mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-25 16:30:15 +00:00
Add transport system, fix NPC spawning, and improve water rendering
Transport System (Phases 1-7): - Implement TransportManager with Catmull-Rom spline path interpolation - Add WMO dynamic transforms for moving transport instances - Implement player attachment via world position composition - Add test transport with circular path around Stormwind harbor - Add /transport board and /transport leave console commands - Reuse taxi flight spline system and external follow camera mode NPC Spawn Fixes: - Add smart ocean spawn filter: blocks land creatures at high altitude over water (Z>50) - Allow legitimate water creatures at sea level (Z≤50) to spawn correctly - Fixes Elder Grey Bears, Highland Striders, and Plainscreepers spawning over ocean - Snap online creatures to terrain height when valid ground exists NpcManager Removal: - Remove deprecated NpcManager (offline mode no longer supported) - Delete npc_manager.hpp and npc_manager.cpp - Simplify NPC animation callbacks to use only creatureInstances_ map - Move NPC callbacks to game initialization in application.cpp Water Rendering: - Fix tile seam gaps caused by per-vertex wave randomization - Add distance-based blending: seamless waves up close (<150u), grid effect far away (>400u) - Smooth transition between seamless and grid modes (150-400 unit range) - Preserves aesthetic grid pattern at horizon while eliminating gaps when swimming
This commit is contained in:
parent
c91e0bb916
commit
2e923311d0
13 changed files with 711 additions and 1079 deletions
|
|
@ -39,6 +39,7 @@ bool WaterRenderer::initialize() {
|
|||
uniform float waveAmp;
|
||||
uniform float waveFreq;
|
||||
uniform float waveSpeed;
|
||||
uniform vec3 viewPos;
|
||||
|
||||
out vec3 FragPos;
|
||||
out vec3 Normal;
|
||||
|
|
@ -48,19 +49,30 @@ bool WaterRenderer::initialize() {
|
|||
void main() {
|
||||
vec3 pos = aPos;
|
||||
|
||||
// Pseudo-random phase offsets to break up regular pattern
|
||||
// Distance from camera for LOD blending
|
||||
float dist = length(viewPos - aPos);
|
||||
float gridBlend = smoothstep(150.0, 400.0, dist); // 0=close (seamless), 1=far (grid effect)
|
||||
|
||||
// Seamless waves (continuous across tiles)
|
||||
float w1_seamless = sin((aPos.x + time * waveSpeed) * waveFreq) * waveAmp;
|
||||
float w2_seamless = cos((aPos.y - time * (waveSpeed * 0.78)) * (waveFreq * 0.82)) * (waveAmp * 0.72);
|
||||
float w3_seamless = sin((aPos.x * 1.7 - time * waveSpeed * 1.3 + aPos.y * 0.3) * waveFreq * 2.1) * (waveAmp * 0.35);
|
||||
float w4_seamless = cos((aPos.y * 1.4 + time * waveSpeed * 0.9 + aPos.x * 0.2) * waveFreq * 1.8) * (waveAmp * 0.28);
|
||||
|
||||
// Grid effect waves (per-vertex randomization for distance view)
|
||||
float hash1 = fract(sin(dot(aPos.xy, vec2(12.9898, 78.233))) * 43758.5453);
|
||||
float hash2 = fract(sin(dot(aPos.xy, vec2(93.9898, 67.345))) * 27153.5328);
|
||||
float w1_grid = sin((aPos.x + time * waveSpeed + hash1 * 6.28) * waveFreq) * waveAmp;
|
||||
float w2_grid = cos((aPos.y - time * (waveSpeed * 0.78) + hash2 * 6.28) * (waveFreq * 0.82)) * (waveAmp * 0.72);
|
||||
float w3_grid = sin((aPos.x * 1.7 - time * waveSpeed * 1.3 + hash1 * 3.14) * waveFreq * 2.1) * (waveAmp * 0.35);
|
||||
float w4_grid = cos((aPos.y * 1.4 + time * waveSpeed * 0.9 + hash2 * 3.14) * waveFreq * 1.8) * (waveAmp * 0.28);
|
||||
|
||||
// Multiple wave octaves with randomized phases for natural variation
|
||||
float w1 = sin((aPos.x + time * waveSpeed + hash1 * 6.28) * waveFreq) * waveAmp;
|
||||
float w2 = cos((aPos.y - time * (waveSpeed * 0.78) + hash2 * 6.28) * (waveFreq * 0.82)) * (waveAmp * 0.72);
|
||||
|
||||
// Add higher frequency detail waves (smaller amplitude)
|
||||
float w3 = sin((aPos.x * 1.7 - time * waveSpeed * 1.3 + hash1 * 3.14) * waveFreq * 2.1) * (waveAmp * 0.35);
|
||||
float w4 = cos((aPos.y * 1.4 + time * waveSpeed * 0.9 + hash2 * 3.14) * waveFreq * 1.8) * (waveAmp * 0.28);
|
||||
|
||||
float wave = w1 + w2 + w3 + w4;
|
||||
// Blend between seamless (close) and grid (far)
|
||||
float wave = mix(
|
||||
w1_seamless + w2_seamless + w3_seamless + w4_seamless,
|
||||
w1_grid + w2_grid + w3_grid + w4_grid,
|
||||
gridBlend
|
||||
);
|
||||
pos.z += wave;
|
||||
|
||||
FragPos = vec3(model * vec4(pos, 1.0));
|
||||
|
|
|
|||
|
|
@ -554,6 +554,49 @@ void WMORenderer::setInstancePosition(uint32_t instanceId, const glm::vec3& posi
|
|||
rebuildSpatialIndex();
|
||||
}
|
||||
|
||||
void WMORenderer::setInstanceTransform(uint32_t instanceId, const glm::mat4& transform) {
|
||||
auto idxIt = instanceIndexById.find(instanceId);
|
||||
if (idxIt == instanceIndexById.end()) return;
|
||||
auto& inst = instances[idxIt->second];
|
||||
|
||||
// Decompose transform to position/rotation/scale
|
||||
inst.position = glm::vec3(transform[3]);
|
||||
|
||||
// Extract rotation (assuming uniform scale)
|
||||
glm::mat3 rotationMatrix(transform);
|
||||
float scaleX = glm::length(glm::vec3(transform[0]));
|
||||
float scaleY = glm::length(glm::vec3(transform[1]));
|
||||
float scaleZ = glm::length(glm::vec3(transform[2]));
|
||||
inst.scale = scaleX; // Assume uniform scale
|
||||
|
||||
if (scaleX > 0.0001f) rotationMatrix[0] /= scaleX;
|
||||
if (scaleY > 0.0001f) rotationMatrix[1] /= scaleY;
|
||||
if (scaleZ > 0.0001f) rotationMatrix[2] /= scaleZ;
|
||||
|
||||
inst.rotation = glm::vec3(0.0f); // Euler angles not directly used, so zero them
|
||||
|
||||
// Update model matrix and bounds
|
||||
inst.modelMatrix = transform;
|
||||
inst.invModelMatrix = glm::inverse(transform);
|
||||
|
||||
auto modelIt = loadedModels.find(inst.modelId);
|
||||
if (modelIt != loadedModels.end()) {
|
||||
const ModelData& model = modelIt->second;
|
||||
transformAABB(inst.modelMatrix, model.boundingBoxMin, model.boundingBoxMax,
|
||||
inst.worldBoundsMin, inst.worldBoundsMax);
|
||||
inst.worldGroupBounds.clear();
|
||||
inst.worldGroupBounds.reserve(model.groups.size());
|
||||
for (const auto& group : model.groups) {
|
||||
glm::vec3 gMin, gMax;
|
||||
transformAABB(inst.modelMatrix, group.boundingBoxMin, group.boundingBoxMax, gMin, gMax);
|
||||
gMin -= glm::vec3(0.5f);
|
||||
gMax += glm::vec3(0.5f);
|
||||
inst.worldGroupBounds.emplace_back(gMin, gMax);
|
||||
}
|
||||
}
|
||||
rebuildSpatialIndex();
|
||||
}
|
||||
|
||||
void WMORenderer::removeInstance(uint32_t instanceId) {
|
||||
auto it = std::find_if(instances.begin(), instances.end(),
|
||||
[instanceId](const WMOInstance& inst) { return inst.id == instanceId; });
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue