예제 #1
0
void CCharacter::FindGroundEntity()
{
	TVector vecVelocity = GetGlobalVelocity();

	if (vecVelocity.Dot(GetUpVector()) > JumpStrength()/2.0f)
	{
		SetGroundEntity(NULL);
		SetSimulated(true);
		return;
	}

	TVector vecUp = GetUpVector() * m_flMaxStepSize;

	size_t iMaxEntities = GameServer()->GetMaxEntities();
	for (size_t j = 0; j < iMaxEntities; j++)
	{
		CBaseEntity* pEntity = CBaseEntity::GetEntity(j);

		if (!pEntity)
			continue;

		if (pEntity->IsDeleted())
			continue;

		if (!pEntity->ShouldCollide())
			continue;

		if (pEntity == this)
			continue;

		TVector vecPoint, vecNormal;
		if (GetMoveParent() == pEntity)
		{
			TMatrix mGlobalToLocal = GetMoveParent()->GetGlobalToLocalTransform();
			Vector vecUpLocal = mGlobalToLocal.TransformNoTranslate(GetUpVector()) * m_flMaxStepSize;

			if (pEntity->CollideLocal(GetLocalOrigin(), GetLocalOrigin() - vecUpLocal, vecPoint, vecNormal))
			{
				SetGroundEntity(pEntity);
				SetSimulated(false);

				return;
			}
		}
		else
		{
			if (pEntity->Collide(GetGlobalOrigin(), GetGlobalOrigin() - vecUp, vecPoint, vecNormal))
			{
				SetGroundEntity(pEntity);
				SetSimulated(false);

				return;
			}
		}
	}

	SetGroundEntity(NULL);
	SetSimulated(true);
}
예제 #2
0
void CCharacter::MoveThink()
{
	if (!GetGroundEntity())
		return;

	if (m_vecGoalVelocity.LengthSqr())
		m_vecGoalVelocity.Normalize();

	m_vecMoveVelocity.x = Approach(m_vecGoalVelocity.x, m_vecMoveVelocity.x, GameServer()->GetFrameTime()*4);
	m_vecMoveVelocity.y = 0;
	m_vecMoveVelocity.z = Approach(m_vecGoalVelocity.z, m_vecMoveVelocity.z, GameServer()->GetFrameTime()*4);

	if (m_vecMoveVelocity.LengthSqr() > 0)
	{
		TMatrix m = GetLocalTransform();

		Vector vecUp = GetUpVector();
		
		if (HasMoveParent())
		{
			TMatrix mGlobalToLocal = GetMoveParent()->GetGlobalToLocalTransform();
			vecUp = mGlobalToLocal.TransformNoTranslate(vecUp);
		}

		Vector vecRight = m.GetForwardVector().Cross(vecUp).Normalized();
		Vector vecForward = vecUp.Cross(vecRight).Normalized();
		m.SetColumn(0, vecForward);
		m.SetColumn(1, vecUp);
		m.SetColumn(2, vecRight);

		TVector vecMove = m_vecMoveVelocity * CharacterSpeed();
		TVector vecLocalVelocity = m.TransformNoTranslate(vecMove);

		SetLocalVelocity(vecLocalVelocity);
	}
	else
		SetLocalVelocity(TVector());

	eastl::vector<CEntityHandle<CBaseEntity> > apCollisionList;

	size_t iMaxEntities = GameServer()->GetMaxEntities();
	for (size_t j = 0; j < iMaxEntities; j++)
	{
		CBaseEntity* pEntity2 = CBaseEntity::GetEntity(j);

		if (!pEntity2)
			continue;

		if (pEntity2->IsDeleted())
			continue;

		if (pEntity2 == this)
			continue;

		if (!pEntity2->ShouldCollide())
			continue;

		apCollisionList.push_back(pEntity2);
	}

	TMatrix mGlobalToLocalRotation;
	if (HasMoveParent())
	{
		mGlobalToLocalRotation = GetMoveParent()->GetGlobalToLocalTransform();
		mGlobalToLocalRotation.SetTranslation(TVector());
	}

	float flSimulationFrameTime = 0.01f;

	// Break simulations up into consistent small steps to preserve accuracy.
	for (; m_flMoveSimulationTime < GameServer()->GetGameTime(); m_flMoveSimulationTime += flSimulationFrameTime)
	{
		TVector vecVelocity = GetLocalVelocity();

		TVector vecLocalOrigin = GetLocalOrigin();
		TVector vecGlobalOrigin = GetGlobalOrigin();

		vecVelocity = vecVelocity * flSimulationFrameTime;

		TVector vecLocalDestination = vecLocalOrigin + vecVelocity;
		TVector vecGlobalDestination = vecLocalDestination;
		if (GetMoveParent())
			vecGlobalDestination = GetMoveParent()->GetGlobalTransform() * vecLocalDestination;

		TVector vecNewLocalOrigin = vecLocalDestination;

		size_t iTries = 0;
		while (true)
		{
			iTries++;

			TVector vecPoint, vecNormal;

			TVector vecLocalCollisionPoint, vecGlobalCollisionPoint;

			bool bContact = false;
			for (size_t i = 0; i < apCollisionList.size(); i++)
			{
				CBaseEntity* pEntity2 = apCollisionList[i];

				if (GetMoveParent() == pEntity2)
				{
					if (pEntity2->CollideLocal(vecLocalOrigin, vecLocalDestination, vecPoint, vecNormal))
					{
						bContact = true;
						Touching(pEntity2);
						vecLocalCollisionPoint = vecPoint;
						vecGlobalCollisionPoint = GetMoveParent()->GetGlobalTransform() * vecPoint;
					}
				}
				else
				{
					if (pEntity2->Collide(vecGlobalOrigin, vecGlobalDestination, vecPoint, vecNormal))
					{
						bContact = true;
						Touching(pEntity2);
						vecGlobalCollisionPoint = vecPoint;
						if (GetMoveParent())
						{
							vecLocalCollisionPoint = GetMoveParent()->GetGlobalToLocalTransform() * vecPoint;
							vecNormal = GetMoveParent()->GetGlobalToLocalTransform().TransformNoTranslate(vecNormal);
						}
						else
							vecLocalCollisionPoint = vecGlobalCollisionPoint;
					}
				}
			}

			if (bContact)
			{
				vecNewLocalOrigin = vecLocalCollisionPoint;
				vecVelocity -= vecLocalCollisionPoint - vecLocalOrigin;
			}

			if (!bContact)
				break;

			if (iTries > 4)
				break;

			vecLocalOrigin = vecLocalCollisionPoint;
			vecGlobalOrigin = vecGlobalCollisionPoint;

			// Clip the velocity to the surface normal of whatever we hit.
			TFloat flDistance = vecVelocity.Dot(vecNormal);

			vecVelocity = vecVelocity - vecNormal * flDistance;

			// Do it one more time just to make sure we're not headed towards the plane.
			TFloat flAdjust = vecVelocity.Dot(vecNormal);
			if (flAdjust < 0.0f)
				vecVelocity -= (vecNormal * flAdjust);

			vecLocalDestination = vecLocalOrigin + vecVelocity;

			if (GetMoveParent())
				vecGlobalDestination = GetMoveParent()->GetGlobalTransform() * vecLocalDestination;
			else
				vecGlobalDestination = vecLocalDestination;

			SetLocalVelocity(vecVelocity.Normalized() * GetLocalVelocity().Length());
		}

		SetLocalOrigin(vecNewLocalOrigin);

		// Try to keep the player on the ground.
		// Untested.
		/*TVector vecStart = GetGlobalOrigin() + GetGlobalTransform().GetUpVector()*m_flMaxStepSize;
		TVector vecEnd = GetGlobalOrigin() - GetGlobalTransform().GetUpVector()*m_flMaxStepSize;

		// First go up a bit
		TVector vecHit, vecNormal;
		Game()->TraceLine(GetGlobalOrigin(), vecStart, vecHit, vecNormal, NULL);
		vecStart = vecHit;

		// Now see if there's ground underneath us.
		bool bHit = Game()->TraceLine(vecStart, vecEnd, vecHit, vecNormal, NULL);
		if (bHit && vecNormal.y >= TFloat(0.7f))
			SetGlobalOrigin(vecHit);*/

		m_flMoveSimulationTime += flSimulationFrameTime;
	}
}
예제 #3
0
void LCPPolyDist<VectorIn,TVector,TTuple>::VerifyWithTestPoints (
    const TVector* akRes, int& riStatusCode)
{
    TVector* akTestPoints1 = new TVector[13];
    TVector* akTestPoints2 = new TVector[13];

    SetupTestPoints(1,m_iNumFaces1,m_iNumPoints1,akRes[0],m_adB1,m_akA1,
        m_akP1,akTestPoints1);
    SetupTestPoints(2,m_iNumFaces2,m_iNumPoints2,akRes[1],m_adB2,m_akA2,
        m_akP2,akTestPoints2);

    double fDiffSq;
    double fMin;
    TVector kDiff;
    int iLine = 0;
    int jLine = 0;

    // min distance between generated points note that one of these points
    // is the "solution"
    int i;
    for (i = 0; i < 13; i++)
    {
        for (int j = 0; j < 13; j++)
        {
            kDiff = akTestPoints1[i]-akTestPoints2[j];
            fDiffSq = kDiff.Dot(kDiff);
            if ( i == 0 && j == 0 )
            {
                fMin = fDiffSq;
            }
            else
            {
                if ( fDiffSq < fMin )
                {
                    fMin = fDiffSq;
                    iLine = i;
                    jLine = j;
                }
            }
        }
    }

    kDiff = akRes[0]-akRes[1];
    float fDistance = (float) kDiff.Dot(kDiff);

    riStatusCode = SC_FOUND_SOLUTION;
    if ( fDistance > fDiffSq )
    {
        m_kLog << "Test points closer than solution points by ";
        m_kLog << fDistance-fDiffSq << " squared units.\n";
        if ( (fDistance-fDiffSq > VERIFY_MIN_DIFFERENCE)
        &&   (iLine != 12 || jLine != 12) )
        {
            riStatusCode = SC_TEST_POINTS_TEST_FAILED;
        }
    }
    m_kLog << endl << " Solution points are separated by "
        << Mathf::Sqrt(fDistance);
    m_kLog << " units." << endl;
    m_kLog << "The smallest distance between test points is "
        << Mathf::Sqrt((float)fMin);
    m_kLog << endl << "and occurs for (" << akTestPoints1[iLine][0];
    for (i = 1; i < m_iDimension; i++)
    {
        m_kLog << ", " << akTestPoints1[iLine][i];
    }
    m_kLog << ") and (" << akTestPoints2[jLine][0];
    for (i = 1; i < m_iDimension; i++)
        m_kLog << ", " << akTestPoints2[jLine][i];
    m_kLog << ")" << endl;

    delete[] akTestPoints1;
    delete[] akTestPoints2;
}