/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CheckLoS():	This function looks at the player and sees if the player is in range and in line of sight.
//
// Returns:		bool = true if the player is in line of sight
//
// Mod. Name: Josh Morgan
// Mod. Date:8/14/12
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool CSlimeMonsterIdleAI::CheckLoS(void)
{
	//creating the sound sphere
	Sphere LoSRadius;
	LoSRadius.SetRadius(LOS_BUBBLE);
	LoSRadius.SetCenter(m_pParentObject->GetWorldPos());
	CSceneObject LoSSphere;
	LoSSphere.SetCollidableObject(&LoSRadius);

	// create a return vector to hold all the objects the kd tree returns
	std::vector <CSceneObject*> ReturnVector;
	// create a unsigned int that will tell the kd tree what you want put in the return vector
	// this uses bit wise operations so you can have more then one object returned
	// use the return flags enum from the kd tree so you know what you can get back
	int ReturnParams = 0;
	int ReturnBody = 0;
	int ReturnObjects = 1<<OBJ_PLAYER | 1<<OBJ_WORLD_COLLISION;

	CKdTree::GetNearObjects(&LoSSphere, PSFLAG_SPHERE, ReturnParams, ReturnVector, ReturnBody, ReturnObjects);

	//bool for checking if there's the player, and the position of the player
	bool bPlayerInRange = false;
	vec3f tPlayerPos = vec3f(0.0f, 0.0f, 0.0f);

	for(unsigned int i = 0; i < ReturnVector.size(); i++)
	{
		IBaseObject* pObject = ((IBaseObject*)ReturnVector[i]);

		if(pObject->GetType() == OBJ_PLAYER)
		{
			bPlayerInRange = true;
			tPlayerPos = pObject->GetWorldPos();
			break;
		}
	}

	if(!bPlayerInRange)
	{
		return false;
	}

	//we make a line to the player since he's in aggro range
	CSceneObject soLineSceneObject;
	Line LineToPlayer;
	LineToPlayer.SetVolumeType(VMT_LINE);
	LineToPlayer.SetStartPoint(vec3f(m_pParentObject->GetWorldPos().x, m_pParentObject->GetWorldPos().y + 100.0f, m_pParentObject->GetWorldPos().z));
	LineToPlayer.SetEndPoint(vec3f(tPlayerPos.x, tPlayerPos.y + 100.0f, tPlayerPos.z));
	soLineSceneObject.SetCollidableObject(&LineToPlayer);

	CKdTree::GetNearObjects(&soLineSceneObject, PSFLAG_LINE, ReturnParams, ReturnVector, ReturnBody, ReturnObjects); 

	soLineSceneObject.SetCollidableObject(nullptr);

	//loop through all the return objects again and check collision with them.
	for(unsigned int i = 0; i < ReturnVector.size(); ++i)
	{
		IBaseObject* pObject = ((IBaseObject*)ReturnVector[i]);
		
		if(pObject->GetType() == OBJ_WORLD_COLLISION)
		{
			//check to see if our line to the player is obstructed by this ocject
			vec3f Intersection = vec3f(FLT_MAX, FLT_MAX, FLT_MAX);
			if(LineToPlayer.LineToAABB(*((AABB*)pObject->GetCollidableObject()), Intersection))
			{
				//D3DXMATRIX mat;
				//D3DXMatrixIdentity(&mat);
				//mat._41 = Intersection.x;
				//mat._42 = Intersection.y;
				//mat._43 = -500;
				//DebugShapes::RenderSphere(mat);

				//we see that there's something between us so I don't have line of sight
				return false;
			}
		}
	}

	//set the slime monster to face the player
	matrix4f _localMat = (*m_pParentObject->GetLocalMat());
	matrix4f rotationMatrix;
	vec2f DtoP = LineToPlayer.GetEndPoint2D() - LineToPlayer.GetStartPoint2D();
	if(DtoP.x <= 0.0f)
	{
		//spawn facing left
		rotationMatrix.make_rotation_y( D3DXToRadian(90) );
	}
	else
	{
		//spawn to face right
		rotationMatrix.make_rotation_y( D3DXToRadian(-90) );
	}
	rotationMatrix.axis_pos = _localMat.axis_pos;
	_localMat = rotationMatrix;
	m_pParentObject->SetLocalMat(&_localMat);
	//I SEE HIM! HE'S RIGHT THERE!
	return true;
}
void SoftBodyNode::DivideTriangle(TDVertexContainer& Vertices, 
								TDConnectContainer& Connections, 
								TDConnectContainer::iterator itFace)
{
	TDConnect::iterator itIdx = itFace->begin();
	TDConnect::size_type nIdxA = *itIdx;
	TDConnect::size_type nIdxB = *(itIdx + 1);
	TDConnect::size_type nIdxC = *(itIdx + 2);
	TDConnect::size_type nIdxD = -1;
	TDConnect::size_type nIdxE = -1;
	TDConnect::size_type nIdxF = -1;
	TDVertex A(m_Vertices[nIdxA]);
	TDVertex B(m_Vertices[nIdxB]);
	TDVertex C(m_Vertices[nIdxC]);
	TDVertex AB(B-A);
	TDVertex AC(C-A);
	TDVertex BC(C-B);
	//TDVertex Normal(AB.Cross(AC));

	//normals of the edges - I don't know if this idea makes sense - I've never come
	//across an edge normal before in computer graphics literature. In this program I've defined the normal of
	//an edge to be the sum of the normals of the adjoining vertices. This is not true in general. 
	//It should be the sum of the normals of the adjoining faces, ie the faces that the edge border, 
	//but in this case because the kernel polyhedron is an octahedron, we may be able to get away with it.
	TDVertex NormalAB(*(m_Normals[nIdxA]) + *(m_Normals[nIdxB]));
	TDVertex NormalAC(*(m_Normals[nIdxA]) + *(m_Normals[nIdxC]));
	TDVertex NormalBC(*(m_Normals[nIdxB]) + *(m_Normals[nIdxC]));
		
	NormalAB = 1.0f/bnu::norm_2(NormalAB) * NormalAB;
	NormalAC = 1.0f/bnu::norm_2(NormalAC) * NormalAC;
	NormalBC = 1.0f/bnu::norm_2(NormalBC) * NormalBC;

	TDVertex MidAB(A + 0.5*AB);
	TDVertex MidAC(A + 0.5*AC);
	TDVertex MidBC(B + 0.5*BC);
	
	Sphere BoundSphere;
	bnu::vector<double> Center(3);
	Center[0] = 0.0; Center[1] = 1.0; Center[2] = 0.0;
	BoundSphere.SetCenter(Center);
	BoundSphere.SetRadius(0.5);
	
	Ray Ray;
	Ray.SetOrigin(MidAB);
	Ray.SetDirection(NormalAB);
	TDVertexContainer Points;	
	FindIntersection(Ray, BoundSphere, Points);
	assert(Points.size() == 1);
	TDVertex D(Points[0]);

	Ray.SetOrigin(MidBC);
	Ray.SetDirection(NormalBC);
	FindIntersection(Ray, BoundSphere, Points);
	assert(Points.size()== 1);
	TDVertex E(Points[0]);

	Ray.SetOrigin(MidAC);
	Ray.SetDirection(NormalAC);
	FindIntersection(Ray, BoundSphere, Points);
	assert(Points.size()== 1);
	TDVertex F(Points[0]);

	TDVertexContainer::iterator itVec;
	if ((itVec = find_if(Vertices.begin(), Vertices.end(), bind(Equal<TDVertex>(), _1, D))) == Vertices.end())
	{
		Vertices.push_back(D);
		nIdxD = Vertices.size() - 1;
	}
	else
	{
		nIdxD = Vertices.size() - (Vertices.end() - itVec);
	}
	if ((itVec = find_if(Vertices.begin(), Vertices.end(), bind(Equal<TDVertex>(), _1, E))) == Vertices.end())
	{
		Vertices.push_back(E);
		nIdxE = Vertices.size() - 1;
	}
	else
	{
		nIdxE = Vertices.size() - (Vertices.end() - itVec);
	}
	if ((itVec = find_if(Vertices.begin(), Vertices.end(), bind(Equal<TDVertex>(), _1, F))) == Vertices.end())
	{
		Vertices.push_back(F);
		nIdxF = Vertices.size() - 1;
	}
	else
	{
		nIdxF = Vertices.size() - (Vertices.end() - itVec);
	}
	
	vector<unsigned> vecFace;
	vecFace.push_back(nIdxA);
	vecFace.push_back(nIdxD);
	vecFace.push_back(nIdxF);
	Connections.push_back(vecFace);
	
	vecFace.clear();
	vecFace.push_back(nIdxD);
	vecFace.push_back(nIdxB);
	vecFace.push_back(nIdxE);
	Connections.push_back(vecFace);

	vecFace.clear();
	vecFace.push_back(nIdxF);
	vecFace.push_back(nIdxE);
	vecFace.push_back(nIdxC);
	Connections.push_back(vecFace);

	vecFace.clear();
	vecFace.push_back(nIdxD);
	vecFace.push_back(nIdxE);
	vecFace.push_back(nIdxF);
	Connections.push_back(vecFace);
}