OpenGL VBO текстуры - PullRequest
       42

OpenGL VBO текстуры

1 голос
/ 03 апреля 2011

Я все еще новичок в VBO, и я хочу сделать модель Collada.После получения всей необходимой информации из файла cae о вершинах, нормалях и текстурах и индексах для вершин, нормалей и текстур соответственно, я поместил их в память как объект модели.осталось только то, как визуализировать этот объект, используя vbo с текстурами.Мне удалось успешно отрисовать объект, взяв вершины и индексы, а затем применив drawlelement для этого в случае рендеринга vbo.Но когда я пытаюсь визуализировать текстуры, происходит сбой, в то время как визуализация их с использованием списка отображения работает правильно, потому что я прохожу каждый треугольник и правильно применяю вершины и текскорд в соответствии с индексом вершины и индексом текстуры.Итак, как я могу применить индексы текстуры, найденные в объекте в vbo, для корректной визуализации текстуры?

Это код для проекта:

#include "bmp.h"

    struct mdl_vert
    {
        float x,y,z;
    };
    struct mdl_normal
    {
        float x,y,z;
    };
    struct mdl_texCoord
    {
        float u,v;
    };
    struct mdl_capacity
    {
        int vertsSize,indicesSize,normalsSize,texCoordsSize;
    };
    struct mdl_indices
    {
        int *vertIndices;
        int *normalIndices;
        int *texIndices;
    };

    class Group
    {
    public:
        mdl_capacity capacity;
        mdl_vert *verts;
        mdl_normal *normals;
        mdl_texCoord *texCoords;
        mdl_indices indices;
        char grp_name[64];

        Group()
        {
            capacity.texCoordsSize=0;
            capacity.normalsSize=0;
            capacity.indicesSize=0;
            capacity.vertsSize=0;
            verts=NULL;
            normals=NULL;
            texCoords=NULL;
            indices.vertIndices=NULL;
            indices.normalIndices=NULL;
            indices.texIndices=NULL;
            for(int i=0;i<64;i++)
                grp_name[i]='\0';
        }
    };

    class Model
    {
    public:
        char tex_name[512];
        std::string Name;
        Group **groups;
        int groupsSize;
    }
    #define VBO_BUFFER_SIZE 4
    struct GroupObject
    {
        GLuint *buffer;
    };
    class ModelObject
    {
    private:
        GLuint displayList;
        GroupObject *groupBuffer;
        bool isLoaded;
        GLuint tex;
        float ang,iniRotX,iniRotY,iniRotZ;
        Model *mdl;
        bool Hide;
        AUX_RGBImageRec* m_pTextureImage;                   // Heightmap Data
    public:
        ModelObject(Model* mdl)
        {
            this->mdl=mdl;
            Redraw();
        }
        void Redraw()
        {
            Hide=false;
            ang=-0;
            iniRotX=1;
            iniRotY=0;
            iniRotZ=0;
            if(displayList!=-1)
                displayList=-1;
            groupBuffer=NULL;
        }

        void BuildTexture(int i)
        {
            if(mdl->groups[i]->capacity.texCoordsSize>0)
            {
                try
                {
                    m_pTextureImage = auxDIBImageLoad( mdl->tex_name );             // Utilize GLaux's Bitmap Load Routine
                    glGenTextures( 1, &tex );                   // Get An Open ID
                    glBindTexture( GL_TEXTURE_2D, tex );                // Bind The Texture
                    glTexImage2D( GL_TEXTURE_2D, 0, 3, m_pTextureImage->sizeX, m_pTextureImage->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, m_pTextureImage->data );
                    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
                    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

                    // Free The Texture Data
                    if( m_pTextureImage )
                    {
                        if( m_pTextureImage->data )
                            free( m_pTextureImage->data );
                        free( m_pTextureImage );
                    }
                }
                catch(std::exception &ex)
                {
                }
            }
        }

        void BuildVBO()
        {
            int index=0;
            groupBuffer=new GroupObject[mdl->groupsSize];

            for(int i=0;i<mdl->groupsSize;i++)
            {
                BuildTexture(i);
                groupBuffer[i].buffer=new GLuint[VBO_BUFFER_SIZE];
                // Generate And Bind The Vertex Buffer
                glGenBuffersARB( 1, &groupBuffer[i].buffer[0] );                            // Get A Valid Name
                glBindBufferARB( GL_ARRAY_BUFFER_ARB, groupBuffer[i].buffer[0] );           // Bind The Buffer
                glBufferDataARB( GL_ARRAY_BUFFER_ARB,mdl->groups[i]->capacity.vertsSize*sizeof(mdl_vert), mdl->groups[i]->verts, GL_STATIC_DRAW_ARB );
                // Generate And Bind The Normal Buffer
                glGenBuffersARB( 1, &groupBuffer[i].buffer[1] );                            // Get A Valid Name
                glBindBufferARB( GL_ARRAY_BUFFER_ARB, groupBuffer[i].buffer[1] );           // Bind The Buffer
                glBufferDataARB( GL_ARRAY_BUFFER_ARB,mdl->groups[i]->capacity.normalsSize*sizeof(mdl_normal),  mdl->groups[i]->normals, GL_STATIC_DRAW_ARB );
                // Generate And Bind The Texture Buffer
                glGenBuffersARB( 1, &groupBuffer[i].buffer[2] );                            // Get A Valid Name
                glBindBufferARB( GL_ARRAY_BUFFER_ARB, groupBuffer[i].buffer[2] );           // Bind The Buffer
                glBufferDataARB( GL_ARRAY_BUFFER_ARB,mdl->groups[i]->capacity.texCoordsSize*sizeof(mdl_texCoord),  mdl->groups[i]->texCoords, GL_STATIC_DRAW_ARB );
                // Generate And Bind The Index Buffer
                glGenBuffersARB(1, &groupBuffer[i].buffer[3]);
                glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, groupBuffer[i].buffer[3]);
                glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mdl->groups[i]->capacity.indicesSize*sizeof(unsigned int),  mdl->groups[i]->indices.vertIndices, GL_STATIC_DRAW_ARB);
            }
        }

        void render()
        {
            if(!Hide)
            {
                if(Drawer.vboSupported())
                {
                    if(groupBuffer==NULL)
                        BuildVBO();
                    glRotatef(ang,iniRotX,iniRotY,iniRotZ);
                    for(int i=0;i<mdl->groupsSize;i++)
                    {
                        // Enable Pointers
                        glEnableClientState( GL_VERTEX_ARRAY );                 // Disable Vertex Arrays
                        glEnableClientState( GL_NORMAL_ARRAY );             // Enable Normal Arrays
                        glEnableClientState( GL_TEXTURE_COORD_ARRAY );              // Enable Texture Coord Arrays

                        glBindBufferARB(  GL_ARRAY_BUFFER_ARB, groupBuffer[i].buffer[0] );
                        glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0));

                        glBindBufferARB(  GL_ARRAY_BUFFER_ARB, groupBuffer[i].buffer[1] );
                        glNormalPointer(GL_FLOAT,0, BUFFER_OFFSET(0));

                        glClientActiveTexture(GL_TEXTURE0);
                        glBindBufferARB(  GL_ARRAY_BUFFER_ARB, groupBuffer[i].buffer[2] );
                        glTexCoordPointer(2,GL_FLOAT,0,BUFFER_OFFSET(0));

                        glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER, groupBuffer[i].buffer[3]);
                        glIndexPointer(GL_UNSIGNED_INT,0,BUFFER_OFFSET(0));
                        glDrawElements( GL_TRIANGLES, mdl->groups[i]->capacity.indicesSize,GL_UNSIGNED_INT, 0); // Draw All Of The Triangles At Once

                        // Disable Pointers
                        glDisableClientState( GL_VERTEX_ARRAY );                    // Disable Vertex Arrays
                        glDisableClientState( GL_NORMAL_ARRAY );                // Enable Normal Arrays
                        glDisableClientState( GL_TEXTURE_COORD_ARRAY );             // Enable Texture Coord Arrays
                    }
                    glRotatef(-ang,iniRotX,iniRotY,iniRotZ);
                }
                else
                {
                    if(this->displayList==-1)
                    {
                        displayList = glGenLists(1);
                        glNewList(displayList,GL_COMPILE_AND_EXECUTE);
                        glRotatef(ang,iniRotX,iniRotY,iniRotZ);
                        for(int j=0;j<mdl->groupsSize;j++)
                        {
                            glEnable(GL_TEXTURE_2D);
                            glBindTexture(GL_TEXTURE_2D, tex);
                            // Enable Pointers
                            BuildTexture(j);
                            //glColor3f(((float)(rand()%256)/256.0f),((float)(rand()%256)/256.0f),((float)(rand()%256)/256.0f));
                            for(int i=0;i<mdl->groups[j]->capacity.indicesSize;i+=3)
                            {
                                int iv1=mdl->groups[j]->indices.vertIndices[i];
                                int in1=mdl->groups[j]->indices.normalIndices[i];
                                int it1=mdl->groups[j]->indices.texIndices[i];
                                int iv2=mdl->groups[j]->indices.vertIndices[i+1];
                                int in2=mdl->groups[j]->indices.normalIndices[i+1];
                                int it2=mdl->groups[j]->indices.texIndices[i+1];
                                int iv3=mdl->groups[j]->indices.vertIndices[i+2];
                                int in3=mdl->groups[j]->indices.normalIndices[i+2];
                                int it3=mdl->groups[j]->indices.texIndices[i+2];
                                glBegin(GL_TRIANGLES);
                                    glTexCoord2f(mdl->groups[j]->texCoords[it1].u,mdl->groups[j]->texCoords[it1].v);
                                    glNormal3f(mdl->groups[j]->normals[in1].x,mdl->groups[j]->normals[in1].y,mdl->groups[j]->normals[in1].z);
                                    glVertex3f(mdl->groups[j]->verts[iv1].x,mdl->groups[j]->verts[iv1].y,mdl->groups[j]->verts[iv1].z);
                                    glTexCoord2f(mdl->groups[j]->texCoords[it2].u,mdl->groups[j]->texCoords[it2].v);
                                    glNormal3f(mdl->groups[j]->normals[in2].x,mdl->groups[j]->normals[in2].y,mdl->groups[j]->normals[in2].z);
                                    glVertex3f(mdl->groups[j]->verts[iv2].x,mdl->groups[j]->verts[iv2].y,mdl->groups[j]->verts[iv2].z);
                                    glTexCoord2f(mdl->groups[j]->texCoords[it3].u,mdl->groups[j]->texCoords[it3].v);
                                    glNormal3f(mdl->groups[j]->normals[in3].x,mdl->groups[j]->normals[in3].y,mdl->groups[j]->normals[in3].z);
                                    glVertex3f(mdl->groups[j]->verts[iv3].x,mdl->groups[j]->verts[iv3].y,mdl->groups[j]->verts[iv3].z);
                                glEnd();
                            }
                            glDisable(GL_TEXTURE_2D);
                        }
                        glRotatef(-ang,iniRotX,iniRotY,iniRotZ);
                        glEndList();
                        glCallList(displayList);
                    }
                    else
                        glCallList(displayList);
                }
            }
        }

