Advertisement

Collision prevention Block to Block in 3d Space

Started by November 30, 2022 09:28 PM
19 comments, last by Tom Sloper 2 years ago

Hello,

I am currently programming a Jump and Run Game with OpenGL and I don't know how I prevent the Kamera from moving into a Block.

So far, there are only cubes in the Scene (length = 1) and the camera is a cuboid 1,2,1 (y is the upgoing coordinate).

I am already able to check if the camera is going to be inside a cube in the next render call but I am struggling on preventing it from going inside it. I have tried it with different approaches but I don't think that those are the right way to go.

Can anyone tell me what the code should look like and how it is done or link me to a tutorial?

You need a function to calculate the closest point on a box surface from a given point inside the box.
This tells you where to move the camera to get outside and travelling the shortest distance.

You also need such things for collision detection and resolve anyway.
Algorithm could be to calculate distances to the 4 edges, project to the edge with the shortest distance.

Advertisement

Some code (untested):

vec2 CalcClosestPointIfInside (vec2 boxMin, vec2 boxMax, vec2 point)
{
	if (point.x < boxMin.x || point.x > boxMax.x ||
		point.y < boxMin.y || point.y > boxMax.y) 
			return point; // point is outside the box
			
	vec2 center = (boxMin + boxMax) * .5f;
	vec2 result;
	result.x = (point.x - center.x > 0.f ? boxMax.x : boxMin.x); // project to the closer edge
	result.y = (point.y - center.y > 0.f ? boxMax.y : boxMin.y);
	return result;
}

boxMin may refer to the top left corner of the axis aligned box, boxMax to the bottom right. But this depends on conventions of your coordinate system, so i prefer min max naming.

If your box is not axis aligned, you can transform the point into the local space of the box, and transform the result back to world space afterwards.

Best resource to look up such tests for more complex shapes: https://github.com/davideberly/GeometricTools/blob/master/GTE/Mathematics/DistPointAlignedBox.h

Looks a bit complicated due to heavy OOP, so it takes some time to find the actual math, though. : )

Aloxen said:
and the camera is a cuboid 1,2,1

Oops, so your camera is a box too, not a point?

So you want to project a box out of another box, correct?

Some years ago this was asked here, and i made an algorithm for a continuous solution.
Continuous here means the solution changed gradually even if the box crosses a diagonal of the other box, which might be nice.
But while continuous, this no longer minimizes energy, so the projection is not along the shortest path near corners.

I'd need to search for this, so let me know first which option sounds better to you…

I also assume you want to keep both boxes axis aligned, so no rotation, like real world physics would cause?

Thank you, I will have a look at it.
For the min and Max point calculation: I have the position of a Block, which is the center of it. why is the box min a vec2?
Would I compute the min point x coordinate like : min.x =Center-0.5, min.y = Center-0.5 and min.z = Center - 0.5?

Advertisement

@undefined Well, like in Minecraft, the cam is 1.75 tall and the surrounding is 0.5 in all directions.

Aloxen said:
For the min and Max point calculation: I have the position of a Block, which is the center of it. why is the box min a vec2?

So your boxes store a center position, which is x and y in 2D, thus we can use a vec2 if we use some linear math lib. (Edit: I thought you're in 2D, but 3D is the same math ofc.)
There are two primary ways to store boxes:

struct box1
{
	float centerX, centerY; // = vec2 center
	float halfWidth, halfHeight; // = vec2 extent // we could also store full width ofc.
}
struct box2
{
	float left, bottom; // = vec2 minCorner
	float right, up; // = vec2 maxCorner
}

Option 1 usually is faster for geometric intersection and closest point tests

Option 2 usually is faster for range queries, e.g. collision detection

Because collision detection processes way more boxes, usually option 1 is the better choice.
But just to let you know. No need to change your preferred conventions you are used to.

Aloxen said:
Would I compute the min point x coordinate like : min.x =Center-0.5, min.y = Center-0.5 and min.z = Center - 0.5?

Yes.

My Collision Detection Function is just a simple If Statement.

if (A.x-0.5 < B.x+0.5) and (A.x+0.5 > B.x-0.5) and

(A.y-1.5 < B.y+0.5) and (A.y+0.5 > B.y-0.5) and

(A.z-0.5 < B.z+0.5) and (A.z+0.5 > B.z-0.5){

result = true else result:=false

I have to write the program in Pascal so the code might not be 100% correct.

Aloxen said:
Well, like in Minecraft, the cam is 1.75 tall and the surrounding is 0.5 in all directions.

Ok.

First, you should use a generic data structure to represent boxes. Don't hard code magic numbers like 1.75 or use custom variables for that. Use Boxes, capsules, spheres, etc. You need such shapes and math much more often than just for the current special case, so it should be generic functionality. You know, write once, reuse anywhere.

Second, you more likely talk about a player controller, not just a camera. Player controllers usually use a capsule, a compressed capsule (to make the round ends more flat), or a cylinder (which causes harder math than capsules).
Box characters are not ideal, because the corners don't give uniform behavior independent of view direction, or worse: View direction affects physics. (Depending on if they remain axis aligned or not)
The link i gave should cover all necessary tests to implement collisions with a static box world.
Sounds you're a beginner. This isn't so easy to get right. Expect to spend some time on it… ; )

This topic is closed to new replies.

Advertisement