c++matrixopenglglm-mathblending

Calculating distance from a camera to a plane of a cube in opengl


I am trying to get transparency blending to work properly on my cube and I have hit a bit of a roadblock. I have gotten blending to work on multiple cubes by simply drawing them in the correct order but getting it to work on the faces of a cube itself has been much harder.

They way I want to solve this is by reordering the indices in the EBO so that it draws the faces in the correct order. I have gotten it to reorder the indices, the problem is that they are not being ordered correctly.

The way I do this is with this method:

void GECCube::SortIndicies(glm::mat4 ModelMatrix)
{

glm::vec4 View = glm::vec4{0.0f, 0.0f, -3.0f, 0.f};
unsigned int NewIndices[36];
std::multimap<float, std::vector<unsigned int>> SortedMap;


for (int i = 0; i < 12; i += 2)
    {
    
    glm::vec4 Tri1 = glm::vec4{
        (Vertices[Indices[i * 3] * 3] + Vertices[Indices[(i * 3) + 1] * 3] + Vertices[Indices[(i * 3) + 2] * 3]) / 3, //X
        (Vertices[Indices[i * 3] * 4] + Vertices[Indices[(i * 3) + 1] * 4] + Vertices[Indices[(i * 3) + 2] * 4]) / 3, //Y
        (Vertices[Indices[i * 3] * 5] + Vertices[Indices[(i * 3) + 1] * 5] + Vertices[Indices[(i * 3) + 2] * 5]) / 3, //Z
        0.f
        };

    glm::vec4 Tri2 = glm::vec4{
        (Vertices[Indices[(i + 1) * 3] * 3] + Vertices[Indices[((i + 1) * 3) + 1] * 3] + Vertices[Indices[((i + 1) * 3) + 2] * 3]) / 3, //X
        (Vertices[Indices[(i + 1) * 3] * 4] + Vertices[Indices[((i + 1) * 3) + 1] * 4] + Vertices[Indices[((i + 1) * 3) + 2] * 4]) / 3, //Y
        (Vertices[Indices[(i + 1) * 3] * 5] + Vertices[Indices[((i + 1) * 3) + 1] * 5] + Vertices[Indices[((i + 1) * 3) + 2] * 5]) / 3, //Z
        0.f
        };

    glm::vec4 PlaneMed = glm::vec4{(Tri1.x + Tri2.x) / 2, (Tri1.y + Tri2.y) / 2 , (Tri1.z + Tri2.z) / 2, 0 };

    float Distance = glm::length(View - (ModelMatrix * PlaneMed));


    std::vector<unsigned int> TransportVector = std::vector<unsigned int>{ Indices[i * 3] , Indices[(i * 3) + 1] , Indices[(i * 3) + 2],
        Indices[(i + 1) * 3] , Indices[((i + 1) * 3) + 1] , Indices[((i + 1) * 3) + 2] };


    SortedMap.insert(std::pair<float, std::vector<unsigned int>>(Distance, TransportVector));
    }


auto MapIterator = SortedMap.begin();
for (int i = 0; i < 12; i += 2)
    {

    NewIndices[i * 3] = MapIterator->second[0];
    NewIndices[(i * 3) + 1] = MapIterator->second[1];
    NewIndices[(i * 3) + 2] = MapIterator->second[2];
    NewIndices[(i + 1) * 3] = MapIterator->second[3];
    NewIndices[((i + 1) * 3) + 1] = MapIterator->second[4];
    NewIndices[((i + 1) * 3) + 2] = MapIterator->second[5];

    if (i != 10) { MapIterator++; }
    
    }


std::copy(std::begin(NewIndices), std::end(NewIndices), std::begin(Indices));

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);
}

I have yet to do something more complicated with the camera so for now it's just at position 0,0,-3.0

The place I think I have done this wrong is when it comes to calculating the distance between the camera and the plane. Namely this:

float Distance = glm::length(View - (ModelMatrix * Plane));

Originally I was just going to use View - Plane but I realized that that would give me the same value for every index so I thought on how to integrate the Model into the distance. I reason that since the shader uses the model matrix to draw at the correct position so should I be able to use it to find the correct position of the plane in model space. But I think I am wrong on this.

All of this comes together in the draw function (it draws multiple cubes):

...    
glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, it->second * 0.9f * std::clamp((float) sinf(( float )SDL_GetTicks() / 1000.f) + 1.5f, 0.f, 3.f));
float angle = 20.0f * ((i + 1)/20) * ( float )SDL_GetTicks() / 200 * glm::radians(50.0f);
model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));
    
OGLCMain->MainCube.SortIndicies(model);
            
int modelLoc = glGetUniformLocation(OGLCMain->ShaderProgram, "model");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
...

Solution

  • So I made the system work by changing the distance code to be calculated using the dot product of the vector on the camera front vector

    Plane = ModelMatrix * Plane
    float Distance = glm::dot((CameraPos - Plane), CameraFront);
    

    and by changing how the plane med is calculated into:

    glm::vec4 Plane = glm::vec4{
            (Vertices[(Indices[(i) * 3] * 5)] + Vertices[(Indices[((i) * 3) + 1] * 5)] + Vertices[(Indices[((i) * 3) + 2] * 5)] + Vertices[(Indices[((i + 1) * 3) + 1] * 5)]) / 4.f,
            (Vertices[(Indices[(i) * 3] * 5) + 1] + Vertices[(Indices[((i) * 3) + 1] * 5) + 1] + Vertices[(Indices[((i) * 3) + 2] * 5) + 1] + Vertices[(Indices[((i + 1) * 3) + 1] * 5) + 1]) / 4.f,
            (Vertices[(Indices[(i) * 3] * 5) + 2] + Vertices[(Indices[((i) * 3) + 1] * 5) + 2] + Vertices[(Indices[((i) * 3) + 2] * 5) + 2] + Vertices[(Indices[((i + 1) * 3) + 1] * 5) + 2]) / 4.f,
            1.f };
    

    I also reversed the order it puts it back in:

    auto MapIterator = SortedMap.begin();
    for (int i = 11; i > 0; i -= 2)
        {
    
        NewIndices[i * 3] = MapIterator->second[0];
        NewIndices[(i * 3) + 1] = MapIterator->second[1];
        NewIndices[(i * 3) + 2] = MapIterator->second[2];
        NewIndices[(i - 1) * 3] = MapIterator->second[3];
        NewIndices[((i - 1) * 3) + 1] = MapIterator->second[4];
        NewIndices[((i - 1) * 3) + 2] = MapIterator->second[5];
    
        MapIterator++; 
        
        }
    

    and changed the distance calculation to:

    float Distance = -glm::dot((CameraPos - Plane), CameraFront);
    

    BUT! This should not matter since both of these reverse the order, thus netting 0 change.

    For clarity the vertex and index array I used for this project looks like this:

    GLfloat TempVertices[] = {
            -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,  // A 0
            0.5f, -0.5f, -0.5f,  1.0f, 0.0f,  // B 1
            0.5f,  0.5f, -0.5f,  1.0f, 1.0f,  // C 2
            -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,  // D 3
            -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,  // E 4
            0.5f, -0.5f,  0.5f,  1.0f, 0.0f,   // F 5
            0.5f,  0.5f,  0.5f,  1.0f, 1.0f,   // G 6
            -0.5f,  0.5f,  0.5f,  0.0f, 1.0f,   // H 7
    
            -0.5f,  0.5f, -0.5f,  0.0f, 0.0f,  // D 8
            -0.5f, -0.5f, -0.5f,  1.0f, 0.0f,  // A 9
            -0.5f, -0.5f,  0.5f,  1.0f, 1.0f,  // E 10
            -0.5f,  0.5f,  0.5f,  0.0f, 1.0f,  // H 11
            0.5f, -0.5f, -0.5f,  0.0f, 0.0f,   // B 12
            0.5f,  0.5f, -0.5f,  1.0f, 0.0f,   // C 13
            0.5f,  0.5f,  0.5f,  1.0f, 1.0f,   // G 14
            0.5f, -0.5f,  0.5f,  0.0f, 1.0f,   // F 15
    
            -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,  // A 16
            0.5f, -0.5f, -0.5f,  1.0f, 0.0f,   // B 17
            0.5f, -0.5f,  0.5f,  1.0f, 1.0f,   // F 18
            -0.5f, -0.5f,  0.5f,  0.0f, 1.0f,  // E 19
            0.5f,  0.5f, -0.5f,   0.0f, 0.0f,  // C 20
            -0.5f,  0.5f, -0.5f,  1.0f, 0.0f,  // D 21
            -0.5f,  0.5f,  0.5f,  1.0f, 1.0f,  // H 22
            0.5f,  0.5f,  0.5f,   0.0f, 1.0f,  // G 23
            };
        
        unsigned int TempIndices[] = {
            // front and back
            0, 3, 2,
            2, 1, 0,
            4, 5, 6,
            6, 7 ,4,
            // left and right
            11, 8, 9,
            9, 10, 11,
            12, 13, 14,
            14, 15, 12,
            // bottom and top
            16, 17, 18,
            18, 19, 16,
            20, 21, 22,
            22, 23, 20
            };