Skip to content

@substack /mars.py
Created

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
virtual mars discovery lab pyscene code
import pyscene
scene = pyscene.pyscene()
import osg, osgDB
import math, re, os
scene.setScale(5e4, 0.5)
scene.viewer.getCamera().setClearColor(osg.Vec4f(0, 0, 0, 0))
mars = scene.readNodeFile("mars.osg")
# make the north pole face up instead of down
mars_trans = osg.MatrixTransform()
mars_trans.postMult(
osg.Matrixd.rotate( math.radians(180), 1, 0, 0 )
)
# and position the planet with the meridian facing the camera
mars_trans.postMult(
osg.Matrixd.rotate( math.radians(180), 0, 0, 1 )
)
mars_trans.addChild(mars)
# make it blend (http://www.palomino3d.org/pal/openscenegraph/)
GL_BLEND=3042
GL_DEPTH_TEST=2929
GL_LIGHTING=2896
trans_state = osg.StateSet()
trans_state.setMode(GL_BLEND, osg.StateAttribute.ON)
trans_state.setRenderingHint(osg.StateSet.TRANSPARENT_BIN)
trans_state.setMode(GL_DEPTH_TEST, osg.StateAttribute.OFF)
trans_state.setMode(GL_LIGHTING, osg.StateAttribute.OFF)
trans = 0.15
for radius in 6.4, 6.45, 6.5, 6.6, 6.7, 6.75 :
trans /= 1.5
atmo = osg.Sphere( osg.Vec3f(0, 0, 0), radius * 1e6 )
atmo_drawable = osg.ShapeDrawable(atmo)
atmo_drawable.setColor( osg.Vec4f(0.76, 0.54, 0.37, trans) )
atmo_geode = osg.Geode()
atmo_geode.addDrawable(atmo_drawable)
atmo_drawable.setStateSet(trans_state)
mars_trans.addChild(atmo_geode)
scene.addChild(mars_trans)
def plot_coord(lat, lon, image=None, flag=None) :
"""
Plot a coordinate on the globe with a pin and a billboard
that changes its opacity based on the viewer's location
"""
geode = osg.Geode()
cone = osg.Cone( osg.Vec3f(0, 0, 6.7e6), 3e4, -0.3e6 )
cone_drawable = osg.ShapeDrawable(cone)
cone_drawable.setColor( osg.Vec4f(1, 0, 0, 1) )
geode.addDrawable(cone_drawable)
sphere = osg.Sphere( osg.Vec3f(0, 0, 6.775e6), 3e4 )
sphere_drawable = osg.ShapeDrawable(sphere)
sphere_drawable.setColor( osg.Vec4f(1, 0, 0, 0.5) )
geode.addDrawable(sphere_drawable)
# Use negative dimensions on the Box to trick out plane-like behaviour
board = osg.Box( osg.Vec3f(0, 0, 7.2e6), -5e5 * 1.6, -1e3, 5e5 )
board_drawable = osg.ShapeDrawable(board)
bb = osg.Billboard()
bb.setNormal( osg.Vec3f(0, 1, 0) )
bb.addDrawable(board_drawable)
texture = osg.Texture2D()
if isinstance(image, str) :
im = osgDB.readImageFile(image)
texture.setImage(im)
state = osg.StateSet(trans_state)
bb.setStateSet(state)
depth = osg.Depth()
depth.setWriteMask(True)
state.setAttributeAndModes(depth, osg.StateAttribute.ON)
state.setTextureAttributeAndModes(0, texture, osg.StateAttribute.ON)
pin_trans = osg.MatrixTransform()
pin_trans.addChild(geode)
pin_trans.addChild(bb)
pin_trans.postMult(
osg.Matrixd.rotate( math.radians(90.0 + lat), 1, 0, 0 )
)
pin_trans.postMult(
osg.Matrixd.rotate( math.radians(lon - 90.0), 0, 0, 1 )
)
position = pin_trans.getMatrix() * osg.Vec3d(0, 0, 7.2e6)
flag_drawable = None
if isinstance(flag, str) :
flag_im = osgDB.readImageFile(flag)
flag_texture = osg.Texture2D()
flag_texture.setImage(flag_im)
flag_board = osg.Box(
osg.Vec3f(
-683.0 / 2 * 5e5 / 512,
1e3,
7.2e6 + (512.0 - 50.0 - 20.0) / 2 * 5.0e5 / 512,
),
-100.0 * 5.0e5 / 512,
-1e3,
50.0 * 5.0e5 / 512,
)
flag_drawable = osg.ShapeDrawable(flag_board)
flag_bb = osg.Billboard()
flag_bb.setNormal( osg.Vec3f(0, 1, 0) )
flag_bb.addDrawable(flag_drawable)
flag_state = osg.StateSet(trans_state)
flag_bb.setStateSet(flag_state)
flag_state.setAttributeAndModes(depth, osg.StateAttribute.ON)
flag_state.setTextureAttributeAndModes(
0, flag_texture, osg.StateAttribute.ON
)
pin_trans.addChild(flag_bb)
return {
"board_drawable" : board_drawable,
"flag_drawable" : flag_drawable,
"position" : position,
"trans" : pin_trans,
}
labels = {
"Olympus Mons" : plot_coord(
18.4, -134, "images/olympus_mons.png",
),
"Arsia Mons" : plot_coord(
-9.5, -120.5, "images/arsia_mons.png"
),
"Ascraeus Mons" : plot_coord(
11.3, -104.5, "images/ascraeus_mons.png"
),
"Pavonis Mons" : plot_coord(
0.8, -113.4, "images/pavonis_mons.png"
),
"Cydonia Mensae" : plot_coord(
40.7, -170.2, "images/cydonia_mensae.png"
),
"Phoenix Lander" : plot_coord(
68, 234, "images/phoenix_lander.png", "images/usa.png",
),
"Spirit Rover" : plot_coord(
-14.6, 175.5, "images/spirit_rover.png", "images/usa.png",
),
"Opportunity Rover" : plot_coord(
-1.9, 354.5, "images/opportunity_rover.png", "images/usa.png",
),
"Sojourner Rover" : plot_coord(
19.1, -33.2, "images/sojourner_rover.png", "images/usa.png",
),
"Viking 1 Lander" : plot_coord(
22.7, -48.2, "images/viking_1_lander.png", "images/usa.png",
),
"Viking 2 Lander" : plot_coord(
48.3, -226.0, "images/viking_2_lander.png", "images/usa.png",
),
"Mars 2 Lander" : plot_coord(
4, -47, "images/mars_2_lander.png", "images/ussr.png",
),
"Mars 3 Lander" : plot_coord(
-45, -158, "images/mars_3_lander.png", "images/ussr.png",
),
}
for value in labels.itervalues() :
mars_trans.addChild(value["trans"])
scene.setLighting(False)
def label_proximity(self, nv, node) :
for (key, value) in labels.iteritems() :
d = (
osg.Matrixd.inverse( mars_trans.getMatrix() ) * value["position"]
-
self.getPosition()
).length()
if d > 2e7 : d = 0
else : d = (1 - d / 2e7) ** 2 * 3
color = osg.Vec4f(1, 1, 1, d)
labels[key]["board_drawable"].setColor(color)
if labels[key]["flag_drawable"] :
labels[key]["flag_drawable"].setColor(color)
scene.addCallback(label_proximity)
scene.planet_velocity = osg.Matrixd()
def spin_planet(self, nv, node) :
mars_trans.postMult(scene.planet_velocity)
scene.addCallback(spin_planet)
def button_handler(self, event) :
if event["mode"] != "button" :
return
r = osg.Matrixd.inverse(
osg.Matrixd.rotate(
self.getViewMatrix().getRotate()
)
)
if event["data"][0] == 9 :
scene.planet_velocity = osg.Matrixd()
elif event["data"][1] == "released" and event["data"][0] in range(4) :
scene.planet_velocity = osg.Matrixd()
elif event["data"][0] in [ 0, 4 ] :
scene.planet_velocity = osg.Matrixd.rotate(
math.radians(0.1), r * osg.Vec3d(0, 1, 0)
)
elif event["data"][0] == 1 :
scene.planet_velocity = osg.Matrixd.rotate(
math.radians(0.1), r * osg.Vec3d(1, 0, 0)
)
elif event["data"][0] in [ 2, 5 ] :
scene.planet_velocity = osg.Matrixd.rotate(
math.radians(0.1), r * osg.Vec3d(0, -1, 0)
)
elif event["data"][0] == 3 :
scene.planet_velocity = osg.Matrixd.rotate(
math.radians(0.1), r * osg.Vec3d(-1, 0, 0)
)
scene.add_vrpn_handler("mars_buttons", button_handler)
scene.postMult( osg.Matrixd.translate(0, 0, 3e7) )
scene.ds.setEyeSeparation(0.001)
coordinates = [
(-6.209900, -99.394042, 0),
(-6.642782, -92.307128, 0),
(-7.079088, -84.440917, 0),
(-8.537565, -77.255859, 0),
(-10.639013, -70.620117, 0),
(-13.304102, -60.644531, 0),
(-14.753635, -56.381835, 0),
(-15.199386, -50.009765, 0),
(-13.432366, -41.352539, 0),
(-5.244127, -36.079101, 0),
(2.591888, -33.156738, 0),
]
def build_links(n=0) :
if not coordinates[n:] : return None
lat, lon, elev = coordinates[n]
point_trans = osg.MatrixTransform()
point_trans.postMult(
osg.Matrixd.translate(0, 0, 7e6 + elev)
)
point_trans.postMult(
osg.Matrixd.rotate( math.radians(90.0 + lat), 1, 0, 0 )
)
point_trans.postMult(
osg.Matrixd.rotate( math.radians(lon - 90.0), 0, 0, 1 )
)
sphere = osg.Sphere(osg.Vec3f(), 5e4)
drawable = osg.ShapeDrawable(sphere)
drawable.setColor( osg.Vec4f(0.76, 0.54, 0.37, 0.5) )
geode = osg.Geode()
geode.addDrawable(drawable)
point_trans.addChild(geode)
mars_trans.addChild(point_trans)
m = point_trans.getMatrix().getTrans()
point = osg.Vec3f(m[0], m[1], m[2])
return {
"geode" : geode,
"drawable" : drawable,
"bound" : osg.BoundingSphere(point, 5e5),
"next" : build_links(n+1),
}
scene.links = build_links()
scene.link = scene.links
def link_path(self, nv, node) :
v = osg.Matrixd.inverse( mars_trans.getMatrix() ) * self.getPosition()
v = osg.Vec3f(v[0], v[1], v[2])
if self.link["bound"].contains(v) :
print "bound"
self.link["drawable"].setColor( osg.Vec4f(0.8, 0.2, 0.2, 0.5) )
self.link = self.link["next"]
if not self.link :
print "none"
self.link = self.links
return
c = self.link["bound"].center()
p = self.getPosition()
velocity = osg.Vec3f(p[0], p[1], p[2]) - c
#velocity = v - c
velocity = osg.Vec3d(
velocity[0] / 5e2,
velocity[1] / 5e2,
velocity[2] / -5e2,
)
self.velocity = osg.Matrixd.translate(velocity)
#self.getPosition() - osg.Vec3d(c[0], c[1], c[2])
scene.addCallback(link_path)
scene.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.