Merge branch 'master' of github.com:worklist/hifi into synthesis

This commit is contained in:
Stephen Birarda 2013-06-06 11:01:16 -07:00
commit b60230b29c
16 changed files with 104 additions and 87 deletions

View file

@ -6,9 +6,13 @@
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
//
#include <PacketHeaders.h>
#include "AvatarAudioRingBuffer.h"
AvatarAudioRingBuffer::AvatarAudioRingBuffer() : _freeVerbs() {
AvatarAudioRingBuffer::AvatarAudioRingBuffer() :
_freeVerbs(),
_shouldLoopbackForAgent(false) {
}
@ -17,4 +21,9 @@ AvatarAudioRingBuffer::~AvatarAudioRingBuffer() {
for (FreeVerbAgentMap::iterator verbIterator = _freeVerbs.begin(); verbIterator != _freeVerbs.end(); verbIterator++) {
delete verbIterator->second;
}
}
int AvatarAudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) {
_shouldLoopbackForAgent = (sourceBuffer[0] == PACKET_HEADER_MICROPHONE_AUDIO_WITH_ECHO);
return PositionalAudioRingBuffer::parseData(sourceBuffer, numBytes);
}

View file

@ -21,13 +21,17 @@ public:
AvatarAudioRingBuffer();
~AvatarAudioRingBuffer();
int parseData(unsigned char* sourceBuffer, int numBytes);
FreeVerbAgentMap& getFreeVerbs() { return _freeVerbs; }
bool shouldLoopbackForAgent() const { return _shouldLoopbackForAgent; }
private:
// disallow copying of AvatarAudioRingBuffer objects
AvatarAudioRingBuffer(const AvatarAudioRingBuffer&);
AvatarAudioRingBuffer& operator= (const AvatarAudioRingBuffer&);
FreeVerbAgentMap _freeVerbs;
bool _shouldLoopbackForAgent;
};
#endif /* defined(__hifi__AvatarAudioRingBuffer__) */

View file

@ -6,6 +6,8 @@
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
//
#include <cstring>
#include <PacketHeaders.h>
#include "InjectedAudioRingBuffer.h"

View file

@ -6,6 +6,8 @@
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
//
#include <cstring>
#include <PacketHeaders.h>
#include "PositionalAudioRingBuffer.h"
@ -14,7 +16,6 @@ PositionalAudioRingBuffer::PositionalAudioRingBuffer() :
AudioRingBuffer(false),
_position(0.0f, 0.0f, 0.0f),
_orientation(0.0f, 0.0f, 0.0f, 0.0f),
_shouldLoopbackForAgent(false),
_willBeAddedToMix(false)
{

View file

@ -28,8 +28,6 @@ public:
const glm::vec3& getPosition() const { return _position; }
const glm::quat& getOrientation() const { return _orientation; }
bool shouldLoopbackForAgent() const { return _shouldLoopbackForAgent; }
protected:
// disallow copying of PositionalAudioRingBuffer objects
PositionalAudioRingBuffer(const PositionalAudioRingBuffer&);
@ -37,7 +35,6 @@ protected:
glm::vec3 _position;
glm::quat _orientation;
bool _shouldLoopbackForAgent;
bool _willBeAddedToMix;
};

View file

