Exemplo n.º 1
0
//============================================
void CWaterShape::getShapeInWorldSpace(NLMISC::CPolygon &poly) const
{
	poly.Vertices.resize(_Poly.Vertices.size());
	// compute the matrix of the object in world space, by using the default tracks
	NLMISC::CMatrix objMat;
	objMat.identity();
	objMat.translate(_DefaultPos.getDefaultValue());
	objMat.rotate(_DefaultRotQuat.getDefaultValue());
	objMat.scale(_DefaultScale.getDefaultValue());

	for (uint k = 0; k < _Poly.Vertices.size(); ++k)
	{
		poly.Vertices[k] = objMat * NLMISC::CVector(_Poly.Vertices[k].x, _Poly.Vertices[k].y, 0);
	}
}
/** Load and compute the bbox of the models that are contained in a given instance group
  * \return true if the computed bbox is valid
  */
static void computeIGBBox(const NL3D::CInstanceGroup &ig, CLightingBBox &result, TShapeMap &shapeMap)
{
	result = CLightingBBox(); // starts with void result
	bool firstBBox = true;	
	/// now, compute the union of all bboxs
	for (CInstanceGroup::TInstanceArray::const_iterator it = ig._InstancesInfos.begin(); it != ig._InstancesInfos.end(); ++it)
	{		
		CLightingBBox currBBox;
		
		bool validBBox = false;
		/// get the bbox from file or from map
		if (shapeMap.count(it->Name)) // already loaded ?
		{
			currBBox = shapeMap[it->Name];
			validBBox = true;
		}
		else // must load the shape to get its bbox
		{		
			std::string shapePathName;
			std::string toLoad = it->Name;
			if (getExt(toLoad).empty()) toLoad += ".shape";
			shapePathName = NLMISC::CPath::lookup(toLoad, false, false);

			if (shapePathName.empty())
			{
				nlwarning("Unable to find shape %s", it->Name.c_str());				
			}
			else
			{
				CIFile shapeInputFile;
				
				if (shapeInputFile.open (shapePathName.c_str()))
				{					
					NL3D::CShapeStream shapeStream;
					try
					{
						shapeStream.serial (shapeInputFile);
						// NB Nico :
						// Deal with water shape -> their 'Receiving' box is set to 'void'
						// this prevent the case where a huge surface of water will cause the zone it is attached to (the 'Zone'
						// field in the villages sheets) to load all the zones that the water surface cover. (This caused
						// an 'out of memory error' in the zone lighter due to too many zone being loaded)
						
						// FIXME : test for water case hardcoded for now						
						CWaterShape *ws = dynamic_cast<CWaterShape *>(shapeStream.getShapePointer());
						if (ws)
						{
							CAABBox bbox;
							shapeStream.getShapePointer()->getAABBox(bbox);
							currBBox.OccludingBox = CPotentialBBox(bbox); // occluding box is used, though the water shape
																		 // doesn't cast shadow -> the tiles flag ('above', 'intersect', 'below water')
																		 // are updated inside the zone_lighter
							currBBox.ReceivingBox.IsVoid = true; // no lighted by the zone lighter !!!
							currBBox.removeVoid();
							shapeMap[it->Name] = currBBox;							
						}
						else
						{

							CAABBox bbox;
							shapeStream.getShapePointer()->getAABBox(bbox);
							currBBox.OccludingBox = CPotentialBBox(bbox);
							currBBox.ReceivingBox = CPotentialBBox(bbox);
							currBBox.removeVoid();
							shapeMap[it->Name] = currBBox;
						}
						validBBox = true;
					}
					
					catch (NLMISC::Exception &e)
					{
						nlwarning("Error while loading shape %s. \n\t Reason : %s ", it->Name.c_str(), e.what());
					}				
				}
				else
				{
					nlwarning("Unable to open shape file %s to get its bbox", it->Name.c_str());
				}
			}
		}


		if (validBBox)
		{
			/// build the model matrix
			NLMISC::CMatrix mat;
			mat.scale(it->Scale);
			NLMISC::CMatrix rotMat;
			rotMat.setRot(it->Rot);
			mat = rotMat * mat;
			mat.setPos(it->Pos);

			/// transform the bbox
			currBBox.transform(mat);
			currBBox.removeVoid();			
			if (firstBBox)
			{
				result = currBBox;
				firstBBox = false;
			}
			else // add to previous one
			{						
				result.makeUnion(currBBox);
			}			
		}		
	}	
}