Пример #1
0
//**********************************************************************************************
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());
				}
			}			
		}				
	}
}
Пример #2
0
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;
}
Пример #4
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;
}
Пример #6
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;
}
Пример #7
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;
}
Пример #8
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;
}