Example #1
0
        /**
         *	\brief Triangulates userPoints and sets mesh data.
         *	@param m Mesh to be used for graphics.
         *	@param c Mesh to be used for collisions.
         *	@param convexity The #PolygonType.  Necessary for producing the correct face orientation.
         */
        public static bool MeshWithPoints(List <Vector2> _points, DrawSettings drawSettings, out Mesh m, out Mesh c, out Draw.PolygonType convexity)
        {
            // Assumes local space.  Returns graphics mesh in the following submesh order:
            // 0 - Front face / back face (optional)
            // 1 - Sides (optional)

            List <Vector2> points = new List <Vector2>(_points);

            m = new Mesh();
            c = new Mesh();

            m.name = "Graphics";
            c.name = "Collisions";

            convexity = Convexity(points);

            if (convexity == Draw.PolygonType.ConcaveClockwise || convexity == Draw.PolygonType.ConvexClockwise)
            {
                points.Reverse();
            }

            // Run a self-intersect test
            if (SelfIntersectTest(points))
            {
                        #if DEBUG
                Debug.LogWarning("Polydraw: Mesh generation failed on self-intersect test.");
                        #endif
                return(false);
            }

            float zOrigin         = 0f;
            float collisionOrigin = 0f;

            float halfSideLength    = drawSettings.sideLength / 2f;
            float colHalfSideLength = drawSettings.colDepth / 2f;

            if (drawSettings.axis != Axis.Forward)
            {
                halfSideLength    = -halfSideLength;
                colHalfSideLength = -colHalfSideLength;
            }

            switch (drawSettings.anchor)
            {
            case Draw.Anchor.Front:
                zOrigin = drawSettings.zPosition + drawSettings.faceOffset + halfSideLength;
                break;

            case Draw.Anchor.Back:
                zOrigin = drawSettings.zPosition + drawSettings.faceOffset - halfSideLength;
                break;

            case Draw.Anchor.Center:
            default:
                zOrigin = drawSettings.zPosition + drawSettings.faceOffset;
                break;
            }

            switch (drawSettings.colAnchor)
            {
            case Draw.Anchor.Front:
                collisionOrigin = drawSettings.zPosition + drawSettings.faceOffset + colHalfSideLength;
                break;

            case Draw.Anchor.Back:
                collisionOrigin = drawSettings.zPosition + drawSettings.faceOffset - colHalfSideLength;
                break;

            case Draw.Anchor.Center:
            default:
                collisionOrigin = drawSettings.zPosition + drawSettings.faceOffset;
                break;
            }

            /*** Generate Front Face ***/
            Triangulator tr            = new Triangulator(points);
            int[]        front_indices = tr.Triangulate();

            // Create the Vector3 vertices
            List <Vector3> front_vertices = points.ToVector3(drawSettings.axis, zOrigin - halfSideLength);

            Vector2 avg = Vector3.zero;
            for (int i = 0; i < points.Count; i++)
            {
                avg += points[i];
            }
            avg /= (float)points.Count;
            avg -= drawSettings.uvOffset;

            List <Vector2> front_uv = new List <Vector2>(points.ToArray());

            for (int i = 0; i < points.Count; i++)
            {
                front_uv[i] -= drawSettings.uvOffset;
                front_uv[i]  = front_uv[i].RotateAroundPoint(avg, drawSettings.uvRotation);
                front_uv[i]  = Vector2.Scale(front_uv[i], drawSettings.uvScale);
            }
            /*** Finish Front Face ***/

            /*** Generate Sides ***/

            // For use with graphics mesh
            List <Vector3> side_vertices = new List <Vector3>();

            // For use with collision mesh
            List <Vector3> collison_vertices = new List <Vector3>();

            for (int i = 0; i < points.Count; i++)
            {
                int next = i >= points.Count - 1 ? 0 : i + 1;

                Vector2 cur = points[i];
                Vector2 nex = points[next];

                side_vertices.Add(cur.ToVector3(drawSettings.axis, zOrigin + halfSideLength));
                side_vertices.Add(cur.ToVector3(drawSettings.axis, zOrigin - halfSideLength));

                side_vertices.Add(nex.ToVector3(drawSettings.axis, zOrigin + halfSideLength));
                side_vertices.Add(nex.ToVector3(drawSettings.axis, zOrigin - halfSideLength));

                collison_vertices.Add(cur.ToVector3(drawSettings.axis, collisionOrigin + colHalfSideLength));
                collison_vertices.Add(cur.ToVector3(drawSettings.axis, collisionOrigin - colHalfSideLength));
                collison_vertices.Add(nex.ToVector3(drawSettings.axis, collisionOrigin + colHalfSideLength));
                collison_vertices.Add(nex.ToVector3(drawSettings.axis, collisionOrigin - colHalfSideLength));
            }

            collison_vertices.Add(points[0].ToVector3(drawSettings.axis, collisionOrigin + colHalfSideLength));
            collison_vertices.Add(points[0].ToVector3(drawSettings.axis, collisionOrigin - colHalfSideLength));

            // +6 connects it to the first 2 verts
            int[] side_indices = new int[(points.Count * 6)];

            int windingOrder = 1;     // assume counter-clockwise, cause y'know, we set it that way

            int v = 0;
            for (int i = 0; i < side_indices.Length; i += 6)
            {
                // 0 is for clockwise winding order, anything else is CC
                if (i % 2 != windingOrder)
                {
                    side_indices[i + 0] = v;
                    side_indices[i + 1] = v + 1;
                    side_indices[i + 2] = v + 2;

                    side_indices[i + 3] = v + 1;
                    side_indices[i + 4] = v + 3;
                    side_indices[i + 5] = v + 2;
                }
                else
                {
                    side_indices[i + 2] = v + 0;
                    side_indices[i + 1] = v + 1;
                    side_indices[i + 0] = v + 2;

                    side_indices[i + 5] = v + 1;
                    side_indices[i + 4] = v + 3;
                    side_indices[i + 3] = v + 2;
                }
                v += 4;
            }
            /*** Finish Generating Sides ***/

            Vector2[] side_uv = CalcSideUVs(side_vertices.ToVector2(drawSettings.axis), drawSettings);
            m.Clear();

            List <Vector3> full_vertices = new List <Vector3>(drawSettings.generateSide ? front_vertices.Concat(side_vertices).ToArray() : front_vertices.ToArray());

            if (drawSettings.generateBackFace)
            {
                List <Vector3> backVerts = points.ToVector3(drawSettings.axis, zOrigin + halfSideLength);
                full_vertices.AddRange(backVerts);
            }

            m.vertices = full_vertices.ToArray();

            if (drawSettings.generateSide && drawSettings.generateBackFace)
            {
                m.subMeshCount = 2;

                int   len = front_indices.Length, sideVertexCount = side_vertices.Count;
                int   full      = len * 2;
                int[] frontBack = new int[full];
                System.Array.Copy(front_indices, frontBack, len);

                for (int i = 0; i < len; i++)
                {
                    frontBack[(full - 1) - i] = front_indices[i] + sideVertexCount + front_vertices.Count;
                }

                m.SetTriangles(frontBack, 0);
                m.SetTriangles(ShiftTriangles(side_indices, front_vertices.Count), 1);
            }
            else if (drawSettings.generateSide || drawSettings.generateBackFace)
            {
                if (drawSettings.generateSide)
                {
                    m.subMeshCount = 2;
                    m.SetTriangles(front_indices, 0);
                    m.SetTriangles(ShiftTriangles(side_indices, front_vertices.Count), 1);
                }
                else
                {
                    m.subMeshCount = 1;

                    int   len       = front_indices.Length;
                    int   full      = len * 2;
                    int[] frontBack = new int[full];
                    System.Array.Copy(front_indices, frontBack, len);

                    for (int i = 0; i < len; i++)
                    {
                        frontBack[(full - 1) - i] = front_indices[i] + front_vertices.Count;
                    }

                    m.SetTriangles(frontBack, 0);
                }
            }
            else
            {
                m.triangles = front_indices;
            }

            List <Vector2> full_uvs = new List <Vector2>(drawSettings.generateSide ? front_uv.Concat(side_uv).ToArray() : front_uv.ToArray());

            if (drawSettings.generateBackFace)
            {
                full_uvs.AddRange(front_uv);
            }

            m.uv = full_uvs.ToArray();
            m.RecalculateNormals();
            m.RecalculateBounds();
            ;

            // Smooth edge normals
            if (drawSettings.generateSide)
            {
                int front = front_vertices.Count;

                Vector3[] nrm = m.normals;

                int len = side_vertices.Count;
                for (int i = 2; i < len; i += 4)     //side_vertices.Count; i+=2)
                {
                    int curr = front + i;
                    int next = i >= len - 2 ? front : front + i + 2;

                    float angle = Vector3.Angle(nrm[curr], nrm[next]);
                    if (angle > drawSettings.smoothAngle)
                    {
                        continue;
                    }

                    Vector3 nrmAvg = ((nrm[curr] + nrm[next]) / 2f).normalized;

                    nrm[curr] = nrmAvg;
                    nrm[next] = nrmAvg;

                    nrm[curr + 1] = nrmAvg;
                    nrm[next + 1] = nrmAvg;
                }

                m.normals = nrm;
            }

            c.Clear();
            c.vertices  = collison_vertices.ToArray();
            c.triangles = side_indices;
            c.uv        = new Vector2[0];//side_uv.ToArray();
            c.RecalculateNormals();
            c.RecalculateBounds();
            return(true);
        }
Example #2
0
        /**
         *	\brief Triangulates userPoints and sets mesh data.
         *	This method should not be called directly unless you absolutely need to.  Use DrawPreviewMesh() or DrawFinalMesh() instead.
         *	@param m Mesh to be used for graphics.
         *	@param c Mesh to be used for collisions.
         *	@param convexity The #PolygonType.  Necessary for producing the correct face orientation.
         */
        public static bool MeshWithPoints(List <Vector2> _points, DrawSettings drawSettings, out Mesh m, out Mesh c, out Draw.PolygonType convexity)
        {
            // Assumes local space.  Returns graphics mesh in the following submesh order:
            // 0 - Front face
            // 1 - Sides (optional)
            // 2 - Back face (planned)

            List <Vector2> points = new List <Vector2>(_points);

//		Debug.Log(drawSettings.ToString());

            m = new Mesh();
            c = new Mesh();

            m.name = "Graphics";
            c.name = "Collisions";

            convexity = Convexity(points);

            if (convexity == Draw.PolygonType.ConcaveClockwise || convexity == Draw.PolygonType.ConvexClockwise)
            {
                points.Reverse();
            }

            // Run a self-intersect test
            if (SelfIntersectTest(points))
            {
                        #if DEBUG
                Debug.LogWarning("Polydraw: Mesh generation failed on self-intersect test.");
                        #endif
                return(false);
            }

            float zOrigin           = 0f;
            float collisionOrigin   = 0f;
            float halfSideLength    = drawSettings.sideLength / 2f;
            float colHalfSideLength = drawSettings.colDepth / 2f;

            switch (drawSettings.anchor)
            {
            case Draw.Anchor.Front:
                zOrigin = drawSettings.zPosition + drawSettings.faceOffset + halfSideLength;
                break;

            case Draw.Anchor.Back:
                zOrigin = drawSettings.zPosition + drawSettings.faceOffset - halfSideLength;
                break;

            case Draw.Anchor.Center:
            default:
                zOrigin = drawSettings.zPosition + drawSettings.faceOffset;
                break;
            }

            switch (drawSettings.colAnchor)
            {
            case Draw.Anchor.Front:
                collisionOrigin = drawSettings.zPosition + drawSettings.faceOffset + colHalfSideLength;
                break;

            case Draw.Anchor.Back:
                collisionOrigin = drawSettings.zPosition + drawSettings.faceOffset - colHalfSideLength;
                break;

            case Draw.Anchor.Center:
            default:
                collisionOrigin = drawSettings.zPosition + drawSettings.faceOffset;
                break;
            }


            /*** Generate Front Face ***/
            Triangulator tr            = new Triangulator(points);
            int[]        front_indices = tr.Triangulate();

            // Create the Vector3 vertices
            List <Vector3> front_vertices = VerticesWithPoints(points, zOrigin - halfSideLength);

            Vector2 avg = Vector3.zero;
            for (int i = 0; i < points.Count; i++)
            {
                avg += points[i];
            }
            avg /= (float)points.Count;
            avg -= drawSettings.uvOffset;

            List <Vector2> front_uv = new List <Vector2>(points.ToArray());

            for (int i = 0; i < points.Count; i++)
            {
                front_uv[i] -= drawSettings.uvOffset;
                front_uv[i]  = front_uv[i].RotateAroundPoint(avg, drawSettings.uvRotation);
                front_uv[i]  = Vector2.Scale(front_uv[i], drawSettings.uvScale);
            }

            /*** Finish Front Face ***/

            /*** Generate Sides ***/

            // For use with graphics mesh
            List <Vector3> side_vertices = new List <Vector3>();
            // For use with collision mesh
            List <Vector3> collison_vertices = new List <Vector3>();

            for (int i = 0; i < points.Count; i++)
            {
                int next = i >= points.Count - 1 ? 0 : i + 1;

                side_vertices.Add(new Vector3(points[i].x, points[i].y, zOrigin + halfSideLength));
                side_vertices.Add(new Vector3(points[i].x, points[i].y, zOrigin - halfSideLength));

                side_vertices.Add(new Vector3(points[next].x, points[next].y, zOrigin + halfSideLength));
                side_vertices.Add(new Vector3(points[next].x, points[next].y, zOrigin - halfSideLength));

                collison_vertices.Add(new Vector3(points[i].x, points[i].y, collisionOrigin + colHalfSideLength));
                collison_vertices.Add(new Vector3(points[i].x, points[i].y, collisionOrigin - colHalfSideLength));
                collison_vertices.Add(new Vector3(points[next].x, points[next].y, collisionOrigin + colHalfSideLength));
                collison_vertices.Add(new Vector3(points[next].x, points[next].y, collisionOrigin - colHalfSideLength));
            }

            collison_vertices.Add(new Vector3(points[0].x, points[0].y, collisionOrigin + colHalfSideLength));
            collison_vertices.Add(new Vector3(points[0].x, points[0].y, collisionOrigin - colHalfSideLength));

            // +6 connects it to the first 2 verts
            int[] side_indices = new int[(points.Count * 6)];

            int windingOrder = 1;     // assume counter-clockwise, cause y'know, we set it that way

            int v = 0;
            for (int i = 0; i < side_indices.Length; i += 6)
            {
                // 0 is for clockwise winding order, anything else is CC
                if (i % 2 != windingOrder)
                {
                    side_indices[i + 0] = v;
                    side_indices[i + 1] = v + 1;
                    side_indices[i + 2] = v + 2;

                    side_indices[i + 3] = v + 1;
                    side_indices[i + 4] = v + 3;
                    side_indices[i + 5] = v + 2;
                }
                else
                {
                    side_indices[i + 2] = v + 0;
                    side_indices[i + 1] = v + 1;
                    side_indices[i + 0] = v + 2;

                    side_indices[i + 5] = v + 1;
                    side_indices[i + 4] = v + 3;
                    side_indices[i + 3] = v + 2;
                }
                v += 4;
            }
            /*** Finish Generating Sides ***/

            Vector2[] side_uv = CalcSideUVs(side_vertices, drawSettings);
            m.Clear();
            m.vertices = drawSettings.generateSide ? front_vertices.Concat(side_vertices).ToArray() : front_vertices.ToArray();
            if (drawSettings.generateSide)
            {
                m.subMeshCount = 2;
                m.SetTriangles(front_indices, 0);
                m.SetTriangles(ShiftTriangles(side_indices, front_vertices.Count), 1);
            }
            else
            {
                m.triangles = front_indices;
            }
            m.uv = drawSettings.generateSide ? front_uv.Concat(side_uv).ToArray() : front_uv.ToArray();
            m.RecalculateNormals();
            m.RecalculateBounds();
            m.Optimize();

            c.Clear();
            c.vertices  = collison_vertices.ToArray();
            c.triangles = side_indices;
            c.uv        = new Vector2[0];//side_uv.ToArray();
            c.RecalculateNormals();
            c.RecalculateBounds();
            return(true);
        }