atteneder / DracoUnity

Draco 3D Data Compression Unity Package
Apache License 2.0
247 stars 39 forks source link

Encoding/decoding produces a mirrored mesh #42

Closed Daniel4144 closed 2 years ago

Daniel4144 commented 2 years ago

Encoding or decoding a mesh mirrors the mesh along the x-axis, I could not determine which one flips the coordinates. The following sample code encodes and decodes a single triangle and displays the mesh before and after, they should be equal:

        Mesh mesh1 = new Mesh();
        mesh1.vertices = new Vector3[] { Vector3.right, Vector3.up, Vector3.forward };
        mesh1.triangles = new int[] { 0, 1, 2 };
        EncodeResult[] result = DracoEncoder.EncodeMesh(mesh1);

        Mesh mesh2 = await new DracoMeshLoader().ConvertDracoMeshToUnity(result[0].data);

        GameObject obj1 = new GameObject("before");
        obj1.AddComponent<MeshFilter>().sharedMesh = mesh1;

        GameObject obj2 = new GameObject("after");
        obj2.AddComponent<MeshFilter>().sharedMesh = mesh2;

        obj1.AddComponent<MeshRenderer>().sharedMaterial = new Material(Shader.Find("Standard"));
        obj2.AddComponent<MeshRenderer>().sharedMaterial = new Material(Shader.Find("Standard"));

The same happens for all meshes, not only in this sample with a single triangle.

DracoUnity version 4.0.2 Unity version version 2020.3.30f1

atteneder commented 2 years ago

@Daniel4144 thanks for reporting!

You're right, that's problematic indeed. Draco itself does not define coordinate space handedness whatsoever, but DracoUnity is most often used in a glTF context, where a coordinate system conversion happens upon decoding.

I need to have a closer look where exactly this happens.

Two solutions come to mind:

The latter seems more sound to me

atteneder commented 2 years ago

@Daniel4144 I had a close look. Space conversion already is an option for DracoMeshLoader:

public DracoMeshLoader(bool convertSpace = true) {
    this.convertSpace = convertSpace;
}

So in your example, try:

Mesh mesh2 = await new DracoMeshLoader(false).ConvertDracoMeshToUnity(result[0].data);

An option for encoding is still missing, but will be required for glTF export.

Daniel4144 commented 2 years ago

Thanks @atteneder for the help. I have missed that option, but that should work. I am using DracoUnity to save generated colliders and load them later and as a workaround I have scaled all colliders with -1 after loading, but the builtin option is way better.