def __projectm(vector, center): """ apply clipping matrix camera transformation matrix camera rotation matrix TODO: finally sort out vertices out of clipping area and return tuple on 2D Coordinates taken from : http://stackoverflow.com/questions/724219/how-to-convert-a-3d-point-into-2d-perspective-projection """ clipping_m = Matrix3D([ [FOV * ASPECT_RATIO, 0.0, 0.0 , 0.0], [0.0 , FOV, 0.0 , 0.0], [0.0 , 0.0, (far + near) / (far-near) , (2.0 * near * far) / (near-far)], [0.0 , 0.0, 1.0 , 0.0] ]) cam_translation_m = Matrix3D.get_shift_matrix(0, 0, -10) cam_rot_m = Matrix3D.get_rot_y_matrix(Y_ANGLE).dot(Matrix3D.get_rot_x_matrix(X_ANGLE)) # mind the order !! new_vector = clipping_m.dot(cam_translation_m.dot(cam_rot_m)).v_dot(vector) new_x = center[0] + new_vector.x * 16.0 / ( 2.0 * new_vector.z) + 8.0 new_y = center[1] + new_vector.y * 9.0 / ( 2.0 * new_vector.z) + 4.5 return new_x, new_y
def update(self): """ called on every frame apply transformation matrix and project every polygon to 2d for color avg_z function is used polygons are sorted on avg_z value finally painting on surface is called """ # Clock vector vector = Matrix3D.get_rot_z_matrix(self.angle).v_dot(self.vector) # projected = self.__project(self.vector, self.center) projected = self.__projectm(vector, self.center) pygame.draw.polygon(self.surface, pygame.Color(255,255,255,0), (self.center, projected), 1) # Cube mesh = self.model.transform(Matrix3D.get_rot_z_matrix(self.angle)) #mesh = mesh.transform(Matrix3D.get_rot_x_matrix(self.angle)) mesh = mesh.transform(Matrix3D.get_scale_matrix(SCALE, SCALE, SCALE)) mesh = mesh.transform(Matrix3D.get_shift_matrix(X_SHIFT, Y_SHIFT, Z_SHIFT)) for face in mesh: vertices = [self.__projectm(vertice, self.center) for vertice in face] pygame.draw.polygon(self.surface, pygame.Color(255,255,255,0), vertices, 1) self.angle += self.angle_step # axis vectors pygame.draw.polygon(self.surface, pygame.Color(255,0,0,0), (self.center, self.__projectm(self.x_axis, self.center)), 1) pygame.draw.polygon(self.surface, pygame.Color(0,255,0,0), (self.center, self.__projectm(self.y_axis, self.center)), 1) pygame.draw.polygon(self.surface, pygame.Color(0,0,255,0), (self.center, self.__projectm(self.z_axis, self.center)), 1)
def __projectm(vector, center): """ apply clipping matrix camera transformation matrix camera rotation matrix TODO: finally sort out vertices out of clipping area and return tuple on 2D Coordinates taken from : http://stackoverflow.com/questions/724219/how-to-convert-a-3d-point-into-2d-perspective-projection """ clipping_m = Matrix3D([[FOV * ASPECT_RATIO, 0.0, 0.0, 0.0], [0.0, FOV, 0.0, 0.0], [ 0.0, 0.0, (far + near) / (far - near), (2.0 * near * far) / (near - far) ], [0.0, 0.0, 1.0, 0.0]]) cam_translation_m = Matrix3D.get_shift_matrix(0, 0, -10) cam_rot_m = Matrix3D.get_rot_y_matrix(Y_ANGLE).dot( Matrix3D.get_rot_x_matrix(X_ANGLE)) # mind the order !! new_vector = clipping_m.dot( cam_translation_m.dot(cam_rot_m)).v_dot(vector) new_x = center[0] + new_vector.x * 16.0 / (2.0 * new_vector.z) + 8.0 new_y = center[1] + new_vector.y * 9.0 / (2.0 * new_vector.z) + 4.5 return new_x, new_y
def get_cube_mesh(): # a cube Mesh consist of six Faces # left faces = [] rec = Face3D(get_rectangle_points()) t = Matrix3D.get_shift_matrix(-1, 0, 0).dot( Matrix3D.get_rot_y_matrix(math.pi / 2)) faces.append(rec.transform(t)) # right t = Matrix3D.get_shift_matrix(1, 0, 0).dot( Matrix3D.get_rot_y_matrix(math.pi / 2)) faces.append(rec.transform(t)) # bottom t = Matrix3D.get_shift_matrix(0, -1, 0).dot( Matrix3D.get_rot_x_matrix(math.pi / 2)) faces.append(rec.transform(t)) # top t = Matrix3D.get_shift_matrix(0, 1, 0).dot( Matrix3D.get_rot_x_matrix(math.pi / 2)) faces.append(rec.transform(t)) # front t = Matrix3D.get_shift_matrix(0, 0, -1) faces.append(rec.transform(t)) # back t = Matrix3D.get_shift_matrix(0, 0, 1) faces.append(rec.transform(t)) return Mesh3D(faces)
def test_m_transforms(self): v = Vector3D(1, 1, 0, 1) m = Matrix3D.get_shift_matrix(5, 5, 0) print "shift matrix:\n", m print "shifted vector:", m.v_dot(v) m = Matrix3D.get_scale_matrix(2, 2, 0) print "scale matrix:\n", m print "scaled vector:", m.v_dot(v)
def test_scale(self): m = Matrix3D.identity() m2 = m.scale(2.0) print "2 * I:\n", m2 m3 = m2.scale(1.0/2.0) print "1/2 * ( 2 * I):\n", m3 assert m3 == m
def test_det(self): m = Matrix3D.identity() print "det(I)=", m.det() # for next example look at # http://matheguru.com/lineare-algebra/207-determinante.html mr = Matrix3D([ [5, 0, 3, -1], [3, 0, 0, 4], [-1, 2, 4, -2], [1, 0, 0, 5], ]) print "T(mr)=\n", mr.transpose() print "det(mr)=", mr.det() assert mr.det() == 66 print "det(T(mr))=", mr.transpose().det() assert mr.det() == mr.transpose().det()
def test_scale(self): m = Matrix3D.identity() m2 = m.scale(2.0) print "2 * I:\n", m2 m3 = m2.scale(1.0 / 2.0) print "1/2 * ( 2 * I):\n", m3 assert m3 == m
def test_inverse(self): # for next example look at # http://matheguru.com/lineare-algebra/207-determinante.html mr = Matrix3D([ [5.0, 0.0, 3.0, -1.0], [3.0, 0.0, 0.0, 4.0], [-1.0, 2.0, 4.0, -2.0], [1.0, 0.0, 0.0, 5.0], ]) print "inverse(mr) =\n", mr.inverse() test_m = Matrix3D([ [0.0, 0.4545454545454546, 0.0, -0.36363636363636365], [-0.6666666666666667, 1.7121212121212122, 0.5, -1.303030303030303], [0.33333333333333337, -0.7878787878787878, 0.0, 0.696969696969697], [0.0, -0.09090909090909091, 0.0, 0.2727272727272727] ]) assert mr.inverse() == test_m
def test_matrix_dot(self): """test dot product identity matrix and transpose""" mi = Matrix3D.identity() # I dot transposed(I) = I assert mi == mi.dot(mi.transpose()) mr = Matrix3D([ [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16], ]) assert mr.dot(mi) == mr test_transposed = Matrix3D([[1, 5, 9, 13], [2, 6, 10, 14], [3, 7, 11, 15], [4, 8, 12, 16]]) assert mr.transpose() == test_transposed test_m = Matrix3D([ [30, 70, 110, 150], [70, 174, 278, 382], [110, 278, 446, 614], [150, 382, 614, 846], ]) assert mr.dot(mr.transpose()) == test_m A = Matrix3D([[3, 0, 0, 0], [0, -1, 0, 0], [0, 0, 2, 0], [0, 0, 0, 1]]) B = Matrix3D([[math.sqrt(3) / 2, 0, -1 / 2, 0], [0, 1, 0, 0], [1 / 2, 0, math.sqrt(3) / 2, 0], [0, 0, 0, 1]]) C = Matrix3D([[1, 0, 0, 3], [0, 1, 0, -1], [0, 0, 1, 2], [0, 0, 0, 1]]) # testing assosiativeness (A*B)*C == A*(B*C) assert A.dot(B).dot(C) == A.dot(B.dot(C))
def solve(self): if self.a.is_singular(): return "infinity" sol = [] for i in range(self.n): t = Matrix3D(self.a) t.set_row(self.b.get_list(), i) sol.append(t.det() / self.a.det()) return sol
def update(self): """ called on every frame apply transformation matrix and project every polygon to 2d for color avg_z function is used polygons are sorted on avg_z value finally painting on surface is called """ # Clock vector vector = Matrix3D.get_rot_z_matrix(self.angle).v_dot(self.vector) # projected = self.__project(self.vector, self.center) projected = self.__projectm(vector, self.center) pygame.draw.polygon(self.surface, pygame.Color(255, 255, 255, 0), (self.center, projected), 1) # Cube mesh = self.model.transform(Matrix3D.get_rot_z_matrix(self.angle)) #mesh = mesh.transform(Matrix3D.get_rot_x_matrix(self.angle)) mesh = mesh.transform(Matrix3D.get_scale_matrix(SCALE, SCALE, SCALE)) mesh = mesh.transform( Matrix3D.get_shift_matrix(X_SHIFT, Y_SHIFT, Z_SHIFT)) for face in mesh: vertices = [ self.__projectm(vertice, self.center) for vertice in face ] pygame.draw.polygon(self.surface, pygame.Color(255, 255, 255, 0), vertices, 1) self.angle += self.angle_step # axis vectors pygame.draw.polygon( self.surface, pygame.Color(255, 0, 0, 0), (self.center, self.__projectm(self.x_axis, self.center)), 1) pygame.draw.polygon( self.surface, pygame.Color(0, 255, 0, 0), (self.center, self.__projectm(self.y_axis, self.center)), 1) pygame.draw.polygon( self.surface, pygame.Color(0, 0, 255, 0), (self.center, self.__projectm(self.z_axis, self.center)), 1)
def get_pyramid_mesh(): faces = [] # front tri = Face3D(get_triangle_points()) #t = Matrix3D.get_shift_matrix(0, 0, 1).dot(Matrix3D.get_rot_x_matrix(-math.pi/4)) face = tri.transform(Matrix3D.get_rot_x_matrix(-math.pi / 4)) face = face.transform(Matrix3D.get_shift_matrix(0, 0, 1)) faces.append(face) # back face = tri.transform(Matrix3D.get_rot_x_matrix(math.pi / 4)) face = face.transform(Matrix3D.get_shift_matrix(0, 0, -1)) faces.append(face) # left face = tri.transform(Matrix3D.get_rot_x_matrix(-math.pi / 4)) face = face.transform(Matrix3D.get_rot_y_matrix(-math.pi / 2)) face = face.transform(Matrix3D.get_shift_matrix(1, 0, 0)) faces.append(face) # right face = tri.transform(Matrix3D.get_rot_x_matrix(-math.pi / 4)) face = face.transform(Matrix3D.get_rot_y_matrix(math.pi / 2)) face = face.transform(Matrix3D.get_shift_matrix(-1, 0, 0)) faces.append(face) return Mesh3D(faces)
def get_pyramid_mesh(): faces = [] # front tri = Face3D(get_triangle_points()) #t = Matrix3D.get_shift_matrix(0, 0, 1).dot(Matrix3D.get_rot_x_matrix(-math.pi/4)) face = tri.transform(Matrix3D.get_rot_x_matrix(-math.pi/4)) face = face.transform(Matrix3D.get_shift_matrix(0, 0, 1)) faces.append(face) # back face = tri.transform(Matrix3D.get_rot_x_matrix(math.pi/4)) face = face.transform(Matrix3D.get_shift_matrix(0, 0, -1)) faces.append(face) # left face = tri.transform(Matrix3D.get_rot_x_matrix(-math.pi/4)) face = face.transform(Matrix3D.get_rot_y_matrix(-math.pi/2)) face = face.transform(Matrix3D.get_shift_matrix(1, 0, 0)) faces.append(face) # right face = tri.transform(Matrix3D.get_rot_x_matrix(-math.pi/4)) face = face.transform(Matrix3D.get_rot_y_matrix(math.pi/2)) face = face.transform(Matrix3D.get_shift_matrix(-1, 0, 0)) faces.append(face) return Mesh3D(faces)
def get_cube_mesh(): # a cube Mesh consist of six Faces # left faces = [] rec = Face3D(get_rectangle_points()) t = Matrix3D.get_shift_matrix(-1, 0, 0).dot(Matrix3D.get_rot_y_matrix(math.pi/2)) faces.append(rec.transform(t)) # right t = Matrix3D.get_shift_matrix(1, 0, 0).dot(Matrix3D.get_rot_y_matrix(math.pi/2)) faces.append(rec.transform(t)) # bottom t = Matrix3D.get_shift_matrix(0, -1, 0).dot(Matrix3D.get_rot_x_matrix(math.pi/2)) faces.append(rec.transform(t)) # top t = Matrix3D.get_shift_matrix(0, 1, 0).dot(Matrix3D.get_rot_x_matrix(math.pi/2)) faces.append(rec.transform(t)) # front t = Matrix3D.get_shift_matrix(0, 0, -1) faces.append(rec.transform(t)) # back t = Matrix3D.get_shift_matrix(0, 0, 1) faces.append(rec.transform(t)) return Mesh3D(faces)
def test_det(self): m = Matrix3D.identity() print "det(I)=", m.det() # for next example look at # http://matheguru.com/lineare-algebra/207-determinante.html mr = Matrix3D([ [ 5, 0, 3, -1 ], [ 3, 0, 0, 4 ], [ -1, 2, 4, -2 ], [ 1, 0, 0, 5 ], ]) print "T(mr)=\n", mr.transpose() print "det(mr)=", mr.det() assert mr.det() == 66 print "det(T(mr))=", mr.transpose().det() assert mr.det() == mr.transpose().det()
def test_matrix_dot(self): """test dot product identity matrix and transpose""" mi = Matrix3D.identity() # I dot transposed(I) = I assert mi == mi.dot(mi.transpose()) mr = Matrix3D([ [ 1, 2, 3, 4 ], [ 5, 6, 7, 8 ], [ 9, 10, 11, 12 ], [ 13, 14, 15, 16 ], ]) assert mr.dot(mi) == mr test_transposed = Matrix3D([ [1, 5, 9, 13], [2, 6, 10, 14], [3, 7, 11, 15], [4, 8, 12, 16] ]) assert mr.transpose() == test_transposed test_m = Matrix3D([ [30, 70, 110, 150], [70, 174, 278, 382], [110, 278, 446, 614], [150, 382, 614, 846], ]) assert mr.dot(mr.transpose()) == test_m A = Matrix3D([ [ 3, 0, 0, 0 ], [ 0, -1, 0, 0 ], [ 0, 0, 2, 0 ], [ 0, 0, 0, 1 ] ]) B = Matrix3D([ [ math.sqrt(3)/2, 0, -1/2, 0 ], [ 0, 1, 0, 0 ], [ 1/2, 0, math.sqrt(3)/2, 0 ], [ 0, 0, 0, 1] ]) C = Matrix3D([ [1, 0, 0, 3], [0, 1, 0, -1], [0, 0, 1, 2], [0, 0, 0, 1] ]) # testing assosiativeness (A*B)*C == A*(B*C) assert A.dot(B).dot(C) == A.dot(B.dot(C))
def test_transformations(self): # test zeros m = Matrix3D.zeros() assert isinstance(m, Matrix3D) # test if __repr__ is able to convert to object m1 = eval(m.__repr__()) assert m == m1 # test identity m = Matrix3D.identity() assert isinstance(m, Matrix3D) # test __getitem__ interface assert m[0, 0] == 1 assert m[1, 1] == 1 assert m[2, 2] == 1 assert m[3, 3] == 1 # get column vector assert m.col(0) == [1, 0, 0, 0] m1 = Matrix3D.identity() assert m1.dot(Matrix3D.identity()) == Matrix3D.identity() assert m1.dot(Matrix3D.zeros()) == Matrix3D.zeros()
def test_rot_matrices(self): m = Matrix3D.get_rot_x_matrix(100) assert m.dot(Matrix3D.identity()) == m m = Matrix3D.get_rot_y_matrix(100) assert m.dot(Matrix3D.identity()) == m m = Matrix3D.get_rot_z_matrix(100) assert m.dot(Matrix3D.identity()) == m # rotate vector only in x-axis around x - nothing should happen v1 = Vector3D(1, 0, 0, 1) assert Matrix3D.get_rot_x_matrix(100).v_dot(v1) == v1 v1 = Vector3D(0, 1, 0, 1) assert Matrix3D.get_rot_y_matrix(100).v_dot(v1) == v1 v1 = Vector3D(0, 0, 1, 1) assert Matrix3D.get_rot_z_matrix(100).v_dot(v1) == v1 # rotate vectors really v1 = Vector3D(1.0, 0.0, 0.0, 1.0) # 90 degrees or pi/2 real_v = Matrix3D.get_rot_z_matrix(math.pi/2).v_dot(v1) test_v = Vector3D.from_list([0.000000, 1.000000, 0.000000, 1.000000]) assert real_v.nearly_equal(test_v) # 180 degrees real_v = Matrix3D.get_rot_z_matrix(math.pi).v_dot(v1) test_v = Vector3D.from_list([-1.000000, 0.000000, 0.000000, 1.000000]) assert real_v.nearly_equal(test_v) # 270 degrees real_v = Matrix3D.get_rot_z_matrix(math.pi + math.pi/2).v_dot(v1) test_v = Vector3D.from_list([0.000000, -1.000000, 0.000000, 1.000000]) assert real_v.nearly_equal(test_v) # 360 degrees real_v = Matrix3D.get_rot_z_matrix(2 * math.pi).v_dot(v1) test_v = Vector3D.from_list([1.000000, 0.000000, 0.000000, 1.000000]) assert real_v.nearly_equal(test_v) # rotate around Y-Axis about 180 degrees real_v = Matrix3D.get_rot_y_matrix(math.pi).v_dot(v1) test_v = Vector3D.from_list([-1.000000, 0.000000, 0.000000, 1.000000]) assert real_v.nearly_equal(test_v) # rotate y:90 and x:90 -> (0, 1, 0, 1) real_v = Matrix3D.get_rot_y_matrix(math.pi/2).v_dot(v1) test_v = Vector3D.from_list([0.000000, 0.000000, -1.000000, 1.000000]) assert real_v.nearly_equal(test_v) real_v = Matrix3D.get_rot_x_matrix(math.pi/2).v_dot(real_v) test_v = Vector3D.from_list([0.000000, 1.000000, 0.000000, 1.000000]) assert real_v.nearly_equal(test_v) # and this is the combined version rot_y = Matrix3D.get_rot_y_matrix(math.pi/2) print "rotation around y:\n", rot_y rot_x = Matrix3D.get_rot_x_matrix(math.pi/2) print "rotation around x:\n", rot_x rot_z = Matrix3D.get_rot_z_matrix(math.pi/2) print "rotation around z:\n", rot_z rot_m = rot_x.dot(rot_y.dot(rot_z)) print "combined rotation matrix:\n", rot_m real_v = rot_m.v_dot(v1) print "resulting vector:", real_v test_v = Vector3D.from_list([0.000000, 1.000000, 0.000000, 1.000000]) assert real_v.nearly_equal(test_v)
def test_rot_matrices(self): m = Matrix3D.get_rot_x_matrix(100) assert m.dot(Matrix3D.identity()) == m m = Matrix3D.get_rot_y_matrix(100) assert m.dot(Matrix3D.identity()) == m m = Matrix3D.get_rot_z_matrix(100) assert m.dot(Matrix3D.identity()) == m # rotate vector only in x-axis around x - nothing should happen v1 = Vector3D(1, 0, 0, 1) assert Matrix3D.get_rot_x_matrix(100).v_dot(v1) == v1 v1 = Vector3D(0, 1, 0, 1) assert Matrix3D.get_rot_y_matrix(100).v_dot(v1) == v1 v1 = Vector3D(0, 0, 1, 1) assert Matrix3D.get_rot_z_matrix(100).v_dot(v1) == v1 # rotate vectors really v1 = Vector3D(1.0, 0.0, 0.0, 1.0) # 90 degrees or pi/2 real_v = Matrix3D.get_rot_z_matrix(math.pi / 2).v_dot(v1) test_v = Vector3D.from_list([0.000000, 1.000000, 0.000000, 1.000000]) assert real_v.nearly_equal(test_v) # 180 degrees real_v = Matrix3D.get_rot_z_matrix(math.pi).v_dot(v1) test_v = Vector3D.from_list([-1.000000, 0.000000, 0.000000, 1.000000]) assert real_v.nearly_equal(test_v) # 270 degrees real_v = Matrix3D.get_rot_z_matrix(math.pi + math.pi / 2).v_dot(v1) test_v = Vector3D.from_list([0.000000, -1.000000, 0.000000, 1.000000]) assert real_v.nearly_equal(test_v) # 360 degrees real_v = Matrix3D.get_rot_z_matrix(2 * math.pi).v_dot(v1) test_v = Vector3D.from_list([1.000000, 0.000000, 0.000000, 1.000000]) assert real_v.nearly_equal(test_v) # rotate around Y-Axis about 180 degrees real_v = Matrix3D.get_rot_y_matrix(math.pi).v_dot(v1) test_v = Vector3D.from_list([-1.000000, 0.000000, 0.000000, 1.000000]) assert real_v.nearly_equal(test_v) # rotate y:90 and x:90 -> (0, 1, 0, 1) real_v = Matrix3D.get_rot_y_matrix(math.pi / 2).v_dot(v1) test_v = Vector3D.from_list([0.000000, 0.000000, -1.000000, 1.000000]) assert real_v.nearly_equal(test_v) real_v = Matrix3D.get_rot_x_matrix(math.pi / 2).v_dot(real_v) test_v = Vector3D.from_list([0.000000, 1.000000, 0.000000, 1.000000]) assert real_v.nearly_equal(test_v) # and this is the combined version rot_y = Matrix3D.get_rot_y_matrix(math.pi / 2) print "rotation around y:\n", rot_y rot_x = Matrix3D.get_rot_x_matrix(math.pi / 2) print "rotation around x:\n", rot_x rot_z = Matrix3D.get_rot_z_matrix(math.pi / 2) print "rotation around z:\n", rot_z rot_m = rot_x.dot(rot_y.dot(rot_z)) print "combined rotation matrix:\n", rot_m real_v = rot_m.v_dot(v1) print "resulting vector:", real_v test_v = Vector3D.from_list([0.000000, 1.000000, 0.000000, 1.000000]) assert real_v.nearly_equal(test_v)
from Matrix3D import Matrix3D from Solver import Solver from Vector import Vector3D filename = 'sle3D.txt' a = Matrix3D() b = Vector3D() a.read_from_file(filename) b.read_from_file(filename) a.print() b.print() print() s = Solver(a, b) print(s.solve())