mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
5c1bd68580
17 changed files with 417 additions and 218 deletions
|
@ -5,4 +5,5 @@ project(hifi)
|
|||
add_subdirectory(space)
|
||||
add_subdirectory(domain)
|
||||
add_subdirectory(mixer)
|
||||
add_subdirectory(voxel)
|
||||
add_subdirectory(interface)
|
|
@ -10,7 +10,7 @@ project(interface)
|
|||
|
||||
if (APPLE)
|
||||
# link in required OS X frameworks and include the right GL headers
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreServices -framework Carbon")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreServices -framework Carbon -framework GLUT")
|
||||
set(GL_HEADERS "#include <GLUT/glut.h>\n#include <OpenGL/glext.h>")
|
||||
else (APPLE)
|
||||
# include the right GL headers for UNIX
|
||||
|
|
|
@ -39,6 +39,8 @@ const short JITTER_BUFFER_SAMPLES = JITTER_BUFFER_LENGTH_MSECS * (SAMPLE_RATE /
|
|||
const short NUM_AUDIO_SOURCES = 2;
|
||||
const short ECHO_SERVER_TEST = 1;
|
||||
|
||||
const int AGENT_LOOPBACK_MODIFIER = 307;
|
||||
|
||||
const char LOCALHOST_MIXER[] = "0.0.0.0";
|
||||
const char WORKCLUB_MIXER[] = "192.168.1.19";
|
||||
const char EC2_WEST_MIXER[] = "54.241.92.53";
|
||||
|
@ -116,6 +118,10 @@ int audioCallback (const void *inputBuffer,
|
|||
correctedYaw += 360;
|
||||
}
|
||||
|
||||
if (data->mixerLoopbackFlag) {
|
||||
correctedYaw = correctedYaw > 0 ? correctedYaw + AGENT_LOOPBACK_MODIFIER : correctedYaw - AGENT_LOOPBACK_MODIFIER;
|
||||
}
|
||||
|
||||
memcpy(currentPacketPtr, &correctedYaw, sizeof(float));
|
||||
currentPacketPtr += sizeof(float);
|
||||
|
||||
|
@ -261,6 +267,14 @@ void *receiveAudioViaUDP(void *args) {
|
|||
pthread_exit(0);
|
||||
}
|
||||
|
||||
void Audio::setMixerLoopbackFlag(bool newMixerLoopbackFlag) {
|
||||
audioData->mixerLoopbackFlag = newMixerLoopbackFlag;
|
||||
}
|
||||
|
||||
bool Audio::getMixerLoopbackFlag() {
|
||||
return audioData->mixerLoopbackFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize portaudio and start an audio stream.
|
||||
* Should be called at the beginning of program exection.
|
||||
|
|
|
@ -23,6 +23,9 @@ public:
|
|||
void render();
|
||||
void render(int screenWidth, int screenHeight);
|
||||
|
||||
bool getMixerLoopbackFlag();
|
||||
void setMixerLoopbackFlag(bool newMixerLoopbackFlag);
|
||||
|
||||
void getInputLoudness(float * lastLoudness, float * averageLoudness);
|
||||
void updateMixerParams(in_addr_t mixerAddress, in_port_t mixerPort);
|
||||
|
||||
|
@ -30,6 +33,7 @@ public:
|
|||
bool terminate();
|
||||
private:
|
||||
bool initialized;
|
||||
|
||||
AudioData *audioData;
|
||||
|
||||
// protects constructor so that public init method is used
|
||||
|
|
|
@ -17,6 +17,8 @@ AudioData::AudioData() {
|
|||
wasStarved = 0;
|
||||
measuredJitter = 0;
|
||||
jitterBuffer = 0;
|
||||
|
||||
mixerLoopbackFlag = false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -38,6 +38,8 @@ class AudioData {
|
|||
|
||||
float lastInputLoudness;
|
||||
float averagedInputLoudness;
|
||||
|
||||
bool mixerLoopbackFlag;
|
||||
};
|
||||
|
||||
#endif /* defined(__interface__AudioData__) */
|
||||
|
|
|
@ -55,11 +55,6 @@ float StDev::getStDev() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
float randFloat () {
|
||||
return (rand()%10000)/10000.f;
|
||||
}
|
||||
|
||||
// Return the azimuth angle in degrees between two points.
|
||||
float azimuth_to(glm::vec3 head_pos, glm::vec3 source_pos) {
|
||||
return atan2(head_pos.x - source_pos.x, head_pos.z - source_pos.z) * 180 / PI;
|
||||
|
|
|
@ -7,24 +7,25 @@
|
|||
//
|
||||
|
||||
#include "VoxelSystem.h"
|
||||
#include <AgentList.h>
|
||||
|
||||
const float MAX_Y_AXIS = 2.0;
|
||||
const float MAX_X_AXIS = 20.0;
|
||||
const float MAX_Z_AXIS = 20.0;
|
||||
const int MAX_VOXELS_PER_SYSTEM = 500000;
|
||||
|
||||
const int VERTICES_PER_VOXEL = 8;
|
||||
const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL;
|
||||
const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL;
|
||||
const int INDICES_PER_VOXEL = 3 * 12;
|
||||
|
||||
GLfloat identityVertices[] = { -1, -1, 1,
|
||||
1, -1, 1,
|
||||
1, -1, -1,
|
||||
-1, -1, -1,
|
||||
1, 1, 1,
|
||||
-1, 1, 1,
|
||||
-1, 1, -1,
|
||||
1, 1, -1 };
|
||||
const float CUBE_WIDTH = 0.025f;
|
||||
|
||||
float identityVertices[] = { -1, -1, 1,
|
||||
1, -1, 1,
|
||||
1, -1, -1,
|
||||
-1, -1, -1,
|
||||
1, 1, 1,
|
||||
-1, 1, 1,
|
||||
-1, 1, -1,
|
||||
1, 1, -1 };
|
||||
|
||||
GLubyte identityIndices[] = { 0,1,2, 0,2,3,
|
||||
0,4,1, 0,4,5,
|
||||
|
@ -33,73 +34,71 @@ GLubyte identityIndices[] = { 0,1,2, 0,2,3,
|
|||
2,3,6, 2,6,7,
|
||||
4,5,6, 4,6,7 };
|
||||
|
||||
VoxelSystem::VoxelSystem() {
|
||||
voxelsRendered = 0;
|
||||
}
|
||||
|
||||
bool onSphereShell(float radius, float scale, glm::vec3 * position) {
|
||||
float vRadius = glm::length(*position);
|
||||
return ((vRadius + scale/2.0 > radius) && (vRadius - scale/2.0 < radius));
|
||||
VoxelSystem::~VoxelSystem() {
|
||||
delete[] verticesArray;
|
||||
delete[] colorsArray;
|
||||
}
|
||||
|
||||
void VoxelSystem::parseData(void *data, int size) {
|
||||
// ignore the first char, it's a V to tell us that this is voxel data
|
||||
char *voxelDataPtr = (char *) data + 1;
|
||||
|
||||
float *position = new float[3];
|
||||
char *color = new char[3];
|
||||
|
||||
// get pointers to position of last append of data
|
||||
GLfloat *parseVerticesPtr = lastAddPointer;
|
||||
GLubyte *parseColorsPtr = colorsArray + (lastAddPointer - verticesArray);
|
||||
|
||||
int voxelsInData = 0;
|
||||
|
||||
// pull voxels out of the received data and put them into our internal memory structure
|
||||
while ((voxelDataPtr - (char *) data) < size) {
|
||||
|
||||
memcpy(position, voxelDataPtr, 3 * sizeof(float));
|
||||
voxelDataPtr += 3 * sizeof(float);
|
||||
memcpy(color, voxelDataPtr, 3);
|
||||
voxelDataPtr += 3;
|
||||
|
||||
for (int v = 0; v < VERTEX_POINTS_PER_VOXEL; v++) {
|
||||
parseVerticesPtr[v] = position[v % 3] + (identityVertices[v] * CUBE_WIDTH);
|
||||
}
|
||||
|
||||
parseVerticesPtr += VERTEX_POINTS_PER_VOXEL;
|
||||
|
||||
for (int c = 0; c < COLOR_VALUES_PER_VOXEL; c++) {
|
||||
parseColorsPtr[c] = color[c % 3];
|
||||
}
|
||||
|
||||
parseColorsPtr += COLOR_VALUES_PER_VOXEL;
|
||||
|
||||
voxelsInData++;
|
||||
}
|
||||
|
||||
// increase the lastAddPointer to the new spot, increase the number of rendered voxels
|
||||
lastAddPointer = parseVerticesPtr;
|
||||
voxelsRendered += voxelsInData;
|
||||
}
|
||||
|
||||
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() {
|
||||
root = new Voxel;
|
||||
}
|
||||
|
||||
float randomFloat(float maximumValue) {
|
||||
return ((float) rand() / ((float) RAND_MAX / maximumValue));
|
||||
}
|
||||
|
||||
void VoxelSystem::init(int numberOfRandomVoxels) {
|
||||
// create the arrays needed to pass to glDrawElements later
|
||||
// position / color are random for now
|
||||
// prep the data structures for incoming voxel data
|
||||
lastDrawPointer = lastAddPointer = verticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM];
|
||||
colorsArray = new GLubyte[COLOR_VALUES_PER_VOXEL * MAX_VOXELS_PER_SYSTEM];
|
||||
|
||||
voxelsRendered = numberOfRandomVoxels;
|
||||
|
||||
// there are 3 points for each vertices, 24 vertices in each cube
|
||||
GLfloat *verticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * numberOfRandomVoxels];
|
||||
GLuint *indicesArray = new GLuint[INDICES_PER_VOXEL * MAX_VOXELS_PER_SYSTEM];
|
||||
|
||||
// we need a color for each vertex in each voxel
|
||||
GLfloat *colorsArray = new GLfloat[COLOR_VALUES_PER_VOXEL * numberOfRandomVoxels];
|
||||
|
||||
// there are 12 triangles in each cube, with three indices for each triangle
|
||||
GLuint *indicesArray = new GLuint[INDICES_PER_VOXEL * numberOfRandomVoxels];
|
||||
|
||||
// new seed based on time now so voxels are different each time
|
||||
srand((unsigned)time(0));
|
||||
|
||||
for (int n = 0; n < numberOfRandomVoxels; n++) {
|
||||
// pick a random point for the center of the cube
|
||||
const float DEATH_STAR_RADIUS = 4.0;
|
||||
const float MAX_CUBE = 0.05;
|
||||
float azimuth = randFloat()*2*PI;
|
||||
float altitude = randFloat()*PI - PI/2;
|
||||
float radius = DEATH_STAR_RADIUS;
|
||||
float thisScale = MAX_CUBE*1/(float)(rand()%8 + 1);
|
||||
float radius_twiddle = (DEATH_STAR_RADIUS/100)*powf(2, (float)(rand()%8));
|
||||
radius += radius_twiddle + (randFloat()*DEATH_STAR_RADIUS/12 - DEATH_STAR_RADIUS/24);
|
||||
glm::vec3 position = glm::vec3(
|
||||
radius * cosf(azimuth) * cosf(altitude),
|
||||
radius * sinf(azimuth) * cosf(altitude),
|
||||
radius * sinf(altitude)
|
||||
);
|
||||
|
||||
// fill the vertices array, and scale the voxels
|
||||
GLfloat *currentVerticesPos = verticesArray + (n * VERTEX_POINTS_PER_VOXEL);
|
||||
for (int v = 0; v < VERTEX_POINTS_PER_VOXEL; v++) {
|
||||
currentVerticesPos[v] = position[v % 3] + (identityVertices[v] * thisScale);
|
||||
}
|
||||
|
||||
// fill the colors array
|
||||
const float MIN_BRIGHTNESS = 0.25;
|
||||
GLfloat *currentColorPos = colorsArray + (n * COLOR_VALUES_PER_VOXEL);
|
||||
float voxelR = MIN_BRIGHTNESS + randomFloat(1)*(1.0 - MIN_BRIGHTNESS);
|
||||
float voxelG = voxelR;
|
||||
float voxelB = voxelR;
|
||||
|
||||
for (int c = 0; c < VERTICES_PER_VOXEL; c++) {
|
||||
currentColorPos[0 + (c * 3)] = voxelR;
|
||||
currentColorPos[1 + (c * 3)] = voxelG;
|
||||
currentColorPos[2 + (c * 3)] = voxelB;
|
||||
}
|
||||
|
||||
// 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++) {
|
||||
// fill the indices array
|
||||
int voxelIndexOffset = n * INDICES_PER_VOXEL;
|
||||
GLuint *currentIndicesPos = indicesArray + voxelIndexOffset;
|
||||
|
@ -114,135 +113,51 @@ void VoxelSystem::init(int numberOfRandomVoxels) {
|
|||
// VBO for the verticesArray
|
||||
glGenBuffers(1, &vboVerticesID);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID);
|
||||
glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * numberOfRandomVoxels, verticesArray, GL_STATIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW);
|
||||
|
||||
// VBO for colorsArray
|
||||
glGenBuffers(1, &vboColorsID);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboColorsID);
|
||||
glBufferData(GL_ARRAY_BUFFER, COLOR_VALUES_PER_VOXEL * sizeof(GLfloat) * numberOfRandomVoxels, colorsArray, GL_STATIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, COLOR_VALUES_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, numberOfRandomVoxels * INDICES_PER_VOXEL * sizeof(GLuint), indicesArray, GL_STATIC_DRAW);
|
||||
|
||||
// delete the verticesArray, indicesArray
|
||||
delete[] verticesArray;
|
||||
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[] indicesArray;
|
||||
delete[] colorsArray;
|
||||
}
|
||||
|
||||
//
|
||||
// Recursively initialize the voxel tree
|
||||
//
|
||||
int VoxelSystem::initVoxels(Voxel * voxel, float scale, glm::vec3 * position) {
|
||||
glm::vec3 averageColor(0,0,0);
|
||||
int childrenCreated = 0;
|
||||
int newVoxels = 0;
|
||||
if (voxel == NULL) voxel = root;
|
||||
averageColor[0] = averageColor[1] = averageColor[2] = 0.0;
|
||||
|
||||
const float RADIUS = 3.9;
|
||||
|
||||
//
|
||||
// First, randomly decide whether to stop here without recursing for children
|
||||
//
|
||||
if (onSphereShell(RADIUS, scale, position) && (scale < 0.25) && (randFloat() < 0.01))
|
||||
{
|
||||
voxel->color.x = 0.1;
|
||||
voxel->color.y = 0.5 + randFloat()*0.5;
|
||||
voxel->color.z = 0.1;
|
||||
for (unsigned char i = 0; i < NUM_CHILDREN; i++) voxel->children[i] = NULL;
|
||||
return 0;
|
||||
} else {
|
||||
// Decide whether to make kids, recurse into them
|
||||
for (unsigned char i = 0; i < NUM_CHILDREN; i++) {
|
||||
if (scale > 0.01) {
|
||||
glm::vec3 shift(scale/2.0*((i&4)>>2)-scale/4.0,
|
||||
scale/2.0*((i&2)>>1)-scale/4.0,
|
||||
scale/2.0*(i&1)-scale/4.0);
|
||||
*position += shift;
|
||||
// Test to see whether the child is also on edge of sphere
|
||||
if (onSphereShell(RADIUS, scale/2.0, position)) {
|
||||
voxel->children[i] = new Voxel;
|
||||
newVoxels++;
|
||||
childrenCreated++;
|
||||
newVoxels += initVoxels(voxel->children[i], scale/2.0, position);
|
||||
averageColor += voxel->children[i]->color;
|
||||
} else voxel->children[i] = NULL;
|
||||
*position -= shift;
|
||||
} else {
|
||||
// No child made: Set pointer to null, nothing to see here.
|
||||
voxel->children[i] = NULL;
|
||||
}
|
||||
}
|
||||
if (childrenCreated > 0) {
|
||||
// If there were children created, the color of this voxel node is average of children
|
||||
averageColor *= 1.0/childrenCreated;
|
||||
voxel->color = averageColor;
|
||||
return newVoxels;
|
||||
} else {
|
||||
// Tested and didn't make any children, so choose my color as a leaf, return
|
||||
voxel->color.x = voxel->color.y = voxel->color.z = 0.5 + randFloat()*0.5;
|
||||
for (unsigned char i = 0; i < NUM_CHILDREN; i++) voxel->children[i] = NULL;
|
||||
return 0;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// The Render Discard is the ratio of the size of the voxel to the distance from the camera
|
||||
// at which the voxel will no longer be shown. Smaller = show more detail.
|
||||
//
|
||||
|
||||
const float RENDER_DISCARD = 0.04; //0.01;
|
||||
|
||||
//
|
||||
// Returns the total number of voxels actually rendered
|
||||
//
|
||||
int VoxelSystem::render(Voxel * voxel, float scale, glm::vec3 * distance) {
|
||||
// If null passed in, start at root
|
||||
if (voxel == NULL) voxel = root;
|
||||
unsigned char i;
|
||||
bool renderedChildren = false;
|
||||
int vRendered = 0;
|
||||
// Recursively render children
|
||||
for (i = 0; i < NUM_CHILDREN; i++) {
|
||||
glm::vec3 shift(scale/2.0*((i&4)>>2)-scale/4.0,
|
||||
scale/2.0*((i&2)>>1)-scale/4.0,
|
||||
scale/2.0*(i&1)-scale/4.0);
|
||||
if ((voxel->children[i] != NULL) && (scale / glm::length(*distance) > RENDER_DISCARD)) {
|
||||
glTranslatef(shift.x, shift.y, shift.z);
|
||||
*distance += shift;
|
||||
vRendered += render(voxel->children[i], scale/2.0, distance);
|
||||
*distance -= shift;
|
||||
glTranslatef(-shift.x, -shift.y, -shift.z);
|
||||
renderedChildren = true;
|
||||
}
|
||||
}
|
||||
// Render this voxel if the children were not rendered
|
||||
if (!renderedChildren)
|
||||
{
|
||||
// This is the place where we need to copy this data to a VBO to make this FAST
|
||||
glColor4f(voxel->color.x, voxel->color.y, voxel->color.z, 1.0);
|
||||
glutSolidCube(scale);
|
||||
vRendered++;
|
||||
}
|
||||
return vRendered;
|
||||
}
|
||||
|
||||
void VoxelSystem::render() {
|
||||
// check if there are new voxels to draw
|
||||
int vertexValuesToDraw = lastAddPointer - lastDrawPointer;
|
||||
|
||||
if (vertexValuesToDraw > 0) {
|
||||
// calculate the offset into each VBO, in vertex point values
|
||||
int vertexBufferOffset = lastDrawPointer - verticesArray;
|
||||
|
||||
// bind the vertices VBO, copy in new data
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, vertexBufferOffset * sizeof(float), vertexValuesToDraw * sizeof(float), lastDrawPointer);
|
||||
|
||||
// bind the colors VBO, copy in new data
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboColorsID);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, vertexBufferOffset * sizeof(GLubyte), vertexValuesToDraw * sizeof(GLubyte), (colorsArray + (lastDrawPointer - verticesArray)));
|
||||
|
||||
// increment the lastDrawPointer to the lastAddPointer value used for this draw
|
||||
lastDrawPointer += vertexValuesToDraw;
|
||||
}
|
||||
|
||||
// tell OpenGL where to find vertex and color information
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID);
|
||||
glVertexPointer(3, GL_FLOAT, 0, 0);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vboColorsID);
|
||||
glColorPointer(3, GL_FLOAT, 0, 0);
|
||||
glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0);
|
||||
|
||||
glNormal3f(0, 1, 0);
|
||||
|
||||
|
|
|
@ -9,11 +9,13 @@
|
|||
#ifndef __interface__Cube__
|
||||
#define __interface__Cube__
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
#include <glm/glm.hpp>
|
||||
#include <iostream>
|
||||
#include <UDPSocket.h>
|
||||
#include <AgentData.h>
|
||||
#include "Util.h"
|
||||
#include "world.h"
|
||||
#include "InterfaceConfig.h"
|
||||
#include <iostream>
|
||||
|
||||
const int NUM_CHILDREN = 8;
|
||||
|
||||
|
@ -22,19 +24,28 @@ struct Voxel {
|
|||
Voxel * children[NUM_CHILDREN];
|
||||
};
|
||||
|
||||
class VoxelSystem {
|
||||
class VoxelSystem : public AgentData {
|
||||
public:
|
||||
VoxelSystem();
|
||||
~VoxelSystem();
|
||||
|
||||
void parseData(void *data, int size);
|
||||
VoxelSystem* clone() const;
|
||||
|
||||
void init();
|
||||
void simulate(float deltaTime);
|
||||
int render(Voxel * voxel, float scale, glm::vec3 * distance);
|
||||
void render();
|
||||
void init();
|
||||
void init(int numberOfRandomVoxels);
|
||||
int initVoxels(Voxel * root, float scale, glm::vec3 * position);
|
||||
void setVoxelsRendered(int v) {voxelsRendered = v;};
|
||||
int getVoxelsRendered() {return voxelsRendered;};
|
||||
Voxel * root;
|
||||
private:
|
||||
int voxelsRendered;
|
||||
GLfloat *verticesArray;
|
||||
GLubyte *colorsArray;
|
||||
GLfloat *lastAddPointer;
|
||||
GLfloat *lastDrawPointer;
|
||||
GLuint vboVerticesID;
|
||||
GLuint vboColorsID;
|
||||
GLuint vboIndicesID;
|
||||
|
|
|
@ -319,8 +319,7 @@ void initDisplay(void)
|
|||
|
||||
void init(void)
|
||||
{
|
||||
// Number of voxels to create
|
||||
voxels.init(100000);
|
||||
voxels.init();
|
||||
|
||||
myHead.setRenderYaw(start_yaw);
|
||||
|
||||
|
@ -333,11 +332,13 @@ void init(void)
|
|||
field = Field();
|
||||
printf( "Field Initialized.\n" );
|
||||
|
||||
if (noise_on)
|
||||
{
|
||||
if (noise_on) {
|
||||
myHead.setNoise(noise);
|
||||
}
|
||||
|
||||
char output[] = "I";
|
||||
char address[] = "10.0.0.10";
|
||||
agentList.getAgentSocket().send(address, 40106, output, 1);
|
||||
|
||||
|
||||
#ifdef MARKER_CAPTURE
|
||||
|
@ -719,7 +720,12 @@ void key(unsigned char k, int x, int y)
|
|||
}
|
||||
|
||||
}
|
||||
if (k == 'h') display_head = !display_head;
|
||||
|
||||
if (k == 'h') {
|
||||
display_head = !display_head;
|
||||
audio.setMixerLoopbackFlag(display_head);
|
||||
}
|
||||
|
||||
if (k == 'm') head_mirror = !head_mirror;
|
||||
|
||||
if (k == 'f') display_field = !display_field;
|
||||
|
@ -751,7 +757,7 @@ void key(unsigned char k, int x, int y)
|
|||
// Receive packets from other agents/servers and decide what to do with them!
|
||||
//
|
||||
void *networkReceive(void *args)
|
||||
{
|
||||
{
|
||||
sockaddr senderAddress;
|
||||
ssize_t bytesReceived;
|
||||
char *incomingPacket = new char[MAX_PACKET_SIZE];
|
||||
|
@ -761,11 +767,13 @@ void *networkReceive(void *args)
|
|||
packetcount++;
|
||||
bytescount += bytesReceived;
|
||||
|
||||
if (incomingPacket[0] != 't') {
|
||||
// Pass everything but transmitter data to the agent list
|
||||
agentList.processAgentData(&senderAddress, incomingPacket, bytesReceived);
|
||||
if (incomingPacket[0] == 't') {
|
||||
// Pass everything but transmitter data to the agent list
|
||||
myHead.hand->processTransmitterData(incomingPacket, bytesReceived);
|
||||
} else if (incomingPacket[0] == 'V') {
|
||||
voxels.parseData(incomingPacket, bytesReceived);
|
||||
} else {
|
||||
myHead.hand->processTransmitterData(incomingPacket, bytesReceived);
|
||||
agentList.processAgentData(&senderAddress, incomingPacket, bytesReceived);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -874,6 +882,12 @@ void audioMixerUpdate(in_addr_t newMixerAddress, in_port_t newMixerPort) {
|
|||
audio.updateMixerParams(newMixerAddress, newMixerPort);
|
||||
}
|
||||
|
||||
void voxelServerAddCallback(sockaddr *voxelServerAddress) {
|
||||
char voxelAsk[] = "I";
|
||||
printf("Asking VS for data!\n");
|
||||
agentList.getAgentSocket().send(voxelServerAddress, voxelAsk, 1);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
struct ifaddrs * ifAddrStruct=NULL;
|
||||
|
@ -929,12 +943,10 @@ int main(int argc, char** argv)
|
|||
// the callback for our instance of AgentList is attachNewHeadToAgent
|
||||
agentList.linkedDataCreateCallback = &attachNewHeadToAgent;
|
||||
agentList.audioMixerSocketUpdate = &audioMixerUpdate;
|
||||
agentList.voxelServerAddCallback = &voxelServerAddCallback;
|
||||
|
||||
// start the thread which checks for silent agents
|
||||
agentList.startSilentAgentRemovalThread();
|
||||
|
||||
// create thread for receipt of data via UDP
|
||||
pthread_create(&networkReceiveThread, NULL, networkReceive, NULL);
|
||||
|
||||
glutInit(&argc, argv);
|
||||
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
|
||||
|
@ -958,6 +970,9 @@ int main(int argc, char** argv)
|
|||
|
||||
init();
|
||||
|
||||
// create thread for receipt of data via UDP
|
||||
pthread_create(&networkReceiveThread, NULL, networkReceive, NULL);
|
||||
|
||||
printf( "Init() complete.\n" );
|
||||
|
||||
glutTimerFunc(1000, Timer, 0);
|
||||
|
|
|
@ -37,12 +37,23 @@ const long MIN_SAMPLE_VALUE = std::numeric_limits<int16_t>::min();
|
|||
const float DISTANCE_RATIO = 3.0/4.2;
|
||||
const int PHASE_DELAY_AT_90 = 20;
|
||||
|
||||
const int AGENT_LOOPBACK_MODIFIER = 307;
|
||||
|
||||
char DOMAIN_HOSTNAME[] = "highfidelity.below92.com";
|
||||
char DOMAIN_IP[100] = ""; // IP Address will be re-set by lookup on startup
|
||||
const int DOMAINSERVER_PORT = 40102;
|
||||
|
||||
AgentList agentList(MIXER_LISTEN_PORT);
|
||||
|
||||
void plateauAdditionOfSamples(int16_t &mixSample, int16_t sampleToAdd) {
|
||||
long sumSample = sampleToAdd + mixSample;
|
||||
|
||||
long normalizedSample = std::min(MAX_SAMPLE_VALUE, sumSample);
|
||||
normalizedSample = std::max(MIN_SAMPLE_VALUE, sumSample);
|
||||
|
||||
mixSample = normalizedSample;
|
||||
}
|
||||
|
||||
void *sendBuffer(void *args)
|
||||
{
|
||||
int sentBytes;
|
||||
|
@ -80,11 +91,23 @@ void *sendBuffer(void *args)
|
|||
for (int i = 0; i < agentList.getAgents().size(); i++) {
|
||||
Agent *agent = &agentList.getAgents()[i];
|
||||
|
||||
AudioRingBuffer *agentRingBuffer = (AudioRingBuffer *) agent->getLinkedData();
|
||||
float agentBearing = agentRingBuffer->getBearing();
|
||||
bool agentWantsLoopback = false;
|
||||
|
||||
if (agentBearing > 180 || agentBearing < -180) {
|
||||
// we were passed an invalid bearing because this agent wants loopback (pressed the H key)
|
||||
agentWantsLoopback = true;
|
||||
|
||||
// correct the bearing
|
||||
agentBearing = agentBearing > 0 ? agentBearing - AGENT_LOOPBACK_MODIFIER : agentBearing + AGENT_LOOPBACK_MODIFIER;
|
||||
}
|
||||
|
||||
int16_t clientMix[BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 2] = {};
|
||||
|
||||
|
||||
for (int j = 0; j < agentList.getAgents().size(); j++) {
|
||||
if (i != j) {
|
||||
AudioRingBuffer *agentRingBuffer = (AudioRingBuffer *) agent->getLinkedData();
|
||||
if (i != j || ( i == j && agentWantsLoopback)) {
|
||||
AudioRingBuffer *otherAgentBuffer = (AudioRingBuffer *)agentList.getAgents()[j].getLinkedData();
|
||||
|
||||
float *agentPosition = agentRingBuffer->getPosition();
|
||||
|
@ -109,7 +132,9 @@ void *sendBuffer(void *args)
|
|||
float triangleAngle = atan2f(fabsf(agentPosition[2] - otherAgentPosition[2]), fabsf(agentPosition[0] - otherAgentPosition[0])) * (180 / M_PI);
|
||||
float angleToSource;
|
||||
|
||||
float agentBearing = agentRingBuffer->getBearing();
|
||||
if (agentWantsLoopback) {
|
||||
|
||||
}
|
||||
|
||||
// find the angle we need for calculation based on the orientation of the triangle
|
||||
if (otherAgentPosition[0] > agentPosition[0]) {
|
||||
|
@ -144,20 +169,21 @@ void *sendBuffer(void *args)
|
|||
? 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] * distanceCoeffs[lowAgentIndex][highAgentIndex];
|
||||
delayedChannel[s] = earlierSample;
|
||||
plateauAdditionOfSamples(delayedChannel[s], earlierSample);
|
||||
}
|
||||
|
||||
int16_t currentSample = (otherAgentBuffer->getNextOutput()[s] * distanceCoeffs[lowAgentIndex][highAgentIndex]);
|
||||
goodChannel[s] = currentSample;
|
||||
plateauAdditionOfSamples(goodChannel[s], currentSample);
|
||||
|
||||
if (s + numSamplesDelay < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) {
|
||||
delayedChannel[s + numSamplesDelay] = currentSample;
|
||||
plateauAdditionOfSamples(delayedChannel[s + numSamplesDelay], currentSample);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -228,10 +254,6 @@ int main(int argc, const char * argv[])
|
|||
|
||||
agentList.startSilentAgentRemovalThread();
|
||||
|
||||
// setup the agentSocket to report to domain server
|
||||
pthread_t reportAliveThread;
|
||||
pthread_create(&reportAliveThread, NULL, reportAliveToDS, NULL);
|
||||
|
||||
// Lookup the IP address of things we have hostnames
|
||||
if (atoi(DOMAIN_IP) == 0) {
|
||||
struct hostent* pHostInfo;
|
||||
|
@ -247,6 +269,10 @@ int main(int argc, const char * argv[])
|
|||
} else {
|
||||
printf("Using static domainserver IP: %s\n", DOMAIN_IP);
|
||||
}
|
||||
|
||||
// setup the agentSocket to report to domain server
|
||||
pthread_t reportAliveThread;
|
||||
pthread_create(&reportAliveThread, NULL, reportAliveToDS, NULL);
|
||||
|
||||
unsigned char *packetData = new unsigned char[MAX_PACKET_SIZE];
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include <pthread.h>
|
||||
#include "SharedUtil.h"
|
||||
|
||||
const char * SOLO_AGENT_TYPES_STRING = "M";
|
||||
const char * SOLO_AGENT_TYPES_STRING = "MV";
|
||||
|
||||
bool stopAgentRemovalThread = false;
|
||||
pthread_mutex_t vectorChangeMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
@ -19,11 +19,13 @@ pthread_mutex_t vectorChangeMutex = PTHREAD_MUTEX_INITIALIZER;
|
|||
AgentList::AgentList() : agentSocket(AGENT_SOCKET_LISTEN_PORT) {
|
||||
linkedDataCreateCallback = NULL;
|
||||
audioMixerSocketUpdate = NULL;
|
||||
voxelServerAddCallback = NULL;
|
||||
}
|
||||
|
||||
AgentList::AgentList(int socketListenPort) : agentSocket(socketListenPort) {
|
||||
linkedDataCreateCallback = NULL;
|
||||
audioMixerSocketUpdate = NULL;
|
||||
voxelServerAddCallback = NULL;
|
||||
}
|
||||
|
||||
AgentList::~AgentList() {
|
||||
|
@ -151,6 +153,8 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket,
|
|||
// to use the local socket information the domain server gave us
|
||||
sockaddr_in *localSocketIn = (sockaddr_in *)localSocket;
|
||||
audioMixerSocketUpdate(localSocketIn->sin_addr.s_addr, localSocketIn->sin_port);
|
||||
} else if (newAgent.getType() == 'V' && voxelServerAddCallback != NULL) {
|
||||
voxelServerAddCallback(localSocket);
|
||||
}
|
||||
|
||||
std::cout << "Added agent - " << &newAgent << "\n";
|
||||
|
@ -162,7 +166,7 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket,
|
|||
return true;
|
||||
} else {
|
||||
|
||||
if (agent->getType() == 'M') {
|
||||
if (agent->getType() == 'M' || agent->getType() == 'V') {
|
||||
// until the Audio class also uses our agentList, we need to update
|
||||
// the lastRecvTimeUsecs for the audio mixer so it doesn't get killed and re-added continously
|
||||
agent->setLastRecvTimeUsecs(usecTimestampNow());
|
||||
|
|
|
@ -27,6 +27,7 @@ class AgentList {
|
|||
|
||||
void(*linkedDataCreateCallback)(Agent *);
|
||||
void(*audioMixerSocketUpdate)(in_addr_t, in_port_t);
|
||||
void(*voxelServerAddCallback)(sockaddr *);
|
||||
|
||||
std::vector<Agent>& getAgents();
|
||||
UDPSocket& getAgentSocket();
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
//
|
||||
|
||||
#include "SharedUtil.h"
|
||||
#include <cstdlib>
|
||||
|
||||
double usecTimestamp(timeval *time) {
|
||||
return (time->tv_sec * 1000000.0 + time->tv_usec);
|
||||
|
@ -16,4 +17,9 @@ double usecTimestampNow() {
|
|||
timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
return (now.tv_sec * 1000000.0 + now.tv_usec);
|
||||
}
|
||||
|
||||
|
||||
float randFloat () {
|
||||
return (rand()%10000)/10000.f;
|
||||
}
|
|
@ -14,5 +14,6 @@
|
|||
|
||||
double usecTimestamp(timeval *time);
|
||||
double usecTimestampNow();
|
||||
float randFloat();
|
||||
|
||||
#endif /* defined(__hifi__SharedUtil__) */
|
||||
|
|
10
voxel/CMakeLists.txt
Normal file
10
voxel/CMakeLists.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
project(voxel)
|
||||
|
||||
file(GLOB VOXEL_SRCS src/*.cpp src/*.h)
|
||||
|
||||
add_executable(voxel ${VOXEL_SRCS})
|
||||
|
||||
include(../LinkHifiShared.cmake)
|
||||
link_hifi_shared_library(voxel)
|
192
voxel/src/main.cpp
Normal file
192
voxel/src/main.cpp
Normal file
|
@ -0,0 +1,192 @@
|
|||
//
|
||||
// main.cpp
|
||||
// Voxel Server
|
||||
//
|
||||
// Created by Stephen Birara on 03/06/13.
|
||||
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include <AgentList.h>
|
||||
#include <sys/time.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <cmath>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
const int VOXEL_LISTEN_PORT = 40106;
|
||||
|
||||
const int NUMBER_OF_VOXELS = 250000;
|
||||
|
||||
const float MAX_UNIT_ANY_AXIS = 20.0f;
|
||||
|
||||
const int VERTICES_PER_VOXEL = 8;
|
||||
const int VERTEX_POINTS_PER_VOXEL = 3 * VERTICES_PER_VOXEL;
|
||||
const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL;
|
||||
|
||||
const int VOXEL_SIZE_BYTES = 3 + (3 * sizeof(float));
|
||||
const int VOXELS_PER_PACKET = (MAX_PACKET_SIZE - 1) / VOXEL_SIZE_BYTES;
|
||||
|
||||
const int MIN_BRIGHTNESS = 64;
|
||||
const float DEATH_STAR_RADIUS = 4.0;
|
||||
const float MAX_CUBE = 0.05;
|
||||
|
||||
char DOMAIN_HOSTNAME[] = "highfidelity.below92.com";
|
||||
char DOMAIN_IP[100] = "192.168.1.47"; // IP Address will be re-set by lookup on startup
|
||||
const int DOMAINSERVER_PORT = 40102;
|
||||
|
||||
AgentList agentList(VOXEL_LISTEN_PORT);
|
||||
in_addr_t localAddress;
|
||||
|
||||
unsigned char randomColorValue() {
|
||||
return MIN_BRIGHTNESS + (rand() % (255 - MIN_BRIGHTNESS));
|
||||
}
|
||||
|
||||
void *reportAliveToDS(void *args) {
|
||||
|
||||
timeval lastSend;
|
||||
unsigned char output[7];
|
||||
|
||||
while (true) {
|
||||
gettimeofday(&lastSend, NULL);
|
||||
|
||||
*output = 'V';
|
||||
packSocket(output + 1, localAddress, htons(VOXEL_LISTEN_PORT));
|
||||
agentList.getAgentSocket().send(DOMAIN_IP, DOMAINSERVER_PORT, output, 7);
|
||||
|
||||
double usecToSleep = 1000000 - (usecTimestampNow() - usecTimestamp(&lastSend));
|
||||
|
||||
if (usecToSleep > 0) {
|
||||
usleep(usecToSleep);
|
||||
} else {
|
||||
std::cout << "No sleep required!";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, const char * argv[])
|
||||
{
|
||||
// get the local address of the voxel server
|
||||
struct ifaddrs * ifAddrStruct=NULL;
|
||||
struct ifaddrs * ifa=NULL;
|
||||
|
||||
getifaddrs(&ifAddrStruct);
|
||||
|
||||
for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) {
|
||||
if (ifa ->ifa_addr->sa_family==AF_INET) { // check it is IP4
|
||||
// is a valid IP4 Address
|
||||
localAddress = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
|
||||
}
|
||||
}
|
||||
|
||||
// Lookup the IP address of things we have hostnames
|
||||
if (atoi(DOMAIN_IP) == 0) {
|
||||
struct hostent* pHostInfo;
|
||||
if ((pHostInfo = gethostbyname(DOMAIN_HOSTNAME)) != NULL) {
|
||||
sockaddr_in tempAddress;
|
||||
memcpy(&tempAddress.sin_addr, pHostInfo->h_addr_list[0], pHostInfo->h_length);
|
||||
strcpy(DOMAIN_IP, inet_ntoa(tempAddress.sin_addr));
|
||||
printf("Domain server %s: %s\n", DOMAIN_HOSTNAME, DOMAIN_IP);
|
||||
|
||||
} else {
|
||||
printf("Failed lookup domainserver\n");
|
||||
}
|
||||
} else {
|
||||
printf("Using static domainserver IP: %s\n", DOMAIN_IP);
|
||||
}
|
||||
|
||||
// setup the agentSocket to report to domain server
|
||||
pthread_t reportAliveThread;
|
||||
pthread_create(&reportAliveThread, NULL, reportAliveToDS, NULL);
|
||||
|
||||
// new seed based on time now so voxels are different each time
|
||||
srand((unsigned)time(0));
|
||||
|
||||
// create the vertex and color arrays to send back to requesting clients
|
||||
|
||||
// setup data structures for our array of points and array of colors
|
||||
float *pointsArray = new float[NUMBER_OF_VOXELS * 3];
|
||||
char *colorsArray = new char[NUMBER_OF_VOXELS * 3];
|
||||
|
||||
for (int n = 0; n < NUMBER_OF_VOXELS; n++) {
|
||||
|
||||
// pick a random point for the center of the cube
|
||||
float azimuth = randFloat() * 2 * M_PI;
|
||||
float altitude = randFloat() * M_PI - M_PI/2;
|
||||
float radius = DEATH_STAR_RADIUS;
|
||||
float radius_twiddle = (DEATH_STAR_RADIUS/100) * powf(2, (float)(rand()%8));
|
||||
float thisScale = MAX_CUBE * 1 / (float)(rand() % 8 + 1);
|
||||
radius += radius_twiddle + (randFloat() * DEATH_STAR_RADIUS/12 - DEATH_STAR_RADIUS / 24);
|
||||
|
||||
// fill the vertices array
|
||||
float *currentPointsPos = pointsArray + (n * 3);
|
||||
currentPointsPos[0] = radius * cosf(azimuth) * cosf(altitude);
|
||||
currentPointsPos[1] = radius * sinf(azimuth) * cosf(altitude);
|
||||
currentPointsPos[2] = radius * sinf(altitude);
|
||||
|
||||
// fill the colors array
|
||||
char *currentColorPos = colorsArray + (n * 3);
|
||||
currentColorPos[0] = randomColorValue();
|
||||
currentColorPos[1] = randomColorValue();
|
||||
currentColorPos[2] = randomColorValue();
|
||||
}
|
||||
|
||||
// we need space for each voxel and for the 'V' characters at the beginning of each voxel packet
|
||||
int voxelDataBytes = VOXEL_SIZE_BYTES * NUMBER_OF_VOXELS + ceil(NUMBER_OF_VOXELS / VOXELS_PER_PACKET);
|
||||
char *voxelData = new char[voxelDataBytes];
|
||||
|
||||
// setup the interleaved voxelData packet
|
||||
for (int v = 0; v < NUMBER_OF_VOXELS; v++) {
|
||||
char *startPointer = voxelData + (v * VOXEL_SIZE_BYTES) + ((v / VOXELS_PER_PACKET) + 1);
|
||||
|
||||
// if this is the start of a voxel packet we need to prepend with a 'V'
|
||||
if (v % VOXELS_PER_PACKET == 0) {
|
||||
*(startPointer - 1) = 'V';
|
||||
}
|
||||
|
||||
memcpy(startPointer, pointsArray + (v * 3), sizeof(float) * 3);
|
||||
memcpy(startPointer + (3 * sizeof(float)), colorsArray + (v * 3), 3);
|
||||
}
|
||||
|
||||
// delete the pointsArray and colorsArray that we no longer need
|
||||
delete[] pointsArray;
|
||||
delete[] colorsArray;
|
||||
|
||||
sockaddr_in agentPublicAddress;
|
||||
|
||||
char *packetData = new char[MAX_PACKET_SIZE];
|
||||
ssize_t receivedBytes;
|
||||
|
||||
int sentVoxels = 0;
|
||||
|
||||
// loop to send to agents requesting data
|
||||
while (true) {
|
||||
if (agentList.getAgentSocket().receive((sockaddr *)&agentPublicAddress, packetData, &receivedBytes)) {
|
||||
if (packetData[0] == 'I') {
|
||||
printf("Sending voxels to agent at address %s\n", inet_ntoa(agentPublicAddress.sin_addr));
|
||||
|
||||
// send the agent all voxels for now
|
||||
// each packet has VOXELS_PER_PACKET, unless it's the last
|
||||
while (sentVoxels != NUMBER_OF_VOXELS) {
|
||||
int voxelsToSend = std::min(VOXELS_PER_PACKET, NUMBER_OF_VOXELS - sentVoxels);
|
||||
|
||||
agentList.getAgentSocket().send((sockaddr *)&agentPublicAddress,
|
||||
voxelData + (sentVoxels * VOXEL_SIZE_BYTES) + ((sentVoxels / VOXELS_PER_PACKET)),
|
||||
(voxelsToSend * VOXEL_SIZE_BYTES + 1));
|
||||
|
||||
// sleep for 500 microseconds to not overload send and have lost packets
|
||||
usleep(500);
|
||||
|
||||
sentVoxels += voxelsToSend;
|
||||
}
|
||||
|
||||
printf("Sent %d voxels to agent.\n", sentVoxels);
|
||||
sentVoxels = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pthread_join(reportAliveThread, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue