mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-25 13:03:50 +00:00
perf: eliminate ~70 unnecessary sqrt ops per frame, optimize caches and threading
Squared distance optimizations across 30 files: - Convert glm::length() comparisons to glm::dot() (no sqrt) - Use glm::inversesqrt() for check-then-normalize patterns (1 rsqrt vs 2 sqrt) - Defer sqrt to after early-out checks in collision/movement code - Hottest paths: camera_controller (21), weather particles, WMO collision, transport movement, creature interpolation, nameplate culling Container and algorithm improvements: - std::map<string> → std::unordered_map for asset/DBC/MPQ/warden caches - std::mutex → std::shared_mutex for asset_manager and mpq_manager caches - std::sort → std::partial_sort in lighting_manager (top-2 of N volumes) - Double-lookup find()+operator[] → insert_or_assign in game_handler - Add reserve() for per-frame vectors: weather, swim_effects, WMO/M2 collision Threading and synchronization: - Replace 1ms busy-wait polling with condition_variable in character_renderer - Move timestamp capture before mutex in logger - Use memory_order_acquire/release for normal map completion signaling API additions: - DBC getStringView()/getStringViewByOffset() for zero-copy string access - Parse creature display IDs from SMSG_CREATURE_QUERY_SINGLE_RESPONSE
This commit is contained in:
parent
cf0e2aa240
commit
b0466e9029
29 changed files with 328 additions and 196 deletions
|
|
@ -111,9 +111,11 @@ std::optional<float> CameraController::getCachedFloorHeight(float x, float y, fl
|
|||
// Check cache validity (position within threshold and frame count)
|
||||
glm::vec2 queryPos(x, y);
|
||||
glm::vec2 cachedPos(lastFloorQueryPos.x, lastFloorQueryPos.y);
|
||||
float dist = glm::length(queryPos - cachedPos);
|
||||
glm::vec2 dq = queryPos - cachedPos;
|
||||
float distSq = glm::dot(dq, dq);
|
||||
constexpr float kFloorThresholdSq = FLOOR_QUERY_DISTANCE_THRESHOLD * FLOOR_QUERY_DISTANCE_THRESHOLD;
|
||||
|
||||
if (dist < FLOOR_QUERY_DISTANCE_THRESHOLD && floorQueryFrameCounter < FLOOR_QUERY_FRAME_INTERVAL) {
|
||||
if (distSq < kFloorThresholdSq && floorQueryFrameCounter < FLOOR_QUERY_FRAME_INTERVAL) {
|
||||
floorQueryFrameCounter++;
|
||||
return cachedFloorHeight;
|
||||
}
|
||||
|
|
@ -194,7 +196,7 @@ void CameraController::update(float deltaTime) {
|
|||
}
|
||||
|
||||
// Smooth camera position
|
||||
if (glm::length(smoothedCamPos) < 0.01f) {
|
||||
if (glm::dot(smoothedCamPos, smoothedCamPos) < 1e-4f) {
|
||||
smoothedCamPos = actualCam;
|
||||
}
|
||||
float camLerp = 1.0f - std::exp(-CAM_SMOOTH_SPEED * deltaTime);
|
||||
|
|
@ -516,9 +518,9 @@ void CameraController::update(float deltaTime) {
|
|||
};
|
||||
|
||||
glm::vec2 fwd2(forward.x, forward.y);
|
||||
float fwdLen = glm::length(fwd2);
|
||||
if (fwdLen > 1e-4f) {
|
||||
fwd2 /= fwdLen;
|
||||
float fwdLenSq = glm::dot(fwd2, fwd2);
|
||||
if (fwdLenSq > 1e-8f) {
|
||||
fwd2 *= glm::inversesqrt(fwdLenSq);
|
||||
std::optional<float> aheadFloor;
|
||||
const float probeZ = targetPos.z + 2.0f;
|
||||
const float dists[] = {0.45f, 0.90f, 1.25f};
|
||||
|
|
@ -566,7 +568,7 @@ void CameraController::update(float deltaTime) {
|
|||
} else {
|
||||
// Manual control: use camera's 3D direction (swim where you look)
|
||||
swimForward = glm::normalize(forward3D);
|
||||
if (glm::length(swimForward) < 1e-4f) {
|
||||
if (glm::dot(swimForward, swimForward) < 1e-8f) {
|
||||
swimForward = forward;
|
||||
}
|
||||
}
|
||||
|
|
@ -583,8 +585,9 @@ void CameraController::update(float deltaTime) {
|
|||
if (nowStrafeLeft) swimMove += swimRight;
|
||||
if (nowStrafeRight) swimMove -= swimRight;
|
||||
|
||||
if (glm::length(swimMove) > 0.001f) {
|
||||
swimMove = glm::normalize(swimMove);
|
||||
float swimMoveLenSq = glm::dot(swimMove, swimMove);
|
||||
if (swimMoveLenSq > 1e-6f) {
|
||||
swimMove *= glm::inversesqrt(swimMoveLenSq);
|
||||
// Use backward swim speed when moving backwards only (not when combining with strafe)
|
||||
float applySpeed = (nowBackward && !nowForward) ? swimBackSpeed : swimSpeed;
|
||||
targetPos += swimMove * applySpeed * physicsDeltaTime;
|
||||
|
|
@ -623,10 +626,12 @@ void CameraController::update(float deltaTime) {
|
|||
// Prevent sinking/clipping through world floor while swimming.
|
||||
// Cache floor queries (update every 3 frames or 1 unit movement)
|
||||
std::optional<float> floorH;
|
||||
float dist2D = glm::length(glm::vec2(targetPos.x - lastFloorQueryPos.x,
|
||||
targetPos.y - lastFloorQueryPos.y));
|
||||
float dx2D = targetPos.x - lastFloorQueryPos.x;
|
||||
float dy2D = targetPos.y - lastFloorQueryPos.y;
|
||||
float dist2DSq = dx2D * dx2D + dy2D * dy2D;
|
||||
constexpr float kFloorDistSq = FLOOR_QUERY_DISTANCE_THRESHOLD * FLOOR_QUERY_DISTANCE_THRESHOLD;
|
||||
bool updateFloorCache = (floorQueryFrameCounter++ >= FLOOR_QUERY_FRAME_INTERVAL) ||
|
||||
(dist2D > FLOOR_QUERY_DISTANCE_THRESHOLD);
|
||||
(dist2DSq > kFloorDistSq);
|
||||
|
||||
if (updateFloorCache) {
|
||||
floorQueryFrameCounter = 0;
|
||||
|
|
@ -685,10 +690,12 @@ void CameraController::update(float deltaTime) {
|
|||
{
|
||||
glm::vec3 swimFrom = *followTarget;
|
||||
glm::vec3 swimTo = targetPos;
|
||||
float swimMoveDist = glm::length(swimTo - swimFrom);
|
||||
glm::vec3 swimDelta = swimTo - swimFrom;
|
||||
float swimMoveDistSq = glm::dot(swimDelta, swimDelta);
|
||||
glm::vec3 stepPos = swimFrom;
|
||||
|
||||
if (swimMoveDist > 0.01f) {
|
||||
if (swimMoveDistSq > 1e-4f) {
|
||||
float swimMoveDist = std::sqrt(swimMoveDistSq);
|
||||
float swimStepSize = cachedInsideWMO ? 0.20f : 0.35f;
|
||||
int swimSteps = std::max(1, std::min(8, static_cast<int>(std::ceil(swimMoveDist / swimStepSize))));
|
||||
glm::vec3 stepDelta = (swimTo - swimFrom) / static_cast<float>(swimSteps);
|
||||
|
|
@ -746,7 +753,7 @@ void CameraController::update(float deltaTime) {
|
|||
|
||||
// Forward/back follows camera 3D direction (same as swim)
|
||||
glm::vec3 flyFwd = glm::normalize(forward3D);
|
||||
if (glm::length(flyFwd) < 1e-4f) flyFwd = forward;
|
||||
if (glm::dot(flyFwd, flyFwd) < 1e-8f) flyFwd = forward;
|
||||
glm::vec3 flyMove(0.0f);
|
||||
if (nowForward) flyMove += flyFwd;
|
||||
if (nowBackward) flyMove -= flyFwd;
|
||||
|
|
@ -756,8 +763,9 @@ void CameraController::update(float deltaTime) {
|
|||
bool flyDescend = !uiWantsKeyboard && xDown && mounted_;
|
||||
if (nowJump) flyMove.z += 1.0f;
|
||||
if (flyDescend) flyMove.z -= 1.0f;
|
||||
if (glm::length(flyMove) > 0.001f) {
|
||||
flyMove = glm::normalize(flyMove);
|
||||
float flyMoveLenSq = glm::dot(flyMove, flyMove);
|
||||
if (flyMoveLenSq > 1e-6f) {
|
||||
flyMove *= glm::inversesqrt(flyMoveLenSq);
|
||||
float flyFwdSpeed = (flightSpeedOverride_ > 0.0f && flightSpeedOverride_ < 200.0f
|
||||
&& !std::isnan(flightSpeedOverride_))
|
||||
? flightSpeedOverride_ : speed;
|
||||
|
|
@ -771,8 +779,9 @@ void CameraController::update(float deltaTime) {
|
|||
// Skip all ground physics — go straight to collision/WMO sections
|
||||
} else {
|
||||
|
||||
if (glm::length(movement) > 0.001f) {
|
||||
movement = glm::normalize(movement);
|
||||
float moveLenSq = glm::dot(movement, movement);
|
||||
if (moveLenSq > 1e-6f) {
|
||||
movement *= glm::inversesqrt(moveLenSq);
|
||||
targetPos += movement * speed * physicsDeltaTime;
|
||||
}
|
||||
|
||||
|
|
@ -784,7 +793,7 @@ void CameraController::update(float deltaTime) {
|
|||
float drag = std::exp(-KNOCKBACK_HORIZ_DRAG * physicsDeltaTime);
|
||||
knockbackHorizVel_ *= drag;
|
||||
// Once negligible, clear the flag so collision/grounding work normally.
|
||||
if (glm::length(knockbackHorizVel_) < 0.05f) {
|
||||
if (glm::dot(knockbackHorizVel_, knockbackHorizVel_) < 0.0025f) {
|
||||
knockbackActive_ = false;
|
||||
knockbackHorizVel_ = glm::vec2(0.0f);
|
||||
}
|
||||
|
|
@ -829,8 +838,9 @@ void CameraController::update(float deltaTime) {
|
|||
// Refresh inside-WMO state before collision/grounding so we don't use stale
|
||||
// terrain-first caches while entering enclosed tunnel/building spaces.
|
||||
if (wmoRenderer && !externalFollow_) {
|
||||
const float insideDist = glm::length(targetPos - lastInsideStateCheckPos_);
|
||||
if (++insideStateCheckCounter_ >= 2 || insideDist > 0.35f) {
|
||||
glm::vec3 insideDelta = targetPos - lastInsideStateCheckPos_;
|
||||
float insideDistSq = glm::dot(insideDelta, insideDelta);
|
||||
if (++insideStateCheckCounter_ >= 2 || insideDistSq > 0.1225f) {
|
||||
insideStateCheckCounter_ = 0;
|
||||
lastInsideStateCheckPos_ = targetPos;
|
||||
|
||||
|
|
@ -853,9 +863,11 @@ void CameraController::update(float deltaTime) {
|
|||
{
|
||||
glm::vec3 startPos = *followTarget;
|
||||
glm::vec3 desiredPos = targetPos;
|
||||
float moveDist = glm::length(desiredPos - startPos);
|
||||
glm::vec3 moveDelta = desiredPos - startPos;
|
||||
float moveDistSq = glm::dot(moveDelta, moveDelta);
|
||||
|
||||
if (moveDist > 0.01f) {
|
||||
if (moveDistSq > 1e-4f) {
|
||||
float moveDist = std::sqrt(moveDistSq);
|
||||
// Smaller step size when inside buildings for tighter collision
|
||||
float stepSize = cachedInsideWMO ? 0.20f : 0.35f;
|
||||
int sweepSteps = std::max(1, std::min(8, static_cast<int>(std::ceil(moveDist / stepSize))));
|
||||
|
|
@ -909,9 +921,11 @@ void CameraController::update(float deltaTime) {
|
|||
std::optional<float> centerM2H;
|
||||
{
|
||||
// Collision cache: skip expensive checks if barely moved (15cm threshold)
|
||||
float distMoved = glm::length(glm::vec2(targetPos.x, targetPos.y) -
|
||||
glm::vec2(lastCollisionCheckPos_.x, lastCollisionCheckPos_.y));
|
||||
bool useCached = grounded && hasCachedFloor_ && distMoved < COLLISION_CACHE_DISTANCE;
|
||||
float dmx = targetPos.x - lastCollisionCheckPos_.x;
|
||||
float dmy = targetPos.y - lastCollisionCheckPos_.y;
|
||||
float distMovedSq = dmx * dmx + dmy * dmy;
|
||||
constexpr float kCollisionCacheDistSq = COLLISION_CACHE_DISTANCE * COLLISION_CACHE_DISTANCE;
|
||||
bool useCached = grounded && hasCachedFloor_ && distMovedSq < kCollisionCacheDistSq;
|
||||
if (useCached) {
|
||||
// Never trust cached ground while actively descending or when
|
||||
// vertical drift from cached floor is meaningful.
|
||||
|
|
@ -1371,11 +1385,13 @@ void CameraController::update(float deltaTime) {
|
|||
float mountedOffset = mounted_ ? mountHeightOffset_ : 0.0f;
|
||||
float pivotLift = 0.0f;
|
||||
if (terrainManager && !externalFollow_ && !cachedInsideInteriorWMO) {
|
||||
float moved = glm::length(glm::vec2(targetPos.x - lastPivotLiftQueryPos_.x,
|
||||
targetPos.y - lastPivotLiftQueryPos_.y));
|
||||
float plx = targetPos.x - lastPivotLiftQueryPos_.x;
|
||||
float ply = targetPos.y - lastPivotLiftQueryPos_.y;
|
||||
float movedSq = plx * plx + ply * ply;
|
||||
constexpr float kPivotLiftPosSq = PIVOT_LIFT_POS_THRESHOLD * PIVOT_LIFT_POS_THRESHOLD;
|
||||
float distDelta = std::abs(currentDistance - lastPivotLiftDistance_);
|
||||
bool queryLift = (++pivotLiftQueryCounter_ >= PIVOT_LIFT_QUERY_INTERVAL) ||
|
||||
(moved >= PIVOT_LIFT_POS_THRESHOLD) ||
|
||||
(movedSq >= kPivotLiftPosSq) ||
|
||||
(distDelta >= PIVOT_LIFT_DIST_THRESHOLD);
|
||||
if (queryLift) {
|
||||
pivotLiftQueryCounter_ = 0;
|
||||
|
|
@ -1421,8 +1437,9 @@ void CameraController::update(float deltaTime) {
|
|||
// Limit max zoom when inside a WMO with a ceiling (building interior)
|
||||
// Throttle: only recheck every 10 frames or when position changes >2 units.
|
||||
if (wmoRenderer) {
|
||||
float distFromLastCheck = glm::length(targetPos - lastInsideWMOCheckPos);
|
||||
if (++insideWMOCheckCounter >= 10 || distFromLastCheck > 2.0f) {
|
||||
glm::vec3 wmoCheckDelta = targetPos - lastInsideWMOCheckPos;
|
||||
float distFromLastCheckSq = glm::dot(wmoCheckDelta, wmoCheckDelta);
|
||||
if (++insideWMOCheckCounter >= 10 || distFromLastCheckSq > 4.0f) {
|
||||
wmoRenderer->updateActiveGroup(targetPos.x, targetPos.y, targetPos.z + 1.0f);
|
||||
insideWMOCheckCounter = 0;
|
||||
lastInsideWMOCheckPos = targetPos;
|
||||
|
|
@ -1486,7 +1503,7 @@ void CameraController::update(float deltaTime) {
|
|||
}
|
||||
|
||||
// Smooth camera position to avoid jitter
|
||||
if (glm::length(smoothedCamPos) < 0.01f) {
|
||||
if (glm::dot(smoothedCamPos, smoothedCamPos) < 1e-4f) {
|
||||
smoothedCamPos = actualCam; // Initialize
|
||||
}
|
||||
float camLerp = 1.0f - std::exp(-CAM_SMOOTH_SPEED * deltaTime);
|
||||
|
|
@ -1503,9 +1520,10 @@ void CameraController::update(float deltaTime) {
|
|||
std::optional<float> camWmoH;
|
||||
if (wmoRenderer) {
|
||||
// Skip expensive WMO floor query if camera barely moved
|
||||
float camDelta = glm::length(glm::vec2(smoothedCamPos.x - lastCamFloorQueryPos.x,
|
||||
smoothedCamPos.y - lastCamFloorQueryPos.y));
|
||||
if (camDelta < 0.3f && hasCachedCamFloor) {
|
||||
float cdx = smoothedCamPos.x - lastCamFloorQueryPos.x;
|
||||
float cdy = smoothedCamPos.y - lastCamFloorQueryPos.y;
|
||||
float camDeltaSq = cdx * cdx + cdy * cdy;
|
||||
if (camDeltaSq < 0.09f && hasCachedCamFloor) {
|
||||
camWmoH = cachedCamWmoFloor;
|
||||
} else {
|
||||
float camFloorProbeZ = smoothedCamPos.z;
|
||||
|
|
@ -1618,8 +1636,9 @@ void CameraController::update(float deltaTime) {
|
|||
float waterSurfaceCamZ = waterH ? (*waterH - WATER_SURFACE_OFFSET + eyeHeight) : newPos.z;
|
||||
bool diveIntent = nowForward && (forward3D.z < -0.28f);
|
||||
|
||||
if (glm::length(movement) > 0.001f) {
|
||||
movement = glm::normalize(movement);
|
||||
float movLenSq = glm::dot(movement, movement);
|
||||
if (movLenSq > 1e-6f) {
|
||||
movement *= glm::inversesqrt(movLenSq);
|
||||
newPos += movement * swimSpeed * physicsDeltaTime;
|
||||
}
|
||||
|
||||
|
|
@ -1652,8 +1671,9 @@ void CameraController::update(float deltaTime) {
|
|||
} else {
|
||||
swimming = false;
|
||||
|
||||
if (glm::length(movement) > 0.001f) {
|
||||
movement = glm::normalize(movement);
|
||||
float movLenSq2 = glm::dot(movement, movement);
|
||||
if (movLenSq2 > 1e-6f) {
|
||||
movement *= glm::inversesqrt(movLenSq2);
|
||||
newPos += movement * speed * physicsDeltaTime;
|
||||
}
|
||||
|
||||
|
|
@ -1680,9 +1700,11 @@ void CameraController::update(float deltaTime) {
|
|||
if (wmoRenderer) {
|
||||
glm::vec3 startFeet = camera->getPosition() - glm::vec3(0, 0, eyeHeight);
|
||||
glm::vec3 desiredFeet = newPos - glm::vec3(0, 0, eyeHeight);
|
||||
float moveDist = glm::length(desiredFeet - startFeet);
|
||||
glm::vec3 feetDelta = desiredFeet - startFeet;
|
||||
float moveDistSq2 = glm::dot(feetDelta, feetDelta);
|
||||
|
||||
if (moveDist > 0.01f) {
|
||||
if (moveDistSq2 > 1e-4f) {
|
||||
float moveDist = std::sqrt(moveDistSq2);
|
||||
float stepSize = cachedInsideWMO ? 0.20f : 0.35f;
|
||||
int sweepSteps = std::max(1, std::min(8, static_cast<int>(std::ceil(moveDist / stepSize))));
|
||||
glm::vec3 stepPos = startFeet;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue