public static void SetSpawnTransform(Transform car, float dist, int height) { int point = 0; dist = Mathf.Repeat(dist, Instance.TotalLength); while (Instance._distances[point] < dist) { ++point; } if (dist == 0) { ++point; } Instance.calculatePandM(--point); float t = Mathf.InverseLerp(Instance._distances[point], Instance._distances[point + 1], dist); Vector3 tangent; float percentThrough = t; Vector3 position = CatmullRom.Interpolate(Instance.p0, Instance.p1, Instance.m0, Instance.m1, t, out tangent); Vector3 normal = Vector3.Lerp(Instance._points[point].Up, Instance._points[(point + 1) % Instance._points.Capacity].Up, percentThrough); float center = Mathf.Lerp(Instance._points[point].Centre, Instance._points[(point + 1) % Instance._points.Capacity].Centre, percentThrough); float width = Mathf.Lerp(Instance._points[point].Width, Instance._points[(point + 1) % Instance._points.Capacity].Width, percentThrough); car.position = position + Vector3.Cross(tangent, normal).normalized *width *center + height * Vector3.up; car.up = normal; car.forward = tangent; }
private void ConstructMesh() { trackMesh.Clear(); List <Vector2> texCoords = new List <Vector2> (); List <int> indices = new List <int> (); meshCoords = new List <Vector3> (); CatmullRom CRS = new CatmullRom(diffCoords); int diffCoordsSize = CRS.pts.Count; float step = 1.0f / (diffCoordsSize * smoothness); float iterator = 0.0f; List <Vector3> outerCoords = new List <Vector3> (); List <Vector3> innerCoords = new List <Vector3> (); for (int i = 0; i < diffCoordsSize * smoothness; i++) { outerCoords.Add(CRS.DisplaceBy(trackWidth, iterator, step)); innerCoords.Add(CRS.Interpolate(iterator)); iterator += step; } WeldOverlappingSections(outerCoords, innerCoords); for (int i = 0; i < diffCoordsSize * smoothness; i++) { meshCoords.Add(innerCoords [i]); meshCoords.Add(outerCoords [i]); meshCoords.Add(innerCoords [i]); meshCoords.Add(outerCoords [i]); texCoords.Add(new Vector2(0, 0)); texCoords.Add(new Vector2(1, 0)); texCoords.Add(new Vector2(0, 1)); texCoords.Add(new Vector2(1, 1)); } int meshCount = meshCoords.Count; for (int i = 0; i < meshCount; i++) { // Tri 1 indices.Add(i % meshCount); indices.Add((i + 2) % meshCount); indices.Add((i + 1) % meshCount); // Tri 2 indices.Add((i + 2) % meshCount); indices.Add((i + 3) % meshCount); indices.Add((i + 1) % meshCount); } trackMesh.vertices = meshCoords.ToArray(); trackMesh.uv = texCoords.ToArray(); trackMesh.RecalculateNormals(); trackMesh.Optimize(); trackMesh.SetIndices(indices.ToArray(), MeshTopology.LineStrip, 0); }
// Basically the same as UpdateTrack() just drawing pretty balls and stuff... void OnDrawGizmos() { int closedAdjustment = ClosedLoop ? 0 : 1; float currentDistance = 0.0f; float step = TotalLength / CurveResolution; int ind = 0; //// 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 for (int i = 0; i < TrackManager.Track.Points.Count - closedAdjustment; i++) { calculatePandM(i); Vector3 position; float t; // Second for loop actually creates the spline for this particular segment while (currentDistance < _distances[i + 1]) { t = Mathf.InverseLerp(_distances[i], _distances[i + 1], currentDistance); Vector3 tangent; float percentThrough = t; position = CatmullRom.Interpolate(p0, p1, m0, m1, t, out tangent); Gizmos.color = Color.red; Gizmos.DrawSphere(position, 0.25f); Vector3 normal; float centre; float width; CalculateNormalCenterWidth(i, percentThrough, out normal, out centre, out width); Gizmos.color = Color.green; Gizmos.DrawSphere(position + Vector3.Cross(tangent, normal).normalized *width *(1 + centre), 0.5f); Gizmos.DrawSphere(position - Vector3.Cross(tangent, normal).normalized *width *(1 - centre), 0.5f); Gizmos.color = Color.yellow; Gizmos.DrawSphere(position + Vector3.Cross(tangent, normal).normalized *width *centre, 0.8f); ++ind; currentDistance += step; } } }
//TODO:: this function doesn't do well on slopes or loops. Make it look at the normal. // Called for the entire track to generate all the tokens for the track. (randomly) Self explanitory... public static void SetTokenPositions(int numTokens) { int closedAdjustment = Instance.ClosedLoop ? 0 : 1; float currentDistance = 0.0f; float step = Instance.TotalLength / numTokens; int ind = 0; // 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 for (int i = 0; i < TrackManager.Track.Points.Count - closedAdjustment; i++) { Instance.calculatePandM(i); Vector3 position; float t; while (currentDistance < Instance._distances[i + 1]) { t = Mathf.InverseLerp(Instance._distances[i], Instance._distances[i + 1], currentDistance); Vector3 tangent; float percentThrough = t; position = CatmullRom.Interpolate(Instance.p0, Instance.p1, Instance.m0, Instance.m1, t, out tangent); Vector3 normal; float centre; float width; Instance.CalculateNormalCenterWidth(i, percentThrough, out normal, out centre, out width); float centerOffset = Random.Range(-1.0f, 1.0f); TokenSpawner.SpawnTokensAtPoint(2 * normal + position + Vector3.Cross(tangent, normal).normalized *width *(centre + centerOffset)); ++ind; currentDistance += step; } } }
public void MoveFeetCatmull(AvatarIKGoal goal, Vector3 currentPosition, float speed) { var step = speed * Time.deltaTime; //to add parameters from function call var newLocalPos = catmullRomSpline.Interpolate(localFootProjection, 0, 0.5f); newGlobalPosition = matrix.MultiplyPoint3x4(new Vector3(0, newLocalPos.y, localFootProjection.z)); // newGlobalPosition = matrix.MultiplyPoint3x4(newLocalPos); var yVar = Mathf.MoveTowards(currentPosition.y, newGlobalPosition.y, step); newGlobalPosition.y = yVar; _animator.SetIKPositionWeight(goal, 1); _animator.SetIKPosition(goal, newGlobalPosition); // var test = new Vector3(0, newGlobalPosition.y, currentPosition.z); // var newY = Vector3.MoveTowards(currentPosition, test, step); // test.y = newY.y; // _animator.SetIKPositionWeight(goal, 1); // _animator.SetIKPosition(goal, test); }
// TODO:: simplify this function. // Set where the vehicle will spawn, according to how far it has traveled through the track. public static void SetSpawnTransform(Transform car, float dist, int height) { int point = 0; //Keep the distance in the correct range. Even if the player has done multiple laps. dist = Mathf.Repeat(dist, Instance.TotalLength); // go through distances until at correct segment index. Works, and is simple. ;) while (Instance._distances[point] < dist) { ++point; } if (dist == 0) { ++point; } Instance.calculatePandM(--point); float t = Mathf.InverseLerp(Instance._distances[point], Instance._distances[point + 1], dist); Vector3 tangent; float percentThrough = t; Vector3 position = CatmullRom.Interpolate(Instance.p0, Instance.p1, Instance.m0, Instance.m1, t, out tangent); Vector3 normal; float centre; float width; Instance.CalculateNormalCenterWidth(point, percentThrough, out normal, out centre, out width); car.position = position + Vector3.Cross(tangent, normal).normalized *width *centre + height * Vector3.up; car.up = normal; car.forward = tangent; }
void UpdateTrack() { MeshFilter mf = GetComponent <MeshFilter>(); Mesh mesh = mf.sharedMesh; int closedAdjustment = ClosedLoop ? 0 : 1; int pointsToMake = CurveResolution + 1; Vector3[] vertices = new Vector3[pointsToMake * 2 + 2]; int[] triangles = new int[pointsToMake * 6]; float currentDistance = 0.0f; float step = TotalLength / CurveResolution; int ind = 0; // 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 for (int i = 0; i < _points.Count - closedAdjustment; i++) { calculatePandM(i); Vector3 position; float t; // Second for loop actually creates the spline for this particular segment while (currentDistance <= _distances[i + 1]) { t = Mathf.InverseLerp(_distances[i], _distances[i + 1], currentDistance); Vector3 tangent; float percentThrough = t; position = CatmullRom.Interpolate(p0, p1, m0, m1, t, out tangent); Vector3 normal = Vector3.Lerp(_points[i].Up, _points[(i + 1) % _points.Capacity].Up, percentThrough); float center = Mathf.Lerp(_points[i].Centre, _points[(i + 1) % _points.Capacity].Centre, percentThrough); float width = Mathf.Lerp(_points[i].Width, _points[(i + 1) % _points.Capacity].Width, percentThrough); vertices[ind * 2] = position + Vector3.Cross(tangent, normal).normalized *width *(1 + center); vertices[ind * 2 + 1] = position - Vector3.Cross(tangent, normal).normalized *width *(1 - center); triangles[ind * 6] = ind * 2 + 1; triangles[ind * 6 + 1] = ind * 2; triangles[ind * 6 + 2] = ind * 2 + 2; triangles[ind * 6 + 3] = ind * 2 + 1; triangles[ind * 6 + 4] = ind * 2 + 2; triangles[ind * 6 + 5] = ind * 2 + 3; ++ind; currentDistance += step; } } vertices[pointsToMake * 2] = vertices[0]; vertices[pointsToMake * 2 + 1] = vertices[1]; mesh.Clear(); mesh.vertices = vertices; mesh.triangles = triangles; mesh.Optimize(); mesh.RecalculateNormals(); mesh.RecalculateBounds(); MeshCollider MCollider = GetComponent <MeshCollider>(); MCollider.sharedMesh = mesh; }
public static List <Vector3> MakeBetterCurve(List <Vector3> points, int resolution, bool loop) { List <Vector3> geometry = loop? points.GetRange(0, points.Count - 1) : points.GetRange(0, points.Count); List <Vector3> betterCurve = new List <Vector3> (); //Number of segments int segmentsCount = loop ? (resolution) * (geometry.Count) : (resolution) * (geometry.Count - 1); if (segmentsCount <= 1) //If the count is less than 2 points it's not a line, return. { return(betterCurve); } Vector3 p0; Vector3 p1; Vector3 m0; Vector3 m1; int closedAdjustment = loop ? 0 : 1; for (int i = 0; i < geometry.Count - closedAdjustment; i++) { p0 = geometry[i]; p1 = (loop == true && i == geometry.Count - 1) ? geometry[0] : geometry[i + 1]; // m0 if (i == 0) { m0 = loop ? 0.5f * (p1 - geometry[geometry.Count - 1]) : p1 - p0; } else { m0 = 0.5f * (p1 - geometry[i - 1]); } // m1 if (loop) { if (i == 0) { m1 = 0.5f * (geometry[i + 2] - p0); } else { m1 = 0.5f * (geometry[(i + 2) % geometry.Count] - p0); } } else { if (i < geometry.Count - 2) { m1 = 0.5f * (geometry[(i + 2) % geometry.Count] - p0); } else { m1 = p1 - p0; } } float t; float pointStep = 1.0f / resolution; if ((i == geometry.Count - 2 && loop == false) || (i == geometry.Count - 1 && loop)) { pointStep = 1.0f / (resolution - 1); // last point of last segment should reach p1 } //Create Road segments for (int j = 0; j < resolution; j++) { t = j * pointStep; betterCurve.Add(CatmullRom.Interpolate(p0, p1, m0, m1, t)); } } return(betterCurve); }
// Fill the mesh with the correct vertices according to the path. void UpdateTrack() { MeshFilter mf = GetComponent <MeshFilter>(); Mesh mesh = mf.sharedMesh; int closedAdjustment = ClosedLoop ? 0 : 1; int pointsToMake = CurveResolution + 1; Vector3[] vertices = new Vector3[pointsToMake * 2 + 2]; int[] triangles = new int[pointsToMake * 6]; float currentDistance = 0.0f; float step = TotalLength / CurveResolution; int ind = 0; // 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 for (int i = 0; i < TrackManager.Track.Points.Count - closedAdjustment; i++) { calculatePandM(i); Vector3 position; float t; // Second for loop actually creates the spline for this particular segment while (currentDistance <= _distances[i + 1]) { t = Mathf.InverseLerp(_distances[i], _distances[i + 1], currentDistance); Vector3 tangent; float percentThrough = t; position = CatmullRom.Interpolate(p0, p1, m0, m1, t, out tangent); // Debug.Log("Track details:: Num points: " + TrackManager.Track.Points.Count + "; i is: " + i + "; capacity: " + TrackManager.Track.Points.Count); Vector3 normal; float centre; float width; CalculateNormalCenterWidth(i, percentThrough, out normal, out centre, out width); vertices[ind * 2] = position + Vector3.Cross(tangent, normal).normalized *width *(1 + centre); vertices[ind * 2 + 1] = position - Vector3.Cross(tangent, normal).normalized *width *(1 - centre); triangles[ind * 6] = ind * 2 + 1; triangles[ind * 6 + 1] = ind * 2; triangles[ind * 6 + 2] = ind * 2 + 2; triangles[ind * 6 + 3] = ind * 2 + 1; triangles[ind * 6 + 4] = ind * 2 + 2; triangles[ind * 6 + 5] = ind * 2 + 3; ++ind; currentDistance += step; } } // close the loop, so the track is complete. (NOTE:: there seems to be a subtle bug with this that I haven't had the patience to fix). vertices[pointsToMake * 2] = vertices[0]; vertices[pointsToMake * 2 + 1] = vertices[1]; // populate and sort out the mesh. (the following +/- 10 lines) mesh.Clear(); mesh.vertices = vertices; mesh.triangles = triangles; mesh.Optimize(); mesh.RecalculateNormals(); mesh.RecalculateBounds(); MeshCollider MCollider = GetComponent <MeshCollider>(); MCollider.sharedMesh = mesh; }
public void DrawSpline(bool store) { if (store) { points.Clear(); inner.Clear(); outer.Clear(); if (generateWaypoints) { waypoints.Clear(); } } Vector3 p0; Vector3 p1; Vector3 m0; Vector3 m1; int pointsToMake; if (ClosedLoop == true) { pointsToMake = (CurveResolution) * (ControlPoints.Count); } else { pointsToMake = (CurveResolution) * (ControlPoints.Count - 1); } if (pointsToMake > 0) //Prevent Number Overflow { CurveCoordinates = new Vector3[pointsToMake]; Tangents = new Vector3[pointsToMake]; int closedAdjustment = ClosedLoop ? 0 : 1; // 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 for (int i = 0; i < ControlPoints.Count - closedAdjustment; i++) { p0 = ControlPoints[i].transform.position; p1 = (ClosedLoop == true && i == ControlPoints.Count - 1) ? ControlPoints[0].transform.position : ControlPoints[i + 1].transform.position; // Tangent calculation for each control point // Tangent M[k] = (P[k+1] - P[k-1]) / 2 // With [] indicating subscript // m0 if (i == 0) { m0 = ClosedLoop ? 0.5f * (p1 - ControlPoints[ControlPoints.Count - 1].transform.position) : p1 - p0; } else { m0 = 0.5f * (p1 - ControlPoints[i - 1].transform.position); } // m1 if (ClosedLoop) { if (i == ControlPoints.Count - 1) { m1 = 0.5f * (ControlPoints[(i + 2) % ControlPoints.Count].transform.position - p0); } else if (i == 0) { m1 = 0.5f * (ControlPoints[i + 2].transform.position - p0); } else { m1 = 0.5f * (ControlPoints[(i + 2) % ControlPoints.Count].transform.position - p0); } } else { if (i < ControlPoints.Count - 2) { m1 = 0.5f * (ControlPoints[(i + 2) % ControlPoints.Count].transform.position - p0); } else { m1 = p1 - p0; } } Vector3 position; float t; float pointStep = 1.0f / CurveResolution; if ((i == ControlPoints.Count - 2 && ClosedLoop == false) || (i == ControlPoints.Count - 1 && ClosedLoop)) { pointStep = 1.0f / (CurveResolution - 1); // last point of last segment should reach p1 } // Second for loop actually creates the spline for this particular segment for (int j = 0; j < CurveResolution; j++) { t = j * pointStep; Vector3 tangent; position = CatmullRom.Interpolate(p0, p1, m0, m1, t, out tangent); CurveCoordinates[i * CurveResolution + j] = position; Tangents[i * CurveResolution + j] = tangent; if (debug) //Normals { Debug.DrawLine(position + Vector3.Cross(tangent, Vector3.up).normalized *extrude / 2 + transform.position, position - Vector3.Cross(tangent, Vector3.up).normalized *extrude / 2 + transform.position, Color.red); Debug.DrawLine(position + Vector3.Cross(tangent, Vector3.up).normalized *extrude / 2 + transform.position, position + Vector3.Cross(tangent, Vector3.up).normalized *(extrude / 2 + edgeWidth) + transform.position, Color.green); //Edge + Debug.DrawLine(position - Vector3.Cross(tangent, Vector3.up).normalized *extrude / 2 + transform.position, position - Vector3.Cross(tangent, Vector3.up).normalized *(extrude / 2 + edgeWidth) + transform.position, Color.green); //Edge - } if (store) { points.Add(position - Vector3.Cross(tangent, Vector3.up).normalized *extrude / 2); points.Add(position); points.Add(position + Vector3.Cross(tangent, Vector3.up).normalized *extrude / 2); inner.Add(position - Vector3.Cross(tangent, Vector3.up).normalized *extrude / 2); inner.Add(position - Vector3.Cross(tangent, Vector3.up).normalized *(extrude / 2 + edgeWidth)); outer.Add(position + Vector3.Cross(tangent, Vector3.up).normalized *extrude / 2); outer.Add(position + Vector3.Cross(tangent, Vector3.up).normalized *(extrude / 2 + edgeWidth)); } } for (int j = 0; j < waypointResolution; j++) { t = j * 1.0f / waypointResolution; Vector3 tangent; position = CatmullRom.Interpolate(p0, p1, m0, m1, t, out tangent); if (debug && generateWaypoints) //Waypoints { Debug.DrawLine(position, position + new Vector3(0, 25, 0), Color.blue); } if (store && generateWaypoints) { waypoints.Add(position); } } } //Curve line for (int i = 0; i < CurveCoordinates.Length - 1; ++i) { Debug.DrawLine(CurveCoordinates[i] + transform.position, CurveCoordinates[i + 1] + transform.position, Color.cyan); } } }
void Update() { Vector3 p0; Vector3 p1; Vector3 m0; Vector3 m1; int pointsToMake; //Debug.Log("This is a test " + Points[0]); if (ClosedLoop == true) { pointsToMake = (CurveResolution) * (Points.Count); } else { pointsToMake = (CurveResolution) * (Points.Count - 1); } CurveCoordinates = new Vector3[pointsToMake]; Tangents = new Vector3[pointsToMake]; int closedAdjustment = ClosedLoop ? 0 : 1; // 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 for (int i = 0; i < Points.Count - closedAdjustment; i++) { //if (Points[i] == null || Points[i + 1] == null || (i > 0 && Points[i - 1] == null) || (i < Points.Count - 2 && Points[i + 2] == null)) //{ // return; //} p0 = Points[i].transform.position; p1 = (ClosedLoop == true && i == Points.Count - 1) ? Points[0].transform.position : Points[i + 1].transform.position; // Tangent calculation for each control point // Tangent M[k] = (P[k+1] - P[k-1]) / 2 // With [] indicating subscript // m0 if (i == 0) { m0 = ClosedLoop ? 0.5f * (p1 - Points[Points.Count - 1].transform.position) : p1 - p0; } else { m0 = 0.5f * (p1 - Points[i - 1].transform.position); } // m1 if (ClosedLoop) { if (i == Points.Count - 1) { m1 = 0.5f * (Points[(i + 2) % Points.Count].transform.position - p0); } else if (i == 0) { m1 = 0.5f * (Points[i + 2].transform.position - p0); } else { m1 = 0.5f * (Points[(i + 2) % Points.Count].transform.position - p0); } } else { if (i < Points.Count - 2) { m1 = 0.5f * (Points[(i + 2) % Points.Count].transform.position - p0); } else { m1 = p1 - p0; } } Vector3 position; float t; float pointStep = 1.0f / CurveResolution; if ((i == Points.Count - 2 && ClosedLoop == false) || (i == Points.Count - 1 && ClosedLoop)) { pointStep = 1.0f / (CurveResolution - 1); // last point of last segment should reach p1 } // Second for loop actually creates the spline for this particular segment for (int j = 0; j < CurveResolution; j++) { t = j * pointStep; Vector3 tangent; position = CatmullRom.Interpolate(p0, p1, m0, m1, t, out tangent); CurveCoordinates[i * CurveResolution + j] = position; Tangents[i * CurveResolution + j] = tangent; //Debug.DrawRay(position, tangent.normalized * 2, Color.red); Debug.DrawLine(position + Vector3.Cross(tangent, Vector3.up).normalized, position - Vector3.Cross(tangent, Vector3.up).normalized, Color.red); } } for (int i = 0; i < CurveCoordinates.Length - 1; ++i) { Debug.DrawLine(CurveCoordinates[i], CurveCoordinates[i + 1]); } }