class RotationAxis(VisibleObject): default_shown = False ignore_light = True def __init__(self, body): VisibleObject.__init__(self, body.get_ascii_name() + '-axis') self.body = body def create_instance(self): self.vertexData = GeomVertexData('vertexData', GeomVertexFormat.getV3(), Geom.UHStatic) self.vertexWriter = GeomVertexWriter(self.vertexData, 'vertex') radius = 1.0 top = LPoint3d(0, 0, radius * 1.25) north_pole = LPoint3d(0, 0, radius) south_pole = LPoint3d(0, 0, -radius) bottom = LPoint3d(0, 0, -radius * 1.25) self.vertexWriter.addData3f(*top) self.vertexWriter.addData3f(*north_pole) self.vertexWriter.addData3f(*south_pole) self.vertexWriter.addData3f(*bottom) self.lines = GeomLines(Geom.UHStatic) self.lines.addVertex(0) self.lines.addVertex(1) self.lines.addVertex(2) self.lines.addVertex(3) self.lines.closePrimitive() self.geom = Geom(self.vertexData) self.geom.addPrimitive(self.lines) self.node = GeomNode(self.body.get_ascii_name() + '-axis') self.node.addGeom(self.geom) self.instance = NodePath(self.node) self.instance.setRenderModeThickness(settings.axis_thickness) self.instance.setColor(self.parent.get_orbit_color()) self.instance.setAntialias(AntialiasAttrib.MMultisample) self.instance.reparentTo(self.context.annotation) def check_settings(self): self.set_shown(settings.show_rotation_axis) def check_visibility(self, pixel_size): if self.parent.shown: distance_to_obs = self.parent.distance_to_obs if distance_to_obs > 0.0: size = self.parent.get_apparent_radius() / (distance_to_obs * pixel_size) else: size = 0.0 self.visible = size > settings.axis_fade else: self.visible = False def update_instance(self, camera_pos, orientation): if self.instance: self.place_instance(self.instance, self.parent) def get_scale(self): return self.body.get_scale()
class Boundary(VisibleObject): ignore_light = True default_shown = True def __init__(self, name, points=[], color=None): VisibleObject.__init__(self, name) self.visible = True if color is None: color = bodyClasses.get_orbit_color('boundary') self.color = color self.points = points def check_settings(self): self.set_shown(settings.show_boundaries) def set_points_list(self, points): self.points = points def create_instance(self): self.vertexData = GeomVertexData('vertexData', GeomVertexFormat.getV3c4(), Geom.UHStatic) self.vertexWriter = GeomVertexWriter(self.vertexData, 'vertex') self.colorwriter = GeomVertexWriter(self.vertexData, 'color') for point in self.points: position = point.project(0, self.context.observer.camera_global_pos, self.context.observer.infinity) self.vertexWriter.addData3f(*position) self.colorwriter.addData4f(*self.color) self.lines = GeomLines(Geom.UHStatic) index = 0 for i in range(len(self.points) - 1): self.lines.addVertex(index) self.lines.addVertex(index + 1) self.lines.closePrimitive() index += 1 self.geom = Geom(self.vertexData) self.geom.addPrimitive(self.lines) self.node = GeomNode("boundary") self.node.addGeom(self.geom) self.instance = NodePath(self.node) self.instance.setRenderModeThickness(settings.boundary_thickness) self.instance.reparentTo(self.context.annotation) self.instance.setBin('background', settings.boundaries_depth) self.instance.set_depth_write(False)
class Orbit(VisibleObject): ignore_light = True default_shown = False selected_color = LColor(1.0, 0.0, 0.0, 1.0) def __init__(self, body): VisibleObject.__init__(self, body.get_ascii_name() + '-orbit') self.body = body self.nbOfPoints = 360 self.orbit = self.find_orbit(self.body) self.color = None self.fade = 0.0 if not self.orbit: print("No orbit for", self.get_name()) self.visible = False self.check_settings() def check_settings(self): if self.body.body_class is None: print("No class for", self.body.get_name()) return self.set_shown(settings.show_orbits and bodyClasses.get_show_orbit(self.body.body_class)) def find_orbit(self, body): if body != None: if not isinstance(body.orbit, FixedOrbit): return body.orbit else: return None, None else: return None, None def set_selected(self, selected): if selected: self.color = self.selected_color else: self.color = self.parent.get_orbit_color() if self.instance: self.instance.setColor(self.color * self.fade) def create_instance(self): if not self.orbit: return self.vertexData = GeomVertexData('vertexData', GeomVertexFormat.getV3(), Geom.UHStatic) self.vertexWriter = GeomVertexWriter(self.vertexData, 'vertex') delta = self.body.parent.get_local_position() for i in range(self.nbOfPoints): time = self.orbit.period / self.nbOfPoints * i pos = self.orbit.get_position_at(time) rot = self.orbit.get_rotation_at(time) pos = self.orbit.frame.get_local_position(rot.xform(pos)) - delta self.vertexWriter.addData3f(*pos) self.lines = GeomLines(Geom.UHStatic) for i in range(self.nbOfPoints - 1): self.lines.addVertex(i) self.lines.addVertex(i + 1) self.lines.closePrimitive() self.lines.addVertex(self.nbOfPoints - 1) self.lines.addVertex(0) self.lines.closePrimitive() self.geom = Geom(self.vertexData) self.geom.addPrimitive(self.lines) self.node = GeomNode(self.body.get_ascii_name() + '-orbit') self.node.addGeom(self.geom) self.instance = NodePath(self.node) self.instance.setRenderModeThickness(settings.orbit_thickness) self.instance.setCollideMask(GeomNode.getDefaultCollideMask()) self.instance.node().setPythonTag('owner', self) self.instance.reparentTo(self.context.annotation_shader) if self.color is None: self.color = self.parent.get_orbit_color() self.instance.setColor(self.color * self.fade) self.instance.setAntialias(AntialiasAttrib.MMultisample) self.appearance = ModelAppearance(attribute_color=True) if settings.use_inv_scaling: vertex_control = LargeObjectVertexControl() else: vertex_control = None self.instance_ready = True self.shader = BasicShader(lighting_model=FlatLightingModel(), vertex_control=vertex_control) self.shader.apply(self, self.appearance) self.shader.update(self, self.appearance) def check_visibility(self, pixel_size): if self.parent.shown and self.orbit: distance_to_obs = self.parent.distance_to_obs if distance_to_obs > 0.0: size = self.orbit.get_apparent_radius() / (distance_to_obs * pixel_size) else: size = 0.0 self.visible = size > settings.orbit_fade self.fade = min( 1.0, max(0.0, (size - settings.orbit_fade) / settings.orbit_fade)) if self.color is not None and self.instance is not None: self.instance.setColor(self.color * self.fade) else: self.visible = False def update_instance(self, camera_pos, orientation): if self.instance: self.place_instance_params(self.instance, self.body.parent.scene_position, self.body.parent.scene_scale_factor, LQuaternion()) self.shader.update(self, self.appearance)
class Asterism(VisibleObject): def __init__(self, name): VisibleObject.__init__(self, name) self.visible = True self.color = bodyClasses.get_orbit_color('constellation') self.position = LPoint3d(0, 0, 0) self.segments = [] self.position = None def check_settings(self): self.set_shown(settings.show_asterisms) def set_segments_list(self, segments): self.segments = segments ra_sin = 0 ra_cos = 0 decl = 0 if len(self.segments) > 0 and len(self.segments[0]) > 0: for star in self.segments[0]: asc = star.orbit.get_right_asc() ra_sin += sin(asc) ra_cos += cos(asc) decl += star.orbit.get_declination() ra = atan2(ra_sin, ra_cos) decl /= len(self.segments[0]) self.position = InfinitePosition(right_asc=ra, right_asc_unit=units.Rad, declination=decl, declination_unit=units.Rad) def create_instance(self): self.vertexData = GeomVertexData('vertexData', GeomVertexFormat.getV3c4(), Geom.UHStatic) self.vertexWriter = GeomVertexWriter(self.vertexData, 'vertex') self.colorwriter = GeomVertexWriter(self.vertexData, 'color') #TODO: Ugly hack to calculate star position from the sun... old_cam_pos = self.context.observer.camera_global_pos self.context.observer.camera_global_pos = LPoint3d() center = LPoint3d() for segment in self.segments: if len(segment) < 2: continue for star in segment: #TODO: Temporary workaround to have star pos star.update(0) star.update_obs(self.context.observer) position, distance, scale_factor = self.get_real_pos_rel( star.rel_position, star.distance_to_obs, star.vector_to_obs) self.vertexWriter.addData3f(*position) self.colorwriter.addData4f(*self.color) self.context.observer.camera_global_pos = old_cam_pos self.lines = GeomLines(Geom.UHStatic) index = 0 for segment in self.segments: if len(segment) < 2: continue for i in range(len(segment) - 1): self.lines.addVertex(index) self.lines.addVertex(index + 1) self.lines.closePrimitive() index += 1 index += 1 self.geom = Geom(self.vertexData) self.geom.addPrimitive(self.lines) self.node = GeomNode("asterism") self.node.addGeom(self.geom) self.instance = NodePath(self.node) self.instance.setRenderModeThickness(settings.asterism_thickness) self.instance.reparentTo(self.context.annotation) self.instance.setBin('background', settings.asterisms_depth) self.instance.set_depth_write(False)
class Grid(VisibleObject): ignore_light = True default_shown = False def __init__(self, name, orientation, color): VisibleObject.__init__(self, name) self.visible = True self.nbOfPoints = 360 self.nbOfRings = 17 self.nbOfSectors = 24 self.points_to_remove = (self.nbOfPoints // (self.nbOfRings + 1)) // 2 self.orientation = orientation self.color = color def create_instance(self): self.vertexData = GeomVertexData('vertexData', GeomVertexFormat.getV3c4(), Geom.UHStatic) self.vertexWriter = GeomVertexWriter(self.vertexData, 'vertex') self.colorwriter = GeomVertexWriter(self.vertexData, 'color') for r in range(1, self.nbOfRings + 1): for i in range(self.nbOfPoints): angle = 2 * pi / self.nbOfPoints * i x = cos(angle) * sin(pi * r / (self.nbOfRings + 1)) y = sin(angle) * sin(pi * r / (self.nbOfRings + 1)) z = sin(-pi / 2 + pi * r / (self.nbOfRings + 1)) self.vertexWriter.addData3f( (self.context.observer.infinity * x, self.context.observer.infinity * y, self.context.observer.infinity * z)) if r == self.nbOfRings / 2 + 1: self.colorwriter.addData4f(self.color.x * 1.5, 0, 0, 1) else: self.colorwriter.addData4f(*self.color) for s in range(self.nbOfSectors): for i in range(self.points_to_remove, self.nbOfPoints // 2 - self.points_to_remove + 1): angle = 2 * pi / self.nbOfPoints * i x = cos(2 * pi * s / self.nbOfSectors) * sin(angle) y = sin(2 * pi * s / self.nbOfSectors) * sin(angle) z = cos(angle) self.vertexWriter.addData3f( (self.context.observer.infinity * x, self.context.observer.infinity * y, self.context.observer.infinity * z)) if s == 0: self.colorwriter.addData4f(self.color.x * 1.5, 0, 0, 1) else: self.colorwriter.addData4f(*self.color) self.lines = GeomLines(Geom.UHStatic) index = 0 for r in range(self.nbOfRings): for i in range(self.nbOfPoints - 1): self.lines.addVertex(index) self.lines.addVertex(index + 1) self.lines.closePrimitive() index += 1 self.lines.addVertex(index) self.lines.addVertex(index - self.nbOfPoints + 1) self.lines.closePrimitive() index += 1 for r in range(self.nbOfSectors): for i in range(self.nbOfPoints // 2 - self.points_to_remove * 2): self.lines.addVertex(index) self.lines.addVertex(index + 1) self.lines.closePrimitive() index += 1 index += 1 self.geom = Geom(self.vertexData) self.geom.addPrimitive(self.lines) self.node = GeomNode("grid") self.node.addGeom(self.geom) self.instance = NodePath(self.node) self.instance.setRenderModeThickness(settings.grid_thickness) #myMaterial = Material() #myMaterial.setEmission((1.0, 1.0, 1.0, 1)) #self.instance.setMaterial(myMaterial) self.instance.reparentTo(self.context.annotation) self.instance.setQuat(LQuaternion(*self.orientation)) def set_orientation(self, orientation): self.orientation = orientation if self.instance: self.instance.setQuat(LQuaternion(*self.orientation))
class Planetimpl(): def __init__(self, world, size, distance, ratio, description, rotation, translation): self.worldOrigin = world self.size = size self.distance = distance self.renderRatio = ratio self.description = description self.rotation = rotation self.translation = translation def impl(self): # Load the Moon model self.planet = loader.loadModel("models/planet_sphere") self.chooseTexture("models/"+self.description+"_1k_tex.jpg") self.planet.reparentTo(self.worldOrigin) self.planet.setScale(self.size * self.renderRatio) self.planet.setPos(self.distance * self.renderRatio, 0.0, 0.0) self.planet.setTag('targetSize', str(self.size)) self.planet.setTag('isPickable', '2') self.startstop = True return self.planet def chooseTexture(self, name): """ Methode zum Setzen der Ursprungstextur """ self.planet.setTexture(loader.loadTexture(name), 1) def line(self): # Create and populate the Moon orbit model using Vertices and Lines self.planetOrbitVertexData = GeomVertexData(self.description+'OrbitVertexData', GeomVertexFormat.getV3(), Geom.UHDynamic) self.planetOrbitVertexWriter = GeomVertexWriter(self.planetOrbitVertexData, 'vertex') self.planetOrbitNumberPoints = 360 for i in range(self.planetOrbitNumberPoints): angleDegrees = i * 360 / self.planetOrbitNumberPoints angleRadians = angleDegrees * (pi / 180.0) x = -self.distance * sin(angleRadians) y = self.distance * cos(angleRadians) self.planetOrbitVertexWriter.addData3f(x, y, 0.0) self.planetOrbitLines = GeomLines(Geom.UHStatic) for i in range(self.planetOrbitNumberPoints-1): self.planetOrbitLines.addVertex(i) self.planetOrbitLines.addVertex(i+1) self.planetOrbitLines.closePrimitive() self.planetOrbitLines.addVertex(self.planetOrbitNumberPoints-1) self.planetOrbitLines.addVertex(0) self.planetOrbitLines.closePrimitive() self.planetOrbitGeom = Geom(self.planetOrbitVertexData) self.planetOrbitGeom.addPrimitive(self.planetOrbitLines) self.planetOrbitNode = GeomNode(self.description+'OrbitNode') self.planetOrbitNode.addGeom(self.planetOrbitGeom) self.planetOrbitNnodePath = render.attachNewNode(self.planetOrbitNode) self.planetOrbitNnodePath.reparentTo(self.worldOrigin) return self.planetOrbitVertexWriter def setstartstop(self): self.startstop = not self.startstop return self.startstop def rotatePlanet(self, task): # Compute earth rotation frameTime = globalClock.getFrameTime() angleDegrees = frameTime * self.rotation self.planet.setHpr(angleDegrees, 0, 0) # End task if self.startstop: return Task.cont else: return Task.done def translatePlanet(self, task): # Compute Moon position relative to Earth with circular orbit frameTime = globalClock.getFrameTime() angleDegrees = frameTime * self.translation angleRadians = angleDegrees * (pi / 180.0) # Compute the Moon's position with respect to the Earth x = -self.distance * self.renderRatio * sin(angleRadians) y = self.distance * self.renderRatio * cos(angleRadians) # Set the position on the model self.planet.setPos(x, y, 0.0) # Also rotate the orbit to follow the Moon and eliminate jitter effect self.planetOrbitVertexWriter.setRow(0) for i in range(self.planetOrbitNumberPoints): angleDegrees = angleDegrees + 360.0 / self.planetOrbitNumberPoints angleRadians = angleDegrees * (pi / 180.0) x = -self.distance * self.renderRatio * sin(angleRadians) y = self.distance * self.renderRatio * cos(angleRadians) self.planetOrbitVertexWriter.setData3f(x, y, 0.0) # End task if self.startstop: return Task.cont else: return Task.done
class Orbit(VisibleObject): ignore_light = True default_shown = False selected_color = LColor(1.0, 0.0, 0.0, 1.0) appearance = None shader = None def __init__(self, body): VisibleObject.__init__(self, body.get_ascii_name() + '-orbit') self.body = body self.owner = body self.nbOfPoints = 360 self.orbit = self.find_orbit(self.body) self.color = None self.fade = 0.0 if not self.orbit: print("No orbit for", self.get_name()) self.visible = False def get_oid_color(self): if self.body is not None: return self.body.oid_color else: return LColor() @classmethod def create_shader(cls): cls.appearance = ModelAppearance(attribute_color=True) if settings.use_inv_scaling: vertex_control = LargeObjectVertexControl() else: vertex_control = None cls.shader = BasicShader(lighting_model=FlatLightingModel(), vertex_control=vertex_control) def check_settings(self): if self.body.body_class is None: print("No class for", self.body.get_name()) return self.set_shown(settings.show_orbits and bodyClasses.get_show_orbit(self.body.body_class)) def find_orbit(self, body): if body != None: if not isinstance(body.orbit, FixedOrbit): return body.orbit else: return None, None else: return None, None def set_selected(self, selected): if selected: self.color = self.selected_color else: self.color = self.parent.get_orbit_color() if self.instance: self.instance.setColor(srgb_to_linear(self.color * self.fade)) def create_instance(self): self.vertexData = GeomVertexData('vertexData', GeomVertexFormat.getV3(), Geom.UHStatic) self.vertexWriter = GeomVertexWriter(self.vertexData, 'vertex') delta = self.body.parent.get_local_position() if self.orbit.is_periodic(): epoch = self.context.time.time_full - self.orbit.period / 2 step = self.orbit.period / (self.nbOfPoints - 1) else: #TODO: Properly calculate orbit start and end time epoch = self.orbit.get_time_of_perihelion() - self.orbit.period * 5.0 step = self.orbit.period * 10.0 / (self.nbOfPoints - 1) for i in range(self.nbOfPoints): time = epoch + step * i pos = self.orbit.get_position_at(time) - delta self.vertexWriter.addData3f(*pos) self.lines = GeomLines(Geom.UHStatic) for i in range(self.nbOfPoints-1): self.lines.addVertex(i) self.lines.addVertex(i+1) if self.orbit.is_periodic() and self.orbit.is_closed(): self.lines.addVertex(self.nbOfPoints-1) self.lines.addVertex(0) self.geom = Geom(self.vertexData) self.geom.addPrimitive(self.lines) self.node = GeomNode(self.body.get_ascii_name() + '-orbit') self.node.addGeom(self.geom) self.instance = NodePath(self.node) self.instance.setRenderModeThickness(settings.orbit_thickness) self.instance.setCollideMask(GeomNode.getDefaultCollideMask()) self.instance.node().setPythonTag('owner', self) self.instance.reparentTo(self.context.annotation) if self.color is None: self.color = self.parent.get_orbit_color() self.instance.setColor(srgb_to_linear(self.color * self.fade)) self.instance_ready = True if self.shader is None: self.create_shader() self.shader.apply(self, self.appearance) self.shader.update(self, self.appearance) def update_geom(self): geom = self.node.modify_geom(0) vdata = geom.modify_vertex_data() vwriter = GeomVertexRewriter(vdata, InternalName.get_vertex()) #TODO: refactor with above code !!! delta = self.body.parent.get_local_position() if self.orbit.is_periodic(): epoch = self.context.time.time_full - self.orbit.period step = self.orbit.period / (self.nbOfPoints - 1) else: #TODO: Properly calculate orbit start and end time epoch = self.orbit.get_time_of_perihelion() - self.orbit.period * 5.0 step = self.orbit.period * 10.0 / (self.nbOfPoints - 1) for i in range(self.nbOfPoints): time = epoch + step * i pos = self.orbit.get_position_at(time) - delta vwriter.setData3f(*pos) def check_visibility(self, pixel_size): if self.parent.parent.visible and self.parent.shown and self.orbit: distance_to_obs = self.parent.distance_to_obs if distance_to_obs > 0.0: size = self.orbit.get_apparent_radius() / (distance_to_obs * pixel_size) else: size = 0.0 self.visible = size > settings.orbit_fade self.fade = min(1.0, max(0.0, (size - settings.orbit_fade) / settings.orbit_fade)) if self.color is not None and self.instance is not None: self.instance.setColor(srgb_to_linear(self.color * self.fade)) else: self.visible = False def update_instance(self, camera_pos, camera_rot): if self.instance: self.place_instance_params(self.instance, self.body.parent.scene_position, self.body.parent.scene_scale_factor, LQuaternion()) self.shader.update(self, self.appearance) def update_user_parameters(self): if self.instance is not None: self.update_geom()
def _build_grid(self): color = getattr(self.parameters, "color", (0, 0, 0, 0)) node = NodePath(self.identifier) sx = self.grid.maxx - self.grid.minx + 1 sy = self.grid.maxy - self.grid.miny + 1 # 1. the squares squares = {} card = CardMaker('') cardgeom = NodePath(card.generate()) for n in range(sx): for nn in range(sy): square = NodePath(self.identifier + '-square-%d-%d' % (n + 1, nn + 1)) cardgeom.instanceTo(square) square.setPos(float(n) / sx, 0, -float(nn + 1) / sy) square.setScale(1.0 / sx, 1, 1.0 / sy) square.setColor(0, 0, 0, 1) square.reparentTo(node) squares[n, nn] = square #2: the lines gnode = GeomNode(self.identifier + "-lines") vformat = GeomVertexFormat.getV3cp() vdata = GeomVertexData(self.identifier + '-lines', vformat, Geom.UHStatic) v_vertex = GeomVertexWriter(vdata, 'vertex') v_colors = GeomVertexWriter(vdata, 'color') for n in range(sx + 1): px = float(n) / sx v_vertex.addData3f(px, 0.0, 0.0) v_colors.addData4f(*color) v_vertex.addData3f(px, 0, -1) v_colors.addData4f(*color) for n in range(sy + 1): py = float(n) / sy v_vertex.addData3f(0.0, 0.0, -py) v_colors.addData4f(*color) v_vertex.addData3f(1.0, 0, -py) v_colors.addData4f(*color) geom = Geom(vdata) prim = GeomLines(Geom.UHStatic) for n in range(sx + 1): prim.addVertex(2 * n) prim.addVertex(2 * n + 1) for n in range(sy + 1): prim.addVertex(2 * (sx + n + 1)) prim.addVertex(2 * (sx + n + 1) + 1) prim.closePrimitive() geom.addPrimitive(prim) gnode.addGeom(geom) node1 = NodePath(gnode) node1.reparentTo(node) self.node, self.squares, self.sx, self.sy = node, squares, sx, sy self.node.reparentTo(self.parentnode)