Exemple #1
0
    private void CombineSegments(Mesh mesh, ManagedMesh[] resultSegments)
    {
        ManagedMesh result = ManagedMesh.Combine(resultSegments);

        mesh.Clear();

        mesh.vertices  = result.vertices;
        mesh.triangles = result.triangles;
        mesh.uv        = result.uv;
        mesh.normals   = result.normals;
        mesh.tangents  = result.tangents;

        mesh.RecalculateBounds();
    }
Exemple #2
0
    private void WeldAndSmooth(LoftingGroup group, ManagedMesh meshA, ManagedMesh meshB)
    {
        float weldDistanceSqr = group.WeldingDistance * group.WeldingDistance;

        var verticesA = meshA.vertices;
        var verticesB = meshB.vertices;

        var normalsA = meshA.normals;
        var normalsB = meshB.normals;

        int i, j, an, bn;

        an = verticesA.Length;
        bn = verticesB.Length;

        for (i = 0; i < an; i++)
        {
            for (j = 0; j < bn; j++)
            {
                // if any one inside limit distance...
                if (Vector3.SqrMagnitude(verticesA[i] - verticesB[j]) < weldDistanceSqr)
                {
                    if (group.Weld)
                    {
                        verticesB[j] = verticesA[i];
                    }

                    if (group.SmoothNormals && Vector3.Dot(normalsA[i], normalsB[j]) > 0)
                    {
                        normalsA[i] = Vector3.Slerp(normalsA[i], normalsB[j], 0.5f);
                        normalsB[j] = normalsA[i];
                    }
                }
            }
        }

        meshA.vertices = verticesA;
        meshB.vertices = verticesB;

        meshA.normals = normalsA;
        meshB.normals = normalsB;
    }
Exemple #3
0
        public void Fix()
        {
            mSegmentMesh = (SegmentMesh != null) ? new ManagedMesh(SegmentMesh) : null;
            mStartPiece  = (StartPiece != null) ? new ManagedMesh(StartPiece) : null;
            mEndPiece    = (EndPiece != null) ? new ManagedMesh(EndPiece) : null;

            //Prevents mesh buffer overflow
            ActiveSegmentsNumber = Mathf.Clamp(
                ActiveSegmentsNumber,
                1,
                ushort.MaxValue / mSegmentMesh.vertexCount);

            if (ResultSegments == null || ResultSegments.Length != ActiveSegmentsNumber)
            {
                var newResultSegments = new ManagedMesh[ActiveSegmentsNumber];

                if (ResultSegments == null)
                {
                    ResultSegments = new ManagedMesh[0];
                }

                int minLenght = Math.Min(ResultSegments.Length, ActiveSegmentsNumber);

                for (int s = 0; s < minLenght; s++)
                {
                    newResultSegments[s] = ResultSegments[s];
                }

                for (int s = minLenght; s < ActiveSegmentsNumber; s++)
                {
                    newResultSegments[s] = new ManagedMesh();
                }

                for (int s = ActiveSegmentsNumber; s < ResultSegments.Length; s++)
                {
                    ResultSegments[s].Clear();
                }

                ResultSegments = newResultSegments;
            }
        }
