Hey @bghgary and @Deltakosh and @sebavan … I am starting to notice something i dont really like in the GLTF Handness.
Every where in the C# Unity GLTF Exporter when dumping out position and rotation we SWITCH the handness. For example, this is out i dump out the node transform position in C#
Vector3 position = useLocal ? nodeTransform.localPosition : nodeTransform.position;
node.Translation = new XGLTF.Math.Vector3(position.x, position.y, -position.z);
// ..
Quaternion rotation = useLocal ? nodeTransform.localRotation : nodeTransform.rotation;
node.Rotation = new XGLTF.Math.Quaternion(rotation.x, rotation.y, -rotation.z, -rotation.w);
Notice the position.z, rotation.z and rotation.w always get NEGATED.
And every where i am using my ExportAccessor i can SWITCH the Handedness for positions and rotations.
public static Vector3 SwitchHandedness(this Vector3 input)
{
return new Vector3(input.x, input.y, -input.z);
}
public static Vector4 SwitchHandedness(this Vector4 input)
{
return new Vector4(input.x, input.y, -input.z, -input.w);
}
public static Quaternion SwitchHandedness(this Quaternion input)
{
return new Quaternion(input.x, input.y, -input.z, -input.w);
}
public static Matrix4x4 SwitchHandedness(this Matrix4x4 matrix)
{
Vector3 position = matrix.GetColumn(3).SwitchHandedness();
Quaternion rotation = Quaternion.LookRotation(matrix.GetColumn(2), matrix.GetColumn(1)).SwitchHandedness();
Vector3 scale = new Vector3(matrix.GetColumn(0).magnitude, matrix.GetColumn(1).magnitude, matrix.GetColumn(2).magnitude);
float epsilon = 0.00001f;
// Some issues can occurs with non uniform scales
if (Mathf.Abs(scale.x - scale.y) > epsilon || Mathf.Abs(scale.y - scale.z) > epsilon || Mathf.Abs(scale.x - scale.z) > epsilon)
{
Debug.LogWarning("A matrix with non uniform scale is being converted from left to right handed system. This code is not working correctly in this case");
}
// Handle negative scale component in matrix decomposition
if (Matrix4x4.Determinant(matrix) < 0)
{
Quaternion rot = Quaternion.LookRotation(matrix.GetColumn(2), matrix.GetColumn(1));
Matrix4x4 corr = Matrix4x4.TRS(matrix.GetColumn(3), rot, Vector3.one).inverse;
Matrix4x4 extractedScale = corr * matrix;
scale = new Vector3(extractedScale.m00, extractedScale.m11, extractedScale.m22);
}
// convert transform values from left handed to right handed
return Matrix4x4.TRS(position, rotation, scale);
}
}
then and example ExportAccessor function support switching the handedness:
private AccessorId ExportAccessor(Vector3[] arr, bool switchHandedness=false, string accessorName = null)
{
var count = arr.Length;
if (count == 0)
{
throw new Exception("Accessors can not have a count of 0.");
}
var accessor = new Accessor();
accessor.ComponentType = GLTFComponentType.Float;
accessor.Count = count;
accessor.Type = GLTFAccessorAttributeType.VEC3;
accessor.Name = accessorName;
List<Vector3> values = new List<Vector3>();
foreach (var vec in arr) { values.Add(switchHandedness ? vec.SwitchHandedness() : vec); }
accessor.Min = new List<double> { values.Select(value => value.x).Min(), values.Select(value => value.y).Min(), values.Select(value => value.z).Min() };
accessor.Max = new List<double> { values.Select(value => value.x).Max(), values.Select(value => value.y).Max(), values.Select(value => value.z).Max() };
var byteOffset = _bufferWriter.BaseStream.Position;
foreach (var vec in values) {
_bufferWriter.Write(vec.x);
_bufferWriter.Write(vec.y);
_bufferWriter.Write(vec.z);
}
var byteLength = _bufferWriter.BaseStream.Position - byteOffset;
accessor.BufferView = ExportBufferView((int)byteOffset, (int)byteLength);
var id = new AccessorId {
Id = _root.Accessors.Count,
Root = _root
};
_root.Accessors.Add(accessor);
return id;
}
That is the GLTF Spec i suppose… So the Babylon does a conversion on the position and rotation when importing GLTF scene file.
Now if using ALL GEOMETRY and CAMERAS AND LIGHTS coming from the GLTF scene file everything is fine.
But id i manually add geometry using code i gotta INVERT the position and rotation to get the same result.
Example… i have a plane and a cube at zero position in scene. In unity, i would make a Camera at position 0,1,-10 and rotation 0,0,0… That camera would be backup on the Z axis 10 units and it show the cube on plane just fine.
If i make the camera in code, for it to show the cube and plane at zero… i have to make the camera in code with position 0,1,10 and rotation 0, Math.PI, 0
Its like i have to think inverted of what i would normally expect a camera 10 units back on the Z-Axis
i think that is gonna be problem when write game mechanic code and where you expect to position and rotate things… I would think.
Is there a way to tell BABYLON GLTF parser NOT to invert the positions and rotations and i will export from Unity C# WITHOUT switching the handedness… I know it would not be a standard GLTF… but maybe i can keep a flag on the scene extras metadata that says DONT switch handedness then in the Babylon GLTF Extension i check that flag BEFORE i start parsing the seen and setup babylon gltf to NOT switch the handedness… Just positions and rotations as is.
What do you think i should do about this in the toolkit ???