diff --git a/src/ExplorerBehaviour.cs b/src/ExplorerBehaviour.cs index fe555de..b9a8ea4 100644 --- a/src/ExplorerBehaviour.cs +++ b/src/ExplorerBehaviour.cs @@ -136,16 +136,12 @@ namespace UnityExplorer { public Vector3 position; public Quaternion rotation; - public Vector3 tangent; - public Vector3 normal; public float fov; - public CatmullRomPoint(Vector3 position, Quaternion rotation, Vector3 tangent, Vector3 normal, float fov) + public CatmullRomPoint(Vector3 position, Quaternion rotation, float fov) { this.position = position; this.rotation = rotation; - this.tangent = tangent; - this.normal = normal; this.fov = fov; } } @@ -197,7 +193,7 @@ namespace UnityExplorer this.controlPoints = controlPoints; this.closedLoop = closedLoop; - GenerateSplinePoints2(); + GenerateSplinePoints(); } //Updates control points @@ -210,7 +206,7 @@ namespace UnityExplorer this.controlPoints = controlPoints; - GenerateSplinePoints2(); + GenerateSplinePoints(); } //Updates closed loop values @@ -218,7 +214,7 @@ namespace UnityExplorer { this.closedLoop = closedLoop; - GenerateSplinePoints2(); + GenerateSplinePoints(); } //Draws a line between every point and the next. @@ -241,28 +237,6 @@ namespace UnityExplorer } } - public void DrawNormals(float extrusion, Color color) - { - if(ValidatePoints()) - { - for(int i = 0; i < splinePoints.Length; i++) - { - Debug.DrawLine(splinePoints[i].position, splinePoints[i].position + splinePoints[i].normal * extrusion, color); - } - } - } - - public void DrawTangents(float extrusion, Color color) - { - if(ValidatePoints()) - { - for(int i = 0; i < splinePoints.Length; i++) - { - Debug.DrawLine(splinePoints[i].position, splinePoints[i].position + splinePoints[i].tangent * extrusion, color); - } - } - } - //Validates if splinePoints have been set already. Throws nullref exception. private bool ValidatePoints() { @@ -298,200 +272,6 @@ namespace UnityExplorer splinePoints = new CatmullRomPoint[pointsToCreate]; } - //Math stuff to generate the spline points - private void GenerateSplinePoints() - { - InitializeProperties(); - - Vector3 p0, p1; //Start position, end position - Vector3 m0, m1; //Position Tangents - Vector4 r0, r1; //Start rotation, end rotation - Vector4 qm0, qm1; //Rotation Tangents - float fov0, fov1; - - for(int i = 0; i < controlPoints.Length; i++){ - if(i>0 && Dot(controlPoints[i - 1].rotation, controlPoints[i].rotation) < 0){ - Quaternion q = controlPoints[i].rotation; - controlPoints[i].rotation = new Quaternion(- q.x, - q.y, - q.z, - q.w); - ExplorerCore.Log($"cambio orientacion n° {i}"); - } - } - - // First for loop goes through each individual control point and connects it to the next, so 0-1, 1-2, 2-3 and so on - int closedAdjustment = closedLoop ? 0 : 1; - int totalframes = 0;//count the total number of frames so we can save the points in the right splinePoints position - - for (int currentPoint = 0; currentPoint < controlPoints.Length - closedAdjustment; currentPoint++) - { - bool closedLoopFinalPoint = (closedLoop && currentPoint == controlPoints.Length - 1); - - p0 = controlPoints[currentPoint].position; - r0 = QuaternionToVector4(controlPoints[currentPoint].rotation); - fov0 = controlPoints[currentPoint].fov; - - if(closedLoopFinalPoint) - { - p1 = controlPoints[0].position; - r1 = QuaternionToVector4(controlPoints[0].rotation); - - //Check if we are using the shortest path on the rotation. If not, change r1 to represent that shortest path. - if (Vector4.Dot(r0, r1) < 0) - r1 = - r1; - - fov1 = controlPoints[0].fov; - } - else - { - p1 = controlPoints[currentPoint + 1].position; - r1 = QuaternionToVector4(controlPoints[currentPoint + 1].rotation); - fov1 = controlPoints[currentPoint + 1].fov; - } - - // m0, qm0 - if (currentPoint == 0) // Tangent M[k] = (P[k+1] - P[k-1]) / 2 - { - if(closedLoop) - { - m0 = p1 - controlPoints[controlPoints.Length - 1].position; - qm0 = r1 - QuaternionToVector4(controlPoints[controlPoints.Length - 1].rotation); - } - else - { - m0 = p1 - p0; - qm0 = r1 - r0; - } - } - else - { - m0 = p1 - controlPoints[currentPoint - 1].position; - qm0 = r1 - QuaternionToVector4(controlPoints[currentPoint - 1].rotation); - } - - // m1, qm1 - if (closedLoop) - { - if (currentPoint == controlPoints.Length - 1) //Last point case - { - m1 = controlPoints[(currentPoint + 2) % controlPoints.Length].position - p0; - qm1 = QuaternionToVector4(controlPoints[(currentPoint + 2) % controlPoints.Length].rotation) - r0; - } - else if (currentPoint == 0) //First point case - { - m1 = controlPoints[currentPoint + 2].position - p0; - qm1 = QuaternionToVector4(controlPoints[currentPoint + 2].rotation) - r0; - } - else - { - m1 = controlPoints[(currentPoint + 2) % controlPoints.Length].position - p0; - qm1 = QuaternionToVector4(controlPoints[(currentPoint + 2) % controlPoints.Length].rotation) - r0; - } - } - else - { - if (currentPoint < controlPoints.Length - 2) - { - m1 = controlPoints[(currentPoint + 2) % controlPoints.Length].position - p0; - qm1 = QuaternionToVector4(controlPoints[(currentPoint + 2) % controlPoints.Length].rotation) - r0; - } - else - { - m1 = p1 - p0; - qm1 = r1 - r0; - } - } - - m0 *= 0.5f; //Doing this here instead of in every single above statement - m1 *= 0.5f; - qm0 *= 0.5f; - qm1 *= 0.5f; - - int frames = controlPoints[currentPoint].frames; //resolution and time the node takes to get to the other node - float pointStep = 1.0f / frames; - - if ((currentPoint == controlPoints.Length - 2 && !closedLoop) || closedLoopFinalPoint) //Final point - { - pointStep = 1.0f / (frames - 1); // last point of last segment should reach p1 - } - - // Creates [frames] points between this control point and the next - for (int tesselatedPoint = 0; tesselatedPoint < frames; tesselatedPoint++) - { - float t = tesselatedPoint * pointStep; - - CatmullRomPoint point = Evaluate(p0, p1, m0, m1, r0, r1, qm0, qm1, fov0, fov1, t); - - splinePoints[totalframes + tesselatedPoint] = point; - } - totalframes+=frames; - } - } - - //Old games dont have a definition for a dot product between quaternions. - static float Dot(Quaternion a, Quaternion b) - { - return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; - } - - static Vector4 QuaternionToVector4(Quaternion q){ - return new Vector4(q.x, q.y, q.z, q.w); - } - - //Evaluates curve at t[0, 1]. Returns point/rotation/normal/tan struct. [0, 1] means clamped between 0 and 1. - public static CatmullRomPoint Evaluate(Vector3 posStart, Vector3 posEnd, Vector3 tanPoint1, Vector3 tanPoint2, Vector4 rotStart, Vector4 rotEnd, Vector4 tanRot1, Vector4 tanRot2, float fovStart, float fovEnd, float t) - { - Vector3 position = CalculatePosition(posStart, posEnd, tanPoint1, tanPoint2, t); - Quaternion rotation = CalculateRotation(rotStart, rotEnd, tanRot1, tanRot2, t); - Vector3 tangent = CalculateTangent(posStart, posEnd, tanPoint1, tanPoint2, t); - Vector3 normal = NormalFromTangent(tangent); - float fov = Mathf.SmoothStep(fovStart, fovEnd, t); - - return new CatmullRomPoint(position, rotation, tangent, normal, fov); - } - - //Calculates curve position at t[0, 1] - public static Vector3 CalculatePosition(Vector3 start, Vector3 end, Vector3 tanPoint1, Vector3 tanPoint2, float t) - { - // Hermite curve formula: - // (2t^3 - 3t^2 + 1) * p0 + (t^3 - 2t^2 + t) * m0 + (-2t^3 + 3t^2) * p1 + (t^3 - t^2) * m1 - Vector3 position = (2.0f * t * t * t - 3.0f * t * t + 1.0f) * start - + (t * t * t - 2.0f * t * t + t) * tanPoint1 - + (-2.0f * t * t * t + 3.0f * t * t) * end - + (t * t * t - t * t) * tanPoint2; - - return position; - } - - public static Quaternion CalculateRotation(Vector4 start, Vector4 end, Vector4 tanPoint1, Vector4 tanPoint2, float t) - { - // Hermite curve formula: - // (2t^3 - 3t^2 + 1) * p0 + (t^3 - 2t^2 + t) * m0 + (-2t^3 + 3t^2) * p1 + (t^3 - t^2) * m1 - Vector4 rotation = (2.0f * t * t * t - 3.0f * t * t + 1.0f) * start - + (t * t * t - 2.0f * t * t + t) * tanPoint1 - + (-2.0f * t * t * t + 3.0f * t * t) * end - + (t * t * t - t * t) * tanPoint2; - - return new Quaternion(rotation.x, rotation.y, rotation.z, rotation.w); - } - - //Calculates tangent at t[0, 1] - public static Vector3 CalculateTangent(Vector3 start, Vector3 end, Vector3 tanPoint1, Vector3 tanPoint2, float t) - { - // Calculate tangents - // p'(t) = (6t² - 6t)p0 + (3t² - 4t + 1)m0 + (-6t² + 6t)p1 + (3t² - 2t)m1 - Vector3 tangent = (6 * t * t - 6 * t) * start - + (3 * t * t - 4 * t + 1) * tanPoint1 - + (-6 * t * t + 6 * t) * end - + (3 * t * t - 2 * t) * tanPoint2; - - return tangent.normalized; - } - - //Calculates normal vector from tangent - public static Vector3 NormalFromTangent(Vector3 tangent) - { - return Vector3.Cross(tangent, Vector3.up).normalized / 2; - } - public void MaybeRunPath(){ if(playingPath){ if(ExplorerCore.CameraPathsManager != null && currentPoint < splinePoints.Length){ @@ -528,6 +308,175 @@ namespace UnityExplorer playingPath = true; } + private void GenerateSplinePoints() + { + InitializeProperties(); + + Vector3 p0, p1, p2, p3; //Previous position, Start position, end position, Next position + Vector4 r0, r1, r2, r3; //Previous rotation, Start rotation, end rotation, Next rotation + float fov0, fov1; + + //Fix rotation + /* + for(int i = 0; i < controlPoints.Length; i++){ + if(i>0 && Dot(controlPoints[i - 1].rotation, controlPoints[i].rotation) < 0){ + Quaternion q = controlPoints[i].rotation; + controlPoints[i].rotation = new Quaternion(- q.x, - q.y, - q.z, - q.w); + ExplorerCore.Log($"cambio orientacion n° {i}"); + } + } + */ + + // First for loop goes through each individual control point and connects it to the next, so 0-1, 1-2, 2-3 and so on + int closedAdjustment = closedLoop ? 0 : 1; + int totalframes = 0;//count the total number of frames so we can save the points in the right splinePoints position + + for (int currentPoint = 0; currentPoint < controlPoints.Length - closedAdjustment; currentPoint++) + { + bool closedLoopFinalPoint = (closedLoop && currentPoint == controlPoints.Length - 1); + + //Had tu add "controlPoints.Length" because C# mod doesnt work well with negative values + int previousPoint = closedLoop ? (currentPoint + controlPoints.Length - 1)%(controlPoints.Length) : System.Math.Max(currentPoint - 1, 0); + int endSegmentPoint = closedLoop ? (currentPoint + 1)%(controlPoints.Length) : System.Math.Min(currentPoint + 1, controlPoints.Length - 1); + int nextPoint = closedLoop ? (currentPoint + 2)%(controlPoints.Length) : System.Math.Min(currentPoint + 2, controlPoints.Length - 1); + + p0 = controlPoints[previousPoint].position; + r0 = QuaternionToVector4(controlPoints[previousPoint].rotation); + + p1 = controlPoints[currentPoint].position; + r1 = QuaternionToVector4(controlPoints[currentPoint].rotation); + + p2 = controlPoints[endSegmentPoint].position; + r2 = QuaternionToVector4(controlPoints[endSegmentPoint].rotation); + + p3 = controlPoints[nextPoint].position; + r3 = QuaternionToVector4(controlPoints[nextPoint].rotation); + + //Check if we are using the shortest path on the rotation. If not, change r1 to represent that shortest path. + if (Vector4.Dot(r0, r1) < 0) + r1 = - r1; + + if (Vector4.Dot(r1, r2) < 0) + r2 = - r2; + + if (Vector4.Dot(r2, r3) < 0) + r3 = - r3; + + fov0 = controlPoints[currentPoint].fov; + fov1 = controlPoints[endSegmentPoint].fov; + + int frames = controlPoints[currentPoint].frames; //resolution and time the node takes to get to the other node + float pointStep = 1.0f / frames; + + if ((currentPoint == controlPoints.Length - 2 && !closedLoop) || closedLoopFinalPoint) //Final point + { + pointStep = 1.0f / (frames - 1); // last point of last segment should reach p1 + } + + // Creates [frames] points between this control point and the next + for (int tesselatedPoint = 0; tesselatedPoint < frames; tesselatedPoint++) + { + float t = tesselatedPoint * pointStep; + + CatmullRomPoint point = Evaluate(p0, p1, p2, p3, r0, r1, r2, r3, fov0, fov1, t); + + splinePoints[totalframes + tesselatedPoint] = point; + } + totalframes+=frames; + } + } + + static CatmullRomPoint Evaluate(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, Vector4 r0, Vector4 r1, Vector4 r2, Vector4 r3, float fovStart, float fovEnd, float t) + { + Vector3 position = CatmullRomInterpolation(p0, p1, p2, p3, t); + Vector4 v4rot = CatmullRomInterpolation(r0, r1, r2, r3, t); + Quaternion rotation = new Quaternion(v4rot.x, v4rot.y, v4rot.z, v4rot.w); + float fov = Mathf.SmoothStep(fovStart, fovEnd, t); + + return new CatmullRomPoint(position, rotation, fov); + } + + //Implementation from: https://qroph.github.io/2018/07/30/smooth-paths-using-catmull-rom-splines.html + static Vector3 CatmullRomInterpolation(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t){ + float tension = 0; + float alpha = 0.5f; + + float t01 = (float) System.Math.Pow((double) Vector3.Distance(p0, p1), (double) alpha); + float t12 = (float) System.Math.Pow((double) Vector3.Distance(p1, p2), (double) alpha); + float t23 = (float) System.Math.Pow((double) Vector3.Distance(p2, p3), (double) alpha); + + Vector3 v1 = t01 != 0 ? (p1 - p0) / t01 : new Vector3(0, 0, 0); + Vector3 v2 = t23 != 0 ? (p3 - p2) / t23 : new Vector3(0, 0, 0); + + Vector3 m1 = (1.0f - tension) * (p2 - p1 + t12 * (v1 - (p2 -p0) / (t01 + t12))); + Vector3 m2 = (1.0f - tension) * (p2 - p1 + t12 * (v2 - (p3 -p1) / (t12 + t23))); + + Vector3 a = 2.0f * (p1 - p2) + m1 + m2; + Vector3 b = -3.0f * (p1 - p2) - m1 - m1 - m2; + Vector3 c = m1; + Vector3 d = p1; + + return a * t * t * t + b * t * t + c * t + d; + } + + static Vector4 CatmullRomInterpolation(Vector4 r0, Vector4 r1, Vector4 r2, Vector4 r3, float t){ + float tension = 0; + float alpha = 0.5f; + + float t01 = (float) System.Math.Pow((double) Vector4.Distance(r0, r1), (double) alpha); + float t12 = (float) System.Math.Pow((double) Vector4.Distance(r1, r2), (double) alpha); + float t23 = (float) System.Math.Pow((double) Vector4.Distance(r2, r3), (double) alpha); + + Vector4 v1 = t01 != 0 ? (r1 - r0) / t01 : new Vector4(0, 0, 0, 0); + Vector4 v2 = t23 != 0 ? (r3 - r2) / t23 : new Vector4(0, 0, 0, 0); + + Vector4 m1 = (1.0f - tension) * (r2 - r1 + t12 * (v1 - (r2 -r0) / (t01 + t12))); + Vector4 m2 = (1.0f - tension) * (r2 - r1 + t12 * (v2 - (r3 -r1) / (t12 + t23))); + + Vector4 a = 2.0f * (r1 - r2) + m1 + m2; + Vector4 b = -3.0f * (r1 - r2) - m1 - m1 - m2; + Vector4 c = m1; + Vector4 d = r1; + + return a * t * t * t + b * t * t + c * t + d; + //return Vector4.Lerp(r1, r2, t); + } + + static Vector3 CatmullRomAlt(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t) + { + float t2 = t * t; + float t3 = t2 * t; + + Vector3 v0 = (p2 - p0) * 0.5f; + Vector3 v1 = (p3 - p1) * 0.5f; + + float h1 = 2 * t3 - 3 * t2 + 1; + float h2 = -2 * t3 + 3 * t2; + float h3 = t3 - 2 * t2 + t; + float h4 = t3 - t2; + + Vector3 interpolatedPoint = h1 * p1 + h2 * p2 + h3 * v0 + h4 * v1; + return interpolatedPoint; + } + + static Vector4 CatmullRomAlt(Vector4 p0, Vector4 p1, Vector4 p2, Vector4 p3, float t) + { + float t2 = t * t; + float t3 = t2 * t; + + Vector4 v0 = (p2 - p0) * 0.5f; + Vector4 v1 = (p3 - p1) * 0.5f; + + float h1 = 2 * t3 - 3 * t2 + 1; + float h2 = -2 * t3 + 3 * t2; + float h3 = t3 - 2 * t2 + t; + float h4 = t3 - t2; + + Vector4 interpolatedPoint = h1 * p1 + h2 * p2 + h3 * v0 + h4 * v1; + return interpolatedPoint; + } + + //Used for calculating path length for constant speed paths public float[] GenerateSplinePointsByRes(int resolution = 3000) //resolution of each segment { List splineSegmentDistances = new List(); @@ -630,170 +579,21 @@ namespace UnityExplorer return splineSegmentDistances.ToArray(); } - private void GenerateSplinePoints2() + //Calculates curve position at t[0, 1] + public static Vector3 CalculatePosition(Vector3 start, Vector3 end, Vector3 tanPoint1, Vector3 tanPoint2, float t) { - InitializeProperties(); + // Hermite curve formula: + // (2t^3 - 3t^2 + 1) * p0 + (t^3 - 2t^2 + t) * m0 + (-2t^3 + 3t^2) * p1 + (t^3 - t^2) * m1 + Vector3 position = (2.0f * t * t * t - 3.0f * t * t + 1.0f) * start + + (t * t * t - 2.0f * t * t + t) * tanPoint1 + + (-2.0f * t * t * t + 3.0f * t * t) * end + + (t * t * t - t * t) * tanPoint2; - Vector3 p0, p1, p2, p3; //Previous position, Start position, end position, Next position - Vector4 r0, r1, r2, r3; //Previous rotation, Start rotation, end rotation, Next rotation - float fov0, fov1; - - //Fix rotation - for(int i = 0; i < controlPoints.Length; i++){ - if(i>0 && Dot(controlPoints[i - 1].rotation, controlPoints[i].rotation) < 0){ - Quaternion q = controlPoints[i].rotation; - controlPoints[i].rotation = new Quaternion(- q.x, - q.y, - q.z, - q.w); - ExplorerCore.Log($"cambio orientacion n° {i}"); - } - } - - // First for loop goes through each individual control point and connects it to the next, so 0-1, 1-2, 2-3 and so on - int closedAdjustment = closedLoop ? 0 : 1; - int totalframes = 0;//count the total number of frames so we can save the points in the right splinePoints position - - for (int currentPoint = 0; currentPoint < controlPoints.Length - closedAdjustment; currentPoint++) - { - bool closedLoopFinalPoint = (closedLoop && currentPoint == controlPoints.Length - 1); - - //Had tu add "controlPoints.Length" because C# mod doesnt work well with negative values - int previousPoint = closedLoop ? (currentPoint + controlPoints.Length - 1)%(controlPoints.Length) : System.Math.Max(currentPoint - 1, 0); - int endSegmentPoint = closedLoop ? (currentPoint + 1)%(controlPoints.Length) : System.Math.Min(currentPoint + 1, controlPoints.Length - 1); - int nextPoint = closedLoop ? (currentPoint + 2)%(controlPoints.Length) : System.Math.Min(currentPoint + 2, controlPoints.Length - 1); - - p0 = controlPoints[previousPoint].position; - r0 = QuaternionToVector4(controlPoints[previousPoint].rotation); - - p1 = controlPoints[currentPoint].position; - r1 = QuaternionToVector4(controlPoints[currentPoint].rotation); - - p2 = controlPoints[endSegmentPoint].position; - r2 = QuaternionToVector4(controlPoints[endSegmentPoint].rotation); - - p3 = controlPoints[nextPoint].position; - r3 = QuaternionToVector4(controlPoints[nextPoint].rotation); - - //Check if we are using the shortest path on the rotation. If not, change r1 to represent that shortest path. - if (Vector4.Dot(r0, r1) < 0) - r1 = - r1; - - if (Vector4.Dot(r1, r2) < 0) - r2 = - r2; - - if (Vector4.Dot(r2, r3) < 0) - r3 = - r3; - - fov0 = controlPoints[currentPoint].fov; - fov1 = controlPoints[endSegmentPoint].fov; - - int frames = controlPoints[currentPoint].frames; //resolution and time the node takes to get to the other node - float pointStep = 1.0f / frames; - - if ((currentPoint == controlPoints.Length - 2 && !closedLoop) || closedLoopFinalPoint) //Final point - { - pointStep = 1.0f / (frames - 1); // last point of last segment should reach p1 - } - - // Creates [frames] points between this control point and the next - for (int tesselatedPoint = 0; tesselatedPoint < frames; tesselatedPoint++) - { - float t = tesselatedPoint * pointStep; - - CatmullRomPoint point = Evaluate2(p0, p1, p2, p3, r0, r1, r2, r3, fov0, fov1, t); - - splinePoints[totalframes + tesselatedPoint] = point; - } - totalframes+=frames; - } + return position; } - static Vector3 CatmullRomInterpolate(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t) - { - float t2 = t * t; - float t3 = t2 * t; - - Vector3 v0 = (p2 - p0) * 0.5f; - Vector3 v1 = (p3 - p1) * 0.5f; - - float h1 = 2 * t3 - 3 * t2 + 1; - float h2 = -2 * t3 + 3 * t2; - float h3 = t3 - 2 * t2 + t; - float h4 = t3 - t2; - - Vector3 interpolatedPoint = h1 * p1 + h2 * p2 + h3 * v0 + h4 * v1; - return interpolatedPoint; - } - - static Vector4 CatmullRomInterpolate(Vector4 p0, Vector4 p1, Vector4 p2, Vector4 p3, float t) - { - float t2 = t * t; - float t3 = t2 * t; - - Vector4 v0 = (p2 - p0) * 0.5f; - Vector4 v1 = (p3 - p1) * 0.5f; - - float h1 = 2 * t3 - 3 * t2 + 1; - float h2 = -2 * t3 + 3 * t2; - float h3 = t3 - 2 * t2 + t; - float h4 = t3 - t2; - - Vector4 interpolatedPoint = h1 * p1 + h2 * p2 + h3 * v0 + h4 * v1; - return interpolatedPoint; - } - - //Implementation from: https://qroph.github.io/2018/07/30/smooth-paths-using-catmull-rom-splines.html - static Vector3 CatmullRom2(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t){ - float tension = 0; - float alpha = 0.5f; - - float t01 = (float) System.Math.Pow((double) Vector3.Distance(p0, p1), (double) alpha); - float t12 = (float) System.Math.Pow((double) Vector3.Distance(p1, p2), (double) alpha); - float t23 = (float) System.Math.Pow((double) Vector3.Distance(p2, p3), (double) alpha); - - Vector3 v1 = t01 != 0 ? (p1 - p0) / t01 : new Vector3(0, 0, 0); - Vector3 v2 = t23 != 0 ? (p3 - p2) / t23 : new Vector3(0, 0, 0); - - Vector3 m1 = (1.0f - tension) * (p2 - p1 + t12 * (v1 - (p2 -p0) / (t01 + t12))); - Vector3 m2 = (1.0f - tension) * (p2 - p1 + t12 * (v2 - (p3 -p1) / (t12 + t23))); - - Vector3 a = 2.0f * (p1 - p2) + m1 + m2; - Vector3 b = -3.0f * (p1 - p2) - m1 - m1 - m2; - Vector3 c = m1; - Vector3 d = p1; - - return a * t * t * t + b * t * t + c * t + d; - } - - static Vector4 CatmullRom2(Vector4 r0, Vector4 r1, Vector4 r2, Vector4 r3, float t){ - float tension = 0; - float alpha = 0.5f; - - float t01 = (float) System.Math.Pow((double) Vector4.Distance(r0, r1), (double) alpha); - float t12 = (float) System.Math.Pow((double) Vector4.Distance(r1, r2), (double) alpha); - float t23 = (float) System.Math.Pow((double) Vector4.Distance(r2, r3), (double) alpha); - - Vector4 v1 = t01 != 0 ? (r1 - r0) / t01 : new Vector4(0, 0, 0, 0); - Vector4 v2 = t23 != 0 ? (r3 - r2) / t23 : new Vector4(0, 0, 0, 0); - - Vector4 m1 = (1.0f - tension) * (r2 - r1 + t12 * (v1 - (r2 -r0) / (t01 + t12))); - Vector4 m2 = (1.0f - tension) * (r2 - r1 + t12 * (v2 - (r3 -r1) / (t12 + t23))); - - Vector4 a = 2.0f * (r1 - r2) + m1 + m2; - Vector4 b = -3.0f * (r1 - r2) - m1 - m1 - m2; - Vector4 c = m1; - Vector4 d = r1; - - return a * t * t * t + b * t * t + c * t + d; - //return Vector4.Lerp(r1, r2, t); - } - - static CatmullRomPoint Evaluate2(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, Vector4 r0, Vector4 r1, Vector4 r2, Vector4 r3, float fovStart, float fovEnd, float t) - { - Vector3 position = CatmullRom2(p0, p1, p2, p3, t); - Vector4 v4rot = CatmullRom2(r0, r1, r2, r3, t); - Quaternion rotation = new Quaternion(v4rot.x, v4rot.y, v4rot.z, v4rot.w); - float fov = Mathf.SmoothStep(fovStart, fovEnd, t); - - return new CatmullRomPoint(position, rotation, new Vector3(0,0,0), new Vector3(0,0,0), fov); + static Vector4 QuaternionToVector4(Quaternion q){ + return new Vector4(q.x, q.y, q.z, q.w); } } } diff --git a/src/UI/Panels/CamPaths.cs b/src/UI/Panels/CamPaths.cs index 6592f8f..87b53aa 100644 --- a/src/UI/Panels/CamPaths.cs +++ b/src/UI/Panels/CamPaths.cs @@ -79,7 +79,7 @@ namespace UnityExplorer.UI.Panels toggleConstantSpeedText.text = "Constant speed"; InputFieldRef CompletePathFramesInput = null; - AddInputField("Frames", "Complete path duration (in frames):", "Default: 2000", out CompletePathFramesInput, TotalFrames_OnEndEdit, false); + AddInputField("Frames", "Constant speed complete path duration (in frames):", "Default: 2000", out CompletePathFramesInput, TotalFrames_OnEndEdit, false); CompletePathFramesInput.Text = pathTotalFrames.ToString(); } @@ -103,13 +103,13 @@ namespace UnityExplorer.UI.Panels UINodes.Add(horiGroup); //Move to Camera - ButtonRef moveToCameraButton = UIFactory.CreateButton(horiGroup, "Move Node to Camera", "Move Node to Camera"); + ButtonRef moveToCameraButton = UIFactory.CreateButton(horiGroup, "Copy Camera pos and rot", "Copy Camera pos and rot"); UIFactory.SetLayoutElement(moveToCameraButton.GameObject, minWidth: 100, minHeight: 25, flexibleWidth: 9999); - moveToCameraButton.OnClick += () => {point.position = FreeCamPanel.ourCamera.transform.position; point.rotation = FreeCamPanel.ourCamera.transform.rotation;}; + moveToCameraButton.OnClick += () => {point.position = FreeCamPanel.ourCamera.transform.position; point.rotation = FreeCamPanel.ourCamera.transform.rotation; controlPoints[index] = point;}; ButtonRef copyFovButton = UIFactory.CreateButton(horiGroup, "Copy Camera FoV", "Copy Camera FoV"); UIFactory.SetLayoutElement(copyFovButton.GameObject, minWidth: 100, minHeight: 25, flexibleWidth: 9999); - copyFovButton.OnClick += () => {point.fov = FreeCamPanel.ourCamera.fieldOfView;}; + copyFovButton.OnClick += () => {point.fov = FreeCamPanel.ourCamera.fieldOfView; controlPoints[index] = point;}; ButtonRef moveToPointButton = UIFactory.CreateButton(horiGroup, "Move Cam to Node", "Move Cam to Node"); UIFactory.SetLayoutElement(moveToPointButton.GameObject, minWidth: 100, minHeight: 25, flexibleWidth: 9999); @@ -213,21 +213,13 @@ namespace UnityExplorer.UI.Panels void UpdateNodeFramesConstantspeed(){ float[] d = ExplorerCore.CameraPathsManager.GenerateSplinePointsByRes(3000); - - ExplorerCore.Log($"d.Length: {d.Length}"); - float dTotal = d.Sum(); - - ExplorerCore.Log($"dTotal: {dTotal}"); - int closedAdjustment = closedLoop ? 0 : 1; + for(int i = 0; i < controlPoints.Count - closedAdjustment; i++) { CatmullRom.PathControlPoint point = controlPoints[i]; point.frames = (int)(pathTotalFrames *(d[i] / dTotal)); controlPoints[i] = point; - - ExplorerCore.Log($"d[{i}]: {d[i]}"); - ExplorerCore.Log(controlPoints[i].frames); } ExplorerCore.CameraPathsManager.Update(controlPoints.ToArray());