LWJGL 3D Collision cannot work out

Collision code so far

		float oldX = getPosition().x;
		float oldY = getPosition().z;
		updateInput();
		float newX = getPosition().x;
		float newY = getPosition().z;
		
		float blockSizeW = Map.WIDTH;
		float blockSizeL = Map.WIDTH;
		
		for(int x = 0; x < map.getWidth();x++){
			for(int z = 0; z < map.getHeight();z++){
				if((map.getPixel(x, z) & 0xFFFFFF) == 0){
					float blockX = x;
					float blockZ = z;
					
					System.out.println(blockX);
					if(newX > blockX && newX + playerSize < blockX){
						System.out.println("h");
					}
				}
			}
		}

I don’t see a question per se, but I’m assuming you’re looking for help with your collision detection code because it’s not working as you expect.

Some more info would probably make it easier to help, such as what’s occurring, what you expect to occur, how the map is represented, and so on. Also, using a debugger is often the fastest way to solve this kind of problem.

Meanwhile though, you might take a look at this conditional:

if(newX > blockX && newX + playerSize < blockX)

And consider what types of values for ‘playerSize’ would be needed for the conditional ever to evaluate to true (and whether you expect ‘playerSize’ ever to have such values).

Yeah sorry that was just a bit of code i left there wasnt the whole thing haha

Okay the map is made by a 2D image which is then turned into a grid style

Code for map (This is a massive bit of code)

