diff --git a/src/controller.h b/src/controller.h index 5bc0915..13168f3 100644 --- a/src/controller.h +++ b/src/controller.h @@ -1268,39 +1268,47 @@ struct Controller { } void updateLights(bool lerp = true) { - TR::Room::Light sunLight; - const TR::Room &room = getLightRoom(); - if (getModel()) { - vec3 center = getBoundingBox().center(); - float maxAtt = 0.0f; - /* - if (room.flags.sky) { // TODO trace rooms up for sun light, add direct light projection - sunLight.x = int32(center.x); - sunLight.y = int32(center.y) - 8192; - sunLight.z = int32(center.z); - sunLight.color = Color32(255, 255, 255, 255); - sunLight.radius = 1000 * 1024; - targetLight = &sunLight; - } else { - */ - { + targetLight = NULL; + int ambient = room.ambient; + + if (getEntity().intensity == -1) { + + if (room.lightsCount && getModel()) { + ambient = 0x1FFF - ambient; + int maxValue = 0; + + vec3 center = getBoundingBox().center(); + + int x = int(center.x); + int y = int(center.y); + int z = int(center.z); + for (int i = 0; i < room.lightsCount; i++) { TR::Room::Light &light = room.lights[i]; - if ((light.color.r | light.color.g | light.color.b) == 0) continue; - vec3 dir = vec3(float(light.x), float(light.y), float(light.z)) - center; - float att = max(0.0f, 1.0f - dir.length2() / SQR(light.radius)) * ((light.color.r + light.color.g + light.color.b) / (3.0f * 255.0f)); + int dx = x - light.x; + int dy = y - light.y; + int dz = z - light.z; - if (att > maxAtt) { - maxAtt = att; - targetLight = &light; + int D = (SQR(dx) + SQR(dy) + SQR(dz)) >> 12; + int R = SQR(light.radius >> 1) >> 12; + + int value = (light.intensity * R) / (D + R) + ambient; + + if (maxValue < value) { + targetLight = &room.lights[i]; + maxValue = value; } } + + ambient = (maxValue + ambient) / 2; + ambient = 0x1FFF - ambient; } - } else - targetLight = NULL; + + intensity = intensityf(ambient); + } if (targetLight == NULL) { mainLightPos = vec3(0); diff --git a/src/format.h b/src/format.h index 681a841..80413a5 100644 --- a/src/format.h +++ b/src/format.h @@ -1347,6 +1347,7 @@ namespace TR { struct Light { int32 x, y, z; uint32 radius; + int32 intensity; Color32 color; } *lights; @@ -3255,6 +3256,7 @@ namespace TR { int value = clamp((intensity > 0x1FFF) ? 0 : (intensity >> 5), 0, 255); light.color.r = light.color.g = light.color.b = value; light.color.a = 0; + light.intensity = intensity; light.radius = stream.readBE32() * 2; } @@ -4382,6 +4384,8 @@ namespace TR { light.color.a = 0; } + light.intensity = intensity; + if (version == VER_TR3_PSX) light.radius >>= 2; diff --git a/src/level.h b/src/level.h index 01cb04b..bd9de0c 100644 --- a/src/level.h +++ b/src/level.h @@ -1664,14 +1664,14 @@ struct Level : IGame { type = Shader::MIRROR; if (isModel) { // model - float intensity = controller->intensity < 0.0f ? intensityf(room.ambient) : controller->intensity; + ASSERT(controller->intensity >= 0.0f); setMainLight(controller); - setRoomParams(roomIndex, type, 1.0f, intensity, controller->specular, 1.0f, mesh->transparent == 1); + setRoomParams(roomIndex, type, 1.0f, controller->intensity, controller->specular, 1.0f, mesh->transparent == 1); vec3 pos = controller->getPos(); if (ambientCache) { - if (!controller->getEntity().isDoor() && !controller->getEntity().isBlock()) { // no advanced ambient lighting for secret (all) doors and blocks + if (!entity.isDoor() && !entity.isBlock()) { // no advanced ambient lighting for secret (all) doors and blocks AmbientCache::Cube cube; ambientCache->getAmbient(roomIndex, pos, cube); if (cube.status == AmbientCache::Cube::READY)