Exemple #4
0
    /// <summary>
    /// Rebuilds the mesh for the specified lofting group
    /// </summary>
    /// <param name="group">lofting group</param>
    private void RebuildMesh(LoftingGroup group)
    {
        if (!group.IsValid)
        {
            throw new ArgumentException("SegmentMesh and MeshFilter can't be null");
        }

        LoftDirection.Normalize();
        var result = group.ResultMesh;

        float segmentStep = group.IntervalLength / group.ActiveSegmentsNumber;

        for (int s = 0; s < group.ActiveSegmentsNumber; s++)
        {
            ManagedMesh segment = group.ResultSegments[s];
            segment.Clear();

            ManagedMesh source = group.mSegmentMesh;

            if (s == 0 && group.mStartPiece != null)
            {
                source = group.mStartPiece;
            }

            if (s == group.ActiveSegmentsNumber - 1 && group.mEndPiece != null)
            {
                source = group.mEndPiece;
            }

            Vector3 pivotShift   = Vector3.Project(source.bounds.center, LoftDirection);
            Vector3 startSPos    = pivotShift - source.bounds.extents.Mul(LoftDirection);
            Vector3 endSPos      = pivotShift + source.bounds.extents.Mul(LoftDirection);
            Vector3 sourceDir    = (endSPos - startSPos);
            float   sourceLenght = sourceDir.magnitude;

            bool flipSegment = RollerCoasterFix && _flipNext;

            Vector3   dirS           = LoftDirection;
            Vector3[] sourceVertices = source.vertices;
            Vector3[] resultVertices = new Vector3[source.vertexCount];

            Vector3[] sourceNormals = source.normals;
            Vector3[] resultNormals = new Vector3[source.vertexCount];

            Vector4[] sourceTangents = source.tangents;
            Vector4[] resultTangents = new Vector4[source.vertexCount];

            for (int i = 0; i < source.vertexCount; i++)
            {
                Vector3 curSPos   = sourceVertices[i] - startSPos;
                Vector3 projected = Vector3.Project(curSPos, dirS);
                Vector3 perp      = curSPos - projected;
                perp.Scale(SegmentScale);
                float sourceT = Mathf.InverseLerp(0f, sourceLenght, projected.magnitude);
                float resultT = group.StartPosition
                                + segmentStep * s + segmentStep * sourceT;

                int   nodeIndex;
                float nodeT = GetNodeT(resultT, out nodeIndex);

                if (nodeIndex < 0)
                {
                    nodeIndex = 0;
                }
                else if (nodeIndex > Nodes.Count - 1)
                {
                    nodeIndex = Nodes.Count - 1;
                }

                int nextIndex = nodeIndex + 1;

                if (nodeIndex >= Nodes.Count - 1)
                {
                    if (Loop)
                    {
                        nextIndex = 0;
                    }
                    else
                    {
                        nodeIndex = Nodes.Count - 2;
                        nextIndex = Nodes.Count - 1;
                    }
                }

                SplineNode fromNode = Nodes[nodeIndex];
                SplineNode toNode   = Nodes[nextIndex];

                Vector3 startRPos = fromNode.LocalPosition;
                Vector3 endRPos   = toNode.LocalPosition;

                Vector3 nodesDir = (endRPos - startRPos);

                Vector3 upwardVector    = Vector3.up;
                float   additionalAngle = 0f;

                if (RollerCoasterFix && s > 0 && nodeIndex > 0)
                {
                    SplineNode prevNode       = Nodes[nodeIndex - 1];
                    Vector3    prevNodesDir   = (startRPos - prevNode.LocalPosition);
                    Vector3    prevNodesDirXZ = prevNodesDir;
                    prevNodesDirXZ.y = 0;

                    Vector3 nodesDirXZ = nodesDir;
                    nodesDirXZ.y = 0;

                    float dot = Vector3.Dot(prevNodesDirXZ, nodesDirXZ);

                    if (Vector3.Dot(Vector3.up, nodesDir) > 0.5f)
                    {
                        upwardVector    = Vector3.left;
                        additionalAngle = -90f * Mathf.Abs(Vector3.Dot(LoftDirection, Vector3.left));
                        _flipNext       = true;
                    }
                    else if (Vector3.Dot(Vector3.up, nodesDir) < -0.5f)
                    {
                        upwardVector    = Vector3.right;
                        additionalAngle = 90f * Mathf.Abs(Vector3.Dot(LoftDirection, Vector3.left));
                        _flipNext       = false;
                    }
                    else
                    {
                        if (flipSegment)
                        {
                            additionalAngle = 180f;
                        }
                    }
                }

                Vector3 startR_RightP = fromNode.RightP;

                Vector3 endRPos_RightP = toNode.RightP;
                Vector3 endRPos_LeftP  = toNode.LeftP;

                float loftAngle = LoftAngle +
                                  Mathf.Lerp(fromNode.AdditionalLoftAngle, toNode.AdditionalLoftAngle, nodeT);

                Vector3 dirR = nodesDir.normalized;

                if (Loop || (nodeIndex > 0 && nodeIndex + 2 < Nodes.Count))
                {
                    dirR = (startR_RightP - startRPos).normalized;
                    Vector3 dirN = (endRPos_RightP - endRPos).normalized;
                    float   t    = QuadraticSmooth ? (nodeT * nodeT) : nodeT;
                    dirR = Vector3.Slerp(dirR, dirN, t);
                }

                Quaternion directionRot =
                    Quaternion.LookRotation(dirR, upwardVector) * Quaternion.Inverse(Quaternion.LookRotation(dirS, upwardVector));

                Quaternion loftRot =
                    Quaternion.AngleAxis(additionalAngle + loftAngle, dirR);

                resultVertices[i] =
                    startRPos
                    + loftRot * (directionRot * perp)
                    + SplinePowerVector3Extensions.Bezier(
                        startRPos - startRPos,
                        startR_RightP - startRPos,
                        endRPos_LeftP - startRPos,
                        endRPos - startRPos, nodeT);

                if (group.ProcessOriginNormals)
                {
                    resultNormals[i] = loftRot * directionRot * sourceNormals[i];
                }

                if (group.ProcessOriginTangents)
                {
                    resultTangents[i] = loftRot * directionRot * sourceTangents[i];
                }
            }

            segment.vertices  = resultVertices;
            segment.triangles = source.triangles;
            segment.uv        = source.uv;
            segment.normals   = resultNormals;
            segment.tangents  = resultTangents;
        }

        for (int s = 0; s < group.ResultSegments.Length; s++)
        {
            if (group.RecalculateNormals)
            {
                group.ResultSegments[s].RecalculateNormals();
            }

            if (s > 0)
            {
                if (group.SmoothNormals || group.Weld)
                {
                    WeldAndSmooth(group, group.ResultSegments[s - 1], group.ResultSegments[s]);
                }
            }

            if (Loop && s == 0)
            {
                if (group.SmoothNormals || group.Weld)
                {
                    WeldAndSmooth(group, group.ResultSegments[group.ResultSegments.Length - 1], group.ResultSegments[s]);
                }
            }
        }

        CombineSegments(result, group.ResultSegments);

#if UNITY_EDITOR
        UnityEditor.MeshUtility.SetMeshCompression(result, UnityEditor.ModelImporterMeshCompression.High);
        result.name = ExportOptions.GetName(this, group);
#endif
        result.Optimize();
        result.hideFlags = HideFlags.DontSave;

        group.ResultMesh = result;

        if (group.MeshFilter != null)
        {
            group.MeshFilter.sharedMesh = null;
            group.MeshFilter.sharedMesh = result;
        }

        if (group.MeshCollider != null)
        {
            group.MeshCollider.sharedMesh = null;
            group.MeshCollider.sharedMesh = result;
        }
    }
