freezy / VisualPinball.Engine

:video_game: Visual Pinball Engine for Unity
https://docs.visualpinball.org
GNU General Public License v3.0
411 stars 62 forks source link

Table Import: Share mesh duplicates #230

Open Pandelii opened 3 years ago

Pandelii commented 3 years ago

For the hybrid renderer to instance objects, duplicate mesh assets need to be sharing the same base mesh. On import, duplicate meshes should be identified and have their mesh component set to a common mesh for that element. For meshes that are the same but a different scale, the mesh should be shared and the transform scaled accordingly. Flipped meshes, meshes who's transform has a negative scale on any axis, can remain a separate mesh as the instancing does not support negatively scaled instances.

Vert count + bounds total volume or name matching may catch most instances.

freezy commented 3 years ago

So for procedurally created meshes, it's quite easy, we can just check the creation parameters. However for primitives I'm wondering how this should work. Table authors tend to merge static meshes of the same material (i.e. screws), and if they're not merged, how should identify duplicates? Hashing the mesh? What if the vertices are actually displaced but the mesh is identical otherwise?

Pandelii commented 3 years ago

There is little we can do for anyone who has made a manual static batch. It is possible to break that apart but ultimately, that will be their responsibility to repair that I would think. If we were feeling particularly adventurous, we could take any mesh and partition it based on connectivity after a welding operation (any verts within 0.0001m with the same normal and UV position are treated as one vert). The connected pieces are then evaluated individually to see if they match other meshes.

For other primitives, vertex count + the total volume of the OBB should be fine for identification I would think. If it has the same count, but has been displaced, the OBB will likely be different. I used the vertex count + OBB volume for my test and it didn't catch anything it shouldn't have, but I also didn't test it on too many tables.

Pandelii commented 3 years ago

The other issue I'm noticing is that there are many cases where a mesh is the same but it has a baked in transform. So a post on one side is exactly the same, but either during the import or during the original (VPX/External) generation, a transform offset was applied that shifted the verts away from the pivot point. These could be handled but it is an extra step of figuring out the centroid (center of the OBB) and adjusting the actual transform after the mesh has been zeroed out.

ecurtz commented 3 years ago

It might not be worth trying to come up with a really smart solution versus some sort of tool for manually replacing them with a little bit of intelligence built in that only tried to align the new properly instanced mesh with the original?

Pandelii commented 3 years ago

I could see that working as well, though I could see that being as complicated as just doing a basic vert count plus obb compare. Would be a handy tool on its own regardless though..

I wouldn't really bother trying the partitioning approach i mentioned above. If the creator statically batched them, good chance they can unbatch them simply enough.

If it helps, my process for doing it manually is pretty simple:

  1. Select a mesh to find its name
  2. Search the hierarchy for thatvname
  3. Select all with that name
  4. Right click next to the mesh value and select "assign from" and select any random one of that list.

Usually works pretty well and catches the majority of the cases. Screws, nuts, bulbs, and sockets tend to follow a pattern.

A few things will not work well doing that unfortunately and it still takes a bit of time to do.

Pandelii commented 3 years ago

Sorry, I'm so used to using them I assumed unity had OBB, it seems they don't and I know they are non-trivial to roll yourself. I dug this up, might be of use if you don't find a simpler solution.
https://github.com/sharpdx/SharpDX/blob/master/Source/SharpDX.Mathematics/OrientedBoundingBox.cs