//********************************************************************************************** void CIGInfo::load(TShapeCache &shapeCache) { if (Loaded) return; Loaded = true; // even if loading fails, don't try twice to load it try { CIFile stream; stream.open(Path); printf(Path.c_str()); CSmartPtr<CInstanceGroup> ig = new CInstanceGroup; ig->serial(stream); IG = ig; // commit } catch(EStream &e) { nlwarning(e.what()); } if (IG) { // complete cache for(uint k = 0; k < IG->getNumInstance(); ++k) { std::string shapeName = standardizeShapeName(IG->getShapeName(k)); if (NLMISC::strlwr(CFile::getExtension(shapeName)) == "pacs_prim") { continue; } TShapeCache::iterator it = shapeCache.find(shapeName); CShapeInfo si; bool buildOK = false; if (it == shapeCache.end()) { CShapeStream ss; try { CIFile stream; std::string path = CPath::lookup(shapeName, false, false); if (!path.empty()) { stream.open(path); ss.serial(stream); CShapeInfo si; si.build(*ss.getShapePointer()); delete ss.getShapePointer(); shapeCache[shapeName].swap(si); } } catch (EStream &e) { // shape not loaded nlwarning(e.what()); } } } } }
int main(int argc, char *argv[]) { uint i; // Avoid warnings. NLMISC::createDebug(); DebugLog->addNegativeFilter("Exception will be launched"); WarningLog->addNegativeFilter("Exception will be launched"); InfoLog->addNegativeFilter("FEHTIMER>"); InfoLog->addNegativeFilter("adding the path"); // Init serial registerSerial3d(); if(argc<4) { puts("Usage: build_clod_bank path_file.cfg config_file.cfg destfile.clodbank [bakeFrameRate=20] "); return 0; } try { // The bank to fill CLodCharacterShapeBank lodShapeBank; // Read the frameRate to process bake of anims float bakeFrameRate= 20; if(argc>=5) { bakeFrameRate= (float)atof(argv[4]); if(bakeFrameRate<=1) { nlwarning("bad bakeFrameRate value, use a default of 20"); bakeFrameRate= 20; } } // parse the path file. //================== // try to load the config file. CConfigFile pathConfig; pathConfig.load (argv[1]); // Get the search pathes CConfigFile::CVar &search_pathes = pathConfig.getVar ("search_pathes"); for (i = 0; i < (uint)search_pathes.size(); i++) { // Add to search path CPath::addSearchPath (search_pathes.asString(i)); } // parse the config file. //================== // try to load the config file. CConfigFile config; config.load (argv[2]); // For all .clod to process //================== CConfigFile::CVar &clod_list = config.getVar ("clod_list"); uint lodId; for (lodId = 0; lodId < (uint)clod_list.size(); lodId++) { string lodName= clod_list.asString(lodId); printf("Process LOD: %s\n", lodName.c_str()); // Search the variable with this name. try { CIFile iFile; // get the anim list. CConfigFile::CVar &clod_anim_list = config.getVar (lodName); // Correct format? if(clod_anim_list.size()<3) { nlwarning("%s skipped. Must have at least the skeleton file name, the lod file name, and one animation", lodName.c_str()); // go to next. continue; } // Init lod shape process //=========================== // The first variable is the name of the skeleton. string skeletonName= clod_anim_list.asString(0); CSmartPtr<CSkeletonShape> skeletonShape; // Load it. iFile.open(CPath::lookup(skeletonName)); CShapeStream strShape; strShape.serial(iFile); iFile.close(); // Get the pointer, check it's a skeleton if(dynamic_cast<CSkeletonShape*>(strShape.getShapePointer()) == NULL) throw Exception("%s is not a Skeleton", skeletonName.c_str()); skeletonShape= (CSkeletonShape*)strShape.getShapePointer(); // The second var is the filename of the lod. string lodFileName= clod_anim_list.asString(1); // Load the shape. CLodCharacterShapeBuild lodShapeBuild; iFile.open( CPath::lookup(lodFileName) ); iFile.serial(lodShapeBuild); iFile.close(); // Prepare to build the lod. CLodCharacterBuilder lodBuilder; lodBuilder.setShape(lodName, skeletonShape, &lodShapeBuild); // Traverse all anim in the list. //=========================== uint animId; for (animId = 2; animId < (uint)clod_anim_list.size(); animId++) { string animFileName= clod_anim_list.asString(animId); // display. printf("Process Anim: %d/%d\r", animId-1, clod_anim_list.size()-2); // Try to load the animation CAnimation *anim= new CAnimation; // NB: continue, to list all ANIM if anim not found try { iFile.open( CPath::lookup(animFileName) ); iFile.serial(*anim); iFile.close(); // Add to the builder. NB: animation will be delete in this method. // NB: the key name here is the entire file, with the .anim, for easier georges editing. lodBuilder.addAnim(animFileName.c_str(), anim, bakeFrameRate); } catch(EPathNotFound &) { printf("ERROR anim not found %s\n", animFileName.c_str()); delete anim; } } printf("\n"); // Add to the bank. //=========================== uint32 shapeId= lodShapeBank.addShape(); *lodShapeBank.getShapeFullAcces(shapeId)= lodBuilder.getLodShape(); } catch(EUnknownVar &evar) { nlwarning(evar.what()); // Any other exception will make the program quit. } } // Save bank. //=========================== // compile lodShapeBank.compile(); // Save COFile oFile(argv[3]); oFile.serial(lodShapeBank); oFile.close(); } catch (Exception& except) { // Error message printf ("ERROR %s.\n Aborting.\n", except.what()); } return 0; }
int main(int argc, char **argv) { // Filter addSearchPath NLMISC::createDebug(); InfoLog->addNegativeFilter("adding the path"); createDebug(); try { // Init init(); uint i, j, k; for (i=0; i<IGs.size(); ++i) { // load ig associated to the zone string igName = IGs[i]+".ig"; CIFile igStream(CPath::lookup(igName)); CInstanceGroup ig; igStream.serial(ig); CAABBox igBBox; bool boxSet = false; nlinfo("Generating BBOX for %s", igName.c_str()); // search in group for water instance for (j=0; j<ig._InstancesInfos.size(); ++j) { /* Ben: c'est degueulasse, mais c'est les coders a la 3D, y savent pas coder Hld: ouai, mais ca marche pas ton truc, alors p'tet qu'on sait pas coder mais toi non plus :p Special Dedicace to SupaGreg! string shapeName = ig._InstancesInfos[j].Name+".shape"; */ string shapeName = ig._InstancesInfos[j].Name; if (CFile::getExtension (shapeName) == "") shapeName += ".shape"; if (NonWaterShapes.find(shapeName) != NonWaterShapes.end()) continue; string shapeNameLookup = CPath::lookup (shapeName, false, false); if (!shapeNameLookup.empty()) { CIFile f; if (f.open (shapeNameLookup)) { CShapeStream shape; shape.serial(f); CWaterShape *wshape = dynamic_cast<CWaterShape *>(shape.getShapePointer()); if (wshape == NULL) { NonWaterShapes.insert(shapeName); continue; } CMatrix matrix; ig.getInstanceMatrix(j, matrix); CPolygon wpoly; wshape->getShapeInWorldSpace(wpoly); for (k=0; k<wpoly.Vertices.size(); ++k) { if (boxSet) { igBBox.extend(matrix * wpoly.Vertices[k]); } else { igBBox.setCenter(matrix * wpoly.Vertices[k]); boxSet = true; } } } else { nlwarning ("Can't load shape %s", shapeNameLookup.c_str()); } } else { NonWaterShapes.insert(shapeName); } } if (boxSet) { Boxes.push_back(CIGBox(igName, igBBox)); nlinfo("Bbox: (%.1f,%.1f)-(%.1f,%.1f)", igBBox.getMin().x, igBBox.getMin().y, igBBox.getMax().x, igBBox.getMax().y); } } COFile output(Output); output.serialCont(Boxes); } catch (Exception &e) { fprintf (stderr,"main trapped an exception: '%s'\n", e.what ()); } #ifndef NL_DEBUG catch (...) { fprintf(stderr,"main trapped an unknown exception\n"); } #endif // NL_DEBUG return 0; }
// *************************************************************************** void CIgLighterLib::lightIg(CInstanceLighter &instanceLighter, const CInstanceGroup &igIn, CInstanceGroup &igOut, CInstanceLighter::CLightDesc &lightDesc, CSurfaceLightingInfo &slInfo, const char *igName) { sint i; // Setup. //======= // Init instanceLighter.init(); // For interiors ig, disable Sun contrib according to ig. lightDesc.DisableSunContribution= !igIn.getRealTimeSunContribution(); // Copy it to igOut, just to keep same setup data for in and out. igOut.enableRealTimeSunContribution(!lightDesc.DisableSunContribution); // Add obstacles. std::vector<CInstanceLighter::CTriangle> obstacles; // only if Shadowing On. if(lightDesc.Shadow) { // Map of shape to load std::map<string, IShape*> shapeMap; // For all instances of igIn. for(i=0; i<(sint)igIn.getNumInstance();i++) { // progress instanceLighter.progress("Loading Shapes obstacles", float(i)/igIn.getNumInstance()); // Skip it?? IgLighterLib use the DontCastShadowForInterior flag. See doc of this flag if(igIn.getInstance(i).DontCastShadow || igIn.getInstance(i).DontCastShadowForInterior) continue; // Get the instance shape name string name= igIn.getShapeName(i); bool shapeFound= true; // Try to find the shape in the UseShapeMap. std::map<string, IShape*>::const_iterator iteMap= lightDesc.UserShapeMap.find (name); // If not found in userShape map, try to load it from the temp loaded ShapeBank. if( iteMap == lightDesc.UserShapeMap.end() ) { // Add a .shape at the end ? if (name.find('.') == std::string::npos) name += ".shape"; // Lookup the file string nameLookup = CPath::lookup (name, false, false); if (!nameLookup.empty()) name = nameLookup; // Find the shape in the bank iteMap= shapeMap.find (name); if (iteMap==shapeMap.end()) { // Input file CIFile inputFile; if (inputFile.open (name)) { // Load it CShapeStream stream; stream.serial (inputFile); // Get the pointer iteMap=shapeMap.insert (std::map<string, IShape*>::value_type (name, stream.getShapePointer ())).first; } else { // Error nlwarning ("WARNING can't load shape %s\n", name.c_str()); shapeFound= false; } } } if(shapeFound) { CMatrix matInst; matInst.setPos(igIn.getInstancePos(i)); matInst.setRot(igIn.getInstanceRot(i)); matInst.scale(igIn.getInstanceScale(i)); // Add triangles of this shape CInstanceLighter::addTriangles(*iteMap->second, matInst, obstacles, i); } } // Clean Up shapes. //----------- std::map<string, IShape*>::iterator iteMap; iteMap= shapeMap.begin(); while(iteMap!= shapeMap.end()) { // delte shape delete iteMap->second; // delete entry in map shapeMap.erase(iteMap); // next iteMap= shapeMap.begin(); } } // Add pointLights of the IG. for(i=0; i<(sint)igIn.getPointLightList().size();i++) { instanceLighter.addStaticPointLight( igIn.getPointLightList()[i], igName ); } // Setup a CIGSurfaceLightBuild if needed. //======= CIGSurfaceLightBuild *igSurfaceLightBuild= NULL; CGlobalRetriever *globalRetriever= slInfo.GlobalRetriever; CRetrieverBank *retrieverBank= slInfo.RetrieverBank; float cellSurfaceLightSize= slInfo.CellSurfaceLightSize; if(retrieverBank && globalRetriever) { igSurfaceLightBuild= new CIGSurfaceLightBuild; igSurfaceLightBuild->CellSize= cellSurfaceLightSize; // col Identifier. string colIdent= slInfo.ColIdentifierPrefix + slInfo.IgFileName + slInfo.ColIdentifierSuffix; // For any retreiverInstance with this identifier. //---------------- uint numInstances= (uint)globalRetriever->getInstances().size(); for(uint instanceId=0; instanceId<numInstances; instanceId++) { const CRetrieverInstance &instance= globalRetriever->getInstance(instanceId); // If this instance is an interior if ( instance.getType() == CLocalRetriever::Interior ) { uint localRetrieverId= instance.getRetrieverId(); const CLocalRetriever &localRetriever= retrieverBank->getRetriever(localRetrieverId); // get the identifer of this localRetriever string retIdent= localRetriever.getIdentifier(); // Match the ident?? if( retIdent.find(colIdent)!=string::npos ) { // check CRetrieverLightGrid not already present CIGSurfaceLightBuild::ItRetrieverGridMap itRgm; itRgm= igSurfaceLightBuild->RetrieverGridMap.find(localRetrieverId); if( itRgm != igSurfaceLightBuild->RetrieverGridMap.end() ) { nlwarning ("ERROR Found 2 different collision retriever with same identifier: '%s'. The 2nd is discared\n", retIdent.c_str()); } else { // Append CRetrieverLightGrid. itRgm= igSurfaceLightBuild->RetrieverGridMap.insert( make_pair(localRetrieverId, CIGSurfaceLightBuild::CRetrieverLightGrid() ) ).first; CIGSurfaceLightBuild::CRetrieverLightGrid &rlg= itRgm->second; // Resize Grids. uint numSurfaces= (uint)localRetriever.getSurfaces().size(); rlg.Grids.resize( numSurfaces ); // Compute the bbox for all surfaces. (NB: local to the localRetriever). vector<CAABBox> surfaceBBoxes; localRetriever.buildInteriorSurfaceBBoxes(surfaceBBoxes); // For each surface, compute it. for(uint surfaceId=0; surfaceId<numSurfaces; surfaceId++) { // Progress. char stmp[256]; sprintf(stmp, "Sample surfaces of %s", retIdent.c_str()); instanceLighter.progress(stmp, surfaceId / float(numSurfaces)); // Compute surface and size of the grid. CIGSurfaceLightBuild::CSurface &surfDst= rlg.Grids[surfaceId]; // Snap Origin on cellSize surfDst.Origin= surfaceBBoxes[surfaceId].getMin(); surfDst.Origin.x= floorf(surfDst.Origin.x/cellSurfaceLightSize) * cellSurfaceLightSize; surfDst.Origin.y= floorf(surfDst.Origin.y/cellSurfaceLightSize) * cellSurfaceLightSize; // Snap Width / Height on cellSize. float sizex= surfaceBBoxes[surfaceId].getMax().x - surfDst.Origin.x; float sizey= surfaceBBoxes[surfaceId].getMax().y - surfDst.Origin.y; surfDst.Width= (uint)floorf(sizex/cellSurfaceLightSize) + 2; surfDst.Height= (uint)floorf(sizey/cellSurfaceLightSize) + 2; // Get Zcenter. float zCenter= surfaceBBoxes[surfaceId].getCenter().z; // Allocate elements. surfDst.Cells.resize(surfDst.Width * surfDst.Height); // For all elements for(sint yCell=0; yCell<(sint)surfDst.Height; yCell++) { for(sint xCell=0; xCell<(sint)surfDst.Width; xCell++) { // compute pos of the cell. ULocalPosition localPos; localPos.Estimation.x= surfDst.Origin.x + xCell*cellSurfaceLightSize; localPos.Estimation.y= surfDst.Origin.y + yCell*cellSurfaceLightSize; localPos.Estimation.z= zCenter; // snap the pos to the surface. localPos.Surface= surfaceId; bool snapped; localRetriever.snapToInteriorGround(localPos, snapped); // if snapped then this point is IN the surface. CIGSurfaceLightBuild::CCellCorner &cell= surfDst.Cells[yCell * surfDst.Width + xCell]; cell.InSurface= snapped; // If ok, retrieve the global (ie world) position if(snapped) { // build a valid globalPosition. UGlobalPosition globalPos; globalPos.InstanceId= instanceId; globalPos.LocalPosition= localPos; // retrieve from globalRetriever. cell.CenterPos= globalRetriever->getGlobalPosition(globalPos); // Add a delta to simulate entity center cell.CenterPos.z+= slInfo.CellRaytraceDeltaZ; // OverSample if(lightDesc.OverSampling==0) { // No OverSample, just add CenterPos to the samples. cell.NumOverSamples= 1; cell.OverSamples[0]= cell.CenterPos; } else { // OverSample. overSampleCell(cell, lightDesc.OverSampling, localRetriever, *globalRetriever, instanceId, localPos, cellSurfaceLightSize, slInfo.CellRaytraceDeltaZ); // it is possible that no samples lies in surfaces (small surface). // In this case, just copy CenterPos into samples. if(cell.NumOverSamples==0) { cell.NumOverSamples= 1; cell.OverSamples[0]= cell.CenterPos; } } } else { // For debug mesh only, get an approximate pos. cell.CenterPos= localPos.Estimation + instance.getOrigin(); cell.CenterPos.z+= slInfo.CellRaytraceDeltaZ; } // Init cell defaults cell.Dilated= false; cell.SunContribution= 0; } } } } } } } } // Run. //======= instanceLighter.light(igIn, igOut, lightDesc, obstacles, NULL, igSurfaceLightBuild); // Output a debug mesh?? if(igSurfaceLightBuild && slInfo.BuildDebugSurfaceShape && !igSurfaceLightBuild->RetrieverGridMap.empty() ) { // Do it for the sun and point lights. for(uint i=0;i<2;i++) { // compute CMesh::CMeshBuild meshBuild; CMeshBase::CMeshBaseBuild meshBaseBuild; CVector deltaPos= CVector::Null; deltaPos.z= - slInfo.CellRaytraceDeltaZ + 0.1f; // What kind of debug? if( i==0 ) igSurfaceLightBuild->buildSunDebugMesh(meshBuild, meshBaseBuild, deltaPos); else igSurfaceLightBuild->buildPLDebugMesh(meshBuild, meshBaseBuild, deltaPos, igOut); // build CMesh mesh; mesh.build(meshBaseBuild, meshBuild); // Save. CShapeStream shapeStream; shapeStream.setShapePointer(&mesh); COFile file; if( i==0 ) file.open(slInfo.DebugSunName); else file.open(slInfo.DebugPLName); shapeStream.serial(file); } } // Clean. //======= if(igSurfaceLightBuild) delete igSurfaceLightBuild; }
// --------------------------------------------------------------------------- // main // --------------------------------------------------------------------------- int main(int nNbArg, char **ppArgs) { if (nNbArg <3 || nNbArg >5) { outString ("ERROR : Wrong number of arguments\n"); outString ("USAGE : lightmap_optimizer <path_lightmaps> <path_shapes> [path_tags] [path_flag8bit]\n"); return -1; } vector<string> AllShapeNames; vector<CMeshBase*> AllShapes; std::vector<std::string> tags; char sLMPDir[MAX_PATH]; char sSHPDir[MAX_PATH]; GetCurrentDirectory (MAX_PATH, sExeDir); // Get absolute directory for lightmaps if (!SetCurrentDirectory(ppArgs[1])) { outString (string("ERROR : directory ") + ppArgs[1] + " do not exists\n"); return -1; } GetCurrentDirectory (MAX_PATH, sLMPDir); SetCurrentDirectory (sExeDir); // Get absolute directory for shapes if (!SetCurrentDirectory(ppArgs[2])) { outString (string("ERROR : directory ") + ppArgs[2] + " do not exists\n"); return -1; } GetCurrentDirectory (MAX_PATH, sSHPDir); dir ("*.shape", AllShapeNames, false); registerSerial3d (); for (uint32 nShp = 0; nShp < AllShapeNames.size(); ++nShp) { try { CShapeStream mesh; NLMISC::CIFile meshfile (AllShapeNames[nShp]); meshfile.serial( mesh ); meshfile.close(); // Add the shape to the map. CMeshBase *pMB = dynamic_cast<CMeshBase*>(mesh.getShapePointer()); AllShapes.push_back (pMB); } catch (NLMISC::EPathNotFound &e) { outString(string("ERROR: shape not found ")+AllShapeNames[nShp]+" - "+e.what()); return -1; } } if (nNbArg > 3 && ppArgs[3] && strlen(ppArgs[3]) > 0) { SetCurrentDirectory (sExeDir); if (!SetCurrentDirectory(ppArgs[3])) { outString (string("ERROR : directory ") + ppArgs[3] + " do not exists\n"); return -1; } dir ("*.tag", tags, false); for(uint k = 0; k < tags.size(); ++k) { std::string::size_type pos = tags[k].find('.'); if (pos != std::string::npos) { tags[k] = tags[k].substr(0, pos); } } } // **** Parse all mesh loaded, to flag each lightmap if 8 bit or not (NB: all layers should be same mode) std::set<string> setLM8Bit; for(uint i=0;i<AllShapes.size();i++) { CMeshBase *pMB= AllShapes[i]; if(!pMB) continue; uint32 nbMat= pMB->getNbMaterial(); for (uint32 m = 0; m < nbMat; ++m) { CMaterial& rMat = const_cast<CMaterial&>(pMB->getMaterial (m)); if (rMat.getShader() == CMaterial::LightMap) { // Begin with stage 0 uint8 stage = 0; while (rMat.getLightMap(stage) != NULL) { ITexture *pIT = rMat.getLightMap (stage); CTextureFile *pTF = dynamic_cast<CTextureFile*>(pIT); if (pTF != NULL) { string sTexName = NLMISC::strlwr(pTF->getFileName()); if(pTF->getUploadFormat()==ITexture::Luminance) setLM8Bit.insert(sTexName); } ++stage; } } } } // **** Parse all lightmaps, sorted by layer, and 8 or 16 bit mode SetCurrentDirectory (sExeDir); for (uint32 lmc8bitMode = 0; lmc8bitMode < 2; ++lmc8bitMode) for (uint32 nNbLayer = 0; nNbLayer < 256; ++nNbLayer) { // Get all lightmaps with same number of layer == nNbLayer // merge lightmaps only if they are in same mode (8bits or 16 bits) vector<string> AllLightmapNames; vector<sint> AllLightmapTags; vector<NLMISC::CBitmap*> AllLightmaps; sint32 i, j, k, m, n; string sFilter; // **** Get All Lightmaps that have this number of layer, and this mode sFilter = "*_" + NLMISC::toString(nNbLayer) + ".tga"; SetCurrentDirectory (sLMPDir); dir (sFilter, AllLightmapNames, false); // filter by layer vector<string> tmpLMs; tmpLMs.reserve(AllLightmapNames.size()); for (i = 0; i < (sint32)AllLightmapNames.size(); ++i) { string sTmp2 = getBaseName (AllLightmapNames[i]); sTmp2 += NLMISC::toString(nNbLayer+1) + ".tga"; // if not More layer than expected, ok if (!fileExist(sTmp2)) { tmpLMs.push_back(AllLightmapNames[i]); } } AllLightmapNames= tmpLMs; // filter by 8bit or not mode. tmpLMs.clear(); for (i = 0; i < (sint32)AllLightmapNames.size(); ++i) { bool lm8Bit= setLM8Bit.find( NLMISC::strlwr(AllLightmapNames[i]) ) !=setLM8Bit.end(); // if same mode if( lm8Bit == (lmc8bitMode==1) ) { tmpLMs.push_back(AllLightmapNames[i]); } } AllLightmapNames= tmpLMs; // **** Build tag info /* for(uint k = 0; k < tags.size(); ++k) { nlinfo("tag %d = %s", (int) k, tags[k].c_str()); } */ AllLightmapTags.resize(AllLightmapNames.size()); for(uint k = 0; k < AllLightmapNames.size(); ++k) { nlinfo("k = %d", (int) k); AllLightmapTags[k] = -1; // search for longest tag that match uint bestLength = 0; for(uint l = 0; l < tags.size(); ++l) { if (AllLightmapNames[k].size() > tags[l].size()) { if (tags[l].size() > bestLength) { std::string start = AllLightmapNames[k].substr(0, tags[l].size()); if (NLMISC::nlstricmp(start, tags[l]) == 0) { bestLength = (uint)tags[l].size(); // the tag matchs AllLightmapTags[k] = l; } } } } if (AllLightmapTags[k] == -1) { nlinfo(NLMISC::toString("Lightmap %s has no tag", AllLightmapNames[k].c_str()).c_str()); } else { nlinfo(NLMISC::toString("Lightmap %s has tag %d : %s", AllLightmapNames[k].c_str(), (int) AllLightmapTags[k], tags[AllLightmapTags[k]].c_str()).c_str()); } } // Check if all layer of the same lightmap has the same size if (nNbLayer > 0) for (i = 0; i < (sint32)AllLightmapNames.size(); ++i) { string sTmp2; sTmp2 = getBaseName (AllLightmapNames[i]) + "0.tga"; uint32 wRef, hRef; try { NLMISC::CIFile inFile; inFile.open(sTmp2); CBitmap::loadSize(inFile, wRef, hRef); } catch (NLMISC::Exception &e) { outString (string("ERROR :") + e.what()); return -1; } bool bFound = false; for (k = 1; k <= (sint32)nNbLayer; ++k) { string sTmp3 = getBaseName (AllLightmapNames[i]) + NLMISC::toString(k) + ".tga"; uint32 wCur = wRef, hCur = hRef; try { NLMISC::CIFile inFile; inFile.open(sTmp3); CBitmap::loadSize(inFile, wCur, hCur); } catch (NLMISC::Exception &) { } if ((wCur != wRef) || (hCur != hRef)) { bFound = true; break; } } // Should delete all layers of this lightmap (in fact in lightmapnames list we have // only the name of the current layer) if (bFound) { sTmp2 = getBaseName (AllLightmapNames[i]); outString(string("ERROR: lightmaps ")+sTmp2+"*.tga not all the same size\n"); for (k = 0; k < (sint32)AllLightmapNames.size(); ++k) { if (strnicmp(AllLightmapNames[k].c_str(), sTmp2.c_str(), sTmp2.size()) == 0) { for (j = k+1; j < (sint32)AllLightmapNames.size(); ++j) { AllLightmapNames[j-1] = AllLightmapNames[j]; AllLightmapTags[j - 1] = AllLightmapTags[j]; } AllLightmapNames.resize (AllLightmapNames.size()-1); AllLightmapTags.resize(AllLightmapTags.size() - 1); k = -1; i = -1; } } } } if (AllLightmapNames.size() == 0) continue; // Load all the lightmaps AllLightmaps.resize (AllLightmapNames.size()); for (i = 0; i < (sint32)AllLightmaps.size(); ++i) { try { NLMISC::CBitmap *pBtmp = new NLMISC::CBitmap; NLMISC::CIFile inFile; inFile.open(AllLightmapNames[i]); pBtmp->load(inFile); AllLightmaps[i] = pBtmp; } catch (NLMISC::Exception &e) { outString (string("ERROR :") + e.what()); return -1; } } // Sort all lightmaps by decreasing size for (i = 0; i < (sint32)(AllLightmaps.size()-1); ++i) for (j = i+1; j < (sint32)AllLightmaps.size(); ++j) { NLMISC::CBitmap *pBI = AllLightmaps[i]; NLMISC::CBitmap *pBJ = AllLightmaps[j]; if ((pBI->getWidth()*pBI->getHeight()) < (pBJ->getWidth()*pBJ->getHeight())) { NLMISC::CBitmap *pBTmp = AllLightmaps[i]; AllLightmaps[i] = AllLightmaps[j]; AllLightmaps[j] = pBTmp; string sTmp = AllLightmapNames[i]; AllLightmapNames[i] = AllLightmapNames[j]; AllLightmapNames[j] = sTmp; sint tagTmp = AllLightmapTags[i]; AllLightmapTags[i] = AllLightmapTags[j]; AllLightmapTags[j] = tagTmp; } } nlassert(AllLightmapTags.size() == AllLightmapNames.size()); for (i = 0; i < (sint32)AllLightmapNames.size(); ++i) { outString(NLMISC::toString("%d / %d\n", (int) i, (int) AllLightmapNames.size())); bool bAssigned = false; for (j = 0; j < i; ++j) { // Tags of both textures must match. We don't want to spread lightmap chunk in bitmap whose other part aren't used by current ig lightmaps (this wastes vram for nothing) if (AllLightmapTags[i] != AllLightmapTags[j]) continue; // Try to place the texture i into the texture j // This can be done only if texture was exported from the same zone. To ensure that, check NLMISC::CBitmap *pBI = AllLightmaps[i]; NLMISC::CBitmap *pBJ = AllLightmaps[j]; sint32 x, y; if (tryAllPos (pBI, pBJ, x, y)) { bAssigned = true; if (!putIn (pBI, pBJ, x, y)) { outString (string("ERROR : cannot put reference lightmap ")+AllLightmapNames[i]+ " in "+AllLightmapNames[j]); return -1; } // Put texture i into texture j for all layers of the lightmap ! for (k = 0; k <= (sint32)nNbLayer; ++k) { string sTexNameI = getBaseName (AllLightmapNames[i]) + NLMISC::toString(k) + ".tga"; string sTexNameJ = getBaseName (AllLightmapNames[j]) + NLMISC::toString(k) + ".tga"; NLMISC::CBitmap BitmapI; NLMISC::CBitmap BitmapJ; NLMISC::CIFile inFile; outString (NLMISC::toString("INFO : Transfering %s (tag = %d) in %s (tag = %d)", sTexNameI.c_str(), (int) AllLightmapTags[i], sTexNameJ.c_str(), (int) AllLightmapTags[j]) + " at ("+NLMISC::toString(x)+","+NLMISC::toString(y)+")\n"); try { inFile.open (sTexNameI); BitmapI.load (inFile); inFile.close (); inFile.open (sTexNameJ); BitmapJ.load (inFile); inFile.close (); } catch (NLMISC::Exception &e) { outString (string("ERROR :") + e.what()); return -1; } if (!putIn (&BitmapI, &BitmapJ, x, y)) { outString (string("ERROR : cannot put lightmap ")+sTexNameI+" in "+sTexNameJ+"\n"); return -1; } // Delete File DeleteFile (sTexNameI.c_str()); outString (string("INFO : Deleting file ")+sTexNameI+"\n"); // Save destination image NLMISC::COFile outFile; outFile.open (sTexNameJ); BitmapJ.writeTGA (outFile, 32); outString (string("INFO : Saving file ")+sTexNameJ+"\n"); } // Change shapes uvs related and names to the lightmap // --------------------------------------------------- SetCurrentDirectory (sSHPDir); for (k = 0; k < (sint32)AllShapes.size(); ++k) { CMeshBase *pMB = AllShapes[k]; if (!pMB) continue; uint nNbMat = pMB->getNbMaterial (); vector< vector<bool> > VerticesNeedRemap; bool bMustSave = false; // Initialize all VerticesNeedRemap CMesh *pMesh = dynamic_cast<CMesh*>(pMB); CMeshMRM *pMeshMRM = dynamic_cast<CMeshMRM*>(pMB); CMeshMultiLod *pMeshML = dynamic_cast<CMeshMultiLod*>(pMB); if (pMesh != NULL) { VerticesNeedRemap.resize(1); // Only one meshgeom vector<bool> &rVNR = VerticesNeedRemap[0]; rVNR.resize (pMesh->getMeshGeom().getVertexBuffer().getNumVertices(), false); } else if (pMeshMRM != NULL) { VerticesNeedRemap.resize(1); // Only one meshmrmgeom vector<bool> &rVNR = VerticesNeedRemap[0]; rVNR.resize (pMeshMRM->getMeshGeom().getVertexBuffer().getNumVertices(), false); } else if (pMeshML != NULL) { sint32 nNumSlot = pMeshML->getNumSlotMesh(); VerticesNeedRemap.resize(nNumSlot); for (m = 0; m < nNumSlot; ++m) { vector<bool> &rVNR = VerticesNeedRemap[m]; const CMeshGeom *pMG = dynamic_cast<const CMeshGeom*>(&pMeshML->getMeshGeom(m)); if (pMG != NULL) rVNR.resize (pMG->getVertexBuffer().getNumVertices(), false); else rVNR.resize(0); } } else continue; // Next mesh // All materials must have the lightmap names changed for (m = 0; m < (sint32)nNbMat; ++m) { bool bMustRemapUV = false; CMaterial& rMat = const_cast<CMaterial&>(pMB->getMaterial (m)); if (rMat.getShader() == CMaterial::LightMap) { // Begin with stage 0 uint8 stage = 0; while (rMat.getLightMap(stage) != NULL) { ITexture *pIT = rMat.getLightMap (stage); CTextureFile *pTF = dynamic_cast<CTextureFile*>(pIT); if (pTF != NULL) { string sTexName = NLMISC::strlwr(getBaseName(pTF->getFileName())); string sTexNameMoved = NLMISC::strlwr(getBaseName(AllLightmapNames[i])); if (sTexName == sTexNameMoved) { // We must remap the name and indicate to remap uvs bMustRemapUV = true; //string sNewTexName = NLMISC::strlwr(getBaseName(AllLightmapNames[j])); //sNewTexName += NLMISC::toString(getLayerNb(pTF->getFileName())) + ".tga"; //pTF->setFileName (sNewTexName); } } ++stage; } } // We have to remap the uvs of this mesh for this material if (bMustRemapUV) // Flaggage of the vertices to remap { if (pMesh != NULL) { // Flag all vertices linked to face with material m FlagVertices (const_cast<CMeshGeom&>(pMesh->getMeshGeom()), m, VerticesNeedRemap[0]); } else if (pMeshMRM != NULL) { FlagVerticesMRM (const_cast<CMeshMRMGeom&>(pMeshMRM->getMeshGeom()), m, VerticesNeedRemap[0]); } else if (pMeshML != NULL) { sint32 nNumSlot = pMeshML->getNumSlotMesh(); for (n = 0; n < nNumSlot; ++n) { // Get the mesh geom CMeshGeom *pMG = const_cast<CMeshGeom*>(dynamic_cast<const CMeshGeom*>(&pMeshML->getMeshGeom(n))); if (pMG) { // Flag the vertices FlagVertices (*pMG, m, VerticesNeedRemap[n]); } else { // Get the mesh MRM geom CMeshMRMGeom *pMMRMG = const_cast<CMeshMRMGeom*>(dynamic_cast<const CMeshMRMGeom*>(&pMeshML->getMeshGeom(n))); if (pMMRMG) { // Flag the vertices FlagVerticesMRM (*pMMRMG, m, VerticesNeedRemap[n]); } } } } } } // Change lightmap names for (m = 0; m < (sint32)nNbMat; ++m) { CMaterial& rMat = const_cast<CMaterial&>(pMB->getMaterial (m)); if (rMat.getShader() == CMaterial::LightMap) { // Begin with stage 0 uint8 stage = 0; while (rMat.getLightMap(stage) != NULL) { ITexture *pIT = rMat.getLightMap (stage); CTextureFile *pTF = dynamic_cast<CTextureFile*>(pIT); if (pTF != NULL) { string sTexName = NLMISC::strlwr(getBaseName(pTF->getFileName())); string sTexNameMoved = NLMISC::strlwr(getBaseName(AllLightmapNames[i])); if (sTexName == sTexNameMoved) { string sNewTexName = NLMISC::strlwr(getBaseName(AllLightmapNames[j])); sNewTexName += NLMISC::toString(getLayerNb(pTF->getFileName())) + ".tga"; pTF->setFileName (sNewTexName); } } ++stage; } } } // We have now the list of vertices to remap for all material that have been changed // So parse this list and apply the transformation : (uv * TexSizeI + decalXY) / TexSizeJ for (m = 0; m < (sint32)VerticesNeedRemap.size(); ++m) { CVertexBuffer *pVB; if (pMesh != NULL) { pVB = const_cast<CVertexBuffer*>(&pMesh->getMeshGeom().getVertexBuffer()); } else if (pMeshMRM != NULL) { pVB = const_cast<CVertexBuffer*>(&pMeshMRM->getMeshGeom().getVertexBuffer()); } else if (pMeshML != NULL) { const CMeshGeom *pMG = dynamic_cast<const CMeshGeom*>(&pMeshML->getMeshGeom(m)); pVB = const_cast<CVertexBuffer*>(&pMG->getVertexBuffer()); } CVertexBufferReadWrite vba; pVB->lock (vba); vector<bool> &rVNR = VerticesNeedRemap[m]; for (n = 0; n < (sint32)rVNR.size(); ++n) if (rVNR[n]) { CUV *pUV = (CUV*)vba.getTexCoordPointer (n,1); pUV->U = (pUV->U*pBI->getWidth() + x) / pBJ->getWidth(); pUV->V = (pUV->V*pBI->getHeight() + y) / pBJ->getHeight(); bMustSave = true; } } if (bMustSave) { try { if (AllShapes[k]) { CShapeStream mesh; mesh.setShapePointer (AllShapes[k]); NLMISC::COFile meshfile (AllShapeNames[k]); meshfile.serial (mesh); meshfile.close (); } } catch (NLMISC::EPathNotFound &e) { outString(string("ERROR: cannot save shape ")+AllShapeNames[k]+" - "+e.what()); return -1; } } } SetCurrentDirectory (sLMPDir); // Get out of the j loop break; } } // if assigned to another bitmap -> delete the bitmap i if (bAssigned) { // Delete Names && tags for (j = i+1; j < (sint32)AllLightmapNames.size(); ++j) { AllLightmapNames[j-1] = AllLightmapNames[j]; AllLightmapTags[j-1] = AllLightmapTags[j]; } AllLightmapNames.resize (AllLightmapNames.size()-1); AllLightmapTags.resize (AllLightmapTags.size()-1); // Delete Lightmaps delete AllLightmaps[i]; for (j = i+1; j < (sint32)AllLightmaps.size(); ++j) AllLightmaps[j-1] = AllLightmaps[j]; AllLightmaps.resize (AllLightmaps.size()-1); i = i - 1; } } } // **** Additionally, output or clear a "flag file" in a dir to info if a 8bit lihgtmap or not if (nNbArg >=5 && ppArgs[4] && strlen(ppArgs[4]) > 0) { SetCurrentDirectory (sExeDir); // out a text file, with list of FILE *out= fopen(ppArgs[4], "wt"); if(!out) { outString(string("ERROR: cannot save ")+ppArgs[4]); } set<string>::iterator it(setLM8Bit.begin()), end(setLM8Bit.end()); for(;it!=end;it++) { string temp= (*it); temp+= "\n"; fputs(temp.c_str(), out); } fclose(out); } return 0; }
int main(int argc, char* argv[]) { // Filter addSearchPath NLMISC::createDebug(); InfoLog->addNegativeFilter ("adding the path"); // Register 3d registerSerial3d (); // Good number of args ? if (argc<5) { // Help message printf ("%s [zonein.zonel] [igout.ig] [parameter_file] [dependancy_file]\n", argv[0]); } else { // Ok, read the zone CIFile inputFile; // Get extension string ext=getExt (argv[1]); string dir=getDir (argv[1]); // Open it for reading if (inputFile.open (argv[1])) { // Zone name string zoneName=toLower (string ("zone_"+getName (argv[1]))); // Load the zone try { // Read the config file CConfigFile parameter; // Load and parse the parameter file parameter.load (argv[3]); // ********** // *** Build the lighter descriptor // ********** CInstanceLighter::CLightDesc lighterDesc; // Light direction CConfigFile::CVar &sun_direction = parameter.getVar ("sun_direction"); lighterDesc.LightDirection.x=sun_direction.asFloat(0); lighterDesc.LightDirection.y=sun_direction.asFloat(1); lighterDesc.LightDirection.z=sun_direction.asFloat(2); lighterDesc.LightDirection.normalize (); // Grid size CConfigFile::CVar &quad_grid_size = parameter.getVar ("quad_grid_size"); lighterDesc.GridSize=quad_grid_size.asInt(); // Grid size CConfigFile::CVar &quad_grid_cell_size = parameter.getVar ("quad_grid_cell_size"); lighterDesc.GridCellSize=quad_grid_cell_size.asFloat(); // Shadows enabled ? CConfigFile::CVar &shadow = parameter.getVar ("shadow"); lighterDesc.Shadow=shadow.asInt ()!=0; // OverSampling CConfigFile::CVar &ig_oversampling = parameter.getVar ("ig_oversampling"); lighterDesc.OverSampling= ig_oversampling.asInt (); // validate value: 0, 2, 4, 8, 16 lighterDesc.OverSampling= raiseToNextPowerOf2(lighterDesc.OverSampling); clamp(lighterDesc.OverSampling, 0U, 16U); if(lighterDesc.OverSampling<2) lighterDesc.OverSampling= 0; // For ig of Zones, never disable Sun contrib !!! lighterDesc.DisableSunContribution= false; // Get the search pathes CConfigFile::CVar &search_pathes = parameter.getVar ("search_pathes"); uint path; for (path = 0; path < (uint)search_pathes.size(); path++) { // Add to search path CPath::addSearchPath (search_pathes.asString(path)); } // A landscape allocated with new: it is not delete because destruction take 3 secondes more! CLandscape *landscape=new CLandscape; landscape->init(); // A zone lighter CMyIgZoneLighter lighter; lighter.init (); // A vector of zone id vector<uint> listZoneId; // The zone CZone zone; // List of ig std::list<CInstanceGroup*> instanceGroup; // Load zone.serial (inputFile); inputFile.close(); // Load ig of the zone string igName = getName (argv[1])+".ig"; string igNameLookup = CPath::lookup (igName, false, false); if (!igNameLookup.empty()) igName = igNameLookup; bool zoneIgLoaded; // Try to open the file CInstanceGroup *centerInstanceGroup= NULL; if (inputFile.open (igName)) { // load the center ig centerInstanceGroup=new CInstanceGroup; // Serial it centerInstanceGroup->serial (inputFile); inputFile.close(); // Add to the list instanceGroup.push_back (centerInstanceGroup); zoneIgLoaded = true; } else { // Warning fprintf (stderr, "Warning: can't load instance group %s\n", igName.c_str()); zoneIgLoaded = false; } // If can't load the center instanceGroup, skip it. if(!zoneIgLoaded) return 0; // Get bank path CConfigFile::CVar &bank_name_var = parameter.getVar ("bank_name"); string bank_name = bank_name_var.asString (); string bank_name_lookup = CPath::lookup (bank_name); if (!bank_name_lookup.empty()) bank_name = bank_name_lookup; // Load the bank if (inputFile.open (bank_name)) { try { // Load landscape->TileBank.serial (inputFile); landscape->initTileBanks(); } catch (const Exception &e) { // Error nlwarning ("ERROR error loading tile bank %s\n%s\n", bank_name.c_str(), e.what()); } } else { // Error nlwarning ("ERROR can't load tile bank %s\n", bank_name.c_str()); } // Add the zone landscape->addZone (zone); listZoneId.push_back (zone.getZoneId()); // Load instance group ? CConfigFile::CVar &load_ig= parameter.getVar ("load_ig"); bool loadInstanceGroup = load_ig.asInt ()!=0; // Continue to build ? bool continu=true; // Try to load additionnal instance group. if (loadInstanceGroup) { // Additionnal instance group try { CConfigFile::CVar &additionnal_ig = parameter.getVar ("additionnal_ig"); for (uint add=0; add<(uint)additionnal_ig.size(); add++) { // Input file CIFile inputFile; // Name of the instance group string name = additionnal_ig.asString(add); string nameLookup = CPath::lookup (name, false, false); if (!nameLookup.empty()) name = nameLookup; // Try to open the file if (inputFile.open (name)) { // New ig CInstanceGroup *group=new CInstanceGroup; // Serial it group->serial (inputFile); inputFile.close(); // Add to the list instanceGroup.push_back (group); } else { // Error nlwarning ("ERROR can't load instance group %s\n", name.c_str()); // Stop before build continu=false; } } } catch (const NLMISC::EUnknownVar &) { nlinfo("No additionnal ig's to load"); } } // Shadow ? if (lighterDesc.Shadow) { // Load and parse the dependency file CConfigFile dependency; dependency.load (argv[4]); // *** Scan dependency file CConfigFile::CVar &dependant_zones = dependency.getVar ("dependencies"); for (uint i=0; i<(uint)dependant_zones.size(); i++) { // Get zone name string zoneName=dependant_zones.asString(i); // Load the zone CZone zoneBis; // Open it for reading if (inputFile.open (dir+zoneName+ext)) { // Read it zoneBis.serial (inputFile); inputFile.close(); // Add the zone landscape->addZone (zoneBis); listZoneId.push_back (zoneBis.getZoneId()); } else { // Error message and continue nlwarning ("ERROR can't load zone %s\n", (dir+zoneName+ext).c_str()); } // Try to load an instance group. if (loadInstanceGroup) { string name = zoneName+".ig"; string nameLookup = CPath::lookup (name, false, false); if (!nameLookup.empty()) name = nameLookup; // Name of the instance group if (inputFile.open (name)) { // New ig CInstanceGroup *group=new CInstanceGroup; // Serial it group->serial (inputFile); inputFile.close(); // Add to the list instanceGroup.push_back (group); } else { // Error message and continue nlwarning ("WARNING can't load instance group %s\n", name.c_str()); } } } } // A vector of CInstanceLighter::CTriangle vector<CInstanceLighter::CTriangle> vectorTriangle; // ********** // *** Build triangle array // ********** landscape->checkBinds (); // Add triangles from landscape, for pointLight lighting. landscape->enableAutomaticLighting (false); lighter.addTriangles (*landscape, listZoneId, 0, vectorTriangle); // Load and add shapes // Map of shape std::map<string, IShape*> shapeMap; // For each instance group std::list<CInstanceGroup*>::iterator ite=instanceGroup.begin(); while (ite!=instanceGroup.end()) { // Instance group CInstanceGroup *group=*ite; // For each instance for (uint instance=0; instance<group->getNumInstance(); instance++) { // Get the instance shape name string name=group->getShapeName (instance); // Skip it?? use the DontCastShadowForExterior flag. See doc of this flag if(group->getInstance(instance).DontCastShadow || group->getInstance(instance).DontCastShadowForExterior) continue; // Add a .shape at the end ? if (!name.empty()) { if (name.find('.') == std::string::npos) name += ".shape"; // Find the file string nameLookup = CPath::lookup (name, false, false); if (!nameLookup.empty()) name = nameLookup; // Find the shape in the bank std::map<string, IShape*>::iterator iteMap=shapeMap.find (name); if (iteMap==shapeMap.end()) { // Input file CIFile inputFile; if (inputFile.open (name)) { // Load it CShapeStream stream; stream.serial (inputFile); // Get the pointer iteMap=shapeMap.insert (std::map<string, IShape*>::value_type (name, stream.getShapePointer ())).first; } else { // Error nlwarning ("WARNING can't load shape %s\n", name.c_str()); } } // Loaded ? if (iteMap!=shapeMap.end()) { // Build the matrix CMatrix scale; scale.identity (); scale.scale (group->getInstanceScale (instance)); CMatrix rot; rot.identity (); rot.setRot (group->getInstanceRot (instance)); CMatrix pos; pos.identity (); pos.setPos (group->getInstancePos (instance)); CMatrix mt=pos*rot*scale; // If centerInstanceGroup, take good instanceId, to avoid selfShadowing sint instanceId; if(group == centerInstanceGroup) instanceId= instance; else instanceId= -1; // Add triangles lighter.addTriangles (*iteMap->second, mt, vectorTriangle, instanceId); } } } // For each point light of the ig const std::vector<CPointLightNamed> &pointLightList= group->getPointLightList(); for (uint plId=0; plId<pointLightList.size(); plId++) { // Add it to the Ig. lighter.addStaticPointLight(pointLightList[plId], igName.c_str ()); } // Next instance group ite++; } // Continue ? if (continu) { // ********** // *** Light! // ********** // Start time TTime time=CTime::getLocalTime (); // Output ig CInstanceGroup output; // Light the zone lighter.light (*centerInstanceGroup, output, lighterDesc, vectorTriangle, landscape); // Compute time printf ("\rCompute time: %d ms \r", (uint)(CTime::getLocalTime ()-time)); // Save the zone COFile outputFile; // Open it if (outputFile.open (argv[2])) { try { // Save the new ig outputFile.serial(output); } catch (const Exception& except) { // Error message nlwarning ("ERROR writing %s: %s\n", argv[2], except.what()); } } else { // Error can't open the file nlwarning ("ERROR Can't open %s for writing\n", argv[2]); } } else { // Error nlwarning ("ERROR Abort: files are missing.\n"); } } catch (const Exception& except) { // Error message nlwarning ("ERROR %s\n", except.what()); } } else { // Error can't open the file nlwarning ("ERROR Can't open %s for reading\n", argv[1]); } } // Landscape is not deleted, nor the instanceGroups, for faster quit. // Must disalbe BlockMemory checks (for pointLights). NL3D_BlockMemoryAssertOnPurge= false; // exit. return 0; }
/* * init() */ bool CPrimChecker::build(const string &primitivesPath, const string &igLandPath, const string &igVillagePath, const string &outputDirectory, bool forceRebuild) { if (Verbose) nlinfo("Checking pacs.packed_prims consistency"); NLLIGO::Register(); // Init ligo if (!LigoConfig.readPrimitiveClass ("world_editor_classes.xml", false)) { // Should be in l:\leveldesign\world_edit_files nlwarning ("Can't load ligo primitive config file world_editor_classes.xml"); return false; } uint i, j; string outputfname = CPath::standardizePath(outputDirectory)+"pacs.packed_prims"; _Grid.clear(); vector<string> files; CPath::getPathContent(primitivesPath, true, false, true, files); for (i=0; i<files.size(); ++i) { if (CFile::getExtension(files[i]) == "primitive") { readFile(files[i]); } } files.clear(); CPath::getPathContent(igLandPath, true, false, true, files); CPath::getPathContent(igVillagePath, true, false, true, files); set<string> noWaterShapes; for (i=0; i<files.size(); ++i) { try { // load ig associated to the zone string igname = files[i]; string ignamelookup = CPath::lookup(igname); //nlinfo("Reading ig '%s'", ignamelookup.c_str()); CIFile igStream(ignamelookup); CInstanceGroup ig; igStream.serial(ig); // search in group for water instance for (j=0; j<ig._InstancesInfos.size(); ++j) { string shapeName = ig._InstancesInfos[j].Name; if (CFile::getExtension (shapeName) == "") shapeName += ".shape"; if (noWaterShapes.find(shapeName) != noWaterShapes.end()) continue; string shapeNameLookup = CPath::lookup (shapeName, false, false); if (!shapeNameLookup.empty()) { CIFile f; if (f.open (shapeNameLookup)) { CShapeStream shape; shape.serial(f); CWaterShape *wshape = dynamic_cast<CWaterShape*>(shape.getShapePointer()); if (wshape == NULL) { noWaterShapes.insert(shapeName); continue; } //nlinfo("Render water shape '%s'", shapeNameLookup.c_str()); CMatrix matrix; ig.getInstanceMatrix(j, matrix); CPolygon wpoly; //wshape->getShapeInWorldSpace(wpoly); CPolygon2D wpoly2d = wshape->getShape(); uint k; for (k=0; k<wpoly2d.Vertices.size(); ++k) { wpoly.Vertices.push_back(matrix * wpoly2d.Vertices[k]); } float zwater = wpoly.Vertices[0].z - WaterThreshold; uint16 idx = (uint16)_WaterHeight.size(); _WaterHeight.push_back(zwater); render(wpoly, idx); if (Verbose) nlinfo("Rendered water shape '%s' in instance '%s'", CFile::getFilenameWithoutExtension(shapeName).c_str(), CFile::getFilenameWithoutExtension(igname).c_str()); } else if (Verbose) { noWaterShapes.insert(shapeName); nlwarning ("Can't load shape %s", shapeNameLookup.c_str()); } } else if (Verbose) { noWaterShapes.insert(shapeName); nlwarning ("Can't find shape %s", shapeName.c_str()); } } } catch (const Exception &e) { nlwarning("%s", e.what()); } } COFile f; if (f.open(outputfname)) { f.serial(_Grid); f.serialCont(_WaterHeight); } else { nlwarning("Couldn't save pacs.packed_prims file '%s'", outputfname.c_str()); } return true; }
void CResourceManager::loadChildren(const std::string &filename) { string ext = CFile::getExtension(filename); if(ext == "shape") { // need to get texture inside the shape NL3D::registerSerial3d(); CShapeStream ss; NLMISC::CIFile i(CPath::lookup(filename, false).c_str()); i.serial(ss); i.close(); CMesh *m = (CMesh*)ss.getShapePointer(); uint nbm = m->getNbMaterial(); for(uint i = 0; i < nbm; i++) { CMaterial &mat = m->getMaterial(i); for(uint j = 0; j < IDRV_MAT_MAXTEXTURES; j++) { ITexture *t = mat.getTexture(j); if(t) { CTextureFile *tf = dynamic_cast<CTextureFile *>(t); if(tf) { get(tf->getFileName()); } else { CTextureMultiFile *tmf = dynamic_cast<CTextureMultiFile *>(t); if(tmf) { for(uint t = 0; t < tmf->getNumFileName(); t++) get(tmf->getFileName(t)); } } } } } } else if(ext == "ps") { // need to get texture inside the shape NL3D::registerSerial3d(); string fn = CFile::getFilename(filename); CShapeBank *bank = new CShapeBank; string shapeCache("mtptShapeCache"); bank->addShapeCache(shapeCache); bank->setShapeCacheSize(shapeCache,1024*1024); std::vector<std::string> filelist; filelist.push_back(filename); CDriverUser *drv = (CDriverUser *)(&C3DTask::getInstance().driver()); bank->preLoadShapes(shapeCache,filelist,string("*.ps"),NULL,true,drv->getDriver()); bool b = bank->isShapeWaiting(); IShape *is = bank->getShape(fn); //bank->load(filename) CParticleSystemShape *ps = (CParticleSystemShape *)is; uint numTexture = ps->getNumCachedTextures(); nlinfo("loadchildren(%s) : num texture = %d",filename.c_str(),numTexture); for(uint i=0;i<numTexture;i++) { ITexture *tex = ps->getCachedTexture(i); CTextureFile *utex = (CTextureFile *)tex; nlinfo("loadchildren(%s) : texture = %s",filename.c_str(),utex->getFileName().c_str()); get(utex->getFileName()); } bank->reset(); delete bank; } }