I tried to rotate an object using the tutorial but it didnt work :(

Hai!

Using the rotating moons tutorial I tried to rotate a object.



Now not only one but multiple…

The problem is that the objects do not rotate at all :frowning:



All I wanted to do was rotate the "Box"es in selectedObj vector but without rotating the object it self, just

the objects position…



Heres my code which doesnt work:

private void rotateObj() {
      Vector3f rotPoint = new Vector3f();
      /*Vector3f maxRotPoint = new Vector3f();
      Vector3f minRotPoint = new Vector3f();
      for (int x = 0;x<MainClass.selectedObj.size();x++){
         Box selected = selectedObj.elementAt(x);
         if (selected.getLocalTranslation().x > maxRotPoint.x){
            maxRotPoint.x = selected.getLocalTranslation().x;
         }
         if (selected.getLocalTranslation().y > maxRotPoint.y){
            maxRotPoint.y = selected.getLocalTranslation().y;
         }
         if (selected.getLocalTranslation().z > maxRotPoint.z){
            maxRotPoint.z = selected.getLocalTranslation().z;
         }
         if (selected.getLocalTranslation().x < minRotPoint.x){
            minRotPoint.x = selected.getLocalTranslation().x;
         }
         if (selected.getLocalTranslation().y < minRotPoint.y){
            minRotPoint.y = selected.getLocalTranslation().y;
         }
         if (selected.getLocalTranslation().z < minRotPoint.z){
            minRotPoint.z = selected.getLocalTranslation().z;
         }
      }*/
      rotPoint.add(MainClass.selectedObj.get(0).getLocalTranslation());
      Node pos = new Node();
      pos.setLocalTranslation(rotPoint);
      for (int x = 0;x<MainClass.selectedObj.size();x++){
         Box selected = selectedObj.elementAt(x);
         pos.attachChild(selected);
         //float[] pos = rotatePos((float) Math.toRadians(90),rotPoint.x,rotPoint.z,selected.getLocalTranslation().x,selected.getLocalTranslation().z);
          //selected.setLocalTranslation(pos[0],selected.getLocalTranslation().y,pos[1]);
         
         float xPos = selected.getLocalScale().x;
         float zPos = selected.getLocalScale().z;
         selected.setLocalScale(new Vector3f(zPos,selected.getLocalScale().y,xPos));
      }
      Quaternion rot = new Quaternion();
      rot.fromAngleAxis(90, Vector3f.UNIT_Y);
      pos.setLocalRotation(rot);
      pos.setName("POS");
      for (int x = 0;x<MainClass.selectedObj.size();x++){
         Box selected = selectedObj.elementAt(x);
         Vector3f selPos = selected.getWorldTranslation();
         System.out.println(selected.getParent());
         selected.setLocalTranslation(selPos);
         rootnode.attachChild(selected);
         
      }
      pos.removeFromParent();
   }

I think a good idea and practice would be to comment your code more.

That way both other people and yourself will have less trouble seeing what is happening.



I'm not quite sure what you're trying to do.

You want to rotate the boxes, but not rotate them, just their position?

Perhaps you want to have the boxes attached to a node with an offset in position from the node, so you can move the boxes in a circle around the node by rotating the node?

By "rotating moons tutorial" I'm guessing you mean jmetest.scene.RotateAboutPoint?



I'll point out a few things in your code, perhaps you can clarify what you're doing, then I'll try to explain how you can do the above rotations.



      rotPoint.add(MainClass.selectedObj.get(0).getLocalTranslation());


Here you're using a method that returns a Vector3f without assigning the returned value to a variable.
If you want to add a Vector3f vector2 to a Vector3f vector1, you can do any of the following:


      vector1 = vector1.add(vector2);
                //or
                vector1.addLocal(vector2);


The latter might be preferred if you just want to add it to the same vector, as it doesn't create a new vector.


      Node pos = new Node();
      pos.setLocalTranslation(rotPoint);


Here you're assigning the same reference to an object (a Vector3f in this case) to two variables.
Perhaps this is what you want to do, but if you change something about the object referenced by pos you also change something about the object referenced by rotPoint, as they point to the same object.
If you don't want this, you can do the following:


      pos.setLocalTranslation(rotPoint.clone());


This creates a deep copy of the object, so you now have references to two different objects instead of the the same object.


      for (int x = 0;x<MainClass.selectedObj.size();x++){
         Box selected = selectedObj.elementAt(x);


Here I just wanted to point out that elementAt(int index) and get(int index) do the same thing.


         pos.attachChild(selected);
         //float[] pos = rotatePos((float) Math.toRadians(90),rotPoint.x,rotPoint.z,selected.getLocalTranslation().x,selected.getLocalTranslation().z);
          //selected.setLocalTranslation(pos[0],selected.getLocalTranslation().y,pos[1]);
         
         float xPos = selected.getLocalScale().x;
         float zPos = selected.getLocalScale().z;
         selected.setLocalScale(new Vector3f(zPos,selected.getLocalScale().y,xPos));
      }
      Quaternion rot = new Quaternion();
      rot.fromAngleAxis(90, Vector3f.UNIT_Y);
      pos.setLocalRotation(rot);
      pos.setName("POS");
      for (int x = 0;x<MainClass.selectedObj.size();x++){
         Box selected = selectedObj.elementAt(x);
         Vector3f selPos = selected.getWorldTranslation();
         System.out.println(selected.getParent());
         selected.setLocalTranslation(selPos);
         rootnode.attachChild(selected);
         
      }
      pos.removeFromParent();
   }



