Merge pull request #1290 from PhilipRosedale/master

Hydra hands realigned for controller to side, local audio loopback option, tweaks to lean driving, tuning of turning
This commit is contained in:
Andrzej Kapolka 2013-11-26 14:50:32 -08:00
commit cd1fa380d5
7 changed files with 66 additions and 37 deletions

View file

@ -27,12 +27,8 @@
#include "Menu.h"
#include "Util.h"
// Uncomment the following definition to test audio device latency by copying output to input
//#define TEST_AUDIO_LOOPBACK
//#define SHOW_AUDIO_DEBUG
#define VISUALIZE_ECHO_CANCELLATION
static const int PHASE_DELAY_AT_90 = 20;
static const float AMPLITUDE_RATIO_AT_90 = 0.5;
static const int MIN_FLANGE_EFFECT_THRESHOLD = 600;
@ -84,11 +80,17 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o
memset(outputLeft, 0, PACKET_LENGTH_BYTES_PER_CHANNEL);
memset(outputRight, 0, PACKET_LENGTH_BYTES_PER_CHANNEL);
// If Mute button is pressed, clear the input buffer
// If Mute button is pressed, clear the input buffer
if (_muted) {
memset(inputLeft, 0, PACKET_LENGTH_BYTES_PER_CHANNEL);
}
// If local loopback enabled, copy input to output
if (Menu::getInstance()->isOptionChecked(MenuOption::EchoLocalAudio)) {
memcpy(outputLeft, inputLeft, PACKET_LENGTH_BYTES_PER_CHANNEL);
memcpy(outputRight, inputLeft, PACKET_LENGTH_BYTES_PER_CHANNEL);
}
// Add Procedural effects to input samples
addProceduralSounds(inputLeft, outputLeft, outputRight, BUFFER_LENGTH_SAMPLES_PER_CHANNEL);
@ -120,7 +122,7 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o
// + 12 for 3 floats for position + float for bearing + 1 attenuation byte
unsigned char dataPacket[MAX_PACKET_SIZE];
PACKET_TYPE packetType = Menu::getInstance()->isOptionChecked(MenuOption::EchoAudio)
PACKET_TYPE packetType = Menu::getInstance()->isOptionChecked(MenuOption::EchoServerAudio)
? PACKET_TYPE_MICROPHONE_AUDIO_WITH_ECHO
: PACKET_TYPE_MICROPHONE_AUDIO_NO_ECHO;
@ -360,7 +362,8 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples) :
_collisionSoundDuration(0.0f),
_proceduralEffectSample(0),
_heartbeatMagnitude(0.0f),
_muted(false)
_muted(false),
_localEcho(false)
{
outputPortAudioError(Pa_Initialize());

View file

@ -70,6 +70,7 @@ public:
// in which case 'true' is returned - otherwise the return value is 'false'.
// The results of the analysis are written to the log.
bool eventuallyAnalyzePing();
private:
PaStream* _stream;
@ -109,6 +110,7 @@ private:
float _heartbeatMagnitude;
bool _muted;
bool _localEcho;
GLuint _micTextureId;
GLuint _muteTextureId;
QRect _iconBounds;

View file

@ -491,8 +491,9 @@ Menu::Menu() :
addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::CoverageMapV2, Qt::SHIFT | Qt::CTRL | Qt::Key_P);
QMenu* audioDebugMenu = developerMenu->addMenu("Audio Debugging Tools");
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoAudio);
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoServerAudio);
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoLocalAudio);
QMenu* voxelProtoOptionsMenu = developerMenu->addMenu("Voxel Server Protocol Options");
addCheckableActionToQMenuAndActionHash(voxelProtoOptionsMenu, MenuOption::SendVoxelColors);

View file

