improvements to subtle moves for view frustum and voxel serving

This commit is contained in:
ZappoMan 2013-10-23 17:49:58 -07:00
parent 0188d55ad3
commit b4c88a85f8
9 changed files with 133 additions and 21 deletions

View file

@ -1700,7 +1700,7 @@ bool VoxelSystem::isViewChanging() {
bool result = false; // assume the best
// If our viewFrustum has changed since our _lastKnownViewFrustum
if (!_lastKnownViewFrustum.matches(_viewFrustum)) {
if (!_lastKnownViewFrustum.isVerySimilar(_viewFrustum)) {
result = true;
_lastKnownViewFrustum = *_viewFrustum; // save last known
}
@ -1716,7 +1716,7 @@ bool VoxelSystem::hasViewChanged() {
}
// If our viewFrustum has changed since our _lastKnownViewFrustum
if (!_lastStableViewFrustum.matches(_viewFrustum)) {
if (!_lastStableViewFrustum.isVerySimilar(_viewFrustum)) {
result = true;
_lastStableViewFrustum = *_viewFrustum; // save last stable
}
@ -1867,7 +1867,7 @@ void VoxelSystem::hideOutOfView(bool forceFullFrustum) {
}
}
if (!forceFullFrustum && _culledOnce && args.lastViewFrustum.matches(args.thisViewFrustum)) {
if (!forceFullFrustum && _culledOnce && args.lastViewFrustum.isVerySimilar(args.thisViewFrustum)) {
//printf("view frustum hasn't changed BAIL!!!\n");
return;
}

View file

@ -84,7 +84,7 @@ bool VoxelNodeData::updateCurrentViewFrustum() {
newestViewFrustum.setEyeOffsetPosition(getCameraEyeOffsetPosition());
// if there has been a change, then recalculate
if (!newestViewFrustum.matches(_currentViewFrustum)) {
if (!newestViewFrustum.isVerySimilar(_currentViewFrustum)) {
_currentViewFrustum = newestViewFrustum;
_currentViewFrustum.calculate();
currentViewFrustumChanged = true;
@ -109,7 +109,7 @@ void VoxelNodeData::setViewSent(bool viewSent) {
void VoxelNodeData::updateLastKnownViewFrustum() {
bool frustumChanges = !_lastKnownViewFrustum.matches(_currentViewFrustum);
bool frustumChanges = !_lastKnownViewFrustum.isVerySimilar(_currentViewFrustum);
if (frustumChanges) {
// save our currentViewFrustum into our lastKnownViewFrustum

View file

@ -10,6 +10,8 @@
#include <algorithm>
#include <glm/glm.hpp>
#include <glm/gtx/quaternion.hpp>
#include <glm/gtx/transform.hpp>
#include <QtCore/QDebug>
@ -296,17 +298,17 @@ ViewFrustum::location ViewFrustum::boxInFrustum(const AABox& box) const {
return regularResult;
}
bool testMatches(glm::quat lhs, glm::quat rhs) {
return (fabs(lhs.x - rhs.x) <= EPSILON && fabs(lhs.y - rhs.y) <= EPSILON && fabs(lhs.z - rhs.z) <= EPSILON
&& fabs(lhs.w - rhs.w) <= EPSILON);
bool testMatches(glm::quat lhs, glm::quat rhs, float epsilon = EPSILON) {
return (fabs(lhs.x - rhs.x) <= epsilon && fabs(lhs.y - rhs.y) <= epsilon && fabs(lhs.z - rhs.z) <= epsilon
&& fabs(lhs.w - rhs.w) <= epsilon);
}
bool testMatches(glm::vec3 lhs, glm::vec3 rhs) {
return (fabs(lhs.x - rhs.x) <= EPSILON && fabs(lhs.y - rhs.y) <= EPSILON && fabs(lhs.z - rhs.z) <= EPSILON);
bool testMatches(glm::vec3 lhs, glm::vec3 rhs, float epsilon = EPSILON) {
return (fabs(lhs.x - rhs.x) <= epsilon && fabs(lhs.y - rhs.y) <= epsilon && fabs(lhs.z - rhs.z) <= epsilon);
}
bool testMatches(float lhs, float rhs) {
return (fabs(lhs - rhs) <= EPSILON);
bool testMatches(float lhs, float rhs, float epsilon = EPSILON) {
return (fabs(lhs - rhs) <= epsilon);
}
bool ViewFrustum::matches(const ViewFrustum& compareTo, bool debug) const {
@ -369,6 +371,93 @@ bool ViewFrustum::matches(const ViewFrustum& compareTo, bool debug) const {
return result;
}
bool isNaN(float f) {
return f != f;
}
bool ViewFrustum::isVerySimilar(const ViewFrustum& compareTo, bool debug) const {
// Compute distance between the two positions
const float POSITION_SIMILAR_ENOUGH = 5.0f; // 5 meters
float positionDistance = glm::distance(_position, compareTo._position);
const float EYEOFFSET_POSITION_SIMILAR_ENOUGH = 0.15f; // 0.15 meters
float eyeOffsetpositionDistance = glm::distance(_eyeOffsetPosition, compareTo._eyeOffsetPosition);
// Compute the angular distance between the two orientations
const float ORIENTATION_SIMILAR_ENOUGH = 10.0f; // 10 degrees in any direction
glm::quat dQOrientation = _orientation * glm::inverse(compareTo._orientation);
float angleOrientation = compareTo._orientation == _orientation ? 0.0f : glm::angle(dQOrientation);
if (isNaN(angleOrientation)) {
angleOrientation = 0.0f;
}
glm::quat dQEyeOffsetOrientation = _eyeOffsetOrientation * glm::inverse(compareTo._eyeOffsetOrientation);
float angleEyeOffsetOrientation = compareTo._eyeOffsetOrientation == _eyeOffsetOrientation
? 0.0f : glm::angle(dQEyeOffsetOrientation);
if (isNaN(angleEyeOffsetOrientation)) {
angleOrientation = 0.0f;
}
bool result =
testMatches(0, positionDistance, POSITION_SIMILAR_ENOUGH) &&
testMatches(0, angleOrientation, ORIENTATION_SIMILAR_ENOUGH) &&
testMatches(compareTo._fieldOfView, _fieldOfView) &&
testMatches(compareTo._aspectRatio, _aspectRatio) &&
testMatches(compareTo._nearClip, _nearClip) &&
testMatches(compareTo._farClip, _farClip) &&
testMatches(compareTo._focalLength, _focalLength) &&
testMatches(0, eyeOffsetpositionDistance, EYEOFFSET_POSITION_SIMILAR_ENOUGH) &&
testMatches(0, angleEyeOffsetOrientation, ORIENTATION_SIMILAR_ENOUGH);
if (!result && debug) {
qDebug("ViewFrustum::isVerySimilar()... result=%s\n", debug::valueOf(result));
qDebug("%s -- compareTo._position=%f,%f,%f _position=%f,%f,%f\n",
(testMatches(compareTo._position,_position, POSITION_SIMILAR_ENOUGH) ? "IS SIMILAR ENOUGH " : "IS NOT SIMILAR ENOUGH"),
compareTo._position.x, compareTo._position.y, compareTo._position.z,
_position.x, _position.y, _position.z );
qDebug("%s -- positionDistance=%f\n",
(testMatches(0,positionDistance, POSITION_SIMILAR_ENOUGH) ? "IS SIMILAR ENOUGH " : "IS NOT SIMILAR ENOUGH"),
positionDistance);
qDebug("%s -- angleOrientation=%f\n",
(testMatches(0, angleOrientation, ORIENTATION_SIMILAR_ENOUGH) ? "IS SIMILAR ENOUGH " : "IS NOT SIMILAR ENOUGH"),
angleOrientation);
qDebug("%s -- compareTo._fieldOfView=%f _fieldOfView=%f\n",
(testMatches(compareTo._fieldOfView, _fieldOfView) ? "MATCHES " : "NO MATCH"),
compareTo._fieldOfView, _fieldOfView);
qDebug("%s -- compareTo._aspectRatio=%f _aspectRatio=%f\n",
(testMatches(compareTo._aspectRatio, _aspectRatio) ? "MATCHES " : "NO MATCH"),
compareTo._aspectRatio, _aspectRatio);
qDebug("%s -- compareTo._nearClip=%f _nearClip=%f\n",
(testMatches(compareTo._nearClip, _nearClip) ? "MATCHES " : "NO MATCH"),
compareTo._nearClip, _nearClip);
qDebug("%s -- compareTo._farClip=%f _farClip=%f\n",
(testMatches(compareTo._farClip, _farClip) ? "MATCHES " : "NO MATCH"),
compareTo._farClip, _farClip);
qDebug("%s -- compareTo._focalLength=%f _focalLength=%f\n",
(testMatches(compareTo._focalLength, _focalLength) ? "MATCHES " : "NO MATCH"),
compareTo._focalLength, _focalLength);
qDebug("%s -- compareTo._eyeOffsetPosition=%f,%f,%f _eyeOffsetPosition=%f,%f,%f\n",
(testMatches(compareTo._eyeOffsetPosition, _eyeOffsetPosition, POSITION_SIMILAR_ENOUGH) ? "IS SIMILAR ENOUGH " : "IS NOT SIMILAR ENOUGH"),
compareTo._eyeOffsetPosition.x, compareTo._eyeOffsetPosition.y, compareTo._eyeOffsetPosition.z,
_eyeOffsetPosition.x, _eyeOffsetPosition.y, _eyeOffsetPosition.z);
qDebug("%s -- eyeOffsetpositionDistance=%f\n",
(testMatches(0,eyeOffsetpositionDistance, EYEOFFSET_POSITION_SIMILAR_ENOUGH) ? "IS SIMILAR ENOUGH " : "IS NOT SIMILAR ENOUGH"),
eyeOffsetpositionDistance);
qDebug("%s -- angleEyeOffsetOrientation=%f\n",
(testMatches(0, angleEyeOffsetOrientation, ORIENTATION_SIMILAR_ENOUGH) ? "IS SIMILAR ENOUGH " : "IS NOT SIMILAR ENOUGH"),
angleEyeOffsetOrientation);
}
return result;
}
void ViewFrustum::computePickRay(float x, float y, glm::vec3& origin, glm::vec3& direction) const {
origin = _nearTopLeft + x*(_nearTopRight - _nearTopLeft) + y*(_nearBottomLeft - _nearTopLeft);
direction = glm::normalize(origin - (_position + _orientation * _eyeOffsetPosition));

View file

@ -85,6 +85,9 @@ public:
bool matches(const ViewFrustum& compareTo, bool debug = false) const;
bool matches(const ViewFrustum* compareTo, bool debug = false) const { return matches(*compareTo, debug); }
bool isVerySimilar(const ViewFrustum& compareTo, bool debug = false) const;
bool isVerySimilar(const ViewFrustum* compareTo, bool debug = false) const { return isVerySimilar(*compareTo, debug); }
void computePickRay(float x, float y, glm::vec3& origin, glm::vec3& direction) const;
void computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& near, float& far,

View file

@ -54,4 +54,9 @@ const uint64_t CLIENT_TO_SERVER_VOXEL_SEND_INTERVAL_USECS = 1000 * 5; // 1 packe
const float VIEW_FRUSTUM_FOV_OVERSEND = 60.0f;
// These are guards to prevent our voxel tree recursive routines from spinning out of control
const int UNREASONABLY_DEEP_RECURSION = 20; // use this for something that you want to be shallow, but not spin out
const int DANGEROUSLY_DEEP_RECURSION = 200; // use this for something that needs to go deeper
#endif

View file

@ -1021,14 +1021,18 @@ VoxelNode* VoxelNode::addChildAtIndex(int childIndex) {
}
// handles staging or deletion of all deep children
void VoxelNode::safeDeepDeleteChildAtIndex(int childIndex) {
void VoxelNode::safeDeepDeleteChildAtIndex(int childIndex, int recursionCount) {
if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
qDebug() << "VoxelNode::safeDeepDeleteChildAtIndex() reached DANGEROUSLY_DEEP_RECURSION, bailing!\n";
return;
}
VoxelNode* childToDelete = getChildAtIndex(childIndex);
if (childToDelete) {
// If the child is not a leaf, then call ourselves recursively on all the children
if (!childToDelete->isLeaf()) {
// delete all it's children
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
childToDelete->safeDeepDeleteChildAtIndex(i);
childToDelete->safeDeepDeleteChildAtIndex(i,recursionCount+1);
}
}
deleteChildAtIndex(childIndex);

View file

@ -48,7 +48,7 @@ public:
void deleteChildAtIndex(int childIndex);
VoxelNode* removeChildAtIndex(int childIndex);
VoxelNode* addChildAtIndex(int childIndex);
void safeDeepDeleteChildAtIndex(int childIndex); // handles deletion of all descendents
void safeDeepDeleteChildAtIndex(int childIndex, int recursionCount = 0); // handles deletion of all descendents
void setColorFromAverageOfChildren();
void setRandomColor(int minimumBrightness);

View file

@ -78,13 +78,18 @@ void VoxelTree::recurseTreeWithOperation(RecurseVoxelTreeOperation operation, vo
}
// Recurses voxel node with an operation function
void VoxelTree::recurseNodeWithOperation(VoxelNode* node, RecurseVoxelTreeOperation operation, void* extraData) {
void VoxelTree::recurseNodeWithOperation(VoxelNode* node, RecurseVoxelTreeOperation operation, void* extraData,
int recursionCount) {
if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
qDebug() << "VoxelTree::recurseNodeWithOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!\n";
return;
}
if (operation(node, extraData)) {
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
VoxelNode* child = node->getChildAtIndex(i);
if (child) {
recurseNodeWithOperation(child, operation, extraData);
recurseNodeWithOperation(child, operation, extraData, recursionCount+1);
}
}
}
@ -100,7 +105,13 @@ void VoxelTree::recurseTreeWithOperationDistanceSorted(RecurseVoxelTreeOperation
// Recurses voxel node with an operation function
void VoxelTree::recurseNodeWithOperationDistanceSorted(VoxelNode* node, RecurseVoxelTreeOperation operation,
const glm::vec3& point, void* extraData) {
const glm::vec3& point, void* extraData, int recursionCount) {
if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
qDebug() << "VoxelTree::recurseNodeWithOperationDistanceSorted() reached DANGEROUSLY_DEEP_RECURSION, bailing!\n";
return;
}
if (operation(node, extraData)) {
// determine the distance sorted order of our children
VoxelNode* sortedChildren[NUMBER_OF_CHILDREN];
@ -641,7 +652,6 @@ void VoxelTree::reaverageVoxelColors(VoxelNode* startNode) {
} else {
recursionCount++;
}
const int UNREASONABLY_DEEP_RECURSION = 20;
if (recursionCount > UNREASONABLY_DEEP_RECURSION) {
qDebug("VoxelTree::reaverageVoxelColors()... bailing out of UNREASONABLY_DEEP_RECURSION\n");
recursionCount--;

View file

@ -190,10 +190,11 @@ public:
bool getShouldReaverage() const { return _shouldReaverage; }
void recurseNodeWithOperation(VoxelNode* node, RecurseVoxelTreeOperation operation, void* extraData);
void recurseNodeWithOperation(VoxelNode* node, RecurseVoxelTreeOperation operation,
void* extraData, int recursionCount = 0);
void recurseNodeWithOperationDistanceSorted(VoxelNode* node, RecurseVoxelTreeOperation operation,
const glm::vec3& point, void* extraData);
const glm::vec3& point, void* extraData, int recursionCount = 0);
void nudgeSubTree(VoxelNode* nodeToNudge, const glm::vec3& nudgeAmount, VoxelEditPacketSender& voxelEditSender);