diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2b552de0ee..e01dc4c152 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2076,10 +2076,10 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node if (rootCode) { VoxelPositionSize rootDetails; voxelDetailsForCode(rootCode, rootDetails); - AABox serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); + AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); serverBounds.scale(TREE_SCALE); - ViewFrustum::location serverFrustumLocation = _viewFrustum.boxInFrustum(serverBounds); + ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds); if (serverFrustumLocation != ViewFrustum::OUTSIDE) { inViewServers++; @@ -2142,10 +2142,10 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node if (rootCode) { VoxelPositionSize rootDetails; voxelDetailsForCode(rootCode, rootDetails); - AABox serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); + AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); serverBounds.scale(TREE_SCALE); - ViewFrustum::location serverFrustumLocation = _viewFrustum.boxInFrustum(serverBounds); + ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds); if (serverFrustumLocation != ViewFrustum::OUTSIDE) { inView = true; } else { diff --git a/interface/src/models/ModelTreeRenderer.cpp b/interface/src/models/ModelTreeRenderer.cpp index 0f9da86887..17d11c267d 100644 --- a/interface/src/models/ModelTreeRenderer.cpp +++ b/interface/src/models/ModelTreeRenderer.cpp @@ -73,6 +73,42 @@ Model* ModelTreeRenderer::getModel(const ModelItem& modelItem) { return model; } +void calculateRotatedExtents(Extents& extents, const glm::quat& rotation) { + glm::vec3 bottomLeftNear(extents.minimum.x, extents.minimum.y, extents.minimum.z); + glm::vec3 bottomRightNear(extents.maximum.x, extents.minimum.y, extents.minimum.z); + glm::vec3 bottomLeftFar(extents.minimum.x, extents.minimum.y, extents.maximum.z); + glm::vec3 bottomRightFar(extents.maximum.x, extents.minimum.y, extents.maximum.z); + glm::vec3 topLeftNear(extents.minimum.x, extents.maximum.y, extents.minimum.z); + glm::vec3 topRightNear(extents.maximum.x, extents.maximum.y, extents.minimum.z); + glm::vec3 topLeftFar(extents.minimum.x, extents.maximum.y, extents.maximum.z); + glm::vec3 topRightFar(extents.maximum.x, extents.maximum.y, extents.maximum.z); + + glm::vec3 bottomLeftNearRotated = rotation * bottomLeftNear; + glm::vec3 bottomRightNearRotated = rotation * bottomRightNear; + glm::vec3 bottomLeftFarRotated = rotation * bottomLeftFar; + glm::vec3 bottomRightFarRotated = rotation * bottomRightFar; + glm::vec3 topLeftNearRotated = rotation * topLeftNear; + glm::vec3 topRightNearRotated = rotation * topRightNear; + glm::vec3 topLeftFarRotated = rotation * topLeftFar; + glm::vec3 topRightFarRotated = rotation * topRightFar; + + extents.minimum = glm::min(bottomLeftNearRotated, + glm::min(bottomRightNearRotated, + glm::min(bottomLeftFarRotated, + glm::min(bottomRightFarRotated, + glm::min(topLeftNearRotated, + glm::min(topRightNearRotated, + glm::min(topLeftFarRotated,topRightFarRotated))))))); + + extents.maximum = glm::max(bottomLeftNearRotated, + glm::max(bottomRightNearRotated, + glm::max(bottomLeftFarRotated, + glm::max(bottomRightFarRotated, + glm::max(topLeftNearRotated, + glm::max(topRightNearRotated, + glm::max(topLeftFarRotated,topRightFarRotated))))))); +} + void ModelTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) { args->_elementsTouched++; // actually render it here... @@ -91,7 +127,7 @@ void ModelTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) if (!isShadowMode && displayElementProxy && numberOfModels > 0) { - glm::vec3 elementCenter = modelTreeElement->getAABox().calcCenter() * (float)TREE_SCALE; + glm::vec3 elementCenter = modelTreeElement->getAACube().calcCenter() * (float)TREE_SCALE; float elementSize = modelTreeElement->getScale() * (float)TREE_SCALE; glColor3f(1.0f, 0.0f, 0.0f); glPushMatrix(); @@ -157,9 +193,9 @@ void ModelTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) for (uint16_t i = 0; i < numberOfModels; i++) { ModelItem& modelItem = modelItems[i]; // render modelItem aspoints - AABox modelBox = modelItem.getAABox(); - modelBox.scale(TREE_SCALE); - if (args->_viewFrustum->boxInFrustum(modelBox) != ViewFrustum::OUTSIDE) { + AACube modelCube = modelItem.getAACube(); + modelCube.scale(TREE_SCALE); + if (args->_viewFrustum->cubeInFrustum(modelCube) != ViewFrustum::OUTSIDE) { glm::vec3 position = modelItem.getPosition() * (float)TREE_SCALE; float radius = modelItem.getRadius() * (float)TREE_SCALE; float size = modelItem.getSize() * (float)TREE_SCALE; @@ -206,10 +242,45 @@ void ModelTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) model->render(alpha, modelRenderMode); if (!isShadowMode && displayModelBounds) { - glColor3f(0.0f, 1.0f, 0.0f); + glm::vec3 unRotatedMinimum = model->getUnscaledMeshExtents().minimum; + glm::vec3 unRotatedMaximum = model->getUnscaledMeshExtents().maximum; + glm::vec3 unRotatedExtents = unRotatedMaximum - unRotatedMinimum; + + float width = unRotatedExtents.x; + float height = unRotatedExtents.y; + float depth = unRotatedExtents.z; + + Extents rotatedExtents = model->getUnscaledMeshExtents(); + calculateRotatedExtents(rotatedExtents, rotation); + + glm::vec3 rotatedSize = rotatedExtents.maximum - rotatedExtents.minimum; + + const glm::vec3& modelScale = model->getScale(); + glPushMatrix(); glTranslatef(position.x, position.y, position.z); + + // draw the orignal bounding cube + glColor4f(1.0f, 1.0f, 0.0f, 1.0f); glutWireCube(size); + + //glColor4f(1.0f, 1.0f, 0.0f, 0.5f); + //glutWireSphere(radius, 15, 15); + + // draw the rotated bounding cube + glColor4f(0.0f, 0.0f, 1.0f, 1.0f); + glPushMatrix(); + glScalef(rotatedSize.x * modelScale.x, rotatedSize.y * modelScale.y, rotatedSize.z * modelScale.z); + glutWireCube(1.0); + glPopMatrix(); + + // draw the model relative bounding box + glm::vec3 axis = glm::axis(rotation); + glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); + glScalef(width * modelScale.x, height * modelScale.y, depth * modelScale.z); + glColor3f(0.0f, 1.0f, 0.0f); + glutWireCube(1.0); + glPopMatrix(); } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 900d7ff951..044effbccb 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -987,8 +987,9 @@ void Model::scaleToFit() { // size is our "target size in world space" // we need to set our model scale so that the extents of the mesh, fit in a cube that size... glm::vec3 dimensions = modelMeshExtents.maximum - modelMeshExtents.minimum; - float maxDimension = glm::max(glm::max(dimensions.x, dimensions.y), dimensions.z); - float maxScale = _scaleToFitLargestDimension / maxDimension; + const float SQRT_THREE = 1.733; // sqrt(3) + float maxDimensionRotated = SQRT_THREE * glm::max(glm::max(dimensions.x, dimensions.y), dimensions.z); + float maxScale = _scaleToFitLargestDimension / maxDimensionRotated; glm::vec3 scale(maxScale, maxScale, maxScale); setScaleInternal(scale); _scaledToFit = true; diff --git a/interface/src/ui/NodeBounds.cpp b/interface/src/ui/NodeBounds.cpp index c4139f39c5..f0e4a25f49 100644 --- a/interface/src/ui/NodeBounds.cpp +++ b/interface/src/ui/NodeBounds.cpp @@ -81,7 +81,7 @@ void NodeBounds::draw() { glm::vec3 location(rootDetails.x, rootDetails.y, rootDetails.z); location *= (float)TREE_SCALE; - AABox serverBounds(location, rootDetails.s * TREE_SCALE); + AACube serverBounds(location, rootDetails.s * TREE_SCALE); glm::vec3 center = serverBounds.getVertex(BOTTOM_RIGHT_NEAR) + ((serverBounds.getVertex(TOP_LEFT_FAR) - serverBounds.getVertex(BOTTOM_RIGHT_NEAR)) / 2.0f); diff --git a/interface/src/ui/OctreeStatsDialog.cpp b/interface/src/ui/OctreeStatsDialog.cpp index ceeb2cf2d7..bd2abba325 100644 --- a/interface/src/ui/OctreeStatsDialog.cpp +++ b/interface/src/ui/OctreeStatsDialog.cpp @@ -293,7 +293,7 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser VoxelPositionSize rootDetails; voxelDetailsForCode(rootCode, rootDetails); - AABox serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); + AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); serverBounds.scale(TREE_SCALE); serverDetails << " jurisdiction: " << qPrintable(rootCodeHex) diff --git a/libraries/models/src/ModelItem.h b/libraries/models/src/ModelItem.h index 838dbc0fc8..284203555d 100644 --- a/libraries/models/src/ModelItem.h +++ b/libraries/models/src/ModelItem.h @@ -198,7 +198,7 @@ public: float getSize() const { return _radius * 2.0f; } /// get maximum dimension in domain scale units (0.0 - 1.0) - AABox getAABox() const { return AABox(getMinimumPoint(), getSize()); } + AACube getAACube() const { return AACube(getMinimumPoint(), getSize()); } // model related properties bool hasModel() const { return !_modelURL.isEmpty(); } diff --git a/libraries/models/src/ModelTree.cpp b/libraries/models/src/ModelTree.cpp index 637079560b..c492ed14ad 100644 --- a/libraries/models/src/ModelTree.cpp +++ b/libraries/models/src/ModelTree.cpp @@ -116,8 +116,8 @@ void ModelTree::storeModel(const ModelItem& model, const SharedNodePointer& send // if we didn't find it in the tree, then store it... if (!theOperator.wasFound()) { - AABox modelBox = model.getAABox(); - ModelTreeElement* element = (ModelTreeElement*)getOrCreateChildElementContaining(model.getAABox()); + AACube modelCube = model.getAACube(); + ModelTreeElement* element = (ModelTreeElement*)getOrCreateChildElementContaining(model.getAACube()); element->storeModel(model); // In the case where we stored it, we also need to mark the entire "path" down to the model as @@ -270,7 +270,7 @@ bool ModelTree::findNearPointOperation(OctreeElement* element, void* extraData) ModelTreeElement* modelTreeElement = static_cast(element); glm::vec3 penetration; - bool sphereIntersection = modelTreeElement->getAABox().findSpherePenetration(args->position, + bool sphereIntersection = modelTreeElement->getAACube().findSpherePenetration(args->position, args->targetRadius, penetration); // If this modelTreeElement contains the point, then search it... @@ -320,7 +320,7 @@ public: bool ModelTree::findInSphereOperation(OctreeElement* element, void* extraData) { FindAllNearPointArgs* args = static_cast(extraData); glm::vec3 penetration; - bool sphereIntersection = element->getAABox().findSpherePenetration(args->position, + bool sphereIntersection = element->getAACube().findSpherePenetration(args->position, args->targetRadius, penetration); // If this element contains the point, then search it... @@ -343,31 +343,31 @@ void ModelTree::findModels(const glm::vec3& center, float radius, QVector _foundModels; }; -bool ModelTree::findInBoxForUpdateOperation(OctreeElement* element, void* extraData) { - FindModelsInBoxArgs* args = static_cast< FindModelsInBoxArgs*>(extraData); - const AABox& elementBox = element->getAABox(); - if (elementBox.touches(args->_box)) { +bool ModelTree::findInCubeForUpdateOperation(OctreeElement* element, void* extraData) { + FindModelsInCubeArgs* args = static_cast< FindModelsInCubeArgs*>(extraData); + const AACube& elementCube = element->getAACube(); + if (elementCube.touches(args->_cube)) { ModelTreeElement* modelTreeElement = static_cast(element); - modelTreeElement->getModelsForUpdate(args->_box, args->_foundModels); + modelTreeElement->getModelsForUpdate(args->_cube, args->_foundModels); return true; } return false; } -void ModelTree::findModelsForUpdate(const AABox& box, QVector foundModels) { - FindModelsInBoxArgs args(box); +void ModelTree::findModelsForUpdate(const AACube& cube, QVector foundModels) { + FindModelsInCubeArgs args(cube); lockForRead(); - recurseTreeWithOperation(findInBoxForUpdateOperation, &args); + recurseTreeWithOperation(findInCubeForUpdateOperation, &args); unlock(); // swap the two lists of model pointers instead of copy foundModels.swap(args._foundModels); @@ -507,7 +507,7 @@ void ModelTree::update() { bool shouldDie = args._movingModels[i].getShouldDie(); // if the particle is still inside our total bounds, then re-add it - AABox treeBounds = getRoot()->getAABox(); + AACube treeBounds = getRoot()->getAACube(); if (!shouldDie && treeBounds.contains(args._movingModels[i].getPosition())) { storeModel(args._movingModels[i]); diff --git a/libraries/models/src/ModelTree.h b/libraries/models/src/ModelTree.h index b8df1c1a22..596ca9074d 100644 --- a/libraries/models/src/ModelTree.h +++ b/libraries/models/src/ModelTree.h @@ -58,11 +58,11 @@ public: /// \remark Side effect: any initial contents in foundModels will be lost void findModels(const glm::vec3& center, float radius, QVector& foundModels); - /// finds all models that touch a box - /// \param box the query box + /// finds all models that touch a cube + /// \param cube the query cube /// \param foundModels[out] vector of non-const ModelItem* /// \remark Side effect: any initial contents in models will be lost - void findModelsForUpdate(const AABox& box, QVector foundModels); + void findModelsForUpdate(const AACube& cube, QVector foundModels); void addNewlyCreatedHook(NewlyCreatedModelHook* hook); void removeNewlyCreatedHook(NewlyCreatedModelHook* hook); @@ -86,7 +86,7 @@ private: static bool findByIDOperation(OctreeElement* element, void* extraData); static bool findAndDeleteOperation(OctreeElement* element, void* extraData); static bool findAndUpdateModelItemIDOperation(OctreeElement* element, void* extraData); - static bool findInBoxForUpdateOperation(OctreeElement* element, void* extraData); + static bool findInCubeForUpdateOperation(OctreeElement* element, void* extraData); void notifyNewlyCreatedModel(const ModelItem& newModel, const SharedNodePointer& senderNode); diff --git a/libraries/models/src/ModelTreeElement.cpp b/libraries/models/src/ModelTreeElement.cpp index 3caaf3a14c..4398e2cb3c 100644 --- a/libraries/models/src/ModelTreeElement.cpp +++ b/libraries/models/src/ModelTreeElement.cpp @@ -57,9 +57,9 @@ bool ModelTreeElement::appendElementData(OctreePacketData* packetData, EncodeBit for (uint16_t i = 0; i < _modelItems->size(); i++) { if (params.viewFrustum) { const ModelItem& model = (*_modelItems)[i]; - AABox modelBox = model.getAABox(); - modelBox.scale(TREE_SCALE); - if (params.viewFrustum->boxInFrustum(modelBox) != ViewFrustum::OUTSIDE) { + AACube modelCube = model.getAACube(); + modelCube.scale(TREE_SCALE); + if (params.viewFrustum->cubeInFrustum(modelCube) != ViewFrustum::OUTSIDE) { indexesOfModelsToInclude << i; numberOfModels++; } @@ -86,18 +86,18 @@ bool ModelTreeElement::appendElementData(OctreePacketData* packetData, EncodeBit bool ModelTreeElement::containsModelBounds(const ModelItem& model) const { glm::vec3 clampedMin = glm::clamp(model.getMinimumPoint(), 0.0f, 1.0f); glm::vec3 clampedMax = glm::clamp(model.getMaximumPoint(), 0.0f, 1.0f); - return _box.contains(clampedMin) && _box.contains(clampedMax); + return _cube.contains(clampedMin) && _cube.contains(clampedMax); } bool ModelTreeElement::bestFitModelBounds(const ModelItem& model) const { glm::vec3 clampedMin = glm::clamp(model.getMinimumPoint(), 0.0f, 1.0f); glm::vec3 clampedMax = glm::clamp(model.getMaximumPoint(), 0.0f, 1.0f); - if (_box.contains(clampedMin) && _box.contains(clampedMax)) { + if (_cube.contains(clampedMin) && _cube.contains(clampedMax)) { int childForMinimumPoint = getMyChildContainingPoint(clampedMin); int childForMaximumPoint = getMyChildContainingPoint(clampedMax); // if this is a really small box, then it's close enough! - if (_box.getScale() <= SMALLEST_REASONABLE_OCTREE_ELEMENT_SCALE) { + if (_cube.getScale() <= SMALLEST_REASONABLE_OCTREE_ELEMENT_SCALE) { return true; } // If I contain both the minimum and maximum point, but two different children of mine @@ -282,18 +282,18 @@ void ModelTreeElement::getModels(const glm::vec3& searchPosition, float searchRa } } -void ModelTreeElement::getModelsForUpdate(const AABox& box, QVector& foundModels) { +void ModelTreeElement::getModelsForUpdate(const AACube& box, QVector& foundModels) { QList::iterator modelItr = _modelItems->begin(); QList::iterator modelEnd = _modelItems->end(); - AABox modelBox; + AACube modelCube; while(modelItr != modelEnd) { ModelItem* model = &(*modelItr); float radius = model->getRadius(); - // NOTE: we actually do box-box collision queries here, which is sloppy but good enough for now - // TODO: decide whether to replace modelBox-box query with sphere-box (requires a square root + // NOTE: we actually do cube-cube collision queries here, which is sloppy but good enough for now + // TODO: decide whether to replace modelCube-cube query with sphere-cube (requires a square root // but will be slightly more accurate). - modelBox.setBox(model->getPosition() - glm::vec3(radius), 2.f * radius); - if (modelBox.touches(_box)) { + modelCube.setBox(model->getPosition() - glm::vec3(radius), 2.f * radius); + if (modelCube.touches(_cube)) { foundModels.push_back(model); } ++modelItr; diff --git a/libraries/models/src/ModelTreeElement.h b/libraries/models/src/ModelTreeElement.h index 83b745206f..acb594c33d 100644 --- a/libraries/models/src/ModelTreeElement.h +++ b/libraries/models/src/ModelTreeElement.h @@ -125,7 +125,7 @@ public: /// finds all models that touch a box /// \param box the query box /// \param models[out] vector of non-const ModelItem* - void getModelsForUpdate(const AABox& box, QVector& foundModels); + void getModelsForUpdate(const AACube& box, QVector& foundModels); const ModelItem* getModelWithID(uint32_t id) const; diff --git a/libraries/octree/src/AABox.cpp b/libraries/octree/src/AABox.cpp index 51b31d4466..7aa4d76134 100644 --- a/libraries/octree/src/AABox.cpp +++ b/libraries/octree/src/AABox.cpp @@ -9,27 +9,31 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AABox.h" +#include "AACube.h" +#include "GeometryUtil.h" #include "SharedUtil.h" -#include "AABox.h" -#include "GeometryUtil.h" - AABox::AABox(const glm::vec3& corner, float size) : - _corner(corner), _scale(size) { + _corner(corner), _scale(size, size, size) { }; -AABox::AABox() : _corner(0,0,0), _scale(0) { +AABox::AABox(const glm::vec3& corner, const glm::vec3& dimensions) : + _corner(corner), _scale(dimensions) { +}; + +AABox::AABox() : _corner(0.0f, 0.0f, 0.0f), _scale(0.0f, 0.0f, 0.0f) { }; glm::vec3 AABox::calcCenter() const { glm::vec3 center(_corner); - center += (glm::vec3(_scale, _scale, _scale) * 0.5f); + center += (_scale * 0.5f); return center; } glm::vec3 AABox::calcTopFarLeft() const { glm::vec3 topFarLeft(_corner); - topFarLeft += glm::vec3(_scale, _scale, _scale); + topFarLeft += _scale; return topFarLeft; }; @@ -41,26 +45,31 @@ void AABox::scale(float scale) { glm::vec3 AABox::getVertex(BoxVertex vertex) const { switch (vertex) { case BOTTOM_LEFT_NEAR: - return _corner + glm::vec3(_scale, 0, 0); + return _corner + glm::vec3(_scale.x, 0, 0); case BOTTOM_RIGHT_NEAR: return _corner; case TOP_RIGHT_NEAR: - return _corner + glm::vec3(0, _scale, 0); + return _corner + glm::vec3(0, _scale.y, 0); case TOP_LEFT_NEAR: - return _corner + glm::vec3(_scale, _scale, 0); + return _corner + glm::vec3(_scale.x, _scale.y, 0); case BOTTOM_LEFT_FAR: - return _corner + glm::vec3(_scale, 0, _scale); + return _corner + glm::vec3(_scale.x, 0, _scale.z); case BOTTOM_RIGHT_FAR: - return _corner + glm::vec3(0, 0, _scale); + return _corner + glm::vec3(0, 0, _scale.z); case TOP_RIGHT_FAR: - return _corner + glm::vec3(0, _scale, _scale); + return _corner + glm::vec3(0, _scale.y, _scale.z); default: //quiet windows warnings case TOP_LEFT_FAR: - return _corner + glm::vec3(_scale, _scale, _scale); + return _corner + _scale; } } void AABox::setBox(const glm::vec3& corner, float scale) { + _corner = corner; + _scale = glm::vec3(scale, scale, scale); +} + +void AABox::setBox(const glm::vec3& corner, const glm::vec3& scale) { _corner = corner; _scale = scale; } @@ -68,13 +77,13 @@ void AABox::setBox(const glm::vec3& corner, float scale) { glm::vec3 AABox::getVertexP(const glm::vec3& normal) const { glm::vec3 result = _corner; if (normal.x > 0) { - result.x += _scale; + result.x += _scale.x; } if (normal.y > 0) { - result.y += _scale; + result.y += _scale.y; } if (normal.z > 0) { - result.z += _scale; + result.z += _scale.z; } return result; } @@ -83,15 +92,15 @@ glm::vec3 AABox::getVertexN(const glm::vec3& normal) const { glm::vec3 result = _corner; if (normal.x < 0) { - result.x += _scale; + result.x += _scale.x; } if (normal.y < 0) { - result.y += _scale; + result.y += _scale.y; } if (normal.z < 0) { - result.z += _scale; + result.z += _scale.z; } return result; @@ -103,9 +112,9 @@ static bool isWithin(float value, float corner, float size) { } bool AABox::contains(const glm::vec3& point) const { - return isWithin(point.x, _corner.x, _scale) && - isWithin(point.y, _corner.y, _scale) && - isWithin(point.z, _corner.z, _scale); + return isWithin(point.x, _corner.x, _scale.x) && + isWithin(point.y, _corner.y, _scale.y) && + isWithin(point.z, _corner.z, _scale.z); } bool AABox::contains(const AABox& otherBox) const { @@ -119,11 +128,33 @@ bool AABox::contains(const AABox& otherBox) const { } bool AABox::touches(const AABox& otherBox) const { - glm::vec3 relativeCenter = _corner - otherBox._corner + (glm::vec3(_scale - otherBox._scale) * 0.5f); - float totalHalfScale = 0.5f * (_scale + otherBox._scale); - return fabs(relativeCenter.x) <= totalHalfScale && - fabs(relativeCenter.y) <= totalHalfScale && - fabs(relativeCenter.z) <= totalHalfScale; + glm::vec3 relativeCenter = _corner - otherBox._corner + ((_scale - otherBox._scale) * 0.5f); + + glm::vec3 totalHalfScale = (_scale + otherBox._scale) * 0.5f; + + return fabs(relativeCenter.x) <= totalHalfScale.x && + fabs(relativeCenter.y) <= totalHalfScale.y && + fabs(relativeCenter.z) <= totalHalfScale.z; +} + +bool AABox::contains(const AACube& otherCube) const { + for (int v = BOTTOM_LEFT_NEAR; v < TOP_LEFT_FAR; v++) { + glm::vec3 vertex = otherCube.getVertex((BoxVertex)v); + if (!contains(vertex)) { + return false; + } + } + return true; +} + +bool AABox::touches(const AACube& otherCube) const { + glm::vec3 relativeCenter = _corner - otherCube.getCorner() + ((_scale - otherCube.getDimensions()) * 0.5f); + + glm::vec3 totalHalfScale = (_scale + otherCube.getDimensions()) * 0.5f; + + return fabs(relativeCenter.x) <= totalHalfScale.x && + fabs(relativeCenter.y) <= totalHalfScale.y && + fabs(relativeCenter.z) <= totalHalfScale.z; } // determines whether a value is within the expanded extents @@ -132,9 +163,9 @@ static bool isWithinExpanded(float value, float corner, float size, float expans } bool AABox::expandedContains(const glm::vec3& point, float expansion) const { - return isWithinExpanded(point.x, _corner.x, _scale, expansion) && - isWithinExpanded(point.y, _corner.y, _scale, expansion) && - isWithinExpanded(point.z, _corner.z, _scale, expansion); + return isWithinExpanded(point.x, _corner.x, _scale.x, expansion) && + isWithinExpanded(point.y, _corner.y, _scale.y, expansion) && + isWithinExpanded(point.z, _corner.z, _scale.z, expansion); } // finds the intersection between a ray and the facing plane on one axis @@ -156,7 +187,7 @@ bool AABox::expandedIntersectsSegment(const glm::vec3& start, const glm::vec3& e } // check each axis glm::vec3 expandedCorner = _corner - glm::vec3(expansion, expansion, expansion); - glm::vec3 expandedSize = glm::vec3(_scale, _scale, _scale) + glm::vec3(expansion, expansion, expansion) * 2.0f; + glm::vec3 expandedSize = _scale + glm::vec3(expansion, expansion, expansion) * 2.0f; glm::vec3 direction = end - start; float axisDistance; return (findIntersection(start.x, direction.x, expandedCorner.x, expandedSize.x, axisDistance) && @@ -181,23 +212,23 @@ bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direct } // check each axis float axisDistance; - if ((findIntersection(origin.x, direction.x, _corner.x, _scale, axisDistance) && axisDistance >= 0 && - isWithin(origin.y + axisDistance*direction.y, _corner.y, _scale) && - isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale))) { + if ((findIntersection(origin.x, direction.x, _corner.x, _scale.x, axisDistance) && axisDistance >= 0 && + isWithin(origin.y + axisDistance*direction.y, _corner.y, _scale.y) && + isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale.z))) { distance = axisDistance; face = direction.x > 0 ? MIN_X_FACE : MAX_X_FACE; return true; } - if ((findIntersection(origin.y, direction.y, _corner.y, _scale, axisDistance) && axisDistance >= 0 && - isWithin(origin.x + axisDistance*direction.x, _corner.x, _scale) && - isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale))) { + if ((findIntersection(origin.y, direction.y, _corner.y, _scale.y, axisDistance) && axisDistance >= 0 && + isWithin(origin.x + axisDistance*direction.x, _corner.x, _scale.x) && + isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale.z))) { distance = axisDistance; face = direction.y > 0 ? MIN_Y_FACE : MAX_Y_FACE; return true; } - if ((findIntersection(origin.z, direction.z, _corner.z, _scale, axisDistance) && axisDistance >= 0 && - isWithin(origin.y + axisDistance*direction.y, _corner.y, _scale) && - isWithin(origin.x + axisDistance*direction.x, _corner.x, _scale))) { + if ((findIntersection(origin.z, direction.z, _corner.z, _scale.z, axisDistance) && axisDistance >= 0 && + isWithin(origin.y + axisDistance*direction.y, _corner.y, _scale.y) && + isWithin(origin.x + axisDistance*direction.x, _corner.x, _scale.x))) { distance = axisDistance; face = direction.z > 0 ? MIN_Z_FACE : MAX_Z_FACE; return true; @@ -260,28 +291,28 @@ glm::vec3 AABox::getClosestPointOnFace(const glm::vec3& point, BoxFace face) con switch (face) { case MIN_X_FACE: return glm::clamp(point, glm::vec3(_corner.x, _corner.y, _corner.z), - glm::vec3(_corner.x, _corner.y + _scale, _corner.z + _scale)); + glm::vec3(_corner.x, _corner.y + _scale.y, _corner.z + _scale.z)); case MAX_X_FACE: - return glm::clamp(point, glm::vec3(_corner.x + _scale, _corner.y, _corner.z), - glm::vec3(_corner.x + _scale, _corner.y + _scale, _corner.z + _scale)); + return glm::clamp(point, glm::vec3(_corner.x + _scale.x, _corner.y, _corner.z), + glm::vec3(_corner.x + _scale.x, _corner.y + _scale.y, _corner.z + _scale.z)); case MIN_Y_FACE: return glm::clamp(point, glm::vec3(_corner.x, _corner.y, _corner.z), - glm::vec3(_corner.x + _scale, _corner.y, _corner.z + _scale)); + glm::vec3(_corner.x + _scale.x, _corner.y, _corner.z + _scale.z)); case MAX_Y_FACE: - return glm::clamp(point, glm::vec3(_corner.x, _corner.y + _scale, _corner.z), - glm::vec3(_corner.x + _scale, _corner.y + _scale, _corner.z + _scale)); + return glm::clamp(point, glm::vec3(_corner.x, _corner.y + _scale.y, _corner.z), + glm::vec3(_corner.x + _scale.x, _corner.y + _scale.y, _corner.z + _scale.z)); case MIN_Z_FACE: return glm::clamp(point, glm::vec3(_corner.x, _corner.y, _corner.z), - glm::vec3(_corner.x + _scale, _corner.y + _scale, _corner.z)); + glm::vec3(_corner.x + _scale.z, _corner.y + _scale.y, _corner.z)); default: //quiet windows warnings case MAX_Z_FACE: - return glm::clamp(point, glm::vec3(_corner.x, _corner.y, _corner.z + _scale), - glm::vec3(_corner.x + _scale, _corner.y + _scale, _corner.z + _scale)); + return glm::clamp(point, glm::vec3(_corner.x, _corner.y, _corner.z + _scale.z), + glm::vec3(_corner.x + _scale.x, _corner.y + _scale.y, _corner.z + _scale.z)); } } @@ -331,7 +362,7 @@ glm::vec3 AABox::getClosestPointOnFace(const glm::vec4& origin, const glm::vec4& glm::vec4 thirdAxisMaxPlane = getPlane((BoxFace)(thirdAxis * 2 + 1)); glm::vec4 offset = glm::vec4(0.0f, 0.0f, 0.0f, - glm::dot(glm::vec3(secondAxisMaxPlane + thirdAxisMaxPlane), glm::vec3(_scale, _scale, _scale)) * 0.5f); + glm::dot(glm::vec3(secondAxisMaxPlane + thirdAxisMaxPlane), _scale) * 0.5f); glm::vec4 diagonals[] = { secondAxisMinPlane + thirdAxisMaxPlane + offset, secondAxisMaxPlane + thirdAxisMaxPlane + offset }; @@ -355,12 +386,12 @@ glm::vec3 AABox::getClosestPointOnFace(const glm::vec4& origin, const glm::vec4& glm::vec4 AABox::getPlane(BoxFace face) const { switch (face) { case MIN_X_FACE: return glm::vec4(-1.0f, 0.0f, 0.0f, _corner.x); - case MAX_X_FACE: return glm::vec4(1.0f, 0.0f, 0.0f, -_corner.x - _scale); + case MAX_X_FACE: return glm::vec4(1.0f, 0.0f, 0.0f, -_corner.x - _scale.x); case MIN_Y_FACE: return glm::vec4(0.0f, -1.0f, 0.0f, _corner.y); - case MAX_Y_FACE: return glm::vec4(0.0f, 1.0f, 0.0f, -_corner.y - _scale); + case MAX_Y_FACE: return glm::vec4(0.0f, 1.0f, 0.0f, -_corner.y - _scale.y); case MIN_Z_FACE: return glm::vec4(0.0f, 0.0f, -1.0f, _corner.z); default: //quiet windows warnings - case MAX_Z_FACE: return glm::vec4(0.0f, 0.0f, 1.0f, -_corner.z - _scale); + case MAX_Z_FACE: return glm::vec4(0.0f, 0.0f, 1.0f, -_corner.z - _scale.z); } } diff --git a/libraries/octree/src/AABox.h b/libraries/octree/src/AABox.h index 1aa0849b70..ef0e535b38 100644 --- a/libraries/octree/src/AABox.h +++ b/libraries/octree/src/AABox.h @@ -17,60 +17,43 @@ #include -enum BoxFace { - MIN_X_FACE, - MAX_X_FACE, - MIN_Y_FACE, - MAX_Y_FACE, - MIN_Z_FACE, - MAX_Z_FACE, - UNKNOWN_FACE -}; +#include "BoxBase.h" -enum BoxVertex { - BOTTOM_LEFT_NEAR = 0, - BOTTOM_RIGHT_NEAR = 1, - TOP_RIGHT_NEAR = 2, - TOP_LEFT_NEAR = 3, - BOTTOM_LEFT_FAR = 4, - BOTTOM_RIGHT_FAR = 5, - TOP_RIGHT_FAR = 6, - TOP_LEFT_FAR = 7 -}; - -const int FACE_COUNT = 6; +class AACube; class AABox { public: AABox(const glm::vec3& corner, float size); + AABox(const glm::vec3& corner, const glm::vec3& dimensions); AABox(); ~AABox() {}; - void setBox(const glm::vec3& corner, float scale); + void setBox(const glm::vec3& corner, const glm::vec3& scale); - // for use in frustum computations - glm::vec3 getVertexP(const glm::vec3& normal) const; - glm::vec3 getVertexN(const glm::vec3& normal) const; + void setBox(const glm::vec3& corner, float scale); + glm::vec3 getVertexP(const glm::vec3& normal) const; + glm::vec3 getVertexN(const glm::vec3& normal) const; + void scale(float scale); + const glm::vec3& getCorner() const { return _corner; } + const glm::vec3& getScale() const { return _scale; } + const glm::vec3& getDimensions() const { return _scale; } - void scale(float scale); + glm::vec3 calcCenter() const; + glm::vec3 calcTopFarLeft() const; + glm::vec3 getVertex(BoxVertex vertex) const; + bool contains(const glm::vec3& point) const; + bool contains(const AABox& otherBox) const; + bool touches(const AABox& otherBox) const; - const glm::vec3& getCorner() const { return _corner; }; - float getScale() const { return _scale; } + bool contains(const AACube& otherCube) const; + bool touches(const AACube& otherCube) const; - glm::vec3 calcCenter() const; - glm::vec3 calcTopFarLeft() const; - - glm::vec3 getVertex(BoxVertex vertex) const; - - bool contains(const glm::vec3& point) const; - bool contains(const AABox& otherBox) const; - 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, BoxFace& face) 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; + 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, BoxFace& face) 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; private: glm::vec3 getClosestPointOnFace(const glm::vec3& point, BoxFace face) const; @@ -80,7 +63,7 @@ private: static BoxFace getOppositeFace(BoxFace face); glm::vec3 _corner; - float _scale; + glm::vec3 _scale; }; #endif // hifi_AABox_h diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index fd0cbcff7c..ae00bf5a58 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -583,7 +583,7 @@ OctreeElement* Octree::getOrCreateChildElementAt(float x, float y, float z, floa return getRoot()->getOrCreateChildElementAt(x, y, z, s); } -OctreeElement* Octree::getOrCreateChildElementContaining(const AABox& box) { +OctreeElement* Octree::getOrCreateChildElementContaining(const AACube& box) { return getRoot()->getOrCreateChildElementContaining(box); } @@ -601,7 +601,7 @@ public: bool findRayIntersectionOp(OctreeElement* element, void* extraData) { RayArgs* args = static_cast(extraData); - AABox box = element->getAABox(); + AACube box = element->getAACube(); float distance; BoxFace face; if (!box.findRayIntersection(args->origin, args->direction, distance, face)) { @@ -664,7 +664,7 @@ bool findSpherePenetrationOp(OctreeElement* element, void* extraData) { SphereArgs* args = static_cast(extraData); // coarse check against bounds - const AABox& box = element->getAABox(); + const AACube& box = element->getAACube(); if (!box.expandedContains(args->center, args->radius)) { return false; } @@ -743,7 +743,7 @@ bool findCapsulePenetrationOp(OctreeElement* element, void* extraData) { CapsuleArgs* args = static_cast(extraData); // coarse check against bounds - const AABox& box = element->getAABox(); + const AACube& box = element->getAACube(); if (!box.expandedIntersectsSegment(args->start, args->end, args->radius)) { return false; } @@ -764,7 +764,7 @@ bool findShapeCollisionsOp(OctreeElement* element, void* extraData) { ShapeArgs* args = static_cast(extraData); // coarse check against bounds - AABox cube = element->getAABox(); + AACube cube = element->getAACube(); cube.scale(TREE_SCALE); if (!cube.expandedContains(args->shape->getPosition(), args->shape->getBoundingRadius())) { return false; @@ -858,7 +858,7 @@ public: // Find the smallest colored voxel enclosing a point (if there is one) bool getElementEnclosingOperation(OctreeElement* element, void* extraData) { GetElementEnclosingArgs* args = static_cast(extraData); - AABox elementBox = element->getAABox(); + AACube elementBox = element->getAACube(); if (elementBox.contains(args->point)) { if (element->hasContent() && element->isLeaf()) { // we've reached a solid leaf containing the point, return the element. @@ -1117,7 +1117,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element, // If the user also asked for occlusion culling, check if this element is occluded, but only if it's not a leaf. // leaf occlusion is handled down below when we check child nodes if (params.wantOcclusionCulling && !element->isLeaf()) { - AABox voxelBox = element->getAABox(); + AACube voxelBox = element->getAACube(); voxelBox.scale(TREE_SCALE); OctreeProjectedPolygon* voxelPolygon = new OctreeProjectedPolygon(params.viewFrustum->getProjectedPolygon(voxelBox)); @@ -1250,7 +1250,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element, if (params.wantOcclusionCulling && childElement->isLeaf()) { // Don't check occlusion here, just add them to our distance ordered array... - AABox voxelBox = childElement->getAABox(); + AACube voxelBox = childElement->getAACube(); voxelBox.scale(TREE_SCALE); OctreeProjectedPolygon* voxelPolygon = new OctreeProjectedPolygon( params.viewFrustum->getProjectedPolygon(voxelBox)); diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 81a9823dd5..496b4016fe 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -236,7 +236,7 @@ public: OctreeElement* getOctreeEnclosingElementAt(float x, float y, float z, float s) const; OctreeElement* getOrCreateChildElementAt(float x, float y, float z, float s); - OctreeElement* getOrCreateChildElementContaining(const AABox& box); + OctreeElement* getOrCreateChildElementContaining(const AACube& box); void recurseTreeWithOperation(RecurseOctreeOperation operation, void* extraData = NULL); void recurseTreeWithPostOperation(RecurseOctreeOperation operation, void* extraData = NULL); diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index 90938ddff3..8f52fec179 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -19,7 +19,7 @@ #include #include -#include "AABox.h" +#include "AACube.h" #include "OctalCode.h" #include "OctreeConstants.h" #include "OctreeElement.h" @@ -93,7 +93,7 @@ void OctreeElement::init(unsigned char * octalCode) { _isDirty = true; _shouldRender = false; _sourceUUIDKey = 0; - calculateAABox(); + calculateAACube(); markWithChangedTime(); } @@ -190,15 +190,15 @@ void OctreeElement::setShouldRender(bool shouldRender) { } } -void OctreeElement::calculateAABox() { +void OctreeElement::calculateAACube() { glm::vec3 corner; - // copy corner into box + // copy corner into cube copyFirstVertexForCode(getOctalCode(),(float*)&corner); // this tells you the "size" of the voxel float voxelScale = 1 / powf(2, numberOfThreeBitSectionsInCode(getOctalCode())); - _box.setBox(corner,voxelScale); + _cube.setBox(corner,voxelScale); } void OctreeElement::deleteChildAtIndex(int childIndex) { @@ -1178,7 +1178,7 @@ void OctreeElement::printDebugDetails(const char* label) const { QString resultString; resultString.sprintf("%s - Voxel at corner=(%f,%f,%f) size=%f\n isLeaf=%s isDirty=%s shouldRender=%s\n children=", label, - _box.getCorner().x, _box.getCorner().y, _box.getCorner().z, _box.getScale(), + _cube.getCorner().x, _cube.getCorner().y, _cube.getCorner().z, _cube.getScale(), debug::valueOf(isLeaf()), debug::valueOf(isDirty()), debug::valueOf(getShouldRender())); elementDebug << resultString; @@ -1192,9 +1192,9 @@ float OctreeElement::getEnclosingRadius() const { } ViewFrustum::location OctreeElement::inFrustum(const ViewFrustum& viewFrustum) const { - AABox box = _box; // use temporary box so we can scale it - box.scale(TREE_SCALE); - return viewFrustum.boxInFrustum(box); + AACube cube = _cube; // use temporary cube so we can scale it + cube.scale(TREE_SCALE); + return viewFrustum.cubeInFrustum(cube); } // There are two types of nodes for which we want to "render" @@ -1228,27 +1228,27 @@ bool OctreeElement::calculateShouldRender(const ViewFrustum* viewFrustum, float // does as much math as possible in voxel scale and then scales up to TREE_SCALE at end float OctreeElement::furthestDistanceToCamera(const ViewFrustum& viewFrustum) const { glm::vec3 furthestPoint; - viewFrustum.getFurthestPointFromCameraVoxelScale(getAABox(), furthestPoint); + viewFrustum.getFurthestPointFromCameraVoxelScale(getAACube(), furthestPoint); glm::vec3 temp = viewFrustum.getPositionVoxelScale() - furthestPoint; float distanceToFurthestPoint = sqrtf(glm::dot(temp, temp)); return distanceToFurthestPoint * (float)TREE_SCALE; } float OctreeElement::distanceToCamera(const ViewFrustum& viewFrustum) const { - glm::vec3 center = _box.calcCenter() * (float)TREE_SCALE; + glm::vec3 center = _cube.calcCenter() * (float)TREE_SCALE; glm::vec3 temp = viewFrustum.getPosition() - center; float distanceToVoxelCenter = sqrtf(glm::dot(temp, temp)); return distanceToVoxelCenter; } float OctreeElement::distanceSquareToPoint(const glm::vec3& point) const { - glm::vec3 temp = point - _box.calcCenter(); + glm::vec3 temp = point - _cube.calcCenter(); float distanceSquare = glm::dot(temp, temp); return distanceSquare; } float OctreeElement::distanceToPoint(const glm::vec3& point) const { - glm::vec3 temp = point - _box.calcCenter(); + glm::vec3 temp = point - _cube.calcCenter(); float distance = sqrtf(glm::dot(temp, temp)); return distance; } @@ -1304,7 +1304,7 @@ void OctreeElement::notifyUpdateHooks() { bool OctreeElement::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject) const { - return _box.findSpherePenetration(center, radius, penetration); + return _cube.findSpherePenetration(center, radius, penetration); } @@ -1323,7 +1323,7 @@ OctreeElement* OctreeElement::getOrCreateChildElementAt(float x, float y, float return this; } // otherwise, we need to find which of our children we should recurse - glm::vec3 ourCenter = _box.calcCenter(); + glm::vec3 ourCenter = _cube.calcCenter(); int childIndex = CHILD_UNKNOWN; // left half @@ -1381,31 +1381,31 @@ OctreeElement* OctreeElement::getOrCreateChildElementAt(float x, float y, float } -OctreeElement* OctreeElement::getOrCreateChildElementContaining(const AABox& box) { +OctreeElement* OctreeElement::getOrCreateChildElementContaining(const AACube& cube) { OctreeElement* child = NULL; float ourScale = getScale(); - float boxScale = box.getScale(); + float cubeScale = cube.getScale(); - if(boxScale > ourScale) { + if(cubeScale > ourScale) { qDebug("UNEXPECTED -- OctreeElement::getOrCreateChildElementContaining() " - "boxScale=[%f] > ourScale=[%f] ", boxScale, ourScale); + "cubeScale=[%f] > ourScale=[%f] ", cubeScale, ourScale); } - // Determine which of our children the minimum and maximum corners of the box live in... - glm::vec3 boxCornerMinimum = box.getCorner(); - glm::vec3 boxCornerMaximum = box.calcTopFarLeft(); + // Determine which of our children the minimum and maximum corners of the cube live in... + glm::vec3 cubeCornerMinimum = cube.getCorner(); + glm::vec3 cubeCornerMaximum = cube.calcTopFarLeft(); - int childIndexBoxMinimum = getMyChildContainingPoint(boxCornerMinimum); - int childIndexBoxMaximum = getMyChildContainingPoint(boxCornerMaximum); + int childIndexCubeMinimum = getMyChildContainingPoint(cubeCornerMinimum); + int childIndexCubeMaximum = getMyChildContainingPoint(cubeCornerMaximum); - // If the minimum and maximum corners of the box are in two different children's boxes, then we are the containing element - if (childIndexBoxMinimum != childIndexBoxMaximum) { + // If the minimum and maximum corners of the cube are in two different children's cubes, then we are the containing element + if (childIndexCubeMinimum != childIndexCubeMaximum) { return this; } // otherwise, they are the same and that child should be considered as the correct element - int childIndex = childIndexBoxMinimum; // both the same... + int childIndex = childIndexCubeMinimum; // both the same... // Now, check if we have a child at that location child = getChildAtIndex(childIndex); @@ -1419,11 +1419,11 @@ OctreeElement* OctreeElement::getOrCreateChildElementContaining(const AABox& box } // Now that we have the child to recurse down, let it answer the original question... - return child->getOrCreateChildElementContaining(box); + return child->getOrCreateChildElementContaining(cube); } int OctreeElement::getMyChildContainingPoint(const glm::vec3& point) const { - glm::vec3 ourCenter = _box.calcCenter(); + glm::vec3 ourCenter = _cube.calcCenter(); int childIndex = CHILD_UNKNOWN; // left half if (point.x > ourCenter.x) { diff --git a/libraries/octree/src/OctreeElement.h b/libraries/octree/src/OctreeElement.h index 3b056fa789..24e4a4a6ac 100644 --- a/libraries/octree/src/OctreeElement.h +++ b/libraries/octree/src/OctreeElement.h @@ -20,7 +20,7 @@ #include -#include "AABox.h" +#include "AACube.h" #include "ViewFrustum.h" #include "OctreeConstants.h" @@ -116,9 +116,9 @@ public: bool safeDeepDeleteChildAtIndex(int childIndex, int recursionCount = 0); - const AABox& getAABox() const { return _box; } - const glm::vec3& getCorner() const { return _box.getCorner(); } - float getScale() const { return _box.getScale(); } + const AACube& getAACube() const { return _cube; } + const glm::vec3& getCorner() const { return _cube.getCorner(); } + float getScale() const { return _cube.getScale(); } int getLevel() const { return numberOfThreeBitSectionsInCode(getOctalCode()) + 1; } float getEnclosingRadius() const; @@ -223,7 +223,7 @@ public: OctreeElement* getOrCreateChildElementAt(float x, float y, float z, float s); - OctreeElement* getOrCreateChildElementContaining(const AABox& box); + OctreeElement* getOrCreateChildElementContaining(const AACube& box); int getMyChildContainingPoint(const glm::vec3& point) const; protected: @@ -240,11 +240,11 @@ protected: void encodeThreeOffsets(int64_t offsetOne, int64_t offsetTwo, int64_t offsetThree); void checkStoreFourChildren(OctreeElement* childOne, OctreeElement* childTwo, OctreeElement* childThree, OctreeElement* childFour); #endif - void calculateAABox(); + void calculateAACube(); void notifyDeleteHooks(); void notifyUpdateHooks(); - AABox _box; /// Client and server, axis aligned box for bounds of this voxel, 48 bytes + AACube _cube; /// Client and server, axis aligned box for bounds of this voxel, 48 bytes /// Client and server, buffer containing the octal code or a pointer to octal code for this node, 8 bytes union octalCode_t { diff --git a/libraries/octree/src/OctreeHeadlessViewer.cpp b/libraries/octree/src/OctreeHeadlessViewer.cpp index 7f19b170b9..5833cb4170 100644 --- a/libraries/octree/src/OctreeHeadlessViewer.cpp +++ b/libraries/octree/src/OctreeHeadlessViewer.cpp @@ -95,10 +95,10 @@ void OctreeHeadlessViewer::queryOctree() { if (rootCode) { VoxelPositionSize rootDetails; voxelDetailsForCode(rootCode, rootDetails); - AABox serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); + AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); serverBounds.scale(TREE_SCALE); - ViewFrustum::location serverFrustumLocation = _viewFrustum.boxInFrustum(serverBounds); + ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds); if (serverFrustumLocation != ViewFrustum::OUTSIDE) { inViewServers++; @@ -161,10 +161,10 @@ void OctreeHeadlessViewer::queryOctree() { if (rootCode) { VoxelPositionSize rootDetails; voxelDetailsForCode(rootCode, rootDetails); - AABox serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); + AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); serverBounds.scale(TREE_SCALE); - ViewFrustum::location serverFrustumLocation = _viewFrustum.boxInFrustum(serverBounds); + ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds); if (serverFrustumLocation != ViewFrustum::OUTSIDE) { inView = true; } else { diff --git a/libraries/octree/src/ViewFrustum.cpp b/libraries/octree/src/ViewFrustum.cpp index c2e38b73c9..c06cb2ea88 100644 --- a/libraries/octree/src/ViewFrustum.cpp +++ b/libraries/octree/src/ViewFrustum.cpp @@ -141,7 +141,7 @@ void ViewFrustum::calculate() { // Set up our keyhole bounding box... glm::vec3 corner = _position - _keyholeRadius; - _keyholeBoundingBox = AABox(corner,(_keyholeRadius * 2.0f)); + _keyholeBoundingCube = AACube(corner,(_keyholeRadius * 2.0f)); } void ViewFrustum::calculateOrthographic() { @@ -184,7 +184,7 @@ void ViewFrustum::calculateOrthographic() { // Set up our keyhole bounding box... glm::vec3 corner = _position - _keyholeRadius; - _keyholeBoundingBox = AABox(corner, (_keyholeRadius * 2.0f)); + _keyholeBoundingCube = AACube(corner, (_keyholeRadius * 2.0f)); } //enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE }; @@ -231,6 +231,44 @@ ViewFrustum::location ViewFrustum::sphereInKeyhole(const glm::vec3& center, floa } +// 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 @@ -238,7 +276,7 @@ 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 (!_keyholeBoundingBox.contains(box)) { + if (!_keyholeBoundingCube.contains(box)) { return OUTSIDE; } @@ -319,14 +357,14 @@ ViewFrustum::location ViewFrustum::sphereInFrustum(const glm::vec3& center, floa } -ViewFrustum::location ViewFrustum::boxInFrustum(const AABox& box) const { +ViewFrustum::location ViewFrustum::cubeInFrustum(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 = boxInKeyhole(box); + keyholeResult = cubeInKeyhole(cube); } if (keyholeResult == INSIDE) { return keyholeResult; @@ -338,10 +376,10 @@ ViewFrustum::location ViewFrustum::boxInFrustum(const AABox& box) const { // also be able to test against the cone to the bounding sphere of the box. for(int i=0; i < 6; i++) { const glm::vec3& normal = _planes[i].getNormal(); - const glm::vec3& boxVertexP = box.getVertexP(normal); + const glm::vec3& boxVertexP = cube.getVertexP(normal); float planeToBoxVertexPDistance = _planes[i].distance(boxVertexP); - const glm::vec3& boxVertexN = box.getVertexN(normal); + const glm::vec3& boxVertexN = cube.getVertexN(normal); float planeToBoxVertexNDistance = _planes[i].distance(boxVertexN); if (planeToBoxVertexPDistance < 0) { @@ -610,7 +648,7 @@ glm::vec2 ViewFrustum::projectPoint(glm::vec3 point, bool& pointInView) const { const int MAX_POSSIBLE_COMBINATIONS = 43; const int hullVertexLookup[MAX_POSSIBLE_COMBINATIONS][MAX_PROJECTED_POLYGON_VERTEX_COUNT+1] = { - // Number of vertices in shadow polygon for the visible faces, then a list of the index of each vertice from the AABox + // Number of vertices in shadow polygon for the visible faces, then a list of the index of each vertice from the AACube //0 {0}, // inside @@ -682,7 +720,7 @@ const int hullVertexLookup[MAX_POSSIBLE_COMBINATIONS][MAX_PROJECTED_POLYGON_VERT {6, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR}, // back, top, left }; -OctreeProjectedPolygon ViewFrustum::getProjectedPolygon(const AABox& box) const { +OctreeProjectedPolygon ViewFrustum::getProjectedPolygon(const AACube& box) const { const glm::vec3& bottomNearRight = box.getCorner(); glm::vec3 topFarLeft = box.calcTopFarLeft(); @@ -749,7 +787,7 @@ OctreeProjectedPolygon ViewFrustum::getProjectedPolygon(const AABox& box) const // Similar strategy to getProjectedPolygon() we use the knowledge of camera position relative to the // axis-aligned voxels to determine which of the voxels vertices must be the furthest. No need for // squares and square-roots. Just compares. -void ViewFrustum::getFurthestPointFromCamera(const AABox& box, glm::vec3& furthestPoint) const { +void ViewFrustum::getFurthestPointFromCamera(const AACube& box, glm::vec3& furthestPoint) const { const glm::vec3& bottomNearRight = box.getCorner(); float scale = box.getScale(); float halfScale = scale * 0.5f; @@ -776,7 +814,7 @@ void ViewFrustum::getFurthestPointFromCamera(const AABox& box, glm::vec3& furthe } } -void ViewFrustum::getFurthestPointFromCameraVoxelScale(const AABox& box, glm::vec3& furthestPoint) const { +void ViewFrustum::getFurthestPointFromCameraVoxelScale(const AACube& box, glm::vec3& furthestPoint) const { const glm::vec3& bottomNearRight = box.getCorner(); float scale = box.getScale(); float halfScale = scale * 0.5f; diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/octree/src/ViewFrustum.h index 4fc3bc2d8b..bed8d9c18c 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/octree/src/ViewFrustum.h @@ -18,6 +18,7 @@ #include #include "AABox.h" +#include "AACube.h" #include "Plane.h" #include "OctreeConstants.h" #include "OctreeProjectedPolygon.h" @@ -94,6 +95,7 @@ public: 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; // some frustum comparisons @@ -111,29 +113,30 @@ public: void printDebugDetails() const; glm::vec2 projectPoint(glm::vec3 point, bool& pointInView) const; - OctreeProjectedPolygon getProjectedPolygon(const AABox& box) const; - void getFurthestPointFromCamera(const AABox& box, glm::vec3& furthestPoint) const; + OctreeProjectedPolygon getProjectedPolygon(const AACube& box) const; + void getFurthestPointFromCamera(const AACube& box, glm::vec3& furthestPoint) const; // assumes box is in voxel scale, not TREE_SCALE, will scale view frustum's position accordingly - void getFurthestPointFromCameraVoxelScale(const AABox& box, glm::vec3& furthestPoint) const; + void getFurthestPointFromCameraVoxelScale(const AACube& box, glm::vec3& furthestPoint) const; 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; void calculateOrthographic(); // camera location/orientation attributes - glm::vec3 _position; // the position in TREE_SCALE - glm::vec3 _positionVoxelScale; // the position in voxel scale - glm::quat _orientation; + glm::vec3 _position; // the position in TREE_SCALE + glm::vec3 _positionVoxelScale; // the position in voxel scale + glm::quat _orientation; // calculated for orientation - glm::vec3 _direction; - glm::vec3 _up; - glm::vec3 _right; + glm::vec3 _direction; + glm::vec3 _up; + glm::vec3 _right; // Lens attributes bool _orthographic; @@ -148,23 +151,23 @@ private: glm::quat _eyeOffsetOrientation; // keyhole attributes - float _keyholeRadius; - AABox _keyholeBoundingBox; + float _keyholeRadius; + AACube _keyholeBoundingCube; // Calculated values - glm::vec3 _offsetPosition; - glm::vec3 _offsetDirection; - glm::vec3 _offsetUp; - glm::vec3 _offsetRight; - glm::vec3 _farTopLeft; - glm::vec3 _farTopRight; - glm::vec3 _farBottomLeft; - glm::vec3 _farBottomRight; - glm::vec3 _nearTopLeft; - glm::vec3 _nearTopRight; - glm::vec3 _nearBottomLeft; - glm::vec3 _nearBottomRight; + glm::vec3 _offsetPosition; + glm::vec3 _offsetDirection; + glm::vec3 _offsetUp; + glm::vec3 _offsetRight; + glm::vec3 _farTopLeft; + glm::vec3 _farTopRight; + glm::vec3 _farBottomLeft; + glm::vec3 _farBottomRight; + glm::vec3 _nearTopLeft; + glm::vec3 _nearTopRight; + glm::vec3 _nearBottomLeft; + glm::vec3 _nearBottomRight; enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE }; ::Plane _planes[6]; // How will this be used? diff --git a/libraries/particles/src/ParticleTree.cpp b/libraries/particles/src/ParticleTree.cpp index dd8cb6e618..ef97c48c20 100644 --- a/libraries/particles/src/ParticleTree.cpp +++ b/libraries/particles/src/ParticleTree.cpp @@ -237,7 +237,7 @@ bool ParticleTree::findNearPointOperation(OctreeElement* element, void* extraDat ParticleTreeElement* particleTreeElement = static_cast(element); glm::vec3 penetration; - bool sphereIntersection = particleTreeElement->getAABox().findSpherePenetration(args->position, + bool sphereIntersection = particleTreeElement->getAACube().findSpherePenetration(args->position, args->targetRadius, penetration); // If this particleTreeElement contains the point, then search it... @@ -287,7 +287,7 @@ public: bool ParticleTree::findInSphereOperation(OctreeElement* element, void* extraData) { FindAllNearPointArgs* args = static_cast(extraData); glm::vec3 penetration; - bool sphereIntersection = element->getAABox().findSpherePenetration(args->position, + bool sphereIntersection = element->getAACube().findSpherePenetration(args->position, args->targetRadius, penetration); // If this element contains the point, then search it... @@ -310,31 +310,31 @@ void ParticleTree::findParticles(const glm::vec3& center, float radius, QVector< foundParticles.swap(args.particles); } -class FindParticlesInBoxArgs { +class FindParticlesInCubeArgs { public: - FindParticlesInBoxArgs(const AABox& box) - : _box(box), _foundParticles() { + FindParticlesInCubeArgs(const AACube& cube) + : _cube(cube), _foundParticles() { } - AABox _box; + AACube _cube; QVector _foundParticles; }; -bool ParticleTree::findInBoxForUpdateOperation(OctreeElement* element, void* extraData) { - FindParticlesInBoxArgs* args = static_cast< FindParticlesInBoxArgs*>(extraData); - const AABox& elementBox = element->getAABox(); - if (elementBox.touches(args->_box)) { +bool ParticleTree::findInCubeForUpdateOperation(OctreeElement* element, void* extraData) { + FindParticlesInCubeArgs* args = static_cast< FindParticlesInCubeArgs*>(extraData); + const AACube& elementBox = element->getAACube(); + if (elementBox.touches(args->_cube)) { ParticleTreeElement* particleTreeElement = static_cast(element); - particleTreeElement->getParticlesForUpdate(args->_box, args->_foundParticles); + particleTreeElement->getParticlesForUpdate(args->_cube, args->_foundParticles); return true; } return false; } -void ParticleTree::findParticlesForUpdate(const AABox& box, QVector foundParticles) { - FindParticlesInBoxArgs args(box); +void ParticleTree::findParticlesForUpdate(const AACube& cube, QVector foundParticles) { + FindParticlesInCubeArgs args(cube); lockForRead(); - recurseTreeWithOperation(findInBoxForUpdateOperation, &args); + recurseTreeWithOperation(findInCubeForUpdateOperation, &args); unlock(); // swap the two lists of particle pointers instead of copy foundParticles.swap(args._foundParticles); @@ -473,7 +473,7 @@ void ParticleTree::update() { bool shouldDie = args._movingParticles[i].getShouldDie(); // if the particle is still inside our total bounds, then re-add it - AABox treeBounds = getRoot()->getAABox(); + AACube treeBounds = getRoot()->getAACube(); if (!shouldDie && treeBounds.contains(args._movingParticles[i].getPosition())) { storeParticle(args._movingParticles[i]); diff --git a/libraries/particles/src/ParticleTree.h b/libraries/particles/src/ParticleTree.h index 0a2ac285b7..01ceb4425c 100644 --- a/libraries/particles/src/ParticleTree.h +++ b/libraries/particles/src/ParticleTree.h @@ -60,7 +60,7 @@ public: /// \param box the query box /// \param foundParticles[out] vector of non-const Particle* /// \remark Side effect: any initial contents in particles will be lost - void findParticlesForUpdate(const AABox& box, QVector foundParticles); + void findParticlesForUpdate(const AACube& box, QVector foundParticles); void addNewlyCreatedHook(NewlyCreatedParticleHook* hook); void removeNewlyCreatedHook(NewlyCreatedParticleHook* hook); @@ -84,7 +84,7 @@ private: static bool findByIDOperation(OctreeElement* element, void* extraData); static bool findAndDeleteOperation(OctreeElement* element, void* extraData); static bool findAndUpdateParticleIDOperation(OctreeElement* element, void* extraData); - static bool findInBoxForUpdateOperation(OctreeElement* element, void* extraData); + static bool findInCubeForUpdateOperation(OctreeElement* element, void* extraData); void notifyNewlyCreatedParticle(const Particle& newParticle, const SharedNodePointer& senderNode); diff --git a/libraries/particles/src/ParticleTreeElement.cpp b/libraries/particles/src/ParticleTreeElement.cpp index b6e59eb0ab..bb2055bb4e 100644 --- a/libraries/particles/src/ParticleTreeElement.cpp +++ b/libraries/particles/src/ParticleTreeElement.cpp @@ -78,7 +78,7 @@ void ParticleTreeElement::update(ParticleTreeUpdateArgs& args) { // If the particle wants to die, or if it's left our bounding box, then move it // into the arguments moving particles. These will be added back or deleted completely - if (particle.getShouldDie() || !_box.contains(particle.getPosition())) { + if (particle.getShouldDie() || !_cube.contains(particle.getPosition())) { args._movingParticles.push_back(particle); // erase this particle @@ -244,18 +244,18 @@ void ParticleTreeElement::getParticles(const glm::vec3& searchPosition, float se } } -void ParticleTreeElement::getParticlesForUpdate(const AABox& box, QVector& foundParticles) { +void ParticleTreeElement::getParticlesForUpdate(const AACube& box, QVector& foundParticles) { QList::iterator particleItr = _particles->begin(); QList::iterator particleEnd = _particles->end(); - AABox particleBox; + AACube particleCube; while(particleItr != particleEnd) { Particle* particle = &(*particleItr); float radius = particle->getRadius(); // NOTE: we actually do box-box collision queries here, which is sloppy but good enough for now // TODO: decide whether to replace particleBox-box query with sphere-box (requires a square root // but will be slightly more accurate). - particleBox.setBox(particle->getPosition() - glm::vec3(radius), 2.f * radius); - if (particleBox.touches(_box)) { + particleCube.setBox(particle->getPosition() - glm::vec3(radius), 2.f * radius); + if (particleCube.touches(_cube)) { foundParticles.push_back(particle); } ++particleItr; diff --git a/libraries/particles/src/ParticleTreeElement.h b/libraries/particles/src/ParticleTreeElement.h index 4381cdd777..c62c135c3d 100644 --- a/libraries/particles/src/ParticleTreeElement.h +++ b/libraries/particles/src/ParticleTreeElement.h @@ -114,7 +114,7 @@ public: /// finds all particles that touch a box /// \param box the query box /// \param particles[out] vector of non-const Particle* - void getParticlesForUpdate(const AABox& box, QVector& foundParticles); + void getParticlesForUpdate(const AACube& box, QVector& foundParticles); const Particle* getParticleWithID(uint32_t id) const; diff --git a/libraries/voxels/src/VoxelDetail.h b/libraries/voxels/src/VoxelDetail.h index 76657cf10b..50a60828e7 100644 --- a/libraries/voxels/src/VoxelDetail.h +++ b/libraries/voxels/src/VoxelDetail.h @@ -14,7 +14,7 @@ #include -#include +#include #include #include "VoxelConstants.h" diff --git a/libraries/voxels/src/VoxelTreeElement.cpp b/libraries/voxels/src/VoxelTreeElement.cpp index f72e628b74..a05484eb03 100644 --- a/libraries/voxels/src/VoxelTreeElement.cpp +++ b/libraries/voxels/src/VoxelTreeElement.cpp @@ -224,15 +224,15 @@ bool VoxelTreeElement::collapseChildren() { bool VoxelTreeElement::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject) const { - if (_box.findSpherePenetration(center, radius, penetration)) { + if (_cube.findSpherePenetration(center, radius, penetration)) { // if the caller wants details about the voxel, then return them here... if (penetratedObject) { VoxelDetail* voxelDetails = new VoxelDetail; - voxelDetails->x = _box.getCorner().x; - voxelDetails->y = _box.getCorner().y; - voxelDetails->z = _box.getCorner().z; - voxelDetails->s = _box.getScale(); + voxelDetails->x = _cube.getCorner().x; + voxelDetails->y = _cube.getCorner().y; + voxelDetails->z = _cube.getCorner().z; + voxelDetails->s = _cube.getScale(); voxelDetails->red = getColor()[RED_INDEX]; voxelDetails->green = getColor()[GREEN_INDEX]; voxelDetails->blue = getColor()[BLUE_INDEX]; diff --git a/libraries/voxels/src/VoxelTreeElement.h b/libraries/voxels/src/VoxelTreeElement.h index 788a728f6f..05777ac0d3 100644 --- a/libraries/voxels/src/VoxelTreeElement.h +++ b/libraries/voxels/src/VoxelTreeElement.h @@ -18,7 +18,7 @@ #include -#include +#include #include #include