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)));
            }
        }
Example #2
0
        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);
        }
Example #3
0
        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);
        }