mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-30 22:45:34 +00:00
Merge pull request #2049 from elsid/bullet_double_precision
Support bullet double precision
This commit is contained in:
commit
c69c7d0b3b
8 changed files with 144 additions and 33 deletions
|
@ -393,9 +393,9 @@ if [ -z $SKIP_DOWNLOAD ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Bullet
|
# Bullet
|
||||||
download "Bullet 2.86" \
|
download "Bullet 2.87" \
|
||||||
"https://www.lysator.liu.se/~ace/OpenMW/deps/Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}.7z" \
|
"https://www.lysator.liu.se/~ace/OpenMW/deps/Bullet-2.87-msvc${MSVC_YEAR}-win${BITS}.7z" \
|
||||||
"Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}.7z"
|
"Bullet-2.87-msvc${MSVC_YEAR}-win${BITS}.7z"
|
||||||
|
|
||||||
# FFmpeg
|
# FFmpeg
|
||||||
download "FFmpeg 3.2.4" \
|
download "FFmpeg 3.2.4" \
|
||||||
|
@ -533,15 +533,15 @@ fi
|
||||||
cd $DEPS
|
cd $DEPS
|
||||||
echo
|
echo
|
||||||
# Bullet
|
# Bullet
|
||||||
printf "Bullet 2.86... "
|
printf "Bullet 2.87... "
|
||||||
{
|
{
|
||||||
cd $DEPS_INSTALL
|
cd $DEPS_INSTALL
|
||||||
if [ -d Bullet ]; then
|
if [ -d Bullet ]; then
|
||||||
printf -- "Exists. (No version checking) "
|
printf -- "Exists. (No version checking) "
|
||||||
elif [ -z $SKIP_EXTRACT ]; then
|
elif [ -z $SKIP_EXTRACT ]; then
|
||||||
rm -rf Bullet
|
rm -rf Bullet
|
||||||
eval 7z x -y "${DEPS}/Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}.7z" $STRIP
|
eval 7z x -y "${DEPS}/Bullet-2.87-msvc${MSVC_YEAR}-win${BITS}.7z" $STRIP
|
||||||
mv "Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}" Bullet
|
mv "Bullet-2.87-msvc${MSVC_YEAR}-win${BITS}" Bullet
|
||||||
fi
|
fi
|
||||||
export BULLET_ROOT="$(real_pwd)/Bullet"
|
export BULLET_ROOT="$(real_pwd)/Bullet"
|
||||||
echo Done.
|
echo Done.
|
||||||
|
|
|
@ -7,12 +7,48 @@
|
||||||
|
|
||||||
#include <LinearMath/btTransform.h>
|
#include <LinearMath/btTransform.h>
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
template <class T>
|
||||||
|
auto makeHeights(const T* heights, float sqrtVerts)
|
||||||
|
-> std::enable_if_t<std::is_same<btScalar, T>::value, std::vector<btScalar>>
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
auto makeHeights(const T* heights, float sqrtVerts)
|
||||||
|
-> std::enable_if_t<!std::is_same<btScalar, T>::value, std::vector<btScalar>>
|
||||||
|
{
|
||||||
|
return std::vector<btScalar>(heights, heights + static_cast<std::ptrdiff_t>(sqrtVerts * sqrtVerts));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
auto getHeights(const T* floatHeights, const std::vector<btScalar>&)
|
||||||
|
-> std::enable_if_t<std::is_same<btScalar, T>::value, const btScalar*>
|
||||||
|
{
|
||||||
|
return floatHeights;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
auto getHeights(const T*, const std::vector<btScalar>& btScalarHeights)
|
||||||
|
-> std::enable_if_t<!std::is_same<btScalar, T>::value, const btScalar*>
|
||||||
|
{
|
||||||
|
return btScalarHeights.data();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWPhysics
|
namespace MWPhysics
|
||||||
{
|
{
|
||||||
HeightField::HeightField(const float* heights, int x, int y, float triSize, float sqrtVerts, float minH, float maxH, const osg::Object* holdObject)
|
HeightField::HeightField(const float* heights, int x, int y, float triSize, float sqrtVerts, float minH, float maxH, const osg::Object* holdObject)
|
||||||
|
: mHeights(makeHeights(heights, sqrtVerts))
|
||||||
{
|
{
|
||||||
mShape = new btHeightfieldTerrainShape(
|
mShape = new btHeightfieldTerrainShape(
|
||||||
sqrtVerts, sqrtVerts, heights, 1,
|
sqrtVerts, sqrtVerts,
|
||||||
|
getHeights(heights, mHeights),
|
||||||
|
1,
|
||||||
minH, maxH, 2,
|
minH, maxH, 2,
|
||||||
PHY_FLOAT, false
|
PHY_FLOAT, false
|
||||||
);
|
);
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
|
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
|
|
||||||
|
#include <LinearMath/btScalar.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class btCollisionObject;
|
class btCollisionObject;
|
||||||
class btHeightfieldTerrainShape;
|
class btHeightfieldTerrainShape;
|
||||||
|
|
||||||
|
@ -27,6 +31,7 @@ namespace MWPhysics
|
||||||
btHeightfieldTerrainShape* mShape;
|
btHeightfieldTerrainShape* mShape;
|
||||||
btCollisionObject* mCollisionObject;
|
btCollisionObject* mCollisionObject;
|
||||||
osg::ref_ptr<const osg::Object> mHoldObject;
|
osg::ref_ptr<const osg::Object> mHoldObject;
|
||||||
|
std::vector<btScalar> mHeights;
|
||||||
|
|
||||||
void operator=(const HeightField&);
|
void operator=(const HeightField&);
|
||||||
HeightField(const HeightField&);
|
HeightField(const HeightField&);
|
||||||
|
|
|
@ -20,22 +20,62 @@ namespace DetourNavigator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
template <class T>
|
||||||
|
struct Wrapper {
|
||||||
|
const T& mValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Range>
|
||||||
|
inline testing::Message& writeRange(testing::Message& message, const Range& range)
|
||||||
|
{
|
||||||
|
message << "{\n";
|
||||||
|
for (const auto& v : range)
|
||||||
|
message << Wrapper<typename std::decay<decltype(v)>::type> {v} << ",\n";
|
||||||
|
return message << "}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace testing
|
namespace testing
|
||||||
{
|
{
|
||||||
|
template <>
|
||||||
|
inline testing::Message& Message::operator <<(const osg::Vec3f& value)
|
||||||
|
{
|
||||||
|
return (*this) << "osg::Vec3f(" << std::setprecision(std::numeric_limits<float>::max_exponent10) << value.x()
|
||||||
|
<< ", " << std::setprecision(std::numeric_limits<float>::max_exponent10) << value.y()
|
||||||
|
<< ", " << std::setprecision(std::numeric_limits<float>::max_exponent10) << value.z()
|
||||||
|
<< ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline testing::Message& Message::operator <<(const Wrapper<osg::Vec3f>& value)
|
||||||
|
{
|
||||||
|
return (*this) << value.mValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline testing::Message& Message::operator <<(const Wrapper<float>& value)
|
||||||
|
{
|
||||||
|
return (*this) << std::setprecision(std::numeric_limits<float>::max_exponent10) << value.mValue;
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline testing::Message& Message::operator <<(const std::deque<osg::Vec3f>& value)
|
inline testing::Message& Message::operator <<(const std::deque<osg::Vec3f>& value)
|
||||||
{
|
{
|
||||||
(*this) << "{\n";
|
return writeRange(*this, value);
|
||||||
for (const auto& v : value)
|
|
||||||
{
|
|
||||||
std::ostringstream stream;
|
|
||||||
stream << "osg::Vec3f("
|
|
||||||
<< std::setprecision(std::numeric_limits<float>::max_exponent10) << v.x() << ", "
|
|
||||||
<< std::setprecision(std::numeric_limits<float>::max_exponent10) << v.y() << ", "
|
|
||||||
<< std::setprecision(std::numeric_limits<float>::max_exponent10) << v.z() << ")";
|
|
||||||
(*this) << stream.str() << ",\n";
|
|
||||||
}
|
}
|
||||||
return (*this) << "}";
|
|
||||||
|
template <>
|
||||||
|
inline testing::Message& Message::operator <<(const std::vector<osg::Vec3f>& value)
|
||||||
|
{
|
||||||
|
return writeRange(*this, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline testing::Message& Message::operator <<(const std::vector<float>& value)
|
||||||
|
{
|
||||||
|
return writeRange(*this, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -363,11 +363,11 @@ namespace
|
||||||
AreaType_ground
|
AreaType_ground
|
||||||
);
|
);
|
||||||
const auto recastMesh = builder.create(mGeneration, mRevision);
|
const auto recastMesh = builder.create(mGeneration, mRevision);
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_THAT(recastMesh->getVertices(), Pointwise(FloatNear(1e-5), std::vector<float>({
|
||||||
1.41421353816986083984375, 0, 1.1920928955078125e-07,
|
1.41421353816986083984375, 0, 1.1920928955078125e-07,
|
||||||
-1.41421353816986083984375, 0, -1.1920928955078125e-07,
|
-1.41421353816986083984375, 0, -1.1920928955078125e-07,
|
||||||
1.1920928955078125e-07, 0, -1.41421353816986083984375,
|
1.1920928955078125e-07, 0, -1.41421353816986083984375,
|
||||||
}));
|
})));
|
||||||
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
||||||
EXPECT_EQ(recastMesh->getAreaTypes(), std::vector<AreaType>({AreaType_ground}));
|
EXPECT_EQ(recastMesh->getAreaTypes(), std::vector<AreaType>({AreaType_ground}));
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <gmock/gmock.h>
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -30,6 +32,34 @@ namespace
|
||||||
shape.processAllTriangles(&callback, aabbMin, aabbMax);
|
shape.processAllTriangles(&callback, aabbMin, aabbMax);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isNear(btScalar lhs, btScalar rhs)
|
||||||
|
{
|
||||||
|
return std::abs(lhs - rhs) <= 1e-5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isNear(const btVector3& lhs, const btVector3& rhs)
|
||||||
|
{
|
||||||
|
return std::equal(
|
||||||
|
static_cast<const btScalar*>(lhs),
|
||||||
|
static_cast<const btScalar*>(lhs) + 3,
|
||||||
|
static_cast<const btScalar*>(rhs),
|
||||||
|
[] (btScalar lhs, btScalar rhs) { return isNear(lhs, rhs); }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isNear(const btMatrix3x3& lhs, const btMatrix3x3& rhs)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
if (!isNear(lhs[i], rhs[i]))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isNear(const btTransform& lhs, const btTransform& rhs)
|
||||||
|
{
|
||||||
|
return isNear(lhs.getOrigin(), rhs.getOrigin()) && isNear(lhs.getBasis(), rhs.getBasis());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::ostream& operator <<(std::ostream& stream, const btVector3& value)
|
static std::ostream& operator <<(std::ostream& stream, const btVector3& value)
|
||||||
|
@ -157,7 +187,7 @@ static bool operator ==(const btCompoundShape& lhs, const btCompoundShape& rhs)
|
||||||
for (int i = 0; i < lhs.getNumChildShapes(); ++i)
|
for (int i = 0; i < lhs.getNumChildShapes(); ++i)
|
||||||
{
|
{
|
||||||
if (!compareObjects(lhs.getChildShape(i), rhs.getChildShape(i))
|
if (!compareObjects(lhs.getChildShape(i), rhs.getChildShape(i))
|
||||||
|| !(lhs.getChildTransform(i) == rhs.getChildTransform(i)))
|
|| !isNear(lhs.getChildTransform(i), rhs.getChildTransform(i)))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -165,13 +195,13 @@ static bool operator ==(const btCompoundShape& lhs, const btCompoundShape& rhs)
|
||||||
|
|
||||||
static bool operator ==(const btBoxShape& lhs, const btBoxShape& rhs)
|
static bool operator ==(const btBoxShape& lhs, const btBoxShape& rhs)
|
||||||
{
|
{
|
||||||
return lhs.getLocalScaling() == rhs.getLocalScaling()
|
return isNear(lhs.getLocalScaling(), rhs.getLocalScaling())
|
||||||
&& lhs.getHalfExtentsWithoutMargin() == rhs.getHalfExtentsWithoutMargin();
|
&& lhs.getHalfExtentsWithoutMargin() == rhs.getHalfExtentsWithoutMargin();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool operator ==(const btBvhTriangleMeshShape& lhs, const btBvhTriangleMeshShape& rhs)
|
static bool operator ==(const btBvhTriangleMeshShape& lhs, const btBvhTriangleMeshShape& rhs)
|
||||||
{
|
{
|
||||||
return lhs.getLocalScaling() == rhs.getLocalScaling()
|
return isNear(lhs.getLocalScaling(), rhs.getLocalScaling())
|
||||||
&& lhs.usesQuantizedAabbCompression() == rhs.usesQuantizedAabbCompression()
|
&& lhs.usesQuantizedAabbCompression() == rhs.usesQuantizedAabbCompression()
|
||||||
&& lhs.getOwnsBvh() == rhs.getOwnsBvh()
|
&& lhs.getOwnsBvh() == rhs.getOwnsBvh()
|
||||||
&& getTriangles(lhs) == getTriangles(rhs);
|
&& getTriangles(lhs) == getTriangles(rhs);
|
||||||
|
|
|
@ -30,8 +30,8 @@ configuration:
|
||||||
clone_depth: 1
|
clone_depth: 1
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
- C:\projects\openmw\deps\Bullet-2.86-msvc2015-win32.7z
|
- C:\projects\openmw\deps\Bullet-2.87-msvc2015-win32.7z
|
||||||
- C:\projects\openmw\deps\Bullet-2.86-msvc2015-win64.7z
|
- C:\projects\openmw\deps\Bullet-2.87-msvc2015-win64.7z
|
||||||
- C:\projects\openmw\deps\MyGUI-3.2.2-msvc2015-win32.7z
|
- C:\projects\openmw\deps\MyGUI-3.2.2-msvc2015-win32.7z
|
||||||
- C:\projects\openmw\deps\MyGUI-3.2.2-msvc2015-win64.7z
|
- C:\projects\openmw\deps\MyGUI-3.2.2-msvc2015-win64.7z
|
||||||
- C:\projects\openmw\deps\OSG-3.4.1-scrawl-msvc2015-win32.7z
|
- C:\projects\openmw\deps\OSG-3.4.1-scrawl-msvc2015-win32.7z
|
||||||
|
|
|
@ -163,15 +163,15 @@ namespace DetourNavigator
|
||||||
|
|
||||||
transformBoundingBox(transform, aabbMin, aabbMax);
|
transformBoundingBox(transform, aabbMin, aabbMax);
|
||||||
|
|
||||||
aabbMin.setX(std::max(mBounds.mMin.x(), aabbMin.x()));
|
aabbMin.setX(std::max(static_cast<btScalar>(mBounds.mMin.x()), aabbMin.x()));
|
||||||
aabbMin.setX(std::min(mBounds.mMax.x(), aabbMin.x()));
|
aabbMin.setX(std::min(static_cast<btScalar>(mBounds.mMax.x()), aabbMin.x()));
|
||||||
aabbMin.setY(std::max(mBounds.mMin.y(), aabbMin.y()));
|
aabbMin.setY(std::max(static_cast<btScalar>(mBounds.mMin.y()), aabbMin.y()));
|
||||||
aabbMin.setY(std::min(mBounds.mMax.y(), aabbMin.y()));
|
aabbMin.setY(std::min(static_cast<btScalar>(mBounds.mMax.y()), aabbMin.y()));
|
||||||
|
|
||||||
aabbMax.setX(std::max(mBounds.mMin.x(), aabbMax.x()));
|
aabbMax.setX(std::max(static_cast<btScalar>(mBounds.mMin.x()), aabbMax.x()));
|
||||||
aabbMax.setX(std::min(mBounds.mMax.x(), aabbMax.x()));
|
aabbMax.setX(std::min(static_cast<btScalar>(mBounds.mMax.x()), aabbMax.x()));
|
||||||
aabbMax.setY(std::max(mBounds.mMin.y(), aabbMax.y()));
|
aabbMax.setY(std::max(static_cast<btScalar>(mBounds.mMin.y()), aabbMax.y()));
|
||||||
aabbMax.setY(std::min(mBounds.mMax.y(), aabbMax.y()));
|
aabbMax.setY(std::min(static_cast<btScalar>(mBounds.mMax.y()), aabbMax.y()));
|
||||||
|
|
||||||
transformBoundingBox(transform.inverse(), aabbMin, aabbMax);
|
transformBoundingBox(transform.inverse(), aabbMin, aabbMax);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue