Java-Gaming.org Hi !
 Featured games (83) games approved by the League of Dukes Games in Showcase (581) Games in Android Showcase (162) games submitted by our members Games in WIP (632) games currently in development
 News: Read the Java Gaming Resources, or peek at the official Java tutorials
 Home Help Search Login Register
Pages: [1]
 ignore  |  Print
 Bug in GeomTransform  (Read 3987 times) 0 Members and 1 Guest are viewing this topic.
arne

Senior Devvie

money is the worst drug- we should not let it rule

 « Posted 2005-03-28 07:37:36 »

Hi
this bug is actually a Java3D vecmath problem, but I post it here too (I've postet it in the Java3D forum too), because it affects the behavior of the GeomTransform.
The thing is this: GeomTransform uses a Matrix4f to store the transformation data into. The rotational part of the transformation data is always created out of Quat4f. When the Rotation data is requested the rotational part of the Matrix4f is transformed back into a Quat4f.
But: this transformation is not a identity transformation !!!
As an example see this code:
 1  2  3  4  5  6  7  8  9  10  11 `        Quat4f qStart = new Quat4f(0,0.707f,0.707f,0);        Matrix4f mStart = new Matrix4f();        mStart.set(qStart);        Quat4f qEnd = new Quat4f();        mStart.get(qEnd);        Matrix4f mEnd = new Matrix4f();        mEnd.set(qEnd);        System.out.println("qStart: "+qStart);        System.out.println("\nmStart: "+mStart);        System.out.println("\nqEnd: "+qEnd);        System.out.println("\nmEnd: "+mEnd);`

When I execute it I get:

qStart: (0.0, 0.7071068, 0.7071068, 0.0)

mStart: -1.0000002, 0.0, 0.0, 0.0
0.0, -1.1920929E-7, 1.0000001, 0.0
0.0, 1.0000001, -1.1920929E-7, 0.0
0.0, 0.0, 0.0, 1.0

qEnd: (NaN, NaN, NaN, NaN)

mEnd: NaN, NaN, NaN, 0.0
NaN, NaN, NaN, 0.0
NaN, NaN, NaN, 0.0
0.0, 0.0, 0.0, 1.0

:: JOODE :: Xith3d :: OdeJava ::
William Denniss

JGO Coder

Projects: 2

Fire at will

 « Reply #1 - Posted 2005-03-28 21:31:11 »

err... crap!

got a workaround?

Will.

arne

Senior Devvie

money is the worst drug- we should not let it rule

 « Reply #2 - Posted 2005-03-29 05:07:35 »

I checked the Java3D forums, where I also posted it and they said, that they know this problem and that we should use Transform3D's instead.  But I don't think this is a good idea for us, because we would have to get the Transform3D from Java3D or xith3d.
It would be better if somebody knows how we could do the transformation without the matrix.

:: JOODE :: Xith3d :: OdeJava ::
 Games published by our own members! Check 'em out!
darkprophet

Senior Devvie

Go Go Gadget Arms

 « Reply #3 - Posted 2005-03-29 11:36:08 »

Well, we have this base covered a long time ago in jME-Physics. Because we didn't rely on using vecmath, we used jme's math stuff (TransformQuatMatrix), we were ok.

Why dont you just have a couple of Vector3f and a Quaternion in there instead of that matrix4f? This is how we solved it (more or less...)

DP

Friends don't let friends make MMORPGs.

Blog | Volatile-Engine
arne

Senior Devvie

money is the worst drug- we should not let it rule

 « Reply #4 - Posted 2005-03-29 12:54:55 »

Quote
Well, we have this base covered a long time ago in jME-Physics. Because we didn't rely on using vecmath, we used jme's math stuff (TransformQuatMatrix), we were ok.

Why dont you just have a couple of Vector3f and a Quaternion in there instead of that matrix4f? This is how we solved it (more or less...)

DP

Thanks for the reply.
The GeomTransform multiplies two transforms (the one of the Body and the one of the EncapsulatedGeom). With Matrices this is simply matrix.mul(anotherMatrix).
How can we do this with a Vector and a Quat ?
How did you do this?

Arne

:: JOODE :: Xith3d :: OdeJava ::
darkprophet

Senior Devvie

Go Go Gadget Arms

 « Reply #5 - Posted 2005-03-29 13:45:02 »

Right, well, i dont multiply em! lol, and it works:

 1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99  100  101  102  103  104  105  106  107  108  109  110  111  112  113  114  115  116  117  118  119  120  121  122  123  124  125  126  127  128  129  130  131  132  133  134  135  136  137  138  139  140  141  142  143  144  145  146  147  148  149  150  151  152  153  154  155  156  157  158  159  160  161  162  163  164  165  166  167  168  169  170  171  172  173  174  175  176  177  178  179  180  181  182  183  184  185  186  187  188  189  190  191  192  193  194  195  196  197  198  199  200  201  202  203  204  205  206  207  208  209  210  211  212  213  214  215  216  217  218  219  220  221  222  223  224  225  226  227  228  229  230  231  232  233  234  235  236  237  238  239  240  241  242  243  244  245  246  247  248  249  250  251  252  253  254  255 ` * Copyright (c) 2004, William Denniss. 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 William Denniss nor the names of * 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) A * RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE * */package org.odejava;import org.odejava.ode.*;import com.jme.math.Quaternion;import com.jme.math.TransformMatrixQuat;import com.jme.math.Vector3f;/** *

The GeomTransform is a geom which encapsulates a Geom, allowing the encapsulated Geom to be transformed * relitive to it.  The GeomTransform can then be added to a Body.

* *

Please refer to the ODE Documentation * for more information.  An example in ODE code exists here

* *

It is a non-placable geometry, therefor the transform setters * must not be called.  However the transform getters may be called.  As it is * non-placable, the getters don't simply delegate the call to ODE.  Rather they * return the world transform of the encapsulated Geom (that is, the transform * of the parent body multiplied by that of the encapsulated Geom).  Subsiquently, * you can bind GeomTransform objects to Display objects.

* * @author William Denniss */public class GeomTransform extends PlaceableGeom {    private PlaceableGeom encapsulatedGeom;    private TransformMatrixQuat cachedBodyTransform = new TransformMatrixQuat();    private TransformMatrixQuat cachedTmpTransform = new TransformMatrixQuat();    /**     * Creates a GeomTransform with no name.     *     * @ode dCreateGeomTransform creates the object     */    public GeomTransform() {        this("");    }    /**     * Greats a GeomTransform with the given name     *     * @param name the name of this Geom     *     * @ode dCreateGeomTransform creates the object     */    public GeomTransform(String name) {        super(name);        spaceId = Ode.getPARENTSPACEID_ZERO();        geomId = Ode.dCreateGeomTransform(spaceId);        updateNativeAddr();    }    /**     * Sets the encapsulated Geom.     *     * @param obj the geom this GeomTransform encapsulates.     *          This Geom should not be added to any Space or associated     *          with any Body.     * @ode dGeomTransformSetGeom sets the encapsulated geom     */    public void setEncapsulatedGeom(PlaceableGeom obj) {        if (encapsulatedGeom != null) {            throw new IllegalOdejavaOperation("Attempt to assign a second Encapsulated geom.  GeomTransform can only have one encapsualted Geom.");        }        encapsulatedGeom = obj;        Ode.dGeomTransformSetGeom(geomId, obj.getId());        encapsulatedGeom.isEncapsulated = true;    }    /**     * Removes the encapsulate Geom.     *     * @dGeomTransformSetGeom     */    public void removeEncapsulatedGeom() {        Ode.dGeomTransformSetGeom(geomId, new SWIGTYPE_p_dGeomID(0, false));        encapsulatedGeom.isEncapsulated = false;        encapsulatedGeom = null;    }    /**     * Returns the encapsulated geometry.     *     * @return the encapsulated geometry.     */    public PlaceableGeom getEncapsulatedGeom() {        return encapsulatedGeom;    }    /**     * Returns the world position of the encapsulated     * geometry.  This is calcualted by multiplying the     * transform matrix of the parent body with the offset     * transform of the encapsulated geom.  To get the     * offset of the encapsulated geom - call getPosition on     * it.     *     * @return the world position of the encapsulated     * geometry     *     * @throws IllegalOdejavaOperation if this GeomTransform doesn't     *         have a parent body or doesn't have an encapsulated Geom     *     * @see updateCachedTransform     */    public Vector3f getPosition() {        return getPosition(new Vector3f());    }    /**     * Returns the world position of the encapsulated     * geometry.  This is calcualted by multiplying the     * transform matrix of the parent body with the offset     * transform of the encapsulated geom.  To get the     * offset of the encapsulated geom - call getPosition on     * it.     *     * @param result Vector3f to write the result to     *     * @return the world position of the encapsulated     * geometry     *     * @throws IllegalOdejavaOperation if this GeomTransform doesn't     *         have a parent body or doesn't have an encapsulated Geom     *     * @see updateCachedTransform     */    public Vector3f getPosition(Vector3f result) {        updateCachedTransform();        cachedBodyTransform.getTranslation(result);        return result;    }    /**     * Returns the world quaternion of the encapsulated     * geometry.  This is calcualted by multiplying the     * transform matrix of the parent body with the offset     * transform of the encapsulated geom.  To get the     * offset of the encapsulated geom - call getQuaternion on     * it.     *     * @param result Quat4f to write the result to     *     * @return the world quaternion of the encapsulated     * geometry     *     * @throws IllegalOdejavaOperation if this GeomTransform doesn't     *         have a parent body or doesn't have an encapsulated Geom     *     * @see updateCachedTransform     */    public Quaternion getQuaternion() {        return getQuaternion(new Quaternion());    }    /**     * Returns the world quaternion of the encapsulated     * geometry.  This is calcualted by multiplying the     * transform matrix of the parent body with the offset     * transform of the encapsulated geom.  To get the     * offset of the encapsulated geom - call getQuaternion on     * it.     *     * @return the world quaternion of the encapsulated     * geometry     *     * @throws IllegalOdejavaOperation if this GeomTransform doesn't     *         have a parent body or doesn't have an encapsulated Geom     *     * @see updateCachedTransform     */    public Quaternion getQuaternion(Quaternion result) {        updateCachedTransform();        cachedBodyTransform.getRotation(result);        return result;    }          /**     * Called by the transform getters.  Gets the     * transform of the parent Body and     * multiplies it by the transform of the encapsulated     * Geom.  The result is stored in the field     * cachedBodyTransform.     *     * @throws IllegalOdejavaOperation if this GeomTransform doesn't     *         have a parent body or doesn't have an encapsulated Geom     */    protected void updateCachedTransform() {        if (this.getBody() == null) {            throw new IllegalOdejavaOperation("This GeomTransform must be added to a body before its transform getters can be called.");        }        if (encapsulatedGeom == null) {            throw new IllegalOdejavaOperation("This GeomTransform must encapsulate a Geom before its transform getters can be called.");        }        cachedBodyTransform.loadIdentity();        cachedTmpTransform.loadIdentity();        cachedBodyTransform.setRotationQuaternion(this.getBody().getQuaternion());        cachedBodyTransform.setTranslation(this.getBody().getPosition());        cachedTmpTransform.setRotationQuaternion(encapsulatedGeom.getQuaternion());        cachedTmpTransform.setTranslation(encapsulatedGeom.getPosition());        //cachedBodyTransform.mul(cachedTmpTransform);    }}`

Friends don't let friends make MMORPGs.

Blog | Volatile-Engine
darkprophet

Senior Devvie

Go Go Gadget Arms

 « Reply #6 - Posted 2005-03-29 13:46:24 »

 1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99  100  101  102  103  104  105  106  107  108  109  110  111  112  113  114  115  116  117  118  119  120  121  122  123  124  125  126  127  128  129  130  131  132  133  134  135  136  137  138  139  140  141  142  143  144  145  146  147  148  149  150  151  152 `package com.jme.math;import com.jme.scene.Spatial;/** * Started Date: Jul 16, 2004

* Same as TransformMatrix, but stores rotations as quats, not Matrix3f.  This is faster for interpolation, but slower * than a matrix using Matrix3f for rotation when doing point translation. * @author Jack Lindamood */public class TransformMatrixQuat {    private Quaternion rot=new Quaternion();    private Vector3f translation=new Vector3f();    private Vector3f scale=new Vector3f(1,1,1);    /**     * Sets this rotation to the given Quaternion value.     * @param rot The new rotation for this matrix.     */    public void setRotationQuaternion(Quaternion rot) {        this.rot.set(rot);    }    /**     * Sets this translation to the given value.     * @param trans The new translation for this matrix.     */    public void setTranslation(Vector3f trans) {        this.translation.set(trans);    }    /**     * Sets this scale to the given value.     * @param scale The new scale for this matrix.     */    public void setScale(Vector3f scale) {        this.scale.set(scale);    }    /**     * Stores this translation value into the given vector3f.  If trans is null, a new vector3f is created to     * hold the value.  The value, once stored, is returned.     * @param trans The store location for this matrix's translation.     * @return The value of this matrix's translation.     */    public Vector3f getTranslation(Vector3f trans) {        if (trans==null) trans=new Vector3f();        trans.set(this.translation);        return trans;    }    /**     * Stores this rotation value into the given Quaternion.  If quat is null, a new Quaternion is created to     * hold the value.  The value, once stored, is returned.     * @param quat The store location for this matrix's rotation.     * @return The value of this matrix's rotation.     */    public Quaternion getRotation(Quaternion quat) {        if (quat==null) quat=new Quaternion();        quat.set(rot);        return quat;    }    /**     * Stores this scale value into the given vector3f.  If scale is null, a new vector3f is created to     * hold the value.  The value, once stored, is returned.     * @param scale The store location for this matrix's scale.     * @return The value of this matrix's scale.     */    public Vector3f getScale(Vector3f scale) {        if (scale==null) scale=new Vector3f();        scale.set(this.scale);        return scale;    }    /**     * Sets this matrix to the interpolation between the first matrix and the second by delta amount.     * @param t1 The begining transform.     * @param t2 The ending transform.     * @param delta An amount between 0 and 1 representing how far to interpolate from t1 to t2.     */    public void interpolateTransforms(TransformMatrixQuat t1, TransformMatrixQuat t2, float delta) {        this.rot.slerp(t1.rot,t2.rot,delta);        this.translation.interpolate(t1.translation,t2.translation,delta);        this.scale.interpolate(t1.scale,t2.scale,delta);    }    /**     * Changes the values of this matrix acording to it's parent.  Very similar to the concept of Node/Spatial transforms.     * @param parent The parent matrix.     * @return This matrix, after combining.     */    public TransformMatrixQuat combineWithParent(TransformMatrixQuat parent) {        scale.multLocal(parent.scale);        rot.multLocal(parent.rot);        parent            .rot            .multLocal(translation)            .multLocal(parent.scale)            .addLocal(parent.translation);        return this;    }    /**     * Applies the values of this matrix to the given Spatial.     * @param spatial The spatial to be affected by this matrix.     */    public void applyToSpatial(Spatial spatial) {        spatial.getLocalScale().set(scale);        spatial.getLocalRotation().set(rot);        spatial.getLocalTranslation().set(translation);    }    /**     * Sets this matrix's translation to the given x,y,z values.     * @param x This matrix's new x translation.     * @param y This matrix's new y translation.     * @param z This matrix's new z translation.     */    public void setTranslation(float x,float y, float z) {        translation.set(x,y,z);    }    /**     * Sets this matrix's scale to the given x,y,z values.     * @param x This matrix's new x scale.     * @param y This matrix's new y scale.     * @param z This matrix's new z scale.     */     public void setScale(float x, float y, float z) {        scale.set(x,y,z);    }    /**     * Loads the identity.  Equal to translation=1,1,1 scale=0,0,0 rot=0,0,0,1.     */    public void loadIdentity() {        translation.set(0,0,0);        scale.set(1,1,1);        rot.set(0,0,0,1);    }    /**     * Sets this matrix to be equal to the given matrix.     * @param matrixQuat The matrix to be equal to.     */    public void set(TransformMatrixQuat matrixQuat) {        this.translation.set(matrixQuat.translation);        this.rot.set(matrixQuat.rot);        this.scale.set(matrixQuat.scale);    }}`

And thats it. Please note that the above TransformMatrixQuat is under the BSD license copyrighted jME.

Heh, this works fine for jme-physics, im not sure about you kerazze Xith dudes.

Friends don't let friends make MMORPGs.

Blog | Volatile-Engine
arne

Senior Devvie

money is the worst drug- we should not let it rule

 « Reply #7 - Posted 2005-03-29 14:09:00 »

Quote
Right, well, i dont multiply em! lol, and it works:

 1  2  3  4  5  6  7  8  9  10  11  12  13  14 `        cachedBodyTransform.loadIdentity();        cachedTmpTransform.loadIdentity();        cachedBodyTransform.setRotationQuaternion(this.getBody().getQuaternion());        cachedBodyTransform.setTranslation(this.getBody().getPosition());        cachedTmpTransform.setRotationQuaternion(encapsulatedGeom.getQuaternion());        cachedTmpTransform.setTranslation(encapsulatedGeom.getPosition());        //cachedBodyTransform.mul(cachedTmpTransform);    }}`

Yeah but you don't apply cachedTmpTransform to cachedBodyTransform either. Or have I missed something

:: JOODE :: Xith3d :: OdeJava ::
darkprophet

Senior Devvie

Go Go Gadget Arms

 « Reply #8 - Posted 2005-03-29 14:13:42 »

i know i dont. But it works fine somehow...

If you dont believe me, pull up the jme-physics (http://jme-physics.sourceforge.net) and run CompoundObjectTest...

DP

Friends don't let friends make MMORPGs.

Blog | Volatile-Engine
arne

Senior Devvie

money is the worst drug- we should not let it rule

 « Reply #9 - Posted 2005-03-29 15:11:29 »

Hi I looked at the code from CompoundedObjectTest, but it doesn't use GeomTransforms in anyway. Does jMe use this physics stuff indirecly - I mean a user doesn't call it directly ?
Can it then be that the GeomTransform (at least the one you printed) is not anymore used, so errors don't show up there?

Ps: You know I'm very sceptical, because when looking at the code there is no way it could work:
You set a TransformMatrixQuat, you don't use - what's this for - it can't have any use. You don't even use it in any other function there. I checked it by searching after "cachedTmpTransform"

:: JOODE :: Xith3d :: OdeJava ::
 Games published by our own members! Check 'em out!
darkprophet

Senior Devvie

Go Go Gadget Arms

 « Reply #10 - Posted 2005-03-30 09:03:14 »

Quote

Hi I looked at the code from CompoundedObjectTest, but it doesn't use GeomTransforms in anyway

Yes, it does use it, but as you said, indirectly.

Look at com.jmex.physics.PhysicsEntityFactory.createNode()

We definetly use GeomTransform. Oh yer, did you run the test? Does it work?

PS. I agree about the cacheTmp thing, it can be removed from our source.

PS2. I am really really crap at maths, so i really can't tell you why this works, all i can say that it does.

DP

Friends don't let friends make MMORPGs.

Blog | Volatile-Engine
arne

Senior Devvie

money is the worst drug- we should not let it rule

 « Reply #11 - Posted 2005-03-30 09:58:54 »

Quote

Yes, it does use it, but as you said, indirectly.

Look at com.jmex.physics.PhysicsEntityFactory.createNode()

We definetly use GeomTransform.

I looked at it, but PhysicsEntityFactory isn't used by the test. Is there maybe a Class extending PhysicsEntityFactory that's used ?
Quote

Oh yer, did you run the test? Does it work?

No I havent yet, because I don't really want to install jMe - I'm happy with xith .
Could you perhaps give me a JavaWebStart-Link, that shows this demo ?
Uhh and anothing thing: I've got an idea how we can test if it's used. You just simply have to put a System.out.println("blahblah") in the code. If it says "blahblah", we know it uses it.

Arne

:: JOODE :: Xith3d :: OdeJava ::
darkprophet

Senior Devvie

Go Go Gadget Arms

 « Reply #12 - Posted 2005-03-30 10:10:41 »

Arne, our approach to physics is very different from Odejava's. The test only creates a PhysicsWorld, and DynamicPhysicsObjects (and a floor which is a staticPhysicsObject). Tee rest happens behind the scenes without you knowing anything. So PhysicsEntityFactory is actually instantiated and created by PhysicsWorld.

Anyway, it is definetly created. And as for your webstart thing, i'l get on it.

DP

Friends don't let friends make MMORPGs.

Blog | Volatile-Engine
darkprophet

Senior Devvie

Go Go Gadget Arms

 « Reply #13 - Posted 2005-03-30 11:05:38 »

http://www.myjavaserver.com/~digiwired/physics.jnlp

There you go. Enjoy the physics show!

DP

Friends don't let friends make MMORPGs.

Blog | Volatile-Engine
arne

Senior Devvie

money is the worst drug- we should not let it rule

 « Reply #14 - Posted 2005-03-30 11:27:00 »

Thanks
It works fine

Makes the mystery only bigger

:: JOODE :: Xith3d :: OdeJava ::
darkprophet

Senior Devvie

Go Go Gadget Arms

 « Reply #15 - Posted 2005-03-30 13:28:51 »

 1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99  100  101  102  103  104  105  106  107  108  109  110  111  112  113  114  115  116  117  118  119  120  121  122  123  124  125  126  127  128  129  130  131  132  133  134  135  136  137  138  139  140  141  142  143  144  145  146  147  148  149  150  151  152  153  154  155  156  157  158  159  160  161  162  163  164  165  166  167  168  169  170  171  172  173  174  175  176  177  178  179  180  181  182  183  184  185  186  187  188  189  190  191  192  193  194  195  196  197  198  199  200  201  202  203  204  205  206  207  208  209  210  211  212  213  214  215 `package org.odejava;import org.odejava.ode.*;import com.jme.math.Quaternion;import com.jme.math.TransformMatrixQuat;import com.jme.math.Vector3f;/** *

The GeomTransform is a geom which encapsulates a Geom, allowing the encapsulated Geom to be transformed * relitive to it.  The GeomTransform can then be added to a Body.

* *

Please refer to the ODE Documentation * for more information.  An example in ODE code exists here

* *

It is a non-placable geometry, therefor the transform setters * must not be called.  However the transform getters may be called.  As it is * non-placable, the getters don't simply delegate the call to ODE.  Rather they * return the world transform of the encapsulated Geom (that is, the transform * of the parent body multiplied by that of the encapsulated Geom).  Subsiquently, * you can bind GeomTransform objects to Display objects.

* * @author William Denniss */public class GeomTransform extends PlaceableGeom {    private PlaceableGeom encapsulatedGeom;    private TransformMatrixQuat cachedBodyTransform = new TransformMatrixQuat();    /**     * Creates a GeomTransform with no name.     *     * @ode dCreateGeomTransform creates the object     */    public GeomTransform() {        this("");    }    /**     * Greats a GeomTransform with the given name     *     * @param name the name of this Geom     *     * @ode dCreateGeomTransform creates the object     */    public GeomTransform(String name) {        super(name);        spaceId = Ode.getPARENTSPACEID_ZERO();        geomId = Ode.dCreateGeomTransform(spaceId);        updateNativeAddr();    }    /**     * Sets the encapsulated Geom.     *     * @param obj the geom this GeomTransform encapsulates.     *          This Geom should not be added to any Space or associated     *          with any Body.     * @ode dGeomTransformSetGeom sets the encapsulated geom     */    public void setEncapsulatedGeom(PlaceableGeom obj) {        if (encapsulatedGeom != null) {            throw new IllegalOdejavaOperation("Attempt to assign a second Encapsulated geom.  GeomTransform can only have one encapsualted Geom.");        }        encapsulatedGeom = obj;        Ode.dGeomTransformSetGeom(geomId, obj.getId());        encapsulatedGeom.isEncapsulated = true;    }    /**     * Removes the encapsulate Geom.     *     * @dGeomTransformSetGeom     */    public void removeEncapsulatedGeom() {        Ode.dGeomTransformSetGeom(geomId, new SWIGTYPE_p_dGeomID(0, false));        encapsulatedGeom.isEncapsulated = false;        encapsulatedGeom = null;    }    /**     * Returns the encapsulated geometry.     *     * @return the encapsulated geometry.     */    public PlaceableGeom getEncapsulatedGeom() {        return encapsulatedGeom;    }    /**     * Returns the world position of the encapsulated     * geometry.  This is calcualted by multiplying the     * transform matrix of the parent body with the offset     * transform of the encapsulated geom.  To get the     * offset of the encapsulated geom - call getPosition on     * it.     *     * @return the world position of the encapsulated     * geometry     *     * @throws IllegalOdejavaOperation if this GeomTransform doesn't     *         have a parent body or doesn't have an encapsulated Geom     *     * @see updateCachedTransform     */    public Vector3f getPosition() {        return getPosition(new Vector3f());    }    /**     * Returns the world position of the encapsulated     * geometry.  This is calcualted by multiplying the     * transform matrix of the parent body with the offset     * transform of the encapsulated geom.  To get the     * offset of the encapsulated geom - call getPosition on     * it.     *     * @param result Vector3f to write the result to     *     * @return the world position of the encapsulated     * geometry     *     * @throws IllegalOdejavaOperation if this GeomTransform doesn't     *         have a parent body or doesn't have an encapsulated Geom     *     * @see updateCachedTransform     */    public Vector3f getPosition(Vector3f result) {        updateCachedTransform();        cachedBodyTransform.getTranslation(result);        return result;    }    /**     * Returns the world quaternion of the encapsulated     * geometry.  This is calcualted by multiplying the     * transform matrix of the parent body with the offset     * transform of the encapsulated geom.  To get the     * offset of the encapsulated geom - call getQuaternion on     * it.     *     * @param result Quat4f to write the result to     *     * @return the world quaternion of the encapsulated     * geometry     *     * @throws IllegalOdejavaOperation if this GeomTransform doesn't     *         have a parent body or doesn't have an encapsulated Geom     *     * @see updateCachedTransform     */    public Quaternion getQuaternion() {        return getQuaternion(new Quaternion());    }    /**     * Returns the world quaternion of the encapsulated     * geometry.  This is calcualted by multiplying the     * transform matrix of the parent body with the offset     * transform of the encapsulated geom.  To get the     * offset of the encapsulated geom - call getQuaternion on     * it.     *     * @return the world quaternion of the encapsulated     * geometry     *     * @throws IllegalOdejavaOperation if this GeomTransform doesn't     *         have a parent body or doesn't have an encapsulated Geom     *     * @see updateCachedTransform     */    public Quaternion getQuaternion(Quaternion result) {        updateCachedTransform();        cachedBodyTransform.getRotation(result);        return result;    }          /**     * Called by the transform getters.  Gets the     * transform of the parent Body and     * multiplies it by the transform of the encapsulated     * Geom.  The result is stored in the field     * cachedBodyTransform.     *     * @throws IllegalOdejavaOperation if this GeomTransform doesn't     *         have a parent body or doesn't have an encapsulated Geom     */    protected void updateCachedTransform() {        if (this.getBody() == null) {            throw new IllegalOdejavaOperation("This GeomTransform must be added to a body before its transform getters can be called.");        }        if (encapsulatedGeom == null) {            throw new IllegalOdejavaOperation("This GeomTransform must encapsulate a Geom before its transform getters can be called.");        }        cachedBodyTransform.loadIdentity();        cachedBodyTransform.setRotationQuaternion(this.getBody().getQuaternion());    }}`

This also works.

PS. This is probably a workaround and not a solution. Tho i dont see why it isn't a solution...

Anyways, it works, and thats what matters...for now

DP

Friends don't let friends make MMORPGs.

Blog | Volatile-Engine
arne

Senior Devvie

money is the worst drug- we should not let it rule

 « Reply #16 - Posted 2005-03-30 13:40:00 »

Have you put a System.out.println("blabla") into the updateCachedTransform-Function? I really would like to know if it gets executed.

:: JOODE :: Xith3d :: OdeJava ::
ewills

Junior Devvie

Java skeletal animation systems rock!

 « Reply #17 - Posted 2005-03-30 14:29:11 »

The Matrices in GeomTransform are used only for the convenience getter functions to get position and rotation.  These getter functions are not called by Ode (I don't use them in my applications either), so this likely explains why the jME demo works.

As for a workaround, I suggest someone implementing a matrixToQuat method in GeomTransform until Matrix4f is fixed.  The matrix to quat formula is:

qx = (m21 - m12)/(4.0f*qw)
qy = (m02 - m20)/(4.0f*qw)
qz = (m10 - m01)/(4.0f*qw)
qw = sqrt(1.0f + m00 + m11 + m22)/2.0f

darkprophet

Senior Devvie

Go Go Gadget Arms

 « Reply #18 - Posted 2005-03-30 14:58:48 »

just done your sysout thing. And no, it doesn't get executed.

DP

Friends don't let friends make MMORPGs.

Blog | Volatile-Engine
arne

Senior Devvie

money is the worst drug- we should not let it rule

 « Reply #19 - Posted 2005-03-30 16:48:25 »

Quote

As for a workaround, I suggest someone implementing a matrixToQuat method in GeomTransform until Matrix4f is fixed.  The matrix to quat formula is:

qx = (m21 - m12)/(4.0f*qw)
qy = (m02 - m20)/(4.0f*qw)
qz = (m10 - m01)/(4.0f*qw)
qw = sqrt(1.0f + m00 + m11 + m22)/2.0f

I implemented your formular, but it doesn't work. I've got a body transform of 0,0,0,1
and a encapsulated transform of 0,0.707f,0.707f,0
and the result, the transform of the GeomTransform, is NaN,NaN,NaN,NaN like the vecmath result.
but (0,0,0,1).mul(0,0.707f,0.707f,0) = (0,0.707f,0.707f,0) , because (0,0,0,1) is the Identity rotation.

I wrote myself some code without the Matrix, it brings good results as the output, but in RunDemo - I'm testing my stuff with RunDemo, because I hope there are no errors there. But there still seems to be a problem with body rotations
When the body-rotation is the Identity rotation it works fine - not like the other code
 1  2  3  4  5  6  7  8  9  10 `        this.getBody().getQuaternion(tmpQuat);        this.getEncapsulatedGeom().getPosition(position);        rotation.set(position.x,position.y,position.z,0);        rotation.mul(tmpQuat);        position.set(rotation.x,rotation.y,rotation.z);        this.getBody().getPosition(tmpPos);        position.add(tmpPos);                this.getEncapsulatedGeom().getQuaternion(rotation);        rotation.mul(tmpQuat);`

Edit: position and rotation are the output values - the ones you get with getQuaternion and getPosition

:: JOODE :: Xith3d :: OdeJava ::
ewills

Junior Devvie

Java skeletal animation systems rock!

 « Reply #20 - Posted 2005-03-31 16:24:23 »

Hmm... sounds like the Matrix4f is being populated with NaNS.  The Matrix4f bug may be in the set(Quat4f q) method (instead or in addition to the bug in the get(Quat4f q) method).  You could try implementing set(Quat4f q).  The upper 3x3 is:

1 - 2*qy2 - 2*qz2        2*qx*qy - 2*qz*qw        2*qx*qz + 2*qy*qw
2*qx*qy + 2*qz*qw       1 - 2*qx2 - 2*qz2       2*qy*qz - 2*qx*qw
2*qx*qz - 2*qy*qw       2*qy*qz + 2*qx*qw       1 - 2*qx2 - 2*qy2

qy2, etc.. == qy squared or qy*qy.
arne

Senior Devvie

money is the worst drug- we should not let it rule

 « Reply #21 - Posted 2005-03-31 16:43:14 »

Ohh - I forgot to tell you:
The matrix created out of the rotation and translation from my function is the same as the one created by multiplying the two matrices.

I don't know if RunDemo or OdejavaToXith is working correctly, because OdejavaToXith is doing something special with Geomtransforms I don't understand. It adds another TransformGroup there. But shouldn't GeomTransform automatically return the correct Position transformed by the body and the Geom?

And something else that I want to get sure of:
(0, 0.707, 0.707, 0) is a valid Quat4f, isn't it? It get's normalized to (0, 0.70710677, 0.70710677, 0) I'm asking, because (0, 0.707107, 0.707107, 0) gets also normalized to the same value, but it doesn't create the NaNs. It creates a Quat4f of (0,0,0, ...E-4)

... means I don't know the exact numerals there.

Edit: I checked OdejavaToXith3D, but I think now, it works correctly.

:: JOODE :: Xith3d :: OdeJava ::
arne

Senior Devvie

money is the worst drug- we should not let it rule

 « Reply #22 - Posted 2005-04-01 04:35:08 »

Hi
I executed this code twice with only the modification of changing the b in line 10 to boxG and the boxG in line 12 to b:
 1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21  22  23 `1     Odejava.getInstance();2     world = new World();3     GeomBox boxG = new GeomBox(280, 60,240);4     GeomTransform t = new MyGeomTransform();5     t.setEncapsulatedGeom(boxG);6     Body b = new Body("boxBody",world);7     b.addGeom(t);8     b.adjustMass(1);9      10    b.setQuaternion(new Quat4f(0,0,0,1));11    boxG.setPosition(20, 600, 30);12    boxG.setQuaternion(new Quat4f(0,0.7071068f,0.7071068f,0));13    geoms.add(t);14    System.out.println("boxG: "+boxG.getQuaternion());15    System.out.println("t :"+t.getQuaternion());16    System.out.println("b :"+b.getQuaternion());17    System.out.println("Transform: "+t.getTransform());18    System.out.println("Rotation: "+t.getRotation());19    System.out.println("axisA: "+t.getAxisAngle());20    System.out.println();21    System.out.println("boxG: "+boxG.getPosition());22    System.out.println("t :"+t.getPosition());23    System.out.println("b :"+b.getPosition());`

 without modification: boxG: (0.0, 0.70710677, 0.70710677, 0.0)t :(0.0, 0.70710677, 0.70710677, 0.0)b :(0.0, 0.0, 0.0, 1.0)Transform: -0.9999999, 0.0, 0.0, 20.00.0, 5.9604645E-8, 0.99999994, 600.00.0, 0.99999994, 5.9604645E-8, 30.00.0, 0.0, 0.0, 1.0Rotation: -0.9999999, 0.0, 0.00.0, 5.9604645E-8, 0.999999940.0, 0.99999994, 5.9604645E-8axisA: (0.0, 0.70710677, 0.70710677, 3.1415927)     boxG: (20.0, 600.0, 30.0)t :(20.0, 600.0, 30.0)b :(0.0, 0.0, 0.0)-> Box is rotated. with modification: boxG: (0.0, 0.0, 0.0, 1.0)t :(0.0, 0.70710677, 0.70710677, 0.0)b :(0.0, 0.70710677, 0.70710677, 0.0)Transform: -0.9999999, 0.0, 0.0, 403.050870.0, 5.9604645E-8, 0.99999994, -14.1421360.0, 0.99999994, 5.9604645E-8, 14.1421360.0, 0.0, 0.0, 1.0Rotation: -0.9999999, 0.0, 0.00.0, 5.9604645E-8, 0.999999940.0, 0.99999994, 5.9604645E-8axisA: (0.0, 0.70710677, 0.70710677, 3.1415927)boxG: (20.0, 600.0, 30.0)t :(403.05087, -14.142136, 14.142136)b :(0.0, 0.0, 0.0)-> Box is not rotated.

The position of the Box is in both cases the same.

I think this is totally strange espacially because the rotation-output does not show any signs, that there might be differences, but RunDemo shows different rotations.
The positions are different, but RunDemo shows the same position.

My only conclusion is, that I've misunderstood something, or rundemo is not working correctly.

PS: The updateCachedTransform is used. I've checked that.

:: JOODE :: Xith3d :: OdeJava ::
arne

Senior Devvie

money is the worst drug- we should not let it rule

 « Reply #23 - Posted 2005-04-02 06:36:13 »

Ok I've solved now why it wasn't shown correctly I called world.step() and that somehow resetted the rotation of the body. Now I can start checking for errors in my transformation code .

:: JOODE :: Xith3d :: OdeJava ::
arne

Senior Devvie

money is the worst drug- we should not let it rule

 « Reply #24 - Posted 2005-04-02 08:02:28 »

Hi
I wrote now some code to do the multiplication of the translations. I use a matrix to transform the translation, but I simply multiply the Quats to get the result Quat.

 1  2  3  4  5  6  7  8  9  10  11 `        this.getBody().getQuaternion(tmpQuat);        this.getEncapsulatedGeom().getPosition(position);        cachedBodyTransform.setIdentity();        cachedBodyTransform.set(tmpQuat);        cachedBodyTransform.transform(position);        this.getBody().getPosition(tmpPos);        position.add(tmpPos);                this.getEncapsulatedGeom().getQuaternion(rotation);        this.getBody().getQuaternion(tmpQuat);        rotation.mul(tmpQuat);`

I think this is a good workaround for the bug , but I haven't been able to test it completely . I'd like to know if it also works for you.

Arne

PS: I have created a subclass of GeomTransform, to do this, because I wasn't able to compile the odejava src - something with the xode stuff sucked - It wasn't able to find some Classes there. It would be good if someone did the changes also to the GeomTransform directly.

Edit: I also think this way not so much garbage gets created.

:: JOODE :: Xith3d :: OdeJava ::
arne

Senior Devvie

money is the worst drug- we should not let it rule

 « Reply #25 - Posted 2005-04-09 06:41:45 »

Holy crap - it's no bug at all - at least it shows correctly, when Joints are used and the simulation proceeds - the code I wrote doesn't work there. So I'm going back to using the old GeomTransform - And with having one big mystery more ...

:: JOODE :: Xith3d :: OdeJava ::
Pages: [1]
 ignore  |  Print

You cannot reply to this message, because it is very, very old.

 Waterwolf (23 views) 2015-05-20 15:01:45 chrislo27 (27 views) 2015-05-20 03:42:21 BurntPizza (63 views) 2015-05-10 15:53:18 FrozenShade (47 views) 2015-05-07 09:11:21 TheLopais (210 views) 2015-05-06 13:36:48 TheLopais (194 views) 2015-05-06 13:35:14 TheLopais (201 views) 2015-05-06 13:33:39 TheLopais (220 views) 2015-05-06 13:32:48 TheLopais (216 views) 2015-05-06 13:31:28 ClaasJG (238 views) 2015-04-30 20:33:25
 Spasi 31x BurntPizza 16x theagentd 13x DavidBVal 13x ra4king 12x EgonOlsen 11x Husk 10x KevinWorkman 9x princec 8x scanevaro 8x opiop65 7x KaiHH 7x revers 6x Riven 6x HeroesGraveDev 5x MrPork 5x
 List of Learning Resources2015-05-05 10:20:32How to: JGO Wikiby Mac702015-02-17 20:56:162D Dynamic Lighting2015-01-01 20:25:42How do I start Java Game Development?by gouessej2014-12-27 19:41:21Resources for WIP gamesby kpars2014-12-18 10:26:14Understanding relations between setOrigin, setScale and setPosition in libGdx2014-10-09 22:35:00Definite guide to supporting multiple device resolutions on Android (2014)2014-10-02 22:36:02List of Learning Resources2014-08-16 10:40:00
 java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org