mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-11-24 13:42:06 +00:00
Fixed a crash related to AABB Tree children counts exceeding the maximum limit
This commit is contained in:
@@ -63,6 +63,8 @@ namespace BSP
|
|||||||
{
|
{
|
||||||
constexpr unsigned int MAX_COLLISION_VERTS = UINT16_MAX;
|
constexpr unsigned int MAX_COLLISION_VERTS = UINT16_MAX;
|
||||||
|
|
||||||
|
constexpr size_t MAX_AABB_TREE_CHILDREN = 128;
|
||||||
|
|
||||||
enum BSPDefaultLights
|
enum BSPDefaultLights
|
||||||
{
|
{
|
||||||
STATIC_LIGHT_INDEX = 0,
|
STATIC_LIGHT_INDEX = 0,
|
||||||
|
|||||||
@@ -209,81 +209,103 @@ namespace BSP
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
int ClipMapLinker::addAABBTreeFromLeaf(BSPTree* node, clipMap_t* clipMap)
|
void ClipMapLinker::addAABBTreeFromLeaf(clipMap_t* clipMap, BSPTree* tree, size_t* out_parentCount, size_t* out_parentStartIndex)
|
||||||
{
|
{
|
||||||
assert(node->isLeaf);
|
assert(tree->isLeaf);
|
||||||
|
|
||||||
size_t objectCount = node->leaf->getObjectCount();
|
size_t leafObjectCount = tree->leaf->getObjectCount();
|
||||||
size_t parentAABBIndex = AABBTreeVec.size();
|
assert(leafObjectCount > 0);
|
||||||
|
if (leafObjectCount > highestLeafObjectCount)
|
||||||
|
highestLeafObjectCount = leafObjectCount;
|
||||||
|
|
||||||
assert(objectCount > 0);
|
// BO2 has a maximum limit of 128 children per AABB tree (essentially),
|
||||||
|
// so this is fixed by adding multiple parent AABB trees that hold 128 children each
|
||||||
|
size_t result = leafObjectCount / BSPGameConstants::MAX_AABB_TREE_CHILDREN;
|
||||||
|
size_t remainder = leafObjectCount % BSPGameConstants::MAX_AABB_TREE_CHILDREN;
|
||||||
|
size_t parentCount = result;
|
||||||
|
if (remainder > 0)
|
||||||
|
parentCount++;
|
||||||
|
|
||||||
if (objectCount > highestLeafObjectCount)
|
size_t parentAABBArrayIndex = AABBTreeVec.size();
|
||||||
highestLeafObjectCount = objectCount;
|
AABBTreeVec.resize(AABBTreeVec.size() + parentCount);
|
||||||
|
size_t unaddedObjectCount = leafObjectCount;
|
||||||
// add the parent AABB node
|
size_t addedObjectCount = 0;
|
||||||
vec3_t parentMins;
|
for (size_t parentIdx = 0; parentIdx < parentCount; parentIdx++)
|
||||||
vec3_t parentMaxs;
|
|
||||||
for (size_t objectIdx = 0; objectIdx < objectCount; objectIdx++)
|
|
||||||
{
|
{
|
||||||
int partitionIndex = node->leaf->getObject(objectIdx)->partitionIndex;
|
size_t childObjectCount = BSPGameConstants::MAX_AABB_TREE_CHILDREN;
|
||||||
CollisionPartition* partition = &clipMap->partitions[partitionIndex];
|
if (unaddedObjectCount <= BSPGameConstants::MAX_AABB_TREE_CHILDREN)
|
||||||
for (int uindIdx = 0; uindIdx < partition->nuinds; uindIdx++)
|
childObjectCount = unaddedObjectCount;
|
||||||
{
|
else
|
||||||
uint16_t uind = clipMap->info.uinds[partition->fuind + uindIdx];
|
unaddedObjectCount -= BSPGameConstants::MAX_AABB_TREE_CHILDREN;
|
||||||
vec3_t vert = clipMap->verts[uind];
|
|
||||||
|
|
||||||
// initalise the parent AABB with the first vertex
|
// add the parent AABB
|
||||||
if (objectIdx == 0 && uindIdx == 0)
|
vec3_t parentMins;
|
||||||
|
vec3_t parentMaxs;
|
||||||
|
for (size_t objectIdx = 0; objectIdx < childObjectCount; objectIdx++)
|
||||||
|
{
|
||||||
|
int partitionIndex = tree->leaf->getObject(addedObjectCount + objectIdx)->partitionIndex;
|
||||||
|
CollisionPartition* partition = &clipMap->partitions[partitionIndex];
|
||||||
|
for (int uindIdx = 0; uindIdx < partition->nuinds; uindIdx++)
|
||||||
{
|
{
|
||||||
parentMins = vert;
|
uint16_t uind = clipMap->info.uinds[partition->fuind + uindIdx];
|
||||||
parentMaxs = vert;
|
vec3_t vert = clipMap->verts[uind];
|
||||||
|
|
||||||
|
// initalise the parent AABB with the first vertex
|
||||||
|
if (objectIdx == 0 && uindIdx == 0)
|
||||||
|
{
|
||||||
|
parentMins = vert;
|
||||||
|
parentMaxs = vert;
|
||||||
|
}
|
||||||
|
|
||||||
|
BSPUtil::updateAABBWithPoint(vert, parentMins, parentMaxs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size_t childObjectStartIndex = AABBTreeVec.size();
|
||||||
|
|
||||||
|
CollisionAabbTree parentAABB;
|
||||||
|
parentAABB.origin = BSPUtil::calcMiddleOfAABB(parentMins, parentMaxs);
|
||||||
|
parentAABB.halfSize = BSPUtil::calcHalfSizeOfAABB(parentMins, parentMaxs);
|
||||||
|
parentAABB.materialIndex = 0; // always use the first material
|
||||||
|
parentAABB.childCount = static_cast<uint16_t>(childObjectCount);
|
||||||
|
parentAABB.u.firstChildIndex = static_cast<int>(childObjectStartIndex);
|
||||||
|
AABBTreeVec.at(parentAABBArrayIndex + parentIdx) = parentAABB;
|
||||||
|
|
||||||
|
// add child AABBs
|
||||||
|
for (size_t objectIdx = 0; objectIdx < childObjectCount; objectIdx++)
|
||||||
|
{
|
||||||
|
int partitionIndex = tree->leaf->getObject(addedObjectCount + objectIdx)->partitionIndex;
|
||||||
|
CollisionPartition* partition = &clipMap->partitions[partitionIndex];
|
||||||
|
vec3_t childMins;
|
||||||
|
vec3_t childMaxs;
|
||||||
|
for (int uindIdx = 0; uindIdx < partition->nuinds; uindIdx++)
|
||||||
|
{
|
||||||
|
uint16_t uind = clipMap->info.uinds[partition->fuind + uindIdx];
|
||||||
|
vec3_t vert = clipMap->verts[uind];
|
||||||
|
|
||||||
|
// initalise the child AABB with the first vertex
|
||||||
|
if (uindIdx == 0)
|
||||||
|
{
|
||||||
|
childMins = vert;
|
||||||
|
childMaxs = vert;
|
||||||
|
}
|
||||||
|
|
||||||
|
BSPUtil::updateAABBWithPoint(vert, childMins, childMaxs);
|
||||||
}
|
}
|
||||||
|
|
||||||
BSPUtil::updateAABBWithPoint(vert, parentMins, parentMaxs);
|
CollisionAabbTree childAABBTree;
|
||||||
}
|
childAABBTree.materialIndex = 0; // always use the first material
|
||||||
}
|
childAABBTree.childCount = 0;
|
||||||
|
childAABBTree.u.partitionIndex = partitionIndex;
|
||||||
CollisionAabbTree parentAABB;
|
childAABBTree.origin = BSPUtil::calcMiddleOfAABB(childMins, childMaxs);
|
||||||
parentAABB.origin = BSPUtil::calcMiddleOfAABB(parentMins, parentMaxs);
|
childAABBTree.halfSize = BSPUtil::calcHalfSizeOfAABB(childMins, childMaxs);
|
||||||
parentAABB.halfSize = BSPUtil::calcHalfSizeOfAABB(parentMins, parentMaxs);
|
AABBTreeVec.emplace_back(childAABBTree);
|
||||||
parentAABB.materialIndex = 0; // always use the first material
|
|
||||||
parentAABB.childCount = static_cast<uint16_t>(objectCount);
|
|
||||||
parentAABB.u.firstChildIndex = static_cast<int>(parentAABBIndex + 1);
|
|
||||||
AABBTreeVec.emplace_back(parentAABB);
|
|
||||||
|
|
||||||
// add child AABB nodes
|
|
||||||
for (size_t objectIdx = 0; objectIdx < objectCount; objectIdx++)
|
|
||||||
{
|
|
||||||
int partitionIndex = node->leaf->getObject(objectIdx)->partitionIndex;
|
|
||||||
CollisionPartition* partition = &clipMap->partitions[partitionIndex];
|
|
||||||
vec3_t childMins;
|
|
||||||
vec3_t childMaxs;
|
|
||||||
for (int uindIdx = 0; uindIdx < partition->nuinds; uindIdx++)
|
|
||||||
{
|
|
||||||
uint16_t uind = clipMap->info.uinds[partition->fuind + uindIdx];
|
|
||||||
vec3_t vert = clipMap->verts[uind];
|
|
||||||
|
|
||||||
// initalise the child AABB with the first vertex
|
|
||||||
if (uindIdx == 0)
|
|
||||||
{
|
|
||||||
childMins = vert;
|
|
||||||
childMaxs = vert;
|
|
||||||
}
|
|
||||||
|
|
||||||
BSPUtil::updateAABBWithPoint(vert, childMins, childMaxs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CollisionAabbTree childAABBTree;
|
addedObjectCount += childObjectCount;
|
||||||
childAABBTree.materialIndex = 0; // always use the first material
|
|
||||||
childAABBTree.childCount = 0;
|
|
||||||
childAABBTree.u.partitionIndex = partitionIndex;
|
|
||||||
childAABBTree.origin = BSPUtil::calcMiddleOfAABB(childMins, childMaxs);
|
|
||||||
childAABBTree.halfSize = BSPUtil::calcHalfSizeOfAABB(childMins, childMaxs);
|
|
||||||
AABBTreeVec.emplace_back(childAABBTree);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return static_cast<int>(parentAABBIndex);
|
*out_parentCount = parentCount;
|
||||||
|
*out_parentStartIndex = parentAABBArrayIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr vec3_t normalX = {1.0f, 0.0f, 0.0f};
|
constexpr vec3_t normalX = {1.0f, 0.0f, 0.0f};
|
||||||
@@ -315,8 +337,11 @@ namespace BSP
|
|||||||
|
|
||||||
if (tree->leaf->getObjectCount() > 0)
|
if (tree->leaf->getObjectCount() > 0)
|
||||||
{
|
{
|
||||||
leaf.firstCollAabbIndex = addAABBTreeFromLeaf(tree, clipMap);
|
size_t parentCount = 0;
|
||||||
leaf.collAabbCount = 1; // 1 as it is the parent of all object AABBs
|
size_t parentStartIndex = 0;
|
||||||
|
addAABBTreeFromLeaf(clipMap, tree, &parentCount, &parentStartIndex);
|
||||||
|
leaf.collAabbCount = static_cast<uint16_t>(parentCount);
|
||||||
|
leaf.firstCollAabbIndex = static_cast<uint16_t>(parentStartIndex);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace BSP
|
|||||||
std::vector<cLeaf_s> leafVec;
|
std::vector<cLeaf_s> leafVec;
|
||||||
std::vector<CollisionAabbTree> AABBTreeVec;
|
std::vector<CollisionAabbTree> AABBTreeVec;
|
||||||
size_t highestLeafObjectCount = 0;
|
size_t highestLeafObjectCount = 0;
|
||||||
int addAABBTreeFromLeaf(BSPTree* node, clipMap_t* clipMap);
|
void addAABBTreeFromLeaf(clipMap_t* clipMap, BSPTree* tree, size_t* out_parentCount, size_t* out_parentStartIndex);
|
||||||
int16_t loadBSPNode(clipMap_t* clipMap, BSPTree* tree);
|
int16_t loadBSPNode(clipMap_t* clipMap, BSPTree* tree);
|
||||||
void loadBSPTree(clipMap_t* clipMap, BSPData* bsp);
|
void loadBSPTree(clipMap_t* clipMap, BSPData* bsp);
|
||||||
bool loadPartitions(clipMap_t* clipMap, BSPData* bsp);
|
bool loadPartitions(clipMap_t* clipMap, BSPData* bsp);
|
||||||
|
|||||||
Reference in New Issue
Block a user