void DrawShape(List <Vector3> mirror, int count, int resolution = 5) { // left side var points = new List <Vector3>(); for (int i = 0; i <= count; i++) { var edge = PFCatmullRomSpline.GetCatmullRomPositions( resolution, PFShape.GetLoopPoint(mirror, i - 1), PFShape.GetLoopPoint(mirror, i), PFShape.GetLoopPoint(mirror, i + 1), PFShape.GetLoopPoint(mirror, i + 2) ); if (i != 0) { edge.RemoveAt(0); } points.AddRange(edge); } for (int i = 0, n = points.Count - 1; i < n; i++) { var from = points[i]; var to = points[i + 1]; Handles.DrawLine(Translate(from), Translate(to)); } for (int i = 0, n = points.Count - 1; i < n; i++) { var from = points[i]; var to = points[i + 1]; Handles.DrawLine(Translate(new Vector2(-from.x, from.y)), Translate(new Vector2(-to.x, to.y))); } }
public static Mesh Build(float size, List <PFControlPoint> controls, int numberOfVerticesOnOneSide = 20, int resolution = 2, float noiseDepth = 0.25f, Vector2 noiseScale = default(Vector2), Vector2 noiseOffset = default(Vector2)) { var mesh = new Mesh(); resolution = Mathf.Max(1, resolution); if (controls.Count < 1) { throw new UnityException("control points size is not enough"); } int controlSize = controls.Count; var counts = GetCounts(controls, numberOfVerticesOnOneSide); int countOnEdge = counts.Aggregate((acc, next) => { return(acc + next); }); var bottom = new Vector3(0f, 0f, 0f); var top = new Vector3(0f, size, 0f); var points = new List <Vector3>(); points.Add(bottom); points.AddRange(controls.Select(p => new Vector3(p.width * size, p.height * size, 0f))); points.Add(top); var reverse = controls.ToList(); reverse.Reverse(); points.AddRange(reverse.Select(p => new Vector3(-p.width * size, p.height * size, 0f))); var vertices = new List <Vector3>(); var uv = new List <Vector2>(); // left side for (int i = 0; i < resolution; i++) { var r = (float)(resolution - i) / resolution; for (int c = 0; c <= controlSize; c++) { var edge = PFCatmullRomSpline.GetCatmullRomPositions( counts[c], GetEdge(GetLoopPoint(points, c - 1), r), GetEdge(GetLoopPoint(points, c), r), GetEdge(GetLoopPoint(points, c + 1), r), GetEdge(GetLoopPoint(points, c + 2), r) ); vertices.AddRange(edge); uv.AddRange(edge.Select(v => { return(new Vector2(v.x / size, v.y / size)); })); } } // midrib for (int c = 0; c <= controlSize; c++) { var edge = PFCatmullRomSpline.GetCatmullRomPositions( counts[c], GetEdge(GetLoopPoint(points, c - 1), 0f), GetEdge(GetLoopPoint(points, c), 0f), GetEdge(GetLoopPoint(points, c + 1), 0f), GetEdge(GetLoopPoint(points, c + 2), 0f) ); vertices.AddRange(edge); uv.AddRange(edge.Select(v => { return(new Vector2(0f, v.y / size)); })); } // right side for (int i = 0; i < resolution; i++) { var r = -(float)(i + 1) / resolution; for (int c = 0; c <= controlSize; c++) { var edge = PFCatmullRomSpline.GetCatmullRomPositions( counts[c], GetEdge(GetLoopPoint(points, c - 1), r), GetEdge(GetLoopPoint(points, c), r), GetEdge(GetLoopPoint(points, c + 1), r), GetEdge(GetLoopPoint(points, c + 2), r) ); vertices.AddRange(edge); uv.AddRange(edge.Select(v => { return(new Vector2(v.x / size, v.y / size)); })); } } var triangles = new List <int>(); // left side faces for (int i = 0, n = resolution; i < n; i++) { var offset = i * countOnEdge; for (int j = 0; j < countOnEdge - 1; j++) { var a = j + offset; var b = a + 1; var c = a + countOnEdge; var d = b + countOnEdge; triangles.Add(a); triangles.Add(b); triangles.Add(c); triangles.Add(b); triangles.Add(d); triangles.Add(c); } } // right side faces for (int i = 0, n = resolution; i < n; i++) { var offset = (i + resolution) * countOnEdge; for (int j = 0; j < countOnEdge - 1; j++) { var a = j + offset; var b = a + 1; var c = a + countOnEdge; var d = b + countOnEdge; triangles.Add(a); triangles.Add(d); triangles.Add(c); triangles.Add(b); triangles.Add(d); triangles.Add(a); } } var noffset = noiseOffset + new Vector2(size, size); mesh.vertices = vertices.Select(v => { return(new Vector3(v.x, v.y, v.y * noiseDepth * Depth(v, noffset, noiseScale))); }).ToArray(); mesh.uv = uv.ToArray(); mesh.triangles = triangles.ToArray(); mesh.RecalculateBounds(); mesh.RecalculateNormals(); return(mesh); }
Mesh Build(List <Vector3> controls, int wresolution, int hresolution, float radius, Func <float, float> f) { controls = controls.ToList(); if (controls.Count < 4) { throw new UnityException("control size is not enough"); } Vector3 first = controls[0], second = controls[1]; Vector3 blast = controls[controls.Count - 2], last = controls[controls.Count - 1]; controls.Insert(0, first + (first - second).normalized * 0.25f); controls.Add(last + (last - blast).normalized * 0.25f); var cores = new List <Vector3>(); for (int i = 1, n = controls.Count - 2; i < n; i++) { var tmp = PFCatmullRomSpline.GetCatmullRomPositions(hresolution, controls[i - 1], controls[i], controls[i + 1], controls[i + 2]); if (i != 1) { tmp.RemoveAt(0); } cores.AddRange(tmp); } var vertices = new List <Vector3>(); var uv = new List <Vector2>(); var triangles = new List <int>(); var mesh = new Mesh(); var circle = new List <Vector3>(); for (int i = 0; i < wresolution; i++) { var r = ((float)i / wresolution) * (Mathf.PI * 2f); var cos = Mathf.Cos(r) * radius; var sin = Mathf.Sin(r) * radius; circle.Add(new Vector3(cos, sin, 0f)); } vertices.Add(cores.First()); Vector3 right = Vector3.right; bool inverse = false; segments = new List <Point>(); for (int i = 0, n = cores.Count; i < n; i++) { var core = cores[i]; var v = (float)i / (n - 1); if (i == 0) { // first segment for (int j = 0; j < wresolution; j++) { triangles.Add(0); triangles.Add((j + 1) % wresolution + 1); triangles.Add(j + 1); } var next = cores[i + 1]; var dir = (next - core).normalized; right = (Quaternion.LookRotation(dir) * Vector3.right).normalized; uv.Add(new Vector2(0.5f, 0f)); } var offset = i * wresolution + 1; if (i < n - 1) { var next = cores[i + 1]; var dir = (next - core).normalized; var cr = (Quaternion.LookRotation(dir) * Vector3.right).normalized; if (Vector3.Dot(right, cr) < 0f) { inverse = !inverse; } var rotation = AddCircle(vertices, core, circle, f(v), dir, inverse); segments.Add(new Point(core, rotation)); right = cr; for (int j = 0; j < wresolution; j++) { var a = offset + j; var b = offset + (j + 1) % wresolution; var c = a + wresolution; var d = b + wresolution; triangles.Add(a); triangles.Add(b); triangles.Add(c); triangles.Add(c); triangles.Add(b); triangles.Add(d); var u = (float)j / (wresolution - 1); uv.Add(new Vector2(u, v)); } } else { // last segment var prev = cores[i - 1]; var dir = (core - prev).normalized; var cr = (Quaternion.LookRotation(dir) * Vector3.right).normalized; if (Vector3.Dot(right, cr) < 0f) { inverse = !inverse; } var rotation = AddCircle(vertices, core, circle, f(v), dir, inverse); tip = new Point(core, rotation); vertices.Add(cores.Last()); uv.Add(new Vector2(0.5f, 1f)); int m = vertices.Count - 1; for (int j = 0; j < wresolution; j++) { triangles.Add(m); triangles.Add(offset + j); triangles.Add(offset + ((j + 1) % wresolution)); var u = (float)j / (wresolution - 1); uv.Add(new Vector2(u, v)); } } } mesh.vertices = vertices.ToArray(); mesh.uv = uv.ToArray(); mesh.triangles = triangles.ToArray(); mesh.RecalculateBounds(); mesh.RecalculateNormals(); return(mesh); }