diff --git a/Assets/Scripts/Car/Car.cs b/Assets/Scripts/Car/Car.cs index 49a7a90..135a152 100644 --- a/Assets/Scripts/Car/Car.cs +++ b/Assets/Scripts/Car/Car.cs @@ -4,8 +4,8 @@ public class Car { private Route route; - private Road currentRoad; - public float roadPositon = 0f, speed = 0f, currentDistance; + public Road currentRoad; + public float roadPositon = 0f, speed = 0f; private int roadIndex = 0; private GameObject gameObject; private Config config; @@ -48,6 +48,9 @@ (2*config.carMass) + (config.carTorque*deltaTime) / (config.carWheelRadius * config.carMass) ; + float t = currentRoad.path.getT(roadPositon); + float maxSpeed = Mathf.Sqrt((float) (-Mathf.Abs(currentRoad.path.getRadius(t)) / 0.2 * Physics.gravity.y)); + speed = Mathf.Min(speed, maxSpeed); float distance = deltaTime * speed; roadPositon += distance; while (roadPositon > currentRoad.path.length) { diff --git a/Assets/Scripts/Car/Car.cs b/Assets/Scripts/Car/Car.cs index 49a7a90..135a152 100644 --- a/Assets/Scripts/Car/Car.cs +++ b/Assets/Scripts/Car/Car.cs @@ -4,8 +4,8 @@ public class Car { private Route route; - private Road currentRoad; - public float roadPositon = 0f, speed = 0f, currentDistance; + public Road currentRoad; + public float roadPositon = 0f, speed = 0f; private int roadIndex = 0; private GameObject gameObject; private Config config; @@ -48,6 +48,9 @@ (2*config.carMass) + (config.carTorque*deltaTime) / (config.carWheelRadius * config.carMass) ; + float t = currentRoad.path.getT(roadPositon); + float maxSpeed = Mathf.Sqrt((float) (-Mathf.Abs(currentRoad.path.getRadius(t)) / 0.2 * Physics.gravity.y)); + speed = Mathf.Min(speed, maxSpeed); float distance = deltaTime * speed; roadPositon += distance; while (roadPositon > currentRoad.path.length) { diff --git a/Assets/Scripts/Primitives/Bezier.cs b/Assets/Scripts/Primitives/Bezier.cs index 521b864..3f03e46 100644 --- a/Assets/Scripts/Primitives/Bezier.cs +++ b/Assets/Scripts/Primitives/Bezier.cs @@ -1,12 +1,13 @@ using System.Collections; using System.Collections.Generic; using UnityEngine; +using System; public class Bezier { public Vector3 A, B, C, D; public float length; - // t(distance) = ??? - public NewtonPolynom TOfDistance = new NewtonPolynom(); + private static float perscision = 16f; + public float[] lengths = new float[(int) perscision + 1]; public Bezier(Vector3 A, Vector3 B, Vector3 C, Vector3 D) { this.A = A; @@ -23,6 +24,30 @@ this.D = Vector3.zero; updateLength(); } + + public void updateLength() { + length = 0f; + Vector3 previous = A; + lengths[0] = 0f; + for (int i = 1; i <= perscision; i++) { + Vector3 current = getPosition(i / perscision); + length += (current - previous).magnitude; + previous = current; + lengths[i] = length; + } + } + + public float getT(float distance) { + int index = 0; + while (!(lengths[index] <= distance && lengths[index+1] > distance)) { + index++; + } + float lengthBefore = lengths[index]; + float lengthAfter = lengths[index+1]; + float segmentLength = lengthAfter - lengthBefore; + float segmentFraction = (distance - lengthBefore) / segmentLength; + return (index + segmentFraction) / perscision; + } public Vector3 getPosition(float t) { float T = 1.0f - t; @@ -33,24 +58,6 @@ D * ( t*t*t); } - public void updateLength() { - length = 0f; - float steps = 5f; - Vector3 previous = A; - TOfDistance = new NewtonPolynom(); - TOfDistance.add(0f, 0f); - for (int i = 1; i <= steps; i++) { - Vector3 current = getPosition(i / steps); - length += (current - previous).magnitude; - previous = current; - TOfDistance.add(length, i/steps); - } - } - - public float getT(float distance) { - return TOfDistance.evaluate(distance); - } - public Vector3 getDirection(float t) { float T = 1.0f - t; return @@ -59,4 +66,20 @@ C * (-3*t*t + 6*T*t) + D * ( 3*t*t ); } + + public Vector3 getAcceleration(float t) { + return + A * (-6 *t + 6 ) + + B * ( 6*t) + + C * ( 18*t - 12 ) + + D * (-18 *t + 6); + } + + public float getRadius(float t) { + Vector3 direction = getDirection(t); + Vector3 acceleration = getAcceleration(t); + return + Mathf.Pow(direction.x * direction.x + direction.z * direction.z, 1.5f) / + Mathf.Abs(direction.x * acceleration.z - direction.z * acceleration.x); + } } diff --git a/Assets/Scripts/Car/Car.cs b/Assets/Scripts/Car/Car.cs index 49a7a90..135a152 100644 --- a/Assets/Scripts/Car/Car.cs +++ b/Assets/Scripts/Car/Car.cs @@ -4,8 +4,8 @@ public class Car { private Route route; - private Road currentRoad; - public float roadPositon = 0f, speed = 0f, currentDistance; + public Road currentRoad; + public float roadPositon = 0f, speed = 0f; private int roadIndex = 0; private GameObject gameObject; private Config config; @@ -48,6 +48,9 @@ (2*config.carMass) + (config.carTorque*deltaTime) / (config.carWheelRadius * config.carMass) ; + float t = currentRoad.path.getT(roadPositon); + float maxSpeed = Mathf.Sqrt((float) (-Mathf.Abs(currentRoad.path.getRadius(t)) / 0.2 * Physics.gravity.y)); + speed = Mathf.Min(speed, maxSpeed); float distance = deltaTime * speed; roadPositon += distance; while (roadPositon > currentRoad.path.length) { diff --git a/Assets/Scripts/Primitives/Bezier.cs b/Assets/Scripts/Primitives/Bezier.cs index 521b864..3f03e46 100644 --- a/Assets/Scripts/Primitives/Bezier.cs +++ b/Assets/Scripts/Primitives/Bezier.cs @@ -1,12 +1,13 @@ using System.Collections; using System.Collections.Generic; using UnityEngine; +using System; public class Bezier { public Vector3 A, B, C, D; public float length; - // t(distance) = ??? - public NewtonPolynom TOfDistance = new NewtonPolynom(); + private static float perscision = 16f; + public float[] lengths = new float[(int) perscision + 1]; public Bezier(Vector3 A, Vector3 B, Vector3 C, Vector3 D) { this.A = A; @@ -23,6 +24,30 @@ this.D = Vector3.zero; updateLength(); } + + public void updateLength() { + length = 0f; + Vector3 previous = A; + lengths[0] = 0f; + for (int i = 1; i <= perscision; i++) { + Vector3 current = getPosition(i / perscision); + length += (current - previous).magnitude; + previous = current; + lengths[i] = length; + } + } + + public float getT(float distance) { + int index = 0; + while (!(lengths[index] <= distance && lengths[index+1] > distance)) { + index++; + } + float lengthBefore = lengths[index]; + float lengthAfter = lengths[index+1]; + float segmentLength = lengthAfter - lengthBefore; + float segmentFraction = (distance - lengthBefore) / segmentLength; + return (index + segmentFraction) / perscision; + } public Vector3 getPosition(float t) { float T = 1.0f - t; @@ -33,24 +58,6 @@ D * ( t*t*t); } - public void updateLength() { - length = 0f; - float steps = 5f; - Vector3 previous = A; - TOfDistance = new NewtonPolynom(); - TOfDistance.add(0f, 0f); - for (int i = 1; i <= steps; i++) { - Vector3 current = getPosition(i / steps); - length += (current - previous).magnitude; - previous = current; - TOfDistance.add(length, i/steps); - } - } - - public float getT(float distance) { - return TOfDistance.evaluate(distance); - } - public Vector3 getDirection(float t) { float T = 1.0f - t; return @@ -59,4 +66,20 @@ C * (-3*t*t + 6*T*t) + D * ( 3*t*t ); } + + public Vector3 getAcceleration(float t) { + return + A * (-6 *t + 6 ) + + B * ( 6*t) + + C * ( 18*t - 12 ) + + D * (-18 *t + 6); + } + + public float getRadius(float t) { + Vector3 direction = getDirection(t); + Vector3 acceleration = getAcceleration(t); + return + Mathf.Pow(direction.x * direction.x + direction.z * direction.z, 1.5f) / + Mathf.Abs(direction.x * acceleration.z - direction.z * acceleration.x); + } } diff --git a/Assets/Scripts/Roads/Road.cs b/Assets/Scripts/Roads/Road.cs index d36ccca..032bed8 100644 --- a/Assets/Scripts/Roads/Road.cs +++ b/Assets/Scripts/Roads/Road.cs @@ -21,8 +21,8 @@ public void initialize(Transform parent) { path = new Bezier(); - pathLine = new FlatBezierRenderer(path, 50, 0.05f); - roadBody = new FlatBezierRenderer(path, 50, 2f); + pathLine = new FlatBezierRenderer(path, 32, 0.05f); + roadBody = new FlatBezierRenderer(path, 32, 2f); arrow1 = new Bezier(); arrow1Renderer = new FlatBezierRenderer(arrow1, 3, 0.05f); @@ -50,7 +50,10 @@ setupArrow(arrow1Renderer, gameObject.transform); setupArrow(arrow2Renderer, gameObject.transform); - update(true); + + foreach (Node node in nodes) { + node.update(); + } } private void setupArrow(FlatBezierRenderer renderer, Transform parent) {