Fix issues, work on HalfEdgeStructure and add unit tests
This commit is contained in:
parent
7a656aedc9
commit
6a01abfae8
|
@ -463,7 +463,7 @@ void CollisionDetection::broadPhaseNotifyOverlappingPair(ProxyShape* shape1, Pro
|
|||
// Make sure the shape with the smallest collision shape type comes first
|
||||
const uint shape1TypeIndex = static_cast<const uint>(shape1->getCollisionShape()->getType());
|
||||
const uint shape2TypeIndex = static_cast<const uint>(shape2->getCollisionShape()->getType());
|
||||
if (shape2TypeIndex > shape1TypeIndex) {
|
||||
if (shape1TypeIndex > shape2TypeIndex) {
|
||||
|
||||
// Swap the two shapes
|
||||
ProxyShape* temp = shape1;
|
||||
|
|
|
@ -179,12 +179,6 @@ class CollisionDetection {
|
|||
/// Compute the collision detection
|
||||
void computeCollisionDetection();
|
||||
|
||||
// TODO : Remove this method
|
||||
/// Report collision between two sets of shapes
|
||||
//void reportCollisionBetweenShapes(CollisionCallback* callback,
|
||||
// const std::set<uint>& shapes1,
|
||||
// const std::set<uint>& shapes2) ;
|
||||
|
||||
/// Ray casting method
|
||||
void raycast(RaycastCallback* raycastCallback, const Ray& ray,
|
||||
unsigned short raycastWithCategoryMaskBits) const;
|
||||
|
@ -210,12 +204,6 @@ class CollisionDetection {
|
|||
/// Allow the broadphase to notify the collision detection about an overlapping pair.
|
||||
void broadPhaseNotifyOverlappingPair(ProxyShape* shape1, ProxyShape* shape2);
|
||||
|
||||
// TODO : Remove this method
|
||||
/// Compute the narrow-phase collision detection
|
||||
//void computeNarrowPhaseBetweenShapes(CollisionCallback* callback,
|
||||
// const std::set<uint>& shapes1,
|
||||
// const std::set<uint>& shapes2);
|
||||
|
||||
/// Return a pointer to the world
|
||||
CollisionWorld* getWorld();
|
||||
|
||||
|
|
|
@ -38,6 +38,8 @@ void HalfEdgeStructure::init(std::vector<Vector3> vertices, std::vector<std::vec
|
|||
std::map<edgeKey, edgeKey> nextEdges;
|
||||
std::map<edgeKey, uint> mapEdgeToStartVertex;
|
||||
std::map<edgeKey, uint> mapEdgeToIndex;
|
||||
std::map<uint, edgeKey> mapEdgeIndexToKey;
|
||||
std::map<uint, edgeKey> mapFaceIndexToEdgeKey;
|
||||
|
||||
// For each vertices
|
||||
for (uint v=0; v<vertices.size(); v++) {
|
||||
|
@ -86,24 +88,27 @@ void HalfEdgeStructure::init(std::vector<Vector3> vertices, std::vector<std::vec
|
|||
mapEdgeToStartVertex.insert(std::make_pair(pairV1V2, v1Index));
|
||||
mapEdgeToStartVertex.insert(std::make_pair(pairV2V1, v2Index));
|
||||
|
||||
mapFaceIndexToEdgeKey.insert(std::make_pair(f, pairV1V2));
|
||||
|
||||
auto itEdge = edges.find(pairV2V1);
|
||||
if (itEdge != edges.end()) {
|
||||
|
||||
const uint edgeIndex = mEdges.size();
|
||||
mEdges.push_back(itEdge->second);
|
||||
mEdges.push_back(edge);
|
||||
|
||||
itEdge->second.twinEdgeIndex = edgeIndex + 1;
|
||||
|
||||
edge.twinEdgeIndex = edgeIndex;
|
||||
|
||||
mVertices[v1Index].edgeIndex = edgeIndex;
|
||||
mVertices[v2Index].edgeIndex = edgeIndex + 1;
|
||||
mapEdgeIndexToKey[edgeIndex] = pairV2V1;
|
||||
mapEdgeIndexToKey[edgeIndex + 1] = pairV1V2;
|
||||
|
||||
mVertices[v1Index].edgeIndex = edgeIndex + 1;
|
||||
mVertices[v2Index].edgeIndex = edgeIndex;
|
||||
|
||||
mapEdgeToIndex.insert(std::make_pair(pairV1V2, edgeIndex + 1));
|
||||
mapEdgeToIndex.insert(std::make_pair(pairV2V1, edgeIndex));
|
||||
|
||||
face.edgeIndex = edgeIndex + 1;
|
||||
mEdges.push_back(itEdge->second);
|
||||
mEdges.push_back(edge);
|
||||
}
|
||||
|
||||
currentFaceEdges.push_back(pairV1V2);
|
||||
|
@ -111,8 +116,12 @@ void HalfEdgeStructure::init(std::vector<Vector3> vertices, std::vector<std::vec
|
|||
}
|
||||
|
||||
// Set next edges
|
||||
std::map<edgeKey, Edge>::iterator it;
|
||||
for (it = edges.begin(); it != edges.end(); ++it) {
|
||||
it->second.nextEdgeIndex = mapEdgeToIndex[nextEdges[it->first]];
|
||||
for (uint i=0; i < mEdges.size(); i++) {
|
||||
mEdges[i].nextEdgeIndex = mapEdgeToIndex[nextEdges[mapEdgeIndexToKey[i]]];
|
||||
}
|
||||
|
||||
// Set face edge
|
||||
for (uint f=0; f < faces.size(); f++) {
|
||||
mFaces[f].edgeIndex = mapEdgeToIndex[mapFaceIndexToEdgeKey[f]];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ class HalfEdgeStructure {
|
|||
public:
|
||||
|
||||
struct Edge {
|
||||
uint vertexIndex; // Index of the vertex at the end of the edge
|
||||
uint vertexIndex; // Index of the vertex at the beginning of the edge
|
||||
uint twinEdgeIndex; // Index of the twin edge
|
||||
uint faceIndex; // Adjacent face index of the edge
|
||||
uint nextEdgeIndex; // Index of the next edge
|
||||
|
@ -54,7 +54,7 @@ class HalfEdgeStructure {
|
|||
};
|
||||
|
||||
struct Vertex {
|
||||
Vector3 point; // Coordinates of the vertex
|
||||
Vector3 point; // Coordinates of the vertex
|
||||
uint edgeIndex; // Index of one edge emanting from this vertex
|
||||
|
||||
/// Constructor
|
||||
|
@ -86,8 +86,8 @@ class HalfEdgeStructure {
|
|||
/// Return the number of faces
|
||||
uint getNbFaces() const;
|
||||
|
||||
/// Return the number of edges
|
||||
uint getNbEdges() const;
|
||||
/// Return the number of half-edges
|
||||
uint getNbHalfEdges() const;
|
||||
|
||||
/// Return the number of vertices
|
||||
uint getNbVertices() const;
|
||||
|
@ -109,7 +109,7 @@ inline uint HalfEdgeStructure::getNbFaces() const {
|
|||
}
|
||||
|
||||
// Return the number of edges
|
||||
inline uint HalfEdgeStructure::getNbEdges() const {
|
||||
inline uint HalfEdgeStructure::getNbHalfEdges() const {
|
||||
return mEdges.size();
|
||||
}
|
||||
|
||||
|
|
|
@ -171,16 +171,16 @@ void reactphysics3d::computeClosestPointBetweenTwoSegments(const Vector3& seg1Po
|
|||
// there is no intersection between the plane and the segment.
|
||||
decimal reactphysics3d::computePlaneSegmentIntersection(const Vector3& segA, const Vector3& segB, const decimal planeD, const Vector3& planeNormal) {
|
||||
|
||||
const decimal parallelEpsilon = decimal(0.0001);
|
||||
const decimal parallelEpsilon = decimal(0.0001);
|
||||
decimal t = decimal(-1);
|
||||
|
||||
// Segment AB
|
||||
const Vector3 ab = segB - segA;
|
||||
|
||||
decimal nDotAB = planeNormal.dot(ab);
|
||||
decimal nDotAB = planeNormal.dot(ab);
|
||||
|
||||
// If the segment is not parallel to the plane
|
||||
if (nDotAB > parallelEpsilon) {
|
||||
if (std::abs(nDotAB) > parallelEpsilon) {
|
||||
t = (planeD - planeNormal.dot(segA)) / nDotAB;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "tests/collision/TestCollisionWorld.h"
|
||||
#include "tests/collision/TestAABB.h"
|
||||
#include "tests/collision/TestDynamicAABBTree.h"
|
||||
#include "tests/collision/TestHalfEdgeStructure.h"
|
||||
|
||||
using namespace reactphysics3d;
|
||||
|
||||
|
@ -61,6 +62,7 @@ int main() {
|
|||
testSuite.addTest(new TestRaycast("Raycasting"));
|
||||
testSuite.addTest(new TestCollisionWorld("CollisionWorld"));
|
||||
testSuite.addTest(new TestDynamicAABBTree("DynamicAABBTree"));
|
||||
testSuite.addTest(new TestHalfEdgeStructure("HalfEdgeStructure"));
|
||||
|
||||
// Run the tests
|
||||
testSuite.run();
|
||||
|
|
|
@ -72,7 +72,7 @@ class TestAABB : public Test {
|
|||
}
|
||||
|
||||
/// Destructor
|
||||
~TestAABB() {
|
||||
virtual ~TestAABB() {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -103,7 +103,6 @@ class TestCollisionWorld : public Test {
|
|||
CollisionBody* mBoxBody;
|
||||
CollisionBody* mSphere1Body;
|
||||
CollisionBody* mSphere2Body;
|
||||
CollisionBody* mCylinderBody;
|
||||
|
||||
// Collision shapes
|
||||
BoxShape* mBoxShape;
|
||||
|
@ -113,7 +112,6 @@ class TestCollisionWorld : public Test {
|
|||
ProxyShape* mBoxProxyShape;
|
||||
ProxyShape* mSphere1ProxyShape;
|
||||
ProxyShape* mSphere2ProxyShape;
|
||||
ProxyShape* mCylinderProxyShape;
|
||||
|
||||
// Collision callback class
|
||||
WorldCollisionCallback mCollisionCallback;
|
||||
|
@ -147,16 +145,14 @@ class TestCollisionWorld : public Test {
|
|||
mBoxProxyShape->setCollisionCategoryBits(CATEGORY_1);
|
||||
mSphere1ProxyShape->setCollisionCategoryBits(CATEGORY_1);
|
||||
mSphere2ProxyShape->setCollisionCategoryBits(CATEGORY_2);
|
||||
mCylinderProxyShape->setCollisionCategoryBits(CATEGORY_3);
|
||||
|
||||
mCollisionCallback.boxBody = mBoxBody;
|
||||
mCollisionCallback.sphere1Body = mSphere1Body;
|
||||
mCollisionCallback.sphere2Body = mSphere2Body;
|
||||
mCollisionCallback.cylinderBody = mCylinderBody;
|
||||
}
|
||||
|
||||
/// Destructor
|
||||
~TestCollisionWorld() {
|
||||
virtual ~TestCollisionWorld() {
|
||||
delete mBoxShape;
|
||||
delete mSphereShape;
|
||||
}
|
||||
|
@ -175,17 +171,12 @@ class TestCollisionWorld : public Test {
|
|||
test(!mCollisionCallback.sphere1CollideWithSphere2);
|
||||
|
||||
test(mWorld->testAABBOverlap(mBoxBody, mSphere1Body));
|
||||
test(mWorld->testAABBOverlap(mBoxBody, mCylinderBody));
|
||||
test(!mWorld->testAABBOverlap(mSphere1Body, mCylinderBody));
|
||||
test(!mWorld->testAABBOverlap(mSphere1Body, mSphere2Body));
|
||||
|
||||
test(mBoxProxyShape->testAABBOverlap(mSphere1ProxyShape->getWorldAABB()));
|
||||
test(mBoxProxyShape->testAABBOverlap(mCylinderProxyShape->getWorldAABB()));
|
||||
test(!mSphere1ProxyShape->testAABBOverlap(mCylinderProxyShape->getWorldAABB()));
|
||||
test(!mSphere1ProxyShape->testAABBOverlap(mSphere2ProxyShape->getWorldAABB()));
|
||||
|
||||
mCollisionCallback.reset();
|
||||
mWorld->testCollision(mCylinderBody, &mCollisionCallback);
|
||||
test(!mCollisionCallback.boxCollideWithSphere1);
|
||||
test(!mCollisionCallback.sphere1CollideWithSphere2);
|
||||
|
||||
|
@ -195,7 +186,6 @@ class TestCollisionWorld : public Test {
|
|||
test(!mCollisionCallback.sphere1CollideWithSphere2);
|
||||
|
||||
mCollisionCallback.reset();
|
||||
mWorld->testCollision(mBoxBody, mCylinderBody, &mCollisionCallback);
|
||||
test(!mCollisionCallback.boxCollideWithSphere1);
|
||||
test(!mCollisionCallback.sphere1CollideWithSphere2);
|
||||
|
||||
|
@ -213,7 +203,6 @@ class TestCollisionWorld : public Test {
|
|||
test(!mCollisionCallback.sphere1CollideWithSphere2);
|
||||
|
||||
mCollisionCallback.reset();
|
||||
mWorld->testCollision(mBoxBody, mCylinderBody, &mCollisionCallback);
|
||||
test(!mCollisionCallback.boxCollideWithSphere1);
|
||||
test(!mCollisionCallback.sphere1CollideWithSphere2);
|
||||
|
||||
|
@ -224,7 +213,6 @@ class TestCollisionWorld : public Test {
|
|||
|
||||
mCollisionCallback.reset();
|
||||
mBoxBody->setIsActive(false);
|
||||
mCylinderBody->setIsActive(false);
|
||||
mSphere1Body->setIsActive(false);
|
||||
mSphere2Body->setIsActive(false);
|
||||
mWorld->testCollision(&mCollisionCallback);
|
||||
|
@ -232,17 +220,12 @@ class TestCollisionWorld : public Test {
|
|||
test(!mCollisionCallback.sphere1CollideWithSphere2);
|
||||
|
||||
test(!mWorld->testAABBOverlap(mBoxBody, mSphere1Body));
|
||||
test(!mWorld->testAABBOverlap(mBoxBody, mCylinderBody));
|
||||
test(!mWorld->testAABBOverlap(mSphere1Body, mCylinderBody));
|
||||
test(!mWorld->testAABBOverlap(mSphere1Body, mSphere2Body));
|
||||
|
||||
test(!mBoxProxyShape->testAABBOverlap(mSphere1ProxyShape->getWorldAABB()));
|
||||
test(!mBoxProxyShape->testAABBOverlap(mCylinderProxyShape->getWorldAABB()));
|
||||
test(!mSphere1ProxyShape->testAABBOverlap(mCylinderProxyShape->getWorldAABB()));
|
||||
test(!mSphere1ProxyShape->testAABBOverlap(mSphere2ProxyShape->getWorldAABB()));
|
||||
|
||||
mBoxBody->setIsActive(true);
|
||||
mCylinderBody->setIsActive(true);
|
||||
mSphere1Body->setIsActive(true);
|
||||
mSphere2Body->setIsActive(true);
|
||||
|
||||
|
@ -251,7 +234,6 @@ class TestCollisionWorld : public Test {
|
|||
mBoxProxyShape->setCollideWithMaskBits(CATEGORY_1 | CATEGORY_3);
|
||||
mSphere1ProxyShape->setCollideWithMaskBits(CATEGORY_1 | CATEGORY_2);
|
||||
mSphere2ProxyShape->setCollideWithMaskBits(CATEGORY_1);
|
||||
mCylinderProxyShape->setCollideWithMaskBits(CATEGORY_1);
|
||||
|
||||
mCollisionCallback.reset();
|
||||
mWorld->testCollision(&mCollisionCallback);
|
||||
|
@ -269,7 +251,6 @@ class TestCollisionWorld : public Test {
|
|||
mBoxProxyShape->setCollideWithMaskBits(CATEGORY_2);
|
||||
mSphere1ProxyShape->setCollideWithMaskBits(CATEGORY_2);
|
||||
mSphere2ProxyShape->setCollideWithMaskBits(CATEGORY_3);
|
||||
mCylinderProxyShape->setCollideWithMaskBits(CATEGORY_1);
|
||||
|
||||
mCollisionCallback.reset();
|
||||
mWorld->testCollision(&mCollisionCallback);
|
||||
|
@ -282,7 +263,6 @@ class TestCollisionWorld : public Test {
|
|||
mBoxProxyShape->setCollideWithMaskBits(0xFFFF);
|
||||
mSphere1ProxyShape->setCollideWithMaskBits(0xFFFF);
|
||||
mSphere2ProxyShape->setCollideWithMaskBits(0xFFFF);
|
||||
mCylinderProxyShape->setCollideWithMaskBits(0xFFFF);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
245
test/tests/collision/TestHalfEdgeStructure.h
Normal file
245
test/tests/collision/TestHalfEdgeStructure.h
Normal file
|
@ -0,0 +1,245 @@
|
|||
#ifndef TEST_HALF_EDGE_STRUCTURE_H
|
||||
#define TEST_HALF_EDGE_STRUCTURE_H
|
||||
|
||||
// Libraries
|
||||
#include "reactphysics3d.h"
|
||||
#include "Test.h"
|
||||
|
||||
/// Reactphysics3D namespace
|
||||
namespace reactphysics3d {
|
||||
|
||||
|
||||
// Class TestHalfEdgeStructure
|
||||
/**
|
||||
* Unit test for the HalfEdgeStructure class.
|
||||
*/
|
||||
class TestHalfEdgeStructure : public Test {
|
||||
|
||||
private :
|
||||
|
||||
// ---------- Atributes ---------- //
|
||||
|
||||
|
||||
public :
|
||||
|
||||
// ---------- Methods ---------- //
|
||||
|
||||
/// Constructor
|
||||
TestHalfEdgeStructure(const std::string& name) : Test(name) {
|
||||
|
||||
}
|
||||
|
||||
/// Destructor
|
||||
virtual ~TestHalfEdgeStructure() {
|
||||
|
||||
}
|
||||
|
||||
/// Run the tests
|
||||
void run() {
|
||||
testCube();
|
||||
testTetrahedron();
|
||||
}
|
||||
|
||||
void testCube() {
|
||||
|
||||
// Create the half-edge structure for a cube
|
||||
std::vector<rp3d::Vector3> vertices;
|
||||
std::vector<std::vector<uint>> faces;
|
||||
rp3d::HalfEdgeStructure cubeStructure;
|
||||
|
||||
// Vertices
|
||||
vertices.push_back(rp3d::Vector3(-0.5, -0.5, 0.5));
|
||||
vertices.push_back(rp3d::Vector3(0.5, -0.5, 0.5));
|
||||
vertices.push_back(rp3d::Vector3(0.5, 0.5, 0.5));
|
||||
vertices.push_back(rp3d::Vector3(-0.5, 0.5, 0.5));
|
||||
vertices.push_back(rp3d::Vector3(-0.5, -0.5, -0.5));
|
||||
vertices.push_back(rp3d::Vector3(0.5, -0.5, -0.5));
|
||||
vertices.push_back(rp3d::Vector3(0.5, 0.5, -0.5));
|
||||
vertices.push_back(rp3d::Vector3(-0.5, 0.5, -0.5));
|
||||
|
||||
// Faces
|
||||
std::vector<uint> face0;
|
||||
face0.push_back(0); face0.push_back(1); face0.push_back(2); face0.push_back(3);
|
||||
std::vector<uint> face1;
|
||||
face1.push_back(1); face1.push_back(5); face1.push_back(6); face1.push_back(2);
|
||||
std::vector<uint> face2;
|
||||
face2.push_back(5); face2.push_back(4); face2.push_back(7); face2.push_back(6);
|
||||
std::vector<uint> face3;
|
||||
face3.push_back(4); face3.push_back(0); face3.push_back(3); face3.push_back(7);
|
||||
std::vector<uint> face4;
|
||||
face4.push_back(0); face4.push_back(4); face4.push_back(5); face4.push_back(1);
|
||||
std::vector<uint> face5;
|
||||
face5.push_back(2); face5.push_back(6); face5.push_back(7); face5.push_back(3);
|
||||
|
||||
faces.push_back(face0);
|
||||
faces.push_back(face1);
|
||||
faces.push_back(face2);
|
||||
faces.push_back(face3);
|
||||
faces.push_back(face4);
|
||||
faces.push_back(face5);
|
||||
|
||||
cubeStructure.init(vertices, faces);
|
||||
|
||||
// --- Test that the half-edge structure of the cube is valid --- //
|
||||
|
||||
test(cubeStructure.getNbFaces() == 6);
|
||||
test(cubeStructure.getNbVertices() == 8);
|
||||
test(cubeStructure.getNbHalfEdges() == 24);
|
||||
|
||||
// Test vertices
|
||||
test(cubeStructure.getVertex(0).point.x == -0.5);
|
||||
test(cubeStructure.getVertex(0).point.y == -0.5);
|
||||
test(cubeStructure.getVertex(0).point.z == 0.5);
|
||||
test(cubeStructure.getHalfEdge(cubeStructure.getVertex(0).edgeIndex).vertexIndex == 0);
|
||||
|
||||
test(cubeStructure.getVertex(1).point.x == 0.5);
|
||||
test(cubeStructure.getVertex(1).point.y == -0.5);
|
||||
test(cubeStructure.getVertex(1).point.z == 0.5);
|
||||
test(cubeStructure.getHalfEdge(cubeStructure.getVertex(1).edgeIndex).vertexIndex == 1);
|
||||
|
||||
test(cubeStructure.getVertex(2).point.x == 0.5);
|
||||
test(cubeStructure.getVertex(2).point.y == 0.5);
|
||||
test(cubeStructure.getVertex(2).point.z == 0.5);
|
||||
test(cubeStructure.getHalfEdge(cubeStructure.getVertex(2).edgeIndex).vertexIndex == 2);
|
||||
|
||||
test(cubeStructure.getVertex(3).point.x == -0.5);
|
||||
test(cubeStructure.getVertex(3).point.y == 0.5);
|
||||
test(cubeStructure.getVertex(3).point.z == 0.5);
|
||||
test(cubeStructure.getHalfEdge(cubeStructure.getVertex(3).edgeIndex).vertexIndex == 3);
|
||||
|
||||
test(cubeStructure.getVertex(4).point.x == -0.5);
|
||||
test(cubeStructure.getVertex(4).point.y == -0.5);
|
||||
test(cubeStructure.getVertex(4).point.z == -0.5);
|
||||
test(cubeStructure.getHalfEdge(cubeStructure.getVertex(4).edgeIndex).vertexIndex == 4);
|
||||
|
||||
test(cubeStructure.getVertex(5).point.x == 0.5);
|
||||
test(cubeStructure.getVertex(5).point.y == -0.5);
|
||||
test(cubeStructure.getVertex(5).point.z == -0.5);
|
||||
test(cubeStructure.getHalfEdge(cubeStructure.getVertex(5).edgeIndex).vertexIndex == 5);
|
||||
|
||||
test(cubeStructure.getVertex(6).point.x == 0.5);
|
||||
test(cubeStructure.getVertex(6).point.y == 0.5);
|
||||
test(cubeStructure.getVertex(6).point.z == -0.5);
|
||||
test(cubeStructure.getHalfEdge(cubeStructure.getVertex(6).edgeIndex).vertexIndex == 6);
|
||||
|
||||
test(cubeStructure.getVertex(7).point.x == -0.5);
|
||||
test(cubeStructure.getVertex(7).point.y == 0.5);
|
||||
test(cubeStructure.getVertex(7).point.z == -0.5);
|
||||
test(cubeStructure.getHalfEdge(cubeStructure.getVertex(7).edgeIndex).vertexIndex == 7);
|
||||
|
||||
// Test faces
|
||||
for (uint f=0; f<6; f++) {
|
||||
test(cubeStructure.getHalfEdge(cubeStructure.getFace(f).edgeIndex).faceIndex == f);
|
||||
}
|
||||
|
||||
// Test edges
|
||||
for (uint f=0; f<6; f++) {
|
||||
|
||||
|
||||
uint edgeIndex = cubeStructure.getFace(f).edgeIndex;
|
||||
const uint firstEdgeIndex = edgeIndex;
|
||||
|
||||
// For each half-edge of the face
|
||||
for (uint e=0; e<4; e++) {
|
||||
|
||||
rp3d::HalfEdgeStructure::Edge edge = cubeStructure.getHalfEdge(edgeIndex);
|
||||
|
||||
test(cubeStructure.getHalfEdge(edge.twinEdgeIndex).twinEdgeIndex == edgeIndex);
|
||||
test(edge.faceIndex == f);
|
||||
|
||||
// Go to the next edge
|
||||
edgeIndex = edge.nextEdgeIndex;
|
||||
}
|
||||
|
||||
test(firstEdgeIndex == edgeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void testTetrahedron() {
|
||||
|
||||
// Create the half-edge structure for a tetrahedron
|
||||
std::vector<rp3d::Vector3> vertices;
|
||||
std::vector<std::vector<uint>> faces;
|
||||
rp3d::HalfEdgeStructure tetrahedron;
|
||||
|
||||
// Vertices
|
||||
vertices.push_back(rp3d::Vector3(1, -1, -1));
|
||||
vertices.push_back(rp3d::Vector3(-1, -1, -1));
|
||||
vertices.push_back(rp3d::Vector3(0, -1, 1));
|
||||
vertices.push_back(rp3d::Vector3(0, 1, 0));
|
||||
|
||||
// Faces
|
||||
std::vector<uint> face0;
|
||||
face0.push_back(0); face0.push_back(1); face0.push_back(2);
|
||||
std::vector<uint> face1;
|
||||
face1.push_back(0); face1.push_back(3); face1.push_back(1);
|
||||
std::vector<uint> face2;
|
||||
face2.push_back(1); face2.push_back(3); face2.push_back(2);
|
||||
std::vector<uint> face3;
|
||||
face3.push_back(0); face3.push_back(2); face3.push_back(3);
|
||||
|
||||
faces.push_back(face0);
|
||||
faces.push_back(face1);
|
||||
faces.push_back(face2);
|
||||
faces.push_back(face3);
|
||||
|
||||
tetrahedron.init(vertices, faces);
|
||||
|
||||
// --- Test that the half-edge structure of the tetrahedron is valid --- //
|
||||
|
||||
test(tetrahedron.getNbFaces() == 4);
|
||||
test(tetrahedron.getNbVertices() == 4);
|
||||
test(tetrahedron.getNbHalfEdges() == 12);
|
||||
|
||||
// Test vertices
|
||||
test(tetrahedron.getVertex(0).point.x == 1);
|
||||
test(tetrahedron.getVertex(0).point.y == -1);
|
||||
test(tetrahedron.getVertex(0).point.z == -1);
|
||||
test(tetrahedron.getHalfEdge(tetrahedron.getVertex(0).edgeIndex).vertexIndex == 0);
|
||||
|
||||
test(tetrahedron.getVertex(1).point.x == -1);
|
||||
test(tetrahedron.getVertex(1).point.y == -1);
|
||||
test(tetrahedron.getVertex(1).point.z == -1);
|
||||
test(tetrahedron.getHalfEdge(tetrahedron.getVertex(1).edgeIndex).vertexIndex == 1);
|
||||
|
||||
test(tetrahedron.getVertex(2).point.x == 0);
|
||||
test(tetrahedron.getVertex(2).point.y == -1);
|
||||
test(tetrahedron.getVertex(2).point.z == 1);
|
||||
test(tetrahedron.getHalfEdge(tetrahedron.getVertex(2).edgeIndex).vertexIndex == 2);
|
||||
|
||||
test(tetrahedron.getVertex(3).point.x == 0);
|
||||
test(tetrahedron.getVertex(3).point.y == 1);
|
||||
test(tetrahedron.getVertex(3).point.z == 0);
|
||||
test(tetrahedron.getHalfEdge(tetrahedron.getVertex(3).edgeIndex).vertexIndex == 3);
|
||||
|
||||
// Test faces
|
||||
for (uint f=0; f<4; f++) {
|
||||
test(tetrahedron.getHalfEdge(tetrahedron.getFace(f).edgeIndex).faceIndex == f);
|
||||
}
|
||||
|
||||
// Test edges
|
||||
for (uint f=0; f<4; f++) {
|
||||
|
||||
uint edgeIndex = tetrahedron.getFace(f).edgeIndex;
|
||||
const uint firstEdgeIndex = edgeIndex;
|
||||
|
||||
// For each half-edge of the face
|
||||
for (uint e=0; e<3; e++) {
|
||||
|
||||
rp3d::HalfEdgeStructure::Edge edge = tetrahedron.getHalfEdge(edgeIndex);
|
||||
|
||||
test(tetrahedron.getHalfEdge(edge.twinEdgeIndex).twinEdgeIndex == edgeIndex);
|
||||
test(edge.faceIndex == f);
|
||||
|
||||
// Go to the next edge
|
||||
edgeIndex = edge.nextEdgeIndex;
|
||||
}
|
||||
|
||||
test(firstEdgeIndex == edgeIndex);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -171,7 +171,7 @@ class TestPointInside : public Test {
|
|||
}
|
||||
|
||||
/// Destructor
|
||||
~TestPointInside() {
|
||||
virtual ~TestPointInside() {
|
||||
delete mBoxShape;
|
||||
delete mSphereShape;
|
||||
delete mCapsuleShape;
|
||||
|
|
|
@ -109,7 +109,6 @@ class TestRaycast : public Test {
|
|||
CollisionBody* mBoxBody;
|
||||
CollisionBody* mSphereBody;
|
||||
CollisionBody* mCapsuleBody;
|
||||
CollisionBody* mConeBody;
|
||||
CollisionBody* mConvexMeshBody;
|
||||
CollisionBody* mConvexMeshBodyEdgesInfo;
|
||||
CollisionBody* mCylinderBody;
|
||||
|
@ -138,12 +137,10 @@ class TestRaycast : public Test {
|
|||
ProxyShape* mBoxProxyShape;
|
||||
ProxyShape* mSphereProxyShape;
|
||||
ProxyShape* mCapsuleProxyShape;
|
||||
ProxyShape* mConeProxyShape;
|
||||
ProxyShape* mConvexMeshProxyShape;
|
||||
ProxyShape* mConvexMeshProxyShapeEdgesInfo;
|
||||
ProxyShape* mCylinderProxyShape;
|
||||
ProxyShape* mCompoundSphereProxyShape;
|
||||
ProxyShape* mCompoundCylinderProxyShape;
|
||||
ProxyShape* mCompoundCapsuleProxyShape;
|
||||
ProxyShape* mTriangleProxyShape;
|
||||
ProxyShape* mConcaveMeshProxyShape;
|
||||
ProxyShape* mHeightFieldProxyShape;
|
||||
|
@ -177,7 +174,6 @@ class TestRaycast : public Test {
|
|||
mBoxBody = mWorld->createCollisionBody(mBodyTransform);
|
||||
mSphereBody = mWorld->createCollisionBody(mBodyTransform);
|
||||
mCapsuleBody = mWorld->createCollisionBody(mBodyTransform);
|
||||
mConeBody = mWorld->createCollisionBody(mBodyTransform);
|
||||
mConvexMeshBody = mWorld->createCollisionBody(mBodyTransform);
|
||||
mConvexMeshBodyEdgesInfo = mWorld->createCollisionBody(mBodyTransform);
|
||||
mCylinderBody = mWorld->createCollisionBody(mBodyTransform);
|
||||
|
@ -253,7 +249,7 @@ class TestRaycast : public Test {
|
|||
Quaternion orientationShape2(-3 *PI / 8, 1.5 * PI/ 3, PI / 13);
|
||||
Transform shapeTransform2(positionShape2, orientationShape2);
|
||||
mLocalShape2ToWorld = mBodyTransform * shapeTransform2;
|
||||
mCompoundCylinderProxyShape = mCompoundBody->addCollisionShape(mCapsuleShape, mShapeTransform);
|
||||
mCompoundCapsuleProxyShape = mCompoundBody->addCollisionShape(mCapsuleShape, mShapeTransform);
|
||||
mCompoundSphereProxyShape = mCompoundBody->addCollisionShape(mSphereShape, shapeTransform2);
|
||||
|
||||
// Concave Mesh shape
|
||||
|
@ -284,7 +280,7 @@ class TestRaycast : public Test {
|
|||
new TriangleVertexArray(8, &(mConcaveMeshVertices[0]), sizeof(Vector3),
|
||||
12, &(mConcaveMeshIndices[0]), sizeof(uint),
|
||||
vertexType,
|
||||
TriangleVertexArray::IndexDataType::INDEX_INTEGER_TYPE);
|
||||
TriangleVertexArray::IndexDataType::INDEX_INTEGER_TYPE);
|
||||
|
||||
|
||||
// Add the triangle vertex array of the subpart to the triangle mesh
|
||||
|
@ -302,19 +298,17 @@ class TestRaycast : public Test {
|
|||
mBoxProxyShape->setCollisionCategoryBits(CATEGORY1);
|
||||
mSphereProxyShape->setCollisionCategoryBits(CATEGORY1);
|
||||
mCapsuleProxyShape->setCollisionCategoryBits(CATEGORY1);
|
||||
mConeProxyShape->setCollisionCategoryBits(CATEGORY2);
|
||||
mConvexMeshProxyShape->setCollisionCategoryBits(CATEGORY2);
|
||||
mConvexMeshProxyShapeEdgesInfo->setCollisionCategoryBits(CATEGORY2);
|
||||
mCylinderProxyShape->setCollisionCategoryBits(CATEGORY2);
|
||||
mCompoundSphereProxyShape->setCollisionCategoryBits(CATEGORY2);
|
||||
mCompoundCylinderProxyShape->setCollisionCategoryBits(CATEGORY2);
|
||||
mCompoundCapsuleProxyShape->setCollisionCategoryBits(CATEGORY2);
|
||||
mTriangleProxyShape->setCollisionCategoryBits(CATEGORY1);
|
||||
mConcaveMeshProxyShape->setCollisionCategoryBits(CATEGORY2);
|
||||
mHeightFieldProxyShape->setCollisionCategoryBits(CATEGORY2);
|
||||
}
|
||||
|
||||
/// Destructor
|
||||
~TestRaycast() {
|
||||
virtual ~TestRaycast() {
|
||||
delete mBoxShape;
|
||||
delete mSphereShape;
|
||||
delete mCapsuleShape;
|
||||
|
@ -1647,7 +1641,7 @@ class TestRaycast : public Test {
|
|||
Ray ray15(mLocalShapeToWorld * Vector3(0, -9, 1), mLocalShapeToWorld * Vector3(0, 30, 1));
|
||||
Ray ray16(mLocalShapeToWorld * Vector3(-1, 2, -7), mLocalShapeToWorld * Vector3(-1, 2, 30));
|
||||
|
||||
mCallback.shapeToTest = mCompoundCylinderProxyShape;
|
||||
mCallback.shapeToTest = mCompoundCapsuleProxyShape;
|
||||
|
||||
test(mCompoundBody->raycast(ray11, raycastInfo));
|
||||
mCallback.reset();
|
||||
|
|
|
@ -150,19 +150,19 @@ class TestMathematicsFunctions : public Test {
|
|||
test(approxEqual(closestSeg2.z, 0.0, 0.000001));
|
||||
computeClosestPointBetweenTwoSegments(Vector3(1, -4, -5), Vector3(1, 4, -5), Vector3(-6, 5, -5), Vector3(6, 5, -5), closestSeg1, closestSeg2);
|
||||
test(approxEqual(closestSeg1.x, 1.0, 0.000001));
|
||||
test(approxEqual(closestSeg1.y, 5.0, 0.000001));
|
||||
test(approxEqual(closestSeg1.y, 4.0, 0.000001));
|
||||
test(approxEqual(closestSeg1.z, -5.0, 0.000001));
|
||||
test(approxEqual(closestSeg2.x, 1.0, 0.000001));
|
||||
test(approxEqual(closestSeg2.y, 5.0, 0.000001));
|
||||
test(approxEqual(closestSeg2.z, -5.0, 0.000001));
|
||||
|
||||
// Test computePlaneSegmentIntersection();
|
||||
test(approxEqual(computePlaneSegmentIntersection(Vector3(-6, 3, 0), Vector3(6, 3, 0), 0.0, Vector3(-1, 0, 0)), 0.5, 0.000001));
|
||||
test(approxEqual(computePlaneSegmentIntersection(Vector3(-6, 3, 0), Vector3(6, 3, 0), 0.0, Vector3(-1, 0, 0)), 0.5, 0.000001));
|
||||
test(approxEqual(computePlaneSegmentIntersection(Vector3(-6, 3, 0), Vector3(6, 3, 0), 0.0, Vector3(1, 0, 0)), 0.5, 0.000001));
|
||||
test(approxEqual(computePlaneSegmentIntersection(Vector3(5, 12, 0), Vector3(5, 4, 0), 6, Vector3(0, 1, 0)), 0.75, 0.000001));
|
||||
test(approxEqual(computePlaneSegmentIntersection(Vector3(5, 4, 8), Vector3(9, 14, 8), 4, Vector3(0, 1, 0)), 0.0, 0.000001));
|
||||
decimal tIntersect = computePlaneSegmentIntersection(Vector3(5, 4, 0), Vector3(9, 4, 0), 4, Vector3(0, 1, 0));
|
||||
test(tIntersect < 0.0 && tIntersect > 1.0);
|
||||
test(tIntersect < 0.0 || tIntersect > 1.0);
|
||||
|
||||
// Test computeDistancePointToLineDistance()
|
||||
test(approxEqual(computeDistancePointToLineDistance(Vector3(6, 0, 0), Vector3(14, 0, 0), Vector3(5, 3, 0)), 3.0, 0.000001));
|
||||
|
|
Loading…
Reference in New Issue
Block a user