Exemple #1
0
        // Add a random path.
        private void CreateRandomPath()
        {
            var path  = new Path3F();
            var point = new Vector3F(0, 0, 0);

            path.Add(new PathKey3F
            {
                Interpolation = SplineInterpolation.CatmullRom,
                Parameter     = 0,
                Point         = point
            });
            for (int i = 1; i < 10; i++)
            {
                point += RandomHelper.Random.NextQuaternionF().Rotate(new Vector3F(0, 0.5f, 0));
                path.Add(new PathKey3F
                {
                    Interpolation = SplineInterpolation.CatmullRom,
                    Parameter     = i,
                    Point         = point
                });
            }
            var pathFigure = new PathFigure3F();

            pathFigure.Segments.Add(path);

            var pathLineNode = new FigureNode(pathFigure)
            {
                Name              = "RandomPath",
                PoseLocal         = new Pose(new Vector3F(4, 1, 2)),
                StrokeThickness   = 3,
                StrokeColor       = new Vector3F(0.5f, 0.3f, 1),
                StrokeAlpha       = 1f,
                DashInWorldSpace  = true,
                StrokeDashPattern = new Vector4F(10, 1, 1, 1) / 100,
            };

            _scene.Children.Add(pathLineNode);
        }
        private Path3F CreatePath()
        {
            Path3F path = new Path3F();

            path.Add(new PathKey3F()
            {
                Parameter     = 10,
                Point         = new Vector3(1, 2, 3),
                Interpolation = SplineInterpolation.StepLeft,
                TangentIn     = new Vector3(1, 0, 0),
                TangentOut    = new Vector3(1, 0, 0),
            });
            path.Add(new PathKey3F()
            {
                Parameter     = 15,
                Point         = new Vector3(4, 5, 7),
                Interpolation = SplineInterpolation.StepCentered,
                TangentIn     = new Vector3(1, 0, 0),
                TangentOut    = new Vector3(1, 0, 0),
            });
            path.Add(new PathKey3F()
            {
                Parameter     = 18,
                Point         = new Vector3(5, 7, 10),
                Interpolation = SplineInterpolation.StepRight,
                TangentIn     = new Vector3(1, 0, 0),
                TangentOut    = new Vector3(1, 0, 0),
            });
            path.Add(new PathKey3F()
            {
                Parameter     = 20,
                Point         = new Vector3(5, 7, 13),
                Interpolation = SplineInterpolation.Linear,
                TangentIn     = new Vector3(1, 0, 0),
                TangentOut    = new Vector3(1, 0, 0),
            });
            path.Add(new PathKey3F()
            {
                Parameter     = 25,
                Point         = new Vector3(6, 7, 14),
                Interpolation = SplineInterpolation.Bezier,
                TangentIn     = new Vector3(5, 6, 13),
                TangentOut    = new Vector3(7, 8, 15),
            });
            path.Add(new PathKey3F()
            {
                Parameter     = 31,
                Point         = new Vector3(8, 10, 16),
                Interpolation = SplineInterpolation.BSpline,
                TangentIn     = new Vector3(1, 0, 0),
                TangentOut    = new Vector3(1, 0, 0),
            });
            path.Add(new PathKey3F()
            {
                Parameter     = 35,
                Point         = new Vector3(10, 12, 14),
                Interpolation = SplineInterpolation.Hermite,
                TangentIn     = new Vector3(1, 0, 0),
                TangentOut    = new Vector3(1, 0, 0),
            });
            path.Add(new PathKey3F()
            {
                Parameter     = 40,
                Point         = new Vector3(10, 14, 8),
                Interpolation = SplineInterpolation.CatmullRom,
                TangentIn     = new Vector3(1, 0, 0),
                TangentOut    = new Vector3(1, 0, 0),
            });
            return(path);
        }
Exemple #3
0
        private void CreatePath()
        {
            // Create a cyclic path. (More information on paths can be found in the DigitalRune
            // Mathematics documentation and related samples.)
            _path = new Path3F
            {
                SmoothEnds = true,
                PreLoop    = CurveLoopType.Cycle,
                PostLoop   = CurveLoopType.Cycle
            };

            // The curvature of the path is defined by a number of path keys.
            _path.Add(new PathKey3F
            {
                Parameter     = 0,                              // The path parameter defines position of the path key on the curve.
                Point         = new Vector3(-4, 0.5f, -3),      // The world space position of the path key.
                Interpolation = SplineInterpolation.CatmullRom, // The type of interpolation that is used between this path key and the next.
            });
            _path.Add(new PathKey3F
            {
                Parameter     = 1,
                Point         = new Vector3(-1, 0.5f, -5),
                Interpolation = SplineInterpolation.CatmullRom,
            });
            _path.Add(new PathKey3F
            {
                Parameter     = 2,
                Point         = new Vector3(3, 0.5f, -4),
                Interpolation = SplineInterpolation.CatmullRom,
            });
            _path.Add(new PathKey3F
            {
                Parameter     = 3,
                Point         = new Vector3(0, 0.5f, 0),
                Interpolation = SplineInterpolation.CatmullRom,
            });
            _path.Add(new PathKey3F
            {
                Parameter     = 4,
                Point         = new Vector3(-3, 0.5f, 3),
                Interpolation = SplineInterpolation.CatmullRom,
            });
            _path.Add(new PathKey3F
            {
                Parameter     = 5,
                Point         = new Vector3(-1, 0.5f, 5),
                Interpolation = SplineInterpolation.CatmullRom,
            });
            _path.Add(new PathKey3F
            {
                Parameter     = 6,
                Point         = new Vector3(0, 0.5f, 0),
                Interpolation = SplineInterpolation.CatmullRom,
            });

            // The last key uses the same position as the first key to create a closed path.
            PathKey3F lastKey = new PathKey3F
            {
                Parameter     = _path.Count,
                Point         = _path[0].Point,
                Interpolation = SplineInterpolation.CatmullRom,
            };

            _path.Add(lastKey);

            // The current path parameter goes from 0 to 7. This path parameter is not linearly
            // proportional to the path length. This is not suitable for animations.
            // To move an object with constant speed along a path, the path parameter should
            // be linearly proportional to the length of the path.
            // ParameterizeByLength() changes the path parameter so that the path parameter
            // at the each key is equal to the length of path (measured from the first key position
            // to the current key position).
            // ParameterizeByLength() uses an iterative process, we end the process after 10
            // iterations or when the error is less than 0.01f.
            _path.ParameterizeByLength(10, 0.01f);

            // Sample the path for rendering.
            int   numberOfSamples = _pointList.Length - 1;
            float pathLength      = _path.Last().Parameter;

            for (int i = 0; i <= numberOfSamples; i++)
            {
                Vector3 pointOnPath = _path.GetPoint(pathLength / numberOfSamples * i);
                _pointList[i] = pointOnPath;
            }
        }
