renaming of AABox to AACube, introduction of actual AABox

This commit is contained in:
ZappoMan 2014-05-23 10:45:04 -07:00
parent 9188b9ac59
commit 39ed7f7b65
26 changed files with 384 additions and 257 deletions

View file

@ -2076,10 +2076,10 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
if (rootCode) { if (rootCode) {
VoxelPositionSize rootDetails; VoxelPositionSize rootDetails;
voxelDetailsForCode(rootCode, 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); serverBounds.scale(TREE_SCALE);
ViewFrustum::location serverFrustumLocation = _viewFrustum.boxInFrustum(serverBounds); ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds);
if (serverFrustumLocation != ViewFrustum::OUTSIDE) { if (serverFrustumLocation != ViewFrustum::OUTSIDE) {
inViewServers++; inViewServers++;
@ -2142,10 +2142,10 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
if (rootCode) { if (rootCode) {
VoxelPositionSize rootDetails; VoxelPositionSize rootDetails;
voxelDetailsForCode(rootCode, 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); serverBounds.scale(TREE_SCALE);
ViewFrustum::location serverFrustumLocation = _viewFrustum.boxInFrustum(serverBounds); ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds);
if (serverFrustumLocation != ViewFrustum::OUTSIDE) { if (serverFrustumLocation != ViewFrustum::OUTSIDE) {
inView = true; inView = true;
} else { } else {

View file

@ -73,6 +73,42 @@ Model* ModelTreeRenderer::getModel(const ModelItem& modelItem) {
return model; 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) { void ModelTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) {
args->_elementsTouched++; args->_elementsTouched++;
// actually render it here... // actually render it here...
@ -91,7 +127,7 @@ void ModelTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
if (!isShadowMode && displayElementProxy && numberOfModels > 0) { 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; float elementSize = modelTreeElement->getScale() * (float)TREE_SCALE;
glColor3f(1.0f, 0.0f, 0.0f); glColor3f(1.0f, 0.0f, 0.0f);
glPushMatrix(); glPushMatrix();
@ -157,9 +193,9 @@ void ModelTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
for (uint16_t i = 0; i < numberOfModels; i++) { for (uint16_t i = 0; i < numberOfModels; i++) {
ModelItem& modelItem = modelItems[i]; ModelItem& modelItem = modelItems[i];
// render modelItem aspoints // render modelItem aspoints
AABox modelBox = modelItem.getAABox(); AACube modelCube = modelItem.getAACube();
modelBox.scale(TREE_SCALE); modelCube.scale(TREE_SCALE);
if (args->_viewFrustum->boxInFrustum(modelBox) != ViewFrustum::OUTSIDE) { if (args->_viewFrustum->cubeInFrustum(modelCube) != ViewFrustum::OUTSIDE) {
glm::vec3 position = modelItem.getPosition() * (float)TREE_SCALE; glm::vec3 position = modelItem.getPosition() * (float)TREE_SCALE;
float radius = modelItem.getRadius() * (float)TREE_SCALE; float radius = modelItem.getRadius() * (float)TREE_SCALE;
float size = modelItem.getSize() * (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); model->render(alpha, modelRenderMode);
if (!isShadowMode && displayModelBounds) { 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(); glPushMatrix();
glTranslatef(position.x, position.y, position.z); glTranslatef(position.x, position.y, position.z);
// draw the orignal bounding cube
glColor4f(1.0f, 1.0f, 0.0f, 1.0f);
glutWireCube(size); 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(); glPopMatrix();
} }

View file

@ -987,8 +987,9 @@ void Model::scaleToFit() {
// size is our "target size in world space" // 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... // 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; glm::vec3 dimensions = modelMeshExtents.maximum - modelMeshExtents.minimum;
float maxDimension = glm::max(glm::max(dimensions.x, dimensions.y), dimensions.z); const float SQRT_THREE = 1.733; // sqrt(3)
float maxScale = _scaleToFitLargestDimension / maxDimension; float maxDimensionRotated = SQRT_THREE * glm::max(glm::max(dimensions.x, dimensions.y), dimensions.z);
float maxScale = _scaleToFitLargestDimension / maxDimensionRotated;
glm::vec3 scale(maxScale, maxScale, maxScale); glm::vec3 scale(maxScale, maxScale, maxScale);
setScaleInternal(scale); setScaleInternal(scale);
_scaledToFit = true; _scaledToFit = true;

View file

@ -81,7 +81,7 @@ void NodeBounds::draw() {
glm::vec3 location(rootDetails.x, rootDetails.y, rootDetails.z); glm::vec3 location(rootDetails.x, rootDetails.y, rootDetails.z);
location *= (float)TREE_SCALE; 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) glm::vec3 center = serverBounds.getVertex(BOTTOM_RIGHT_NEAR)
+ ((serverBounds.getVertex(TOP_LEFT_FAR) - serverBounds.getVertex(BOTTOM_RIGHT_NEAR)) / 2.0f); + ((serverBounds.getVertex(TOP_LEFT_FAR) - serverBounds.getVertex(BOTTOM_RIGHT_NEAR)) / 2.0f);

View file

@ -293,7 +293,7 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser
VoxelPositionSize rootDetails; VoxelPositionSize rootDetails;
voxelDetailsForCode(rootCode, 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); serverBounds.scale(TREE_SCALE);
serverDetails << " jurisdiction: " serverDetails << " jurisdiction: "
<< qPrintable(rootCodeHex) << qPrintable(rootCodeHex)

View file

@ -198,7 +198,7 @@ public:
float getSize() const { return _radius * 2.0f; } float getSize() const { return _radius * 2.0f; }
/// get maximum dimension in domain scale units (0.0 - 1.0) /// 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 // model related properties
bool hasModel() const { return !_modelURL.isEmpty(); } bool hasModel() const { return !_modelURL.isEmpty(); }

View file

@ -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 we didn't find it in the tree, then store it...
if (!theOperator.wasFound()) { if (!theOperator.wasFound()) {
AABox modelBox = model.getAABox(); AACube modelCube = model.getAACube();
ModelTreeElement* element = (ModelTreeElement*)getOrCreateChildElementContaining(model.getAABox()); ModelTreeElement* element = (ModelTreeElement*)getOrCreateChildElementContaining(model.getAACube());
element->storeModel(model); element->storeModel(model);
// In the case where we stored it, we also need to mark the entire "path" down to the model as // 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<ModelTreeElement*>(element); ModelTreeElement* modelTreeElement = static_cast<ModelTreeElement*>(element);
glm::vec3 penetration; glm::vec3 penetration;
bool sphereIntersection = modelTreeElement->getAABox().findSpherePenetration(args->position, bool sphereIntersection = modelTreeElement->getAACube().findSpherePenetration(args->position,
args->targetRadius, penetration); args->targetRadius, penetration);
// If this modelTreeElement contains the point, then search it... // If this modelTreeElement contains the point, then search it...
@ -320,7 +320,7 @@ public:
bool ModelTree::findInSphereOperation(OctreeElement* element, void* extraData) { bool ModelTree::findInSphereOperation(OctreeElement* element, void* extraData) {
FindAllNearPointArgs* args = static_cast<FindAllNearPointArgs*>(extraData); FindAllNearPointArgs* args = static_cast<FindAllNearPointArgs*>(extraData);
glm::vec3 penetration; glm::vec3 penetration;
bool sphereIntersection = element->getAABox().findSpherePenetration(args->position, bool sphereIntersection = element->getAACube().findSpherePenetration(args->position,
args->targetRadius, penetration); args->targetRadius, penetration);
// If this element contains the point, then search it... // If this element contains the point, then search it...
@ -343,31 +343,31 @@ void ModelTree::findModels(const glm::vec3& center, float radius, QVector<const
foundModels.swap(args.models); foundModels.swap(args.models);
} }
class FindModelsInBoxArgs { class FindModelsInCubeArgs {
public: public:
FindModelsInBoxArgs(const AABox& box) FindModelsInCubeArgs(const AACube& cube)
: _box(box), _foundModels() { : _cube(cube), _foundModels() {
} }
AABox _box; AACube _cube;
QVector<ModelItem*> _foundModels; QVector<ModelItem*> _foundModels;
}; };
bool ModelTree::findInBoxForUpdateOperation(OctreeElement* element, void* extraData) { bool ModelTree::findInCubeForUpdateOperation(OctreeElement* element, void* extraData) {
FindModelsInBoxArgs* args = static_cast< FindModelsInBoxArgs*>(extraData); FindModelsInCubeArgs* args = static_cast< FindModelsInCubeArgs*>(extraData);
const AABox& elementBox = element->getAABox(); const AACube& elementCube = element->getAACube();
if (elementBox.touches(args->_box)) { if (elementCube.touches(args->_cube)) {
ModelTreeElement* modelTreeElement = static_cast<ModelTreeElement*>(element); ModelTreeElement* modelTreeElement = static_cast<ModelTreeElement*>(element);
modelTreeElement->getModelsForUpdate(args->_box, args->_foundModels); modelTreeElement->getModelsForUpdate(args->_cube, args->_foundModels);
return true; return true;
} }
return false; return false;
} }
void ModelTree::findModelsForUpdate(const AABox& box, QVector<ModelItem*> foundModels) { void ModelTree::findModelsForUpdate(const AACube& cube, QVector<ModelItem*> foundModels) {
FindModelsInBoxArgs args(box); FindModelsInCubeArgs args(cube);
lockForRead(); lockForRead();
recurseTreeWithOperation(findInBoxForUpdateOperation, &args); recurseTreeWithOperation(findInCubeForUpdateOperation, &args);
unlock(); unlock();
// swap the two lists of model pointers instead of copy // swap the two lists of model pointers instead of copy
foundModels.swap(args._foundModels); foundModels.swap(args._foundModels);
@ -507,7 +507,7 @@ void ModelTree::update() {
bool shouldDie = args._movingModels[i].getShouldDie(); bool shouldDie = args._movingModels[i].getShouldDie();
// if the particle is still inside our total bounds, then re-add it // 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())) { if (!shouldDie && treeBounds.contains(args._movingModels[i].getPosition())) {
storeModel(args._movingModels[i]); storeModel(args._movingModels[i]);

View file

@ -58,11 +58,11 @@ public:
/// \remark Side effect: any initial contents in foundModels will be lost /// \remark Side effect: any initial contents in foundModels will be lost
void findModels(const glm::vec3& center, float radius, QVector<const ModelItem*>& foundModels); void findModels(const glm::vec3& center, float radius, QVector<const ModelItem*>& foundModels);
/// finds all models that touch a box /// finds all models that touch a cube
/// \param box the query box /// \param cube the query cube
/// \param foundModels[out] vector of non-const ModelItem* /// \param foundModels[out] vector of non-const ModelItem*
/// \remark Side effect: any initial contents in models will be lost /// \remark Side effect: any initial contents in models will be lost
void findModelsForUpdate(const AABox& box, QVector<ModelItem*> foundModels); void findModelsForUpdate(const AACube& cube, QVector<ModelItem*> foundModels);
void addNewlyCreatedHook(NewlyCreatedModelHook* hook); void addNewlyCreatedHook(NewlyCreatedModelHook* hook);
void removeNewlyCreatedHook(NewlyCreatedModelHook* hook); void removeNewlyCreatedHook(NewlyCreatedModelHook* hook);
@ -86,7 +86,7 @@ private:
static bool findByIDOperation(OctreeElement* element, void* extraData); static bool findByIDOperation(OctreeElement* element, void* extraData);
static bool findAndDeleteOperation(OctreeElement* element, void* extraData); static bool findAndDeleteOperation(OctreeElement* element, void* extraData);
static bool findAndUpdateModelItemIDOperation(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); void notifyNewlyCreatedModel(const ModelItem& newModel, const SharedNodePointer& senderNode);

View file

@ -57,9 +57,9 @@ bool ModelTreeElement::appendElementData(OctreePacketData* packetData, EncodeBit
for (uint16_t i = 0; i < _modelItems->size(); i++) { for (uint16_t i = 0; i < _modelItems->size(); i++) {
if (params.viewFrustum) { if (params.viewFrustum) {
const ModelItem& model = (*_modelItems)[i]; const ModelItem& model = (*_modelItems)[i];
AABox modelBox = model.getAABox(); AACube modelCube = model.getAACube();
modelBox.scale(TREE_SCALE); modelCube.scale(TREE_SCALE);
if (params.viewFrustum->boxInFrustum(modelBox) != ViewFrustum::OUTSIDE) { if (params.viewFrustum->cubeInFrustum(modelCube) != ViewFrustum::OUTSIDE) {
indexesOfModelsToInclude << i; indexesOfModelsToInclude << i;
numberOfModels++; numberOfModels++;
} }
@ -86,18 +86,18 @@ bool ModelTreeElement::appendElementData(OctreePacketData* packetData, EncodeBit
bool ModelTreeElement::containsModelBounds(const ModelItem& model) const { bool ModelTreeElement::containsModelBounds(const ModelItem& model) const {
glm::vec3 clampedMin = glm::clamp(model.getMinimumPoint(), 0.0f, 1.0f); glm::vec3 clampedMin = glm::clamp(model.getMinimumPoint(), 0.0f, 1.0f);
glm::vec3 clampedMax = glm::clamp(model.getMaximumPoint(), 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 { bool ModelTreeElement::bestFitModelBounds(const ModelItem& model) const {
glm::vec3 clampedMin = glm::clamp(model.getMinimumPoint(), 0.0f, 1.0f); glm::vec3 clampedMin = glm::clamp(model.getMinimumPoint(), 0.0f, 1.0f);
glm::vec3 clampedMax = glm::clamp(model.getMaximumPoint(), 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 childForMinimumPoint = getMyChildContainingPoint(clampedMin);
int childForMaximumPoint = getMyChildContainingPoint(clampedMax); int childForMaximumPoint = getMyChildContainingPoint(clampedMax);
// if this is a really small box, then it's close enough! // 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; return true;
} }
// If I contain both the minimum and maximum point, but two different children of mine // 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<ModelItem*>& foundModels) { void ModelTreeElement::getModelsForUpdate(const AACube& box, QVector<ModelItem*>& foundModels) {
QList<ModelItem>::iterator modelItr = _modelItems->begin(); QList<ModelItem>::iterator modelItr = _modelItems->begin();
QList<ModelItem>::iterator modelEnd = _modelItems->end(); QList<ModelItem>::iterator modelEnd = _modelItems->end();
AABox modelBox; AACube modelCube;
while(modelItr != modelEnd) { while(modelItr != modelEnd) {
ModelItem* model = &(*modelItr); ModelItem* model = &(*modelItr);
float radius = model->getRadius(); float radius = model->getRadius();
// NOTE: we actually do box-box collision queries here, which is sloppy but good enough for now // NOTE: we actually do cube-cube 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 // TODO: decide whether to replace modelCube-cube query with sphere-cube (requires a square root
// but will be slightly more accurate). // but will be slightly more accurate).
modelBox.setBox(model->getPosition() - glm::vec3(radius), 2.f * radius); modelCube.setBox(model->getPosition() - glm::vec3(radius), 2.f * radius);
if (modelBox.touches(_box)) { if (modelCube.touches(_cube)) {
foundModels.push_back(model); foundModels.push_back(model);
} }
++modelItr; ++modelItr;

View file

@ -125,7 +125,7 @@ public:
/// finds all models that touch a box /// finds all models that touch a box
/// \param box the query box /// \param box the query box
/// \param models[out] vector of non-const ModelItem* /// \param models[out] vector of non-const ModelItem*
void getModelsForUpdate(const AABox& box, QVector<ModelItem*>& foundModels); void getModelsForUpdate(const AACube& box, QVector<ModelItem*>& foundModels);
const ModelItem* getModelWithID(uint32_t id) const; const ModelItem* getModelWithID(uint32_t id) const;

View file

@ -9,27 +9,31 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // 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 "SharedUtil.h"
#include "AABox.h"
#include "GeometryUtil.h"
AABox::AABox(const glm::vec3& corner, float size) : 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 AABox::calcCenter() const {
glm::vec3 center(_corner); glm::vec3 center(_corner);
center += (glm::vec3(_scale, _scale, _scale) * 0.5f); center += (_scale * 0.5f);
return center; return center;
} }
glm::vec3 AABox::calcTopFarLeft() const { glm::vec3 AABox::calcTopFarLeft() const {
glm::vec3 topFarLeft(_corner); glm::vec3 topFarLeft(_corner);
topFarLeft += glm::vec3(_scale, _scale, _scale); topFarLeft += _scale;
return topFarLeft; return topFarLeft;
}; };
@ -41,26 +45,31 @@ void AABox::scale(float scale) {
glm::vec3 AABox::getVertex(BoxVertex vertex) const { glm::vec3 AABox::getVertex(BoxVertex vertex) const {
switch (vertex) { switch (vertex) {
case BOTTOM_LEFT_NEAR: case BOTTOM_LEFT_NEAR:
return _corner + glm::vec3(_scale, 0, 0); return _corner + glm::vec3(_scale.x, 0, 0);
case BOTTOM_RIGHT_NEAR: case BOTTOM_RIGHT_NEAR:
return _corner; return _corner;
case TOP_RIGHT_NEAR: case TOP_RIGHT_NEAR:
return _corner + glm::vec3(0, _scale, 0); return _corner + glm::vec3(0, _scale.y, 0);
case TOP_LEFT_NEAR: case TOP_LEFT_NEAR:
return _corner + glm::vec3(_scale, _scale, 0); return _corner + glm::vec3(_scale.x, _scale.y, 0);
case BOTTOM_LEFT_FAR: case BOTTOM_LEFT_FAR:
return _corner + glm::vec3(_scale, 0, _scale); return _corner + glm::vec3(_scale.x, 0, _scale.z);
case BOTTOM_RIGHT_FAR: case BOTTOM_RIGHT_FAR:
return _corner + glm::vec3(0, 0, _scale); return _corner + glm::vec3(0, 0, _scale.z);
case TOP_RIGHT_FAR: case TOP_RIGHT_FAR:
return _corner + glm::vec3(0, _scale, _scale); return _corner + glm::vec3(0, _scale.y, _scale.z);
default: //quiet windows warnings default: //quiet windows warnings
case TOP_LEFT_FAR: case TOP_LEFT_FAR:
return _corner + glm::vec3(_scale, _scale, _scale); return _corner + _scale;
} }
} }
void AABox::setBox(const glm::vec3& corner, float 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; _corner = corner;
_scale = scale; _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 AABox::getVertexP(const glm::vec3& normal) const {
glm::vec3 result = _corner; glm::vec3 result = _corner;
if (normal.x > 0) { if (normal.x > 0) {
result.x += _scale; result.x += _scale.x;
} }
if (normal.y > 0) { if (normal.y > 0) {
result.y += _scale; result.y += _scale.y;
} }
if (normal.z > 0) { if (normal.z > 0) {
result.z += _scale; result.z += _scale.z;
} }
return result; return result;
} }
@ -83,15 +92,15 @@ glm::vec3 AABox::getVertexN(const glm::vec3& normal) const {
glm::vec3 result = _corner; glm::vec3 result = _corner;
if (normal.x < 0) { if (normal.x < 0) {
result.x += _scale; result.x += _scale.x;
} }
if (normal.y < 0) { if (normal.y < 0) {
result.y += _scale; result.y += _scale.y;
} }
if (normal.z < 0) { if (normal.z < 0) {
result.z += _scale; result.z += _scale.z;
} }
return result; return result;
@ -103,9 +112,9 @@ static bool isWithin(float value, float corner, float size) {
} }
bool AABox::contains(const glm::vec3& point) const { bool AABox::contains(const glm::vec3& point) const {
return isWithin(point.x, _corner.x, _scale) && return isWithin(point.x, _corner.x, _scale.x) &&
isWithin(point.y, _corner.y, _scale) && isWithin(point.y, _corner.y, _scale.y) &&
isWithin(point.z, _corner.z, _scale); isWithin(point.z, _corner.z, _scale.z);
} }
bool AABox::contains(const AABox& otherBox) const { 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 { bool AABox::touches(const AABox& otherBox) const {
glm::vec3 relativeCenter = _corner - otherBox._corner + (glm::vec3(_scale - otherBox._scale) * 0.5f); glm::vec3 relativeCenter = _corner - otherBox._corner + ((_scale - otherBox._scale) * 0.5f);
float totalHalfScale = 0.5f * (_scale + otherBox._scale);
return fabs(relativeCenter.x) <= totalHalfScale && glm::vec3 totalHalfScale = (_scale + otherBox._scale) * 0.5f;
fabs(relativeCenter.y) <= totalHalfScale &&
fabs(relativeCenter.z) <= totalHalfScale; 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 // 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 { bool AABox::expandedContains(const glm::vec3& point, float expansion) const {
return isWithinExpanded(point.x, _corner.x, _scale, expansion) && return isWithinExpanded(point.x, _corner.x, _scale.x, expansion) &&
isWithinExpanded(point.y, _corner.y, _scale, expansion) && isWithinExpanded(point.y, _corner.y, _scale.y, expansion) &&
isWithinExpanded(point.z, _corner.z, _scale, expansion); isWithinExpanded(point.z, _corner.z, _scale.z, expansion);
} }
// finds the intersection between a ray and the facing plane on one axis // 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 // check each axis
glm::vec3 expandedCorner = _corner - glm::vec3(expansion, expansion, expansion); 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; glm::vec3 direction = end - start;
float axisDistance; float axisDistance;
return (findIntersection(start.x, direction.x, expandedCorner.x, expandedSize.x, 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 // check each axis
float axisDistance; float axisDistance;
if ((findIntersection(origin.x, direction.x, _corner.x, _scale, axisDistance) && axisDistance >= 0 && if ((findIntersection(origin.x, direction.x, _corner.x, _scale.x, axisDistance) && axisDistance >= 0 &&
isWithin(origin.y + axisDistance*direction.y, _corner.y, _scale) && isWithin(origin.y + axisDistance*direction.y, _corner.y, _scale.y) &&
isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale))) { isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale.z))) {
distance = axisDistance; distance = axisDistance;
face = direction.x > 0 ? MIN_X_FACE : MAX_X_FACE; face = direction.x > 0 ? MIN_X_FACE : MAX_X_FACE;
return true; return true;
} }
if ((findIntersection(origin.y, direction.y, _corner.y, _scale, axisDistance) && axisDistance >= 0 && if ((findIntersection(origin.y, direction.y, _corner.y, _scale.y, axisDistance) && axisDistance >= 0 &&
isWithin(origin.x + axisDistance*direction.x, _corner.x, _scale) && isWithin(origin.x + axisDistance*direction.x, _corner.x, _scale.x) &&
isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale))) { isWithin(origin.z + axisDistance*direction.z, _corner.z, _scale.z))) {
distance = axisDistance; distance = axisDistance;
face = direction.y > 0 ? MIN_Y_FACE : MAX_Y_FACE; face = direction.y > 0 ? MIN_Y_FACE : MAX_Y_FACE;
return true; return true;
} }
if ((findIntersection(origin.z, direction.z, _corner.z, _scale, axisDistance) && axisDistance >= 0 && if ((findIntersection(origin.z, direction.z, _corner.z, _scale.z, axisDistance) && axisDistance >= 0 &&
isWithin(origin.y + axisDistance*direction.y, _corner.y, _scale) && isWithin(origin.y + axisDistance*direction.y, _corner.y, _scale.y) &&
isWithin(origin.x + axisDistance*direction.x, _corner.x, _scale))) { isWithin(origin.x + axisDistance*direction.x, _corner.x, _scale.x))) {
distance = axisDistance; distance = axisDistance;
face = direction.z > 0 ? MIN_Z_FACE : MAX_Z_FACE; face = direction.z > 0 ? MIN_Z_FACE : MAX_Z_FACE;
return true; return true;
@ -260,28 +291,28 @@ glm::vec3 AABox::getClosestPointOnFace(const glm::vec3& point, BoxFace face) con
switch (face) { switch (face) {
case MIN_X_FACE: case MIN_X_FACE:
return glm::clamp(point, glm::vec3(_corner.x, _corner.y, _corner.z), 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: case MAX_X_FACE:
return glm::clamp(point, glm::vec3(_corner.x + _scale, _corner.y, _corner.z), return glm::clamp(point, glm::vec3(_corner.x + _scale.x, _corner.y, _corner.z),
glm::vec3(_corner.x + _scale, _corner.y + _scale, _corner.z + _scale)); glm::vec3(_corner.x + _scale.x, _corner.y + _scale.y, _corner.z + _scale.z));
case MIN_Y_FACE: case MIN_Y_FACE:
return glm::clamp(point, glm::vec3(_corner.x, _corner.y, _corner.z), 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: case MAX_Y_FACE:
return glm::clamp(point, glm::vec3(_corner.x, _corner.y + _scale, _corner.z), return glm::clamp(point, glm::vec3(_corner.x, _corner.y + _scale.y, _corner.z),
glm::vec3(_corner.x + _scale, _corner.y + _scale, _corner.z + _scale)); glm::vec3(_corner.x + _scale.x, _corner.y + _scale.y, _corner.z + _scale.z));
case MIN_Z_FACE: case MIN_Z_FACE:
return glm::clamp(point, glm::vec3(_corner.x, _corner.y, _corner.z), 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 default: //quiet windows warnings
case MAX_Z_FACE: case MAX_Z_FACE:
return glm::clamp(point, glm::vec3(_corner.x, _corner.y, _corner.z + _scale), return glm::clamp(point, glm::vec3(_corner.x, _corner.y, _corner.z + _scale.z),
glm::vec3(_corner.x + _scale, _corner.y + _scale, _corner.z + _scale)); 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 thirdAxisMaxPlane = getPlane((BoxFace)(thirdAxis * 2 + 1));
glm::vec4 offset = glm::vec4(0.0f, 0.0f, 0.0f, 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, glm::vec4 diagonals[] = { secondAxisMinPlane + thirdAxisMaxPlane + offset,
secondAxisMaxPlane + 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 { glm::vec4 AABox::getPlane(BoxFace face) const {
switch (face) { switch (face) {
case MIN_X_FACE: return glm::vec4(-1.0f, 0.0f, 0.0f, _corner.x); 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 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); case MIN_Z_FACE: return glm::vec4(0.0f, 0.0f, -1.0f, _corner.z);
default: //quiet windows warnings 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);
} }
} }

View file

@ -17,55 +17,38 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
enum BoxFace { #include "BoxBase.h"
MIN_X_FACE,
MAX_X_FACE,
MIN_Y_FACE,
MAX_Y_FACE,
MIN_Z_FACE,
MAX_Z_FACE,
UNKNOWN_FACE
};
enum BoxVertex { class AACube;
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 AABox { class AABox {
public: public:
AABox(const glm::vec3& corner, float size); AABox(const glm::vec3& corner, float size);
AABox(const glm::vec3& corner, const glm::vec3& dimensions);
AABox(); AABox();
~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 void setBox(const glm::vec3& corner, float scale);
glm::vec3 getVertexP(const glm::vec3& normal) const; glm::vec3 getVertexP(const glm::vec3& normal) const;
glm::vec3 getVertexN(const glm::vec3& normal) const; glm::vec3 getVertexN(const glm::vec3& normal) const;
void scale(float scale); void scale(float scale);
const glm::vec3& getCorner() const { return _corner; }
const glm::vec3& getCorner() const { return _corner; }; const glm::vec3& getScale() const { return _scale; }
float getScale() const { return _scale; } const glm::vec3& getDimensions() const { return _scale; }
glm::vec3 calcCenter() const; glm::vec3 calcCenter() const;
glm::vec3 calcTopFarLeft() const; glm::vec3 calcTopFarLeft() const;
glm::vec3 getVertex(BoxVertex vertex) const; glm::vec3 getVertex(BoxVertex vertex) const;
bool contains(const glm::vec3& point) const; bool contains(const glm::vec3& point) const;
bool contains(const AABox& otherBox) const; bool contains(const AABox& otherBox) const;
bool touches(const AABox& otherBox) const; bool touches(const AABox& otherBox) const;
bool contains(const AACube& otherCube) const;
bool touches(const AACube& otherCube) const;
bool expandedContains(const glm::vec3& point, float expansion) const; bool expandedContains(const glm::vec3& point, float expansion) const;
bool expandedIntersectsSegment(const glm::vec3& start, const glm::vec3& end, 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 findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const;
@ -80,7 +63,7 @@ private:
static BoxFace getOppositeFace(BoxFace face); static BoxFace getOppositeFace(BoxFace face);
glm::vec3 _corner; glm::vec3 _corner;
float _scale; glm::vec3 _scale;
}; };
#endif // hifi_AABox_h #endif // hifi_AABox_h

View file

@ -583,7 +583,7 @@ OctreeElement* Octree::getOrCreateChildElementAt(float x, float y, float z, floa
return getRoot()->getOrCreateChildElementAt(x, y, z, s); return getRoot()->getOrCreateChildElementAt(x, y, z, s);
} }
OctreeElement* Octree::getOrCreateChildElementContaining(const AABox& box) { OctreeElement* Octree::getOrCreateChildElementContaining(const AACube& box) {
return getRoot()->getOrCreateChildElementContaining(box); return getRoot()->getOrCreateChildElementContaining(box);
} }
@ -601,7 +601,7 @@ public:
bool findRayIntersectionOp(OctreeElement* element, void* extraData) { bool findRayIntersectionOp(OctreeElement* element, void* extraData) {
RayArgs* args = static_cast<RayArgs*>(extraData); RayArgs* args = static_cast<RayArgs*>(extraData);
AABox box = element->getAABox(); AACube box = element->getAACube();
float distance; float distance;
BoxFace face; BoxFace face;
if (!box.findRayIntersection(args->origin, args->direction, distance, face)) { if (!box.findRayIntersection(args->origin, args->direction, distance, face)) {
@ -664,7 +664,7 @@ bool findSpherePenetrationOp(OctreeElement* element, void* extraData) {
SphereArgs* args = static_cast<SphereArgs*>(extraData); SphereArgs* args = static_cast<SphereArgs*>(extraData);
// coarse check against bounds // coarse check against bounds
const AABox& box = element->getAABox(); const AACube& box = element->getAACube();
if (!box.expandedContains(args->center, args->radius)) { if (!box.expandedContains(args->center, args->radius)) {
return false; return false;
} }
@ -743,7 +743,7 @@ bool findCapsulePenetrationOp(OctreeElement* element, void* extraData) {
CapsuleArgs* args = static_cast<CapsuleArgs*>(extraData); CapsuleArgs* args = static_cast<CapsuleArgs*>(extraData);
// coarse check against bounds // coarse check against bounds
const AABox& box = element->getAABox(); const AACube& box = element->getAACube();
if (!box.expandedIntersectsSegment(args->start, args->end, args->radius)) { if (!box.expandedIntersectsSegment(args->start, args->end, args->radius)) {
return false; return false;
} }
@ -764,7 +764,7 @@ bool findShapeCollisionsOp(OctreeElement* element, void* extraData) {
ShapeArgs* args = static_cast<ShapeArgs*>(extraData); ShapeArgs* args = static_cast<ShapeArgs*>(extraData);
// coarse check against bounds // coarse check against bounds
AABox cube = element->getAABox(); AACube cube = element->getAACube();
cube.scale(TREE_SCALE); cube.scale(TREE_SCALE);
if (!cube.expandedContains(args->shape->getPosition(), args->shape->getBoundingRadius())) { if (!cube.expandedContains(args->shape->getPosition(), args->shape->getBoundingRadius())) {
return false; return false;
@ -858,7 +858,7 @@ public:
// Find the smallest colored voxel enclosing a point (if there is one) // Find the smallest colored voxel enclosing a point (if there is one)
bool getElementEnclosingOperation(OctreeElement* element, void* extraData) { bool getElementEnclosingOperation(OctreeElement* element, void* extraData) {
GetElementEnclosingArgs* args = static_cast<GetElementEnclosingArgs*>(extraData); GetElementEnclosingArgs* args = static_cast<GetElementEnclosingArgs*>(extraData);
AABox elementBox = element->getAABox(); AACube elementBox = element->getAACube();
if (elementBox.contains(args->point)) { if (elementBox.contains(args->point)) {
if (element->hasContent() && element->isLeaf()) { if (element->hasContent() && element->isLeaf()) {
// we've reached a solid leaf containing the point, return the element. // 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. // 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 // leaf occlusion is handled down below when we check child nodes
if (params.wantOcclusionCulling && !element->isLeaf()) { if (params.wantOcclusionCulling && !element->isLeaf()) {
AABox voxelBox = element->getAABox(); AACube voxelBox = element->getAACube();
voxelBox.scale(TREE_SCALE); voxelBox.scale(TREE_SCALE);
OctreeProjectedPolygon* voxelPolygon = new OctreeProjectedPolygon(params.viewFrustum->getProjectedPolygon(voxelBox)); OctreeProjectedPolygon* voxelPolygon = new OctreeProjectedPolygon(params.viewFrustum->getProjectedPolygon(voxelBox));
@ -1250,7 +1250,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
if (params.wantOcclusionCulling && childElement->isLeaf()) { if (params.wantOcclusionCulling && childElement->isLeaf()) {
// Don't check occlusion here, just add them to our distance ordered array... // 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); voxelBox.scale(TREE_SCALE);
OctreeProjectedPolygon* voxelPolygon = new OctreeProjectedPolygon( OctreeProjectedPolygon* voxelPolygon = new OctreeProjectedPolygon(
params.viewFrustum->getProjectedPolygon(voxelBox)); params.viewFrustum->getProjectedPolygon(voxelBox));

View file

@ -236,7 +236,7 @@ public:
OctreeElement* getOctreeEnclosingElementAt(float x, float y, float z, float s) const; OctreeElement* getOctreeEnclosingElementAt(float x, float y, float z, float s) const;
OctreeElement* getOrCreateChildElementAt(float x, float y, float z, float s); 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 recurseTreeWithOperation(RecurseOctreeOperation operation, void* extraData = NULL);
void recurseTreeWithPostOperation(RecurseOctreeOperation operation, void* extraData = NULL); void recurseTreeWithPostOperation(RecurseOctreeOperation operation, void* extraData = NULL);

View file

@ -19,7 +19,7 @@
#include <PerfStat.h> #include <PerfStat.h>
#include <assert.h> #include <assert.h>
#include "AABox.h" #include "AACube.h"
#include "OctalCode.h" #include "OctalCode.h"
#include "OctreeConstants.h" #include "OctreeConstants.h"
#include "OctreeElement.h" #include "OctreeElement.h"
@ -93,7 +93,7 @@ void OctreeElement::init(unsigned char * octalCode) {
_isDirty = true; _isDirty = true;
_shouldRender = false; _shouldRender = false;
_sourceUUIDKey = 0; _sourceUUIDKey = 0;
calculateAABox(); calculateAACube();
markWithChangedTime(); markWithChangedTime();
} }
@ -190,15 +190,15 @@ void OctreeElement::setShouldRender(bool shouldRender) {
} }
} }
void OctreeElement::calculateAABox() { void OctreeElement::calculateAACube() {
glm::vec3 corner; glm::vec3 corner;
// copy corner into box // copy corner into cube
copyFirstVertexForCode(getOctalCode(),(float*)&corner); copyFirstVertexForCode(getOctalCode(),(float*)&corner);
// this tells you the "size" of the voxel // this tells you the "size" of the voxel
float voxelScale = 1 / powf(2, numberOfThreeBitSectionsInCode(getOctalCode())); float voxelScale = 1 / powf(2, numberOfThreeBitSectionsInCode(getOctalCode()));
_box.setBox(corner,voxelScale); _cube.setBox(corner,voxelScale);
} }
void OctreeElement::deleteChildAtIndex(int childIndex) { void OctreeElement::deleteChildAtIndex(int childIndex) {
@ -1178,7 +1178,7 @@ void OctreeElement::printDebugDetails(const char* label) const {
QString resultString; QString resultString;
resultString.sprintf("%s - Voxel at corner=(%f,%f,%f) size=%f\n isLeaf=%s isDirty=%s shouldRender=%s\n children=", label, 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())); debug::valueOf(isLeaf()), debug::valueOf(isDirty()), debug::valueOf(getShouldRender()));
elementDebug << resultString; elementDebug << resultString;
@ -1192,9 +1192,9 @@ float OctreeElement::getEnclosingRadius() const {
} }
ViewFrustum::location OctreeElement::inFrustum(const ViewFrustum& viewFrustum) const { ViewFrustum::location OctreeElement::inFrustum(const ViewFrustum& viewFrustum) const {
AABox box = _box; // use temporary box so we can scale it AACube cube = _cube; // use temporary cube so we can scale it
box.scale(TREE_SCALE); cube.scale(TREE_SCALE);
return viewFrustum.boxInFrustum(box); return viewFrustum.cubeInFrustum(cube);
} }
// There are two types of nodes for which we want to "render" // 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 // 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 { float OctreeElement::furthestDistanceToCamera(const ViewFrustum& viewFrustum) const {
glm::vec3 furthestPoint; glm::vec3 furthestPoint;
viewFrustum.getFurthestPointFromCameraVoxelScale(getAABox(), furthestPoint); viewFrustum.getFurthestPointFromCameraVoxelScale(getAACube(), furthestPoint);
glm::vec3 temp = viewFrustum.getPositionVoxelScale() - furthestPoint; glm::vec3 temp = viewFrustum.getPositionVoxelScale() - furthestPoint;
float distanceToFurthestPoint = sqrtf(glm::dot(temp, temp)); float distanceToFurthestPoint = sqrtf(glm::dot(temp, temp));
return distanceToFurthestPoint * (float)TREE_SCALE; return distanceToFurthestPoint * (float)TREE_SCALE;
} }
float OctreeElement::distanceToCamera(const ViewFrustum& viewFrustum) const { 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; glm::vec3 temp = viewFrustum.getPosition() - center;
float distanceToVoxelCenter = sqrtf(glm::dot(temp, temp)); float distanceToVoxelCenter = sqrtf(glm::dot(temp, temp));
return distanceToVoxelCenter; return distanceToVoxelCenter;
} }
float OctreeElement::distanceSquareToPoint(const glm::vec3& point) const { 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); float distanceSquare = glm::dot(temp, temp);
return distanceSquare; return distanceSquare;
} }
float OctreeElement::distanceToPoint(const glm::vec3& point) const { 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)); float distance = sqrtf(glm::dot(temp, temp));
return distance; return distance;
} }
@ -1304,7 +1304,7 @@ void OctreeElement::notifyUpdateHooks() {
bool OctreeElement::findSpherePenetration(const glm::vec3& center, float radius, bool OctreeElement::findSpherePenetration(const glm::vec3& center, float radius,
glm::vec3& penetration, void** penetratedObject) const { 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; return this;
} }
// otherwise, we need to find which of our children we should recurse // 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; int childIndex = CHILD_UNKNOWN;
// left half // 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; OctreeElement* child = NULL;
float ourScale = getScale(); float ourScale = getScale();
float boxScale = box.getScale(); float cubeScale = cube.getScale();
if(boxScale > ourScale) { if(cubeScale > ourScale) {
qDebug("UNEXPECTED -- OctreeElement::getOrCreateChildElementContaining() " 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... // Determine which of our children the minimum and maximum corners of the cube live in...
glm::vec3 boxCornerMinimum = box.getCorner(); glm::vec3 cubeCornerMinimum = cube.getCorner();
glm::vec3 boxCornerMaximum = box.calcTopFarLeft(); glm::vec3 cubeCornerMaximum = cube.calcTopFarLeft();
int childIndexBoxMinimum = getMyChildContainingPoint(boxCornerMinimum); int childIndexCubeMinimum = getMyChildContainingPoint(cubeCornerMinimum);
int childIndexBoxMaximum = getMyChildContainingPoint(boxCornerMaximum); 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 the minimum and maximum corners of the cube are in two different children's cubes, then we are the containing element
if (childIndexBoxMinimum != childIndexBoxMaximum) { if (childIndexCubeMinimum != childIndexCubeMaximum) {
return this; return this;
} }
// otherwise, they are the same and that child should be considered as the correct element // 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 // Now, check if we have a child at that location
child = getChildAtIndex(childIndex); 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... // 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 { int OctreeElement::getMyChildContainingPoint(const glm::vec3& point) const {
glm::vec3 ourCenter = _box.calcCenter(); glm::vec3 ourCenter = _cube.calcCenter();
int childIndex = CHILD_UNKNOWN; int childIndex = CHILD_UNKNOWN;
// left half // left half
if (point.x > ourCenter.x) { if (point.x > ourCenter.x) {

View file

@ -20,7 +20,7 @@
#include <SharedUtil.h> #include <SharedUtil.h>
#include "AABox.h" #include "AACube.h"
#include "ViewFrustum.h" #include "ViewFrustum.h"
#include "OctreeConstants.h" #include "OctreeConstants.h"
@ -116,9 +116,9 @@ public:
bool safeDeepDeleteChildAtIndex(int childIndex, int recursionCount = 0); bool safeDeepDeleteChildAtIndex(int childIndex, int recursionCount = 0);
const AABox& getAABox() const { return _box; } const AACube& getAACube() const { return _cube; }
const glm::vec3& getCorner() const { return _box.getCorner(); } const glm::vec3& getCorner() const { return _cube.getCorner(); }
float getScale() const { return _box.getScale(); } float getScale() const { return _cube.getScale(); }
int getLevel() const { return numberOfThreeBitSectionsInCode(getOctalCode()) + 1; } int getLevel() const { return numberOfThreeBitSectionsInCode(getOctalCode()) + 1; }
float getEnclosingRadius() const; float getEnclosingRadius() const;
@ -223,7 +223,7 @@ public:
OctreeElement* getOrCreateChildElementAt(float x, float y, float z, float s); 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; int getMyChildContainingPoint(const glm::vec3& point) const;
protected: protected:
@ -240,11 +240,11 @@ protected:
void encodeThreeOffsets(int64_t offsetOne, int64_t offsetTwo, int64_t offsetThree); void encodeThreeOffsets(int64_t offsetOne, int64_t offsetTwo, int64_t offsetThree);
void checkStoreFourChildren(OctreeElement* childOne, OctreeElement* childTwo, OctreeElement* childThree, OctreeElement* childFour); void checkStoreFourChildren(OctreeElement* childOne, OctreeElement* childTwo, OctreeElement* childThree, OctreeElement* childFour);
#endif #endif
void calculateAABox(); void calculateAACube();
void notifyDeleteHooks(); void notifyDeleteHooks();
void notifyUpdateHooks(); 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 /// Client and server, buffer containing the octal code or a pointer to octal code for this node, 8 bytes
union octalCode_t { union octalCode_t {

View file

@ -95,10 +95,10 @@ void OctreeHeadlessViewer::queryOctree() {
if (rootCode) { if (rootCode) {
VoxelPositionSize rootDetails; VoxelPositionSize rootDetails;
voxelDetailsForCode(rootCode, 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); serverBounds.scale(TREE_SCALE);
ViewFrustum::location serverFrustumLocation = _viewFrustum.boxInFrustum(serverBounds); ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds);
if (serverFrustumLocation != ViewFrustum::OUTSIDE) { if (serverFrustumLocation != ViewFrustum::OUTSIDE) {
inViewServers++; inViewServers++;
@ -161,10 +161,10 @@ void OctreeHeadlessViewer::queryOctree() {
if (rootCode) { if (rootCode) {
VoxelPositionSize rootDetails; VoxelPositionSize rootDetails;
voxelDetailsForCode(rootCode, 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); serverBounds.scale(TREE_SCALE);
ViewFrustum::location serverFrustumLocation = _viewFrustum.boxInFrustum(serverBounds); ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds);
if (serverFrustumLocation != ViewFrustum::OUTSIDE) { if (serverFrustumLocation != ViewFrustum::OUTSIDE) {
inView = true; inView = true;
} else { } else {

View file

@ -141,7 +141,7 @@ void ViewFrustum::calculate() {
// Set up our keyhole bounding box... // Set up our keyhole bounding box...
glm::vec3 corner = _position - _keyholeRadius; glm::vec3 corner = _position - _keyholeRadius;
_keyholeBoundingBox = AABox(corner,(_keyholeRadius * 2.0f)); _keyholeBoundingCube = AACube(corner,(_keyholeRadius * 2.0f));
} }
void ViewFrustum::calculateOrthographic() { void ViewFrustum::calculateOrthographic() {
@ -184,7 +184,7 @@ void ViewFrustum::calculateOrthographic() {
// Set up our keyhole bounding box... // Set up our keyhole bounding box...
glm::vec3 corner = _position - _keyholeRadius; 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 }; //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 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 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 // 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 // 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 // this and not check with sphere penetration which is more expensive
if (!_keyholeBoundingBox.contains(box)) { if (!_keyholeBoundingCube.contains(box)) {
return OUTSIDE; 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 regularResult = INSIDE;
ViewFrustum::location keyholeResult = OUTSIDE; ViewFrustum::location keyholeResult = OUTSIDE;
// If we have a keyholeRadius, check that first, since it's cheaper // If we have a keyholeRadius, check that first, since it's cheaper
if (_keyholeRadius >= 0.0f) { if (_keyholeRadius >= 0.0f) {
keyholeResult = boxInKeyhole(box); keyholeResult = cubeInKeyhole(cube);
} }
if (keyholeResult == INSIDE) { if (keyholeResult == INSIDE) {
return keyholeResult; 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. // also be able to test against the cone to the bounding sphere of the box.
for(int i=0; i < 6; i++) { for(int i=0; i < 6; i++) {
const glm::vec3& normal = _planes[i].getNormal(); 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); 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); float planeToBoxVertexNDistance = _planes[i].distance(boxVertexN);
if (planeToBoxVertexPDistance < 0) { 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 MAX_POSSIBLE_COMBINATIONS = 43;
const int hullVertexLookup[MAX_POSSIBLE_COMBINATIONS][MAX_PROJECTED_POLYGON_VERTEX_COUNT+1] = { 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
{0}, // inside {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 {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(); const glm::vec3& bottomNearRight = box.getCorner();
glm::vec3 topFarLeft = box.calcTopFarLeft(); 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 // 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 // axis-aligned voxels to determine which of the voxels vertices must be the furthest. No need for
// squares and square-roots. Just compares. // 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(); const glm::vec3& bottomNearRight = box.getCorner();
float scale = box.getScale(); float scale = box.getScale();
float halfScale = scale * 0.5f; 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(); const glm::vec3& bottomNearRight = box.getCorner();
float scale = box.getScale(); float scale = box.getScale();
float halfScale = scale * 0.5f; float halfScale = scale * 0.5f;

View file

@ -18,6 +18,7 @@
#include <glm/gtc/quaternion.hpp> #include <glm/gtc/quaternion.hpp>
#include "AABox.h" #include "AABox.h"
#include "AACube.h"
#include "Plane.h" #include "Plane.h"
#include "OctreeConstants.h" #include "OctreeConstants.h"
#include "OctreeProjectedPolygon.h" #include "OctreeProjectedPolygon.h"
@ -94,6 +95,7 @@ public:
ViewFrustum::location pointInFrustum(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 sphereInFrustum(const glm::vec3& center, float radius) const;
ViewFrustum::location cubeInFrustum(const AACube& cube) const;
ViewFrustum::location boxInFrustum(const AABox& box) const; ViewFrustum::location boxInFrustum(const AABox& box) const;
// some frustum comparisons // some frustum comparisons
@ -111,16 +113,17 @@ public:
void printDebugDetails() const; void printDebugDetails() const;
glm::vec2 projectPoint(glm::vec3 point, bool& pointInView) const; glm::vec2 projectPoint(glm::vec3 point, bool& pointInView) const;
OctreeProjectedPolygon getProjectedPolygon(const AABox& box) const; OctreeProjectedPolygon getProjectedPolygon(const AACube& box) const;
void getFurthestPointFromCamera(const AABox& box, glm::vec3& furthestPoint) 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 // 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: private:
// Used for keyhole calculations // Used for keyhole calculations
ViewFrustum::location pointInKeyhole(const glm::vec3& point) const; ViewFrustum::location pointInKeyhole(const glm::vec3& point) const;
ViewFrustum::location sphereInKeyhole(const glm::vec3& center, float radius) 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; ViewFrustum::location boxInKeyhole(const AABox& box) const;
void calculateOrthographic(); void calculateOrthographic();
@ -149,7 +152,7 @@ private:
// keyhole attributes // keyhole attributes
float _keyholeRadius; float _keyholeRadius;
AABox _keyholeBoundingBox; AACube _keyholeBoundingCube;
// Calculated values // Calculated values

View file

@ -237,7 +237,7 @@ bool ParticleTree::findNearPointOperation(OctreeElement* element, void* extraDat
ParticleTreeElement* particleTreeElement = static_cast<ParticleTreeElement*>(element); ParticleTreeElement* particleTreeElement = static_cast<ParticleTreeElement*>(element);
glm::vec3 penetration; glm::vec3 penetration;
bool sphereIntersection = particleTreeElement->getAABox().findSpherePenetration(args->position, bool sphereIntersection = particleTreeElement->getAACube().findSpherePenetration(args->position,
args->targetRadius, penetration); args->targetRadius, penetration);
// If this particleTreeElement contains the point, then search it... // If this particleTreeElement contains the point, then search it...
@ -287,7 +287,7 @@ public:
bool ParticleTree::findInSphereOperation(OctreeElement* element, void* extraData) { bool ParticleTree::findInSphereOperation(OctreeElement* element, void* extraData) {
FindAllNearPointArgs* args = static_cast<FindAllNearPointArgs*>(extraData); FindAllNearPointArgs* args = static_cast<FindAllNearPointArgs*>(extraData);
glm::vec3 penetration; glm::vec3 penetration;
bool sphereIntersection = element->getAABox().findSpherePenetration(args->position, bool sphereIntersection = element->getAACube().findSpherePenetration(args->position,
args->targetRadius, penetration); args->targetRadius, penetration);
// If this element contains the point, then search it... // 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); foundParticles.swap(args.particles);
} }
class FindParticlesInBoxArgs { class FindParticlesInCubeArgs {
public: public:
FindParticlesInBoxArgs(const AABox& box) FindParticlesInCubeArgs(const AACube& cube)
: _box(box), _foundParticles() { : _cube(cube), _foundParticles() {
} }
AABox _box; AACube _cube;
QVector<Particle*> _foundParticles; QVector<Particle*> _foundParticles;
}; };
bool ParticleTree::findInBoxForUpdateOperation(OctreeElement* element, void* extraData) { bool ParticleTree::findInCubeForUpdateOperation(OctreeElement* element, void* extraData) {
FindParticlesInBoxArgs* args = static_cast< FindParticlesInBoxArgs*>(extraData); FindParticlesInCubeArgs* args = static_cast< FindParticlesInCubeArgs*>(extraData);
const AABox& elementBox = element->getAABox(); const AACube& elementBox = element->getAACube();
if (elementBox.touches(args->_box)) { if (elementBox.touches(args->_cube)) {
ParticleTreeElement* particleTreeElement = static_cast<ParticleTreeElement*>(element); ParticleTreeElement* particleTreeElement = static_cast<ParticleTreeElement*>(element);
particleTreeElement->getParticlesForUpdate(args->_box, args->_foundParticles); particleTreeElement->getParticlesForUpdate(args->_cube, args->_foundParticles);
return true; return true;
} }
return false; return false;
} }
void ParticleTree::findParticlesForUpdate(const AABox& box, QVector<Particle*> foundParticles) { void ParticleTree::findParticlesForUpdate(const AACube& cube, QVector<Particle*> foundParticles) {
FindParticlesInBoxArgs args(box); FindParticlesInCubeArgs args(cube);
lockForRead(); lockForRead();
recurseTreeWithOperation(findInBoxForUpdateOperation, &args); recurseTreeWithOperation(findInCubeForUpdateOperation, &args);
unlock(); unlock();
// swap the two lists of particle pointers instead of copy // swap the two lists of particle pointers instead of copy
foundParticles.swap(args._foundParticles); foundParticles.swap(args._foundParticles);
@ -473,7 +473,7 @@ void ParticleTree::update() {
bool shouldDie = args._movingParticles[i].getShouldDie(); bool shouldDie = args._movingParticles[i].getShouldDie();
// if the particle is still inside our total bounds, then re-add it // 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())) { if (!shouldDie && treeBounds.contains(args._movingParticles[i].getPosition())) {
storeParticle(args._movingParticles[i]); storeParticle(args._movingParticles[i]);

View file

@ -60,7 +60,7 @@ public:
/// \param box the query box /// \param box the query box
/// \param foundParticles[out] vector of non-const Particle* /// \param foundParticles[out] vector of non-const Particle*
/// \remark Side effect: any initial contents in particles will be lost /// \remark Side effect: any initial contents in particles will be lost
void findParticlesForUpdate(const AABox& box, QVector<Particle*> foundParticles); void findParticlesForUpdate(const AACube& box, QVector<Particle*> foundParticles);
void addNewlyCreatedHook(NewlyCreatedParticleHook* hook); void addNewlyCreatedHook(NewlyCreatedParticleHook* hook);
void removeNewlyCreatedHook(NewlyCreatedParticleHook* hook); void removeNewlyCreatedHook(NewlyCreatedParticleHook* hook);
@ -84,7 +84,7 @@ private:
static bool findByIDOperation(OctreeElement* element, void* extraData); static bool findByIDOperation(OctreeElement* element, void* extraData);
static bool findAndDeleteOperation(OctreeElement* element, void* extraData); static bool findAndDeleteOperation(OctreeElement* element, void* extraData);
static bool findAndUpdateParticleIDOperation(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); void notifyNewlyCreatedParticle(const Particle& newParticle, const SharedNodePointer& senderNode);

View file

@ -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 // 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 // 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); args._movingParticles.push_back(particle);
// erase this particle // erase this particle
@ -244,18 +244,18 @@ void ParticleTreeElement::getParticles(const glm::vec3& searchPosition, float se
} }
} }
void ParticleTreeElement::getParticlesForUpdate(const AABox& box, QVector<Particle*>& foundParticles) { void ParticleTreeElement::getParticlesForUpdate(const AACube& box, QVector<Particle*>& foundParticles) {
QList<Particle>::iterator particleItr = _particles->begin(); QList<Particle>::iterator particleItr = _particles->begin();
QList<Particle>::iterator particleEnd = _particles->end(); QList<Particle>::iterator particleEnd = _particles->end();
AABox particleBox; AACube particleCube;
while(particleItr != particleEnd) { while(particleItr != particleEnd) {
Particle* particle = &(*particleItr); Particle* particle = &(*particleItr);
float radius = particle->getRadius(); float radius = particle->getRadius();
// NOTE: we actually do box-box collision queries here, which is sloppy but good enough for now // 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 // TODO: decide whether to replace particleBox-box query with sphere-box (requires a square root
// but will be slightly more accurate). // but will be slightly more accurate).
particleBox.setBox(particle->getPosition() - glm::vec3(radius), 2.f * radius); particleCube.setBox(particle->getPosition() - glm::vec3(radius), 2.f * radius);
if (particleBox.touches(_box)) { if (particleCube.touches(_cube)) {
foundParticles.push_back(particle); foundParticles.push_back(particle);
} }
++particleItr; ++particleItr;

View file

@ -114,7 +114,7 @@ public:
/// finds all particles that touch a box /// finds all particles that touch a box
/// \param box the query box /// \param box the query box
/// \param particles[out] vector of non-const Particle* /// \param particles[out] vector of non-const Particle*
void getParticlesForUpdate(const AABox& box, QVector<Particle*>& foundParticles); void getParticlesForUpdate(const AACube& box, QVector<Particle*>& foundParticles);
const Particle* getParticleWithID(uint32_t id) const; const Particle* getParticleWithID(uint32_t id) const;

View file

@ -14,7 +14,7 @@
#include <QtScript/QScriptEngine> #include <QtScript/QScriptEngine>
#include <AABox.h> #include <AACube.h>
#include <SharedUtil.h> #include <SharedUtil.h>
#include "VoxelConstants.h" #include "VoxelConstants.h"

View file

@ -224,15 +224,15 @@ bool VoxelTreeElement::collapseChildren() {
bool VoxelTreeElement::findSpherePenetration(const glm::vec3& center, float radius, bool VoxelTreeElement::findSpherePenetration(const glm::vec3& center, float radius,
glm::vec3& penetration, void** penetratedObject) const { 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 the caller wants details about the voxel, then return them here...
if (penetratedObject) { if (penetratedObject) {
VoxelDetail* voxelDetails = new VoxelDetail; VoxelDetail* voxelDetails = new VoxelDetail;
voxelDetails->x = _box.getCorner().x; voxelDetails->x = _cube.getCorner().x;
voxelDetails->y = _box.getCorner().y; voxelDetails->y = _cube.getCorner().y;
voxelDetails->z = _box.getCorner().z; voxelDetails->z = _cube.getCorner().z;
voxelDetails->s = _box.getScale(); voxelDetails->s = _cube.getScale();
voxelDetails->red = getColor()[RED_INDEX]; voxelDetails->red = getColor()[RED_INDEX];
voxelDetails->green = getColor()[GREEN_INDEX]; voxelDetails->green = getColor()[GREEN_INDEX];
voxelDetails->blue = getColor()[BLUE_INDEX]; voxelDetails->blue = getColor()[BLUE_INDEX];

View file

@ -18,7 +18,7 @@
#include <QReadWriteLock> #include <QReadWriteLock>
#include <AABox.h> #include <AACube.h>
#include <OctreeElement.h> #include <OctreeElement.h>
#include <SharedUtil.h> #include <SharedUtil.h>