///内侧轴线(未完成) ---- 2017-09-07 /// public static void MedialAxis(this TriangleNet.Mesh triMesh) { var bounds = triMesh.bounds; var voronoi = new StandardVoronoi(triMesh, bounds); //List<TriangleNet.Topology.DCEL.HalfEdge> edges = new List<TriangleNet.Topology.DCEL.HalfEdge>(); Dictionary <dVertex, int> vertLookup = new Dictionary <dVertex, int>(); foreach (var vert in voronoi.Vertices.Where(v => !v.IsOn(bounds))) { if (!vert.leaving.origin.IsOn(bounds)) { if (!vertLookup.Keys.Contains(vert)) { vertLookup.Add(vert, 0); } vertLookup [vert]++; } } foreach (var vert in vertLookup) { Debug.Log(vert.Key + ", " + vert.Value); } //Dictionary<halfEdge, int> edgeLookup = new Dictionary<halfEdge, int>(); int count = 0; foreach (var edge in voronoi.HalfEdges.Where(e => !e.origin.IsOn(bounds))) { Debug.Log(" : " + count++ + edge + " <=> " + edge.twin); } }
public static List <List <Vertex> > VonoroiFaces(this TriangleNet.Mesh triMesh) { var voronoi = new StandardVoronoi(triMesh); List <List <Vertex> > result = new List <List <Vertex> >(); foreach (var face in voronoi.Faces) { result.Add(face.GetAllVertices( ).Select(p => new Vertex(p.x, p.y, p.id)).ToList( )); } var rect = triMesh.Bounds; result.Add(new List <Vertex> (rect.Path( ))); return(result); }
private VoronoiBase GenerateVoronoi(ref Polygon polygon, int relaxationCount = 0) { if (polygon.Count < 3) { return(null); } StandardVoronoi voronoi = null; for (int i = 0; i < relaxationCount + 1; i++) { TriangleNet.Mesh mesh = (TriangleNet.Mesh)polygon.Triangulate(); data.bounds = mesh.Bounds; voronoi = new StandardVoronoi(mesh, rectangle); if (relaxationCount != 0) { polygon = voronoi.Lloyd_Relaxation(rectangle); } } return(voronoi); }
Dictionary <Point, Rigidbody> UpdateRigidbodys(SkinnedMeshRenderer skineedRenderer, TriangleNet.Mesh triMesh, bool isForward) { var vertexLookup = new Dictionary <Point, Rigidbody> ( ); var skinnedRoot = skineedRenderer.transform; ///------------------------------------------------------------------------- /// int boneIndex0 = 0; var bindposes = new List <Matrix4x4>(); var bones = new List <Transform>(); var fBoneWeights = new List <BoneWeight>(); var voronoi = new StandardVoronoi(triMesh); var triAreas = triMesh.Triangles.Sum(t => t.Area()); Debug.Log("Tri Areas : " + triAreas); foreach (var face in voronoi.Faces) { var origins = face.GetAllVertices(); if (origins.Count( ) > 0) { var center = face.generator; var obj = GameObject.CreatePrimitive(UnityEngine.PrimitiveType.Sphere);//new GameObject(); obj.name = "V_" + center.Label + "_" + center.ID; obj.transform.localScale = Vector3.one * 0.005F; var renderer = obj.GetComponent <MeshRenderer> ( ); if (renderer) { renderer.enabled = false; } var worldPosition = skinnedRoot.transform.TransformPoint(new Vector3(( float )center.x, ( float )center.y, 0)); obj.transform.position = worldPosition; obj.transform.parent = skinnedRoot;// Root.transform; bones.Add(obj.transform); bindposes.Add(obj.transform.worldToLocalMatrix * skinnedRoot.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; // if ( center.Label == 0 ) rigidbody.constraints ^= RigidbodyConstraints.FreezeRotation; vertexLookup.Add(center, rigidbody); boneIndex0++; } } foreach (var edge in triMesh.Edges) { var v0 = triMesh.Vertices.ElementAt(edge.P0); var v1 = triMesh.Vertices.ElementAt(edge.P1); bool isBounds = v0.Label != 0 && v1.Label != 0; 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 = isBounds ? 4F : 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 = isForward ? triMesh.Triangles.SelectMany(t => t.vertices.Reverse().Select(v => v.id)).ToArray() : triMesh.Triangles.SelectMany(t => t.vertices.Select(v => v.id)).ToArray();//.Reverse() var normals = triMesh.Vertices.Select(v => isForward ? Vector3.back : Vector3.forward); var bounds = triMesh.bounds; var l = bounds.Left; var b = bounds.Bottom; var w = bounds.Width; var h = bounds.Height; float dir = isForward ? 1F : -1F; var uvs = triMesh.Vertices.Select(v => new Vector2(dir * (float)((v.x)), (float)((v.y))) * 0.2F).ToArray(); 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( ); skineedRenderer.sharedMesh = uniMesh; skineedRenderer.bones = bones.ToArray( ); skineedRenderer.rootBone = skinnedRoot; return(vertexLookup); }
void GenMap() { /* * <settings> */ int starsAm = 10000; // What percentage of space is taken up by stars. int starDensity = 20; // Minimal corridor length relative to maximal star size. float minCorridorLengthCoeff = 3.0f; // What percentage of space is taken up by corridors. int corridorDensity = 60; float maxz = 3.0f; /* * </settings> */ float max_star_size = Mathf.Max(pos_star_sizes); Debug.Log("Max star size: " + max_star_size); float min_corridor_length = max_star_size * minCorridorLengthCoeff; float min_corridor_length_squared = Mathf.Pow(min_corridor_length, 2); int starsx = Mathf.RoundToInt(Mathf.Sqrt(starsAm)); int starsy = starsx; float width = (starsx * max_star_size) + ((starsx - 1) * min_corridor_length); float height = (starsy * max_star_size) + ((starsy - 1) * min_corridor_length); background.transform.localScale = new Vector3(width * 0.11f, 1.0f, height * 0.11f); background.GetComponent <MeshRenderer>().material.SetTextureScale("_MainTex", new Vector2(width / 70.0f, height / 70.0f)); Debug.Log("Dimensions: " + width + ", " + height); float minx = width * -0.5f; float miny = height * -0.5f; float maxx = width * 0.5f; float maxy = height * 0.5f; float max_offset_x = (width / starsx) - ((min_corridor_length - max_star_size) * 0.5f); float max_offset_y = (height / starsy) - ((min_corridor_length - max_star_size) * 0.5f); Debug.Log("Offsets: " + max_offset_x + ", " + max_offset_y); Rectangle bounds = new Rectangle(minx, miny, width, height); TriangleNet.Mesh mesh = (TriangleNet.Mesh)GenericMesher.StructuredMesh(bounds, starsx - 1, starsy - 1); List <TriangleNet.Geometry.Vertex> stars = new List <TriangleNet.Geometry.Vertex>(); List <TriangleNet.Geometry.Vertex> shuffled_verts = new List <TriangleNet.Geometry.Vertex>(mesh.Vertices); shuffled_verts.Shuffle(); int stars_amount = 0; foreach (TriangleNet.Geometry.Vertex v in shuffled_verts) { if (stars_amount > 3 && Random.Range(0, 101) > starDensity) { continue; } stars.Add(v); stars_amount++; } GenericMesher gm = new GenericMesher(new SweepLine()); mesh = (TriangleNet.Mesh)gm.Triangulate(stars); StandardVoronoi sv = new StandardVoronoi(mesh); Polygon final = new Polygon(sv.Vertices.Count); Dictionary <int, TriangleNet.Geometry.Vertex> good_stars = new Dictionary <int, TriangleNet.Geometry.Vertex>(); Dictionary <int, int> bad2goodstar = new Dictionary <int, int>(); List <int> outBoundStars = new List <int>(); foreach (TriangleNet.Topology.DCEL.Vertex v in sv.Vertices) { if (v.x < minx || v.x > maxx || v.y < miny || v.y > maxy) { outBoundStars.Add(v.id); continue; } bool invalid = false; foreach (TriangleNet.Geometry.Vertex other in good_stars.Values) { Vector2 v1 = new Vector2((float)v.x, (float)v.y); Vector2 v2 = new Vector2((float)other.x, (float)other.y); if ((v2 - v1).sqrMagnitude < min_corridor_length_squared) { invalid = true; bad2goodstar[v.id] = other.id; } } if (invalid) { continue; } TriangleNet.Geometry.Vertex new_v = new TriangleNet.Geometry.Vertex(v.x, v.y); new_v.id = v.id; good_stars[v.id] = new_v; final.Add(new_v); } List <Segment> good_segments = new List <Segment>(); foreach (Edge e in sv.Edges) { if (outBoundStars.Contains(e.P0) || outBoundStars.Contains(e.P1)) { continue; } int P0_id; int P1_id; if (bad2goodstar.ContainsKey(e.P0)) { P0_id = bad2goodstar[e.P0]; } else { P0_id = e.P0; } if (bad2goodstar.ContainsKey(e.P1)) { P1_id = bad2goodstar[e.P1]; } else { P1_id = e.P1; } if (P0_id == P1_id) { continue; } good_segments.Add(new Segment(good_stars[P0_id], good_stars[P1_id])); } Dictionary <int, List <int> > connected_stars = new Dictionary <int, List <int> >(); foreach (Segment s in good_segments) { if (!connected_stars.ContainsKey(s.P0)) { connected_stars[s.P0] = new List <int>(); } connected_stars[s.P0].Add(s.P1); if (!connected_stars.ContainsKey(s.P1)) { connected_stars[s.P1] = new List <int>(); } connected_stars[s.P1].Add(s.P0); } Debug.Log("Currently edges: " + good_segments.Count); List <Segment> temp_segments = new List <Segment>(good_segments); temp_segments.Shuffle(); foreach (Segment s in temp_segments) { if (Random.Range(0, 101) > corridorDensity && RemovalConnectionsCheck(connected_stars, s.P0, s.P1)) { connected_stars[s.P0].Remove(s.P1); connected_stars[s.P1].Remove(s.P0); good_segments.Remove(s); } } foreach (Segment s in good_segments) { final.Add(s); } Debug.Log("Stars after everything: " + final.Points.Count); Debug.Log("Corridors after everything: " + good_segments.Count); CreateMap(final, maxz, 0.0f); }
// 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; }
private void ResetBuffers(TriangleNet.Mesh triMesh) { var bounds = triMesh.Bounds; var x = (float)(bounds.Left + bounds.Right) * 0.5F; var y = (float)(bounds.Top + bounds.Bottom) * 0.5F; Center = new Vector3(x, y, 0); //Mass : Vertex massesCount = triMesh.Vertices.Count; List <Mass> masses = new List <Mass>();//new Mass [massesCount]; var voronoi = new StandardVoronoi(triMesh); foreach (var vertex in triMesh.Vertices) //for(int i =0; i < vertCount; i++ ) { var mass = new Mass(); mass.id = vertex.id; //0, 1, 2, ... index mass.label = vertex.label; //1, 1, ..., 2, 2, ..., 3, 3, ..., 4, 4, ..., 0, 0, 0 ... mass.nor = Vector3.back; //new Vector3 ( ( float ) vertex.x, ( float ) vertex.y, 0 ); //var z = vertex.label == 0 ? -0.1F : 0.0F; mass.pos = new Vector3(( float )vertex.X, ( float )vertex.Y, 0); mass.vel = Vector3.zero; mass.force = Vector3.zero; var face = voronoi.Faces [vertex.id]; var origins = face.GetAllVertices(); mass.mass = (origins.Count > 0 ? origins.Area( ) : 0) * KGSM; //masses [ vertex.id ] = mass; masses.Add(mass); } //如果 顶点数量 不能被十整除 则 增加 不足 部分; if (massesCount % 10 > 0) { massesCount += 10 - (massesCount % 10); for (int k = triMesh.vertices.Count; k < massesCount; k++) { masses.Add(new Mass( ) { id = -1 }); } } massBuffer = new ComputeBuffer(massesCount, sizeof(float) * 13 + sizeof(int) * 2); massBuffer.SetData(masses.ToArray( )); //Spring : Edge + Shear spring //Spring[] springs = new Spring[edgeCount]; List <Spring> springs = new List <Spring>(); //int i = 0; foreach (var edge in triMesh.Edges) { var spring = new Spring(); spring.m0 = edge.P0; spring.m1 = edge.P1; var v0 = triMesh.Vertices.ElementAt(edge.P0); var v1 = triMesh.Vertices.ElementAt(edge.P1); //bool isBounds = v0.Label != 0 && v1.Label != 0; var pt_0 = new Vector2((float)v0.x, (float)v0.y); var pt_1 = new Vector2((float)v1.x, (float)v1.y); spring.length = Vector2.Distance(pt_0, pt_1); //bool isEdge = v0.label != 0 && v1.label != 0; //spring.stiffness =10.0F; //springs [ i ] = spring; springs.Add(spring); //i++; } foreach (var triangle in triMesh.Triangles) { for (int j = 0; j < 3; j++) { var currID = triangle.GetVertexID(j); var nextID = triangle.GetVertexID((j + 1) % 3); var preID = triangle.GetVertexID((j + 2) % 3); var neighbor = triangle.GetNeighbor(j); if (neighbor != null) { var ids = new int[3] { neighbor.GetVertexID(0), neighbor.GetVertexID(1), neighbor.GetVertexID(2) }; var oppID = ids.FirstOrDefault(id => id != nextID && id != preID); bool isContants = springs.Any(s => (s.m0 == currID && s.m1 == oppID) || (s.m1 == currID && s.m0 == oppID)); if (!isContants) { var spring = new Spring(); spring.m0 = currID; spring.m1 = oppID; var v0 = triMesh.Vertices.ElementAt(currID); var v1 = triMesh.Vertices.ElementAt(oppID); //bool isBounds = v0.Label != 0 && v1.Label != 0; var pt_0 = new Vector2((float)v0.x, (float)v0.y); var pt_1 = new Vector2((float)v1.x, (float)v1.y); spring.length = Vector2.Distance(pt_0, pt_1); //bool isEdge = v0.label != 0 && v1.label != 0; //spring.stiffness = 10.0F; springs.Add(spring); } } } } springsCount = springs.Count; if (springsCount % 10 > 0) { springsCount += 10 - (springsCount % 10); for (int l = springs.Count; l < springsCount; l++) { springs.Add(new Spring( ) { m0 = 0, m1 = 0, length = 0 }); //, stiffness = 0 } ); } } springBuffer = new ComputeBuffer(springsCount, sizeof(float) * 1 + sizeof(int) * 2); springBuffer.SetData(springs.ToArray( )); clothingShader.SetBuffer(initForcesKernel, ClothingShaderProperties.MassBufferName, massBuffer); clothingShader.SetBuffer(updateForcesKernel, ClothingShaderProperties.MassBufferName, massBuffer); clothingShader.SetBuffer(updateForcesKernel, ClothingShaderProperties.SpringBufferName, springBuffer); clothingShader.SetBuffer(updatePosKernel, ClothingShaderProperties.MassBufferName, massBuffer); clothingShader.SetFloat(ClothingShaderProperties.DampingName, Damping); clothingShader.SetFloat(ClothingShaderProperties.SpringStiffnessName, SpringStiffness); clothingShader.SetVector(ClothingShaderProperties.CenterName, Center); }