Add loading screen with random WOWEE splash images

- Add loading screen system with stb_image for JPEG loading
- Two loading screen images (orc and dwarf) randomly selected
- Display loading screen while terrain data loads
- Cache WMO inverse matrices to reduce per-frame computation
- Stub WMO liquid rendering (needs coordinate system fix)
- Update spawn point to Stormwind Trade District
This commit is contained in:
Kelsi 2026-02-03 13:33:31 -08:00
parent 665a73e75f
commit 01bf3b4c08
14 changed files with 8395 additions and 165 deletions

View file

@ -620,6 +620,9 @@ void WMORenderer::WMOInstance::updateModelMatrix() {
modelMatrix = glm::rotate(modelMatrix, rotation.x, glm::vec3(1.0f, 0.0f, 0.0f));
modelMatrix = glm::scale(modelMatrix, glm::vec3(scale));
// Cache inverse for collision detection
invModelMatrix = glm::inverse(modelMatrix);
}
GLuint WMORenderer::loadTexture(const std::string& path) {
@ -728,10 +731,9 @@ std::optional<float> WMORenderer::getFloorHeight(float glX, float glY, float glZ
const ModelData& model = it->second;
// Transform ray into model-local space
glm::mat4 invModel = glm::inverse(instance.modelMatrix);
glm::vec3 localOrigin = glm::vec3(invModel * glm::vec4(worldOrigin, 1.0f));
glm::vec3 localDir = glm::normalize(glm::vec3(invModel * glm::vec4(worldDir, 0.0f)));
// Use cached inverse matrix
glm::vec3 localOrigin = glm::vec3(instance.invModelMatrix * glm::vec4(worldOrigin, 1.0f));
glm::vec3 localDir = glm::normalize(glm::vec3(instance.invModelMatrix * glm::vec4(worldDir, 0.0f)));
for (const auto& group : model.groups) {
// Quick bounding box check: does the ray intersect this group's AABB?
@ -785,10 +787,9 @@ bool WMORenderer::checkWallCollision(const glm::vec3& from, const glm::vec3& to,
if (it == loadedModels.end()) continue;
const ModelData& model = it->second;
glm::mat4 invModel = glm::inverse(instance.modelMatrix);
// Transform positions into local space
glm::vec3 localTo = glm::vec3(invModel * glm::vec4(to, 1.0f));
// Transform positions into local space using cached inverse
glm::vec3 localTo = glm::vec3(instance.invModelMatrix * glm::vec4(to, 1.0f));
for (const auto& group : model.groups) {
// Quick bounding box check
@ -865,8 +866,7 @@ bool WMORenderer::isInsideWMO(float glX, float glY, float glZ, uint32_t* outMode
if (it == loadedModels.end()) continue;
const ModelData& model = it->second;
glm::mat4 invModel = glm::inverse(instance.modelMatrix);
glm::vec3 localPos = glm::vec3(invModel * glm::vec4(glX, glY, glZ, 1.0f));
glm::vec3 localPos = glm::vec3(instance.invModelMatrix * glm::vec4(glX, glY, glZ, 1.0f));
// Check if inside any group's bounding box
for (const auto& group : model.groups) {
@ -890,10 +890,9 @@ float WMORenderer::raycastBoundingBoxes(const glm::vec3& origin, const glm::vec3
const ModelData& model = it->second;
// Transform ray into local space
glm::mat4 invModel = glm::inverse(instance.modelMatrix);
glm::vec3 localOrigin = glm::vec3(invModel * glm::vec4(origin, 1.0f));
glm::vec3 localDir = glm::normalize(glm::vec3(invModel * glm::vec4(direction, 0.0f)));
// Use cached inverse matrix
glm::vec3 localOrigin = glm::vec3(instance.invModelMatrix * glm::vec4(origin, 1.0f));
glm::vec3 localDir = glm::normalize(glm::vec3(instance.invModelMatrix * glm::vec4(direction, 0.0f)));
for (const auto& group : model.groups) {
// Ray-AABB intersection (slab method)