This commit is contained in:
Andrzej Kapolka 2013-05-19 18:38:09 -07:00
commit 0539739720
36 changed files with 966 additions and 825 deletions

View file

@ -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)

View file

@ -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})

View file

@ -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 <cmath>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <OctalCode.h>
#include <AgentList.h>
#include <AgentTypes.h>
#include <EnvironmentData.h>
#include <VoxelTree.h>
#include <SharedUtil.h>
#include <PacketHeaders.h>
#include <SceneUtils.h>
#ifdef _WIN32
#include "Syssocket.h"
#include "Systime.h"
#else
#include <sys/time.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#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;
}

View file

@ -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})

View file

@ -18,6 +18,7 @@
#include <signal.h>
#include <AgentList.h>
#include <Agent.h>
#include <AgentTypes.h>
#include <SharedUtil.h>
#include <StdDev.h>
@ -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);
}
}

View file

@ -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;

View file

@ -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();
}

View file

@ -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);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

View file

@ -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...

View file

@ -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<float>::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<NUM_AVATAR_JOINTS; b++) {
@ -1143,14 +1058,10 @@ const glm::vec3& Avatar::getHeadPosition() const {
return _joint[ AVATAR_JOINT_HEAD_BASE ].position;
}
glm::vec3 Avatar::getApproximateEyePosition() {
return _head.getApproximateEyePosition();
}
void Avatar::updateArmIKAndConstraints(float deltaTime) {
// determine the arm vector
@ -1401,7 +1312,6 @@ void Avatar::transmitterV2RenderLevels(int width, int height) {
glEnd();
}
void Avatar::setHeadFromGyros(glm::vec3* eulerAngles, glm::vec3* angularVelocity, float deltaTime, float smoothingTime) {
//
// Given absolute position and angular velocity information, update the avatar's head angles
@ -1440,8 +1350,6 @@ void Avatar::setHeadFromGyros(glm::vec3* eulerAngles, glm::vec3* angularVelocity
}
}
const char AVATAR_DATA_FILENAME[] = "avatar.ifd";
void Avatar::writeAvatarDataToFile() {
@ -1469,5 +1377,4 @@ void Avatar::readAvatarDataFromFile() {
}
fclose(avatarFile);
}
}
}

View file

@ -76,10 +76,7 @@ enum AvatarJointID
class Avatar : public AvatarData {
public:
Avatar(bool isMine);
~Avatar();
Avatar(const Avatar &otherAvatar);
Avatar* clone() const;
void reset();
void updateHeadFromGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity);
void updateFromMouse(int mouseX, int mouseY, int screenWidth, int screenHeight);
@ -102,18 +99,18 @@ public:
const glm::vec3& getSpringyHeadPosition() const ; // get the springy position of the avatar's head
const glm::vec3& getJointPosition(AvatarJointID j) const { return _joint[j].springyPosition; };
const glm::vec3& getBodyUpDirection() const { return _orientation.getUp(); };
float getSpeed() const { return _speed; };
float getSpeed() const { return _speed; }
const glm::vec3& getVelocity() const { return _velocity; };
float getGirth();
float getHeight();
float getHeight() const { return _height; }
AvatarMode getMode();
AvatarMode getMode() const { return _mode; }
void setMousePressed(bool pressed);
void render(bool lookingInMirror, glm::vec3 cameraPosition);
void renderBody(bool lookingInMirror);
void simulate(float);
void setHandMovementValues( glm::vec3 movement );
void setMovedHandOffset(glm::vec3 movedHandOffset) { _movedHandOffset = movedHandOffset; }
void updateArmIKAndConstraints( float deltaTime );
void setDisplayingHead( bool displayingHead );
@ -140,6 +137,9 @@ public:
void readAvatarDataFromFile();
private:
// privatize copy constructor and assignment operator to avoid copying
Avatar(const Avatar&);
Avatar& operator= (const Avatar&);
struct AvatarJoint
{
@ -179,7 +179,6 @@ private:
float _maxArmLength;
Orientation _orientation;
int _driveKeys[MAX_DRIVE_KEYS];
GLUquadric* _sphere;
float _renderYaw;
float _renderPitch; // Pitch from view frustum when this is own head
bool _transmitterIsFirstData;

View file

@ -27,135 +27,52 @@ float _MouthWidthChoices[3] = {0.5, 0.77, 0.3};
float _browWidth = 0.8;
float _browThickness = 0.16;
char iris_texture_file[] = "resources/images/green_eye.png";
const char IRIS_TEXTURE_FILENAME[] = "resources/images/iris.png";
unsigned int IRIS_TEXTURE_WIDTH = 768;
unsigned int IRIS_TEXTURE_HEIGHT = 498;
vector<unsigned char> irisTexture;
vector<unsigned char> 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);

View file

@ -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();

View file

@ -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<short>::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();
}

View file

@ -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__) */

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -13,14 +13,14 @@
#include <glm/glm.hpp>
#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;

View file

@ -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));

View file

@ -10,22 +10,19 @@
#define __interface__AudioRingBuffer__
#include <stdint.h>
#include <glm/glm.hpp>
#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__) */

View file

@ -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<uint16_t>::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);
}
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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

View file

@ -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;
}
}

View file

@ -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);

View file

@ -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

View file

@ -10,6 +10,7 @@
#include <cstdio>
#include <cstring>
#include <cctype>
#include <time.h>
#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;
}

View file

@ -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);

View file

@ -11,19 +11,18 @@
#include <cstring>
#include <cstdio>
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;

View file

@ -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;

View file

@ -19,6 +19,7 @@
#include <SharedUtil.h>
#include <PacketHeaders.h>
#include <SceneUtils.h>
#include <PerfStat.h>
#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);
}
}
}