Orbits within orbits

Hi all,

I’m having an issue getting a node to orbit another node that is its self in orbit around a third node. The fist orbiting node works fine with just a simple control added, but when I attach the satellite node to the first it just its at 0,0,0, not where i coded it to go. below is a simple version of what I have, if anyone can tell me why the moon is not orbiting the earth it would help loads thanks.

All nodes in the system with geomerty use this node class ( stripped of all none related code )
[java]public class SimpleCelestialBody extends Node {

private ArrayList<Node> bodies = new ArrayList<Node>(); // list of all bodies attached to this one
private GamePlayAppState app;
private Vector3f location;
private Bodies body;
private Geometry shape;

private Material m_dirt;
private Material m_trail;


public SimpleCelestialBody(GamePlayAppState app, Bodies body) {
    this(body.name);
    this.app = app;
    this.body = body;

    if (body.getRadius() != 0) {
        setMaterials(body.color);

        // creat the geometry model for the body
        Sphere sphear = new Sphere(64, 64, body.radius / 10000);

        shape = new Geometry("Sphere", sphear);

        shape.setMaterial(m_dirt);
        // attach the shape this node
        this.attachChild(shape);

        // align the geom
        shape.rotate((FastMath.DEG_TO_RAD * 90) - body.getTilt(), 0.0f, 0.0f);

        // place the body on the correct orbital path before update loop starts 
        Vector3f pivot = new Vector3f((float) body.getSemimajorAxis() / 100000, 0, 0);
        shape.setLocalTranslation(pivot);

       
        // add the needed controls to the shape
        shape.addControl(new SimpleCelestialBodyControl(body));

        // add a trail to the body
        this.addTrail();
    }


}[/java] 

and this node class is used to define the pivots of the orbits

[/java]public class SimpleOrbitNode extends Node {

private SimpleCelestialBody orbitingBody;

public SimpleOrbitNode(GamePlayAppState app, Bodies body) {

    //add the orbit control
    this.addControl(new SimpleOrbitNodeControl(body));

    // attach the orbiting body
    this.orbitingBody = new SimpleCelestialBody(app, body);
    this.attachChild(this.orbitingBody);

}


public SimpleCelestialBody getOrbitingBody() {
    return orbitingBody;
}

} [java]

The system is constructed like this…Bodies is the class that defined the orbital elements and body(geometry) parameters
[java]
SimpleCelestialBody system = new SimpleCelestialBody(this, Bodies.SolarSystem);
SimpleOrbitNode earth = new SimpleOrbitNode(this, Bodies.Earth);
earth.getOrbitingBody().attachBody(new SimpleOrbitNode(this, Bodies.Luna));
this.system.attachBody(earth);
app.getRootNode().attachChild(system);
[/java]

Thanks for any pointers you may have on this.

apparently I can not edit or delete my own posts so I’m sorry for the mess above I hope this works
Hi all,

I’m having an issue getting a node to orbit another node that is its self in orbit around a third node. The fist orbiting node works fine with just a simple control added, but when I attach the satellite node to the first it just its at 0,0,0, not where i coded it to go. below is a simple version of what I have, if anyone can tell me why the moon is not orbiting the earth it would help loads thanks.

All nodes in the system with geomerty use this node class ( stripped of all none related code )
[java]public class SimpleCelestialBody extends Node {

private ArrayList<Node> bodies = new ArrayList<Node>(); // list of all bodies attached to this one
private GamePlayAppState app;
private Vector3f location;
private Bodies body;
private Geometry shape;

private Material m_dirt;
private Material m_trail;


public SimpleCelestialBody(GamePlayAppState app, Bodies body) {
    this(body.name);
    this.app = app;
    this.body = body;

    if (body.getRadius() != 0) {
        setMaterials(body.color);

        // creat the geometry model for the body
        Sphere sphear = new Sphere(64, 64, body.radius / 10000);

        shape = new Geometry("Sphere", sphear);

        shape.setMaterial(m_dirt);
        // attach the shape this node
        this.attachChild(shape);

        // align the geom
        shape.rotate((FastMath.DEG_TO_RAD * 90) - body.getTilt(), 0.0f, 0.0f);

        // place the body on the correct orbital path before update loop starts 
        Vector3f pivot = new Vector3f((float) body.getSemimajorAxis() / 100000, 0, 0);
        shape.setLocalTranslation(pivot);

       
        // add the needed controls to the shape
        shape.addControl(new SimpleCelestialBodyControl(body));

        // add a trail to the body
        this.addTrail();
    }


}[/java] 

and this node class is used to define the pivots of the orbits

[java]public class SimpleOrbitNode extends Node {

private SimpleCelestialBody orbitingBody;

public SimpleOrbitNode(GamePlayAppState app, Bodies body) {

    //add the orbit control
    this.addControl(new SimpleOrbitNodeControl(body));

    // attach the orbiting body
    this.orbitingBody = new SimpleCelestialBody(app, body);
    this.attachChild(this.orbitingBody);

}


public SimpleCelestialBody getOrbitingBody() {
    return orbitingBody;
}

} [/java]

The system is constructed like this…Bodies is the class that defined the orbital elements and body(geometry) parameters
[java]
SimpleCelestialBody system = new SimpleCelestialBody(this, Bodies.SolarSystem);
SimpleOrbitNode earth = new SimpleOrbitNode(this, Bodies.Earth);
earth.getOrbitingBody().attachBody(new SimpleOrbitNode(this, Bodies.Luna));
this.system.attachBody(earth);
app.getRootNode().attachChild(system);
[/java]

Thanks for any pointers you may have on this.

All of the custom extension of Node aren’t doing you any favors in describing your problem. It makes it harder to follow what’s going on (and is generally discouraged anyway since everything you’re doing could have been done with just controls on regular nodes).

If you reduced this problem down to a simple test case using regular JME classes, I think you would see that it either works or you’d have something more straight-forward to post and we could show you what’s wrong with your hierarchy. For example, I have no idea what your control is doing… maybe it’s messing everything up. Who knows?

Your hierarchy should look something like:

  • Earth Solar System Orbit Node - rotate this for year revolutions
    • Earth Node (translated from center of solar system)
      • Earth geometry - rotate this for day/night
      • Moon orbit node at earth's 0,0,0 - rotate this for moon orbit
        • Moon Geometry - rotate this for moon 'days' (though in the case of our moon, inverse angle of the orbit)

Edit: redoing hierarchy since the bullet levels were swallowed:

  • Earth Solar System Orbit Node - rotate this for year revolutions
    • Earth Node (translated from center of solar system)
      • Earth geometry - rotate this for day/night
      • Moon orbit node at earth’s 0,0,0 - rotate this for moon orbit
        • Moon Geometry - rotate this for moon ‘days’ (though in the case of our moon, inverse angle of the orbit)

hi, and thanks for the response. I’m sorry I have only messing with JME3 for a short time and this is more a project to learn the things your telling me then actualy to produce something. I will re-write this as you described as see if I have any more luck.

thanks

hi again. So I played with what you said and came up with the code below. its very much simplified i think from what I will need to achieve what I want, but the orbits work and I can expand on this.

I just a have a question though…

as this look there is a ‘physical’ link between a parent and child node and as such changes to the rotation of the parent automatically get passed to the child node. This by design I know, but is there a way so that the rotation changes are not passed down but still have the child follow the parents translation? The best I can come up with to achieve this is to mirror any rotation changes on the parent to the child. so if I rotate the parent 0.01f on the z axiz i have to then rotate the child -0.01f on the z axiz to ensure it does not rotate around when its parent does. I hope that’s not to confusing.

[java]public class Main extends SimpleApplication {

public static void main(String[] args) {
    Main app = new Main();
    AppSettings gameSettings = new AppSettings(false);
    gameSettings.setFullscreen(false);
    gameSettings.setResolution(1680, 1050);

    gameSettings.setVSync(false);
    gameSettings.setTitle("orbitTest");
    gameSettings.setUseInput(true);
    gameSettings.setFrameRate(500);
    gameSettings.setSamples(0);
    gameSettings.setRenderer("LWJGL-OpenGL2");
    app.settings = gameSettings;
    app.setShowSettings(false);

    app.start();
}
private Node sun; // the sun
private Node planetOrbitNode; //the planets orbit node
private Node planet; // the planet
private Node moonOrbitNode; // te moons orbit node
private Node moon; // the moon

@Override
public void simpleInitApp() {
    cam.setLocation(new Vector3f(0, 0, 20));
    cam.lookAt(new Vector3f(0, 0, 0), Vector3f.UNIT_Y);
    flyCam.setMoveSpeed(100);
    flyCam.setZoomSpeed(1);


    Node system = new Node("System");
    
    sun = new Node("Sun");
    Geometry g_sun = new Geometry("Sun", new Box(0.5f, 0.5f, 0.5f));
    Material m_sun = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    m_sun.setColor("Color", ColorRGBA.Orange);
    g_sun.setMaterial(m_sun);
    sun.attachChild(g_sun);


    planet = new Node("Planet");
    Geometry g_planet = new Geometry("planet", new Box(0.5f, 0.5f, 0.5f));
    Material m_planet = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    m_planet.setColor("Color", ColorRGBA.Green);
    g_planet.setMaterial(m_planet);
    planet.attachChild(g_planet);
    planetOrbitNode = new Node("PON");
    planetOrbitNode.attachChild(planet);
    planet.setLocalTranslation(0, 3, 0);

    // 
    moon = new Node("moon");
    Geometry g_moon = new Geometry("moon", new Box(0.25f, 0.25f, 0.25f));
    Material m_moon = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    m_moon.setColor("Color", ColorRGBA.DarkGray);
    g_moon.setMaterial(m_moon);
    moon.attachChild(g_moon);

    // attach the moon to its orbit node
    moonOrbitNode = new Node("MON");
    moonOrbitNode.attachChild(moon);
    moon.setLocalTranslation(0, 1.5f, 0);
    // attatch the moons orbit node to the planet
    planet.attachChild(moonOrbitNode);


    system.attachChild(planetOrbitNode);
    system.attachChild(sun);
    rootNode.attachChild(system);

}

@Override
public void simpleUpdate(float tpf) {
    this.moonOrbitNode.rotate(0, 0, -0.002f);
    this.moon.rotate(0, 0, 0.001f);
    this.planetOrbitNode.rotate(0, 0, 0.001f);
    this.planet.rotate(0, 0, 0.001f);
    this.sun.rotate(0, 0, -0.002f);
}

@Override
public void simpleRender(RenderManager rm) {
    //TODO: add render code
}

}[/java]

The easiest would be to do as I’ve done in my example. Use one node for translation and then have children that have different rotations. Or do you mean that as the earth is rotating around the sun then it also gets rotated to keep facing the sun. Yeah, there is really no way around that. You would have to apply counter rotation, I guess.

Alternately, don’t use the node hierarchy at all for positioning your spatial bodies and just calculate them directly. Personally, this is what I would do if simulating a solar system. After all, none of these are really traveling in circles anyway. Just calculate the time versus position of the ellipse for each body and move it.

I have no real need for elliptical orbits at the moment, so this works for now, thanks for your pointers though. I have transposed what I learned here back to my original code and its now working as expected. That’s the kind of answer that works, give clues not solutions and the lesson is learned.