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:
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user