I've been working on adding a line-of-sight/ray-tracing system to my 3d block-world game. I've tried several different methods and they all work fairly well. At the moment I'm using something similar to what Bukkit uses.

Essentially, using the point of origin (the player location, plus the extra height for the "eye" of the camera), and the current yaw and pitch, I'm looking for every block that the line of sight would pass through.

For the most part it works - however, the "ray" is always slightly off, by roughly half a block or so. What I mean is, as I slowly move my cursor left/right or up/down, the block I'm actually focusing on doesn't "highlight" (for testing, I set it to snow) until the cursor is roughly to the middle. This offset varies a bit based on my angle to the block.


It seems like when my cursor is on the left 50% of a block, the block to the left highlights. The top 50% of the block, the block above highlights. Same for right/bottom 50%s.

I'm trying to understand where this discrepancy is coming from. I've been tweaking and toying with code based on the assumption that one of the following is the issue:

  • The "eye" offset or the player's location are wrong. I'm using the same y offset the camera uses and as far as I can tell from collision, the standing location of the player is accurate
  • The ray somehow needs adjusted yaw/pitch values? I don't see how, those yaw/pitch values are used for the camera. They should describe the exact direction the ray needs
  • The "normalization" code for the vector is wrong. I've found essentially same code in multiple examples, and it seems like it doesn't round/cast values, so I shouldn't be losing anything

I'm looking for advise on:

  • What values are the most likely cause for a half-block offset?
  • or, how do I fix?

The player's camera is set like this:

GL11.glRotatef(pitch, 1.0f, 0, 0);
GL11.glRotatef(360.0f - yaw, 0, 1.0f, 0);
GL11.glTranslatef(-position.x, -position.y - EYE_HEIGHT, -position.z);

EYE_HEIGHT is 1.8f

The "direction" vector is normalized like this:

Vector vector = new Vector(0,0,0);
vector.setY( (float)-Math.sin(Math.toRadians(pitch)) );
float v = (float)Math.cos(Math.toRadians(pitch) );
vector.setX( (float)(Math.sin(Math.toRadians(yaw))*-v)  );
vector.setZ( (float)(Math.cos(Math.toRadians(yaw))*v)  );

And the player's location is essentially just a `Vector3f.

I've found several alternate methods of calculating the right info here on gamedev, but the code I have is so close it doesn't seem worth ditching. Though I will if needed, lol.

  • \$\begingroup\$ chances are that the actual ray-casting logic is wrong \$\endgroup\$ – ratchet freak Dec 5 '13 at 10:14
  • \$\begingroup\$ The fact that you are using immediate-mode OpenGL makes things harder. But the easy solution would be to calculate the ray, then set the direction the camera in the direction of the ray. If you're still experiencing the same problem, then the issue is with your ray-block intersection checking. \$\endgroup\$ – Fault Dec 5 '13 at 14:19
  • \$\begingroup\$ I've bookmarked several other ray-casting examples I can try just in case, but the block checking code I have is from the bukkit project and should be well tested. I'm new to all this, so how I render the world is based on some example projects. I'm googling "immedate mode" now, lol. What do you mean by "calc the ray first, then set the direction in the direction of the ray?" \$\endgroup\$ – BotskoNet Dec 5 '13 at 15:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.