def world_to_screen_point(point, camera): """Get view of the point on screen""" tr = camera.transform.get_global_transform() screen_plane = Plane.From_normal(tr.forward, point) screen_middle_point = Ray(tr.position, tr.forward).intersect_plane(screen_plane) screen_width = math.tan(math.radians(camera.FOV / 2)) * vector3.magnitude( vector3.subtract(screen_middle_point, tr.position)) * 2 screen_height = screen_width / camera.aspect_ratio point_in_camera_space = convert_to_different_space( vector3.subtract(point, screen_middle_point), tr.right, tr.down, tr.forward) point_right_vector = vector3.add( vector3.scale(tr.right, screen_width / 2), vector3.scale(tr.right, point_in_camera_space[0])) point_down_vector = vector3.add( vector3.scale(tr.down, screen_height / 2), vector3.scale(tr.down, point_in_camera_space[1])) point_right = vector3.magnitude(point_right_vector) / screen_width point_down = vector3.magnitude(point_down_vector) / screen_height scale_right = vector3.scale_div(point_right_vector, tr.right) if scale_right < 0: point_right = -point_right scale_down = vector3.scale_div(point_down_vector, tr.down) if scale_down < 0: point_down = -point_down return (point_right * camera.resolution[0], point_down * camera.resolution[1])
def Calculate_normal(self, inverted=False): plane_vector1 = vector3.subtract(self.vertex[0], self.vertex[1]) plane_vector2 = vector3.subtract(self.vertex[1], self.vertex[2]) normal = vector3.cross(plane_vector1, plane_vector2) normal = vector3.normalize(normal) if not inverted: return normal else: return vector3.scale(normal, -1)
def From_points(vertex1, vertex2, vertex3): plane_vector1 = vector3.subtract(vertex1, vertex2) plane_vector2 = vector3.subtract(vertex2, vertex3) normal = vector3.cross(plane_vector1, plane_vector2) normal = vector3.normalize(normal) a = normal[0] b = normal[1] c = normal[2] d = -normal[0] * vertex1[0] - normal[1] * vertex1[1] - normal[ 2] * vertex1[2] plane = Plane((a, b, c, d)) return plane
def should_face_be_backwards_culled(face): return vector3.dot( vector3.subtract( face.vertex[0], Local_to_world_space(camera.main_camera.transform.position, camera.main_camera.parent.transform)), face.normal) > 0
def limit_edge_to_camera_clip(edge, camera): clipping_plane = camera.get_clipping_plane() a_behind_clip = is_point_behind_camera_clip(edge.A, camera) b_behind_clip = is_point_behind_camera_clip(edge.B, camera) if a_behind_clip and b_behind_clip: return None if a_behind_clip: ray = Ray(edge.B, vector3.subtract(edge.A, edge.B)) edge.A = ray.intersect_plane(clipping_plane) if b_behind_clip: ray = Ray(edge.A, vector3.subtract(edge.B, edge.A)) edge.B = ray.intersect_plane(clipping_plane) return edge
def _sort_faces_(): #TODO: FIX THIS switch = True while switch: switch = False for i in range(0, len(all_faces) - 1): if vector3.dot(all_faces[i].normal, Screen.main_camera.global_transform.forward) < 0: vc = all_faces[i].normal else: vc = vector3.scale(all_faces[i].normal, -1) above = True below = True for vertex in all_faces[i + 1].vertex: if Geometry.Axis_view( vc, vector3.subtract(vertex, all_faces[i].vertex[0])) >= 0: below = False else: above = False if not above and not below: if vector3.dot( all_faces[i + 1].normal, Screen.main_camera.global_transform.forward) < 0: vc = all_faces[i + 1].normal else: vc = vector3.scale(all_faces[i + 1].normal, -1) above = True below = True for vertex in all_faces[i].vertex: if Geometry.Axis_view( vc, vector3.subtract(vertex, all_faces[i + 1].vertex[0])) >= 0: below = False else: above = False if above: all_faces[i], all_faces[i + 1] = all_faces[i + 1], all_faces[i] switch = True elif below: all_faces[i], all_faces[i + 1] = all_faces[i + 1], all_faces[i] switch = True
def Dist_from_ground(self): ray = Ray( Local_to_world_space(self.parent.collider.center, self.parent.transform), (0, 0, -1)) if ray.Collide(self.parent).point and ray.Collide().point: dist_vector = vector3.subtract(ray.Collide().point, ray.Collide(self.parent).point) return vector3.magnitude(dist_vector) else: return None
def Point_collision(box, point): box_center = vector3.add( box.parent.transform.position, Quaternion.rotate_vector(box.center, box.parent.transform.rotation)) rotated_point = Quaternion.rotate_vector( vector3.subtract(point, box_center), box.parent.transform.rotation.conjugate()) if abs(rotated_point[0]) > box.size[0] * box.parent.transform.scale[0]: return False if abs(rotated_point[1]) > box.size[1] * box.parent.transform.scale[1]: return False if abs(rotated_point[2]) > box.size[2] * box.parent.transform.scale[2]: return False return True
def get_signed_distance_to_point(self, point): """ Returns: 0 if point lays on the plane distance from the plane if point is on positive side of plane Negative distance if point is on negative side of plane """ if self.factors[2] != 0.0: plane_point = (0.0, 0.0, -self.factors[3] / self.factors[2]) elif self.factors[1] != 0.0: plane_point = (0.0, -self.factors[3] / self.factors[1], 0.0) else: plane_point = (-self.factors[3] / self.factors[0], 0.0, 0.0) points_diff = vector3.subtract(point, plane_point) return vector3.dot(points_diff, self.normal())
def World_to_local_space(point, transform): point_translated = vector3.subtract(point, transform.position) point_translated_and_rotated = Quaternion.rotate_vector(point_translated, transform.rotation.inverse()) return point_translated_and_rotated
def is_point_behind_camera_clip(point, camera): tr = camera.transform.get_global_transform() clip_position = vector3.add(tr.position, vector3.scale(tr.forward, camera.clip_min)) return vector3.dot(vector3.subtract(point, clip_position), tr.forward) < 0.0