def cam_transform(self, camera): """camera = VCam object returns Position object representing the camera's view""" # translation inversion t = self.translate(-camera.pos[0], -camera.pos[1], -camera.pos[2]) cam_pos_col = [[camera.pos[0]], [camera.pos[1]], [camera.pos[2]]] cam_upvec_col = [[camera.upvec[0]], [camera.upvec[1]], [camera.upvec[2]]] # rotation inversion # ***maybe try quaternions here instead? # 3 perpendicular unit vecs with Z pointing towards the camera Z = matrix.normalize(matrix.subtract(t.vec[0:3], cam_pos_col)) X = matrix.normalize(matrix.crossprod(cam_upvec_col, Z)) Y = matrix.crossprod(Z, X) # camera rotation inversion matrix for the object C = [ [X[0][0], X[1][0], X[2][0], 0], # [Xaxis.x, Xaxis.y, Xaxis.z, 0] [Y[0][0], Y[1][0], Y[2][0], 0], # [Yaxis.x, Yaxis.y, Yaxis.z, 0] [Z[0][0], Z[1][0], Z[2][0], 0], # [Zaxis.x, Zaxis.y, Zaxis.z, 0] [0, 0, 0, 1] ] # the camera transformation can be done with a single matrix mult vec = matrix.multiply(C, t.vec) return Position(vec[0][0], vec[1][0], vec[2][0])
def get_roll_to(head, tail, normal): """ Compute the roll angle for a bone to make the bone's local x axis align with the specified normal. """ p1 = toZisUp3(head) p2 = toZisUp3(tail) xvec = normal pvec = matrix.normalize(p2-p1) xy = np.dot(xvec,pvec) yvec = matrix.normalize(pvec-xy*xvec) zvec = matrix.normalize(np.cross(xvec, yvec)) mat = np.asarray((xvec,yvec,zvec), dtype=np.float32) try: assertOrthogonal(mat) except Exception as e: log.warning("Calculated matrix is not orthogonal (%s)" % e) quat = tm.quaternion_from_matrix(mat) if abs(quat[0]) < 1e-4: return 0 else: roll = math.pi - 2*math.atan(quat[2]/quat[0]) if roll < -math.pi: roll += 2*math.pi elif roll > math.pi: roll -= 2*math.pi return roll
def compute_camera_ray(width, height, camera, view_width, x, y): normalized_x = (0.5 - (1.0 * x / width)) * view_width normalized_y = (0.5 - (1.0 * y / height)) * view_width ray_direction = matrix.normalize(normalized_x * camera.right + normalized_y * camera.up + camera.direction) ray = Ray(origin=camera.position, vector=ray_direction) return ray
def ray(self, x, y): u = self.canvas['width'] * ((x / self.image['width']) - 0.5) v = self.canvas['height'] * ((y / self.image['height']) - 0.5) w = -self.zPlane['near'] a = np.array(self.coordSystem['x'] * u) b = np.array(self.coordSystem['y'] * v) c = np.array(self.coordSystem['z'] * w) d = mat.normalize((a + b) + c) return d
def get_normal(skel, plane_name, plane_defs, human=None): """ Return the normal of a triangle plane defined between three joint positions, using counter-clockwise winding order (right-handed). """ if plane_name not in plane_defs: log.warning("No plane with name %s defined for skeleton.", plane_name) return np.asarray([0,1,0], dtype=np.float32) if not human: from core import G human = G.app.selectedHuman joint_names = plane_defs[plane_name] j1,j2,j3 = joint_names p1 = skel.getJointPosition(j1, human)[:3] * skel.scale p2 = skel.getJointPosition(j2, human)[:3] * skel.scale p3 = skel.getJointPosition(j3, human)[:3] * skel.scale pvec = matrix.normalize(p2-p1) yvec = matrix.normalize(p3-p2) return matrix.normalize(np.cross(yvec, pvec))
def get_intersection(self, ray): c = (self.center - ray.origin) c_distance_sqred = (c**2).sum() proj_on_ray = np.dot(c, ray.vector) d = self.radius ** 2 - (c_distance_sqred - proj_on_ray ** 2) if d >= 0: d = math.sqrt(d) v = proj_on_ray / np.linalg.norm(ray.vector) distance = v - d intersection_point = ray.origin + distance * ray.vector # find normal normal = matrix.normalize(intersection_point - self.center) return distance, normal return None, None
def getMatrix(head, tail, normal): mat = np.identity(4, dtype=np.float32) bone_direction = tail - head bone_direction = matrix.normalize(bone_direction[:3]) normal = matrix.normalize(normal[:3]) # This would be the ideal case, where normal is always perpendicular to # bone_direction, which in practice will often not be the case ''' # Construct a base with orthonormal vectors mat[:3,0] = normal[:3] # bone local X axis mat[:3,1] = bone_direction[:3] # bone local Y axis # Create a Z vector perpendicular on X and Y axes z_axis = matrix.normalize(np.cross(normal, bone_direction)) mat[:3,2] = z_axis[:3] # bone local Z axis ''' # We want an orthonormal base, so... # Take Z as perpendicular to normal and bone_direction # We want a right handed axis system so use cross product order X * Y * Z z_axis = matrix.normalize(np.cross(normal, bone_direction)) # We now have two vertices that are orthogonal, we still need Y # Calculate Y as orthogonal on the other two, it should approximate the # normal specified as argument to this function x_axis = matrix.normalize(np.cross(bone_direction, z_axis)) # Now we construct our orthonormal base mat[:3,0] = x_axis[:3] # bone local X axis mat[:3,1] = bone_direction[:3] # bone local Y axis mat[:3,2] = z_axis[:3] # bone local Z axis # Add head position as translation mat[:3,3] = head[:3] return mat
# shape.transform = rotation_z(pi / 4) * scaling(0.5, 1, 1) # shape.transform = shearing(1, 0, 0, 0, 0, 0) * scaling(0.5, 1, 1) start = time.time() print("Starting render...") for y in range(canvas_pixels): world_y = half - pixel_size * y for x in range(canvas_pixels): world_x = -half + pixel_size * x position = point(world_x, world_y, wall_z) r = ray(ray_origin, normalize(position - ray_origin)) xs = intersect(shape, r) if hit(xs) is not None: write_pixel(canvas, x, y, color) end = time.time() print("Finished render.") print(str(round(end - start, 2)) + "s") start = time.time() print("Start writing file...") canvas_to_ppm(canvas).write_file("images/circle.ppm") end = time.time() print("Finished writing file.") print(str(round(end - start, 2)) + "s")
def getRestDirection(self): # TODO make configurable like getRestMatrix return matrix.normalize(self.getRestOffset())
def getRestDirection(self): return matrix.normalize(self.getRestOffset())
def __compute_right_up(self): self.right = matrix.normalize(np.cross(self.direction, self.up)) self.up = np.cross(self.right, self.direction)
def look_at(self, eye, center, up): self.position = eye self.direction = matrix.normalize(center - eye) self.up = matrix.normalize(up) self.__compute_right_up()