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

This commit is contained in:
tosh 2013-04-24 13:32:30 +02:00
commit 225188a6f9
17 changed files with 633 additions and 406 deletions

View file

@ -133,7 +133,7 @@ int main(int argc, const char * argv[])
if (DEBUG_TO_SELF ||
!agent->matches((sockaddr *)&agentPublicAddress, (sockaddr *)&agentLocalAddress, agentType)) {
if (memchr(SOLO_AGENT_TYPES_STRING, agent->getType(), 1) == NULL) {
if (memchr(SOLO_AGENT_TYPES, agent->getType(), sizeof(SOLO_AGENT_TYPES)) == NULL) {
// this is an agent of which there can be multiple, just add them to the packet
// don't send avatar agents to other avatars, that will come from avatar mixer
if (agentType != AGENT_TYPE_AVATAR || agent->getType() != AGENT_TYPE_AVATAR) {

View file

@ -13,20 +13,31 @@
#include <PacketHeaders.h>
#include <AgentList.h>
#include <AvatarData.h>
#include <AudioInjector.h>
const int EVE_AGENT_LIST_PORT = 55441;
const float DATA_SEND_INTERVAL_MSECS = 10;
const int EVE_AGENT_LISTEN_PORT = 55441;
const float RANDOM_POSITION_MAX_DIMENSION = 5.0f;
const float DATA_SEND_INTERVAL_MSECS = 15;
const float MIN_AUDIO_SEND_INTERVAL_SECS = 10;
const int MIN_ITERATIONS_BETWEEN_AUDIO_SENDS = (MIN_AUDIO_SEND_INTERVAL_SECS * 1000) / DATA_SEND_INTERVAL_MSECS;
const int MAX_AUDIO_SEND_INTERVAL_SECS = 15;
const float MAX_ITERATIONS_BETWEEN_AUDIO_SENDS = (MAX_AUDIO_SEND_INTERVAL_SECS * 1000) / DATA_SEND_INTERVAL_MSECS;
bool stopReceiveAgentDataThread;
bool injectAudioThreadRunning = false;
void *receiveAgentData(void *args)
{
int TEMP_AUDIO_LISTEN_PORT = 55439;
// UDPSocket audioSocket(TEMP_AUDIO_LISTEN_PORT);
void *receiveAgentData(void *args) {
sockaddr senderAddress;
ssize_t bytesReceived;
unsigned char incomingPacket[MAX_PACKET_SIZE];
AgentList *agentList = AgentList::getInstance();
Agent *avatarMixer = NULL;
AgentList* agentList = AgentList::getInstance();
Agent* avatarMixer = NULL;
while (!::stopReceiveAgentDataThread) {
if (agentList->getAgentSocket().receive(&senderAddress, incomingPacket, &bytesReceived)) {
@ -54,9 +65,35 @@ void *receiveAgentData(void *args)
return NULL;
}
int main(int argc, char* argv[]) {
void *injectAudio(void *args) {
::injectAudioThreadRunning = true;
AudioInjector* eveAudioInjector = (AudioInjector *)args;
// look for an audio mixer in our agent list
Agent* audioMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AUDIO_MIXER);
if (audioMixer != NULL) {
// until the audio mixer is setup for ping-reply, activate the public socket if it's not active
if (audioMixer->getActiveSocket() == NULL) {
audioMixer->activatePublicSocket();
}
// we have an active audio mixer we can send data to
// eveAudioInjector->injectAudio(&::audioSocket, audioMixer->getActiveSocket());
}
::injectAudioThreadRunning = false;
pthread_exit(0);
return NULL;
}
int main(int argc, const char* argv[]) {
// new seed for random audio sleep times
srand(time(0));
// create an AgentList instance to handle communication with other agents
AgentList *agentList = AgentList::createInstance(AGENT_TYPE_AVATAR, EVE_AGENT_LIST_PORT);
AgentList* agentList = AgentList::createInstance(AGENT_TYPE_AVATAR, EVE_AGENT_LISTEN_PORT);
// start telling the domain server that we are alive
agentList->startDomainServerCheckInThread();
@ -74,15 +111,22 @@ int main(int argc, char* argv[]) {
AvatarData eve = AvatarData();
// move eve away from the origin
eve.setBodyPosition(glm::vec3(3, 0, -3));
// pick a random point inside a 10x10 grid
// turn her back towards the origin
eve.setBodyYaw(-45);
eve.setPosition(glm::vec3(randFloatInRange(-RANDOM_POSITION_MAX_DIMENSION, RANDOM_POSITION_MAX_DIMENSION),
0,
randFloatInRange(-RANDOM_POSITION_MAX_DIMENSION, RANDOM_POSITION_MAX_DIMENSION)));
// face any instance of eve down the z-axis
eve.setBodyYaw(0);
// put her hand out so somebody can shake it
eve.setHandPosition(glm::vec3(eve.getBodyPosition()[0] - 0.2,
eve.setHandPosition(glm::vec3(eve.getPosition()[0] - 0.2,
0.25,
eve.getBodyPosition()[2] + 0.1));
eve.getPosition()[2] + 0.1));
// read eve's audio data
AudioInjector eveAudioInjector("eve.raw");
unsigned char broadcastPacket[MAX_PACKET_SIZE];
broadcastPacket[0] = PACKET_HEADER_HEAD_DATA;
@ -92,6 +136,9 @@ int main(int argc, char* argv[]) {
timeval thisSend;
double numMicrosecondsSleep = 0;
// int numIterationsLeftBeforeAudioSend = 0;
// pthread_t injectAudioThread;
while (true) {
// update the thisSend timeval to the current time
gettimeofday(&thisSend, NULL);
@ -104,10 +151,21 @@ int main(int argc, char* argv[]) {
// use the getBroadcastData method in the AvatarData class to populate the broadcastPacket buffer
numBytesToSend = eve.getBroadcastData((broadcastPacket + 1));
// use the UDPSocket instance attached to our agent list to send avatar data to mixer
agentList->getAgentSocket().send(avatarMixer->getActiveSocket(), broadcastPacket, numBytesToSend);
}
// temporarily disable Eve's audio sending until the file is actually available on EC2 box
// if (numIterationsLeftBeforeAudioSend == 0) {
// if (!::injectAudioThreadRunning) {
// pthread_create(&injectAudioThread, NULL, injectAudio, (void*) &eveAudioInjector);
//
// numIterationsLeftBeforeAudioSend = randIntInRange(MIN_ITERATIONS_BETWEEN_AUDIO_SENDS,
// MAX_ITERATIONS_BETWEEN_AUDIO_SENDS);
// }
// } else {
// numIterationsLeftBeforeAudioSend--;
// }
// sleep for the correct amount of time to have data send be consistently timed
if ((numMicrosecondsSleep = (DATA_SEND_INTERVAL_MSECS * 1000) - (usecTimestampNow() - usecTimestamp(&thisSend))) > 0) {

View file

@ -14,4 +14,4 @@ link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
# link the threads library
find_package(Threads REQUIRED)
target_link_libraries(injector ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(${TARGET_NAME} ${CMAKE_THREAD_LIBS_INIT})

View file

@ -1,5 +1,5 @@
//
// injector.cpp
// main.cpp
// Audio Injector
//
// Created by Leonardo Murillo on 3/5/13.
@ -11,39 +11,27 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <vector>
#include <fstream>
#include <algorithm>
#include <arpa/inet.h>
#include <string.h>
#include <sstream>
#include "UDPSocket.h"
#include "UDPSocket.cpp"
#include <SharedUtil.h>
#include <PacketHeaders.h>
#include <UDPSocket.h>
#include <AudioInjector.h>
char EC2_WEST_AUDIO_SERVER[] = "54.241.92.53";
const int AUDIO_UDP_LISTEN_PORT = 55443;
const int BUFFER_LENGTH_BYTES = 512;
const int BUFFER_LENGTH_SAMPLES = BUFFER_LENGTH_BYTES / sizeof(int16_t);
const float SAMPLE_RATE = 22050.0;
const float BUFFER_SEND_INTERVAL_USECS = (BUFFER_LENGTH_SAMPLES / SAMPLE_RATE) * 1000000;
// Command line parameter defaults
bool loopAudio = true;
float sleepIntervalMin = 1.00;
float sleepIntervalMax = 2.00;
float positionInUniverse[] = {0, 0, 0, 0};
unsigned char attenuationModifier = 255;
char *sourceAudioFile;
char *sourceAudioFile = NULL;
const char *allowedParameters = ":rb::t::c::a::f:";
char *charBuffer;
int16_t *buffer;
long length;
UDPSocket *streamSocket;
float floatArguments[4] = {0.0f, 0.0f, 0.0f, 0.0f};
unsigned char attenuationModifier = 255;
void usage(void)
{
@ -62,19 +50,19 @@ bool processParameters(int parameterCount, char* parameterData[])
while ((p = getopt(parameterCount, parameterData, allowedParameters)) != -1) {
switch (p) {
case 'r':
loopAudio = false;
::loopAudio = false;
std::cout << "[DEBUG] Random sleep mode enabled" << std::endl;
break;
case 'b':
sleepIntervalMin = atof(optarg);
::sleepIntervalMin = atof(optarg);
std::cout << "[DEBUG] Min delay between plays " << sleepIntervalMin << "sec" << std::endl;
break;
case 't':
sleepIntervalMax = atof(optarg);
::sleepIntervalMax = atof(optarg);
std::cout << "[DEBUG] Max delay between plays " << sleepIntervalMax << "sec" << std::endl;
break;
case 'f':
sourceAudioFile = optarg;
::sourceAudioFile = optarg;
std::cout << "[DEBUG] Opening file: " << sourceAudioFile << std::endl;
break;
case 'c':
@ -84,7 +72,7 @@ bool processParameters(int parameterCount, char* parameterData[])
int i = 0;
while (std::getline(ss, token, ',')) {
positionInUniverse[i] = atof(token.c_str());
::floatArguments[i] = atof(token.c_str());
++i;
if (i == 4) {
break;
@ -94,7 +82,7 @@ bool processParameters(int parameterCount, char* parameterData[])
break;
}
case 'a':
attenuationModifier = atoi(optarg);
::attenuationModifier = atoi(optarg);
std::cout << "[DEBUG] Attenuation modifier: " << optarg << std::endl;
break;
default:
@ -103,79 +91,44 @@ bool processParameters(int parameterCount, char* parameterData[])
}
}
return true;
};
};_Position
void loadFile(void) {
std::fstream sourceFile;
sourceFile.open(sourceAudioFile, std::ios::in | std::ios::binary);
sourceFile.seekg(0, std::ios::end);
length = sourceFile.tellg();
sourceFile.seekg(0, std::ios::beg);
long sizeOfShortArray = length / 2;
buffer = new int16_t[sizeOfShortArray];
sourceFile.read((char *)buffer, length);
}
void stream(void)
{
timeval startTime;
int leadingBytes = 1 + (sizeof(float) * 4);
unsigned char dataPacket[BUFFER_LENGTH_BYTES + leadingBytes];
dataPacket[0] = PACKET_HEADER_INJECT_AUDIO;
unsigned char *currentPacketPtr = dataPacket + 1;
for (int p = 0; p < 4; p++) {
memcpy(currentPacketPtr, &positionInUniverse[p], sizeof(float));
currentPacketPtr += sizeof(float);
}
*currentPacketPtr = attenuationModifier;
currentPacketPtr++;
for (int i = 0; i < length; i += BUFFER_LENGTH_SAMPLES) {
gettimeofday(&startTime, NULL);
memcpy(currentPacketPtr, &buffer[i], BUFFER_LENGTH_BYTES);
streamSocket->send(EC2_WEST_AUDIO_SERVER, AUDIO_UDP_LISTEN_PORT, dataPacket, sizeof(dataPacket));
double usecToSleep = usecTimestamp(&startTime) + BUFFER_SEND_INTERVAL_USECS - usecTimestampNow();
usleep(usecToSleep);
}
};
int main(int argc, char* argv[])
{
int main(int argc, const char* argv[]) {
srand(time(0));
int AUDIO_UDP_SEND_PORT = 1500 + (rand() % (int)(1500 - 2000 + 1));
streamSocket = new UDPSocket(AUDIO_UDP_SEND_PORT);
UDPSocket streamSocket(AUDIO_UDP_SEND_PORT);
if (processParameters(argc, argv)) {
if (sourceAudioFile) {
loadFile();
} else {
sockaddr_in mixerSocket;
mixerSocket.sin_family = AF_INET;
mixerSocket.sin_addr.s_addr = inet_addr(EC2_WEST_AUDIO_SERVER);
mixerSocket.sin_port = htons((uint16_t)AUDIO_UDP_LISTEN_PORT);
if (processParameters(argc, argv)) {
if (::sourceAudioFile == NULL) {
std::cout << "[FATAL] Source audio file not specified" << std::endl;
exit(-1);
}
for (int i = 0; i < sizeof(positionInUniverse)/sizeof(positionInUniverse[0]); ++i) {
std::cout << "Position " << positionInUniverse[i] << std::endl;
}
float delay;
int usecDelay;
while (true) {
stream();
} else {
AudioInjector injector(sourceAudioFile);
if (loopAudio) {
delay = 0;
} else {
delay = randFloatInRange(sleepIntervalMin, sleepIntervalMax);
injector.setPosition(::floatArguments);
injector.setBearing(*(::floatArguments + 3));
injector.setAttenuationModifier(::attenuationModifier);
float delay = 0;
int usecDelay = 0;
while (true) {
injector.injectAudio(&streamSocket, (sockaddr*) &mixerSocket);
if (!::loopAudio) {
delay = randFloatInRange(::sleepIntervalMin, ::sleepIntervalMax);
usecDelay = delay * 1000 * 1000;
usleep(usecDelay);
}
}
usecDelay = delay * 1000 * 1000;
usleep(usecDelay);
}
}
}
return 0;
}

View file

@ -157,7 +157,7 @@ int audioCallback (const void *inputBuffer,
// memcpy the three float positions
for (int p = 0; p < 3; p++) {
memcpy(currentPacketPtr, &data->linkedHead->getBodyPosition()[p], sizeof(float));
memcpy(currentPacketPtr, &data->linkedHead->getPosition()[p], sizeof(float));
currentPacketPtr += sizeof(float);
}
@ -250,8 +250,16 @@ int audioCallback (const void *inputBuffer,
}
// play whatever we have in the audio buffer
//
// if we haven't fired off the flange effect, check if we should
int lastYawMeasured = fabsf(data->linkedHead->getLastMeasuredYaw());
//
//
// NOTE: PER - LastMeasuredHeadYaw is now relative to body position, represents the local
// rotation of the head relative to body, this may effect flange effect!
//
//
int lastYawMeasured = fabsf(data->linkedHead->getLastMeasuredHeadYaw());
if (!samplesLeftForFlange && lastYawMeasured > MIN_FLANGE_EFFECT_THRESHOLD) {
// we should flange for one second

View file

@ -35,8 +35,6 @@ float browThickness = 0.16;
bool usingBigSphereCollisionTest = true;
char iris_texture_file[] = "resources/images/green_eye.png";
vector<unsigned char> iris_texture;
@ -50,7 +48,7 @@ Head::Head(bool isMine) {
_velocity = glm::vec3( 0.0, 0.0, 0.0 );
_thrust = glm::vec3( 0.0, 0.0, 0.0 );
_rotation = glm::quat( 0.0f, 0.0f, 0.0f, 0.0f );
_closestOtherAvatar = 0;
_nearOtherAvatar = false;
_bodyYaw = -90.0;
_bodyPitch = 0.0;
_bodyRoll = 0.0;
@ -62,7 +60,7 @@ Head::Head(bool isMine) {
//_transmitterTimer = 0;
_transmitterHz = 0.0;
_transmitterPackets = 0;
_numOtherAvatarsInView = 0;
//_numOtherAvatars = 0;
initializeSkeleton();
@ -75,9 +73,9 @@ Head::Head(bool isMine) {
_head.interPupilDistance = 0.6;
_head.interBrowDistance = 0.75;
_head.nominalPupilSize = 0.10;
_head.yaw = 0.0;
_head.pitch = 0.0;
_head.roll = 0.0;
//_head.yaw = 0.0;
//_head.pitch = 0.0;
//_head.roll = 0.0;
_head.pitchRate = 0.0;
_head.yawRate = 0.0;
_head.rollRate = 0.0;
@ -106,7 +104,6 @@ Head::Head(bool isMine) {
_head.eyeContactTarget = LEFT_EYE;
_head.scale = 1.0;
_head.audioAttack = 0.0;
_head.loudness = 0.0;
_head.averageLoudness = 0.0;
_head.lastLoudness = 0.0;
_head.browAudioLift = 0.0;
@ -120,7 +117,11 @@ Head::Head(bool isMine) {
_renderPitch = 0.0;
_sphere = NULL;
_handHolding.position = glm::vec3( 0.0, 0.0, 0.0 );
_handHolding.velocity = glm::vec3( 0.0, 0.0, 0.0 );
_handHolding.force = 10.0f;
if (iris_texture.size() == 0) {
switchToResourcesParentIfRequired();
unsigned error = lodepng::decode(iris_texture, iris_texture_width, iris_texture_height, iris_texture_file);
@ -128,23 +129,19 @@ Head::Head(bool isMine) {
printLog("error %u: %s\n", error, lodepng_error_text(error));
}
}
//--------------------------------------------------
// test... just slam them into random positions...
//--------------------------------------------------
_otherAvatarHandPosition[ 0 ] = glm::vec3( 0.0f, 0.3f, 2.0f );
_otherAvatarHandPosition[ 1 ] = glm::vec3( 4.0f, 0.3f, 2.0f );
_otherAvatarHandPosition[ 2 ] = glm::vec3( 2.0f, 0.3f, 2.0f );
_otherAvatarHandPosition[ 3 ] = glm::vec3( 1.0f, 0.3f, -4.0f );
_otherAvatarHandPosition[ 4 ] = glm::vec3( -2.0f, 0.3f, -2.0f );
_otherAvatar.handPosition = glm::vec3( 0.0f, 0.0f, 0.0f );
_otherAvatar.handState = 0;
}
Head::Head(const Head &otherAvatar) {
_velocity = otherAvatar._velocity;
_thrust = otherAvatar._thrust;
_rotation = otherAvatar._rotation;
_closestOtherAvatar = otherAvatar._closestOtherAvatar;
_nearOtherAvatar = otherAvatar._nearOtherAvatar;
_bodyYaw = otherAvatar._bodyYaw;
_bodyPitch = otherAvatar._bodyPitch;
_bodyRoll = otherAvatar._bodyRoll;
@ -176,9 +173,9 @@ Head::Head(const Head &otherAvatar) {
_head.interPupilDistance = otherAvatar._head.interPupilDistance;
_head.interBrowDistance = otherAvatar._head.interBrowDistance;
_head.nominalPupilSize = otherAvatar._head.nominalPupilSize;
_head.yaw = otherAvatar._head.yaw;
_head.pitch = otherAvatar._head.pitch;
_head.roll = otherAvatar._head.roll;
//_head.yaw = otherAvatar._head.yaw;
//_head.pitch = otherAvatar._head.pitch;
//_head.roll = otherAvatar._head.roll;
_head.yawRate = otherAvatar._head.yawRate;
_head.pitchRate = otherAvatar._head.pitchRate;
_head.rollRate = otherAvatar._head.rollRate;
@ -207,7 +204,6 @@ Head::Head(const Head &otherAvatar) {
_head.eyeContactTarget = otherAvatar._head.eyeContactTarget;
_head.scale = otherAvatar._head.scale;
_head.audioAttack = otherAvatar._head.audioAttack;
_head.loudness = otherAvatar._head.loudness;
_head.averageLoudness = otherAvatar._head.averageLoudness;
_head.lastLoudness = otherAvatar._head.lastLoudness;
_head.browAudioLift = otherAvatar._head.browAudioLift;
@ -234,14 +230,14 @@ Head* Head::clone() const {
}
void Head::reset() {
_head.pitch = _head.yaw = _head.roll = 0;
_headPitch = _headYaw = _headRoll = 0;
_head.leanForward = _head.leanSideways = 0;
}
//this pertains to moving the head with the glasses
//---------------------------------------------------
void Head::UpdateGyros(float frametime, SerialInterface * serialInterface, int head_mirror, glm::vec3 * gravity)
void Head::UpdateGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity)
// Using serial data, update avatar/render position and angles
{
const float PITCH_ACCEL_COUPLING = 0.5;
@ -269,20 +265,15 @@ void Head::UpdateGyros(float frametime, SerialInterface * serialInterface, int h
const float MAX_YAW = 85;
const float MIN_YAW = -85;
if ((_head.pitch < MAX_PITCH) && (_head.pitch > MIN_PITCH))
addPitch(measured_pitch_rate * -HEAD_ROTATION_SCALE * frametime);
if ((_headPitch < MAX_PITCH) && (_headPitch > MIN_PITCH))
addHeadPitch(measured_pitch_rate * -HEAD_ROTATION_SCALE * frametime);
addRoll(-measured_roll_rate * HEAD_ROLL_SCALE * frametime);
addHeadRoll(measured_roll_rate * HEAD_ROLL_SCALE * frametime);
if (head_mirror) {
if ((_head.yaw < MAX_YAW) && (_head.yaw > MIN_YAW))
addYaw(-_head.yawRate * HEAD_ROTATION_SCALE * frametime);
addLean(-measured_lateral_accel * frametime * HEAD_LEAN_SCALE, -measured_fwd_accel*frametime * HEAD_LEAN_SCALE);
} else {
if ((_head.yaw < MAX_YAW) && (_head.yaw > MIN_YAW))
addYaw(_head.yawRate * -HEAD_ROTATION_SCALE * frametime);
addLean(measured_lateral_accel * frametime * -HEAD_LEAN_SCALE, measured_fwd_accel*frametime * HEAD_LEAN_SCALE);
}
if ((_headYaw < MAX_YAW) && (_headYaw > MIN_YAW))
addHeadYaw(_head.yawRate * HEAD_ROTATION_SCALE * frametime);
addLean(-measured_lateral_accel * frametime * HEAD_LEAN_SCALE, -measured_fwd_accel*frametime * HEAD_LEAN_SCALE);
}
void Head::addLean(float x, float z) {
@ -304,7 +295,6 @@ void Head::setMousePressed( bool d ) {
_mousePressed = d;
}
void Head::simulate(float deltaTime) {
//-------------------------------------------------------------
@ -313,15 +303,12 @@ void Head::simulate(float deltaTime) {
//-------------------------------------------------------------
if ( _isMine )
{
//-------------------------------------
// DEBUG - other avatars...
//-------------------------------------
_closestOtherAvatar = -1;
_nearOtherAvatar = false;
float closestDistance = 10000.0f;
AgentList * agentList = AgentList::getInstance();
_numOtherAvatarsInView =0;
//_numOtherAvatars = 0;
for(std::vector<Agent>::iterator agent = agentList->getAgents().begin();
agent != agentList->getAgents().end();
@ -329,63 +316,63 @@ void Head::simulate(float deltaTime) {
if (( agent->getLinkedData() != NULL && ( agent->getType() == AGENT_TYPE_AVATAR ) )) {
Head *otherAvatar = (Head *)agent->getLinkedData();
if ( _numOtherAvatarsInView < MAX_OTHER_AVATARS ) {
// if ( _numOtherAvatars < MAX_OTHER_AVATARS )
{
//-----------------------------------------------------------
// test other avatar hand position for proximity...
//-----------------------------------------------------------
_otherAvatarHandPosition[ _numOtherAvatarsInView ] = otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND );
//------------------------------------------------------
// check for collisions with other avatars and respond
//------------------------------------------------------
updateAvatarCollisionDetectionAndResponse
(
otherAvatar->getPosition(),
otherAvatar->getGirth(),
otherAvatar->getHeight(),
otherAvatar->getBodyUpDirection(),
deltaTime
);
//-------------------------------------------------
// test other avatar hand position for proximity
//------------------------------------------------
glm::vec3 v( _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position );
v -= _otherAvatarHandPosition[ _numOtherAvatarsInView ];
v -= otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND );
float distance = glm::length( v );
if ( distance < _maxArmLength ) {
if ( distance < closestDistance ) {
closestDistance = distance;
_closestOtherAvatar = _numOtherAvatarsInView;
_numOtherAvatarsInView++;
_nearOtherAvatar = true;
_otherAvatar.handPosition = otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND );
_otherAvatar.handState = (int)otherAvatar->getHandState();
}
}
}
}
}
/*
///for testing only (prior to having real avs working)
for (int o=0; o<NUM_OTHER_AVATARS; o++) {
//-------------------------------------
// test other avs for proximity...
//-------------------------------------
glm::vec3 v( _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position );
v -= _DEBUG_otherAvatarListPosition[o];
float distance = glm::length( v );
if ( distance < _maxArmLength ) {
if ( distance < closestDistance ) {
closestDistance = distance;
_closestOtherAvatar = o;
}
}
}
*/
}//if ( _isMine )
if ( usingBigSphereCollisionTest ) {
//--------------------------------------------------------------
// test for avatar collision response (using a big sphere :)
//--------------------------------------------------------------
updateBigSphereCollisionTest(deltaTime);
updateAvatarCollisionDetectionAndResponse
(
_TEST_bigSpherePosition,
_TEST_bigSphereRadius,
_TEST_bigSphereRadius,
glm::vec3( 0.0, 1.0, 0.0 ),
deltaTime
);
}
if ( AVATAR_GRAVITY ) {
if ( _bodyPosition.y > _bone[ AVATAR_BONE_RIGHT_FOOT ].radius * 2.0 ) {
if ( _position.y > _bone[ AVATAR_BONE_RIGHT_FOOT ].radius * 2.0 ) {
_velocity += glm::dvec3( 0.0, -1.0, 0.0 ) * ( 6.0 * deltaTime );
}
else {
if ( _bodyPosition.y < _bone[ AVATAR_BONE_RIGHT_FOOT ].radius ) {
_bodyPosition.y = _bone[ AVATAR_BONE_RIGHT_FOOT ].radius;
if ( _position.y < _bone[ AVATAR_BONE_RIGHT_FOOT ].radius ) {
_position.y = _bone[ AVATAR_BONE_RIGHT_FOOT ].radius;
_velocity.y = 0.0;
}
}
@ -400,7 +387,7 @@ void Head::simulate(float deltaTime) {
// reset hand and arm positions according to hand movement
//------------------------------------------------------------
if (_usingBodySprings) {
updateHandMovement();
updateHandMovement( deltaTime );
updateBodySprings( deltaTime );
}
@ -462,10 +449,6 @@ void Head::simulate(float deltaTime) {
_bodyYaw += _bodyYawDelta * deltaTime;
}
// we will be eventually getting head rotation from elsewhere. For now, just setting it to body rotation
_head.yaw = _bodyYaw;
_head.pitch = _bodyPitch;
_head.roll = _bodyRoll;
//----------------------------------------------------------
// decay body yaw delta
@ -480,28 +463,37 @@ void Head::simulate(float deltaTime) {
//----------------------------------------------------------
// update position by velocity
//----------------------------------------------------------
_bodyPosition += (glm::vec3)_velocity * deltaTime;
_position += (glm::vec3)_velocity * deltaTime;
//----------------------------------------------------------
// decay velocity
//----------------------------------------------------------
_velocity *= ( 1.0 - LIN_VEL_DECAY * deltaTime );
//
// Update Head information
//
// we will be eventually getting head rotation from elsewhere. For now, just setting it to body rotation
//_head.yaw = _bodyYaw;
//_head.pitch = _bodyPitch;
//_head.roll = _bodyRoll;
if (!_head.noise) {
// Decay back toward center
_head.pitch *= (1.0f - DECAY*2*deltaTime);
_head.yaw *= (1.0f - DECAY*2*deltaTime);
_head.roll *= (1.0f - DECAY*2*deltaTime);
_headPitch *= (1.0f - DECAY * 2 * deltaTime);
_headYaw *= (1.0f - DECAY * 2 * deltaTime);
_headRoll *= (1.0f - DECAY * 2 * deltaTime);
}
else {
// Move toward new target
_head.pitch += (_head.pitchTarget - _head.pitch)*10*deltaTime; // (1.f - DECAY*deltaTime)*Pitch + ;
_head.yaw += (_head.yawTarget - _head.yaw )*10*deltaTime; // (1.f - DECAY*deltaTime);
_head.roll *= (1.f - DECAY*deltaTime);
_headPitch += (_head.pitchTarget - _headPitch) * 10 * deltaTime; // (1.f - DECAY*deltaTime)*Pitch + ;
_headYaw += (_head.yawTarget - _headYaw ) * 10 * deltaTime; // (1.f - DECAY*deltaTime);
_headRoll *= 1.f - (DECAY * deltaTime);
}
_head.leanForward *= (1.f - DECAY*30.f*deltaTime);
_head.leanSideways *= (1.f - DECAY*30.f*deltaTime);
_head.leanForward *= (1.f - DECAY * 30 * deltaTime);
_head.leanSideways *= (1.f - DECAY * 30 * deltaTime);
// Update where the avatar's eyes are
//
@ -511,8 +503,8 @@ void Head::simulate(float deltaTime) {
_head.eyeContact = 1;
if (!_head.eyeContact) {
// If we just stopped making eye contact,move the eyes markedly away
_head.eyeballPitch[0] = _head.eyeballPitch[1] = _head.eyeballPitch[0] + 5.0 + (randFloat() - 0.5)*10;
_head.eyeballYaw [0] = _head.eyeballYaw [1] = _head.eyeballYaw [0] + 5.0 + (randFloat() - 0.5)*5;
_head.eyeballPitch[0] = _head.eyeballPitch[1] = _head.eyeballPitch[0] + 5.0 + (randFloat() - 0.5) * 10;
_head.eyeballYaw [0] = _head.eyeballYaw [1] = _head.eyeballYaw [0] + 5.0 + (randFloat() - 0.5) * 5;
} else {
// If now making eye contact, turn head to look right at viewer
SetNewHeadTarget(0,0);
@ -539,63 +531,75 @@ void Head::simulate(float deltaTime) {
if (_head.eyeContactTarget == RIGHT_EYE) eye_target_yaw_adjust = -DEGREES_BETWEEN_VIEWER_EYES;
if (_head.eyeContactTarget == MOUTH) eye_target_pitch_adjust = DEGREES_TO_VIEWER_MOUTH;
_head.eyeballPitch[0] = _head.eyeballPitch[1] = -_head.pitch + eye_target_pitch_adjust;
_head.eyeballYaw[0] = _head.eyeballYaw[1] = -_head.yaw + eye_target_yaw_adjust;
_head.eyeballPitch[0] = _head.eyeballPitch[1] = -_headPitch + eye_target_pitch_adjust;
_head.eyeballYaw[0] = _head.eyeballYaw[1] = -_headYaw + eye_target_yaw_adjust;
}
if (_head.noise)
{
_head.pitch += (randFloat() - 0.5)*0.2*_head.noiseEnvelope;
_head.yaw += (randFloat() - 0.5)*0.3*_head.noiseEnvelope;
//PupilSize += (randFloat() - 0.5)*0.001*NoiseEnvelope;
_headPitch += (randFloat() - 0.5) * 0.2 * _head.noiseEnvelope;
_headYaw += (randFloat() - 0.5) * 0.3 *_head.noiseEnvelope;
//PupilSize += (randFloat() - 0.5) * 0.001*NoiseEnvelope;
if (randFloat() < 0.005) _head.mouthWidth = MouthWidthChoices[rand()%3];
if (!_head.eyeContact) {
if (randFloat() < 0.01) _head.eyeballPitch[0] = _head.eyeballPitch[1] = (randFloat() - 0.5)*20;
if (randFloat() < 0.01) _head.eyeballYaw[0] = _head.eyeballYaw[1] = (randFloat()- 0.5)*10;
if (randFloat() < 0.01) _head.eyeballPitch[0] = _head.eyeballPitch[1] = (randFloat() - 0.5) * 20;
if (randFloat() < 0.01) _head.eyeballYaw[0] = _head.eyeballYaw[1] = (randFloat()- 0.5) * 10;
}
if ((randFloat() < 0.005) && (fabs(_head.pitchTarget - _head.pitch) < 1.0) && (fabs(_head.yawTarget - _head.yaw) < 1.0)) {
SetNewHeadTarget((randFloat()-0.5)*20.0, (randFloat()-0.5)*45.0);
if ((randFloat() < 0.005) && (fabs(_head.pitchTarget - _headPitch) < 1.0) && (fabs(_head.yawTarget - _headYaw) < 1.0)) {
SetNewHeadTarget((randFloat()-0.5) * 20.0, (randFloat()-0.5) * 45.0);
}
if (0) {
// Pick new target
_head.pitchTarget = (randFloat() - 0.5)*45;
_head.yawTarget = (randFloat() - 0.5)*22;
_head.pitchTarget = (randFloat() - 0.5) * 45;
_head.yawTarget = (randFloat() - 0.5) * 22;
}
if (randFloat() < 0.01)
{
_head.eyebrowPitch[0] = _head.eyebrowPitch[1] = BrowPitchAngle[rand()%3];
_head.eyebrowRoll [0] = _head.eyebrowRoll[1] = BrowRollAngle[rand()%5];
_head.eyebrowRoll [1]*=-1;
_head.eyebrowRoll [1] *=-1;
}
}
}
float Head::getGirth() {
return COLLISION_BODY_RADIUS;
}
float Head::getHeight() {
return COLLISION_HEIGHT;
}
glm::vec3 Head::getBodyUpDirection() {
return _orientation.getUp();
}
//--------------------------------------------------------------------------------
// This is a workspace for testing avatar body collision detection and response
//--------------------------------------------------------------------------------
void Head::updateBigSphereCollisionTest( float deltaTime ) {
void Head::updateAvatarCollisionDetectionAndResponse
( glm::vec3 collisionPosition, float collisionGirth, float collisionHeight, glm::vec3 collisionUpVector, float deltaTime ) {
float myBodyApproximateBoundingRadius = 1.0f;
glm::vec3 vectorFromMyBodyToBigSphere(_bodyPosition - _TEST_bigSpherePosition);
glm::vec3 vectorFromMyBodyToBigSphere(_position - collisionPosition);
bool jointCollision = false;
float distanceToBigSphere = glm::length(vectorFromMyBodyToBigSphere);
if ( distanceToBigSphere < myBodyApproximateBoundingRadius + _TEST_bigSphereRadius)
if ( distanceToBigSphere < myBodyApproximateBoundingRadius + collisionGirth )
{
for (int b=0; b<NUM_AVATAR_BONES; b++)
{
glm::vec3 vectorFromJointToBigSphereCenter(_bone[b].springyPosition - _TEST_bigSpherePosition);
glm::vec3 vectorFromJointToBigSphereCenter(_bone[b].springyPosition - collisionPosition);
float distanceToBigSphereCenter = glm::length(vectorFromJointToBigSphereCenter);
float combinedRadius = _bone[b].radius + _TEST_bigSphereRadius;
float combinedRadius = _bone[b].radius + collisionGirth;
if ( distanceToBigSphereCenter < combinedRadius )
{
jointCollision = true;
@ -608,7 +612,7 @@ void Head::updateBigSphereCollisionTest( float deltaTime ) {
_bone[b].springyVelocity += collisionForce * 30.0f * deltaTime;
_velocity += collisionForce * 100.0f * deltaTime;
_bone[b].springyPosition = _TEST_bigSpherePosition + directionVector * combinedRadius;
_bone[b].springyPosition = collisionPosition + directionVector * combinedRadius;
}
}
}
@ -621,23 +625,22 @@ void Head::updateBigSphereCollisionTest( float deltaTime ) {
}
}
}
void Head::render(int faceToFace) {
void Head::render(bool lookingInMirror) {
//---------------------------------------------------
// show avatar position
//---------------------------------------------------
glColor4f( 0.5f, 0.5f, 0.5f, 0.6 );
glPushMatrix();
glTranslatef(_bodyPosition.x, _bodyPosition.y, _bodyPosition.z);
glTranslatef(_position.x, _position.y, _position.z);
glScalef( 0.03, 0.03, 0.03 );
glutSolidSphere( 1, 10, 10 );
glPopMatrix();
if ( usingBigSphereCollisionTest ) {
//---------------------------------------------------
// show TEST big sphere
@ -658,31 +661,18 @@ void Head::render(int faceToFace) {
//---------------------------------------------------
// render head
//---------------------------------------------------
renderHead(faceToFace);
renderHead(lookingInMirror);
//---------------------------------------------------------------------------
// if this is my avatar, then render my interactions with the other avatars
//---------------------------------------------------------------------------
if ( _isMine )
{
/*
//---------------------------------------------------
// render other avatars (DEBUG TEST)
//---------------------------------------------------
for (int o=0; o<_numOtherAvatarsInView; o++) {
glPushMatrix();
glTranslatef( _otherAvatarHandPosition[o].x, _otherAvatarHandPosition[o].y, _otherAvatarHandPosition[o].z );
glScalef( 0.03, 0.03, 0.03 );
glutSolidSphere( 1, 10, 10 );
glPopMatrix();
}
*/
if (_usingBodySprings) {
if ( _closestOtherAvatar != -1 ) {
if ( _nearOtherAvatar ) {
glm::vec3 v1( _bone[ AVATAR_BONE_RIGHT_HAND ].position );
glm::vec3 v2( _otherAvatarHandPosition[ _closestOtherAvatar ] );
glm::vec3 v2( _otherAvatar.handPosition );
glLineWidth( 8.0 );
glColor4f( 0.7f, 0.4f, 0.1f, 0.6 );
@ -695,9 +685,9 @@ void Head::render(int faceToFace) {
}
}
void Head::renderHead(int faceToFace) {
void Head::renderHead(bool lookingInMirror) {
int side = 0;
glEnable(GL_DEPTH_TEST);
@ -723,9 +713,15 @@ void Head::renderHead(int faceToFace) {
glScalef( 0.03, 0.03, 0.03 );
glRotatef(_head.yaw, 0, 1, 0);
glRotatef(_head.pitch, 1, 0, 0);
glRotatef(_head.roll, 0, 0, 1);
if (lookingInMirror) {
glRotatef(_bodyYaw - _headYaw, 0, 1, 0);
glRotatef(_bodyPitch + _headPitch, 1, 0, 0);
glRotatef(_bodyRoll - _headRoll, 0, 0, 1);
} else {
glRotatef(_bodyYaw + _headYaw, 0, 1, 0);
glRotatef(_bodyPitch + _headPitch, 1, 0, 0);
glRotatef(_bodyRoll + _headRoll, 0, 0, 1);
}
glScalef(2.0, 2.0, 2.0);
glColor3fv(skinColor);
@ -745,17 +741,17 @@ void Head::renderHead(int faceToFace) {
glPopMatrix();
// _eyebrows
_head.audioAttack = 0.9*_head.audioAttack + 0.1*fabs(_head.loudness - _head.lastLoudness);
_head.lastLoudness = _head.loudness;
_head.audioAttack = 0.9 * _head.audioAttack + 0.1 * fabs(_audioLoudness - _head.lastLoudness);
_head.lastLoudness = _audioLoudness;
const float BROW_LIFT_THRESHOLD = 100;
if (_head.audioAttack > BROW_LIFT_THRESHOLD)
_head.browAudioLift += sqrt(_head.audioAttack)/1000.0;
_head.browAudioLift += sqrt(_head.audioAttack) / 1000.0;
_head.browAudioLift *= .90;
glPushMatrix();
glTranslatef(-_head.interBrowDistance/2.0,0.4,0.45);
glTranslatef(-_head.interBrowDistance / 2.0,0.4,0.45);
for(side = 0; side < 2; side++) {
glColor3fv(browColor);
glPushMatrix();
@ -809,7 +805,7 @@ void Head::renderHead(int faceToFace) {
glPushMatrix();
{
glRotatef(_head.eyeballPitch[1], 1, 0, 0);
glRotatef(_head.eyeballYaw[1] + _head.yaw + _head.pupilConverge, 0, 1, 0);
glRotatef(_head.eyeballYaw[1] + _headYaw + _head.pupilConverge, 0, 1, 0);
glTranslatef(0,0,.35);
glRotatef(-75,1,0,0);
glScalef(1.0, 0.4, 1.0);
@ -835,7 +831,7 @@ void Head::renderHead(int faceToFace) {
glPushMatrix();
{
glRotatef(_head.eyeballPitch[0], 1, 0, 0);
glRotatef(_head.eyeballYaw[0] + _head.yaw - _head.pupilConverge, 0, 1, 0);
glRotatef(_head.eyeballYaw[0] + _headYaw - _head.pupilConverge, 0, 1, 0);
glTranslatef(0, 0, .35);
glRotatef(-75, 1, 0, 0);
glScalef(1.0, 0.4, 1.0);
@ -979,9 +975,6 @@ void Head::initializeSkeleton() {
updateSkeleton();
}
void Head::calculateBoneLengths() {
for (int b=0; b<NUM_AVATAR_BONES; b++) {
_bone[b].length = glm::length( _bone[b].defaultPosePosition );
@ -1006,7 +999,7 @@ void Head::updateSkeleton() {
for (int b=0; b<NUM_AVATAR_BONES; b++) {
if ( _bone[b].parent == AVATAR_BONE_NULL ) {
_bone[b].orientation.set( _orientation );
_bone[b].position = _bodyPosition;
_bone[b].position = _position;
}
else {
_bone[b].orientation.set( _bone[ _bone[b].parent ].orientation );
@ -1045,7 +1038,7 @@ void Head::updateBodySprings( float deltaTime ) {
glm::vec3 springVector( _bone[b].springyPosition );
if ( _bone[b].parent == AVATAR_BONE_NULL ) {
springVector -= _bodyPosition;
springVector -= _position;
}
else {
springVector -= _bone[ _bone[b].parent ].springyPosition;
@ -1123,7 +1116,7 @@ glm::vec3 Head::getBonePosition( AvatarBoneID b ) {
void Head::updateHandMovement() {
void Head::updateHandMovement( float deltaTime ) {
glm::vec3 transformedHandMovement;
transformedHandMovement
@ -1133,28 +1126,45 @@ void Head::updateHandMovement() {
_bone[ AVATAR_BONE_RIGHT_HAND ].position += transformedHandMovement;
//if holding hands, add a pull to the hand...
if ( _usingBodySprings ) {
if ( _closestOtherAvatar != -1 ) {
if ( _mousePressed ) {
setHandState(_mousePressed);
bool atLeastOneAvatarIsGrasping = false;
if ( getHandState() == 1 ) { atLeastOneAvatarIsGrasping = true; }
//if ( _isMine ) {
//if ( _otherAvatar.handState == 1 ) {
if ( _nearOtherAvatar ) {
atLeastOneAvatarIsGrasping = true;
}
//}
//}
glm::vec3 handToHandVector( _otherAvatarHandPosition[ _closestOtherAvatar ]);
handToHandVector -= _bone[ AVATAR_BONE_RIGHT_HAND ].position;
//_bone[ AVATAR_BONE_RIGHT_HAND ].springyVelocity -= handPull;
_bone[ AVATAR_BONE_RIGHT_HAND ].position = _otherAvatarHandPosition[ _closestOtherAvatar ];
}
}
}
//---------------------------------------------------------------------
// if holding hands with another avatar, add a force to the hand...
//---------------------------------------------------------------------
if ( atLeastOneAvatarIsGrasping ) {
glm::vec3 vectorToOtherHand = _otherAvatar.handPosition - _handHolding.position;
glm::vec3 vectorToMyHand = _bone[ AVATAR_BONE_RIGHT_HAND ].position - _handHolding.position;
_handHolding.velocity *= 0.7;
_handHolding.velocity += ( vectorToOtherHand + vectorToMyHand ) * _handHolding.force * deltaTime;
_handHolding.position += _handHolding.velocity;
_bone[ AVATAR_BONE_RIGHT_HAND ].position = _handHolding.position;
}
else {
_handHolding.position = _bone[ AVATAR_BONE_RIGHT_HAND ].position;
_handHolding.velocity = glm::vec3( 0.0, 0.0, 0.0 );
}
//-------------------------------------------------------------------------------
// determine the arm vector
//-------------------------------------------------------------------------------
glm::vec3 armVector = _bone[ AVATAR_BONE_RIGHT_HAND ].position;
armVector -= _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position;
//-------------------------------------------------------------------------------
// test to see if right hand is being dragged beyond maximum arm length
//-------------------------------------------------------------------------------
@ -1175,30 +1185,13 @@ void Head::updateHandMovement() {
constrainedPosition += armVector;
_bone[ AVATAR_BONE_RIGHT_HAND ].position = constrainedPosition;
}
/*
//-------------------------------------------------------------------------------
// keep arm from going through av body...
//-------------------------------------------------------------------------------
glm::vec3 adjustedArmVector = _bone[ AVATAR_BONE_RIGHT_HAND ].position;
adjustedArmVector -= _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position;
float rightComponent = glm::dot( adjustedArmVector, avatar.orientation.getRight() );
if ( rightComponent < 0.0 )
{
_bone[ AVATAR_BONE_RIGHT_HAND ].position -= avatar.orientation.getRight() * rightComponent;
}
*/
//-----------------------------------------------------------------------------
// set elbow position
//-----------------------------------------------------------------------------
glm::vec3 newElbowPosition = _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position;
newElbowPosition += armVector * ONE_HALF;
//glm::vec3 perpendicular = glm::cross( frontDirection, armVector );
glm::vec3 perpendicular = glm::cross( _orientation.getFront(), armVector );
newElbowPosition += perpendicular * ( 1.0f - ( _maxArmLength / distance ) ) * ONE_HALF;
_bone[ AVATAR_BONE_RIGHT_UPPER_ARM ].position = newElbowPosition;
@ -1226,7 +1219,7 @@ void Head::renderBody() {
//renderBoneAsBlock( (AvatarBoneID)b);
//render bone orientation
renderOrientationDirections( _bone[b].springyPosition, _bone[b].orientation, _bone[b].radius * 2.0 );
//renderOrientationDirections( _bone[b].springyPosition, _bone[b].orientation, _bone[b].radius * 2.0 );
if ( _usingBodySprings ) {
glColor3fv( skinColor );
@ -1274,8 +1267,10 @@ void Head::renderBody() {
}
}
if (( _usingBodySprings ) && ( _mousePressed )) {
glColor4f( 1.0, 1.0, 0.5, 0.5 );
//---------------------------------------------------------
// if the hand is grasping, show it...
//---------------------------------------------------------
if (( _usingBodySprings ) && ( getHandState() == 1 )) {
glPushMatrix();
glTranslatef
(
@ -1283,7 +1278,10 @@ void Head::renderBody() {
_bone[ AVATAR_BONE_RIGHT_HAND ].springyPosition.y,
_bone[ AVATAR_BONE_RIGHT_HAND ].springyPosition.z
);
glutSolidSphere( 0.03f, 10.0f, 5.0f );
glColor4f( 1.0, 1.0, 0.8, 0.3 ); glutSolidSphere( 0.020f, 10.0f, 10.0f );
glColor4f( 1.0, 1.0, 0.4, 0.2 ); glutSolidSphere( 0.025f, 10.0f, 10.0f );
glColor4f( 1.0, 1.0, 0.2, 0.1 ); glutSolidSphere( 0.030f, 10.0f, 10.0f );
glPopMatrix();
}
}
@ -1302,9 +1300,6 @@ void Head::renderBoneAsBlock( AvatarBoneID b ) {
glPopMatrix();
}
void Head::SetNewHeadTarget(float pitch, float yaw) {
_head.pitchTarget = pitch;
_head.yawTarget = yaw;

View file

@ -29,6 +29,9 @@ const float YAW_MAG = 300.0;
const float TEST_YAW_DECAY = 5.0;
const float LIN_VEL_DECAY = 5.0;
const float COLLISION_BODY_RADIUS = 0.1;
const float COLLISION_HEIGHT = 1.5;
enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH};
#define FWD 0
@ -41,7 +44,7 @@ enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH};
#define ROT_RIGHT 7
#define MAX_DRIVE_KEYS 8
#define MAX_OTHER_AVATARS 50 // temporary - for testing purposes!
#define MAX_OTHER_AVATARS 10 // temporary - for testing purposes!
enum AvatarMode
{
@ -81,6 +84,29 @@ enum AvatarBoneID
NUM_AVATAR_BONES
};
struct AvatarCollisionElipsoid
{
bool colliding;
glm::vec3 position;
float girth;
float height;
glm::vec3 upVector;
};
struct AvatarHandHolding
{
glm::vec3 position;
glm::vec3 velocity;
float force;
};
struct OtherAvatar
{
glm::vec3 handPosition;
int handState;
};
struct AvatarBone
{
AvatarBoneID parent; // which bone is this bone connected to?
@ -100,9 +126,6 @@ struct AvatarBone
struct AvatarHead
{
float pitch;
float yaw;
float roll;
float pitchRate;
float yawRate;
float rollRate;
@ -134,7 +157,7 @@ struct AvatarHead
eyeContactTargets eyeContactTarget;
// Sound loudness information
float loudness, lastLoudness;
float lastLoudness;
float averageLoudness;
float audioAttack;
};
@ -148,11 +171,8 @@ class Head : public AvatarData {
Head* clone() const;
void reset();
void UpdateGyros(float frametime, SerialInterface * serialInterface, int head_mirror, glm::vec3 * gravity);
void UpdateGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity);
void setNoise (float mag) { _head.noise = mag; }
void setPitch(float p) {_head.pitch = p; }
void setYaw(float y) {_head.yaw = y; }
void setRoll(float r) {_head.roll = r; };
void setScale(float s) {_head.scale = s; };
void setRenderYaw(float y) {_renderYaw = y;}
void setRenderPitch(float p) {_renderPitch = p;}
@ -160,14 +180,8 @@ class Head : public AvatarData {
float getRenderPitch() {return _renderPitch;}
void setLeanForward(float dist);
void setLeanSideways(float dist);
void addPitch(float p) {_head.pitch -= p; }
void addYaw(float y){_head.yaw -= y; }
void addRoll(float r){_head.roll += r; }
void addLean(float x, float z);
float getPitch() {return _head.pitch;}
float getRoll() {return _head.roll;}
float getYaw() {return _head.yaw;}
float getLastMeasuredYaw() {return _head.yawRate;}
float getLastMeasuredHeadYaw() const {return _head.yawRate;}
float getBodyYaw() {return _bodyYaw;};
void addBodyYaw(float y) {_bodyYaw += y;};
@ -175,25 +189,27 @@ class Head : public AvatarData {
glm::vec3 getHeadLookatDirectionUp();
glm::vec3 getHeadLookatDirectionRight();
glm::vec3 getHeadPosition();
glm::vec3 getBonePosition( AvatarBoneID b );
glm::vec3 getBonePosition( AvatarBoneID b );
glm::vec3 getBodyUpDirection();
//int getHandState();
float getGirth();
float getHeight();
AvatarMode getMode();
void setMousePressed( bool pressed );
void render(int faceToFace);
void render(bool lookingInMirror);
void renderBody();
void renderHead( int faceToFace);
void renderHead(bool lookingInMirror);
void simulate(float);
void startHandMovement();
void stopHandMovement();
void setHandMovementValues( glm::vec3 movement );
void updateHandMovement();
void updateHandMovement( float deltaTime );
float getLoudness() {return _head.loudness;};
float getAverageLoudness() {return _head.averageLoudness;};
void setAverageLoudness(float al) {_head.averageLoudness = al;};
void setLoudness(float l) {_head.loudness = l;};
void SetNewHeadTarget(float, float);
// Set what driving keys are being pressed to control thrust levels
@ -205,45 +221,38 @@ class Head : public AvatarData {
void addThrust(glm::vec3 newThrust) { _thrust += newThrust; };
glm::vec3 getThrust() { return _thrust; };
//
// Related to getting transmitter UDP data used to animate the avatar hand
//
void processTransmitterData(unsigned char * packetData, int numBytes);
float getTransmitterHz() { return _transmitterHz; };
private:
AvatarHead _head;
bool _isMine;
glm::vec3 _TEST_bigSpherePosition;
float _TEST_bigSphereRadius;
glm::vec3 _otherAvatarHandPosition[ MAX_OTHER_AVATARS ];
bool _mousePressed;
float _bodyYawDelta;
int _closestOtherAvatar;
bool _usingBodySprings;
glm::vec3 _movedHandOffset;
float _springVelocityDecay;
float _springForce;
glm::quat _rotation; // the rotation of the avatar body as a whole expressed as a quaternion
AvatarBone _bone[ NUM_AVATAR_BONES ];
AvatarMode _mode;
glm::dvec3 _velocity;
glm::vec3 _thrust;
float _maxArmLength;
Orientation _orientation;
int _numOtherAvatarsInView;
int _driveKeys[MAX_DRIVE_KEYS];
GLUquadric* _sphere;
float _renderYaw;
float _renderPitch; // Pitch from view frustum when this is own head.
//
// Related to getting transmitter UDP data used to animate the avatar hand
//
timeval _transmitterTimer;
float _transmitterHz;
int _transmitterPackets;
AvatarHead _head;
bool _isMine;
glm::vec3 _TEST_bigSpherePosition;
float _TEST_bigSphereRadius;
OtherAvatar _otherAvatar;
bool _mousePressed;
float _bodyYawDelta;
bool _nearOtherAvatar;
bool _usingBodySprings;
glm::vec3 _movedHandOffset;
float _springVelocityDecay;
float _springForce;
glm::quat _rotation; // the rotation of the avatar body as a whole expressed as a quaternion
AvatarBone _bone[ NUM_AVATAR_BONES ];
AvatarMode _mode;
AvatarHandHolding _handHolding;
glm::dvec3 _velocity;
glm::vec3 _thrust;
float _maxArmLength;
Orientation _orientation;
int _driveKeys[MAX_DRIVE_KEYS];
GLUquadric* _sphere;
float _renderYaw;
float _renderPitch; // Pitch from view frustum when this is own head
timeval _transmitterTimer;
float _transmitterHz;
int _transmitterPackets;
//-----------------------------
// private methods...
@ -253,10 +262,16 @@ class Head : public AvatarData {
void initializeBodySprings();
void updateBodySprings( float deltaTime );
void calculateBoneLengths();
void updateBigSphereCollisionTest( float deltaTime );
void readSensors();
void renderBoneAsBlock( AvatarBoneID b );
void updateAvatarCollisionDetectionAndResponse
(
glm::vec3 collisionPosition,
float collisionGirth,
float collisionHeight,
glm::vec3 collisionUpVector,
float deltaTime
);
};
#endif

View file

@ -185,7 +185,7 @@ int VoxelSystem::treeToArrays(VoxelNode *currentNode, const glm::vec3& nodePosi
int voxelsAdded = 0;
float halfUnitForVoxel = powf(0.5, *currentNode->octalCode) * (0.5 * TREE_SCALE);
glm::vec3 viewerPosition = viewerHead->getBodyPosition();
glm::vec3 viewerPosition = viewerHead->getPosition();
// debug LOD code
glm::vec3 debugNodePosition;

View file

@ -96,8 +96,6 @@ int packetsPerSecond = 0;
int bytesPerSecond = 0;
int bytesCount = 0;
int headMirror = 1; // Whether to mirror own head when viewing it
int WIDTH = 1200; // Window size
int HEIGHT = 800;
int fullscreen = 0;
@ -163,7 +161,7 @@ int noiseOn = 0; // Whether to add random noise
float noise = 1.0; // Overall magnitude scaling for random noise levels
int displayLevels = 0;
int displayHead = 0;
bool lookingInMirror = 0; // Are we currently rendering one's own head as if in mirror?
int displayField = 0;
int displayHeadMouse = 1; // Display sample mouse pointer controlled by head movement
@ -306,7 +304,7 @@ void displayStats(void)
char legend2[] = "* - toggle stars, & - toggle paint mode, '-' - send erase all, '%' - send add scene";
drawtext(10, statsVerticalOffset + 32, 0.10f, 0, 1.0, 0, legend2);
glm::vec3 avatarPos = myAvatar.getBodyPosition();
glm::vec3 avatarPos = myAvatar.getPosition();
char stats[200];
sprintf(stats, "FPS = %3.0f Pkts/s = %d Bytes/s = %d Head(x,y,z)= %4.2f, %4.2f, %4.2f ",
@ -398,8 +396,8 @@ void init(void)
if (noiseOn) {
myAvatar.setNoise(noise);
}
myAvatar.setBodyPosition(start_location);
myCamera.setPosition( start_location );
myAvatar.setPosition(start_location);
myCamera.setPosition(start_location);
#ifdef MARKER_CAPTURE
@ -440,7 +438,7 @@ void reset_sensors()
renderYawRate = 0;
renderPitchRate = 0;
myAvatar.setBodyPosition(start_location);
myAvatar.setPosition(start_location);
headMouseX = WIDTH/2;
headMouseY = HEIGHT/2;
@ -459,7 +457,7 @@ void updateAvatar(float frametime)
float gyroPitchRate = serialPort.getRelativeValue(HEAD_PITCH_RATE);
float gyroYawRate = serialPort.getRelativeValue(HEAD_YAW_RATE );
myAvatar.UpdateGyros(frametime, &serialPort, headMirror, &gravity);
myAvatar.UpdateGyros(frametime, &serialPort, &gravity);
//
// Update gyro-based mouse (X,Y on screen)
@ -553,7 +551,7 @@ void updateAvatar(float frametime)
// If I'm in paint mode, send a voxel out to VOXEL server agents.
if (::paintOn) {
glm::vec3 avatarPos = myAvatar.getBodyPosition();
glm::vec3 avatarPos = myAvatar.getPosition();
// For some reason, we don't want to flip X and Z here.
::paintingVoxel.x = avatarPos.x/10.0;
@ -819,7 +817,7 @@ void display(void)
//--------------------------------------------------------
// camera settings
//--------------------------------------------------------
if ( displayHead ) {
if ( ::lookingInMirror ) {
//-----------------------------------------------
// set the camera to looking at my own face
//-----------------------------------------------
@ -835,7 +833,7 @@ void display(void)
//----------------------------------------------------
// set the camera to third-person view behind my av
//----------------------------------------------------
myCamera.setTargetPosition ( myAvatar.getBodyPosition() );
myCamera.setTargetPosition ( myAvatar.getPosition() );
myCamera.setYaw ( 180.0 - myAvatar.getBodyYaw() );
myCamera.setPitch ( 0.0 ); // temporarily, this must be 0.0 or else bad juju
myCamera.setRoll ( 0.0 );
@ -913,7 +911,7 @@ void display(void)
drawGroundPlaneGrid( 5.0f, 9 );
// Draw cloud of dots
if (!displayHead) cloud.render();
if (!::lookingInMirror) cloud.render();
// Draw voxels
if ( showingVoxels )
@ -935,16 +933,16 @@ void display(void)
}
}
if ( !displayHead ) balls.render();
if ( !::lookingInMirror ) balls.render();
// Render the world box
if (!displayHead && statsOn) render_world_box();
if (!::lookingInMirror && statsOn) render_world_box();
// brad's frustum for debugging
if (::frustumOn) renderViewFrustum(::viewFrustum);
//Render my own avatar
myAvatar.render(true);
myAvatar.render(::lookingInMirror);
}
glPopMatrix();
@ -962,7 +960,7 @@ void display(void)
if (audioScope.getState()) audioScope.render();
#endif
if (displayHeadMouse && !displayHead && statsOn) {
if (displayHeadMouse && !::lookingInMirror && statsOn) {
// Display small target box at center or head mouse target that can also be used to measure LOD
glColor3f(1.0, 1.0, 1.0);
glDisable(GL_LINE_SMOOTH);
@ -1058,7 +1056,7 @@ int setValue(int state, bool *value) {
}
int setHead(int state) {
return setValue(state, &displayHead);
return setValue(state, &::lookingInMirror);
}
int setField(int state) {
@ -1091,10 +1089,6 @@ int setMenu(int state) {
return setValue(state, &::menuOn);
}
int setMirror(int state) {
return setValue(state, &headMirror);
}
int setDisplayFrustum(int state) {
return setValue(state, &::frustumOn);
}
@ -1200,10 +1194,9 @@ void initMenu() {
MenuColumn *menuColumnOptions, *menuColumnTools, *menuColumnDebug, *menuColumnFrustum;
// Options
menuColumnOptions = menu.addColumn("Options");
menuColumnOptions->addRow("(H)ead", setHead);
menuColumnOptions->addRow("Mirror (h)", setHead);
menuColumnOptions->addRow("Field (f)", setField);
menuColumnOptions->addRow("(N)oise", setNoise);
menuColumnOptions->addRow("Mirror", setMirror);
menuColumnOptions->addRow("(V)oxels", setVoxels);
menuColumnOptions->addRow("Stars (*)", setStars);
menuColumnOptions->addRow("(Q)uit", quitApp);
@ -1273,7 +1266,7 @@ void shiftPaintingColor()
}
void setupPaintingVoxel() {
glm::vec3 avatarPos = myAvatar.getBodyPosition();
glm::vec3 avatarPos = myAvatar.getPosition();
::paintingVoxel.x = avatarPos.z/-10.0; // voxel space x is negative z head space
::paintingVoxel.y = avatarPos.y/-10.0; // voxel space y is negative y head space
@ -1412,9 +1405,9 @@ void key(unsigned char k, int x, int y)
}
if (k == 'h') {
displayHead = !displayHead;
::lookingInMirror = !::lookingInMirror;
#ifndef _WIN32
audio.setMixerLoopbackFlag(displayHead);
audio.setMixerLoopbackFlag(::lookingInMirror);
#endif
}
@ -1502,7 +1495,7 @@ void idle(void) {
//
updateAvatar(deltaTime);
//loop through all the other avatars and simulate them.
//loop through all the other avatars and simulate them...
AgentList * agentList = AgentList::getInstance();
for(std::vector<Agent>::iterator agent = agentList->getAgents().begin(); agent != agentList->getAgents().end(); agent++)
{
@ -1520,7 +1513,6 @@ void idle(void) {
glutPostRedisplay();
lastTimeIdle = check;
}
// Read serial data

View file

@ -34,9 +34,14 @@ int unpackFloatAngleFromTwoByte(uint16_t* byteAnglePointer, float* destinationPo
}
AvatarData::AvatarData() :
_handPosition(0,0,0),
_bodyYaw(-90.0),
_bodyPitch(0.0),
_bodyRoll(0.0),
_headYaw(0),
_headPitch(0),
_headRoll(0),
_handState(0),
_cameraPosition(0,0,0),
_cameraDirection(0,0,0),
_cameraUp(0,0,0),
@ -63,15 +68,31 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
// that can pack any type given the number of bytes
// and return the number of bytes to push the pointer
memcpy(destinationBuffer, &_bodyPosition, sizeof(float) * 3);
// Body world position
memcpy(destinationBuffer, &_position, sizeof(float) * 3);
destinationBuffer += sizeof(float) * 3;
// Body rotation (NOTE: This needs to become a quaternion to save two bytes)
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _bodyYaw);
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _bodyPitch);
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _bodyRoll);
// Head rotation (NOTE: This needs to become a quaternion to save two bytes)
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headYaw);
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headPitch);
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headRoll);
// Hand Position
memcpy(destinationBuffer, &_handPosition, sizeof(float) * 3);
destinationBuffer += sizeof(float) * 3;
// Hand State (0 = not grabbing, 1 = grabbing)
memcpy(destinationBuffer, &_handState, sizeof(char));
destinationBuffer += sizeof(char);
// Instantaneous audio loudness (used to drive facial animation)
memcpy(destinationBuffer, &_audioLoudness, sizeof(float));
destinationBuffer += sizeof(float);
// camera details
memcpy(destinationBuffer, &_cameraPosition, sizeof(_cameraPosition));
@ -91,6 +112,7 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
memcpy(destinationBuffer, &_cameraFarClip, sizeof(_cameraFarClip));
destinationBuffer += sizeof(_cameraFarClip);
return destinationBuffer - bufferStart;
}
@ -102,16 +124,32 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
unsigned char* startPosition = sourceBuffer;
memcpy(&_bodyPosition, sourceBuffer, sizeof(float) * 3);
// Body world position
memcpy(&_position, sourceBuffer, sizeof(float) * 3);
sourceBuffer += sizeof(float) * 3;
// Body rotation (NOTE: This needs to become a quaternion to save two bytes)
sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t *)sourceBuffer, &_bodyYaw);
sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t *)sourceBuffer, &_bodyPitch);
sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t *)sourceBuffer, &_bodyRoll);
// Head rotation (NOTE: This needs to become a quaternion to save two bytes)
sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t *)sourceBuffer, &_headYaw);
sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t *)sourceBuffer, &_headPitch);
sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t *)sourceBuffer, &_headRoll);
// Hand Position
memcpy(&_handPosition, sourceBuffer, sizeof(float) * 3);
sourceBuffer += sizeof(float) * 3;
// Hand State
memcpy(&_handState, sourceBuffer, sizeof(char));
sourceBuffer += sizeof(char);
// Instantaneous audio loudness (used to drive facial animation)
memcpy(&_audioLoudness, sourceBuffer, sizeof(float));
sourceBuffer += sizeof(float);
// camera details
memcpy(&_cameraPosition, sourceBuffer, sizeof(_cameraPosition));
sourceBuffer += sizeof(_cameraPosition);
@ -133,14 +171,14 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
return sourceBuffer - startPosition;
}
glm::vec3 AvatarData::getBodyPosition() {
return glm::vec3(_bodyPosition.x,
_bodyPosition.y,
_bodyPosition.z);
glm::vec3 AvatarData::getPosition() {
return glm::vec3(_position.x,
_position.y,
_position.z);
}
void AvatarData::setBodyPosition(glm::vec3 bodyPosition) {
_bodyPosition = bodyPosition;
void AvatarData::setPosition(glm::vec3 position) {
_position = position;
}
void AvatarData::setHandPosition(glm::vec3 handPosition) {

View file

@ -20,23 +20,41 @@ public:
AvatarData* clone() const;
glm::vec3 getBodyPosition();
void setBodyPosition(glm::vec3 bodyPosition);
glm::vec3 getPosition();
void setPosition(glm::vec3 position);
void setHandPosition(glm::vec3 handPosition);
int getBroadcastData(unsigned char* destinationBuffer);
int parseData(unsigned char* sourceBuffer, int numBytes);
// Body Rotation
float getBodyYaw();
void setBodyYaw(float bodyYaw);
float getBodyPitch();
void setBodyPitch(float bodyPitch);
float getBodyRoll();
void setBodyYaw(float bodyYaw);
void setBodyPitch(float bodyPitch);
void setBodyRoll(float bodyRoll);
// getters for camera details
// Head Rotation
void setHeadPitch(float p) {_headPitch = p; }
void setHeadYaw(float y) {_headYaw = y; }
void setHeadRoll(float r) {_headRoll = r; };
const float getHeadPitch() const { return _headPitch; };
const float getHeadYaw() const { return _headYaw; };
const float getHeadRoll() const { return _headRoll; };
void addHeadPitch(float p) {_headPitch -= p; }
void addHeadYaw(float y){_headYaw -= y; }
void addHeadRoll(float r){_headRoll += r; }
// Hand State
void setHandState(char s) { _handState = s; };
const float getHandState() const {return _handState; }; //@Philip - shouldn't this be an int or a char?
// Instantaneous audio loudness to drive mouth/facial animation
void setLoudness(float l) { _audioLoudness = l; };
const float getLoudness() const {return _audioLoudness; };
// getters for camera details
const glm::vec3& getCameraPosition() const { return _cameraPosition; };
const glm::vec3& getCameraDirection() const { return _cameraDirection; }
const glm::vec3& getCameraUp() const { return _cameraUp; }
@ -57,13 +75,25 @@ public:
void setCameraFarClip(float farClip) { _cameraFarClip = farClip; }
protected:
glm::vec3 _bodyPosition;
glm::vec3 _position;
glm::vec3 _handPosition;
// Body rotation
float _bodyYaw;
float _bodyPitch;
float _bodyRoll;
// Head rotation (relative to body)
float _headYaw;
float _headPitch;
float _headRoll;
// Audio loudness (used to drive facial animation)
float _audioLoudness;
// Hand state (are we grabbing something or not)
char _handState;
// camera details for the avatar
glm::vec3 _cameraPosition;

View file

@ -24,7 +24,7 @@
using shared_lib::printLog;
const char SOLO_AGENT_TYPES_STRING[] = {
const char SOLO_AGENT_TYPES[3] = {
AGENT_TYPE_AVATAR_MIXER,
AGENT_TYPE_AUDIO_MIXER,
AGENT_TYPE_VOXEL
@ -305,8 +305,8 @@ void AgentList::handlePingReply(sockaddr *agentAddress) {
}
}
Agent* AgentList::soloAgentOfType(char agentType) {
if (memchr(SOLO_AGENT_TYPES_STRING, agentType, 1)) {
Agent* AgentList::soloAgentOfType(char agentType) {
if (memchr(SOLO_AGENT_TYPES, agentType, sizeof(SOLO_AGENT_TYPES)) != NULL) {
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) {
if (agent->getType() == agentType) {
return &*agent;
@ -428,7 +428,7 @@ void *checkInWithDomainServer(void *args) {
sockaddr_in tempAddress;
memcpy(&tempAddress.sin_addr, pHostInfo->h_addr_list[0], pHostInfo->h_length);
strcpy(DOMAIN_IP, inet_ntoa(tempAddress.sin_addr));
printLog("Domain server: %s \n", DOMAIN_HOSTNAME);
printLog("Domain server: %s - %s\n", DOMAIN_HOSTNAME, DOMAIN_IP);
} else {
printLog("Failed lookup domainserver\n");

View file

@ -22,7 +22,7 @@
const int MAX_PACKET_SIZE = 1500;
const unsigned int AGENT_SOCKET_LISTEN_PORT = 40103;
const int AGENT_SILENCE_THRESHOLD_USECS = 2 * 1000000;
extern const char SOLO_AGENT_TYPES_STRING[];
extern const char SOLO_AGENT_TYPES[3];
extern char DOMAIN_HOSTNAME[];
extern char DOMAIN_IP[100]; // IP Address will be re-set by lookup on startup

View file

@ -0,0 +1,103 @@
//
// AudioInjector.cpp
// hifi
//
// Created by Stephen Birarda on 4/23/13.
//
//
#include <sys/time.h>
#include <fstream>
#include <cstring>
#include "SharedUtil.h"
#include "PacketHeaders.h"
#include "AudioInjector.h"
const int BUFFER_LENGTH_BYTES = 512;
const int BUFFER_LENGTH_SAMPLES = BUFFER_LENGTH_BYTES / sizeof(int16_t);
const float SAMPLE_RATE = 22050.0f;
const float BUFFER_SEND_INTERVAL_USECS = (BUFFER_LENGTH_SAMPLES / SAMPLE_RATE) * 1000000;
AudioInjector::AudioInjector(const char* filename) :
_numTotalBytesAudio(0),
_bearing(0),
_attenuationModifier(255)
{
_position[0] = 0.0f;
_position[1] = 0.0f;
_position[2] = 0.0f;
std::fstream sourceFile;
sourceFile.open(filename, std::ios::in | std::ios::binary);
sourceFile.seekg(0, std::ios::end);
_numTotalBytesAudio = sourceFile.tellg();
if (_numTotalBytesAudio == -1) {
printf("Error reading audio data from file %s\n", filename);
_audioSampleArray = NULL;
} else {
printf("Read %d bytes from audio file\n", _numTotalBytesAudio);
sourceFile.seekg(0, std::ios::beg);
long sizeOfShortArray = _numTotalBytesAudio / 2;
_audioSampleArray = new int16_t[sizeOfShortArray];
sourceFile.read((char *)_audioSampleArray, _numTotalBytesAudio);
}
}
AudioInjector::~AudioInjector() {
delete[] _audioSampleArray;
}
void AudioInjector::setPosition(float* position) {
_position[0] = position[0];
_position[1] = position[1];
_position[2] = position[2];
}
void AudioInjector::injectAudio(UDPSocket* injectorSocket, sockaddr* destinationSocket) const {
if (_audioSampleArray != NULL) {
timeval startTime;
// one byte for header, 3 positional floats, 1 bearing float, 1 attenuation modifier byte
int leadingBytes = 1 + (sizeof(float) * 4) + 1;
unsigned char dataPacket[BUFFER_LENGTH_BYTES + leadingBytes];
dataPacket[0] = PACKET_HEADER_INJECT_AUDIO;
unsigned char *currentPacketPtr = dataPacket + 1;
for (int i = 0; i < 3; i++) {
memcpy(currentPacketPtr, &_position[i], sizeof(float));
currentPacketPtr += sizeof(float);
}
*currentPacketPtr = _attenuationModifier;
currentPacketPtr++;
memcpy(currentPacketPtr, &_bearing, sizeof(float));
currentPacketPtr += sizeof(float);
for (int i = 0; i < _numTotalBytesAudio; i += BUFFER_LENGTH_BYTES) {
gettimeofday(&startTime, NULL);
int numBytesToCopy = BUFFER_LENGTH_BYTES;
if (_numTotalBytesAudio - i < BUFFER_LENGTH_BYTES) {
numBytesToCopy = _numTotalBytesAudio - i;
memset(currentPacketPtr + numBytesToCopy, 0, BUFFER_LENGTH_BYTES - numBytesToCopy);
}
memcpy(currentPacketPtr, _audioSampleArray + (i / 2), numBytesToCopy);
injectorSocket->send(destinationSocket, dataPacket, sizeof(dataPacket));
double usecToSleep = BUFFER_SEND_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&startTime));
if (usecToSleep > 0) {
usleep(usecToSleep);
}
}
}
}

View file

@ -0,0 +1,35 @@
//
// AudioInjector.h
// hifi
//
// Created by Stephen Birarda on 4/23/13.
//
//
#ifndef __hifi__AudioInjector__
#define __hifi__AudioInjector__
#include <iostream>
#include <netinet/in.h>
#include "UDPSocket.h"
class AudioInjector {
public:
AudioInjector(const char* filename);
~AudioInjector();
void setPosition(float* position);
void setBearing(float bearing) { _bearing = bearing; }
void setAttenuationModifier(unsigned char attenuationModifier) { _attenuationModifier = attenuationModifier; }
void injectAudio(UDPSocket* injectorSocket, sockaddr* destinationSocket) const;
private:
int16_t* _audioSampleArray;
int _numTotalBytesAudio;
float _position[3];
float _bearing;
unsigned char _attenuationModifier;
};
#endif /* defined(__hifi__AudioInjector__) */

View file

@ -19,7 +19,7 @@ VoxelAgentData::~VoxelAgentData() {
}
VoxelAgentData::VoxelAgentData(const VoxelAgentData &otherAgentData) {
memcpy(&_bodyPosition, &otherAgentData._bodyPosition, sizeof(_bodyPosition));
memcpy(&_position, &otherAgentData._position, sizeof(_position));
rootMarkerNode = new MarkerNode();
}

View file

@ -199,7 +199,7 @@ void *distributeVoxelsToListeners(void *args) {
stopOctal = randomTree.loadBitstreamBuffer(voxelPacketEnd,
randomTree.rootNode,
agentData->rootMarkerNode,
agentData->getBodyPosition(),
agentData->getPosition(),
treeRoot,
viewFrustum,
::viewFrustumCulling,