From d0ae3ecdb5b6b3cea766d8aca21f511dafd68366 Mon Sep 17 00:00:00 2001 From: LJW-Dev <48092720+LJW-Dev@users.noreply.github.com> Date: Wed, 22 Apr 2026 19:22:45 +0800 Subject: [PATCH] feat: Loading sun data through GLTF --- src/ObjLoading/Game/T6/BSP/BSP.h | 7 +- src/ObjLoading/Game/T6/BSP/BSPCreator.cpp | 171 +++++++------- .../Game/T6/BSP/Linker/ComWorldLinker.cpp | 208 +++++++----------- .../Game/T6/BSP/Linker/GfxWorldLinker.cpp | 69 +++--- .../Game/T6/BSP/Linker/GfxWorldLinker.h | 2 +- 5 files changed, 198 insertions(+), 259 deletions(-) diff --git a/src/ObjLoading/Game/T6/BSP/BSP.h b/src/ObjLoading/Game/T6/BSP/BSP.h index e85f50c7..18c49e63 100644 --- a/src/ObjLoading/Game/T6/BSP/BSP.h +++ b/src/ObjLoading/Game/T6/BSP/BSP.h @@ -88,7 +88,6 @@ namespace BSP enum BSPLightType { LIGHT_TYPE_DIRECTIONAL, - LIGHT_TYPE_POINT, LIGHT_TYPE_SPOT }; @@ -101,9 +100,8 @@ namespace BSP vec3_t pos; vec3_t direction; - bool hasPosBeenSet; - // angle is in radians. only used on spot/dir lights + // angle is in radians. only used on spot lights float innerConeAngle; float outerConeAngle; }; @@ -172,6 +170,9 @@ namespace BSP std::vector zm_spawners; std::vector entities; + bool hasSunlightBeenSet; + BSPLight sunlight; + std::vector models; }; diff --git a/src/ObjLoading/Game/T6/BSP/BSPCreator.cpp b/src/ObjLoading/Game/T6/BSP/BSPCreator.cpp index f75f759e..fc502398 100644 --- a/src/ObjLoading/Game/T6/BSP/BSPCreator.cpp +++ b/src/ObjLoading/Game/T6/BSP/BSPCreator.cpp @@ -359,32 +359,85 @@ namespace return vertexOffset; } - bool addLightNode(const gltf::JsonNode& node, Eigen::Matrix4f& nodeMatrix) + bool addLightNode(const JsonRoot& jRoot, const gltf::JsonNode& node, Eigen::Matrix4f& nodeMatrix) { - assert(m_is_world_gfx); + if (!m_is_world_gfx || !jRoot.extensions || !jRoot.extensions->KHR_lights_punctual || !jRoot.extensions->KHR_lights_punctual->lights) + return false; assert(node.extensions); assert(node.extensions->KHR_lights_punctual); int lightIndex = node.extensions->KHR_lights_punctual->light; + const JsonPunctualLight& jsLight = jRoot.extensions->KHR_lights_punctual->lights->at(lightIndex); + BSPLight light{}; - assert(lightIndex >= 0); - if (m_bsp->lights[lightIndex].hasPosBeenSet == true) - con::warn("Internal error, multiple nodes reference the same light. Light positions/rotations are likely incorrect."); + light.outerConeAngle = std::numbers::pi_v / 4.0f; /// spec of 45 degrees + light.innerConeAngle = 0.0f; + if (jsLight.type == JsonPunctualLightType::DIRECTIONAL) + { + if (m_bsp->hasSunlightBeenSet) + con::warn("WARNING: multiple sunlight nodes found, only one will be used as the sun."); + light.type = LIGHT_TYPE_DIRECTIONAL; + m_bsp->hasSunlightBeenSet = true; + } + else if (jsLight.type == JsonPunctualLightType::POINT) + { + con::warn("Ignoring point light as BO2 does not support point lights."); + return false; + } + else // JsonPunctualLightType::SPOT + { + light.type = LIGHT_TYPE_SPOT; + + assert(jsLight.spot); + if (jsLight.spot->innerConeAngle) + light.innerConeAngle = *jsLight.spot->innerConeAngle; + + if (jsLight.spot->outerConeAngle) + light.outerConeAngle = *jsLight.spot->outerConeAngle; + } + + if (!jsLight.color) + { + light.colour.x = 1.0f; + light.colour.y = 1.0f; + light.colour.z = 1.0f; + } + else + { + light.colour.x = (*jsLight.color)[0]; + light.colour.y = (*jsLight.color)[1]; + light.colour.z = (*jsLight.color)[2]; + } + + if (!jsLight.intensity) + light.intensity = 1000.0f; // adjusted from spec to better match BO2 + else + light.intensity = *jsLight.intensity; + + if (!jsLight.range) + light.range = 1000.0f; // adjusted from spec to better match BO2 + else + light.range = *jsLight.range; Eigen::Vector4f position(0, 0, 0, 1.0f); Eigen::Vector4f transformedPosition = nodeMatrix * position; - m_bsp->lights[lightIndex].pos = vec3_t{transformedPosition.x(), transformedPosition.y(), transformedPosition.z()}; - RhcToLhcCoordinates(m_bsp->lights[lightIndex].pos.v); + light.pos = vec3_t{transformedPosition.x(), transformedPosition.y(), transformedPosition.z()}; + RhcToLhcCoordinates(light.pos.v); - // GLTF spec uses +Y up and the default light direction is straight down - Eigen::Vector3f defaultDirection(0.0f, -1.0f, 0.0f); + Eigen::Vector3f defaultDirection(0.0f, 0.0f, 1.0f); // lights use this value for the forward angle instead in BO2 Eigen::Affine3f affineTransform(nodeMatrix); Eigen::Matrix3f rotationMatrix = affineTransform.rotation(); Eigen::Vector3f outputDirection = rotationMatrix * defaultDirection; outputDirection.normalize(); - m_bsp->lights[lightIndex].direction = vec3_t{outputDirection.x(), outputDirection.y(), outputDirection.z()}; + light.direction.x = outputDirection.x(); + light.direction.y = outputDirection.y(); + light.direction.z = outputDirection.z(); + RhcToLhcCoordinates(light.direction.v); - m_bsp->lights[lightIndex].hasPosBeenSet = true; + if (jsLight.type == JsonPunctualLightType::DIRECTIONAL) + m_bsp->sunlight = light; + else + m_bsp->lights.emplace_back(light); return true; } @@ -588,7 +641,6 @@ namespace xmodel.rotationQuaternion.w = rotationQuat.w(); RhcToLhcQuaternion(xmodel.rotationQuaternion.v); - con::warn("XModels don't support scale currently, keep it at 1 in your editor"); xmodel.scale = 1.0f; calculateXmodelBounds(xmodel, node.mesh, nodeMatrix, jRoot); @@ -904,7 +956,7 @@ namespace bool addNodeToBSP(const JsonRoot& jRoot, const gltf::JsonNode& node, Eigen::Matrix4f& nodeMatrix) { if (m_is_world_gfx && node.extensions && node.extensions->KHR_lights_punctual) - return addLightNode(node, nodeMatrix); + return addLightNode(jRoot, node, nodeMatrix); if (node.extras) { @@ -1040,80 +1092,6 @@ namespace m_curr_bsp_world->materials.emplace_back(emptyMaterial); } - void LoadLights(const JsonRoot& jRoot) - { - if (!m_is_world_gfx) - return; - if (!jRoot.extensions) - return; - if (!jRoot.extensions->KHR_lights_punctual) - return; - if (!jRoot.extensions->KHR_lights_punctual->lights) - return; - - const std::vector& jsLightArray = jRoot.extensions->KHR_lights_punctual->lights.value(); - m_bsp->lights.reserve(jsLightArray.size()); - for (const JsonPunctualLight& jsLight : jsLightArray) - { - if (jsLight.type == JsonPunctualLightType::POINT) - con::error("Any point lights will be converted to a spotlight as point lights are unsupported right now."); - - BSPLight light{}; - - // position and direction data will be set during node traversal - light.hasPosBeenSet = false; - - if (!jsLight.color) - { - light.colour.x = 1.0f; - light.colour.y = 1.0f; - light.colour.z = 1.0f; - } - else - { - light.colour.x = (*jsLight.color)[0]; - light.colour.y = (*jsLight.color)[1]; - light.colour.z = (*jsLight.color)[2]; - } - - if (!jsLight.intensity) - light.intensity = 100000.0f; // adjusted from spec to better match BO2 - else - light.intensity = *jsLight.intensity; - - if (!jsLight.range) - light.range = 1000.0f; // adjusted from spec to better match BO2 - else - light.range = *jsLight.range; - - if (jsLight.type == JsonPunctualLightType::DIRECTIONAL) - { - light.type = LIGHT_TYPE_DIRECTIONAL; - } - else if (jsLight.type == JsonPunctualLightType::POINT) - { - light.type = LIGHT_TYPE_POINT; - } - else // JsonPunctualLightType::SPOT - { - light.type = LIGHT_TYPE_SPOT; - - assert(jsLight.spot); - if (!jsLight.spot->innerConeAngle) - light.innerConeAngle = 0.0f; - else - light.innerConeAngle = *jsLight.spot->innerConeAngle; - - if (!jsLight.spot->outerConeAngle) - light.outerConeAngle = 3.14159265359f / 4.0f; /// spec of 45 degrees - else - light.outerConeAngle = *jsLight.spot->outerConeAngle; - } - - m_bsp->lights.emplace_back(light); - } - } - void TraverseNodes(const JsonRoot& jRoot) { // Make sure there are any nodes to traverse @@ -1266,9 +1244,6 @@ namespace CreateBufferViews(jRoot); CreateAccessors(jRoot); - if (isGfxWorld) // lights aren't needed in collision data - LoadLights(jRoot); - LoadMaterials(jRoot); TraverseNodes(jRoot); // requires materials and lights } @@ -1330,6 +1305,9 @@ namespace BSP bsp->name = mapName; bsp->bspName = "maps/mp/" + mapName + ".d3dbsp"; bsp->isZombiesMap = isZombiesMap; + bsp->hasSunlightBeenSet = false; + + con::warn("XModels don't support scale currently, keep it at 1 in your editor"); BSPLoader loader(bsp.get()); if (isGfxFileGltf) @@ -1375,6 +1353,19 @@ namespace BSP } } + if (!bsp->hasSunlightBeenSet) + { + con::info("Writing default sun values"); + bsp->sunlight.type = LIGHT_TYPE_DIRECTIONAL; + bsp->sunlight.colour = {1.0f, 1.0f, 1.0f}; + bsp->sunlight.range = 1000.0f; + bsp->sunlight.intensity = 1000.0f; + bsp->sunlight.pos = {0.0f, 0.0f, 0.0f}; + bsp->sunlight.direction = {0.0f, -1.0f, 0.0f}; + bsp->sunlight.innerConeAngle = 0.0f; + bsp->sunlight.outerConeAngle = 0.0f; + } + return bsp; } } // namespace BSP diff --git a/src/ObjLoading/Game/T6/BSP/Linker/ComWorldLinker.cpp b/src/ObjLoading/Game/T6/BSP/Linker/ComWorldLinker.cpp index c52de71e..12284f9b 100644 --- a/src/ObjLoading/Game/T6/BSP/Linker/ComWorldLinker.cpp +++ b/src/ObjLoading/Game/T6/BSP/Linker/ComWorldLinker.cpp @@ -15,16 +15,6 @@ namespace BSP bool ComWorldLinker::createLightDefs() { - T6::GfxLightDef* lightDefCube = m_memory.Alloc(); - lightDefCube->name = m_memory.Dup("white_light_cube"); - lightDefCube->lmapLookupStart = 0; // always 0 - lightDefCube->attenuation.samplerState = 115; // always 115 - auto imageCubeAsset = m_context.LoadDependency("whitesquare_ft"); - if (imageCubeAsset == nullptr) - return false; - lightDefCube->attenuation.image = imageCubeAsset->Asset(); - m_context.AddAsset(lightDefCube->name, lightDefCube); - T6::GfxLightDef* lightDef2d = m_memory.Alloc(); lightDef2d->name = m_memory.Dup("white_light"); lightDef2d->lmapLookupStart = 0; // always 0 @@ -38,89 +28,6 @@ namespace BSP return true; } - // does not set: type, cosHalfFovOuter, cosHalfFovInner, cosHalfFovExpanded, roundness, defName - void setLightCommonValues(ComPrimaryLight* light, BSPLight* bspLight) - { - light->origin.x = bspLight->pos.x; - light->origin.y = bspLight->pos.y; - light->origin.z = bspLight->pos.z; - - // colour also effects the brightness of the light, it's unclear what the min/max is - vec3_t BSPColor; - BSPColor.x = bspLight->colour.x; - BSPColor.y = bspLight->colour.y; - BSPColor.z = bspLight->colour.z; - light->color.x = BSPColor.x; - light->color.y = BSPColor.y; - light->color.z = BSPColor.z; - light->diffuseColor.x = BSPColor.x; - light->diffuseColor.y = BSPColor.y; - light->diffuseColor.z = BSPColor.z; - light->diffuseColor.w = 0.0f; // always 0 - - // the forward dir of the light, default is (0, 0, 1) to face down (-Z up) - light->dir.x = bspLight->direction.x; - light->dir.y = bspLight->direction.y; - light->dir.z = bspLight->direction.z; - - light->dAttenuation = bspLight->intensity; // not 100% sure if these values are calculated the same - - // the radius of the light's lens - light->radius = bspLight->range; - - light->falloff.x = 0.0f; - light->falloff.y = bspLight->range; // only Y is set - light->falloff.z = 0.0f; - light->falloff.w = 0.0f; - - // allways 0 - light->angle.x = 0.0f; - light->angle.y = 0.0f; - light->angle.z = 0.0f; - light->angle.w = 0.0f; - - // 0 - light cannot move - // 1 <= x > 0 - limit that it can move each game update - light->translationLimit = 0.0f; - - // 1.0f - light cannot rotate - // -1.0f - infinitely rotate - // between 1 and -1 - limit that it can rotate each game update - light->rotationLimit = 1.0f; - - // default values from official map - light->useCookie = 0; - light->cookieControl0.x = 0.0f; - light->cookieControl0.y = 0.0f; - light->cookieControl0.z = 1.0f; - light->cookieControl0.w = 1.0f; - light->cookieControl1.x = 0.0f; - light->cookieControl1.y = 0.0f; - light->cookieControl1.z = 0.0f; - light->cookieControl1.w = 0.0f; - light->cookieControl2.x = 0.0f; - light->cookieControl2.y = 0.0f; - light->cookieControl2.z = 0.0f; - light->cookieControl2.w = 0.0f; - - // these are possibly the result of cos(), unsure how the angle is generated though - // values taken from official maps - light->aAbB.x = 0.5303301215171814f; - light->aAbB.y = 0.7071067690849304f; - light->aAbB.z = 0.5303301215171814f; - light->aAbB.w = 0.7071067690849304f; - - // light won't light the surface unless canUseShadowMap is set to 1 - // may be to do with lights casting shadows on other lights - light->canUseShadowMap = 1; - light->shadowmapVolume = 0; // ignored if this is set to 0 - - light->exponent = 0; - light->priority = 0; - light->cullDist = 1000; - light->mipDistance = 0.0f; - } - ComWorld* ComWorldLinker::linkComWorld(BSPData* bsp) { // all lights that aren't the sunlight or default light need their own GfxLightDef asset @@ -142,52 +49,93 @@ namespace BSP for (size_t lightIdx = 0; lightIdx < totalLightCount; lightIdx++) { ComPrimaryLight* light = &comWorld->primaryLights[lightIdx]; - if (lightIdx == BSPGameConstants::EMPTY_LIGHT_INDEX) continue; // first (empty) light has no data else if (lightIdx == BSPGameConstants::SUN_LIGHT_INDEX) { - const vec4_t sunLightColor = BSPEditableConstants::SUNLIGHT_COLOR; - const vec3_t sunLightDirection = BSPEditableConstants::SUNLIGHT_DIRECTION; + BSPLight* bspLight = &bsp->sunlight; + light->type = GFX_LIGHT_TYPE_DIR; - light->diffuseColor.r = sunLightColor.r; - light->diffuseColor.g = sunLightColor.g; - light->diffuseColor.a = sunLightColor.a; - light->dir.x = sunLightDirection.x; - light->dir.y = sunLightDirection.y; - light->dir.z = sunLightDirection.z; + light->dir.x = bspLight->direction.x; + light->dir.y = bspLight->direction.y; + light->dir.z = bspLight->direction.z; + light->diffuseColor.x = bspLight->colour.x; + light->diffuseColor.y = bspLight->colour.y; + light->diffuseColor.z = bspLight->colour.z; + light->color.x = bspLight->colour.x; + light->color.y = bspLight->colour.y; + light->color.z = bspLight->colour.z; } else { BSPLight* bspLight = &bsp->lights.at(lightIdx - BSPGameConstants::BSP_DEFAULT_LIGHT_COUNT); - if (bspLight->type == LIGHT_TYPE_DIRECTIONAL) - { - light->type = GFX_LIGHT_TYPE_DIR; - light->defName = "white_light"; - light->roundness = 1.0f; - light->cosHalfFovInner = cosf(bspLight->innerConeAngle); - light->cosHalfFovOuter = cosf(bspLight->outerConeAngle); - light->cosHalfFovExpanded = cosf(bspLight->outerConeAngle); - } - else if (bspLight->type == LIGHT_TYPE_SPOT) - { - light->type = GFX_LIGHT_TYPE_SPOT; - light->defName = "white_light"; - light->roundness = 1.0f; - light->cosHalfFovInner = cosf(bspLight->innerConeAngle); - light->cosHalfFovOuter = cosf(bspLight->outerConeAngle); - light->cosHalfFovExpanded = cosf(bspLight->outerConeAngle); - } - else // LIGHT_TYPE_POINT - { - light->type = GFX_LIGHT_TYPE_OMNI; - light->defName = "white_light_cube"; - light->roundness = 0.0f; - light->cosHalfFovInner = cosf(30.0f * (std::numbers::pi_v / 180.0f)); - light->cosHalfFovOuter = cosf(55.0f * (std::numbers::pi_v / 180.0f)); - light->cosHalfFovExpanded = cosf(55.0f * (std::numbers::pi_v / 180.0f)); - } - setLightCommonValues(light, bspLight); + + light->aAbB.x = 0.28173786401748657f; + light->aAbB.y = 0.5634757280349731f; + light->aAbB.z = 0.5634757280349731f; + light->aAbB.w = 0.7071067690849304f; + + light->angle.x = 0.0f; + light->angle.y = 0.0f; + light->angle.z = -0.5235987901687622f; + light->angle.w = 0.0f; + + light->canUseShadowMap = 1; + + light->cookieControl0.x = 0.0f; + light->cookieControl0.y = 0.0f; + light->cookieControl0.z = 1.0f; + light->cookieControl0.w = 1.0f; + light->cookieControl1.x = 0.0f; + light->cookieControl1.y = 0.0f; + light->cookieControl1.z = 0.0f; + light->cookieControl1.w = 0.0f; + light->cookieControl2.x = 0.0f; + light->cookieControl2.y = 0.0f; + light->cookieControl2.z = 0.0f; + light->cookieControl2.w = 0.0f; + + light->color.x = bspLight->colour.x; + light->color.y = bspLight->colour.y; + light->color.z = bspLight->colour.z; + light->cosHalfFovInner = cosf(bspLight->innerConeAngle); + light->cosHalfFovOuter = cosf(bspLight->outerConeAngle); + light->cosHalfFovExpanded = cosf(bspLight->outerConeAngle); + + light->cullDist = 1000; + light->dAttenuation = 10000.0f; + light->defName = "white_light"; + + light->diffuseColor.x = bspLight->colour.x; + light->diffuseColor.y = bspLight->colour.y; + light->diffuseColor.z = bspLight->colour.z; + light->diffuseColor.w = 0.0f; + + light->dir.x = bspLight->direction.x; + light->dir.y = bspLight->direction.y; + light->dir.z = bspLight->direction.z; + + light->exponent = 0; + + light->falloff.y = bspLight->range; + + light->mipDistance = bspLight->range; + + light->priority = 0; + + light->origin.x = bspLight->pos.x; + light->origin.y = bspLight->pos.y; + light->origin.z = bspLight->pos.z; + + light->radius = bspLight->range; + light->rotationLimit = 1.0f; + light->shadowmapVolume = 0; + light->translationLimit = 0.0f; + light->useCookie = 0; + + light->roundness = 0.0f; + + light->type = GFX_LIGHT_TYPE_SPOT; } } diff --git a/src/ObjLoading/Game/T6/BSP/Linker/GfxWorldLinker.cpp b/src/ObjLoading/Game/T6/BSP/Linker/GfxWorldLinker.cpp index 2777775a..9ad676f6 100644 --- a/src/ObjLoading/Game/T6/BSP/Linker/GfxWorldLinker.cpp +++ b/src/ObjLoading/Game/T6/BSP/Linker/GfxWorldLinker.cpp @@ -4,6 +4,23 @@ #include "../BSPUtil.h" #include "Utils/Pack.h" +namespace +{ + unsigned int packLmapCoord(float X, float Y) + { + float XStep = X * 65535.0f; + float YStep = Y * 65535.0f; + + unsigned int result = 0; + result |= (unsigned int)XStep; + result &= 0xFFFF; + result |= (unsigned int)YStep << 16; + result &= 0xFFFFFFFF; + + return result; + } +} // namespace + namespace BSP { GfxWorldLinker::GfxWorldLinker(MemoryManager& memory, ISearchPath& searchPath, AssetCreationContext& context) @@ -30,9 +47,7 @@ namespace BSP gfxVertex->normal.packed = pack32::Vec3PackUnitVecThirdBased(bspVertex.normal.v); gfxVertex->tangent.packed = pack32::Vec3PackUnitVecThirdBased(bspVertex.tangent.v); gfxVertex->binormalSign = bspVertex.binormal.v[0] > 0.0f ? 1.0f : -1.0f; - - // lightmap isn't implemented currently - gfxVertex->lmapCoord.packed = 0; + gfxVertex->lmapCoord.packed = packLmapCoord(0.0f, 0.0f); } gfxWorld->draw.vd0.data = reinterpret_cast(vertexBuffer); @@ -439,14 +454,14 @@ namespace BSP gfxWorld->lightGrid.rowDataStart = m_memory.Alloc(rowDataStartSize); // Adding 0x0F so the lookup table will be 0x10 bytes in size - gfxWorld->lightGrid.rawRowDataSize = static_cast(sizeof(GfxLightGridRow) + 0x0F); + gfxWorld->lightGrid.rawRowDataSize = static_cast(sizeof(GfxLightGridRow) + 0x1FF); GfxLightGridRow* row = static_cast(m_memory.AllocRaw(gfxWorld->lightGrid.rawRowDataSize)); row->colStart = 0; - row->colCount = 0x1000; // 0x1000 as this is large enough for all checks done by the game + row->colCount = 0xFFFF; row->zStart = 0; - row->zCount = 0xFF; // 0xFF as this is large enough for all checks done by the game, but small enough not to mess with other checks + row->zCount = 0xFF; // 0xFF as this seems to be the sweet spot of values row->firstEntry = 0; - for (int i = 0; i < 0x10; i++) // set the lookup table to all 0 + for (int i = 0; i < 0x200; i++) // set the lookup table to all 0xFF row->lookupTable[i] = -1; gfxWorld->lightGrid.rawRowData = reinterpret_cast(row); @@ -464,7 +479,7 @@ namespace BSP // colours are looked up with a lightgrid entries colorsIndex gfxWorld->lightGrid.colorCount = 0x1000; // 0x1000 as it should be enough to hold every index gfxWorld->lightGrid.colors = m_memory.Alloc(gfxWorld->lightGrid.colorCount); - memset(gfxWorld->lightGrid.colors, BSPEditableConstants::LIGHTGRID_COLOUR, rowDataStartSize * sizeof(uint16_t)); + memset(gfxWorld->lightGrid.colors, 32, rowDataStartSize * sizeof(uint16_t)); // we use the colours array instead of coeffs array gfxWorld->lightGrid.coeffCount = 0; @@ -619,33 +634,17 @@ namespace BSP } } - void GfxWorldLinker::loadSunData(GfxWorld* gfxWorld) + void GfxWorldLinker::loadSunData(BSPData* bsp, GfxWorld* gfxWorld) { - // default values taken from mp_dig - gfxWorld->sunParse.fogTransitionTime = 0.001f; - gfxWorld->sunParse.name[0] = 0x00; - - gfxWorld->sunParse.initWorldSun->control = 0; - gfxWorld->sunParse.initWorldSun->exposure = 2.5f; - gfxWorld->sunParse.initWorldSun->angles.x = -29.0f; - gfxWorld->sunParse.initWorldSun->angles.y = 254.0f; - gfxWorld->sunParse.initWorldSun->angles.z = 0.0f; - gfxWorld->sunParse.initWorldSun->sunCd.x = 1.0f; - gfxWorld->sunParse.initWorldSun->sunCd.y = 0.89f; - gfxWorld->sunParse.initWorldSun->sunCd.z = 0.69f; - gfxWorld->sunParse.initWorldSun->sunCd.w = 13.5f; - gfxWorld->sunParse.initWorldSun->ambientColor.x = 0.0f; - gfxWorld->sunParse.initWorldSun->ambientColor.y = 0.0f; - gfxWorld->sunParse.initWorldSun->ambientColor.z = 0.0f; - gfxWorld->sunParse.initWorldSun->ambientColor.w = 0.0f; - gfxWorld->sunParse.initWorldSun->skyColor.x = 0.0f; - gfxWorld->sunParse.initWorldSun->skyColor.y = 0.0f; - gfxWorld->sunParse.initWorldSun->skyColor.z = 0.0f; - gfxWorld->sunParse.initWorldSun->skyColor.w = 0.0f; - gfxWorld->sunParse.initWorldSun->sunCs.x = 0.0f; - gfxWorld->sunParse.initWorldSun->sunCs.y = 0.0f; - gfxWorld->sunParse.initWorldSun->sunCs.z = 0.0f; - gfxWorld->sunParse.initWorldSun->sunCs.w = 0.0f; + BSPLight& sunlight = bsp->sunlight; + vec3_t viewAngles = BSPUtil::convertForwardVectorToViewAngles(sunlight.direction); + gfxWorld->sunParse.initWorldSun->angles.x = viewAngles.x; + gfxWorld->sunParse.initWorldSun->angles.y = viewAngles.y; + gfxWorld->sunParse.initWorldSun->angles.z = viewAngles.z; + gfxWorld->sunParse.initWorldSun->sunCd.x = sunlight.colour.x; + gfxWorld->sunParse.initWorldSun->sunCd.y = sunlight.colour.y; + gfxWorld->sunParse.initWorldSun->sunCd.z = sunlight.colour.z; + gfxWorld->sunParse.initWorldSun->sunCd.w = 1.0f; gfxWorld->sunParse.initWorldFog->baseDist = 150.0f; gfxWorld->sunParse.initWorldFog->baseHeight = -100.0f; @@ -849,7 +848,7 @@ namespace BSP loadModels(bsp, gfxWorld); // requires surfaces - loadSunData(gfxWorld); + loadSunData(bsp, gfxWorld); loadDynEntData(gfxWorld); diff --git a/src/ObjLoading/Game/T6/BSP/Linker/GfxWorldLinker.h b/src/ObjLoading/Game/T6/BSP/Linker/GfxWorldLinker.h index e594cd01..570df5ac 100644 --- a/src/ObjLoading/Game/T6/BSP/Linker/GfxWorldLinker.h +++ b/src/ObjLoading/Game/T6/BSP/Linker/GfxWorldLinker.h @@ -31,7 +31,7 @@ namespace BSP void loadSkyBox(BSPData* projInfo, GfxWorld* gfxWorld); void loadDynEntData(GfxWorld* gfxWorld); bool loadOutdoors(GfxWorld* gfxWorld); - void loadSunData(GfxWorld* gfxWorld); + void loadSunData(BSPData* projInfo, GfxWorld* gfxWorld); void loadWorldBounds(GfxWorld* gfxWorld); }; } // namespace BSP