From 29e02f26819cec8c82103482602f48edfd3ff2d7 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 7 Jul 2014 09:36:31 -0700 Subject: [PATCH] more hacking on virtualizing entities --- libraries/entities/src/EntityItem.cpp | 18 ++++-- libraries/entities/src/EntityItem.h | 8 ++- libraries/entities/src/EntityTree.cpp | 44 +++++++++++---- libraries/entities/src/EntityTree.h | 9 ++- libraries/entities/src/EntityTreeElement.cpp | 59 +++++++++++++++++--- libraries/entities/src/EntityTreeElement.h | 1 + tests/octree/src/ModelTests.cpp | 2 +- tests/octree/src/OctreeTests.cpp | 2 +- 8 files changed, 112 insertions(+), 31 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 11c2375eca..75d0e9ec16 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -37,18 +37,21 @@ const QString& EntityTypes::getEntityTypeName(EntityType_t entityType) { return matchedTypeName != _typeNameHash.end() ? matchedTypeName.value() : UNKNOWN_EntityType_t_NAME; } -bool EntityTypes::registerEntityTypeName(EntityType_t entityType, const QString& name) { +bool EntityTypes::registerEntityType(EntityType_t entityType, const QString& name) { _typeNameHash.insert(entityType, name); return true; } EntityItem* EntityTypes::constructEntityItem(EntityType_t entityType, const EntityItemID& entityID, const EntityItemProperties& properties) { - return new EntityItem(entityID, properties); // for now, needs to support registration of constructor + return NULL; // new EntityItem(entityID, properties); // for now, needs to support registration of constructor } +EntityItem* EntityTypes::constructEntityItem(const unsigned char* data, int bytesToRead) { + return NULL; // TODO Implement this for real! +} -bool registered = EntityTypes::registerEntityTypeName(EntityTypes::Base, "Base") - && EntityTypes::registerEntityTypeName(EntityTypes::Model, "Model"); // TODO: move this to model subclass +bool registered = EntityTypes::registerEntityType(EntityTypes::Base, "Base") + && EntityTypes::registerEntityType(EntityTypes::Model, "Model"); // TODO: move this to model subclass uint32_t EntityItem::_nextID = 0; @@ -663,7 +666,8 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef encodedType = typeCoder; // determine true length dataAt += encodedType.size(); bytesRead += encodedType.size(); - _type = typeCoder; + quint32 type = typeCoder; + _type = (EntityTypes::EntityType_t)type; // _lastEdited memcpy(&_lastEdited, dataAt, sizeof(_lastEdited)); @@ -783,6 +787,8 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef EntityItem* EntityItem::fromEditPacket(const unsigned char* data, int length, int& processedBytes, EntityTree* tree, bool& valid) { EntityItem* result = NULL; +#if 0 + bool wantDebug = false; if (wantDebug) { qDebug() << "EntityItem EntityItem::fromEditPacket() length=" << length; @@ -967,6 +973,8 @@ EntityItem* EntityItem::fromEditPacket(const unsigned char* data, int length, in qDebug() << " EntityItem id in packet:" << editID; newEntityItem.debugDump(); } + +#endif // TODO: need to make this actually return something... return result; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 7a268e7754..e3363b9a85 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -70,12 +70,18 @@ public: typedef enum EntityType { Base, Model, - Particle + Particle, + Box, + Sphere, + Plane, + Cylinder } EntityType_t; static const QString& getEntityTypeName(EntityType_t entityType); static bool registerEntityType(EntityType_t entityType, const QString& name); + static EntityItem* constructEntityItem(EntityType_t entityType, const EntityItemID& entityID, const EntityItemProperties& properties); + static EntityItem* constructEntityItem(const unsigned char* data, int bytesToRead); private: static QHash _typeNameHash; }; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 8ac0647b1d..4de7548d18 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -249,8 +249,9 @@ public: virtual OctreeElement* PossiblyCreateChildAt(OctreeElement* element, int childIndex); private: EntityTree* _tree; - const EntityItem* _existingEntity; + EntityItem* _existingEntity; EntityTreeElement* _containingElement; + const EntityItemProperties& _properties; EntityItemID _entityItemID; bool _foundOld; bool _foundNew; @@ -271,11 +272,14 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree, _tree(tree), _existingEntity(existingEntity), _containingElement(containingElement), + _properties(properties), _entityItemID(existingEntity->getEntityItemID()), _foundOld(false), _foundNew(false), _removeOld(false), - _changeTime(usecTimestampNow()) + _changeTime(usecTimestampNow()), + _oldEntityCube(), + _newEntityCube() { // caller must have verified existence of containingElement and oldEntity assert(_containingElement && _existingEntity); @@ -353,8 +357,7 @@ bool UpdateEntityOperator::PreRecursion(OctreeElement* element) { // If this element is the best fit for the new entity properties, then add/or update it if (entityTreeElement->bestFitBounds(_newEntityCube)) { - - if (entityTreeElement->addOrUpdateEntity(_existingEntity, properties)) { + if (entityTreeElement->addOrUpdateEntity(_existingEntity, _properties)) { //qDebug() << "UpdateEntityOperator::PreRecursion()... model was updated!"; _foundNew = true; @@ -363,8 +366,6 @@ bool UpdateEntityOperator::PreRecursion(OctreeElement* element) { // means we're still searching for our old model and this branch // contains our old model. In which case we want to keep searching. } - } - } else { keepSearching = true; } @@ -393,7 +394,7 @@ OctreeElement* UpdateEntityOperator::PossiblyCreateChildAt(OctreeElement* elemen // We only care if this happens while still searching for the new model location. // Check to see if if (!_foundNew) { - int indexOfChildContainingNewEntity = element->getMyChildContaining(_newEntity.getAACube()); + int indexOfChildContainingNewEntity = element->getMyChildContaining(_newEntityCube); if (childIndex == indexOfChildContainingNewEntity) { return element->addChildAtIndex(childIndex); @@ -409,6 +410,8 @@ OctreeElement* UpdateEntityOperator::PossiblyCreateChildAt(OctreeElement* elemen // move to a different EntityTreeElement, otherwise it will not move. If the entity can not move, then the dirty path // can be determined to just be the path to the entity void EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties) { + +#if 0 EntityItem* updateItem = NULL; bool entityMightMove = properties.containsBoundsProperties(); @@ -455,11 +458,14 @@ void EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProp } storeEntity(updateItem); +#endif } void EntityTree::addEntity(const EntityItemID& entityID, const EntityItemProperties& properties) { +#if 0 EntityItem updateItem(entityID, properties); storeEntity(updateItem); +#endif } class EntityToDeleteDetails { @@ -825,7 +831,7 @@ void EntityTree::findEntities(const AACube& cube, QVector foundEnti foundEntitys.swap(args._foundEntitys); } -const EntityItem* EntityTree::findEntityByID(uint32_t id, bool alreadyLocked) const { +EntityItem* EntityTree::findEntityByID(uint32_t id, bool alreadyLocked) const { EntityItemID entityID(id); bool wantDebug = false; @@ -839,8 +845,8 @@ const EntityItem* EntityTree::findEntityByID(uint32_t id, bool alreadyLocked) co return findEntityByEntityItemID(entityID); } -const EntityItem* EntityTree::findEntityByEntityItemID(const EntityItemID& entityID) const { - const EntityItem* foundEntity = NULL; +EntityItem* EntityTree::findEntityByEntityItemID(const EntityItemID& entityID) const { + EntityItem* foundEntity = NULL; EntityTreeElement* containingElement = getContainingElement(entityID); if (containingElement) { foundEntity = containingElement->getEntityWithEntityItemID(entityID); @@ -856,14 +862,19 @@ int EntityTree::processEditPacketData(PacketType packetType, const unsigned char // we handle these types of "edit" packets switch (packetType) { case PacketTypeEntityAddOrEdit: { - bool isValid; - EntityItem newEntity = EntityItem::fromEditPacket(editData, maxLength, processedBytes, this, isValid); + // TODO: need to do this + +#if 0 + bool isValid = false; + EntityItem* newEntity = NULL; // EntityItem::fromEditPacket(editData, maxLength, processedBytes, this, isValid); if (isValid) { storeEntity(newEntity, senderNode); if (newEntity.isNewlyCreated()) { notifyNewlyCreatedEntity(newEntity, senderNode); } } +#endif + } break; default: @@ -1146,3 +1157,12 @@ void EntityTree::debugDumpMap() { qDebug() << i.key() << ": " << i.value(); } } + + +void EntityTree::rememberDirtyCube(const AACube& cube) { + // TODO: do something here +} + +void EntityTree::rememberEntityToMove(const EntityItem* entity) { + // TODO: do something here +} diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 43ce620f72..36f92d7e49 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -58,8 +58,8 @@ public: void deleteEntity(const EntityItemID& modelID); void deleteEntitys(QSet modelIDs); const EntityItem* findClosestEntity(glm::vec3 position, float targetRadius); - const EntityItem* findEntityByID(uint32_t id, bool alreadyLocked = false) const; - const EntityItem* findEntityByEntityItemID(const EntityItemID& modelID) const; + EntityItem* findEntityByID(uint32_t id, bool alreadyLocked = false) const; + EntityItem* findEntityByEntityItemID(const EntityItemID& modelID) const; /// finds all models that touch a sphere /// \param center the center of the sphere @@ -95,6 +95,11 @@ public: void setContainingElement(const EntityItemID& entityItemID, EntityTreeElement* element); void debugDumpMap(); + + void rememberDirtyCube(const AACube& cube); + void rememberEntityToMove(const EntityItem* entity); + + private: static bool updateOperation(OctreeElement* element, void* extraData); diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index f44609851c..5bb441dc8b 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -641,6 +641,15 @@ bool EntityTreeElement::removeEntityItem(const EntityItem* entity) { } +// Things we want to accomplish as we read these entities from the data buffer. +// +// 1) correctly update the properties of the entity +// 2) add any new entities that didn't previously exist +// 3) mark our tree as dirty down to the path of the previous location of the entity +// 4) mark our tree as dirty down to the path of the new location of the entity +// +// Since we're potentially reading several entities, we'd prefer to do all the moving around +// and dirty path marking in one pass. int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args) { @@ -667,17 +676,45 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int if (bytesLeftToRead >= (int)(numberOfEntities * expectedBytesPerEntity)) { for (uint16_t i = 0; i < numberOfEntities; i++) { - EntityItem tempEntity; // we will read into this + int bytesForThisEntity = 0; EntityItemID entityItemID = EntityItem::readEntityItemIDFromBuffer(dataAt, bytesLeftToRead, args); - const EntityItem* existingEntityItem = _myTree->findEntityByEntityItemID(entityItemID); - if (existingEntityItem) { - // copy original properties... - tempEntity.copyChangedProperties(*existingEntityItem); - } - // read only the changed properties - int bytesForThisEntity = tempEntity.readEntityDataFromBuffer(dataAt, bytesLeftToRead, args); + EntityItem* entityItem = _myTree->findEntityByEntityItemID(entityItemID); + bool newEntity = false; - _myTree->storeEntity(tempEntity); + // If the item already exists in our tree, we want do the following... + // 1) remember the old cube for the entity so we can mark it as dirty + // 2) allow the existing item to read from the databuffer + // 3) check to see if after reading the item, the + if (entityItem) { + AACube existingEntityCube = entityItem->getAACube(); + _myTree->rememberDirtyCube(existingEntityCube); + bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args); + } else { + entityItem = EntityTypes::constructEntityItem(dataAt, bytesLeftToRead); + + if (entityItem) { + bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args); + addEntityItem(entityItem); // add this new entity to this elements entities + newEntity = true; + } + } + + if (entityItem) { + if (newEntity) { + AACube newEntityCube = entityItem->getAACube(); + _myTree->rememberDirtyCube(newEntityCube); + } + + if (!bestFitEntityBounds(entityItem)) { + _myTree->rememberEntityToMove(entityItem); + if (!newEntity) { + AACube newEntityCube = entityItem->getAACube(); + _myTree->rememberDirtyCube(newEntityCube); + } + } + } + + // Move the buffer forward to read more entities dataAt += bytesForThisEntity; bytesLeftToRead -= bytesForThisEntity; bytesRead += bytesForThisEntity; @@ -688,6 +725,10 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int return bytesRead; } +void EntityTreeElement::addEntityItem(EntityItem* entity) { + _entityItems->push_back(entity); +} + // will average a "common reduced LOD view" from the the child elements... void EntityTreeElement::calculateAverageFromChildren() { // nothing to do here yet... diff --git a/libraries/entities/src/EntityTreeElement.h b/libraries/entities/src/EntityTreeElement.h index ac65e912a4..649248b36a 100644 --- a/libraries/entities/src/EntityTreeElement.h +++ b/libraries/entities/src/EntityTreeElement.h @@ -122,6 +122,7 @@ public: bool updateEntity(const EntityItem& entity); bool addOrUpdateEntity(EntityItem* entity, const EntityItemProperties& properties); + void addEntityItem(EntityItem* entity); void updateEntityItemID(FindAndUpdateEntityItemIDArgs* args); diff --git a/tests/octree/src/ModelTests.cpp b/tests/octree/src/ModelTests.cpp index 1ce02eed9d..59c09863e9 100644 --- a/tests/octree/src/ModelTests.cpp +++ b/tests/octree/src/ModelTests.cpp @@ -292,7 +292,7 @@ void EntityTests::modelTreeTests(bool verbose) { EntityTreeElement* containingElement = tree.getContainingElement(modelID); AACube elementCube = containingElement ? containingElement->getAACube() : AACube(); - bool elementIsBestFit = containingElement->bestFitEntityBounds(*foundEntityByID); + bool elementIsBestFit = containingElement->bestFitEntityBounds(foundEntityByID); if (extraVerbose) { qDebug() << "foundEntityByRadius=" << foundEntityByRadius; diff --git a/tests/octree/src/OctreeTests.cpp b/tests/octree/src/OctreeTests.cpp index 05b4c97f53..1ac094eefd 100644 --- a/tests/octree/src/OctreeTests.cpp +++ b/tests/octree/src/OctreeTests.cpp @@ -1271,7 +1271,7 @@ void OctreeTests::byteCountCodingTests(bool verbose) { void OctreeTests::modelItemTests(bool verbose) { -#ifdef HIDE_SUBCLASS_METHODS +#if 0 // def HIDE_SUBCLASS_METHODS //verbose = true; EntityTreeElementExtraEncodeData modelTreeElementExtraEncodeData;