Added a very simple light source so the 3D models now have simple shading applied to them.
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
from vectors import Vector2d, Vector3d, Vector4d
|
from vectors import Vector2d, Vector3d, Vector4d
|
||||||
from matrix import Matrix3x3
|
from matrix import Matrix3x3
|
||||||
|
from triangle import Triangle
|
||||||
|
|
||||||
class Engine:
|
class Engine:
|
||||||
def __init__(self, width, height):
|
def __init__(self, width, height):
|
||||||
@@ -41,6 +42,4 @@ class Mesh:
|
|||||||
row1 = self.vertices[int(tmp[2]) - 1]
|
row1 = self.vertices[int(tmp[2]) - 1]
|
||||||
row2 = self.vertices[int(tmp[3]) - 1]
|
row2 = self.vertices[int(tmp[3]) - 1]
|
||||||
|
|
||||||
tri = Matrix3x3(row0, row1, row2)
|
self.triangles.append(Triangle(Matrix3x3(row0, row1, row2)))
|
||||||
|
|
||||||
self.triangles.append(tri)#Vector3d(x - 1, y - 1, z - 1))
|
|
||||||
|
|||||||
@@ -4,16 +4,31 @@ import copy
|
|||||||
from matrix import Matrix4x4, Matrix3x3
|
from matrix import Matrix4x4, Matrix3x3
|
||||||
from vectors import Vector4d, Vector3d, Vector2d
|
from vectors import Vector4d, Vector3d, Vector2d
|
||||||
from engine import Mesh
|
from engine import Mesh
|
||||||
|
from triangle import Triangle
|
||||||
|
|
||||||
ui = window.Window(600, 600)
|
ui = window.Window(600, 600)
|
||||||
near_plane = 0.1
|
near_plane = 0.1
|
||||||
far_plane = 1000.0
|
far_plane = 1000.0
|
||||||
fov = 90.0
|
fov = 90.0
|
||||||
|
|
||||||
tris = Mesh()
|
tris =[
|
||||||
|
Matrix3x3(Vector3d(0.0,0.0,0.0),Vector3d(0.0,1.0,0.0),Vector3d(1.0,1.0,0.0)),
|
||||||
|
Matrix3x3(Vector3d(0.0,0.0,0.0),Vector3d(1.0,1.0,0.0),Vector3d(1.0,0.0,0.0)),
|
||||||
|
Matrix3x3(Vector3d(1.0,0.0,0.0),Vector3d(1.0,1.0,0.0),Vector3d(1.0,1.0,1.0)),
|
||||||
|
Matrix3x3(Vector3d(1.0,0.0,0.0),Vector3d(1.0,1.0,1.0),Vector3d(1.0,0.0,1.0)),
|
||||||
|
Matrix3x3(Vector3d(1.0,0.0,1.0),Vector3d(1.0,1.0,1.0),Vector3d(0.0,1.0,1.0)),
|
||||||
|
Matrix3x3(Vector3d(1.0,0.0,1.0),Vector3d(0.0,1.0,1.0),Vector3d(0.0,0.0,1.0)),
|
||||||
|
Matrix3x3(Vector3d(0.0,0.0,1.0),Vector3d(0.0,1.0,1.0),Vector3d(0.0,1.0,0.0)),
|
||||||
|
Matrix3x3(Vector3d(0.0,0.0,1.0),Vector3d(0.0,1.0,0.0),Vector3d(0.0,0.0,0.0)),
|
||||||
|
Matrix3x3(Vector3d(0.0,1.0,0.0),Vector3d(0.0,1.0,1.0),Vector3d(1.0,1.0,1.0)),
|
||||||
|
Matrix3x3(Vector3d(0.0,1.0,0.0),Vector3d(1.0,1.0,1.0),Vector3d(1.0,1.0,0.0)),
|
||||||
|
Matrix3x3(Vector3d(1.0,0.0,1.0),Vector3d(0.0,0.0,1.0),Vector3d(0.0,0.0,0.0)),
|
||||||
|
Matrix3x3(Vector3d(1.0,0.0,1.0),Vector3d(0.0,0.0,0.0),Vector3d(1.0,0.0,0.0))
|
||||||
|
]
|
||||||
|
|
||||||
|
#tris = Mesh()
|
||||||
def main():
|
def main():
|
||||||
tris.load_obj_file('shuttle.obj')
|
#tris.load_obj_file('shuttle.obj')
|
||||||
|
|
||||||
ui.thetax = 1
|
ui.thetax = 1
|
||||||
ui.window.bind('<Left>', left)
|
ui.window.bind('<Left>', left)
|
||||||
@@ -31,8 +46,7 @@ def right(event):
|
|||||||
ui.theta += .01
|
ui.theta += .01
|
||||||
|
|
||||||
def mouse_start(event):
|
def mouse_start(event):
|
||||||
#x, y =
|
ui.canvas.old_coords = event.x, event.y
|
||||||
ui.canvas.old_coords = event.x, event.y #x, y
|
|
||||||
|
|
||||||
def mouse_end(event):
|
def mouse_end(event):
|
||||||
x, y = ui.canvas.old_coords[0] - event.x, ui.canvas.old_coords[1] - event.y
|
x, y = ui.canvas.old_coords[0] - event.x, ui.canvas.old_coords[1] - event.y
|
||||||
@@ -47,6 +61,8 @@ def mouse_end(event):
|
|||||||
ui.thetax += .01
|
ui.thetax += .01
|
||||||
else:
|
else:
|
||||||
ui.thetax -= .01
|
ui.thetax -= .01
|
||||||
|
|
||||||
|
draw_scene()
|
||||||
#ui.theta += x / ui.width
|
#ui.theta += x / ui.width
|
||||||
|
|
||||||
def draw_scene():
|
def draw_scene():
|
||||||
@@ -76,7 +92,9 @@ def draw_scene():
|
|||||||
|
|
||||||
rotation_matrix_x = Matrix4x4(row0, row1, row2, row3)
|
rotation_matrix_x = Matrix4x4(row0, row1, row2, row3)
|
||||||
|
|
||||||
for tri in tris.triangles:
|
triangles = []
|
||||||
|
|
||||||
|
for tri in tris:
|
||||||
# Rotate on the z-axis
|
# Rotate on the z-axis
|
||||||
row0 = rotation_matrix_z.multiply_3d(tri.row0)
|
row0 = rotation_matrix_z.multiply_3d(tri.row0)
|
||||||
row1 = rotation_matrix_z.multiply_3d(tri.row1)
|
row1 = rotation_matrix_z.multiply_3d(tri.row1)
|
||||||
@@ -91,34 +109,76 @@ def draw_scene():
|
|||||||
rotated_x = Matrix3x3(row0, row1, row2)
|
rotated_x = Matrix3x3(row0, row1, row2)
|
||||||
# The offset into the screen
|
# The offset into the screen
|
||||||
translated = copy.copy(rotated_x)
|
translated = copy.copy(rotated_x)
|
||||||
translated.row0.z += 8.0
|
translated.row0.z += 3.0
|
||||||
translated.row1.z += 8.0
|
translated.row1.z += 3.0
|
||||||
translated.row2.z += 8.0
|
translated.row2.z += 3.0
|
||||||
# Scale into view
|
|
||||||
row0 = projection_matrix.multiply_3d(translated.row0)
|
|
||||||
row1 = projection_matrix.multiply_3d(translated.row1)
|
|
||||||
row2 = projection_matrix.multiply_3d(translated.row2)
|
|
||||||
|
|
||||||
projected = Matrix3x3(row0, row1, row2)
|
# Use cross-product to get the surface normal (a Vector3d)
|
||||||
|
x = translated.row1.x - translated.row0.x
|
||||||
|
y = translated.row1.y - translated.row0.y
|
||||||
|
z = translated.row1.z - translated.row0.z
|
||||||
|
line1 = Vector3d(x, y, z)
|
||||||
|
|
||||||
projected.row0.x += 1
|
x = translated.row2.x - translated.row0.x
|
||||||
projected.row0.y += 1
|
y = translated.row2.y - translated.row0.y
|
||||||
projected.row1.x += 1
|
z = translated.row2.z - translated.row0.z
|
||||||
projected.row1.y += 1
|
line2 = Vector3d(x, y, z)
|
||||||
projected.row2.x += 1
|
|
||||||
projected.row2.y += 1
|
|
||||||
projected.row0.x *= .5 * ui.width
|
|
||||||
projected.row0.y *= .5 * ui.height
|
|
||||||
projected.row1.x *= .5 * ui.width
|
|
||||||
projected.row1.y *= .5 * ui.height
|
|
||||||
projected.row2.x *= .5 * ui.width
|
|
||||||
projected.row2.y *= .5 * ui.height
|
|
||||||
|
|
||||||
coords = [projected.row0.x, projected.row0.y, projected.row1.x, projected.row1.y, projected.row2.x, projected.row2.y]
|
normal = line1.cross_product(line2)
|
||||||
ui.canvas.create_polygon(coords, fill="", outline="black")
|
|
||||||
|
# Now we normalize the normal
|
||||||
|
w = math.sqrt(normal.x * normal.x + normal.y * normal.y + normal.z * normal.z)
|
||||||
|
normal.x /= w
|
||||||
|
normal.y /= w
|
||||||
|
normal.z /= w
|
||||||
|
|
||||||
|
# Do we display this triangle?
|
||||||
|
if normal.dot_product(translated.row0) < 0.0:
|
||||||
|
# Lighting
|
||||||
|
light = Vector3d(0, 0, -1) # Shining at the player.
|
||||||
|
|
||||||
|
w = math.sqrt(light.x * light.x + light.y * light.y + light.z * light.z)
|
||||||
|
light.x /= w
|
||||||
|
light.y /= w
|
||||||
|
light.z /= w
|
||||||
|
|
||||||
|
dot_product = normal.dot_product(light)
|
||||||
|
r = abs(int(255 * dot_product))
|
||||||
|
|
||||||
|
# Scale into view
|
||||||
|
row0 = projection_matrix.multiply_3d(translated.row0)
|
||||||
|
row1 = projection_matrix.multiply_3d(translated.row1)
|
||||||
|
row2 = projection_matrix.multiply_3d(translated.row2)
|
||||||
|
|
||||||
|
projected = Matrix3x3(row0, row1, row2)
|
||||||
|
|
||||||
|
projected.row0.x += 1
|
||||||
|
projected.row0.y += 1
|
||||||
|
projected.row1.x += 1
|
||||||
|
projected.row1.y += 1
|
||||||
|
projected.row2.x += 1
|
||||||
|
projected.row2.y += 1
|
||||||
|
projected.row0.x *= .5 * ui.width
|
||||||
|
projected.row0.y *= .5 * ui.height
|
||||||
|
projected.row1.x *= .5 * ui.width
|
||||||
|
projected.row1.y *= .5 * ui.height
|
||||||
|
projected.row2.x *= .5 * ui.width
|
||||||
|
projected.row2.y *= .5 * ui.height
|
||||||
|
|
||||||
|
t = Triangle(projected)
|
||||||
|
t.color = r
|
||||||
|
triangles.append(t)
|
||||||
|
|
||||||
|
for projected in triangles:
|
||||||
|
r = projected.color
|
||||||
|
coords = [projected.coords.row0.x, projected.coords.row0.y, projected.coords.row1.x, projected.coords.row1.y, projected.coords.row2.x, projected.coords.row2.y]
|
||||||
|
ui.canvas.create_polygon(coords, fill=from_rgb(r, r, r), outline="black")
|
||||||
|
|
||||||
ui.canvas.update()
|
ui.canvas.update()
|
||||||
|
|
||||||
ui.canvas.after(100, draw_scene)
|
#ui.canvas.after(100, draw_scene)
|
||||||
|
|
||||||
|
def from_rgb(r, b, g):
|
||||||
|
return "#%02x%02x%02x" %(r, g, b)
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import vectors
|
||||||
|
|
||||||
|
class Triangle:
|
||||||
|
def __init__(self, coords):
|
||||||
|
self.coords = coords # Matrix3x3
|
||||||
|
self.object_id = None
|
||||||
|
self.color = None
|
||||||
+1
-1
@@ -17,7 +17,7 @@ class Vector3d:
|
|||||||
# Returns the 'normal'.
|
# Returns the 'normal'.
|
||||||
x = self.y * vector3d.z - self.z * vector3d.y
|
x = self.y * vector3d.z - self.z * vector3d.y
|
||||||
y = self.z * vector3d.x - self.x * vector3d.z
|
y = self.z * vector3d.x - self.x * vector3d.z
|
||||||
z = self.x * vectored.y - self.y * vector3d.x
|
z = self.x * vector3d.y - self.y * vector3d.x
|
||||||
|
|
||||||
return Vector3d(x, y, z)
|
return Vector3d(x, y, z)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user