octree uses shared pointers

This commit is contained in:
Seth Alves 2015-09-06 10:31:12 -07:00
parent 9a8bd607b5
commit 31fcd55d47
72 changed files with 748 additions and 624 deletions
assignment-client/src
interface/src
libraries

View file

@ -36,7 +36,7 @@ EntityServer::~EntityServer() {
_pruneDeletedEntitiesTimer->deleteLater();
}
EntityTree* tree = (EntityTree*)_tree;
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_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<EntityTree*>(_tree);
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_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<EntityTree*>(_tree);
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
bool hasMoreToSend = true;
packetsSent = 0;
@ -122,7 +123,7 @@ int EntityServer::sendSpecialPackets(const SharedNodePointer& node, OctreeQueryN
}
void EntityServer::pruneDeletedEntities() {
EntityTree* tree = static_cast<EntityTree*>(_tree);
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_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<EntityTree*>(_tree);
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
tree->setWantEditLogging(wantEditLogging);
}

View file

@ -47,7 +47,7 @@ public slots:
void pruneDeletedEntities();
protected:
virtual Octree* createTree();
virtual OctreePointer createTree();
private slots:
void handleEntityPacket(QSharedPointer<NLPacket> packet, SharedNodePointer senderNode);

View file

@ -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);
}
}
}

View file

@ -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)

View file

@ -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) {

View file

@ -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<NLPacket> 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;

View file

@ -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<AvatarManager>()->clearOtherAvatars();
_physicsEngine.deleteObjects(DependencyManager::get<AvatarManager>()->getObjectsToDelete());
_physicsEngine->deleteObjects(DependencyManager::get<AvatarManager>()->getObjectsToDelete());
DependencyManager::destroy<OffscreenUi>();
DependencyManager::destroy<AvatarManager>();
@ -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<EntityItemID> 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<EntityScriptingInterface>();
@ -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<SoundCache>().data(), &SoundCache::getSound);
connect(tree.get(), &EntityTree::newCollisionSoundURL, DependencyManager::get<SoundCache>().data(), &SoundCache::getSound);
connect(_myAvatar, &MyAvatar::newCollisionSoundURL, DependencyManager::get<SoundCache>().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<AvatarManager>().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());
}
}

View file

@ -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)

View file

@ -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,

View file

