JBullet Quanternion to JPCT Matrix rotation

Started by .jayderyu, March 03, 2009, 03:18:58 PM

Previous topic - Next topic

.jayderyu

That's right i'm tackling JBullet. Going good except that last few days on working with getting Quat to Euler. I just can't get it to work right. No matter what I do a physics box will always show Object3D primitive Box at an angle with the corner stiking through the floor.


import sre.roam.JPCTLib;

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

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

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 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;
  }
 
}

The conversion code above has worked in other graphical cases. Other uses of Bullet+Irrelect, Ode and ogre. I just can't get it to work with JBullet and JPCT.


maybe i'm missing something silly. I don't know. So I'm thinking of using cyberkilla skeletal
Matrix.setQuaternionRotation(). Which converts a quat to a float mat[16].
Will changing a quat to a JPCT.Matrix cause any troubles. Will children rotate with the new matrix or will I have to continue with trying to work a way with Object3D.rotate().


EgonOlsen

Converting it to a matrix should be fine. Maybe even better than using the rotate()-methods. Quaternions and matrices are mathematically equivalent (albeit some people claim that they aren't and that quaternions are more powerful, but that's bs...they may be more convenient in some cases but don't do anything that a matrix can't), so this shouldn't be a problem.
Which kind of boxes are using? If you are using the ones created by Primitives.getBox()...those are not axis aligned. Maybe that causes the problems?

.jayderyu

#2
Thanks, it works better. Still not right thought. Theres no more wierd rotation jerks. It's just that when the box settles on the ground it sits on it's edge. I'm not sure if it's a physics problem or a still a rotation error. I'm also asking at the bullet forums.

To note the matrix translation from TransformWorld in the motionstate also has a rotation matrix. So I was able to use some old code form somewhere on the forums here to get Matrix3fToMatrix(). I noticed a performance increase with this.

If I ever manage to solve this I'll write up a JPCT Physics integration guide just to save new comers some grief on merging the two systems :)

edit: sigh your right, the box isn't Y axis aligned.