Merge pull request #694 from ZappoMan/voxel_animation

Fixed issue of "delta sending" not sending changed/animated voxels
This commit is contained in:
Stephen Birarda 2013-07-16 17:31:16 -07:00
commit 5c279777b6
9 changed files with 56 additions and 17 deletions

View file

@ -222,7 +222,7 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
memcpy(&handPositionRelative, sourceBuffer, sizeof(float) * 3);
_handPosition = _position + handPositionRelative;
sourceBuffer += sizeof(float) * 3;
// Lookat Position
memcpy(&_headData->_lookAtPosition, sourceBuffer, sizeof(_headData->_lookAtPosition));
sourceBuffer += sizeof(_headData->_lookAtPosition);
@ -430,4 +430,3 @@ int unpackFloatFromByte(unsigned char* buffer, float& value, float scaleBy) {
value = ((float)holder / (float) 255) * scaleBy;
return sizeof(holder);
}

View file

@ -29,7 +29,6 @@ const int WANT_OCCLUSION_CULLING_BIT = 7; // 8th bit
const float MAX_AUDIO_LOUDNESS = 1000.0; // close enough for mouth animation
enum KeyState
{
NO_KEY_DOWN = 0,

View file

@ -7,6 +7,7 @@
//
#include <algorithm> // std:min
#include <cassert>
#include <cmath>
#include <cstring>
@ -16,6 +17,7 @@
#include "OctalCode.h"
int numberOfThreeBitSectionsInCode(unsigned char * octalCode) {
assert(octalCode);
if (*octalCode == 255) {
return *octalCode + numberOfThreeBitSectionsInCode(octalCode + 1);
} else {

View file

@ -21,6 +21,7 @@ const glm::vec3 IDENTITY_UP = glm::vec3( 0.0f, 1.0f, 0.0f);
const glm::vec3 IDENTITY_FRONT = glm::vec3( 0.0f, 0.0f,-1.0f);
const bool LOW_RES_MONO = false; // while in "low res mode" do voxels switch to monochrome
const uint64_t CHANGE_FUDGE = 1000 * 200; // useconds of fudge in determining if we want to resend changed voxels
const int TREE_SCALE = 128;

View file

@ -85,6 +85,7 @@ public:
void clearDirtyBit() { _isDirty = false; };
bool hasChangedSince(uint64_t time) const { return (_lastChanged > time); };
void markWithChangedTime() { _lastChanged = usecTimestampNow(); };
uint64_t getLastChanged() const { return _lastChanged; };
void handleSubtreeChanged(VoxelTree* myTree);
glBufferIndex getBufferIndex() const { return _glBufferIndex; };

View file

@ -373,7 +373,6 @@ void VoxelTree::deleteVoxelAt(float x, float y, float z, float s, bool stage) {
delete[] octalCode; // cleanup memory
}
class DeleteVoxelCodeFromTreeArgs {
public:
bool stage;
@ -1005,17 +1004,24 @@ bool VoxelTree::findCapsulePenetration(const glm::vec3& start, const glm::vec3&
return args.found;
}
int VoxelTree::encodeTreeBitstream(VoxelNode* node, unsigned char* outputBuffer, int availableBytes, VoxelNodeBag& bag,
EncodeBitstreamParams& params) const {
// How many bytes have we written so far at this level;
int bytesWritten = 0;
// These two cases should not ever happen... but if they do, we don't want to crash.
if (!node || !node->getOctalCode()) {
qDebug("VoxelTree::encodeTreeBitstream() BAD VoxelNode! Bailing!");
return bytesWritten;
}
// If we're at a node that is out of view, then we can return, because no nodes below us will be in view!
if (params.viewFrustum && !node->isInView(*params.viewFrustum)) {
return bytesWritten;
}
// write the octal code
int codeLength;
if (params.chopLevels) {
@ -1074,7 +1080,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
if (currentEncodeLevel >= params.maxEncodeLevel) {
return bytesAtThisLevel;
}
// caller can pass NULL as viewFrustum if they want everything
if (params.viewFrustum) {
float distance = node->distanceToCamera(*params.viewFrustum);
@ -1107,10 +1113,21 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
}
}
// If we were in view, then bail out early!
if (wasInView) {
// If we were previously in the view, then we normally will return out of here and stop recursing. But
// if we're in deltaViewFrustum mode, and this node has changed since it was last sent, then we do
// need to send it.
if (wasInView && !(params.deltaViewFrustum && node->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))) {
return bytesAtThisLevel;
}
}
/** Not ready for production - coming soon.
// If we're not in delta sending mode, but the voxel hasn't changed, then we can also bail early...
if (!params.deltaViewFrustum && !node->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE)) {
printf("not delta sending, and the node hasn't changed, bail early... lastSent=%lld getLastChanged=%lld\n",
params.lastViewFrustumSent, node->getLastChanged());
return bytesAtThisLevel;
}
**/
// If the user also asked for occlusion culling, check if this node is occluded, but only if it's not a leaf.
// leaf occlusion is handled down below when we check child nodes
@ -1270,8 +1287,12 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
}
}
// If our child wasn't in view (or we're ignoring wasInView) then we add it to our sending items
if (!childWasInView) {
// If our child wasn't in view (or we're ignoring wasInView) then we add it to our sending items.
// Or if we were previously in the view, but this node has changed since it was last sent, then we do
// need to send it.
if (!childWasInView ||
(params.deltaViewFrustum &&
childNode->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))){
childrenColoredBits += (1 << (7 - originalIndex));
inViewWithColorCount++;
} else {
@ -1355,7 +1376,6 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
if (oneAtBit(childrenExistInPacketBits, originalIndex)) {
int thisLevel = currentEncodeLevel;
// remember this for reshuffling
recursiveSliceStarts[originalIndex] = outputBuffer;

View file

@ -35,6 +35,7 @@ typedef enum {GRADIENT, RANDOM, NATURAL} creationMode;
#define DONT_CHOP 0
#define NO_BOUNDARY_ADJUST 0
#define LOW_RES_MOVING_ADJUST 1
#define IGNORE_LAST_SENT 0
class EncodeBitstreamParams {
public:
@ -49,6 +50,7 @@ public:
bool wantOcclusionCulling;
long childWasInViewDiscarded;
int boundaryLevelAdjust;
uint64_t lastViewFrustumSent;
CoverageMap* map;
@ -62,7 +64,8 @@ public:
const ViewFrustum* lastViewFrustum = IGNORE_VIEW_FRUSTUM,
bool wantOcclusionCulling= NO_OCCLUSION_CULLING,
CoverageMap* map = IGNORE_COVERAGE_MAP,
int boundaryLevelAdjust = NO_BOUNDARY_ADJUST) :
int boundaryLevelAdjust = NO_BOUNDARY_ADJUST,
uint64_t lastViewFrustumSent = IGNORE_LAST_SENT) :
maxEncodeLevel (maxEncodeLevel),
maxLevelReached (0),
viewFrustum (viewFrustum),
@ -74,6 +77,7 @@ public:
wantOcclusionCulling (wantOcclusionCulling),
childWasInViewDiscarded (0),
boundaryLevelAdjust (boundaryLevelAdjust),
lastViewFrustumSent (lastViewFrustumSent),
map (map)
{}
};

View file

@ -7,6 +7,7 @@
//
#include "PacketHeaders.h"
#include "SharedUtil.h"
#include "VoxelNodeData.h"
#include <cstring>
#include <cstdio>
@ -23,7 +24,6 @@ VoxelNodeData::VoxelNodeData(Node* owningNode) :
{
_voxelPacket = new unsigned char[MAX_VOXEL_PACKET_SIZE];
_voxelPacketAt = _voxelPacket;
resetVoxelPacket();
}
@ -80,5 +80,9 @@ void VoxelNodeData::updateLastKnownViewFrustum() {
// save our currentViewFrustum into our lastKnownViewFrustum
_lastKnownViewFrustum = _currentViewFrustum;
}
// save that we know the view has been sent.
uint64_t now = usecTimestampNow();
setLastTimeBagEmpty(now); // is this what we want? poor names
}

View file

@ -173,10 +173,10 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
// If the current view frustum has changed OR we have nothing to send, then search against
// the current view frustum for things to send.
if (viewFrustumChanged || nodeData->nodeBag.isEmpty()) {
uint64_t now = usecTimestampNow();
if (::debugVoxelSending) {
printf("(viewFrustumChanged=%s || nodeData->nodeBag.isEmpty() =%s)...\n",
debug::valueOf(viewFrustumChanged), debug::valueOf(nodeData->nodeBag.isEmpty()));
uint64_t now = usecTimestampNow();
if (nodeData->getLastTimeBagEmpty() > 0) {
float elapsedSceneSend = (now - nodeData->getLastTimeBagEmpty()) / 1000000.0f;
if (viewFrustumChanged) {
@ -188,13 +188,21 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
debug::valueOf(nodeData->getWantOcclusionCulling()), debug::valueOf(wantDelta),
debug::valueOf(wantColor));
}
nodeData->setLastTimeBagEmpty(now); // huh? why is this inside debug? probably not what we want
}
// if our view has changed, we need to reset these things...
if (viewFrustumChanged) {
nodeData->nodeBag.deleteAll();
nodeData->map.erase();
}
if (!viewFrustumChanged && !nodeData->getWantDelta()) {
// only set our last sent time if we weren't resetting due to frustum change
uint64_t now = usecTimestampNow();
nodeData->setLastTimeBagEmpty(now);
if (::debugVoxelSending) {
printf("ENTIRE SCENE SENT! nodeData->setLastTimeBagEmpty(now=[%lld])\n", now);
}
}
nodeData->nodeBag.insert(serverTree.rootNode);
@ -233,7 +241,8 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
EncodeBitstreamParams params(INT_MAX, &nodeData->getCurrentViewFrustum(), wantColor,
WANT_EXISTS_BITS, DONT_CHOP, wantDelta, lastViewFrustum,
wantOcclusionCulling, coverageMap, boundaryLevelAdjust);
wantOcclusionCulling, coverageMap, boundaryLevelAdjust,
nodeData->getLastTimeBagEmpty());
bytesWritten = serverTree.encodeTreeBitstream(subTree, &tempOutputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1,
nodeData->nodeBag, params);