@ -324,7 +324,8 @@ int main(int argc, const char* argv[]) {
// pull any new audio data from agents off of the network stack
while (agentList->getAgentSocket()->receive(agentAddress, packetData, &receivedBytes)) {
if (packetData[0] == PACKET_HEADER_MICROPHONE_AUDIO) {
if (packetData[0] == PACKET_HEADER_MICROPHONE_AUDIO_NO_ECHO ||
packetData[0] == PACKET_HEADER_MICROPHONE_AUDIO_WITH_ECHO) {
Agent* avatarAgent = agentList->addOrUpdateAgent(agentAddress,
agentAddress,
AGENT_TYPE_AVATAR,

View file

@ -19,6 +19,7 @@
#endif
#include <glm/gtx/quaternion.hpp>
#include <glm/gtx/vector_angle.hpp>
#include <QActionGroup>
#include <QBoxLayout>
@ -303,11 +304,12 @@ void Application::paintGL() {
} else if (OculusManager::isConnected()) {
_myCamera.setUpShift (0.0f);
_myCamera.setDistance (0.0f);
_myCamera.setTightness (100.0f);
_myCamera.setTightness (0.0f); // Camera is directly connected to head without smoothing
_myCamera.setTargetPosition(_myAvatar.getHeadJointPosition());
_myCamera.setTargetRotation(_myAvatar.getHead().getOrientation());
} else if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
_myCamera.setTightness(0.0f); // In first person, camera follows head exactly without delay
_myCamera.setTargetPosition(_myAvatar.getBallPosition(AVATAR_JOINT_HEAD_BASE));
_myCamera.setTargetRotation(_myAvatar.getHead().getWorldAlignedOrientation());
@ -316,19 +318,9 @@ void Application::paintGL() {
_myCamera.setTargetRotation(_myAvatar.getHead().getWorldAlignedOrientation());
}
// important...
// Update camera position
_myCamera.update( 1.f/_fps );
// Render anything (like HUD items) that we want to be in 3D but not in worldspace
/*
const float HUD_Z_OFFSET = -5.f;
glPushMatrix();
glm::vec3 test(0.5, 0.5, 0.5);
glTranslatef(1, 1, HUD_Z_OFFSET);
drawVector(&test);
glPopMatrix();
*/
// Note: whichCamera is used to pick between the normal camera myCamera for our
// main camera, vs, an alternate camera. The alternate camera we support right now
@ -1567,6 +1559,7 @@ void Application::init() {
void Application::updateAvatar(float deltaTime) {
if (_serialHeadSensor.active) {
// Update avatar head translation
@ -1600,7 +1593,6 @@ void Application::updateAvatar(float deltaTime) {
}
if (OculusManager::isConnected()) {
float yaw, pitch, roll;
OculusManager::getEulerAngles(yaw, pitch, roll);
@ -1609,7 +1601,7 @@ void Application::updateAvatar(float deltaTime) {
_myAvatar.getHead().setPitch(pitch);
_myAvatar.getHead().setRoll(roll);
}
// Get audio loudness data from audio input device
#ifndef _WIN32
_myAvatar.getHead().setAudioLoudness(_audio.getLastInputLoudness());
@ -1971,7 +1963,7 @@ void Application::displaySide(Camera& whichCamera) {
}
}
agentList->unlock();
// Render my own Avatar
_myAvatar.render(_lookingInMirror->isChecked(), _renderAvatarBalls->isChecked());
_myAvatar.setDisplayingLookatVectors(_renderLookatOn->isChecked());

View file

@ -135,7 +135,9 @@ int audioCallback (const void* inputBuffer,
// + 12 for 3 floats for position + float for bearing + 1 attenuation byte
unsigned char dataPacket[BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes];
dataPacket[0] = PACKET_HEADER_MICROPHONE_AUDIO;
dataPacket[0] = (Application::getInstance()->shouldEchoAudio())
? PACKET_HEADER_MICROPHONE_AUDIO_WITH_ECHO
: PACKET_HEADER_MICROPHONE_AUDIO_NO_ECHO;
unsigned char *currentPacketPtr = dataPacket + 1;
// memcpy the three float positions

View file

@ -7,6 +7,7 @@
#include <glm/glm.hpp>
#include <glm/gtx/quaternion.hpp>
#include <glm/gtx/vector_angle.hpp>
#include <vector>
#include <lodepng.h>
#include <SharedUtil.h>
@ -87,9 +88,9 @@ _worldUpDirection(DEFAULT_UP_DIRECTION),
_mouseRayOrigin(0.0f, 0.0f, 0.0f),
_mouseRayDirection(0.0f, 0.0f, 0.0f),
_interactingOther(NULL),
_cumulativeMouseYaw(0.0f),
_isMouseTurningRight(false),
_voxels(this)
{
// give the pointer to our head to inherited _headData variable from AvatarData
@ -279,16 +280,12 @@ void Avatar::updateHeadFromGyros(float deltaTime, SerialInterface* serialInterfa
const float AMPLIFY_PITCH = 2.f;
const float AMPLIFY_YAW = 2.f;
const float AMPLIFY_ROLL = 2.f;
float measuredPitchRate = serialInterface->getLastPitchRate();
float measuredYawRate = serialInterface->getLastYawRate();
float measuredRollRate = serialInterface->getLastRollRate();
// Update avatar head position based on measured gyro rates
_head.addPitch(measuredPitchRate * AMPLIFY_PITCH * deltaTime);
_head.addYaw(measuredYawRate * AMPLIFY_YAW * deltaTime);
_head.addRoll(measuredRollRate * AMPLIFY_ROLL * deltaTime);
glm::vec3 estimatedRotation = serialInterface->getEstimatedRotation();
_head.setPitch(estimatedRotation.x * AMPLIFY_PITCH);
_head.setYaw(estimatedRotation.y * AMPLIFY_YAW);
_head.setRoll(estimatedRotation.z * AMPLIFY_ROLL);
// Update head lean distance based on accelerometer data
glm::vec3 headRotationRates(_head.getPitch(), _head.getYaw(), _head.getRoll());
@ -321,11 +318,10 @@ glm::quat Avatar::getWorldAlignedOrientation () const {
}
void Avatar::updateFromMouse(int mouseX, int mouseY, int screenWidth, int screenHeight) {
// Update yaw based on mouse behavior
// Update head yaw and pitch based on mouse input
const float MOUSE_MOVE_RADIUS = 0.15f;
const float MOUSE_ROTATE_SPEED = 3.0f;
const float MOUSE_ROTATE_SPEED = 4.0f;
const float MOUSE_PITCH_SPEED = 1.5f;
const float MAX_YAW_TO_ADD = 180.f;
const int TITLE_BAR_HEIGHT = 46;
float mouseLocationX = (float)mouseX / (float)screenWidth - 0.5f;
float mouseLocationY = (float)mouseY / (float)screenHeight - 0.5f;
@ -334,30 +330,18 @@ void Avatar::updateFromMouse(int mouseX, int mouseY, int screenWidth, int scree
//
// Mouse must be inside screen (not at edge) and not on title bar for movement to happen
//
if (fabs(mouseLocationX) > MOUSE_MOVE_RADIUS) {
// Add Yaw
float mouseYawAdd = (fabs(mouseLocationX) - MOUSE_MOVE_RADIUS) / (0.5f - MOUSE_MOVE_RADIUS) * MOUSE_ROTATE_SPEED;
bool rightTurning = (mouseLocationX > 0.f);
if (_isMouseTurningRight == rightTurning) {
_cumulativeMouseYaw += mouseYawAdd;
} else {
_cumulativeMouseYaw = 0;
_isMouseTurningRight = rightTurning;
}
if (_cumulativeMouseYaw < MAX_YAW_TO_ADD) {
setBodyYaw(getBodyYaw() - (rightTurning ? mouseYawAdd : -mouseYawAdd));
}
} else {
_cumulativeMouseYaw = 0;
}
if (fabs(mouseLocationY) > MOUSE_MOVE_RADIUS) {
float mousePitchAdd = (fabs(mouseLocationY) - MOUSE_MOVE_RADIUS) / (0.5f - MOUSE_MOVE_RADIUS) * MOUSE_PITCH_SPEED;
bool downPitching = (mouseLocationY > 0.f);
_head.setPitch(_head.getPitch() + (downPitching ? -mousePitchAdd : mousePitchAdd));
if (mouseLocationX > MOUSE_MOVE_RADIUS) {
_head.addYaw(-(mouseLocationX - MOUSE_MOVE_RADIUS) / (0.5f - MOUSE_MOVE_RADIUS) * MOUSE_ROTATE_SPEED);
} else if (mouseLocationX < -MOUSE_MOVE_RADIUS) {
_head.addYaw(-(mouseLocationX + MOUSE_MOVE_RADIUS) / (0.5f - MOUSE_MOVE_RADIUS) * MOUSE_ROTATE_SPEED);
}
if (mouseLocationY > MOUSE_MOVE_RADIUS) {
_head.addPitch(-(mouseLocationY - MOUSE_MOVE_RADIUS) / (0.5f - MOUSE_MOVE_RADIUS) * MOUSE_PITCH_SPEED);
} else if (mouseLocationY < -MOUSE_MOVE_RADIUS) {
_head.addPitch(-(mouseLocationY + MOUSE_MOVE_RADIUS) / (0.5f - MOUSE_MOVE_RADIUS) * MOUSE_PITCH_SPEED);
}
}
return;
}
@ -539,19 +523,21 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
}
// Compute instantaneous acceleration
float acceleration = glm::distance(getVelocity(), oldVelocity) / deltaTime;
float forwardAcceleration = glm::length(glm::dot(getBodyFrontDirection(), getVelocity() - oldVelocity)) / deltaTime;
const float ACCELERATION_PITCH_DECAY = 0.4f;
const float ACCELERATION_YAW_DECAY = 0.4f;
const float ACCELERATION_PULL_THRESHOLD = 0.2f;
const float OCULUS_ACCELERATION_PULL_THRESHOLD = 1.0f;
const int OCULUS_YAW_OFFSET_THRESHOLD = 10;
// Decay HeadPitch as a function of acceleration, so that you look straight ahead when
// you start moving, but don't do this with an HMD like the Oculus.
if (!OculusManager::isConnected()) {
_head.setPitch(_head.getPitch() * (1.f - acceleration * ACCELERATION_PITCH_DECAY * deltaTime));
_head.setYaw(_head.getYaw() * (1.f - acceleration * ACCELERATION_YAW_DECAY * deltaTime));
} else if (fabsf(acceleration) > OCULUS_ACCELERATION_PULL_THRESHOLD
if (forwardAcceleration > ACCELERATION_PULL_THRESHOLD) {
_head.setPitch(_head.getPitch() * (1.f - forwardAcceleration * ACCELERATION_PITCH_DECAY * deltaTime));
_head.setYaw(_head.getYaw() * (1.f - forwardAcceleration * ACCELERATION_YAW_DECAY * deltaTime));
}
} else if (fabsf(forwardAcceleration) > OCULUS_ACCELERATION_PULL_THRESHOLD
&& fabs(_head.getYaw()) > OCULUS_YAW_OFFSET_THRESHOLD) {
// if we're wearing the oculus
// and this acceleration is above the pull threshold
@ -1304,4 +1290,4 @@ void Avatar::renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2,
}
glEnd();
}
}

View file

@ -194,7 +194,6 @@ private:
glm::vec3 _mouseRayOrigin;
glm::vec3 _mouseRayDirection;
Avatar* _interactingOther;
float _cumulativeMouseYaw;
bool _isMouseTurningRight;
AvatarVoxelSystem _voxels;

View file

@ -7,9 +7,7 @@
#include <glm/gtx/quaternion.hpp>
#include <SharedUtil.h>
#include <VoxelConstants.h>
#include <OculusManager.h>
#include "Log.h"
#include "Camera.h"
#include "Util.h"
@ -88,22 +86,19 @@ void Camera::updateFollowMode(float deltaTime) {
t = 1.0;
}
// update rotation (before position!)
if (_needsToInitialize || OculusManager::isConnected()) {
// Update position and rotation, setting directly if tightness is 0.0
if (_needsToInitialize || (_tightness == 0.0f)) {
_rotation = _targetRotation;
_idealPosition = _targetPosition + _rotation * glm::vec3(0.0f, _upShift, _distance);
_position = _idealPosition;
_needsToInitialize = false;
} else {
// pull rotation towards ideal
_rotation = safeMix(_rotation, _targetRotation, t);
}
_idealPosition = _targetPosition + _rotation * glm::vec3(0.0f, _upShift, _distance);
if (_needsToInitialize) {
_position = _idealPosition;
_needsToInitialize = false;
} else {
// force position towards ideal position
_position += (_idealPosition - _position) * t;
_idealPosition = _targetPosition + _rotation * glm::vec3(0.0f, _upShift, _distance);
_position += (_idealPosition - _position) * t;
}
}

View file

@ -6,6 +6,8 @@
//
#include "SerialInterface.h"
#include <glm/gtx/vector_angle.hpp>
#include <math.h>
#ifdef __APPLE__
#include <regex.h>
@ -15,6 +17,7 @@
const short NO_READ_MAXIMUM_MSECS = 3000;
const int GRAVITY_SAMPLES = 60; // Use the first few samples to baseline values
const int SENSOR_FUSION_SAMPLES = 200;
const int LONG_TERM_RATE_SAMPLES = 1000;
const bool USING_INVENSENSE_MPU9150 = 1;
@ -227,6 +230,7 @@ void SerialInterface::readData(float deltaTime) {
// Update raw rotation estimates
_estimatedRotation += deltaTime * (_lastRotationRates - _averageRotationRates);
// Update estimated position and velocity
float const DECAY_VELOCITY = 0.95f;
@ -235,10 +239,7 @@ void SerialInterface::readData(float deltaTime) {
_estimatedPosition += deltaTime * _estimatedVelocity;
_estimatedVelocity *= DECAY_VELOCITY;
_estimatedPosition *= DECAY_POSITION;
//glm::vec3 baseline = glm::normalize(_gravity);
//glm::vec3 current = glm::normalize(_lastAcceleration);
// Accumulate a set of initial baseline readings for setting gravity
if (totalSamples == 0) {
_averageRotationRates = _lastRotationRates;
@ -255,8 +256,31 @@ void SerialInterface::readData(float deltaTime) {
if (totalSamples < GRAVITY_SAMPLES) {
_gravity = (1.f - 1.f/(float)GRAVITY_SAMPLES) * _gravity +
1.f/(float)GRAVITY_SAMPLES * _lastAcceleration;
} else {
// Use gravity reading to do sensor fusion on the pitch and roll estimation
float truePitchAngle = glm::angle(glm::normalize(glm::vec3(0, _gravity.y, _gravity.z)),
glm::normalize(glm::vec3(0, _lastAcceleration.y, _lastAcceleration.z)))
* ((_lastAcceleration.z > _gravity.z) ? -1.0 : 1.0);
float trueRollAngle = glm::angle(glm::normalize(glm::vec3(_gravity.x, _gravity.y, 0)),
glm::normalize(glm::vec3(_lastAcceleration.x, _lastAcceleration.y, 0)))
* ((_lastAcceleration.x > _gravity.x) ? -1.0 : 1.0);
// PER: BUG: This is bizarre, because glm::angle() SOMETIMES returns NaN for what seem to
// be perfectly valid inputs. So I added these NaN tests, gotta fix.
if (!glm::isnan(truePitchAngle) && !glm::isnan(trueRollAngle)) {
_estimatedRotation.x = (1.f - 1.f/(float)SENSOR_FUSION_SAMPLES) * _estimatedRotation.x
+ 1.f/(float)SENSOR_FUSION_SAMPLES * truePitchAngle;
_estimatedRotation.z = (1.f - 1.f/(float)SENSOR_FUSION_SAMPLES) * _estimatedRotation.z
+ 1.f/(float)SENSOR_FUSION_SAMPLES * trueRollAngle;
// Without a compass heading, always decay estimated Yaw slightly
const float YAW_DECAY = 0.995;
_estimatedRotation.y *= YAW_DECAY;
}
}
}
totalSamples++;
}

View file

@ -57,7 +57,9 @@ void eulerToOrthonormals(glm::vec3 * angles, glm::vec3 * front, glm::vec3 * righ
front->x = frontNew.x; front->y = frontNew.y; front->z = frontNew.z;
}
void printVector(glm::vec3 vec) {
printf("%4.2f, %4.2f, %4.2f\n", vec.x, vec.y, vec.z);
}
// Return the azimuth angle in degrees between two points.
float azimuth_to(glm::vec3 head_pos, glm::vec3 source_pos) {

View file

@ -43,6 +43,8 @@ void noiseTest(int w, int h);
void drawVector(glm::vec3* vector);
void printVector(glm::vec3 vec);
float angleBetween(const glm::vec3& v1, const glm::vec3& v2);
glm::quat rotationBetween(const glm::vec3& v1, const glm::vec3& v2);

View file

@ -119,7 +119,7 @@ void Agent::recordBytesReceived(int bytesReceived) {
}
float Agent::getAveragePacketsPerSecond() {
if (_bytesReceivedMovingAverage != NULL) {
if (_bytesReceivedMovingAverage) {
return (1 / _bytesReceivedMovingAverage->getEventDeltaAverage());
} else {
return 0;
@ -127,7 +127,7 @@ float Agent::getAveragePacketsPerSecond() {
}
float Agent::getAverageKilobitsPerSecond() {
if (_bytesReceivedMovingAverage != NULL) {
if (_bytesReceivedMovingAverage) {
return (_bytesReceivedMovingAverage->getAverageSampleValuePerSecond() * (8.0f / 1000));
} else {
return 0;

View file

@ -3,7 +3,7 @@
// hifi
//
// Created by Stephen Birarda on 4/8/13.
//
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
//
// The packet headers below refer to the first byte of a received UDP packet transmitted between
// any two Hifi components. For example, a packet whose first byte is 'P' is always a ping packet.
@ -20,7 +20,8 @@ const PACKET_HEADER PACKET_HEADER_HEAD_DATA = 'H';
const PACKET_HEADER PACKET_HEADER_Z_COMMAND = 'Z';
const PACKET_HEADER PACKET_HEADER_INJECT_AUDIO = 'I';
const PACKET_HEADER PACKET_HEADER_MIXED_AUDIO = 'A';
const PACKET_HEADER PACKET_HEADER_MICROPHONE_AUDIO = 'M';
const PACKET_HEADER PACKET_HEADER_MICROPHONE_AUDIO_NO_ECHO = 'M';
const PACKET_HEADER PACKET_HEADER_MICROPHONE_AUDIO_WITH_ECHO = 'm';
const PACKET_HEADER PACKET_HEADER_SET_VOXEL = 'S';
const PACKET_HEADER PACKET_HEADER_SET_VOXEL_DESTRUCTIVE = 'O';
const PACKET_HEADER PACKET_HEADER_ERASE_VOXEL = 'E';