Add unit tests for the TriangleVertexArray
This commit is contained in:
parent
37e2c79cf2
commit
4a37ba3994
|
@ -26,14 +26,27 @@
|
|||
// Libraries
|
||||
#include "mathematics_functions.h"
|
||||
#include "Vector3.h"
|
||||
#include "Vector2.h"
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
using namespace reactphysics3d;
|
||||
|
||||
/// Compute the barycentric coordinates u, v, w of a point p inside the triangle (a, b, c)
|
||||
/// This method uses the technique described in the book Real-Time collision detection by
|
||||
/// Christer Ericson.
|
||||
|
||||
// Function to test if two vectors are (almost) equal
|
||||
bool reactphysics3d::approxEqual(const Vector3& vec1, const Vector3& vec2, decimal epsilon) {
|
||||
return approxEqual(vec1.x, vec2.x, epsilon) && approxEqual(vec1.y, vec2.y, epsilon) &&
|
||||
approxEqual(vec1.z, vec2.z, epsilon);
|
||||
}
|
||||
|
||||
// Function to test if two vectors are (almost) equal
|
||||
bool reactphysics3d::approxEqual(const Vector2& vec1, const Vector2& vec2, decimal epsilon) {
|
||||
return approxEqual(vec1.x, vec2.x, epsilon) && approxEqual(vec1.y, vec2.y, epsilon);
|
||||
}
|
||||
|
||||
// Compute the barycentric coordinates u, v, w of a point p inside the triangle (a, b, c)
|
||||
// This method uses the technique described in the book Real-Time collision detection by
|
||||
// Christer Ericson.
|
||||
void reactphysics3d::computeBarycentricCoordinatesInTriangle(const Vector3& a, const Vector3& b, const Vector3& c,
|
||||
const Vector3& p, decimal& u, decimal& v, decimal& w) {
|
||||
const Vector3 v0 = b - a;
|
||||
|
@ -52,7 +65,7 @@ void reactphysics3d::computeBarycentricCoordinatesInTriangle(const Vector3& a, c
|
|||
u = decimal(1.0) - v - w;
|
||||
}
|
||||
|
||||
/// Clamp a vector such that it is no longer than a given maximum length
|
||||
// Clamp a vector such that it is no longer than a given maximum length
|
||||
Vector3 reactphysics3d::clamp(const Vector3& vector, decimal maxLength) {
|
||||
if (vector.lengthSquare() > maxLength * maxLength) {
|
||||
return vector.getUnit() * maxLength;
|
||||
|
@ -60,17 +73,17 @@ Vector3 reactphysics3d::clamp(const Vector3& vector, decimal maxLength) {
|
|||
return vector;
|
||||
}
|
||||
|
||||
/// Return true if two vectors are parallel
|
||||
// Return true if two vectors are parallel
|
||||
bool reactphysics3d::areParallelVectors(const Vector3& vector1, const Vector3& vector2) {
|
||||
return vector1.cross(vector2).lengthSquare() < decimal(0.00001);
|
||||
}
|
||||
|
||||
/// Return true if two vectors are orthogonal
|
||||
// Return true if two vectors are orthogonal
|
||||
bool reactphysics3d::areOrthogonalVectors(const Vector3& vector1, const Vector3& vector2) {
|
||||
return std::abs(vector1.dot(vector2)) < decimal(0.00001);
|
||||
}
|
||||
|
||||
/// Compute and return a point on segment from "segPointA" and "segPointB" that is closest to point "pointC"
|
||||
// Compute and return a point on segment from "segPointA" and "segPointB" that is closest to point "pointC"
|
||||
Vector3 reactphysics3d::computeClosestPointOnSegment(const Vector3& segPointA, const Vector3& segPointB, const Vector3& pointC) {
|
||||
|
||||
const Vector3 ab = segPointB - segPointA;
|
||||
|
@ -95,9 +108,9 @@ Vector3 reactphysics3d::computeClosestPointOnSegment(const Vector3& segPointA, c
|
|||
return segPointA + t * ab;
|
||||
}
|
||||
|
||||
/// Compute the closest points between two segments
|
||||
/// This method uses the technique described in the book Real-Time
|
||||
/// collision detection by Christer Ericson.
|
||||
// Compute the closest points between two segments
|
||||
// This method uses the technique described in the book Real-Time
|
||||
// collision detection by Christer Ericson.
|
||||
void reactphysics3d::computeClosestPointBetweenTwoSegments(const Vector3& seg1PointA, const Vector3& seg1PointB,
|
||||
const Vector3& seg2PointA, const Vector3& seg2PointB,
|
||||
Vector3& closestPointSeg1, Vector3& closestPointSeg2) {
|
||||
|
@ -175,7 +188,7 @@ void reactphysics3d::computeClosestPointBetweenTwoSegments(const Vector3& seg1Po
|
|||
closestPointSeg2 = seg2PointA + d2 * t;
|
||||
}
|
||||
|
||||
/// Compute the intersection between a plane and a segment
|
||||
// Compute the intersection between a plane and a segment
|
||||
// Let the plane define by the equation planeNormal.dot(X) = planeD with X a point on the plane and "planeNormal" the plane normal. This method
|
||||
// computes the intersection P between the plane and the segment (segA, segB). The method returns the value "t" such
|
||||
// that P = segA + t * (segB - segA). Note that it only returns a value in [0, 1] if there is an intersection. Otherwise,
|
||||
|
@ -282,8 +295,8 @@ std::vector<Vector3> reactphysics3d::clipSegmentWithPlanes(const Vector3& segA,
|
|||
return outputVertices;
|
||||
}
|
||||
|
||||
/// Clip a polygon against multiple planes and return the clipped polygon vertices
|
||||
/// This method implements the Sutherland–Hodgman clipping algorithm
|
||||
// Clip a polygon against multiple planes and return the clipped polygon vertices
|
||||
// This method implements the Sutherland–Hodgman clipping algorithm
|
||||
std::vector<Vector3> reactphysics3d::clipPolygonWithPlanes(const std::vector<Vector3>& polygonVertices, const std::vector<Vector3>& planesPoints,
|
||||
const std::vector<Vector3>& planesNormals) {
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
namespace reactphysics3d {
|
||||
|
||||
struct Vector3;
|
||||
struct Vector2;
|
||||
|
||||
// ---------- Mathematics functions ---------- //
|
||||
|
||||
|
@ -47,6 +48,12 @@ inline bool approxEqual(decimal a, decimal b, decimal epsilon = MACHINE_EPSILON)
|
|||
return (std::fabs(a - b) < epsilon);
|
||||
}
|
||||
|
||||
/// Function to test if two vectors are (almost) equal
|
||||
bool approxEqual(const Vector3& vec1, const Vector3& vec2, decimal epsilon = MACHINE_EPSILON);
|
||||
|
||||
/// Function to test if two vectors are (almost) equal
|
||||
bool approxEqual(const Vector2& vec1, const Vector2& vec2, decimal epsilon = MACHINE_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) {
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "tests/collision/TestAABB.h"
|
||||
#include "tests/collision/TestDynamicAABBTree.h"
|
||||
#include "tests/collision/TestHalfEdgeStructure.h"
|
||||
#include "tests/collision/TestTriangleVertexArray.h"
|
||||
|
||||
using namespace reactphysics3d;
|
||||
|
||||
|
@ -59,6 +60,7 @@ int main() {
|
|||
|
||||
testSuite.addTest(new TestAABB("AABB"));
|
||||
testSuite.addTest(new TestPointInside("IsPointInside"));
|
||||
testSuite.addTest(new TestTriangleVertexArray("TriangleVertexArray"));
|
||||
testSuite.addTest(new TestRaycast("Raycasting"));
|
||||
testSuite.addTest(new TestCollisionWorld("CollisionWorld"));
|
||||
testSuite.addTest(new TestDynamicAABBTree("DynamicAABBTree"));
|
||||
|
|
|
@ -277,9 +277,8 @@ class TestRaycast : public Test {
|
|||
TriangleVertexArray::VertexDataType::VERTEX_DOUBLE_TYPE;
|
||||
mConcaveMeshVertexArray =
|
||||
new TriangleVertexArray(8, &(mConcaveMeshVertices[0]), sizeof(Vector3),
|
||||
12, &(mConcaveMeshIndices[0]), sizeof(uint),
|
||||
vertexType,
|
||||
TriangleVertexArray::IndexDataType::INDEX_INTEGER_TYPE);
|
||||
12, &(mConcaveMeshIndices[0]), 3 * sizeof(uint),
|
||||
vertexType, TriangleVertexArray::IndexDataType::INDEX_INTEGER_TYPE);
|
||||
|
||||
|
||||
// Add the triangle vertex array of the subpart to the triangle mesh
|
||||
|
|
261
test/tests/collision/TestTriangleVertexArray.h
Normal file
261
test/tests/collision/TestTriangleVertexArray.h
Normal file
|
@ -0,0 +1,261 @@
|
|||
/********************************************************************************
|
||||
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
|
||||
* Copyright (c) 2010-2016 Daniel Chappuis *
|
||||
*********************************************************************************
|
||||
* *
|
||||
* This software is provided 'as-is', without any express or implied warranty. *
|
||||
* In no event will the authors be held liable for any damages arising from the *
|
||||
* use of this software. *
|
||||
* *
|
||||
* Permission is granted to anyone to use this software for any purpose, *
|
||||
* including commercial applications, and to alter it and redistribute it *
|
||||
* freely, subject to the following restrictions: *
|
||||
* *
|
||||
* 1. The origin of this software must not be misrepresented; you must not claim *
|
||||
* that you wrote the original software. If you use this software in a *
|
||||
* product, an acknowledgment in the product documentation would be *
|
||||
* appreciated but is not required. *
|
||||
* *
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be *
|
||||
* misrepresented as being the original software. *
|
||||
* *
|
||||
* 3. This notice may not be removed or altered from any source distribution. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef TEST_TRIANGLE_VERTEX_ARRAY_H
|
||||
#define TEST_TRIANGLE_VERTEX_ARRAY_H
|
||||
|
||||
// Libraries
|
||||
#include "reactphysics3d.h"
|
||||
|
||||
/// Reactphysics3D namespace
|
||||
namespace reactphysics3d {
|
||||
|
||||
|
||||
// Class TestTriangleVertexArray
|
||||
/**
|
||||
* Unit test for the TestTriangleArray class.
|
||||
*/
|
||||
class TestTriangleVertexArray : public Test {
|
||||
|
||||
private :
|
||||
|
||||
// ---------- Atributes ---------- //
|
||||
|
||||
float mVertices1[4*3];
|
||||
double mVertices2[4*3];
|
||||
float mNormals2[4*3];
|
||||
uint mIndices1[6];
|
||||
short mIndices2[6];
|
||||
TriangleVertexArray* mTriangleVertexArray1;
|
||||
TriangleVertexArray* mTriangleVertexArray2;
|
||||
|
||||
Vector3 mVertex0;
|
||||
Vector3 mVertex1;
|
||||
Vector3 mVertex2;
|
||||
Vector3 mVertex3;
|
||||
Vector3 mVertex4;
|
||||
Vector3 mVertex5;
|
||||
Vector3 mVertex6;
|
||||
Vector3 mVertex7;
|
||||
|
||||
Vector3 mNormal0;
|
||||
Vector3 mNormal1;
|
||||
Vector3 mNormal2;
|
||||
Vector3 mNormal3;
|
||||
|
||||
public :
|
||||
|
||||
// ---------- Methods ---------- //
|
||||
|
||||
/// Constructor
|
||||
TestTriangleVertexArray(const std::string& name) : Test(name) {
|
||||
|
||||
mVertex0 = Vector3(0, 0, 4);
|
||||
mVertex1 = Vector3(0, 0, -3);
|
||||
mVertex2 = Vector3(-2, 0, 0);
|
||||
mVertex3 = Vector3(0, -5, 0);
|
||||
|
||||
// Initialize data
|
||||
mVertices1[0] = mVertex0.x; mVertices1[1] = mVertex0.y; mVertices1[2] = mVertex0.z;
|
||||
mVertices1[3] = mVertex1.x; mVertices1[4] = mVertex1.y; mVertices1[5] = mVertex1.z;
|
||||
mVertices1[6] = mVertex2.x; mVertices1[7] = mVertex2.y; mVertices1[8] = mVertex2.z;
|
||||
mVertices1[9] = mVertex3.x; mVertices1[10] = mVertex3.y; mVertices1[11] = mVertex3.z;
|
||||
|
||||
mIndices1[0] = 0; mIndices1[1] = 1; mIndices1[2] = 2;
|
||||
mIndices1[3] = 0; mIndices1[4] = 3; mIndices1[5] = 1;
|
||||
|
||||
mVertex4 = Vector3(0, 0, 5);
|
||||
mVertex5 = Vector3(0, 0, -7);
|
||||
mVertex6 = Vector3(-2, 0, 0);
|
||||
mVertex7 = Vector3(0, -5, 0);
|
||||
|
||||
mVertices2[0] = static_cast<double>(mVertex4.x); mVertices2[1] = static_cast<double>(mVertex4.y); mVertices2[2] = static_cast<double>(mVertex4.z);
|
||||
mVertices2[3] = static_cast<double>(mVertex5.x); mVertices2[4] = static_cast<double>(mVertex5.y); mVertices2[5] = static_cast<double>(mVertex5.z);
|
||||
mVertices2[6] = static_cast<double>(mVertex6.x); mVertices2[7] = static_cast<double>(mVertex6.y); mVertices2[8] = static_cast<double>(mVertex6.z);
|
||||
mVertices2[9] = static_cast<double>(mVertex7.x); mVertices2[10] = static_cast<double>(mVertex7.y); mVertices2[11] = static_cast<double>(mVertex7.z);
|
||||
|
||||
mIndices2[0] = 0; mIndices2[1] = 1; mIndices2[2] = 2;
|
||||
mIndices2[3] = 0; mIndices2[4] = 3; mIndices2[5] = 1;
|
||||
|
||||
mNormal0 = Vector3(2, 4, 6);
|
||||
mNormal1 = Vector3(1, 6, -3);
|
||||
mNormal2 = Vector3(-2, 4, 7);
|
||||
mNormal3 = Vector3(-5, 2, 9);
|
||||
mNormal0.normalize();
|
||||
mNormal1.normalize();
|
||||
mNormal2.normalize();
|
||||
mNormal3.normalize();
|
||||
mNormals2[0] = mNormal0.x; mNormals2[1] = mNormal0.y; mNormals2[2] = mNormal0.z;
|
||||
mNormals2[3] = mNormal1.x; mNormals2[4] = mNormal1.y; mNormals2[5] = mNormal1.z;
|
||||
mNormals2[6] = mNormal2.x; mNormals2[7] = mNormal2.y; mNormals2[8] = mNormal2.z;
|
||||
mNormals2[9] = mNormal3.x; mNormals2[10] = mNormal3.y; mNormals2[11] = mNormal3.z;
|
||||
|
||||
// Create triangle vertex array with automatic normals computation
|
||||
mTriangleVertexArray1 = new TriangleVertexArray(4, static_cast<const void*>(mVertices1), 3 * sizeof(float),
|
||||
2, static_cast<const void*>(mIndices1), 3 * sizeof(uint),
|
||||
TriangleVertexArray::VertexDataType::VERTEX_FLOAT_TYPE,
|
||||
TriangleVertexArray::IndexDataType::INDEX_INTEGER_TYPE);
|
||||
|
||||
// Create triangle vertex array with normals defined by the user
|
||||
mTriangleVertexArray2 = new TriangleVertexArray(4, static_cast<const void*>(mVertices2), 3 * sizeof(double),
|
||||
static_cast<const void*>(mNormals2), 3 * sizeof(float),
|
||||
2, static_cast<const void*>(mIndices2), 3 * sizeof(short),
|
||||
TriangleVertexArray::VertexDataType::VERTEX_DOUBLE_TYPE,
|
||||
TriangleVertexArray::NormalDataType::NORMAL_FLOAT_TYPE,
|
||||
TriangleVertexArray::IndexDataType::INDEX_SHORT_TYPE);
|
||||
|
||||
}
|
||||
|
||||
/// Destructor
|
||||
virtual ~TestTriangleVertexArray() {
|
||||
delete mTriangleVertexArray1;
|
||||
delete mTriangleVertexArray2;
|
||||
}
|
||||
|
||||
/// Run the tests
|
||||
void run() {
|
||||
|
||||
// ----- First triangle vertex array ----- //
|
||||
|
||||
test(mTriangleVertexArray1->getVertexDataType() == TriangleVertexArray::VertexDataType::VERTEX_FLOAT_TYPE);
|
||||
test(mTriangleVertexArray1->getIndexDataType() == TriangleVertexArray::IndexDataType::INDEX_INTEGER_TYPE);
|
||||
test(mTriangleVertexArray1->getVertexNormalDataType() == TriangleVertexArray::NormalDataType::NORMAL_FLOAT_TYPE);
|
||||
test(mTriangleVertexArray1->getNbTriangles() == 2);
|
||||
test(mTriangleVertexArray1->getNbVertices() == 4);
|
||||
test(mTriangleVertexArray1->getIndicesStart() == static_cast<const void*>(mIndices1));
|
||||
test(mTriangleVertexArray1->getVerticesStart() == static_cast<const void*>(mVertices1));
|
||||
test(mTriangleVertexArray1->getIndicesStride() == (3 * sizeof(uint)));
|
||||
test(mTriangleVertexArray1->getVerticesStride() == (3 * sizeof(float)));
|
||||
|
||||
// Get triangle indices
|
||||
|
||||
uint triangle0Indices[3];
|
||||
mTriangleVertexArray1->getTriangleVerticesIndices(0, triangle0Indices);
|
||||
|
||||
test(triangle0Indices[0] == mIndices1[0]);
|
||||
test(triangle0Indices[1] == mIndices1[1]);
|
||||
test(triangle0Indices[2] == mIndices1[2]);
|
||||
|
||||
uint triangle1Indices[3];
|
||||
mTriangleVertexArray1->getTriangleVerticesIndices(1, triangle1Indices);
|
||||
|
||||
test(triangle1Indices[0] == mIndices1[3]);
|
||||
test(triangle1Indices[1] == mIndices1[4]);
|
||||
test(triangle1Indices[2] == mIndices1[5]);
|
||||
|
||||
// Get triangle vertices
|
||||
|
||||
Vector3 triangle0Vertices[3];
|
||||
mTriangleVertexArray1->getTriangleVertices(0, triangle0Vertices);
|
||||
|
||||
test(approxEqual(triangle0Vertices[0], mVertex0, decimal(0.0000001)));
|
||||
test(approxEqual(triangle0Vertices[1], mVertex1, decimal(0.0000001)));
|
||||
test(approxEqual(triangle0Vertices[2], mVertex2, decimal(0.0000001)));
|
||||
|
||||
Vector3 triangle1Vertices[3];
|
||||
mTriangleVertexArray1->getTriangleVertices(1, triangle1Vertices);
|
||||
|
||||
test(approxEqual(triangle1Vertices[0], mVertex0, decimal(0.0000001)));
|
||||
test(approxEqual(triangle1Vertices[1], mVertex3, decimal(0.0000001)));
|
||||
test(approxEqual(triangle1Vertices[2], mVertex1, decimal(0.0000001)));
|
||||
|
||||
// Get triangle normals
|
||||
|
||||
Vector3 triangle0Normals[3];
|
||||
mTriangleVertexArray1->getTriangleVerticesNormals(0, triangle0Normals);
|
||||
|
||||
Vector3 triangle1Normals[3];
|
||||
mTriangleVertexArray1->getTriangleVerticesNormals(1, triangle1Normals);
|
||||
|
||||
const Vector3 normal0Test(decimal(0.9792), decimal(0.20268), 0);
|
||||
const Vector3 normal2Test(0, 1, 0);
|
||||
const Vector3 normal3Test(1, 0, 0);
|
||||
|
||||
test(approxEqual(triangle0Normals[0], normal0Test, decimal(0.0001)));
|
||||
test(approxEqual(triangle0Normals[2], normal2Test, decimal(0.0001)));
|
||||
test(approxEqual(triangle1Normals[1], normal3Test, decimal(0.0001)));
|
||||
|
||||
// ----- Second triangle vertex array ----- //
|
||||
|
||||
test(mTriangleVertexArray2->getVertexDataType() == TriangleVertexArray::VertexDataType::VERTEX_DOUBLE_TYPE);
|
||||
test(mTriangleVertexArray2->getIndexDataType() == TriangleVertexArray::IndexDataType::INDEX_SHORT_TYPE);
|
||||
test(mTriangleVertexArray2->getVertexNormalDataType() == TriangleVertexArray::NormalDataType::NORMAL_FLOAT_TYPE);
|
||||
test(mTriangleVertexArray2->getNbTriangles() == 2);
|
||||
test(mTriangleVertexArray2->getNbVertices() == 4);
|
||||
test(mTriangleVertexArray2->getIndicesStart() == static_cast<const void*>(mIndices2));
|
||||
test(mTriangleVertexArray2->getVerticesStart() == static_cast<const void*>(mVertices2));
|
||||
test(mTriangleVertexArray2->getVerticesNormalsStart() == static_cast<const void*>(mNormals2));
|
||||
test(mTriangleVertexArray2->getIndicesStride() == (3 * sizeof(short)));
|
||||
test(mTriangleVertexArray2->getVerticesStride() == (3 * sizeof(double)));
|
||||
test(mTriangleVertexArray2->getVerticesNormalsStride() == (3 * sizeof(float)));
|
||||
|
||||
// Get triangle indices
|
||||
|
||||
mTriangleVertexArray2->getTriangleVerticesIndices(0, triangle0Indices);
|
||||
|
||||
test(triangle0Indices[0] == mIndices2[0]);
|
||||
test(triangle0Indices[1] == mIndices2[1]);
|
||||
test(triangle0Indices[2] == mIndices2[2]);
|
||||
|
||||
mTriangleVertexArray2->getTriangleVerticesIndices(1, triangle1Indices);
|
||||
|
||||
test(triangle1Indices[0] == mIndices2[3]);
|
||||
test(triangle1Indices[1] == mIndices2[4]);
|
||||
test(triangle1Indices[2] == mIndices2[5]);
|
||||
|
||||
// Get triangle vertices
|
||||
|
||||
mTriangleVertexArray2->getTriangleVertices(0, triangle0Vertices);
|
||||
|
||||
test(approxEqual(triangle0Vertices[0], mVertex4, decimal(0.0000001)));
|
||||
test(approxEqual(triangle0Vertices[1], mVertex5, decimal(0.0000001)));
|
||||
test(approxEqual(triangle0Vertices[2], mVertex6, decimal(0.0000001)));
|
||||
|
||||
mTriangleVertexArray2->getTriangleVertices(1, triangle1Vertices);
|
||||
|
||||
test(approxEqual(triangle1Vertices[0], mVertex4, decimal(0.0000001)));
|
||||
test(approxEqual(triangle1Vertices[1], mVertex7, decimal(0.0000001)));
|
||||
test(approxEqual(triangle1Vertices[2], mVertex5, decimal(0.0000001)));
|
||||
|
||||
// Get triangle normals
|
||||
|
||||
mTriangleVertexArray2->getTriangleVerticesNormals(0, triangle0Normals);
|
||||
mTriangleVertexArray2->getTriangleVerticesNormals(1, triangle1Normals);
|
||||
|
||||
test(approxEqual(triangle0Normals[0], mNormal0, decimal(0.000001)));
|
||||
test(approxEqual(triangle0Normals[1], mNormal1, decimal(0.000001)));
|
||||
test(approxEqual(triangle0Normals[2], mNormal2, decimal(0.000001)));
|
||||
|
||||
test(approxEqual(triangle1Normals[0], mNormal0, decimal(0.000001)));
|
||||
test(approxEqual(triangle1Normals[1], mNormal3, decimal(0.000001)));
|
||||
test(approxEqual(triangle1Normals[2], mNormal1, decimal(0.000001)));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user