Search Unity

MESH PRO? Deforming, cutting, substracting mesh. Help!

Discussion in 'Scripting' started by Nakel, Jan 22, 2020.

  1. Nakel

    Nakel

    Joined:
    Sep 28, 2017
    Posts:
    106
    I've been looking for many options on how to do this during RUNTIME...
    (this representation is not perfect but Its to show you what I intend to do)



    • The problem if I use CSG (subtract or intersect) Its too demanding for the CPU and often It doesn't work on non-primitive meshes. So It actually doesn't seem to be working the ones I found on GitHub...
    • I can cut the mesh with a plane that is super easy and not demanding at all... I need to do the same but not with a plane... any figures (mostly stairscases)
    • Also I cant simply model the terrain with those stairs because the terrain is always going to be random. And no... this is not intended to be used on a game.
    I talked to an expert and he told me that I could use a spline since it has coordinates and then I would be easy to build the stairs and delete the polygons inside of it... Is that possible? or there are better ways...

    Please consider that I need only the mesh that intersects them two like in the 2D representation.

    THANKS
     
    Last edited: Jan 22, 2020
  2. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    This is a non-trivial problem.
    Depending on what it's for you may want to look into raymarching, since it's pretty easy to add or subtract shapes with it, but other than visuals you cant really do a lot with it. Since you already seem to have some terrain generation going on this doesnt seem to be an option, but i still wanted to mention it just in case.
    If it's 'just' about performance, you can easily calculate these things in realtime using either an implementation in DOTS (CPU), or a compute shader (GPU) to speed the calculations up by an insane amount (factor 10x-100x or more).

    This doesnt solve the problem of actually subtracting the meshes, but then again it's non-trivial, so pick your poison.
    Not quite sure if the problem becomes easier since you only need the 2D representation. The solution should still involve 'manually' building a new mesh based on the two others and their vertices.
     
  3. neoshaman

    neoshaman

    Joined:
    Feb 11, 2011
    Posts:
    6,493
    Probably the fastest way to do this is to have voxel representation, and remesh on that.
     
  4. Nakel

    Nakel

    Joined:
    Sep 28, 2017
    Posts:
    106
    How would I do that?
     
  5. Nakel

    Nakel

    Joined:
    Sep 28, 2017
    Posts:
    106
    Thanks for the answer. I'm diggin into it...
     
  6. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    I think what he meant is the following:
    You would have your shapes defined in a scalar field. You would render this scalar field using something like marching cubes. You could then pretty easily subtract a shape from your mesh by removing the scalar values inside of it. So imagine you want to render a large cube (ground). Your scalar field would then contain the maximum values of, for example, 1 inside that shape. If you wanted to subtract a smaller cube (or stairs) from it, you could then set all scalar values inside the to-be-subtracted shape to the minimum value of 0 and render the resulting mesh anew.

    I always found this pretty helpful for visualizing what happens:


    Problems that come to mind with this approach:
    • Implementation may take some time (especially if performance is a concern, ie realtime is a goal). You could however build on already existing implementations and also utilize a compute shader for it.
    • You may not be able actually achieve what you want, since the mesh you end up with may not be the exact representation of the two meshes you wanted to subtract. This should become clear when watching the video, since the rendered representation depends on the scalar field, not the actual shape you tried to subtract from it. To fix this you could use a very high resolution for your scalar points, but that would again decrease performance.
    • If the shapes you used were guaranteed blocky (which doesnt seem like it), then you could use 'actual blocks' as meshes instead of something like marching cubes. Kind of like how games like Minecraft do it.
    • It doesnt actually solve your goal of getting the 2D intersection, even tho if you are happy with the 3D representation and dont need it done in realtime you could always brute-force this. In the end this would come down to the points lying on some mesh and some plane, which comes down to the intersection of a line and a plane, which you then could do for every vertex pair in every triangle of the mesh. There is probably a smarter way to do this tho.
     
    Last edited: Jan 24, 2020
  7. Nakel

    Nakel

    Joined:
    Sep 28, 2017
    Posts:
    106
    Thank you really much for answering.
    I think I'm complicating things too much... let's forget about extracting a mesh from another....

    What if we simply deform the mesh with another object (probably a mesh) that has a particular shape... so that everything inside of it (vértices and triangles probably using raycasting or mesh colliders) get deleted and adapt the form of the object.. just like this one:

    so if we put a cube inside the terrain It would make a hole of a cube in the mesh. The forms and figures Im going to be using are mostly like stairs, so not so complex also...

    What do you think?
     
  8. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    You'd have to check what vertices are inside of the shape and delete them. Then you'll need to do the same for the other object in reverse. Then you'll need to combine them. To do this, however, you'll need to flip the triangles of the inserted object, since you can only look at triangles from one side. Afterwards you still need to reconnect the meshes in some proper way, meaning you have to connect all the open vertices, but not connect the wrong ones.
    And if that's a goal, do all the above in realtime of course (involving multithreading which is an easy cause for errors).
    All in all definitely not an easy task.

    Computers are good at a lot of things, but they are not good as working with visuals unless we tell them precisely what algorithm to follow. Things like 'indenting a mesh using another mesh' seems increadibly easy for our brains, but expressing this mathematically and programmatically is quite hard.

    Here are just a few things that you need to pay attention to using the mesh-combining approach:
    • You plan to delete vertices inside the shape of the inserted object. What if none exist? The cube we insert your stairs into may have as little as 8 vertices, none of which have to be inside the stairs.
    • Not only does the stair need to 'cut into' (a thing we still have problems defining) the cube, but the cube also needs to cut the stairs in the right plane too. Otherwise bumps or artifacts may occur.
    • The process of 'cutting into' needs to create new vertices and triangles, since the object just changed its shape.
    • I already mentioned that you need to flip the triangles of the inserted shape, since otherwise it would be look-through, but you'd also have to figure out what way the triangles you are going to create yourself need to face.
    • Now that we have two partial meshes we need to insert new vertices and triangles to even make them fit together.
    Even when thinking about something like a cube and a (blocky) staircase this is not trivial. And to be robust, your solution would need to work with basically any shape combination anyways.
    If you think you have a solution for your situation, try implementing them. It may work for your case. If not, you either need to look into defining a robust algorithm that takes care of this problem, or using an easier solution (like voxelizing the problem) which may come with drawbacks for your requirements.
    It depends on what you intend to use this for and how important a feature it is going to be.
    Edit: Again, if you only need visuals of something subtracted from something else, nothing better than raymarching. If you need things to stand on it or be physically simulated (and dont intend to code these things yourself, which is possible), not so much.
     
    Last edited: Jan 25, 2020
  9. Nakel

    Nakel

    Joined:
    Sep 28, 2017
    Posts:
    106
    Is there any way to actually detect all triangles or vertices inside of a mesh (collider and non primitive) I'm looking for deleting triangles inside of the mesh and after that just merge them both meshes...
     
  10. Tarball

    Tarball

    Joined:
    Oct 16, 2016
    Posts:
    166
    If this is not for a game, why don't you use some CAD program? It would be very easy to do in FreeCAD, for example. What is the application?
     
  11. Nakel

    Nakel

    Joined:
    Sep 28, 2017
    Posts:
    106
    I'm making a software that calculates volumes in real-time. So shapes are going to be changing constantly I need to integrate this type of operation in the software....
     
  12. Tarball

    Tarball

    Joined:
    Oct 16, 2016
    Posts:
    166
    I see, well you might as well download the source code of FreeCAD or something similar and see what's under the hood. It's open source. Even in CAD, you don't do these sorts of operations on the meshes themselves. You do the operation on a solid and convert to/from a mesh when convenient. I would rethink your approach. Still though, I don't think Unity is the tool for the job. Just my two cents.
     
  13. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    Not sure if i'm missing the point of your question, but the mesh type itself offers you access to the vertices and triangles it contains. Even tho, triangles are defined as the indices of vertices that make them up so you'd have to do some calculations yourself if you want to work with an actual triangle.
    https://docs.unity3d.com/ScriptReference/Mesh.html

    If you do something that works please keep us updated :)
     
  14. Nakel

    Nakel

    Joined:
    Sep 28, 2017
    Posts:
    106
    I was thinking on something like OnTriggerEnter(mesh collider just as explain myself)... a mesh and getting only the triangles that intersect the collider...

    at this point I think I'll hire a freelancer... :( I really need to get this done... But I'll keep you updated.
     
  15. joshcamas

    joshcamas

    Joined:
    Jun 16, 2017
    Posts:
    1,277
  16. Nakel

    Nakel

    Joined:
    Sep 28, 2017
    Posts:
    106
    I did something like this....
    Code (CSharp):
    1.  
    2.         mesh = MapMesh.GetComponent<MeshFilter>().mesh;
    3.  
    4.         List<Vector3> vertices = mesh.vertices.ToList();
    5.         List<Vector3> verticesToRemove = new List<Vector3>();
    6.         Bounds bounds = hole.GetComponent<MeshRenderer>().bounds;
    7.         float minX = bounds.min.x;
    8.         float minZ = bounds.min.z;
    9.         float maxX = bounds.max.x;
    10.         float maxZ = bounds.max.z;
    11.  
    12.         for (int i = 0; i < vertices.Count; i++)
    13.         {
    14.             Vector3 v = vertices[i];
    15.             if (minX > v.x || maxX < v.x ||
    16.                 minZ > v.z || maxZ < v.z) continue;
    17.  
    18.             RaycastHit hit;
    19.             if (!Physics.Raycast(v + new Vector3(0, offset, 0), Vector3.down, out hit, float.MaxValue, holeMask)) continue;
    20.  
    21.             verticesToRemove.Add(vertices[i]);
    22.         }