Exemple #4
0
        private void CreateRoad()
        {
            //RandomHelper.Random = new Random(1234567);

            // Set isClosed to true join the start and the end of the road.
            bool isClosed = false;

            // Create a new TerrainRoadLayer which paints a road onto the terrain.
            // The road itself is defined by a mesh which is set later.
            _roadLayer = new TerrainRoadLayer(GraphicsService)
            {
                DiffuseColor    = new Vector3(0.5f),
                SpecularColor   = new Vector3(1),
                DiffuseTexture  = ContentManager.Load <Texture2D>("Terrain/Road-Asphalt-Diffuse"),
                NormalTexture   = ContentManager.Load <Texture2D>("Terrain/Road-Asphalt-Normal"),
                SpecularTexture = ContentManager.Load <Texture2D>("Terrain/Road-Asphalt-Specular"),
                HeightTexture   = ContentManager.Load <Texture2D>("Terrain/Road-Asphalt-Height"),

                // The size of the tileable detail textures in world space units.
                TileSize = 5,

                // The border blend range controls how the border of the road fades out.
                // We fade out 5% of the texture on each side of the road.
                BorderBlendRange = new Vector4(0.05f, 0.05f, 0.05f, 0.05f),
            };

            // Create 3D spline path with some semi-random control points.
            _roadPath = new Path3F
            {
                PreLoop    = isClosed ? CurveLoopType.Cycle : CurveLoopType.Linear,
                PostLoop   = isClosed ? CurveLoopType.Cycle : CurveLoopType.Linear,
                SmoothEnds = isClosed,
            };

            // The position of the next path key.
            Vector3 position = new Vector3(
                RandomHelper.Random.NextFloat(-20, 20),
                0,
                RandomHelper.Random.NextFloat(-20, 20));

            // The direction to the next path key.
            Vector3 direction = Quaternion.CreateRotationY(RandomHelper.Random.NextFloat(0, 10)).Rotate(Vector3.Forward);

            // Add path keys.
            for (int j = 0; j < 10; j++)
            {
                // Instead of a normal PathKey3F, we use a TerrainRoadPathKey which allows to control
                // the road with and the side falloff.
                var key = new TerrainRoadPathKey
                {
                    Interpolation = SplineInterpolation.CatmullRom,
                    Parameter     = j,
                    Point         = position,

                    // The width of the road at the path key.
                    Width = RandomHelper.Random.NextFloat(6, 10),

                    // The side falloff (which is used in ClampTerrainToRoad to blend the height values with
                    // the road).
                    SideFalloff = RandomHelper.Random.NextFloat(20, 40),
                };

                _roadPath.Add(key);

                // Get next random position and direction.
                position   += direction * RandomHelper.Random.NextFloat(20, 40);
                position.Y += RandomHelper.Random.NextFloat(-2, 2);
                direction   = Quaternion.CreateRotationY(RandomHelper.Random.NextFloat(-1, 1))
                              .Rotate(direction);
            }

            if (isClosed)
            {
                // To create a closed path the first and the last key should be identical.
                _roadPath[_roadPath.Count - 1].Point = _roadPath[0].Point;
                ((TerrainRoadPathKey)_roadPath[_roadPath.Count - 1]).Width       = ((TerrainRoadPathKey)_roadPath[0]).Width;
                ((TerrainRoadPathKey)_roadPath[_roadPath.Count - 1]).SideFalloff =
                    ((TerrainRoadPathKey)_roadPath[0]).SideFalloff;

                // Since the path is closed we do not have to fade out the start and the end of the road.
                _roadLayer.BorderBlendRange *= new Vector4(1, 0, 1, 0);
            }

            // Convert the path to a mesh.
            Submesh roadSubmesh;
            Aabb    roadAabb;
            float   roadLength;

            TerrainRoadLayer.CreateMesh(
                GraphicsService.GraphicsDevice,
                _roadPath,
                4,
                10,
                0.1f,
                out roadSubmesh,
                out roadAabb,
                out roadLength);

            // Set the mesh in the road layer.
            _roadLayer.SetMesh(roadSubmesh, roadAabb, roadLength, true);

            if (isClosed)
            {
                // When the path is closed, the end texture and the start texture coordinates should
                // match. This is the case if (roadLength / tileSize) is an integer.
                var numberOfTiles = (int)(roadLength / _roadLayer.TileSize);
                _roadLayer.TileSize = roadLength / numberOfTiles;
            }

            // The road layer is added to the layers of a tile. We have to add the road to each terrain
            // tile which it overlaps.
            foreach (var tile in _terrainObject.TerrainNode.Terrain.Tiles)
            {
                if (GeometryHelper.HaveContact(tile.Aabb, _roadLayer.Aabb.Value))
                {
                    tile.Layers.Add(_roadLayer);
                }
            }
        }
Exemple #5
0
 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;
 }
Exemple #6
0
        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();
        }
Exemple #7
0
        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));
        }
Exemple #8
0
        public void GetParameterByLength()
        {
            Path3F empty = new Path3F();
              empty.ParameterizeByLength(20, 0.001f); // No exception, do nothing.
              Assert.IsTrue(float.IsNaN(empty.GetParameterFromLength(10, 20, 0.1f)));

              Path3F path = CreatePath();
              path.ParameterizeByLength(20, 0.001f);

              Assert.AreEqual(0, path.GetParameterFromLength(0, 20, 0.001f));
              Assert.AreEqual(3, path.GetParameterFromLength(3, 20, 0.001f));
              Assert.AreEqual(path[4].Parameter, path.GetParameterFromLength(path[4].Parameter, 20, 0.01f));
              Assert.AreEqual(path[5].Parameter, path.GetParameterFromLength(path[5].Parameter, 20, 0.01f));
              Assert.AreEqual(path[6].Parameter, path.GetParameterFromLength(path[6].Parameter, 20, 0.01f));
              Assert.AreEqual(path[7].Parameter, path.GetParameterFromLength(path[7].Parameter, 20, 0.01f));
              Assert.AreEqual(path[8].Parameter, path.GetParameterFromLength(path[8].Parameter, 20, 0.01f));
              Assert.AreEqual(path[9].Parameter, path.GetParameterFromLength(path[9].Parameter, 20, 0.01f));

              float pathLength = path[9].Parameter;

              float desiredLength = 11;
              float actualLength = path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.01f), 20, 0.01f);
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.01f));

              desiredLength = 26;
              actualLength = path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.01f), 20, 0.01f);
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.01f));

              desiredLength = 33.5f;
              actualLength = path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.001f), 20, 0.001f);
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.01f));

              path.PreLoop = CurveLoopType.Linear;
              path.PostLoop = CurveLoopType.Linear;
              desiredLength = 60;
              actualLength = path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.001f), 20, 0.001f);
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.1f));

              desiredLength = -10f;
              actualLength = -path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.001f), 20, 0.001f);
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.01f));

              path.PreLoop = CurveLoopType.CycleOffset;
              path.PostLoop = CurveLoopType.CycleOffset;
              path.ParameterizeByLength(20, 0.001f);
              desiredLength = -90;
              actualLength = -path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.01f), 20, 0.01f);
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.1f));
              desiredLength = -50;
              actualLength = -path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.01f), 20, 0.01f);
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.1f));
              desiredLength = -30;
              actualLength = -path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.01f), 20, 0.01f);
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.1f));
              desiredLength = 50;
              actualLength = path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.01f), 20, 0.01f);
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.1f));
              desiredLength = 100;
              actualLength = path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.01f), 20, 0.01f);
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.1f));
              desiredLength = 130;
              actualLength = path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.01f), 20, 0.01f);
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.1f));
              desiredLength = 200;
              actualLength = path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.01f), 20, 0.01f);
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.1f));

              path.PreLoop = CurveLoopType.Oscillate;
              path.PostLoop = CurveLoopType.Cycle;
              path.ParameterizeByLength(20, 0.001f);
              desiredLength = -110;
              actualLength = -path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.01f), 20, 0.01f);
              Assert.IsTrue(-3 * pathLength < path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(-2 * pathLength > path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.1f));
              desiredLength = -50;
              actualLength = -path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.01f), 20, 0.01f);
              Assert.IsTrue(-2 * pathLength < path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(-1 * pathLength > path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.1f));
              desiredLength = -30;
              actualLength = -path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.01f), 20, 0.01f);
              Assert.IsTrue(-1 * pathLength < path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(0 > path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.1f));
              desiredLength = 50;
              actualLength = path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.01f), 20, 0.01f);
              Assert.IsTrue(1 * pathLength < path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(2 * pathLength > path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.1f));
              desiredLength = 110;
              actualLength = path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.01f), 20, 0.01f);
              Assert.IsTrue(2 * pathLength < path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(3 * pathLength > path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.1f));
              desiredLength = 130;
              actualLength = path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.01f), 20, 0.01f);
              Assert.IsTrue(3 * pathLength < path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(4 * pathLength > path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.1f));
              desiredLength = 190;
              actualLength = path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.01f), 20, 0.01f);
              Assert.IsTrue(4 * pathLength < path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(5 * pathLength > path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.2f));

              path.PreLoop = CurveLoopType.Cycle;
              path.PostLoop = CurveLoopType.Oscillate;
              path.ParameterizeByLength(20, 0.001f);
              desiredLength = -90;
              actualLength = -path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.01f), 20, 0.01f);
              Assert.IsTrue(-3 * pathLength < path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(-2 * pathLength > path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.1f));
              desiredLength = -50;
              actualLength = -path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.01f), 20, 0.01f);
              Assert.IsTrue(-2 * pathLength < path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(-1 * pathLength > path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.1f));
              desiredLength = -30;
              actualLength = -path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.01f), 20, 0.01f);
              Assert.IsTrue(-1 * pathLength < path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(0 > path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.1f));
              desiredLength = 50;
              actualLength = path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.01f), 20, 0.01f);
              Assert.IsTrue(pathLength < path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(2 * pathLength > path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.1f));
              desiredLength = 110;
              actualLength = path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.01f), 20, 0.01f);
              Assert.IsTrue(2 * pathLength < path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(3 * pathLength > path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.1f));
              desiredLength = 130;
              actualLength = path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.01f), 20, 0.01f);
              Assert.IsTrue(3 * pathLength < path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(4 * pathLength > path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.1f));
              desiredLength = 210;
              actualLength = path.GetLength(0, path.GetParameterFromLength(desiredLength, 20, 0.01f), 20, 0.01f);
              Assert.IsTrue(5 * pathLength < path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(6 * pathLength > path.GetParameterFromLength(desiredLength, 20, 0.01f));
              Assert.IsTrue(Numeric.AreEqual(desiredLength, actualLength, 0.1f));

              // Test path with zero length.
              path = new Path3F();
              path.Add(new PathKey3F()
              {
            Parameter = 10,
            Point = new Vector3F(0, 0, 1),
            Interpolation = SplineInterpolation.Linear,
            TangentIn = new Vector3F(1, 0, 0),
            TangentOut = new Vector3F(1, 0, 0),
              });
              path.ParameterizeByLength(20, 0.001f);
              Assert.AreEqual(0, path.GetParameterFromLength(0, 20, 0.1f));
              path.Add(new PathKey3F()
              {
            Parameter = 20,
            Point = new Vector3F(0, 0, 1),
            Interpolation = SplineInterpolation.Linear,
            TangentIn = new Vector3F(1, 0, 0),
            TangentOut = new Vector3F(1, 0, 0),
              });
              path.ParameterizeByLength(20, 0.001f);
              Assert.AreEqual(0, path.GetParameterFromLength(0, 20, 0.1f));
        }
