Spatials that use matrices

Hi all,



I am reviewing jMonkeyEngine as a possible replacement for our current rendering system.

I have come across a few questions but I'll simply start with this one:



We often manipulate matrices in our transform hierarchy "directly", for various reasons, but let's just use the example of skewing an object, i.e. non-orthogonal matrix.  A real world example of using this could be with instancing plant and terrain features in the static case, and for cartoony character motion in the case of animations.



Since the jME Spatial class is quat based and quat can not represent skew matrices, where can I manipuate the backing matrice directly (in the source code I see there is no backing matrix in Spatial) and/or is there another type of Spatial I am missing or where I can do this.



Thanks for any help






Currently there is no API in jME to manipulate the transformation matrices for a Spatial directly. For Nodes (Spatials containing other Spatials) even non-uniform scale is not supported (can be set, but does not give consistent results concerning mesh positions and point transformations). Of course a shear or direct matrix override could be introduced, if it's really important for you (if not in the official version it could at least be done locally with a few lines of code) …

Yes it is important to us for other reasons…

For example, we have lots of graph behaviors that use scene information to create matrix transforms "from scratch". and it seems like a waste to convert to Quats (where we would lose the scale and skew) just to have the engine internals convert that back to a matrix for rendering.


irrisor said:

Currently there is no API in jME to manipulate the transformation matrices for a Spatial directly. For Nodes (Spatials containing other Spatials) even non-uniform scale is not supported (can be set, but does not give consistent results concerning mesh positions and point transformations). Of course a shear or direct matrix override could be introduced, if it's really important for you (if not in the official version it could at least be done locally with a few lines of code) ...


How exactly could this be done "locally", where does the render pipeline matrix state get exposed?
Again thanks for any help.

The state is not exposed. But you could add a new field 'overridingMatrix' to Spatial with a FloatBuffer and alter the code in LWJGLRenderer.doTransforms to use that matrix with glLoadMatrix instead of applying translation, rotation and scale if it is present, like this:

Index: jME/src/com/jme/scene/Spatial.java
===================================================================
--- jME/src/com/jme/scene/Spatial.java   (revision 1.126)
+++ jME/src/com/jme/scene/Spatial.java   Thu Oct 25 20:04:01 CEST 2007
@@ -34,6 +34,7 @@
 
 import java.io.IOException;
 import java.io.Serializable;
+import java.nio.FloatBuffer;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Stack;
@@ -837,4 +838,14 @@
         worldTranslation = new Vector3f();
         worldScale = new Vector3f(1.0f, 1.0f, 1.0f);
     }
+
+    private FloatBuffer overrideMatrix;
+
+    public FloatBuffer getOverrideMatrix() {
+        return overrideMatrix;
-}
No newline at end of file
+    }
+
+    public void setOverrideMatrix( FloatBuffer overrideMatrix ) {
+        this.overrideMatrix = overrideMatrix;
+    }
+}
No newline at end of file
Index: jME/src/com/jme/renderer/lwjgl/LWJGLRenderer.java
===================================================================
--- jME/src/com/jme/renderer/lwjgl/LWJGLRenderer.java   (revision 1.145)
+++ jME/src/com/jme/renderer/lwjgl/LWJGLRenderer.java   Thu Oct 25 20:04:01 CEST 2007
@@ -1480,8 +1478,15 @@
             RendererRecord matRecord = (RendererRecord) DisplaySystem.getDisplaySystem().getCurrentContext().getRendererRecord();
             matRecord.switchMode(GL11.GL_MODELVIEW);
            GL11.glPushMatrix();
-   
+
+            final FloatBuffer overrideMatrix = t.getOverrideMatrix();
+            if ( overrideMatrix != null )
+            {
+                GL11.glLoadMatrix( overrideMatrix );
+            }
+            else
+            {
-           Vector3f translation = t.getWorldTranslation();
+            Vector3f translation = t.getWorldTranslation();
            if (!translation.equals(Vector3f.ZERO))
                GL11.glTranslatef(translation.x, translation.y, translation.z);
    
@@ -1495,8 +1500,9 @@
            if (!scale.equals(Vector3f.UNIT_XYZ)) {
                GL11.glScalef(scale.x, scale.y, scale.z);
             }
-        }
-    }
+            }
+        }
+    }
    
     protected void undoTransforms(Spatial t) {
        if (!generatingDisplayList || (t.getLocks() & SceneElement.LOCKED_TRANSFORMS) != 0) {



This would be at the cost of an additional field for each spatial, thus I think it should not go into CVS. But if it's fine for you to use a patched version of jME you can go with it...

OK that's pretty cool, of course, we need to add local and global(world) matrices, just like the local and world position Vectors and Quats, and then the issue is that the two different kinds are not going to be in sync, so you really can't use the quats/etc.



Finally, if we did this how would it affect bounds tracking in the engine?  Wouldn't this kind of local change totally fail for view culling, sort order, etc.?

That's right, you'd need to compute the bounds differently. You would need to do that in GeomBatch.updateWorldBound (and in SharedBatch and TriangleBatch). But as you cannot simply apply a matrix here you would need to come up with methods in the bounding classes to adapt that matrix. Or you'd find approximated values for translation, scale and rotation - that's easier and does not need to have the actual jME source modified.



If you want to use jME's triangle accuracy collision detection you'd need to replace the transformations in the collision tree generator as well.


irrisor said:

That's right, you'd need to compute the bounds differently. You would need to do that in GeomBatch.updateWorldBound (and in SharedBatch and TriangleBatch). But as you cannot simply apply a matrix here you would need to come up with methods in the bounding classes to adapt that matrix. Or you'd find approximated values for translation, scale and rotation - that's easier and does not need to have the actual jME source modified.

If you want to use jME's triangle accuracy collision detection you'd need to replace the transformations in the collision tree generator as well.


That's sounds like pretty much a rewrite/parallel pipeline to able to use regular 4x4 matrices.
Damn, that's pretty much a deal breaker for us.
Thanks so much for your quick responses.

We have had requests on this from other people/companies as well, so this is something moving up on the priolist i believe. But it might have to wait until the first release on our way towards the 2.0…