Exemple #5
0
        public static ManagedMesh Combine(ManagedMesh[] segments)
        {
            ManagedMesh result = new ManagedMesh();

            Vector3[] vertices  = new Vector3[segments.Sum(p => p.vertices.Length)];
            int[]     triangles = new int[segments.Sum(p => p.triangles.Length)];
            Vector2[] uv        = new Vector2[segments.Sum(p => p.uv.Length)];
            Vector3[] normals   = new Vector3[segments.Sum(p => p.normals.Length)];
            Vector4[] tangents  = new Vector4[segments.Sum(p => p.tangents.Length)];

            int verticesShift  = 0;
            int trianglesShift = 0;
            int uvShift        = 0;
            int normalsShift   = 0;
            int tangentsShift  = 0;

            for (int k = 0; k < segments.Length; k++)
            {
                if (k > 0)
                {
                    var previousSegment = segments[k - 1];
                    verticesShift  += previousSegment.vertices.Length;
                    trianglesShift += previousSegment.triangles.Length;
                    uvShift        += previousSegment.uv.Length;
                    normalsShift   += previousSegment.normals.Length;
                    tangentsShift  += previousSegment.tangents.Length;
                }

                var segment = segments[k];

                for (int i = 0; i < segment.vertices.Length; i++)
                {
                    vertices[verticesShift + i] = segment.vertices[i];
                }

                for (int i = 0; i < segment.triangles.Length; i++)
                {
                    triangles[trianglesShift + i] = verticesShift + segment.triangles[i];
                }

                for (int i = 0; i < segment.uv.Length; i++)
                {
                    uv[uvShift + i] = segment.uv[i];
                }

                for (int i = 0; i < segment.normals.Length; i++)
                {
                    normals[normalsShift + i] = segment.normals[i];
                }

                for (int i = 0; i < segment.tangents.Length; i++)
                {
                    tangents[tangentsShift + i] = segment.tangents[i];
                }
            }

            result.vertices  = vertices;
            result.triangles = triangles;
            result.uv        = uv;
            result.normals   = normals;
            result.tangents  = tangents;

            return(result);
        }
