From f00947ada7adeaf8e63301591c0658d61c451054 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 11 Sep 2014 08:33:41 -0700 Subject: [PATCH] handle registration point in rendering of box, sphere, and model entities --- examples/editModels.js | 10 +++++ .../src/entities/RenderableBoxEntityItem.cpp | 18 ++++++--- .../entities/RenderableModelEntityItem.cpp | 2 +- .../entities/RenderableSphereEntityItem.cpp | 14 +++++-- interface/src/renderer/Model.cpp | 34 +++++++++-------- interface/src/renderer/Model.h | 19 +++++++--- libraries/entities/src/EntityItem.cpp | 38 ++++++++++--------- libraries/entities/src/EntityItem.h | 5 ++- 8 files changed, 91 insertions(+), 49 deletions(-) diff --git a/examples/editModels.js b/examples/editModels.js index ca45c94995..740c992888 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -2865,6 +2865,13 @@ function handeMenuEvent(menuItem) { array.push({ label: "Z:", value: properties.position.z.toFixed(decimals) }); index++; + array.push({ label: "Registration X:", value: properties.registrationPoint.x.toFixed(decimals) }); + index++; + array.push({ label: "Registration Y:", value: properties.registrationPoint.y.toFixed(decimals) }); + index++; + array.push({ label: "Registration Z:", value: properties.registrationPoint.z.toFixed(decimals) }); + index++; + array.push({ label: "Rotation:", type: "header" }); index++; var angles = Quat.safeEulerAngles(properties.rotation); @@ -3023,6 +3030,9 @@ Window.nonBlockingFormClosed.connect(function() { properties.position.x = array[index++].value; properties.position.y = array[index++].value; properties.position.z = array[index++].value; + properties.registrationPoint.x = array[index++].value; + properties.registrationPoint.y = array[index++].value; + properties.registrationPoint.z = array[index++].value; index++; // skip header var angles = Quat.safeEulerAngles(properties.rotation); diff --git a/interface/src/entities/RenderableBoxEntityItem.cpp b/interface/src/entities/RenderableBoxEntityItem.cpp index 0156f051ae..1397bf8e34 100644 --- a/interface/src/entities/RenderableBoxEntityItem.cpp +++ b/interface/src/entities/RenderableBoxEntityItem.cpp @@ -32,7 +32,8 @@ EntityItem* RenderableBoxEntityItem::factory(const EntityItemID& entityID, const void RenderableBoxEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableBoxEntityItem::render"); assert(getType() == EntityTypes::Box); - glm::vec3 position = getPosition() * (float)TREE_SCALE; + glm::vec3 position = getPositionInMeters(); + glm::vec3 center = getCenter() * (float)TREE_SCALE; glm::vec3 dimensions = getDimensions() * (float)TREE_SCALE; glm::vec3 halfDimensions = dimensions / 2.0f; glm::quat rotation = getRotation(); @@ -43,7 +44,7 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { if (useGlutCube) { glColor3ub(getColor()[RED_INDEX], getColor()[GREEN_INDEX], getColor()[BLUE_INDEX]); glPushMatrix(); - glTranslatef(position.x, position.y, position.z); + glTranslatef(center.x, center.y, center.z); 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); @@ -87,10 +88,15 @@ 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); - - // we need to do half the size because the geometry in the VBOs are from -1,-1,-1 to 1,1,1 - glScalef(halfDimensions.x, halfDimensions.y, halfDimensions.z); - glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, indices); + + + glPushMatrix(); + glm::vec3 positionToCenter = center - position; + glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); + // we need to do half the size because the geometry in the VBOs are from -1,-1,-1 to 1,1,1 + glScalef(halfDimensions.x, halfDimensions.y, halfDimensions.z); + glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, indices); + glPopMatrix(); glPopMatrix(); glDisableClientState(GL_VERTEX_ARRAY); // disable vertex arrays diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index f74abd2a13..643cceb030 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -99,7 +99,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { glm::quat rotation = getRotation(); if (needsSimulation() && _model->isActive()) { _model->setScaleToFit(true, dimensions); - _model->setSnapModelToCenter(true); + _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); _model->setRotation(rotation); _model->setTranslation(position); diff --git a/interface/src/entities/RenderableSphereEntityItem.cpp b/interface/src/entities/RenderableSphereEntityItem.cpp index d03a384063..d5286b0ab3 100644 --- a/interface/src/entities/RenderableSphereEntityItem.cpp +++ b/interface/src/entities/RenderableSphereEntityItem.cpp @@ -31,7 +31,8 @@ EntityItem* RenderableSphereEntityItem::factory(const EntityItemID& entityID, co void RenderableSphereEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableSphereEntityItem::render"); assert(getType() == EntityTypes::Sphere); - glm::vec3 position = getPosition() * (float)TREE_SCALE; + glm::vec3 position = getPositionInMeters(); + glm::vec3 center = getCenterInMeters(); glm::vec3 dimensions = getDimensions() * (float)TREE_SCALE; glm::quat rotation = getRotation(); @@ -40,7 +41,14 @@ void RenderableSphereEntityItem::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); - glScalef(dimensions.x, dimensions.y, dimensions.z); - glutSolidSphere(0.5f, 15, 15); + + + glPushMatrix(); + glm::vec3 positionToCenter = center - position; + glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); + + glScalef(dimensions.x, dimensions.y, dimensions.z); + glutSolidSphere(0.5f, 15, 15); + glPopMatrix(); glPopMatrix(); }; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 867083fe90..280f5bd21a 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -56,8 +56,8 @@ Model::Model(QObject* parent) : _scaleToFit(false), _scaleToFitDimensions(0.0f), _scaledToFit(false), - _snapModelToCenter(false), - _snappedToCenter(false), + _snapModelToRegistrationPoint(false), + _snappedToRegistrationPoint(false), _showTrueJointTransforms(true), _lodDistance(0.0f), _pupilDilation(0.0f), @@ -157,8 +157,8 @@ void Model::setOffset(const glm::vec3& offset) { _offset = offset; // if someone manually sets our offset, then we are no longer snapped to center - _snapModelToCenter = false; - _snappedToCenter = false; + _snapModelToRegistrationPoint = false; + _snappedToRegistrationPoint = false; } void Model::initProgram(ProgramObject& program, Model::Locations& locations, @@ -905,30 +905,34 @@ void Model::scaleToFit() { _scaledToFit = true; } -void Model::setSnapModelToCenter(bool snapModelToCenter) { - if (_snapModelToCenter != snapModelToCenter) { - _snapModelToCenter = snapModelToCenter; - _snappedToCenter = false; // force re-centering +void Model::setSnapModelToRegistrationPoint(bool snapModelToRegistrationPoint, const glm::vec3& registrationPoint) { + glm::vec3 clampedRegistrationPoint = glm::clamp(registrationPoint, 0.0f, 1.0f); + if (_snapModelToRegistrationPoint != snapModelToRegistrationPoint || _registrationPoint != clampedRegistrationPoint) { + _snapModelToRegistrationPoint = snapModelToRegistrationPoint; + _registrationPoint = clampedRegistrationPoint; + _snappedToRegistrationPoint = false; // force re-centering } } -void Model::snapToCenter() { +void Model::snapToRegistrationPoint() { Extents modelMeshExtents = getUnscaledMeshExtents(); - glm::vec3 halfDimensions = (modelMeshExtents.maximum - modelMeshExtents.minimum) * 0.5f; - glm::vec3 offset = -modelMeshExtents.minimum - halfDimensions; + glm::vec3 dimensions = (modelMeshExtents.maximum - modelMeshExtents.minimum); + glm::vec3 offset = -modelMeshExtents.minimum - (dimensions * _registrationPoint); _offset = offset; - _snappedToCenter = true; + _snappedToRegistrationPoint = true; } void Model::simulate(float deltaTime, bool fullUpdate) { - fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit) || (_snapModelToCenter && !_snappedToCenter); + fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit) + || (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint); + if (isActive() && fullUpdate) { // check for scale to fit if (_scaleToFit && !_scaledToFit) { scaleToFit(); } - if (_snapModelToCenter && !_snappedToCenter) { - snapToCenter(); + if (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint) { + snapToRegistrationPoint(); } simulateInternal(deltaTime); } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index f56aed37a0..6c27970d8e 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -55,8 +55,15 @@ public: 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; } + void setSnapModelToCenter(bool snapModelToCenter) { + setSnapModelToRegistrationPoint(snapModelToCenter, glm::vec3(0.5f,0.5f,0.5f)); + }; + bool getSnapModelToCenter() { + return _snapModelToRegistrationPoint && _registrationPoint == glm::vec3(0.5f,0.5f,0.5f); + } + + void setSnapModelToRegistrationPoint(bool snapModelToRegistrationPoint, const glm::vec3& registrationPoint); + bool getSnapModelToRegistrationPoint() { return _snapModelToRegistrationPoint; } void setScale(const glm::vec3& scale); const glm::vec3& getScale() const { return _scale; } @@ -185,8 +192,10 @@ protected: 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 - bool _snappedToCenter; /// are we currently snapped to center + bool _snapModelToRegistrationPoint; /// is the model's offset automatically adjusted to a registration point in model space + bool _snappedToRegistrationPoint; /// are we currently snapped to a registration point + glm::vec3 _registrationPoint; /// the point in model space our center is snapped to + bool _showTrueJointTransforms; QVector _localLights; @@ -207,7 +216,7 @@ protected: void setScaleInternal(const glm::vec3& scale); void scaleToFit(); - void snapToCenter(); + void snapToRegistrationPoint(); void simulateInternal(float deltaTime); diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index fc66b9bc6c..d84b11284f 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -499,14 +499,6 @@ void EntityItem::adjustEditPacketForClockSkew(unsigned char* editPacketBuffer, s } } -float EntityItem::getDistanceToBottomOfEntity() const { - // TODO: change this to support registration point - // TODO: fix this to correctly handle rotation... since _dimensions is in entity space, - // if the entity has been rotated, then the distance to world.y=0 is not the same - // as the dimensions.y - return _dimensions.y / 2.0f; -} - bool EntityItem::isRestingOnSurface() const { // TODO: change this to support registration point return _position.y <= getDistanceToBottomOfEntity() @@ -727,20 +719,30 @@ 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: fix this to correctly handle rotation... since _dimensions is in entity space, +// if the entity has been rotated, then the distance to world.y=0 is not the same +// as the dimensions.y +float EntityItem::getDistanceToBottomOfEntity() const { + glm::vec3 minimumPoint = getMinimumPoint(); + return minimumPoint.y; } -// 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); +// TODO: doesn't this need to handle rotation? +glm::vec3 EntityItem::getMinimumPoint() const { + return _position - (_dimensions * _registrationPoint); } +// TODO: doesn't this need to handle rotation? +glm::vec3 EntityItem::getMaximumPoint() const { + glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint; + return _position + (_dimensions * registrationRemainder); +} + +glm::vec3 EntityItem::getCenter() const { + return _position + (_dimensions * (glm::vec3(0.5f,0.5f,0.5f) - _registrationPoint)); +} + + // 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) diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index a95bb3f462..08d44fc553 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -126,6 +126,9 @@ public: 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)); } + glm::vec3 getCenter() const; /// calculates center of the entity in domain scale units (0.0 - 1.0) + glm::vec3 getCenterInMeters() const { return getCenter() * (float) TREE_SCALE; } + static const glm::vec3 DEFAULT_DIMENSIONS; const glm::vec3& getDimensions() const { return _dimensions; } /// get dimensions in domain scale units (0.0 - 1.0) glm::vec3 getDimensionsInMeters() const { return _dimensions * (float) TREE_SCALE; } /// get dimensions in meters @@ -203,7 +206,7 @@ public: static const glm::vec3 DEFAULT_REGISTRATION_POINT; const glm::vec3& getRegistrationPoint() const { return _registrationPoint; } /// registration point as ratio of entity - void setRegistrationPoint(const glm::vec3& value) { _registrationPoint = value; } /// registration point as ratio of entity + void setRegistrationPoint(const glm::vec3& value) { _registrationPoint = glm::clamp(value, 0.0f, 1.0f); } /// registration point as ratio of entity static const glm::vec3 NO_ANGULAR_VELOCITY; static const glm::vec3 DEFAULT_ANGULAR_VELOCITY;