Search Unity

Boolean Mesh Project

Discussion in 'Scripting' started by IsGreen, Feb 8, 2014.

  1. IsGreen

    IsGreen

    Joined:
    Jan 17, 2014
    Posts:
    206

    Project finished:

    Intersection Image:
    Union Image:
    Difference Image:

    Download: https://app.box.com/s/a97omj348mazfh0vasx5

    Texture Material Included. Example script:

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class csSceneBoolean : MonoBehaviour {
    5.  
    6.     public MeshCollider meshColliderA;
    7.     public MeshCollider meshColliderB;
    8.  
    9.     // Use this for initialization
    10.     void Start () {
    11.  
    12.         // Create new GameObject
    13.         GameObject newObject = new GameObject();
    14.         newObject.transform.localScale*=2f;
    15.         MeshFilter meshFilter = newObject.AddComponent<MeshFilter>();
    16.         MeshRenderer meshRenderer = newObject.AddComponent<MeshRenderer>();
    17.         meshRenderer.materials = new Material[2]{meshColliderA.transform.renderer.materials[0],meshColliderB.transform.renderer.materials[0]};
    18.    
    19.         // Assign booleanMesh
    20.         BooleanMesh booleanMesh = new BooleanMesh(meshColliderA,meshColliderB);
    21.         //meshFilter.mesh = booleanMesh.Difference();
    22.         //meshFilter.mesh = booleanMesh.Union();
    23.         meshFilter.mesh = booleanMesh.Intersection();
    24.    
    25.     }  
    26.  
    27. }
     
    Last edited: Feb 12, 2014
  2. IsGreen

    IsGreen

    Joined:
    Jan 17, 2014
    Posts:
    206
    I have found information about is necessary to adjust vertices order in triangle if cross product of vector v2-v1,v3-v1, multiply by normals is negative.

    Code (csharp):
    1.     void recalculateTriangles(Vector3[] vertices,Vector3[] normals,int[] triangles){
    2.        
    3.         Vector3 a,b,c;
    4.         int v1,v2,v3;
    5.        
    6.         for(int i=0;i<triangles.Length;i+=3){
    7.            
    8.             v1 = triangles[i];
    9.             v2 = triangles[i+1];
    10.             v3 = triangles[i+2];
    11.            
    12.             a = vertices[v1];
    13.             b = vertices[v2];
    14.             c = vertices[v3];
    15.            
    16.             if(Vector3.Dot(normals[v1]+normals[v2]+normals[v3],Vector3.Cross((b-a),(c-a)))<0f){
    17.                
    18.                 triangles[i+2]=v1;
    19.                 triangles[i]=v3;
    20.                
    21.             }
    22.            
    23.         }
    24.        
    25.     }
    And this problem is solved.

    But, another problem has appeared. The second mesh present problems of normals. The triangles exist, the problem is another time about normals.

    If you change mesh order, from A to B, by B to A, the problem appears always in the second mesh.

    Image Screen:
    $q8tc.jpg

    Someone know what adjust type is necessary to join vertices and triangles groups of two meshes?.
     
  3. IsGreen

    IsGreen

    Joined:
    Jan 17, 2014
    Posts:
    206
    Was another bug, wasn't normal problem.

    The second problem was due to mesh order between recording processes vertices inside or outside of the mesh and the calculation of intersections, the intersections and which are calculated based on whether the tip is in or out of mesh. (If the vertex of the mesh is within a raycast is not drawn, that is, the intersection is not calculated).
    *
    Project ended with texture mapping included. The download link is in the first message.
     
  4. idlebyte

    idlebyte

    Joined:
    Feb 3, 2013
    Posts:
    17
    Would it be possible to modify this to receive an array or list of meshes? 3+ operands?

    Thanks,
    -Dustin

    It seems like the easiest way might be to modify lines 17-23 of csSceneBoolean.cs into a loop and modify the input to include the object and the action to be performed per object. Then the loop could apply each object and its operation starting with the first in the list. *Sunday booked* Obviously this loop could be in my code on the game side, but I want it as simple as possible so I need to try to do as much within the scripts provided. Thanks for the start!
     
    Last edited: Apr 27, 2014
  5. idlebyte

    idlebyte

    Joined:
    Feb 3, 2013
    Posts:
    17
    Running into issues retrieving the proceduraly generated mesh (for collision detection on next operand) from the newGameobject. Any recommendations?

    Thanks,
    -Dustin
     
  6. bondematt

    bondematt

    Joined:
    Nov 15, 2012
    Posts:
    1
    Using these two lines you can use the newly created mesh to generate the new MeshCollider on the GameObject that was created by the script.

    Code (csharp):
    1. MeshCollider meshCollider = newObject.AddComponent<MeshCollider>();
    2.  
    3. meshCollider.sharedMesh = meshFilter.sharedMesh;
    Edit: They need to be placed after the new mesh is generated in csSceneBoolean of course.
     
  7. idlebyte

    idlebyte

    Joined:
    Feb 3, 2013
    Posts:
    17
    This clears the error and shows the mesh applied to the meshCollider, but they have no name (not even 'instance'), just blank. This isn't a problem...

    But, when pulling newObject.getComponent<MeshCollider> on the next 'BooleanMesh ='/booleanmesh.difference action, the second operand isn't applied? Will debug more tomorrow. Thanks!
     
  8. idlebyte

    idlebyte

    Joined:
    Feb 3, 2013
    Posts:
    17
    Finally got to debugging the multi-operand problem, the first mesh (generated from first two operands) gets generated and handed to the Boolean function fine from within my looping script (loop apply operands+meshes until all done).

    Infinite loop problem now, BooleanMesh.cs under the function bool ConcaveHull gets stuck 'while' (270-280) looping the same raycast when csBooleanMesh calls BooleanMesh.Difference passing the dynamically generated mesh and a third mesh present as scene start (To make the next hole or the third operand dynamically).

    Some of the steps below are from reading about meshes being null'd before re-written and a lot of sharedmesh copying to get the generated mesh passed to the boolean function successfully. Would love a cleaner version, plan to clean up once i get working.

    Code (csharp):
    1.  
    2.     public MeshCollider meshColliderA;  Sphere with sphere meshcollider added
    3.     public MeshCollider meshColliderB;  Cube-log used to poke hole in sphere, cube meshcollider added
    4.     public MeshCollider meshColliderC;  Cube-log used to poke hole in sphere, cube meshcollider added
    5.  
    6. <...>
    7.             GameObject newObject = new GameObject ();  
    8.             newObject.transform.localScale *= 2f;  
    9.             MeshFilter meshFilter = newObject.AddComponent<MeshFilter> ();  
    10.             MeshRenderer meshRenderer = newObject.AddComponent<MeshRenderer> ();  
    11.             MeshCollider newMeshCollider = newObject.AddComponent<MeshCollider>();
    12.  
    13.  
    14.             meshRenderer.materials = new Material[2] {
    15.                 meshColliderA.transform.renderer.materials [0],
    16.                 meshColliderB.transform.renderer.materials [0]
    17.             };
    18.  
    19.             BooleanMesh booleanMesh = new BooleanMesh (meshColliderA, meshColliderB);  
    20.             meshFilter.mesh = booleanMesh.Difference ();  
    21.             newMeshCollider.sharedMesh = meshFilter.sharedMesh;
    22.            
    23.  
    24.             //second operation test
    25.             BooleanMesh booleanMeshB = new BooleanMesh (newMeshCollider, meshColliderC);  
    26.             meshFilter.mesh = null;
    27.             meshFilter.mesh = booleanMeshB.Difference();
    28.             meshFilter.sharedMesh = null;
    29.             meshFilter.sharedMesh = booleanMeshB.Difference();
    30.             newMeshCollider.sharedMesh = null;
    31.             newMeshCollider.sharedMesh = meshFilter.sharedMesh;
    32.  
    33.  
    For some reason the generated mesh and a third static mesh (C) causes BooleanMesh.cs\bool ConcaveHull to 'infinite while' loop with the same raycast. I'll keep digging but appreciate any help.

    Thanks,
    -Dustin
     
    Last edited: May 2, 2014
  9. Leuthil

    Leuthil

    Joined:
    Jul 26, 2013
    Posts:
    97
    I am eager to try this. I have tried a few Boolean operation solutions in Unity (two of which I paid for) and none of them worked without bugs, and by bugs I mean extremely common bugs (missing normals usually). Most of them were based off the CSG.js solution which I guess doesn't work properly in Unity. I will be testing this one out and posting back my results.
     
  10. IsGreen

    IsGreen

    Joined:
    Jan 17, 2014
    Posts:
    206
    The code is a start, as idlebyte said.

    It works correctly with two meshes that have a single material, in the first Boolean operation.

    If multiple Boolean operations are performed, or a Boolean operation is performed with meshes that have two or more materials each, not working properly, since the code is not designed to create an array of materials with the two meshes (created only two submesh).

    The first thing to do is to create a submesh for each material.

    Secondly, would do more tests with concave objects. The code use a Raycast to detect breakpoints, but Raycast detects the collision depending on the normal of the triangle.

    In principle, if the vertex of the object is inside the other object, not takes Raycast. So I say that I should be testing with concave objects. May be necessary to modify this feature.

    May the Force be with you.
     
    Last edited: Jun 20, 2014
  11. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    It sounds like a really valuable contribution to the community. Thank you for sharing it, and please keep up the great work!
     
  12. Leuthil

    Leuthil

    Joined:
    Jul 26, 2013
    Posts:
    97
    I have an issue that I've had with all the other Boolean operations packages I've tried. I just have two cubes with mesh colliders that are exactly beside each other. The result is always broken. Here is an example pic of what I mean:


    I also tried with the same material and same result. The z axis on both cubes are exactly the same which seems to be causing issues with the normals.
     
  13. kaarme

    kaarme

    Joined:
    May 1, 2014
    Posts:
    177
    Damn. First I thought this was awesome, but it doesn't work with multiple operations. The result is pretty messy.
     
  14. ProbePLayer

    ProbePLayer

    Joined:
    Oct 19, 2012
    Posts:
    19
    I am figuring this out right now for a proof-of-concept game of mine.

    Thanks a lot IsGreen, I heart you. I will make sure your contribution is not forgotten.
     
  15. turndapage

    turndapage

    Joined:
    Jun 25, 2015
    Posts:
    12
    I always get a mesh of the two original meshes that were intersected if it is convex. I tried the code written by bondematt, but it made now difference. Could it have something to do with the resulting mesh having two sub-meshes?
     
  16. fermas

    fermas

    Joined:
    Sep 21, 2015
    Posts:
    15
    I am not being able to download the package. When I click the button at app.box website in order to download, nothing happens. Would it be possible to make it available again? Many thanks.
     
  17. abgamers

    abgamers

    Joined:
    Dec 22, 2009
    Posts:
    97
    Even I'm unable to download the pack, same problem as Fermas.
     
  18. virendravishth

    virendravishth

    Joined:
    Sep 12, 2016
    Posts:
    7
    It is nice. Is their any update?
    Can it be used in run time for continuous Boolean subtraction viz. simulation of grinding/cutting/drilling type scene..

    Thanks...