Esempio n. 1
0
/*! Render the model; the time parameter is ignored right now
 *  since this class doesn't currently support animation.
 */
void
ModelGeometry::render(RenderContext& rc, double /* t */)
{
    // The first time the mesh is rendered, we will try and place the
    // vertex data in a vertex buffer object and potentially get a huge
    // rendering performance boost.  This can consume a great deal of
    // memory, since we're duplicating the vertex data.  TODO: investigate
    // the possibility of deleting the original data.  We can always map
    // read-only later on for things like picking, but this could be a low
    // performance path.
    if (!m_vbInitialized && isVBOSupported())
    {
        m_vbInitialized = true;

        for (unsigned int i = 0; i < m_model->getMeshCount(); ++i)
        {
            Mesh* mesh = m_model->getMesh(i);
            const Mesh::VertexDescription& vertexDesc = mesh->getVertexDescription();

            GLuint vboId = 0;
            if (mesh->getVertexCount() * vertexDesc.stride > MinVBOSize)
            {
                glGenBuffersARB(1, &vboId);
                if (vboId != 0)
                {
                    glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId);
                    glBufferDataARB(GL_ARRAY_BUFFER_ARB,
                                    mesh->getVertexCount() * vertexDesc.stride,
                                    mesh->getVertexData(),
                                    GL_STATIC_DRAW_ARB);
					glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
                }
            }

            m_glData->vbos.push_back(vboId);
        }
    }

    unsigned int lastMaterial = ~0u;
    unsigned int materialCount = m_model->getMaterialCount();

    // Iterate over all meshes in the model
    for (unsigned int meshIndex = 0; meshIndex < m_model->getMeshCount(); ++meshIndex)
    {
        Mesh* mesh = m_model->getMesh(meshIndex);
        GLuint vboId = 0;

        if (m_glData && meshIndex < m_glData->vbos.size())
        {
            vboId = m_glData->vbos[meshIndex];
        }

        if (vboId != 0)
        {
            // Bind the vertex buffer object.
            glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId);
            rc.setVertexArrays(mesh->getVertexDescription(), NULL);
        }
        else
        {
            // No vertex buffer object; just use normal vertex arrays
            rc.setVertexArrays(mesh->getVertexDescription(), mesh->getVertexData());
        }

        // Iterate over all primitive groups in the mesh
        for (unsigned int groupIndex = 0; groupIndex < mesh->getGroupCount(); ++groupIndex)
        {
            const Mesh::PrimitiveGroup* group = mesh->getGroup(groupIndex);

            // Set up the material
            const Material* material = NULL;
            unsigned int materialIndex = group->materialIndex;
            if (materialIndex != lastMaterial && materialIndex < materialCount)
            {
                material = m_model->getMaterial(materialIndex);
            }

            rc.setMaterial(material);
            rc.drawGroup(*group);
        }

        // If we set a VBO, unbind it.
        if (vboId != 0)
        {
            glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
        }
    }
}