Camera collisions with the mesh

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
lantzvillian
Posts: 4
Joined: Fri Nov 04, 2011 10:23 pm

Camera collisions with the mesh

Post by lantzvillian »

Hi all,

I'll start off that I am very interested with BEPU as a way to solve my collisions problem with a 1st person camera and a maze (anyone remember the Maze screensaver circa windows 98?). I have the camera running around and a .x mesh loaded. My problem is that the camera can clip through my mesh and I don't want that.

How would I go about creating a collision detection for my mesh?

Cheers!
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Camera collisions with the mesh

Post by Norbo »

How would I go about creating a collision detection for my mesh?
First, if you haven't already, I would recommend checking out the Getting Started documentation and demos. This includes setting up a StaticMesh. The main source download also includes the BEPUphysicsDemos project, which has 40+ example simulations to look at.

Treating your camera as if it had collision detection basically amounts to making a character. You may want to check out the SimpleCharacterController or CharacterController in the BEPUphysicsDemos. There's also a SphereCharacterController in the development version.

A general overview of characters can be found in this blog post.

You may not want the full power of a proper character controller. Instead, maybe a simple floating sphere would suffice. This is the simplest possible form of 'character controller.' Basically, create a Sphere entity, add it to the space, and control its motion using velocities created from user input. The camera's position follows the entity's Position.
lantzvillian
Posts: 4
Joined: Fri Nov 04, 2011 10:23 pm

Re: Camera collisions with the mesh

Post by lantzvillian »

I did have a glance at the Sample, but I noticed the camera didn't bump into the boxes and it clipped.

Then I looked at the demo and it did, but in the meantime while I gander at the examples you have mentioned - just a cube or sphere for the camera char would work for me.

So far with Bepu, I have the space var, the reference loaded and the Space.Add call is giving an error.

Code: Select all

protected override void LoadContent()
        {
            landscape = Content.Load<Model>("landscape");

            Vector3[] staticTriangleVertices;
            int[] staticTriangleIndices;
            TriangleMesh.GetVerticesAndIndicesFromModel(landscape, out staticTriangleVertices, out staticTriangleIndices);
            var staticLandscape = new StaticMesh(staticTriangleVertices, staticTriangleIndices, new AffineTransform(new Vector3(G.INCH, G.INCH, G.INCH), Quaternion.Identity, new Vector3(0, 0, 0)));
            staticLandscape.Sidedness = TriangleSidedness.Counterclockwise;
            staticLandscape.ImproveBoundaryBehavior = true;
            Space.Add(staticLandscape);
       
        }
The error is:
An object reference is required for the non-static field, method or property...
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Camera collisions with the mesh

Post by Norbo »

It sounds like your variable is not named 'Space'. It interprets Space.Add as an attempt at a static method call, but there is no static Add method for the Space class.
lantzvillian
Posts: 4
Joined: Fri Nov 04, 2011 10:23 pm

Re: Camera collisions with the mesh

Post by lantzvillian »

Okay seems a rebuild fixed everything + what you said. Now I want to added a box right and then link that to the cameras movements - how I don't know?

LoadContent function:

Code: Select all

        protected override void LoadContent()
        {
          blah blah/....
            space = new Space();

            Box box = new Box(new Vector3(0, 4, 0), 1, 1, 1, 1);
            space.Add(box);

            Vector3[] staticTriangleVertices;
            int[] staticTriangleIndices;
            TriangleMesh.GetVerticesAndIndicesFromModel(landscape, out staticTriangleVertices, out staticTriangleIndices);
            var staticLandscape = new StaticMesh(staticTriangleVertices, staticTriangleIndices, new AffineTransform(new Vector3(0,0,0), Quaternion.Identity, new Vector3(0, 0, 0)));
            staticLandscape.Sidedness = TriangleSidedness.Counterclockwise;
            staticLandscape.ImproveBoundaryBehavior = true;
            space.Add(staticLandscape);
}
Then in my update function:

Code: Select all

protected override void Update(GameTime gameTime)
        {
            HandleInput();
            space.Update();

            UpdateCamera(gameTime);

            base.Update(gameTime);
        }
Then my UpdateCamera function looks something like:

Code: Select all

        private void UpdateCamera(GameTime gameTime)
        {
            float time = (float)gameTime.ElapsedGameTime.TotalMilliseconds;

            // Check for input to rotate the camera.
            float cameraPitch = -currentGamePadState.ThumbSticks.Right.Y * time * 0.001f;
            float cameraTurn = -currentGamePadState.ThumbSticks.Right.X * time * 0.001f;

            if (currentKeyboardState.IsKeyDown(Keys.Left))
                cameraTurn += time * 0.001f;

            if (currentKeyboardState.IsKeyDown(Keys.Right))
                cameraTurn -= time * 0.001f;

            Vector3 cameraRight = Vector3.Cross(Vector3.Up, cameraFront);
            Vector3 flatFront = Vector3.Cross(cameraRight, Vector3.Up);

            Matrix cameraPitchMatrix = Matrix.CreateFromAxisAngle(cameraRight, cameraPitch);
            Matrix cameraTurnMatrix = Matrix.CreateFromAxisAngle(Vector3.Up, cameraTurn);

            Vector3 turnedFront = Vector3.TransformNormal(cameraFront, cameraPitchMatrix * cameraTurnMatrix);

            // Check angle so camera cannot flip and allow side to side rotation
            if (Vector3.Dot(turnedFront, flatFront) > 0.001f)
            {
                cameraFront = Vector3.Normalize(turnedFront);
            }

            // Check for input to move the camera around forward/backward and strafe
            if (currentKeyboardState.IsKeyDown(Keys.W))
                cameraPosition += cameraFront * time * 0.01f;
            
            if (currentKeyboardState.IsKeyDown(Keys.S))
                cameraPosition -= cameraFront * time * 0.01f;

            if (currentKeyboardState.IsKeyDown(Keys.A))
                cameraPosition += cameraRight * time * 0.01f;

            if (currentKeyboardState.IsKeyDown(Keys.D))
                cameraPosition -= cameraRight * time * 0.01f;
Where and how do I proceed now? I had a quick look at the examples, but it isn't clear to me.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Camera collisions with the mesh

Post by Norbo »

Where and how do I proceed now? I had a quick look at the examples, but it isn't clear to me.
The general idea is what I posted earlier:
Basically, create a Sphere entity, add it to the space, and control its motion using velocities created from user input. The camera's position follows the entity's Position.
It doesn't have to be a sphere, but their curved nature is convenient. You'll probably also want to set the sphere entity's LocalInertiaTensorInverse = new Matrix3X3(). This gives the entity effectively infinite rotational inertia. In other words, it cannot rotate. Instead of rolling around, it will slide around. This helps avoid odd situations where your character is actually spinning at a high rate of speed due to prior collisions such that when it hits a wall, it gains some confusing linear velocity.

The important bit is that the camera does not define the position of the physical entity. It's the other way around- the physics defines where the camera is. Instead of offsetting your camera's position every frame by a fixed amount and trying to teleport your physical entity along with it, use the player input to change the velocity of the physical entity and read the physical entity's Position for use as the camera's position.

For example, pressing "W" would result in modifying the LinearVelocity property of the physical entity in the camera's forward direction. You could simply add a fixed amount of velocity in the direction every frame.

More robust would be a system which has a desired speed, and you modify the velocity to reach that speed in that direction. The SimpleCharacterController, SphereCharacterController, and CharacterController all show how to manage horizontal movement in different ways. The SimpleCharacterController's approach is the easiest to adopt to a different system. If you have a specific question about a particular element in the system, just let me know.
lantzvillian
Posts: 4
Joined: Fri Nov 04, 2011 10:23 pm

Re: Camera collisions with the mesh

Post by lantzvillian »

Ahh I see what your saying - all I want though is just a simple does camera hit object. Object doesn't need to rotate, but if it does eventually thats okay with me.

I guess what I am struggling with is getting started, so I guess if I could detect if or when the two objects are colliding now I'd bumble about and get back.. I am scouring the forms, but nothing is clear cut. I'm not really a Windows/graphic programmer by trade.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Camera collisions with the mesh

Post by Norbo »

It sounds like there's a substantial inferential distance. I'll try to connect the dots with some more high-level stuff.

Keeping the camera from going through the walls means that the camera is associated with a physical object. This physical object must be capable of velocity-based motion. It must detect collisions with StaticMeshes which have been added. Finally, it should respond to the detected collisions. Responding to a collision means that its velocity changes due to an impact based on the contacts created during collision detection.

The Entity class covers all objects which are capable of velocity-based motion. This means that static-only geometry collidables, such as the StaticMesh, Terrain, and InstancedMesh are not entities.

Entities can be either dynamic or kinematic.

Kinematic entities do not respond to collisions or constraints; they can be considered 'unstoppable forces' or 'immovable objects.' Kinematic entities can have their LinearVelocity or AngularVelocity set directly to get them to move. A kinematic entity will happily tunnel right through a StaticMesh because the kinematic entity does not respond to collisions.

Dynamic entities do respond to collisions and constraints. They fall, bounce around, and do all the other regular physical-object things.

There's a variety of ways to construct entities, as can be seen in the EntityConstructionDemo of the BEPUphysicsDemos. A common easy way to construct entities is using the prefab types, like Box, Sphere, Cylinder, and so on. All entities have multiple constructors. Constructors with a 'mass' parameter will construct a dynamic entity. Constructors without a 'mass' parameter will construct a kinematic entity. You can also switch between the two later by using the BecomeKinematic or BecomeDynamic methods, but it's best to construct the right kind up front if possible.

Since you don't want your camera to tunnel through walls, you want collision response which in turn means you need to use a dynamic entity.

The association between the camera and the physical entity can be thought of as driving a car. When you are driving, you are not propelling yourself and pulling the car with you. Instead, you are giving input to the car through its interface (e.g. the steering wheel and pedals). The car uses your input to move, and you follow its motion.

Similarly, the camera should not define the position state of the entity. The camera gives input to the entity, and the camera follows the entity.

The input will be in the form of changes to the entity's LinearVelocity property. Those changes are created based on the current user input and facing directions of the camera. The camera follows the entity by looking at the entity's Position property every frame and adjusting its view matrix accordingly.

It may appear 'simpler' at first glance to control the position of the entity directly using the camera's position. However, this would require that you handle collision response yourself. This is because the camera is still noclipping all over the place by default, and the physical object is being discontinuously teleported. The built-in collision response system can do nothing to stop the camera as there is no feedback to the camera's position and there is no velocity for the collision solver to work with.

It is technically possible to program your own logic to handle collision response such that you could use kinematic entities or whatever you want. However, there will almost certainly be some corner cases where the custom collision handling code just doesn't feel very good. It's almost always easier and better to just use the regular collision response solver.
Post Reply