mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 04:44:11 +02:00
use shapeInFrustum() names again
but at the same time make the code more redable also: add some more efficient shape-touches-view methods and cleanup some whitespace
This commit is contained in:
parent
8200babf78
commit
dfdf375853
15 changed files with 150 additions and 610 deletions
|
@ -3423,9 +3423,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
|
|||
rootDetails.y * TREE_SCALE,
|
||||
rootDetails.z * TREE_SCALE) - glm::vec3(HALF_TREE_SCALE),
|
||||
rootDetails.s * TREE_SCALE);
|
||||
ViewFrustum::location serverFrustumLocation = _viewFrustum.computeCubeViewLocation(serverBounds);
|
||||
|
||||
if (serverFrustumLocation != ViewFrustum::OUTSIDE) {
|
||||
if ((bool)(_viewFrustum.cubeInFrustum(serverBounds))) {
|
||||
inViewServers++;
|
||||
}
|
||||
}
|
||||
|
@ -3491,12 +3489,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
|
|||
rootDetails.s * TREE_SCALE);
|
||||
|
||||
|
||||
ViewFrustum::location serverFrustumLocation = _viewFrustum.computeCubeViewLocation(serverBounds);
|
||||
if (serverFrustumLocation != ViewFrustum::OUTSIDE) {
|
||||
inView = true;
|
||||
} else {
|
||||
inView = false;
|
||||
}
|
||||
inView = (bool)(_viewFrustum.cubeInFrustum(serverBounds));
|
||||
} else {
|
||||
if (wantExtraDebugging) {
|
||||
qCDebug(interfaceapp) << "Jurisdiction without RootCode for node " << *node << ". That's unusual!";
|
||||
|
|
|
@ -188,8 +188,7 @@ void Avatar::simulate(float deltaTime) {
|
|||
|
||||
// simple frustum check
|
||||
float boundingRadius = getBoundingRadius();
|
||||
bool inViewFrustum = qApp->getViewFrustum()->computeSphereViewLocation(getPosition(), boundingRadius) !=
|
||||
ViewFrustum::OUTSIDE;
|
||||
bool inViewFrustum = (bool)(qApp->getViewFrustum()->sphereInFrustum(getPosition(), boundingRadius));
|
||||
|
||||
{
|
||||
PerformanceTimer perfTimer("hand");
|
||||
|
@ -401,7 +400,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
|||
frustum = qApp->getDisplayViewFrustum();
|
||||
}
|
||||
|
||||
if (frustum->computeSphereViewLocation(getPosition(), boundingRadius) == ViewFrustum::OUTSIDE) {
|
||||
if ((bool)(frustum->sphereInFrustum(getPosition(), boundingRadius))) {
|
||||
endRender();
|
||||
return;
|
||||
}
|
||||
|
@ -517,7 +516,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
|||
auto& frustum = *renderArgs->_viewFrustum;
|
||||
auto textPosition = getDisplayNamePosition();
|
||||
|
||||
if (frustum.computePointFrustumLocation(textPosition) == ViewFrustum::INSIDE) {
|
||||
if ((bool)frustum.pointInFrustum(textPosition)) {
|
||||
renderDisplayName(batch, frustum, textPosition);
|
||||
}
|
||||
}
|
||||
|
@ -671,7 +670,7 @@ glm::vec3 Avatar::getDisplayNamePosition() const {
|
|||
}
|
||||
|
||||
Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& frustum, const glm::vec3& textPosition) const {
|
||||
Q_ASSERT_X(frustum.computePointFrustumLocation(textPosition) == ViewFrustum::INSIDE,
|
||||
Q_ASSERT_X((bool)(frustum.pointInFrustum(textPosition)),
|
||||
"Avatar::calculateDisplayNameTransform", "Text not in viewfrustum.");
|
||||
glm::vec3 toFrustum = frustum.getPosition() - textPosition;
|
||||
|
||||
|
|
|
@ -304,15 +304,13 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
|
|||
// frustum culling on rendering.
|
||||
bool success;
|
||||
AACube entityCube = entity->getQueryAACube(success);
|
||||
if (!success || params.viewFrustum->computeCubeViewLocation(entityCube) == ViewFrustum::OUTSIDE) {
|
||||
if (!success || params.viewFrustum->cubeTouchesKeyhole(entityCube)) {
|
||||
includeThisEntity = false; // out of view, don't include it
|
||||
}
|
||||
|
||||
// Now check the size of the entity, it's possible that a "too small to see" entity is included in a
|
||||
// larger octree cell because of its position (for example if it crosses the boundary of a cell it
|
||||
// pops to the next higher cell. So we want to check to see that the entity is large enough to be seen
|
||||
// before we consider including it.
|
||||
if (includeThisEntity) {
|
||||
} else {
|
||||
// Check the size of the entity, it's possible that a "too small to see" entity is included in a
|
||||
// larger octree cell because of its position (for example if it crosses the boundary of a cell it
|
||||
// pops to the next higher cell. So we want to check to see that the entity is large enough to be seen
|
||||
// before we consider including it.
|
||||
success = true;
|
||||
// we can't cull a parent-entity by its dimensions because the child may be larger. we need to
|
||||
// avoid sending details about a child but not the parent. the parent's queryAACube should have
|
||||
|
|
|
@ -459,7 +459,7 @@ float OctreeElement::getEnclosingRadius() const {
|
|||
}
|
||||
|
||||
ViewFrustum::location OctreeElement::computeViewLocation(const ViewFrustum& viewFrustum) const {
|
||||
return viewFrustum.computeCubeViewLocation(_cube);
|
||||
return viewFrustum.cubeInFrustum(_cube);
|
||||
}
|
||||
|
||||
// There are two types of nodes for which we want to "render"
|
||||
|
|
|
@ -91,9 +91,7 @@ void OctreeHeadlessViewer::queryOctree() {
|
|||
|
||||
if (foundRootDetails) {
|
||||
AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s);
|
||||
ViewFrustum::location serverFrustumLocation = _viewFrustum.computeCubeViewLocation(serverBounds);
|
||||
|
||||
if (serverFrustumLocation != ViewFrustum::OUTSIDE) {
|
||||
if ((bool)(_viewFrustum.cubeInFrustum(serverBounds))) {
|
||||
inViewServers++;
|
||||
}
|
||||
}
|
||||
|
@ -164,13 +162,7 @@ void OctreeHeadlessViewer::queryOctree() {
|
|||
|
||||
if (foundRootDetails) {
|
||||
AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s);
|
||||
|
||||
ViewFrustum::location serverFrustumLocation = _viewFrustum.computeCubeViewLocation(serverBounds);
|
||||
if (serverFrustumLocation != ViewFrustum::OUTSIDE) {
|
||||
inView = true;
|
||||
} else {
|
||||
inView = false;
|
||||
}
|
||||
inView = (bool)(_viewFrustum.cubeInFrustum(serverBounds));
|
||||
}
|
||||
|
||||
if (inView) {
|
||||
|
|
|
@ -134,115 +134,8 @@ const char* ViewFrustum::debugPlaneName (int plane) const {
|
|||
return "Unknown";
|
||||
}
|
||||
|
||||
ViewFrustum::location ViewFrustum::pointInKeyhole(const glm::vec3& point) const {
|
||||
|
||||
ViewFrustum::location result = INTERSECT;
|
||||
|
||||
float distance = glm::distance(point, _position);
|
||||
if (distance > _keyholeRadius) {
|
||||
result = OUTSIDE;
|
||||
} else if (distance < _keyholeRadius) {
|
||||
result = INSIDE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// To determine if two spheres intersect, simply calculate the distance between the centers of the two spheres.
|
||||
// If the distance is greater than the sum of the two sphere radii, they don’t intersect. Otherwise they intersect.
|
||||
// If the distance plus the radius of sphere A is less than the radius of sphere B then, sphere A is inside of sphere B
|
||||
ViewFrustum::location ViewFrustum::sphereInKeyhole(const glm::vec3& center, float radius) const {
|
||||
ViewFrustum::location result = INTERSECT;
|
||||
|
||||
float distance = glm::distance(center, _position);
|
||||
if (distance > (radius + _keyholeRadius)) {
|
||||
result = OUTSIDE;
|
||||
} else if ((distance + radius) < _keyholeRadius) {
|
||||
result = INSIDE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// A box is inside a sphere if all of its corners are inside the sphere
|
||||
// A box intersects a sphere if any of its edges (as rays) interesect the sphere
|
||||
// A box is outside a sphere if none of its edges (as rays) interesect the sphere
|
||||
ViewFrustum::location ViewFrustum::cubeInKeyhole(const AACube& cube) const {
|
||||
|
||||
// First check to see if the cube is in the bounding cube for the sphere, if it's not, then we can short circuit
|
||||
// this and not check with sphere penetration which is more expensive
|
||||
if (!_keyholeBoundingCube.contains(cube)) {
|
||||
return OUTSIDE;
|
||||
}
|
||||
|
||||
glm::vec3 penetration;
|
||||
bool intersects = cube.findSpherePenetration(_position, _keyholeRadius, penetration);
|
||||
|
||||
ViewFrustum::location result = OUTSIDE;
|
||||
|
||||
// if the cube intersects the sphere, then it may also be inside... calculate further
|
||||
if (intersects) {
|
||||
result = INTERSECT;
|
||||
|
||||
// test all the corners, if they are all inside the sphere, the entire cube is in the sphere
|
||||
bool allPointsInside = true; // assume the best
|
||||
for (int v = BOTTOM_LEFT_NEAR; v < TOP_LEFT_FAR; v++) {
|
||||
glm::vec3 vertex = cube.getVertex((BoxVertex)v);
|
||||
if (!pointInKeyhole(vertex)) {
|
||||
allPointsInside = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (allPointsInside) {
|
||||
result = INSIDE;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// A box is inside a sphere if all of its corners are inside the sphere
|
||||
// A box intersects a sphere if any of its edges (as rays) interesect the sphere
|
||||
// A box is outside a sphere if none of its edges (as rays) interesect the sphere
|
||||
ViewFrustum::location ViewFrustum::boxInKeyhole(const AABox& box) const {
|
||||
|
||||
// First check to see if the box is in the bounding box for the sphere, if it's not, then we can short circuit
|
||||
// this and not check with sphere penetration which is more expensive
|
||||
if (!_keyholeBoundingCube.contains(box)) {
|
||||
return OUTSIDE;
|
||||
}
|
||||
|
||||
glm::vec3 penetration;
|
||||
bool intersects = box.findSpherePenetration(_position, _keyholeRadius, penetration);
|
||||
|
||||
ViewFrustum::location result = OUTSIDE;
|
||||
|
||||
// if the box intersects the sphere, then it may also be inside... calculate further
|
||||
if (intersects) {
|
||||
result = INTERSECT;
|
||||
|
||||
// test all the corners, if they are all inside the sphere, the entire box is in the sphere
|
||||
bool allPointsInside = true; // assume the best
|
||||
for (int v = BOTTOM_LEFT_NEAR; v < TOP_LEFT_FAR; v++) {
|
||||
glm::vec3 vertex = box.getVertex((BoxVertex)v);
|
||||
if (!pointInKeyhole(vertex)) {
|
||||
allPointsInside = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (allPointsInside) {
|
||||
result = INSIDE;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ViewFrustum::location ViewFrustum::computePointFrustumLocation(const glm::vec3& point) const {
|
||||
// only checks against frustum, not sphere
|
||||
ViewFrustum::location ViewFrustum::pointInFrustum(const glm::vec3& point) const {
|
||||
// only check against frustum
|
||||
for(int i = 0; i < 6; ++i) {
|
||||
float distance = _planes[i].distance(point);
|
||||
if (distance < 0.0f) {
|
||||
|
@ -252,101 +145,101 @@ ViewFrustum::location ViewFrustum::computePointFrustumLocation(const glm::vec3&
|
|||
return INSIDE;
|
||||
}
|
||||
|
||||
ViewFrustum::location ViewFrustum::computeSphereViewLocation(const glm::vec3& center, float radius) const {
|
||||
ViewFrustum::location regularResult = INSIDE;
|
||||
ViewFrustum::location keyholeResult = OUTSIDE;
|
||||
|
||||
// If we have a keyholeRadius, check that first, since it's cheaper
|
||||
if (_keyholeRadius >= 0.0f) {
|
||||
keyholeResult = sphereInKeyhole(center, radius);
|
||||
}
|
||||
if (keyholeResult == INSIDE) {
|
||||
return keyholeResult;
|
||||
}
|
||||
|
||||
float distance;
|
||||
ViewFrustum::location ViewFrustum::sphereInFrustum(const glm::vec3& center, float radius) const {
|
||||
// only check against frustum
|
||||
ViewFrustum::location result = INSIDE;
|
||||
for(int i=0; i < 6; i++) {
|
||||
distance = _planes[i].distance(center);
|
||||
float distance = _planes[i].distance(center);
|
||||
if (distance < -radius) {
|
||||
// This is outside the regular frustum, so just return the value from checking the keyhole
|
||||
return keyholeResult;
|
||||
return OUTSIDE;
|
||||
} else if (distance < radius) {
|
||||
regularResult = INTERSECT;
|
||||
result = INTERSECT;
|
||||
}
|
||||
}
|
||||
|
||||
return regularResult;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
ViewFrustum::location ViewFrustum::computeCubeViewLocation(const AACube& cube) const {
|
||||
|
||||
ViewFrustum::location regularResult = INSIDE;
|
||||
ViewFrustum::location keyholeResult = OUTSIDE;
|
||||
|
||||
// If we have a keyholeRadius, check that first, since it's cheaper
|
||||
if (_keyholeRadius >= 0.0f) {
|
||||
keyholeResult = cubeInKeyhole(cube);
|
||||
}
|
||||
if (keyholeResult == INSIDE) {
|
||||
return keyholeResult;
|
||||
}
|
||||
|
||||
// TODO: These calculations are expensive, taking up 80% of our time in this function.
|
||||
// This appears to be expensive because we have to test the distance to each plane.
|
||||
// One suggested optimization is to first check against the approximated cone. We might
|
||||
// also be able to test against the cone to the bounding sphere of the box.
|
||||
ViewFrustum::location ViewFrustum::cubeInFrustum(const AACube& cube) const {
|
||||
// only check against frustum
|
||||
ViewFrustum::location result = INSIDE;
|
||||
for(int i=0; i < 6; i++) {
|
||||
const glm::vec3& normal = _planes[i].getNormal();
|
||||
const glm::vec3& boxVertexP = cube.getVertexP(normal);
|
||||
float planeToBoxVertexPDistance = _planes[i].distance(boxVertexP);
|
||||
|
||||
const glm::vec3& boxVertexN = cube.getVertexN(normal);
|
||||
float planeToBoxVertexNDistance = _planes[i].distance(boxVertexN);
|
||||
|
||||
if (planeToBoxVertexPDistance < 0) {
|
||||
// This is outside the regular frustum, so just return the value from checking the keyhole
|
||||
return keyholeResult;
|
||||
} else if (planeToBoxVertexNDistance < 0) {
|
||||
regularResult = INTERSECT;
|
||||
// check distance to farthest cube point
|
||||
if ( _planes[i].distance(cube.getFarthestVertex(normal)) < 0.0f) {
|
||||
return OUTSIDE;
|
||||
} else {
|
||||
// check distance to nearest cube point
|
||||
if (_planes[i].distance(cube.getNearestVertex(normal)) < 0.0f) {
|
||||
// cube straddles the plane
|
||||
result = INTERSECT;
|
||||
}
|
||||
}
|
||||
}
|
||||
return regularResult;
|
||||
return result;
|
||||
}
|
||||
|
||||
ViewFrustum::location ViewFrustum::computeBoxViewLocation(const AABox& box) const {
|
||||
|
||||
ViewFrustum::location regularResult = INSIDE;
|
||||
ViewFrustum::location keyholeResult = OUTSIDE;
|
||||
|
||||
// If we have a keyholeRadius, check that first, since it's cheaper
|
||||
if (_keyholeRadius >= 0.0f) {
|
||||
keyholeResult = boxInKeyhole(box);
|
||||
}
|
||||
if (keyholeResult == INSIDE) {
|
||||
return keyholeResult;
|
||||
}
|
||||
|
||||
// TODO: These calculations are expensive, taking up 80% of our time in this function.
|
||||
// This appears to be expensive because we have to test the distance to each plane.
|
||||
// One suggested optimization is to first check against the approximated cone. We might
|
||||
// also be able to test against the cone to the bounding sphere of the box.
|
||||
ViewFrustum::location ViewFrustum::boxInFrustum(const AABox& box) const {
|
||||
// only check against frustum
|
||||
ViewFrustum::location result = INSIDE;
|
||||
for(int i=0; i < 6; i++) {
|
||||
const glm::vec3& normal = _planes[i].getNormal();
|
||||
const glm::vec3& boxVertexP = box.getVertexP(normal);
|
||||
float planeToBoxVertexPDistance = _planes[i].distance(boxVertexP);
|
||||
|
||||
const glm::vec3& boxVertexN = box.getVertexN(normal);
|
||||
float planeToBoxVertexNDistance = _planes[i].distance(boxVertexN);
|
||||
|
||||
if (planeToBoxVertexPDistance < 0) {
|
||||
// This is outside the regular frustum, so just return the value from checking the keyhole
|
||||
return keyholeResult;
|
||||
} else if (planeToBoxVertexNDistance < 0) {
|
||||
regularResult = INTERSECT;
|
||||
// check distance to farthest box point
|
||||
if ( _planes[i].distance(box.getFarthestVertex(normal)) < 0.0f) {
|
||||
return OUTSIDE;
|
||||
} else {
|
||||
// check distance to nearest box point
|
||||
if (_planes[i].distance(box.getNearestVertex(normal)) < 0.0f) {
|
||||
// box straddles the plane
|
||||
result = INTERSECT;
|
||||
}
|
||||
}
|
||||
}
|
||||
return regularResult;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ViewFrustum::sphereTouchesKeyhole(const glm::vec3& center, float radius) const {
|
||||
// check positive touch against central sphere
|
||||
if (glm::length(center - _position) <= (radius + _keyholeRadius)) {
|
||||
return true;
|
||||
}
|
||||
// check negative touches against frustum planes
|
||||
for(int i=0; i < 6; i++) {
|
||||
if ( _planes[i].distance(center) < -radius) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ViewFrustum::cubeTouchesKeyhole(const AACube& cube) const {
|
||||
// check positive touch against central sphere
|
||||
if (cube.touchesSphere(_position, _keyholeRadius)) {
|
||||
return true;
|
||||
}
|
||||
// check negative touches against frustum planes
|
||||
for(int i=0; i < 6; i++) {
|
||||
const glm::vec3& normal = _planes[i].getNormal();
|
||||
if ( _planes[i].distance(cube.getFarthestVertex(normal)) < 0.0f) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ViewFrustum::boxTouchesKeyhole(const AABox& box) const {
|
||||
// check positive touch against central sphere
|
||||
if (box.touchesSphere(_position, _keyholeRadius)) {
|
||||
return true;
|
||||
}
|
||||
// check negative touches against frustum planes
|
||||
for(int i=0; i < 6; i++) {
|
||||
const glm::vec3& normal = _planes[i].getNormal();
|
||||
if ( _planes[i].distance(box.getFarthestVertex(normal)) < 0.0f) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool testMatches(glm::quat lhs, glm::quat rhs, float epsilon = EPSILON) {
|
||||
|
|
|
@ -89,13 +89,16 @@ public:
|
|||
|
||||
void calculate();
|
||||
|
||||
typedef enum {OUTSIDE, INTERSECT, INSIDE} location;
|
||||
typedef enum { OUTSIDE = 0, INTERSECT, INSIDE } location;
|
||||
|
||||
ViewFrustum::location computePointFrustumLocation(const glm::vec3& point) const;
|
||||
ViewFrustum::location pointInFrustum(const glm::vec3& point) const;
|
||||
ViewFrustum::location sphereInFrustum(const glm::vec3& center, float radius) const;
|
||||
ViewFrustum::location cubeInFrustum(const AACube& cube) const;
|
||||
ViewFrustum::location boxInFrustum(const AABox& box) const;
|
||||
|
||||
ViewFrustum::location computeSphereViewLocation(const glm::vec3& center, float radius) const;
|
||||
ViewFrustum::location computeCubeViewLocation(const AACube& cube) const;
|
||||
ViewFrustum::location computeBoxViewLocation(const AABox& box) const;
|
||||
bool sphereTouchesKeyhole(const glm::vec3& center, float radius) const;
|
||||
bool cubeTouchesKeyhole(const AACube& cube) const;
|
||||
bool boxTouchesKeyhole(const AABox& box) const;
|
||||
|
||||
// some frustum comparisons
|
||||
bool matches(const ViewFrustum& compareTo, bool debug = false) const;
|
||||
|
@ -132,12 +135,6 @@ public:
|
|||
|
||||
const ::Plane* getPlanes() const { return _planes; }
|
||||
private:
|
||||
// Used for keyhole calculations
|
||||
ViewFrustum::location pointInKeyhole(const glm::vec3& point) const;
|
||||
ViewFrustum::location sphereInKeyhole(const glm::vec3& center, float radius) const;
|
||||
ViewFrustum::location cubeInKeyhole(const AACube& cube) const;
|
||||
ViewFrustum::location boxInKeyhole(const AABox& box) const;
|
||||
|
||||
// camera location/orientation attributes
|
||||
glm::vec3 _position; // the position in world-frame
|
||||
glm::quat _orientation;
|
||||
|
@ -166,7 +163,7 @@ private:
|
|||
float _fieldOfView = DEFAULT_FIELD_OF_VIEW_DEGREES;
|
||||
glm::vec4 _corners[8];
|
||||
glm::vec3 _cornersWorld[8];
|
||||
::Plane _planes[6]; // How will this be used?
|
||||
::Plane _planes[6]; // plane normals point inside frustum
|
||||
|
||||
const char* debugPlaneName (int plane) const;
|
||||
|
||||
|
|
|
@ -474,15 +474,12 @@ void ModelMeshPartPayload::render(RenderArgs* args) const {
|
|||
#ifdef DEBUG_BOUNDING_PARTS
|
||||
{
|
||||
AABox partBounds = getPartBounds(_meshIndex, partIndex);
|
||||
bool inView = args->_viewFrustum->computeBoxViewLocation(partBounds) != ViewFrustum::OUTSIDE;
|
||||
|
||||
glm::vec4 cubeColor;
|
||||
glm::vec4 cubeColor(1.0f, 1.0f, 0.0f, 1.0f);
|
||||
if (isSkinned) {
|
||||
cubeColor = glm::vec4(0.0f, 1.0f, 1.0f, 1.0f);
|
||||
} else if (inView) {
|
||||
} else if ((bool)(args->_viewFrustum->boxInFrustum(partBounds))) {
|
||||
cubeColor = glm::vec4(1.0f, 0.0f, 1.0f, 1.0f);
|
||||
} else {
|
||||
cubeColor = glm::vec4(1.0f, 1.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
Transform transform;
|
||||
|
|
|
@ -41,8 +41,8 @@ void render::cullItems(const RenderContextPointer& renderContext, const CullFunc
|
|||
// when they are outside of the view frustum...
|
||||
bool outOfView;
|
||||
{
|
||||
PerformanceTimer perfTimer("computeBoxViewLocation");
|
||||
outOfView = frustum->computeBoxViewLocation(item.bound) == ViewFrustum::OUTSIDE;
|
||||
PerformanceTimer perfTimer("boxInFrustum");
|
||||
outOfView = frustum->boxInFrustum(item.bound) == ViewFrustum::OUTSIDE;
|
||||
}
|
||||
if (!outOfView) {
|
||||
bool bigEnoughToRender;
|
||||
|
@ -238,7 +238,7 @@ void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const Re
|
|||
}
|
||||
|
||||
bool viewTest(const AABox& bound) {
|
||||
if (_args->_viewFrustum->computeBoxViewLocation(bound) == ViewFrustum::OUTSIDE) {
|
||||
if (_args->_viewFrustum->boxInFrustum(bound) == ViewFrustum::OUTSIDE) {
|
||||
_renderDetails._outOfView++;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -75,32 +75,32 @@ void AABox::setBox(const glm::vec3& corner, const glm::vec3& scale) {
|
|||
_scale = scale;
|
||||
}
|
||||
|
||||
glm::vec3 AABox::getVertexP(const glm::vec3& normal) const {
|
||||
glm::vec3 AABox::getFarthestVertex(const glm::vec3& normal) const {
|
||||
glm::vec3 result = _corner;
|
||||
if (normal.x > 0) {
|
||||
if (normal.x > 0.0f) {
|
||||
result.x += _scale.x;
|
||||
}
|
||||
if (normal.y > 0) {
|
||||
if (normal.y > 0.0f) {
|
||||
result.y += _scale.y;
|
||||
}
|
||||
if (normal.z > 0) {
|
||||
if (normal.z > 0.0f) {
|
||||
result.z += _scale.z;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
glm::vec3 AABox::getVertexN(const glm::vec3& normal) const {
|
||||
glm::vec3 AABox::getNearestVertex(const glm::vec3& normal) const {
|
||||
glm::vec3 result = _corner;
|
||||
|
||||
if (normal.x < 0) {
|
||||
if (normal.x < 0.0f) {
|
||||
result.x += _scale.x;
|
||||
}
|
||||
|
||||
if (normal.y < 0) {
|
||||
if (normal.y < 0.0f) {
|
||||
result.y += _scale.y;
|
||||
}
|
||||
|
||||
if (normal.z < 0) {
|
||||
if (normal.z < 0.0f) {
|
||||
result.z += _scale.z;
|
||||
}
|
||||
|
||||
|
@ -217,7 +217,7 @@ bool AABox::expandedIntersectsSegment(const glm::vec3& start, const glm::vec3& e
|
|||
isWithin(start.x + axisDistance*direction.x, expandedCorner.x, expandedSize.x));
|
||||
}
|
||||
|
||||
bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal) const {
|
||||
// handle the trivial case where the box contains the origin
|
||||
if (contains(origin)) {
|
||||
|
@ -281,6 +281,12 @@ bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direct
|
|||
return false;
|
||||
}
|
||||
|
||||
bool AABox::touchesSphere(const glm::vec3& center, float radius) const {
|
||||
// Avro's algorithm from this paper: http://www.mrtc.mdh.se/projects/3Dgraphics/paperF.pdf
|
||||
glm::vec3 e = glm::max(_corner - center, Vectors::ZERO) + glm::max(center - _corner - _scale, Vectors::ZERO);
|
||||
return glm::length2(e) <= radius * radius;
|
||||
}
|
||||
|
||||
bool AABox::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const {
|
||||
glm::vec4 center4 = glm::vec4(center, 1.0f);
|
||||
|
||||
|
@ -537,4 +543,4 @@ void AABox::transform(const Transform& transform) {
|
|||
scale(transform.getScale());
|
||||
rotate(transform.getRotation());
|
||||
translate(transform.getTranslation());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,12 +35,12 @@ public:
|
|||
AABox(const glm::vec3& corner, const glm::vec3& dimensions);
|
||||
AABox();
|
||||
~AABox() {};
|
||||
|
||||
|
||||
void setBox(const glm::vec3& corner, const glm::vec3& scale);
|
||||
|
||||
void setBox(const glm::vec3& corner, float scale);
|
||||
glm::vec3 getVertexP(const glm::vec3& normal) const;
|
||||
glm::vec3 getVertexN(const glm::vec3& normal) const;
|
||||
glm::vec3 getFarthestVertex(const glm::vec3& normal) const; // return vertex most parallel to normal
|
||||
glm::vec3 getNearestVertex(const glm::vec3& normal) const; // return vertex most anti-parallel to normal
|
||||
|
||||
const glm::vec3& getCorner() const { return _corner; }
|
||||
const glm::vec3& getScale() const { return _scale; }
|
||||
|
@ -68,11 +68,12 @@ public:
|
|||
|
||||
bool expandedContains(const glm::vec3& point, float expansion) const;
|
||||
bool expandedIntersectsSegment(const glm::vec3& start, const glm::vec3& end, float expansion) const;
|
||||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal) const;
|
||||
bool touchesSphere(const glm::vec3& center, float radius) const; // fast but may generate false positives
|
||||
bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const;
|
||||
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) const;
|
||||
|
||||
|
||||
bool isNull() const { return _scale == glm::vec3(0.0f, 0.0f, 0.0f); }
|
||||
|
||||
AABox clamp(const glm::vec3& min, const glm::vec3& max) const;
|
||||
|
@ -113,7 +114,7 @@ inline bool operator==(const AABox& a, const AABox& b) {
|
|||
}
|
||||
|
||||
inline QDebug operator<<(QDebug debug, const AABox& box) {
|
||||
debug << "AABox[ ("
|
||||
debug << "AABox[ ("
|
||||
<< box.getCorner().x << "," << box.getCorner().y << "," << box.getCorner().z << " ) to ("
|
||||
<< box.calcTopFarLeft().x << "," << box.calcTopFarLeft().y << "," << box.calcTopFarLeft().z << ") size: ("
|
||||
<< box.getDimensions().x << "," << box.getDimensions().y << "," << box.getDimensions().z << ")"
|
||||
|
|
|
@ -79,32 +79,32 @@ void AACube::setBox(const glm::vec3& corner, float scale) {
|
|||
_scale = scale;
|
||||
}
|
||||
|
||||
glm::vec3 AACube::getVertexP(const glm::vec3& normal) const {
|
||||
glm::vec3 AACube::getFarthestVertex(const glm::vec3& normal) const {
|
||||
glm::vec3 result = _corner;
|
||||
if (normal.x > 0) {
|
||||
if (normal.x > 0.0f) {
|
||||
result.x += _scale;
|
||||
}
|
||||
if (normal.y > 0) {
|
||||
if (normal.y > 0.0f) {
|
||||
result.y += _scale;
|
||||
}
|
||||
if (normal.z > 0) {
|
||||
if (normal.z > 0.0f) {
|
||||
result.z += _scale;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
glm::vec3 AACube::getVertexN(const glm::vec3& normal) const {
|
||||
glm::vec3 AACube::getNearestVertex(const glm::vec3& normal) const {
|
||||
glm::vec3 result = _corner;
|
||||
|
||||
if (normal.x < 0) {
|
||||
if (normal.x < 0.0f) {
|
||||
result.x += _scale;
|
||||
}
|
||||
|
||||
if (normal.y < 0) {
|
||||
if (normal.y < 0.0f) {
|
||||
result.y += _scale;
|
||||
}
|
||||
|
||||
if (normal.z < 0) {
|
||||
if (normal.z < 0.0f) {
|
||||
result.z += _scale;
|
||||
}
|
||||
|
||||
|
@ -284,6 +284,12 @@ bool AACube::findRayIntersection(const glm::vec3& origin, const glm::vec3& direc
|
|||
return false;
|
||||
}
|
||||
|
||||
bool AACube::touchesSphere(const glm::vec3& center, float radius) const {
|
||||
// Avro's algorithm from this paper: http://www.mrtc.mdh.se/projects/3Dgraphics/paperF.pdf
|
||||
glm::vec3 e = glm::max(_corner - center, Vectors::ZERO) + glm::max(center - _corner - glm::vec3(_scale), Vectors::ZERO);
|
||||
return glm::length2(e) <= radius * radius;
|
||||
}
|
||||
|
||||
bool AACube::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const {
|
||||
glm::vec4 center4 = glm::vec4(center, 1.0f);
|
||||
|
||||
|
|
|
@ -34,8 +34,8 @@ public:
|
|||
~AACube() {};
|
||||
|
||||
void setBox(const glm::vec3& corner, float scale);
|
||||
glm::vec3 getVertexP(const glm::vec3& normal) const;
|
||||
glm::vec3 getVertexN(const glm::vec3& normal) const;
|
||||
glm::vec3 getFarthestVertex(const glm::vec3& normal) const; // return vertex most parallel to normal
|
||||
glm::vec3 getNearestVertex(const glm::vec3& normal) const; // return vertex most anti-parallel to normal
|
||||
void scale(float scale);
|
||||
const glm::vec3& getCorner() const { return _corner; }
|
||||
float getScale() const { return _scale; }
|
||||
|
@ -56,8 +56,9 @@ public:
|
|||
bool touches(const AABox& otherBox) const;
|
||||
bool expandedContains(const glm::vec3& point, float expansion) const;
|
||||
bool expandedIntersectsSegment(const glm::vec3& start, const glm::vec3& end, float expansion) const;
|
||||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal) const;
|
||||
bool touchesSphere(const glm::vec3& center, float radius) const;
|
||||
bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const;
|
||||
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) const;
|
||||
|
||||
|
@ -88,7 +89,7 @@ inline bool operator!=(const AACube& a, const AACube& b) {
|
|||
}
|
||||
|
||||
inline QDebug operator<<(QDebug debug, const AACube& cube) {
|
||||
debug << "AACube[ ("
|
||||
debug << "AACube[ ("
|
||||
<< cube.getCorner().x << "," << cube.getCorner().y << "," << cube.getCorner().z << " ) to ("
|
||||
<< cube.calcTopFarLeft().x << "," << cube.calcTopFarLeft().y << "," << cube.calcTopFarLeft().z << ") size: ("
|
||||
<< cube.getDimensions().x << "," << cube.getDimensions().y << "," << cube.getDimensions().z << ")"
|
||||
|
|
|
@ -1,316 +0,0 @@
|
|||
//
|
||||
// AngularConstraintTests.cpp
|
||||
// tests/physics/src
|
||||
//
|
||||
// Created by Andrew Meadows on 2014.05.30
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "AngularConstraintTests.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <AngularConstraint.h>
|
||||
#include <NumericalConstants.h>
|
||||
#include <StreamUtils.h>
|
||||
|
||||
#include "../QTestExtensions.h"
|
||||
|
||||
|
||||
QTEST_MAIN(AngularConstraintTests)
|
||||
|
||||
void AngularConstraintTests::testHingeConstraint() {
|
||||
float minAngle = -PI;
|
||||
float maxAngle = 0.0f;
|
||||
glm::vec3 yAxis(0.0f, 1.0f, 0.0f);
|
||||
glm::vec3 minAngles(0.0f, -PI, 0.0f);
|
||||
glm::vec3 maxAngles(0.0f, 0.0f, 0.0f);
|
||||
|
||||
AngularConstraint* c = AngularConstraint::newAngularConstraint(minAngles, maxAngles);
|
||||
QVERIFY2(c != nullptr, "newAngularConstraint should make a constraint");
|
||||
{ // test in middle of constraint
|
||||
float angle = 0.5f * (minAngle + maxAngle);
|
||||
glm::quat rotation = glm::angleAxis(angle, yAxis);
|
||||
|
||||
glm::quat newRotation = rotation;
|
||||
bool constrained = c->clamp(newRotation);
|
||||
|
||||
QVERIFY2(constrained == false, "HingeConstraint should not clamp()");
|
||||
QVERIFY2(rotation == newRotation, "HingeConstraint should not change rotation");
|
||||
}
|
||||
{ // test just inside min edge of constraint
|
||||
float angle = minAngle + 10.0f * EPSILON;
|
||||
glm::quat rotation = glm::angleAxis(angle, yAxis);
|
||||
|
||||
glm::quat newRotation = rotation;
|
||||
bool constrained = c->clamp(newRotation);
|
||||
|
||||
QVERIFY2(!constrained, "HingeConstraint should not clamp()");
|
||||
QVERIFY2(newRotation == rotation, "HingeConstraint should not change rotation");
|
||||
}
|
||||
{ // test just inside max edge of constraint
|
||||
float angle = maxAngle - 10.0f * EPSILON;
|
||||
glm::quat rotation = glm::angleAxis(angle, yAxis);
|
||||
|
||||
glm::quat newRotation = rotation;
|
||||
bool constrained = c->clamp(newRotation);
|
||||
|
||||
QVERIFY2(!constrained, "HingeConstraint should not clamp()");
|
||||
QVERIFY2(newRotation == rotation, "HingeConstraint should not change rotation");
|
||||
}
|
||||
{ // test just outside min edge of constraint
|
||||
float angle = minAngle - 0.001f;
|
||||
glm::quat rotation = glm::angleAxis(angle, yAxis);
|
||||
|
||||
glm::quat newRotation = rotation;
|
||||
bool constrained = c->clamp(newRotation);
|
||||
glm::quat expectedRotation = glm::angleAxis(minAngle, yAxis);
|
||||
|
||||
QVERIFY2(constrained, "HingeConstraint should clamp()");
|
||||
QVERIFY2(newRotation != rotation, "HingeConstraint should change rotation");
|
||||
QCOMPARE_WITH_ABS_ERROR(newRotation, expectedRotation, EPSILON);
|
||||
}
|
||||
{ // test just outside max edge of constraint
|
||||
float angle = maxAngle + 0.001f;
|
||||
glm::quat rotation = glm::angleAxis(angle, yAxis);
|
||||
|
||||
glm::quat newRotation = rotation;
|
||||
bool constrained = c->clamp(newRotation);
|
||||
|
||||
QVERIFY2(constrained, "HingeConstraint should clamp()");
|
||||
QVERIFY2(newRotation != rotation, "HingeConstraint should change rotation");
|
||||
QCOMPARE_WITH_ABS_ERROR(newRotation, rotation, EPSILON);
|
||||
}
|
||||
{ // test far outside min edge of constraint (wraps around to max)
|
||||
float angle = minAngle - 0.75f * (TWO_PI - (maxAngle - minAngle));
|
||||
glm::quat rotation = glm::angleAxis(angle, yAxis);
|
||||
|
||||
glm::quat newRotation = rotation;
|
||||
bool constrained = c->clamp(newRotation);
|
||||
|
||||
glm::quat expectedRotation = glm::angleAxis(maxAngle, yAxis);
|
||||
QVERIFY2(constrained, "HingeConstraint should clamp()");
|
||||
QVERIFY2(newRotation != rotation, "HingeConstraint should change rotation");
|
||||
QCOMPARE_WITH_ABS_ERROR(newRotation, expectedRotation, EPSILON);
|
||||
}
|
||||
{ // test far outside max edge of constraint (wraps around to min)
|
||||
float angle = maxAngle + 0.75f * (TWO_PI - (maxAngle - minAngle));
|
||||
glm::quat rotation = glm::angleAxis(angle, yAxis);
|
||||
|
||||
glm::quat newRotation = rotation;
|
||||
bool constrained = c->clamp(newRotation);
|
||||
glm::quat expectedRotation = glm::angleAxis(minAngle, yAxis);
|
||||
|
||||
QVERIFY2(constrained, "HingeConstraint should clamp()");
|
||||
QVERIFY2(newRotation != rotation, "HingeConstraint should change rotation");
|
||||
QCOMPARE_WITH_ABS_ERROR(newRotation, expectedRotation, EPSILON);
|
||||
}
|
||||
|
||||
float ACCEPTABLE_ERROR = 1.0e-4f;
|
||||
{ // test nearby but off-axis rotation
|
||||
float offAngle = 0.1f;
|
||||
glm::quat offRotation(offAngle, glm::vec3(1.0f, 0.0f, 0.0f));
|
||||
float angle = 0.5f * (maxAngle + minAngle);
|
||||
glm::quat rotation = offRotation * glm::angleAxis(angle, yAxis);
|
||||
|
||||
glm::quat newRotation = rotation;
|
||||
bool constrained = c->clamp(newRotation);
|
||||
glm::quat expectedRotation = glm::angleAxis(angle, yAxis);
|
||||
|
||||
QVERIFY2(constrained, "HingeConstraint should clamp()");
|
||||
QVERIFY2(newRotation != rotation, "HingeConstraint should change rotation");
|
||||
QCOMPARE_WITH_ABS_ERROR(newRotation, expectedRotation, ACCEPTABLE_ERROR);
|
||||
}
|
||||
{ // test way off rotation > maxAngle
|
||||
float offAngle = 0.5f;
|
||||
glm::quat offRotation = glm::angleAxis(offAngle, glm::vec3(1.0f, 0.0f, 0.0f));
|
||||
float angle = maxAngle + 0.2f * (TWO_PI - (maxAngle - minAngle));
|
||||
glm::quat rotation = glm::angleAxis(angle, yAxis);
|
||||
rotation = offRotation * glm::angleAxis(angle, yAxis);
|
||||
|
||||
glm::quat newRotation = rotation;
|
||||
bool constrained = c->clamp(newRotation);
|
||||
glm::quat expectedRotation = glm::angleAxis(maxAngle, yAxis);
|
||||
|
||||
QVERIFY2(constrained, "HingeConstraint should clamp()");
|
||||
QVERIFY2(newRotation != rotation, "HingeConstraint should change rotation");
|
||||
QCOMPARE_WITH_ABS_ERROR(newRotation, expectedRotation, EPSILON);
|
||||
}
|
||||
{ // test way off rotation < minAngle
|
||||
float offAngle = 0.5f;
|
||||
glm::quat offRotation = glm::angleAxis(offAngle, glm::vec3(1.0f, 0.0f, 0.0f));
|
||||
float angle = minAngle - 0.2f * (TWO_PI - (maxAngle - minAngle));
|
||||
glm::quat rotation = glm::angleAxis(angle, yAxis);
|
||||
rotation = offRotation * glm::angleAxis(angle, yAxis);
|
||||
|
||||
glm::quat newRotation = rotation;
|
||||
bool constrained = c->clamp(newRotation);
|
||||
glm::quat expectedRotation = glm::angleAxis(minAngle, yAxis);
|
||||
|
||||
QVERIFY2(constrained, "HingeConstraint should clamp()");
|
||||
QVERIFY2(newRotation != rotation, "HingeConstraint should change rotation");
|
||||
QCOMPARE_WITH_ABS_ERROR(newRotation, expectedRotation, EPSILON);
|
||||
}
|
||||
{ // test way off rotation > maxAngle with wrap over to minAngle
|
||||
float offAngle = -0.5f;
|
||||
glm::quat offRotation = glm::angleAxis(offAngle, glm::vec3(1.0f, 0.0f, 0.0f));
|
||||
float angle = maxAngle + 0.6f * (TWO_PI - (maxAngle - minAngle));
|
||||
glm::quat rotation = glm::angleAxis(angle, yAxis);
|
||||
rotation = offRotation * glm::angleAxis(angle, yAxis);
|
||||
|
||||
glm::quat newRotation = rotation;
|
||||
bool constrained = c->clamp(newRotation);
|
||||
glm::quat expectedRotation = glm::angleAxis(minAngle, yAxis);
|
||||
|
||||
QVERIFY2(constrained, "HingeConstraint should clamp()");
|
||||
QVERIFY2(newRotation != rotation, "HingeConstraint should change rotation");
|
||||
QCOMPARE_WITH_ABS_ERROR(newRotation, expectedRotation, EPSILON);
|
||||
}
|
||||
{ // test way off rotation < minAngle with wrap over to maxAngle
|
||||
float offAngle = -0.6f;
|
||||
glm::quat offRotation = glm::angleAxis(offAngle, glm::vec3(1.0f, 0.0f, 0.0f));
|
||||
float angle = minAngle - 0.7f * (TWO_PI - (maxAngle - minAngle));
|
||||
glm::quat rotation = glm::angleAxis(angle, yAxis);
|
||||
rotation = offRotation * glm::angleAxis(angle, yAxis);
|
||||
|
||||
glm::quat newRotation = rotation;
|
||||
bool constrained = c->clamp(newRotation);
|
||||
glm::quat expectedRotation = glm::angleAxis(maxAngle, yAxis);
|
||||
|
||||
QVERIFY2(constrained, "HingeConstraint should clamp()");
|
||||
QVERIFY2(newRotation != rotation, "HingeConstraint should change rotation");
|
||||
QCOMPARE_WITH_ABS_ERROR(newRotation, expectedRotation, EPSILON);
|
||||
}
|
||||
delete c;
|
||||
}
|
||||
|
||||
void AngularConstraintTests::testConeRollerConstraint() {
|
||||
float minAngleX = -PI / 5.0f;
|
||||
float minAngleY = -PI / 5.0f;
|
||||
float minAngleZ = -PI / 8.0f;
|
||||
|
||||
float maxAngleX = PI / 4.0f;
|
||||
float maxAngleY = PI / 3.0f;
|
||||
float maxAngleZ = PI / 4.0f;
|
||||
|
||||
glm::vec3 minAngles(minAngleX, minAngleY, minAngleZ);
|
||||
glm::vec3 maxAngles(maxAngleX, maxAngleY, maxAngleZ);
|
||||
AngularConstraint* c = AngularConstraint::newAngularConstraint(minAngles, maxAngles);
|
||||
|
||||
float expectedConeAngle = 0.25f * (maxAngleX - minAngleX + maxAngleY - minAngleY);
|
||||
glm::vec3 middleAngles = 0.5f * (maxAngles + minAngles);
|
||||
glm::quat yaw = glm::angleAxis(middleAngles[1], glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
glm::quat pitch = glm::angleAxis(middleAngles[0], glm::vec3(1.0f, 0.0f, 0.0f));
|
||||
glm::vec3 expectedConeAxis = pitch * yaw * glm::vec3(0.0f, 0.0f, 1.0f);
|
||||
|
||||
glm::vec3 xAxis(1.0f, 0.0f, 0.0f);
|
||||
glm::vec3 perpAxis = glm::normalize(xAxis - glm::dot(xAxis, expectedConeAxis) * expectedConeAxis);
|
||||
|
||||
QVERIFY2(c != nullptr, "newAngularConstraint() should make a constraint");
|
||||
{ // test in middle of constraint
|
||||
glm::vec3 angles(PI/20.0f, 0.0f, PI/10.0f);
|
||||
glm::quat rotation(angles);
|
||||
|
||||
glm::quat newRotation = rotation;
|
||||
bool constrained = c->clamp(newRotation);
|
||||
QVERIFY2(!constrained, "ConeRollerConstraint should not clamp()");
|
||||
QVERIFY2(newRotation == rotation, "ConeRollerConstraint should not change rotation");
|
||||
}
|
||||
float deltaAngle = 0.001f;
|
||||
{ // test just inside edge of cone
|
||||
glm::quat rotation = glm::angleAxis(expectedConeAngle - deltaAngle, perpAxis);
|
||||
|
||||
glm::quat newRotation = rotation;
|
||||
bool constrained = c->clamp(newRotation);
|
||||
|
||||
QVERIFY2(!constrained, "ConeRollerConstraint should not clamp()");
|
||||
QVERIFY2(newRotation == rotation, "ConeRollerConstraint should not change rotation");
|
||||
}
|
||||
{ // test just outside edge of cone
|
||||
glm::quat rotation = glm::angleAxis(expectedConeAngle + deltaAngle, perpAxis);
|
||||
|
||||
glm::quat newRotation = rotation;
|
||||
bool constrained = c->clamp(newRotation);
|
||||
|
||||
QVERIFY2(constrained, "ConeRollerConstraint should clamp()");
|
||||
QVERIFY2(newRotation != rotation, "ConeRollerConstraint should change rotation");
|
||||
}
|
||||
{ // test just inside min edge of roll
|
||||
glm::quat rotation = glm::angleAxis(minAngleZ + deltaAngle, expectedConeAxis);
|
||||
|
||||
glm::quat newRotation = rotation;
|
||||
bool constrained = c->clamp(newRotation);
|
||||
|
||||
QVERIFY2(!constrained, "ConeRollerConstraint should not clamp()");
|
||||
QVERIFY2(newRotation == rotation, "ConeRollerConstraint should not change rotation");
|
||||
}
|
||||
{ // test just inside max edge of roll
|
||||
glm::quat rotation = glm::angleAxis(maxAngleZ - deltaAngle, expectedConeAxis);
|
||||
|
||||
glm::quat newRotation = rotation;
|
||||
bool constrained = c->clamp(newRotation);
|
||||
|
||||
QVERIFY2(!constrained, "ConeRollerConstraint should not clamp()");
|
||||
QVERIFY2(newRotation == rotation, "ConeRollerConstraint should not change rotation");
|
||||
}
|
||||
{ // test just outside min edge of roll
|
||||
glm::quat rotation = glm::angleAxis(minAngleZ - deltaAngle, expectedConeAxis);
|
||||
|
||||
glm::quat newRotation = rotation;
|
||||
bool constrained = c->clamp(newRotation);
|
||||
glm::quat expectedRotation = glm::angleAxis(minAngleZ, expectedConeAxis);
|
||||
|
||||
QVERIFY2(constrained, "ConeRollerConstraint should clamp()");
|
||||
QVERIFY2(newRotation != rotation, "ConeRollerConstraint should change rotation");
|
||||
QCOMPARE_WITH_ABS_ERROR(newRotation, expectedRotation, EPSILON);
|
||||
}
|
||||
{ // test just outside max edge of roll
|
||||
glm::quat rotation = glm::angleAxis(maxAngleZ + deltaAngle, expectedConeAxis);
|
||||
|
||||
glm::quat newRotation = rotation;
|
||||
bool constrained = c->clamp(newRotation);
|
||||
glm::quat expectedRotation = glm::angleAxis(maxAngleZ, expectedConeAxis);
|
||||
|
||||
QVERIFY2(constrained, "ConeRollerConstraint should clamp()");
|
||||
QVERIFY2(newRotation != rotation, "ConeRollerConstraint should change rotation");
|
||||
QCOMPARE_WITH_ABS_ERROR(newRotation, expectedRotation, EPSILON);
|
||||
}
|
||||
deltaAngle = 0.25f * expectedConeAngle;
|
||||
{ // test far outside cone and min roll
|
||||
glm::quat roll = glm::angleAxis(minAngleZ - deltaAngle, expectedConeAxis);
|
||||
glm::quat pitchYaw = glm::angleAxis(expectedConeAngle + deltaAngle, perpAxis);
|
||||
glm::quat rotation = pitchYaw * roll;
|
||||
|
||||
glm::quat newRotation = rotation;
|
||||
bool constrained = c->clamp(newRotation);
|
||||
|
||||
glm::quat expectedRoll = glm::angleAxis(minAngleZ, expectedConeAxis);
|
||||
glm::quat expectedPitchYaw = glm::angleAxis(expectedConeAngle, perpAxis);
|
||||
glm::quat expectedRotation = expectedPitchYaw * expectedRoll;
|
||||
|
||||
QVERIFY2(constrained, "ConeRollerConstraint should clamp()");
|
||||
QVERIFY2(newRotation != rotation, "ConeRollerConstraint should change rotation");
|
||||
QCOMPARE_WITH_ABS_ERROR(newRotation, expectedRotation, EPSILON);
|
||||
}
|
||||
{ // test far outside cone and max roll
|
||||
glm::quat roll = glm::angleAxis(maxAngleZ + deltaAngle, expectedConeAxis);
|
||||
glm::quat pitchYaw = glm::angleAxis(- expectedConeAngle - deltaAngle, perpAxis);
|
||||
glm::quat rotation = pitchYaw * roll;
|
||||
|
||||
glm::quat newRotation = rotation;
|
||||
bool constrained = c->clamp(newRotation);
|
||||
|
||||
glm::quat expectedRoll = glm::angleAxis(maxAngleZ, expectedConeAxis);
|
||||
glm::quat expectedPitchYaw = glm::angleAxis(- expectedConeAngle, perpAxis);
|
||||
glm::quat expectedRotation = expectedPitchYaw * expectedRoll;
|
||||
|
||||
QVERIFY2(constrained, "ConeRollerConstraint should clamp()");
|
||||
QVERIFY2(newRotation != rotation, "ConeRollerConstraint should change rotation");
|
||||
QCOMPARE_WITH_ABS_ERROR(newRotation, expectedRotation, EPSILON);
|
||||
}
|
||||
delete c;
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
//
|
||||
// AngularConstraintTests.h
|
||||
// tests/physics/src
|
||||
//
|
||||
// Created by Andrew Meadows on 2014.05.30
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_AngularConstraintTests_h
|
||||
#define hifi_AngularConstraintTests_h
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
class AngularConstraintTests : public QObject {
|
||||
Q_OBJECT
|
||||
private slots:
|
||||
void testHingeConstraint();
|
||||
void testConeRollerConstraint();
|
||||
};
|
||||
|
||||
float getErrorDifference(const glm::quat& a, const glm::quat& b);
|
||||
|
||||
#endif // hifi_AngularConstraintTests_h
|
Loading…
Reference in a new issue