fix(DB/Gameobject): Recalculate quaternion rotation values from orientation (#24617)

This commit is contained in:
blinkysc
2026-02-06 14:41:08 -06:00
committed by GitHub
parent 653136e311
commit 9b63cde7cb
8 changed files with 105 additions and 41 deletions

View File

@@ -298,7 +298,7 @@ bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, u
return false;
}
SetLocalRotation(rotation);
SetWorldRotation(rotation);
GameObjectAddon const* gameObjectAddon = sObjectMgr->GetGameObjectAddon(GetSpawnId());
QuaternionData parentRotation;
@@ -1038,7 +1038,7 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask, bool
data.posY = GetPositionY();
data.posZ = GetPositionZ();
data.orientation = GetOrientation();
data.rotation = m_localRotation;
data.rotation = WorldRotation;
data.spawntimesecs = m_spawnedByDefault ? m_respawnDelayTime : -(int32)m_respawnDelayTime;
data.animprogress = GetGoAnimProgress();
data.go_state = GetGoState();
@@ -1064,10 +1064,10 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask, bool
stmt->SetData(index++, GetPositionY());
stmt->SetData(index++, GetPositionZ());
stmt->SetData(index++, GetOrientation());
stmt->SetData(index++, m_localRotation.x);
stmt->SetData(index++, m_localRotation.y);
stmt->SetData(index++, m_localRotation.z);
stmt->SetData(index++, m_localRotation.w);
stmt->SetData(index++, WorldRotation.x);
stmt->SetData(index++, WorldRotation.y);
stmt->SetData(index++, WorldRotation.z);
stmt->SetData(index++, WorldRotation.w);
stmt->SetData(index++, int32(m_respawnDelayTime));
stmt->SetData(index++, GetGoAnimProgress());
stmt->SetData(index++, uint8(GetGoState()));
@@ -2199,24 +2199,18 @@ void GameObject::UpdatePackedRotation()
static const int32 PACK_X = PACK_YZ << 1;
static const int32 PACK_YZ_MASK = (PACK_YZ << 1) - 1;
static const int32 PACK_X_MASK = (PACK_X << 1) - 1;
int8 w_sign = (m_localRotation.w >= 0.f ? 1 : -1);
int64 x = int32(m_localRotation.x * PACK_X) * w_sign & PACK_X_MASK;
int64 y = int32(m_localRotation.y * PACK_YZ) * w_sign & PACK_YZ_MASK;
int64 z = int32(m_localRotation.z * PACK_YZ) * w_sign & PACK_YZ_MASK;
int8 w_sign = (WorldRotation.w >= 0.f ? 1 : -1);
int64 x = int32(WorldRotation.x * PACK_X) * w_sign & PACK_X_MASK;
int64 y = int32(WorldRotation.y * PACK_YZ) * w_sign & PACK_YZ_MASK;
int64 z = int32(WorldRotation.z * PACK_YZ) * w_sign & PACK_YZ_MASK;
m_packedRotation = z | (y << 21) | (x << 42);
}
void GameObject::SetLocalRotation(G3D::Quat const& rot)
void GameObject::SetWorldRotation(G3D::Quat const& rot)
{
G3D::Quat rotation;
// Temporary solution for gameobjects that have no rotation data in DB:
if (G3D::fuzzyEq(rot.z, 0.f) && G3D::fuzzyEq(rot.w, 0.f))
rotation = G3D::Quat::fromAxisAngleRotation(G3D::Vector3::unitZ(), GetOrientation());
else
rotation = rot;
G3D::Quat rotation = rot;
rotation.unitize();
m_localRotation = rotation;
WorldRotation = rotation;
UpdatePackedRotation();
}
@@ -2228,26 +2222,26 @@ void GameObject::SetTransportPathRotation(float qx, float qy, float qz, float qw
SetFloatValue(GAMEOBJECT_PARENTROTATION + 3, qw);
}
void GameObject::SetLocalRotationAngles(float z_rot, float y_rot, float x_rot)
void GameObject::SetWorldRotationAngles(float z_rot, float y_rot, float x_rot)
{
SetLocalRotation(G3D::Quat(G3D::Matrix3::fromEulerAnglesZYX(z_rot, y_rot, x_rot)));
SetWorldRotation(G3D::Quat(G3D::Matrix3::fromEulerAnglesZYX(z_rot, y_rot, x_rot)));
}
G3D::Quat GameObject::GetWorldRotation() const
G3D::Quat GameObject::GetFinalWorldRotation() const
{
G3D::Quat localRotation = GetLocalRotation();
G3D::Quat worldRotation = GetWorldRotation();
if (Transport* transport = GetTransport())
{
G3D::Quat worldRotation = transport->GetWorldRotation();
G3D::Quat transportRotation = transport->GetWorldRotation();
G3D::Quat transportRotationQuat(transportRotation.x, transportRotation.y, transportRotation.z, transportRotation.w);
G3D::Quat worldRotationQuat(worldRotation.x, worldRotation.y, worldRotation.z, worldRotation.w);
G3D::Quat localRotationQuat(localRotation.x, localRotation.y, localRotation.z, localRotation.w);
G3D::Quat resultRotation = localRotationQuat * worldRotationQuat;
G3D::Quat resultRotation = worldRotationQuat * transportRotationQuat;
return G3D::Quat(resultRotation.x, resultRotation.y, resultRotation.z, resultRotation.w);
}
return localRotation;
return worldRotation;
}
void GameObject::ModifyHealth(int32 change, Unit* attackerOrHealer /*= nullptr*/, uint32 spellId /*= 0*/)
@@ -2967,10 +2961,10 @@ bool GameObject::IsAtInteractDistance(Position const& pos, float radius) const
float maxY = displayInfo->maxY * scale + radius;
float maxZ = displayInfo->maxZ * scale + radius;
G3D::Quat worldRotation = GetWorldRotation();
G3D::Quat worldRotationQuat(worldRotation.x, worldRotation.y, worldRotation.z, worldRotation.w);
G3D::Quat finalRotation = GetFinalWorldRotation();
G3D::Quat finalRotationQuat(finalRotation.x, finalRotation.y, finalRotation.z, finalRotation.w);
return G3D::CoordinateFrame {{worldRotationQuat}, {GetPositionX(), GetPositionY(), GetPositionZ()}}.toWorldSpace(G3D::Box {{minX, minY, minZ}, {maxX, maxY, maxZ}}).contains({pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()});
return G3D::CoordinateFrame {{finalRotationQuat}, {GetPositionX(), GetPositionY(), GetPositionZ()}}.toWorldSpace(G3D::Box {{minX, minY, minZ}, {maxX, maxY, maxZ}}).contains({pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()});
}
return GetExactDist(&pos) <= radius;

