Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Missing faces when displaying STL data

Tags:

c++

opengl

I wrote a simple parser for the ASCII STL format. When I try to render the triangles with the supplied normals, the resulting object is missing many faces:

This is how it should look like:

What I already tried:

  • explicitly disabled backface culling (though it shouldn't have been active before)
  • ensured that the depth buffer is enabled

Here is a minimal sample program which reproduces the error:

 #include <SDL2/SDL.h>
 #include <SDL2/SDL_main.h>
 #include <SDL2/SDL_render.h>
 #include <SDL2/SDL_opengl.h>

int main(int argc, char **argv) {
    SDL_Init(SDL_INIT_VIDEO);
    int screen_w=1280,screen_h=720;
    SDL_Window * win = SDL_CreateWindow("test", 20, 20, screen_w, screen_h,
            SDL_WINDOW_OPENGL);
    SDL_GLContext glcontext = SDL_GL_CreateContext(win);


    STLParser stlparser;
    std::ifstream file(".\\logo.stl");
    stlparser.parseAscii(file);
    const auto& ndata = stlparser.getNData();
    const auto& vdata = stlparser.getVData();
    std::cout << "number of facets: " << ndata.size() << std::endl;

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);


    glMatrixMode(GL_PROJECTION | GL_MODELVIEW);
    glLoadIdentity();
    glScalef(1.f, -1.f, 1.f);
    glOrtho(0, screen_w, 0, screen_h, -screen_w, screen_w);

    glClearDepth(1.0f);
    glDepthFunc(GL_LEQUAL);
    glEnable(GL_DEPTH_TEST);

    glDisable(GL_CULL_FACE);

    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_VERTEX_ARRAY);

    glNormalPointer(GL_FLOAT, 0, ndata.data());
    glVertexPointer(3, GL_FLOAT, 0, vdata.data());

    SDL_Event event;
    bool quit = false;

    while (!quit) {
        while (SDL_PollEvent(&event))
            switch(event.type) {
            case SDL_QUIT: quit = true; break;
            }
            ;
        // Drawing
        glClearColor(255,255,255,255);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glTranslatef(screen_w/2,0,0);
        glRotatef(0.5,0,1,0);
        glTranslatef(-screen_w/2,0,0);


        glPushMatrix();
        glTranslatef(screen_w/2,screen_h/2,0);


        glColor3f(0.5,0.5,0);
        glDrawArrays(GL_TRIANGLES, 0, vdata.size());

        glPopMatrix();


        SDL_GL_SwapWindow(win);

        SDL_Delay(10);
    }
    SDL_DestroyWindow(win);
    SDL_Quit();
    return 0;
}

The STLParser methods getNData() and getVData() have the following signatures:

const std::vector<std::array<float,3>>& getNData() const;
const std::vector<std::array<std::array<float,3>,3>>& getVData() const;

STLParser output should be correct, but I can provide the sources as well if needed.

What am I doing wrong?

like image 240
TheBender Avatar asked Mar 16 '23 13:03

TheBender


1 Answers

You should change

glDrawArrays(GL_TRIANGLES, 0, vdata.size());

to

glDrawArrays(GL_TRIANGLES, 0, 3 * vdata.size());

I.e. count should be vertex count, but not triangle count.

like image 195
Evgeny Panasyuk Avatar answered Mar 28 '23 03:03

Evgeny Panasyuk