转载:Using the BoxCollider Library

待我称王封你为后i 2021-12-07 14:27 331阅读 0赞

Ship Game – Using the BoxCollider Library

This article explains how you can use the BoxCollider library in your own game. This is a custom collision detection and response library created for Ship Game. This article contains instructions for including the BoxCollider library in your project, sample code to implement simple collision detection and response, and a description of the BoxCollider API.

Adding the BoxCollider Library

The BoxCollider library comes with Ship Game, and is a separate project from the Ship Game project.

Note: To use BoxCollider, you must be using XNA Game Studio Refresh 1.0 or greater.

With your game solution open, copy the source folder for BoxCollider into your solution folder. In XNA Game Studio, right-click on your solution node in Solution Explorer, click Add, and then click Existing Project.

From the dialog box that appears, browse to the BoxCollider folder you copied to your solution folder. Choose either the Windows or Xbox 360 version of BoxCollider, depending on whether your game solution targets Windows or Xbox 360. Click the appropriate project file, and then click Add.

Then, right-click on your game project node in Solution Explorer, and click Project Dependencies.

022608_0121_UsingtheBo1.png
Figure 1: Project Dependencies window with BoxColliderWin checked, and a reference to BoxColliderWin Library

In the dialog box that appears, check the box next to the BoxCollider project you added, and click OK. This will make XNA Game Studio to build the BoxCollider project before it builds your game project, so that your game can reference the built BoxCollider library.

Finally, you must add a reference to the BoxCollider library inside your game project. Right-click your game project and select Add Reference.

From the dialog box that appears, choose the Projects tab, select the BoxCollider project that appears in the list, and click OK.

You are now ready to use the BoxCollider library.

Using the BoxCollider Library

The BoxCollider library makes three-dimensional collision detection and response easy by providing a CollisionMesh object – a subdivided set of collision geometry – for any XNA Framework Model object. You can then use the CollisionMesh to test for collisions.

Generate Collision Mesh

The first step is to generate a CollisionMesh for each Model object you wish to test for collision. Start by loading your Model through the Content Pipeline using ContentManager.Load. Once you have loaded the model, pass it to the constructor for a new CollisionMesh object.

  1. // load standard XNA Model
  2. Model model = content.Load<Model>("content/mymodel.x");
  3. // create collision mesh with 4 levels of octree subdivision
  4. // (4^levels = 4^4 = 256 leaf nodes)
  5. CollisionMesh collision = new CollisionMesh( model, 4 );
  6. // dispose model
  7. model = null;

When creating a CollisionMesh object, you have a choice as to the number of subdivisions you want the CollisionMesh to use. Four is good default value; you may want to raise the number if you need very accurate collision or are using complex geometry, but be aware that more subdivisions means more processor time spent in collision testing, which will affect performance.

After you have constructed the CollisionMesh object, you can discard the Model object used to create the CollisionMesh.

Collision Testing Using CollisionMesh

Once you have created a CollisionMesh object, use the following member methods of the CollisionMesh object to detect collision.

bool PointIntersect(
Vector3 rayStart,
Vector3 rayEnd,
out float intersectDistance,
out Vector3 intersectPosition,
out Vector3 intersectNormal)

This method extends a ray from rayStart to rayEnd and checks for an intersection with the CollisionMesh. The method returns true and fills the three out parameters with information about the closest intersection if an intersection between the ray and the mesh exists.

bool BoxIntersect(
CollisionBox box,
Vector3 rayStart,
Vector3 rayEnd,
out float intersectDistance,
out Vector3 intersectPosition,
out Vector3 intersectNormal)

This method is similar to the PointIntersect method above, but binds an axis-aligned bounding box (AABB) around the ray segment. This method executes three different collision tests to detect intersection from the box to the mesh: box vertices to mesh faces, mesh vertices to box faces, and mesh edges to box edges. A hierarchical space subdivision tree makes sure only the mesh faces in the region affected by the movement are tested for collision.

void PointMove(
Vector3 pointStart,
Vector3 pointEnd,
float frictionFactor,
float bumpFactor,
uint recurseLevel,
out Vector3 pointResult)

More than just a collision test like the preceding methods, this method moves a point in space, testing for collisions along the movement path, reflecting recursively, and returning the point’s new position in space after all collisions have been accounted for.

Pass in the start position and desired end position (pointStart and pointEnd), and the maximum number of reflections (recurseLevel).

When a collision occurs along the path, the reflected path is calculated based on the normal of the face. The final reflected path is calculated using frictionFactor and bumpFactor according to this equation:

reflectedPath = frictionFactor * reflectedPath + bumpFactor * originalPath

A typical collision against a hard surface will use a frictionFactor of 1 and a bumpFactor of 0.

The method will fill pointResult with the final location of the point after all collisions have been resolved.

void BoxMove(
CollisionBox box,
Vector3 pointStart,
Vector3 pointEnd,
float frictionFactor,
float bumpFactor,
uint recurseLevel,
out Vector3 pointResult)

This method is similar to the PointMove method above, but binds an AABB around the ray segment. The method collides the box against the mesh, recursively operating through any intersections found. Like PointMove, the method fills pointResult with the final position for the box after any possible collisions. This method is useful for camera and player collision detection with the environment.

A Collision Example

The following example shows how to collide a moving object with a collision mesh in the scene.

First, save the current position of the moving object. Then, compute the new position by using the velocity of the object and elapsed game time. Then, test for collision between the saved position and the new position.

