mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-17 09:33:51 +00:00
Add mount pitch and roll for realistic taxi flight animation
Flying mounts now tilt and bank realistically during taxi flights: - Pitch (up/down): calculated from spline tangent's z-component (altitude change) - Roll (banking): proportional to turn rate, clamped to ~40 degrees - Yaw: existing horizontal orientation from spline direction Implementation: - Added mountPitch_ and mountRoll_ to Renderer (radians) - Updated TaxiOrientationCallback to pass yaw, pitch, roll - Calculate pitch using asin(tangent.z) for altitude tilt - Calculate roll from yaw change rate: -orientDiff * 2.5, clamped to ±0.7 rad - Applied to mount rotation: glm::vec3(pitch, roll, yaw) This fixes the "weirdness" where mounts flew sideways or without natural banking.
This commit is contained in:
parent
2e0a7e0039
commit
92031102e4
5 changed files with 34 additions and 12 deletions
|
|
@ -501,8 +501,8 @@ public:
|
|||
using TaxiPrecacheCallback = std::function<void(const std::vector<glm::vec3>&)>;
|
||||
void setTaxiPrecacheCallback(TaxiPrecacheCallback cb) { taxiPrecacheCallback_ = std::move(cb); }
|
||||
|
||||
// Taxi orientation callback (for mount rotation)
|
||||
using TaxiOrientationCallback = std::function<void(float orientationRadians)>;
|
||||
// Taxi orientation callback (for mount rotation: yaw, pitch, roll in radians)
|
||||
using TaxiOrientationCallback = std::function<void(float yaw, float pitch, float roll)>;
|
||||
void setTaxiOrientationCallback(TaxiOrientationCallback cb) { taxiOrientationCallback_ = std::move(cb); }
|
||||
|
||||
// Callback for when taxi flight is about to start (after mounting delay, before movement begins)
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ public:
|
|||
// Mount rendering
|
||||
void setMounted(uint32_t mountInstId, float heightOffset);
|
||||
void setTaxiFlight(bool onTaxi) { taxiFlight_ = onTaxi; }
|
||||
void setMountPitchRoll(float pitch, float roll) { mountPitch_ = pitch; mountRoll_ = roll; }
|
||||
void clearMount();
|
||||
bool isMounted() const { return mountInstanceId_ != 0; }
|
||||
|
||||
|
|
@ -274,6 +275,8 @@ private:
|
|||
// Mount state
|
||||
uint32_t mountInstanceId_ = 0;
|
||||
float mountHeightOffset_ = 0.0f;
|
||||
float mountPitch_ = 0.0f; // Up/down tilt (radians)
|
||||
float mountRoll_ = 0.0f; // Left/right banking (radians)
|
||||
bool taxiFlight_ = false;
|
||||
|
||||
bool terrainEnabled = true;
|
||||
|
|
|
|||
|
|
@ -719,11 +719,13 @@ void Application::setupUICallbacks() {
|
|||
});
|
||||
|
||||
// Taxi orientation callback - update mount rotation during flight
|
||||
gameHandler->setTaxiOrientationCallback([this](float orientationRadians) {
|
||||
gameHandler->setTaxiOrientationCallback([this](float yaw, float pitch, float roll) {
|
||||
if (renderer && renderer->getCameraController()) {
|
||||
// Convert radians to degrees for camera controller
|
||||
float yawDegrees = glm::degrees(orientationRadians);
|
||||
// Convert radians to degrees for camera controller (character facing)
|
||||
float yawDegrees = glm::degrees(yaw);
|
||||
renderer->getCameraController()->setFacingYaw(yawDegrees);
|
||||
// Set mount pitch and roll for realistic flight animation
|
||||
renderer->setMountPitchRoll(pitch, roll);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -5195,12 +5195,17 @@ void GameHandler::startClientTaxiPath(const std::vector<uint32_t>& pathNodes) {
|
|||
glm::vec3 dir = end - start;
|
||||
float initialOrientation = std::atan2(dir.y, dir.x) - 1.57079632679f;
|
||||
|
||||
// Calculate initial pitch from altitude change
|
||||
glm::vec3 dirNorm = glm::normalize(dir);
|
||||
float initialPitch = std::asin(std::clamp(dirNorm.z, -1.0f, 1.0f));
|
||||
float initialRoll = 0.0f; // No initial banking
|
||||
|
||||
playerEntity->setPosition(start.x, start.y, start.z, initialOrientation);
|
||||
movementInfo.orientation = initialOrientation;
|
||||
|
||||
// Update mount rotation immediately
|
||||
// Update mount rotation immediately with pitch and roll
|
||||
if (taxiOrientationCallback_) {
|
||||
taxiOrientationCallback_(initialOrientation);
|
||||
taxiOrientationCallback_(initialOrientation, initialPitch, initialRoll);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5281,15 +5286,24 @@ void GameHandler::updateClientTaxi(float deltaTime) {
|
|||
3.0f * (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t2
|
||||
);
|
||||
|
||||
// Smooth orientation based on spline tangent
|
||||
// Calculate yaw from horizontal direction
|
||||
float targetOrientation = std::atan2(tangent.y, tangent.x) - 1.57079632679f;
|
||||
|
||||
// Smooth rotation transition (lerp towards target)
|
||||
// Calculate pitch from vertical component (altitude change)
|
||||
glm::vec3 tangentNorm = glm::normalize(tangent);
|
||||
float pitch = std::asin(std::clamp(tangentNorm.z, -1.0f, 1.0f));
|
||||
|
||||
// Calculate roll (banking) from rate of yaw change
|
||||
float currentOrientation = movementInfo.orientation;
|
||||
float orientDiff = targetOrientation - currentOrientation;
|
||||
// Normalize angle difference to [-PI, PI]
|
||||
while (orientDiff > 3.14159265f) orientDiff -= 6.28318530f;
|
||||
while (orientDiff < -3.14159265f) orientDiff += 6.28318530f;
|
||||
// Bank proportional to turn rate (scaled for visual effect)
|
||||
float roll = -orientDiff * 2.5f;
|
||||
roll = std::clamp(roll, -0.7f, 0.7f); // Limit to ~40 degrees
|
||||
|
||||
// Smooth rotation transition (lerp towards target)
|
||||
float smoothOrientation = currentOrientation + orientDiff * std::min(1.0f, deltaTime * 3.0f);
|
||||
|
||||
playerEntity->setPosition(nextPos.x, nextPos.y, nextPos.z, smoothOrientation);
|
||||
|
|
@ -5298,9 +5312,9 @@ void GameHandler::updateClientTaxi(float deltaTime) {
|
|||
movementInfo.z = nextPos.z;
|
||||
movementInfo.orientation = smoothOrientation;
|
||||
|
||||
// Update mount rotation to face flight direction
|
||||
// Update mount rotation with yaw, pitch, and roll for realistic flight
|
||||
if (taxiOrientationCallback_) {
|
||||
taxiOrientationCallback_(smoothOrientation);
|
||||
taxiOrientationCallback_(smoothOrientation, pitch, roll);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -508,6 +508,8 @@ void Renderer::setMounted(uint32_t mountInstId, float heightOffset) {
|
|||
void Renderer::clearMount() {
|
||||
mountInstanceId_ = 0;
|
||||
mountHeightOffset_ = 0.0f;
|
||||
mountPitch_ = 0.0f;
|
||||
mountRoll_ = 0.0f;
|
||||
charAnimState = CharAnimState::IDLE;
|
||||
if (cameraController) {
|
||||
cameraController->setMounted(false);
|
||||
|
|
@ -659,7 +661,8 @@ void Renderer::updateCharacterAnimation() {
|
|||
if (mountInstanceId_ > 0) {
|
||||
characterRenderer->setInstancePosition(mountInstanceId_, characterPosition);
|
||||
float yawRad = glm::radians(characterYaw);
|
||||
characterRenderer->setInstanceRotation(mountInstanceId_, glm::vec3(0.0f, 0.0f, yawRad));
|
||||
// Apply pitch (up/down), roll (banking), and yaw for realistic flight
|
||||
characterRenderer->setInstanceRotation(mountInstanceId_, glm::vec3(mountPitch_, mountRoll_, yawRad));
|
||||
|
||||
// Drive mount model animation: idle when still, run when moving
|
||||
auto pickMountAnim = [&](std::initializer_list<uint32_t> candidates, uint32_t fallback) -> uint32_t {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue