Beispiel #1
0
void ResetCamera()
{
    g_model.getCenter(g_targetPos[0], g_targetPos[1], g_targetPos[2]);

    g_cameraPos[0] = g_targetPos[0];
    g_cameraPos[1] = g_targetPos[1];
    g_cameraPos[2] = g_targetPos[2] + g_model.getRadius() + CAMERA_ZNEAR + 0.4f;

    g_pitch = 0.0f;
    g_heading = 0.0f;
}
Beispiel #2
0
void init_VBO()
{
    // 1 vertex, 1 normal, + N element sets
    num_buffer_objects = 2 + model.getNumberOfMeshes();
    bufferObjects = (GLuint*) malloc( sizeof(GLuint) * num_buffer_objects );
    glGenBuffers( num_buffer_objects, bufferObjects );


    //
    // Copy data to video memory
    //

    // Vertices array stores Vertex data & Normal Data
    glBindBuffer( GL_ARRAY_BUFFER, bufferObjects[VERTEX_DATA] );
    glBufferData( GL_ARRAY_BUFFER, model.getVertexSize() * model.getNumberOfVertices(),
                                        model.getVertexBuffer(), GL_STATIC_DRAW );

    /* Normal data
    if ( model.hasNormals())
    {  
        glBindBuffer( GL_ARRAY_BUFFER, bufferObjects[NORMAL_DATA] );
        glBufferData( GL_ARRAY_BUFFER, sizeof(float)* model.getNumberOfVertices() * 3,
                                                model.getVertexBuffer()->normal, GL_STATIC_DRAW );
    } */

    for ( int i = 0; i < model.getNumberOfMeshes(); ++i )
    {
        const ModelOBJ::Mesh *pMesh = &model.getMesh(i);

        // Indexes
        glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, bufferObjects[INDEX_DATA+i] );
        glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * pMesh->triangleCount * 3, model.getIndexBuffer() + pMesh->startIndex, GL_STATIC_DRAW ); 

    }
}
Beispiel #3
0
void UnloadModel()
{
    SetCursor(LoadCursor(0, IDC_WAIT));

    ModelTextures::iterator i = g_modelTextures.begin();

    while (i != g_modelTextures.end())
    {
        glDeleteTextures(1, &i->second);
        ++i;
    }

    g_modelTextures.clear();
    g_model.destroy();

    SetCursor(LoadCursor(0, IDC_ARROW));
    SetWindowText(g_hWnd, APP_TITLE);
}
Beispiel #4
0
void LoadModel(const char *pszFilename)
{
    // Import the OBJ file and normalize to unit length.

    SetCursor(LoadCursor(0, IDC_WAIT));

    if (!g_model.import(pszFilename))
    {
        SetCursor(LoadCursor(0, IDC_ARROW));
        throw std::runtime_error("Failed to load model.");
    }

					
					
	//g_model.normalize();





}
bool MeshLoader::Load(const std::string& name) {
	bool calculateTangents = true;
	bool calculateNormals = true;
	char msg[256];
	sprintf_s(msg, "# Loading mesh %s", name.c_str());
	LOG(msg);

	ModelOBJ* obj = new ModelOBJ();
	if(!obj->import((Filesystem::Instance().GetMediaRoot()+name).c_str(), calculateNormals)) {
		char msg[256];
		sprintf_s(msg, "# Problem loading mesh %s!", name.c_str());
		LOG_ERROR(msg);
		return false;
	}

	MeshPtr mesh(new Mesh(name));
	mesh->m_NumVertices = obj->getNumberOfVertices();
	mesh->m_NumIndices = obj->getNumberOfIndices();
	mesh->m_Vertices.reset(new Vertex[mesh->m_NumVertices]);
	mesh->m_Indices.reset(new uint32[mesh->m_NumIndices]);
	const ModelOBJ::Vertex* vertices = obj->getVertexBuffer();

	for(uint32 i=0; i<mesh->m_NumVertices; i++) {
		memcpy(&(mesh->m_Vertices[i].position), vertices[i].position, sizeof(float)*3);
		memcpy(&(mesh->m_Vertices[i].normal), vertices[i].normal, sizeof(float)*3);
		memcpy(&(mesh->m_Vertices[i].texCoords), vertices[i].texCoord, sizeof(float)*2);
	}
	
	const std::vector<uint16>& indices = obj->getIndexBuffer();
	for(uint32 i=0; i<mesh->m_NumIndices; i++) {
			mesh->m_Indices[i] = indices[i];
	}

	if(calculateTangents) CalculateTangents(mesh);

	delete obj;

	m_Meshes[name] = mesh;
	sprintf_s(msg, "# Done loading mesh! Vertices# %i, Indices#: %i, HasTangents: %i\n", mesh->m_NumVertices, mesh->m_NumIndices, (int)calculateTangents);
	LOG(msg);
	return true;
}
Beispiel #6
0
void draw_test_model_VBO()
{
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_INDEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);

    // Here’s where the data is now
    // Vertex data
    glBindBuffer( GL_ARRAY_BUFFER, bufferObjects[VERTEX_DATA] );
    glVertexPointer( 3, GL_FLOAT, model.getVertexSize(), 0 );

    // Normal data
    if ( model.hasNormals())
    {  
        //glBindBuffer( GL_ARRAY_BUFFER, bufferObjects[NORMAL_DATA] );
        glBindBuffer( GL_ARRAY_BUFFER, bufferObjects[VERTEX_DATA] );
        glNormalPointer( GL_FLOAT, model.getVertexSize(), model.getVertexBuffer()->normal /* pointer? */ ); 
    }

    for ( int i = 0; i < model.getNumberOfMeshes(); ++i )
    {
        const ModelOBJ::Mesh * pMesh = &model.getMesh(i);

        // Indexes
        glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, bufferObjects[INDEX_DATA+i] );
        glDrawElements( GL_TRIANGLES, pMesh->triangleCount * 3, GL_UNSIGNED_INT, 0 ); 
    }

    // free the VBO context for regular Vertex Array calls
    glBindBuffer( GL_ARRAY_BUFFER, 0 );
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );

    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_INDEX_ARRAY);
}
void ModelVBO::BindBuffers(ModelOBJ obj)
{
    if (obj.hasPositions())
    {
        // 1rst attribute buffer : vertices
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
        glVertexAttribPointer(
            0,                  // attribute
            3,                  // size
            GL_FLOAT,           // type
            GL_FALSE,           // normalized?
            obj.getVertexSize(),                  // stride
            (void *)0           // array buffer offset
        );
    }

    if (obj.hasTextureCoords())
    {
        // 2nd attribute buffer : UVs
        glEnableVertexAttribArray(1);
        glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
        glVertexAttribPointer(
            1,                                // attribute
            2,                                // size
            GL_FLOAT,                         // type
            GL_FALSE,                         // normalized?
            obj.getVertexSize(),                                // stride
            (void *)(3 * sizeof(float))                       // array buffer offset
        );
    }

    if (obj.hasNormals())
    {
        // 3rd attribute buffer : normals
        glEnableVertexAttribArray(2);
        glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
        glVertexAttribPointer(
            2,                                // attribute
            3,                                // size
            GL_FLOAT,                         // type
            GL_FALSE,                         // normalized?
            obj.getVertexSize(),                                // stride
            (void *)(5 * sizeof(float))                      // array buffer offset
        );
    }

    if (obj.hasTangents())
    {
        // 4th attribute buffer : tangents
        glEnableVertexAttribArray(3);
        glBindBuffer(GL_ARRAY_BUFFER, tangentbuffer);
        glVertexAttribPointer(
            3,                                // attribute
            4,                                // size
            GL_FLOAT,                         // type
            GL_FALSE,                         // normalized?
            obj.getVertexSize(),                                // stride
            (void *)(8 * sizeof(float))                     // array buffer offset
        );
    }
}
void ModelVBO::Load(ModelOBJ obj)
{
    if (obj.hasPositions())
    {
        glGenBuffers(1, &vertexbuffer);
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
        glBufferData(GL_ARRAY_BUFFER, obj.getNumberOfVertices() * obj.getVertexSize(), obj.getVertexBuffer(), GL_STATIC_DRAW);
    }

    if (obj.hasTextureCoords())
    {
        glGenBuffers(1, &uvbuffer);
        glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
        glBufferData(GL_ARRAY_BUFFER, obj.getNumberOfVertices() * obj.getVertexSize(), obj.getVertexBuffer(), GL_STATIC_DRAW);
    }

    if (obj.hasNormals())
    {
        glGenBuffers(1, &normalbuffer);
        glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
        glBufferData(GL_ARRAY_BUFFER, obj.getNumberOfVertices() * obj.getVertexSize(), obj.getVertexBuffer(), GL_STATIC_DRAW);
    }

    if (obj.hasTangents())
    {
        glGenBuffers(1, &tangentbuffer);
        glBindBuffer(GL_ARRAY_BUFFER, tangentbuffer);
        glBufferData(GL_ARRAY_BUFFER, obj.getNumberOfVertices() * obj.getVertexSize(), obj.getVertexBuffer(), GL_STATIC_DRAW);
    }

    glGenBuffers(1, &elementbuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, obj.getNumberOfIndices() * obj.getIndexSize(), obj.getIndexBuffer(),
                 GL_STATIC_DRAW);
}
Beispiel #9
0
void ProcessMouseInput(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    // Use the left mouse button to track the camera.
    // Use the middle mouse button to dolly the camera.
    // Use the right mouse button to orbit the camera.

    enum CameraMode {CAMERA_NONE, CAMERA_TRACK, CAMERA_DOLLY, CAMERA_ORBIT};

    static CameraMode cameraMode = CAMERA_NONE;
    static POINT ptMousePrev = {0};
    static POINT ptMouseCurrent = {0};
    static int mouseButtonsDown = 0;
    static float dx = 0.0f;
    static float dy = 0.0f;

    switch (msg)
    {
    case WM_LBUTTONDOWN:
        cameraMode = CAMERA_TRACK;
        ++mouseButtonsDown;
        SetCapture(hWnd);
        ptMousePrev.x = static_cast<int>(static_cast<short>(LOWORD(lParam)));
        ptMousePrev.y = static_cast<int>(static_cast<short>(HIWORD(lParam)));
        ClientToScreen(hWnd, &ptMousePrev);
        break;

    case WM_RBUTTONDOWN:
        cameraMode = CAMERA_ORBIT;
        ++mouseButtonsDown;
        SetCapture(hWnd);
        ptMousePrev.x = static_cast<int>(static_cast<short>(LOWORD(lParam)));
        ptMousePrev.y = static_cast<int>(static_cast<short>(HIWORD(lParam)));
        ClientToScreen(hWnd, &ptMousePrev);
        break;

    case WM_MBUTTONDOWN:
        cameraMode = CAMERA_DOLLY;
        ++mouseButtonsDown;
        SetCapture(hWnd);
        ptMousePrev.x = static_cast<int>(static_cast<short>(LOWORD(lParam)));
        ptMousePrev.y = static_cast<int>(static_cast<short>(HIWORD(lParam)));
        ClientToScreen(hWnd, &ptMousePrev);
        break;

    case WM_MOUSEMOVE:
        ptMouseCurrent.x = static_cast<int>(static_cast<short>(LOWORD(lParam)));
        ptMouseCurrent.y = static_cast<int>(static_cast<short>(HIWORD(lParam)));
        ClientToScreen(hWnd, &ptMouseCurrent);

        switch (cameraMode)
        {
        case CAMERA_TRACK:
            dx = static_cast<float>(ptMouseCurrent.x - ptMousePrev.x);
            dx *= MOUSE_TRACK_SPEED;

            dy = static_cast<float>(ptMouseCurrent.y - ptMousePrev.y);
            dy *= MOUSE_TRACK_SPEED;

            g_cameraPos[0] -= dx;
            g_cameraPos[1] += dy;

            g_targetPos[0] -= dx;
            g_targetPos[1] += dy;

            break;

        case CAMERA_DOLLY:
            dy = static_cast<float>(ptMouseCurrent.y - ptMousePrev.y);
            dy *= MOUSE_DOLLY_SPEED;

            g_cameraPos[2] -= dy;

            if (g_cameraPos[2] < g_model.getRadius() + CAMERA_ZNEAR)
                g_cameraPos[2] = g_model.getRadius() + CAMERA_ZNEAR;

            if (g_cameraPos[2] > CAMERA_ZFAR - g_model.getRadius())
                g_cameraPos[2] = CAMERA_ZFAR - g_model.getRadius();

            break;

        case CAMERA_ORBIT:
            dx = static_cast<float>(ptMouseCurrent.x - ptMousePrev.x);
            dx *= MOUSE_ORBIT_SPEED;

            dy = static_cast<float>(ptMouseCurrent.y - ptMousePrev.y);
            dy *= MOUSE_ORBIT_SPEED;

            g_heading += dx;
            g_pitch += dy;

            if (g_pitch > 90.0f)
                g_pitch = 90.0f;

            if (g_pitch < -90.0f)
                g_pitch = -90.0f;

            break;
        }

        ptMousePrev.x = ptMouseCurrent.x;
        ptMousePrev.y = ptMouseCurrent.y;
        break;

    case WM_LBUTTONUP:
    case WM_RBUTTONUP:
    case WM_MBUTTONUP:
        if (--mouseButtonsDown <= 0)
        {
            mouseButtonsDown = 0;
            cameraMode = CAMERA_NONE;
            ReleaseCapture();
        }
        else
        {
            if (wParam & MK_LBUTTON)
                cameraMode = CAMERA_TRACK;
            else if (wParam & MK_RBUTTON)
                cameraMode = CAMERA_ORBIT;
            else if (wParam & MK_MBUTTON)
                cameraMode = CAMERA_DOLLY;
        }
        break;

    default:
        break;
    }
}
Beispiel #10
0
void DrawFrame()
{
    glViewport(0, 0, g_windowWidth, g_windowHeight);
    glClearColor(0.3f, 0.5f, 0.9f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(CAMERA_FOVY,
        static_cast<float>(g_windowWidth) / static_cast<float>(g_windowHeight),
        CAMERA_ZNEAR, CAMERA_ZFAR);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(g_cameraPos[0], g_cameraPos[1], g_cameraPos[2],
        g_targetPos[0], g_targetPos[1], g_targetPos[2],
        0.0f, 1.0f, 0.0f);

    glRotatef(g_pitch, 1.0f, 0.0f, 0.0f);
    glRotatef(g_heading, 0.0f, 1.0f, 0.0f);

const ModelOBJ::Mesh *pMesh = 0;
    const ModelOBJ::Material *pMaterial = 0;
    const ModelOBJ::Vertex *pVertices = 0;
    ModelTextures::const_iterator iter;

    for (int i = 0; i < g_model.getNumberOfMeshes(); ++i)
    {
        pMesh = &g_model.getMesh(i);
        pMaterial = pMesh->pMaterial;
        pVertices = g_model.getVertexBuffer();

        glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, pMaterial->ambient);
        glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pMaterial->diffuse);
        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, pMaterial->specular);
        glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, pMaterial->shininess * 128.0f);

        if (g_enableTextures)
        {
            iter = g_modelTextures.find(pMaterial->colorMapFilename);

            if (iter == g_modelTextures.end())
            {
                glDisable(GL_TEXTURE_2D);
            }
            else
            {
                glEnable(GL_TEXTURE_2D);
                glBindTexture(GL_TEXTURE_2D, iter->second);
            }
        }
        else
        {
            glDisable(GL_TEXTURE_2D);
        }

            glEnableClientState(GL_VERTEX_ARRAY);
            glVertexPointer(3, GL_FLOAT, g_model.getVertexSize(),   g_model.getVertexBuffer()->position);
       
            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
            glTexCoordPointer(2, GL_FLOAT, g_model.getVertexSize(), g_model.getVertexBuffer()->texCoord);
       
            glEnableClientState(GL_NORMAL_ARRAY);
            glNormalPointer(GL_FLOAT, g_model.getVertexSize(),      g_model.getVertexBuffer()->normal);
    
       




        glDrawElements(GL_TRIANGLES, pMesh->triangleCount * 3, GL_UNSIGNED_INT, g_model.getIndexBuffer() + pMesh->startIndex);



           glDisableClientState(GL_NORMAL_ARRAY);

            glDisableClientState(GL_TEXTURE_COORD_ARRAY);

            glDisableClientState(GL_VERTEX_ARRAY);
    }
}
Beispiel #11
0
bool Convert(const char* pFilePath)
{
    ModelOBJ model;
    FILE* pOutput = 0;
    SubMesh subMesh;
    static char pOutPath[MAX_PATH];

//open mesh
    if (!model.import(pFilePath))
    {
        printf("Failed to open file '%s'!\n", pFilePath);
        return false;
    }

    //open output file
    ConvertFileName(pFilePath, pOutPath);
    if (fopen_s(&pOutput, pOutPath, "wb") != 0)
    {
        printf("Could not open output file '%s'!\n", pOutPath);
        return false;
    }


    //write basic info
    int verticesCount = model.getNumberOfVertices();
    int indiciesCount = model.getNumberOfIndices();
    int subMeshesCount = model.getNumberOfMeshes();

    printf("Veritces count: %i\n", verticesCount);
    printf("Indicies count: %i\n", indiciesCount);
    printf("Submeshes count: %i\n", subMeshesCount);

    fwrite("nfm", 4, 1, pOutput); //signature
    fwrite(&verticesCount, sizeof(int), 1, pOutput);
    fwrite(&indiciesCount, sizeof(int), 1, pOutput);
    fwrite(&subMeshesCount, sizeof(int), 1, pOutput);



    //write verticies
    XVertex* pVertices = (XVertex*)malloc(verticesCount * sizeof(XVertex));
    const ModelOBJ::Vertex* pModelVertices = model.getVertexBuffer();
    for (int i = 0; i < verticesCount; i++)
    {
        //vertex position
        pVertices[i].pos[0] = pModelVertices[i].position[0];
        pVertices[i].pos[1] = pModelVertices[i].position[1];
        pVertices[i].pos[2] = -pModelVertices[i].position[2];

        //vertex texture coordinates
        pVertices[i].texCoord[0] = pModelVertices[i].texCoord[0];
        pVertices[i].texCoord[1] = pModelVertices[i].texCoord[1];

        //vertex normal
        if (ISNAN(pModelVertices[i].normal[0]) || ISNAN(pModelVertices[i].normal[1]) ||
                ISNAN(pModelVertices[i].normal[2]))
        {
            pVertices[i].normal[0] = 0;
            pVertices[i].normal[1] = 127;
            pVertices[i].normal[2] = 0;
        }
        else
        {
            pVertices[i].normal[0] = FloatToChar(pModelVertices[i].normal[0]);
            pVertices[i].normal[1] = FloatToChar(pModelVertices[i].normal[1]);
            pVertices[i].normal[2] = FloatToChar(-pModelVertices[i].normal[2]);
        }

        //vertex tangent
        if (ISNAN(pModelVertices[i].tangent[0]) || ISNAN(pModelVertices[i].tangent[1]) ||
                ISNAN(pModelVertices[i].tangent[2]))
        {
            pVertices[i].tangent[0] = 127;
            pVertices[i].tangent[1] = 0;
            pVertices[i].tangent[2] = 0;
        }
        else
        {
            pVertices[i].tangent[0] = FloatToChar(pModelVertices[i].tangent[0]);
            pVertices[i].tangent[1] = FloatToChar(pModelVertices[i].tangent[1]);
            pVertices[i].tangent[2] = FloatToChar(-pModelVertices[i].tangent[2]);
        }

        pVertices[i].normal[3] = 0;
        pVertices[i].tangent[3] = 0;
    }
    fwrite(pVertices, sizeof(XVertex), verticesCount, pOutput);
    free(pVertices);


    //write indicies
    fwrite(model.getIndexBuffer(), sizeof(int), indiciesCount, pOutput);



    //write submeshes
    UINT triCounter = 0;
    for (int i = 0; i < model.getNumberOfMeshes(); i++)
    {
        ModelOBJ::Mesh srcMesh = model.getMesh(i);
        subMesh.indexOffset = srcMesh.startIndex;
        subMesh.triangleCount = srcMesh.triangleCount;
        ZeroMemory(subMesh.materialName, MAT_NAME_MAX_LENGTH);
        strcpy(subMesh.materialName, srcMesh.pMaterial->name.c_str());

        fwrite(&subMesh, sizeof(SubMesh), 1, pOutput);
    }

    //close output file
    fclose(pOutput);


    //generate material files
    int matCount = model.getNumberOfMaterials();
    for (int i = 0; i < matCount; i++)
    {
        const ModelOBJ::Material& mat = model.getMaterial(i);

        char fileName[MAX_PATH];
        ExtractFileDir(pFilePath, fileName);
        strcat(fileName, "..\\Materials\\");
        strcat(fileName, mat.name.c_str());
        strcat(fileName, ".cfg");

        //check if material already exists
        if (FileExists(fileName))
        {
            printf("Material %s already exists. Skipping cfg generation...\n", mat.name.c_str());
            continue;
        }

        FILE* pMatFile = fopen(fileName, "w");
        fprintf(pMatFile, "Layers = \n(\n\t{\n");

        if (mat.colorMapFilename.length())
            fprintf(pMatFile, "\t\tDiffuseTexture = \"%s\"\n", mat.colorMapFilename.c_str());
        if (mat.bumpMapFilename.length())
            fprintf(pMatFile, "\t\tNormalTexture = \"%s\"\n", mat.bumpMapFilename.c_str());


        fprintf(pMatFile, "\t}\n);");
        fclose(pMatFile);
    }
}
Beispiel #12
0
//MODEL - vertex array version
void draw_test_model_Vertex_Arrays()
{
    const ModelOBJ::Mesh *pMesh = 0;
    const ModelOBJ::Material *pMaterial = 0;


    for (int i = 0; i < model.getNumberOfMeshes(); ++i)
    {
        pMesh = &model.getMesh(i);
        pMaterial = pMesh->pMaterial;


        glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, pMaterial->ambient);
        glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pMaterial->diffuse);
        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, pMaterial->specular);
        glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, pMaterial->shininess * 128.0f);

        if (model.hasPositions())
        {
            glEnableClientState(GL_VERTEX_ARRAY);
            glVertexPointer(3, GL_FLOAT, model.getVertexSize(),
                    model.getVertexBuffer()->position);
        }


        if ( model.hasNormals())
        {  
            glEnableClientState(GL_NORMAL_ARRAY);
            glNormalPointer(GL_FLOAT, model.getVertexSize(),
                model.getVertexBuffer()->normal);
        }

        glDrawElements(GL_TRIANGLES, pMesh->triangleCount * 3, GL_UNSIGNED_INT,
            model.getIndexBuffer() + pMesh->startIndex);

        if (model.hasNormals())
            glDisableClientState(GL_NORMAL_ARRAY);

        if (model.hasPositions())
            glDisableClientState(GL_VERTEX_ARRAY);
    }

}