Exemple #6
0
    private void WeldAndSmooth(LoftingGroup group, ManagedMesh meshA, ManagedMesh meshB)
    {
        float weldDistanceSqr = group.WeldingDistance * group.WeldingDistance;

        var verticesA = meshA.vertices;
        var verticesB = meshB.vertices;

        var normalsA = meshA.normals;
        var normalsB = meshB.normals;

        int i, j, an, bn;
        an = verticesA.Length;
        bn = verticesB.Length;

        for (i = 0; i < an; i++)
            for (j = 0; j < bn; j++)
            {
                // if any one inside limit distance...
                if (Vector3.SqrMagnitude(verticesA[i] - verticesB[j]) < weldDistanceSqr)
                {
                    if (group.Weld)
                    {
                        verticesB[j] = verticesA[i];
                    }

                    if (group.SmoothNormals && Vector3.Dot(normalsA[i], normalsB[j]) > 0)
                    {
                        normalsA[i] = Vector3.Slerp(normalsA[i], normalsB[j], 0.5f);
                        normalsB[j] = normalsA[i];
                    }
                }
            }

        meshA.vertices = verticesA;
        meshB.vertices = verticesB;

        meshA.normals = normalsA;
        meshB.normals = normalsB;
    }
Exemple #7
0
    private void CombineSegments(Mesh mesh, ManagedMesh[] resultSegments)
    {
        ManagedMesh result = ManagedMesh.Combine(resultSegments);
        mesh.Clear();

        mesh.vertices = result.vertices;
        mesh.triangles = result.triangles;
        mesh.uv = result.uv;
        mesh.normals = result.normals;
        mesh.tangents = result.tangents;

        mesh.RecalculateBounds();
    }
Exemple #8
0
        public static ManagedMesh Combine(ManagedMesh[] segments)
        {
            ManagedMesh result = new ManagedMesh();

            Vector3[] vertices = new Vector3[segments.Sum(p => p.vertices.Length)];
            int[] triangles = new int[segments.Sum(p => p.triangles.Length)];
            Vector2[] uv = new Vector2[segments.Sum(p => p.uv.Length)];
            Vector3[] normals = new Vector3[segments.Sum(p => p.normals.Length)];
            Vector4[] tangents = new Vector4[segments.Sum(p => p.tangents.Length)];

            int verticesShift = 0;
            int trianglesShift = 0;
            int uvShift = 0;
            int normalsShift = 0;
            int tangentsShift = 0;

            for (int k = 0; k < segments.Length; k++)
            {
                if (k > 0)
                {
                    var previousSegment = segments[k - 1];
                    verticesShift += previousSegment.vertices.Length;
                    trianglesShift += previousSegment.triangles.Length;
                    uvShift += previousSegment.uv.Length;
                    normalsShift += previousSegment.normals.Length;
                    tangentsShift += previousSegment.tangents.Length;
                }

                var segment = segments[k];

                for (int i = 0; i < segment.vertices.Length; i++)
                {
                    vertices[verticesShift + i] = segment.vertices[i];
                }

                for (int i = 0; i < segment.triangles.Length; i++)
                {
                    triangles[trianglesShift + i] = verticesShift + segment.triangles[i];
                }

                for (int i = 0; i < segment.uv.Length; i++)
                {
                    uv[uvShift + i] = segment.uv[i];
                }

                for (int i = 0; i < segment.normals.Length; i++)
                {
                    normals[normalsShift + i] = segment.normals[i];
                }

                for (int i = 0; i < segment.tangents.Length; i++)
                {
                    tangents[tangentsShift + i] = segment.tangents[i];
                }
            }

            result.vertices = vertices;
            result.triangles = triangles;
            result.uv = uv;
            result.normals = normals;
            result.tangents = tangents;

            return result;
        }
Exemple #9
0
        public void Fix()
        {
            mSegmentMesh = (SegmentMesh != null) ? new ManagedMesh(SegmentMesh) : null;
            mStartPiece = (StartPiece != null) ? new ManagedMesh(StartPiece) : null;
            mEndPiece = (EndPiece != null) ? new ManagedMesh(EndPiece) : null;

            //Prevents mesh buffer overflow
            ActiveSegmentsNumber = Mathf.Clamp(
                ActiveSegmentsNumber,
                1,
                ushort.MaxValue / mSegmentMesh.vertexCount);

            if (ResultSegments == null || ResultSegments.Length != ActiveSegmentsNumber)
            {
                var newResultSegments = new ManagedMesh[ActiveSegmentsNumber];

                if (ResultSegments == null)
                {
                    ResultSegments = new ManagedMesh[0];
                }

                int minLenght = Math.Min(ResultSegments.Length, ActiveSegmentsNumber);

                for (int s = 0; s < minLenght; s++)
                {
                    newResultSegments[s] = ResultSegments[s];
                }

                for (int s = minLenght; s < ActiveSegmentsNumber; s++)
                {
                    newResultSegments[s] = new ManagedMesh();
                }

                for (int s = ActiveSegmentsNumber; s < ResultSegments.Length; s++)
                {
                    ResultSegments[s].Clear();
                }

                ResultSegments = newResultSegments;
            }
        }