Files
terrain_generator/main.py
T

181 lines
5.0 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.scale = 3
ui.thetax = 1
ui.thetaz = 1
ui.window.bind('<Left>', left)
ui.window.bind('<Right>', right)
ui.window.bind('<Up>', up)
ui.window.bind('<Down>', down)
ui.window.bind('<Button-4>', wheel)
ui.window.bind('<Button-5>', wheel)
#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 wheel(event):
# respond to Linux or Windows wheel event
#if event.num == 5 or event.delta == -120:
if event.num == 4:
ui.scale -= .5
else:
ui.scale += .5
if ui.scale < 1.5:
ui.scale = 1.5
draw_scene()
def left(event):
ui.thetaz += .1
draw_scene()
def right(event):
ui.thetaz -= .1
draw_scene()
def up(event):
ui.thetax += .1
draw_scene()
def down(event):
ui.thetax -= .1
draw_scene()
def mouse_start(event):
ui.canvas.old_coords = event.x, event.y
def mouse_end(event):
x, y = event.x - ui.width / 2, event.y - ui.height / 2
if x < 0:
ui.thetax -= .01
else:
ui.thetax += .01
if y < 0:
ui.thetaz -= .01
else:
ui.thetaz += .01
draw_scene()
def draw_scene():
ui.canvas.delete("all")
aspect_ratio = ui.height / ui.width
projection_matrix = Matrix4x4.get_projection_matrix(fov, aspect_ratio, near_plane, far_plane)
rotation_matrix_z = Matrix4x4.get_y_rotation_matrix(ui.thetaz * .5)
rotation_matrix_x = Matrix4x4.get_x_rotation_matrix(ui.thetax)
translation = Matrix4x4.get_translation_matrix(Vector3d(0, 0, ui.scale))
world_matrix = Matrix4x4.get_identity_matrix()
world_matrix = rotation_matrix_z.multiply_matrix(rotation_matrix_x)
world_matrix = world_matrix.multiply_matrix(translation)
triangles = []
for tri in tris:
row1 = world_matrix.multiply_3d(tri[0])
row2 = world_matrix.multiply_3d(tri[1])
row3 = world_matrix.multiply_3d(tri[2])
transformed = Matrix3x3(row1, row2, row3)
line1 = transformed.row2.subtract_3d(transformed.row1)
line2 = transformed.row3.subtract_3d(transformed.row1)
normal = line1.cross_product(line2)
normal = normal.get_normalized_form()
# Do we display this triangle?
if normal.dot_product(transformed.row1) < 0.0:
# Lighting
light = Vector3d(0, 0, -1) # Shining at the player.
light = light.get_normalized_form()
dot_product = normal.dot_product(light)
r = abs(int(255 * dot_product))
# Scale into view
row1 = projection_matrix.multiply_3d(transformed.row1)
row2 = projection_matrix.multiply_3d(transformed.row2)
row3 = projection_matrix.multiply_3d(transformed.row3)
projected = Matrix3x3(row1, row2, row3)
projected.row1 = projected.row1.divide_3d(1)
projected.row2 = projected.row2.divide_3d(1)
projected.row3 = projected.row3.divide_3d(1)
offset = Vector3d(1, 1, 0)
projected.row1 = projected.row1.add_3d(offset)
projected.row2 = projected.row2.add_3d(offset)
projected.row3 = projected.row3.add_3d(offset)
projected.row1.x *= .5 * ui.width
projected.row1.y *= .5 * ui.height
projected.row2.x *= .5 * ui.width
projected.row2.y *= .5 * ui.height
projected.row3.x *= .5 * ui.width
projected.row3.y *= .5 * ui.height
t = Triangle(projected)
t.color = r
t.average = (t.coords.row1.z + t.coords.row2.z + t.coords.row3.z) / 3
triangles.append(t)
# Sort the triangles so they are drawn in order.
triangles.sort(key=lambda r: r.average, reverse = True)
for projected in triangles:
r = projected.color
coords = [projected.coords.row1.x, projected.coords.row1.y, projected.coords.row2.x, projected.coords.row2.y, projected.coords.row3.x, projected.coords.row3.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()