예제 #1
0
 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)
예제 #2
0
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()
예제 #3
0
 def step(self, direction, distance):
     rotation = LQuaterniond()
     look_at(rotation, direction, LVector3d.up())
     delta = rotation.xform(LVector3d(0, distance, 0))
     self.delta(delta)