I don't quite understand your intentions with your code, but this is how you could do a circular rotation of objects around a mid-point node.

Assuming rotQuat1 is a Quaternion instantiated before this and pivotNode1 is a node instantiated before this,
angle is an int in degrees and axis is an axis (e.g. Vector3f.UNIT_Y), box is a Box instantiated before this.


//We set the local translation of the box to offset it from the center of the pivot node
box.setLocalTranslation(50,0,0);

//When we attach the box to the node the local translation of the box becomes relative to the node's position
pivotNode1.attachChild(box);
rootNode.attachChild(pivotNode1);

//We rotate the quaternion with a certain angle around an axis
rotQuat1.fromAngleAxis(angle, axis);

//We set the rotation represented by the quaternion to the pivot node
//Because the box is attached to this node, it will rotate around the pivot node
//but as it is offset from the center of the pivot node it will appear to move in a circle around it
pivotNode1.setLocalRotation(rotQuat1);



If you want to turn it continuously you of course have to increase the rotation continuously.
Hope this cleared things up a bit.

Thanks alot :slight_smile:

I changed a few things and totaly over-commented the method XD

Right now if u rotate multiple objects, they move to a strange position

and there they tend to rotate wierdly or not at all…



Here is the new, awsomely documented code :smiley:

   private void rotateObj() {
      Vector3f rotPoint = new Vector3f(MainClass.selectedObj.get(0).getLocalTranslation());
      //Get the position on which all objects should rotate around
      //in this case, the first object in the list
      Node pos = new Node();
      pos.setLocalTranslation(rotPoint.clone());
      //Creates a node which should contain the objects and rotate
      //and we set the position of it to the rotation point "rotPoint"
      for (int x = 0;x<MainClass.selectedObj.size();x++){
         Box selected = selectedObj.elementAt(x);
         selected.setLocalTranslation(selected.getLocalTranslation().subtract(rotPoint));
         //Sets the selected local translation so it keeps it distance to the
         //node "pos" when its changed parent from rootNode to "pos"
         pos.attachChild(selected);
         //adds the object
      }
      rootNode.attachChild(pos);
      //adds node to rootNode
      Quaternion rot = new Quaternion();
      rot = rot.fromAngleAxis((float) 90, Vector3f.UNIT_Y);
      pos.setLocalRotation(rot);
      //Sets the rotation off the node to 90 degrees on the y axis
      for (int x = 0;x<MainClass.selectedObj.size();x++){
         Box selected = selectedObj.elementAt(x);
         Vector3f selPos = selected.getWorldTranslation();
         //saves the World location
         selected.setLocalTranslation(selPos);
         //applies the location so that we do not get it wrong
         //when chaing parent
         rootnode.attachChild(selected);
         //applying it back to the rootNode
         
      }
      pos.removeFromParent();
      //deletes the node "pos"
   }

That's alot easier to read, thanks! :slight_smile:



I tried your example, doing incremental rotation and using a timer to see how it rotates.

What I found was that you're trying to access the new translations of objects that haven't been updated in the scene graph.

