mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 22:44:15 +02:00
working on addressing issues with sibling cells and server clock skew causing some properties to be ignored
This commit is contained in:
parent
1fa587b88a
commit
b244e78af4
13 changed files with 923 additions and 137 deletions
|
@ -61,9 +61,9 @@ bool BoxEntityItem::setProperties(const EntityItemProperties& properties, bool f
|
|||
bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
uint64_t now = usecTimestampNow();
|
||||
int elapsed = now - _lastEdited;
|
||||
int elapsed = now - getLastEdited();
|
||||
qDebug() << "BoxEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
|
||||
"now=" << now << " _lastEdited=" << _lastEdited;
|
||||
"now=" << now << " getLastEdited()=" << getLastEdited();
|
||||
}
|
||||
setLastEdited(properties._lastEdited);
|
||||
}
|
||||
|
|
|
@ -42,7 +42,9 @@ void EntityItem::initFromEntityItemID(const EntityItemID& entityItemID) {
|
|||
|
||||
// init values with defaults before calling setProperties
|
||||
//uint64_t now = usecTimestampNow();
|
||||
_lastEdited = 0;
|
||||
_lastEditedRemote = 0;
|
||||
_lastEditedLocal = 0;
|
||||
//_lastEdited = 0;
|
||||
_lastUpdated = 0;
|
||||
_created = 0; // TODO: when do we actually want to make this "now"
|
||||
|
||||
|
@ -60,7 +62,9 @@ void EntityItem::initFromEntityItemID(const EntityItemID& entityItemID) {
|
|||
|
||||
EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) {
|
||||
_type = EntityTypes::Unknown;
|
||||
_lastEdited = 0;
|
||||
_lastEditedRemote = 0;
|
||||
_lastEditedLocal = 0;
|
||||
//_lastEdited = 0;
|
||||
_lastUpdated = 0;
|
||||
_created = properties.getCreated();
|
||||
initFromEntityItemID(entityItemID);
|
||||
|
@ -84,7 +88,16 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param
|
|||
}
|
||||
|
||||
OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
||||
EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData) const {
|
||||
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData) const {
|
||||
|
||||
|
||||
const bool wantDebug = false;
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "EntityItem::appendEntityData()....";
|
||||
qDebug() << " entity=" << this;
|
||||
qDebug() << " entityItemID=" << getEntityItemID();
|
||||
}
|
||||
|
||||
// ALL this fits...
|
||||
// object ID [16 bytes]
|
||||
|
@ -111,9 +124,42 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
EntityPropertyFlags propertiesDidntFit = requestedProperties;
|
||||
|
||||
// If we are being called for a subsequent pass at appendEntityData() that failed to completely encode this item,
|
||||
// then our modelTreeElementExtraEncodeData should include data about which properties we need to append.
|
||||
if (modelTreeElementExtraEncodeData && modelTreeElementExtraEncodeData->includedItems.contains(getEntityItemID())) {
|
||||
requestedProperties = modelTreeElementExtraEncodeData->includedItems.value(getEntityItemID());
|
||||
// then our entityTreeElementExtraEncodeData should include data about which properties we need to append.
|
||||
if (entityTreeElementExtraEncodeData && wantDebug) {
|
||||
qDebug() << " entityTreeElementExtraEncodeData INCLUDED";
|
||||
}
|
||||
|
||||
|
||||
if (entityTreeElementExtraEncodeData && entityTreeElementExtraEncodeData->entities.contains(getEntityItemID())) {
|
||||
requestedProperties = entityTreeElementExtraEncodeData->entities.value(getEntityItemID());
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << " entityTreeElementExtraEncodeData INCLUDED -AND- this entity is included";
|
||||
qDebug() << " --- requestedProperties ---";
|
||||
qDebug() << " PROP_MODEL_URL: " << requestedProperties.getHasProperty(PROP_MODEL_URL)<< " entity ID:" << getEntityItemID();
|
||||
qDebug() << " --- all requestedProperties ---";
|
||||
|
||||
#define DEBUG_REQUESTED_PROPERTY(x) if (requestedProperties.getHasProperty(x)) { qDebug() << " " #x; }
|
||||
|
||||
DEBUG_REQUESTED_PROPERTY(PROP_MODEL_URL);
|
||||
DEBUG_REQUESTED_PROPERTY(PROP_PAGED_PROPERTY)
|
||||
DEBUG_REQUESTED_PROPERTY(PROP_CUSTOM_PROPERTIES_INCLUDED);
|
||||
DEBUG_REQUESTED_PROPERTY(PROP_POSITION);
|
||||
DEBUG_REQUESTED_PROPERTY(PROP_RADIUS);
|
||||
DEBUG_REQUESTED_PROPERTY(PROP_ROTATION);
|
||||
DEBUG_REQUESTED_PROPERTY(PROP_MASS);
|
||||
DEBUG_REQUESTED_PROPERTY(PROP_VELOCITY);
|
||||
DEBUG_REQUESTED_PROPERTY(PROP_GRAVITY);
|
||||
DEBUG_REQUESTED_PROPERTY(PROP_DAMPING);
|
||||
DEBUG_REQUESTED_PROPERTY(PROP_LIFETIME);
|
||||
DEBUG_REQUESTED_PROPERTY(PROP_SCRIPT);
|
||||
DEBUG_REQUESTED_PROPERTY(PROP_COLOR);
|
||||
DEBUG_REQUESTED_PROPERTY(PROP_ANIMATION_URL);
|
||||
DEBUG_REQUESTED_PROPERTY(PROP_ANIMATION_FPS);
|
||||
DEBUG_REQUESTED_PROPERTY(PROP_ANIMATION_FRAME_INDEX);
|
||||
DEBUG_REQUESTED_PROPERTY(PROP_ANIMATION_PLAYING);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LevelDetails modelLevel = packetData->startLevel();
|
||||
|
@ -320,16 +366,40 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
propertiesDidntFit -= PROP_SCRIPT;
|
||||
}
|
||||
|
||||
appendSubclassData(packetData, params, modelTreeElementExtraEncodeData,
|
||||
appendSubclassData(packetData, params, entityTreeElementExtraEncodeData,
|
||||
requestedProperties,
|
||||
propertyFlags,
|
||||
propertiesDidntFit,
|
||||
propertyCount,
|
||||
appendState);
|
||||
}
|
||||
|
||||
|
||||
#define DEBUG_PROPERTY(y, x) if (y.getHasProperty(x)) { qDebug() << " " #x; }
|
||||
|
||||
if (propertyCount > 0) {
|
||||
int endOfEntityItemData = packetData->getUncompressedByteOffset();
|
||||
|
||||
qDebug() << "Entity Properties THIS ROUND... entityID:" << getEntityItemID();
|
||||
|
||||
DEBUG_PROPERTY(propertyFlags, PROP_MODEL_URL);
|
||||
DEBUG_PROPERTY(propertyFlags, PROP_PAGED_PROPERTY)
|
||||
DEBUG_PROPERTY(propertyFlags, PROP_CUSTOM_PROPERTIES_INCLUDED);
|
||||
DEBUG_PROPERTY(propertyFlags, PROP_POSITION);
|
||||
DEBUG_PROPERTY(propertyFlags, PROP_RADIUS);
|
||||
DEBUG_PROPERTY(propertyFlags, PROP_ROTATION);
|
||||
DEBUG_PROPERTY(propertyFlags, PROP_MASS);
|
||||
DEBUG_PROPERTY(propertyFlags, PROP_VELOCITY);
|
||||
DEBUG_PROPERTY(propertyFlags, PROP_GRAVITY);
|
||||
DEBUG_PROPERTY(propertyFlags, PROP_DAMPING);
|
||||
DEBUG_PROPERTY(propertyFlags, PROP_LIFETIME);
|
||||
DEBUG_PROPERTY(propertyFlags, PROP_SCRIPT);
|
||||
DEBUG_PROPERTY(propertyFlags, PROP_COLOR);
|
||||
DEBUG_PROPERTY(propertyFlags, PROP_ANIMATION_URL);
|
||||
DEBUG_PROPERTY(propertyFlags, PROP_ANIMATION_FPS);
|
||||
DEBUG_PROPERTY(propertyFlags, PROP_ANIMATION_FRAME_INDEX);
|
||||
DEBUG_PROPERTY(propertyFlags, PROP_ANIMATION_PLAYING);
|
||||
|
||||
|
||||
|
||||
encodedPropertyFlags = propertyFlags;
|
||||
int newPropertyFlagsLength = encodedPropertyFlags.length();
|
||||
|
@ -338,6 +408,9 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
|
||||
// if the size of the PropertyFlags shrunk, we need to shift everything down to front of packet.
|
||||
if (newPropertyFlagsLength < oldPropertyFlagsLength) {
|
||||
|
||||
qDebug() << "PACKET SHIFTING!!! <<<<<<<<<<<<<<<< ";
|
||||
|
||||
int oldSize = packetData->getUncompressedSize();
|
||||
const unsigned char* modelItemData = packetData->getUncompressedData(propertyFlagsOffset + oldPropertyFlagsLength);
|
||||
int modelItemDataLength = endOfEntityItemData - startOfEntityItemData;
|
||||
|
@ -359,7 +432,32 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
// If any part of the model items didn't fit, then the element is considered partial
|
||||
if (appendState != OctreeElement::COMPLETED) {
|
||||
// add this item into our list for the next appendElementData() pass
|
||||
modelTreeElementExtraEncodeData->includedItems.insert(getEntityItemID(), propertiesDidntFit);
|
||||
|
||||
qDebug() << "Entity Partially encoded... entityID:" << getEntityItemID();
|
||||
|
||||
#define DEBUG_PROPERTY(y, x) if (y.getHasProperty(x)) { qDebug() << " " #x; }
|
||||
|
||||
DEBUG_PROPERTY(propertiesDidntFit, PROP_MODEL_URL);
|
||||
DEBUG_PROPERTY(propertiesDidntFit, PROP_PAGED_PROPERTY)
|
||||
DEBUG_PROPERTY(propertiesDidntFit, PROP_CUSTOM_PROPERTIES_INCLUDED);
|
||||
DEBUG_PROPERTY(propertiesDidntFit, PROP_POSITION);
|
||||
DEBUG_PROPERTY(propertiesDidntFit, PROP_RADIUS);
|
||||
DEBUG_PROPERTY(propertiesDidntFit, PROP_ROTATION);
|
||||
DEBUG_PROPERTY(propertiesDidntFit, PROP_MASS);
|
||||
DEBUG_PROPERTY(propertiesDidntFit, PROP_VELOCITY);
|
||||
DEBUG_PROPERTY(propertiesDidntFit, PROP_GRAVITY);
|
||||
DEBUG_PROPERTY(propertiesDidntFit, PROP_DAMPING);
|
||||
DEBUG_PROPERTY(propertiesDidntFit, PROP_LIFETIME);
|
||||
DEBUG_PROPERTY(propertiesDidntFit, PROP_SCRIPT);
|
||||
DEBUG_PROPERTY(propertiesDidntFit, PROP_COLOR);
|
||||
DEBUG_PROPERTY(propertiesDidntFit, PROP_ANIMATION_URL);
|
||||
DEBUG_PROPERTY(propertiesDidntFit, PROP_ANIMATION_FPS);
|
||||
DEBUG_PROPERTY(propertiesDidntFit, PROP_ANIMATION_FRAME_INDEX);
|
||||
DEBUG_PROPERTY(propertiesDidntFit, PROP_ANIMATION_PLAYING);
|
||||
|
||||
entityTreeElementExtraEncodeData->entities.insert(getEntityItemID(), propertiesDidntFit);
|
||||
} else {
|
||||
qDebug() << "Entity COMPLETED... entityID:" << getEntityItemID();
|
||||
}
|
||||
|
||||
return appendState;
|
||||
|
@ -448,34 +546,42 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
}
|
||||
|
||||
quint64 lastEditedFromBuffer = 0;
|
||||
quint64 lastEditedFromBufferAdjusted = 0;
|
||||
|
||||
// TODO: we could make this encoded as a delta from _created
|
||||
// _lastEdited
|
||||
memcpy(&lastEditedFromBuffer, dataAt, sizeof(lastEditedFromBuffer));
|
||||
dataAt += sizeof(lastEditedFromBuffer);
|
||||
bytesRead += sizeof(lastEditedFromBuffer);
|
||||
lastEditedFromBuffer -= clockSkew;
|
||||
|
||||
qDebug() << "data from server **************** ";
|
||||
qDebug() << " entityItemID=" << getEntityItemID();
|
||||
qDebug() << " now=" << usecTimestampNow();
|
||||
qDebug() << " getLastEdited();=" << getLastEdited();
|
||||
qDebug() << " _lastEditedRemote=" << _lastEditedRemote;
|
||||
qDebug() << " _lastEditedLocal=" << _lastEditedLocal;
|
||||
qDebug() << " lastEditedFromBuffer=" << lastEditedFromBuffer << " (BEFORE clockskew adjust)";
|
||||
qDebug() << " clockSkew=" << clockSkew;
|
||||
lastEditedFromBufferAdjusted = lastEditedFromBuffer - clockSkew;
|
||||
qDebug() << " lastEditedFromBufferAdjusted=" << lastEditedFromBufferAdjusted << " (AFTER clockskew adjust)";
|
||||
|
||||
|
||||
// If we've changed our local tree more recently than the new data from this packet
|
||||
// then we will not be changing our values, instead we just read and skip the data
|
||||
if (_lastEdited > lastEditedFromBuffer) {
|
||||
if (_lastEditedLocal > lastEditedFromBufferAdjusted) {
|
||||
overwriteLocalData = false;
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "IGNORING old data from server!!! **************** _lastEdited=" << _lastEdited
|
||||
<< "lastEditedFromBuffer=" << lastEditedFromBuffer << "now=" << usecTimestampNow();
|
||||
if (true || wantDebug) {
|
||||
qDebug() << "IGNORING old data from server!!! ****************";
|
||||
}
|
||||
} else {
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "USING NEW data from server!!! **************** OLD _lastEdited=" << _lastEdited
|
||||
<< "lastEditedFromBuffer=" << lastEditedFromBuffer << "now=" << usecTimestampNow();
|
||||
if (true || wantDebug) {
|
||||
qDebug() << "USING NEW data from server!!! ****************";
|
||||
}
|
||||
|
||||
_lastEdited = lastEditedFromBuffer;
|
||||
|
||||
_lastEditedRemote = lastEditedFromBuffer;
|
||||
_lastEditedRemoteClockSkew = clockSkew;
|
||||
somethingChangedNotification(); // notify derived classes that something has changed
|
||||
|
||||
}
|
||||
|
||||
// last updated is stored as ByteCountCoded delta from lastEdited
|
||||
|
@ -483,7 +589,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
ByteCountCoded<quint64> updateDeltaCoder = encodedUpdateDelta;
|
||||
quint64 updateDelta = updateDeltaCoder;
|
||||
if (overwriteLocalData) {
|
||||
_lastUpdated = _lastEdited + updateDelta; // don't adjust for clock skew since we already did that for _lastEdited
|
||||
_lastUpdated = lastEditedFromBufferAdjusted + updateDelta; // don't adjust for clock skew since we already did that for _lastEdited
|
||||
}
|
||||
encodedUpdateDelta = updateDeltaCoder; // determine true length
|
||||
dataAt += encodedUpdateDelta.size();
|
||||
|
@ -865,9 +971,9 @@ bool EntityItem::setProperties(const EntityItemProperties& properties, bool forc
|
|||
bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
uint64_t now = usecTimestampNow();
|
||||
int elapsed = now - _lastEdited;
|
||||
int elapsed = now - getLastEdited();
|
||||
qDebug() << "EntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
|
||||
"now=" << now << " _lastEdited=" << _lastEdited;
|
||||
"now=" << now << " getLastEdited()=" << getLastEdited();
|
||||
}
|
||||
setLastEdited(properties._lastEdited);
|
||||
}
|
||||
|
|
|
@ -62,19 +62,21 @@ public:
|
|||
virtual void somethingChangedNotification() { }
|
||||
|
||||
quint64 getLastUpdated() const { return _lastUpdated; } /// Last simulated time of this entity universal usecs
|
||||
quint64 getLastEdited() const { return _lastEdited; } /// Last edited time of this entity universal usecs
|
||||
void setLastEdited(quint64 lastEdited) { _lastEdited = lastEdited; _lastUpdated = lastEdited; }
|
||||
|
||||
/// Last edited time of this entity universal usecs
|
||||
quint64 getLastEdited() const { return std::max((_lastEditedRemote - _lastEditedRemoteClockSkew), _lastEditedLocal); }
|
||||
void setLastEdited(quint64 lastEdited) { _lastEditedLocal = lastEdited; _lastEditedLocal = lastEdited; }
|
||||
float getEditedAgo() const /// Elapsed seconds since this entity was last edited
|
||||
{ return (float)(usecTimestampNow() - _lastEdited) / (float)USECS_PER_SECOND; }
|
||||
{ return (float)(usecTimestampNow() - getLastEdited()) / (float)USECS_PER_SECOND; }
|
||||
|
||||
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
|
||||
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const;
|
||||
|
||||
virtual OctreeElement::AppendState appendEntityData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
||||
EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData) const;
|
||||
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData) const;
|
||||
|
||||
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
||||
EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData,
|
||||
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData,
|
||||
EntityPropertyFlags& requestedProperties,
|
||||
EntityPropertyFlags& propertyFlags,
|
||||
EntityPropertyFlags& propertiesDidntFit,
|
||||
|
@ -188,7 +190,10 @@ protected:
|
|||
uint32_t _creatorTokenID;
|
||||
bool _newlyCreated;
|
||||
quint64 _lastUpdated;
|
||||
quint64 _lastEdited;
|
||||
//quint64 _lastEdited;
|
||||
quint64 _lastEditedLocal;
|
||||
quint64 _lastEditedRemote;
|
||||
quint64 _lastEditedRemoteClockSkew;
|
||||
quint64 _created;
|
||||
|
||||
glm::vec3 _position;
|
||||
|
|
|
@ -62,6 +62,11 @@ public:
|
|||
const unsigned char* editData, int maxLength, const SharedNodePointer& senderNode);
|
||||
|
||||
virtual bool rootElementHasData() const { return true; }
|
||||
|
||||
// the root at least needs to store the number of entities in the packet/buffer
|
||||
virtual int minimumRequiredRootDataBytes() const { return sizeof(uint16_t); }
|
||||
virtual bool suppressEmptySubtrees() const { return false; }
|
||||
|
||||
virtual bool versionHasSVOfileBreaks(PacketVersion thisVersion) const
|
||||
{ return thisVersion >= VERSION_ENTITIES_HAS_FILE_BREAKS; }
|
||||
|
||||
|
|
|
@ -50,6 +50,246 @@ EntityTreeElement* EntityTreeElement::addChildAtIndex(int index) {
|
|||
return newElement;
|
||||
}
|
||||
|
||||
void EntityTreeElement::debugExtraEncodeData(EncodeBitstreamParams& params) const {
|
||||
qDebug() << "EntityTreeElement::debugExtraEncodeData()... ";
|
||||
qDebug() << " element:" << getAACube();
|
||||
|
||||
OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
|
||||
assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes
|
||||
|
||||
if (extraEncodeData->contains(this)) {
|
||||
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData
|
||||
= static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(this));
|
||||
qDebug() << " encode data:" << entityTreeElementExtraEncodeData;
|
||||
} else {
|
||||
qDebug() << " encode data: MISSING!!";
|
||||
}
|
||||
}
|
||||
|
||||
void EntityTreeElement::initializeExtraEncodeData(EncodeBitstreamParams& params) const {
|
||||
OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
|
||||
assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes
|
||||
|
||||
// Check to see if this element yet has encode data... if it doesn't create it
|
||||
if (!extraEncodeData->contains(this)) {
|
||||
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData = new EntityTreeElementExtraEncodeData();
|
||||
|
||||
qDebug() << "EntityTreeElement::initializeExtraEncodeData()... ";
|
||||
qDebug() << " element:" << getAACube();
|
||||
entityTreeElementExtraEncodeData->elementCompleted = (_entityItems->size() == 0);
|
||||
qDebug() << " elementCompleted:" << entityTreeElementExtraEncodeData->elementCompleted << "[ _entityItems->size()=" << _entityItems->size() <<" ]";
|
||||
qDebug() << " --- initialize this element's child element state ---";
|
||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||
EntityTreeElement* child = getChildAtIndex(i);
|
||||
if (!child) {
|
||||
entityTreeElementExtraEncodeData->childCompleted[i] = true; // if no child exists, it is completed
|
||||
qDebug() << " childCompleted[" << i <<"]= true -- completed";
|
||||
} else {
|
||||
if (child->hasEntities()) {
|
||||
qDebug() << " childCompleted[" << i <<"] " << child->getAACube() << "= false -- HAS ENTITIES NEEDS ENCODING";
|
||||
} else {
|
||||
entityTreeElementExtraEncodeData->childCompleted[i] = true; // if the child doesn't have enities, it is completed
|
||||
qDebug() << " childCompleted[" << i <<"] " << child->getAACube() << "= true -- doesn't have entities";
|
||||
}
|
||||
}
|
||||
}
|
||||
qDebug() << " --- initialize this element's entities state ---";
|
||||
for (uint16_t i = 0; i < _entityItems->size(); i++) {
|
||||
EntityItem* entity = (*_entityItems)[i];
|
||||
entityTreeElementExtraEncodeData->entities.insert(entity->getEntityItemID(), entity->getEntityProperties(params));
|
||||
}
|
||||
|
||||
// TODO: some of these inserts might be redundant!!!
|
||||
qDebug() << " ADDING encode data (" << __LINE__ << ") for element " << getAACube() << " data=" << entityTreeElementExtraEncodeData;
|
||||
extraEncodeData->insert(this, entityTreeElementExtraEncodeData);
|
||||
}
|
||||
}
|
||||
|
||||
bool EntityTreeElement::shouldIncludeChild(int childIndex, EncodeBitstreamParams& params) const {
|
||||
OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
|
||||
assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes
|
||||
|
||||
if (extraEncodeData->contains(this)) {
|
||||
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData
|
||||
= static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(this));
|
||||
|
||||
bool childCompleted = entityTreeElementExtraEncodeData->childCompleted[childIndex];
|
||||
|
||||
// If we haven't completely sent the child yet, then we should include it
|
||||
return !childCompleted;
|
||||
}
|
||||
|
||||
// I'm not sure this should ever happen, since we should have the extra encode data if we're considering
|
||||
// the child data for this element
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EntityTreeElement::shouldRecurseSubtree(OctreeElement* parent, EncodeBitstreamParams& params, OctreeElementBag* bag) const {
|
||||
qDebug() << "EntityTreeElement::shouldRecurseSubtree()... ????????????????????????";
|
||||
qDebug() << " element:" << getAACube();
|
||||
|
||||
OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
|
||||
assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes
|
||||
|
||||
if (extraEncodeData->contains(this)) {
|
||||
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData
|
||||
= static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(this));
|
||||
qDebug() << " this element encode data:" << entityTreeElementExtraEncodeData;
|
||||
} else {
|
||||
qDebug() << " this element encode data: MISSING!!!";
|
||||
}
|
||||
|
||||
qDebug() << " parent:" << parent->getAACube();
|
||||
if (extraEncodeData->contains(parent)) {
|
||||
EntityTreeElementExtraEncodeData* parentExtraEncodeData
|
||||
= static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(parent));
|
||||
qDebug() << " parent encode data:" << parentExtraEncodeData;
|
||||
} else {
|
||||
qDebug() << " parent encode data: MISSING!!!";
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void EntityTreeElement::updateEncodedData(int childIndex, AppendState childAppendState, EncodeBitstreamParams& params) const {
|
||||
OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
|
||||
assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes
|
||||
|
||||
qDebug() << "EntityTreeElement::updateEncodedData()... ";
|
||||
qDebug() << " element:" << getAACube();
|
||||
qDebug() << " child:" << childIndex << getChildAtIndex(childIndex)->getAACube();
|
||||
switch(childAppendState) {
|
||||
case OctreeElement::NONE:
|
||||
qDebug() << " childAppendState: NONE";
|
||||
break;
|
||||
case OctreeElement::PARTIAL:
|
||||
qDebug() << " childAppendState: PARTIAL";
|
||||
break;
|
||||
case OctreeElement::COMPLETED:
|
||||
qDebug() << " childAppendState: COMPLETED";
|
||||
break;
|
||||
}
|
||||
|
||||
if (extraEncodeData->contains(this)) {
|
||||
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData
|
||||
= static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(this));
|
||||
|
||||
|
||||
if (childAppendState == OctreeElement::COMPLETED) {
|
||||
entityTreeElementExtraEncodeData->childCompleted[childIndex] = true;
|
||||
qDebug() << " SETTING childCompleted[" << childIndex << "] = true - " << getChildAtIndex(childIndex)->getAACube();
|
||||
}
|
||||
|
||||
qDebug() << " encode data:" << entityTreeElementExtraEncodeData;
|
||||
} else {
|
||||
assert(false); // this shouldn't happen!
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void EntityTreeElement::elementEncodeComplete(EncodeBitstreamParams& params, OctreeElementBag* bag) const {
|
||||
const bool wantDebug = true;
|
||||
OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
|
||||
assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes
|
||||
assert(extraEncodeData->contains(this));
|
||||
|
||||
EntityTreeElementExtraEncodeData* thisExtraEncodeData
|
||||
= static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(this));
|
||||
|
||||
// Note: this will be called when OUR element has finished running through encodeTreeBitstreamRecursion()
|
||||
// which means, it's possible that our parent element hasn't finished encoding OUR data... so
|
||||
// in this case, our children may be complete, and we should clean up their encode data...
|
||||
// but not necessarily cleanup our own encode data...
|
||||
//
|
||||
// If we're really complete here's what must be true...
|
||||
// 1) out own data must be complete
|
||||
// 2) the data for all our immediate children must be complete.
|
||||
// However, the following might also be the case...
|
||||
// 1) it's ok for our child trees to not yet be fully encoded/complete...
|
||||
// SO LONG AS... the our child's node is in the bag ready for encoding
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "------------------------------------------------------------------------------------";
|
||||
qDebug() << "EntityTreeElement::elementEncodeComplete()...";
|
||||
qDebug() << " element=" << getAACube();
|
||||
qDebug() << " encode data (this):" << thisExtraEncodeData;
|
||||
if (!thisExtraEncodeData->elementCompleted) {
|
||||
qDebug() << " ******* PROBABLY OK ---- WARNING ********* this element was not complete!!";
|
||||
qDebug() << " we really only care that our data is complete when we attempt to check our parent...";
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||
EntityTreeElement* childElement = getChildAtIndex(i);
|
||||
if (childElement) {
|
||||
bool isThisChildReallyComplete = thisExtraEncodeData->childCompleted[i];
|
||||
|
||||
// why would this ever fail???
|
||||
// If we've encoding this element before... but we're coming back a second time in an attempt to
|
||||
// encoud our parent... this might happen.
|
||||
if (extraEncodeData->contains(childElement)) {
|
||||
EntityTreeElementExtraEncodeData* childExtraEncodeData
|
||||
= static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(childElement));
|
||||
|
||||
// If the child element is not complete, then it should be in the bag for re-encoding
|
||||
if (!thisExtraEncodeData->childCompleted[i]) {
|
||||
if (bag->contains(childElement)) {
|
||||
qDebug() << " GOOD this element's child["<< i << "] " << childElement->getAACube() << " was not complete, but it's in the bag!!";
|
||||
} else {
|
||||
qDebug() << " ******* WARNING ********* this element's child["<< i << "] " << childElement->getAACube() << " was not complete, AND IT'S NOT IN THE BAG!!";
|
||||
}
|
||||
}
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << " child[" << i <<"] has extra data";
|
||||
qDebug() << " child:" << childElement->getAACube();
|
||||
qDebug() << " encode data (child):" << childExtraEncodeData;
|
||||
// If we're completing THIS element then ALL of our child elements must have been able to add their element data
|
||||
if (childExtraEncodeData->elementCompleted) {
|
||||
qDebug() << " GOOD this element's child["<< i << "] " << childElement->getAACube() << " element data was complete!!";
|
||||
} else {
|
||||
qDebug() << " ******* WARNING ********* this element's child["<< i << "] " << childElement->getAACube() << " element data was NOT COMPLETE!!";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (int ii = 0; ii < NUMBER_OF_CHILDREN; ii++) {
|
||||
if (!childExtraEncodeData->childCompleted[ii]) {
|
||||
OctreeElement* grandChild = childElement->getChildAtIndex(ii);
|
||||
if (bag->contains(childElement)) {
|
||||
qDebug() << " GOOD this element's child["<< i << "]'s child["<< ii << "] " << grandChild->getAACube()
|
||||
<< " was not complete, but the child " << childElement->getAACube() << " is in the bag!!";
|
||||
} else {
|
||||
qDebug() << " ******* WARNING ********* this element's child["<< i << "]'s child["<< ii << "] " << grandChild->getAACube()
|
||||
<< " was not complete, AND THE CHILD " << childElement->getAACube() << " IS NOT IN THE BAG!!";
|
||||
}
|
||||
|
||||
isThisChildReallyComplete = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (isThisChildReallyComplete) {
|
||||
/*
|
||||
qDebug() << " REMOVE CHILD EXTRA DATA....";
|
||||
qDebug() << " DELETING -- CHILD EXTRA DATA....";
|
||||
qDebug() << " REMOVING encode data (" << __LINE__ << ") for element " << childElement->getAACube() << " data=" << childExtraEncodeData;
|
||||
extraEncodeData->remove(childElement);
|
||||
delete childExtraEncodeData;
|
||||
*/
|
||||
}
|
||||
} else {
|
||||
qDebug() << " ******* WARNING ********* this element's child["<< i << "] " << childElement->getAACube() << " didn't have extra encode data ------ UNEXPECTED!!!!!";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "------------------------------------------------------------------------------------";
|
||||
}
|
||||
|
||||
OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData* packetData,
|
||||
EncodeBitstreamParams& params) const {
|
||||
|
@ -61,6 +301,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
|
|||
qDebug() << " START OF ELEMENT packetData->uncompressed size:" << packetData->getUncompressedSize();
|
||||
qDebug() << " params.lastViewFrustumSent=" << params.lastViewFrustumSent;
|
||||
}
|
||||
|
||||
OctreeElement::AppendState appendElementState = OctreeElement::COMPLETED; // assume the best...
|
||||
|
||||
// first, check the params.extraEncodeData to see if there's any partial re-encode data for this element
|
||||
|
@ -73,9 +314,42 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
|
|||
} else {
|
||||
// if there wasn't one already, then create one
|
||||
entityTreeElementExtraEncodeData = new EntityTreeElementExtraEncodeData();
|
||||
|
||||
qDebug() << "EntityTreeElement::appendElementData()... ENCODE DATA MISSING, SETTING IT UP NOW ";
|
||||
qDebug() << " element:" << getAACube();
|
||||
entityTreeElementExtraEncodeData->elementCompleted = (_entityItems->size() == 0);
|
||||
qDebug() << " elementCompleted:" << entityTreeElementExtraEncodeData->elementCompleted << "[ _entityItems->size()=" << _entityItems->size() <<" ]";
|
||||
qDebug() << " --- initialize child elements state ---";
|
||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||
EntityTreeElement* child = getChildAtIndex(i);
|
||||
if (!child) {
|
||||
entityTreeElementExtraEncodeData->childCompleted[i] = true; // if no child exists, it is completed
|
||||
qDebug() << " childCompleted[" << i <<"]= true -- completed";
|
||||
} else {
|
||||
if (child->hasEntities()) {
|
||||
qDebug() << " childCompleted[" << i <<"] " << child->getAACube() << "= false -- HAS ENTITIES NEEDS ENCODING";
|
||||
} else {
|
||||
entityTreeElementExtraEncodeData->childCompleted[i] = true; // if the child doesn't have enities, it is completed
|
||||
qDebug() << " childCompleted[" << i <<"] " << child->getAACube() << "= true -- doesn't have entities";
|
||||
}
|
||||
}
|
||||
}
|
||||
qDebug() << " --- initialize this element's entities state ---";
|
||||
for (uint16_t i = 0; i < _entityItems->size(); i++) {
|
||||
EntityItem* entity = (*_entityItems)[i];
|
||||
entityTreeElementExtraEncodeData->entities.insert(entity->getEntityItemID(), entity->getEntityProperties(params));
|
||||
}
|
||||
}
|
||||
|
||||
//assert(extraEncodeData);
|
||||
//assert(extraEncodeData->contains(this));
|
||||
//entityTreeElementExtraEncodeData = static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(this));
|
||||
|
||||
|
||||
LevelDetails elementLevel = packetData->startLevel();
|
||||
if (wantDebug) {
|
||||
qDebug() << "------------- elementLevel = packetData->startLevel() -------------";
|
||||
}
|
||||
|
||||
// write our entities out... first determine which of the entities are in view based on our params
|
||||
uint16_t numberOfEntities = 0;
|
||||
|
@ -86,50 +360,56 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
|
|||
qDebug() << "EntityTreeElement::appendElementData() _entityItems->size()=" << _entityItems->size();
|
||||
}
|
||||
|
||||
for (uint16_t i = 0; i < _entityItems->size(); i++) {
|
||||
EntityItem* entity = (*_entityItems)[i];
|
||||
bool includeThisEntity = true;
|
||||
// It's possible that our element has been previous completed. In this case we'll simply not include any of our
|
||||
// entities for encoding. This is needed because we encode the element data at the "parent" level, and so we
|
||||
// need to handle the case where our sibling elements need encoding but we don't.
|
||||
if (!entityTreeElementExtraEncodeData->elementCompleted) {
|
||||
for (uint16_t i = 0; i < _entityItems->size(); i++) {
|
||||
EntityItem* entity = (*_entityItems)[i];
|
||||
bool includeThisEntity = true;
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "params.forceSendScene=" << params.forceSendScene;
|
||||
qDebug() << "entity->getLastEdited()=" << entity->getLastEdited();
|
||||
qDebug() << "entity->getLastEdited() > params.lastViewFrustumSent="
|
||||
<< (entity->getLastEdited() > params.lastViewFrustumSent);
|
||||
}
|
||||
|
||||
if (!params.forceSendScene && entity->getLastEdited() < params.lastViewFrustumSent) {
|
||||
if (wantDebug) {
|
||||
qDebug() << "NOT forceSendScene, and not changed since last sent SUPPRESSING this ENTITY"
|
||||
<< entity->getEntityItemID();
|
||||
if (false && wantDebug) {
|
||||
qDebug() << "params.forceSendScene=" << params.forceSendScene;
|
||||
qDebug() << "entity->getLastEdited()=" << entity->getLastEdited();
|
||||
qDebug() << "entity->getLastEdited() > params.lastViewFrustumSent="
|
||||
<< (entity->getLastEdited() > params.lastViewFrustumSent);
|
||||
}
|
||||
includeThisEntity = false;
|
||||
}
|
||||
|
||||
if (hadElementExtraData) {
|
||||
includeThisEntity = includeThisEntity &&
|
||||
entityTreeElementExtraEncodeData->includedItems.contains(entity->getEntityItemID());
|
||||
if (wantDebug) {
|
||||
qDebug() << " hadElementExtraData=" << hadElementExtraData;
|
||||
qDebug() << " entity[" << i <<"].entityItemID=" << entity->getEntityItemID();
|
||||
qDebug() << " entity[" << i <<"].includeThisEntity=" << includeThisEntity;
|
||||
if (!params.forceSendScene && entity->getLastEdited() < params.lastViewFrustumSent) {
|
||||
if (false && wantDebug) {
|
||||
qDebug() << "NOT forceSendScene, and not changed since last sent SUPPRESSING this ENTITY"
|
||||
<< entity->getEntityItemID();
|
||||
}
|
||||
includeThisEntity = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (includeThisEntity && params.viewFrustum) {
|
||||
AACube entityCube = entity->getAACube();
|
||||
entityCube.scale(TREE_SCALE);
|
||||
if (params.viewFrustum->cubeInFrustum(entityCube) == ViewFrustum::OUTSIDE) {
|
||||
includeThisEntity = false; // out of view, don't include it
|
||||
if (hadElementExtraData) {
|
||||
includeThisEntity = includeThisEntity &&
|
||||
entityTreeElementExtraEncodeData->entities.contains(entity->getEntityItemID());
|
||||
if (wantDebug) {
|
||||
qDebug() << " entity[" << i <<"] cubeInFrustum(entityCube) == ViewFrustum::OUTSIDE "
|
||||
"includeThisEntity=" << includeThisEntity;
|
||||
if (includeThisEntity) {
|
||||
qDebug() << " entity[" << i <<"].entityItemID=" << entity->getEntityItemID();
|
||||
qDebug() << " entity[" << i <<"].includeThisEntity=" << includeThisEntity;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (includeThisEntity) {
|
||||
indexesOfEntitiesToInclude << i;
|
||||
numberOfEntities++;
|
||||
if (includeThisEntity && params.viewFrustum) {
|
||||
AACube entityCube = entity->getAACube();
|
||||
entityCube.scale(TREE_SCALE);
|
||||
if (params.viewFrustum->cubeInFrustum(entityCube) == ViewFrustum::OUTSIDE) {
|
||||
includeThisEntity = false; // out of view, don't include it
|
||||
if (wantDebug) {
|
||||
qDebug() << " entity[" << i <<"] cubeInFrustum(entityCube) == ViewFrustum::OUTSIDE "
|
||||
"includeThisEntity=" << includeThisEntity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (includeThisEntity) {
|
||||
indexesOfEntitiesToInclude << i;
|
||||
numberOfEntities++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,13 +453,25 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
|
|||
qDebug() << "--- AFTER entity ---";
|
||||
qDebug() << " packetData->getUncompressedSize=" << packetData->getUncompressedSize() << "line:" << __LINE__;
|
||||
qDebug() << " packetData->getReservedBytes=" << packetData->getReservedBytes();
|
||||
|
||||
switch(appendEntityState) {
|
||||
case OctreeElement::NONE:
|
||||
qDebug() << " indexesOfEntitiesToInclude.... entity[" << i <<"] DIDN'T FIT!!!";
|
||||
break;
|
||||
case OctreeElement::PARTIAL:
|
||||
qDebug() << " indexesOfEntitiesToInclude.... entity[" << i <<"] PARTIAL FIT!!!";
|
||||
break;
|
||||
case OctreeElement::COMPLETED:
|
||||
qDebug() << " indexesOfEntitiesToInclude.... entity[" << i <<"] IT ALL FIT!!!";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If none of this entity data was able to be appended, then discard it
|
||||
// and don't include it in our entity count
|
||||
if (appendEntityState == OctreeElement::NONE) {
|
||||
if (wantDebug) {
|
||||
qDebug() << " indexesOfEntitiesToInclude.... entity[" << i <<"] DIDN'T FIT!!!";
|
||||
qDebug() << " calling discardLevel(entityLevel)...";
|
||||
}
|
||||
packetData->discardLevel(entityLevel);
|
||||
} else {
|
||||
|
@ -188,33 +480,31 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
|
|||
packetData->endLevel(entityLevel);
|
||||
actualNumberOfEntities++;
|
||||
if (wantDebug) {
|
||||
qDebug() << " indexesOfEntitiesToInclude.... entity[" << i <<"] ALL OR SOME FIT!!!";
|
||||
qDebug() << " calling endLevel(entityLevel)...";
|
||||
}
|
||||
}
|
||||
|
||||
// If the entity item got completely appended, then we can remove it from the extra encode data
|
||||
if (appendEntityState == OctreeElement::COMPLETED) {
|
||||
entityTreeElementExtraEncodeData->includedItems.remove(entity->getEntityItemID());
|
||||
if (wantDebug) {
|
||||
qDebug() << " indexesOfEntitiesToInclude.... entity[" << i <<"] IT ALL FIT!!!";
|
||||
}
|
||||
} else {
|
||||
if (wantDebug) {
|
||||
if (appendEntityState == OctreeElement::NONE) {
|
||||
qDebug() << " indexesOfEntitiesToInclude.... entity[" << i <<"] DIDN'T FIT!!!";
|
||||
} else {
|
||||
qDebug() << " indexesOfEntitiesToInclude.... entity[" << i <<"] PARTIAL FIT!!!";
|
||||
}
|
||||
qDebug() << " since entity fit, removing it from entities...";
|
||||
}
|
||||
entityTreeElementExtraEncodeData->entities.remove(entity->getEntityItemID());
|
||||
}
|
||||
|
||||
// If any part of the entity items didn't fit, then the element is considered partial
|
||||
// NOTE: if the entity item didn't fit or only partially fit, then the entity item should have
|
||||
// added itself to the extra encode data.
|
||||
if (appendEntityState != OctreeElement::COMPLETED) {
|
||||
if (wantDebug) {
|
||||
qDebug() << " entity not complete, element must be partial!!!!";
|
||||
}
|
||||
appendElementState = OctreeElement::PARTIAL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// we we couldn't add the entity count, then we couldn't add anything for this element and we're in a NONE state
|
||||
appendElementState = OctreeElement::NONE;
|
||||
}
|
||||
|
||||
if (wantDebug) {
|
||||
|
@ -222,30 +512,121 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
|
|||
qDebug() << " actualNumberOfEntities=" << actualNumberOfEntities;
|
||||
qDebug() << " numberOfEntities=" << numberOfEntities;
|
||||
qDebug() << " appendElementState=" << appendElementState;
|
||||
switch(appendElementState) {
|
||||
case OctreeElement::NONE:
|
||||
qDebug() << " OctreeElement::NONE";
|
||||
break;
|
||||
case OctreeElement::PARTIAL:
|
||||
qDebug() << " OctreeElement::PARTIAL";
|
||||
break;
|
||||
case OctreeElement::COMPLETED:
|
||||
qDebug() << " OctreeElement::COMPLETED";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we were provided with extraEncodeData, and we allocated and/or got entityTreeElementExtraEncodeData
|
||||
// then we need to do some additional processing, namely make sure our extraEncodeData is up to date for
|
||||
// this octree element.
|
||||
if (extraEncodeData && entityTreeElementExtraEncodeData) {
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << " handling extra encode data....";
|
||||
}
|
||||
|
||||
// If after processing we have some includedItems left in it, then make sure we re-add it back to our map
|
||||
if (entityTreeElementExtraEncodeData->includedItems.size()) {
|
||||
// After processing, if we are PARTIAL or COMPLETED then we need to re-include our extra data.
|
||||
// Only our patent can remove our extra data in these cases and only after it knows that all of it's
|
||||
// children have been encoded.
|
||||
// If we weren't able to encode ANY data about ourselves, then we go ahead and remove our element data
|
||||
// since that will signal that the entire element needs to be encoded on the next attempt
|
||||
if (appendElementState == OctreeElement::NONE) {
|
||||
|
||||
if (!entityTreeElementExtraEncodeData->elementCompleted && entityTreeElementExtraEncodeData->entities.size() == 0) {
|
||||
/*
|
||||
if (wantDebug) {
|
||||
qDebug() << " REMOVING OUR EXTRA DATA BECAUSE NOTHING FIT AND WE HAD NO PREVIOUS DATA....";
|
||||
qDebug() << " for element:" << getAACube();
|
||||
qDebug() << " elementCompleted=" << entityTreeElementExtraEncodeData->elementCompleted;
|
||||
qDebug() << " entities.size()=" << entityTreeElementExtraEncodeData->entities.size();
|
||||
qDebug() << " appendElementState=";
|
||||
switch(appendElementState) {
|
||||
case OctreeElement::NONE:
|
||||
qDebug() << " OctreeElement::NONE";
|
||||
break;
|
||||
case OctreeElement::PARTIAL:
|
||||
qDebug() << " OctreeElement::PARTIAL";
|
||||
break;
|
||||
case OctreeElement::COMPLETED:
|
||||
qDebug() << " OctreeElement::COMPLETED";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << " --------- DO WE REALLY WANT TO DO THIS?????????????? --------------------";
|
||||
qDebug() << " REMOVING encode data (" << __LINE__ << ") for element " << getAACube() << " data=" << entityTreeElementExtraEncodeData;
|
||||
extraEncodeData->remove(this);
|
||||
delete entityTreeElementExtraEncodeData;
|
||||
*/
|
||||
|
||||
|
||||
} else {
|
||||
// TODO: some of these inserts might be redundant!!!
|
||||
qDebug() << " ADDING encode data (" << __LINE__ << ") for element " << getAACube() << " data=" << entityTreeElementExtraEncodeData;
|
||||
extraEncodeData->insert(this, entityTreeElementExtraEncodeData);
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << " RE INSERT OUR EXTRA DATA.... NOTHING FIT... BUT WE PREVIOUSLY STORED SOMETHING...";
|
||||
qDebug() << " for element:" << getAACube();
|
||||
qDebug() << " elementCompleted=" << entityTreeElementExtraEncodeData->elementCompleted;
|
||||
qDebug() << " entities.size()=" << entityTreeElementExtraEncodeData->entities.size();
|
||||
qDebug() << " appendElementState=";
|
||||
switch(appendElementState) {
|
||||
case OctreeElement::NONE:
|
||||
qDebug() << " OctreeElement::NONE";
|
||||
break;
|
||||
case OctreeElement::PARTIAL:
|
||||
qDebug() << " OctreeElement::PARTIAL";
|
||||
break;
|
||||
case OctreeElement::COMPLETED:
|
||||
qDebug() << " OctreeElement::COMPLETED";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
// If we weren't previously completed, check to see if we are
|
||||
if (!entityTreeElementExtraEncodeData->elementCompleted) {
|
||||
// If all of our items have been encoded, then we are complete as an element.
|
||||
if (entityTreeElementExtraEncodeData->entities.size() == 0) {
|
||||
if (wantDebug) {
|
||||
qDebug() << " since our entities.size() is 0 --- we are assuming we're done <<<<<<<<<<<<<<<<<<";
|
||||
}
|
||||
entityTreeElementExtraEncodeData->elementCompleted = true;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: some of these inserts might be redundant!!!
|
||||
qDebug() << " ADDING encode data (" << __LINE__ << ") for element " << getAACube() << " data=" << entityTreeElementExtraEncodeData;
|
||||
extraEncodeData->insert(this, entityTreeElementExtraEncodeData);
|
||||
if (wantDebug) {
|
||||
qDebug() << " RE INSERT OUR EXTRA DATA....";
|
||||
qDebug() << " for element:" << getAACube();
|
||||
qDebug() << " elementCompleted=" << entityTreeElementExtraEncodeData->elementCompleted;
|
||||
qDebug() << " entities.size()=" << entityTreeElementExtraEncodeData->entities.size();
|
||||
qDebug() << " appendElementState=";
|
||||
switch(appendElementState) {
|
||||
case OctreeElement::NONE:
|
||||
qDebug() << " OctreeElement::NONE";
|
||||
break;
|
||||
case OctreeElement::PARTIAL:
|
||||
qDebug() << " OctreeElement::PARTIAL";
|
||||
break;
|
||||
case OctreeElement::COMPLETED:
|
||||
qDebug() << " OctreeElement::COMPLETED";
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// otherwise, clean things up...
|
||||
extraEncodeData->remove(this);
|
||||
delete entityTreeElementExtraEncodeData;
|
||||
if (wantDebug) {
|
||||
qDebug() << " REMOVE OUR EXTRA DATA....";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -288,6 +669,18 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
|
|||
|
||||
if (wantDebug) {
|
||||
qDebug() << "END OF ELEMENT packetData->uncompressed size:" << packetData->getUncompressedSize();
|
||||
qDebug() << "RETURNING appendElementState=";
|
||||
switch(appendElementState) {
|
||||
case OctreeElement::NONE:
|
||||
qDebug() << " OctreeElement::NONE";
|
||||
break;
|
||||
case OctreeElement::PARTIAL:
|
||||
qDebug() << " OctreeElement::PARTIAL";
|
||||
break;
|
||||
case OctreeElement::COMPLETED:
|
||||
qDebug() << " OctreeElement::COMPLETED";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return appendElementState;
|
||||
|
|
|
@ -38,9 +38,28 @@ public:
|
|||
|
||||
class EntityTreeElementExtraEncodeData {
|
||||
public:
|
||||
QMap<EntityItemID, EntityPropertyFlags> includedItems;
|
||||
EntityTreeElementExtraEncodeData() :
|
||||
elementCompleted(false),
|
||||
entities() {
|
||||
memset(childCompleted, 0, sizeof(childCompleted));
|
||||
}
|
||||
bool elementCompleted;
|
||||
bool childCompleted[NUMBER_OF_CHILDREN];
|
||||
QMap<EntityItemID, EntityPropertyFlags> entities;
|
||||
};
|
||||
|
||||
inline QDebug operator<<(QDebug debug, const EntityTreeElementExtraEncodeData* data) {
|
||||
debug << "{";
|
||||
debug << " elementCompleted: " << data->elementCompleted << ", ";
|
||||
debug << " childCompleted[]: ";
|
||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||
debug << " " << i << ":" << data->childCompleted[i] << ", ";
|
||||
}
|
||||
debug << " entities.size: " << data->entities.size() << "}";
|
||||
return debug;
|
||||
}
|
||||
|
||||
|
||||
class SendModelsOperationArgs {
|
||||
public:
|
||||
glm::vec3 root;
|
||||
|
@ -59,7 +78,7 @@ public:
|
|||
virtual ~EntityTreeElement();
|
||||
|
||||
// type safe versions of OctreeElement methods
|
||||
EntityTreeElement* getChildAtIndex(int index) { return (EntityTreeElement*)OctreeElement::getChildAtIndex(index); }
|
||||
EntityTreeElement* getChildAtIndex(int index) const { return (EntityTreeElement*)OctreeElement::getChildAtIndex(index); }
|
||||
|
||||
// methods you can and should override to implement your tree functionality
|
||||
|
||||
|
@ -88,6 +107,14 @@ public:
|
|||
/// Override to indicate that this element requires a split before editing lower elements in the octree
|
||||
virtual bool requiresSplit() const { return false; }
|
||||
|
||||
virtual void debugExtraEncodeData(EncodeBitstreamParams& params) const;
|
||||
virtual void initializeExtraEncodeData(EncodeBitstreamParams& params) const;
|
||||
virtual bool shouldIncludeChild(int childIndex, EncodeBitstreamParams& params) const;
|
||||
virtual bool shouldRecurseSubtree(OctreeElement* parent, EncodeBitstreamParams& params, OctreeElementBag* bag) const;
|
||||
virtual void updateEncodedData(int childIndex, AppendState childAppendState, EncodeBitstreamParams& params) const;
|
||||
virtual void elementEncodeComplete(EncodeBitstreamParams& params, OctreeElementBag* bag) const;
|
||||
|
||||
|
||||
/// Override to serialize the state of this element. This is used for persistance and for transmission across the network.
|
||||
virtual OctreeElement::AppendState appendElementData(OctreePacketData* packetData, EncodeBitstreamParams& params) const;
|
||||
|
||||
|
|
|
@ -93,9 +93,9 @@ bool ModelEntityItem::setProperties(const EntityItemProperties& properties, bool
|
|||
bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
uint64_t now = usecTimestampNow();
|
||||
int elapsed = now - _lastEdited;
|
||||
int elapsed = now - getLastEdited();
|
||||
qDebug() << "ModelEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
|
||||
"now=" << now << " _lastEdited=" << _lastEdited;
|
||||
"now=" << now << " getLastEdited()=" << getLastEdited();
|
||||
}
|
||||
setLastEdited(properties._lastEdited);
|
||||
}
|
||||
|
@ -141,8 +141,14 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
QString modelURLString((const char*)dataAt);
|
||||
dataAt += modelURLLength;
|
||||
bytesRead += modelURLLength;
|
||||
|
||||
qDebug() << "ModelEntityItem::readEntitySubclassDataFromBuffer().... EntityID: " << getEntityItemID() << " --- PROP_MODEL_URL:" << modelURLString;
|
||||
|
||||
if (overwriteLocalData) {
|
||||
setModelURL(modelURLString);
|
||||
qDebug() << " setModelURL(modelURLString)=" << getModelURL();
|
||||
} else {
|
||||
qDebug() << " WARNING >>>>>>>>>>> IGNORING NEW DATA!!!! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,11 +229,11 @@ int ModelEntityItem::oldVersionReadEntityDataFromBuffer(const unsigned char* dat
|
|||
_lastUpdated -= clockSkew;
|
||||
|
||||
// _lastEdited
|
||||
memcpy(&_lastEdited, dataAt, sizeof(_lastEdited));
|
||||
dataAt += sizeof(_lastEdited);
|
||||
bytesRead += sizeof(_lastEdited);
|
||||
_lastEdited -= clockSkew;
|
||||
_created = _lastEdited; // NOTE: old models didn't have age or created time, assume their last edit was a create
|
||||
memcpy(&_lastEditedRemote, dataAt, sizeof(_lastEditedRemote));
|
||||
dataAt += sizeof(_lastEditedRemote);
|
||||
bytesRead += sizeof(_lastEditedRemote);
|
||||
_lastEditedRemote -= clockSkew;
|
||||
_created = _lastEditedRemote; // NOTE: old models didn't have age or created time, assume their last edit was a create
|
||||
|
||||
QString ageAsString = formatSecondsElapsed(getAge());
|
||||
qDebug() << "Loading old model file, _created = _lastEdited =" << _created
|
||||
|
@ -320,7 +326,7 @@ EntityPropertyFlags ModelEntityItem::getEntityProperties(EncodeBitstreamParams&
|
|||
|
||||
|
||||
void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
||||
EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData,
|
||||
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData,
|
||||
EntityPropertyFlags& requestedProperties,
|
||||
EntityPropertyFlags& propertyFlags,
|
||||
EntityPropertyFlags& propertiesDidntFit,
|
||||
|
@ -350,6 +356,9 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit
|
|||
LevelDetails propertyLevel = packetData->startLevel();
|
||||
successPropertyFits = packetData->appendValue(getModelURL());
|
||||
if (successPropertyFits) {
|
||||
|
||||
qDebug() << "ModelEntityItem::appendSubclassData().... EntityID: " << getEntityItemID() << " --- PROP_MODEL_URL:" << getModelURL();
|
||||
|
||||
propertyFlags |= PROP_MODEL_URL;
|
||||
propertiesDidntFit -= PROP_MODEL_URL;
|
||||
propertyCount++;
|
||||
|
|
|
@ -30,7 +30,7 @@ public:
|
|||
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const;
|
||||
|
||||
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
||||
EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData,
|
||||
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData,
|
||||
EntityPropertyFlags& requestedProperties,
|
||||
EntityPropertyFlags& propertyFlags,
|
||||
EntityPropertyFlags& propertiesDidntFit,
|
||||
|
|
|
@ -58,9 +58,9 @@ bool SphereEntityItem::setProperties(const EntityItemProperties& properties, boo
|
|||
bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
uint64_t now = usecTimestampNow();
|
||||
int elapsed = now - _lastEdited;
|
||||
int elapsed = now - getLastEdited();
|
||||
qDebug() << "SphereEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
|
||||
"now=" << now << " _lastEdited=" << _lastEdited;
|
||||
"now=" << now << " getLastEdited()=" << getLastEdited();
|
||||
}
|
||||
setLastEdited(properties.getLastEdited());
|
||||
}
|
||||
|
|
|
@ -1,7 +1,41 @@
|
|||
// REQUIRED:
|
||||
|
||||
2) Test file save load for case where two siblings have more than MTU amount of data. I wonder if the fact that file save
|
||||
doesn't include the extra exists bits will break something.
|
||||
|
||||
http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/Feisar_Ship.FBX#1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/newInvader16x16-large-purple.svo#1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
-123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
|
||||
|
||||
1) clock skew sometimes causes properties to get reject when sent from the server...
|
||||
|
||||
-- this appears to be related to clock skew!!!
|
||||
-- need to determine "when to deleted extra data" --
|
||||
|
||||
|
||||
|
||||
When encoding ----
|
||||
if the parent node gets pulled from the bag first... things go ok
|
||||
if the child node gets pulled first --
|
||||
and it encodes the grandchildren ---
|
||||
THEN -- it seems like things break:
|
||||
1) the parent node will encode the children -- OK
|
||||
2) then will attempt to recurse into the children..
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
7) some jutter with moving entities
|
||||
-- I think this might only happen with lots of models in an element or in view
|
||||
|
@ -14,20 +48,27 @@
|
|||
- does the same pruning/reallocating issue as the old UpdateEntityOperator
|
||||
- doesn't used clamped boxes for best fit tests... so could be problematic
|
||||
|
||||
-- crash on shutdown while animating...
|
||||
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
|
||||
0 io.highfidelity.Interface 0x000000010cf99a6a EntityTree::updateChangingEntities(unsigned long long, QSet<EntityItemID>&) + 202
|
||||
1 io.highfidelity.Interface 0x000000010cf998a6 EntityTree::update() + 70
|
||||
2 io.highfidelity.Interface 0x000000010cb64a3e EntityTreeRenderer::update() + 62
|
||||
3 io.highfidelity.Interface 0x000000010c9eb6ec Application::update(float) + 796
|
||||
4 io.highfidelity.Interface 0x000000010c9f5e26 Application::idle() + 550
|
||||
5 io.highfidelity.Interface 0x000000010c99f567 Application::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) + 1655
|
||||
6 QtCore 0x0000000112474a30 QMetaObject::activate(QObject*, int, int, void**) + 2640
|
||||
7 QtCore 0x000000011246d5c1 QObject::event(QEvent*) + 49
|
||||
|
||||
|
||||
|
||||
// NICE TO HAVE:
|
||||
|
||||
|
||||
1) clean up Octree::encodeTreeBitstreamRecursion() --
|
||||
It would be nice to clean up this function to be shorter...
|
||||
1015-1158 - helper functions "exit early helpers"
|
||||
1200-1245 - helper function "sorted children"
|
||||
1248-1376 - helper function "visible children" -
|
||||
this handles LOD, occlusion, in view/was in view for child elements
|
||||
NOTE: this information could be cached for secondary passes of the element
|
||||
in the same scene encode since they shouldn't change in same scene encode
|
||||
|
||||
|
||||
11) quickly do some edits... then change domains... watch the entities continue to exist in new domain and move around.
|
||||
-- verify this happens in old code, if so... move to "nice to have"
|
||||
-- maybe this relates to having incoming packets waiting in the processing queue... they should be discarded on switching domains?
|
||||
|
||||
|
||||
Z) Consider using client side "on the fly" billboard of entites to handle LOD
|
||||
-- have routine to shoot views of an entity for 6 faces
|
||||
-- store those images in the entity on the client
|
||||
|
@ -102,9 +143,17 @@
|
|||
10 libsystem_pthread.dylib 0x00007fff8bb9afc9 thread_start + 13
|
||||
|
||||
|
||||
11) quickly do some edits... then change domains... watch the entities continue to exist in new domain and move around.
|
||||
-- verify this happens in old code, if so... move to "nice to have"
|
||||
|
||||
-- crash on shutdown while animating...???
|
||||
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
|
||||
0 io.highfidelity.Interface 0x000000010cf99a6a EntityTree::updateChangingEntities(unsigned long long, QSet<EntityItemID>&) + 202
|
||||
1 io.highfidelity.Interface 0x000000010cf998a6 EntityTree::update() + 70
|
||||
2 io.highfidelity.Interface 0x000000010cb64a3e EntityTreeRenderer::update() + 62
|
||||
3 io.highfidelity.Interface 0x000000010c9eb6ec Application::update(float) + 796
|
||||
4 io.highfidelity.Interface 0x000000010c9f5e26 Application::idle() + 550
|
||||
5 io.highfidelity.Interface 0x000000010c99f567 Application::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) + 1655
|
||||
6 QtCore 0x0000000112474a30 QMetaObject::activate(QObject*, int, int, void**) + 2640
|
||||
7 QtCore 0x000000011246d5c1 QObject::event(QEvent*) + 49
|
||||
|
||||
===============
|
||||
|
||||
|
@ -237,6 +286,7 @@
|
|||
// SOLVED -- 52) Look into why non-changed octree cells are being resent when editing an entity --
|
||||
// this is probably because we're marking the trees as dirty -- but we probably can not send entitys that haven't changed
|
||||
// Solution -- suppress sending of entities that haven't been edited since the last view frustum sent
|
||||
// SOLVED -- 53) Test sibling cells
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -952,6 +952,7 @@ int Octree::encodeTreeBitstream(OctreeElement* element,
|
|||
// If the octalcode couldn't fit, then we can return, because no nodes below us will fit...
|
||||
if (!roomForOctalCode) {
|
||||
bag.insert(element);
|
||||
qDebug() << "params.stopReason = EncodeBitstreamParams::DIDNT_FIT --- line:" << __LINE__;
|
||||
params.stopReason = EncodeBitstreamParams::DIDNT_FIT;
|
||||
return bytesWritten;
|
||||
}
|
||||
|
@ -977,9 +978,11 @@ int Octree::encodeTreeBitstream(OctreeElement* element,
|
|||
|
||||
// if includeColor and childBytesWritten == 2, then it can only mean that the lower level trees don't exist or for some
|
||||
// reason couldn't be written... so reset them here... This isn't true for the non-color included case
|
||||
if (params.includeColor && childBytesWritten == 2) {
|
||||
childBytesWritten = 0;
|
||||
//params.stopReason = EncodeBitstreamParams::UNKNOWN; // possibly should be DIDNT_FIT...
|
||||
if (suppressEmptySubtrees()) {
|
||||
if (params.includeColor && childBytesWritten == 2) {
|
||||
childBytesWritten = 0;
|
||||
//params.stopReason = EncodeBitstreamParams::UNKNOWN; // possibly should be DIDNT_FIT...
|
||||
}
|
||||
}
|
||||
|
||||
// if we wrote child bytes, then return our result of all bytes written
|
||||
|
@ -1010,6 +1013,15 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
|
||||
// The append state of this level/element.
|
||||
OctreeElement::AppendState elementAppendState = OctreeElement::COMPLETED; // assume the best
|
||||
if (element != _rootElement) {
|
||||
qDebug() << "TOP OF Octree::encodeTreeBitstreamRecursion().... elementAppendState = OctreeElement::COMPLETED ----";
|
||||
if (element) {
|
||||
qDebug() << " element=" << element->getAACube();
|
||||
element->debugExtraEncodeData(params);
|
||||
} else {
|
||||
qDebug() << " element=NULL";
|
||||
}
|
||||
}
|
||||
|
||||
// How many bytes have we written so far at this level;
|
||||
int bytesAtThisLevel = 0;
|
||||
|
@ -1018,6 +1030,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
if (!element) {
|
||||
qDebug("WARNING! encodeTreeBitstreamRecursion() called with element=NULL");
|
||||
params.stopReason = EncodeBitstreamParams::NULL_NODE;
|
||||
qDebug() << "encodeTreeBitstreamRecursion() --- returning from line: " << __LINE__;
|
||||
return bytesAtThisLevel;
|
||||
}
|
||||
|
||||
|
@ -1029,6 +1042,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
// If we've reached our max Search Level, then stop searching.
|
||||
if (currentEncodeLevel >= params.maxEncodeLevel) {
|
||||
params.stopReason = EncodeBitstreamParams::TOO_DEEP;
|
||||
qDebug() << "encodeTreeBitstreamRecursion() --- returning from line: " << __LINE__;
|
||||
return bytesAtThisLevel;
|
||||
}
|
||||
|
||||
|
@ -1038,6 +1052,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
// but once we're in our own jurisdiction, then we need to make sure we're not below it.
|
||||
if (JurisdictionMap::BELOW == params.jurisdictionMap->isMyJurisdiction(element->getOctalCode(), CHECK_NODE_ONLY)) {
|
||||
params.stopReason = EncodeBitstreamParams::OUT_OF_JURISDICTION;
|
||||
qDebug() << "encodeTreeBitstreamRecursion() --- returning from line: " << __LINE__;
|
||||
return bytesAtThisLevel;
|
||||
}
|
||||
}
|
||||
|
@ -1056,6 +1071,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
params.stats->skippedDistance(element);
|
||||
}
|
||||
params.stopReason = EncodeBitstreamParams::LOD_SKIP;
|
||||
qDebug() << "encodeTreeBitstreamRecursion() --- returning from line: " << __LINE__;
|
||||
return bytesAtThisLevel;
|
||||
}
|
||||
|
||||
|
@ -1074,6 +1090,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
params.stats->skippedOutOfView(element);
|
||||
}
|
||||
params.stopReason = EncodeBitstreamParams::OUT_OF_VIEW;
|
||||
qDebug() << "encodeTreeBitstreamRecursion() --- returning from line: " << __LINE__;
|
||||
return bytesAtThisLevel;
|
||||
}
|
||||
|
||||
|
@ -1114,6 +1131,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
params.stats->skippedWasInView(element);
|
||||
}
|
||||
params.stopReason = EncodeBitstreamParams::WAS_IN_VIEW;
|
||||
qDebug() << "encodeTreeBitstreamRecursion() --- returning from line: " << __LINE__;
|
||||
return bytesAtThisLevel;
|
||||
}
|
||||
|
||||
|
@ -1125,6 +1143,9 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
params.stats->skippedNoChange(element);
|
||||
}
|
||||
params.stopReason = EncodeBitstreamParams::NO_CHANGE;
|
||||
if (element != _rootElement) {
|
||||
qDebug() << "encodeTreeBitstreamRecursion() --- returning from line: " << __LINE__;
|
||||
}
|
||||
return bytesAtThisLevel;
|
||||
}
|
||||
|
||||
|
@ -1145,6 +1166,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
params.stats->skippedOccluded(element);
|
||||
}
|
||||
params.stopReason = EncodeBitstreamParams::OCCLUDED;
|
||||
qDebug() << "encodeTreeBitstreamRecursion() --- returning from line: " << __LINE__;
|
||||
return bytesAtThisLevel;
|
||||
}
|
||||
} else {
|
||||
|
@ -1171,14 +1193,30 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
int requiredBytes = sizeof(childrenDataBits) + sizeof(childrenExistInPacketBits);
|
||||
if (params.includeExistsBits) {
|
||||
requiredBytes += sizeof(childrenExistInTreeBits);
|
||||
}
|
||||
}
|
||||
|
||||
// If this datatype allows root elements to include data, and this is the root, then ask the tree for the
|
||||
// minimum bytes needed for root data and reserve those also
|
||||
if (element == _rootElement && rootElementHasData()) {
|
||||
requiredBytes += minimumRequiredRootDataBytes();
|
||||
if (wantDebug) {
|
||||
qDebug() << "Reserving at least " << minimumRequiredRootDataBytes() << " additional bytes for root data <<<<<<<<<<";
|
||||
}
|
||||
}
|
||||
if (wantDebug) {
|
||||
qDebug() << "Reserving total of " << requiredBytes <<" bytes for this elements data <<<<<<<<<<<<<<";
|
||||
}
|
||||
|
||||
bool continueThisLevel = packetData->reserveBytes(requiredBytes);
|
||||
|
||||
// If we can't reserve our minimum bytes then we can discard this level and return as if none of this level fits
|
||||
if (!continueThisLevel) {
|
||||
qDebug() << " .....COULDN'T RESERVE MINIMUM BYTES.....";
|
||||
packetData->discardLevel(thisLevelKey);
|
||||
qDebug() << "params.stopReason = EncodeBitstreamParams::DIDNT_FIT --- line:" << __LINE__;
|
||||
params.stopReason = EncodeBitstreamParams::DIDNT_FIT;
|
||||
bag.insert(element);
|
||||
qDebug() << "encodeTreeBitstreamRecursion() --- returning from line: " << __LINE__;
|
||||
return bytesAtThisLevel;
|
||||
}
|
||||
|
||||
|
@ -1361,29 +1399,41 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
}
|
||||
}
|
||||
|
||||
// NOTE: the childrenDataBits is really more generically the childDataBits and it indicates
|
||||
// that there is an array of child element data included in this packet. We wil write this bit mask
|
||||
// but we may come back later and update the bits that are actually included
|
||||
// NOTE: the childrenDataBits indicates that there is an array of child element data included in this packet.
|
||||
// We wil write this bit mask but we may come back later and update the bits that are actually included
|
||||
packetData->releaseReservedBytes(sizeof(childrenDataBits));
|
||||
continueThisLevel = packetData->appendBitMask(childrenDataBits);
|
||||
|
||||
// we know the last thing we wrote to the packet was our childrenDataBits. Let's remember where that was!
|
||||
int childDataBitsPlaceHolder = packetData->getUncompressedByteOffset(sizeof(childrenDataBits));
|
||||
unsigned char actualChildrenDataBits = 0;
|
||||
|
||||
if (continueThisLevel) {
|
||||
bytesAtThisLevel += sizeof(childrenDataBits); // keep track of byte count
|
||||
if (params.stats) {
|
||||
params.stats->colorBitsWritten();
|
||||
}
|
||||
assert(continueThisLevel); // since we used reserved bits, this really shouldn't fail
|
||||
bytesAtThisLevel += sizeof(childrenDataBits); // keep track of byte count
|
||||
if (params.stats) {
|
||||
params.stats->colorBitsWritten(); // really data bits not just color bits
|
||||
}
|
||||
|
||||
// write the child element data...
|
||||
if (continueThisLevel && params.includeColor) {
|
||||
// NOW might be a good time to give our tree subclass and this element a chance to set up and check any extra encode data
|
||||
element->initializeExtraEncodeData(params);
|
||||
|
||||
// write the child element data... NOTE: includeColor means include element data
|
||||
// NOTE: the format of the bitstream is generally this:
|
||||
// [octalcode]
|
||||
// [bitmask for existence of child data]
|
||||
// N x [child data]
|
||||
// [bitmask for existence of child elements in tree]
|
||||
// [bitmask for existence of child elements in buffer]
|
||||
// N x [ ... tree for children ...]
|
||||
//
|
||||
// This section of the code, is writing the "N x [child data]" portion of this bitstream
|
||||
if (params.includeColor) {
|
||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||
if (oneAtBit(childrenDataBits, i)) {
|
||||
OctreeElement* childElement = element->getChildAtIndex(i);
|
||||
if (childElement) {
|
||||
|
||||
// the childrenDataBits were set up by the in view/LOD logic, it may contain children that we've already
|
||||
// processed and sent the data bits for. Let our tree subclass determine if it really wants to send the
|
||||
// data for this child at this point
|
||||
if (childElement && element->shouldIncludeChild(i, params)) {
|
||||
|
||||
int bytesBeforeChild = packetData->getUncompressedSize();
|
||||
|
||||
|
@ -1394,7 +1444,11 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
// to be completed.
|
||||
LevelDetails childDataLevelKey = packetData->startLevel();
|
||||
|
||||
qDebug() << "Octree::encodeTreeBitstreamRecursion().... calling childElement->appendElementData()... child:" << childElement->getAACube();
|
||||
OctreeElement::AppendState childAppendState = childElement->appendElementData(packetData, params);
|
||||
|
||||
// allow our tree subclass to do any additional bookkeeping it needs to do with encoded data state
|
||||
element->updateEncodedData(i, childAppendState, params);
|
||||
|
||||
// Continue this level so long as some part of this child element was appended.
|
||||
bool childFit = (childAppendState != OctreeElement::NONE);
|
||||
|
@ -1405,15 +1459,27 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
actualChildrenDataBits += (1 << (7 - i));
|
||||
continueThisLevel = packetData->endLevel(childDataLevelKey);
|
||||
} else {
|
||||
if (wantDebug) {
|
||||
qDebug() << "(childAppendState == OctreeElement::NONE) ... consider this element PARTIAL *************************************************";
|
||||
qDebug() << " childElement=" << childElement->getAACube();
|
||||
}
|
||||
packetData->discardLevel(childDataLevelKey);
|
||||
elementAppendState = OctreeElement::PARTIAL;
|
||||
params.stopReason = EncodeBitstreamParams::DIDNT_FIT;
|
||||
qDebug() << "Octree::encodeTreeBitstreamRecursion().... at least one child didn't fit elementAppendState = OctreeElement::PARTIAL ----";
|
||||
qDebug() << "params.stopReason = EncodeBitstreamParams::DIDNT_FIT --- line:" << __LINE__;
|
||||
}
|
||||
|
||||
// If this child was partially appended, then consider this element to be partially appended
|
||||
if (childAppendState == OctreeElement::PARTIAL) {
|
||||
if (wantDebug) {
|
||||
qDebug() << "(childAppendState == OctreeElement::PARTIAL) ... consider this element PARTIAL";
|
||||
qDebug() << " childElement=" << childElement->getAACube();
|
||||
}
|
||||
elementAppendState = OctreeElement::PARTIAL;
|
||||
params.stopReason = EncodeBitstreamParams::DIDNT_FIT;
|
||||
qDebug() << "Octree::encodeTreeBitstreamRecursion().... at least one child WAS PARTIAL elementAppendState = OctreeElement::PARTIAL ----";
|
||||
qDebug() << "params.stopReason = EncodeBitstreamParams::DIDNT_FIT --- line:" << __LINE__;
|
||||
}
|
||||
|
||||
int bytesAfterChild = packetData->getUncompressedSize();
|
||||
|
@ -1424,14 +1490,35 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
if (params.stats && (childAppendState != OctreeElement::NONE)) {
|
||||
params.stats->colorSent(childElement);
|
||||
}
|
||||
} else {
|
||||
qDebug() << "Octree::encodeTreeBitstreamRecursion().... DIDN'T ATTEMPT TO appendElementData() for child[" << i << "]";
|
||||
if (childElement) {
|
||||
qDebug() << " childElement=" << childElement->getAACube();
|
||||
} else {
|
||||
qDebug() << " childElement=NULL";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!continueThisLevel) {
|
||||
qDebug() << "******* WARNING UNEXPECTED CASE ***********************************************************";
|
||||
qDebug() << "reached end of child element data loop with continueThisLevel=FALSE....";
|
||||
qDebug() << "This is not expected!!!!";
|
||||
qDebug() << "*******************************************************************************************";
|
||||
}
|
||||
|
||||
if (actualChildrenDataBits != childrenDataBits) {
|
||||
// repair the child data mask
|
||||
continueThisLevel = packetData->updatePriorBitMask(childDataBitsPlaceHolder, actualChildrenDataBits);
|
||||
|
||||
if (!continueThisLevel) {
|
||||
qDebug() << "******* WARNING UNEXPECTED CASE ***********************************************************";
|
||||
qDebug() << "Failed to update childDataBitsPlaceHolder -- continueThisLevel=FALSE....";
|
||||
qDebug() << "This is not expected!!!!";
|
||||
qDebug() << "*******************************************************************************************";
|
||||
}
|
||||
}
|
||||
|
||||
// if the caller wants to include childExistsBits, then include them even if not in view, put them before the
|
||||
|
@ -1444,6 +1531,11 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
if (params.stats) {
|
||||
params.stats->existsBitsWritten();
|
||||
}
|
||||
} else {
|
||||
qDebug() << "******* WARNING UNEXPECTED CASE ***********************************************************";
|
||||
qDebug() << "Failed to append childrenExistInTreeBits -- continueThisLevel=FALSE....";
|
||||
qDebug() << "This is not expected!!!!";
|
||||
qDebug() << "*******************************************************************************************";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1456,12 +1548,28 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
if (params.stats) {
|
||||
params.stats->existsInPacketBitsWritten();
|
||||
}
|
||||
} else {
|
||||
qDebug() << "******* WARNING UNEXPECTED CASE ***********************************************************";
|
||||
qDebug() << "Failed to append childrenExistInPacketBits -- continueThisLevel=FALSE....";
|
||||
qDebug() << "This is not expected!!!!";
|
||||
qDebug() << "*******************************************************************************************";
|
||||
}
|
||||
}
|
||||
|
||||
// We only need to keep digging, if there is at least one child that is inView, and not a leaf.
|
||||
keepDiggingDeeper = (inViewNotLeafCount > 0);
|
||||
|
||||
//
|
||||
// NOTE: the format of the bitstream is generally this:
|
||||
// [octalcode]
|
||||
// [bitmask for existence of child data]
|
||||
// N x [child data]
|
||||
// [bitmask for existence of child elements in tree]
|
||||
// [bitmask for existence of child elements in buffer]
|
||||
// N x [ ... tree for children ...]
|
||||
//
|
||||
// This section of the code, is writing the "N x [ ... tree for children ...]" portion of this bitstream
|
||||
//
|
||||
if (continueThisLevel && keepDiggingDeeper) {
|
||||
|
||||
// at this point, we need to iterate the children who are in view, even if not colored
|
||||
|
@ -1505,8 +1613,10 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
// recursing, by returning TRUE in recurseChildrenWithData().
|
||||
|
||||
if (recurseChildrenWithData() || !params.viewFrustum || !oneAtBit(childrenDataBits, originalIndex)) {
|
||||
childTreeBytesOut = encodeTreeBitstreamRecursion(childElement, packetData, bag, params,
|
||||
thisLevel, nodeLocationThisView);
|
||||
if (childElement->shouldRecurseSubtree(element, params, &bag)) {
|
||||
childTreeBytesOut = encodeTreeBitstreamRecursion(childElement, packetData, bag, params,
|
||||
thisLevel, nodeLocationThisView);
|
||||
}
|
||||
}
|
||||
|
||||
// remember this for reshuffling
|
||||
|
@ -1552,6 +1662,12 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
|
||||
// repair the child exists mask
|
||||
continueThisLevel = packetData->updatePriorBitMask(childExistsPlaceHolder, childrenExistInPacketBits);
|
||||
if (!continueThisLevel) {
|
||||
qDebug() << "******* WARNING UNEXPECTED CASE ***********************************************************";
|
||||
qDebug() << "Failed to update childExistsPlaceHolder -- continueThisLevel=FALSE....";
|
||||
qDebug() << "This is not expected!!!!";
|
||||
qDebug() << "*******************************************************************************************";
|
||||
}
|
||||
|
||||
// If this is the last of the child exists bits, then we're actually be rolling out the entire tree
|
||||
if (params.stats && childrenExistInPacketBits == 0) {
|
||||
|
@ -1559,7 +1675,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
}
|
||||
|
||||
if (!continueThisLevel) {
|
||||
if (wantDebug) {
|
||||
if (true || wantDebug) {
|
||||
qDebug() << " WARNING line:" << __LINE__;
|
||||
qDebug() << " breaking the child recursion loop with continueThisLevel=false!!!";
|
||||
qDebug() << " AFTER attempting to updatePriorBitMask() for empty sub tree....";
|
||||
|
@ -1594,6 +1710,12 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
|
||||
// now that all slices are back in the correct order, copy them to the correct output buffer
|
||||
continueThisLevel = packetData->updatePriorBytes(firstRecursiveSliceOffset, &tempReshuffleBuffer[0], allSlicesSize);
|
||||
if (!continueThisLevel) {
|
||||
qDebug() << "******* WARNING UNEXPECTED CASE ***********************************************************";
|
||||
qDebug() << "Failed to update recursive slice!!! -- continueThisLevel=FALSE....";
|
||||
qDebug() << "This is not expected!!!!";
|
||||
qDebug() << "*******************************************************************************************";
|
||||
}
|
||||
}
|
||||
} // end keepDiggingDeeper
|
||||
|
||||
|
@ -1603,6 +1725,10 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
|
||||
int bytesBeforeChild = packetData->getUncompressedSize();
|
||||
|
||||
// release the bytes we reserved...
|
||||
qDebug() << "RELEASING previously reserved " << minimumRequiredRootDataBytes() << " bytes for root -- line:" << __LINE__;
|
||||
packetData->releaseReservedBytes(minimumRequiredRootDataBytes());
|
||||
|
||||
LevelDetails rootDataLevelKey = packetData->startLevel();
|
||||
OctreeElement::AppendState rootAppendState = element->appendElementData(packetData, params);
|
||||
bool partOfRootFit = (rootAppendState != OctreeElement::NONE);
|
||||
|
@ -1620,6 +1746,8 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
if (!allOfRootFit) {
|
||||
elementAppendState = OctreeElement::PARTIAL;
|
||||
params.stopReason = EncodeBitstreamParams::DIDNT_FIT;
|
||||
qDebug() << "Octree::encodeTreeBitstreamRecursion().... ROOT DATA WAS PARTIAL OR DIDN'T FIT elementAppendState = OctreeElement::PARTIAL ----";
|
||||
qDebug() << "params.stopReason = EncodeBitstreamParams::DIDNT_FIT --- line:" << __LINE__;
|
||||
}
|
||||
|
||||
// do we really ever NOT want to continue this level???
|
||||
|
@ -1634,6 +1762,14 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
params.stats->colorSent(element);
|
||||
}
|
||||
}
|
||||
|
||||
if (!continueThisLevel) {
|
||||
qDebug() << "******* WARNING UNEXPECTED CASE ***********************************************************";
|
||||
qDebug() << "Something failed in packing ROOT data -- continueThisLevel=FALSE....";
|
||||
qDebug() << "This is not expected!!!!";
|
||||
qDebug() << "*******************************************************************************************";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// if we were unable to fit this level in our packet, then rewind and add it to the element bag for
|
||||
|
@ -1642,12 +1778,22 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
continueThisLevel = packetData->endLevel(thisLevelKey);
|
||||
} else {
|
||||
packetData->discardLevel(thisLevelKey);
|
||||
qDebug() << "******* WARNING UNEXPECTED CASE ***********************************************************";
|
||||
qDebug() << "Something failed in attempting to pack this element -- continueThisLevel=FALSE....";
|
||||
qDebug() << "This is not expected!!!!";
|
||||
qDebug() << "*******************************************************************************************";
|
||||
}
|
||||
|
||||
// This happens if the element could not be written at all. In the case of Octree's that support partial
|
||||
// element data, continueThisLevel will be true. So this only happens if the full element needs to be
|
||||
// added back to the element bag.
|
||||
if (!continueThisLevel) {
|
||||
qDebug() << "******* WARNING UNEXPECTED CASE ***********************************************************";
|
||||
qDebug() << "Something failed in attempting to pack this element -- continueThisLevel=FALSE....";
|
||||
qDebug() << "IS THIS EVER EXPECTED????";
|
||||
qDebug() << " calling bag.insert(element);.....";
|
||||
qDebug() << "*******************************************************************************************";
|
||||
|
||||
bag.insert(element);
|
||||
|
||||
// don't need to check element here, because we can't get here with no element
|
||||
|
@ -1656,6 +1802,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
}
|
||||
|
||||
params.stopReason = EncodeBitstreamParams::DIDNT_FIT;
|
||||
qDebug() << "params.stopReason = EncodeBitstreamParams::DIDNT_FIT --- line:" << __LINE__;
|
||||
bytesAtThisLevel = 0; // didn't fit
|
||||
} else {
|
||||
|
||||
|
@ -1665,10 +1812,31 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
|||
// and assume that the appendElementData() has stored any required state data
|
||||
// in the params extraEncodeData
|
||||
if (elementAppendState == OctreeElement::PARTIAL) {
|
||||
if (true || wantDebug) {
|
||||
qDebug() << "(elementAppendState == OctreeElement::PARTIAL) ...";
|
||||
qDebug() << " RE INSERT THIS(parent) element into bag";
|
||||
qDebug() << " element:" << element->getAACube();
|
||||
}
|
||||
|
||||
bag.insert(element);
|
||||
}
|
||||
}
|
||||
|
||||
// If our element is completed let the element know so it can do any cleanup it of extra wants
|
||||
if (elementAppendState == OctreeElement::COMPLETED) {
|
||||
if (true || wantDebug) {
|
||||
qDebug() << "*********************************************************************************************************";
|
||||
qDebug() << "(elementAppendState == OctreeElement::COMPLETED)";
|
||||
qDebug() << " calling element->elementEncodeComplete(params)";
|
||||
qDebug() << " element=" << element->getAACube();
|
||||
}
|
||||
element->elementEncodeComplete(params, &bag);
|
||||
if (true || wantDebug) {
|
||||
qDebug() << "*********************************************************************************************************";
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "encodeTreeBitstreamRecursion() --- returning from line: " << __LINE__;
|
||||
return bytesAtThisLevel;
|
||||
}
|
||||
|
||||
|
@ -1855,11 +2023,18 @@ void Octree::writeToSVOFile(const char* fileName, OctreeElement* element) {
|
|||
params.extraEncodeData = &extraEncodeData;
|
||||
|
||||
while (!elementBag.isEmpty()) {
|
||||
qDebug() << "WRITING SVO ---- START LOOP ---------------";
|
||||
OctreeElement* subTree = elementBag.extract();
|
||||
qDebug() << "WRITING SVO subTree=" << subTree->getAACube();
|
||||
|
||||
lockForRead(); // do tree locking down here so that we have shorter slices and less thread contention
|
||||
bytesWritten = encodeTreeBitstream(subTree, &packetData, elementBag, params);
|
||||
unlock();
|
||||
|
||||
qDebug() << "WRITING SVO subTree=" << subTree->getAACube() << " bytesWritten=" << bytesWritten;
|
||||
qDebug() << "WRITING SVO subTree=" << subTree->getAACube() << " params.stopReason=" << params.getStopReason();
|
||||
qDebug() << "WRITING SVO subTree=" << subTree->getAACube() << " packetData.hasContent()=" << packetData.hasContent();
|
||||
|
||||
// if the subTree couldn't fit, and so we should reset the packet and reinsert the element in our bag and try again
|
||||
if (bytesWritten == 0 && (params.stopReason == EncodeBitstreamParams::DIDNT_FIT)) {
|
||||
if (packetData.hasContent()) {
|
||||
|
@ -1870,13 +2045,16 @@ void Octree::writeToSVOFile(const char* fileName, OctreeElement* element) {
|
|||
file.write((const char*)&bufferSize, sizeof(bufferSize));
|
||||
}
|
||||
file.write((const char*)packetData.getFinalizedData(), packetData.getFinalizedSize());
|
||||
qDebug() << "WRITING SVO actually writing to the file bufferSize:" << packetData.getFinalizedSize();
|
||||
lastPacketWritten = true;
|
||||
}
|
||||
packetData.reset(); // is there a better way to do this? could we fit more?
|
||||
qDebug() << "WRITING SVO INSERT SUBTREE FOR ANOTHER GO ... subTree=" << subTree->getAACube();
|
||||
elementBag.insert(subTree);
|
||||
} else {
|
||||
lastPacketWritten = false;
|
||||
}
|
||||
qDebug() << "WRITING SVO ---- END LOOP ---------------";
|
||||
}
|
||||
|
||||
if (!lastPacketWritten) {
|
||||
|
@ -1887,8 +2065,10 @@ void Octree::writeToSVOFile(const char* fileName, OctreeElement* element) {
|
|||
file.write((const char*)&bufferSize, sizeof(bufferSize));
|
||||
}
|
||||
file.write((const char*)packetData.getFinalizedData(), packetData.getFinalizedSize());
|
||||
qDebug() << "WRITING SVO actually writing to the file bufferSize:" << packetData.getFinalizedSize();
|
||||
}
|
||||
}
|
||||
qDebug() << "WRITING SVO CLOSING FILE";
|
||||
file.close();
|
||||
}
|
||||
|
||||
|
|
|
@ -233,6 +233,8 @@ public:
|
|||
|
||||
virtual bool recurseChildrenWithData() const { return true; }
|
||||
virtual bool rootElementHasData() const { return false; }
|
||||
virtual int minimumRequiredRootDataBytes() const { return 0; }
|
||||
virtual bool suppressEmptySubtrees() const { return true; }
|
||||
|
||||
/// some versions of the SVO file will include breaks with buffer lengths between each buffer chunk in the SVO
|
||||
/// file. If the Octree subclass expects this for this particular version of the file, it should override this
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
class EncodeBitstreamParams;
|
||||
class Octree;
|
||||
class OctreeElement;
|
||||
class OctreeElementBag;
|
||||
class OctreeElementDeleteHook;
|
||||
class OctreePacketData;
|
||||
class ReadBitstreamToTreeParams;
|
||||
|
@ -90,6 +91,14 @@ public:
|
|||
/// The state of the call to appendElementData
|
||||
typedef enum { COMPLETED, PARTIAL, NONE } AppendState;
|
||||
|
||||
virtual void debugExtraEncodeData(EncodeBitstreamParams& params) const { }
|
||||
virtual void initializeExtraEncodeData(EncodeBitstreamParams& params) const { }
|
||||
virtual bool shouldIncludeChild(int childIndex, EncodeBitstreamParams& params) const { return true; }
|
||||
virtual bool shouldRecurseSubtree(OctreeElement* parent, EncodeBitstreamParams& params, OctreeElementBag* bag) const { return true; }
|
||||
|
||||
virtual void updateEncodedData(int childIndex, AppendState childAppendState, EncodeBitstreamParams& params) const { }
|
||||
virtual void elementEncodeComplete(EncodeBitstreamParams& params, OctreeElementBag* bag) const { }
|
||||
|
||||
/// Override to serialize the state of this element. This is used for persistance and for transmission across the network.
|
||||
virtual AppendState appendElementData(OctreePacketData* packetData, EncodeBitstreamParams& params) const
|
||||
{ return COMPLETED; }
|
||||
|
|
Loading…
Reference in a new issue