JPCT quaternion to euler problem

Post Reply
.jayderyu
Posts: 19
Joined: Sat Jan 17, 2009 10:51 am

JPCT quaternion to euler problem

Post by .jayderyu »

Hi well I posted a problem in the JBullet section I resolved what I was doing wrong in generel. Now instead i'm having euler problems in general.

I am using euler conversion code that I have seen around. No matter what I play around with I can't get it to work. Currently i'm testing with 5 boxes stacking on top of each other. They fall and pop they bounce up. Looks nice. It becomes noticable that when the boxes settle they are not flat. often they are at an angle with the tips graphicly sinking into the ground. Seems to indicate that my rotation is off.

JPCt doesn't support rotation absolute values. I rotate the object by an amount. So I compare new and old rotation. Below is my MotionState that I wrote up. I have been working on this for days.

Code: Select all

import javax.vecmath.Vector3f;
import javax.vecmath.Quat4f;

import com.threed.jpct.SimpleVector;
import com.threed.jpct.Object3D;

import javabullet.linearmath.MotionState;
import javabullet.linearmath.Transform;

public class JPCTBulletMotionState implements MotionState{
	public final Transform graphicsWorldTrans = new Transform();
	public final Transform centerOfMassOffset = new Transform();
	public final Transform startWorldTrans = new Transform();
  
  private Object3D obj3d;
  
  private float tran_x, tran_y, tran_z; // empty place spots
  private SimpleVector rotate = new SimpleVector();
  private SimpleVector last_rotate = new SimpleVector();
  
  public JPCTBulletMotionState()
  {
		graphicsWorldTrans.setIdentity();
		centerOfMassOffset.setIdentity();
		startWorldTrans.setIdentity();
  }
  
	public JPCTBulletMotionState(Transform startTrans)
  {
    this.graphicsWorldTrans.set(startTrans);
		centerOfMassOffset.setIdentity();
		this.startWorldTrans.set(startTrans);
	}  
  
	public JPCTBulletMotionState(Transform startTrans, Transform centerOfMassOffset)
  {
    this.graphicsWorldTrans.set(startTrans);
		this.centerOfMassOffset.set(centerOfMassOffset);
		this.startWorldTrans.set(startTrans);
	}  
  
  public void setObject(Object3D obj)
  {
    obj3d = obj;
  }
  
  public void getWorldTransform(Transform worldTrans){
 		worldTrans.set(graphicsWorldTrans);
                       //worldTrans.inverse(centerOfMassOffset);
                      //worldTrans.set(centerOfMassOffset);
		//worldTrans.mul(graphicsWorldTrans);
    return;
  }
  
  public void setWorldTransform(Transform worldTrans)
  {
    SimpleVector pos = obj3d.getTransformedCenter();
    
    tran_x = worldTrans.origin.x - pos.x;
    tran_y = worldTrans.origin.y - pos.y;
    tran_z = worldTrans.origin.z - pos.z;
    obj3d.translate(tran_x, tran_y, tran_z);
    
    Quat4f quat = worldTrans.getRotation();
    quat.inverse();
    quat.normalize();
    QuatToEuler(quat);
    
    graphicsWorldTrans.origin.set(tran_x, tran_y, tran_z);

    float rx = last_rotate.x - rotate.x;
    float rz = last_rotate.y - rotate.y;
    float ry = last_rotate.z - rotate.z;
    quat.set(rx,rz,ry, quat.w);
    graphicsWorldTrans.setRotation(quat);

    if(obj3d != null)
    {
      obj3d.rotateX(rx);
      obj3d.rotateY(ry);
      obj3d.rotateZ(rz);
    }
  }
  
  public void print(String txt)
  {
    System.out.println(txt);
  }

