def go_to_surface(self, duration = None, height=1.001): if not self.ui.selected: return target = self.ui.selected if duration is None: duration = settings.slow_move print("Go to surface", target.get_name()) self.ui.sync_selected() center = target.get_rel_position_to(self.ship._global_position) direction = self.ship.get_pos() - center new_orientation = LQuaterniond() lookAt(new_orientation, direction) height = target.get_height_under(self.ship.get_pos()) + 10 * units.m new_position = center + new_orientation.xform(LVector3d(0, height, 0)) self.move_and_rotate_to(new_position, new_orientation, duration=duration)
class StellarObject(LabelledObject): has_rotation_axis = False has_reference_axis = False has_orbit = True has_halo = False has_resolved_halo = False virtual_object = False support_offset_body_center = True def __init__(self, names, orbit=None, rotation=None, body_class=None, point_color=None, description=''): LabelledObject.__init__(self, names) self.description = description self.system = None self.body_class = body_class if orbit is None: orbit = FixedOrbit() self.orbit = orbit if rotation is None: rotation = FixedRotation() self.rotation = rotation if point_color is None: point_color = LColor(1.0, 1.0, 1.0, 1.0) self.point_color = point_color self.abs_magnitude = 99.0 #Flags self.visible = True #TODO: Should be False at init self.resolved = True #TODO: Should be False at init self.in_view = False self.selected = False #Cached values self._position = LPoint3d() self._global_position = LPoint3d() self._local_position = LPoint3d() self._orbit_position = LPoint3d() self._orbit_rotation = LQuaterniond() self._orientation = LQuaterniond() self._equatorial = LQuaterniond() self._app_magnitude = None self._extend = 0.0 #Scene parameters self.rel_position = None self.distance_to_obs = None self.vector_to_obs = None self.distance_to_star = None self.vector_to_star = None self.height_under = 0.0 self.star = None self.light_color = (1.0, 1.0, 1.0, 1.0) self.visible_size = 0.0 self.scene_position = None self.scene_orientation = None self.scene_scale_factor = None self.world_body_center_offset = LVector3d() self.model_body_center_offset = LVector3d() self.projected_world_body_center_offset = LVector3d() #Components self.orbit_object = None self.rotation_axis = None self.reference_axis = None self.init_annotations = False self.init_components = False self.update_frozen = False #TODO: Should be done properly self.orbit.body = self self.rotation.body = self objectsDB.add(self) def check_settings(self): LabelledObject.check_settings(self) if self.body_class is None: print("No class for", self.get_name()) return self.set_shown(bodyClasses.get_show(self.body_class)) def get_fullname(self, separator='/'): if hasattr(self, "primary") and self.primary is not None: name = self.primary.get_friendly_name() else: name = self.get_friendly_name() if not hasattr(self.parent, "primary") or self.parent.primary is not self: fullname = self.parent.get_fullname(separator) else: fullname = self.parent.parent.get_fullname(separator) if fullname != '': return fullname + separator + name else: return name def create_label_instance(self): if isinstance(self.orbit, FixedPosition): return FixedOrbitLabel(self.get_ascii_name() + '-label') else: return StellarBodyLabel(self.get_ascii_name() + '-label') def get_description(self): return self.description def create_annotations(self): if self.has_orbit and self.orbit.dynamic: self.create_orbit_object() self.init_annotations = True def create_components(self): if self.has_rotation_axis: self.rotation_axis = RotationAxis(self) self.add_component(self.rotation_axis) if self.has_reference_axis: self.reference_axis = ReferenceAxis(self) self.add_component(self.reference_axis) self.init_components = True def update_components(self, camera_pos): pass def remove_components(self): self.remove_component(self.rotation_axis) self.rotation_axis = None self.remove_component(self.reference_axis) self.reference_axis = None self.init_components = False def remove_annotations(self): self.remove_component(self.orbit_object) self.orbit_object = None self.init_annotations = False def set_system(self, system): self.system = system def set_body_class(self, body_class): self.body_class = body_class def create_orbit_object(self): if self.orbit_object is None and not isinstance(self.orbit, FixedOrbit) and not isinstance(self.orbit, FixedPosition): self.orbit_object = Orbit(self) self.add_component(self.orbit_object) def set_orbit(self, orbit): if self.orbit_object is not None: self.remove_component(self.orbit_object) self.orbit_object = None self.orbit = orbit self.orbit.body = self if self.has_orbit and self.init_annotations: self.create_orbit_object() def set_rotation(self, rotation): self.rotation = rotation if self.rotation: self.rotation.body = self def find_by_name(self, name, name_up=None): if self.is_named(name, name_up): return self else: return None def is_named(self, name, name_up=None): if name_up is None: name_up = name.upper() for name in self.names: if name.upper() == name_up: return True else: return False def set_selected(self, selected): self.selected = selected if self.orbit_object: self.orbit_object.set_selected(selected) else: if self.parent: self.parent.set_selected(selected) def set_parent(self, parent): CompositeObject.set_parent(self, parent) self.orbit.frame.set_parent_body(self.parent) self.rotation.frame.set_parent_body(self.parent) self.create_orbit_object() def set_star(self, star): self.star = star def is_emissive(self): return False def get_label_color(self): return bodyClasses.get_label_color(self.body_class) def get_label_size(self): return settings.label_size def get_label_text(self): return self.get_name() def get_orbit_color(self): return bodyClasses.get_orbit_color(self.body_class) def get_apparent_radius(self): return 0 def get_extend(self): return self.get_apparent_radius() def calc_height_under(self, camera_pos): self.height_under = self.get_height_under(camera_pos) def get_abs_magnitude(self): return 99.0 def get_app_magnitude(self): if self.distance_to_obs != None and self.distance_to_obs > 0: return abs_to_app_mag(self.get_abs_magnitude(), self.distance_to_obs) return 99.0 def get_global_position(self): #TODO: should be done in frame #TODO: cache value for given time global_position = self.parent.get_global_position() + self.orbit.get_global_position_at(0) return global_position def get_local_position(self): return self.orbit.frame.get_local_position(self._orbit_rotation.xform(self._orbit_position)) def get_position(self): return self.get_global_position() + self.get_local_position() def get_rel_position_to(self, position): return (self.get_global_position() - position) + self.get_local_position() def get_abs_rotation(self): return self.rotation.frame.get_abs_orientation(self._orientation) def get_equatorial_rotation(self): return self.rotation.frame.get_abs_orientation(self._equatorial) def get_sync_rotation(self): return self.rotation.frame.get_abs_orientation(self._orientation) def cartesian_to_spherical(self, position): sync_frame = SynchroneReferenceFrame(self) rel_position = sync_frame.get_rel_position(position) distance = rel_position.length() if distance > 0: theta = asin(rel_position[2] / distance) if rel_position[0] != 0.0: phi = atan2(rel_position[1], rel_position[0]) #Offset phi by 180 deg with proper wrap around #phi = (phi + pi + pi) % (2 * pi) - pi else: phi = 0.0 else: phi = 0.0 theta = 0.0 return (phi, theta, distance) def spherical_to_cartesian(self, position): (phi, theta, distance) = position #Offset phi by 180 deg with proper wrap around #phi = (phi + pi + pi) % (2 * pi) - pi rel_position = LPoint3d(cos(theta) * cos(phi), cos(theta) * sin(phi), sin(theta)) rel_position *= distance sync_frame = SynchroneReferenceFrame(self) position = sync_frame.get_local_position(rel_position) return position def spherical_to_longlat(self, position): (phi, theta, distance) = position x = phi / pi / 2 + 0.5 y = 1.0 - (theta / pi + 0.5) return (x, y, distance) def longlat_to_spherical(self, position): (x, y, distance) = position phi = (x - 0.5) * pi / 2 tetha = (1.0 - y - 0.5) * pi return (phi, tetha, distance) def calc_global_distance_to(self, position): direction = self.get_position() - position length = direction.length() return (direction / length, length) def calc_local_distance_to(self, position): direction = position - self.get_local_position() length = direction.length() return (direction / length, length) def get_height_under(self, position): return self.get_apparent_radius() def calc_visible_size(self, pixel_size): if self.distance_to_obs > 0.0: return self.get_extend() / (self.distance_to_obs * pixel_size) else: return 0.0 def update(self, time): self._orbit_position = self.orbit.get_position_at(time) self._orbit_rotation = self.orbit.get_rotation_at(time) self._orientation = self.rotation.get_rotation_at(time) self._equatorial = self.rotation.get_equatorial_rotation_at(time) self._local_position = self.orbit.frame.get_local_position(self._orbit_rotation.xform(self._orbit_position)) self._global_position = self.parent._global_position + self.orbit.get_global_position_at(time) self._position = self._global_position + self._local_position if self.star: (self.vector_to_star, self.distance_to_star) = self.calc_local_distance_to(self.star.get_local_position()) CompositeObject.update(self, time) self.update_frozen = not self.resolved and not (self.orbit.dynamic or self.rotation.dynamic) def update_obs(self, observer): global_delta = self._global_position - observer.camera_global_pos local_delta = self._local_position - observer._position self.rel_position = global_delta + local_delta length = self.rel_position.length() self.vector_to_obs = -self.rel_position / length self.distance_to_obs = length self.cos_view_angle = observer.camera_vector.dot(-self.vector_to_obs) CompositeObject.update_obs(self, observer) def check_visibility(self, pixel_size): if self.distance_to_obs > 0.0: self.visible_size = self._extend / (self.distance_to_obs * pixel_size) else: self.visible_size = 0.0 self._app_magnitude = self.get_app_magnitude() self.resolved = self.visible_size > settings.min_body_size if self.resolved: radius = self.get_extend() if self.distance_to_obs > radius: D = self.rel_position + (self.context.observer.camera_vector * (radius * self.context.observer.inv_sin_dfov)) len_squared = D.dot(D) e = D.dot(self.context.observer.camera_vector) self.in_view = e >= 0.0 and e*e > len_squared * self.context.observer.sqr_cos_dfov #TODO: add check if object is slightly behind the observer else: #We are in the object self.in_view = True else: #Don't bother checking the visibility of a point self.in_view = True self.visible = self.in_view and (self.visible_size > 1.0 or self._app_magnitude < settings.lowest_app_magnitude) if not self.virtual_object and self.resolved and self.in_view: self.context.add_visible(self) LabelledObject.check_visibility(self, pixel_size) def check_and_update_instance(self, camera_pos, orientation, pointset): if self.support_offset_body_center and self.visible and self.resolved and settings.offset_body_center: height = self.get_height_under(camera_pos) self.scene_rel_position = self.rel_position + self.vector_to_obs * height distance_to_obs = self.distance_to_obs - height else: self.scene_rel_position = self.rel_position distance_to_obs = self.distance_to_obs self.scene_position, self.scene_distance, self.scene_scale_factor = self.get_real_pos_rel(self.scene_rel_position, distance_to_obs, self.vector_to_obs) self.scene_orientation = self.get_abs_rotation() if self.label is None: self.create_label() if self.visible: if not self.init_annotations: self.create_annotations() self.check_settings() if self.resolved: if self.support_offset_body_center and settings.offset_body_center: self.world_body_center_offset = -self.vector_to_obs * self.height_under * self.scene_scale_factor self.model_body_center_offset = self.scene_orientation.conjugate().xform(-self.vector_to_obs) * self.height_under / self.get_apparent_radius() if not self.init_components: self.create_components() self.check_settings() self.update_components(camera_pos) if self.visible_size < settings.min_body_size * 2: self.update_point(pointset) if self.has_resolved_halo and self._app_magnitude < smallest_glare_mag: self.update_halo() else: if self.init_components: self.remove_components() self.update_point(pointset) else: if not self.resolved: if self.init_components: self.remove_components() CompositeObject.check_and_update_instance(self, camera_pos, orientation, pointset) def remove_instance(self): CompositeObject.remove_instance(self) if self.init_components: self.remove_components() if self.init_annotations: self.remove_annotations() self.remove_label() def update_point(self, pointset): scale = mag_to_scale(self._app_magnitude) if scale > 0: color = self.point_color * scale size = max(pointset.min_size, pointset.min_size + scale * settings.mag_pixel_scale) pointset.add_point(self.scene_position, color, size) if self.has_halo and self._app_magnitude < smallest_glare_mag: self.update_halo() def update_halo(self): if not settings.show_halo: return coef = smallest_glare_mag - self._app_magnitude + 6.0 radius = self.visible_size if radius < 1.0: radius = 1.0 size = radius * coef * 2.0 position = self.scene_position self.context.haloset.add_point(LVector3(*position), self.point_color, size * 2) def show_rotation_axis(self): if self.rotation_axis: self.rotation_axis.show() def hide_rotation_axis(self): if self.rotation_axis: self.rotation_axis.hide() def toggle_rotation_axis(self): if self.rotation_axis: self.rotation_axis.toggle_shown() def show_reference_axis(self): if self.reference_axis: self.reference_axis.show() def hide_reference_axis(self): if self.reference_axis: self.reference_axis.hide() def toggle_reference_axis(self): if self.reference_axis: self.reference_axis.toggle_shown() def show_orbit(self): if self.orbit_object: self.orbit_object.show() def hide_orbit(self): if self.orbit_object: self.orbit_object.hide() def toggle_orbit(self): if self.orbit_object: self.orbit_object.toggle_shown()
def step(self, direction, distance): rotation = LQuaterniond() look_at(rotation, direction, LVector3d.up()) delta = rotation.xform(LVector3d(0, distance, 0)) self.delta(delta)