def makeTriangle(x0, y0, z0, x1, y1, z1, x2, y2, z2): s_0_1 = vector3d(x0, y0, z0) s_0_2 = vector3d(x1, y1, z1) s_0_3 = vector3d(x2, y2, z2) line0 = [s_0_1, s_0_2, s_0_3] onetriangle = triangle(line0) return onetriangle
def vector_cross_product(vector_x, vector_y): vector_z = vector3d(0.1, 0.1, 0.1) vector_z.x = vector_x.y * vector_y.z - vector_x.z * vector_y.y vector_z.y = vector_x.z * vector_y.x - vector_x.x * vector_y.z vector_z.z = vector_x.x * vector_y.y - vector_x.y * vector_y.x return vector_z
def vector_add_vector(vector1, vector2): vector = vector3d(0.1, 0.1, 0.1) vector.x = vector1.x + vector2.x vector.y = vector1.y + vector2.y vector.z = vector1.z + vector2.z return vector
def vector_minus_vector(vector1, vector2): vector = vector3d(0.1, 0.1, 0.1) vector.x = vector1.x - vector2.x vector.y = vector1.y - vector2.y vector.z = vector1.z - vector2.z return vector
def matrix_point_at(position_vector, target_vector, up_vector): forward_vector = vector3d(0.1, 0.1, 0.1) forward_vector = vector_minus_vector(target_vector, position_vector) forward_vector = vector_normal_make(forward_vector) a = vector3d(0.1, 0.1, 0.1) a.x = forward_vector.x * vector_dotProduct(up_vector, forward_vector) a.y = forward_vector.y * vector_dotProduct(up_vector, forward_vector) a.z = forward_vector.z * vector_dotProduct(up_vector, forward_vector) new_up_vector = vector3d(0.1, 0.1, 0.1) new_up_vector = vector_minus_vector(up_vector, a) new_up_vector = vector_normal_make(new_up_vector) new_right_vector = vector3d(0.1, 0.1, 0.1) new_right_vector = vector_cross_product(new_up_vector, forward_vector) matrix4x4 = np.array([[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]]) matrix4x4[0][0] = new_right_vector.x matrix4x4[1][0] = new_up_vector.x matrix4x4[2][0] = forward_vector.x matrix4x4[3][0] = position_vector.x matrix4x4[0][1] = new_right_vector.y matrix4x4[1][1] = new_up_vector.y matrix4x4[2][1] = forward_vector.y matrix4x4[3][1] = position_vector.y matrix4x4[0][2] = new_right_vector.z matrix4x4[1][2] = new_up_vector.z matrix4x4[2][2] = forward_vector.z matrix4x4[3][2] = position_vector.z matrix4x4[0][3] = 0.0 matrix4x4[1][3] = 0.0 matrix4x4[2][3] = 0.0 matrix4x4[3][3] = 1.0 return matrix4x4
def multiplayMatrixVector(inputV, matrix4x4): outputV = vector3d(0, 0, 0) outputV.x = inputV.x * matrix4x4[0][0] + inputV.y * matrix4x4[1][ 0] + inputV.z * matrix4x4[2][0] + matrix4x4[3][0] outputV.y = inputV.x * matrix4x4[0][1] + inputV.y * matrix4x4[1][ 1] + inputV.z * matrix4x4[2][1] + matrix4x4[3][1] outputV.z = inputV.x * matrix4x4[0][2] + inputV.y * matrix4x4[1][ 2] + inputV.z * matrix4x4[2][2] + matrix4x4[3][2] w = inputV.x * matrix4x4[0][3] + inputV.y * matrix4x4[1][ 3] + inputV.z * matrix4x4[2][3] + matrix4x4[3][3] if w != 0.0: outputV.x = outputV.x / w outputV.y = outputV.y / w outputV.z = outputV.z / w return outputV
def make_mesh_from_file(strings): meshCube = [] point_list = [] with open(strings) as f: for line in f.readlines(): point = [i.rstrip() for i in line.split(' ')] if point[0] == 'v': x = vector3d(float(point[1]), float(point[2]), float(point[3])) point_list.append(x) if point[0] == 'f': oneTriangle = makeTriangle(point_list[int(point[1]) - 1].x, point_list[int(point[1]) - 1].y, point_list[int(point[1]) - 1].z, point_list[int(point[2]) - 1].x, point_list[int(point[2]) - 1].y, point_list[int(point[2]) - 1].z, point_list[int(point[3]) - 1].x, point_list[int(point[3]) - 1].y, point_list[int(point[3]) - 1].z) meshCube.append(oneTriangle) return meshCube
def Update(elapsedTime): global vectorLookDirection global vectorCamera global fYaw vForward = multiply_each_vector_by_number(vectorLookDirection, 8.0 * elapsedTime, 8.0 * elapsedTime, 8.0 * elapsedTime) for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() elif event.type == pygame.KEYDOWN: if (event.key == pygame.K_RIGHT): print("---left---") vectorCamera.x += 8.0 * elapsedTime if (event.key == pygame.K_LEFT): print("---right---") vectorCamera.x -= 8.0 * elapsedTime if (event.key == pygame.K_UP): print("---up---") vectorCamera.y -= 8.0 * elapsedTime if (event.key == pygame.K_DOWN): print("---down---") vectorCamera.y += 8.0 * elapsedTime if (event.key == pygame.K_a): print("---left turn---") fYaw -= 2.0 * elapsedTime if (event.key == pygame.K_d): print("---right turn---") fYaw += 2.0 * elapsedTime if (event.key == pygame.K_w): print("---forward---") vectorCamera = vector_add_vector(vectorCamera, vForward) if (event.key == pygame.K_s): print("---backward---") vectorCamera = vector_minus_vector(vectorCamera, vForward) global theta theta += 0.1 * elapsedTime theta = 0 Matirx_Rotate_X = matirx_rotate_X(theta) Matirx_Rotate_Z = matirx_rotate_Z(180 / 180 * 3.1415926) for triangles in meshCube: triProjected = triangle(line1) triTranslated = triangle(line1) triRotatedZ = triangle(line1) triRotatedZX = triangle(line1) triViewed = triangle(line1) # Rotate in Z-Axis triRotatedZ.line1 = multiplayMatrixVector(triangles.line1, Matirx_Rotate_Z) triRotatedZ.line2 = multiplayMatrixVector(triangles.line2, Matirx_Rotate_Z) triRotatedZ.line3 = multiplayMatrixVector(triangles.line3, Matirx_Rotate_Z) # Rotate in X-Axis triRotatedZX.line1 = multiplayMatrixVector(triRotatedZ.line1, Matirx_Rotate_X) triRotatedZX.line2 = multiplayMatrixVector(triRotatedZ.line2, Matirx_Rotate_X) triRotatedZX.line3 = multiplayMatrixVector(triRotatedZ.line3, Matirx_Rotate_X) # Offset into the screen triTranslated = add_each_vector_by_number(triRotatedZX, 10, 10, 10) normal = vector3d(0.1, 0.1, 0.1) vectorline1 = vector3d(0.1, 0.1, 0.1) vectorline2 = vector3d(0.1, 0.1, 0.1) vectorline1 = vector_minus_vector(triTranslated.line2, triTranslated.line1) vectorline2 = vector_minus_vector(triTranslated.line3, triTranslated.line1) normal = vector_cross_product(vectorline1, vectorline2) normal = vector_normal_make(normal) vectorUp = vector3d(0.0, 1.0, 0.0) vectorTarget = vector3d(0.0, 0.0, 1.0) Matirx_Rotate_Y = matirx_rotate_Y(fYaw) vectorLookDirection = multiplayMatrixVector(vectorTarget, Matirx_Rotate_Y) vectorTarget = vector_add_vector(vectorCamera, vectorLookDirection) matrix_camera = matrix_point_at(vectorCamera, vectorTarget, vectorUp) matrix_view = matrix_quike_inverse(matrix_camera) dotProductOfVectors = vector_dotProduct( normal, vector_minus_vector(triTranslated.line1, vectorCamera)) if dotProductOfVectors < 0: lightdirection = vector3d(0.0, 0.0, -1.0) lightdirection = vector_normal_make(lightdirection) dotProductOflight = vector_dotProduct(normal, lightdirection) # Convert World Space --> View Space triViewed.line1 = multiplayMatrixVector(triTranslated.line1, matrix_view) triViewed.line2 = multiplayMatrixVector(triTranslated.line2, matrix_view) triViewed.line3 = multiplayMatrixVector(triTranslated.line3, matrix_view) number_clipped_triangle = 0 clipped_triangle = [] clip_result = triangle_clip_against_plane(vector3d(0.0, 0.0, 0.1), vector3d(0.0, 0.0, 1.0), triViewed) if clip_result == False: print("wrong!") number_clipped_triangle = clip_result[0] if clip_result[1] is not None: clipped_triangle.append(clip_result[1]) if clip_result[2] is not None: clipped_triangle.append(clip_result[2]) for i in range(number_clipped_triangle): #Project triangles from 3D --> 2D triProjected.line1 = multiplayMatrixVector( clipped_triangle[i].line1, matrix4x4Projection) triProjected.line2 = multiplayMatrixVector( clipped_triangle[i].line2, matrix4x4Projection) triProjected.line3 = multiplayMatrixVector( clipped_triangle[i].line3, matrix4x4Projection) triProjected.line1.x += 1.0 triProjected.line1.y += 1.0 triProjected.line2.x += 1.0 triProjected.line2.y += 1.0 triProjected.line3.x += 1.0 triProjected.line3.y += 1.0 multiply_each_vector_by_number(triProjected.line1, 0.5 * 640.0, 0.5 * 480.0, 1) multiply_each_vector_by_number(triProjected.line2, 0.5 * 640.0, 0.5 * 480.0, 1) multiply_each_vector_by_number(triProjected.line3, 0.5 * 640.0, 0.5 * 480.0, 1) # Rasterize triangle if dotProductOflight < 0: dotProductOflight = 0.001 global listTriangleProjected listTriangleProjected.append([triProjected, dotProductOflight]) sortedListofTriangleProjected = Sort(listTriangleProjected) listTriangleProjected = [] for trianglesSorted, dotProductOflightSorted in sortedListofTriangleProjected: clipped_1 = makeTriangle(0, 0, 0, 0, 0, 0, 0, 0, 0) clipped_2 = makeTriangle(0, 0, 0, 0, 0, 0, 0, 0, 0) triangle_to_draw = [] triangle_to_draw.append([trianglesSorted, dotProductOflightSorted]) new_triangles = 1 for p in range(4): number_triangle_to_add = 0 while new_triangles > 0: test = triangle_to_draw.pop(0) test = test[0] if isnan(test.line3.x): print("=============Nan number of vector================") exit(0) new_triangles = new_triangles - 1 if p == 0: clip_result = triangle_clip_against_plane( vector3d(0.0, 0.0, 0.0), vector3d(0.0, 1.0, 0.0), test) number_triangle_to_add = clip_result[0] clipped_1 = clip_result[1] clipped_2 = clip_result[2] if p == 1: clip_result = triangle_clip_against_plane( vector3d(0.0, 480.0 - 1, 0.0), vector3d(0.0, -1.0, 0.0), test) number_triangle_to_add = clip_result[0] clipped_1 = clip_result[1] clipped_2 = clip_result[2] if p == 2: clip_result = triangle_clip_against_plane( vector3d(0.0, 0.0, 0.0), vector3d(1.0, 0.0, 0.0), test) number_triangle_to_add = clip_result[0] clipped_1 = clip_result[1] clipped_2 = clip_result[2] if p == 3: clip_result = triangle_clip_against_plane( vector3d(640.0 - 1, 0.0, 0.0), vector3d(-1.0, 0.0, 0.0), test) number_triangle_to_add = clip_result[0] clipped_1 = clip_result[1] clipped_2 = clip_result[2] for w in range(number_triangle_to_add): if w == 0: triangle_to_draw.append( [clipped_1, dotProductOflightSorted]) if w == 1: triangle_to_draw.append( [clipped_2, dotProductOflightSorted]) new_triangles = len(triangle_to_draw) for triangles_sorted_to_draw, dotProductOflight_to_draw in triangle_to_draw: pygame.draw.polygon(screen, (0, 0, 255 * dotProductOflight_to_draw), [(triangles_sorted_to_draw.line1.x, triangles_sorted_to_draw.line1.y), (triangles_sorted_to_draw.line2.x, triangles_sorted_to_draw.line2.y), (triangles_sorted_to_draw.line3.x, triangles_sorted_to_draw.line3.y)], 0) pygame.display.flip()
#! /usr/bin/env python import math import pygame import numpy as np from math import isnan from objects import vector3d, triangle, mesh from linearAlgebra import matrix4x4Projection, matrix_rotateZ, matrix_rotateX, matrix_camera, matrix_view, matrix_I, multiplayMatrixVector, makeTriangle, make_mesh_from_file, Sort, matirx_rotate_X, matirx_rotate_Y, matirx_rotate_Z, add_each_vector_by_number, multiply_each_vector_by_number, vector_minus_vector, vector_add_vector, vector_cross_product, vector_normal_make, vector_dotProduct, matrix_point_at, matrix_quike_inverse from clipFunctions import line_intersect_plane, calculate_distance_from_point_to_plane, triangle_clip_against_plane screen = pygame.display.set_mode((640, 480), pygame.HWSURFACE | pygame.DOUBLEBUF) running = 1 x1 = vector3d(1, 1, 1) x2 = vector3d(1, 1, 1) x3 = vector3d(1, 1, 1) line1 = [x1, x2, x3] meshCube = mesh() meshCubeinput = make_mesh_from_file("3dObject/mountain.obj") pointlist = [ 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0 ]