Пример #1
0
        private void DrawSelectedSegmentGUI()
        {
            int segmentIndex = splineEditingGUIDrawer.selectedSegmentIndex;

            if (segmentIndex < 0 ||
                segmentIndex >= water.Spline.Anchors.Count)
            {
                return;
            }
            string label = "Selected Segment";
            string id    = "poseidon-selected-segment";

            PEditorCommon.Foldout(label, true, id, () =>
            {
                EditorGUI.indentLevel -= 1;
                EditorGUI.BeginChangeCheck();
                PSplineSegment s                    = water.Spline.Segments[segmentIndex];
                GUI.enabled                         = !PSplineToolConfig.Instance.AutoTangent;
                s.StartTangent                      = PEditorCommon.InlineVector3Field("Start Tangent", s.StartTangent);
                s.EndTangent                        = PEditorCommon.InlineVector3Field("End Tangent", s.EndTangent);
                GUI.enabled                         = true;
                s.ResolutionMultiplierY             = EditorGUILayout.Slider("Resolution Multiplier Y", s.ResolutionMultiplierY, 0f, 2f);
                water.Spline.Segments[segmentIndex] = s;
                if (EditorGUI.EndChangeCheck())
                {
                    water.GenerateSplineMeshAtSegment(segmentIndex);
                }
                EditorGUI.indentLevel += 1;
            });
        }
Пример #2
0
        private void HandleSelectedSegmentModifications()
        {
            if (selectedSegmentIndex < 0 || selectedSegmentIndex >= water.Spline.Segments.Count)
            {
                return;
            }
            if (!water.Spline.IsSegmentValid(selectedSegmentIndex))
            {
                return;
            }
            PSplineSegment segment     = water.Spline.Segments[selectedSegmentIndex];
            PSplineAnchor  startAnchor = water.Spline.Anchors[segment.StartIndex];
            PSplineAnchor  endAnchor   = water.Spline.Anchors[segment.EndIndex];

            Vector3 worldStartPosition = water.transform.TransformPoint(startAnchor.Position);
            Vector3 worldEndPosition   = water.transform.TransformPoint(endAnchor.Position);
            Vector3 worldStartTangent  = water.transform.TransformPoint(segment.StartTangent);
            Vector3 worldEndTangent    = water.transform.TransformPoint(segment.EndTangent);

            EditorGUI.BeginChangeCheck();
            Handles.zTest     = UnityEngine.Rendering.CompareFunction.Always;
            worldStartTangent = Handles.PositionHandle(worldStartTangent, Quaternion.identity);
            worldEndTangent   = Handles.PositionHandle(worldEndTangent, Quaternion.identity);

            segment.StartTangent = water.transform.InverseTransformPoint(worldStartTangent);
            segment.EndTangent   = water.transform.InverseTransformPoint(worldEndTangent);
            if (EditorGUI.EndChangeCheck())
            {
                water.GenerateSplineMeshAtSegment(selectedSegmentIndex);
            }

            Handles.color = Color.white;
            Handles.DrawLine(worldStartPosition, worldStartTangent);
            Handles.DrawLine(worldEndPosition, worldEndTangent);
        }
Пример #3
0
        public Vector3 EvaluateScale(int segmentIndex, float t)
        {
            PSplineSegment s           = Segments[segmentIndex];
            PSplineAnchor  startAnchor = Anchors[s.StartIndex];
            PSplineAnchor  endAnchor   = Anchors[s.EndIndex];

            return(Vector3.Lerp(startAnchor.Scale, endAnchor.Scale, t));
        }
Пример #4
0
        public Quaternion EvaluateRotation(int segmentIndex, float t)
        {
            PSplineSegment s           = Segments[segmentIndex];
            PSplineAnchor  startAnchor = Anchors[s.StartIndex];
            PSplineAnchor  endAnchor   = Anchors[s.EndIndex];

            return(Quaternion.Lerp(startAnchor.Rotation, endAnchor.Rotation, t));
        }
Пример #5
0
        public bool IsSegmentValid(int segmentIndex)
        {
            PSplineSegment s = Segments[segmentIndex];

            if (s == null)
            {
                return(false);
            }
            bool startIndexValid =
                s.StartIndex >= 0 &&
                s.StartIndex < Anchors.Count &&
                Anchors[s.StartIndex] != null;
            bool endIndexValid =
                s.EndIndex >= 0 &&
                s.EndIndex < Anchors.Count &&
                Anchors[s.EndIndex] != null;

            return(startIndexValid && endIndexValid);
        }
Пример #6
0
        private bool CheckHasBranch()
        {
            int[] count = new int[Anchors.Count];
            for (int i = 0; i < Segments.Count; ++i)
            {
                if (!IsSegmentValid(i))
                {
                    continue;
                }
                PSplineSegment s = Segments[i];
                count[s.StartIndex] += 1;
                count[s.EndIndex]   += 1;
                if (count[s.StartIndex] > 2 || count[s.EndIndex] > 2)
                {
                    return(true);
                }
            }

            return(false);
        }
Пример #7
0
        public Vector3 EvaluatePosition(int segmentIndex, float t)
        {
            PSplineSegment s           = Segments[segmentIndex];
            PSplineAnchor  startAnchor = Anchors[s.StartIndex];
            PSplineAnchor  endAnchor   = Anchors[s.EndIndex];

            Vector3 p0 = startAnchor.Position;
            Vector3 p1 = s.StartTangent;
            Vector3 p2 = s.EndTangent;
            Vector3 p3 = endAnchor.Position;

            t = Mathf.Clamp01(t);
            float   oneMinusT = 1 - t;
            Vector3 p         =
                oneMinusT * oneMinusT * oneMinusT * p0 +
                3 * oneMinusT * oneMinusT * t * p1 +
                3 * oneMinusT * t * t * p2 +
                t * t * t * p3;

            return(p);
        }
Пример #8
0
        public override void Apply()
        {
            if (SplineCreator == null && Water == null)
            {
                return;
            }
            if (Water.MeshType != PWaterMeshType.Spline)
            {
                return;
            }

            GSpline gSpline = SplineCreator.Spline;
            PSpline pSpline = Water.Spline;

            pSpline.Dispose();
            pSpline.Anchors.Clear();
            pSpline.Segments.Clear();

            for (int i = 0; i < gSpline.Anchors.Count; ++i)
            {
                PSplineAnchor a = (PSplineAnchor)gSpline.Anchors[i];
                a.Position += Vector3.up * HeightOffset;
                pSpline.Anchors.Add(a);
            }

            for (int i = 0; i < gSpline.Segments.Count; ++i)
            {
                PSplineSegment s = (PSplineSegment)gSpline.Segments[i];
                s.StartTangent += Vector3.up * HeightOffset;
                s.EndTangent   += Vector3.up * HeightOffset;
                pSpline.Segments.Add(s);
            }

            Water.transform.position   = transform.position;
            Water.transform.rotation   = transform.rotation;
            Water.transform.localScale = transform.localScale;
            Water.SplineWidth          = SplineCreator.Width + SplineCreator.FalloffWidth * 2;
            Water.GenerateSplineMesh();
            Water.ReCalculateBounds();
        }
Пример #9
0
        public PSplineSegment AddSegment(int startIndex, int endIndex)
        {
            PSplineSegment s = Segments.Find(s0 =>
                                             (s0.StartIndex == startIndex && s0.EndIndex == endIndex) ||
                                             (s0.StartIndex == endIndex && s0.EndIndex == startIndex));

            if (s != null)
            {
                return(s);
            }
            PSplineSegment newSegment = new PSplineSegment();

            newSegment.StartIndex = startIndex;
            newSegment.EndIndex   = endIndex;
            Segments.Add(newSegment);
            PSplineAnchor startAnchor = Anchors[newSegment.StartIndex];
            PSplineAnchor endAnchor   = Anchors[newSegment.EndIndex];
            Vector3       direction   = (endAnchor.Position - startAnchor.Position).normalized;
            float         length      = (endAnchor.Position - startAnchor.Position).magnitude / 3;

            newSegment.StartTangent = startAnchor.Position + direction * length;
            newSegment.EndTangent   = endAnchor.Position - direction * length;
            return(newSegment);
        }
