Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (539)
Games in Android Showcase (132)
games submitted by our members
Games in WIP (601)
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 3597 times)
0 Members and 1 Guest are viewing this topic.
Offline 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 ::
Offline William Denniss

JGO Coder


Projects: 2


Fire at will


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

err... crap!

got a workaround?

Will.

Offline 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. Sad
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!
Legends of Yore - The Casual Retro Roguelike
Offline 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
Offline 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 ::
Offline 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;

/**
 * <p>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.</p>
 *
 * <p>Please refer to the <a href="http://opende.sourceforge.net/ode-latest-userguide.html#sec_10_7_7">ODE Documentation</a>
 * for more information.  An example in ODE code exists <a href="http://q12.org/pipermail/ode/2002-July/005462.html"> here</a></p>
 *
 * <p>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.</p>
 *
 * @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
Offline 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<br><br>
 * 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
Offline 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 Huh

:: JOODE :: Xith3d :: OdeJava ::
Offline 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
Offline 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!
Legends of Yore - The Casual Retro Roguelike
Offline 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
Offline 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 Smiley.
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 ::
Offline 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
Offline 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
Offline 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 Smiley

Makes the mystery only bigger Sad

:: JOODE :: Xith3d :: OdeJava ::
Offline 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;

/**
 * <p>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.</p>
 *
 * <p>Please refer to the <a href="http://opende.sourceforge.net/ode-latest-userguide.html#sec_10_7_7">ODE Documentation</a>
 * for more information.  An example in ODE code exists <a href="http://q12.org/pipermail/ode/2002-July/005462.html"> here</a></p>
 *
 * <p>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.</p>
 *
 * @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
Offline 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 ::
Offline 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

Offline 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
Offline 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 Sad
When the body-rotation is the Identity rotation it works fine - not like the other code Smiley
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 ::
Offline 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.
Offline 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 ::
Offline 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.0
0.0, 5.9604645E-8, 0.99999994, 600.0
0.0, 0.99999994, 5.9604645E-8, 30.0
0.0, 0.0, 0.0, 1.0

Rotation: -0.9999999, 0.0, 0.0
0.0, 5.9604645E-8, 0.99999994
0.0, 0.99999994, 5.9604645E-8

axisA: (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.05087
0.0, 5.9604645E-8, 0.99999994, -14.142136
0.0, 0.99999994, 5.9604645E-8, 14.142136
0.0, 0.0, 0.0, 1.0

Rotation: -0.9999999, 0.0, 0.0
0.0, 5.9604645E-8, 0.99999994
0.0, 0.99999994, 5.9604645E-8

axisA: (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 ::
Offline 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 Smiley I called world.step() and that somehow resetted the rotation of the body. Now I can start checking for errors in my transformation code Smiley.

:: JOODE :: Xith3d :: OdeJava ::
Offline 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 Grin, but I haven't been able to test it completely Sad. 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 ::
Offline 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.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

rwatson462 (30 views)
2014-12-15 09:26:44

Mr.CodeIt (20 views)
2014-12-14 19:50:38

BurntPizza (42 views)
2014-12-09 22:41:13

BurntPizza (76 views)
2014-12-08 04:46:31

JscottyBieshaar (37 views)
2014-12-05 12:39:02

SHC (51 views)
2014-12-03 16:27:13

CopyableCougar4 (48 views)
2014-11-29 21:32:03

toopeicgaming1999 (115 views)
2014-11-26 15:22:04

toopeicgaming1999 (103 views)
2014-11-26 15:20:36

toopeicgaming1999 (31 views)
2014-11-26 15:20:08
Resources for WIP games
by kpars
2014-12-18 10:26:14

Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50
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
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!