public static void GenIntersection( CuttingPlane plane, Vector3 a, Vector3 b, Vector3 c, RingGenerator rings ) { // find intersection vertices Vector3 e = plane.Intersection(a, c, Vector2.zero, Vector2.zero, 0).Item1, d = plane.Intersection(b, c, Vector2.zero, Vector2.zero, 0).Item1; // if e == d, the three vertices lie in a line, // and thus do not make up a triangle if (e == d) { return; // not sure if this is nescessary throw MeshUtilsException.ZeroAreaTriangle(); } // find proper direction for ring Vector3 tri_nor = Vector3.Cross(c - a, c - b); bool dir = Vector3.Dot(e - d, Vector3.Cross(plane.normal, tri_nor)) > 0; // add connected pair in ring generator rings.AddConnected(dir?e:d, dir?d:e); }
public static CuttingPlane InLocalSpace(Vector3 normal, Vector3 pointInPlane, Transform transform) { CuttingPlane worldSpace = new CuttingPlane( transform.worldToLocalMatrix.transpose * normal, transform.TransformPoint(pointInPlane), null ); return(new CuttingPlane(normal, pointInPlane, worldSpace)); }
public CuttingPlane ToLocalSpace(Transform transform) { CuttingPlane worldSpace = ToWorldSpace(); return(new CuttingPlane( transform.localToWorldMatrix.transpose * worldSpace.normal, transform.InverseTransformPoint(worldSpace.pointInPlane), worldSpace )); }
List <GameObject> IterativeCut(GameObject obj, int count) { CutParams param = new CutParams(false, false, false, false, Vector3.zero, float.PositiveInfinity, 0, Vector3.zero); try { CutResult res = API.PerformCut(obj, CuttingPlane.RandomInWorldSpace(obj.transform.position), param); res.DestroyObject(); if (res == null) { return(new List <GameObject>()); } if (count > 1) { List <GameObject> ret = new List <GameObject>(); foreach (CutObj robj in res.Results) { ret.AddRange( IterativeCut( robj .CopyParent() .CopyMaterial() .CopyVelocity() .WithDriftVelocity(0.2f) .Instantiate(), count - 1 ) ); } return(ret); } else { return(res.ConvertAll( robj => robj .CopyParent() .CopyMaterial() .WithCollider() .WithRenderer() .CopyVelocity() .WithDriftVelocity(0.2f) .Instantiate() )); } } catch (MeshUtilsException e) { Debug.LogWarning(e); obj.AddComponent <Rigidbody>(); obj.AddComponent <MeshRenderer>(); obj.AddComponent <MeshCollider>(); return(new List <GameObject>() { obj }); } }
void Test() { //for (int i = 0; i < 10; i++) { foreach (GameObject obj in objs) { Debug.Log(obj); DateTime start = DateTime.Now; CutParams p = new CutParams(false, false, false, false, Vector3.zero, 0.2f, 0, Vector2.zero); CuttingPlane pl = CuttingPlane.InWorldSpace(obj.transform.up, obj.transform.position); if (GapAlgorithm.Run(obj, pl, p) == null) { throw new Exception("test failed"); } Debug.Log((DateTime.Now - start).TotalMilliseconds + " elapsed"); } //} }
public void OnCollisionEnter(Collision col) { if (ignoreColliders.Contains(col.collider)) { ignoreColliders.Remove(col.collider); return; } Cuttable cuttable; if (!col.gameObject.TryGetComponent <Cuttable>(out cuttable)) { return; } Vector3 cutDir = directionsAreNormals ? TransformNormal(cutDirection, transform) : transform.TransformDirection(cutDirection); float relVel = (col.relativeVelocity - Vector3.Project(col.relativeVelocity, cutDir)).magnitude; // Debug.Log("vel: "+relVel); // Debug.DrawRay(col.GetContact(0).point,col.relativeVelocity-Vector3.Project(col.relativeVelocity,cutDir)/relVel,Color.blue,1); if (minimumVelocity > relVel) { return; } Vector3 dir = omnidirectionalMode ? -col.relativeVelocity : cutDir; Vector3 edge = directionsAreNormals ? TransformNormal(edgeDirection, transform) : transform.TransformDirection(edgeDirection); Vector3 angleProjection = Vector3.ProjectOnPlane(gameObject.GetComponentInParent <Rigidbody>().velocity, edge); // Debug.Log("angle: "+Vector3.Angle(angleProjection,cutDir)); // if (Vector3.Angle(angleProjection,cutDir) > 70) Debug.Break(); // Debug.DrawRay(col.GetContact(0).point,angleProjection,Color.red,1); // Debug.DrawRay(col.GetContact(0).point,cutDir,Color.green,1); // Debug.DrawRay(col.GetContact(0).point,-col.relativeVelocity,Color.blue,1); if (Vector3.Angle(angleProjection, cutDir) > maxAngle) { return; } Vector3 normal = Vector3.Cross(dir, edge).normalized; Vector3 pointInPlane = useContactPoint ? col.GetContact(0).point : transform.position; CuttingPlane plane = CuttingPlane.InWorldSpace(normal, pointInPlane); CutParams param = new CutParams( cuttable.checkForHoles, true, cuttable.closeOpenSurfaces, cuttable.allowOpenSurfaces, Vector3.zero, float.PositiveInfinity, 0, cuttable.innerTextureCoordinate ); CutResult result = PerformCut(col.gameObject, plane, param); if (result != null) { if (cuttable.polySeparate) { result.PolySeparate(); } result.DestroyObject(); foreach (CutObj res in result.Results) { GameObject resObj = res .UseDefaults() .WithDriftVelocity(driftVelocity) .WithSeperationDistance(seperationDistance) .WithRingWidth(cuttable.highlightWidth) .WithRingColor(cuttable.highLightColor) .FallbackToColor(new Color(1, 0.1f, 0.1f)) .Instantiate(); cuttable.CopyTo(resObj); ignoreColliders.Add(resObj.GetComponent <Collider>()); } } }
public List <MeshPart> PartialPolySeparate( CuttingPlane plane, HashSet <Vector3> allow_cut ) { //Debug.Log("allow_cut"); //foreach (Vector3 v in allow_cut) Debug.Log(VecStr(v)); //Debug.Log("missing"); List <Tuple <HashSet <int>, HashSet <Vector3>, List <int> > > list = new List <Tuple <HashSet <int>, HashSet <Vector3>, List <int> > >(); AssertMatchingCounts(); // create index groups for (int i = 0; i < indices.Count; i += 3) { int i0 = indices[i], i1 = indices[i + 1], i2 = indices[i + 2]; Vector3 v0 = vertices[i0], v1 = vertices[i1], v2 = vertices[i2]; bool ci0 = allow_cut.Contains(v0), ci1 = allow_cut.Contains(v1), ci2 = allow_cut.Contains(v2); AddIndices(list, vertices, v0, v1, v2, i0, i1, i2, ci0, ci1, ci2); } return(list.ConvertAll(set => { MeshPart part = new MeshPart(false); int doSwap = 0, doStay = 0; // temporary solution (?) foreach (int ind in set.Item3) { Vector3 point = vertices[ind]; if (!allow_cut.Contains(point)) { if (plane.IsAbove(point)) { doSwap++; } else { doStay++; } } ; if (part.indexMap.ContainsKey(ind)) { part.indices.Add(part.indexMap[ind]); } else { part.indexMap.Add(ind, part.vertices.Count); part.indices.Add(part.vertices.Count); part.vertices.Add(point); if (uvs.Count > 0) { part.uvs.Add(uvs[ind]); } } } if (doSwap > doStay) { part.SwapSide(); } part.AssertMatchingCounts(); return part; })); }
private CuttingPlane(Vector3 normal, Vector3 pointInPlane, CuttingPlane worldSpace) : base(normal, pointInPlane) { this.worldSpace = worldSpace; }
public static CutResult Run( GameObject target, CuttingPlane plane, CutParams param ) { CuttingPlane cutting_plane = plane.ToLocalSpace(target.transform); Mesh mesh = target.GetComponent <MeshFilter>().mesh; MeshPart pos = new MeshPart(true), neg = new MeshPart(false); RingGenerator rings = new RingGenerator(); //DateTime start = DateTime.Now; Vector2[] uvs = mesh.uv; Vector3[] vertices = mesh.vertices; Vector3[] normals = mesh.normals; int[] triangles = mesh.triangles; bool addUVs = uvs.Length > 0 && param.innerTextureCoord != null, addNormals = normals.Length > 0; // divide mesh in half by vertices int i = 0; foreach (Vector3 vertex in vertices) { if (cutting_plane.IsAbove(vertex)) { pos.indexMap.Add(i, pos.vertices.Count); pos.vertices.Add(vertex); if (addUVs) { pos.uvs.Add(uvs[i]); } if (addNormals) { pos.normals.Add(normals[i]); } } else { neg.indexMap.Add(i, neg.vertices.Count); neg.vertices.Add(vertex); if (addUVs) { neg.uvs.Add(uvs[i]); } if (addNormals) { neg.normals.Add(normals[i]); } } i++; } //Debug.Log((DateTime.Now-start).TotalMilliseconds+" elapsed (1)"); //start = DateTime.Now; // if either vertex list is empty the knife plane didn't collide if (pos.vertices.Count == 0 || neg.vertices.Count == 0) { if (!param.allowSingleResult) { return(null); } } // put triangles in correct mesh for (i = 0; i < triangles.Length; i += 3) { // find orignal indices int i_a = triangles[i], i_b = triangles[i + 1], i_c = triangles[i + 2]; // find original verticies Vector3 a = vertices[i_a], b = vertices[i_b], c = vertices[i_c]; // find original uvs Vector2 txa, txb, txc; if (addUVs) { txa = uvs[i_a]; txb = uvs[i_b]; txc = uvs[i_c]; } else { txa = txb = txc = Vector3.zero; } // find original normals Vector3 na, nb, nc; if (addNormals) { na = normals[i_a]; nb = normals[i_b]; nc = normals[i_c]; } else { na = nb = nc = Vector3.zero; } // seperation check bool aAbove = cutting_plane.IsAbove(a), bAbove = cutting_plane.IsAbove(b), cAbove = cutting_plane.IsAbove(c); if (aAbove && bAbove && cAbove) { // triangle above plane pos.indices.Add(pos.indexMap[i_a]); pos.indices.Add(pos.indexMap[i_b]); pos.indices.Add(pos.indexMap[i_c]); } else if (!aAbove && !bAbove && !cAbove) { // triangle below plane neg.indices.Add(neg.indexMap[i_a]); neg.indices.Add(neg.indexMap[i_b]); neg.indices.Add(neg.indexMap[i_c]); } else { // triangle crosses plane // call Util.GenTriangles if (aAbove == bAbove) { // a, b, c GenTriangles( cutting_plane, aAbove ? pos : neg, !aAbove ? pos : neg, a, b, c, txa, txb, txc, na, nb, nc, i_a, i_b, i_c, rings, addUVs, addNormals ); } else if (aAbove == cAbove) { // c, a, b GenTriangles( cutting_plane, aAbove ? pos : neg, !aAbove ? pos : neg, c, a, b, txc, txa, txb, na, nb, nc, i_c, i_a, i_b, rings, addUVs, addNormals ); } else if (bAbove == cAbove) { // b, c, a (use bAbove) GenTriangles( cutting_plane, bAbove ? pos : neg, !bAbove ? pos : neg, b, c, a, txb, txc, txa, na, nb, nc, i_b, i_c, i_a, rings, addUVs, addNormals ); } } } //Debug.Log((DateTime.Now-start).TotalMilliseconds+" elapsed (2)"); //start = DateTime.Now; List <Ring> ringOut = rings.GetRings(param.selfConnectRings, param.ignorePartialRings); List <Ring> analysis = param.hiearchyAnalysis ? Hierarchy.Analyse(ringOut, cutting_plane.normal) : ringOut; Vector2?innerUV = addUVs ? param.innerTextureCoord : null; // generate seperation meshing foreach (var ring in analysis) { GenerateRingMesh(ring, pos, cutting_plane.normal, innerUV, addNormals); GenerateRingMesh(ring, neg, cutting_plane.normal, innerUV, addNormals); } //Debug.Log((DateTime.Now-start).TotalMilliseconds+" elapsed (3)"); //start = DateTime.Now; return(new CutResult(target, cutting_plane.ToWorldSpace().normal, ringOut, pos, neg)); }
public static CutResult Run( GameObject target, CuttingPlane plane, CutParams param ) { CuttingPlane cutting_plane = plane.ToLocalSpace(target.transform); Mesh mesh = target.GetComponent <MeshFilter>().mesh; MeshPart pos = new MeshPart(true), neg = new MeshPart(false); RingGenerator pos_rings = new RingGenerator(), neg_rings = new RingGenerator(); Vector2[] uvs = mesh.uv; Vector3[] vertices = mesh.vertices; Vector3[] normals = mesh.normals; int[] triangles = mesh.triangles; bool addUVs = uvs.Length > 0 && param.innerTextureCoord != null, addNormals = normals.Length > 0; // removed indices HashSet <int> removed = new HashSet <int>(); // divide mesh in half by vertices int i = -1; foreach (Vector3 vertex in vertices) { i++; float dist = cutting_plane.Distance(vertex); if (dist < param.seperationDistance) { removed.Add(i); continue; } if (cutting_plane.IsAbove(vertex)) { pos.indexMap.Add(i, pos.vertices.Count); pos.vertices.Add(vertex); if (addUVs) { pos.uvs.Add(uvs[i]); } if (addNormals) { pos.normals.Add(normals[i]); } } else { neg.indexMap.Add(i, neg.vertices.Count); neg.vertices.Add(vertex); if (addUVs) { neg.uvs.Add(uvs[i]); } if (addNormals) { pos.normals.Add(normals[i]); } } } // if either vertex list is empty and no vertices were removed, the knife plane didn't collide if (pos.vertices.Count == 0 || neg.vertices.Count == 0) { if (!param.allowSingleResult) { return(null); } } // put triangles in correct mesh for (i = 0; i < triangles.Length; i += 3) { // find orignal indices int i_a = triangles[i], i_b = triangles[i + 1], i_c = triangles[i + 2]; // find if these were removed in cut bool r_a = removed.Contains(i_a), r_b = removed.Contains(i_b), r_c = removed.Contains(i_c); // if all are removed, ignore triangle if (r_a && r_b && r_c) { continue; } // find original verticies Vector3 a = vertices[i_a], b = vertices[i_b], c = vertices[i_c]; Vector2 txa, txb, txc; // find original uvs if (uvs.Length > 0) { txa = uvs[i_a]; txb = uvs[i_b]; txc = uvs[i_c]; } else { txa = txb = txc = Vector2.zero; } // find original normals Vector3 na, nb, nc; if (addNormals) { na = normals[i_a]; nb = normals[i_b]; nc = normals[i_c]; } else { na = nb = nc = Vector3.zero; } // seperation check bool aAbove = cutting_plane.IsAbove(a), bAbove = cutting_plane.IsAbove(b), cAbove = cutting_plane.IsAbove(c); if (!r_a && !r_b && !r_c) { // all available if (aAbove && bAbove && cAbove) { // triangle above plane pos.indices.Add(pos.indexMap[i_a]); pos.indices.Add(pos.indexMap[i_b]); pos.indices.Add(pos.indexMap[i_c]); } else if (!aAbove && !bAbove && !cAbove) { // triangle below plane neg.indices.Add(neg.indexMap[i_a]); neg.indices.Add(neg.indexMap[i_b]); neg.indices.Add(neg.indexMap[i_c]); } else { // triangle crosses plane if (aAbove == bAbove) { // a, b, c GenTwoTriangles( cutting_plane, aAbove ? pos : neg, a, b, c, txa, txb, txc, na, nb, nc, i_a, i_b, i_c, aAbove ? pos_rings : neg_rings, addUVs, addNormals, -param.seperationDistance ); GenTriangle( cutting_plane, cAbove ? pos : neg, c, a, b, txc, txa, txb, nc, na, nb, i_c, i_a, i_b, cAbove ? pos_rings : neg_rings, addUVs, addNormals, param.seperationDistance ); } else if (aAbove == cAbove) { // c, a, b GenTwoTriangles( cutting_plane, aAbove ? pos : neg, c, a, b, txc, txa, txb, nc, na, nb, i_c, i_a, i_b, aAbove ? pos_rings : neg_rings, addUVs, addNormals, -param.seperationDistance ); GenTriangle( cutting_plane, bAbove ? pos : neg, b, c, a, txb, txc, txa, nb, nc, na, i_b, i_c, i_a, bAbove ? pos_rings : neg_rings, addUVs, addNormals, param.seperationDistance ); } else if (bAbove == cAbove) { // b, c, a GenTwoTriangles( cutting_plane, bAbove ? pos : neg, b, c, a, txb, txc, txa, nb, nc, na, i_b, i_c, i_a, bAbove ? pos_rings : neg_rings, addUVs, addNormals, -param.seperationDistance ); GenTriangle( cutting_plane, aAbove ? pos : neg, a, b, c, txa, txb, txc, na, nb, nc, i_a, i_b, i_c, aAbove ? pos_rings : neg_rings, addUVs, addNormals, param.seperationDistance ); } } } else if (!r_a && !r_b) { // a and b available if (aAbove != bAbove) { GenTriangle( cutting_plane, aAbove ? pos : neg, a, b, c, txa, txb, txc, na, nb, nc, i_a, i_b, i_c, aAbove ? pos_rings : neg_rings, addUVs, addNormals, param.seperationDistance ); GenTriangle( cutting_plane, bAbove ? pos : neg, b, c, a, txb, txc, txa, nb, nc, na, i_b, i_c, i_a, bAbove ? pos_rings : neg_rings, addUVs, addNormals, param.seperationDistance ); } else { GenTwoTriangles( cutting_plane, aAbove ? pos : neg, a, b, c, txa, txb, txc, na, nb, nc, i_a, i_b, i_c, aAbove ? pos_rings : neg_rings, addUVs, addNormals, -param.seperationDistance ); } } else if (!r_a && !r_c) { // a and c available if (aAbove != cAbove) { GenTriangle( cutting_plane, aAbove ? pos : neg, a, b, c, txa, txb, txc, na, nb, nc, i_a, i_b, i_c, aAbove ? pos_rings : neg_rings, addUVs, addNormals, param.seperationDistance ); GenTriangle( cutting_plane, cAbove ? pos : neg, c, a, b, txc, txa, txb, nc, na, nb, i_c, i_a, i_b, cAbove ? pos_rings : neg_rings, addUVs, addNormals, param.seperationDistance ); } else { GenTwoTriangles( cutting_plane, aAbove ? pos : neg, c, a, b, txc, txa, txb, nc, na, nb, i_c, i_a, i_b, aAbove ? pos_rings : neg_rings, addUVs, addNormals, -param.seperationDistance ); } } else if (!r_b && !r_c) { // b and c available if (bAbove != cAbove) { GenTriangle( cutting_plane, bAbove ? pos : neg, b, c, a, txb, txc, txa, nb, nc, na, i_b, i_c, i_a, bAbove ? pos_rings : neg_rings, addUVs, addNormals, param.seperationDistance ); GenTriangle( cutting_plane, cAbove ? pos : neg, c, a, b, txc, txa, txb, nc, na, nb, i_c, i_a, i_b, cAbove ? pos_rings : neg_rings, addUVs, addNormals, param.seperationDistance ); } else { GenTwoTriangles( cutting_plane, bAbove ? pos : neg, b, c, a, txb, txc, txa, nb, nc, na, i_b, i_c, i_a, bAbove ? pos_rings : neg_rings, addUVs, addNormals, -param.seperationDistance ); } } else if (!r_a) { // a available GenTriangle( cutting_plane, aAbove ? pos : neg, a, b, c, txa, txb, txc, na, nb, nc, i_a, i_b, i_c, aAbove ? pos_rings : neg_rings, addUVs, addNormals, param.seperationDistance ); } else if (!r_b) { // b available GenTriangle( cutting_plane, bAbove ? pos : neg, b, c, a, txb, txc, txa, nb, nc, na, i_b, i_c, i_a, bAbove ? pos_rings : neg_rings, addUVs, addNormals, param.seperationDistance ); } else { // c available GenTriangle( cutting_plane, cAbove ? pos : neg, c, a, b, txc, txa, txb, nc, na, nb, i_c, i_a, i_b, cAbove ? pos_rings : neg_rings, addUVs, addNormals, param.seperationDistance ); } } List <Ring> pos_ring_res = pos_rings.GetRings(param.selfConnectRings, param.ignorePartialRings); List <Ring> neg_ring_res = neg_rings.GetRings(param.selfConnectRings, param.ignorePartialRings); List <Ring> pos_analysis = param.hiearchyAnalysis ? Hierarchy.Analyse(pos_ring_res, cutting_plane.normal) : pos_ring_res; List <Ring> neg_analysis = param.hiearchyAnalysis ? Hierarchy.Analyse(neg_ring_res, cutting_plane.normal) : neg_ring_res; Vector2?innerUV = addUVs ? param.innerTextureCoord : null; // generate seperation meshing foreach (var ring in pos_analysis) { GenerateRingMesh(ring, pos, cutting_plane.normal, innerUV); } foreach (var ring in neg_analysis) { GenerateRingMesh(ring, neg, cutting_plane.normal, innerUV); } List <MeshPart> resParts = new List <MeshPart>(); if (pos.vertices.Count > 0) { resParts.Add(pos); } if (neg.vertices.Count > 0) { resParts.Add(neg); } if (resParts.Count < 2 && !param.allowSingleResult) { return(null); } return(new CutResult(target, resParts, cutting_plane.ToWorldSpace().normal, new List <Ring>(), false)); }
public static void GenPartialTriangles( CuttingPlane plane, MeshPart part, Vector3 a, Vector3 b, Vector3 c, Vector2 txa, Vector2 txb, Vector2 txc, int i_a, int i_b, int i_c, HashSet <Vector3> allow_cut, bool addUVs ) { // find intersection vertices / uvs var es = plane.Intersection(a, c, txa, txc, 0); var ds = plane.Intersection(b, c, txb, txc, 0); Vector3 e = es.Item1, d = ds.Item1; Vector2 txe = es.Item2, txd = ds.Item2; // if e == d, the three vertices lie in a line, // and thus do not make up a triangle if (e == d) { return; // not sure if this is nescessary throw MeshUtilsException.ZeroAreaTriangle(); } if ( !allow_cut.Contains(e) && !allow_cut.Contains(d) ) { // triangle must not be cut part.indices.Add(part.indexMap[i_a]); part.indices.Add(part.indexMap[i_b]); part.indices.Add(part.indexMap[i_c]); return; } // new indices int i0 = part.vertices.Count, i1 = part.vertices.Count + 2; // add new vertices and uvs part.vertices.Add(d); part.vertices.Add(e); part.vertices.Add(d); part.vertices.Add(e); if (addUVs) { part.uvs.Add(txd); part.uvs.Add(txe); part.uvs.Add(txd); part.uvs.Add(txe); } // generate triangles ... // add a,d,e part.indices.Add(part.indexMap[i_a]); part.indices.Add(i0); part.indices.Add(i0 + 1); // add a,b,d part.indices.Add(part.indexMap[i_a]); part.indices.Add(part.indexMap[i_b]); part.indices.Add(i0); // add e,d,c part.indices.Add(i1 + 1); part.indices.Add(i1); part.indices.Add(part.indexMap[i_c]); }
// ------------------------------------------------------------ // Generate single triangle for an intersecting triangle a,b,c // It is assumed that a is on the positive half plane // ------------------------------------------------------------ public static void GenTriangle( CuttingPlane plane, MeshPart pos, Vector3 a, Vector3 b, Vector3 c, Vector2 txa, Vector2 txb, Vector2 txc, Vector3 na, Vector3 nb, Vector3 nc, int i_a, int i_b, int i_c, RingGenerator rings, bool addUVs, bool addNormals, float shift ) { // find intersection vertices / uvs var es = plane.Intersection(c, a, txa, txc, nc, na, shift); var ds = plane.Intersection(b, a, txb, txc, nb, na, shift); Vector3 e = es.Item1, d = ds.Item1; Vector2 txe = es.Item2, txd = ds.Item2; Vector3 ne = es.Item3, nd = ds.Item3; // if e == d, the three vertices lie in a line, // and thus do not make up a triangle if (e == d) { return; // not sure if this is nescessary throw MeshUtilsException.ZeroAreaTriangle(); } // new indices int i0 = pos.vertices.Count; // add connected pair in ring generator // find proper direction for ring Vector3 tri_nor = Vector3.Cross(c - a, c - b); bool dir = Vector3.Dot(e - d, Vector3.Cross(plane.normal, tri_nor)) > 0; rings.AddConnected(dir?e:d, dir?d:e); // add new vertices and uvs pos.vertices.Add(d); pos.vertices.Add(e); if (addUVs) { pos.uvs.Add(txd); pos.uvs.Add(txe); } if (addNormals) { pos.normals.Add(nd); pos.normals.Add(ne); } // add a,d,e to positive indicies pos.indices.Add(pos.indexMap[i_a]); pos.indices.Add(i0); pos.indices.Add(i0 + 1); }
public static CutResult Run( GameObject target, CuttingPlane plane, CutParams param ) { CuttingPlane cutting_plane = plane.ToLocalSpace(target.transform); Mesh mesh = target.GetComponent <MeshFilter>().mesh; MeshPart part = new MeshPart(false); Vector2[] uvs = mesh.uv; Vector3[] vertices = mesh.vertices; int[] triangles = mesh.triangles; // // First we find the rings that are eligable for cutting // RingGenerator rings = new RingGenerator(); int i; for (i = 0; i < triangles.Length; i += 3) { // find orignal indices int i_a = triangles[i], i_b = triangles[i + 1], i_c = triangles[i + 2]; // find original verticies Vector3 a = vertices[i_a], b = vertices[i_b], c = vertices[i_c]; // seperation check bool aAbove = cutting_plane.IsAbove(a), bAbove = cutting_plane.IsAbove(b), cAbove = cutting_plane.IsAbove(c); if (aAbove == bAbove && aAbove == cAbove) { continue; } if (aAbove == bAbove) { // a, b, c GenIntersection( cutting_plane, a, b, c, rings ); } else if (aAbove == cAbove) { // c, a, b GenIntersection( cutting_plane, c, a, b, rings ); } else if (bAbove == cAbove) { // b, c, a GenIntersection( cutting_plane, b, c, a, rings ); } } Vector3 point = target.transform.InverseTransformPoint(param.originPoint); List <Ring> resulting_rings = new List <Ring>(); foreach (Ring ring in rings.GetRings(param.selfConnectRings, param.ignorePartialRings)) { Vector3 vec = ring.FurthestVectorToRingPerimeter(point); vec = target.transform.TransformVector(vec); // Debug.DrawRay(param.originPoint,vec,Color.blue,10); float mag = vec.magnitude; Debug.Log(mag); if (mag < param.maxCutDistance) { resulting_rings.Add(ring); } } if (resulting_rings.Count == 0) { return(null); } // Debug.Log(resulting_rings.Count); HashSet <Vector3> allow_cut = new HashSet <Vector3>(); foreach (Ring ring in resulting_rings) { foreach (Vector3 v in ring.verts) { allow_cut.Add(v); } } // // Start of cutting // bool addUVs = uvs.Length > 0 && param.innerTextureCoord != null; // transfer vertices into MeshPart i = 0; foreach (Vector3 vertex in vertices) { part.indexMap.Add(i, part.vertices.Count); part.vertices.Add(vertex); if (addUVs) { part.uvs.Add(uvs[i]); } i++; } // process triangles for (i = 0; i < triangles.Length; i += 3) { // find orignal indices int i_a = triangles[i], i_b = triangles[i + 1], i_c = triangles[i + 2]; // find original verticies Vector3 a = vertices[i_a], b = vertices[i_b], c = vertices[i_c]; Vector2 txa, txb, txc; // find original uvs if (uvs.Length > 0) { txa = uvs[i_a]; txb = uvs[i_b]; txc = uvs[i_c]; } else { txa = txb = txc = Vector2.zero; } // seperation check bool aAbove = cutting_plane.IsAbove(a), bAbove = cutting_plane.IsAbove(b), cAbove = cutting_plane.IsAbove(c); if (aAbove == bAbove && aAbove == cAbove) { // triangle on one side of plane part.indices.Add(part.indexMap[i_a]); part.indices.Add(part.indexMap[i_b]); part.indices.Add(part.indexMap[i_c]); } else { // triangle crosses plane if (aAbove == bAbove) { // a, b, c GenPartialTriangles( cutting_plane, part, a, b, c, txa, txb, txc, i_a, i_b, i_c, allow_cut, addUVs ); } else if (aAbove == cAbove) { // c, a, b GenPartialTriangles( cutting_plane, part, c, a, b, txc, txa, txb, i_c, i_a, i_b, allow_cut, addUVs ); } else if (bAbove == cAbove) { // b, c, a GenPartialTriangles( cutting_plane, part, b, c, a, txb, txc, txa, i_b, i_c, i_a, allow_cut, addUVs ); } } } List <Ring> analysis = param.hiearchyAnalysis ? Hierarchy.Analyse(resulting_rings, cutting_plane.normal) : resulting_rings; List <MeshPart> parts = part.PartialPolySeparate(cutting_plane, allow_cut); if (parts.Count < 2 && !param.allowSingleResult) { return(null); } // generate seperation meshing if (parts.Count > 0) { foreach (var ring in analysis) { foreach (var resPart in parts) { GenerateRingMesh(ring, resPart, cutting_plane.normal, param.innerTextureCoord); } } } return(new CutResult(target, parts, cutting_plane.ToWorldSpace().normal, resulting_rings, true)); }