Merge pull request #2817 from PhilipRosedale/master

Clear visualization of hand/palm targets, improved audio scope
This commit is contained in:
Brad Hefta-Gaub 2014-05-08 11:13:06 -07:00
commit cb14cc59c2
15 changed files with 77 additions and 171 deletions

View file

@ -1217,10 +1217,6 @@ void Application::touchBeginEvent(QTouchEvent* event) {
return;
}
// put any application specific touch behavior below here..
_lastTouchAvgX = _touchAvgX;
_lastTouchAvgY = _touchAvgY;
}
void Application::touchEndEvent(QTouchEvent* event) {
@ -1875,34 +1871,6 @@ void Application::updateMyAvatarLookAtPosition() {
_myAvatar->getHead()->setLookAtPosition(lookAtSpot);
}
void Application::updateHandAndTouch(float deltaTime) {
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showWarnings, "Application::updateHandAndTouch()");
// Update from Touch
if (_isTouchPressed) {
_lastTouchAvgX = _touchAvgX;
_lastTouchAvgY = _touchAvgY;
}
}
void Application::updateLeap(float deltaTime) {
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showWarnings, "Application::updateLeap()");
}
void Application::updateSixense(float deltaTime) {
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showWarnings, "Application::updateSixense()");
_sixenseManager.update(deltaTime);
}
void Application::updateSerialDevices(float deltaTime) {
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showWarnings, "Application::updateSerialDevices()");
}
void Application::updateThreads(float deltaTime) {
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showWarnings, "Application::updateThreads()");
@ -2016,11 +1984,7 @@ void Application::update(float deltaTime) {
updateVisage();
_myAvatar->updateLookAtTargetAvatar();
updateMyAvatarLookAtPosition();
updateHandAndTouch(deltaTime); // Update state for touch sensors
updateLeap(deltaTime); // Leap finger-sensing device
updateSixense(deltaTime); // Razer Hydra controllers
updateSerialDevices(deltaTime); // Read serial port interface devices
_sixenseManager.update(deltaTime);
updateMyAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...
_avatarManager.updateOtherAvatars(deltaTime); //loop through all the other avatars and simulate them...

View file

@ -343,10 +343,6 @@ private:
void updateFaceshift();
void updateVisage();
void updateMyAvatarLookAtPosition();
void updateHandAndTouch(float deltaTime);
void updateLeap(float deltaTime);
void updateSixense(float deltaTime);
void updateSerialDevices(float deltaTime);
void updateThreads(float deltaTime);
void updateMetavoxels(float deltaTime);
void updateCamera(float deltaTime);
@ -477,8 +473,6 @@ private:
float _touchAvgX;
float _touchAvgY;
float _lastTouchAvgX;
float _lastTouchAvgY;
float _touchDragStartedAvgX;
float _touchDragStartedAvgY;
bool _isTouchPressed; // true if multitouch has been pressed (clear when finished)

View file

@ -1068,6 +1068,7 @@ void Audio::toggleScope() {
memset(_scopeInput.data(), 0, width * sizeof(int16_t));
memset(_scopeOutputLeft.data(), 0, width * sizeof(int16_t));
memset(_scopeOutputRight.data(), 0, width * sizeof(int16_t));
_scopeEnabledPause = false;
}
}

View file

@ -272,9 +272,6 @@ Menu::Menu() :
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Bandwidth, 0, true);
addActionToQMenuAndActionHash(viewMenu, MenuOption::BandwidthDetails, 0, this, SLOT(bandwidthDetails()));
addActionToQMenuAndActionHash(viewMenu, MenuOption::OctreeStats, 0, this, SLOT(octreeStatsDetails()));
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::AudioScope, 0, false,
appInstance->getAudio(),
SLOT(toggleScope()));
QMenu* developerMenu = addMenu("Developer");
@ -376,20 +373,6 @@ Menu::Menu() :
addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::PipelineWarnings);
addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::SuppressShortTimings);
addCheckableActionToQMenuAndActionHash(renderDebugMenu,
MenuOption::CullSharedFaces,
Qt::CTRL | Qt::SHIFT | Qt::Key_C,
false,
appInstance->getVoxels(),
SLOT(cullSharedFaces()));
addCheckableActionToQMenuAndActionHash(renderDebugMenu,
MenuOption::ShowCulledSharedFaces,
0,
false,
appInstance->getVoxels(),
SLOT(showCulledSharedFaces()));
QMenu* audioDebugMenu = developerMenu->addMenu("Audio Debugging Tools");
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioNoiseReduction,
0,
@ -413,8 +396,11 @@ Menu::Menu() :
false,
appInstance->getAudio(),
SLOT(toggleToneInjection()));
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioScope, Qt::CTRL | Qt::Key_P, false,
appInstance->getAudio(),
SLOT(toggleScope()));
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioScopePause,
Qt::CTRL | Qt::Key_P,
Qt::CTRL | Qt::SHIFT | Qt::Key_P ,
false,
appInstance->getAudio(),
SLOT(toggleScopePause()));

