1
\$\begingroup\$

I am calculating collision for my fps-camera by checking if the x/z-position of the camera is inside a plane. And the detection works fine. The plane is represented as two-component vectors min and max:

bool point_within_rectangle(glm::vec2 p, glm::vec2 min, glm::vec2 max)
{
    if ((p.x < max.x && p.x > min.x) && ((p.y < max.y && p.y > min.y)))
        return true;

    return false;
}

I am having problems visualizing the rectangles. This function draws a quad and creates an according vao if it wasn't created yet.

void RenderQuad(Geometry *geometry, vec3 min, vec3 max)
{
    if (geometry->vao == 0)
    {
        float quadVertices[] = {
            // positions        // texture Coords
            min.x, max.y, min.z, 0.0f, 1.0f,
            min.x, min.y, max.z, 0.0f, 0.0f,
            max.x, max.y, min.z, 1.0f, 1.0f,
            max.x, min.y, max.z, 1.0f, 0.0f,
        };
        // setup plane VAO
        glGenVertexArrays(1, &geometry->vao);
        glGenBuffers(1, &geometry->vbo);
        glBindVertexArray(geometry->vao);
        glBindBuffer(GL_ARRAY_BUFFER, geometry->vbo);
        glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *)0);
        glEnableVertexAttribArray(1);
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *)(3 * sizeof(float)));
    }
    glBindVertexArray(geometry->vao);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    glBindVertexArray(0);
}

My idea was to render a quad like this:

vec2 min = vec2{-8.0f, -8.0f};
vec2 max = vec2{8.0f, 8.0f}

mat4 model = mat4(1.0f);
flat_shader.set_mat4("model", model);
RenderQuad(&navmesh_geometry, vec3{min.x, 0.0f, min.y}, vec3{max.x, 0.0f, max.y}); 

enter image description here

While this does work, it breaks when I try to render another quad which is not centered around world origin. In that case I still see only the above rectangle.

vec2 min2 = vec2{-13.0f, 1.0f};
vec2 max2 = vec2{-11.0f, 2.0f};

I am drawing both rectangles in a loop.

    for (std::vector<NavMesh>::iterator it_mesh = nav_meshes.begin(); it_mesh != nav_meshes.end(); ++it_mesh)
    {
        model = mat4(1.0f);
        flat_shader.set_mat4("model", model);
        RenderQuad(&navmesh_geometry,
                         vec3{it_mesh->min.x, 0.0f, it_mesh->min.y},
                         vec3{it_mesh->max.x, 0.0f, it_mesh->max.y});
    }

I can see the second rectangle if I don't draw the first one. I suppose that the problem lies in the assumption that the min max values in the vao are in world space, while they are in object space. That way I guess that the second rectangle is not visible because it is drawn around world origin occluded by the first rectangle.

My first approach was to center the model around it's calculated center by translating it.

// Prepare..
mat4 model = mat4(1.0f);
model = translate(model, vec3{
    (it_mesh->min.x + it_mesh->max.x) / 2.0f,
    0.0f,
    (it_mesh->min.y + it_mesh->max.y) / 2.0f});
// Draw...

This seems to screw up the scale of the rectangle.

enter image description here

I guess I am missing the right rendering approach for this problem. How would I render a rectangle with the according min and max values in world space?

In case it helps my vertex and fragment shaders are straight forward.

#version 330 core
layout (location = 0) in vec3 aPos;
// uv layout not used.

uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;

void main()
{
    gl_Position = projection * view * model * vec4(aPos, 1.0);
}
#version 330 core
out vec4 FragColor;

uniform vec3 color;

void main() {
    FragColor = vec4(color, 1.);
}

projection and view are also correctly passed to the shader. I did not include that part in my snippets above.

\$\endgroup\$

0

You must log in to answer this question.

Browse other questions tagged .