@ -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)
{

View file

@ -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:

View file

@ -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;

View file

@ -107,7 +107,7 @@ void EntityTreeRenderer::clear() {
void EntityTreeRenderer::init() {
OctreeRenderer::init();
EntityTree* entityTree = static_cast<EntityTree*>(_tree);
EntityTreePointer entityTree = std::static_pointer_cast<EntityTree>(_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<EntityTree*>(_tree)->findEntityByEntityItemID(entityItemID);
EntityItemPointer entity = std::static_pointer_cast<EntityTree>(_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<EntityTree*>(_tree)->setFBXService(this);
std::static_pointer_cast<EntityTree>(_tree)->setFBXService(this);
}
void EntityTreeRenderer::update() {
if (_tree && !_shuttingDown) {
EntityTree* tree = static_cast<EntityTree*>(_tree);
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_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<EntityTree*>(_tree)->findEntities(avatarPosition, radius, foundEntities);
std::static_pointer_cast<EntityTree>(_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<DeferredLightingEffect>();
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<EntityTreeElement*>(element);
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
EntityItems& entityItems = entityTreeElement->getEntities();
@ -684,7 +686,7 @@ int EntityTreeRenderer::getBoundaryLevelAdjust() const {
void EntityTreeRenderer::processEraseMessage(NLPacket& packet, const SharedNodePointer& sourceNode) {
static_cast<EntityTree*>(_tree)->processEraseMessage(packet, sourceNode);
std::static_pointer_cast<EntityTree>(_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<EntityTree*>(_tree);
EntityTreePointer entityTree = std::static_pointer_cast<EntityTree>(_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<EntityTree*>(_tree)->findEntityByID(entityID);
auto entity = std::static_pointer_cast<EntityTree>(_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<EntityTree*>(_tree);
EntityTreePointer entityTree = std::static_pointer_cast<EntityTree>(_tree);
const QUuid& myNodeID = DependencyManager::get<NodeList>()->getSessionUUID();
playEntityCollisionSound(myNodeID, entityTree, idA, collision);
playEntityCollisionSound(myNodeID, entityTree, idB, collision);

View file

@ -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<EntityTree*>(_tree); }
EntityTreePointer getTree() { return std::static_pointer_cast<EntityTree>(_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<ZoneEntityItem> 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<EntityItemID, EntityScriptDetails> _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;

View file

@ -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

View file

@ -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();

View file

@ -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);
}

View file

@ -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);

View file

@ -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<PhysicalEntitySimulation*>(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;
}

View file

@ -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);

View file

@ -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<EntityTreeElement*>(element);
bool AddEntityOperator::preRecursion(OctreeElementPointer element) {
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(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

View file

@ -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;

View file

@ -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<EntityTreeElement*>(element);
bool DeleteEntityOperator::preRecursion(OctreeElementPointer element) {
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(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<EntityTreeElement*>(element);
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
entityTreeElement->pruneChildren(); // take this opportunity to prune any empty leaves
return keepSearching; // if we haven't yet found it, keep looking
}

View file

@ -16,7 +16,7 @@ class EntityToDeleteDetails {
public:
EntityItemPointer entity;
AACube cube;
EntityTreeElement* containingElement;
EntityTreeElementPointer containingElement;
};
typedef QSet<EntityToDeleteDetails> 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

View file

@ -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

View file

@ -33,9 +33,11 @@
class EntitySimulation;
class EntityTreeElement;
class EntityTreeElementExtraEncodeData;
class EntityActionInterface;
class EntityTree;
typedef std::shared_ptr<EntityTree> EntityTreePointer;
typedef std::shared_ptr<EntityActionInterface> EntityActionPointer;
typedef std::shared_ptr<EntityTreeElement> 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

View file

@ -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,

View file

@ -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

View file

@ -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);

View file

@ -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.

View file

@ -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<EntityTree>(shared_from_this()));
return std::static_pointer_cast<OctreeElement>(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<EntityItemID> 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<FindNearPointArgs*>(extraData);
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(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<FindAllNearPointArgs*>(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<EntityTreeElement*>(element);
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(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<EntityItemPointer> _foundEntities;
};
bool EntityTree::findInCubeOperation(OctreeElement* element, void* extraData) {
bool EntityTree::findInCubeOperation(OctreeElementPointer element, void* extraData) {
FindEntitiesInCubeArgs* args = static_cast<FindEntitiesInCubeArgs*>(extraData);
if (element->getAACube().touches(args->_cube)) {
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
entityTreeElement->getEntities(args->_cube, args->_foundEntities);
return true;
}
@ -535,10 +543,10 @@ public:
QVector<EntityItemPointer> _foundEntities;
};
bool EntityTree::findInBoxOperation(OctreeElement* element, void* extraData) {
bool EntityTree::findInBoxOperation(OctreeElementPointer element, void* extraData) {
FindEntitiesInBoxArgs* args = static_cast<FindEntitiesInBoxArgs*>(extraData);
if (element->getAACube().touches(args->_box)) {
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(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<EntityTreeElementExtraEncodeData*>(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<EntityItemID, EntityTreeElement*> i(_entityToElementMap);
QHashIterator<EntityItemID, EntityTreeElementPointer> 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<EntityTreeElement*>(element);
bool ContentsDimensionOperator::preRecursion(OctreeElementPointer element) {
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(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<EntityTreeElement*>(element);
qCDebug(entities) << "EntityTreeElement [" << entityTreeElement << "]";
bool DebugOperator::preRecursion(OctreeElementPointer element) {
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(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<EntityTreeElement*>(element);
bool PruneOperator::postRecursion(OctreeElementPointer element) {
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
entityTreeElement->pruneChildren();
return true;
}
@ -1013,7 +1021,8 @@ void EntityTree::pruneTree() {
recurseTreeWithOperator(&theOperator);
}
QVector<EntityItemID> EntityTree::sendEntities(EntityEditPacketSender* packetSender, EntityTree* localTree, float x, float y, float z) {
QVector<EntityItemID> 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<EntityItemID> EntityTree::sendEntities(EntityEditPacketSender* packetSen
return newEntityIDs;
}
bool EntityTree::sendEntitiesOperation(OctreeElement* element, void* extraData) {
bool EntityTree::sendEntitiesOperation(OctreeElementPointer element, void* extraData) {
SendEntitiesOperationArgs* args = static_cast<SendEntitiesOperationArgs*>(extraData);
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(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);

View file

@ -17,6 +17,10 @@
#include <Octree.h>
class EntityTree;
typedef std::shared_ptr<EntityTree> 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<EntityItemID>* 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<EntityTreeElement*>(_rootElement); }
EntityTreeElementPointer getRoot() {
if (!_rootElement) {
createRootElement();
}
return std::static_pointer_cast<EntityTreeElement>(_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<EntityItemID> sendEntities(EntityEditPacketSender* packetSender, EntityTree* localTree, float x, float y, float z);
QVector<EntityItemID> 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<EntityTree>(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<quint64, QUuid> _recentlyDeletedEntityItemIDs;
EntityItemFBXService* _fbxService;
QHash<EntityItemID, EntityTreeElement*> _entityToElementMap;
QHash<EntityItemID, EntityTreeElementPointer> _entityToElementMap;
EntitySimulation* _simulation;

View file

@ -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<EntityTreeElement>(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<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(this));
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData
= static_cast<EntityTreeElementExtraEncodeData*>(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<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(childElement));
= static_cast<EntityTreeElementExtraEncodeData*>(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<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(this));
entityTreeElementExtraEncodeData =
static_cast<EntityTreeElementExtraEncodeData*>(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()) {

View file

@ -25,6 +25,7 @@ typedef QVector<EntityItemPointer> EntityItems;
class EntityTree;
class EntityTreeElement;
typedef std::shared_ptr<EntityTreeElement> 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<EntityTreeElement>(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<EntityTreeElement>(shared_from_this());
}
OctreeElementPointer getThisOctreeElementPointer() {
return std::static_pointer_cast<OctreeElement>(shared_from_this());
}
const ConstOctreeElementPointer getConstThisOctreeElementPointer() const {
return std::static_pointer_cast<const OctreeElement>(shared_from_this());
}
protected:
virtual void init(unsigned char * octalCode);
EntityTree* _myTree;
EntityTreePointer _myTree;
EntityItems* _entityItems;
};

View file

@ -23,7 +23,7 @@ void EntityTreeHeadlessViewer::init() {
OctreeHeadlessViewer::init();
if (!_simulation) {
SimpleEntitySimulation* simpleSimulation = new SimpleEntitySimulation();
EntityTree* entityTree = static_cast<EntityTree*>(_tree);
EntityTreePointer entityTree = std::static_pointer_cast<EntityTree>(_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<EntityTree*>(_tree);
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_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<EntityTree*>(_tree)->processEraseMessage(packet, sourceNode);
std::static_pointer_cast<EntityTree>(_tree)->processEraseMessage(packet, sourceNode);
}

View file

@ -36,14 +36,18 @@ public:
void update();
EntityTree* getTree() { return (EntityTree*)_tree; }
EntityTreePointer getTree() { return std::static_pointer_cast<EntityTree>(_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;
};

View file

@ -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;

View file

@ -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<EntityTreeElement*>(element);
bool MovingEntitiesOperator::preRecursion(OctreeElementPointer element) {
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(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<EntityTreeElement*>(element);
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(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) {

View file

@ -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<EntityToMoveDetails> _entitiesToMove;
quint64 _changeTime;
int _foundOldCount;
int _foundNewCount;
int _lookingCount;
bool shouldRecurseSubTree(OctreeElement* element);
bool shouldRecurseSubTree(OctreeElementPointer element);
bool _wantDebug;
};

View file

@ -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;

View file

@ -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;

View file

@ -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<EntityTreeElement*>(element);
bool RecurseOctreeToMapOperator::postRecursion(OctreeElementPointer element) {
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
const EntityItems& entities = entityTreeElement->getEntities();
QVariantList entitiesQList = qvariant_cast<QVariantList>(_map["Entities"]);

View file

@ -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;
};

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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<EntityTreeElement*>(element);
bool UpdateEntityOperator::preRecursion(OctreeElementPointer element) {
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(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<EntityTreeElement*>(element);
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(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

View file

@ -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;
};

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -15,7 +15,8 @@
#include <EnvironmentData.h>
#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

View file

@ -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<RayArgs*>(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<SphereArgs*>(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<CapsuleArgs*>(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<ContentArgs*>(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<GetElementEnclosingArgs*>(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;
}

View file

@ -14,6 +14,7 @@
#include <set>
#include <SimpleMovingAverage.h>
#include <memory>
class CoverageMap;
class ReadBitstreamToTreeParams;
@ -22,7 +23,7 @@ class OctreeElement;
class OctreeElementBag;
class OctreePacketData;
class Shape;
typedef std::shared_ptr<Octree> OctreePointer;
#include "JurisdictionMap.h"
#include "ViewFrustum.h"
@ -35,19 +36,18 @@ class Shape;
#include <QObject>
#include <QReadWriteLock>
extern QVector<QString> 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<uint, AACube> 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<Octree> {
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;
};

View file

@ -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<OctreeElementUpdateHook*> 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

View file

@ -33,27 +33,30 @@ class OctreePacketData;
class ReadBitstreamToTreeParams;
class Shape;
class VoxelSystem;
typedef std::shared_ptr<OctreeElement> OctreeElementPointer;
typedef std::shared_ptr<const OctreeElement> ConstOctreeElementPointer;
typedef std::shared_ptr<Octree> 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<OctreeElement> {
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<OctreeElementDeleteHook*> _deleteHooks;

View file

@ -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<OctreeElement*>::iterator front = _bagElements.begin();
QSet<OctreeElementPointer>::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);
}

View file

@ -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<OctreeElement*> _bagElements;
QSet<OctreeElementPointer> _bagElements;
bool _hooked;
};
typedef QMap<const OctreeElement*,void*> OctreeElementExtraEncodeData;
typedef QMap<const OctreeElement*, void*> OctreeElementExtraEncodeData;
#endif // hifi_OctreeElementBag_h

View file

@ -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 */ }

View file

@ -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),

View file

@ -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<BackupRule> _backupRules;
bool _debugTimestampNow;
quint64 _lastTimeDebug;

View file

@ -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<RenderArgs*>(extraData);
if (element->isInView(*args->_viewFrustum)) {
if (element->hasContent()) {

View file

@ -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;

View file

@ -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++;

View file

@ -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();

View file

@ -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) {

View file

@ -24,8 +24,8 @@ PhysicalEntitySimulation::~PhysicalEntitySimulation() {
}
void PhysicalEntitySimulation::init(
EntityTree* tree,
PhysicsEngine* physicsEngine,
EntityTreePointer tree,
PhysicsEnginePointer physicsEngine,
EntityEditPacketSender* packetSender) {
assert(tree);
setEntityTree(tree);

View file

@ -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<PhysicalEntitySimulation> PhysicalEntitySimulationPointer;
#endif // hifi_PhysicalEntitySimulation_h

View file

@ -17,9 +17,6 @@
#include "ThreadSafeDynamicsWorld.h"
#include "PhysicsLogging.h"
static uint32_t _numSubsteps;
// static
uint32_t PhysicsEngine::getNumSubsteps() {
return _numSubsteps;
}

View file

@ -44,8 +44,7 @@ typedef QVector<Collision> 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<QUuid, EntityActionPointer> _objectActions;
btHashMap<btHashInt, int16_t> _collisionMasks;
uint32_t _numSubsteps;
};
typedef std::shared_ptr<PhysicsEngine> PhysicsEnginePointer;
#endif // hifi_PhysicsEngine_h

View file

@ -12,6 +12,7 @@
#ifndef hifi_SharedUtil_h
#define hifi_SharedUtil_h
#include <memory>
#include <math.h>
#include <stdint.h>
@ -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 <typename T>
uint qHash(const std::shared_ptr<T>& ptr, uint seed = 0)
{
return qHash(ptr.get(), seed);
}
#endif // hifi_SharedUtil_h