// *************************************************************************** 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) { if (argc != 2) { printf("usage : %s file.ig\n", argv[0]); return -1; } try { uint k; CInstanceGroup ig; CIFile inputStream; if (!inputStream.open(string(argv[1]))) { printf("unable to open %s\n", argv[1]); return -1; } ig.serial(inputStream); printf("Origine\n"); printf("---------\n"); CVector gpos = ig.getGlobalPos(); printf("global pos : x = %.1f, y = %.1f, z =%.1f\n", gpos.x, gpos.y, gpos.z); printf("Instances\n"); printf("---------\n"); for(k = 0; k < ig._InstancesInfos.size(); ++k) { printf("instance %s : x = %.1f, y = %.1f, z = %.1f, sx = %.1f, sy = %.1f, sz = %.1f\n", ig._InstancesInfos[k].Name.c_str(), ig._InstancesInfos[k].Pos.x + gpos.x, ig._InstancesInfos[k].Pos.y + gpos.y, ig._InstancesInfos[k].Pos.z + gpos.z, ig._InstancesInfos[k].Scale.x, ig._InstancesInfos[k].Scale.y, ig._InstancesInfos[k].Scale.z); } printf("\n"); printf("Lights\n"); printf("---------\n"); for(k = 0; k < ig.getNumPointLights(); ++k) { const CPointLightNamed &pl = ig.getPointLightNamed(k); printf("light group = %d, anim = \"%s\" x = %.1f, y = %.1f, z = %.1f\n", pl.LightGroup, pl.AnimatedLight.c_str(), pl.getPosition().x + gpos.x, pl.getPosition().y + gpos.y, pl.getPosition().z + gpos.z); } printf("---------\n"); printf("Realtime sun contribution = %s\n", ig.getRealTimeSunContribution() ? "on" : "off"); printf("---------\n"); // IGSurfaceLight info. const CIGSurfaceLight::TRetrieverGridMap &rgm= ig.getIGSurfaceLight().getRetrieverGridMap(); printf("IGSurfaceLighting: CellSize: %f. NumGridRetriever: %u\n", ig.getIGSurfaceLight().getCellSize(), (uint)rgm.size() ); uint rgmInst= 0; uint totalCells= 0; CIGSurfaceLight::TRetrieverGridMap::const_iterator it= rgm.begin(); for(;it!=rgm.end();it++) { for(uint i=0;i<it->second.Grids.size();i++) { printf("grid(%d, %d): %dx%d\n", rgmInst, i, it->second.Grids[i].Width, it->second.Grids[i].Height ); totalCells+= it->second.Grids[i].Cells.size(); } rgmInst++; } printf("TotalCells: %d\n", totalCells); } catch (const std::exception &e) { printf("%s\n", e.what()); } }
// --------------------------------------------------------------------------- int main(int nNbArg, char**ppArgs) { if (!NLMISC::INelContext::isContextInitialised()) new CApplicationContext(); NL3D_BlockMemoryAssertOnPurge = false; char sCurDir[MAX_PATH]; getcwd (sCurDir, MAX_PATH); if (nNbArg != 2) { printf ("Use : ig_elevation configfile.cfg\n"); printf ("\nExample of config.cfg\n\n"); printf ("InputIGDir = \"ig_land_max\";\n"); printf ("OutputIGDir = \"ig_land_max_elev\";\n"); printf ("CellSize = 160.0;\n"); printf ("HeightMapFile1 = \"w:/database/landscape/ligo/jungle/big.tga\";\n"); printf ("ZFactor1 = 1.0;\n"); printf ("HeightMapFile2 = \"w:/database/landscape/ligo/jungle/noise.tga\";\n"); printf ("ZFactor2 = 0.5;\n"); printf ("LandFile = \"w:/matis.land\";\n"); return -1; } SExportOptions options; if (!options.load(ppArgs[1])) { return -1; } // Get all ig files in the input directory and elevate to the z of the double heightmap // Load the land CZoneRegion *ZoneRegion = loadLand(options.LandFile); CZoneLimits zl; if (ZoneRegion) { zl._ZoneMinX = ZoneRegion->getMinX() < 0 ? 0 : ZoneRegion->getMinX(); zl._ZoneMaxX = ZoneRegion->getMaxX() > 255 ? 255 : ZoneRegion->getMaxX(); zl._ZoneMinY = ZoneRegion->getMinY() > 0 ? 0 : ZoneRegion->getMinY(); zl._ZoneMaxY = ZoneRegion->getMaxY() < -255 ? -255 : ZoneRegion->getMaxY(); } else { nlwarning("A ligo .land file cannot be found"); zl._ZoneMinX = 0; zl._ZoneMaxX = 255; zl._ZoneMinY = 0; zl._ZoneMaxY = 255; } // Load the 2 height maps CBitmap *HeightMap1 = NULL; if (!options.HeightMapFile1.empty()) { HeightMap1 = new CBitmap; try { CIFile inFile; if (inFile.open(options.HeightMapFile1)) { HeightMap1->load (inFile); } else { string sTmp = string("Couldn't not open ")+string(options.HeightMapFile1) +string(" : heightmap 1 map ignored"); outString(sTmp); delete HeightMap1; HeightMap1 = NULL; } } catch (const Exception &e) { string sTmp = string("Cant load height map : ") + options.HeightMapFile1 + " : " + e.what(); outString (sTmp); delete HeightMap1; HeightMap1 = NULL; } } CBitmap *HeightMap2 = NULL; if (!options.HeightMapFile2.empty()) { HeightMap2 = new CBitmap; try { CIFile inFile; if (inFile.open(options.HeightMapFile2)) { HeightMap2->load (inFile); } else { string sTmp = string("Couldn't not open ")+string(options.HeightMapFile2) +string(" : heightmap 2 map ignored\n"); outString(sTmp); delete HeightMap2; HeightMap2 = NULL; } } catch (const Exception &e) { string sTmp = string("Cant load height map : ") + options.HeightMapFile2 + " : " + e.what() + "\n"; outString (sTmp); delete HeightMap2; HeightMap1 = NULL; } } // Get all files vector<string> vAllFiles; chdir (options.InputIGDir.c_str()); dir (".ig", vAllFiles, false); chdir (sCurDir); for (uint32 i = 0; i < vAllFiles.size(); ++i) { chdir (options.InputIGDir.c_str()); CInstanceGroup *pIG = LoadInstanceGroup (vAllFiles[i].c_str()); chdir (sCurDir); if (pIG != NULL) { bool realTimeSunContribution = pIG->getRealTimeSunContribution(); // For all instances !!! CVector vGlobalPos; CInstanceGroup::TInstanceArray IA; vector<CCluster> Clusters; vector<CPortal> Portals; vector<CPointLightNamed> PLN; pIG->retrieve (vGlobalPos, IA, Clusters, Portals, PLN); if (IA.empty() && PLN.empty() && Portals.empty() && Clusters.empty()) continue; uint k; // elevate instance for(k = 0; k < IA.size(); ++k) { CVector instancePos = vGlobalPos + IA[k].Pos; IA[k].Pos.z += getHeightMapZ(instancePos.x, instancePos.y, zl, options, HeightMap1, HeightMap2); } // lights for(k = 0; k < PLN.size(); ++k) { CVector lightPos = vGlobalPos + PLN[k].getPosition(); PLN[k].setPosition( PLN[k].getPosition() + getHeightMapZ(lightPos.x, lightPos.y, zl, options, HeightMap1, HeightMap2) * CVector::K); } // portals std::vector<CVector> portal; for(k = 0; k < Portals.size(); ++k) { Portals[k].getPoly(portal); if (portal.empty()) { nlwarning("Empty portal found"); continue; } // compute mean position of the poly CVector meanPos(0, 0, 0); uint l; for(l = 0; l < portal.size(); ++l) meanPos += portal[l]; meanPos /= (float) portal.size(); meanPos += vGlobalPos; float z = getHeightMapZ(meanPos.x, meanPos.y, zl, options, HeightMap1, HeightMap2); for(l = 0; l < portal.size(); ++l) { portal[l].z += z; } Portals[k].setPoly(portal); } // clusters std::vector<CPlane> volume; CMatrix transMatrix; for(k = 0; k < Clusters.size(); ++k) { CVector clusterPos = vGlobalPos + Clusters[k].getBBox().getCenter(); float z = getHeightMapZ(clusterPos.x, clusterPos.y, zl, options, HeightMap1, HeightMap2); transMatrix.setPos(z * CVector::K); Clusters[k].applyMatrix(transMatrix); } CInstanceGroup *pIGout = new CInstanceGroup; pIGout->build (vGlobalPos, IA, Clusters, Portals, PLN); pIGout->enableRealTimeSunContribution(realTimeSunContribution); chdir (options.OutputIGDir.c_str()); SaveInstanceGroup (vAllFiles[i].c_str(), pIGout); chdir (sCurDir); delete pIG; } } return 1; }