Files
terrain_generator/main.py
T

243 lines
7.2 KiB
Python

import window
import math
import copy
from tkinter.font import Font
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 = [
Matrix3x3(Vector3d(0,0,0),Vector3d(0,2000,0.0),Vector3d(1,1,0))
]'''
tris = Mesh()
def main():
tris.load_obj_file('reduced.obj')
#tris.load_csv('values.csv')
ui.scale = 3
ui.thetax = 1
ui.thetaz = 1
ui.canvas.configure(scrollregion = ui.canvas.bbox("all"))
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.bind('<Motion>', mouse_motion)
ui.canvas.old_coords = None
ui.canvas.just_the_tip = ui.canvas.create_rectangle(0, 0, 0, 0, fill='blue')
ui.canvas.just_the_label = ui.canvas.create_text(0, 0)
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()
ui.canvas.yview_moveto(.1)
ui.canvas.update()
def up(event):
ui.thetax += .1
draw_scene()
ui.canvas.create_text(100, 100, text="Up pressed")
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 mouse_motion(event):
x, y = event.x, event.y
draw_x = x
draw_y = y
id = ui.canvas.find_closest(x, y)
n = ui.canvas.coords(id)
if len(n) != 6: return
text = "1250 = 100((1 -1.08 ^ -240) / 0.08) | 95%"#"Nearest Triangle: (%d, %d) (%d, %d) (%d, %d)" %(n[0], n[1], n[2], n[3], n[4], n[5])#"Now the tool tip auto sizes to fit text"
width = Font(size=12, family="Hack").measure(text)
if width + x > ui.width:
draw_x = x - width - 30
if draw_x < 0:
draw_x = 0
y += 20
ui.canvas.delete(ui.canvas.just_the_tip)
ui.canvas.delete(ui.canvas.just_the_label)
ui.canvas.just_the_tip = ui.canvas.create_rectangle(draw_x + 14, y, draw_x + width + 16, y + 20, fill='grey')
ui.canvas.just_the_label = ui.canvas.create_text(draw_x + width / 2 + 15, y + 9, font="Hack 12", text=text)
ui.canvas.update()
#width = tk.font.Font(size=12, family="Times New Roman").measure("Some Tool Tip Nonsense")
#heigth = ui.canvas.find_withtag(ui.canvas.just_the_label) #.winfo_height()
#print(width)
#ui.canvas.delete(ui.canvas.just_the_label)
#ui.canvas.just_the_label = ui.canvas.create_text(x + width, y + y/2, text="Some tool tip nonsense")
#ui.canvas.update()
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)
#print("Z:\n%s" %(rotation_matrix_z))
rotation_matrix_x = Matrix4x4.get_x_rotation_matrix(ui.thetax)
#print("X:\n%s" %(rotation_matrix_x))
translation = Matrix4x4.get_translation_matrix(Vector3d(0, 0, ui.scale))
#print("T:\n%s" %(translation))
world_matrix = Matrix4x4.get_identity_matrix()
#print("W:\n%s" %(world_matrix))
world_matrix = rotation_matrix_z.multiply_matrix(rotation_matrix_x)
#print("W * Z:\n%s" %(world_matrix))
world_matrix = world_matrix.multiply_matrix(translation)
#print("W * T:\n%s" %(world_matrix))
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))
color = compute(r)
# 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 = color
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
'''
print("1: x:%f.2 y:%f.2" %(projected.coords.row1.x, projected.coords.row1.y))
print("2: x:%f.2 y:%f.2" %(projected.coords.row2.x, projected.coords.row2.y))
print("3: x:%f.2 y:%f.2" %(projected.coords.row3.x, projected.coords.row3.y))
print()
'''
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[0], r[1], r[2]), outline=from_rgb(0, 255, 0))
ui.canvas.update()
#ui.canvas.after(100, draw_scene)
def from_rgb(r, b, g):
return "#%02x%02x%02x" %(r, g, b)
def compute(r):
r = r * 0.38
b = r
g = r * 1.6
if g > 255:
g = 255
return (int(r), int(g), int(b))
main()