BoundingBox Collision Is Always True

Started by
12 comments, last by mitko29 12 years, 2 months ago
Hi all , I am trying to make boundingbox collision for my 3D models instead using Sphere because is more accurate, but collision is always true here,how am I drawing the box:


BoundingBox sbox;
private Vector3 min = new Vector3(float.MaxValue,float.MaxValue,float.MaxValue);
private Vector3 max = new Vector3(float.MinValue,float.MinValue,float.MinValue);
foreach (ModelMesh meshh in texture.Meshes)
{
foreach (ModelMeshPart meshPart in meshh.MeshParts)
{
int vertexStride = meshPart.VertexBuffer.VertexDeclaration.VertexStride;
int vertexBufferSize = meshPart.NumVertices * vertexStride;
float[] vertexData = new float[vertexBufferSize / sizeof(float)];
meshPart.VertexBuffer.GetData<float>(vertexData);

for (int i = 0; i < vertexBufferSize / sizeof(float); i += vertexStride / sizeof(float))
{
Vector3 transformedPosition = Vector3.Transform(new Vector3(vertexData, vertexData[i + 1], vertexData[i + 2]), enemymat);
min = Vector3.Min(min, transformedPosition);
max = Vector3.Max(max, transformedPosition);
}
}
sbox = new BoundingBox(min,max);



Result:

fd319f203b887046.png
and when I debug the bounding box , here what I see:

c4cc565babf3d727.png
Advertisement
Have you stepped through the code in the debugger? Have you printed out the values of the boxes you generate? Note that the value 3,402823E+38 equals http://msdn.microsoft.com/en-us/library/system.single.maxvalue.aspx , and your bounding box comes out degenerate to large negative values, as you initialize in the code before running the inner loop. That suggests that for some model, the inner loop of your AABB extrude algorithm is not run even once, leaving the box degenerate.

Have you stepped through the code in the debugger? Have you printed out the values of the boxes you generate? Note that the value 3,402823E+38 equals http://msdn.microsof...e.maxvalue.aspx , and your bounding box comes out degenerate to large negative values, as you initialize in the code before running the inner loop. That suggests that for some model, the inner loop of your AABB extrude algorithm is not run even once, leaving the box degenerate.

oh, sorry for my stupidity,now I put the code inside the Update method and debuget again now the result are great:

c1b3f0fab2ac4d3a.png

but the problem is that when enemy initialize on screen and I check for collision it's always true and the values of position.X don't change (I understand that the problem come from the collision , because when I remove the code for collision the problem disappear).
and the second problem I am now seeing is that the box become to big while the model is moving maybe I have to calculate the old and the new position and then redraw the center of the box ?
f8b9967aee59e88e.png
Someone..... ?
Can we see your BB testing function code? Also, when checking collisions with bounding volumes, I think it's very important to take model transformations into account (i.e. checking with transformed bounding boxes).
There's no "hard", and "the impossible" takes just a little time.
Well I upgrade the code above a little bit:

protected BoundingBox CalculateBox()
{
Matrix worldTransform = Matrix.CreateTranslation(Vector3.Zero);
Vector3 min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
Vector3 max = new Vector3(float.MinValue, float.MinValue, float.MinValue);
ModelMesh mesh = myModel.Meshes[0];
foreach (ModelMeshPart meshPart in mesh.MeshParts)
{
// Vertex buffer parameters
int vertexStride = meshPart.VertexBuffer.VertexDeclaration.VertexStride;
int vertexBufferSize = meshPart.NumVertices * vertexStride;
// Get vertex data as float
float[] vertexData = new float[vertexBufferSize / sizeof(float)];
meshPart.VertexBuffer.GetData<float>(vertexData);
// Iterate through vertices (possibly) growing bounding box, all calculations are done in world space
for (int i = 0; i < vertexBufferSize / sizeof(float); i += vertexStride / sizeof(float))
{
Vector3 transformedPosition = Vector3.Transform(new Vector3(vertexData, vertexData[i + 1], vertexData[i + 2]), worldTransform);
min = Vector3.Min(min, transformedPosition);
max = Vector3.Max(max, transformedPosition);
}
}
// Create and return bounding box
return new BoundingBox(min, max);

Now I get better bounding box around my model,but I am not sure how WorldTransform is changing the transformation .

So I am drawing my player this way:

foreach (ModelMesh mesh in myModel.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
if (effect is BasicEffect)
{
(effect).EnableDefaultLighting();
}
effect.World = transforms[mesh.ParentBone.Index] *
Matrix.CreateScale(1 / mesh.BoundingSphere.Radius)
* scaling * rotation * translation;

effect.View = Matrix.CreateLookAt(
new Microsoft.Xna.Framework.Vector3(0, 0, 3),
Microsoft.Xna.Framework.Vector3.Zero,
Microsoft.Xna.Framework.Vector3.Up);
effect.Projection = Matrix.CreatePerspective(
1, 1 / GraphicsDevice.Viewport.AspectRatio, 1f, 10000);
}
mesh.Draw();
}
}

and I am drawing enemy this way:

Matrix[] transforms = new Matrix[texture.Bones.Count];
texture.CopyAbsoluteBoneTransformsTo(transforms);
foreach (ModelMesh meshh in texture.Meshes)
{
foreach (BasicEffect effect in meshh.Effects)
{
if (effect is BasicEffect)
{
(effect).EnableDefaultLighting();
}
effect.World = transforms[meshh.ParentBone.Index] *
Matrix.CreateRotationY(modelRotation)
* Matrix.CreateTranslation(position) ;

effect.View = Matrix.CreateLookAt(new Vector3(0.0f, 50.0f, 5000.0f),
Vector3.Zero, Vector3.Up);
effect.Projection = Matrix.CreatePerspectiveFieldOfView(
MathHelper.ToRadians(45.0f), aspectRatio,
1.0f, 10000.0f);
}
meshh.Draw();
}

