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);
}
void CCharacter::ShowPlayerVectors() const
{
	TMatrix m = GetGlobalTransform();

	Vector vecUp = GetUpVector();
	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);

	CCharacter* pLocalCharacter = Game()->GetLocalPlayer()->GetCharacter();

	TVector vecEyeHeight = GetUpVector() * EyeHeight();

	CRenderingContext c(GameServer()->GetRenderer());

	c.Translate((GetGlobalOrigin() - pLocalCharacter->GetGlobalOrigin()));
	c.SetColor(Color(255, 255, 255));
	c.BeginRenderDebugLines();
	c.Vertex(Vector(0,0,0));
	c.Vertex((float)EyeHeight() * vecUp);
	c.EndRender();

	if (!GetGlobalVelocity().IsZero())
	{
		c.BeginRenderDebugLines();
		c.Vertex(vecEyeHeight);
		c.Vertex(vecEyeHeight + GetGlobalVelocity());
		c.EndRender();
	}

	c.SetColor(Color(255, 0, 0));
	c.BeginRenderDebugLines();
	c.Vertex(vecEyeHeight);
	c.Vertex(vecEyeHeight + vecForward);
	c.EndRender();

	c.SetColor(Color(0, 255, 0));
	c.BeginRenderDebugLines();
	c.Vertex(vecEyeHeight);
	c.Vertex(vecEyeHeight + vecRight);
	c.EndRender();

	c.SetColor(Color(0, 0, 255));
	c.BeginRenderDebugLines();
	c.Vertex(vecEyeHeight);
	c.Vertex(vecEyeHeight + vecUp);
	c.EndRender();

	TVector vecPoint, vecNormal;
	if (Game()->TraceLine(GetGlobalOrigin(), GetGlobalOrigin() - GetUpVector()*100, vecPoint, vecNormal, NULL))
	{
		c.Translate(vecPoint - GetGlobalOrigin());
		c.Scale(0.1f, 0.1f, 0.1f);
		c.SetColor(Color(255, 255, 255));
		c.RenderSphere();
	}
}
void CCharacterController::FindGround(btCollisionWorld* pCollisionWorld)
{
	if (m_hEntity->IsFlying())
	{
		m_hEntity->SetGroundEntity(nullptr);
		return;
	}

	if (GetVelocity().dot(GetUpVector()) > m_flJumpSpeed/2.0f)
	{
		m_hEntity->SetGroundEntity(nullptr);
		return;
	}

	bool bWalking = !m_hEntity->IsFlying() && m_hEntity->GetGroundEntity();

	float flDropHeight = bWalking?m_flStepHeight:m_pConvexShape->getMargin()*2;

	btVector3 vecStepDrop = GetUpVector() * flDropHeight;
	btVector3 vecGroundPosition = m_pGhostObject->getWorldTransform().getOrigin() - vecStepDrop;

	CTraceResult tr;
	PlayerTrace(pCollisionWorld, m_pGhostObject->getWorldTransform().getOrigin(), vecGroundPosition, tr);

	if (tr.m_flFraction < 1)
	{
		btScalar flDot = GetUpVector().dot(ToBTVector(tr.m_vecNormal));
		if (flDot < m_flMaxSlopeCosine)
			m_hEntity->SetGroundEntity(nullptr);
		else
		{
			CEntityHandle<CBaseEntity> hOther = CEntityHandle<CBaseEntity>(tr.m_iHit);
			if (hOther)
				m_hEntity->SetGroundEntity(hOther);
			else
			{
				m_hEntity->SetGroundEntityExtra(tr.m_iHitExtra);
			}
		}
	}
	else
		m_hEntity->SetGroundEntity(nullptr);

	if (bWalking && m_hEntity->GetGroundEntity() && tr.m_flFraction > 0.0f && tr.m_flFraction < 1.0f)
	{
		btVector3 vecNewOrigin;
		vecNewOrigin.setInterpolate3(m_pGhostObject->getWorldTransform().getOrigin(), vecGroundPosition, tr.m_flFraction);

		float flMargin = m_pConvexShape->getMargin() + 0.001f;
		if ((vecNewOrigin - m_pGhostObject->getWorldTransform().getOrigin()).length2() > flMargin*flMargin)
		{
			m_pGhostObject->getWorldTransform().setOrigin(vecNewOrigin);
			return;
		}
	}

	return;
}
void CCharacterController::PlayerFall(btCollisionWorld* pCollisionWorld, btScalar dt)
{
	Vector vecCurrentVelocity = m_hEntity->GetLocalVelocity();
	vecCurrentVelocity += ToTVector(GetGravity()) * dt;
	m_hEntity->SetLocalVelocity(vecCurrentVelocity);

	btVector3 vecVelocity = ToBTVector(vecCurrentVelocity);

	if (m_vecMoveVelocity.length2())
	{
		btVector3 vecAllowedMoveVelocity = PerpendicularComponent(m_vecMoveVelocity, GetUpVector());
		if (vecAllowedMoveVelocity.dot(vecVelocity) < 0)
			vecVelocity = PerpendicularComponent(vecVelocity, vecAllowedMoveVelocity.normalized());

		vecVelocity += vecAllowedMoveVelocity * dt;
	}

	if (vecVelocity.length2() > m_flMaxSpeed*m_flMaxSpeed)
		vecVelocity = vecVelocity.normalized() * m_flMaxSpeed;

	if (vecVelocity.length2() < 0.001f)
		return;

	btTransform mWorld;
	mWorld = m_pGhostObject->getWorldTransform();

	btVector3 vecOriginalPosition = mWorld.getOrigin();

	StepForwardAndStrafe(pCollisionWorld, vecVelocity * dt);
}
Exemple #5
0
EAngle Matrix4x4::GetAngles() const
{
#ifdef _DEBUG
	// If any of the below is not true then you have a matrix that has been scaled or reflected or something and it won't work to try to pull its Eulers
	bool b = fabs(GetForwardVector().LengthSqr() - 1) < 0.001f;
	if (!b)
	{
		TAssertNoMsg(b);
		return EAngle(0, 0, 0);
	}

	b = fabs(GetUpVector().LengthSqr() - 1) < 0.001f;
	if (!b)
	{
		TAssertNoMsg(b);
		return EAngle(0, 0, 0);
	}

	b = fabs(GetLeftVector().LengthSqr() - 1) < 0.001f;
	if (!b)
	{
		TAssertNoMsg(b);
		return EAngle(0, 0, 0);
	}

	b = GetForwardVector().Cross(GetLeftVector()).Equals(GetUpVector(), 0.001f);
	if (!b)
	{
		TAssertNoMsg(b);
		return EAngle(0, 0, 0);
	}
#endif

	if (m[0][2] > 0.999999f)
		return EAngle(asin(Clamp(m[0][2], -1.0f, 1.0f)) * 180/M_PI, -atan2(m[1][0], m[1][1]) * 180/M_PI, 0);
	else if (m[0][2] < -0.999999f)
		return EAngle(asin(Clamp(m[0][2], -1.0f, 1.0f)) * 180/M_PI, -atan2(m[1][0], m[1][1]) * 180/M_PI, 0);

	// Clamp to [-1, 1] looping
	float flPitch = fmod(m[0][2], 2.0f);
	if (flPitch > 1)
		flPitch -= 2;
	else if (flPitch < -1)
		flPitch += 2;

	return EAngle(asin(flPitch) * 180/M_PI, -atan2(-m[0][1], m[0][0]) * 180/M_PI, atan2(-m[1][2], m[2][2]) * 180/M_PI);
}
Vector Matrix4x4::GetScale() const
{
	Vector vecReturn;
	vecReturn.x = GetForwardVector().Length();
	vecReturn.y = GetUpVector().Length();
	vecReturn.z = GetRightVector().Length();
	return vecReturn;
}
void CCharacterController::jump()
{
	if (!canJump())
		return;

	SetJumpSpeed((float)m_hEntity->JumpStrength());

	m_hEntity->SetGlobalVelocity(ToTVector(GetUpVector()) * m_flJumpSpeed + m_hEntity->GetGlobalVelocity());

	m_hEntity->SetGroundEntity(nullptr);
}
// Use the information embedded in a matrix to create its inverse.
// http://youtu.be/7CxKAtWqHC8
Matrix4x4 Matrix4x4::InvertedTR() const
{
	// This method can only be used if the matrix is a translation/rotation matrix.
	// The below asserts will trigger if this is not the case.
	TAssert(fabs(GetForwardVector().LengthSqr() - 1) < 0.00001f);   // Each basis vector should be length 1.
	TAssert(fabs(GetUpVector().LengthSqr() - 1) < 0.00001f);
	TAssert(fabs(GetRightVector().LengthSqr() - 1) < 0.00001f);
	TAssert(fabs(GetForwardVector().Dot(GetUpVector())) < 0.0001f); // All vectors should be orthogonal.
	TAssert(fabs(GetForwardVector().Dot(GetRightVector())) < 0.0001f);
	TAssert(fabs(GetRightVector().Dot(GetUpVector())) < 0.0001f);

	Matrix4x4 M;

	// Create the transposed upper 3x3 matrix
	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++)
			M.m[i][j] = m[j][i];

	// The new matrix translation = -Rt
	M.SetTranslation(-(M*GetTranslation()));

	return M;
}
Exemple #9
0
DoubleMatrix4x4 DoubleMatrix4x4::InvertedRT() const
{
	TAssertNoMsg(fabs(GetForwardVector().LengthSqr() - 1) < 0.00001);
	TAssertNoMsg(fabs(GetLeftVector().LengthSqr() - 1) < 0.00001);
	TAssertNoMsg(fabs(GetUpVector().LengthSqr() - 1) < 0.00001);

	DoubleMatrix4x4 r;

	for (int h = 0; h < 3; h++)
		for (int v = 0; v < 3; v++)
			r.m[h][v] = m[v][h];

	r.SetTranslation(r*(-GetTranslation()));

	return r;
}
Exemple #10
0
void CCharacter::Jump()
{
	if (!GetGroundEntity())
		return;

	SetGroundEntity(NULL);

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

	SetLocalVelocity(GetLocalVelocity() + vecLocalUp * JumpStrength());
}
void CSPCharacter::LockViewToPlanet()
{
	// Now lock the roll value to the planet.
	CPlanet* pNearestPlanet = GetNearestPlanet();
	if (!pNearestPlanet)
		return;

	Matrix4x4 mGlobalRotation = GetGlobalTransform();
	mGlobalRotation.SetTranslation(CScalableVector());

	// Construct a "local space" for the planet
	Vector vecPlanetUp = GetUpVector();
	Vector vecPlanetForward = mGlobalRotation.GetForwardVector();
	Vector vecPlanetRight = vecPlanetForward.Cross(vecPlanetUp).Normalized();
	vecPlanetForward = vecPlanetUp.Cross(vecPlanetRight).Normalized();

	Matrix4x4 mPlanet(vecPlanetForward, vecPlanetUp, vecPlanetRight);
	Matrix4x4 mPlanetInverse = mPlanet;
	mPlanetInverse.InvertTR();

	// Bring our current view angles into that local space
	Matrix4x4 mLocalRotation = mPlanetInverse * mGlobalRotation;
	EAngle angLocalRotation = mLocalRotation.GetAngles();

	// Lock them so that the roll is 0
	// I'm sure there's a way to do this without converting to euler but at this point I don't care.
	angLocalRotation.r = 0;
	Matrix4x4 mLockedLocalRotation;
	mLockedLocalRotation.SetAngles(angLocalRotation);

	// Bring it back out to global space
	Matrix4x4 mLockedRotation = mPlanet * mLockedLocalRotation;

	// Only use the changed r value to avoid floating point crap
	EAngle angNewLockedRotation = GetGlobalAngles();
	EAngle angOverloadRotation = mLockedRotation.GetAngles();

	// Lerp our way there
	float flTimeToLocked = 1;
	if (GameServer()->GetGameTime() - m_flLastEnteredAtmosphere > flTimeToLocked)
		angNewLockedRotation.r = angOverloadRotation.r;
	else
		angNewLockedRotation.r = RemapValClamped(SLerp(GameServer()->GetGameTime() - m_flLastEnteredAtmosphere, 0.3f), 0, flTimeToLocked, m_flRollFromSpace, angOverloadRotation.r);

	SetGlobalAngles(angNewLockedRotation);
}
Exemple #12
0
// Not a true inversion, only works if the matrix is a translation/rotation matrix.
void Matrix4x4::InvertRT()
{
	TAssertNoMsg(fabs(GetForwardVector().LengthSqr() - 1) < 0.00001f);
	TAssertNoMsg(fabs(GetLeftVector().LengthSqr() - 1) < 0.00001f);
	TAssertNoMsg(fabs(GetUpVector().LengthSqr() - 1) < 0.00001f);

	Matrix4x4 t;

	for (int h = 0; h < 3; h++)
		for (int v = 0; v < 3; v++)
			t.m[h][v] = m[v][h];

	Vector vecTranslation = GetTranslation();

	Init(t);

	SetTranslation(t*(-vecTranslation));
}
void
JXMesaCamera::PrepareTransforms()
{
	// texture transform

	glMatrixMode(GL_TEXTURE);
	glLoadIdentity();

	// projection transform

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	const JFloat aspectRatio = itsGLViewport.width / (JFloat) itsGLViewport.height;
	if (itsPerspectiveFlag)
		{
		gluPerspective(itsFOVAngle, aspectRatio, itsNearZ, itsFarZ);
		}
	else
		{
		glOrtho(-1.0,+1.0,
				-1.0/aspectRatio,+1.0/aspectRatio,
				-1.0,+1.0);
		}

	// viewing transform -- must be last so objects can change it

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	const JVector& p = GetPosition();
	const JVector& a = GetAttentionPt();
	const JVector& u = GetUpVector();

	gluLookAt(p.GetElement(1), p.GetElement(2), p.GetElement(3),
			  a.GetElement(1), a.GetElement(2), a.GetElement(3),
			  u.GetElement(1), u.GetElement(2), u.GetElement(3));
}
Exemple #14
0
void Camera::RotateV(double angle) {
Rotate(GetEyePoint(), GetUpVector(), angle);
}
void CCharacterController::StepForwardAndStrafe(btCollisionWorld* pCollisionWorld, const btVector3& vecWalkMove)
{
	//printf("m_vecNormalizedDirection=%f,%f,%f\n", m_vecNormalizedDirection[0],m_vecNormalizedDirection[1],m_vecNormalizedDirection[2]);

	// phase 2: forward and strafe
	btVector3 vecStartPosition = m_pGhostObject->getWorldTransform().getOrigin();
	btVector3 vecTargetPosition = vecStartPosition + vecWalkMove;

	btScalar flFraction = 1.0;
	btScalar flDistance2 = (vecStartPosition-vecTargetPosition).length2();

	int iMaxIter = 4;

	while (flFraction > btScalar(0.01) && iMaxIter-- > 0)
	{
		CTraceResult tr;
		PlayerTrace(pCollisionWorld, vecStartPosition, vecTargetPosition, tr);

		flFraction -= tr.m_flFraction;

		if (tr.m_flFraction < 1)
		{
			Vector vecVelocity = m_hEntity->GetLocalVelocity();
			Vector vecNewVelocity = ToTVector(PerpendicularComponent(ToBTVector(vecVelocity), ToBTVector(tr.m_vecNormal)));
			m_hEntity->SetLocalVelocity(vecNewVelocity);

			vecStartPosition.setInterpolate3 (vecStartPosition, vecTargetPosition, tr.m_flFraction);

			btVector3 vecNormal = ToBTVector(tr.m_vecNormal);

			btVector3 vecMovement = vecTargetPosition-vecStartPosition;

			// Run along the wall we hit.
			btVector3 vecParallelDir = ParallelComponent(vecMovement, vecNormal);
			btVector3 vecPerpendicularDir = vecMovement - vecParallelDir;

			// If the vector is horizontal then we'll bring it back up to its original scale
			// so that we're sliding along a wall. If it's vertical though, we'll leave it at
			// the short scale so that we climb ramps slower.
			float flRescaleAmount = RemapVal(std::fabs(vecParallelDir.normalized().dot(GetUpVector())), 0, 1, vecMovement.length()/vecPerpendicularDir.length(), 1);

			vecTargetPosition = vecStartPosition + vecPerpendicularDir * flRescaleAmount;

			vecStartPosition += vecNormal * m_pConvexShape->getMargin();
			vecTargetPosition += vecNormal * m_pConvexShape->getMargin();

			btVector3 currentDir = vecTargetPosition - vecStartPosition;
			flDistance2 = currentDir.length2();
			if (flDistance2 > SIMD_EPSILON)
			{
				currentDir.normalize();
				/* See Quake2: "If velocity is against original velocity, stop ead to avoid tiny oscilations in sloping corners." */
				if (currentDir.dot(GetVelocity().normalized()) <= btScalar(0.0))
					break;
			} else
			{
				//printf("currentDir: don't normalize a zero vector\n");
				break;
			}

		} else {
			// we moved whole way
			vecStartPosition = vecTargetPosition;
		}
	}

	m_pGhostObject->getWorldTransform().setOrigin(vecStartPosition);
}
bool CCharacterController::RecoverFromPenetration(btCollisionWorld* pCollisionWorld)
{
	if (!IsColliding())
		return false;

	bool bPenetration = false;

	pCollisionWorld->getDispatcher()->dispatchAllCollisionPairs(m_pGhostObject->getOverlappingPairCache(), pCollisionWorld->getDispatchInfo(), pCollisionWorld->getDispatcher());

	btVector3 vecCurrentPosition = m_pGhostObject->getWorldTransform().getOrigin();
	btVector3 vecOriginalPosition = vecCurrentPosition;

	btScalar maxPen = btScalar(0.0);
	for (int i = 0; i < m_pGhostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++)
	{
		m_aManifolds.resize(0);

		btBroadphasePair* pCollisionPair = &m_pGhostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];

		btCollisionObject* pObject0 = static_cast<btCollisionObject*>(pCollisionPair->m_pProxy0->m_clientObject);
		btCollisionObject* pObject1 = static_cast<btCollisionObject*>(pCollisionPair->m_pProxy1->m_clientObject);

		if (!pObject0->hasContactResponse() || !pObject1->hasContactResponse())
			continue;

		if (pObject0->getBroadphaseHandle()->m_collisionFilterGroup == CG_TRIGGER || pObject1->getBroadphaseHandle()->m_collisionFilterGroup == CG_TRIGGER)
			continue;

		if (pCollisionPair->m_algorithm)
			pCollisionPair->m_algorithm->getAllContactManifolds(m_aManifolds);

		for (int j = 0; j < m_aManifolds.size(); j++)
		{
			btPersistentManifold* pManifold = m_aManifolds[j];

			const btCollisionObject* obA = static_cast<const btCollisionObject*>(pManifold->getBody0());
			const btCollisionObject* obB = static_cast<const btCollisionObject*>(pManifold->getBody1());

			btScalar directionSign;
			CEntityHandle<CBaseEntity> hOther;
			size_t iExtra;
			if (obA == m_pGhostObject)
			{
				if (obB->getBroadphaseHandle()->m_collisionFilterGroup & btBroadphaseProxy::SensorTrigger)
					continue;

				directionSign = btScalar(-1.0);
				hOther = CEntityHandle<CBaseEntity>((size_t)obB->getUserPointer());
				iExtra = (size_t)obB->getUserPointer()-GameServer()->GetMaxEntities();

				if (obB->getCollisionFlags()&btCollisionObject::CF_CHARACTER_OBJECT)
				{
					// If I'm heavier than he, don't let him push me around
					if (hOther->GetMass() < m_hEntity->GetMass())
						continue;
				}
			}
			else
			{
				if (obA->getBroadphaseHandle()->m_collisionFilterGroup & btBroadphaseProxy::SensorTrigger)
					continue;

				directionSign = btScalar(1.0);
				hOther = CEntityHandle<CBaseEntity>((size_t)obA->getUserPointer());
				iExtra = (size_t)obB->getUserPointer()-GameServer()->GetMaxEntities();

				if (obA->getCollisionFlags()&btCollisionObject::CF_CHARACTER_OBJECT)
				{
					// If I'm heavier than he, don't let him push me around
					if (hOther->GetMass() < m_hEntity->GetMass())
						continue;
				}
			}

			for (int p = 0; p < pManifold->getNumContacts(); p++)
			{
				const btManifoldPoint& pt = pManifold->getContactPoint(p);

				if (obA == m_pGhostObject)
				{
					if (hOther)
					{
						if (!m_hEntity->ShouldCollideWith(hOther, Vector(pt.getPositionWorldOnB())))
							continue;
					}
					else
					{
						if (!m_hEntity->ShouldCollideWithExtra(iExtra, Vector(pt.getPositionWorldOnB())))
							continue;
					}
				}
				else
				{
					if (hOther)
					{
						if (!m_hEntity->ShouldCollideWith(hOther, Vector(pt.getPositionWorldOnA())))
							continue;
					}
					else
					{
						if (!m_hEntity->ShouldCollideWithExtra(iExtra, Vector(pt.getPositionWorldOnA())))
							continue;
					}
				}

				btScalar flDistance = pt.getDistance();
				btScalar flMargin = std::max(obA->getCollisionShape()->getMargin(), obB->getCollisionShape()->getMargin());

				if (flDistance < -flMargin)
				{
					flDistance += flMargin;

					if (flDistance < maxPen)
						maxPen = flDistance;

					btScalar flDot = pt.m_normalWorldOnB.dot(GetUpVector());
					btVector3 vecAdjustment;
					if (flDot > 0.707f)
						vecAdjustment = GetUpVector() * (directionSign * flDistance * 1.001f);
					else
						vecAdjustment = pt.m_normalWorldOnB * (directionSign * flDistance * 1.001f);

					if (vecAdjustment.length2() < 0.001*0.001)
						continue;

					vecCurrentPosition += vecAdjustment;

					bPenetration = true;
				} else {
					//printf("touching %f\n", dist);
				}
			}

			//pManifold->clearManifold();
		}
	}

	btTransform mNew = m_pGhostObject->getWorldTransform();
	mNew.setOrigin(mNew.getOrigin() + (vecCurrentPosition - vecOriginalPosition) * m_vecLinearFactor);
	m_pGhostObject->setWorldTransform(mNew);

	return bPenetration;
}
bool CCharacterController::onGround() const
{
	return GetVelocity().dot(GetUpVector()) > 0;
}
void CCharacterController::PlayerWalk(btCollisionWorld* pCollisionWorld, btScalar dt)
{
	Vector vecCurrentVelocity = m_hEntity->GetLocalVelocity();
	vecCurrentVelocity.z = 0;

	// Calculate friction first, so that the player's movement commands can overwhelm it.
	if (vecCurrentVelocity.Length2DSqr() > 0.00001f)
	{
		if (m_hEntity->GetGroundEntity())
		{
			float flSpeed2D = vecCurrentVelocity.Length2D();

			float flFriction = sv_friction.GetFloat() * flSpeed2D * dt;

			float flNewSpeed = flSpeed2D - flFriction;

			if (flNewSpeed < 0)
				flNewSpeed = 0;

			float flScale = flNewSpeed / flSpeed2D;

			vecCurrentVelocity *= flScale;

			m_hEntity->SetLocalVelocity(vecCurrentVelocity);
		}
	}

	// Calculate a new velocity using the player's desired direction of travel.
	btVector3 vecWishDirection = m_vecMoveVelocity;
	vecWishDirection.setZ(0);
	float flWishVelocity = m_vecMoveVelocity.length();
	if (flWishVelocity)
		vecWishDirection = vecWishDirection / flWishVelocity;
	else
		vecWishDirection = btVector3(0, 0, 0);

	if (flWishVelocity > m_hEntity->CharacterSpeed())
		flWishVelocity = m_hEntity->CharacterSpeed();

	float flVelocityInWishDirection = GetVelocity().dot(vecWishDirection);

	float flDirectionChange = flWishVelocity - flVelocityInWishDirection;

	if (flDirectionChange > 0)
	{
		float flAccelerationAmount = flWishVelocity * m_hEntity->CharacterAcceleration() * dt;
		if (flAccelerationAmount > flDirectionChange)
			flAccelerationAmount = flDirectionChange;
		vecCurrentVelocity = vecCurrentVelocity + ToTVector(vecWishDirection) * flAccelerationAmount;

		TAssert(vecCurrentVelocity.z == 0);
	}

	float flCurrentVelocity = vecCurrentVelocity.Length();

	if (flCurrentVelocity > m_hEntity->CharacterSpeed())
		vecCurrentVelocity *= m_hEntity->CharacterSpeed()/flCurrentVelocity;

	if (vecCurrentVelocity.LengthSqr() < 0.001f)
	{
		m_hEntity->SetLocalVelocity(Vector());
		return;
	}

	btTransform mWorld = m_pGhostObject->getWorldTransform();

	// Try moving the player directly, if it's possible.
	{
		btVector3 vecTargetPosition = mWorld.getOrigin() + ToBTVector(vecCurrentVelocity) * dt;

		CTraceResult tr;
		PlayerTrace(pCollisionWorld, mWorld.getOrigin(), vecTargetPosition, tr);

		if (tr.m_flFraction == 1)
		{
			mWorld.setOrigin(vecTargetPosition);
			m_pGhostObject->setWorldTransform(mWorld);
			m_hEntity->SetLocalVelocity(vecCurrentVelocity);
			return;
		}
	}

	// There was something blocking the way. Try walking up a step or along walls.

	btVector3 vecSavedStepUp(0, 0, 0);

	{
		// Move up a bit to try to clear a step.
		btVector3 vecStartPosition = m_pGhostObject->getWorldTransform().getOrigin();
		btVector3 vecTargetPosition = m_pGhostObject->getWorldTransform().getOrigin() + GetUpVector() * m_flStepHeight;

		CTraceResult tr;
		PlayerTrace(pCollisionWorld, vecStartPosition, vecTargetPosition, tr);

		if (tr.m_flFraction < 1)
		{
			// we moved up only a fraction of the step height
			btVector3 vecInterpolated;
			vecInterpolated.setInterpolate3(m_pGhostObject->getWorldTransform().getOrigin(), vecTargetPosition, tr.m_flFraction);
			m_pGhostObject->getWorldTransform().setOrigin(vecInterpolated);

			vecSavedStepUp = vecInterpolated - vecStartPosition;
		}
		else
		{
			vecSavedStepUp = vecTargetPosition - vecStartPosition;
			m_pGhostObject->getWorldTransform().setOrigin(vecTargetPosition);
		}
	}

	StepForwardAndStrafe(pCollisionWorld, ToBTVector(vecCurrentVelocity) * dt);

	if (vecSavedStepUp.length2() > 0)
	{
		// Move back down as much as we moved up.
		btVector3 vecStartPosition = m_pGhostObject->getWorldTransform().getOrigin();
		btVector3 vecTargetPosition = m_pGhostObject->getWorldTransform().getOrigin() - vecSavedStepUp;

		CTraceResult tr;
		PlayerTrace(pCollisionWorld, vecStartPosition, vecTargetPosition, tr);

		if (tr.m_flFraction < 1)
		{
			btVector3 vecInterpolated;
			vecInterpolated.setInterpolate3(m_pGhostObject->getWorldTransform().getOrigin(), vecTargetPosition, tr.m_flFraction);
			m_pGhostObject->getWorldTransform().setOrigin(vecInterpolated);
		}
		else
			m_pGhostObject->getWorldTransform().setOrigin(vecTargetPosition);
	}
}
Exemple #19
0
void Player::AttackAnimationTimerFinished()
{
	if (IsBow())
	{
	}
	else if (IsBoomerang())
	{
		vec3 boomerangSpawnPosition = GetCenter() + (m_forward*0.75f) + (GetRightVector()*-0.4f) + (GetUpVector()*0.5f);

		float cameraModification = (m_cameraForward.y*17.5f);
		if (m_cameraForward.y < 0.0f)
		{
			cameraModification = (m_cameraForward.y*5.0f);
		}

		vec3 boomerangTarget = boomerangSpawnPosition + m_forward*15.0f + (vec3(0.0f, 1.0f, 0.0f) * cameraModification);
		if (m_pTargetEnemy != NULL)
		{
			boomerangTarget = m_pTargetEnemy->GetProjectileHitboxCenter();
			if (m_pTargetEnemy->IsMoving())
			{
				boomerangTarget += m_pTargetEnemy->GetForwardVector() * (m_pTargetEnemy->GetMovementSpeed() / 3.0f);
			}
		}

		float curveTime = length(boomerangTarget - boomerangSpawnPosition) / 15.0f;
		if (curveTime <= 0.4f)
			curveTime = 0.4f;

		Projectile* pProjectile = m_pProjectileManager->CreateProjectile(boomerangSpawnPosition, vec3(0.0f, 0.0f, 0.0f), 0.0f, "media/gamedata/weapons/Boomerang/BoomerangThrown.weapon", 0.05f);
		pProjectile->SetProjectileType(true, false, false);
		pProjectile->SetOwner(this, NULL, NULL);
		pProjectile->SetGravityMultiplier(0.0f);
		pProjectile->SetReturnToPlayer(true);
		pProjectile->SetProjectileCurveParams(m_forward, boomerangTarget, curveTime);
		pProjectile->SetWorldCollisionEnabled(true);

		m_pVoxelCharacter->SetRenderRightWeapon(false);
	}
	else if (IsStaff())
	{
		float powerAmount = 25.0f;
		float cameraMultiplier = 25.0f;

		vec3 spellSpawnPosition = GetCenter() + (m_forward*1.25f) + (GetUpVector()*0.25f);

		if (VoxGame::GetInstance()->GetCameraMode() == CameraMode_FirstPerson)
		{
			cameraMultiplier = 30.0f;
			spellSpawnPosition.y += 0.75f;
		}

		vec3 spellSpawnVelocity = m_forward * powerAmount + vec3(0.0f, 1.0f, 0.0f) * (m_cameraForward.y*cameraMultiplier);

		if (m_pTargetEnemy != NULL)
		{
			vec3 toTarget = m_pTargetEnemy->GetProjectileHitboxCenter() - GetCenter();
			spellSpawnVelocity = (normalize(toTarget) * powerAmount);
		}

		Projectile* pProjectile = m_pProjectileManager->CreateProjectile(spellSpawnPosition, spellSpawnVelocity, 0.0f, "media/gamedata/items/Fireball/Fireball.item", 0.05f);
		pProjectile->SetProjectileType(true, false, false);
		pProjectile->SetOwner(this, NULL, NULL);
		pProjectile->SetGravityMultiplier(0.0f);
	}
	else if (IsWand())
	{
	}
	else if (IsBomb())
	{
		vec3 bombSpawnPosition = GetCenter() + (m_forward*0.75f) + (GetUpVector()*0.5f);

		float liftAmount = 8.0f;
		float powerAmount = 30.0f;
		float cameraMultiplier = 25.0f;

		if (VoxGame::GetInstance()->GetCameraMode() == CameraMode_FirstPerson)
		{
			cameraMultiplier = 30.0f;
		}

		vec3 bombSpawnVelocity;
		if (m_pTargetEnemy)
		{
			// Enemy target
			vec3 toTarget = m_pTargetEnemy->GetCenter() - GetCenter();
			float toTargetDistance = length(toTarget);
			liftAmount += toTargetDistance * 0.04f;
			bombSpawnVelocity = (normalize(toTarget) * powerAmount) + vec3(0.0f, liftAmount, 0.0f);
		}
		else
		{
			bombSpawnVelocity = (m_forward * powerAmount) + (GetUpVector() * liftAmount) + vec3(0.0f, 1.0f, 0.0f) * (m_cameraForward.y*cameraMultiplier);
		}

		Projectile* pProjectile = m_pProjectileManager->CreateProjectile(bombSpawnPosition, bombSpawnVelocity, 0.0f, "media/gamedata/items/Bomb/BombThrown.item", 0.05f);
		pProjectile->SetProjectileType(true, false, false);
		pProjectile->SetOwner(this, NULL, NULL);
		pProjectile->SetGravityMultiplier(3.5f);
		float explodeRadius = 3.5f - (GetRandomNumber(-150, 0, 2) * 0.01f);
		pProjectile->SetExplodingProjectile(true, explodeRadius);

		//m_pVoxelCharacter->SetRenderRightWeapon(false);

		InventoryItem* pItem = m_pInventoryManager->GetInventoryItemForEquipSlot(EquipSlot_RightHand);
		if (pItem != NULL)
		{
			if (pItem->m_quantity != -1)
			{
				pItem->m_quantity -= 1;
			}
			if (pItem->m_quantity == 0)
			{
				// Remove this item from the manager, and remove it from the inventory and GUI
				UnequipItem(EquipSlot_RightHand, false, false);
				m_pInventoryManager->RemoveInventoryItem(EquipSlot_RightHand);
				m_pActionBar->RemoveInventoryItemFromActionBar(pItem->m_title);
			}
		}
	}
	else if (IsConsumable())
	{
	}
	else if (IsDagger())
	{
	}
	else if (IsHammer())
	{
	}
	else if (IsMace())
	{
	}
	else if (IsSickle())
	{
	}
	else if (IsPickaxe())
	{
		Item* pInteractItem = VoxGame::GetInstance()->GetInteractItem();
		if (pInteractItem != NULL)
		{
			pInteractItem->Interact();
		}
		else
		{
			DestroyBlock();
		}
	}
	else if (IsAxe())
	{
	}
	else if (Is2HandedSword())
	{
	}
	else if (IsSword())
	{
	}
	else if (IsBlockPlacing())
	{
	}
	else if (IsItemPlacing())
	{
	}
	else if (IsSceneryPlacing())
	{
	}
	else if (IsSpellHands())
	{
		float powerAmount = 25.0f;
		float cameraMultiplier = 25.0f;

		vec3 spellSpawnPosition = GetCenter() + (m_forward*0.5f) + (GetUpVector()*0.0f);

		// For right hand
		spellSpawnPosition += -(GetRightVector()*0.4f);

		if (VoxGame::GetInstance()->GetCameraMode() == CameraMode_FirstPerson)
		{
			cameraMultiplier = 30.0f;
			spellSpawnPosition.y += 0.75f;
		}

		vec3 spellSpawnVelocity = m_forward * powerAmount + vec3(0.0f, 1.0f, 0.0f) * (m_cameraForward.y*cameraMultiplier);

		if (m_pTargetEnemy != NULL)
		{
			vec3 toTarget = m_pTargetEnemy->GetProjectileHitboxCenter() - GetCenter();
			spellSpawnVelocity = (normalize(toTarget) * powerAmount);
		}

		Projectile* pProjectile = m_pProjectileManager->CreateProjectile(spellSpawnPosition, spellSpawnVelocity, 0.0f, "media/gamedata/items/Fireball/FireballBlue.item", 0.05f);
		pProjectile->SetProjectileType(true, false, false);
		pProjectile->SetOwner(this, NULL, NULL);
		pProjectile->SetGravityMultiplier(0.0f);
	}
	else if (IsShield())
	{
	}
	else if (IsTorch())
	{
	}
}
Exemple #20
0
void Player::AttackAnimationTimerFinished_Alternative()
{
	if (IsBow())
	{
	}
	else if (IsBoomerang())
	{
	}
	else if (IsStaff())
	{
	}
	else if (IsWand())
	{
	}
	else if (IsBomb())
	{
	}
	else if (IsConsumable())
	{
	}
	else if (IsDagger())
	{
	}
	else if (IsHammer())
	{
	}
	else if (IsMace())
	{
	}
	else if (IsSickle())
	{
	}
	else if (IsPickaxe())
	{
	}
	else if (IsAxe())
	{
	}
	else if (Is2HandedSword())
	{
	}
	else if (IsSword())
	{
	}
	else if (IsBlockPlacing())
	{
	}
	else if (IsItemPlacing())
	{
	}
	else if (IsSceneryPlacing())
	{
	}
	else if (IsSpellHands())
	{
		float powerAmount = 25.0f;
		float cameraMultiplier = 25.0f;

		vec3 spellSpawnPosition = GetCenter() + (m_forward*0.5f) + (GetUpVector()*0.0f);

		// For left hand
		spellSpawnPosition += (GetRightVector()*0.4f);

		if (VoxGame::GetInstance()->GetCameraMode() == CameraMode_FirstPerson)
		{
			cameraMultiplier = 30.0f;
			spellSpawnPosition.y += 0.75f;
		}

		vec3 spellSpawnVelocity = m_forward * powerAmount + vec3(0.0f, 1.0f, 0.0f) * (m_cameraForward.y*cameraMultiplier);

		if (m_pTargetEnemy != NULL)
		{
			vec3 toTarget = m_pTargetEnemy->GetProjectileHitboxCenter() - GetCenter();
			spellSpawnVelocity = (normalize(toTarget) * powerAmount);
		}

		Projectile* pProjectile = m_pProjectileManager->CreateProjectile(spellSpawnPosition, spellSpawnVelocity, 0.0f, "media/gamedata/items/Fireball/FireballBlue.item", 0.05f);
		pProjectile->SetProjectileType(true, false, false);
		pProjectile->SetOwner(this, NULL, NULL);
		pProjectile->SetGravityMultiplier(0.0f);
	}
	else if (IsShield())
	{
	}
	else if (IsTorch())
	{
	}
}
Exemple #21
0
void Camera::RotateU(double angle) {
	Rotate(GetEyePoint(), cross(GetLookVector(), GetUpVector()), angle);
}
Exemple #22
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;
	}
}