opengl3dmeshgl-triangle-strip

How do I draw a rectangular box using GL_TRIANGLE_STRIP?


I'm new to OpenGL programming and need some help wrapping my head around this issue. I found this answer detailing how to create a cube mesh using a GL_TRIANGLE_STRIP. However, I want to create a rectangular box where the one axis isn't just elongated but rather repeated, so that the geometry ends up something like this:

enter image description here

I can't figure out how I'm supposed to construct such a shape where the geometry gets generated correctly, with correct normals and closed ends, with the winding order to keep in mind and what-not.

How should I be thinking and defining the vertices?


Solution

  • The formula for the triangle strip cube does most of the work, all you have to do is extend the long faces to add more in between, which can be done with for loops. Cube with long faces There are two times the strip changes direction, both on the bottom face, so we just need a little manual work there. I wrote up this simple function to create vertices based on a length, and it will build a length by 1 by 1 rectangle.

    void generateRect(int length, std::vector<glm::vec3>& vertices) {
        std::vector<glm::vec3> vertexArray;
        
        //Generate nescessary points
        float x = length / 2.0f;
        for (int i = 0; i <= length; i++) {
            vertexArray.push_back(glm::vec3(x, -0.5f, 0.5f));
            vertexArray.push_back(glm::vec3(x, -0.5f, -0.5f));
            vertexArray.push_back(glm::vec3(x, 0.5f, 0.5f));
            vertexArray.push_back(glm::vec3(x, 0.5f, -0.5f));
            x -= 1.0f;
        }
        
        //+Y face
        for (int i = 0; i <= length; i++) {
            int index = i * 4 + 3;
            vertices.push_back(vertexArray.at(index));
            vertices.push_back(vertexArray.at(index - 1));
        }
        
        //Change direction (Half of -X face)
        vertices.push_back(vertexArray.at(length * 4));
        
        //+Z face
        for (int i = length - 1; i >= 0; i--) {
            int index = i * 4;
            vertices.push_back(vertexArray.at(index + 2));
            vertices.push_back(vertexArray.at(index));
        }
        
        //-Z face (+X face created as well)
        for (int i = 0; i <= length; i++) {
            int index = i * 4 + 3;
            vertices.push_back(vertexArray.at(index));
            vertices.push_back(vertexArray.at(index - 2));
        }
        
        //Change direction (Other half of -X face)
        vertices.push_back(vertexArray.at(length * 4));
        
        //-Y face
        for (int i = length - 1; i >= 0; i--) {
            int index = i * 4;
            vertices.push_back(vertexArray.at(index + 1));
            vertices.push_back(vertexArray.at(index));
        }
    }
    

    From this we get our rectangle, and for texturing I just used a cubemap as I've been doing skyboxes. OpenGL is smart enough to know the winding order will be reversed every other triangle, so no need to do any fancy math. You just have to make sure it's right for the first one, in this case the first one is counter-clockwise.

    Result

    For normal generation, it's a little harder as the vertices must share a normal as well, even if it's being used for a different face. I don't think there is a workaround, but I haven't done much with triangle strip so there may be, perhaps something to do with a geometry shader.