Files
terrain_generator/main.py
T

185 lines
5.5 KiB
Python

import window
import math
import copy
from matrix import Matrix4x4, Matrix3x3
from vectors import Vector4d, Vector3d, Vector2d
from engine import Mesh
from triangle import Triangle
ui = window.Window(600, 600)
near_plane = 0.1
far_plane = 1000.0
fov = 90.0
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():
#tris.load_obj_file('shuttle.obj')
ui.thetax = 1
ui.window.bind('<Left>', left)
ui.window.bind('<Right>', right)
ui.window.bind('<ButtonPress-1>', mouse_start)
ui.canvas.bind('<B1-Motion>', mouse_end)
ui.canvas.old_coords = None
ui.window.after(0, draw_scene)
ui.show()
def left(event):
ui.theta -= .01
def right(event):
ui.theta += .01
def mouse_start(event):
ui.canvas.old_coords = event.x, event.y
def mouse_end(event):
x, y = ui.canvas.old_coords[0] - event.x, ui.canvas.old_coords[1] - event.y
if x < 0:
ui.theta += .01
else:
ui.theta -= .01
print(ui.theta)
if y < 0:
ui.thetax += .01
else:
ui.thetax -= .01
draw_scene()
#ui.theta += x / ui.width
def draw_scene():
ui.canvas.delete("all")
#ui.theta += .01 # scaling factor
aspect_ratio = ui.height / ui.width
fov_rad = ui.theta / math.tan(fov * 0.5 / 180.0 * math.pi)
row0 = Vector4d(aspect_ratio * fov_rad, 0, 0, 0)
row1 = Vector4d(0, fov_rad, 0, 0)
row2 = Vector4d(0, 0, far_plane / (far_plane - near_plane), 1.0)
row3 = Vector4d(0, 0, -far_plane * near_plane / (far_plane - near_plane), 0)
projection_matrix = Matrix4x4(row0, row1, row2, row3)
row0 = Vector4d(math.cos(ui.theta), math.sin(ui.theta), 0, 0)
row1 = Vector4d(-math.sin(ui.theta), math.cos(ui.theta), 0, 0)
row2 = Vector4d(0, 0, 1, 0)
row3 = Vector4d(0, 0, 0, 1)
rotation_matrix_z = Matrix4x4(row0, row1, row2, row3)
row0 = Vector4d(1, 0, 0, 0)
row1 = Vector4d(0, math.cos(ui.thetax * 0.5), math.sin(ui.thetax * 0.5), 0)
row2 = Vector4d(0, -math.sin(ui.thetax * 0.5), math.cos(ui.thetax * 0.5), 0)
row3 = Vector4d(0, 0, 0, 1)
rotation_matrix_x = Matrix4x4(row0, row1, row2, row3)
triangles = []
for tri in tris:
# Rotate on the z-axis
row0 = rotation_matrix_z.multiply_3d(tri.row0)
row1 = rotation_matrix_z.multiply_3d(tri.row1)
row2 = rotation_matrix_z.multiply_3d(tri.row2)
rotated_z = Matrix3x3(row0, row1, row2)
# Rotate on the x-axis
row0 = rotation_matrix_x.multiply_3d(rotated_z.row0)
row1 = rotation_matrix_x.multiply_3d(rotated_z.row1)
row2 = rotation_matrix_x.multiply_3d(rotated_z.row2)
rotated_x = Matrix3x3(row0, row1, row2)
# The offset into the screen
translated = copy.copy(rotated_x)
translated.row0.z += 3.0
translated.row1.z += 3.0
translated.row2.z += 3.0
# 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)
x = translated.row2.x - translated.row0.x
y = translated.row2.y - translated.row0.y
z = translated.row2.z - translated.row0.z
line2 = Vector3d(x, y, z)
normal = line1.cross_product(line2)
# 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.after(100, draw_scene)
def from_rgb(r, b, g):
return "#%02x%02x%02x" %(r, g, b)
main()