public void TestSmoothWithDuplicate() { var poly = GetPolygon(); var options = new ConstraintOptions() { ConformingDelaunay = true }; var quality = new QualityOptions() { MinimumAngle = 30.0 }; var mesh = poly.Triangulate(options, quality); Assert.AreEqual(1, mesh.Vertices .Where(v => v.Type == VertexType.UndeadVertex) .Count()); quality.MaximumArea = 0.2; mesh.Refine(quality, true); Assert.AreEqual(1, mesh.Vertices .Where(v => v.Type == VertexType.UndeadVertex) .Count()); var smoother = new SimpleSmoother(); // Smooth mesh. Assert.IsTrue(smoother.Smooth(mesh, 25) > 0); }
// generate mesh private TriangleNet.Mesh DxfMesh(Polygon poly) { // routine to generate a mesh from the contnet of poly // Set quality and constraint options. var options = new ConstraintOptions() { ConformingDelaunay = true }; var quality = new QualityOptions() { MinimumAngle = 15.0, MaximumArea = mds.minimumMeshArea }; // create the mesh mesh = (TriangleNet.Mesh)poly.Triangulate(options, quality); // make sure there are at least 1000 elements in the mesh while (mesh.Triangles.Count < 1000) { mds.minimumMeshArea = mds.minimumMeshArea / 2; quality.MaximumArea = mds.minimumMeshArea; mesh = (TriangleNet.Mesh)poly.Triangulate(options, quality); } // smooth the mesh var smoother = new SimpleSmoother(); smoother.Smooth(mesh); return(mesh); }
private void Smooth() { if (mesh == null || settings.ExceptionThrown) { return; } if (!mesh.IsPolygon) { return; } var smoother = new SimpleSmoother(); try { smoother.Smooth(this.mesh); statisticView.UpdateStatistic(mesh); HandleMeshUpdate(); } catch (Exception ex) { LockOnException(); DarkMessageBox.Show("Exception - Smooth", ex.Message, MessageBoxButtons.OK); } UpdateLog(); }
public static IMesh CreateMesh() { // Generate the input geometry. var poly = Example3.CreatePolygon(h); // Since we want to do CVT smoothing, ensure that the mesh // is conforming Delaunay. var options = new ConstraintOptions() { ConformingDelaunay = true }; // Set maximum area quality option (we don't need to set a minimum // angle, since smoothing will improve the triangle shapes). var quality = new QualityOptions() { // Given the boundary segment size, we set a maximum // area constraint assuming equilateral triangles. The // relaxation parameter is chosen to reduce the deviation // from this ideal value. MaximumArea = (Math.Sqrt(3) / 4 * h * h) * relax }; // Generate mesh using the polygons Triangulate extension method. var mesh = poly.Triangulate(options, quality); var smoother = new SimpleSmoother(); // Smooth mesh. smoother.Smooth(mesh, 25, .05); return(mesh); }
public static bool Run(bool print = false) { // Generate the input geometry. var poly = CreatePolygon(); // Define regions (first one defines the area constraint). poly.Regions.Add(new RegionPointer(1.5, 0.0, 1, 0.01)); poly.Regions.Add(new RegionPointer(2.5, 0.0, 2)); // Set quality and constraint options. var options = new ConstraintOptions() { ConformingDelaunay = true }; var quality = new QualityOptions() { MinimumAngle = 25.0, VariableArea = true }; //quality.UserTest = (t, area) => t.Label == 1 && area > 0.01; var mesh = poly.Triangulate(options, quality); var smoother = new SimpleSmoother(); smoother.Smooth(mesh, 5); if (print) { SvgImage.Save(mesh, "example-5.svg", 500); } return(mesh.Triangles.Count > 0); }
public static void Tessellate(float minAngle, float maxAngle, float meshAreaFactor, float largestTriangleAreaFactor, int smoothIterations, IList <Vector2> vertices, IList <Edge> edges, IList <int> indices) { if (vertices.Count < 3) { return; } largestTriangleAreaFactor = Mathf.Clamp01(largestTriangleAreaFactor); var polygon = new Polygon(vertices.Count); for (int i = 0; i < vertices.Count; ++i) { Vector2 position = vertices[i]; polygon.Add(new Vertex(position.x, position.y, 1)); } for (int i = 0; i < edges.Count; ++i) { Edge edge = edges[i]; polygon.Add(new Segment(polygon.Points[edge.index1], polygon.Points[edge.index2])); } var mesh = polygon.Triangulate(); var statistic = new Statistic(); statistic.Update((UnityEngine.Experimental.U2D.TriangleNet.Mesh)mesh, 1); var maxAreaToApply = (double)Mathf.Max((float)statistic.LargestArea * largestTriangleAreaFactor, (float)(statistic.MeshArea * meshAreaFactor)); var qualityOptions = new QualityOptions() { SteinerPoints = 0 }; if (maxAreaToApply > 0f) { qualityOptions.MaximumArea = maxAreaToApply; } qualityOptions.MinimumAngle = minAngle; qualityOptions.MaximumAngle = maxAngle; mesh.Refine(qualityOptions, false); mesh.Renumber(); if (smoothIterations > 0) { try { var smoother = new SimpleSmoother(); smoother.Smooth(mesh, smoothIterations); } catch (System.Exception) { Debug.Log(TextContent.smoothMeshError); } } vertices.Clear(); edges.Clear(); indices.Clear(); foreach (Vertex vertex in mesh.Vertices) { vertices.Add(new Vector2((float)vertex.X, (float)vertex.Y)); } foreach (ISegment segment in mesh.Segments) { edges.Add(new Edge(segment.P0, segment.P1)); } foreach (ITriangle triangle in mesh.Triangles) { int id0 = triangle.GetVertexID(0); int id1 = triangle.GetVertexID(1); int id2 = triangle.GetVertexID(2); if (id0 < 0 || id1 < 0 || id2 < 0 || id0 >= vertices.Count || id1 >= vertices.Count || id2 >= vertices.Count) { continue; } indices.Add(id0); indices.Add(id2); indices.Add(id1); } }
public static Mesh RefineRegions() { // Generate the input geometry. var poly = new Polygon(); var center = new Point(0, 0); // Three concentric circles. poly.Add(Example2.Circle(1.0, center, 0.1, 1), center); poly.Add(Example2.Circle(2.0, center, 0.1, 2)); poly.Add(Example2.Circle(3.0, center, 0.3, 3)); // Define regions. poly.Regions.Add(new RegionPointer(1.5, 0.0, 1)); poly.Regions.Add(new RegionPointer(2.5, 0.0, 2)); // Set quality and constraint options. var options = new ConstraintOptions() { ConformingDelaunay = true }; var quality = new QualityOptions() { MinimumAngle = 25.0 }; // Generate mesh. var mesh = (Mesh)poly.Triangulate(options, quality); var smoother = new SimpleSmoother(); // Smooth mesh and re-apply quality options. smoother.Smooth(mesh); mesh.Refine(quality); // Calculate mesh quality var statistic = new QualityMeasure(); statistic.Update(mesh); // Use the minimum triangle area for region refinement double area = 1.75 * statistic.AreaMinimum; foreach (var t in mesh.Triangles) { // Set area constraint for all triangles in region 1 if (t.Label == 1) { t.Area = area; } } // Use per triangle area constraint for next refinement quality.VariableArea = true; // Refine mesh to meet area constraint. mesh.Refine(quality); // Smooth once again. smoother.Smooth(mesh); return(mesh); }
// Use this for initialization void Start( ) { var p = new Polygon(); p.Add(CosSegements(-Size, -Size, Size, -Size, partsNum, 1)); p.Add(CosSegements(Size, -Size, Size, Size, partsNum, 2)); p.Add(CosSegements(Size, Size, -Size, Size, partsNum, 3)); p.Add(CosSegements(-Size, Size, -Size, -Size, partsNum, 4)); //var polygon = FileProcessor.Read("Assets/Plugins/Data/box_with_a_hole.poly"); var options = new ConstraintOptions() { ConformingDelaunay = true }; var quality = new QualityOptions() { MinimumAngle = 25F, MaximumArea = 0.1F }; var triMesh = (TriangleNet.Mesh)p.Triangulate(options, quality); var smoothing = new SimpleSmoother(); smoothing.Smooth(triMesh); triMesh.Refine(quality); triMesh.Renumber( ); int boneIndex0 = 0; var bindposes = new List <Matrix4x4>(); var bones = new List <Transform>(); var fBoneWeights = new List <BoneWeight>(); var vertexLookup = new Dictionary <Point, Rigidbody>(); Root = new GameObject( ); Root.transform.parent = transform; Root.transform.localRotation = Quaternion.identity; var voronoi = new StandardVoronoi(triMesh); var triAreas = triMesh.Triangles.Sum(t => t.Area()); Debug.Log("Tri Areas : " + triAreas); Debug.Log("Vor Count : " + voronoi.Faces.Count); float SumArea = 0F; foreach (var face in voronoi.Faces) { var origins = face.GetAllVertices(); //var origins = face.EnumerateEdges().Select(e => (Point) e.Origin); if (origins.Count() > 0) { SumArea += origins.Area( ); var obj = GameObject.CreatePrimitive(PrimitiveType.Sphere);//new GameObject(); obj.transform.localScale = Vector3.one * 0.005F; var renderer = obj.GetComponent <MeshRenderer> ( ); if (renderer) { renderer.enabled = false; } //obj.GetComponent<SphereCollider> ( ).enabled = false; var center = face.generator;// origins.MassCenter(); var worldPosition = transform.TransformPoint(new Vector3(( float )center.x, ( float )center.y, 0)); obj.transform.position = worldPosition; obj.transform.parent = Root.transform; bones.Add(obj.transform); bindposes.Add(obj.transform.worldToLocalMatrix * transform.localToWorldMatrix); var weight = new BoneWeight(); weight.boneIndex0 = boneIndex0; weight.weight0 = 1.0F; fBoneWeights.Add(weight); var rigidbody = obj.AddComponent <Rigidbody>(); rigidbody.useGravity = false; rigidbody.interpolation = RigidbodyInterpolation.Interpolate; rigidbody.mass = origins.Area( ) * KGSM; rigidbody.drag = 4; rigidbody.angularDrag = 2; rigidbody.constraints ^= RigidbodyConstraints.FreezeRotation; //if ( center.y > 1.9 ) rigidbody.isKinematic = true; if (center.y == Size) { rigid_Up.Add(rigidbody); } else if (center.y == -Size) { rigid_Down.Add(rigidbody); } else if (center.x == Size) { rigid_Right.Add(rigidbody); } else if (center.x == -Size) { rigid_Left.Add(rigidbody); } else { others.Add(rigidbody); } All.Add(rigidbody); vertexLookup.Add(center, rigidbody); boneIndex0++; } //SkinnedMeshRenderer.BakeMesh } foreach (var edge in triMesh.Edges) { var v0 = triMesh.Vertices.ElementAt(edge.P0); var v1 = triMesh.Vertices.ElementAt(edge.P1); var pt_0 = new Vector2((float)v0.x, (float)v0.y); var pt_1 = new Vector2((float)v1.x, (float)v1.y); var distance = Vector2.Distance(pt_0, pt_1); var rigid_0 = vertexLookup[v0]; var rigid_1 = vertexLookup[v1]; var spring = rigid_0.gameObject.AddComponent <SpringJoint>(); spring.connectedBody = rigid_1; spring.minDistance = distance * .96F; spring.maxDistance = distance * 1.00F; spring.spring = 8F; spring.damper = 0F; spring.autoConfigureConnectedAnchor = false; spring.enableCollision = false; spring.connectedAnchor = spring.anchor = Vector3.zero; spring.axis = Vector3.back; spring.tolerance = 0.01F; spring.enablePreprocessing = false; } var vertices = triMesh.Vertices.Select(v => new Vector3((float)v.x, (float)v.y, 0)).ToArray(); var triangles = triMesh.Triangles.SelectMany(t => t.vertices.Select(v => v.id)).ToArray();//.Reverse() var normals = triMesh.Vertices.Select(v => transform.forward); var bounds = triMesh.bounds; var l = bounds.Left; var b = bounds.Bottom; var w = bounds.Width; var h = bounds.Height; var uvs = triMesh.Vertices.Select(v => new Vector2(-(float)((v.x - l) / w), (float)((v.y - b) / h))).ToArray(); Debug.Log(string.Format("Vertices : {0}, Edge : {1}, Segments : {2}, Triangles : {3}, Holes : {4}", triMesh.Vertices.Count, triMesh.Edges.Count( ), triMesh.Segments.Count, triMesh.Triangles.Count, triMesh.Holes.Count)); var skinnedRenderer = GetComponent <SkinnedMeshRenderer>(); //var meshFilter = GetComponent<MeshFilter>(); //if ( !meshFilter ) //{ // meshFilter = gameObject.AddComponent<MeshFilter> ( ); //} var uniMesh = new Mesh(); uniMesh.vertices = vertices; uniMesh.triangles = triangles; uniMesh.uv = uvs; uniMesh.normals = normals.ToArray( ); uniMesh.boneWeights = fBoneWeights.ToArray( ); uniMesh.bindposes = bindposes.ToArray( ); skinnedRenderer.sharedMesh = uniMesh; skinnedRenderer.bones = bones.ToArray( ); skinnedRenderer.rootBone = Root.transform; //GetComponent<MeshCollider> ( ).sharedMesh = uniMesh; }
public PolyGraph( int width, int height, int sparcity, int padding, int smoothingSteps, ICornerMode cornerMode) { this.width = width; this.height = height; edgeIdCounter = 0; cornerIdCounter = 0; faces = new Dictionary <int, PolyFace>(); corners = new Dictionary <int, PolyCorner>(); edges = new Dictionary <int, PolyEdge>(); Mesh faceMesh; // Randomly generate a delaunay trianglulation to use as faces for the PolyGraph. { Polygon polygon = new Polygon(); Vertex[] bounds = new Vertex[4] { new Vertex(0, 0), new Vertex(0, height), new Vertex(width, height), new Vertex(width, 0) }; PoissonDiscSampler sampler = new PoissonDiscSampler( width - 2 * padding, height - 2 * padding, sparcity); SimpleSmoother smoother = new SimpleSmoother(); for (int i = 0; i < 4; i++) { polygon.Add(new Segment( bounds[i], bounds[(i + 1) % 4], 1 ), 0); } foreach (UnityEngine.Vector2 sample in sampler.Samples()) { polygon.Add(new Vertex(sample.x + padding, sample.y + padding)); } faceMesh = (Mesh)polygon.Triangulate( new ConstraintOptions() { ConformingDelaunay = true }); smoother.Smooth(faceMesh, smoothingSteps); } // Compose and add faces to face dictionary. foreach (Vertex vertex in faceMesh.Vertices) { int xInt = Convert.ToInt32(vertex.x); int yInt = Convert.ToInt32(vertex.y); bool x0Border = xInt == 0; bool x1Border = xInt == width; bool y0Border = yInt == 0; bool y1Border = yInt == height; PolyFace face; if (x0Border | x1Border | y0Border | y1Border) { Vertex borderVertex = new Vertex(); borderVertex.x = vertex.x; borderVertex.y = vertex.y; if (x0Border) { vertex.x += padding / 2; } if (x1Border) { vertex.x -= padding / 2; } if (y0Border) { vertex.y += padding / 2; } if (y1Border) { vertex.y -= padding / 2; } PolyCorner borderCorner = new PolyCorner(cornerIdCounter++, borderVertex); face = new PolyFace(vertex); face.borderCorner = borderCorner; if ((x0Border?1:0) + (x1Border?1:0) + (y0Border?1:0) + (y1Border?1:0) == 2) { face.isFaceBorderCorner = true; } borderCorner.surroundingFaces.Add(face); face.surroundingCorners.Add(borderCorner); corners.Add(borderCorner.id, borderCorner); } else { face = new PolyFace(vertex); } faces.Add(face.id, face); } foreach (Triangle triangle in faceMesh.triangles) { // Compose corner dicitonary from remaining faces. PolyCorner corner = new PolyCorner(cornerIdCounter++, triangle, cornerMode); foreach (Vertex faceVertex in triangle.vertices) { PolyFace face = faces[faceVertex.id]; face.surroundingCorners.Add(corner); corner.surroundingFaces.Add(face); } corners.Add(corner.id, corner); } // Compose and add edges to edge dictionary. foreach (TriangleNet.Geometry.Edge meshEdge in faceMesh.Edges) { // Add pointers between corners faces and edges. PolyFace face0 = faces[meshEdge.P0]; PolyFace face1 = faces[meshEdge.P1]; face0.neighbouringFaces.Add(face1); face1.neighbouringFaces.Add(face0); PolyEdge edge = new PolyEdge(edgeIdCounter++, face0, face1); edges.Add(edge.id, edge); face0.surroundingEdges.Add(edge); face1.surroundingEdges.Add(edge); foreach (PolyCorner corner in face0.surroundingCorners) { if (face1.surroundingCorners.Contains(corner)) { edge.surroundingCorners.Add(corner); corner.surroundingEdges.Add(edge); } } if (edge.surroundingCorners.Count == 1) { PolyCorner faceCorner0 = face0.borderCorner; PolyCorner faceCorner1 = face1.borderCorner; Vertex f0 = faceCorner0.vertex; Vertex f1 = faceCorner1.vertex; Vertex v0 = edge.surroundingCorners[0].vertex; Vertex f = f1 - f0; Vertex v = v0 - f0; Vertex projvf = (((f * v) / Math.Pow(f.Magnitude(), 2)) * f); PolyCorner corner = new PolyCorner(cornerIdCounter++, projvf + f0); edge.surroundingCorners.Add(corner); corner.surroundingEdges.Add(edge); corner.surroundingFaces.Add(face1); corner.surroundingFaces.Add(face0); face0.surroundingCorners.Add(corner); face1.surroundingCorners.Add(corner); corners.Add(corner.id, corner); PolyEdge faceEdge0 = new PolyEdge(edgeIdCounter++, face0); PolyEdge faceEdge1 = new PolyEdge(edgeIdCounter++, face1); edges.Add(faceEdge0.id, faceEdge0); edges.Add(faceEdge1.id, faceEdge1); faceEdge0.surroundingCorners.Add(faceCorner0); faceEdge0.surroundingCorners.Add(corner); faceCorner0.surroundingEdges.Add(faceEdge0); faceEdge1.surroundingCorners.Add(faceCorner1); faceEdge1.surroundingCorners.Add(corner); faceCorner1.surroundingEdges.Add(faceEdge1); } } foreach (KeyValuePair <int, PolyEdge> kvp in edges) { PolyEdge edge = kvp.Value; edge.vertex = (edge.surroundingCorners[0].vertex + edge.surroundingCorners[1].vertex) / 2; } ConstraintOptions options = new ConstraintOptions() { ConformingDelaunay = false }; foreach (KeyValuePair <int, PolyFace> kvp in faces) { PolyFace face = kvp.Value; face.GenerateMeshData(options); } }
// Use this for initialization void Start() { //var geometry = FileReader.ReadPolyFile("Assets/Plugins/Data/superior.poly"); var p = new Polygon(); //p.Add ( ClacSegments ( -2, -2, 2, -2, 1 ) ); //p.Add ( ClacSegments ( 2, -2, 2, 2, 2 ) ); //p.Add ( ClacSegments ( 2, 2, -2, 2, 3 ) ); //p.Add ( ClacSegments ( -2, 2, -2, -2, 4 ) ); p.Add(ClacSegments(-3, -3, 3, -3, 1)); p.Add(ClacSegments(3, -3, 3, 3, 2)); p.Add(ClacSegments(3, 3, -3, 3, 3)); p.Add(ClacSegments(-3, 3, -3, -3, 4)); // Add the outer box contour with boundary marker 1. // p.Add ( new Contour ( new Vertex [ 4 ] //{ // new Vertex(-3,-3, 1), // new Vertex(3, -3, 1), // new Vertex(3, 3, 1), // new Vertex(-3, 3, 1) //}, 1 ) ); // p.Add ( new Contour ( new Vertex [ 4 ] //{ // new Vertex(-2.9,-2.9, 1), // new Vertex(2.9, -2.9, 1), // new Vertex(2.9, 2.9, 1), // new Vertex(-2.9, 2.9, 1) //}, 1 ) ); // Add the inner box contour with boundary marker 2. p.Add(new Contour(new Vertex [4] { new Vertex(1.0, 1.0, 2), new Vertex(2.0, 1.0, 2), new Vertex(2.0, 2.0, 2), new Vertex(1.0, 2.0, 2) }, 5) , new Point(1.5, 1.5)); // Make it a hole. //var polygon = FileProcessor.Read("Assets/Plugins/Data/box_with_a_hole.poly"); var options = new ConstraintOptions() { ConformingDelaunay = true }; var quality = new QualityOptions() { MinimumAngle = 25F, MaximumArea = 0.04F }; var triMesh = (TriangleNet.Mesh)p.Triangulate(options, quality); var smoothing = new SimpleSmoother(); smoothing.Smooth(triMesh); triMesh.Refine(quality, true); triMesh.Renumber( ); //var bounds = new Rectangle(-1.0, -1.0, 2.0, 2.0); //var triMesh = GenericMesher.StructuredMesh(bounds, 20, 20); var vertices = triMesh.Vertices.Select(v => new Vector3((float)v.x, (float)v.y, 0)).ToArray(); var triangles = triMesh.Triangles.SelectMany(t => t.vertices.Select(v => v.id)).ToArray();//.Reverse() var normals = triMesh.Vertices.Select(v => transform.forward).ToArray(); var bounds = triMesh.bounds; var l = bounds.Left; var b = bounds.Bottom; var w = bounds.Width; var h = bounds.Height; var uvs = triMesh.Vertices.Select(v => new Vector2(-(float)((v.x - l) / w), (float)((v.y - b) / h))).ToArray(); var skinnedRenderer = GetComponent <SkinnedMeshRenderer>(); var uniMesh = new Mesh( ); uniMesh.vertices = vertices; uniMesh.triangles = triangles; uniMesh.uv = uvs; uniMesh.normals = normals; skinnedRenderer.sharedMesh = uniMesh; var cloth = GetComponent <Cloth>(); if (!cloth) { cloth = gameObject.AddComponent <Cloth> ( ); } var coes = new List <ClothSkinningCoefficient>(); foreach (var v in vertices) { coes.Add(new ClothSkinningCoefficient( ) { maxDistance = 10, collisionSphereDistance = 0.1F }); } cloth.coefficients = coes.ToArray( ); ClothSphereColliderPair pair = new ClothSphereColliderPair(sphereFirst, null); cloth.sphereColliders = new ClothSphereColliderPair [] { pair }; //cloth.externalAcceleration = new Vector3 ( 0, -10, 0 ); cloth.stretchingStiffness = 0.9F; cloth.bendingStiffness = 0.1F; cloth.collisionMassScale = 0.1F; cloth.friction = 1F; cloth.SetEnabledFading(true); cloth.sleepThreshold = 0.1F; cloth.damping = 0.2F; }
// Use this for initialization void Start() { var p = new Polygon(); //Add the outer box contour with boundary marker 1. p.Add(new Contour(new Vertex [4] { new Vertex(-3, -3, 1), new Vertex(3, -3, 1), new Vertex(3, 3, 1), new Vertex(-3, 3, 1) }, 1)); var options = new ConstraintOptions() { ConformingDelaunay = true }; var quality = new QualityOptions() { MinimumAngle = 25F, MaximumArea = 0.04F }; var triMesh = (TriangleNet.Mesh)p.Triangulate(options, quality); var smoothing = new SimpleSmoother(); smoothing.Smooth(triMesh); triMesh.Refine(quality, true); triMesh.Renumber( ); var vertices = triMesh.Vertices.Select(v => new Vector3((float)v.x, (float)v.y, 0)).ToArray(); var triangles = triMesh.Triangles.SelectMany(t => t.vertices.Select(v => v.id)).ToArray();//.Reverse() var normals = triMesh.Vertices.Select(v => transform.forward).ToArray(); var bounds = triMesh.bounds; var l = bounds.Left; var b = bounds.Bottom; var w = bounds.Width; var h = bounds.Height; var uvs = triMesh.Vertices.Select(v => new Vector2(-(float)((v.x - l) / w), (float)((v.y - b) / h))).ToArray(); //SkinnedMeshRenderer var skinnedRenderer = GetComponent <SkinnedMeshRenderer>(); var uniMesh = new Mesh( ); uniMesh.vertices = vertices; uniMesh.triangles = triangles; uniMesh.uv = uvs; uniMesh.normals = normals; //Bones int boneIndex0 = 0; var bindposes = new List <Matrix4x4>(); var bones = new List <Transform>(); var fBoneWeights = new List <BoneWeight>(); Root = new GameObject( ); Root.transform.parent = transform; Root.transform.localRotation = Quaternion.identity; var handler = new GameObject(); handler.name = "Handler"; handler.transform.parent = Root.transform; handler.transform.localRotation = Quaternion.identity; foreach (var vertex in triMesh.Vertices) //.Where(v=>v.y > 2.9F) ) { var obj = GameObject.CreatePrimitive(PrimitiveType.Sphere); //new GameObject(); obj.transform.localScale = Vector3.one * 0.1F; var renderer = obj.GetComponent <MeshRenderer> ( ); if (renderer) { renderer.enabled = false; } var worldPosition = transform.TransformPoint(new Vector3(( float )vertex.x, ( float )vertex.y, 0)); obj.transform.position = worldPosition; if (vertex.y > 2.9F) { obj.name = "HERE"; obj.transform.parent = handler.transform; } else { obj.transform.parent = Root.transform; } bones.Add(obj.transform); bindposes.Add(obj.transform.worldToLocalMatrix * transform.localToWorldMatrix); var weight = new BoneWeight(); weight.boneIndex0 = boneIndex0; weight.weight0 = 1.0F; fBoneWeights.Add(weight); boneIndex0++; } uniMesh.boneWeights = fBoneWeights.ToArray( ); uniMesh.bindposes = bindposes.ToArray( ); skinnedRenderer.sharedMesh = uniMesh; skinnedRenderer.bones = bones.ToArray( ); skinnedRenderer.rootBone = Root.transform; //Cloth var cloth = GetComponent <Cloth>(); if (!cloth) { cloth = gameObject.AddComponent <Cloth> ( ); } var coes = new List <ClothSkinningCoefficient>(); foreach (var v in vertices) { if (v.y < 2.9F) { coes.Add(new ClothSkinningCoefficient( ) { maxDistance = 10, collisionSphereDistance = 0.1F }); } else { coes.Add(new ClothSkinningCoefficient( ) { maxDistance = 0, collisionSphereDistance = 0.1F }); } } cloth.coefficients = coes.ToArray( ); ClothSphereColliderPair pair = new ClothSphereColliderPair(sphereFirst, null); cloth.sphereColliders = new ClothSphereColliderPair [] { pair }; //cloth.externalAcceleration = new Vector3 ( 0, -10, 0 ); cloth.stretchingStiffness = 0.9F; cloth.bendingStiffness = 0.1F; cloth.collisionMassScale = 0.1F; cloth.friction = 1F; cloth.SetEnabledFading(true); cloth.sleepThreshold = 0.1F; cloth.damping = 0.2F; }