AsciiFBXExporterForUnity icon indicating copy to clipboard operation
AsciiFBXExporterForUnity copied to clipboard

Duplicate meshes are written to the FBX file once.

Open KellanHiggins opened this issue 9 years ago • 14 comments

To prevent FBX files from exporting excessively, the system should recognize the same geometry and not write it to the file twice. Instead use the FBX reference system to export it once and reference it multiple times.

KellanHiggins avatar Apr 16 '16 15:04 KellanHiggins

How would this work exactly? I would be interested in implementing this as I need to export a lot of similiar objects into a single fbx file. Are there any docs on this.

Zod- avatar Aug 29 '17 16:08 Zod-

Nvm figured it out. I'm using a name based id system with the full hierarchy name e.g. /RootObject.SomeChild.MeshContainer.Mesh to reference geometry ids in a dictionary so I can just reuse it instead of defining a new geometry element. This will work quite good for me as all my objects will be named the same but maybe could replace that name id with a hash of the mesh triangles to make it more generic.

Zod- avatar Aug 29 '17 17:08 Zod-

I'm not exactly sure how you hashed the mesh. Are you reading off of the mesh name? What if two meshes have the same name (as they often do in Unity).

I am also a little worried about passing around that Dictionary. Maybe a better way would be to build a list of all the meshes in the tree first and then write and link them later.

KellanHiggins avatar Nov 06 '17 01:11 KellanHiggins

In the end I used instance ids for everything. Every unity object has an instance id, which will be the same since the objects point to the same resources in case of meshes, materials and so on. There is no need to calculate hashes or generate any random ids including the ones for game object.

Zod- avatar Nov 06 '17 01:11 Zod-

Oh that is actually pretty good. Hadn't thought of using the Unity instance IDs. I am guessing that isn't in the pull request you linked above?

KellanHiggins avatar Nov 06 '17 01:11 KellanHiggins

Yeah I think I've never committed that. I ended up remaking the whole exporter with a class based structure for each object in the FBXDocument. Here's a snippet from the caching in that:

        private readonly FbxConnectionsNode _connections;
        private readonly HashSet<long> _geometryCache = new HashSet<long>();

        private void AddGeometry(GameObject root)
        {
            foreach (var transform in root.transform.EnumerateHierarchy())
            {
                var gameObject = transform.gameObject;
                var mesh = gameObject.GetMesh();
                if (mesh == null) { continue; }

                if (!_geometryCache.Contains(InstanceId(mesh)))
                {
                    ChildNodes.Add(new FbxGeometryNode(mesh));
                    _geometryCache.Add(InstanceId(mesh));
                }
                _connections.Add(InstanceId(gameObject), InstanceId(mesh));
            }
        }

        public static long InstanceId(Object obj)
        {
            return Mathf.Abs(obj.GetInstanceID());
        }

Zod- avatar Nov 06 '17 12:11 Zod-

Oh interesting. What do you mean by class based? Each type of structure has a its own class that then cane be serialized?

KellanHiggins avatar Nov 06 '17 16:11 KellanHiggins

Exactly, however I'm sure there is a way to improve this further because there are quite a lot of classes now. I also seperated the serialization from the hierarchy construction. On the first pass the complete hierarchy is generated, which also has the reference to cached gameobjects, meshes, materials and so on. Then afterwards that structure can be serialized and streamed directly into a file. It's also possible to do this in a seperate thread since I'm only accessing cached objects and not any unity api directly.

FbxDocument fbxDocument = new FbxDocument(gameObjects, "path");
IEnumerable<string> lines = FbxAsciiWriter.SerializeDocument(fbxDocument);
new Thread(() => { StreamToFile(lines); }).Start();

Zod- avatar Nov 06 '17 17:11 Zod-

Oh nice, that is a good idea. Glad I could get you on the right track, the FBX format is definitely pretty obtuse. I had considered classes but I wanted to get this out quick. Really like the separate thread.

KellanHiggins avatar Nov 06 '17 17:11 KellanHiggins

I just looked at the graph of the forks on this project and you've been busy @Zod-. Good work!

KellanHiggins avatar Nov 06 '17 17:11 KellanHiggins

@Zod- Does your fork support this usecase? I have a scene I need to export with hundreds of reused meshes. Without this feature it's not really feasible to export. Did you succeed in your fork to support this?

HelloKitty avatar Mar 12 '18 15:03 HelloKitty

@HelloKitty The only thing my current fork doesn't support is textures compared to the original exporter.

Zod- avatar Mar 12 '18 15:03 Zod-

@hellokitty I've been able to write a system so identical meshes aren't duplicated in a branch of this called the Unity To High Fedelity exporter. However it is a bit complex to move back into this branch. How much programming experience do you have. If you looked at that could you figure out how I did it there? I am a little slammed with my current projects.

KellanHiggins avatar Mar 12 '18 19:03 KellanHiggins

I did have caching in the old exporter at some point but using a different concept that didn't work quite as well as with the ids. It's not hard to modify to use the ids instead.

https://github.com/Zod-/UnityFBXExporter/commit/ee9209d1785cbec90598fc37049a0fc2e41d5690

Basically swap the string dictionary with a long hashset and use the logic above to get ids.

Zod- avatar Mar 13 '18 12:03 Zod-