// 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;
}
Exemple #2
0
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();
    }
}
Exemple #3
0
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;
}
Exemple #7
0
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;
}
Exemple #12
0
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;
}
Exemple #15
0
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;
}