mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 20:44:14 +02:00
Merge branch 'master' of https://github.com/worklist/hifi into reorient
Conflicts: interface/src/Avatar.cpp
This commit is contained in:
commit
9b301eb235
17 changed files with 341 additions and 72 deletions
|
@ -33,6 +33,7 @@ bool includeBillboard = true;
|
|||
bool includeBorderTracer = true;
|
||||
bool includeMovingBug = true;
|
||||
bool includeBlinkingVoxel = false;
|
||||
bool includeDanceFloor = true;
|
||||
|
||||
|
||||
const int ANIMATION_LISTEN_PORT = 40107;
|
||||
|
@ -392,6 +393,131 @@ static void sendBlinkingStringOfLights() {
|
|||
}
|
||||
}
|
||||
|
||||
bool danceFloorInitialized = false;
|
||||
const float DANCE_FLOOR_LIGHT_SIZE = 1.0f / TREE_SCALE; // approximately 1 meter
|
||||
const int DANCE_FLOOR_LENGTH = 10;
|
||||
const int DANCE_FLOOR_WIDTH = 10;
|
||||
glm::vec3 danceFloorPosition(100.0f / TREE_SCALE, 30.0f / TREE_SCALE, 10.0f / TREE_SCALE);
|
||||
glm::vec3 danceFloorLights[DANCE_FLOOR_LENGTH][DANCE_FLOOR_WIDTH];
|
||||
unsigned char danceFloorOffColor[3] = { 240, 240, 240 };
|
||||
const int DANCE_FLOOR_COLORS = 6;
|
||||
|
||||
unsigned char danceFloorOnColorA[DANCE_FLOOR_COLORS][3] = {
|
||||
{ 255, 0, 0 }, { 0, 255, 0 }, { 0, 0, 255 },
|
||||
{ 0, 191, 255 }, { 0, 250, 154 }, { 255, 69, 0 },
|
||||
};
|
||||
unsigned char danceFloorOnColorB[DANCE_FLOOR_COLORS][3] = {
|
||||
{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } ,
|
||||
{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }
|
||||
};
|
||||
float danceFloorGradient = 0.5f;
|
||||
const float BEATS_PER_MINUTE = 118.0f;
|
||||
const float SECONDS_PER_MINUTE = 60.0f;
|
||||
const float FRAMES_PER_BEAT = (SECONDS_PER_MINUTE * ACTUAL_FPS) / BEATS_PER_MINUTE;
|
||||
float danceFloorGradientIncrement = 1.0f / FRAMES_PER_BEAT;
|
||||
const float DANCE_FLOOR_MAX_GRADIENT = 1.0f;
|
||||
const float DANCE_FLOOR_MIN_GRADIENT = 0.0f;
|
||||
const int DANCE_FLOOR_VOXELS_PER_PACKET = 100;
|
||||
const int PACKETS_PER_DANCE_FLOOR = DANCE_FLOOR_VOXELS_PER_PACKET / (DANCE_FLOOR_WIDTH * DANCE_FLOOR_LENGTH);
|
||||
int danceFloorColors[DANCE_FLOOR_WIDTH][DANCE_FLOOR_LENGTH];
|
||||
|
||||
void sendDanceFloor() {
|
||||
PACKET_HEADER message = PACKET_HEADER_SET_VOXEL_DESTRUCTIVE; // we're a bully!
|
||||
float lightScale = DANCE_FLOOR_LIGHT_SIZE;
|
||||
static VoxelDetail details[DANCE_FLOOR_VOXELS_PER_PACKET];
|
||||
unsigned char* bufferOut;
|
||||
int sizeOut;
|
||||
|
||||
// first initialized the billboard of lights if needed...
|
||||
if (!::danceFloorInitialized) {
|
||||
for (int i = 0; i < DANCE_FLOOR_WIDTH; i++) {
|
||||
for (int j = 0; j < DANCE_FLOOR_LENGTH; j++) {
|
||||
|
||||
int randomColorIndex = randIntInRange( -(DANCE_FLOOR_COLORS), (DANCE_FLOOR_COLORS + 1));
|
||||
::danceFloorColors[i][j] = randomColorIndex;
|
||||
::danceFloorLights[i][j] = ::danceFloorPosition +
|
||||
glm::vec3(i * DANCE_FLOOR_LIGHT_SIZE, 0, j * DANCE_FLOOR_LIGHT_SIZE);
|
||||
}
|
||||
}
|
||||
::danceFloorInitialized = true;
|
||||
}
|
||||
|
||||
::danceFloorGradient += ::danceFloorGradientIncrement;
|
||||
|
||||
if (::danceFloorGradient >= DANCE_FLOOR_MAX_GRADIENT) {
|
||||
::danceFloorGradient = DANCE_FLOOR_MAX_GRADIENT;
|
||||
::danceFloorGradientIncrement = -::danceFloorGradientIncrement;
|
||||
}
|
||||
if (::danceFloorGradient <= DANCE_FLOOR_MIN_GRADIENT) {
|
||||
::danceFloorGradient = DANCE_FLOOR_MIN_GRADIENT;
|
||||
::danceFloorGradientIncrement = -::danceFloorGradientIncrement;
|
||||
}
|
||||
|
||||
for (int i = 0; i < DANCE_FLOOR_LENGTH; i++) {
|
||||
for (int j = 0; j < DANCE_FLOOR_WIDTH; j++) {
|
||||
|
||||
int nthVoxel = ((i * DANCE_FLOOR_WIDTH) + j);
|
||||
int item = nthVoxel % DANCE_FLOOR_VOXELS_PER_PACKET;
|
||||
|
||||
::danceFloorLights[i][j] = ::danceFloorPosition +
|
||||
glm::vec3(i * DANCE_FLOOR_LIGHT_SIZE, 0, j * DANCE_FLOOR_LIGHT_SIZE);
|
||||
|
||||
details[item].s = lightScale;
|
||||
details[item].x = ::danceFloorLights[i][j].x;
|
||||
details[item].y = ::danceFloorLights[i][j].y;
|
||||
details[item].z = ::danceFloorLights[i][j].z;
|
||||
|
||||
if (danceFloorColors[i][j] > 0) {
|
||||
int color = danceFloorColors[i][j] - 1;
|
||||
details[item].red = (::danceFloorOnColorA[color][0] +
|
||||
((::danceFloorOnColorB[color][0] - ::danceFloorOnColorA[color][0])
|
||||
* ::danceFloorGradient));
|
||||
details[item].green = (::danceFloorOnColorA[color][1] +
|
||||
((::danceFloorOnColorB[color][1] - ::danceFloorOnColorA[color][1])
|
||||
* ::danceFloorGradient));
|
||||
details[item].blue = (::danceFloorOnColorA[color][2] +
|
||||
((::danceFloorOnColorB[color][2] - ::danceFloorOnColorA[color][2])
|
||||
* ::danceFloorGradient));
|
||||
} else if (::danceFloorColors[i][j] < 0) {
|
||||
int color = -(::danceFloorColors[i][j] + 1);
|
||||
details[item].red = (::danceFloorOnColorB[color][0] +
|
||||
((::danceFloorOnColorA[color][0] - ::danceFloorOnColorB[color][0])
|
||||
* ::danceFloorGradient));
|
||||
details[item].green = (::danceFloorOnColorB[color][1] +
|
||||
((::danceFloorOnColorA[color][1] - ::danceFloorOnColorB[color][1])
|
||||
* ::danceFloorGradient));
|
||||
details[item].blue = (::danceFloorOnColorB[color][2] +
|
||||
((::danceFloorOnColorA[color][2] - ::danceFloorOnColorB[color][2])
|
||||
* ::danceFloorGradient));
|
||||
} else {
|
||||
int color = 0;
|
||||
details[item].red = (::danceFloorOnColorB[color][0] +
|
||||
((::danceFloorOnColorA[color][0] - ::danceFloorOnColorB[color][0])
|
||||
* ::danceFloorGradient));
|
||||
details[item].green = (::danceFloorOnColorB[color][1] +
|
||||
((::danceFloorOnColorA[color][1] - ::danceFloorOnColorB[color][1])
|
||||
* ::danceFloorGradient));
|
||||
details[item].blue = (::danceFloorOnColorB[color][2] +
|
||||
((::danceFloorOnColorA[color][2] - ::danceFloorOnColorB[color][2])
|
||||
* ::danceFloorGradient));
|
||||
}
|
||||
|
||||
if (item == DANCE_FLOOR_VOXELS_PER_PACKET - 1) {
|
||||
if (createVoxelEditMessage(message, 0, DANCE_FLOOR_VOXELS_PER_PACKET,
|
||||
(VoxelDetail*)&details, bufferOut, sizeOut)){
|
||||
::packetsSent++;
|
||||
::bytesSent += sizeOut;
|
||||
if (::shouldShowPacketsPerSecond) {
|
||||
printf("sending packet of size=%d\n", sizeOut);
|
||||
}
|
||||
AgentList::getInstance()->broadcastToAgents(bufferOut, sizeOut, &AGENT_TYPE_VOXEL, 1);
|
||||
delete[] bufferOut;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool billboardInitialized = false;
|
||||
const int BILLBOARD_HEIGHT = 9;
|
||||
const int BILLBOARD_WIDTH = 45;
|
||||
|
@ -405,7 +531,7 @@ float billboardGradientIncrement = 0.01f;
|
|||
const float BILLBOARD_MAX_GRADIENT = 1.0f;
|
||||
const float BILLBOARD_MIN_GRADIENT = 0.0f;
|
||||
const float BILLBOARD_LIGHT_SIZE = 0.125f / TREE_SCALE; // approximately 1/8 meter per light
|
||||
const int VOXELS_PER_PACKET = 135;
|
||||
const int VOXELS_PER_PACKET = 100;
|
||||
const int PACKETS_PER_BILLBOARD = VOXELS_PER_PACKET / (BILLBOARD_HEIGHT * BILLBOARD_WIDTH);
|
||||
|
||||
|
||||
|
@ -514,6 +640,9 @@ void* animateVoxels(void* args) {
|
|||
if (::includeBlinkingVoxel) {
|
||||
sendVoxelBlinkMessage();
|
||||
}
|
||||
if (::includeDanceFloor) {
|
||||
sendDanceFloor();
|
||||
}
|
||||
|
||||
double end = usecTimestampNow();
|
||||
double elapsedSeconds = (end - ::start) / 1000000.0;
|
||||
|
@ -555,6 +684,9 @@ int main(int argc, const char * argv[])
|
|||
const char* INCLUDE_BLINKING_VOXEL = "--includeBlinkingVoxel";
|
||||
::includeBlinkingVoxel = cmdOptionExists(argc, argv, INCLUDE_BLINKING_VOXEL);
|
||||
|
||||
const char* NO_DANCE_FLOOR = "--NoDanceFloor";
|
||||
::includeDanceFloor = !cmdOptionExists(argc, argv, NO_DANCE_FLOOR);
|
||||
|
||||
// Handle Local Domain testing with the --local command line
|
||||
const char* showPPS = "--showPPS";
|
||||
::shouldShowPacketsPerSecond = cmdOptionExists(argc, argv, showPPS);
|
||||
|
|
|
@ -55,7 +55,7 @@ const float BUFFER_SEND_INTERVAL_USECS = (BUFFER_LENGTH_SAMPLES_PER_CHANNEL / SA
|
|||
const long MAX_SAMPLE_VALUE = std::numeric_limits<int16_t>::max();
|
||||
const long MIN_SAMPLE_VALUE = std::numeric_limits<int16_t>::min();
|
||||
|
||||
const float DISTANCE_RATIO = 3.0f / 0.3f;
|
||||
const float DISTANCE_SCALE = 2.5f;
|
||||
const float PHASE_AMPLITUDE_RATIO_AT_90 = 0.5;
|
||||
const int PHASE_DELAY_AT_90 = 20;
|
||||
|
||||
|
@ -166,8 +166,8 @@ int main(int argc, const char* argv[]) {
|
|||
powf(agentPosition.z - otherAgentPosition.z, 2));
|
||||
|
||||
float minCoefficient = std::min(1.0f,
|
||||
powf(0.5,
|
||||
(logf(DISTANCE_RATIO * distanceToAgent) / logf(2.5))
|
||||
powf(0.3,
|
||||
(logf(DISTANCE_SCALE * distanceToAgent) / logf(2.5))
|
||||
- 1));
|
||||
distanceCoefficients[lowAgentIndex][highAgentIndex] = minCoefficient;
|
||||
}
|
||||
|
@ -214,8 +214,8 @@ int main(int argc, const char* argv[]) {
|
|||
(OFF_AXIS_ATTENUATION_FORMULA_STEP * (fabsf(angleOfDelivery) / 90.0f));
|
||||
|
||||
attenuationCoefficient = distanceCoefficients[lowAgentIndex][highAgentIndex]
|
||||
* otherAgentBuffer->getAttenuationRatio()
|
||||
* offAxisCoefficient;
|
||||
* otherAgentBuffer->getAttenuationRatio()
|
||||
* offAxisCoefficient;
|
||||
|
||||
bearingRelativeAngleToSource *= (M_PI / 180);
|
||||
|
||||
|
@ -225,15 +225,15 @@ int main(int argc, const char* argv[]) {
|
|||
}
|
||||
|
||||
int16_t* goodChannel = bearingRelativeAngleToSource > 0.0f
|
||||
? clientSamples + BUFFER_LENGTH_SAMPLES_PER_CHANNEL
|
||||
: clientSamples;
|
||||
? clientSamples + BUFFER_LENGTH_SAMPLES_PER_CHANNEL
|
||||
: clientSamples;
|
||||
int16_t* delayedChannel = bearingRelativeAngleToSource > 0.0f
|
||||
? clientSamples
|
||||
: clientSamples + BUFFER_LENGTH_SAMPLES_PER_CHANNEL;
|
||||
? clientSamples
|
||||
: clientSamples + BUFFER_LENGTH_SAMPLES_PER_CHANNEL;
|
||||
|
||||
int16_t* delaySamplePointer = otherAgentBuffer->getNextOutput() == otherAgentBuffer->getBuffer()
|
||||
? otherAgentBuffer->getBuffer() + RING_BUFFER_SAMPLES - numSamplesDelay
|
||||
: otherAgentBuffer->getNextOutput() - numSamplesDelay;
|
||||
? otherAgentBuffer->getBuffer() + RING_BUFFER_SAMPLES - numSamplesDelay
|
||||
: otherAgentBuffer->getNextOutput() - numSamplesDelay;
|
||||
|
||||
for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) {
|
||||
|
||||
|
@ -246,7 +246,7 @@ int main(int argc, const char* argv[]) {
|
|||
int16_t currentSample = (otherAgentBuffer->getNextOutput()[s] * attenuationCoefficient);
|
||||
plateauAdditionOfSamples(goodChannel[s], currentSample);
|
||||
|
||||
if (s + numSamplesDelay < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) {
|
||||
if (s + numSamplesDelay < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) {
|
||||
plateauAdditionOfSamples(delayedChannel[s + numSamplesDelay],
|
||||
currentSample * weakChannelAmplitudeRatio);
|
||||
}
|
||||
|
@ -287,6 +287,11 @@ int main(int argc, const char* argv[]) {
|
|||
}
|
||||
|
||||
agentList->updateAgentWithData(agentAddress, packetData, receivedBytes);
|
||||
|
||||
if (std::isnan(((AudioRingBuffer *)avatarAgent->getLinkedData())->getBearing())) {
|
||||
// kill off this agent - temporary solution to mixer crash on mac sleep
|
||||
avatarAgent->setAlive(false);
|
||||
}
|
||||
} else if (packetData[0] == PACKET_HEADER_INJECT_AUDIO) {
|
||||
Agent* matchingInjector = NULL;
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ int main(int argc, const char* argv[]) {
|
|||
|
||||
// parse positional data from an agent
|
||||
agentList->updateAgentWithData(avatarAgent, packetData, receivedBytes);
|
||||
|
||||
case PACKET_HEADER_INJECT_AUDIO:
|
||||
currentBufferPosition = broadcastPacket + 1;
|
||||
|
||||
// send back a packet with other active agent data to this agent
|
||||
|
|
|
@ -204,6 +204,4 @@ int main(int argc, const char* argv[]) {
|
|||
agentList->stopDomainServerCheckInThread();
|
||||
agentList->stopPingUnknownAgentsThread();
|
||||
agentList->stopSilentAgentRemovalThread();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -18,4 +18,5 @@ include_glm(${TARGET_NAME} ${ROOT_DIR})
|
|||
# link the shared hifi library
|
||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR})
|
||||
link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR})
|
|
@ -14,14 +14,16 @@
|
|||
#include <string.h>
|
||||
#include <sstream>
|
||||
|
||||
#include <AgentList.h>
|
||||
#include <AgentTypes.h>
|
||||
#include <AvatarData.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <UDPSocket.h>
|
||||
#include <AudioInjector.h>
|
||||
#include <AudioInjectionManager.h>
|
||||
|
||||
char EC2_WEST_AUDIO_SERVER[] = "54.241.92.53";
|
||||
const int AUDIO_UDP_LISTEN_PORT = 55443;
|
||||
const int AVATAR_MIXER_DATA_SEND_INTERVAL_MSECS = 15;
|
||||
|
||||
const int DEFAULT_INJECTOR_VOLUME = 0xFF;
|
||||
|
||||
|
@ -30,12 +32,12 @@ bool loopAudio = true;
|
|||
float sleepIntervalMin = 1.00;
|
||||
float sleepIntervalMax = 2.00;
|
||||
char *sourceAudioFile = NULL;
|
||||
const char *allowedParameters = ":rb::t::c::a::f:";
|
||||
const char *allowedParameters = ":rb::t::c::a::f::d:";
|
||||
float floatArguments[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
unsigned char volume = DEFAULT_INJECTOR_VOLUME;
|
||||
float triggerDistance = 0;
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
void usage(void) {
|
||||
std::cout << "High Fidelity - Interface audio injector" << std::endl;
|
||||
std::cout << " -r Random sleep mode. If not specified will default to constant loop." << std::endl;
|
||||
std::cout << " -b FLOAT Min. number of seconds to sleep. Only valid in random sleep mode. Default 1.0" << std::endl;
|
||||
|
@ -43,10 +45,10 @@ void usage(void)
|
|||
std::cout << " -c FLOAT,FLOAT,FLOAT,FLOAT X,Y,Z,YAW position in universe where audio will be originating from and direction. Defaults to 0,0,0,0" << std::endl;
|
||||
std::cout << " -a 0-255 Attenuation curve modifier, defaults to 255" << std::endl;
|
||||
std::cout << " -f FILENAME Name of audio source file. Required - RAW format, 22050hz 16bit signed mono" << std::endl;
|
||||
std::cout << " -d FLOAT Trigger distance for injection. If not specified will loop constantly" << std::endl;
|
||||
}
|
||||
|
||||
bool processParameters(int parameterCount, char* parameterData[])
|
||||
{
|
||||
bool processParameters(int parameterCount, char* parameterData[]) {
|
||||
int p;
|
||||
while ((p = getopt(parameterCount, parameterData, allowedParameters)) != -1) {
|
||||
switch (p) {
|
||||
|
@ -86,6 +88,10 @@ bool processParameters(int parameterCount, char* parameterData[])
|
|||
::volume = atoi(optarg);
|
||||
std::cout << "[DEBUG] Attenuation modifier: " << optarg << std::endl;
|
||||
break;
|
||||
case 'd':
|
||||
::triggerDistance = atof(optarg);
|
||||
std::cout << "[DEBUG] Trigger distance: " << optarg << std::endl;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
return false;
|
||||
|
@ -94,45 +100,149 @@ bool processParameters(int parameterCount, char* parameterData[])
|
|||
return true;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
bool stopReceiveAgentDataThread;
|
||||
|
||||
void *receiveAgentData(void *args) {
|
||||
sockaddr senderAddress;
|
||||
ssize_t bytesReceived;
|
||||
unsigned char incomingPacket[MAX_PACKET_SIZE];
|
||||
|
||||
AgentList* agentList = AgentList::getInstance();
|
||||
|
||||
while (!::stopReceiveAgentDataThread) {
|
||||
if (agentList->getAgentSocket()->receive(&senderAddress, incomingPacket, &bytesReceived)) {
|
||||
switch (incomingPacket[0]) {
|
||||
case PACKET_HEADER_BULK_AVATAR_DATA:
|
||||
// this is the positional data for other agents
|
||||
// pass that off to the agentList processBulkAgentData method
|
||||
agentList->processBulkAgentData(&senderAddress, incomingPacket, bytesReceived);
|
||||
break;
|
||||
default:
|
||||
// have the agentList handle list of agents from DS, replies from other agents, etc.
|
||||
agentList->processAgentData(&senderAddress, incomingPacket, bytesReceived);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pthread_exit(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void createAvatarDataForAgent(Agent* agent) {
|
||||
if (!agent->getLinkedData()) {
|
||||
agent->setLinkedData(new AvatarData(agent));
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// new seed for random audio sleep times
|
||||
srand(time(0));
|
||||
|
||||
int AUDIO_UDP_SEND_PORT = 1500 + (rand() % (int)(1500 - 2000 + 1));
|
||||
|
||||
UDPSocket streamSocket(AUDIO_UDP_SEND_PORT);
|
||||
|
||||
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 (processParameters(argc, argv)) {
|
||||
if (::sourceAudioFile == NULL) {
|
||||
std::cout << "[FATAL] Source audio file not specified" << std::endl;
|
||||
exit(-1);
|
||||
} else {
|
||||
AudioInjector injector(sourceAudioFile);
|
||||
|
||||
// create an AgentList instance to handle communication with other agents
|
||||
AgentList* agentList = AgentList::createInstance(AGENT_TYPE_AUDIO_INJECTOR, AUDIO_UDP_SEND_PORT);
|
||||
|
||||
pthread_t receiveAgentDataThread;
|
||||
pthread_create(&receiveAgentDataThread, NULL, receiveAgentData, NULL);
|
||||
|
||||
// start telling the domain server that we are alive
|
||||
agentList->startDomainServerCheckInThread();
|
||||
|
||||
// start the agent list thread that will kill off agents when they stop talking
|
||||
agentList->startSilentAgentRemovalThread();
|
||||
|
||||
injector.setPosition(glm::vec3(::floatArguments[0], ::floatArguments[1], ::floatArguments[2]));
|
||||
injector.setBearing(*(::floatArguments + 3));
|
||||
injector.setVolume(::volume);
|
||||
|
||||
float delay = 0;
|
||||
int usecDelay = 0;
|
||||
|
||||
// register the callback for agent data creation
|
||||
agentList->linkedDataCreateCallback = createAvatarDataForAgent;
|
||||
|
||||
unsigned char broadcastPacket = PACKET_HEADER_INJECT_AUDIO;
|
||||
|
||||
timeval thisSend;
|
||||
double numMicrosecondsSleep = 0;
|
||||
|
||||
while (true) {
|
||||
injector.injectAudio(&streamSocket, (sockaddr*) &mixerSocket);
|
||||
|
||||
if (!::loopAudio) {
|
||||
delay = randFloatInRange(::sleepIntervalMin, ::sleepIntervalMax);
|
||||
usecDelay = delay * 1000 * 1000;
|
||||
usleep(usecDelay);
|
||||
if (::triggerDistance) {
|
||||
|
||||
// update the thisSend timeval to the current time
|
||||
gettimeofday(&thisSend, NULL);
|
||||
|
||||
// find the current avatar mixer
|
||||
Agent* avatarMixer = agentList->soloAgentOfType(AGENT_TYPE_AVATAR_MIXER);
|
||||
|
||||
// make sure we actually have an avatar mixer with an active socket
|
||||
if (avatarMixer && avatarMixer->getActiveSocket() != NULL) {
|
||||
// use the UDPSocket instance attached to our agent list to ask avatar mixer for a list of avatars
|
||||
agentList->getAgentSocket()->send(avatarMixer->getActiveSocket(),
|
||||
&broadcastPacket,
|
||||
sizeof(broadcastPacket));
|
||||
}
|
||||
|
||||
if (!injector.isInjectingAudio()) {
|
||||
// enumerate the other agents to decide if one is close enough that we should inject
|
||||
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
|
||||
AvatarData* avatarData = (AvatarData*) agent->getLinkedData();
|
||||
|
||||
if (avatarData) {
|
||||
glm::vec3 tempVector = injector.getPosition() - avatarData->getPosition();
|
||||
float squareDistance = glm::dot(tempVector, tempVector);
|
||||
|
||||
if (squareDistance <= ::triggerDistance) {
|
||||
// look for an audio mixer in our agent list
|
||||
Agent* audioMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AUDIO_MIXER);
|
||||
|
||||
if (audioMixer) {
|
||||
// we have an active audio mixer we can send data to
|
||||
AudioInjectionManager::threadInjector(&injector);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sleep for the correct amount of time to have data send be consistently timed
|
||||
if ((numMicrosecondsSleep = (AVATAR_MIXER_DATA_SEND_INTERVAL_MSECS * 1000) -
|
||||
(usecTimestampNow() - usecTimestamp(&thisSend))) > 0) {
|
||||
usleep(numMicrosecondsSleep);
|
||||
}
|
||||
} else {
|
||||
// look for an audio mixer in our agent list
|
||||
Agent* audioMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AUDIO_MIXER);
|
||||
|
||||
if (audioMixer) {
|
||||
injector.injectAudio(agentList->getAgentSocket(), audioMixer->getActiveSocket());
|
||||
}
|
||||
|
||||
float delay = 0;
|
||||
int usecDelay = 0;
|
||||
|
||||
if (!::loopAudio) {
|
||||
delay = randFloatInRange(::sleepIntervalMin, ::sleepIntervalMax);
|
||||
usecDelay = delay * 1000 * 1000;
|
||||
usleep(usecDelay);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// stop the receive agent data thread
|
||||
stopReceiveAgentDataThread = true;
|
||||
pthread_join(receiveAgentDataThread, NULL);
|
||||
|
||||
// stop the agent list's threads
|
||||
agentList->stopDomainServerCheckInThread();
|
||||
agentList->stopSilentAgentRemovalThread();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -954,11 +954,7 @@ void Application::pair() {
|
|||
PairingHandler::sendPairRequest();
|
||||
}
|
||||
|
||||
void Application::setHead(bool head) {
|
||||
#ifndef _WIN32
|
||||
_audio.setMixerLoopbackFlag(head);
|
||||
#endif
|
||||
|
||||
void Application::setHead(bool head) {
|
||||
if (head) {
|
||||
_myCamera.setMode(CAMERA_MODE_MIRROR);
|
||||
_myCamera.setModeShiftRate(100.0f);
|
||||
|
@ -1115,13 +1111,15 @@ void Application::initMenu() {
|
|||
_window->setMenuBar(menuBar);
|
||||
|
||||
QMenu* fileMenu = menuBar->addMenu("File");
|
||||
fileMenu->addAction("Quit", this, SLOT(quit()), Qt::Key_Q);
|
||||
fileMenu->addAction("Quit", this, SLOT(quit()), (Qt::Key_Q || Qt::Key_Control));
|
||||
|
||||
QMenu* pairMenu = menuBar->addMenu("Pair");
|
||||
pairMenu->addAction("Pair", this, SLOT(pair()));
|
||||
|
||||
QMenu* optionsMenu = menuBar->addMenu("Options");
|
||||
(_lookingInMirror = optionsMenu->addAction("Mirror", this, SLOT(setHead(bool)), Qt::Key_H))->setCheckable(true);
|
||||
(_echoAudioMode = optionsMenu->addAction("Echo Audio"))->setCheckable(true);
|
||||
|
||||
optionsMenu->addAction("Noise", this, SLOT(setNoise(bool)), Qt::Key_N)->setCheckable(true);
|
||||
(_gyroLook = optionsMenu->addAction("Gyro Look"))->setCheckable(true);
|
||||
_gyroLook->setChecked(true);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <time.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QAction>
|
||||
|
||||
#include <AgentList.h>
|
||||
|
||||
|
@ -64,6 +65,7 @@ public:
|
|||
Avatar* getAvatar() { return &_myAvatar; }
|
||||
VoxelSystem* getVoxels() { return &_voxels; }
|
||||
Environment* getEnvironment() { return &_environment; }
|
||||
bool shouldEchoAudio() { return _echoAudioMode->isChecked(); }
|
||||
|
||||
private slots:
|
||||
|
||||
|
@ -137,7 +139,8 @@ private:
|
|||
QMainWindow* _window;
|
||||
QGLWidget* _glWidget;
|
||||
|
||||
QAction* _lookingInMirror; // Are we currently rendering one's own head as if in mirror?
|
||||
QAction* _lookingInMirror; // Are we currently rendering one's own head as if in mirror?
|
||||
QAction* _echoAudioMode; // Are we asking the mixer to echo back our audio?
|
||||
QAction* _gyroLook; // Whether to allow the gyro data from head to move your view
|
||||
QAction* _mouseLook; // Whether the have the mouse near edge of screen move your view
|
||||
QAction* _showHeadMouse; // Whether the have the mouse near edge of screen move your view
|
||||
|
|
|
@ -158,10 +158,10 @@ int audioCallback (const void* inputBuffer,
|
|||
correctedYaw += 360;
|
||||
}
|
||||
|
||||
if (parentAudio->_mixerLoopbackFlag) {
|
||||
if (Application::getInstance()->shouldEchoAudio()) {
|
||||
correctedYaw = correctedYaw > 0
|
||||
? correctedYaw + AGENT_LOOPBACK_MODIFIER
|
||||
: correctedYaw - AGENT_LOOPBACK_MODIFIER;
|
||||
? correctedYaw + AGENT_LOOPBACK_MODIFIER
|
||||
: correctedYaw - AGENT_LOOPBACK_MODIFIER;
|
||||
}
|
||||
|
||||
memcpy(currentPacketPtr, &correctedYaw, sizeof(float));
|
||||
|
@ -310,7 +310,6 @@ Audio::Audio(Oscilloscope* scope) :
|
|||
NUM_AUDIO_CHANNELS * (SAMPLE_RATE / 1000.0)),
|
||||
_wasStarved(0),
|
||||
_lastInputLoudness(0),
|
||||
_mixerLoopbackFlag(false),
|
||||
_lastVelocity(0),
|
||||
_lastAcceleration(0),
|
||||
_totalPacketsReceived(0),
|
||||
|
|
|
@ -24,8 +24,6 @@ public:
|
|||
|
||||
void render(int screenWidth, int screenHeight);
|
||||
|
||||
void setMixerLoopbackFlag(bool mixerLoopbackFlag) { _mixerLoopbackFlag = mixerLoopbackFlag; }
|
||||
|
||||
float getLastInputLoudness() const { return _lastInputLoudness; };
|
||||
|
||||
void setLastAcceleration(glm::vec3 lastAcceleration) { _lastAcceleration = lastAcceleration; };
|
||||
|
@ -52,7 +50,6 @@ private:
|
|||
short _jitterBufferSamples;
|
||||
int _wasStarved;
|
||||
float _lastInputLoudness;
|
||||
bool _mixerLoopbackFlag;
|
||||
glm::vec3 _lastVelocity;
|
||||
glm::vec3 _lastAcceleration;
|
||||
int _totalPacketsReceived;
|
||||
|
|
|
@ -476,7 +476,14 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) {
|
|||
glm::quat orientation = getOrientation();
|
||||
|
||||
// reset hand and arm positions according to hand movement
|
||||
glm::vec3 transformedHandMovement = orientation * (_movedHandOffset * glm::vec3(-2.0f, -1.0f, -1.0f));
|
||||
glm::vec3 right = orientation * IDENTITY_RIGHT;
|
||||
glm::vec3 up = orientation * IDENTITY_UP;
|
||||
glm::vec3 front = orientation * IDENTITY_FRONT;
|
||||
|
||||
glm::vec3 transformedHandMovement
|
||||
= right * _movedHandOffset.x * 2.0f
|
||||
+ up * -_movedHandOffset.y * 2.0f
|
||||
+ front * -_movedHandOffset.y * 2.0f;
|
||||
|
||||
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position += transformedHandMovement;
|
||||
|
||||
|
@ -1139,8 +1146,12 @@ void Avatar::renderBody(bool lookingInMirror) {
|
|||
float alpha = lookingInMirror ? 1.0f : glm::clamp((distanceToCamera - RENDER_TRANSLUCENT_BEYOND) /
|
||||
(RENDER_OPAQUE_BEYOND - RENDER_TRANSLUCENT_BEYOND), 0.f, 1.f);
|
||||
|
||||
if (lookingInMirror || _owningAgent) {
|
||||
alpha = 1.0f;
|
||||
}
|
||||
|
||||
// Always render other people, and render myself when beyond threshold distance
|
||||
if (b == AVATAR_JOINT_HEAD_BASE) { // the head is rendered as a special case
|
||||
if (b == AVATAR_JOINT_HEAD_BASE) { // the head is rendered as a special
|
||||
if (lookingInMirror || _owningAgent || distanceToCamera > RENDER_OPAQUE_BEYOND * 0.5) {
|
||||
_head.render(lookingInMirror, _cameraPosition, alpha);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
const float THREAD_RADIUS = 0.007;
|
||||
const float HANDS_CLOSE_ENOUGH_TO_GRASP = 0.2;
|
||||
const float AVATAR_FACING_THRESHOLD = 0.1f; // (-1 to 1) (larger value indicates narrower angle of influence
|
||||
const float AVATAR_FACING_THRESHOLD = -0.5f; // (-1 to 1) (larger value indicates narrower angle of influence
|
||||
|
||||
AvatarTouch::AvatarTouch() {
|
||||
|
||||
|
@ -55,8 +55,7 @@ void AvatarTouch::simulate (float deltaTime) {
|
|||
facingEachOther = true;
|
||||
}
|
||||
|
||||
if ((distanceBetweenBodies < _reachableRadius)
|
||||
&& (facingEachOther)) {
|
||||
if (distanceBetweenBodies < _reachableRadius) {
|
||||
_canReachToOtherAvatar = true;
|
||||
|
||||
_vectorBetweenHands = _yourHandPosition - _myHandPosition;
|
||||
|
|
|
@ -42,8 +42,8 @@ vector<unsigned char> irisTexture;
|
|||
|
||||
Head::Head(Avatar* owningAvatar) :
|
||||
HeadData((AvatarData*)owningAvatar),
|
||||
_renderAlpha(0.0),
|
||||
yawRate(0.0f),
|
||||
_renderAlpha(0.0),
|
||||
_returnHeadToCenter(false),
|
||||
_skinColor(0.0f, 0.0f, 0.0f),
|
||||
_position(0.0f, 0.0f, 0.0f),
|
||||
|
@ -364,7 +364,9 @@ void Head::renderMouth() {
|
|||
glm::vec3 rightBottom = _mouthPosition + r * 0.4f - u * 1.0f + f * 0.7f;
|
||||
|
||||
// constrain all mouth vertices to a sphere slightly larger than the head...
|
||||
float constrainedRadius = _scale + 0.001f;
|
||||
const float MOUTH_OFFSET_OFF_FACE = 0.003f;
|
||||
|
||||
float constrainedRadius = _scale + MOUTH_OFFSET_OFF_FACE;
|
||||
middle = _position + glm::normalize(middle - _position) * constrainedRadius;
|
||||
leftCorner = _position + glm::normalize(leftCorner - _position) * constrainedRadius;
|
||||
rightCorner = _position + glm::normalize(rightCorner - _position) * constrainedRadius;
|
||||
|
|
|
@ -887,11 +887,14 @@ bool VoxelSystem::removeOutOfViewOperation(VoxelNode* node, void* extraData) {
|
|||
|
||||
bool VoxelSystem::isViewChanging() {
|
||||
bool result = false; // assume the best
|
||||
|
||||
/** TEMPORARY HACK ******
|
||||
// If our viewFrustum has changed since our _lastKnowViewFrustum
|
||||
if (_viewFrustum && !_lastKnowViewFrustum.matches(_viewFrustum)) {
|
||||
result = true;
|
||||
_lastKnowViewFrustum = *_viewFrustum; // save last known
|
||||
}
|
||||
**/
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,11 @@ void* AudioInjectionManager::injectAudioViaThread(void* args) {
|
|||
|
||||
// if we don't have an explicit destination socket then pull active socket for current audio mixer from agent list
|
||||
if (!_isDestinationSocketExplicit) {
|
||||
_destinationSocket = *AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AUDIO_MIXER)->getActiveSocket();
|
||||
Agent* audioMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AUDIO_MIXER);
|
||||
|
||||
if (audioMixer) {
|
||||
_destinationSocket = *audioMixer->getActiveSocket();
|
||||
}
|
||||
}
|
||||
|
||||
injector->injectAudio(_injectorSocket, &_destinationSocket);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
//
|
||||
|
||||
#include <cstring>
|
||||
#include <math.h>
|
||||
|
||||
#include "PacketHeaders.h"
|
||||
|
||||
|
@ -56,7 +57,12 @@ int AudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
memcpy(&_bearing, dataBuffer, sizeof(float));
|
||||
dataBuffer += sizeof(_bearing);
|
||||
|
||||
if (_bearing > 180 || _bearing < -180) {
|
||||
// if this agent sent us a NaN bearing then don't consider this good audio and bail
|
||||
if (std::isnan(_bearing)) {
|
||||
_endOfLastWrite = _nextOutput = _buffer;
|
||||
_started = false;
|
||||
return 0;
|
||||
} else if (_bearing > 180 || _bearing < -180) {
|
||||
// we were passed an invalid bearing because this agent wants loopback (pressed the H key)
|
||||
_shouldLoopbackForAgent = true;
|
||||
|
||||
|
@ -66,7 +72,7 @@ int AudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
: _bearing + AGENT_LOOPBACK_MODIFIER;
|
||||
} else {
|
||||
_shouldLoopbackForAgent = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// make sure we have enough bytes left for this to be the right amount of audio
|
||||
|
|
|
@ -250,7 +250,8 @@ Agent* AgentList::addOrUpdateAgent(sockaddr* publicSocket, sockaddr* localSocket
|
|||
|
||||
if (agent->getType() == AGENT_TYPE_AUDIO_MIXER ||
|
||||
agent->getType() == AGENT_TYPE_VOXEL ||
|
||||
agent->getType() == AGENT_TYPE_ANIMATION_SERVER) {
|
||||
agent->getType() == AGENT_TYPE_ANIMATION_SERVER ||
|
||||
agent->getType() == AGENT_TYPE_AUDIO_INJECTOR) {
|
||||
// until the Audio class also uses our agentList, we need to update
|
||||
// the lastRecvTimeUsecs for the audio mixer so it doesn't get killed and re-added continously
|
||||
agent->setLastHeardMicrostamp(usecTimestampNow());
|
||||
|
|
Loading…
Reference in a new issue