mirror of
https://github.com/overte-org/overte.git
synced 2025-08-16 11:12:25 +02:00
Merge pull request #694 from ZappoMan/voxel_animation
Fixed issue of "delta sending" not sending changed/animated voxels
This commit is contained in:
commit
5c279777b6
9 changed files with 56 additions and 17 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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; };
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
{}
|
||||
};
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue