//********************************************************************************************** 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()); } } } } }
bool CNelExport::exportSkeleton (const char *sPath, INode* pNode, TimeValue time) { // Result to return bool bRet=false; // Build the skeleton format CSkeletonShape *skeletonShape=new CSkeletonShape(); TInodePtrInt mapId; _ExportNel->buildSkeletonShape (*skeletonShape, *pNode, NULL, mapId, time); // Open a file COFile file; if (file.open (sPath)) { try { // Create a streamable shape CShapeStream shapeStream (skeletonShape); // Serial the shape shapeStream.serial (file); // All is good bRet=true; } catch (Exception &e) { nlwarning (e.what()); } } // Delete the pointer delete skeletonShape; return bRet; }
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; }
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; }
bool CNelExport::exportMesh (const char *sPath, INode& node, TimeValue time) { // Result to return bool bRet=false; // Eval the object a time ObjectState os = node.EvalWorldState(time); // Object exist ? if (os.obj) { // Skeleton shape CSkeletonShape *skeletonShape=NULL; TInodePtrInt *mapIdPtr=NULL; TInodePtrInt mapId; // If model skinned ? if (CExportNel::isSkin (node)) { // Create a skeleton INode *skeletonRoot=CExportNel::getSkeletonRootBone (node); // Skeleton exist ? if (skeletonRoot) { // Build a skeleton skeletonShape=new CSkeletonShape(); // Add skeleton bind pos info CExportNel::mapBoneBindPos boneBindPos; CExportNel::addSkeletonBindPos (node, boneBindPos); // Build the skeleton based on the bind pos information _ExportNel->buildSkeletonShape (*skeletonShape, *skeletonRoot, &boneBindPos, mapId, time); // Set the pointer to not NULL mapIdPtr=&mapId; // Erase the skeleton if (skeletonShape) delete skeletonShape; } } DWORD t = timeGetTime(); if (InfoLog) InfoLog->display("Beg buildShape %s \n", node.GetName()); // Export in mesh format IShape* pShape=_ExportNel->buildShape (node, time, mapIdPtr, true); if (InfoLog) InfoLog->display("End buildShape in %d ms \n", timeGetTime()-t); // Conversion success ? if (pShape) { // Open a file COFile file; if (file.open (sPath)) { try { // Create a streamable shape CShapeStream shapeStream (pShape); // Serial the shape shapeStream.serial (file); // All is good bRet=true; } catch (...) { } } // Delete the pointer delete pShape; } } return bRet; }
/* * 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; }