LWJGL - Voxel Engine

Hi,

I’ve implemented testing voxel at player position, this is what I’ve already done and it isn’t very accurate, you can still pass through blocks - hence the reason I was asking over using AABB.

Or are you saying which maybe you are - use each corner of the player as position for voxel, thus you could test 8 positions?

@Argo - so, once I’ve got the block I then use sphere test with the blocks AABB?

I think doing a sphere (player) to AABB (voxel) test would prove best method. I’ve modified some AABB/Circle/CollisionLibrary class code to support Z:


public class AABB {
	public Vector center;
	public float r[];

	public AABB(final float width, final float height, final float depth) {
		center = new Vector();
		r = new float[3];
		r[0] = width * 0.5f;
		r[1] = height * 0.5f;
		r[2] = depth * 0.5f;
	}

	public void update(final Vector position) {
		center.x = position.x;
		center.y = position.y;
		center.z = position.z;
	}
}

public class Circle {
	public Vector center;
	public float radius;

	public Circle(final float radius) {
		center = new Vector();
		this.radius = radius;
	}

	public void update(final Vector position) {
		center.x = position.x;
		center.y = position.y;
		center.z = position.z;
	}
}

public class CollisionLibrary {
	public static boolean testAABBAABB(final AABB box1, final AABB box2) {
		   if (Math.abs(box1.center.x - box2.center.x) > (box1.r[0] + box2.r[0])) return false;
		   if (Math.abs(box1.center.y - box2.center.y) > (box1.r[1] + box2.r[1])) return false;
		   if (Math.abs(box1.center.z - box2.center.z) > (box1.r[2] + box2.r[2])) return false;
		   return true;
		}
	
	public static float sqDistPointAABB(final Vector p, final AABB aabb) {
		   float sqDist = 0.0f;
		   float v;
		   float minX, minY, minZ, maxX, maxY, maxZ;
		      
		   // get the minX, maxX, minY, maxY and minZ, maxZ points of the AABB
		   minX = aabb.center.x - aabb.r[0];
		   maxX = aabb.center.x + aabb.r[0];
		      
		   minY = aabb.center.y - aabb.r[1];
		   maxY = aabb.center.y + aabb.r[1];
		      
		   minZ = aabb.center.z - aabb.r[2];
		   maxZ = aabb.center.z + aabb.r[2];
		      
		   // test the bounds against the points X axis
		   v = p.x;
		      
		   if (v < minX) sqDist += (minX - v) * (minX - v);
		   if (v > maxX) sqDist += (v - maxX) * (v - maxX);
		      
		   // test the bounds against the points Y axis
		   v = p.y;
		      
		   if (v < minY) sqDist += (minY - v) * (minY - v);
		   if (v > maxY) sqDist += (v - maxY) * (v - maxY);
		      
		   // test the bounds against the points Z axis
		   v = p.z;
		      
		   if (v < minZ) sqDist += (minZ - v) * (minZ - v);
		   if (v > maxZ) sqDist += (v - maxZ) * (v - maxZ);
		      
		   return sqDist;
		}
	
		public static boolean testCircleAABB(final Circle circle, final AABB box) {
		   // get the squared distance between circle center and the AABB
		   float sqDist = sqDistPointAABB(circle.center, box);
		   float r = circle.radius;
		      
		   return sqDist <= r * r;
		}
	
}

Thanks

Why don’t you use the collision check I am using? It is really accurate.

Anyway, I am trying to create a basic block picking but I cannot really get it working.

Do you check which block you are on before doing your AABB, so you know if block is active or not?

You will need to do a ray cast to do the picking, I’m going to try that tomorrow providing I get this collision working!

You don’t need to test if the block is active. The only thing you need to test for is if the player vector position is within the block vector. If it is, handle collision appropriately. I don’t understand why you keep bringing up your

active

boolean :stuck_out_tongue:

I save the current chunk to a list.

Then, every time that I move I check only the current chunk for solid blocks. If I am inside a solid block after my movement, you get back to position you were before colliding.

Also, I set my onGround bool to false each time I move, so my gravity script can check if I am still walking on solid blocks.

Paul.

That seems a little sketchy… you really shouldn’t really on that way of collision unless you’re writing anything other than a basic 2D game. You really should just AABBs and implement sliding movement.

@opiop65 - Surely you need to test if the block is active else you would collide with every block in the chunk?!?!? My chunks are made up of 16^3 blocks, of course, some of them are not active, so how do I check the blocks in the chunk?!

Thanks

So, why is this so hard again? Just get the blocks around you. <.< Its not that hard if you know how big the cubes are. Its like a grid. Treat the chunk as a grid, and find where you are in the grid. Then test collisions around it.

Hi @Argo,

So, get blocks around player and do Sphere to AABB on these blocks…

All my blocks are 1x1x1.

I’ve set player radius as 1 as they are also 1 unit.

Example:


Vector playerPosition = new Vector();
playerPosition.x = Math.abs(v.x);        // get player/camera position
playerPosition.y = Math.abs(v.y); 
playerPosition.z = Math.abs(v.z);
playerSphere.update(playerPosition);   // playerSphere is radius of 1
	    
AABB voxel = new AABB(1,1,1);  // width, height, depth
Vector voxelPosition = new Vector();
voxelPosition.x = 7; voxelPosition.y = 1; voxelPosition.z = 7;
voxel.update(voxelPosition);

if(CollisionLibrary.testCircleAABB(playerSphere, voxel)) {
    // do whatever
}

The above code is just an example of a block that is at position x:7, y:1 and z:7, so, when player is at that position, collision occurs, and it does, and is a whole lot better than just doing collision with, is player on block N.

Of course, the example above needs to get the blocks position around the player - top, bottom, front, back, left, right - then check for collision with these.

When I get a block - I NEED to see if it is active or not, otherwise what is the point in testing for a collision with an empty block?!

Will need a slide vector when collision for more realism - this is in fact an impulse force, so guess it could be:

impulse = -(playerVelocity * blockCollidedWithNormal) * blockCollidedWithNormal;
playerVelocity += impulse;

Or, has anybody else any good ways of doing a slide vector without tons of trig?!

*EDIT - I found this article on sliding vectors / collision response :

http://www.peroxide.dk/papers/collision/collision.pdf

Thanks

Collision detection is easy.
Convincing them that they don’t need AABBs to collide with the world is hard.

Some forms of collision detection is easy, some not so. I’m finding AABB the best solution for what I am trying to do having tried another method which wasn’t too successful.

What I’m struggling with is collision response, what to do when collision occurs. Of course, we need to determine if the collision was in front, behind, above, below, left or right of the player first of all.

When I land on top of a block, I then cannot move forward as my code thinks there is a collision in front, even though it is with the ground… :frowning:

You could split the vertical test and forward movement test up. I always knew the height I was testing, before I tried to test forward movement. So when you move forward there is only 1 test.

There only needs to be one test - in the direction you want to move.
When you test, you should not alter the actual players position.

If a collision occurs, you can either:

Not move,
Or are repelled with some force, so that you are pushed sideways, so you don’t feel like you are sticking to a wall when approaching it at an angle.

I still cannot make block picking to work.

@Vermeer - I believe you need to add the height on when checking collision so we don’t get a collision with block below. I do the ground test in a separate collision check, from there I get the height of the ground we are on and now use that when moving.

As for not moving player when testing, you mean store the cameras position in a player vector and check this before allowing movement? Makes sense.

I think getting the players normal (direction vector) so we always know which way the player is facing would be beneficial to this form of collision detection, thus, we would know if we collided from front of player, behind or left, right - below shows P as player and arrow showing players normal vector.

 /|\        P
  |         |
  P       \|/    

So if a collision occurs, we could check the players normal vector…would this work?

Hi Steg

I guess there are lots of ways to approach this, but I think the important thing that you know how the solution works in your game so that you can fix issues with it.

Yes - I don’t apply transformations directly to the player, but a dummy object. If There is no collision, I then move the player.

I also use the players vector too yes, so I will know which block to test. I think I didn’t explain below that once you test the height, you do use that height information when testing the forward movement.

Have you got it working how you want yet?

What part is not working, how far have you got with it?

I don’t really know how to apply the rotation to the block picking.

@Pauler -

Off top of my head, not at computer with my code:



double cameraPitchInRadians = Math.toRadians(camera.getCameraPitch());
double cameraYawInRadians = Math.toRadians(camera.getCameraYaw());
float f = (float)Math.cos(cameraPitchInRadians);
         
float newX = distanceFromCameraYouWantToMeasure * f * (float)Math.sin(cameraYawInRadians);
float newZ = distanceFromCameraYouWantToMeasure * f * (float)Math.cos(cameraYawInRadians);
float newY = distanceFromCameraYouWantToMeasure * (float)Math.sin(cameraPitchInRadians);
float newX = distancefromcamera * Math.sin(cameraxrotInRadians);
float newZ = distancefromcamera * Math.cos(camerayrotInRadians);




@Vermeer - not had time to look at it yet, hopefully get some time later this evening. Think going to try and get normal vector of player direction…

These are my methods to send a ray from the camera, it may be very in-efficiant, but it works to test it.
You will notice I have lots of small methods to add vectors and suchlike.

Basically I use trig to calculate where the camera is pointing, then test along the ray at 0.1f intervals, and check if It hits a solid block.
Someone may suggest a better way, and it can certainly be optimised a lot. Trig functions are expensive, Once the angle is know you can
make use of the same angle, without recalculating. But this may help you get it working, so you can develop it.

http://pastebin.java-gaming.org/94c3e0b3f53

I believe Sparky83 put some code up for a good ray cast - the 3d game primer book by Fletcher Dunn explains it :slight_smile:

PS - does anybody know how to do a slide vector once a collision has occurred, I believe I need this as sometimes my player gets stuck when collision happens…