1 Ответ

1 голос
/ 10 января 2012

В OpenGL нет текстурных индексов. Такое разделение позиций и текстур довольно распространено в программном обеспечении для моделирования, так как им проще управлять. Но в OpenGL вам нужно иметь столько же координат текстур, сколько есть позиций, чтобы их можно было индексировать, используя один и тот же индекс.

Это потребует от вас перестройки всех буферов, чтобы каждая комбинация индекса вершины, нормального индекса и индекса texcoord, встречающаяся в вашей модели, могла быть сопоставлена ​​с одним индексом для рендеринга OpenGL. Я попробую написать псевдокод:

struct Trinity {
    int iv, in, it;

    bool operator <(const Trinity &t) const // implement less-than operator as required by std::map
    {
        return iv < t.iv || (iv == t.iv && (in < t.in || (in == t.in && it < t.it)));
    }
};

#include <map>
#include <vector>

for(int j=0;j<mdl->groupsSize;j++) { // for each object ...
    int next_index = 0; // next index to be assigned

    std::map<int, Trinity> index_map; // map of collada indices to OpenGL indices

    std::vector<int> new_indices; // new indices that can be used for drawing with OpenGL
    std::vector<float> new_positions, new_texcoords, new_normals; // other arrays

    for(int i=0;i<mdl->groups[j]->capacity.indicesSize;i++) { // for each vertex ...
        Trinity t;
        t.iv = mdl->groups[j]->indices.vertIndices[i];
        t.in = mdl->groups[j]->indices.normalIndices[i];
        t.it = mdl->groups[j]->indices.texIndices[i];
        // go through all the vertices' indices

        int index;
        if(index_map.find(t) != index_map.end())
            index = index_map[t]; // we already saw this combination of indices, reuse it
        else {
            index = next_index; // this is new; assign a new index
            ++ next_index;
            index_map[t] = index; // store the index in the map

            new_positions.push_back(mdl->groups[j]->verts[t.iv].x);
            new_positions.push_back(mdl->groups[j]->verts[t.iv].y);
            new_positions.push_back(mdl->groups[j]->verts[t.iv].z);

            new_texcoords.push_back(mdl->groups[j]->texCoords[t.it].u);
            new_texcoords.push_back(mdl->groups[j]->texCoords[t.it].v);

            new_normals.push_back(mdl->groups[j]->normals[t.in].x);
            new_normals.push_back(mdl->groups[j]->normals[t.in].y);
            new_normals.push_back(mdl->groups[j]->normals[t.in].z);
            // add this particular combination of coordinates at the end of the buffers
        }
        // translate the combination of iv, in, it to a single index

        new_indices.push_back(index);
        // store it in the array
    }

    // object data ready to pass to VBOs
}

Теперь вы можете помещать new_indices, new_positions, new_normals и new_texcoords в VBO и отображать их. Надеюсь, это поможет ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...