  public void QuatToEuler(Quat4f quat)
  {
	  double sqw;
	  double sqx;
	  double sqy;
	  double sqz;
	
	  double rotxrad;
	  double rotyrad;
	  double rotzrad;
	
	  sqw = quat.w * quat.w;
	  sqx = quat.x * quat.x;
	  sqy = quat.y * quat.y;
	  sqz = quat.z * quat.z;
	  rotxrad = (double)Math.atan2(2.0 * ( quat.y * quat.z + quat.x * quat.w ) , ( -sqx - sqy + sqz + sqw ));
	  rotyrad = (double)Math.asin(-2.0 * ( quat.x * quat.z - quat.y * quat.w ));
	  rotzrad = (double)Math.atan2(2.0 * ( quat.x * quat.y + quat.z * quat.w ) , (  sqx - sqy - sqz + sqw ));
    
    last_rotate.set((float)rotate.x, (float)rotate.y, (float)rotate.z);
	  rotate.set((float)rotxrad, (float)rotyrad, (float)rotzrad);
    return;
  }
  
}
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA
Contact:

Re: JPCT quaternion to euler problem

Post by Erwin Coumans »

This issue is JPCT related, not Bullet.

Bullet btWorldTransform provides a position and a 3x3 orientation matrix. Try updating the JPCt matrix, using the set method. http://www.jpct.net/doc/com/threed/jpct/Matrix.html#set(int, int, float);
Good luck,
Erwin
.jayderyu
Posts: 19
Joined: Sat Jan 17, 2009 10:51 am

Re: JPCT quaternion to euler problem

Post by .jayderyu »

I thought I would ask here first since I thought the difficulty would be more on getting on how to use the transform. Thanks for the tip, It animates better. Though I'm still having troubles. My current problem I'm not sure if it's a graphics rotation or a physics problem.

the animation looks nice. everything seems to fall and hits the ground well. It's that when it's on the ground 90% of the time the boxes rest on there edge rather than flat.

http://sre.hopto.org/images/badangle.gif
http://sre.hopto.org/images/badangle2.gif
http://sre.hopto.org/images/badangle3.gif

I've added/changes to this

Code: Select all

  public void setWorldTransform(Transform worldTrans)
  {
    ...
    Matrix3fToMatrix(worldTrans.basis);

    if(obj3d != null)
    {
      obj3d.setRotationMatrix(matrix);
    }
  }




// this code isn't mine. It was found on the JPCT forum who needed to get a Matrix3f to Matrix
	protected void Matrix3fToMatrix(Matrix3f input)
	{
		//Declare variables
		float[] insertDump = new float[16]; //The array holding the values in the new Matrix
		float[] rowDump = new float[3];     //The array for temporarily holding values from the rows of the Matrix3f
		int targetElement = 0;              //Points to the next location in the insertDump to add data
		
    //input.normalize();
    //input.invert();
    
		//Loop through the rows of the Matrix3f
		for (int sourceRow = 0; sourceRow < 3; sourceRow++)
		{
			//Grab the row from the Matrix3f
			input.getRow(sourceRow, rowDump);
			
			//Insert the 3 elements from the Matrix3f into the Matrix.  The fourth element has been initialized to 0.0f.
			insertDump[targetElement] = rowDump[0];
			insertDump[targetElement + 1] = rowDump[1];
			insertDump[targetElement + 2] = rowDump[2];
			
			//Move the target ahead by four spaces
			targetElement += 4;
		}
		
		//The final row consists of { 0.0f, 0.0f, 0.0f, 1.0f }, since this is a rotation matrix
		insertDump[15] = 1.0f;
		
		//Create the new Matrix and load in the values
		//Matrix output = new Matrix();
		matrix.setDump(insertDump);
		
		//Return
		return;
	}  
.jayderyu
Posts: 19
Joined: Sat Jan 17, 2009 10:51 am

Re: JPCT quaternion to euler problem

Post by .jayderyu »

NM, JPCT Primitive Box factory just drives me insane. The rotation problem is in fact that the box Y rotation isn't aligned. A box along the Y view is more like a diamond. ugg.

Thanks for your help. The suggestions provided a performance improvement none the less.
Post Reply