This commit is contained in:
Stephen Birarda 2014-05-28 10:09:55 -07:00
commit 54bdae4428
21 changed files with 393 additions and 239 deletions

22
examples/playSoundWave.js Normal file
View file

@ -0,0 +1,22 @@
//
// playSoundWave.js
// examples
//
// Created by Ryan Huffman on 05/27/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
var soundClip = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Cocktail%20Party%20Snippets/Walken1.wav");
function playSound() {
var options = new AudioInjectionOptions();
var position = MyAvatar.position;
options.position = position;
options.volume = 0.5;
Audio.playSound(soundClip, options);
}
Script.setInterval(playSound, 10000);

View file

@ -13,8 +13,15 @@
uniform sampler2DShadow shadowMap;
// the inverse of the size of the shadow map
const float shadowScale = 1.0 / 2048.0;
varying vec4 shadowColor;
void main(void) {
gl_FragColor = mix(shadowColor, gl_Color, shadow2D(shadowMap, gl_TexCoord[0].stp));
gl_FragColor = mix(shadowColor, gl_Color, 0.25 *
(shadow2D(shadowMap, gl_TexCoord[0].stp + vec3(-shadowScale, -shadowScale, 0.0)).r +
shadow2D(shadowMap, gl_TexCoord[0].stp + vec3(-shadowScale, shadowScale, 0.0)).r +
shadow2D(shadowMap, gl_TexCoord[0].stp + vec3(shadowScale, -shadowScale, 0.0)).r +
shadow2D(shadowMap, gl_TexCoord[0].stp + vec3(shadowScale, shadowScale, 0.0)).r));
}

View file

@ -2291,6 +2291,12 @@ void Application::updateShadowMap() {
radius = qMax(radius, glm::distance(points[i], center));
}
center = inverseRotation * center;
// to reduce texture "shimmer," move in texel increments
float texelSize = (2.0f * radius) / fbo->width();
center = glm::vec3(roundf(center.x / texelSize) * texelSize, roundf(center.y / texelSize) * texelSize,
roundf(center.z / texelSize) * texelSize);
glm::vec3 minima(center.x - radius, center.y - radius, center.z - radius);
glm::vec3 maxima(center.x + radius, center.y + radius, center.z + radius);

View file