Exemple #9
0
 private Path3F CreatePath()
 {
     Path3F path = new Path3F();
       path.Add(new PathKey3F()
       {
     Parameter = 10,
     Point = new Vector3F(0, 0, 1),
     Interpolation = SplineInterpolation.Linear,
     TangentIn = new Vector3F(1, 0, 0),
     TangentOut = new Vector3F(1, 0, 0),
       });
       path.Add(new PathKey3F()
       {
     Parameter = 12,
     Point = new Vector3F(1, 2, 3),
     Interpolation = SplineInterpolation.StepLeft,
     TangentIn = new Vector3F(1, 0, 0),
     TangentOut = new Vector3F(1, 0, 0),
       });
       path.Add(new PathKey3F()
       {
     Parameter = 15,
     Point = new Vector3F(4, 5, 7),
     Interpolation = SplineInterpolation.StepCentered,
     TangentIn = new Vector3F(1, 0, 0),
     TangentOut = new Vector3F(1, 0, 0),
       });
       path.Add(new PathKey3F()
       {
     Parameter = 18,
     Point = new Vector3F(5, 7, 10),
     Interpolation = SplineInterpolation.StepRight,
     TangentIn = new Vector3F(1, 0, 0),
     TangentOut = new Vector3F(1, 0, 0),
       });
       path.Add(new PathKey3F()
       {
     Parameter = 20,
     Point = new Vector3F(5, 7, 13),
     Interpolation = SplineInterpolation.Linear,
     TangentIn = new Vector3F(1, 0, 0),
     TangentOut = new Vector3F(1, 0, 0),
       });
       path.Add(new PathKey3F()
       {
     Parameter = 31,
     Point = new Vector3F(8, 10, 16),
     Interpolation = SplineInterpolation.BSpline,
     TangentIn = new Vector3F(1, 0, 0),
     TangentOut = new Vector3F(1, 0, 0),
       });
       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.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 = 40,
     Point = new Vector3F(10, 14, 8),
     Interpolation = SplineInterpolation.CatmullRom,
     TangentIn = new Vector3F(1, 0, 0),
     TangentOut = new Vector3F(1, 0, 0),
       });
       path.Add(new PathKey3F()
       {
     Parameter = 50,
     Point = new Vector3F(20, 14, 8),
     Interpolation = SplineInterpolation.CatmullRom,
     TangentIn = new Vector3F(1, 0, 0),
     TangentOut = new Vector3F(1, 0, 0),
       });
       path.Sort();
       return path;
 }
Exemple #10
0
        // Creates a random 3D path.
        private void CreatePath()
        {
            // Create a cyclic path.
            _path = new Path3F
            {
                PreLoop    = CurveLoopType.Cycle,
                PostLoop   = CurveLoopType.Cycle,
                SmoothEnds = true
            };

            // Add random path key points.
            for (int i = 0; i < 5; i++)
            {
                float x   = RandomHelper.Random.NextFloat(-3, 3);
                float y   = RandomHelper.Random.NextFloat(1, 3);
                float z   = RandomHelper.Random.NextFloat(-3, 0);
                var   key = new PathKey3F
                {
                    Parameter     = i,
                    Point         = new Vector3F(x, y, z),
                    Interpolation = SplineInterpolation.CatmullRom
                };
                _path.Add(key);
            }

            // The last key uses the same position as the first key to create a closed path.
            var lastKey = new PathKey3F
            {
                Parameter     = _path.Count,
                Point         = _path[0].Point,
                Interpolation = SplineInterpolation.CatmullRom,
            };

            _path.Add(lastKey);

            // The current path parameter goes from 0 to 5. This path parameter is not linearly
            // proportional to the path length. This is not suitable for animations.
            // To move an object with constant speed along the path, the path parameter should
            // be linearly proportional to the length of the path.
            // ParameterizeByLength() changes the path parameter so that the path parameter
            // at the each key is equal to the length of path (measured from the first key position
            // to the current key position).
            // ParameterizeByLength() uses and iterative process, we end the process after 10
            // iterations or when the error is less than 0.001f.
            _path.ParameterizeByLength(10, 0.001f);

            // Now, the parameter of the first key (_path[0]) is unchanged.
            // The parameter of the second key (_path[1]) is equal to the length of the path
            // from the first key to the second key.
            // The parameter of the third key (_path[2]) is equal to the length of the path
            // from the first key to the third key.
            // And so on.

            // The parameter of the last key is equal to the length of the whole path:
            //   float pathLength = _path[_path.Count - 1].Parameter;

            // Important: The path parameter is now equal to the path length at the path keys.
            // But in general between path keys the path parameter is not linearly proportional
            // to the path length. This is due to the nature of splines.
            //
            // Example:
            // Lets assume the second path key is at path length 100 and the third key is
            // at path length 200.
            // If we call _path.GetPoint(100), we get the position of the second key.
            // If we call _path.GetPoint(200), we get the position ot the third key.
            // We can call _path.GetPoint(130) to get a position on the path between the second and
            // third key. But it is not guaranteed that the path is exactly 130 long at this position.
            // We only know that the point is somewhere between 100 and 200 path length.
            //
            // To get the path point at exactly the distance 130 from the path start, we have to call
            //   float parameter = _path.GetParameterFromLength(130, 10, 0.01f);
            // This uses an iterative root finding process to find the path parameter where the
            // path length is 130.
            // Then we can get the path position with
            //   Vector3F pathPointAt130Length = _path.GetPoint(parameter).
        }
Exemple #11
0
    // Add a random path.
    private void CreateRandomPath()
    {
      var path = new Path3F();
      var point = new Vector3F(0, 0, 0);
      path.Add(new PathKey3F
      {
        Interpolation = SplineInterpolation.CatmullRom,
        Parameter = 0,
        Point = point
      });
      for (int i = 1; i < 10; i++)
      {
        point += RandomHelper.Random.NextQuaternionF().Rotate(new Vector3F(0, 0.5f, 0));
        path.Add(new PathKey3F
        {
          Interpolation = SplineInterpolation.CatmullRom,
          Parameter = i,
          Point = point
        });
      }
      var pathFigure = new PathFigure3F();
      pathFigure.Segments.Add(path);

      var pathLineNode = new FigureNode(pathFigure)
      {
        Name = "RandomPath",
        PoseLocal = new Pose(new Vector3F(4, 1, 2)),
        StrokeThickness = 3,
        StrokeColor = new Vector3F(0.5f, 0.3f, 1),
        StrokeAlpha = 1f,
        DashInWorldSpace = true,
        StrokeDashPattern = new Vector4F(10, 1, 1, 1) / 100,
      };
      _scene.Children.Add(pathLineNode);
    }
