Add OpenMW commits up to 6 May 2021
# Conflicts: # CMakeLists.txt # components/CMakeLists.txtpull/593/head
commit
ea6d5c68ae
@ -0,0 +1,26 @@
|
||||
set(TMP_ROOT ${CMAKE_BINARY_DIR}/try-compile)
|
||||
file(MAKE_DIRECTORY ${TMP_ROOT})
|
||||
|
||||
file(WRITE ${TMP_ROOT}/checkbullet.cpp
|
||||
"
|
||||
#include <BulletCollision/CollisionShapes/btSphereShape.h>
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
btSphereShape shape(1.0);
|
||||
btScalar mass(1.0);
|
||||
btVector3 inertia;
|
||||
shape.calculateLocalInertia(mass, inertia);
|
||||
return 0;
|
||||
}
|
||||
")
|
||||
|
||||
message(STATUS "Checking if Bullet uses double precision")
|
||||
|
||||
try_compile(RESULT_VAR
|
||||
${TMP_ROOT}/temp
|
||||
${TMP_ROOT}/checkbullet.cpp
|
||||
COMPILE_DEFINITIONS "-DBT_USE_DOUBLE_PRECISION"
|
||||
LINK_LIBRARIES ${BULLET_LIBRARIES}
|
||||
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${BULLET_INCLUDE_DIRS}"
|
||||
)
|
||||
set(HAS_DOUBLE_PRECISION_BULLET ${RESULT_VAR})
|
@ -1,67 +0,0 @@
|
||||
if (UNIX)
|
||||
|
||||
if (APPLE)
|
||||
|
||||
set(CMAKE_OS_NAME "OSX" CACHE STRING "Operating system name" FORCE)
|
||||
|
||||
else (APPLE)
|
||||
|
||||
## Check for Debian GNU/Linux ________________
|
||||
|
||||
find_file(DEBIAN_FOUND debian_version debconf.conf
|
||||
PATHS /etc
|
||||
)
|
||||
if (DEBIAN_FOUND)
|
||||
set(CMAKE_OS_NAME "Debian" CACHE STRING "Operating system name" FORCE)
|
||||
endif (DEBIAN_FOUND)
|
||||
|
||||
## Check for Fedora _________________________
|
||||
|
||||
find_file(FEDORA_FOUND fedora-release
|
||||
PATHS /etc
|
||||
)
|
||||
if (FEDORA_FOUND)
|
||||
set(CMAKE_OS_NAME "Fedora" CACHE STRING "Operating system name" FORCE)
|
||||
endif (FEDORA_FOUND)
|
||||
|
||||
## Check for RedHat _________________________
|
||||
|
||||
find_file(REDHAT_FOUND redhat-release inittab.RH
|
||||
PATHS /etc
|
||||
)
|
||||
if (REDHAT_FOUND)
|
||||
set(CMAKE_OS_NAME "RedHat" CACHE STRING "Operating system name" FORCE)
|
||||
endif (REDHAT_FOUND)
|
||||
|
||||
## Extra check for Ubuntu ____________________
|
||||
|
||||
if (DEBIAN_FOUND)
|
||||
|
||||
## At its core Ubuntu is a Debian system, with
|
||||
## a slightly altered configuration; hence from
|
||||
## a first superficial inspection a system will
|
||||
## be considered as Debian, which signifies an
|
||||
## extra check is required.
|
||||
|
||||
find_file(UBUNTU_EXTRA legal issue
|
||||
PATHS /etc
|
||||
)
|
||||
|
||||
if (UBUNTU_EXTRA)
|
||||
## Scan contents of file
|
||||
file(STRINGS ${UBUNTU_EXTRA} UBUNTU_FOUND
|
||||
REGEX Ubuntu
|
||||
)
|
||||
## Check result of string search
|
||||
if (UBUNTU_FOUND)
|
||||
set(CMAKE_OS_NAME "Ubuntu" CACHE STRING "Operating system name" FORCE)
|
||||
set(DEBIAN_FOUND FALSE)
|
||||
endif (UBUNTU_FOUND)
|
||||
|
||||
endif (UBUNTU_EXTRA)
|
||||
|
||||
endif (DEBIAN_FOUND)
|
||||
|
||||
endif (APPLE)
|
||||
|
||||
endif (UNIX)
|
@ -1,179 +0,0 @@
|
||||
#include "chunkytrimesh.hpp"
|
||||
#include "exceptions.hpp"
|
||||
|
||||
#include <osg/Vec2f>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace DetourNavigator
|
||||
{
|
||||
namespace
|
||||
{
|
||||
struct BoundsItem
|
||||
{
|
||||
Rect mBounds;
|
||||
std::ptrdiff_t mOffset;
|
||||
unsigned char mAreaTypes;
|
||||
};
|
||||
|
||||
template <std::size_t axis>
|
||||
struct LessBoundsItem
|
||||
{
|
||||
bool operator ()(const BoundsItem& lhs, const BoundsItem& rhs) const
|
||||
{
|
||||
return lhs.mBounds.mMinBound[axis] < rhs.mBounds.mMinBound[axis];
|
||||
}
|
||||
};
|
||||
|
||||
void calcExtends(const std::vector<BoundsItem>& items, const std::size_t imin, const std::size_t imax,
|
||||
Rect& bounds)
|
||||
{
|
||||
bounds = items[imin].mBounds;
|
||||
|
||||
std::for_each(
|
||||
items.begin() + static_cast<std::ptrdiff_t>(imin) + 1,
|
||||
items.begin() + static_cast<std::ptrdiff_t>(imax),
|
||||
[&] (const BoundsItem& item)
|
||||
{
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
bounds.mMinBound[i] = std::min(bounds.mMinBound[i], item.mBounds.mMinBound[i]);
|
||||
bounds.mMaxBound[i] = std::max(bounds.mMaxBound[i], item.mBounds.mMaxBound[i]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void subdivide(std::vector<BoundsItem>& items, const std::size_t imin, const std::size_t imax,
|
||||
const std::size_t trisPerChunk, const std::vector<int>& inIndices, const std::vector<AreaType>& inAreaTypes,
|
||||
std::size_t& curNode, std::vector<ChunkyTriMeshNode>& nodes, std::size_t& curTri,
|
||||
std::vector<int>& outIndices, std::vector<AreaType>& outAreaTypes)
|
||||
{
|
||||
const auto inum = imax - imin;
|
||||
const auto icur = curNode;
|
||||
|
||||
if (curNode >= nodes.size())
|
||||
return;
|
||||
|
||||
ChunkyTriMeshNode& node = nodes[curNode++];
|
||||
|
||||
if (inum <= trisPerChunk)
|
||||
{
|
||||
// Leaf
|
||||
calcExtends(items, imin, imax, node.mBounds);
|
||||
|
||||
// Copy triangles.
|
||||
node.mOffset = static_cast<std::ptrdiff_t>(curTri);
|
||||
node.mSize = inum;
|
||||
|
||||
for (std::size_t i = imin; i < imax; ++i)
|
||||
{
|
||||
std::copy(
|
||||
inIndices.begin() + items[i].mOffset * 3,
|
||||
inIndices.begin() + items[i].mOffset * 3 + 3,
|
||||
outIndices.begin() + static_cast<std::ptrdiff_t>(curTri) * 3
|
||||
);
|
||||
outAreaTypes[curTri] = inAreaTypes[static_cast<std::size_t>(items[i].mOffset)];
|
||||
curTri++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Split
|
||||
calcExtends(items, imin, imax, node.mBounds);
|
||||
|
||||
if (node.mBounds.mMaxBound.x() - node.mBounds.mMinBound.x()
|
||||
>= node.mBounds.mMaxBound.y() - node.mBounds.mMinBound.y())
|
||||
{
|
||||
// Sort along x-axis
|
||||
std::sort(
|
||||
items.begin() + static_cast<std::ptrdiff_t>(imin),
|
||||
items.begin() + static_cast<std::ptrdiff_t>(imax),
|
||||
LessBoundsItem<0> {}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Sort along y-axis
|
||||
std::sort(
|
||||
items.begin() + static_cast<std::ptrdiff_t>(imin),
|
||||
items.begin() + static_cast<std::ptrdiff_t>(imax),
|
||||
LessBoundsItem<1> {}
|
||||
);
|
||||
}
|
||||
|
||||
const auto isplit = imin + inum / 2;
|
||||
|
||||
// Left
|
||||
subdivide(items, imin, isplit, trisPerChunk, inIndices, inAreaTypes, curNode, nodes, curTri, outIndices, outAreaTypes);
|
||||
// Right
|
||||
subdivide(items, isplit, imax, trisPerChunk, inIndices, inAreaTypes, curNode, nodes, curTri, outIndices, outAreaTypes);
|
||||
|
||||
const auto iescape = static_cast<std::ptrdiff_t>(curNode) - static_cast<std::ptrdiff_t>(icur);
|
||||
// Negative index means escape.
|
||||
node.mOffset = -iescape;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ChunkyTriMesh::ChunkyTriMesh(const std::vector<float>& verts, const std::vector<int>& indices,
|
||||
const std::vector<AreaType>& flags, const std::size_t trisPerChunk)
|
||||
: mMaxTrisPerChunk(0)
|
||||
{
|
||||
const auto trianglesCount = indices.size() / 3;
|
||||
|
||||
if (trianglesCount == 0)
|
||||
return;
|
||||
|
||||
const auto nchunks = (trianglesCount + trisPerChunk - 1) / trisPerChunk;
|
||||
|
||||
mNodes.resize(nchunks * 4);
|
||||
mIndices.resize(trianglesCount * 3);
|
||||
mAreaTypes.resize(trianglesCount);
|
||||
|
||||
// Build tree
|
||||
std::vector<BoundsItem> items(trianglesCount);
|
||||
|
||||
for (std::size_t i = 0; i < trianglesCount; i++)
|
||||
{
|
||||
auto& item = items[i];
|
||||
|
||||
item.mOffset = static_cast<std::ptrdiff_t>(i);
|
||||
item.mAreaTypes = flags[i];
|
||||
|
||||
// Calc triangle XZ bounds.
|
||||
const auto baseIndex = static_cast<std::size_t>(indices[i * 3]) * 3;
|
||||
|
||||
item.mBounds.mMinBound.x() = item.mBounds.mMaxBound.x() = verts[baseIndex + 0];
|
||||
item.mBounds.mMinBound.y() = item.mBounds.mMaxBound.y() = verts[baseIndex + 2];
|
||||
|
||||
for (std::size_t j = 1; j < 3; ++j)
|
||||
{
|
||||
const auto index = static_cast<std::size_t>(indices[i * 3 + j]) * 3;
|
||||
|
||||
item.mBounds.mMinBound.x() = std::min(item.mBounds.mMinBound.x(), verts[index + 0]);
|
||||
item.mBounds.mMinBound.y() = std::min(item.mBounds.mMinBound.y(), verts[index + 2]);
|
||||
|
||||
item.mBounds.mMaxBound.x() = std::max(item.mBounds.mMaxBound.x(), verts[index + 0]);
|
||||
item.mBounds.mMaxBound.y() = std::max(item.mBounds.mMaxBound.y(), verts[index + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t curTri = 0;
|
||||
std::size_t curNode = 0;
|
||||
subdivide(items, 0, trianglesCount, trisPerChunk, indices, flags, curNode, mNodes, curTri, mIndices, mAreaTypes);
|
||||
|
||||
items.clear();
|
||||
|
||||
mNodes.resize(curNode);
|
||||
|
||||
// Calc max tris per node.
|
||||
for (auto& node : mNodes)
|
||||
{
|
||||
const bool isLeaf = node.mOffset >= 0;
|
||||
if (!isLeaf)
|
||||
continue;
|
||||
if (node.mSize > mMaxTrisPerChunk)
|
||||
mMaxTrisPerChunk = node.mSize;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
#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(ChunkyTriMesh&&) = default;
|
||||
ChunkyTriMesh& operator=(ChunkyTriMesh&&) = default;
|
||||
|
||||
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
|
Loading…
Reference in New Issue