/*========================================================================== * (C) 2005 Universitat Jaume I *========================================================================== * PROYECT: GAME TOOLS *========================================================================== * CONTENT: * * * @file GeoLodStripsLibrary.cpp *===========================================================================*/ #include "GeoLodStripsLibrary.h" using namespace Geometry; using namespace std; //----------------------------------------------------------------------------- // Constructor. //----------------------------------------------------------------------------- LodStripsLibrary::LodStripsLibrary( const LodStripsLibraryData *lodstripsdata, Mesh *geomesh, IndexData *userindexdata) { // Sets the current lod. mCurrentLod = 0; // Sets the global mesh. mGeoMesh = geomesh; delete_indexdata = false; dataRetrievalInterface = userindexdata; indices_x_submesh = NULL; offsets_x_submesh = NULL; mStripsSubmesh = NULL; submesh_x_strip = NULL; lodFactor = 1.0f; current_triangle_count = 0; // 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); } } //----------------------------------------------------------------------------- // Destructor //----------------------------------------------------------------------------- LodStripsLibrary::~LodStripsLibrary() { delete [] mStrips; if (delete_indexdata) delete dataRetrievalInterface; if (indices_x_submesh) delete[] indices_x_submesh; if (offsets_x_submesh) delete[] offsets_x_submesh; if (mStripsSubmesh) delete[] mStripsSubmesh; if (submesh_x_strip) delete[] submesh_x_strip; } //----------------------------------------------------------------------------- // 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; if (lodfactor<0.0f) lodfactor=0.0f; if (lodfactor>1.0f) lodfactor=1.0f; uint32 newLOD = (uint32)((1.0f - lodfactor) * mLods); lodFactor=lodfactor; if (newLOD != mCurrentLod) { if (newLOD > mCurrentLod) { // Forwards. // Increments LOD (decreases level of detail) for ( lod = mCurrentLod; (lod < newLOD) || ((mCurrentRegLOD->obligatory == 1) && (lod < (mLods - 1))); 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(); int stripsize_ini = strip->size(); // 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++; } // lastLOD = mCurrentRegLOD; mCurrentRegLOD++; mStripsChanges[t] = 1; int stripsize_end = strip->size(); indices_x_submesh[submesh_x_strip[t]] -= (stripsize_ini - stripsize_end); } mCurrentLod = lod + 1; } } // If LOD is less than actual. else { mCurrentRegLOD--; mCurrentData--; // Decrements LOD. for ( lod = mCurrentLod; (lod > newLOD) || ((mCurrentRegLOD->obligatory == 1) && (lod > 0)) || ((mCurrentRegLOD[1].obligatory == 1) && (lod > 0)); lod--) { total_changes = mPChanges[lod - 1]; for (i = 0; i < total_changes; i++) { t = mCurrentRegLOD->strip; strip = &(mStrips[t]); start = mStrips[t].begin(); int stripsize_ini = strip->size(); // 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--; } // lastLOD = mCurrentRegLOD; mCurrentRegLOD--; mStripsChanges[t] = 1; int stripsize_end = strip->size(); indices_x_submesh[submesh_x_strip[t]] += (stripsize_end - stripsize_ini); } // Update LOD. mCurrentLod = lod - 1; // Debug. cout << "Obligatory: " << (int)mCurrentRegLOD->obligatory << endl; } mCurrentData++; mCurrentRegLOD++; } } /* // debug! FILE *f = fopen("lodstrips_lodinfo.txt","wt"); fprintf(f,"mCurrentLOD: %d",mCurrentLod); fprintf(f,"mLods: %d",mLods); for (int i=0; imax) 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,indexdata_user_data); // temporal! // dataRetrievalInterface->Init(total_strip_size); /* dataRetrievalInterface->numinds=total_strip_size; dataRetrievalInterface->numvalidinds=total_strip_size;*/ // 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]; int totaltiras = 0; for (unsigned int submesh = 0; submesh < geomesh->mSubMeshCount; submesh++) for (unsigned int strip = 0; strip < geomesh->mSubMesh[submesh].mStripCount; strip++) totaltiras++; submesh_x_strip = new int[totaltiras]; int istrip = 0; for (unsigned int submesh = 0; submesh < geomesh->mSubMeshCount; submesh++) { geoSubMesh = &geomesh->mSubMesh[submesh]; indices_x_submesh[submesh] = 0; // For each one of the strips. for (unsigned int strip = 0; strip < geoSubMesh->mStripCount; strip++, istrip++) { // Insert an empty strip. submesh_x_strip[istrip] = submesh; 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. (DEG!) 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 (DEG!) indexEnd--; } int i; i = 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) { int target_submesh = 0; size_t strip_count = 0; unsigned int ii_submesh = 0; current_triangle_count = 0; // indices_x_submesh is calculated without degenerates, // we must add the degenerate indices added here uint32 numdeg = mGeoMesh->mSubMesh[target_submesh].mStripCount * 2 - 2; dataRetrievalInterface->Begin(target_submesh, indices_x_submesh[target_submesh] + numdeg); current_triangle_count += indices_x_submesh[target_submesh] + numdeg; // For each strip. for (unsigned int i = 0; i < mTotalStrips; i++, strip_count++) { if (strip_count >= mGeoMesh->mSubMesh[target_submesh].mStripCount) { 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]; } mStripsSubmesh[target_submesh] = (int)strip_count; strip_count = 0; target_submesh++; ii_submesh = 0; dataRetrievalInterface->End(); numdeg = mGeoMesh->mSubMesh[target_submesh].mStripCount*2 - 2; dataRetrievalInterface->Begin(target_submesh, indices_x_submesh[target_submesh] + numdeg); current_triangle_count += indices_x_submesh[target_submesh] + numdeg; } int lastindex = -1; for ( SmallIntVector::iterator it = mStrips[i].begin(); it != mStrips[i].end(); it++, ii_submesh++) { // repeat the first index of the strip: degenerate (DEG!) // except for the first strip in a mesh if ((lastindex == -1) && (strip_count > 0)) { lastindex = *it; dataRetrievalInterface->SetIndex(ii_submesh,*it); ii_submesh++; } lastindex = *it; dataRetrievalInterface->SetIndex(ii_submesh,*it); } // repeat last vertex of the strip: degenerate (DEG!) // except for the last strip in a mesh if (strip_count < mGeoMesh->mSubMesh[target_submesh].mStripCount-1) { dataRetrievalInterface->SetIndex(ii_submesh,lastindex); ii_submesh++; } } if (strip_count >= mGeoMesh->mSubMesh[target_submesh].mStripCount) { 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]; } mStripsSubmesh[target_submesh] = (int)strip_count; strip_count = 0; target_submesh++; } dataRetrievalInterface->End(); }