mirror of
https://github.com/originalnicodr/CinematicUnityExplorer.git
synced 2026-10-10 13:03:15 +08:00
Added custom frame amount for each node.
This commit is contained in:
+178
-88
@@ -154,16 +154,17 @@ namespace UnityExplorer
|
||||
public Vector3 position;
|
||||
public Quaternion rotation;
|
||||
public float fov;
|
||||
public int frames;
|
||||
|
||||
public PathControlPoint(Vector3 position, Quaternion rotation, float fov)
|
||||
public PathControlPoint(Vector3 position, Quaternion rotation, float fov, int frames = 500)
|
||||
{
|
||||
this.position = position;
|
||||
this.rotation = rotation;
|
||||
this.fov = fov;
|
||||
this.frames = frames;
|
||||
}
|
||||
}
|
||||
|
||||
private int resolution; //Amount of points between control points. [Tesselation factor]
|
||||
private bool closedLoop;
|
||||
|
||||
private CatmullRomPoint[] splinePoints; //Generated spline points
|
||||
@@ -172,7 +173,7 @@ namespace UnityExplorer
|
||||
public bool playingPath;
|
||||
int currentPoint = 0;
|
||||
|
||||
//Returns spline points. Count is contorolPoints * resolution + [resolution] points if closed loop.
|
||||
//Returns spline points. Count is the summation of all the node frames (it excludes the last node frames if path isn't a closed loop).
|
||||
public CatmullRomPoint[] GetPoints()
|
||||
{
|
||||
if(splinePoints == null)
|
||||
@@ -183,16 +184,15 @@ namespace UnityExplorer
|
||||
return splinePoints;
|
||||
}
|
||||
|
||||
public CatmullRom(PathControlPoint[] controlPoints, int resolution, bool closedLoop)
|
||||
public CatmullRom(PathControlPoint[] controlPoints, bool closedLoop)
|
||||
{
|
||||
if(controlPoints == null || controlPoints.Length <= 2 || resolution < 2)
|
||||
if(controlPoints == null || controlPoints.Length <= 2)
|
||||
{
|
||||
ExplorerCore.Log(controlPoints);
|
||||
throw new ArgumentException("Catmull Rom Error: Too few control points or resolution too small");
|
||||
throw new ArgumentException("Catmull Rom Error: Too few control points!");
|
||||
}
|
||||
|
||||
this.controlPoints = controlPoints;
|
||||
this.resolution = resolution;
|
||||
this.closedLoop = closedLoop;
|
||||
|
||||
GenerateSplinePoints();
|
||||
@@ -211,14 +211,9 @@ namespace UnityExplorer
|
||||
GenerateSplinePoints();
|
||||
}
|
||||
|
||||
//Updates resolution and closed loop values
|
||||
public void Update(int resolution, bool closedLoop)
|
||||
//Updates closed loop values
|
||||
public void Update(bool closedLoop)
|
||||
{
|
||||
if(resolution < 2)
|
||||
{
|
||||
throw new ArgumentException("Invalid Resolution. Make sure it's >= 1");
|
||||
}
|
||||
this.resolution = resolution;
|
||||
this.closedLoop = closedLoop;
|
||||
|
||||
GenerateSplinePoints();
|
||||
@@ -229,22 +224,15 @@ namespace UnityExplorer
|
||||
{
|
||||
if(ValidatePoints())
|
||||
{
|
||||
//LineRenderer lineRenderer = new GameObject().GetComponent<LineRenderer>();
|
||||
|
||||
for(int i = 0; i < splinePoints.Length; i++)
|
||||
{
|
||||
if(i == splinePoints.Length - 1 && closedLoop)
|
||||
{
|
||||
//lineRenderer.SetPosition(i, splinePoints[0].position);
|
||||
//lineRenderer.SetPosition(i + 1, splinePoints[i].position);
|
||||
|
||||
Debug.DrawLine(splinePoints[i].position, splinePoints[0].position, color);
|
||||
}
|
||||
else if(i < splinePoints.Length - 1)
|
||||
{
|
||||
//lineRenderer.SetPosition(i, splinePoints[i].position);
|
||||
//lineRenderer.SetPosition(i + 1, splinePoints[i + 1].position);
|
||||
|
||||
Debug.DrawLine(splinePoints[i].position, splinePoints[i+1].position, color);
|
||||
}
|
||||
}
|
||||
@@ -283,20 +271,29 @@ namespace UnityExplorer
|
||||
return splinePoints != null;
|
||||
}
|
||||
|
||||
//Sets the length of the point array based on resolution/closed loop.
|
||||
//Sets the length of the point array based on total amount of frames.
|
||||
private void InitializeProperties()
|
||||
{
|
||||
int pointsToCreate;
|
||||
int pointsToCreate = 0;
|
||||
if (closedLoop)
|
||||
{
|
||||
pointsToCreate = resolution * controlPoints.Length; //Loops back to the beggining, so no need to adjust for arrays starting at 0
|
||||
for (var i = 0; i < controlPoints.Length; i++)
|
||||
{
|
||||
pointsToCreate += controlPoints[i].frames;//Loops back to the beggining, so no need to adjust for arrays starting at 0
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pointsToCreate = resolution * (controlPoints.Length - 1);
|
||||
for (var i = 0; i < controlPoints.Length - 1; i++)
|
||||
{
|
||||
pointsToCreate += controlPoints[i].frames;
|
||||
}
|
||||
}
|
||||
|
||||
splinePoints = new CatmullRomPoint[pointsToCreate];
|
||||
//if(splinePoints != null)
|
||||
// Array.Clear(splinePoints, 0, splinePoints.Length);
|
||||
|
||||
splinePoints = new CatmullRomPoint[pointsToCreate];
|
||||
}
|
||||
|
||||
//Math stuff to generate the spline points
|
||||
@@ -311,6 +308,15 @@ namespace UnityExplorer
|
||||
|
||||
// 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;
|
||||
|
||||
/*
|
||||
Quaternion[] rotationArray = new Quaternion[controlPoints.Length];
|
||||
for(int i = 0; i < controlPoints.Length - closedAdjustment; i++)
|
||||
rotationArray[i] = controlPoints[i].rotation;
|
||||
*/
|
||||
|
||||
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);
|
||||
@@ -380,22 +386,24 @@ namespace UnityExplorer
|
||||
m0 *= 0.5f; //Doing this here instead of in every single above statement
|
||||
m1 *= 0.5f;
|
||||
|
||||
float pointStep = 1.0f / resolution;
|
||||
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 / (resolution - 1); // last point of last segment should reach p1
|
||||
pointStep = 1.0f / (frames - 1); // last point of last segment should reach p1
|
||||
}
|
||||
|
||||
// Creates [resolution] points between this control point and the next
|
||||
for (int tesselatedPoint = 0; tesselatedPoint < resolution; tesselatedPoint++)
|
||||
// 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, r0, r1, m0, m1, fov0, fov1, t);
|
||||
|
||||
splinePoints[currentPoint * resolution + tesselatedPoint] = point;
|
||||
splinePoints[totalframes + tesselatedPoint] = point;
|
||||
}
|
||||
totalframes+=frames;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,13 +453,14 @@ namespace UnityExplorer
|
||||
|
||||
public void MaybeRunPath(){
|
||||
if(playingPath){
|
||||
if(ExplorerCore.CameraPathsManager != null && currentPoint < ExplorerCore.CameraPathsManager.GetPoints().Length){
|
||||
CatmullRomPoint point = ExplorerCore.CameraPathsManager.GetPoints()[currentPoint];
|
||||
if(ExplorerCore.CameraPathsManager != null && currentPoint < splinePoints.Length){
|
||||
CatmullRomPoint point = splinePoints[currentPoint];
|
||||
|
||||
FreeCamPanel.ourCamera.transform.position = point.position;
|
||||
FreeCamPanel.ourCamera.transform.rotation = point.rotation;
|
||||
FreeCamPanel.ourCamera.fieldOfView = point.fov;
|
||||
currentPoint++;
|
||||
if(currentPoint >= ExplorerCore.CameraPathsManager.GetPoints().Length)
|
||||
if(currentPoint >= splinePoints.Length)
|
||||
playingPath = false;
|
||||
}
|
||||
}
|
||||
@@ -477,73 +486,154 @@ namespace UnityExplorer
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
public struct LineDrawer
|
||||
{
|
||||
private LineRenderer lineRenderer;
|
||||
private float lineSize;
|
||||
|
||||
public LineDrawer(float lineSize = 0.2f)
|
||||
//SQUAD
|
||||
//Ported by CodeKiwi
|
||||
//https://forum.unity.com/threads/need-help-implementing-quaternion-squad.273931/#post-4447033
|
||||
public class Squad {
|
||||
// Returns a smoothed quaternion along the set of quaternions making up the spline, each quaternion is along an equidistant value in t
|
||||
public static Quaternion Spline(Quaternion[] quaternions , float t )
|
||||
{
|
||||
//GameObject lineObj = new GameObject("LineObj");
|
||||
//lineRenderer = lineObj.AddComponent<UnityEngine.LineRenderer>();
|
||||
var section = (int)((quaternions.Length - 1) * t);
|
||||
|
||||
//Particles/Additive
|
||||
//lineRenderer.material = new Material(Shader.Find("Hidden/Internal-Colored"));
|
||||
var alongLine = (quaternions.Length - 1) * t - section;
|
||||
|
||||
lineRenderer = new GameObject().GetComponent<UnityEngine.LineRenderer>();
|
||||
|
||||
this.lineSize = lineSize;
|
||||
}
|
||||
|
||||
private void init(float lineSize = 0.2f)
|
||||
{
|
||||
if (lineRenderer == null)
|
||||
if (section == 0)
|
||||
{
|
||||
//GameObject lineObj = new GameObject("LineObj");
|
||||
//lineRenderer = lineObj.AddComponent<UnityEngine.LineRenderer>();
|
||||
|
||||
//Particles/Additive
|
||||
//lineRenderer.material = new Material(Shader.Find("Hidden/Internal-Colored"));
|
||||
|
||||
lineRenderer = new GameObject().GetComponent<UnityEngine.LineRenderer>();
|
||||
|
||||
this.lineSize = lineSize;
|
||||
return SplineSegment(quaternions[section], quaternions[section], quaternions[section + 1], quaternions[section + 2], alongLine);
|
||||
}
|
||||
}
|
||||
|
||||
//Draws lines through the provided vertices
|
||||
public void DrawLineInGameView(Vector3 start, Vector3 end, Color color)
|
||||
{
|
||||
if (lineRenderer == null)
|
||||
else if( section == quaternions.Length - 2 && section > 0)
|
||||
{
|
||||
init(0.2f);
|
||||
return SplineSegment(quaternions[section - 1], quaternions[section], quaternions[section + 1], quaternions[section + 1], alongLine);
|
||||
}
|
||||
else if ( section >= 1 && section<quaternions.Length -2)
|
||||
{
|
||||
return SplineSegment(quaternions[section - 1], quaternions[section], quaternions[section + 1], quaternions[section + 2], alongLine);
|
||||
}
|
||||
|
||||
//Set color
|
||||
lineRenderer.startColor = color;
|
||||
lineRenderer.endColor = color;
|
||||
|
||||
//Set width
|
||||
lineRenderer.startWidth = lineSize;
|
||||
lineRenderer.endWidth = lineSize;
|
||||
|
||||
//Set line count which is 2
|
||||
lineRenderer.positionCount = 2;
|
||||
|
||||
//Set the postion of both two lines
|
||||
lineRenderer.SetPosition(0, start);
|
||||
lineRenderer.SetPosition(1, end);
|
||||
Debug.LogError("???");
|
||||
return Quaternion.identity;
|
||||
}
|
||||
|
||||
public void Destroy()
|
||||
static Quaternion SlerpNoInvert(Quaternion fro , Quaternion to, float factor)
|
||||
{
|
||||
if (lineRenderer != null)
|
||||
float dot = Quaternion.Dot(fro, to);
|
||||
|
||||
if (Mathf.Abs(dot) > 0.9999f)
|
||||
{
|
||||
//UnityEngine.Object.Destroy(lineRenderer.gameObject);
|
||||
return fro;
|
||||
}
|
||||
|
||||
float theta = Mathf.Acos(dot);
|
||||
var sinT = 1.0f / Mathf.Sin(theta);
|
||||
|
||||
var newFactor = Mathf.Sin(factor * theta) * sinT;
|
||||
|
||||
var invFactor = Mathf.Sin((1.0f - factor) * theta) * sinT;
|
||||
|
||||
return new Quaternion(invFactor * fro.x + newFactor * to.x, invFactor * fro.y + newFactor * to.y, invFactor * fro.z + newFactor * to.z, invFactor * fro.w + newFactor * to.w);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Returns a smooth approximation between q1 and q2 using t1 and t2 as 'tangents'
|
||||
static Quaternion SQUAD(Quaternion q1 , Quaternion t1 , Quaternion t2 , Quaternion q2 , float t)
|
||||
{
|
||||
float slerpT = 2.0f * t * (1.0f - t);
|
||||
|
||||
Quaternion slerp1 = SlerpNoInvert(q1, q2, t);
|
||||
|
||||
Quaternion slerp2 = SlerpNoInvert(t1, t2, t);
|
||||
|
||||
return SlerpNoInvert(slerp1, slerp2, slerpT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Returns a quaternion between q1 and q2 as part of a smooth SQUAD segment
|
||||
public static Quaternion SplineSegment(Quaternion q0, Quaternion q1, Quaternion q2, Quaternion q3, float t)
|
||||
{
|
||||
Quaternion qa = Intermediate(q0, q1, q2);
|
||||
Quaternion qb = Intermediate(q1, q2, q3);
|
||||
return SQUAD(q1, qa, qb, q2, t);
|
||||
|
||||
}
|
||||
|
||||
static public void Exp(ref Quaternion a )
|
||||
{
|
||||
float angle = Mathf.Sqrt(a.x * a.x + a.y * a.y + a.z * a.z);
|
||||
|
||||
float sinAngle = Mathf.Sin(angle);
|
||||
a.w = Mathf.Cos(angle);
|
||||
|
||||
if (Mathf.Abs(sinAngle) >= 1.0e-15)
|
||||
{
|
||||
float coeff = sinAngle / angle;
|
||||
a.x *= coeff;
|
||||
a.y *= coeff;
|
||||
a.z *= coeff;
|
||||
}
|
||||
|
||||
}
|
||||
static Quaternion Add(Quaternion a , Quaternion b )
|
||||
{
|
||||
var r = new Quaternion();
|
||||
r.w = a.w + b.w;
|
||||
r.x = a.x + b.x;
|
||||
r.y = a.y + b.y;
|
||||
r.z = a.z + b.z;
|
||||
return r;
|
||||
}
|
||||
|
||||
static void Scale(ref Quaternion a, float s)
|
||||
{
|
||||
a.w *= s;
|
||||
a.x *= s;
|
||||
a.y *= s;
|
||||
a.z *= s;
|
||||
}
|
||||
|
||||
// Tries to compute sensible tangent values for the quaternion
|
||||
static Quaternion Intermediate(Quaternion q0, Quaternion q1, Quaternion q2 )
|
||||
{
|
||||
Quaternion q1inv = Quaternion.Inverse(q1);
|
||||
|
||||
Quaternion c1 = q1inv * q2;
|
||||
|
||||
Quaternion c2 = q1inv * q0;
|
||||
|
||||
//c1.Log();
|
||||
//c2.Log();
|
||||
|
||||
Quaternion c3 = Add(c2, c1);// c2 + c1;
|
||||
Scale(ref c3, -0.25f);// c3.Scale(-0.25f);
|
||||
|
||||
Exp(ref c3);// c3.Exp();
|
||||
|
||||
Quaternion r = q1 * c3;
|
||||
#if MONO
|
||||
return Normalize(r);
|
||||
#else
|
||||
r.Normalize();
|
||||
return r;
|
||||
#endif
|
||||
}
|
||||
#if MONO
|
||||
public static float Dot(Quaternion a, Quaternion b)
|
||||
{
|
||||
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
|
||||
}
|
||||
|
||||
public static Quaternion Normalize(Quaternion q)
|
||||
{
|
||||
float mag = Mathf.Sqrt(Dot(q, q));
|
||||
|
||||
if (mag < Mathf.Epsilon)
|
||||
return Quaternion.identity;
|
||||
|
||||
return new Quaternion(q.x / mag, q.y / mag, q.z / mag, q.w / mag);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user