public Map(Bitmap map, float xPos,float yPos,float zPos) {
		this.mapImage = map;
	
		ArrayList<Float> verticesArray = new ArrayList<>();
		ArrayList<Integer> indicesArray = new ArrayList<>();
		ArrayList<Float> textureArray = new ArrayList<>();
		
		for(int x = 0;x < mapImage.getWidth();x++){
			for(int z = 0; z < mapImage.getHeight();z++){
				if((mapImage.getPixel(x,z) & 0xFFFFFF) == 0){
					continue;
				}
				// Top
				indicesArray.add(verticesArray.size()/3 + 0);
				indicesArray.add(verticesArray.size()/3 + 1);
				indicesArray.add(verticesArray.size()/3 + 2);
				
				indicesArray.add(verticesArray.size()/3 + 2);
				indicesArray.add(verticesArray.size()/3 + 3);
				indicesArray.add(verticesArray.size()/3 + 0);
				
				addVertex(verticesArray, x*WIDTH, HEIGHT, z*LENGTH);
				addVertex(verticesArray, x*WIDTH, HEIGHT, (z+1)*LENGTH);
				addVertex(verticesArray, (x+1)*WIDTH, HEIGHT, (z+1)*LENGTH);
				addVertex(verticesArray, (x+1)*WIDTH, HEIGHT, z*LENGTH);
				
				textureArray.add(0f/NUMBER_TEX);
				textureArray.add(0f/NUMBER_TEX);
				
				textureArray.add(0f/NUMBER_TEX);
				textureArray.add(1f/NUMBER_TEX);
				
				textureArray.add(1f/NUMBER_TEX);
				textureArray.add(1f/NUMBER_TEX);
				
				textureArray.add(1f/NUMBER_TEX);
				textureArray.add(0f/NUMBER_TEX);
				
				
				// Ground
				indicesArray.add(verticesArray.size()/3 + 0);
				indicesArray.add(verticesArray.size()/3 + 1);
				indicesArray.add(verticesArray.size()/3 + 2);
				
				indicesArray.add(verticesArray.size()/3 + 2);
				indicesArray.add(verticesArray.size()/3 + 3);
				indicesArray.add(verticesArray.size()/3 + 0);
				
				addVertex(verticesArray, x*WIDTH, 0, z*LENGTH);
				addVertex(verticesArray, x*WIDTH, 0, (z+1)*LENGTH);
				addVertex(verticesArray, (x+1)*WIDTH, 0, (z+1)*LENGTH);
				addVertex(verticesArray, (x+1)*WIDTH, 0, z*LENGTH);
				
				
				textureArray.add(0f/NUMBER_TEX);
				textureArray.add(0f/NUMBER_TEX);
				
				textureArray.add(0f/NUMBER_TEX);
				textureArray.add(1f/NUMBER_TEX);
				
				textureArray.add(1f/NUMBER_TEX);
				textureArray.add(1f/NUMBER_TEX);
				
				textureArray.add(1f/NUMBER_TEX);
				textureArray.add(0f/NUMBER_TEX);
				
				// Walls
				if((mapImage.getPixel(x,z -1) & 0xFFFFFF) == 0){
					indicesArray.add(verticesArray.size()/3 + 0);
					indicesArray.add(verticesArray.size()/3 + 1);
					indicesArray.add(verticesArray.size()/3 + 2);
					
					indicesArray.add(verticesArray.size()/3 + 2);
					indicesArray.add(verticesArray.size()/3 + 3);
					indicesArray.add(verticesArray.size()/3 + 0);
					
					addVertex(verticesArray, x*WIDTH, 0, z*LENGTH);
					addVertex(verticesArray, (x+1)*WIDTH, 0, z*LENGTH);
					addVertex(verticesArray, (x+1)*WIDTH, HEIGHT, z*LENGTH);
					addVertex(verticesArray, x*WIDTH, HEIGHT, z*LENGTH);
					
					textureArray.add(0f/NUMBER_TEX);
					textureArray.add(0f/NUMBER_TEX);
					
					textureArray.add(0f/NUMBER_TEX);
					textureArray.add(1f/NUMBER_TEX);
					
					textureArray.add(1f/NUMBER_TEX);
					textureArray.add(1f/NUMBER_TEX);
					
					textureArray.add(1f/NUMBER_TEX);
					textureArray.add(0f/NUMBER_TEX);
				}
				if((mapImage.getPixel(x,z +1) & 0xFFFFFF) == 0){
					indicesArray.add(verticesArray.size()/3 + 0);
					indicesArray.add(verticesArray.size()/3 + 1);
					indicesArray.add(verticesArray.size()/3 + 2);
					
					indicesArray.add(verticesArray.size()/3 + 2);
					indicesArray.add(verticesArray.size()/3 + 3);
					indicesArray.add(verticesArray.size()/3 + 0);
					
					addVertex(verticesArray, x*WIDTH, 0, (z+1)*LENGTH);
					addVertex(verticesArray, (x+1)*WIDTH, 0, (z+1)*LENGTH);
					addVertex(verticesArray, (x+1)*WIDTH, HEIGHT, (z+1)*LENGTH);
					addVertex(verticesArray, x*WIDTH, HEIGHT, (z+1)*LENGTH);
					
					textureArray.add(0f/NUMBER_TEX);
					textureArray.add(0f/NUMBER_TEX);
					
					textureArray.add(0f/NUMBER_TEX);
					textureArray.add(1f/NUMBER_TEX);
					
					textureArray.add(1f/NUMBER_TEX);
					textureArray.add(1f/NUMBER_TEX);
					
					textureArray.add(1f/NUMBER_TEX);
					textureArray.add(0f/NUMBER_TEX);
				}
				if((mapImage.getPixel(x-1,z) & 0xFFFFFF) == 0){
					indicesArray.add(verticesArray.size()/3 + 0);
					indicesArray.add(verticesArray.size()/3 + 1);
					indicesArray.add(verticesArray.size()/3 + 2);
					
					indicesArray.add(verticesArray.size()/3 + 2);
					indicesArray.add(verticesArray.size()/3 + 3);
					indicesArray.add(verticesArray.size()/3 + 0);
					
					addVertex(verticesArray, x*WIDTH, 0, z*LENGTH);
					addVertex(verticesArray, x*WIDTH, 0, (z+1)*LENGTH);
					addVertex(verticesArray, x*WIDTH, HEIGHT, (z+1)*LENGTH);
					addVertex(verticesArray, x*WIDTH, HEIGHT, z*LENGTH);
					
					textureArray.add(0f/NUMBER_TEX);
					textureArray.add(0f/NUMBER_TEX);
					
					textureArray.add(0f/NUMBER_TEX);
					textureArray.add(1f/NUMBER_TEX);
					
					textureArray.add(1f/NUMBER_TEX);
					textureArray.add(1f/NUMBER_TEX);
					
					textureArray.add(1f/NUMBER_TEX);
					textureArray.add(0f/NUMBER_TEX);
				}
				if((mapImage.getPixel(x+1,z) & 0xFFFFFF) == 0){
					indicesArray.add(verticesArray.size()/3 + 0);
					indicesArray.add(verticesArray.size()/3 + 1);
					indicesArray.add(verticesArray.size()/3 + 2);
					
					indicesArray.add(verticesArray.size()/3 + 2);
					indicesArray.add(verticesArray.size()/3 + 3);
					indicesArray.add(verticesArray.size()/3 + 0);
					
					addVertex(verticesArray, (x+1)*WIDTH, 0, z*LENGTH);
					addVertex(verticesArray, (x+1)*WIDTH, 0, (z+1)*LENGTH);
					addVertex(verticesArray, (x+1)*WIDTH, HEIGHT, (z+1)*LENGTH);
					addVertex(verticesArray, (x+1)*WIDTH, HEIGHT, z*LENGTH);
					
					textureArray.add(0f/NUMBER_TEX);
					textureArray.add(0f/NUMBER_TEX);
					
					textureArray.add(0f/NUMBER_TEX);
					textureArray.add(1f/NUMBER_TEX);
					
					textureArray.add(1f/NUMBER_TEX);
					textureArray.add(1f/NUMBER_TEX);
					
					textureArray.add(1f/NUMBER_TEX);
					textureArray.add(0f/NUMBER_TEX);
				}
			}
		}
		
		float[] vertices = new float[verticesArray.size()];
		int[] indices = new int[indicesArray.size()];
		float[] textureCoords = new float[textureArray.size()];
		
		for(int i = 0;i < verticesArray.size();i++){
			vertices[i] = verticesArray.get(i);
		}
		for(int i = 0;i < indicesArray.size();i++){
			indices[i] = indicesArray.get(i);
		}
		for(int i = 0;i < textureArray.size();i++){
			textureCoords[i] = textureArray.get(i);
		}
		
		float[] normals = {
				0,1,0
		};
		
		rawModel = new VertexArray(vertices, indices, textureCoords, normals);
		
		Texture stoneTexture = Utils.loadTexture("tileSheet");
		mapModel = new TexturedModel(new Model(rawModel), stoneTexture);
		mapModel.getModel().setPosition(xPos*WIDTH, yPos*HEIGHT, zPos*LENGTH);
		
	}

The only progress i have made so far is this

float oldX = getPosition().x;
		float oldZ = getPosition().z;
		updateInput();
		updateMovement();
		
		float blockSizeW = Map.WIDTH;
		float blockSizeL = Map.LENGTH;
		
		float newX = getPosition().x;
		float newZ = getPosition().z;
		
		for(int x = 0; x < map.getWidth();x++){
			for(int z = 0; z < map.getHeight();z++){
				if((map.getPixel(x, z) & 0xFFFFFF) == 0){
					float blockX = x*blockSizeW;
					float blockZ = z*blockSizeL;
					if(x == 1 && z == 0){
					System.out.println("BX " + blockX);
					System.out.println("CamX " + newX);
					
					}
					
					Vector3f speed = getMoveVector();
					if(speed.x > 0){
						if(newX + playerSize > blockX && newX + playerSize < blockX + blockSizeW){
							System.out.println("h");
						}
					}else if(speed.x < 0){
						
					}
				}
			}
		}

But it seems to be colliding all of the time

This should do it. Some untested code, but I think you’ll get what I mean.


public static boolean collides(float blockX, float blockZ, float newX, float newZ) {
      if(Math.abs(blockX - newX) < (Map.WIDTH + playerSizeX) / 2.0f) {
         if(Math.abs(blockZ - newZ) < (Map.LENGTH + playerSizeZ) / 2.0f) {
            return true;
         }
      }
      return false;
}

