Blender up-axis and physics

I’m having some issues regarding imported blender models and the handling of physics.

This has already been described here.



Basically, the object is rotated by the importer to fix the up axis, but for physics purposes this is not the case. For me the result is that my car is launched over my bridge.



To fix this I’ve made the changes below to the mesh helper and the object helper.

In effect, instead of rotating the model, it rotates the meshes within the model.



The changes to MeshHelper had been submitted by Nehon previously, but on their own they caused problems with rotations of the objects within the model. This was already discussed here



My models were created with blender 2.5



[patch]

Index: src/blender/com/jme3/scene/plugins/blender/meshes/MeshHelper.java

===================================================================

— src/blender/com/jme3/scene/plugins/blender/meshes/MeshHelper.java (revision 8366)

+++ src/blender/com/jme3/scene/plugins/blender/meshes/MeshHelper.java (working copy)

@@ -498,7 +498,11 @@

List<Structure> mVerts = pMVert.fetchData(blenderContext.getInputStream());



for (int i = 0; i < verticesAmount; ++i) {



DynamicArray<Number> coordinates = (DynamicArray<Number>) mVerts.get(i).getFieldValue(“co”);


  •        vertices<i> = new Vector3f(coordinates.get(0).floatValue(), coordinates.get(1).floatValue(), coordinates.get(2).floatValue());<br />
    

+ if (blenderContext.getBlenderKey().isFixUpAxis()) {

+ vertices = new Vector3f(coordinates.get(0).floatValue(), coordinates.get(2).floatValue(), -coordinates.get(1).floatValue());

+ } else {

+ vertices = new Vector3f(coordinates.get(0).floatValue(), coordinates.get(1).floatValue(), coordinates.get(2).floatValue());

+ }

}

return vertices;

}

[/patch]

[patch]
Index: src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java
===================================================================
--- src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java (revision 8366)
+++ src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java (working copy)
@@ -309,13 +309,11 @@
size.get(1).floatValue() * scaleY,

size.get(2).floatValue() * scaleZ);



- //the root object is transformed if the Y axis is UP

- if(fixUpAxis && (pParent.isNull() || (parent!=null && !this.shouldBeLoaded(parent, blenderContext)))) {

- float y = translation.y;

- translation.y = translation.z;

- translation.z = -y;

- rotation = this.upAxisRotationQuaternion.mult(rotation);

- }

+ if (fixUpAxis) {

+ float y = translation.y;

+ translation.y = translation.z;

+ translation.z = -y;

+ }



//create the result

Transform t = new Transform(translation, rotation);

[/patch]

Yes, definitely a deficiency in how the blender loader rotates the model, it should rotate the mesh instead (basically transform its vertices). Sorry but I guess theres no fix but rotating and applying the rotation in blender atm. @Kaelthas: This needs to be addressed, the models can’t just have some local rotation when the y axis is “fixed”. This is about the best example why :slight_smile:

Hi Normen, the above changes should take care of it, at least for static models. I can imagine that animations might require some more work though.

The above solution works for me with Blender 2.5. Hopefully some other people can test it as well to see if it works for them and we can get this in.

Yeah, this whole transformation/rotation thing is a complicated beast… This simple form of applying the change in axes is already not quite working per se.

So far, we’ve rotated the meshes and the objects within the model. For static models I think we are there already. Rotating 90 degrees around the x axis results in switching the y and z values (And a ‘-’ added to one of them) so this is just taking a shortcut.

No its not enough. Think for example of a child spatial that is offset by z+10. It not only changes its rotation but also its location when its parent gets rotated around x. Generally having a local rotation for the children instead of a zero one would be okay though I think…

I’ve ran some more tests and there are still some issues. It seems I fixed the offset, but not the local child rotation.

I’m trying to fix that as well…

Ok, I’ve got a new patch for the ObjectHelper. With this all rotations and translations should be fixed. The last remaining issue is with scaling, this is still going wrong.

Below is the new patch:

[patch]

Index: src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java