Exemple #12
0
    private void CreateRoad()
    {
      //RandomHelper.Random = new Random(1234567);

      // Set isClosed to true join the start and the end of the road.
      bool isClosed = false;

      // Create a new TerrainRoadLayer which paints a road onto the terrain.
      // The road itself is defined by a mesh which is set later.
      _roadLayer = new TerrainRoadLayer(GraphicsService)
      {
        DiffuseColor = new Vector3F(0.5f),
        SpecularColor = new Vector3F(1),
        DiffuseTexture = ContentManager.Load<Texture2D>("Terrain/Road-Asphalt-Diffuse"),
        NormalTexture = ContentManager.Load<Texture2D>("Terrain/Road-Asphalt-Normal"),
        SpecularTexture = ContentManager.Load<Texture2D>("Terrain/Road-Asphalt-Specular"),
        HeightTexture = ContentManager.Load<Texture2D>("Terrain/Road-Asphalt-Height"),

        // The size of the tileable detail textures in world space units.
        TileSize = 5,

        // The border blend range controls how the border of the road fades out.
        // We fade out 5% of the texture on each side of the road.
        BorderBlendRange = new Vector4F(0.05f, 0.05f, 0.05f, 0.05f),
      };

      // Create 3D spline path with some semi-random control points.
      _roadPath = new Path3F
      {
        PreLoop = isClosed ? CurveLoopType.Cycle : CurveLoopType.Linear,
        PostLoop = isClosed ? CurveLoopType.Cycle : CurveLoopType.Linear,
        SmoothEnds = isClosed,
      };

      // The position of the next path key.
      Vector3F position = new Vector3F(
        RandomHelper.Random.NextFloat(-20, 20),
        0,
        RandomHelper.Random.NextFloat(-20, 20));

      // The direction to the next path key.
      Vector3F direction = QuaternionF.CreateRotationY(RandomHelper.Random.NextFloat(0, 10)).Rotate(Vector3F.Forward);

      // Add path keys.
      for (int j = 0; j < 10; j++)
      {
        // Instead of a normal PathKey3F, we use a TerrainRoadPathKey which allows to control
        // the road with and the side falloff.
        var key = new TerrainRoadPathKey
        {
          Interpolation = SplineInterpolation.CatmullRom,
          Parameter = j,
          Point = position,

          // The width of the road at the path key.
          Width = RandomHelper.Random.NextFloat(6, 10),

          // The side falloff (which is used in ClampTerrainToRoad to blend the height values with
          // the road).
          SideFalloff = RandomHelper.Random.NextFloat(20, 40),
        };

        _roadPath.Add(key);

        // Get next random position and direction.
        position += direction * RandomHelper.Random.NextFloat(20, 40);
        position.Y += RandomHelper.Random.NextFloat(-2, 2);
        direction = QuaternionF.CreateRotationY(RandomHelper.Random.NextFloat(-1, 1))
                               .Rotate(direction);
      }

      if (isClosed)
      {
        // To create a closed path the first and the last key should be identical.
        _roadPath[_roadPath.Count - 1].Point = _roadPath[0].Point;
        ((TerrainRoadPathKey)_roadPath[_roadPath.Count - 1]).Width = ((TerrainRoadPathKey)_roadPath[0]).Width;
        ((TerrainRoadPathKey)_roadPath[_roadPath.Count - 1]).SideFalloff =
          ((TerrainRoadPathKey)_roadPath[0]).SideFalloff;

        // Since the path is closed we do not have to fade out the start and the end of the road.
        _roadLayer.BorderBlendRange *= new Vector4F(1, 0, 1, 0);
      }

      // Convert the path to a mesh.
      Submesh roadSubmesh;
      Aabb roadAabb;
      float roadLength;
      TerrainRoadLayer.CreateMesh(
        GraphicsService.GraphicsDevice,
        _roadPath,
        4,
        10,
        0.1f,
        out roadSubmesh,
        out roadAabb,
        out roadLength);

      // Set the mesh in the road layer.
      _roadLayer.SetMesh(roadSubmesh, roadAabb, roadLength, true);

      if (isClosed)
      {
        // When the path is closed, the end texture and the start texture coordinates should 
        // match. This is the case if (roadLength / tileSize) is an integer.
        var numberOfTiles = (int)(roadLength / _roadLayer.TileSize);
        _roadLayer.TileSize = roadLength / numberOfTiles;
      }

      // The road layer is added to the layers of a tile. We have to add the road to each terrain
      // tile which it overlaps.
      foreach (var tile in _terrainObject.TerrainNode.Terrain.Tiles)
        if (GeometryHelper.HaveContact(tile.Aabb, _roadLayer.Aabb.Value))
          tile.Layers.Add(_roadLayer);
    }
Exemple #13
0
    // Creates a random 3D path.
    private void CreatePath()
    {
      // Create a cyclic path.
      _path = new Path3F
      {
        PreLoop = CurveLoopType.Cycle,
        PostLoop = CurveLoopType.Cycle,
        SmoothEnds = true
      };

      // Add random path key points.
      for (int i = 0; i < 5; i++)
      {
        float x = RandomHelper.Random.NextFloat(-3, 3);
        float y = RandomHelper.Random.NextFloat(1, 3);
        float z = RandomHelper.Random.NextFloat(-3, 0);
        var key = new PathKey3F
        {
          Parameter = i,
          Point = new Vector3F(x, y, z),
          Interpolation = SplineInterpolation.CatmullRom
        };
        _path.Add(key);
      }

      // The last key uses the same position as the first key to create a closed path.
      var lastKey = new PathKey3F
      {
        Parameter = _path.Count,
        Point = _path[0].Point,
        Interpolation = SplineInterpolation.CatmullRom,
      };
      _path.Add(lastKey);

      // The current path parameter goes from 0 to 5. This path parameter is not linearly
      // proportional to the path length. This is not suitable for animations.
      // To move an object with constant speed along the path, the path parameter should
      // be linearly proportional to the length of the path.
      // ParameterizeByLength() changes the path parameter so that the path parameter
      // at the each key is equal to the length of path (measured from the first key position
      // to the current key position).
      // ParameterizeByLength() uses and iterative process, we end the process after 10 
      // iterations or when the error is less than 0.001f.
      _path.ParameterizeByLength(10, 0.001f);

      // Now, the parameter of the first key (_path[0]) is unchanged.
      // The parameter of the second key (_path[1]) is equal to the length of the path
      // from the first key to the second key.
      // The parameter of the third key (_path[2]) is equal to the length of the path
      // from the first key to the third key.
      // And so on. 

      // The parameter of the last key is equal to the length of the whole path:
      //   float pathLength = _path[_path.Count - 1].Parameter;

      // Important: The path parameter is now equal to the path length at the path keys.
      // But in general between path keys the path parameter is not linearly proportional
      // to the path length. This is due to the nature of splines.
      //
      // Example: 
      // Lets assume the second path key is at path length 100 and the third key is 
      // at path length 200.
      // If we call _path.GetPoint(100), we get the position of the second key.
      // If we call _path.GetPoint(200), we get the position ot the third key.
      // We can call _path.GetPoint(130) to get a position on the path between the second and
      // third key. But it is not guaranteed that the path is exactly 130 long at this position.
      // We only know that the point is somewhere between 100 and 200 path length.
      //
      // To get the path point at exactly the distance 130 from the path start, we have to call
      //   float parameter = _path.GetParameterFromLength(130, 10, 0.01f);
      // This uses an iterative root finding process to find the path parameter where the
      // path length is 130.
      // Then we can get the path position with 
      //   Vector3F pathPointAt130Length = _path.GetPoint(parameter).
    }
Exemple #14
0
    private void CreatePath()
    {
      // Create a cyclic path. (More information on paths can be found in the DigitalRune
      // Mathematics documentation and related samples.)
      _path = new Path3F
      {
        SmoothEnds = true,
        PreLoop = CurveLoopType.Cycle,
        PostLoop = CurveLoopType.Cycle
      };

      // The curvature of the path is defined by a number of path keys.
      _path.Add(new PathKey3F
      {
        Parameter = 0,                                  // The path parameter defines position of the path key on the curve.
        Point = new Vector3F(-4, 0.5f, -3),             // The world space position of the path key.
        Interpolation = SplineInterpolation.CatmullRom, // The type of interpolation that is used between this path key and the next.
      });
      _path.Add(new PathKey3F
      {
        Parameter = 1,
        Point = new Vector3F(-1, 0.5f, -5),
        Interpolation = SplineInterpolation.CatmullRom,
      });
      _path.Add(new PathKey3F
      {
        Parameter = 2,
        Point = new Vector3F(3, 0.5f, -4),
        Interpolation = SplineInterpolation.CatmullRom,
      });
      _path.Add(new PathKey3F
      {
        Parameter = 3,
        Point = new Vector3F(0, 0.5f, 0),
        Interpolation = SplineInterpolation.CatmullRom,
      });
      _path.Add(new PathKey3F
      {
        Parameter = 4,
        Point = new Vector3F(-3, 0.5f, 3),
        Interpolation = SplineInterpolation.CatmullRom,
      });
      _path.Add(new PathKey3F
      {
        Parameter = 5,
        Point = new Vector3F(-1, 0.5f, 5),
        Interpolation = SplineInterpolation.CatmullRom,
      });
      _path.Add(new PathKey3F
      {
        Parameter = 6,
        Point = new Vector3F(0, 0.5f, 0),
        Interpolation = SplineInterpolation.CatmullRom,
      });

      // The last key uses the same position as the first key to create a closed path.
      PathKey3F lastKey = new PathKey3F
      {
        Parameter = _path.Count,
        Point = _path[0].Point,
        Interpolation = SplineInterpolation.CatmullRom,
      };
      _path.Add(lastKey);

      // The current path parameter goes from 0 to 7. This path parameter is not linearly
      // proportional to the path length. This is not suitable for animations.
      // To move an object with constant speed along a path, the path parameter should
      // be linearly proportional to the length of the path.
      // ParameterizeByLength() changes the path parameter so that the path parameter
      // at the each key is equal to the length of path (measured from the first key position
      // to the current key position).
      // ParameterizeByLength() uses an iterative process, we end the process after 10 
      // iterations or when the error is less than 0.01f.
      _path.ParameterizeByLength(10, 0.01f);

      // Sample the path for rendering.
      int numberOfSamples = _pointList.Length - 1;
      float pathLength = _path.Last().Parameter;
      for (int i = 0; i <= numberOfSamples; i++)
      {
        Vector3F pointOnPath = _path.GetPoint(pathLength / numberOfSamples * i);
        _pointList[i] = pointOnPath;
      }
    }