Example #1
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;
    }
Example #2
0
        public string GetName(SplineFormer splineFormer, LoftingGroup group)
        {
            if (!ExtendedNaming)
            {
                return(String.Format("{0} Lg#{1} result", splineFormer.gameObject.name, splineFormer.LoftingGroups.IndexOf(group)));
            }

            List <string> parts = new List <string>(10);

            if (AddObjectName)
            {
                parts.Add(splineFormer.gameObject.name);
            }
            if (AddLoftingGroupIndex)
            {
                parts.Add(String.Format("Lg#{0}", splineFormer.LoftingGroups.IndexOf(group)));
            }
            if (!String.IsNullOrEmpty(CustomName))
            {
                parts.Add(CustomName);
            }
            if (AddDateTime)
            {
                parts.Add(DateTime.Now.ToString());
            }
            if (AddAutoIncrementNumber)
            {
                _uk++;
                parts.Add(_uk.ToString());
            }

            string name = String.Join(" ", parts.ToArray());

            name = CleanFileName(name);
            return(name);
        }
Example #3
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;
        }
    }
Example #4
0
        public string GetName(SplineFormer splineFormer, LoftingGroup group)
        {
            if (!ExtendedNaming)
            {
                return String.Format("{0} Lg#{1} result", splineFormer.gameObject.name, splineFormer.LoftingGroups.IndexOf(group));
            }

            List<string> parts = new List<string>(10);
            if (AddObjectName)
                parts.Add(splineFormer.gameObject.name);
            if (AddLoftingGroupIndex)
                parts.Add(String.Format("Lg#{0}", splineFormer.LoftingGroups.IndexOf(group)));
            if (!String.IsNullOrEmpty(CustomName))
                parts.Add(CustomName);
            if (AddDateTime)
                parts.Add(DateTime.Now.ToString());
            if (AddAutoIncrementNumber)
            {
                _uk++;
                parts.Add(_uk.ToString());
            }

            string name = String.Join(" ", parts.ToArray());
            name = CleanFileName(name);
            return name;
        }
Example #5
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;
    }
Example #6
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;
        }
    }