From 8e7a2ac5362349aab0c0af4a697733b79a6e493e Mon Sep 17 00:00:00 2001 From: AlessandroSigna Date: Tue, 15 Dec 2015 15:41:36 -0800 Subject: [PATCH 01/15] Exposing emmisive property of the Image3DOverlay --- interface/src/ui/overlays/Image3DOverlay.cpp | 18 ++++++++++++++---- interface/src/ui/overlays/Image3DOverlay.h | 1 + 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/overlays/Image3DOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp index 11fb647f01..6e4c274943 100644 --- a/interface/src/ui/overlays/Image3DOverlay.cpp +++ b/interface/src/ui/overlays/Image3DOverlay.cpp @@ -26,14 +26,16 @@ QString const Image3DOverlay::TYPE = "image3d"; Image3DOverlay::Image3DOverlay() { - _isLoaded = false; + _isLoaded = false; + _emmisive = false; } Image3DOverlay::Image3DOverlay(const Image3DOverlay* image3DOverlay) : Billboard3DOverlay(image3DOverlay), _url(image3DOverlay->_url), _texture(image3DOverlay->_texture), - _fromImage(image3DOverlay->_fromImage) + _fromImage(image3DOverlay->_fromImage), + _emmisive(image3DOverlay->_emmisive) { } @@ -93,8 +95,8 @@ void Image3DOverlay::render(RenderArgs* args) { batch->setModelTransform(transform); batch->setResourceTexture(0, _texture->getGPUTexture()); - - DependencyManager::get()->bindSimpleProgram(*batch, true, false, false, true); + + DependencyManager::get()->bindSimpleProgram(*batch, true, false, _emmisive, true); DependencyManager::get()->renderQuad( *batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha) @@ -144,6 +146,11 @@ void Image3DOverlay::setProperties(const QScriptValue &properties) { setClipFromSource(subImageRect); } } + + QScriptValue emmisiveValue = properties.property("emmisive"); + if (emmisiveValue.isValid()) { + _emmisive = emmisiveValue.toBool(); + } } QScriptValue Image3DOverlay::getProperty(const QString& property) { @@ -156,6 +163,9 @@ QScriptValue Image3DOverlay::getProperty(const QString& property) { if (property == "offsetPosition") { return vec3toScriptValue(_scriptEngine, getOffsetPosition()); } + if (property == "emmisive") { + return _emmisive; + } return Billboard3DOverlay::getProperty(property); } diff --git a/interface/src/ui/overlays/Image3DOverlay.h b/interface/src/ui/overlays/Image3DOverlay.h index f848023fbe..0e40c73619 100644 --- a/interface/src/ui/overlays/Image3DOverlay.h +++ b/interface/src/ui/overlays/Image3DOverlay.h @@ -46,6 +46,7 @@ public: private: QString _url; NetworkTexturePointer _texture; + bool _emmisive; QRect _fromImage; // where from in the image to sample }; From e9f52b12116ea4e67c2c083dae73cb6002e6fdd5 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 10 Dec 2015 14:40:30 -0800 Subject: [PATCH 02/15] properly scale avatar collision shape --- interface/src/Application.cpp | 5 +- interface/src/avatar/Avatar.cpp | 76 +++++++++++-------- interface/src/avatar/Avatar.h | 12 +-- interface/src/avatar/AvatarManager.cpp | 26 +++---- interface/src/avatar/AvatarMotionState.h | 2 +- interface/src/avatar/Hand.cpp | 6 +- interface/src/avatar/MyAvatar.cpp | 46 +++++++---- interface/src/avatar/MyAvatar.h | 5 +- .../src/avatar/MyCharacterController.cpp | 2 +- interface/src/avatar/SkeletonModel.cpp | 2 +- interface/src/ui/ApplicationCompositor.cpp | 2 +- interface/src/ui/PreferencesDialog.cpp | 2 +- interface/src/ui/overlays/OverlaysPayload.cpp | 2 +- libraries/avatars/src/AvatarData.cpp | 2 +- 14 files changed, 108 insertions(+), 82 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 930d3b0b8f..c34d2ce649 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1260,15 +1260,14 @@ void Application::paintGL() { hmdOffset.x = -hmdOffset.x; _myCamera.setPosition(myAvatar->getDefaultEyePosition() - + glm::vec3(0, _raiseMirror * myAvatar->getAvatarScale(), 0) + + glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0) + mirrorBodyOrientation * glm::vec3(0.0f, 0.0f, 1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror + mirrorBodyOrientation * hmdOffset); - } else { _myCamera.setRotation(myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))); _myCamera.setPosition(myAvatar->getDefaultEyePosition() - + glm::vec3(0, _raiseMirror * myAvatar->getAvatarScale(), 0) + + glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0) + (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror); } diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 7a234f2b47..8231d1ebdd 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -99,7 +99,8 @@ Avatar::Avatar(RigPointer rig) : // we may have been created in the network thread, but we live in the main thread moveToThread(qApp->thread()); - setAvatarScale(1.0f); + setScale(glm::vec3(1.0f)); // avatar scale is uniform + // give the pointer to our head to inherited _headData variable from AvatarData _headData = static_cast(new Head(this)); _handData = static_cast(new Hand(this)); @@ -143,15 +144,28 @@ AABox Avatar::getBounds() const { float Avatar::getLODDistance() const { return DependencyManager::get()->getAvatarLODDistanceMultiplier() * - glm::distance(qApp->getCamera()->getPosition(), getPosition()) / getAvatarScale(); + glm::distance(qApp->getCamera()->getPosition(), getPosition()) / getUniformScale(); +} + +void Avatar::animateScaleChanges(float deltaTime) { + float currentScale = getUniformScale(); + if (currentScale != _targetScale) { + const float SCALE_ANIMATION_TIMESCALE = 1.0f; + float blendFactor = deltaTime / SCALE_ANIMATION_TIMESCALE; + float animatedScale = (1.0f - blendFactor) * currentScale + blendFactor * _targetScale; + const float CLOSE_ENOUGH = 0.05f; + if (fabsf(animatedScale - _targetScale) / _targetScale < CLOSE_ENOUGH) { + animatedScale = _targetScale; + } + setScale(glm::vec3(animatedScale)); // avatar scale is uniform + rebuildCollisionShape(); + } } void Avatar::simulate(float deltaTime) { PerformanceTimer perfTimer("simulate"); - if (getAvatarScale() != _targetScale) { - setAvatarScale(_targetScale); - } + animateScaleChanges(deltaTime); // update the billboard render flag const float BILLBOARD_HYSTERESIS_PROPORTION = 0.1f; @@ -164,7 +178,7 @@ void Avatar::simulate(float deltaTime) { _shouldRenderBillboard = true; qCDebug(interfaceapp) << "Billboarding" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for LOD" << getLODDistance(); } - + const bool isControllerLogging = DependencyManager::get()->getRenderDistanceControllerIsLogging(); float renderDistance = DependencyManager::get()->getRenderDistance(); const float SKIP_HYSTERESIS_PROPORTION = isControllerLogging ? 0.0f : BILLBOARD_HYSTERESIS_PROPORTION; @@ -210,7 +224,7 @@ void Avatar::simulate(float deltaTime) { _skeletonModel.getHeadPosition(headPosition); Head* head = getHead(); head->setPosition(headPosition); - head->setScale(getAvatarScale()); + head->setScale(getUniformScale()); head->simulate(deltaTime, false, _shouldRenderBillboard); } } @@ -238,12 +252,12 @@ void Avatar::simulate(float deltaTime) { measureMotionDerivatives(deltaTime); } -bool Avatar::isLookingAtMe(AvatarSharedPointer avatar) { +bool Avatar::isLookingAtMe(AvatarSharedPointer avatar) const { const float HEAD_SPHERE_RADIUS = 0.1f; glm::vec3 theirLookAt = dynamic_pointer_cast(avatar)->getHead()->getLookAtPosition(); glm::vec3 myEyePosition = getHead()->getEyePosition(); - return glm::distance(theirLookAt, myEyePosition) <= (HEAD_SPHERE_RADIUS * getAvatarScale()); + return glm::distance(theirLookAt, myEyePosition) <= (HEAD_SPHERE_RADIUS * getUniformScale()); } void Avatar::slamPosition(const glm::vec3& newPosition) { @@ -423,7 +437,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { const float BASE_LIGHT_DISTANCE = 2.0f; const float LIGHT_EXPONENT = 1.0f; const float LIGHT_CUTOFF = glm::radians(80.0f); - float distance = BASE_LIGHT_DISTANCE * getAvatarScale(); + float distance = BASE_LIGHT_DISTANCE * getUniformScale(); glm::vec3 position = glm::mix(_skeletonModel.getTranslation(), getHead()->getFaceModel().getTranslation(), 0.9f); glm::quat orientation = getOrientation(); foreach (const AvatarManager::LocalLight& light, DependencyManager::get()->getLocalLights()) { @@ -479,7 +493,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { } DependencyManager::get()->renderSolidSphereInstance(batch, - Transform(transform).postScale(eyeDiameter * getAvatarScale() / 2.0f + RADIUS_INCREMENT), + Transform(transform).postScale(eyeDiameter * getUniformScale() / 2.0f + RADIUS_INCREMENT), glm::vec4(LOOKING_AT_ME_COLOR, alpha)); position = getHead()->getRightEyePosition(); @@ -489,7 +503,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { eyeDiameter = DEFAULT_EYE_DIAMETER; } DependencyManager::get()->renderSolidSphereInstance(batch, - Transform(transform).postScale(eyeDiameter * getAvatarScale() / 2.0f + RADIUS_INCREMENT), + Transform(transform).postScale(eyeDiameter * getUniformScale() / 2.0f + RADIUS_INCREMENT), glm::vec4(LOOKING_AT_ME_COLOR, alpha)); } @@ -590,9 +604,9 @@ void Avatar::simulateAttachments(float deltaTime) { glm::quat jointRotation; if (_skeletonModel.getJointPositionInWorldFrame(jointIndex, jointPosition) && _skeletonModel.getJointRotationInWorldFrame(jointIndex, jointRotation)) { - model->setTranslation(jointPosition + jointRotation * attachment.translation * getAvatarScale()); + model->setTranslation(jointPosition + jointRotation * attachment.translation * getUniformScale()); model->setRotation(jointRotation * attachment.rotation); - model->setScaleToFit(true, getAvatarScale() * attachment.scale, true); // hack to force rescale + model->setScaleToFit(true, getUniformScale() * attachment.scale, true); // hack to force rescale model->setSnapModelToCenter(false); // hack to force resnap model->setSnapModelToCenter(true); model->simulate(deltaTime); @@ -647,7 +661,7 @@ void Avatar::renderBillboard(RenderArgs* renderArgs) { } float Avatar::getBillboardSize() const { - return getAvatarScale() * BILLBOARD_DISTANCE * glm::tan(glm::radians(BILLBOARD_FIELD_OF_VIEW / 2.0f)); + return getUniformScale() * BILLBOARD_DISTANCE * glm::tan(glm::radians(BILLBOARD_FIELD_OF_VIEW / 2.0f)); } #ifdef DEBUG @@ -796,7 +810,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, co } void Avatar::setSkeletonOffset(const glm::vec3& offset) { - const float MAX_OFFSET_LENGTH = getAvatarScale() * 0.5f; + const float MAX_OFFSET_LENGTH = getUniformScale() * 0.5f; float offsetLength = glm::length(offset); if (offsetLength > MAX_OFFSET_LENGTH) { _skeletonOffset = (MAX_OFFSET_LENGTH / offsetLength) * offset; @@ -905,7 +919,7 @@ glm::vec3 Avatar::getJointPosition(const QString& name) const { void Avatar::scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const { //Scale a world space vector as if it was relative to the position - positionToScale = getPosition() + getAvatarScale() * (positionToScale - getPosition()); + positionToScale = getPosition() + getUniformScale() * (positionToScale - getPosition()); } void Avatar::setFaceModelURL(const QUrl& faceModelURL) { @@ -945,7 +959,7 @@ void Avatar::setAttachmentData(const QVector& attachmentData) { for (int i = 0; i < attachmentData.size(); i++) { _attachmentModels[i]->setURL(attachmentData.at(i).modelURL); _attachmentModels[i]->setSnapModelToCenter(true); - _attachmentModels[i]->setScaleToFit(true, getAvatarScale() * _attachmentData.at(i).scale); + _attachmentModels[i]->setScaleToFit(true, getUniformScale() * _attachmentData.at(i).scale); } } @@ -1033,15 +1047,6 @@ void Avatar::renderJointConnectingCone(gpu::Batch& batch, glm::vec3 position1, g } } -void Avatar::setAvatarScale(float scale) { - if (_targetScale * (1.0f - RESCALING_TOLERANCE) < scale && - scale < _targetScale * (1.0f + RESCALING_TOLERANCE)) { - setScale(glm::vec3(_targetScale)); - } else { - setScale(glm::vec3(scale)); - } -} - float Avatar::getSkeletonHeight() const { Extents extents = _skeletonModel.getBindExtents(); return extents.maximum.y - extents.minimum.y; @@ -1053,7 +1058,7 @@ float Avatar::getHeadHeight() const { // HACK: We have a really odd case when fading out for some models where this value explodes float result = extents.maximum.y - extents.minimum.y; - if (result >= 0.0f && result < 100.0f * getAvatarScale() ) { + if (result >= 0.0f && result < 100.0f * getUniformScale() ) { return result; } } @@ -1096,13 +1101,20 @@ void Avatar::setShowDisplayName(bool showDisplayName) { // virtual void Avatar::computeShapeInfo(ShapeInfo& shapeInfo) { - shapeInfo.setCapsuleY(_skeletonModel.getBoundingCapsuleRadius(), 0.5f * _skeletonModel.getBoundingCapsuleHeight()); - shapeInfo.setOffset(_skeletonModel.getBoundingCapsuleOffset()); + float uniformScale = getUniformScale(); + shapeInfo.setCapsuleY(uniformScale * _skeletonModel.getBoundingCapsuleRadius(), + 0.5f * uniformScale * _skeletonModel.getBoundingCapsuleHeight()); + shapeInfo.setOffset(uniformScale * _skeletonModel.getBoundingCapsuleOffset()); } // virtual -void Avatar::rebuildSkeletonBody() { - DependencyManager::get()->updateAvatarPhysicsShape(this); +void Avatar::rebuildCollisionShape() { + if (_motionState) { + _motionState->addDirtyFlags(Simulation::DIRTY_SHAPE); + } else { + // adebug TODO: move most of updateAvatarPhysicsShape() to here + DependencyManager::get()->updateAvatarPhysicsShape(this); + } } glm::vec3 Avatar::getLeftPalmPosition() { diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index cdb995efea..379ab8b627 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -36,7 +36,6 @@ namespace render { static const float SCALING_RATIO = .05f; static const float SMOOTHING_RATIO = .05f; // 0 < ratio < 1 -static const float RESCALING_TOLERANCE = .02f; static const float BILLBOARD_FIELD_OF_VIEW = 30.0f; // degrees static const float BILLBOARD_DISTANCE = 5.56f; // meters @@ -89,7 +88,7 @@ public: SkeletonModel& getSkeletonModel() { return _skeletonModel; } const SkeletonModel& getSkeletonModel() const { return _skeletonModel; } glm::vec3 getChestPosition() const; - float getAvatarScale() const { return getScale().y; } + float getUniformScale() const { return getScale().y; } const Head* getHead() const { return static_cast(_headData); } Head* getHead() { return static_cast(_headData); } Hand* getHand() { return static_cast(_handData); } @@ -154,7 +153,7 @@ public: // (otherwise floating point error will cause problems at large positions). void applyPositionDelta(const glm::vec3& delta); - virtual void rebuildSkeletonBody(); + virtual void rebuildCollisionShape(); virtual void computeShapeInfo(ShapeInfo& shapeInfo); @@ -199,14 +198,15 @@ protected: float _stringLength; bool _moving; ///< set when position is changing - bool isLookingAtMe(AvatarSharedPointer avatar); - // protected methods... + bool isLookingAtMe(AvatarSharedPointer avatar) const; + + virtual void animateScaleChanges(float deltaTime); + glm::vec3 getBodyRightDirection() const { return getOrientation() * IDENTITY_RIGHT; } glm::vec3 getBodyUpDirection() const { return getOrientation() * IDENTITY_UP; } glm::vec3 getBodyFrontDirection() const { return getOrientation() * IDENTITY_FRONT; } glm::quat computeRotationFromBodyToWorldUp(float proportion = 1.0f) const; - void setAvatarScale(float scale); void measureMotionDerivatives(float deltaTime); float getSkeletonHeight() const; diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 7c1a52f1b3..562bea3542 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -203,7 +203,7 @@ void AvatarManager::simulateAvatarFades(float deltaTime) { while (fadingIterator != _avatarFades.end()) { auto avatar = std::static_pointer_cast(*fadingIterator); avatar->startUpdate(); - avatar->setTargetScale(avatar->getAvatarScale() * SHRINK_RATE); + avatar->setTargetScale(avatar->getUniformScale() * SHRINK_RATE); if (avatar->getTargetScale() <= MIN_FADE_SCALE) { avatar->removeFromScene(*fadingIterator, scene, pendingChanges); fadingIterator = _avatarFades.erase(fadingIterator); @@ -375,19 +375,17 @@ void AvatarManager::handleCollisionEvents(const CollisionEvents& collisionEvents } void AvatarManager::updateAvatarPhysicsShape(Avatar* avatar) { - AvatarMotionState* motionState = avatar->getMotionState(); - if (motionState) { - motionState->addDirtyFlags(Simulation::DIRTY_SHAPE); - } else { - ShapeInfo shapeInfo; - avatar->computeShapeInfo(shapeInfo); - btCollisionShape* shape = ObjectMotionState::getShapeManager()->getShape(shapeInfo); - if (shape) { - AvatarMotionState* motionState = new AvatarMotionState(avatar, shape); - avatar->setMotionState(motionState); - _motionStatesToAdd.insert(motionState); - _avatarMotionStates.insert(motionState); - } + // adebug TODO: move most of this logic to MyAvatar class + assert(!avatar->getMotionState()); + + ShapeInfo shapeInfo; + avatar->computeShapeInfo(shapeInfo); + btCollisionShape* shape = ObjectMotionState::getShapeManager()->getShape(shapeInfo); + if (shape) { + AvatarMotionState* motionState = new AvatarMotionState(avatar, shape); + avatar->setMotionState(motionState); + _motionStatesToAdd.insert(motionState); + _avatarMotionStates.insert(motionState); } } diff --git a/interface/src/avatar/AvatarMotionState.h b/interface/src/avatar/AvatarMotionState.h index 1c49705f23..b5101d2c70 100644 --- a/interface/src/avatar/AvatarMotionState.h +++ b/interface/src/avatar/AvatarMotionState.h @@ -46,7 +46,7 @@ public: virtual float getObjectFriction() const; virtual float getObjectLinearDamping() const; virtual float getObjectAngularDamping() const; - + virtual glm::vec3 getObjectPosition() const; virtual glm::quat getObjectRotation() const; virtual glm::vec3 getObjectLinearVelocity() const; diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 4f16449aa2..fe03d22f0b 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -37,7 +37,7 @@ void Hand::simulate(float deltaTime, bool isMine) { void Hand::renderHandTargets(RenderArgs* renderArgs, bool isMine) { float avatarScale = 1.0f; if (_owningAvatar) { - avatarScale = _owningAvatar->getAvatarScale(); + avatarScale = _owningAvatar->getUniformScale(); } const float alpha = 1.0f; @@ -62,7 +62,7 @@ void Hand::renderHandTargets(RenderArgs* renderArgs, bool isMine) { transform.setRotation(palm.getRotation()); transform.postScale(SPHERE_RADIUS); DependencyManager::get()->renderSolidSphereInstance(batch, transform, grayColor); - + // draw a green sphere at the old "finger tip" transform = Transform(); position = palm.getTipPosition(); @@ -72,7 +72,7 @@ void Hand::renderHandTargets(RenderArgs* renderArgs, bool isMine) { DependencyManager::get()->renderSolidSphereInstance(batch, transform, greenColor); } } - + const float AXIS_RADIUS = 0.1f * SPHERE_RADIUS; const float AXIS_LENGTH = 10.0f * SPHERE_RADIUS; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 9331682714..926d41f1ca 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -284,13 +284,26 @@ void MyAvatar::update(float deltaTime) { extern QByteArray avatarStateToFrame(const AvatarData* _avatar); extern void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avatar); +void MyAvatar::animateScaleChanges(float deltaTime) { + // HACK: override Avatar::animateScaleChanges() until MyAvatar has a MotionState + float currentScale = getUniformScale(); + if (currentScale != _targetScale) { + const float SCALE_ANIMATION_TIMESCALE = 1.0f; + float blendFactor = deltaTime / SCALE_ANIMATION_TIMESCALE; + float animatedScale = (1.0f - blendFactor) * currentScale + blendFactor * _targetScale; + const float CLOSE_ENOUGH = 0.05f; + if (fabsf(animatedScale - _targetScale) / _targetScale < CLOSE_ENOUGH) { + animatedScale = _targetScale; + } + setScale(glm::vec3(animatedScale)); + rebuildCollisionShape(); + } +} + void MyAvatar::simulate(float deltaTime) { PerformanceTimer perfTimer("simulate"); - if (getAvatarScale() != _targetScale) { - float scale = (1.0f - SMOOTHING_RATIO) * getAvatarScale() + SMOOTHING_RATIO * _targetScale; - setAvatarScale(scale); - } + animateScaleChanges(deltaTime); { PerformanceTimer perfTimer("transform"); @@ -337,7 +350,7 @@ void MyAvatar::simulate(float deltaTime) { headPosition = getPosition(); } head->setPosition(headPosition); - head->setScale(getAvatarScale()); + head->setScale(getUniformScale()); head->simulate(deltaTime, true); } @@ -681,7 +694,7 @@ void MyAvatar::loadData() { _leanScale = loadSetting(settings, "leanScale", 0.05f); _targetScale = loadSetting(settings, "scale", 1.0f); - setAvatarScale(getAvatarScale()); + setScale(glm::vec3(getUniformScale())); _animGraphUrl = settings.value("animGraphURL", "").toString(); _fullAvatarURLFromPreferences = settings.value("fullAvatarURL", AvatarData::defaultFullAvatarModelUrl()).toUrl(); @@ -809,7 +822,7 @@ void MyAvatar::updateLookAtTargetAvatar() { float distanceTo = glm::length(avatar->getHead()->getEyePosition() - cameraPosition); avatar->setIsLookAtTarget(false); if (!avatar->isMyAvatar() && avatar->isInitialized() && - (distanceTo < GREATEST_LOOKING_AT_DISTANCE * getAvatarScale())) { + (distanceTo < GREATEST_LOOKING_AT_DISTANCE * getUniformScale())) { float angleTo = glm::angle(lookForward, glm::normalize(avatar->getHead()->getEyePosition() - cameraPosition)); if (angleTo < (smallestAngleTo * (isCurrentTarget ? KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR : 1.0f))) { _lookAtTargetAvatar = avatarPointer; @@ -1036,14 +1049,15 @@ glm::vec3 MyAvatar::getSkeletonPosition() const { return Avatar::getPosition(); } -void MyAvatar::rebuildSkeletonBody() { +void MyAvatar::rebuildCollisionShape() { // compute localAABox - float radius = _skeletonModel.getBoundingCapsuleRadius(); - float height = _skeletonModel.getBoundingCapsuleHeight() + 2.0f * radius; + float scale = getUniformScale(); + float radius = scale * _skeletonModel.getBoundingCapsuleRadius(); + float height = scale * _skeletonModel.getBoundingCapsuleHeight() + 2.0f * radius; glm::vec3 corner(-radius, -0.5f * height, -radius); - corner += _skeletonModel.getBoundingCapsuleOffset(); - glm::vec3 scale(2.0f * radius, height, 2.0f * radius); - _characterController.setLocalBoundingBox(corner, scale); + corner += scale * _skeletonModel.getBoundingCapsuleOffset(); + glm::vec3 diagonal(2.0f * radius, height, 2.0f * radius); + _characterController.setLocalBoundingBox(corner, diagonal); } void MyAvatar::prepareForPhysicsSimulation() { @@ -1331,7 +1345,7 @@ const float RENDER_HEAD_CUTOFF_DISTANCE = 0.50f; bool MyAvatar::cameraInsideHead() const { const Head* head = getHead(); const glm::vec3 cameraPosition = qApp->getCamera()->getPosition(); - return glm::length(cameraPosition - head->getEyePosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * getAvatarScale()); + return glm::length(cameraPosition - head->getEyePosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * getUniformScale()); } bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const { @@ -1455,11 +1469,11 @@ glm::vec3 MyAvatar::applyKeyboardMotor(float deltaTime, const glm::vec3& localVe if (isHovering) { // we're flying --> complex acceleration curve with high max speed float motorSpeed = glm::length(_keyboardMotorVelocity); - float finalMaxMotorSpeed = getAvatarScale() * MAX_KEYBOARD_MOTOR_SPEED; + float finalMaxMotorSpeed = getUniformScale() * MAX_KEYBOARD_MOTOR_SPEED; float speedGrowthTimescale = 2.0f; float speedIncreaseFactor = 1.8f; motorSpeed *= 1.0f + glm::clamp(deltaTime / speedGrowthTimescale , 0.0f, 1.0f) * speedIncreaseFactor; - const float maxBoostSpeed = getAvatarScale() * MAX_BOOST_SPEED; + const float maxBoostSpeed = getUniformScale() * MAX_BOOST_SPEED; if (motorSpeed < maxBoostSpeed) { // an active keyboard motor should never be slower than this float boostCoefficient = (maxBoostSpeed - motorSpeed) / maxBoostSpeed; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 514261bf16..bce6521c07 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -249,7 +249,7 @@ public slots: Q_INVOKABLE void updateMotionBehaviorFromMenu(); - virtual void rebuildSkeletonBody() override; + virtual void rebuildCollisionShape() override; Q_INVOKABLE QUrl getAnimGraphUrl() const { return _animGraphUrl; } @@ -263,6 +263,9 @@ public slots: glm::vec3 getPositionForAudio(); glm::quat getOrientationForAudio(); +protected: + void animateScaleChanges(float deltaTime); + signals: void audioListenerModeChanged(); void transformChanged(); diff --git a/interface/src/avatar/MyCharacterController.cpp b/interface/src/avatar/MyCharacterController.cpp index 23d601e58e..c7f2945757 100644 --- a/interface/src/avatar/MyCharacterController.cpp +++ b/interface/src/avatar/MyCharacterController.cpp @@ -32,7 +32,7 @@ MyCharacterController::~MyCharacterController() { void MyCharacterController::updateShapeIfNecessary() { if (_pendingFlags & PENDING_FLAG_UPDATE_SHAPE) { - _pendingFlags &= ~ PENDING_FLAG_UPDATE_SHAPE; + _pendingFlags &= ~PENDING_FLAG_UPDATE_SHAPE; // compute new dimensions from avatar's bounding box float x = _boxScale.x; diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 342f8315e1..47c22e9f08 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -69,7 +69,7 @@ void SkeletonModel::initJointStates() { _headClipDistance = -(meshExtents.minimum.z / _scale.z - _defaultEyeModelPosition.z); _headClipDistance = std::max(_headClipDistance, DEFAULT_NEAR_CLIP); - _owningAvatar->rebuildSkeletonBody(); + _owningAvatar->rebuildCollisionShape(); emit skeletonLoaded(); } diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 99285c6558..e5ecdfe217 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -386,7 +386,7 @@ bool ApplicationCompositor::calculateRayUICollisionPoint(const glm::vec3& positi glm::vec3 relativeDirection = glm::normalize(inverseOrientation * direction); float t; - if (raySphereIntersect(relativeDirection, relativePosition, _oculusUIRadius * myAvatar->getAvatarScale(), &t)){ + if (raySphereIntersect(relativeDirection, relativePosition, _oculusUIRadius * myAvatar->getUniformScale(), &t)){ result = position + direction * t; return true; } diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 9a995263cd..f7ef0c9d56 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -199,7 +199,7 @@ void PreferencesDialog::loadPreferences() { ui.leanScaleSpin->setValue(myAvatar->getLeanScale()); - ui.avatarScaleSpin->setValue(myAvatar->getAvatarScale()); + ui.avatarScaleSpin->setValue(myAvatar->getUniformScale()); ui.avatarAnimationEdit->setText(myAvatar->getAnimGraphUrl().toString()); ui.maxOctreePPSSpin->setValue(qApp->getMaxOctreePacketsPerSecond()); diff --git a/interface/src/ui/overlays/OverlaysPayload.cpp b/interface/src/ui/overlays/OverlaysPayload.cpp index 1b1c48c3ca..753106fa0a 100644 --- a/interface/src/ui/overlays/OverlaysPayload.cpp +++ b/interface/src/ui/overlays/OverlaysPayload.cpp @@ -68,7 +68,7 @@ namespace render { glm::vec3 myAvatarPosition = avatar->getPosition(); float angle = glm::degrees(glm::angle(myAvatarRotation)); glm::vec3 axis = glm::axis(myAvatarRotation); - float myAvatarScale = avatar->getAvatarScale(); + float myAvatarScale = avatar->getUniformScale(); Transform transform = Transform(); transform.setTranslation(myAvatarPosition); transform.setRotation(glm::angleAxis(angle, axis)); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index d241df7e0e..dce973fb33 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -90,7 +90,7 @@ const QUrl& AvatarData::defaultFullAvatarModelUrl() { // There are a number of possible strategies for this set of tools through endRender, below. void AvatarData::nextAttitude(glm::vec3 position, glm::quat orientation) { avatarLock.lock(); - Transform trans; + Transform trans = getTransform(); trans.setTranslation(position); trans.setRotation(orientation); SpatiallyNestable::setTransform(trans); From 33634cdaa16e8faec4fb375f5efcb6ae9e0d27ef Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 10 Dec 2015 18:09:58 -0800 Subject: [PATCH 03/15] properly delete departing avatars --- interface/src/avatar/Avatar.cpp | 21 +++++++++++++-------- interface/src/avatar/Avatar.h | 5 ++++- interface/src/avatar/AvatarManager.cpp | 16 ++++++++-------- interface/src/avatar/AvatarManager.h | 14 +++++++------- libraries/avatars/src/AvatarData.h | 5 +++++ 5 files changed, 37 insertions(+), 24 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 8231d1ebdd..a0fa822512 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -150,11 +150,12 @@ float Avatar::getLODDistance() const { void Avatar::animateScaleChanges(float deltaTime) { float currentScale = getUniformScale(); if (currentScale != _targetScale) { - const float SCALE_ANIMATION_TIMESCALE = 1.0f; - float blendFactor = deltaTime / SCALE_ANIMATION_TIMESCALE; - float animatedScale = (1.0f - blendFactor) * currentScale + blendFactor * _targetScale; - const float CLOSE_ENOUGH = 0.05f; - if (fabsf(animatedScale - _targetScale) / _targetScale < CLOSE_ENOUGH) { + const float SCALE_ANIMATION_TIMESCALE = 0.5f; + float scaleVelocity = (_targetScale - currentScale) / SCALE_ANIMATION_TIMESCALE; + float animatedScale = currentScale + deltaTime * scaleVelocity; + const float MIN_SCALE_SPEED = 0.3f; + if (fabsf(scaleVelocity) < MIN_SCALE_SPEED) { + // close enough animatedScale = _targetScale; } setScale(glm::vec3(animatedScale)); // avatar scale is uniform @@ -165,6 +166,9 @@ void Avatar::animateScaleChanges(float deltaTime) { void Avatar::simulate(float deltaTime) { PerformanceTimer perfTimer("simulate"); + if (!isDead() && !_motionState) { + DependencyManager::get()->updateAvatarPhysicsShape(this); + } animateScaleChanges(deltaTime); // update the billboard render flag @@ -1107,13 +1111,14 @@ void Avatar::computeShapeInfo(ShapeInfo& shapeInfo) { shapeInfo.setOffset(uniformScale * _skeletonModel.getBoundingCapsuleOffset()); } +void Avatar::setMotionState(AvatarMotionState* motionState) { + _motionState = motionState; +} + // virtual void Avatar::rebuildCollisionShape() { if (_motionState) { _motionState->addDirtyFlags(Simulation::DIRTY_SHAPE); - } else { - // adebug TODO: move most of updateAvatarPhysicsShape() to here - DependencyManager::get()->updateAvatarPhysicsShape(this); } } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 379ab8b627..4926212b4d 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -157,7 +157,6 @@ public: virtual void computeShapeInfo(ShapeInfo& shapeInfo); - void setMotionState(AvatarMotionState* motionState) { _motionState = motionState; } AvatarMotionState* getMotionState() { return _motionState; } virtual void setPosition(const glm::vec3& position) override; @@ -172,6 +171,10 @@ public slots: glm::quat getRightPalmRotation(); protected: + friend class AvatarManager; + + void setMotionState(AvatarMotionState* motionState); + SkeletonModel _skeletonModel; glm::vec3 _skeletonOffset; QVector _attachmentModels; diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 562bea3542..38f191872e 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -223,14 +223,14 @@ AvatarSharedPointer AvatarManager::newSharedAvatar() { AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWeakPointer& mixerWeakPointer) { auto newAvatar = AvatarHashMap::addAvatar(sessionUUID, mixerWeakPointer); auto rawRenderableAvatar = std::static_pointer_cast(newAvatar); - + render::ScenePointer scene = qApp->getMain3DScene(); render::PendingChanges pendingChanges; if (DependencyManager::get()->shouldRenderAvatars()) { rawRenderableAvatar->addToScene(rawRenderableAvatar, scene, pendingChanges); } scene->enqueuePendingChanges(pendingChanges); - + return newAvatar; } @@ -251,7 +251,7 @@ void AvatarManager::removeAvatarMotionState(AvatarSharedPointer avatar) { // virtual void AvatarManager::removeAvatar(const QUuid& sessionUUID) { QWriteLocker locker(&_hashLock); - + auto removedAvatar = _avatarHash.take(sessionUUID); if (removedAvatar) { handleRemovedAvatar(removedAvatar); @@ -260,7 +260,8 @@ void AvatarManager::removeAvatar(const QUuid& sessionUUID) { void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar) { AvatarHashMap::handleRemovedAvatar(removedAvatar); - + + removedAvatar->die(); removeAvatarMotionState(removedAvatar); _avatarFades.push_back(removedAvatar); } @@ -268,7 +269,7 @@ void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar void AvatarManager::clearOtherAvatars() { // clear any avatars that came from an avatar-mixer QWriteLocker locker(&_hashLock); - + AvatarHash::iterator avatarIterator = _avatarHash.begin(); while (avatarIterator != _avatarHash.end()) { auto avatar = std::static_pointer_cast(avatarIterator.value()); @@ -278,7 +279,7 @@ void AvatarManager::clearOtherAvatars() { } else { auto removedAvatar = avatarIterator.value(); avatarIterator = _avatarHash.erase(avatarIterator); - + handleRemovedAvatar(removedAvatar); } } @@ -375,7 +376,6 @@ void AvatarManager::handleCollisionEvents(const CollisionEvents& collisionEvents } void AvatarManager::updateAvatarPhysicsShape(Avatar* avatar) { - // adebug TODO: move most of this logic to MyAvatar class assert(!avatar->getMotionState()); ShapeInfo shapeInfo; @@ -414,6 +414,6 @@ AvatarSharedPointer AvatarManager::getAvatarBySessionID(const QUuid& sessionID) if (sessionID == _myAvatar->getSessionUUID()) { return _myAvatar; } - + return findAvatar(sessionID); } diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 84a4bc44b8..d63df9fb76 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -52,7 +52,7 @@ public: glm::vec3 color; glm::vec3 direction; }; - + Q_INVOKABLE void setLocalLights(const QVector& localLights); Q_INVOKABLE QVector getLocalLights() const; // Currently, your own avatar will be included as the null avatar id. @@ -67,7 +67,7 @@ public: void handleCollisionEvents(const CollisionEvents& collisionEvents); void updateAvatarPhysicsShape(Avatar* avatar); - + // Expose results and parameter-tuning operations to other systems, such as stats and javascript. Q_INVOKABLE float getRenderDistance() { return _renderDistance; } Q_INVOKABLE float getRenderDistanceInverseLowLimit() { return _renderDistanceController.getControlledValueLowLimit(); } @@ -80,7 +80,7 @@ public: Q_INVOKABLE void setRenderDistanceKD(float newValue) { _renderDistanceController.setKD(newValue); } Q_INVOKABLE void setRenderDistanceInverseLowLimit(float newValue) { _renderDistanceController.setControlledValueLowLimit(newValue); } Q_INVOKABLE void setRenderDistanceInverseHighLimit(float newValue); - + public slots: void setShouldShowReceiveStats(bool shouldShowReceiveStats) { _shouldShowReceiveStats = shouldShowReceiveStats; } void updateAvatarRenderStatus(bool shouldRenderAvatars); @@ -90,19 +90,19 @@ private: AvatarManager(const AvatarManager& other); void simulateAvatarFades(float deltaTime); - + // virtual overrides virtual AvatarSharedPointer newSharedAvatar(); virtual AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer& mixerWeakPointer); void removeAvatarMotionState(AvatarSharedPointer avatar); - + virtual void removeAvatar(const QUuid& sessionUUID); virtual void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar); - + QVector _avatarFades; std::shared_ptr _myAvatar; quint64 _lastSendAvatarDataTime = 0; // Controls MyAvatar send data rate. - + QVector _localLights; bool _shouldShowReceiveStats = false; diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 1fa33ff606..cbd15f2ce1 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -342,6 +342,9 @@ public: glm::vec3 getClientGlobalPosition() { return _globalPosition; } + void die() { _isDead = true; } + bool isDead() const { return _isDead; } + public slots: void sendAvatarDataPacket(); void sendIdentityPacket(); @@ -413,6 +416,8 @@ protected: // updates about one avatar to another. glm::vec3 _globalPosition; + bool _isDead { false }; + private: friend void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avatar); static QUrl _defaultFullAvatarModelUrl; From bab07516f032db80e2475b42d90cc94283276a7f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 14 Dec 2015 12:06:11 -0800 Subject: [PATCH 04/15] fix size of rendered bounding capsule --- interface/src/avatar/Avatar.cpp | 3 ++- interface/src/avatar/SkeletonModel.cpp | 23 +++++++++++++---------- interface/src/avatar/SkeletonModel.h | 2 +- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index a0fa822512..9e881f49ea 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -454,7 +454,8 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { bool renderBounding = Menu::getInstance()->isOptionChecked(MenuOption::RenderBoundingCollisionShapes); if (renderBounding && shouldRenderHead(renderArgs) && _skeletonModel.isRenderable()) { PROFILE_RANGE_BATCH(batch, __FUNCTION__":skeletonBoundingCollisionShapes"); - _skeletonModel.renderBoundingCollisionShapes(*renderArgs->_batch, 0.7f); + const float BOUNDING_SHAPE_ALPHA = 0.7f; + _skeletonModel.renderBoundingCollisionShapes(*renderArgs->_batch, getUniformScale(), BOUNDING_SHAPE_ALPHA); } // If this is the avatar being looked at, render a little ball above their head diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 47c22e9f08..e8d952973b 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -338,35 +338,38 @@ void SkeletonModel::computeBoundingShape() { return; } - _rig->computeAvatarBoundingCapsule(geometry, - _boundingCapsuleRadius, - _boundingCapsuleHeight, - _boundingCapsuleLocalOffset); + float radius, height; + glm::vec3 offset; + _rig->computeAvatarBoundingCapsule(geometry, radius, height, offset); + float invScale = 1.0f / _owningAvatar->getUniformScale(); + _boundingCapsuleRadius = invScale * radius; + _boundingCapsuleHeight = invScale * height; + _boundingCapsuleLocalOffset = invScale * offset; } -void SkeletonModel::renderBoundingCollisionShapes(gpu::Batch& batch, float alpha) { +void SkeletonModel::renderBoundingCollisionShapes(gpu::Batch& batch, float scale, float alpha) { auto geometryCache = DependencyManager::get(); auto deferredLighting = DependencyManager::get(); // draw a blue sphere at the capsule top point - glm::vec3 topPoint = _translation + getRotation() * (_boundingCapsuleLocalOffset + (0.5f * _boundingCapsuleHeight) * glm::vec3(0.0f, 1.0f, 0.0f)); + glm::vec3 topPoint = _translation + getRotation() * (scale * (_boundingCapsuleLocalOffset + (0.5f * _boundingCapsuleHeight) * Vectors::UNIT_Y)); deferredLighting->renderSolidSphereInstance(batch, - Transform().setTranslation(topPoint).postScale(_boundingCapsuleRadius), + Transform().setTranslation(topPoint).postScale(scale * _boundingCapsuleRadius), glm::vec4(0.6f, 0.6f, 0.8f, alpha)); // draw a yellow sphere at the capsule bottom point - glm::vec3 bottomPoint = topPoint - glm::vec3(0.0f, _boundingCapsuleHeight, 0.0f); + glm::vec3 bottomPoint = topPoint - glm::vec3(0.0f, scale * _boundingCapsuleHeight, 0.0f); glm::vec3 axis = topPoint - bottomPoint; deferredLighting->renderSolidSphereInstance(batch, - Transform().setTranslation(bottomPoint).postScale(_boundingCapsuleRadius), + Transform().setTranslation(bottomPoint).postScale(scale * _boundingCapsuleRadius), glm::vec4(0.8f, 0.8f, 0.6f, alpha)); // draw a green cylinder between the two points glm::vec3 origin(0.0f); batch.setModelTransform(Transform().setTranslation(bottomPoint)); deferredLighting->bindSimpleProgram(batch); - Avatar::renderJointConnectingCone(batch, origin, axis, _boundingCapsuleRadius, _boundingCapsuleRadius, + Avatar::renderJointConnectingCone(batch, origin, axis, scale * _boundingCapsuleRadius, scale * _boundingCapsuleRadius, glm::vec4(0.6f, 0.8f, 0.6f, alpha)); } diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index 9b73119238..7541a002dc 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -89,7 +89,7 @@ public: /// \return whether or not the head was found. glm::vec3 getDefaultEyeModelPosition() const; - void renderBoundingCollisionShapes(gpu::Batch& batch, float alpha); + void renderBoundingCollisionShapes(gpu::Batch& batch, float scale, float alpha); float getBoundingCapsuleRadius() const { return _boundingCapsuleRadius; } float getBoundingCapsuleHeight() const { return _boundingCapsuleHeight; } const glm::vec3 getBoundingCapsuleOffset() const { return _boundingCapsuleLocalOffset; } From cd1e3810ca43c7d3822c7581096f79dd2bd5ac18 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 14 Dec 2015 12:06:31 -0800 Subject: [PATCH 05/15] set the scale of avatar on login, don't animate --- interface/src/avatar/MyAvatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 926d41f1ca..73ff332a37 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -694,7 +694,7 @@ void MyAvatar::loadData() { _leanScale = loadSetting(settings, "leanScale", 0.05f); _targetScale = loadSetting(settings, "scale", 1.0f); - setScale(glm::vec3(getUniformScale())); + setScale(glm::vec3(_targetScale)); _animGraphUrl = settings.value("animGraphURL", "").toString(); _fullAvatarURLFromPreferences = settings.value("fullAvatarURL", AvatarData::defaultFullAvatarModelUrl()).toUrl(); From c3823de353ea40d96501fce20b84c778759991d3 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 14 Dec 2015 12:07:03 -0800 Subject: [PATCH 06/15] setClampedTargetScale()-->setTargetScaleVerbose() --- interface/src/ui/PreferencesDialog.cpp | 2 +- libraries/avatars/src/AvatarData.cpp | 5 +---- libraries/avatars/src/AvatarData.h | 6 +++--- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index f7ef0c9d56..a38cc13100 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -256,7 +256,7 @@ void PreferencesDialog::savePreferences() { myAvatar->getHead()->setPupilDilation(ui.pupilDilationSlider->value() / (float)ui.pupilDilationSlider->maximum()); myAvatar->setLeanScale(ui.leanScaleSpin->value()); - myAvatar->setClampedTargetScale(ui.avatarScaleSpin->value()); + myAvatar->setTargetScaleVerbose(ui.avatarScaleSpin->value()); if (myAvatar->getAnimGraphUrl() != ui.avatarAnimationEdit->text()) { // If changed, destroy the old and start with the new myAvatar->setAnimGraphUrl(ui.avatarAnimationEdit->text()); } diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index dce973fb33..645e0ad7fc 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -132,10 +132,7 @@ void AvatarData::setTargetScale(float targetScale) { _targetScale = std::max(MIN_AVATAR_SCALE, std::min(MAX_AVATAR_SCALE, targetScale)); } -void AvatarData::setClampedTargetScale(float targetScale) { - - targetScale = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); - +void AvatarData::setTargetScaleVerbose(float targetScale) { setTargetScale(targetScale); qCDebug(avatars) << "Changed scale to " << _targetScale; } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index cbd15f2ce1..64c215cee7 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -172,7 +172,7 @@ public: AvatarData(); virtual ~AvatarData(); - + static const QUrl& defaultFullAvatarModelUrl(); virtual bool isMyAvatar() const { return false; } @@ -237,7 +237,7 @@ public: // Scale float getTargetScale() const; void setTargetScale(float targetScale); - void setClampedTargetScale(float targetScale); + void setTargetScaleVerbose(float targetScale); // Hand State Q_INVOKABLE void setHandState(char s) { _handState = s; } @@ -261,7 +261,7 @@ public: Q_INVOKABLE bool isJointDataValid(const QString& name) const; Q_INVOKABLE glm::quat getJointRotation(const QString& name) const; Q_INVOKABLE glm::vec3 getJointTranslation(const QString& name) const; - + Q_INVOKABLE virtual QVector getJointRotations() const; Q_INVOKABLE virtual void setJointRotations(QVector jointRotations); Q_INVOKABLE virtual void setJointTranslations(QVector jointTranslations); From 9b0c199ed75752d71556adcc27244aacee49aa72 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 15 Dec 2015 15:30:56 -0800 Subject: [PATCH 07/15] updateAvatarPhysicsShape-->addAvatarToSimulation --- interface/src/avatar/Avatar.cpp | 2 +- interface/src/avatar/AvatarManager.cpp | 3 ++- interface/src/avatar/AvatarManager.h | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 9e881f49ea..504124c4a7 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -167,7 +167,7 @@ void Avatar::simulate(float deltaTime) { PerformanceTimer perfTimer("simulate"); if (!isDead() && !_motionState) { - DependencyManager::get()->updateAvatarPhysicsShape(this); + DependencyManager::get()->addAvatarToSimulation(this); } animateScaleChanges(deltaTime); diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 38f191872e..312742e778 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -375,13 +375,14 @@ void AvatarManager::handleCollisionEvents(const CollisionEvents& collisionEvents } } -void AvatarManager::updateAvatarPhysicsShape(Avatar* avatar) { +void AvatarManager::addAvatarToSimulation(Avatar* avatar) { assert(!avatar->getMotionState()); ShapeInfo shapeInfo; avatar->computeShapeInfo(shapeInfo); btCollisionShape* shape = ObjectMotionState::getShapeManager()->getShape(shapeInfo); if (shape) { + // we don't add to the simulation now, we put it on a list to be added later AvatarMotionState* motionState = new AvatarMotionState(avatar, shape); avatar->setMotionState(motionState); _motionStatesToAdd.insert(motionState); diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index d63df9fb76..1b165495c3 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -66,7 +66,7 @@ public: void handleOutgoingChanges(const VectorOfMotionStates& motionStates); void handleCollisionEvents(const CollisionEvents& collisionEvents); - void updateAvatarPhysicsShape(Avatar* avatar); + void addAvatarToSimulation(Avatar* avatar); // Expose results and parameter-tuning operations to other systems, such as stats and javascript. Q_INVOKABLE float getRenderDistance() { return _renderDistance; } From 7baee8c39138e80c05238dd0e93f2671a7cb90dc Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 15 Dec 2015 15:34:16 -0800 Subject: [PATCH 08/15] use glm::clamp() instead of std::min() and max() --- libraries/avatars/src/AvatarData.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 645e0ad7fc..2ed9a47e02 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -129,7 +129,7 @@ float AvatarData::getTargetScale() const { } void AvatarData::setTargetScale(float targetScale) { - _targetScale = std::max(MIN_AVATAR_SCALE, std::min(MAX_AVATAR_SCALE, targetScale)); + _targetScale = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); } void AvatarData::setTargetScaleVerbose(float targetScale) { From 0e1e5db7eb808a71f209e7c219e74a87b29ddf58 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 15 Dec 2015 16:29:39 -0800 Subject: [PATCH 09/15] only need one animateScaleChanges() implementation --- interface/src/avatar/Avatar.cpp | 13 ++++++++----- interface/src/avatar/MyAvatar.cpp | 16 ---------------- interface/src/avatar/MyAvatar.h | 3 --- 3 files changed, 8 insertions(+), 24 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 504124c4a7..f8040754d7 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -150,14 +150,17 @@ float Avatar::getLODDistance() const { void Avatar::animateScaleChanges(float deltaTime) { float currentScale = getUniformScale(); if (currentScale != _targetScale) { + // use exponential decay toward _targetScale const float SCALE_ANIMATION_TIMESCALE = 0.5f; - float scaleVelocity = (_targetScale - currentScale) / SCALE_ANIMATION_TIMESCALE; - float animatedScale = currentScale + deltaTime * scaleVelocity; - const float MIN_SCALE_SPEED = 0.3f; - if (fabsf(scaleVelocity) < MIN_SCALE_SPEED) { - // close enough + float blendFactor = glm::clamp(deltaTime / SCALE_ANIMATION_TIMESCALE, 0.0f, 1.0f); + float animatedScale = (1.0f - blendFactor) * currentScale + blendFactor * _targetScale; + + // snap to the end when we get close enough + const float MIN_RELATIVE_SCALE_ERROR = 0.03f; + if (fabsf(_targetScale - currentScale) / _targetScale < 0.03f) { animatedScale = _targetScale; } + setScale(glm::vec3(animatedScale)); // avatar scale is uniform rebuildCollisionShape(); } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 73ff332a37..5c8230bd88 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -284,22 +284,6 @@ void MyAvatar::update(float deltaTime) { extern QByteArray avatarStateToFrame(const AvatarData* _avatar); extern void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avatar); -void MyAvatar::animateScaleChanges(float deltaTime) { - // HACK: override Avatar::animateScaleChanges() until MyAvatar has a MotionState - float currentScale = getUniformScale(); - if (currentScale != _targetScale) { - const float SCALE_ANIMATION_TIMESCALE = 1.0f; - float blendFactor = deltaTime / SCALE_ANIMATION_TIMESCALE; - float animatedScale = (1.0f - blendFactor) * currentScale + blendFactor * _targetScale; - const float CLOSE_ENOUGH = 0.05f; - if (fabsf(animatedScale - _targetScale) / _targetScale < CLOSE_ENOUGH) { - animatedScale = _targetScale; - } - setScale(glm::vec3(animatedScale)); - rebuildCollisionShape(); - } -} - void MyAvatar::simulate(float deltaTime) { PerformanceTimer perfTimer("simulate"); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index bce6521c07..019ba0f992 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -263,9 +263,6 @@ public slots: glm::vec3 getPositionForAudio(); glm::quat getOrientationForAudio(); -protected: - void animateScaleChanges(float deltaTime); - signals: void audioListenerModeChanged(); void transformChanged(); From 08f75917876e1e50f7a7c1a4c9f051a12355b117 Mon Sep 17 00:00:00 2001 From: AlessandroSigna Date: Wed, 16 Dec 2015 10:02:47 -0800 Subject: [PATCH 10/15] Fix misspelling --- interface/src/ui/overlays/Image3DOverlay.cpp | 16 ++++++++-------- interface/src/ui/overlays/Image3DOverlay.h | 2 +- .../render-utils/src/DeferredLightingEffect.cpp | 4 ++-- .../render-utils/src/DeferredLightingEffect.h | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/interface/src/ui/overlays/Image3DOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp index 6e4c274943..7d105a6ccf 100644 --- a/interface/src/ui/overlays/Image3DOverlay.cpp +++ b/interface/src/ui/overlays/Image3DOverlay.cpp @@ -27,7 +27,7 @@ QString const Image3DOverlay::TYPE = "image3d"; Image3DOverlay::Image3DOverlay() { _isLoaded = false; - _emmisive = false; + _emissive = false; } Image3DOverlay::Image3DOverlay(const Image3DOverlay* image3DOverlay) : @@ -35,7 +35,7 @@ Image3DOverlay::Image3DOverlay(const Image3DOverlay* image3DOverlay) : _url(image3DOverlay->_url), _texture(image3DOverlay->_texture), _fromImage(image3DOverlay->_fromImage), - _emmisive(image3DOverlay->_emmisive) + _emissive(image3DOverlay->_emissive) { } @@ -96,7 +96,7 @@ void Image3DOverlay::render(RenderArgs* args) { batch->setModelTransform(transform); batch->setResourceTexture(0, _texture->getGPUTexture()); - DependencyManager::get()->bindSimpleProgram(*batch, true, false, _emmisive, true); + DependencyManager::get()->bindSimpleProgram(*batch, true, false, _emissive, true); DependencyManager::get()->renderQuad( *batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha) @@ -147,9 +147,9 @@ void Image3DOverlay::setProperties(const QScriptValue &properties) { } } - QScriptValue emmisiveValue = properties.property("emmisive"); - if (emmisiveValue.isValid()) { - _emmisive = emmisiveValue.toBool(); + QScriptValue emissiveValue = properties.property("emissive"); + if (emissiveValue.isValid()) { + _emissive = emissiveValue.toBool(); } } @@ -163,8 +163,8 @@ QScriptValue Image3DOverlay::getProperty(const QString& property) { if (property == "offsetPosition") { return vec3toScriptValue(_scriptEngine, getOffsetPosition()); } - if (property == "emmisive") { - return _emmisive; + if (property == "emissive") { + return _emissive; } return Billboard3DOverlay::getProperty(property); diff --git a/interface/src/ui/overlays/Image3DOverlay.h b/interface/src/ui/overlays/Image3DOverlay.h index 0e40c73619..f2cc3789ee 100644 --- a/interface/src/ui/overlays/Image3DOverlay.h +++ b/interface/src/ui/overlays/Image3DOverlay.h @@ -46,7 +46,7 @@ public: private: QString _url; NetworkTexturePointer _texture; - bool _emmisive; + bool _emissive; QRect _fromImage; // where from in the image to sample }; diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 10b58b156b..dcadaa5177 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -169,8 +169,8 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) { gpu::PipelinePointer DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled, - bool emmisive, bool depthBias) { - SimpleProgramKey config{textured, culled, emmisive, depthBias}; + bool emissive, bool depthBias) { + SimpleProgramKey config{textured, culled, emissive, depthBias}; gpu::PipelinePointer pipeline = getPipeline(config); batch.setPipeline(pipeline); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 9c4809a82e..eee5993c29 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -38,7 +38,7 @@ public: /// Sets up the state necessary to render static untextured geometry with the simple program. gpu::PipelinePointer bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true, - bool emmisive = false, bool depthBias = false); + bool emissive = false, bool depthBias = false); void renderSolidSphereInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec4& color); void renderSolidSphereInstance(gpu::Batch& batch, const Transform& xfm, const glm::vec3& color) { From d3c57821c0338b70e068b01f2b5f6c9721609773 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 16 Dec 2015 14:00:04 -0800 Subject: [PATCH 11/15] call a method on actions before each physics simulation step. use this to attempt to dejitter held objects --- interface/src/Application.cpp | 3 + interface/src/avatar/AvatarActionHold.cpp | 70 ++++++++++++++++++- interface/src/avatar/AvatarActionHold.h | 14 ++-- .../entities/src/EntityActionInterface.h | 2 + libraries/physics/src/CharacterController.cpp | 13 ++++ libraries/physics/src/CharacterController.h | 2 + libraries/physics/src/ObjectAction.h | 34 ++++----- libraries/physics/src/ObjectActionOffset.h | 10 +-- libraries/physics/src/ObjectActionSpring.h | 10 +-- libraries/physics/src/PhysicsEngine.cpp | 8 +++ libraries/physics/src/PhysicsEngine.h | 1 + 11 files changed, 134 insertions(+), 33 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f3291469cb..e28d1b2eac 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2989,6 +2989,9 @@ void Application::update(float deltaTime) { _physicsEngine->changeObjects(motionStates); myAvatar->prepareForPhysicsSimulation(); + _physicsEngine->forEachAction([&](EntityActionPointer action) { + action->prepareForPhysicsSimulation(); + }); getEntities()->getTree()->withWriteLock([&] { _physicsEngine->stepSimulation(); diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index fab838aa68..87cf53143c 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -14,6 +14,7 @@ #include #include "avatar/AvatarManager.h" +#include "CharacterController.h" const uint16_t AvatarActionHold::holdVersion = 1; @@ -32,6 +33,57 @@ AvatarActionHold::~AvatarActionHold() { #endif } +void AvatarActionHold::prepareForPhysicsSimulation() { + auto avatarManager = DependencyManager::get(); + auto holdingAvatar = std::static_pointer_cast(avatarManager->getAvatarBySessionID(_holderID)); + + if (!holdingAvatar) { + return; + } + + withTryReadLock([&]{ + bool isRightHand = (_hand == "right"); + + if (_ignoreIK && holdingAvatar->isMyAvatar()) { + return; + } + + if (holdingAvatar->isMyAvatar()) { + glm::vec3 palmPosition { Vectors::ZERO }; + glm::quat palmRotation { Quaternions::IDENTITY }; + if (isRightHand) { + palmPosition = holdingAvatar->getHand()->getCopyOfPalmData(HandData::RightHand).getPosition(); + palmRotation = holdingAvatar->getHand()->getCopyOfPalmData(HandData::RightHand).getRotation(); + } else { + palmPosition = holdingAvatar->getHand()->getCopyOfPalmData(HandData::LeftHand).getPosition(); + palmRotation = holdingAvatar->getHand()->getCopyOfPalmData(HandData::LeftHand).getRotation(); + } + + // XXX dup code + MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); + MyCharacterController* controller = myAvatar ? myAvatar->getCharacterController() : nullptr; + if (!controller) { + qDebug() << "AvatarActionHold::prepareForPhysicsSimulation failed to get character controller"; + return; + } + glm::vec3 avatarRigidBodyPosition; + glm::quat avatarRigidBodyRotation; + controller->getRigidBodyLocation(avatarRigidBodyPosition, avatarRigidBodyRotation); + + + if (isRightHand) { + palmPosition = holdingAvatar->getRightPalmPosition(); + palmRotation = holdingAvatar->getRightPalmRotation(); + } else { + palmPosition = holdingAvatar->getLeftPalmPosition(); + palmRotation = holdingAvatar->getLeftPalmRotation(); + } + + _palmOffsetFromRigidBody = palmPosition - avatarRigidBodyPosition; + } + }); +} + std::shared_ptr AvatarActionHold::getTarget(glm::quat& rotation, glm::vec3& position) { auto avatarManager = DependencyManager::get(); auto holdingAvatar = std::static_pointer_cast(avatarManager->getAvatarBySessionID(_holderID)); @@ -44,7 +96,7 @@ std::shared_ptr AvatarActionHold::getTarget(glm::quat& rotation, glm::ve bool isRightHand = (_hand == "right"); glm::vec3 palmPosition { Vectors::ZERO }; glm::quat palmRotation { Quaternions::IDENTITY }; - + if (_ignoreIK && holdingAvatar->isMyAvatar()) { // We cannot ignore other avatars IK and this is not the point of this option // This is meant to make the grabbing behavior more reactive. @@ -55,6 +107,22 @@ std::shared_ptr AvatarActionHold::getTarget(glm::quat& rotation, glm::ve palmPosition = holdingAvatar->getHand()->getCopyOfPalmData(HandData::LeftHand).getPosition(); palmRotation = holdingAvatar->getHand()->getCopyOfPalmData(HandData::LeftHand).getRotation(); } + } else if (holdingAvatar->isMyAvatar()) { + // XXX dup code + MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); + MyCharacterController* controller = myAvatar ? myAvatar->getCharacterController() : nullptr; + if (!controller) { + qDebug() << "AvatarActionHold::prepareForPhysicsSimulation failed to get character controller"; + return; + } + glm::vec3 avatarRigidBodyPosition; + glm::quat avatarRigidBodyRotation; + controller->getRigidBodyLocation(avatarRigidBodyPosition, avatarRigidBodyRotation); + + + + palmPosition = avatarRigidBodyPosition + _palmOffsetFromRigidBody; + palmRotation = holdingAvatar->getRightPalmRotation(); // XXX } else { if (isRightHand) { palmPosition = holdingAvatar->getRightPalmPosition(); diff --git a/interface/src/avatar/AvatarActionHold.h b/interface/src/avatar/AvatarActionHold.h index 63f30a75d9..2746c817ca 100644 --- a/interface/src/avatar/AvatarActionHold.h +++ b/interface/src/avatar/AvatarActionHold.h @@ -25,18 +25,20 @@ public: AvatarActionHold(const QUuid& id, EntityItemPointer ownerEntity); virtual ~AvatarActionHold(); - virtual bool updateArguments(QVariantMap arguments); - virtual QVariantMap getArguments(); + virtual bool updateArguments(QVariantMap arguments) override; + virtual QVariantMap getArguments() override; - virtual void updateActionWorker(float deltaTimeStep); + virtual void updateActionWorker(float deltaTimeStep) override; QByteArray serialize() const; - virtual void deserialize(QByteArray serializedArguments); + virtual void deserialize(QByteArray serializedArguments) override; - virtual bool shouldSuppressLocationEdits() { return _active && !_ownerEntity.expired(); } + virtual bool shouldSuppressLocationEdits() override { return _active && !_ownerEntity.expired(); } std::shared_ptr getTarget(glm::quat& rotation, glm::vec3& position); + virtual void prepareForPhysicsSimulation() override; + private: void doKinematicUpdate(float deltaTimeStep); @@ -56,6 +58,8 @@ private: float _previousDeltaTimeStep = 0.0f; glm::vec3 _previousPositionalDelta; + + glm::vec3 _palmOffsetFromRigidBody; }; #endif // hifi_AvatarActionHold_h diff --git a/libraries/entities/src/EntityActionInterface.h b/libraries/entities/src/EntityActionInterface.h index a192661e52..ba59d66cf4 100644 --- a/libraries/entities/src/EntityActionInterface.h +++ b/libraries/entities/src/EntityActionInterface.h @@ -58,6 +58,8 @@ public: virtual bool shouldSuppressLocationEdits() { return false; } + virtual void prepareForPhysicsSimulation() { } + // these look in the arguments map for a named argument. if it's not found or isn't well formed, // ok will be set to false (note that it's never set to true -- set it to true before calling these). // if required is true, failure to extract an argument will cause a warning to be printed. diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index 44d4269e0e..86d57b7ee9 100644 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -15,6 +15,7 @@ #include "BulletUtil.h" #include "PhysicsCollisionGroups.h" +#include "ObjectMotionState.h" const btVector3 LOCAL_UP_AXIS(0.0f, 1.0f, 0.0f); const float JUMP_SPEED = 3.5f; @@ -379,3 +380,15 @@ void CharacterController::preSimulation() { void CharacterController::postSimulation() { // postSimulation() exists for symmetry and just in case we need to do something here later } + + +bool CharacterController::getRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation) { + if (!_rigidBody) { + return false; + } + + const btTransform& worldTrans = _rigidBody->getCenterOfMassTransform(); + avatarRigidBodyPosition = bulletToGLM(worldTrans.getOrigin()) + ObjectMotionState::getWorldOffset(); + avatarRigidBodyRotation = bulletToGLM(worldTrans.getRotation()); + return true; +} diff --git a/libraries/physics/src/CharacterController.h b/libraries/physics/src/CharacterController.h index 88c02d0940..7bdc35fc0b 100644 --- a/libraries/physics/src/CharacterController.h +++ b/libraries/physics/src/CharacterController.h @@ -79,6 +79,8 @@ public: void setEnabled(bool enabled); bool isEnabled() const { return _enabled && _dynamicsWorld; } + bool getRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation); + protected: void updateUpAxis(const glm::quat& rotation); diff --git a/libraries/physics/src/ObjectAction.h b/libraries/physics/src/ObjectAction.h index e44036eadc..4ca13f2fbf 100644 --- a/libraries/physics/src/ObjectAction.h +++ b/libraries/physics/src/ObjectAction.h @@ -29,12 +29,12 @@ public: ObjectAction(EntityActionType type, const QUuid& id, EntityItemPointer ownerEntity); virtual ~ObjectAction(); - virtual void removeFromSimulation(EntitySimulation* simulation) const; - virtual EntityItemWeakPointer getOwnerEntity() const { return _ownerEntity; } - virtual void setOwnerEntity(const EntityItemPointer ownerEntity) { _ownerEntity = ownerEntity; } + virtual void removeFromSimulation(EntitySimulation* simulation) const override; + virtual EntityItemWeakPointer getOwnerEntity() const override { return _ownerEntity; } + virtual void setOwnerEntity(const EntityItemPointer ownerEntity) override { _ownerEntity = ownerEntity; } - virtual bool updateArguments(QVariantMap arguments); - virtual QVariantMap getArguments(); + virtual bool updateArguments(QVariantMap arguments) override; + virtual QVariantMap getArguments() override; // this is called from updateAction and should be overridden by subclasses virtual void updateActionWorker(float deltaTimeStep) = 0; @@ -43,25 +43,25 @@ public: virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep); virtual void debugDraw(btIDebugDraw* debugDrawer); - virtual QByteArray serialize() const = 0; - virtual void deserialize(QByteArray serializedArguments) = 0; + virtual QByteArray serialize() const override = 0; + virtual void deserialize(QByteArray serializedArguments) override = 0; - virtual bool lifetimeIsOver(); - virtual quint64 getExpires() { return _expires; } + virtual bool lifetimeIsOver() override; + virtual quint64 getExpires() override { return _expires; } protected: quint64 localTimeToServerTime(quint64 timeValue) const; quint64 serverTimeToLocalTime(quint64 timeValue) const; virtual btRigidBody* getRigidBody(); - virtual glm::vec3 getPosition(); - virtual void setPosition(glm::vec3 position); - virtual glm::quat getRotation(); - virtual void setRotation(glm::quat rotation); - virtual glm::vec3 getLinearVelocity(); - virtual void setLinearVelocity(glm::vec3 linearVelocity); - virtual glm::vec3 getAngularVelocity(); - virtual void setAngularVelocity(glm::vec3 angularVelocity); + virtual glm::vec3 getPosition() override; + virtual void setPosition(glm::vec3 position) override; + virtual glm::quat getRotation() override; + virtual void setRotation(glm::quat rotation) override; + virtual glm::vec3 getLinearVelocity() override; + virtual void setLinearVelocity(glm::vec3 linearVelocity) override; + virtual glm::vec3 getAngularVelocity() override; + virtual void setAngularVelocity(glm::vec3 angularVelocity) override; virtual void activateBody(); virtual void forceBodyNonStatic(); diff --git a/libraries/physics/src/ObjectActionOffset.h b/libraries/physics/src/ObjectActionOffset.h index 1918da6996..ea01b10d33 100644 --- a/libraries/physics/src/ObjectActionOffset.h +++ b/libraries/physics/src/ObjectActionOffset.h @@ -22,13 +22,13 @@ public: ObjectActionOffset(const QUuid& id, EntityItemPointer ownerEntity); virtual ~ObjectActionOffset(); - virtual bool updateArguments(QVariantMap arguments); - virtual QVariantMap getArguments(); + virtual bool updateArguments(QVariantMap arguments) override; + virtual QVariantMap getArguments() override; - virtual void updateActionWorker(float deltaTimeStep); + virtual void updateActionWorker(float deltaTimeStep) override; - virtual QByteArray serialize() const; - virtual void deserialize(QByteArray serializedArguments); + virtual QByteArray serialize() const override; + virtual void deserialize(QByteArray serializedArguments) override; private: static const uint16_t offsetVersion; diff --git a/libraries/physics/src/ObjectActionSpring.h b/libraries/physics/src/ObjectActionSpring.h index caa64c3d3a..96bb900bf6 100644 --- a/libraries/physics/src/ObjectActionSpring.h +++ b/libraries/physics/src/ObjectActionSpring.h @@ -19,13 +19,13 @@ public: ObjectActionSpring(const QUuid& id, EntityItemPointer ownerEntity); virtual ~ObjectActionSpring(); - virtual bool updateArguments(QVariantMap arguments); - virtual QVariantMap getArguments(); + virtual bool updateArguments(QVariantMap arguments) override; + virtual QVariantMap getArguments() override; - virtual void updateActionWorker(float deltaTimeStep); + virtual void updateActionWorker(float deltaTimeStep) override; - virtual QByteArray serialize() const; - virtual void deserialize(QByteArray serializedArguments); + virtual QByteArray serialize() const override; + virtual void deserialize(QByteArray serializedArguments) override; protected: static const uint16_t springVersion; diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 10e285186c..22695a1b66 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -497,3 +497,11 @@ void PhysicsEngine::removeAction(const QUuid actionID) { _objectActions.remove(actionID); } } + +void PhysicsEngine::forEachAction(std::function actor) { + QHashIterator iter(_objectActions); + while (iter.hasNext()) { + iter.next(); + actor(iter.value()); + } +} diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index e7b5fd79d4..05032ccae2 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -97,6 +97,7 @@ public: EntityActionPointer getActionByID(const QUuid& actionID) const; void addAction(EntityActionPointer action); void removeAction(const QUuid actionID); + void forEachAction(std::function actor); private: void removeContacts(ObjectMotionState* motionState); From 8bfbb69316712d5573aa435dc089c816de7f7c27 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 16 Dec 2015 14:21:56 -0800 Subject: [PATCH 12/15] clean up code, change try-locks to locks --- interface/src/avatar/AvatarActionHold.cpp | 89 ++++++++--------------- interface/src/avatar/AvatarActionHold.h | 1 + 2 files changed, 31 insertions(+), 59 deletions(-) diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index 87cf53143c..32d35e3f8f 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -33,6 +33,19 @@ AvatarActionHold::~AvatarActionHold() { #endif } +glm::vec3 AvatarActionHold::getAvatarRigidBodyPosition() { + MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); + MyCharacterController* controller = myAvatar ? myAvatar->getCharacterController() : nullptr; + if (!controller) { + qDebug() << "AvatarActionHold::getAvatarRigidBodyPosition failed to get character controller"; + return glm::vec3(0.0f); + } + glm::vec3 avatarRigidBodyPosition; + glm::quat avatarRigidBodyRotation; + controller->getRigidBodyLocation(avatarRigidBodyPosition, avatarRigidBodyRotation); + return avatarRigidBodyPosition; +} + void AvatarActionHold::prepareForPhysicsSimulation() { auto avatarManager = DependencyManager::get(); auto holdingAvatar = std::static_pointer_cast(avatarManager->getAvatarBySessionID(_holderID)); @@ -41,45 +54,14 @@ void AvatarActionHold::prepareForPhysicsSimulation() { return; } - withTryReadLock([&]{ - bool isRightHand = (_hand == "right"); - + withReadLock([&]{ if (_ignoreIK && holdingAvatar->isMyAvatar()) { return; } - if (holdingAvatar->isMyAvatar()) { - glm::vec3 palmPosition { Vectors::ZERO }; - glm::quat palmRotation { Quaternions::IDENTITY }; - if (isRightHand) { - palmPosition = holdingAvatar->getHand()->getCopyOfPalmData(HandData::RightHand).getPosition(); - palmRotation = holdingAvatar->getHand()->getCopyOfPalmData(HandData::RightHand).getRotation(); - } else { - palmPosition = holdingAvatar->getHand()->getCopyOfPalmData(HandData::LeftHand).getPosition(); - palmRotation = holdingAvatar->getHand()->getCopyOfPalmData(HandData::LeftHand).getRotation(); - } - - // XXX dup code - MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); - MyCharacterController* controller = myAvatar ? myAvatar->getCharacterController() : nullptr; - if (!controller) { - qDebug() << "AvatarActionHold::prepareForPhysicsSimulation failed to get character controller"; - return; - } - glm::vec3 avatarRigidBodyPosition; - glm::quat avatarRigidBodyRotation; - controller->getRigidBodyLocation(avatarRigidBodyPosition, avatarRigidBodyRotation); - - - if (isRightHand) { - palmPosition = holdingAvatar->getRightPalmPosition(); - palmRotation = holdingAvatar->getRightPalmRotation(); - } else { - palmPosition = holdingAvatar->getLeftPalmPosition(); - palmRotation = holdingAvatar->getLeftPalmRotation(); - } - - _palmOffsetFromRigidBody = palmPosition - avatarRigidBodyPosition; + glm::vec3 palmPosition = (_hand == "right") ? + holdingAvatar->getRightPalmPosition() : holdingAvatar->getLeftPalmPosition(); + _palmOffsetFromRigidBody = palmPosition - getAvatarRigidBodyPosition(); } }); } @@ -92,7 +74,7 @@ std::shared_ptr AvatarActionHold::getTarget(glm::quat& rotation, glm::ve return holdingAvatar; } - withTryReadLock([&]{ + withReadLock([&]{ bool isRightHand = (_hand == "right"); glm::vec3 palmPosition { Vectors::ZERO }; glm::quat palmRotation { Quaternions::IDENTITY }; @@ -108,21 +90,12 @@ std::shared_ptr AvatarActionHold::getTarget(glm::quat& rotation, glm::ve palmRotation = holdingAvatar->getHand()->getCopyOfPalmData(HandData::LeftHand).getRotation(); } } else if (holdingAvatar->isMyAvatar()) { - // XXX dup code - MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); - MyCharacterController* controller = myAvatar ? myAvatar->getCharacterController() : nullptr; - if (!controller) { - qDebug() << "AvatarActionHold::prepareForPhysicsSimulation failed to get character controller"; - return; + palmPosition = getAvatarRigidBodyPosition() + _palmOffsetFromRigidBody; + if (isRightHand) { + palmRotation = holdingAvatar->getRightPalmRotation(); + } else { + palmRotation = holdingAvatar->getLeftPalmRotation(); } - glm::vec3 avatarRigidBodyPosition; - glm::quat avatarRigidBodyRotation; - controller->getRigidBodyLocation(avatarRigidBodyPosition, avatarRigidBodyRotation); - - - - palmPosition = avatarRigidBodyPosition + _palmOffsetFromRigidBody; - palmRotation = holdingAvatar->getRightPalmRotation(); // XXX } else { if (isRightHand) { palmPosition = holdingAvatar->getRightPalmPosition(); @@ -171,21 +144,19 @@ void AvatarActionHold::updateActionWorker(float deltaTimeStep) { if (valid && holdCount > 0) { position /= holdCount; - bool gotLock = withTryWriteLock([&]{ + withWriteLock([&]{ _positionalTarget = position; _rotationalTarget = rotation; _positionalTargetSet = true; _rotationalTargetSet = true; _active = true; }); - if (gotLock) { - if (_kinematic) { - doKinematicUpdate(deltaTimeStep); - } else { - activateBody(); - forceBodyNonStatic(); - ObjectActionSpring::updateActionWorker(deltaTimeStep); - } + if (_kinematic) { + doKinematicUpdate(deltaTimeStep); + } else { + activateBody(); + forceBodyNonStatic(); + ObjectActionSpring::updateActionWorker(deltaTimeStep); } } } diff --git a/interface/src/avatar/AvatarActionHold.h b/interface/src/avatar/AvatarActionHold.h index 2746c817ca..36a9aa3049 100644 --- a/interface/src/avatar/AvatarActionHold.h +++ b/interface/src/avatar/AvatarActionHold.h @@ -35,6 +35,7 @@ public: virtual bool shouldSuppressLocationEdits() override { return _active && !_ownerEntity.expired(); } + glm::vec3 getAvatarRigidBodyPosition(); std::shared_ptr getTarget(glm::quat& rotation, glm::vec3& position); virtual void prepareForPhysicsSimulation() override; From 489d4099a7dbd76f59fa2d7b62092de402ba5748 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 16 Dec 2015 15:21:20 -0800 Subject: [PATCH 13/15] add locationChanged to model entities --- interface/src/avatar/AvatarActionHold.cpp | 2 ++ .../entities-renderer/src/RenderableModelEntityItem.cpp | 8 ++++++++ .../entities-renderer/src/RenderableModelEntityItem.h | 1 + 3 files changed, 11 insertions(+) diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index 32d35e3f8f..160a437f44 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -199,6 +199,8 @@ void AvatarActionHold::doKinematicUpdate(float deltaTimeStep) { motionState->dirtyInternalKinematicChanges(); + ownerEntity->setPosition(_positionalTarget); + _previousPositionalTarget = _positionalTarget; _previousRotationalTarget = _rotationalTarget; _previousSet = true; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index b5203ea460..14e89b59fd 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -625,3 +625,11 @@ glm::vec3 RenderableModelEntityItem::getAbsoluteJointTranslationInObjectFrame(in } return glm::vec3(0.0f); } + +void RenderableModelEntityItem::locationChanged() { + EntityItem::locationChanged(); + if (_model && _model->isActive()) { + _model->setRotation(getRotation()); + _model->setTranslation(getPosition()); + } +} diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 143113146e..cf948bd7a0 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -73,6 +73,7 @@ public: virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; virtual void loader() override; + virtual void locationChanged() override; private: void remapTextures(); From d7affcf811a8e5a46d5f201336effbeeec1584e3 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 16 Dec 2015 15:41:27 -0800 Subject: [PATCH 14/15] keep track of palm rotation vs avatar as well as palm translation --- interface/src/avatar/AvatarActionHold.cpp | 49 +++++++++++++++++------ interface/src/avatar/AvatarActionHold.h | 3 +- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index 160a437f44..5a4dbfa4d1 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -33,17 +33,15 @@ AvatarActionHold::~AvatarActionHold() { #endif } -glm::vec3 AvatarActionHold::getAvatarRigidBodyPosition() { +bool AvatarActionHold::getAvatarRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation) { MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); MyCharacterController* controller = myAvatar ? myAvatar->getCharacterController() : nullptr; if (!controller) { - qDebug() << "AvatarActionHold::getAvatarRigidBodyPosition failed to get character controller"; - return glm::vec3(0.0f); + qDebug() << "AvatarActionHold::getAvatarRigidBodyLocation failed to get character controller"; + return false; } - glm::vec3 avatarRigidBodyPosition; - glm::quat avatarRigidBodyRotation; controller->getRigidBodyLocation(avatarRigidBodyPosition, avatarRigidBodyRotation); - return avatarRigidBodyPosition; + return true; } void AvatarActionHold::prepareForPhysicsSimulation() { @@ -59,9 +57,28 @@ void AvatarActionHold::prepareForPhysicsSimulation() { return; } if (holdingAvatar->isMyAvatar()) { - glm::vec3 palmPosition = (_hand == "right") ? - holdingAvatar->getRightPalmPosition() : holdingAvatar->getLeftPalmPosition(); - _palmOffsetFromRigidBody = palmPosition - getAvatarRigidBodyPosition(); + glm::vec3 palmPosition; + glm::quat palmRotation; + if (_hand == "right") { + palmPosition = holdingAvatar->getRightPalmPosition(); + palmRotation = holdingAvatar->getRightPalmRotation(); + } else { + palmPosition = holdingAvatar->getLeftPalmPosition(); + palmRotation = holdingAvatar->getLeftPalmRotation(); + } + + glm::vec3 avatarRigidBodyPosition; + glm::quat avatarRigidBodyRotation; + getAvatarRigidBodyLocation(avatarRigidBodyPosition, avatarRigidBodyRotation); + + // determine the difference in translation and rotation between the avatar's + // rigid body and the palm position. The avatar's rigid body will be moved by bullet + // between this call and the call to getTarget, below. A call to get*PalmPosition in + // getTarget would get the palm position of the previous location of the avatar (because + // bullet has moved the av's rigid body but the rigid body's location has not yet been + // copied out into the Avatar class. + _palmOffsetFromRigidBody = palmPosition - avatarRigidBodyPosition; + _palmRotationFromRigidBody = glm::inverse(avatarRigidBodyRotation) * palmRotation; } }); } @@ -90,7 +107,17 @@ std::shared_ptr AvatarActionHold::getTarget(glm::quat& rotation, glm::ve palmRotation = holdingAvatar->getHand()->getCopyOfPalmData(HandData::LeftHand).getRotation(); } } else if (holdingAvatar->isMyAvatar()) { - palmPosition = getAvatarRigidBodyPosition() + _palmOffsetFromRigidBody; + glm::vec3 avatarRigidBodyPosition; + glm::quat avatarRigidBodyRotation; + getAvatarRigidBodyLocation(avatarRigidBodyPosition, avatarRigidBodyRotation); + + // the offset and rotation between the avatar's rigid body and the palm were determined earlier + // in prepareForPhysicsSimulation. At this point, the avatar's rigid body has been moved by bullet + // and the data in the Avatar class is stale. This means that the result of get*PalmPosition will + // be stale. Instead, determine the current palm position with the current avatar's rigid body + // location and the saved offsets. + palmPosition = avatarRigidBodyPosition + _palmOffsetFromRigidBody; + palmRotation = avatarRigidBodyRotation * _palmRotationFromRigidBody; if (isRightHand) { palmRotation = holdingAvatar->getRightPalmRotation(); } else { @@ -199,8 +226,6 @@ void AvatarActionHold::doKinematicUpdate(float deltaTimeStep) { motionState->dirtyInternalKinematicChanges(); - ownerEntity->setPosition(_positionalTarget); - _previousPositionalTarget = _positionalTarget; _previousRotationalTarget = _rotationalTarget; _previousSet = true; diff --git a/interface/src/avatar/AvatarActionHold.h b/interface/src/avatar/AvatarActionHold.h index 36a9aa3049..fc8baf6dcc 100644 --- a/interface/src/avatar/AvatarActionHold.h +++ b/interface/src/avatar/AvatarActionHold.h @@ -35,7 +35,7 @@ public: virtual bool shouldSuppressLocationEdits() override { return _active && !_ownerEntity.expired(); } - glm::vec3 getAvatarRigidBodyPosition(); + bool getAvatarRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation); std::shared_ptr getTarget(glm::quat& rotation, glm::vec3& position); virtual void prepareForPhysicsSimulation() override; @@ -61,6 +61,7 @@ private: glm::vec3 _previousPositionalDelta; glm::vec3 _palmOffsetFromRigidBody; + glm::quat _palmRotationFromRigidBody; }; #endif // hifi_AvatarActionHold_h From 5f9bdcb2aa6ba705ac3173cdebf9fbb171e03b90 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 16 Dec 2015 15:52:20 -0800 Subject: [PATCH 15/15] fix lock type --- interface/src/avatar/AvatarActionHold.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index 5a4dbfa4d1..34b959575d 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -52,7 +52,7 @@ void AvatarActionHold::prepareForPhysicsSimulation() { return; } - withReadLock([&]{ + withWriteLock([&]{ if (_ignoreIK && holdingAvatar->isMyAvatar()) { return; }