/// <summary> /// apply physical explosion to fragment piece (2D case) /// </summary> void ApplyExplosion2D(ExploderTransform meshTransform, Vector3 centroid, float force, GameObject original) { var rigid = rigid2D; // apply fragment mass and velocity properties var parentVelocity = Vector2.zero; var parentAngularVelocity = 0.0f; var mass = settings.FragmentOptions.Mass; // inherit velocity and mass from original object if (settings.FragmentOptions.InheritParentPhysicsProperty) { if (original && original.GetComponent <Rigidbody2D>()) { var parentRigid = original.GetComponent <Rigidbody2D>(); parentVelocity = parentRigid.velocity; parentAngularVelocity = parentRigid.angularVelocity; mass = parentRigid.mass / settings.TargetFragments; } } Vector2 forceVector = (meshTransform.TransformPoint(centroid) - settings.Position).normalized; float angularVelocity = settings.FragmentOptions.AngularVelocity * (settings.FragmentOptions.RandomAngularVelocityVector ? Random.insideUnitCircle.x : settings.FragmentOptions.AngularVelocityVector.y); if (settings.UseForceVector) { forceVector = settings.ForceVector; } rigid.velocity = forceVector * force + parentVelocity; rigid.angularVelocity = angularVelocity + parentAngularVelocity; rigid.mass = mass; }
/// <summary> /// cut mesh by plane /// </summary> /// <param name="mesh">mesh to cut</param> /// <param name="meshTransform">transformation of the mesh</param> /// <param name="plane">cutting plane</param> /// <param name="triangulateHoles">flag for triangulation of holes</param> /// <param name="crossSectionVertexColor">this color will be assigned to cross section, valid only for vertex color shaders</param> /// <param name="crossUV">uv mapping area for cross section</param> /// <param name="allowOpenMesh">allow cutting of open mesh</param> /// <returns>processing time</returns> public float Cut(ExploderMesh mesh, ExploderTransform meshTransform, Plane plane, bool triangulateHoles, bool allowOpenMesh, ref List <ExploderMesh> meshes, Color crossSectionVertexColor, Vector4 crossUV) { this.crossSectionVertexColour = crossSectionVertexColor; this.crossSectionUV = crossUV; return(Cut(mesh, meshTransform, plane, triangulateHoles, allowOpenMesh, ref meshes)); }
private void ApplyExplosion2D( ExploderTransform meshTransform, Vector3 centroid, float force, GameObject original) { Rigidbody2D rigid2D = this.rigid2D; Vector2 vector2_1 = Vector2.get_zero(); float num1 = 0.0f; float num2 = this.settings.FragmentOptions.Mass; if (this.settings.FragmentOptions.InheritParentPhysicsProperty && Object.op_Implicit((Object)original) && Object.op_Implicit((Object)original.GetComponent <Rigidbody2D>())) { Rigidbody2D component = (Rigidbody2D)original.GetComponent <Rigidbody2D>(); vector2_1 = component.get_velocity(); num1 = component.get_angularVelocity(); num2 = component.get_mass() / (float)this.settings.TargetFragments; } Vector3 vector3 = Vector3.op_Subtraction(meshTransform.TransformPoint(centroid), this.settings.Position); Vector2 vector2_2 = Vector2.op_Implicit(((Vector3) ref vector3).get_normalized()); float num3 = this.settings.FragmentOptions.AngularVelocity * (!this.settings.FragmentOptions.RandomAngularVelocityVector ? (float)this.settings.FragmentOptions.AngularVelocityVector.y : (float)Random.get_insideUnitCircle().x); if (this.settings.UseForceVector) { vector2_2 = Vector2.op_Implicit(this.settings.ForceVector); } rigid2D.set_velocity(Vector2.op_Addition(Vector2.op_Multiply(vector2_2, force), vector2_1)); rigid2D.set_angularVelocity(num3 + num1); rigid2D.set_mass(num2); }
/// <summary> /// make inverse transformation of this plane to target space /// </summary> /// <param name="transform">target transformation space</param> public void InverseTransform(ExploderTransform transform) { // inverse transform normal var inverseNormal = transform.InverseTransformDirection(Normal); // inverse transform point var inversePoint = transform.InverseTransformPoint(Pnt); // update plane Normal = inverseNormal; Distance = Vector3.Dot(inverseNormal, inversePoint); }
/// <summary> /// apply physical explosion to fragment piece /// </summary> public void ApplyExplosion(ExploderTransform meshTransform, Vector3 centroid, Vector3 mainCentroid, ExploderObject.FragmentOption fragmentOption, bool useForceVector, Vector3 ForceVector, float force, GameObject original, int targetFragments) { if (rigid2D) { ApplyExplosion2D(meshTransform, centroid, mainCentroid, fragmentOption, useForceVector, ForceVector, force, original, targetFragments); return; } var rigid = rigidBody; // apply fragment mass and velocity properties var parentVelocity = Vector3.zero; var parentAngularVelocity = Vector3.zero; var mass = fragmentOption.Mass; var useGravity = fragmentOption.UseGravity; rigid.maxAngularVelocity = fragmentOption.MaxAngularVelocity; // inherit velocity and mass from original object if (fragmentOption.InheritParentPhysicsProperty) { if (original && original.GetComponent <Rigidbody>()) { var parentRigid = original.GetComponent <Rigidbody>(); parentVelocity = parentRigid.velocity; parentAngularVelocity = parentRigid.angularVelocity; mass = parentRigid.mass / targetFragments; useGravity = parentRigid.useGravity; } } var forceVector = (meshTransform.TransformPoint(centroid) - mainCentroid).normalized; var angularVelocity = fragmentOption.AngularVelocity * (fragmentOption.RandomAngularVelocityVector ? Random.onUnitSphere : fragmentOption.AngularVelocityVector); if (useForceVector) { forceVector = ForceVector; } rigid.velocity = forceVector * force + parentVelocity; rigid.angularVelocity = angularVelocity + parentAngularVelocity; rigid.mass = mass; maxVelocity = fragmentOption.MaxVelocity; rigid.useGravity = useGravity; }
/// <summary> /// apply physical explosion to fragment piece /// </summary> public void ApplyExplosion(ExploderTransform meshTransform, Vector3 centroid, float force, GameObject original, ExploderParams set) { this.settings = set; if (rigid2D) { ApplyExplosion2D(meshTransform, centroid, force, original); return; } var rigid = rigidBody; // apply fragment mass and velocity properties var parentVelocity = Vector3.zero; var parentAngularVelocity = Vector3.zero; var mass = settings.FragmentOptions.Mass; var useGravity = settings.FragmentOptions.UseGravity; rigid.maxAngularVelocity = settings.FragmentOptions.MaxAngularVelocity; // inherit velocity and mass from original object if (settings.FragmentOptions.InheritParentPhysicsProperty) { if (original && original.GetComponent <Rigidbody>()) { var parentRigid = original.GetComponent <Rigidbody>(); parentVelocity = parentRigid.velocity; parentAngularVelocity = parentRigid.angularVelocity; mass = parentRigid.mass / settings.TargetFragments; useGravity = parentRigid.useGravity; } } var forceVector = (meshTransform.TransformPoint(centroid) - settings.Position).normalized; var angularVelocity = settings.FragmentOptions.AngularVelocity * (settings.FragmentOptions.RandomAngularVelocityVector ? Random.onUnitSphere : settings.FragmentOptions.AngularVelocityVector); if (settings.UseForceVector) { forceVector = settings.ForceVector; } rigid.velocity = forceVector * force + parentVelocity; rigid.angularVelocity = angularVelocity + parentAngularVelocity; rigid.mass = mass; rigid.useGravity = useGravity; }
public void ApplyExplosion( ExploderTransform meshTransform, Vector3 centroid, float force, GameObject original, ExploderParams set) { this.settings = set; if (Object.op_Implicit((Object)this.rigid2D)) { this.ApplyExplosion2D(meshTransform, centroid, force, original); } else { Rigidbody rigidBody = this.rigidBody; Vector3 vector3_1 = Vector3.get_zero(); Vector3 vector3_2 = Vector3.get_zero(); float num = this.settings.FragmentOptions.Mass; bool useGravity = this.settings.FragmentOptions.UseGravity; rigidBody.set_maxAngularVelocity(this.settings.FragmentOptions.MaxAngularVelocity); if (this.settings.FragmentOptions.InheritParentPhysicsProperty && Object.op_Implicit((Object)original) && Object.op_Implicit((Object)original.GetComponent <Rigidbody>())) { Rigidbody component = (Rigidbody)original.GetComponent <Rigidbody>(); vector3_1 = component.get_velocity(); vector3_2 = component.get_angularVelocity(); num = component.get_mass() / (float)this.settings.TargetFragments; useGravity = component.get_useGravity(); } Vector3 vector3_3 = Vector3.op_Subtraction(meshTransform.TransformPoint(centroid), this.settings.Position); Vector3 vector3_4 = ((Vector3) ref vector3_3).get_normalized(); Vector3 vector3_5 = Vector3.op_Multiply(this.settings.FragmentOptions.AngularVelocity, !this.settings.FragmentOptions.RandomAngularVelocityVector ? this.settings.FragmentOptions.AngularVelocityVector : Random.get_onUnitSphere()); if (this.settings.UseForceVector) { vector3_4 = this.settings.ForceVector; } rigidBody.set_velocity(Vector3.op_Addition(Vector3.op_Multiply(vector3_4, force), vector3_1)); rigidBody.set_angularVelocity(Vector3.op_Addition(vector3_5, vector3_2)); rigidBody.set_mass(num); rigidBody.set_useGravity(useGravity); } }
/// <summary> /// apply physical explosion to fragment piece (2D case) /// </summary> void ApplyExplosion2D(ExploderTransform meshTransform, Vector3 centroid, Vector3 mainCentroid, ExploderObject.FragmentOption fragmentOption, bool useForceVector, Vector2 ForceVector, float force, GameObject original, int targetFragments) { var rigid = rigid2D; // apply fragment mass and velocity properties var parentVelocity = Vector2.zero; var parentAngularVelocity = 0.0f; var mass = fragmentOption.Mass; // inherit velocity and mass from original object if (fragmentOption.InheritParentPhysicsProperty) { if (original && original.GetComponent <Rigidbody2D>()) { var parentRigid = original.GetComponent <Rigidbody2D>(); parentVelocity = parentRigid.velocity; parentAngularVelocity = parentRigid.angularVelocity; mass = parentRigid.mass / targetFragments; } } Vector2 forceVector = (meshTransform.TransformPoint(centroid) - mainCentroid).normalized; float angularVelocity = fragmentOption.AngularVelocity * (fragmentOption.RandomAngularVelocityVector ? Random.insideUnitCircle.x : fragmentOption.AngularVelocityVector.y); if (useForceVector) { forceVector = ForceVector; } rigid.velocity = forceVector * force + parentVelocity; rigid.angularVelocity = angularVelocity + parentAngularVelocity; rigid.mass = mass; maxVelocity = fragmentOption.MaxVelocity; }
float Cut(ExploderMesh mesh, ExploderTransform meshTransform, Plane plane, bool triangulateHoles, bool allowOpenMesh, ref List <ExploderMesh> meshes) { var stopWatch = new Stopwatch(); stopWatch.Start(); #if PROFILING MeasureIt.Begin("CutAllocations"); #endif // cache mesh data var trianglesNum = mesh.triangles.Length; var verticesNum = mesh.vertices.Length; var meshTriangles = mesh.triangles; var meshTangents = mesh.tangents; var meshColors = mesh.colors32; var meshVertices = mesh.vertices; var meshNormals = mesh.normals; var meshUV = mesh.uv; var useMeshTangents = meshTangents != null && meshTangents.Length > 0; var useVertexColors = meshColors != null && meshColors.Length > 0; var useNormals = meshNormals != null && meshNormals.Length > 0; // preallocate buffers AllocateBuffers(trianglesNum, verticesNum, useMeshTangents, useVertexColors); ExploderMesh mesh0, mesh1; #if PROFILING MeasureIt.End("CutAllocations"); MeasureIt.Begin("CutCycleFirstPass"); #endif // first pass - find complete triangles on both sides of the plane for (int i = 0; i < trianglesNum; i += 3) { // get triangle points var v0 = meshVertices[meshTriangles[i]]; var v1 = meshVertices[meshTriangles[i + 1]]; var v2 = meshVertices[meshTriangles[i + 2]]; var side0 = plane.GetSideFix(ref v0); var side1 = plane.GetSideFix(ref v1); var side2 = plane.GetSideFix(ref v2); meshVertices[meshTriangles[i]] = v0; meshVertices[meshTriangles[i + 1]] = v1; meshVertices[meshTriangles[i + 2]] = v2; // Utils.Log(plane.Pnt + " " + v0 + " " + v1 + " " + " " + v2); // all points on one side if (side0 == side1 && side1 == side2) { var idx = side0 ? 0 : 1; if (meshTriangles[i] >= triCache.Length) { ExploderUtils.Log("TriCacheError " + meshTriangles[i] + " " + triCache.Length + " " + meshVertices.Length); } if (triCache[meshTriangles[i]] == 0) { triangles[idx].Add(triCounter[idx]); vertices[idx].Add(meshVertices[meshTriangles[i]]); uvs[idx].Add(meshUV[meshTriangles[i]]); if (useNormals) { normals[idx].Add(meshNormals[meshTriangles[i]]); } if (useMeshTangents) { tangents[idx].Add(meshTangents[meshTriangles[i]]); } if (useVertexColors) { vertexColors[idx].Add(meshColors[meshTriangles[i]]); } centroid[idx] += meshVertices[meshTriangles[i]]; triCache[meshTriangles[i]] = triCounter[idx] + 1; triCounter[idx]++; } else { triangles[idx].Add(triCache[meshTriangles[i]] - 1); } if (triCache[meshTriangles[i + 1]] == 0) { triangles[idx].Add(triCounter[idx]); vertices[idx].Add(meshVertices[meshTriangles[i + 1]]); uvs[idx].Add(meshUV[meshTriangles[i + 1]]); if (useNormals) { normals[idx].Add(meshNormals[meshTriangles[i + 1]]); } if (useMeshTangents) { tangents[idx].Add(meshTangents[meshTriangles[i + 1]]); } if (useVertexColors) { vertexColors[idx].Add(meshColors[meshTriangles[i + 1]]); } centroid[idx] += meshVertices[meshTriangles[i + 1]]; triCache[meshTriangles[i + 1]] = triCounter[idx] + 1; triCounter[idx]++; } else { triangles[idx].Add(triCache[meshTriangles[i + 1]] - 1); } if (triCache[meshTriangles[i + 2]] == 0) { triangles[idx].Add(triCounter[idx]); vertices[idx].Add(meshVertices[meshTriangles[i + 2]]); uvs[idx].Add(meshUV[meshTriangles[i + 2]]); if (useNormals) { normals[idx].Add(meshNormals[meshTriangles[i + 2]]); } if (useMeshTangents) { tangents[idx].Add(meshTangents[meshTriangles[i + 2]]); } if (useVertexColors) { vertexColors[idx].Add(meshColors[meshTriangles[i + 2]]); } centroid[idx] += meshVertices[meshTriangles[i + 2]]; triCache[meshTriangles[i + 2]] = triCounter[idx] + 1; triCounter[idx]++; } else { triangles[idx].Add(triCache[meshTriangles[i + 2]] - 1); } } else { // intersection triangles add to list and process it in second pass cutTris.Add(i); } } if (vertices[0].Count == 0) { centroid[0] = meshVertices[0]; } else { centroid[0] /= vertices[0].Count; } if (vertices[1].Count == 0) { centroid[1] = meshVertices[1]; } else { centroid[1] /= vertices[1].Count; } // UnityEngine.Debug.LogFormat("cut: {0} -- {1}, normal: {2}, tris: {3}", vertices[0].Count, vertices[1].Count, plane.Normal, cutTris.Count); #if PROFILING MeasureIt.End("CutCycleFirstPass"); MeasureIt.Begin("CutCycleSecondPass"); #endif if (cutTris.Count < 1) { stopWatch.Stop(); return(stopWatch.ElapsedMilliseconds); } AllocateContours(cutTris.Count); // second pass - cut intersecting triangles in half foreach (var cutTri in cutTris) { var triangle = new Triangle { ids = new[] { meshTriangles[cutTri + 0], meshTriangles[cutTri + 1], meshTriangles[cutTri + 2] }, pos = new[] { meshVertices[meshTriangles[cutTri + 0]], meshVertices[meshTriangles[cutTri + 1]], meshVertices[meshTriangles[cutTri + 2]] }, normal = useNormals ? new[] { meshNormals[meshTriangles[cutTri + 0]], meshNormals[meshTriangles[cutTri + 1]], meshNormals[meshTriangles[cutTri + 2]] } : new[] { Vector3.zero, Vector3.zero, Vector3.zero }, uvs = new[] { meshUV[meshTriangles[cutTri + 0]], meshUV[meshTriangles[cutTri + 1]], meshUV[meshTriangles[cutTri + 2]] }, tangents = useMeshTangents ? new[] { meshTangents[meshTriangles[cutTri + 0]], meshTangents[meshTriangles[cutTri + 1]], meshTangents[meshTriangles[cutTri + 2]] } : new [] { Vector4.zero, Vector4.zero, Vector4.zero }, colors = useVertexColors ? new[] { meshColors[meshTriangles[cutTri + 0]], meshColors[meshTriangles[cutTri + 1]], meshColors[meshTriangles[cutTri + 2]] } : new Color32[] { Color.white, Color.white, Color.white }, }; // check points with a plane var side0 = plane.GetSide(triangle.pos[0]); var side1 = plane.GetSide(triangle.pos[1]); var side2 = plane.GetSide(triangle.pos[2]); float t0, t1; Vector3 s0 = Vector3.zero, s1 = Vector3.zero; var idxLeft = side0 ? 0 : 1; var idxRight = 1 - idxLeft; if (side0 == side1) { var a = plane.IntersectSegment(triangle.pos[2], triangle.pos[0], out t0, ref s0); var b = plane.IntersectSegment(triangle.pos[2], triangle.pos[1], out t1, ref s1); ExploderUtils.Assert(a && b, "!!!!!!!!!!!!!!!"); // left side ... 2 triangles var s0Left = AddIntersectionPoint(s0, triangle, triangle.ids[2], triangle.ids[0], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var s1Left = AddIntersectionPoint(s1, triangle, triangle.ids[2], triangle.ids[1], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var v0Left = AddTrianglePoint(triangle.pos[0], triangle.normal[0], triangle.uvs[0], triangle.tangents[0], triangle.colors[0], triangle.ids[0], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var v1Left = AddTrianglePoint(triangle.pos[1], triangle.normal[1], triangle.uvs[1], triangle.tangents[1], triangle.colors[1], triangle.ids[1], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); // Triangle (s0, v0, s1) triangles[idxLeft].Add(s0Left); triangles[idxLeft].Add(v0Left); triangles[idxLeft].Add(s1Left); // Triangle (s1, v0, v1) triangles[idxLeft].Add(s1Left); triangles[idxLeft].Add(v0Left); triangles[idxLeft].Add(v1Left); // right side ... 1 triangle var s0Right = AddIntersectionPoint(s0, triangle, triangle.ids[2], triangle.ids[0], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); var s1Right = AddIntersectionPoint(s1, triangle, triangle.ids[2], triangle.ids[1], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); var v2Right = AddTrianglePoint(triangle.pos[2], triangle.normal[2], triangle.uvs[2], triangle.tangents[2], triangle.colors[2], triangle.ids[2], triCache, cornerVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); // Triangle (v2, s0, s1) triangles[idxRight].Add(v2Right); triangles[idxRight].Add(s0Right); triangles[idxRight].Add(s1Right); // buffer intersection vertices for triangulation if (triangulateHoles) { if (idxLeft == 0) { contour.AddTriangle(cutTri, s0Left, s1Left, s0, s1); } else { contour.AddTriangle(cutTri, s0Right, s1Right, s0, s1); } } } else if (side0 == side2) { var a = plane.IntersectSegment(triangle.pos[1], triangle.pos[0], out t0, ref s1); var b = plane.IntersectSegment(triangle.pos[1], triangle.pos[2], out t1, ref s0); ExploderUtils.Assert(a && b, "!!!!!!!!!!!!!"); // left side ... 2 triangles var s0Left = AddIntersectionPoint(s0, triangle, triangle.ids[1], triangle.ids[2], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var s1Left = AddIntersectionPoint(s1, triangle, triangle.ids[1], triangle.ids[0], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var v0Left = AddTrianglePoint(triangle.pos[0], triangle.normal[0], triangle.uvs[0], triangle.tangents[0], triangle.colors[0], triangle.ids[0], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var v2Left = AddTrianglePoint(triangle.pos[2], triangle.normal[2], triangle.uvs[2], triangle.tangents[2], triangle.colors[2], triangle.ids[2], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); // Triangle (v2, s1, s0) triangles[idxLeft].Add(v2Left); triangles[idxLeft].Add(s1Left); triangles[idxLeft].Add(s0Left); // Triangle (v2, v0, s1) triangles[idxLeft].Add(v2Left); triangles[idxLeft].Add(v0Left); triangles[idxLeft].Add(s1Left); // right side ... 1 triangle var s0Right = AddIntersectionPoint(s0, triangle, triangle.ids[1], triangle.ids[2], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); var s1Right = AddIntersectionPoint(s1, triangle, triangle.ids[1], triangle.ids[0], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); var v1Right = AddTrianglePoint(triangle.pos[1], triangle.normal[1], triangle.uvs[1], triangle.tangents[1], triangle.colors[1], triangle.ids[1], triCache, cornerVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); // Triangle (s0, s1, v1) triangles[idxRight].Add(s0Right); triangles[idxRight].Add(s1Right); triangles[idxRight].Add(v1Right); // buffer intersection vertices for triangulation if (triangulateHoles) { if (idxLeft == 0) { contour.AddTriangle(cutTri, s0Left, s1Left, s0, s1); } else { contour.AddTriangle(cutTri, s0Right, s1Right, s0, s1); } } } else { var a = plane.IntersectSegment(triangle.pos[0], triangle.pos[1], out t0, ref s0); var b = plane.IntersectSegment(triangle.pos[0], triangle.pos[2], out t1, ref s1); ExploderUtils.Assert(a && b, "!!!!!!!!!!!!!"); // right side ... 2 triangles var s0Right = AddIntersectionPoint(s0, triangle, triangle.ids[0], triangle.ids[1], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); var s1Right = AddIntersectionPoint(s1, triangle, triangle.ids[0], triangle.ids[2], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); var v1Right = AddTrianglePoint(triangle.pos[1], triangle.normal[1], triangle.uvs[1], triangle.tangents[1], triangle.colors[1], triangle.ids[1], triCache, cornerVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); var v2Right = AddTrianglePoint(triangle.pos[2], triangle.normal[2], triangle.uvs[2], triangle.tangents[2], triangle.colors[2], triangle.ids[2], triCache, cornerVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); // Triangle (v2, s1, v1) triangles[idxRight].Add(v2Right); triangles[idxRight].Add(s1Right); triangles[idxRight].Add(v1Right); // Triangle (s1, s0, v1) triangles[idxRight].Add(s1Right); triangles[idxRight].Add(s0Right); triangles[idxRight].Add(v1Right); // left side ... 1 triangle var s0Left = AddIntersectionPoint(s0, triangle, triangle.ids[0], triangle.ids[1], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var s1Left = AddIntersectionPoint(s1, triangle, triangle.ids[0], triangle.ids[2], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var v0Left = AddTrianglePoint(triangle.pos[0], triangle.normal[0], triangle.uvs[0], triangle.tangents[0], triangle.colors[0], triangle.ids[0], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); // Triangle (s1, v0, s0) triangles[idxLeft].Add(s1Left); triangles[idxLeft].Add(v0Left); triangles[idxLeft].Add(s0Left); // buffer intersection vertices for triangulation if (triangulateHoles) { if (idxLeft == 0) { contour.AddTriangle(cutTri, s0Left, s1Left, s0, s1); } else { contour.AddTriangle(cutTri, s0Right, s1Right, s0, s1); } } } } #if PROFILING MeasureIt.End("CutCycleSecondPass"); #endif if (triangulateHoles) { #if PROFILING MeasureIt.Begin("FindContours"); #endif contour.FindContours(); if (contour.contour.Count == 0 || contour.contour[0].Count < 3) { // triangulateHoles = false; if (allowOpenMesh) { triangulateHoles = false; } else { stopWatch.Stop(); return(stopWatch.ElapsedMilliseconds); } } #if PROFILING MeasureIt.End("FindContours"); #endif } List <int>[] trianglesCut = null; var centroid0 = Vector3.zero; var centroid1 = Vector3.zero; var min0 = Vector3.zero; var max0 = Vector3.zero; var min1 = Vector3.zero; var max1 = Vector3.zero; ExploderMesh.CalculateCentroid(vertices[0], ref centroid0, ref min0, ref max0); ExploderMesh.CalculateCentroid(vertices[1], ref centroid1, ref min1, ref max1); if (triangulateHoles) { #if PROFILING MeasureIt.Begin("Triangulate"); #endif trianglesCut = new List <int>[2] { new List <int>(contour.MidPointsCount), new List <int>(contour.MidPointsCount) }; Triangulate(contour.contour, plane, vertices, normals, uvs, tangents, vertexColors, trianglesCut, true, useMeshTangents, useVertexColors, useNormals); #if PROFILING MeasureIt.End("Triangulate"); #endif } if (vertices[0].Count > 3 && vertices[1].Count > 3) { #if PROFILING MeasureIt.Begin("CutEndCopyBack"); #endif mesh0 = new ExploderMesh(); mesh1 = new ExploderMesh(); var verticesArray0 = vertices[0].ToArray(); var verticesArray1 = vertices[1].ToArray(); mesh0.vertices = verticesArray0; mesh0.uv = uvs[0].ToArray(); mesh1.vertices = verticesArray1; mesh1.uv = uvs[1].ToArray(); if (useNormals) { mesh0.normals = normals[0].ToArray(); mesh1.normals = normals[1].ToArray(); } if (useMeshTangents) { mesh0.tangents = tangents[0].ToArray(); mesh1.tangents = tangents[1].ToArray(); } if (useVertexColors) { mesh0.colors32 = vertexColors[0].ToArray(); mesh1.colors32 = vertexColors[1].ToArray(); } if (trianglesCut != null && trianglesCut[0].Count > 3) { triangles[0].AddRange(trianglesCut[0]); triangles[1].AddRange(trianglesCut[1]); } mesh0.triangles = triangles[0].ToArray(); mesh1.triangles = triangles[1].ToArray(); mesh0.centroid = centroid0; mesh0.min = min0; mesh0.max = max0; mesh1.centroid = centroid1; mesh1.min = min1; mesh1.max = max1; #if PROFILING MeasureIt.End("CutEndCopyBack"); #endif meshes = new List <ExploderMesh> { mesh0, mesh1 }; stopWatch.Stop(); return(stopWatch.ElapsedMilliseconds); } stopWatch.Stop(); // UnityEngine.Debug.Log("Empty cut! " + vertices[0].Count + " " + vertices[1].Count); return(stopWatch.ElapsedMilliseconds); }
private float Cut( ExploderMesh mesh, ExploderTransform meshTransform, Plane plane, bool triangulateHoles, bool allowOpenMesh, ref List <ExploderMesh> meshes) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); int length1 = mesh.triangles.Length; int length2 = mesh.vertices.Length; int[] triangles1 = mesh.triangles; Vector4[] tangents = mesh.tangents; Color32[] colors32 = mesh.colors32; Vector3[] vertices = mesh.vertices; Vector3[] normals = mesh.normals; Vector2[] uv = mesh.uv; bool flag1 = tangents != null && tangents.Length > 0; bool flag2 = colors32 != null && colors32.Length > 0; bool useNormals = normals != null && normals.Length > 0; this.AllocateBuffers(length1, length2, flag1, flag2); for (int index1 = 0; index1 < length1; index1 += 3) { Vector3 n1 = vertices[triangles1[index1]]; Vector3 n2 = vertices[triangles1[index1 + 1]]; Vector3 n3 = vertices[triangles1[index1 + 2]]; bool sideFix1 = plane.GetSideFix(ref n1); bool sideFix2 = plane.GetSideFix(ref n2); bool sideFix3 = plane.GetSideFix(ref n3); vertices[triangles1[index1]] = n1; vertices[triangles1[index1 + 1]] = n2; vertices[triangles1[index1 + 2]] = n3; if (sideFix1 == sideFix2 && sideFix2 == sideFix3) { int index2 = !sideFix1 ? 1 : 0; if (triangles1[index1] < this.triCache.Length) { ; } if (this.triCache[triangles1[index1]] == 0) { this.triangles[index2].Add(this.triCounter[index2]); this.vertices[index2].Add(vertices[triangles1[index1]]); this.uvs[index2].Add(uv[triangles1[index1]]); if (useNormals) { this.normals[index2].Add(normals[triangles1[index1]]); } if (flag1) { this.tangents[index2].Add(tangents[triangles1[index1]]); } if (flag2) { this.vertexColors[index2].Add(colors32[triangles1[index1]]); } ref Vector3 local = ref this.centroid[index2]; local = Vector3.op_Addition(local, vertices[triangles1[index1]]); this.triCache[triangles1[index1]] = this.triCounter[index2] + 1; ++this.triCounter[index2]; } else { this.triangles[index2].Add(this.triCache[triangles1[index1]] - 1); } if (this.triCache[triangles1[index1 + 1]] == 0) { this.triangles[index2].Add(this.triCounter[index2]); this.vertices[index2].Add(vertices[triangles1[index1 + 1]]); this.uvs[index2].Add(uv[triangles1[index1 + 1]]); if (useNormals) { this.normals[index2].Add(normals[triangles1[index1 + 1]]); } if (flag1) { this.tangents[index2].Add(tangents[triangles1[index1 + 1]]); } if (flag2) { this.vertexColors[index2].Add(colors32[triangles1[index1 + 1]]); } ref Vector3 local = ref this.centroid[index2]; local = Vector3.op_Addition(local, vertices[triangles1[index1 + 1]]); this.triCache[triangles1[index1 + 1]] = this.triCounter[index2] + 1; ++this.triCounter[index2]; }