@ -97,9 +97,11 @@ Audio::Audio(int16_t initialJitterBufferSamples, QObject* parent) :
_scopeEnabledPause(false),
_scopeInputOffset(0),
_scopeOutputOffset(0),
_scopeInput(SAMPLES_PER_SCOPE_WIDTH * sizeof(int16_t), 0),
_scopeOutputLeft(SAMPLES_PER_SCOPE_WIDTH * sizeof(int16_t), 0),
_scopeOutputRight(SAMPLES_PER_SCOPE_WIDTH * sizeof(int16_t), 0)
_framesPerScope(DEFAULT_FRAMES_PER_SCOPE),
_samplesPerScope(NETWORK_SAMPLES_PER_FRAME * _framesPerScope),
_scopeInput(0),
_scopeOutputLeft(0),
_scopeOutputRight(0)
{
// clear the array of locally injected samples
memset(_localProceduralSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL);
@ -592,7 +594,7 @@ void Audio::handleAudioInput() {
unsigned int monoAudioChannel = 0;
addBufferToScope(_scopeInput, _scopeInputOffset, monoAudioSamples, monoAudioChannel, numMonoAudioChannels);
_scopeInputOffset += NETWORK_SAMPLES_PER_FRAME;
_scopeInputOffset %= SAMPLES_PER_SCOPE_WIDTH;
_scopeInputOffset %= _samplesPerScope;
}
NodeList* nodeList = NodeList::getInstance();
@ -849,7 +851,7 @@ void Audio::processReceivedAudio(const QByteArray& audioByteArray) {
samples, audioChannel, numAudioChannels);
_scopeOutputOffset += NETWORK_SAMPLES_PER_FRAME;
_scopeOutputOffset %= SAMPLES_PER_SCOPE_WIDTH;
_scopeOutputOffset %= _samplesPerScope;
samples += NETWORK_SAMPLES_PER_FRAME * numAudioChannels;
}
}
@ -1060,25 +1062,73 @@ void Audio::renderToolBox(int x, int y, bool boxed) {
glDisable(GL_TEXTURE_2D);
}
void Audio::toggleScope() {
_scopeEnabled = !_scopeEnabled;
if (_scopeEnabled) {
_scopeInputOffset = 0;
_scopeOutputOffset = 0;
allocateScope();
} else {
freeScope();
}
}
void Audio::toggleScopePause() {
_scopeEnabledPause = !_scopeEnabledPause;
}
void Audio::toggleScope() {
_scopeEnabled = !_scopeEnabled;
if (_scopeEnabled) {
static const int width = SAMPLES_PER_SCOPE_WIDTH;
_scopeInputOffset = 0;
_scopeOutputOffset = 0;
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;
void Audio::selectAudioScopeFiveFrames() {
if (Menu::getInstance()->isOptionChecked(MenuOption::AudioScopeFiveFrames)) {
reallocateScope(5);
}
}
void Audio::selectAudioScopeTwentyFrames() {
if (Menu::getInstance()->isOptionChecked(MenuOption::AudioScopeTwentyFrames)) {
reallocateScope(20);
}
}
void Audio::selectAudioScopeFiftyFrames() {
if (Menu::getInstance()->isOptionChecked(MenuOption::AudioScopeFiftyFrames)) {
reallocateScope(50);
}
}
void Audio::allocateScope() {
int num = _samplesPerScope * sizeof(int16_t);
_scopeInput = new QByteArray(num, 0);
_scopeOutputLeft = new QByteArray(num, 0);
_scopeOutputRight = new QByteArray(num, 0);
}
void Audio::reallocateScope(int frames) {
if (_framesPerScope != frames) {
_framesPerScope = frames;
_samplesPerScope = NETWORK_SAMPLES_PER_FRAME * _framesPerScope;
QMutexLocker lock(&_guard);
freeScope();
allocateScope();
}
}
void Audio::freeScope() {
if (_scopeInput) {
delete _scopeInput;
_scopeInput = 0;
}
if (_scopeOutputLeft) {
delete _scopeOutputLeft;
_scopeOutputLeft = 0;
}
if (_scopeOutputRight) {
delete _scopeOutputRight;
_scopeOutputRight = 0;
}
}
void Audio::addBufferToScope(
QByteArray& byteArray, unsigned int frameOffset, const int16_t* source, unsigned int sourceChannel, unsigned int sourceNumberOfChannels) {
QByteArray* byteArray, unsigned int frameOffset, const int16_t* source, unsigned int sourceChannel, unsigned int sourceNumberOfChannels) {
// Constant multiplier to map sample value to vertical size of scope
float multiplier = (float)MULTIPLIER_SCOPE_HEIGHT / logf(2.0f);
@ -1089,8 +1139,9 @@ void Audio::addBufferToScope(
// Temporary variable receives mapping of sample value
int16_t value;
QMutexLocker lock(&_guard);
// Short int pointer to mapped samples in byte array
int16_t* destination = (int16_t*) byteArray.data();
int16_t* destination = (int16_t*) byteArray->data();
for (unsigned int i = 0; i < NETWORK_SAMPLES_PER_FRAME; i++) {
sample = (float)source[i * sourceNumberOfChannels + sourceChannel];
@ -1116,18 +1167,20 @@ void Audio::renderScope(int width, int height) {
static const float outputLeftColor[4] = { 0.7f, .3f, 0.3f, 0.6f };
static const float outputRightColor[4] = { 0.3f, .3f, 0.7f, 0.6f };
static const int gridRows = 2;
static const int gridCols = 5;
int gridCols = _framesPerScope;
int x = (width - SAMPLES_PER_SCOPE_WIDTH) / 2;
int y = (height - SAMPLES_PER_SCOPE_HEIGHT) / 2;
int w = SAMPLES_PER_SCOPE_WIDTH;
int h = SAMPLES_PER_SCOPE_HEIGHT;
int x = (width - SCOPE_WIDTH) / 2;
int y = (height - SCOPE_HEIGHT) / 2;
int w = SCOPE_WIDTH;
int h = SCOPE_HEIGHT;
renderBackground(backgroundColor, x, y, w, h);
renderGrid(gridColor, x, y, w, h, gridRows, gridCols);
renderLineStrip(inputColor, x, y, w, _scopeInputOffset, _scopeInput);
renderLineStrip(outputLeftColor, x, y, w, _scopeOutputOffset, _scopeOutputLeft);
renderLineStrip(outputRightColor, x, y, w, _scopeOutputOffset, _scopeOutputRight);
QMutexLocker lock(&_guard);
renderLineStrip(inputColor, x, y, _samplesPerScope, _scopeInputOffset, _scopeInput);
renderLineStrip(outputLeftColor, x, y, _samplesPerScope, _scopeOutputOffset, _scopeOutputLeft);
renderLineStrip(outputRightColor, x, y, _samplesPerScope, _scopeOutputOffset, _scopeOutputRight);
}
void Audio::renderBackground(const float* color, int x, int y, int width, int height) {
@ -1170,21 +1223,54 @@ void Audio::renderGrid(const float* color, int x, int y, int width, int height,
glColor4f(1, 1, 1, 1);
}
void Audio::renderLineStrip(const float* color, int x, int y, int n, int offset, const QByteArray& byteArray) {
void Audio::renderLineStrip(const float* color, int x, int y, int n, int offset, const QByteArray* byteArray) {
glColor4fv(color);
glBegin(GL_LINE_STRIP);
int16_t sample;
int16_t* samples = ((int16_t*) byteArray.data()) + offset;
y += SAMPLES_PER_SCOPE_HEIGHT / 2;
for (int i = n - offset; --i >= 0; ) {
sample = *samples++;
int16_t* samples = ((int16_t*) byteArray->data()) + offset;
int numSamplesToAverage = _framesPerScope / DEFAULT_FRAMES_PER_SCOPE;
int count = (n - offset) / numSamplesToAverage;
int remainder = (n - offset) % numSamplesToAverage;
y += SCOPE_HEIGHT / 2;
// Compute and draw the sample averages from the offset position
for (int i = count; --i >= 0; ) {
sample = 0;
for (int j = numSamplesToAverage; --j >= 0; ) {
sample += *samples++;
}
sample /= numSamplesToAverage;
glVertex2i(x++, y - sample);
}
samples = (int16_t*) byteArray.data();
for (int i = offset; --i >= 0; ) {
sample = *samples++;
// Compute and draw the sample average across the wrap boundary
if (remainder != 0) {
sample = 0;
for (int j = remainder; --j >= 0; ) {
sample += *samples++;
}
samples = (int16_t*) byteArray->data();
for (int j = numSamplesToAverage - remainder; --j >= 0; ) {
sample += *samples++;
}
sample /= numSamplesToAverage;
glVertex2i(x++, y - sample);
} else {
samples = (int16_t*) byteArray->data();
}
// Compute and draw the sample average from the beginning to the offset
count = (offset - remainder) / numSamplesToAverage;
for (int i = count; --i >= 0; ) {
sample = 0;
for (int j = numSamplesToAverage; --j >= 0; ) {
sample += *samples++;
}
sample /= numSamplesToAverage;
glVertex2i(x++, y - sample);
}
glEnd();

View file

@ -85,6 +85,9 @@ public slots:
void toggleScope();
void toggleScopePause();
void toggleAudioSpatialProcessing();
void selectAudioScopeFiveFrames();
void selectAudioScopeTwentyFrames();
void selectAudioScopeFiftyFrames();
virtual void handleAudioByteArray(const QByteArray& audioByteArray);
@ -197,28 +200,36 @@ private:
int calculateNumberOfFrameSamples(int numBytes);
float calculateDeviceToNetworkInputRatio(int numBytes);
// Audio scope methods for allocation/deallocation
void allocateScope();
void freeScope();
void reallocateScope(int frames);
// Audio scope methods for data acquisition
void addBufferToScope(
QByteArray& byteArray, unsigned int frameOffset, const int16_t* source, unsigned int sourceChannel, unsigned int sourceNumberOfChannels);
QByteArray* byteArray, unsigned int frameOffset, const int16_t* source, unsigned int sourceChannel, unsigned int sourceNumberOfChannels);
// Audio scope methods for rendering
void renderBackground(const float* color, int x, int y, int width, int height);
void renderGrid(const float* color, int x, int y, int width, int height, int rows, int cols);
void renderLineStrip(const float* color, int x, int y, int n, int offset, const QByteArray& byteArray);
void renderLineStrip(const float* color, int x, int y, int n, int offset, const QByteArray* byteArray);
// Audio scope data
static const unsigned int NETWORK_SAMPLES_PER_FRAME = NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL;
static const unsigned int FRAMES_PER_SCOPE = 5;
static const unsigned int SAMPLES_PER_SCOPE_WIDTH = FRAMES_PER_SCOPE * NETWORK_SAMPLES_PER_FRAME;
static const unsigned int DEFAULT_FRAMES_PER_SCOPE = 5;
static const unsigned int SCOPE_WIDTH = NETWORK_SAMPLES_PER_FRAME * DEFAULT_FRAMES_PER_SCOPE;
static const unsigned int MULTIPLIER_SCOPE_HEIGHT = 20;
static const unsigned int SAMPLES_PER_SCOPE_HEIGHT = 2 * 15 * MULTIPLIER_SCOPE_HEIGHT;
static const unsigned int SCOPE_HEIGHT = 2 * 15 * MULTIPLIER_SCOPE_HEIGHT;
bool _scopeEnabled;
bool _scopeEnabledPause;
int _scopeInputOffset;
int _scopeOutputOffset;
QByteArray _scopeInput;
QByteArray _scopeOutputLeft;
QByteArray _scopeOutputRight;
int _framesPerScope;
int _samplesPerScope;
QMutex _guard;
QByteArray* _scopeInput;
QByteArray* _scopeOutputLeft;
QByteArray* _scopeOutputRight;
};

View file

@ -417,7 +417,8 @@ Menu::Menu() :
false,
appInstance->getAudio(),
SLOT(toggleToneInjection()));
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioScope, Qt::CTRL | Qt::Key_P, false,
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioScope,
Qt::CTRL | Qt::Key_P, false,
appInstance->getAudio(),
SLOT(toggleScope()));
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioScopePause,
@ -426,6 +427,33 @@ Menu::Menu() :
appInstance->getAudio(),
SLOT(toggleScopePause()));
QMenu* audioScopeMenu = audioDebugMenu->addMenu("Audio Scope Options");
addDisabledActionAndSeparator(audioScopeMenu, "Display Frames");
{
QAction *fiveFrames = addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopeFiveFrames,
0,
true,
appInstance->getAudio(),
SLOT(selectAudioScopeFiveFrames()));
QAction *twentyFrames = addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopeTwentyFrames,
0,
false,
appInstance->getAudio(),
SLOT(selectAudioScopeTwentyFrames()));
QAction *fiftyFrames = addCheckableActionToQMenuAndActionHash(audioScopeMenu, MenuOption::AudioScopeFiftyFrames,
0,
false,
appInstance->getAudio(),
SLOT(selectAudioScopeFiftyFrames()));
QActionGroup* audioScopeFramesGroup = new QActionGroup(audioScopeMenu);
audioScopeFramesGroup->addAction(fiveFrames);
audioScopeFramesGroup->addAction(twentyFrames);
audioScopeFramesGroup->addAction(fiftyFrames);
}
QMenu* spatialAudioMenu = audioDebugMenu->addMenu("Spatial Audio");
addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessing,

View file

@ -279,6 +279,10 @@ namespace MenuOption {
const QString AudioNoiseReduction = "Audio Noise Reduction";
const QString AudioScope = "Audio Scope";
const QString AudioScopePause = "Pause Audio Scope";
const QString AudioScopeFrames = "Display Frames";
const QString AudioScopeFiveFrames = "Five";
const QString AudioScopeTwentyFrames = "Twenty";
const QString AudioScopeFiftyFrames = "Fifty";
const QString AudioToneInjection = "Inject Test Tone";
const QString AudioSpatialProcessing = "Audio Spatial Processing";
const QString AudioSpatialProcessingHeadOriented = "Head Oriented";

View file

@ -69,3 +69,12 @@ void FaceModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJ
state.rotation = glm::angleAxis(glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) *
joint.rotation;
}
bool FaceModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const {
if (!isActive()) {
return false;
}
const FBXGeometry& geometry = _geometry->getFBXGeometry();
return getJointPosition(geometry.leftEyeJointIndex, firstEyePosition) &&
getJointPosition(geometry.rightEyeJointIndex, secondEyePosition);
}

View file

@ -29,6 +29,10 @@ public:
virtual void maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state);
virtual void maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state);
/// Retrieve the positions of up to two eye meshes.
/// \return whether or not both eye meshes were found
bool getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const;
private:
Head* _owningHead;

View file

@ -103,7 +103,7 @@ void Hand::collideAgainstOurself() {
getLeftRightPalmIndices(leftPalmIndex, rightPalmIndex);
float scaledPalmRadius = PALM_COLLISION_RADIUS * _owningAvatar->getScale();
const Model& skeletonModel = _owningAvatar->getSkeletonModel();
const SkeletonModel& skeletonModel = _owningAvatar->getSkeletonModel();
for (int i = 0; i < int(getNumPalms()); i++) {
PalmData& palm = getPalms()[i];
if (!palm.isActive()) {

View file

@ -31,7 +31,6 @@ Head::Head(Avatar* owningAvatar) :
_rightEyePosition(0.0f, 0.0f, 0.0f),
_eyePosition(0.0f, 0.0f, 0.0f),
_scale(1.0f),
_gravity(0.0f, -1.0f, 0.0f),
_lastLoudness(0.0f),
_audioAttack(0.0f),
_angularVelocity(0,0,0),

View file

@ -45,7 +45,6 @@ public:
void render(float alpha, Model::RenderMode mode);
void setScale(float scale);
void setPosition(glm::vec3 position) { _position = position; }
void setGravity(glm::vec3 gravity) { _gravity = gravity; }
void setAverageLoudness(float averageLoudness) { _averageLoudness = averageLoudness; }
void setReturnToCenter (bool returnHeadToCenter) { _returnHeadToCenter = returnHeadToCenter; }
void setRenderLookatVectors(bool onOff) { _renderLookatVectors = onOff; }
@ -118,7 +117,6 @@ private:
glm::vec3 _rightEyePosition;
glm::vec3 _eyePosition;
float _scale;
glm::vec3 _gravity;
float _lastLoudness;
float _audioAttack;
glm::vec3 _angularVelocity;

View file

@ -378,7 +378,6 @@ void MyAvatar::setLocalGravity(glm::vec3 gravity) {
void MyAvatar::setGravity(const glm::vec3& gravity) {
_gravity = gravity;
getHead()->setGravity(_gravity);
// use the gravity to determine the new world up direction, if possible
float gravityLength = glm::length(gravity);

View file

@ -198,10 +198,25 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) {
}
void SkeletonModel::updateJointState(int index) {
JointState& state = _jointStates[index];
const FBXGeometry& geometry = _geometry->getFBXGeometry();
const FBXJoint& joint = geometry.joints.at(index);
if (joint.parentIndex != -1) {
const JointState& parentState = _jointStates.at(joint.parentIndex);
if (index == geometry.leanJointIndex) {
maybeUpdateLeanRotation(parentState, joint, state);
} else if (index == geometry.neckJointIndex) {
maybeUpdateNeckRotation(parentState, joint, state);
} else if (index == geometry.leftEyeJointIndex || index == geometry.rightEyeJointIndex) {
maybeUpdateEyeRotation(parentState, joint, state);
}
}
Model::updateJointState(index);
if (index == _geometry->getFBXGeometry().rootJointIndex) {
JointState& state = _jointStates[index];
state.transform[3][0] = 0.0f;
state.transform[3][1] = 0.0f;
state.transform[3][2] = 0.0f;
@ -347,4 +362,72 @@ void SkeletonModel::setHandPosition(int jointIndex, const glm::vec3& position, c
setJointRotation(jointIndex, rotation, true, PALM_PRIORITY);
}
bool SkeletonModel::getLeftHandPosition(glm::vec3& position) const {
return getJointPosition(getLeftHandJointIndex(), position);
}
bool SkeletonModel::getLeftHandRotation(glm::quat& rotation) const {
return getJointRotation(getLeftHandJointIndex(), rotation);
}
bool SkeletonModel::getRightHandPosition(glm::vec3& position) const {
return getJointPosition(getRightHandJointIndex(), position);
}
bool SkeletonModel::getRightHandRotation(glm::quat& rotation) const {
return getJointRotation(getRightHandJointIndex(), rotation);
}
bool SkeletonModel::restoreLeftHandPosition(float percent, float priority) {
return restoreJointPosition(getLeftHandJointIndex(), percent, priority);
}
bool SkeletonModel::getLeftShoulderPosition(glm::vec3& position) const {
return getJointPosition(getLastFreeJointIndex(getLeftHandJointIndex()), position);
}
float SkeletonModel::getLeftArmLength() const {
return getLimbLength(getLeftHandJointIndex());
}
bool SkeletonModel::restoreRightHandPosition(float percent, float priority) {
return restoreJointPosition(getRightHandJointIndex(), percent, priority);
}
bool SkeletonModel::getRightShoulderPosition(glm::vec3& position) const {
return getJointPosition(getLastFreeJointIndex(getRightHandJointIndex()), position);
}
float SkeletonModel::getRightArmLength() const {
return getLimbLength(getRightHandJointIndex());
}
bool SkeletonModel::getHeadPosition(glm::vec3& headPosition) const {
return isActive() && getJointPosition(_geometry->getFBXGeometry().headJointIndex, headPosition);
}
bool SkeletonModel::getNeckPosition(glm::vec3& neckPosition) const {
return isActive() && getJointPosition(_geometry->getFBXGeometry().neckJointIndex, neckPosition);
}
bool SkeletonModel::getNeckParentRotation(glm::quat& neckParentRotation) const {
if (!isActive()) {
return false;
}
const FBXGeometry& geometry = _geometry->getFBXGeometry();
if (geometry.neckJointIndex == -1) {
return false;
}
return getJointRotation(geometry.joints.at(geometry.neckJointIndex).parentIndex, neckParentRotation);
}
bool SkeletonModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const {
if (!isActive()) {
return false;
}
const FBXGeometry& geometry = _geometry->getFBXGeometry();
return getJointPosition(geometry.leftEyeJointIndex, firstEyePosition) &&
getJointPosition(geometry.rightEyeJointIndex, secondEyePosition);
}

View file

@ -34,7 +34,69 @@ public:
void getBodyShapes(QVector<const Shape*>& shapes) const;
void renderIKConstraints();
/// Returns the index of the left hand joint, or -1 if not found.
int getLeftHandJointIndex() const { return isActive() ? _geometry->getFBXGeometry().leftHandJointIndex : -1; }
/// Returns the index of the right hand joint, or -1 if not found.
int getRightHandJointIndex() const { return isActive() ? _geometry->getFBXGeometry().rightHandJointIndex : -1; }
/// Retrieve the position of the left hand
/// \return true whether or not the position was found
bool getLeftHandPosition(glm::vec3& position) const;
/// Retrieve the rotation of the left hand
/// \return true whether or not the rotation was found
bool getLeftHandRotation(glm::quat& rotation) const;
/// Retrieve the position of the right hand
/// \return true whether or not the position was found
bool getRightHandPosition(glm::vec3& position) const;
/// Retrieve the rotation of the right hand
/// \return true whether or not the rotation was found
bool getRightHandRotation(glm::quat& rotation) const;
/// Restores some percentage of the default position of the left hand.
/// \param percent the percentage of the default position to restore
/// \return whether or not the left hand joint was found
bool restoreLeftHandPosition(float percent = 1.0f, float priority = 1.0f);
/// Gets the position of the left shoulder.
/// \return whether or not the left shoulder joint was found
bool getLeftShoulderPosition(glm::vec3& position) const;
/// Returns the extended length from the left hand to its last free ancestor.
float getLeftArmLength() const;
/// Restores some percentage of the default position of the right hand.
/// \param percent the percentage of the default position to restore
/// \return whether or not the right hand joint was found
bool restoreRightHandPosition(float percent = 1.0f, float priority = 1.0f);
/// Gets the position of the right shoulder.
/// \return whether or not the right shoulder joint was found
bool getRightShoulderPosition(glm::vec3& position) const;
/// Returns the extended length from the right hand to its first free ancestor.
float getRightArmLength() const;
/// Returns the position of the head joint.
/// \return whether or not the head was found
bool getHeadPosition(glm::vec3& headPosition) const;
/// Returns the position of the neck joint.
/// \return whether or not the neck was found
bool getNeckPosition(glm::vec3& neckPosition) const;
/// Returns the rotation of the neck joint's parent.
/// \return whether or not the neck was found
bool getNeckParentRotation(glm::quat& neckRotation) const;
/// Retrieve the positions of up to two eye meshes.
/// \return whether or not both eye meshes were found
bool getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const;
protected:
void applyHandPosition(int jointIndex, const glm::vec3& position);
@ -44,9 +106,9 @@ protected:
/// Updates the state of the joint at the specified index.
virtual void updateJointState(int index);
virtual void maybeUpdateLeanRotation(const JointState& parentState, const FBXJoint& joint, JointState& state);
virtual void maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state);
virtual void maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state);
void maybeUpdateLeanRotation(const JointState& parentState, const FBXJoint& joint, JointState& state);
void maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state);
void maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state);
private:

View file

@ -63,7 +63,7 @@ static void setPalm(float deltaTime, int index) {
if (!Application::getInstance()->getJoystickManager()->getJoystickStates().isEmpty()) {
const JoystickState& state = Application::getInstance()->getJoystickManager()->getJoystickStates().at(0);
if (state.axes.size() >= 4 && state.buttons.size() >= 4) {
if (index == SIXENSE_CONTROLLER_ID_LEFT_HAND) {
if (index == LEFT_HAND_INDEX) {
palm->setControllerButtons(state.buttons.at(1) ? BUTTON_FWD : 0);
palm->setTrigger(state.buttons.at(0) ? 1.0f : 0.0f);
palm->setJoystick(state.axes.at(0), -state.axes.at(1));
@ -82,7 +82,7 @@ static void setPalm(float deltaTime, int index) {
Model* skeletonModel = &Application::getInstance()->getAvatar()->getSkeletonModel();
int jointIndex;
glm::quat inverseRotation = glm::inverse(Application::getInstance()->getAvatar()->getOrientation());
if (index == SIXENSE_CONTROLLER_ID_LEFT_HAND) {
if (index == LEFT_HAND_INDEX) {
jointIndex = skeletonModel->getLeftHandJointIndex();
skeletonModel->getJointRotation(jointIndex, rotation, true);
rotation = inverseRotation * rotation * glm::quat(glm::vec3(0.0f, PI_OVER_TWO, 0.0f));
@ -180,8 +180,8 @@ void PrioVR::update(float deltaTime) {
}
// convert the joysticks into palm data
setPalm(deltaTime, SIXENSE_CONTROLLER_ID_LEFT_HAND);
setPalm(deltaTime, SIXENSE_CONTROLLER_ID_RIGHT_HAND);
setPalm(deltaTime, LEFT_HAND_INDEX);
setPalm(deltaTime, RIGHT_HAND_INDEX);
#endif
}

View file

@ -613,78 +613,6 @@ int Model::getLastFreeJointIndex(int jointIndex) const {
return (isActive() && jointIndex != -1) ? _geometry->getFBXGeometry().joints.at(jointIndex).freeLineage.last() : -1;
}
bool Model::getHeadPosition(glm::vec3& headPosition) const {
return isActive() && getJointPosition(_geometry->getFBXGeometry().headJointIndex, headPosition);
}
bool Model::getNeckPosition(glm::vec3& neckPosition) const {
return isActive() && getJointPosition(_geometry->getFBXGeometry().neckJointIndex, neckPosition);
}
bool Model::getNeckRotation(glm::quat& neckRotation) const {
return isActive() && getJointRotation(_geometry->getFBXGeometry().neckJointIndex, neckRotation);
}
bool Model::getNeckParentRotation(glm::quat& neckParentRotation) const {
if (!isActive()) {
return false;
}
const FBXGeometry& geometry = _geometry->getFBXGeometry();
if (geometry.neckJointIndex == -1) {
return false;
}
return getJointRotation(geometry.joints.at(geometry.neckJointIndex).parentIndex, neckParentRotation);
}
bool Model::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const {
if (!isActive()) {
return false;
}
const FBXGeometry& geometry = _geometry->getFBXGeometry();
return getJointPosition(geometry.leftEyeJointIndex, firstEyePosition) &&
getJointPosition(geometry.rightEyeJointIndex, secondEyePosition);
}
bool Model::getLeftHandPosition(glm::vec3& position) const {
return getJointPosition(getLeftHandJointIndex(), position);
}
bool Model::getLeftHandRotation(glm::quat& rotation) const {
return getJointRotation(getLeftHandJointIndex(), rotation);
}
bool Model::getRightHandPosition(glm::vec3& position) const {
return getJointPosition(getRightHandJointIndex(), position);
}
bool Model::getRightHandRotation(glm::quat& rotation) const {
return getJointRotation(getRightHandJointIndex(), rotation);
}
bool Model::restoreLeftHandPosition(float percent, float priority) {
return restoreJointPosition(getLeftHandJointIndex(), percent, priority);
}
bool Model::getLeftShoulderPosition(glm::vec3& position) const {
return getJointPosition(getLastFreeJointIndex(getLeftHandJointIndex()), position);
}
float Model::getLeftArmLength() const {
return getLimbLength(getLeftHandJointIndex());
}
bool Model::restoreRightHandPosition(float percent, float priority) {
return restoreJointPosition(getRightHandJointIndex(), percent, priority);
}
bool Model::getRightShoulderPosition(glm::vec3& position) const {
return getJointPosition(getLastFreeJointIndex(getRightHandJointIndex()), position);
}
float Model::getRightArmLength() const {
return getLimbLength(getRightHandJointIndex());
}
void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bool delayLoad) {
// don't recreate the geometry if it's the same URL
if (_url == url) {
@ -1210,15 +1138,6 @@ void Model::updateJointState(int index) {
state.combinedRotation = _rotation * combinedRotation;
} else {
const JointState& parentState = _jointStates.at(joint.parentIndex);
if (index == geometry.leanJointIndex) {
maybeUpdateLeanRotation(parentState, joint, state);
} else if (index == geometry.neckJointIndex) {
maybeUpdateNeckRotation(parentState, joint, state);
} else if (index == geometry.leftEyeJointIndex || index == geometry.rightEyeJointIndex) {
maybeUpdateEyeRotation(parentState, joint, state);
}
glm::quat combinedRotation = joint.preRotation * state.rotation * joint.postRotation;
state.transform = parentState.transform * glm::translate(state.translation) * joint.preTransform *
glm::mat4_cast(combinedRotation) * joint.postTransform;
@ -1226,18 +1145,6 @@ void Model::updateJointState(int index) {
}
}
void Model::maybeUpdateLeanRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
// nothing by default
}
void Model::maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
// nothing by default
}
void Model::maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
// nothing by default
}
bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const glm::quat& rotation, bool useRotation,
int lastFreeIndex, bool allIntermediatesFree, const glm::vec3& alignment, float priority) {
if (jointIndex == -1 || _jointStates.isEmpty()) {

View file

@ -115,78 +115,12 @@ public:
/// Sets the joint state at the specified index.
void setJointState(int index, bool valid, const glm::quat& rotation = glm::quat(), float priority = 1.0f);
/// Returns the index of the left hand joint, or -1 if not found.
int getLeftHandJointIndex() const { return isActive() ? _geometry->getFBXGeometry().leftHandJointIndex : -1; }
/// Returns the index of the right hand joint, or -1 if not found.
int getRightHandJointIndex() const { return isActive() ? _geometry->getFBXGeometry().rightHandJointIndex : -1; }
/// Returns the index of the parent of the indexed joint, or -1 if not found.
int getParentJointIndex(int jointIndex) const;
/// Returns the index of the last free ancestor of the indexed joint, or -1 if not found.
int getLastFreeJointIndex(int jointIndex) const;
/// Returns the position of the head joint.
/// \return whether or not the head was found
bool getHeadPosition(glm::vec3& headPosition) const;
/// Returns the position of the neck joint.
/// \return whether or not the neck was found
bool getNeckPosition(glm::vec3& neckPosition) const;
/// Returns the rotation of the neck joint.
/// \return whether or not the neck was found
bool getNeckRotation(glm::quat& neckRotation) const;
/// Returns the rotation of the neck joint's parent.
/// \return whether or not the neck was found
bool getNeckParentRotation(glm::quat& neckRotation) const;
/// Retrieve the positions of up to two eye meshes.
/// \return whether or not both eye meshes were found
bool getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const;
/// Retrieve the position of the left hand
/// \return true whether or not the position was found
bool getLeftHandPosition(glm::vec3& position) const;
/// Retrieve the rotation of the left hand
/// \return true whether or not the rotation was found
bool getLeftHandRotation(glm::quat& rotation) const;
/// Retrieve the position of the right hand
/// \return true whether or not the position was found
bool getRightHandPosition(glm::vec3& position) const;
/// Retrieve the rotation of the right hand
/// \return true whether or not the rotation was found
bool getRightHandRotation(glm::quat& rotation) const;
/// Restores some percentage of the default position of the left hand.
/// \param percent the percentage of the default position to restore
/// \return whether or not the left hand joint was found
bool restoreLeftHandPosition(float percent = 1.0f, float priority = 1.0f);
/// Gets the position of the left shoulder.
/// \return whether or not the left shoulder joint was found
bool getLeftShoulderPosition(glm::vec3& position) const;
/// Returns the extended length from the left hand to its last free ancestor.
float getLeftArmLength() const;
/// Restores some percentage of the default position of the right hand.
/// \param percent the percentage of the default position to restore
/// \return whether or not the right hand joint was found
bool restoreRightHandPosition(float percent = 1.0f, float priority = 1.0f);
/// Gets the position of the right shoulder.
/// \return whether or not the right shoulder joint was found
bool getRightShoulderPosition(glm::vec3& position) const;
/// Returns the extended length from the right hand to its first free ancestor.
float getRightArmLength() const;
bool getJointPosition(int jointIndex, glm::vec3& position) const;
bool getJointRotation(int jointIndex, glm::quat& rotation, bool fromBind = false) const;
@ -284,10 +218,6 @@ protected:
/// Updates the state of the joint at the specified index.
virtual void updateJointState(int index);
virtual void maybeUpdateLeanRotation(const JointState& parentState, const FBXJoint& joint, JointState& state);
virtual void maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state);
virtual void maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state);
bool setJointPosition(int jointIndex, const glm::vec3& translation, const glm::quat& rotation = glm::quat(),
bool useRotation = false, int lastFreeIndex = -1, bool allIntermediatesFree = false,
const glm::vec3& alignment = glm::vec3(0.0f, -1.0f, 0.0f), float priority = 1.0f);

View file

@ -237,27 +237,30 @@ void Sound::interpretAsWav(const QByteArray& inputAudioByteArray, QByteArray& ou
return;
}
// Skip any extra data in the WAVE chunk
waveStream.skipRawData(fileHeader.wave.descriptor.size - (sizeof(WAVEHeader) - sizeof(chunk)));
// Read off remaining header information
DATAHeader dataHeader;
if (waveStream.readRawData(reinterpret_cast<char *>(&dataHeader), sizeof(DATAHeader)) == sizeof(DATAHeader)) {
if (strncmp(dataHeader.descriptor.id, "data", 4) != 0) {
qDebug() << "Invalid wav audio data header.";
while (true) {
// Read chunks until the "data" chunk is found
if (waveStream.readRawData(reinterpret_cast<char *>(&dataHeader), sizeof(DATAHeader)) == sizeof(DATAHeader)) {
if (strncmp(dataHeader.descriptor.id, "data", 4) == 0) {
break;
}
waveStream.skipRawData(dataHeader.descriptor.size);
} else {
qDebug() << "Could not read wav audio data header.";
return;
}
} else {
qDebug() << "Could not read wav audio data header.";
return;
}
if (qFromLittleEndian<quint32>(fileHeader.riff.descriptor.size) != qFromLittleEndian<quint32>(dataHeader.descriptor.size) + 36) {
qDebug() << "Did not read audio file chank headers correctly.";
return;
}
// Now pull out the data
quint32 outputAudioByteArraySize = qFromLittleEndian<quint32>(dataHeader.descriptor.size);
outputAudioByteArray.resize(outputAudioByteArraySize);
waveStream.readRawData(outputAudioByteArray.data(), outputAudioByteArraySize);
if (waveStream.readRawData(outputAudioByteArray.data(), outputAudioByteArraySize) != outputAudioByteArraySize) {
qDebug() << "Error reading WAV file";
}
} else {
qDebug() << "Could not read wav audio file header.";

View file

@ -53,10 +53,10 @@ void HandData::getLeftRightPalmIndices(int& leftPalmIndex, int& rightPalmIndex)
for (size_t i = 0; i < _palms.size(); i++) {
const PalmData& palm = _palms[i];
if (palm.isActive()) {
if (palm.getSixenseID() == SIXENSE_CONTROLLER_ID_LEFT_HAND) {
if (palm.getSixenseID() == LEFT_HAND_INDEX) {
leftPalmIndex = i;
}
if (palm.getSixenseID() == SIXENSE_CONTROLLER_ID_RIGHT_HAND) {
if (palm.getSixenseID() == RIGHT_HAND_INDEX) {
rightPalmIndex = i;
}
}

View file

@ -23,16 +23,12 @@
class AvatarData;
class PalmData;
const int LEFT_HAND_INDEX = 0;
const int RIGHT_HAND_INDEX = 1;
const int NUM_HANDS = 2;
const int NUM_FINGERS_PER_HAND = 5;
const int NUM_FINGERS = NUM_HANDS * NUM_FINGERS_PER_HAND;
const int LEAPID_INVALID = -1;
const int SIXENSEID_INVALID = -1;
const int SIXENSE_CONTROLLER_ID_LEFT_HAND = 0;
const int SIXENSE_CONTROLLER_ID_RIGHT_HAND = 1;
class HandData {
public:
HandData(AvatarData* owningAvatar);