mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 14:03:55 +02:00
Merge branch 'master' of https://github.com/worklist/hifi into view_frustum_work
This commit is contained in:
commit
0bec7156aa
31 changed files with 982 additions and 839 deletions
|
@ -133,7 +133,7 @@ int main(int argc, const char * argv[])
|
|||
|
||||
if (DEBUG_TO_SELF ||
|
||||
!agent->matches((sockaddr *)&agentPublicAddress, (sockaddr *)&agentLocalAddress, agentType)) {
|
||||
if (memchr(SOLO_AGENT_TYPES_STRING, agent->getType(), 1) == NULL) {
|
||||
if (memchr(SOLO_AGENT_TYPES, agent->getType(), sizeof(SOLO_AGENT_TYPES)) == NULL) {
|
||||
// this is an agent of which there can be multiple, just add them to the packet
|
||||
// don't send avatar agents to other avatars, that will come from avatar mixer
|
||||
if (agentType != AGENT_TYPE_AVATAR || agent->getType() != AGENT_TYPE_AVATAR) {
|
||||
|
|
101
eve/src/main.cpp
101
eve/src/main.cpp
|
@ -13,20 +13,31 @@
|
|||
#include <PacketHeaders.h>
|
||||
#include <AgentList.h>
|
||||
#include <AvatarData.h>
|
||||
#include <AudioInjector.h>
|
||||
|
||||
const int EVE_AGENT_LIST_PORT = 55441;
|
||||
const float DATA_SEND_INTERVAL_MSECS = 10;
|
||||
const int EVE_AGENT_LISTEN_PORT = 55441;
|
||||
|
||||
const float RANDOM_POSITION_MAX_DIMENSION = 5.0f;
|
||||
|
||||
const float DATA_SEND_INTERVAL_MSECS = 15;
|
||||
const float MIN_AUDIO_SEND_INTERVAL_SECS = 10;
|
||||
const int MIN_ITERATIONS_BETWEEN_AUDIO_SENDS = (MIN_AUDIO_SEND_INTERVAL_SECS * 1000) / DATA_SEND_INTERVAL_MSECS;
|
||||
const int MAX_AUDIO_SEND_INTERVAL_SECS = 15;
|
||||
const float MAX_ITERATIONS_BETWEEN_AUDIO_SENDS = (MAX_AUDIO_SEND_INTERVAL_SECS * 1000) / DATA_SEND_INTERVAL_MSECS;
|
||||
|
||||
bool stopReceiveAgentDataThread;
|
||||
bool injectAudioThreadRunning = false;
|
||||
|
||||
void *receiveAgentData(void *args)
|
||||
{
|
||||
int TEMP_AUDIO_LISTEN_PORT = 55439;
|
||||
// UDPSocket audioSocket(TEMP_AUDIO_LISTEN_PORT);
|
||||
|
||||
void *receiveAgentData(void *args) {
|
||||
sockaddr senderAddress;
|
||||
ssize_t bytesReceived;
|
||||
unsigned char incomingPacket[MAX_PACKET_SIZE];
|
||||
|
||||
AgentList *agentList = AgentList::getInstance();
|
||||
Agent *avatarMixer = NULL;
|
||||
AgentList* agentList = AgentList::getInstance();
|
||||
Agent* avatarMixer = NULL;
|
||||
|
||||
while (!::stopReceiveAgentDataThread) {
|
||||
if (agentList->getAgentSocket().receive(&senderAddress, incomingPacket, &bytesReceived)) {
|
||||
|
@ -54,9 +65,35 @@ void *receiveAgentData(void *args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
void *injectAudio(void *args) {
|
||||
::injectAudioThreadRunning = true;
|
||||
|
||||
AudioInjector* eveAudioInjector = (AudioInjector *)args;
|
||||
|
||||
// look for an audio mixer in our agent list
|
||||
Agent* audioMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AUDIO_MIXER);
|
||||
|
||||
if (audioMixer != NULL) {
|
||||
// until the audio mixer is setup for ping-reply, activate the public socket if it's not active
|
||||
if (audioMixer->getActiveSocket() == NULL) {
|
||||
audioMixer->activatePublicSocket();
|
||||
}
|
||||
|
||||
// we have an active audio mixer we can send data to
|
||||
// eveAudioInjector->injectAudio(&::audioSocket, audioMixer->getActiveSocket());
|
||||
}
|
||||
|
||||
::injectAudioThreadRunning = false;
|
||||
pthread_exit(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
// new seed for random audio sleep times
|
||||
srand(time(0));
|
||||
|
||||
// create an AgentList instance to handle communication with other agents
|
||||
AgentList *agentList = AgentList::createInstance(AGENT_TYPE_AVATAR, EVE_AGENT_LIST_PORT);
|
||||
AgentList* agentList = AgentList::createInstance(AGENT_TYPE_AVATAR, EVE_AGENT_LISTEN_PORT);
|
||||
|
||||
// start telling the domain server that we are alive
|
||||
agentList->startDomainServerCheckInThread();
|
||||
|
@ -74,15 +111,21 @@ int main(int argc, char* argv[]) {
|
|||
AvatarData eve = AvatarData();
|
||||
|
||||
// move eve away from the origin
|
||||
eve.setBodyPosition(glm::vec3(3, 0, -3));
|
||||
// pick a random point inside a 10x10 grid
|
||||
|
||||
// turn her back towards the origin
|
||||
eve.setBodyYaw(-45);
|
||||
eve.setPosition(glm::vec3(randFloatInRange(-RANDOM_POSITION_MAX_DIMENSION, RANDOM_POSITION_MAX_DIMENSION),
|
||||
0,
|
||||
randFloatInRange(-RANDOM_POSITION_MAX_DIMENSION, RANDOM_POSITION_MAX_DIMENSION)));
|
||||
|
||||
// face any instance of eve down the z-axis
|
||||
eve.setBodyYaw(0);
|
||||
|
||||
// put her hand out so somebody can shake it
|
||||
eve.setHandPosition(glm::vec3(eve.getBodyPosition()[0] - 0.2,
|
||||
eve.setHandPosition(glm::vec3(eve.getPosition()[0] - 0.2,
|
||||
0.25,
|
||||
eve.getBodyPosition()[2] + 0.1));
|
||||
eve.getPosition()[2] + 0.1));
|
||||
// read eve's audio data
|
||||
AudioInjector eveAudioInjector("eve.raw");
|
||||
|
||||
unsigned char broadcastPacket[MAX_PACKET_SIZE];
|
||||
broadcastPacket[0] = PACKET_HEADER_HEAD_DATA;
|
||||
|
@ -92,6 +135,11 @@ int main(int argc, char* argv[]) {
|
|||
timeval thisSend;
|
||||
double numMicrosecondsSleep = 0;
|
||||
|
||||
// int numIterationsLeftBeforeAudioSend = 0;
|
||||
// pthread_t injectAudioThread;
|
||||
|
||||
int handStateTimer = 0;
|
||||
|
||||
while (true) {
|
||||
// update the thisSend timeval to the current time
|
||||
gettimeofday(&thisSend, NULL);
|
||||
|
@ -104,15 +152,38 @@ int main(int argc, char* argv[]) {
|
|||
// use the getBroadcastData method in the AvatarData class to populate the broadcastPacket buffer
|
||||
numBytesToSend = eve.getBroadcastData((broadcastPacket + 1));
|
||||
|
||||
|
||||
// use the UDPSocket instance attached to our agent list to send avatar data to mixer
|
||||
agentList->getAgentSocket().send(avatarMixer->getActiveSocket(), broadcastPacket, numBytesToSend);
|
||||
}
|
||||
|
||||
// temporarily disable Eve's audio sending until the file is actually available on EC2 box
|
||||
// if (numIterationsLeftBeforeAudioSend == 0) {
|
||||
// if (!::injectAudioThreadRunning) {
|
||||
// pthread_create(&injectAudioThread, NULL, injectAudio, (void*) &eveAudioInjector);
|
||||
//
|
||||
// numIterationsLeftBeforeAudioSend = randIntInRange(MIN_ITERATIONS_BETWEEN_AUDIO_SENDS,
|
||||
// MAX_ITERATIONS_BETWEEN_AUDIO_SENDS);
|
||||
// }
|
||||
// } else {
|
||||
// numIterationsLeftBeforeAudioSend--;
|
||||
// }
|
||||
|
||||
// sleep for the correct amount of time to have data send be consistently timed
|
||||
if ((numMicrosecondsSleep = (DATA_SEND_INTERVAL_MSECS * 1000) - (usecTimestampNow() - usecTimestamp(&thisSend))) > 0) {
|
||||
usleep(numMicrosecondsSleep);
|
||||
}
|
||||
}
|
||||
|
||||
// simulate the effect of pressing and un-pressing the mouse button/pad
|
||||
handStateTimer++;
|
||||
if ( handStateTimer == 100 ) {
|
||||
eve.setHandState(1);
|
||||
}
|
||||
if ( handStateTimer == 150 ) {
|
||||
eve.setHandState(0);
|
||||
}
|
||||
if ( handStateTimer >= 200 ) {
|
||||
handStateTimer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// stop the receive agent data thread
|
||||
|
|
|
@ -14,4 +14,4 @@ link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
|||
|
||||
# link the threads library
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(injector ${CMAKE_THREAD_LIBS_INIT})
|
||||
target_link_libraries(${TARGET_NAME} ${CMAKE_THREAD_LIBS_INIT})
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// injector.cpp
|
||||
// main.cpp
|
||||
// Audio Injector
|
||||
//
|
||||
// Created by Leonardo Murillo on 3/5/13.
|
||||
|
@ -11,39 +11,27 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <arpa/inet.h>
|
||||
#include <string.h>
|
||||
#include <sstream>
|
||||
#include "UDPSocket.h"
|
||||
#include "UDPSocket.cpp"
|
||||
|
||||
|
||||
#include <SharedUtil.h>
|
||||
#include <PacketHeaders.h>
|
||||
|
||||
#include <UDPSocket.h>
|
||||
#include <AudioInjector.h>
|
||||
|
||||
char EC2_WEST_AUDIO_SERVER[] = "54.241.92.53";
|
||||
const int AUDIO_UDP_LISTEN_PORT = 55443;
|
||||
const int BUFFER_LENGTH_BYTES = 512;
|
||||
const int BUFFER_LENGTH_SAMPLES = BUFFER_LENGTH_BYTES / sizeof(int16_t);
|
||||
const float SAMPLE_RATE = 22050.0;
|
||||
const float BUFFER_SEND_INTERVAL_USECS = (BUFFER_LENGTH_SAMPLES / SAMPLE_RATE) * 1000000;
|
||||
|
||||
// Command line parameter defaults
|
||||
bool loopAudio = true;
|
||||
float sleepIntervalMin = 1.00;
|
||||
float sleepIntervalMax = 2.00;
|
||||
float positionInUniverse[] = {0, 0, 0, 0};
|
||||
unsigned char attenuationModifier = 255;
|
||||
char *sourceAudioFile;
|
||||
char *sourceAudioFile = NULL;
|
||||
const char *allowedParameters = ":rb::t::c::a::f:";
|
||||
|
||||
char *charBuffer;
|
||||
int16_t *buffer;
|
||||
long length;
|
||||
|
||||
UDPSocket *streamSocket;
|
||||
float floatArguments[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
unsigned char attenuationModifier = 255;
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
|
@ -54,7 +42,7 @@ void usage(void)
|
|||
std::cout << " -c FLOAT,FLOAT,FLOAT,FLOAT X,Y,Z,YAW position in universe where audio will be originating from and direction. Defaults to 0,0,0,0" << std::endl;
|
||||
std::cout << " -a 0-255 Attenuation curve modifier, defaults to 255" << std::endl;
|
||||
std::cout << " -f FILENAME Name of audio source file. Required - RAW format, 22050hz 16bit signed mono" << std::endl;
|
||||
};
|
||||
}
|
||||
|
||||
bool processParameters(int parameterCount, char* parameterData[])
|
||||
{
|
||||
|
@ -62,19 +50,19 @@ bool processParameters(int parameterCount, char* parameterData[])
|
|||
while ((p = getopt(parameterCount, parameterData, allowedParameters)) != -1) {
|
||||
switch (p) {
|
||||
case 'r':
|
||||
loopAudio = false;
|
||||
::loopAudio = false;
|
||||
std::cout << "[DEBUG] Random sleep mode enabled" << std::endl;
|
||||
break;
|
||||
case 'b':
|
||||
sleepIntervalMin = atof(optarg);
|
||||
::sleepIntervalMin = atof(optarg);
|
||||
std::cout << "[DEBUG] Min delay between plays " << sleepIntervalMin << "sec" << std::endl;
|
||||
break;
|
||||
case 't':
|
||||
sleepIntervalMax = atof(optarg);
|
||||
::sleepIntervalMax = atof(optarg);
|
||||
std::cout << "[DEBUG] Max delay between plays " << sleepIntervalMax << "sec" << std::endl;
|
||||
break;
|
||||
case 'f':
|
||||
sourceAudioFile = optarg;
|
||||
::sourceAudioFile = optarg;
|
||||
std::cout << "[DEBUG] Opening file: " << sourceAudioFile << std::endl;
|
||||
break;
|
||||
case 'c':
|
||||
|
@ -84,7 +72,7 @@ bool processParameters(int parameterCount, char* parameterData[])
|
|||
|
||||
int i = 0;
|
||||
while (std::getline(ss, token, ',')) {
|
||||
positionInUniverse[i] = atof(token.c_str());
|
||||
::floatArguments[i] = atof(token.c_str());
|
||||
++i;
|
||||
if (i == 4) {
|
||||
break;
|
||||
|
@ -94,7 +82,7 @@ bool processParameters(int parameterCount, char* parameterData[])
|
|||
break;
|
||||
}
|
||||
case 'a':
|
||||
attenuationModifier = atoi(optarg);
|
||||
::attenuationModifier = atoi(optarg);
|
||||
std::cout << "[DEBUG] Attenuation modifier: " << optarg << std::endl;
|
||||
break;
|
||||
default:
|
||||
|
@ -105,77 +93,42 @@ bool processParameters(int parameterCount, char* parameterData[])
|
|||
return true;
|
||||
};
|
||||
|
||||
void loadFile(void) {
|
||||
std::fstream sourceFile;
|
||||
sourceFile.open(sourceAudioFile, std::ios::in | std::ios::binary);
|
||||
sourceFile.seekg(0, std::ios::end);
|
||||
length = sourceFile.tellg();
|
||||
sourceFile.seekg(0, std::ios::beg);
|
||||
long sizeOfShortArray = length / 2;
|
||||
buffer = new int16_t[sizeOfShortArray];
|
||||
sourceFile.read((char *)buffer, length);
|
||||
}
|
||||
|
||||
void stream(void)
|
||||
{
|
||||
timeval startTime;
|
||||
|
||||
int leadingBytes = 1 + (sizeof(float) * 4);
|
||||
unsigned char dataPacket[BUFFER_LENGTH_BYTES + leadingBytes];
|
||||
|
||||
dataPacket[0] = PACKET_HEADER_INJECT_AUDIO;
|
||||
unsigned char *currentPacketPtr = dataPacket + 1;
|
||||
|
||||
for (int p = 0; p < 4; p++) {
|
||||
memcpy(currentPacketPtr, &positionInUniverse[p], sizeof(float));
|
||||
currentPacketPtr += sizeof(float);
|
||||
}
|
||||
|
||||
*currentPacketPtr = attenuationModifier;
|
||||
currentPacketPtr++;
|
||||
|
||||
for (int i = 0; i < length; i += BUFFER_LENGTH_SAMPLES) {
|
||||
gettimeofday(&startTime, NULL);
|
||||
memcpy(currentPacketPtr, &buffer[i], BUFFER_LENGTH_BYTES);
|
||||
streamSocket->send(EC2_WEST_AUDIO_SERVER, AUDIO_UDP_LISTEN_PORT, dataPacket, sizeof(dataPacket));
|
||||
double usecToSleep = usecTimestamp(&startTime) + BUFFER_SEND_INTERVAL_USECS - usecTimestampNow();
|
||||
usleep(usecToSleep);
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int main(int argc, char* argv[]) {
|
||||
|
||||
srand(time(0));
|
||||
int AUDIO_UDP_SEND_PORT = 1500 + (rand() % (int)(1500 - 2000 + 1));
|
||||
|
||||
streamSocket = new UDPSocket(AUDIO_UDP_SEND_PORT);
|
||||
UDPSocket streamSocket(AUDIO_UDP_SEND_PORT);
|
||||
|
||||
if (processParameters(argc, argv)) {
|
||||
if (sourceAudioFile) {
|
||||
loadFile();
|
||||
} else {
|
||||
sockaddr_in mixerSocket;
|
||||
mixerSocket.sin_family = AF_INET;
|
||||
mixerSocket.sin_addr.s_addr = inet_addr(EC2_WEST_AUDIO_SERVER);
|
||||
mixerSocket.sin_port = htons((uint16_t)AUDIO_UDP_LISTEN_PORT);
|
||||
|
||||
if (processParameters(argc, argv)) {
|
||||
if (::sourceAudioFile == NULL) {
|
||||
std::cout << "[FATAL] Source audio file not specified" << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < sizeof(positionInUniverse)/sizeof(positionInUniverse[0]); ++i) {
|
||||
std::cout << "Position " << positionInUniverse[i] << std::endl;
|
||||
}
|
||||
|
||||
float delay;
|
||||
int usecDelay;
|
||||
while (true) {
|
||||
stream();
|
||||
} else {
|
||||
AudioInjector injector(sourceAudioFile);
|
||||
|
||||
if (loopAudio) {
|
||||
delay = 0;
|
||||
} else {
|
||||
delay = randFloatInRange(sleepIntervalMin, sleepIntervalMax);
|
||||
injector.setPosition(::floatArguments);
|
||||
injector.setBearing(*(::floatArguments + 3));
|
||||
injector.setAttenuationModifier(::attenuationModifier);
|
||||
|
||||
float delay = 0;
|
||||
int usecDelay = 0;
|
||||
|
||||
while (true) {
|
||||
injector.injectAudio(&streamSocket, (sockaddr*) &mixerSocket);
|
||||
|
||||
if (!::loopAudio) {
|
||||
delay = randFloatInRange(::sleepIntervalMin, ::sleepIntervalMax);
|
||||
usecDelay = delay * 1000 * 1000;
|
||||
usleep(usecDelay);
|
||||
}
|
||||
}
|
||||
usecDelay = delay * 1000 * 1000;
|
||||
usleep(usecDelay);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -130,7 +130,7 @@ int audioCallback (const void *inputBuffer,
|
|||
|
||||
loudness /= BUFFER_LENGTH_SAMPLES;
|
||||
data->lastInputLoudness = loudness;
|
||||
data->averagedInputLoudness = 0.66*data->averagedInputLoudness + 0.33*loudness;
|
||||
|
||||
//
|
||||
// If scope is turned on, copy input buffer to scope
|
||||
//
|
||||
|
@ -157,7 +157,7 @@ int audioCallback (const void *inputBuffer,
|
|||
|
||||
// memcpy the three float positions
|
||||
for (int p = 0; p < 3; p++) {
|
||||
memcpy(currentPacketPtr, &data->linkedHead->getBodyPosition()[p], sizeof(float));
|
||||
memcpy(currentPacketPtr, &data->linkedAvatar->getPosition()[p], sizeof(float));
|
||||
currentPacketPtr += sizeof(float);
|
||||
}
|
||||
|
||||
|
@ -165,7 +165,7 @@ int audioCallback (const void *inputBuffer,
|
|||
*(currentPacketPtr++) = 255;
|
||||
|
||||
// memcpy the corrected render yaw
|
||||
float correctedYaw = fmodf(data->linkedHead->getRenderYaw(), 360);
|
||||
float correctedYaw = fmodf(data->linkedAvatar->getRenderYaw(), 360);
|
||||
|
||||
if (correctedYaw > 180) {
|
||||
correctedYaw -= 360;
|
||||
|
@ -259,7 +259,7 @@ int audioCallback (const void *inputBuffer,
|
|||
// rotation of the head relative to body, this may effect flange effect!
|
||||
//
|
||||
//
|
||||
int lastYawMeasured = fabsf(data->linkedHead->getLastMeasuredHeadYaw());
|
||||
int lastYawMeasured = fabsf(data->linkedAvatar->getLastMeasuredHeadYaw());
|
||||
|
||||
if (!samplesLeftForFlange && lastYawMeasured > MIN_FLANGE_EFFECT_THRESHOLD) {
|
||||
// we should flange for one second
|
||||
|
@ -448,7 +448,7 @@ void Audio::setWalkingState(bool newWalkState) {
|
|||
* @return Returns true if successful or false if an error occurred.
|
||||
Use Audio::getError() to retrieve the error code.
|
||||
*/
|
||||
Audio::Audio(Oscilloscope *s, Head *linkedHead)
|
||||
Audio::Audio(Oscilloscope *s, Avatar *linkedAvatar)
|
||||
{
|
||||
// read the walking sound from the raw file and store it
|
||||
// in the in memory array
|
||||
|
@ -472,7 +472,7 @@ Audio::Audio(Oscilloscope *s, Head *linkedHead)
|
|||
|
||||
audioData = new AudioData();
|
||||
|
||||
audioData->linkedHead = linkedHead;
|
||||
audioData->linkedAvatar = linkedAvatar;
|
||||
|
||||
// setup a UDPSocket
|
||||
audioData->audioSocket = new UDPSocket(AUDIO_UDP_LISTEN_PORT);
|
||||
|
@ -510,9 +510,8 @@ error:
|
|||
}
|
||||
|
||||
|
||||
void Audio::getInputLoudness(float * lastLoudness, float * averageLoudness) {
|
||||
*lastLoudness = audioData->lastInputLoudness;
|
||||
*averageLoudness = audioData->averagedInputLoudness;
|
||||
float Audio::getInputLoudness() const {
|
||||
return audioData->lastInputLoudness;
|
||||
}
|
||||
|
||||
void Audio::render(int screenWidth, int screenHeight)
|
||||
|
|
|
@ -12,12 +12,12 @@
|
|||
#include <portaudio.h>
|
||||
#include "AudioData.h"
|
||||
#include "Oscilloscope.h"
|
||||
#include "Head.h"
|
||||
#include "Avatar.h"
|
||||
|
||||
class Audio {
|
||||
public:
|
||||
// initializes audio I/O
|
||||
Audio(Oscilloscope *s, Head *linkedHead);
|
||||
Audio(Oscilloscope *s, Avatar *linkedAvatar);
|
||||
|
||||
void render();
|
||||
void render(int screenWidth, int screenHeight);
|
||||
|
@ -25,7 +25,7 @@ public:
|
|||
bool getMixerLoopbackFlag();
|
||||
void setMixerLoopbackFlag(bool newMixerLoopbackFlag);
|
||||
|
||||
void getInputLoudness(float * lastLoudness, float * averageLoudness);
|
||||
float getInputLoudness() const;
|
||||
void updateMixerParams(in_addr_t mixerAddress, in_port_t mixerPort);
|
||||
|
||||
void setWalkingState(bool newWalkState);
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include <glm/glm.hpp>
|
||||
#include "AudioRingBuffer.h"
|
||||
#include "UDPSocket.h"
|
||||
#include "Head.h"
|
||||
#include "Avatar.h"
|
||||
|
||||
class AudioData {
|
||||
public:
|
||||
|
@ -23,7 +23,7 @@ class AudioData {
|
|||
|
||||
UDPSocket *audioSocket;
|
||||
|
||||
Head *linkedHead;
|
||||
Avatar *linkedAvatar;
|
||||
|
||||
// store current mixer address and port
|
||||
in_addr_t mixerAddress;
|
||||
|
@ -36,7 +36,6 @@ class AudioData {
|
|||
int wasStarved;
|
||||
|
||||
float lastInputLoudness;
|
||||
float averagedInputLoudness;
|
||||
|
||||
bool mixerLoopbackFlag;
|
||||
bool playWalkSound;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,13 +1,13 @@
|
|||
//
|
||||
// Head.h
|
||||
// Avatar.h
|
||||
// interface
|
||||
//
|
||||
// Created by Philip Rosedale on 9/11/12.
|
||||
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __interface__head__
|
||||
#define __interface__head__
|
||||
#ifndef __interface__avatar__
|
||||
#define __interface__avatar__
|
||||
|
||||
#include <AvatarData.h>
|
||||
#include <Orientation.h>
|
||||
|
@ -29,6 +29,9 @@ const float YAW_MAG = 300.0;
|
|||
const float TEST_YAW_DECAY = 5.0;
|
||||
const float LIN_VEL_DECAY = 5.0;
|
||||
|
||||
const float COLLISION_BODY_RADIUS = 0.1;
|
||||
const float COLLISION_HEIGHT = 1.5;
|
||||
|
||||
enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH};
|
||||
|
||||
#define FWD 0
|
||||
|
@ -41,7 +44,7 @@ enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH};
|
|||
#define ROT_RIGHT 7
|
||||
#define MAX_DRIVE_KEYS 8
|
||||
|
||||
#define MAX_OTHER_AVATARS 50 // temporary - for testing purposes!
|
||||
#define MAX_OTHER_AVATARS 10 // temporary - for testing purposes!
|
||||
|
||||
enum AvatarMode
|
||||
{
|
||||
|
@ -81,6 +84,22 @@ enum AvatarBoneID
|
|||
NUM_AVATAR_BONES
|
||||
};
|
||||
|
||||
struct AvatarCollisionElipsoid
|
||||
{
|
||||
bool colliding;
|
||||
glm::vec3 position;
|
||||
float girth;
|
||||
float height;
|
||||
glm::vec3 upVector;
|
||||
};
|
||||
|
||||
struct AvatarHandHolding
|
||||
{
|
||||
glm::vec3 position;
|
||||
glm::vec3 velocity;
|
||||
float force;
|
||||
};
|
||||
|
||||
struct AvatarBone
|
||||
{
|
||||
AvatarBoneID parent; // which bone is this bone connected to?
|
||||
|
@ -137,12 +156,12 @@ struct AvatarHead
|
|||
};
|
||||
|
||||
|
||||
class Head : public AvatarData {
|
||||
class Avatar : public AvatarData {
|
||||
public:
|
||||
Head(bool isMine);
|
||||
~Head();
|
||||
Head(const Head &otherHead);
|
||||
Head* clone() const;
|
||||
Avatar(bool isMine);
|
||||
~Avatar();
|
||||
Avatar(const Avatar &otherAvatar);
|
||||
Avatar* clone() const;
|
||||
|
||||
void reset();
|
||||
void UpdateGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity);
|
||||
|
@ -163,8 +182,11 @@ class Head : public AvatarData {
|
|||
glm::vec3 getHeadLookatDirectionUp();
|
||||
glm::vec3 getHeadLookatDirectionRight();
|
||||
glm::vec3 getHeadPosition();
|
||||
glm::vec3 getBonePosition( AvatarBoneID b );
|
||||
|
||||
glm::vec3 getBonePosition( AvatarBoneID b );
|
||||
glm::vec3 getBodyUpDirection();
|
||||
float getGirth();
|
||||
float getHeight();
|
||||
|
||||
AvatarMode getMode();
|
||||
|
||||
void setMousePressed( bool pressed );
|
||||
|
@ -175,11 +197,12 @@ class Head : public AvatarData {
|
|||
void startHandMovement();
|
||||
void stopHandMovement();
|
||||
void setHandMovementValues( glm::vec3 movement );
|
||||
void updateHandMovement();
|
||||
void updateHandMovement( float deltaTime );
|
||||
void updateArmIKAndConstraints( float deltaTime );
|
||||
|
||||
float getAverageLoudness() {return _head.averageLoudness;};
|
||||
void setAverageLoudness(float al) {_head.averageLoudness = al;};
|
||||
|
||||
|
||||
void SetNewHeadTarget(float, float);
|
||||
|
||||
// Set what driving keys are being pressed to control thrust levels
|
||||
|
@ -191,58 +214,55 @@ class Head : public AvatarData {
|
|||
void addThrust(glm::vec3 newThrust) { _thrust += newThrust; };
|
||||
glm::vec3 getThrust() { return _thrust; };
|
||||
|
||||
//
|
||||
// Related to getting transmitter UDP data used to animate the avatar hand
|
||||
//
|
||||
|
||||
void processTransmitterData(unsigned char * packetData, int numBytes);
|
||||
float getTransmitterHz() { return _transmitterHz; };
|
||||
|
||||
private:
|
||||
AvatarHead _head;
|
||||
bool _isMine;
|
||||
glm::vec3 _TEST_bigSpherePosition;
|
||||
float _TEST_bigSphereRadius;
|
||||
glm::vec3 _otherAvatarHandPosition[ MAX_OTHER_AVATARS ];
|
||||
bool _mousePressed;
|
||||
float _bodyYawDelta;
|
||||
int _closestOtherAvatar;
|
||||
bool _usingBodySprings;
|
||||
glm::vec3 _movedHandOffset;
|
||||
float _springVelocityDecay;
|
||||
float _springForce;
|
||||
glm::quat _rotation; // the rotation of the avatar body as a whole expressed as a quaternion
|
||||
AvatarBone _bone[ NUM_AVATAR_BONES ];
|
||||
AvatarMode _mode;
|
||||
glm::dvec3 _velocity;
|
||||
glm::vec3 _thrust;
|
||||
float _maxArmLength;
|
||||
Orientation _orientation;
|
||||
int _numOtherAvatarsInView;
|
||||
int _driveKeys[MAX_DRIVE_KEYS];
|
||||
GLUquadric* _sphere;
|
||||
float _renderYaw;
|
||||
float _renderPitch; // Pitch from view frustum when this is own head.
|
||||
|
||||
//
|
||||
// Related to getting transmitter UDP data used to animate the avatar hand
|
||||
//
|
||||
timeval _transmitterTimer;
|
||||
float _transmitterHz;
|
||||
int _transmitterPackets;
|
||||
AvatarHead _head;
|
||||
bool _isMine;
|
||||
glm::vec3 _TEST_bigSpherePosition;
|
||||
float _TEST_bigSphereRadius;
|
||||
bool _mousePressed;
|
||||
float _bodyYawDelta;
|
||||
bool _usingBodySprings;
|
||||
glm::vec3 _movedHandOffset;
|
||||
float _springVelocityDecay;
|
||||
float _springForce;
|
||||
glm::quat _rotation; // the rotation of the avatar body as a whole expressed as a quaternion
|
||||
AvatarBone _bone[ NUM_AVATAR_BONES ];
|
||||
AvatarMode _mode;
|
||||
AvatarHandHolding _handHolding;
|
||||
glm::dvec3 _velocity;
|
||||
glm::vec3 _thrust;
|
||||
float _maxArmLength;
|
||||
Orientation _orientation;
|
||||
int _driveKeys[MAX_DRIVE_KEYS];
|
||||
GLUquadric* _sphere;
|
||||
float _renderYaw;
|
||||
float _renderPitch; // Pitch from view frustum when this is own head
|
||||
timeval _transmitterTimer;
|
||||
float _transmitterHz;
|
||||
int _transmitterPackets;
|
||||
Avatar* _interactingOther;
|
||||
bool _interactingOtherIsNearby;
|
||||
|
||||
//-----------------------------
|
||||
// private methods...
|
||||
//-----------------------------
|
||||
void initializeSkeleton();
|
||||
void updateSkeleton();
|
||||
void initializeBodySprings();
|
||||
void updateBodySprings( float deltaTime );
|
||||
void calculateBoneLengths();
|
||||
void updateBigSphereCollisionTest( float deltaTime );
|
||||
void readSensors();
|
||||
void renderBoneAsBlock( AvatarBoneID b );
|
||||
|
||||
void updateAvatarCollisionDetectionAndResponse
|
||||
(
|
||||
glm::vec3 collisionPosition,
|
||||
float collisionGirth,
|
||||
float collisionHeight,
|
||||
glm::vec3 collisionUpVector,
|
||||
float deltaTime
|
||||
);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -46,6 +46,7 @@ Cloud::Cloud(int num,
|
|||
void Cloud::render() {
|
||||
|
||||
float particleAttenuationQuadratic[] = { 0.0f, 0.0f, 2.0f };
|
||||
float particleAttenuationConstant[] = { 1.0f, 0.0f, 0.0f };
|
||||
|
||||
glEnable( GL_TEXTURE_2D );
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
|
@ -73,6 +74,10 @@ void Cloud::render() {
|
|||
glEnd();
|
||||
glDisable( GL_POINT_SPRITE_ARB );
|
||||
glDisable( GL_TEXTURE_2D );
|
||||
|
||||
glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, particleAttenuationConstant );
|
||||
glPointParameterfARB( GL_POINT_SIZE_MAX_ARB, 1.0f );
|
||||
glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, 0.0f );
|
||||
}
|
||||
|
||||
void Cloud::simulate (float deltaTime) {
|
||||
|
|
|
@ -55,7 +55,7 @@ class Log {
|
|||
public:
|
||||
|
||||
explicit Log(FILE* tPipeTo = stdout, unsigned bufferedLines = 1024,
|
||||
unsigned defaultLogWidth = 240, unsigned defaultCharWidth = 6, unsigned defaultCharHeight = 20);
|
||||
unsigned defaultLogWidth = 400, unsigned defaultCharWidth = 6, unsigned defaultCharHeight = 20);
|
||||
~Log();
|
||||
|
||||
void setLogWidth(unsigned pixels);
|
||||
|
|
|
@ -34,7 +34,17 @@ float Stars::changeLOD(float fraction, float overalloc, float realloc) {
|
|||
return float(_ptrController->changeLOD(fraction, overalloc, realloc));
|
||||
}
|
||||
|
||||
void Stars::render(float fovDiagonal, float aspect, glm::mat4 const& view) {
|
||||
void Stars::render(float fovY, float aspect, float nearZ) {
|
||||
|
||||
// determine length of screen diagonal from quadrant height and aspect ratio
|
||||
float quadrantHeight = nearZ * tan(angleConvert<Degrees,Radians>(fovY) * 0.5f);
|
||||
float halfDiagonal = sqrt(quadrantHeight * quadrantHeight * (1.0f + aspect * aspect));
|
||||
|
||||
// determine fov angle in respect to the diagonal
|
||||
float fovDiagonal = atan(halfDiagonal / nearZ) * 2.0f;
|
||||
|
||||
// pull the modelview matrix off the GL stack
|
||||
glm::mat4 view; glGetFloatv(GL_MODELVIEW_MATRIX, glm::value_ptr(view));
|
||||
|
||||
_ptrController->render(fovDiagonal, aspect, glm::affineInverse(view));
|
||||
}
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
|
||||
namespace starfield { class Controller; }
|
||||
|
||||
/**
|
||||
* Starfield rendering component.
|
||||
*/
|
||||
//
|
||||
// Starfield rendering component.
|
||||
//
|
||||
class Stars {
|
||||
|
||||
starfield::Controller* _ptrController;
|
||||
|
@ -25,49 +25,49 @@ class Stars {
|
|||
Stars();
|
||||
~Stars();
|
||||
|
||||
/**
|
||||
* Reads input file from URL. Returns true upon success.
|
||||
*
|
||||
* The limit parameter allows to reduce the number of stars
|
||||
* that are loaded, keeping the brightest ones.
|
||||
*/
|
||||
//
|
||||
// Reads input file from URL. Returns true upon success.
|
||||
//
|
||||
// The limit parameter allows to reduce the number of stars
|
||||
// that are loaded, keeping the brightest ones.
|
||||
//
|
||||
bool readInput(const char* url, const char* cacheFile = 0l, unsigned limit = 200000);
|
||||
|
||||
/**
|
||||
* Renders the starfield from a local viewer's perspective.
|
||||
* The parameter specifies the field of view.
|
||||
*/
|
||||
void render(float fovDiagonal, float aspect, glm::mat4 const& view);
|
||||
//
|
||||
// Renders the starfield from a local viewer's perspective.
|
||||
// The parameters specifiy the field of view.
|
||||
//
|
||||
void render(float fovY, float aspect, float nearZ);
|
||||
|
||||
/**
|
||||
* Sets the resolution for FOV culling.
|
||||
*
|
||||
* The parameter determines the number of tiles in azimuthal
|
||||
* and altitudinal directions.
|
||||
*
|
||||
* GPU resources are updated upon change in which case 'true'
|
||||
* is returned.
|
||||
*/
|
||||
//
|
||||
// Sets the resolution for FOV culling.
|
||||
//
|
||||
// The parameter determines the number of tiles in azimuthal
|
||||
// and altitudinal directions.
|
||||
//
|
||||
// GPU resources are updated upon change in which case 'true'
|
||||
// is returned.
|
||||
//
|
||||
bool setResolution(unsigned k);
|
||||
|
||||
/**
|
||||
* Allows to alter the number of stars to be rendered given a
|
||||
* factor. The least brightest ones are omitted first.
|
||||
*
|
||||
* The further parameters determine when GPU resources should
|
||||
* be reallocated. Its value is fractional in respect to the
|
||||
* last number of stars 'n' that caused 'n * (1+overalloc)' to
|
||||
* be allocated. When the next call to setLOD causes the total
|
||||
* number of stars that could be rendered to drop below 'n *
|
||||
* (1-realloc)' or rises above 'n * (1+realloc)' GPU resources
|
||||
* are updated. Note that all parameters must be fractions,
|
||||
* that is within the range [0;1] and that 'overalloc' must be
|
||||
* greater than or equal to 'realloc'.
|
||||
*
|
||||
* The current level of detail is returned as a float in [0;1].
|
||||
*/
|
||||
//
|
||||
// Allows to alter the number of stars to be rendered given a
|
||||
// factor. The least brightest ones are omitted first.
|
||||
//
|
||||
// The further parameters determine when GPU resources should
|
||||
// be reallocated. Its value is fractional in respect to the
|
||||
// last number of stars 'n' that caused 'n * (1+overalloc)' to
|
||||
// be allocated. When the next call to setLOD causes the total
|
||||
// number of stars that could be rendered to drop below 'n *
|
||||
// (1-realloc)' or rises above 'n * (1+realloc)' GPU resources
|
||||
// are updated. Note that all parameters must be fractions,
|
||||
// that is within the range [0;1] and that 'overalloc' must be
|
||||
// greater than or equal to 'realloc'.
|
||||
//
|
||||
// The current level of detail is returned as a float in [0;1].
|
||||
//
|
||||
float changeLOD(float factor,
|
||||
float overalloc = 0.25, float realloc = 0.15);
|
||||
float overalloc = 0.25, float realloc = 0.15);
|
||||
|
||||
private:
|
||||
// don't copy/assign
|
||||
|
|
|
@ -90,6 +90,7 @@ void render_vector(glm::vec3 * vec)
|
|||
// Draw marker dots for magnitude
|
||||
glEnd();
|
||||
float particleAttenuationQuadratic[] = { 0.0f, 0.0f, 2.0f }; // larger Z = smaller particles
|
||||
float particleAttenuationConstant[] = { 1.0f, 0.0f, 0.0f };
|
||||
|
||||
glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, particleAttenuationQuadratic );
|
||||
|
||||
|
@ -104,6 +105,7 @@ void render_vector(glm::vec3 * vec)
|
|||
glVertex3f(0,0,vec->z);
|
||||
glEnd();
|
||||
|
||||
glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, particleAttenuationConstant );
|
||||
}
|
||||
|
||||
void render_world_box()
|
||||
|
|
|
@ -23,25 +23,27 @@
|
|||
|
||||
const int MAX_VOXELS_PER_SYSTEM = 250000;
|
||||
|
||||
const int VERTICES_PER_VOXEL = 8;
|
||||
const int VERTICES_PER_VOXEL = 24;
|
||||
const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL;
|
||||
const int INDICES_PER_VOXEL = 3 * 12;
|
||||
|
||||
float identityVertices[] = { 0, 0, 0,
|
||||
1, 0, 0,
|
||||
1, 1, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 1,
|
||||
1, 0, 1,
|
||||
1, 1, 1,
|
||||
0, 1, 1 };
|
||||
float identityVertices[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1,
|
||||
0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1,
|
||||
0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1 };
|
||||
|
||||
GLubyte identityIndices[] = { 0,1,2, 0,2,3,
|
||||
0,1,5, 0,4,5,
|
||||
0,3,7, 0,4,7,
|
||||
1,2,6, 1,5,6,
|
||||
2,3,7, 2,6,7,
|
||||
4,5,6, 4,6,7 };
|
||||
GLfloat identityNormals[] = { 0,0,-1, 0,0,-1, 0,0,-1, 0,0,-1,
|
||||
0,0,+1, 0,0,+1, 0,0,+1, 0,0,+1,
|
||||
0,-1,0, 0,-1,0, 0,+1,0, 0,+1,0,
|
||||
0,-1,0, 0,-1,0, 0,+1,0, 0,+1,0,
|
||||
-1,0,0, +1,0,0, +1,0,0, -1,0,0,
|
||||
-1,0,0, +1,0,0, +1,0,0, -1,0,0 };
|
||||
|
||||
GLubyte identityIndices[] = { 0,2,1, 0,3,2, // Z- .
|
||||
8,9,13, 8,13,12, // Y-
|
||||
16,23,19, 16,20,23, // X-
|
||||
17,18,22, 17,22,21, // X+
|
||||
10,11,15, 10,15,14, // Y+
|
||||
4,5,6, 4,6,7 }; // Z+ .
|
||||
|
||||
VoxelSystem::VoxelSystem() {
|
||||
voxelsRendered = 0;
|
||||
|
@ -49,7 +51,7 @@ VoxelSystem::VoxelSystem() {
|
|||
pthread_mutex_init(&bufferWriteLock, NULL);
|
||||
}
|
||||
|
||||
VoxelSystem::~VoxelSystem() {
|
||||
VoxelSystem::~VoxelSystem() {
|
||||
delete[] readVerticesArray;
|
||||
delete[] writeVerticesArray;
|
||||
delete[] readColorsArray;
|
||||
|
@ -58,8 +60,8 @@ VoxelSystem::~VoxelSystem() {
|
|||
pthread_mutex_destroy(&bufferWriteLock);
|
||||
}
|
||||
|
||||
void VoxelSystem::setViewerHead(Head *newViewerHead) {
|
||||
viewerHead = newViewerHead;
|
||||
void VoxelSystem::setViewerAvatar(Avatar *newViewerAvatar) {
|
||||
viewerAvatar = newViewerAvatar;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -70,9 +72,9 @@ void VoxelSystem::setViewerHead(Head *newViewerHead) {
|
|||
// Complaints: Brad :)
|
||||
// To Do: Need to add color data to the file.
|
||||
void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) {
|
||||
|
||||
|
||||
tree->loadVoxelsFile(fileName,wantColorRandomizer);
|
||||
|
||||
|
||||
copyWrittenDataToReadArrays();
|
||||
}
|
||||
|
||||
|
@ -119,7 +121,7 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
|
||||
unsigned char command = *sourceBuffer;
|
||||
unsigned char *voxelData = sourceBuffer + 1;
|
||||
|
||||
|
||||
switch(command) {
|
||||
case PACKET_HEADER_VOXEL_DATA:
|
||||
{
|
||||
|
@ -204,7 +206,7 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
case PACKET_HEADER_Z_COMMAND:
|
||||
|
||||
// the Z command is a special command that allows the sender to send high level semantic
|
||||
// requests, like erase all, or add sphere scene, different receivers may handle these
|
||||
// requests, like erase all, or add sphere scene, different receivers may handle these
|
||||
// messages differently
|
||||
char* packetData = (char *)sourceBuffer;
|
||||
char* command = &packetData[1]; // start of the command
|
||||
|
@ -225,7 +227,7 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
setupNewVoxelsForDrawing();
|
||||
return numBytes;
|
||||
}
|
||||
|
@ -258,7 +260,7 @@ int VoxelSystem::treeToArrays(VoxelNode *currentNode, const glm::vec3& nodePosi
|
|||
int voxelsAdded = 0;
|
||||
|
||||
float halfUnitForVoxel = powf(0.5, *currentNode->octalCode) * (0.5 * TREE_SCALE);
|
||||
glm::vec3 viewerPosition = viewerHead->getBodyPosition();
|
||||
glm::vec3 viewerPosition = viewerAvatar->getPosition();
|
||||
|
||||
// debug LOD code
|
||||
glm::vec3 debugNodePosition;
|
||||
|
@ -285,11 +287,11 @@ int VoxelSystem::treeToArrays(VoxelNode *currentNode, const glm::vec3& nodePosi
|
|||
for (int i = 0; i < 8; i++) {
|
||||
// check if there is a child here
|
||||
if (currentNode->children[i] != NULL) {
|
||||
|
||||
|
||||
glm::vec3 childNodePosition;
|
||||
copyFirstVertexForCode(currentNode->children[i]->octalCode,(float*)&childNodePosition);
|
||||
childNodePosition *= (float)TREE_SCALE; // scale it up
|
||||
|
||||
|
||||
/**** disabled ************************************************************************************************
|
||||
// Note: Stephen, I intentionally left this in so you would talk to me about it. Here's the deal, this code
|
||||
// doesn't seem to work correctly. It returns X and Z flipped and the values are negative. Since we use the
|
||||
|
@ -299,7 +301,7 @@ int VoxelSystem::treeToArrays(VoxelNode *currentNode, const glm::vec3& nodePosi
|
|||
// calculate the child's position based on the parent position
|
||||
for (int j = 0; j < 3; j++) {
|
||||
childNodePosition[j] = nodePosition[j];
|
||||
|
||||
|
||||
if (oneAtBit(branchIndexWithDescendant(currentNode->octalCode,currentNode->children[i]->octalCode),(7 - j))) {
|
||||
childNodePosition[j] -= (powf(0.5, *currentNode->children[i]->octalCode) * TREE_SCALE);
|
||||
}
|
||||
|
@ -316,13 +318,13 @@ int VoxelSystem::treeToArrays(VoxelNode *currentNode, const glm::vec3& nodePosi
|
|||
float startVertex[3];
|
||||
copyFirstVertexForCode(currentNode->octalCode,(float*)&startVertex);
|
||||
float voxelScale = 1 / powf(2, *currentNode->octalCode);
|
||||
|
||||
|
||||
// populate the array with points for the 8 vertices
|
||||
// and RGB color for each added vertex
|
||||
for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) {
|
||||
*writeVerticesEndPointer = startVertex[j % 3] + (identityVertices[j] * voxelScale);
|
||||
*(writeColorsArray + (writeVerticesEndPointer - writeVerticesArray)) = currentNode->getColor()[j % 3];
|
||||
|
||||
|
||||
writeVerticesEndPointer++;
|
||||
}
|
||||
voxelsAdded++;
|
||||
|
@ -344,7 +346,7 @@ void VoxelSystem::init() {
|
|||
readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM];
|
||||
|
||||
GLuint *indicesArray = new GLuint[INDICES_PER_VOXEL * MAX_VOXELS_PER_SYSTEM];
|
||||
|
||||
|
||||
// populate the indicesArray
|
||||
// this will not change given new voxels, so we can set it all up now
|
||||
for (int n = 0; n < MAX_VOXELS_PER_SYSTEM; n++) {
|
||||
|
@ -352,84 +354,107 @@ void VoxelSystem::init() {
|
|||
int voxelIndexOffset = n * INDICES_PER_VOXEL;
|
||||
GLuint *currentIndicesPos = indicesArray + voxelIndexOffset;
|
||||
int startIndex = (n * VERTICES_PER_VOXEL);
|
||||
|
||||
|
||||
for (int i = 0; i < INDICES_PER_VOXEL; i++) {
|
||||
// add indices for this side of the cube
|
||||
currentIndicesPos[i] = startIndex + identityIndices[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GLfloat *normalsArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM];
|
||||
GLfloat *normalsArrayEndPointer = normalsArray;
|
||||
|
||||
// populate the normalsArray
|
||||
for (int n = 0; n < MAX_VOXELS_PER_SYSTEM; n++) {
|
||||
for (int i = 0; i < VERTEX_POINTS_PER_VOXEL; i++) {
|
||||
*(normalsArrayEndPointer++) = identityNormals[i];
|
||||
}
|
||||
}
|
||||
|
||||
// VBO for the verticesArray
|
||||
glGenBuffers(1, &vboVerticesID);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID);
|
||||
glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW);
|
||||
|
||||
|
||||
// VBO for the normalsArray
|
||||
glGenBuffers(1, &vboNormalsID);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboNormalsID);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM,
|
||||
normalsArray, GL_STATIC_DRAW);
|
||||
|
||||
// VBO for colorsArray
|
||||
glGenBuffers(1, &vboColorsID);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboColorsID);
|
||||
glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW);
|
||||
|
||||
|
||||
// VBO for the indicesArray
|
||||
glGenBuffers(1, &vboIndicesID);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
|
||||
INDICES_PER_VOXEL * sizeof(GLuint) * MAX_VOXELS_PER_SYSTEM,
|
||||
indicesArray, GL_STATIC_DRAW);
|
||||
|
||||
// delete the indices array that is no longer needed
|
||||
|
||||
// delete the indices and normals arrays that are no longer needed
|
||||
delete[] indicesArray;
|
||||
delete[] normalsArray;
|
||||
}
|
||||
|
||||
void VoxelSystem::render() {
|
||||
|
||||
glPushMatrix();
|
||||
|
||||
|
||||
if (readVerticesEndPointer != readVerticesArray) {
|
||||
// try to lock on the buffer write
|
||||
// just avoid pulling new data if it is currently being written
|
||||
if (pthread_mutex_trylock(&bufferWriteLock) == 0) {
|
||||
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, (readVerticesEndPointer - readVerticesArray) * sizeof(GLfloat), readVerticesArray);
|
||||
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboColorsID);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, (readVerticesEndPointer - readVerticesArray) * sizeof(GLubyte), readColorsArray);
|
||||
|
||||
|
||||
readVerticesEndPointer = readVerticesArray;
|
||||
|
||||
|
||||
pthread_mutex_unlock(&bufferWriteLock);
|
||||
}
|
||||
}
|
||||
|
||||
// tell OpenGL where to find vertex and color information
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID);
|
||||
glVertexPointer(3, GL_FLOAT, 0, 0);
|
||||
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboNormalsID);
|
||||
glNormalPointer(GL_FLOAT, 0, 0);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboColorsID);
|
||||
glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0);
|
||||
|
||||
|
||||
// draw the number of voxels we have
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID);
|
||||
glScalef(10, 10, 10);
|
||||
glDrawElements(GL_TRIANGLES, 36 * voxelsRendered, GL_UNSIGNED_INT, 0);
|
||||
|
||||
|
||||
// deactivate vertex and color arrays after drawing
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
|
||||
// bind with 0 to switch back to normal operation
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
|
||||
// scale back down to 1 so heads aren't massive
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void VoxelSystem::simulate(float deltaTime) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
int VoxelSystem::_nodeCount = 0;
|
||||
|
@ -440,7 +465,7 @@ bool VoxelSystem::randomColorOperation(VoxelNode* node, bool down, void* extraDa
|
|||
if (down) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
_nodeCount++;
|
||||
if (node->isColored()) {
|
||||
nodeColor newColor = { 0,0,0,1 };
|
||||
|
@ -471,9 +496,9 @@ bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, bool down, void*
|
|||
if (down) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
_nodeCount++;
|
||||
|
||||
|
||||
// always false colorize
|
||||
unsigned char newR = randomColorValue(150);
|
||||
unsigned char newG = randomColorValue(150);
|
||||
|
@ -500,7 +525,7 @@ bool VoxelSystem::trueColorizeOperation(VoxelNode* node, bool down, void* extraD
|
|||
if (down) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
_nodeCount++;
|
||||
node->setFalseColored(false);
|
||||
//printf("setting true color for node %d\n",_nodeCount);
|
||||
|
@ -521,23 +546,23 @@ bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, bool down, void*
|
|||
if (down) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
ViewFrustum* viewFrustum = (ViewFrustum*) extraData;
|
||||
|
||||
|
||||
_nodeCount++;
|
||||
|
||||
|
||||
// only do this for truely colored voxels...
|
||||
if (node->isColored()) {
|
||||
// first calculate the AAbox for the voxel
|
||||
AABox voxelBox;
|
||||
node->getAABox(voxelBox);
|
||||
|
||||
|
||||
voxelBox.scale(TREE_SCALE);
|
||||
|
||||
|
||||
printf("voxelBox corner=(%f,%f,%f) x=%f\n",
|
||||
voxelBox.getCorner().x, voxelBox.getCorner().y, voxelBox.getCorner().z,
|
||||
voxelBox.getSize().x);
|
||||
|
||||
|
||||
// If the voxel is outside of the view frustum, then false color it red
|
||||
if (ViewFrustum::OUTSIDE == viewFrustum->boxInFrustum(voxelBox)) {
|
||||
// Out of view voxels are colored RED
|
||||
|
@ -554,7 +579,7 @@ bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, bool down, void*
|
|||
} else {
|
||||
printf("voxel not colored, don't consider it\n");
|
||||
}
|
||||
|
||||
|
||||
return true; // keep going!
|
||||
}
|
||||
|
||||
|
@ -576,7 +601,7 @@ bool VoxelSystem::falseColorizeDistanceFromViewOperation(VoxelNode* node, bool d
|
|||
}
|
||||
|
||||
ViewFrustum* viewFrustum = (ViewFrustum*) extraData;
|
||||
|
||||
|
||||
// only do this for truly colored voxels...
|
||||
if (node->isColored()) {
|
||||
|
||||
|
@ -590,10 +615,10 @@ bool VoxelSystem::falseColorizeDistanceFromViewOperation(VoxelNode* node, bool d
|
|||
|
||||
// scale up the node position
|
||||
nodePosition = nodePosition*(float)TREE_SCALE;
|
||||
|
||||
|
||||
float halfUnitForVoxel = powf(0.5, *node->octalCode) * (0.5 * TREE_SCALE);
|
||||
glm::vec3 viewerPosition = viewFrustum->getPosition();
|
||||
|
||||
|
||||
//printf("halfUnitForVoxel=%f\n",halfUnitForVoxel);
|
||||
//printf("viewer.x=%f y=%f z=%f \n", viewerPosition.x, viewerPosition.y, viewerPosition.z);
|
||||
//printf("node.x=%f y=%f z=%f \n", nodePosition.x, nodePosition.y, nodePosition.z);
|
||||
|
@ -606,7 +631,7 @@ bool VoxelSystem::falseColorizeDistanceFromViewOperation(VoxelNode* node, bool d
|
|||
_nodeCount++;
|
||||
|
||||
float distanceRatio = (_minDistance==_maxDistance) ? 1 : (distance - _minDistance)/(_maxDistance - _minDistance);
|
||||
|
||||
|
||||
// We want to colorize this in 16 bug chunks of color
|
||||
const unsigned char maxColor = 255;
|
||||
const unsigned char colorBands = 16;
|
||||
|
@ -615,7 +640,7 @@ bool VoxelSystem::falseColorizeDistanceFromViewOperation(VoxelNode* node, bool d
|
|||
unsigned char newR = (colorBand*(gradientOver/colorBands))+(maxColor-gradientOver);
|
||||
unsigned char newG = 0;
|
||||
unsigned char newB = 0;
|
||||
//printf("Setting color down=%s distance=%f min=%f max=%f distanceRatio=%f color=%d \n",
|
||||
//printf("Setting color down=%s distance=%f min=%f max=%f distanceRatio=%f color=%d \n",
|
||||
// (down ? "TRUE" : "FALSE"), distance, _minDistance, _maxDistance, distanceRatio, (int)newR);
|
||||
|
||||
node->setFalseColor(newR,newG,newB);
|
||||
|
@ -641,7 +666,7 @@ bool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, bool down,
|
|||
//printf("getDistanceFromViewRangeOperation() down=%s\n",(down ? "TRUE" : "FALSE"));
|
||||
|
||||
ViewFrustum* viewFrustum = (ViewFrustum*) extraData;
|
||||
|
||||
|
||||
// only do this for truly colored voxels...
|
||||
if (node->isColored()) {
|
||||
|
||||
|
@ -687,7 +712,7 @@ void VoxelSystem::falseColorizeDistanceFromView(ViewFrustum* viewFrustum) {
|
|||
printf("determining distance range for %d nodes\n",_nodeCount);
|
||||
|
||||
_nodeCount = 0;
|
||||
|
||||
|
||||
tree->recurseTreeWithOperation(falseColorizeDistanceFromViewOperation,(void*)viewFrustum);
|
||||
printf("setting in distance false color for %d nodes\n",_nodeCount);
|
||||
setupNewVoxelsForDrawing();
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include <AgentData.h>
|
||||
#include <VoxelTree.h>
|
||||
#include <ViewFrustum.h>
|
||||
#include "Head.h"
|
||||
#include "Avatar.h"
|
||||
#include "Util.h"
|
||||
#include "world.h"
|
||||
|
||||
|
@ -25,16 +25,16 @@ class VoxelSystem : public AgentData {
|
|||
public:
|
||||
VoxelSystem();
|
||||
~VoxelSystem();
|
||||
|
||||
|
||||
int parseData(unsigned char* sourceBuffer, int numBytes);
|
||||
VoxelSystem* clone() const;
|
||||
|
||||
|
||||
void init();
|
||||
void simulate(float deltaTime);
|
||||
void render();
|
||||
void setVoxelsRendered(int v) {voxelsRendered = v;};
|
||||
int getVoxelsRendered() {return voxelsRendered;};
|
||||
void setViewerHead(Head *newViewerHead);
|
||||
void setViewerAvatar(Avatar *newViewerAvatar);
|
||||
void loadVoxelsFile(const char* fileName,bool wantColorRandomizer);
|
||||
void createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer);
|
||||
|
||||
|
@ -67,7 +67,7 @@ private:
|
|||
static float _minDistance;
|
||||
|
||||
int voxelsRendered;
|
||||
Head *viewerHead;
|
||||
Avatar *viewerAvatar;
|
||||
VoxelTree *tree;
|
||||
GLfloat *readVerticesArray;
|
||||
GLubyte *readColorsArray;
|
||||
|
@ -76,6 +76,7 @@ private:
|
|||
GLubyte *writeColorsArray;
|
||||
GLfloat *writeVerticesEndPointer;
|
||||
GLuint vboVerticesID;
|
||||
GLuint vboNormalsID;
|
||||
GLuint vboColorsID;
|
||||
GLuint vboIndicesID;
|
||||
pthread_mutex_t bufferWriteLock;
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
#include "MenuColumn.h"
|
||||
#include "Menu.h"
|
||||
#include "Camera.h"
|
||||
#include "Head.h"
|
||||
#include "Avatar.h"
|
||||
#include "Particle.h"
|
||||
#include "Texture.h"
|
||||
#include "Cloud.h"
|
||||
|
@ -107,7 +107,7 @@ Oscilloscope audioScope(256,200,true);
|
|||
|
||||
ViewFrustum viewFrustum; // current state of view frustum, perspective, orientation, etc.
|
||||
|
||||
Head myAvatar(true); // The rendered avatar of oneself
|
||||
Avatar myAvatar(true); // The rendered avatar of oneself
|
||||
Camera myCamera; // My view onto the world (sometimes on myself :)
|
||||
Camera viewFrustumOffsetCamera; // The camera we use to sometimes show the view frustum from an offset mode
|
||||
|
||||
|
@ -157,11 +157,15 @@ VoxelDetail paintingVoxel; // The voxel we're painting if we're paintin
|
|||
unsigned char dominantColor = 0; // The dominant color of the voxel we're painting
|
||||
bool perfStatsOn = false; // Do we want to display perfStats?
|
||||
|
||||
bool logOn = true; // Whether to show on-screen log
|
||||
|
||||
int noiseOn = 0; // Whether to add random noise
|
||||
float noise = 1.0; // Overall magnitude scaling for random noise levels
|
||||
|
||||
bool gyroLook = false; // Whether to allow the gyro data from head to move your view
|
||||
|
||||
int displayLevels = 0;
|
||||
bool lookingInMirror = 0; // Are we currently rendering one's own head as if in mirror?
|
||||
bool lookingInMirror = 0; // Are we currently rendering one's own head as if in mirror?
|
||||
int displayField = 0;
|
||||
|
||||
int displayHeadMouse = 1; // Display sample mouse pointer controlled by head movement
|
||||
|
@ -304,7 +308,7 @@ void displayStats(void)
|
|||
char legend2[] = "* - toggle stars, & - toggle paint mode, '-' - send erase all, '%' - send add scene";
|
||||
drawtext(10, statsVerticalOffset + 32, 0.10f, 0, 1.0, 0, legend2);
|
||||
|
||||
glm::vec3 avatarPos = myAvatar.getBodyPosition();
|
||||
glm::vec3 avatarPos = myAvatar.getPosition();
|
||||
|
||||
char stats[200];
|
||||
sprintf(stats, "FPS = %3.0f Pkts/s = %d Bytes/s = %d Head(x,y,z)= %4.2f, %4.2f, %4.2f ",
|
||||
|
@ -380,7 +384,7 @@ void initDisplay(void)
|
|||
void init(void)
|
||||
{
|
||||
voxels.init();
|
||||
voxels.setViewerHead(&myAvatar);
|
||||
voxels.setViewerAvatar(&myAvatar);
|
||||
myAvatar.setRenderYaw(startYaw);
|
||||
|
||||
initializeHandController();
|
||||
|
@ -396,8 +400,8 @@ void init(void)
|
|||
if (noiseOn) {
|
||||
myAvatar.setNoise(noise);
|
||||
}
|
||||
myAvatar.setBodyPosition(start_location);
|
||||
myCamera.setPosition( start_location );
|
||||
myAvatar.setPosition(start_location);
|
||||
myCamera.setPosition(start_location);
|
||||
|
||||
|
||||
#ifdef MARKER_CAPTURE
|
||||
|
@ -438,7 +442,7 @@ void reset_sensors()
|
|||
|
||||
renderYawRate = 0;
|
||||
renderPitchRate = 0;
|
||||
myAvatar.setBodyPosition(start_location);
|
||||
myAvatar.setPosition(start_location);
|
||||
headMouseX = WIDTH/2;
|
||||
headMouseY = HEIGHT/2;
|
||||
|
||||
|
@ -476,31 +480,16 @@ void updateAvatar(float frametime)
|
|||
headMouseY = min(headMouseY, HEIGHT);
|
||||
|
||||
// Update render direction (pitch/yaw) based on measured gyro rates
|
||||
const int MIN_YAW_RATE = 100;
|
||||
const int MIN_PITCH_RATE = 100;
|
||||
const float YAW_SENSITIVITY = 0.02;
|
||||
const float PITCH_SENSITIVITY = 0.05;
|
||||
const float MIN_YAW_RATE = 5;
|
||||
const float YAW_SENSITIVITY = 1.0;
|
||||
|
||||
// Update render pitch and yaw rates based on keyPositions
|
||||
const float KEY_YAW_SENSITIVITY = 2.0;
|
||||
if (myAvatar.getDriveKeys(ROT_LEFT)) renderYawRate -= KEY_YAW_SENSITIVITY*frametime;
|
||||
if (myAvatar.getDriveKeys(ROT_RIGHT)) renderYawRate += KEY_YAW_SENSITIVITY*frametime;
|
||||
// If enabled, Update render pitch and yaw based on gyro data
|
||||
if (::gyroLook) {
|
||||
if (fabs(gyroYawRate) > MIN_YAW_RATE) {
|
||||
myAvatar.addBodyYaw(-gyroYawRate * YAW_SENSITIVITY * frametime);
|
||||
}
|
||||
}
|
||||
|
||||
if (fabs(gyroYawRate) > MIN_YAW_RATE)
|
||||
{
|
||||
if (gyroYawRate > 0)
|
||||
renderYawRate += (gyroYawRate - MIN_YAW_RATE) * YAW_SENSITIVITY * frametime;
|
||||
else
|
||||
renderYawRate += (gyroYawRate + MIN_YAW_RATE) * YAW_SENSITIVITY * frametime;
|
||||
}
|
||||
if (fabs(gyroPitchRate) > MIN_PITCH_RATE)
|
||||
{
|
||||
if (gyroPitchRate > 0)
|
||||
renderPitchRate += (gyroPitchRate - MIN_PITCH_RATE) * PITCH_SENSITIVITY * frametime;
|
||||
else
|
||||
renderPitchRate += (gyroPitchRate + MIN_PITCH_RATE) * PITCH_SENSITIVITY * frametime;
|
||||
}
|
||||
|
||||
float renderPitch = myAvatar.getRenderPitch();
|
||||
// Decay renderPitch toward zero because we never look constantly up/down
|
||||
renderPitch *= (1.f - 2.0*frametime);
|
||||
|
@ -514,11 +503,8 @@ void updateAvatar(float frametime)
|
|||
myAvatar.setRenderPitch(renderPitch + renderPitchRate);
|
||||
|
||||
// Get audio loudness data from audio input device
|
||||
float loudness, averageLoudness;
|
||||
#ifndef _WIN32
|
||||
audio.getInputLoudness(&loudness, &averageLoudness);
|
||||
myAvatar.setLoudness(loudness);
|
||||
myAvatar.setAverageLoudness(averageLoudness);
|
||||
myAvatar.setLoudness(audio.getInputLoudness());
|
||||
#endif
|
||||
|
||||
// Update Avatar with latest camera and view frustum data...
|
||||
|
@ -551,7 +537,7 @@ void updateAvatar(float frametime)
|
|||
// If I'm in paint mode, send a voxel out to VOXEL server agents.
|
||||
if (::paintOn) {
|
||||
|
||||
glm::vec3 avatarPos = myAvatar.getBodyPosition();
|
||||
glm::vec3 avatarPos = myAvatar.getPosition();
|
||||
|
||||
// For some reason, we don't want to flip X and Z here.
|
||||
::paintingVoxel.x = avatarPos.x/10.0;
|
||||
|
@ -833,7 +819,7 @@ void display(void)
|
|||
//----------------------------------------------------
|
||||
// set the camera to third-person view behind my av
|
||||
//----------------------------------------------------
|
||||
myCamera.setTargetPosition ( myAvatar.getBodyPosition() );
|
||||
myCamera.setTargetPosition ( myAvatar.getPosition() );
|
||||
myCamera.setYaw ( 180.0 - myAvatar.getBodyYaw() );
|
||||
myCamera.setPitch ( 0.0 ); // temporarily, this must be 0.0 or else bad juju
|
||||
myCamera.setRoll ( 0.0 );
|
||||
|
@ -878,9 +864,10 @@ void display(void)
|
|||
if (::starsOn) {
|
||||
// should be the first rendering pass - w/o depth buffer / lighting
|
||||
|
||||
glm::mat4 view;
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, glm::value_ptr(view));
|
||||
stars.render(angleConvert<Degrees,Radians>(whichCamera.getFieldOfView()), aspectRatio, view);
|
||||
|
||||
// finally render the starfield
|
||||
stars.render(whichCamera.getFieldOfView(), aspectRatio, whichCamera.getNearClip());
|
||||
|
||||
}
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
|
@ -927,7 +914,7 @@ void display(void)
|
|||
agent != agentList->getAgents().end();
|
||||
agent++) {
|
||||
if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) {
|
||||
Head *avatar = (Head *)agent->getLinkedData();
|
||||
Avatar *avatar = (Avatar *)agent->getLinkedData();
|
||||
avatar->render(0);
|
||||
}
|
||||
}
|
||||
|
@ -935,7 +922,7 @@ void display(void)
|
|||
if ( !::lookingInMirror ) balls.render();
|
||||
|
||||
// Render the world box
|
||||
if (!::lookingInMirror && statsOn) render_world_box();
|
||||
if (!::lookingInMirror && ::statsOn) { render_world_box(); }
|
||||
|
||||
// brad's frustum for debugging
|
||||
if (::frustumOn) renderViewFrustum(::viewFrustum);
|
||||
|
@ -977,13 +964,12 @@ void display(void)
|
|||
// Show detected levels from the serial I/O ADC channel sensors
|
||||
if (displayLevels) serialPort.renderLevels(WIDTH,HEIGHT);
|
||||
|
||||
// Display miscellaneous text stats onscreen
|
||||
if (statsOn) {
|
||||
glLineWidth(1.0f);
|
||||
glPointSize(1.0f);
|
||||
displayStats();
|
||||
logger.render(WIDTH, HEIGHT);
|
||||
}
|
||||
// Display stats and log text onscreen
|
||||
glLineWidth(1.0f);
|
||||
glPointSize(1.0f);
|
||||
|
||||
if (::statsOn) { displayStats(); }
|
||||
if (::logOn) { logger.render(WIDTH, HEIGHT); }
|
||||
|
||||
// Show menu
|
||||
if (::menuOn) {
|
||||
|
@ -1072,6 +1058,16 @@ int setNoise(int state) {
|
|||
return iRet;
|
||||
}
|
||||
|
||||
int setLog(int state) {
|
||||
int iRet = setValue(state, &::logOn);
|
||||
return iRet;
|
||||
}
|
||||
|
||||
int setGyroLook(int state) {
|
||||
int iRet = setValue(state, &::gyroLook);
|
||||
return iRet;
|
||||
}
|
||||
|
||||
int setVoxels(int state) {
|
||||
return setValue(state, &::showingVoxels);
|
||||
}
|
||||
|
@ -1081,7 +1077,7 @@ int setStars(int state) {
|
|||
}
|
||||
|
||||
int setStats(int state) {
|
||||
return setValue(state, &statsOn);
|
||||
return setValue(state, &::statsOn);
|
||||
}
|
||||
|
||||
int setMenu(int state) {
|
||||
|
@ -1190,19 +1186,24 @@ const char* getFrustumRenderModeName(int state) {
|
|||
}
|
||||
|
||||
void initMenu() {
|
||||
MenuColumn *menuColumnOptions, *menuColumnTools, *menuColumnDebug, *menuColumnFrustum;
|
||||
MenuColumn *menuColumnOptions, *menuColumnRender, *menuColumnTools, *menuColumnDebug, *menuColumnFrustum;
|
||||
// Options
|
||||
menuColumnOptions = menu.addColumn("Options");
|
||||
menuColumnOptions->addRow("Mirror (h)", setHead);
|
||||
menuColumnOptions->addRow("Field (f)", setField);
|
||||
menuColumnOptions->addRow("(N)oise", setNoise);
|
||||
menuColumnOptions->addRow("(V)oxels", setVoxels);
|
||||
menuColumnOptions->addRow("Stars (*)", setStars);
|
||||
menuColumnOptions->addRow("(Q)uit", quitApp);
|
||||
menuColumnOptions->addRow("Noise (n)", setNoise);
|
||||
menuColumnOptions->addRow("Gyro Look", setGyroLook);
|
||||
menuColumnOptions->addRow("Quit (q)", quitApp);
|
||||
|
||||
// Render
|
||||
menuColumnRender = menu.addColumn("Render");
|
||||
menuColumnRender->addRow("Voxels (V)", setVoxels);
|
||||
menuColumnRender->addRow("Stars (*)", setStars);
|
||||
menuColumnRender->addRow("Field (f)", setField);
|
||||
|
||||
// Tools
|
||||
menuColumnTools = menu.addColumn("Tools");
|
||||
menuColumnTools->addRow("Stats (/)", setStats);
|
||||
menuColumnTools->addRow("Stats (/)", setStats);
|
||||
menuColumnTools->addRow("Log ", setLog);
|
||||
menuColumnTools->addRow("(M)enu", setMenu);
|
||||
|
||||
// Frustum Options
|
||||
|
@ -1265,7 +1266,7 @@ void shiftPaintingColor()
|
|||
}
|
||||
|
||||
void setupPaintingVoxel() {
|
||||
glm::vec3 avatarPos = myAvatar.getBodyPosition();
|
||||
glm::vec3 avatarPos = myAvatar.getPosition();
|
||||
|
||||
::paintingVoxel.x = avatarPos.z/-10.0; // voxel space x is negative z head space
|
||||
::paintingVoxel.y = avatarPos.y/-10.0; // voxel space y is negative y head space
|
||||
|
@ -1360,7 +1361,7 @@ void key(unsigned char k, int x, int y)
|
|||
|
||||
// Process keypresses
|
||||
if (k == 'q' || k == 'Q') ::terminate();
|
||||
if (k == '/') statsOn = !statsOn; // toggle stats
|
||||
if (k == '/') ::statsOn = !::statsOn; // toggle stats
|
||||
if (k == '*') ::starsOn = !::starsOn; // toggle stars
|
||||
if (k == 'V' || k == 'v') ::showingVoxels = !::showingVoxels; // toggle voxels
|
||||
if (k == 'F') ::frustumOn = !::frustumOn; // toggle view frustum debugging
|
||||
|
@ -1494,13 +1495,13 @@ void idle(void) {
|
|||
//
|
||||
updateAvatar(deltaTime);
|
||||
|
||||
//loop through all the other avatars and simulate them.
|
||||
//loop through all the other avatars and simulate them...
|
||||
AgentList * agentList = AgentList::getInstance();
|
||||
for(std::vector<Agent>::iterator agent = agentList->getAgents().begin(); agent != agentList->getAgents().end(); agent++)
|
||||
{
|
||||
if (agent->getLinkedData() != NULL)
|
||||
{
|
||||
Head *avatar = (Head *)agent->getLinkedData();
|
||||
Avatar *avatar = (Avatar *)agent->getLinkedData();
|
||||
avatar->simulate(deltaTime);
|
||||
}
|
||||
}
|
||||
|
@ -1512,7 +1513,6 @@ void idle(void) {
|
|||
|
||||
glutPostRedisplay();
|
||||
lastTimeIdle = check;
|
||||
|
||||
}
|
||||
|
||||
// Read serial data
|
||||
|
@ -1612,7 +1612,7 @@ void mouseoverFunc( int x, int y)
|
|||
|
||||
void attachNewHeadToAgent(Agent *newAgent) {
|
||||
if (newAgent->getLinkedData() == NULL) {
|
||||
newAgent->setLinkedData(new Head(false));
|
||||
newAgent->setLinkedData(new Avatar(false));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -130,17 +130,18 @@ namespace starfield {
|
|||
|
||||
float halfPersp = perspective * 0.5f;
|
||||
|
||||
// determine dimensions based on a sought screen diagonal
|
||||
//
|
||||
// ww + hh = dd
|
||||
// a = h / w => h = wa
|
||||
// ww + ww aa = dd
|
||||
// ww = dd / (1 + aa)
|
||||
float diag = 2.0f * std::sin(halfPersp);
|
||||
// define diagonal and near distance
|
||||
float halfDiag = std::sin(halfPersp);
|
||||
float nearClip = std::cos(halfPersp);
|
||||
|
||||
float hw = 0.5f * sqrt(diag * diag / (1.0f + aspect * aspect));
|
||||
float hh = hw * aspect;
|
||||
// determine half dimensions based on the screen diagonal
|
||||
//
|
||||
// ww + hh = dd
|
||||
// a = w / h => w = ha
|
||||
// hh + hh aa = dd
|
||||
// hh = dd / (1 + aa)
|
||||
float hh = sqrt(halfDiag * halfDiag / (1.0f + aspect * aspect));
|
||||
float hw = hh * aspect;
|
||||
|
||||
// cancel all translation
|
||||
mat4 matrix = orientation;
|
||||
|
@ -154,6 +155,9 @@ namespace starfield {
|
|||
float azimuth = atan2(ahead.x,-ahead.z) + Radians::pi();
|
||||
float altitude = atan2(-ahead.y, hypotf(ahead.x, ahead.z));
|
||||
angleHorizontalPolar<Radians>(azimuth, altitude);
|
||||
float const eps = 0.002f;
|
||||
altitude = glm::clamp(altitude,
|
||||
-Radians::halfPi() + eps, Radians::halfPi() - eps);
|
||||
#if STARFIELD_HEMISPHERE_ONLY
|
||||
altitude = std::max(0.0f, altitude);
|
||||
#endif
|
||||
|
@ -162,24 +166,25 @@ namespace starfield {
|
|||
|
||||
// printLog("Stars.cpp: starting on tile #%d\n", tileIndex);
|
||||
|
||||
|
||||
#if STARFIELD_DEBUG_CULLING
|
||||
mat4 matrix_debug = glm::translate(
|
||||
glm::frustum(-hw, hw, -hh, hh, nearClip, 10.0f),
|
||||
vec3(0.0f, 0.0f, -4.0f)) * glm::affineInverse(matrix);
|
||||
mat4 matrix_debug = glm::translate(glm::frustum(-hw, hw, -hh, hh, nearClip, 10.0f),
|
||||
vec3(0.0f, 0.0f, -4.0f)) *
|
||||
glm::affineInverse(matrix);
|
||||
#endif
|
||||
|
||||
matrix = glm::frustum(-hw,hw, -hh,hh, nearClip,10.0f)
|
||||
* glm::affineInverse(matrix);
|
||||
matrix = glm::frustum(-hw,hw, -hh,hh, nearClip,10.0f) * glm::affineInverse(matrix);
|
||||
|
||||
this->_itrOutIndex = (unsigned*) _arrBatchOffs;
|
||||
this->_vecWxform = vec3(row(matrix, 3));
|
||||
this->_valHalfPersp = halfPersp;
|
||||
this->_valMinBright = minBright;
|
||||
|
||||
floodFill(_arrTile + tileIndex, TileSelection(*this,
|
||||
_arrTile, _arrTile + _objTiling.getTileCount(),
|
||||
(Tile**) _arrBatchCount));
|
||||
TileSelection::Cursor cursor;
|
||||
cursor.current = _arrTile + _objTiling.getTileIndex(azimuth, altitude);
|
||||
cursor.firstInRow = _arrTile + _objTiling.getTileIndex(0.0f, altitude);
|
||||
|
||||
floodFill(cursor, TileSelection(*this, _arrTile, _arrTile + _objTiling.getTileCount(),
|
||||
(TileSelection::Cursor*) _arrBatchCount));
|
||||
|
||||
#if STARFIELD_DEBUG_CULLING
|
||||
# define matrix matrix_debug
|
||||
|
@ -269,31 +274,35 @@ namespace starfield {
|
|||
|
||||
class TileSelection {
|
||||
|
||||
public:
|
||||
struct Cursor { Tile* current, * firstInRow; };
|
||||
private:
|
||||
Renderer& _refRenderer;
|
||||
Tile** const _arrStack;
|
||||
Tile** _itrStack;
|
||||
Cursor* const _arrStack;
|
||||
Cursor* _itrStack;
|
||||
Tile const* const _arrTile;
|
||||
Tile const* const _itrTilesEnd;
|
||||
Tile const* const _ptrTilesEnd;
|
||||
|
||||
public:
|
||||
|
||||
TileSelection(Renderer& renderer, Tile const* tiles,
|
||||
Tile const* tiles_end, Tile** stack) :
|
||||
Tile const* tiles_end, Cursor* stack) :
|
||||
|
||||
_refRenderer(renderer),
|
||||
_arrStack(stack),
|
||||
_itrStack(stack),
|
||||
_arrTile(tiles),
|
||||
_itrTilesEnd(tiles_end) {
|
||||
_ptrTilesEnd(tiles_end) {
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// flood fill strategy
|
||||
|
||||
bool select(Tile* t) {
|
||||
bool select(Cursor const& c) {
|
||||
Tile* t = c.current;
|
||||
|
||||
if (t < _arrTile || t >= _itrTilesEnd ||
|
||||
if (t < _arrTile || t >= _ptrTilesEnd ||
|
||||
!! (t->flags & Tile::checked)) {
|
||||
|
||||
// out of bounds or been here already
|
||||
|
@ -311,7 +320,8 @@ namespace starfield {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool process(Tile* t) {
|
||||
bool process(Cursor const& c) {
|
||||
Tile* t = c.current;
|
||||
|
||||
if (! (t->flags & Tile::visited)) {
|
||||
|
||||
|
@ -321,14 +331,39 @@ namespace starfield {
|
|||
return false;
|
||||
}
|
||||
|
||||
void right(Tile*& cursor) const { cursor += 1; }
|
||||
void left(Tile*& cursor) const { cursor -= 1; }
|
||||
void up(Tile*& cursor) const { cursor += yStride(); }
|
||||
void down(Tile*& cursor) const { cursor -= yStride(); }
|
||||
void right(Cursor& c) const {
|
||||
|
||||
void defer(Tile* t) { *_itrStack++ = t; }
|
||||
c.current += 1;
|
||||
if (c.current == c.firstInRow + _refRenderer._objTiling.getAzimuthalTiles()) {
|
||||
c.current = c.firstInRow;
|
||||
}
|
||||
}
|
||||
void left(Cursor& c) const {
|
||||
|
||||
if (c.current == c.firstInRow) {
|
||||
c.current = c.firstInRow + _refRenderer._objTiling.getAzimuthalTiles();
|
||||
}
|
||||
c.current -= 1;
|
||||
}
|
||||
void up(Cursor& c) const {
|
||||
|
||||
bool deferred(Tile*& cursor) {
|
||||
unsigned d = _refRenderer._objTiling.getAzimuthalTiles();
|
||||
c.current += d;
|
||||
c.firstInRow += d;
|
||||
}
|
||||
void down(Cursor& c) const {
|
||||
|
||||
unsigned d = _refRenderer._objTiling.getAzimuthalTiles();
|
||||
c.current -= d;
|
||||
c.firstInRow -= d;
|
||||
}
|
||||
|
||||
void defer(Cursor const& t) {
|
||||
|
||||
*_itrStack++ = t;
|
||||
}
|
||||
|
||||
bool deferred(Cursor& cursor) {
|
||||
|
||||
if (_itrStack != _arrStack) {
|
||||
cursor = *--_itrStack;
|
||||
|
@ -336,12 +371,6 @@ namespace starfield {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned yStride() const {
|
||||
|
||||
return _refRenderer._objTiling.getAzimuthalTiles();
|
||||
}
|
||||
};
|
||||
|
||||
bool visitTile(Tile* t) {
|
||||
|
@ -362,6 +391,7 @@ namespace starfield {
|
|||
bool tileVisible(Tile* t, unsigned i) {
|
||||
|
||||
float slice = _objTiling.getSliceAngle();
|
||||
float halfSlice = 0.5f * slice;
|
||||
unsigned stride = _objTiling.getAzimuthalTiles();
|
||||
float azimuth = (i % stride) * slice;
|
||||
float altitude = (i / stride) * slice - Radians::halfPi();
|
||||
|
@ -371,14 +401,13 @@ namespace starfield {
|
|||
vec3 tileCenter = vec3(gx * exz, sin(altitude), gz * exz);
|
||||
float w = dot(_vecWxform, tileCenter);
|
||||
|
||||
float halfSlice = 0.5f * slice;
|
||||
float daz = halfSlice * cos(abs(altitude) - halfSlice);
|
||||
float daz = halfSlice * cos(std::max(0.0f, abs(altitude) - halfSlice));
|
||||
float dal = halfSlice;
|
||||
float adjustedNear = cos(_valHalfPersp + sqrt(daz * daz + dal * dal));
|
||||
|
||||
// printLog("Stars.cpp: checking tile #%d, w = %f, near = %f\n", i, w, nearClip);
|
||||
|
||||
return w > adjustedNear;
|
||||
return w >= adjustedNear;
|
||||
}
|
||||
|
||||
void updateVertexCount(Tile* t, BrightnessLevel minBright) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// starfield/renderer/
|
||||
// starfield/renderer/Tiling.h
|
||||
// interface
|
||||
//
|
||||
// Created by Tobias Schwinger on 3/22/13.
|
||||
|
@ -51,6 +51,7 @@ namespace starfield {
|
|||
private:
|
||||
|
||||
unsigned discreteAngle(float unsigned_angle) const {
|
||||
|
||||
return unsigned(floor(unsigned_angle * _valRcpSlice + 0.5f));
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
|
|||
// and return the number of bytes to push the pointer
|
||||
|
||||
// Body world position
|
||||
memcpy(destinationBuffer, &_bodyPosition, sizeof(float) * 3);
|
||||
memcpy(destinationBuffer, &_position, sizeof(float) * 3);
|
||||
destinationBuffer += sizeof(float) * 3;
|
||||
|
||||
// Body rotation (NOTE: This needs to become a quaternion to save two bytes)
|
||||
|
@ -125,7 +125,7 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
unsigned char* startPosition = sourceBuffer;
|
||||
|
||||
// Body world position
|
||||
memcpy(&_bodyPosition, sourceBuffer, sizeof(float) * 3);
|
||||
memcpy(&_position, sourceBuffer, sizeof(float) * 3);
|
||||
sourceBuffer += sizeof(float) * 3;
|
||||
|
||||
// Body rotation (NOTE: This needs to become a quaternion to save two bytes)
|
||||
|
@ -171,14 +171,14 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
return sourceBuffer - startPosition;
|
||||
}
|
||||
|
||||
glm::vec3 AvatarData::getBodyPosition() {
|
||||
return glm::vec3(_bodyPosition.x,
|
||||
_bodyPosition.y,
|
||||
_bodyPosition.z);
|
||||
glm::vec3 AvatarData::getPosition() {
|
||||
return glm::vec3(_position.x,
|
||||
_position.y,
|
||||
_position.z);
|
||||
}
|
||||
|
||||
void AvatarData::setBodyPosition(glm::vec3 bodyPosition) {
|
||||
_bodyPosition = bodyPosition;
|
||||
void AvatarData::setPosition(glm::vec3 position) {
|
||||
_position = position;
|
||||
}
|
||||
|
||||
void AvatarData::setHandPosition(glm::vec3 handPosition) {
|
||||
|
|
|
@ -20,8 +20,8 @@ public:
|
|||
|
||||
AvatarData* clone() const;
|
||||
|
||||
glm::vec3 getBodyPosition();
|
||||
void setBodyPosition(glm::vec3 bodyPosition);
|
||||
glm::vec3 getPosition();
|
||||
void setPosition(glm::vec3 position);
|
||||
void setHandPosition(glm::vec3 handPosition);
|
||||
|
||||
int getBroadcastData(unsigned char* destinationBuffer);
|
||||
|
@ -39,20 +39,20 @@ public:
|
|||
void setHeadPitch(float p) {_headPitch = p; }
|
||||
void setHeadYaw(float y) {_headYaw = y; }
|
||||
void setHeadRoll(float r) {_headRoll = r; };
|
||||
const float getHeadPitch() const { return _headPitch; };
|
||||
const float getHeadYaw() const { return _headYaw; };
|
||||
const float getHeadRoll() const { return _headRoll; };
|
||||
float getHeadPitch() const { return _headPitch; };
|
||||
float getHeadYaw() const { return _headYaw; };
|
||||
float getHeadRoll() const { return _headRoll; };
|
||||
void addHeadPitch(float p) {_headPitch -= p; }
|
||||
void addHeadYaw(float y){_headYaw -= y; }
|
||||
void addHeadRoll(float r){_headRoll += r; }
|
||||
|
||||
// Hand State
|
||||
void setHandState(char s) { _handState = s; };
|
||||
const float getHandState() const {return _handState; };
|
||||
char getHandState() const {return _handState; };
|
||||
|
||||
// Instantaneous audio loudness to drive mouth/facial animation
|
||||
void setLoudness(float l) { _audioLoudness = l; };
|
||||
const float getLoudness() const {return _audioLoudness; };
|
||||
float getLoudness() const {return _audioLoudness; };
|
||||
|
||||
// getters for camera details
|
||||
const glm::vec3& getCameraPosition() const { return _cameraPosition; };
|
||||
|
@ -75,7 +75,7 @@ public:
|
|||
void setCameraFarClip(float farClip) { _cameraFarClip = farClip; }
|
||||
|
||||
protected:
|
||||
glm::vec3 _bodyPosition;
|
||||
glm::vec3 _position;
|
||||
glm::vec3 _handPosition;
|
||||
|
||||
// Body rotation
|
||||
|
|
|
@ -261,30 +261,19 @@ float Agent::getAverageKilobitsPerSecond() {
|
|||
}
|
||||
|
||||
void Agent::printLog(Agent const& agent) {
|
||||
|
||||
sockaddr_in *agentPublicSocket = (sockaddr_in *) agent.publicSocket;
|
||||
sockaddr_in *agentLocalSocket = (sockaddr_in *) agent.localSocket;
|
||||
|
||||
const char* publicAddressString = (agentPublicSocket == NULL)
|
||||
? "Unknown"
|
||||
: inet_ntoa(agentPublicSocket->sin_addr);
|
||||
unsigned short publicAddressPort = (agentPublicSocket == NULL)
|
||||
? 0
|
||||
: ntohs(agentPublicSocket->sin_port);
|
||||
char publicAddressBuffer[16] = {'\0'};
|
||||
unsigned short publicAddressPort = loadBufferWithSocketInfo(publicAddressBuffer, agent.publicSocket);
|
||||
|
||||
char localAddressBuffer[16] = {'\0'};
|
||||
unsigned short localAddressPort = loadBufferWithSocketInfo(localAddressBuffer, agent.localSocket);
|
||||
|
||||
const char* localAddressString = (agentLocalSocket == NULL)
|
||||
? "Unknown"
|
||||
: inet_ntoa(agentLocalSocket->sin_addr);
|
||||
unsigned short localAddressPort = (agentLocalSocket == NULL)
|
||||
? 0
|
||||
: ntohs(agentPublicSocket->sin_port);
|
||||
|
||||
::printLog("ID: %d T: %s (%c) PA: %s:%d LA: %s:%d\n",
|
||||
agent.agentId,
|
||||
agent.getTypeName(),
|
||||
agent.type,
|
||||
publicAddressString,
|
||||
publicAddressBuffer,
|
||||
publicAddressPort,
|
||||
localAddressString,
|
||||
localAddressBuffer,
|
||||
localAddressPort);
|
||||
}
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
using shared_lib::printLog;
|
||||
|
||||
const char SOLO_AGENT_TYPES_STRING[] = {
|
||||
const char SOLO_AGENT_TYPES[3] = {
|
||||
AGENT_TYPE_AVATAR_MIXER,
|
||||
AGENT_TYPE_AUDIO_MIXER,
|
||||
AGENT_TYPE_VOXEL
|
||||
|
@ -305,8 +305,8 @@ void AgentList::handlePingReply(sockaddr *agentAddress) {
|
|||
}
|
||||
}
|
||||
|
||||
Agent* AgentList::soloAgentOfType(char agentType) {
|
||||
if (memchr(SOLO_AGENT_TYPES_STRING, agentType, 1)) {
|
||||
Agent* AgentList::soloAgentOfType(char agentType) {
|
||||
if (memchr(SOLO_AGENT_TYPES, agentType, sizeof(SOLO_AGENT_TYPES)) != NULL) {
|
||||
for(std::vector<Agent>::iterator agent = agents.begin(); agent != agents.end(); agent++) {
|
||||
if (agent->getType() == agentType) {
|
||||
return &*agent;
|
||||
|
@ -428,7 +428,7 @@ void *checkInWithDomainServer(void *args) {
|
|||
sockaddr_in tempAddress;
|
||||
memcpy(&tempAddress.sin_addr, pHostInfo->h_addr_list[0], pHostInfo->h_length);
|
||||
strcpy(DOMAIN_IP, inet_ntoa(tempAddress.sin_addr));
|
||||
printLog("Domain server: %s \n", DOMAIN_HOSTNAME);
|
||||
printLog("Domain server: %s - %s\n", DOMAIN_HOSTNAME, DOMAIN_IP);
|
||||
|
||||
} else {
|
||||
printLog("Failed lookup domainserver\n");
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
const int MAX_PACKET_SIZE = 1500;
|
||||
const unsigned int AGENT_SOCKET_LISTEN_PORT = 40103;
|
||||
const int AGENT_SILENCE_THRESHOLD_USECS = 2 * 1000000;
|
||||
extern const char SOLO_AGENT_TYPES_STRING[];
|
||||
extern const char SOLO_AGENT_TYPES[3];
|
||||
|
||||
extern char DOMAIN_HOSTNAME[];
|
||||
extern char DOMAIN_IP[100]; // IP Address will be re-set by lookup on startup
|
||||
|
|
103
libraries/shared/src/AudioInjector.cpp
Normal file
103
libraries/shared/src/AudioInjector.cpp
Normal file
|
@ -0,0 +1,103 @@
|
|||
//
|
||||
// AudioInjector.cpp
|
||||
// hifi
|
||||
//
|
||||
// Created by Stephen Birarda on 4/23/13.
|
||||
//
|
||||
//
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
|
||||
#include "SharedUtil.h"
|
||||
#include "PacketHeaders.h"
|
||||
|
||||
#include "AudioInjector.h"
|
||||
|
||||
const int BUFFER_LENGTH_BYTES = 512;
|
||||
const int BUFFER_LENGTH_SAMPLES = BUFFER_LENGTH_BYTES / sizeof(int16_t);
|
||||
const float SAMPLE_RATE = 22050.0f;
|
||||
const float BUFFER_SEND_INTERVAL_USECS = (BUFFER_LENGTH_SAMPLES / SAMPLE_RATE) * 1000000;
|
||||
|
||||
AudioInjector::AudioInjector(const char* filename) :
|
||||
_numTotalBytesAudio(0),
|
||||
_bearing(0),
|
||||
_attenuationModifier(255)
|
||||
{
|
||||
_position[0] = 0.0f;
|
||||
_position[1] = 0.0f;
|
||||
_position[2] = 0.0f;
|
||||
|
||||
std::fstream sourceFile;
|
||||
|
||||
sourceFile.open(filename, std::ios::in | std::ios::binary);
|
||||
sourceFile.seekg(0, std::ios::end);
|
||||
|
||||
_numTotalBytesAudio = sourceFile.tellg();
|
||||
if (_numTotalBytesAudio == -1) {
|
||||
printf("Error reading audio data from file %s\n", filename);
|
||||
_audioSampleArray = NULL;
|
||||
} else {
|
||||
printf("Read %d bytes from audio file\n", _numTotalBytesAudio);
|
||||
sourceFile.seekg(0, std::ios::beg);
|
||||
long sizeOfShortArray = _numTotalBytesAudio / 2;
|
||||
_audioSampleArray = new int16_t[sizeOfShortArray];
|
||||
|
||||
sourceFile.read((char *)_audioSampleArray, _numTotalBytesAudio);
|
||||
}
|
||||
}
|
||||
|
||||
AudioInjector::~AudioInjector() {
|
||||
delete[] _audioSampleArray;
|
||||
}
|
||||
|
||||
void AudioInjector::setPosition(float* position) {
|
||||
_position[0] = position[0];
|
||||
_position[1] = position[1];
|
||||
_position[2] = position[2];
|
||||
}
|
||||
|
||||
void AudioInjector::injectAudio(UDPSocket* injectorSocket, sockaddr* destinationSocket) const {
|
||||
if (_audioSampleArray != NULL) {
|
||||
timeval startTime;
|
||||
|
||||
// one byte for header, 3 positional floats, 1 bearing float, 1 attenuation modifier byte
|
||||
int leadingBytes = 1 + (sizeof(float) * 4) + 1;
|
||||
unsigned char dataPacket[BUFFER_LENGTH_BYTES + leadingBytes];
|
||||
|
||||
dataPacket[0] = PACKET_HEADER_INJECT_AUDIO;
|
||||
unsigned char *currentPacketPtr = dataPacket + 1;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
memcpy(currentPacketPtr, &_position[i], sizeof(float));
|
||||
currentPacketPtr += sizeof(float);
|
||||
}
|
||||
|
||||
*currentPacketPtr = _attenuationModifier;
|
||||
currentPacketPtr++;
|
||||
|
||||
memcpy(currentPacketPtr, &_bearing, sizeof(float));
|
||||
currentPacketPtr += sizeof(float);
|
||||
|
||||
for (int i = 0; i < _numTotalBytesAudio; i += BUFFER_LENGTH_BYTES) {
|
||||
gettimeofday(&startTime, NULL);
|
||||
|
||||
int numBytesToCopy = BUFFER_LENGTH_BYTES;
|
||||
|
||||
if (_numTotalBytesAudio - i < BUFFER_LENGTH_BYTES) {
|
||||
numBytesToCopy = _numTotalBytesAudio - i;
|
||||
memset(currentPacketPtr + numBytesToCopy, 0, BUFFER_LENGTH_BYTES - numBytesToCopy);
|
||||
}
|
||||
|
||||
memcpy(currentPacketPtr, _audioSampleArray + (i / 2), numBytesToCopy);
|
||||
|
||||
injectorSocket->send(destinationSocket, dataPacket, sizeof(dataPacket));
|
||||
|
||||
double usecToSleep = BUFFER_SEND_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&startTime));
|
||||
if (usecToSleep > 0) {
|
||||
usleep(usecToSleep);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
35
libraries/shared/src/AudioInjector.h
Normal file
35
libraries/shared/src/AudioInjector.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// AudioInjector.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Stephen Birarda on 4/23/13.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef __hifi__AudioInjector__
|
||||
#define __hifi__AudioInjector__
|
||||
|
||||
#include <iostream>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "UDPSocket.h"
|
||||
|
||||
class AudioInjector {
|
||||
public:
|
||||
AudioInjector(const char* filename);
|
||||
~AudioInjector();
|
||||
|
||||
void setPosition(float* position);
|
||||
void setBearing(float bearing) { _bearing = bearing; }
|
||||
void setAttenuationModifier(unsigned char attenuationModifier) { _attenuationModifier = attenuationModifier; }
|
||||
|
||||
void injectAudio(UDPSocket* injectorSocket, sockaddr* destinationSocket) const;
|
||||
private:
|
||||
int16_t* _audioSampleArray;
|
||||
int _numTotalBytesAudio;
|
||||
float _position[3];
|
||||
float _bearing;
|
||||
unsigned char _attenuationModifier;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__AudioInjector__) */
|
|
@ -9,32 +9,31 @@
|
|||
#ifndef __hifi__FloodFill__
|
||||
#define __hifi__FloodFill__
|
||||
|
||||
/**
|
||||
* Line scanning, iterative flood fill algorithm.
|
||||
*
|
||||
* The strategy must obey the following contract:
|
||||
*
|
||||
* There is an associated cursor that represents a position on the image.
|
||||
* The member functions 'left(C&)', 'right(C&)', 'up(C&)', and 'down(C&)'
|
||||
* move it.
|
||||
* The state of a cursor can be deferred to temporary storage (typically a
|
||||
* stack or a queue) using the 'defer(C const&)' member function.
|
||||
* Calling 'deferred(C&)' restores a cursor's state from temporary storage
|
||||
* and removes it there.
|
||||
* The 'select(C const&)' and 'process(C const&)' functions control the
|
||||
* algorithm. The former is called to determine where to go. It may be
|
||||
* called multiple times but does not have to (and should not) return
|
||||
* 'true' more than once for a pixel to be selected (will cause memory
|
||||
* overuse, otherwise). The latter will never be called for a given pixel
|
||||
* unless previously selected. It may be called multiple times, in which
|
||||
* case it should return 'true' upon successful processing and 'false'
|
||||
* when an already processed pixel has been visited.
|
||||
*
|
||||
* Note: The terms "image" and "pixel" are used for illustratory purposes
|
||||
* and mean "undirected graph with 4-connected 2D grid topology" and "node",
|
||||
* respectively.
|
||||
*
|
||||
*/
|
||||
//
|
||||
// Line scanning, iterative flood fill algorithm.
|
||||
//
|
||||
// The strategy must obey the following contract:
|
||||
//
|
||||
// There is an associated cursor that represents a position on the image.
|
||||
// The member functions 'left(C&)', 'right(C&)', 'up(C&)', and 'down(C&)'
|
||||
// move it.
|
||||
// The state of a cursor can be deferred to temporary storage (typically a
|
||||
// stack or a queue) using the 'defer(C const&)' member function.
|
||||
// Calling 'deferred(C&)' restores a cursor's state from temporary storage
|
||||
// and removes it there.
|
||||
// The 'select(C const&)' and 'process(C const&)' functions control the
|
||||
// algorithm. The former is called to determine where to go. It may be
|
||||
// called multiple times but does not have to (and should not) return
|
||||
// 'true' more than once for a pixel to be selected (will cause memory
|
||||
// overuse, otherwise). The latter will never be called for a given pixel
|
||||
// unless previously selected. It may be called multiple times, in which
|
||||
// case it should return 'true' upon successful processing and 'false'
|
||||
// when an already processed pixel has been visited.
|
||||
//
|
||||
// Note: The terms "image" and "pixel" are used for illustratory purposes
|
||||
// and mean "undirected graph with 4-connected 2D grid topology" and "node",
|
||||
// respectively.
|
||||
//
|
||||
template< class Strategy, typename Cursor >
|
||||
void floodFill(Cursor const& position,
|
||||
Strategy const& strategy = Strategy());
|
||||
|
@ -63,57 +62,39 @@ struct floodFill_impl : Strategy {
|
|||
}
|
||||
|
||||
Cursor higher, lower, h,l, i;
|
||||
bool higherFound, lowerFound, hf, lf;
|
||||
do {
|
||||
|
||||
if (! process(position)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
higher = position; higherFound = false;
|
||||
up(higher); yTest(higher, higherFound);
|
||||
lower = position; lowerFound = false;
|
||||
down(lower); yTest(lower, lowerFound);
|
||||
higher = position;
|
||||
up(higher);
|
||||
if (select(higher)) { defer(higher); }
|
||||
|
||||
lower = position;
|
||||
down(lower);
|
||||
if (select(lower)) { defer(lower); }
|
||||
|
||||
i = position, h = higher, l = lower;
|
||||
hf = higherFound, lf = lowerFound;
|
||||
do {
|
||||
right(i), right(h), right(l); yTest(h,hf); yTest(l,lf);
|
||||
|
||||
} while (selectAndProcess(i));
|
||||
right(i), right(h), right(l);
|
||||
if (select(h)) { defer(h); }
|
||||
if (select(l)) { defer(l); }
|
||||
|
||||
} while (select(i) && process(i));
|
||||
|
||||
i = position, h = higher, l = lower;
|
||||
hf = higherFound, lf = lowerFound;
|
||||
do {
|
||||
left(i); left(h); left(l); yTest(h,hf); yTest(l,lf);
|
||||
left(i); left(h); left(l);
|
||||
if (select(h)) { defer(h); }
|
||||
if (select(l)) { defer(l); }
|
||||
|
||||
} while (selectAndProcess(i));
|
||||
} while (select(i) && process(i));
|
||||
|
||||
} while (deferred(position));
|
||||
}
|
||||
|
||||
bool selectAndProcess(Cursor const& i) {
|
||||
|
||||
if (select(i)) {
|
||||
|
||||
process(i);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void yTest(Cursor const& i, bool& state) {
|
||||
|
||||
if (! select(i)) {
|
||||
|
||||
state = false;
|
||||
|
||||
} else if (! state) {
|
||||
|
||||
state = true;
|
||||
defer(i);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template< class Strategy, typename Cursor >
|
||||
|
|
|
@ -107,6 +107,18 @@ int getLocalAddress() {
|
|||
return localAddress;
|
||||
}
|
||||
|
||||
unsigned short loadBufferWithSocketInfo(char *addressBuffer, sockaddr *socket) {
|
||||
if (socket != NULL) {
|
||||
char *copyBuffer = inet_ntoa(((sockaddr_in*) socket)->sin_addr);
|
||||
memcpy(addressBuffer, copyBuffer, strlen(copyBuffer));
|
||||
return htons(((sockaddr_in*) socket)->sin_port);
|
||||
} else {
|
||||
const char* unknownAddress = "Unknown";
|
||||
memcpy(addressBuffer, unknownAddress, strlen(unknownAddress));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
UDPSocket::UDPSocket(int listeningPort) {
|
||||
init();
|
||||
// create the socket
|
||||
|
|
|
@ -36,5 +36,6 @@ int packSocket(unsigned char *packStore, in_addr_t inAddress, in_port_t networkO
|
|||
int packSocket(unsigned char *packStore, sockaddr *socketToPack);
|
||||
int unpackSocket(unsigned char *packedData, sockaddr *unpackDestSocket);
|
||||
int getLocalAddress();
|
||||
unsigned short loadBufferWithSocketInfo(char *addressBuffer, sockaddr *socket);
|
||||
|
||||
#endif /* defined(__interface__UDPSocket__) */
|
||||
|
|
|
@ -19,7 +19,7 @@ VoxelAgentData::~VoxelAgentData() {
|
|||
}
|
||||
|
||||
VoxelAgentData::VoxelAgentData(const VoxelAgentData &otherAgentData) {
|
||||
memcpy(&_bodyPosition, &otherAgentData._bodyPosition, sizeof(_bodyPosition));
|
||||
memcpy(&_position, &otherAgentData._position, sizeof(_position));
|
||||
rootMarkerNode = new MarkerNode();
|
||||
}
|
||||
|
||||
|
|
|
@ -199,7 +199,7 @@ void *distributeVoxelsToListeners(void *args) {
|
|||
stopOctal = randomTree.loadBitstreamBuffer(voxelPacketEnd,
|
||||
randomTree.rootNode,
|
||||
agentData->rootMarkerNode,
|
||||
agentData->getBodyPosition(),
|
||||
agentData->getPosition(),
|
||||
treeRoot,
|
||||
viewFrustum,
|
||||
::viewFrustumCulling,
|
||||
|
|
Loading…
Reference in a new issue