===================================================================

— src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java (revision 8373)

+++ src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java (working copy)

@@ -308,15 +308,14 @@

Vector3f scale = new Vector3f(size.get(0).floatValue() * scaleX,



size.get(1).floatValue() * scaleY,



size.get(2).floatValue() * scaleZ);



+


  •   if(fixUpAxis) {<br />
    

+ float y = translation.y;

+ translation.y = translation.z;

+ translation.z = -y;

+ rotation = this.upAxisRotationQuaternion.inverse().mult(rotation).mult(upAxisRotationQuaternion).inverse();

+ }



- //the root object is transformed if the Y axis is UP

- if(fixUpAxis && (pParent.isNull() || (parent!=null && !this.shouldBeLoaded(parent, blenderContext)))) {

- float y = translation.y;

- translation.y = translation.z;

- translation.z = -y;

- rotation = this.upAxisRotationQuaternion.mult(rotation);

- }

-

//create the result

Transform t = new Transform(translation, rotation);

t.setScale(scale);

[/patch]

The whole translation thing should be done using Transforms and the combineWithParent() method, it considers location, rotation and scale.

I’m not certain what you suggest. These modifications are in the method that creates the Transform.

Yes, but it reinvents the wheel and makes the common mistakes while doing that (e.g. scale doesn’t work). The class “transform” has methods to handle combination of transforms (that is location,rotation,scale) that already have been debugged :wink: I explained that in one of @Kaelthas’ threads. Anyway if you can get scale into this go ahead…

Ok, this patch fixes scaling as well, as long as objects are not nested more than 2 deep.

For some reason it requires information from its parent to calculate the scale, but only the immediate parent is available.

Judging by the comments, this is an issue @Kaelthas had also encountered already.

To fix this might require a bit more work.



@Normen I agree that it would be best to use existing, tested code. I’m not certain if we could use that here though as we want to present the model to the application as if it had the y axis up.



[patch]

Index: src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java

===================================================================

— src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java (revision 8373)

+++ src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java (working copy)

@@ -306,17 +306,17 @@

float scaleY = (float) Math.sqrt(parentInv.m01 * parentInv.m01 + parentInv.m11 * parentInv.m11 + parentInv.m21 * parentInv.m21);



float scaleZ = (float) Math.sqrt(parentInv.m02 * parentInv.m02 + parentInv.m12 * parentInv.m12 + parentInv.m22 * parentInv.m22);



Vector3f scale = new Vector3f(size.get(0).floatValue() * scaleX,


  •   							  size.get(1).floatValue() * scaleY,<br />
    

- size.get(2).floatValue() * scaleZ);

+ size.get(1).floatValue() * scaleY,

+ size.get(2).floatValue() * scaleZ);

+

+ if(fixUpAxis) {

+ float y = translation.y;

+ translation.y = translation.z;

+ translation.z = -y;

+ rotation = this.upAxisRotationQuaternion.inverse().mult(rotation).mult(upAxisRotationQuaternion).inverse();

+ scale = new Vector3f(scale.x, scale.z, scale.y);

+ }



- //the root object is transformed if the Y axis is UP

- if(fixUpAxis && (pParent.isNull() || (parent!=null && !this.shouldBeLoaded(parent, blenderContext)))) {

- float y = translation.y;

- translation.y = translation.z;

- translation.z = -y;

- rotation = this.upAxisRotationQuaternion.mult(rotation);

- }

-

//create the result

Transform t = new Transform(translation, rotation);

t.setScale(scale);


[/patch]
2 Likes

Cool, thanks. The idea about using the transforms was to set the local transforms of the blender objects but switch the axes and then combine them. As its now it cannot work as each scaled parent affects all its children and their children so it has to be considered locally.

Your welcome! Although we’re not quite there yet, this should make some people happy. (At least me… :wink: )

@Normen If these patches are ok, could you commit them? (MeshHelper at the top and the final ObjectHelper) I don’t have those permissions.



Thanks!



Maarten