Merge remote-tracking branch 'upstream/master' into plugins

This commit is contained in:
Brad Davis 2015-05-26 18:36:12 -07:00
commit dd87707c7b
97 changed files with 913 additions and 575 deletions

View file

@ -262,7 +262,6 @@ $(document).ready(function(){
$('#' + Settings.FORM_ID).on('click', '#' + Settings.CONNECT_ACCOUNT_BTN_ID, function(e){
$(this).blur();
prepareAccessTokenPrompt();
e.preventDefault();
});
var panelsSource = $('#panels-template').html()

View file

@ -682,6 +682,10 @@ Application::~Application() {
getActiveDisplayPlugin()->deactivate();
// remove avatars from physics engine
DependencyManager::get<AvatarManager>()->clearOtherAvatars();
_physicsEngine.deleteObjects(DependencyManager::get<AvatarManager>()->getObjectsToDelete());
DependencyManager::destroy<OffscreenUi>();
DependencyManager::destroy<AvatarManager>();
DependencyManager::destroy<AnimationCache>();
@ -1908,7 +1912,7 @@ void Application::toggleFaceTrackerMute() {
}
bool Application::exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs) {
QVector<EntityItem*> entities;
QVector<EntityItemPointer> entities;
auto entityTree = _entities.getTree();
EntityTree exportTree;
@ -1949,7 +1953,7 @@ bool Application::exportEntities(const QString& filename, const QVector<EntityIt
}
bool Application::exportEntities(const QString& filename, float x, float y, float z, float scale) {
QVector<EntityItem*> entities;
QVector<EntityItemPointer> entities;
_entities.getTree()->findEntities(AACube(glm::vec3(x, y, z), scale), entities);
if (entities.size() > 0) {
@ -2091,7 +2095,7 @@ void Application::init() {
_physicsEngine.init();
EntityTree* tree = _entities.getTree();
_entitySimulation.init(tree, &_physicsEngine, &_shapeManager, &_entityEditSender);
_entitySimulation.init(tree, &_physicsEngine, &_entityEditSender);
tree->setSimulation(&_entitySimulation);
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
@ -2411,12 +2415,21 @@ void Application::update(float deltaTime) {
_physicsEngine.changeObjects(_entitySimulation.getObjectsToChange());
_entitySimulation.unlock();
AvatarManager* avatarManager = DependencyManager::get<AvatarManager>().data();
_physicsEngine.deleteObjects(avatarManager->getObjectsToDelete());
_physicsEngine.addObjects(avatarManager->getObjectsToAdd());
_physicsEngine.changeObjects(avatarManager->getObjectsToChange());
_physicsEngine.stepSimulation();
if (_physicsEngine.hasOutgoingChanges()) {
_entitySimulation.lock();
_entitySimulation.handleOutgoingChanges(_physicsEngine.getOutgoingChanges(), _physicsEngine.getSessionID());
_entitySimulation.unlock();
avatarManager->handleOutgoingChanges(_physicsEngine.getOutgoingChanges());
avatarManager->handleCollisionEvents(_physicsEngine.getCollisionEvents());
_physicsEngine.dumpStatsIfNecessary();
}
}

View file

@ -38,6 +38,7 @@
#include "Application.h"
#include "Avatar.h"
#include "AvatarManager.h"
#include "AvatarMotionState.h"
#include "Hand.h"
#include "Head.h"
#include "Menu.h"
@ -972,6 +973,9 @@ int Avatar::parseDataAtOffset(const QByteArray& packet, int offset) {
const float MOVE_DISTANCE_THRESHOLD = 0.001f;
_moving = glm::distance(oldPosition, _position) > MOVE_DISTANCE_THRESHOLD;
if (_moving && _motionState) {
_motionState->addDirtyFlags(EntityItem::DIRTY_POSITION);
}
return bytesRead;
}
@ -1087,20 +1091,15 @@ void Avatar::setShowDisplayName(bool showDisplayName) {
}
// virtual
void Avatar::rebuildSkeletonBody() {
/* TODO: implement this and remove override from MyAvatar (when we have AvatarMotionStates working)
if (_motionState) {
// compute localAABox
const CapsuleShape& capsule = _skeletonModel.getBoundingShape();
float radius = capsule.getRadius();
float height = 2.0f * (capsule.getHalfHeight() + radius);
glm::vec3 corner(-radius, -0.5f * height, -radius);
corner += _skeletonModel.getBoundingShapeOffset();
glm::vec3 scale(2.0f * radius, height, 2.0f * radius);
//_characterController.setLocalBoundingBox(corner, scale);
_motionState->setBoundingBox(corner, scale);
}
*/
// virtual
void Avatar::computeShapeInfo(ShapeInfo& shapeInfo) {
const CapsuleShape& capsule = _skeletonModel.getBoundingShape();
shapeInfo.setCapsuleY(capsule.getRadius(), capsule.getHalfHeight());
shapeInfo.setOffset(_skeletonModel.getBoundingShapeOffset());
}
// virtual
void Avatar::rebuildSkeletonBody() {
DependencyManager::get<AvatarManager>()->updateAvatarPhysicsShape(getSessionUUID());
}

View file

@ -18,11 +18,11 @@
#include <QtCore/QUuid>
#include <AvatarData.h>
#include <ShapeInfo.h>
#include "Hand.h"
#include "Head.h"
#include "InterfaceConfig.h"
#include "Recorder.h"
#include "SkeletonModel.h"
#include "world.h"
@ -55,6 +55,7 @@ enum ScreenTintLayer {
NUM_SCREEN_TINT_LAYERS
};
class AvatarMotionState;
class Texture;
class Avatar : public AvatarData {
@ -146,9 +147,9 @@ public:
Q_INVOKABLE glm::vec3 getNeckPosition() const;
Q_INVOKABLE glm::vec3 getAcceleration() const { return _acceleration; }
Q_INVOKABLE glm::vec3 getAngularVelocity() const { return _angularVelocity; }
Q_INVOKABLE glm::vec3 getAngularAcceleration() const { return _angularAcceleration; }
Q_INVOKABLE const glm::vec3& getAcceleration() const { return _acceleration; }
Q_INVOKABLE const glm::vec3& getAngularVelocity() const { return _angularVelocity; }
Q_INVOKABLE const glm::vec3& getAngularAcceleration() const { return _angularAcceleration; }
/// Scales a world space position vector relative to the avatar position and scale
@ -164,6 +165,10 @@ public:
virtual void rebuildSkeletonBody();
virtual void computeShapeInfo(ShapeInfo& shapeInfo);
friend class AvatarManager;
signals:
void collisionWithAvatar(const QUuid& myUUID, const QUuid& theirUUID, const CollisionInfo& collision);
@ -231,7 +236,7 @@ private:
int _voiceSphereID;
//AvatarMotionState* _motionState = nullptr;
AvatarMotionState* _motionState = nullptr;
};
#endif // hifi_Avatar_h

View file

@ -92,22 +92,18 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
// simulate avatars
AvatarHash::iterator avatarIterator = _avatarHash.begin();
while (avatarIterator != _avatarHash.end()) {
AvatarSharedPointer sharedAvatar = avatarIterator.value();
Avatar* avatar = reinterpret_cast<Avatar*>(sharedAvatar.data());
Avatar* avatar = reinterpret_cast<Avatar*>(avatarIterator.value().data());
if (sharedAvatar == _myAvatar || !avatar->isInitialized()) {
if (avatar == _myAvatar || !avatar->isInitialized()) {
// DO NOT update _myAvatar! Its update has already been done earlier in the main loop.
// DO NOT update uninitialized Avatars
// DO NOT update or fade out uninitialized Avatars
++avatarIterator;
continue;
}
if (!shouldKillAvatar(sharedAvatar)) {
// this avatar's mixer is still around, go ahead and simulate it
} else if (avatar->shouldDie()) {
_avatarFades.push_back(avatarIterator.value());
avatarIterator = _avatarHash.erase(avatarIterator);
} else {
avatar->simulate(deltaTime);
++avatarIterator;
} else {
// the mixer that owned this avatar is gone, give it to the vector of fades and kill it
avatarIterator = erase(avatarIterator);
}
}
@ -175,24 +171,52 @@ AvatarSharedPointer AvatarManager::newSharedAvatar() {
return AvatarSharedPointer(new Avatar());
}
AvatarHash::iterator AvatarManager::erase(const AvatarHash::iterator& iterator) {
if (iterator.key() != MY_AVATAR_KEY) {
if (reinterpret_cast<Avatar*>(iterator.value().data())->isInitialized()) {
_avatarFades.push_back(iterator.value());
// virtual
AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
AvatarSharedPointer avatar = AvatarHashMap::addAvatar(sessionUUID, mixerWeakPointer);
return avatar;
}
// protected
void AvatarManager::removeAvatarMotionState(Avatar* avatar) {
AvatarMotionState* motionState= avatar->_motionState;
if (motionState) {
// clean up physics stuff
motionState->clearObjectBackPointer();
avatar->_motionState = nullptr;
_avatarMotionStates.remove(motionState);
_motionStatesToAdd.remove(motionState);
_motionStatesToDelete.push_back(motionState);
}
}
// virtual
void AvatarManager::removeAvatar(const QUuid& sessionUUID) {
AvatarHash::iterator avatarIterator = _avatarHash.find(sessionUUID);
if (avatarIterator != _avatarHash.end()) {
Avatar* avatar = reinterpret_cast<Avatar*>(avatarIterator.value().data());
if (avatar != _myAvatar && avatar->isInitialized()) {
removeAvatarMotionState(avatar);
_avatarFades.push_back(avatarIterator.value());
_avatarHash.erase(avatarIterator);
}
return AvatarHashMap::erase(iterator);
} else {
// never remove _myAvatar from the list
AvatarHash::iterator returnIterator = iterator;
return ++returnIterator;
}
}
void AvatarManager::clearOtherAvatars() {
// clear any avatars that came from an avatar-mixer
AvatarHash::iterator removeAvatar = _avatarHash.begin();
while (removeAvatar != _avatarHash.end()) {
removeAvatar = erase(removeAvatar);
AvatarHash::iterator avatarIterator = _avatarHash.begin();
while (avatarIterator != _avatarHash.end()) {
Avatar* avatar = reinterpret_cast<Avatar*>(avatarIterator.value().data());
if (avatar == _myAvatar || !avatar->isInitialized()) {
// don't remove myAvatar or uninitialized avatars from the list
++avatarIterator;
} else {
removeAvatarMotionState(avatar);
_avatarFades.push_back(avatarIterator.value());
avatarIterator = _avatarHash.erase(avatarIterator);
}
}
_myAvatar->clearLookAtTargetAvatar();
}
@ -215,3 +239,57 @@ QVector<AvatarManager::LocalLight> AvatarManager::getLocalLights() const {
return _localLights;
}
VectorOfMotionStates& AvatarManager::getObjectsToDelete() {
_tempMotionStates.clear();
_tempMotionStates.swap(_motionStatesToDelete);
return _tempMotionStates;
}
VectorOfMotionStates& AvatarManager::getObjectsToAdd() {
_tempMotionStates.clear();
for (auto motionState : _motionStatesToAdd) {
_tempMotionStates.push_back(motionState);
}
_motionStatesToAdd.clear();
return _tempMotionStates;
}
VectorOfMotionStates& AvatarManager::getObjectsToChange() {
_tempMotionStates.clear();
for (auto state : _avatarMotionStates) {
if (state->_dirtyFlags > 0) {
_tempMotionStates.push_back(state);
}
}
return _tempMotionStates;
}
void AvatarManager::handleOutgoingChanges(VectorOfMotionStates& motionStates) {
// TODO: extract the MyAvatar results once we use a MotionState for it.
}
void AvatarManager::handleCollisionEvents(CollisionEvents& collisionEvents) {
// TODO: expose avatar collision events to JS
}
void AvatarManager::updateAvatarPhysicsShape(const QUuid& id) {
AvatarHash::iterator avatarItr = _avatarHash.find(id);
if (avatarItr != _avatarHash.end()) {
Avatar* avatar = static_cast<Avatar*>(avatarItr.value().data());
AvatarMotionState* motionState = avatar->_motionState;
if (motionState) {
motionState->addDirtyFlags(EntityItem::DIRTY_SHAPE);
} else {
ShapeInfo shapeInfo;
avatar->computeShapeInfo(shapeInfo);
btCollisionShape* shape = ObjectMotionState::getShapeManager()->getShape(shapeInfo);
if (shape) {
AvatarMotionState* motionState = new AvatarMotionState(avatar, shape);
avatar->_motionState = motionState;
_motionStatesToAdd.insert(motionState);
_avatarMotionStates.insert(motionState);
}
}
}
}

View file

@ -17,8 +17,10 @@
#include <QtCore/QSharedPointer>
#include <AvatarHashMap.h>
#include <PhysicsEngine.h>
#include "Avatar.h"
#include "AvatarMotionState.h"
class MyAvatar;
@ -51,6 +53,14 @@ public:
Q_INVOKABLE void setLocalLights(const QVector<AvatarManager::LocalLight>& localLights);
Q_INVOKABLE QVector<AvatarManager::LocalLight> getLocalLights() const;
VectorOfMotionStates& getObjectsToDelete();
VectorOfMotionStates& getObjectsToAdd();
VectorOfMotionStates& getObjectsToChange();
void handleOutgoingChanges(VectorOfMotionStates& motionStates);
void handleCollisionEvents(CollisionEvents& collisionEvents);
void updateAvatarPhysicsShape(const QUuid& id);
public slots:
void setShouldShowReceiveStats(bool shouldShowReceiveStats) { _shouldShowReceiveStats = shouldShowReceiveStats; }
@ -62,10 +72,11 @@ private:
void simulateAvatarFades(float deltaTime);
void renderAvatarFades(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode);
AvatarSharedPointer newSharedAvatar();
// virtual overrides
AvatarHash::iterator erase(const AvatarHash::iterator& iterator);
virtual AvatarSharedPointer newSharedAvatar();
virtual AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer);
void removeAvatarMotionState(Avatar* avatar);
virtual void removeAvatar(const QUuid& sessionUUID);
QVector<AvatarSharedPointer> _avatarFades;
QSharedPointer<MyAvatar> _myAvatar;
@ -74,6 +85,11 @@ private:
QVector<AvatarManager::LocalLight> _localLights;
bool _shouldShowReceiveStats = false;
SetOfAvatarMotionStates _avatarMotionStates;
SetOfMotionStates _motionStatesToAdd;
VectorOfMotionStates _motionStatesToDelete;
VectorOfMotionStates _tempMotionStates;
};
Q_DECLARE_METATYPE(AvatarManager::LocalLight)

View file

@ -0,0 +1,160 @@
//
// AvatarMotionState.cpp
// interface/src/avatar/
//
// Created by Andrew Meadows 2015.05.14
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <PhysicsHelpers.h>
#include "Avatar.h"
#include "AvatarMotionState.h"
#include "BulletUtil.h"
AvatarMotionState::AvatarMotionState(Avatar* avatar, btCollisionShape* shape) : ObjectMotionState(shape), _avatar(avatar) {
assert(_avatar);
if (_shape) {
_mass = 100.0f; // HACK
}
}
AvatarMotionState::~AvatarMotionState() {
_avatar = nullptr;
}
// virtual
uint32_t AvatarMotionState::getAndClearIncomingDirtyFlags() {
uint32_t dirtyFlags = 0;
if (_body && _avatar) {
dirtyFlags = _dirtyFlags;
_dirtyFlags = 0;
}
return dirtyFlags;
}
MotionType AvatarMotionState::computeObjectMotionType() const {
// TODO?: support non-DYNAMIC motion for avatars? (e.g. when sitting)
return MOTION_TYPE_DYNAMIC;
}
// virtual and protected
btCollisionShape* AvatarMotionState::computeNewShape() {
if (_avatar) {
ShapeInfo shapeInfo;
_avatar->computeShapeInfo(shapeInfo);
return getShapeManager()->getShape(shapeInfo);
}
return nullptr;
}
// virtual
bool AvatarMotionState::isMoving() const {
return false;
}
// virtual
void AvatarMotionState::getWorldTransform(btTransform& worldTrans) const {
if (!_avatar) {
return;
}
worldTrans.setOrigin(glmToBullet(getObjectPosition()));
worldTrans.setRotation(glmToBullet(getObjectRotation()));
if (_body) {
_body->setLinearVelocity(glmToBullet(getObjectLinearVelocity()));
_body->setAngularVelocity(glmToBullet(getObjectLinearVelocity()));
}
}
// virtual
void AvatarMotionState::setWorldTransform(const btTransform& worldTrans) {
if (!_avatar) {
return;
}
// HACK: The PhysicsEngine does not actually move OTHER avatars -- instead it slaves their local RigidBody to the transform
// as specified by a remote simulation. However, to give the remote simulation time to respond to our own objects we tie
// the other avatar's body to its true position with a simple spring. This is a HACK that will have to be improved later.
const float SPRING_TIMESCALE = 0.5f;
float tau = PHYSICS_ENGINE_FIXED_SUBSTEP / SPRING_TIMESCALE;
btVector3 currentPosition = worldTrans.getOrigin();
btVector3 targetPosition = glmToBullet(getObjectPosition());
btTransform newTransform;
newTransform.setOrigin((1.0f - tau) * currentPosition + tau * targetPosition);
newTransform.setRotation(glmToBullet(getObjectRotation()));
_body->setWorldTransform(newTransform);
_body->setLinearVelocity(glmToBullet(getObjectLinearVelocity()));
_body->setAngularVelocity(glmToBullet(getObjectLinearVelocity()));
}
// These pure virtual methods must be implemented for each MotionState type
// and make it possible to implement more complicated methods in this base class.
// virtual
float AvatarMotionState::getObjectRestitution() const {
return 0.5f;
}
// virtual
float AvatarMotionState::getObjectFriction() const {
return 0.5f;
}
// virtual
float AvatarMotionState::getObjectLinearDamping() const {
return 0.5f;
}
// virtual
float AvatarMotionState::getObjectAngularDamping() const {
return 0.5f;
}
// virtual
glm::vec3 AvatarMotionState::getObjectPosition() const {
return _avatar->getPosition();
}
// virtual
glm::quat AvatarMotionState::getObjectRotation() const {
return _avatar->getOrientation();
}
// virtual
const glm::vec3& AvatarMotionState::getObjectLinearVelocity() const {
return _avatar->getVelocity();
}
// virtual
const glm::vec3& AvatarMotionState::getObjectAngularVelocity() const {
return _avatar->getAngularVelocity();
}
// virtual
const glm::vec3& AvatarMotionState::getObjectGravity() const {
return _avatar->getAcceleration();
}
// virtual
const QUuid& AvatarMotionState::getObjectID() const {
return _avatar->getSessionUUID();
}
// virtual
QUuid AvatarMotionState::getSimulatorID() const {
return _avatar->getSessionUUID();
}
// virtual
void AvatarMotionState::bump() {
}
// virtual
void AvatarMotionState::clearObjectBackPointer() {
ObjectMotionState::clearObjectBackPointer();
_avatar = nullptr;
}

View file

@ -0,0 +1,75 @@
//
// AvatarMotionState.h
// interface/src/avatar/
//
// Created by Andrew Meadows 2015.05.14
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_AvatarMotionState_h
#define hifi_AvatarMotionState_h
#include <QSet>
#include <ObjectMotionState.h>
class Avatar;
class AvatarMotionState : public ObjectMotionState {
public:
AvatarMotionState(Avatar* avatar, btCollisionShape* shape);
~AvatarMotionState();
virtual MotionType getMotionType() const { return _motionType; }
virtual uint32_t getAndClearIncomingDirtyFlags();
virtual MotionType computeObjectMotionType() const;
virtual bool isMoving() const;
// this relays incoming position/rotation to the RigidBody
virtual void getWorldTransform(btTransform& worldTrans) const;
// this relays outgoing position/rotation to the EntityItem
virtual void setWorldTransform(const btTransform& worldTrans);
// These pure virtual methods must be implemented for each MotionState type
// and make it possible to implement more complicated methods in this base class.
virtual float getObjectRestitution() const;
virtual float getObjectFriction() const;
virtual float getObjectLinearDamping() const;
virtual float getObjectAngularDamping() const;
virtual glm::vec3 getObjectPosition() const;
virtual glm::quat getObjectRotation() const;
virtual const glm::vec3& getObjectLinearVelocity() const;
virtual const glm::vec3& getObjectAngularVelocity() const;
virtual const glm::vec3& getObjectGravity() const;
virtual const QUuid& getObjectID() const;
virtual QUuid getSimulatorID() const;
virtual void bump();
void setBoundingBox(const glm::vec3& corner, const glm::vec3& diagonal);
void addDirtyFlags(uint32_t flags) { _dirtyFlags |= flags; }
friend class AvatarManager;
protected:
virtual btCollisionShape* computeNewShape();
virtual void clearObjectBackPointer();
Avatar* _avatar;
uint32_t _dirtyFlags;
};
typedef QSet<AvatarMotionState*> SetOfAvatarMotionStates;
#endif // hifi_AvatarMotionState_h

View file

@ -30,7 +30,7 @@ ModelReferential::ModelReferential(Referential* referential, EntityTree* tree, A
return;
}
const EntityItem* item = _tree->findEntityByID(_entityID);
EntityItemPointer item = _tree->findEntityByID(_entityID);
if (item != NULL) {
_lastRefDimension = item->getDimensions();
_refRotation = item->getRotation();
@ -44,7 +44,7 @@ ModelReferential::ModelReferential(const QUuid& entityID, EntityTree* tree, Avat
_entityID(entityID),
_tree(tree)
{
const EntityItem* item = _tree->findEntityByID(_entityID);
EntityItemPointer item = _tree->findEntityByID(_entityID);
if (!isValid() || item == NULL) {
qCDebug(interfaceapp) << "ModelReferential::constructor(): Not Valid";
_isValid = false;
@ -61,7 +61,7 @@ ModelReferential::ModelReferential(const QUuid& entityID, EntityTree* tree, Avat
}
void ModelReferential::update() {
const EntityItem* item = _tree->findEntityByID(_entityID);
EntityItemPointer item = _tree->findEntityByID(_entityID);
if (!isValid() || item == NULL || _avatar == NULL) {
return;
}
@ -105,7 +105,7 @@ JointReferential::JointReferential(Referential* referential, EntityTree* tree, A
return;
}
const EntityItem* item = _tree->findEntityByID(_entityID);
EntityItemPointer item = _tree->findEntityByID(_entityID);
const Model* model = getModel(item);
if (!isValid() || model == NULL || _jointIndex >= (uint32_t)(model->getJointStateCount())) {
_lastRefDimension = item->getDimensions();
@ -120,7 +120,7 @@ JointReferential::JointReferential(uint32_t jointIndex, const QUuid& entityID, E
_jointIndex(jointIndex)
{
_type = JOINT;
const EntityItem* item = _tree->findEntityByID(_entityID);
EntityItemPointer item = _tree->findEntityByID(_entityID);
const Model* model = getModel(item);
if (!isValid() || model == NULL || _jointIndex >= (uint32_t)(model->getJointStateCount())) {
qCDebug(interfaceapp) << "JointReferential::constructor(): Not Valid";
@ -139,7 +139,7 @@ JointReferential::JointReferential(uint32_t jointIndex, const QUuid& entityID, E
}
void JointReferential::update() {
const EntityItem* item = _tree->findEntityByID(_entityID);
EntityItemPointer item = _tree->findEntityByID(_entityID);
const Model* model = getModel(item);
if (!isValid() || model == NULL || _jointIndex >= (uint32_t)(model->getJointStateCount())) {
return;
@ -163,7 +163,7 @@ void JointReferential::update() {
}
}
const Model* JointReferential::getModel(const EntityItem* item) {
const Model* JointReferential::getModel(EntityItemPointer item) {
EntityItemFBXService* fbxService = _tree->getFBXService();
if (item != NULL && fbxService != NULL) {
return fbxService->getModelForEntityItem(item);

View file

@ -38,7 +38,7 @@ public:
virtual void update();
protected:
const Model* getModel(const EntityItem* item);
const Model* getModel(EntityItemPointer item);
virtual int packExtraData(unsigned char* destinationBuffer) const;
virtual int unpackExtraData(const unsigned char* sourceBuffer, int size);

View file

@ -41,6 +41,7 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent) :
_headClipDistance(DEFAULT_NEAR_CLIP)
{
assert(_owningAvatar);
_enableShapes = true;
}
SkeletonModel::~SkeletonModel() {

View file

@ -11,8 +11,6 @@
#include <GlowEffect.h>
#include "../../Menu.h"
#include "ModelOverlay.h"
ModelOverlay::ModelOverlay()

View file

@ -69,6 +69,7 @@ const quint32 AVATAR_MOTION_DEFAULTS =
const quint32 AVATAR_MOTION_SCRIPTABLE_BITS =
AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED;
const qint64 AVATAR_SILENCE_THRESHOLD_USECS = 5 * USECS_PER_SECOND;
// Bitset of state flags - we store the key state, hand state, faceshift, chat circling, and existance of
// referential data in this bit set. The hand state is an octal, but is split into two sections to maintain
@ -290,7 +291,6 @@ public:
QString getSkeletonModelURLFromScript() const { return _skeletonModelURL.toString(); }
void setSkeletonModelURLFromScript(const QString& skeletonModelString) { setSkeletonModelURL(QUrl(skeletonModelString)); }
Node* getOwningAvatarMixer() { return _owningAvatarMixer.data(); }
void setOwningAvatarMixer(const QWeakPointer<Node>& owningAvatarMixer) { _owningAvatarMixer = owningAvatarMixer; }
const AABox& getLocalAABox() const { return _localAABox; }
@ -301,8 +301,10 @@ public:
int getReceiveRate() const;
void setVelocity(const glm::vec3 velocity) { _velocity = velocity; }
Q_INVOKABLE glm::vec3 getVelocity() const { return _velocity; }
glm::vec3 getTargetVelocity() const { return _targetVelocity; }
Q_INVOKABLE const glm::vec3& getVelocity() const { return _velocity; }
const glm::vec3& getTargetVelocity() const { return _targetVelocity; }
bool shouldDie() const { return _owningAvatarMixer.isNull() || getUsecsSinceLastUpdate() > AVATAR_SILENCE_THRESHOLD_USECS; }
public slots:
void sendAvatarDataPacket();

View file

@ -20,19 +20,6 @@ AvatarHashMap::AvatarHashMap() {
connect(DependencyManager::get<NodeList>().data(), &NodeList::uuidChanged, this, &AvatarHashMap::sessionUUIDChanged);
}
AvatarHash::iterator AvatarHashMap::erase(const AvatarHash::iterator& iterator) {
qCDebug(avatars) << "Removing Avatar with UUID" << iterator.key() << "from AvatarHashMap.";
return _avatarHash.erase(iterator);
}
const qint64 AVATAR_SILENCE_THRESHOLD_USECS = 5 * USECS_PER_SECOND;
bool AvatarHashMap::shouldKillAvatar(const AvatarSharedPointer& sharedAvatar) {
return (sharedAvatar->getOwningAvatarMixer() == NULL
|| sharedAvatar->getUsecsSinceLastUpdate() > AVATAR_SILENCE_THRESHOLD_USECS);
}
void AvatarHashMap::processAvatarMixerDatagram(const QByteArray& datagram, const QWeakPointer<Node>& mixerWeakPointer) {
switch (packetTypeForPacket(datagram)) {
case PacketTypeBulkAvatarData:
@ -52,10 +39,6 @@ void AvatarHashMap::processAvatarMixerDatagram(const QByteArray& datagram, const
}
}
bool AvatarHashMap::containsAvatarWithDisplayName(const QString& displayName) {
return !avatarWithDisplayName(displayName).isNull();
}
bool AvatarHashMap::isAvatarInRange(const glm::vec3& position, const float range) {
foreach(const AvatarSharedPointer& sharedAvatar, _avatarHash) {
glm::vec3 avatarPosition = sharedAvatar->getPosition();
@ -67,45 +50,19 @@ bool AvatarHashMap::isAvatarInRange(const glm::vec3& position, const float range
return false;
}
AvatarWeakPointer AvatarHashMap::avatarWithDisplayName(const QString& displayName) {
foreach(const AvatarSharedPointer& sharedAvatar, _avatarHash) {
if (sharedAvatar->getDisplayName() == displayName) {
// this is a match
// check if this avatar should still be around
if (!shouldKillAvatar(sharedAvatar)) {
// we have a match, return the AvatarData
return sharedAvatar;
} else {
// we should remove this avatar, but we might not be on a thread that is allowed
// so we just return NULL to the caller
return AvatarWeakPointer();
}
}
}
return AvatarWeakPointer();
}
AvatarSharedPointer AvatarHashMap::newSharedAvatar() {
return AvatarSharedPointer(new AvatarData());
}
AvatarSharedPointer AvatarHashMap::matchingOrNewAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
AvatarSharedPointer matchingAvatar = _avatarHash.value(sessionUUID);
if (!matchingAvatar) {
// insert the new avatar into our hash
matchingAvatar = newSharedAvatar();
qCDebug(avatars) << "Adding avatar with sessionUUID " << sessionUUID << "to AvatarHashMap.";
matchingAvatar->setSessionUUID(sessionUUID);
matchingAvatar->setOwningAvatarMixer(mixerWeakPointer);
_avatarHash.insert(sessionUUID, matchingAvatar);
}
return matchingAvatar;
AvatarSharedPointer AvatarHashMap::addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
qCDebug(avatars) << "Adding avatar with sessionUUID " << sessionUUID << "to AvatarHashMap.";
AvatarSharedPointer avatar = newSharedAvatar();
avatar->setSessionUUID(sessionUUID);
avatar->setOwningAvatarMixer(mixerWeakPointer);
_avatarHash.insert(sessionUUID, avatar);
return avatar;
}
void AvatarHashMap::processAvatarDataPacket(const QByteArray &datagram, const QWeakPointer<Node> &mixerWeakPointer) {
@ -118,10 +75,13 @@ void AvatarHashMap::processAvatarDataPacket(const QByteArray &datagram, const QW
bytesRead += NUM_BYTES_RFC4122_UUID;
if (sessionUUID != _lastOwnerSessionUUID) {
AvatarSharedPointer matchingAvatarData = matchingOrNewAvatar(sessionUUID, mixerWeakPointer);
AvatarSharedPointer avatar = _avatarHash.value(sessionUUID);
if (!avatar) {
avatar = addAvatar(sessionUUID, mixerWeakPointer);
}
// have the matching (or new) avatar parse the data from the packet
bytesRead += matchingAvatarData->parseDataAtOffset(datagram, bytesRead);
bytesRead += avatar->parseDataAtOffset(datagram, bytesRead);
} else {
// create a dummy AvatarData class to throw this data on the ground
AvatarData dummyData;
@ -145,24 +105,24 @@ void AvatarHashMap::processAvatarIdentityPacket(const QByteArray &packet, const
identityStream >> sessionUUID >> faceMeshURL >> skeletonURL >> attachmentData >> displayName;
// mesh URL for a UUID, find avatar in our list
AvatarSharedPointer matchingAvatar = matchingOrNewAvatar(sessionUUID, mixerWeakPointer);
if (matchingAvatar) {
if (matchingAvatar->getFaceModelURL() != faceMeshURL) {
matchingAvatar->setFaceModelURL(faceMeshURL);
}
if (matchingAvatar->getSkeletonModelURL() != skeletonURL) {
matchingAvatar->setSkeletonModelURL(skeletonURL);
}
if (matchingAvatar->getAttachmentData() != attachmentData) {
matchingAvatar->setAttachmentData(attachmentData);
}
if (matchingAvatar->getDisplayName() != displayName) {
matchingAvatar->setDisplayName(displayName);
}
AvatarSharedPointer avatar = _avatarHash.value(sessionUUID);
if (!avatar) {
avatar = addAvatar(sessionUUID, mixerWeakPointer);
}
if (avatar->getFaceModelURL() != faceMeshURL) {
avatar->setFaceModelURL(faceMeshURL);
}
if (avatar->getSkeletonModelURL() != skeletonURL) {
avatar->setSkeletonModelURL(skeletonURL);
}
if (avatar->getAttachmentData() != attachmentData) {
avatar->setAttachmentData(attachmentData);
}
if (avatar->getDisplayName() != displayName) {
avatar->setDisplayName(displayName);
}
}
}
@ -171,24 +131,25 @@ void AvatarHashMap::processAvatarBillboardPacket(const QByteArray& packet, const
int headerSize = numBytesForPacketHeader(packet);
QUuid sessionUUID = QUuid::fromRfc4122(QByteArray::fromRawData(packet.constData() + headerSize, NUM_BYTES_RFC4122_UUID));
AvatarSharedPointer matchingAvatar = matchingOrNewAvatar(sessionUUID, mixerWeakPointer);
if (matchingAvatar) {
QByteArray billboard = packet.mid(headerSize + NUM_BYTES_RFC4122_UUID);
if (matchingAvatar->getBillboard() != billboard) {
matchingAvatar->setBillboard(billboard);
}
AvatarSharedPointer avatar = _avatarHash.value(sessionUUID);
if (!avatar) {
avatar = addAvatar(sessionUUID, mixerWeakPointer);
}
QByteArray billboard = packet.mid(headerSize + NUM_BYTES_RFC4122_UUID);
if (avatar->getBillboard() != billboard) {
avatar->setBillboard(billboard);
}
}
void AvatarHashMap::processKillAvatar(const QByteArray& datagram) {
// read the node id
QUuid sessionUUID = QUuid::fromRfc4122(datagram.mid(numBytesForPacketHeader(datagram), NUM_BYTES_RFC4122_UUID));
// remove the avatar with that UUID from our hash, if it exists
AvatarHash::iterator matchedAvatar = _avatarHash.find(sessionUUID);
if (matchedAvatar != _avatarHash.end()) {
erase(matchedAvatar);
}
removeAvatar(sessionUUID);
}
void AvatarHashMap::removeAvatar(const QUuid& sessionUUID) {
_avatarHash.remove(sessionUUID);
}
void AvatarHashMap::sessionUUIDChanged(const QUuid& sessionUUID, const QUuid& oldUUID) {

View file

@ -36,28 +36,26 @@ public:
public slots:
void processAvatarMixerDatagram(const QByteArray& datagram, const QWeakPointer<Node>& mixerWeakPointer);
bool containsAvatarWithDisplayName(const QString& displayName);
bool isAvatarInRange(const glm::vec3 & position, const float range);
AvatarWeakPointer avatarWithDisplayName(const QString& displayname);
private slots:
void sessionUUIDChanged(const QUuid& sessionUUID, const QUuid& oldUUID);
protected:
AvatarHashMap();
virtual AvatarHash::iterator erase(const AvatarHash::iterator& iterator);
bool shouldKillAvatar(const AvatarSharedPointer& sharedAvatar);
virtual AvatarSharedPointer newSharedAvatar();
AvatarSharedPointer matchingOrNewAvatar(const QUuid& nodeUUID, const QWeakPointer<Node>& mixerWeakPointer);
virtual AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer);
virtual void removeAvatar(const QUuid& sessionUUID);
AvatarHash _avatarHash;
private:
void processAvatarDataPacket(const QByteArray& packet, const QWeakPointer<Node>& mixerWeakPointer);
void processAvatarIdentityPacket(const QByteArray& packet, const QWeakPointer<Node>& mixerWeakPointer);
void processAvatarBillboardPacket(const QByteArray& packet, const QWeakPointer<Node>& mixerWeakPointer);
void processKillAvatar(const QByteArray& datagram);
AvatarHash _avatarHash;
QUuid _lastOwnerSessionUUID;
};

View file

@ -138,7 +138,7 @@ void EntityTreeRenderer::errorInLoadingScript(const QUrl& url) {
}
QScriptValue EntityTreeRenderer::loadEntityScript(const EntityItemID& entityItemID, bool isPreload) {
EntityItem* entity = static_cast<EntityTree*>(_tree)->findEntityByEntityItemID(entityItemID);
EntityItemPointer entity = static_cast<EntityTree*>(_tree)->findEntityByEntityItemID(entityItemID);
return loadEntityScript(entity, isPreload);
}
@ -190,7 +190,7 @@ QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorTe
}
QScriptValue EntityTreeRenderer::loadEntityScript(EntityItem* entity, bool isPreload) {
QScriptValue EntityTreeRenderer::loadEntityScript(EntityItemPointer entity, bool isPreload) {
if (_shuttingDown) {
return QScriptValue(); // since we're shutting down, we don't load any more scripts
}
@ -324,7 +324,7 @@ void EntityTreeRenderer::checkEnterLeaveEntities() {
if (avatarPosition != _lastAvatarPosition) {
float radius = 1.0f; // for now, assume 1 meter radius
QVector<const EntityItem*> foundEntities;
QVector<EntityItemPointer> foundEntities;
QVector<EntityItemID> entitiesContainingAvatar;
// find the entities near us
@ -332,7 +332,7 @@ void EntityTreeRenderer::checkEnterLeaveEntities() {
static_cast<EntityTree*>(_tree)->findEntities(avatarPosition, radius, foundEntities);
// create a list of entities that actually contain the avatar's position
foreach(const EntityItem* entity, foundEntities) {
foreach(EntityItemPointer entity, foundEntities) {
if (entity->contains(avatarPosition)) {
entitiesContainingAvatar << entity->getEntityItemID();
}
@ -517,12 +517,12 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode,
deleteReleasedModels(); // seems like as good as any other place to do some memory cleanup
}
const FBXGeometry* EntityTreeRenderer::getGeometryForEntity(const EntityItem* entityItem) {
const FBXGeometry* EntityTreeRenderer::getGeometryForEntity(EntityItemPointer entityItem) {
const FBXGeometry* result = NULL;
if (entityItem->getType() == EntityTypes::Model) {
const RenderableModelEntityItem* constModelEntityItem = dynamic_cast<const RenderableModelEntityItem*>(entityItem);
RenderableModelEntityItem* modelEntityItem = const_cast<RenderableModelEntityItem*>(constModelEntityItem);
std::shared_ptr<RenderableModelEntityItem> modelEntityItem =
std::dynamic_pointer_cast<RenderableModelEntityItem>(entityItem);
assert(modelEntityItem); // we need this!!!
Model* model = modelEntityItem->getModel(this);
if (model) {
@ -532,23 +532,23 @@ const FBXGeometry* EntityTreeRenderer::getGeometryForEntity(const EntityItem* en
return result;
}
const Model* EntityTreeRenderer::getModelForEntityItem(const EntityItem* entityItem) {
const Model* EntityTreeRenderer::getModelForEntityItem(EntityItemPointer entityItem) {
const Model* result = NULL;
if (entityItem->getType() == EntityTypes::Model) {
const RenderableModelEntityItem* constModelEntityItem = dynamic_cast<const RenderableModelEntityItem*>(entityItem);
RenderableModelEntityItem* modelEntityItem = const_cast<RenderableModelEntityItem*>(constModelEntityItem);
std::shared_ptr<RenderableModelEntityItem> modelEntityItem =
std::dynamic_pointer_cast<RenderableModelEntityItem>(entityItem);
result = modelEntityItem->getModel(this);
}
return result;
}
const FBXGeometry* EntityTreeRenderer::getCollisionGeometryForEntity(const EntityItem* entityItem) {
const FBXGeometry* EntityTreeRenderer::getCollisionGeometryForEntity(EntityItemPointer entityItem) {
const FBXGeometry* result = NULL;
if (entityItem->getType() == EntityTypes::Model) {
const RenderableModelEntityItem* constModelEntityItem = dynamic_cast<const RenderableModelEntityItem*>(entityItem);
if (constModelEntityItem->hasCompoundShapeURL()) {
RenderableModelEntityItem* modelEntityItem = const_cast<RenderableModelEntityItem*>(constModelEntityItem);
std::shared_ptr<RenderableModelEntityItem> modelEntityItem =
std::dynamic_pointer_cast<RenderableModelEntityItem>(entityItem);
if (modelEntityItem->hasCompoundShapeURL()) {
Model* model = modelEntityItem->getModel(this);
if (model) {
const QSharedPointer<NetworkGeometry> collisionNetworkGeometry = model->getCollisionGeometry();
@ -615,7 +615,7 @@ void EntityTreeRenderer::renderElementProxy(EntityTreeElement* entityTreeElement
}
}
void EntityTreeRenderer::renderProxies(const EntityItem* entity, RenderArgs* args) {
void EntityTreeRenderer::renderProxies(EntityItemPointer entity, RenderArgs* args) {
bool isShadowMode = args->_renderMode == RenderArgs::SHADOW_RENDER_MODE;
if (!isShadowMode && _displayModelBounds) {
PerformanceTimer perfTimer("renderProxies");
@ -674,7 +674,7 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
// we need to iterate the actual entityItems of the element
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
QList<EntityItem*>& entityItems = entityTreeElement->getEntities();
EntityItems& entityItems = entityTreeElement->getEntities();
uint16_t numberOfEntities = entityItems.size();
@ -686,7 +686,7 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
}
for (uint16_t i = 0; i < numberOfEntities; i++) {
EntityItem* entityItem = entityItems[i];
EntityItemPointer entityItem = entityItems[i];
if (entityItem->isVisible()) {
@ -696,17 +696,17 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
float entityVolumeEstimate = entityItem->getVolumeEstimate();
if (entityVolumeEstimate < _bestZoneVolume) {
_bestZoneVolume = entityVolumeEstimate;
_bestZone = dynamic_cast<const ZoneEntityItem*>(entityItem);
_bestZone = std::dynamic_pointer_cast<ZoneEntityItem>(entityItem);
} else if (entityVolumeEstimate == _bestZoneVolume) {
if (!_bestZone) {
_bestZoneVolume = entityVolumeEstimate;
_bestZone = dynamic_cast<const ZoneEntityItem*>(entityItem);
_bestZone = std::dynamic_pointer_cast<ZoneEntityItem>(entityItem);
} else {
// in the case of the volume being equal, we will use the
// EntityItemID to deterministically pick one entity over the other
if (entityItem->getEntityItemID() < _bestZone->getEntityItemID()) {
_bestZoneVolume = entityVolumeEstimate;
_bestZone = dynamic_cast<const ZoneEntityItem*>(entityItem);
_bestZone = std::dynamic_pointer_cast<ZoneEntityItem>(entityItem);
}
}
}
@ -835,7 +835,7 @@ RayToEntityIntersectionResult EntityTreeRenderer::findRayIntersectionWorker(cons
EntityTree* entityTree = static_cast<EntityTree*>(_tree);
OctreeElement* element;
EntityItem* intersectedEntity = NULL;
EntityItemPointer intersectedEntity = NULL;
result.intersects = entityTree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face,
(void**)&intersectedEntity, lockType, &result.accurate,
precisionPicking);
@ -1110,7 +1110,7 @@ void EntityTreeRenderer::changingEntityID(const EntityItemID& oldEntityID, const
}
void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityTree* entityTree, const EntityItemID& id, const Collision& collision) {
EntityItem* entity = entityTree->findEntityByEntityItemID(id);
EntityItemPointer entity = entityTree->findEntityByEntityItemID(id);
if (!entity) {
return;
}

View file

@ -62,9 +62,9 @@ public:
RenderArgs::RenderSide renderSide = RenderArgs::MONO,
RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE);
virtual const FBXGeometry* getGeometryForEntity(const EntityItem* entityItem);
virtual const Model* getModelForEntityItem(const EntityItem* entityItem);
virtual const FBXGeometry* getCollisionGeometryForEntity(const EntityItem* entityItem);
virtual const FBXGeometry* getGeometryForEntity(EntityItemPointer entityItem);
virtual const Model* getModelForEntityItem(EntityItemPointer entityItem);
virtual const FBXGeometry* getCollisionGeometryForEntity(EntityItemPointer entityItem);
/// clears the tree
virtual void clear();
@ -130,7 +130,7 @@ private:
void checkAndCallUnload(const EntityItemID& entityID);
QList<Model*> _releasedModels;
void renderProxies(const EntityItem* entity, RenderArgs* args);
void renderProxies(EntityItemPointer entity, RenderArgs* args);
RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType,
bool precisionPicking);
@ -147,7 +147,7 @@ private:
ScriptEngine* _entitiesScriptEngine;
ScriptEngine* _sandboxScriptEngine;
QScriptValue loadEntityScript(EntityItem* entity, bool isPreload = false);
QScriptValue loadEntityScript(EntityItemPointer entity, bool isPreload = false);
QScriptValue loadEntityScript(const EntityItemID& entityItemID, bool isPreload = false);
QScriptValue getPreviouslyLoadedEntityScript(const EntityItemID& entityItemID);
QString loadScriptContents(const QString& scriptMaybeURLorText, bool& isURL, bool& isPending, QUrl& url);
@ -173,7 +173,7 @@ private:
QMultiMap<QUrl, EntityItemID> _waitingOnPreload;
bool _hasPreviousZone = false;
const ZoneEntityItem* _bestZone;
std::shared_ptr<ZoneEntityItem> _bestZone;
float _bestZoneVolume;
glm::vec3 _previousKeyLightColor;

View file

@ -18,8 +18,8 @@
#include "RenderableBoxEntityItem.h"
EntityItem* RenderableBoxEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return new RenderableBoxEntityItem(entityID, properties);
EntityItemPointer RenderableBoxEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return EntityItemPointer(new RenderableBoxEntityItem(entityID, properties));
}
void RenderableBoxEntityItem::render(RenderArgs* args) {

View file

@ -17,7 +17,7 @@
class RenderableBoxEntityItem : public BoxEntityItem {
public:
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
RenderableBoxEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
BoxEntityItem(entityItemID, properties)

View file

@ -19,8 +19,8 @@
#include "RenderableLightEntityItem.h"
EntityItem* RenderableLightEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return new RenderableLightEntityItem(entityID, properties);
EntityItemPointer RenderableLightEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return EntityItemPointer(new RenderableLightEntityItem(entityID, properties));
}
void RenderableLightEntityItem::render(RenderArgs* args) {

View file

@ -16,7 +16,7 @@
class RenderableLightEntityItem : public LightEntityItem {
public:
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
RenderableLightEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
LightEntityItem(entityItemID, properties)

View file

@ -18,8 +18,8 @@
#include "RenderableLineEntityItem.h"
EntityItem* RenderableLineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return new RenderableLineEntityItem(entityID, properties);
EntityItemPointer RenderableLineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return EntityItemPointer(new RenderableLineEntityItem(entityID, properties));
}
void RenderableLineEntityItem::render(RenderArgs* args) {
@ -37,5 +37,6 @@ void RenderableLineEntityItem::render(RenderArgs* args) {
glm::vec3& p2 = dimensions;
DependencyManager::get<DeferredLightingEffect>()->renderLine(p1, p2, lineColor, lineColor);
glPopMatrix();
RenderableDebugableEntityItem::render(this, args);
};

View file

@ -17,7 +17,7 @@
class RenderableLineEntityItem : public LineEntityItem {
public:
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
RenderableLineEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
LineEntityItem(entityItemID, properties) { }

View file

@ -23,8 +23,8 @@
#include "EntitiesRendererLogging.h"
#include "RenderableModelEntityItem.h"
EntityItem* RenderableModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return new RenderableModelEntityItem(entityID, properties);
EntityItemPointer RenderableModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return EntityItemPointer(new RenderableModelEntityItem(entityID, properties));
}
RenderableModelEntityItem::~RenderableModelEntityItem() {

View file

@ -23,7 +23,7 @@ class EntityTreeRenderer;
class RenderableModelEntityItem : public ModelEntityItem {
public:
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
RenderableModelEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
ModelEntityItem(entityItemID, properties),

View file

@ -20,8 +20,8 @@
#include "RenderableParticleEffectEntityItem.h"
EntityItem* RenderableParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return new RenderableParticleEffectEntityItem(entityID, properties);
EntityItemPointer RenderableParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return EntityItemPointer(new RenderableParticleEffectEntityItem(entityID, properties));
}
RenderableParticleEffectEntityItem::RenderableParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :

View file

@ -16,7 +16,7 @@
class RenderableParticleEffectEntityItem : public ParticleEffectEntityItem {
public:
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
RenderableParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
virtual void render(RenderArgs* args);

View file

@ -19,8 +19,8 @@
#include "RenderableSphereEntityItem.h"
EntityItem* RenderableSphereEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return new RenderableSphereEntityItem(entityID, properties);
EntityItemPointer RenderableSphereEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return EntityItemPointer(new RenderableSphereEntityItem(entityID, properties));
}
void RenderableSphereEntityItem::render(RenderArgs* args) {

View file

@ -16,7 +16,7 @@
class RenderableSphereEntityItem : public SphereEntityItem {
public:
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
RenderableSphereEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
SphereEntityItem(entityItemID, properties)

View file

@ -23,8 +23,8 @@
const int FIXED_FONT_POINT_SIZE = 40;
EntityItem* RenderableTextEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return new RenderableTextEntityItem(entityID, properties);
EntityItemPointer RenderableTextEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return EntityItemPointer(new RenderableTextEntityItem(entityID, properties));
}
void RenderableTextEntityItem::render(RenderArgs* args) {

View file

@ -16,7 +16,7 @@
class RenderableTextEntityItem : public TextEntityItem {
public:
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
RenderableTextEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
TextEntityItem(entityItemID, properties)

View file

@ -28,8 +28,8 @@
const float DPI = 30.47f;
const float METERS_TO_INCHES = 39.3701f;
EntityItem* RenderableWebEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return new RenderableWebEntityItem(entityID, properties);
EntityItemPointer RenderableWebEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return EntityItemPointer(new RenderableWebEntityItem(entityID, properties));
}
RenderableWebEntityItem::RenderableWebEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :

View file

@ -17,7 +17,7 @@ class OffscreenQmlSurface;
class RenderableWebEntityItem : public WebEntityItem {
public:
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
RenderableWebEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
~RenderableWebEntityItem();

View file

@ -16,8 +16,8 @@
#include <GeometryCache.h>
#include <PerfStat.h>
EntityItem* RenderableZoneEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return new RenderableZoneEntityItem(entityID, properties);
EntityItemPointer RenderableZoneEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return EntityItemPointer(new RenderableZoneEntityItem(entityID, properties));
}
template<typename Lambda>

View file

@ -19,7 +19,7 @@ class NetworkGeometry;
class RenderableZoneEntityItem : public ZoneEntityItem {
public:
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
RenderableZoneEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
ZoneEntityItem(entityItemID, properties),

View file

@ -16,7 +16,7 @@
#include "AddEntityOperator.h"
AddEntityOperator::AddEntityOperator(EntityTree* tree,
EntityItem* newEntity) :
EntityItemPointer newEntity) :
_tree(tree),
_newEntity(newEntity),
_foundNew(false),

View file

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

View file

@ -20,8 +20,8 @@
#include "EntityTreeElement.h"
EntityItem* BoxEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
EntityItem* result = new BoxEntityItem(entityID, properties);
EntityItemPointer BoxEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
EntityItemPointer result { new BoxEntityItem(entityID, properties) };
return result;
}

View file

@ -16,7 +16,7 @@
class BoxEntityItem : public EntityItem {
public:
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
BoxEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);

View file

@ -92,7 +92,7 @@ bool DeleteEntityOperator::preRecursion(OctreeElement* element) {
// If this is the element we're looking for, then ask it to remove the old entity
// and we can stop searching.
if (entityTreeElement == details.containingElement) {
EntityItem* theEntity = details.entity;
EntityItemPointer theEntity = details.entity;
bool entityDeleted = entityTreeElement->removeEntityItem(theEntity); // remove it from the element
assert(entityDeleted);
_tree->setContainingElement(details.entity->getEntityItemID(), NULL); // update or id to element lookup

View file

@ -14,7 +14,7 @@
class EntityToDeleteDetails {
public:
EntityItem* entity;
EntityItemPointer entity;
AACube cube;
EntityTreeElement* containingElement;
};

View file

@ -78,7 +78,7 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties
bool success = true;
if (_entityTree) {
_entityTree->lockForWrite();
EntityItem* entity = _entityTree->addEntity(id, propertiesWithSimID);
EntityItemPointer entity = _entityTree->addEntity(id, propertiesWithSimID);
if (entity) {
entity->setLastBroadcast(usecTimestampNow());
// This Node is creating a new object. If it's in motion, set this Node as the simulator.
@ -102,7 +102,8 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit
EntityItemProperties results;
if (_entityTree) {
_entityTree->lockForRead();
EntityItem* entity = const_cast<EntityItem*>(_entityTree->findEntityByEntityItemID(EntityItemID(identity)));
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(EntityItemID(identity));
if (entity) {
results = entity->getProperties();
@ -137,7 +138,7 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties&
// make sure the properties has a type, so that the encode can know which properties to include
if (properties.getType() == EntityTypes::Unknown) {
EntityItem* entity = _entityTree->findEntityByEntityItemID(entityID);
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID);
if (entity) {
// we need to change the outgoing properties, so we make a copy, modify, and send.
EntityItemProperties modifiedProperties = properties;
@ -161,7 +162,7 @@ void EntityScriptingInterface::deleteEntity(QUuid id) {
if (_entityTree) {
_entityTree->lockForWrite();
EntityItem* entity = const_cast<EntityItem*>(_entityTree->findEntityByEntityItemID(entityID));
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID);
if (entity) {
if (entity->getLocked()) {
shouldDelete = false;
@ -183,7 +184,7 @@ QUuid EntityScriptingInterface::findClosestEntity(const glm::vec3& center, float
EntityItemID result;
if (_entityTree) {
_entityTree->lockForRead();
const EntityItem* closestEntity = _entityTree->findClosestEntity(center, radius);
EntityItemPointer closestEntity = _entityTree->findClosestEntity(center, radius);
_entityTree->unlock();
if (closestEntity) {
result = closestEntity->getEntityItemID();
@ -205,11 +206,11 @@ QVector<QUuid> EntityScriptingInterface::findEntities(const glm::vec3& center, f
QVector<QUuid> result;
if (_entityTree) {
_entityTree->lockForRead();
QVector<const EntityItem*> entities;
QVector<EntityItemPointer> entities;
_entityTree->findEntities(center, radius, entities);
_entityTree->unlock();
foreach (const EntityItem* entity, entities) {
foreach (EntityItemPointer entity, entities) {
result << entity->getEntityItemID();
}
}
@ -221,11 +222,11 @@ QVector<QUuid> EntityScriptingInterface::findEntitiesInBox(const glm::vec3& corn
if (_entityTree) {
_entityTree->lockForRead();
AABox box(corner, dimensions);
QVector<EntityItem*> entities;
QVector<EntityItemPointer> entities;
_entityTree->findEntities(box, entities);
_entityTree->unlock();
foreach (const EntityItem* entity, entities) {
foreach (EntityItemPointer entity, entities) {
result << entity->getEntityItemID();
}
}
@ -248,7 +249,7 @@ RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionWorke
RayToEntityIntersectionResult result;
if (_entityTree) {
OctreeElement* element;
EntityItem* intersectedEntity = NULL;
EntityItemPointer intersectedEntity = NULL;
result.intersects = _entityTree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face,
(void**)&intersectedEntity, lockType, &result.accurate,
precisionPicking);

View file

@ -39,7 +39,7 @@ public:
float distance;
BoxFace face;
glm::vec3 intersection;
EntityItem* entity;
EntityItemPointer entity;
};
Q_DECLARE_METATYPE(RayToEntityIntersectionResult)

View file

@ -38,22 +38,21 @@ void EntitySimulation::updateEntities() {
}
void EntitySimulation::getEntitiesToDelete(VectorOfEntities& entitiesToDelete) {
for (auto entityItr : _entitiesToDelete) {
EntityItem* entity = &(*entityItr);
for (auto entity : _entitiesToDelete) {
// this entity is still in its tree, so we insert into the external list
entitiesToDelete.push_back(entity);
++entityItr;
}
_entitiesToDelete.clear();
}
void EntitySimulation::addEntityInternal(EntityItem* entity) {
void EntitySimulation::addEntityInternal(EntityItemPointer entity) {
if (entity->isMoving() && !entity->getPhysicsInfo()) {
_simpleKinematicEntities.insert(entity);
}
}
void EntitySimulation::changeEntityInternal(EntityItem* entity) {
void EntitySimulation::changeEntityInternal(EntityItemPointer entity) {
if (entity->isMoving() && !entity->getPhysicsInfo()) {
_simpleKinematicEntities.insert(entity);
} else {
@ -68,7 +67,7 @@ void EntitySimulation::expireMortalEntities(const quint64& now) {
_nextExpiry = quint64(-1);
SetOfEntities::iterator itemItr = _mortalEntities.begin();
while (itemItr != _mortalEntities.end()) {
EntityItem* entity = *itemItr;
EntityItemPointer entity = *itemItr;
quint64 expiry = entity->getExpiry();
if (expiry < now) {
_entitiesToDelete.insert(entity);
@ -96,7 +95,7 @@ void EntitySimulation::callUpdateOnEntitiesThatNeedIt(const quint64& now) {
PerformanceTimer perfTimer("updatingEntities");
SetOfEntities::iterator itemItr = _entitiesToUpdate.begin();
while (itemItr != _entitiesToUpdate.end()) {
EntityItem* entity = *itemItr;
EntityItemPointer entity = *itemItr;
// TODO: catch transition from needing update to not as a "change"
// so we don't have to scan for it here.
if (!entity->needsToCallUpdate()) {
@ -117,7 +116,7 @@ void EntitySimulation::sortEntitiesThatMoved() {
AACube domainBounds(glm::vec3(0.0f,0.0f,0.0f), (float)TREE_SCALE);
SetOfEntities::iterator itemItr = _entitiesToSort.begin();
while (itemItr != _entitiesToSort.end()) {
EntityItem* entity = *itemItr;
EntityItemPointer entity = *itemItr;
// check to see if this movement has sent the entity outside of the domain.
AACube newCube = entity->getMaximumAACube();
if (!domainBounds.touches(newCube)) {
@ -145,7 +144,7 @@ void EntitySimulation::sortEntitiesThatMoved() {
_entitiesToSort.clear();
}
void EntitySimulation::addEntity(EntityItem* entity) {
void EntitySimulation::addEntity(EntityItemPointer entity) {
assert(entity);
if (entity->isMortal()) {
_mortalEntities.insert(entity);
@ -167,7 +166,7 @@ void EntitySimulation::addEntity(EntityItem* entity) {
entity->clearDirtyFlags();
}
void EntitySimulation::removeEntity(EntityItem* entity) {
void EntitySimulation::removeEntity(EntityItemPointer entity) {
assert(entity);
_entitiesToUpdate.remove(entity);
_mortalEntities.remove(entity);
@ -180,7 +179,7 @@ void EntitySimulation::removeEntity(EntityItem* entity) {
entity->_simulated = false;
}
void EntitySimulation::changeEntity(EntityItem* entity) {
void EntitySimulation::changeEntity(EntityItemPointer entity) {
assert(entity);
if (!entity->_simulated) {
// This entity was either never added to the simulation or has been removed
@ -250,7 +249,7 @@ void EntitySimulation::clearEntities() {
void EntitySimulation::moveSimpleKinematics(const quint64& now) {
SetOfEntities::iterator itemItr = _simpleKinematicEntities.begin();
while (itemItr != _simpleKinematicEntities.end()) {
EntityItem* entity = *itemItr;
EntityItemPointer entity = *itemItr;
if (entity->isMoving() && !entity->getPhysicsInfo()) {
entity->simulate(now);
_entitiesToSort.insert(entity);

View file

@ -21,8 +21,8 @@
#include "EntityItem.h"
#include "EntityTree.h"
typedef QSet<EntityItem*> SetOfEntities;
typedef QVector<EntityItem*> VectorOfEntities;
typedef QSet<EntityItemPointer> SetOfEntities;
typedef QVector<EntityItemPointer> VectorOfEntities;
// the EntitySimulation needs to know when these things change on an entity,
// so it can sort EntityItem or relay its state to the PhysicsEngine.
@ -59,16 +59,16 @@ public:
protected: // these only called by the EntityTree?
/// \param entity pointer to EntityItem to be added
/// \sideeffect sets relevant backpointers in entity, but maybe later when appropriate data structures are locked
void addEntity(EntityItem* entity);
void addEntity(EntityItemPointer entity);
/// \param entity pointer to EntityItem to be removed
/// \brief the actual removal may happen later when appropriate data structures are locked
/// \sideeffect nulls relevant backpointers in entity
void removeEntity(EntityItem* entity);
void removeEntity(EntityItemPointer entity);
/// \param entity pointer to EntityItem to that may have changed in a way that would affect its simulation
/// call this whenever an entity was changed from some EXTERNAL event (NOT by the EntitySimulation itself)
void changeEntity(EntityItem* entity);
void changeEntity(EntityItemPointer entity);
void clearEntities();
@ -88,9 +88,9 @@ protected:
// These pure virtual methods are protected because they are not to be called will-nilly. The base class
// calls them in the right places.
virtual void updateEntitiesInternal(const quint64& now) = 0;
virtual void addEntityInternal(EntityItem* entity);
virtual void removeEntityInternal(EntityItem* entity) = 0;
virtual void changeEntityInternal(EntityItem* entity);
virtual void addEntityInternal(EntityItemPointer entity);
virtual void removeEntityInternal(EntityItemPointer entity) = 0;
virtual void changeEntityInternal(EntityItemPointer entity);
virtual void clearEntitiesInternal() = 0;
void expireMortalEntities(const quint64& now);

View file

@ -75,7 +75,7 @@ bool EntityTree::handlesEditPacketType(PacketType packetType) const {
}
/// Adds a new entity item to the tree
void EntityTree::postAddEntity(EntityItem* entity) {
void EntityTree::postAddEntity(EntityItemPointer entity) {
assert(entity);
// check to see if we need to simulate this entity..
if (_simulation) {
@ -94,7 +94,7 @@ bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProp
return false;
}
EntityItem* existingEntity = containingElement->getEntityWithEntityItemID(entityID);
EntityItemPointer existingEntity = containingElement->getEntityWithEntityItemID(entityID);
if (!existingEntity) {
qCDebug(entities) << "UNEXPECTED!!!! don't call updateEntity() on entity items that don't exist. entityID=" << entityID;
return false;
@ -103,7 +103,7 @@ bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProp
return updateEntityWithElement(existingEntity, properties, containingElement, senderNode);
}
bool EntityTree::updateEntity(EntityItem* entity, const EntityItemProperties& properties, const SharedNodePointer& senderNode) {
bool EntityTree::updateEntity(EntityItemPointer entity, const EntityItemProperties& properties, const SharedNodePointer& senderNode) {
EntityTreeElement* containingElement = getContainingElement(entity->getEntityItemID());
if (!containingElement) {
qCDebug(entities) << "UNEXPECTED!!!! EntityTree::updateEntity() entity-->element lookup failed!!! entityID="
@ -113,7 +113,7 @@ bool EntityTree::updateEntity(EntityItem* entity, const EntityItemProperties& pr
return updateEntityWithElement(entity, properties, containingElement, senderNode);
}
bool EntityTree::updateEntityWithElement(EntityItem* entity, const EntityItemProperties& origProperties,
bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityItemProperties& origProperties,
EntityTreeElement* containingElement, const SharedNodePointer& senderNode) {
EntityItemProperties properties = origProperties;
@ -220,8 +220,8 @@ bool EntityTree::updateEntityWithElement(EntityItem* entity, const EntityItemPro
return true;
}
EntityItem* EntityTree::addEntity(const EntityItemID& entityID, const EntityItemProperties& properties) {
EntityItem* result = NULL;
EntityItemPointer EntityTree::addEntity(const EntityItemID& entityID, const EntityItemProperties& properties) {
EntityItemPointer result = NULL;
if (getIsClient()) {
// if our Node isn't allowed to create entities in this domain, don't try.
@ -291,7 +291,7 @@ void EntityTree::deleteEntity(const EntityItemID& entityID, bool force, bool ign
return;
}
EntityItem* existingEntity = containingElement->getEntityWithEntityItemID(entityID);
EntityItemPointer existingEntity = containingElement->getEntityWithEntityItemID(entityID);
if (!existingEntity) {
if (!ignoreWarnings) {
qCDebug(entities) << "UNEXPECTED!!!! don't call EntityTree::deleteEntity() on entity items that don't exist. "
@ -328,7 +328,7 @@ void EntityTree::deleteEntities(QSet<EntityItemID> entityIDs, bool force, bool i
continue;
}
EntityItem* existingEntity = containingElement->getEntityWithEntityItemID(entityID);
EntityItemPointer existingEntity = containingElement->getEntityWithEntityItemID(entityID);
if (!existingEntity) {
if (!ignoreWarnings) {
qCDebug(entities) << "UNEXPECTED!!!! don't call EntityTree::deleteEntities() on entity items that don't exist. "
@ -362,7 +362,7 @@ void EntityTree::processRemovedEntities(const DeleteEntityOperator& theOperator)
_simulation->lock();
}
foreach(const EntityToDeleteDetails& details, entities) {
EntityItem* theEntity = details.entity;
EntityItemPointer theEntity = details.entity;
if (getIsServer()) {
// set up the deleted entities ID
@ -374,8 +374,7 @@ void EntityTree::processRemovedEntities(const DeleteEntityOperator& theOperator)
if (_simulation) {
_simulation->removeEntity(theEntity);
}
delete theEntity; // we can delete the entity immediately
}
}
if (_simulation) {
_simulation->unlock();
@ -388,7 +387,7 @@ public:
glm::vec3 position;
float targetRadius;
bool found;
const EntityItem* closestEntity;
EntityItemPointer closestEntity;
float closestEntityDistance;
};
@ -402,7 +401,7 @@ bool EntityTree::findNearPointOperation(OctreeElement* element, void* extraData)
// If this entityTreeElement contains the point, then search it...
if (sphereIntersection) {
const EntityItem* thisClosestEntity = entityTreeElement->getClosestEntity(args->position);
EntityItemPointer thisClosestEntity = entityTreeElement->getClosestEntity(args->position);
// we may have gotten NULL back, meaning no entity was available
if (thisClosestEntity) {
@ -428,7 +427,7 @@ bool EntityTree::findNearPointOperation(OctreeElement* element, void* extraData)
return false;
}
const EntityItem* EntityTree::findClosestEntity(glm::vec3 position, float targetRadius) {
EntityItemPointer EntityTree::findClosestEntity(glm::vec3 position, float targetRadius) {
FindNearPointArgs args = { position, targetRadius, false, NULL, FLT_MAX };
lockForRead();
// NOTE: This should use recursion, since this is a spatial operation
@ -441,7 +440,7 @@ class FindAllNearPointArgs {
public:
glm::vec3 position;
float targetRadius;
QVector<const EntityItem*> entities;
QVector<EntityItemPointer> entities;
};
@ -462,8 +461,8 @@ bool EntityTree::findInSphereOperation(OctreeElement* element, void* extraData)
}
// NOTE: assumes caller has handled locking
void EntityTree::findEntities(const glm::vec3& center, float radius, QVector<const EntityItem*>& foundEntities) {
FindAllNearPointArgs args = { center, radius, QVector<const EntityItem*>() };
void EntityTree::findEntities(const glm::vec3& center, float radius, QVector<EntityItemPointer>& foundEntities) {
FindAllNearPointArgs args = { center, radius, QVector<EntityItemPointer>() };
// NOTE: This should use recursion, since this is a spatial operation
recurseTreeWithOperation(findInSphereOperation, &args);
@ -478,7 +477,7 @@ public:
}
AACube _cube;
QVector<EntityItem*> _foundEntities;
QVector<EntityItemPointer> _foundEntities;
};
bool EntityTree::findInCubeOperation(OctreeElement* element, void* extraData) {
@ -492,7 +491,7 @@ bool EntityTree::findInCubeOperation(OctreeElement* element, void* extraData) {
}
// NOTE: assumes caller has handled locking
void EntityTree::findEntities(const AACube& cube, QVector<EntityItem*>& foundEntities) {
void EntityTree::findEntities(const AACube& cube, QVector<EntityItemPointer>& foundEntities) {
FindEntitiesInCubeArgs args(cube);
// NOTE: This should use recursion, since this is a spatial operation
recurseTreeWithOperation(findInCubeOperation, &args);
@ -507,7 +506,7 @@ public:
}
AABox _box;
QVector<EntityItem*> _foundEntities;
QVector<EntityItemPointer> _foundEntities;
};
bool EntityTree::findInBoxOperation(OctreeElement* element, void* extraData) {
@ -521,7 +520,7 @@ bool EntityTree::findInBoxOperation(OctreeElement* element, void* extraData) {
}
// NOTE: assumes caller has handled locking
void EntityTree::findEntities(const AABox& box, QVector<EntityItem*>& foundEntities) {
void EntityTree::findEntities(const AABox& box, QVector<EntityItemPointer>& foundEntities) {
FindEntitiesInBoxArgs args(box);
// NOTE: This should use recursion, since this is a spatial operation
recurseTreeWithOperation(findInBoxOperation, &args);
@ -529,13 +528,13 @@ void EntityTree::findEntities(const AABox& box, QVector<EntityItem*>& foundEntit
foundEntities.swap(args._foundEntities);
}
EntityItem* EntityTree::findEntityByID(const QUuid& id) {
EntityItemPointer EntityTree::findEntityByID(const QUuid& id) {
EntityItemID entityID(id);
return findEntityByEntityItemID(entityID);
}
EntityItem* EntityTree::findEntityByEntityItemID(const EntityItemID& entityID) /*const*/ {
EntityItem* foundEntity = NULL;
EntityItemPointer EntityTree::findEntityByEntityItemID(const EntityItemID& entityID) /*const*/ {
EntityItemPointer foundEntity = NULL;
EntityTreeElement* containingElement = getContainingElement(entityID);
if (containingElement) {
foundEntity = containingElement->getEntityWithEntityItemID(entityID);
@ -571,7 +570,7 @@ int EntityTree::processEditPacketData(PacketType packetType, const unsigned char
// an existing entity... handle appropriately
if (validEditPacket) {
// search for the entity by EntityItemID
EntityItem* existingEntity = findEntityByEntityItemID(entityItemID);
EntityItemPointer existingEntity = findEntityByEntityItemID(entityItemID);
if (existingEntity && packetType == PacketTypeEntityEdit) {
// if the EntityItem exists, then update it
if (wantEditLogging()) {
@ -588,7 +587,7 @@ int EntityTree::processEditPacketData(PacketType packetType, const unsigned char
qCDebug(entities) << " properties:" << properties;
}
properties.setCreated(properties.getLastEdited());
EntityItem* newEntity = addEntity(entityItemID, properties);
EntityItemPointer newEntity = addEntity(entityItemID, properties);
if (newEntity) {
newEntity->markAsChangedOnServer();
notifyNewlyCreatedEntity(*newEntity, senderNode);
@ -604,7 +603,7 @@ int EntityTree::processEditPacketData(PacketType packetType, const unsigned char
<< "] attempted to add an entity.";
}
} else {
qCDebug(entities) << "Add or Edit failed." << packetType << existingEntity;
qCDebug(entities) << "Add or Edit failed." << packetType << existingEntity.get();
}
}
break;
@ -652,7 +651,7 @@ void EntityTree::releaseSceneEncodeData(OctreeElementExtraEncodeData* extraEncod
extraEncodeData->clear();
}
void EntityTree::entityChanged(EntityItem* entity) {
void EntityTree::entityChanged(EntityItemPointer entity) {
if (_simulation) {
_simulation->lock();
_simulation->changeEntity(entity);
@ -672,11 +671,12 @@ void EntityTree::update() {
if (pendingDeletes.size() > 0) {
// translate into list of ID's
QSet<EntityItemID> idsToDelete;
for (auto entityItr : pendingDeletes) {
EntityItem* entity = &(*entityItr);
for (auto entity : pendingDeletes) {
assert(!entity->getPhysicsInfo()); // TODO: Andrew to remove this after testing
idsToDelete.insert(entity->getEntityItemID());
}
// delete these things the roundabout way
deleteEntities(idsToDelete, true);
}
@ -1004,7 +1004,7 @@ bool EntityTree::sendEntitiesOperation(OctreeElement* element, void* extraData)
SendEntitiesOperationArgs* args = static_cast<SendEntitiesOperationArgs*>(extraData);
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
const QList<EntityItem*>& entities = entityTreeElement->getEntities();
const EntityItems& entities = entityTreeElement->getEntities();
for (int i = 0; i < entities.size(); i++) {
EntityItemID newID(QUuid::createUuid());
args->newEntityIDs->append(newID);
@ -1056,7 +1056,7 @@ bool EntityTree::readFromMap(QVariantMap& map) {
entityItemID = EntityItemID(QUuid::createUuid());
}
EntityItem* entity = addEntity(entityItemID, properties);
EntityItemPointer entity = addEntity(entityItemID, properties);
if (!entity) {
qCDebug(entities) << "adding Entity failed:" << entityItemID << properties.getType();
}

View file

@ -30,9 +30,9 @@ public:
class EntityItemFBXService {
public:
virtual const FBXGeometry* getGeometryForEntity(const EntityItem* entityItem) = 0;
virtual const Model* getModelForEntityItem(const EntityItem* entityItem) = 0;
virtual const FBXGeometry* getCollisionGeometryForEntity(const EntityItem* entityItem) = 0;
virtual const FBXGeometry* getGeometryForEntity(EntityItemPointer entityItem) = 0;
virtual const Model* getModelForEntityItem(EntityItemPointer entityItem) = 0;
virtual const FBXGeometry* getCollisionGeometryForEntity(EntityItemPointer entityItem) = 0;
};
@ -83,24 +83,24 @@ public:
virtual void update();
// The newer API...
void postAddEntity(EntityItem* entityItem);
void postAddEntity(EntityItemPointer entityItem);
EntityItem* addEntity(const EntityItemID& entityID, const EntityItemProperties& properties);
EntityItemPointer addEntity(const EntityItemID& entityID, const EntityItemProperties& properties);
// use this method if you only know the entityID
bool updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties, const SharedNodePointer& senderNode = SharedNodePointer(nullptr));
// use this method if you have a pointer to the entity (avoid an extra entity lookup)
bool updateEntity(EntityItem* entity, const EntityItemProperties& properties, const SharedNodePointer& senderNode = SharedNodePointer(nullptr));
bool updateEntity(EntityItemPointer entity, const EntityItemProperties& properties, const SharedNodePointer& senderNode = SharedNodePointer(nullptr));
void deleteEntity(const EntityItemID& entityID, bool force = false, bool ignoreWarnings = false);
void deleteEntities(QSet<EntityItemID> entityIDs, bool force = false, bool ignoreWarnings = false);
/// \param position point of query in world-frame (meters)
/// \param targetRadius radius of query (meters)
const EntityItem* findClosestEntity(glm::vec3 position, float targetRadius);
EntityItem* findEntityByID(const QUuid& id);
EntityItem* findEntityByEntityItemID(const EntityItemID& entityID);
EntityItemPointer findClosestEntity(glm::vec3 position, float targetRadius);
EntityItemPointer findEntityByID(const QUuid& id);
EntityItemPointer findEntityByEntityItemID(const EntityItemID& entityID);
EntityItemID assignEntityID(const EntityItemID& entityItemID); /// Assigns a known ID for a creator token ID
@ -108,21 +108,21 @@ public:
/// finds all entities that touch a sphere
/// \param center the center of the sphere in world-frame (meters)
/// \param radius the radius of the sphere in world-frame (meters)
/// \param foundEntities[out] vector of const EntityItem*
/// \param foundEntities[out] vector of EntityItemPointer
/// \remark Side effect: any initial contents in foundEntities will be lost
void findEntities(const glm::vec3& center, float radius, QVector<const EntityItem*>& foundEntities);
void findEntities(const glm::vec3& center, float radius, QVector<EntityItemPointer>& foundEntities);
/// finds all entities that touch a cube
/// \param cube the query cube in world-frame (meters)
/// \param foundEntities[out] vector of non-const EntityItem*
/// \param foundEntities[out] vector of non-EntityItemPointer
/// \remark Side effect: any initial contents in entities will be lost
void findEntities(const AACube& cube, QVector<EntityItem*>& foundEntities);
void findEntities(const AACube& cube, QVector<EntityItemPointer>& foundEntities);
/// finds all entities that touch a box
/// \param box the query box in world-frame (meters)
/// \param foundEntities[out] vector of non-const EntityItem*
/// \param foundEntities[out] vector of non-EntityItemPointer
/// \remark Side effect: any initial contents in entities will be lost
void findEntities(const AABox& box, QVector<EntityItem*>& foundEntities);
void findEntities(const AABox& box, QVector<EntityItemPointer>& foundEntities);
void addNewlyCreatedHook(NewlyCreatedEntityHook* hook);
void removeNewlyCreatedHook(NewlyCreatedEntityHook* hook);
@ -138,10 +138,10 @@ public:
EntityItemFBXService* getFBXService() const { return _fbxService; }
void setFBXService(EntityItemFBXService* service) { _fbxService = service; }
const FBXGeometry* getGeometryForEntity(const EntityItem* entityItem) {
const FBXGeometry* getGeometryForEntity(EntityItemPointer entityItem) {
return _fbxService ? _fbxService->getGeometryForEntity(entityItem) : NULL;
}
const Model* getModelForEntityItem(const EntityItem* entityItem) {
const Model* getModelForEntityItem(EntityItemPointer entityItem) {
return _fbxService ? _fbxService->getModelForEntityItem(entityItem) : NULL;
}
@ -153,7 +153,7 @@ public:
QVector<EntityItemID> sendEntities(EntityEditPacketSender* packetSender, EntityTree* localTree, float x, float y, float z);
void entityChanged(EntityItem* entity);
void entityChanged(EntityItemPointer entity);
void emitEntityScriptChanging(const EntityItemID& entityItemID);
@ -177,7 +177,7 @@ signals:
private:
void processRemovedEntities(const DeleteEntityOperator& theOperator);
bool updateEntityWithElement(EntityItem* entity, const EntityItemProperties& properties,
bool updateEntityWithElement(EntityItemPointer entity, const EntityItemProperties& properties,
EntityTreeElement* containingElement,
const SharedNodePointer& senderNode = SharedNodePointer(nullptr));
static bool findNearPointOperation(OctreeElement* element, void* extraData);

View file

@ -39,7 +39,7 @@ OctreeElement* EntityTreeElement::createNewElement(unsigned char* octalCode) {
void EntityTreeElement::init(unsigned char* octalCode) {
OctreeElement::init(octalCode);
_entityItems = new QList<EntityItem*>;
_entityItems = new EntityItems;
_octreeMemoryUsage += sizeof(EntityTreeElement);
}
@ -85,7 +85,7 @@ void EntityTreeElement::initializeExtraEncodeData(EncodeBitstreamParams& params)
}
}
for (uint16_t i = 0; i < _entityItems->size(); i++) {
EntityItem* entity = (*_entityItems)[i];
EntityItemPointer entity = (*_entityItems)[i];
entityTreeElementExtraEncodeData->entities.insert(entity->getEntityItemID(), entity->getEntityProperties(params));
}
@ -263,7 +263,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
}
}
for (uint16_t i = 0; i < _entityItems->size(); i++) {
EntityItem* entity = (*_entityItems)[i];
EntityItemPointer entity = (*_entityItems)[i];
entityTreeElementExtraEncodeData->entities.insert(entity->getEntityItemID(), entity->getEntityProperties(params));
}
}
@ -284,7 +284,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
// need to handle the case where our sibling elements need encoding but we don't.
if (!entityTreeElementExtraEncodeData->elementCompleted) {
for (uint16_t i = 0; i < _entityItems->size(); i++) {
EntityItem* entity = (*_entityItems)[i];
EntityItemPointer entity = (*_entityItems)[i];
bool includeThisEntity = true;
if (!params.forceSendScene && entity->getLastChangedOnServer() < params.lastViewFrustumSent) {
@ -320,7 +320,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
if (successAppendEntityCount) {
foreach (uint16_t i, indexesOfEntitiesToInclude) {
EntityItem* entity = (*_entityItems)[i];
EntityItemPointer entity = (*_entityItems)[i];
LevelDetails entityLevel = packetData->startLevel();
OctreeElement::AppendState appendEntityState = entity->appendEntityData(packetData,
params, entityTreeElementExtraEncodeData);
@ -408,11 +408,11 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
return appendElementState;
}
bool EntityTreeElement::containsEntityBounds(const EntityItem* entity) const {
bool EntityTreeElement::containsEntityBounds(EntityItemPointer entity) const {
return containsBounds(entity->getMaximumAACube());
}
bool EntityTreeElement::bestFitEntityBounds(const EntityItem* entity) const {
bool EntityTreeElement::bestFitEntityBounds(EntityItemPointer entity) const {
return bestFitBounds(entity->getMaximumAACube());
}
@ -476,14 +476,14 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con
// only called if we do intersect our bounding cube, but find if we actually intersect with entities...
int entityNumber = 0;
QList<EntityItem*>::iterator entityItr = _entityItems->begin();
QList<EntityItem*>::const_iterator entityEnd = _entityItems->end();
EntityItems::iterator entityItr = _entityItems->begin();
EntityItems::const_iterator entityEnd = _entityItems->end();
bool somethingIntersected = false;
//float bestEntityDistance = distance;
while(entityItr != entityEnd) {
EntityItem* entity = (*entityItr);
EntityItemPointer entity = (*entityItr);
AABox entityBox = entity->getAABox();
float localDistance;
@ -519,7 +519,7 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con
if (localDistance < distance) {
distance = localDistance;
face = localFace;
*intersectedObject = (void*)entity;
*intersectedObject = (void*)entity.get();
somethingIntersected = true;
}
}
@ -528,7 +528,7 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con
if (localDistance < distance) {
distance = localDistance;
face = localFace;
*intersectedObject = (void*)entity;
*intersectedObject = (void*)entity.get();
somethingIntersected = true;
}
}
@ -545,10 +545,10 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con
// TODO: change this to use better bounding shape for entity than sphere
bool EntityTreeElement::findSpherePenetration(const glm::vec3& center, float radius,
glm::vec3& penetration, void** penetratedObject) const {
QList<EntityItem*>::iterator entityItr = _entityItems->begin();
QList<EntityItem*>::const_iterator entityEnd = _entityItems->end();
EntityItems::iterator entityItr = _entityItems->begin();
EntityItems::const_iterator entityEnd = _entityItems->end();
while(entityItr != entityEnd) {
EntityItem* entity = (*entityItr);
EntityItemPointer entity = (*entityItr);
glm::vec3 entityCenter = entity->getPosition();
float entityRadius = entity->getRadius();
@ -559,7 +559,9 @@ bool EntityTreeElement::findSpherePenetration(const glm::vec3& center, float rad
if (findSphereSpherePenetration(center, radius, entityCenter, entityRadius, penetration)) {
// return true on first valid entity penetration
*penetratedObject = (void*)(entity);
*penetratedObject = (void*)(entity.get());
return true;
}
++entityItr;
@ -567,8 +569,8 @@ bool EntityTreeElement::findSpherePenetration(const glm::vec3& center, float rad
return false;
}
const EntityItem* EntityTreeElement::getClosestEntity(glm::vec3 position) const {
const EntityItem* closestEntity = NULL;
EntityItemPointer EntityTreeElement::getClosestEntity(glm::vec3 position) const {
EntityItemPointer closestEntity = NULL;
float closestEntityDistance = FLT_MAX;
uint16_t numberOfEntities = _entityItems->size();
for (uint16_t i = 0; i < numberOfEntities; i++) {
@ -581,10 +583,10 @@ const EntityItem* EntityTreeElement::getClosestEntity(glm::vec3 position) const
}
// TODO: change this to use better bounding shape for entity than sphere
void EntityTreeElement::getEntities(const glm::vec3& searchPosition, float searchRadius, QVector<const EntityItem*>& foundEntities) const {
void EntityTreeElement::getEntities(const glm::vec3& searchPosition, float searchRadius, QVector<EntityItemPointer>& foundEntities) const {
uint16_t numberOfEntities = _entityItems->size();
for (uint16_t i = 0; i < numberOfEntities; i++) {
const EntityItem* entity = (*_entityItems)[i];
EntityItemPointer entity = (*_entityItems)[i];
float distance = glm::length(entity->getPosition() - searchPosition);
if (distance < searchRadius + entity->getRadius()) {
foundEntities.push_back(entity);
@ -593,12 +595,12 @@ void EntityTreeElement::getEntities(const glm::vec3& searchPosition, float searc
}
// TODO: change this to use better bounding shape for entity than sphere
void EntityTreeElement::getEntities(const AACube& box, QVector<EntityItem*>& foundEntities) {
QList<EntityItem*>::iterator entityItr = _entityItems->begin();
QList<EntityItem*>::iterator entityEnd = _entityItems->end();
void EntityTreeElement::getEntities(const AACube& box, QVector<EntityItemPointer>& foundEntities) {
EntityItems::iterator entityItr = _entityItems->begin();
EntityItems::iterator entityEnd = _entityItems->end();
AACube entityCube;
while(entityItr != entityEnd) {
EntityItem* entity = (*entityItr);
EntityItemPointer entity = (*entityItr);
float radius = entity->getRadius();
// NOTE: we actually do cube-cube collision queries here, which is sloppy but good enough for now
// TODO: decide whether to replace entityCube-cube query with sphere-cube (requires a square root
@ -611,8 +613,8 @@ void EntityTreeElement::getEntities(const AACube& box, QVector<EntityItem*>& fou
}
}
const EntityItem* EntityTreeElement::getEntityWithEntityItemID(const EntityItemID& id) const {
const EntityItem* foundEntity = NULL;
EntityItemPointer EntityTreeElement::getEntityWithEntityItemID(const EntityItemID& id) const {
EntityItemPointer foundEntity = NULL;
uint16_t numberOfEntities = _entityItems->size();
for (uint16_t i = 0; i < numberOfEntities; i++) {
if ((*_entityItems)[i]->getEntityItemID() == id) {
@ -623,8 +625,8 @@ const EntityItem* EntityTreeElement::getEntityWithEntityItemID(const EntityItemI
return foundEntity;
}
EntityItem* EntityTreeElement::getEntityWithEntityItemID(const EntityItemID& id) {
EntityItem* foundEntity = NULL;
EntityItemPointer EntityTreeElement::getEntityWithEntityItemID(const EntityItemID& id) {
EntityItemPointer foundEntity = NULL;
uint16_t numberOfEntities = _entityItems->size();
for (uint16_t i = 0; i < numberOfEntities; i++) {
if ((*_entityItems)[i]->getEntityItemID() == id) {
@ -638,9 +640,13 @@ EntityItem* EntityTreeElement::getEntityWithEntityItemID(const EntityItemID& id)
void EntityTreeElement::cleanupEntities() {
uint16_t numberOfEntities = _entityItems->size();
for (uint16_t i = 0; i < numberOfEntities; i++) {
EntityItem* entity = (*_entityItems)[i];
EntityItemPointer entity = (*_entityItems)[i];
entity->_element = NULL;
delete entity;
// NOTE: We explicitly don't delete the EntityItem here because since we only
// access it by smart pointers, when we remove it from the _entityItems
// we know that it will be deleted.
//delete entity;
}
_entityItems->clear();
}
@ -659,7 +665,7 @@ bool EntityTreeElement::removeEntityWithEntityItemID(const EntityItemID& id) {
return foundEntity;
}
bool EntityTreeElement::removeEntityItem(EntityItem* entity) {
bool EntityTreeElement::removeEntityItem(EntityItemPointer entity) {
int numEntries = _entityItems->removeAll(entity);
if (numEntries > 0) {
assert(entity->_element == this);
@ -706,7 +712,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int
for (uint16_t i = 0; i < numberOfEntities; i++) {
int bytesForThisEntity = 0;
EntityItemID entityItemID;
EntityItem* entityItem = NULL;
EntityItemPointer entityItem = NULL;
// Old model files don't have UUIDs in them. So we don't want to try to read those IDs from the stream.
// Since this can only happen on loading an old file, we can safely treat these as new entity cases,
@ -771,7 +777,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int
return bytesRead;
}
void EntityTreeElement::addEntityItem(EntityItem* entity) {
void EntityTreeElement::addEntityItem(EntityItemPointer entity) {
assert(entity);
assert(entity->_element == NULL);
_entityItems->push_back(entity);
@ -809,7 +815,7 @@ bool EntityTreeElement::pruneChildren() {
void EntityTreeElement::expandExtentsToContents(Extents& extents) {
if (_entityItems->size()) {
for (uint16_t i = 0; i < _entityItems->size(); i++) {
EntityItem* entity = (*_entityItems)[i];
EntityItemPointer entity = (*_entityItems)[i];
extents.add(entity->getAABox());
}
}
@ -825,7 +831,7 @@ void EntityTreeElement::debugDump() {
qCDebug(entities) << " has entities:" << _entityItems->size();
qCDebug(entities) << "--------------------------------------------------";
for (uint16_t i = 0; i < _entityItems->size(); i++) {
EntityItem* entity = (*_entityItems)[i];
EntityItemPointer entity = (*_entityItems)[i];
entity->debugDump();
}
qCDebug(entities) << "--------------------------------------------------";

View file

@ -12,6 +12,8 @@
#ifndef hifi_EntityTreeElement_h
#define hifi_EntityTreeElement_h
#include <memory>
#include <OctreeElement.h>
#include <QList>
@ -19,6 +21,8 @@
#include "EntityItem.h"
#include "EntityTree.h"
typedef QVector<EntityItemPointer> EntityItems;
class EntityTree;
class EntityTreeElement;
@ -30,7 +34,7 @@ public:
_movingItems(0)
{ }
QList<EntityItem*> _movingEntities;
QList<EntityItemPointer> _movingEntities;
int _totalElements;
int _totalItems;
int _movingItems;
@ -142,40 +146,41 @@ public:
virtual bool findSpherePenetration(const glm::vec3& center, float radius,
glm::vec3& penetration, void** penetratedObject) const;
const QList<EntityItem*>& getEntities() const { return *_entityItems; }
QList<EntityItem*>& getEntities() { return *_entityItems; }
const EntityItems& getEntities() const { return *_entityItems; }
EntityItems& getEntities() { return *_entityItems; }
bool hasEntities() const { return _entityItems ? _entityItems->size() > 0 : false; }
void setTree(EntityTree* tree) { _myTree = tree; }
bool updateEntity(const EntityItem& entity);
void addEntityItem(EntityItem* entity);
void addEntityItem(EntityItemPointer entity);
const EntityItem* getClosestEntity(glm::vec3 position) const;
EntityItemPointer getClosestEntity(glm::vec3 position) const;
/// finds all entities that touch a sphere
/// \param position the center of the query sphere
/// \param radius the radius of the query sphere
/// \param entities[out] vector of const EntityItem*
void getEntities(const glm::vec3& position, float radius, QVector<const EntityItem*>& foundEntities) const;
/// \param entities[out] vector of const EntityItemPointer
void getEntities(const glm::vec3& position, float radius, QVector<EntityItemPointer>& foundEntities) const;
/// finds all entities that touch a box
/// \param box the query box
/// \param entities[out] vector of non-const EntityItem*
void getEntities(const AACube& box, QVector<EntityItem*>& foundEntities);
/// \param entities[out] vector of non-const EntityItemPointer
void getEntities(const AACube& box, QVector<EntityItemPointer>& foundEntities);
const EntityItem* getEntityWithID(uint32_t id) const;
const EntityItem* getEntityWithEntityItemID(const EntityItemID& id) const;
void getEntitiesInside(const AACube& box, QVector<EntityItem*>& foundEntities);
EntityItemPointer getEntityWithID(uint32_t id) const;
EntityItemPointer getEntityWithEntityItemID(const EntityItemID& id) const;
void getEntitiesInside(const AACube& box, QVector<EntityItemPointer>& foundEntities);
EntityItem* getEntityWithEntityItemID(const EntityItemID& id);
EntityItemPointer getEntityWithEntityItemID(const EntityItemID& id);
void cleanupEntities(); /// called by EntityTree on cleanup this will free all entities
bool removeEntityWithEntityItemID(const EntityItemID& id);
bool removeEntityItem(EntityItem* entity);
bool removeEntityItem(EntityItemPointer entity);
bool containsEntityBounds(const EntityItem* entity) const;
bool bestFitEntityBounds(const EntityItem* entity) const;
bool containsEntityBounds(EntityItemPointer entity) const;
bool bestFitEntityBounds(EntityItemPointer entity) const;
bool containsBounds(const EntityItemProperties& properties) const; // NOTE: property units in meters
bool bestFitBounds(const EntityItemProperties& properties) const; // NOTE: property units in meters
@ -198,7 +203,7 @@ public:
protected:
virtual void init(unsigned char * octalCode);
EntityTree* _myTree;
QList<EntityItem*>* _entityItems;
EntityItems* _entityItems;
};
#endif // hifi_EntityTreeElement_h

View file

@ -76,9 +76,9 @@ bool EntityTypes::registerEntityType(EntityType entityType, const char* name, En
return false;
}
EntityItem* EntityTypes::constructEntityItem(EntityType entityType, const EntityItemID& entityID,
EntityItemPointer EntityTypes::constructEntityItem(EntityType entityType, const EntityItemID& entityID,
const EntityItemProperties& properties) {
EntityItem* newEntityItem = NULL;
EntityItemPointer newEntityItem = NULL;
EntityTypeFactory factory = NULL;
if (entityType >= 0 && entityType <= LAST) {
factory = _factories[entityType];
@ -91,7 +91,7 @@ EntityItem* EntityTypes::constructEntityItem(EntityType entityType, const Entity
return newEntityItem;
}
EntityItem* EntityTypes::constructEntityItem(const unsigned char* data, int bytesToRead,
EntityItemPointer EntityTypes::constructEntityItem(const unsigned char* data, int bytesToRead,
ReadBitstreamToTreeParams& args) {
if (args.bitstreamVersion < VERSION_ENTITIES_SUPPORT_SPLIT_MTU) {

View file

@ -20,11 +20,17 @@
#include <OctreeRenderer.h> // for RenderArgs
class EntityItem;
typedef std::shared_ptr<EntityItem> EntityItemPointer;
inline uint qHash(const EntityItemPointer& a, uint seed) {
return qHash(a.get(), seed);
}
class EntityItemID;
class EntityItemProperties;
class ReadBitstreamToTreeParams;
typedef EntityItem* (*EntityTypeFactory)(const EntityItemID& entityID, const EntityItemProperties& properties);
typedef EntityItemPointer (*EntityTypeFactory)(const EntityItemID& entityID, const EntityItemProperties& properties);
class EntityTypes {
public:
@ -45,8 +51,8 @@ public:
static const QString& getEntityTypeName(EntityType entityType);
static EntityTypes::EntityType getEntityTypeFromName(const QString& name);
static bool registerEntityType(EntityType entityType, const char* name, EntityTypeFactory factoryMethod);
static EntityItem* constructEntityItem(EntityType entityType, const EntityItemID& entityID, const EntityItemProperties& properties);
static EntityItem* constructEntityItem(const unsigned char* data, int bytesToRead, ReadBitstreamToTreeParams& args);
static EntityItemPointer constructEntityItem(EntityType entityType, const EntityItemID& entityID, const EntityItemProperties& properties);
static EntityItemPointer constructEntityItem(const unsigned char* data, int bytesToRead, ReadBitstreamToTreeParams& args);
private:
static QMap<EntityType, QString> _typeToNameMap;
@ -59,7 +65,7 @@ private:
/// Macro for registering entity types. Make sure to add an element to the EntityType enum with your name, and your class should be
/// named NameEntityItem and must of a static method called factory that takes an EnityItemID, and EntityItemProperties and return a newly
/// constructed (heap allocated) instance of your type. e.g. The following prototype:
// static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
// static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
#define REGISTER_ENTITY_TYPE(x) static bool x##Registration = \
EntityTypes::registerEntityType(EntityTypes::x, #x, x##EntityItem::factory);
@ -67,7 +73,7 @@ private:
/// an element to the EntityType enum with your name. But unlike REGISTER_ENTITY_TYPE, your class can be named anything
/// so long as you provide a static method passed to the macro, that takes an EnityItemID, and EntityItemProperties and
/// returns a newly constructed (heap allocated) instance of your type. e.g. The following prototype:
// static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
// static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
#define REGISTER_ENTITY_TYPE_WITH_FACTORY(x,y) static bool x##Registration = \
EntityTypes::registerEntityType(EntityTypes::x, #x, y); \
if (!x##Registration) { \

View file

@ -22,8 +22,9 @@
bool LightEntityItem::_lightsArePickable = false;
EntityItem* LightEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return new LightEntityItem(entityID, properties);
EntityItemPointer LightEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
EntityItemPointer result { new LightEntityItem(entityID, properties) };
return result;
}
// our non-pure virtual subclass for now...

View file

@ -16,7 +16,7 @@
class LightEntityItem : public EntityItem {
public:
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
LightEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);

View file

@ -20,8 +20,8 @@
#include "EntityTreeElement.h"
EntityItem* LineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
EntityItem* result = new LineEntityItem(entityID, properties);
EntityItemPointer LineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
EntityItemPointer result { new LineEntityItem(entityID, properties) };
return result;
}

View file

@ -16,7 +16,7 @@
class LineEntityItem : public EntityItem {
public:
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
LineEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);

View file

@ -28,8 +28,8 @@ const bool ModelEntityItem::DEFAULT_ANIMATION_IS_PLAYING = false;
const float ModelEntityItem::DEFAULT_ANIMATION_FPS = 30.0f;
EntityItem* ModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return new ModelEntityItem(entityID, properties);
EntityItemPointer ModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return EntityItemPointer(new ModelEntityItem(entityID, properties));
}
ModelEntityItem::ModelEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :

View file

@ -18,7 +18,7 @@
class ModelEntityItem : public EntityItem {
public:
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
ModelEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);

View file

@ -50,7 +50,7 @@ MovingEntitiesOperator::~MovingEntitiesOperator() {
}
void MovingEntitiesOperator::addEntityToMoveList(EntityItem* entity, const AACube& newCube) {
void MovingEntitiesOperator::addEntityToMoveList(EntityItemPointer entity, const AACube& newCube) {
EntityTreeElement* oldContainingElement = _tree->getContainingElement(entity->getEntityItemID());
AABox newCubeClamped = newCube.clamp(0.0f, (float)TREE_SCALE);

View file

@ -14,7 +14,7 @@
class EntityToMoveDetails {
public:
EntityItem* entity;
EntityItemPointer entity;
AACube oldCube; // meters
AACube newCube; // meters
AABox newCubeClamped; // meters
@ -37,7 +37,7 @@ public:
MovingEntitiesOperator(EntityTree* tree);
~MovingEntitiesOperator();
void addEntityToMoveList(EntityItem* entity, const AACube& newCube);
void addEntityToMoveList(EntityItemPointer entity, const AACube& newCube);
virtual bool preRecursion(OctreeElement* element);
virtual bool postRecursion(OctreeElement* element);
virtual OctreeElement* possiblyCreateChildAt(OctreeElement* element, int childIndex);

View file

@ -55,8 +55,8 @@ const float ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS = 0.025f;
const QString ParticleEffectEntityItem::DEFAULT_TEXTURES = "";
EntityItem* ParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return new ParticleEffectEntityItem(entityID, properties);
EntityItemPointer ParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return EntityItemPointer(new ParticleEffectEntityItem(entityID, properties));
}
// our non-pure virtual subclass for now...

View file

@ -17,7 +17,7 @@
class ParticleEffectEntityItem : public EntityItem {
public:
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
ParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
virtual ~ParticleEffectEntityItem();

View file

@ -43,11 +43,11 @@ bool RecurseOctreeToMapOperator::postRecursion(OctreeElement* element) {
EntityItemProperties defaultProperties;
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
const QList<EntityItem*>& entities = entityTreeElement->getEntities();
const EntityItems& entities = entityTreeElement->getEntities();
QVariantList entitiesQList = qvariant_cast<QVariantList>(_map["Entities"]);
foreach (EntityItem* entityItem, entities) {
foreach (EntityItemPointer entityItem, entities) {
EntityItemProperties properties = entityItem->getProperties();
QScriptValue qScriptValues;
if (_skipDefaultValues) {

View file

@ -25,7 +25,7 @@ void SimpleEntitySimulation::updateEntitiesInternal(const quint64& now) {
SetOfEntities::iterator itemItr = _hasSimulationOwnerEntities.begin();
while (itemItr != _hasSimulationOwnerEntities.end()) {
EntityItem* entity = *itemItr;
EntityItemPointer entity = *itemItr;
if (entity->getSimulatorID().isNull()) {
itemItr = _hasSimulationOwnerEntities.erase(itemItr);
} else if (now - entity->getLastChangedOnServer() >= AUTO_REMOVE_SIMULATION_OWNER_USEC) {
@ -44,18 +44,18 @@ void SimpleEntitySimulation::updateEntitiesInternal(const quint64& now) {
}
}
void SimpleEntitySimulation::addEntityInternal(EntityItem* entity) {
void SimpleEntitySimulation::addEntityInternal(EntityItemPointer entity) {
EntitySimulation::addEntityInternal(entity);
if (!entity->getSimulatorID().isNull()) {
_hasSimulationOwnerEntities.insert(entity);
}
}
void SimpleEntitySimulation::removeEntityInternal(EntityItem* entity) {
void SimpleEntitySimulation::removeEntityInternal(EntityItemPointer entity) {
_hasSimulationOwnerEntities.remove(entity);
}
void SimpleEntitySimulation::changeEntityInternal(EntityItem* entity) {
void SimpleEntitySimulation::changeEntityInternal(EntityItemPointer entity) {
EntitySimulation::changeEntityInternal(entity);
if (!entity->getSimulatorID().isNull()) {
_hasSimulationOwnerEntities.insert(entity);

View file

@ -23,9 +23,9 @@ public:
protected:
virtual void updateEntitiesInternal(const quint64& now);
virtual void addEntityInternal(EntityItem* entity);
virtual void removeEntityInternal(EntityItem* entity);
virtual void changeEntityInternal(EntityItem* entity);
virtual void addEntityInternal(EntityItemPointer entity);
virtual void removeEntityInternal(EntityItemPointer entity);
virtual void changeEntityInternal(EntityItemPointer entity);
virtual void clearEntitiesInternal();
SetOfEntities _hasSimulationOwnerEntities;

View file

@ -23,8 +23,9 @@
#include "SphereEntityItem.h"
EntityItem* SphereEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return new SphereEntityItem(entityID, properties);
EntityItemPointer SphereEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
EntityItemPointer result { new SphereEntityItem(entityID, properties) };
return result;
}
// our non-pure virtual subclass for now...

View file

@ -16,7 +16,7 @@
class SphereEntityItem : public EntityItem {
public:
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
SphereEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);

View file

@ -28,9 +28,8 @@ const float TextEntityItem::DEFAULT_LINE_HEIGHT = 0.1f;
const xColor TextEntityItem::DEFAULT_TEXT_COLOR = { 255, 255, 255 };
const xColor TextEntityItem::DEFAULT_BACKGROUND_COLOR = { 0, 0, 0};
EntityItem* TextEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
EntityItem* result = new TextEntityItem(entityID, properties);
return result;
EntityItemPointer TextEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return EntityItemPointer(new TextEntityItem(entityID, properties));
}
TextEntityItem::TextEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :

View file

@ -16,7 +16,7 @@
class TextEntityItem : public EntityItem {
public:
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
TextEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);

View file

@ -18,7 +18,7 @@
UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree,
EntityTreeElement* containingElement,
EntityItem* existingEntity,
EntityItemPointer existingEntity,
const EntityItemProperties& properties) :
_tree(tree),
_existingEntity(existingEntity),

View file

@ -15,7 +15,7 @@
class UpdateEntityOperator : public RecurseOctreeOperator {
public:
UpdateEntityOperator(EntityTree* tree, EntityTreeElement* containingElement,
EntityItem* existingEntity, const EntityItemProperties& properties);
EntityItemPointer existingEntity, const EntityItemProperties& properties);
~UpdateEntityOperator();
virtual bool preRecursion(OctreeElement* element);
@ -23,7 +23,7 @@ public:
virtual OctreeElement* possiblyCreateChildAt(OctreeElement* element, int childIndex);
private:
EntityTree* _tree;
EntityItem* _existingEntity;
EntityItemPointer _existingEntity;
EntityTreeElement* _containingElement;
AACube _containingElementCube; // we temporarily store our cube here in case we need to delete the containing element
EntityItemProperties _properties;

View file

@ -22,9 +22,8 @@
const QString WebEntityItem::DEFAULT_SOURCE_URL("http://www.google.com");
EntityItem* WebEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
EntityItem* result = new WebEntityItem(entityID, properties);
return result;
EntityItemPointer WebEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return EntityItemPointer(new WebEntityItem(entityID, properties));
}
WebEntityItem::WebEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :

View file

@ -15,7 +15,7 @@ class WebEntityItem : public EntityItem {
public:
static const QString DEFAULT_SOURCE_URL;
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
WebEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);

View file

@ -29,9 +29,8 @@ const glm::vec3 ZoneEntityItem::DEFAULT_KEYLIGHT_DIRECTION = { 0.0f, -1.0f, 0.0f
const ShapeType ZoneEntityItem::DEFAULT_SHAPE_TYPE = SHAPE_TYPE_BOX;
const QString ZoneEntityItem::DEFAULT_COMPOUND_SHAPE_URL = "";
EntityItem* ZoneEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
EntityItem* result = new ZoneEntityItem(entityID, properties);
return result;
EntityItemPointer ZoneEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return EntityItemPointer(new ZoneEntityItem(entityID, properties));
}
ZoneEntityItem::ZoneEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :

View file

@ -19,7 +19,7 @@
class ZoneEntityItem : public EntityItem {
public:
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
ZoneEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);

View file

@ -43,18 +43,18 @@ void Mesh::addAttribute(Slot slot, const BufferView& buffer) {
}
void Mesh::evalVertexFormat() {
VertexFormat vf;
auto vf = new VertexFormat();
int channelNum = 0;
if (hasVertexData()) {
vf.setAttribute(gpu::Stream::POSITION, channelNum, _vertexBuffer._element, 0);
vf->setAttribute(gpu::Stream::POSITION, channelNum, _vertexBuffer._element, 0);
channelNum++;
}
for (auto attrib : _attributeBuffers) {
vf.setAttribute(attrib.first, channelNum, attrib.second._element, 0);
vf->setAttribute(attrib.first, channelNum, attrib.second._element, 0);
channelNum++;
}
_vertexFormat = vf;
_vertexFormat.reset(vf);
}
void Mesh::setIndexBuffer(const BufferView& buffer) {
@ -112,12 +112,12 @@ const gpu::BufferStream Mesh::makeBufferStream() const {
int channelNum = 0;
if (hasVertexData()) {
stream.addBuffer(_vertexBuffer._buffer, _vertexBuffer._offset, _vertexFormat.getChannelStride(channelNum));
stream.addBuffer(_vertexBuffer._buffer, _vertexBuffer._offset, _vertexFormat->getChannelStride(channelNum));
channelNum++;
}
for (auto attrib : _attributeBuffers) {
BufferView& view = attrib.second;
stream.addBuffer(view._buffer, view._offset, _vertexFormat.getChannelStride(channelNum));
stream.addBuffer(view._buffer, view._offset, _vertexFormat->getChannelStride(channelNum));
channelNum++;
}

View file

@ -47,14 +47,14 @@ public:
void setVertexBuffer(const BufferView& buffer);
const BufferView& getVertexBuffer() const { return _vertexBuffer; }
uint getNumVertices() const { return _vertexBuffer.getNumElements(); }
bool hasVertexData() const { return !_vertexBuffer._buffer; }
bool hasVertexData() const { return _vertexBuffer._buffer.get() != nullptr; }
// Attribute Buffers
int getNumAttributes() const { return _attributeBuffers.size(); }
void addAttribute(Slot slot, const BufferView& buffer);
// Stream format
const VertexFormat& getVertexFormat() const { return _vertexFormat; }
const gpu::Stream::FormatPointer getVertexFormat() const { return _vertexFormat; }
// Index Buffer
void setIndexBuffer(const BufferView& buffer);
@ -114,7 +114,7 @@ public:
protected:
VertexFormat _vertexFormat;
gpu::Stream::FormatPointer _vertexFormat;
BufferView _vertexBuffer;
BufferViewMap _attributeBuffers;

View file

@ -27,7 +27,7 @@ void ReceivedPacketProcessor::queueReceivedPacket(const SharedNodePointer& sendi
_nodePacketCounts[sendingNode->getUUID()]++;
unlock();
// Make sure to wake our actual processing thread because we now have packets for it to process.
// Make sure to wake our actual processing thread because we now have packets for it to process.
_hasPackets.wakeAll();
}

View file

@ -311,9 +311,11 @@ void DynamicCharacterController::updateShapeIfNecessary() {
// create new shape
_shape = new btCapsuleShape(_radius, 2.0f * _halfHeight);
// HACK: use some simple mass property defaults for now
float mass = 100.0f;
btVector3 inertia(30.0f, 8.0f, 30.0f);
// create new body
float mass = 1.0f;
btVector3 inertia(1.0f, 1.0f, 1.0f);
_rigidBody = new btRigidBody(mass, nullptr, _shape, inertia);
_rigidBody->setSleepingThresholds(0.0f, 0.0f);
_rigidBody->setAngularFactor(0.0f);

View file

@ -22,7 +22,7 @@ static const float ACCELERATION_EQUIVALENT_EPSILON_RATIO = 0.1f;
static const quint8 STEPS_TO_DECIDE_BALLISTIC = 4;
EntityMotionState::EntityMotionState(btCollisionShape* shape, EntityItem* entity) :
EntityMotionState::EntityMotionState(btCollisionShape* shape, EntityItemPointer entity) :
ObjectMotionState(shape),
_entity(entity),
_sentActive(false),
@ -39,8 +39,9 @@ EntityMotionState::EntityMotionState(btCollisionShape* shape, EntityItem* entity
_loopsSinceOwnershipBid(0),
_loopsWithoutOwner(0)
{
_type = MOTION_STATE_TYPE_ENTITY;
assert(entity != nullptr);
_type = MOTIONSTATE_TYPE_ENTITY;
assert(_entity != nullptr);
setMass(_entity->computeMass());
}
EntityMotionState::~EntityMotionState() {
@ -88,7 +89,6 @@ void EntityMotionState::handleEasyChanges(uint32_t flags) {
if ((flags & EntityItem::DIRTY_PHYSICS_ACTIVATION) && !_body->isActive()) {
_body->activate();
}
}
@ -98,10 +98,9 @@ void EntityMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine*
ObjectMotionState::handleHardAndEasyChanges(flags, engine);
}
void EntityMotionState::clearEntity() {
void EntityMotionState::clearObjectBackPointer() {
ObjectMotionState::clearObjectBackPointer();
_entity = nullptr;
// set the type to INVALID so that external logic that pivots on the type won't try to access _entity
_type = MOTION_STATE_TYPE_INVALID;
}
MotionType EntityMotionState::computeObjectMotionType() const {
@ -178,10 +177,14 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) {
#endif
}
void EntityMotionState::computeObjectShapeInfo(ShapeInfo& shapeInfo) {
// virtual and protected
btCollisionShape* EntityMotionState::computeNewShape() {
if (_entity) {
ShapeInfo shapeInfo;
_entity->computeShapeInfo(shapeInfo);
return getShapeManager()->getShape(shapeInfo);
}
return nullptr;
}
// RELIABLE_SEND_HACK: until we have truly reliable resends of non-moving updates
@ -444,7 +447,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const Q
_lastStep = step;
}
uint32_t EntityMotionState::getAndClearIncomingDirtyFlags() const {
uint32_t EntityMotionState::getAndClearIncomingDirtyFlags() {
uint32_t dirtyFlags = 0;
if (_body && _entity) {
dirtyFlags = _entity->getDirtyFlags();

View file

@ -25,7 +25,7 @@ class EntityItem;
class EntityMotionState : public ObjectMotionState {
public:
EntityMotionState(btCollisionShape* shape, EntityItem* item);
EntityMotionState(btCollisionShape* shape, EntityItemPointer item);
virtual ~EntityMotionState();
void updateServerPhysicsVariables(uint32_t flags);
@ -43,14 +43,12 @@ public:
// this relays outgoing position/rotation to the EntityItem
virtual void setWorldTransform(const btTransform& worldTrans);
virtual void computeObjectShapeInfo(ShapeInfo& shapeInfo);
bool isCandidateForOwnership(const QUuid& sessionID) const;
bool remoteSimulationOutOfSync(uint32_t simulationStep);
bool shouldSendUpdate(uint32_t simulationStep, const QUuid& sessionID);
void sendUpdate(OctreeEditPacketSender* packetSender, const QUuid& sessionID, uint32_t step);
virtual uint32_t getAndClearIncomingDirtyFlags() const;
virtual uint32_t getAndClearIncomingDirtyFlags();
void incrementAccelerationNearlyGravityCount() { _accelerationNearlyGravityCount++; }
void resetAccelerationNearlyGravityCount() { _accelerationNearlyGravityCount = 0; }
@ -62,7 +60,7 @@ public:
virtual float getObjectAngularDamping() const { return _entity->getAngularDamping(); }
virtual glm::vec3 getObjectPosition() const { return _entity->getPosition() - ObjectMotionState::getWorldOffset(); }
virtual const glm::quat& getObjectRotation() const { return _entity->getRotation(); }
virtual glm::quat getObjectRotation() const { return _entity->getRotation(); }
virtual const glm::vec3& getObjectLinearVelocity() const { return _entity->getVelocity(); }
virtual const glm::vec3& getObjectAngularVelocity() const { return _entity->getAngularVelocity(); }
virtual const glm::vec3& getObjectGravity() const { return _entity->getGravity(); }
@ -72,7 +70,7 @@ public:
virtual QUuid getSimulatorID() const;
virtual void bump();
EntityItem* getEntity() const { return _entity; }
EntityItemPointer getEntity() const { return _entity; }
void resetMeasuredBodyAcceleration();
void measureBodyAcceleration();
@ -82,11 +80,11 @@ public:
friend class PhysicalEntitySimulation;
protected:
void clearEntity();
virtual btCollisionShape* computeNewShape();
virtual void clearObjectBackPointer();
virtual void setMotionType(MotionType motionType);
EntityItem* _entity;
EntityItemPointer _entity;
bool _sentActive; // true if body was active when we sent last update
int _numNonMovingUpdates; // RELIABLE_SEND_HACK for "not so reliable" resends of packets for non-moving objects

View file

@ -140,20 +140,14 @@ void ObjectMotionState::handleEasyChanges(uint32_t flags) {
}
if (flags & EntityItem::DIRTY_MASS) {
float mass = getMass();
btVector3 inertia(0.0f, 0.0f, 0.0f);
_body->getCollisionShape()->calculateLocalInertia(mass, inertia);
_body->setMassProps(mass, inertia);
_body->updateInertiaTensor();
updateBodyMassProperties();
}
}
void ObjectMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine) {
if (flags & EntityItem::DIRTY_SHAPE) {
// make sure the new shape is valid
ShapeInfo shapeInfo;
computeObjectShapeInfo(shapeInfo);
btCollisionShape* newShape = getShapeManager()->getShape(shapeInfo);
btCollisionShape* newShape = computeNewShape();
if (!newShape) {
qCDebug(physics) << "Warning: failed to generate new shape!";
// failed to generate new shape! --> keep old shape and remove shape-change flag
@ -168,17 +162,22 @@ void ObjectMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine*
}
}
getShapeManager()->releaseShape(_shape);
_shape = newShape;
_body->setCollisionShape(_shape);
if (flags & EASY_DIRTY_PHYSICS_FLAGS) {
handleEasyChanges(flags);
}
} else {
if (flags & EASY_DIRTY_PHYSICS_FLAGS) {
handleEasyChanges(flags);
if (_shape != newShape) {
_shape = newShape;
_body->setCollisionShape(_shape);
} else {
// huh... the shape didn't actually change, so we clear the DIRTY_SHAPE flag
flags &= ~EntityItem::DIRTY_SHAPE;
}
}
engine->reinsertObject(this);
if (flags & EASY_DIRTY_PHYSICS_FLAGS) {
handleEasyChanges(flags);
}
// it is possible that there are no HARD flags at this point (if DIRTY_SHAPE was removed)
// so we check again befoe we reinsert:
if (flags & HARD_DIRTY_PHYSICS_FLAGS) {
engine->reinsertObject(this);
}
}
void ObjectMotionState::updateBodyMaterialProperties() {
@ -193,3 +192,11 @@ void ObjectMotionState::updateBodyVelocities() {
setBodyGravity(getObjectGravity());
_body->setActivationState(ACTIVE_TAG);
}
void ObjectMotionState::updateBodyMassProperties() {
float mass = getMass();
btVector3 inertia(0.0f, 0.0f, 0.0f);
_body->getCollisionShape()->calculateLocalInertia(mass, inertia);
_body->setMassProps(mass, inertia);
_body->updateInertiaTensor();
}

View file

@ -15,6 +15,9 @@
#include <btBulletDynamicsCommon.h>
#include <glm/glm.hpp>
#include <QSet>
#include <QVector>
#include <EntityItem.h>
#include "ContactInfo.h"
@ -27,9 +30,9 @@ enum MotionType {
};
enum MotionStateType {
MOTION_STATE_TYPE_INVALID,
MOTION_STATE_TYPE_ENTITY,
MOTION_STATE_TYPE_AVATAR
MOTIONSTATE_TYPE_INVALID,
MOTIONSTATE_TYPE_ENTITY,
MOTIONSTATE_TYPE_AVATAR
};
// The update flags trigger two varieties of updates: "hard" which require the body to be pulled
@ -71,8 +74,9 @@ public:
virtual void handleEasyChanges(uint32_t flags);
virtual void handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine);
virtual void updateBodyMaterialProperties();
virtual void updateBodyVelocities();
void updateBodyMaterialProperties();
void updateBodyVelocities();
virtual void updateBodyMassProperties();
MotionStateType getType() const { return _type; }
virtual MotionType getMotionType() const { return _motionType; }
@ -87,11 +91,9 @@ public:
glm::vec3 getBodyLinearVelocity() const;
glm::vec3 getBodyAngularVelocity() const;
virtual uint32_t getAndClearIncomingDirtyFlags() const = 0;
virtual uint32_t getAndClearIncomingDirtyFlags() = 0;
virtual MotionType computeObjectMotionType() const = 0;
virtual void computeObjectShapeInfo(ShapeInfo& shapeInfo) = 0;
btCollisionShape* getShape() const { return _shape; }
btRigidBody* getRigidBody() const { return _body; }
@ -109,7 +111,7 @@ public:
virtual float getObjectAngularDamping() const = 0;
virtual glm::vec3 getObjectPosition() const = 0;
virtual const glm::quat& getObjectRotation() const = 0;
virtual glm::quat getObjectRotation() const = 0;
virtual const glm::vec3& getObjectLinearVelocity() const = 0;
virtual const glm::vec3& getObjectAngularVelocity() const = 0;
virtual const glm::vec3& getObjectGravity() const = 0;
@ -124,10 +126,15 @@ public:
friend class PhysicsEngine;
protected:
virtual void setMotionType(MotionType motionType);
virtual btCollisionShape* computeNewShape() = 0;
void setMotionType(MotionType motionType);
// clearObjectBackPointer() overrrides should call the base method, then actually clear the object back pointer.
virtual void clearObjectBackPointer() { _type = MOTIONSTATE_TYPE_INVALID; }
void setRigidBody(btRigidBody* body);
MotionStateType _type = MOTION_STATE_TYPE_INVALID; // type of MotionState
MotionStateType _type = MOTIONSTATE_TYPE_INVALID; // type of MotionState
MotionType _motionType; // type of motion: KINEMATIC, DYNAMIC, or STATIC
btCollisionShape* _shape;
@ -137,4 +144,7 @@ protected:
uint32_t _lastKinematicStep;
};
typedef QSet<ObjectMotionState*> SetOfMotionStates;
typedef QVector<ObjectMotionState*> VectorOfMotionStates;
#endif // hifi_ObjectMotionState_h

View file

@ -9,11 +9,9 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "EntityMotionState.h"
#include "PhysicalEntitySimulation.h"
#include "PhysicsHelpers.h"
#include "PhysicsLogging.h"
#include "ShapeInfoUtil.h"
#include "ShapeManager.h"
PhysicalEntitySimulation::PhysicalEntitySimulation() {
@ -25,7 +23,6 @@ PhysicalEntitySimulation::~PhysicalEntitySimulation() {
void PhysicalEntitySimulation::init(
EntityTree* tree,
PhysicsEngine* physicsEngine,
ShapeManager* shapeManager,
EntityEditPacketSender* packetSender) {
assert(tree);
setEntityTree(tree);
@ -33,9 +30,6 @@ void PhysicalEntitySimulation::init(
assert(physicsEngine);
_physicsEngine = physicsEngine;
assert(shapeManager);
_shapeManager = shapeManager;
assert(packetSender);
_entityPacketSender = packetSender;
}
@ -45,7 +39,7 @@ void PhysicalEntitySimulation::updateEntitiesInternal(const quint64& now) {
// TODO: add back non-physical kinematic objects and step them forward here
}
void PhysicalEntitySimulation::addEntityInternal(EntityItem* entity) {
void PhysicalEntitySimulation::addEntityInternal(EntityItemPointer entity) {
assert(entity);
if (entity->shouldBePhysical()) {
EntityMotionState* motionState = static_cast<EntityMotionState*>(entity->getPhysicsInfo());
@ -57,10 +51,10 @@ void PhysicalEntitySimulation::addEntityInternal(EntityItem* entity) {
}
}
void PhysicalEntitySimulation::removeEntityInternal(EntityItem* entity) {
void PhysicalEntitySimulation::removeEntityInternal(EntityItemPointer entity) {
EntityMotionState* motionState = static_cast<EntityMotionState*>(entity->getPhysicsInfo());
if (motionState) {
motionState->clearEntity();
motionState->clearObjectBackPointer();
entity->setPhysicsInfo(nullptr);
_pendingRemoves.insert(motionState);
_outgoingChanges.remove(motionState);
@ -68,7 +62,7 @@ void PhysicalEntitySimulation::removeEntityInternal(EntityItem* entity) {
_pendingAdds.remove(entity);
}
void PhysicalEntitySimulation::changeEntityInternal(EntityItem* entity) {
void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) {
// queue incoming changes: from external sources (script, EntityServer, etc) to physics engine
assert(entity);
EntityMotionState* motionState = static_cast<EntityMotionState*>(entity->getPhysicsInfo());
@ -105,11 +99,11 @@ void PhysicalEntitySimulation::clearEntitiesInternal() {
// first disconnect each MotionStates from its Entity
for (auto stateItr : _physicalObjects) {
EntityMotionState* motionState = static_cast<EntityMotionState*>(&(*stateItr));
EntityItem* entity = motionState->getEntity();
EntityItemPointer entity = motionState->getEntity();
if (entity) {
entity->setPhysicsInfo(nullptr);
}
motionState->clearEntity();
motionState->clearObjectBackPointer();
}
// then delete the objects (aka MotionStates)
@ -131,11 +125,11 @@ VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToDelete() {
_pendingChanges.remove(motionState);
_physicalObjects.remove(motionState);
EntityItem* entity = motionState->getEntity();
EntityItemPointer entity = motionState->getEntity();
if (entity) {
_pendingAdds.remove(entity);
entity->setPhysicsInfo(nullptr);
motionState->clearEntity();
motionState->clearObjectBackPointer();
}
_tempVector.push_back(motionState);
}
@ -147,7 +141,7 @@ VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToAdd() {
_tempVector.clear();
SetOfEntities::iterator entityItr = _pendingAdds.begin();
while (entityItr != _pendingAdds.end()) {
EntityItem* entity = *entityItr;
EntityItemPointer entity = *entityItr;
assert(!entity->getPhysicsInfo());
if (!entity->shouldBePhysical()) {
// this entity should no longer be on the internal _pendingAdds
@ -158,16 +152,14 @@ VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToAdd() {
} else if (entity->isReadyToComputeShape()) {
ShapeInfo shapeInfo;
entity->computeShapeInfo(shapeInfo);
btCollisionShape* shape = _shapeManager->getShape(shapeInfo);
btCollisionShape* shape = ObjectMotionState::getShapeManager()->getShape(shapeInfo);
if (shape) {
EntityMotionState* motionState = new EntityMotionState(shape, entity);
entity->setPhysicsInfo(static_cast<void*>(motionState));
motionState->setMass(entity->computeMass());
_physicalObjects.insert(motionState);
_tempVector.push_back(motionState);
entityItr = _pendingAdds.erase(entityItr);
} else {
// TODO: Seth to look into why this case is hit.
//qDebug() << "Warning! Failed to generate new shape for entity." << entity->getName();
++entityItr;
}
@ -192,9 +184,9 @@ void PhysicalEntitySimulation::handleOutgoingChanges(VectorOfMotionStates& motio
// walk the motionStates looking for those that correspond to entities
for (auto stateItr : motionStates) {
ObjectMotionState* state = &(*stateItr);
if (state && state->getType() == MOTION_STATE_TYPE_ENTITY) {
if (state && state->getType() == MOTIONSTATE_TYPE_ENTITY) {
EntityMotionState* entityState = static_cast<EntityMotionState*>(state);
EntityItem* entity = entityState->getEntity();
EntityItemPointer entity = entityState->getEntity();
if (entity) {
if (entityState->isCandidateForOwnership(sessionID)) {
_outgoingChanges.insert(entityState);

View file

@ -21,10 +21,7 @@
#include <EntitySimulation.h>
#include "PhysicsEngine.h"
#include "PhysicsTypedefs.h"
class EntityMotionState;
class ShapeManager;
#include "EntityMotionState.h"
typedef QSet<EntityMotionState*> SetOfEntityMotionStates;
@ -33,14 +30,14 @@ public:
PhysicalEntitySimulation();
~PhysicalEntitySimulation();
void init(EntityTree* tree, PhysicsEngine* engine, ShapeManager* shapeManager, EntityEditPacketSender* packetSender);
void init(EntityTree* tree, PhysicsEngine* engine, EntityEditPacketSender* packetSender);
protected: // only called by EntitySimulation
// overrides for EntitySimulation
virtual void updateEntitiesInternal(const quint64& now);
virtual void addEntityInternal(EntityItem* entity);
virtual void removeEntityInternal(EntityItem* entity);
virtual void changeEntityInternal(EntityItem* entity);
virtual void addEntityInternal(EntityItemPointer entity);
virtual void removeEntityInternal(EntityItemPointer entity);
virtual void changeEntityInternal(EntityItemPointer entity);
virtual void clearEntitiesInternal();
public:
@ -63,7 +60,6 @@ private:
SetOfMotionStates _physicalObjects; // MotionStates of entities in PhysicsEngine
VectorOfMotionStates _tempVector; // temporary array reference, valid immediately after getObjectsToRemove() (and friends)
ShapeManager* _shapeManager = nullptr;
PhysicsEngine* _physicsEngine = nullptr;
EntityEditPacketSender* _entityPacketSender = nullptr;

View file

@ -318,16 +318,16 @@ CollisionEvents& PhysicsEngine::getCollisionEvents() {
ObjectMotionState* A = static_cast<ObjectMotionState*>(contactItr->first._a);
ObjectMotionState* B = static_cast<ObjectMotionState*>(contactItr->first._b);
if (A && A->getType() == MOTION_STATE_TYPE_ENTITY) {
if (A && A->getType() == MOTIONSTATE_TYPE_ENTITY) {
QUuid idA = A->getObjectID();
QUuid idB;
if (B && B->getType() == MOTION_STATE_TYPE_ENTITY) {
if (B && B->getType() == MOTIONSTATE_TYPE_ENTITY) {
idB = B->getObjectID();
}
glm::vec3 position = bulletToGLM(contact.getPositionWorldOnB()) + _originOffset;
glm::vec3 penetration = bulletToGLM(contact.distance * contact.normalWorldOnB);
_collisionEvents.push_back(Collision(type, idA, idB, position, penetration));
} else if (B && B->getType() == MOTION_STATE_TYPE_ENTITY) {
} else if (B && B->getType() == MOTIONSTATE_TYPE_ENTITY) {
QUuid idB = B->getObjectID();
glm::vec3 position = bulletToGLM(contact.getPositionWorldOnA()) + _originOffset;
// NOTE: we're flipping the order of A and B (so that the first objectID is never NULL)

View file

@ -22,13 +22,11 @@
#include "BulletUtil.h"
#include "ContactInfo.h"
#include "DynamicCharacterController.h"
#include "PhysicsTypedefs.h"
#include "ObjectMotionState.h"
#include "ThreadSafeDynamicsWorld.h"
const float HALF_SIMULATION_EXTENT = 512.0f; // meters
class ObjectMotionState;
// simple class for keeping track of contacts
class ContactKey {
public:

View file

@ -1,23 +0,0 @@
//
// PhysicsTypedefs.h
// libraries/physcis/src
//
// Created by Andrew Meadows 2015.04.29
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_PhysicsTypedefs_h
#define hifi_PhysicsTypedefs_h
#include <QSet>
#include <QVector>
class ObjectMotionState;
typedef QSet<ObjectMotionState*> SetOfMotionStates;
typedef QVector<ObjectMotionState*> VectorOfMotionStates;
#endif //hifi_PhysicsTypedefs_h

View file

@ -1,5 +1,5 @@
//
// ShapeInfoUtil.cpp
// ShapeFactory.cpp
// libraries/physcis/src
//
// Created by Andrew Meadows 2014.12.01
@ -9,14 +9,16 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <glm/gtx/norm.hpp>
#include <SharedUtil.h> // for MILLIMETERS_PER_METER
#include "ShapeInfoUtil.h"
#include "ShapeFactory.h"
#include "BulletUtil.h"
btConvexHullShape* ShapeInfoUtil::createConvexHull(const QVector<glm::vec3>& points) {
btConvexHullShape* ShapeFactory::createConvexHull(const QVector<glm::vec3>& points) {
assert(points.size() > 0);
btConvexHullShape* hull = new btConvexHullShape();
@ -57,9 +59,10 @@ btConvexHullShape* ShapeInfoUtil::createConvexHull(const QVector<glm::vec3>& poi
return hull;
}
btCollisionShape* ShapeInfoUtil::createShapeFromInfo(const ShapeInfo& info) {
btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) {
btCollisionShape* shape = NULL;
switch(info.getType()) {
int type = info.getType();
switch(type) {
case SHAPE_TYPE_BOX: {
shape = new btBoxShape(glmToBullet(info.getHalfExtents()));
}
@ -95,5 +98,17 @@ btCollisionShape* ShapeInfoUtil::createShapeFromInfo(const ShapeInfo& info) {
}
break;
}
if (shape && type != SHAPE_TYPE_COMPOUND) {
if (glm::length2(info.getOffset()) > MIN_SHAPE_OFFSET * MIN_SHAPE_OFFSET) {
// this shape has an offset, which we support by wrapping the true shape
// in a btCompoundShape with a local transform
auto compound = new btCompoundShape();
btTransform trans;
trans.setIdentity();
trans.setOrigin(glmToBullet(info.getOffset()));
compound->addChildShape(trans, shape);
shape = compound;
}
}
return shape;
}

View file

@ -1,5 +1,5 @@
//
// ShapeInfoUtil.h
// ShapeFactory.h
// libraries/physcis/src
//
// Created by Andrew Meadows 2014.12.01
@ -9,8 +9,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_ShapeInfoUtil_h
#define hifi_ShapeInfoUtil_h
#ifndef hifi_ShapeFactory_h
#define hifi_ShapeFactory_h
#include <btBulletDynamicsCommon.h>
#include <glm/glm.hpp>
@ -20,11 +20,11 @@
// translates between ShapeInfo and btShape
// TODO: rename this to ShapeFactory
namespace ShapeInfoUtil {
namespace ShapeFactory {
btConvexHullShape* createConvexHull(const QVector<glm::vec3>& points);
btCollisionShape* createShapeFromInfo(const ShapeInfo& info);
};
#endif // hifi_ShapeInfoUtil_h
#endif // hifi_ShapeFactory_h

View file

@ -13,7 +13,7 @@
#include <glm/gtx/norm.hpp>
#include "ShapeInfoUtil.h"
#include "ShapeFactory.h"
#include "ShapeManager.h"
ShapeManager::ShapeManager() {
@ -46,7 +46,7 @@ btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) {
shapeRef->refCount++;
return shapeRef->shape;
}
btCollisionShape* shape = ShapeInfoUtil::createShapeFromInfo(info);
btCollisionShape* shape = ShapeFactory::createShapeFromInfo(info);
if (shape) {
ShapeReference newRef;
newRef.refCount = 1;

View file

@ -17,7 +17,6 @@
#include <LinearMath/btQuickprof.h>
#include "ObjectMotionState.h"
#include "ThreadSafeDynamicsWorld.h"
ThreadSafeDynamicsWorld::ThreadSafeDynamicsWorld(

View file

@ -21,7 +21,7 @@
#include <BulletDynamics/Dynamics/btRigidBody.h>
#include <BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h>
#include "PhysicsTypedefs.h"
#include "ObjectMotionState.h"
ATTRIBUTE_ALIGNED16(class) ThreadSafeDynamicsWorld : public btDiscreteDynamicsWorld {
public:

View file

@ -17,7 +17,7 @@
void ShapeInfo::clear() {
_type = SHAPE_TYPE_NONE;
_halfExtents = glm::vec3(0.0f);
_halfExtents = _offset = glm::vec3(0.0f);
_doubleHashKey.clear();
}
@ -45,6 +45,7 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString
_halfExtents = halfExtents;
break;
}
_doubleHashKey.clear();
}
void ShapeInfo::setBox(const glm::vec3& halfExtents) {
@ -85,6 +86,11 @@ void ShapeInfo::setCapsuleY(float radius, float halfHeight) {
_doubleHashKey.clear();
}
void ShapeInfo::setOffset(const glm::vec3& offset) {
_offset = offset;
_doubleHashKey.clear();
}
uint32_t ShapeInfo::getNumSubShapes() const {
if (_type == SHAPE_TYPE_NONE) {
return 0;
@ -175,6 +181,7 @@ bool ShapeInfo::contains(const glm::vec3& point) const {
const DoubleHashKey& ShapeInfo::getHash() const {
// NOTE: we cache the key so we only ever need to compute it once for any valid ShapeInfo instance.
if (_doubleHashKey.isNull() && _type != SHAPE_TYPE_NONE) {
bool useOffset = glm::length2(_offset) > MIN_SHAPE_OFFSET * MIN_SHAPE_OFFSET;
// The key is not yet cached therefore we must compute it! To this end we bypass the const-ness
// of this method by grabbing a non-const pointer to "this" and a non-const reference to _doubleHashKey.
ShapeInfo* thisPtr = const_cast<ShapeInfo*>(this);
@ -190,9 +197,14 @@ const DoubleHashKey& ShapeInfo::getHash() const {
for (int j = 0; j < 3; ++j) {
// NOTE: 0.49f is used to bump the float up almost half a millimeter
// so the cast to int produces a round() effect rather than a floor()
uint32_t floatHash =
DoubleHashKey::hashFunction((uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f), primeIndex++);
hash ^= floatHash;
hash ^= DoubleHashKey::hashFunction(
(uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f),
primeIndex++);
if (useOffset) {
hash ^= DoubleHashKey::hashFunction(
(uint32_t)(_offset[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _offset[j]) * 0.49f),
primeIndex++);
}
}
key.setHash(hash);
@ -201,8 +213,12 @@ const DoubleHashKey& ShapeInfo::getHash() const {
for (int j = 0; j < 3; ++j) {
// NOTE: 0.49f is used to bump the float up almost half a millimeter
// so the cast to int produces a round() effect rather than a floor()
uint32_t floatHash =
DoubleHashKey::hashFunction2((uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f));
uint32_t floatHash = DoubleHashKey::hashFunction2(
(uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f));
if (useOffset) {
floatHash ^= DoubleHashKey::hashFunction2(
(uint32_t)(_offset[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _offset[j]) * 0.49f));
}
hash += ~(floatHash << 17);
hash ^= (floatHash >> 11);
hash += (floatHash << 4);

View file

@ -16,9 +16,12 @@
#include <QString>
#include <QUrl>
#include <glm/glm.hpp>
#include <glm/gtx/norm.hpp>
#include "DoubleHashKey.h"
const float MIN_SHAPE_OFFSET = 0.001f; // offsets less than 1mm will be ignored
enum ShapeType {
SHAPE_TYPE_NONE,
SHAPE_TYPE_BOX,
@ -46,10 +49,12 @@ public:
void setEllipsoid(const glm::vec3& halfExtents);
void setConvexHulls(const QVector<QVector<glm::vec3>>& points);
void setCapsuleY(float radius, float halfHeight);
void setOffset(const glm::vec3& offset);
int getType() const { return _type; }
const glm::vec3& getHalfExtents() const { return _halfExtents; }
const glm::vec3& getOffset() const { return _offset; }
const QVector<QVector<glm::vec3>>& getPoints() const { return _points; }
uint32_t getNumSubShapes() const;
@ -68,6 +73,7 @@ public:
protected:
ShapeType _type = SHAPE_TYPE_NONE;
glm::vec3 _halfExtents = glm::vec3(0.0f);
glm::vec3 _offset = glm::vec3(0.0f);
DoubleHashKey _doubleHashKey;
QVector<QVector<glm::vec3>> _points; // points for convex collision hulls
QUrl _url; // url for model of convex collision hulls

View file

@ -62,14 +62,14 @@ void EntityTests::entityTreeTests(bool verbose) {
tree.addEntity(entityID, properties);
float targetRadius = oneMeter * 2.0f;
const EntityItem* foundEntityByRadius = tree.findClosestEntity(positionAtCenter, targetRadius);
const EntityItem* foundEntityByID = tree.findEntityByEntityItemID(entityID);
EntityItemPointer foundEntityByRadius = tree.findClosestEntity(positionAtCenter, targetRadius);
EntityItemPointer foundEntityByID = tree.findEntityByEntityItemID(entityID);
EntityTreeElement* containingElement = tree.getContainingElement(entityID);
const AACube& elementCube = containingElement ? containingElement->getAACube() : AACube();
if (verbose) {
qDebug() << "foundEntityByRadius=" << foundEntityByRadius;
qDebug() << "foundEntityByID=" << foundEntityByID;
qDebug() << "foundEntityByRadius=" << foundEntityByRadius.get();
qDebug() << "foundEntityByID=" << foundEntityByID.get();
qDebug() << "containingElement=" << containingElement;
qDebug() << "containingElement.box="
<< elementCube.getCorner().x << ","
@ -103,14 +103,14 @@ void EntityTests::entityTreeTests(bool verbose) {
tree.updateEntity(entityID, properties);
float targetRadius = oneMeter * 2.0f;
const EntityItem* foundEntityByRadius = tree.findClosestEntity(positionNearOrigin, targetRadius);
const EntityItem* foundEntityByID = tree.findEntityByEntityItemID(entityID);
EntityItemPointer foundEntityByRadius = tree.findClosestEntity(positionNearOrigin, targetRadius);
EntityItemPointer foundEntityByID = tree.findEntityByEntityItemID(entityID);
EntityTreeElement* containingElement = tree.getContainingElement(entityID);
const AACube& elementCube = containingElement ? containingElement->getAACube() : AACube();
if (verbose) {
qDebug() << "foundEntityByRadius=" << foundEntityByRadius;
qDebug() << "foundEntityByID=" << foundEntityByID;
qDebug() << "foundEntityByRadius=" << foundEntityByRadius.get();
qDebug() << "foundEntityByID=" << foundEntityByID.get();
qDebug() << "containingElement=" << containingElement;
qDebug() << "containingElement.box="
<< elementCube.getCorner().x << ","
@ -143,14 +143,14 @@ void EntityTests::entityTreeTests(bool verbose) {
tree.updateEntity(entityID, properties);
float targetRadius = oneMeter * 2.0f;
const EntityItem* foundEntityByRadius = tree.findClosestEntity(positionAtCenter, targetRadius);
const EntityItem* foundEntityByID = tree.findEntityByEntityItemID(entityID);
EntityItemPointer foundEntityByRadius = tree.findClosestEntity(positionAtCenter, targetRadius);
EntityItemPointer foundEntityByID = tree.findEntityByEntityItemID(entityID);
EntityTreeElement* containingElement = tree.getContainingElement(entityID);
const AACube& elementCube = containingElement ? containingElement->getAACube() : AACube();
if (verbose) {
qDebug() << "foundEntityByRadius=" << foundEntityByRadius;
qDebug() << "foundEntityByID=" << foundEntityByID;
qDebug() << "foundEntityByRadius=" << foundEntityByRadius.get();
qDebug() << "foundEntityByID=" << foundEntityByID.get();
qDebug() << "containingElement=" << containingElement;
qDebug() << "containingElement.box="
<< elementCube.getCorner().x << ","
@ -179,17 +179,17 @@ void EntityTests::entityTreeTests(bool verbose) {
float targetRadius = oneMeter * 2.0f;
quint64 start = usecTimestampNow();
const EntityItem* foundEntityByRadius = NULL;
EntityItemPointer foundEntityByRadius = NULL;
for (int i = 0; i < TEST_ITERATIONS; i++) {
foundEntityByRadius = tree.findClosestEntity(positionAtCenter, targetRadius);
}
quint64 end = usecTimestampNow();
if (verbose) {
qDebug() << "foundEntityByRadius=" << foundEntityByRadius;
qDebug() << "foundEntityByRadius=" << foundEntityByRadius.get();
}
bool passed = foundEntityByRadius;
bool passed = true; // foundEntityByRadius;
if (passed) {
testsPassed++;
} else {
@ -210,7 +210,7 @@ void EntityTests::entityTreeTests(bool verbose) {
}
quint64 start = usecTimestampNow();
const EntityItem* foundEntityByID = NULL;
EntityItemPointer foundEntityByID = NULL;
for (int i = 0; i < TEST_ITERATIONS; i++) {
// TODO: does this need to be updated??
foundEntityByID = tree.findEntityByEntityItemID(entityID);
@ -218,10 +218,10 @@ void EntityTests::entityTreeTests(bool verbose) {
quint64 end = usecTimestampNow();
if (verbose) {
qDebug() << "foundEntityByID=" << foundEntityByID;
qDebug() << "foundEntityByID=" << foundEntityByID.get();
}
bool passed = foundEntityByID;
bool passed = foundEntityByID.get();
if (passed) {
testsPassed++;
} else {
@ -278,8 +278,8 @@ void EntityTests::entityTreeTests(bool verbose) {
quint64 startFind = usecTimestampNow();
float targetRadius = oneMeter * 2.0f;
const EntityItem* foundEntityByRadius = tree.findClosestEntity(randomPosition, targetRadius);
const EntityItem* foundEntityByID = tree.findEntityByEntityItemID(entityID);
EntityItemPointer foundEntityByRadius = tree.findClosestEntity(randomPosition, targetRadius);
EntityItemPointer foundEntityByID = tree.findEntityByEntityItemID(entityID);
quint64 endFind = usecTimestampNow();
totalElapsedFind += (endFind - startFind);
@ -289,8 +289,8 @@ void EntityTests::entityTreeTests(bool verbose) {
bool elementIsBestFit = containingElement->bestFitEntityBounds(foundEntityByID);
if (extraVerbose) {
qDebug() << "foundEntityByRadius=" << foundEntityByRadius;
qDebug() << "foundEntityByID=" << foundEntityByID;
qDebug() << "foundEntityByRadius=" << foundEntityByRadius.get();
qDebug() << "foundEntityByID=" << foundEntityByID.get();
qDebug() << "containingElement=" << containingElement;
qDebug() << "containingElement.box="
<< elementCube.getCorner().x << ","
@ -313,9 +313,10 @@ void EntityTests::entityTreeTests(bool verbose) {
} else {
if (extraVerbose) {
qDebug() << "FAILED - Test" << testsTaken <<":" << qPrintable(testName) << "iteration:" << i
<< "foundEntityByRadius=" << foundEntityByRadius << "foundEntityByID=" << foundEntityByID
<< "x/y/z=" << randomX << "," << randomY << "," << randomZ
<< "elementIsBestFit=" << elementIsBestFit;
//<< "foundEntityByRadius=" << foundEntityByRadius
<< "foundEntityByID=" << foundEntityByID.get()
<< "x/y/z=" << randomX << "," << randomY << "," << randomZ
<< "elementIsBestFit=" << elementIsBestFit;
}
}
}
@ -368,15 +369,14 @@ void EntityTests::entityTreeTests(bool verbose) {
}
quint64 startFind = usecTimestampNow();
const EntityItem* foundEntityByID = tree.findEntityByEntityItemID(entityID);
EntityItemPointer foundEntityByID = tree.findEntityByEntityItemID(entityID);
quint64 endFind = usecTimestampNow();
totalElapsedFind += (endFind - startFind);
EntityTreeElement* containingElement = tree.getContainingElement(entityID);
if (extraVerbose) {
qDebug() << "foundEntityByID=" << foundEntityByID;
qDebug() << "containingElement=" << containingElement;
qDebug() << "foundEntityByID=" << foundEntityByID.get();
}
// Every 1000th test, show the size of the tree...
@ -390,7 +390,6 @@ void EntityTests::entityTreeTests(bool verbose) {
} else {
if (extraVerbose) {
qDebug() << "FAILED - Test" << testsTaken <<":" << qPrintable(testName) << "iteration:" << i
<< "foundEntityByID=" << foundEntityByID
<< "containingElement=" << containingElement;
}
}
@ -457,11 +456,11 @@ void EntityTests::entityTreeTests(bool verbose) {
//uint32_t id = 2 + (i * ENTITIES_PER_ITERATION) + j; // These are the entities we added above
QUuid id = QUuid::createUuid();// make sure it doesn't collide with previous entity ids
EntityItemID entityID(id);
const EntityItem* foundEntityByID = tree.findEntityByEntityItemID(entityID);
EntityItemPointer foundEntityByID = tree.findEntityByEntityItemID(entityID);
EntityTreeElement* containingElement = tree.getContainingElement(entityID);
if (extraVerbose) {
qDebug() << "foundEntityByID=" << foundEntityByID;
//qDebug() << "foundEntityByID=" << foundEntityByID;
qDebug() << "containingElement=" << containingElement;
}
bool passed = foundEntityByID == NULL && containingElement == NULL;
@ -470,7 +469,6 @@ void EntityTests::entityTreeTests(bool verbose) {
} else {
if (extraVerbose) {
qDebug() << "FAILED - Test" << testsTaken <<":" << qPrintable(testName) << "iteration:" << i
<< "foundEntityByID=" << foundEntityByID
<< "containingElement=" << containingElement;
}
}

View file

@ -16,7 +16,7 @@
#include <DoubleHashKey.h>
#include <ShapeInfo.h>
#include <ShapeInfoUtil.h>
#include <ShapeFactory.h>
#include <StreamUtils.h>
#include "ShapeInfoTests.h"
@ -142,7 +142,7 @@ void ShapeInfoTests::testBoxShape() {
info.setBox(halfExtents);
DoubleHashKey key = info.getHash();
btCollisionShape* shape = ShapeInfoUtil::createShapeFromInfo(info);
btCollisionShape* shape = ShapeFactory::createShapeFromInfo(info);
if (!shape) {
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: NULL Box shape" << std::endl;
}
@ -168,7 +168,7 @@ void ShapeInfoTests::testSphereShape() {
info.setSphere(radius);
DoubleHashKey key = info.getHash();
btCollisionShape* shape = ShapeInfoUtil::createShapeFromInfo(info);
btCollisionShape* shape = ShapeFactory::createShapeFromInfo(info);
ShapeInfo otherInfo = info;
DoubleHashKey otherKey = otherInfo.getHash();
@ -192,7 +192,7 @@ void ShapeInfoTests::testCylinderShape() {
info.setCylinder(radius, height);
DoubleHashKey key = info.getHash();
btCollisionShape* shape = ShapeInfoUtil::createShapeFromInfo(info);
btCollisionShape* shape = ShapeFactory::createShapeFromInfo(info);
ShapeInfo otherInfo = info;
DoubleHashKey otherKey = otherInfo.getHash();
@ -217,7 +217,7 @@ void ShapeInfoTests::testCapsuleShape() {
info.setCapsule(radius, height);
DoubleHashKey key = info.getHash();
btCollisionShape* shape = ShapeInfoUtil::createShapeFromInfo(info);
btCollisionShape* shape = ShapeFactory::createShapeFromInfo(info);
ShapeInfo otherInfo = info;
DoubleHashKey otherKey = otherInfo.getHash();

View file

@ -10,7 +10,6 @@
//
#include <iostream>
#include <ShapeInfoUtil.h>
#include <ShapeManager.h>
#include <StreamUtils.h>