If a collision is found, update the current position with the position after collision, and re-compute the velocity vector.

bool UpdatePosition(

  1. Vector3 Position, // current position
  2. Vector3 Velocity, // current velocity
  3. float ElapsedTime, // frame elapsed time
  4. CollisionBox ObjectBox, // moving collision object
  5. CollisionModel SceneCollision) // scene collision object

{

// hold position before movement

Vector3 LastPos = Position;

// update movement

Position += Velocity * ElapsedTime;

// test for collision with level

Vector3 CollisionPos;

if (SceneCollision.BoxMove(Box, LastPos, Position,

1.0f, 0.0f, 3, out CollisionPos))

{

// update to valid position after collision

Position = CollisionPos;

// compute new velocity after collision

Velocity = (CollisionPos - LastPos) *

(1.0f / ElapsedTime);

// collision found!

return true;

}

  1. // collision not found
  2. return false;

}

This code assumes a moving object of considerable size. For bouncing weapon projectiles and other point-based moving objects, consider using the same code as above but replacing the call to BoxMove with a call to PointMove. The PointMove method is faster and does not require a bounding box object, since it considers only an infinitely small point moving as a line segment.

Collision in Chase Camera Sample

This example implements collision detection in the Chase Camera sample available at http://creators.xna.com. Adding this behavior to the sample is straightforward.

First, create a new variable that will store the position of the camera after collision has been calculated, and change the Position get property to return this new collision-aware position rather than the original position.

Then, modify the Update method. Call PointIntersect to check for collision between the camera target and camera position. If a collision is found, move the camera closer to its target.

Vector3collisionPosition;

///

/// Position of camera in world space.

///

public Vector3 Position

{

get { return collisionPosition; }

}

private Vector3 position;

private Vector3 collisionPosition;

///

/// Animates the camera from its current position towards the desired offset

/// behind the chased object. The camera’s animation is controlled by a simple

/// physical spring attached to the camera and anchored to the desired position.

///

public void Update(float elapsedTime, CollisionMesh collision)

{

UpdateWorldPositions();

// Calculate spring force

Vector3 stretch = position - desiredPosition;

Vector3 force = -stiffness * stretch - damping * velocity;

// Apply acceleration

Vector3 acceleration = force / mass;

velocity += acceleration * elapsedTime;

// Apply velocity

position += velocity * elapsedTime;

// test camera for collision with world

collisionPosition = position;

if (collision != null)

{

float collisionDistance;

Vector3 collisionPoint, collisionNormal;

if (collision.PointIntersect(lookAt, position, out collisionDistance,

out collisionPoint, out collisionNormal))

{

Vector3 dir = Vector3.Normalize(collisionPoint - lookAt);

collisionPosition = collisionPoint - 10 * dir;

}

}

UpdateMatrices();

}

BoxCollider Classes

The following classes are included in the BoxCollider library:

Collision Helper Classes

CollisionBox

This class implements an AABB. It is defined by two 3D points representing the minimum and maximum points of the box. Several methods are included to allow for both intersection and containment tests. You should have a CollisionBox object for each dynamic object in your game that requires dynamic collision detection with other objects in the scene.

CollisionFace

This class holds the vertices used by one face in the mesh object. Also included are methods to detect collision to a face, including ray-to-triangle intersection and edge-to-edge intersection.

CollisionMesh

This class implements model-ready collision detection. It is created using a regular Model object and will copy and process all information needed for collision upon its construction. This class holds information about all triangles in the original Model object plus an octree (a tree with 8 child nodes per parent node) object to speed up intersection to the model faces.

CollisionTree

This class implements a basic octree. It holds the root node for the tree and includes methods to find what leaf nodes and what elements inside those leaf nodes intersect a given selection box.

CollisionTreeNode

This class implements a tree node. Each node has a bounding box and a list of child nodes. If no child nodes are included, the node is considered a leaf node. Leaf nodes contain a list of elements derived from CollisionTreeElem.

CollisionTreeElem

This is the abstract base class for an element included in the collision tree. The CollisionFace class is derived from it, which allows CollisionFace objects to be included in leaf nodes of the collision tree. Each element can be included in multiple leaf nodes; all elements are included in all leaf nodes their bounding boxes touch. Objects derived from this class must be static and cannot move and change nodes in the tree.

CollisionTreeElemDynamic

This is the base class for a dynamic element that can be included in the collision tree. It behaves like the static CollisionTreeElem but allows dynamic adding to or removing from the tree. As an example, a derived object could remove itself from the collision tree, move around, and then be added back to the collision tree (possibly including itself in different leaf nodes after moving).

Camera Classes

CollisionCamera

This is an abstract class serving as a base implementation for a camera object that supports collision detection with a model in the scene.

CollisionCameraObserver

This class implements an observer-type camera, which uses six degrees of freedom, allowing you to move and rotate in all three axes. This class contains simple movement and collision.

CollisionCameraPerson

This class implements a first-person shooter-type camera. The collision object used is a rectangle (with long axis in the Y direction). It can move only in the X and Z planes and is pushed down in the Y direction by a gravity force.

This class has special code to detect ground collision and supports smooth walking up/down stairs and ramps. It also allows jumping when the camera is in contact with the ground, by applying an upward force in the Y axis.

转载于:https://www.cnblogs.com/jerryhong/archive/2008/02/26/1081582.html

发表评论

表情:
评论列表 (有 0 条评论,331人围观)

还没有评论,来说两句吧...

相关阅读