Spatial/Node Translation and Rotation insights

Hello everyone,



In this topic i'd like to summarize my experiences as i learned jME's node and spatial rotation system, in case anyone gets stuck where i did in the future.

When i began my journey in the ugly and dry mathematical side of 3d animation in jME i believed that everything can be rotated around its center. Every spatial has a setLocalRotation method, so here is it, problem solved. I can rotate locally as i want. I did as i said, but the results were not what i wanted. The cube i wanted to rotate around it's center, did actually rotate around its corner. No problem, i translated it, so the center would be where last time the corner was. What happened? It still rotated around that same corner. I tried several other methods but they did not lead me to success.

Then i got a hunch on the forum. When you move or rotate a shape in jME, it is moved/rotated along its zero coordinate of creation.

For example if i crate my box like:

Box box = new Box("The Box From 0", new Vector3f(0,0,0), new Vector3f(1,1,1));


The setLocalRotation method will rotate around its left-down corner.
But if i create my box like:

Box box = new Box("The Box From Center", new Vector3f(-0.5f,-0.5f,-0.5f), new Vector3f(0.5f,0.5f,0.5f));


Then the box gets treated at its center.
So far i havent found any methods to modify this treating center. If there is one, i apologize, but if not, then it should be implemented.
I hope you will find this post useful. Thank you for your attention:)

An object always rotates around (0,0)



But as an alternative you can give an object a local translation, attach it to a Node, and then rotate that node. The (0,0) centre will then be displaced by the amountof the local translation.

llama said:


But as an alternative you can give an object a local translation, attach it to a Node, and then rotate that node. The (0,0) centre will then be displaced by the amountof the local translation.


Thats right, but it would still rotate about its (0,0) of creation. The first box i mentioned always rotates around its down-left corner.  To make it rotate about its center you have create it a way that its center is at (0,0).
I'll put together an example app, to demonstrate.

This is the Rotation example with a box. I commented out another box. Try both of them.


/*
 * Copyright (c) 2003-2008 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import jmetest.scene.TestRotateAboutPoint;

import com.jme.app.SimpleGame;
import com.jme.bounding.BoundingSphere;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.scene.Node;
import com.jme.scene.shape.Box;
import com.jme.scene.shape.Sphere;

/**
 * @version $Id: TestRotateAboutPoint.java,v 1.1 2007/08/03 00:04:00 nca Exp $
 */
public class TestRotate extends SimpleGame {
  private Quaternion rotQuat1 = new Quaternion();
  private Quaternion rotQuat2 = new Quaternion();
 
  private float angle = 0;
  private Vector3f axis = new Vector3f(0, 1, 0);
  private Sphere s;
  private Sphere moon1;
  private Box moon2;
  private Node pivotNode1, pivotNode2;

  /**
   * Entry point for the test,
   * @param args
   */
  public static void main(String[] args) {
    TestRotate app = new TestRotate();
    //app.setConfigShowMode(ConfigShowMode.AlwaysShow);
    app.start();
  }

  protected void simpleUpdate() {
    if (tpf < 1) {
      angle = angle + (tpf * 1);
      if (angle > 360) {
        angle = 0;
      }
    }
    rotQuat1.fromAngleAxis(angle, axis);
    pivotNode1.setLocalRotation(rotQuat1);
   
    rotQuat2.fromAngleAxis(angle * 2, axis);
    pivotNode2.setLocalRotation(rotQuat2);
   
  }

  /**
   * builds the trimesh.
   * @see com.jme.app.SimpleGame#initGame()
   */
  protected void simpleInitGame() {
    display.setTitle("jME - Rotation About a Point");

    //Planet
    s = new Sphere("Planet", 25, 25, 25);
    s.setModelBound(new BoundingSphere());
    s.updateModelBound();
    //rootNode.attachChild(s);
   
    //Moons
    moon1 = new Sphere("Moon 1",25, 25, 10);
    moon1.setModelBound(new BoundingSphere());
    moon1.updateModelBound();
    moon1.setLocalTranslation(40, 0, 0);
    pivotNode1 = new Node("PivotNode 1");
    pivotNode1.attachChild(moon1);
   
    moon2 = new Box("Moon 2",new Vector3f(0,0,0), new Vector3f(20,20,20));
    //moon2 = new Box("Moon 2",new Vector3f(-10,-10,-10), new Vector3f(10,10,10));
    moon2.setModelBound(new BoundingSphere());
    moon2.updateModelBound();
    //moon2.setLocalTranslation(60, 0, 0);
    pivotNode2 = new Node("PivotNode 2");
    pivotNode2.attachChild(moon2);
   
    rootNode.attachChild(pivotNode1);
    rootNode.attachChild(pivotNode2);
  }
}

like llama said, you always rotate or transform around origo (think of it as transforming the coordinate system). the constructors of the box allows you to define how the vertices of the box are to be created, relative to origo (0,0,0).

I know i've done very little low level opengl programing, but isnt this a problem? Isn't it possible to change this zero coordinate? It's a little odd that i have to reacreate my whole object if i just want to change it's center.

Forgive me my stubbornness:) I dont mean to offend.

Well, you can also use the Geometry methods translatePoints and rotatePoints to shift your Geometry in its local coordinate space, effectively changing its origin.