void CPHMovementControl::PathDIrPoint(const xr_vector<DetailPathManager::STravelPathPoint> &path,  int index,  float distance,  float precesition, Fvector &dir  )
{
	Fvector to_path_point;
	Fvector corrected_path_dir;CorrectPathDir(GetPathDir(),path,index,corrected_path_dir);
	to_path_point.sub(vPathPoint,vPosition);	//_new position
	float mag=to_path_point.magnitude();

	if(mag<EPS) //near the point
	{  
		if(0==index||m_path_size-1==index) //on path eidge
		{
			dir.set(corrected_path_dir);//??
			return;
		}
		dir.sub(path[index].position,path[index-1].position);
		dir.normalize_safe();
		dir.add(corrected_path_dir);
		dir.normalize_safe();
	}
	to_path_point.mul(1.f/mag);
	if(m_path_size-1==index)//on_path_edge
	{
		dir.set(to_path_point);
		return;
	}


	if(mag<EPS||fis_zero(dXZMag(to_path_point),EPS))
	{
		dir.set(corrected_path_dir);
		return;//mean dir
	}
	
	Fvector tangent;
	tangent.crossproduct(Fvector().set(0,1,0),to_path_point);

	VERIFY(!fis_zero(tangent.magnitude()));
	tangent.normalize();
	if(dir.square_magnitude()>EPS)
	{
		if(tangent.dotproduct(dir)<0.f)tangent.invert();
	}
	else
	{
		if(tangent.dotproduct(corrected_path_dir)<0.f)tangent.invert();
	}

	if(mag>FootRadius())to_path_point.mul(precesition);
	else to_path_point.mul(mag*precesition);
	dir.add(tangent,to_path_point);
	dir.normalize_safe();
}
void CPHMovementControl::PathDIrLine(const xr_vector<DetailPathManager::STravelPathPoint> &path,  int index,  float distance,  float precesition, Fvector &dir  )
{

	Fvector to_path_point;
	Fvector corrected_path_dir;CorrectPathDir(GetPathDir(),path,index,corrected_path_dir);
	to_path_point.sub(vPathPoint,vPosition);	//_new position
	float mag=to_path_point.magnitude();
	if(mag<EPS)
	{
	dir.set(corrected_path_dir);
	return;
	}
	to_path_point.mul(1.f/mag);
	if(mag>FootRadius())to_path_point.mul(precesition);
	else to_path_point.mul(mag*precesition);
	dir.add(corrected_path_dir,to_path_point);
	dir.normalize_safe();
}
bool SceneLoader::LoadFromFile(const char* file_name)
{
	KTimer stop_watch(true);
	FILE* pFile = NULL;
	bool ret = false;
	int ext = _FileExtension(file_name);

	std::string file_dir;
	GetPathDir(file_name, file_dir);
	Texture::TextureManager::GetInstance()->AddSearchPath(file_dir.c_str());

	if (!mpScene)
		mpScene = new KSceneSet;
	else
		mpScene->Reset();

	mIsFromOBJ = false;
	mIsSceneLoaded = false;
	KTimer fileReadingTime(true);
	// Perform the file reading
	if (ext == FILE_EXT_OBJ) {
		KRT_ObjFileLoader OBJLoader;
		OBJLoader.mUseTexMap = USE_TEX_MAP ? true : false;

		// Create scene
		UINT32 kd_idx = 0;
		KScene* pKDScene = mpScene->AddKDScene(kd_idx);
		mpScene->SceneNode_Create(kd_idx);

		if (OBJLoader.LoadObjFile(file_name, *pKDScene)) {
			ret = true;
			mIsFromOBJ = true;
		}
		else {
			mpScene->Reset();
			ret = false;
		}
	}
	else if (ext == FILE_EXT_ABC) {
		if (mAbcLoader.Load(file_name, *mpScene))
			ret = true;
		else {
			mpScene->Reset();
			ret = false;
		}
	}

	if (ret) {
		BuildNodeIdMap();
		mIsSceneLoaded = true;
	}

	mFileLoadingTime = UINT32(fileReadingTime.Stop() * 1000);

	// End of file reading, now build the acceleration structure
	mpAccelData = new KAccelStruct_BVH(mpScene);
	mpAccelData->SceneNode_BuildAccelData(NULL);

	KBBox scene_box = mpAccelData->GetSceneBBox();
	KVec3 center = scene_box.Center();
	float radius = nvmath::length(scene_box.mMax - scene_box.mMin) * 1.0f;
	
	CameraManager* pCameraMan = CameraManager::GetInstance();
	if (pCameraMan->GetCameraCnt() == 0 && mpScene) {
		// If there's no camera, create a default light regarding the bounding box of scene
		KCamera* pPinHoleCamera = pCameraMan->OpenCamera("__default", true);
		KCamera::MotionState ms;
		ms.pos = center + KVec3(0.5,0.5,0.5)*radius;
		ms.lookat = center;
		ms.up = KVec3(0, 1.0f, 0);
		ms.xfov = 45.0f;
		ms.focal = radius * 0.5f;
		pPinHoleCamera->SetupStillCamera(ms);
	}
	
	LightScheme* pLightScheme = LightScheme::GetInstance();
	if (pLightScheme->GetLightCount() == 0 && mpScene) {
		// If there's no light source, create a default one, otherwize the scene will be entirely dark.
		PointLightBase* pLight0 = dynamic_cast<PointLightBase*>(pLightScheme->CreateLightSource(POINT_LIGHT_TYPE));
		PointLightBase* pLight1 = dynamic_cast<PointLightBase*>(pLightScheme->CreateLightSource(POINT_LIGHT_TYPE));
		pLight0->SetIntensity(KColor(0.55f, 0.55f, 0.55f));
		pLight1->SetIntensity(KColor(0.55f, 0.55f, 0.55f));
		pLight0->SetPos(center + KVec3(0,1,1)*(radius*3.0f));
		pLight1->SetPos(center + KVec3(1,1,0)*(radius*3.0f));
	}

	if (pFile)
		fclose(pFile);

	mLoadingTime = stop_watch.Stop();

	return ret;
}
void CPHMovementControl::Calculate(const xr_vector<DetailPathManager::STravelPathPoint>& path,float speed,  u32& travel_point,  float& precision  )
{
#ifdef DEBUG
	if(ph_dbg_draw_mask1.test(ph_m1_DbgTrackObject)&&(!!pObject->cName())&&stricmp(PH_DBG_ObjectTrack(),*pObject->cName())==0)
	{
		Msg("CPHMovementControl::Calculate in %s (Object Position) %f,%f,%f",PH_DBG_ObjectTrack(),pObject->Position().x,pObject->Position().y,pObject->Position().z);
		Msg("CPHMovementControl::Calculate in %s (CPHMovementControl::vPosition) %f,%f,%f",PH_DBG_ObjectTrack(),vPosition.x,vPosition.y,vPosition.z);
	}
#endif
	if(!m_character->b_exist)	return;
	if(m_capture) 
	{
		if(m_capture->Failed()) xr_delete(m_capture);
	}
	

	Fvector new_position;
	m_character->IPosition(new_position);

	int index=0;//nearest point
	//float distance;//distance

	bool  near_line;
	m_path_size=path.size();
	Fvector dir;
	dir.set(0,0,0);
	if(m_path_size==0)
	{
		speed=0;
		vPosition.set(new_position);
	}
	else if(b_exect_position)
	{
		m_start_index=travel_point;

		//////////////////////////////////////////////////////////////////////////
		//////////////////////////////////////////////////////////////////////////
		if((m_path_size-1)>(int)travel_point)
			dir.sub(path[travel_point+1].position,path[travel_point].position);
		else
			dir.sub(path[travel_point].position,new_position);
		m_start_index=travel_point;
		dir.y=0.f;
		dir.normalize_safe();
		vPosition.set(new_position);
		m_path_distance=0;
		SetPathDir	(dir);
		vPathPoint.set(vPosition);


	}
	else {
		Fvector dif;

		dif.sub(new_position,vPathPoint);
		float radius = dif.magnitude()*2.f;
		if(m_path_size==1)
		{
			speed=0.f;
			vPosition.set(new_position);	//todo - insert it in PathNearestPoint
			index=0;
			vPathPoint.set(path[0].position);
			Fvector _d;
			_d.sub(path[0].position,new_position);
			SetPathDir	(_d);
			m_path_distance=GetPathDir().magnitude();
			if(m_path_distance>EPS)
			{
				Fvector _d = GetPathDir();
				_d.mul(1.f/m_path_distance);
				SetPathDir(_d);
			}
			near_line=false;
		}
		else
		{
			m_path_distance=dInfinity;
			near_line=true;
			if(m_start_index<m_path_size)
			{
				PathNearestPointFindUp(path,new_position,index,radius,near_line);
				PathNearestPointFindDown(path,new_position,index,radius,near_line);
			}
			if(m_path_distance>radius)
			{
				m_start_index=0;
				PathNearestPoint(path,new_position,index,near_line);
			}
			vPosition.set(new_position);//for PathDirLine && PathDirPoint
			if(near_line) PathDIrLine(path,index,m_path_distance,precision,dir);
			else		  PathDIrPoint(path,index,m_path_distance,precision,dir);
			
	
			travel_point=(u32)index;
			m_start_index=index;
			if(fis_zero(speed)) dir.set(0,0,0);
		}

	}
	
	dir.y=0.f;
	//VERIFY(!(fis_zero(dir.magnitude())&&!fis_zero(speed)));
	dir.normalize_safe();
	
	/////////////////////////////////////////////////////////////////
	if(bExernalImpulse)
	{

		//vAccel.add(vExternalImpulse);
		Fvector V;
		V.set(dir);
		//V.mul(speed*fMass/fixed_step);
		V.mul(speed*10.f);
		V.add(vExternalImpulse);
		m_character->ApplyForce(vExternalImpulse);
		speed=V.magnitude();

		if(!fis_zero(speed))
		{
			dir.set(V);
			dir.mul(1.f/speed);
		}
		speed/=10.f;
		vExternalImpulse.set(0.f,0.f,0.f);
		bExernalImpulse=false;
	}
	/////////////////////////
	//if(!PhyssicsOnlyMode()){
	//	Fvector	v;//m_character->GetVelocity(v);
	//	v.mul(dir,speed);
	//	SetVelocity(v);//hk
	//	
	//}
	/////////////////////////
	m_character->SetMaximumVelocity(speed);
	m_character->SetAcceleration(dir);
	//////////////////////////////////////////////////////
	m_character->GetSmothedVelocity(vVelocity);
	fActualVelocity=vVelocity.magnitude();

	gcontact_Was=m_character->ContactWas();
	const ICollisionDamageInfo* di=m_character->CollisionDamageInfo();
	fContactSpeed=0.f;
	{
		fContactSpeed=di->ContactVelocity();
		gcontact_Power				= fContactSpeed/fMaxCrashSpeed;
		gcontact_HealthLost			= 0;
		if (fContactSpeed>fMinCrashSpeed) 
		{
			gcontact_HealthLost = 
				((fContactSpeed-fMinCrashSpeed))/(fMaxCrashSpeed-fMinCrashSpeed);
		}
	}

	CheckEnvironment(vPosition);
	bSleep=false;
	b_exect_position=false;
	//m_character->Reinit();
}