Page MenuHome

Negative scale in 1 axis of a child causes animations export incorrectly with wrong scales
Closed, ArchivedPublic

Description

System Information
Windows 10, Nvidia 950M

Blender Version
Broken: 2.68.0 r58537, it is not a new bug, it was happening in older versions also

Short description of error
object.matrix_local.to_scale() is returning the wrong result when you have a child object that has 1 axis with a negative scale.

Exact steps for others to reproduce the error
Have an object that is connected to 1 or more parents.
Set the x axis scale to -1 (to mirror the part)
Add 2 rotation animation frames to that part.
Export the file (either Collada and Direct X)
Open the file in Open 3D Model Viewer and check the animation to see that it is wrong.

I have included images of the start and end frame in both blender and open 3d viewer to show exactly what is wrong.

I took a look at the python script in the included Direct X exporter and I found the line that the problem happens.
it has just executed
Scene.frame_set(Frame)
then it attempts to get the scale
Scale = BlenderObject.matrix_local.to_scale()
And the returned result of this line is wrong, it has negative scale for all 3 axis, instead of just the x axis.

If I check the value of the matrix local using
print("{:9f},{:9f},{:9f},".format(BlenderObject.matrix_local[0][0],BlenderObject.matrix_local[1][1], BlenderObject.matrix_local[2][2]))
it shows correctly a negative, then 2 positives as it should.

Event Timeline

Bastien Montagne (mont29) changed the task status from Unknown Status to Archived.Feb 28 2016, 8:32 PM
Bastien Montagne (mont29) claimed this task.

There is no “right” or “wrong” result, it is mathematically impossible to “correctly” decompose a negative matrix (to simplify, because it’s impossible to distinguish between a 180° rotation and a -1 scaling along an axis). So thanks for the report, but no bug here.

PS: fyi, current official blender version is 2.76 (and we are about to release 2.77)…

blender knows that the part has a negative matrix, in the exporters there should be logic to detect this case and create animation sets that render the objects in the correct location

Rowan Harris (RowanHarris) changed the task status from Archived to Unknown Status.Mar 1 2016, 12:01 AM

It is a valid bug, the animation sets produced on export are not valid when you have a negative axis scale and a parent object

@Bastien Montagne (mont29), while you cant tell the difference between negative scale and rotation, Blender will decompose giving compatible scale+rotation which will give the same result.

@Rowan Harris (RowanHarris), this is more a TODO then a bug. if authors of exporters have time to support this corner case.

this is the problem, it is not giving a compatible scale + rotation, as you can see in the images the export for collada gives a different wrong animation result than what is in blender. Direct X exporter also gives the identical result

Bastien Montagne (mont29) changed the task status from Unknown Status to Archived.Mar 1 2016, 2:26 PM

First of all, please do not reopen tasks that way. This issue you reported was invalid, again you cannot get a 'valid' scale value from decomposition of negative matrix.

As Campbell said, problem here is with exporters handling of negative (inverse of) parent matrix, which has to be reported on case by case, one report for each affected exporter, such that we can assign them to relevant maintainer. This is not a blender bug (e.g., FBX exporter seems to handle that case nice - for once :P).

Blender TODO here could be that (infamous) 'IO helper' toolset, to ease IO scripts task when fiddling with all those nasty matrix transforms…

not sure if anyone actually is interested...but I fixed the bug in the export script after fumbling around with python for 4 hours and learning the blender commands
in the file export_x.py

the fix is to use

Position, Rotation, Scale = BlenderObject.matrix_local.decompose()

instead of

Rotation = BlenderObject.rotation_euler.to_quaternion()
Scale = BlenderObject.matrix_local.to_scale()
Position = BlenderObject.matrix_local.to_translation()