Aug
9
2011

Fake Mesh Slicer v3.0

Testing different technique
– Capsule (but bit too low poly & capsulecollider not so good for this..)
– ‘Infinity plane’ for cutting ( http://unity3d.com/support/documenta…nce/Plane.html )
– Using “Plane.GetSide” to check which side the vertex is
– if its above cutplane, move it down with distance from “Plane.GetDistanceToPoint”
– Clone the slice from original object

Webplayer:
http://unitycoder.com/upload/demos/slicer3/
wasd = move cutting plane
qe = rotate cutting plane (dont rotate it upside down..)
space = slice
mouse = drag objects (try dragging the original object and cut it while hanging in air)
(cannot cut the slices, just the original object, although should be possible to do that, or to cut multiple objects at the same time)

Download source + webplayer scene:
fakeSlicer3.unityPackage


Related Posts

About the Author:

.fi

16 Comments + Add Comment

  • nice. thank you!

  • btw. this package has a small bug,
    some vertices are pushed in wrong direction/too far,
    when the cutting plane rotated (not straight).

    cant remember it right now how to fix it,
    but it might be something to do with the cutting planes local rotation or distance..(?)

  • Nice script, thank you for sharing this.
    Is it possible to make it cutting just small peace of mesh. I have tested it on one mesh represent terrain and it is cutting all peaks, i will to cut (flatten) just a small peace of that terrain mesh?

    Chears

  • Unity simple Mesh cutting Code

  • Hello MGear. I got interested in this project to make my own cutting script. I need it for my game project. unfortunately for now it is not really working as I expect it to. all vertices are supposed to follow at the EXACT point of the blade cut but something is wrong… Here’s your code + my own mixed up together.

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class example : MonoBehaviour
    {
    private static Plane blade;

    int[] triangles;
    Vector3[] vertices;
    Mesh mesh;

    List vertsTrigConnections = new List();
    List vertTrigDirToNotCalculate = new List();
    List totalDirections = new List();

    List rightSideVertTemp = new List();
    List leftSideVertTemp = new List();

    List newVertices = new List();

    Vector3 dir0;
    Vector3 dir1;
    Vector3 dir2;

    void Update()
    {
    float mouseVert = Input.GetAxisRaw(“Mouse Y”);
    float mouseHorz = Input.GetAxisRaw(“Mouse X”);

    transform.Rotate(new Vector3(-mouseVert, mouseHorz, 0));

    Debug.DrawRay(new Vector3(transform.position.x, transform.position.y, transform.position.z), transform.forward, Color.red, 0.1f);

    if (Input.GetMouseButtonDown(0))
    {
    RaycastHit hit;

    if (Physics.Raycast(transform.position, transform.forward, out hit, 20f))
    {
    mesh = hit.transform.GetComponent().mesh;
    GameObject hitObject = hit.transform.gameObject;
    blade = new Plane(hit.transform.InverseTransformDirection(transform.right), hit.transform.InverseTransformPoint(transform.position));

    for (int i = 0; i < hit.transform.GetComponent().mesh.vertices.Length; i++)
    {
    if (!blade.GetSide(hit.transform.GetComponent().mesh.vertices[i]))
    {
    leftSideVertTemp.Add(hit.transform.GetComponent().mesh.vertices[i]);
    }
    if (blade.GetSide(hit.transform.GetComponent().mesh.vertices[i]))
    {
    rightSideVertTemp.Add(hit.transform.GetComponent().mesh.vertices[i]);
    }
    }

    vertices = hitObject.transform.GetComponent().mesh.vertices;
    triangles = hitObject.transform.GetComponent().mesh.triangles;

    for (int i = 0; i < triangles.Length; i += 3)
    {

    Vector3 worldPt0 = vertices[triangles[i + 0]];
    Vector3 worldPt1 = vertices[triangles[i + 1]];
    Vector3 worldPt2 = vertices[triangles[i + 2]];

    vertsTrigConnections.Add(worldPt0);
    vertsTrigConnections.Add(worldPt1);
    vertsTrigConnections.Add(worldPt2);

    dir0 = worldPt1 – worldPt0;
    dir1 = worldPt2 – worldPt1;
    dir2 = worldPt0 – worldPt2;

    if (!totalDirections.Contains(dir0))
    {
    totalDirections.Add(dir0);
    }
    if (!totalDirections.Contains(dir1))
    {
    totalDirections.Add(dir1);
    }
    if (!totalDirections.Contains(dir2))
    {
    totalDirections.Add(dir2);
    }

    for (int h = 0; h < vertsTrigConnections.Count – 1; h++)
    {
    for (int f = h + 1; f < vertsTrigConnections.Count; f++)
    {
    if (vertsTrigConnections[h] == vertsTrigConnections[f])
    {
    vertTrigDirToNotCalculate.Add(vertsTrigConnections[h]);
    }
    }
    }

    Debug.Log(vertsTrigConnections.Count);

    for (int h = 0; h < vertTrigDirToNotCalculate.Count – 1; h++)
    {
    for (int f = h + 1; f < vertTrigDirToNotCalculate.Count; f++)
    {
    if (dir0 == vertTrigDirToNotCalculate[h] – vertTrigDirToNotCalculate[f] ||
    dir0 == vertTrigDirToNotCalculate[f] – vertTrigDirToNotCalculate[h])
    {
    //Debug.Log("coliss1");
    //totalDirections1.Remove(dir0);
    totalDirections.Remove(dir0);
    }
    if (dir1 == vertTrigDirToNotCalculate[h] – vertTrigDirToNotCalculate[f] ||
    dir1 == vertTrigDirToNotCalculate[f] – vertTrigDirToNotCalculate[h])
    {
    //Debug.Log("coliss2");
    //totalDirections2.Remove(dir1);
    totalDirections.Remove(dir1);
    }

    if (dir2 == vertTrigDirToNotCalculate[h] – vertTrigDirToNotCalculate[f] ||
    dir2 == vertTrigDirToNotCalculate[f] – vertTrigDirToNotCalculate[h])
    {
    //Debug.Log("coliss3");
    //totalDirections3.Remove(dir2);
    totalDirections.Remove(dir2);
    }
    }
    }

    var enumerator999 = rightSideVertTemp.GetEnumerator();
    while (enumerator999.MoveNext())
    {
    var currentVert = enumerator999.Current;
    var enumerator888 = leftSideVertTemp.GetEnumerator();
    while (enumerator888.MoveNext())
    {
    var currentVert1 = enumerator888.Current;
    Vector3 dir = (currentVert1 – currentVert);
    Vector3 diri = (currentVert – currentVert1);

    for (var g = 0; g < vertices.Length; g++)
    {

    for (int j = 0; j < totalDirections.Count; j++)
    {
    if (worldPt0 == currentVert && totalDirections[j] == dir)
    {
    Ray vecRay0 = new Ray(worldPt0, totalDirections[j]);
    float dist0;
    if (blade.Raycast(vecRay0, out dist0))
    {
    if (!newVertices.Contains(vecRay0.GetPoint(dist0)))
    {
    newVertices.Add(vecRay0.GetPoint(dist0) + hit.transform.position);
    }
    if (worldPt0 == vertices[g])
    {
    vertices[g] = vecRay0.GetPoint(dist0);
    }
    }
    }
    }
    for (int j = 0; j < totalDirections.Count; j++)
    {

    if (worldPt1 == currentVert && totalDirections[j] == dir)
    {
    Ray vecRay1 = new Ray(worldPt1, totalDirections[j]);
    float dist1;

    if (blade.Raycast(vecRay1, out dist1))
    {
    if (!newVertices.Contains(vecRay1.GetPoint(dist1)))
    {
    newVertices.Add(vecRay1.GetPoint(dist1) + hit.transform.position);
    }
    if (worldPt1 == vertices[g])
    {
    vertices[g] = vecRay1.GetPoint(dist1);
    }

    }
    }
    }
    for (int j = 0; j < totalDirections.Count; j++)
    {
    if (worldPt2 == currentVert && totalDirections[j] == dir)
    {
    Ray vecRay2 = new Ray(worldPt2, totalDirections[j]);
    float dist2;

    if (blade.Raycast(vecRay2, out dist2))
    {
    if (!newVertices.Contains(vecRay2.GetPoint(dist2)))
    {
    newVertices.Add(vecRay2.GetPoint(dist2) + hit.transform.position);
    }
    if (worldPt2 == vertices[g])
    {
    vertices[g] = vecRay2.GetPoint(dist2);
    }
    }
    }
    }
    }
    }
    }
    }
    }
    mesh.vertices = vertices;
    mesh.RecalculateBounds();
    }
    rightSideVertTemp.Clear();
    leftSideVertTemp.Clear();
    newVertices.Clear();
    vertsTrigConnections.Clear();
    vertTrigDirToNotCalculate.Clear();
    totalDirections.Clear();
    }
    }

  • i seem to have fixed my issue… i just took off the if’s worldPt0 == currentVert && worldPt1 == currentVert && worldPt2 == currentVert… now its lag the problem. What the code does is the same as yours except it moves the vertices to the pinpoint correct position… not in all angles though. Thank you by the way for sharing your project Mgear.
    Nine

  • An open source mesh slicer framework for Unity3D Game Engine. Written in C#.
    https://github.com/DavidArayan/EzySlice

  • “Slice meshes in runtime in a dynamic way. Very similar to what is implemented in Metal Gear Rising.”
    https://github.com/toninhoPinto/MeshSlicingRunTime

  • […] usato il falso affettatrice 3.0 (http://unitycoder.com/blog/2011/08/09/fake-mesh-slicer-v3-0/) e inclusi nel campione hanno una capsula che […]

  • […] utilizado el falso segmentación 3.0 (http://unitycoder.com/blog/2011/08/09/fake-mesh-slicer-v3-0/) e incluidas en la muestra, tienen una cápsula que la segmentación de las […]

  • source code and a simplified version of the demo from my master thesis in “Procedural Mesh Splitting”
    https://github.com/DanniSchou/MeshSplitting

  • […] Obtuve este código de aquí. […]

  • […] una cortadora falsa 3.0 (http://unitycoder.com/blog/2011/08/09/fake-mesh-slicer-v3-0/) e incluidos en la muestra, tienen una cápsula en la que funciona la […]

Leave a comment

Connect

Twitter View LinkedIn profile Youtube Github Join Discord Twitch Instagram BlueSky

UnityLauncherPro

Get UnityLauncherPRO and work faster with Unity Projects!
*free unity hub alternative

@unitycoder_com

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.