@ -168,7 +168,8 @@ namespace MenuOption {
const QString DisplayLeapHands = "Display Leap Hands";
const QString DontRenderVoxels = "Don't call _voxels.render()";
const QString DontCallOpenGLForVoxels = "Don't call glDrawRangeElementsEXT() for Voxels";
const QString EchoAudio = "Echo Audio";
const QString EchoServerAudio = "Echo Server Audio";
const QString EchoLocalAudio = "Echo Local Audio";
const QString ExportVoxels = "Export Voxels";
const QString ExtraDebugging = "Extra Debugging";
const QString DontFadeOnVoxelServerChanges = "Don't Fade In/Out on Voxel Server Changes";

View file

@ -381,15 +381,18 @@ void MyAvatar::updateFromGyrosAndOrWebcam(bool turnWithHead) {
if (faceshift->isActive()) {
estimatedPosition = faceshift->getHeadTranslation();
estimatedRotation = safeEulerAngles(faceshift->getHeadRotation());
// Rotate the body if the head is turned quickly
// Rotate the body if the head is turned beyond the screen
if (turnWithHead) {
glm::vec3 headAngularVelocity = faceshift->getHeadAngularVelocity();
const float FACESHIFT_YAW_TURN_SENSITIVITY = 0.25f;
const float FACESHIFT_MIN_YAW_TURN = 10.f;
const float FACESHIFT_MAX_YAW_TURN = 30.f;
const float FACESHIFT_YAW_TURN_SENSITIVITY = 0.5f;
const float FACESHIFT_MIN_YAW_TURN = 15.f;
const float FACESHIFT_MAX_YAW_TURN = 50.f;
if ( (fabs(estimatedRotation.y) > FACESHIFT_MIN_YAW_TURN) &&
(fabs(estimatedRotation.y) < FACESHIFT_MAX_YAW_TURN) ) {
_bodyYawDelta += estimatedRotation.y * FACESHIFT_YAW_TURN_SENSITIVITY;
if (estimatedRotation.y > 0.f) {
_bodyYawDelta += (estimatedRotation.y - FACESHIFT_MIN_YAW_TURN) * FACESHIFT_YAW_TURN_SENSITIVITY;
} else {
_bodyYawDelta += (estimatedRotation.y + FACESHIFT_MIN_YAW_TURN) * FACESHIFT_YAW_TURN_SENSITIVITY;
}
}
}
} else if (gyros->isActive()) {
@ -459,22 +462,33 @@ void MyAvatar::updateFromGyrosAndOrWebcam(bool turnWithHead) {
if (!Menu::getInstance()->isOptionChecked(MenuOption::MoveWithLean)) {
return;
}
const float ANGULAR_DRIVE_SCALE = 0.1f;
const float ANGULAR_DEAD_ZONE = 0.3f;
setDriveKeys(FWD, glm::clamp(-_head.getLeanForward() * ANGULAR_DRIVE_SCALE - ANGULAR_DEAD_ZONE, 0.0f, 1.0f));
setDriveKeys(BACK, glm::clamp(_head.getLeanForward() * ANGULAR_DRIVE_SCALE - ANGULAR_DEAD_ZONE, 0.0f, 1.0f));
setDriveKeys(LEFT, glm::clamp(_head.getLeanSideways() * ANGULAR_DRIVE_SCALE - ANGULAR_DEAD_ZONE, 0.0f, 1.0f));
setDriveKeys(RIGHT, glm::clamp(-_head.getLeanSideways() * ANGULAR_DRIVE_SCALE - ANGULAR_DEAD_ZONE, 0.0f, 1.0f));
// only consider going up if we're not going in any of the four horizontal directions
if (_driveKeys[FWD] == 0.0f && _driveKeys[BACK] == 0.0f && _driveKeys[LEFT] == 0.0f && _driveKeys[RIGHT] == 0.0f) {
const float LINEAR_DRIVE_SCALE = 5.0f;
const float LINEAR_DEAD_ZONE = 0.95f;
float torsoDelta = glm::length(relativePosition) - TORSO_LENGTH;
setDriveKeys(UP, glm::clamp(torsoDelta * LINEAR_DRIVE_SCALE - LINEAR_DEAD_ZONE, 0.0f, 1.0f));
} else {
setDriveKeys(UP, 0.0f);
// Move with Lean by applying thrust proportional to leaning
glm::quat orientation = _head.getCameraOrientation();
glm::vec3 front = orientation * IDENTITY_FRONT;
glm::vec3 right = orientation * IDENTITY_RIGHT;
float leanForward = _head.getLeanForward();
float leanSideways = _head.getLeanSideways();
// Degrees of 'dead zone' when leaning, and amount of acceleration to apply to lean angle
const float LEAN_FWD_DEAD_ZONE = 15.f;
const float LEAN_SIDEWAYS_DEAD_ZONE = 10.f;
const float LEAN_FWD_THRUST_SCALE = 4.f;
const float LEAN_SIDEWAYS_THRUST_SCALE = 3.f;
if (fabs(leanForward) > LEAN_FWD_DEAD_ZONE) {
if (leanForward > 0.f) {
addThrust(front * -(leanForward - LEAN_FWD_DEAD_ZONE) * LEAN_FWD_THRUST_SCALE);
} else {
addThrust(front * -(leanForward + LEAN_FWD_DEAD_ZONE) * LEAN_FWD_THRUST_SCALE);
}
}
if (fabs(leanSideways) > LEAN_SIDEWAYS_DEAD_ZONE) {
if (leanSideways > 0.f) {
addThrust(right * -(leanSideways - LEAN_SIDEWAYS_DEAD_ZONE) * LEAN_SIDEWAYS_THRUST_SCALE);
} else {
addThrust(right * -(leanSideways + LEAN_SIDEWAYS_DEAD_ZONE) * LEAN_SIDEWAYS_THRUST_SCALE);
}
}
}

View file

@ -58,12 +58,20 @@ void SixenseManager::update() {
avatar->setDriveKeys(DOWN, data.trigger);
}
// set palm position and normal based on Hydra position/orientation
// Set palm position and normal based on Hydra position/orientation
PalmData palm(&hand);
palm.setActive(true);
glm::vec3 position(-data.pos[0], data.pos[1], -data.pos[2]);
glm::vec3 position(data.pos[0], data.pos[1], data.pos[2]);
// Adjust for distance between acquisition 'orb' and the user's torso
// (distance to the right of body center, distance below torso, distance behind torso)
const glm::vec3 SPHERE_TO_TORSO(-250.f, -300.f, -300.f);
position = SPHERE_TO_TORSO + position;
palm.setRawPosition(position);
glm::quat rotation(data.rot_quat[3], -data.rot_quat[0], data.rot_quat[1], -data.rot_quat[2]);
// Rotate about controller
rotation = glm::angleAxis(180.0f, 0.f, 1.f, 0.f) * rotation;
const glm::vec3 PALM_VECTOR(0.0f, -1.0f, 0.0f);
palm.setRawNormal(rotation * PALM_VECTOR);

View file

@ -113,20 +113,20 @@ PerformanceWarning::~PerformanceWarning() {
if ((_alwaysDisplay || _renderWarningsOn) && elapsedmsec > 1) {
if (elapsedmsec > 1000) {
double elapsedsec = (end - _start) / 1000000.0;
qDebug("%s took %lf seconds %s\n", _message, elapsedsec, (_alwaysDisplay ? "" : "WARNING!") );
qDebug("%s took %.2lf seconds %s\n", _message, elapsedsec, (_alwaysDisplay ? "" : "WARNING!") );
} else {
if (_suppressShortTimings) {
if (elapsedmsec > 10) {
qDebug("%s took %lf milliseconds %s\n", _message, elapsedmsec,
qDebug("%s took %.1lf milliseconds %s\n", _message, elapsedmsec,
(_alwaysDisplay || (elapsedmsec < 10) ? "" : "WARNING!"));
}
} else {
qDebug("%s took %lf milliseconds %s\n", _message, elapsedmsec,
qDebug("%s took %.2lf milliseconds %s\n", _message, elapsedmsec,
(_alwaysDisplay || (elapsedmsec < 10) ? "" : "WARNING!"));
}
}
} else if (_alwaysDisplay) {
qDebug("%s took %lf milliseconds\n", _message, elapsedmsec);
qDebug("%s took %.2lf milliseconds\n", _message, elapsedmsec);
}
// if the caller gave us a pointer to store the running total, track it now.
if (_runningTotal) {