From 31fcd55d473ce7a6c9008a373c79b2ca67e3c934 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 6 Sep 2015 10:31:12 -0700 Subject: [PATCH] octree uses shared pointers --- .../src/entities/EntityServer.cpp | 17 +- assignment-client/src/entities/EntityServer.h | 2 +- .../src/octree/OctreeQueryNode.cpp | 12 +- .../src/octree/OctreeSendThread.cpp | 4 +- assignment-client/src/octree/OctreeServer.cpp | 3 +- assignment-client/src/octree/OctreeServer.h | 6 +- interface/src/Application.cpp | 64 ++++--- interface/src/Application.h | 6 +- interface/src/avatar/Avatar.cpp | 2 +- interface/src/avatar/ModelReferential.cpp | 8 +- interface/src/avatar/ModelReferential.h | 10 +- interface/src/avatar/MyAvatar.cpp | 4 +- .../src/EntityTreeRenderer.cpp | 43 +++-- .../src/EntityTreeRenderer.h | 19 +- .../src/RenderableLightEntityItem.cpp | 2 +- .../src/RenderableLightEntityItem.h | 2 +- .../src/RenderableModelEntityItem.cpp | 7 +- .../src/RenderableModelEntityItem.h | 2 +- .../src/RenderablePolyVoxEntityItem.cpp | 10 +- .../src/RenderablePolyVoxEntityItem.h | 2 +- libraries/entities/src/AddEntityOperator.cpp | 15 +- libraries/entities/src/AddEntityOperator.h | 10 +- .../entities/src/DeleteEntityOperator.cpp | 16 +- libraries/entities/src/DeleteEntityOperator.h | 14 +- libraries/entities/src/EntityItem.cpp | 32 +--- libraries/entities/src/EntityItem.h | 13 +- .../entities/src/EntityScriptingInterface.cpp | 16 +- .../entities/src/EntityScriptingInterface.h | 7 +- libraries/entities/src/EntitySimulation.cpp | 2 +- libraries/entities/src/EntitySimulation.h | 6 +- libraries/entities/src/EntityTree.cpp | 115 +++++++----- libraries/entities/src/EntityTree.h | 42 +++-- libraries/entities/src/EntityTreeElement.cpp | 94 ++++++---- libraries/entities/src/EntityTreeElement.h | 29 ++- .../entities/src/EntityTreeHeadlessViewer.cpp | 6 +- .../entities/src/EntityTreeHeadlessViewer.h | 8 +- libraries/entities/src/LineEntityItem.h | 2 +- .../entities/src/MovingEntitiesOperator.cpp | 20 +- .../entities/src/MovingEntitiesOperator.h | 14 +- libraries/entities/src/PolyLineEntityItem.h | 2 +- libraries/entities/src/PolyVoxEntityItem.h | 2 +- .../src/RecurseOctreeToMapOperator.cpp | 15 +- .../entities/src/RecurseOctreeToMapOperator.h | 10 +- libraries/entities/src/SphereEntityItem.cpp | 5 +- libraries/entities/src/SphereEntityItem.h | 2 +- libraries/entities/src/TextEntityItem.cpp | 2 +- libraries/entities/src/TextEntityItem.h | 2 +- .../entities/src/UpdateEntityOperator.cpp | 38 ++-- libraries/entities/src/UpdateEntityOperator.h | 20 +- libraries/entities/src/WebEntityItem.cpp | 2 +- libraries/entities/src/WebEntityItem.h | 2 +- libraries/entities/src/ZoneEntityItem.cpp | 2 +- libraries/entities/src/ZoneEntityItem.h | 7 +- libraries/octree/src/Octree.cpp | 177 +++++++++++------- libraries/octree/src/Octree.h | 70 +++---- libraries/octree/src/OctreeElement.cpp | 113 ++++++----- libraries/octree/src/OctreeElement.h | 69 +++---- libraries/octree/src/OctreeElementBag.cpp | 14 +- libraries/octree/src/OctreeElementBag.h | 16 +- libraries/octree/src/OctreeHeadlessViewer.h | 2 +- libraries/octree/src/OctreePersistThread.cpp | 2 +- libraries/octree/src/OctreePersistThread.h | 12 +- libraries/octree/src/OctreeRenderer.cpp | 13 +- libraries/octree/src/OctreeRenderer.h | 16 +- libraries/octree/src/OctreeSceneStats.cpp | 19 +- libraries/octree/src/OctreeSceneStats.h | 18 +- libraries/physics/src/EntityMotionState.cpp | 4 +- .../physics/src/PhysicalEntitySimulation.cpp | 4 +- .../physics/src/PhysicalEntitySimulation.h | 7 +- libraries/physics/src/PhysicsEngine.cpp | 3 - libraries/physics/src/PhysicsEngine.h | 7 +- libraries/shared/src/SharedUtil.h | 9 +- 72 files changed, 748 insertions(+), 624 deletions(-) diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index feef396c72..bde53e4a87 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -36,7 +36,7 @@ EntityServer::~EntityServer() { _pruneDeletedEntitiesTimer->deleteLater(); } - EntityTree* tree = (EntityTree*)_tree; + EntityTreePointer tree = std::static_pointer_cast(_tree); tree->removeNewlyCreatedHook(this); } @@ -50,8 +50,9 @@ OctreeQueryNode* EntityServer::createOctreeQueryNode() { return new EntityNodeData(); } -Octree* EntityServer::createTree() { - EntityTree* tree = new EntityTree(true); +OctreePointer EntityServer::createTree() { + EntityTreePointer tree = EntityTreePointer(new EntityTree(true)); + tree->createRootElement(); tree->addNewlyCreatedHook(this); if (!_entitySimulation) { SimpleEntitySimulation* simpleSimulation = new SimpleEntitySimulation(); @@ -82,7 +83,7 @@ bool EntityServer::hasSpecialPacketsToSend(const SharedNodePointer& node) { if (nodeData) { quint64 deletedEntitiesSentAt = nodeData->getLastDeletedEntitiesSentAt(); - EntityTree* tree = static_cast(_tree); + EntityTreePointer tree = std::static_pointer_cast(_tree); shouldSendDeletedEntities = tree->hasEntitiesDeletedSince(deletedEntitiesSentAt); } @@ -97,7 +98,7 @@ int EntityServer::sendSpecialPackets(const SharedNodePointer& node, OctreeQueryN quint64 deletedEntitiesSentAt = nodeData->getLastDeletedEntitiesSentAt(); quint64 deletePacketSentAt = usecTimestampNow(); - EntityTree* tree = static_cast(_tree); + EntityTreePointer tree = std::static_pointer_cast(_tree); bool hasMoreToSend = true; packetsSent = 0; @@ -122,7 +123,7 @@ int EntityServer::sendSpecialPackets(const SharedNodePointer& node, OctreeQueryN } void EntityServer::pruneDeletedEntities() { - EntityTree* tree = static_cast(_tree); + EntityTreePointer tree = std::static_pointer_cast(_tree); if (tree->hasAnyDeletedEntities()) { quint64 earliestLastDeletedEntitiesSent = usecTimestampNow() + 1; // in the future @@ -147,8 +148,6 @@ void EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectio qDebug("wantEditLogging=%s", debug::valueOf(wantEditLogging)); - EntityTree* tree = static_cast(_tree); + EntityTreePointer tree = std::static_pointer_cast(_tree); tree->setWantEditLogging(wantEditLogging); } - - diff --git a/assignment-client/src/entities/EntityServer.h b/assignment-client/src/entities/EntityServer.h index 1c4eda3cc0..7d314057cc 100644 --- a/assignment-client/src/entities/EntityServer.h +++ b/assignment-client/src/entities/EntityServer.h @@ -47,7 +47,7 @@ public slots: void pruneDeletedEntities(); protected: - virtual Octree* createTree(); + virtual OctreePointer createTree(); private slots: void handleEntityPacket(QSharedPointer packet, SharedNodePointer senderNode); diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index 6395397c51..64c5b4318a 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -338,9 +338,9 @@ void OctreeQueryNode::dumpOutOfView() { int outOfView = 0; OctreeElementBag tempBag; while (!elementBag.isEmpty()) { - OctreeElement* node = elementBag.extract(); - if (node->isInView(_currentViewFrustum)) { - tempBag.insert(node); + OctreeElementPointer elt = elementBag.extract(); + if (elt->isInView(_currentViewFrustum)) { + tempBag.insert(elt); stillInView++; } else { outOfView++; @@ -348,9 +348,9 @@ void OctreeQueryNode::dumpOutOfView() { } if (stillInView > 0) { while (!tempBag.isEmpty()) { - OctreeElement* node = tempBag.extract(); - if (node->isInView(_currentViewFrustum)) { - elementBag.insert(node); + OctreeElementPointer elt = tempBag.extract(); + if (elt->isInView(_currentViewFrustum)) { + elementBag.insert(elt); } } } diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 62517e698b..ad6ac8b39f 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -421,7 +421,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus lockWaitElapsedUsec = (float)(lockWaitEnd - lockWaitStart); quint64 encodeStart = usecTimestampNow(); - OctreeElement* subTree = nodeData->elementBag.extract(); + OctreeElementPointer subTree = nodeData->elementBag.extract(); /* TODO: Looking for a way to prevent locking and encoding a tree that is not // going to result in any packets being sent... @@ -430,7 +430,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus // and we've already seen at least one duplicate packet, then we probably don't need // to lock the tree and encode, because the result should be that no bytes will be // encoded, and this will be a duplicate packet from the last one we sent... - OctreeElement* root = _myServer->getOctree()->getRoot(); + OctreeElementPointer root = _myServer->getOctree()->getRoot(); bool skipEncode = false; if ( (subTree == root) diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index a0350622db..f8bbeeac7b 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -280,8 +280,7 @@ OctreeServer::~OctreeServer() { // cleanup our tree here... qDebug() << qPrintable(_safeServerName) << "server START cleaning up octree... [" << this << "]"; - delete _tree; - _tree = NULL; + _tree.reset(); qDebug() << qPrintable(_safeServerName) << "server DONE cleaning up octree... [" << this << "]"; if (_instance == this) { diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index 419cdabc58..54add7a794 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -42,7 +42,7 @@ public: bool wantsDebugReceiving() const { return _debugReceiving; } bool wantsVerboseDebug() const { return _verboseDebug; } - Octree* getOctree() { return _tree; } + OctreePointer getOctree() { return _tree; } JurisdictionMap* getJurisdiction() { return _jurisdiction; } int getPacketsPerClientPerInterval() const { return std::min(_packetsPerClientPerInterval, @@ -131,7 +131,7 @@ private slots: void handleJurisdictionRequestPacket(QSharedPointer packet, SharedNodePointer senderNode); protected: - virtual Octree* createTree() = 0; + virtual OctreePointer createTree() = 0; bool readOptionBool(const QString& optionName, const QJsonObject& settingsSectionObject, bool& result); bool readOptionInt(const QString& optionName, const QJsonObject& settingsSectionObject, int& result); bool readOptionString(const QString& optionName, const QJsonObject& settingsSectionObject, QString& result); @@ -160,7 +160,7 @@ protected: QString _persistAsFileType; int _packetsPerClientPerInterval; int _packetsTotalPerInterval; - Octree* _tree; // this IS a reaveraging tree + OctreePointer _tree; // this IS a reaveraging tree bool _wantPersist; bool _debugSending; bool _debugReceiving; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8505e999dd..ae97d5aa94 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -333,10 +333,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _frameCount(0), _fps(60.0f), _justStarted(true), - _physicsEngine(glm::vec3(0.0f)), + _physicsEngine(new PhysicsEngine(Vectors::ZERO)), _entities(true, this, this), _entityClipboardRenderer(false, this, this), - _entityClipboard(), + _entityClipboard(new EntityTree()), _viewFrustum(), _lastQueriedViewFrustum(), _lastQueriedTime(usecTimestampNow()), @@ -370,6 +370,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : { setInstance(this); + _entityClipboard->createRootElement(); + _pluginContainer = new PluginContainerProxy(); Plugin::setContainer(_pluginContainer); #ifdef Q_OS_WIN @@ -841,7 +843,7 @@ void Application::emptyLocalCache() { } Application::~Application() { - EntityTree* tree = _entities.getTree(); + EntityTreePointer tree = _entities.getTree(); tree->lockForWrite(); _entities.getTree()->setSimulation(NULL); tree->unlock(); @@ -851,7 +853,7 @@ Application::~Application() { Menu::getInstance()->deleteLater(); - _physicsEngine.setCharacterController(NULL); + _physicsEngine->setCharacterController(NULL); _myAvatar = NULL; ModelEntityItem::cleanupLoadedAnimations(); @@ -866,7 +868,7 @@ Application::~Application() { // remove avatars from physics engine DependencyManager::get()->clearOtherAvatars(); - _physicsEngine.deleteObjects(DependencyManager::get()->getObjectsToDelete()); + _physicsEngine->deleteObjects(DependencyManager::get()->getObjectsToDelete()); DependencyManager::destroy(); DependencyManager::destroy(); @@ -1486,7 +1488,7 @@ void Application::keyPressEvent(QKeyEvent* event) { break; case Qt::Key_F: { - _physicsEngine.dumpNextStats(); + _physicsEngine->dumpNextStats(); break; } @@ -2355,7 +2357,7 @@ void Application::saveSettings() { } bool Application::importEntities(const QString& urlOrFilename) { - _entityClipboard.eraseAllOctreeElements(); + _entityClipboard->eraseAllOctreeElements(); QUrl url(urlOrFilename); @@ -2364,15 +2366,15 @@ bool Application::importEntities(const QString& urlOrFilename) { url = QUrl::fromLocalFile(urlOrFilename); } - bool success = _entityClipboard.readFromURL(url.toString()); + bool success = _entityClipboard->readFromURL(url.toString()); if (success) { - _entityClipboard.reaverageOctreeElements(); + _entityClipboard->reaverageOctreeElements(); } return success; } QVector Application::pasteEntities(float x, float y, float z) { - return _entityClipboard.sendEntities(&_entityEditSender, _entities.getTree(), x, y, z); + return _entityClipboard->sendEntities(&_entityEditSender, _entities.getTree(), x, y, z); } void Application::initDisplay() { @@ -2417,10 +2419,10 @@ void Application::init() { _entities.setViewFrustum(getViewFrustum()); ObjectMotionState::setShapeManager(&_shapeManager); - _physicsEngine.init(); + _physicsEngine->init(); - EntityTree* tree = _entities.getTree(); - _entitySimulation.init(tree, &_physicsEngine, &_entityEditSender); + EntityTreePointer tree = _entities.getTree(); + _entitySimulation.init(tree, _physicsEngine, &_entityEditSender); tree->setSimulation(&_entitySimulation); auto entityScriptingInterface = DependencyManager::get(); @@ -2435,10 +2437,10 @@ void Application::init() { _entityClipboardRenderer.init(); _entityClipboardRenderer.setViewFrustum(getViewFrustum()); - _entityClipboardRenderer.setTree(&_entityClipboard); + _entityClipboardRenderer.setTree(_entityClipboard); // Make sure any new sounds are loaded as soon as know about them. - connect(tree, &EntityTree::newCollisionSoundURL, DependencyManager::get().data(), &SoundCache::getSound); + connect(tree.get(), &EntityTree::newCollisionSoundURL, DependencyManager::get().data(), &SoundCache::getSound); connect(_myAvatar, &MyAvatar::newCollisionSoundURL, DependencyManager::get().data(), &SoundCache::getSound); } @@ -2812,18 +2814,18 @@ void Application::update(float deltaTime) { _myAvatar->relayDriveKeysToCharacterController(); _entitySimulation.lock(); - _physicsEngine.deleteObjects(_entitySimulation.getObjectsToDelete()); + _physicsEngine->deleteObjects(_entitySimulation.getObjectsToDelete()); _entitySimulation.unlock(); _entities.getTree()->lockForWrite(); _entitySimulation.lock(); - _physicsEngine.addObjects(_entitySimulation.getObjectsToAdd()); + _physicsEngine->addObjects(_entitySimulation.getObjectsToAdd()); _entitySimulation.unlock(); _entities.getTree()->unlock(); _entities.getTree()->lockForWrite(); _entitySimulation.lock(); - VectorOfMotionStates stillNeedChange = _physicsEngine.changeObjects(_entitySimulation.getObjectsToChange()); + VectorOfMotionStates stillNeedChange = _physicsEngine->changeObjects(_entitySimulation.getObjectsToChange()); _entitySimulation.setObjectsToChange(stillNeedChange); _entitySimulation.unlock(); _entities.getTree()->unlock(); @@ -2833,29 +2835,29 @@ void Application::update(float deltaTime) { _entitySimulation.unlock(); AvatarManager* avatarManager = DependencyManager::get().data(); - _physicsEngine.deleteObjects(avatarManager->getObjectsToDelete()); - _physicsEngine.addObjects(avatarManager->getObjectsToAdd()); - _physicsEngine.changeObjects(avatarManager->getObjectsToChange()); + _physicsEngine->deleteObjects(avatarManager->getObjectsToDelete()); + _physicsEngine->addObjects(avatarManager->getObjectsToAdd()); + _physicsEngine->changeObjects(avatarManager->getObjectsToChange()); _entities.getTree()->lockForWrite(); - _physicsEngine.stepSimulation(); + _physicsEngine->stepSimulation(); _entities.getTree()->unlock(); - if (_physicsEngine.hasOutgoingChanges()) { + if (_physicsEngine->hasOutgoingChanges()) { _entities.getTree()->lockForWrite(); _entitySimulation.lock(); - _entitySimulation.handleOutgoingChanges(_physicsEngine.getOutgoingChanges(), _physicsEngine.getSessionID()); + _entitySimulation.handleOutgoingChanges(_physicsEngine->getOutgoingChanges(), _physicsEngine->getSessionID()); _entitySimulation.unlock(); _entities.getTree()->unlock(); _entities.getTree()->lockForWrite(); - avatarManager->handleOutgoingChanges(_physicsEngine.getOutgoingChanges()); + avatarManager->handleOutgoingChanges(_physicsEngine->getOutgoingChanges()); _entities.getTree()->unlock(); - auto collisionEvents = _physicsEngine.getCollisionEvents(); + auto collisionEvents = _physicsEngine->getCollisionEvents(); avatarManager->handleCollisionEvents(collisionEvents); - _physicsEngine.dumpStatsIfNecessary(); + _physicsEngine->dumpStatsIfNecessary(); if (!_aboutToQuit) { PerformanceTimer perfTimer("entities"); @@ -4102,7 +4104,7 @@ bool Application::acceptURL(const QString& urlString) { } void Application::setSessionUUID(const QUuid& sessionUUID) { - _physicsEngine.setSessionUUID(sessionUUID); + _physicsEngine->setSessionUUID(sessionUUID); } bool Application::askToSetAvatarUrl(const QString& url) { @@ -4351,7 +4353,7 @@ void Application::openUrl(const QUrl& url) { void Application::updateMyAvatarTransform() { const float SIMULATION_OFFSET_QUANTIZATION = 16.0f; // meters glm::vec3 avatarPosition = _myAvatar->getPosition(); - glm::vec3 physicsWorldOffset = _physicsEngine.getOriginOffset(); + glm::vec3 physicsWorldOffset = _physicsEngine->getOriginOffset(); if (glm::distance(avatarPosition, physicsWorldOffset) > SIMULATION_OFFSET_QUANTIZATION) { glm::vec3 newOriginOffset = avatarPosition; int halfExtent = (int)HALF_SIMULATION_EXTENT; @@ -4360,7 +4362,7 @@ void Application::updateMyAvatarTransform() { ((int)(avatarPosition[i] / SIMULATION_OFFSET_QUANTIZATION)) * (int)SIMULATION_OFFSET_QUANTIZATION)); } // TODO: Andrew to replace this with method that actually moves existing object positions in PhysicsEngine - _physicsEngine.setOriginOffset(newOriginOffset); + _physicsEngine->setOriginOffset(newOriginOffset); } } @@ -4558,7 +4560,7 @@ void Application::checkSkeleton() { _myAvatar->useFullAvatarURL(AvatarData::defaultFullAvatarModelUrl(), DEFAULT_FULL_AVATAR_MODEL_NAME); } else { - _physicsEngine.setCharacterController(_myAvatar->getCharacterController()); + _physicsEngine->setCharacterController(_myAvatar->getCharacterController()); } } diff --git a/interface/src/Application.h b/interface/src/Application.h index 6c3b68cf6f..d82a5b378f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -208,7 +208,7 @@ public: QUndoStack* getUndoStack() { return &_undoStack; } MainWindow* getWindow() { return _window; } OctreeQuery& getOctreeQuery() { return _octreeQuery; } - EntityTree* getEntityClipboard() { return &_entityClipboard; } + EntityTreePointer getEntityClipboard() { return _entityClipboard; } EntityTreeRenderer* getEntityClipboardRenderer() { return &_entityClipboardRenderer; } EntityEditPacketSender* getEntityEditPacketSender() { return &_entityEditSender; } @@ -533,11 +533,11 @@ private: ShapeManager _shapeManager; PhysicalEntitySimulation _entitySimulation; - PhysicsEngine _physicsEngine; + PhysicsEnginePointer _physicsEngine; EntityTreeRenderer _entities; EntityTreeRenderer _entityClipboardRenderer; - EntityTree _entityClipboard; + EntityTreePointer _entityClipboard; ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc. ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 55699bccbe..aa401f91f8 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -152,7 +152,7 @@ void Avatar::simulate(float deltaTime) { // update the avatar's position according to its referential if (_referential) { if (_referential->hasExtraData()) { - EntityTree* tree = Application::getInstance()->getEntities()->getTree(); + EntityTreePointer tree = Application::getInstance()->getEntities()->getTree(); switch (_referential->type()) { case Referential::MODEL: _referential = new ModelReferential(_referential, diff --git a/interface/src/avatar/ModelReferential.cpp b/interface/src/avatar/ModelReferential.cpp index 46290b17b5..18c5e36e7a 100644 --- a/interface/src/avatar/ModelReferential.cpp +++ b/interface/src/avatar/ModelReferential.cpp @@ -16,7 +16,7 @@ #include "InterfaceLogging.h" #include "ModelReferential.h" -ModelReferential::ModelReferential(Referential* referential, EntityTree* tree, AvatarData* avatar) : +ModelReferential::ModelReferential(Referential* referential, EntityTreePointer tree, AvatarData* avatar) : Referential(MODEL, avatar), _tree(tree) { @@ -39,7 +39,7 @@ ModelReferential::ModelReferential(Referential* referential, EntityTree* tree, A } } -ModelReferential::ModelReferential(const QUuid& entityID, EntityTree* tree, AvatarData* avatar) : +ModelReferential::ModelReferential(const QUuid& entityID, EntityTreePointer tree, AvatarData* avatar) : Referential(MODEL, avatar), _entityID(entityID), _tree(tree) @@ -96,7 +96,7 @@ int ModelReferential::unpackExtraData(const unsigned char *sourceBuffer, int siz return NUM_BYTES_RFC4122_UUID; } -JointReferential::JointReferential(Referential* referential, EntityTree* tree, AvatarData* avatar) : +JointReferential::JointReferential(Referential* referential, EntityTreePointer tree, AvatarData* avatar) : ModelReferential(referential, tree, avatar) { _type = JOINT; @@ -115,7 +115,7 @@ JointReferential::JointReferential(Referential* referential, EntityTree* tree, A update(); } -JointReferential::JointReferential(uint32_t jointIndex, const QUuid& entityID, EntityTree* tree, AvatarData* avatar) : +JointReferential::JointReferential(uint32_t jointIndex, const QUuid& entityID, EntityTreePointer tree, AvatarData* avatar) : ModelReferential(entityID, tree, avatar), _jointIndex(jointIndex) { diff --git a/interface/src/avatar/ModelReferential.h b/interface/src/avatar/ModelReferential.h index ed38253b0b..810db4b8e5 100644 --- a/interface/src/avatar/ModelReferential.h +++ b/interface/src/avatar/ModelReferential.h @@ -19,8 +19,8 @@ class Model; class ModelReferential : public Referential { public: - ModelReferential(Referential* ref, EntityTree* tree, AvatarData* avatar); - ModelReferential(const QUuid& entityID, EntityTree* tree, AvatarData* avatar); + ModelReferential(Referential* ref, EntityTreePointer tree, AvatarData* avatar); + ModelReferential(const QUuid& entityID, EntityTreePointer tree, AvatarData* avatar); virtual void update(); protected: @@ -28,13 +28,13 @@ protected: virtual int unpackExtraData(const unsigned char* sourceBuffer, int size); QUuid _entityID; - EntityTree* _tree; + EntityTreePointer _tree; }; class JointReferential : public ModelReferential { public: - JointReferential(Referential* ref, EntityTree* tree, AvatarData* avatar); - JointReferential(uint32_t jointIndex, const QUuid& entityID, EntityTree* tree, AvatarData* avatar); + JointReferential(Referential* ref, EntityTreePointer tree, AvatarData* avatar); + JointReferential(uint32_t jointIndex, const QUuid& entityID, EntityTreePointer tree, AvatarData* avatar); virtual void update(); protected: diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index de7e2ba8fb..a9e36d0fa9 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -459,7 +459,7 @@ void MyAvatar::clearReferential() { } bool MyAvatar::setModelReferential(const QUuid& id) { - EntityTree* tree = Application::getInstance()->getEntities()->getTree(); + EntityTreePointer tree = Application::getInstance()->getEntities()->getTree(); changeReferential(new ModelReferential(id, tree, this)); if (_referential->isValid()) { return true; @@ -470,7 +470,7 @@ bool MyAvatar::setModelReferential(const QUuid& id) { } bool MyAvatar::setJointReferential(const QUuid& id, int jointIndex) { - EntityTree* tree = Application::getInstance()->getEntities()->getTree(); + EntityTreePointer tree = Application::getInstance()->getEntities()->getTree(); changeReferential(new JointReferential(jointIndex, id, tree, this)); if (!_referential->isValid()) { return true; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 72400dcefb..4b3a1ec5d4 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -107,7 +107,7 @@ void EntityTreeRenderer::clear() { void EntityTreeRenderer::init() { OctreeRenderer::init(); - EntityTree* entityTree = static_cast(_tree); + EntityTreePointer entityTree = std::static_pointer_cast(_tree); entityTree->setFBXService(this); if (_wantScripts) { @@ -121,10 +121,11 @@ void EntityTreeRenderer::init() { // make sure our "last avatar position" is something other than our current position, so that on our // first chance, we'll check for enter/leave entity events. _lastAvatarPosition = _viewState->getAvatarPosition() + glm::vec3((float)TREE_SCALE); - - connect(entityTree, &EntityTree::deletingEntity, this, &EntityTreeRenderer::deletingEntity, Qt::QueuedConnection); - connect(entityTree, &EntityTree::addingEntity, this, &EntityTreeRenderer::addingEntity, Qt::QueuedConnection); - connect(entityTree, &EntityTree::entityScriptChanging, this, &EntityTreeRenderer::entitySciptChanging, Qt::QueuedConnection); + + connect(entityTree.get(), &EntityTree::deletingEntity, this, &EntityTreeRenderer::deletingEntity, Qt::QueuedConnection); + connect(entityTree.get(), &EntityTree::addingEntity, this, &EntityTreeRenderer::addingEntity, Qt::QueuedConnection); + connect(entityTree.get(), &EntityTree::entityScriptChanging, + this, &EntityTreeRenderer::entitySciptChanging, Qt::QueuedConnection); } void EntityTreeRenderer::shutdown() { @@ -149,7 +150,7 @@ void EntityTreeRenderer::errorInLoadingScript(const QUrl& url) { } QScriptValue EntityTreeRenderer::loadEntityScript(const EntityItemID& entityItemID, bool isPreload, bool reload) { - EntityItemPointer entity = static_cast(_tree)->findEntityByEntityItemID(entityItemID); + EntityItemPointer entity = std::static_pointer_cast(_tree)->findEntityByEntityItemID(entityItemID); return loadEntityScript(entity, isPreload, reload); } @@ -302,16 +303,16 @@ QScriptValue EntityTreeRenderer::getPreviouslyLoadedEntityScript(const EntityIte return QScriptValue(); // no script } -void EntityTreeRenderer::setTree(Octree* newTree) { +void EntityTreeRenderer::setTree(OctreePointer newTree) { OctreeRenderer::setTree(newTree); - static_cast(_tree)->setFBXService(this); + std::static_pointer_cast(_tree)->setFBXService(this); } void EntityTreeRenderer::update() { if (_tree && !_shuttingDown) { - EntityTree* tree = static_cast(_tree); + EntityTreePointer tree = std::static_pointer_cast(_tree); tree->update(); - + // check to see if the avatar has moved and if we need to handle enter/leave entity logic checkEnterLeaveEntities(); @@ -341,7 +342,7 @@ void EntityTreeRenderer::checkEnterLeaveEntities() { // find the entities near us _tree->lockForRead(); // don't let someone else change our tree while we search - static_cast(_tree)->findEntities(avatarPosition, radius, foundEntities); + std::static_pointer_cast(_tree)->findEntities(avatarPosition, radius, foundEntities); // create a list of entities that actually contain the avatar's position foreach(EntityItemPointer entity, foundEntities) { @@ -553,7 +554,7 @@ const FBXGeometry* EntityTreeRenderer::getCollisionGeometryForEntity(EntityItemP return result; } -void EntityTreeRenderer::renderElementProxy(EntityTreeElement* entityTreeElement, RenderArgs* args) { +void EntityTreeRenderer::renderElementProxy(EntityTreeElementPointer entityTreeElement, RenderArgs* args) { auto deferredLighting = DependencyManager::get(); Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; @@ -627,10 +628,11 @@ void EntityTreeRenderer::renderProxies(EntityItemPointer entity, RenderArgs* arg } } -void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) { +void EntityTreeRenderer::renderElement(OctreeElementPointer element, RenderArgs* args) { // actually render it here... // we need to iterate the actual entityItems of the element - EntityTreeElement* entityTreeElement = static_cast(element); + EntityTreeElementPointer entityTreeElement = std::static_pointer_cast(element); + EntityItems& entityItems = entityTreeElement->getEntities(); @@ -684,7 +686,7 @@ int EntityTreeRenderer::getBoundaryLevelAdjust() const { void EntityTreeRenderer::processEraseMessage(NLPacket& packet, const SharedNodePointer& sourceNode) { - static_cast(_tree)->processEraseMessage(packet, sourceNode); + std::static_pointer_cast(_tree)->processEraseMessage(packet, sourceNode); } Model* EntityTreeRenderer::allocateModel(const QString& url, const QString& collisionUrl) { @@ -760,9 +762,9 @@ RayToEntityIntersectionResult EntityTreeRenderer::findRayIntersectionWorker(cons bool precisionPicking) { RayToEntityIntersectionResult result; if (_tree) { - EntityTree* entityTree = static_cast(_tree); + EntityTreePointer entityTree = std::static_pointer_cast(_tree); - OctreeElement* element; + OctreeElementPointer element; EntityItemPointer intersectedEntity = NULL; result.intersects = entityTree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face, (void**)&intersectedEntity, lockType, &result.accurate, @@ -1018,7 +1020,7 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) { void EntityTreeRenderer::addingEntity(const EntityItemID& entityID) { checkAndCallPreload(entityID); - auto entity = static_cast(_tree)->findEntityByID(entityID); + auto entity = std::static_pointer_cast(_tree)->findEntityByID(entityID); if (entity) { addEntityToScene(entity); } @@ -1063,7 +1065,8 @@ void EntityTreeRenderer::checkAndCallUnload(const EntityItemID& entityID) { } } -void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityTree* entityTree, const EntityItemID& id, const Collision& collision) { +void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityTreePointer entityTree, + const EntityItemID& id, const Collision& collision) { EntityItemPointer entity = entityTree->findEntityByEntityItemID(id); if (!entity) { return; @@ -1130,7 +1133,7 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons } // See if we should play sounds - EntityTree* entityTree = static_cast(_tree); + EntityTreePointer entityTree = std::static_pointer_cast(_tree); const QUuid& myNodeID = DependencyManager::get()->getSessionUUID(); playEntityCollisionSound(myNodeID, entityTree, idA, collision); playEntityCollisionSound(myNodeID, entityTree, idB, collision); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 25eb87b422..8afdf6e084 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -45,15 +45,15 @@ public: virtual char getMyNodeType() const { return NodeType::EntityServer; } virtual PacketType::Value getMyQueryMessageType() const { return PacketType::EntityQuery; } virtual PacketType::Value getExpectedPacketType() const { return PacketType::EntityData; } - virtual void renderElement(OctreeElement* element, RenderArgs* args); + virtual void renderElement(OctreeElementPointer element, RenderArgs* args); virtual float getSizeScale() const; virtual int getBoundaryLevelAdjust() const; - virtual void setTree(Octree* newTree); + virtual void setTree(OctreePointer newTree); void shutdown(); void update(); - EntityTree* getTree() { return static_cast(_tree); } + EntityTreePointer getTree() { return std::static_pointer_cast(_tree); } void processEraseMessage(NLPacket& packet, const SharedNodePointer& sourceNode); @@ -123,15 +123,19 @@ public slots: void setDisplayModelBounds(bool value) { _displayModelBounds = value; } void setDisplayModelElementProxy(bool value) { _displayModelElementProxy = value; } void setDontDoPrecisionPicking(bool value) { _dontDoPrecisionPicking = value; } - + protected: - virtual Octree* createTree() { return new EntityTree(true); } + virtual OctreePointer createTree() { + EntityTreePointer newTree = EntityTreePointer(new EntityTree(true)); + newTree->createRootElement(); + return newTree; + } private: void addEntityToScene(EntityItemPointer entity); void applyZonePropertiesToScene(std::shared_ptr zone); - void renderElementProxy(EntityTreeElement* entityTreeElement, RenderArgs* args); + void renderElementProxy(EntityTreeElementPointer entityTreeElement, RenderArgs* args); void checkAndCallPreload(const EntityItemID& entityID, const bool reload = false); void checkAndCallUnload(const EntityItemID& entityID); @@ -162,7 +166,8 @@ private: QHash _entityScripts; - void playEntityCollisionSound(const QUuid& myNodeID, EntityTree* entityTree, const EntityItemID& id, const Collision& collision); + void playEntityCollisionSound(const QUuid& myNodeID, EntityTreePointer entityTree, + const EntityItemID& id, const Collision& collision); bool _lastMouseEventValid; MouseEvent _lastMouseEvent; diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp index 3ce4d404d9..19b1ec9c8d 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp @@ -54,7 +54,7 @@ void RenderableLightEntityItem::render(RenderArgs* args) { }; bool RenderableLightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { // TODO: consider if this is really what we want to do. We've made it so that "lights are pickable" is a global state diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.h b/libraries/entities-renderer/src/RenderableLightEntityItem.h index a0c424e240..bf73493729 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.h +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.h @@ -26,7 +26,7 @@ public: virtual void render(RenderArgs* args); virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const; SIMPLE_RENDERABLE(); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index eed908e429..16cf80062d 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -367,13 +367,14 @@ EntityItemProperties RenderableModelEntityItem::getProperties() const { } bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { if (!_model) { return true; } - //qCDebug(entitiesrenderer) << "RenderableModelEntityItem::findDetailedRayIntersection() precisionPicking:" << precisionPicking; - + // qCDebug(entitiesrenderer) << "RenderableModelEntityItem::findDetailedRayIntersection() precisionPicking:" + // << precisionPicking; + QString extraInfo; return _model->findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, extraInfo, precisionPicking); } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 4842063af3..d2c9370553 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -55,7 +55,7 @@ public: virtual void render(RenderArgs* args); virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const; Model* getModel(EntityTreeRenderer* renderer); diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 5ddee32f88..2e8696625c 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -351,7 +351,7 @@ public: bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, - OctreeElement*& element, + OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const @@ -858,8 +858,8 @@ void RenderablePolyVoxEntityItem::compressVolumeDataAndSendEditPacketAsync() { properties.setVoxelDataDirty(); properties.setLastEdited(now); - EntityTreeElement* element = getElement(); - EntityTree* tree = element ? element->getTree() : nullptr; + EntityTreeElementPointer element = getElement(); + EntityTreePointer tree = element ? element->getTree() : nullptr; EntitySimulation* simulation = tree ? tree->getSimulation() : nullptr; PhysicalEntitySimulation* peSimulation = static_cast(simulation); EntityEditPacketSender* packetSender = peSimulation ? peSimulation->getPacketSender() : nullptr; @@ -917,8 +917,8 @@ void RenderablePolyVoxEntityItem::clearOutOfDateNeighbors() { void RenderablePolyVoxEntityItem::cacheNeighbors() { clearOutOfDateNeighbors(); - EntityTreeElement* element = getElement(); - EntityTree* tree = element ? element->getTree() : nullptr; + EntityTreeElementPointer element = getElement(); + EntityTreePointer tree = element ? element->getTree() : nullptr; if (!tree) { return; } diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index 01578b5e58..14853d929e 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -64,7 +64,7 @@ public: void render(RenderArgs* args); virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const; virtual void setVoxelData(QByteArray voxelData); diff --git a/libraries/entities/src/AddEntityOperator.cpp b/libraries/entities/src/AddEntityOperator.cpp index 51015c1ff4..2bfbbe2fd9 100644 --- a/libraries/entities/src/AddEntityOperator.cpp +++ b/libraries/entities/src/AddEntityOperator.cpp @@ -15,8 +15,7 @@ #include "AddEntityOperator.h" -AddEntityOperator::AddEntityOperator(EntityTree* tree, - EntityItemPointer newEntity) : +AddEntityOperator::AddEntityOperator(EntityTreePointer tree, EntityItemPointer newEntity) : _tree(tree), _newEntity(newEntity), _foundNew(false), @@ -25,16 +24,16 @@ AddEntityOperator::AddEntityOperator(EntityTree* tree, { // caller must have verified existence of newEntity assert(_newEntity); - + _newEntityBox = _newEntity->getMaximumAACube().clamp((float)(-HALF_TREE_SCALE), (float)HALF_TREE_SCALE); } -bool AddEntityOperator::preRecursion(OctreeElement* element) { - EntityTreeElement* entityTreeElement = static_cast(element); +bool AddEntityOperator::preRecursion(OctreeElementPointer element) { + EntityTreeElementPointer entityTreeElement = std::static_pointer_cast(element); // In Pre-recursion, we're generally deciding whether or not we want to recurse this // path of the tree. For this operation, we want to recurse the branch of the tree if - // and of the following are true: + // any of the following are true: // * We have not yet found the location for the new entity, and this branch contains the bounds of the new entity bool keepSearching = false; // assume we don't need to search any more @@ -59,7 +58,7 @@ bool AddEntityOperator::preRecursion(OctreeElement* element) { return keepSearching; // if we haven't yet found it, keep looking } -bool AddEntityOperator::postRecursion(OctreeElement* element) { +bool AddEntityOperator::postRecursion(OctreeElementPointer element) { // 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. @@ -73,7 +72,7 @@ bool AddEntityOperator::postRecursion(OctreeElement* element) { return keepSearching; // if we haven't yet found it, keep looking } -OctreeElement* AddEntityOperator::possiblyCreateChildAt(OctreeElement* element, int childIndex) { +OctreeElementPointer AddEntityOperator::possiblyCreateChildAt(OctreeElementPointer element, int childIndex) { // 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 diff --git a/libraries/entities/src/AddEntityOperator.h b/libraries/entities/src/AddEntityOperator.h index d7e7371bb0..6aa2d5f727 100644 --- a/libraries/entities/src/AddEntityOperator.h +++ b/libraries/entities/src/AddEntityOperator.h @@ -14,13 +14,13 @@ class AddEntityOperator : public RecurseOctreeOperator { public: - AddEntityOperator(EntityTree* tree, EntityItemPointer newEntity); + AddEntityOperator(EntityTreePointer tree, EntityItemPointer newEntity); - virtual bool preRecursion(OctreeElement* element); - virtual bool postRecursion(OctreeElement* element); - virtual OctreeElement* possiblyCreateChildAt(OctreeElement* element, int childIndex); + virtual bool preRecursion(OctreeElementPointer element); + virtual bool postRecursion(OctreeElementPointer element); + virtual OctreeElementPointer possiblyCreateChildAt(OctreeElementPointer element, int childIndex); private: - EntityTree* _tree; + EntityTreePointer _tree; EntityItemPointer _newEntity; bool _foundNew; quint64 _changeTime; diff --git a/libraries/entities/src/DeleteEntityOperator.cpp b/libraries/entities/src/DeleteEntityOperator.cpp index bb96b9698d..48335c22b8 100644 --- a/libraries/entities/src/DeleteEntityOperator.cpp +++ b/libraries/entities/src/DeleteEntityOperator.cpp @@ -16,7 +16,7 @@ #include "EntitiesLogging.h" #include "DeleteEntityOperator.h" -DeleteEntityOperator::DeleteEntityOperator(EntityTree* tree, const EntityItemID& searchEntityID) : +DeleteEntityOperator::DeleteEntityOperator(EntityTreePointer tree, const EntityItemID& searchEntityID) : _tree(tree), _changeTime(usecTimestampNow()), _foundCount(0), @@ -28,7 +28,7 @@ DeleteEntityOperator::DeleteEntityOperator(EntityTree* tree, const EntityItemID& DeleteEntityOperator::~DeleteEntityOperator() { } -DeleteEntityOperator::DeleteEntityOperator(EntityTree* tree) : +DeleteEntityOperator::DeleteEntityOperator(EntityTreePointer tree) : _tree(tree), _changeTime(usecTimestampNow()), _foundCount(0), @@ -55,7 +55,7 @@ void DeleteEntityOperator::addEntityIDToDeleteList(const EntityItemID& searchEnt // does this entity tree element contain the old entity -bool DeleteEntityOperator::subTreeContainsSomeEntitiesToDelete(OctreeElement* element) { +bool DeleteEntityOperator::subTreeContainsSomeEntitiesToDelete(OctreeElementPointer element) { bool containsEntity = false; // If we don't have an old entity, then we don't contain the entity, otherwise @@ -72,9 +72,9 @@ bool DeleteEntityOperator::subTreeContainsSomeEntitiesToDelete(OctreeElement* el return containsEntity; } -bool DeleteEntityOperator::preRecursion(OctreeElement* element) { - EntityTreeElement* entityTreeElement = static_cast(element); - +bool DeleteEntityOperator::preRecursion(OctreeElementPointer element) { + EntityTreeElementPointer entityTreeElement = std::static_pointer_cast(element); + // In Pre-recursion, we're generally deciding whether or not we want to recurse this // path of the tree. For this operation, we want to recurse the branch of the tree if: // * We have not yet found the all entities, and @@ -108,7 +108,7 @@ bool DeleteEntityOperator::preRecursion(OctreeElement* element) { return keepSearching; // if we haven't yet found it, keep looking } -bool DeleteEntityOperator::postRecursion(OctreeElement* element) { +bool DeleteEntityOperator::postRecursion(OctreeElementPointer element) { // 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. @@ -125,7 +125,7 @@ bool DeleteEntityOperator::postRecursion(OctreeElement* element) { // children are the containing element for any entity in our lists of entities to delete, then they // must have already deleted the entity, and they are safe to prune. Since this operation doesn't // ever add any elements we don't have to worry about memory being reused within this recursion pass. - EntityTreeElement* entityTreeElement = static_cast(element); + EntityTreeElementPointer entityTreeElement = std::static_pointer_cast(element); entityTreeElement->pruneChildren(); // take this opportunity to prune any empty leaves return keepSearching; // if we haven't yet found it, keep looking } diff --git a/libraries/entities/src/DeleteEntityOperator.h b/libraries/entities/src/DeleteEntityOperator.h index 48024b530c..ae2ec3621e 100644 --- a/libraries/entities/src/DeleteEntityOperator.h +++ b/libraries/entities/src/DeleteEntityOperator.h @@ -16,7 +16,7 @@ class EntityToDeleteDetails { public: EntityItemPointer entity; AACube cube; - EntityTreeElement* containingElement; + EntityTreeElementPointer containingElement; }; typedef QSet RemovedEntities; @@ -31,22 +31,22 @@ inline bool operator==(const EntityToDeleteDetails& a, const EntityToDeleteDetai class DeleteEntityOperator : public RecurseOctreeOperator { public: - DeleteEntityOperator(EntityTree* tree); - DeleteEntityOperator(EntityTree* tree, const EntityItemID& searchEntityID); + DeleteEntityOperator(EntityTreePointer tree); + DeleteEntityOperator(EntityTreePointer tree, const EntityItemID& searchEntityID); ~DeleteEntityOperator(); void addEntityIDToDeleteList(const EntityItemID& searchEntityID); - virtual bool preRecursion(OctreeElement* element); - virtual bool postRecursion(OctreeElement* element); + virtual bool preRecursion(OctreeElementPointer element); + virtual bool postRecursion(OctreeElementPointer element); const RemovedEntities& getEntities() const { return _entitiesToDelete; } private: - EntityTree* _tree; + EntityTreePointer _tree; RemovedEntities _entitiesToDelete; quint64 _changeTime; int _foundCount; int _lookingCount; - bool subTreeContainsSomeEntitiesToDelete(OctreeElement* element); + bool subTreeContainsSomeEntitiesToDelete(OctreeElementPointer element); }; #endif // hifi_DeleteEntityOperator_h diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 9fa6ccac65..9f06b0d661 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -89,7 +89,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) : EntityItem::~EntityItem() { // clear out any left-over actions - EntityTree* entityTree = _element ? _element->getTree() : nullptr; + EntityTreePointer entityTree = _element ? _element->getTree() : nullptr; EntitySimulation* simulation = entityTree ? entityTree->getSimulation() : nullptr; if (simulation) { clearActions(simulation); @@ -985,6 +985,12 @@ bool EntityItem::isMoving() const { return hasVelocity() || hasAngularVelocity(); } +EntityTreePointer EntityItem::getTree() const { + EntityTreeElementPointer elt = getElement(); + EntityTreePointer tree = elt ? elt->getTree() : nullptr; + return tree; +} + glm::mat4 EntityItem::getEntityToWorldMatrix() const { glm::mat4 translation = glm::translate(getPosition()); glm::mat4 rotation = glm::mat4_cast(getRotation()); @@ -1155,12 +1161,6 @@ void EntityItem::recordCreationTime() { _lastSimulated = now; } -void EntityItem::setCenterPosition(const glm::vec3& position) { - Transform transformToCenter = getTransformToCenter(); - transformToCenter.setTranslation(position); - setTranformToCenter(transformToCenter); -} - const Transform EntityItem::getTransformToCenter() const { Transform result = getTransform(); if (getRegistrationPoint() != ENTITY_ITEM_HALF_VEC3) { // If it is not already centered, translate to center @@ -1169,18 +1169,6 @@ const Transform EntityItem::getTransformToCenter() const { return result; } -void EntityItem::setTranformToCenter(const Transform& transform) { - if (getRegistrationPoint() == ENTITY_ITEM_HALF_VEC3) { - // If it is already centered, just call setTransform - setTransform(transform); - return; - } - - Transform copy = transform; - copy.postTranslate(getRegistrationPoint() - ENTITY_ITEM_HALF_VEC3); // Center to position - setTransform(copy); -} - void EntityItem::setDimensions(const glm::vec3& value) { if (value.x <= 0.0f || value.y <= 0.0f || value.z <= 0.0f) { return; @@ -1577,7 +1565,7 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulation* s assertWriteLocked(); if (_objectActions.contains(actionID)) { if (!simulation) { - EntityTree* entityTree = _element ? _element->getTree() : nullptr; + EntityTreePointer entityTree = _element ? _element->getTree() : nullptr; simulation = entityTree ? entityTree->getSimulation() : nullptr; } @@ -1633,7 +1621,7 @@ void EntityItem::deserializeActionsInternal() { // Keep track of which actions got added or updated by the new actionData - EntityTree* entityTree = _element ? _element->getTree() : nullptr; + EntityTreePointer entityTree = _element ? _element->getTree() : nullptr; assert(entityTree); EntitySimulation* simulation = entityTree ? entityTree->getSimulation() : nullptr; assert(simulation); @@ -1770,8 +1758,6 @@ QVariantMap EntityItem::getActionArguments(const QUuid& actionID) const { return result; } - - #define ENABLE_LOCKING 1 #ifdef ENABLE_LOCKING diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 54a524b5a2..fee2841ba3 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -33,9 +33,11 @@ class EntitySimulation; class EntityTreeElement; class EntityTreeElementExtraEncodeData; - class EntityActionInterface; +class EntityTree; +typedef std::shared_ptr EntityTreePointer; typedef std::shared_ptr EntityActionPointer; +typedef std::shared_ptr EntityTreeElementPointer; namespace render { @@ -201,7 +203,7 @@ public: virtual bool supportsDetailedRayIntersection() const { return false; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { return true; } // attributes applicable to all entity types @@ -216,7 +218,7 @@ public: inline const Transform& getTransform() const { return _transform; } inline void setTransform(const Transform& transform) { _transform = transform; requiresRecalcBoxes(); } - /// Position in meters (0.0 - TREE_SCALE) + /// Position in meters (-TREE_SCALE - TREE_SCALE) inline const glm::vec3& getPosition() const { return _transform.getTranslation(); } inline void setPosition(const glm::vec3& value) { _transform.setTranslation(value); requiresRecalcBoxes(); } @@ -388,7 +390,8 @@ public: void* getPhysicsInfo() const { return _physicsInfo; } void setPhysicsInfo(void* data) { _physicsInfo = data; } - EntityTreeElement* getElement() const { return _element; } + EntityTreeElementPointer getElement() const { return _element; } + EntityTreePointer getTree() const; static void setSendPhysicsUpdates(bool value) { _sendPhysicsUpdates = value; } static bool getSendPhysicsUpdates() { return _sendPhysicsUpdates; } @@ -494,7 +497,7 @@ protected: uint32_t _dirtyFlags; // things that have changed from EXTERNAL changes (via script or packet) but NOT from simulation // these backpointers are only ever set/cleared by friends: - EntityTreeElement* _element = nullptr; // set by EntityTreeElement + EntityTreeElementPointer _element = nullptr; // set by EntityTreeElement void* _physicsInfo = nullptr; // set by EntitySimulation bool _simulated; // set by EntitySimulation diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index b337c05776..85e2d4c7ba 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -47,19 +47,19 @@ bool EntityScriptingInterface::canRez() { return nodeList->getThisNodeCanRez(); } -void EntityScriptingInterface::setEntityTree(EntityTree* modelTree) { +void EntityScriptingInterface::setEntityTree(EntityTreePointer modelTree) { if (_entityTree) { - disconnect(_entityTree, &EntityTree::addingEntity, this, &EntityScriptingInterface::addingEntity); - disconnect(_entityTree, &EntityTree::deletingEntity, this, &EntityScriptingInterface::deletingEntity); - disconnect(_entityTree, &EntityTree::clearingEntities, this, &EntityScriptingInterface::clearingEntities); + disconnect(_entityTree.get(), &EntityTree::addingEntity, this, &EntityScriptingInterface::addingEntity); + disconnect(_entityTree.get(), &EntityTree::deletingEntity, this, &EntityScriptingInterface::deletingEntity); + disconnect(_entityTree.get(), &EntityTree::clearingEntities, this, &EntityScriptingInterface::clearingEntities); } _entityTree = modelTree; if (_entityTree) { - connect(_entityTree, &EntityTree::addingEntity, this, &EntityScriptingInterface::addingEntity); - connect(_entityTree, &EntityTree::deletingEntity, this, &EntityScriptingInterface::deletingEntity); - connect(_entityTree, &EntityTree::clearingEntities, this, &EntityScriptingInterface::clearingEntities); + connect(_entityTree.get(), &EntityTree::addingEntity, this, &EntityScriptingInterface::addingEntity); + connect(_entityTree.get(), &EntityTree::deletingEntity, this, &EntityScriptingInterface::deletingEntity); + connect(_entityTree.get(), &EntityTree::clearingEntities, this, &EntityScriptingInterface::clearingEntities); } } @@ -280,7 +280,7 @@ RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionWorke RayToEntityIntersectionResult result; if (_entityTree) { - OctreeElement* element; + OctreeElementPointer element; EntityItemPointer intersectedEntity = NULL; result.intersects = _entityTree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face, (void**)&intersectedEntity, lockType, &result.accurate, diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index ff693e4585..50e30c4f37 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -23,6 +23,7 @@ #include "PolyVoxEntityItem.h" #include "LineEntityItem.h" #include "PolyLineEntityItem.h" +#include "EntityTree.h" #include "EntityEditPacketSender.h" @@ -60,8 +61,8 @@ public: virtual NodeType_t getServerNodeType() const { return NodeType::EntityServer; } virtual OctreeEditPacketSender* createPacketSender() { return new EntityEditPacketSender(); } - void setEntityTree(EntityTree* modelTree); - EntityTree* getEntityTree() { return _entityTree; } + void setEntityTree(EntityTreePointer modelTree); + EntityTreePointer getEntityTree() { return _entityTree; } public slots: @@ -178,7 +179,7 @@ private: RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType, bool precisionPicking); - EntityTree* _entityTree; + EntityTreePointer _entityTree; }; #endif // hifi_EntityScriptingInterface_h diff --git a/libraries/entities/src/EntitySimulation.cpp b/libraries/entities/src/EntitySimulation.cpp index 06f5023193..92c1ca2c3b 100644 --- a/libraries/entities/src/EntitySimulation.cpp +++ b/libraries/entities/src/EntitySimulation.cpp @@ -15,7 +15,7 @@ #include "EntitiesLogging.h" #include "MovingEntitiesOperator.h" -void EntitySimulation::setEntityTree(EntityTree* tree) { +void EntitySimulation::setEntityTree(EntityTreePointer tree) { if (_entityTree && _entityTree != tree) { _mortalEntities.clear(); _nextExpiry = quint64(-1); diff --git a/libraries/entities/src/EntitySimulation.h b/libraries/entities/src/EntitySimulation.h index c1822abe77..ec42499d5b 100644 --- a/libraries/entities/src/EntitySimulation.h +++ b/libraries/entities/src/EntitySimulation.h @@ -51,7 +51,7 @@ public: void unlock() { _mutex.unlock(); } /// \param tree pointer to EntityTree which is stored internally - void setEntityTree(EntityTree* tree); + void setEntityTree(EntityTreePointer tree); void updateEntities(); @@ -82,7 +82,7 @@ protected: // these only called by the EntityTree? public: - EntityTree* getEntityTree() { return _entityTree; } + EntityTreePointer getEntityTree() { return _entityTree; } void getEntitiesToDelete(VectorOfEntities& entitiesToDelete); @@ -106,7 +106,7 @@ protected: QMutex _mutex; // back pointer to EntityTree structure - EntityTree* _entityTree; + EntityTreePointer _entityTree; // We maintain multiple lists, each for its distinct purpose. // An entity may be in more than one list. diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index ba0e3f495f..3d2ebf046e 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -31,7 +31,6 @@ EntityTree::EntityTree(bool shouldReaverage) : _fbxService(NULL), _simulation(NULL) { - _rootElement = createNewElement(); resetClientEditStats(); } @@ -39,10 +38,19 @@ EntityTree::~EntityTree() { eraseAllOctreeElements(false); } -EntityTreeElement* EntityTree::createNewElement(unsigned char * octalCode) { - EntityTreeElement* newElement = new EntityTreeElement(octalCode); - newElement->setTree(this); - return newElement; +void EntityTree::createRootElement() { + _rootElement = createNewElement(); +} + +OctreeElementPointer EntityTree::createNewElement(unsigned char* octalCode) { + EntityTreeElementPointer newElement = EntityTreeElementPointer(new EntityTreeElement(octalCode), + // see comment int EntityTreeElement::createNewElement + [=](EntityTreeElement* elt) { + EntityTreeElementPointer tmpSharedPointer(elt); + elt->notifyDeleteHooks(); + }); + newElement->setTree(std::static_pointer_cast(shared_from_this())); + return std::static_pointer_cast(newElement); } void EntityTree::eraseAllOctreeElements(bool createNewRoot) { @@ -54,7 +62,7 @@ void EntityTree::eraseAllOctreeElements(bool createNewRoot) { _simulation->clearEntities(); _simulation->unlock(); } - foreach (EntityTreeElement* element, _entityToElementMap) { + foreach (EntityTreeElementPointer element, _entityToElementMap) { element->cleanupEntities(); } _entityToElementMap.clear(); @@ -90,7 +98,7 @@ void EntityTree::postAddEntity(EntityItemPointer entity) { } bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties, const SharedNodePointer& senderNode) { - EntityTreeElement* containingElement = getContainingElement(entityID); + EntityTreeElementPointer containingElement = getContainingElement(entityID); if (!containingElement) { return false; } @@ -104,7 +112,7 @@ bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProp } bool EntityTree::updateEntity(EntityItemPointer entity, const EntityItemProperties& properties, const SharedNodePointer& senderNode) { - EntityTreeElement* containingElement = getContainingElement(entity->getEntityItemID()); + EntityTreeElementPointer containingElement = getContainingElement(entity->getEntityItemID()); if (!containingElement) { return false; } @@ -112,7 +120,7 @@ bool EntityTree::updateEntity(EntityItemPointer entity, const EntityItemProperti } bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityItemProperties& origProperties, - EntityTreeElement* containingElement, const SharedNodePointer& senderNode) { + EntityTreeElementPointer containingElement, const SharedNodePointer& senderNode) { EntityItemProperties properties = origProperties; bool allowLockChange; @@ -139,7 +147,7 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI if (!wantsLocked) { EntityItemProperties tempProperties; tempProperties.setLocked(wantsLocked); - UpdateEntityOperator theOperator(this, containingElement, entity, tempProperties); + UpdateEntityOperator theOperator(getThisPointer(), containingElement, entity, tempProperties); recurseTreeWithOperator(&theOperator); _isDirty = true; } @@ -201,7 +209,7 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI quint64 entityScriptTimestampBefore = entity->getScriptTimestamp(); QString collisionSoundURLBefore = entity->getCollisionSoundURL(); uint32_t preFlags = entity->getDirtyFlags(); - UpdateEntityOperator theOperator(this, containingElement, entity, properties); + UpdateEntityOperator theOperator(getThisPointer(), containingElement, entity, properties); recurseTreeWithOperator(&theOperator); _isDirty = true; @@ -258,10 +266,10 @@ EntityItemPointer EntityTree::addEntity(const EntityItemID& entityID, const Enti } // You should not call this on existing entities that are already part of the tree! Call updateEntity() - EntityTreeElement* containingElement = getContainingElement(entityID); + EntityTreeElementPointer containingElement = getContainingElement(entityID); if (containingElement) { qCDebug(entities) << "UNEXPECTED!!! ----- don't call addEntity() on existing entity items. entityID=" << entityID - << "containingElement=" << containingElement; + << "containingElement=" << containingElement.get(); return result; } @@ -274,7 +282,7 @@ EntityItemPointer EntityTree::addEntity(const EntityItemID& entityID, const Enti result->recordCreationTime(); } // Recurse the tree and store the entity in the correct tree element - AddEntityOperator theOperator(this, result); + AddEntityOperator theOperator(getThisPointer(), result); recurseTreeWithOperator(&theOperator); postAddEntity(result); @@ -295,7 +303,7 @@ void EntityTree::maybeNotifyNewCollisionSoundURL(const QString& previousCollisio void EntityTree::setSimulation(EntitySimulation* simulation) { if (simulation) { // assert that the simulation's backpointer has already been properly connected - assert(simulation->getEntityTree() == this); + assert(simulation->getEntityTree().get() == this); } if (_simulation && _simulation != simulation) { // It's important to clearEntities() on the simulation since taht will update each @@ -308,7 +316,7 @@ void EntityTree::setSimulation(EntitySimulation* simulation) { } void EntityTree::deleteEntity(const EntityItemID& entityID, bool force, bool ignoreWarnings) { - EntityTreeElement* containingElement = getContainingElement(entityID); + EntityTreeElementPointer containingElement = getContainingElement(entityID); if (!containingElement) { if (!ignoreWarnings) { qCDebug(entities) << "UNEXPECTED!!!! EntityTree::deleteEntity() entityID doesn't exist!!! entityID=" << entityID; @@ -335,7 +343,7 @@ void EntityTree::deleteEntity(const EntityItemID& entityID, bool force, bool ign emit deletingEntity(entityID); // NOTE: callers must lock the tree before using this method - DeleteEntityOperator theOperator(this, entityID); + DeleteEntityOperator theOperator(getThisPointer(), entityID); recurseTreeWithOperator(&theOperator); processRemovedEntities(theOperator); _isDirty = true; @@ -343,9 +351,9 @@ void EntityTree::deleteEntity(const EntityItemID& entityID, bool force, bool ign void EntityTree::deleteEntities(QSet entityIDs, bool force, bool ignoreWarnings) { // NOTE: callers must lock the tree before using this method - DeleteEntityOperator theOperator(this); + DeleteEntityOperator theOperator(getThisPointer()); foreach(const EntityItemID& entityID, entityIDs) { - EntityTreeElement* containingElement = getContainingElement(entityID); + EntityTreeElementPointer containingElement = getContainingElement(entityID); if (!containingElement) { if (!ignoreWarnings) { qCDebug(entities) << "UNEXPECTED!!!! EntityTree::deleteEntities() entityID doesn't exist!!! entityID=" << entityID; @@ -418,9 +426,9 @@ public: }; -bool EntityTree::findNearPointOperation(OctreeElement* element, void* extraData) { +bool EntityTree::findNearPointOperation(OctreeElementPointer element, void* extraData) { FindNearPointArgs* args = static_cast(extraData); - EntityTreeElement* entityTreeElement = static_cast(element); + EntityTreeElementPointer entityTreeElement = std::static_pointer_cast(element); glm::vec3 penetration; bool sphereIntersection = entityTreeElement->getAACube().findSpherePenetration(args->position, args->targetRadius, penetration); @@ -470,14 +478,14 @@ public: }; -bool EntityTree::findInSphereOperation(OctreeElement* element, void* extraData) { +bool EntityTree::findInSphereOperation(OctreeElementPointer element, void* extraData) { FindAllNearPointArgs* args = static_cast(extraData); glm::vec3 penetration; bool sphereIntersection = element->getAACube().findSpherePenetration(args->position, args->targetRadius, penetration); // If this element contains the point, then search it... if (sphereIntersection) { - EntityTreeElement* entityTreeElement = static_cast(element); + EntityTreeElementPointer entityTreeElement = std::static_pointer_cast(element); entityTreeElement->getEntities(args->position, args->targetRadius, args->entities); return true; // keep searching in case children have closer entities } @@ -506,10 +514,10 @@ public: QVector _foundEntities; }; -bool EntityTree::findInCubeOperation(OctreeElement* element, void* extraData) { +bool EntityTree::findInCubeOperation(OctreeElementPointer element, void* extraData) { FindEntitiesInCubeArgs* args = static_cast(extraData); if (element->getAACube().touches(args->_cube)) { - EntityTreeElement* entityTreeElement = static_cast(element); + EntityTreeElementPointer entityTreeElement = std::static_pointer_cast(element); entityTreeElement->getEntities(args->_cube, args->_foundEntities); return true; } @@ -535,10 +543,10 @@ public: QVector _foundEntities; }; -bool EntityTree::findInBoxOperation(OctreeElement* element, void* extraData) { +bool EntityTree::findInBoxOperation(OctreeElementPointer element, void* extraData) { FindEntitiesInBoxArgs* args = static_cast(extraData); if (element->getAACube().touches(args->_box)) { - EntityTreeElement* entityTreeElement = static_cast(element); + EntityTreeElementPointer entityTreeElement = std::static_pointer_cast(element); entityTreeElement->getEntities(args->_box, args->_foundEntities); return true; } @@ -561,7 +569,7 @@ EntityItemPointer EntityTree::findEntityByID(const QUuid& id) { EntityItemPointer EntityTree::findEntityByEntityItemID(const EntityItemID& entityID) /*const*/ { EntityItemPointer foundEntity = NULL; - EntityTreeElement* containingElement = getContainingElement(entityID); + EntityTreeElementPointer containingElement = getContainingElement(entityID); if (containingElement) { foundEntity = containingElement->getEntityWithEntityItemID(entityID); } @@ -701,7 +709,7 @@ void EntityTree::removeNewlyCreatedHook(NewlyCreatedEntityHook* hook) { void EntityTree::releaseSceneEncodeData(OctreeElementExtraEncodeData* extraEncodeData) const { - foreach(void* extraData, *extraEncodeData) { + for (auto extraData : extraEncodeData->values()) { EntityTreeElementExtraEncodeData* thisExtraEncodeData = static_cast(extraData); delete thisExtraEncodeData; } @@ -932,13 +940,13 @@ int EntityTree::processEraseMessageDetails(const QByteArray& dataByteArray, cons return processedBytes; } -EntityTreeElement* EntityTree::getContainingElement(const EntityItemID& entityItemID) /*const*/ { +EntityTreeElementPointer EntityTree::getContainingElement(const EntityItemID& entityItemID) /*const*/ { // TODO: do we need to make this thread safe? Or is it acceptable as is - EntityTreeElement* element = _entityToElementMap.value(entityItemID); + EntityTreeElementPointer element = _entityToElementMap.value(entityItemID); return element; } -void EntityTree::setContainingElement(const EntityItemID& entityItemID, EntityTreeElement* element) { +void EntityTree::setContainingElement(const EntityItemID& entityItemID, EntityTreeElementPointer element) { // TODO: do we need to make this thread safe? Or is it acceptable as is if (element) { _entityToElementMap[entityItemID] = element; @@ -949,25 +957,25 @@ void EntityTree::setContainingElement(const EntityItemID& entityItemID, EntityTr void EntityTree::debugDumpMap() { qCDebug(entities) << "EntityTree::debugDumpMap() --------------------------"; - QHashIterator i(_entityToElementMap); + QHashIterator i(_entityToElementMap); while (i.hasNext()) { i.next(); - qCDebug(entities) << i.key() << ": " << i.value(); + qCDebug(entities) << i.key() << ": " << i.value().get(); } qCDebug(entities) << "-----------------------------------------------------"; } class ContentsDimensionOperator : public RecurseOctreeOperator { public: - virtual bool preRecursion(OctreeElement* element); - virtual bool postRecursion(OctreeElement* element) { return true; } + virtual bool preRecursion(OctreeElementPointer element); + virtual bool postRecursion(OctreeElementPointer element) { return true; } float getLargestDimension() const { return _contentExtents.largestDimension(); } private: Extents _contentExtents; }; -bool ContentsDimensionOperator::preRecursion(OctreeElement* element) { - EntityTreeElement* entityTreeElement = static_cast(element); +bool ContentsDimensionOperator::preRecursion(OctreeElementPointer element) { + EntityTreeElementPointer entityTreeElement = std::static_pointer_cast(element); entityTreeElement->expandExtentsToContents(_contentExtents); return true; } @@ -980,13 +988,13 @@ float EntityTree::getContentsLargestDimension() { class DebugOperator : public RecurseOctreeOperator { public: - virtual bool preRecursion(OctreeElement* element); - virtual bool postRecursion(OctreeElement* element) { return true; } + virtual bool preRecursion(OctreeElementPointer element); + virtual bool postRecursion(OctreeElementPointer element) { return true; } }; -bool DebugOperator::preRecursion(OctreeElement* element) { - EntityTreeElement* entityTreeElement = static_cast(element); - qCDebug(entities) << "EntityTreeElement [" << entityTreeElement << "]"; +bool DebugOperator::preRecursion(OctreeElementPointer element) { + EntityTreeElementPointer entityTreeElement = std::static_pointer_cast(element); + qCDebug(entities) << "EntityTreeElement [" << entityTreeElement.get() << "]"; entityTreeElement->debugDump(); return true; } @@ -998,12 +1006,12 @@ void EntityTree::dumpTree() { class PruneOperator : public RecurseOctreeOperator { public: - virtual bool preRecursion(OctreeElement* element) { return true; } - virtual bool postRecursion(OctreeElement* element); + virtual bool preRecursion(OctreeElementPointer element) { return true; } + virtual bool postRecursion(OctreeElementPointer element); }; -bool PruneOperator::postRecursion(OctreeElement* element) { - EntityTreeElement* entityTreeElement = static_cast(element); +bool PruneOperator::postRecursion(OctreeElementPointer element) { + EntityTreeElementPointer entityTreeElement = std::static_pointer_cast(element); entityTreeElement->pruneChildren(); return true; } @@ -1013,7 +1021,8 @@ void EntityTree::pruneTree() { recurseTreeWithOperator(&theOperator); } -QVector EntityTree::sendEntities(EntityEditPacketSender* packetSender, EntityTree* localTree, float x, float y, float z) { +QVector EntityTree::sendEntities(EntityEditPacketSender* packetSender, EntityTreePointer localTree, + float x, float y, float z) { SendEntitiesOperationArgs args; args.packetSender = packetSender; args.localTree = localTree; @@ -1026,9 +1035,9 @@ QVector EntityTree::sendEntities(EntityEditPacketSender* packetSen return newEntityIDs; } -bool EntityTree::sendEntitiesOperation(OctreeElement* element, void* extraData) { +bool EntityTree::sendEntitiesOperation(OctreeElementPointer element, void* extraData) { SendEntitiesOperationArgs* args = static_cast(extraData); - EntityTreeElement* entityTreeElement = static_cast(element); + EntityTreeElementPointer entityTreeElement = std::static_pointer_cast(element); const EntityItems& entities = entityTreeElement->getEntities(); for (int i = 0; i < entities.size(); i++) { @@ -1052,8 +1061,10 @@ bool EntityTree::sendEntitiesOperation(OctreeElement* element, void* extraData) return true; } -bool EntityTree::writeToMap(QVariantMap& entityDescription, OctreeElement* element, bool skipDefaultValues) { - entityDescription["Entities"] = QVariantList(); +bool EntityTree::writeToMap(QVariantMap& entityDescription, OctreeElementPointer element, bool skipDefaultValues) { + if (! entityDescription.contains("Entities")) { + entityDescription["Entities"] = QVariantList(); + } QScriptEngine scriptEngine; RecurseOctreeToMapOperator theOperator(entityDescription, element, &scriptEngine, skipDefaultValues); recurseTreeWithOperator(&theOperator); diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 4ade0afc6d..a813cd4846 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -17,6 +17,10 @@ #include +class EntityTree; +typedef std::shared_ptr EntityTreePointer; + + #include "EntityTreeElement.h" #include "DeleteEntityOperator.h" @@ -39,7 +43,7 @@ public: class SendEntitiesOperationArgs { public: glm::vec3 root; - EntityTree* localTree; + EntityTreePointer localTree; EntityEditPacketSender* packetSender; QVector* newEntityIDs; }; @@ -51,11 +55,18 @@ public: EntityTree(bool shouldReaverage = false); virtual ~EntityTree(); + void createRootElement(); + /// Implements our type specific root element factory - virtual EntityTreeElement* createNewElement(unsigned char * octalCode = NULL); + virtual OctreeElementPointer createNewElement(unsigned char* octalCode = NULL); /// Type safe version of getRoot() - EntityTreeElement* getRoot() { return static_cast(_rootElement); } + EntityTreeElementPointer getRoot() { + if (!_rootElement) { + createRootElement(); + } + return std::static_pointer_cast(_rootElement); + } virtual void eraseAllOctreeElements(bool createNewRoot = true); @@ -145,13 +156,14 @@ public: return _fbxService ? _fbxService->getModelForEntityItem(entityItem) : NULL; } - EntityTreeElement* getContainingElement(const EntityItemID& entityItemID) /*const*/; - void setContainingElement(const EntityItemID& entityItemID, EntityTreeElement* element); + EntityTreeElementPointer getContainingElement(const EntityItemID& entityItemID) /*const*/; + void setContainingElement(const EntityItemID& entityItemID, EntityTreeElementPointer element); void debugDumpMap(); virtual void dumpTree(); virtual void pruneTree(); - QVector sendEntities(EntityEditPacketSender* packetSender, EntityTree* localTree, float x, float y, float z); + QVector sendEntities(EntityEditPacketSender* packetSender, EntityTreePointer localTree, + float x, float y, float z); void entityChanged(EntityItemPointer entity); @@ -163,7 +175,7 @@ public: bool wantEditLogging() const { return _wantEditLogging; } void setWantEditLogging(bool value) { _wantEditLogging = value; } - bool writeToMap(QVariantMap& entityDescription, OctreeElement* element, bool skipDefaultValues); + bool writeToMap(QVariantMap& entityDescription, OctreeElementPointer element, bool skipDefaultValues); bool readFromMap(QVariantMap& entityDescription); float getContentsLargestDimension(); @@ -193,6 +205,8 @@ public: quint64 getMaxEditDelta() const { return _maxEditDelta; } quint64 getTotalTrackedEdits() const { return _totalTrackedEdits; } + EntityTreePointer getThisPointer() { return std::static_pointer_cast(shared_from_this()); } + signals: void deletingEntity(const EntityItemID& entityID); void addingEntity(const EntityItemID& entityID); @@ -204,13 +218,13 @@ private: void processRemovedEntities(const DeleteEntityOperator& theOperator); bool updateEntityWithElement(EntityItemPointer entity, const EntityItemProperties& properties, - EntityTreeElement* containingElement, + EntityTreeElementPointer containingElement, const SharedNodePointer& senderNode = SharedNodePointer(nullptr)); - static bool findNearPointOperation(OctreeElement* element, void* extraData); - static bool findInSphereOperation(OctreeElement* element, void* extraData); - static bool findInCubeOperation(OctreeElement* element, void* extraData); - static bool findInBoxOperation(OctreeElement* element, void* extraData); - static bool sendEntitiesOperation(OctreeElement* element, void* extraData); + static bool findNearPointOperation(OctreeElementPointer element, void* extraData); + static bool findInSphereOperation(OctreeElementPointer element, void* extraData); + static bool findInCubeOperation(OctreeElementPointer element, void* extraData); + static bool findInBoxOperation(OctreeElementPointer element, void* extraData); + static bool sendEntitiesOperation(OctreeElementPointer element, void* extraData); void notifyNewlyCreatedEntity(const EntityItem& newEntity, const SharedNodePointer& senderNode); @@ -221,7 +235,7 @@ private: QMultiMap _recentlyDeletedEntityItemIDs; EntityItemFBXService* _fbxService; - QHash _entityToElementMap; + QHash _entityToElementMap; EntitySimulation* _simulation; diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index a023f46c5e..536c3d6d9f 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -30,26 +30,46 @@ EntityTreeElement::~EntityTreeElement() { // This will be called primarily on addChildAt(), which means we're adding a child of our // own type to our own tree. This means we should initialize that child with any tree and type -// specific settings that our children must have. -OctreeElement* EntityTreeElement::createNewElement(unsigned char* octalCode) { - EntityTreeElement* newChild = new EntityTreeElement(octalCode); +// specific settings that our children must have. +OctreeElementPointer EntityTreeElement::createNewElement(unsigned char* octalCode) { + EntityTreeElementPointer newChild = + EntityTreeElementPointer(new EntityTreeElement(octalCode), + // This is a little bit horrible, but I haven't found a better way. The OctreeElement + // destructor used to call notifyDeleteHooks(), which calls zero or more of + // OctreeElementDeleteHook::elementDeleted + // which (now) expects an OctreeElementPointer argument. The destructor doesn't have + // access to the shared pointer (which has had its reference count drop to zero, + // or the destructor wouldn't have been called). The destructor also can't + // make a new shared pointer -- shared_from_this() is forbidden in a destructor, and + // using OctreeElementPointer(this) also fails. So, I've installed a custom deleter: + [=](EntityTreeElement* elt) { + // make a new shared pointer with a reference count of 1 (and no custom deleter) + EntityTreeElementPointer tmpSharedPointer(elt); + // call notifyDeleteHooks which will use shared_from_this() to get this same + // shared pointer, for use with the elementDeleted calls. + elt->notifyDeleteHooks(); + // And now tmpSharedPointer's reference count drops to zero and the + // normal destructors are called. + }); newChild->setTree(_myTree); return newChild; } + + void EntityTreeElement::init(unsigned char* octalCode) { OctreeElement::init(octalCode); _entityItems = new EntityItems; _octreeMemoryUsage += sizeof(EntityTreeElement); } -EntityTreeElement* EntityTreeElement::addChildAtIndex(int index) { - EntityTreeElement* newElement = (EntityTreeElement*)OctreeElement::addChildAtIndex(index); - newElement->setTree(_myTree); +OctreeElementPointer EntityTreeElement::addChildAtIndex(int index) { + OctreeElementPointer newElement = OctreeElement::addChildAtIndex(index); + std::static_pointer_cast(newElement)->setTree(_myTree); return newElement; } -void EntityTreeElement::debugExtraEncodeData(EncodeBitstreamParams& params) const { +void EntityTreeElement::debugExtraEncodeData(EncodeBitstreamParams& params) const { qCDebug(entities) << "EntityTreeElement::debugExtraEncodeData()... "; qCDebug(entities) << " element:" << _cube; @@ -57,15 +77,15 @@ void EntityTreeElement::debugExtraEncodeData(EncodeBitstreamParams& params) cons assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes if (extraEncodeData->contains(this)) { - EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData - = static_cast(extraEncodeData->value(this)); + EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData + = static_cast(extraEncodeData->value(this)); qCDebug(entities) << " encode data:" << entityTreeElementExtraEncodeData; } else { qCDebug(entities) << " encode data: MISSING!!"; } } -void EntityTreeElement::initializeExtraEncodeData(EncodeBitstreamParams& params) const { +void EntityTreeElement::initializeExtraEncodeData(EncodeBitstreamParams& params) { 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 @@ -73,7 +93,7 @@ void EntityTreeElement::initializeExtraEncodeData(EncodeBitstreamParams& params) EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData = new EntityTreeElementExtraEncodeData(); entityTreeElementExtraEncodeData->elementCompleted = (_entityItems->size() == 0); for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - EntityTreeElement* child = getChildAtIndex(i); + EntityTreeElementPointer child = getChildAtIndex(i); if (!child) { entityTreeElementExtraEncodeData->childCompleted[i] = true; // if no child exists, it is completed } else { @@ -94,7 +114,7 @@ void EntityTreeElement::initializeExtraEncodeData(EncodeBitstreamParams& params) } } -bool EntityTreeElement::shouldIncludeChildData(int childIndex, EncodeBitstreamParams& params) const { +bool EntityTreeElement::shouldIncludeChildData(int childIndex, EncodeBitstreamParams& params) const { OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData; assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes @@ -115,7 +135,7 @@ bool EntityTreeElement::shouldIncludeChildData(int childIndex, EncodeBitstreamPa } bool EntityTreeElement::shouldRecurseChildTree(int childIndex, EncodeBitstreamParams& params) const { - EntityTreeElement* childElement = getChildAtIndex(childIndex); + EntityTreeElementPointer childElement = getChildAtIndex(childIndex); if (childElement->alreadyFullyEncoded(params)) { return false; } @@ -176,24 +196,24 @@ void EntityTreeElement::elementEncodeComplete(EncodeBitstreamParams& params, Oct // 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 + // 1) our 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... + // 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 bool someChildTreeNotComplete = false; for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - EntityTreeElement* childElement = getChildAtIndex(i); + EntityTreeElementPointer childElement = getChildAtIndex(i); if (childElement) { // 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)) { + if (extraEncodeData->contains(childElement.get())) { EntityTreeElementExtraEncodeData* childExtraEncodeData - = static_cast(extraEncodeData->value(childElement)); - + = static_cast(extraEncodeData->value(childElement.get())); + if (wantDebug) { qCDebug(entities) << "checking child: " << childElement->_cube; qCDebug(entities) << " childElement->isLeaf():" << childElement->isLeaf(); @@ -243,7 +263,8 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData = NULL; bool hadElementExtraData = false; if (extraEncodeData && extraEncodeData->contains(this)) { - entityTreeElementExtraEncodeData = static_cast(extraEncodeData->value(this)); + entityTreeElementExtraEncodeData = + static_cast(extraEncodeData->value(this)); hadElementExtraData = true; } else { // if there wasn't one already, then create one @@ -251,14 +272,15 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData entityTreeElementExtraEncodeData->elementCompleted = (_entityItems->size() == 0); for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - EntityTreeElement* child = getChildAtIndex(i); + EntityTreeElementPointer child = getChildAtIndex(i); if (!child) { entityTreeElementExtraEncodeData->childCompleted[i] = true; // if no child exists, it is completed } else { if (child->hasEntities()) { entityTreeElementExtraEncodeData->childCompleted[i] = false; } else { - entityTreeElementExtraEncodeData->childCompleted[i] = true; // if the child doesn't have enities, it is completed + // if the child doesn't have enities, it is completed + entityTreeElementExtraEncodeData->childCompleted[i] = true; } } } @@ -300,7 +322,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData // we want to use the maximum possible box for this, so that we don't have to worry about the nuance of // simulation changing what's visible. consider the case where the entity contains an angular velocity - // the entity may not be in view and then in view a frame later, let the client side handle it's view + // the entity may not be in view and then in view a frame later, let the client side handle its view // frustum culling on rendering. AACube entityCube = entity->getMaximumAACube(); if (params.viewFrustum->cubeInFrustum(entityCube) == ViewFrustum::OUTSIDE) { @@ -322,8 +344,8 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData foreach (uint16_t i, indexesOfEntitiesToInclude) { EntityItemPointer entity = (*_entityItems)[i]; LevelDetails entityLevel = packetData->startLevel(); - OctreeElement::AppendState appendEntityState = entity->appendEntityData(packetData, - params, entityTreeElementExtraEncodeData); + OctreeElement::AppendState appendEntityState = + entity->appendEntityData(packetData, params, entityTreeElementExtraEncodeData); // If none of this entity data was able to be appended, then discard it // and don't include it in our entity count @@ -473,7 +495,7 @@ bool EntityTreeElement::bestFitBounds(const glm::vec3& minPoint, const glm::vec3 } bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking, float distanceToElementCube) { // only called if we do intersect our bounding cube, but find if we actually intersect with entities... @@ -671,7 +693,7 @@ bool EntityTreeElement::removeEntityWithEntityItemID(const EntityItemID& id) { bool EntityTreeElement::removeEntityItem(EntityItemPointer entity) { int numEntries = _entityItems->removeAll(entity); if (numEntries > 0) { - assert(entity->_element == this); + assert(entity->_element.get() == this); entity->_element = NULL; return true; } @@ -694,7 +716,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int ReadBitstreamToTreeParams& args) { // If we're the root, but this bitstream doesn't support root elements with data, then // return without reading any bytes - if (this == _myTree->getRoot() && args.bitstreamVersion < VERSION_ROOT_ELEMENT_HAS_DATA) { + if (this == _myTree->getRoot().get() && args.bitstreamVersion < VERSION_ROOT_ELEMENT_HAS_DATA) { return 0; } @@ -737,7 +759,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int QString entityScriptBefore = entityItem->getScript(); quint64 entityScriptTimestampBefore = entityItem->getScriptTimestamp(); bool bestFitBefore = bestFitEntityBounds(entityItem); - EntityTreeElement* currentContainingElement = _myTree->getContainingElement(entityItemID); + EntityTreeElementPointer currentContainingElement = _myTree->getContainingElement(entityItemID); bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args); if (entityItem->getDirtyFlags()) { @@ -746,13 +768,13 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int bool bestFitAfter = bestFitEntityBounds(entityItem); if (bestFitBefore != bestFitAfter) { - // This is the case where the entity existed, and is in some element in our tree... + // This is the case where the entity existed, and is in some element in our tree... if (!bestFitBefore && bestFitAfter) { // This is the case where the entity existed, and is in some element in our tree... - if (currentContainingElement != this) { + if (currentContainingElement.get() != this) { currentContainingElement->removeEntityItem(entityItem); addEntityItem(entityItem); - _myTree->setContainingElement(entityItemID, this); + _myTree->setContainingElement(entityItemID, getThisPointer()); } } } @@ -770,7 +792,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args); addEntityItem(entityItem); // add this new entity to this elements entities entityItemID = entityItem->getEntityItemID(); - _myTree->setContainingElement(entityItemID, this); + _myTree->setContainingElement(entityItemID, getThisPointer()); _myTree->postAddEntity(entityItem); if (entityItem->getCreated() == UNKNOWN_CREATED_TIME) { entityItem->recordCreationTime(); @@ -790,9 +812,9 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int void EntityTreeElement::addEntityItem(EntityItemPointer entity) { assert(entity); - assert(entity->_element == NULL); + assert(entity->_element == nullptr); _entityItems->push_back(entity); - entity->_element = this; + entity->_element = getThisPointer(); } // will average a "common reduced LOD view" from the the child elements... @@ -812,7 +834,7 @@ bool EntityTreeElement::collapseChildren() { bool EntityTreeElement::pruneChildren() { bool somethingPruned = false; for (int childIndex = 0; childIndex < NUMBER_OF_CHILDREN; childIndex++) { - EntityTreeElement* child = getChildAtIndex(childIndex); + EntityTreeElementPointer child = getChildAtIndex(childIndex); // if my child is a leaf, but has no entities, then it's safe to delete my child if (child && child->isLeaf() && !child->hasEntities()) { diff --git a/libraries/entities/src/EntityTreeElement.h b/libraries/entities/src/EntityTreeElement.h index 05d1904384..ca56e9b0fb 100644 --- a/libraries/entities/src/EntityTreeElement.h +++ b/libraries/entities/src/EntityTreeElement.h @@ -25,6 +25,7 @@ typedef QVector EntityItems; class EntityTree; class EntityTreeElement; +typedef std::shared_ptr EntityTreeElementPointer; class EntityTreeUpdateArgs { public: @@ -79,18 +80,20 @@ class EntityTreeElement : public OctreeElement { EntityTreeElement(unsigned char* octalCode = NULL); - virtual OctreeElement* createNewElement(unsigned char* octalCode = NULL); + virtual OctreeElementPointer createNewElement(unsigned char* octalCode = NULL); public: virtual ~EntityTreeElement(); // type safe versions of OctreeElement methods - EntityTreeElement* getChildAtIndex(int index) const { return (EntityTreeElement*)OctreeElement::getChildAtIndex(index); } + EntityTreeElementPointer getChildAtIndex(int index) const { + return std::static_pointer_cast(OctreeElement::getChildAtIndex(index)); + } // methods you can and should override to implement your tree functionality /// Adds a child to the current element. Override this if there is additional child initialization your class needs. - virtual EntityTreeElement* addChildAtIndex(int index); + virtual OctreeElementPointer addChildAtIndex(int index); /// Override this to implement LOD averaging on changes to the tree. virtual void calculateAverageFromChildren(); @@ -115,7 +118,7 @@ public: virtual bool requiresSplit() const { return false; } virtual void debugExtraEncodeData(EncodeBitstreamParams& params) const; - virtual void initializeExtraEncodeData(EncodeBitstreamParams& params) const; + virtual void initializeExtraEncodeData(EncodeBitstreamParams& params); virtual bool shouldIncludeChildData(int childIndex, EncodeBitstreamParams& params) const; virtual bool shouldRecurseChildTree(int childIndex, EncodeBitstreamParams& params) const; virtual void updateEncodedData(int childIndex, AppendState childAppendState, EncodeBitstreamParams& params) const; @@ -140,7 +143,7 @@ public: virtual bool canRayIntersect() const { return hasEntities(); } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking, float distanceToElementCube); virtual bool findSpherePenetration(const glm::vec3& center, float radius, @@ -151,8 +154,8 @@ public: bool hasEntities() const { return _entityItems ? _entityItems->size() > 0 : false; } - void setTree(EntityTree* tree) { _myTree = tree; } - EntityTree* getTree() const { return _myTree; } + void setTree(EntityTreePointer tree) { _myTree = tree; } + EntityTreePointer getTree() const { return _myTree; } bool updateEntity(const EntityItem& entity); void addEntityItem(EntityItemPointer entity); @@ -201,9 +204,19 @@ public: void expandExtentsToContents(Extents& extents); + EntityTreeElementPointer getThisPointer() { + return std::static_pointer_cast(shared_from_this()); + } + OctreeElementPointer getThisOctreeElementPointer() { + return std::static_pointer_cast(shared_from_this()); + } + const ConstOctreeElementPointer getConstThisOctreeElementPointer() const { + return std::static_pointer_cast(shared_from_this()); + } + protected: virtual void init(unsigned char * octalCode); - EntityTree* _myTree; + EntityTreePointer _myTree; EntityItems* _entityItems; }; diff --git a/libraries/entities/src/EntityTreeHeadlessViewer.cpp b/libraries/entities/src/EntityTreeHeadlessViewer.cpp index 80c0a7fa7f..fd1191b968 100644 --- a/libraries/entities/src/EntityTreeHeadlessViewer.cpp +++ b/libraries/entities/src/EntityTreeHeadlessViewer.cpp @@ -23,7 +23,7 @@ void EntityTreeHeadlessViewer::init() { OctreeHeadlessViewer::init(); if (!_simulation) { SimpleEntitySimulation* simpleSimulation = new SimpleEntitySimulation(); - EntityTree* entityTree = static_cast(_tree); + EntityTreePointer entityTree = std::static_pointer_cast(_tree); simpleSimulation->setEntityTree(entityTree); entityTree->setSimulation(simpleSimulation); _simulation = simpleSimulation; @@ -32,7 +32,7 @@ void EntityTreeHeadlessViewer::init() { void EntityTreeHeadlessViewer::update() { if (_tree) { - EntityTree* tree = static_cast(_tree); + EntityTreePointer tree = std::static_pointer_cast(_tree); if (tree->tryLockForWrite()) { tree->update(); tree->unlock(); @@ -41,5 +41,5 @@ void EntityTreeHeadlessViewer::update() { } void EntityTreeHeadlessViewer::processEraseMessage(NLPacket& packet, const SharedNodePointer& sourceNode) { - static_cast(_tree)->processEraseMessage(packet, sourceNode); + std::static_pointer_cast(_tree)->processEraseMessage(packet, sourceNode); } diff --git a/libraries/entities/src/EntityTreeHeadlessViewer.h b/libraries/entities/src/EntityTreeHeadlessViewer.h index a14fe14a71..da4ad0eace 100644 --- a/libraries/entities/src/EntityTreeHeadlessViewer.h +++ b/libraries/entities/src/EntityTreeHeadlessViewer.h @@ -36,14 +36,18 @@ public: void update(); - EntityTree* getTree() { return (EntityTree*)_tree; } + EntityTreePointer getTree() { return std::static_pointer_cast(_tree); } void processEraseMessage(NLPacket& packet, const SharedNodePointer& sourceNode); virtual void init(); protected: - virtual Octree* createTree() { return new EntityTree(true); } + virtual OctreePointer createTree() { + EntityTreePointer newTree = EntityTreePointer(new EntityTree(true)); + newTree->createRootElement(); + return newTree; + } EntitySimulation* _simulation; }; diff --git a/libraries/entities/src/LineEntityItem.h b/libraries/entities/src/LineEntityItem.h index 6d0f00ef04..3b7590a460 100644 --- a/libraries/entities/src/LineEntityItem.h +++ b/libraries/entities/src/LineEntityItem.h @@ -64,7 +64,7 @@ class LineEntityItem : public EntityItem { // never have a ray intersection pick a LineEntityItem. virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { return false; } virtual void debugDump() const; diff --git a/libraries/entities/src/MovingEntitiesOperator.cpp b/libraries/entities/src/MovingEntitiesOperator.cpp index 7dd1ab849c..0002ebb570 100644 --- a/libraries/entities/src/MovingEntitiesOperator.cpp +++ b/libraries/entities/src/MovingEntitiesOperator.cpp @@ -16,7 +16,7 @@ #include "MovingEntitiesOperator.h" -MovingEntitiesOperator::MovingEntitiesOperator(EntityTree* tree) : +MovingEntitiesOperator::MovingEntitiesOperator(EntityTreePointer tree) : _tree(tree), _changeTime(usecTimestampNow()), _foundOldCount(0), @@ -51,7 +51,7 @@ MovingEntitiesOperator::~MovingEntitiesOperator() { void MovingEntitiesOperator::addEntityToMoveList(EntityItemPointer entity, const AACube& newCube) { - EntityTreeElement* oldContainingElement = _tree->getContainingElement(entity->getEntityItemID()); + EntityTreeElementPointer oldContainingElement = _tree->getContainingElement(entity->getEntityItemID()); AABox newCubeClamped = newCube.clamp((float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE); if (_wantDebug) { @@ -109,7 +109,7 @@ void MovingEntitiesOperator::addEntityToMoveList(EntityItemPointer entity, const } // does this entity tree element contain the old entity -bool MovingEntitiesOperator::shouldRecurseSubTree(OctreeElement* element) { +bool MovingEntitiesOperator::shouldRecurseSubTree(OctreeElementPointer element) { bool containsEntity = false; // If we don't have an old entity, then we don't contain the entity, otherwise @@ -141,8 +141,8 @@ bool MovingEntitiesOperator::shouldRecurseSubTree(OctreeElement* element) { return containsEntity; } -bool MovingEntitiesOperator::preRecursion(OctreeElement* element) { - EntityTreeElement* entityTreeElement = static_cast(element); +bool MovingEntitiesOperator::preRecursion(OctreeElementPointer element) { + EntityTreeElementPointer entityTreeElement = std::static_pointer_cast(element); // In Pre-recursion, we're generally deciding whether or not we want to recurse this // path of the tree. For this operation, we want to recurse the branch of the tree if @@ -169,7 +169,7 @@ bool MovingEntitiesOperator::preRecursion(OctreeElement* element) { qCDebug(entities) << " entityTreeElement->bestFitBounds(details.newCube):" << entityTreeElement->bestFitBounds(details.newCube); qCDebug(entities) << " details.entity:" << details.entity->getEntityItemID(); qCDebug(entities) << " details.oldContainingElementCube:" << details.oldContainingElementCube; - qCDebug(entities) << " entityTreeElement:" << entityTreeElement; + qCDebug(entities) << " entityTreeElement:" << entityTreeElement.get(); qCDebug(entities) << " details.newCube:" << details.newCube; qCDebug(entities) << " details.newCubeClamped:" << details.newCubeClamped; qCDebug(entities) << " _lookingCount:" << _lookingCount; @@ -195,7 +195,7 @@ bool MovingEntitiesOperator::preRecursion(OctreeElement* element) { if (!details.newFound && entityTreeElement->bestFitBounds(details.newCube)) { EntityItemID entityItemID = details.entity->getEntityItemID(); // remove from the old before adding - EntityTreeElement* oldElement = details.entity->getElement(); + EntityTreeElementPointer oldElement = details.entity->getElement(); if (oldElement != entityTreeElement) { if (oldElement) { oldElement->removeEntityItem(details.entity); @@ -221,7 +221,7 @@ bool MovingEntitiesOperator::preRecursion(OctreeElement* element) { return keepSearching; // if we haven't yet found it, keep looking } -bool MovingEntitiesOperator::postRecursion(OctreeElement* element) { +bool MovingEntitiesOperator::postRecursion(OctreeElementPointer element) { // 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. @@ -254,14 +254,14 @@ bool MovingEntitiesOperator::postRecursion(OctreeElement* element) { } } if (!elementSubTreeContainsOldElements || !elementIsDirectParentOfOldElment) { - EntityTreeElement* entityTreeElement = static_cast(element); + EntityTreeElementPointer entityTreeElement = std::static_pointer_cast(element); entityTreeElement->pruneChildren(); // take this opportunity to prune any empty leaves } return keepSearching; // if we haven't yet found it, keep looking } -OctreeElement* MovingEntitiesOperator::possiblyCreateChildAt(OctreeElement* element, int childIndex) { +OctreeElementPointer MovingEntitiesOperator::possiblyCreateChildAt(OctreeElementPointer element, int childIndex) { // 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 locations. if (_foundNewCount < _lookingCount) { diff --git a/libraries/entities/src/MovingEntitiesOperator.h b/libraries/entities/src/MovingEntitiesOperator.h index bef17058f4..5d16c41543 100644 --- a/libraries/entities/src/MovingEntitiesOperator.h +++ b/libraries/entities/src/MovingEntitiesOperator.h @@ -18,7 +18,7 @@ public: AACube oldCube; // meters AACube newCube; // meters AABox newCubeClamped; // meters - EntityTreeElement* oldContainingElement; + EntityTreeElementPointer oldContainingElement; AACube oldContainingElementCube; // meters bool oldFound; bool newFound; @@ -34,22 +34,22 @@ inline bool operator==(const EntityToMoveDetails& a, const EntityToMoveDetails& class MovingEntitiesOperator : public RecurseOctreeOperator { public: - MovingEntitiesOperator(EntityTree* tree); + MovingEntitiesOperator(EntityTreePointer tree); ~MovingEntitiesOperator(); void addEntityToMoveList(EntityItemPointer entity, const AACube& newCube); - virtual bool preRecursion(OctreeElement* element); - virtual bool postRecursion(OctreeElement* element); - virtual OctreeElement* possiblyCreateChildAt(OctreeElement* element, int childIndex); + virtual bool preRecursion(OctreeElementPointer element); + virtual bool postRecursion(OctreeElementPointer element); + virtual OctreeElementPointer possiblyCreateChildAt(OctreeElementPointer element, int childIndex); bool hasMovingEntities() const { return _entitiesToMove.size() > 0; } private: - EntityTree* _tree; + EntityTreePointer _tree; QSet _entitiesToMove; quint64 _changeTime; int _foundOldCount; int _foundNewCount; int _lookingCount; - bool shouldRecurseSubTree(OctreeElement* element); + bool shouldRecurseSubTree(OctreeElementPointer element); bool _wantDebug; }; diff --git a/libraries/entities/src/PolyLineEntityItem.h b/libraries/entities/src/PolyLineEntityItem.h index 25b348fa55..e5fdcf9b78 100644 --- a/libraries/entities/src/PolyLineEntityItem.h +++ b/libraries/entities/src/PolyLineEntityItem.h @@ -73,7 +73,7 @@ class PolyLineEntityItem : public EntityItem { // never have a ray intersection pick a PolyLineEntityItem. virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { return false; } virtual void debugDump() const; diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index 20a0646c9b..31906a9cc0 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -44,7 +44,7 @@ class PolyVoxEntityItem : public EntityItem { // never have a ray intersection pick a PolyVoxEntityItem. virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { return false; } virtual void debugDump() const; diff --git a/libraries/entities/src/RecurseOctreeToMapOperator.cpp b/libraries/entities/src/RecurseOctreeToMapOperator.cpp index 167e3513c1..a249262b2b 100644 --- a/libraries/entities/src/RecurseOctreeToMapOperator.cpp +++ b/libraries/entities/src/RecurseOctreeToMapOperator.cpp @@ -13,8 +13,8 @@ RecurseOctreeToMapOperator::RecurseOctreeToMapOperator(QVariantMap& map, - OctreeElement *top, - QScriptEngine *engine, + OctreeElementPointer top, + QScriptEngine* engine, bool skipDefaultValues) : RecurseOctreeOperator(), _map(map), @@ -22,7 +22,7 @@ RecurseOctreeToMapOperator::RecurseOctreeToMapOperator(QVariantMap& map, _engine(engine), _skipDefaultValues(skipDefaultValues) { - // if some element "top" was given, only save information for that element and it's children. + // if some element "top" was given, only save information for that element and its children. if (_top) { _withinTop = false; } else { @@ -31,18 +31,15 @@ RecurseOctreeToMapOperator::RecurseOctreeToMapOperator(QVariantMap& map, } }; -bool RecurseOctreeToMapOperator::preRecursion(OctreeElement* element) { +bool RecurseOctreeToMapOperator::preRecursion(OctreeElementPointer element) { if (element == _top) { _withinTop = true; } return true; } -bool RecurseOctreeToMapOperator::postRecursion(OctreeElement* element) { - - EntityItemProperties defaultProperties; - - EntityTreeElement* entityTreeElement = static_cast(element); +bool RecurseOctreeToMapOperator::postRecursion(OctreeElementPointer element) { + EntityTreeElementPointer entityTreeElement = std::static_pointer_cast(element); const EntityItems& entities = entityTreeElement->getEntities(); QVariantList entitiesQList = qvariant_cast(_map["Entities"]); diff --git a/libraries/entities/src/RecurseOctreeToMapOperator.h b/libraries/entities/src/RecurseOctreeToMapOperator.h index bfa5024b09..35c7f1b6a9 100644 --- a/libraries/entities/src/RecurseOctreeToMapOperator.h +++ b/libraries/entities/src/RecurseOctreeToMapOperator.h @@ -13,13 +13,13 @@ class RecurseOctreeToMapOperator : public RecurseOctreeOperator { public: - RecurseOctreeToMapOperator(QVariantMap& map, OctreeElement *top, QScriptEngine *engine, bool skipDefaultValues); - bool preRecursion(OctreeElement* element); - bool postRecursion(OctreeElement* element); + RecurseOctreeToMapOperator(QVariantMap& map, OctreeElementPointer top, QScriptEngine* engine, bool skipDefaultValues); + bool preRecursion(OctreeElementPointer element); + bool postRecursion(OctreeElementPointer element); private: QVariantMap& _map; - OctreeElement *_top; - QScriptEngine *_engine; + OctreeElementPointer _top; + QScriptEngine* _engine; bool _withinTop; bool _skipDefaultValues; }; diff --git a/libraries/entities/src/SphereEntityItem.cpp b/libraries/entities/src/SphereEntityItem.cpp index c77a513cfc..48eb5e01f7 100644 --- a/libraries/entities/src/SphereEntityItem.cpp +++ b/libraries/entities/src/SphereEntityItem.cpp @@ -94,8 +94,9 @@ void SphereEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBi } bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, - void** intersectedObject, bool precisionPicking) const { + bool& keepSearching, OctreeElementPointer& element, + float& distance, BoxFace& face, + void** intersectedObject, bool precisionPicking) const { // determine the ray in the frame of the entity transformed from a unit sphere glm::mat4 entityToWorldMatrix = getEntityToWorldMatrix(); glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); diff --git a/libraries/entities/src/SphereEntityItem.h b/libraries/entities/src/SphereEntityItem.h index 94c1d77096..3b29a3a1f5 100644 --- a/libraries/entities/src/SphereEntityItem.h +++ b/libraries/entities/src/SphereEntityItem.h @@ -54,7 +54,7 @@ public: virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const; virtual void debugDump() const; diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index 3ab15ba6cb..61730b208c 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -129,7 +129,7 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits } bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { glm::vec3 dimensions = getDimensions(); glm::vec2 xyDimensions(dimensions.x, dimensions.y); diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index bf03c192c7..a659f3c39b 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -47,7 +47,7 @@ public: virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const; static const QString DEFAULT_TEXT; diff --git a/libraries/entities/src/UpdateEntityOperator.cpp b/libraries/entities/src/UpdateEntityOperator.cpp index 991d725f97..5d6f3986b2 100644 --- a/libraries/entities/src/UpdateEntityOperator.cpp +++ b/libraries/entities/src/UpdateEntityOperator.cpp @@ -16,14 +16,14 @@ #include "UpdateEntityOperator.h" -UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree, - EntityTreeElement* containingElement, - EntityItemPointer existingEntity, +UpdateEntityOperator::UpdateEntityOperator(EntityTreePointer tree, + EntityTreeElementPointer containingElement, + EntityItemPointer existingEntity, const EntityItemProperties& properties) : _tree(tree), _existingEntity(existingEntity), _containingElement(containingElement), - _containingElementCube(containingElement->getAACube()), + _containingElementCube(containingElement->getAACube()), _properties(properties), _entityItemID(existingEntity->getEntityItemID()), _foundOld(false), @@ -37,10 +37,10 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree, { // caller must have verified existence of containingElement and oldEntity assert(_containingElement && _existingEntity); - + if (_wantDebug) { qCDebug(entities) << "UpdateEntityOperator::UpdateEntityOperator() -----------------------------"; - } + } // Here we have a choice to make, do we want to "tight fit" the actual minimum for the // entity into the the element, or do we want to use the entities "relaxed" bounds @@ -144,7 +144,7 @@ UpdateEntityOperator::~UpdateEntityOperator() { // does this entity tree element contain the old entity -bool UpdateEntityOperator::subTreeContainsOldEntity(OctreeElement* element) { +bool UpdateEntityOperator::subTreeContainsOldEntity(OctreeElementPointer element) { // 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 @@ -162,7 +162,7 @@ bool UpdateEntityOperator::subTreeContainsOldEntity(OctreeElement* element) { return elementContainsOldBox; } -bool UpdateEntityOperator::subTreeContainsNewEntity(OctreeElement* element) { +bool UpdateEntityOperator::subTreeContainsNewEntity(OctreeElementPointer element) { bool elementContainsNewBox = element->getAACube().contains(_newEntityBox); if (_wantDebug) { @@ -179,8 +179,8 @@ bool UpdateEntityOperator::subTreeContainsNewEntity(OctreeElement* element) { } -bool UpdateEntityOperator::preRecursion(OctreeElement* element) { - EntityTreeElement* entityTreeElement = static_cast(element); +bool UpdateEntityOperator::preRecursion(OctreeElementPointer element) { + EntityTreeElementPointer entityTreeElement = std::static_pointer_cast(element); // In Pre-recursion, we're generally deciding whether or not we want to recurse this // path of the tree. For this operation, we want to recurse the branch of the tree if @@ -211,8 +211,8 @@ bool UpdateEntityOperator::preRecursion(OctreeElement* element) { if (_wantDebug) { qCDebug(entities) << " OLD TREE CASE...."; - qCDebug(entities) << " entityTreeElement=" << entityTreeElement; - qCDebug(entities) << " _containingElement=" << _containingElement; + qCDebug(entities) << " entityTreeElement=" << entityTreeElement.get(); + qCDebug(entities) << " _containingElement=" << _containingElement.get(); } // If this is the element we're looking for, then ask it to remove the old entity @@ -234,7 +234,7 @@ bool UpdateEntityOperator::preRecursion(OctreeElement* element) { // the entity knows what element it's in, so we remove it from that one // NOTE: we know we haven't yet added it to its new element because _removeOld is true - EntityTreeElement* oldElement = _existingEntity->getElement(); + EntityTreeElementPointer oldElement = _existingEntity->getElement(); oldElement->removeEntityItem(_existingEntity); _tree->setContainingElement(_entityItemID, NULL); @@ -260,8 +260,8 @@ bool UpdateEntityOperator::preRecursion(OctreeElement* element) { if (_wantDebug) { qCDebug(entities) << " NEW TREE CASE...."; - qCDebug(entities) << " entityTreeElement=" << entityTreeElement; - qCDebug(entities) << " _containingElement=" << _containingElement; + qCDebug(entities) << " entityTreeElement=" << entityTreeElement.get(); + qCDebug(entities) << " _containingElement=" << _containingElement.get(); qCDebug(entities) << " entityTreeElement->bestFitBounds(_newEntityBox)=" << entityTreeElement->bestFitBounds(_newEntityBox); } @@ -272,7 +272,7 @@ bool UpdateEntityOperator::preRecursion(OctreeElement* element) { qCDebug(entities) << " *** THIS ELEMENT IS BEST FIT ***"; } - EntityTreeElement* oldElement = _existingEntity->getElement(); + EntityTreeElementPointer oldElement = _existingEntity->getElement(); // if we are the existing containing element, then we can just do the update of the entity properties if (entityTreeElement == oldElement) { @@ -317,7 +317,7 @@ bool UpdateEntityOperator::preRecursion(OctreeElement* element) { return keepSearching; // if we haven't yet found it, keep looking } -bool UpdateEntityOperator::postRecursion(OctreeElement* element) { +bool UpdateEntityOperator::postRecursion(OctreeElementPointer element) { // 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. @@ -342,14 +342,14 @@ bool UpdateEntityOperator::postRecursion(OctreeElement* element) { // 2) we are removing the old, but this subtree doesn't contain the old // 3) we are removing the old, this subtree contains the old, but this element isn't a direct parent of _containingElement if (!_removeOld || !subtreeContainsOld || !element->isParentOf(_containingElement)) { - EntityTreeElement* entityTreeElement = static_cast(element); + EntityTreeElementPointer entityTreeElement = std::static_pointer_cast(element); entityTreeElement->pruneChildren(); // take this opportunity to prune any empty leaves } return keepSearching; // if we haven't yet found it, keep looking } -OctreeElement* UpdateEntityOperator::possiblyCreateChildAt(OctreeElement* element, int childIndex) { +OctreeElementPointer UpdateEntityOperator::possiblyCreateChildAt(OctreeElementPointer element, int childIndex) { // 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 diff --git a/libraries/entities/src/UpdateEntityOperator.h b/libraries/entities/src/UpdateEntityOperator.h index 5091ef4c5d..f1c791f9f1 100644 --- a/libraries/entities/src/UpdateEntityOperator.h +++ b/libraries/entities/src/UpdateEntityOperator.h @@ -14,17 +14,17 @@ class UpdateEntityOperator : public RecurseOctreeOperator { public: - UpdateEntityOperator(EntityTree* tree, EntityTreeElement* containingElement, - EntityItemPointer existingEntity, const EntityItemProperties& properties); + UpdateEntityOperator(EntityTreePointer tree, EntityTreeElementPointer containingElement, + EntityItemPointer existingEntity, const EntityItemProperties& properties); ~UpdateEntityOperator(); - - virtual bool preRecursion(OctreeElement* element); - virtual bool postRecursion(OctreeElement* element); - virtual OctreeElement* possiblyCreateChildAt(OctreeElement* element, int childIndex); + + virtual bool preRecursion(OctreeElementPointer element); + virtual bool postRecursion(OctreeElementPointer element); + virtual OctreeElementPointer possiblyCreateChildAt(OctreeElementPointer element, int childIndex); private: - EntityTree* _tree; + EntityTreePointer _tree; EntityItemPointer _existingEntity; - EntityTreeElement* _containingElement; + EntityTreeElementPointer _containingElement; AACube _containingElementCube; // we temporarily store our cube here in case we need to delete the containing element EntityItemProperties _properties; EntityItemID _entityItemID; @@ -40,8 +40,8 @@ private: AABox _oldEntityBox; // clamped to domain AABox _newEntityBox; // clamped to domain - bool subTreeContainsOldEntity(OctreeElement* element); - bool subTreeContainsNewEntity(OctreeElement* element); + bool subTreeContainsOldEntity(OctreeElementPointer element); + bool subTreeContainsNewEntity(OctreeElementPointer element); bool _wantDebug; }; diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index c3dc757199..041022a916 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -99,7 +99,7 @@ void WebEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitst } bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { glm::vec3 dimensions = getDimensions(); glm::vec2 xyDimensions(dimensions.x, dimensions.y); diff --git a/libraries/entities/src/WebEntityItem.h b/libraries/entities/src/WebEntityItem.h index d98eab8d24..24e19e1cb1 100644 --- a/libraries/entities/src/WebEntityItem.h +++ b/libraries/entities/src/WebEntityItem.h @@ -46,7 +46,7 @@ public: virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const; virtual void setSourceUrl(const QString& value); diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp index fb8ec325a3..fed85bf6a5 100644 --- a/libraries/entities/src/ZoneEntityItem.cpp +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -246,7 +246,7 @@ void ZoneEntityItem::setCompoundShapeURL(const QString& url) { } bool ZoneEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const { return _zonesArePickable; diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h index 1aa3f3e13a..e112103529 100644 --- a/libraries/entities/src/ZoneEntityItem.h +++ b/libraries/entities/src/ZoneEntityItem.h @@ -15,7 +15,8 @@ #include #include "AtmospherePropertyGroup.h" -#include "EntityItem.h" +#include "EntityItem.h" +#include "EntityTree.h" class ZoneEntityItem : public EntityItem { public: @@ -99,7 +100,7 @@ public: virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const; virtual void debugDump() const; @@ -129,6 +130,8 @@ protected: static bool _drawZoneBoundaries; static bool _zonesArePickable; + + EntityTreePointer subTree; }; #endif // hifi_ZoneEntityItem_h diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 93933c5301..e7f265b4f2 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -71,6 +71,44 @@ Octree::~Octree() { eraseAllOctreeElements(false); } + +// Inserts the value and key into three arrays sorted by the key array, the first array is the value, +// the second array is a sorted key for the value, the third array is the index for the value in it original +// non-sorted array +// returns -1 if size exceeded +// originalIndexArray is optional +int insertOctreeElementIntoSortedArrays(OctreeElementPointer value, float key, int originalIndex, + OctreeElementPointer* valueArray, float* keyArray, int* originalIndexArray, + int currentCount, int maxCount) { + + if (currentCount < maxCount) { + int i = 0; + if (currentCount > 0) { + while (i < currentCount && key > keyArray[i]) { + i++; + } + // i is our desired location + // shift array elements to the right + if (i < currentCount && i+1 < maxCount) { + for (int j = currentCount - 1; j > i; j--) { + valueArray[j] = valueArray[j - 1]; + keyArray[j] = keyArray[j - 1]; + } + } + } + // place new element at i + valueArray[i] = value; + keyArray[i] = key; + if (originalIndexArray) { + originalIndexArray[i] = originalIndex; + } + return currentCount + 1; + } + return -1; // error case +} + + + // Recurses voxel tree calling the RecurseOctreeOperation function for each element. // stops recursion if operation function returns false. void Octree::recurseTreeWithOperation(RecurseOctreeOperation operation, void* extraData) { @@ -83,7 +121,7 @@ void Octree::recurseTreeWithPostOperation(RecurseOctreeOperation operation, void } // Recurses voxel element with an operation function -void Octree::recurseElementWithOperation(OctreeElement* element, RecurseOctreeOperation operation, void* extraData, +void Octree::recurseElementWithOperation(OctreeElementPointer element, RecurseOctreeOperation operation, void* extraData, int recursionCount) { if (recursionCount > DANGEROUSLY_DEEP_RECURSION) { static QString repeatedMessage @@ -96,7 +134,7 @@ void Octree::recurseElementWithOperation(OctreeElement* element, RecurseOctreeOp if (operation(element, extraData)) { for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - OctreeElement* child = element->getChildAtIndex(i); + OctreeElementPointer child = element->getChildAtIndex(i); if (child) { recurseElementWithOperation(child, operation, extraData, recursionCount+1); } @@ -105,8 +143,8 @@ void Octree::recurseElementWithOperation(OctreeElement* element, RecurseOctreeOp } // Recurses voxel element with an operation function -void Octree::recurseElementWithPostOperation(OctreeElement* element, RecurseOctreeOperation operation, void* extraData, - int recursionCount) { +void Octree::recurseElementWithPostOperation(OctreeElementPointer element, RecurseOctreeOperation operation, + void* extraData, int recursionCount) { if (recursionCount > DANGEROUSLY_DEEP_RECURSION) { static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex( @@ -117,7 +155,7 @@ void Octree::recurseElementWithPostOperation(OctreeElement* element, RecurseOctr } for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - OctreeElement* child = element->getChildAtIndex(i); + OctreeElementPointer child = element->getChildAtIndex(i); if (child) { recurseElementWithPostOperation(child, operation, extraData, recursionCount+1); } @@ -134,7 +172,7 @@ void Octree::recurseTreeWithOperationDistanceSorted(RecurseOctreeOperation opera } // Recurses voxel element with an operation function -void Octree::recurseElementWithOperationDistanceSorted(OctreeElement* element, RecurseOctreeOperation operation, +void Octree::recurseElementWithOperationDistanceSorted(OctreeElementPointer element, RecurseOctreeOperation operation, const glm::vec3& point, void* extraData, int recursionCount) { if (recursionCount > DANGEROUSLY_DEEP_RECURSION) { @@ -148,24 +186,24 @@ void Octree::recurseElementWithOperationDistanceSorted(OctreeElement* element, R if (operation(element, extraData)) { // determine the distance sorted order of our children - OctreeElement* sortedChildren[NUMBER_OF_CHILDREN] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + OctreeElementPointer sortedChildren[NUMBER_OF_CHILDREN] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; float distancesToChildren[NUMBER_OF_CHILDREN] = { 0, 0, 0, 0, 0, 0, 0, 0 }; int indexOfChildren[NUMBER_OF_CHILDREN] = { 0, 0, 0, 0, 0, 0, 0, 0 }; int currentCount = 0; for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - OctreeElement* childElement = element->getChildAtIndex(i); + OctreeElementPointer childElement = element->getChildAtIndex(i); if (childElement) { // chance to optimize, doesn't need to be actual distance!! Could be distance squared float distanceSquared = childElement->distanceSquareToPoint(point); - currentCount = insertIntoSortedArrays((void*)childElement, distanceSquared, i, - (void**)&sortedChildren, (float*)&distancesToChildren, - (int*)&indexOfChildren, currentCount, NUMBER_OF_CHILDREN); + currentCount = insertOctreeElementIntoSortedArrays(childElement, distanceSquared, i, + sortedChildren, (float*)&distancesToChildren, + (int*)&indexOfChildren, currentCount, NUMBER_OF_CHILDREN); } } for (int i = 0; i < currentCount; i++) { - OctreeElement* childElement = sortedChildren[i]; + OctreeElementPointer childElement = sortedChildren[i]; if (childElement) { recurseElementWithOperationDistanceSorted(childElement, operation, point, extraData); } @@ -177,7 +215,8 @@ void Octree::recurseTreeWithOperator(RecurseOctreeOperator* operatorObject) { recurseElementWithOperator(_rootElement, operatorObject); } -bool Octree::recurseElementWithOperator(OctreeElement* element, RecurseOctreeOperator* operatorObject, int recursionCount) { +bool Octree::recurseElementWithOperator(OctreeElementPointer element, + RecurseOctreeOperator* operatorObject, int recursionCount) { if (recursionCount > DANGEROUSLY_DEEP_RECURSION) { static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex( @@ -189,7 +228,7 @@ bool Octree::recurseElementWithOperator(OctreeElement* element, RecurseOctreeOpe if (operatorObject->preRecursion(element)) { for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - OctreeElement* child = element->getChildAtIndex(i); + OctreeElementPointer child = element->getChildAtIndex(i); // If there is no child at that location, the Operator may want to create a child at that location. // So give the operator a chance to do so.... @@ -209,8 +248,8 @@ bool Octree::recurseElementWithOperator(OctreeElement* element, RecurseOctreeOpe } -OctreeElement* Octree::nodeForOctalCode(OctreeElement* ancestorElement, - const unsigned char* needleCode, OctreeElement** parentOfFoundElement) const { +OctreeElementPointer Octree::nodeForOctalCode(OctreeElementPointer ancestorElement, const unsigned char* needleCode, + OctreeElementPointer* parentOfFoundElement) const { // special case for NULL octcode if (!needleCode) { return _rootElement; @@ -219,7 +258,7 @@ OctreeElement* Octree::nodeForOctalCode(OctreeElement* ancestorElement, // find the appropriate branch index based on this ancestorElement if (*needleCode > 0) { int branchForNeedle = branchIndexWithDescendant(ancestorElement->getOctalCode(), needleCode); - OctreeElement* childElement = ancestorElement->getChildAtIndex(branchForNeedle); + OctreeElementPointer childElement = ancestorElement->getChildAtIndex(branchForNeedle); if (childElement) { if (*childElement->getOctalCode() == *needleCode) { @@ -245,7 +284,8 @@ OctreeElement* Octree::nodeForOctalCode(OctreeElement* ancestorElement, } // returns the element created! -OctreeElement* Octree::createMissingElement(OctreeElement* lastParentElement, const unsigned char* codeToReach, int recursionCount) { +OctreeElementPointer Octree::createMissingElement(OctreeElementPointer lastParentElement, + const unsigned char* codeToReach, int recursionCount) { if (recursionCount > DANGEROUSLY_DEEP_RECURSION) { static QString repeatedMessage @@ -274,7 +314,7 @@ OctreeElement* Octree::createMissingElement(OctreeElement* lastParentElement, co } } -int Octree::readElementData(OctreeElement* destinationElement, const unsigned char* nodeData, int bytesAvailable, +int Octree::readElementData(OctreeElementPointer destinationElement, const unsigned char* nodeData, int bytesAvailable, ReadBitstreamToTreeParams& args) { int bytesLeftToRead = bytesAvailable; @@ -305,7 +345,7 @@ int Octree::readElementData(OctreeElement* destinationElement, const unsigned ch if (oneAtBit(colorInPacketMask, i)) { // addChildAtIndex() should actually be called getOrAddChildAtIndex(). // When it adds the child it automatically sets the detinationElement dirty. - OctreeElement* childElementAt = destinationElement->addChildAtIndex(i); + OctreeElementPointer childElementAt = destinationElement->addChildAtIndex(i); int childElementDataRead = childElementAt->readElementDataFromBuffer(nodeData + bytesRead, bytesLeftToRead, args); childElementAt->setSourceUUID(args.sourceUUID); @@ -405,7 +445,8 @@ void Octree::readBitstreamToTree(const unsigned char * bitstream, unsigned long // if there are more bytes after that, it's assumed to be another root relative tree while (bitstreamAt < bitstream + bufferSizeBytes) { - OctreeElement* bitstreamRootElement = nodeForOctalCode(args.destinationElement, (unsigned char *)bitstreamAt, NULL); + OctreeElementPointer bitstreamRootElement = nodeForOctalCode(args.destinationElement, + (unsigned char *)bitstreamAt, NULL); int numberOfThreeBitSectionsInStream = numberOfThreeBitSectionsInCode(bitstreamAt, bufferSizeBytes); if (numberOfThreeBitSectionsInStream > UNREASONABLY_DEEP_RECURSION) { static QString repeatedMessage @@ -491,7 +532,7 @@ void Octree::deleteOctalCodeFromTree(const unsigned char* codeBuffer, bool colla deleteOctalCodeFromTreeRecursion(_rootElement, &args); } -void Octree::deleteOctalCodeFromTreeRecursion(OctreeElement* element, void* extraData) { +void Octree::deleteOctalCodeFromTreeRecursion(OctreeElementPointer element, void* extraData) { DeleteOctalCodeFromTreeArgs* args = (DeleteOctalCodeFromTreeArgs*)extraData; int lengthOfElementCode = numberOfThreeBitSectionsInCode(element->getOctalCode()); @@ -508,14 +549,14 @@ void Octree::deleteOctalCodeFromTreeRecursion(OctreeElement* element, void* extr // Ok, we know we haven't reached our target element yet, so keep looking int childIndex = branchIndexWithDescendant(element->getOctalCode(), args->codeBuffer); - OctreeElement* childElement = element->getChildAtIndex(childIndex); + OctreeElementPointer childElement = element->getChildAtIndex(childIndex); // If there is no child at the target location, and the current parent element is a colored leaf, // then it means we were asked to delete a child out of a larger leaf voxel. // We support this by breaking up the parent voxel into smaller pieces. if (!childElement && element->requiresSplit()) { // we need to break up ancestors until we get to the right level - OctreeElement* ancestorElement = element; + OctreeElementPointer ancestorElement = element; while (true) { int index = branchIndexWithDescendant(ancestorElement->getOctalCode(), args->codeBuffer); @@ -576,23 +617,22 @@ void Octree::deleteOctalCodeFromTreeRecursion(OctreeElement* element, void* extr // If the lower level did some work, then we need to let this element know, so it can // do any bookkeeping it wants to, like color re-averaging, time stamp marking, etc if (args->pathChanged) { - element->handleSubtreeChanged(this); + element->handleSubtreeChanged(shared_from_this()); } } void Octree::eraseAllOctreeElements(bool createNewRoot) { - delete _rootElement; // this will recurse and delete all children - _rootElement = NULL; - if (createNewRoot) { _rootElement = createNewElement(); + } else { + _rootElement.reset(); // this will recurse and delete all children } _isDirty = true; } // Note: this is an expensive call. Don't call it unless you really need to reaverage the entire tree (from startElement) -void Octree::reaverageOctreeElements(OctreeElement* startElement) { +void Octree::reaverageOctreeElements(OctreeElementPointer startElement) { if (!startElement) { startElement = getRoot(); } @@ -628,9 +668,9 @@ void Octree::reaverageOctreeElements(OctreeElement* startElement) { } } -OctreeElement* Octree::getOctreeElementAt(float x, float y, float z, float s) const { +OctreeElementPointer Octree::getOctreeElementAt(float x, float y, float z, float s) const { unsigned char* octalCode = pointToOctalCode(x,y,z,s); - OctreeElement* element = nodeForOctalCode(_rootElement, octalCode, NULL); + OctreeElementPointer element = nodeForOctalCode(_rootElement, octalCode, NULL); if (*element->getOctalCode() != *octalCode) { element = NULL; } @@ -638,20 +678,20 @@ OctreeElement* Octree::getOctreeElementAt(float x, float y, float z, float s) co return element; } -OctreeElement* Octree::getOctreeEnclosingElementAt(float x, float y, float z, float s) const { +OctreeElementPointer Octree::getOctreeEnclosingElementAt(float x, float y, float z, float s) const { unsigned char* octalCode = pointToOctalCode(x,y,z,s); - OctreeElement* element = nodeForOctalCode(_rootElement, octalCode, NULL); + OctreeElementPointer element = nodeForOctalCode(_rootElement, octalCode, NULL); delete[] octalCode; // cleanup memory return element; } -OctreeElement* Octree::getOrCreateChildElementAt(float x, float y, float z, float s) { +OctreeElementPointer Octree::getOrCreateChildElementAt(float x, float y, float z, float s) { return getRoot()->getOrCreateChildElementAt(x, y, z, s); } -OctreeElement* Octree::getOrCreateChildElementContaining(const AACube& box) { +OctreeElementPointer Octree::getOrCreateChildElementContaining(const AACube& box) { return getRoot()->getOrCreateChildElementContaining(box); } @@ -660,7 +700,7 @@ class RayArgs { public: glm::vec3 origin; glm::vec3 direction; - OctreeElement*& element; + OctreeElementPointer& element; float& distance; BoxFace& face; void** intersectedObject; @@ -668,7 +708,7 @@ public: bool precisionPicking; }; -bool findRayIntersectionOp(OctreeElement* element, void* extraData) { +bool findRayIntersectionOp(OctreeElementPointer element, void* extraData) { RayArgs* args = static_cast(extraData); bool keepSearching = true; if (element->findRayIntersection(args->origin, args->direction, keepSearching, @@ -679,7 +719,7 @@ bool findRayIntersectionOp(OctreeElement* element, void* extraData) { } bool Octree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, + OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject, Octree::lockType lockType, bool* accurateResult, bool precisionPicking) { RayArgs args = { origin, direction, element, distance, face, intersectedObject, false, precisionPicking}; @@ -720,7 +760,7 @@ public: void* penetratedObject; /// the type is defined by the type of Octree, the caller is assumed to know the type }; -bool findSpherePenetrationOp(OctreeElement* element, void* extraData) { +bool findSpherePenetrationOp(OctreeElementPointer element, void* extraData) { SphereArgs* args = static_cast(extraData); // coarse check against bounds @@ -797,7 +837,7 @@ public: CubeList* cubes; }; -bool findCapsulePenetrationOp(OctreeElement* element, void* extraData) { +bool findCapsulePenetrationOp(OctreeElementPointer element, void* extraData) { CapsuleArgs* args = static_cast(extraData); // coarse check against bounds @@ -830,7 +870,7 @@ uint qHash(const glm::vec3& point) { (((quint64)(point.z * RESOLUTION_PER_METER)) % MAX_SCALED_COMPONENT << 2 * BITS_PER_COMPONENT)); } -bool findContentInCubeOp(OctreeElement* element, void* extraData) { +bool findContentInCubeOp(OctreeElementPointer element, void* extraData) { ContentArgs* args = static_cast(extraData); // coarse check against bounds @@ -894,12 +934,12 @@ bool Octree::findContentInCube(const AACube& cube, CubeList& cubes) { class GetElementEnclosingArgs { public: - OctreeElement* element; + OctreeElementPointer element; glm::vec3 point; }; // Find the smallest colored voxel enclosing a point (if there is one) -bool getElementEnclosingOperation(OctreeElement* element, void* extraData) { +bool getElementEnclosingOperation(OctreeElementPointer element, void* extraData) { GetElementEnclosingArgs* args = static_cast(extraData); if (element->getAACube().contains(args->point)) { if (element->hasContent() && element->isLeaf()) { @@ -914,7 +954,7 @@ bool getElementEnclosingOperation(OctreeElement* element, void* extraData) { return true; // keep looking } -OctreeElement* Octree::getElementEnclosingPoint(const glm::vec3& point, Octree::lockType lockType, bool* accurateResult) { +OctreeElementPointer Octree::getElementEnclosingPoint(const glm::vec3& point, Octree::lockType lockType, bool* accurateResult) { GetElementEnclosingArgs args; args.point = point; args.element = NULL; @@ -947,9 +987,9 @@ OctreeElement* Octree::getElementEnclosingPoint(const glm::vec3& point, Octree:: -int Octree::encodeTreeBitstream(OctreeElement* element, - OctreePacketData* packetData, OctreeElementBag& bag, - EncodeBitstreamParams& params) { +int Octree::encodeTreeBitstream(OctreeElementPointer element, + OctreePacketData* packetData, OctreeElementBag& bag, + EncodeBitstreamParams& params) { // How many bytes have we written so far at this level; int bytesWritten = 0; @@ -1005,7 +1045,7 @@ int Octree::encodeTreeBitstream(OctreeElement* element, ViewFrustum::location parentLocationThisView = ViewFrustum::INTERSECT; // assume parent is in view, but not fully int childBytesWritten = encodeTreeBitstreamRecursion(element, packetData, bag, params, - currentEncodeLevel, parentLocationThisView); + currentEncodeLevel, parentLocationThisView); // if childBytesWritten == 1 then something went wrong... that's not possible @@ -1036,10 +1076,10 @@ int Octree::encodeTreeBitstream(OctreeElement* element, return bytesWritten; } -int Octree::encodeTreeBitstreamRecursion(OctreeElement* element, - OctreePacketData* packetData, OctreeElementBag& bag, - EncodeBitstreamParams& params, int& currentEncodeLevel, - const ViewFrustum::location& parentLocationThisView) const { +int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element, + OctreePacketData* packetData, OctreeElementBag& bag, + EncodeBitstreamParams& params, int& currentEncodeLevel, + const ViewFrustum::location& parentLocationThisView) const { const bool wantDebug = false; @@ -1228,13 +1268,13 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element, int inViewNotLeafCount = 0; int inViewWithColorCount = 0; - OctreeElement* sortedChildren[NUMBER_OF_CHILDREN] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + OctreeElementPointer sortedChildren[NUMBER_OF_CHILDREN] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; float distancesToChildren[NUMBER_OF_CHILDREN] = { 0, 0, 0, 0, 0, 0, 0, 0 }; int indexOfChildren[NUMBER_OF_CHILDREN] = { 0, 0, 0, 0, 0, 0, 0, 0 }; int currentCount = 0; for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - OctreeElement* childElement = element->getChildAtIndex(i); + OctreeElementPointer childElement = element->getChildAtIndex(i); // if the caller wants to include childExistsBits, then include them even if not in view, if however, // we're in a portion of the tree that's not our responsibility, then we assume the child nodes exist @@ -1254,9 +1294,9 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element, if (childElement) { float distance = params.viewFrustum ? childElement->distanceToCamera(*params.viewFrustum) : 0; - currentCount = insertIntoSortedArrays((void*)childElement, distance, i, - (void**)&sortedChildren, (float*)&distancesToChildren, - (int*)&indexOfChildren, currentCount, NUMBER_OF_CHILDREN); + currentCount = insertOctreeElementIntoSortedArrays(childElement, distance, i, + sortedChildren, (float*)&distancesToChildren, + (int*)&indexOfChildren, currentCount, NUMBER_OF_CHILDREN); } } else { sortedChildren[i] = childElement; @@ -1275,7 +1315,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element, // for each child element in Distance sorted order..., check to see if they exist, are colored, and in view, and if so // add them to our distance ordered array of children for (int i = 0; i < currentCount; i++) { - OctreeElement* childElement = sortedChildren[i]; + OctreeElementPointer childElement = sortedChildren[i]; int originalIndex = indexOfChildren[i]; bool childIsInView = (childElement && @@ -1291,7 +1331,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element, params.stats->skippedOutOfView(childElement); } } else { - // Before we determine consider this further, let's see if it's in our LOD scope... + // Before we consider this further, let's see if it's in our LOD scope... float distance = distancesToChildren[i]; float boundaryDistance = !params.viewFrustum ? 1 : boundaryDistanceForRenderLevel(childElement->getLevel() + params.boundaryLevelAdjust, @@ -1318,7 +1358,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element, // If the user also asked for occlusion culling, check if this element is occluded if (params.wantOcclusionCulling && childElement->isLeaf()) { // Don't check occlusion here, just add them to our distance ordered array... - + // FIXME params.ViewFrustum is used here, but later it is checked against nullptr. OctreeProjectedPolygon* voxelPolygon = new OctreeProjectedPolygon( params.viewFrustum->getProjectedPolygon(childElement->getAACube())); @@ -1432,7 +1472,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element, if (params.includeColor) { for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { if (oneAtBit(childrenDataBits, i)) { - OctreeElement* childElement = element->getChildAtIndex(i); + OctreeElementPointer childElement = element->getChildAtIndex(i); // 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 @@ -1578,7 +1618,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element, // for each child element in Distance sorted order..., check to see if they exist, are colored, and in view, and if so // add them to our distance ordered array of children for (int indexByDistance = 0; indexByDistance < currentCount; indexByDistance++) { - OctreeElement* childElement = sortedChildren[indexByDistance]; + OctreeElementPointer childElement = sortedChildren[indexByDistance]; int originalIndex = indexOfChildren[indexByDistance]; if (oneAtBit(childrenExistInPacketBits, originalIndex)) { @@ -2058,7 +2098,7 @@ bool Octree::readJSONFromStream(unsigned long streamLength, QDataStream& inputSt return true; } -void Octree::writeToFile(const char* fileName, OctreeElement* element, QString persistAsFileType) { +void Octree::writeToFile(const char* fileName, OctreeElementPointer element, QString persistAsFileType) { // make the sure file extension makes sense QString qFileName = fileNameWithoutExtension(QString(fileName), PERSIST_EXTENSIONS) + "." + persistAsFileType; QByteArray byteArray = qFileName.toUtf8(); @@ -2075,12 +2115,12 @@ void Octree::writeToFile(const char* fileName, OctreeElement* element, QString p } } -void Octree::writeToJSONFile(const char* fileName, OctreeElement* element, bool doGzip) { +void Octree::writeToJSONFile(const char* fileName, OctreeElementPointer element, bool doGzip) { QVariantMap entityDescription; qCDebug(octree, "Saving JSON SVO to file %s...", fileName); - OctreeElement* top; + OctreeElementPointer top; if (element) { top = element; } else { @@ -2120,7 +2160,7 @@ void Octree::writeToJSONFile(const char* fileName, OctreeElement* element, bool } } -void Octree::writeToSVOFile(const char* fileName, OctreeElement* element) { +void Octree::writeToSVOFile(const char* fileName, OctreeElementPointer element) { std::ofstream file(fileName, std::ios::out|std::ios::binary); if(file.is_open()) { @@ -2160,7 +2200,7 @@ void Octree::writeToSVOFile(const char* fileName, OctreeElement* element) { bool lastPacketWritten = false; while (!elementBag.isEmpty()) { - OctreeElement* subTree = elementBag.extract(); + OctreeElementPointer subTree = elementBag.extract(); lockForRead(); // do tree locking down here so that we have shorter slices and less thread contention EncodeBitstreamParams params(INT_MAX, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS); @@ -2208,7 +2248,7 @@ unsigned long Octree::getOctreeElementsCount() { return nodeCount; } -bool Octree::countOctreeElementsOperation(OctreeElement* element, void* extraData) { +bool Octree::countOctreeElementsOperation(OctreeElementPointer element, void* extraData) { (*(unsigned long*)extraData)++; return true; // keep going } @@ -2216,4 +2256,3 @@ bool Octree::countOctreeElementsOperation(OctreeElement* element, void* extraDat void Octree::cancelImport() { _stopImport = true; } - diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 0b3dc0027f..fe6b31807b 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -14,6 +14,7 @@ #include #include +#include class CoverageMap; class ReadBitstreamToTreeParams; @@ -22,7 +23,7 @@ class OctreeElement; class OctreeElementBag; class OctreePacketData; class Shape; - +typedef std::shared_ptr OctreePointer; #include "JurisdictionMap.h" #include "ViewFrustum.h" @@ -35,19 +36,18 @@ class Shape; #include #include - extern QVector PERSIST_EXTENSIONS; /// derive from this class to use the Octree::recurseTreeWithOperator() method class RecurseOctreeOperator { public: - virtual bool preRecursion(OctreeElement* element) = 0; - virtual bool postRecursion(OctreeElement* element) = 0; - virtual OctreeElement* possiblyCreateChildAt(OctreeElement* element, int childIndex) { return NULL; } + virtual bool preRecursion(OctreeElementPointer element) = 0; + virtual bool postRecursion(OctreeElementPointer element) = 0; + virtual OctreeElementPointer possiblyCreateChildAt(OctreeElementPointer element, int childIndex) { return NULL; } }; // Callback function, for recuseTreeWithOperation -typedef bool (*RecurseOctreeOperation)(OctreeElement* element, void* extraData); +typedef bool (*RecurseOctreeOperation)(OctreeElementPointer element, void* extraData); typedef enum {GRADIENT, RANDOM, NATURAL} creationMode; typedef QHash CubeList; @@ -190,7 +190,7 @@ class ReadBitstreamToTreeParams { public: bool includeColor; bool includeExistsBits; - OctreeElement* destinationElement; + OctreeElementPointer destinationElement; QUuid sourceUUID; SharedNodePointer sourceNode; bool wantImportProgress; @@ -201,7 +201,7 @@ public: ReadBitstreamToTreeParams( bool includeColor = WANT_COLOR, bool includeExistsBits = WANT_EXISTS_BITS, - OctreeElement* destinationElement = NULL, + OctreeElementPointer destinationElement = NULL, QUuid sourceUUID = QUuid(), SharedNodePointer sourceNode = SharedNodePointer(), bool wantImportProgress = false, @@ -216,14 +216,14 @@ public: {} }; -class Octree : public QObject { +class Octree : public QObject, public std::enable_shared_from_this { Q_OBJECT public: Octree(bool shouldReaverage = false); virtual ~Octree(); /// Your tree class must implement this to create the correct element type - virtual OctreeElement* createNewElement(unsigned char * octalCode = NULL) = 0; + virtual OctreeElementPointer createNewElement(unsigned char * octalCode = NULL) = 0; // These methods will allow the OctreeServer to send your tree inbound edit packets of your // own definition. Implement these to allow your octree based server to support editing @@ -250,26 +250,26 @@ public: virtual void update() { } // nothing to do by default - OctreeElement* getRoot() { return _rootElement; } + OctreeElementPointer getRoot() { return _rootElement; } virtual void eraseAllOctreeElements(bool createNewRoot = true); void readBitstreamToTree(const unsigned char* bitstream, unsigned long int bufferSizeBytes, ReadBitstreamToTreeParams& args); void deleteOctalCodeFromTree(const unsigned char* codeBuffer, bool collapseEmptyTrees = DONT_COLLAPSE); - void reaverageOctreeElements(OctreeElement* startElement = NULL); + void reaverageOctreeElements(OctreeElementPointer startElement = NULL); void deleteOctreeElementAt(float x, float y, float z, float s); /// Find the voxel at position x,y,z,s /// \return pointer to the OctreeElement or NULL if none at x,y,z,s. - OctreeElement* getOctreeElementAt(float x, float y, float z, float s) const; + OctreeElementPointer getOctreeElementAt(float x, float y, float z, float s) const; /// Find the voxel at position x,y,z,s /// \return pointer to the OctreeElement or to the smallest enclosing parent if none at x,y,z,s. - OctreeElement* getOctreeEnclosingElementAt(float x, float y, float z, float s) const; + OctreeElementPointer getOctreeEnclosingElementAt(float x, float y, float z, float s) const; - OctreeElement* getOrCreateChildElementAt(float x, float y, float z, float s); - OctreeElement* getOrCreateChildElementContaining(const AACube& box); + OctreeElementPointer getOrCreateChildElementAt(float x, float y, float z, float s); + OctreeElementPointer getOrCreateChildElementContaining(const AACube& box); void recurseTreeWithOperation(RecurseOctreeOperation operation, void* extraData = NULL); void recurseTreeWithPostOperation(RecurseOctreeOperation operation, void* extraData = NULL); @@ -282,7 +282,7 @@ public: void recurseTreeWithOperator(RecurseOctreeOperator* operatorObject); - int encodeTreeBitstream(OctreeElement* element, OctreePacketData* packetData, OctreeElementBag& bag, + int encodeTreeBitstream(OctreeElementPointer element, OctreePacketData* packetData, OctreeElementBag& bag, EncodeBitstreamParams& params) ; bool isDirty() const { return _isDirty; } @@ -303,7 +303,7 @@ public: } lockType; bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElement*& node, float& distance, BoxFace& face, + OctreeElementPointer& node, float& distance, BoxFace& face, void** intersectedObject = NULL, Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL, @@ -322,17 +322,17 @@ public: /// \param point query point in world-frame (meters) /// \param lockType how to lock the tree (Lock, TryLock, NoLock) /// \param[out] accurateResult pointer to output result, will be set "true" or "false" if non-null - OctreeElement* getElementEnclosingPoint(const glm::vec3& point, + OctreeElementPointer getElementEnclosingPoint(const glm::vec3& point, Octree::lockType lockType = Octree::TryLock, bool* accurateResult = NULL); // Note: this assumes the fileFormat is the HIO individual voxels code files void loadOctreeFile(const char* fileName, bool wantColorRandomizer); // Octree exporters - void writeToFile(const char* filename, OctreeElement* element = NULL, QString persistAsFileType = "svo"); - void writeToJSONFile(const char* filename, OctreeElement* element = NULL, bool doGzip = false); - void writeToSVOFile(const char* filename, OctreeElement* element = NULL); - virtual bool writeToMap(QVariantMap& entityDescription, OctreeElement* element, bool skipDefaultValues) = 0; + void writeToFile(const char* filename, OctreeElementPointer element = NULL, QString persistAsFileType = "svo"); + void writeToJSONFile(const char* filename, OctreeElementPointer element = NULL, bool doGzip = false); + void writeToSVOFile(const char* filename, OctreeElementPointer element = NULL); + virtual bool writeToMap(QVariantMap& entityDescription, OctreeElementPointer element, bool skipDefaultValues) = 0; // Octree importers bool readFromFile(const char* filename); @@ -347,18 +347,18 @@ public: bool getShouldReaverage() const { return _shouldReaverage; } - void recurseElementWithOperation(OctreeElement* element, RecurseOctreeOperation operation, + void recurseElementWithOperation(OctreeElementPointer element, RecurseOctreeOperation operation, void* extraData, int recursionCount = 0); /// Traverse child nodes of node applying operation in post-fix order /// - void recurseElementWithPostOperation(OctreeElement* element, RecurseOctreeOperation operation, + void recurseElementWithPostOperation(OctreeElementPointer element, RecurseOctreeOperation operation, void* extraData, int recursionCount = 0); - void recurseElementWithOperationDistanceSorted(OctreeElement* element, RecurseOctreeOperation operation, + void recurseElementWithOperationDistanceSorted(OctreeElementPointer element, RecurseOctreeOperation operation, const glm::vec3& point, void* extraData, int recursionCount = 0); - bool recurseElementWithOperator(OctreeElement* element, RecurseOctreeOperator* operatorObject, int recursionCount = 0); + bool recurseElementWithOperator(OctreeElementPointer element, RecurseOctreeOperator* operatorObject, int recursionCount = 0); bool getIsViewing() const { return _isViewing; } /// This tree is receiving inbound viewer datagrams. void setIsViewing(bool isViewing) { _isViewing = isViewing; } @@ -389,28 +389,28 @@ public slots: protected: - void deleteOctalCodeFromTreeRecursion(OctreeElement* element, void* extraData); + void deleteOctalCodeFromTreeRecursion(OctreeElementPointer element, void* extraData); - int encodeTreeBitstreamRecursion(OctreeElement* element, + int encodeTreeBitstreamRecursion(OctreeElementPointer element, OctreePacketData* packetData, OctreeElementBag& bag, EncodeBitstreamParams& params, int& currentEncodeLevel, const ViewFrustum::location& parentLocationThisView) const; - static bool countOctreeElementsOperation(OctreeElement* element, void* extraData); + static bool countOctreeElementsOperation(OctreeElementPointer element, void* extraData); - OctreeElement* nodeForOctalCode(OctreeElement* ancestorElement, const unsigned char* needleCode, OctreeElement** parentOfFoundElement) const; - OctreeElement* createMissingElement(OctreeElement* lastParentElement, const unsigned char* codeToReach, int recursionCount = 0); - int readElementData(OctreeElement *destinationElement, const unsigned char* nodeData, + OctreeElementPointer nodeForOctalCode(OctreeElementPointer ancestorElement, const unsigned char* needleCode, OctreeElementPointer* parentOfFoundElement) const; + OctreeElementPointer createMissingElement(OctreeElementPointer lastParentElement, const unsigned char* codeToReach, int recursionCount = 0); + int readElementData(OctreeElementPointer destinationElement, const unsigned char* nodeData, int bufferSizeBytes, ReadBitstreamToTreeParams& args); - OctreeElement* _rootElement; + OctreeElementPointer _rootElement = nullptr; bool _isDirty; bool _shouldReaverage; bool _stopImport; QReadWriteLock _lock; - + bool _isViewing; bool _isServer; }; diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index 2bbacccf95..9e2cfbbf63 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -42,7 +42,7 @@ void OctreeElement::resetPopulationStatistics() { OctreeElement::OctreeElement() { // Note: you must call init() from your subclass, otherwise the OctreeElement will not be properly // initialized. You will see DEADBEEF in your memory debugger if you have not properly called init() - debug::setDeadBeef(this, sizeof(*this)); + // debug::setDeadBeef(this, sizeof(*this)); } void OctreeElement::init(unsigned char * octalCode) { @@ -80,9 +80,13 @@ void OctreeElement::init(unsigned char * octalCode) { #endif #ifdef SIMPLE_EXTERNAL_CHILDREN - _children.single = NULL; + _childrenSingle.reset(); #endif + for (int i = 0; i < NUMBER_OF_CHILDREN; i ++) { + _externalChildren[i].reset(); + } + _isDirty = true; _shouldRender = false; _sourceUUIDKey = 0; @@ -91,7 +95,10 @@ void OctreeElement::init(unsigned char * octalCode) { } OctreeElement::~OctreeElement() { - notifyDeleteHooks(); + // We can't call notifyDeleteHooks from here: + // notifyDeleteHooks(); + // see comment in EntityTreeElement::createNewElement. + assert(_deleteHooksNotified); _voxelNodeCount--; if (isLeaf()) { _voxelNodeLeafCount--; @@ -117,7 +124,7 @@ void OctreeElement::markWithChangedTime() { // changed. However, you should hopefully make your bookkeeping relatively // localized, because this method will get called for every node in an // recursive unwinding case like delete or add voxel -void OctreeElement::handleSubtreeChanged(Octree* myTree) { +void OctreeElement::handleSubtreeChanged(OctreePointer myTree) { // here's a good place to do color re-averaging... if (myTree->getShouldReaverage()) { calculateAverageFromChildren(); @@ -196,9 +203,9 @@ void OctreeElement::calculateAACube() { } void OctreeElement::deleteChildAtIndex(int childIndex) { - OctreeElement* childAt = getChildAtIndex(childIndex); + OctreeElementPointer childAt = getChildAtIndex(childIndex); if (childAt) { - delete childAt; + childAt.reset(); setChildAtIndex(childIndex, NULL); _isDirty = true; markWithChangedTime(); @@ -211,8 +218,8 @@ void OctreeElement::deleteChildAtIndex(int childIndex) { } // does not delete the node! -OctreeElement* OctreeElement::removeChildAtIndex(int childIndex) { - OctreeElement* returnedChild = getChildAtIndex(childIndex); +OctreeElementPointer OctreeElement::removeChildAtIndex(int childIndex) { + OctreeElementPointer returnedChild = getChildAtIndex(childIndex); if (returnedChild) { setChildAtIndex(childIndex, NULL); _isDirty = true; @@ -226,10 +233,10 @@ OctreeElement* OctreeElement::removeChildAtIndex(int childIndex) { return returnedChild; } -bool OctreeElement::isParentOf(OctreeElement* possibleChild) const { +bool OctreeElement::isParentOf(OctreeElementPointer possibleChild) const { if (possibleChild) { for (int childIndex = 0; childIndex < NUMBER_OF_CHILDREN; childIndex++) { - OctreeElement* childAt = getChildAtIndex(childIndex); + OctreeElementPointer childAt = getChildAtIndex(childIndex); if (childAt == possibleChild) { return true; } @@ -246,7 +253,7 @@ quint64 OctreeElement::_setChildAtIndexCalls = 0; quint64 OctreeElement::_externalChildrenCount = 0; quint64 OctreeElement::_childrenCount[NUMBER_OF_CHILDREN + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -OctreeElement* OctreeElement::getChildAtIndex(int childIndex) const { +OctreeElementPointer OctreeElement::getChildAtIndex(int childIndex) const { #ifdef SIMPLE_CHILD_ARRAY return _simpleChildArray[childIndex]; #endif // SIMPLE_CHILD_ARRAY @@ -264,14 +271,14 @@ OctreeElement* OctreeElement::getChildAtIndex(int childIndex) const { // return null int firstIndex = getNthBit(_childBitmask, 1); if (firstIndex == childIndex) { - return _children.single; + return _childrenSingle; } else { return NULL; } } break; default : { - return _children.external[childIndex]; + return _externalChildren[childIndex]; } break; } #endif // def SIMPLE_EXTERNAL_CHILDREN @@ -280,19 +287,21 @@ OctreeElement* OctreeElement::getChildAtIndex(int childIndex) const { void OctreeElement::deleteAllChildren() { // first delete all the OctreeElement objects... for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - OctreeElement* childAt = getChildAtIndex(i); + OctreeElementPointer childAt = getChildAtIndex(i); if (childAt) { - delete childAt; + childAt.reset(); } } if (_childrenExternal) { // if the children_t union represents _children.external we need to delete it here - delete[] _children.external; + for (int i = 0; i < NUMBER_OF_CHILDREN; i ++) { + _externalChildren[i].reset(); + } } } -void OctreeElement::setChildAtIndex(int childIndex, OctreeElement* child) { +void OctreeElement::setChildAtIndex(int childIndex, OctreeElementPointer child) { #ifdef SIMPLE_CHILD_ARRAY int previousChildCount = getChildCount(); if (child) { @@ -332,44 +341,47 @@ void OctreeElement::setChildAtIndex(int childIndex, OctreeElement* child) { } if ((previousChildCount == 0 || previousChildCount == 1) && newChildCount == 0) { - _children.single = NULL; + _childrenSingle.reset(); } else if (previousChildCount == 0 && newChildCount == 1) { - _children.single = child; + _childrenSingle = child; } else if (previousChildCount == 1 && newChildCount == 2) { - OctreeElement* previousChild = _children.single; - _children.external = new OctreeElement*[NUMBER_OF_CHILDREN]; - memset(_children.external, 0, sizeof(OctreeElement*) * NUMBER_OF_CHILDREN); - _children.external[firstIndex] = previousChild; - _children.external[childIndex] = child; + OctreeElementPointer previousChild = _childrenSingle; + for (int i = 0; i < NUMBER_OF_CHILDREN; i ++) { + _externalChildren[i].reset(); + } + _externalChildren[firstIndex] = previousChild; + _externalChildren[childIndex] = child; _childrenExternal = true; - _externalChildrenMemoryUsage += NUMBER_OF_CHILDREN * sizeof(OctreeElement*); + _externalChildrenMemoryUsage += NUMBER_OF_CHILDREN * sizeof(OctreeElementPointer); } else if (previousChildCount == 2 && newChildCount == 1) { assert(!child); // we are removing a child, so this must be true! - OctreeElement* previousFirstChild = _children.external[firstIndex]; - OctreeElement* previousSecondChild = _children.external[secondIndex]; + OctreeElementPointer previousFirstChild = _externalChildren[firstIndex]; + OctreeElementPointer previousSecondChild = _externalChildren[secondIndex]; - delete[] _children.external; + for (int i = 0; i < NUMBER_OF_CHILDREN; i ++) { + _externalChildren[i].reset(); + } _childrenExternal = false; - _externalChildrenMemoryUsage -= NUMBER_OF_CHILDREN * sizeof(OctreeElement*); + _externalChildrenMemoryUsage -= NUMBER_OF_CHILDREN * sizeof(OctreeElementPointer); if (childIndex == firstIndex) { - _children.single = previousSecondChild; + _childrenSingle = previousSecondChild; } else { - _children.single = previousFirstChild; + _childrenSingle = previousFirstChild; } } else { - _children.external[childIndex] = child; + _externalChildren[childIndex] = child; } #endif // def SIMPLE_EXTERNAL_CHILDREN } -OctreeElement* OctreeElement::addChildAtIndex(int childIndex) { - OctreeElement* childAt = getChildAtIndex(childIndex); +OctreeElementPointer OctreeElement::addChildAtIndex(int childIndex) { + OctreeElementPointer childAt = getChildAtIndex(childIndex); if (!childAt) { // before adding a child, see if we're currently a leaf if (isLeaf()) { @@ -397,7 +409,7 @@ bool OctreeElement::safeDeepDeleteChildAtIndex(int childIndex, int recursionCoun qCDebug(octree) << "OctreeElement::safeDeepDeleteChildAtIndex() reached DANGEROUSLY_DEEP_RECURSION, bailing!"; return deleteApproved; } - OctreeElement* childToDelete = getChildAtIndex(childIndex); + OctreeElementPointer childToDelete = getChildAtIndex(childIndex); if (childToDelete) { if (childToDelete->deleteApproved()) { // If the child is not a leaf, then call ourselves recursively on all the children @@ -428,7 +440,7 @@ bool OctreeElement::safeDeepDeleteChildAtIndex(int childIndex, int recursionCoun void OctreeElement::printDebugDetails(const char* label) const { unsigned char childBits = 0; for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - OctreeElement* childAt = getChildAtIndex(i); + OctreeElementPointer childAt = getChildAtIndex(i); if (childAt) { setAtBit(childBits,i); } @@ -534,9 +546,10 @@ void OctreeElement::removeDeleteHook(OctreeElementDeleteHook* hook) { void OctreeElement::notifyDeleteHooks() { _deleteHooksLock.lockForRead(); for (unsigned int i = 0; i < _deleteHooks.size(); i++) { - _deleteHooks[i]->elementDeleted(this); + _deleteHooks[i]->elementDeleted(shared_from_this()); } _deleteHooksLock.unlock(); + _deleteHooksNotified = true; } std::vector OctreeElement::_updateHooks; @@ -556,12 +569,12 @@ void OctreeElement::removeUpdateHook(OctreeElementUpdateHook* hook) { void OctreeElement::notifyUpdateHooks() { for (unsigned int i = 0; i < _updateHooks.size(); i++) { - _updateHooks[i]->elementUpdated(this); + _updateHooks[i]->elementUpdated(shared_from_this()); } } bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) { keepSearching = true; // assume that we will continue searching after this. @@ -599,12 +612,12 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3 } bool OctreeElement::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking, float distanceToElementCube) { // we did hit this element, so calculate appropriate distances if (hasContent()) { - element = this; + element = shared_from_this(); distance = distanceToElementCube; if (intersectedObject) { *intersectedObject = this; @@ -622,8 +635,8 @@ bool OctreeElement::findSpherePenetration(const glm::vec3& center, float radius, } // TODO: consider removing this, or switching to using getOrCreateChildElementContaining(const AACube& box)... -OctreeElement* OctreeElement::getOrCreateChildElementAt(float x, float y, float z, float s) { - OctreeElement* child = NULL; +OctreeElementPointer OctreeElement::getOrCreateChildElementAt(float x, float y, float z, float s) { + OctreeElementPointer child = NULL; // If the requested size is less than or equal to our scale, but greater than half our scale, then // we are the Element they are looking for. float ourScale = getScale(); @@ -635,7 +648,7 @@ OctreeElement* OctreeElement::getOrCreateChildElementAt(float x, float y, float } if (s > halfOurScale) { - return this; + return shared_from_this(); } int childIndex = getMyChildContainingPoint(glm::vec3(x, y, z)); @@ -651,15 +664,15 @@ OctreeElement* OctreeElement::getOrCreateChildElementAt(float x, float y, float } -OctreeElement* OctreeElement::getOrCreateChildElementContaining(const AACube& cube) { - OctreeElement* child = NULL; +OctreeElementPointer OctreeElement::getOrCreateChildElementContaining(const AACube& cube) { + OctreeElementPointer child = NULL; int childIndex = getMyChildContaining(cube); // If getMyChildContaining() returns CHILD_UNKNOWN then it means that our level // is the correct level for this cube if (childIndex == CHILD_UNKNOWN) { - return this; + return shared_from_this(); } // Now, check if we have a child at that location @@ -677,15 +690,15 @@ OctreeElement* OctreeElement::getOrCreateChildElementContaining(const AACube& cu return child->getOrCreateChildElementContaining(cube); } -OctreeElement* OctreeElement::getOrCreateChildElementContaining(const AABox& box) { - OctreeElement* child = NULL; +OctreeElementPointer OctreeElement::getOrCreateChildElementContaining(const AABox& box) { + OctreeElementPointer child = NULL; int childIndex = getMyChildContaining(box); // If getMyChildContaining() returns CHILD_UNKNOWN then it means that our level // is the correct level for this cube if (childIndex == CHILD_UNKNOWN) { - return this; + return shared_from_this(); } // Now, check if we have a child at that location diff --git a/libraries/octree/src/OctreeElement.h b/libraries/octree/src/OctreeElement.h index d2f3f7d3aa..475d9568bb 100644 --- a/libraries/octree/src/OctreeElement.h +++ b/libraries/octree/src/OctreeElement.h @@ -33,27 +33,30 @@ class OctreePacketData; class ReadBitstreamToTreeParams; class Shape; class VoxelSystem; +typedef std::shared_ptr OctreeElementPointer; +typedef std::shared_ptr ConstOctreeElementPointer; +typedef std::shared_ptr OctreePointer; // Callers who want delete hook callbacks should implement this class class OctreeElementDeleteHook { public: - virtual void elementDeleted(OctreeElement* element) = 0; + virtual void elementDeleted(OctreeElementPointer element) = 0; }; // Callers who want update hook callbacks should implement this class class OctreeElementUpdateHook { public: - virtual void elementUpdated(OctreeElement* element) = 0; + virtual void elementUpdated(OctreeElementPointer element) = 0; }; -class OctreeElement { +class OctreeElement: public std::enable_shared_from_this { protected: // can only be constructed by derived implementation OctreeElement(); - virtual OctreeElement* createNewElement(unsigned char * octalCode = NULL) = 0; + virtual OctreeElementPointer createNewElement(unsigned char * octalCode = NULL) = 0; public: virtual void init(unsigned char * octalCode); /// Your subclass must call init on construction. @@ -62,7 +65,7 @@ public: // methods you can and should override to implement your tree functionality /// Adds a child to the current element. Override this if there is additional child initialization your class needs. - virtual OctreeElement* addChildAtIndex(int childIndex); + virtual OctreeElementPointer addChildAtIndex(int childIndex); /// Override this to implement LOD averaging on changes to the tree. virtual void calculateAverageFromChildren() { } @@ -90,7 +93,7 @@ public: typedef enum { COMPLETED, PARTIAL, NONE } AppendState; virtual void debugExtraEncodeData(EncodeBitstreamParams& params) const { } - virtual void initializeExtraEncodeData(EncodeBitstreamParams& params) const { } + virtual void initializeExtraEncodeData(EncodeBitstreamParams& params) { } virtual bool shouldIncludeChildData(int childIndex, EncodeBitstreamParams& params) const { return true; } virtual bool shouldRecurseChildTree(int childIndex, EncodeBitstreamParams& params) const { return true; } @@ -116,11 +119,11 @@ public: virtual bool canRayIntersect() const { return isLeaf(); } virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& node, float& distance, BoxFace& face, + bool& keepSearching, OctreeElementPointer& node, float& distance, BoxFace& face, void** intersectedObject = NULL, bool precisionPicking = false); virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking, float distanceToElementCube); /// \param center center of sphere in meters @@ -132,10 +135,10 @@ public: // Base class methods you don't need to implement const unsigned char* getOctalCode() const { return (_octcodePointer) ? _octalCode.pointer : &_octalCode.buffer[0]; } - OctreeElement* getChildAtIndex(int childIndex) const; + OctreeElementPointer getChildAtIndex(int childIndex) const; void deleteChildAtIndex(int childIndex); - OctreeElement* removeChildAtIndex(int childIndex); - bool isParentOf(OctreeElement* possibleChild) const; + OctreeElementPointer removeChildAtIndex(int childIndex); + bool isParentOf(OctreeElementPointer possibleChild) const; /// handles deletion of all descendants, returns false if delete not approved bool safeDeepDeleteChildAtIndex(int childIndex, int recursionCount = 0); @@ -145,16 +148,16 @@ public: const glm::vec3& getCorner() const { return _cube.getCorner(); } float getScale() const { return _cube.getScale(); } int getLevel() const { return numberOfThreeBitSectionsInCode(getOctalCode()) + 1; } - + float getEnclosingRadius() const; bool isInView(const ViewFrustum& viewFrustum) const { return inFrustum(viewFrustum) != ViewFrustum::OUTSIDE; } ViewFrustum::location inFrustum(const ViewFrustum& viewFrustum) const; - float distanceToCamera(const ViewFrustum& viewFrustum) const; + float distanceToCamera(const ViewFrustum& viewFrustum) const; float furthestDistanceToCamera(const ViewFrustum& viewFrustum) const; - bool calculateShouldRender(const ViewFrustum* viewFrustum, + bool calculateShouldRender(const ViewFrustum* viewFrustum, float voxelSizeScale = DEFAULT_OCTREE_SIZE_SCALE, int boundaryLevelAdjust = 0) const; - + // points are assumed to be in Voxel Coordinates (not TREE_SCALE'd) float distanceSquareToPoint(const glm::vec3& point) const; // when you don't need the actual distance, use this. float distanceToPoint(const glm::vec3& point) const; @@ -168,13 +171,13 @@ public: bool hasChangedSince(quint64 time) const { return (_lastChanged > time); } void markWithChangedTime(); quint64 getLastChanged() const { return _lastChanged; } - void handleSubtreeChanged(Octree* myTree); - + void handleSubtreeChanged(OctreePointer myTree); + // Used by VoxelSystem for rendering in/out of view and LOD void setShouldRender(bool shouldRender); bool getShouldRender() const { return _shouldRender; } - - + + void setSourceUUID(const QUuid& sourceID); QUuid getSourceUUID() const; uint16_t getSourceUUIDKey() const { return _sourceUUIDKey; } @@ -186,7 +189,7 @@ public: static void addUpdateHook(OctreeElementUpdateHook* hook); static void removeUpdateHook(OctreeElementUpdateHook* hook); - + static void resetPopulationStatistics(); static unsigned long getNodeCount() { return _voxelNodeCount; } static unsigned long getInternalNodeCount() { return _voxelNodeCount - _voxelNodeLeafCount; } @@ -204,7 +207,7 @@ public: static quint64 getExternalChildrenCount() { return _externalChildrenCount; } static quint64 getChildrenCount(int childCount) { return _childrenCount[childCount]; } - + enum ChildIndex { CHILD_BOTTOM_RIGHT_NEAR = 0, CHILD_BOTTOM_RIGHT_FAR = 1, @@ -231,9 +234,9 @@ public: }; - OctreeElement* getOrCreateChildElementAt(float x, float y, float z, float s); - OctreeElement* getOrCreateChildElementContaining(const AACube& box); - OctreeElement* getOrCreateChildElementContaining(const AABox& box); + OctreeElementPointer getOrCreateChildElementAt(float x, float y, float z, float s); + OctreeElementPointer getOrCreateChildElementContaining(const AACube& box); + OctreeElementPointer getOrCreateChildElementContaining(const AABox& box); int getMyChildContaining(const AACube& cube) const; int getMyChildContaining(const AABox& box) const; int getMyChildContainingPoint(const glm::vec3& point) const; @@ -241,7 +244,7 @@ public: protected: void deleteAllChildren(); - void setChildAtIndex(int childIndex, OctreeElement* child); + void setChildAtIndex(int childIndex, OctreeElementPointer child); void calculateAACube(); void notifyDeleteHooks(); @@ -253,22 +256,22 @@ protected: union octalCode_t { unsigned char buffer[8]; unsigned char* pointer; - } _octalCode; + } _octalCode; quint64 _lastChanged; /// Client and server, timestamp this node was last changed, 8 bytes /// Client and server, pointers to child nodes, various encodings #ifdef SIMPLE_CHILD_ARRAY - OctreeElement* _simpleChildArray[8]; /// Only used when SIMPLE_CHILD_ARRAY is enabled + OctreeElementPointer _simpleChildArray[8]; /// Only used when SIMPLE_CHILD_ARRAY is enabled #endif #ifdef SIMPLE_EXTERNAL_CHILDREN - union children_t { - OctreeElement* single; - OctreeElement** external; - } _children; + // union children_t { + OctreeElementPointer _childrenSingle; + OctreeElementPointer _externalChildren[NUMBER_OF_CHILDREN]; + // } _children; #endif - + uint16_t _sourceUUIDKey; /// Client only, stores node id of voxel server that sent his voxel, 2 bytes // Support for _sourceUUID, we use these static member variables to track the UUIDs that are @@ -287,6 +290,8 @@ protected: _unknownBufferIndex : 1, _childrenExternal : 1; /// Client only, is this voxel's VBO buffer the unknown buffer index, 1 bit + bool _deleteHooksNotified = false; + static QReadWriteLock _deleteHooksLock; static std::vector _deleteHooks; diff --git a/libraries/octree/src/OctreeElementBag.cpp b/libraries/octree/src/OctreeElementBag.cpp index 0f1e091c6f..5af63c7bb1 100644 --- a/libraries/octree/src/OctreeElementBag.cpp +++ b/libraries/octree/src/OctreeElementBag.cpp @@ -31,7 +31,7 @@ void OctreeElementBag::unhookNotifications() { } } -void OctreeElementBag::elementDeleted(OctreeElement* element) { +void OctreeElementBag::elementDeleted(OctreeElementPointer element) { remove(element); // note: remove can safely handle nodes that aren't in it, so we don't need to check contains() } @@ -41,25 +41,25 @@ void OctreeElementBag::deleteAll() { } -void OctreeElementBag::insert(OctreeElement* element) { +void OctreeElementBag::insert(OctreeElementPointer element) { _bagElements.insert(element); } -OctreeElement* OctreeElementBag::extract() { - OctreeElement* result = NULL; +OctreeElementPointer OctreeElementBag::extract() { + OctreeElementPointer result = NULL; if (_bagElements.size() > 0) { - QSet::iterator front = _bagElements.begin(); + QSet::iterator front = _bagElements.begin(); result = *front; _bagElements.erase(front); } return result; } -bool OctreeElementBag::contains(OctreeElement* element) { +bool OctreeElementBag::contains(OctreeElementPointer element) { return _bagElements.contains(element); } -void OctreeElementBag::remove(OctreeElement* element) { +void OctreeElementBag::remove(OctreeElementPointer element) { _bagElements.remove(element); } diff --git a/libraries/octree/src/OctreeElementBag.h b/libraries/octree/src/OctreeElementBag.h index 1b74f507c6..8ef01b44a2 100644 --- a/libraries/octree/src/OctreeElementBag.h +++ b/libraries/octree/src/OctreeElementBag.h @@ -23,24 +23,24 @@ class OctreeElementBag : public OctreeElementDeleteHook { public: OctreeElementBag(); ~OctreeElementBag(); - - void insert(OctreeElement* element); // put a element into the bag - OctreeElement* extract(); // pull a element out of the bag (could come in any order) - bool contains(OctreeElement* element); // is this element in the bag? - void remove(OctreeElement* element); // remove a specific element from the bag + + void insert(OctreeElementPointer element); // put a element into the bag + OctreeElementPointer extract(); // pull a element out of the bag (could come in any order) + bool contains(OctreeElementPointer element); // is this element in the bag? + void remove(OctreeElementPointer element); // remove a specific element from the bag bool isEmpty() const { return _bagElements.isEmpty(); } int count() const { return _bagElements.size(); } void deleteAll(); - virtual void elementDeleted(OctreeElement* element); + virtual void elementDeleted(OctreeElementPointer element); void unhookNotifications(); private: - QSet _bagElements; + QSet _bagElements; bool _hooked; }; -typedef QMap OctreeElementExtraEncodeData; +typedef QMap OctreeElementExtraEncodeData; #endif // hifi_OctreeElementBag_h diff --git a/libraries/octree/src/OctreeHeadlessViewer.h b/libraries/octree/src/OctreeHeadlessViewer.h index d54d54952a..be076e7b5f 100644 --- a/libraries/octree/src/OctreeHeadlessViewer.h +++ b/libraries/octree/src/OctreeHeadlessViewer.h @@ -30,7 +30,7 @@ class OctreeHeadlessViewer : public OctreeRenderer { public: OctreeHeadlessViewer(); virtual ~OctreeHeadlessViewer(); - virtual void renderElement(OctreeElement* element, RenderArgs* args) { /* swallow these */ } + virtual void renderElement(OctreeElementPointer element, RenderArgs* args) { /* swallow these */ } virtual void init(); virtual void render(RenderArgs* renderArgs) override { /* swallow these */ } diff --git a/libraries/octree/src/OctreePersistThread.cpp b/libraries/octree/src/OctreePersistThread.cpp index bb6f62ef84..332a60feb9 100644 --- a/libraries/octree/src/OctreePersistThread.cpp +++ b/libraries/octree/src/OctreePersistThread.cpp @@ -31,7 +31,7 @@ const int OctreePersistThread::DEFAULT_PERSIST_INTERVAL = 1000 * 30; // every 30 seconds -OctreePersistThread::OctreePersistThread(Octree* tree, const QString& filename, int persistInterval, +OctreePersistThread::OctreePersistThread(OctreePointer tree, const QString& filename, int persistInterval, bool wantBackup, const QJsonObject& settings, bool debugTimestampNow, QString persistAsFileType) : _tree(tree), diff --git a/libraries/octree/src/OctreePersistThread.h b/libraries/octree/src/OctreePersistThread.h index e756c13f59..d3aa3d3968 100644 --- a/libraries/octree/src/OctreePersistThread.h +++ b/libraries/octree/src/OctreePersistThread.h @@ -33,8 +33,8 @@ public: static const int DEFAULT_PERSIST_INTERVAL; - OctreePersistThread(Octree* tree, const QString& filename, int persistInterval = DEFAULT_PERSIST_INTERVAL, - bool wantBackup = false, const QJsonObject& settings = QJsonObject(), + OctreePersistThread(OctreePointer tree, const QString& filename, int persistInterval = DEFAULT_PERSIST_INTERVAL, + bool wantBackup = false, const QJsonObject& settings = QJsonObject(), bool debugTimestampNow = false, QString persistAsFileType="svo"); bool isInitialLoadComplete() const { return _initialLoadComplete; } @@ -48,7 +48,7 @@ signals: protected: /// Implements generic processing behavior for this thread. virtual bool process(); - + void persist(); void backup(); void rollOldBackupVersions(const BackupRule& rule); @@ -56,9 +56,9 @@ protected: bool getMostRecentBackup(const QString& format, QString& mostRecentBackupFileName, QDateTime& mostRecentBackupTime); quint64 getMostRecentBackupTimeInUsecs(const QString& format); void parseSettings(const QJsonObject& settings); - + private: - Octree* _tree; + OctreePointer _tree; QString _filename; int _persistInterval; bool _initialLoadComplete; @@ -69,7 +69,7 @@ private: quint64 _lastCheck; bool _wantBackup; QVector _backupRules; - + bool _debugTimestampNow; quint64 _lastTimeDebug; diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index ce9bd1e3fd..1b221f8d0f 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -35,22 +35,15 @@ void OctreeRenderer::init() { } OctreeRenderer::~OctreeRenderer() { - if (_tree && _managedTree) { - delete _tree; - } } -void OctreeRenderer::setTree(Octree* newTree) { - if (_tree && _managedTree) { - delete _tree; - _managedTree = false; - } +void OctreeRenderer::setTree(OctreePointer newTree) { _tree = newTree; } void OctreeRenderer::processDatagram(NLPacket& packet, SharedNodePointer sourceNode) { bool extraDebugging = false; - + if (extraDebugging) { qCDebug(octree) << "OctreeRenderer::processDatagram()"; } @@ -199,7 +192,7 @@ void OctreeRenderer::processDatagram(NLPacket& packet, SharedNodePointer sourceN } } -bool OctreeRenderer::renderOperation(OctreeElement* element, void* extraData) { +bool OctreeRenderer::renderOperation(OctreeElementPointer element, void* extraData) { RenderArgs* args = static_cast(extraData); if (element->isInView(*args->_viewFrustum)) { if (element->hasContent()) { diff --git a/libraries/octree/src/OctreeRenderer.h b/libraries/octree/src/OctreeRenderer.h index 85a193a3e6..a49ca5bae5 100644 --- a/libraries/octree/src/OctreeRenderer.h +++ b/libraries/octree/src/OctreeRenderer.h @@ -38,12 +38,12 @@ public: virtual char getMyNodeType() const = 0; virtual PacketType::Value getMyQueryMessageType() const = 0; virtual PacketType::Value getExpectedPacketType() const = 0; - virtual void renderElement(OctreeElement* element, RenderArgs* args) = 0; + virtual void renderElement(OctreeElementPointer element, RenderArgs* args) = 0; virtual float getSizeScale() const { return DEFAULT_OCTREE_SIZE_SCALE; } virtual int getBoundaryLevelAdjust() const { return 0; } - virtual void setTree(Octree* newTree); - + virtual void setTree(OctreePointer newTree); + /// process incoming data virtual void processDatagram(NLPacket& packet, SharedNodePointer sourceNode); @@ -56,7 +56,7 @@ public: ViewFrustum* getViewFrustum() const { return _viewFrustum; } void setViewFrustum(ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; } - static bool renderOperation(OctreeElement* element, void* extraData); + static bool renderOperation(OctreeElementPointer element, void* extraData); /// clears the tree virtual void clear(); @@ -71,11 +71,11 @@ public: float getAverageWaitLockPerPacket() const { return _waitLockPerPacket.getAverage(); } float getAverageUncompressPerPacket() const { return _uncompressPerPacket.getAverage(); } float getAverageReadBitstreamPerPacket() const { return _readBitstreamPerPacket.getAverage(); } - -protected: - virtual Octree* createTree() = 0; - Octree* _tree; +protected: + virtual OctreePointer createTree() = 0; + + OctreePointer _tree; bool _managedTree; ViewFrustum* _viewFrustum; diff --git a/libraries/octree/src/OctreeSceneStats.cpp b/libraries/octree/src/OctreeSceneStats.cpp index 55213fdb7a..cd60b8b846 100644 --- a/libraries/octree/src/OctreeSceneStats.cpp +++ b/libraries/octree/src/OctreeSceneStats.cpp @@ -149,7 +149,8 @@ OctreeSceneStats::~OctreeSceneStats() { reset(); } -void OctreeSceneStats::sceneStarted(bool isFullScene, bool isMoving, OctreeElement* root, JurisdictionMap* jurisdictionMap) { +void OctreeSceneStats::sceneStarted(bool isFullScene, bool isMoving, OctreeElementPointer root, + JurisdictionMap* jurisdictionMap) { reset(); // resets packet and octree stats _isStarted = true; _start = usecTimestampNow(); @@ -286,7 +287,7 @@ void OctreeSceneStats::packetSent(int bytes) { _bytes += bytes; } -void OctreeSceneStats::traversed(const OctreeElement* element) { +void OctreeSceneStats::traversed(const OctreeElementPointer element) { _traversed++; if (element->isLeaf()) { _leaves++; @@ -295,7 +296,7 @@ void OctreeSceneStats::traversed(const OctreeElement* element) { } } -void OctreeSceneStats::skippedDistance(const OctreeElement* element) { +void OctreeSceneStats::skippedDistance(const OctreeElementPointer element) { _skippedDistance++; if (element->isLeaf()) { _leavesSkippedDistance++; @@ -304,7 +305,7 @@ void OctreeSceneStats::skippedDistance(const OctreeElement* element) { } } -void OctreeSceneStats::skippedOutOfView(const OctreeElement* element) { +void OctreeSceneStats::skippedOutOfView(const OctreeElementPointer element) { _skippedOutOfView++; if (element->isLeaf()) { _leavesSkippedOutOfView++; @@ -313,7 +314,7 @@ void OctreeSceneStats::skippedOutOfView(const OctreeElement* element) { } } -void OctreeSceneStats::skippedWasInView(const OctreeElement* element) { +void OctreeSceneStats::skippedWasInView(const OctreeElementPointer element) { _skippedWasInView++; if (element->isLeaf()) { _leavesSkippedWasInView++; @@ -322,7 +323,7 @@ void OctreeSceneStats::skippedWasInView(const OctreeElement* element) { } } -void OctreeSceneStats::skippedNoChange(const OctreeElement* element) { +void OctreeSceneStats::skippedNoChange(const OctreeElementPointer element) { _skippedNoChange++; if (element->isLeaf()) { _leavesSkippedNoChange++; @@ -331,7 +332,7 @@ void OctreeSceneStats::skippedNoChange(const OctreeElement* element) { } } -void OctreeSceneStats::skippedOccluded(const OctreeElement* element) { +void OctreeSceneStats::skippedOccluded(const OctreeElementPointer element) { _skippedOccluded++; if (element->isLeaf()) { _leavesSkippedOccluded++; @@ -340,7 +341,7 @@ void OctreeSceneStats::skippedOccluded(const OctreeElement* element) { } } -void OctreeSceneStats::colorSent(const OctreeElement* element) { +void OctreeSceneStats::colorSent(const OctreeElementPointer element) { _colorSent++; if (element->isLeaf()) { _leavesColorSent++; @@ -349,7 +350,7 @@ void OctreeSceneStats::colorSent(const OctreeElement* element) { } } -void OctreeSceneStats::didntFit(const OctreeElement* element) { +void OctreeSceneStats::didntFit(const OctreeElementPointer element) { _didntFit++; if (element->isLeaf()) { _leavesDidntFit++; diff --git a/libraries/octree/src/OctreeSceneStats.h b/libraries/octree/src/OctreeSceneStats.h index d840c0d6f6..77cc02b247 100644 --- a/libraries/octree/src/OctreeSceneStats.h +++ b/libraries/octree/src/OctreeSceneStats.h @@ -37,7 +37,7 @@ public: OctreeSceneStats& operator= (const OctreeSceneStats& other); // copy assignment /// Call when beginning the computation of a scene. Initializes internal structures - void sceneStarted(bool fullScene, bool moving, OctreeElement* root, JurisdictionMap* jurisdictionMap); + void sceneStarted(bool fullScene, bool moving, OctreeElementPointer root, JurisdictionMap* jurisdictionMap); bool getIsSceneStarted() const { return _isStarted; } /// Call when the computation of a scene is completed. Finalizes internal structures @@ -55,28 +55,28 @@ public: void encodeStopped(); /// Track that a element was traversed as part of computation of a scene. - void traversed(const OctreeElement* element); + void traversed(const OctreeElementPointer element); /// Track that a element was skipped as part of computation of a scene due to being beyond the LOD distance. - void skippedDistance(const OctreeElement* element); + void skippedDistance(const OctreeElementPointer element); /// Track that a element was skipped as part of computation of a scene due to being out of view. - void skippedOutOfView(const OctreeElement* element); + void skippedOutOfView(const OctreeElementPointer element); /// Track that a element was skipped as part of computation of a scene due to previously being in view while in delta sending - void skippedWasInView(const OctreeElement* element); + void skippedWasInView(const OctreeElementPointer element); /// Track that a element was skipped as part of computation of a scene due to not having changed since last full scene sent - void skippedNoChange(const OctreeElement* element); + void skippedNoChange(const OctreeElementPointer element); /// Track that a element was skipped as part of computation of a scene due to being occluded - void skippedOccluded(const OctreeElement* element); + void skippedOccluded(const OctreeElementPointer element); /// Track that a element's color was was sent as part of computation of a scene - void colorSent(const OctreeElement* element); + void colorSent(const OctreeElementPointer element); /// Track that a element was due to be sent, but didn't fit in the packet and was moved to next packet - void didntFit(const OctreeElement* element); + void didntFit(const OctreeElementPointer element); /// Track that the color bitmask was was sent as part of computation of a scene void colorBitsWritten(); diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index dc3c0ea4e8..0b0979f03b 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -31,8 +31,8 @@ const quint64 USECS_BETWEEN_OWNERSHIP_BIDS = USECS_PER_SECOND / 5; #ifdef WANT_DEBUG_ENTITY_TREE_LOCKS bool EntityMotionState::entityTreeIsLocked() const { - EntityTreeElement* element = _entity ? _entity->getElement() : nullptr; - EntityTree* tree = element ? element->getTree() : nullptr; + EntityTreeElementPointer element = _entity ? _entity->getElement() : nullptr; + EntityTreePointer tree = element ? element->getTree() : nullptr; if (tree) { bool readSuccess = tree->tryLockForRead(); if (readSuccess) { diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index 97cf6a549a..92658b27a1 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -24,8 +24,8 @@ PhysicalEntitySimulation::~PhysicalEntitySimulation() { } void PhysicalEntitySimulation::init( - EntityTree* tree, - PhysicsEngine* physicsEngine, + EntityTreePointer tree, + PhysicsEnginePointer physicsEngine, EntityEditPacketSender* packetSender) { assert(tree); setEntityTree(tree); diff --git a/libraries/physics/src/PhysicalEntitySimulation.h b/libraries/physics/src/PhysicalEntitySimulation.h index 7599c7d1b5..aaf729dcb8 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.h +++ b/libraries/physics/src/PhysicalEntitySimulation.h @@ -30,7 +30,7 @@ public: PhysicalEntitySimulation(); ~PhysicalEntitySimulation(); - void init(EntityTree* tree, PhysicsEngine* engine, EntityEditPacketSender* packetSender); + void init(EntityTreePointer tree, PhysicsEnginePointer engine, EntityEditPacketSender* packetSender); virtual void addAction(EntityActionPointer action); virtual void applyActionChanges(); @@ -66,10 +66,13 @@ private: SetOfMotionStates _physicalObjects; // MotionStates of entities in PhysicsEngine VectorOfMotionStates _tempVector; // temporary array reference, valid immediately after getObjectsToRemove() (and friends) - PhysicsEngine* _physicsEngine = nullptr; + PhysicsEnginePointer _physicsEngine = nullptr; EntityEditPacketSender* _entityPacketSender = nullptr; uint32_t _lastStepSendPackets = 0; }; + +typedef std::shared_ptr PhysicalEntitySimulationPointer; + #endif // hifi_PhysicalEntitySimulation_h diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 040055b313..2931f58ccd 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -17,9 +17,6 @@ #include "ThreadSafeDynamicsWorld.h" #include "PhysicsLogging.h" -static uint32_t _numSubsteps; - -// static uint32_t PhysicsEngine::getNumSubsteps() { return _numSubsteps; } diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index 67b38323cc..ad7820a311 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -44,8 +44,7 @@ typedef QVector CollisionEvents; class PhysicsEngine { public: - // TODO: find a good way to make this a non-static method - static uint32_t getNumSubsteps(); + uint32_t getNumSubsteps(); PhysicsEngine(const glm::vec3& offset); ~PhysicsEngine(); @@ -129,6 +128,10 @@ private: QHash _objectActions; btHashMap _collisionMasks; + + uint32_t _numSubsteps; }; +typedef std::shared_ptr PhysicsEnginePointer; + #endif // hifi_PhysicsEngine_h diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 17a32e7910..4967778cb4 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -12,6 +12,7 @@ #ifndef hifi_SharedUtil_h #define hifi_SharedUtil_h +#include #include #include @@ -123,11 +124,17 @@ private: bool isBetween(int64_t value, int64_t max, int64_t min); -/// \return bool is the float NaN +/// \return bool is the float NaN bool isNaN(float value); QString formatUsecTime(float usecs, int prec = 3); QString formatSecondsElapsed(float seconds); bool similarStrings(const QString& stringA, const QString& stringB); +template +uint qHash(const std::shared_ptr& ptr, uint seed = 0) +{ + return qHash(ptr.get(), seed); +} + #endif // hifi_SharedUtil_h