/*========================================================================== * (C) 2005 Universitat Jaume I *========================================================================== * PROYECT: GAME TOOLS *========================================================================== * CONTENT: * * * @file GeoLodStripsLibrary.cpp *===========================================================================*/ #include "GeoLodStripsLibrary.h" using namespace Geometry; //----------------------------------------------------------------------------- // Constructors. //----------------------------------------------------------------------------- LodStripsLibrary::LodStripsLibrary(const LodStripsLibraryData *lodstripsdata, Mesh *geomesh, CREATEINDEXDATAFUNC idfun) :create_index_data_func(idfun?idfun:DefaultIndexDataCreator) { // 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; indices_x_submesh = NULL; offsets_x_submesh = NULL; mStripsSubmesh = NULL; // Loads the Level Of Detail file. LodStripsLibrary::LoadStripMesh(lodstripsdata,mGeoMesh); GoToLod(0.0f); minFaces = 0; for (unsigned int strip = 0; strip < mTotalStrips; strip++) minFaces += int(mStrips[strip].size() - 2); GoToLod(1.0f); maxFaces = 0; for (unsigned int strip = 0; strip < mTotalStrips; strip++) maxFaces += int(mStrips[strip].size() - 2); } //----------------------------------------------------------------------------- // Destroyer. //----------------------------------------------------------------------------- LodStripsLibrary::~LodStripsLibrary() { delete [] mStrips; if (dataRetrievalInterface) delete dataRetrievalInterface; if (indices_x_submesh) delete[] indices_x_submesh; if (offsets_x_submesh) delete[] offsets_x_submesh; if (mStripsSubmesh) delete[] mStripsSubmesh; } //----------------------------------------------------------------------------- // Public. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Go to the level of detail. //----------------------------------------------------------------------------- void LodStripsLibrary::GoToLod(float lodfactor) { 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; uint32 newLOD = (uint32)((1.0f - lodfactor) * mLods); // 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; } //----------------------------------------------------------------------------- // 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;*/ return maxFaces; } //----------------------------------------------------------------------------- // 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;*/ return minFaces; } //----------------------------------------------------------------------------- // 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() { 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()]; unsigned int total_strip_size = 0; for (unsigned int i = 0; i < mFileStrips.size(); i++) { total_strip_size += t = int(mFileStrips[i].size()); if (t>max) max = t; mTotalFaces += t - 2; } changes_array = new LODRegisterType[mFileChangesLOD.size()]; // Fill up changes array. for (unsigned int i = 0; i < mFileChangesLOD.size(); ++i) { changes_array[i] = mFileChangesLOD[i]; } mCurrentRegLOD = changes_array; // Copy strips. unsigned int numDegenerated = 2*mTotalStrips - 2; dataRetrievalInterface=create_index_data_func(total_strip_size+numDegenerated); // temporal! dataRetrievalInterface->Begin(); unsigned int ii = 0; for (unsigned int i = 0; i < mFileStrips.size(); i++) { for (unsigned int j = 0; j < mFileStrips[i].size(); j++,ii++) { mStrips[i].push_back(mFileStrips[i][j]); dataRetrievalInterface->SetIndex(ii,mFileStrips[i][j]); } // Reset flags of strips changed. mStripsChanges[i] = 0; } dataRetrievalInterface->End(); for (unsigned int i = 0; i < mData.size(); i++) { data_array[i] = mData[i]; } mCurrentData = data_array; // Fill up mVertex. for(unsigned int i = 0; i < mFileVertices.size(); i++) { mVertex[i] = mFileVertices[i]; } // delete[] strip_sizes; } //----------------------------------------------------------------------------- // LoadStripMesh //----------------------------------------------------------------------------- void LodStripsLibrary::LoadStripMesh(const LodStripsLibraryData *lodstripsdata, 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. indices_x_submesh = new int[geomesh->mSubMeshCount]; offsets_x_submesh = new int[geomesh->mSubMeshCount]; 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; indices_x_submesh[submesh] = 0; if (submesh==0) offsets_x_submesh[submesh] = 0; else offsets_x_submesh[submesh] = indices_x_submesh[submesh-1]; // For each index of the strip. for (index = indexBegin; index < indexEnd; index++) { mFileStrips[t].push_back(indexBegin[i]); indices_x_submesh[submesh]++; i++; } } } // TODO: LOD file loaded in load file mesh process. // 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);*/ mFileVertices = lodstripsdata->mFileVertices; mFileChangesLOD = lodstripsdata->mFileChangesLOD; mData = lodstripsdata->mData; p_changes = lodstripsdata->p_changes; mStripsSubmesh = new int [geomesh->mSubMeshCount]; for (size_t submesh = 0; submesh < geomesh->mSubMeshCount; submesh++) { mStripsSubmesh[submesh]=0; } // 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) { unsigned int ii = 0; dataRetrievalInterface->Begin(); int counter = 0; int target_submesh = 0; size_t strip_count = 0; for (unsigned int i = 0; i < mTotalStrips; i++, strip_count++) { if (strip_count >= mGeoMesh->mSubMesh[target_submesh].mStripCount) { indices_x_submesh[target_submesh] = counter; if (target_submesh==0) { offsets_x_submesh[target_submesh] = 0; } else { offsets_x_submesh[target_submesh] = indices_x_submesh[target_submesh-1] + offsets_x_submesh[target_submesh-1]; } counter = 0; mStripsSubmesh[target_submesh] = (int)strip_count; strip_count = 0; target_submesh++; } int lastindex = -1; for (SmallIntVector::iterator it=mStrips[i].begin(); it!=mStrips[i].end(); it++, ii++) { /* // repeat the first index of the strip: degenerate if (lastindex==-1) { lastindex=*it; dataRetrievalInterface->SetIndex(ii,*it); counter++; ii++; }*/ lastindex=*it; dataRetrievalInterface->SetIndex(ii,*it); counter++; } /* // last repeat last vertex of the strip: degenerate dataRetrievalInterface->SetIndex(ii,lastindex); counter++; ii++;*/ dataRetrievalInterface->SetNumValidIndices(ii); } if (strip_count >= mGeoMesh->mSubMesh[target_submesh].mStripCount) { indices_x_submesh[target_submesh] = counter; if (target_submesh==0) offsets_x_submesh[target_submesh] = 0; else offsets_x_submesh[target_submesh] = indices_x_submesh[target_submesh-1] + offsets_x_submesh[target_submesh-1]; counter = 0; mStripsSubmesh[target_submesh] = (int)strip_count; strip_count = 0; target_submesh++; } dataRetrievalInterface->End(); }