/* ========================================================================== * (C) 2006 Universitat Jaume I * ========================================================================== * PROYECT: GAME TOOLS * ==========================================================================*/ /** CONTENT: * * * @file OgreLodStripsLibrary.cpp /*===========================================================================*/ #include "OgreLodStripsLibrary.h" //----------------------------------------------------------------------------- // Constructors. //----------------------------------------------------------------------------- LodStripsLibrary::LodStripsLibrary( std::string name, Ogre::Mesh *geomesh) { const char *name_of_file; mMaxLod=0; mMinLod=0; // Sets the current lod. mCurrentLod = 0; // Converts a String to const char *. name_of_file = name.data(); original_mesh=geomesh; // Loads the Level Of Detail file. LodStripsLibrary::LoadStripMesh((char*)name_of_file,geomesh); } //----------------------------------------------------------------------------- // Destroyer. //----------------------------------------------------------------------------- LodStripsLibrary::~LodStripsLibrary() { delete [] mPChanges; if (mMaxLod>0) delete [] mStrips; delete [] mVertex; delete [] mStripsSubmesh; delete [] mRegLODBegin; delete [] mDataBegin; } //----------------------------------------------------------------------------- // Public. //----------------------------------------------------------------------------- /* Go to the level of detail. */ Ogre::uint32 LodStripsLibrary::GoToLod(Ogre::uint32 newLOD) { register int j; register int offset; unsigned int i; long int k; long int l; unsigned int lod; long int t; long int r; long int sig; long int el1; long int el2; long int total_changes; long int totalR; SmallIntVector *strip; SmallIntVector::iterator start; Ogre::uint32 return_value; // Initialize the return value to the current LOD. return_value = mCurrentLod; if (newLOD != mCurrentLod) { if (newLOD > mCurrentLod) { //HACIA ADELANTE //CurrentRegLOD //Incrementamos el LOD -> Calcular siguientes for (lod = mCurrentLod; lod < newLOD; lod++) { sig = mVertex[lod]; total_changes = mPChanges[lod]; for (i = 0; i < total_changes; i++) { // Strip q Cambia. t = mCurrentRegLOD->strip; strip = &(mStrips[t]); //start = strip->begin(); start=(mStrips+t)->begin(); // Position. totalR = mCurrentRegLOD->position; for (j = totalR - 1; j >= 0; j--) { //start[*mCurrentData] = sig; *(start+*mCurrentData)=sig; ++mCurrentData; } // L1. totalR = mCurrentRegLOD->vertexRepetition; for (j = totalR - 1; j >= 0; j--) { offset = *mCurrentData + 1; strip->erase( start + offset, start + offset + (*(mCurrentData + 1))); ++mCurrentData; ++mCurrentData; } // L2 totalR = mCurrentRegLOD->edgeRepetition; for (j = totalR - 1; j >= 0; j--) { offset = *mCurrentData + 2; strip->erase( start + offset, start + offset + 2*(*(mCurrentData + 1))); ++mCurrentData; ++mCurrentData; } ++mCurrentRegLOD; } mCurrentLod = lod + 1; } } // Si el nuevo LOD es menos que el actual. else { --mCurrentRegLOD; --mCurrentData; // Decrementamos el LOD -> Calcular anteriores. for (lod = mCurrentLod; lod > newLOD; lod--) { total_changes = mPChanges[lod - 1]; for (i = 0; i < total_changes; i++) { t = mCurrentRegLOD->strip; strip = &(mStrips[t]); //start = mStrips[t].begin(); start=(mStrips+t)->begin(); // L2. totalR = mCurrentRegLOD->edgeRepetition; for (j = 0; j < totalR; j++) { el1 = (*strip)[*(mCurrentData - 1)]; el2 = (*strip)[*(mCurrentData - 1) + 1]; r = *(mCurrentData); for (k = 0; k < r; k++) { (*strip).insert(start+*(mCurrentData - 1),el2); (*strip).insert(start+*(mCurrentData - 1),el1); } --mCurrentData; --mCurrentData; } // Vertex Repetition. totalR = mCurrentRegLOD->vertexRepetition; for (j = 0; j < totalR; j++) { el1 = (*strip)[*(mCurrentData-1)]; r = *(mCurrentData); for (k = 0; k < r; k++) { (*strip).insert(start+*(mCurrentData-1),el1); } --mCurrentData; --mCurrentData; } // POS. totalR = mCurrentRegLOD->position; for (j = 0; j < totalR; j++) { (*strip)[*mCurrentData] = lod - 1; --mCurrentData; } --mCurrentRegLOD; } // Actualizar LOD. mCurrentLod = lod - 1; } ++mCurrentData; ++mCurrentRegLOD; } } // Copy to Ogre buffers including the degenerated triangles for (i = 0; i < GetStripCount(); i++) { start = mStrips[i].begin(); mStrips[i].insert(start,mStrips[i][0]); mStrips[i].push_back(mStrips[i][mStrips[i].size()-1]); } Ogre::HardwareIndexBufferSharedPtr ibuf; Ogre::IndexData *indexes; Ogre::RenderOperation mRenderOp; j=0; for (int submesh=0; submesh < original_mesh->getNumSubMeshes(); submesh++) { k=0; for (i = 0; i < mStripsSubmesh[submesh]; i++) k+=mStrips[j+i].size(); original_mesh->getSubMesh(submesh)->_getRenderOperation(mRenderOp,0); ibuf = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( Ogre::HardwareIndexBuffer::IT_32BIT, // type of index k, // number of indexes Ogre::HardwareBuffer::HBU_DISCARDABLE , // usage false); // no shadow buffer mRenderOp.indexData->indexBuffer = ibuf; mRenderOp.indexData->indexStart = 0; mRenderOp.indexData->indexCount = k; k=0; unsigned long* pIdx = static_cast(ibuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); for (i = 0; i < mStripsSubmesh[submesh]; i++) { for (l=0;lunlock(); } //Erase the degenerated triangles for (i = 0; i < GetStripCount(); i++) { start = mStrips[i].begin(); mStrips[i].erase(start); mStrips[i].pop_back(); } return return_value; } /* Gets the maximum level of detail. */ Ogre::uint32 LodStripsLibrary::MaxLod() { return mMaxLod; } /* Gets the minimum level of detail. */ Ogre::uint32 LodStripsLibrary::MinLod() { return mMinLod; } /// Returns the number of vertices of the highest LOD. Ogre::uint32 LodStripsLibrary::MaxVertices() { Ogre::uint32 number_of_vertices; number_of_vertices = mTotalVertices; return number_of_vertices; } /// Returns the number of vertices of the lowest LOD. Ogre::uint32 LodStripsLibrary::MinVertices() { Ogre::uint32 number_of_vertices; // Total vertices less total lod. number_of_vertices = mTotalVertices - (mMaxLod + 1); return number_of_vertices; } /// Returns the number of triangles of the highest LOD. Ogre::uint32 LodStripsLibrary::MaxFaces() { Ogre::uint32 number_of_faces; Ogre::uint32 current_lod; current_lod = GoToLod(MaxLod()); // Initialize number of faces count. number_of_faces = 0; // For each strip. for (int strip = 0; strip < mTotalStrips; strip++) { number_of_faces += mStrips[strip].size() - 2; } GoToLod(current_lod); return number_of_faces; } /// Returns the number of triangles of the lowest LOD. Ogre::uint32 LodStripsLibrary::MinFaces() { Ogre::uint32 current_lod; Ogre::uint32 number_of_faces; current_lod = GoToLod(MinLod()); // Initialize number of faces count. number_of_faces = 0; // For each strip. for (int strip = 0; strip < mTotalStrips; strip++) { number_of_faces += mStrips[strip].size() - 2; } GoToLod(current_lod); return number_of_faces; } /// Establishes the new LOD range. /// Only the LODs in that range are stored and used. void LodStripsLibrary::TrimByLod(Ogre::uint32 minLod, Ogre::uint32 maxLod) { mMinLod = minLod; mMaxLod = maxLod; } Ogre::uint32 LodStripsLibrary::GetStripCount() const { return (Ogre::uint32) mTotalStrips; } Ogre::uint32 LodStripsLibrary::GetIndexCountByStrip(Ogre::uint32 istrip) const { return (Ogre::uint32) mStrips[istrip].size(); } //----------------------------------------------------------------------------- // Private. //----------------------------------------------------------------------------- /* Copy a STL vector to a C array. */ void LodStripsLibrary::CopyVectors2Arrays() { unsigned int i; int j; SmallInt max; SmallInt t; SmallInt *data_array; SmallIntVector tira; LODRegisterType *changes_array; LODRegisterVector list_changes; mTotalStrips = mFileStrips.size(); mVertex = new SmallInt[mTotalVertices]; mStrips = new SmallIntVector[mTotalStrips]; data_array = new SmallInt[mData.size()]; //Calcular el tamaņo maximo de tira y el numero de caras total max = 0; mTotalFaces = 0; for (i = 0; i < mFileStrips.size(); i++) { t = mFileStrips[i].size(); if (t>max) { max = t; } mTotalFaces += t - 2; } //Nueva version de ALLOCATE. changes_array = new LODRegisterType[mFileChangesLOD.size()]; //Rellenar vChanges for (i = 0; i < mFileChangesLOD.size(); ++i) { changes_array[i] = mFileChangesLOD[i]; } mCurrentRegLOD = changes_array; mRegLODBegin = changes_array; //COPY---------------------------------- //Copiar las tiras for (i = 0; i < mFileStrips.size(); i++) { for (j = 0; j < mFileStrips[i].size(); j++) { //Rellenar el vVector mStrips[i].push_back(mFileStrips[i][j]); } } for (i = 0; i < mData.size(); i++) { data_array[i] = mData[i]; } mCurrentData = data_array; mDataBegin = data_array; //Meter los vertices en mVertex for(i = 0; i < mFileVertices.size(); i++) { mVertex[i] = mFileVertices[i]; } mFileVertices.clear(); mFileVertices.clear(); mFileChangesLOD.clear(); mFileStrips.clear(); mData.clear(); } //----------------------------------------------------------------------------- // LoadStripMesh //----------------------------------------------------------------------------- void LodStripsLibrary::LoadStripMesh(char *name, Ogre::Mesh *geomesh) { FILE *fp; SmallIntVector strip_aux; LODRegisterType lod_register; std::vector list_pos; std::vector p_changes; int value; int v = 0; int t = 0; int c = -1; char buff[80]; Ogre::SubMesh *geoSubMesh; int count=0; int num_strips=0; // Open the LOD file. if ((fp = fopen (name, "r")) == NULL) { // Error in open. } else { mTotalChanges = 0; while (!feof (fp)) { fgets (buff, 80, fp); if (*buff == 'v') { //VERTICES sscanf (buff+2,"%d",&value); mFileVertices.push_back(value); v++; } else if ( (*buff == 'c') || (*buff == 'd')) { if (*buff == 'c') { // c indica que empieza un nuevo cambio c++; } else { unsigned int a; unsigned int b; unsigned int c; unsigned int d; sscanf (buff+2,"%u %u %u %u\n",&a,&b,&c,&d); lod_register.strip = a; lod_register.position = b; lod_register.vertexRepetition = c; lod_register.edgeRepetition = d; mFileChangesLOD.push_back(lod_register); } } else if (*buff=='b') { sscanf(buff+2,"%u",&value); mData.push_back(value); } else if (*buff=='p') { sscanf (buff+2,"%u",&value); p_changes.push_back(value); }//Fin ElseIf } // End WhileEOF fclose(fp); mStripsSubmesh= new int [geomesh->getNumSubMeshes()]; // For each one of the submeshes. for (int submesh = 0; submesh < geomesh->getNumSubMeshes(); submesh++) { geoSubMesh = geomesh->getSubMesh(submesh); count=0; num_strips=0; Ogre::HardwareIndexBufferSharedPtr ibuf = geoSubMesh->indexData->indexBuffer; if (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT) { unsigned int* pIndexes = static_cast (ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY) ); //We must be carefull with the degenerated triangles while (count<(geoSubMesh->indexData->indexCount-1)) { // Insert an empty strip. strip_aux.clear(); mFileStrips.push_back(strip_aux); mFileStrips[t].push_back(pIndexes[count++]); while ((count<(geoSubMesh->indexData->indexCount-1))&&(pIndexes[count]!=pIndexes[count+1])) { mFileStrips[t].push_back(pIndexes[count++]); } mFileStrips[t].push_back(pIndexes[count]); //For the degenerated triangles count+=3; char linea[256]; sprintf(linea,"%d %d (%d) %d %d %d %d",pIndexes[count-2],pIndexes[count-1],pIndexes[count],pIndexes[count+1],pIndexes[count+2],pIndexes[count+3],pIndexes[count+4]); t++; num_strips++; } } else { unsigned short* pIndexes = static_cast (ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY) ); while (countindexData->indexCount) { // Insert an empty strip. strip_aux.clear(); mFileStrips.push_back(strip_aux); mFileStrips[t].push_back(pIndexes[count++]); while ((count<(geoSubMesh->indexData->indexCount-1))&&(pIndexes[count]!=pIndexes[count+1])) { mFileStrips[t].push_back(pIndexes[count++]); } mFileStrips[t].push_back(pIndexes[count]); //For the degenerated triangles count+=3; char linea[256]; sprintf(linea,"%d %d (%d) %d %d %d %d",pIndexes[count-2],pIndexes[count-1],pIndexes[count],pIndexes[count+1],pIndexes[count+2],pIndexes[count+3],pIndexes[count+4]); t++; num_strips++; } } ibuf->unlock(); mStripsSubmesh[submesh]=num_strips; } // Max / Min values for LOD. mLods = p_changes.size(); mMinLod = 0; mMaxLod = mLods; //// CHAPUZA PROVISIONAL: EL ULTIMO ELEMENTO SE REPITE 2 VECES V.v mPChanges = new SmallInt[mLods]; for (unsigned int i = 0; i < mLods; i++) { mPChanges[i] = p_changes[i]; } mTotalVertices = mFileVertices.size(); mTotalStrips = mFileStrips.size(); mTotalChanges = mFileChangesLOD.size(); //Copy the data to the structure we will use CopyVectors2Arrays(); } }