-
|
|
BoundingBox Collision need help (new at XNA)
|
Hello,
I'm a student and need some help figuring out how to detect collision at which side of the boundingbox the collision happens.
I've searched for alot of differant tutorials but none really help me with this problem. Our game is build up from cubes so a boundingbox would be optimal to use.
EDIT: Removed Link.
I hope for a quick reply,
- Dastrus
|
|
-
|
|
Re: BoundingBox Collision need help (new at XNA)
|
Game hobbyist hell-bent on coding a diabolical Matrix
|
|
-
|
|
Re: BoundingBox Collision need help (new at XNA)
|
Thanks, it helped me alot.
I have stumbled across a problem though.
I get stuck at the corners. Do any of you have a solution?
Here's the code:
| private static void CheckCorners(CModel _model) | | { | | Vector3[] cornerPoints = new Vector3[2]; | | cornerPoints[0] = new Vector3(_model.position.X - 0.5f, _model.position.Y - 0.5f, _model.position.Z - 0.5f); | | cornerPoints[1] = new Vector3(_model.position.X + 0.5f, _model.position.Y + 0.5f, _model.position.Z + 0.5f); | | _model.modelBoundingBox = BoundingBox.CreateFromPoints(cornerPoints); | | } | | | | private static void CheckCorners2(CModel _model) | | { | | Vector3[] cornerPoints = new Vector3[2]; | | cornerPoints[0] = new Vector3(_model.position.X - 1, _model.position.Y - 1, _model.position.Z - 1); | | cornerPoints[1] = new Vector3(_model.position.X + 1, _model.position.Y + 1, _model.position.Z + 1); | | _model.modelBoundingBox = BoundingBox.CreateFromPoints(cornerPoints); | | } | | | | private static void CheckCollision(CCamera camera, CPlayer model1, CModel model2) | | { | | if (model1.modelBoundingBox.Intersects(model2.modelBoundingBox)) | | { | | // Create a vector going from body0 to body1 | | Vector3 vecToBody1 = model1.world.Translation - model2.world.Translation; | | | | // If this float is positive then the right vector points in the general direction of body1 | | Single A = Vector3.Dot(model2.world.Right, vecToBody1); | | | | // If this single is positive, then vector up points in the general direction of body1 | | Single B = Vector3.Dot(model2.world.Up, vecToBody1); | | | | // If this single is positive, than vector forward points in the general direction of body1 | | Single C = Vector3.Dot(model2.world.Forward, vecToBody1); | | | | if (A > (model2.scale.X - 1)) | | { | | camera.cameraPosition.X = camera.lastPosition.X; | | } | | else if (A < (-model2.scale.X + 1)) | | { | | camera.cameraPosition.X = camera.lastPosition.X; | | } | | | | //if (B > 0.01f) | | //{ | | // camera.cameraPosition.Y -= 0.1f; | | //} | | //if (B < 0) | | //{ | | // camera.cameraPosition.Y += 0.1f; | | //} | | | | if (C > (model2.scale.X - 1)) | | { | | camera.cameraPosition.Z = camera.lastPosition.Z; | | } | | else if (C < (-model2.scale.X + 1)) | | { | | camera.cameraPosition.Z = camera.lastPosition.Z; | | } | | | | | | return; | | } | | } |
|
|
-
|
|
Re: BoundingBox Collision need help (new at XNA)
|
I've edited my code abit and it works ok at times, but when I increase the speed of my character it will go through the boundingbox (even sometimes at the speed it has now 3.0f * deltaTime), and the character will get stuck at the far edges. The edges are abit of a problem so I would like to hear a better alternative, or a way to fix it. Would also like an alternative to the "going through the boundingBox at high speed" problem.
Could any of you please help me?
Thank alot,
Dastrus
| private static void CheckCorners(CModel _model) | | { | | Vector3[] cornerPoints = new Vector3[2]; | | cornerPoints[0] = new Vector3(_model.position.X - (_model.scale.X / 2), _model.position.Y - (_model.scale.X / 2), _model.position.Z - (_model.scale.X / 2)); | | cornerPoints[1] = new Vector3(_model.position.X + (_model.scale.X / 2), _model.position.Y + (_model.scale.X / 2), _model.position.Z + (_model.scale.X / 2)); | | _model.modelBoundingBox = BoundingBox.CreateFromPoints(cornerPoints); | | } | | | | private static void CheckCollision(CCamera camera, CPlayer model1, CModel model2) | | { | | if (model1.modelBoundingBox.Intersects(model2.modelBoundingBox)) | | { | | // Create a vector going from model1 to model2 | | Vector3 vecToModel2 = model2.world.Translation - model1.world.Translation; | | | | // If this float is positive then the right vector points in the general direction of body1 | | Single A = Vector3.Dot(model1.world.Right, vecToModel2); | | | | // If this single is positive, then vector up points in the general direction of body1 | | Single B = Vector3.Dot(model1.world.Up, vecToModel2); | | | | // If this single is positive, than vector forward points in the general direction of body1 | | Single C = Vector3.Dot(model1.world.Forward, vecToModel2); | | | | //right side | | if (A >= ((model2.scale.X - 1) + (0.24f * model2.scale.X)) && camera.lastPosition.X < camera.cameraPosition.X) | | { | | camera.cameraPosition.X = camera.lastPosition.X; | | } | | //left side | | else if (A <= (-(model2.scale.X - 1) - (0.24f * model2.scale.X)) && camera.lastPosition.X > camera.cameraPosition.X) | | { | | camera.cameraPosition.X = camera.lastPosition.X; | | } | | | | //up side | | if (B >= ((model2.scale.Y - 1) + (0.24f * model2.scale.Y)) && camera.lastPosition.Y < camera.cameraPosition.Y) | | { | | camera.cameraPosition.Y = camera.lastPosition.Y; | | } | | //down side | | else if (B <= (-(model2.scale.Y - 1) - (0.24f * model2.scale.Y)) && camera.lastPosition.Y > camera.cameraPosition.Y) | | { | | //camera.isOnGround = true; | | camera.cameraPosition.Y = camera.lastPosition.Y; | | } | | | | //front side | | if (C >= ((model2.scale.Z - 1) + (0.24f * model2.scale.Z)) && camera.lastPosition.Z > camera.cameraPosition.Z) | | { | | camera.cameraPosition.Z = camera.lastPosition.Z; | | } | | //back side | | else if (C <= (-(model2.scale.Z - 1) - (0.24f * model2.scale.Z)) && camera.lastPosition.Z < camera.cameraPosition.Z) | | { | | camera.cameraPosition.Z = camera.lastPosition.Z; | | } | | | | return; | | } | | } |
|
|
-
|
|
Re: BoundingBox Collision need help (new at XNA)
|
The reason why you pass through the box is because you're working in a digital, discretized world instead of an analog, continuous world.
What the hell does that mean?
Well, your collision routines check an intersection at point v0 and then at point v1, but the problem is, they don't check the continuous stream of positions you could be in between those two points.
What you need to do is the following, in psuedo code:
Cast a ray from v0 to v1 and check if the ray intersects the box.
If the ray intersects the box, then do those calculations.
I think I'll have eggs for breakfast.
|
|
-
|
|
Re: BoundingBox Collision need help (new at XNA)
|
I did try ray collision before, but it didn't really seem to work the way I wanted it to work so I avoided it. But it does indeed seem like the best option.
Here is my code, I tried using "if (distanceDOWN <= 0.1f)" but that didn't seem to work, unless I made it <= 10f, but once I did that to all I couldn't move when it collided.
I must be doing something wrong, I hope one of you can figure out what.
| private void RayIntersect(CPlayer avatar, CModel model, Vector3 scaleDirection) | | { | | Vector3 directionDOWN = avatar.position + new Vector3(0, -1, 0); | | float distanceDOWN = directionDOWN.Length(); | | //directionDOWN.Normalize(); | | | | Vector3 directionUP = avatar.position + new Vector3(0, 1, 0); | | float distanceUP = directionUP.Length(); | | //directionUP.Normalize(); | | | | Vector3 directionFORWARD = avatar.position + new Vector3(0, 0, 1); | | float distanceFORWARD = directionFORWARD.Length(); | | //directionFORWARD.Normalize(); | | | | Vector3 directionBACK = avatar.position + new Vector3(0, 0, -1); | | float distanceBACK = directionBACK.Length(); | | //directionBACK.Normalize(); | | | | Vector3 directionRIGHT = avatar.position + new Vector3(1, 0, 0); | | float distanceRIGHT = directionRIGHT.Length(); | | //directionRIGHT.Normalize(); | | | | Vector3 directionLEFT = avatar.position + new Vector3(-1, 0, 0); | | float distanceLEFT = directionLEFT.Length(); | | //directionLEFT.Normalize(); | | | | Ray rayUP = new Ray(avatar.position, directionUP); | | Ray rayDOWN = new Ray(avatar.position, directionDOWN); | | Ray rayFORWARD = new Ray(avatar.position, directionFORWARD); | | Ray rayBACK = new Ray(avatar.position, directionBACK); | | Ray rayRIGHT = new Ray(avatar.position, directionRIGHT); | | Ray rayLEFT = new Ray(avatar.position, directionLEFT); | | | | float? intersectionDOWN = rayDOWN.Intersects(model.modelBoundingBox); | | float? intersectionUP = rayUP.Intersects(model.modelBoundingBox); | | float? intersectionFORWARD = rayFORWARD.Intersects(model.modelBoundingBox); | | float? intersectionBACK = rayBACK.Intersects(model.modelBoundingBox); | | float? intersectionRIGHT = rayRIGHT.Intersects(model.modelBoundingBox); | | float? intersectionLEFT = rayLEFT.Intersects(model.modelBoundingBox); | | | | if (intersectionDOWN != null) | | { | | if (intersectionDOWN <= 0.01f && camera.lastPosition.Y < camera.cameraPosition.Y) | | { | | camera.cameraPosition.Y = camera.lastPosition.Y; | | } | | } | | | | if (intersectionUP != null) | | { | | if (intersectionUP <= 0.01f && camera.lastPosition.Y > camera.cameraPosition.Y) | | { | | camera.cameraPosition.Y = camera.lastPosition.Y; | | } | | } | | | | if (intersectionFORWARD != null) | | { | | if (intersectionFORWARD <= 0.01f) | | { | | camera.cameraPosition.Z = camera.lastPosition.Z; | | } | | } | | | | if (intersectionBACK != null) | | { | | if (intersectionBACK <= 0.01f) | | { | | camera.cameraPosition.Z = camera.lastPosition.Z; | | } | | } | | | | if (intersectionRIGHT != null) | | { | | if (intersectionRIGHT <= 0.01f && camera.lastPosition.X < camera.cameraPosition.X) | | { | | camera.cameraPosition.X = camera.lastPosition.X; | | } | | } | | | | if (intersectionLEFT != null) | | { | | if (intersectionLEFT <= 0.01f && camera.lastPosition.X > camera.cameraPosition.X) | | { | | camera.cameraPosition.X = camera.lastPosition.X; | | //model.scale += scaleDirection; | | } | | } | | | | } |
|
|
-
|
|
Re: BoundingBox Collision need help (new at XNA)
|
Hi,
I found this article from XNA Wiki very useful when I first started with bounding boxes.. It is a completed class which you can use for now and when you get more familiar with bounding boxes you will be able to write your own class which will be the best solution for your project.
Hope this helps.
|
|
-
|
|
Re: BoundingBox Collision need help (new at XNA)
|
I forgot to mention..
There's one more function that I used to check for collision:
| static BasicEffect effect; | | static VertexDeclaration vertDecl; | | | | static Vector3[] tempVecs3 = new Vector3[512]; | | static ushort[] tempUshorts = new ushort[512 * 3]; | | | | public static BoundingBox CalculateBoundingBox(ModelMesh mm, Matrix transform) | | { | | BoundingBox bb = new BoundingBox(); | | bool first = true; | | Matrix x = Matrix.Identity; | | ModelBone mb = mm.ParentBone; | | | | while (mb != null) | | { | | x = x * mb.Transform; | | mb = mb.Parent; | | } | | | | foreach (ModelMeshPart mp in mm.MeshParts) | | { | | int n = mp.NumVertices; | | if (n > tempVecs3.Length) | | tempVecs3 = new Vector3[n + 128]; | | int l = mp.PrimitiveCount * 3; | | if (l > tempUshorts.Length) | | tempUshorts = new ushort[l + 128]; | | if (n == 0 || l == 0) | | continue; | | mm.IndexBuffer.GetData<ushort>(tempUshorts, mp.StartIndex, l); | | mm.VertexBuffer.GetData<Vector3>(mp.StreamOffset, tempVecs3, mp.BaseVertex, n, mp.VertexStride); | | if (first) | | { | | bb.Min = Vector3.Transform(tempVecs3[tempUshorts[0]], x); | | bb.Max = bb.Min; | | first = false; | | } | | for (int i = 0; i != l; ++i) | | { | | ushort us = tempUshorts[i]; | | Vector3 v = Vector3.Transform(tempVecs3[us], x); | | Vector3.Max(ref v, ref bb.Max, out bb.Max); | | Vector3.Min(ref v, ref bb.Min, out bb.Min); | | } | | } | | return bb; | | } | And you can simply call this function like in the code below:
| BoundingBox boundingBox = new BoundingBox(); | | boundingBox = CalculateBoundingBox(mesh, TransformMatrix); | | | | Vector3[] corners = boundingBox.GetCorners(); | | Vector3.Transform(corners, ref TransformMatrix, corners); | | boundingBox = BoundingBox.CreateFromPoints(corners); | And you can easily check for collision with:
| return boundingBox.Intersects(AnotherBoundingBoxOrSomething); | And you get a true / false value. Simple as that..
|
|
|