View File

@@ -144,12 +144,12 @@ public:
[[nodiscard]] ObjectGuid::LowType GetSpawnId() const { return m_spawnId; }
// z_rot, y_rot, x_rot - rotation angles around z, y and x axes
void SetLocalRotationAngles(float z_rot, float y_rot, float x_rot);
void SetLocalRotation(G3D::Quat const& rot);
void SetWorldRotationAngles(float z_rot, float y_rot, float x_rot);
void SetWorldRotation(G3D::Quat const& rot);
void SetTransportPathRotation(float qx, float qy, float qz, float qw);
[[nodiscard]] G3D::Quat const& GetLocalRotation() const { return m_localRotation; }
[[nodiscard]] int64 GetPackedLocalRotation() const { return m_packedRotation; }
[[nodiscard]] G3D::Quat GetWorldRotation() const;
[[nodiscard]] G3D::Quat const& GetWorldRotation() const { return WorldRotation; }
[[nodiscard]] int64 GetPackedWorldRotation() const { return m_packedRotation; }
[[nodiscard]] G3D::Quat GetFinalWorldRotation() const;
// overwrite WorldObject function for proper name localization
[[nodiscard]] std::string const& GetNameForLocaleIdx(LocaleConstant locale_idx) const override;
@@ -394,7 +394,7 @@ protected:
bool m_allowModifyDestructibleBuilding;
int64 m_packedRotation;
G3D::Quat m_localRotation;
G3D::Quat WorldRotation;
Position m_stationaryPosition;
ObjectGuid m_lootRecipient;