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 test_ref(): o = OctreeNode(0, LPoint3d(0, 2, 0), 1, 1) for i in range(75): leaf = OctreeLeaf("leaf", LPoint3d(), 0, 0) o.add(leaf) leaf_child = OctreeLeaf("child", LPoint3d(), 2, 0) o.add(leaf_child) assert o.get_num_leaves() == 75 assert o.get_num_children() == 1
def test_one_leaf(): o = OctreeNode(66, LPoint3d(1, 2, 3), 77, 88, 99) leaf = OctreeLeaf("leaf", LPoint3d(), 0, 0) o.add(leaf) assert o.level == 66 assert o.center == LPoint3d(1, 2, 3) assert o.width == 77 assert o.threshold == 88 assert o.index == 99 assert o.get_num_children() == 0 assert o.get_num_leaves() == 1
def __init__(self, cam, lens): CameraBase.__init__(self, cam, lens) #Global position of the camera, i.e. the center of the current system self.camera_global_pos = LPoint3d() #Local position of the camera within the system in the current camera reference frame #Initialize not at zero to avoid null vector when starting to move self.camera_pos = LPoint3d(0, -1, 0) #Camera orientation in the current camera reference frame self.camera_rot = LQuaterniond() #Camera reference frame self.camera_frame = AbsoluteReferenceFrame() #Direction of sight of the camera self.camera_vector = LVector3d.forward()
def test_ref_2(): o = OctreeNode(0, LPoint3d(0, 2, 0), 1, 1) for i in range(75): leaf = OctreeLeaf("leaf", LPoint3d(0, -2, 0), 0, 0) o.add(leaf) leaf_child = OctreeLeaf("child", LPoint3d(0, 2, 0), 2, 0) o.add(leaf_child) assert o.get_num_leaves() == 75 assert o.get_num_children() == 1 f = create_frustum() for i in range(100): t = VisibleObjectsTraverser(f, 6.0, 1) o.traverse(t) assert t.get_leaves() == (leaf_child, )
def decode(self, data): name = data.get('name') radius = data.get('radius', 10) radius_units = data.get('radius-units', units.m) radius *= radius_units camera_distance = data.get('camera-distance', None) camera_pos = data.get('camera-position', None) camera_pos_units = data.get('camera-position-units', units.m) camera_rot_data = data.get('camera-rotation', None) if camera_rot_data is not None: if len(camera_rot_data) == 3: camera_rot = LQuaterniond() camera_rot.set_hpr(LVector3d(*camera_rot_data)) else: camera_rot = LQuaterniond(*camera_rot_data) else: camera_rot = LQuaterniond() shape = data.get('shape') appearance = data.get('appearance') lighting_model = data.get('lighting-model') shape, extra = ShapeYamlParser.decode(shape) if appearance is None: if isinstance(shape, MeshShape): appearance = 'model' else: appearance = 'textures' appearance = AppearanceYamlParser.decode(appearance) lighting_model = LightingModelYamlParser.decode( lighting_model, appearance) shader = BasicShader( lighting_model=lighting_model, use_model_texcoord=not extra.get('create-uv', False)) ship_object = ShapeObject('ship', shape=shape, appearance=appearance, shader=shader) if camera_distance is None: if camera_pos is None: camera_distance = 5.0 camera_pos = LPoint3d(0, -camera_distance * radius, 0) else: camera_pos = LPoint3d(*camera_pos) * camera_pos_units camera_distance = camera_pos.length() / radius else: camera_pos = LPoint3d(0, -camera_distance * radius, 0) ship = VisibleShip(name, ship_object, radius) ship.set_camera_hints(camera_distance, camera_pos, camera_rot) for mode in self.camera_modes: ship.add_camera_mode(mode) self.app.add_ship(ship)
def show_cell(self, cell): print(cell.center, cell.width) position = cell.center - self.context.observer.get_position() self.octree_points.add_point_scale(position, LColor(1, 1, 1, 1), 5) self.octree_points.add_point_scale( position + LPoint3d(-cell.width, -cell.width, -cell.width), LColor(1, 0, 1, 1), 5) self.octree_points.add_point_scale( position + LPoint3d(cell.width, -cell.width, -cell.width), LColor(1, 0, 1, 1), 5) self.octree_points.add_point_scale( position + LPoint3d(cell.width, -cell.width, cell.width), LColor(1, 0, 1, 1), 5) self.octree_points.add_point_scale( position + LPoint3d(-cell.width, -cell.width, cell.width), LColor(1, 0, 1, 1), 5) self.octree_points.add_point_scale( position + LPoint3d(cell.width, cell.width, -cell.width), LColor(1, 1, 0, 1), 5) self.octree_points.add_point_scale( position + LPoint3d(-cell.width, cell.width, -cell.width), LColor(0, 1, 0, 1), 5) self.octree_points.add_point_scale( position + LPoint3d(-cell.width, cell.width, cell.width), LColor(0, 1, 0, 1), 5) self.octree_points.add_point_scale( position + LPoint3d(cell.width, cell.width, cell.width), LColor(1, 1, 0, 1), 5)
def test_traverse_front(): o = OctreeNode(0, LPoint3d(), 0, 0) f = create_frustum() leaf_center = OctreeLeaf("center", LPoint3d(), 0, 0) leaf_front = OctreeLeaf("front", LPoint3d(0, 2, 0), 0, 0) leaf_back = OctreeLeaf("back", LPoint3d(0, -2, 0), 0, 0) o.add(leaf_center) o.add(leaf_front) o.add(leaf_back) t = VisibleObjectsTraverser(f, 6.0, 1) o.traverse(t) assert t.get_leaves() == (leaf_center, leaf_front) assert leaf_center.get_update_id() == 1 assert leaf_front.get_update_id() == 1 assert leaf_back.get_update_id() == 0
def add_in_child(self, obj, position, magnitude): index = 0 if position.x >= self.center.x: index |= 1 if position.y >= self.center.y: index |= 2 if position.z >= self.center.z: index |= 4 if self.children[index] is None: child_offset = self.half_width / 2.0 child_center = LPoint3d(self.center) if (index & 1) != 0: child_center.x += child_offset else: child_center.x -= child_offset if (index & 2) != 0: child_center.y += child_offset else: child_center.y -= child_offset if (index & 4) != 0: child_center.z += child_offset else: child_center.z -= child_offset child = Octree(self.level + 1, child_center, self.half_width, self.child_threshold, index) self.children[index] = child Octree.nb_cells += 1 self.children[index].add(obj, position, magnitude)
def move(self, task): dt = globalClock.getDt() if self.trigger_check_settings: self.terrain.check_settings() self.trigger_check_settings = False control = self.nav.update(dt) ralph_height = self.get_height(self.ralph.getPos()) self.ralph.setZ(ralph_height) if not control: self.follow_cam.update() else: #TODO: Should have a FreeCam class for mouse orbit and this in update() self.cam.lookAt(self.floater) if self.shadow_caster is not None: vec = self.ralph.getPos() - self.cam.getPos() vec.set_z(0) dist = vec.length() vec.normalize() self.shadow_caster.set_pos(self.ralph.get_pos() - vec * dist + vec * self.ralph_config.shadow_size / 2) render.set_shader_input("camera", self.cam.get_pos()) self.vector_to_obs = base.cam.get_pos() self.vector_to_obs.normalize() self.distance_to_obs = self.cam.get_z() - self.get_height( self.cam.getPos()) self.scene_rel_position = -base.cam.get_pos() self.terrain.update_instance(LPoint3d(*self.cam.getPos()), None) return task.cont
def update_instance(self, camera_pos, orientation): body = self.parent if body.is_emissive() and (not body.resolved or isinstance(body, DeepSpaceObject)): if body.scene_position != None: self.instance.setPos(*body.scene_position) scale = abs(self.context.observer.pixel_size * body.get_label_size() * body.scene_distance) else: scale = 0.0 else: offset = body.get_apparent_radius() * 1.01 rel_front_pos = body.rel_position - orientation.xform(LPoint3d(0, offset, 0)) vector_to_obs = LVector3d(-rel_front_pos) distance_to_obs = vector_to_obs.length() vector_to_obs /= distance_to_obs position, distance, scale_factor = self.get_real_pos_rel(rel_front_pos, distance_to_obs, vector_to_obs) self.instance.setPos(*position) scale = abs(self.context.observer.pixel_size * body.get_label_size() * distance) color = body.get_label_color() * self.fade self.look_at.set_pos(LVector3(*(orientation.xform(LVector3d.forward())))) self.label_instance.look_at(self.look_at, LVector3(), LVector3(*(orientation.xform(LVector3d.up())))) color[3] = 1.0 self.label.setTextColor(color) if scale < 1e-7: print("Label too far", self.get_name()) scale = 1e-7 self.instance.setScale(scale)
class CelestialComponent(object): nodePath = None truePos = LPoint3d(0, 0, 0) mass = 0 soi = 0 kind = None orbit = {}
def getBodyPosition(self, entity, time): """Returns celestial position relative to the parent""" # Convert to radians M = radians(eval(entity.orbit['M'])(time)) w = radians(eval(entity.orbit['w'])(time)) i = radians(eval(entity.orbit['i'])(time)) N = radians(eval(entity.orbit['N'])(time)) a = entity.orbit['a'] e = eval(entity.orbit['e'])(time) # Compute eccentric anomaly E = M + e * sin(M) * (1.0 + e * cos(M)) if degrees(E) > 0.05: E = self.computeE(E, M, e) # http://stjarnhimlen.se/comp/tutorial.html # Compute distance and true anomaly xv = a * (cos(E) - e) yv = a * (sqrt(1.0 - e * e) * sin(E)) v = atan2(yv, xv) r = sqrt(xv * xv + yv * yv) xh = r * (cos(N) * cos(v + w) - sin(N) * sin(v + w) * cos(i)) yh = r * (sin(N) * cos(v + w) + cos(N) * sin(v + w) * cos(i)) zh = r * (sin(v + w) * sin(i)) position = LPoint3d(xh, yh, zh) # If we are not a moon then our orbits are done in au. # Our units in panda are km, so we convert to km # FIXME: Add moon body type if entity.kind != TYPES['moon']: position = position * 149598000 return position
def __init__(self, model, offset=None, rotation=None, scale=None, auto_scale_mesh=True, flatten=True, panda=False, attribution=None, context=defaultDirContext): Shape.__init__(self) self.model = model self.attribution = attribution self.context = context if offset is None: offset = LPoint3d() self.offset = offset if rotation is None: rotation = LQuaterniond() if scale is None and not auto_scale_mesh: scale = LVector3d(1, 1, 1) self.scale_factor = scale self.rotation = rotation self.auto_scale_mesh = auto_scale_mesh self.flatten = flatten self.panda = panda self.mesh = None self.callback = None self.cb_args = None
def __init__(self, period, semi_major_axis, eccentricity, frame): self.period = period self.mean_motion = 2 * pi / period self.max_distance = semi_major_axis * (1.0 + eccentricity) self.frame = frame self.origin = LPoint3d() self.body = None
def GenerateCollisionEgg(heightmap, output, input='data/collision3k.egg', scale=100.0): input_egg = EggData() input_egg.read(input) output_egg = EggData() output_egg.setCoordinateSystem(CS_default) output_egg.stealChildren(input_egg) VertexPool = output_egg.getChildren()[1] print("Generating mesh, this may take a while...", end="") for i in range(VertexPool.getHighestIndex()): if i%20000 == 0: try: base.graphicsEngine.renderFrame() print('.', end="") except: pass vert = VertexPool.getVertex(i) x0, y0, _ = vert.getPos3() #x, y = int(floor(x0+0.5)), int(floor(y0+0.5)) x, y = int(x0), int(y0) if x==512: x=511 elif x==0: x=1 if y==512: y=511 elif y==0: y=1 vert.setPos(LPoint3d(x0, y0, heightmap.getBright(x,512-y)*scale)) output_egg.writeEgg(output)
def __init__(self, context): StellarSystem.__init__(self, 'Universe', orbit=FixedOrbit(frame=AbsoluteReferenceFrame()), rotation=FixedRotation(frame=AbsoluteReferenceFrame()), description='Universe') self.visible = True self.octree_width = 100000.0 * units.Ly abs_mag = app_to_abs_mag(6.0, self.octree_width * Octree.coef) self.octree = Octree(0, LPoint3d(10 * units.Ly, 10 * units.Ly, 10 * units.Ly), self.octree_width, abs_mag) self.octree_cells = [] self.octree_old_cells = None self.octree_cells_to_clean = None self.update_id = 0 self.to_update = [] self.to_update_extra = [] self.nb_cells = 0 self.nb_leaves = 0 self.nb_leaves_in_cells = 0 self.dump_octree = False self.dump_octree_stats = False self.octree_points = PointsSet(use_sprites=False, use_sizes=False, points_size=20) self.octree_points.instance.reparentTo(self.context.annotation)
def get2DBodyPosition(self, component, time): """Returns celestial position relative to the parent""" # Convert to radians M = radians(eval(component.orbit['M'])(time)) w = radians(eval(component.orbit['w'])(time)) i = radians(eval(component.orbit['i'])(time)) N = radians(eval(component.orbit['N'])(time)) a = component.orbit['a'] e = eval(component.orbit['e'])(time) # Compute eccentric anomaly E = M + e * sin(M) * (1.0 + e * cos(M)) if degrees(E) > 0.05: E = self.computeE(E, M, e) # Compute distance and true anomaly xv = a * (cos(E) - e) yv = a * (sqrt(1.0 - e * e) * sin(E)) v = atan2(yv, xv) r = sqrt(xv * xv + yv * yv) xh = r * (cos(N) * cos(v + w) - sin(N) * sin(v + w) * cos(i)) yh = r * (sin(N) * cos(v + w) + cos(N) * sin(v + w) * cos(i)) position = LPoint3d(xh, yh, 0) # If we are not a moon then our orbits are done in au. # We need to convert to km # FIXME: Add moon body type if component.kind != TYPES['moon']: position = position * 149598000 return position
def set_altitude(self, altitude): pos = self.body.get_pos() distance = self.body.frame.body.get_height_under(pos) new_frame_pos = LPoint3d(self.body.get_frame_pos()) new_frame_pos[2] = distance + altitude self.body.set_frame_pos(new_frame_pos) self.altitude = altitude
def create_spiral_distance(self, count, radius, spread, zspread, points, colors, sizes): sprite_size = self.sprite_size arm_color = self.arms_color disk_color = self.bulge_color bulge_size = self.bulge_size() sersic_inv = 1. / self.sersic_disk distance = 0 for c in range(count * 2): r = sqrt(random() + bulge_size*bulge_size) theta = random() * 2 * pi x = r * cos(theta) y = r * sin(theta) z = gauss(0.0, zspread) coef = 0.0 for c in (0, 1.): arm_angle = self.inv_shape_func(r) * max(self.max_angle, 0.001) / (2 * pi) mtheta = c * pi + theta delta = abs(mtheta - arm_angle) for i in range(int(self.max_angle / (2 * pi)) + 1): delta = min(delta, abs(mtheta - arm_angle - (i + 1) * 2 * pi), abs(mtheta - arm_angle + (i + 1) * 2 * pi)) coef = max(pow(max(1 - delta / pi, 0.0), self.arm_spread), coef) point = LPoint3d(x * radius, y * radius, z * radius) points.append(point) distance = max(distance, point.length()) color = disk_color * (1 - coef) + arm_color * coef color = color * (1 - 0.9 * pow(r, sersic_inv)) color[3] = 1.0 colors.append(color) size = sprite_size + gauss(0, sprite_size) sizes.append(size) self.size = distance
def __init__(self, name): VisibleObject.__init__(self, name) self.camera_modes = [CameraController.FIXED] self.frame = AbsoluteReferenceFrame() self._frame_position = LPoint3d() self._frame_rotation = LQuaterniond() self._position = LPoint3d() self._global_position = LPoint3d() self._local_position = LPoint3d() self._orientation = LQuaterniond() self.camera_distance = 0.0 self.camera_pos = LPoint3d() self.camera_rot = LQuaterniond()
def spherical_to_frame_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 return rel_position
def decode(self, data, frame=None): position = LPoint3d(*data.get('position', [0, 0, 0])) position_units = DistanceUnitsYamlParser.decode( data.get('position-units', 'pc')) if data.get('frame') is not None or frame is None: frame = FrameYamlParser.decode(data.get('frame', 'J2000Ecliptic')) return FixedPosition(position=position * position_units, frame=frame)
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 get_position_at(self, time): mean_anomaly = (time - self.epoch) * self.mean_motion + self.mean_anomaly def kepler_func(x): return mean_anomaly + self.eccentricity * sin(x) - x def kepler_func_prime(x): return self.eccentricity * cos(x) - 1 def solve_fixed(f, x0, maxiter): x = 0 res = x0 for i in range(0, maxiter): x = res res = f(x) return res try: #eccentric_anomaly=solve_fixed(kepler_func, mean_anomaly, maxiter=5) eccentric_anomaly = newton(kepler_func, mean_anomaly, kepler_func_prime, maxiter=10) except RuntimeError: print("Could not converge", self.body.get_name()) eccentric_anomaly = mean_anomaly a = self.pericenter_distance / (1.0 - self.eccentricity) x = a * (cos(eccentric_anomaly) - self.eccentricity) y = a * sqrt(1 - self.eccentricity * self.eccentricity) * sin(eccentric_anomaly) return LPoint3d(x, y, 0.0)
def __init__(self, position=LPoint3d(0, 0, 0), rotation=LQuaterniond(), frame=None): Orbit.__init__(self, frame) self.position = position self.rotation = rotation
def test_empty(): o = OctreeNode(0, LPoint3d(), 0, 0) assert o.level == 0 assert o.center == LPoint3d() assert o.width == 0 assert o.threshold == 0 assert o.index == -1 assert o.get_num_children() == 0 assert o.get_num_leaves() == 0 o = OctreeNode(66, LPoint3d(1, 2, 3), 77, 88, 99) assert o.level == 66 assert o.center == LPoint3d(1, 2, 3) assert o.width == 77 assert o.threshold == 88 assert o.index == 99 assert o.get_num_children() == 0 assert o.get_num_leaves() == 0
def getTruePos(self, debug=False): '''Returns the "true" position of this object''' if debug: print self.nodePath.getName( ), self.zoney * physics.ZONESIZE, self.nodePath.getY( ), self.zoney * physics.ZONESIZE + self.nodePath.getY() return LPoint3d(self.zonex * physics.ZONESIZE + self.nodePath.getX(), self.zoney * physics.ZONESIZE + self.nodePath.getY(), self.nodePath.getZ())
def DisplacementUVSphere(radius, heightmap, scale, rings=5, sectors=5, inv_texture_u=False, inv_texture_v=True): data = EggData() pool = EggVertexPool('pool') vertices = [] data.addChild(pool) R = 1. / (rings) S = 1. / (sectors) for r in range(0, rings + 1): for s in range(0, sectors + 1): cos_s = cos(2 * pi * s * S + pi) sin_s = sin(2 * pi * s * S + pi) sin_r = sin(pi * r * R) cos_r = cos(pi * r * R) x = cos_s * sin_r y = sin_s * sin_r z = cos_r vertex = EggVertex() u = s * S v = r * R height = radius + heightmap.get_height_uv(u, v) * scale vertex.setPos(LPoint3d(x * height, y * height, z * height)) if inv_texture_v: v = 1.0 - v if inv_texture_u: u = 1.0 - u vertex.setUv(LPoint2d(u, v)) pool.addVertex(vertex) vertices.append(vertex) index = 0 for r in range(0, rings): for s in range(0, sectors): poly = EggPolygon() data.addChild(poly) poly.addVertex(vertices[index + sectors + 1]) poly.addVertex(vertices[index]) poly.addVertex(vertices[index + sectors]) poly = EggPolygon() data.addChild(poly) poly.addVertex(vertices[index + sectors + 1]) poly.addVertex(vertices[index + 1]) poly.addVertex(vertices[index]) index += 1 data.removeUnusedVertices(True) data.recomputeVertexNormals(45) data.recomputeTangentBinormal(GlobPattern("")) node = loadEggData(data) path = NodePath(node) path.flattenStrong() return path
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