def update_sphere(self): # start = datetime.now() if (datetime.now() - self._last_time).total_seconds() > 0.1: if self._ui.track_camera: if self._camera is None: self._camera = SceneManager.get_instance().current_scene.active_camera # Store the camera pos for access by the quad children self._camera_pos = self._camera.node_parent.transform.position - self.transform.position self._camera_pos_sc = CubeSphereMap.get_cube_coord(self._camera_pos.x, self._camera_pos.y, self._camera_pos.z) self._line.line_to(self._camera_pos) if self._ui.planet_camera: # Check if the camera has intersected the planet. if self._camera_pos.magnitude() < (self._radius + self._max_height): u = self._camera_pos_sc.x v = self._camera_pos_sc.y face = self._camera_pos_sc.face self._camera.node_parent.transform.position = CubeSphereMap.get_sphere_position(u, v, face, (self._radius + self._max_height)) # Reset the number of splits self._num_splits = 0 #print "Resetting splits" # If the camera has moved a sufficient distance to warrant an update # if self._last_camera_pos is None: # self._last_camera_pos = self._camera_pos # dist = self._last_camera_pos - self._camera_pos # if dist.magnitude() > 1.0: # Calc the horizon altitude = self._camera_pos.magnitude() horizon_altitude = max([altitude-self.radius, self.max_height]) self._horizon = math.sqrt(horizon_altitude * horizon_altitude + 2.0 * horizon_altitude * self._radius) if True: # Update all of the sides of the cube/sphere for child in self.transform.children: if isinstance(child.node, SphereQuad): child.node.update_surface() self._last_camera_pos = self._camera_pos self._last_time = datetime.now() # Update the UI with the camera pos # self._ui.rel_camera_pos = self._camera_pos # self._ui.camera_pos = self._camera_pos_sc if not self._camera_pos_sc is None: pos = CubeSphereMap.get_sphere_vector(self._camera_pos_sc.x, self._camera_pos_sc.y, self._camera_pos_sc.face) pos.normalize() pos *= (self._radius / 1.9) self._camera_gizmo.transform.position = pos
def update_surface(self): pos = self._sphere_parent.camera.node_parent.transform.position # Get the distances of the camera from the quads # This needs to be updated in future to handle transform applied to the planet # i.e. rotation and position distances = [pos.distance(self._child_pos[QuadName.TL]), pos.distance(self._child_pos[QuadName.TR]), pos.distance(self._child_pos[QuadName.BR]), pos.distance(self._child_pos[QuadName.BL]), ] # Sort the quads by distance from the camera for updating and rendering. # Not using actual distances to avoid precision errors coord = CubeSphereMap.get_cube_coord(*pos) self._sorted_quads = [] if coord.x < self._centre_coords[0]: # In top left if coord.y < self._centre_coords[1]: #print "TL" self._sorted_quads.append(0) self._sorted_quads.append(1) self._sorted_quads.append(2) self._sorted_quads.append(3) # In bottom left else: #print "BL" self._sorted_quads.append(2) self._sorted_quads.append(0) self._sorted_quads.append(3) self._sorted_quads.append(1) else: # In top right if coord.y < self._centre_coords[1]: #print "TR" self._sorted_quads.append(1) self._sorted_quads.append(0) self._sorted_quads.append(3) self._sorted_quads.append(2) # In bottom right else: #print "BR" self._sorted_quads.append(2) self._sorted_quads.append(3) self._sorted_quads.append(0) self._sorted_quads.append(1) # Calculate the quadrant size using the length of the diagonal across the quadrant #TODO: Maybe this is used to adjust the frustrum on the fly when the camera gets close to the planet?? quad_size = self._child_pos[QuadName.TL] - self._child_pos[QuadName.BR] * 1.0 #( radius / frustrum radius).... radius = self._sphere_parent.radius # Calculate split priority # Adjust the quadrant size because the quadrants become distorted near the corners of the cube # resulting in incorrect splitting/merging of quads. quad_size = (self._corners[2] - self._corners[0]) * radius priority = 0.0 if quad_size > (self._sphere_parent.max_height * 0.001): priority = self._sphere_parent.split_factor * math.pow(quad_size, self._sphere_parent.split_power ) for quad_inc in self._sorted_quads: # Check to see if the camera is within this quadrant if not self.hit_test(self._sphere_parent.camera_pos_sc, quad_inc): # Check the quadrant against the horizon distance if self._sphere_parent.horizon > 0.0 and \ (distances[quad_inc] - radius) > self._sphere_parent.horizon: if not self._get_quad(quad_inc) is None: self._get_quad(quad_inc)._merge() #print "Horizon" continue # Check the quadrant against the view frustrum if not self._get_quad(quad_inc) is None and not self._get_quad(quad_inc)._is_split: child_quad_size = quad_size / 2.0 inside = self._sphere_parent.camera.sphere_inside(self._child_pos[quad_inc], child_quad_size) if inside == 1: quad = self._get_quad(quad_inc) #Logger.Log("Culling Quad: sz: %f name: %s pos: %s" % ( child_quad_size, quad.name, str(child_pos[quad_inc]) ) ) quad._merge() continue if distances[quad_inc] > priority: if not self._get_quad(quad_inc) is None: #print "merging due to distance: " + QuadName.quad_string(quad_inc) self._get_quad(quad_inc)._merge() # if self._level == self._planet_root._max_depth: # print "merging split level: %d" % self._level # print priority # print distances #print "Distance" continue # If the quad is futher away than its size then dont split it if distances[quad_inc] > quad_size: continue # if self._level <= self._planet_root._max_depth: # # print priority # # print distances # # print "Split level: %d" % self._levelx # Logger.Log("Splitting Quad: name: %s" % ( self.name) ) # self._split(quad_inc) if self._is_split: self._get_quad(quad_inc).update_surface() elif self._level <= self._planet_root._max_depth: #Logger.Log("Splitting Quad: name: %s" % ( self.name) ) self._split(quad_inc)