Пример #10
0
        public void Create(PWater water, int segmentIndex)
        {
            this.water = water;

            List <Vector3> vertices  = new List <Vector3>();
            List <Vector4> uvs0      = new List <Vector4>();
            List <Vector4> uvs1      = new List <Vector4>();
            List <Color>   colors    = new List <Color>();
            List <int>     triangles = new List <int>();

            PSpline        spline = water.Spline;
            PSplineSegment s      = water.Spline.Segments[segmentIndex];

            Vector3    pos0, pos1;
            Quaternion rotation0, rotation1;
            Vector3    scale0, scale1;
            Matrix4x4  matrix0, matrix1;

            Vector4 bl, tl, tr, br;
            Vector4 v0, v1, v2, v3;
            Vector4 flow0, flow1;
            int     currentVertexCount;

            float halfWidth = water.SplineWidth * 0.5f;
            int   resY      = Mathf.RoundToInt(water.SplineResolutionY * s.ResolutionMultiplierY);

            resY = Mathf.Clamp(resY, 2, 100);
            if (resY % 2 == 1)
            {
                resY -= 1;
            }
            int   resX = water.SplineResolutionX;
            float xStep = 1.0f / resX;
            float yStep = 1.0f / resY;
            float x0, x1;
            float y0, y1;

            for (int yIndex = 0; yIndex < resY; ++yIndex)
            {
                y0        = yIndex * yStep;
                pos0      = spline.EvaluatePosition(segmentIndex, y0);
                rotation0 = spline.EvaluateRotation(segmentIndex, y0);
                scale0    = spline.EvaluateScale(segmentIndex, y0);
                matrix0   = Matrix4x4.TRS(pos0, rotation0, scale0);

                y1        = (yIndex + 1) * yStep;
                pos1      = spline.EvaluatePosition(segmentIndex, y1);
                rotation1 = spline.EvaluateRotation(segmentIndex, y1);
                scale1    = spline.EvaluateScale(segmentIndex, y1);
                matrix1   = Matrix4x4.TRS(pos1, rotation1, scale1);

                bl = matrix0.MultiplyPoint(new Vector3(-halfWidth, 0, 0));
                tl = matrix1.MultiplyPoint(new Vector3(-halfWidth, 0, 0));
                tr = matrix1.MultiplyPoint(new Vector3(halfWidth, 0, 0));
                br = matrix0.MultiplyPoint(new Vector3(halfWidth, 0, 0));

                for (int xIndex = 0; xIndex < resX; ++xIndex)
                {
                    x0 = xIndex * xStep;
                    x1 = (xIndex + 1) * xStep;

                    v0 = Vector4.Lerp(bl, br, x0);
                    v1 = Vector4.Lerp(tl, tr, x0);
                    v2 = Vector4.Lerp(tl, tr, x1);
                    v3 = Vector4.Lerp(bl, br, x1);

                    currentVertexCount = vertices.Count;
                    triangles.Add(currentVertexCount + 0);
                    triangles.Add(currentVertexCount + 1);
                    triangles.Add(currentVertexCount + 2);
                    triangles.Add(currentVertexCount + 3);
                    triangles.Add(currentVertexCount + 4);
                    triangles.Add(currentVertexCount + 5);

                    flow0 = matrix0.MultiplyVector(Vector3.forward * 2);
                    flow1 = matrix1.MultiplyVector(Vector3.forward * 2);

                    if ((xIndex + yIndex) % 2 == 0)
                    {
                        BakeData(vertices, uvs0, colors, uvs1, v0, v1, v2, flow0, flow1, flow1);
                        BakeData(vertices, uvs0, colors, uvs1, v1, v2, v0, flow1, flow1, flow0);
                        BakeData(vertices, uvs0, colors, uvs1, v2, v0, v1, flow1, flow0, flow1);

                        BakeData(vertices, uvs0, colors, uvs1, v2, v3, v0, flow1, flow0, flow0);
                        BakeData(vertices, uvs0, colors, uvs1, v3, v0, v2, flow0, flow0, flow1);
                        BakeData(vertices, uvs0, colors, uvs1, v0, v2, v3, flow0, flow1, flow0);
                    }
                    else
                    {
                        BakeData(vertices, uvs0, colors, uvs1, v0, v1, v3, flow0, flow1, flow0);
                        BakeData(vertices, uvs0, colors, uvs1, v1, v3, v0, flow1, flow0, flow0);
                        BakeData(vertices, uvs0, colors, uvs1, v3, v0, v1, flow0, flow0, flow1);

                        BakeData(vertices, uvs0, colors, uvs1, v2, v3, v1, flow1, flow0, flow1);
                        BakeData(vertices, uvs0, colors, uvs1, v3, v1, v2, flow0, flow1, flow1);
                        BakeData(vertices, uvs0, colors, uvs1, v1, v2, v3, flow1, flow1, flow0);
                    }
                }
            }

            Mesh m = s.Mesh;

            m.Clear();
            m.SetVertices(vertices);
            m.SetUVs(0, uvs0);
            m.SetUVs(1, uvs1);
            m.SetColors(colors);
            m.SetTriangles(triangles, 0);
            m.RecalculateBounds();
        }
Пример #11
0
        public int[] SmoothTangents(params int[] anchorIndices)
        {
            int[]     anchorRanks    = new int[Anchors.Count];
            Vector3[] directions     = new Vector3[Anchors.Count];
            float[]   segmentLengths = new float[Segments.Count];

            for (int i = 0; i < Segments.Count; ++i)
            {
                PSplineSegment s = Segments[i];
                anchorRanks[s.StartIndex] += 1;
                anchorRanks[s.EndIndex]   += 1;

                PSplineAnchor aStart = Anchors[s.StartIndex];
                PSplineAnchor aEnd   = Anchors[s.EndIndex];

                Vector3 startToEnd = aEnd.Position - aStart.Position;
                Vector3 d          = Vector3.Normalize(startToEnd);
                directions[s.StartIndex] += d;
                directions[s.EndIndex]   += d;

                segmentLengths[i] = startToEnd.magnitude;
            }

            for (int i = 0; i < directions.Length; ++i)
            {
                if (anchorRanks[i] == 0)
                {
                    continue;
                }
                directions[i] = Vector3.Normalize(directions[i] / anchorRanks[i]);
            }

            if (anchorIndices == null || anchorIndices.Length == 0)
            {
                anchorIndices = PUtilities.GetIndicesArray(Anchors.Count);
            }

            for (int i = 0; i < anchorIndices.Length; ++i)
            {
                int index = anchorIndices[i];
                if (anchorRanks[index] > 0)
                {
                    Quaternion rot = Quaternion.LookRotation(directions[index], Vector3.up);
                    Anchors[index].Rotation = rot;
                }
            }

            List <int> segmentIndices = new List <int>();

            for (int i = 0; i < Segments.Count; ++i)
            {
                PSplineSegment s = Segments[i];
                for (int j = 0; j < anchorIndices.Length; ++j)
                {
                    int anchorIndex = anchorIndices[j];
                    if (s.StartIndex == anchorIndex || s.EndIndex == anchorIndex)
                    {
                        segmentIndices.Add(i);
                    }
                }
            }

            for (int i = 0; i < segmentIndices.Count; ++i)
            {
                int            index  = segmentIndices[i];
                PSplineSegment s      = Segments[index];
                PSplineAnchor  aStart = Anchors[s.StartIndex];
                PSplineAnchor  aEnd   = Anchors[s.EndIndex];

                float   sLength       = segmentLengths[index];
                float   tangentLength = sLength * 0.33f;
                Vector3 dirStart      = directions[s.StartIndex];
                Vector3 dirEnd        = directions[s.EndIndex];
                s.StartTangent = aStart.Position + dirStart * tangentLength;
                s.EndTangent   = aEnd.Position - dirEnd * tangentLength;
            }
            return(segmentIndices.ToArray());
        }