Last active
August 29, 2015 14:25
-
-
Save ashumeow/ccd95e08a1ab1c407a01 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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