From b78b8ccbb095170ceabba4f3d252034615551ea0 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 9 Sep 2014 13:33:05 -0700 Subject: [PATCH] first cut at replacing radius with dimensions --- examples/editModels.js | 91 ++++++--- interface/src/avatar/ModelReferential.cpp | 16 +- interface/src/entities/EntityTreeRenderer.cpp | 1 + .../src/entities/RenderableBoxEntityItem.cpp | 12 +- .../entities/RenderableModelEntityItem.cpp | 4 +- .../entities/RenderableSphereEntityItem.cpp | 8 +- interface/src/renderer/Model.cpp | 19 +- interface/src/renderer/Model.h | 5 +- libraries/entities/src/BoxEntityItem.cpp | 19 +- libraries/entities/src/EntityItem.cpp | 177 +++++++++++------- libraries/entities/src/EntityItem.h | 43 ++++- .../entities/src/EntityItemProperties.cpp | 68 ++++--- libraries/entities/src/EntityItemProperties.h | 69 ++++--- libraries/entities/src/EntityTreeElement.cpp | 3 + libraries/entities/src/ModelEntityItem.cpp | 56 ++---- libraries/entities/src/ModelEntityItem.h | 9 + libraries/entities/src/SphereEntityItem.cpp | 10 +- .../entities/src/UpdateEntityOperator.cpp | 11 +- libraries/networking/src/PacketHeaders.cpp | 5 +- libraries/networking/src/PacketHeaders.h | 1 + tests/octree/src/ModelTests.cpp | 11 +- 21 files changed, 392 insertions(+), 246 deletions(-) diff --git a/examples/editModels.js b/examples/editModels.js index cec1bff783..2888141bf1 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -40,7 +40,7 @@ var LEFT = 0; var RIGHT = 1; var SPAWN_DISTANCE = 1; -var DEFAULT_RADIUS = 0.10; +var DEFAULT_DIMENSION = 0.20; var modelURLs = [ "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/Feisar_Ship.FBX", @@ -1220,7 +1220,7 @@ var toolBar = (function () { Entities.addEntity({ type: "Model", position: position, - radius: DEFAULT_RADIUS, + dimensions: { x: DEFAULT_DIMENSION, y: DEFAULT_DIMENSION, z: DEFAULT_DIMENSION }, modelURL: url }); print("Model added: " + url); @@ -1311,7 +1311,7 @@ var toolBar = (function () { Entities.addEntity({ type: "Box", position: position, - radius: DEFAULT_RADIUS, + dimensions: { x: DEFAULT_DIMENSION, y: DEFAULT_DIMENSION, z: DEFAULT_DIMENSION }, color: { red: 255, green: 0, blue: 0 } }); } else { @@ -1327,7 +1327,7 @@ var toolBar = (function () { Entities.addEntity({ type: "Sphere", position: position, - radius: DEFAULT_RADIUS, + dimensions: { x: DEFAULT_DIMENSION, y: DEFAULT_DIMENSION, z: DEFAULT_DIMENSION }, color: { red: 255, green: 0, blue: 0 } }); } else { @@ -1804,7 +1804,7 @@ function controller(wichSide) { this.modelURL = ""; this.oldModelRotation; this.oldModelPosition; - this.oldModelRadius; + this.oldModelHalfDiagonal; this.positionAtGrab; this.rotationAtGrab; @@ -1864,7 +1864,7 @@ function controller(wichSide) { this.oldModelPosition = properties.position; this.oldModelRotation = properties.rotation; - this.oldModelRadius = properties.radius; + this.oldModelHalfDiagonal = Vec3.length(properties.dimensions) / 2.0; this.positionAtGrab = this.palmPosition; this.rotationAtGrab = this.rotation; @@ -1873,7 +1873,7 @@ function controller(wichSide) { this.jointsIntersectingFromStart = []; for (var i = 0; i < jointList.length; i++) { var distance = Vec3.distance(MyAvatar.getJointPosition(jointList[i]), this.oldModelPosition); - if (distance < this.oldModelRadius) { + if (distance < this.oldModelHalfDiagonal) { this.jointsIntersectingFromStart.push(i); } } @@ -1897,10 +1897,10 @@ function controller(wichSide) { if (closestJointIndex != -1) { print("closestJoint: " + jointList[closestJointIndex]); - print("closestJointDistance (attach max distance): " + closestJointDistance + " (" + this.oldModelRadius + ")"); + print("closestJointDistance (attach max distance): " + closestJointDistance + " (" + this.oldModelHalfDiagonal + ")"); } - if (closestJointDistance < this.oldModelRadius) { + if (closestJointDistance < this.oldModelHalfDiagonal) { if (this.jointsIntersectingFromStart.indexOf(closestJointIndex) != -1 || (leftController.grabbing && rightController.grabbing && @@ -1916,7 +1916,7 @@ function controller(wichSide) { var attachmentRotation = Quat.multiply(Quat.inverse(jointRotation), this.oldModelRotation); MyAvatar.attach(this.modelURL, jointList[closestJointIndex], - attachmentOffset, attachmentRotation, 2.0 * this.oldModelRadius, + attachmentOffset, attachmentRotation, 2.0 * this.oldModelHalfDiagonal, true, false); Entities.deleteEntity(this.entityID); } @@ -1970,11 +1970,12 @@ function controller(wichSide) { var z = Vec3.dot(Vec3.subtract(P, A), this.right); var X = Vec3.sum(A, Vec3.multiply(B, x)); var d = Vec3.length(Vec3.subtract(P, X)); + var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; - var angularSize = 2 * Math.atan(properties.radius / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14; + var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14; if (0 < x && angularSize > MIN_ANGULAR_SIZE) { if (angularSize > MAX_ANGULAR_SIZE) { - print("Angular size too big: " + 2 * Math.atan(properties.radius / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14); + print("Angular size too big: " + angularSize); return { valid: false }; } @@ -2021,7 +2022,10 @@ function controller(wichSide) { origin: this.palmPosition, direction: this.front }); - var angularSize = 2 * Math.atan(intersection.properties.radius / Vec3.distance(Camera.getPosition(), intersection.properties.position)) * 180 / 3.14; + + var halfDiagonal = Vec3.length(intersection.properties.dimensions) / 2.0; + + var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), intersection.properties.position)) * 180 / 3.14; if (intersection.accurate && intersection.entityID.isKnownID && angularSize > MIN_ANGULAR_SIZE && angularSize < MAX_ANGULAR_SIZE) { this.glowedIntersectingModel = intersection.entityID; Entities.editEntity(this.glowedIntersectingModel, { glowLevel: 0.25 }); @@ -2099,7 +2103,7 @@ function controller(wichSide) { var indicesToRemove = []; for (var i = 0; i < this.jointsIntersectingFromStart.length; ++i) { var distance = Vec3.distance(MyAvatar.getJointPosition(this.jointsIntersectingFromStart[i]), this.oldModelPosition); - if (distance >= this.oldModelRadius) { + if (distance >= this.oldModelHalfDiagonal) { indicesToRemove.push(this.jointsIntersectingFromStart[i]); } @@ -2192,7 +2196,12 @@ function controller(wichSide) { Vec3.multiplyQbyV(MyAvatar.getJointCombinedRotation(attachments[attachmentIndex].jointName), attachments[attachmentIndex].translation)), rotation: Quat.multiply(MyAvatar.getJointCombinedRotation(attachments[attachmentIndex].jointName), attachments[attachmentIndex].rotation), - radius: attachments[attachmentIndex].scale / 2.0, + + // TODO: how do we know the correct dimensions for detachment??? + dimensions: { x: attachments[attachmentIndex].scale / 2.0, + y: attachments[attachmentIndex].scale / 2.0, + z: attachments[attachmentIndex].scale / 2.0 }, + modelURL: attachments[attachmentIndex].modelURL }; @@ -2310,15 +2319,21 @@ function moveEntities() { Entities.editEntity(leftController.entityID, { position: newPosition, rotation: rotation, - radius: leftController.oldModelRadius * ratio + // TODO: how do we know the correct dimensions for detachment??? + //radius: leftController.oldModelHalfDiagonal * ratio + dimensions: { x: leftController.oldModelHalfDiagonal * ratio, + y: leftController.oldModelHalfDiagonal * ratio, + z: leftController.oldModelHalfDiagonal * ratio } + + }); leftController.oldModelPosition = newPosition; leftController.oldModelRotation = rotation; - leftController.oldModelRadius *= ratio; + leftController.oldModelHalfDiagonal *= ratio; rightController.oldModelPosition = newPosition; rightController.oldModelRotation = rotation; - rightController.oldModelRadius *= ratio; + rightController.oldModelHalfDiagonal *= ratio; return; } leftController.moveEntity(); @@ -2407,7 +2422,9 @@ function Tooltip() { text += "Pitch: " + angles.x.toFixed(this.decimals) + "\n" text += "Yaw: " + angles.y.toFixed(this.decimals) + "\n" text += "Roll: " + angles.z.toFixed(this.decimals) + "\n" - text += "Scale: " + 2 * properties.radius.toFixed(this.decimals) + "\n" + text += "Width: " + properties.dimensions.x.toFixed(this.decimals) + "\n" + text += "Height: " + properties.dimensions.y.toFixed(this.decimals) + "\n" + text += "Depth: " + properties.dimensions.z.toFixed(this.decimals) + "\n" text += "ID: " + properties.id + "\n" if (properties.type == "Model") { text += "Model URL: " + properties.modelURL + "\n" @@ -2477,7 +2494,9 @@ function mousePressEvent(event) { if (isLocked(properties)) { print("Model locked " + properties.id); } else { - print("Checking properties: " + properties.id + " " + properties.isKnownID); + var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; + + print("Checking properties: " + properties.id + " " + properties.isKnownID + " - Half Diagonal:" + halfDiagonal); // P P - Model // /| A - Palm // / | d B - unit vector toward tip @@ -2496,8 +2515,9 @@ function mousePressEvent(event) { var x = Vec3.dot(Vec3.subtract(P, A), B); var X = Vec3.sum(A, Vec3.multiply(B, x)); var d = Vec3.length(Vec3.subtract(P, X)); + var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; - var angularSize = 2 * Math.atan(properties.radius / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14; + var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14; if (0 < x && angularSize > MIN_ANGULAR_SIZE) { if (angularSize < MAX_ANGULAR_SIZE) { entitySelected = true; @@ -2506,13 +2526,13 @@ function mousePressEvent(event) { orientation = MyAvatar.orientation; intersection = rayPlaneIntersection(pickRay, P, Quat.getFront(orientation)); } else { - print("Angular size too big: " + 2 * Math.atan(properties.radius / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14); + print("Angular size too big: " + angularSize); } } } } if (entitySelected) { - selectedEntityProperties.oldRadius = selectedEntityProperties.radius; + selectedEntityProperties.oldDimensions = selectedEntityProperties.dimensions; selectedEntityProperties.oldPosition = { x: selectedEntityProperties.position.x, y: selectedEntityProperties.position.y, @@ -2550,8 +2570,12 @@ function mouseMoveEvent(event) { glowedEntityID.id = -1; glowedEntityID.isKnownID = false; } + + var halfDiagonal = Vec3.length(entityIntersection.properties.dimensions) / 2.0; - var angularSize = 2 * Math.atan(entityIntersection.properties.radius / Vec3.distance(Camera.getPosition(), entityIntersection.properties.position)) * 180 / 3.14; + var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), + entityIntersection.properties.position)) * 180 / 3.14; + if (entityIntersection.entityID.isKnownID && angularSize > MIN_ANGULAR_SIZE && angularSize < MAX_ANGULAR_SIZE) { Entities.editEntity(entityIntersection.entityID, { glowLevel: 0.25 }); glowedEntityID = entityIntersection.entityID; @@ -2573,7 +2597,7 @@ function mouseMoveEvent(event) { } pickRay = Camera.computePickRay(event.x, event.y); if (wasShifted != event.isShifted || modifier != oldModifier) { - selectedEntityProperties.oldRadius = selectedEntityProperties.radius; + selectedEntityProperties.oldDimensions = selectedEntityProperties.dimensions; selectedEntityProperties.oldPosition = { x: selectedEntityProperties.position.x, @@ -2603,9 +2627,12 @@ function mouseMoveEvent(event) { return; case 1: // Let's Scale - selectedEntityProperties.radius = (selectedEntityProperties.oldRadius * + selectedEntityProperties.dimensions = Vec3.multiply(selectedEntityProperties.dimensions, (1.0 + (mouseLastPosition.y - event.y) / SCALE_FACTOR)); - if (selectedEntityProperties.radius < 0.01) { + + var halfDiagonal = Vec3.length(selectedEntityProperties.dimensions) / 2.0; + + if (halfDiagonal < 0.01) { print("Scale too small ... bailling."); return; } @@ -2815,7 +2842,10 @@ function handeMenuEvent(menuItem) { array.push({ label: "Pitch:", value: angles.x.toFixed(decimals) }); array.push({ label: "Yaw:", value: angles.y.toFixed(decimals) }); array.push({ label: "Roll:", value: angles.z.toFixed(decimals) }); - array.push({ label: "Scale:", value: 2 * properties.radius.toFixed(decimals) }); + + array.push({ label: "Width:", value: properties.dimensions.x.toFixed(decimals) }); + array.push({ label: "Height:", value: properties.dimensions.y.toFixed(decimals) }); + array.push({ label: "Depth:", value: properties.dimensions.z.toFixed(decimals) }); array.push({ label: "Velocity X:", value: properties.velocity.x.toFixed(decimals) }); array.push({ label: "Velocity Y:", value: properties.velocity.y.toFixed(decimals) }); @@ -2851,7 +2881,10 @@ function handeMenuEvent(menuItem) { angles.y = array[index++].value; angles.z = array[index++].value; properties.rotation = Quat.fromVec3Degrees(angles); - properties.radius = array[index++].value / 2; + + properties.dimensions.x = array[index++].value; + properties.dimensions.y = array[index++].value; + properties.dimensions.z = array[index++].value; properties.velocity.x = array[index++].value; properties.velocity.y = array[index++].value; diff --git a/interface/src/avatar/ModelReferential.cpp b/interface/src/avatar/ModelReferential.cpp index eb2a61a819..df6e272da7 100644 --- a/interface/src/avatar/ModelReferential.cpp +++ b/interface/src/avatar/ModelReferential.cpp @@ -33,7 +33,7 @@ ModelReferential::ModelReferential(Referential* referential, EntityTree* tree, A const EntityItem* item = _tree->findEntityByID(_entityID); if (item != NULL) { - _refScale = item->getRadius(); + _refScale = item->getLargestDimension(); _refRotation = item->getRotation(); _refPosition = item->getPosition() * (float)TREE_SCALE; update(); @@ -52,7 +52,7 @@ ModelReferential::ModelReferential(const QUuid& entityID, EntityTree* tree, Avat return; } - _refScale = item->getRadius(); + _refScale = item->getLargestDimension(); _refRotation = item->getRotation(); _refPosition = item->getPosition() * (float)TREE_SCALE; @@ -69,8 +69,8 @@ void ModelReferential::update() { } bool somethingChanged = false; - if (item->getRadius() != _refScale) { - _refScale = item->getRadius(); + if (item->getLargestDimension() != _refScale) { + _refScale = item->getLargestDimension(); _avatar->setTargetScale(_refScale * _scale, true); somethingChanged = true; } @@ -109,7 +109,7 @@ JointReferential::JointReferential(Referential* referential, EntityTree* tree, A const EntityItem* item = _tree->findEntityByID(_entityID); const Model* model = getModel(item); if (!isValid() || model == NULL || _jointIndex >= (uint32_t)(model->getJointStateCount())) { - _refScale = item->getRadius(); + _refScale = item->getLargestDimension(); model->getJointRotationInWorldFrame(_jointIndex, _refRotation); model->getJointPositionInWorldFrame(_jointIndex, _refPosition); } @@ -129,7 +129,7 @@ JointReferential::JointReferential(uint32_t jointIndex, const QUuid& entityID, E return; } - _refScale = item->getRadius(); + _refScale = item->getLargestDimension(); model->getJointRotationInWorldFrame(_jointIndex, _refRotation); model->getJointPositionInWorldFrame(_jointIndex, _refPosition); @@ -147,8 +147,8 @@ void JointReferential::update() { } bool somethingChanged = false; - if (item->getRadius() != _refScale) { - _refScale = item->getRadius(); + if (item->getLargestDimension() != _refScale) { + _refScale = item->getLargestDimension(); _avatar->setTargetScale(_refScale * _scale, true); somethingChanged = true; } diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index 8dd88a79cc..495952f895 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -216,6 +216,7 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) EntityItem* entityItem = entityItems[i]; // render entityItem AACube entityCube = entityItem->getAACube(); + entityCube.scale(TREE_SCALE); // TODO: some entity types (like lights) might want to be rendered even diff --git a/interface/src/entities/RenderableBoxEntityItem.cpp b/interface/src/entities/RenderableBoxEntityItem.cpp index 673f41574e..0156f051ae 100644 --- a/interface/src/entities/RenderableBoxEntityItem.cpp +++ b/interface/src/entities/RenderableBoxEntityItem.cpp @@ -33,7 +33,8 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableBoxEntityItem::render"); assert(getType() == EntityTypes::Box); glm::vec3 position = getPosition() * (float)TREE_SCALE; - float size = getSize() * (float)TREE_SCALE; + glm::vec3 dimensions = getDimensions() * (float)TREE_SCALE; + glm::vec3 halfDimensions = dimensions / 2.0f; glm::quat rotation = getRotation(); @@ -45,7 +46,8 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { glTranslatef(position.x, position.y, position.z); glm::vec3 axis = glm::axis(rotation); glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - glutSolidCube(size); + glScalef(dimensions.x, dimensions.y, dimensions.z); + glutSolidCube(1.0f); glPopMatrix(); } else { @@ -79,8 +81,6 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { glNormalPointer(GL_FLOAT, 0, normals); glVertexPointer(3, GL_FLOAT, 0, vertices); - //glEnable(GL_BLEND); - glColor3ub(getColor()[RED_INDEX], getColor()[GREEN_INDEX], getColor()[BLUE_INDEX]); glPushMatrix(); @@ -89,9 +89,7 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); // we need to do half the size because the geometry in the VBOs are from -1,-1,-1 to 1,1,1 - float halfSize = size/2.0f; - - glScalef(halfSize, halfSize, halfSize); + glScalef(halfDimensions.x, halfDimensions.y, halfDimensions.z); glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, indices); glPopMatrix(); diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index e2a710123e..f74abd2a13 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -65,8 +65,8 @@ void RenderableModelEntityItem::render(RenderArgs* args) { bool drawAsModel = hasModel(); glm::vec3 position = getPosition() * (float)TREE_SCALE; - float radius = getRadius() * (float)TREE_SCALE; float size = getSize() * (float)TREE_SCALE; + glm::vec3 dimensions = getDimensions() * (float)TREE_SCALE; if (drawAsModel) { glPushMatrix(); @@ -98,7 +98,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { glm::quat rotation = getRotation(); if (needsSimulation() && _model->isActive()) { - _model->setScaleToFit(true, radius * 2.0f); + _model->setScaleToFit(true, dimensions); _model->setSnapModelToCenter(true); _model->setRotation(rotation); _model->setTranslation(position); diff --git a/interface/src/entities/RenderableSphereEntityItem.cpp b/interface/src/entities/RenderableSphereEntityItem.cpp index 01f41e83ae..d03a384063 100644 --- a/interface/src/entities/RenderableSphereEntityItem.cpp +++ b/interface/src/entities/RenderableSphereEntityItem.cpp @@ -32,11 +32,15 @@ void RenderableSphereEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableSphereEntityItem::render"); assert(getType() == EntityTypes::Sphere); glm::vec3 position = getPosition() * (float)TREE_SCALE; - float radius = getRadius() * (float)TREE_SCALE; + glm::vec3 dimensions = getDimensions() * (float)TREE_SCALE; + glm::quat rotation = getRotation(); glColor3ub(getColor()[RED_INDEX], getColor()[GREEN_INDEX], getColor()[BLUE_INDEX]); glPushMatrix(); glTranslatef(position.x, position.y, position.z); - glutSolidSphere(radius, 15, 15); + glm::vec3 axis = glm::axis(rotation); + glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); + glScalef(dimensions.x, dimensions.y, dimensions.z); + glutSolidSphere(0.5f, 15, 15); glPopMatrix(); }; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index d49eefa4bd..867083fe90 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -54,7 +54,7 @@ Model::Model(QObject* parent) : QObject(parent), _scale(1.0f, 1.0f, 1.0f), _scaleToFit(false), - _scaleToFitLargestDimension(0.0f), + _scaleToFitDimensions(0.0f), _scaledToFit(false), _snapModelToCenter(false), _snappedToCenter(false), @@ -882,23 +882,26 @@ void Blender::run() { Q_ARG(const QVector&, vertices), Q_ARG(const QVector&, normals)); } -void Model::setScaleToFit(bool scaleToFit, float largestDimension) { - if (_scaleToFit != scaleToFit || _scaleToFitLargestDimension != largestDimension) { +void Model::setScaleToFit(bool scaleToFit, const glm::vec3& dimensions) { + if (_scaleToFit != scaleToFit || _scaleToFitDimensions != dimensions) { _scaleToFit = scaleToFit; - _scaleToFitLargestDimension = largestDimension; + _scaleToFitDimensions = dimensions; _scaledToFit = false; // force rescaling } } +void Model::setScaleToFit(bool scaleToFit, float largestDimension) { + setScaleToFit(scaleToFit, glm::vec3(largestDimension, largestDimension, largestDimension)); +} + void Model::scaleToFit() { Extents modelMeshExtents = getUnscaledMeshExtents(); // size is our "target size in world space" // we need to set our model scale so that the extents of the mesh, fit in a cube that size... - float maxDimension = glm::distance(modelMeshExtents.maximum, modelMeshExtents.minimum); - float maxScale = _scaleToFitLargestDimension / maxDimension; - glm::vec3 scale(maxScale, maxScale, maxScale); - setScaleInternal(scale); + glm::vec3 meshDimensions = modelMeshExtents.maximum - modelMeshExtents.minimum; + glm::vec3 rescaleDimensions = _scaleToFitDimensions / meshDimensions; + setScaleInternal(rescaleDimensions); _scaledToFit = true; } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 66baaac90d..f56aed37a0 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -52,7 +52,8 @@ public: void setScaleToFit(bool scaleToFit, float largestDimension = 0.0f); bool getScaleToFit() const { return _scaleToFit; } /// is scale to fit enabled bool getIsScaledToFit() const { return _scaledToFit; } /// is model scaled to fit - bool getScaleToFitDimension() const { return _scaleToFitLargestDimension; } /// the dimension model is scaled to + const glm::vec3& getScaleToFitDimensions() const { return _scaleToFitDimensions; } /// the dimensions model is scaled to + void setScaleToFit(bool scaleToFit, const glm::vec3& dimensions); void setSnapModelToCenter(bool snapModelToCenter); bool getSnapModelToCenter() { return _snapModelToCenter; } @@ -181,7 +182,7 @@ protected: glm::vec3 _offset; bool _scaleToFit; /// If you set scaleToFit, we will calculate scale based on MeshExtents - float _scaleToFitLargestDimension; /// this is the dimension that scale to fit will use + glm::vec3 _scaleToFitDimensions; /// this is the dimensions that scale to fit will use bool _scaledToFit; /// have we scaled to fit bool _snapModelToCenter; /// is the model's offset automatically adjusted to center around 0,0,0 in model space diff --git a/libraries/entities/src/BoxEntityItem.cpp b/libraries/entities/src/BoxEntityItem.cpp index c683a71562..83d6d7eff9 100644 --- a/libraries/entities/src/BoxEntityItem.cpp +++ b/libraries/entities/src/BoxEntityItem.cpp @@ -20,13 +20,15 @@ EntityItem* BoxEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { - return new BoxEntityItem(entityID, properties); + EntityItem* result = new BoxEntityItem(entityID, properties); + return result; } BoxEntityItem::BoxEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : - EntityItem(entityItemID, properties) -{ + EntityItem(entityItemID) +{ _type = EntityTypes::Box; + _created = properties.getCreated(); setProperties(properties, true); } @@ -44,18 +46,9 @@ EntityItemProperties BoxEntityItem::getProperties() const { bool BoxEntityItem::setProperties(const EntityItemProperties& properties, bool forceCopy) { bool somethingChanged = false; - somethingChanged = EntityItem::setProperties(properties, forceCopy); // set the properties in our base class - if (properties._colorChanged || forceCopy) { - setColor(properties._color); - somethingChanged = true; - } - - if (properties._glowLevelChanged || forceCopy) { - setGlowLevel(properties._glowLevel); - somethingChanged = true; - } + SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor); if (somethingChanged) { bool wantDebug = false; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index a472e7ec39..e64b1d503d 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -35,6 +35,9 @@ const glm::vec3 EntityItem::NO_GRAVITY = glm::vec3(0, 0, 0); const glm::vec3 EntityItem::REGULAR_GRAVITY = glm::vec3(0, (-9.8f / TREE_SCALE), 0); const glm::vec3 EntityItem::DEFAULT_GRAVITY = EntityItem::NO_GRAVITY; const QString EntityItem::DEFAULT_SCRIPT = QString(""); +const glm::quat EntityItem::DEFAULT_ROTATION; +const glm::vec3 EntityItem::DEFAULT_DIMENSIONS = glm::vec3(0.1f, 0.1f, 0.1f); + void EntityItem::initFromEntityItemID(const EntityItemID& entityItemID) { _id = entityItemID.id; @@ -50,8 +53,8 @@ void EntityItem::initFromEntityItemID(const EntityItemID& entityItemID) { _created = 0; // TODO: when do we actually want to make this "now" _position = glm::vec3(0,0,0); - _radius = 0; - _rotation = ENTITY_DEFAULT_ROTATION; + _rotation = DEFAULT_ROTATION; + _dimensions = DEFAULT_DIMENSIONS; _glowLevel = DEFAULT_GLOW_LEVEL; _mass = DEFAULT_MASS; @@ -61,6 +64,16 @@ void EntityItem::initFromEntityItemID(const EntityItemID& entityItemID) { _lifetime = DEFAULT_LIFETIME; } +EntityItem::EntityItem(const EntityItemID& entityItemID) { + _type = EntityTypes::Unknown; + _lastEdited = 0; + _lastEditedFromRemote = 0; + _lastEditedFromRemoteInRemoteTime = 0; + _lastUpdated = 0; + _created = 0; + initFromEntityItemID(entityItemID); +} + EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) { _type = EntityTypes::Unknown; _lastEdited = 0; @@ -76,7 +89,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param EntityPropertyFlags requestedProperties; requestedProperties += PROP_POSITION; - requestedProperties += PROP_RADIUS; + requestedProperties += PROP_DIMENSIONS; // NOTE: PROP_RADIUS obsolete requestedProperties += PROP_ROTATION; requestedProperties += PROP_MASS; requestedProperties += PROP_VELOCITY; @@ -84,6 +97,9 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_DAMPING; requestedProperties += PROP_LIFETIME; requestedProperties += PROP_SCRIPT; + // TODO: add PROP_REGISTRATION_POINT, + // TODO: add PROP_ROTATIONAL_VELOCITY, + // TODO: add PROP_VISIBLE, return requestedProperties; } @@ -178,10 +194,9 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet // These items would go here once supported.... // PROP_PAGED_PROPERTY, // PROP_CUSTOM_PROPERTIES_INCLUDED, - // PROP_VISIBLE, APPEND_ENTITY_PROPERTY(PROP_POSITION, appendPosition, getPosition()); - APPEND_ENTITY_PROPERTY(PROP_RADIUS, appendValue, getRadius()); + APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, appendValue, getDimensions()); // NOTE: PROP_RADIUS obsolete APPEND_ENTITY_PROPERTY(PROP_ROTATION, appendValue, getRotation()); APPEND_ENTITY_PROPERTY(PROP_MASS, appendValue, getMass()); APPEND_ENTITY_PROPERTY(PROP_VELOCITY, appendValue, getVelocity()); @@ -189,6 +204,9 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_DAMPING, appendValue, getDamping()); APPEND_ENTITY_PROPERTY(PROP_LIFETIME, appendValue, getLifetime()); APPEND_ENTITY_PROPERTY(PROP_SCRIPT, appendValue, getScript()); + // TODO: add PROP_REGISTRATION_POINT, + // TODO: add PROP_ROTATIONAL_VELOCITY, + // TODO: add PROP_VISIBLE, appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, @@ -408,9 +426,23 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef EntityPropertyFlags propertyFlags = encodedPropertyFlags; dataAt += propertyFlags.getEncodedLength(); bytesRead += propertyFlags.getEncodedLength(); - + READ_ENTITY_PROPERTY(PROP_POSITION, glm::vec3, _position); - READ_ENTITY_PROPERTY(PROP_RADIUS, float, _radius); + + // Old bitstreams had PROP_RADIUS, new bitstreams have PROP_DIMENSIONS + if (args.bitstreamVersion < VERSION_ENTITIES_SUPPORT_DIMENSIONS) { + if (propertyFlags.getHasProperty(PROP_RADIUS)) { + float fromBuffer; + memcpy(&fromBuffer, dataAt, sizeof(fromBuffer)); + dataAt += sizeof(fromBuffer); + bytesRead += sizeof(fromBuffer); + if (overwriteLocalData) { + setRadiusInMeters(fromBuffer); + } + } + } else { + READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, _dimensions); + } READ_ENTITY_PROPERTY_QUAT(PROP_ROTATION, _rotation); READ_ENTITY_PROPERTY(PROP_MASS, float, _mass); READ_ENTITY_PROPERTY(PROP_VELOCITY, glm::vec3, _velocity); @@ -418,6 +450,9 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_DAMPING, float, _damping); READ_ENTITY_PROPERTY(PROP_LIFETIME, float, _lifetime); READ_ENTITY_PROPERTY_STRING(PROP_SCRIPT,setScript); + // TODO: add PROP_REGISTRATION_POINT, + // TODO: add PROP_ROTATIONAL_VELOCITY, + // TODO: add PROP_VISIBLE, bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, propertyFlags, overwriteLocalData); @@ -429,7 +464,7 @@ void EntityItem::debugDump() const { qDebug() << "EntityItem id:" << getEntityItemID(); qDebug(" edited ago:%f", getEditedAgo()); qDebug(" position:%f,%f,%f", _position.x, _position.y, _position.z); - qDebug(" radius:%f", getRadius()); + qDebug() << " dimensions:" << _dimensions; } // adjust any internal timestamps to fix clock skew for this server @@ -453,8 +488,14 @@ void EntityItem::adjustEditPacketForClockSkew(unsigned char* editPacketBuffer, s } } +float EntityItem::getDistanceToBottomOfEntity() const { + // TODO: change this to support registration point + return _dimensions.y / 2.0f; +} + bool EntityItem::isRestingOnSurface() const { - return _position.y <= _radius + // TODO: change this to support registration point + return _position.y <= getDistanceToBottomOfEntity() && _velocity.y >= -EPSILON && _velocity.y <= EPSILON && _gravity.y < 0.0f; } @@ -491,8 +532,8 @@ void EntityItem::update(const quint64& updateTime) { position += velocity * timeElapsed; - // handle bounces off the ground... We bounce at the height of our radius... - if (position.y <= _radius) { + // handle bounces off the ground... We bounce at the distance to the bottom of our entity + if (position.y <= getDistanceToBottomOfEntity()) { velocity = velocity * glm::vec3(1,-1,1); // if we've slowed considerably, then just stop moving @@ -500,7 +541,7 @@ void EntityItem::update(const quint64& updateTime) { velocity = NO_VELOCITY; } - position.y = _radius; + position.y = getDistanceToBottomOfEntity(); } // handle gravity.... @@ -512,7 +553,7 @@ void EntityItem::update(const quint64& updateTime) { // "ground" plane of the domain, but for now it if (hasGravity() && isRestingOnSurface()) { velocity.y = 0.0f; - position.y = _radius; + position.y = getDistanceToBottomOfEntity(); } // handle damping @@ -574,7 +615,7 @@ EntityItemProperties EntityItem::getProperties() const { properties._type = getType(); properties._position = getPosition() * (float) TREE_SCALE; - properties._radius = getRadius() * (float) TREE_SCALE; + properties.setDimensions(getDimensions() * (float) TREE_SCALE); properties._rotation = getRotation(); properties._mass = getMass(); @@ -585,7 +626,6 @@ EntityItemProperties EntityItem::getProperties() const { properties._script = getScript(); properties._positionChanged = false; - properties._radiusChanged = false; properties._rotationChanged = false; properties._massChanged = false; properties._velocityChanged = false; @@ -610,55 +650,19 @@ bool EntityItem::setProperties(const EntityItemProperties& properties, bool forc _created = properties.getCreated(); } } - - if (properties._positionChanged || forceCopy) { - // clamp positions to the domain to prevent someone from moving an entity out of the domain - setPosition(glm::clamp(properties._position / (float) TREE_SCALE, 0.0f, 1.0f)); - somethingChanged = true; - } - if (properties._radiusChanged || forceCopy) { - setRadius(properties._radius / (float) TREE_SCALE); - somethingChanged = true; - } - - if (properties._rotationChanged || forceCopy) { - setRotation(properties._rotation); - somethingChanged = true; - } - - if (properties._massChanged || forceCopy) { - setMass(properties._mass); - somethingChanged = true; - } - - if (properties._velocityChanged || forceCopy) { - setVelocity(properties._velocity / (float) TREE_SCALE); - somethingChanged = true; - } - - if (properties._massChanged || forceCopy) { - setMass(properties._mass); - somethingChanged = true; - } - if (properties._gravityChanged || forceCopy) { - setGravity(properties._gravity / (float) TREE_SCALE); - somethingChanged = true; - } - - if (properties._dampingChanged || forceCopy) { - setDamping(properties._damping); - somethingChanged = true; - } - if (properties._lifetimeChanged || forceCopy) { - setLifetime(properties._lifetime); - somethingChanged = true; - } - - if (properties._scriptChanged || forceCopy) { - setScript(properties._script); - somethingChanged = true; - } + SET_ENTITY_PROPERTY_FROM_PROPERTIES(position, setPositionInMeters); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(dimensions, setDimensionsInMeters); // NOTE: radius is obsolete + SET_ENTITY_PROPERTY_FROM_PROPERTIES(rotation, setRotation); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(mass, setMass); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(velocity, setVelocity); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(gravity, setGravity); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(damping, setDamping); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifetime, setLifetime); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(script, setScript); + //SET_ENTITY_PROPERTY_FROM_PROPERTIES(registrationPoint, setRegistrationPoint); + //SET_ENTITY_PROPERTY_FROM_PROPERTIES(rotationalVelocity, setRotationalVelocity); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(glowLevel, setGlowLevel); if (somethingChanged) { somethingChangedNotification(); // notify derived classes that something has changed @@ -675,3 +679,50 @@ bool EntityItem::setProperties(const EntityItemProperties& properties, bool forc return somethingChanged; } +float EntityItem::getSize() const { + return glm::length(_dimensions); +} + +// TODO: Add support for registration point +glm::vec3 EntityItem::getMinimumPoint() const { + // This assumes the registration point is in the center, we need to update this when we really support + // registration point + return _position - (_dimensions / 2.0f); +} + +// TODO: Add support for registration point +glm::vec3 EntityItem::getMaximumPoint() const { + // This assumes the registration point is in the center, we need to update this when we really support + // registration point + return _position + (_dimensions / 2.0f); +} + +// NOTE: This should only be used in cases of old bitstreams which only contain radius data +// 0,0,0 --> maxDimension,maxDimension,maxDimension +// ... has a corner to corner distance of glm::length(maxDimension,maxDimension,maxDimension) +// ... radius = cornerToCornerLength / 2.0f +// ... radius * 2.0f = cornerToCornerLength +// ... cornerToCornerLength = sqrt(3 x maxDimension ^ 2) +// ... cornerToCornerLength = sqrt(3 x maxDimension ^ 2) +// ... radius * 2.0f = sqrt(3 x maxDimension ^ 2) +// ... (radius * 2.0f) ^2 = 3 x maxDimension ^ 2 +// ... ((radius * 2.0f) ^2) / 3 = maxDimension ^ 2 +// ... sqrt(((radius * 2.0f) ^2) / 3) = maxDimension +// ... sqrt((diameter ^2) / 3) = maxDimension +// +void EntityItem::setRadius(float value) { + float diameter = value * 2.0f; + float maxDimension = sqrt((diameter * diameter) / 3.0f); + _dimensions = glm::vec3(maxDimension, maxDimension, maxDimension); +} + +// TODO: get rid of all users of this function... +// ... radius = cornerToCornerLength / 2.0f +// ... cornerToCornerLength = sqrt(3 x maxDimension ^ 2) +// ... radius = sqrt(3 x maxDimension ^ 2) / 2.0f; +float EntityItem::getRadius() const { + float length = glm::length(_dimensions); + float radius = length / 2.0f; + return radius; +} + diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 2d6af48f15..e7cf296f44 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -25,6 +25,7 @@ #include "EntityItemProperties.h" #include "EntityTypes.h" +class EntityTreeElement; class EntityTreeElementExtraEncodeData; #define DONT_ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() = 0; @@ -39,6 +40,7 @@ class EntityItem { public: DONT_ALLOW_INSTANTIATION // This class can not be instantiated directly + EntityItem(const EntityItemID& entityItemID); EntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); virtual ~EntityItem() { } @@ -120,10 +122,21 @@ public: EntityTypes::EntityType getType() const { return _type; } const glm::vec3& getPosition() const { return _position; } /// get position in domain scale units (0.0 - 1.0) void setPosition(const glm::vec3& value) { _position = value; } /// set position in domain scale units (0.0 - 1.0) + void setPositionInMeters(const glm::vec3& value) /// set position in meter units (0.0 - TREE_SCALE) + { setPosition(glm::clamp(value / (float) TREE_SCALE, 0.0f, 1.0f)); } - float getRadius() const { return _radius; } /// get radius in domain scale units (0.0 - 1.0) - void setRadius(float value) { _radius = value; } /// set radius in domain scale units (0.0 - 1.0) + static const glm::vec3 DEFAULT_DIMENSIONS; + const glm::vec3& getDimensions() const { return _dimensions; } /// get dimensions in domain scale units (0.0 - 1.0) + float getDistanceToBottomOfEntity() const; /// get the distance from the position of the entity to its "bottom" in y axis + float getLargestDimension() const { return glm::length(_dimensions); } /// get the largest possible dimension + /// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately + void setDimensions(const glm::vec3& value) { _dimensions = value; } + + /// set dimensions in meter units (0.0 - TREE_SCALE) this will also reset radius appropriately + void setDimensionsInMeters(const glm::vec3& value) { setDimensions(value / (float) TREE_SCALE); } + + static const glm::quat DEFAULT_ROTATION; const glm::quat& getRotation() const { return _rotation; } void setRotation(const glm::quat& rotation) { _rotation = rotation; } @@ -173,9 +186,9 @@ public: bool lifetimeHasExpired() const; // position, size, and bounds related helpers - float getSize() const { return _radius * 2.0f; } /// get maximum dimension in domain scale units (0.0 - 1.0) - glm::vec3 getMinimumPoint() const { return _position - glm::vec3(_radius, _radius, _radius); } - glm::vec3 getMaximumPoint() const { return _position + glm::vec3(_radius, _radius, _radius); } + float getSize() const; /// get maximum dimension in domain scale units (0.0 - 1.0) + glm::vec3 getMinimumPoint() const; + glm::vec3 getMaximumPoint() const; AACube getAACube() const { return AACube(getMinimumPoint(), getSize()); } /// AACube in domain scale units (0.0 - 1.0) static const QString DEFAULT_SCRIPT; @@ -196,7 +209,7 @@ protected: quint64 _created; glm::vec3 _position; - float _radius; + glm::vec3 _dimensions; glm::quat _rotation; float _glowLevel; float _mass; @@ -205,6 +218,24 @@ protected: float _damping; float _lifetime; QString _script; + + // NOTE: Radius support is obsolete, but these private helper functions are available for this class to + // parse old data streams + + /// set radius in domain scale units (0.0 - 1.0) this will also reset dimensions to be equal for each axis + void setRadius(float value); + /// set radius in meter units (0.0 - TREE_SCALE), this will also reset dimensions to be equal for each axis + void setRadiusInMeters(float value) { + float valueInTreeUnits = value / (float) TREE_SCALE; + setRadius(valueInTreeUnits); + } + +private: + // TODO: We need to get rid of these users of getRadius()... but for now, we'll make them friends + // so they can be the only ones accessing this method. + friend EntityTreeElement; + float getRadius() const; + }; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 65babb6e16..f79f64de25 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -18,6 +18,7 @@ #include "EntityItem.h" #include "EntityItemProperties.h" +#include "ModelEntityItem.h" EntityItemProperties::EntityItemProperties() : @@ -28,8 +29,8 @@ EntityItemProperties::EntityItemProperties() : _type(EntityTypes::Unknown), _position(0), - _radius(ENTITY_DEFAULT_RADIUS), - _rotation(ENTITY_DEFAULT_ROTATION), + _dimensions(EntityItem::DEFAULT_DIMENSIONS), + _rotation(EntityItem::DEFAULT_ROTATION), _mass(EntityItem::DEFAULT_MASS), _velocity(EntityItem::DEFAULT_VELOCITY), _gravity(EntityItem::DEFAULT_GRAVITY), @@ -38,7 +39,7 @@ EntityItemProperties::EntityItemProperties() : _script(EntityItem::DEFAULT_SCRIPT), _positionChanged(false), - _radiusChanged(false), + _dimensionsChanged(false), _rotationChanged(false), _massChanged(false), _velocityChanged(false), @@ -50,9 +51,9 @@ EntityItemProperties::EntityItemProperties() : _color(), _modelURL(""), _animationURL(""), - _animationIsPlaying(false), - _animationFrameIndex(0.0), - _animationFPS(ENTITY_DEFAULT_ANIMATION_FPS), + _animationIsPlaying(ModelEntityItem::DEFAULT_ANIMATION_IS_PLAYING), + _animationFrameIndex(ModelEntityItem::DEFAULT_ANIMATION_FRAME_INDEX), + _animationFPS(ModelEntityItem::DEFAULT_ANIMATION_FPS), _glowLevel(0.0f), _colorChanged(false), @@ -73,7 +74,7 @@ void EntityItemProperties::debugDump() const { qDebug() << " _id=" << _id; qDebug() << " _idSet=" << _idSet; qDebug() << " _position=" << _position.x << "," << _position.y << "," << _position.z; - qDebug() << " _radius=" << _radius; + qDebug() << " _dimensions=" << getDimensions(); qDebug() << " _modelURL=" << _modelURL; qDebug() << " changed properties..."; EntityPropertyFlags props = getChangedProperties(); @@ -82,8 +83,8 @@ void EntityItemProperties::debugDump() const { EntityPropertyFlags EntityItemProperties::getChangedProperties() const { EntityPropertyFlags changedProperties; - if (_radiusChanged) { - changedProperties += PROP_RADIUS; + if (_dimensionsChanged) { + changedProperties += PROP_DIMENSIONS; } if (_positionChanged) { @@ -158,7 +159,8 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons QScriptValue position = vec3toScriptValue(engine, _position); properties.setProperty("position", position); - properties.setProperty("radius", _radius); + QScriptValue dimensions = vec3toScriptValue(engine, _dimensions); + properties.setProperty("dimensions", dimensions); QScriptValue rotation = quatToScriptValue(engine, _rotation); properties.setProperty("rotation", rotation); properties.setProperty("mass", _mass); @@ -198,7 +200,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons } void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { - QScriptValue typeScriptValue = object.property("type"); if (typeScriptValue.isValid()) { QString typeName; @@ -222,13 +223,19 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { } } - QScriptValue radius = object.property("radius"); - if (radius.isValid()) { - float newRadius; - newRadius = radius.toVariant().toFloat(); - if (_defaultSettings || newRadius != _radius) { - _radius = newRadius; - _radiusChanged = true; + QScriptValue dimensions = object.property("dimensions"); + if (dimensions.isValid()) { + QScriptValue x = dimensions.property("x"); + QScriptValue y = dimensions.property("y"); + QScriptValue z = dimensions.property("z"); + if (x.isValid() && y.isValid() && z.isValid()) { + glm::vec3 newDimensions; + newDimensions.x = x.toVariant().toFloat(); + newDimensions.y = y.toVariant().toFloat(); + newDimensions.z = z.toVariant().toFloat(); + if (_defaultSettings || newDimensions != getDimensions()) { + setDimensions(newDimensions); + } } } @@ -403,7 +410,6 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { _glowLevelChanged = true; } } - _lastEdited = usecTimestampNow(); } @@ -432,7 +438,6 @@ void EntityItemPropertiesFromScriptValue(const QScriptValue &object, EntityItemP // bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItemID id, const EntityItemProperties& properties, unsigned char* bufferOut, int sizeIn, int& sizeOut) { - OctreePacketData ourDataPacket(false, sizeIn); // create a packetData object to add out packet details too. OctreePacketData* packetData = &ourDataPacket; // we want a pointer to this so we can use our APPEND_ENTITY_PROPERTY macro @@ -535,7 +540,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem // PROP_VISIBLE, APPEND_ENTITY_PROPERTY(PROP_POSITION, appendPosition, properties.getPosition()); - APPEND_ENTITY_PROPERTY(PROP_RADIUS, appendValue, properties.getRadius()); + APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, appendValue, properties.getDimensions()); // NOTE: PROP_RADIUS obsolete APPEND_ENTITY_PROPERTY(PROP_ROTATION, appendValue, properties.getRotation()); APPEND_ENTITY_PROPERTY(PROP_MASS, appendValue, properties.getMass()); APPEND_ENTITY_PROPERTY(PROP_VELOCITY, appendValue, properties.getVelocity()); @@ -727,7 +732,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int processedBytes += propertyFlags.getEncodedLength(); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_POSITION, glm::vec3, setPosition); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RADIUS, float, setRadius); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DIMENSIONS, glm::vec3, setDimensions); // NOTE: PROP_RADIUS obsolete READ_ENTITY_PROPERTY_QUAT_TO_PROPERTIES(PROP_ROTATION, setRotation); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MASS, float, setMass); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VELOCITY, glm::vec3, setVelocity); @@ -741,6 +746,9 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_FPS, float, setAnimationFPS); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_FRAME_INDEX, float, setAnimationFrameIndex); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_PLAYING, bool, setAnimationIsPlaying); + // TODO: add PROP_REGISTRATION_POINT, + // TODO: add PROP_ROTATIONAL_VELOCITY, + // TODO: add PROP_VISIBLE, return valid; } @@ -777,7 +785,6 @@ bool EntityItemProperties::encodeEraseEntityMessage(const EntityItemID& entityIt void EntityItemProperties::markAllChanged() { _positionChanged = true; - _radiusChanged = true; _rotationChanged = true; _massChanged = true; _velocityChanged = true; @@ -795,3 +802,18 @@ void EntityItemProperties::markAllChanged() { _glowLevelChanged = true; } + + +// TODO: Add support for registration point +glm::vec3 EntityItemProperties::getMinimumPointMeters() const { + // This assumes the registration point is in the center, we need to update this when we really support + // registration point + return _position - (_dimensions / 2.0f); +} + +// TODO: Add support for registration point +glm::vec3 EntityItemProperties::getMaximumPointMeters() const { + // This assumes the registration point is in the center, we need to update this when we really support + // registration point + return _position + (_dimensions / 2.0f); +} diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index fc506ce10c..881a0b4afc 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -31,16 +32,6 @@ #include "EntityTypes.h" -// TODO: should these be static members of EntityItem or EntityItemProperties? -const float ENTITY_DEFAULT_RADIUS = 0.1f / TREE_SCALE; -const float ENTITY_MINIMUM_ELEMENT_SIZE = (1.0f / 100000.0f) / TREE_SCALE; // smallest size container -const QString ENTITY_DEFAULT_MODEL_URL(""); -const glm::quat ENTITY_DEFAULT_ROTATION; -const QString ENTITY_DEFAULT_ANIMATION_URL(""); -const float ENTITY_DEFAULT_ANIMATION_FPS = 30.0f; - -const quint64 UNKNOWN_CREATED_TIME = (quint64)(-1); -const quint64 USE_EXISTING_CREATED_TIME = (quint64)(-2); // PropertyFlags support enum EntityPropertyList { @@ -50,7 +41,8 @@ enum EntityPropertyList { // these properties are supported by the EntityItem base class PROP_VISIBLE, PROP_POSITION, - PROP_RADIUS, + PROP_RADIUS, // NOTE: PROP_RADIUS is obsolete and only included in old format streams + PROP_DIMENSIONS = PROP_RADIUS, PROP_ROTATION, PROP_MASS, PROP_VELOCITY, @@ -67,16 +59,23 @@ enum EntityPropertyList { PROP_ANIMATION_FRAME_INDEX, PROP_ANIMATION_PLAYING, - PROP_LAST_ITEM = PROP_ANIMATION_PLAYING + // these properties are supported by the EntityItem base class + PROP_REGISTRATION_POINT, + PROP_ROTATIONAL_VELOCITY, + + PROP_LAST_ITEM = PROP_ROTATIONAL_VELOCITY }; typedef PropertyFlags EntityPropertyFlags; +const quint64 UNKNOWN_CREATED_TIME = (quint64)(-1); +const quint64 USE_EXISTING_CREATED_TIME = (quint64)(-2); + /// A collection of properties of an entity item used in the scripting API. Translates between the actual properties of an /// entity and a JavaScript style hash/QScriptValue storing a set of properties. Used in scripting to set/get the complete /// set of entity item properties via JavaScript hashes/QScriptValues -/// all units for position, radius, etc are in meter units +/// all units for position, dimensions, etc are in meter units class EntityItemProperties { friend class EntityItem; // TODO: consider removing this friend relationship and use public methods friend class ModelEntityItem; // TODO: consider removing this friend relationship and use public methods @@ -96,8 +95,8 @@ public: /// used by EntityScriptingInterface to return EntityItemProperties for unknown models void setIsUnknownID() { _id = UNKNOWN_ENTITY_ID; _idSet = true; } - glm::vec3 getMinimumPointMeters() const { return _position - glm::vec3(_radius, _radius, _radius); } - glm::vec3 getMaximumPointMeters() const { return _position + glm::vec3(_radius, _radius, _radius); } + glm::vec3 getMinimumPointMeters() const; + glm::vec3 getMaximumPointMeters() const; AACube getAACubeMeters() const { return AACube(getMinimumPointMeters(), getMaxDimension()); } /// AACube in meter units glm::vec3 getMinimumPointTreeUnits() const { return getMinimumPointMeters() / (float)TREE_SCALE; } @@ -109,18 +108,22 @@ public: void debugDump() const; + // properties of all entities EntityTypes::EntityType getType() const { return _type; } - const glm::vec3& getPosition() const { return _position; } - float getRadius() const { return _radius; } - float getMaxDimension() const { return _radius * 2.0f; } - glm::vec3 getDimensions() const { return glm::vec3(_radius, _radius, _radius) * 2.0f; } - const glm::quat& getRotation() const { return _rotation; } void setType(EntityTypes::EntityType type) { _type = type; } + + const glm::vec3& getPosition() const { return _position; } /// set position in meter units, will be clamped to domain bounds void setPosition(const glm::vec3& value) { _position = glm::clamp(value, 0.0f, (float)TREE_SCALE); _positionChanged = true; } - void setRadius(float value) { _radius = value; _radiusChanged = true; } + + + const glm::vec3& getDimensions() const { return _dimensions; } + void setDimensions(const glm::vec3& value) { _dimensions = value; _dimensionsChanged = true; } + float getMaxDimension() const { return glm::max(_dimensions.x, _dimensions.y, _dimensions.z); } + + const glm::quat& getRotation() const { return _rotation; } void setRotation(const glm::quat& rotation) { _rotation = rotation; _rotationChanged = true; } float getMass() const { return _mass; } @@ -148,9 +151,9 @@ public: // NOTE: how do we handle _defaultSettings??? - bool containsBoundsProperties() const { return (_positionChanged || _radiusChanged); } + bool containsBoundsProperties() const { return (_positionChanged || _dimensionsChanged); } bool containsPositionChange() const { return _positionChanged; } - bool containsRadiusChange() const { return _radiusChanged; } + bool containsDimensionsChange() const { return _dimensionsChanged; } // TODO: this need to be more generic. for now, we're going to have the properties class support these as // named getter/setters, but we want to move them to generic types... @@ -184,7 +187,6 @@ public: EntityItemID& entityID, EntityItemProperties& properties); bool positionChanged() const { return _positionChanged; } - bool radiusChanged() const { return _radiusChanged; } bool rotationChanged() const { return _rotationChanged; } bool massChanged() const { return _massChanged; } bool velocityChanged() const { return _velocityChanged; } @@ -192,6 +194,8 @@ public: bool dampingChanged() const { return _dampingChanged; } bool lifetimeChanged() const { return _lifetimeChanged; } bool scriptChanged() const { return _scriptChanged; } + bool dimensionsChanged() const { return _dimensionsChanged; } + bool registrationPointChanged() const { return _registrationPointChanged; } bool colorChanged() const { return _colorChanged; } bool modelURLChanged() const { return _modelURLChanged; } bool animationURLChanged() const { return _animationURLChanged; } @@ -213,7 +217,7 @@ private: EntityTypes::EntityType _type; glm::vec3 _position; - float _radius; + glm::vec3 _dimensions; glm::quat _rotation; float _mass; glm::vec3 _velocity; @@ -221,9 +225,10 @@ private: float _damping; float _lifetime; QString _script; + glm::vec3 _registrationPoint; bool _positionChanged; - bool _radiusChanged; + bool _dimensionsChanged; bool _rotationChanged; bool _massChanged; bool _velocityChanged; @@ -231,6 +236,7 @@ private: bool _dampingChanged; bool _lifetimeChanged; bool _scriptChanged; + bool _registrationPointChanged; // TODO: this need to be more generic. for now, we're going to have the properties class support these as // named getter/setters, but we want to move them to generic types... @@ -358,6 +364,17 @@ void EntityItemPropertiesFromScriptValue(const QScriptValue &object, EntityItemP properties.O(color); \ } +#define SET_ENTITY_PROPERTY_FROM_PROPERTIES(P,M) \ + if (properties._##P##Changed || forceCopy) { \ + M(properties._##P); \ + somethingChanged = true; \ + } + +#define SET_ENTITY_PROPERTY_FROM_PROPERTIES_GETTER(C,G,S) \ + if (properties.C() || forceCopy) { \ + S(properties.G()); \ + somethingChanged = true; \ + } #endif // hifi_EntityItemProperties_h diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 8f223abf7e..7f94d362eb 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -555,6 +555,7 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con return somethingIntersected; } +// TODO: change this to use better bounding shape for entity than sphere bool EntityTreeElement::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject) const { QList::iterator entityItr = _entityItems->begin(); @@ -605,6 +606,7 @@ const EntityItem* EntityTreeElement::getClosestEntity(glm::vec3 position) const return closestEntity; } +// TODO: change this to use better bounding shape for entity than sphere void EntityTreeElement::getEntities(const glm::vec3& searchPosition, float searchRadius, QVector& foundEntities) const { uint16_t numberOfEntities = _entityItems->size(); for (uint16_t i = 0; i < numberOfEntities; i++) { @@ -616,6 +618,7 @@ void EntityTreeElement::getEntities(const glm::vec3& searchPosition, float searc } } +// TODO: change this to use better bounding shape for entity than sphere void EntityTreeElement::getEntities(const AACube& box, QVector& foundEntities) { QList::iterator entityItr = _entityItems->begin(); QList::iterator entityEnd = _entityItems->end(); diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 1c1cd19831..7989d085c6 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -17,6 +17,13 @@ #include "ModelEntityItem.h" +const QString ModelEntityItem::DEFAULT_MODEL_URL = QString(""); +const QString ModelEntityItem::DEFAULT_ANIMATION_URL = QString(""); +const float ModelEntityItem::DEFAULT_ANIMATION_FRAME_INDEX = 0.0f; +const bool ModelEntityItem::DEFAULT_ANIMATION_IS_PLAYING = false; +const float ModelEntityItem::DEFAULT_ANIMATION_FPS = 30.0f; + + EntityItem* ModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { return new ModelEntityItem(entityID, properties); } @@ -55,40 +62,13 @@ EntityItemProperties ModelEntityItem::getProperties() const { bool ModelEntityItem::setProperties(const EntityItemProperties& properties, bool forceCopy) { bool somethingChanged = false; somethingChanged = EntityItem::setProperties(properties, forceCopy); // set the properties in our base class - if (properties._colorChanged || forceCopy) { - setColor(properties._color); - somethingChanged = true; - } - if (properties._modelURLChanged || forceCopy) { - setModelURL(properties._modelURL); - somethingChanged = true; - } - - if (properties._animationURLChanged || forceCopy) { - setAnimationURL(properties._animationURL); - somethingChanged = true; - } - - if (properties._animationIsPlayingChanged || forceCopy) { - setAnimationIsPlaying(properties._animationIsPlaying); - somethingChanged = true; - } - - if (properties._animationFrameIndexChanged || forceCopy) { - setAnimationFrameIndex(properties._animationFrameIndex); - somethingChanged = true; - } - - if (properties._animationFPSChanged || forceCopy) { - setAnimationFPS(properties._animationFPS); - somethingChanged = true; - } - - if (properties._glowLevelChanged || forceCopy) { - setGlowLevel(properties._glowLevel); - somethingChanged = true; - } + SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(modelURL, setModelURL); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationURL, setAnimationURL); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationIsPlaying, setAnimationIsPlaying); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationFrameIndex, setAnimationFrameIndex); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationFPS, setAnimationFPS); if (somethingChanged) { bool wantDebug = false; @@ -169,9 +149,11 @@ int ModelEntityItem::oldVersionReadEntityDataFromBuffer(const unsigned char* dat << "old ID=" << oldID << "new ID=" << _id; // radius - memcpy(&_radius, dataAt, sizeof(_radius)); - dataAt += sizeof(_radius); - bytesRead += sizeof(_radius); + float radius; + memcpy(&radius, dataAt, sizeof(radius)); + dataAt += sizeof(radius); + bytesRead += sizeof(radius); + setRadius(radius); // position memcpy(&_position, dataAt, sizeof(_position)); @@ -393,7 +375,7 @@ void ModelEntityItem::debugDump() const { qDebug() << "ModelEntityItem id:" << getEntityItemID(); qDebug() << " edited ago:" << getEditedAgo(); qDebug() << " position:" << getPosition() * (float)TREE_SCALE; - qDebug() << " radius:" << getRadius() * (float)TREE_SCALE; + qDebug() << " dimensions:" << getDimensions() * (float)TREE_SCALE; qDebug() << " model URL:" << getModelURL(); } diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index c8d2abf29a..7af2c08332 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -54,8 +54,12 @@ public: const rgbColor& getColor() const { return _color; } xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; } bool hasModel() const { return !_modelURL.isEmpty(); } + + static const QString DEFAULT_MODEL_URL; const QString& getModelURL() const { return _modelURL; } + bool hasAnimation() const { return !_animationURL.isEmpty(); } + static const QString DEFAULT_ANIMATION_URL; const QString& getAnimationURL() const { return _animationURL; } QVector getSittingPoints() const { return _sittingPoints; } @@ -69,8 +73,13 @@ public: // model related properties void setModelURL(const QString& url) { _modelURL = url; } void setAnimationURL(const QString& url) { _animationURL = url; } + static const float DEFAULT_ANIMATION_FRAME_INDEX; void setAnimationFrameIndex(float value) { _animationFrameIndex = value; } + + static const bool DEFAULT_ANIMATION_IS_PLAYING; void setAnimationIsPlaying(bool value) { _animationIsPlaying = value; } + + static const float DEFAULT_ANIMATION_FPS; void setAnimationFPS(float value) { _animationFPS = value; } void setSittingPoints(QVector sittingPoints) { _sittingPoints = sittingPoints; } diff --git a/libraries/entities/src/SphereEntityItem.cpp b/libraries/entities/src/SphereEntityItem.cpp index 836cc24524..09364ddbfe 100644 --- a/libraries/entities/src/SphereEntityItem.cpp +++ b/libraries/entities/src/SphereEntityItem.cpp @@ -43,15 +43,7 @@ EntityItemProperties SphereEntityItem::getProperties() const { bool SphereEntityItem::setProperties(const EntityItemProperties& properties, bool forceCopy) { bool somethingChanged = EntityItem::setProperties(properties, forceCopy); // set the properties in our base class - if (properties.colorChanged() || forceCopy) { - setColor(properties.getColor()); - somethingChanged = true; - } - - if (properties.glowLevelChanged() || forceCopy) { - setGlowLevel(properties.getGlowLevel()); - somethingChanged = true; - } + SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor); if (somethingChanged) { bool wantDebug = false; diff --git a/libraries/entities/src/UpdateEntityOperator.cpp b/libraries/entities/src/UpdateEntityOperator.cpp index 65a86a80ca..28fa8f4040 100644 --- a/libraries/entities/src/UpdateEntityOperator.cpp +++ b/libraries/entities/src/UpdateEntityOperator.cpp @@ -39,15 +39,14 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree, _oldEntityCube = _existingEntity->getAACube(); _oldEntityBox = _oldEntityCube.clamp(0.0f, 1.0f); // clamp to domain bounds - // If the new properties has position OR radius changes, but not both, we need to + // If the new properties has position OR dimension changes, but not both, we need to // get the old property value and set it in our properties in order for our bounds // calculations to work. - if (_properties.containsPositionChange() && !_properties.containsRadiusChange()) { - float oldRadiusInMeters = _existingEntity->getRadius() * (float)TREE_SCALE; - _properties.setRadius(oldRadiusInMeters); + if (_properties.containsPositionChange() && !_properties.containsDimensionsChange()) { + glm::vec3 oldDimensionsInMeters = _existingEntity->getDimensions() * (float)TREE_SCALE; + _properties.setDimensions(oldDimensionsInMeters); } - - if (!_properties.containsPositionChange() && _properties.containsRadiusChange()) { + if (!_properties.containsPositionChange() && _properties.containsDimensionsChange()) { glm::vec3 oldPositionInMeters = _existingEntity->getPosition() * (float)TREE_SCALE; _properties.setPosition(oldPositionInMeters); } diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index f3937dd2e3..5513c09a61 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -75,8 +75,11 @@ PacketVersion versionForPacketType(PacketType type) { return 1; case PacketTypeParticleErase: return 1; + + case PacketTypeEntityAddOrEdit: case PacketTypeEntityData: - return VERSION_ENTITIES_SUPPORT_SPLIT_MTU; + return VERSION_ENTITIES_SUPPORT_DIMENSIONS; + case PacketTypeEntityErase: return 2; case PacketTypeAudioStreamStats: diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index bb64388dd6..207cf680d3 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -117,6 +117,7 @@ const PacketVersion VERSION_ENTITIES_HAVE_ANIMATION = 1; const PacketVersion VERSION_ROOT_ELEMENT_HAS_DATA = 2; const PacketVersion VERSION_ENTITIES_SUPPORT_SPLIT_MTU = 3; const PacketVersion VERSION_ENTITIES_HAS_FILE_BREAKS = VERSION_ENTITIES_SUPPORT_SPLIT_MTU; +const PacketVersion VERSION_ENTITIES_SUPPORT_DIMENSIONS = 4; const PacketVersion VERSION_VOXELS_HAS_FILE_BREAKS = 1; #endif // hifi_PacketHeaders_h diff --git a/tests/octree/src/ModelTests.cpp b/tests/octree/src/ModelTests.cpp index b91963726f..405b4a95d3 100644 --- a/tests/octree/src/ModelTests.cpp +++ b/tests/octree/src/ModelTests.cpp @@ -45,7 +45,7 @@ void EntityTests::entityTreeTests(bool verbose) { 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; + //float halfMeter = oneMeter / 2.0f; float halfOfDomain = TREE_SCALE * 0.5f; glm::vec3 positionNearOriginInMeters(oneMeter, oneMeter, oneMeter); // when using properties, these are in meter not tree units glm::vec3 positionAtCenterInMeters(halfOfDomain, halfOfDomain, halfOfDomain); @@ -60,7 +60,8 @@ void EntityTests::entityTreeTests(bool verbose) { } properties.setPosition(positionAtCenterInMeters); - properties.setRadius(halfMeter); + // TODO: Fix these unit tests. + //properties.setRadius(halfMeter); //properties.setModelURL("https://s3-us-west-1.amazonaws.com/highfidelity-public/ozan/theater.fbx"); tree.addEntity(entityID, properties); @@ -265,8 +266,10 @@ void EntityTests::entityTreeTests(bool verbose) { glm::vec3 randomPositionInTreeUnits = randomPositionInMeters / (float)TREE_SCALE; properties.setPosition(randomPositionInMeters); - properties.setRadius(halfMeter); -//properties.setModelURL("https://s3-us-west-1.amazonaws.com/highfidelity-public/ozan/theater.fbx"); + + // TODO: fix these unit tests + //properties.setRadius(halfMeter); + //properties.setModelURL("https://s3-us-west-1.amazonaws.com/highfidelity-public/ozan/theater.fbx"); if (extraVerbose) { qDebug() << "iteration:" << i