void LodInputProviderBuffer::initialize( LodData* data ) { #if OGRE_DEBUG_MODE data->mMeshName = mBuffer.meshName; #endif data->mMeshBoundingSphereRadius = mBuffer.boundingSphereRadius; unsigned short submeshCount = ushort(mBuffer.submesh.size()); for (unsigned short i = 0; i < submeshCount; ++i) { LodInputBuffer::Submesh& submesh = mBuffer.submesh[i]; LodVertexBuffer& vertexBuffer = (submesh.useSharedVertexBuffer ? mBuffer.sharedVertexBuffer : submesh.vertexBuffer); addVertexData(data, vertexBuffer, submesh.useSharedVertexBuffer); addIndexData(data, submesh.indexBuffer, submesh.useSharedVertexBuffer, i); } // These were only needed for addIndexData() and addVertexData(). mSharedVertexLookup.clear(); mVertexLookup.clear(); }
void LodInputProviderMesh::initialize( LodData* data ) { #if OGRE_DEBUG_MODE data->mMeshName = mMesh->getName(); #endif data->mMeshBoundingSphereRadius = mMesh->getBoundingSphereRadius(); unsigned short submeshCount = mMesh->getNumSubMeshes(); for (unsigned short i = 0; i < submeshCount; ++i) { const SubMesh* submesh = mMesh->getSubMesh(i); VertexData* vertexData = (submesh->useSharedVertices ? mMesh->sharedVertexData : submesh->vertexData); addVertexData(data, vertexData, submesh->useSharedVertices); if(submesh->indexData->indexCount > 0) addIndexData(data, submesh->indexData, submesh->useSharedVertices, i); } // These were only needed for addIndexData() and addVertexData(). mSharedVertexLookup.clear(); mVertexLookup.clear(); }
/* Loads a heightmap from a grey scaled image which must have square dimensions. @param the path to the file @return whether the file was correctly loaded or not */ bool Ground::loadHeightMap(string path) { FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; FIBITMAP* dib(0); fif = FreeImage_GetFileType(path.c_str(), 0); if (fif == FIF_UNKNOWN) { fif = FreeImage_GetFIFFromFilename(path.c_str()); } if (fif == FIF_UNKNOWN) { std::cout << "Unknown Filetype\n"; return false; } if (FreeImage_FIFSupportsReading(fif)) { dib = FreeImage_Load(fif, path.c_str()); } if (!dib) { std::cout << "Unable to load height map\n"; return false; } BYTE* dataPointer = FreeImage_GetBits(dib); hmRows = FreeImage_GetHeight(dib); hmCols = FreeImage_GetWidth(dib); // How much to increase data pointer to get to next pixel data unsigned int ptr_inc = FreeImage_GetBPP(dib) == 24 ? 3 : 1; // Length of one row in data unsigned int row_step = ptr_inc * hmCols; glGenBuffers(1, &hmdataVertexBufferID); vector<vector<glm::vec2>> UVcoordinates(hmRows, vector<glm::vec2>(hmCols)); vector<vector<glm::vec3>> vertices(hmRows, vector<glm::vec3>(hmCols)); float textureU = float(hmCols * 0.1); float textureV = float(hmRows * 0.1); // Calculate vertex and texture data from the value of the color in the height map for (int i = 0; i < hmRows; i++) { for (int j = 0; j < hmCols; j++) { float x = float(j) / float(hmCols - 1); float z = float(i) / float(hmRows - 1); float y = float(*(dataPointer + row_step * i + j * ptr_inc)) / 255.f; vertices[i][j] = glm::vec3(-.5 + x, y, -.5 + z); UVcoordinates[i][j] = glm::vec2(textureU * x, textureV * z); scaledHeight.insert(std::pair<std::pair<float, float>, float>(std::pair<float, float>(x, z), y)); } } // Calculate the normals by getting the normals of both triangles in a quad and storing them in a 3 dimensional vector vector<vector<glm::vec3>> triangleNormals[2]; // Every quad has 2 triangles for (int i = 0; i < 2; i++) { triangleNormals[i] = vector<vector<glm::vec3>>(hmRows - 1, vector<glm::vec3>(hmCols - 1)); } // iterate through every quad and calculate the normals for (int i = 0; i < hmRows - 1; i++){ for (int j = 0; j < hmCols - 1; j++) { glm::vec3 triangle0[] = {vertices[i][j], vertices[i+1][j], vertices[i+1][j+1]}; glm::vec3 triangle1[] = {vertices[i+1][j+1], vertices[i][j+1], vertices[i][j]}; glm::vec3 triangle0Norm = glm::cross(triangle0[0] - triangle0[1], triangle0[1] - triangle0[2]); glm::vec3 triangle1Norm = glm::cross(triangle1[0] - triangle1[1], triangle1[1] - triangle1[2]); triangleNormals[0][i][j] = glm::normalize(triangle0Norm); triangleNormals[1][i][j] = glm::normalize(triangle1Norm); } } // Calculate the normal of every vertex by taking the average of each adjacent triangle's normal vector<vector<glm::vec3>> vertexNormals = vector<vector<glm::vec3>>(hmRows, vector<glm::vec3>(hmCols)); for (int i = 0; i < hmRows; i++) { for (int j = 0; j < hmCols; j++) { glm::vec3 norm(0,0,0); if (i != 0 && j != 0) { for(int k = 0; k < 2; k++) { norm += triangleNormals[k][i-1][j-1]; } } if (i != (hmRows - 1) && j != (hmCols - 1)) { for (int k = 0; k < 2; k++) { norm += triangleNormals[k][i][j]; } } if (i != 0 && j != (hmCols - 1)) { norm += triangleNormals[0][i-1][j]; } if (i != (hmRows - 1) && j != 0 ) { norm += triangleNormals[1][i][j-1]; } norm = glm::normalize(norm); vertexNormals[i][j] = norm; } } // Create the buffer for the indexed drawing glGenBuffers(1, &hmdataVertexBufferID); data.reserve(hmRows * hmCols * (2 * sizeof(glm::vec3) + sizeof(glm::vec2))); dataSize = hmRows * hmCols * (2 * sizeof(glm::vec3) + sizeof(glm::vec2)); currentDataSize = 0; glGenBuffers(1, &hmdataVertexBufferID); for (int i = 0; i < hmRows; i++) { for (int j = 0; j < hmCols; j++) { addData(&vertices[i][j], sizeof(glm::vec3)); addData(&UVcoordinates[i][j], sizeof(glm::vec2)); addData(&vertexNormals[i][j], sizeof(glm::vec3)); } } glGenBuffers(1, &indexVertexBufferID); indexSize = 0; currentIndexSize = 0; int restartIndex = hmRows * hmCols; for (int i = 0; i < hmRows - 1; i++) { for (int j = 0; j < hmCols; j++) { for (int k = 0; k < 2; k++) { int row = i + (1 - k); int index = row * hmCols + j; addIndexData(&index, sizeof(int)); } } addIndexData(&restartIndex, sizeof(int)); } glGenVertexArrays(1, &vertexArrayID); glBindVertexArray(vertexArrayID); glBindBuffer(GL_ARRAY_BUFFER, hmdataVertexBufferID); glBufferData(GL_ARRAY_BUFFER, data.size(), &data[0], GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 2*sizeof(glm::vec3)+sizeof(glm::vec2), 0); // Texture coordinates glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2*sizeof(glm::vec3)+sizeof(glm::vec2), (void*)sizeof(glm::vec3)); // Normal vectors glEnableVertexAttribArray(2); glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 2*sizeof(glm::vec3)+sizeof(glm::vec2), (void*)(sizeof(glm::vec3)+sizeof(glm::vec2))); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVertexBufferID); glBufferData(GL_ELEMENT_ARRAY_BUFFER, iData.size(), &iData[0], GL_STATIC_DRAW); return true; }
//--------------------------------------------------------------------- void OptimiseTool::processMesh(Ogre::MeshPtr mesh) { bool rebuildEdgeList = false; // Shared geometry if (mesh->sharedVertexData) { print("Optimising mesh shared vertex data..."); setTargetVertexData(mesh->sharedVertexData); for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) { SubMesh* sm = mesh->getSubMesh(i); if (sm->useSharedVertices) { addIndexData(sm->indexData); } } if (optimiseGeometry()) { if (mesh->getSkeletonName() != StringUtil::BLANK) { print(" fixing bone assignments..."); Mesh::BoneAssignmentIterator currentIt = mesh->getBoneAssignmentIterator(); Mesh::VertexBoneAssignmentList newList = getAdjustedBoneAssignments(currentIt); mesh->clearBoneAssignments(); for (Mesh::VertexBoneAssignmentList::iterator bi = newList.begin(); bi != newList.end(); ++bi) { mesh->addBoneAssignment(bi->second); } } for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) { SubMesh* sm = mesh->getSubMesh(i); if (mesh->getSkeletonName() != StringUtil::BLANK) { print(" fixing bone assignments..."); Mesh::BoneAssignmentIterator currentIt = sm->getBoneAssignmentIterator(); Mesh::VertexBoneAssignmentList newList = getAdjustedBoneAssignments(currentIt); sm->clearBoneAssignments(); for (Mesh::VertexBoneAssignmentList::iterator bi = newList.begin(); bi != newList.end(); ++bi) { sm->addBoneAssignment(bi->second); } } if (sm->useSharedVertices) { fixLOD(sm->mLodFaceList); } } rebuildEdgeList = true; } } // Dedicated geometry for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) { SubMesh* sm = mesh->getSubMesh(i); if (!sm->useSharedVertices) { print("Optimising submesh " + StringConverter::toString(i) + " dedicated vertex data "); setTargetVertexData(sm->vertexData); addIndexData(sm->indexData); if (optimiseGeometry()) { if (mesh->getSkeletonName() != StringUtil::BLANK) { print(" fixing bone assignments..."); Mesh::BoneAssignmentIterator currentIt = sm->getBoneAssignmentIterator(); Mesh::VertexBoneAssignmentList newList = getAdjustedBoneAssignments(currentIt); sm->clearBoneAssignments(); for (Mesh::VertexBoneAssignmentList::iterator bi = newList.begin(); bi != newList.end(); ++bi) { sm->addBoneAssignment(bi->second); } } fixLOD(sm->mLodFaceList); rebuildEdgeList = true; } } } if (rebuildEdgeList && mesh->isEdgeListBuilt()) { // force rebuild of edge list mesh->freeEdgeList(); mesh->buildEdgeList(); } }