Search Unity

Split CSG Mesh

Discussion in 'World Building' started by Plummers, Apr 12, 2020.

  1. Plummers

    Plummers

    Joined:
    Oct 29, 2015
    Posts:
    31
    Hi,
    I have a mesh that is cut into two parts by subtraction using the CSG tool. Is there a way to split this "cut" mesh into two different meshes?

    Thanks in advance
     
  2. Plummers

    Plummers

    Joined:
    Oct 29, 2015
    Posts:
    31
    Solved.

    Found a way looping through the vertices of the whole mesh to get the "cut" parts out and then create a new gameobject for each of them. Seems to work well.
     
  3. Vsion-Studio

    Vsion-Studio

    Joined:
    Oct 7, 2019
    Posts:
    3
    Hi Plummers
    I'm interested in the same thing. I've used the CSG tool from this repo: https://github.com/karl-/pb_CSG
    and I also want to separate the meshes when are split with substraction.

    Can you please detail a little bit more the solution you found?
    Thanks!
     
    Plummers likes this.
  4. Plummers

    Plummers

    Joined:
    Oct 29, 2015
    Posts:
    31
    Hi,

    It's been a while since I was playing around with this, it's pretty cool when it works. Here's my code I found for splitting the mesh. Let me know if this makes sense, I can help further if I put my brain to it! Cheers

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3. using UnityEngine.ProBuilder.MeshOperations;
    4. using UnityEngine.ProBuilder;
    5.  
    6. public class splitMesh : MonoBehaviour
    7. {
    8.     public Material invisible;
    9.     public List<GameObject> SplitMesh(GameObject whole)
    10.     {
    11.         List<GameObject> results = new List<GameObject>();
    12.  
    13.         MeshRenderer meshRenderer = whole.GetComponent<MeshRenderer>();
    14.         Mesh mesh = whole.GetComponent<MeshFilter>().mesh;
    15.         bool destroy = false;
    16.         int[] indices = mesh.triangles;
    17.         Vector3[] verts = mesh.vertices;
    18.         List<Vector3> newVerts = new List<Vector3>();
    19.         List<Vector3> vertList = new List<Vector3>(verts);
    20.  
    21.         int count = 0;
    22.         while (vertList.Count > 0)
    23.         {
    24.             count++;
    25.             newVerts.Clear();
    26.             newVerts.Add(vertList[0]);
    27.             newVerts.Add(vertList[1]);
    28.             newVerts.Add(vertList[2]);
    29.             for (int i = 3; i < vertList.Count; i += 3)
    30.             {
    31.                 bool check = false;
    32.                 for (int j = 0; j < 3 && !check; j++)
    33.                 {
    34.                    for (int v = 0; v < newVerts.Count && !check;v++)
    35.                     {
    36.                         if (newVerts[v] == vertList[i + j])
    37.                         {
    38.                             check = true;
    39.                         }
    40.                     }
    41.                 }
    42.                 if (check)
    43.                 {
    44.                     for (int k = 0; k < 3; k++)
    45.                     {
    46.                         newVerts.Add(vertList[i + k]);
    47.                     }
    48.                     for (int k = 0; k < 3; k++)
    49.                     {
    50.                         vertList.RemoveAt(i + 2 - k);
    51.                     }
    52.                     i = 0;
    53.                 }
    54.             }
    55.             vertList.RemoveAt(0);
    56.             vertList.RemoveAt(0);
    57.             vertList.RemoveAt(0);
    58.             Vector3[] vertsR = new Vector3[newVerts.Count];
    59.             List<int> indR = new List<int>();
    60.             for (int i = 0; i < newVerts.Count; i++)
    61.             {
    62.                 vertsR[i] = newVerts[i];
    63.                 indR.Add(indices[i]);
    64.             }
    65.             Mesh newMeshGG = new Mesh();
    66.             newMeshGG.vertices = vertsR;
    67.             newMeshGG.triangles = indR.ToArray();
    68.  
    69.             newMeshGG.RecalculateNormals();
    70.             if (vertList.Count == 0 && count == 1)
    71.             {
    72.                 results.Add(whole);
    73.             }
    74.             else
    75.             {
    76.                 GameObject gg = new GameObject("newGameObject");
    77.                 gg.transform.SetParent(whole.transform.parent);
    78.                 gg.AddComponent<MeshRenderer>().material = invisible;
    79.                 gg.GetComponent<MeshRenderer>().enabled = false;
    80.                 gg.AddComponent<MeshFilter>().mesh = newMeshGG;
    81.                 ProBuilderizeShape(gg);
    82.                 results.Add(gg);
    83.                 destroy = true;
    84.             }
    85.  
    86.         }
    87.  
    88.         if (destroy)
    89.         {
    90.             Destroy(whole);
    91.         }
    92.  
    93.         return results;
    94.     }
    95.  
    96.     public void ProBuilderizeShape(GameObject shape)
    97.     {
    98.         var filter = shape.GetComponent<MeshFilter>();
    99.         // Add a new uninitialized pb_Object
    100.         var mesh2 = shape.AddComponent<ProBuilderMesh>();
    101.         // Create a new MeshImporter
    102.         var importer = new MeshImporter(mesh2);
    103.         // Import from a GameObject. In this case we're loading and assigning to the same GameObject, but you may
    104.         // load and apply to different Objects as well.
    105.         importer.Import(filter.sharedMesh);
    106.         // Since we're loading and setting from the same object, it is necessary to create a new mesh to avoid
    107.         // overwriting the mesh that is being read from.
    108.         filter.sharedMesh = new Mesh();
    109.         // Apply the imported geometry to the pb_Object
    110.         mesh2.ToMesh();
    111.         // Rebuild UVs, Collisions, Tangents, etc.
    112.         mesh2.Refresh();
    113.         mesh2.CenterPivot(null);
    114.     }
    115. }
     
    Vsion-Studio likes this.
  5. Vsion-Studio

    Vsion-Studio

    Joined:
    Oct 7, 2019
    Posts:
    3
    Hi!
    I've been trying your code and it works fine for my needs. Thank you very much!
     
    Plummers likes this.
  6. Spectra_7

    Spectra_7

    Joined:
    Oct 17, 2017
    Posts:
    24
    Hello Plummers.

    Thanks a lot for the code. It works pretty good.
    One problem I am facing is that, the CPU freezes in between.

    Is there any way to improve performance like using Compute Shaders, etc?
     
    Last edited: Mar 10, 2021
  7. Plummers

    Plummers

    Joined:
    Oct 29, 2015
    Posts:
    31
    Hi Spectra_7,
    Cool, happy you got it working. As for performance I'm not sure, I remember that the ProBuilder guys were maybe working on improving their split function because it was in early testing.

    Good luck
     
unityunity