2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2026-06-06 08:42:35 +00:00

feat: Loading sun data through GLTF

This commit is contained in:
LJW-Dev
2026-04-22 19:22:45 +08:00
committed by Jan Laupetin
parent 855825c6de
commit d0ae3ecdb5
5 changed files with 198 additions and 259 deletions
+4 -3
View File
@@ -88,7 +88,6 @@ namespace BSP
enum BSPLightType enum BSPLightType
{ {
LIGHT_TYPE_DIRECTIONAL, LIGHT_TYPE_DIRECTIONAL,
LIGHT_TYPE_POINT,
LIGHT_TYPE_SPOT LIGHT_TYPE_SPOT
}; };
@@ -101,9 +100,8 @@ namespace BSP
vec3_t pos; vec3_t pos;
vec3_t direction; 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 innerConeAngle;
float outerConeAngle; float outerConeAngle;
}; };
@@ -172,6 +170,9 @@ namespace BSP
std::vector<BSPZSpawnerZM> zm_spawners; std::vector<BSPZSpawnerZM> zm_spawners;
std::vector<BSPEntity> entities; std::vector<BSPEntity> entities;
bool hasSunlightBeenSet;
BSPLight sunlight;
std::vector<BSPModel> models; std::vector<BSPModel> models;
}; };
+81 -90
View File
@@ -359,32 +359,85 @@ namespace
return vertexOffset; 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);
assert(node.extensions->KHR_lights_punctual); assert(node.extensions->KHR_lights_punctual);
int lightIndex = node.extensions->KHR_lights_punctual->light; int lightIndex = node.extensions->KHR_lights_punctual->light;
const JsonPunctualLight& jsLight = jRoot.extensions->KHR_lights_punctual->lights->at(lightIndex);
BSPLight light{};
assert(lightIndex >= 0); light.outerConeAngle = std::numbers::pi_v<float> / 4.0f; /// spec of 45 degrees
if (m_bsp->lights[lightIndex].hasPosBeenSet == true) light.innerConeAngle = 0.0f;
con::warn("Internal error, multiple nodes reference the same light. Light positions/rotations are likely incorrect."); 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 position(0, 0, 0, 1.0f);
Eigen::Vector4f transformedPosition = nodeMatrix * position; Eigen::Vector4f transformedPosition = nodeMatrix * position;
m_bsp->lights[lightIndex].pos = vec3_t{transformedPosition.x(), transformedPosition.y(), transformedPosition.z()}; light.pos = vec3_t{transformedPosition.x(), transformedPosition.y(), transformedPosition.z()};
RhcToLhcCoordinates(m_bsp->lights[lightIndex].pos.v); RhcToLhcCoordinates(light.pos.v);
// GLTF spec uses +Y up and the default light direction is straight down Eigen::Vector3f defaultDirection(0.0f, 0.0f, 1.0f); // lights use this value for the forward angle instead in BO2
Eigen::Vector3f defaultDirection(0.0f, -1.0f, 0.0f);
Eigen::Affine3f affineTransform(nodeMatrix); Eigen::Affine3f affineTransform(nodeMatrix);
Eigen::Matrix3f rotationMatrix = affineTransform.rotation(); Eigen::Matrix3f rotationMatrix = affineTransform.rotation();
Eigen::Vector3f outputDirection = rotationMatrix * defaultDirection; Eigen::Vector3f outputDirection = rotationMatrix * defaultDirection;
outputDirection.normalize(); 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; return true;
} }
@@ -588,7 +641,6 @@ namespace
xmodel.rotationQuaternion.w = rotationQuat.w(); xmodel.rotationQuaternion.w = rotationQuat.w();
RhcToLhcQuaternion(xmodel.rotationQuaternion.v); RhcToLhcQuaternion(xmodel.rotationQuaternion.v);
con::warn("XModels don't support scale currently, keep it at 1 in your editor");
xmodel.scale = 1.0f; xmodel.scale = 1.0f;
calculateXmodelBounds(xmodel, node.mesh, nodeMatrix, jRoot); calculateXmodelBounds(xmodel, node.mesh, nodeMatrix, jRoot);
@@ -904,7 +956,7 @@ namespace
bool addNodeToBSP(const JsonRoot& jRoot, const gltf::JsonNode& node, Eigen::Matrix4f& nodeMatrix) bool addNodeToBSP(const JsonRoot& jRoot, const gltf::JsonNode& node, Eigen::Matrix4f& nodeMatrix)
{ {
if (m_is_world_gfx && node.extensions && node.extensions->KHR_lights_punctual) if (m_is_world_gfx && node.extensions && node.extensions->KHR_lights_punctual)
return addLightNode(node, nodeMatrix); return addLightNode(jRoot, node, nodeMatrix);
if (node.extras) if (node.extras)
{ {
@@ -1040,80 +1092,6 @@ namespace
m_curr_bsp_world->materials.emplace_back(emptyMaterial); 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<JsonPunctualLight>& 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) void TraverseNodes(const JsonRoot& jRoot)
{ {
// Make sure there are any nodes to traverse // Make sure there are any nodes to traverse
@@ -1266,9 +1244,6 @@ namespace
CreateBufferViews(jRoot); CreateBufferViews(jRoot);
CreateAccessors(jRoot); CreateAccessors(jRoot);
if (isGfxWorld) // lights aren't needed in collision data
LoadLights(jRoot);
LoadMaterials(jRoot); LoadMaterials(jRoot);
TraverseNodes(jRoot); // requires materials and lights TraverseNodes(jRoot); // requires materials and lights
} }
@@ -1330,6 +1305,9 @@ namespace BSP
bsp->name = mapName; bsp->name = mapName;
bsp->bspName = "maps/mp/" + mapName + ".d3dbsp"; bsp->bspName = "maps/mp/" + mapName + ".d3dbsp";
bsp->isZombiesMap = isZombiesMap; 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()); BSPLoader loader(bsp.get());
if (isGfxFileGltf) 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; return bsp;
} }
} // namespace BSP } // namespace BSP
@@ -15,16 +15,6 @@ namespace BSP
bool ComWorldLinker::createLightDefs() bool ComWorldLinker::createLightDefs()
{ {
T6::GfxLightDef* lightDefCube = m_memory.Alloc<T6::GfxLightDef>();
lightDefCube->name = m_memory.Dup("white_light_cube");
lightDefCube->lmapLookupStart = 0; // always 0
lightDefCube->attenuation.samplerState = 115; // always 115
auto imageCubeAsset = m_context.LoadDependency<T6::AssetImage>("whitesquare_ft");
if (imageCubeAsset == nullptr)
return false;
lightDefCube->attenuation.image = imageCubeAsset->Asset();
m_context.AddAsset<T6::AssetLightDef>(lightDefCube->name, lightDefCube);
T6::GfxLightDef* lightDef2d = m_memory.Alloc<T6::GfxLightDef>(); T6::GfxLightDef* lightDef2d = m_memory.Alloc<T6::GfxLightDef>();
lightDef2d->name = m_memory.Dup("white_light"); lightDef2d->name = m_memory.Dup("white_light");
lightDef2d->lmapLookupStart = 0; // always 0 lightDef2d->lmapLookupStart = 0; // always 0
@@ -38,89 +28,6 @@ namespace BSP
return true; 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) ComWorld* ComWorldLinker::linkComWorld(BSPData* bsp)
{ {
// all lights that aren't the sunlight or default light need their own GfxLightDef asset // 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++) for (size_t lightIdx = 0; lightIdx < totalLightCount; lightIdx++)
{ {
ComPrimaryLight* light = &comWorld->primaryLights[lightIdx]; ComPrimaryLight* light = &comWorld->primaryLights[lightIdx];
if (lightIdx == BSPGameConstants::EMPTY_LIGHT_INDEX) if (lightIdx == BSPGameConstants::EMPTY_LIGHT_INDEX)
continue; // first (empty) light has no data continue; // first (empty) light has no data
else if (lightIdx == BSPGameConstants::SUN_LIGHT_INDEX) else if (lightIdx == BSPGameConstants::SUN_LIGHT_INDEX)
{ {
const vec4_t sunLightColor = BSPEditableConstants::SUNLIGHT_COLOR; BSPLight* bspLight = &bsp->sunlight;
const vec3_t sunLightDirection = BSPEditableConstants::SUNLIGHT_DIRECTION;
light->type = GFX_LIGHT_TYPE_DIR; light->type = GFX_LIGHT_TYPE_DIR;
light->diffuseColor.r = sunLightColor.r; light->dir.x = bspLight->direction.x;
light->diffuseColor.g = sunLightColor.g; light->dir.y = bspLight->direction.y;
light->diffuseColor.a = sunLightColor.a; light->dir.z = bspLight->direction.z;
light->dir.x = sunLightDirection.x; light->diffuseColor.x = bspLight->colour.x;
light->dir.y = sunLightDirection.y; light->diffuseColor.y = bspLight->colour.y;
light->dir.z = sunLightDirection.z; 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 else
{ {
BSPLight* bspLight = &bsp->lights.at(lightIdx - BSPGameConstants::BSP_DEFAULT_LIGHT_COUNT); BSPLight* bspLight = &bsp->lights.at(lightIdx - BSPGameConstants::BSP_DEFAULT_LIGHT_COUNT);
if (bspLight->type == LIGHT_TYPE_DIRECTIONAL)
{ light->aAbB.x = 0.28173786401748657f;
light->type = GFX_LIGHT_TYPE_DIR; light->aAbB.y = 0.5634757280349731f;
light->defName = "white_light"; light->aAbB.z = 0.5634757280349731f;
light->roundness = 1.0f; 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->cosHalfFovInner = cosf(bspLight->innerConeAngle);
light->cosHalfFovOuter = cosf(bspLight->outerConeAngle); light->cosHalfFovOuter = cosf(bspLight->outerConeAngle);
light->cosHalfFovExpanded = cosf(bspLight->outerConeAngle); light->cosHalfFovExpanded = cosf(bspLight->outerConeAngle);
}
else if (bspLight->type == LIGHT_TYPE_SPOT) light->cullDist = 1000;
{ light->dAttenuation = 10000.0f;
light->type = GFX_LIGHT_TYPE_SPOT;
light->defName = "white_light"; light->defName = "white_light";
light->roundness = 1.0f;
light->cosHalfFovInner = cosf(bspLight->innerConeAngle); light->diffuseColor.x = bspLight->colour.x;
light->cosHalfFovOuter = cosf(bspLight->outerConeAngle); light->diffuseColor.y = bspLight->colour.y;
light->cosHalfFovExpanded = cosf(bspLight->outerConeAngle); light->diffuseColor.z = bspLight->colour.z;
} light->diffuseColor.w = 0.0f;
else // LIGHT_TYPE_POINT
{ light->dir.x = bspLight->direction.x;
light->type = GFX_LIGHT_TYPE_OMNI; light->dir.y = bspLight->direction.y;
light->defName = "white_light_cube"; 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->roundness = 0.0f;
light->cosHalfFovInner = cosf(30.0f * (std::numbers::pi_v<float> / 180.0f));
light->cosHalfFovOuter = cosf(55.0f * (std::numbers::pi_v<float> / 180.0f)); light->type = GFX_LIGHT_TYPE_SPOT;
light->cosHalfFovExpanded = cosf(55.0f * (std::numbers::pi_v<float> / 180.0f));
}
setLightCommonValues(light, bspLight);
} }
} }
@@ -4,6 +4,23 @@
#include "../BSPUtil.h" #include "../BSPUtil.h"
#include "Utils/Pack.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 namespace BSP
{ {
GfxWorldLinker::GfxWorldLinker(MemoryManager& memory, ISearchPath& searchPath, AssetCreationContext& context) GfxWorldLinker::GfxWorldLinker(MemoryManager& memory, ISearchPath& searchPath, AssetCreationContext& context)
@@ -30,9 +47,7 @@ namespace BSP
gfxVertex->normal.packed = pack32::Vec3PackUnitVecThirdBased(bspVertex.normal.v); gfxVertex->normal.packed = pack32::Vec3PackUnitVecThirdBased(bspVertex.normal.v);
gfxVertex->tangent.packed = pack32::Vec3PackUnitVecThirdBased(bspVertex.tangent.v); gfxVertex->tangent.packed = pack32::Vec3PackUnitVecThirdBased(bspVertex.tangent.v);
gfxVertex->binormalSign = bspVertex.binormal.v[0] > 0.0f ? 1.0f : -1.0f; gfxVertex->binormalSign = bspVertex.binormal.v[0] > 0.0f ? 1.0f : -1.0f;
gfxVertex->lmapCoord.packed = packLmapCoord(0.0f, 0.0f);
// lightmap isn't implemented currently
gfxVertex->lmapCoord.packed = 0;
} }
gfxWorld->draw.vd0.data = reinterpret_cast<char*>(vertexBuffer); gfxWorld->draw.vd0.data = reinterpret_cast<char*>(vertexBuffer);
@@ -439,14 +454,14 @@ namespace BSP
gfxWorld->lightGrid.rowDataStart = m_memory.Alloc<uint16_t>(rowDataStartSize); gfxWorld->lightGrid.rowDataStart = m_memory.Alloc<uint16_t>(rowDataStartSize);
// Adding 0x0F so the lookup table will be 0x10 bytes in size // Adding 0x0F so the lookup table will be 0x10 bytes in size
gfxWorld->lightGrid.rawRowDataSize = static_cast<unsigned int>(sizeof(GfxLightGridRow) + 0x0F); gfxWorld->lightGrid.rawRowDataSize = static_cast<unsigned int>(sizeof(GfxLightGridRow) + 0x1FF);
GfxLightGridRow* row = static_cast<GfxLightGridRow*>(m_memory.AllocRaw(gfxWorld->lightGrid.rawRowDataSize)); GfxLightGridRow* row = static_cast<GfxLightGridRow*>(m_memory.AllocRaw(gfxWorld->lightGrid.rawRowDataSize));
row->colStart = 0; 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->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; 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; row->lookupTable[i] = -1;
gfxWorld->lightGrid.rawRowData = reinterpret_cast<aligned_byte_pointer*>(row); gfxWorld->lightGrid.rawRowData = reinterpret_cast<aligned_byte_pointer*>(row);
@@ -464,7 +479,7 @@ namespace BSP
// colours are looked up with a lightgrid entries colorsIndex // 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.colorCount = 0x1000; // 0x1000 as it should be enough to hold every index
gfxWorld->lightGrid.colors = m_memory.Alloc<GfxCompressedLightGridColors>(gfxWorld->lightGrid.colorCount); gfxWorld->lightGrid.colors = m_memory.Alloc<GfxCompressedLightGridColors>(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 // we use the colours array instead of coeffs array
gfxWorld->lightGrid.coeffCount = 0; 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 BSPLight& sunlight = bsp->sunlight;
gfxWorld->sunParse.fogTransitionTime = 0.001f; vec3_t viewAngles = BSPUtil::convertForwardVectorToViewAngles(sunlight.direction);
gfxWorld->sunParse.name[0] = 0x00; gfxWorld->sunParse.initWorldSun->angles.x = viewAngles.x;
gfxWorld->sunParse.initWorldSun->angles.y = viewAngles.y;
gfxWorld->sunParse.initWorldSun->control = 0; gfxWorld->sunParse.initWorldSun->angles.z = viewAngles.z;
gfxWorld->sunParse.initWorldSun->exposure = 2.5f; gfxWorld->sunParse.initWorldSun->sunCd.x = sunlight.colour.x;
gfxWorld->sunParse.initWorldSun->angles.x = -29.0f; gfxWorld->sunParse.initWorldSun->sunCd.y = sunlight.colour.y;
gfxWorld->sunParse.initWorldSun->angles.y = 254.0f; gfxWorld->sunParse.initWorldSun->sunCd.z = sunlight.colour.z;
gfxWorld->sunParse.initWorldSun->angles.z = 0.0f; gfxWorld->sunParse.initWorldSun->sunCd.w = 1.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;
gfxWorld->sunParse.initWorldFog->baseDist = 150.0f; gfxWorld->sunParse.initWorldFog->baseDist = 150.0f;
gfxWorld->sunParse.initWorldFog->baseHeight = -100.0f; gfxWorld->sunParse.initWorldFog->baseHeight = -100.0f;
@@ -849,7 +848,7 @@ namespace BSP
loadModels(bsp, gfxWorld); // requires surfaces loadModels(bsp, gfxWorld); // requires surfaces
loadSunData(gfxWorld); loadSunData(bsp, gfxWorld);
loadDynEntData(gfxWorld); loadDynEntData(gfxWorld);
@@ -31,7 +31,7 @@ namespace BSP
void loadSkyBox(BSPData* projInfo, GfxWorld* gfxWorld); void loadSkyBox(BSPData* projInfo, GfxWorld* gfxWorld);
void loadDynEntData(GfxWorld* gfxWorld); void loadDynEntData(GfxWorld* gfxWorld);
bool loadOutdoors(GfxWorld* gfxWorld); bool loadOutdoors(GfxWorld* gfxWorld);
void loadSunData(GfxWorld* gfxWorld); void loadSunData(BSPData* projInfo, GfxWorld* gfxWorld);
void loadWorldBounds(GfxWorld* gfxWorld); void loadWorldBounds(GfxWorld* gfxWorld);
}; };
} // namespace BSP } // namespace BSP