Ejemplo n.º 1
0
// LoadMap: try to load the map from given file; reinitialise the scene to new data if successful
void CMapReader::LoadMap(const VfsPath& pathname, CTerrain *pTerrain_,
						 WaterManager* pWaterMan_, SkyManager* pSkyMan_,
						 CLightEnv *pLightEnv_, CGameView *pGameView_, CCinemaManager* pCinema_, CTriggerManager* pTrigMan_,
						 CSimulation2 *pSimulation2_, const CSimContext* pSimContext_, int playerID_, bool skipEntities)
{
	// latch parameters (held until DelayedLoadFinished)
	pTerrain = pTerrain_;
	pLightEnv = pLightEnv_;
	pGameView = pGameView_;
	pWaterMan = pWaterMan_;
	pSkyMan = pSkyMan_;
	pCinema = pCinema_;
	pTrigMan = pTrigMan_;
	pSimulation2 = pSimulation2_;
	pSimContext = pSimContext_;
	m_PlayerID = playerID_;
	m_SkipEntities = skipEntities;
	m_StartingCameraTarget = INVALID_ENTITY;

	filename_xml = pathname.ChangeExtension(L".xml");

	// In some cases (particularly tests) we don't want to bother storing a large
	// mostly-empty .pmp file, so we let the XML file specify basic terrain instead.
	// If there's an .xml file and no .pmp, then we're probably in this XML-only mode
	only_xml = false;
	if (!VfsFileExists(pathname) && VfsFileExists(filename_xml))
	{
		only_xml = true;
	}

	file_format_version = CMapIO::FILE_VERSION; // default if there's no .pmp

	if (!only_xml)
	{
		// [25ms]
		unpacker.Read(pathname, "PSMP");
		file_format_version = unpacker.GetVersion();
	}

	// check oldest supported version
	if (file_format_version < FILE_READ_VERSION)
		throw PSERROR_File_InvalidVersion();

	// delete all existing entities
	if (pSimulation2)
		pSimulation2->ResetState();

	// load map settings script
	RegMemFun(this, &CMapReader::LoadScriptSettings, L"CMapReader::LoadScriptSettings", 50);

	// load player settings script (must be done before reading map)
	RegMemFun(this, &CMapReader::LoadPlayerSettings, L"CMapReader::LoadPlayerSettings", 50);

	// unpack the data
	if (!only_xml)
		RegMemFun(this, &CMapReader::UnpackMap, L"CMapReader::UnpackMap", 1200);

	// read the corresponding XML file
	RegMemFun(this, &CMapReader::ReadXML, L"CMapReader::ReadXML", 5800);

	// apply data to the world
	RegMemFun(this, &CMapReader::ApplyData, L"CMapReader::ApplyData", 5);

	// load map settings script (must be done after reading map)
	RegMemFun(this, &CMapReader::LoadMapSettings, L"CMapReader::LoadMapSettings", 5);

	RegMemFun(this, &CMapReader::DelayLoadFinished, L"CMapReader::DelayLoadFinished", 5);
}
Ejemplo n.º 2
0
// Load: read and return a new CModelDef initialised with data from given file
CModelDef* CModelDef::Load(const VfsPath& filename, const VfsPath& name)
{
	CFileUnpacker unpacker;

	// read everything in from file
	unpacker.Read(filename,"PSMD");
			
	// check version
	if (unpacker.GetVersion()<FILE_READ_VERSION) {
		throw PSERROR_File_InvalidVersion();
	}

	std::auto_ptr<CModelDef> mdef (new CModelDef());
	mdef->m_Name = name;

	// now unpack everything 
	mdef->m_NumVertices = unpacker.UnpackSize();
	mdef->m_pVertices=new SModelVertex[mdef->m_NumVertices];
	unpacker.UnpackRaw(mdef->m_pVertices,sizeof(SModelVertex)*mdef->m_NumVertices);
	
	mdef->m_NumFaces = unpacker.UnpackSize();
	mdef->m_pFaces=new SModelFace[mdef->m_NumFaces];
	unpacker.UnpackRaw(mdef->m_pFaces,sizeof(SModelFace)*mdef->m_NumFaces);
	
	mdef->m_NumBones = unpacker.UnpackSize();
	if (mdef->m_NumBones)
	{
		mdef->m_Bones=new CBoneState[mdef->m_NumBones];
		unpacker.UnpackRaw(mdef->m_Bones,mdef->m_NumBones*sizeof(CBoneState));

		mdef->m_pBlendIndices = new size_t[mdef->m_NumVertices];
		std::vector<SVertexBlend> blends;
		for (size_t i = 0; i < mdef->m_NumVertices; i++)
		{
			const SVertexBlend &blend = mdef->m_pVertices[i].m_Blend;
			if (blend.m_Bone[1] == 0xFF)
			{
				mdef->m_pBlendIndices[i] = blend.m_Bone[0];
			}
			else
			{
				// If there's already a vertex using the same blend as this, then
				// reuse its entry from blends; otherwise add the new one to blends
				size_t j;
				for (j = 0; j < blends.size(); j++)
				{
					if (blend == blends[j]) break;
				}
				if (j >= blends.size())
					blends.push_back(blend);
				mdef->m_pBlendIndices[i] = mdef->m_NumBones + j;
			}
		}

		mdef->m_NumBlends = blends.size();
		mdef->m_pBlends = new SVertexBlend[mdef->m_NumBlends];
		std::copy(blends.begin(), blends.end(), mdef->m_pBlends);
	}

	if (unpacker.GetVersion() >= 2)
	{
		// versions >=2 also have prop point data
		size_t numPropPoints = unpacker.UnpackSize();
		mdef->m_PropPoints.resize(numPropPoints);
		if (numPropPoints)
		{
			for (size_t i = 0; i < numPropPoints; i++)
			{
				unpacker.UnpackString(mdef->m_PropPoints[i].m_Name);
				unpacker.UnpackRaw(&mdef->m_PropPoints[i].m_Position.X, sizeof(mdef->m_PropPoints[i].m_Position));
				unpacker.UnpackRaw(&mdef->m_PropPoints[i].m_Rotation.m_V.X, sizeof(mdef->m_PropPoints[i].m_Rotation));
				unpacker.UnpackRaw(&mdef->m_PropPoints[i].m_BoneIndex, sizeof(mdef->m_PropPoints[i].m_BoneIndex));

				// build prop point transform
				mdef->m_PropPoints[i].m_Transform.SetIdentity();
				mdef->m_PropPoints[i].m_Transform.Rotate(mdef->m_PropPoints[i].m_Rotation);
				mdef->m_PropPoints[i].m_Transform.Translate(mdef->m_PropPoints[i].m_Position);
			}
		}
	}

	if (unpacker.GetVersion() <= 2)
	{
		// Versions <=2 don't include the default 'root' prop point, so add it here

		SPropPoint prop;
		prop.m_Name = "root";
		prop.m_Transform.SetIdentity();
		prop.m_BoneIndex = 0xFF;

		mdef->m_PropPoints.push_back(prop);
	}

	if (unpacker.GetVersion() <= 2)
	{
		// Versions <=2 store the vertexes relative to the bind pose. That
		// isn't useful when you want to do correct skinning, so later versions
		// store them in world space. So, fix the old models by skinning each
		// vertex:

		if (mdef->m_NumBones) // only do skinned models
		{
			std::vector<CMatrix3D> bindPose (mdef->m_NumBones);

			for (size_t i = 0; i < mdef->m_NumBones; ++i)
			{
				bindPose[i].SetIdentity();
				bindPose[i].Rotate(mdef->m_Bones[i].m_Rotation);
				bindPose[i].Translate(mdef->m_Bones[i].m_Translation);
			}

			for (size_t i = 0; i < mdef->m_NumVertices; ++i)
			{
				mdef->m_pVertices[i].m_Coords = SkinPoint(mdef->m_pVertices[i], &bindPose[0]);
				mdef->m_pVertices[i].m_Norm = SkinNormal(mdef->m_pVertices[i], &bindPose[0]);
			}
		}
	}

	return mdef.release();
}