diff --git a/CMakeLists.txt b/CMakeLists.txt index 14692ef3f4..8af8081975 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 2.8) project(hifi) +add_subdirectory(animation-server) add_subdirectory(avatar-mixer) add_subdirectory(audio-mixer) add_subdirectory(domain-server) diff --git a/animation-server/CMakeLists.txt b/animation-server/CMakeLists.txt new file mode 100644 index 0000000000..e9662366af --- /dev/null +++ b/animation-server/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 2.8) + +set(TARGET_NAME animation-server) + +set(ROOT_DIR ..) +set(MACRO_DIR ${ROOT_DIR}/cmake/macros) + +# setup for find modules +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/") + +# set up the external glm library +include(${MACRO_DIR}/IncludeGLM.cmake) +include_glm(${TARGET_NAME} ${ROOT_DIR}) + +include(${MACRO_DIR}/SetupHifiProject.cmake) + +setup_hifi_project(${TARGET_NAME}) + +# link in the shared library +include(${MACRO_DIR}/LinkHifiLibrary.cmake) +link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) + +# link in the hifi voxels library +link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR}) + + diff --git a/animation-server/src/main.cpp b/animation-server/src/main.cpp new file mode 100644 index 0000000000..18b4ad787c --- /dev/null +++ b/animation-server/src/main.cpp @@ -0,0 +1,398 @@ +// +// main.cpp +// Animation Server +// +// Created by Brad Hefta-Gaub on 05/16/2013 +// Copyright (c) 2012 High Fidelity, Inc. All rights reserved. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include "Syssocket.h" +#include "Systime.h" +#else +#include +#include +#include +#endif + +bool shouldShowPacketsPerSecond = false; // do we want to debug packets per second + +const int ANIMATION_LISTEN_PORT = 40107; +const int ACTUAL_FPS = 60; +const double OUR_FPS_IN_MILLISECONDS = 1000.0/ACTUAL_FPS; // determines FPS from our desired FPS +const int ANIMATE_VOXELS_INTERVAL_USECS = OUR_FPS_IN_MILLISECONDS * 1000.0; // converts from milliseconds to usecs + +bool wantLocalDomain = false; + +static void sendVoxelServerZMessage() { + char message[100]; + sprintf(message,"%c%s",'Z',"a message"); + int messageSize = strlen(message) + 1; + AgentList::getInstance()->broadcastToAgents((unsigned char*) message, messageSize, &AGENT_TYPE_VOXEL, 1); +} + +unsigned long packetsSent = 0; +unsigned long bytesSent = 0; + +static void sendVoxelEditMessage(PACKET_HEADER header, VoxelDetail& detail) { + unsigned char* bufferOut; + int sizeOut; + + if (createVoxelEditMessage(header, 0, 1, &detail, 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; + } +} + +float intensity = 0.5f; +float intensityIncrement = 0.1f; +const float MAX_INTENSITY = 1.0f; +const float MIN_INTENSITY = 0.5f; +const float BEACON_SIZE = 0.25f / TREE_SCALE; // approximately 1/4th meter + +static void sendVoxelBlinkMessage() { + VoxelDetail detail; + detail.s = BEACON_SIZE; + + glm::vec3 position = glm::vec3(0, 0, detail.s); + + detail.x = detail.s * floor(position.x / detail.s); + detail.y = detail.s * floor(position.y / detail.s); + detail.z = detail.s * floor(position.z / detail.s); + + ::intensity += ::intensityIncrement; + if (::intensity >= MAX_INTENSITY) { + ::intensity = MAX_INTENSITY; + ::intensityIncrement = -::intensityIncrement; + } + if (::intensity <= MIN_INTENSITY) { + ::intensity = MIN_INTENSITY; + ::intensityIncrement = -::intensityIncrement; + } + + detail.red = 255 * ::intensity; + detail.green = 0 * ::intensity; + detail.blue = 0 * ::intensity; + + PACKET_HEADER message = PACKET_HEADER_SET_VOXEL_DESTRUCTIVE; + + sendVoxelEditMessage(message, detail); +} + +bool stringOfLightsInitialized = false; +int currentLight = 0; +int lightMovementDirection = 1; +const int SEGMENT_COUNT = 4; +const int LIGHTS_PER_SEGMENT = 80; +const int LIGHT_COUNT = LIGHTS_PER_SEGMENT * SEGMENT_COUNT; +glm::vec3 stringOfLights[LIGHT_COUNT]; +unsigned char offColor[3] = { 240, 240, 240 }; +unsigned char onColor[3] = { 0, 255, 255 }; +const float STRING_OF_LIGHTS_SIZE = 0.125f / TREE_SCALE; // approximately 1/8th meter + +static void sendBlinkingStringOfLights() { + PACKET_HEADER message = PACKET_HEADER_SET_VOXEL_DESTRUCTIVE; // we're a bully! + float lightScale = STRING_OF_LIGHTS_SIZE; + static VoxelDetail details[LIGHTS_PER_SEGMENT]; + unsigned char* bufferOut; + int sizeOut; + + // first initialized the string of lights if needed... + if (!stringOfLightsInitialized) { + for (int segment = 0; segment < SEGMENT_COUNT; segment++) { + for (int indexInSegment = 0; indexInSegment < LIGHTS_PER_SEGMENT; indexInSegment++) { + + int i = (segment * LIGHTS_PER_SEGMENT) + indexInSegment; + + // four different segments on sides of initial platform + switch (segment) { + case 0: + // along x axis + stringOfLights[i] = glm::vec3(indexInSegment * lightScale, 0, 0); + break; + case 1: + // parallel to Z axis at outer X edge + stringOfLights[i] = glm::vec3(LIGHTS_PER_SEGMENT * lightScale, 0, indexInSegment * lightScale); + break; + case 2: + // parallel to X axis at outer Z edge + stringOfLights[i] = glm::vec3((LIGHTS_PER_SEGMENT-indexInSegment) * lightScale, 0, + LIGHTS_PER_SEGMENT * lightScale); + break; + case 3: + // on Z axis + stringOfLights[i] = glm::vec3(0, 0, (LIGHTS_PER_SEGMENT-indexInSegment) * lightScale); + break; + } + + details[indexInSegment].s = STRING_OF_LIGHTS_SIZE; + details[indexInSegment].x = stringOfLights[i].x; + details[indexInSegment].y = stringOfLights[i].y; + details[indexInSegment].z = stringOfLights[i].z; + + details[indexInSegment].red = offColor[0]; + details[indexInSegment].green = offColor[1]; + details[indexInSegment].blue = offColor[2]; + } + + // send entire segment at once + if (createVoxelEditMessage(message, 0, LIGHTS_PER_SEGMENT, (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; + } + + } + stringOfLightsInitialized = true; + } else { + // turn off current light + details[0].x = stringOfLights[currentLight].x; + details[0].y = stringOfLights[currentLight].y; + details[0].z = stringOfLights[currentLight].z; + details[0].red = offColor[0]; + details[0].green = offColor[1]; + details[0].blue = offColor[2]; + + // move current light... + // if we're at the end of our string, then change direction + if (currentLight == LIGHT_COUNT-1) { + lightMovementDirection = -1; + } + if (currentLight == 0) { + lightMovementDirection = 1; + } + currentLight += lightMovementDirection; + + // turn on new current light + details[1].x = stringOfLights[currentLight].x; + details[1].y = stringOfLights[currentLight].y; + details[1].z = stringOfLights[currentLight].z; + details[1].red = onColor[0]; + details[1].green = onColor[1]; + details[1].blue = onColor[2]; + + // send both changes in same message + if (createVoxelEditMessage(message, 0, 2, (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; +glm::vec3 billboardPosition((0.125f / TREE_SCALE),(0.125f / TREE_SCALE),0); +glm::vec3 billboardLights[BILLBOARD_HEIGHT][BILLBOARD_WIDTH]; +unsigned char billboardOffColor[3] = { 240, 240, 240 }; +unsigned char billboardOnColorA[3] = { 0, 0, 255 }; +unsigned char billboardOnColorB[3] = { 0, 255, 0 }; +float billboardGradient = 0.5f; +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 PACKETS_PER_BILLBOARD = VOXELS_PER_PACKET / (BILLBOARD_HEIGHT * BILLBOARD_WIDTH); + + +// top to bottom... +bool billboardMessage[BILLBOARD_HEIGHT][BILLBOARD_WIDTH] = { + { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, + { 0,0,1,0,0,1,0,1,0,0,0,0,0,1,0,0,0,0,1,1,1,1,0,0,0,0,0,1,0,1,1,1,0,1,0,1,0,0,1,0,0,0,0,0,0 }, + { 0,0,1,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,1,0,1,0,0,0,1,1,1,0,0,0,0,0 }, + { 0,0,1,1,1,1,0,1,0,1,1,1,0,1,1,1,0,0,1,1,1,0,0,0,0,1,1,1,0,1,1,1,0,1,0,1,0,0,1,0,0,1,0,1,0 }, + { 0,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,0,0,0,0,1,0,1,0,1,0,1,0,0,0,1,0,1,0,0,1,0,0,1,0,1,0 }, + { 0,0,1,0,0,1,0,1,0,1,1,1,0,1,0,1,0,0,1,0,0,0,0,1,0,1,1,1,0,1,1,1,0,1,0,1,0,0,1,0,0,1,1,1,0 }, + { 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0 }, + { 0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0 }, + { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } +}; + +static void sendBillboard() { + PACKET_HEADER message = PACKET_HEADER_SET_VOXEL_DESTRUCTIVE; // we're a bully! + float lightScale = BILLBOARD_LIGHT_SIZE; + static VoxelDetail details[VOXELS_PER_PACKET]; + unsigned char* bufferOut; + int sizeOut; + + // first initialized the billboard of lights if needed... + if (!billboardInitialized) { + for (int i = 0; i < BILLBOARD_HEIGHT; i++) { + for (int j = 0; j < BILLBOARD_WIDTH; j++) { + + billboardLights[i][j] = billboardPosition + glm::vec3(j * lightScale, (float)((BILLBOARD_HEIGHT - i) * lightScale), 0); + } + } + billboardInitialized = true; + } + + ::billboardGradient += ::billboardGradientIncrement; + + if (::billboardGradient >= BILLBOARD_MAX_GRADIENT) { + ::billboardGradient = BILLBOARD_MAX_GRADIENT; + ::billboardGradientIncrement = -::billboardGradientIncrement; + } + if (::billboardGradient <= BILLBOARD_MIN_GRADIENT) { + ::billboardGradient = BILLBOARD_MIN_GRADIENT; + ::billboardGradientIncrement = -::billboardGradientIncrement; + } + + for (int i = 0; i < BILLBOARD_HEIGHT; i++) { + for (int j = 0; j < BILLBOARD_WIDTH; j++) { + + int nthVoxel = ((i * BILLBOARD_WIDTH) + j); + int item = nthVoxel % VOXELS_PER_PACKET; + + billboardLights[i][j] = billboardPosition + glm::vec3(j * lightScale, (float)((BILLBOARD_HEIGHT - i) * lightScale), 0); + + details[item].s = lightScale; + details[item].x = billboardLights[i][j].x; + details[item].y = billboardLights[i][j].y; + details[item].z = billboardLights[i][j].z; + + if (billboardMessage[i][j]) { + details[item].red = (billboardOnColorA[0] + ((billboardOnColorB[0] - billboardOnColorA[0]) * ::billboardGradient)); + details[item].green = (billboardOnColorA[1] + ((billboardOnColorB[1] - billboardOnColorA[1]) * ::billboardGradient)); + details[item].blue = (billboardOnColorA[2] + ((billboardOnColorB[2] - billboardOnColorA[2]) * ::billboardGradient)); + } else { + details[item].red = billboardOffColor[0]; + details[item].green = billboardOffColor[1]; + details[item].blue = billboardOffColor[2]; + } + + if (item == VOXELS_PER_PACKET - 1) { + if (createVoxelEditMessage(message, 0, 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; + } + } + } + } +} + +double start = 0; + + +void* animateVoxels(void* args) { + + AgentList* agentList = AgentList::getInstance(); + timeval lastSendTime; + + while (true) { + gettimeofday(&lastSendTime, NULL); + + // some animations + //sendVoxelBlinkMessage(); + sendBlinkingStringOfLights(); + sendBillboard(); + + double end = usecTimestampNow(); + double elapsedSeconds = (end - ::start) / 1000000.0; + if (::shouldShowPacketsPerSecond) { + printf("packetsSent=%ld, bytesSent=%ld pps=%f bps=%f\n",packetsSent,bytesSent, + (float)(packetsSent/elapsedSeconds),(float)(bytesSent/elapsedSeconds)); + } + // dynamically sleep until we need to fire off the next set of voxels + double usecToSleep = ANIMATE_VOXELS_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&lastSendTime)); + + if (usecToSleep > 0) { + usleep(usecToSleep); + } else { + std::cout << "Last send took too much time, not sleeping!\n"; + } + } + + pthread_exit(0); +} + + +int main(int argc, const char * argv[]) +{ + ::start = usecTimestampNow(); + + AgentList* agentList = AgentList::createInstance(AGENT_TYPE_ANIMATION_SERVER, ANIMATION_LISTEN_PORT); + setvbuf(stdout, NULL, _IOLBF, 0); + + // Handle Local Domain testing with the --local command line + const char* showPPS = "--showPPS"; + ::shouldShowPacketsPerSecond = cmdOptionExists(argc, argv, showPPS); + + // Handle Local Domain testing with the --local command line + const char* local = "--local"; + ::wantLocalDomain = cmdOptionExists(argc, argv,local); + if (::wantLocalDomain) { + printf("Local Domain MODE!\n"); + int ip = getLocalAddress(); + sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF)); + } + + agentList->linkedDataCreateCallback = NULL; // do we need a callback? + agentList->startSilentAgentRemovalThread(); + agentList->startDomainServerCheckInThread(); + + srand((unsigned)time(0)); + + pthread_t animateVoxelThread; + pthread_create(&animateVoxelThread, NULL, animateVoxels, NULL); + + sockaddr agentPublicAddress; + + unsigned char* packetData = new unsigned char[MAX_PACKET_SIZE]; + ssize_t receivedBytes; + + // loop to send to agents requesting data + while (true) { + // Agents sending messages to us... + if (agentList->getAgentSocket()->receive(&agentPublicAddress, packetData, &receivedBytes)) { + switch (packetData[0]) { + default: { + AgentList::getInstance()->processAgentData(&agentPublicAddress, packetData, receivedBytes); + } break; + } + } + } + + pthread_join(animateVoxelThread, NULL); + + return 0; +} diff --git a/audio-mixer/CMakeLists.txt b/audio-mixer/CMakeLists.txt index 3e2d9939b0..eac2792883 100644 --- a/audio-mixer/CMakeLists.txt +++ b/audio-mixer/CMakeLists.txt @@ -3,11 +3,18 @@ cmake_minimum_required(VERSION 2.8) set(ROOT_DIR ..) set(MACRO_DIR ${ROOT_DIR}/cmake/macros) +# setup for find modules +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/") + set(TARGET_NAME audio-mixer) include(${MACRO_DIR}/SetupHifiProject.cmake) setup_hifi_project(${TARGET_NAME}) +# set up the external glm library +include(${MACRO_DIR}/IncludeGLM.cmake) +include_glm(${TARGET_NAME} ${ROOT_DIR}) + # link the shared hifi library include(${MACRO_DIR}/LinkHifiLibrary.cmake) link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) diff --git a/audio-mixer/src/main.cpp b/audio-mixer/src/main.cpp index 5bb33a9198..6593876d0b 100644 --- a/audio-mixer/src/main.cpp +++ b/audio-mixer/src/main.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -132,128 +133,130 @@ int main(int argc, const char* argv[]) { memset(distanceCoefficients, 0, sizeof(distanceCoefficients)); for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { - AudioRingBuffer* agentRingBuffer = (AudioRingBuffer*) agent->getLinkedData(); - - // zero out the client mix for this agent - memset(clientSamples, 0, sizeof(clientSamples)); - - for (AgentList::iterator otherAgent = agentList->begin(); otherAgent != agentList->end(); otherAgent++) { - if (otherAgent != agent || (otherAgent == agent && agentRingBuffer->shouldLoopbackForAgent())) { - AudioRingBuffer* otherAgentBuffer = (AudioRingBuffer*) otherAgent->getLinkedData(); - - if (otherAgentBuffer->shouldBeAddedToMix()) { + if (agent->getType() == AGENT_TYPE_AVATAR) { + AudioRingBuffer* agentRingBuffer = (AudioRingBuffer*) agent->getLinkedData(); + + // zero out the client mix for this agent + memset(clientSamples, 0, sizeof(clientSamples)); + + for (AgentList::iterator otherAgent = agentList->begin(); otherAgent != agentList->end(); otherAgent++) { + if (otherAgent != agent || (otherAgent == agent && agentRingBuffer->shouldLoopbackForAgent())) { + AudioRingBuffer* otherAgentBuffer = (AudioRingBuffer*) otherAgent->getLinkedData(); - float bearingRelativeAngleToSource = 0.f; - float attenuationCoefficient = 1.f; - int numSamplesDelay = 0; - float weakChannelAmplitudeRatio = 1.f; - - if (otherAgent != agent) { - Position agentPosition = agentRingBuffer->getPosition(); - Position otherAgentPosition = otherAgentBuffer->getPosition(); + if (otherAgentBuffer->shouldBeAddedToMix()) { - // calculate the distance to the other agent + float bearingRelativeAngleToSource = 0.f; + float attenuationCoefficient = 1.f; + int numSamplesDelay = 0; + float weakChannelAmplitudeRatio = 1.f; - // use the distance to the other agent to calculate the change in volume for this frame - int lowAgentIndex = std::min(agent.getAgentIndex(), otherAgent.getAgentIndex()); - int highAgentIndex = std::max(agent.getAgentIndex(), otherAgent.getAgentIndex()); - - if (distanceCoefficients[lowAgentIndex][highAgentIndex] == 0) { - float distanceToAgent = sqrtf(powf(agentPosition.x - otherAgentPosition.x, 2) + - powf(agentPosition.y - otherAgentPosition.y, 2) + - powf(agentPosition.z - otherAgentPosition.z, 2)); + if (otherAgent != agent) { + glm::vec3 agentPosition = agentRingBuffer->getPosition(); + glm::vec3 otherAgentPosition = otherAgentBuffer->getPosition(); - float minCoefficient = std::min(1.0f, - powf(0.5, - (logf(DISTANCE_RATIO * distanceToAgent) / logf(3)) - 1)); - distanceCoefficients[lowAgentIndex][highAgentIndex] = minCoefficient; - } - - - // get the angle from the right-angle triangle - float triangleAngle = atan2f(fabsf(agentPosition.z - otherAgentPosition.z), - fabsf(agentPosition.x - otherAgentPosition.x)) * (180 / M_PI); - float absoluteAngleToSource = 0; - bearingRelativeAngleToSource = 0; - - // find the angle we need for calculation based on the orientation of the triangle - if (otherAgentPosition.x > agentPosition.x) { - if (otherAgentPosition.z > agentPosition.z) { - absoluteAngleToSource = -90 + triangleAngle; - } else { - absoluteAngleToSource = -90 - triangleAngle; + // calculate the distance to the other agent + + // use the distance to the other agent to calculate the change in volume for this frame + int lowAgentIndex = std::min(agent.getAgentIndex(), otherAgent.getAgentIndex()); + int highAgentIndex = std::max(agent.getAgentIndex(), otherAgent.getAgentIndex()); + + if (distanceCoefficients[lowAgentIndex][highAgentIndex] == 0) { + float distanceToAgent = sqrtf(powf(agentPosition.x - otherAgentPosition.x, 2) + + powf(agentPosition.y - otherAgentPosition.y, 2) + + powf(agentPosition.z - otherAgentPosition.z, 2)); + + float minCoefficient = std::min(1.0f, + powf(0.5, + (logf(DISTANCE_RATIO * distanceToAgent) / logf(3)) - 1)); + distanceCoefficients[lowAgentIndex][highAgentIndex] = minCoefficient; } - } else { - if (otherAgentPosition.z > agentPosition.z) { - absoluteAngleToSource = 90 - triangleAngle; + + + // get the angle from the right-angle triangle + float triangleAngle = atan2f(fabsf(agentPosition.z - otherAgentPosition.z), + fabsf(agentPosition.x - otherAgentPosition.x)) * (180 / M_PI); + float absoluteAngleToSource = 0; + bearingRelativeAngleToSource = 0; + + // find the angle we need for calculation based on the orientation of the triangle + if (otherAgentPosition.x > agentPosition.x) { + if (otherAgentPosition.z > agentPosition.z) { + absoluteAngleToSource = -90 + triangleAngle; + } else { + absoluteAngleToSource = -90 - triangleAngle; + } } else { - absoluteAngleToSource = 90 + triangleAngle; + if (otherAgentPosition.z > agentPosition.z) { + absoluteAngleToSource = 90 - triangleAngle; + } else { + absoluteAngleToSource = 90 + triangleAngle; + } } + + bearingRelativeAngleToSource = absoluteAngleToSource - agentRingBuffer->getBearing(); + + if (bearingRelativeAngleToSource > 180) { + bearingRelativeAngleToSource -= 360; + } else if (bearingRelativeAngleToSource < -180) { + bearingRelativeAngleToSource += 360; + } + + float angleOfDelivery = absoluteAngleToSource - otherAgentBuffer->getBearing(); + + if (angleOfDelivery > 180) { + angleOfDelivery -= 360; + } else if (angleOfDelivery < -180) { + angleOfDelivery += 360; + } + + float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION + + (OFF_AXIS_ATTENUATION_FORMULA_STEP * (fabsf(angleOfDelivery) / 90.0f)); + + attenuationCoefficient = distanceCoefficients[lowAgentIndex][highAgentIndex] + * otherAgentBuffer->getAttenuationRatio() + * offAxisCoefficient; + + bearingRelativeAngleToSource *= (M_PI / 180); + + float sinRatio = fabsf(sinf(bearingRelativeAngleToSource)); + numSamplesDelay = PHASE_DELAY_AT_90 * sinRatio; + weakChannelAmplitudeRatio = 1 - (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio); } - bearingRelativeAngleToSource = absoluteAngleToSource - agentRingBuffer->getBearing(); - - if (bearingRelativeAngleToSource > 180) { - bearingRelativeAngleToSource -= 360; - } else if (bearingRelativeAngleToSource < -180) { - bearingRelativeAngleToSource += 360; - } - - float angleOfDelivery = absoluteAngleToSource - otherAgentBuffer->getBearing(); - - if (angleOfDelivery > 180) { - angleOfDelivery -= 360; - } else if (angleOfDelivery < -180) { - angleOfDelivery += 360; - } - - float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION + - (OFF_AXIS_ATTENUATION_FORMULA_STEP * (fabsf(angleOfDelivery) / 90.0f)); - - attenuationCoefficient = distanceCoefficients[lowAgentIndex][highAgentIndex] - * otherAgentBuffer->getAttenuationRatio() - * offAxisCoefficient; - - bearingRelativeAngleToSource *= (M_PI / 180); - - float sinRatio = fabsf(sinf(bearingRelativeAngleToSource)); - numSamplesDelay = PHASE_DELAY_AT_90 * sinRatio; - weakChannelAmplitudeRatio = 1 - (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio); - } - - int16_t* goodChannel = bearingRelativeAngleToSource > 0.0f + int16_t* goodChannel = bearingRelativeAngleToSource > 0.0f ? clientSamples + BUFFER_LENGTH_SAMPLES_PER_CHANNEL : clientSamples; - int16_t* delayedChannel = bearingRelativeAngleToSource > 0.0f + int16_t* delayedChannel = bearingRelativeAngleToSource > 0.0f ? clientSamples : clientSamples + BUFFER_LENGTH_SAMPLES_PER_CHANNEL; - - int16_t* delaySamplePointer = otherAgentBuffer->getNextOutput() == otherAgentBuffer->getBuffer() + + int16_t* delaySamplePointer = otherAgentBuffer->getNextOutput() == otherAgentBuffer->getBuffer() ? otherAgentBuffer->getBuffer() + RING_BUFFER_SAMPLES - numSamplesDelay : otherAgentBuffer->getNextOutput() - numSamplesDelay; - - for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) { - if (s < numSamplesDelay) { - // pull the earlier sample for the delayed channel - int earlierSample = delaySamplePointer[s] * attenuationCoefficient; - plateauAdditionOfSamples(delayedChannel[s], earlierSample * weakChannelAmplitudeRatio); - } - - int16_t currentSample = (otherAgentBuffer->getNextOutput()[s] * attenuationCoefficient); - plateauAdditionOfSamples(goodChannel[s], currentSample); - - if (s + numSamplesDelay < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { - plateauAdditionOfSamples(delayedChannel[s + numSamplesDelay], - currentSample * weakChannelAmplitudeRatio); + for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) { + + if (s < numSamplesDelay) { + // pull the earlier sample for the delayed channel + int earlierSample = delaySamplePointer[s] * attenuationCoefficient; + plateauAdditionOfSamples(delayedChannel[s], earlierSample * weakChannelAmplitudeRatio); + } + + int16_t currentSample = (otherAgentBuffer->getNextOutput()[s] * attenuationCoefficient); + plateauAdditionOfSamples(goodChannel[s], currentSample); + + if (s + numSamplesDelay < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { + plateauAdditionOfSamples(delayedChannel[s + numSamplesDelay], + currentSample * weakChannelAmplitudeRatio); + } } } } } + + memcpy(clientPacket + 1, clientSamples, sizeof(clientSamples)); + agentList->getAgentSocket()->send(agent->getPublicSocket(), clientPacket, BUFFER_LENGTH_BYTES + 1); } - - memcpy(clientPacket + 1, clientSamples, sizeof(clientSamples)); - agentList->getAgentSocket()->send(agent->getPublicSocket(), clientPacket, BUFFER_LENGTH_BYTES + 1); } // push forward the next output pointers for any audio buffers we used @@ -272,16 +275,45 @@ int main(int argc, const char* argv[]) { // pull any new audio data from agents off of the network stack while (agentList->getAgentSocket()->receive(agentAddress, packetData, &receivedBytes)) { - if (packetData[0] == PACKET_HEADER_INJECT_AUDIO || packetData[0] == PACKET_HEADER_MICROPHONE_AUDIO) { - char agentType = (packetData[0] == PACKET_HEADER_MICROPHONE_AUDIO) - ? AGENT_TYPE_AVATAR - : AGENT_TYPE_AUDIO_INJECTOR; + if (packetData[0] == PACKET_HEADER_MICROPHONE_AUDIO) { + Agent* avatarAgent = agentList->addOrUpdateAgent(agentAddress, + agentAddress, + AGENT_TYPE_AVATAR, + agentList->getLastAgentID()); - if (agentList->addOrUpdateAgent(agentAddress, agentAddress, agentType, agentList->getLastAgentID())) { + if (avatarAgent->getAgentID() == agentList->getLastAgentID()) { agentList->increaseAgentID(); } agentList->updateAgentWithData(agentAddress, packetData, receivedBytes); + } else if (packetData[0] == PACKET_HEADER_INJECT_AUDIO) { + Agent* matchingInjector = NULL; + + for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { + if (agent->getLinkedData()) { + + AudioRingBuffer* ringBuffer = (AudioRingBuffer*) agent->getLinkedData(); + if (memcmp(ringBuffer->getStreamIdentifier(), + packetData + 1, + STREAM_IDENTIFIER_NUM_BYTES) == 0) { + // this is the matching stream, assign to matchingInjector and stop looking + matchingInjector = &*agent; + break; + } + } + } + + if (!matchingInjector) { + matchingInjector = agentList->addOrUpdateAgent(NULL, + NULL, + AGENT_TYPE_AUDIO_INJECTOR, + agentList->getLastAgentID()); + agentList->increaseAgentID(); + + } + + // give the new audio data to the matching injector agent + agentList->updateAgentWithData(matchingInjector, packetData, receivedBytes); } } diff --git a/avatar-mixer/src/main.cpp b/avatar-mixer/src/main.cpp index d51e48b055..da2b41b1bd 100644 --- a/avatar-mixer/src/main.cpp +++ b/avatar-mixer/src/main.cpp @@ -70,6 +70,7 @@ int main(int argc, const char* argv[]) { unsigned char* currentBufferPosition = NULL; uint16_t agentID = 0; + Agent* avatarAgent = NULL; while (true) { if (agentList->getAgentSocket()->receive(agentAddress, packetData, &receivedBytes)) { @@ -79,10 +80,10 @@ int main(int argc, const char* argv[]) { unpackAgentId(packetData + 1, &agentID); // add or update the agent in our list - agentList->addOrUpdateAgent(agentAddress, agentAddress, AGENT_TYPE_AVATAR, agentID); + avatarAgent = agentList->addOrUpdateAgent(agentAddress, agentAddress, AGENT_TYPE_AVATAR, agentID); // parse positional data from an agent - agentList->updateAgentWithData(agentAddress, packetData, receivedBytes); + agentList->updateAgentWithData(avatarAgent, packetData, receivedBytes); currentBufferPosition = broadcastPacket + 1; diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 959456bd03..968057623f 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -115,10 +115,12 @@ int main(int argc, const char * argv[]) } } - if (agentList->addOrUpdateAgent((sockaddr*) &agentPublicAddress, - (sockaddr*) &agentLocalAddress, - agentType, - agentList->getLastAgentID())) { + Agent* newAgent = agentList->addOrUpdateAgent((sockaddr*) &agentPublicAddress, + (sockaddr*) &agentLocalAddress, + agentType, + agentList->getLastAgentID()); + + if (newAgent->getAgentID() == agentList->getLastAgentID()) { agentList->increaseAgentID(); } diff --git a/eve/src/main.cpp b/eve/src/main.cpp index 52f307c18f..62be6e36cd 100644 --- a/eve/src/main.cpp +++ b/eve/src/main.cpp @@ -37,6 +37,8 @@ const float EVE_PELVIS_HEIGHT = 0.565925f; const float AUDIO_INJECT_PROXIMITY = 0.4f; const int EVE_VOLUME_BYTE = 190; +const char EVE_AUDIO_FILENAME[] = "/etc/highfidelity/eve/resources/eve.raw"; + bool stopReceiveAgentDataThread; void *receiveAgentData(void *args) { @@ -93,7 +95,7 @@ int main(int argc, const char* argv[]) { pthread_create(&receiveAgentDataThread, NULL, receiveAgentData, NULL); // create an AvatarData object, "eve" - AvatarData eve = AvatarData(); + AvatarData eve; // move eve away from the origin // pick a random point inside a 10x10 grid @@ -114,7 +116,7 @@ int main(int argc, const char* argv[]) { AudioInjectionManager::setInjectorSocket(agentList->getAgentSocket()); // read eve's audio data - AudioInjector eveAudioInjector("/etc/highfidelity/eve/resources/eve.raw"); + AudioInjector eveAudioInjector(EVE_AUDIO_FILENAME); // lower Eve's volume by setting the attentuation modifier (this is a value out of 255) eveAudioInjector.setVolume(EVE_VOLUME_BYTE); diff --git a/interface/resources/images/green_eye.png b/interface/resources/images/green_eye.png deleted file mode 100644 index 05bf108a00..0000000000 Binary files a/interface/resources/images/green_eye.png and /dev/null differ diff --git a/interface/resources/images/iris.png b/interface/resources/images/iris.png new file mode 100644 index 0000000000..fce68fe95d Binary files /dev/null and b/interface/resources/images/iris.png differ diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9563b62e58..dada57c1ec 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -470,13 +470,6 @@ void Application::resizeGL(int width, int height) { glLoadIdentity(); } -static void sendVoxelServerEraseAll() { - char message[100]; - sprintf(message,"%c%s",'Z',"erase all"); - int messageSize = strlen(message) + 1; - AgentList::getInstance()->broadcastToAgents((unsigned char*) message, messageSize, &AGENT_TYPE_VOXEL, 1); -} - static void sendVoxelServerAddScene() { char message[100]; sprintf(message,"%c%s",'Z',"add scene"); @@ -860,14 +853,14 @@ void Application::idle() { if (_myAvatar.isTransmitterV2Connected()) { const float HAND_FORCE_SCALING = 0.05f; const float* handAcceleration = _myAvatar.getTransmitterHandLastAcceleration(); - _myAvatar.setHandMovementValues(glm::vec3(-handAcceleration[0] * HAND_FORCE_SCALING, + _myAvatar.setMovedHandOffset(glm::vec3(-handAcceleration[0] * HAND_FORCE_SCALING, handAcceleration[1] * HAND_FORCE_SCALING, handAcceleration[2] * HAND_FORCE_SCALING)); } else { // update behaviors for avatar hand movement: handControl takes mouse values as input, // and gives back 3D values modulated for smooth transitioning between interaction modes. _handControl.update(_mouseX, _mouseY); - _myAvatar.setHandMovementValues(_handControl.getValues()); + _myAvatar.setMovedHandOffset(_handControl.getValues()); } // tell my avatar if the mouse is being pressed... diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 909a3d912f..9b351a7684 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -58,9 +58,7 @@ bool usingBigSphereCollisionTest = true; float chatMessageScale = 0.0015; float chatMessageHeight = 0.45; - Avatar::Avatar(bool isMine) { - _orientation.setToIdentity(); _velocity = glm::vec3(0.0f, 0.0f, 0.0f); @@ -92,11 +90,8 @@ Avatar::Avatar(bool isMine) { _interactingOther = NULL; for (int i = 0; i < MAX_DRIVE_KEYS; i++) _driveKeys[i] = false; - - _head.initialize(); _movedHandOffset = glm::vec3(0.0f, 0.0f, 0.0f); - _sphere = NULL; _handHoldingPosition = glm::vec3(0.0f, 0.0f, 0.0f); _distanceToNearestAvatar = std::numeric_limits::max(); _gravity = glm::vec3(0.0f, -1.0f, 0.0f); @@ -111,57 +106,6 @@ Avatar::Avatar(bool isMine) { else { _balls = NULL; } } -Avatar::Avatar(const Avatar &otherAvatar) :_head(otherAvatar._head) { //include the copy constructor for head - - _velocity = otherAvatar._velocity; - _thrust = otherAvatar._thrust; - _rotation = otherAvatar._rotation; - _bodyYaw = otherAvatar._bodyYaw; - _bodyPitch = otherAvatar._bodyPitch; - _bodyRoll = otherAvatar._bodyRoll; - _bodyPitchDelta = otherAvatar._bodyPitchDelta; - _bodyYawDelta = otherAvatar._bodyYawDelta; - _bodyRollDelta = otherAvatar._bodyRollDelta; - _mousePressed = otherAvatar._mousePressed; - _mode = otherAvatar._mode; - _isMine = otherAvatar._isMine; - _renderYaw = otherAvatar._renderYaw; - _maxArmLength = otherAvatar._maxArmLength; - _transmitterTimer = otherAvatar._transmitterTimer; - _transmitterIsFirstData = otherAvatar._transmitterIsFirstData; - _transmitterTimeLastReceived = otherAvatar._transmitterTimeLastReceived; - _transmitterHz = otherAvatar._transmitterHz; - _transmitterInitialReading = otherAvatar._transmitterInitialReading; - _transmitterPackets = otherAvatar._transmitterPackets; - _isTransmitterV2Connected = otherAvatar._isTransmitterV2Connected; - _TEST_bigSphereRadius = otherAvatar._TEST_bigSphereRadius; - _TEST_bigSpherePosition = otherAvatar._TEST_bigSpherePosition; - _movedHandOffset = otherAvatar._movedHandOffset; - - _orientation.set(otherAvatar._orientation); - - _sphere = NULL; - - initializeSkeleton(); - - for (int i = 0; i < MAX_DRIVE_KEYS; i++) _driveKeys[i] = otherAvatar._driveKeys[i]; - - _distanceToNearestAvatar = otherAvatar._distanceToNearestAvatar; - - initializeSkeleton(); - -} - -Avatar::~Avatar() { - if (_sphere != NULL) { - gluDeleteQuadric(_sphere); - } -} - -Avatar* Avatar::clone() const { - return new Avatar(*this); -} - void Avatar::reset() { _headPitch = _headYaw = _headRoll = 0; _head.leanForward = _head.leanSideways = 0; @@ -472,8 +416,6 @@ void Avatar::simulate(float deltaTime) { } } - - void Avatar::checkForMouseRayTouching() { for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { @@ -489,13 +431,10 @@ void Avatar::checkForMouseRayTouching() { } } - void Avatar::setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction ) { _mouseRayOrigin = origin; _mouseRayDirection = direction; } - - void Avatar::updateHandMovementAndTouching(float deltaTime) { // reset hand and arm positions according to hand movement @@ -612,12 +551,6 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) { } } - -float Avatar::getHeight() { - return _height; -} - - void Avatar::updateCollisionWithSphere(glm::vec3 position, float radius, float deltaTime) { float myBodyApproximateBoundingRadius = 1.0f; glm::vec3 vectorFromMyBodyToBigSphere(_position - position); @@ -656,9 +589,6 @@ void Avatar::updateCollisionWithSphere(glm::vec3 position, float radius, float d } } - - - void Avatar::updateAvatarCollisions(float deltaTime) { // Reset detector for nearest avatar @@ -689,9 +619,6 @@ void Avatar::updateAvatarCollisions(float deltaTime) { } } - - - //detect collisions with other avatars and respond void Avatar::applyCollisionWithOtherAvatar(Avatar * otherAvatar, float deltaTime) { @@ -747,8 +674,6 @@ void Avatar::applyCollisionWithOtherAvatar(Avatar * otherAvatar, float deltaTime otherAvatar->_velocity *= bodyMomentum; } - - void Avatar::setDisplayingHead(bool displayingHead) { _displayingHead = displayingHead; } @@ -851,16 +776,6 @@ void Avatar::render(bool lookingInMirror, glm::vec3 cameraPosition) { } } - - -void Avatar::setHandMovementValues(glm::vec3 handOffset) { - _movedHandOffset = handOffset; -} - -AvatarMode Avatar::getMode() { - return _mode; -} - void Avatar::initializeSkeleton() { for (int b=0; b irisTexture; -vector iris_texture; -unsigned int iris_texture_width = 512; -unsigned int iris_texture_height = 256; - -Head::Head() { - if (iris_texture.size() == 0) { - switchToResourcesParentIfRequired(); - unsigned error = lodepng::decode(iris_texture, iris_texture_width, iris_texture_height, iris_texture_file); - if (error != 0) { - printLog("error %u: %s\n", error, lodepng_error_text(error)); - } - } -} - -Head::Head(const Head &head) { - - yawRate = head.yawRate; - noise = head.noise; - leanForward = head.leanForward; - leanSideways = head.leanSideways; - - _sphere = NULL; - _returnHeadToCenter = head._returnHeadToCenter; - _audioLoudness = head._audioLoudness; - _skinColor = head._skinColor; - _position = head._position; - _rotation = head._rotation; - _lookatPosition = head._lookatPosition; - _leftEyePosition = head._leftEyePosition; - _rightEyePosition = head._rightEyePosition; - _yaw = head._yaw; - _pitch = head._pitch; - _roll = head._roll; - _pitchRate = head._pitchRate; - _rollRate = head._rollRate; - _eyeballPitch[0] = head._eyeballPitch[0]; - _eyeballYaw [0] = head._eyeballYaw [0]; - _eyebrowPitch[0] = head._eyebrowPitch[0]; - _eyebrowRoll [0] = head._eyebrowRoll [0]; - _eyeballPitch[1] = head._eyeballPitch[1]; - _eyeballYaw [1] = head._eyeballYaw [1]; - _eyebrowPitch[1] = head._eyebrowPitch[1]; - _eyebrowRoll [1] = head._eyebrowRoll [1]; - _eyeballScaleX = head._eyeballScaleX; - _eyeballScaleY = head._eyeballScaleY; - _eyeballScaleZ = head._eyeballScaleZ; - _interPupilDistance = head._interPupilDistance; - _interBrowDistance = head._interBrowDistance; - _nominalPupilSize = head._nominalPupilSize; - _pupilSize = head._pupilSize; - _mouthPitch = head._mouthPitch; - _mouthYaw = head._mouthYaw; - _mouthWidth = head._mouthWidth; - _mouthHeight = head._mouthHeight; - _pitchTarget = head._pitchTarget; - _yawTarget = head._yawTarget; - _noiseEnvelope = head._noiseEnvelope; - _pupilConverge = head._pupilConverge; - _scale = head._scale; - _eyeContact = head._eyeContact; - _browAudioLift = head._browAudioLift; - _eyeContactTarget = head._eyeContactTarget; - _orientation = head._orientation; - _bodyYaw = head._bodyYaw; - _lastLoudness = head._lastLoudness; - _averageLoudness = head._averageLoudness; - _audioAttack = head._audioAttack; - _looking = head._looking; - _gravity = head._gravity; - _returnSpringScale = head._returnSpringScale; -} - - - -void Head::initialize() { - - _bodyYaw = 0.0f; - _audioLoudness = 0.0; - _skinColor = glm::vec3(0.0f, 0.0f, 0.0f); - _position = glm::vec3(0.0f, 0.0f, 0.0f); - _lookatPosition = glm::vec3(0.0f, 0.0f, 0.0f); - _gravity = glm::vec3(0.0f, -1.0f, 0.0f); // default - _yaw = 0.0f; - _pitch = 0.0f; - _roll = 0.0f; - _pupilSize = 0.10; - _interPupilDistance = 0.6; - _interBrowDistance = 0.75; - _nominalPupilSize = 0.10; - _pitchRate = 0.0; - yawRate = 0.0; - _rollRate = 0.0; +Head::Head() : + yawRate(0.0f), + noise(0.0f), + leanForward(0.0f), + leanSideways(0.0f), + _audioLoudness(0.0f), + _skinColor(0.0f, 0.0f, 0.0f), + _position(0.0f, 0.0f, 0.0f), + _rotation(0.0f, 0.0f, 0.0f), + _lookatPosition(0.0f, 0.0f, 0.0f), + _yaw(0.0f), + _pitch(0.0f), + _roll(0.0f), + _eyeballPitch(), + _eyeballYaw(), + _interBrowDistance(0.75f), + _mouthPitch(0), + _mouthYaw(0), + _mouthWidth(1.0f), + _mouthHeight(0.2f), + _pitchTarget(0.0f), + _yawTarget(0.0f), + _noiseEnvelope(1.0f), + _scale(1.0f), + _eyeContact(1), + _browAudioLift(0.0f), + _gravity(0.0f, -1.0f, 0.0f), + _lastLoudness(0.0f), + _averageLoudness(0.0f), + _audioAttack(0.0f), + _returnSpringScale(1.0f), + _bodyYaw(0.0f), + _eyeContactTarget(LEFT_EYE) +{ _eyebrowPitch[0] = -30; _eyebrowPitch[1] = -30; _eyebrowRoll [0] = 20; _eyebrowRoll [1] = -20; - _mouthPitch = 0; - _mouthYaw = 0; - _mouthWidth = 1.0; - _mouthHeight = 0.2; - _eyeballPitch[0] = 0; - _eyeballPitch[1] = 0; - _eyeballScaleX = 1.2; - _eyeballScaleY = 1.5; - _eyeballScaleZ = 1.0; - _eyeballYaw[0] = 0; - _eyeballYaw[1] = 0; - _pitchTarget = 0; - _yawTarget = 0; - _noiseEnvelope = 1.0; - _pupilConverge = 10.0; - leanForward = 0.0; - leanSideways = 0.0; - _eyeContact = 1; - _eyeContactTarget = LEFT_EYE; - _scale = 1.0; - _audioAttack = 0.0; - _averageLoudness = 0.0; - _lastLoudness = 0.0; - _browAudioLift = 0.0; - noise = 0; - _returnSpringScale = 1.0; - _sphere = NULL; } void Head::setPositionRotationAndScale(glm::vec3 p, glm::vec3 r, float s) { - _position = p; _scale = s; _yaw = r.x; @@ -163,15 +80,6 @@ void Head::setPositionRotationAndScale(glm::vec3 p, glm::vec3 r, float s) { _roll = r.z; } -void Head::setSkinColor(glm::vec3 c) { - _skinColor = c; -} - -void Head::setAudioLoudness(float loudness) { - _audioLoudness = loudness; -} - - void Head::setNewTarget(float pitch, float yaw) { _pitchTarget = pitch; _yawTarget = yaw; @@ -180,7 +88,7 @@ void Head::setNewTarget(float pitch, float yaw) { void Head::simulate(float deltaTime, bool isMine) { //generate orientation directions based on Euler angles... - _orientation.setToPitchYawRoll( _pitch, _bodyYaw + _yaw, _roll); + _orientation.setToPitchYawRoll( -_pitch, _bodyYaw + _yaw, _roll); //calculate the eye positions (algorithm still being designed) updateEyePositions(); @@ -238,15 +146,21 @@ void Head::simulate(float deltaTime, bool isMine) { if (randFloat() < 0.1) { _eyeContactTarget = MOUTH; } else { - if (randFloat() < 0.5) _eyeContactTarget = LEFT_EYE; else _eyeContactTarget = RIGHT_EYE; + if (randFloat() < 0.5) { + _eyeContactTarget = LEFT_EYE; + } else { + _eyeContactTarget = RIGHT_EYE; + } } } + // Set eyeball pitch and yaw to make contact - float eye_target_yaw_adjust = 0; - float eye_target_pitch_adjust = 0; - if (_eyeContactTarget == LEFT_EYE) eye_target_yaw_adjust = DEGREES_BETWEEN_VIEWER_EYES; - if (_eyeContactTarget == RIGHT_EYE) eye_target_yaw_adjust = -DEGREES_BETWEEN_VIEWER_EYES; - if (_eyeContactTarget == MOUTH) eye_target_pitch_adjust = DEGREES_TO_VIEWER_MOUTH; + float eye_target_yaw_adjust = 0.0f; + float eye_target_pitch_adjust = 0.0f; + + if (_eyeContactTarget == LEFT_EYE ) { eye_target_yaw_adjust = DEGREES_BETWEEN_VIEWER_EYES; } + if (_eyeContactTarget == RIGHT_EYE) { eye_target_yaw_adjust = -DEGREES_BETWEEN_VIEWER_EYES; } + if (_eyeContactTarget == MOUTH ) { eye_target_pitch_adjust = DEGREES_TO_VIEWER_MOUTH; } _eyeballPitch[0] = _eyeballPitch[1] = -_pitch + eye_target_pitch_adjust; _eyeballYaw [0] = _eyeballYaw [1] = _yaw + eye_target_yaw_adjust; @@ -290,7 +204,6 @@ void Head::simulate(float deltaTime, bool isMine) { } - void Head::updateEyePositions() { float rightShift = _scale * 0.27f; float upShift = _scale * 0.38f; @@ -306,7 +219,6 @@ void Head::updateEyePositions() { + _orientation.getFront() * frontShift; } - void Head::setLooking(bool looking) { _looking = looking; @@ -320,16 +232,6 @@ void Head::setLooking(bool looking) { } } -/* -void Head::setLookatPosition(glm::vec3 l) { - _lookatPosition = l; -} - -void Head::setGravity(glm::vec3 gravity) { - _gravity = gravity; -} -*/ - glm::vec3 Head::getApproximateEyePosition() { return _leftEyePosition + (_rightEyePosition - _leftEyePosition) * ONE_HALF; } @@ -401,10 +303,10 @@ void Head::render(bool lookingInMirror) { glPopMatrix(); // Mouth - const float MIN_LOUDNESS_SCALE_WIDTH = 0.7f; - const float WIDTH_SENSITIVITY = 60.f; - const float HEIGHT_SENSITIVITY = 30.f; - const float MIN_LOUDNESS_SCALE_HEIGHT = 1.0f; +// const float MIN_LOUDNESS_SCALE_WIDTH = 0.7f; +// const float WIDTH_SENSITIVITY = 60.f; +// const float HEIGHT_SENSITIVITY = 30.f; +// const float MIN_LOUDNESS_SCALE_HEIGHT = 1.0f; glPushMatrix(); glTranslatef(0,-0.35,0.75); glColor3f(0,0,0); @@ -421,9 +323,6 @@ void Head::render(bool lookingInMirror) { glutSolidCube(0.5); glPopMatrix(); - - // the original code from Philip's implementation - //previouseRenderEyeBalls(); glPopMatrix(); @@ -436,26 +335,30 @@ void Head::render(bool lookingInMirror) { } } - - - void Head::renderEyeBalls() { - - //make the texture for the iris... - if (_sphere == NULL) { - _sphere = gluNewQuadric(); - gluQuadricTexture(_sphere, GL_TRUE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gluQuadricOrientation(_sphere, GLU_OUTSIDE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, iris_texture_width, iris_texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &iris_texture[0]); + + if (::irisTexture.size() == 0) { + switchToResourcesParentIfRequired(); + unsigned error = lodepng::decode(::irisTexture, IRIS_TEXTURE_WIDTH, IRIS_TEXTURE_HEIGHT, IRIS_TEXTURE_FILENAME); + if (error != 0) { + printLog("error %u: %s\n", error, lodepng_error_text(error)); + } } + // setup the texutre to be used on each eye + GLUquadric* irisQuadric = gluNewQuadric(); + gluQuadricTexture(irisQuadric, GL_TRUE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gluQuadricOrientation(irisQuadric, GLU_OUTSIDE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, IRIS_TEXTURE_WIDTH, IRIS_TEXTURE_HEIGHT, + 0, GL_RGBA, GL_UNSIGNED_BYTE, &::irisTexture[0]); + // left eyeball glPushMatrix(); glColor3fv(_eyeColor); glTranslatef(_leftEyePosition.x, _leftEyePosition.y, _leftEyePosition.z); - gluSphere(_sphere, 0.02, 30, 30); + gluSphere(irisQuadric, 0.02, 30, 30); glPopMatrix(); // left iris @@ -474,7 +377,7 @@ void Head::renderEyeBalls() { glTranslatef( 0.0f, -0.018f, 0.0f);//push the iris out a bit (otherwise - inside of eyeball!) glScalef( 1.0f, 0.5f, 1.0f); // flatten the iris glEnable(GL_TEXTURE_2D); - gluSphere(_sphere, 0.007, 15, 15); + gluSphere(irisQuadric, 0.007, 15, 15); glDisable(GL_TEXTURE_2D); glPopMatrix(); } @@ -484,7 +387,7 @@ void Head::renderEyeBalls() { glPushMatrix(); glColor3fv(_eyeColor); glTranslatef(_rightEyePosition.x, _rightEyePosition.y, _rightEyePosition.z); - gluSphere(_sphere, 0.02, 30, 30); + gluSphere(irisQuadric, 0.02, 30, 30); glPopMatrix(); //right iris @@ -503,89 +406,16 @@ void Head::renderEyeBalls() { glTranslatef( 0.0f, -0.018f, 0.0f);//push the iris out a bit (otherwise - inside of eyeball!) glScalef( 1.0f, 0.5f, 1.0f); // flatten the iris glEnable(GL_TEXTURE_2D); - gluSphere(_sphere, 0.007, 15, 15); + gluSphere(irisQuadric, 0.007, 15, 15); glDisable(GL_TEXTURE_2D); glPopMatrix(); } + + // delete the iris quadric now that we're done with it + gluDeleteQuadric(irisQuadric); glPopMatrix(); } - - - - -void Head::previouseRenderEyeBalls() { - - glTranslatef(0, 1.0, 0); - - glTranslatef(-_interPupilDistance/2.0,-0.68,0.7); - // Right Eye - glRotatef(-10, 1, 0, 0); - glColor3fv(_eyeColor); - glPushMatrix(); - { - glTranslatef(_interPupilDistance/10.0, 0, 0.05); - glRotatef(20, 0, 0, 1); - glScalef(_eyeballScaleX, _eyeballScaleY, _eyeballScaleZ); - glutSolidSphere(0.25, 30, 30); - } - glPopMatrix(); - - // Right Pupil - if (_sphere == NULL) { - _sphere = gluNewQuadric(); - gluQuadricTexture(_sphere, GL_TRUE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gluQuadricOrientation(_sphere, GLU_OUTSIDE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, iris_texture_width, iris_texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &iris_texture[0]); - } - - glPushMatrix(); - { - glRotatef(_eyeballPitch[1], 1, 0, 0); - glRotatef(_eyeballYaw[1] + _yaw + _pupilConverge, 0, 1, 0); - glTranslatef(0,0,.35); - glRotatef(-75,1,0,0); - glScalef(1.0, 0.4, 1.0); - - glEnable(GL_TEXTURE_2D); - gluSphere(_sphere, _pupilSize, 15, 15); - glDisable(GL_TEXTURE_2D); - } - glPopMatrix(); - - - // Left Eye - glColor3fv(_eyeColor); - glTranslatef(_interPupilDistance, 0, 0); - glPushMatrix(); - { - glTranslatef(-_interPupilDistance/10.0, 0, .05); - glRotatef(-20, 0, 0, 1); - glScalef(_eyeballScaleX, _eyeballScaleY, _eyeballScaleZ); - glutSolidSphere(0.25, 30, 30); - } - glPopMatrix(); - - // Left Pupil - glPushMatrix(); - { - glRotatef(_eyeballPitch[0], 1, 0, 0); - glRotatef(_eyeballYaw[0] + _yaw - _pupilConverge, 0, 1, 0); - glTranslatef(0, 0, .35); - glRotatef(-75, 1, 0, 0); - glScalef(1.0, 0.4, 1.0); - - glEnable(GL_TEXTURE_2D); - gluSphere(_sphere, _pupilSize, 15, 15); - glDisable(GL_TEXTURE_2D); - } - glPopMatrix(); -} - - - void Head::debugRenderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition) { glColor3f(0.0f, 0.0f, 0.0f); diff --git a/interface/src/Head.h b/interface/src/Head.h index 209ef0704d..8f5afd052a 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -16,36 +16,38 @@ #include "SerialInterface.h" #include "Orientation.h" -enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH}; +enum eyeContactTargets +{ + LEFT_EYE, + RIGHT_EYE, + MOUTH +}; class Head { public: Head(); - Head(const Head &otherHead); - - void initialize(); void simulate(float deltaTime, bool isMine); - void setPositionRotationAndScale(glm::vec3 position, glm::vec3 rotation, float scale); - void setSkinColor(glm::vec3 color); - void setAudioLoudness(float loudness); void render(bool lookingInMirror); - void setNewTarget(float, float); - void setSpringScale(float s) { _returnSpringScale = s; } - void setLookatPosition(glm::vec3 l ) { _lookatPosition = l; } - void setLooking(bool looking); - void setGravity(glm::vec3 gravity) { _gravity = gravity; } - void setBodyYaw(float y) { _bodyYaw = y; } - - glm::vec3 getApproximateEyePosition(); - - // Do you want head to try to return to center (depends on interface detected) - void setReturnToCenter(bool returnHeadToCenter) { _returnHeadToCenter = returnHeadToCenter; } - const bool getReturnToCenter() const { return _returnHeadToCenter; } - - float getAverageLoudness() {return _averageLoudness;}; - void setAverageLoudness(float al) { _averageLoudness = al;}; + void setLooking(bool looking); + void setPositionRotationAndScale(glm::vec3 position, glm::vec3 rotation, float scale); + void setNewTarget(float, float); + + void setLookatPosition (glm::vec3 lookatPosition ) { _lookatPosition = lookatPosition; } + void setGravity (glm::vec3 gravity ) { _gravity = gravity; } + void setSkinColor (glm::vec3 skinColor ) { _skinColor = skinColor; } + void setBodyYaw (float bodyYaw ) { _bodyYaw = bodyYaw; } + void setSpringScale (float returnSpringScale ) { _returnSpringScale = returnSpringScale; } + void setAverageLoudness(float averageLoudness ) { _averageLoudness = averageLoudness; } + void setAudioLoudness (float audioLoudness ) { _audioLoudness = audioLoudness; } + void setReturnToCenter (bool returnHeadToCenter) { _returnHeadToCenter = returnHeadToCenter; } + + glm::vec3 getApproximateEyePosition(); + const bool getReturnToCenter() const { return _returnHeadToCenter; } // Do you want head to try to return to center (depends on interface detected) + float getAverageLoudness() {return _averageLoudness;}; + + //some public members (left-over from pulling Head out of Avatar - I may see about privatizing these later). float yawRate; float noise; float leanForward; @@ -53,63 +55,43 @@ public: private: - bool _returnHeadToCenter; - float _audioLoudness; - glm::vec3 _skinColor; - glm::vec3 _position; - glm::vec3 _rotation; - glm::vec3 _lookatPosition; - - glm::vec3 _leftEyePosition; - glm::vec3 _rightEyePosition; - - float _yaw; - float _pitch; - float _roll; - float _pitchRate; - float _rollRate; - float _eyeballPitch[2]; - float _eyeballYaw [2]; - float _eyebrowPitch[2]; - float _eyebrowRoll [2]; - float _eyeballScaleX; - float _eyeballScaleY; - float _eyeballScaleZ; - float _interPupilDistance; - float _interBrowDistance; - float _nominalPupilSize; - float _pupilSize; - float _mouthPitch; - float _mouthYaw; - float _mouthWidth; - float _mouthHeight; - float _pitchTarget; - float _yawTarget; - float _noiseEnvelope; - float _pupilConverge; - float _scale; - int _eyeContact; - float _browAudioLift; - eyeContactTargets _eyeContactTarget; + bool _returnHeadToCenter; + float _audioLoudness; + glm::vec3 _skinColor; + glm::vec3 _position; + glm::vec3 _rotation; + glm::vec3 _lookatPosition; + glm::vec3 _leftEyePosition; + glm::vec3 _rightEyePosition; + float _yaw; + float _pitch; + float _roll; + float _eyeballPitch[2]; + float _eyeballYaw [2]; + float _eyebrowPitch[2]; + float _eyebrowRoll [2]; + float _interBrowDistance; + float _mouthPitch; + float _mouthYaw; + float _mouthWidth; + float _mouthHeight; + float _pitchTarget; + float _yawTarget; + float _noiseEnvelope; + float _scale; + int _eyeContact; + float _browAudioLift; + bool _looking; + glm::vec3 _gravity; + float _lastLoudness; + float _averageLoudness; + float _audioAttack; + float _returnSpringScale; //strength of return springs Orientation _orientation; - float _bodyYaw; - - // Sound loudness information - float _lastLoudness; - float _averageLoudness; - float _audioAttack; - - bool _looking; - glm::vec3 _gravity; - - - GLUquadric* _sphere; - - // Strength of return springs - float _returnSpringScale; + float _bodyYaw; + eyeContactTargets _eyeContactTarget; // private methods - void previouseRenderEyeBalls(); void renderEyeBalls(); void debugRenderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition); void updateEyePositions(); diff --git a/interface/src/Oscilloscope.cpp b/interface/src/Oscilloscope.cpp index d081dbb0dc..088ef6ac14 100644 --- a/interface/src/Oscilloscope.cpp +++ b/interface/src/Oscilloscope.cpp @@ -20,13 +20,15 @@ using namespace std; namespace { // everything in here only exists while compiling this .cpp file // one sample buffer per channel - unsigned const N_SAMPLES_ALLOC = Oscilloscope::MAX_SAMPLES * Oscilloscope::MAX_CHANNELS; + unsigned const MAX_SAMPLES = Oscilloscope::MAX_SAMPLES_PER_CHANNEL * Oscilloscope::MAX_CHANNELS; // adding an x-coordinate yields twice the amount of vertices - unsigned const MAX_COORDS = Oscilloscope::MAX_SAMPLES * 2; - unsigned const N_COORDS_ALLOC = MAX_COORDS * Oscilloscope::MAX_CHANNELS; - - unsigned const N_ALLOC_TOTAL = N_SAMPLES_ALLOC + N_COORDS_ALLOC; + unsigned const MAX_COORDS_PER_CHANNEL = Oscilloscope::MAX_SAMPLES_PER_CHANNEL * 2; + // allocated once for each channel + unsigned const MAX_COORDS = MAX_COORDS_PER_CHANNEL * Oscilloscope::MAX_CHANNELS; + + // total amount of memory to allocate (in 16-bit integers) + unsigned const N_INT16_TO_ALLOC = MAX_SAMPLES + MAX_COORDS; } @@ -38,13 +40,13 @@ Oscilloscope::Oscilloscope(int w, int h, bool isEnabled) : // allocate enough space for the sample data and to turn it into // vertices and since they're all 'short', do so in one shot - _arrSamples = new short[N_ALLOC_TOTAL]; - memset(_arrSamples, 0, N_ALLOC_TOTAL * sizeof(short)); - _arrVertices = _arrSamples + N_SAMPLES_ALLOC; + _arrSamples = new short[N_INT16_TO_ALLOC]; + memset(_arrSamples, 0, N_INT16_TO_ALLOC * sizeof(short)); + _arrVertices = _arrSamples + MAX_SAMPLES; - // initialize write positions + // initialize write positions to start of each channel's region for (unsigned ch = 0; ch < MAX_CHANNELS; ++ch) { - _arrWritePos[ch] = MAX_SAMPLES * ch; + _arrWritePos[ch] = MAX_SAMPLES_PER_CHANNEL * ch; } } @@ -58,25 +60,31 @@ void Oscilloscope::addSamples(unsigned ch, short const* data, unsigned n) { if (! enabled || inputPaused) { return; } - - unsigned baseOffs = MAX_SAMPLES * ch; - unsigned endOffs = baseOffs + MAX_SAMPLES; - - unsigned writePos = _arrWritePos[ch]; - unsigned newWritePos = writePos + n; + // determine start/end offset of this channel's region + unsigned baseOffs = MAX_SAMPLES_PER_CHANNEL * ch; + unsigned endOffs = baseOffs + MAX_SAMPLES_PER_CHANNEL; + + // fetch write position for this channel + unsigned writePos = _arrWritePos[ch]; + + // determine write position after adding the samples + unsigned newWritePos = writePos + n; unsigned n2 = 0; if (newWritePos >= endOffs) { + // passed boundary of the circular buffer? -> we need to copy two blocks n2 = newWritePos - endOffs; newWritePos = baseOffs + n2; n -= n2; } - + + // copy data memcpy(_arrSamples + writePos, data, n * sizeof(short)); if (n2 > 0) { memcpy(_arrSamples + baseOffs, data + n, n2 * sizeof(short)); } - + + // set new write position for this channel _arrWritePos[ch] = newWritePos; } @@ -85,34 +93,38 @@ void Oscilloscope::render(int x, int y) { if (! enabled) { return; } - - // expand data to vertex data, now + + // determine lowpass / downsample factors int lowpass = -int(std::numeric_limits::min()) * _valLowpass; unsigned downsample = _valDownsample; // keep half of the buffer for writing and ensure an even vertex count - unsigned usedWidth = min(_valWidth, MAX_SAMPLES / (downsample * 2)) & ~1u; + unsigned usedWidth = min(_valWidth, MAX_SAMPLES_PER_CHANNEL / (downsample * 2)) & ~1u; unsigned usedSamples = usedWidth * downsample; + // expand samples to vertex data for (unsigned ch = 0; ch < MAX_CHANNELS; ++ch) { - - short const* basePtr = _arrSamples + MAX_SAMPLES * ch; - short const* endPtr = basePtr + MAX_SAMPLES; + // for each channel: determine memory regions + short const* basePtr = _arrSamples + MAX_SAMPLES_PER_CHANNEL * ch; + short const* endPtr = basePtr + MAX_SAMPLES_PER_CHANNEL; short const* inPtr = _arrSamples + _arrWritePos[ch]; - short* outPtr = _arrVertices + MAX_COORDS * ch; + short* outPtr = _arrVertices + MAX_COORDS_PER_CHANNEL * ch; int sample = 0, x = usedWidth; for (int i = int(usedSamples); --i >= 0 ;) { - if (inPtr == basePtr) { + // handle boundary, reading the circular sample buffer inPtr = endPtr; } - sample += ((*--inPtr - sample) * lowpass) >> 15; + // read and (eventually) filter sample + sample += ((*--inPtr - sample) * lowpass) >> 15; + // write every nth as y with a corresponding x-coordinate if (i % downsample == 0) { *outPtr++ = short(--x); *outPtr++ = short(sample); } } } - + + // set up rendering state (vertex data lives at _arrVertices) glLineWidth(1.0); glDisable(GL_LINE_SMOOTH); glPushMatrix(); @@ -120,12 +132,20 @@ void Oscilloscope::render(int x, int y) { glScaled(1.0f, _valHeight / 32767.0f, 1.0f); glVertexPointer(2, GL_SHORT, 0, _arrVertices); glEnableClientState(GL_VERTEX_ARRAY); + + // render channel 0 glColor3f(1.0f, 1.0f, 1.0f); - glDrawArrays(GL_LINE_STRIP, MAX_SAMPLES * 0, usedWidth); + glDrawArrays(GL_LINES, MAX_SAMPLES_PER_CHANNEL * 0, usedWidth); + + // render channel 1 glColor3f(0.0f, 1.0f ,1.0f); - glDrawArrays(GL_LINE_STRIP, MAX_SAMPLES * 1, usedWidth); + glDrawArrays(GL_LINES, MAX_SAMPLES_PER_CHANNEL * 1, usedWidth); + + // render channel 2 glColor3f(0.0f, 1.0f ,1.0f); - glDrawArrays(GL_LINE_STRIP, MAX_SAMPLES * 2, usedWidth); + glDrawArrays(GL_LINES, MAX_SAMPLES_PER_CHANNEL * 2, usedWidth); + + // reset rendering state glDisableClientState(GL_VERTEX_ARRAY); glPopMatrix(); } diff --git a/interface/src/Oscilloscope.h b/interface/src/Oscilloscope.h index 2474753cdf..8c0b727b6e 100644 --- a/interface/src/Oscilloscope.h +++ b/interface/src/Oscilloscope.h @@ -13,31 +13,19 @@ class Oscilloscope { public: - static unsigned const MAX_CHANNELS = 3; - static unsigned const MAX_SAMPLES = 4096; // per channel -private: - unsigned _valWidth; - unsigned _valHeight; - short* _arrSamples; - short* _arrVertices; - unsigned _arrWritePos[MAX_CHANNELS]; - - float _valLowpass; - unsigned _valDownsample; - -public: - Oscilloscope(int width, int height, bool isEnabled); ~Oscilloscope(); - volatile bool enabled; - volatile bool inputPaused; - - void addSamples(unsigned ch, short const* data, unsigned n); void render(int x, int y); + static unsigned const MAX_CHANNELS = 3; + static unsigned const MAX_SAMPLES_PER_CHANNEL = 4096; + + volatile bool enabled; + volatile bool inputPaused; + void setLowpass(float w) { assert(w > 0.0f && w <= 1.0f); _valLowpass = w; } void setDownsampling(unsigned f) { assert(f > 0); _valDownsample = f; } @@ -46,8 +34,16 @@ private: Oscilloscope(Oscilloscope const&); // = delete; Oscilloscope& operator=(Oscilloscope const&); // = delete; - // implementation - inline short* bufferBase(int i, int channel); + // state variables + + unsigned _valWidth; + unsigned _valHeight; + short* _arrSamples; + short* _arrVertices; + unsigned _arrWritePos[MAX_CHANNELS]; + + float _valLowpass; + unsigned _valDownsample; }; #endif /* defined(__interface__oscilloscope__) */ diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index ac74d81c7f..a3796f68c1 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -417,11 +417,6 @@ int VoxelSystem::updateNodeInArraysAsPartialVBO(VoxelNode* node) { return 0; // not-updated } -VoxelSystem* VoxelSystem::clone() const { - // this still needs to be implemented, will need to be used if VoxelSystem is attached to agent - return NULL; -} - void VoxelSystem::init() { _renderWarningsOn = false; diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index a3560c1b31..2d6d9717f6 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -31,7 +31,6 @@ public: ~VoxelSystem(); int parseData(unsigned char* sourceBuffer, int numBytes); - VoxelSystem* clone() const; void setViewFrustum(ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; }; @@ -82,6 +81,10 @@ public: creationMode mode, bool destructive = false, bool debug = false); private: + // disallow copying of VoxelSystem objects + VoxelSystem(const VoxelSystem&); + VoxelSystem& operator= (const VoxelSystem&); + int _callsToTreesToArrays; VoxelNodeBag _removedVoxels; diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 689b4c6cd9..a0f68e299b 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -24,6 +24,8 @@ AudioInjector::AudioInjector(const char* filename) : _indexOfNextSlot(0), _isInjectingAudio(false) { + loadRandomIdentifier(_streamIdentifier, STREAM_IDENTIFIER_NUM_BYTES); + std::fstream sourceFile; sourceFile.open(filename, std::ios::in | std::ios::binary); @@ -51,6 +53,8 @@ AudioInjector::AudioInjector(int maxNumSamples) : _indexOfNextSlot(0), _isInjectingAudio(false) { + loadRandomIdentifier(_streamIdentifier, STREAM_IDENTIFIER_NUM_BYTES); + _audioSampleArray = new int16_t[maxNumSamples]; memset(_audioSampleArray, 0, _numTotalSamples * sizeof(int16_t)); } @@ -65,13 +69,18 @@ void AudioInjector::injectAudio(UDPSocket* injectorSocket, sockaddr* destination timeval startTime; - // one byte for header, 3 positional floats, 1 bearing float, 1 attenuation modifier byte - int leadingBytes = 1 + (sizeof(float) * 4) + 1; + // calculate the number of bytes required for additional data + int leadingBytes = sizeof(PACKET_HEADER) + sizeof(_streamIdentifier) + + sizeof(_position) + sizeof(_bearing) + sizeof(_volume); unsigned char dataPacket[BUFFER_LENGTH_BYTES + leadingBytes]; dataPacket[0] = PACKET_HEADER_INJECT_AUDIO; unsigned char *currentPacketPtr = dataPacket + 1; + // copy the identifier for this injector + memcpy(currentPacketPtr, &_streamIdentifier, sizeof(_streamIdentifier)); + currentPacketPtr += sizeof(_streamIdentifier); + memcpy(currentPacketPtr, &_position, sizeof(_position)); currentPacketPtr += sizeof(_position); diff --git a/libraries/audio/src/AudioInjector.h b/libraries/audio/src/AudioInjector.h index eb22df1177..2571947e99 100644 --- a/libraries/audio/src/AudioInjector.h +++ b/libraries/audio/src/AudioInjector.h @@ -13,14 +13,14 @@ #include +#include "AudioRingBuffer.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; class AudioInjector { - friend class AudioInjectionManager; - public: AudioInjector(const char* filename); AudioInjector(int maxNumSamples); @@ -43,6 +43,7 @@ public: void addSample(const int16_t sample); void addSamples(int16_t* sampleBuffer, int numSamples); private: + unsigned char _streamIdentifier[STREAM_IDENTIFIER_NUM_BYTES]; int16_t* _audioSampleArray; int _numTotalSamples; glm::vec3 _position; diff --git a/libraries/audio/src/AudioRingBuffer.cpp b/libraries/audio/src/AudioRingBuffer.cpp index 746ff523f8..59b35b18a3 100644 --- a/libraries/audio/src/AudioRingBuffer.cpp +++ b/libraries/audio/src/AudioRingBuffer.cpp @@ -18,34 +18,17 @@ AudioRingBuffer::AudioRingBuffer(int ringSamples, int bufferSamples) : _endOfLastWrite(NULL), _started(false), _shouldBeAddedToMix(false), - _shouldLoopbackForAgent(false) { - + _shouldLoopbackForAgent(false), + _streamIdentifier() +{ _buffer = new int16_t[_ringBufferLengthSamples]; _nextOutput = _buffer; }; -AudioRingBuffer::AudioRingBuffer(const AudioRingBuffer &otherRingBuffer) { - _ringBufferLengthSamples = otherRingBuffer._ringBufferLengthSamples; - _bufferLengthSamples = otherRingBuffer._bufferLengthSamples; - _started = otherRingBuffer._started; - _shouldBeAddedToMix = otherRingBuffer._shouldBeAddedToMix; - _shouldLoopbackForAgent = otherRingBuffer._shouldLoopbackForAgent; - - _buffer = new int16_t[_ringBufferLengthSamples]; - memcpy(_buffer, otherRingBuffer._buffer, sizeof(int16_t) * _ringBufferLengthSamples); - - _nextOutput = _buffer + (otherRingBuffer._nextOutput - otherRingBuffer._buffer); - _endOfLastWrite = _buffer + (otherRingBuffer._endOfLastWrite - otherRingBuffer._buffer); -} - AudioRingBuffer::~AudioRingBuffer() { delete[] _buffer; }; -AudioRingBuffer* AudioRingBuffer::clone() const { - return new AudioRingBuffer(*this); -} - const int AGENT_LOOPBACK_MODIFIER = 307; int AudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) { @@ -57,6 +40,12 @@ int AudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) { // if this came from an injector or interface client // there's data required for spatialization to pull out + if (sourceBuffer[0] == PACKET_HEADER_INJECT_AUDIO) { + // we've got a stream identifier to pull from the packet + memcpy(&_streamIdentifier, dataBuffer, sizeof(_streamIdentifier)); + dataBuffer += sizeof(_streamIdentifier); + } + memcpy(&_position, dataBuffer, sizeof(_position)); dataBuffer += (sizeof(_position)); diff --git a/libraries/audio/src/AudioRingBuffer.h b/libraries/audio/src/AudioRingBuffer.h index fb739629c9..b448f93cee 100644 --- a/libraries/audio/src/AudioRingBuffer.h +++ b/libraries/audio/src/AudioRingBuffer.h @@ -10,22 +10,19 @@ #define __interface__AudioRingBuffer__ #include + +#include + #include "AgentData.h" -struct Position { - float x; - float y; - float z; -}; +const int STREAM_IDENTIFIER_NUM_BYTES = 8; class AudioRingBuffer : public AgentData { public: AudioRingBuffer(int ringSamples, int bufferSamples); ~AudioRingBuffer(); - AudioRingBuffer(const AudioRingBuffer &otherRingBuffer); int parseData(unsigned char* sourceBuffer, int numBytes); - AudioRingBuffer* clone() const; int16_t* getNextOutput() const { return _nextOutput; } void setNextOutput(int16_t* nextOutput) { _nextOutput = nextOutput; } @@ -41,16 +38,21 @@ public: bool shouldBeAddedToMix() const { return _shouldBeAddedToMix; } void setShouldBeAddedToMix(bool shouldBeAddedToMix) { _shouldBeAddedToMix = shouldBeAddedToMix; } - const Position& getPosition() const { return _position; } + const glm::vec3& getPosition() const { return _position; } float getAttenuationRatio() const { return _attenuationRatio; } float getBearing() const { return _bearing; } bool shouldLoopbackForAgent() const { return _shouldLoopbackForAgent; } + const unsigned char* getStreamIdentifier() const { return _streamIdentifier; } short diffLastWriteNextOutput(); private: + // disallow copying of AudioRingBuffer objects + AudioRingBuffer(const AudioRingBuffer&); + AudioRingBuffer& operator= (const AudioRingBuffer&); + int _ringBufferLengthSamples; int _bufferLengthSamples; - Position _position; + glm::vec3 _position; float _attenuationRatio; float _bearing; int16_t* _nextOutput; @@ -59,6 +61,7 @@ private: bool _started; bool _shouldBeAddedToMix; bool _shouldLoopbackForAgent; + unsigned char _streamIdentifier[STREAM_IDENTIFIER_NUM_BYTES]; }; #endif /* defined(__interface__AudioRingBuffer__) */ diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index ab60088cf8..2e11e8aa84 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -19,7 +19,6 @@ using namespace std; using avatars_lib::printLog; - int packFloatAngleToTwoByte(unsigned char* buffer, float angle) { const float ANGLE_CONVERSION_RATIO = (std::numeric_limits::max() / 360.0); @@ -34,14 +33,6 @@ int unpackFloatAngleFromTwoByte(uint16_t* byteAnglePointer, float* destinationPo return sizeof(uint16_t); } -AvatarData::~AvatarData() { - -} - -AvatarData* AvatarData::clone() const { - return new AvatarData(*this); -} - int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { unsigned char* bufferStart = destinationBuffer; @@ -200,49 +191,9 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { return sourceBuffer - startPosition; } -const glm::vec3& AvatarData::getPosition() const { - return _position; -} - -void AvatarData::setPosition(glm::vec3 position) { - _position = position; -} - -void AvatarData::setHandPosition(glm::vec3 handPosition) { - _handPosition = handPosition; -} - -float AvatarData::getBodyYaw() { - return _bodyYaw; -} - -void AvatarData::setBodyYaw(float bodyYaw) { - _bodyYaw = bodyYaw; -} - -float AvatarData::getBodyPitch() { - return _bodyPitch; -} - -void AvatarData::setBodyPitch(float bodyPitch) { - _bodyPitch = bodyPitch; -} - -float AvatarData::getBodyRoll() { - return _bodyRoll; -} - -void AvatarData::setBodyRoll(float bodyRoll) { - _bodyRoll = bodyRoll; -} - void AvatarData::setHeadPitch(float p) { // Set head pitch and apply limits const float MAX_PITCH = 60; const float MIN_PITCH = -60; _headPitch = glm::clamp(p, MIN_PITCH, MAX_PITCH); -} - - - - +} \ No newline at end of file diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index f131f82c85..f37c4f3396 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -52,25 +52,23 @@ public: _wantResIn(false), _wantColor(true) { }; + const glm::vec3& getPosition() const { return _position; } + void setPosition(const glm::vec3 position) { _position = position; } - ~AvatarData(); - - AvatarData* clone() const; - - const glm::vec3& getPosition() const; - void setPosition(glm::vec3 position); - void setHandPosition(glm::vec3 handPosition); + void setHandPosition(const glm::vec3 handPosition) { _handPosition = handPosition; } int getBroadcastData(unsigned char* destinationBuffer); int parseData(unsigned char* sourceBuffer, int numBytes); // Body Rotation - float getBodyYaw(); - float getBodyPitch(); - float getBodyRoll(); - void setBodyYaw(float bodyYaw); - void setBodyPitch(float bodyPitch); - void setBodyRoll(float bodyRoll); + float getBodyYaw() const { return _bodyYaw; } + void setBodyYaw(float bodyYaw) { _bodyYaw = bodyYaw; } + + float getBodyPitch() const { return _bodyPitch; } + void setBodyPitch(float bodyPitch) { _bodyPitch = bodyPitch; } + + float getBodyRoll() const {return _bodyRoll; } + void setBodyRoll(float bodyRoll) { _bodyRoll = bodyRoll; } // Head Rotation void setHeadPitch(float p); @@ -134,6 +132,10 @@ public: void setWantDelta(bool wantDelta) { _wantDelta = wantDelta; } protected: + // privatize the copy constructor and assignment operator so they cannot be called + AvatarData(const AvatarData&); + AvatarData& operator= (const AvatarData&); + glm::vec3 _position; glm::vec3 _handPosition; diff --git a/libraries/shared/src/Agent.cpp b/libraries/shared/src/Agent.cpp index db4170515a..f21f06eba6 100644 --- a/libraries/shared/src/Agent.cpp +++ b/libraries/shared/src/Agent.cpp @@ -55,67 +55,6 @@ Agent::Agent(sockaddr* publicSocket, sockaddr* localSocket, char type, uint16_t } } -Agent::Agent(const Agent &otherAgent) : - _type(otherAgent._type), - _agentID(otherAgent._agentID), - _wakeMicrostamp(otherAgent._wakeMicrostamp), - _lastHeardMicrostamp(otherAgent._lastHeardMicrostamp), - _isAlive(otherAgent._isAlive) -{ - if (otherAgent._publicSocket) { - _publicSocket = new sockaddr(*otherAgent._localSocket); - } else { - _publicSocket = NULL; - } - - if (otherAgent._localSocket) { - _localSocket = new sockaddr(*otherAgent._localSocket); - } else { - _localSocket = NULL; - } - - if (otherAgent._activeSocket == otherAgent._publicSocket) { - _activeSocket = _publicSocket; - } else if (otherAgent._activeSocket == otherAgent._localSocket) { - _activeSocket = _localSocket; - } else { - _activeSocket = NULL; - } - - if (otherAgent._linkedData) { - _linkedData = otherAgent._linkedData->clone(); - } else { - _linkedData = NULL; - } - - if (otherAgent._bytesReceivedMovingAverage != NULL) { - _bytesReceivedMovingAverage = new SimpleMovingAverage(100); - memcpy(_bytesReceivedMovingAverage, otherAgent._bytesReceivedMovingAverage, sizeof(SimpleMovingAverage)); - } else { - _bytesReceivedMovingAverage = NULL; - } -} - -Agent& Agent::operator=(Agent otherAgent) { - swap(*this, otherAgent); - return *this; -} - -void Agent::swap(Agent &first, Agent &second) { - using std::swap; - - swap(first._isAlive, second._isAlive); - swap(first._publicSocket, second._publicSocket); - swap(first._localSocket, second._localSocket); - swap(first._activeSocket, second._activeSocket); - swap(first._type, second._type); - swap(first._linkedData, second._linkedData); - swap(first._agentID, second._agentID); - swap(first._wakeMicrostamp, second._wakeMicrostamp); - swap(first._lastHeardMicrostamp, second._lastHeardMicrostamp); - swap(first._bytesReceivedMovingAverage, second._bytesReceivedMovingAverage); -} - Agent::~Agent() { delete _publicSocket; delete _localSocket; @@ -130,6 +69,7 @@ const char* AGENT_TYPE_NAME_INTERFACE = "Client Interface"; const char* AGENT_TYPE_NAME_AUDIO_MIXER = "Audio Mixer"; const char* AGENT_TYPE_NAME_AVATAR_MIXER = "Avatar Mixer"; const char* AGENT_TYPE_NAME_AUDIO_INJECTOR = "Audio Injector"; +const char* AGENT_TYPE_NAME_ANIMATION_SERVER = "Animation Server"; const char* AGENT_TYPE_NAME_UNKNOWN = "Unknown"; const char* Agent::getTypeName() const { @@ -146,6 +86,8 @@ const char* Agent::getTypeName() const { return AGENT_TYPE_NAME_AVATAR_MIXER; case AGENT_TYPE_AUDIO_INJECTOR: return AGENT_TYPE_NAME_AUDIO_INJECTOR; + case AGENT_TYPE_ANIMATION_SERVER: + return AGENT_TYPE_NAME_ANIMATION_SERVER; default: return AGENT_TYPE_NAME_UNKNOWN; } diff --git a/libraries/shared/src/Agent.h b/libraries/shared/src/Agent.h index 55ef67c8e5..5201fd9048 100644 --- a/libraries/shared/src/Agent.h +++ b/libraries/shared/src/Agent.h @@ -24,9 +24,8 @@ class Agent { public: Agent(sockaddr* publicSocket, sockaddr* localSocket, char type, uint16_t agentID); - Agent(const Agent &otherAgent); ~Agent(); - Agent& operator=(Agent otherAgent); + bool operator==(const Agent& otherAgent); bool matches(sockaddr* otherPublicSocket, sockaddr* otherLocalSocket, char otherAgentType); @@ -66,7 +65,9 @@ public: static void printLog(Agent const&); private: - void swap(Agent &first, Agent &second); + // privatize copy and assignment operator to disallow Agent copying + Agent(const Agent &otherAgent); + Agent& operator=(Agent otherAgent); char _type; uint16_t _agentID; diff --git a/libraries/shared/src/AgentData.h b/libraries/shared/src/AgentData.h index f8bef16b41..342f501a1e 100644 --- a/libraries/shared/src/AgentData.h +++ b/libraries/shared/src/AgentData.h @@ -10,10 +10,9 @@ #define hifi_AgentData_h class AgentData { - public: - virtual ~AgentData() = 0; - virtual int parseData(unsigned char* sourceBuffer, int numBytes) = 0; - virtual AgentData* clone() const = 0; +public: + virtual ~AgentData() = 0; + virtual int parseData(unsigned char* sourceBuffer, int numBytes) = 0; }; #endif diff --git a/libraries/shared/src/AgentList.cpp b/libraries/shared/src/AgentList.cpp index fef0446056..c667f733a4 100644 --- a/libraries/shared/src/AgentList.cpp +++ b/libraries/shared/src/AgentList.cpp @@ -126,11 +126,7 @@ void AgentList::processBulkAgentData(sockaddr *senderAddress, unsigned char *pac if (!matchingAgent) { // we're missing this agent, we need to add it to the list - addOrUpdateAgent(NULL, NULL, AGENT_TYPE_AVATAR, agentID); - - // TODO: this is a really stupid way to do this - // Add a reverse iterator and go from the end of the list - matchingAgent = agentWithID(agentID); + matchingAgent = addOrUpdateAgent(NULL, NULL, AGENT_TYPE_AVATAR, agentID); } currentPosition += updateAgentWithData(matchingAgent, @@ -218,7 +214,7 @@ int AgentList::processDomainServerList(unsigned char *packetData, size_t dataByt return readAgents; } -bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType, uint16_t agentId) { +Agent* AgentList::addOrUpdateAgent(sockaddr* publicSocket, sockaddr* localSocket, char agentType, uint16_t agentId) { AgentList::iterator agent = end(); if (publicSocket != NULL) { @@ -250,7 +246,7 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, addAgentToList(newAgent); - return true; + return newAgent; } else { if (agent->getType() == AGENT_TYPE_AUDIO_MIXER || agent->getType() == AGENT_TYPE_VOXEL) { @@ -260,7 +256,7 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, } // we had this agent already, do nothing for now - return false; + return &*agent; } } diff --git a/libraries/shared/src/AgentList.h b/libraries/shared/src/AgentList.h index 280927929f..3ac7cf1f8d 100644 --- a/libraries/shared/src/AgentList.h +++ b/libraries/shared/src/AgentList.h @@ -59,7 +59,7 @@ public: Agent* agentWithAddress(sockaddr *senderAddress); Agent* agentWithID(uint16_t agentID); - bool addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType, uint16_t agentId); + Agent* addOrUpdateAgent(sockaddr* publicSocket, sockaddr* localSocket, char agentType, uint16_t agentId); void processAgentData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes); void processBulkAgentData(sockaddr *senderAddress, unsigned char *packetData, int numTotalBytes); diff --git a/libraries/shared/src/AgentTypes.h b/libraries/shared/src/AgentTypes.h index e095cb1035..4f3100fe03 100644 --- a/libraries/shared/src/AgentTypes.h +++ b/libraries/shared/src/AgentTypes.h @@ -24,5 +24,6 @@ const char AGENT_TYPE_AVATAR = 'I'; const char AGENT_TYPE_AUDIO_MIXER = 'M'; const char AGENT_TYPE_AVATAR_MIXER = 'W'; const char AGENT_TYPE_AUDIO_INJECTOR = 'A'; +const char AGENT_TYPE_ANIMATION_SERVER = 'a'; #endif diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index d6820897b8..113b3fdda0 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #ifdef _WIN32 #include "Syssocket.h" #endif @@ -114,6 +115,15 @@ void switchToResourcesParentIfRequired() { #endif } +void loadRandomIdentifier(unsigned char* identifierBuffer, int numBytes) { + // seed the the random number generator + srand(time(NULL)); + + for (int i = 0; i < numBytes; i++) { + identifierBuffer[i] = rand() % 256; + } +} + ////////////////////////////////////////////////////////////////////////////////////////// // Function: getCmdOption() // Description: Handy little function to tell you if a command line flag and option was @@ -215,6 +225,7 @@ bool createVoxelEditMessage(unsigned char command, short int sequence, sizeOut=actualMessageSize; memcpy(bufferOut,messageBuffer,actualMessageSize); } + delete[] messageBuffer; // clean up our temporary buffer return success; } diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 98baa5488a..d0e71ec71e 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -53,6 +53,8 @@ void setAtBit(unsigned char& byte, int bitIndex); void switchToResourcesParentIfRequired(); +void loadRandomIdentifier(unsigned char* identifierBuffer, int numBytes); + const char* getCmdOption(int argc, const char * argv[],const char* option); bool cmdOptionExists(int argc, const char * argv[],const char* option); diff --git a/voxel-server/src/VoxelAgentData.cpp b/voxel-server/src/VoxelAgentData.cpp index 4eb971f275..e25defef7a 100644 --- a/voxel-server/src/VoxelAgentData.cpp +++ b/voxel-server/src/VoxelAgentData.cpp @@ -11,19 +11,18 @@ #include #include -VoxelAgentData::VoxelAgentData() { - init(); +VoxelAgentData::VoxelAgentData() : + _viewSent(false), + _voxelPacketAvailableBytes(MAX_VOXEL_PACKET_SIZE), + _maxSearchLevel(1), + _maxLevelReachedInLastSearch(1) +{ + _voxelPacket = new unsigned char[MAX_VOXEL_PACKET_SIZE]; + _voxelPacketAt = _voxelPacket; + + resetVoxelPacket(); } -void VoxelAgentData::init() { - _voxelPacket = new unsigned char[MAX_VOXEL_PACKET_SIZE]; - _voxelPacketAvailableBytes = MAX_VOXEL_PACKET_SIZE; - _voxelPacketAt = _voxelPacket; - _maxSearchLevel = 1; - _maxLevelReachedInLastSearch = 1; - resetVoxelPacket(); - _viewSent = false; -} void VoxelAgentData::resetVoxelPacket() { _voxelPacket[0] = getWantColor() ? PACKET_HEADER_VOXEL_DATA : PACKET_HEADER_VOXEL_DATA_MONOCHROME; @@ -43,15 +42,6 @@ VoxelAgentData::~VoxelAgentData() { delete[] _voxelPacket; } -VoxelAgentData::VoxelAgentData(const VoxelAgentData &otherAgentData) { - memcpy(&_position, &otherAgentData._position, sizeof(_position)); - init(); -} - -VoxelAgentData* VoxelAgentData::clone() const { - return new VoxelAgentData(*this); -} - bool VoxelAgentData::updateCurrentViewFrustum() { bool currentViewFrustumChanged = false; ViewFrustum newestViewFrustum; diff --git a/voxel-server/src/VoxelAgentData.h b/voxel-server/src/VoxelAgentData.h index 99be7e6042..fbf5f12d3d 100644 --- a/voxel-server/src/VoxelAgentData.h +++ b/voxel-server/src/VoxelAgentData.h @@ -19,11 +19,7 @@ class VoxelAgentData : public AvatarData { public: VoxelAgentData(); ~VoxelAgentData(); - VoxelAgentData(const VoxelAgentData &otherAgentData); - - VoxelAgentData* clone() const; - void init(); // sets up data internals void resetVoxelPacket(); // resets voxel packet to after "V" header void writeToPacket(unsigned char* buffer, int bytes); // writes to end of packet @@ -52,7 +48,10 @@ public: bool getViewSent() const { return _viewSent; }; void setViewSent(bool viewSent) { _viewSent = viewSent; } -private: +private: + VoxelAgentData(const VoxelAgentData &); + VoxelAgentData& operator= (const VoxelAgentData&); + bool _viewSent; unsigned char* _voxelPacket; unsigned char* _voxelPacketAt; diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 25e86f1f8a..c268031e74 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #ifdef _WIN32 #include "Syssocket.h" @@ -31,6 +32,7 @@ const char* LOCAL_VOXELS_PERSIST_FILE = "resources/voxels.hio2"; const char* VOXELS_PERSIST_FILE = "/etc/highfidelity/voxel-server/resources/voxels.hio2"; +const double VOXEL_PERSIST_INTERVAL = 1000.0 * 30; // every 30 seconds const int VOXEL_LISTEN_PORT = 40106; @@ -54,6 +56,9 @@ bool wantLocalDomain = false; bool wantColorRandomizer = false; bool debugVoxelSending = false; +bool shouldShowAnimationDebug = false; + + EnvironmentData environmentData; @@ -341,13 +346,33 @@ void deepestLevelVoxelDistributor(AgentList* agentList, } // end if bag wasn't empty, and so we sent stuff... } +double lastPersistVoxels = 0; void persistVoxelsWhenDirty() { + double now = usecTimestampNow(); + double sinceLastTime = (now - ::lastPersistVoxels) / 1000.0; + // check the dirty bit and persist here... - if (::wantVoxelPersist && ::randomTree.isDirty()) { - printf("saving voxels to file...\n"); - randomTree.writeToFileV2(::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE); - randomTree.clearDirtyBit(); // tree is clean after saving - printf("DONE saving voxels to file...\n"); + if (::wantVoxelPersist && ::randomTree.isDirty() && sinceLastTime > VOXEL_PERSIST_INTERVAL) { + + { + PerformanceWarning warn(::shouldShowAnimationDebug, + "persistVoxelsWhenDirty() - reaverageVoxelColors()", ::shouldShowAnimationDebug); + + // after done inserting all these voxels, then reaverage colors + randomTree.reaverageVoxelColors(randomTree.rootNode); + } + + + { + PerformanceWarning warn(::shouldShowAnimationDebug, + "persistVoxelsWhenDirty() - writeToFileV2()", ::shouldShowAnimationDebug); + + printf("saving voxels to file...\n"); + randomTree.writeToFileV2(::wantLocalDomain ? LOCAL_VOXELS_PERSIST_FILE : VOXELS_PERSIST_FILE); + randomTree.clearDirtyBit(); // tree is clean after saving + printf("DONE saving voxels to file...\n"); + } + ::lastPersistVoxels = usecTimestampNow(); } } @@ -421,6 +446,10 @@ int main(int argc, const char * argv[]) ::debugVoxelSending = cmdOptionExists(argc, argv, DEBUG_VOXEL_SENDING); printf("debugVoxelSending=%s\n", (::debugVoxelSending ? "yes" : "no")); + const char* WANT_ANIMATION_DEBUG = "--shouldShowAnimationDebug"; + ::shouldShowAnimationDebug = cmdOptionExists(argc, argv, WANT_ANIMATION_DEBUG); + printf("shouldShowAnimationDebug=%s\n", (::shouldShowAnimationDebug ? "yes" : "no")); + const char* WANT_COLOR_RANDOMIZER = "--wantColorRandomizer"; ::wantColorRandomizer = cmdOptionExists(argc, argv, WANT_COLOR_RANDOMIZER); printf("wantColorRandomizer=%s\n", (::wantColorRandomizer ? "yes" : "no")); @@ -498,17 +527,26 @@ int main(int argc, const char * argv[]) // loop to send to agents requesting data while (true) { + // check to see if we need to persist our voxel state - persistVoxelsWhenDirty(); + persistVoxelsWhenDirty(); if (agentList->getAgentSocket()->receive(&agentPublicAddress, packetData, &receivedBytes)) { // XXXBHG: Hacked in support for 'S' SET command if (packetData[0] == PACKET_HEADER_SET_VOXEL || packetData[0] == PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) { bool destructive = (packetData[0] == PACKET_HEADER_SET_VOXEL_DESTRUCTIVE); + + PerformanceWarning warn(::shouldShowAnimationDebug, + destructive ? "PACKET_HEADER_SET_VOXEL_DESTRUCTIVE" : "PACKET_HEADER_SET_VOXEL", + ::shouldShowAnimationDebug); + unsigned short int itemNumber = (*((unsigned short int*)&packetData[1])); - printf("got %s - command from client receivedBytes=%ld itemNumber=%d\n", - destructive ? "PACKET_HEADER_SET_VOXEL_DESTRUCTIVE" : "PACKET_HEADER_SET_VOXEL", - receivedBytes,itemNumber); + + if (::shouldShowAnimationDebug) { + printf("got %s - command from client receivedBytes=%ld itemNumber=%d\n", + destructive ? "PACKET_HEADER_SET_VOXEL_DESTRUCTIVE" : "PACKET_HEADER_SET_VOXEL", + receivedBytes,itemNumber); + } int atByte = 3; unsigned char* pVoxelData = (unsigned char*)&packetData[3]; while (atByte < receivedBytes) { @@ -521,28 +559,35 @@ int main(int argc, const char * argv[]) int red = pVoxelData[voxelCodeSize+0]; int green = pVoxelData[voxelCodeSize+1]; int blue = pVoxelData[voxelCodeSize+2]; - printf("insert voxels - wantColorRandomizer=%s old r=%d,g=%d,b=%d \n", - (::wantColorRandomizer?"yes":"no"),red,green,blue); + + if (::shouldShowAnimationDebug) { + printf("insert voxels - wantColorRandomizer=%s old r=%d,g=%d,b=%d \n", + (::wantColorRandomizer?"yes":"no"),red,green,blue); + } + red = std::max(0,std::min(255,red + colorRandomizer)); green = std::max(0,std::min(255,green + colorRandomizer)); blue = std::max(0,std::min(255,blue + colorRandomizer)); - printf("insert voxels - wantColorRandomizer=%s NEW r=%d,g=%d,b=%d \n", - (::wantColorRandomizer?"yes":"no"),red,green,blue); + + if (::shouldShowAnimationDebug) { + printf("insert voxels - wantColorRandomizer=%s NEW r=%d,g=%d,b=%d \n", + (::wantColorRandomizer?"yes":"no"),red,green,blue); + } pVoxelData[voxelCodeSize+0]=red; pVoxelData[voxelCodeSize+1]=green; pVoxelData[voxelCodeSize+2]=blue; - float* vertices = firstVertexForCode(pVoxelData); - printf("inserting voxel at: %f,%f,%f\n",vertices[0],vertices[1],vertices[2]); - delete []vertices; + if (::shouldShowAnimationDebug) { + float* vertices = firstVertexForCode(pVoxelData); + printf("inserting voxel at: %f,%f,%f\n",vertices[0],vertices[1],vertices[2]); + delete []vertices; + } randomTree.readCodeColorBufferToTree(pVoxelData, destructive); // skip to next pVoxelData+=voxelDataSize; atByte+=voxelDataSize; } - // after done inserting all these voxels, then reaverage colors - randomTree.reaverageVoxelColors(randomTree.rootNode); } if (packetData[0] == PACKET_HEADER_ERASE_VOXEL) { @@ -575,6 +620,9 @@ int main(int argc, const char * argv[]) printf("got Z message == add scene\n"); addSphereScene(&randomTree); } + if (0==strcmp(command,(char*)"a message")) { + printf("got Z message == a message, nothing to do, just report\n"); + } totalLength += commandLength+1; } @@ -587,9 +635,12 @@ int main(int argc, const char * argv[]) if (packetData[0] == PACKET_HEADER_HEAD_DATA) { uint16_t agentID = 0; unpackAgentId(packetData + sizeof(PACKET_HEADER_HEAD_DATA), &agentID); - agentList->addOrUpdateAgent(&agentPublicAddress, &agentPublicAddress, AGENT_TYPE_AVATAR, agentID); + Agent* agent = agentList->addOrUpdateAgent(&agentPublicAddress, + &agentPublicAddress, + AGENT_TYPE_AVATAR, + agentID); - agentList->updateAgentWithData(&agentPublicAddress, packetData, receivedBytes); + agentList->updateAgentWithData(agent, packetData, receivedBytes); } } }