Closed stephengold closed 11 months ago
Given how limited the support for scaling is in JME, I suggest just marking this as a limitation.
I know the source of your discovery comes from interpreting scales from loaded models but we already don't support a variety of scaling. (For example, because JME doesn't really support non-uniform scaling anywhere except at the leaf Geometry.) So even if we were to somehow fix this issue in Matrix, it's not really going to solve the model interpretation issue which is effectively impossible.
An even number of -1 scaling factors is equivalent to a rotation.
Using that insight, here's a workaround for Transform.fromTransformMatrix(Matrix4f)
:
Transform result = new Transform();
float determinant = matrix4f.determinant();
if (determinant < 0f) {
matrix4f.m00 *= -1f;
matrix4f.m10 *= -1f;
matrix4f.m20 *= -1f;
}
result.fromTransformMatrix(matrix4f);
if (determinant < 0f) {
result.getScale().x *= -1f;
}
An even number of -1 scaling factors is equivalent to a rotation.
Math is not my strong point, but would a scaling factor of -1 not only rotate the model, but turn it inside out?
An even number of -1 scaling factors is equivalent to a rotation.
Math is not my strong point, but would a scaling factor of -1 not only rotate the model, but turn it inside out?
You're right. It would turn a model inside-out. That would be something for the caller to address, if such a transform were ever applied to a mesh or model.
However, com.jme3.math
doesn't deal with meshes or models, so Transform
and Matrix4f
don't deal with the concept of inside-out.
com.jme3.math breaks in many places if scale factors are allowed to be negative. For instance,
Matrix4f.toScaleVector(Vector3f)
assigns a (positive) square root to each component:https://github.com/jMonkeyEngine/jmonkeyengine/blob/a94c37aa732b387c153d6c113e37155c0f40f320/jme3-core/src/main/java/com/jme3/math/Matrix4f.java#L1861-L1873
As a consequence of this bug (or undocumented assumption) the zero-argument
Matrix4f.oScaleVector()
method is also broken, as isTransform.fromTransformMatrix(Matrix4f)
.Here is a code fragment that demonstrates those breakages:
If this issue were solved, the transforms
a
andb
would be approximately equal, as would the vectorsscaleA
andscaleB
. Instead, we get:There's a similar assumption of positive scale factors in
Quaternion.fromRotationMatrix()
, which rejects scaling but only if all the scale factors are positive.Directly or indirectly, JMonkeyEngine uses these methods in many places, notably
Transform.invert()
, which is similarly broken, as demonstrated by the following code fragment:If this issue were solved, the transforms
a
andc
would be approximately equal. Instead, we get:If a matrix contains an odd number of negative scale factors, the fact can be detected using determinants. However, I don't know an easy way to detect an even number of negative scale factors.