Matrix4x4 CLevelEntity::CalculateGlobalTransform(CLevelEntity* pThis) { Matrix4x4 mLocal; tstring sLocalOrigin = pThis->GetParameterValue("Origin"); if (sLocalOrigin.length() && CanUnserializeString_TVector(sLocalOrigin)) mLocal.SetTranslation(UnserializeString_TVector(sLocalOrigin)); tstring sLocalAngles = pThis->GetParameterValue("Angles"); if (sLocalAngles.length() && CanUnserializeString_EAngle(sLocalAngles)) mLocal.SetAngles(UnserializeString_EAngle(sLocalAngles)); tstring sAABB = pThis->GetParameterValue("BoundingBox"); if (CanUnserializeString_AABB(sAABB)) { AABB aabbBounds = UnserializeString_AABB(sAABB, pThis->GetName(), pThis->m_sClass, "BoundingBox"); // Center the entity around this bounding box. Vector vecGlobalOrigin = aabbBounds.Center(); mLocal.SetTranslation(mLocal.GetTranslation() + vecGlobalOrigin); Vector vecNewOrigin = mLocal.GetTranslation(); pThis->SetParameterValue("Origin", pretty_float(vecNewOrigin.x) + " " + pretty_float(vecNewOrigin.y) + " " + pretty_float(vecNewOrigin.z)); aabbBounds.m_vecMins -= vecGlobalOrigin; aabbBounds.m_vecMaxs -= vecGlobalOrigin; pThis->SetParameterValue("BoundingBox", pretty_float(aabbBounds.m_vecMins.x) + " " + pretty_float(aabbBounds.m_vecMins.y) + " " + pretty_float(aabbBounds.m_vecMins.z) + " " + pretty_float(aabbBounds.m_vecMaxs.x) + " " + pretty_float(aabbBounds.m_vecMaxs.y) + " " + pretty_float(aabbBounds.m_vecMaxs.z)); } return mLocal; }
Matrix4x4 Matrix4x4::AddAngles(const EAngle& a) { Matrix4x4 r; r.SetAngles(a); (*this) *= r; return *this; }
Matrix4x4 Matrix4x4::operator+=(const EAngle& a) { Matrix4x4 r; r.SetAngles(a); (*this) *= r; return *this; }
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); }