mirror of
https://github.com/overte-org/overte.git
synced 2025-08-07 00:44:38 +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++) {
|
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
||||||
EntityItem& entityItem = entityItems[i];
|
EntityItem* entityItem = entityItems[i];
|
||||||
// render entityItem aspoints
|
// render entityItem aspoints
|
||||||
AACube entityCube = entityItem.getAACube();
|
AACube entityCube = entityItem->getAACube();
|
||||||
entityCube.scale(TREE_SCALE);
|
entityCube.scale(TREE_SCALE);
|
||||||
if (args->_viewFrustum->cubeInFrustum(entityCube) != ViewFrustum::OUTSIDE) {
|
if (args->_viewFrustum->cubeInFrustum(entityCube) != ViewFrustum::OUTSIDE) {
|
||||||
glm::vec3 position = entityItem.getPosition() * (float)TREE_SCALE;
|
glm::vec3 position = entityItem->getPosition() * (float)TREE_SCALE;
|
||||||
float radius = entityItem.getRadius() * (float)TREE_SCALE;
|
float radius = entityItem->getRadius() * (float)TREE_SCALE;
|
||||||
float size = entityItem.getSize() * (float)TREE_SCALE;
|
float size = entityItem->getSize() * (float)TREE_SCALE;
|
||||||
|
|
||||||
#ifdef HIDE_SUBCLASS_METHODS
|
#ifdef HIDE_SUBCLASS_METHODS
|
||||||
bool drawAsModel = entityItem.hasModel();
|
bool drawAsModel = entityItem->hasModel();
|
||||||
#else
|
#else
|
||||||
bool drawAsModel = false;
|
bool drawAsModel = false;
|
||||||
#endif
|
#endif
|
||||||
|
@ -238,27 +238,27 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
|
||||||
{
|
{
|
||||||
const float alpha = 1.0f;
|
const float alpha = 1.0f;
|
||||||
|
|
||||||
Model* model = getModel(entityItem);
|
Model* model = getModel(*entityItem);
|
||||||
|
|
||||||
if (model) {
|
if (model) {
|
||||||
model->setScaleToFit(true, radius * 2.0f);
|
model->setScaleToFit(true, radius * 2.0f);
|
||||||
model->setSnapModelToCenter(true);
|
model->setSnapModelToCenter(true);
|
||||||
|
|
||||||
// set the rotation
|
// set the rotation
|
||||||
glm::quat rotation = entityItem.getRotation();
|
glm::quat rotation = entityItem->getRotation();
|
||||||
model->setRotation(rotation);
|
model->setRotation(rotation);
|
||||||
|
|
||||||
// set the position
|
// set the position
|
||||||
model->setTranslation(position);
|
model->setTranslation(position);
|
||||||
|
|
||||||
// handle animations..
|
// handle animations..
|
||||||
if (entityItem.hasAnimation()) {
|
if (entityItem->hasAnimation()) {
|
||||||
if (!entityItem.jointsMapped()) {
|
if (!entityItem->jointsMapped()) {
|
||||||
QStringList modelJointNames = model->getJointNames();
|
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++) {
|
for (int i = 0; i < frameData.size(); i++) {
|
||||||
model->setJointState(i, true, frameData[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::RenderMode modelRenderMode = args->_renderMode == OctreeRenderer::SHADOW_RENDER_MODE
|
||||||
? Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE;
|
? Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE;
|
||||||
|
|
||||||
if (entityItem.getGlowLevel() > 0.0f) {
|
if (entityItem->getGlowLevel() > 0.0f) {
|
||||||
Glower glower(entityItem.getGlowLevel());
|
Glower glower(entityItem->getGlowLevel());
|
||||||
|
|
||||||
if (model->isActive()) {
|
if (model->isActive()) {
|
||||||
model->render(alpha, modelRenderMode);
|
model->render(alpha, modelRenderMode);
|
||||||
} else {
|
} else {
|
||||||
// if we couldn't get a model, then just draw a sphere
|
// 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();
|
glPushMatrix();
|
||||||
glTranslatef(position.x, position.y, position.z);
|
glTranslatef(position.x, position.y, position.z);
|
||||||
glutSolidSphere(radius, 15, 15);
|
glutSolidSphere(radius, 15, 15);
|
||||||
|
@ -289,7 +289,7 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
|
||||||
model->render(alpha, modelRenderMode);
|
model->render(alpha, modelRenderMode);
|
||||||
} else {
|
} else {
|
||||||
// if we couldn't get a model, then just draw a sphere
|
// 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();
|
glPushMatrix();
|
||||||
glTranslatef(position.x, position.y, position.z);
|
glTranslatef(position.x, position.y, position.z);
|
||||||
glutSolidSphere(radius, 15, 15);
|
glutSolidSphere(radius, 15, 15);
|
||||||
|
@ -340,7 +340,7 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// if we couldn't get a model, then just draw a sphere
|
// 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();
|
glPushMatrix();
|
||||||
glTranslatef(position.x, position.y, position.z);
|
glTranslatef(position.x, position.y, position.z);
|
||||||
glutSolidSphere(radius, 15, 15);
|
glutSolidSphere(radius, 15, 15);
|
||||||
|
@ -350,7 +350,7 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} 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);
|
glColor3f(1.0f, 0.0f, 0.0f);
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glTranslatef(position.x, position.y, position.z);
|
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) {
|
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) {
|
EntityItem* EntityTypes::constructEntityItem(const unsigned char* data, int bytesToRead) {
|
||||||
|
|
|
@ -74,7 +74,8 @@ public:
|
||||||
Box,
|
Box,
|
||||||
Sphere,
|
Sphere,
|
||||||
Plane,
|
Plane,
|
||||||
Cylinder
|
Cylinder,
|
||||||
|
Pyramid
|
||||||
} EntityType_t;
|
} EntityType_t;
|
||||||
|
|
||||||
static const QString& getEntityTypeName(EntityType_t entityType);
|
static const QString& getEntityTypeName(EntityType_t entityType);
|
||||||
|
@ -128,9 +129,13 @@ public:
|
||||||
/// used by EntityScriptingInterface to return EntityItemProperties for unknown models
|
/// used by EntityScriptingInterface to return EntityItemProperties for unknown models
|
||||||
void setIsUnknownID() { _id = UNKNOWN_ENTITY_ID; _idSet = true; }
|
void setIsUnknownID() { _id = UNKNOWN_ENTITY_ID; _idSet = true; }
|
||||||
|
|
||||||
glm::vec3 getMinimumPoint() const { return _position - glm::vec3(_radius, _radius, _radius); }
|
glm::vec3 getMinimumPointMeters() const { return _position - glm::vec3(_radius, _radius, _radius); }
|
||||||
glm::vec3 getMaximumPoint() const { return _position + glm::vec3(_radius, _radius, _radius); }
|
glm::vec3 getMaximumPointMeters() const { return _position + glm::vec3(_radius, _radius, _radius); }
|
||||||
AACube getAACube() const { return AACube(getMinimumPoint(), getMaxDimension()); } /// AACube in domain scale units (0.0 - 1.0)
|
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;
|
void debugDump() const;
|
||||||
|
|
||||||
// properties of all entities
|
// 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
|
#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
|
/// 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 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* EntityTree::getOrCreateEntityItem(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||||
EntityItem* result = NULL;
|
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 the element does not exist, then create a new one of the specified type...
|
||||||
if (!result) {
|
if (!result) {
|
||||||
EntityTypes::EntityType_t type = properties.getType();
|
result = addEntity(entityID, properties);
|
||||||
result = EntityTypes::constructEntityItem(type, entityID, properties);
|
|
||||||
}
|
}
|
||||||
return result;
|
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 {
|
class UpdateEntityOperator : public RecurseOctreeOperator {
|
||||||
public:
|
public:
|
||||||
|
@ -293,7 +214,7 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree,
|
||||||
_foundOld = true;
|
_foundOld = true;
|
||||||
_newEntityCube = _oldEntityCube;
|
_newEntityCube = _oldEntityCube;
|
||||||
} else {
|
} else {
|
||||||
_newEntityCube = properties.getAACube();
|
_newEntityCube = properties.getAACubeTreeUnits();
|
||||||
_removeOld = true; // our properties are going to move us, so remember this for later processing
|
_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
|
// 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
|
// then we need to remove it, and the updateEntity below will store it in the
|
||||||
// correct element.
|
// correct element.
|
||||||
if (!_removeOld) {
|
if (_removeOld) {
|
||||||
entityTreeElement->removeEntityItem(_existingEntity); // NOTE: only removes the entity, doesn't delete it
|
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
|
// If we haven't yet found the new location, then we need to
|
||||||
|
@ -403,69 +324,47 @@ OctreeElement* UpdateEntityOperator::PossiblyCreateChildAt(OctreeElement* elemen
|
||||||
return NULL;
|
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
|
bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||||
EntityItem* updateItem = NULL;
|
bool updated = false;
|
||||||
|
// You should not call this on existing entities that are already part of the tree! Call updateEntity()
|
||||||
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
|
|
||||||
EntityTreeElement* containingElement = getContainingElement(entityID);
|
EntityTreeElement* containingElement = getContainingElement(entityID);
|
||||||
|
if (!containingElement) {
|
||||||
if (wantDebug) {
|
assert(containingElement); // don't call updateEntity() on entity items that don't exist
|
||||||
qDebug() << "EntityTree::updateEntity(entityID, properties) containingElement=" << containingElement;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (containingElement) {
|
EntityItem* existingEntity = containingElement->getEntityWithEntityItemID(entityID);
|
||||||
const EntityItem* oldEntity = containingElement->getEntityWithEntityItemID(entityID);
|
if (!existingEntity) {
|
||||||
if (oldEntity) {
|
assert(existingEntity); // don't call updateEntity() on entity items that don't exist
|
||||||
EntityItemProperties oldProps = oldEntity->getProperties();
|
return false;
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
storeEntity(updateItem);
|
UpdateEntityOperator theOperator(this, containingElement, existingEntity, properties);
|
||||||
#endif
|
|
||||||
|
recurseTreeWithOperator(&theOperator);
|
||||||
|
_isDirty = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityTree::addEntity(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
EntityItem* EntityTree::addEntity(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||||
#if 0
|
EntityItem* result = NULL;
|
||||||
EntityItem updateItem(entityID, properties);
|
// You should not call this on existing entities that are already part of the tree! Call updateEntity()
|
||||||
storeEntity(updateItem);
|
EntityTreeElement* containingElement = getContainingElement(entityID);
|
||||||
#endif
|
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 {
|
class EntityToDeleteDetails {
|
||||||
|
@ -487,7 +386,7 @@ class DeleteEntityOperator : public RecurseOctreeOperator {
|
||||||
public:
|
public:
|
||||||
DeleteEntityOperator(EntityTree* tree);
|
DeleteEntityOperator(EntityTree* tree);
|
||||||
DeleteEntityOperator(EntityTree* tree, const EntityItemID& searchEntityID);
|
DeleteEntityOperator(EntityTree* tree, const EntityItemID& searchEntityID);
|
||||||
void modelToDelete(const EntityItemID& searchEntityID);
|
void addEntityIDToDeleteList(const EntityItemID& searchEntityID);
|
||||||
virtual bool PreRecursion(OctreeElement* element);
|
virtual bool PreRecursion(OctreeElement* element);
|
||||||
virtual bool PostRecursion(OctreeElement* element);
|
virtual bool PostRecursion(OctreeElement* element);
|
||||||
private:
|
private:
|
||||||
|
@ -505,7 +404,7 @@ DeleteEntityOperator::DeleteEntityOperator(EntityTree* tree, const EntityItemID&
|
||||||
_foundCount(0),
|
_foundCount(0),
|
||||||
_lookingCount(0)
|
_lookingCount(0)
|
||||||
{
|
{
|
||||||
modelToDelete(searchEntityID);
|
addEntityIDToDeleteList(searchEntityID);
|
||||||
}
|
}
|
||||||
|
|
||||||
DeleteEntityOperator::DeleteEntityOperator(EntityTree* tree) :
|
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
|
// check our tree, to determine if this model is known
|
||||||
EntityToDeleteDetails details;
|
EntityToDeleteDetails details;
|
||||||
details.containingElement = _tree->getContainingElement(searchEntityID);
|
details.containingElement = _tree->getContainingElement(searchEntityID);
|
||||||
|
@ -629,7 +528,7 @@ void EntityTree::deleteEntitys(QSet<EntityItemID> modelIDs) {
|
||||||
DeleteEntityOperator theOperator(this);
|
DeleteEntityOperator theOperator(this);
|
||||||
foreach(const EntityItemID& entityID, modelIDs) {
|
foreach(const EntityItemID& entityID, modelIDs) {
|
||||||
// First, look for the existing model in the tree..
|
// First, look for the existing model in the tree..
|
||||||
theOperator.modelToDelete(entityID);
|
theOperator.addEntityIDToDeleteList(entityID);
|
||||||
}
|
}
|
||||||
|
|
||||||
recurseTreeWithOperator(&theOperator);
|
recurseTreeWithOperator(&theOperator);
|
||||||
|
@ -854,7 +753,6 @@ EntityItem* EntityTree::findEntityByEntityItemID(const EntityItemID& entityID) c
|
||||||
return foundEntity;
|
return foundEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int EntityTree::processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength,
|
int EntityTree::processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength,
|
||||||
const unsigned char* editData, int maxLength, const SharedNodePointer& senderNode) {
|
const unsigned char* editData, int maxLength, const SharedNodePointer& senderNode) {
|
||||||
|
|
||||||
|
@ -941,6 +839,9 @@ void EntityTree::update() {
|
||||||
int movingEntitys = args._movingEntities.size();
|
int movingEntitys = args._movingEntities.size();
|
||||||
|
|
||||||
for (int i = 0; i < movingEntitys; i++) {
|
for (int i = 0; i < movingEntitys; i++) {
|
||||||
|
|
||||||
|
// XXXBHG: replace storeEntity with new API!!
|
||||||
|
#if 0 //////////////////////////////////////////////////////
|
||||||
bool shouldDie = args._movingEntities[i]->getShouldBeDeleted();
|
bool shouldDie = args._movingEntities[i]->getShouldBeDeleted();
|
||||||
|
|
||||||
// if the particle is still inside our total bounds, then re-add it
|
// if the particle is still inside our total bounds, then re-add it
|
||||||
|
@ -955,6 +856,7 @@ void EntityTree::update() {
|
||||||
_recentlyDeletedEntityItemIDs.insert(deletedAt, entityItemID);
|
_recentlyDeletedEntityItemIDs.insert(deletedAt, entityItemID);
|
||||||
_recentlyDeletedEntitysLock.unlock();
|
_recentlyDeletedEntitysLock.unlock();
|
||||||
}
|
}
|
||||||
|
#endif // 0 //////////////////////////////////////////////////////
|
||||||
}
|
}
|
||||||
|
|
||||||
// prune the tree...
|
// prune the tree...
|
||||||
|
|
|
@ -50,11 +50,16 @@ public:
|
||||||
virtual bool rootElementHasData() const { return true; }
|
virtual bool rootElementHasData() const { return true; }
|
||||||
virtual void update();
|
virtual void update();
|
||||||
|
|
||||||
|
// The newer API...
|
||||||
EntityItem* getOrCreateEntityItem(const EntityItemID& entityID, const EntityItemProperties& properties);
|
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 storeEntity(const EntityItem& model, const SharedNodePointer& senderNode = SharedNodePointer());
|
||||||
void updateEntity(const EntityItemID& modelID, const EntityItemProperties& properties);
|
//void updateEntity(const EntityItemID& modelID, const EntityItemProperties& properties);
|
||||||
void addEntity(const EntityItemID& modelID, const EntityItemProperties& properties);
|
|
||||||
void deleteEntity(const EntityItemID& modelID);
|
void deleteEntity(const EntityItemID& modelID);
|
||||||
void deleteEntitys(QSet<EntityItemID> modelIDs);
|
void deleteEntitys(QSet<EntityItemID> modelIDs);
|
||||||
const EntityItem* findClosestEntity(glm::vec3 position, float targetRadius);
|
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 {
|
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 {
|
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 {
|
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...
|
// If we didn't find the entity here, then let's check to see if we should add it...
|
||||||
_entityItems->push_back(entity);
|
_entityItems->push_back(entity);
|
||||||
|
entity->setProperties(properties); // still need to update the properties!
|
||||||
markWithChangedTime();
|
markWithChangedTime();
|
||||||
// Since we're adding this item to this element, we need to let the tree know about it
|
// Since we're adding this item to this element, we need to let the tree know about it
|
||||||
_myTree->setContainingElement(entity->getEntityItemID(), this);
|
_myTree->setContainingElement(entity->getEntityItemID(), this);
|
||||||
|
@ -410,75 +411,6 @@ bool EntityTreeElement::addOrUpdateEntity(EntityItem* entity, const EntityItemPr
|
||||||
return true;
|
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) {
|
void EntityTreeElement::updateEntityItemID(FindAndUpdateEntityItemIDArgs* args) {
|
||||||
bool wantDebug = false;
|
bool wantDebug = false;
|
||||||
uint16_t numberOfEntities = _entityItems->size();
|
uint16_t numberOfEntities = _entityItems->size();
|
||||||
|
@ -519,8 +451,6 @@ void EntityTreeElement::updateEntityItemID(FindAndUpdateEntityItemIDArgs* args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const EntityItem* EntityTreeElement::getClosestEntity(glm::vec3 position) const {
|
const EntityItem* EntityTreeElement::getClosestEntity(glm::vec3 position) const {
|
||||||
const EntityItem* closestEntity = NULL;
|
const EntityItem* closestEntity = NULL;
|
||||||
float closestEntityDistance = FLT_MAX;
|
float closestEntityDistance = FLT_MAX;
|
||||||
|
|
|
@ -152,14 +152,14 @@ public:
|
||||||
bool containsEntityBounds(const EntityItem* entity) const;
|
bool containsEntityBounds(const EntityItem* entity) const;
|
||||||
bool bestFitEntityBounds(const EntityItem* entity) const;
|
bool bestFitEntityBounds(const EntityItem* entity) const;
|
||||||
|
|
||||||
bool containsBounds(const EntityItemProperties& properties) const;
|
bool containsBounds(const EntityItemProperties& properties) const; // NOTE: property units in meters
|
||||||
bool bestFitBounds(const EntityItemProperties& properties) const;
|
bool bestFitBounds(const EntityItemProperties& properties) const; // NOTE: property units in meters
|
||||||
|
|
||||||
bool containsBounds(const AACube& bounds) const;
|
bool containsBounds(const AACube& bounds) const; // NOTE: units in tree units
|
||||||
bool bestFitBounds(const AACube& bounds) const;
|
bool bestFitBounds(const AACube& bounds) const; // NOTE: units in tree units
|
||||||
|
|
||||||
bool containsBounds(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;
|
bool bestFitBounds(const glm::vec3& minPoint, const glm::vec3& maxPoint) const; // NOTE: units in tree units
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void init(unsigned char * octalCode);
|
virtual void init(unsigned char * octalCode);
|
||||||
|
|
|
@ -25,8 +25,9 @@
|
||||||
//#include "EntityTests.h"
|
//#include "EntityTests.h"
|
||||||
#include "ModelTests.h" // needs to be EntityTests.h soon
|
#include "ModelTests.h" // needs to be EntityTests.h soon
|
||||||
|
|
||||||
void EntityTests::modelTreeTests(bool verbose) {
|
void EntityTests::entityTreeTests(bool verbose) {
|
||||||
#ifdef HIDE_SUBCLASS_METHODS
|
|
||||||
|
//#ifdef HIDE_SUBCLASS_METHODS
|
||||||
bool extraVerbose = false;
|
bool extraVerbose = false;
|
||||||
int testsTaken = 0;
|
int testsTaken = 0;
|
||||||
int testsPassed = 0;
|
int testsPassed = 0;
|
||||||
|
@ -36,13 +37,13 @@ void EntityTests::modelTreeTests(bool verbose) {
|
||||||
qDebug() << "******************************************************************************************";
|
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;
|
EntityTree tree;
|
||||||
uint32_t id = 1;
|
uint32_t id = 1;
|
||||||
EntityItemID modelID(id);
|
EntityItemID entityID(id);
|
||||||
modelID.isKnownID = false; // this is a temporary workaround to allow local tree models to be added with known IDs
|
entityID.isKnownID = false; // this is a temporary workaround to allow local tree entities to be added with known IDs
|
||||||
EntityItemProperties properties;
|
EntityItemProperties properties;
|
||||||
float oneMeter = 1.0f;
|
float oneMeter = 1.0f;
|
||||||
float halfMeter = oneMeter / 2.0f;
|
float halfMeter = oneMeter / 2.0f;
|
||||||
|
@ -54,21 +55,21 @@ void EntityTests::modelTreeTests(bool verbose) {
|
||||||
|
|
||||||
{
|
{
|
||||||
testsTaken++;
|
testsTaken++;
|
||||||
QString testName = "add model to tree and search";
|
QString testName = "add entity to tree and search";
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
qDebug() << "Test" << testsTaken <<":" << qPrintable(testName);
|
qDebug() << "Test" << testsTaken <<":" << qPrintable(testName);
|
||||||
}
|
}
|
||||||
|
|
||||||
properties.setPosition(positionAtCenterInMeters);
|
properties.setPosition(positionAtCenterInMeters);
|
||||||
properties.setRadius(halfMeter);
|
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
|
float targetRadius = oneMeter * 2.0 / (float)TREE_SCALE; // in tree units
|
||||||
const EntityItem* foundEntityByRadius = tree.findClosestEntity(positionAtCenterInTreeUnits, targetRadius);
|
const EntityItem* foundEntityByRadius = tree.findClosestEntity(positionAtCenterInTreeUnits, targetRadius);
|
||||||
const EntityItem* foundEntityByID = tree.findEntityByID(id);
|
const EntityItem* foundEntityByID = tree.findEntityByID(id);
|
||||||
EntityTreeElement* containingElement = tree.getContainingElement(modelID);
|
EntityTreeElement* containingElement = tree.getContainingElement(entityID);
|
||||||
AACube elementCube = containingElement ? containingElement->getAACube() : AACube();
|
AACube elementCube = containingElement ? containingElement->getAACube() : AACube();
|
||||||
|
|
||||||
if (verbose) {
|
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++;
|
testsTaken++;
|
||||||
QString testName = "change position of model in tree";
|
QString testName = "change position of entity in tree";
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
qDebug() << "Test" << testsTaken <<":" << qPrintable(testName);
|
qDebug() << "Test" << testsTaken <<":" << qPrintable(testName);
|
||||||
}
|
}
|
||||||
|
@ -106,12 +107,12 @@ void EntityTests::modelTreeTests(bool verbose) {
|
||||||
|
|
||||||
properties.setPosition(newPosition);
|
properties.setPosition(newPosition);
|
||||||
|
|
||||||
tree.updateEntity(modelID, properties);
|
tree.updateEntity(entityID, properties);
|
||||||
|
|
||||||
float targetRadius = oneMeter * 2.0 / (float)TREE_SCALE; // in tree units
|
float targetRadius = oneMeter * 2.0 / (float)TREE_SCALE; // in tree units
|
||||||
const EntityItem* foundEntityByRadius = tree.findClosestEntity(positionNearOriginInTreeUnits, targetRadius);
|
const EntityItem* foundEntityByRadius = tree.findClosestEntity(positionNearOriginInTreeUnits, targetRadius);
|
||||||
const EntityItem* foundEntityByID = tree.findEntityByID(id);
|
const EntityItem* foundEntityByID = tree.findEntityByID(id);
|
||||||
EntityTreeElement* containingElement = tree.getContainingElement(modelID);
|
EntityTreeElement* containingElement = tree.getContainingElement(entityID);
|
||||||
AACube elementCube = containingElement ? containingElement->getAACube() : AACube();
|
AACube elementCube = containingElement ? containingElement->getAACube() : AACube();
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
|
@ -137,7 +138,7 @@ void EntityTests::modelTreeTests(bool verbose) {
|
||||||
|
|
||||||
{
|
{
|
||||||
testsTaken++;
|
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) {
|
if (verbose) {
|
||||||
qDebug() << "Test" << testsTaken <<":" << qPrintable(testName);
|
qDebug() << "Test" << testsTaken <<":" << qPrintable(testName);
|
||||||
}
|
}
|
||||||
|
@ -146,12 +147,12 @@ void EntityTests::modelTreeTests(bool verbose) {
|
||||||
|
|
||||||
properties.setPosition(newPosition);
|
properties.setPosition(newPosition);
|
||||||
|
|
||||||
tree.updateEntity(modelID, properties);
|
tree.updateEntity(entityID, properties);
|
||||||
|
|
||||||
float targetRadius = oneMeter * 2.0 / (float)TREE_SCALE; // in tree units
|
float targetRadius = oneMeter * 2.0 / (float)TREE_SCALE; // in tree units
|
||||||
const EntityItem* foundEntityByRadius = tree.findClosestEntity(positionAtCenterInTreeUnits, targetRadius);
|
const EntityItem* foundEntityByRadius = tree.findClosestEntity(positionAtCenterInTreeUnits, targetRadius);
|
||||||
const EntityItem* foundEntityByID = tree.findEntityByID(id);
|
const EntityItem* foundEntityByID = tree.findEntityByID(id);
|
||||||
EntityTreeElement* containingElement = tree.getContainingElement(modelID);
|
EntityTreeElement* containingElement = tree.getContainingElement(entityID);
|
||||||
AACube elementCube = containingElement ? containingElement->getAACube() : AACube();
|
AACube elementCube = containingElement ? containingElement->getAACube() : AACube();
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
|
@ -244,7 +245,7 @@ void EntityTests::modelTreeTests(bool verbose) {
|
||||||
|
|
||||||
testsTaken++;
|
testsTaken++;
|
||||||
const int TEST_ITERATIONS = 1000;
|
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) {
|
if (verbose) {
|
||||||
qDebug() << "Test" << testsTaken <<":" << qPrintable(testName);
|
qDebug() << "Test" << testsTaken <<":" << qPrintable(testName);
|
||||||
}
|
}
|
||||||
|
@ -253,9 +254,9 @@ void EntityTests::modelTreeTests(bool verbose) {
|
||||||
quint64 totalElapsedAdd = 0;
|
quint64 totalElapsedAdd = 0;
|
||||||
quint64 totalElapsedFind = 0;
|
quint64 totalElapsedFind = 0;
|
||||||
for (int i = 0; i < TEST_ITERATIONS; i++) {
|
for (int i = 0; i < TEST_ITERATIONS; i++) {
|
||||||
uint32_t id = i + 2; // make sure it doesn't collide with previous model ids
|
uint32_t id = i + 2; // make sure it doesn't collide with previous entity ids
|
||||||
EntityItemID modelID(id);
|
EntityItemID entityID(id);
|
||||||
modelID.isKnownID = false; // this is a temporary workaround to allow local tree models to be added with known IDs
|
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 randomX = randFloatInRange(1.0f ,(float)TREE_SCALE - 1.0f);
|
||||||
float randomY = 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) {
|
if (extraVerbose) {
|
||||||
qDebug() << "iteration:" << i
|
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();
|
qDebug() << "before:" << i << "getOctreeElementsCount()=" << tree.getOctreeElementsCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
quint64 startAdd = usecTimestampNow();
|
quint64 startAdd = usecTimestampNow();
|
||||||
tree.addEntity(modelID, properties);
|
tree.addEntity(entityID, properties);
|
||||||
quint64 endAdd = usecTimestampNow();
|
quint64 endAdd = usecTimestampNow();
|
||||||
totalElapsedAdd += (endAdd - startAdd);
|
totalElapsedAdd += (endAdd - startAdd);
|
||||||
|
|
||||||
|
@ -289,7 +290,7 @@ void EntityTests::modelTreeTests(bool verbose) {
|
||||||
quint64 endFind = usecTimestampNow();
|
quint64 endFind = usecTimestampNow();
|
||||||
totalElapsedFind += (endFind - startFind);
|
totalElapsedFind += (endFind - startFind);
|
||||||
|
|
||||||
EntityTreeElement* containingElement = tree.getContainingElement(modelID);
|
EntityTreeElement* containingElement = tree.getContainingElement(entityID);
|
||||||
AACube elementCube = containingElement ? containingElement->getAACube() : AACube();
|
AACube elementCube = containingElement ? containingElement->getAACube() : AACube();
|
||||||
|
|
||||||
bool elementIsBestFit = containingElement->bestFitEntityBounds(foundEntityByID);
|
bool elementIsBestFit = containingElement->bestFitEntityBounds(foundEntityByID);
|
||||||
|
@ -348,7 +349,7 @@ void EntityTests::modelTreeTests(bool verbose) {
|
||||||
{
|
{
|
||||||
testsTaken++;
|
testsTaken++;
|
||||||
const int TEST_ITERATIONS = 1000;
|
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) {
|
if (verbose) {
|
||||||
qDebug() << "Test" << testsTaken <<":" << qPrintable(testName);
|
qDebug() << "Test" << testsTaken <<":" << qPrintable(testName);
|
||||||
}
|
}
|
||||||
|
@ -357,16 +358,16 @@ void EntityTests::modelTreeTests(bool verbose) {
|
||||||
quint64 totalElapsedDelete = 0;
|
quint64 totalElapsedDelete = 0;
|
||||||
quint64 totalElapsedFind = 0;
|
quint64 totalElapsedFind = 0;
|
||||||
for (int i = 0; i < TEST_ITERATIONS; i++) {
|
for (int i = 0; i < TEST_ITERATIONS; i++) {
|
||||||
uint32_t id = i + 2; // These are the models we added above
|
uint32_t id = i + 2; // These are the entities we added above
|
||||||
EntityItemID modelID(id);
|
EntityItemID entityID(id);
|
||||||
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
|
||||||
|
|
||||||
if (extraVerbose) {
|
if (extraVerbose) {
|
||||||
qDebug() << "before:" << i << "getOctreeElementsCount()=" << tree.getOctreeElementsCount();
|
qDebug() << "before:" << i << "getOctreeElementsCount()=" << tree.getOctreeElementsCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
quint64 startDelete = usecTimestampNow();
|
quint64 startDelete = usecTimestampNow();
|
||||||
tree.deleteEntity(modelID);
|
tree.deleteEntity(entityID);
|
||||||
quint64 endDelete = usecTimestampNow();
|
quint64 endDelete = usecTimestampNow();
|
||||||
totalElapsedDelete += (endDelete - startDelete);
|
totalElapsedDelete += (endDelete - startDelete);
|
||||||
|
|
||||||
|
@ -379,7 +380,7 @@ void EntityTests::modelTreeTests(bool verbose) {
|
||||||
quint64 endFind = usecTimestampNow();
|
quint64 endFind = usecTimestampNow();
|
||||||
totalElapsedFind += (endFind - startFind);
|
totalElapsedFind += (endFind - startFind);
|
||||||
|
|
||||||
EntityTreeElement* containingElement = tree.getContainingElement(modelID);
|
EntityTreeElement* containingElement = tree.getContainingElement(entityID);
|
||||||
|
|
||||||
if (extraVerbose) {
|
if (extraVerbose) {
|
||||||
qDebug() << "foundEntityByID=" << foundEntityByID;
|
qDebug() << "foundEntityByID=" << foundEntityByID;
|
||||||
|
@ -426,9 +427,9 @@ void EntityTests::modelTreeTests(bool verbose) {
|
||||||
{
|
{
|
||||||
testsTaken++;
|
testsTaken++;
|
||||||
const int TEST_ITERATIONS = 100;
|
const int TEST_ITERATIONS = 100;
|
||||||
const int MODELS_PER_ITERATION = 10;
|
const int ENTITIES_PER_ITERATION = 10;
|
||||||
QString testName = "Performance - delete " + QString::number(MODELS_PER_ITERATION)
|
QString testName = "Performance - delete " + QString::number(ENTITIES_PER_ITERATION)
|
||||||
+ " models from tree " + QString::number(TEST_ITERATIONS) + " times";
|
+ " entities from tree " + QString::number(TEST_ITERATIONS) + " times";
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
qDebug() << "Test" << testsTaken <<":" << qPrintable(testName);
|
qDebug() << "Test" << testsTaken <<":" << qPrintable(testName);
|
||||||
}
|
}
|
||||||
|
@ -438,11 +439,11 @@ void EntityTests::modelTreeTests(bool verbose) {
|
||||||
quint64 totalElapsedFind = 0;
|
quint64 totalElapsedFind = 0;
|
||||||
for (int i = 0; i < TEST_ITERATIONS; i++) {
|
for (int i = 0; i < TEST_ITERATIONS; i++) {
|
||||||
|
|
||||||
QSet<EntityItemID> modelsToDelete;
|
QSet<EntityItemID> entitiesToDelete;
|
||||||
for (int j = 0; j < MODELS_PER_ITERATION; j++) {
|
for (int j = 0; j < ENTITIES_PER_ITERATION; j++) {
|
||||||
uint32_t id = 2 + (i * MODELS_PER_ITERATION) + j; // These are the models we added above
|
uint32_t id = 2 + (i * ENTITIES_PER_ITERATION) + j; // These are the entities we added above
|
||||||
EntityItemID modelID(id);
|
EntityItemID entityID(id);
|
||||||
modelsToDelete << modelID;
|
entitiesToDelete << entityID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extraVerbose) {
|
if (extraVerbose) {
|
||||||
|
@ -450,7 +451,7 @@ void EntityTests::modelTreeTests(bool verbose) {
|
||||||
}
|
}
|
||||||
|
|
||||||
quint64 startDelete = usecTimestampNow();
|
quint64 startDelete = usecTimestampNow();
|
||||||
tree.deleteEntitys(modelsToDelete);
|
tree.deleteEntitys(entitiesToDelete);
|
||||||
quint64 endDelete = usecTimestampNow();
|
quint64 endDelete = usecTimestampNow();
|
||||||
totalElapsedDelete += (endDelete - startDelete);
|
totalElapsedDelete += (endDelete - startDelete);
|
||||||
|
|
||||||
|
@ -459,11 +460,11 @@ void EntityTests::modelTreeTests(bool verbose) {
|
||||||
}
|
}
|
||||||
|
|
||||||
quint64 startFind = usecTimestampNow();
|
quint64 startFind = usecTimestampNow();
|
||||||
for (int j = 0; j < MODELS_PER_ITERATION; j++) {
|
for (int j = 0; j < ENTITIES_PER_ITERATION; j++) {
|
||||||
uint32_t id = 2 + (i * MODELS_PER_ITERATION) + j; // These are the models we added above
|
uint32_t id = 2 + (i * ENTITIES_PER_ITERATION) + j; // These are the entities we added above
|
||||||
EntityItemID modelID(id);
|
EntityItemID entityID(id);
|
||||||
const EntityItem* foundEntityByID = tree.findEntityByID(id);
|
const EntityItem* foundEntityByID = tree.findEntityByID(id);
|
||||||
EntityTreeElement* containingElement = tree.getContainingElement(modelID);
|
EntityTreeElement* containingElement = tree.getContainingElement(entityID);
|
||||||
|
|
||||||
if (extraVerbose) {
|
if (extraVerbose) {
|
||||||
qDebug() << "foundEntityByID=" << foundEntityByID;
|
qDebug() << "foundEntityByID=" << foundEntityByID;
|
||||||
|
@ -490,7 +491,7 @@ void EntityTests::modelTreeTests(bool verbose) {
|
||||||
qDebug() << "getOctreeElementsCount()=" << tree.getOctreeElementsCount();
|
qDebug() << "getOctreeElementsCount()=" << tree.getOctreeElementsCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool passed = iterationsPassed == (TEST_ITERATIONS * MODELS_PER_ITERATION);
|
bool passed = iterationsPassed == (TEST_ITERATIONS * ENTITIES_PER_ITERATION);
|
||||||
if (passed) {
|
if (passed) {
|
||||||
testsPassed++;
|
testsPassed++;
|
||||||
} else {
|
} else {
|
||||||
|
@ -509,11 +510,12 @@ void EntityTests::modelTreeTests(bool verbose) {
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
qDebug() << "******************************************************************************************";
|
qDebug() << "******************************************************************************************";
|
||||||
}
|
}
|
||||||
#endif
|
//#endif
|
||||||
|
//#endif // 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void EntityTests::runAllTests(bool verbose) {
|
void EntityTests::runAllTests(bool verbose) {
|
||||||
modelTreeTests(verbose);
|
entityTreeTests(verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#define hifi_EntityTests_h
|
#define hifi_EntityTests_h
|
||||||
|
|
||||||
namespace EntityTests {
|
namespace EntityTests {
|
||||||
void modelTreeTests(bool verbose = false);
|
void entityTreeTests(bool verbose = false);
|
||||||
void runAllTests(bool verbose = false);
|
void runAllTests(bool verbose = false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue