mirror of
https://github.com/overte-org/overte.git
synced 2025-04-15 17:20:12 +02:00
more work on virtual entities, unit tests passing woot
This commit is contained in:
parent
29e02f2681
commit
3145d150f3
9 changed files with 332 additions and 394 deletions
|
@ -215,17 +215,17 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
|
|||
}
|
||||
|
||||
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
||||
EntityItem& entityItem = entityItems[i];
|
||||
EntityItem* entityItem = entityItems[i];
|
||||
// render entityItem aspoints
|
||||
AACube entityCube = entityItem.getAACube();
|
||||
AACube entityCube = entityItem->getAACube();
|
||||
entityCube.scale(TREE_SCALE);
|
||||
if (args->_viewFrustum->cubeInFrustum(entityCube) != ViewFrustum::OUTSIDE) {
|
||||
glm::vec3 position = entityItem.getPosition() * (float)TREE_SCALE;
|
||||
float radius = entityItem.getRadius() * (float)TREE_SCALE;
|
||||
float size = entityItem.getSize() * (float)TREE_SCALE;
|
||||
glm::vec3 position = entityItem->getPosition() * (float)TREE_SCALE;
|
||||
float radius = entityItem->getRadius() * (float)TREE_SCALE;
|
||||
float size = entityItem->getSize() * (float)TREE_SCALE;
|
||||
|
||||
#ifdef HIDE_SUBCLASS_METHODS
|
||||
bool drawAsModel = entityItem.hasModel();
|
||||
bool drawAsModel = entityItem->hasModel();
|
||||
#else
|
||||
bool drawAsModel = false;
|
||||
#endif
|
||||
|
@ -238,27 +238,27 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
|
|||
{
|
||||
const float alpha = 1.0f;
|
||||
|
||||
Model* model = getModel(entityItem);
|
||||
Model* model = getModel(*entityItem);
|
||||
|
||||
if (model) {
|
||||
model->setScaleToFit(true, radius * 2.0f);
|
||||
model->setSnapModelToCenter(true);
|
||||
|
||||
// set the rotation
|
||||
glm::quat rotation = entityItem.getRotation();
|
||||
glm::quat rotation = entityItem->getRotation();
|
||||
model->setRotation(rotation);
|
||||
|
||||
// set the position
|
||||
model->setTranslation(position);
|
||||
|
||||
// handle animations..
|
||||
if (entityItem.hasAnimation()) {
|
||||
if (!entityItem.jointsMapped()) {
|
||||
if (entityItem->hasAnimation()) {
|
||||
if (!entityItem->jointsMapped()) {
|
||||
QStringList modelJointNames = model->getJointNames();
|
||||
entityItem.mapJoints(modelJointNames);
|
||||
entityItem->mapJoints(modelJointNames);
|
||||
}
|
||||
|
||||
QVector<glm::quat> frameData = entityItem.getAnimationFrame();
|
||||
QVector<glm::quat> frameData = entityItem->getAnimationFrame();
|
||||
for (int i = 0; i < frameData.size(); i++) {
|
||||
model->setJointState(i, true, frameData[i]);
|
||||
}
|
||||
|
@ -271,14 +271,14 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
|
|||
Model::RenderMode modelRenderMode = args->_renderMode == OctreeRenderer::SHADOW_RENDER_MODE
|
||||
? Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE;
|
||||
|
||||
if (entityItem.getGlowLevel() > 0.0f) {
|
||||
Glower glower(entityItem.getGlowLevel());
|
||||
if (entityItem->getGlowLevel() > 0.0f) {
|
||||
Glower glower(entityItem->getGlowLevel());
|
||||
|
||||
if (model->isActive()) {
|
||||
model->render(alpha, modelRenderMode);
|
||||
} else {
|
||||
// if we couldn't get a model, then just draw a sphere
|
||||
glColor3ub(entityItem.getColor()[RED_INDEX],entityItem.getColor()[GREEN_INDEX],entityItem.getColor()[BLUE_INDEX]);
|
||||
glColor3ub(entityItem->getColor()[RED_INDEX],entityItem->getColor()[GREEN_INDEX],entityItem->getColor()[BLUE_INDEX]);
|
||||
glPushMatrix();
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
glutSolidSphere(radius, 15, 15);
|
||||
|
@ -289,7 +289,7 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
|
|||
model->render(alpha, modelRenderMode);
|
||||
} else {
|
||||
// if we couldn't get a model, then just draw a sphere
|
||||
glColor3ub(entityItem.getColor()[RED_INDEX],entityItem.getColor()[GREEN_INDEX],entityItem.getColor()[BLUE_INDEX]);
|
||||
glColor3ub(entityItem->getColor()[RED_INDEX],entityItem->getColor()[GREEN_INDEX],entityItem->getColor()[BLUE_INDEX]);
|
||||
glPushMatrix();
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
glutSolidSphere(radius, 15, 15);
|
||||
|
@ -340,7 +340,7 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
|
|||
}
|
||||
} else {
|
||||
// if we couldn't get a model, then just draw a sphere
|
||||
glColor3ub(entityItem.getColor()[RED_INDEX],entityItem.getColor()[GREEN_INDEX],entityItem.getColor()[BLUE_INDEX]);
|
||||
glColor3ub(entityItem->getColor()[RED_INDEX],entityItem->getColor()[GREEN_INDEX],entityItem->getColor()[BLUE_INDEX]);
|
||||
glPushMatrix();
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
glutSolidSphere(radius, 15, 15);
|
||||
|
@ -350,7 +350,7 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
|
|||
glPopMatrix();
|
||||
#endif
|
||||
} else {
|
||||
//glColor3ub(entityItem.getColor()[RED_INDEX],entityItem.getColor()[GREEN_INDEX],entityItem.getColor()[BLUE_INDEX]);
|
||||
//glColor3ub(entityItem->getColor()[RED_INDEX],entityItem->getColor()[GREEN_INDEX],entityItem.getColor()[BLUE_INDEX]);
|
||||
glColor3f(1.0f, 0.0f, 0.0f);
|
||||
glPushMatrix();
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
|
|
|
@ -43,7 +43,44 @@ bool EntityTypes::registerEntityType(EntityType_t entityType, const QString& nam
|
|||
}
|
||||
|
||||
EntityItem* EntityTypes::constructEntityItem(EntityType_t entityType, const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return NULL; // new EntityItem(entityID, properties); // for now, needs to support registration of constructor
|
||||
EntityItem* newEntityItem = NULL;
|
||||
|
||||
// switch statement for now, needs to support registration of constructor
|
||||
switch (entityType) {
|
||||
// Base, // ??? not supported?
|
||||
case Model:
|
||||
newEntityItem = new ModelEntityItem(entityID, properties);
|
||||
break;
|
||||
|
||||
case Particle:
|
||||
newEntityItem = new ParticleEntityItem(entityID, properties);
|
||||
break;
|
||||
|
||||
case Box:
|
||||
newEntityItem = new BoxEntityItem(entityID, properties);
|
||||
break;
|
||||
|
||||
case Sphere:
|
||||
newEntityItem = new SphereEntityItem(entityID, properties);
|
||||
break;
|
||||
|
||||
case Plane:
|
||||
newEntityItem = new PlaneEntityItem(entityID, properties);
|
||||
break;
|
||||
|
||||
case Cylinder:
|
||||
newEntityItem = new CylinderEntityItem(entityID, properties);
|
||||
break;
|
||||
|
||||
case Pyramid:
|
||||
newEntityItem = new PyramidEntityItem(entityID, properties);
|
||||
break;
|
||||
|
||||
default:
|
||||
newEntityItem = new ModelEntityItem(entityID, properties);
|
||||
break;
|
||||
}
|
||||
return newEntityItem;
|
||||
}
|
||||
|
||||
EntityItem* EntityTypes::constructEntityItem(const unsigned char* data, int bytesToRead) {
|
||||
|
|
|
@ -74,7 +74,8 @@ public:
|
|||
Box,
|
||||
Sphere,
|
||||
Plane,
|
||||
Cylinder
|
||||
Cylinder,
|
||||
Pyramid
|
||||
} EntityType_t;
|
||||
|
||||
static const QString& getEntityTypeName(EntityType_t entityType);
|
||||
|
@ -128,9 +129,13 @@ public:
|
|||
/// used by EntityScriptingInterface to return EntityItemProperties for unknown models
|
||||
void setIsUnknownID() { _id = UNKNOWN_ENTITY_ID; _idSet = true; }
|
||||
|
||||
glm::vec3 getMinimumPoint() const { return _position - glm::vec3(_radius, _radius, _radius); }
|
||||
glm::vec3 getMaximumPoint() const { return _position + glm::vec3(_radius, _radius, _radius); }
|
||||
AACube getAACube() const { return AACube(getMinimumPoint(), getMaxDimension()); } /// AACube in domain scale units (0.0 - 1.0)
|
||||
glm::vec3 getMinimumPointMeters() const { return _position - glm::vec3(_radius, _radius, _radius); }
|
||||
glm::vec3 getMaximumPointMeters() const { return _position + glm::vec3(_radius, _radius, _radius); }
|
||||
AACube getAACubeMeters() const { return AACube(getMinimumPointMeters(), getMaxDimension()); } /// AACube in meter units
|
||||
|
||||
glm::vec3 getMinimumPointTreeUnits() const { return getMinimumPointMeters() / (float)TREE_SCALE; }
|
||||
glm::vec3 getMaximumPointTreeUnits() const { return getMaximumPointMeters() / (float)TREE_SCALE; }
|
||||
AACube getAACubeTreeUnits() const { return AACube(getMinimumPointMeters()/(float)TREE_SCALE, getMaxDimension()/(float)TREE_SCALE); } /// AACube in domain scale units (0.0 - 1.0)
|
||||
void debugDump() const;
|
||||
|
||||
// properties of all entities
|
||||
|
@ -426,4 +431,61 @@ protected:
|
|||
|
||||
};
|
||||
|
||||
// our non-pure virtual subclass for now...
|
||||
class ModelEntityItem : public EntityItem {
|
||||
public:
|
||||
ModelEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
EntityItem(entityItemID, properties) { };
|
||||
|
||||
virtual void somePureVirtualFunction() { }; // allow this class to be constructed
|
||||
};
|
||||
|
||||
class ParticleEntityItem : public EntityItem {
|
||||
public:
|
||||
ParticleEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
EntityItem(entityItemID, properties) { };
|
||||
|
||||
virtual void somePureVirtualFunction() { }; // allow this class to be constructed
|
||||
};
|
||||
|
||||
class BoxEntityItem : public EntityItem {
|
||||
public:
|
||||
BoxEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
EntityItem(entityItemID, properties) { };
|
||||
|
||||
virtual void somePureVirtualFunction() { }; // allow this class to be constructed
|
||||
};
|
||||
|
||||
class SphereEntityItem : public EntityItem {
|
||||
public:
|
||||
SphereEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
EntityItem(entityItemID, properties) { };
|
||||
|
||||
virtual void somePureVirtualFunction() { }; // allow this class to be constructed
|
||||
};
|
||||
|
||||
class PlaneEntityItem : public EntityItem {
|
||||
public:
|
||||
PlaneEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
EntityItem(entityItemID, properties) { };
|
||||
|
||||
virtual void somePureVirtualFunction() { }; // allow this class to be constructed
|
||||
};
|
||||
|
||||
class CylinderEntityItem : public EntityItem {
|
||||
public:
|
||||
CylinderEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
EntityItem(entityItemID, properties) { };
|
||||
|
||||
virtual void somePureVirtualFunction() { }; // allow this class to be constructed
|
||||
};
|
||||
|
||||
class PyramidEntityItem : public EntityItem {
|
||||
public:
|
||||
PyramidEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
EntityItem(entityItemID, properties) { };
|
||||
|
||||
virtual void somePureVirtualFunction() { }; // allow this class to be constructed
|
||||
};
|
||||
|
||||
#endif // hifi_EntityItem_h
|
||||
|
|
|
@ -37,190 +37,12 @@ bool EntityTree::handlesEditPacketType(PacketType packetType) const {
|
|||
}
|
||||
}
|
||||
|
||||
class StoreEntityOperator : public RecurseOctreeOperator {
|
||||
public:
|
||||
StoreEntityOperator(EntityTree* tree, const EntityItem& searchEntity);
|
||||
virtual bool PreRecursion(OctreeElement* element);
|
||||
virtual bool PostRecursion(OctreeElement* element);
|
||||
virtual OctreeElement* PossiblyCreateChildAt(OctreeElement* element, int childIndex);
|
||||
private:
|
||||
EntityTree* _tree;
|
||||
const EntityItem& _newEntity;
|
||||
const EntityItem* _oldEntity;
|
||||
EntityTreeElement* _containingElement;
|
||||
bool _foundOld;
|
||||
bool _foundNew;
|
||||
quint64 _changeTime;
|
||||
|
||||
bool subTreeContainsOldEntity(OctreeElement* element);
|
||||
bool subTreeContainsNewEntity(OctreeElement* element);
|
||||
};
|
||||
|
||||
StoreEntityOperator::StoreEntityOperator(EntityTree* tree, const EntityItem& searchEntity) :
|
||||
_tree(tree),
|
||||
_newEntity(searchEntity),
|
||||
_oldEntity(NULL),
|
||||
_containingElement(NULL),
|
||||
_foundOld(false),
|
||||
_foundNew(false),
|
||||
_changeTime(usecTimestampNow())
|
||||
{
|
||||
// check our tree, to determine if this model is known
|
||||
_containingElement = _tree->getContainingElement(searchEntity.getEntityItemID());
|
||||
if (_containingElement) {
|
||||
_oldEntity = _containingElement->getEntityWithEntityItemID(searchEntity.getEntityItemID());
|
||||
if (!_oldEntity) {
|
||||
//assert(_oldEntity);
|
||||
qDebug() << "that's UNEXPECTED, we got a _containingElement, but couldn't find the oldEntity!";
|
||||
}
|
||||
|
||||
// If this containing element would be the best fit for our new model, then just do the new
|
||||
// portion of the store pass, since the change path will be the same for both parts of the update
|
||||
if (_containingElement->bestFitEntityBounds(&_newEntity)) {
|
||||
_foundOld = true;
|
||||
}
|
||||
} else {
|
||||
// if the old model is not known, then we can consider if found, and
|
||||
// we'll only be searching for the new location
|
||||
_foundOld = true;
|
||||
}
|
||||
}
|
||||
|
||||
// does this model tree element contain the old model
|
||||
bool StoreEntityOperator::subTreeContainsOldEntity(OctreeElement* element) {
|
||||
bool containsEntity = false;
|
||||
|
||||
// If we don't have an old model, then we don't contain the model, otherwise
|
||||
// check the bounds
|
||||
if (_oldEntity) {
|
||||
AACube elementCube = element->getAACube();
|
||||
AACube modelCube = _oldEntity->getAACube();
|
||||
containsEntity = elementCube.contains(modelCube);
|
||||
}
|
||||
return containsEntity;
|
||||
}
|
||||
|
||||
bool StoreEntityOperator::subTreeContainsNewEntity(OctreeElement* element) {
|
||||
AACube elementCube = element->getAACube();
|
||||
AACube modelCube = _newEntity.getAACube();
|
||||
return elementCube.contains(modelCube);
|
||||
}
|
||||
|
||||
|
||||
bool StoreEntityOperator::PreRecursion(OctreeElement* element) {
|
||||
EntityTreeElement* modelTreeElement = static_cast<EntityTreeElement*>(element);
|
||||
|
||||
// In Pre-recursion, we're generally deciding whether or not we want to recurse this
|
||||
// path of the tree. For this operation, we want to recurse the branch of the tree if
|
||||
// and of the following are true:
|
||||
// * We have not yet found the old model, and this branch contains our old model
|
||||
// * We have not yet found the new model, and this branch contains our new model
|
||||
//
|
||||
// Note: it's often the case that the branch in question contains both the old model
|
||||
// and the new model.
|
||||
|
||||
bool keepSearching = false; // assume we don't need to search any more
|
||||
|
||||
// If we haven't yet found the old model, and this subTreeContains our old
|
||||
// model, then we need to keep searching.
|
||||
if (!_foundOld && subTreeContainsOldEntity(element)) {
|
||||
|
||||
// If this is the element we're looking for, then ask it to remove the old model
|
||||
// and we can stop searching.
|
||||
if (modelTreeElement == _containingElement) {
|
||||
|
||||
// If the containgElement IS NOT the best fit for the new model properties
|
||||
// then we need to remove it, and the updateEntity below will store it in the
|
||||
// correct element.
|
||||
if (!_containingElement->bestFitEntityBounds(&_newEntity)) {
|
||||
modelTreeElement->removeEntityWithEntityItemID(_newEntity.getEntityItemID());
|
||||
|
||||
// If we haven't yet found the new location, then we need to
|
||||
// make sure to remove our model to element map, because for
|
||||
// now we're not in that map
|
||||
if (!_foundNew) {
|
||||
_tree->setContainingElement(_newEntity.getEntityItemID(), NULL);
|
||||
}
|
||||
}
|
||||
_foundOld = true;
|
||||
} else {
|
||||
// if this isn't the element we're looking for, then keep searching
|
||||
keepSearching = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If we haven't yet found the new model, and this subTreeContains our new
|
||||
// model, then we need to keep searching.
|
||||
if (!_foundNew && subTreeContainsNewEntity(element)) {
|
||||
|
||||
// Note: updateEntity() will only operate on correctly found models and/or add them
|
||||
// to the element if they SHOULD be stored there.
|
||||
if (modelTreeElement->updateEntity(_newEntity)) {
|
||||
//qDebug() << "StoreEntityOperator::PreRecursion()... model was updated!";
|
||||
_foundNew = true;
|
||||
// NOTE: don't change the keepSearching here, if it came in here
|
||||
// false then we stay false, if it came in here true, then it
|
||||
// means we're still searching for our old model and this branch
|
||||
// contains our old model. In which case we want to keep searching.
|
||||
|
||||
} else {
|
||||
keepSearching = true;
|
||||
}
|
||||
}
|
||||
|
||||
return keepSearching; // if we haven't yet found it, keep looking
|
||||
}
|
||||
|
||||
bool StoreEntityOperator::PostRecursion(OctreeElement* element) {
|
||||
// Post-recursion is the unwinding process. For this operation, while we
|
||||
// unwind we want to mark the path as being dirty if we changed it below.
|
||||
// We might have two paths, one for the old model and one for the new model.
|
||||
bool keepSearching = !_foundOld || !_foundNew;
|
||||
|
||||
// As we unwind, if we're in either of these two paths, we mark our element
|
||||
// as dirty.
|
||||
if ((_foundOld && subTreeContainsOldEntity(element)) ||
|
||||
(_foundNew && subTreeContainsNewEntity(element))) {
|
||||
element->markWithChangedTime();
|
||||
}
|
||||
return keepSearching; // if we haven't yet found it, keep looking
|
||||
}
|
||||
|
||||
OctreeElement* StoreEntityOperator::PossiblyCreateChildAt(OctreeElement* element, int childIndex) {
|
||||
// If we're getting called, it's because there was no child element at this index while recursing.
|
||||
// We only care if this happens while still searching for the new model location.
|
||||
// Check to see if
|
||||
if (!_foundNew) {
|
||||
int indexOfChildContainingNewEntity = element->getMyChildContaining(_newEntity.getAACube());
|
||||
|
||||
if (childIndex == indexOfChildContainingNewEntity) {
|
||||
return element->addChildAtIndex(childIndex);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void EntityTree::storeEntity(const EntityItem& model, const SharedNodePointer& senderNode) {
|
||||
// NOTE: callers must lock the tree before using this method
|
||||
|
||||
// First, look for the existing model in the tree..
|
||||
StoreEntityOperator theOperator(this, model);
|
||||
|
||||
recurseTreeWithOperator(&theOperator);
|
||||
_isDirty = true;
|
||||
|
||||
bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
EntityTreeElement* containingElement = getContainingElement(model.getEntityItemID());
|
||||
qDebug() << "EntityTree::storeEntity().... after store... containingElement=" << containingElement;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Give an EntityItemID and EntityItemProperties, this will either find the correct entity that already exists
|
||||
/// in the tree or it will create a new entity of the type specified by the properties and return that item.
|
||||
/// In the case that it creates a new item, the item will be properly added to the tree and all appropriate lookup hashes.
|
||||
EntityItem* EntityTree::getOrCreateEntityItem(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItem* result = NULL;
|
||||
|
||||
|
@ -232,12 +54,111 @@ EntityItem* EntityTree::getOrCreateEntityItem(const EntityItemID& entityID, cons
|
|||
|
||||
// if the element does not exist, then create a new one of the specified type...
|
||||
if (!result) {
|
||||
EntityTypes::EntityType_t type = properties.getType();
|
||||
result = EntityTypes::constructEntityItem(type, entityID, properties);
|
||||
result = addEntity(entityID, properties);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
class AddEntityOperator : public RecurseOctreeOperator {
|
||||
public:
|
||||
AddEntityOperator(EntityTree* tree, EntityItem* newEntity);
|
||||
|
||||
virtual bool PreRecursion(OctreeElement* element);
|
||||
virtual bool PostRecursion(OctreeElement* element);
|
||||
virtual OctreeElement* PossiblyCreateChildAt(OctreeElement* element, int childIndex);
|
||||
private:
|
||||
EntityTree* _tree;
|
||||
EntityItem* _newEntity;
|
||||
bool _foundNew;
|
||||
quint64 _changeTime;
|
||||
|
||||
AACube _newEntityCube;
|
||||
};
|
||||
|
||||
AddEntityOperator::AddEntityOperator(EntityTree* tree,
|
||||
EntityItem* newEntity) :
|
||||
_tree(tree),
|
||||
_newEntity(newEntity),
|
||||
_foundNew(false),
|
||||
_changeTime(usecTimestampNow()),
|
||||
_newEntityCube()
|
||||
{
|
||||
// caller must have verified existence of newEntity
|
||||
assert(_newEntity);
|
||||
|
||||
_newEntityCube = _newEntity->getAACube();
|
||||
}
|
||||
|
||||
bool AddEntityOperator::PreRecursion(OctreeElement* element) {
|
||||
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
|
||||
|
||||
// In Pre-recursion, we're generally deciding whether or not we want to recurse this
|
||||
// path of the tree. For this operation, we want to recurse the branch of the tree if
|
||||
// and of the following are true:
|
||||
// * We have not yet found the location for the new entity, and this branch contains the bounds of the new entity
|
||||
|
||||
bool keepSearching = false; // assume we don't need to search any more
|
||||
|
||||
// If we haven't yet found the new model, and this subTreeContains our new
|
||||
// model, then we need to keep searching.
|
||||
if (!_foundNew && element->getAACube().contains(_newEntityCube)) {
|
||||
|
||||
// If this element is the best fit for the new entity properties, then add/or update it
|
||||
if (entityTreeElement->bestFitBounds(_newEntityCube)) {
|
||||
entityTreeElement->addEntityItem(_newEntity);
|
||||
_tree->setContainingElement(_newEntity->getEntityItemID(), entityTreeElement);
|
||||
_foundNew = true;
|
||||
keepSearching = false;
|
||||
} else {
|
||||
keepSearching = true;
|
||||
}
|
||||
}
|
||||
|
||||
return keepSearching; // if we haven't yet found it, keep looking
|
||||
}
|
||||
|
||||
bool AddEntityOperator::PostRecursion(OctreeElement* element) {
|
||||
// Post-recursion is the unwinding process. For this operation, while we
|
||||
// unwind we want to mark the path as being dirty if we changed it below.
|
||||
// We might have two paths, one for the old model and one for the new model.
|
||||
bool keepSearching = !_foundNew;
|
||||
|
||||
// As we unwind, if we're in either of these two paths, we mark our element
|
||||
// as dirty.
|
||||
if ((_foundNew && element->getAACube().contains(_newEntityCube))) {
|
||||
element->markWithChangedTime();
|
||||
}
|
||||
return keepSearching; // if we haven't yet found it, keep looking
|
||||
}
|
||||
|
||||
OctreeElement* AddEntityOperator::PossiblyCreateChildAt(OctreeElement* element, int childIndex) {
|
||||
// If we're getting called, it's because there was no child element at this index while recursing.
|
||||
// We only care if this happens while still searching for the new model location.
|
||||
// Check to see if
|
||||
if (!_foundNew) {
|
||||
int indexOfChildContainingNewEntity = element->getMyChildContaining(_newEntityCube);
|
||||
|
||||
if (childIndex == indexOfChildContainingNewEntity) {
|
||||
return element->addChildAtIndex(childIndex);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// Adds a new entity item to the tree
|
||||
void EntityTree::addEntityItem(EntityItem* entityItem) {
|
||||
// You should not call this on existing entities that are already part of the tree! Call updateEntity()
|
||||
EntityItemID entityID = entityItem->getEntityItemID();
|
||||
EntityTreeElement* containingElement = getContainingElement(entityID);
|
||||
assert(containingElement == NULL); // don't call addEntityItem() on existing entity items
|
||||
|
||||
// Recurse the tree and store the entity in the correct tree element
|
||||
AddEntityOperator theOperator(this, entityItem);
|
||||
|
||||
recurseTreeWithOperator(&theOperator);
|
||||
_isDirty = true;
|
||||
}
|
||||
|
||||
|
||||
class UpdateEntityOperator : public RecurseOctreeOperator {
|
||||
public:
|
||||
|
@ -293,7 +214,7 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree,
|
|||
_foundOld = true;
|
||||
_newEntityCube = _oldEntityCube;
|
||||
} else {
|
||||
_newEntityCube = properties.getAACube();
|
||||
_newEntityCube = properties.getAACubeTreeUnits();
|
||||
_removeOld = true; // our properties are going to move us, so remember this for later processing
|
||||
}
|
||||
|
||||
|
@ -334,7 +255,7 @@ bool UpdateEntityOperator::PreRecursion(OctreeElement* element) {
|
|||
// If the containgElement IS NOT the best fit for the new model properties
|
||||
// then we need to remove it, and the updateEntity below will store it in the
|
||||
// correct element.
|
||||
if (!_removeOld) {
|
||||
if (_removeOld) {
|
||||
entityTreeElement->removeEntityItem(_existingEntity); // NOTE: only removes the entity, doesn't delete it
|
||||
|
||||
// If we haven't yet found the new location, then we need to
|
||||
|
@ -403,69 +324,47 @@ OctreeElement* UpdateEntityOperator::PossiblyCreateChildAt(OctreeElement* elemen
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// NOTE: This should only be called on entities that are known to exist. If the entity can not be found, the method
|
||||
// will exit without any changes to tree state
|
||||
//
|
||||
// NOTE: If the properties contain position/scale/rotation, then there is a potential that the entity could need to
|
||||
// move to a different EntityTreeElement, otherwise it will not move. If the entity can not move, then the dirty path
|
||||
// can be determined to just be the path to the entity
|
||||
void EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
|
||||
#if 0
|
||||
EntityItem* updateItem = NULL;
|
||||
|
||||
bool entityMightMove = properties.containsBoundsProperties();
|
||||
|
||||
// since the properties might not be complete, they may only contain some values,
|
||||
// we need to first see if we already have the entity in our tree, and make a copy of
|
||||
// its existing properties first
|
||||
bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
bool updated = false;
|
||||
// You should not call this on existing entities that are already part of the tree! Call updateEntity()
|
||||
EntityTreeElement* containingElement = getContainingElement(entityID);
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "EntityTree::updateEntity(entityID, properties) containingElement=" << containingElement;
|
||||
if (!containingElement) {
|
||||
assert(containingElement); // don't call updateEntity() on entity items that don't exist
|
||||
return false;
|
||||
}
|
||||
|
||||
if (containingElement) {
|
||||
const EntityItem* oldEntity = containingElement->getEntityWithEntityItemID(entityID);
|
||||
if (oldEntity) {
|
||||
EntityItemProperties oldProps = oldEntity->getProperties();
|
||||
if (wantDebug) {
|
||||
qDebug() << "EntityTree::updateEntity(entityID, properties) ********** COPY PROPERTIES FROM oldEntity=" << oldEntity << "*******************";
|
||||
qDebug() << "EntityTree::updateEntity(entityID, properties) oldEntity=" << oldEntity;
|
||||
oldProps.debugDump();
|
||||
qDebug() << "EntityTree::updateEntity(entityID, properties) line:" << __LINE__ << "about to call updateItem.setProperties(oldProps);";
|
||||
}
|
||||
updateItem.setProperties(oldProps, true); // force copy
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "EntityTree::updateEntity(entityID, properties) line:" << __LINE__ << "updateItem:";
|
||||
updateItem.debugDump();
|
||||
}
|
||||
|
||||
} else {
|
||||
if (wantDebug) {
|
||||
qDebug() << "EntityTree::updateEntity(entityID, properties) WAIT WHAT!!! COULDN'T FIND oldEntity=" << oldEntity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (updateItem) {
|
||||
updateItem.setProperties(properties);
|
||||
|
||||
if (wantDebug) {
|
||||
qDebug() << "EntityTree::updateEntity(entityID, properties) line:" << __LINE__ << "updateItem:";
|
||||
updateItem.debugDump();
|
||||
EntityItem* existingEntity = containingElement->getEntityWithEntityItemID(entityID);
|
||||
if (!existingEntity) {
|
||||
assert(existingEntity); // don't call updateEntity() on entity items that don't exist
|
||||
return false;
|
||||
}
|
||||
|
||||
storeEntity(updateItem);
|
||||
#endif
|
||||
UpdateEntityOperator theOperator(this, containingElement, existingEntity, properties);
|
||||
|
||||
recurseTreeWithOperator(&theOperator);
|
||||
_isDirty = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EntityTree::addEntity(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
#if 0
|
||||
EntityItem updateItem(entityID, properties);
|
||||
storeEntity(updateItem);
|
||||
#endif
|
||||
EntityItem* EntityTree::addEntity(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItem* result = NULL;
|
||||
// You should not call this on existing entities that are already part of the tree! Call updateEntity()
|
||||
EntityTreeElement* containingElement = getContainingElement(entityID);
|
||||
if (containingElement) {
|
||||
assert(containingElement == NULL); // don't call addEntity() on existing entity items
|
||||
return result;
|
||||
}
|
||||
|
||||
// construct the instance of the entity
|
||||
EntityTypes::EntityType_t type = properties.getType();
|
||||
result = EntityTypes::constructEntityItem(type, entityID, properties);
|
||||
if (result) {
|
||||
// this does the actual adding of the entity
|
||||
addEntityItem(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
class EntityToDeleteDetails {
|
||||
|
@ -487,7 +386,7 @@ class DeleteEntityOperator : public RecurseOctreeOperator {
|
|||
public:
|
||||
DeleteEntityOperator(EntityTree* tree);
|
||||
DeleteEntityOperator(EntityTree* tree, const EntityItemID& searchEntityID);
|
||||
void modelToDelete(const EntityItemID& searchEntityID);
|
||||
void addEntityIDToDeleteList(const EntityItemID& searchEntityID);
|
||||
virtual bool PreRecursion(OctreeElement* element);
|
||||
virtual bool PostRecursion(OctreeElement* element);
|
||||
private:
|
||||
|
@ -505,7 +404,7 @@ DeleteEntityOperator::DeleteEntityOperator(EntityTree* tree, const EntityItemID&
|
|||
_foundCount(0),
|
||||
_lookingCount(0)
|
||||
{
|
||||
modelToDelete(searchEntityID);
|
||||
addEntityIDToDeleteList(searchEntityID);
|
||||
}
|
||||
|
||||
DeleteEntityOperator::DeleteEntityOperator(EntityTree* tree) :
|
||||
|
@ -516,7 +415,7 @@ DeleteEntityOperator::DeleteEntityOperator(EntityTree* tree) :
|
|||
{
|
||||
}
|
||||
|
||||
void DeleteEntityOperator::modelToDelete(const EntityItemID& searchEntityID) {
|
||||
void DeleteEntityOperator::addEntityIDToDeleteList(const EntityItemID& searchEntityID) {
|
||||
// check our tree, to determine if this model is known
|
||||
EntityToDeleteDetails details;
|
||||
details.containingElement = _tree->getContainingElement(searchEntityID);
|
||||
|
@ -629,7 +528,7 @@ void EntityTree::deleteEntitys(QSet<EntityItemID> modelIDs) {
|
|||
DeleteEntityOperator theOperator(this);
|
||||
foreach(const EntityItemID& entityID, modelIDs) {
|
||||
// First, look for the existing model in the tree..
|
||||
theOperator.modelToDelete(entityID);
|
||||
theOperator.addEntityIDToDeleteList(entityID);
|
||||
}
|
||||
|
||||
recurseTreeWithOperator(&theOperator);
|
||||
|
@ -854,7 +753,6 @@ EntityItem* EntityTree::findEntityByEntityItemID(const EntityItemID& entityID) c
|
|||
return foundEntity;
|
||||
}
|
||||
|
||||
|
||||
int EntityTree::processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength,
|
||||
const unsigned char* editData, int maxLength, const SharedNodePointer& senderNode) {
|
||||
|
||||
|
@ -941,6 +839,9 @@ void EntityTree::update() {
|
|||
int movingEntitys = args._movingEntities.size();
|
||||
|
||||
for (int i = 0; i < movingEntitys; i++) {
|
||||
|
||||
// XXXBHG: replace storeEntity with new API!!
|
||||
#if 0 //////////////////////////////////////////////////////
|
||||
bool shouldDie = args._movingEntities[i]->getShouldBeDeleted();
|
||||
|
||||
// if the particle is still inside our total bounds, then re-add it
|
||||
|
@ -955,6 +856,7 @@ void EntityTree::update() {
|
|||
_recentlyDeletedEntityItemIDs.insert(deletedAt, entityItemID);
|
||||
_recentlyDeletedEntitysLock.unlock();
|
||||
}
|
||||
#endif // 0 //////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
// prune the tree...
|
||||
|
|
|
@ -50,11 +50,16 @@ public:
|
|||
virtual bool rootElementHasData() const { return true; }
|
||||
virtual void update();
|
||||
|
||||
// The newer API...
|
||||
EntityItem* getOrCreateEntityItem(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
void addEntityItem(EntityItem* entityItem);
|
||||
EntityItem* addEntity(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
bool updateEntity(const EntityItemID& modelID, const EntityItemProperties& properties);
|
||||
|
||||
|
||||
// the old API
|
||||
void storeEntity(const EntityItem& model, const SharedNodePointer& senderNode = SharedNodePointer());
|
||||
void updateEntity(const EntityItemID& modelID, const EntityItemProperties& properties);
|
||||
void addEntity(const EntityItemID& modelID, const EntityItemProperties& properties);
|
||||
//void updateEntity(const EntityItemID& modelID, const EntityItemProperties& properties);
|
||||
void deleteEntity(const EntityItemID& modelID);
|
||||
void deleteEntitys(QSet<EntityItemID> modelIDs);
|
||||
const EntityItem* findClosestEntity(glm::vec3 position, float targetRadius);
|
||||
|
|
|
@ -183,11 +183,11 @@ bool EntityTreeElement::bestFitEntityBounds(const EntityItem* entity) const {
|
|||
}
|
||||
|
||||
bool EntityTreeElement::containsBounds(const EntityItemProperties& properties) const {
|
||||
return containsBounds(properties.getMinimumPoint(), properties.getMaximumPoint());
|
||||
return containsBounds(properties.getMinimumPointTreeUnits(), properties.getMaximumPointTreeUnits());
|
||||
}
|
||||
|
||||
bool EntityTreeElement::bestFitBounds(const EntityItemProperties& properties) const {
|
||||
return bestFitBounds(properties.getMinimumPoint(), properties.getMaximumPoint());
|
||||
return bestFitBounds(properties.getMinimumPointTreeUnits(), properties.getMaximumPointTreeUnits());
|
||||
}
|
||||
|
||||
bool EntityTreeElement::containsBounds(const AACube& bounds) const {
|
||||
|
@ -403,6 +403,7 @@ bool EntityTreeElement::addOrUpdateEntity(EntityItem* entity, const EntityItemPr
|
|||
|
||||
// If we didn't find the entity here, then let's check to see if we should add it...
|
||||
_entityItems->push_back(entity);
|
||||
entity->setProperties(properties); // still need to update the properties!
|
||||
markWithChangedTime();
|
||||
// Since we're adding this item to this element, we need to let the tree know about it
|
||||
_myTree->setContainingElement(entity->getEntityItemID(), this);
|
||||
|
@ -410,75 +411,6 @@ bool EntityTreeElement::addOrUpdateEntity(EntityItem* entity, const EntityItemPr
|
|||
return true;
|
||||
}
|
||||
|
||||
// TODO: the old entity code has support for sittingPoints... need to determine how to handle this...
|
||||
// for local editors, the old updateModels(id, properties) had this code...
|
||||
// if (found) {
|
||||
// thisModel.setProperties(properties);
|
||||
// if (_myTree->getGeometryForModel(thisModel)) {
|
||||
// thisModel.setSittingPoints(_myTree->getGeometryForModel(thisModel)->sittingPoints);
|
||||
// }
|
||||
// ...
|
||||
#if 0
|
||||
bool EntityTreeElement::updateEntity(const EntityItem& entity) {
|
||||
const bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
EntityItemID entityItemID = entity.getEntityItemID();
|
||||
qDebug() << "EntityTreeElement::updateEntity(entity) entityID.id="
|
||||
<< entityItemID.id << "creatorTokenID=" << entityItemID.creatorTokenID;
|
||||
}
|
||||
|
||||
// NOTE: this method must first lookup the entity by ID, hence it is O(N)
|
||||
// and "entity is not found" is worst-case (full N) but maybe we don't care?
|
||||
// (guaranteed that num entities per elemen is small?)
|
||||
uint16_t numberOfEntities = _entityItems->size();
|
||||
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
||||
EntityItem* thisEntity = (*_entityItems)[i];
|
||||
if (thisEntity->getID() == entity.getID()) {
|
||||
if (wantDebug) {
|
||||
qDebug() << "found entity with id";
|
||||
}
|
||||
int difference = thisEntity->getLastUpdated() - entity.getLastUpdated();
|
||||
bool changedOnServer = thisEntity->getLastEdited() <= entity.getLastEdited();
|
||||
bool localOlder = thisEntity->getLastUpdated() < entity.getLastUpdated();
|
||||
if (changedOnServer || localOlder) {
|
||||
if (wantDebug) {
|
||||
qDebug("local entity [id:%d] %s and %s than server entity by %d, entity.isNewlyCreated()=%s",
|
||||
entity.getID(), (changedOnServer ? "CHANGED" : "same"),
|
||||
(localOlder ? "OLDER" : "NEWER"),
|
||||
difference, debug::valueOf(entity.isNewlyCreated()) );
|
||||
}
|
||||
|
||||
thisEntity->copyChangedProperties(entity);
|
||||
markWithChangedTime();
|
||||
|
||||
// seems like we shouldn't need this
|
||||
_myTree->setContainingElement(entity.getEntityItemID(), this);
|
||||
} else {
|
||||
if (wantDebug) {
|
||||
qDebug(">>> IGNORING SERVER!!! Would've caused jutter! <<< "
|
||||
"local entity [id:%d] %s and %s than server entity by %d, entity.isNewlyCreated()=%s",
|
||||
entity.getID(), (changedOnServer ? "CHANGED" : "same"),
|
||||
(localOlder ? "OLDER" : "NEWER"),
|
||||
difference, debug::valueOf(entity.isNewlyCreated()) );
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't find the entity here, then let's check to see if we should add it...
|
||||
if (bestFitEntityBounds(entity)) {
|
||||
_entityItems->push_back(entity);
|
||||
markWithChangedTime();
|
||||
// Since we're adding this item to this element, we need to let the tree know about it
|
||||
_myTree->setContainingElement(entity.getEntityItemID(), this);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void EntityTreeElement::updateEntityItemID(FindAndUpdateEntityItemIDArgs* args) {
|
||||
bool wantDebug = false;
|
||||
uint16_t numberOfEntities = _entityItems->size();
|
||||
|
@ -519,8 +451,6 @@ void EntityTreeElement::updateEntityItemID(FindAndUpdateEntityItemIDArgs* args)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const EntityItem* EntityTreeElement::getClosestEntity(glm::vec3 position) const {
|
||||
const EntityItem* closestEntity = NULL;
|
||||
float closestEntityDistance = FLT_MAX;
|
||||
|
|
|
@ -152,14 +152,14 @@ public:
|
|||
bool containsEntityBounds(const EntityItem* entity) const;
|
||||
bool bestFitEntityBounds(const EntityItem* entity) const;
|
||||
|
||||
bool containsBounds(const EntityItemProperties& properties) const;
|
||||
bool bestFitBounds(const EntityItemProperties& properties) const;
|
||||
bool containsBounds(const EntityItemProperties& properties) const; // NOTE: property units in meters
|
||||
bool bestFitBounds(const EntityItemProperties& properties) const; // NOTE: property units in meters
|
||||
|
||||
bool containsBounds(const AACube& bounds) const;
|
||||
bool bestFitBounds(const AACube& bounds) const;
|
||||
bool containsBounds(const AACube& bounds) const; // NOTE: units in tree units
|
||||
bool bestFitBounds(const AACube& bounds) const; // NOTE: units in tree units
|
||||
|
||||
bool containsBounds(const glm::vec3& minPoint, const glm::vec3& maxPoint) const;
|
||||
bool bestFitBounds(const glm::vec3& minPoint, const glm::vec3& maxPoint) const;
|
||||
bool containsBounds(const glm::vec3& minPoint, const glm::vec3& maxPoint) const; // NOTE: units in tree units
|
||||
bool bestFitBounds(const glm::vec3& minPoint, const glm::vec3& maxPoint) const; // NOTE: units in tree units
|
||||
|
||||
protected:
|
||||
virtual void init(unsigned char * octalCode);
|
||||
|
|
|
@ -25,8 +25,9 @@
|
|||
//#include "EntityTests.h"
|
||||
#include "ModelTests.h" // needs to be EntityTests.h soon
|
||||
|
||||
void EntityTests::modelTreeTests(bool verbose) {
|
||||
#ifdef HIDE_SUBCLASS_METHODS
|
||||
void EntityTests::entityTreeTests(bool verbose) {
|
||||
|
||||
//#ifdef HIDE_SUBCLASS_METHODS
|
||||
bool extraVerbose = false;
|
||||
int testsTaken = 0;
|
||||
int testsPassed = 0;
|
||||
|
@ -36,13 +37,13 @@ void EntityTests::modelTreeTests(bool verbose) {
|
|||
qDebug() << "******************************************************************************************";
|
||||
}
|
||||
|
||||
qDebug() << "EntityTests::modelTreeTests()";
|
||||
qDebug() << "EntityTests::entityTreeTests()";
|
||||
|
||||
// Tree, id, and model properties used in many tests below...
|
||||
// Tree, id, and entity properties used in many tests below...
|
||||
EntityTree tree;
|
||||
uint32_t id = 1;
|
||||
EntityItemID modelID(id);
|
||||
modelID.isKnownID = false; // this is a temporary workaround to allow local tree models to be added with known IDs
|
||||
EntityItemID entityID(id);
|
||||
entityID.isKnownID = false; // this is a temporary workaround to allow local tree entities to be added with known IDs
|
||||
EntityItemProperties properties;
|
||||
float oneMeter = 1.0f;
|
||||
float halfMeter = oneMeter / 2.0f;
|
||||
|
@ -54,21 +55,21 @@ void EntityTests::modelTreeTests(bool verbose) {
|
|||
|
||||
{
|
||||
testsTaken++;
|
||||
QString testName = "add model to tree and search";
|
||||
QString testName = "add entity to tree and search";
|
||||
if (verbose) {
|
||||
qDebug() << "Test" << testsTaken <<":" << qPrintable(testName);
|
||||
}
|
||||
|
||||
properties.setPosition(positionAtCenterInMeters);
|
||||
properties.setRadius(halfMeter);
|
||||
//properties.setModelURL("https://s3-us-west-1.amazonaws.com/highfidelity-public/ozan/theater.fbx");
|
||||
//properties.setModelURL("https://s3-us-west-1.amazonaws.com/highfidelity-public/ozan/theater.fbx");
|
||||
|
||||
tree.addEntity(modelID, properties);
|
||||
tree.addEntity(entityID, properties);
|
||||
|
||||
float targetRadius = oneMeter * 2.0 / (float)TREE_SCALE; // in tree units
|
||||
const EntityItem* foundEntityByRadius = tree.findClosestEntity(positionAtCenterInTreeUnits, targetRadius);
|
||||
const EntityItem* foundEntityByID = tree.findEntityByID(id);
|
||||
EntityTreeElement* containingElement = tree.getContainingElement(modelID);
|
||||
EntityTreeElement* containingElement = tree.getContainingElement(entityID);
|
||||
AACube elementCube = containingElement ? containingElement->getAACube() : AACube();
|
||||
|
||||
if (verbose) {
|
||||
|
@ -93,11 +94,11 @@ void EntityTests::modelTreeTests(bool verbose) {
|
|||
}
|
||||
}
|
||||
|
||||
modelID.isKnownID = true; // this is a temporary workaround to allow local tree models to be added with known IDs
|
||||
entityID.isKnownID = true; // this is a temporary workaround to allow local tree entities to be added with known IDs
|
||||
|
||||
{
|
||||
testsTaken++;
|
||||
QString testName = "change position of model in tree";
|
||||
QString testName = "change position of entity in tree";
|
||||
if (verbose) {
|
||||
qDebug() << "Test" << testsTaken <<":" << qPrintable(testName);
|
||||
}
|
||||
|
@ -106,12 +107,12 @@ void EntityTests::modelTreeTests(bool verbose) {
|
|||
|
||||
properties.setPosition(newPosition);
|
||||
|
||||
tree.updateEntity(modelID, properties);
|
||||
tree.updateEntity(entityID, properties);
|
||||
|
||||
float targetRadius = oneMeter * 2.0 / (float)TREE_SCALE; // in tree units
|
||||
const EntityItem* foundEntityByRadius = tree.findClosestEntity(positionNearOriginInTreeUnits, targetRadius);
|
||||
const EntityItem* foundEntityByID = tree.findEntityByID(id);
|
||||
EntityTreeElement* containingElement = tree.getContainingElement(modelID);
|
||||
EntityTreeElement* containingElement = tree.getContainingElement(entityID);
|
||||
AACube elementCube = containingElement ? containingElement->getAACube() : AACube();
|
||||
|
||||
if (verbose) {
|
||||
|
@ -137,7 +138,7 @@ void EntityTests::modelTreeTests(bool verbose) {
|
|||
|
||||
{
|
||||
testsTaken++;
|
||||
QString testName = "change position of model in tree back to center";
|
||||
QString testName = "change position of entity in tree back to center";
|
||||
if (verbose) {
|
||||
qDebug() << "Test" << testsTaken <<":" << qPrintable(testName);
|
||||
}
|
||||
|
@ -146,12 +147,12 @@ void EntityTests::modelTreeTests(bool verbose) {
|
|||
|
||||
properties.setPosition(newPosition);
|
||||
|
||||
tree.updateEntity(modelID, properties);
|
||||
tree.updateEntity(entityID, properties);
|
||||
|
||||
float targetRadius = oneMeter * 2.0 / (float)TREE_SCALE; // in tree units
|
||||
const EntityItem* foundEntityByRadius = tree.findClosestEntity(positionAtCenterInTreeUnits, targetRadius);
|
||||
const EntityItem* foundEntityByID = tree.findEntityByID(id);
|
||||
EntityTreeElement* containingElement = tree.getContainingElement(modelID);
|
||||
EntityTreeElement* containingElement = tree.getContainingElement(entityID);
|
||||
AACube elementCube = containingElement ? containingElement->getAACube() : AACube();
|
||||
|
||||
if (verbose) {
|
||||
|
@ -244,7 +245,7 @@ void EntityTests::modelTreeTests(bool verbose) {
|
|||
|
||||
testsTaken++;
|
||||
const int TEST_ITERATIONS = 1000;
|
||||
QString testName = "Performance - add model to tree " + QString::number(TEST_ITERATIONS) + " times";
|
||||
QString testName = "Performance - add entity to tree " + QString::number(TEST_ITERATIONS) + " times";
|
||||
if (verbose) {
|
||||
qDebug() << "Test" << testsTaken <<":" << qPrintable(testName);
|
||||
}
|
||||
|
@ -253,9 +254,9 @@ void EntityTests::modelTreeTests(bool verbose) {
|
|||
quint64 totalElapsedAdd = 0;
|
||||
quint64 totalElapsedFind = 0;
|
||||
for (int i = 0; i < TEST_ITERATIONS; i++) {
|
||||
uint32_t id = i + 2; // make sure it doesn't collide with previous model ids
|
||||
EntityItemID modelID(id);
|
||||
modelID.isKnownID = false; // this is a temporary workaround to allow local tree models to be added with known IDs
|
||||
uint32_t id = i + 2; // make sure it doesn't collide with previous entity ids
|
||||
EntityItemID entityID(id);
|
||||
entityID.isKnownID = false; // this is a temporary workaround to allow local tree entities to be added with known IDs
|
||||
|
||||
float randomX = randFloatInRange(1.0f ,(float)TREE_SCALE - 1.0f);
|
||||
float randomY = randFloatInRange(1.0f ,(float)TREE_SCALE - 1.0f);
|
||||
|
@ -269,12 +270,12 @@ void EntityTests::modelTreeTests(bool verbose) {
|
|||
|
||||
if (extraVerbose) {
|
||||
qDebug() << "iteration:" << i
|
||||
<< "ading model at x/y/z=" << randomX << "," << randomY << "," << randomZ;
|
||||
<< "ading entity at x/y/z=" << randomX << "," << randomY << "," << randomZ;
|
||||
qDebug() << "before:" << i << "getOctreeElementsCount()=" << tree.getOctreeElementsCount();
|
||||
}
|
||||
|
||||
quint64 startAdd = usecTimestampNow();
|
||||
tree.addEntity(modelID, properties);
|
||||
tree.addEntity(entityID, properties);
|
||||
quint64 endAdd = usecTimestampNow();
|
||||
totalElapsedAdd += (endAdd - startAdd);
|
||||
|
||||
|
@ -289,7 +290,7 @@ void EntityTests::modelTreeTests(bool verbose) {
|
|||
quint64 endFind = usecTimestampNow();
|
||||
totalElapsedFind += (endFind - startFind);
|
||||
|
||||
EntityTreeElement* containingElement = tree.getContainingElement(modelID);
|
||||
EntityTreeElement* containingElement = tree.getContainingElement(entityID);
|
||||
AACube elementCube = containingElement ? containingElement->getAACube() : AACube();
|
||||
|
||||
bool elementIsBestFit = containingElement->bestFitEntityBounds(foundEntityByID);
|
||||
|
@ -348,7 +349,7 @@ void EntityTests::modelTreeTests(bool verbose) {
|
|||
{
|
||||
testsTaken++;
|
||||
const int TEST_ITERATIONS = 1000;
|
||||
QString testName = "Performance - delete model from tree " + QString::number(TEST_ITERATIONS) + " times";
|
||||
QString testName = "Performance - delete entity from tree " + QString::number(TEST_ITERATIONS) + " times";
|
||||
if (verbose) {
|
||||
qDebug() << "Test" << testsTaken <<":" << qPrintable(testName);
|
||||
}
|
||||
|
@ -357,16 +358,16 @@ void EntityTests::modelTreeTests(bool verbose) {
|
|||
quint64 totalElapsedDelete = 0;
|
||||
quint64 totalElapsedFind = 0;
|
||||
for (int i = 0; i < TEST_ITERATIONS; i++) {
|
||||
uint32_t id = i + 2; // These are the models we added above
|
||||
EntityItemID modelID(id);
|
||||
modelID.isKnownID = true; // this is a temporary workaround to allow local tree models to be added with known IDs
|
||||
uint32_t id = i + 2; // These are the entities we added above
|
||||
EntityItemID entityID(id);
|
||||
entityID.isKnownID = true; // this is a temporary workaround to allow local tree entities to be added with known IDs
|
||||
|
||||
if (extraVerbose) {
|
||||
qDebug() << "before:" << i << "getOctreeElementsCount()=" << tree.getOctreeElementsCount();
|
||||
}
|
||||
|
||||
quint64 startDelete = usecTimestampNow();
|
||||
tree.deleteEntity(modelID);
|
||||
tree.deleteEntity(entityID);
|
||||
quint64 endDelete = usecTimestampNow();
|
||||
totalElapsedDelete += (endDelete - startDelete);
|
||||
|
||||
|
@ -379,7 +380,7 @@ void EntityTests::modelTreeTests(bool verbose) {
|
|||
quint64 endFind = usecTimestampNow();
|
||||
totalElapsedFind += (endFind - startFind);
|
||||
|
||||
EntityTreeElement* containingElement = tree.getContainingElement(modelID);
|
||||
EntityTreeElement* containingElement = tree.getContainingElement(entityID);
|
||||
|
||||
if (extraVerbose) {
|
||||
qDebug() << "foundEntityByID=" << foundEntityByID;
|
||||
|
@ -426,9 +427,9 @@ void EntityTests::modelTreeTests(bool verbose) {
|
|||
{
|
||||
testsTaken++;
|
||||
const int TEST_ITERATIONS = 100;
|
||||
const int MODELS_PER_ITERATION = 10;
|
||||
QString testName = "Performance - delete " + QString::number(MODELS_PER_ITERATION)
|
||||
+ " models from tree " + QString::number(TEST_ITERATIONS) + " times";
|
||||
const int ENTITIES_PER_ITERATION = 10;
|
||||
QString testName = "Performance - delete " + QString::number(ENTITIES_PER_ITERATION)
|
||||
+ " entities from tree " + QString::number(TEST_ITERATIONS) + " times";
|
||||
if (verbose) {
|
||||
qDebug() << "Test" << testsTaken <<":" << qPrintable(testName);
|
||||
}
|
||||
|
@ -438,11 +439,11 @@ void EntityTests::modelTreeTests(bool verbose) {
|
|||
quint64 totalElapsedFind = 0;
|
||||
for (int i = 0; i < TEST_ITERATIONS; i++) {
|
||||
|
||||
QSet<EntityItemID> modelsToDelete;
|
||||
for (int j = 0; j < MODELS_PER_ITERATION; j++) {
|
||||
uint32_t id = 2 + (i * MODELS_PER_ITERATION) + j; // These are the models we added above
|
||||
EntityItemID modelID(id);
|
||||
modelsToDelete << modelID;
|
||||
QSet<EntityItemID> entitiesToDelete;
|
||||
for (int j = 0; j < ENTITIES_PER_ITERATION; j++) {
|
||||
uint32_t id = 2 + (i * ENTITIES_PER_ITERATION) + j; // These are the entities we added above
|
||||
EntityItemID entityID(id);
|
||||
entitiesToDelete << entityID;
|
||||
}
|
||||
|
||||
if (extraVerbose) {
|
||||
|
@ -450,7 +451,7 @@ void EntityTests::modelTreeTests(bool verbose) {
|
|||
}
|
||||
|
||||
quint64 startDelete = usecTimestampNow();
|
||||
tree.deleteEntitys(modelsToDelete);
|
||||
tree.deleteEntitys(entitiesToDelete);
|
||||
quint64 endDelete = usecTimestampNow();
|
||||
totalElapsedDelete += (endDelete - startDelete);
|
||||
|
||||
|
@ -459,11 +460,11 @@ void EntityTests::modelTreeTests(bool verbose) {
|
|||
}
|
||||
|
||||
quint64 startFind = usecTimestampNow();
|
||||
for (int j = 0; j < MODELS_PER_ITERATION; j++) {
|
||||
uint32_t id = 2 + (i * MODELS_PER_ITERATION) + j; // These are the models we added above
|
||||
EntityItemID modelID(id);
|
||||
for (int j = 0; j < ENTITIES_PER_ITERATION; j++) {
|
||||
uint32_t id = 2 + (i * ENTITIES_PER_ITERATION) + j; // These are the entities we added above
|
||||
EntityItemID entityID(id);
|
||||
const EntityItem* foundEntityByID = tree.findEntityByID(id);
|
||||
EntityTreeElement* containingElement = tree.getContainingElement(modelID);
|
||||
EntityTreeElement* containingElement = tree.getContainingElement(entityID);
|
||||
|
||||
if (extraVerbose) {
|
||||
qDebug() << "foundEntityByID=" << foundEntityByID;
|
||||
|
@ -490,7 +491,7 @@ void EntityTests::modelTreeTests(bool verbose) {
|
|||
qDebug() << "getOctreeElementsCount()=" << tree.getOctreeElementsCount();
|
||||
}
|
||||
|
||||
bool passed = iterationsPassed == (TEST_ITERATIONS * MODELS_PER_ITERATION);
|
||||
bool passed = iterationsPassed == (TEST_ITERATIONS * ENTITIES_PER_ITERATION);
|
||||
if (passed) {
|
||||
testsPassed++;
|
||||
} else {
|
||||
|
@ -509,11 +510,12 @@ void EntityTests::modelTreeTests(bool verbose) {
|
|||
if (verbose) {
|
||||
qDebug() << "******************************************************************************************";
|
||||
}
|
||||
#endif
|
||||
//#endif
|
||||
//#endif // 0
|
||||
}
|
||||
|
||||
|
||||
void EntityTests::runAllTests(bool verbose) {
|
||||
modelTreeTests(verbose);
|
||||
entityTreeTests(verbose);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#define hifi_EntityTests_h
|
||||
|
||||
namespace EntityTests {
|
||||
void modelTreeTests(bool verbose = false);
|
||||
void entityTreeTests(bool verbose = false);
|
||||
void runAllTests(bool verbose = false);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue