Working on HeightFieldShape
This commit is contained in:
parent
538070ac4b
commit
03a31e44f3
|
@ -82,6 +82,9 @@ class AABB {
|
||||||
/// Set the maximum coordinates of the AABB
|
/// Set the maximum coordinates of the AABB
|
||||||
void setMax(const Vector3& max);
|
void setMax(const Vector3& max);
|
||||||
|
|
||||||
|
/// Return the size of the AABB in the three dimension x, y and z
|
||||||
|
Vector3 getExtent() const;
|
||||||
|
|
||||||
/// Inflate each side of the AABB by a given size
|
/// Inflate each side of the AABB by a given size
|
||||||
void inflate(decimal dx, decimal dy, decimal dz);
|
void inflate(decimal dx, decimal dy, decimal dz);
|
||||||
|
|
||||||
|
@ -142,6 +145,11 @@ inline void AABB::setMax(const Vector3& max) {
|
||||||
mMaxCoordinates = max;
|
mMaxCoordinates = max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the size of the AABB in the three dimension x, y and z
|
||||||
|
inline Vector3 AABB::getExtent() const {
|
||||||
|
return mMaxCoordinates - mMinCoordinates;
|
||||||
|
}
|
||||||
|
|
||||||
// Inflate each side of the AABB by a given size
|
// Inflate each side of the AABB by a given size
|
||||||
inline void AABB::inflate(decimal dx, decimal dy, decimal dz) {
|
inline void AABB::inflate(decimal dx, decimal dy, decimal dz) {
|
||||||
mMaxCoordinates += Vector3(dx, dy, dz);
|
mMaxCoordinates += Vector3(dx, dy, dz);
|
||||||
|
|
|
@ -30,15 +30,18 @@ using namespace reactphysics3d;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
// TODO : Add documentation to this constructor
|
// TODO : Add documentation to this constructor
|
||||||
HeightFieldShape::HeightFieldShape(int width, int length, int minHeight, int maxHeight,
|
HeightFieldShape::HeightFieldShape(int nbWidthGridPoints, int nbLengthGridPoints, decimal minHeight, decimal maxHeight,
|
||||||
const void* heightFieldData, HeightDataType dataType, int upAxis,
|
const void* heightFieldData, HeightDataType dataType, int upAxis,
|
||||||
decimal integerHeightScale)
|
decimal integerHeightScale)
|
||||||
: ConcaveShape(CONCAVE_MESH), mWidth(width), mLength(length), mMinHeight(minHeight),
|
: ConcaveShape(CONCAVE_MESH), mNbWidthGridPoints(nbWidthGridPoints), mNbLengthGridPoints(nbLengthGridPoints),
|
||||||
|
mWidth(nbWidthGridPoints - 1), mLength(nbWidthGridPoints - 1), mMinHeight(minHeight),
|
||||||
mMaxHeight(maxHeight), mUpAxis(upAxis), mIntegerHeightScale(integerHeightScale),
|
mMaxHeight(maxHeight), mUpAxis(upAxis), mIntegerHeightScale(integerHeightScale),
|
||||||
mHeightDataType(dataType) {
|
mHeightDataType(dataType) {
|
||||||
|
|
||||||
assert(width >= 1);
|
assert(nbWidthGridPoints >= 2);
|
||||||
assert(length >= 1);
|
assert(nbLengthGridPoints >= 2);
|
||||||
|
assert(mWidth >= 1);
|
||||||
|
assert(mLength >= 1);
|
||||||
assert(minHeight <= maxHeight);
|
assert(minHeight <= maxHeight);
|
||||||
assert(upAxis == 0 || upAxis == 1 || upAxis == 2);
|
assert(upAxis == 0 || upAxis == 1 || upAxis == 2);
|
||||||
|
|
||||||
|
@ -78,7 +81,10 @@ void HeightFieldShape::getLocalBounds(Vector3& min, Vector3& max) const {
|
||||||
max = mAABB.getMax() * mScaling;
|
max = mAABB.getMax() * mScaling;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use a callback method on all triangles of the concave shape inside a given AABB
|
// Test collision with the triangles of the height field shape. The idea is to use the AABB
|
||||||
|
// of the body when need to test and see against which triangles of the height-field we need
|
||||||
|
// to test for collision. We compute the sub-grid points that are inside the other body's AABB
|
||||||
|
// and then for each rectangle in the sub-grid we generate two triangles that we use to test collision.
|
||||||
void HeightFieldShape::testAllTriangles(TriangleCallback& callback, const AABB& localAABB) const {
|
void HeightFieldShape::testAllTriangles(TriangleCallback& callback, const AABB& localAABB) const {
|
||||||
|
|
||||||
// Compute the non-scaled AABB
|
// Compute the non-scaled AABB
|
||||||
|
@ -90,7 +96,56 @@ void HeightFieldShape::testAllTriangles(TriangleCallback& callback, const AABB&
|
||||||
int maxGridCoords[3];
|
int maxGridCoords[3];
|
||||||
computeMinMaxGridCoordinates(minGridCoords, maxGridCoords, localAABB);
|
computeMinMaxGridCoordinates(minGridCoords, maxGridCoords, localAABB);
|
||||||
|
|
||||||
|
// Compute the starting and ending coords of the sub-grid according to the up axis
|
||||||
|
int iMin, iMax, jMin, jMax;
|
||||||
|
switch(mUpAxis) {
|
||||||
|
case 0 : iMin = clamp(minGridCoords[1], 0, mNbWidthGridPoints - 1);
|
||||||
|
iMax = clamp(maxGridCoords[1], 0, mNbWidthGridPoints - 1);
|
||||||
|
jMin = clamp(minGridCoords[2], 0, mNbLengthGridPoints - 1);
|
||||||
|
jMax = clamp(maxGridCoords[2], 0, mNbLengthGridPoints - 1);
|
||||||
|
break;
|
||||||
|
case 1 : iMin = clamp(minGridCoords[0], 0, mNbWidthGridPoints - 1);
|
||||||
|
iMax = clamp(maxGridCoords[0], 0, mNbWidthGridPoints - 1);
|
||||||
|
jMin = clamp(minGridCoords[2], 0, mNbLengthGridPoints - 1);
|
||||||
|
jMax = clamp(maxGridCoords[2], 0, mNbLengthGridPoints - 1);
|
||||||
|
break;
|
||||||
|
case 2 : iMin = clamp(minGridCoords[0], 0, mNbWidthGridPoints - 1);
|
||||||
|
iMax = clamp(maxGridCoords[0], 0, mNbWidthGridPoints - 1);
|
||||||
|
jMin = clamp(minGridCoords[1], 0, mNbLengthGridPoints - 1);
|
||||||
|
jMax = clamp(maxGridCoords[1], 0, mNbLengthGridPoints - 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(iMin >= 0 && iMin < mNbWidthGridPoints);
|
||||||
|
assert(iMax >= 0 && iMax < mNbWidthGridPoints);
|
||||||
|
assert(jMin >= 0 && jMin < mNbLengthGridPoints);
|
||||||
|
assert(jMax >= 0 && jMax < mNbLengthGridPoints);
|
||||||
|
|
||||||
|
// For each sub-grid points (except the last ones one each dimension)
|
||||||
|
for (int i = iMin; i < iMax; i++) {
|
||||||
|
for (int j = jMin; j < jMax; j++) {
|
||||||
|
|
||||||
|
// Compute the four point of the current quad
|
||||||
|
Vector3 p1 = getVertexAt(i, j);
|
||||||
|
Vector3 p2 = getVertexAt(i, j + 1);
|
||||||
|
Vector3 p3 = getVertexAt(i + 1, j);
|
||||||
|
Vector3 p4 = getVertexAt(i + 1, j + 1);
|
||||||
|
|
||||||
|
// Generate the first triangle for the current grid rectangle
|
||||||
|
Vector3 trianglePoints[3] = {p1, p2, p3};
|
||||||
|
|
||||||
|
// Test collision against the first triangle
|
||||||
|
callback.testTriangle(trianglePoints);
|
||||||
|
|
||||||
|
// Generate the second triangle for the current grid rectangle
|
||||||
|
trianglePoints[0] = p3;
|
||||||
|
trianglePoints[1] = p2;
|
||||||
|
trianglePoints[2] = p4;
|
||||||
|
|
||||||
|
// Test collision against the second triangle
|
||||||
|
callback.testTriangle(trianglePoints);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the min/max grid coords corresponding to the intersection of the AABB of the height field and
|
// Compute the min/max grid coords corresponding to the intersection of the AABB of the height field and
|
||||||
|
@ -104,6 +159,13 @@ void HeightFieldShape::computeMinMaxGridCoordinates(int* minCoords, int* maxCoor
|
||||||
Vector3 maxPoint = Vector3::max(aabbToCollide.getMax(), mAABB.getMin());
|
Vector3 maxPoint = Vector3::max(aabbToCollide.getMax(), mAABB.getMin());
|
||||||
maxPoint = Vector3::min(maxPoint, mAABB.getMax());
|
maxPoint = Vector3::min(maxPoint, mAABB.getMax());
|
||||||
|
|
||||||
|
// Translate the min/max points such that the we compute grid points from [0 ... mNbWidthGridPoints]
|
||||||
|
// and from [0 ... mNbLengthGridPoints] because the AABB coordinates range are [-mWdith/2 ... mWidth/2]
|
||||||
|
// and [-mLength/2 ... mLength/2]
|
||||||
|
const Vector3 translateVec = mAABB.getExtent();
|
||||||
|
minPoint += translateVec;
|
||||||
|
maxPoint += translateVec;
|
||||||
|
|
||||||
// Convert the floating min/max coords of the AABB into closest integer
|
// Convert the floating min/max coords of the AABB into closest integer
|
||||||
// grid values (note that we use the closest grid coordinate that is out
|
// grid values (note that we use the closest grid coordinate that is out
|
||||||
// of the AABB)
|
// of the AABB)
|
||||||
|
|
|
@ -51,11 +51,17 @@ class HeightFieldShape : public ConcaveShape {
|
||||||
|
|
||||||
// -------------------- Attributes -------------------- //
|
// -------------------- Attributes -------------------- //
|
||||||
|
|
||||||
|
/// Number of grid points in the width dimension
|
||||||
|
int mNbWidthGridPoints;
|
||||||
|
|
||||||
|
/// Number of grid points in the length dimension
|
||||||
|
int mNbLengthGridPoints;
|
||||||
|
|
||||||
/// Height field width
|
/// Height field width
|
||||||
int mWidth;
|
decimal mWidth;
|
||||||
|
|
||||||
/// Height field length
|
/// Height field length
|
||||||
int mLength;
|
decimal mLength;
|
||||||
|
|
||||||
/// Minimum height of the height field
|
/// Minimum height of the height field
|
||||||
decimal mMinHeight;
|
decimal mMinHeight;
|
||||||
|
@ -115,7 +121,7 @@ class HeightFieldShape : public ConcaveShape {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
HeightFieldShape(int width, int length, int minHeight, int maxHeight,
|
HeightFieldShape(int nbWidthGridPoints, int nbLengthGridPoints, decimal minHeight, decimal maxHeight,
|
||||||
const void* heightFieldData, HeightDataType dataType,
|
const void* heightFieldData, HeightDataType dataType,
|
||||||
int upAxis = 1, decimal integerHeightScale = 1.0f);
|
int upAxis = 1, decimal integerHeightScale = 1.0f);
|
||||||
|
|
||||||
|
@ -163,16 +169,19 @@ inline Vector3 HeightFieldShape::getVertexAt(int x, int y) const {
|
||||||
case 0: return Vector3(height - originToZeroHeight, -mWidth * decimal(0.5) + x, -mLength * decimal(0.5) + y) * mScaling;
|
case 0: return Vector3(height - originToZeroHeight, -mWidth * decimal(0.5) + x, -mLength * decimal(0.5) + y) * mScaling;
|
||||||
case 1: return Vector3(-mWidth * decimal(0.5) + x, height - originToZeroHeight, -mLength * decimal(0.5) + y) * mScaling;
|
case 1: return Vector3(-mWidth * decimal(0.5) + x, height - originToZeroHeight, -mLength * decimal(0.5) + y) * mScaling;
|
||||||
case 2: return Vector3(-mWidth * decimal(0.5) + x, -mLength * decimal(0.5) + y, height - originToZeroHeight) * mScaling;
|
case 2: return Vector3(-mWidth * decimal(0.5) + x, -mLength * decimal(0.5) + y, height - originToZeroHeight) * mScaling;
|
||||||
|
default: assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the height of a given (x,y) point in the height field
|
// Return the height of a given (x,y) point in the height field
|
||||||
inline decimal HeightFieldShape::getHeightAt(int x, int y) const {
|
inline decimal HeightFieldShape::getHeightAt(int x, int y) const {
|
||||||
|
|
||||||
switch(mHeightDataType) {
|
switch(mHeightDataType) {
|
||||||
case HEIGHT_FLOAT_TYPE : return ((float*)mHeightFieldData)[y * mWidth + x];
|
case HEIGHT_FLOAT_TYPE : return ((float*)mHeightFieldData)[y * mNbWidthGridPoints + x];
|
||||||
case HEIGHT_DOUBLE_TYPE : return ((double*)mHeightFieldData)[y * mWidth + x];
|
case HEIGHT_DOUBLE_TYPE : return ((double*)mHeightFieldData)[y * mNbWidthGridPoints + x];
|
||||||
case HEIGHT_INT_TYPE : return ((int*)mHeightFieldData)[y * mWidth + x] * mIntegerHeightScale;
|
case HEIGHT_INT_TYPE : return ((int*)mHeightFieldData)[y * mNbWidthGridPoints + x] * mIntegerHeightScale;
|
||||||
|
default: assert(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,13 @@ inline bool approxEqual(decimal a, decimal b, decimal epsilon = MACHINE_EPSILON)
|
||||||
return (std::fabs(a - b) < epsilon);
|
return (std::fabs(a - b) < epsilon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Function that returns the result of the "value" clamped by
|
||||||
|
/// two others values "lowerLimit" and "upperLimit"
|
||||||
|
inline int clamp(int value, int lowerLimit, int upperLimit) {
|
||||||
|
assert(lowerLimit <= upperLimit);
|
||||||
|
return std::min(std::max(value, lowerLimit), upperLimit);
|
||||||
|
}
|
||||||
|
|
||||||
/// Function that returns the result of the "value" clamped by
|
/// Function that returns the result of the "value" clamped by
|
||||||
/// two others values "lowerLimit" and "upperLimit"
|
/// two others values "lowerLimit" and "upperLimit"
|
||||||
inline decimal clamp(decimal value, decimal lowerLimit, decimal upperLimit) {
|
inline decimal clamp(decimal value, decimal lowerLimit, decimal upperLimit) {
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
#include "collision/shapes/CapsuleShape.h"
|
#include "collision/shapes/CapsuleShape.h"
|
||||||
#include "collision/shapes/ConvexMeshShape.h"
|
#include "collision/shapes/ConvexMeshShape.h"
|
||||||
#include "collision/shapes/ConcaveMeshShape.h"
|
#include "collision/shapes/ConcaveMeshShape.h"
|
||||||
|
#include "collision/shapes/HeightFieldShape.h"
|
||||||
#include "collision/shapes/AABB.h"
|
#include "collision/shapes/AABB.h"
|
||||||
#include "collision/ProxyShape.h"
|
#include "collision/ProxyShape.h"
|
||||||
#include "collision/RaycastInfo.h"
|
#include "collision/RaycastInfo.h"
|
||||||
|
|
|
@ -124,6 +124,20 @@ class TestAABB : public Test {
|
||||||
test(approxEqual(aabbInflate.getMax().y, 8, 0.00001));
|
test(approxEqual(aabbInflate.getMax().y, 8, 0.00001));
|
||||||
test(approxEqual(aabbInflate.getMax().z, 35, 0.00001));
|
test(approxEqual(aabbInflate.getMax().z, 35, 0.00001));
|
||||||
|
|
||||||
|
// -------- Test getExtent() --------- //
|
||||||
|
|
||||||
|
test(approxEqual(mAABB1.getExtent().x, 20));
|
||||||
|
test(approxEqual(mAABB1.getExtent().y, 20));
|
||||||
|
test(approxEqual(mAABB1.getExtent().z, 20));
|
||||||
|
|
||||||
|
test(approxEqual(mAABB2.getExtent().x, 3));
|
||||||
|
test(approxEqual(mAABB2.getExtent().y, 16));
|
||||||
|
test(approxEqual(mAABB2.getExtent().z, 60));
|
||||||
|
|
||||||
|
test(approxEqual(mAABB3.getExtent().x, 25));
|
||||||
|
test(approxEqual(mAABB3.getExtent().y, 15));
|
||||||
|
test(approxEqual(mAABB3.getExtent().z, 28));
|
||||||
|
|
||||||
// -------- Test getCenter() -------- //
|
// -------- Test getCenter() -------- //
|
||||||
|
|
||||||
test(mAABB1.getCenter().x == 0);
|
test(mAABB1.getCenter().x == 0);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user