mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 08:04:01 +02:00
Merge branch 'master' of https://github.com/worklist/hifi
This commit is contained in:
commit
0539739720
36 changed files with 966 additions and 825 deletions
|
@ -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)
|
||||
|
|
26
animation-server/CMakeLists.txt
Normal file
26
animation-server/CMakeLists.txt
Normal 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})
|
||||
|
||||
|
398
animation-server/src/main.cpp
Normal file
398
animation-server/src/main.cpp
Normal 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;
|
||||
}
|
|
@ -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})
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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 |
BIN
interface/resources/images/iris.png
Normal file
BIN
interface/resources/images/iris.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 144 KiB |
|
@ -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...
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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__) */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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__) */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue