mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-04 06:13:09 +02:00
fixed some problems in UpdateEntityOperator in case where original containing element isn't best fit
This commit is contained in:
parent
f654fac851
commit
2fab662e8c
11 changed files with 532 additions and 124 deletions
|
@ -66,8 +66,21 @@ void EntityTreeRenderer::update() {
|
|||
}
|
||||
|
||||
void EntityTreeRenderer::render(RenderMode renderMode) {
|
||||
|
||||
bool wantDebug = false;
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "------------ EntityTreeRenderer::render() -- BEFORE WE BEGIN: the tree[" << _tree << "] -------------";
|
||||
static_cast<EntityTree*>(_tree)->dumpTree();
|
||||
qDebug() << "------------ EntityTreeRenderer::render() -- END the tree-------------";
|
||||
}
|
||||
|
||||
OctreeRenderer::render(renderMode);
|
||||
deleteReleasedModels(); // seems like as good as any other place to do some memory cleanup
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "------------ DONE EntityTreeRenderer::render() -------------";
|
||||
}
|
||||
}
|
||||
|
||||
const FBXGeometry* EntityTreeRenderer::getGeometryForEntity(const EntityItem* entityItem) {
|
||||
|
@ -98,6 +111,14 @@ const Model* EntityTreeRenderer::getModelForEntityItem(const EntityItem* entityI
|
|||
}
|
||||
|
||||
void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) {
|
||||
bool wantDebug = false;
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "EntityTreeRenderer::renderElement()...";
|
||||
qDebug() << " element=" << element;
|
||||
qDebug() << " element->getAACube()=" << element->getAACube();
|
||||
}
|
||||
|
||||
//PerformanceTimer perfTimer("renderElement");
|
||||
args->_elementsTouched++;
|
||||
// actually render it here...
|
||||
|
@ -180,8 +201,6 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
|
|||
|
||||
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
||||
EntityItem* entityItem = entityItems[i];
|
||||
bool wantDebug = false;
|
||||
|
||||
if (wantDebug) {
|
||||
bool isBestFit = entityTreeElement->bestFitEntityBounds(entityItem);
|
||||
qDebug() << "EntityTreeRenderer::renderElement() "
|
||||
|
@ -202,6 +221,12 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
|
|||
if (entityItem->getGlowLevel() > 0.0f) {
|
||||
glower = new Glower(entityItem->getGlowLevel());
|
||||
}
|
||||
if (wantDebug) {
|
||||
qDebug() << " EntityTreeRenderer about to render entity...";
|
||||
qDebug() << " element=" << element;
|
||||
qDebug() << " entityItem=" << entityItem;
|
||||
qDebug() << " entityItem->getEntityItemID()=" << entityItem->getEntityItemID();
|
||||
}
|
||||
entityItem->render(args);
|
||||
if (glower) {
|
||||
delete glower;
|
||||
|
|
|
@ -21,36 +21,95 @@ DeleteEntityOperator::DeleteEntityOperator(EntityTree* tree, const EntityItemID&
|
|||
_foundCount(0),
|
||||
_lookingCount(0)
|
||||
{
|
||||
bool wantDebug = false;
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "DeleteEntityOperator(EntityTree* tree, const EntityItemID& searchEntityID).... ";
|
||||
qDebug() << " tree=" << tree;
|
||||
qDebug() << " _tree=" << tree;
|
||||
qDebug() << "------------ DeleteEntityOperator -- BEFORE WE BEGIN: the tree[" << _tree << "] -------------";
|
||||
_tree->dumpTree();
|
||||
qDebug() << "------------ DeleteEntityOperator -- END the tree-------------";
|
||||
}
|
||||
addEntityIDToDeleteList(searchEntityID);
|
||||
}
|
||||
|
||||
DeleteEntityOperator::~DeleteEntityOperator() {
|
||||
bool wantDebug = false;
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "~DeleteEntityOperator(EntityTree* tree, const EntityItemID& searchEntityID).... ";
|
||||
qDebug() << "------------ ~DeleteEntityOperator -- AFTER WE'RE DONE: the tree[" << _tree << "] -------------";
|
||||
_tree->dumpTree();
|
||||
qDebug() << "------------ ~DeleteEntityOperator -- END the tree-------------";
|
||||
}
|
||||
}
|
||||
|
||||
DeleteEntityOperator::DeleteEntityOperator(EntityTree* tree) :
|
||||
_tree(tree),
|
||||
_changeTime(usecTimestampNow()),
|
||||
_foundCount(0),
|
||||
_lookingCount(0)
|
||||
{
|
||||
bool wantDebug = false;
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "DeleteEntityOperator(EntityTree* tree).... ";
|
||||
qDebug() << " tree=" << tree;
|
||||
qDebug() << " _tree=" << _tree;
|
||||
qDebug() << "------------ DeleteEntityOperator -- BEFORE WE BEGIN: the tree[" << _tree << "] -------------";
|
||||
_tree->dumpTree();
|
||||
qDebug() << "------------ DeleteEntityOperator -- END the tree-------------";
|
||||
}
|
||||
}
|
||||
|
||||
void DeleteEntityOperator::addEntityIDToDeleteList(const EntityItemID& searchEntityID) {
|
||||
bool wantDebug = false;
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "DeleteEntityOperator::addEntityIDToDeleteList(const EntityItemID& searchEntityID).... ";
|
||||
qDebug() << " _tree=" << _tree;
|
||||
qDebug() << " searchEntityID=" << searchEntityID;
|
||||
}
|
||||
|
||||
// check our tree, to determine if this entity is known
|
||||
EntityToDeleteDetails details;
|
||||
details.containingElement = _tree->getContainingElement(searchEntityID);
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << " details.containingElement=" << details.containingElement;
|
||||
}
|
||||
|
||||
if (details.containingElement) {
|
||||
details.entity = details.containingElement->getEntityWithEntityItemID(searchEntityID);
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << " details.entity=" << details.entity;
|
||||
}
|
||||
|
||||
if (!details.entity) {
|
||||
//assert(false);
|
||||
qDebug() << "that's UNEXPECTED, we got a _containingElement, but couldn't find the oldEntity!";
|
||||
} else {
|
||||
details.cube = details.containingElement->getAACube();
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << " details.cube=" << details.cube;
|
||||
}
|
||||
|
||||
_entitiesToDelete << details;
|
||||
_lookingCount++;
|
||||
|
||||
|
||||
_tree->trackDeletedEntity(searchEntityID);
|
||||
// before deleting any entity make sure to remove it from our Mortal, Changing, and Moving lists
|
||||
_tree->removeEntityFromSimulationLists(searchEntityID);
|
||||
}
|
||||
}
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << " _entitiesToDelete.size():" << _entitiesToDelete.size();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -73,6 +132,29 @@ bool DeleteEntityOperator::subTreeContainsSomeEntitiesToDelete(OctreeElement* el
|
|||
}
|
||||
|
||||
bool DeleteEntityOperator::PreRecursion(OctreeElement* element) {
|
||||
bool wantDebug = false;
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "DeleteEntityOperator::PreRecursion().... ";
|
||||
qDebug() << " element=" << element;
|
||||
qDebug() << " element.AACube=" << element->getAACube();
|
||||
qDebug() << " _lookingCount=" << _lookingCount;
|
||||
qDebug() << " _foundCount=" << _foundCount;
|
||||
|
||||
qDebug() << " --------- list of deleting entities -----------";
|
||||
foreach(const EntityToDeleteDetails& details, _entitiesToDelete) {
|
||||
|
||||
qDebug() << " ENTITY TO DELETE";
|
||||
qDebug() << " entity=" << details.entity;
|
||||
qDebug() << " entityItemID=" << details.entity->getEntityItemID();
|
||||
qDebug() << " cube=" << details.cube;
|
||||
qDebug() << " containingElement=" << details.containingElement;
|
||||
qDebug() << " containingElement->getAACube()=" << details.containingElement->getAACube();
|
||||
}
|
||||
qDebug() << " --------- list of deleting entities -----------";
|
||||
}
|
||||
|
||||
|
||||
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
|
||||
|
||||
// In Pre-recursion, we're generally deciding whether or not we want to recurse this
|
||||
|
@ -98,10 +180,20 @@ bool DeleteEntityOperator::PreRecursion(OctreeElement* element) {
|
|||
if (entityTreeElement == details.containingElement) {
|
||||
EntityItemID entityItemID = details.entity->getEntityItemID();
|
||||
EntityItem* theEntity = entityTreeElement->getEntityWithEntityItemID(entityItemID); // find the actual entity
|
||||
entityTreeElement->removeEntityItem(theEntity); // remove it from the element
|
||||
bool removed = entityTreeElement->removeEntityItem(theEntity); // remove it from the element
|
||||
_tree->setContainingElement(entityItemID, NULL); // update or id to element lookup
|
||||
delete theEntity; // now actually delete the entity!
|
||||
_foundCount++;
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "DeleteEntityOperator::PreRecursion().... deleting entity:" << entityItemID;
|
||||
qDebug() << " details.entity=" << details.entity;
|
||||
qDebug() << " theEntity=" << theEntity;
|
||||
qDebug() << " called entityTreeElement->removeEntityItem(theEntity)";
|
||||
qDebug() << " removed=" << removed;
|
||||
qDebug() << " called _tree->setContainingElement(entityItemID, NULL)";
|
||||
qDebug() << " called delete theEntity";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,6 +205,27 @@ bool DeleteEntityOperator::PreRecursion(OctreeElement* element) {
|
|||
}
|
||||
|
||||
bool DeleteEntityOperator::PostRecursion(OctreeElement* element) {
|
||||
bool wantDebug = false;
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "DeleteEntityOperator::PostRecursion().... ";
|
||||
qDebug() << " element=" << element;
|
||||
qDebug() << " element.AACube=" << element->getAACube();
|
||||
qDebug() << " _lookingCount=" << _lookingCount;
|
||||
qDebug() << " _foundCount=" << _foundCount;
|
||||
|
||||
qDebug() << " --------- list of deleting entities -----------";
|
||||
foreach(const EntityToDeleteDetails& details, _entitiesToDelete) {
|
||||
|
||||
qDebug() << " DELETING ENTITY";
|
||||
qDebug() << " entity=" << details.entity;
|
||||
qDebug() << " entityItemID=" << details.entity->getEntityItemID();
|
||||
qDebug() << " cube=" << details.cube;
|
||||
qDebug() << " containingElement=" << details.containingElement;
|
||||
}
|
||||
qDebug() << " --------- list of deleting entities -----------";
|
||||
}
|
||||
|
||||
// Post-recursion is the unwinding process. For this operation, while we
|
||||
// unwind we want to mark the path as being dirty if we changed it below.
|
||||
// We might have two paths, one for the old entity and one for the new entity.
|
||||
|
@ -124,9 +237,9 @@ bool DeleteEntityOperator::PostRecursion(OctreeElement* element) {
|
|||
element->markWithChangedTime();
|
||||
}
|
||||
|
||||
|
||||
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
|
||||
bool somethingPruned = entityTreeElement->pruneChildren(); // take this opportunity to prune any empty leaves
|
||||
bool wantDebug = false;
|
||||
if (somethingPruned && wantDebug) {
|
||||
qDebug() << "DeleteEntityOperator::PostRecursion() something pruned!!!";
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ class DeleteEntityOperator : public RecurseOctreeOperator {
|
|||
public:
|
||||
DeleteEntityOperator(EntityTree* tree);
|
||||
DeleteEntityOperator(EntityTree* tree, const EntityItemID& searchEntityID);
|
||||
~DeleteEntityOperator();
|
||||
|
||||
void addEntityIDToDeleteList(const EntityItemID& searchEntityID);
|
||||
virtual bool PreRecursion(OctreeElement* element);
|
||||
virtual bool PostRecursion(OctreeElement* element);
|
||||
|
|
|
@ -694,16 +694,23 @@ void EntityTree::changeEntityState(EntityItem* const entity,
|
|||
void EntityTree::update() {
|
||||
// our new strategy should be to segregate entities into three classes:
|
||||
// 1) stationary things that are not changing - most models
|
||||
// 2) stationary things that are animating - they can be touched linearly and they don't change the tree
|
||||
// 2) mortal things - these are stationary but have a lifetime - then need to be checked,
|
||||
// can be touched linearly, and won't change the tree
|
||||
// 2) changing things - like things animating they can be touched linearly and they don't change the tree
|
||||
// 3) moving things - these need to scan the tree and update accordingly
|
||||
|
||||
// finally - all things that need to be deleted, can be handled on a single delete pass.
|
||||
//
|
||||
// TODO: theoretically we could combine the move and delete tree passes...
|
||||
lockForWrite();
|
||||
quint64 now = usecTimestampNow();
|
||||
QSet<EntityItemID> entitiesToDelete;
|
||||
updateChangingEntities(now, entitiesToDelete);
|
||||
updateMovingEntities(now, entitiesToDelete);
|
||||
updateMortalEntities(now, entitiesToDelete);
|
||||
deleteEntities(entitiesToDelete);
|
||||
|
||||
if (entitiesToDelete.size() > 0) {
|
||||
deleteEntities(entitiesToDelete);
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
@ -749,66 +756,76 @@ void EntityTree::updateChangingEntities(quint64 now, QSet<EntityItemID>& entitie
|
|||
|
||||
void EntityTree::updateMovingEntities(quint64 now, QSet<EntityItemID>& entitiesToDelete) {
|
||||
bool wantDebug = false;
|
||||
MovingEntitiesOperator moveOperator(this);
|
||||
|
||||
QSet<EntityItem*> entitiesBecomingStatic;
|
||||
QSet<EntityItem*> entitiesBecomingMortal;
|
||||
QSet<EntityItem*> entitiesBecomingChanging;
|
||||
if (_movingEntities.size() > 0) {
|
||||
MovingEntitiesOperator moveOperator(this);
|
||||
|
||||
// TODO: switch these to iterators so we can remove items that get deleted
|
||||
for (int i = 0; i < _movingEntities.size(); i++) {
|
||||
EntityItem* thisEntity = _movingEntities[i];
|
||||
QSet<EntityItem*> entitiesBecomingStatic;
|
||||
QSet<EntityItem*> entitiesBecomingMortal;
|
||||
QSet<EntityItem*> entitiesBecomingChanging;
|
||||
|
||||
// always check to see if the lifetime has expired, for immortal entities this is always false
|
||||
if (thisEntity->lifetimeHasExpired()) {
|
||||
qDebug() << "Lifetime has expired for entity:" << thisEntity->getEntityItemID();
|
||||
entitiesToDelete << thisEntity->getEntityItemID();
|
||||
entitiesBecomingStatic << thisEntity;
|
||||
} else {
|
||||
AACube oldCube = thisEntity->getAACube();
|
||||
thisEntity->update(now);
|
||||
AACube newCube = thisEntity->getAACube();
|
||||
|
||||
// check to see if this movement has sent the entity outside of the domain.
|
||||
AACube domainBounds(glm::vec3(0.0f,0.0f,0.0f), 1.0f);
|
||||
if (!domainBounds.touches(newCube)) {
|
||||
if (wantDebug) {
|
||||
qDebug() << "The entity " << thisEntity->getEntityItemID() << " moved outside of the domain. Delete it.";
|
||||
}
|
||||
// TODO: switch these to iterators so we can remove items that get deleted
|
||||
for (int i = 0; i < _movingEntities.size(); i++) {
|
||||
EntityItem* thisEntity = _movingEntities[i];
|
||||
|
||||
// always check to see if the lifetime has expired, for immortal entities this is always false
|
||||
if (thisEntity->lifetimeHasExpired()) {
|
||||
qDebug() << "Lifetime has expired for entity:" << thisEntity->getEntityItemID();
|
||||
entitiesToDelete << thisEntity->getEntityItemID();
|
||||
entitiesBecomingStatic << thisEntity;
|
||||
} else {
|
||||
AACube oldCube = thisEntity->getAACube();
|
||||
thisEntity->update(now);
|
||||
AACube newCube = thisEntity->getAACube();
|
||||
if (wantDebug) {
|
||||
qDebug() << "EntityTree::update() thisEntity=" << thisEntity;
|
||||
qDebug() << " oldCube=" << oldCube;
|
||||
qDebug() << " newCube=" << newCube;
|
||||
qDebug() << "MOVING entity " << thisEntity->getEntityItemID();
|
||||
qDebug() << " oldCube:" << oldCube;
|
||||
qDebug() << " newCube:" << newCube;
|
||||
}
|
||||
|
||||
// check to see if this movement has sent the entity outside of the domain.
|
||||
AACube domainBounds(glm::vec3(0.0f,0.0f,0.0f), 1.0f);
|
||||
if (!domainBounds.touches(newCube)) {
|
||||
if (wantDebug) {
|
||||
qDebug() << "The entity moved outside of the domain. Delete it.";
|
||||
qDebug() << " entity=" << thisEntity;
|
||||
qDebug() << " entityID=" << thisEntity->getEntityItemID();
|
||||
}
|
||||
|
||||
moveOperator.addEntityToMoveList(thisEntity, oldCube, newCube);
|
||||
|
||||
// check to see if this entity is no longer moving
|
||||
EntityItem::SimulationState newState = thisEntity->getSimulationState();
|
||||
if (newState == EntityItem::Changing) {
|
||||
entitiesBecomingChanging << thisEntity;
|
||||
} else if (newState == EntityItem::Mortal) {
|
||||
entitiesBecomingMortal << thisEntity;
|
||||
} else if (newState == EntityItem::Static) {
|
||||
entitiesToDelete << thisEntity->getEntityItemID();
|
||||
entitiesBecomingStatic << thisEntity;
|
||||
} else {
|
||||
if (wantDebug) {
|
||||
qDebug() << " ACTUALLY MOVING IT";
|
||||
}
|
||||
|
||||
moveOperator.addEntityToMoveList(thisEntity, oldCube, newCube);
|
||||
|
||||
// check to see if this entity is no longer moving
|
||||
EntityItem::SimulationState newState = thisEntity->getSimulationState();
|
||||
if (newState == EntityItem::Changing) {
|
||||
entitiesBecomingChanging << thisEntity;
|
||||
} else if (newState == EntityItem::Mortal) {
|
||||
entitiesBecomingMortal << thisEntity;
|
||||
} else if (newState == EntityItem::Static) {
|
||||
entitiesBecomingStatic << thisEntity;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
recurseTreeWithOperator(&moveOperator);
|
||||
if (moveOperator.hasMovingEntities()) {
|
||||
recurseTreeWithOperator(&moveOperator);
|
||||
}
|
||||
|
||||
// change state for any entities that were moving but are now either static, mortal, or changing
|
||||
foreach(EntityItem* entity, entitiesBecomingStatic) {
|
||||
changeEntityState(entity, EntityItem::Moving, EntityItem::Static);
|
||||
}
|
||||
foreach(EntityItem* entity, entitiesBecomingMortal) {
|
||||
changeEntityState(entity, EntityItem::Moving, EntityItem::Mortal);
|
||||
}
|
||||
foreach(EntityItem* entity, entitiesBecomingChanging) {
|
||||
changeEntityState(entity, EntityItem::Moving, EntityItem::Changing);
|
||||
// change state for any entities that were moving but are now either static, mortal, or changing
|
||||
foreach(EntityItem* entity, entitiesBecomingStatic) {
|
||||
changeEntityState(entity, EntityItem::Moving, EntityItem::Static);
|
||||
}
|
||||
foreach(EntityItem* entity, entitiesBecomingMortal) {
|
||||
changeEntityState(entity, EntityItem::Moving, EntityItem::Mortal);
|
||||
}
|
||||
foreach(EntityItem* entity, entitiesBecomingChanging) {
|
||||
changeEntityState(entity, EntityItem::Moving, EntityItem::Changing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1196,6 +1213,7 @@ public:
|
|||
|
||||
bool DebugOperator::PreRecursion(OctreeElement* element) {
|
||||
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
|
||||
qDebug() << "EntityTreeElement [" << entityTreeElement << "]";
|
||||
entityTreeElement->debugDump();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -54,8 +54,6 @@ EntityTreeElement* EntityTreeElement::addChildAtIndex(int index) {
|
|||
OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData* packetData,
|
||||
EncodeBitstreamParams& params) const {
|
||||
|
||||
|
||||
|
||||
bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
qDebug() << "EntityTreeElement::appendElementData()";
|
||||
|
@ -600,17 +598,8 @@ bool EntityTreeElement::removeEntityWithEntityItemID(const EntityItemID& id) {
|
|||
return foundEntity;
|
||||
}
|
||||
|
||||
bool EntityTreeElement::removeEntityItem(const EntityItem* entity) {
|
||||
bool foundEntity = false;
|
||||
uint16_t numberOfEntities = _entityItems->size();
|
||||
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
||||
if ((*_entityItems)[i] == entity) {
|
||||
foundEntity = true;
|
||||
_entityItems->removeAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return foundEntity;
|
||||
bool EntityTreeElement::removeEntityItem(EntityItem* entity) {
|
||||
return _entityItems->removeAll(entity) > 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -666,7 +655,9 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int
|
|||
EntityItem::SimulationState oldState = entityItem->getSimulationState();
|
||||
bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args);
|
||||
EntityItem::SimulationState newState = entityItem->getSimulationState();
|
||||
_myTree->changeEntityState(entityItem, oldState, newState);
|
||||
if (oldState != newState) {
|
||||
_myTree->changeEntityState(entityItem, oldState, newState);
|
||||
}
|
||||
bool bestFitAfter = bestFitEntityBounds(entityItem);
|
||||
|
||||
if (bestFitBefore != bestFitAfter) {
|
||||
|
@ -675,19 +666,20 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int
|
|||
// This is the case where the entity existed, and is in some element in our tree...
|
||||
if (currentContainingElement != this) {
|
||||
currentContainingElement->removeEntityItem(entityItem);
|
||||
this->addEntityItem(entityItem);
|
||||
addEntityItem(entityItem);
|
||||
_myTree->setContainingElement(entityItemID, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
entityItem = EntityTypes::constructEntityItem(dataAt, bytesLeftToRead, args);
|
||||
|
||||
if (entityItem) {
|
||||
bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args);
|
||||
addEntityItem(entityItem); // add this new entity to this elements entities
|
||||
_myTree->setContainingElement(entityItem->getEntityItemID(), this);
|
||||
_myTree->setContainingElement(entityItemID, this);
|
||||
newEntity = true;
|
||||
EntityItem::SimulationState newState = entityItem->getSimulationState();
|
||||
_myTree->changeEntityState(entityItem, EntityItem::Static, newState);
|
||||
}
|
||||
}
|
||||
// Move the buffer forward to read more entities
|
||||
|
|
|
@ -143,7 +143,7 @@ public:
|
|||
|
||||
void cleanupEntities(); /// called by EntityTree on cleanup this will free all entities
|
||||
bool removeEntityWithEntityItemID(const EntityItemID& id);
|
||||
bool removeEntityItem(const EntityItem* entity);
|
||||
bool removeEntityItem(EntityItem* entity);
|
||||
|
||||
bool containsEntityBounds(const EntityItem* entity) const;
|
||||
bool bestFitEntityBounds(const EntityItem* entity) const;
|
||||
|
|
|
@ -22,8 +22,31 @@ MovingEntitiesOperator::MovingEntitiesOperator(EntityTree* tree) :
|
|||
_foundNewCount(0),
|
||||
_lookingCount(0)
|
||||
{
|
||||
bool wantDebug = false;
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "MovingEntitiesOperator..... *********** start here!";
|
||||
qDebug() << " tree=" << tree;
|
||||
qDebug() << " _tree=" << _tree;
|
||||
|
||||
qDebug() << "------------ MovingEntitiesOperator -- BEFORE WE BEGIN: the tree[" << _tree << "] -------------";
|
||||
_tree->dumpTree();
|
||||
qDebug() << "------------ MovingEntitiesOperator -- END the tree-------------";
|
||||
}
|
||||
}
|
||||
|
||||
MovingEntitiesOperator::~MovingEntitiesOperator() {
|
||||
bool wantDebug = false;
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "~MovingEntitiesOperator().... ";
|
||||
qDebug() << "------------ ~MovingEntitiesOperator -- AFTER WE'RE DONE: the tree[" << _tree << "] -------------";
|
||||
_tree->dumpTree();
|
||||
qDebug() << "------------ ~MovingEntitiesOperator -- END the tree-------------";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MovingEntitiesOperator::addEntityToMoveList(EntityItem* entity, const AACube& oldCube, const AACube& newCube) {
|
||||
// check our tree, to determine if this entity is known
|
||||
EntityToMoveDetails details;
|
||||
|
@ -33,6 +56,7 @@ void MovingEntitiesOperator::addEntityToMoveList(EntityItem* entity, const AACub
|
|||
details.newFound = false;
|
||||
details.oldCube = oldCube;
|
||||
details.newCube = newCube;
|
||||
details.newBox = newCube.clamp(0.0f, 1.0f);
|
||||
_entitiesToMove << details;
|
||||
_lookingCount++;
|
||||
}
|
||||
|
@ -56,6 +80,32 @@ bool MovingEntitiesOperator::shouldRecurseSubTree(OctreeElement* element) {
|
|||
}
|
||||
|
||||
bool MovingEntitiesOperator::PreRecursion(OctreeElement* element) {
|
||||
bool wantDebug = false;
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "MovingEntitiesOperator::PreRecursion().... ";
|
||||
qDebug() << " element=" << element;
|
||||
qDebug() << " element.AACube=" << element->getAACube();
|
||||
qDebug() << " _lookingCount=" << _lookingCount;
|
||||
qDebug() << " _foundNewCount=" << _foundNewCount;
|
||||
qDebug() << " _foundOldCount=" << _foundOldCount;
|
||||
|
||||
qDebug() << " --------- list of moving entities -----------";
|
||||
foreach(const EntityToMoveDetails& details, _entitiesToMove) {
|
||||
|
||||
qDebug() << " MOVING ENTITY";
|
||||
qDebug() << " entity=" << details.entity;
|
||||
qDebug() << " entityItemID=" << details.entity->getEntityItemID();
|
||||
qDebug() << " oldCube=" << details.oldCube;
|
||||
qDebug() << " newCube=" << details.newCube;
|
||||
qDebug() << " newBox=" << details.newBox;
|
||||
qDebug() << " oldContainingElement=" << details.oldContainingElement;
|
||||
qDebug() << " oldFound=" << details.oldFound;
|
||||
qDebug() << " newFound=" << details.newFound;
|
||||
}
|
||||
qDebug() << " --------- list of moving entities -----------";
|
||||
}
|
||||
|
||||
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
|
||||
|
||||
// In Pre-recursion, we're generally deciding whether or not we want to recurse this
|
||||
|
@ -68,34 +118,97 @@ bool MovingEntitiesOperator::PreRecursion(OctreeElement* element) {
|
|||
// and the new entity.
|
||||
|
||||
bool keepSearching = (_foundOldCount < _lookingCount) || (_foundNewCount < _lookingCount);
|
||||
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << " keepSearching=" << keepSearching;
|
||||
qDebug() << " shouldRecurseSubTree(element)=" << shouldRecurseSubTree(element);
|
||||
}
|
||||
|
||||
// If we haven't yet found all the entities, and this sub tree contains at least one of our
|
||||
// entities, then we need to keep searching.
|
||||
if (keepSearching && shouldRecurseSubTree(element)) {
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << " PROCESSING MOVE ON THIS ELEMENT";
|
||||
}
|
||||
|
||||
// check against each of our search entities
|
||||
|
||||
qDebug() << " --------- PROCESSING list of moving entities -----------";
|
||||
foreach(const EntityToMoveDetails& details, _entitiesToMove) {
|
||||
|
||||
qDebug() << " PROCESSING --- MOVING ENTITY";
|
||||
qDebug() << " entity=" << details.entity;
|
||||
qDebug() << " entityItemID=" << details.entity->getEntityItemID();
|
||||
qDebug() << " oldCube=" << details.oldCube;
|
||||
qDebug() << " newCube=" << details.newCube;
|
||||
qDebug() << " newBox=" << details.newBox;
|
||||
qDebug() << " oldContainingElement=" << details.oldContainingElement;
|
||||
qDebug() << " oldFound=" << details.oldFound;
|
||||
qDebug() << " newFound=" << details.newFound;
|
||||
|
||||
if (!details.oldFound) {
|
||||
qDebug() << " THIS ENTITY'S OLD LOCATION HAS NOT BEEN FOUND... ";
|
||||
}
|
||||
|
||||
if (entityTreeElement == details.oldContainingElement) {
|
||||
qDebug() << " THIS ELEMENT IS THE ENTITY'S OLD LOCATION... ";
|
||||
}
|
||||
|
||||
// If this is one of the old elements we're looking for, then ask it to remove the old entity
|
||||
if (!details.oldFound && entityTreeElement == details.oldContainingElement) {
|
||||
EntityItemID entityItemID = details.entity->getEntityItemID();
|
||||
entityTreeElement->removeEntityWithEntityItemID(entityItemID);
|
||||
|
||||
//qDebug() << "removing entityItem from element... entityItemID=" << entityItemID << "entityTreeElement=" << entityTreeElement;
|
||||
qDebug() << " PROCESSING REMOVE ENTITY FROM OLD ELEMENT <<<<<<<<<<<<<";
|
||||
|
||||
entityTreeElement->removeEntityItem(details.entity);
|
||||
qDebug() << "removing entityItem from element... ";
|
||||
qDebug() << " entity=" << details.entity;
|
||||
qDebug() << " entityItemID=" << details.entity->getEntityItemID();
|
||||
qDebug() << " entityTreeElement=" << entityTreeElement;
|
||||
qDebug() << " element=" << element;
|
||||
qDebug() << " element->getAACube()=" << element->getAACube();
|
||||
|
||||
_foundOldCount++;
|
||||
//details.oldFound = true; // TODO: would be nice to add this optimization
|
||||
}
|
||||
|
||||
// If this element is the best fit for the new bounds of this entity then add the entity to the element
|
||||
bool bestFitCube = entityTreeElement->bestFitBounds(details.newCube);
|
||||
bool bestFitBox = entityTreeElement->bestFitBounds(details.newBox);
|
||||
qDebug() << " bestFitCube=" << bestFitCube;
|
||||
qDebug() << " bestFitBox=" << bestFitBox;
|
||||
if (bestFitCube != bestFitBox) {
|
||||
qDebug() << " WHOA!!!! bestFitCube != bestFitBox!!!!";
|
||||
}
|
||||
|
||||
if (!details.newFound) {
|
||||
qDebug() << " THIS ENTITY'S NEW LOCATION HAS NOT BEEN FOUND... ";
|
||||
}
|
||||
|
||||
if (entityTreeElement->bestFitBounds(details.newCube)) {
|
||||
qDebug() << " THIS ELEMENT IS THE ENTITY'S BEST FIT NEW LOCATION... ";
|
||||
}
|
||||
|
||||
if (!details.newFound && entityTreeElement->bestFitBounds(details.newCube)) {
|
||||
|
||||
qDebug() << " PROCESSING ADD ENTITY TO NEW ELEMENT <<<<<<<<<<<<<";
|
||||
|
||||
|
||||
EntityItemID entityItemID = details.entity->getEntityItemID();
|
||||
qDebug() << "adding entityItem to element...";
|
||||
qDebug() << " entity=" << details.entity;
|
||||
qDebug() << " entityItemID=" << entityItemID;
|
||||
qDebug() << " entityTreeElement=" << entityTreeElement;
|
||||
qDebug() << " element=" << element;
|
||||
qDebug() << " element->getAACube()=" << element->getAACube();
|
||||
entityTreeElement->addEntityItem(details.entity);
|
||||
_tree->setContainingElement(entityItemID, entityTreeElement);
|
||||
//qDebug() << "adding entityItem to element... entityItemID=" << entityItemID << "entityTreeElement=" << entityTreeElement;
|
||||
|
||||
_foundNewCount++;
|
||||
//details.newFound = true; // TODO: would be nice to add this optimization
|
||||
}
|
||||
}
|
||||
qDebug() << " --------- DONE PROCESSING list of moving entities -----------";
|
||||
|
||||
// if we haven't found all of our search for entities, then keep looking
|
||||
keepSearching = (_foundOldCount < _lookingCount) || (_foundNewCount < _lookingCount);
|
||||
|
@ -105,6 +218,33 @@ bool MovingEntitiesOperator::PreRecursion(OctreeElement* element) {
|
|||
}
|
||||
|
||||
bool MovingEntitiesOperator::PostRecursion(OctreeElement* element) {
|
||||
bool wantDebug = false;
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "MovingEntitiesOperator::PostRecursion().... ";
|
||||
qDebug() << " element=" << element;
|
||||
qDebug() << " element.AACube=" << element->getAACube();
|
||||
qDebug() << " _lookingCount=" << _lookingCount;
|
||||
qDebug() << " _foundNewCount=" << _foundNewCount;
|
||||
qDebug() << " _foundOldCount=" << _foundOldCount;
|
||||
|
||||
qDebug() << " --------- list of moving entities -----------";
|
||||
foreach(const EntityToMoveDetails& details, _entitiesToMove) {
|
||||
|
||||
qDebug() << " MOVING ENTITY";
|
||||
qDebug() << " entity=" << details.entity;
|
||||
qDebug() << " entityItemID=" << details.entity->getEntityItemID();
|
||||
qDebug() << " oldCube=" << details.oldCube;
|
||||
qDebug() << " newCube=" << details.newCube;
|
||||
qDebug() << " newBox=" << details.newBox;
|
||||
qDebug() << " oldContainingElement=" << details.oldContainingElement;
|
||||
qDebug() << " oldFound=" << details.oldFound;
|
||||
qDebug() << " newFound=" << details.newFound;
|
||||
}
|
||||
qDebug() << " --------- list of moving entities -----------";
|
||||
|
||||
}
|
||||
|
||||
// Post-recursion is the unwinding process. For this operation, while we
|
||||
// unwind we want to mark the path as being dirty if we changed it below.
|
||||
// We might have two paths, one for the old entity and one for the new entity.
|
||||
|
@ -118,7 +258,6 @@ bool MovingEntitiesOperator::PostRecursion(OctreeElement* element) {
|
|||
|
||||
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
|
||||
bool somethingPruned = entityTreeElement->pruneChildren(); // take this opportunity to prune any empty leaves
|
||||
bool wantDebug = false;
|
||||
if (somethingPruned && wantDebug) {
|
||||
qDebug() << "MovingEntitiesOperator::PostRecursion() something pruned!!!";
|
||||
}
|
||||
|
@ -131,8 +270,27 @@ OctreeElement* MovingEntitiesOperator::PossiblyCreateChildAt(OctreeElement* elem
|
|||
|
||||
if (wantDebug) {
|
||||
qDebug() << "MovingEntitiesOperator::PossiblyCreateChildAt().... ";
|
||||
qDebug() << " _foundNewCount=" << _foundNewCount;
|
||||
qDebug() << " element=" << element;
|
||||
qDebug() << " element.AACube=" << element->getAACube();
|
||||
qDebug() << " childIndex=" << childIndex;
|
||||
qDebug() << " _lookingCount=" << _lookingCount;
|
||||
qDebug() << " _foundNewCount=" << _foundNewCount;
|
||||
qDebug() << " _foundOldCount=" << _foundOldCount;
|
||||
|
||||
qDebug() << " --------- list of moving entities -----------";
|
||||
foreach(const EntityToMoveDetails& details, _entitiesToMove) {
|
||||
|
||||
qDebug() << " MOVING ENTITY";
|
||||
qDebug() << " entity=" << details.entity;
|
||||
qDebug() << " entityItemID=" << details.entity->getEntityItemID();
|
||||
qDebug() << " oldCube=" << details.oldCube;
|
||||
qDebug() << " newCube=" << details.newCube;
|
||||
qDebug() << " newBox=" << details.newBox;
|
||||
qDebug() << " oldContainingElement=" << details.oldContainingElement;
|
||||
qDebug() << " oldFound=" << details.oldFound;
|
||||
qDebug() << " newFound=" << details.newFound;
|
||||
}
|
||||
qDebug() << " --------- list of moving entities -----------";
|
||||
}
|
||||
|
||||
// If we're getting called, it's because there was no child element at this index while recursing.
|
||||
|
@ -145,25 +303,37 @@ OctreeElement* MovingEntitiesOperator::PossiblyCreateChildAt(OctreeElement* elem
|
|||
foreach(const EntityToMoveDetails& details, _entitiesToMove) {
|
||||
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
|
||||
|
||||
bool thisElementIsBestFit = entityTreeElement->bestFitBounds(details.newCube);
|
||||
if (wantDebug) {
|
||||
qDebug() << " thisElementIsBestFit=" << thisElementIsBestFit;
|
||||
bool thisElementIsBestFitCube = entityTreeElement->bestFitBounds(details.newCube);
|
||||
bool thisElementIsBestFitBox = entityTreeElement->bestFitBounds(details.newBox);
|
||||
qDebug() << " thisElementIsBestFitCube=" << thisElementIsBestFitCube;
|
||||
qDebug() << " thisElementIsBestFitBox=" << thisElementIsBestFitBox;
|
||||
qDebug() << " details.newCube=" << details.newCube;
|
||||
qDebug() << " details.newBox=" << details.newBox;
|
||||
qDebug() << " element=" << element;
|
||||
qDebug() << " element->getAACube()=" << element->getAACube();
|
||||
}
|
||||
|
||||
// if the scale of our desired cube is smaller than our children, then consider making a child
|
||||
if (details.newCube.getScale() <= childElementScale) {
|
||||
//qDebug() << " calling element->getMyChildContaining(details.newCube); ---------";
|
||||
int indexOfChildContainingNewEntity = element->getMyChildContaining(details.newCube);
|
||||
//qDebug() << " called element->getMyChildContaining(details.newCube); ---------";
|
||||
if (details.newBox.getLargestDimension() <= childElementScale) {
|
||||
|
||||
int indexOfChildContainingNewEntity = element->getMyChildContaining(details.newBox);
|
||||
if (wantDebug) {
|
||||
qDebug() << " called element->getMyChildContaining(details.newBox); ---------";
|
||||
qDebug() << " childIndex=" << childIndex;
|
||||
qDebug() << " indexOfChildContainingNewEntity=" << indexOfChildContainingNewEntity;
|
||||
}
|
||||
|
||||
// If the childIndex we were asked if we wanted to create contains this newCube,
|
||||
// then we will create this branch and continue. We can exit this loop immediately
|
||||
// because if we need this branch for any one entity then it doesn't matter if it's
|
||||
// needed for more entities.
|
||||
if (childIndex == indexOfChildContainingNewEntity) {
|
||||
return element->addChildAtIndex(childIndex);
|
||||
OctreeElement* newChild = element->addChildAtIndex(childIndex);
|
||||
if (wantDebug) {
|
||||
qDebug() << " CREATING NEW CHILD --- childIndex=" << childIndex << "newChild=" << newChild;
|
||||
}
|
||||
return newChild;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ public:
|
|||
EntityItem* entity;
|
||||
AACube oldCube;
|
||||
AACube newCube;
|
||||
AABox newBox;
|
||||
EntityTreeElement* oldContainingElement;
|
||||
bool oldFound;
|
||||
bool newFound;
|
||||
|
@ -33,10 +34,13 @@ inline bool operator==(const EntityToMoveDetails& a, const EntityToMoveDetails&
|
|||
class MovingEntitiesOperator : public RecurseOctreeOperator {
|
||||
public:
|
||||
MovingEntitiesOperator(EntityTree* tree);
|
||||
~MovingEntitiesOperator();
|
||||
|
||||
void addEntityToMoveList(EntityItem* entity, const AACube& oldCube, const AACube& newCube);
|
||||
virtual bool PreRecursion(OctreeElement* element);
|
||||
virtual bool PostRecursion(OctreeElement* element);
|
||||
virtual OctreeElement* PossiblyCreateChildAt(OctreeElement* element, int childIndex);
|
||||
bool hasMovingEntities() const { return _entitiesToMove.size() > 0; }
|
||||
private:
|
||||
EntityTree* _tree;
|
||||
QSet<EntityToMoveDetails> _entitiesToMove;
|
||||
|
|
|
@ -28,6 +28,7 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree,
|
|||
_foundOld(false),
|
||||
_foundNew(false),
|
||||
_removeOld(false),
|
||||
_dontMove(false), // assume we'll be moving
|
||||
_changeTime(usecTimestampNow()),
|
||||
_oldEntityCube(),
|
||||
_newEntityCube()
|
||||
|
@ -42,6 +43,10 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree,
|
|||
|
||||
if (wantDebug) {
|
||||
qDebug() << "UpdateEntityOperator....";
|
||||
qDebug() << " _existingEntity=" << _existingEntity;
|
||||
qDebug() << " _entityItemID=" << _entityItemID;
|
||||
qDebug() << " _containingElement=" << _containingElement;
|
||||
qDebug() << " _containingElement->getAACube()=" << _containingElement->getAACube();
|
||||
qDebug() << " _oldEntityCube=" << _oldEntityCube;
|
||||
qDebug() << " _oldEntityBox=" << _oldEntityBox;
|
||||
qDebug() << " _existingEntity->getPosition()=" << _existingEntity->getPosition() * (float)TREE_SCALE << "in meters";
|
||||
|
@ -64,16 +69,30 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree,
|
|||
// If our new properties don't have bounds details (no change to position, etc) or if this containing element would
|
||||
// be the best fit for our new properties, then just do the new portion of the store pass, since the change path will
|
||||
// be the same for both parts of the update
|
||||
|
||||
bool oldElementBestFit = _containingElement->bestFitBounds(_properties);
|
||||
|
||||
|
||||
// if we don't have bounds properties, then use our old clamped box to determine best fit
|
||||
if (!_properties.containsBoundsProperties()) {
|
||||
oldElementBestFit = _containingElement->bestFitBounds(_oldEntityBox);
|
||||
}
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << " _properties.containsBoundsProperties()=" << _properties.containsBoundsProperties();
|
||||
qDebug() << " oldElementBestFit=" << oldElementBestFit;
|
||||
}
|
||||
|
||||
if (!_properties.containsBoundsProperties() || oldElementBestFit) {
|
||||
// For some reason we've seen a case where the original containing element isn't a best fit for the old properties
|
||||
// in this case we want to move it, even if the properties haven't changed.
|
||||
if (!_properties.containsBoundsProperties() && !oldElementBestFit) {
|
||||
_newEntityCube = _oldEntityCube;
|
||||
_removeOld = true; // our properties are going to move us, so remember this for later processing
|
||||
if (wantDebug) {
|
||||
qDebug() << " old element is NOT the best element even though props not changing <<<<<";
|
||||
}
|
||||
} else if (!_properties.containsBoundsProperties() || oldElementBestFit) {
|
||||
_foundOld = true;
|
||||
_newEntityCube = _oldEntityCube;
|
||||
_dontMove = true;
|
||||
if (wantDebug) {
|
||||
qDebug() << " old element is best element <<<<<";
|
||||
}
|
||||
|
@ -94,12 +113,37 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree,
|
|||
qDebug() << " _newEntityCube=" << _newEntityCube;
|
||||
qDebug() << " _newEntityBox=" << _newEntityBox;
|
||||
qDebug() << " _removeOld=" << _removeOld;
|
||||
qDebug() << " _containingElement->bestFitBounds(_properties)=" << _containingElement->bestFitBounds(_properties);
|
||||
qDebug() << " _containingElement->bestFitBounds(_oldEntityCube)=" << _containingElement->bestFitBounds(_oldEntityCube);
|
||||
qDebug() << " _containingElement->bestFitBounds(_oldEntityBox)=" << _containingElement->bestFitBounds(_oldEntityBox);
|
||||
qDebug() << " _containingElement->bestFitBounds(_newEntityCube)=" << _containingElement->bestFitBounds(_newEntityCube);
|
||||
qDebug() << " _containingElement->bestFitBounds(_newEntityBox)=" << _containingElement->bestFitBounds(_newEntityBox);
|
||||
|
||||
qDebug() << "------------ UpdateEntityOperator -- BEFORE WE BEGIN: the tree[" << _tree << "] -------------";
|
||||
_tree->dumpTree();
|
||||
qDebug() << "------------ UpdateEntityOperator -- END the tree-------------";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UpdateEntityOperator::~UpdateEntityOperator() {
|
||||
bool wantDebug = false;
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "~UpdateEntityOperator().... ";
|
||||
qDebug() << "------------ ~UpdateEntityOperator -- AFTER WE'RE DONE: the tree[" << _tree << "] -------------";
|
||||
_tree->dumpTree();
|
||||
qDebug() << "------------ ~UpdateEntityOperator -- END the tree-------------";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// does this entity tree element contain the old entity
|
||||
bool UpdateEntityOperator::subTreeContainsOldEntity(OctreeElement* element) {
|
||||
bool elementContainsOldBox = element->getAACube().contains(_oldEntityBox);
|
||||
|
||||
// We've found cases where the old entity might be placed in an element that is not actually the best fit
|
||||
// so when we're searching the tree for the old element, we use the known cube for the known containing element
|
||||
bool elementContainsOldBox = element->getAACube().contains(_containingElementCube);
|
||||
|
||||
/*
|
||||
bool elementContainsOldCube = element->getAACube().contains(_oldEntityCube);
|
||||
|
@ -177,6 +221,11 @@ bool UpdateEntityOperator::PreRecursion(OctreeElement* element) {
|
|||
|
||||
if (wantDebug) {
|
||||
qDebug() << " OLD BRANCH....";
|
||||
qDebug() << " _dontMove=" << _dontMove;
|
||||
qDebug() << " _removeOld=" << _removeOld;
|
||||
qDebug() << " entityTreeElement == _containingElement=" << (entityTreeElement == _containingElement);
|
||||
qDebug() << " entityTreeElement->bestFitBounds(_newEntityBox)=" << entityTreeElement->bestFitBounds(_newEntityBox);
|
||||
qDebug() << " _containingElement->bestFitBounds(_newEntityBox)=" << _containingElement->bestFitBounds(_newEntityBox);
|
||||
}
|
||||
|
||||
|
||||
|
@ -223,6 +272,11 @@ bool UpdateEntityOperator::PreRecursion(OctreeElement* element) {
|
|||
|
||||
if (wantDebug) {
|
||||
qDebug() << " NEW BRANCH....";
|
||||
qDebug() << " _dontMove=" << _dontMove;
|
||||
qDebug() << " _removeOld=" << _removeOld;
|
||||
qDebug() << " entityTreeElement == _containingElement=" << (entityTreeElement == _containingElement);
|
||||
qDebug() << " entityTreeElement->bestFitBounds(_newEntityBox)=" << entityTreeElement->bestFitBounds(_newEntityBox);
|
||||
qDebug() << " _containingElement->bestFitBounds(_newEntityBox)=" << _containingElement->bestFitBounds(_newEntityBox);
|
||||
}
|
||||
|
||||
|
||||
|
@ -231,9 +285,13 @@ bool UpdateEntityOperator::PreRecursion(OctreeElement* element) {
|
|||
|
||||
if (wantDebug) {
|
||||
qDebug() << " NEW BRANCH.... BEST FIT";
|
||||
qDebug() << " _dontMove=" << _dontMove;
|
||||
qDebug() << " _removeOld=" << _removeOld;
|
||||
qDebug() << " entityTreeElement == _containingElement=" << (entityTreeElement == _containingElement);
|
||||
}
|
||||
|
||||
// if we are the existing containing element, then we can just do the update of the entity properties
|
||||
|
||||
if (entityTreeElement == _containingElement) {
|
||||
assert(!_removeOld); // We shouldn't be in a remove old case and also be the new best fit
|
||||
|
||||
|
@ -246,6 +304,15 @@ bool UpdateEntityOperator::PreRecursion(OctreeElement* element) {
|
|||
|
||||
} else {
|
||||
// otherwise, this is an add case.
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "UpdateEntityOperator()... UPDATING EXISTING ENTITY -- PLACE IN NEW ELEMENT";
|
||||
qDebug() << " element=" << entityTreeElement;
|
||||
qDebug() << " element cube=" << entityTreeElement->getAACube();
|
||||
qDebug() << " existingEntity=" << _existingEntity;
|
||||
qDebug() << " entityItemID=" << _entityItemID;
|
||||
}
|
||||
|
||||
entityTreeElement->addEntityItem(_existingEntity);
|
||||
_existingEntity->setProperties(_properties); // still need to update the properties!
|
||||
_tree->setContainingElement(_entityItemID, entityTreeElement);
|
||||
|
@ -324,37 +391,38 @@ bool UpdateEntityOperator::PostRecursion(OctreeElement* element) {
|
|||
}
|
||||
|
||||
OctreeElement* UpdateEntityOperator::PossiblyCreateChildAt(OctreeElement* element, int childIndex) {
|
||||
|
||||
bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
qDebug() << "UpdateEntityOperator::PossiblyCreateChildAt()...";
|
||||
qDebug() << " element=" << element;
|
||||
qDebug() << " element->getAACube()=" << element->getAACube();
|
||||
qDebug() << " childIndex=" << childIndex;
|
||||
|
||||
bool subtreeContainsOld = subTreeContainsOldEntity(element);
|
||||
bool subtreeContainsNew = subTreeContainsNewEntity(element);
|
||||
|
||||
qDebug() << " subtreeContainsOld=" << subtreeContainsOld;
|
||||
qDebug() << " subtreeContainsNew=" << subtreeContainsNew;
|
||||
|
||||
qDebug() << " _foundOld=" << _foundOld;
|
||||
qDebug() << " _foundNew=" << _foundNew;
|
||||
qDebug() << " _removeOld=" << _removeOld;
|
||||
|
||||
qDebug() << " _containingElement=" << _containingElement;
|
||||
qDebug() << " _containingElementCube=" << _containingElementCube;
|
||||
|
||||
qDebug() << " _properties.getPosition()=" << _properties.getPosition() << "in meters";
|
||||
qDebug() << " _properties.getRadius()=" << _properties.getRadius() << "in meters";
|
||||
qDebug() << " _newEntityCube=" << _newEntityCube;
|
||||
qDebug() << " _newEntityBox=" << _newEntityBox;
|
||||
}
|
||||
|
||||
// If we're getting called, it's because there was no child element at this index while recursing.
|
||||
// We only care if this happens while still searching for the new entity location.
|
||||
// Check to see if
|
||||
if (!_foundNew) {
|
||||
|
||||
bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
qDebug() << "UpdateEntityOperator::PossiblyCreateChildAt()...";
|
||||
qDebug() << " element=" << element;
|
||||
qDebug() << " element->getAACube()=" << element->getAACube();
|
||||
qDebug() << " childIndex=" << childIndex;
|
||||
|
||||
bool subtreeContainsOld = subTreeContainsOldEntity(element);
|
||||
bool subtreeContainsNew = subTreeContainsNewEntity(element);
|
||||
|
||||
qDebug() << " subtreeContainsOld=" << subtreeContainsOld;
|
||||
qDebug() << " subtreeContainsNew=" << subtreeContainsNew;
|
||||
|
||||
qDebug() << " _foundOld=" << _foundOld;
|
||||
qDebug() << " _foundNew=" << _foundNew;
|
||||
qDebug() << " _removeOld=" << _removeOld;
|
||||
|
||||
qDebug() << " _containingElement=" << _containingElement;
|
||||
qDebug() << " _containingElementCube=" << _containingElementCube;
|
||||
|
||||
qDebug() << " _properties.getPosition()=" << _properties.getPosition() << "in meters";
|
||||
qDebug() << " _properties.getRadius()=" << _properties.getRadius() << "in meters";
|
||||
qDebug() << " _newEntityCube=" << _newEntityCube;
|
||||
qDebug() << " _newEntityBox=" << _newEntityBox;
|
||||
}
|
||||
|
||||
|
||||
float childElementScale = element->getScale() / 2.0f; // all of our children will be half our scale
|
||||
|
||||
// Note: because the entity's bounds might have been clamped to the domain. We want to check if the
|
||||
|
|
|
@ -16,6 +16,7 @@ class UpdateEntityOperator : public RecurseOctreeOperator {
|
|||
public:
|
||||
UpdateEntityOperator(EntityTree* tree, EntityTreeElement* containingElement,
|
||||
EntityItem* existingEntity, const EntityItemProperties& properties);
|
||||
~UpdateEntityOperator();
|
||||
|
||||
virtual bool PreRecursion(OctreeElement* element);
|
||||
virtual bool PostRecursion(OctreeElement* element);
|
||||
|
@ -30,6 +31,7 @@ private:
|
|||
bool _foundOld;
|
||||
bool _foundNew;
|
||||
bool _removeOld;
|
||||
bool _dontMove;
|
||||
quint64 _changeTime;
|
||||
|
||||
AACube _oldEntityCube;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
// REQUIRED:
|
||||
|
||||
1) crash on rendering of element that flies off the domain???
|
||||
|
||||
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.
|
||||
|
||||
|
@ -9,15 +7,12 @@
|
|||
|
||||
4) test animation again...
|
||||
|
||||
5) PROP_VISIBLE
|
||||
|
||||
6) PROP_SCRIPT
|
||||
|
||||
7) some jutter with moving entities
|
||||
-- I think this might only happen with lots of models in an element or in view
|
||||
this may be related to issue 13 below
|
||||
|
||||
8) Look into why non-changed octree cells are being resent when editing an entity
|
||||
8) 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
|
||||
|
||||
9) Verify pruning logic...
|
||||
The old code used the update loop to handle pruning elements from the tree - do we need this?
|
||||
|
@ -27,11 +22,23 @@
|
|||
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"
|
||||
|
||||
12) Double check operators for these problems:
|
||||
MovingEntitiesOperator has these issues:
|
||||
- does the same pruning/reallocating issue as the old UpdateEntityOperator
|
||||
- doesn't used clamped boxes for best fit tests... so could be problematic
|
||||
|
||||
// NICE TO HAVE:
|
||||
|
||||
|
||||
why is _entityItems a pointer? why not just make it a member of EntityTreeElement....
|
||||
|
||||
1) EnterEntity/LeaveEntity JS messages
|
||||
|
||||
2) PROP_VISIBLE
|
||||
|
||||
3) PROP_SCRIPT
|
||||
|
||||
|
||||
2) update and verify all particle examples to use new entity features
|
||||
|
||||
3) implement support for requestedProperties in appendEntityData() that only include CHANGED properties for the viewer...
|
||||
|
@ -200,6 +207,13 @@
|
|||
// -- 3) the containing element got pruned
|
||||
// -- 4) the NEW branch is traversed and PossiblyCreateChildAt creates a new element -- THAT HAS SAME POINTER AS CONTAINING ELEMENT!!!!
|
||||
// -- 5) the logic for recursedelement == _containingElement gets confused
|
||||
// SOLVED -- 47) crash on rendering of element that flies off the domain
|
||||
// -- root cause was an UpdateEntityOperator that left two copies of the entity in the tree
|
||||
// this was caused by the original element that the entity was in (according to the server)
|
||||
// was not actually the best fit. it's not clear how this happened, but we can protect
|
||||
// against it in the update operator if it does happen again. This made update operator more robust.
|
||||
// SOLVED -- 48) server and client definitley not adding entities to proper update lists on load... only on change...
|
||||
|
||||
|
||||
---------------- properties -----------------
|
||||
Base properties...
|
||||
|
|
Loading…
Reference in a new issue