Raw File
SimCharSoftFall.cpp
#include "sim/SimCharSoftFall.h"

const double gFallDistCheckPeriod = 5;
const double gFallContactCheckPeriod = 0.1;
const double gMaxFallDist = 0.5;
const double gFallContactDiscount = 0.9;
const double gMaxSumFallContact = 0.25;

#define ENABLE_SOFT_FALL

cSimCharSoftFall::cSimCharSoftFall()
{
	ResetFallDistCounter();
	mPrevCheckPos.setZero();
	mFailFallDist = false;
	ResetFallContactCounter();
	mSumFallContact = 0;
}

cSimCharSoftFall::~cSimCharSoftFall()
{

}

bool cSimCharSoftFall::Init(std::shared_ptr<cWorld> world, const tParams& params)
{
	bool succ = cSimCharacter::Init(world, params);
	ResetFallDistCounter();
	mPrevCheckPos = GetRootPos();
	mFailFallDist = false;
	ResetFallContactCounter();
	mSumFallContact = 0;
	return succ;
}

void cSimCharSoftFall::Reset()
{
	cSimCharacter::Reset();
	ResetFallDistCounter();
	mPrevCheckPos = GetRootPos();
	mFailFallDist = false;
	ResetFallContactCounter();
	mSumFallContact = 0;
}

void cSimCharSoftFall::Update(double time_step)
{
	cSimCharacter::Update(time_step);
	UpdateFallDistCheck(time_step);
	UpdateFallContactCheck(time_step);
}

bool cSimCharSoftFall::HasFallen() const
{
	bool fall_contact = FailFallContact();
	bool fall_dist = FailFallDist();
	bool fall_misc = FailFallMisc();

	bool has_fallen = fall_contact || fall_dist || fall_misc;
	return has_fallen;
}


void cSimCharSoftFall::ResetFallDistCounter()
{
	mFallDistCounter = gFallDistCheckPeriod;
}

bool cSimCharSoftFall::FailFallDist() const
{
	return mFailFallDist;
}

void cSimCharSoftFall::UpdateFallDistCheck(double time_step)
{
	mFallDistCounter -= time_step;
	if (mFallDistCounter <= 0)
	{
		tVector root_pos = GetRootPos();
		tVector dist = root_pos - mPrevCheckPos;

		if (dist.squaredNorm() < gMaxFallDist * gMaxFallDist)
		{
			mFailFallDist = true;
		}

		mPrevCheckPos = root_pos;
		ResetFallDistCounter();
	}
}

void cSimCharSoftFall::ResetFallContactCounter()
{
	mFallContatCounter = gFallContactCheckPeriod;
}

bool cSimCharSoftFall::FailFallContact() const
{
#if defined(ENABLE_SOFT_FALL)
	return mSumFallContact > gMaxSumFallContact;
#else
	return CheckFallContact();
#endif
}

bool cSimCharSoftFall::CheckFallContact() const
{
	return false;
}

void cSimCharSoftFall::UpdateFallContactCheck(double time_step)
{
	const double discount = gFallContactDiscount;
	const double norm = (1 + 1 / (1 - discount));

	mFallContatCounter -= time_step;
	if (mFallContatCounter <= 0)
	{
		bool has_contact = CheckFallContact();
		double val = (has_contact) ? 1 : 0;
		mSumFallContact = val/ norm + discount * mSumFallContact;

		ResetFallContactCounter();
	}
}

bool cSimCharSoftFall::FailFallMisc() const
{
	return false;
}
back to top