I save to a list the chunk I am colliding with, and I do all the checks there.
Chunk you are colliding with or block?
The easiest solution right now is to go through those coordinates from Y0, to Yn, and if there is a block there, set that to the highest block.
Thanks, will take a look at that.
Just looking at my collision again, may switch to AABB, do you have any experience of this?
You SHOULD switch to AABB. Its one of the easiest algorithms to use because the the blocks are aligned to the axises, and spheres are round.
^ take a good look at that. it explains AABB-AABB, AABB-Sphere, and Sphere-Sphere
I used this
Thanks for that,
I’ve already put together a simple AABB class, this look ok?
public class AABB {
Vector3f vecMax = new Vector3f(0,0,0);
Vector3f vecMin = new Vector3f(0,0,0);
public AABB(Vector3f bottom, Vector3f top)
{
vecMax.x = top.x; vecMax.y = top.y; vecMax.z = top.z;
vecMin.x = bottom.x; vecMin.y = bottom.y; vecMin.z = bottom.z;
}
public AABB(float tx, float ty, float tz, float bx, float by, float bz)
{
vecMax.x = tx; vecMax.y = ty; vecMax.z = tz;
vecMin.x = bx; vecMin.y = by; vecMin.z = bz;
}
public static boolean detectCollision(AABB tBox1, AABB tBox2)
{
// System.out.println("minx: " + tBox1.vecMin.x + " obj max:" + tBox2.vecMax.x);
// System.out.println("miny: " + tBox1.vecMin.y + " obj max:" + tBox2.vecMax.y);
// System.out.println("minz: " + tBox1.vecMin.z + " obj max:" + tBox2.vecMax.z);
if(tBox1.vecMin.x > tBox2.vecMax.x) return false;
if(tBox1.vecMin.y > tBox2.vecMax.y) return false;
if(tBox1.vecMin.z > tBox2.vecMax.z) return false;
if(tBox1.vecMax.x < tBox2.vecMin.x) return false;
if(tBox1.vecMax.y < tBox2.vecMin.y) return false;
if(tBox1.vecMax.z < tBox2.vecMin.z) return false;
return true;
}
}
My issue is, how many blocks do you check for collision with? Somebody mentioned the blocks around the player which still means using voxel space and also AABB.
Just added another check for z axis and it worked more than fine.
All you need to do is run AABB-Sphere(if you are using a sphere for the player) against the block above, below, to the right, to the left.
Ok - so I guess you still need to convert from camera space (position of player) to voxel space then?
Yes, and make sure you are using the position of the voxel you are contained in, not the position of the voxel you are standing on.
Personally, I didn’t.
Wait, it depends on if you store your blocks with world position(where in the world) or block position.
Blocks are translated to world positions, was meaning, as they are held in a 3d array, we can offset into this to get the block.
I render my blocks in each chunk with the following:
private int createChunkList() {
tx = 0; ty = 0; tz = 0;
int iHidden = 0;
int iBlockCount = 0;
boolean bLeft = !false;
boolean bRight = !false;
boolean bAbove = !false;
boolean bBelow = !false;
boolean bFront = !false;
boolean bBack = !false;
boolean bDefault = true;
glEnable(GL11.GL_CULL_FACE);
GL11.glEnable(GL_TEXTURE_2D);
// some how need a way of getting the blocks texture bound...
GL11.glBindTexture(GL_TEXTURE_2D, TextureManager.getInstance().getId());
glBegin(GL11.GL_QUADS);
for (int x = 0; x < Chunk.CHUNK_SIZE; x++) {
for (int y = 0; y < Chunk.CHUNK_SIZE; y++) {
for (int z = 0; z < Chunk.CHUNK_SIZE; z++) {
Block block = GetBlock(x,y,z);
texture = TextureManager.getInstance().getTexture(block.getType());
if(!GetBlock(x,y,z).IsActive()) //
{
continue;
}
bLeft = bDefault;
if(x > 0)
{
bLeft = Blocks[x-1][y][z].IsActive();
} else bLeft = false;
bRight = bDefault;
if(x < Chunk.CHUNK_SIZE - 1)
{
bRight = Blocks[x+1][y][z].IsActive();
} else bRight = false;
bAbove = bDefault;
if(y > 0)
{
bAbove = Blocks[x][y-1][z].IsActive();
} else bAbove = false;
bBelow = bDefault;
if(y < Chunk.CHUNK_SIZE - 1)
{
bBelow = Blocks[x][y+1][z].IsActive();
} else bBelow = false;
bFront = bDefault;
if(z > 0)
{
bFront = Blocks[x][y][z-1].IsActive();
} else bFront = false;
bBack = bDefault;
if(z < Chunk.CHUNK_SIZE - 1)
{
bBack = Blocks[x][y][z+1].IsActive();
} else bBack = false;
boolean bResult = bLeft & bRight & bAbove &
bBelow & bFront & bBack;
if(!bResult) // Block is not hidden by neighbouring blocks
{
tx = ((xOffset * Chunk.CHUNK_SIZE) ) + (x);// << 1);
ty = ((yOffset * Chunk.CHUNK_SIZE) ) + (y);// << 1);
tz = ((zOffset * Chunk.CHUNK_SIZE) ) + (z);// << 1);
renderBlock(GetBlock(x,y,z).getType());
iBlockCount++; // total of blocks that can be seen
}
else
iHidden++; // amount of blocks that are surrounded
}
}
}
glEnd();
glDisable(GL11.GL_CULL_FACE);
return iBlockCount;
}
private void renderBlock(Block.BlockType type) {
GL11.glTexCoord2f(texture.u * 0.0625f, (texture.v + 1) * 0.0625f);
off_glVertex3f(-0.5f, -0.5f, 0.5f); // Bottom Left Of The Texture and Quad
GL11.glTexCoord2f((1+texture.u) * 0.0625f, (texture.v+1) * 0.0625f);
off_glVertex3f( 0.5f, -0.5f, 0.5f); // Bottom Right Of The Texture and Quad
GL11.glTexCoord2f((texture.u + 1) * 0.0625f, (0+texture.v) * 0.0625f);
off_glVertex3f( 0.5f, 0.5f, 0.5f); // Top Right Of The Texture and Quad
GL11.glTexCoord2f((texture.u + 0) * 0.0625f, (texture.v + 0) * 0.0625f);
off_glVertex3f(-0.5f, 0.5f, 0.5f); // Top Left Of The Texture and Quad
// Back Face
GL11.glTexCoord2f(texture.u * 0.0625f, (texture.v + 1) * 0.0625f);
off_glVertex3f(-0.5f, -0.5f, -0.5f); // Bottom Right Of The Texture and Quad
GL11.glTexCoord2f(texture.u * 0.0625f, texture.v * 0.0625f);
off_glVertex3f(-0.5f, 0.5f, -0.5f); // Top Right Of The Texture and Quad
GL11.glTexCoord2f((texture.u + 1) * 0.0625f, texture.v * 0.0625f);
off_glVertex3f( 0.5f, 0.5f, -0.5f); // Top Left Of The Texture and Quad
GL11.glTexCoord2f((texture.u + 1) * 0.0625f, (texture.v + 1) * 0.0625f);
off_glVertex3f( 0.5f, -0.5f, -0.5f); // Bottom Left Of The Texture and Quad
// Top Face
GL11.glTexCoord2f(texture.ut * 0.0625f, (texture.vt + 1) * 0.0625f);
off_glVertex3f(-0.5f, 0.5f, -0.5f); // Top Left Of The Texture and Quad
GL11.glTexCoord2f(texture.ut * 0.0625f, texture.vt * 0.0625f);
off_glVertex3f(-0.5f, 0.5f, 0.5f); // Bottom Left Of The Texture and Quad
GL11.glTexCoord2f((texture.ut + 1) * 0.0625f, texture.vt * 0.0625f);
off_glVertex3f( 0.5f, 0.5f, 0.5f); // Bottom Right Of The Texture and Quad
GL11.glTexCoord2f((texture.ut + 1) * 0.0625f, (texture.vt + 1) * 0.0625f);
off_glVertex3f( 0.5f, 0.5f, -0.5f); // Top Right Of The Texture and Quad
// Bottom Face
GL11.glTexCoord2f(texture.u * 0.0625f, (texture.v + 1) * 0.0625f);
off_glVertex3f(-0.5f, -0.5f, -0.5f); // Top Right Of The Texture and Quad
GL11.glTexCoord2f(texture.u * 0.0625f, texture.v * 0.0625f);
off_glVertex3f( 0.5f, -0.5f, -0.5f); // Top Left Of The Texture and Quad
GL11.glTexCoord2f((texture.u + 1) * 0.0625f, texture.v * 0.0625f);
off_glVertex3f( 0.5f, -0.5f, 0.5f); // Bottom Left Of The Texture and Quad
GL11.glTexCoord2f((texture.u + 1) * 0.0625f, (texture.v + 1) * 0.0625f);
off_glVertex3f(-0.5f, -0.5f, 0.5f); // Bottom Right Of The Texture and Quad
// Right face
GL11.glTexCoord2f(texture.u * 0.0625f, (texture.v + 1) * 0.0625f);
off_glVertex3f( 0.5f, -0.5f, -0.5f); // Bottom Right Of The Texture and Quad
GL11.glTexCoord2f(texture.u * 0.0625f, texture.v * 0.0625f);
off_glVertex3f( 0.5f, 0.5f, -0.5f); // Top Right Of The Texture and Quad
GL11.glTexCoord2f((texture.u + 1) * 0.0625f, texture.v * 0.0625f);
off_glVertex3f( 0.5f, 0.5f, 0.5f); // Top Left Of The Texture and Quad
GL11.glTexCoord2f((texture.u + 1) * 0.0625f, (texture.v + 1) * 0.0625f);
off_glVertex3f( 0.5f, -0.5f, 0.5f); // Bottom Left Of The Texture and Quad
// Left Face
GL11.glTexCoord2f(texture.u * 0.0625f, (texture.v + 1) * 0.0625f);
off_glVertex3f(-0.5f, -0.5f, -0.5f); // Bottom Left Of The Texture and Quad
GL11.glTexCoord2f((1+texture.u) * 0.0625f, (1+texture.v) * 0.0625f);
off_glVertex3f(-0.5f, -0.5f, 0.5f); // Bottom Right Of The Texture and Quad
GL11.glTexCoord2f((texture.u + 1) * 0.0625f, (0+texture.v) * 0.0625f);
off_glVertex3f(-0.5f, 0.5f, 0.5f); // Top Right Of The Texture and Quad
GL11.glTexCoord2f((texture.u + 0) * 0.0625f, (texture.v + 0) * 0.0625f);
off_glVertex3f(-0.5f, 0.5f, -0.5f); // Top Left Of The Texture and Quad
glColor3f(1,1,1);
}
private void off_glVertex3f(float x,float y,float z){
glVertex3f(tx+x,ty+y,tz+z);
}
So, without using voxel space and using AABB instead, how could I do the collision checks?
Thanks
Think will need to look at the AABB because the collision isn’t great just using voxel space i.e.is there a block in front, back etc…
With AABB, surely you still need to know details of the block you are testing against, I mean, is the block active or not - so, you still need to pull out the blocks data from your block array?!
My block picking and removing needs to be changed to, looks like using Bresenham’s line algorithm or a voxel traversal algorithm. The latter, here is a paper on it, what does anybody think? http://www.cse.yorku.ca/~amana/research/grid.pdf
Here is a link of my project with the voxel space collision checks:
Collision detection:
For each of the eight corners of the player (±x, ±y, ±z):
Floor the position.
Get the voxel for that position.
If null or not solid then collision is false.
If collision is false for all points, move. Otherwise don’t move.
Depending on the size of the player (if it’s bigger then one block), you may need to add more points along the edges/faces.
Thanks for the input. Could you not just take the players near bottom left and far top right corners to define its AABB?
So:
- Get AABB for player
- Get voxel at cameras/player position
- If not air
i. Get AABB for block
ii. If player AABB overlaps block AABB - collision so don’t move
Does that sound correct?
Thanks
The method I explained doesn’t use AABB.
I would rather use a sphere for the player instead of an AABB. IT needs more calculations, but it makes more sense to me