Qucik question I put Map.Width and Map.LENGTH as the block size does that make a difference?

I used them as the blocksize, since you did that here:

Hmm It doesnt seem to work :confused:

Is blockX and newX the center or a corner?

I am guessing corner? I am not completely sure. Can you skype me? Skype: tommohawkaction

Hi

You should look at the source code of my game as I use the same kind of level and my rudimentary system of collision detection works. I create 3D levels composed of orthogonal walls from 2D images:
http://svn.code.sf.net/p/tuer/code/alpha/main/GameModel.java

Sorry dude but I am finding it very hard to understand you code :?

Okay good news i have managed to work it out using an old 2D method of collision i used to use
however when i brush against the wall while hold the left button i get stuck untill i let go of the left button

Necessary code

Vector3f speed = getMoveVector();
					if(speed.x > 0){
						//RIGHT
					if(newX + playerSize > blockX && newX + playerSize< blockX + blockSizeW){
						if(newZ - blockSizeL > blockZ && newZ - blockSizeL< blockZ + Math.abs(blockSizeL)){
						getPosition().x = oldX;
						}
					}
						
						
					}else if(speed.x < 0){
							// TODO
						//LEFT
					if(newX - playerSize> blockX && newX - playerSize < blockX + blockSizeW){
						if(newZ > blockZ && newZ< blockZ + Math.abs(blockSizeL)){
						getPosition().x = oldX;
						}
					}
					}
					
					if(speed.z < 0){
						//TOP
					if(newX - playerSize > blockX && newX - playerSize< blockX + blockSizeW){
						if(newZ - playerSize + Math.abs(blockSizeL) > blockZ && newZ - playerSize  + Math.abs(blockSizeL) < blockZ + Math.abs(blockSizeL)){
						getPosition().z = oldZ;
						}
					}
					}else if(speed.z > 0){
						//BOTTOM
					if(newX > blockX && newX < blockX + blockSizeW){
						if(newZ + Math.abs(blockSizeL)+ playerSize > blockZ && newZ + Math.abs(blockSizeL)+ playerSize< blockZ + Math.abs(blockSizeL)){
						getPosition().z = oldZ;
						}
					}
					}

Here’s a couple more suggestions for you.

First, I’d suggest at least considering using a z-vertical coordinate system rather than y-vertical. This is just personal preference, and I’m just suggesting it as an option. Personally, for 3-d environments with a strong 2-d component (such as the one under discussion here) I find z-vertical to be easier to reason about because the problems you’re really interested in (such as collision detection) map to a 2-d xy coordinate system. You might think you have to use y-vertical because y is typically ‘up’ in camera space, but camera space and world space can use different conventions if you want, so this isn’t an issue. Anyway, just something to consider.

As for your collision detection, it sounds like what you want is the typical ‘sliding’ behavior, where when you run into a wall you don’t just stop but rather slide along the wall.

The simplest way I know of to implement this is as follows. Treat your player as a circle, and check the circle against every candidate tile for collision (the candidates can easily be determined due to the regularity of the grid). The circle-tile test is a circle-to-axis-aligned-square test, which is fairly straightforward. If a collision is detected, move the circle along the minimum translation vector until it’s no longer intersecting the tile. Do this for each tile with which the circle is intersecting.

Provided the circle is smaller than a single tile and that it doesn’t move so quickly that it could tunnel through walls, this should work and give you the sliding behavior you’re looking for. (Maybe this is what gouessej’s code is doing - I’m not sure.)

Although this is fairly simple, if you don’t have much experience with vector math or collision detection and resolution, it might not be obvious how to implement this, but you can always ask for help here or look for resources online (of which there are quite a few).