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; }
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 ); } }
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); }
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; }
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); }
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; } }
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); } }
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); } }
//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); } }