//
// 从建筑物的行走面数据文件中读取三角形的信息。
//
// 参数: std::string strFileName 建筑物行走面的数据文件。
//
// return: 0 - 成功。 非0 失败。具体含义根据需要待定。
DWORD FairyEditorFrame::LoadCollisionDataFromFile(std::string strFileName, TRI_INFO_VECTOR &TriInfoVector)
{
	
	FILE* pFile = NULL;
	pFile = ::fopen(strFileName.c_str(), "rb");
	if(NULL == pFile)
	{
		return 1;
	}

	DWORD dwVersion = 0;
	int   iTriCount = 0;

	TRI_INFO triInfo;
	TriInfoVector.clear();

	::fread(&dwVersion, sizeof(dwVersion), 1, pFile);
	::fread(&iTriCount, sizeof(iTriCount), 1, pFile);

	for(int i = 0; i < iTriCount; i++)
	{
		::fread(&triInfo, sizeof(triInfo), 1, pFile);
		TriInfoVector.push_back(triInfo);
	}

	::fclose(pFile);

	return 0;
}
//
// 从行走面数据文件中读取数据。
//
// 参数:行走面数据文件, 包含路径。
UINT CBuildingCollisionMng::LoadCollisionTriInfoFromFile(const char* szFileName)
{

	// 读取新的数据之前, 要清空数据.
	ClearData();

	if(!szFileName || szFileName[0] == '\0') return 1;

	char* lpAddress = NULL;
	DWORD dwSize = CGameProcedure::s_pResourceProvider->loadResource(szFileName, lpAddress, "Scene");

	if(dwSize > 0)
	{
		char* pPoint = lpAddress;

		//FILE* pFile = NULL;
		//pFile = ::fopen(szFileName, "rb");
		//if(NULL == pFile)
		//{
		//	return 1;
		//}

		TRI_INFO	triInfo;
		POINT_2D	pos;
		UINT		dwVersion = 0;
		INT         iPosCount = 0;
		INT         iTriCount = 0;

		TRI_INFO_VECTOR triInfoVector;

		// 读取版本号
		//::fread(&dwVersion, sizeof(dwVersion), 1, pFile);
		memcpy(&dwVersion, pPoint, sizeof(dwVersion)); pPoint+=sizeof(dwVersion);

		// 读取注册过的三角形的位置的个数
		//::fread(&iPosCount, sizeof(iPosCount), 1, pFile);
		memcpy(&iPosCount, pPoint, sizeof(iPosCount)); pPoint+=sizeof(iPosCount);

		for(INT i = 0; i < iPosCount; i++)
		{
			// 清空三角形信息数组。
			triInfoVector.clear();

			// 读取位置
			//::fread(&pos, sizeof(pos), 1, pFile);
			memcpy(&pos, pPoint, sizeof(pos)); pPoint+=sizeof(pos);
			
			// 读取注册这个位置的三角形的个数
			//::fread(&iTriCount, sizeof(iTriCount), 1, pFile);
			memcpy(&iTriCount, pPoint, sizeof(iTriCount)); pPoint+=sizeof(iTriCount);
			for(INT j = 0; j < iTriCount; j++)
			{
				//::fread(&triInfo, sizeof(triInfo), 1, pFile);
				memcpy(&triInfo, pPoint, sizeof(triInfo)); pPoint+=sizeof(triInfo);
				triInfoVector.push_back(triInfo);
			}

			if(triInfoVector.size())
			{
				m_triInfoMap[pos] = triInfoVector;
			}
		}

		//::fclose(pFile);
		CGameProcedure::s_pResourceProvider->unloadResource( lpAddress, dwSize );
	}

	return 0;
}
//
// 把三角形信息写到地图的三角形与位置的映射表中。
//
// 参数1: 三角形列表。
// 
// 参数2: 三角形的变换矩阵。
//
void FairyEditorFrame::WriteCollisionDataToTriMap_Rectangle(TRI_INFO_VECTOR &TriInfoVector, Ogre::Matrix4& TransformMatrix)
{

	
	int iCount = 0;			//每一个物体的行走面三角形个数
	
	POINT_3D  Info1;		// 行走面的第一个点。
	POINT_3D  Info2;        // 行走面的第二个点。
    POINT_3D  Info3;		// 行走面的第三个点.

	POINT_3D  recP1;		// 矩形第一个点。
	POINT_3D  recP2;        // 矩形第二个点。
    POINT_3D  recP3;		// 矩形第三个点.
	POINT_3D  recP4;		// 矩形第四个点.

	float       fV1x = 0;		// 用来求三角形三条边的参数方程。 
	float       fV1z = 0;		//
	float       fV2x = 0;		// fV1x = v1.x - v2.x  fV1z = v1.z - v2.z
	float       fV2z = 0;		// fV2x = v2.x - v3.x  fV2y = v2.z - v3.z
	float       fV3x = 0;		// fV3x = v3.x - v1.x  fV3y = v3.z - v1.z
	float       fV3z = 0;		//


	float       fMinX = 0;		// 用来求三角形三条边的参数方程。 
	float       fMinZ = 0;		//
	float       fMaxX = 0;		// fV1x = v1.x - v2.x  fV1z = v1.z - v2.z
	float       fMaxZ = 0;		// fV2x = v2.x - v3.x  fV2y = v2.z - v3.z
	


	float       ft = 0;			// 参数方程比率t

	int iScanStart = 0;		// 扫描线的开始点。
	int iScanEnd   = 0;		// 扫描线的结束点。

	float fFindStart = 0;		// 每次扫描找到的开始点。
	float fFindEnd   = 0;		// 每次扫描找到的结束点。

	float fValue = 0;		// 找到的值。

	POINT_2D point2DKey;

	int iFaceCount = TriInfoVector.size();

	TRI_INFO Tri;

	Info1.fx = TriInfoVector[0].f1x;
	Info1.fy = TriInfoVector[0].f1y;
	Info1.fz = TriInfoVector[0].f1z;

	TranslateSceneToGameLogic(Info1.fx, Info1.fy, Info1.fz, TransformMatrix);

	fMinX = Info1.fx;
	fMinZ = Info1.fz;
	fMaxX = Info1.fx;
	fMaxZ = Info1.fz;

	for(int i = 0; i < iFaceCount; i++)
	{

		// 计算点一
		Info1.fx = TriInfoVector[i].f1x;
		Info1.fy = TriInfoVector[i].f1y;
		Info1.fz = TriInfoVector[i].f1z;
		TranslateSceneToGameLogic(Info1.fx, Info1.fy, Info1.fz, TransformMatrix);

		if(fMinX > Info1.fx)
		{
			fMinX = Info1.fx;
		}

		if(fMinZ > Info1.fz)
		{
			fMinZ = Info1.fz;
		}

		if(fMaxX < Info1.fx)
		{
			fMaxX = Info1.fx;
		}

		if(fMaxZ < Info1.fz)
		{
			fMaxZ = Info1.fz;
		}

		// 计算点二		
		Info1.fx = TriInfoVector[i].f2x;
		Info1.fy = TriInfoVector[i].f2y;
		Info1.fz = TriInfoVector[i].f2z;
		TranslateSceneToGameLogic(Info1.fx, Info1.fy, Info1.fz, TransformMatrix);

		if(fMinX > Info1.fx)
		{
			fMinX = Info1.fx;
		}

		if(fMinZ > Info1.fz)
		{
			fMinZ = Info1.fz;
		}

		if(fMaxX < Info1.fx)
		{
			fMaxX = Info1.fx;
		}

		if(fMaxZ < Info1.fz)
		{
			fMaxZ = Info1.fz;
		}


		// 计算点三
		Info1.fx = TriInfoVector[i].f3x;
		Info1.fy = TriInfoVector[i].f3y;
		Info1.fz = TriInfoVector[i].f3z;
		TranslateSceneToGameLogic(Info1.fx, Info1.fy, Info1.fz, TransformMatrix);

		if(fMinX > Info1.fx)
		{
			fMinX = Info1.fx;
		}

		if(fMinZ > Info1.fz)
		{
			fMinZ = Info1.fz;
		}

		if(fMaxX < Info1.fx)
		{
			fMaxX = Info1.fx;
		}

		if(fMaxZ < Info1.fz)
		{
			fMaxZ = Info1.fz;
		}

	}// for(int i = 0; i < iFaceCount; i++)


	int iMinX = 0;
	int iMinZ = 0;
	int iMaxX = 0;
	int iMaxZ = 0;

	iMinX = fMinX - 1;
	iMinZ =	fMinZ - 1;
	iMaxX =	fMaxX + 1;
	iMaxZ =	fMaxZ + 1;

	TRI_INFO_VECTOR newTriInfoVector;
	for(int x = iMinX; x <= iMaxX; x++)
		for(int z = iMinZ; z <= iMaxZ; z++)
		{

			recP1.fx = x;
			recP1.fz = z;
			recP2.fx = x + 1;
			recP2.fz = z;
            recP3.fx = x + 1;
			recP3.fz = z + 1;
			recP4.fx = x;
			recP4.fz = z + 1;

			for(int iFace = 0; iFace < iFaceCount; iFace++)
			{

				// 计算点一
				Info1.fx = TriInfoVector[iFace].f1x;
				Info1.fy = TriInfoVector[iFace].f1y;
				Info1.fz = TriInfoVector[iFace].f1z;
				TranslateSceneToGameLogic(Info1.fx, Info1.fy, Info1.fz, TransformMatrix);

				// 计算点二		
				Info2.fx = TriInfoVector[iFace].f2x;
				Info2.fy = TriInfoVector[iFace].f2y;
				Info2.fz = TriInfoVector[iFace].f2z;
				TranslateSceneToGameLogic(Info2.fx, Info2.fy, Info2.fz, TransformMatrix);

				// 计算点三
				Info3.fx = TriInfoVector[iFace].f3x;
				Info3.fy = TriInfoVector[iFace].f3y;
				Info3.fz = TriInfoVector[iFace].f3z;
				TranslateSceneToGameLogic(Info3.fx, Info3.fy, Info3.fz, TransformMatrix);

				if(Is_Rectangle_Triangle_Intersect(Info1, Info2, Info3, recP1, recP2, recP3, recP4))
				{
					// 把三角形注册到地图中去
					Tri.f1x = Info1.fx;
					Tri.f1y = Info1.fy;
					Tri.f1z = Info1.fz;
					Tri.f2x = Info2.fx;
					Tri.f2y = Info2.fy;
					Tri.f2z = Info2.fz;
					Tri.f3x = Info3.fx;
					Tri.f3y = Info3.fy; 
					Tri.f3z = Info3.fz;

					point2DKey.iX = x;
					point2DKey.iY = z;
					if(m_TriInMapInfoMap.m_triInfoInMap.count(point2DKey))
					{
						m_TriInMapInfoMap.m_triInfoInMap[point2DKey].push_back(Tri);
						
					}
					else
					{
						newTriInfoVector.clear();
						newTriInfoVector.push_back(Tri);
						m_TriInMapInfoMap.m_triInfoInMap[point2DKey] = newTriInfoVector;
					}

				}// if(Is_Rectangle_Triangle_Intersect(Info1, Info2, Info3, recP1, recP2, recP3, recP4))

			}// for(int iFace = 0; iFace < iFaceCount; iFace++)

		}	//for(int x = iMinX; x < iMaxX; x++)
		//for(int z = fMinZ; z < fMaxZ; z++)


}
//
// 把三角形信息写到地图的三角形与位置的映射表中。
//
// 参数1: 三角形列表。
// 
// 参数2: 三角形的变换矩阵。
//
void FairyEditorFrame::WriteCollisionDataToTriMap(TRI_INFO_VECTOR &TriInfoVector, Ogre::Matrix4& TransformMatrix)
{

	typedef std::vector<SCANLINE_INFO> SCAN_LINE_VECTOR;

	SCANLINE_INFO    Scanline_info;			// 扫描信息.
	SCAN_LINE_VECTOR ScanLineVector;		// 每一个三角形的扫描信息.
	
	int iCount = 0;			//每一个物体的行走面三角形个数
	
	POINT_3D  Info1;		// 行走面的第一个点。
	POINT_3D  Info2;        // 行走面的第二个点。
    POINT_3D  Info3;		// 行走面的第三个点.

	float       fV1x;		// 用来求三角形三条边的参数方程。 
	float       fV1z;		//
	float       fV2x;		// fV1x = v1.x - v2.x  fV1z = v1.z - v2.z
	float       fV2z;		// fV2x = v2.x - v3.x  fV2y = v2.z - v3.z
	float       fV3x;		// fV3x = v3.x - v1.x  fV3y = v3.z - v1.z
	float       fV3z;		//

	float       ft;			// 参数方程比率t

	int iScanStart = 0;		// 扫描线的开始点。
	int iScanEnd   = 0;		// 扫描线的结束点。

	float fFindStart;		// 每次扫描找到的开始点。
	float fFindEnd;			// 每次扫描找到的结束点。

	float fMaxX = 0;		// 三角形x的取值范围.
	float fMinX = 0;		//

	float fValue = 0;		// 找到的值。

	POINT_2D point2DKey;

	// 需要扫描的三角形。
	TRI_INFO tri;

	int iFaceCount = TriInfoVector.size();

	TRI_INFO Tri;
	for(int i = 0; i < iFaceCount; i++)
	{
		ScanLineVector.clear();
		
		Tri = TriInfoVector[i];
		Info1.fx = TriInfoVector[i].f1x;
		Info1.fy = TriInfoVector[i].f1y;
		Info1.fz = TriInfoVector[i].f1z;
		TranslateSceneToGameLogic(Info1.fx, Info1.fy, Info1.fz, TransformMatrix);
		fMinX = Info1.fx;
		fMaxX = Info1.fx;
			
		Info2.fx = TriInfoVector[i].f2x;
		Info2.fy = TriInfoVector[i].f2y;
		Info2.fz = TriInfoVector[i].f2z;
		TranslateSceneToGameLogic(Info2.fx, Info2.fy, Info2.fz, TransformMatrix);
		//fMinX = min(fMinX, Info2.fx);
		//fMaxX = max(fMaxX, Info2.fx);
		if(fMinX > Info2.fx)
		{
			fMinX = Info2.fx;
		}
		if(fMaxX < Info2.fx)
		{
			fMaxX = Info2.fx;
		}
				

		Info3.fx = TriInfoVector[i].f3x;
		Info3.fy = TriInfoVector[i].f3y;
		Info3.fz = TriInfoVector[i].f3z;
		TranslateSceneToGameLogic(Info3.fx, Info3.fy, Info3.fz, TransformMatrix);
		//fMinX = min(fMinX, Info3.fx);
		//fMaxX = max(fMaxX, Info3.fx);
		if(fMinX > Info3.fx)
		{
			fMinX = Info3.fx;
		}
		if(fMaxX < Info3.fx)
		{
			fMaxX = Info3.fx;
		}
			
		
		// 计算要扫描的三角形。
		tri.f1x = Info1.fx;
		tri.f1y = Info1.fy;
		tri.f1z = Info1.fz;
		
		tri.f2x = Info2.fx;
		tri.f2y = Info2.fy;
		tri.f2z = Info2.fz;

		tri.f3x = Info3.fx;
		tri.f3y = Info3.fy;
		tri.f3z = Info3.fz;


		//////////////////////////////////////////////////////////////////////////////////////////////////
		//
		//  找到所有的扫描线.
		//
		//

		// 扫描第一条边。
		fV1x = Info2.fx - Info1.fx;
		fV1z = Info2.fz - Info1.fz;
		if(fabs((float)fV1x) < 0.0001)
		{

			Scanline_info.iStart    = (int)((Info1.fz < Info2.fy) ? Info1.fz : Info2.fz ) - 1;
			Scanline_info.iEnd      = (int)((Info1.fz > Info2.fy) ? Info1.fz : Info2.fz ) + 1;
			Scanline_info.iScanLine = (int)Info1.fx;
			ScanLineVector.push_back(Scanline_info);

		}

			
		// 扫描第二条边。
		fV2x = Info3.fx - Info2.fx;
		fV2z = Info3.fz - Info2.fz;
		if(fabs((float)fV2x) < 0.0001)
		{

			Scanline_info.iStart    = (int)((Info3.fz < Info2.fz) ? Info3.fz : Info2.fz) - 1;
			Scanline_info.iEnd      = (int)((Info3.fz > Info2.fz) ? Info3.fz : Info2.fz) + 1;
			Scanline_info.iScanLine = (int)Info2.fx;
			ScanLineVector.push_back(Scanline_info);

		}

		// 扫描第三条边。
		fV3x = Info1.fx - Info3.fx;
		fV3z = Info1.fz - Info3.fz;
		if(fabs((float)fV3x) < 0.0001)
		{

			Scanline_info.iStart    = (int)((Info1.fz < Info3.fz) ? Info1.fz : Info3.fz) - 1;
			Scanline_info.iEnd      = (int)((Info1.fz > Info3.fz) ? Info1.fz : Info3.fz) + 1;
			Scanline_info.iScanLine = (int)Info3.fx;
			ScanLineVector.push_back(Scanline_info);

		}

		iScanStart = (int)fMinX - 1;			// 扫描线的开始点。
		iScanEnd   = (int)fMaxX + 1;			// 扫描线的结束点。
		
		for(int k = iScanStart; k <= iScanEnd; k++)
		{// 循环每一个扫描线.
			
			///////////////////////////////////////////////////////
			//
			// 初始化这三个值的意义是第一条直线段可能不在扫描线中
			//
			//
			fFindStart = 10000.0f;		// 这个取值要大于直线方程中可能取到的最大值。
			fFindEnd   = 0;	
			fValue     = -1;

			if(fabs((float)fV1x) > 0.0001)
			{
				ft = (k * 1.0f - Info1.fx) / fV1x;
				if((ft >= 0)&&(ft <= 1.0))
				{
					fValue     = Info1.fz + ft * fV1z; 
					fFindStart = Info1.fz + ft * fV1z; 
					fFindEnd   = Info1.fz + ft * fV1z; 
				}
			}

			if(fabs((float)fV2x) > 0.0001)
			{
				ft = (k * 1.0f - Info2.fx) / fV2x;
				if((ft >= 0)&&(ft <= 1.0))
				{
					fValue = Info2.fz + ft * fV2z;
					if(fValue < fFindStart)
					{
						fFindStart = fValue;
					}

					if(fValue > fFindEnd)
					{
						fFindEnd = fValue;
					}
				}

			}

			if(fabs((float)fV3x) > 0.0001)
			{
				ft = (k * 1.0f - Info3.fx) / fV3x;
				if((ft >= 0)&&(ft <= 1.0))
				{
					fValue = Info3.fz + ft * fV3z;
					if(fValue < fFindStart)
					{
						fFindStart = fValue;
					}

					if(fValue > fFindEnd)
					{
						fFindEnd = fValue;
					}
				}

			}

			if(fValue >= 0)
			{
				Scanline_info.iStart    = (int)(fFindStart) - 1;
				Scanline_info.iEnd      = (int)(fFindEnd) + 1;
				Scanline_info.iScanLine = (int)k;
				ScanLineVector.push_back(Scanline_info);
			}
		
			// 循环每一个扫描线结束.
		}// for(int k = iScanStart; k <= iScanEnd; k++)

		// 把三角形的三个顶点, 添加到数组
		Scanline_info.iStart    = (int)(Info1.fz);
		Scanline_info.iEnd      = (int)(Info1.fz);
		Scanline_info.iScanLine = (int)(Info1.fx);
		ScanLineVector.push_back(Scanline_info);

		Scanline_info.iStart    = (int)(Info2.fz);
		Scanline_info.iEnd      = (int)(Info2.fz);
		Scanline_info.iScanLine = (int)(Info2.fx);
		ScanLineVector.push_back(Scanline_info);

		Scanline_info.iStart    = (int)(Info3.fz);
		Scanline_info.iEnd      = (int)(Info3.fz);
		Scanline_info.iScanLine = (int)(Info3.fx);
		ScanLineVector.push_back(Scanline_info);
	
		//
		//  找到所有的扫描线.
		//
		//
		//////////////////////////////////////////////////////////////////////////////////////////////////
	
		// 根据找到的扫描线把三角形注册到地图中。
		TRI_INFO_VECTOR newTriInfoVector;
		for(int j = 0; j < (int)ScanLineVector.size(); j++)
		{
			for(int iY = ScanLineVector[j].iStart; iY <= ScanLineVector[j].iEnd; iY++)
			{
				point2DKey.iX = ScanLineVector[j].iScanLine;
				point2DKey.iY = iY;
				if(m_TriInMapInfoMap.m_triInfoInMap.count(point2DKey))
				{
					m_TriInMapInfoMap.m_triInfoInMap[point2DKey].push_back(tri);
					
				}
				else
				{
					newTriInfoVector.clear();
					newTriInfoVector.push_back(tri);
					m_TriInMapInfoMap.m_triInfoInMap[point2DKey] = newTriInfoVector;
				}
			}

		}

	}// for(int i = 0; i < iFaceCount; i++)

}