mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 05:44:12 +02:00
octree uses shared pointers
This commit is contained in:
parent
9a8bd607b5
commit
31fcd55d47
72 changed files with 748 additions and 624 deletions
assignment-client/src
entities
octree
interface/src
libraries
entities-renderer/src
EntityTreeRenderer.cppEntityTreeRenderer.hRenderableLightEntityItem.cppRenderableLightEntityItem.hRenderableModelEntityItem.cppRenderableModelEntityItem.hRenderablePolyVoxEntityItem.cppRenderablePolyVoxEntityItem.h
entities/src
AddEntityOperator.cppAddEntityOperator.hDeleteEntityOperator.cppDeleteEntityOperator.hEntityItem.cppEntityItem.hEntityScriptingInterface.cppEntityScriptingInterface.hEntitySimulation.cppEntitySimulation.hEntityTree.cppEntityTree.hEntityTreeElement.cppEntityTreeElement.hEntityTreeHeadlessViewer.cppEntityTreeHeadlessViewer.hLineEntityItem.hMovingEntitiesOperator.cppMovingEntitiesOperator.hPolyLineEntityItem.hPolyVoxEntityItem.hRecurseOctreeToMapOperator.cppRecurseOctreeToMapOperator.hSphereEntityItem.cppSphereEntityItem.hTextEntityItem.cppTextEntityItem.hUpdateEntityOperator.cppUpdateEntityOperator.hWebEntityItem.cppWebEntityItem.hZoneEntityItem.cppZoneEntityItem.h
octree/src
Octree.cppOctree.hOctreeElement.cppOctreeElement.hOctreeElementBag.cppOctreeElementBag.hOctreeHeadlessViewer.hOctreePersistThread.cppOctreePersistThread.hOctreeRenderer.cppOctreeRenderer.hOctreeSceneStats.cppOctreeSceneStats.h
physics/src
EntityMotionState.cppPhysicalEntitySimulation.cppPhysicalEntitySimulation.hPhysicsEngine.cppPhysicsEngine.h
shared/src
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ public slots:
|
|||
void pruneDeletedEntities();
|
||||
|
||||
protected:
|
||||
virtual Octree* createTree();
|
||||
virtual OctreePointer createTree();
|
||||
|
||||
private slots:
|
||||
void handleEntityPacket(QSharedPointer<NLPacket> packet, SharedNodePointer senderNode);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"]);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */ }
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -24,8 +24,8 @@ PhysicalEntitySimulation::~PhysicalEntitySimulation() {
|
|||
}
|
||||
|
||||
void PhysicalEntitySimulation::init(
|
||||
EntityTree* tree,
|
||||
PhysicsEngine* physicsEngine,
|
||||
EntityTreePointer tree,
|
||||
PhysicsEnginePointer physicsEngine,
|
||||
EntityEditPacketSender* packetSender) {
|
||||
assert(tree);
|
||||
setEntityTree(tree);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -17,9 +17,6 @@
|
|||
#include "ThreadSafeDynamicsWorld.h"
|
||||
#include "PhysicsLogging.h"
|
||||
|
||||
static uint32_t _numSubsteps;
|
||||
|
||||
// static
|
||||
uint32_t PhysicsEngine::getNumSubsteps() {
|
||||
return _numSubsteps;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue