/* File: ScenePlanet.java University of Applied Science Berne,HTA-Biel/Bienne, Computer Science Department. Diploma thesis J3D Solar System Simulator Originally written by Marcel Portner & Bernhard Hari (c) 2000 CVS - Information : $Header: /var/cvsreps/projects/c450/2000/sss3d/source_diploma/sss3d/contentbranch/planets/ScenePlanet.java,v 1.18 2000/12/15 02:53:25 portm Exp $ $Author: portm $ $Date: 2000/12/15 02:53:25 $ $State: Exp $ */ package sss3d.contentbranch.planets; import sss3d.contentbranch.*; import sss3d.utils.SSS3dConstants; import sss3d.utils.observer.*; import sss3d.contentbranch.orbit.*; import sss3d.utils.xmlparser.XMLConstants; import javax.media.j3d.*; import javax.vecmath.*; import com.sun.j3d.utils.behaviors.interpolators.*; import java.util.Date; import java.awt.Color; /** * This class describe the scene of a planet. * * @author Marcel Portner & Bernhard Hari * @version $Revision: 1.18 $ * @see Planet */ public class ScenePlanet implements SceneCelestialObjects, PositionObserver, InfoObserver { private RotPosScaleTCBSplinePathInterpolator spline; private RotationInterpolator rotator; private Alpha rotationAlpha; private Alpha animAlpha; private long alphaTime = 0; private Date date; private BranchGroup removableCoordBG; private BranchGroup removableOrbitBG; private TransformGroup trGrRotAndLeafs; private TransformGroup trGrOrbit; private TransformGroup trGrTendSpline; private ColorOrbit colorOrbit; private Planet planet; private ObjectsPositions objPos; private ObjectsInformation objInfo; private InitializationObject iniObject; /** * Initializes a new ScenePlanet. * * @param planet a object reference of a given planet. * @param objPos a reference to the concrete subject of * the observer pattern positions * @param objInfo a reference to the concrete subject of * the observer pattern information */ public ScenePlanet(Planet planet, ObjectsPositions objPos, ObjectsInformation objInfo ) { this.planet = planet; this.objPos = objPos; this.objPos.attach(this); this.objInfo = objInfo; this.objInfo.attach(this); this.iniObject = objInfo.getInitializationObject(); } /** * .Removes this object from the position observer list. */ public void destroy() { objPos.detach(this); objInfo.detach(this); planet = null; } /** * Updates the position state of the object.
* * @param orbitPos a reference to the list containing all position observer */ public void update(OrbitPositions orbitPos) { } /** * Updates the information state of the object.
* * @param id identification of the object that has to be updated * @param parameter the parameter that has been updated */ public void update( String id, int parameter ) { if ( id.equals( planet.getId() ) || id.equals("all") ) { IniData data = (IniData)objInfo.getParameter( XMLConstants.PLANET, planet.getId() ); switch ( parameter ) { case XMLConstants.VISIBLE : // implemented inside SceneSolarSystem break; case XMLConstants.COORDINATESYSTEM : if(data.hasCoordinateSystem()) { addCoord(); } else { removeCoord(); } break; case XMLConstants.ORBIT : if(data.hasOrbit()) { addOrbit(); } else { removeOrbit(); } break; case XMLConstants.COLORORBIT : setOrbitColor(data.getColorOrbit()); break; case XMLConstants.ANIMATIONSPEED : setAnimSpeed(); break; default : break; } } } /** * Returns the ID of the current planet. * * @return the ID to idendification the planet. */ public String getId() { return planet.getId(); } /** * Returns a CelestialObjectInfo of the current planet. * This object has all specific information of the current planet. * * @return a CelestialObjectInfo of the current planet. */ public CelestialObjectInfo getInfo() { return planet.getInfo(); } /** * This method handle the animation and rotation of the celestial objects. * * @param animate if true, start animation; if false stop animation. * @param rotate if true, start rotation; if false stop rotation. */ public void setAnimation(boolean animate, boolean rotate) { date = new Date(); if(animate) { /* Set the stop time for the animation and rotation. Without this trick, the celestial objects are jumping around. Because when the animation is stop, the objects goes on in the background. */ alphaTime = date.getTime() - alphaTime; rotationAlpha.setStartTime(alphaTime); animAlpha.setStartTime(alphaTime); } else { // save the stop time for the animation and rotation. alphaTime = animAlpha.getStartTime(); alphaTime = date.getTime() - alphaTime; } // set the animation and rotation to stop or go. spline.setEnable(animate); rotator.setEnable(rotate); } /** * Set the animation speed for the planet. */ public void setAnimSpeed() { date = new Date(); AnimationSpeed animationSpeed = (AnimationSpeed)objInfo.getInitializationObject().getParameter(XMLConstants.ANIMATIONSPEED); int factor = 0; switch(animationSpeed.getType()) { case AnimationSpeed.DAYS_PER_SECOND: factor = 1; break; case AnimationSpeed.HOURS_PER_SECOND: factor = 24; break; case AnimationSpeed.MINUTES_PER_SECOND: factor = 24 * 60; break; default: } int animSpeed = animationSpeed.getValue(); long duration = (long)(planet.getRotOwnAxis() * factor / animSpeed); long increasing = rotationAlpha.getIncreasingAlphaDuration(); // delta t = t1*(1-T2/T1) long diff = (long)((date.getTime() - rotationAlpha.getStartTime()) * (1.0f - (float)duration / (float)increasing)); rotationAlpha.setIncreasingAlphaDuration(duration); rotationAlpha.setStartTime(rotationAlpha.getStartTime() + diff); duration = (long)(planet.getRotOrbit() * factor / animSpeed); increasing = animAlpha.getIncreasingAlphaDuration(); // delta t = t1*(1-T2/T1) diff = (long)((date.getTime() - animAlpha.getStartTime()) * (1.0f - (float)duration / (float)increasing)); animAlpha.setIncreasingAlphaDuration(duration); animAlpha.setStartTime(animAlpha.getStartTime() + diff); } /** * Add the coordinate system to this scenegraph. */ public void addCoord() { trGrRotAndLeafs.addChild(removableCoordBG); } /** * Remove the coordinate system from this scenegraph. */ public void removeCoord() { removableCoordBG.detach(); } /** * Add the color orbit to this scenegraph. */ public void addOrbit() { trGrOrbit.addChild(removableOrbitBG); } /** * Remove the color orbit from this scenegraph. */ public void removeOrbit() { removableOrbitBG.detach(); } /** * Set a new orbit color. * * @param orbitColor the new color of the orbit */ public void setOrbitColor(Color orbitColor) { colorOrbit.setColor(orbitColor); } /** * Get the current position of the planet. * * @return a Transform3D with the current position. */ public Transform3D getCurrentPosition() { Transform3D transVec = new Transform3D(); Transform3D transRot = new Transform3D(); trGrTendSpline.getTransform(transVec); trGrRotAndLeafs.getTransform(transRot); Vector3d vec = new Vector3d(); transVec.get(vec); transRot.setTranslation(vec); return transRot; } /** * Returns the BranchGroup of the created planet scene. * It has a planet as leaf, make a rotation to the own axis and * make with a TCB-spline function a rotation around the sun. * * @return the BranchGroup of the given planet. */ public BranchGroup createSceneGraph() { // A BoundingSphere instance as general bounding region. BoundingSphere boundsGen = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), SSS3dConstants.BOUNDRADIUS); // Create the first TransformGroup node trGrRotAndLeafs for the planet, // the coordinate system and the rotation trGrRotAndLeafs = new TransformGroup(); // With the ALLOW_TRANSFORM_READ and ALLOW_TRANSFORM_WRITE // capabilities, we allow the modification of the TransformGroup's // code by the Behavior's code at run time. trGrRotAndLeafs.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); trGrRotAndLeafs.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); trGrRotAndLeafs.setCapability(Group.ALLOW_CHILDREN_READ); trGrRotAndLeafs.setCapability(Group.ALLOW_CHILDREN_WRITE); trGrRotAndLeafs.setCapability(Group.ALLOW_CHILDREN_EXTEND); // Attach the ring of the Saturn if(getId().equals("saturn")) { TransformGroup trGrRing = new TransformGroup(); // Set the picking of the CoordinateSystem BranchGroup to false. trGrRing.setPickable(false); SaturnRing ring = new SaturnRing(1.3, 2.0, new Color3f(0.99f, 0.88f, 0.79f), 160); trGrRing.addChild(ring); // Duplicate the ring strip geometry and set the // appearance of the new Shape3D object without culling. // This is done because we will see the ring on both side!!!! PolygonAttributes polyAttrib = new PolygonAttributes(); polyAttrib.setCullFace(PolygonAttributes.CULL_NONE); Appearance polyAppear = ring.getAppearance(); polyAppear.setPolygonAttributes(polyAttrib); trGrRing.addChild(new Shape3D(ring.getGeometry(), polyAppear)); trGrRotAndLeafs.addChild(trGrRing); } // Attach the leaf node "planet" to the TransformGroup trGrRotAndLeafs. trGrRotAndLeafs.addChild(planet); removableCoordBG = new BranchGroup(); // Create and attach a coordinate system to the TransformGroup node // trGrRotAndLeafs, that is to the planet. removableCoordBG.addChild(new CoordinateSystem(1.2f)); // Allow to detach the Coordinate System removableCoordBG.setCapability(BranchGroup.ALLOW_DETACH); // Set the picking of the CoordinateSystem BranchGroup to false. removableCoordBG.setPickable(false); trGrRotAndLeafs.addChild(removableCoordBG); // Prepare the RotationInterpolator (Behavior) for the // planet's rotation about its own axis. Transform3D tr3Drot = new Transform3D(); float startRot, endRot; if(planet.getRotOwnAxis() > 0) { // Create the alpha(t) function. Positiv rotation! rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE, 0, 0, /*planet.getRotOwnAxis()*/Long.MAX_VALUE, 0, 0, 0, 0, 0); startRot = 0.0f; endRot = (float)(2.0 * Math.PI); } else { // Create the alpha(t) function. Negativ rotation! rotationAlpha = new Alpha(-1, Alpha.DECREASING_ENABLE, 0, 0, 0, 0, 0, /*Math.abs(planet.getRotOwnAxis())*/Long.MAX_VALUE, 0, 0); startRot = (float)(2.0 * Math.PI); endRot = 0.0f; } // Create the planet's rotation about its own axis. rotator = new RotationInterpolator(rotationAlpha, trGrRotAndLeafs, tr3Drot, startRot, endRot); rotator.setSchedulingBounds(boundsGen); trGrRotAndLeafs.addChild(rotator); // Create the second TransformGroup node trGrTendSpline for the planet's // rotation around the sun and the tend. trGrTendSpline = new TransformGroup(); // With the ALLOW_TRANSFORM_READ and ALLOW_TRANSFORM_WRITE // capabilities, we allow the modification of the TransformGroup's // code by the Behavior's code at run time. trGrTendSpline.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); trGrTendSpline.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); // Attach trGrRotAndLeafs node to the trGrTendSpline node. trGrTendSpline.addChild(trGrRotAndLeafs); Transform3D yAxis = new Transform3D(); // Create the alpha(t) function. animAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE, 0, 0, /*planet.getRotOrbit()*/Long.MAX_VALUE, 0, 0, 0, 0, 0); // rotate the planet to his true tend Matrix4d mat = new Matrix4d(); mat.rotX(Math.toRadians(planet.getDegree())); Quat4f r = new Quat4f(); r.set(mat); // set scale of the planet float scale; boolean compressed = ((Boolean)iniObject.getParameter(XMLConstants.COMPRESSED)).booleanValue(); if(compressed) { scale = planet.getLogRadius(); } else { scale = planet.getRadius(); } Point3f s = new Point3f(scale, scale, scale); Double time = (Double)iniObject.getParameter(XMLConstants.JDAY); // take the positions of the planet Point3f[] pos = objPos.getPositions(getInfo(), time.doubleValue(), compressed); int pointNrs = pos.length; float stepLength = 1 / (float)pointNrs; float stepPos = 0.0f; // save the positions in the TCBKeyFrame TCBKeyFrame[] keyFrames = new TCBKeyFrame[pointNrs+1]; for(int i = 0; i < pointNrs; i++) { keyFrames[i] = new TCBKeyFrame(stepPos, 0, pos[i], r, s, 0.0f, 0.0f, 0.0f); stepPos += stepLength; } keyFrames[pointNrs] = new TCBKeyFrame(1.0f, 0, pos[0], r, s, 0.0f, 0.0f, 0.0f); // make a spline courve of the position points spline = new RotPosScaleTCBSplinePathInterpolator(animAlpha, trGrTendSpline, yAxis, keyFrames); spline.setSchedulingBounds(boundsGen); trGrTendSpline.addChild(spline); // Create the TransformGroup node trGrOrbit for the planet orbit. trGrOrbit = new TransformGroup(); trGrOrbit.addChild(trGrTendSpline); trGrOrbit.setCapability(Group.ALLOW_CHILDREN_READ); trGrOrbit.setCapability(Group.ALLOW_CHILDREN_WRITE); trGrOrbit.setCapability(Group.ALLOW_CHILDREN_EXTEND); removableOrbitBG = new BranchGroup(); colorOrbit = new ColorLineOrbit(Color.red); colorOrbit.setPositions(pos); // Attach the leaf node "orbit" to the BranchGroup removableOrbitBG. removableOrbitBG.addChild(colorOrbit); removableOrbitBG.setCapability(BranchGroup.ALLOW_DETACH); // Set the picking of the ColorOrbit BranchGroup to false. removableOrbitBG.setPickable(false); trGrOrbit.addChild(removableOrbitBG); BranchGroup brGrAll = new BranchGroup(); brGrAll.addChild(trGrOrbit); brGrAll.setCapability(BranchGroup.ALLOW_DETACH); // Return the final version of the BranchGroup node brGrAll. return brGrAll; } }