/* ========================================================================== * (C) 2005 Universitat Jaume I * ========================================================================== * PROYECT: GAME TOOLS * ==========================================================================*/ /** CONTENT: * * * @file GeoLodStripsLibrary.cpp /*===========================================================================*/ #include "GeoLodStripsLibrary.h" using namespace Geometry; //----------------------------------------------------------------------------- // Constructors. //----------------------------------------------------------------------------- LodStripsLibrary::LodStripsLibrary( std::string name, Mesh *geomesh) { const char *name_of_file; // Sets the current lod. mCurrentLod = 0; // Converts a String to const char *. name_of_file = name.data(); // Sets the global mesh. mGeoMesh = geomesh; // Loads the Level Of Detail file. LodStripsLibrary::LoadStripMesh((char*)name_of_file,mGeoMesh); } //----------------------------------------------------------------------------- // Destroyer. //----------------------------------------------------------------------------- LodStripsLibrary::~LodStripsLibrary() { delete[] mStrips; } //----------------------------------------------------------------------------- // Public. //----------------------------------------------------------------------------- /* Go to the level of detail. */ uint32 LodStripsLibrary::GoToLod(uint32 newLOD) { register int j; register int offset; long int i; long int k; long int l; long int b_change_ok = 1; long int lod; long int t; long int p; long int r; long int sig; long int p_end; long int p_init; long int p_end_all; long int el1; long int el2; long int total_changes; long int totalR; int b256; SmallIntVector *strip; SmallIntVector::iterator start; SmallInt *p_data; 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(); // Position. totalR = mCurrentRegLOD->position; for (j = totalR - 1; j >= 0; j--) { 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; mStripsChanges[t] = 1; } 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(); // 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; mStripsChanges[t] = 1; } // Actualizar LOD. mCurrentLod = lod - 1; } ++mCurrentData; ++mCurrentRegLOD; } } /* // Visualizar. k = 0; for (uint32 i = 0; i < mTotalStrips; i++) { l = mStrips[i].size(); // Los dos degenerados. k = k + l + 2; // If is not the first strip. if (i != 0) { start = mStrips[i].begin(); // Degenerado. mStrips[i].insert(start,mStrips[i][0]); } // If is not the last strip. if (i != (mTotalStrips - 1)) { // Degenerado. mStrips[i].push_back(mStrips[i][mStrips[i].size() - 1]); } } */ /* * Write in the hardware buffer. * int contTira = 0; // Vuelca los datos en el buffer de pantalla. //Ogre::HardwareIndexBufferSharedPtr ibuf; for(unsigned int j = 0; j < mGeoMesh->mSubMeshCount; j++) { k = 0; for(unsigned int s = 0; s < mGeoMesh->mSubMesh[j].mStripCount; s++) { l = mStrips[contTira].size(); mIndexBuffer[j]->writeData(k*sizeof(unsigned long), l*sizeof(unsigned long), &mStrips[contTira][0]); k = k + l; contTira++; } indexes[j]->indexCount = k; } */ /* // Para el bunny. start = mStrips[0].begin(); mStrips[0].erase(start); */ /* for (uint32 i = 0; i < mTotalStrips; i++) { start = mStrips[i].begin(); // If is not the first strip. if (i != 0) { mStrips[i].erase(start); } // If is not the last strip. if (i != (mTotalStrips - 1)) { mStrips[i].pop_back(); } } */ return return_value; } /* Gets the maximum level of detail. */ uint32 LodStripsLibrary::MaxLod() { return mMaxLod; } /* Gets the minimum level of detail. */ uint32 LodStripsLibrary::MinLod() { return mMinLod; } /// Returns the number of vertices of the highest LOD. uint32 LodStripsLibrary::MaxVertices() { uint32 number_of_vertices; number_of_vertices = mTotalVertices; return number_of_vertices; } /// Returns the number of vertices of the lowest LOD. uint32 LodStripsLibrary::MinVertices() { uint32 current_lod; 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. uint32 LodStripsLibrary::MaxFaces() { uint32 number_of_faces; 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. uint32 LodStripsLibrary::MinFaces() { uint32 current_lod; 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(uint32 minLod, uint32 maxLod) { mMinLod = minLod; mMaxLod = maxLod; } uint32 LodStripsLibrary::GetStripCount() { return (uint32) mTotalStrips; } //----------------------------------------------------------------------------- // Private. //----------------------------------------------------------------------------- /* Copy a STL vector to a C array. */ void LodStripsLibrary::CopyVectors2Arrays() { int i; int j; int *vertex; int t_actual; SmallInt max; SmallInt t; SmallInt strip; SmallInt *data_array; SmallIntVector tira; LODRegisterType lod_register; LODRegisterType *changes_array; LODRegisterVector list_changes; mTotalStrips = mFileStrips.size(); mVertex = new SmallInt[mTotalVertices]; mStripsChanges = new SmallInt[mTotalChanges]; 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; //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]); } //Poner a 0 los flags de modificados. mStripsChanges[i] = 0; } for (i = 0; i < mData.size(); i++) { data_array[i] = mData[i]; } mCurrentData = data_array; //Meter los vertices en mVertex for(i = 0; i < mFileVertices.size(); i++) { mVertex[i] = mFileVertices[i]; } } //----------------------------------------------------------------------------- // LoadStripMesh //----------------------------------------------------------------------------- void LodStripsLibrary::LoadStripMesh(char *name, Mesh *geomesh) { FILE *fp; VertexType vertex_aux; SmallIntVector strip_aux; LODRegisterType lod_register; std::vector list_pos; std::vector p_changes; int value; int v = 0; int t = -1; int s = 0; int sig = 0; int c = -1; char buff[80]; char *ptr; Index *index; Index *indexBegin; Index *indexEnd; SubMesh *geoSubMesh; // For each one of the submeshes. for (int submesh = 0; submesh < geomesh->mSubMeshCount; submesh++) { geoSubMesh = &geomesh->mSubMesh[submesh]; // For each one of the strips. for (int strip = 0; strip < geoSubMesh->mStripCount; strip++) { // Insert an empty strip. t++; strip_aux.clear(); mFileStrips.push_back(strip_aux); // First index of the strip. indexBegin = geoSubMesh->mStrip[strip]; // If the strips is not the first. if (strip != 0) { indexBegin++; } // If is the final strip if (strip == (geoSubMesh->mStripCount - 1)) { // The end of the index array. indexEnd = &geoSubMesh->mIndex[geoSubMesh->mIndexCount]; } else { // The beginning of the next strip. indexEnd = geoSubMesh->mStrip[strip + 1]; // Remove degenerated indexEnd--; } int i; i = 0; // For each index of the strip. for (index = indexBegin; index < indexEnd; index++) { mFileStrips[t].push_back(indexBegin[i]); i++; } } } // 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); // 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(); } }