public override void Update(GameTime gameTime) { // Update _time. _time += (float)gameTime.ElapsedGameTime.TotalSeconds; var debugRenderer = GraphicsScreen.DebugRenderer; debugRenderer.Clear(); // Draw the path key points. foreach (var point in _path.Select(key => key.Point)) { debugRenderer.DrawPoint(point, Color.Black, false); } // Draw the path. for (float i = 0; i < _path.Last().Parameter; i += 0.1f) { var point0 = _path.GetPoint(i); var point1 = _path.GetPoint((i + 0.1f)); debugRenderer.DrawLine(point0, point1, Color.Black, false); } // Move an object with constant speed along the path. const float speed = 2; var traveledDistance = _time * speed; // Get path parameter where the path length is equal to traveledDistance. var parameter = _path.GetParameterFromLength(traveledDistance, 10, 0.01f); // Get path point at the traveledDistance. Vector3F position = _path.GetPoint(parameter); // Get the path tangent at traveledDistance and use it as the forward direction. Vector3F forward = _path.GetTangent(parameter).Normalized; // Draw an object on the path. DrawObject(position, forward); base.Update(gameTime); }
public override void Update(GameTime gameTime) { float deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds; // Move an object with constant speed along the path. const float speed = 5; float newPathPosition = _currentPathPosition + deltaTime * speed; // Get path parameter where the path length is equal to newPathPosition. float parameter = _path.GetParameterFromLength(newPathPosition, 10, 0.01f); // Get path point at the newPathPosition. Vector3 position = _path.GetPoint(parameter); // Get the path tangent at newPathPosition and use it as the forward direction. Vector3 forward = _path.GetTangent(parameter).Normalized; Quaternion currentOrientation = Quaternion.CreateFromRotationMatrix(_kinematicBody.Pose.Orientation); Quaternion targetOrientation = Quaternion.CreateFromRotationMatrix(Vector3.UnitY, forward); Quaternion orientationDelta = targetOrientation * currentOrientation.Conjugated; // Selective Negation: // A certain rotation can be described by two quaternions: q and -q. For example, if you look // to the north and want to look to the east you can either rotate 90 degrees clockwise or // 270 degrees counter-clockwise. In the game we always want to rotate using the // smaller angle. This is done using "Selective Negation": The dot product of two quaternions // is proportional to the cosine of the rotation angle. If the cosine of the angle is < 0, // the angle is larger than +/- 90 degrees. In this case we must use -orientationDelta to // rotate using the smaller angle. if (Quaternion.Dot(currentOrientation, targetOrientation) < 0) { orientationDelta = -orientationDelta; } // We could directly set the new position of the kinematic body. However, directly // setting a position is like "teleporting" an object. The body would not interact // properly with other objects in the physics simulation. // Instead we apply a linear and angular velocity to the body. The simulation will // automatically update the position of the body. If the body touches other objects // along the way it will push these objects with the appropriate force. // Note that the physics simulation may advance with a different time step than the // rest of the game. deltaTime = Math.Max(deltaTime, Simulation.Settings.Timing.FixedTimeStep); // Determine the linear velocity that moves the body forward. Vector3 linearVelocity = (position - _kinematicBody.Pose.Position) / deltaTime; // Determine the angular velocity that rotates the body. Vector3 angularVelocity; Vector3 rotationAxis = orientationDelta.Axis; if (!rotationAxis.IsNumericallyZero) { // The angular velocity is computed as rotationAxis * rotationSpeed. // The rotation speed is computed as angle / time. (Note: The angle is given in radians.) float rotationSpeed = (orientationDelta.Angle / deltaTime); angularVelocity = rotationAxis * rotationSpeed; } else { // The axis of rotation is 0. That means the no rotation should be applied. angularVelocity = Vector3.Zero; } _kinematicBody.LinearVelocity = linearVelocity; _kinematicBody.AngularVelocity = angularVelocity; _currentPathPosition = newPathPosition; // Let the base class render the rigid bodies. base.Update(gameTime); // Draw the 3D path. var debugRenderer = GraphicsScreen.DebugRenderer; for (int i = 0; i < _pointList.Length; i++) { debugRenderer.DrawLine(_pointList[i], _pointList[(i + 1) % _pointList.Length], Color.Black, false); } }
public void TwoKeyCurvesTest() { Path3F curve = new Path3F(); curve.Add(new PathKey3F() { Parameter = 1, Point = new Vector3F(1, 2, 0), Interpolation = SplineInterpolation.CatmullRom, }); curve.Add(new PathKey3F() { Parameter = 3, Point = new Vector3F(3, 4, 0), Interpolation = SplineInterpolation.CatmullRom, }); curve.PreLoop = CurveLoopType.Constant; curve.PostLoop = CurveLoopType.Constant; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(2, 3, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(3, 4, 0), curve.GetPoint(3)); Assert.AreEqual(new Vector3F(3, 4, 0), curve.GetPoint(4)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(1, 1, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(1, 1, 0), curve.GetTangent(2)); Assert.AreEqual(new Vector3F(1, 1, 0), curve.GetTangent(3)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(4)); Assert.IsTrue(Numeric.AreEqual(new Vector3F(2, 2, 0).Length, curve.GetLength(0, 4, 10, 0.01f), 0.01f)); curve.PreLoop = CurveLoopType.Linear; curve.PostLoop = CurveLoopType.Linear; curve.PreLoop = CurveLoopType.Cycle; curve.PostLoop = CurveLoopType.Cycle; curve.PreLoop = CurveLoopType.CycleOffset; curve.PostLoop = CurveLoopType.CycleOffset; curve.PreLoop = CurveLoopType.Oscillate; curve.PostLoop = CurveLoopType.Oscillate; }
public void OneKeyCurvesTest() { // Test linear curves with 1 point Path3F curve = new Path3F(); curve.Add(new PathKey3F() { Parameter = 1, Point = new Vector3F(1, 2, 0), Interpolation = SplineInterpolation.Linear, }); curve.PreLoop = CurveLoopType.Constant; curve.PostLoop = CurveLoopType.Constant; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); curve.PreLoop = CurveLoopType.Linear; curve.PostLoop = CurveLoopType.Linear; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); curve.PreLoop = CurveLoopType.Cycle; curve.PostLoop = CurveLoopType.Cycle; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); curve.PreLoop = CurveLoopType.CycleOffset; curve.PostLoop = CurveLoopType.CycleOffset; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); curve.PreLoop = CurveLoopType.Oscillate; curve.PostLoop = CurveLoopType.Oscillate; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); // Test step curves with 1 point curve = new Path3F(); curve.Add(new PathKey3F() { Parameter = 1, Point = new Vector3F(1, 2, 0), Interpolation = SplineInterpolation.StepLeft, }); curve.PreLoop = CurveLoopType.Constant; curve.PostLoop = CurveLoopType.Constant; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); curve.PreLoop = CurveLoopType.Linear; curve.PostLoop = CurveLoopType.Linear; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); curve.PreLoop = CurveLoopType.Cycle; curve.PostLoop = CurveLoopType.Cycle; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); curve.PreLoop = CurveLoopType.CycleOffset; curve.PostLoop = CurveLoopType.CycleOffset; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); curve.PreLoop = CurveLoopType.Oscillate; curve.PostLoop = CurveLoopType.Oscillate; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); // Test B-spline curves with 1 point curve = new Path3F(); curve.Add(new PathKey3F() { Parameter = 1, Point = new Vector3F(1, 2, 0), Interpolation = SplineInterpolation.BSpline, }); curve.PreLoop = CurveLoopType.Constant; curve.PostLoop = CurveLoopType.Constant; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); curve.PreLoop = CurveLoopType.Linear; curve.PostLoop = CurveLoopType.Linear; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); curve.PreLoop = CurveLoopType.Cycle; curve.PostLoop = CurveLoopType.Cycle; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); curve.PreLoop = CurveLoopType.CycleOffset; curve.PostLoop = CurveLoopType.CycleOffset; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); curve.PreLoop = CurveLoopType.Oscillate; curve.PostLoop = CurveLoopType.Oscillate; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); // Test Catmull-Rom curves with 1 point curve = new Path3F(); curve.Add(new PathKey3F() { Parameter = 1, Point = new Vector3F(1, 2, 0), Interpolation = SplineInterpolation.CatmullRom, }); curve.PreLoop = CurveLoopType.Constant; curve.PostLoop = CurveLoopType.Constant; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); curve.PreLoop = CurveLoopType.Linear; curve.PostLoop = CurveLoopType.Linear; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); curve.PreLoop = CurveLoopType.Cycle; curve.PostLoop = CurveLoopType.Cycle; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); curve.PreLoop = CurveLoopType.CycleOffset; curve.PostLoop = CurveLoopType.CycleOffset; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); curve.PreLoop = CurveLoopType.Oscillate; curve.PostLoop = CurveLoopType.Oscillate; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); // Test Hermite curves with 1 point curve = new Path3F(); curve.Add(new PathKey3F() { Parameter = 1, Point = new Vector3F(1, 2, 0), Interpolation = SplineInterpolation.Hermite, TangentIn = new Vector3F(2, -2, 0), TangentOut = new Vector3F(2, 2, 0), }); curve.PreLoop = CurveLoopType.Constant; curve.PostLoop = CurveLoopType.Constant; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 20, 0.01f)); curve.PreLoop = CurveLoopType.Constant; curve.PostLoop = CurveLoopType.Linear; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(3, 4, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(2, 2, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(2, 2, 0), curve.GetTangent(2)); Assert.IsTrue(Numeric.AreEqual(new Vector3F(2, 2, 0).Length, curve.GetLength(0, 2, 10, 0.01f), 0.1f)); curve.PreLoop = CurveLoopType.Linear; curve.PostLoop = CurveLoopType.Constant; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(-1, 4, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(2, -2, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(2, -2, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.IsTrue(Numeric.AreEqual(new Vector3F(2, 2, 0).Length, curve.GetLength(0, 2, 10, 0.01f), 0.1f)); curve.PreLoop = CurveLoopType.Linear; curve.PostLoop = CurveLoopType.Linear; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(-1, 4, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(3, 4, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(2, -2, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(2, 2, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(2, 2, 0), curve.GetTangent(2)); Assert.IsTrue(Numeric.AreEqual(new Vector3F(4, 4, 0).Length, curve.GetLength(0, 2, 10, 0.01f), 0.1f)); curve.PreLoop = CurveLoopType.Cycle; curve.PostLoop = CurveLoopType.Cycle; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); curve.PreLoop = CurveLoopType.CycleOffset; curve.PostLoop = CurveLoopType.CycleOffset; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); curve.PreLoop = CurveLoopType.Oscillate; curve.PostLoop = CurveLoopType.Oscillate; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); // Test Bezier curves with 1 point curve = new Path3F(); curve.Add(new PathKey3F() { Parameter = 1, Point = new Vector3F(1, 2, 0), Interpolation = SplineInterpolation.Bezier, TangentIn = new Vector3F(1, 2, 0) - new Vector3F(2, -2, 0) / 3, TangentOut = new Vector3F(1, 2, 0) + new Vector3F(2, 2, 0) / 3, }); curve.PreLoop = CurveLoopType.Constant; curve.PostLoop = CurveLoopType.Constant; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); curve.PreLoop = CurveLoopType.Constant; curve.PostLoop = CurveLoopType.Linear; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(3, 4, 0), curve.GetPoint(2))); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(2, 2, 0), curve.GetTangent(1))); Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(2, 2, 0), curve.GetTangent(2))); Assert.IsTrue(Numeric.AreEqual(new Vector3F(2, 2, 0).Length, curve.GetLength(0, 2, 10, 0.01f), 0.1f)); curve.PreLoop = CurveLoopType.Linear; curve.PostLoop = CurveLoopType.Constant; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(-1, 4, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(2, -2, 0), curve.GetTangent(0))); Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(2, -2, 0), curve.GetTangent(1))); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.IsTrue(Numeric.AreEqual(new Vector3F(2, 2, 0).Length, curve.GetLength(0, 2, 10, 0.01f), 0.1f)); curve.PreLoop = CurveLoopType.Linear; curve.PostLoop = CurveLoopType.Linear; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(-1, 4, 0), curve.GetPoint(0)); Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(3, 4, 0), curve.GetPoint(2))); Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(2, -2, 0), curve.GetTangent(0))); Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(2, 2, 0), curve.GetTangent(1))); Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(2, 2, 0), curve.GetTangent(2))); Assert.IsTrue(Numeric.AreEqual(new Vector3F(4, 4, 0).Length, curve.GetLength(0, 2, 10, 0.01f), 0.1f)); curve.PreLoop = CurveLoopType.Cycle; curve.PostLoop = CurveLoopType.Cycle; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); curve.PreLoop = CurveLoopType.CycleOffset; curve.PostLoop = CurveLoopType.CycleOffset; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); curve.PreLoop = CurveLoopType.Oscillate; curve.PostLoop = CurveLoopType.Oscillate; Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(1)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(0)); Assert.AreEqual(new Vector3F(1, 2, 0), curve.GetPoint(2)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(0)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(1)); Assert.AreEqual(new Vector3F(0, 0, 0), curve.GetTangent(2)); Assert.AreEqual(0, curve.GetLength(0, 2, 10, 0.01f)); }
public void GetTangentShouldReturnZeroIfPathIsEmpty() { Path3F empty = new Path3F(); empty.Sort(); Assert.AreEqual(Vector3F.Zero, empty.GetTangent(-0.5f)); Assert.AreEqual(Vector3F.Zero, empty.GetTangent(0)); Assert.AreEqual(Vector3F.Zero, empty.GetTangent(0.5f)); }
public void GetTangent() { Path3F path = CreatePath(); path.PreLoop = CurveLoopType.Constant; path.PostLoop = CurveLoopType.Oscillate; Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(0, 0, 0), path.GetTangent(-10))); Assert.IsTrue(Vector3F.AreNumericallyEqual((new Vector3F(1, 2, 3) - new Vector3F(0, 0, 1)) / 2, path.GetTangent(10))); Assert.IsTrue(Vector3F.AreNumericallyEqual((new Vector3F(1, 2, 3) - new Vector3F(0, 0, 1)) / 2, path.GetTangent(11.5f))); Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(0, 0, 0), path.GetTangent(16))); Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(0, 0, 0), path.GetTangent(85))); CatmullRomSegment3F catmullOscillate = new CatmullRomSegment3F() { Point1 = new Vector3F(10, 12, 14), Point2 = new Vector3F(10, 14, 8), Point3 = new Vector3F(20, 14, 8), Point4 = new Vector3F(30, 14, 8), }; Assert.IsTrue(Vector3F.AreNumericallyEqual(catmullOscillate.GetTangent(0.3f) / 10.0f, path.GetTangent(43))); Assert.IsTrue(Vector3F.AreNumericallyEqual(-catmullOscillate.GetTangent(0.7f) / 10.0f, path.GetTangent(53))); path.PreLoop = CurveLoopType.Linear; path.PostLoop = CurveLoopType.Cycle; Assert.IsTrue(Vector3F.AreNumericallyEqual((new Vector3F(1, 2, 3) - new Vector3F(0, 0, 1)) / 2, path.GetTangent(0))); path.PreLoop = CurveLoopType.Cycle; path.PostLoop = CurveLoopType.CycleOffset; Assert.IsTrue(Vector3F.AreNumericallyEqual(catmullOscillate.GetTangent(0.4f) / 10.0f, path.GetTangent(-36))); Assert.IsTrue(Vector3F.AreNumericallyEqual(catmullOscillate.GetTangent(0.4f) / 10.0f, path.GetTangent(4))); Assert.IsTrue(Vector3F.AreNumericallyEqual(catmullOscillate.GetTangent(0.3f) / 10.0f, path.GetTangent(83))); path.PreLoop = CurveLoopType.CycleOffset; path.PostLoop = CurveLoopType.Linear; Assert.IsTrue(Vector3F.AreNumericallyEqual(catmullOscillate.GetTangent(1f) / 10.0f, path.GetTangent(434))); path.PreLoop = CurveLoopType.Oscillate; path.PostLoop = CurveLoopType.Constant; path = new Path3F(); path.Add(new PathKey3F() { Parameter = 25, Point = new Vector3F(6, 7, 14), Interpolation = SplineInterpolation.Bezier, TangentIn = new Vector3F(5, 6, 13), TangentOut = new Vector3F(7, 8, 15), }); path.Add(new PathKey3F() { Parameter = 35, Point = new Vector3F(10, 12, 14), Interpolation = SplineInterpolation.Hermite, TangentIn = new Vector3F(1, 0, 0), TangentOut = new Vector3F(1, 0, 0), }); path.PreLoop = CurveLoopType.Linear; path.PostLoop = CurveLoopType.Linear; float Δu = path[1].Parameter - path[0].Parameter; Assert.IsTrue(Vector3F.AreNumericallyEqual((new Vector3F(6, 7, 14) - new Vector3F(5, 6, 13)) * 3 / Δu, path.GetTangent(0))); Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(1, 0, 0) / Δu, path.GetTangent(100))); path[1].Parameter = 25; path[0].Parameter = 35; path.Sort(); Δu = path[1].Parameter - path[0].Parameter; Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(1, 0, 0) / Δu, path.GetTangent(0))); Assert.IsTrue(Vector3F.AreNumericallyEqual((new Vector3F(7, 8, 15) - new Vector3F(6, 7, 14)) * 3 / Δu, path.GetTangent(100))); path.Add(new PathKey3F() { Parameter = 15, Point = new Vector3F(0, 0, 0), Interpolation = SplineInterpolation.BSpline, }); path.Sort(); }