// TODO: All of these Get() functions look very similar. // Keep them all for their interface, but have them call a common function //----------------------------------------------------------------------------- CPUTMaterial *CPUTAssetLibrary::GetMaterial(const cString &name, bool nameIsFullPathAndFilename, const cString &modelSuffix, const cString &meshSuffix) { // Resolve name to absolute path before searching CPUTOSServices *pServices = CPUTOSServices::GetOSServices(); cString absolutePathAndFilename; pServices->ResolveAbsolutePathAndFilename( nameIsFullPathAndFilename? name : (mMaterialDirectoryName + name + _L(".mtl")), &absolutePathAndFilename); // If we already have one by this name, then return it CPUTMaterial *pMaterial = FindMaterial(absolutePathAndFilename, true); if(NULL==pMaterial) { // We don't already have it in the library, so create it. pMaterial = CPUTMaterial::CreateMaterial( absolutePathAndFilename, modelSuffix, meshSuffix ); return pMaterial; } else if( (0==modelSuffix.length()) && !pMaterial->MaterialRequiresPerModelPayload() ) { // This material doesn't have per-model elements, so we don't need to clone it. pMaterial->AddRef(); return pMaterial; } #ifdef _DEBUG // We need to clone the material. Do that by loading it again, but with a different name. // Add the model's suffix (address as string, plus model's material array index as string) CPUTMaterial *pUniqueMaterial = FindMaterial(absolutePathAndFilename + modelSuffix + meshSuffix, true); ASSERT( NULL == pUniqueMaterial, _L("Unique material already not unique: ") + absolutePathAndFilename + modelSuffix + meshSuffix ); #endif CPUTMaterial *pClonedMaterial = pMaterial->CloneMaterial( absolutePathAndFilename, modelSuffix, meshSuffix ); AddMaterial( absolutePathAndFilename + modelSuffix + meshSuffix, pClonedMaterial ); return pClonedMaterial; }
void L3DS::ReadFaceList(const LChunk &chunk, LMesh &mesh) { // variables unsigned short count, t; uint i; LTri tri; LChunk ch; char str[20]; //uint mat; // consistency checks if (chunk.id != TRI_FACELIST) { ErrorMsg("L3DS::ReadFaceList - internal error: wrong chunk passed as parameter"); return; } GotoChunk(chunk); tri.smoothingGroups = 1; // read the number of faces count = ReadShort(); mesh.SetTriangleArraySize(count); for (i=0; i<count; i++) { tri.a = ReadShort(); tri.b = ReadShort(); tri.c = ReadShort(); ReadShort(); mesh.SetTri(tri, i); } // now read the optional chunks ch = ReadChunk(); int mat_id; while (ch.end <= chunk.end) { switch (ch.id) { case TRI_MAT_GROUP: ReadASCIIZ(str, 20); mat_id=0; if (FindMaterial(str)!=NULL) mat_id = FindMaterial(str)->GetID(); mesh.AddMaterial(mat_id); count = ReadShort(); for (i=0; i<count; i++) { t = ReadShort(); mesh.GetTri(t).materialId = mat_id; } break; case TRI_SMOOTH_GROUP: for (i=0; i<mesh.GetTriangleCount(); i++) mesh.GetTri(i).smoothingGroups = (ulong) ReadInt(); break; } SkipChunk(ch); ch = ReadChunk(); } }
void DiscoverMacroTextures() { CUtlDict<int,int> tempDict; g_FaceMacroTextureInfos.SetSize( numfaces ); for ( int iFace=0; iFace < numfaces; iFace++ ) { texinfo_t *pTexInfo = &texinfo[dfaces[iFace].texinfo]; if ( pTexInfo->texdata < 0 ) continue; dtexdata_t *pTexData = &dtexdata[pTexInfo->texdata]; const char *pMaterialName = &g_TexDataStringData[ g_TexDataStringTable[pTexData->nameStringTableID] ]; MaterialSystemMaterial_t hMaterial = FindMaterial( pMaterialName, NULL, false ); const char *pMacroTextureName = GetMaterialVar( hMaterial, "$macro_texture" ); if ( pMacroTextureName ) { if ( tempDict.Find( pMacroTextureName ) == tempDict.InvalidIndex() ) { Msg( "-- DiscoverMacroTextures: %s\n", pMacroTextureName ); tempDict.Insert( pMacroTextureName, 0 ); } int stringID = TexDataStringTable_AddOrFindString( pMacroTextureName ); g_FaceMacroTextureInfos[iFace].m_MacroTextureNameID = (unsigned short)stringID; } else { g_FaceMacroTextureInfos[iFace].m_MacroTextureNameID = 0xFFFF; } } }
//! gets a material using creation info. Attempts to match with an existing instance. Material* MaterialProvider::GetMaterial(const Material::CreationInfo& info) { if (auto material = FindMaterial(info)) return material; else return CreateMaterial(info); }
const char *GetShaderNameForTexInfo( int iTexInfo ) { texinfo_t *pTexInfo = &texinfo[iTexInfo]; dtexdata_t *pTexData = GetTexData( pTexInfo->texdata ); const char *pMaterialName = TexDataStringTable_GetString( pTexData->nameStringTableID ); MaterialSystemMaterial_t hMaterial = FindMaterial( pMaterialName, NULL, false ); const char *pShaderName = GetMaterialShaderName( hMaterial ); return pShaderName; }
bool ExportScene::AddMaterial( ExportMaterial* pMaterial ) { if( !pMaterial ) return false; if( FindMaterial( pMaterial->GetDCCObject() ) ) return false; m_vMaterials.push_back( pMaterial ); return true; }
int DetailList::FindMaterial( int face, mesh3ds *mesh, Int32 detailIndex ) { // finds the name of the material used by the face // then finds the index of that material in our material list // If the face is not associated with any material, it uses // the default material. So we just return 0. for( int i = 0; i < mesh->nmats; i++ ) { for( int j = 0; j < mesh->matarray[i].nfaces; j++ ) if( mesh->matarray[i].faceindex[j] == face ) { char n[18]; n[0] = detailIndex + 1; strcpy( n+1, mesh->matarray[i].name ); return FindMaterial( n ); } } // face uses default material, so we will use material 0 return 0; }
// TODO: All of these Get() functions look very similar. // Keep them all for their interface, but have them call a common function //----------------------------------------------------------------------------- CPUTMaterial *CPUTAssetLibrary::GetMaterial( const std::string &name, bool nameIsFullPathAndFilename ){ // Resolve name to absolute path before searching std::string absolutePathAndFilename; if (name[0] == '%') { absolutePathAndFilename = mSystemDirectoryName + "Material/" + name.substr(1) + ".mtl"; // TODO: Instead of having the Material/directory hardcoded here it could be set like the normal material directory. But then there would need to be a bunch new variables like SetSystemMaterialDirectory CPUTFileSystem::ResolveAbsolutePathAndFilename(absolutePathAndFilename, &absolutePathAndFilename); } else if( !nameIsFullPathAndFilename ) { CPUTFileSystem::ResolveAbsolutePathAndFilename( mMaterialDirectoryName + name + ".mtl", &absolutePathAndFilename); } else { absolutePathAndFilename = name; } CPUTMaterial *pMaterial = NULL; pMaterial = FindMaterial(absolutePathAndFilename, true); if( pMaterial ) { pMaterial->AddRef(); } else { pMaterial = CPUTMaterial::Create(absolutePathAndFilename); LIBRARY_ASSERT(pMaterial, "Failed creating material Effect."); if (pMaterial != NULL) { AddMaterial(absolutePathAndFilename, "", "", pMaterial); } } return pMaterial; }
//----------------------------------------------------------------------------- // Purpose: Factory. Creates a material by name, first looking in the cache. // Input : pszMaterialName - Name of material, ie "brick/brickfloor01". // Output : Returns a pointer to the new material object, NULL if the given // material did not exist. //----------------------------------------------------------------------------- CMaterial *CMaterialCache::CreateMaterial(const char *pszMaterialName) { CMaterial *pMaterial = NULL; if (pszMaterialName != NULL) { // // Find this material in the cache. If it is here, return it. // pMaterial = FindMaterial(pszMaterialName); if (pMaterial == NULL) { // // Not found in the cache, try to create it. // pMaterial = CMaterial::CreateMaterial(pszMaterialName, true); if (pMaterial != NULL) { // // Success. Add the newly created material to the cache. // AddMaterial(pMaterial); return(pMaterial); } } else { // // Found in the cache, bump the reference count. // AddRef(pMaterial); } } return(pMaterial); }
tstring AppSettings::FindMaterial(const tstring& fname) const { TCHAR buffer[MAX_PATH]; // Simply check for fully qualified path if (!PathIsRelative(fname.c_str())) { if (-1 != _taccess(fname.c_str(), 0)) return fname; } // Test if its relative and in one of the specified root paths for (tstringlist::const_iterator itr = materialRootPaths.begin(), end = materialRootPaths.end(); itr != end; ++itr) { PathCombine(buffer, itr->c_str(), fname.c_str()); if (-1 != _taccess(buffer, 0)) { return tstring(buffer); } } for (LPCTSTR filepart = PathFindNextComponent(fname.c_str()); filepart != nullptr; filepart = PathFindNextComponent(filepart)) { if (wildmatch(TEXT("materials\\*"), filepart)) { return FindMaterial(fname); } } return fname; }
MaterialSystemMaterial_t FindOriginalMaterial( const char *materialName, bool *pFound, bool bComplain ) { MaterialSystemMaterial_t matID; matID = FindMaterial( GetOriginalMaterialNameForPatchedMaterial( materialName ), pFound, bComplain ); return matID; }
void sXSILoader::ScanMesh(sInt indent,sXSIModel *model) { sChar buffer[256]; sChar chunk[XSISIZE]; sChar name[XSISIZE]; sChar *cmd; sInt supports,i,j,k,max; sInt fcount; sInt vcount; sXSICluster *cluster; sInt cr,cg,cb,ca; sInt set,set2; sInt PosCount; sVector *Pos; sInt NormCount; sVector *Norm; sInt ColorCount; sU32 *Color; sInt UVCount[sXSI_MAXUV]; sF32 *UV[sXSI_MAXUV]; sChar UVName[sXSI_MAXUV][XSISIZE]; // init shape holder PosCount = 0; Pos = 0; NormCount = 0; Norm = 0; ColorCount = 0; Color = 0; for(i=0;i<sXSI_MAXUV;i++) { UVCount[i] = 0; UV[i] = 0; } while(*Scan!=0 && *Scan!='}' && !Error) { ScanChunk(indent,chunk,name); if(sCmpString(chunk,"SI_Shape")==0) { supports = ScanInt(); ScanString(buffer,sizeof(buffer)); if(sCmpString(buffer,"ORDERED")!=0) Error = sTRUE; for(i=0;i<supports && !Error;i++) { max = ScanInt(); ScanString(buffer,sizeof(buffer)); if(sCmpString(buffer,"POSITION")==0) { sVERIFY(Pos==0); PosCount = max; Pos = new sVector[max]; for(j=0;j<max;j++) { Pos[j].x = ScanFloat(); Pos[j].y = ScanFloat(); Pos[j].z = ScanFloat(); } } else if(sCmpString(buffer,"NORMAL")==0) { sVERIFY(Norm==0); NormCount = max; Norm = new sVector[max]; for(j=0;j<max;j++) { Norm[j].x = ScanFloat(); Norm[j].y = ScanFloat(); Norm[j].z = ScanFloat(); } } else if(sCmpString(buffer,"COLOR")==0) { sVERIFY(Color==0); ColorCount = max; Color = new sU32[max]; for(j=0;j<max;j++) { cr = sRange<sInt>(ScanFloat()*255,255,0); cg = sRange<sInt>(ScanFloat()*255,255,0); cb = sRange<sInt>(ScanFloat()*255,255,0); ca = sRange<sInt>(ScanFloat()*256,255,0); Color[j] = (ca<<24)|(cb<<16)|(cg<<8)|(cr); } } else if(sCmpString(buffer,"TEX_COORD_UV")==0) { set = 0; sVERIFY(UV[set]==0); UVCount[set] = max; UV[set] = new sF32[max*2]; for(j=0;j<max;j++) { UV[set][j*2+0] = ScanFloat(); UV[set][j*2+1] = 1.0f-ScanFloat(); } } else if(sCmpMem(buffer,"TEX_COORD_UV",12)==0) { j=12; set = 0; while(buffer[j]>='0' && buffer[j]<='9') set = set*10 + (buffer[j++]-'0'); sVERIFY(set>=0 && set<sXSI_MAXUV); sVERIFY(UV[set]==0); ScanString(UVName[set],sizeof(UVName[set])); UVCount[set] = max; UV[set] = new sF32[max*2]; for(j=0;j<max;j++) { UV[set][j*2+0] = ScanFloat(); UV[set][j*2+1] = 1.0f-ScanFloat(); } } else { Error = sTRUE; } } EndChunk(); } else if(sCmpString(chunk,"SI_PolygonList")==0) { cluster = new sXSICluster; fcount = ScanInt(); sCopyString(buffer,"|POSITION|",sizeof(buffer)); i = sGetStringLen(buffer); ScanString(buffer+i,sizeof(buffer)-i); #if DUMPCHUNK sDPrintF(" %s",buffer); #endif ScanString(name,sizeof(name)); cluster->Material = FindMaterial(name); vcount = ScanInt(); cluster->VertexCount = vcount; cluster->IndexCount = vcount; cluster->Vertices = new sXSIVertex[vcount]; cluster->Faces = new sInt[vcount*2]; model->Clusters->Add(cluster); j = 0; for(i=0;i<fcount;i++) { max = ScanInt(); cluster->Vertices[j].Init(); cluster->Faces[j*2+0] = max; cluster->Faces[j*2+1] = j; j++; for(k=1;k<max;k++) { cluster->Vertices[j].Init(); cluster->Faces[j*2+0] = 0; cluster->Faces[j*2+1] = j; j++; } } sVERIFY(j==vcount); cmd = buffer; while(!Error && *cmd) { if(sCmpMem(cmd,"|POSITION",9)==0) { cmd+=9; sVERIFY(Pos); for(i=0;i<vcount;i++) { j = ScanInt(); cluster->Vertices[i].Pos = Pos[j]; cluster->Vertices[i].Index = j; } } else if(sCmpMem(cmd,"|NORMAL",7)==0) { cmd+=7; sVERIFY(Norm); for(i=0;i<vcount;i++) { j = ScanInt(); cluster->Vertices[i].Normal = Norm[j]; cluster->Vertices[i].Normal.Init(0,0,0,1); } } else if(sCmpMem(cmd,"|COLOR",6)==0) { cmd+=6; sVERIFY(Color); for(i=0;i<vcount;i++) { j = ScanInt(); cluster->Vertices[i].Color = Color[j]; } } else if(sCmpMem(cmd,"|TEX_COORD_UV",13)==0) { cmd+=13; set = 0; if(*cmd>='0' && *cmd<='9') { while(*cmd>='0' && *cmd<='9') set = set*10 + ((*cmd++)-'0'); sVERIFY(set>=0 && set<sXSI_MAXUV); sVERIFY(UV[set]) for(set2=0;set2<4;set2++) if(sCmpString(TSName[cluster->Material->TUV[set2]],UVName[set])==0) break; } else { set2 = 0; } for(i=0;i<vcount;i++) { j = ScanInt(); if(set2>=0 && set2<2) { cluster->Vertices[i].UV[set2][0] = 0.0f;// UV[set][j*2+0]; cluster->Vertices[i].UV[set2][1] = 0.0f;// UV[set][j*2+1]; } } } else {
void Streaker::AddStreak(const std::string &varname, StreakInfo &s, PDBFileObject *pdb) { const char *mName = "Streaker::AddStreak: "; // Make sure that all variables exist and that their sizes are good. TypeEnum t[3]; std::string typeString[3]; int nTotalElements[3]; int *dimensions[3]; int nDims[3]; bool xExists = pdb->SymbolExists(s.xvar.c_str(), &t[0], typeString[0], &nTotalElements[0], &dimensions[0], &nDims[0]); bool yExists = pdb->SymbolExists(s.yvar.c_str(), &t[1], typeString[1], &nTotalElements[1], &dimensions[1], &nDims[1]); bool zExists = pdb->SymbolExists(s.zvar.c_str(), &t[2], typeString[2], &nTotalElements[2], &dimensions[2], &nDims[2]); if(xExists && yExists && zExists) { debug4 << mName << "All streakplot variables exist." << endl; // Make sure that xvar is 1d and that the others are 2/3d (inc. time) // and that yvar is the same size as zvar. if(nDims[0] > 1) { debug4 << mName << "The time variable " << s.xvar.c_str() << " has " << nDims[0] << " dimensions instead of 1." << endl; goto invalid; } if(nDims[1] == 1 || nDims[1] > 3) { debug4 << mName << "The yvar variable " << s.yvar.c_str() << " has " << nDims[1] << " dimensions; not 2 or 3." << endl; goto invalid; } if(nDims[2] == 1 || nDims[2] > 3) { debug4 << mName << "The zvar variable " << s.zvar.c_str() << " has " << nDims[1] << " dimensions; not 2 or 3." << endl; goto invalid; } if(nDims[1] != nDims[2]) { debug4 << mName << "The yvar,zvar dimensions do not match." << endl; goto invalid; } // Make sure that yvar's last dimension is the same size as xvar if // we have an xvar is an array. if(nDims[0] == 1 && dimensions[0][0] != dimensions[1][nDims[1]-1]) { debug4 << mName << "Time dims: " << dimensions[0][0] << " are not the same as yvar's last dimension: " << dimensions[1][nDims[1]-1] << endl; goto invalid; } // Make sure yvar, zvar are the same size. for(int i = 0; i < nDims[1]; ++i) if(dimensions[1][i] != dimensions[2][i]) { debug4 << mName << "yvar's dim[" << i << "]=" << dimensions[1][i] << " and that is not equal to zvar's dim[" << i << "]=" << dimensions[2][i] << endl; goto invalid; } // Make sure that the slice is valid. if(s.slice == 0) { if(s.sliceIndex >= dimensions[1][0]) { debug4 << mName << "X slice=" << s.sliceIndex << " is larger than yvar's dim[0]=" << dimensions[1][0] << endl; goto invalid; } s.hsize = dimensions[1][1]; } else if(s.slice == 1) { if(s.sliceIndex >= dimensions[1][1]) { debug4 << mName << "Y slice=" << s.sliceIndex << " is larger than yvar's dim[1]=" << dimensions[1][1] << endl; goto invalid; } s.hsize = dimensions[1][0]; } s.hasMaterial = FindMaterial(pdb, dimensions[2], nDims[2]); // Okay, it looks good. Add the streak. streaks[varname] = s; } else debug4 << mName << "One or more streakplot variables is missing." << endl; invalid: for(int i = 0; i < 3; ++i) delete [] dimensions[i]; }
// TODO: All of these Get() functions look very similar. // Keep them all for their interface, but have them call a common function //----------------------------------------------------------------------------- CPUTMaterial *CPUTAssetLibrary::GetMaterial( const cString &name, bool nameIsFullPathAndFilename, const CPUTModel *pModel, int meshIndex, const char **pShaderMacros, // Note: this is honored only on first load. Subsequent GetMaterial calls will return the material with shaders as compiled with original macros. int numSystemMaterials, cString *pSystemMaterialNames, // Note: this is honored only on first load. Subsequent GetMaterial calls will return the material with shaders as compiled with original macros. cString *pExternalName, float4 *pExternals, // list of values for the externals int *pExternalOffset, // list of offsets to each of the exernals (e.g., char offset of this external in the cbExternals constant buffer) int *pExternalSize, int externalCount ){ // Resolve name to absolute path before searching cString absolutePathAndFilename; if (name[0] == '%') { absolutePathAndFilename = mSystemDirectoryName + _L("Material/") + name.substr(1) + _L(".mtl"); // TODO: Instead of having the Material/directory hardcoded here it could be set like the normal material directory. But then there would need to be a bunch new variables like SetSystemMaterialDirectory CPUTFileSystem::ResolveAbsolutePathAndFilename(absolutePathAndFilename, &absolutePathAndFilename); } else if( !nameIsFullPathAndFilename ) { CPUTFileSystem::ResolveAbsolutePathAndFilename( mMaterialDirectoryName + name + _L(".mtl"), &absolutePathAndFilename); } else { absolutePathAndFilename = name; } CPUTMaterial *pMaterial=NULL; if( pModel ) { pMaterial = pModel->GetMaterial( meshIndex ); if( pMaterial ) { pMaterial->AddRef(); return pMaterial; } } if( !pMaterial && !pShaderMacros && !pExternals ) { // Loading a non-instanced material (or, the master). // The caller supplied macros, so we assume they make the material unique. // TODO: Track macros and match if duplicate macros supplied? pMaterial = FindMaterial(absolutePathAndFilename, true); } // If the material has per-model properties, then we need a material clone if( pMaterial ) { pMaterial->AddRef(); } else { pMaterial = CPUTMaterial::CreateMaterial( absolutePathAndFilename, pModel, meshIndex, pShaderMacros, numSystemMaterials, pSystemMaterialNames, externalCount, pExternalName, pExternals, pExternalOffset, pExternalSize ); ASSERT( pMaterial, _L("Failed creating material.") ); } // Not looking for an instance, so return what we found return pMaterial; }
int readOBJ(struct OBJ_Model * obj) { if (obj->filename == 0 ) { fprintf(stderr,"readOBJ called with a null filename , cannot continue \n"); return 0; } /* Read the .obj model from file FILENAME */ /* All faces are converted to be triangles */ FILE *file=0; char buf[128]; char buf1[128]; unsigned int wrongDecimalSeperatorBug=0; long unsigned int numvertices; /* number of vertices in model */ long unsigned int numnormals; /* number of normals in model */ long unsigned int numcolors; long unsigned int numtexs; /* number of normals in texture coordintaes */ long unsigned int numfaces; /* number of faces in model */ long unsigned int numgroups; /* number of groups in model */ GLuint cur_group,material, mat; long unsigned int v,n,t,i; int grp; fprintf(stderr,"TODO : proper string allocation here for filename %s \n",obj->filename); char fname[2*MAX_MODEL_PATHS+1]={0}; snprintf(fname,2*MAX_MODEL_PATHS,"%s/%s.obj",obj->directory , obj->filename); fprintf(stderr,"Opening File %s ..\n",fname); file=fopen(fname,"r"); if(file==0) { fprintf(stderr,"Could not open file %s for reading Object\n",fname); return 0; } // strcpy(name,filename); strcpy(obj->matLib,""); //Group Pass rewind(file); numgroups = 1; while(fscanf(file, "%s", buf) != EOF) { if(buf[0]=='g') numgroups++; else fgets(buf, sizeof(buf), file); // eat up rest of line } if(numgroups==0) { numgroups=1; } obj->groups = (Group*) malloc(sizeof(Group)* numgroups); if (obj->groups == 0) { fprintf(stderr,"Could not make enough space for %lu groups \n",numgroups); fclose(file); return 0; } obj->numGroups = 0; obj->numFaces =0; // 1st Pass rewind(file); numtexs = 0; numvertices = 0; numnormals = 0; numcolors = 0; numfaces = 0; cur_group = AddGroup(obj,"default"); obj->groups[0].material=0; while(fscanf(file, "%s", buf) != EOF) { if(strcmp(buf, "mtllib")==0) { fscanf(file, "%s", buf1); strcpy(obj->matLib, buf1); loadMTL(obj,obj->directory ,buf1); printf("loadmtl %s survived\n", obj->matLib); } switch(buf[0]) { case '#': fgets(buf, sizeof(buf), file); break; // comment eat up rest of line // v, vn, vt case 'v': switch(buf[1]) { case '\0': // vertex eat up rest of line fgets(buf, sizeof(buf), file); numvertices++; if (floatingPointCheck(buf,strlen(buf)) ) { ++wrongDecimalSeperatorBug; } if (countChar(buf,strlen(buf),' ',buf[1])==6) { numcolors++ ; } //meshlab extension for colors on obj files break; case 'n': // normal eat up rest of line fgets(buf, sizeof(buf), file); numnormals++; break; case 't': //texture coordinate eat up rest of line fgets(buf, sizeof(buf), file); numtexs ++; break; default: fprintf(stderr,"Unexpected characters ( \"%s\" ) while waiting for v, vn ,vt .\n", buf); return 0; break; } break; case 'm': fgets(buf, sizeof(buf), file); break; case 'u': fgets(buf, sizeof(buf), file); break;// eat up rest of line case 'g': //group eat up rest of line fgets(buf, sizeof(buf), file); sscanf(buf, "%s", buf); cur_group = AddGroup(obj,buf); break; case 'f': // face v =0; n = 0; t = 0; fscanf(file, "%s", buf); // can be one of %d, %d//%d, %d/%d, %d/%d/%d if (strstr(buf, "//")) { // v//n sscanf(buf, "%d//%d", &v, &n); fscanf(file, "%d//%d", &v, &n); fscanf(file, "%d//%d", &v, &n); obj->numFaces++; while(fscanf(file, "%d//%d", &v, &n) > 0) { obj->numFaces++; } } else if (sscanf(buf, "%d/%d/%d", &v, &t, &n) == 3) { // v/t/n fscanf(file, "%d/%d/%d", &v, &t, &n); fscanf(file, "%d/%d/%d", &v, &t, &n); obj->numFaces++; while(fscanf(file, "%d/%d/%d", &v, &t, &n) > 0) { obj->numFaces++; } } else if (sscanf(buf, "%d/%d", &v, &t) == 2) { // v/t fscanf(file, "%d/%d", &v, &t); fscanf(file, "%d/%d", &v, &t); obj->numFaces++; while(fscanf(file, "%d/%d", &v, &t) > 0) { obj->numFaces++; } } else { // v fscanf(file, "%d", &v); fscanf(file, "%d", &v); obj->numFaces++; while(fscanf(file, "%d", &v) > 0) { obj->numFaces++; } } break; //end of face case default: fgets(buf, sizeof(buf), file); break; // eat up rest of line } } // set the stats in the model structure obj->numVertices = numvertices; obj->numNormals = numnormals; obj->numTexs = numtexs; obj->numColors = numcolors; printf("Vertices : %ld\n",obj->numVertices); printf("Normals : %ld\n",obj->numNormals); printf("Faces : %ld\n",obj->numFaces); printf("Groups : %ld\n",obj->numGroups); printf("Texes : %ld\n",obj->numTexs); printf("Colors : %ld\n",obj->numColors); if (wrongDecimalSeperatorBug) { fprintf(stderr,RED "! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !\n"); fprintf(stderr,RED "\n\n\n\nThis OBJ file has a wrong seperator for floating point numbers \n"); fprintf(stderr," please use sed -i 's/,/./g' %s \n\n\n" NORMAL,obj->filename); fprintf(stderr,RED "! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !\n"); } for(i=0; i<obj->numGroups; i++) { obj->groups[i].numFaces=0; printf("%d\n", obj->groups[i].hasNormals);//0, 0 } // Allocating memory fprintf(stderr,"Allocating memory for faces\n"); obj->faceList = (Face*) malloc(sizeof(Face)*(obj->numFaces+2)); if (obj->faceList == 0) { fprintf(stderr,"Could not allocate enough memory for face struct\n"); } memset (obj->faceList,0,sizeof(Face)*(obj->numFaces+2)); fprintf(stderr,"Allocating memory for vertices\n"); obj->vertexList = (Vertex*) malloc(sizeof(Vertex)*(obj->numVertices+2)); if (obj->vertexList == 0) { fprintf(stderr,"Could not allocate enough memory for vertex struct\n"); } memset (obj->vertexList,0,sizeof(Vertex)*(obj->numVertices+2)); if(obj->numNormals!=0) { fprintf(stderr,"Allocating memory for normals\n"); obj->normalList=(Normal*)malloc(sizeof(Normal)*(obj->numNormals+2)); if (obj->normalList == 0) { fprintf(stderr,"Could not allocate enough memory for normal struct\n"); } memset (obj->normalList,0,sizeof(Normal)*(obj->numNormals+2)); } if(obj->numTexs!=0) { fprintf(stderr,"Allocating memory for textures\n"); obj->texList=(TexCoords*)malloc(sizeof(TexCoords)*(obj->numTexs+2)); if (obj->texList == 0) { fprintf(stderr,"Could not allocate enough memory for texture struct\n"); } memset (obj->texList,0,sizeof(TexCoords)*(obj->numTexs+2)); } if(obj->numColors!=0) { fprintf(stderr,"Allocating memory for colors\n"); obj->colorList=(RGBColors*)malloc(sizeof(RGBColors)*(obj->numColors+2)); if (obj->colorList == 0) { fprintf(stderr,"Could not allocate enough memory for colors struct\n"); } memset (obj->colorList,0,sizeof(RGBColors)*(obj->numColors+2)); } // Second Pass rewind(file); //These dont work if they become 0 :P obj->numVertices = 1; obj->numNormals = 1; obj->numTexs = 1; obj->numColors = 1; obj->customColor =( obj->numColors > 0 ); obj->numFaces = 0; material = 0; grp = 0; while(!feof(file)) { fscanf(file, "%s", buf); if(!strcmp(buf, "usemtl")) { fscanf(file, "%s", buf1); unsigned int foundMaterial; if ( FindMaterial( obj, buf1 , &foundMaterial) ) { mat = foundMaterial; obj->groups[grp].material = mat; strcpy(obj->matLib, buf1); printf("loadmtl %s\n", obj->matLib); } } switch(buf[0]) { case '#': fgets(buf, sizeof(buf), file); break; // comment eat up rest of line case 'v': // v, vn, vt switch(buf[1]) { case '\0': // vertex if ( obj->customColor ) { fscanf(file, "%f %f %f %f %f %f", &obj->vertexList[obj->numVertices].x, &obj->vertexList[obj->numVertices].y, &obj->vertexList[obj->numVertices].z, &obj->colorList[obj->numColors].r, &obj->colorList[obj->numColors].g, &obj->colorList[obj->numColors].b ); obj->numVertices++; obj->numColors++; } else { fscanf(file, "%f %f %f", &obj->vertexList[obj->numVertices].x, &obj->vertexList[obj->numVertices].y, &obj->vertexList[obj->numVertices].z); obj->numVertices++; } break; case 'n': // normal fscanf(file, "%f %f %f", &obj->normalList[obj->numNormals].n1, &obj->normalList[obj->numNormals].n2, &obj->normalList[obj->numNormals].n3); obj->numNormals++; break; case 't': // normal fscanf(file, "%f %f", &obj->texList[obj->numTexs].u, &obj->texList[obj->numTexs].v); obj->numTexs++; break; } break; case 'u': fgets(buf, sizeof(buf), file); break; // eat up rest of line case 'g': // group eat up rest of line fgets(buf, sizeof(buf), file); sscanf(buf, "%s", buf); grp = FindGroup(obj,buf); obj->groups[grp].material = material; break; case 'f': //face v = 0; n = 0; t = 0; fscanf(file, "%s", buf); // can be one of %d, %d//%d, %d/%d, %d/%d/%d if (strstr(buf, "//")) { // v//n sscanf(buf, "%d//%d", &v, &n); obj->faceList[obj->numFaces].v[0] = v; obj->faceList[obj->numFaces].n[0] = n; fscanf(file, "%d//%d", &v, &n); obj->faceList[obj->numFaces].v[1] = v; obj->faceList[obj->numFaces].n[1] = n; fscanf(file, "%d//%d", &v, &n); obj->faceList[obj->numFaces].v[2] = v; obj->faceList[obj->numFaces].n[2] = n; AddFacetoG(&obj->groups[grp],obj->numFaces); obj->numFaces++; obj->groups[grp].hasNormals = 1; obj->groups[grp].hasTex = 0; while(fscanf(file, "%d//%d", &v, &n) > 0) { obj->faceList[obj->numFaces].v[0] = obj->faceList[obj->numFaces-1].v[0]; obj->faceList[obj->numFaces].n[0] = obj->faceList[obj->numFaces-1].n[0]; obj->faceList[obj->numFaces].v[1] = obj->faceList[obj->numFaces-1].v[2]; obj->faceList[obj->numFaces].n[1] = obj->faceList[obj->numFaces-1].n[2]; obj->faceList[obj->numFaces].v[2] = v; obj->faceList[obj->numFaces].n[2] = n; AddFacetoG(&obj->groups[grp],obj->numFaces); obj->numFaces++; } } else if (sscanf(buf, "%d/%d/%d", &v, &t, &n) == 3) { // v/t/n obj->faceList[obj->numFaces].v[0] = v; obj->faceList[obj->numFaces].n[0] = n; obj->faceList[obj->numFaces].t[0] = t; fscanf(file, "%d/%d/%d", &v, &t, &n); obj->faceList[obj->numFaces].v[1] = v; obj->faceList[obj->numFaces].n[1] = n; obj->faceList[obj->numFaces].t[1] = t; fscanf(file, "%d/%d/%d", &v, &t, &n); obj->faceList[obj->numFaces].v[2] = v; obj->faceList[obj->numFaces].n[2] = n; obj->faceList[obj->numFaces].t[2] = t; AddFacetoG(&obj->groups[grp],obj->numFaces); obj->numFaces++; obj->groups[grp].hasNormals = 1; obj->groups[grp].hasTex = 1; while(fscanf(file, "%d/%d/%d", &v, &t, &n) > 0) { obj->faceList[obj->numFaces].v[0] = obj->faceList[obj->numFaces-1].v[0]; obj->faceList[obj->numFaces].n[0] = obj->faceList[obj->numFaces-1].n[0]; obj->faceList[obj->numFaces].t[0] = obj->faceList[obj->numFaces-1].t[0]; obj->faceList[obj->numFaces].v[1] = obj->faceList[obj->numFaces-1].v[2]; obj->faceList[obj->numFaces].n[1] = obj->faceList[obj->numFaces-1].n[2]; obj->faceList[obj->numFaces].t[1] = obj->faceList[obj->numFaces-1].t[2]; obj->faceList[obj->numFaces].v[2] = v; obj->faceList[obj->numFaces].n[2] = n; obj->faceList[obj->numFaces].t[2] = t; AddFacetoG(&obj->groups[grp],obj->numFaces); obj->numFaces++; } } else if (sscanf(buf, "%d/%d", &v, &t) == 2) { // v/t obj->groups[grp].hasTex = 1; obj->faceList[obj->numFaces].v[0] = v; obj->faceList[obj->numFaces].t[0] = t; fscanf(file, "%d/%d", &v, &t); obj->faceList[obj->numFaces].v[1] = v; obj->faceList[obj->numFaces].t[1] = t; fscanf(file, "%d/%d", &v, &t); obj->faceList[obj->numFaces].v[2] = v; obj->faceList[obj->numFaces].t[2] = t; AddFacetoG(&obj->groups[grp],obj->numFaces); obj->numFaces++; while(fscanf(file, "%d/%d", &v, &t) > 0) { obj->faceList[obj->numFaces].v[0] = obj->faceList[obj->numFaces-1].v[0]; obj->faceList[obj->numFaces].t[0] = obj->faceList[obj->numFaces-1].t[0]; obj->faceList[obj->numFaces].v[1] = obj->faceList[obj->numFaces-1].v[2]; obj->faceList[obj->numFaces].t[1] = obj->faceList[obj->numFaces-1].t[2]; obj->faceList[obj->numFaces].v[2] = v; obj->faceList[obj->numFaces].t[2] = t; AddFacetoG(&obj->groups[grp],obj->numFaces); obj->numFaces++; }//while } else { // v sscanf(buf, "%d", &v); obj->faceList[obj->numFaces].v[0] = v; fscanf(file, "%d", &v); obj->faceList[obj->numFaces].v[1] = v; fscanf(file, "%d", &v); obj->faceList[obj->numFaces].v[2] = v; obj->groups[grp].hasNormals = 0; obj->groups[grp].hasTex = 0; AddFacetoG(&obj->groups[grp],obj->numFaces); obj->numFaces++; while(fscanf(file, "%d", &v) == 1) { obj->faceList[obj->numFaces].v[0] = obj->faceList[obj->numFaces-1].v[0]; obj->faceList[obj->numFaces].v[1] = obj->faceList[obj->numFaces-1].v[2]; obj->faceList[obj->numFaces].v[2] = v; AddFacetoG(&obj->groups[grp],obj->numFaces); obj->numFaces++; } } break; default: fgets(buf, sizeof(buf), file); break; // eat up rest of line } } fclose(file); printf("Model has %ld faces %u colors \n",obj->numFaces, obj->numColors); for(i=0; i<obj->numGroups; i++) { // fprintf(stderr,"Group %s has %ld faces and material %s, \t \n",obj->groups[i].name,obj->groups[i].numFaces,obj->matList[obj->groups[i].material].name); } #if CALCULATE_3D_BOUNDING_BOX calculateOBJBBox(obj); #endif // CALCULATE_3D_BOUNDING_BOX return 1; }