mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2026-06-06 08:42:35 +00:00
161 lines
4.7 KiB
C++
161 lines
4.7 KiB
C++
#include "BSPCalculation.h"
|
|
|
|
namespace BSP
|
|
{
|
|
constexpr int MAX_NODE_SIZE = 512; // maximum size a BSP node can be before it becomes a leaf
|
|
|
|
BSPObject::BSPObject(float xMin, float yMin, float zMin, float xMax, float yMax, float zMax, int objPartitionIndex)
|
|
{
|
|
min.x = xMin;
|
|
min.y = yMin;
|
|
min.z = zMin;
|
|
max.x = xMax;
|
|
max.y = yMax;
|
|
max.z = zMax;
|
|
partitionIndex = objPartitionIndex;
|
|
}
|
|
|
|
void BSPLeaf::addObject(std::shared_ptr<BSPObject> object)
|
|
{
|
|
objectList.emplace_back(std::move(object));
|
|
}
|
|
|
|
BSPObject* BSPLeaf::getObject(size_t index)
|
|
{
|
|
return objectList.at(index).get();
|
|
}
|
|
|
|
size_t BSPLeaf::getObjectCount()
|
|
{
|
|
return objectList.size();
|
|
}
|
|
|
|
BSPNode::BSPNode(std::unique_ptr<BSPTree> frontTree, std::unique_ptr<BSPTree> backTree, PlaneAxis nodeAxis, float nodeDistance)
|
|
{
|
|
front = std::move(frontTree);
|
|
back = std::move(backTree);
|
|
axis = nodeAxis;
|
|
distance = nodeDistance;
|
|
}
|
|
|
|
PlaneSide BSPNode::objectIsInFront(BSPObject* object)
|
|
{
|
|
float minCoord, maxCoord;
|
|
|
|
// Select the relevant coordinate based on the plane's axis
|
|
if (axis == AXIS_X)
|
|
{
|
|
minCoord = object->min.x;
|
|
maxCoord = object->max.x;
|
|
}
|
|
else if (axis == AXIS_Y)
|
|
{
|
|
minCoord = object->min.y;
|
|
maxCoord = object->max.y;
|
|
}
|
|
else // axis == AXIS_Z
|
|
{
|
|
minCoord = object->min.z;
|
|
maxCoord = object->max.z;
|
|
}
|
|
|
|
// Compare with the plane's distance
|
|
if (maxCoord < distance)
|
|
{
|
|
return SIDE_BACK; // Object is entirely on the negative side
|
|
}
|
|
else if (minCoord > distance)
|
|
{
|
|
return SIDE_FRONT; // Object is entirely on the positive side
|
|
}
|
|
else
|
|
{
|
|
return SIDE_INTERSECTS;
|
|
}
|
|
}
|
|
|
|
BSPTree::BSPTree(float xMin, float yMin, float zMin, float xMax, float yMax, float zMax, int treeLevel)
|
|
{
|
|
min.x = xMin;
|
|
min.y = yMin;
|
|
min.z = zMin;
|
|
max.x = xMax;
|
|
max.y = yMax;
|
|
max.z = zMax;
|
|
level = treeLevel;
|
|
splitTree();
|
|
}
|
|
|
|
void BSPTree::splitTree()
|
|
{
|
|
std::unique_ptr<BSPTree> front;
|
|
std::unique_ptr<BSPTree> back;
|
|
float halfLength;
|
|
|
|
if (max.x - min.x > MAX_NODE_SIZE)
|
|
{
|
|
// split along the x axis
|
|
halfLength = (min.x + max.x) * 0.5f;
|
|
front = std::make_unique<BSPTree>(halfLength, min.y, min.z, max.x, max.y, max.z, level + 1);
|
|
back = std::make_unique<BSPTree>(min.x, min.y, min.z, halfLength, max.y, max.z, level + 1);
|
|
|
|
isLeaf = false;
|
|
node = std::make_unique<BSPNode>(std::move(front), std::move(back), AXIS_X, halfLength);
|
|
leaf = nullptr;
|
|
}
|
|
else if (max.y - min.y > MAX_NODE_SIZE)
|
|
{
|
|
// split along the x axis
|
|
halfLength = (min.y + max.y) * 0.5f;
|
|
front = std::make_unique<BSPTree>(min.x, halfLength, min.z, max.x, max.y, max.z, level + 1);
|
|
back = std::make_unique<BSPTree>(min.x, min.y, min.z, max.x, halfLength, max.z, level + 1);
|
|
|
|
isLeaf = false;
|
|
node = std::make_unique<BSPNode>(std::move(front), std::move(back), AXIS_Y, halfLength);
|
|
leaf = nullptr;
|
|
}
|
|
else if (max.z - min.z > MAX_NODE_SIZE)
|
|
{
|
|
// split along the z axis
|
|
halfLength = (min.z + max.z) * 0.5f;
|
|
front = std::make_unique<BSPTree>(min.x, min.y, halfLength, max.x, max.y, max.z, level + 1);
|
|
back = std::make_unique<BSPTree>(min.x, min.y, min.z, max.x, max.y, halfLength, level + 1);
|
|
|
|
isLeaf = false;
|
|
node = std::make_unique<BSPNode>(std::move(front), std::move(back), AXIS_Z, halfLength);
|
|
leaf = nullptr;
|
|
}
|
|
else
|
|
{
|
|
isLeaf = true;
|
|
node = nullptr;
|
|
leaf = std::make_unique<BSPLeaf>();
|
|
}
|
|
}
|
|
|
|
void BSPTree::addObjectToTree(std::shared_ptr<BSPObject> object)
|
|
{
|
|
if (isLeaf)
|
|
{
|
|
leaf->addObject(std::move(object));
|
|
}
|
|
else
|
|
{
|
|
PlaneSide side = node->objectIsInFront(object.get());
|
|
if (side == SIDE_FRONT)
|
|
{
|
|
node->front->addObjectToTree(std::move(object));
|
|
}
|
|
else if (side == SIDE_BACK)
|
|
{
|
|
node->back->addObjectToTree(std::move(object));
|
|
}
|
|
else // intersects
|
|
{
|
|
node->front->addObjectToTree(object);
|
|
node->back->addObjectToTree(object);
|
|
}
|
|
}
|
|
}
|
|
} // namespace BSP
|