AsciiFBXExporterForUnity
AsciiFBXExporterForUnity copied to clipboard
Duplicate meshes are written to the FBX file once.
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.
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.
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.
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.
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.
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?
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());
}
Oh interesting. What do you mean by class based? Each type of structure has a its own class that then cane be serialized?
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();
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.
I just looked at the graph of the forks on this project and you've been busy @Zod-. Good work!
@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 The only thing my current fork doesn't support is textures compared to the original exporter.
@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.
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.