You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
2.8 KiB
C++
100 lines
2.8 KiB
C++
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_CHUNKYTRIMESH_H
|
|
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_CHUNKYTRIMESH_H
|
|
|
|
#include "areatype.hpp"
|
|
|
|
#include <osg/Vec2f>
|
|
|
|
#include <array>
|
|
#include <vector>
|
|
|
|
namespace DetourNavigator
|
|
{
|
|
struct Rect
|
|
{
|
|
osg::Vec2f mMinBound;
|
|
osg::Vec2f mMaxBound;
|
|
};
|
|
|
|
struct ChunkyTriMeshNode
|
|
{
|
|
Rect mBounds;
|
|
std::ptrdiff_t mOffset;
|
|
std::size_t mSize;
|
|
};
|
|
|
|
struct Chunk
|
|
{
|
|
const int* const mIndices;
|
|
const AreaType* const mAreaTypes;
|
|
const std::size_t mSize;
|
|
};
|
|
|
|
inline bool checkOverlapRect(const Rect& lhs, const Rect& rhs)
|
|
{
|
|
bool overlap = true;
|
|
overlap = (lhs.mMinBound.x() > rhs.mMaxBound.x() || lhs.mMaxBound.x() < rhs.mMinBound.x()) ? false : overlap;
|
|
overlap = (lhs.mMinBound.y() > rhs.mMaxBound.y() || lhs.mMaxBound.y() < rhs.mMinBound.y()) ? false : overlap;
|
|
return overlap;
|
|
}
|
|
|
|
class ChunkyTriMesh
|
|
{
|
|
public:
|
|
/// Creates partitioned triangle mesh (AABB tree),
|
|
/// where each node contains at max trisPerChunk triangles.
|
|
ChunkyTriMesh(const std::vector<float>& verts, const std::vector<int>& tris,
|
|
const std::vector<AreaType>& flags, const std::size_t trisPerChunk);
|
|
|
|
ChunkyTriMesh(const ChunkyTriMesh&) = delete;
|
|
ChunkyTriMesh& operator=(const ChunkyTriMesh&) = delete;
|
|
|
|
/// Returns the chunk indices which overlap the input rectable.
|
|
template <class Function>
|
|
void forEachChunksOverlappingRect(const Rect& rect, Function&& function) const
|
|
{
|
|
// Traverse tree
|
|
for (std::size_t i = 0; i < mNodes.size(); )
|
|
{
|
|
const ChunkyTriMeshNode* node = &mNodes[i];
|
|
const bool overlap = checkOverlapRect(rect, node->mBounds);
|
|
const bool isLeafNode = node->mOffset >= 0;
|
|
|
|
if (isLeafNode && overlap)
|
|
function(i);
|
|
|
|
if (overlap || isLeafNode)
|
|
i++;
|
|
else
|
|
{
|
|
const auto escapeIndex = -node->mOffset;
|
|
i += static_cast<std::size_t>(escapeIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
Chunk getChunk(const std::size_t chunkId) const
|
|
{
|
|
const auto& node = mNodes[chunkId];
|
|
return Chunk {
|
|
mIndices.data() + node.mOffset * 3,
|
|
mAreaTypes.data() + node.mOffset,
|
|
node.mSize
|
|
};
|
|
}
|
|
|
|
std::size_t getMaxTrisPerChunk() const
|
|
{
|
|
return mMaxTrisPerChunk;
|
|
}
|
|
|
|
private:
|
|
std::vector<ChunkyTriMeshNode> mNodes;
|
|
std::vector<int> mIndices;
|
|
std::vector<AreaType> mAreaTypes;
|
|
std::size_t mMaxTrisPerChunk;
|
|
};
|
|
}
|
|
|
|
#endif
|