Newbie question

Sorry for such a newbie question, I'm still trying to learn the scene graph and it's abilities.



I decided to try and make a model of the universe as a way to start learning jme.  I came up with a pretty good initial program of planets orbiting the sun, but the code was really messy.  All of my planets were creating new Sphere objects… Knowing the slightest bit about the scene graph, I'm pretty sure there is a better way to do this.  I decided to start over and find a better way to do this. 



My question: is it possible to create only one Sphere object and use it for all of the planets while being able to change planet sizes and textures?  Below was my attempt to do this:


      
protected void simpleInitGame() {
      display.setTitle("Universe");
                Sphere s = new Sphere("planets");  //use s to create all of the planets
      Node universe = new Node("Universe");  //Contain all of the planet nodes
      
                //Create the sun
      Node sun = new Node("SunNode");//Node to hold the sun sphere
      s.setName("sun");  //Is this necessary?
      s.setData(new Vector3f(0,0,0), 36, 25, 4.0f);
      TextureState ts = display.getRenderer().createTextureState();
      ts.setTexture(TextureManager.loadTexture(Main.class.getClassLoader()
               .getResource("data/maps/sun.jpg"),
              Texture.MM_LINEAR_LINEAR,
                 Texture.FM_LINEAR));
      s.setRenderState(ts);
      s.setModelBound(new BoundingBox());
      s.updateModelBound();
      sun.attachChild(s);
      
      universe.attachChild(sun);

      //Create the earth
      Node earth = new Node("EarthNode"); //Node to hold the earth sphere
      s.setName("earth");  //Is this necessary?
      s.setData(new Vector3f(-5,0,0),36,25,2.5f);
      TextureState ts2 = display.getRenderer().createTextureState();
      ts2.setTexture(TextureManager.loadTexture(Main.class.getClassLoader()
               .getResource("data/maps/earth800.jpg"),
                 Texture.MM_LINEAR_LINEAR,
                    Texture.FM_LINEAR));
      s.setRenderState(ts2);
      s.setModelBound(new BoundingBox());
      s.updateModelBound();
      earth.attachChild(s);
      //orbitSun(earth);
      
      universe.attachChild(earth);
      
      rootNode.attachChild(universe);
}



Is it also possible to do this with TextureStates? I hope I explained myself clearly enough.  Thanks!

I guess I should have waited another half hour before posting.  I came up with what I think is a better solution.


   protected void simpleInitGame() {
      display.setTitle("Universe");
      Node universe = new Node("Universe");  //Contain all of the planet nodes
      
      universe.attachChild(createPlanet("sun", new Vector3f(10,0,0), 5, "sun"));
      universe.attachChild(createPlanet("earth", new Vector3f(-5,0,0), 2.5f, "earth800"));
            
      rootNode.attachChild(universe);
   }
   
   protected Node createPlanet(String name, Vector3f startPos, float radius, String texture){
      Node n = new Node(name + "Node");//Node to hold the sun sphere
      n.attachChild(new Sphere(name, 36, 25, radius));
      TextureState ts = display.getRenderer().createTextureState();
      ts.setTexture(TextureManager.loadTexture(Main.class.getClassLoader()
               .getResource("data/maps/" + texture + ".jpg"),
              Texture.MM_LINEAR_LINEAR,
                 Texture.FM_LINEAR));
      n.getChild(name).setRenderState(ts);
      n.getChild(name).setModelBound(new BoundingBox());
      n.getChild(name).updateModelBound();
      n.setLocalTranslation(startPos);
      return n;
   }



I spent about 3 hours trying to figure this out; Ironically, as soon as I posted the first time the light bulb went on!  I guess thats part of the learning curve.  :D

Anywho, I'm sure this code could still be improved, I'm open to suggestions!

Thanks again!

You could go further by making each Planet share a Sphere, through the SharedMesh object.

Thanks mojo, I’ll have to experiment with the SharedMesh object.



I’m having another block in the road.  What I’m trying to do is spin the earth along its poles.



I created the sphere node, set its texture, and rotated it so it looked right side up. Here is a screen shot: http://img221.imageshack.us/img221/4662/earthtwott3.jpg



Then I added the sphere object as a child node to my node object n. I also rotated n by 23.5 degrees. here is that screen shot: http://img221.imageshack.us/img221/4371/earthonell4.jpg



The problem I’m having is that when i add the SpatialTransformer code, the earth seems to reset back to what it looked like in the first screen shot and then rotate.  I want the earth to rotate on it’s axis while tilted.  What am I doing wrong?



Here is my code:



protected void simpleInitGame() {
      Node n = new Node("Bleh");
      Sphere s = new Sphere("earth", 36, 25, 5f);
      
      TextureState ts = display.getRenderer().createTextureState();
      ts.setTexture(TextureManager.loadTexture(Main.class.getClassLoader()
               .getResource("data/maps/earth800.jpg"),
              Texture.MM_LINEAR_LINEAR,
                 Texture.FM_LINEAR));
      s.setRenderState(ts);
      s.updateRenderState();
      s.setModelBound(new BoundingBox());
      s.updateModelBound();
      
      //Make the planet look right side up
      Quaternion origPos = new Quaternion();
      origPos.fromAngleAxis(FastMath.DEG_TO_RAD*270, new Vector3f(1,0,0));
      s.setLocalRotation(origPos);
      n.attachChild(s);

      
      //Angle the planet via my node
      Quaternion tilt = new Quaternion();
      tilt.fromAngleAxis(FastMath.DEG_TO_RAD * 23.5f, new Vector3f(0,0,1));
      n.setLocalRotation(tilt);
      
      
      //create a controller to rotate my node
      SpatialTransformer st=new SpatialTransformer(1);
      st.setObject(n,0,-1);
       
      Quaternion x0=new Quaternion();
      x0.fromAngleAxis(0,new Vector3f(0,1,0));
      st.setRotation(0,8,x0);
      
      Quaternion x180=new Quaternion();
      x180.fromAngleAxis(FastMath.DEG_TO_RAD*180,new Vector3f(0,1,0));
      st.setRotation(0,16,x180);
      
      st.interpolateMissing();
      n.addController(st);
       
      rootNode.attachChild(n);
   }

I found a post by MojoMonkey from a year and a half ago about the problem I'm having.  He said:



When you set the position sets for the spatial transformer this will override the local translation of the object it is acting on.


So the local translation of my n node is being overridden by the spatial transformer.  I'm assuming this is the issue that I'm having, and I'll simply have to rethink the structure of my scene graph.

I do have another *hopefully* simple question.  If I create a Sphere object, is there any way to translate it twice?  I realize it could be done in one rotation, but I've been out of school for awhile and my linear algebra skills are on the decline.

Here is what I tried; however, this didn't produce the expected results.  Any suggestions?


//Make the planet look right side up
Quaternion center= new Quaternion();
center.fromAngleAxis(FastMath.DEG_TO_RAD*270, new Vector3f(1,0,0));
s.setLocalRotation(center);

//Angle the planet
Quaternion tilt = new Quaternion();
tilt.fromAngleAxis(FastMath.DEG_TO_RAD * 23.5f, new Vector3f(0,0,1));
s.setLocalRotation(tilt);
n.attachChild(s);


Seems to me as You are overwriting center with tilt.

To achieve what You want You have to multiply Your quats (or was it matrices ?) or use a node above s to set tilt.



edit: or did You mean to translate it and then rotate it ?

I did mean to rotate it twice.  how do I go about multiplyng the quats?



Thanks winkman

not sure this actually works but it would be something along:



center.multLocal(tilt);
s.setLocalRotation(center);