I am currently working on a Minecraft like game with OpenGL and C++. I've gotten as far as abstracting a Camera object and setting up movement and even defining basic gravity like simulations, but I am stuck on collision detection and resolution.
Movement is defined by a function which adds an 'x' and 'z' velocity depending on the key pressed. I finally get a velocity vector which may look like (-2.0, 0.0, 2.5)
. The Velocity vector is then added to the camera's Position vector in a Move function. Then, I look for collisions and try to resolve them (currently only with the y-axis but even that does not work). The code for the Move function looks like:
void Camera::Move(const std::vector<glm::vec3>& cubePositions)
{
glm::vec3 nPos = glm::vec3((int)(round(Position.x)), (int)(round(Position.y)), (int)(round(Position.z)));
Position += Velocity;
// Collision resolution
for (float i = -2.0f; i <= 2.0f; i++)
{
for (float j = -2.0f; j <= 2.0f; j++)
{
for (float k = -2.0f; k <= 2.0f; k++)
{
if (std::find(cubePositions.begin(), cubePositions.end(), glm::vec3(nPos.x - i, nPos.y - j, nPos.z - k)) == cubePositions.end())
continue;
glm::vec3 box = glm::vec3(nPos.x - i, nPos.y - j, nPos.z - k);
if
(((Position.x - 0.5f <= box.x + 0.5f) || (Position.x + 0.5f >= box.x - 0.5f)) &&
((Position.y - 2.0f <= box.y + 0.5f) || (Position.y + 0.5f >= box.y - 0.5f)) &&
((Position.z - 0.5f <= box.z + 0.5f) || (Position.z + 0.5f >= box.z - 0.5f)))
{
LOG("Collision check with box " << box.x << " " << box.y << " " << box.z);
Position.y -= Velocity.y;
LOG("Position.y: " << Position.y);
}
}
}
}
LOG("Position: " << Position.x << " " << Position.y << " " << Position.z);
Velocity = glm::vec3(0.0f);
}
(LOG is just a macro which prints to the screen). Right now, when a collision with a block is detected, it causes this sort of jumpy motion. This is the output:
...
[LOG] Position: 2.10997 -12.1245 3.19591
[LOG] Position: 2.10997 -12.1899 3.19591
[LOG] Position: 2.10997 -12.2546 3.19591
[LOG] Position: 2.10997 -12.3261 3.19591
[LOG] Position: 2.10997 -12.3952 3.19591
[LOG] Position: 2.10997 -12.4618 3.19591
[LOG] Position: 2.10997 -12.5288 3.19591
[LOG] Collision check with box 4 -15 5
[LOG] Position.y: -12.5288
[LOG] Collision check with box 4 -15 4
[LOG] Position.y: -12.4595
[LOG] Collision check with box 4 -15 3
[LOG] Position.y: -12.3903
[LOG] Collision check with box 4 -15 2
[LOG] Position.y: -12.321
[LOG] Collision check with box 4 -15 1
[LOG] Position.y: -12.2518
[LOG] Collision check with box 3 -15 5
[LOG] Position.y: -12.1825
[LOG] Collision check with box 3 -15 4
[LOG] Position.y: -12.1133
[LOG] Collision check with box 3 -15 3
[LOG] Position.y: -12.044
[LOG] Collision check with box 3 -15 2
[LOG] Position.y: -11.9748
[LOG] Collision check with box 3 -15 1
[LOG] Position.y: -11.9055
[LOG] Collision check with box 2 -15 5
[LOG] Position.y: -11.8363
[LOG] Collision check with box 2 -15 4
[LOG] Position.y: -11.767
[LOG] Collision check with box 2 -15 3
[LOG] Position.y: -11.6978
[LOG] Collision check with box 2 -15 2
[LOG] Position.y: -11.6285
[LOG] Collision check with box 2 -15 1
[LOG] Position.y: -11.5593
[LOG] Collision check with box 1 -15 5
[LOG] Position.y: -11.49
[LOG] Collision check with box 1 -15 4
[LOG] Position.y: -11.4208
[LOG] Collision check with box 1 -15 3
[LOG] Position.y: -11.3515
[LOG] Collision check with box 1 -15 2
[LOG] Position.y: -11.2823
[LOG] Collision check with box 1 -15 1
[LOG] Position.y: -11.213
[LOG] Collision check with box 0 -15 5
[LOG] Position.y: -11.1437
[LOG] Collision check with box 0 -15 4
[LOG] Position.y: -11.0745
[LOG] Collision check with box 0 -15 3
[LOG] Position.y: -11.0052
[LOG] Collision check with box 0 -15 2
[LOG] Position.y: -10.936
[LOG] Collision check with box 0 -15 1
[LOG] Position.y: -10.8667
[LOG] Position: 2.10997 -10.8667 3.19591
[LOG] Position: 2.10997 -10.9176 3.19591
...
(here, when I say with box x y z, x y z refers to the box's co-ordinates, which are just transformations applied to a defined set of vertices when each box is drawn)
I have been working on this for a while, and looked for a while for a solution, but could not find any. I appreciate any help :)
Edit: I changed the if-condition since I found out it was, wrong. But the bouncing motion still exists, only to a lesser scale. The correct if-condition:
if
(((Position.x - 0.5f <= box.x + 0.5f) && (Position.x + 0.5f >= box.x - 0.5f)) &&
((Position.y - 2.0f <= box.y + 0.5f) && (Position.y + 0.5f >= box.y - 0.5f)) &&
((Position.z - 0.5f <= box.z + 0.5f) && (Position.z + 0.5f >= box.z - 0.5f)))
The output:
...
[LOG] Position: 5.43324 -12.5657 6.24592
[LOG] Collision check with box 6 -15 7
[LOG] Position.y: -12.5657
[LOG] Collision check with box 6 -15 6
[LOG] Position.y: -12.5014
[LOG] Collision check with box 5 -15 7
[LOG] Position.y: -12.4371
[LOG] Position: 5.43324 -12.4371 6.24592
[LOG] Position: 5.43324 -12.5011 6.24592
[LOG] Collision check with box 6 -15 7
[LOG] Position.y: -12.5011
[LOG] Collision check with box 6 -15 6
[LOG] Position.y: -12.4362
[LOG] Position: 5.43324 -12.4362 6.24592
[LOG] Position: 5.43324 -12.5246 6.24592
[LOG] Collision check with box 6 -15 7
[LOG] Position.y: -12.5246
[LOG] Collision check with box 6 -15 6
[LOG] Position.y: -12.4312
[LOG] Position: 5.43324 -12.4312 6.24592
...