Whinarn / UnityMeshSimplifier

Mesh simplification for Unity.
MIT License
1.76k stars 277 forks source link

Out of memory when SimplifyMesh a big model, any suggestion ? #65

Closed Summer006 closed 1 year ago

Summer006 commented 1 year ago

Hi I have a very big model file, vertex count 8810599, triangle count 13439326. My goal is import that model file at runtime (DONE) and run SimplifyMesh to make a reducing.

but when I execute SimplifyMesh, it throw "Out of memory" exception, at IncreaseCapacity function in ResizableArray.cs I debug a little,found IncreaseCapacity with size 40M.

Any suggestion with this issue?

ps: My PC has 16G DDR4 memory, if I add it to 64G will it help ?

Whinarn commented 1 year ago

Hi, so I haven't stayed up to date with this project for a while, and I don't have everything in my head anymore. But I checked the code and from what I can see, each vertex would take 120 bytes of memory, 92 bytes per triangle and then 8 bytes per ref (which will be at least the count of vertices but can grow).

With your numbers, you would run up to about 2.2 GB of memory based on my calculations. Of course this is without any .NET overhead, but I can't see that it would increase by too much more. I'm not sure what would increase the capacity to 40M. All ResizableArrays should be fixed size, except for the refs one.

And looking through the code it would double each time it tries to add new elements when the capacity isn't enough. Perhaps not ideal that the code isn't trying to preallocate some extra. But this might be why you see such a big capacity. I can see at least one bug where a supposed optimization to prevent the capacity growing when it doesn't have to here (it only copies, it doesn't reset the count of the array back to what it was, so it doesn't really end up save any memory). Anyhow, we are talking about 8 bytes per ref + potential .NET overhead. Not too big of a deal. 40 million refs would be under 400MB.

Unity itself chunks up a bit of RAM, and based on the OS that you are running, one would assume that you might not have that much spare. I'd personally say that 16GB is a bit low today. I think even 32GB would help, no need to go all the way up to 64GB. I cannot really give you more guidance than that, since it also depends on what else you have running on your machine.

I can say that I have never tested this with that big meshes, other than the one that was used as an example for the original algorithm that I ported, but I believe that it was a lot smaller than yours still. My idea with this package was to provide a simplifier that could run at runtime, and would be fast enough to not be a burden. But of course there might be use cases out there that I never considered. Anyhow, it should work, with enough RAM. While a fix of the bug I mentioned above could reduce some RAM allocated, I don't think it would actually solve your problem at all.

Just also have in mind that since this is at runtime, you must also consider the machine that would run the simplifier as well. If this is something that would end up being published somehow, where you cannot possibly know the specs of the client machine in advance (other than specified minimum requirements ofc).

I hope this helps!

Summer006 commented 1 year ago

Hi Whinarn:

Thank you very much (really).

1, looks like OutOfMemoryException occur at first Initialize , with set Vertices: (ps: IncreaseCapacity: 0 ==> 40317960)

OutOfMemoryException: Out of memory UnityMeshSimplifier.ResizableArray1[T].IncreaseCapacity (System.Int32 capacity) (at Assets/UnityMeshSimplifier/Runtime/Utility/ResizableArray.cs:137) UnityMeshSimplifier.ResizableArray1[T].Resize (System.Int32 length, System.Boolean trimExess, System.Boolean clearMemory) (at Assets/UnityMeshSimplifier/Runtime/Utility/ResizableArray.cs:166) UnityMeshSimplifier.MeshSimplifier.set_Vertices (UnityEngine.Vector3[] value) (at Assets/UnityMeshSimplifier/Runtime/MeshSimplifier.cs:289) UnityMeshSimplifier.MeshSimplifier.Initialize (UnityEngine.Mesh mesh) (at Assets/UnityMeshSimplifier/Runtime/MeshSimplifier.cs:2052) UnityMeshSimplifier.LODGenerator.SimplifyMesh (UnityEngine.Mesh mesh, System.Single quality, UnityMeshSimplifier.SimplificationOptions& options) (at Assets/UnityMeshSimplifier/Runtime/LODGenerator.cs:699)

2, Had test on a high performace PC with 64G memory, same issue, OutOfMemoryException . Strange thing: in my pc ( 16G mem), when OutOfMemoryException occur, my memory use more than 98% (In windows task manager inspector), it's understandable. BUT, that 64G mem PC, memory use percent has 50% FREE!!! still got OutOfMemoryException ????

3, Possible solution (of I think): 3.1 Replace flat array to BigArray(Sparse Arrays?) or MemoryMappedFile , in ResizableArray.cs: I had tried a litte, but stuck on lots of struct value changing directly. (Maybe change struct to class will be ok? any suggestion on this ?) 3.2 Actually, my purpose is make a available collider mesh, because original model mesh is too big, can not used as collider mesh. And then, the purpose of collider mesh is do the mouse hit test / raycast, to get the vector3 of click point at surface of mesh. So if there is a way to get that vector3 point without building collider mesh, that would be help! (not found yet)

expect for your reply, thanks~

Whinarn commented 1 year ago

Sorry I was away on a business trip for two days.

Well this is certainly interesting. Is there any possibility to share an example mesh that you are working with? I'd like to debug it and see what's going on.

If you do not want to share it publicly you could send it to me privately though email (which you can find in the commit log).

Summer006 commented 1 year ago

Thanks, and.... I think maybe I found a solution, which is:

before import model, first run an external exe: use "simplify.exe" (which this repo based on ?) to make a simplified version, this step can successfully done on my 16g pc without any exception or error. then import these 2 model files, one by one. seems to be OK, so far so good :-)

about the model file? it's not interesting at all, that's not a complex model as you think. just a stupid very very simple shape , but is scaned from UAV, and no second handled, so it's very very huge, but let me say, after 99.5% simplify (eg: quality set to 0.05), almost nothing changed !!
9DBB76BE0A98F5E2922EE3C04EC64156