Merge branch 'master' into homer

Conflicts:
	assignment-client/src/octree/OctreeSendThread.cpp
	interface/src/Application.cpp
	libraries/entities-renderer/src/EntityTreeRenderer.cpp
	libraries/entities/src/EntityItem.cpp
	libraries/entities/src/EntityTree.cpp
	libraries/entities/src/EntityTreeElement.cpp
	libraries/entities/src/EntityTreeElement.h
	libraries/entities/src/EntityTreeHeadlessViewer.cpp
	libraries/entities/src/RecurseOctreeToMapOperator.cpp
	libraries/octree/src/Octree.h
	libraries/physics/src/EntityMotionState.cpp
This commit is contained in:
Brad Davis 2015-09-11 16:31:18 -07:00
commit 9b81842850
89 changed files with 966 additions and 813 deletions

View file

@ -36,7 +36,7 @@ EntityServer::~EntityServer() {
_pruneDeletedEntitiesTimer->deleteLater();
}
EntityTree* tree = (EntityTree*)_tree;
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
tree->removeNewlyCreatedHook(this);
}
@ -50,8 +50,9 @@ OctreeQueryNode* EntityServer::createOctreeQueryNode() {
return new EntityNodeData();
}
Octree* EntityServer::createTree() {
EntityTree* tree = new EntityTree(true);
OctreePointer EntityServer::createTree() {
EntityTreePointer tree = EntityTreePointer(new EntityTree(true));
tree->createRootElement();
tree->addNewlyCreatedHook(this);
if (!_entitySimulation) {
SimpleEntitySimulation* simpleSimulation = new SimpleEntitySimulation();
@ -82,7 +83,7 @@ bool EntityServer::hasSpecialPacketsToSend(const SharedNodePointer& node) {
if (nodeData) {
quint64 deletedEntitiesSentAt = nodeData->getLastDeletedEntitiesSentAt();
EntityTree* tree = static_cast<EntityTree*>(_tree);
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
shouldSendDeletedEntities = tree->hasEntitiesDeletedSince(deletedEntitiesSentAt);
}
@ -97,7 +98,7 @@ int EntityServer::sendSpecialPackets(const SharedNodePointer& node, OctreeQueryN
quint64 deletedEntitiesSentAt = nodeData->getLastDeletedEntitiesSentAt();
quint64 deletePacketSentAt = usecTimestampNow();
EntityTree* tree = static_cast<EntityTree*>(_tree);
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
bool hasMoreToSend = true;
packetsSent = 0;
@ -122,7 +123,7 @@ int EntityServer::sendSpecialPackets(const SharedNodePointer& node, OctreeQueryN
}
void EntityServer::pruneDeletedEntities() {
EntityTree* tree = static_cast<EntityTree*>(_tree);
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
if (tree->hasAnyDeletedEntities()) {
quint64 earliestLastDeletedEntitiesSent = usecTimestampNow() + 1; // in the future
@ -147,8 +148,6 @@ void EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectio
qDebug("wantEditLogging=%s", debug::valueOf(wantEditLogging));
EntityTree* tree = static_cast<EntityTree*>(_tree);
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
tree->setWantEditLogging(wantEditLogging);
}

View file

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

View file

@ -338,9 +338,9 @@ void OctreeQueryNode::dumpOutOfView() {
int outOfView = 0;
OctreeElementBag tempBag;
while (!elementBag.isEmpty()) {
OctreeElement* node = elementBag.extract();
if (node->isInView(_currentViewFrustum)) {
tempBag.insert(node);
OctreeElementPointer elementToCheck = elementBag.extract();
if (elementToCheck->isInView(_currentViewFrustum)) {
tempBag.insert(elementToCheck);
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 elementToKeepInBag = tempBag.extract();
if (elementToKeepInBag->isInView(_currentViewFrustum)) {
elementBag.insert(elementToKeepInBag);
}
}
}

View file

@ -421,7 +421,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus
lockWaitElapsedUsec = (float)(lockWaitEnd - lockWaitStart);
quint64 encodeStart = usecTimestampNow();
OctreeElement* subTree = nodeData->elementBag.extract();
OctreeElementPointer subTree = nodeData->elementBag.extract();
/* TODO: Looking for a way to prevent locking and encoding a tree that is not
// going to result in any packets being sent...
@ -430,7 +430,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus
// and we've already seen at least one duplicate packet, then we probably don't need
// to lock the tree and encode, because the result should be that no bytes will be
// encoded, and this will be a duplicate packet from the last one we sent...
OctreeElement* root = _myServer->getOctree()->getRoot();
OctreeElementPointer root = _myServer->getOctree()->getRoot();
bool skipEncode = false;
if (
(subTree == root)

View file

@ -280,8 +280,7 @@ OctreeServer::~OctreeServer() {
// cleanup our tree here...
qDebug() << qPrintable(_safeServerName) << "server START cleaning up octree... [" << this << "]";
delete _tree;
_tree = NULL;
_tree.reset();
qDebug() << qPrintable(_safeServerName) << "server DONE cleaning up octree... [" << this << "]";
if (_instance == this) {

View file

@ -42,7 +42,7 @@ public:
bool wantsDebugReceiving() const { return _debugReceiving; }
bool wantsVerboseDebug() const { return _verboseDebug; }
Octree* getOctree() { return _tree; }
OctreePointer getOctree() { return _tree; }
JurisdictionMap* getJurisdiction() { return _jurisdiction; }
int getPacketsPerClientPerInterval() const { return std::min(_packetsPerClientPerInterval,
@ -131,7 +131,7 @@ private slots:
void handleJurisdictionRequestPacket(QSharedPointer<NLPacket> packet, SharedNodePointer senderNode);
protected:
virtual Octree* createTree() = 0;
virtual OctreePointer createTree() = 0;
bool readOptionBool(const QString& optionName, const QJsonObject& settingsSectionObject, bool& result);
bool readOptionInt(const QString& optionName, const QJsonObject& settingsSectionObject, int& result);
bool readOptionString(const QString& optionName, const QJsonObject& settingsSectionObject, QString& result);
@ -160,7 +160,7 @@ protected:
QString _persistAsFileType;
int _packetsPerClientPerInterval;
int _packetsTotalPerInterval;
Octree* _tree; // this IS a reaveraging tree
OctreePointer _tree; // this IS a reaveraging tree
bool _wantPersist;
bool _debugSending;
bool _debugReceiving;

View file

@ -144,7 +144,7 @@ controller.prototype.checkPointer = function() {
Script.setTimeout(function() {
var props = Entities.getEntityProperties(self.pointer);
Entities.editEntity(self.pointer, {
lifetime: props.age + EXTRA_TIME
lifetime: props.age + EXTRA_TIME + LIFETIME
});
self.checkPointer();
}, POINTER_CHECK_TIME);

View file

@ -260,6 +260,7 @@ var toolBar = (function () {
cameraManager.disable();
} else {
hasShownPropertiesTool = false;
cameraManager.enable();
entityListTool.setVisible(true);
gridTool.setVisible(true);
grid.setEnabled(true);
@ -669,11 +670,15 @@ function mouseMove(event) {
lastMousePosition = { x: event.x, y: event.y };
highlightEntityUnderCursor(lastMousePosition, false);
idleMouseTimerId = Script.setTimeout(handleIdleMouse, IDLE_MOUSE_TIMEOUT);
}
function handleIdleMouse() {
idleMouseTimerId = null;
if (isActive) {
highlightEntityUnderCursor(lastMousePosition, true);
}
}
function highlightEntityUnderCursor(position, accurateRay) {
@ -797,7 +802,6 @@ function mouseClickEvent(event) {
selectionDisplay.select(selectedEntityID, event);
if (Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT)) {
cameraManager.enable();
cameraManager.focus(selectionManager.worldPosition,
selectionManager.worldDimensions,
Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
@ -1138,7 +1142,6 @@ Controller.keyReleaseEvent.connect(function (event) {
} else if (event.text == "f") {
if (isActive) {
if (selectionManager.hasSelection()) {
cameraManager.enable();
cameraManager.focus(selectionManager.worldPosition,
selectionManager.worldDimensions,
Menu.isOptionChecked(MENU_EASE_ON_FOCUS));

View file

@ -1,5 +1,7 @@
(function() {
Script.include("../libraries/utils.js");
// Script.include("../libraries/utils.js");
//Need absolute path for now, for testing before PR merge and s3 cloning. Will change post-merge
Script.include("https://hifi-public.s3.amazonaws.com/scripts/libraries/utils.js");
GRAB_FRAME_USER_DATA_KEY = "grabFrame";
this.userData = {};
@ -18,13 +20,14 @@
var self = this;
var stopSetting = JSON.stringify({
running: false
});
var startSetting = JSON.stringify({
running: true
});
var timeSinceLastMoved = 0;
var RESET_TIME_THRESHOLD = 5;
var DISTANCE_FROM_HOME_THRESHOLD = 0.5;
var HOME_POSITION = {
x: 549.12,
y: 495.555,
z: 503.77
};
this.getUserData = function() {
@ -40,14 +43,26 @@
}
this.update = function(deltaTime) {
self.properties = Entities.getEntityProperties(self.entityId);
self.getUserData();
self.properties = Entities.getEntityProperties(self.entityId);
if (Vec3.length(self.properties.velocity) < 0.1 && Vec3.distance(HOME_POSITION, self.properties.position) > DISTANCE_FROM_HOME_THRESHOLD) {
timeSinceLastMoved += deltaTime;
if (timeSinceLastMoved > RESET_TIME_THRESHOLD) {
self.reset();
timeSinceLastMoved = 0;
}
} else {
timeSinceLastMoved = 0;
}
if (self.userData.grabKey && self.userData.grabKey.activated === true) {
if (self.activated !== true) {
//We were just grabbed, so create a particle system
self.grab();
Entities.editEntity(self.paintStream, {
animationSettings: startSetting
});
self.activated = true;
}
//Move emitter to where entity is always when its activated
self.sprayStream();
@ -59,6 +74,54 @@
}
}
this.grab = function() {
self.activated = true;
var animationSettings = JSON.stringify({
fps: 30,
loop: true,
firstFrame: 1,
lastFrame: 10000,
running: true
});
this.paintStream = Entities.addEntity({
type: "ParticleEffect",
animationSettings: animationSettings,
position: this.properties.position,
textures: "https://raw.githubusercontent.com/ericrius1/SantasLair/santa/assets/smokeparticle.png",
emitVelocity: ZERO_VEC,
emitAcceleration: ZERO_VEC,
velocitySpread: {
x: .02,
y: .02,
z: 0.02
},
emitRate: 100,
particleRadius: 0.01,
color: {
red: 170,
green: 20,
blue: 150
},
lifetime: 500, //probably wont be holding longer than this straight
});
}
this.letGo = function() {
self.activated = false;
Entities.deleteEntity(this.paintStream);
}
this.reset = function() {
Entities.editEntity(self.entityId, {
position: HOME_POSITION,
rotation: Quat.fromPitchYawRollDegrees(0, 0, 0),
angularVelocity: ZERO_VEC,
velocity: ZERO_VEC
});
}
this.sprayStream = function() {
var forwardVec = Quat.getFront(self.properties.rotation);
forwardVec = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, 90, 0), forwardVec);
@ -134,9 +197,9 @@
blue: randInt(190, 250)
},
dimensions: {
x: 5,
y: 5,
z: 5
x: 50,
y: 50,
z: 50
},
lifetime: 100
});
@ -167,41 +230,8 @@
}
setEntityCustomData(GRAB_FRAME_USER_DATA_KEY, this.entityId, data);
}
this.initialize();
}
this.initialize = function() {
var animationSettings = JSON.stringify({
fps: 30,
loop: true,
firstFrame: 1,
lastFrame: 10000,
running: false
});
this.paintStream = Entities.addEntity({
type: "ParticleEffect",
animationSettings: animationSettings,
position: this.properties.position,
textures: "https://raw.githubusercontent.com/ericrius1/SantasLair/santa/assets/smokeparticle.png",
emitVelocity: ZERO_VEC,
emitAcceleration: ZERO_VEC,
velocitySpread: {
x: .02,
y: .02,
z: 0.02
},
emitRate: 100,
particleRadius: 0.01,
color: {
red: 170,
green: 20,
blue: 150
},
lifespan: 5,
});
}
this.unload = function() {
Script.update.disconnect(this.update);

View file

@ -49,7 +49,7 @@ EntityListTool = function(opts) {
var selectedIDs = [];
for (var i = 0; i < selectionManager.selections.length; i++) {
selectedIDs.push(selectionManager.selections[i].id);
selectedIDs.push(selectionManager.selections[i].id); // ?
}
var data = {
@ -70,7 +70,6 @@ EntityListTool = function(opts) {
}
selectionManager.setSelections(entityIDs);
if (data.focus) {
cameraManager.enable();
cameraManager.focus(selectionManager.worldPosition,
selectionManager.worldDimensions,
Menu.isOptionChecked(MENU_EASE_ON_FOCUS));

View file

@ -8,67 +8,31 @@
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
var scriptURL = "entityScripts/sprayPaintCan.js";
//Just temporarily using my own bucket here so others can test the entity. Once PR is tested and merged, then the entity script will appear in its proper place in S3, and I wil switch it
var scriptURL = "https://hifi-public.s3.amazonaws.com/eric/scripts/sprayPaintCan.js?=v1";
var modelURL = "https://hifi-public.s3.amazonaws.com/eric/models/paintcan.fbx";
var center = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Camera.getOrientation())));
var paintGun = Entities.addEntity({
var sprayCan = Entities.addEntity({
type: "Model",
modelURL: "https://hifi-public.s3.amazonaws.com/eric/models/sprayGun.fbx?=v4",
position: center,
name: "spraycan",
modelURL: modelURL,
position: {x: 549.12, y:495.55, z:503.77},
rotation: {x: 0, y: 0, z: 0, w: 1},
dimensions: {
x: 0.03,
y: 0.15,
z: 0.34
x: 0.07,
y: 0.17,
z: 0.07
},
collisionsWillMove: true,
shapeType: 'box',
script: scriptURL
});
var whiteboard = Entities.addEntity({
type: "Box",
position: center,
dimensions: {
x: 2,
y: 1.5,
z: .01
},
rotation: orientationOf(Vec3.subtract(MyAvatar.position, center)),
color: {
red: 250,
green: 250,
blue: 250
},
// visible: false
script: scriptURL,
gravity: {x: 0, y: -0.5, z: 0},
velocity: {x: 0, y: -1, z: 0}
});
function cleanup() {
Entities.deleteEntity(paintGun);
Entities.deleteEntity(whiteboard);
Entities.deleteEntity(sprayCan);
}
Script.scriptEnding.connect(cleanup);
function orientationOf(vector) {
var Y_AXIS = {
x: 0,
y: 1,
z: 0
};
var X_AXIS = {
x: 1,
y: 0,
z: 0
};
var theta = 0.0;
var RAD_TO_DEG = 180.0 / Math.PI;
var direction, yaw, pitch;
direction = Vec3.normalize(vector);
yaw = Quat.angleAxis(Math.atan2(direction.x, direction.z) * RAD_TO_DEG, Y_AXIS);
pitch = Quat.angleAxis(Math.asin(-direction.y) * RAD_TO_DEG, X_AXIS);
return Quat.multiply(yaw, pitch);
}

View file

@ -335,10 +335,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()),
@ -372,6 +372,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
{
setInstance(this);
_entityClipboard->createRootElement();
_pluginContainer = new PluginContainerProxy();
Plugin::setContainer(_pluginContainer);
#ifdef Q_OS_WIN
@ -861,7 +863,7 @@ void Application::emptyLocalCache() {
}
Application::~Application() {
EntityTree* tree = _entities.getTree();
EntityTreePointer tree = _entities.getTree();
tree->setSimulation(NULL);
_octreeProcessor.terminate();
@ -869,7 +871,7 @@ Application::~Application() {
Menu::getInstance()->deleteLater();
_physicsEngine.setCharacterController(NULL);
_physicsEngine->setCharacterController(NULL);
_myAvatar = NULL;
ModelEntityItem::cleanupLoadedAnimations();
@ -886,7 +888,7 @@ Application::~Application() {
DependencyManager::get<AvatarManager>()->clearOtherAvatars();
VectorOfMotionStates motionStates;
DependencyManager::get<AvatarManager>()->getObjectsToDelete(motionStates);
_physicsEngine.deleteObjects(motionStates);
_physicsEngine->deleteObjects(motionStates);
DependencyManager::destroy<OffscreenUi>();
DependencyManager::destroy<AvatarManager>();
@ -1513,7 +1515,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
break;
case Qt::Key_F: {
_physicsEngine.dumpNextStats();
_physicsEngine->dumpNextStats();
break;
}
@ -2395,7 +2397,7 @@ void Application::saveSettings() {
}
bool Application::importEntities(const QString& urlOrFilename) {
_entityClipboard.eraseAllOctreeElements();
_entityClipboard->eraseAllOctreeElements();
QUrl url(urlOrFilename);
@ -2404,15 +2406,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() {
@ -2457,10 +2459,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>();
@ -2475,10 +2477,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);
setAvatarUpdateThreading(Menu::getInstance()->isOptionChecked(MenuOption::EnableAvatarUpdateThreading));
@ -2861,17 +2863,18 @@ void Application::update(float deltaTime) {
PerformanceTimer perfTimer("physics");
_myAvatar->relayDriveKeysToCharacterController();
static VectorOfMotionStates motionStates;
_entitySimulation.getObjectsToDelete(motionStates);
_physicsEngine.deleteObjects(motionStates);
_physicsEngine->deleteObjects(motionStates);
_entities.getTree()->withWriteLock([&] {
_entitySimulation.getObjectsToAdd(motionStates);
_physicsEngine.addObjects(motionStates);
_physicsEngine->addObjects(motionStates);
});
_entities.getTree()->withWriteLock([&] {
_entitySimulation.getObjectsToChange(motionStates);
VectorOfMotionStates stillNeedChange = _physicsEngine.changeObjects(motionStates);
VectorOfMotionStates stillNeedChange = _physicsEngine->changeObjects(motionStates);
_entitySimulation.setObjectsToChange(stillNeedChange);
});
@ -2879,26 +2882,26 @@ void Application::update(float deltaTime) {
AvatarManager* avatarManager = DependencyManager::get<AvatarManager>().data();
avatarManager->getObjectsToDelete(motionStates);
_physicsEngine.deleteObjects(motionStates);
_physicsEngine->deleteObjects(motionStates);
avatarManager->getObjectsToAdd(motionStates);
_physicsEngine.addObjects(motionStates);
_physicsEngine->addObjects(motionStates);
avatarManager->getObjectsToChange(motionStates);
_physicsEngine.changeObjects(motionStates);
_physicsEngine->changeObjects(motionStates);
_entities.getTree()->withWriteLock([&] {
_physicsEngine.stepSimulation();
_physicsEngine->stepSimulation();
});
if (_physicsEngine.hasOutgoingChanges()) {
if (_physicsEngine->hasOutgoingChanges()) {
_entities.getTree()->withWriteLock([&] {
_entitySimulation.handleOutgoingChanges(_physicsEngine.getOutgoingChanges(), _physicsEngine.getSessionID());
avatarManager->handleOutgoingChanges(_physicsEngine.getOutgoingChanges());
_entitySimulation.handleOutgoingChanges(_physicsEngine->getOutgoingChanges(), _physicsEngine->getSessionID());
avatarManager->handleOutgoingChanges(_physicsEngine->getOutgoingChanges());
});
auto collisionEvents = _physicsEngine.getCollisionEvents();
auto collisionEvents = _physicsEngine->getCollisionEvents();
avatarManager->handleCollisionEvents(collisionEvents);
_physicsEngine.dumpStatsIfNecessary();
_physicsEngine->dumpStatsIfNecessary();
if (!_aboutToQuit) {
PerformanceTimer perfTimer("entities");
@ -4147,7 +4150,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) {
@ -4396,7 +4399,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;
@ -4405,7 +4408,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);
}
}
@ -4603,7 +4606,7 @@ void Application::checkSkeleton() {
_myAvatar->useFullAvatarURL(AvatarData::defaultFullAvatarModelUrl(), DEFAULT_FULL_AVATAR_MODEL_NAME);
} else {
_physicsEngine.setCharacterController(_myAvatar->getCharacterController());
_physicsEngine->setCharacterController(_myAvatar->getCharacterController());
}
}

View file

@ -209,7 +209,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; }
@ -538,11 +538,11 @@ private:
ShapeManager _shapeManager;
PhysicalEntitySimulation _entitySimulation;
PhysicsEngine _physicsEngine;
PhysicsEnginePointer _physicsEngine;
EntityTreeRenderer _entities;
EntityTreeRenderer _entityClipboardRenderer;
EntityTree _entityClipboard;
EntityTreePointer _entityClipboard;
ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc.
ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels)

View file

@ -152,7 +152,7 @@ void Avatar::simulate(float deltaTime) {
// update the avatar's position according to its referential
if (_referential) {
if (_referential->hasExtraData()) {
EntityTree* tree = Application::getInstance()->getEntities()->getTree();
EntityTreePointer tree = Application::getInstance()->getEntities()->getTree();
switch (_referential->type()) {
case Referential::MODEL:
_referential = new ModelReferential(_referential,

View file

@ -16,7 +16,7 @@
#include "InterfaceLogging.h"
#include "ModelReferential.h"
ModelReferential::ModelReferential(Referential* referential, EntityTree* tree, AvatarData* avatar) :
ModelReferential::ModelReferential(Referential* referential, EntityTreePointer tree, AvatarData* avatar) :
Referential(MODEL, avatar),
_tree(tree)
{
@ -39,7 +39,7 @@ ModelReferential::ModelReferential(Referential* referential, EntityTree* tree, A
}
}
ModelReferential::ModelReferential(const QUuid& entityID, EntityTree* tree, AvatarData* avatar) :
ModelReferential::ModelReferential(const QUuid& entityID, EntityTreePointer tree, AvatarData* avatar) :
Referential(MODEL, avatar),
_entityID(entityID),
_tree(tree)
@ -96,7 +96,7 @@ int ModelReferential::unpackExtraData(const unsigned char *sourceBuffer, int siz
return NUM_BYTES_RFC4122_UUID;
}
JointReferential::JointReferential(Referential* referential, EntityTree* tree, AvatarData* avatar) :
JointReferential::JointReferential(Referential* referential, EntityTreePointer tree, AvatarData* avatar) :
ModelReferential(referential, tree, avatar)
{
_type = JOINT;
@ -115,7 +115,7 @@ JointReferential::JointReferential(Referential* referential, EntityTree* tree, A
update();
}
JointReferential::JointReferential(uint32_t jointIndex, const QUuid& entityID, EntityTree* tree, AvatarData* avatar) :
JointReferential::JointReferential(uint32_t jointIndex, const QUuid& entityID, EntityTreePointer tree, AvatarData* avatar) :
ModelReferential(entityID, tree, avatar),
_jointIndex(jointIndex)
{

View file

@ -19,8 +19,8 @@ class Model;
class ModelReferential : public Referential {
public:
ModelReferential(Referential* ref, EntityTree* tree, AvatarData* avatar);
ModelReferential(const QUuid& entityID, EntityTree* tree, AvatarData* avatar);
ModelReferential(Referential* ref, EntityTreePointer tree, AvatarData* avatar);
ModelReferential(const QUuid& entityID, EntityTreePointer tree, AvatarData* avatar);
virtual void update();
protected:
@ -28,13 +28,13 @@ protected:
virtual int unpackExtraData(const unsigned char* sourceBuffer, int size);
QUuid _entityID;
EntityTree* _tree;
EntityTreePointer _tree;
};
class JointReferential : public ModelReferential {
public:
JointReferential(Referential* ref, EntityTree* tree, AvatarData* avatar);
JointReferential(uint32_t jointIndex, const QUuid& entityID, EntityTree* tree, AvatarData* avatar);
JointReferential(Referential* ref, EntityTreePointer tree, AvatarData* avatar);
JointReferential(uint32_t jointIndex, const QUuid& entityID, EntityTreePointer tree, AvatarData* avatar);
virtual void update();
protected:

View file

@ -458,7 +458,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;
@ -469,7 +469,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;
@ -1276,7 +1276,8 @@ void MyAvatar::initAnimGraph() {
//
// or run a local web-server
// python -m SimpleHTTPServer&
auto graphUrl = QUrl("https://gist.githubusercontent.com/hyperlogic/e58e0a24cc341ad5d060/raw/2a994bef7726ce8e9efcee7622b8b1a1b6b67490/ik-avatar.json");
// auto graphUrl = QUrl("http://localhost:8000/avatar.json");
auto graphUrl = QUrl("https://gist.githubusercontent.com/hyperlogic/e58e0a24cc341ad5d060/raw/8f824da2908fd89ad1befadd1d8f5d7b3b6efa66/ik-avatar.json");
_rig->initAnimGraph(graphUrl, _skeletonModel.getGeometry()->getFBXGeometry());
}

View file

@ -116,6 +116,17 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
params.leanForward = head->getFinalLeanForward();
params.torsoTwist = head->getTorsoTwist();
params.localHeadOrientation = head->getFinalOrientationInLocalFrame();
params.localHeadPitch = head->getFinalPitch();
params.localHeadYaw = head->getFinalYaw();
params.localHeadRoll = head->getFinalRoll();
params.isInHMD = qApp->getAvatarUpdater()->isHMDMode();
// get HMD position from sensor space into world space, and back into model space
glm::mat4 worldToModel = glm::inverse(createMatFromQuatAndPos(myAvatar->getOrientation(), myAvatar->getPosition()));
glm::vec3 yAxis(0.0f, 1.0f, 0.0f);
glm::vec3 hmdPosition = glm::angleAxis((float)M_PI, yAxis) * transformPoint(worldToModel * myAvatar->getSensorToWorldMatrix(), myAvatar->getHMDSensorPosition());
params.localHeadPosition = hmdPosition;
params.worldHeadOrientation = head->getFinalOrientationInWorldFrame();
params.eyeLookAt = head->getLookAtPosition();
params.eyeSaccade = head->getSaccade();

View file

@ -40,7 +40,7 @@ void AnimInverseKinematics::loadPoses(const AnimPoseVec& poses) {
void AnimInverseKinematics::computeAbsolutePoses(AnimPoseVec& absolutePoses) const {
int numJoints = (int)_relativePoses.size();
absolutePoses.clear();
absolutePoses.reserve(numJoints);
absolutePoses.resize(numJoints);
assert(numJoints <= _skeleton->getNumJoints());
for (int i = 0; i < numJoints; ++i) {
int parentIndex = _skeleton->getParentIndex(i);

View file

@ -149,6 +149,7 @@ public:
void set(const std::string& key, const glm::quat& value) { _map[key] = AnimVariant(value); }
void set(const std::string& key, const glm::mat4& value) { _map[key] = AnimVariant(value); }
void set(const std::string& key, const std::string& value) { _map[key] = AnimVariant(value); }
void unset(const std::string& key) { _map.erase(key); }
void setTrigger(const std::string& key) { _triggers.insert(key); }
void clearTriggers() { _triggers.clear(); }

View file

@ -30,6 +30,9 @@ void Rig::HeadParameters::dump() const {
qCDebug(animation, " localHeadOrientation axis = (%.5f, %.5f, %.5f), theta = %0.5f", (double)axis.x, (double)axis.y, (double)axis.z, (double)theta);
axis = glm::axis(worldHeadOrientation);
theta = glm::angle(worldHeadOrientation);
qCDebug(animation, " localHead pitch = %.5f, yaw = %.5f, roll = %.5f", (double)localHeadPitch, (double)localHeadYaw, (double)localHeadRoll);
qCDebug(animation, " localHeadPosition = (%.5f, %.5f, %.5f)", (double)localHeadPosition.x, (double)localHeadPosition.y, (double)localHeadPosition.z);
qCDebug(animation, " isInHMD = %s", isInHMD ? "true" : "false");
qCDebug(animation, " worldHeadOrientation axis = (%.5f, %.5f, %.5f), theta = %0.5f", (double)axis.x, (double)axis.y, (double)axis.z, (double)theta);
axis = glm::axis(modelRotation);
theta = glm::angle(modelRotation);
@ -953,56 +956,70 @@ void Rig::updateFromHeadParameters(const HeadParameters& params) {
if (params.enableLean) {
updateLeanJoint(params.leanJointIndex, params.leanSideways, params.leanForward, params.torsoTwist);
}
updateNeckJoint(params.neckJointIndex, params.localHeadOrientation, params.leanSideways, params.leanForward, params.torsoTwist);
updateNeckJoint(params.neckJointIndex, params);
updateEyeJoints(params.leftEyeJointIndex, params.rightEyeJointIndex, params.modelTranslation, params.modelRotation,
params.worldHeadOrientation, params.eyeLookAt, params.eyeSaccade);
}
static const glm::vec3 X_AXIS(1.0f, 0.0f, 0.0f);
static const glm::vec3 Y_AXIS(0.0f, 1.0f, 0.0f);
static const glm::vec3 Z_AXIS(0.0f, 0.0f, 1.0f);
void Rig::updateLeanJoint(int index, float leanSideways, float leanForward, float torsoTwist) {
if (index >= 0 && _jointStates[index].getParentIndex() >= 0) {
if (_enableAnimGraph && _animSkeleton) {
glm::vec3 xAxis(1.0f, 0.0f, 0.0f);
glm::vec3 yAxis(0.0f, 1.0f, 0.0f);
glm::vec3 zAxis(0.0f, 0.0f, 1.0f);
glm::quat absRot = (glm::angleAxis(-RADIANS_PER_DEGREE * leanSideways, zAxis) *
glm::angleAxis(-RADIANS_PER_DEGREE * leanForward, xAxis) *
glm::angleAxis(RADIANS_PER_DEGREE * torsoTwist, yAxis));
glm::quat absRot = (glm::angleAxis(-RADIANS_PER_DEGREE * leanSideways, Z_AXIS) *
glm::angleAxis(-RADIANS_PER_DEGREE * leanForward, X_AXIS) *
glm::angleAxis(RADIANS_PER_DEGREE * torsoTwist, Y_AXIS));
_animVars.set("lean", absRot);
} else if (!_enableAnimGraph) {
auto& parentState = _jointStates[_jointStates[index].getParentIndex()];
// get the rotation axes in joint space and use them to adjust the rotation
glm::vec3 xAxis(1.0f, 0.0f, 0.0f);
glm::vec3 yAxis(0.0f, 1.0f, 0.0f);
glm::vec3 zAxis(0.0f, 0.0f, 1.0f);
glm::quat inverse = glm::inverse(parentState.getRotation() * getJointDefaultRotationInParentFrame(index));
setJointRotationInConstrainedFrame(index,
glm::angleAxis(- RADIANS_PER_DEGREE * leanSideways, inverse * zAxis) *
glm::angleAxis(- RADIANS_PER_DEGREE * leanForward, inverse * xAxis) *
glm::angleAxis(RADIANS_PER_DEGREE * torsoTwist, inverse * yAxis) *
glm::angleAxis(- RADIANS_PER_DEGREE * leanSideways, inverse * Z_AXIS) *
glm::angleAxis(- RADIANS_PER_DEGREE * leanForward, inverse * X_AXIS) *
glm::angleAxis(RADIANS_PER_DEGREE * torsoTwist, inverse * Y_AXIS) *
getJointState(index).getDefaultRotation(), DEFAULT_PRIORITY);
}
}
}
void Rig::updateNeckJoint(int index, const glm::quat& localHeadOrientation, float leanSideways, float leanForward, float torsoTwist) {
void Rig::updateNeckJoint(int index, const HeadParameters& params) {
if (index >= 0 && _jointStates[index].getParentIndex() >= 0) {
auto& state = _jointStates[index];
auto& parentState = _jointStates[state.getParentIndex()];
if (_enableAnimGraph && _animSkeleton) {
// the params.localHeadOrientation is composed incorrectly, so re-compose it correctly from pitch, yaw and roll.
glm::quat realLocalHeadOrientation = (glm::angleAxis(glm::radians(-params.localHeadRoll), Z_AXIS) *
glm::angleAxis(glm::radians(params.localHeadYaw), Y_AXIS) *
glm::angleAxis(glm::radians(-params.localHeadPitch), X_AXIS));
_animVars.set("headRotation", realLocalHeadOrientation);
// get the rotation axes in joint space and use them to adjust the rotation
glm::mat3 axes = glm::mat3_cast(glm::quat());
glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransform() *
glm::translate(getJointDefaultTranslationInConstrainedFrame(index)) *
state.getPreTransform() * glm::mat4_cast(state.getPreRotation())));
glm::vec3 pitchYawRoll = safeEulerAngles(localHeadOrientation);
glm::vec3 lean = glm::radians(glm::vec3(leanForward, torsoTwist, leanSideways));
pitchYawRoll -= lean;
setJointRotationInConstrainedFrame(index,
glm::angleAxis(-pitchYawRoll.z, glm::normalize(inverse * axes[2])) *
glm::angleAxis(pitchYawRoll.y, glm::normalize(inverse * axes[1])) *
glm::angleAxis(-pitchYawRoll.x, glm::normalize(inverse * axes[0])) *
state.getDefaultRotation(), DEFAULT_PRIORITY);
auto rootTrans = _animSkeleton->getAbsoluteBindPose(_rootJointIndex).trans;
if (params.isInHMD) {
_animVars.set("headPosition", params.localHeadPosition + rootTrans);
} else {
_animVars.unset("headPosition");
}
} else if (!_enableAnimGraph) {
auto& state = _jointStates[index];
auto& parentState = _jointStates[state.getParentIndex()];
// get the rotation axes in joint space and use them to adjust the rotation
glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransform() *
glm::translate(getJointDefaultTranslationInConstrainedFrame(index)) *
state.getPreTransform() * glm::mat4_cast(state.getPreRotation())));
glm::vec3 pitchYawRoll = safeEulerAngles(params.localHeadOrientation);
glm::vec3 lean = glm::radians(glm::vec3(params.leanForward, params.torsoTwist, params.leanSideways));
pitchYawRoll -= lean;
setJointRotationInConstrainedFrame(index,
glm::angleAxis(-pitchYawRoll.z, glm::normalize(inverse * Z_AXIS)) *
glm::angleAxis(pitchYawRoll.y, glm::normalize(inverse * Y_AXIS)) *
glm::angleAxis(-pitchYawRoll.x, glm::normalize(inverse * X_AXIS)) *
state.getDefaultRotation(), DEFAULT_PRIORITY);
}
}
}

View file

@ -59,6 +59,11 @@ public:
bool enableLean = false;
glm::quat modelRotation = glm::quat();
glm::quat localHeadOrientation = glm::quat();
float localHeadPitch = 0.0f; // degrees
float localHeadYaw = 0.0f; // degrees
float localHeadRoll = 0.0f; // degrees
glm::vec3 localHeadPosition = glm::vec3();
bool isInHMD = false;
glm::quat worldHeadOrientation = glm::quat();
glm::vec3 eyeLookAt = glm::vec3(); // world space
glm::vec3 eyeSaccade = glm::vec3(); // world space
@ -177,7 +182,7 @@ public:
protected:
void updateLeanJoint(int index, float leanSideways, float leanForward, float torsoTwist);
void updateNeckJoint(int index, const glm::quat& localHeadOrientation, float leanSideways, float leanForward, float torsoTwist);
void updateNeckJoint(int index, const HeadParameters& params);
void updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm::quat& modelRotation, const glm::quat& worldHeadOrientation, const glm::vec3& lookAt, const glm::vec3& saccade);
QVector<JointState> _jointStates;

View file

@ -108,7 +108,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) {
@ -122,10 +122,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() {
@ -150,7 +151,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);
}
@ -242,7 +243,6 @@ QScriptValue EntityTreeRenderer::loadEntityScript(EntityItemPointer entity, bool
QString scriptContents = loadScriptContents(entityScript, isURL, isPending, url, reload);
if (isPending && isPreload && isURL) {
//qDebug() << "attempted to load script, isPending, _waitingOnPreload.insert() url:" << url << "entityID:" << entityID;
_waitingOnPreload.insert(url, entityID);
}
@ -304,16 +304,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();
@ -325,8 +325,7 @@ void EntityTreeRenderer::update() {
QScriptValueList currentClickingEntityArgs = createMouseEventArgs(_currentClickingOnEntityID, _lastMouseEvent);
QScriptValue currentClickingEntity = loadEntityScript(_currentClickingOnEntityID);
if (currentClickingEntity.property("holdingClickOnEntity").isValid()) {
//qDebug() << "About to call holdingClickOnEntity() current thread:" << QThread::currentThread() << "entities thread:" << _entitiesScriptEngine->thread();
_entitiesScriptEngine->callScriptMethod("holdingClickOnEntity", currentClickingEntity, currentClickingEntityArgs);
currentClickingEntity.property("holdingClickOnEntity").call(currentClickingEntity, currentClickingEntityArgs);
}
}
@ -345,7 +344,7 @@ void EntityTreeRenderer::checkEnterLeaveEntities() {
// find the entities near us
// don't let someone else change our tree while we search
_tree->withReadLock([&] {
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) {
@ -366,9 +365,7 @@ void EntityTreeRenderer::checkEnterLeaveEntities() {
QScriptValueList entityArgs = createEntityArgs(entityID);
QScriptValue entityScript = loadEntityScript(entityID);
if (entityScript.property("leaveEntity").isValid()) {
//qDebug() << "About to call leaveEntity() current thread:" << QThread::currentThread() << "entities thread:" << _entitiesScriptEngine->thread();
_entitiesScriptEngine->callScriptMethod("leaveEntity", entityScript, entityArgs);
entityScript.property("leaveEntity").call(entityScript, entityArgs);
}
}
@ -381,8 +378,7 @@ void EntityTreeRenderer::checkEnterLeaveEntities() {
QScriptValueList entityArgs = createEntityArgs(entityID);
QScriptValue entityScript = loadEntityScript(entityID);
if (entityScript.property("enterEntity").isValid()) {
//qDebug() << "About to call enterEntity() current thread:" << QThread::currentThread() << "entities thread:" << _entitiesScriptEngine->thread();
_entitiesScriptEngine->callScriptMethod("enterEntity", entityScript, entityArgs);
entityScript.property("enterEntity").call(entityScript, entityArgs);
}
}
}
@ -401,8 +397,7 @@ void EntityTreeRenderer::leaveAllEntities() {
QScriptValueList entityArgs = createEntityArgs(entityID);
QScriptValue entityScript = loadEntityScript(entityID);
if (entityScript.property("leaveEntity").isValid()) {
//qDebug() << "About to call leaveEntity() current thread:" << QThread::currentThread() << "entities thread:" << _entitiesScriptEngine->thread();
_entitiesScriptEngine->callScriptMethod("leaveEntity", entityScript, entityArgs);
entityScript.property("leaveEntity").call(entityScript, entityArgs);
}
}
_currentEntitiesInside.clear();
@ -569,7 +564,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;
@ -643,10 +638,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);
bool isShadowMode = args->_renderMode == RenderArgs::SHADOW_RENDER_MODE;
@ -693,7 +689,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) {
@ -769,9 +765,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,
@ -848,7 +844,7 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event, unsigned int device
bool precisionPicking = !_dontDoPrecisionPicking;
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking);
if (rayPickResult.intersects) {
qCDebug(entitiesrenderer) << "mousePressEvent over entity:" << rayPickResult.entityID;
//qCDebug(entitiesrenderer) << "mousePressEvent over entity:" << rayPickResult.entityID;
QString urlString = rayPickResult.properties.getHref();
QUrl url = QUrl(urlString, QUrl::StrictMode);
@ -862,15 +858,13 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event, unsigned int device
QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID);
QScriptValue entityScript = loadEntityScript(rayPickResult.entity);
if (entityScript.property("mousePressOnEntity").isValid()) {
//qDebug() << "About to call mousePressOnEntity() current thread:" << QThread::currentThread() << "entities thread:" << _entitiesScriptEngine->thread();
_entitiesScriptEngine->callScriptMethod("mousePressOnEntity", entityScript, entityScriptArgs);
entityScript.property("mousePressOnEntity").call(entityScript, entityScriptArgs);
}
_currentClickingOnEntityID = rayPickResult.entityID;
emit clickDownOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID));
if (entityScript.property("clickDownOnEntity").isValid()) {
//qDebug() << "About to call clickDownOnEntity() current thread:" << QThread::currentThread() << "entities thread:" << _entitiesScriptEngine->thread();
_entitiesScriptEngine->callScriptMethod("clickDownOnEntity", entityScript, entityScriptArgs);
entityScript.property("clickDownOnEntity").call(entityScript, entityScriptArgs);
}
} else {
emit mousePressOffEntity(rayPickResult, event, deviceID);
@ -896,7 +890,7 @@ void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event, unsigned int devi
QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID);
QScriptValue entityScript = loadEntityScript(rayPickResult.entity);
if (entityScript.property("mouseReleaseOnEntity").isValid()) {
_entitiesScriptEngine->callScriptMethod("mouseReleaseOnEntity", entityScript, entityScriptArgs);
entityScript.property("mouseReleaseOnEntity").call(entityScript, entityScriptArgs);
}
}
@ -908,8 +902,7 @@ void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event, unsigned int devi
QScriptValueList currentClickingEntityArgs = createMouseEventArgs(_currentClickingOnEntityID, event, deviceID);
QScriptValue currentClickingEntity = loadEntityScript(_currentClickingOnEntityID);
if (currentClickingEntity.property("clickReleaseOnEntity").isValid()) {
//qDebug() << "About to call clickReleaseOnEntity() current thread:" << QThread::currentThread() << "entities thread:" << _entitiesScriptEngine->thread();
_entitiesScriptEngine->callScriptMethod("clickReleaseOnEntity", currentClickingEntity, currentClickingEntityArgs);
currentClickingEntity.property("clickReleaseOnEntity").call(currentClickingEntity, currentClickingEntityArgs);
}
}
@ -937,13 +930,11 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event, unsigned int deviceI
// load the entity script if needed...
QScriptValue entityScript = loadEntityScript(rayPickResult.entity);
if (entityScript.property("mouseMoveEvent").isValid()) {
//qDebug() << "About to call mouseMoveEvent() current thread:" << QThread::currentThread() << "entities thread:" << _entitiesScriptEngine->thread();
_entitiesScriptEngine->callScriptMethod("mouseMoveEvent", entityScript, entityScriptArgs);
entityScript.property("mouseMoveEvent").call(entityScript, entityScriptArgs);
}
emit mouseMoveOnEntity(rayPickResult, event, deviceID);
if (entityScript.property("mouseMoveOnEntity").isValid()) {
//qDebug() << "About to call mouseMoveOnEntity() current thread:" << QThread::currentThread() << "entities thread:" << _entitiesScriptEngine->thread();
_entitiesScriptEngine->callScriptMethod("mouseMoveOnEntity", entityScript, entityScriptArgs);
entityScript.property("mouseMoveOnEntity").call(entityScript, entityScriptArgs);
}
// handle the hover logic...
@ -957,9 +948,7 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event, unsigned int deviceI
QScriptValue currentHoverEntity = loadEntityScript(_currentHoverOverEntityID);
if (currentHoverEntity.property("hoverLeaveEntity").isValid()) {
//qDebug() << "About to call hoverLeaveEntity() current thread:" << QThread::currentThread() << "entities thread:" << _entitiesScriptEngine->thread();
_entitiesScriptEngine->callScriptMethod("hoverLeaveEntity", currentHoverEntity, currentHoverEntityArgs);
currentHoverEntity.property("hoverLeaveEntity").call(currentHoverEntity, currentHoverEntityArgs);
}
}
@ -968,8 +957,7 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event, unsigned int deviceI
if (rayPickResult.entityID != _currentHoverOverEntityID) {
emit hoverEnterEntity(rayPickResult.entityID, MouseEvent(*event, deviceID));
if (entityScript.property("hoverEnterEntity").isValid()) {
//qDebug() << "About to call hoverEnterEntity() current thread:" << QThread::currentThread() << "entities thread:" << _entitiesScriptEngine->thread();
_entitiesScriptEngine->callScriptMethod("hoverEnterEntity", entityScript, entityScriptArgs);
entityScript.property("hoverEnterEntity").call(entityScript, entityScriptArgs);
}
}
@ -977,8 +965,7 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event, unsigned int deviceI
// we should send our hover over event
emit hoverOverEntity(rayPickResult.entityID, MouseEvent(*event, deviceID));
if (entityScript.property("hoverOverEntity").isValid()) {
//qDebug() << "About to call hoverOverEntity() current thread:" << QThread::currentThread() << "entities thread:" << _entitiesScriptEngine->thread();
_entitiesScriptEngine->callScriptMethod("hoverOverEntity", entityScript, entityScriptArgs);
entityScript.property("hoverOverEntity").call(entityScript, entityScriptArgs);
}
// remember what we're hovering over
@ -995,8 +982,7 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event, unsigned int deviceI
QScriptValue currentHoverEntity = loadEntityScript(_currentHoverOverEntityID);
if (currentHoverEntity.property("hoverLeaveEntity").isValid()) {
//qDebug() << "About to call hoverLeaveEntity() current thread:" << QThread::currentThread() << "entities thread:" << _entitiesScriptEngine->thread();
_entitiesScriptEngine->callScriptMethod("hoverLeaveEntity", currentHoverEntity, currentHoverEntityArgs);
currentHoverEntity.property("hoverLeaveEntity").call(currentHoverEntity, currentHoverEntityArgs);
}
_currentHoverOverEntityID = UNKNOWN_ENTITY_ID; // makes it the unknown ID
@ -1012,8 +998,7 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event, unsigned int deviceI
QScriptValue currentClickingEntity = loadEntityScript(_currentClickingOnEntityID);
if (currentClickingEntity.property("holdingClickOnEntity").isValid()) {
//qDebug() << "About to call holdingClickOnEntity() current thread:" << QThread::currentThread() << "entities thread:" << _entitiesScriptEngine->thread();
_entitiesScriptEngine->callScriptMethod("holdingClickOnEntity", currentClickingEntity, currentClickingEntityArgs);
currentClickingEntity.property("holdingClickOnEntity").call(currentClickingEntity, currentClickingEntityArgs);
}
}
_lastMouseEvent = MouseEvent(*event, deviceID);
@ -1038,7 +1023,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);
}
@ -1068,8 +1053,7 @@ void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID, const
QScriptValue entityScript = loadEntityScript(entityID, true, reload); // is preload!
if (entityScript.property("preload").isValid()) {
QScriptValueList entityArgs = createEntityArgs(entityID);
//qDebug() << "About to call preload() current thread:" << QThread::currentThread() << "entities thread:" << _entitiesScriptEngine->thread();
_entitiesScriptEngine->callScriptMethod("preload", entityScript, entityArgs);
entityScript.property("preload").call(entityScript, entityArgs);
}
}
}
@ -1079,13 +1063,13 @@ void EntityTreeRenderer::checkAndCallUnload(const EntityItemID& entityID) {
QScriptValue entityScript = getPreviouslyLoadedEntityScript(entityID);
if (entityScript.property("unload").isValid()) {
QScriptValueList entityArgs = createEntityArgs(entityID);
//qDebug() << "About to call unload() current thread:" << QThread::currentThread() << "entities thread:" << _entitiesScriptEngine->thread();
_entitiesScriptEngine->callScriptMethod("unload", entityScript, entityArgs);
entityScript.property("unload").call(entityScript, entityArgs);
}
}
}
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;
@ -1152,7 +1136,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);
@ -1165,9 +1149,7 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons
args << idA.toScriptValue(_entitiesScriptEngine);
args << idB.toScriptValue(_entitiesScriptEngine);
args << collisionToScriptValue(_entitiesScriptEngine, collision);
//qDebug() << "About to call collisionWithEntity() current thread:" << QThread::currentThread() << "entities thread:" << _entitiesScriptEngine->thread();
_entitiesScriptEngine->callScriptMethod("collisionWithEntity", entityScriptA, args);
entityScriptA.property("collisionWithEntity").call(entityScriptA, args);
}
emit collisionWithEntity(idB, idA, collision);
@ -1177,9 +1159,7 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons
args << idB.toScriptValue(_entitiesScriptEngine);
args << idA.toScriptValue(_entitiesScriptEngine);
args << collisionToScriptValue(_entitiesScriptEngine, collision);
//qDebug() << "About to call collisionWithEntity() current thread:" << QThread::currentThread() << "entities thread:" << _entitiesScriptEngine->thread();
_entitiesScriptEngine->callScriptMethod("collisionWithEntity", entityScriptB, args);
entityScriptB.property("collisionWithEntity").call(entityScriptA, args);
}
}

View file

@ -45,15 +45,15 @@ public:
virtual char getMyNodeType() const { return NodeType::EntityServer; }
virtual PacketType getMyQueryMessageType() const { return PacketType::EntityQuery; }
virtual PacketType getExpectedPacketType() const { return PacketType::EntityData; }
virtual void renderElement(OctreeElement* element, RenderArgs* args);
virtual void renderElement(OctreeElementPointer element, RenderArgs* args);
virtual float getSizeScale() const;
virtual int getBoundaryLevelAdjust() const;
virtual void setTree(Octree* newTree);
virtual void setTree(OctreePointer newTree);
void shutdown();
void update();
EntityTree* getTree() { return static_cast<EntityTree*>(_tree); }
EntityTreePointer getTree() { return std::static_pointer_cast<EntityTree>(_tree); }
void processEraseMessage(NLPacket& packet, const SharedNodePointer& sourceNode);
@ -123,15 +123,19 @@ public slots:
void setDisplayModelBounds(bool value) { _displayModelBounds = value; }
void setDisplayModelElementProxy(bool value) { _displayModelElementProxy = value; }
void setDontDoPrecisionPicking(bool value) { _dontDoPrecisionPicking = value; }
protected:
virtual Octree* createTree() { return new EntityTree(true); }
virtual OctreePointer createTree() {
EntityTreePointer newTree = EntityTreePointer(new EntityTree(true));
newTree->createRootElement();
return newTree;
}
private:
void addEntityToScene(EntityItemPointer entity);
void applyZonePropertiesToScene(std::shared_ptr<ZoneEntityItem> zone);
void renderElementProxy(EntityTreeElement* entityTreeElement, RenderArgs* args);
void renderElementProxy(EntityTreeElementPointer entityTreeElement, RenderArgs* args);
void checkAndCallPreload(const EntityItemID& entityID, const bool reload = false);
void checkAndCallUnload(const EntityItemID& entityID);
@ -162,7 +166,8 @@ private:
QHash<EntityItemID, EntityScriptDetails> _entityScripts;
void playEntityCollisionSound(const QUuid& myNodeID, EntityTree* entityTree, const EntityItemID& id, const Collision& collision);
void playEntityCollisionSound(const QUuid& myNodeID, EntityTreePointer entityTree,
const EntityItemID& id, const Collision& collision);
bool _lastMouseEventValid;
MouseEvent _lastMouseEvent;

View file

@ -54,7 +54,7 @@ void RenderableLightEntityItem::render(RenderArgs* args) {
};
bool RenderableLightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) const {
// TODO: consider if this is really what we want to do. We've made it so that "lights are pickable" is a global state

View file

@ -26,7 +26,7 @@ public:
virtual void render(RenderArgs* args);
virtual bool supportsDetailedRayIntersection() const { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) const;
SIMPLE_RENDERABLE();

View file

@ -367,13 +367,14 @@ EntityItemProperties RenderableModelEntityItem::getProperties() const {
}
bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) const {
if (!_model) {
return true;
}
//qCDebug(entitiesrenderer) << "RenderableModelEntityItem::findDetailedRayIntersection() precisionPicking:" << precisionPicking;
// qCDebug(entitiesrenderer) << "RenderableModelEntityItem::findDetailedRayIntersection() precisionPicking:"
// << precisionPicking;
QString extraInfo;
return _model->findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, extraInfo, precisionPicking);
}

View file

@ -55,7 +55,7 @@ public:
virtual void render(RenderArgs* args);
virtual bool supportsDetailedRayIntersection() const { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) const;
Model* getModel(EntityTreeRenderer* renderer);

View file

@ -351,7 +351,7 @@ public:
bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& origin,
const glm::vec3& direction,
bool& keepSearching,
OctreeElement*& element,
OctreeElementPointer& element,
float& distance, BoxFace& face,
void** intersectedObject,
bool precisionPicking) const
@ -858,8 +858,8 @@ void RenderablePolyVoxEntityItem::compressVolumeDataAndSendEditPacketAsync() {
properties.setVoxelDataDirty();
properties.setLastEdited(now);
EntityTreeElement* element = getElement();
EntityTree* tree = element ? element->getTree() : nullptr;
EntityTreeElementPointer element = getElement();
EntityTreePointer tree = element ? element->getTree() : nullptr;
EntitySimulation* simulation = tree ? tree->getSimulation() : nullptr;
PhysicalEntitySimulation* peSimulation = static_cast<PhysicalEntitySimulation*>(simulation);
EntityEditPacketSender* packetSender = peSimulation ? peSimulation->getPacketSender() : nullptr;
@ -917,8 +917,8 @@ void RenderablePolyVoxEntityItem::clearOutOfDateNeighbors() {
void RenderablePolyVoxEntityItem::cacheNeighbors() {
clearOutOfDateNeighbors();
EntityTreeElement* element = getElement();
EntityTree* tree = element ? element->getTree() : nullptr;
EntityTreeElementPointer element = getElement();
EntityTreePointer tree = element ? element->getTree() : nullptr;
if (!tree) {
return;
}

View file

@ -64,7 +64,7 @@ public:
void render(RenderArgs* args);
virtual bool supportsDetailedRayIntersection() const { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) const;
virtual void setVoxelData(QByteArray voxelData);

View file

@ -15,8 +15,7 @@
#include "AddEntityOperator.h"
AddEntityOperator::AddEntityOperator(EntityTree* tree,
EntityItemPointer newEntity) :
AddEntityOperator::AddEntityOperator(EntityTreePointer tree, EntityItemPointer newEntity) :
_tree(tree),
_newEntity(newEntity),
_foundNew(false),
@ -25,16 +24,16 @@ AddEntityOperator::AddEntityOperator(EntityTree* tree,
{
// caller must have verified existence of newEntity
assert(_newEntity);
_newEntityBox = _newEntity->getMaximumAACube().clamp((float)(-HALF_TREE_SCALE), (float)HALF_TREE_SCALE);
}
bool AddEntityOperator::preRecursion(OctreeElement* element) {
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
bool AddEntityOperator::preRecursion(OctreeElementPointer element) {
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
// In Pre-recursion, we're generally deciding whether or not we want to recurse this
// path of the tree. For this operation, we want to recurse the branch of the tree if
// and of the following are true:
// any of the following are true:
// * We have not yet found the location for the new entity, and this branch contains the bounds of the new entity
bool keepSearching = false; // assume we don't need to search any more
@ -59,7 +58,7 @@ bool AddEntityOperator::preRecursion(OctreeElement* element) {
return keepSearching; // if we haven't yet found it, keep looking
}
bool AddEntityOperator::postRecursion(OctreeElement* element) {
bool AddEntityOperator::postRecursion(OctreeElementPointer element) {
// Post-recursion is the unwinding process. For this operation, while we
// unwind we want to mark the path as being dirty if we changed it below.
// We might have two paths, one for the old entity and one for the new entity.
@ -73,7 +72,7 @@ bool AddEntityOperator::postRecursion(OctreeElement* element) {
return keepSearching; // if we haven't yet found it, keep looking
}
OctreeElement* AddEntityOperator::possiblyCreateChildAt(OctreeElement* element, int childIndex) {
OctreeElementPointer AddEntityOperator::possiblyCreateChildAt(OctreeElementPointer element, int childIndex) {
// If we're getting called, it's because there was no child element at this index while recursing.
// We only care if this happens while still searching for the new entity location.
// Check to see if

View file

@ -14,13 +14,13 @@
class AddEntityOperator : public RecurseOctreeOperator {
public:
AddEntityOperator(EntityTree* tree, EntityItemPointer newEntity);
AddEntityOperator(EntityTreePointer tree, EntityItemPointer newEntity);
virtual bool preRecursion(OctreeElement* element);
virtual bool postRecursion(OctreeElement* element);
virtual OctreeElement* possiblyCreateChildAt(OctreeElement* element, int childIndex);
virtual bool preRecursion(OctreeElementPointer element);
virtual bool postRecursion(OctreeElementPointer element);
virtual OctreeElementPointer possiblyCreateChildAt(OctreeElementPointer element, int childIndex);
private:
EntityTree* _tree;
EntityTreePointer _tree;
EntityItemPointer _newEntity;
bool _foundNew;
quint64 _changeTime;

View file

@ -16,7 +16,7 @@
#include "EntitiesLogging.h"
#include "DeleteEntityOperator.h"
DeleteEntityOperator::DeleteEntityOperator(EntityTree* tree, const EntityItemID& searchEntityID) :
DeleteEntityOperator::DeleteEntityOperator(EntityTreePointer tree, const EntityItemID& searchEntityID) :
_tree(tree),
_changeTime(usecTimestampNow()),
_foundCount(0),
@ -28,7 +28,7 @@ DeleteEntityOperator::DeleteEntityOperator(EntityTree* tree, const EntityItemID&
DeleteEntityOperator::~DeleteEntityOperator() {
}
DeleteEntityOperator::DeleteEntityOperator(EntityTree* tree) :
DeleteEntityOperator::DeleteEntityOperator(EntityTreePointer tree) :
_tree(tree),
_changeTime(usecTimestampNow()),
_foundCount(0),
@ -55,7 +55,7 @@ void DeleteEntityOperator::addEntityIDToDeleteList(const EntityItemID& searchEnt
// does this entity tree element contain the old entity
bool DeleteEntityOperator::subTreeContainsSomeEntitiesToDelete(OctreeElement* element) {
bool DeleteEntityOperator::subTreeContainsSomeEntitiesToDelete(OctreeElementPointer element) {
bool containsEntity = false;
// If we don't have an old entity, then we don't contain the entity, otherwise
@ -72,9 +72,9 @@ bool DeleteEntityOperator::subTreeContainsSomeEntitiesToDelete(OctreeElement* el
return containsEntity;
}
bool DeleteEntityOperator::preRecursion(OctreeElement* element) {
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
bool DeleteEntityOperator::preRecursion(OctreeElementPointer element) {
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
// In Pre-recursion, we're generally deciding whether or not we want to recurse this
// path of the tree. For this operation, we want to recurse the branch of the tree if:
// * We have not yet found the all entities, and
@ -108,7 +108,7 @@ bool DeleteEntityOperator::preRecursion(OctreeElement* element) {
return keepSearching; // if we haven't yet found it, keep looking
}
bool DeleteEntityOperator::postRecursion(OctreeElement* element) {
bool DeleteEntityOperator::postRecursion(OctreeElementPointer element) {
// Post-recursion is the unwinding process. For this operation, while we
// unwind we want to mark the path as being dirty if we changed it below.
// We might have two paths, one for the old entity and one for the new entity.
@ -125,7 +125,7 @@ bool DeleteEntityOperator::postRecursion(OctreeElement* element) {
// children are the containing element for any entity in our lists of entities to delete, then they
// must have already deleted the entity, and they are safe to prune. Since this operation doesn't
// ever add any elements we don't have to worry about memory being reused within this recursion pass.
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
entityTreeElement->pruneChildren(); // take this opportunity to prune any empty leaves
return keepSearching; // if we haven't yet found it, keep looking
}

View file

@ -16,7 +16,7 @@ class EntityToDeleteDetails {
public:
EntityItemPointer entity;
AACube cube;
EntityTreeElement* containingElement;
EntityTreeElementPointer containingElement;
};
typedef QSet<EntityToDeleteDetails> RemovedEntities;
@ -31,22 +31,22 @@ inline bool operator==(const EntityToDeleteDetails& a, const EntityToDeleteDetai
class DeleteEntityOperator : public RecurseOctreeOperator {
public:
DeleteEntityOperator(EntityTree* tree);
DeleteEntityOperator(EntityTree* tree, const EntityItemID& searchEntityID);
DeleteEntityOperator(EntityTreePointer tree);
DeleteEntityOperator(EntityTreePointer tree, const EntityItemID& searchEntityID);
~DeleteEntityOperator();
void addEntityIDToDeleteList(const EntityItemID& searchEntityID);
virtual bool preRecursion(OctreeElement* element);
virtual bool postRecursion(OctreeElement* element);
virtual bool preRecursion(OctreeElementPointer element);
virtual bool postRecursion(OctreeElementPointer element);
const RemovedEntities& getEntities() const { return _entitiesToDelete; }
private:
EntityTree* _tree;
EntityTreePointer _tree;
RemovedEntities _entitiesToDelete;
quint64 _changeTime;
int _foundCount;
int _lookingCount;
bool subTreeContainsSomeEntitiesToDelete(OctreeElement* element);
bool subTreeContainsSomeEntitiesToDelete(OctreeElementPointer element);
};
#endif // hifi_DeleteEntityOperator_h

View file

@ -89,7 +89,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) :
EntityItem::~EntityItem() {
// clear out any left-over actions
EntityTree* entityTree = _element ? _element->getTree() : nullptr;
EntityTreePointer entityTree = _element ? _element->getTree() : nullptr;
EntitySimulation* simulation = entityTree ? entityTree->getSimulation() : nullptr;
if (simulation) {
clearActions(simulation);
@ -985,6 +985,12 @@ bool EntityItem::isMoving() const {
return hasVelocity() || hasAngularVelocity();
}
EntityTreePointer EntityItem::getTree() const {
EntityTreeElementPointer containingElement = getElement();
EntityTreePointer tree = containingElement ? containingElement->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;
@ -1578,7 +1566,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;
}
@ -1634,7 +1622,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);

View file

@ -33,9 +33,11 @@
class EntitySimulation;
class EntityTreeElement;
class EntityTreeElementExtraEncodeData;
class EntityActionInterface;
class EntityTree;
typedef std::shared_ptr<EntityTree> EntityTreePointer;
typedef std::shared_ptr<EntityActionInterface> EntityActionPointer;
typedef std::shared_ptr<EntityTreeElement> EntityTreeElementPointer;
namespace render {
@ -204,7 +206,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
@ -219,7 +221,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(); }
@ -391,7 +393,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; }
@ -497,7 +500,7 @@ protected:
uint32_t _dirtyFlags; // things that have changed from EXTERNAL changes (via script or packet) but NOT from simulation
// these backpointers are only ever set/cleared by friends:
EntityTreeElement* _element = nullptr; // set by EntityTreeElement
EntityTreeElementPointer _element = nullptr; // set by EntityTreeElement
void* _physicsInfo = nullptr; // set by EntitySimulation
bool _simulated; // set by EntitySimulation

View file

@ -47,19 +47,19 @@ bool EntityScriptingInterface::canRez() {
return nodeList->getThisNodeCanRez();
}
void EntityScriptingInterface::setEntityTree(EntityTree* modelTree) {
void EntityScriptingInterface::setEntityTree(EntityTreePointer elementTree) {
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;
_entityTree = elementTree;
if (_entityTree) {
connect(_entityTree, &EntityTree::addingEntity, this, &EntityScriptingInterface::addingEntity);
connect(_entityTree, &EntityTree::deletingEntity, this, &EntityScriptingInterface::deletingEntity);
connect(_entityTree, &EntityTree::clearingEntities, this, &EntityScriptingInterface::clearingEntities);
connect(_entityTree.get(), &EntityTree::addingEntity, this, &EntityScriptingInterface::addingEntity);
connect(_entityTree.get(), &EntityTree::deletingEntity, this, &EntityScriptingInterface::deletingEntity);
connect(_entityTree.get(), &EntityTree::clearingEntities, this, &EntityScriptingInterface::clearingEntities);
}
}
@ -280,7 +280,7 @@ RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionWorke
RayToEntityIntersectionResult result;
if (_entityTree) {
OctreeElement* element;
OctreeElementPointer element;
EntityItemPointer intersectedEntity = NULL;
result.intersects = _entityTree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face,
(void**)&intersectedEntity, lockType, &result.accurate,

View file

@ -23,6 +23,7 @@
#include "PolyVoxEntityItem.h"
#include "LineEntityItem.h"
#include "PolyLineEntityItem.h"
#include "EntityTree.h"
#include "EntityEditPacketSender.h"
@ -60,8 +61,8 @@ public:
virtual NodeType_t getServerNodeType() const { return NodeType::EntityServer; }
virtual OctreeEditPacketSender* createPacketSender() { return new EntityEditPacketSender(); }
void setEntityTree(EntityTree* modelTree);
EntityTree* getEntityTree() { return _entityTree; }
void setEntityTree(EntityTreePointer modelTree);
EntityTreePointer getEntityTree() { return _entityTree; }
public slots:
@ -178,7 +179,7 @@ private:
RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType,
bool precisionPicking);
EntityTree* _entityTree;
EntityTreePointer _entityTree;
};
#endif // hifi_EntityScriptingInterface_h

View file

@ -15,7 +15,7 @@
#include "EntitiesLogging.h"
#include "MovingEntitiesOperator.h"
void EntitySimulation::setEntityTree(EntityTree* tree) {
void EntitySimulation::setEntityTree(EntityTreePointer tree) {
if (_entityTree && _entityTree != tree) {
_mortalEntities.clear();
_nextExpiry = quint64(-1);

View file

@ -48,7 +48,7 @@ public:
virtual ~EntitySimulation() { setEntityTree(NULL); }
/// \param tree pointer to EntityTree which is stored internally
void setEntityTree(EntityTree* tree);
void setEntityTree(EntityTreePointer tree);
void updateEntities();
@ -79,7 +79,7 @@ protected: // these only called by the EntityTree?
public:
EntityTree* getEntityTree() { return _entityTree; }
EntityTreePointer getEntityTree() { return _entityTree; }
void getEntitiesToDelete(VectorOfEntities& entitiesToDelete);
@ -110,7 +110,7 @@ private:
void moveSimpleKinematics();
// back pointer to EntityTree structure
EntityTree* _entityTree;
EntityTreePointer _entityTree;
// We maintain multiple lists, each for its distinct purpose.
// An entity may be in more than one list.

View file

@ -31,7 +31,6 @@ EntityTree::EntityTree(bool shouldReaverage) :
_fbxService(NULL),
_simulation(NULL)
{
_rootElement = createNewElement();
resetClientEditStats();
}
@ -39,10 +38,19 @@ EntityTree::~EntityTree() {
eraseAllOctreeElements(false);
}
EntityTreeElement* EntityTree::createNewElement(unsigned char * octalCode) {
EntityTreeElement* newElement = new EntityTreeElement(octalCode);
newElement->setTree(this);
return newElement;
void EntityTree::createRootElement() {
_rootElement = createNewElement();
}
OctreeElementPointer EntityTree::createNewElement(unsigned char* octalCode) {
EntityTreeElementPointer newElement = EntityTreeElementPointer(new EntityTreeElement(octalCode),
// see comment int EntityTreeElement::createNewElement
[=](EntityTreeElement* dyingElement) {
EntityTreeElementPointer tmpSharedPointer(dyingElement);
dyingElement->notifyDeleteHooks();
});
newElement->setTree(std::static_pointer_cast<EntityTree>(shared_from_this()));
return std::static_pointer_cast<OctreeElement>(newElement);
}
void EntityTree::eraseAllOctreeElements(bool createNewRoot) {
@ -52,7 +60,7 @@ void EntityTree::eraseAllOctreeElements(bool createNewRoot) {
if (_simulation) {
_simulation->clearEntities();
}
foreach (EntityTreeElement* element, _entityToElementMap) {
foreach (EntityTreeElementPointer element, _entityToElementMap) {
element->cleanupEntities();
}
_entityToElementMap.clear();
@ -86,7 +94,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;
}
@ -100,7 +108,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;
}
@ -108,7 +116,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;
@ -135,7 +143,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;
}
@ -197,7 +205,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;
@ -252,10 +260,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;
}
@ -268,7 +276,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);
@ -290,7 +298,7 @@ void EntityTree::setSimulation(EntitySimulation* simulation) {
this->withWriteLock([&] {
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
@ -302,7 +310,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;
@ -329,7 +337,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;
@ -337,9 +345,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;
@ -406,9 +414,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);
@ -458,14 +466,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
}
@ -494,10 +502,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;
}
@ -523,10 +531,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;
}
@ -549,7 +557,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);
}
@ -689,7 +697,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;
}
@ -915,13 +923,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;
@ -932,25 +940,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;
}
@ -963,13 +971,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;
}
@ -981,12 +989,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;
}
@ -996,7 +1004,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;
@ -1009,9 +1018,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);
entityTreeElement->forEachEntity([&](EntityItemPointer entityItem) {
EntityItemID newID(QUuid::createUuid());
args->newEntityIDs->append(newID);
@ -1032,8 +1041,10 @@ bool EntityTree::sendEntitiesOperation(OctreeElement* element, void* extraData)
return true;
}
bool EntityTree::writeToMap(QVariantMap& entityDescription, OctreeElement* element, bool skipDefaultValues) {
entityDescription["Entities"] = QVariantList();
bool EntityTree::writeToMap(QVariantMap& entityDescription, OctreeElementPointer element, bool skipDefaultValues) {
if (! entityDescription.contains("Entities")) {
entityDescription["Entities"] = QVariantList();
}
QScriptEngine scriptEngine;
RecurseOctreeToMapOperator theOperator(entityDescription, element, &scriptEngine, skipDefaultValues);
recurseTreeWithOperator(&theOperator);

View file

@ -17,6 +17,10 @@
#include <Octree.h>
class EntityTree;
typedef std::shared_ptr<EntityTree> EntityTreePointer;
#include "EntityTreeElement.h"
#include "DeleteEntityOperator.h"
@ -39,7 +43,7 @@ public:
class SendEntitiesOperationArgs {
public:
glm::vec3 root;
EntityTree* localTree;
EntityTreePointer localTree;
EntityEditPacketSender* packetSender;
QVector<EntityItemID>* newEntityIDs;
};
@ -51,11 +55,18 @@ public:
EntityTree(bool shouldReaverage = false);
virtual ~EntityTree();
void createRootElement();
/// Implements our type specific root element factory
virtual EntityTreeElement* createNewElement(unsigned char * octalCode = NULL);
virtual OctreeElementPointer createNewElement(unsigned char* octalCode = NULL);
/// Type safe version of getRoot()
EntityTreeElement* getRoot() { return static_cast<EntityTreeElement*>(_rootElement); }
EntityTreeElementPointer getRoot() {
if (!_rootElement) {
createRootElement();
}
return std::static_pointer_cast<EntityTreeElement>(_rootElement);
}
virtual void eraseAllOctreeElements(bool createNewRoot = true);
@ -145,13 +156,14 @@ public:
return _fbxService ? _fbxService->getModelForEntityItem(entityItem) : NULL;
}
EntityTreeElement* getContainingElement(const EntityItemID& entityItemID) /*const*/;
void setContainingElement(const EntityItemID& entityItemID, EntityTreeElement* element);
EntityTreeElementPointer getContainingElement(const EntityItemID& entityItemID) /*const*/;
void setContainingElement(const EntityItemID& entityItemID, EntityTreeElementPointer element);
void debugDumpMap();
virtual void dumpTree();
virtual void pruneTree();
QVector<EntityItemID> sendEntities(EntityEditPacketSender* packetSender, EntityTree* localTree, float x, float y, float z);
QVector<EntityItemID> sendEntities(EntityEditPacketSender* packetSender, EntityTreePointer localTree,
float x, float y, float z);
void entityChanged(EntityItemPointer entity);
@ -163,7 +175,7 @@ public:
bool wantEditLogging() const { return _wantEditLogging; }
void setWantEditLogging(bool value) { _wantEditLogging = value; }
bool writeToMap(QVariantMap& entityDescription, OctreeElement* element, bool skipDefaultValues);
bool writeToMap(QVariantMap& entityDescription, OctreeElementPointer element, bool skipDefaultValues);
bool readFromMap(QVariantMap& entityDescription);
float getContentsLargestDimension();
@ -193,6 +205,8 @@ public:
quint64 getMaxEditDelta() const { return _maxEditDelta; }
quint64 getTotalTrackedEdits() const { return _totalTrackedEdits; }
EntityTreePointer getThisPointer() { return std::static_pointer_cast<EntityTree>(shared_from_this()); }
signals:
void deletingEntity(const EntityItemID& entityID);
void addingEntity(const EntityItemID& entityID);
@ -204,13 +218,13 @@ private:
void processRemovedEntities(const DeleteEntityOperator& theOperator);
bool updateEntityWithElement(EntityItemPointer entity, const EntityItemProperties& properties,
EntityTreeElement* containingElement,
EntityTreeElementPointer containingElement,
const SharedNodePointer& senderNode = SharedNodePointer(nullptr));
static bool findNearPointOperation(OctreeElement* element, void* extraData);
static bool findInSphereOperation(OctreeElement* element, void* extraData);
static bool findInCubeOperation(OctreeElement* element, void* extraData);
static bool findInBoxOperation(OctreeElement* element, void* extraData);
static bool sendEntitiesOperation(OctreeElement* element, void* extraData);
static bool findNearPointOperation(OctreeElementPointer element, void* extraData);
static bool findInSphereOperation(OctreeElementPointer element, void* extraData);
static bool findInCubeOperation(OctreeElementPointer element, void* extraData);
static bool findInBoxOperation(OctreeElementPointer element, void* extraData);
static bool sendEntitiesOperation(OctreeElementPointer element, void* extraData);
void notifyNewlyCreatedEntity(const EntityItem& newEntity, const SharedNodePointer& senderNode);
@ -221,7 +235,7 @@ private:
QMultiMap<quint64, QUuid> _recentlyDeletedEntityItemIDs;
EntityItemFBXService* _fbxService;
QHash<EntityItemID, EntityTreeElement*> _entityToElementMap;
QHash<EntityItemID, EntityTreeElementPointer> _entityToElementMap;
EntitySimulation* _simulation;

View file

@ -28,25 +28,45 @@ 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* dyingElement) {
// make a new shared pointer with a reference count of 1 (and no custom deleter)
EntityTreeElementPointer tmpSharedPointer(dyingElement);
// call notifyDeleteHooks which will use shared_from_this() to get this same
// shared pointer, for use with the elementDeleted calls.
dyingElement->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);
_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;
@ -54,15 +74,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
@ -70,7 +90,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 {
@ -90,7 +110,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
@ -111,7 +131,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;
}
@ -172,24 +192,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();
@ -239,7 +259,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
@ -247,14 +268,15 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
entityTreeElementExtraEncodeData->elementCompleted = !hasContent();
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;
}
}
}
@ -471,7 +493,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...
@ -651,7 +673,7 @@ bool EntityTreeElement::removeEntityItem(EntityItemPointer entity) {
numEntries = _entityItems.removeAll(entity);
});
if (numEntries > 0) {
assert(entity->_element == this);
assert(entity->_element.get() == this);
entity->_element = NULL;
return true;
}
@ -674,7 +696,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;
}
@ -717,7 +739,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()) {
@ -726,13 +748,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());
}
}
}
@ -750,7 +772,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();
@ -770,11 +792,11 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int
void EntityTreeElement::addEntityItem(EntityItemPointer entity) {
assert(entity);
assert(entity->_element == NULL);
assert(entity->_element == nullptr);
withWriteLock([&] {
_entityItems.push_back(entity);
});
entity->_element = this;
entity->_element = getThisPointer();
}
// will average a "common reduced LOD view" from the the child elements...
@ -794,7 +816,7 @@ bool EntityTreeElement::collapseChildren() {
bool EntityTreeElement::pruneChildren() {
bool somethingPruned = false;
for (int childIndex = 0; childIndex < NUMBER_OF_CHILDREN; childIndex++) {
EntityTreeElement* child = getChildAtIndex(childIndex);
EntityTreeElementPointer child = getChildAtIndex(childIndex);
// if my child is a leaf, but has no entities, then it's safe to delete my child
if (child && child->isLeaf() && !child->hasEntities()) {

View file

@ -25,6 +25,7 @@ typedef QVector<EntityItemPointer> EntityItems;
class EntityTree;
class EntityTreeElement;
typedef std::shared_ptr<EntityTreeElement> EntityTreeElementPointer;
class EntityTreeUpdateArgs {
public:
@ -79,18 +80,20 @@ class EntityTreeElement : public OctreeElement, ReadWriteLockable {
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,
@ -159,8 +162,8 @@ public:
virtual uint16_t size() const;
bool hasEntities() const { return size() > 0; }
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);
@ -207,9 +210,19 @@ public:
void expandExtentsToContents(Extents& extents);
EntityTreeElementPointer getThisPointer() {
return std::static_pointer_cast<EntityTreeElement>(shared_from_this());
}
OctreeElementPointer getThisOctreeElementPointer() {
return std::static_pointer_cast<OctreeElement>(shared_from_this());
}
const ConstOctreeElementPointer getConstThisOctreeElementPointer() const {
return std::static_pointer_cast<const OctreeElement>(shared_from_this());
}
protected:
virtual void init(unsigned char * octalCode);
EntityTree* _myTree;
EntityTreePointer _myTree;
EntityItems _entityItems;
};

View file

@ -23,7 +23,7 @@ void EntityTreeHeadlessViewer::init() {
OctreeHeadlessViewer::init();
if (!_simulation) {
SimpleEntitySimulation* simpleSimulation = new SimpleEntitySimulation();
EntityTree* entityTree = static_cast<EntityTree*>(_tree);
EntityTreePointer entityTree = std::static_pointer_cast<EntityTree>(_tree);
simpleSimulation->setEntityTree(entityTree);
entityTree->setSimulation(simpleSimulation);
_simulation = simpleSimulation;
@ -32,7 +32,7 @@ void EntityTreeHeadlessViewer::init() {
void EntityTreeHeadlessViewer::update() {
if (_tree) {
EntityTree* tree = static_cast<EntityTree*>(_tree);
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
tree->withTryWriteLock([&] {
tree->update();
});
@ -40,5 +40,5 @@ void EntityTreeHeadlessViewer::update() {
}
void EntityTreeHeadlessViewer::processEraseMessage(NLPacket& packet, const SharedNodePointer& sourceNode) {
static_cast<EntityTree*>(_tree)->processEraseMessage(packet, sourceNode);
std::static_pointer_cast<EntityTree>(_tree)->processEraseMessage(packet, sourceNode);
}

View file

@ -36,14 +36,18 @@ public:
void update();
EntityTree* getTree() { return (EntityTree*)_tree; }
EntityTreePointer getTree() { return std::static_pointer_cast<EntityTree>(_tree); }
void processEraseMessage(NLPacket& packet, const SharedNodePointer& sourceNode);
virtual void init();
protected:
virtual Octree* createTree() { return new EntityTree(true); }
virtual OctreePointer createTree() {
EntityTreePointer newTree = EntityTreePointer(new EntityTree(true));
newTree->createRootElement();
return newTree;
}
EntitySimulation* _simulation;
};

View file

@ -64,7 +64,7 @@ class LineEntityItem : public EntityItem {
// never have a ray intersection pick a LineEntityItem.
virtual bool supportsDetailedRayIntersection() const { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) const { return false; }
virtual void debugDump() const;

View file

@ -16,7 +16,7 @@
#include "MovingEntitiesOperator.h"
MovingEntitiesOperator::MovingEntitiesOperator(EntityTree* tree) :
MovingEntitiesOperator::MovingEntitiesOperator(EntityTreePointer tree) :
_tree(tree),
_changeTime(usecTimestampNow()),
_foundOldCount(0),
@ -51,7 +51,7 @@ MovingEntitiesOperator::~MovingEntitiesOperator() {
void MovingEntitiesOperator::addEntityToMoveList(EntityItemPointer entity, const AACube& newCube) {
EntityTreeElement* oldContainingElement = _tree->getContainingElement(entity->getEntityItemID());
EntityTreeElementPointer oldContainingElement = _tree->getContainingElement(entity->getEntityItemID());
AABox newCubeClamped = newCube.clamp((float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE);
if (_wantDebug) {
@ -109,7 +109,7 @@ void MovingEntitiesOperator::addEntityToMoveList(EntityItemPointer entity, const
}
// does this entity tree element contain the old entity
bool MovingEntitiesOperator::shouldRecurseSubTree(OctreeElement* element) {
bool MovingEntitiesOperator::shouldRecurseSubTree(OctreeElementPointer element) {
bool containsEntity = false;
// If we don't have an old entity, then we don't contain the entity, otherwise
@ -141,8 +141,8 @@ bool MovingEntitiesOperator::shouldRecurseSubTree(OctreeElement* element) {
return containsEntity;
}
bool MovingEntitiesOperator::preRecursion(OctreeElement* element) {
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
bool MovingEntitiesOperator::preRecursion(OctreeElementPointer element) {
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
// In Pre-recursion, we're generally deciding whether or not we want to recurse this
// path of the tree. For this operation, we want to recurse the branch of the tree if
@ -169,7 +169,7 @@ bool MovingEntitiesOperator::preRecursion(OctreeElement* element) {
qCDebug(entities) << " entityTreeElement->bestFitBounds(details.newCube):" << entityTreeElement->bestFitBounds(details.newCube);
qCDebug(entities) << " details.entity:" << details.entity->getEntityItemID();
qCDebug(entities) << " details.oldContainingElementCube:" << details.oldContainingElementCube;
qCDebug(entities) << " entityTreeElement:" << entityTreeElement;
qCDebug(entities) << " entityTreeElement:" << entityTreeElement.get();
qCDebug(entities) << " details.newCube:" << details.newCube;
qCDebug(entities) << " details.newCubeClamped:" << details.newCubeClamped;
qCDebug(entities) << " _lookingCount:" << _lookingCount;
@ -195,7 +195,7 @@ bool MovingEntitiesOperator::preRecursion(OctreeElement* element) {
if (!details.newFound && entityTreeElement->bestFitBounds(details.newCube)) {
EntityItemID entityItemID = details.entity->getEntityItemID();
// remove from the old before adding
EntityTreeElement* oldElement = details.entity->getElement();
EntityTreeElementPointer oldElement = details.entity->getElement();
if (oldElement != entityTreeElement) {
if (oldElement) {
oldElement->removeEntityItem(details.entity);
@ -221,7 +221,7 @@ bool MovingEntitiesOperator::preRecursion(OctreeElement* element) {
return keepSearching; // if we haven't yet found it, keep looking
}
bool MovingEntitiesOperator::postRecursion(OctreeElement* element) {
bool MovingEntitiesOperator::postRecursion(OctreeElementPointer element) {
// Post-recursion is the unwinding process. For this operation, while we
// unwind we want to mark the path as being dirty if we changed it below.
// We might have two paths, one for the old entity and one for the new entity.
@ -254,14 +254,14 @@ bool MovingEntitiesOperator::postRecursion(OctreeElement* element) {
}
}
if (!elementSubTreeContainsOldElements || !elementIsDirectParentOfOldElment) {
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
entityTreeElement->pruneChildren(); // take this opportunity to prune any empty leaves
}
return keepSearching; // if we haven't yet found it, keep looking
}
OctreeElement* MovingEntitiesOperator::possiblyCreateChildAt(OctreeElement* element, int childIndex) {
OctreeElementPointer MovingEntitiesOperator::possiblyCreateChildAt(OctreeElementPointer element, int childIndex) {
// If we're getting called, it's because there was no child element at this index while recursing.
// We only care if this happens while still searching for the new entity locations.
if (_foundNewCount < _lookingCount) {

View file

@ -18,7 +18,7 @@ public:
AACube oldCube; // meters
AACube newCube; // meters
AABox newCubeClamped; // meters
EntityTreeElement* oldContainingElement;
EntityTreeElementPointer oldContainingElement;
AACube oldContainingElementCube; // meters
bool oldFound;
bool newFound;
@ -34,22 +34,22 @@ inline bool operator==(const EntityToMoveDetails& a, const EntityToMoveDetails&
class MovingEntitiesOperator : public RecurseOctreeOperator {
public:
MovingEntitiesOperator(EntityTree* tree);
MovingEntitiesOperator(EntityTreePointer tree);
~MovingEntitiesOperator();
void addEntityToMoveList(EntityItemPointer entity, const AACube& newCube);
virtual bool preRecursion(OctreeElement* element);
virtual bool postRecursion(OctreeElement* element);
virtual OctreeElement* possiblyCreateChildAt(OctreeElement* element, int childIndex);
virtual bool preRecursion(OctreeElementPointer element);
virtual bool postRecursion(OctreeElementPointer element);
virtual OctreeElementPointer possiblyCreateChildAt(OctreeElementPointer element, int childIndex);
bool hasMovingEntities() const { return _entitiesToMove.size() > 0; }
private:
EntityTree* _tree;
EntityTreePointer _tree;
QSet<EntityToMoveDetails> _entitiesToMove;
quint64 _changeTime;
int _foundOldCount;
int _foundNewCount;
int _lookingCount;
bool shouldRecurseSubTree(OctreeElement* element);
bool shouldRecurseSubTree(OctreeElementPointer element);
bool _wantDebug;
};

View file

@ -73,7 +73,7 @@ class PolyLineEntityItem : public EntityItem {
// never have a ray intersection pick a PolyLineEntityItem.
virtual bool supportsDetailedRayIntersection() const { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) const { return false; }
virtual void debugDump() const;

View file

@ -44,7 +44,7 @@ class PolyVoxEntityItem : public EntityItem {
// never have a ray intersection pick a PolyVoxEntityItem.
virtual bool supportsDetailedRayIntersection() const { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) const { return false; }
virtual void debugDump() const;

View file

@ -13,8 +13,8 @@
RecurseOctreeToMapOperator::RecurseOctreeToMapOperator(QVariantMap& map,
OctreeElement *top,
QScriptEngine *engine,
OctreeElementPointer top,
QScriptEngine* engine,
bool skipDefaultValues) :
RecurseOctreeOperator(),
_map(map),
@ -22,7 +22,7 @@ RecurseOctreeToMapOperator::RecurseOctreeToMapOperator(QVariantMap& map,
_engine(engine),
_skipDefaultValues(skipDefaultValues)
{
// if some element "top" was given, only save information for that element and it's children.
// if some element "top" was given, only save information for that element and its children.
if (_top) {
_withinTop = false;
} else {
@ -31,18 +31,18 @@ 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) {
bool RecurseOctreeToMapOperator::postRecursion(OctreeElementPointer element) {
EntityItemProperties defaultProperties;
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
QVariantList entitiesQList = qvariant_cast<QVariantList>(_map["Entities"]);
entityTreeElement->forEachEntity([&](EntityItemPointer entityItem) {

View file

@ -13,13 +13,13 @@
class RecurseOctreeToMapOperator : public RecurseOctreeOperator {
public:
RecurseOctreeToMapOperator(QVariantMap& map, OctreeElement *top, QScriptEngine *engine, bool skipDefaultValues);
bool preRecursion(OctreeElement* element);
bool postRecursion(OctreeElement* element);
RecurseOctreeToMapOperator(QVariantMap& map, OctreeElementPointer top, QScriptEngine* engine, bool skipDefaultValues);
bool preRecursion(OctreeElementPointer element);
bool postRecursion(OctreeElementPointer element);
private:
QVariantMap& _map;
OctreeElement *_top;
QScriptEngine *_engine;
OctreeElementPointer _top;
QScriptEngine* _engine;
bool _withinTop;
bool _skipDefaultValues;
};

View file

@ -94,8 +94,9 @@ void SphereEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBi
}
bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) const {
bool& keepSearching, OctreeElementPointer& element,
float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) const {
// determine the ray in the frame of the entity transformed from a unit sphere
glm::mat4 entityToWorldMatrix = getEntityToWorldMatrix();
glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix);

View file

@ -54,7 +54,7 @@ public:
virtual bool supportsDetailedRayIntersection() const { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) const;
virtual void debugDump() const;

View file

@ -129,7 +129,7 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits
}
bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) const {
glm::vec3 dimensions = getDimensions();
glm::vec2 xyDimensions(dimensions.x, dimensions.y);

View file

@ -47,7 +47,7 @@ public:
virtual bool supportsDetailedRayIntersection() const { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) const;
static const QString DEFAULT_TEXT;

View file

@ -16,14 +16,14 @@
#include "UpdateEntityOperator.h"
UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree,
EntityTreeElement* containingElement,
EntityItemPointer existingEntity,
UpdateEntityOperator::UpdateEntityOperator(EntityTreePointer tree,
EntityTreeElementPointer containingElement,
EntityItemPointer existingEntity,
const EntityItemProperties& properties) :
_tree(tree),
_existingEntity(existingEntity),
_containingElement(containingElement),
_containingElementCube(containingElement->getAACube()),
_containingElementCube(containingElement->getAACube()),
_properties(properties),
_entityItemID(existingEntity->getEntityItemID()),
_foundOld(false),
@ -37,10 +37,10 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree,
{
// caller must have verified existence of containingElement and oldEntity
assert(_containingElement && _existingEntity);
if (_wantDebug) {
qCDebug(entities) << "UpdateEntityOperator::UpdateEntityOperator() -----------------------------";
}
}
// Here we have a choice to make, do we want to "tight fit" the actual minimum for the
// entity into the the element, or do we want to use the entities "relaxed" bounds
@ -144,7 +144,7 @@ UpdateEntityOperator::~UpdateEntityOperator() {
// does this entity tree element contain the old entity
bool UpdateEntityOperator::subTreeContainsOldEntity(OctreeElement* element) {
bool UpdateEntityOperator::subTreeContainsOldEntity(OctreeElementPointer element) {
// We've found cases where the old entity might be placed in an element that is not actually the best fit
// so when we're searching the tree for the old element, we use the known cube for the known containing element
@ -162,7 +162,7 @@ bool UpdateEntityOperator::subTreeContainsOldEntity(OctreeElement* element) {
return elementContainsOldBox;
}
bool UpdateEntityOperator::subTreeContainsNewEntity(OctreeElement* element) {
bool UpdateEntityOperator::subTreeContainsNewEntity(OctreeElementPointer element) {
bool elementContainsNewBox = element->getAACube().contains(_newEntityBox);
if (_wantDebug) {
@ -179,8 +179,8 @@ bool UpdateEntityOperator::subTreeContainsNewEntity(OctreeElement* element) {
}
bool UpdateEntityOperator::preRecursion(OctreeElement* element) {
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
bool UpdateEntityOperator::preRecursion(OctreeElementPointer element) {
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
// In Pre-recursion, we're generally deciding whether or not we want to recurse this
// path of the tree. For this operation, we want to recurse the branch of the tree if
@ -211,8 +211,8 @@ bool UpdateEntityOperator::preRecursion(OctreeElement* element) {
if (_wantDebug) {
qCDebug(entities) << " OLD TREE CASE....";
qCDebug(entities) << " entityTreeElement=" << entityTreeElement;
qCDebug(entities) << " _containingElement=" << _containingElement;
qCDebug(entities) << " entityTreeElement=" << entityTreeElement.get();
qCDebug(entities) << " _containingElement=" << _containingElement.get();
}
// If this is the element we're looking for, then ask it to remove the old entity
@ -234,7 +234,7 @@ bool UpdateEntityOperator::preRecursion(OctreeElement* element) {
// the entity knows what element it's in, so we remove it from that one
// NOTE: we know we haven't yet added it to its new element because _removeOld is true
EntityTreeElement* oldElement = _existingEntity->getElement();
EntityTreeElementPointer oldElement = _existingEntity->getElement();
oldElement->removeEntityItem(_existingEntity);
_tree->setContainingElement(_entityItemID, NULL);
@ -260,8 +260,8 @@ bool UpdateEntityOperator::preRecursion(OctreeElement* element) {
if (_wantDebug) {
qCDebug(entities) << " NEW TREE CASE....";
qCDebug(entities) << " entityTreeElement=" << entityTreeElement;
qCDebug(entities) << " _containingElement=" << _containingElement;
qCDebug(entities) << " entityTreeElement=" << entityTreeElement.get();
qCDebug(entities) << " _containingElement=" << _containingElement.get();
qCDebug(entities) << " entityTreeElement->bestFitBounds(_newEntityBox)=" << entityTreeElement->bestFitBounds(_newEntityBox);
}
@ -272,7 +272,7 @@ bool UpdateEntityOperator::preRecursion(OctreeElement* element) {
qCDebug(entities) << " *** THIS ELEMENT IS BEST FIT ***";
}
EntityTreeElement* oldElement = _existingEntity->getElement();
EntityTreeElementPointer oldElement = _existingEntity->getElement();
// if we are the existing containing element, then we can just do the update of the entity properties
if (entityTreeElement == oldElement) {
@ -317,7 +317,7 @@ bool UpdateEntityOperator::preRecursion(OctreeElement* element) {
return keepSearching; // if we haven't yet found it, keep looking
}
bool UpdateEntityOperator::postRecursion(OctreeElement* element) {
bool UpdateEntityOperator::postRecursion(OctreeElementPointer element) {
// Post-recursion is the unwinding process. For this operation, while we
// unwind we want to mark the path as being dirty if we changed it below.
// We might have two paths, one for the old entity and one for the new entity.
@ -342,14 +342,14 @@ bool UpdateEntityOperator::postRecursion(OctreeElement* element) {
// 2) we are removing the old, but this subtree doesn't contain the old
// 3) we are removing the old, this subtree contains the old, but this element isn't a direct parent of _containingElement
if (!_removeOld || !subtreeContainsOld || !element->isParentOf(_containingElement)) {
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
entityTreeElement->pruneChildren(); // take this opportunity to prune any empty leaves
}
return keepSearching; // if we haven't yet found it, keep looking
}
OctreeElement* UpdateEntityOperator::possiblyCreateChildAt(OctreeElement* element, int childIndex) {
OctreeElementPointer UpdateEntityOperator::possiblyCreateChildAt(OctreeElementPointer element, int childIndex) {
// If we're getting called, it's because there was no child element at this index while recursing.
// We only care if this happens while still searching for the new entity location.
// Check to see if

View file

@ -14,17 +14,17 @@
class UpdateEntityOperator : public RecurseOctreeOperator {
public:
UpdateEntityOperator(EntityTree* tree, EntityTreeElement* containingElement,
EntityItemPointer existingEntity, const EntityItemProperties& properties);
UpdateEntityOperator(EntityTreePointer tree, EntityTreeElementPointer containingElement,
EntityItemPointer existingEntity, const EntityItemProperties& properties);
~UpdateEntityOperator();
virtual bool preRecursion(OctreeElement* element);
virtual bool postRecursion(OctreeElement* element);
virtual OctreeElement* possiblyCreateChildAt(OctreeElement* element, int childIndex);
virtual bool preRecursion(OctreeElementPointer element);
virtual bool postRecursion(OctreeElementPointer element);
virtual OctreeElementPointer possiblyCreateChildAt(OctreeElementPointer element, int childIndex);
private:
EntityTree* _tree;
EntityTreePointer _tree;
EntityItemPointer _existingEntity;
EntityTreeElement* _containingElement;
EntityTreeElementPointer _containingElement;
AACube _containingElementCube; // we temporarily store our cube here in case we need to delete the containing element
EntityItemProperties _properties;
EntityItemID _entityItemID;
@ -40,8 +40,8 @@ private:
AABox _oldEntityBox; // clamped to domain
AABox _newEntityBox; // clamped to domain
bool subTreeContainsOldEntity(OctreeElement* element);
bool subTreeContainsNewEntity(OctreeElement* element);
bool subTreeContainsOldEntity(OctreeElementPointer element);
bool subTreeContainsNewEntity(OctreeElementPointer element);
bool _wantDebug;
};

View file

@ -99,7 +99,7 @@ void WebEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitst
}
bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) const {
glm::vec3 dimensions = getDimensions();
glm::vec2 xyDimensions(dimensions.x, dimensions.y);

View file

@ -46,7 +46,7 @@ public:
virtual bool supportsDetailedRayIntersection() const { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) const;
virtual void setSourceUrl(const QString& value);

View file

@ -246,7 +246,7 @@ void ZoneEntityItem::setCompoundShapeURL(const QString& url) {
}
bool ZoneEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) const {
return _zonesArePickable;

View file

@ -15,7 +15,8 @@
#include <EnvironmentData.h>
#include "AtmospherePropertyGroup.h"
#include "EntityItem.h"
#include "EntityItem.h"
#include "EntityTree.h"
class ZoneEntityItem : public EntityItem {
public:
@ -99,7 +100,7 @@ public:
virtual bool supportsDetailedRayIntersection() const { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) const;
virtual void debugDump() const;

View file

@ -70,6 +70,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) {
@ -82,7 +120,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
@ -95,7 +133,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);
}
@ -104,8 +142,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(
@ -116,7 +154,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);
}
@ -133,7 +171,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) {
@ -147,24 +185,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);
}
@ -176,7 +214,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(
@ -188,7 +227,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....
@ -208,8 +247,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;
@ -218,7 +257,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) {
@ -244,7 +283,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
@ -273,7 +313,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;
@ -304,7 +344,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);
@ -404,7 +444,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
@ -490,7 +531,7 @@ void Octree::deleteOctalCodeFromTree(const unsigned char* codeBuffer, bool colla
});
}
void Octree::deleteOctalCodeFromTreeRecursion(OctreeElement* element, void* extraData) {
void Octree::deleteOctalCodeFromTreeRecursion(OctreeElementPointer element, void* extraData) {
DeleteOctalCodeFromTreeArgs* args = (DeleteOctalCodeFromTreeArgs*)extraData;
int lengthOfElementCode = numberOfThreeBitSectionsInCode(element->getOctalCode());
@ -507,14 +548,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);
@ -575,23 +616,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();
}
@ -627,9 +667,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;
}
@ -637,20 +677,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);
}
@ -659,7 +699,7 @@ class RayArgs {
public:
glm::vec3 origin;
glm::vec3 direction;
OctreeElement*& element;
OctreeElementPointer& element;
float& distance;
BoxFace& face;
void** intersectedObject;
@ -667,7 +707,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,
@ -678,7 +718,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};
@ -705,7 +745,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
@ -767,7 +807,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
@ -800,7 +840,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
@ -848,12 +888,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()) {
@ -868,7 +908,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;
@ -887,9 +927,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;
@ -945,7 +985,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
@ -976,10 +1016,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;
@ -1168,13 +1208,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
@ -1194,9 +1234,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;
@ -1215,7 +1255,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 &&
@ -1231,7 +1271,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,
@ -1258,7 +1298,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()));
@ -1372,7 +1412,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
@ -1518,7 +1558,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)) {
@ -1999,7 +2039,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();
@ -2016,12 +2056,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 {
@ -2061,7 +2101,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()) {
@ -2102,7 +2142,7 @@ void Octree::writeToSVOFile(const char* fileName, OctreeElement* element) {
bool lastPacketWritten = false;
while (!elementBag.isEmpty()) {
OctreeElement* subTree = elementBag.extract();
OctreeElementPointer subTree = elementBag.extract();
EncodeBitstreamParams params(INT_MAX, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS);
withReadLock([&] {
@ -2150,7 +2190,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
}
@ -2158,4 +2198,3 @@ bool Octree::countOctreeElementsOperation(OctreeElement* element, void* extraDat
void Octree::cancelImport() {
_stopImport = true;
}

View file

@ -12,10 +12,11 @@
#ifndef hifi_Octree_h
#define hifi_Octree_h
#include <memory>
#include <set>
#include <QHash>
#include <QObject>
#include <QReadWriteLock>
class CoverageMap;
class ReadBitstreamToTreeParams;
@ -24,6 +25,8 @@ class OctreeElement;
class OctreeElementBag;
class OctreePacketData;
class Shape;
typedef std::shared_ptr<Octree> OctreePointer;
#include <shared/ReadWriteLockable.h>
#include <SimpleMovingAverage.h>
@ -41,13 +44,13 @@ 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 +193,7 @@ class ReadBitstreamToTreeParams {
public:
bool includeColor;
bool includeExistsBits;
OctreeElement* destinationElement;
OctreeElementPointer destinationElement;
QUuid sourceUUID;
SharedNodePointer sourceNode;
bool wantImportProgress;
@ -201,7 +204,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 +219,14 @@ public:
{}
};
class Octree : public QObject, public ReadWriteLockable {
class Octree : public QObject, public std::enable_shared_from_this<Octree>, public ReadWriteLockable {
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 +253,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 +285,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; }
@ -296,7 +299,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,
@ -315,17 +318,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);
@ -340,18 +343,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; }
@ -382,21 +385,21 @@ 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;

View file

@ -42,7 +42,7 @@ void OctreeElement::resetPopulationStatistics() {
OctreeElement::OctreeElement() {
// Note: you must call init() from your subclass, otherwise the OctreeElement will not be properly
// initialized. You will see DEADBEEF in your memory debugger if you have not properly called init()
debug::setDeadBeef(this, sizeof(*this));
// debug::setDeadBeef(this, sizeof(*this));
}
void OctreeElement::init(unsigned char * octalCode) {
@ -80,9 +80,13 @@ void OctreeElement::init(unsigned char * octalCode) {
#endif
#ifdef SIMPLE_EXTERNAL_CHILDREN
_children.single = NULL;
_childrenSingle.reset();
#endif
for (int i = 0; i < NUMBER_OF_CHILDREN; i ++) {
_externalChildren[i].reset();
}
_isDirty = true;
_shouldRender = false;
_sourceUUIDKey = 0;
@ -91,7 +95,10 @@ void OctreeElement::init(unsigned char * octalCode) {
}
OctreeElement::~OctreeElement() {
notifyDeleteHooks();
// We can't call notifyDeleteHooks from here:
// notifyDeleteHooks();
// see comment in EntityTreeElement::createNewElement.
assert(_deleteHooksNotified);
_voxelNodeCount--;
if (isLeaf()) {
_voxelNodeLeafCount--;
@ -117,7 +124,7 @@ void OctreeElement::markWithChangedTime() {
// changed. However, you should hopefully make your bookkeeping relatively
// localized, because this method will get called for every node in an
// recursive unwinding case like delete or add voxel
void OctreeElement::handleSubtreeChanged(Octree* myTree) {
void OctreeElement::handleSubtreeChanged(OctreePointer myTree) {
// here's a good place to do color re-averaging...
if (myTree->getShouldReaverage()) {
calculateAverageFromChildren();
@ -196,9 +203,9 @@ void OctreeElement::calculateAACube() {
}
void OctreeElement::deleteChildAtIndex(int childIndex) {
OctreeElement* childAt = getChildAtIndex(childIndex);
OctreeElementPointer childAt = getChildAtIndex(childIndex);
if (childAt) {
delete childAt;
childAt.reset();
setChildAtIndex(childIndex, NULL);
_isDirty = true;
markWithChangedTime();
@ -211,8 +218,8 @@ void OctreeElement::deleteChildAtIndex(int childIndex) {
}
// does not delete the node!
OctreeElement* OctreeElement::removeChildAtIndex(int childIndex) {
OctreeElement* returnedChild = getChildAtIndex(childIndex);
OctreeElementPointer OctreeElement::removeChildAtIndex(int childIndex) {
OctreeElementPointer returnedChild = getChildAtIndex(childIndex);
if (returnedChild) {
setChildAtIndex(childIndex, NULL);
_isDirty = true;
@ -226,10 +233,10 @@ OctreeElement* OctreeElement::removeChildAtIndex(int childIndex) {
return returnedChild;
}
bool OctreeElement::isParentOf(OctreeElement* possibleChild) const {
bool OctreeElement::isParentOf(OctreeElementPointer possibleChild) const {
if (possibleChild) {
for (int childIndex = 0; childIndex < NUMBER_OF_CHILDREN; childIndex++) {
OctreeElement* childAt = getChildAtIndex(childIndex);
OctreeElementPointer childAt = getChildAtIndex(childIndex);
if (childAt == possibleChild) {
return true;
}
@ -246,7 +253,7 @@ quint64 OctreeElement::_setChildAtIndexCalls = 0;
quint64 OctreeElement::_externalChildrenCount = 0;
quint64 OctreeElement::_childrenCount[NUMBER_OF_CHILDREN + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
OctreeElement* OctreeElement::getChildAtIndex(int childIndex) const {
OctreeElementPointer OctreeElement::getChildAtIndex(int childIndex) const {
#ifdef SIMPLE_CHILD_ARRAY
return _simpleChildArray[childIndex];
#endif // SIMPLE_CHILD_ARRAY
@ -264,14 +271,14 @@ OctreeElement* OctreeElement::getChildAtIndex(int childIndex) const {
// return null
int firstIndex = getNthBit(_childBitmask, 1);
if (firstIndex == childIndex) {
return _children.single;
return _childrenSingle;
} else {
return NULL;
}
} break;
default : {
return _children.external[childIndex];
return _externalChildren[childIndex];
} break;
}
#endif // def SIMPLE_EXTERNAL_CHILDREN
@ -280,19 +287,21 @@ OctreeElement* OctreeElement::getChildAtIndex(int childIndex) const {
void OctreeElement::deleteAllChildren() {
// first delete all the OctreeElement objects...
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
OctreeElement* childAt = getChildAtIndex(i);
OctreeElementPointer childAt = getChildAtIndex(i);
if (childAt) {
delete childAt;
childAt.reset();
}
}
if (_childrenExternal) {
// if the children_t union represents _children.external we need to delete it here
delete[] _children.external;
for (int i = 0; i < NUMBER_OF_CHILDREN; i ++) {
_externalChildren[i].reset();
}
}
}
void OctreeElement::setChildAtIndex(int childIndex, OctreeElement* child) {
void OctreeElement::setChildAtIndex(int childIndex, OctreeElementPointer child) {
#ifdef SIMPLE_CHILD_ARRAY
int previousChildCount = getChildCount();
if (child) {
@ -332,44 +341,47 @@ void OctreeElement::setChildAtIndex(int childIndex, OctreeElement* child) {
}
if ((previousChildCount == 0 || previousChildCount == 1) && newChildCount == 0) {
_children.single = NULL;
_childrenSingle.reset();
} else if (previousChildCount == 0 && newChildCount == 1) {
_children.single = child;
_childrenSingle = child;
} else if (previousChildCount == 1 && newChildCount == 2) {
OctreeElement* previousChild = _children.single;
_children.external = new OctreeElement*[NUMBER_OF_CHILDREN];
memset(_children.external, 0, sizeof(OctreeElement*) * NUMBER_OF_CHILDREN);
_children.external[firstIndex] = previousChild;
_children.external[childIndex] = child;
OctreeElementPointer previousChild = _childrenSingle;
for (int i = 0; i < NUMBER_OF_CHILDREN; i ++) {
_externalChildren[i].reset();
}
_externalChildren[firstIndex] = previousChild;
_externalChildren[childIndex] = child;
_childrenExternal = true;
_externalChildrenMemoryUsage += NUMBER_OF_CHILDREN * sizeof(OctreeElement*);
_externalChildrenMemoryUsage += NUMBER_OF_CHILDREN * sizeof(OctreeElementPointer);
} else if (previousChildCount == 2 && newChildCount == 1) {
assert(!child); // we are removing a child, so this must be true!
OctreeElement* previousFirstChild = _children.external[firstIndex];
OctreeElement* previousSecondChild = _children.external[secondIndex];
OctreeElementPointer previousFirstChild = _externalChildren[firstIndex];
OctreeElementPointer previousSecondChild = _externalChildren[secondIndex];
delete[] _children.external;
for (int i = 0; i < NUMBER_OF_CHILDREN; i ++) {
_externalChildren[i].reset();
}
_childrenExternal = false;
_externalChildrenMemoryUsage -= NUMBER_OF_CHILDREN * sizeof(OctreeElement*);
_externalChildrenMemoryUsage -= NUMBER_OF_CHILDREN * sizeof(OctreeElementPointer);
if (childIndex == firstIndex) {
_children.single = previousSecondChild;
_childrenSingle = previousSecondChild;
} else {
_children.single = previousFirstChild;
_childrenSingle = previousFirstChild;
}
} else {
_children.external[childIndex] = child;
_externalChildren[childIndex] = child;
}
#endif // def SIMPLE_EXTERNAL_CHILDREN
}
OctreeElement* OctreeElement::addChildAtIndex(int childIndex) {
OctreeElement* childAt = getChildAtIndex(childIndex);
OctreeElementPointer OctreeElement::addChildAtIndex(int childIndex) {
OctreeElementPointer childAt = getChildAtIndex(childIndex);
if (!childAt) {
// before adding a child, see if we're currently a leaf
if (isLeaf()) {
@ -397,7 +409,7 @@ bool OctreeElement::safeDeepDeleteChildAtIndex(int childIndex, int recursionCoun
qCDebug(octree) << "OctreeElement::safeDeepDeleteChildAtIndex() reached DANGEROUSLY_DEEP_RECURSION, bailing!";
return deleteApproved;
}
OctreeElement* childToDelete = getChildAtIndex(childIndex);
OctreeElementPointer childToDelete = getChildAtIndex(childIndex);
if (childToDelete) {
if (childToDelete->deleteApproved()) {
// If the child is not a leaf, then call ourselves recursively on all the children
@ -428,7 +440,7 @@ bool OctreeElement::safeDeepDeleteChildAtIndex(int childIndex, int recursionCoun
void OctreeElement::printDebugDetails(const char* label) const {
unsigned char childBits = 0;
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
OctreeElement* childAt = getChildAtIndex(i);
OctreeElementPointer childAt = getChildAtIndex(i);
if (childAt) {
setAtBit(childBits,i);
}
@ -534,9 +546,10 @@ void OctreeElement::removeDeleteHook(OctreeElementDeleteHook* hook) {
void OctreeElement::notifyDeleteHooks() {
_deleteHooksLock.lockForRead();
for (unsigned int i = 0; i < _deleteHooks.size(); i++) {
_deleteHooks[i]->elementDeleted(this);
_deleteHooks[i]->elementDeleted(shared_from_this());
}
_deleteHooksLock.unlock();
_deleteHooksNotified = true;
}
std::vector<OctreeElementUpdateHook*> OctreeElement::_updateHooks;
@ -556,12 +569,12 @@ void OctreeElement::removeUpdateHook(OctreeElementUpdateHook* hook) {
void OctreeElement::notifyUpdateHooks() {
for (unsigned int i = 0; i < _updateHooks.size(); i++) {
_updateHooks[i]->elementUpdated(this);
_updateHooks[i]->elementUpdated(shared_from_this());
}
}
bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) {
keepSearching = true; // assume that we will continue searching after this.
@ -599,12 +612,12 @@ bool OctreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3
}
bool OctreeElement::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking, float distanceToElementCube) {
// we did hit this element, so calculate appropriate distances
if (hasContent()) {
element = this;
element = shared_from_this();
distance = distanceToElementCube;
if (intersectedObject) {
*intersectedObject = this;
@ -622,8 +635,8 @@ bool OctreeElement::findSpherePenetration(const glm::vec3& center, float radius,
}
// TODO: consider removing this, or switching to using getOrCreateChildElementContaining(const AACube& box)...
OctreeElement* OctreeElement::getOrCreateChildElementAt(float x, float y, float z, float s) {
OctreeElement* child = NULL;
OctreeElementPointer OctreeElement::getOrCreateChildElementAt(float x, float y, float z, float s) {
OctreeElementPointer child = NULL;
// If the requested size is less than or equal to our scale, but greater than half our scale, then
// we are the Element they are looking for.
float ourScale = getScale();
@ -635,7 +648,7 @@ OctreeElement* OctreeElement::getOrCreateChildElementAt(float x, float y, float
}
if (s > halfOurScale) {
return this;
return shared_from_this();
}
int childIndex = getMyChildContainingPoint(glm::vec3(x, y, z));
@ -651,15 +664,15 @@ OctreeElement* OctreeElement::getOrCreateChildElementAt(float x, float y, float
}
OctreeElement* OctreeElement::getOrCreateChildElementContaining(const AACube& cube) {
OctreeElement* child = NULL;
OctreeElementPointer OctreeElement::getOrCreateChildElementContaining(const AACube& cube) {
OctreeElementPointer child = NULL;
int childIndex = getMyChildContaining(cube);
// If getMyChildContaining() returns CHILD_UNKNOWN then it means that our level
// is the correct level for this cube
if (childIndex == CHILD_UNKNOWN) {
return this;
return shared_from_this();
}
// Now, check if we have a child at that location
@ -677,15 +690,15 @@ OctreeElement* OctreeElement::getOrCreateChildElementContaining(const AACube& cu
return child->getOrCreateChildElementContaining(cube);
}
OctreeElement* OctreeElement::getOrCreateChildElementContaining(const AABox& box) {
OctreeElement* child = NULL;
OctreeElementPointer OctreeElement::getOrCreateChildElementContaining(const AABox& box) {
OctreeElementPointer child = NULL;
int childIndex = getMyChildContaining(box);
// If getMyChildContaining() returns CHILD_UNKNOWN then it means that our level
// is the correct level for this cube
if (childIndex == CHILD_UNKNOWN) {
return this;
return shared_from_this();
}
// Now, check if we have a child at that location

View file

@ -33,27 +33,30 @@ class OctreePacketData;
class ReadBitstreamToTreeParams;
class Shape;
class VoxelSystem;
typedef std::shared_ptr<OctreeElement> OctreeElementPointer;
typedef std::shared_ptr<const OctreeElement> ConstOctreeElementPointer;
typedef std::shared_ptr<Octree> OctreePointer;
// Callers who want delete hook callbacks should implement this class
class OctreeElementDeleteHook {
public:
virtual void elementDeleted(OctreeElement* element) = 0;
virtual void elementDeleted(OctreeElementPointer element) = 0;
};
// Callers who want update hook callbacks should implement this class
class OctreeElementUpdateHook {
public:
virtual void elementUpdated(OctreeElement* element) = 0;
virtual void elementUpdated(OctreeElementPointer element) = 0;
};
class OctreeElement {
class OctreeElement: public std::enable_shared_from_this<OctreeElement> {
protected:
// can only be constructed by derived implementation
OctreeElement();
virtual OctreeElement* createNewElement(unsigned char * octalCode = NULL) = 0;
virtual OctreeElementPointer createNewElement(unsigned char * octalCode = NULL) = 0;
public:
virtual void init(unsigned char * octalCode); /// Your subclass must call init on construction.
@ -62,7 +65,7 @@ public:
// methods you can and should override to implement your tree functionality
/// Adds a child to the current element. Override this if there is additional child initialization your class needs.
virtual OctreeElement* addChildAtIndex(int childIndex);
virtual OctreeElementPointer addChildAtIndex(int childIndex);
/// Override this to implement LOD averaging on changes to the tree.
virtual void calculateAverageFromChildren() { }
@ -90,7 +93,7 @@ public:
typedef enum { COMPLETED, PARTIAL, NONE } AppendState;
virtual void debugExtraEncodeData(EncodeBitstreamParams& params) const { }
virtual void initializeExtraEncodeData(EncodeBitstreamParams& params) const { }
virtual void initializeExtraEncodeData(EncodeBitstreamParams& params) { }
virtual bool shouldIncludeChildData(int childIndex, EncodeBitstreamParams& params) const { return true; }
virtual bool shouldRecurseChildTree(int childIndex, EncodeBitstreamParams& params) const { return true; }
@ -116,11 +119,11 @@ public:
virtual bool canRayIntersect() const { return isLeaf(); }
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& node, float& distance, BoxFace& face,
bool& keepSearching, OctreeElementPointer& node, float& distance, BoxFace& face,
void** intersectedObject = NULL, bool precisionPicking = false);
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking, float distanceToElementCube);
/// \param center center of sphere in meters
@ -132,10 +135,10 @@ public:
// Base class methods you don't need to implement
const unsigned char* getOctalCode() const { return (_octcodePointer) ? _octalCode.pointer : &_octalCode.buffer[0]; }
OctreeElement* getChildAtIndex(int childIndex) const;
OctreeElementPointer getChildAtIndex(int childIndex) const;
void deleteChildAtIndex(int childIndex);
OctreeElement* removeChildAtIndex(int childIndex);
bool isParentOf(OctreeElement* possibleChild) const;
OctreeElementPointer removeChildAtIndex(int childIndex);
bool isParentOf(OctreeElementPointer possibleChild) const;
/// handles deletion of all descendants, returns false if delete not approved
bool safeDeepDeleteChildAtIndex(int childIndex, int recursionCount = 0);
@ -145,16 +148,16 @@ public:
const glm::vec3& getCorner() const { return _cube.getCorner(); }
float getScale() const { return _cube.getScale(); }
int getLevel() const { return numberOfThreeBitSectionsInCode(getOctalCode()) + 1; }
float getEnclosingRadius() const;
bool isInView(const ViewFrustum& viewFrustum) const { return inFrustum(viewFrustum) != ViewFrustum::OUTSIDE; }
ViewFrustum::location inFrustum(const ViewFrustum& viewFrustum) const;
float distanceToCamera(const ViewFrustum& viewFrustum) const;
float distanceToCamera(const ViewFrustum& viewFrustum) const;
float furthestDistanceToCamera(const ViewFrustum& viewFrustum) const;
bool calculateShouldRender(const ViewFrustum* viewFrustum,
bool calculateShouldRender(const ViewFrustum* viewFrustum,
float voxelSizeScale = DEFAULT_OCTREE_SIZE_SCALE, int boundaryLevelAdjust = 0) const;
// points are assumed to be in Voxel Coordinates (not TREE_SCALE'd)
float distanceSquareToPoint(const glm::vec3& point) const; // when you don't need the actual distance, use this.
float distanceToPoint(const glm::vec3& point) const;
@ -168,13 +171,13 @@ public:
bool hasChangedSince(quint64 time) const { return (_lastChanged > time); }
void markWithChangedTime();
quint64 getLastChanged() const { return _lastChanged; }
void handleSubtreeChanged(Octree* myTree);
void handleSubtreeChanged(OctreePointer myTree);
// Used by VoxelSystem for rendering in/out of view and LOD
void setShouldRender(bool shouldRender);
bool getShouldRender() const { return _shouldRender; }
void setSourceUUID(const QUuid& sourceID);
QUuid getSourceUUID() const;
uint16_t getSourceUUIDKey() const { return _sourceUUIDKey; }
@ -186,7 +189,7 @@ public:
static void addUpdateHook(OctreeElementUpdateHook* hook);
static void removeUpdateHook(OctreeElementUpdateHook* hook);
static void resetPopulationStatistics();
static unsigned long getNodeCount() { return _voxelNodeCount; }
static unsigned long getInternalNodeCount() { return _voxelNodeCount - _voxelNodeLeafCount; }
@ -204,7 +207,7 @@ public:
static quint64 getExternalChildrenCount() { return _externalChildrenCount; }
static quint64 getChildrenCount(int childCount) { return _childrenCount[childCount]; }
enum ChildIndex {
CHILD_BOTTOM_RIGHT_NEAR = 0,
CHILD_BOTTOM_RIGHT_FAR = 1,
@ -231,9 +234,9 @@ public:
};
OctreeElement* getOrCreateChildElementAt(float x, float y, float z, float s);
OctreeElement* getOrCreateChildElementContaining(const AACube& box);
OctreeElement* getOrCreateChildElementContaining(const AABox& box);
OctreeElementPointer getOrCreateChildElementAt(float x, float y, float z, float s);
OctreeElementPointer getOrCreateChildElementContaining(const AACube& box);
OctreeElementPointer getOrCreateChildElementContaining(const AABox& box);
int getMyChildContaining(const AACube& cube) const;
int getMyChildContaining(const AABox& box) const;
int getMyChildContainingPoint(const glm::vec3& point) const;
@ -241,7 +244,7 @@ public:
protected:
void deleteAllChildren();
void setChildAtIndex(int childIndex, OctreeElement* child);
void setChildAtIndex(int childIndex, OctreeElementPointer child);
void calculateAACube();
void notifyDeleteHooks();
@ -253,22 +256,22 @@ protected:
union octalCode_t {
unsigned char buffer[8];
unsigned char* pointer;
} _octalCode;
} _octalCode;
quint64 _lastChanged; /// Client and server, timestamp this node was last changed, 8 bytes
/// Client and server, pointers to child nodes, various encodings
#ifdef SIMPLE_CHILD_ARRAY
OctreeElement* _simpleChildArray[8]; /// Only used when SIMPLE_CHILD_ARRAY is enabled
OctreeElementPointer _simpleChildArray[8]; /// Only used when SIMPLE_CHILD_ARRAY is enabled
#endif
#ifdef SIMPLE_EXTERNAL_CHILDREN
union children_t {
OctreeElement* single;
OctreeElement** external;
} _children;
// union children_t {
OctreeElementPointer _childrenSingle;
OctreeElementPointer _externalChildren[NUMBER_OF_CHILDREN];
// } _children;
#endif
uint16_t _sourceUUIDKey; /// Client only, stores node id of voxel server that sent his voxel, 2 bytes
// Support for _sourceUUID, we use these static member variables to track the UUIDs that are
@ -287,6 +290,8 @@ protected:
_unknownBufferIndex : 1,
_childrenExternal : 1; /// Client only, is this voxel's VBO buffer the unknown buffer index, 1 bit
bool _deleteHooksNotified = false;
static QReadWriteLock _deleteHooksLock;
static std::vector<OctreeElementDeleteHook*> _deleteHooks;

View file

@ -31,7 +31,7 @@ void OctreeElementBag::unhookNotifications() {
}
}
void OctreeElementBag::elementDeleted(OctreeElement* element) {
void OctreeElementBag::elementDeleted(OctreeElementPointer element) {
remove(element); // note: remove can safely handle nodes that aren't in it, so we don't need to check contains()
}
@ -41,25 +41,25 @@ void OctreeElementBag::deleteAll() {
}
void OctreeElementBag::insert(OctreeElement* element) {
void OctreeElementBag::insert(OctreeElementPointer element) {
_bagElements.insert(element);
}
OctreeElement* OctreeElementBag::extract() {
OctreeElement* result = NULL;
OctreeElementPointer OctreeElementBag::extract() {
OctreeElementPointer result = NULL;
if (_bagElements.size() > 0) {
QSet<OctreeElement*>::iterator front = _bagElements.begin();
QSet<OctreeElementPointer>::iterator front = _bagElements.begin();
result = *front;
_bagElements.erase(front);
}
return result;
}
bool OctreeElementBag::contains(OctreeElement* element) {
bool OctreeElementBag::contains(OctreeElementPointer element) {
return _bagElements.contains(element);
}
void OctreeElementBag::remove(OctreeElement* element) {
void OctreeElementBag::remove(OctreeElementPointer element) {
_bagElements.remove(element);
}

View file

@ -23,24 +23,24 @@ class OctreeElementBag : public OctreeElementDeleteHook {
public:
OctreeElementBag();
~OctreeElementBag();
void insert(OctreeElement* element); // put a element into the bag
OctreeElement* extract(); // pull a element out of the bag (could come in any order)
bool contains(OctreeElement* element); // is this element in the bag?
void remove(OctreeElement* element); // remove a specific element from the bag
void insert(OctreeElementPointer element); // put a element into the bag
OctreeElementPointer extract(); // pull a element out of the bag (could come in any order)
bool contains(OctreeElementPointer element); // is this element in the bag?
void remove(OctreeElementPointer element); // remove a specific element from the bag
bool isEmpty() const { return _bagElements.isEmpty(); }
int count() const { return _bagElements.size(); }
void deleteAll();
virtual void elementDeleted(OctreeElement* element);
virtual void elementDeleted(OctreeElementPointer element);
void unhookNotifications();
private:
QSet<OctreeElement*> _bagElements;
QSet<OctreeElementPointer> _bagElements;
bool _hooked;
};
typedef QMap<const OctreeElement*,void*> OctreeElementExtraEncodeData;
typedef QMap<const OctreeElement*, void*> OctreeElementExtraEncodeData;
#endif // hifi_OctreeElementBag_h

View file

@ -30,7 +30,7 @@ class OctreeHeadlessViewer : public OctreeRenderer {
public:
OctreeHeadlessViewer();
virtual ~OctreeHeadlessViewer();
virtual void renderElement(OctreeElement* element, RenderArgs* args) { /* swallow these */ }
virtual void renderElement(OctreeElementPointer element, RenderArgs* args) { /* swallow these */ }
virtual void init();
virtual void render(RenderArgs* renderArgs) override { /* swallow these */ }

View file

@ -31,7 +31,7 @@
const int OctreePersistThread::DEFAULT_PERSIST_INTERVAL = 1000 * 30; // every 30 seconds
OctreePersistThread::OctreePersistThread(Octree* tree, const QString& filename, int persistInterval,
OctreePersistThread::OctreePersistThread(OctreePointer tree, const QString& filename, int persistInterval,
bool wantBackup, const QJsonObject& settings, bool debugTimestampNow,
QString persistAsFileType) :
_tree(tree),

View file

@ -33,8 +33,8 @@ public:
static const int DEFAULT_PERSIST_INTERVAL;
OctreePersistThread(Octree* tree, const QString& filename, int persistInterval = DEFAULT_PERSIST_INTERVAL,
bool wantBackup = false, const QJsonObject& settings = QJsonObject(),
OctreePersistThread(OctreePointer tree, const QString& filename, int persistInterval = DEFAULT_PERSIST_INTERVAL,
bool wantBackup = false, const QJsonObject& settings = QJsonObject(),
bool debugTimestampNow = false, QString persistAsFileType="svo");
bool isInitialLoadComplete() const { return _initialLoadComplete; }
@ -48,7 +48,7 @@ signals:
protected:
/// Implements generic processing behavior for this thread.
virtual bool process();
void persist();
void backup();
void rollOldBackupVersions(const BackupRule& rule);
@ -56,9 +56,9 @@ protected:
bool getMostRecentBackup(const QString& format, QString& mostRecentBackupFileName, QDateTime& mostRecentBackupTime);
quint64 getMostRecentBackupTimeInUsecs(const QString& format);
void parseSettings(const QJsonObject& settings);
private:
Octree* _tree;
OctreePointer _tree;
QString _filename;
int _persistInterval;
bool _initialLoadComplete;
@ -69,7 +69,7 @@ private:
quint64 _lastCheck;
bool _wantBackup;
QVector<BackupRule> _backupRules;
bool _debugTimestampNow;
quint64 _lastTimeDebug;

View file

@ -35,22 +35,15 @@ void OctreeRenderer::init() {
}
OctreeRenderer::~OctreeRenderer() {
if (_tree && _managedTree) {
delete _tree;
}
}
void OctreeRenderer::setTree(Octree* newTree) {
if (_tree && _managedTree) {
delete _tree;
_managedTree = false;
}
void OctreeRenderer::setTree(OctreePointer newTree) {
_tree = newTree;
}
void OctreeRenderer::processDatagram(NLPacket& packet, SharedNodePointer sourceNode) {
bool extraDebugging = false;
if (extraDebugging) {
qCDebug(octree) << "OctreeRenderer::processDatagram()";
}
@ -199,7 +192,7 @@ void OctreeRenderer::processDatagram(NLPacket& packet, SharedNodePointer sourceN
}
}
bool OctreeRenderer::renderOperation(OctreeElement* element, void* extraData) {
bool OctreeRenderer::renderOperation(OctreeElementPointer element, void* extraData) {
RenderArgs* args = static_cast<RenderArgs*>(extraData);
if (element->isInView(*args->_viewFrustum)) {
if (element->hasContent()) {

View file

@ -38,12 +38,12 @@ public:
virtual char getMyNodeType() const = 0;
virtual PacketType getMyQueryMessageType() const = 0;
virtual PacketType getExpectedPacketType() const = 0;
virtual void renderElement(OctreeElement* element, RenderArgs* args) = 0;
virtual void renderElement(OctreeElementPointer element, RenderArgs* args) = 0;
virtual float getSizeScale() const { return DEFAULT_OCTREE_SIZE_SCALE; }
virtual int getBoundaryLevelAdjust() const { return 0; }
virtual void setTree(Octree* newTree);
virtual void setTree(OctreePointer newTree);
/// process incoming data
virtual void processDatagram(NLPacket& packet, SharedNodePointer sourceNode);
@ -56,7 +56,7 @@ public:
ViewFrustum* getViewFrustum() const { return _viewFrustum; }
void setViewFrustum(ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; }
static bool renderOperation(OctreeElement* element, void* extraData);
static bool renderOperation(OctreeElementPointer element, void* extraData);
/// clears the tree
virtual void clear();
@ -71,11 +71,11 @@ public:
float getAverageWaitLockPerPacket() const { return _waitLockPerPacket.getAverage(); }
float getAverageUncompressPerPacket() const { return _uncompressPerPacket.getAverage(); }
float getAverageReadBitstreamPerPacket() const { return _readBitstreamPerPacket.getAverage(); }
protected:
virtual Octree* createTree() = 0;
Octree* _tree;
protected:
virtual OctreePointer createTree() = 0;
OctreePointer _tree;
bool _managedTree;
ViewFrustum* _viewFrustum;

View file

@ -149,7 +149,8 @@ OctreeSceneStats::~OctreeSceneStats() {
reset();
}
void OctreeSceneStats::sceneStarted(bool isFullScene, bool isMoving, OctreeElement* root, JurisdictionMap* jurisdictionMap) {
void OctreeSceneStats::sceneStarted(bool isFullScene, bool isMoving, OctreeElementPointer root,
JurisdictionMap* jurisdictionMap) {
reset(); // resets packet and octree stats
_isStarted = true;
_start = usecTimestampNow();
@ -286,7 +287,7 @@ void OctreeSceneStats::packetSent(int bytes) {
_bytes += bytes;
}
void OctreeSceneStats::traversed(const OctreeElement* element) {
void OctreeSceneStats::traversed(const OctreeElementPointer element) {
_traversed++;
if (element->isLeaf()) {
_leaves++;
@ -295,7 +296,7 @@ void OctreeSceneStats::traversed(const OctreeElement* element) {
}
}
void OctreeSceneStats::skippedDistance(const OctreeElement* element) {
void OctreeSceneStats::skippedDistance(const OctreeElementPointer element) {
_skippedDistance++;
if (element->isLeaf()) {
_leavesSkippedDistance++;
@ -304,7 +305,7 @@ void OctreeSceneStats::skippedDistance(const OctreeElement* element) {
}
}
void OctreeSceneStats::skippedOutOfView(const OctreeElement* element) {
void OctreeSceneStats::skippedOutOfView(const OctreeElementPointer element) {
_skippedOutOfView++;
if (element->isLeaf()) {
_leavesSkippedOutOfView++;
@ -313,7 +314,7 @@ void OctreeSceneStats::skippedOutOfView(const OctreeElement* element) {
}
}
void OctreeSceneStats::skippedWasInView(const OctreeElement* element) {
void OctreeSceneStats::skippedWasInView(const OctreeElementPointer element) {
_skippedWasInView++;
if (element->isLeaf()) {
_leavesSkippedWasInView++;
@ -322,7 +323,7 @@ void OctreeSceneStats::skippedWasInView(const OctreeElement* element) {
}
}
void OctreeSceneStats::skippedNoChange(const OctreeElement* element) {
void OctreeSceneStats::skippedNoChange(const OctreeElementPointer element) {
_skippedNoChange++;
if (element->isLeaf()) {
_leavesSkippedNoChange++;
@ -331,7 +332,7 @@ void OctreeSceneStats::skippedNoChange(const OctreeElement* element) {
}
}
void OctreeSceneStats::skippedOccluded(const OctreeElement* element) {
void OctreeSceneStats::skippedOccluded(const OctreeElementPointer element) {
_skippedOccluded++;
if (element->isLeaf()) {
_leavesSkippedOccluded++;
@ -340,7 +341,7 @@ void OctreeSceneStats::skippedOccluded(const OctreeElement* element) {
}
}
void OctreeSceneStats::colorSent(const OctreeElement* element) {
void OctreeSceneStats::colorSent(const OctreeElementPointer element) {
_colorSent++;
if (element->isLeaf()) {
_leavesColorSent++;
@ -349,7 +350,7 @@ void OctreeSceneStats::colorSent(const OctreeElement* element) {
}
}
void OctreeSceneStats::didntFit(const OctreeElement* element) {
void OctreeSceneStats::didntFit(const OctreeElementPointer element) {
_didntFit++;
if (element->isLeaf()) {
_leavesDidntFit++;

View file

@ -38,7 +38,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
@ -56,28 +56,28 @@ public:
void encodeStopped();
/// Track that a element was traversed as part of computation of a scene.
void traversed(const OctreeElement* element);
void traversed(const OctreeElementPointer element);
/// Track that a element was skipped as part of computation of a scene due to being beyond the LOD distance.
void skippedDistance(const OctreeElement* element);
void skippedDistance(const OctreeElementPointer element);
/// Track that a element was skipped as part of computation of a scene due to being out of view.
void skippedOutOfView(const OctreeElement* element);
void skippedOutOfView(const OctreeElementPointer element);
/// Track that a element was skipped as part of computation of a scene due to previously being in view while in delta sending
void skippedWasInView(const OctreeElement* element);
void skippedWasInView(const OctreeElementPointer element);
/// Track that a element was skipped as part of computation of a scene due to not having changed since last full scene sent
void skippedNoChange(const OctreeElement* element);
void skippedNoChange(const OctreeElementPointer element);
/// Track that a element was skipped as part of computation of a scene due to being occluded
void skippedOccluded(const OctreeElement* element);
void skippedOccluded(const OctreeElementPointer element);
/// Track that a element's color was was sent as part of computation of a scene
void colorSent(const OctreeElement* element);
void colorSent(const OctreeElementPointer element);
/// Track that a element was due to be sent, but didn't fit in the packet and was moved to next packet
void didntFit(const OctreeElement* element);
void didntFit(const OctreeElementPointer element);
/// Track that the color bitmask was was sent as part of computation of a scene
void colorBitsWritten();

View file

@ -31,12 +31,12 @@ 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) {
return true;
}
return tree->isLocked();
return true;
}
#else
bool entityTreeIsLocked() {

View file

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

View file

@ -30,7 +30,7 @@ public:
PhysicalEntitySimulation();
~PhysicalEntitySimulation();
void init(EntityTree* tree, PhysicsEngine* engine, EntityEditPacketSender* packetSender);
void init(EntityTreePointer tree, PhysicsEnginePointer engine, EntityEditPacketSender* packetSender);
virtual void addAction(EntityActionPointer action) override;
virtual void applyActionChanges() override;
@ -65,10 +65,13 @@ private:
SetOfMotionStates _physicalObjects; // MotionStates of entities in PhysicsEngine
PhysicsEngine* _physicsEngine = nullptr;
PhysicsEnginePointer _physicsEngine = nullptr;
EntityEditPacketSender* _entityPacketSender = nullptr;
uint32_t _lastStepSendPackets = 0;
};
typedef std::shared_ptr<PhysicalEntitySimulation> PhysicalEntitySimulationPointer;
#endif // hifi_PhysicalEntitySimulation_h

View file

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

View file

@ -44,8 +44,7 @@ typedef QVector<Collision> CollisionEvents;
class PhysicsEngine {
public:
// TODO: find a good way to make this a non-static method
static uint32_t getNumSubsteps();
uint32_t getNumSubsteps();
PhysicsEngine(const glm::vec3& offset);
~PhysicsEngine();
@ -129,6 +128,10 @@ private:
QHash<QUuid, EntityActionPointer> _objectActions;
btHashMap<btHashInt, int16_t> _collisionMasks;
uint32_t _numSubsteps;
};
typedef std::shared_ptr<PhysicsEngine> PhysicsEnginePointer;
#endif // hifi_PhysicsEngine_h

View file

@ -176,6 +176,14 @@ void AnimDebugDraw::removePoses(const std::string& key) {
_poses.erase(key);
}
void AnimDebugDraw::addPose(const std::string& key, const AnimPose& pose, const AnimPose& rootPose) {
_singlePoses[key] = SinglePoseInfo(pose, rootPose);
}
void AnimDebugDraw::removePose(const std::string& key) {
_singlePoses.erase(key);
}
static const uint32_t red = toRGBA(255, 0, 0, 255);
static const uint32_t green = toRGBA(0, 255, 0, 255);
static const uint32_t blue = toRGBA(0, 0, 255, 255);
@ -333,6 +341,7 @@ void AnimDebugDraw::update() {
const size_t VERTICES_PER_LINK = 8 * 2;
const float BONE_RADIUS = 0.01f; // 1 cm
const float POSE_RADIUS = 0.1f; // 10 cm
// figure out how many verts we will need.
int numVerts = 0;
@ -371,6 +380,8 @@ void AnimDebugDraw::update() {
}
}
numVerts += _singlePoses.size() * VERTICES_PER_BONE;
data._vertexBuffer->resize(sizeof(Vertex) * numVerts);
Vertex* verts = (Vertex*)data._vertexBuffer->editData();
Vertex* v = verts;
@ -475,6 +486,13 @@ void AnimDebugDraw::update() {
}
}
for (auto& iter : _singlePoses) {
AnimPose pose = std::get<0>(iter.second);
AnimPose rootPose = std::get<1>(iter.second);
const float radius = POSE_RADIUS / (pose.scale.x * rootPose.scale.x);
addBone(rootPose, pose, radius, v);
}
assert(numVerts == (v - verts));
data._indexBuffer->resize(sizeof(uint16_t) * numVerts);

View file

@ -27,15 +27,22 @@ public:
AnimDebugDraw();
~AnimDebugDraw();
// draw a skeleton bind pose
void addSkeleton(const std::string& key, AnimSkeleton::ConstPointer skeleton, const AnimPose& rootPose, const glm::vec4& color);
void removeSkeleton(const std::string& key);
// draw the interal poses for a specific animNode
void addAnimNode(const std::string& key, AnimNode::ConstPointer animNode, const AnimPose& rootPose, const glm::vec4& color);
void removeAnimNode(const std::string& key);
// draw a set of poses with a skeleton
void addPoses(const std::string& key, AnimSkeleton::ConstPointer skeleton, const AnimPoseVec& poses, const AnimPose& rootPose, const glm::vec4& color);
void removePoses(const std::string& key);
// draw a single pose
void addPose(const std::string& key, const AnimPose& rootPose, const AnimPose& pose);
void removePose(const std::string& key);
void update();
protected:
@ -48,10 +55,12 @@ protected:
typedef std::tuple<AnimSkeleton::ConstPointer, AnimPose, glm::vec4> SkeletonInfo;
typedef std::tuple<AnimNode::ConstPointer, AnimPose, glm::vec4> AnimNodeInfo;
typedef std::tuple<AnimSkeleton::ConstPointer, AnimPoseVec, AnimPose, glm::vec4> PosesInfo;
typedef std::tuple<AnimPose, AnimPose> SinglePoseInfo;
std::unordered_map<std::string, SkeletonInfo> _skeletons;
std::unordered_map<std::string, AnimNodeInfo> _animNodes;
std::unordered_map<std::string, PosesInfo> _poses;
std::unordered_map<std::string, SinglePoseInfo> _singlePoses;
// no copies
AnimDebugDraw(const AnimDebugDraw&) = delete;

View file

@ -68,7 +68,6 @@ void ScriptCache::scriptDownloaded() {
qCDebug(scriptengine) << "Done downloading script at:" << url.toString();
foreach(ScriptUser* user, scriptUsers) {
// FIXME - I sometimes get a crash deep below here inside of Qt while evaluating the script
user->scriptContentsAvailable(url, _scriptCache[url]);
}
} else {

View file

@ -261,20 +261,6 @@ bool ScriptEngine::setScriptContents(const QString& scriptContents, const QStrin
return true;
}
void ScriptEngine::callScriptMethod(QString methodName, QScriptValue script, QScriptValueList args) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this,
"callScriptMethod",
Q_ARG(QString, methodName),
Q_ARG(QScriptValue, script),
Q_ARG(QScriptValueList, args));
return;
}
//qDebug() << "About to call " << methodName << "() current thread : " << QThread::currentThread() << "engine thread : " << thread();
script.property(methodName).call(script, args);
}
void ScriptEngine::loadURL(const QUrl& scriptURL, bool reload) {
if (_isRunning) {
return;

View file

@ -65,8 +65,6 @@ public:
int numArguments = -1);
Q_INVOKABLE void setIsAvatar(bool isAvatar);
Q_INVOKABLE void callScriptMethod(QString methodName, QScriptValue script, QScriptValueList args);
bool isAvatar() const { return _isAvatar; }
void setAvatarData(AvatarData* avatarData, const QString& objectName);

View file

@ -26,8 +26,7 @@ static int quatMetaTypeId = qRegisterMetaType<glm::quat>();
static int xColorMetaTypeId = qRegisterMetaType<xColor>();
static int pickRayMetaTypeId = qRegisterMetaType<PickRay>();
static int collisionMetaTypeId = qRegisterMetaType<Collision>();
static int qMapURLStringMetaTypeId = qRegisterMetaType<QMap<QUrl, QString>>();
static int qScriptValueListMetaTypeId = qRegisterMetaType<QScriptValueList>("QScriptValueList");
static int qMapURLStringMetaTypeId = qRegisterMetaType<QMap<QUrl,QString>>();
void registerMetaTypes(QScriptEngine* engine) {
qScriptRegisterMetaType(engine, vec4toScriptValue, vec4FromScriptValue);

View file

@ -12,6 +12,7 @@
#ifndef hifi_SharedUtil_h
#define hifi_SharedUtil_h
#include <memory>
#include <math.h>
#include <stdint.h>
@ -123,11 +124,17 @@ private:
bool isBetween(int64_t value, int64_t max, int64_t min);
/// \return bool is the float NaN
/// \return bool is the float NaN
bool isNaN(float value);
QString formatUsecTime(float usecs, int prec = 3);
QString formatSecondsElapsed(float seconds);
bool similarStrings(const QString& stringA, const QString& stringB);
template <typename T>
uint qHash(const std::shared_ptr<T>& ptr, uint seed = 0)
{
return qHash(ptr.get(), seed);
}
#endif // hifi_SharedUtil_h

View file

@ -22,6 +22,11 @@
"jointName": "LeftHand",
"positionVar": "leftHandPosition",
"rotationVar": "leftHandRotation"
},
{
"jointName": "Head",
"positionVar": "headPosition",
"rotationVar": "headRotation"
}
]
},