View file

@ -297,7 +297,6 @@ namespace MenuOption {
const QString CollideWithParticles = "Collide With Particles";
const QString CollideWithVoxels = "Collide With Voxels";
const QString Collisions = "Collisions";
const QString CullSharedFaces = "Cull Shared Voxel Faces";
const QString DecreaseAvatarSize = "Decrease Avatar Size";
const QString DecreaseVoxelSize = "Decrease Voxel Size";
const QString DisableAutoAdjustLOD = "Disable Automatically Adjusting LOD";
@ -367,7 +366,6 @@ namespace MenuOption {
const QString SettingsExport = "Export Settings";
const QString SettingsImport = "Import Settings";
const QString Shadows = "Shadows";
const QString ShowCulledSharedFaces = "Show Culled Shared Voxel Faces";
const QString ShowIKConstraints = "Show IK Constraints";
const QString Stars = "Stars";
const QString Stats = "Stats";

View file

@ -213,7 +213,7 @@ void Hand::render(bool isMine, Model::RenderMode renderMode) {
}
if (renderMode != Model::SHADOW_RENDER_MODE && Menu::getInstance()->isOptionChecked(MenuOption::DisplayHands)) {
renderLeapHands(isMine);
renderHandTargets(isMine);
}
glEnable(GL_DEPTH_TEST);
@ -221,11 +221,11 @@ void Hand::render(bool isMine, Model::RenderMode renderMode) {
}
void Hand::renderLeapHands(bool isMine) {
void Hand::renderHandTargets(bool isMine) {
const float alpha = 1.0f;
const glm::vec3 handColor(1.0, 0.84, 0.66); // use the skin color
const glm::vec3 handColor(1.0, 0.0, 0.0); // Color the hand targets red to be different than skin
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
@ -262,23 +262,37 @@ void Hand::renderLeapHands(bool isMine) {
glPopMatrix();
}
}
// Draw the finger root cones
const float PALM_BALL_RADIUS = 0.03f;
const float PALM_DISK_RADIUS = 0.06f;
const float PALM_DISK_THICKNESS = 0.01f;
const float PALM_FINGER_ROD_RADIUS = 0.003f;
// Draw the palm ball and disk
for (size_t i = 0; i < getNumPalms(); ++i) {
PalmData& palm = getPalms()[i];
if (palm.isActive()) {
for (size_t f = 0; f < palm.getNumFingers(); ++f) {
FingerData& finger = palm.getFingers()[f];
if (finger.isActive()) {
glColor4f(handColor.r, handColor.g, handColor.b, 0.5);
glColor4f(handColor.r, handColor.g, handColor.b, alpha);
glm::vec3 tip = finger.getTipPosition();
glm::vec3 root = finger.getRootPosition();
Avatar::renderJointConnectingCone(root, tip, 0.001f, 0.003f);
Avatar::renderJointConnectingCone(root, tip, PALM_FINGER_ROD_RADIUS, PALM_FINGER_ROD_RADIUS);
// Render sphere at palm/finger root
glm::vec3 palmNormal = root + palm.getNormal() * PALM_DISK_THICKNESS;
Avatar::renderJointConnectingCone(root, palmNormal, PALM_DISK_RADIUS, 0.0f);
glPushMatrix();
glTranslatef(root.x, root.y, root.z);
glutSolidSphere(PALM_BALL_RADIUS, 20.0f, 20.0f);
glPopMatrix();
}
}
}
}
/*
// Draw the hand paddles
int MAX_NUM_PADDLES = 2; // one for left and one for right
glColor4f(handColor.r, handColor.g, handColor.b, 0.3f);
@ -309,6 +323,7 @@ void Hand::renderLeapHands(bool isMine) {
Avatar::renderJointConnectingCone(root, tip, HAND_PADDLE_RADIUS, 0.f);
}
}
*/
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);

View file

@ -76,7 +76,7 @@ private:
std::vector<HandBall> _leapFingerTipBalls;
std::vector<HandBall> _leapFingerRootBalls;
void renderLeapHands(bool isMine);
void renderHandTargets(bool isMine);
void renderLeapFingerTrails();
void calculateGeometry();

View file

@ -106,16 +106,10 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
const float BROW_LIFT_THRESHOLD = 100.0f;
if (_audioAttack > BROW_LIFT_THRESHOLD) {
_browAudioLift += sqrtf(_audioAttack) * 0.00005f;
_browAudioLift += sqrtf(_audioAttack) * 0.01f;
}
_browAudioLift = glm::clamp(_browAudioLift *= 0.7f, 0.0f, 1.0f);
const float CLAMP = 0.01f;
if (_browAudioLift > CLAMP) {
_browAudioLift = CLAMP;
}
_browAudioLift *= 0.7f;
const float BLINK_SPEED = 10.0f;
const float FULLY_OPEN = 0.0f;
const float FULLY_CLOSED = 1.0f;
@ -147,12 +141,12 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
}
// use data to update fake Faceshift blendshape coefficients
const float BROW_LIFT_SCALE = 500.0f;
const float JAW_OPEN_SCALE = 0.01f;
const float JAW_OPEN_DEAD_ZONE = 0.75f;
Application::getInstance()->getFaceshift()->updateFakeCoefficients(_leftEyeBlink, _rightEyeBlink,
min(1.0f, _browAudioLift * BROW_LIFT_SCALE), glm::clamp(sqrt(_averageLoudness * JAW_OPEN_SCALE) -
JAW_OPEN_DEAD_ZONE, 0.0f, 1.0f), _blendshapeCoefficients);
const float JAW_OPEN_SCALE = 10.f;
Application::getInstance()->getFaceshift()->updateFakeCoefficients(_leftEyeBlink,
_rightEyeBlink,
_browAudioLift,
glm::clamp(log(_averageLoudness) / JAW_OPEN_SCALE, 0.0f, 1.0f),
_blendshapeCoefficients);
}
if (!isMine) {

View file

@ -99,13 +99,17 @@ void MyAvatar::reset() {
setVelocity(glm::vec3(0.0f));
setThrust(glm::vec3(0.0f));
setOrientation(glm::quat(glm::vec3(0.0f)));
// Reset the pitch and roll components of the avatar's orientation, preserve yaw direction
glm::vec3 eulers = safeEulerAngles(getOrientation());
eulers.x = 0.f;
eulers.z = 0.f;
setOrientation(glm::quat(eulers));
}
void MyAvatar::update(float deltaTime) {
Head* head = getHead();
head->relaxLean(deltaTime);
updateFromGyros(deltaTime);
updateFromFaceTracker(deltaTime);
if (Menu::getInstance()->isOptionChecked(MenuOption::MoveWithLean)) {
// Faceshift drive is enabled, set the avatar drive based on the head position
moveWithLean();
@ -132,7 +136,14 @@ void MyAvatar::simulate(float deltaTime) {
}
// update the movement of the hand and process handshaking with other avatars...
updateHandMovementAndTouching(deltaTime);
bool pointing = false;
if (_mousePressed) {
_handState = HAND_STATE_GRASPING;
} else if (pointing) {
_handState = HAND_STATE_POINTING;
} else {
_handState = HAND_STATE_NULL;
}
updateOrientation(deltaTime);
@ -228,7 +239,7 @@ void MyAvatar::simulate(float deltaTime) {
}
// Update avatar head rotation with sensor data
void MyAvatar::updateFromGyros(float deltaTime) {
void MyAvatar::updateFromFaceTracker(float deltaTime) {
glm::vec3 estimatedPosition, estimatedRotation;
FaceTracker* tracker = Application::getInstance()->getActiveFaceTracker();
@ -911,40 +922,6 @@ void MyAvatar::updateThrust(float deltaTime) {
}
*/
void MyAvatar::updateHandMovementAndTouching(float deltaTime) {
glm::quat orientation = getOrientation();
// reset hand and arm positions according to hand movement
glm::vec3 up = orientation * IDENTITY_UP;
bool pointing = false;
if (glm::length(_mouseRayDirection) > EPSILON && !Application::getInstance()->isMouseHidden()) {
// confine to the approximate shoulder plane
glm::vec3 pointDirection = _mouseRayDirection;
if (glm::dot(_mouseRayDirection, up) > 0.0f) {
glm::vec3 projectedVector = glm::cross(up, glm::cross(_mouseRayDirection, up));
if (glm::length(projectedVector) > EPSILON) {
pointDirection = glm::normalize(projectedVector);
}
}
glm::vec3 shoulderPosition;
if (_skeletonModel.getRightShoulderPosition(shoulderPosition)) {
glm::vec3 farVector = _mouseRayOrigin + pointDirection * (float)TREE_SCALE - shoulderPosition;
const float ARM_RETRACTION = 0.75f;
float retractedLength = _skeletonModel.getRightArmLength() * ARM_RETRACTION;
setHandPosition(shoulderPosition + glm::normalize(farVector) * retractedLength);
pointing = true;
}
}
if (_mousePressed) {
_handState = HAND_STATE_GRASPING;
} else if (pointing) {
_handState = HAND_STATE_POINTING;
} else {
_handState = HAND_STATE_NULL;
}
}
void MyAvatar::updateCollisionWithEnvironment(float deltaTime, float radius) {
glm::vec3 up = getBodyUpDirection();

View file

@ -38,7 +38,7 @@ public:
void reset();
void update(float deltaTime);
void simulate(float deltaTime);
void updateFromGyros(float deltaTime);
void updateFromFaceTracker(float deltaTime);
void moveWithLean();
void render(const glm::vec3& cameraPosition, RenderMode renderMode = NORMAL_RENDER_MODE);
@ -147,7 +147,6 @@ private:
float computeMotorTimescale();
void applyMotor(float deltaTime);
void applyThrust(float deltaTime);
void updateHandMovementAndTouching(float deltaTime);
void updateCollisionWithAvatars(float deltaTime);
void updateCollisionWithEnvironment(float deltaTime, float radius);
void updateCollisionWithVoxels(float deltaTime, float radius);

View file

@ -38,24 +38,23 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
Hand* hand = _owningAvatar->getHand();
hand->getLeftRightPalmIndices(leftPalmIndex, rightPalmIndex);
const float HAND_RESTORATION_PERIOD = 1.f; // seconds
float handRestorePercent = glm::clamp(deltaTime / HAND_RESTORATION_PERIOD, 0.f, 1.f);
const float HAND_RESTORATION_RATE = 0.25f;
const FBXGeometry& geometry = _geometry->getFBXGeometry();
if (leftPalmIndex == -1) {
// no Leap data; set hands from mouse
if (_owningAvatar->getHandState() == HAND_STATE_NULL) {
restoreRightHandPosition(handRestorePercent);
restoreRightHandPosition(HAND_RESTORATION_RATE);
} else {
applyHandPosition(geometry.rightHandJointIndex, _owningAvatar->getHandPosition());
}
restoreLeftHandPosition(handRestorePercent);
restoreLeftHandPosition(HAND_RESTORATION_RATE);
} else if (leftPalmIndex == rightPalmIndex) {
// right hand only
applyPalmData(geometry.rightHandJointIndex, geometry.rightFingerJointIndices, geometry.rightFingertipJointIndices,
hand->getPalms()[leftPalmIndex]);
restoreLeftHandPosition(handRestorePercent);
restoreLeftHandPosition(HAND_RESTORATION_RATE);
} else {
applyPalmData(geometry.leftHandJointIndex, geometry.leftFingerJointIndices, geometry.leftFingertipJointIndices,

View file

@ -30,6 +30,7 @@ const float NECK_Z = 300.f; // millimeters
SixenseManager::SixenseManager() {
#ifdef HAVE_SIXENSE
_lastMovement = 0;
_amountMoved = glm::vec3(0.0f);
_calibrationState = CALIBRATION_STATE_IDLE;
// By default we assume the _neckBase (in orb frame) is as high above the orb
@ -122,14 +123,21 @@ void SixenseManager::update(float deltaTime) {
palm->setRawRotation(rotation);
// Compute current velocity from position change
glm::vec3 rawVelocity = (position - palm->getRawPosition()) / deltaTime / 1000.f;
glm::vec3 rawVelocity;
if (deltaTime > 0.f) {
rawVelocity = (position - palm->getRawPosition()) / deltaTime / 1000.f;
} else {
rawVelocity = glm::vec3(0.0f);
}
palm->setRawVelocity(rawVelocity); // meters/sec
palm->setRawPosition(position);
// use the velocity to determine whether there's any movement (if the hand isn't new)
const float MOVEMENT_SPEED_THRESHOLD = 0.05f;
if (glm::length(rawVelocity) > MOVEMENT_SPEED_THRESHOLD && foundHand) {
const float MOVEMENT_DISTANCE_THRESHOLD = 0.003f;
_amountMoved += rawVelocity * deltaTime;
if (glm::length(_amountMoved) > MOVEMENT_DISTANCE_THRESHOLD && foundHand) {
_lastMovement = usecTimestampNow();
_amountMoved = glm::vec3(0.0f);
}
// initialize the "finger" based on the direction
@ -143,7 +151,11 @@ void SixenseManager::update(float deltaTime) {
// Store the one fingertip in the palm structure so we can track velocity
glm::vec3 oldTipPosition = palm->getTipRawPosition();
palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime / 1000.f);
if (deltaTime > 0.f) {
palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime / 1000.f);
} else {
palm->setTipVelocity(glm::vec3(0.f));
}
palm->setTipPosition(newTipPosition);
// three fingers indicates to the skeleton that we have enough data to determine direction
@ -158,8 +170,8 @@ void SixenseManager::update(float deltaTime) {
}
// if the controllers haven't been moved in a while, disable
const unsigned int MOVEMENT_DISABLE_DURATION = 30 * 1000 * 1000;
if (usecTimestampNow() - _lastMovement > MOVEMENT_DISABLE_DURATION) {
const unsigned int MOVEMENT_DISABLE_SECONDS = 3;
if (usecTimestampNow() - _lastMovement > (MOVEMENT_DISABLE_SECONDS * 1000 * 1000)) {
for (std::vector<PalmData>::iterator it = hand->getPalms().begin(); it != hand->getPalms().end(); it++) {
it->setActive(false);
}

View file

@ -64,6 +64,7 @@ private:
#endif
quint64 _lastMovement;
glm::vec3 _amountMoved;
};
#endif // hifi_SixenseManager_h

View file

@ -1711,38 +1711,6 @@ bool VoxelSystem::inspectForExteriorOcclusionsOperation(OctreeElement* element,
return true;
}
void VoxelSystem::cullSharedFaces() {
if (Menu::getInstance()->isOptionChecked(MenuOption::CullSharedFaces)) {
_useVoxelShader = false;
_usePrimitiveRenderer = true;
inspectForOcclusions();
} else {
_usePrimitiveRenderer = false;
clearAllNodesBufferIndex();
}
_writeRenderFullVBO = true;
_tree->setDirtyBit();
setupNewVoxelsForDrawing();
}
void VoxelSystem::showCulledSharedFaces() {
_tree->lockForRead();
if (Menu::getInstance()->isOptionChecked(MenuOption::ShowCulledSharedFaces)) {
_showCulledSharedFaces = true;
} else {
_showCulledSharedFaces = false;
}
_tree->unlock();
if (Menu::getInstance()->isOptionChecked(MenuOption::CullSharedFaces)) {
_writeRenderFullVBO = true;
_tree->setDirtyBit();
setupNewVoxelsForDrawing();
}
}
void VoxelSystem::inspectForOcclusions() {
if (_inOcclusions) {

View file

@ -95,9 +95,7 @@ public slots:
// Methods that recurse tree
void forceRedrawEntireTree();
void clearAllNodesBufferIndex();
void cullSharedFaces();
void showCulledSharedFaces();
void setDisableFastVoxelPipeline(bool disableFastVoxelPipeline);
void setUseVoxelShader(bool useVoxelShader);
void setVoxelsAsPoints(bool voxelsAsPoints);