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; }); }
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); }
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)); }
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)); }
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); }
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); }
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); }
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(); }
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); }
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(); }
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()); }