0

I have been working on a Minecraft-like voxel game for a while and decided to implements block placing and destroying via raycasting. I realized however, that when standing very close to a block, the block rotates around itself rather than the camera (or viewing plane). The eye position is off by approx. 0.5 on any given axis. I'm very sure that this is why my raycasting is not working precisely and I think the problem lies in projection.

I've tried using different projection methods but they all have the same outcome. Adjusting the camera's position when creating the view matrix also didn't work and led to some strange stretching and wrong rotations.

My projection matrix code:

public static Matrix4f createProjectionMatrix (float fov, float aspectRatio, float clipNear, float clipFar) {
    float tanHalfFOV = (float)Math.tan(fov/2);
    float zm = clipFar + clipNear;
    float zp = clipFar - clipNear;

    Matrix4f matrix = new Matrix4f();
    matrix.m00(1.0f / (tanHalfFOV * aspectRatio));
    matrix.m11(1.0f / tanHalfFOV);
    matrix.m22(-zm / zp);
    matrix.m32(-2.0f * clipNear * clipFar / zp);
    matrix.m23(-1.0f);

    return matrix;
}

The view matrix code:

public static Matrix4f getViewMatrix () {
    return new Matrix4f().rotateXYZ(rotation).translate(-position.x, -position.y, -position.z);
}

The shader code:

#version 400 core

in vec3 worldCoords;
in vec2 textureCoords;

out vec2 passTextureCoords;

uniform mat4 projViewMatrix;

void main () {
    gl_Position = projViewMatrix * vec4(worldCoords, 1.0);

    passTextureCoords = textureCoords;
}

Rendering code:

public static void render (ChunkMesh cm) {
    Renderable model = cm.getModel();

    Shaders.CHUNK_MESH_SHADER.activate();
    Shaders.CHUNK_MESH_SHADER.loadToUniform("projViewMatrix", Display.getProjectionMatrix().mul(Camera.getViewMatrix(), new Matrix4f()));

    GL30.glBindVertexArray(model.vaoID);
    GL20.glEnableVertexAttribArray(0);
    GL20.glEnableVertexAttribArray(1);

    GL13.glActiveTexture(GL13.GL_TEXTURE0);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, BlockTexture.TEXTURE.textureID);

    GL11.glDrawElements(GL11.GL_TRIANGLES, model.vertexCount, GL11.GL_UNSIGNED_INT, 0l);

    GL20.glDisableVertexAttribArray(0);
    GL20.glDisableVertexAttribArray(1);
    GL30.glBindVertexArray(0);

    Shaders.CHUNK_MESH_SHADER.deactivate();
}

Along any given axis the raycasting performs quite well but when facing in between two axes the raycasting looks like its origin is different than the center of the screen. Since my question is focused on the misalignment rather than the raycasting (Which seemingly works), I will only add the code if requested. Any help is appreciated!

J. Lengel
  • 570
  • 3
  • 16

1 Answers1

2

This is a somewhat educated guess, because you have not exactly specified what Matrix4f actually is. But assuming some standard conventions like the Matrix4f class from lwjgl, the constructor will initialize the new matrix to identity. Therefore, you need to modify your createProjectionMatrix() function to add

matrix.m33(0.0);

to explicitly set the very last element to zero, since without it, you actually set w_clip = -z_eye + 1, moving your projection center 1 unit in front of where you think your camera is.

derhass
  • 43,833
  • 2
  • 57
  • 78