/// <summary>
        /// Rescales a convex hull shape.
        /// </summary>
        /// <param name="shape">The shape.</param>
        /// <param name="scaleFactor">The scaling factor.</param>
        /// <returns>The new hull.</returns>
        public static ConvexHullShape Rescale(this ConvexHullShape shape, Vector3 scaleFactor)
        {
            ReadOnlyList <Vector3> verts   = shape.Vertices;
            List <Vector3>         newlist = new List <Vector3>(verts.Count);

            foreach (Vector3 vert in verts)
            {
                newlist.Add(vert * scaleFactor);
            }
            double        len       = scaleFactor.Length();
            RawList <int> triangles = CommonResources.GetIntList();

            ConvexHullHelper.GetConvexHull(newlist, triangles);
            InertiaHelper.ComputeShapeDistribution(newlist, triangles, out double volume, out Matrix3x3 volumeDistribution);
            ConvexShapeDescription csd = new ConvexShapeDescription()
            {
                CollisionMargin   = shape.CollisionMargin,
                EntityShapeVolume = new BEPUphysics.CollisionShapes.EntityShapeVolumeDescription()
                {
                    Volume             = volume,
                    VolumeDistribution = volumeDistribution
                },
                MaximumRadius = shape.MaximumRadius * len,
                MinimumRadius = shape.MinimumRadius * len
            };

            CommonResources.GiveBack(triangles);
            return(new ConvexHullShape(newlist, csd));
        }
Beispiel #2
0
        public override void Start()
        {
            ConvexShapeDescription desc = new ConvexShapeDescription
            {
                CollisionMargin = Margin
            };

            _shape = new BoxShape(HalfExtends.X, HalfExtends.Y, HalfExtends.Z, desc);
        }
Beispiel #3
0
        public static Model LoadConvexMesh(Scene scene, Device device)
        {
            var torusModel = ColladaLoader.Load(@"Resources\Torus.DAE", device);

            var core = scene.Core;

            // Allocate memory for the points and triangles
            var convexMeshDesc = new ConvexMeshDescription()
            {
                PointCount = torusModel.VertexPositions.Length
            };

            convexMeshDesc.Flags |= ConvexFlag.ComputeConvex;
            convexMeshDesc.AllocatePoints <Vector3>(torusModel.VertexPositions.Length);

            // Write in the points and triangles
            // We only want the Position component of the vertex. Also scale down the mesh.
            foreach (var vertex in torusModel.VertexPositions)
            {
                var t        = SlimDX.Matrix.Scaling(0.1f, 0.1f, 0.1f);
                var position = SlimDX.Vector3.TransformCoordinate(vertex, t);

                convexMeshDesc.PointsStream.Write(position);
            }

            //

            // Cook to memory or to a file
            ConvexMesh convexMesh;

            using (var stream = new MemoryStream())
            {
                //FileStream stream = new FileStream( @"Convex Mesh.cooked", FileMode.CreateNew );

                Cooking.InitializeCooking(new ConsoleOutputStream());
                Cooking.CookConvexMesh(convexMeshDesc, stream);
                Cooking.CloseCooking();

                stream.Position = 0;

                convexMesh = core.CreateConvexMesh(stream);
            }
            var convexShapeDesc = new ConvexShapeDescription(convexMesh);

            var actorDesc = new ActorDescription()
            {
                BodyDescription = new BodyDescription(10.0f),
                GlobalPose      = Matrix.Translation(30, 30, 0)
            };

            actorDesc.Shapes.Add(convexShapeDesc);

            var actor = scene.CreateActor(actorDesc);

            return(torusModel);
        }
        /// <summary>
        /// You can put a scale (-1) operation in the global pose, it works! (not for convex meshes though!)
        /// NOTE: WARNING: scaling not supported!!! (still not supported, it has been delayed for several reasons)
        /// </summary>
        /// <param name="data"></param>
        /// <param name="scene"></param>
        /// <param name="globalPose"></param>
        /// <returns></returns>
        private ActorDescription createActorDesc(MeshCollisionData data, StillDesign.PhysX.Scene scene, Matrix globalPose)
        {
            // From PhysX SDK:
            //There are some performance implications of compound shapes that the user should be aware of:
            //You should avoid static actors being compounds; there's a limit to the number of triangles allowed in one actor's mesh shapes and subshapes exceeding the limit will be ignored.
            //TODO: is this about triangle meshes only? EDIT: i dont think so



            // Pull scaling out of the transformation
            Vector3    scale, translation;
            Quaternion rotation;

            globalPose.Decompose(out scale, out rotation, out translation);

            //globalPose = Matrix.CreateFromQuaternion(rotation) * Matrix.CreateTranslation(translation);
            var scaleMat = Matrix.Identity;// Matrix.CreateScale(scale);


            ActorDescription actorDesc = new ActorDescription();

            for (int i = 0; i < data.Boxes.Count; i++)
            {
                var box   = data.Boxes[i];
                var shape = new BoxShapeDescription(box.Dimensions);
                shape.LocalPose = box.Orientation * scaleMat;
                actorDesc.Shapes.Add(shape);
            }

            for (int i = 0; i < data.ConvexMeshes.Count; i++)
            {
                var convex = data.ConvexMeshes[i];
                var shape  = new ConvexShapeDescription();
                shape.ConvexMesh = MeshPhysicsPool.CreateConvexMesh(scene, convex);

                shape.Flags = ShapeFlag.Visualization;
                actorDesc.Shapes.Add(shape);
            }



            if (data.TriangleMesh != null)
            {
                TriangleMesh triangleMesh;
                triangleMesh = MeshPhysicsPool.CreateTriangleMesh(scene, data.TriangleMesh);

                TriangleMeshShapeDescription shapeDesc = new TriangleMeshShapeDescription();
                shapeDesc.TriangleMesh = triangleMesh;
                shapeDesc.Flags        = ShapeFlag.Visualization; // Vizualization enabled, obviously (not obviously enabled, obvious that this enables visualization)

                actorDesc.Shapes.Add(shapeDesc);
            }

            actorDesc.GlobalPose = globalPose;
            return(actorDesc);
        }
Beispiel #5
0
		public static Model LoadConvexMesh(Scene scene, Device device)
		{
			var torusModel = ColladaLoader.Load(@"Resources\Torus.DAE", device);

			var core = scene.Core;

			// Allocate memory for the points and triangles
			var convexMeshDesc = new ConvexMeshDescription()
			{
				PointCount = torusModel.VertexPositions.Length
			};
			convexMeshDesc.Flags |= ConvexFlag.ComputeConvex;
			convexMeshDesc.AllocatePoints<Vector3>(torusModel.VertexPositions.Length);

			// Write in the points and triangles
			// We only want the Position component of the vertex. Also scale down the mesh.
			foreach (var vertex in torusModel.VertexPositions)
			{
				var t = SlimDX.Matrix.Scaling(0.1f, 0.1f, 0.1f);
				var position = SlimDX.Vector3.TransformCoordinate(vertex, t);

				convexMeshDesc.PointsStream.Write(position);
			}

			//

			// Cook to memory or to a file
			ConvexMesh convexMesh;
			using (var stream = new MemoryStream())
			{
				//FileStream stream = new FileStream( @"Convex Mesh.cooked", FileMode.CreateNew );

				Cooking.InitializeCooking(new ConsoleOutputStream());
				Cooking.CookConvexMesh(convexMeshDesc, stream);
				Cooking.CloseCooking();

				stream.Position = 0;

				convexMesh = core.CreateConvexMesh(stream);
			}
			var convexShapeDesc = new ConvexShapeDescription(convexMesh);

			var actorDesc = new ActorDescription()
			{
				BodyDescription = new BodyDescription(10.0f),
				GlobalPose = Matrix.Translation(30, 30, 0)
			};
			actorDesc.Shapes.Add(convexShapeDesc);

			var actor = scene.CreateActor(actorDesc);

			return torusModel;
		}
        /// <summary>
        /// Constructs a new demo.
        /// </summary>
        /// <param name="game">Game owning this demo.</param>
        public EntityConstructionDemo(DemosGame game)
            : base(game)
        {
            //An entity is the basic physical simulation object in BEPUphysics.  It represents a rigid body which can be dynamic or kinematic.
            //Dynamic objects can bounce around and respond to collisions using forces.  Kinematic entities can move using velocity,
            //but effectively have infinite inertia and do not respond to collisions or forces.

            //For each of the below constructors, there are multiple overloads.  Half have a mass parameter, half do not.  If a mass parameter is specified,
            //the object is created as a dynamic object.  If a mass parameter is not specified, it is created as a kinematic object.  This state can be changed later
            //by using the BecomeDynamic/BecomeKinematic methods.


            //************************
            //There are a variety of ways to construct entities depending on your needs.
            //The most common approach is to use the 'prefab' types, like the Box, Sphere, ConvexHull, Cylinder, and so on (BEPUphysics.Entities.Prefabs namespace).
            //These provide a short cut to constructing the objects and generally provide convenience accessors to shape properties.

            //We'll start with such an entity for the kinematic ground.  Notice how it allows the definition of position and shape data all in the constructor.
            //It has other overloads that allow you to specify a mass (for a dynamic object) or a full MotionState instead of just a position.
            Box ground = new Box(new Vector3(0, -.5f, 0), 50, 1, 50);

            Space.Add(ground);

            //If you examine the ground's CollisionInformation property, you'll find that it is a generic method which returns a ConvexCollidable<BoxShape>.
            //So, in addition to having convenience properties, it also lets you go deeper into the object's data by knowing what the types are.


            //************************
            //Let's go one level up the hierarchy to Entity<T>.  This is the superclass of all prefab types.
            //The generic parameter is the type of the Collidable that the entity uses as its collision proxy.
            //It is also what allows prefab types' CollisionInformation property to return that type rather than EntityCollidable.

            Space.Add(new Entity <ConvexCollidable <SphereShape> >(new ConvexCollidable <SphereShape>(new SphereShape(1)), 1)
            {
                Position = new Vector3(-10, 1, 0)
            });

            //That's a bit unwieldy<<>><>, but it works.  Directly constructing entities in this manner isn't common or generally necessary.
            //If you want to have a CollisionInformation property that returns a specific type but don't want to use a specific prefab type, this is the way to go.

            //Note that the constructor itself does not include any position/motion state parameters nor does it include any direct shape data.  The position and other auxiliary
            //properties can be set after it's been constructed.  In this case, object initializer syntax is used to set the Position.
            //The shape data is included within the first EntityCollidable parameter which defines the entity's collision proxy.
            //The prefab types discussed previously all create such EntityCollidables internally using the data passed into the constructor.


            //************************
            //So let's move onto something a little more convenient.  Entity<T> has a non-generic parent Entity.  It still has a CollisionInformation property,
            //but it returns an EntityCollidable rather than a specific type.

            Space.Add(new Entity(new BoxShape(2, 2, 2), 1)
            {
                Position = new Vector3(10, 1, 0)
            });

            //Much better! No more ugly generic type syntax pollution.  Notice that there are quite a few overloads in the Entity.
            //In addition to overloads that accept EntityCollidable instances (as used in the generic entity above), Entity provides constructors that
            //take shapes directly.  Internally, the entity can create its own EntityCollidable instance based on the shape.  This further simplifies the construction process.

            //An object initializer is once again used to set the position, since the constructors do not have all the convenience constructor frills of the prefab types.


            //************************
            //All of the above entity types have read-only CollisionInformation properties.  Once an entity of those types is created, it cannot change its fundamental shape.
            //A sphere may get bigger or smaller, but a sphere entity couldn't become a box entity.

            //That's where the MorphableEntity comes in.

            var morphable = new MorphableEntity(new CylinderShape(2, 1), 1)
            {
                Position = new Vector3(10, 3, 0)
            };

            Space.Add(morphable);

            //It is constructed identically to its parent Entity class, but after being created, the EntityCollidable it uses can change!
            morphable.CollisionInformation = new ConvexCollidable <ConeShape>(new ConeShape(2, 1));

            //That's neat, but that collidable constructor with generic type is a bit ugly.  We don't care about doing any type-specific configuration
            //on the EntityCollidable itself, so we can just tell the shape to make us an EntityCollidable instance.  This is what the Entity/MorphableEntity constructors
            //do internally when given an EntityShape instead of an EntityCollidable (which in turn contains an EntityShape).
            morphable.CollisionInformation = new ConeShape(2, 1).GetCollidableInstance();

            //While this is arguably a bit prettier, its major benefit comes from the fact that you don't need to know the type of the shape to call GetCollidableInstance.
            //If it's an EntityShape, it can create an EntityCollidable for itself.



            //************************
            //That's it for the different types of entities.  Another very useful technique is to share shapes and initialization between entities.
            //Re-using convex hulls is a common use case.  They have a fairly expensive initialization, and they tend to be some of the larger shapes memory-wise.
            //Rather than having a thousand redundant copies of identical geometry, one shape can be made and reused for subsequent entities.

            //First, create the pointset that composes the convex hull.
            var vertices = new[]
            {
                new Vector3(-1, 0, -1),
                new Vector3(-1, 0, 1),
                new Vector3(1, 0, -1),
                new Vector3(1, 0, 1),
                new Vector3(0, 2, 0)
            };
            //Construct the shape itself.
            var convexHullShape = new ConvexHullShape(vertices);

            //Create an entity using the shape.
            var convexHull = new Entity(convexHullShape, 2)
            {
                Position = new Vector3(0, 1, 0)
            };

            Space.Add(convexHull);
            //Create a bunch of other shapes using that first shape's properties.
            //Instead of using a first entity's data, this could also be pulled in from some external source (deserialized save data or something).
            for (int i = 1; i <= 10; i++)
            {
                Space.Add(new Entity(convexHullShape, convexHull.Mass, convexHull.LocalInertiaTensor)
                {
                    Position = new Vector3(0, 1 + i * 3, 0)
                });
            }

            //In older versions, initializing the entity was a little expensive if the inertia tensor and some other data wasn't provided.
            //These days, the cost is done once in the shape and the entity initialization is pretty much always super cheap.
            //So, you don't need to share inertia tensors for performance reasons.

            //************************
            //All convex shapes are centered on their local origin.  If you create a box entity and assign its position to (0,1,0), the box shape's center will end up at (0,1,0).
            //For simple shapes like the box, that's always the case without doing any work just based on the definition of the shape.

            //More complicated shapes, like the ConvexHullShape, can be constructed from data which is not initially centered around the origin.  For example, consider these vertices:
            vertices = new[]
            {
                new Vector3(-5, 15, -1),
                new Vector3(-5, 15, 1),
                new Vector3(-3, 15, -1),
                new Vector3(-3, 15, 1),
                new Vector3(-4, 17, 0),
                new Vector3(-4, 13, 0)
            };
            //The center of those points is obviously going to be very far from the origin.
            //When we construct a ConvexHullShape, the points get 'recentered.'
            convexHullShape = new ConvexHullShape(vertices);

            //If you look at the convexHullShape.Vertices list, you'll see that the points are relative to a local origin now.
            //So now it's centered on the local origin, as was needed.  But there's a problem- what if you wanted your convex hull entity to end up at the original vertex positions?
            //To get it there, we need to know the offset from the original vertices to the local vertices.
            //Fortunately, there is a constructor overload which provides it!
            Vector3 center;

            convexHullShape = new ConvexHullShape(vertices, out center);

            //Now, when the entity is created, we can position it at the original point's center.  The shape still contains local data, but the entity's location ends up putting the shape in the right spot.
            convexHull = new Entity(convexHullShape, 2)
            {
                Position = center
            };
            Space.Add(convexHull);


            //************************
            //Compound bodies are unique in that they allow you to specify groups of shapes to create a concave shape.
            //Here's the common simple approach to making a compound body, using a prefab type for now.
            CompoundBody body = new CompoundBody(new List <CompoundShapeEntry>
            {
                new CompoundShapeEntry(new BoxShape(1, 1, 1), new Vector3(-7, 3, 8), 1),
                new CompoundShapeEntry(new BoxShape(1, 3, 1), new Vector3(-8, 2, 8), 5),
                new CompoundShapeEntry(new BoxShape(1, 1, 1), new Vector3(-9, 1, 8), 1)
            }, 10);

            Space.Add(body);
            //Each entry has a shape, a rigid transform (orientation and/or translation), and a weight.
            //The rigid transform defines the position of the shape in world space.  They will be recentered into local space within the CompoundShape itself (see previous convex hull example).
            //The 'weight' parameter does not correspond directly to mass, but rather to the contribution of that shape to the whole relative to other shapes.
            //It used to compute the center position of the shape.  When used by a dynamic entity, it is also used to compute a proper inertia tensor.  The resulting inertia tensor is scaled by the entity's actual mass.


            //************************
            //Just like shapes can be shared between entities, you can re-use a shape for multiple entries within a compound body.
            var compoundShape = new CompoundShape(new List <CompoundShapeEntry>
            {
                new CompoundShapeEntry(convexHullShape, new Vector3(7, 3, 8), 1),
                new CompoundShapeEntry(convexHullShape, new RigidTransform(new Vector3(8, 2, 8), Quaternion.CreateFromAxisAngle(Vector3.Forward, MathHelper.PiOver2)), 5),
                new CompoundShapeEntry(convexHullShape, new Vector3(9, 1, 8), 1)
            });

            //And just like normal convex shapes can be shared, so can compound shapes!
            for (int i = 0; i < 3; i++)
            {
                Space.Add(new Entity(compoundShape, 10)
                {
                    Position = new Vector3(8, 10 + i * 4, 8)
                });
            }

            //************************
            //You can also use compound shapes as subshapes, creating nested compounds.
            Space.Add(new Entity(new CompoundShape(new List <CompoundShapeEntry>
            {
                new CompoundShapeEntry(compoundShape, new Vector3(7, 5, 8), 1),
                new CompoundShapeEntry(compoundShape, new Vector3(9, 1, 8), 1)
            }), 10)
            {
                Position = new Vector3(8, 25, 8)
            });


            //************************
            //Sometimes, it's nice to be able to change how subshapes behave.
            //This example will use a prefab CompoundBody type, but note that there exists a CompoundCollidable that can be constructed independently as well.
            //Just like a list of CompoundShapeEntry objects can be used to construct a compound object, a list of CompoundChildData objects can too.
            //CompoundChildData objects contain CompoundShapeEntry objects as well as other data to be used by a Collidable instance.
            //That extra data includes material, events, and collision rules.

            var compoundBody = new CompoundBody(new List <CompoundChildData>
            {
                new CompoundChildData {
                    Entry = new CompoundShapeEntry(new CylinderShape(1, 1), new Vector3(0, 2, 8)), CollisionRules = new CollisionRules {
                        Personal = CollisionRule.NoBroadPhase
                    }
                },
                new CompoundChildData {
                    Entry = new CompoundShapeEntry(new BoxShape(3, 1, 3), new Vector3(0, 1, 8)), Material = new Material(3, 3, 0)
                }
            }, 10);

            Space.Add(compoundBody);

            //In this example, one of the two blocks doesn't collide with anything.  The other does collide, and has a very high friction material.

            //************************
            //While sharing shapes can help reduce load times, sometimes it's useful to eliminate the shape's initialization cost too.
            //For this purpose, all shapes have a constructor which takes a bunch of data that fully defines the shape.
            //The constructor assumes that all of it is correct; it won't catch any errors or do any additional preprocessing.

            //For example, let's construct a ConvexHullShape from the our earlier ConvexHullShape.
            //We'll need a ConvexShapeDescription that defines the data common to all convex shapes.
            var shapeDescription = new ConvexShapeDescription
            {
                CollisionMargin   = convexHullShape.CollisionMargin,
                MinimumRadius     = convexHullShape.MinimumRadius,
                MaximumRadius     = convexHullShape.MaximumRadius,
                EntityShapeVolume = new EntityShapeVolumeDescription
                {
                    Volume             = convexHullShape.Volume,
                    VolumeDistribution = convexHullShape.VolumeDistribution
                }
            };

            //Now, along with the surface vertices from the previous shape, the new shape can be created:
            var shapeFromCachedData = new ConvexHullShape(convexHullShape.Vertices, shapeDescription);

            //Usually, the data for these constructors will come from some cache or storage. For example,
            //a game could store out the above information to disk from a content development tool.
            //At load time, the matching shape can be created at virtually no cost.

            //Stuff the shape into the world!
            Space.Add(new Entity(shapeFromCachedData, 10)
            {
                Position = new Vector3(-10, 5, -5)
            });

            Game.Camera.Position = new Vector3(0, 3, 25);
        }
        /// <summary>Simple examples of all the PhysX bits running together</summary>
        private void LoadPhysics()
        {
            // The ground plane (if created) sould be the first actor
            _groundActor      = _scene.Actors.First();
            _groundActor.Name = "Default Ground Plane";

            //

            #region Some Boxes
            for (int x = 0; x < 5; x++)
            {
                BoxShapeDescription boxShapeDesc = new BoxShapeDescription(2, 3, 8);

                ActorDescription actorDesc = new ActorDescription()
                {
                    Name            = String.Format("Box {0}", x),
                    BodyDescription = new BodyDescription(10.0f),
                    GlobalPose      = Matrix.CreateTranslation(100, 15 + 3 * x, 20),
                    Shapes          = { boxShapeDesc }
                };

                Actor actor = _scene.CreateActor(actorDesc);
            }
            #endregion

            #region Cloth (Flag)
            {
                // Create a Grid of Points
                VertexGrid grid = VertexGrid.CreateGrid(10, 10);

                ClothMeshDescription clothMeshDesc = new ClothMeshDescription();
                clothMeshDesc.AllocateVertices <Vector3>(grid.Points.Length);
                clothMeshDesc.AllocateTriangles <int>(grid.Indices.Length / 3);

                clothMeshDesc.VertexCount   = grid.Points.Length;
                clothMeshDesc.TriangleCount = grid.Indices.Length / 3;

                clothMeshDesc.VerticesStream.SetData(grid.Points);
                clothMeshDesc.TriangleStream.SetData(grid.Indices);

                // We are using 32 bit integers, so make sure the 16 bit flag is removed.
                // 32 bits are the default, so this isn't technically needed
                clothMeshDesc.Flags &= ~MeshFlag.Indices16Bit;

                // Write the cooked data to memory
                MemoryStream memoryStream = new MemoryStream();

                Cooking.InitializeCooking();
                Cooking.CookClothMesh(clothMeshDesc, memoryStream);
                Cooking.CloseCooking();

                // Need to reset the position of the stream to the beginning
                memoryStream.Position = 0;

                ClothMesh clothMesh = _core.CreateClothMesh(memoryStream);

                //

                ClothDescription clothDesc = new ClothDescription()
                {
                    ClothMesh  = clothMesh,
                    Flags      = ClothFlag.Gravity | ClothFlag.Bending | ClothFlag.CollisionTwoway | ClothFlag.Visualization,
                    GlobalPose =
                        Matrix.CreateFromYawPitchRoll(0, (float)Math.PI / 2.0f, (float)Math.PI / 2.0f) *
                        Matrix.CreateTranslation(0, 20, 0)
                };
                clothDesc.MeshData.AllocatePositions <Vector3>(grid.Points.Length);
                clothDesc.MeshData.AllocateIndices <int>(grid.Indices.Length);

                clothDesc.MeshData.MaximumVertices = grid.Points.Length;
                clothDesc.MeshData.MaximumIndices  = grid.Indices.Length;

                clothDesc.MeshData.NumberOfVertices = grid.Points.Length;
                clothDesc.MeshData.NumberOfIndices  = grid.Indices.Length;

                _flag = _scene.CreateCloth(clothDesc);

                // Flag Pole
                ActorDescription flagPoleActorDesc = new ActorDescription()
                {
                    GlobalPose = Matrix.CreateTranslation(0, 10, 0),
                    Shapes     = { new BoxShapeDescription(1.0f, 20.0f, 1.0f) }
                };

                Actor flagPoleActor = _scene.CreateActor(flagPoleActorDesc);

                _flag.AttachToShape(flagPoleActor.Shapes[0], 0);
                _flag.WindAcceleration = new Vector3(10, 10, 10);
                _flag.BendingStiffness = 0.1f;
            }
            #endregion

            #region Revolute Joint
            {
                BoxShapeDescription boxShapeDescA = new BoxShapeDescription(3, 3, 3);
                BoxShapeDescription boxShapeDescB = new BoxShapeDescription(3, 3, 3);

                ActorDescription actorDescA = new ActorDescription()
                {
                    BodyDescription = new BodyDescription(10.0f),
                    GlobalPose      = Matrix.CreateTranslation(75, 1.5f, 55),
                    Shapes          = { boxShapeDescA }
                };
                Actor actorA = _scene.CreateActor(actorDescA);

                ActorDescription actorDescB = new ActorDescription()
                {
                    BodyDescription = new BodyDescription(10.0f),
                    GlobalPose      = Matrix.CreateTranslation(70, 1.5f, 55),
                    Shapes          = { boxShapeDescB }
                };
                Actor actorB = _scene.CreateActor(actorDescB);

                //

                RevoluteJointDescription revoluteJointDesc = new RevoluteJointDescription()
                {
                    Actor1 = actorA,
                    Actor2 = actorB,
                    Motor  = new MotorDescription(20, 20.1f, true)
                };
                revoluteJointDesc.Flags |= RevoluteJointFlag.MotorEnabled;
                revoluteJointDesc.SetGlobalAnchor(new Vector3(73.5f, 1.5f, 55));
                revoluteJointDesc.SetGlobalAxis(new Vector3(1, 0, 0));

                RevoluteJoint revoluteJoint = _scene.CreateJoint(revoluteJointDesc) as RevoluteJoint;
            }
            #endregion

            #region Prismatic Joint with Limit
            {
                Actor actorA, actorB;
                {
                    BoxShapeDescription boxShapeDesc = new BoxShapeDescription(3, 3, 3);

                    BodyDescription bodyDesc = new BodyDescription(10.0f);
                    bodyDesc.BodyFlags |= BodyFlag.Kinematic;

                    ActorDescription actorDesc = new ActorDescription()
                    {
                        BodyDescription = bodyDesc,
                        GlobalPose      = Matrix.CreateTranslation(70, 25, 65),
                        Shapes          = { boxShapeDesc }
                    };
                    actorA = _scene.CreateActor(actorDesc);
                }
                {
                    BoxShapeDescription boxShapeDesc = new BoxShapeDescription(3, 3, 3);

                    ActorDescription actorDesc = new ActorDescription()
                    {
                        BodyDescription = new BodyDescription(10.0f),
                        GlobalPose      = Matrix.CreateTranslation(70, 15, 65),
                        Shapes          = { boxShapeDesc }
                    };
                    actorB = _scene.CreateActor(actorDesc);
                }

                PrismaticJointDescription prismaticJointDesc = new PrismaticJointDescription()
                {
                    Actor1 = actorA,
                    Actor2 = actorB,
                };
                prismaticJointDesc.SetGlobalAnchor(new Vector3(70, 20, 65));
                prismaticJointDesc.SetGlobalAxis(new Vector3(0, 1, 0));

                PrismaticJoint prismaticJoint = _scene.CreateJoint(prismaticJointDesc) as PrismaticJoint;

                LimitPlane limitPlane = new LimitPlane(new Vector3(0, 1, 0), new Vector3(-30, 8, -30), 0);
                prismaticJoint.AddLimitPlane(limitPlane);
            }
            #endregion

            #region Fluid
            {
                const int maximumParticles = 1000;

                FluidEmitterDescription fluidEmitterDesc = new FluidEmitterDescription()
                {
                    DimensionX   = 0.5f,
                    DimensionY   = 0.5f,
                    Rate         = 15,
                    RelativePose = Matrix.CreateTranslation(-40, 10, 50),
                    Shape        = EmitterShape.Rectangular,
                    Type         = EmitterType.ConstantFlowRate,
                    RandomAngle  = 0.5f
                };
                fluidEmitterDesc.Flags |= (FluidEmitterFlag.Enabled | FluidEmitterFlag.Visualization);

                FluidDescription fluidDesc = new FluidDescription()
                {
                    Emitters         = { fluidEmitterDesc },
                    Flags            = FluidFlag.Enabled | FluidFlag.Visualization,
                    MaximumParticles = maximumParticles
                };
                fluidDesc.ParticleWriteData.AllocatePositionBuffer <Vector3>(maximumParticles);
                fluidDesc.ParticleWriteData.NumberOfParticles = maximumParticles;

                Fluid fluid = _scene.CreateFluid(fluidDesc);

                // Ledge
                {
                    BoxShapeDescription boxShapeDesc = new BoxShapeDescription(5, 0.1f, 5);

                    ActorDescription drainActorDesc = new ActorDescription()
                    {
                        GlobalPose = Matrix.CreateRotationX(0.5f) * Matrix.CreateTranslation(-40, 5, 52),
                        Shapes     = { boxShapeDesc }
                    };

                    Actor drianActor = _scene.CreateActor(drainActorDesc);
                }

                // Drain
                {
                    BoxShapeDescription boxShapeDesc = new BoxShapeDescription(5, 0.1f, 5);
                    boxShapeDesc.Flags |= ShapeFlag.FluidDrain;

                    ActorDescription drainActorDesc = new ActorDescription()
                    {
                        GlobalPose = Matrix.CreateTranslation(-40, 0, 55),
                        Shapes     = { boxShapeDesc }
                    };

                    Actor drianActor = _scene.CreateActor(drainActorDesc);
                }
            }
            #endregion

            #region Force Field
            {
                BoxForceFieldShapeDescription boxForceFieldShapeDesc = new BoxForceFieldShapeDescription()
                {
                    Size = new Vector3(10, 10, 10)
                };

                ForceFieldLinearKernelDescription kernelDesc = new ForceFieldLinearKernelDescription()
                {
                    Constant = new Vector3(0, 100.0f, 0)
                };

                ForceFieldLinearKernel kernel = _scene.CreateForceFieldLinearKernel(kernelDesc);

                ForceFieldShapeGroupDescription shapeGroupDesc = new ForceFieldShapeGroupDescription()
                {
                    Shapes = { boxForceFieldShapeDesc }
                };

                ForceFieldShapeGroup shapeGroup = _scene.CreateForceFieldShapeGroup(shapeGroupDesc);

                BoxForceFieldShape boxForceFieldShape = shapeGroup.CreateShape(boxForceFieldShapeDesc) as BoxForceFieldShape;
                boxForceFieldShape.Pose = Matrix.CreateTranslation(30, 5, 0);

                ForceFieldDescription forceFieldDesc = new ForceFieldDescription()
                {
                    Kernel      = kernel,
                    ShapeGroups = { shapeGroup }
                };
                ForceField forceField = _scene.CreateForceField(forceFieldDesc);
            }
            #endregion

            #region Heightfield
            {
                int rows    = 25;
                int columns = 25;

                HeightFieldSample[] samples = new HeightFieldSample[rows * columns];
                for (int r = 0; r < rows; r++)
                {
                    for (int c = 0; c < columns; c++)
                    {
                        // Put a z and x curve together
                        double h = Math.Sin(c) * Math.Cos(r) * short.MaxValue;

                        HeightFieldSample sample = new HeightFieldSample();
                        sample.Height           = (short)h;
                        sample.MaterialIndex0   = 0;
                        sample.MaterialIndex1   = 1;
                        sample.TessellationFlag = 0;

                        samples[r * columns + c] = sample;
                    }
                }

                HeightFieldDescription heightFieldDesc = new HeightFieldDescription()
                {
                    NumberOfRows    = rows,
                    NumberOfColumns = columns,
                    Samples         = samples
                };

                HeightField heightField = _core.CreateHeightField(heightFieldDesc);

                //

                HeightFieldShapeDescription heightFieldShapeDesc = new HeightFieldShapeDescription()
                {
                    HeightField  = heightField,
                    HoleMaterial = 2,
                    // The max height of our samples is short.MaxValue and we want it to be 1
                    HeightScale = 1.0f / (float)short.MaxValue,
                    RowScale    = 3,
                    ColumnScale = 3
                };
                heightFieldShapeDesc.LocalPosition = new Vector3(-0.5f * rows * 1 * heightFieldShapeDesc.RowScale, 0, -0.5f * columns * 1 * heightFieldShapeDesc.ColumnScale);

                ActorDescription actorDesc = new ActorDescription()
                {
                    GlobalPose = Matrix.CreateTranslation(100, 0, 0),
                    Shapes     = { heightFieldShapeDesc }
                };
                Actor actor = _scene.CreateActor(actorDesc);
            }
            #endregion

            #region Convex Mesh
            {
                ModelMesh mesh = _torusModel.Meshes.First();

                Matrix[] transforms = new Matrix[_torusModel.Bones.Count];
                _torusModel.CopyAbsoluteBoneTransformsTo(transforms);

                // Gets the vertices from the mesh
                VertexPositionNormalTexture[] vertices = new VertexPositionNormalTexture[mesh.MeshParts[0].NumVertices];
                mesh.VertexBuffer.GetData <VertexPositionNormalTexture>(vertices);

                //

                // Allocate memory for the points and triangles
                var convexMeshDesc = new ConvexMeshDescription()
                {
                    PointCount = vertices.Length
                };
                convexMeshDesc.Flags |= ConvexFlag.ComputeConvex;
                convexMeshDesc.AllocatePoints <Vector3>(vertices.Length);

                // Write in the points and triangles
                // We only want the Position component of the vertex. Also scale down the mesh
                foreach (VertexPositionNormalTexture vertex in vertices)
                {
                    Vector3 position = Vector3.Transform(vertex.Position, Matrix.CreateScale(0.1f, 0.1f, 0.1f) * transforms[0]);

                    convexMeshDesc.PointsStream.Write(position);
                }

                //

                // Cook to memory or to a file
                MemoryStream stream = new MemoryStream();
                //FileStream stream = new FileStream( @"Convex Mesh.cooked", FileMode.CreateNew );

                Cooking.InitializeCooking(new ConsoleOutputStream());
                Cooking.CookConvexMesh(convexMeshDesc, stream);
                Cooking.CloseCooking();

                stream.Position = 0;

                ConvexMesh convexMesh = _core.CreateConvexMesh(stream);

                ConvexShapeDescription convexShapeDesc = new ConvexShapeDescription(convexMesh);

                ActorDescription actorDesc = new ActorDescription()
                {
                    BodyDescription = new BodyDescription(10.0f),
                    GlobalPose      = Matrix.CreateTranslation(30, 30, 0)
                };
                actorDesc.Shapes.Add(convexShapeDesc);

                _torusActor = _scene.CreateActor(actorDesc);
            }
            #endregion

            #region SoftBody
            if (false)              // Enable to view soft bodies, they run slowly
            {
                XmlDocument doc = new XmlDocument();
                doc.Load("Teapot.xml");

                // Not how NxuStream are meant to used but what ever :S
                Vector3[] vertices          = ReadVertices(doc.SelectSingleNode("/NXUSTREAM2/NxuPhysicsCollection/NxSoftBodyMeshDesc/vertices"));
                int[]     tetrahedraSingles = ReadTetrahedra(doc.SelectSingleNode("/NXUSTREAM2/NxuPhysicsCollection/NxSoftBodyMeshDesc/tetrahedra"));

                var softBodyMeshDesc = new SoftBodyMeshDescription()
                {
                    VertexCount     = vertices.Length,
                    TetrahedraCount = tetrahedraSingles.Length / 4                     // Tetrahedras come in quadruples of ints
                };

                softBodyMeshDesc.AllocateVertices <Vector3>(softBodyMeshDesc.VertexCount);
                softBodyMeshDesc.AllocateTetrahedra <int>(softBodyMeshDesc.TetrahedraCount);                  // Note: T is an int. T is the type of each point

                softBodyMeshDesc.VertexStream.SetData(vertices);
                softBodyMeshDesc.TetrahedraStream.SetData(tetrahedraSingles);

                MemoryStream memoryStream = new MemoryStream();

                Cooking.InitializeCooking();
                Cooking.CookSoftBodyMesh(softBodyMeshDesc, memoryStream);
                Cooking.CloseCooking();

                memoryStream.Position = 0;

                SoftBodyMesh softBodyMesh = _core.CreateSoftBodyMesh(memoryStream);

                SoftBodyDescription desc = new SoftBodyDescription()
                {
                    GlobalPose   = Matrix.CreateTranslation(-30, 20, -30),
                    SoftBodyMesh = softBodyMesh
                };
                desc.Flags |= SoftBodyFlag.Visualization;

                desc.MeshData.AllocatePositions <Vector3>(vertices.Length);
                desc.MeshData.AllocateIndices <int>(tetrahedraSingles.Length);

                SoftBody softBody = _scene.CreateSoftBody(desc);
            }
            #endregion

            #region Reports
            // Contact report
            // When the capsule actor hits the ground make it bounce by using the conact report
            {
                CapsuleShapeDescription capsuleShapeDesc = new CapsuleShapeDescription(1, 5);

                ActorDescription actorDesc = new ActorDescription()
                {
                    GlobalPose      = Matrix.CreateTranslation(-30, 20, 0),
                    BodyDescription = new BodyDescription(10.0f),
                    Name            = "Report Capsule",
                    Shapes          = { capsuleShapeDesc }
                };

                _contactReportActor = _scene.CreateActor(actorDesc);

                _scene.SetActorPairFlags(_contactReportActor, _groundActor, ContactPairFlag.All);

                _scene.UserContactReport = new ContactReport(this);
            }

            // Trigger Reports
            {
                BoxShapeDescription boxShapeDesc = new BoxShapeDescription(15, 8, 15);
                boxShapeDesc.Flags |= (ShapeFlag.TriggerOnEnter | ShapeFlag.TriggerOnLeave);

                ActorDescription actorDesc = new ActorDescription()
                {
                    GlobalPose = Matrix.CreateTranslation(-30, 4, 0),
                    Shapes     = { boxShapeDesc }
                };
                _scene.CreateActor(actorDesc);

                _scene.UserTriggerReport = new TriggerReport(this);
            }

            _scene.UserNotify = new Notify(this);
            #endregion

            #region Wheel
            {
                _basicVehicle = new Vehicle(this);
            }
            #endregion

            #region Controller
            {
                ControllerManager manager = _scene.CreateControllerManager();

                CapsuleControllerDescription capsuleControllerDesc = new CapsuleControllerDescription(4, 3)
                {
                    Callback = new ControllerHitReport()
                };

                CapsuleController capsuleController = manager.CreateController <CapsuleController>(capsuleControllerDesc);
                capsuleController.Position   = new Vector3(0, 1.5f + 2, -15);
                capsuleController.Actor.Name = "BoxController";
                capsuleController.SetCollisionEnabled(true);
            }
            #endregion
        }
	    private ShapeDescription ToShape(PrimitiveBaseShape baseShape)
        {
            ConvexShapeDescription convexShapeDescription = new ConvexShapeDescription();
            //ShapeDescription retval = new BodyDescription()
        }