/*========================================================================== * (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, CREATEMULTIINDEXDATAFUNC midfun) :create_multi_index_data_func(midfun?midfun:DefaultMultiIndexDataCreator) { 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; dataRetrievalInterface=NULL; // Loads the Level Of Detail file. LodStripsLibrary::LoadStripMesh((char*)name_of_file,mGeoMesh); } //----------------------------------------------------------------------------- // Destroyer. //----------------------------------------------------------------------------- LodStripsLibrary::~LodStripsLibrary() { delete [] mStrips; if (dataRetrievalInterface) delete dataRetrievalInterface; } //----------------------------------------------------------------------------- // 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 b_change_ok = 1; unsigned long int lod; long int t; long int r; long int next; long int el1; long int el2; long int total_changes; long int totalR; SmallIntVector *strip; SmallIntVector::iterator start; uint32 return_value; // Initialize the return value to the current LOD. return_value = mCurrentLod; if (newLOD != mCurrentLod) { if (newLOD > mCurrentLod) { // Forwards. // Increments LOD. for (lod = mCurrentLod; lod < newLOD; lod++) { next = mVertex[lod]; total_changes = mPChanges[lod]; for (i = 0; i < total_changes; i++) { // Strip change. t = mCurrentRegLOD->strip; strip = &(mStrips[t]); start = strip->begin(); // Position. totalR = mCurrentRegLOD->position; for (j = totalR - 1; j >= 0; j--) { start[*mCurrentData] = next; ++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; } } // If LOD is less than actual. else { mCurrentRegLOD--; mCurrentData--; // Decrements LOD. 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; } // Update LOD. mCurrentLod = lod - 1; } mCurrentData++; mCurrentRegLOD++; } } UpdateDataRetrievalInterface(); 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() { return mMaxVerticesLOD; } //----------------------------------------------------------------------------- // Returns the number of vertices of the lowest LOD. //----------------------------------------------------------------------------- uint32 LodStripsLibrary::MinVertices() { uint32 number_of_vertices; // Total vertices of minimum lod. number_of_vertices = mMaxVerticesLOD - (mMinLod + 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 (unsigned int strip = 0; strip < mTotalStrips; strip++) { number_of_faces += int(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 (unsigned int strip = 0; strip < mTotalStrips; strip++) { number_of_faces += int(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) { // Refresh number of vercies of the max lod. mMaxVerticesLOD += mMaxLod - maxLod; mMinLod = minLod; mMaxLod = maxLod; } /* //----------------------------------------------------------------------------- // Get strip count. //----------------------------------------------------------------------------- uint32 LodStripsLibrary::GetStripCount() const { return (uint32) mTotalStrips; } //----------------------------------------------------------------------------- // Get Index by strip. //----------------------------------------------------------------------------- uint32 LodStripsLibrary::GetIndexCountByStrip(uint32 istrip) const { return (uint32) mStrips[istrip].size(); } */ //----------------------------------------------------------------------------- // Private. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Copy a STL vector to a C array. //----------------------------------------------------------------------------- void LodStripsLibrary::CopyVectors2Arrays() { unsigned int i; unsigned int j; SmallInt max; SmallInt t; SmallInt *data_array; SmallIntVector tira; LODRegisterType *changes_array; LODRegisterVector list_changes; mTotalStrips = int(mFileStrips.size()); mVertex = new SmallInt[mTotalVertices]; mStripsChanges = new SmallInt[mTotalChanges]; mStrips = new SmallIntVector[mTotalStrips]; data_array = new SmallInt[mData.size()]; max = 0; mTotalFaces = 0; unsigned int * strip_sizes = new unsigned int[mFileStrips.size()]; for (i = 0; i < mFileStrips.size(); i++) { strip_sizes[i] = t = int(mFileStrips[i].size()); if (t>max) max = t; mTotalFaces += t - 2; } changes_array = new LODRegisterType[mFileChangesLOD.size()]; // Fill up changes array. for (i = 0; i < mFileChangesLOD.size(); ++i) { changes_array[i] = mFileChangesLOD[i]; } mCurrentRegLOD = changes_array; // Copy strips. dataRetrievalInterface=create_multi_index_data_func(mFileStrips.size(),strip_sizes); dataRetrievalInterface->Begin(); for (i = 0; i < mFileStrips.size(); i++) { for (j = 0; j < mFileStrips[i].size(); j++) { mStrips[i].push_back(mFileStrips[i][j]); dataRetrievalInterface->SetIndex(i,j,mFileStrips[i][j]); } // Reset flags of strips changed. mStripsChanges[i] = 0; } dataRetrievalInterface->End(); for (i = 0; i < mData.size(); i++) { data_array[i] = mData[i]; } mCurrentData = data_array; // Fill up mVertex. for(i = 0; i < mFileVertices.size(); i++) { mVertex[i] = mFileVertices[i]; } delete[] strip_sizes; } //----------------------------------------------------------------------------- // LoadStripMesh //----------------------------------------------------------------------------- void LodStripsLibrary::LoadStripMesh(char *name, 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 = -1; int s = 0; int next = 0; int c = -1; char buff[80]; Index *index; Index *indexBegin; Index *indexEnd; SubMesh *geoSubMesh; // For each one of the submeshes. for (unsigned int submesh = 0; submesh < geomesh->mSubMeshCount; submesh++) { geoSubMesh = &geomesh->mSubMesh[submesh]; // For each one of the strips. for (unsigned 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') { sscanf (buff+2,"%d",&value); mFileVertices.push_back(value); v++; } else if ( (*buff == 'c') || (*buff == 'd')) { if (*buff == 'c') { 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); } } fclose(fp); // Max / Min values for LOD. mLods = int(p_changes.size()); mMaxLod = 0; mMinLod = mLods; mPChanges = new SmallInt[mLods]; for (unsigned int i = 0; i < mLods; i++) { mPChanges[i] = p_changes[i]; } mTotalVertices = int(mFileVertices.size()); mMaxVerticesLOD = mTotalVertices; mTotalStrips = int(mFileStrips.size()); mTotalChanges = int(mFileChangesLOD.size()); //Copy the data to the structure we will use CopyVectors2Arrays(); } } void LodStripsLibrary::UpdateDataRetrievalInterface(void) { dataRetrievalInterface->Begin(); for (int i=0; iSetIndex(i,j,*it); dataRetrievalInterface->SetNumValidIndices(i,j); } dataRetrievalInterface->End(); }