and check for collision this way:

for (int i = enemies.Count - 1; i >= 0; i--)
{
enemies.Update(gameTime);
if (enemies.Sbox.Intersects(bb))
{
enemies.Alive = false;
}
}

Where enemies is List<Enemy>.
The result is :
0be8e8103ee5002b.png

The white bounding box is the player and the red is the enemy.
but no matter where the player is the enemy always stop at this red line in the middle.
When I debug the collision code I receive this :
b690d3867a80ffc5.png
I hope this is enough , if you need something else just say :)
I don't know C#, so I'll suggest you something in C++. Hope you can understand and convert them for your needs.

First, a bounding box can be defined by minimum and maximum points. These points' components are retrieved from minimum and maximum values from all vertices' components, respectively. So, calculation is easy:
loop throug all vertices
{
min_x = the smallest x component of all vertices,
min_y = the smallest y component of all vertices,
min_z = the smallest z component of all vertices,

max_x = the biggest x component of all vertices,
max_y = the biggest y component of all vertices,
max_z = the biggest z component of all vertices,
}

Try this snippet to calculate your bounding box:
float _min = FLT_MIN; //in your code, this would be float.MinValue
float _max = FLT_MAX; //float.MaxValue

float min_x, min_y, min_z;
float max_x, max_y, max_z;
min_x = min_y = min_z = _max;
max_x = max_y = max_z = _min;
for (v = 0; v < numVertices; v++)
{
float x = vertices[v].x, y = vertices[v].y, z = vertices[v].z;
min_x = min (min_x, x);
min_y = min (min_y, y);
min_z = min (min_z, z);

max_x = max (max_x, x);
max_y = max (max_y, y);
max_z = max (max_z, z);
}


While checking for AABB collisions, I recommend you to check "transformed AABBs". Here a snippet from my engine to calculate "transformed AABB":

const AABB
AABB::Transform (const matrix4x4& objectWorldMatrix) const
{
AABB aabb;

vector3 c = this->CenterPt(), //CenterPt() returns (minPt + maxPt) / 2.0f;
e = .5f * this->Extents(); //Extents() returns (maxPt - minPt);

c = c.TransformCoord (objectWorldMatrix); //coord

matrix4x4 mat;
mat.Identity();

mat(0, 0) = objectWorldMatrix(0, 0);
mat(1, 0) = objectWorldMatrix(1, 0);
mat(2, 0) = objectWorldMatrix(2, 0);
mat(0, 1) = objectWorldMatrix(0, 1);
mat(1, 1) = objectWorldMatrix(1, 1);
mat(2, 1) = objectWorldMatrix(2, 1);
mat(0, 2) = objectWorldMatrix(0, 2);
mat(1, 2) = objectWorldMatrix(1, 2);
mat(2, 2) = objectWorldMatrix(2, 2);
e = e.TransformNormal (mat); //normal

aabb.MinPt = (m - e);
aabb.MaxPt = (m + e);

return aabb;
}

Note that the keypoint here is this: Don't even touch min and max points of an aabb, just build another one with transformed points and return it. So, before checking, don't touch your model mesh's original AABB (calculated once after loading/creating) and calculate a transformed one from this original "in every frame".

Now you got a transformed bounding box, and you can check collisions.

Try these. And tell us the results.

hth.
-R
There's no "hard", and "the impossible" takes just a little time.
Well I build your snipped code and i find out that the above I post do the same,but I am not able to understand the c++ collision code and what is AABB ?
When however the result now is this, but I still can detect collision , simply using the Intersect method :
09552167d47a5c0f.png
AABB means "Axis Aligned Bounding Box" (i.e. transformed bounding box).

I didn't gave you any collision code. I gave bounding box calculation and transformation. So intersection/collision is up to you.

Transformation is the keypoint here because checking transformed bounding boxes (AABBs) is the only, the best and the most accurate way. Note that a bounding box must be calculated once after model creating/loading. And you must check the collisions/intersections between transformed bounding boxes.

So, in every frame:
1) Process Input: Get input from mouse, keyboard, joystick etc. and process them if you're using'em (e.g. to rotate and/or move a model or camera).
2) Update your models' transformations: Calculate world matrix for all your models. Calculate view and projection matrices if you need.
2-a) Update your models' bounding boxes: This is the keypoint. I talked about transforming bounding boxes in my previous post. Use world matrices to update bounding boxes. I say again: Don't even touch a model's original bounding box. Create a transformed one instead. And store it.
NOTE: I think you're something wrong in this step. For example, I think you're checking original (i.e. calculated after model creating) bounding boxes. They're always placed at world-space origin so they always instersects each other. Above code gives you how they are transformed.
3) Update physics: This means checking collisions/intersections for you. Don't forget: Don't update original bounding boxes. Create another ones over the originals but with transformed parameters. So, don't use original bounding boxes for checking collisions, use the transformed ones calculated in previous step instead.
4) Render: Whatever you like.

hth.
-R
There's no "hard", and "the impossible" takes just a little time.
Thanks for explanation,but I wrote my own Intersect function and now its working perfectly :)
I want to ask you how can I move on object to another, I mean that I have to model in world space with some coordinates and I initialize the enemy model at these position new Vector3(0,0,3); and my player is at position Vector3(100,100,3); .
So when ever my player move I want the other object to follow it,after its initialization and calculate the rotation too, how can I do that ?
I apply a picture for better understanding :)
ad0deb9699924d3c.png

This topic is closed to new replies.

Advertisement