What you need to do is add a "rootNode.updateGeometricState(0, true);" after changing the rotation of your pivot node, if you want to get the new world translations straight afterwards.

If you don't need them until the next update, "rootNode.updateGeometricState(float tpf, boolean initiator);" is called every update, so then they would be updated.



Here is a working example.

It uses a timer to show the rotation more clearly.

The only thing I added to your rotateObj()-method is "rootNode.updateGeometricState(0, true);" after setting the new rotation.


import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;

import javax.swing.Timer;

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


public class RotationTest2 extends SimpleGame {
   private Vector<Box> selectedObj = new Vector<Box>();
   
   public RotationTest2() {
      
   }

   @Override
   protected void simpleInitGame() {
      Box box1 = new Box("Box1", Vector3f.ZERO.clone(),5,5,5);
      box1.setModelBound(new BoundingBox());
      box1.updateModelBound();
      box1.updateRenderState();
      box1.setLocalTranslation(new Vector3f(50,50,-50));
      Box box2 = new Box("Box2", Vector3f.ZERO.clone(),5,5,5);
      box2.setModelBound(new BoundingBox());
      box2.updateModelBound();
      box2.updateRenderState();
      box2.setLocalTranslation(new Vector3f(100,50,-50));
      Box box3 = new Box("Box3", Vector3f.ZERO.clone(),5,5,5);
      box3.setModelBound(new BoundingBox());
      box3.updateModelBound();
      box3.updateRenderState();
      box3.setLocalTranslation(new Vector3f(50,100,-50));
      Box box4 = new Box("Box4", Vector3f.ZERO.clone(),5,5,5);
      box4.setModelBound(new BoundingBox());
      box4.updateModelBound();
      box4.updateRenderState();
      box4.setLocalTranslation(new Vector3f(50,50,-100));
      Box box5 = new Box("Box5", Vector3f.ZERO.clone(),5,5,5);
      box5.setModelBound(new BoundingBox());
      box5.updateModelBound();
      box5.updateRenderState();
      box5.setLocalTranslation(new Vector3f(100,100,-100));
      
      selectedObj.add(box1);
      selectedObj.add(box2);
      selectedObj.add(box3);
      selectedObj.add(box4);
      selectedObj.add(box5);
      
      rotateObj();
   }
   
   private void rotateObj() {
      Vector3f rotPoint = new Vector3f(selectedObj.get(0).getLocalTranslation());
      //Get the position on which all objects should rotate around
      //in this case, the first object in the list
      final Node pos = new Node();
      pos.setLocalTranslation(rotPoint.clone());
      //Creates a node which should contain the objects and rotate
      //and we set the position of it to the rotation point "rotPoint"
      for (int x = 0;x<selectedObj.size();x++){
         Box selected = selectedObj.elementAt(x);
         selected.setLocalTranslation(selected.getLocalTranslation().subtract(rotPoint));
         //Sets the selected local translation so it keeps it distance to the
         //node "pos" when its changed parent from rootNode to "pos"
         pos.attachChild(selected);
         //adds the object
      }
      rootNode.attachChild(pos);
      //adds node to rootNode
      
      //Set up a timer to do the rotation after 3 seconds
      Timer timer = new Timer(3000, new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent e) {
            Quaternion rot = new Quaternion();
            rot = rot.fromAngleAxis((float) 90, Vector3f.UNIT_Y);
            pos.setLocalRotation(rot);
            rootNode.updateGeometricState(0, true);
            //Sets the rotation off the node to 90 degrees on the y axis
            for (int x = 0;x<selectedObj.size();x++){
               Box selected = selectedObj.elementAt(x);
               Vector3f selPos = selected.getWorldTranslation();
               //saves the World location
               selected.setLocalTranslation(selPos);
               //applies the location so that we do not get it wrong
               //when chaing parent
               rootNode.attachChild(selected);
               //applying it back to the rootNode
               
            }
            pos.removeFromParent();
            //deletes the node "pos"
         }
      });
      timer.start();
   }
   
   public static void main(String[] args) {
      RotationTest2 test = new RotationTest2();
      test.start();
   }
}


Good luck!

Your so awsome Tunami it works perfect :slight_smile:



Thanks alot for taking time fixing it for me, I ow you one  :smiley: