Example #1
0
        protected virtual float CalculateStretch(SplineData spline)
        {
            float length = spline.length;

            float meshLength  = 0;
            float stretchable = 0;

            int meshIndex = 0;
            int rep       = 0;

            while (true)
            {
                float sz  = meshes[meshIndex].meshLength;
                float gap = meshes[meshIndex].gapLength;

                if (meshLength + sz + gap <= length)
                {
                    meshLength += sz + gap;

                    if ((meshes[meshIndex].stretchMode & StretchMode.Mesh) == StretchMode.Mesh)
                    {
                        stretchable += sz;
                    }

                    if ((meshes[meshIndex].stretchMode & StretchMode.Gaps) == StretchMode.Gaps)
                    {
                        stretchable += gap;
                    }
                }
                else
                {
                    break;
                }

                rep++;
                if (rep >= meshes[meshIndex].repeat)
                {
                    rep       = 0;
                    meshIndex = (meshIndex + 1) % meshes.Length;
                }
            }

            if (stretchable > 0)
            {
                return((length - meshLength + stretchable) / stretchable);
            }
            else
            {
                return(1);
            }
        }
Example #2
0
        private void AddVertexDataDeformed(
            SplineData spline, Mesh mesh, StretchMode stretch, AlignMode align,
            float stretchFactor, float meshStart, float minZ, Vector3 center,
            List <Vector3> vertices, List <Vector3> normals, List <Vector2> uvs)
        {
            Vector3[] inVerts   = mesh.vertices;
            Vector3[] inNormals = mesh.normals;
            Vector2[] inUvs     = uvs != null ? mesh.uv : null;

            float centerPos      = Mathf.Clamp01(meshStart + (center.z - minZ) / spline.length);
            var   centerRotation = spline.GetRotation(centerPos);

            if (align == AlignMode.ForceUpright)
            {
                centerRotation = Quaternion.Euler(0, centerRotation.eulerAngles.y, 0);
            }
            else if (align == AlignMode.NoRotation)
            {
                centerRotation = Quaternion.identity;
            }

            Vector3 centerOffset = spline.GetPoint(centerPos) + (centerRotation * Vector3.forward * minZ);

            Matrix4x4 alignMatrix = Matrix4x4.TRS(centerOffset, centerRotation, Vector3.one);

            for (int i = 0; i < inVerts.Length; i++)
            {
                var vert   = inVerts[i];
                var normal = inNormals[i];
                var uv     = Vector2.zero;
                if (inUvs != null && inUvs.Length > i)
                {
                    uv = inUvs[i];
                }

                vert.z -= minZ;
                if ((stretch & StretchMode.Mesh) == StretchMode.Mesh)
                {
                    vert.z *= stretchFactor;
                }

                if (align == AlignMode.Deform)
                {
                    float pos  = Mathf.Clamp01(meshStart + (vert.z / spline.length));
                    var   srot = spline.GetRotation(pos);
                    var   spos = spline.GetPoint(pos);

                    vert   = spos + (srot * Vector3.ProjectOnPlane(vert, Vector3.forward));
                    normal = srot * normal;
                }
                else
                {
                    vert = alignMatrix.MultiplyPoint(vert);

                    normal = alignMatrix.MultiplyVector(normal);
                }

                vertices.Add(vert);
                normals.Add(normal);
                if (uvs != null)
                {
                    uvs.Add(uv);
                }
            }
        }
Example #3
0
        protected virtual float AddMesh(SplineData spline, int meshIndex, float stretchFactor, float meshStart,
                                        List <Vector3> vertices, List <Vector3> normals, List <Vector2> uvs, List <int>[] triangles,
                                        List <Vector3> collisionVertices, List <Vector3> collisionNormals, List <int> collisionTriangles)
        {
            var mesh   = meshes[meshIndex];
            var toAdd  = mesh.render;
            var toAddC = mesh.collision;

            var stretch = mesh.stretchMode;
            var align   = mesh.alignMode;

            float sizeZ    = mesh.meshLength;
            float startGap = meshes[meshIndex].gapBefore;
            float endGap   = meshes[meshIndex].gapAfter;

            if ((stretch & StretchMode.Mesh) == StretchMode.Mesh)
            {
                sizeZ *= stretchFactor;
            }

            if ((stretch & StretchMode.Gaps) == StretchMode.Gaps)
            {
                startGap *= stretchFactor;
                endGap   *= stretchFactor;
            }

            meshStart += startGap / spline.length;
            float meshEnd = meshStart + (sizeZ + endGap) / spline.length;

            if (meshEnd <= 1 + (0.1f / spline.length))
            {
                int   vCount = vertices.Count;
                float minZ   = toAdd.bounds.min.z;
                var   center = toAdd.bounds.center;
                AddVertexDataDeformed(spline, toAdd, stretch, align, stretchFactor, meshStart, minZ, center, vertices, normals, uvs);

                for (int i = 0; i < toAdd.subMeshCount; i++)
                {
                    int destList = 0;
                    if (keepSeparateMaterials)
                    {
                        destList = submeshStartIndices[meshIndex] + i;
                    }

                    if (triangles[destList] == null)
                    {
                        triangles[destList] = new List <int>();
                    }

                    AddTriangleData(toAdd, i, vCount, triangles[destList]);
                }

                if (separateCollisionMesh && toAddC)
                {
                    int cvCount = collisionVertices.Count;
                    AddVertexDataDeformed(spline, toAddC, stretch, align, stretchFactor, meshStart, minZ, center, collisionVertices, collisionNormals, null);
                    AddTriangleData(toAddC, 0, cvCount, collisionTriangles);
                }
            }

            return(meshEnd);
        }
Example #4
0
        /// <summary>
        /// Create or update the rendering and collision mesh, and return them in out parameters.
        /// </summary>
        /// <param name="spline">The spline to align to.</param>
        /// <param name="mesh">The resulting render mesh.</param>
        /// <param name="collisionMesh">The resulting collision mesh.</param>
        public virtual void CreateMeshes(SplineData spline, out Mesh mesh, out Mesh collisionMesh)
        {
            if (meshes.Length == 0)
            {
                Debug.LogError("SplineMeshProfile needs at least one mesh!");
            }

            int submeshCount = GetSubmeshCount();

            List <Vector3> vertices = new List <Vector3>();
            List <Vector3> normals  = new List <Vector3>();
            List <Vector2> uvs      = new List <Vector2>();

            List <int>[] triangles = new List <int> [submeshCount];

            List <Vector3> collisionVertices  = null;
            List <Vector3> collisionNormals   = null;
            List <int>     collisionTriangles = null;

            if (separateCollisionMesh)
            {
                collisionVertices  = new List <Vector3>();
                collisionNormals   = new List <Vector3>();
                collisionTriangles = new List <int>();
            }

            if (meshes.Any(m => m.totalLength > 0))
            {
                float f         = 0;
                int   meshIndex = 0;
                int   rep       = 0;

                float stretch = CalculateStretch(spline);

                while (f < 1)
                {
                    if (meshes[meshIndex].render)
                    {
                        f = AddMesh(spline, meshIndex, stretch, f, vertices, normals, uvs, triangles, collisionVertices, collisionNormals, collisionTriangles);
                    }
                    else
                    {
                        f += meshes[meshIndex].gapLength / spline.length;
                    }

                    rep++;
                    if (rep >= meshes[meshIndex].repeat)
                    {
                        rep       = 0;
                        meshIndex = (meshIndex + 1) % meshes.Length;
                    }
                }
            }
            else
            {
                Debug.LogWarning("SplineMesh cannot be built without at least one mesh with a z size greater than 0.");
            }

            mesh      = new Mesh();
            mesh.name = "Spline Mesh";
            mesh.SetVertices(vertices);
            mesh.SetNormals(normals);
            mesh.SetUVs(0, uvs);
            mesh.subMeshCount = triangles.Length;
            for (int i = 0; i < triangles.Length; i++)
            {
                mesh.SetTriangles(triangles[i], i);
            }
            mesh.RecalculateTangents();
            mesh.RecalculateBounds();

            if (separateCollisionMesh)
            {
                collisionMesh      = new Mesh();
                collisionMesh.name = "Spline Collision";
                collisionMesh.SetVertices(collisionVertices);
                collisionMesh.SetNormals(collisionNormals);
                collisionMesh.subMeshCount = 1;
                collisionMesh.SetTriangles(collisionTriangles, 0);
                collisionMesh.RecalculateTangents();
                collisionMesh.RecalculateBounds();
            }
            else
            {
                collisionMesh = mesh;
            }
        }