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

feat: load xmodels from GLTF and link them, xmodel collision not working yet.

This commit is contained in:
LJW-Dev
2026-03-20 10:54:30 +08:00
committed by Jan Laupetin
parent 7a9d1fa7cb
commit 7ea2ebedbb
8 changed files with 346 additions and 129 deletions
+14 -16
View File
@@ -43,12 +43,26 @@ namespace BSP
int indexOfFirstIndex;
};
struct BSPXModel
{
std::string name;
vec3_t origin;
vec4_t rotationQuaternion;
float scale;
bool areBoundsValid;
vec3_t mins;
vec3_t maxs;
};
struct BSPWorld
{
std::vector<BSPSurface> surfaces;
std::vector<BSPVertex> vertices;
std::vector<uint16_t> indices;
std::vector<BSPMaterial> materials;
std::vector<BSPXModel> xmodels;
};
enum BSPLightType
@@ -74,21 +88,6 @@ namespace BSP
float outerConeAngle;
};
struct BSPXModel
{
std::string name;
vec3_t origin;
float scale;
vec3_t forward;
vec3_t right;
vec3_t up;
bool areBoundsValid;
vec3_t mins;
vec3_t maxs;
};
enum BSPSpawnPointType
{
SPAWNPOINT_TYPE_DEFENDER,
@@ -112,7 +111,6 @@ namespace BSP
BSPWorld colWorld;
std::vector<BSPLight> lights;
std::vector<BSPXModel> xmodels;
std::vector<BSPSpawnPoint> spawnpoints;
};
+115 -3
View File
@@ -32,6 +32,16 @@ namespace
unsigned m_index_accessor;
};
void RhcToLhcQuaternion(float (&coords)[4])
{
const float two[4]{coords[0], coords[1], coords[2], coords[3]};
coords[0] = two[0];
coords[1] = -two[2];
coords[2] = two[1];
coords[3] = two[3];
}
void RhcToLhcCoordinates(float (&coords)[3])
{
const float two[3]{coords[0], coords[1], coords[2]};
@@ -392,8 +402,110 @@ namespace
return true;
}
bool addXModelNode(const gltf::JsonNode& node)
void calculateXmodelBounds(BSPXModel& xmodel, std::optional<int> meshIndex, Eigen::Matrix4f& nodeMatrix, const JsonRoot& jRoot)
{
if (meshIndex)
{
xmodel.areBoundsValid = true;
Eigen::Vector4f position(0, 0, 0, 1.0f);
Eigen::Vector4f transformedPosition = nodeMatrix * position;
xmodel.mins.x = transformedPosition.x();
xmodel.mins.y = transformedPosition.y();
xmodel.mins.z = transformedPosition.z();
xmodel.maxs.x = transformedPosition.x();
xmodel.maxs.y = transformedPosition.y();
xmodel.maxs.z = transformedPosition.z();
RhcToLhcCoordinates(xmodel.mins.v);
RhcToLhcCoordinates(xmodel.maxs.v);
const auto& mesh = jRoot.meshes.value()[*meshIndex];
for (size_t primIdx = 0; primIdx < mesh.primitives.size(); primIdx++)
{
const auto& primitive = mesh.primitives.at(primIdx);
if (!primitive.attributes.POSITION)
throw GltfLoadException("Requires primitives attribute POSITION");
// clang-format off
const auto* positionAccessor = GetAccessorForIndex(
"POSITION",
primitive.attributes.POSITION,
{ JsonAccessorType::VEC3 },
{ JsonAccessorComponentType::FLOAT }
).value_or(nullptr);
// clang-format on
assert(positionAccessor != nullptr);
for (size_t vertexIndex = 0u; vertexIndex < positionAccessor->GetCount(); vertexIndex++)
{
vec3_t vertex;
if (!positionAccessor->GetFloatVec3(vertexIndex, vertex.v))
assert(false);
Eigen::Vector4f position(vertex.x, vertex.y, vertex.z, 1.0f);
Eigen::Vector4f transformedPosition = nodeMatrix * position;
vertex.x = transformedPosition.x();
vertex.y = transformedPosition.y();
vertex.z = transformedPosition.z();
RhcToLhcCoordinates(vertex.v);
if (vertexIndex == 0 && primIdx == 0)
{
xmodel.mins = vertex;
xmodel.maxs = vertex;
}
else
BSPUtil::updateAABBWithPoint(vertex, xmodel.mins, xmodel.maxs);
}
}
}
else
{
xmodel.areBoundsValid = false;
xmodel.mins.x = 0.0f;
xmodel.mins.y = 0.0f;
xmodel.mins.z = 0.0f;
xmodel.maxs.x = 0.0f;
xmodel.maxs.y = 0.0f;
xmodel.maxs.z = 0.0f;
}
}
bool addXModelNode(const JsonRoot& jRoot, const gltf::JsonNode& node)
{
assert(node.extras);
assert(node.extras->xmodel);
Eigen::Matrix4f nodeMatrix = createNodeMatrix(node);
BSPXModel xmodel;
if (node.extras->xmodel->size() == 0)
throw GltfLoadException("Xmodel has no name.");
xmodel.name = *node.extras->xmodel;
Eigen::Vector4f position(0, 0, 0, 1.0f);
Eigen::Vector4f transformedPosition = nodeMatrix * position;
xmodel.origin.x = transformedPosition.x();
xmodel.origin.y = transformedPosition.y();
xmodel.origin.z = transformedPosition.z();
RhcToLhcCoordinates(xmodel.origin.v);
Eigen::Affine3f affineTransform(nodeMatrix);
Eigen::Quaternionf rotationQuat(affineTransform.rotation());
rotationQuat.normalize();
xmodel.rotationQuaternion.x = rotationQuat.x();
xmodel.rotationQuaternion.y = rotationQuat.y();
xmodel.rotationQuaternion.z = rotationQuat.z();
xmodel.rotationQuaternion.w = rotationQuat.w(); // Eigen is WXYZ, game is XYZW
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);
m_curr_bsp_world->xmodels.emplace_back(xmodel);
return true;
}
@@ -447,8 +559,8 @@ namespace
if (node.extras)
{
if (m_is_world_gfx && node.extras->xmodel)
return addXModelNode(node);
if (node.extras->xmodel)
return addXModelNode(jRoot, node);
if (m_is_world_gfx && node.extras->spawnpoint)
return addSpawnPointNode(node);
+69 -1
View File
@@ -104,7 +104,43 @@ namespace BSP
return sqrtf((x * x) + (y * y) + (z * z));
}
void BSPUtil::convertAnglesToAxis(vec3_t* angles, vec3_t* axis)
void BSPUtil::calculateXmodelBounds(XModel* xmodel, vec3_t axis[3], vec3_t& out_mins, vec3_t& out_maxs)
{
out_mins.x = 0.0f;
out_mins.y = 0.0f;
out_mins.z = 0.0f;
out_maxs.x = 0.0f;
out_maxs.y = 0.0f;
out_maxs.z = 0.0f;
for (auto surfaceIndex = 0u; surfaceIndex < xmodel->lodInfo[0].numsurfs; surfaceIndex++)
{
const auto& surface = xmodel->surfs[surfaceIndex + xmodel->lodInfo[0].surfIndex];
if (!surface.verts0)
continue;
for (auto vertIndex = 0u; vertIndex < surface.vertCount; vertIndex++)
{
const auto& vertex = surface.verts0[vertIndex].xyz;
vec3_t rotatedVert;
rotatedVert.x = (vertex.x * axis[0].x) + (vertex.y * axis[1].x) + (vertex.z * axis[2].x);
rotatedVert.y = (vertex.x * axis[0].y) + (vertex.y * axis[1].y) + (vertex.z * axis[2].y);
rotatedVert.z = (vertex.x * axis[0].z) + (vertex.y * axis[1].z) + (vertex.z * axis[2].z);
if (vertIndex == 0 && surfaceIndex == 0)
{
out_mins = rotatedVert;
out_maxs = rotatedVert;
}
else
BSPUtil::updateAABBWithPoint(rotatedVert, out_mins, out_maxs);
}
}
}
void BSPUtil::convertAnglesToAxis(vec3_t* angles, vec3_t axis[3])
{
float cosX = cos(angles->x);
float sinX = sin(angles->x);
@@ -124,6 +160,38 @@ namespace BSP
axis[2].z = cosZ * cosX;
}
void BSPUtil::convertQuaternionToAxis(vec4_t* quat, vec3_t axis[3])
{
float quatX = quat->v[0];
float quatY = quat->v[1];
float quatZ = quat->v[2];
float quatW = quat->v[3];
float xx = (quatX * 2.0) * quatX;
float xy = (quatX * 2.0) * quatY;
float xz = (quatX * 2.0) * quatZ;
float xw = (quatX * 2.0) * quatW;
float yy = (quatY * 2.0) * quatY;
float yz = (quatY * 2.0) * quatZ;
float yw = (quatY * 2.0) * quatW;
float zz = (quatZ * 2.0) * quatZ;
float zw = (quatZ * 2.0) * quatW;
axis->x = 1.0f - (zz + yy);
axis->y = zw + xy;
axis->z = xz - yw;
axis[1].x = xy - zw;
axis[1].y = 1.0f - (zz + xx);
axis[1].z = yz + xw;
axis[2].x = yw + xz;
axis[2].y = yz - xw;
axis[2].z = 1.0f - (yy + xx);
}
vec3_t BSPUtil::convertForwardVectorToViewAngles(vec3_t& forwardVec)
{
vec3_t viewAngles;
+3 -1
View File
@@ -16,7 +16,9 @@ namespace BSP
static vec3_t calcHalfSizeOfAABB(vec3_t& mins, vec3_t& maxs);
static size_t allignBy128(size_t size);
static float distBetweenPoints(vec3_t& p1, vec3_t& p2);
static void convertAnglesToAxis(vec3_t* angles, vec3_t* axis);
static void calculateXmodelBounds(XModel* xmodel, vec3_t axis[3], vec3_t& out_mins, vec3_t& out_maxs);
static void convertAnglesToAxis(vec3_t* angles, vec3_t axis[3]);
static void convertQuaternionToAxis(vec4_t* quat, vec3_t axis[3]);
static vec3_t convertForwardVectorToViewAngles(vec3_t& forwardVec);
static void matrixTranspose3x3(const vec3_t* in, vec3_t* out);
static vec3_t convertStringToVec3(std::string& str);
@@ -154,54 +154,77 @@ namespace BSP
clipMap->cmodels[0].info = nullptr;
}
void ClipMapLinker::loadXModelCollision(clipMap_t* clipMap)
bool ClipMapLinker::loadXModelCollision(clipMap_t* clipMap, BSPData* bsp)
{
// Right now XModels aren't supported
clipMap->numStaticModels = 0;
clipMap->staticModelList = nullptr;
// WIP code left in for future support
/*
auto gfxWorldAsset = m_context.LoadDependency<AssetGfxWorld>(bsp->bspName);
assert(gfxWorldAsset != nullptr);
GfxWorld* gfxWorld = gfxWorldAsset->Asset();
clipMap->numStaticModels = gfxWorld->dpvs.smodelCount;
clipMap->numStaticModels = bsp->colWorld.xmodels.size();
clipMap->staticModelList = new cStaticModel_s[clipMap->numStaticModels];
for (unsigned int i = 0; i < clipMap->numStaticModels; i++)
{
GfxStaticModelDrawInst* gfxModelDrawInst = &gfxWorld->dpvs.smodelDrawInsts[i];
GfxStaticModelInst* gfxModelInst = &gfxWorld->dpvs.smodelInsts[i];
cStaticModel_s* currModel = &clipMap->staticModelList[i];
BSPXModel& bspModel = bsp->colWorld.xmodels.at(i);
vec3_t xmodelAxis[3];
BSPUtil::convertQuaternionToAxis(&bspModel.rotationQuaternion, xmodelAxis);
auto xModelAsset = m_context.LoadDependency<AssetXModel>(bspModel.name);
if (xModelAsset == nullptr)
{
con::error("Unable to load xmodel asset: \"{}\"", bspModel.name);
return false;
}
else
currModel->xmodel = (XModel*)xModelAsset->Asset();
currModel->origin.x = bspModel.origin.x;
currModel->origin.y = bspModel.origin.y;
currModel->origin.z = bspModel.origin.z;
currModel->contents = 1;
// currModel->contents = currModel->xmodel->contents;
if (!xModelAsset->IsReference())
{
BSPUtil::calculateXmodelBounds(currModel->xmodel, xmodelAxis, currModel->absmin, currModel->absmax);
currModel->absmin.x = (currModel->absmin.x * bspModel.scale) + bspModel.origin.x;
currModel->absmin.y = (currModel->absmin.y * bspModel.scale) + bspModel.origin.y;
currModel->absmin.z = (currModel->absmin.z * bspModel.scale) + bspModel.origin.z;
currModel->absmax.x = (currModel->absmax.x * bspModel.scale) + bspModel.origin.x;
currModel->absmax.y = (currModel->absmax.y * bspModel.scale) + bspModel.origin.y;
currModel->absmax.z = (currModel->absmax.z * bspModel.scale) + bspModel.origin.z;
}
else
{
if (bspModel.areBoundsValid)
{
currModel->absmin = bspModel.mins;
currModel->absmax = bspModel.maxs;
}
else
{
con::warn("Unable to determine the bounds of xmodel: \"{}\"", bspModel.name);
currModel->absmin.x = bspModel.origin.x - 1.0f;
currModel->absmin.y = bspModel.origin.y - 1.0f;
currModel->absmin.z = bspModel.origin.z - 1.0f;
currModel->absmax.x = bspModel.origin.x + 1.0f;
currModel->absmax.y = bspModel.origin.y + 1.0f;
currModel->absmax.z = bspModel.origin.z + 1.0f;
}
}
BSPUtil::matrixTranspose3x3(xmodelAxis, currModel->invScaledAxis);
currModel->invScaledAxis[0].x = (1.0f / bspModel.scale) * currModel->invScaledAxis[0].x;
currModel->invScaledAxis[0].y = (1.0f / bspModel.scale) * currModel->invScaledAxis[0].y;
currModel->invScaledAxis[0].z = (1.0f / bspModel.scale) * currModel->invScaledAxis[0].z;
currModel->invScaledAxis[1].x = (1.0f / bspModel.scale) * currModel->invScaledAxis[1].x;
currModel->invScaledAxis[1].y = (1.0f / bspModel.scale) * currModel->invScaledAxis[1].y;
currModel->invScaledAxis[1].z = (1.0f / bspModel.scale) * currModel->invScaledAxis[1].z;
currModel->invScaledAxis[2].x = (1.0f / bspModel.scale) * currModel->invScaledAxis[2].x;
currModel->invScaledAxis[2].y = (1.0f / bspModel.scale) * currModel->invScaledAxis[2].y;
currModel->invScaledAxis[2].z = (1.0f / bspModel.scale) * currModel->invScaledAxis[2].z;
memset(&currModel->writable, 0, sizeof(cStaticModelWritable));
currModel->xmodel = gfxModelDrawInst->model;
currModel->contents = gfxModelDrawInst->model->contents;
currModel->origin.x = gfxModelDrawInst->placement.origin.x;
currModel->origin.y = gfxModelDrawInst->placement.origin.y;
currModel->origin.z = gfxModelDrawInst->placement.origin.z;
// TODO: this does not account for model rotation or scale
currModel->absmin.x = gfxModelInst->mins.x;
currModel->absmin.y = gfxModelInst->mins.y;
currModel->absmin.z = gfxModelInst->mins.z;
currModel->absmax.x = gfxModelInst->maxs.x;
currModel->absmax.y = gfxModelInst->maxs.y;
currModel->absmax.z = gfxModelInst->maxs.z;
BSPUtil::matrixTranspose3x3(gfxModelDrawInst->placement.axis, currModel->invScaledAxis);
currModel->invScaledAxis[0].x = (1.0f / gfxModelDrawInst->placement.scale) * currModel->invScaledAxis[0].x;
currModel->invScaledAxis[0].y = (1.0f / gfxModelDrawInst->placement.scale) * currModel->invScaledAxis[0].y;
currModel->invScaledAxis[0].z = (1.0f / gfxModelDrawInst->placement.scale) * currModel->invScaledAxis[0].z;
currModel->invScaledAxis[1].x = (1.0f / gfxModelDrawInst->placement.scale) * currModel->invScaledAxis[1].x;
currModel->invScaledAxis[1].y = (1.0f / gfxModelDrawInst->placement.scale) * currModel->invScaledAxis[1].y;
currModel->invScaledAxis[1].z = (1.0f / gfxModelDrawInst->placement.scale) * currModel->invScaledAxis[1].z;
currModel->invScaledAxis[2].x = (1.0f / gfxModelDrawInst->placement.scale) * currModel->invScaledAxis[2].x;
currModel->invScaledAxis[2].y = (1.0f / gfxModelDrawInst->placement.scale) * currModel->invScaledAxis[2].y;
currModel->invScaledAxis[2].z = (1.0f / gfxModelDrawInst->placement.scale) * currModel->invScaledAxis[2].z;
}
*/
}
// out_mins and out_maxs are initialised in the function
@@ -691,7 +714,7 @@ namespace BSP
loadDynEnts(clipMap);
loadXModelCollision(clipMap);
loadXModelCollision(clipMap, bsp);
loadMaterials(clipMap, bsp);
@@ -24,7 +24,7 @@ namespace BSP
void loadDynEnts(clipMap_t* clipMap);
void loadRopesAndConstraints(clipMap_t* clipMap);
void loadSubModelCollision(clipMap_t* clipMap, BSPData* bsp);
void loadXModelCollision(clipMap_t* clipMap);
bool loadXModelCollision(clipMap_t* clipMap, BSPData* bsp);
std::vector<cplane_s> planeVec;
std::vector<cNode_t> nodeVec;
@@ -145,59 +145,44 @@ namespace BSP
return true;
}
void GfxWorldLinker::loadXModels(BSPData* bsp, GfxWorld* gfxWorld)
bool GfxWorldLinker::loadXModels(BSPData* bsp, GfxWorld* gfxWorld)
{
/*
Models are unsupported right now
Code is left in in case it is supported later on
unsigned int modelCount = projInfo->modelCount;
size_t modelCount = bsp->gfxWorld.xmodels.size();
gfxWorld->dpvs.smodelCount = modelCount;
gfxWorld->dpvs.smodelInsts = new GfxStaticModelInst[modelCount];
gfxWorld->dpvs.smodelDrawInsts = new GfxStaticModelDrawInst[modelCount];
for (unsigned int i = 0; i < modelCount; i++)
for (size_t modelIdx = 0; modelIdx < modelCount; modelIdx++)
{
auto currModel = &gfxWorld->dpvs.smodelDrawInsts[i];
auto currModelInst = &gfxWorld->dpvs.smodelInsts[i];
customMapModel* inModel = &projInfo->models[i];
auto currModel = &gfxWorld->dpvs.smodelDrawInsts[modelIdx];
auto currModelInst = &gfxWorld->dpvs.smodelInsts[modelIdx];
BSPXModel& bspModel = bsp->gfxWorld.xmodels.at(modelIdx);
auto xModelAsset = m_context.LoadDependency<AssetXModel>(inModel->name);
auto xModelAsset = m_context.LoadDependency<AssetXModel>(bspModel.name);
if (xModelAsset == nullptr)
{
printf("XModel %s not found!\n", inModel->name.c_str());
currModel->model = nullptr;
con::error("Unable to load xmodel asset: \"{}\"", bspModel.name);
return false;
}
else
currModel->model = (XModel*)xModelAsset->Asset();
currModel->placement.origin.x = inModel->origin.x;
currModel->placement.origin.y = inModel->origin.y;
currModel->placement.origin.z = inModel->origin.z;
currModel->placement.origin = BSPUtil::convertToBO2Coords(currModel->placement.origin);
currModel->placement.scale = inModel->scale;
currModel->placement.origin.x = bspModel.origin.x;
currModel->placement.origin.y = bspModel.origin.y;
currModel->placement.origin.z = bspModel.origin.z;
BSPUtil::convertQuaternionToAxis(&bspModel.rotationQuaternion, currModel->placement.axis);
currModel->placement.scale = bspModel.scale;
BSPUtil::convertAnglesToAxis(&inModel->rotation, currModel->placement.axis);
// mins and maxs are calculated in world space not local space
// TODO: this does not account for model rotation or scale
currModelInst->mins.x = currModel->model->mins.x + currModel->placement.origin.x;
currModelInst->mins.y = currModel->model->mins.y + currModel->placement.origin.y;
currModelInst->mins.z = currModel->model->mins.z + currModel->placement.origin.z;
currModelInst->maxs.x = currModel->model->maxs.x + currModel->placement.origin.x;
currModelInst->maxs.y = currModel->model->maxs.y + currModel->placement.origin.y;
currModelInst->maxs.z = currModel->model->maxs.z + currModel->placement.origin.z;
currModel->cullDist = DEFAULT_SMODEL_CULL_DIST;
currModel->flags = DEFAULT_SMODEL_FLAGS;
currModel->primaryLightIndex = DEFAULT_SMODEL_LIGHT;
currModel->reflectionProbeIndex = DEFAULT_SMODEL_REFLECTION_PROBE;
currModel->cullDist = 10000.0f;
currModel->flags = 0;
currModel->primaryLightIndex = 0;
currModel->reflectionProbeIndex = 0;
currModel->smid = modelIdx;
// unknown use / unused
currModel->smid = i;
memset(&currModel->lightingSH, 0, sizeof(GfxLightingSHQuantized));
currModel->invScaleSq = 0.0f;
currModel->lightingHandle = 0;
currModel->lightingHandle = 0; // overwritten to by the game
currModel->colorsIndex = 0;
currModel->visibility = 0;
@@ -211,13 +196,39 @@ namespace BSP
currModel->lmapVertexInfo[2].lmapVertexColors = nullptr;
currModel->lmapVertexInfo[3].numLmapVertexColors = 0;
currModel->lmapVertexInfo[3].lmapVertexColors = nullptr;
}
*/
unsigned int modelCount = 0;
gfxWorld->dpvs.smodelCount = modelCount;
gfxWorld->dpvs.smodelInsts = m_memory.Alloc<GfxStaticModelInst>(modelCount);
gfxWorld->dpvs.smodelDrawInsts = m_memory.Alloc<GfxStaticModelDrawInst>(modelCount);
if (!xModelAsset->IsReference())
{
BSPUtil::calculateXmodelBounds(currModel->model, currModel->placement.axis, currModelInst->mins, currModelInst->maxs);
currModelInst->mins.x = (currModelInst->mins.x * bspModel.scale) + bspModel.origin.x;
currModelInst->mins.y = (currModelInst->mins.y * bspModel.scale) + bspModel.origin.y;
currModelInst->mins.z = (currModelInst->mins.z * bspModel.scale) + bspModel.origin.z;
currModelInst->maxs.x = (currModelInst->maxs.x * bspModel.scale) + bspModel.origin.x;
currModelInst->maxs.y = (currModelInst->maxs.y * bspModel.scale) + bspModel.origin.y;
currModelInst->maxs.z = (currModelInst->maxs.z * bspModel.scale) + bspModel.origin.z;
}
else
{
if (bspModel.areBoundsValid)
{
currModelInst->mins = bspModel.mins;
currModelInst->maxs = bspModel.maxs;
}
else
{
con::warn("Unable to determine the bounds of xmodel: \"{}\"", bspModel.name);
currModelInst->mins.x = bspModel.origin.x - 1.0f;
currModelInst->mins.y = bspModel.origin.y - 1.0f;
currModelInst->mins.z = bspModel.origin.z - 1.0f;
currModelInst->maxs.x = bspModel.origin.x + 1.0f;
currModelInst->maxs.y = bspModel.origin.y + 1.0f;
currModelInst->maxs.z = bspModel.origin.z + 1.0f;
}
}
currModelInst->lightingOrigin.x = 0.0f;
currModelInst->lightingOrigin.y = 0.0f;
currModelInst->lightingOrigin.z = 0.0f;
}
// visdata is written to by the game
// all visdata is alligned by 128
@@ -228,7 +239,7 @@ namespace BSP
gfxWorld->dpvs.smodelVisData[2] = m_memory.Alloc<char>(allignedModelCount);
gfxWorld->dpvs.smodelVisDataCameraSaved = m_memory.Alloc<char>(allignedModelCount);
gfxWorld->dpvs.smodelCastsShadow = m_memory.Alloc<char>(allignedModelCount);
for (unsigned int i = 0; i < modelCount; i++)
for (size_t i = 0; i < modelCount; i++)
{
if ((gfxWorld->dpvs.smodelDrawInsts[i].flags & STATIC_MODEL_FLAG_NO_SHADOW) == 0)
gfxWorld->dpvs.smodelCastsShadow[i] = 1;
@@ -236,8 +247,7 @@ namespace BSP
gfxWorld->dpvs.smodelCastsShadow[i] = 0;
}
// official maps set this to 0
gfxWorld->dpvs.usageCount = 0;
return true;
}
void GfxWorldLinker::cleanGfxWorld(GfxWorld* gfxWorld)
@@ -245,6 +255,9 @@ namespace BSP
// checksum is generated by the game
gfxWorld->checksum = 0;
// official maps set this to 0
gfxWorld->dpvs.usageCount = 0;
// Remove Coronas
gfxWorld->coronaCount = 0;
gfxWorld->coronas = nullptr;
@@ -735,7 +748,8 @@ namespace BSP
if (!loadMapSurfaces(bsp, gfxWorld))
return nullptr;
loadXModels(bsp, gfxWorld);
if (!loadXModels(bsp, gfxWorld))
return nullptr;
if (!loadLightmapData(gfxWorld))
return nullptr;
@@ -20,7 +20,7 @@ namespace BSP
void loadDrawData(BSPData* projInfo, GfxWorld* gfxWorld);
bool loadMapSurfaces(BSPData* projInfo, GfxWorld* gfxWorld);
void loadXModels(BSPData* projInfo, GfxWorld* gfxWorld);
bool loadXModels(BSPData* projInfo, GfxWorld* gfxWorld);
void cleanGfxWorld(GfxWorld* gfxWorld);
void loadGfxLights(BSPData* bsp, GfxWorld* gfxWorld);
void loadLightGrid(GfxWorld* gfxWorld);