mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-07-23 14:14:28 +02:00
Merge branch 'master' of https://github.com/worklist/hifi
Conflicts: interface/src/main.cpp
This commit is contained in:
commit
43b5e9430f
12 changed files with 408 additions and 127 deletions
|
@ -139,6 +139,7 @@ Avatar::Avatar(bool isMine) {
|
||||||
_interactingOther = NULL;
|
_interactingOther = NULL;
|
||||||
//_canReachToOtherAvatar = false;
|
//_canReachToOtherAvatar = false;
|
||||||
_handHoldingPosition = glm::vec3( 0.0, 0.0, 0.0 );
|
_handHoldingPosition = glm::vec3( 0.0, 0.0, 0.0 );
|
||||||
|
_distanceToNearestAvatar = std::numeric_limits<float>::max();
|
||||||
|
|
||||||
initializeSkeleton();
|
initializeSkeleton();
|
||||||
|
|
||||||
|
@ -227,6 +228,7 @@ Avatar::Avatar(const Avatar &otherAvatar) {
|
||||||
_head.lastLoudness = otherAvatar._head.lastLoudness;
|
_head.lastLoudness = otherAvatar._head.lastLoudness;
|
||||||
_head.browAudioLift = otherAvatar._head.browAudioLift;
|
_head.browAudioLift = otherAvatar._head.browAudioLift;
|
||||||
_head.noise = otherAvatar._head.noise;
|
_head.noise = otherAvatar._head.noise;
|
||||||
|
_distanceToNearestAvatar = otherAvatar._distanceToNearestAvatar;
|
||||||
|
|
||||||
initializeSkeleton();
|
initializeSkeleton();
|
||||||
|
|
||||||
|
@ -325,6 +327,7 @@ bool Avatar::getIsNearInteractingOther() {
|
||||||
|
|
||||||
void Avatar::simulate(float deltaTime) {
|
void Avatar::simulate(float deltaTime) {
|
||||||
|
|
||||||
|
|
||||||
//keep this - I'm still using it to test things....
|
//keep this - I'm still using it to test things....
|
||||||
/*
|
/*
|
||||||
//TEST
|
//TEST
|
||||||
|
@ -356,6 +359,9 @@ _head.leanForward = 0.02 * sin( tt * 0.8 );
|
||||||
// all the other avatars for potential interactions...
|
// all the other avatars for potential interactions...
|
||||||
if ( _isMine )
|
if ( _isMine )
|
||||||
{
|
{
|
||||||
|
// Reset detector for nearest avatar
|
||||||
|
_distanceToNearestAvatar = std::numeric_limits<float>::max();
|
||||||
|
|
||||||
AgentList* agentList = AgentList::getInstance();
|
AgentList* agentList = AgentList::getInstance();
|
||||||
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
|
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
|
||||||
if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) {
|
if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) {
|
||||||
|
@ -369,7 +375,9 @@ _head.leanForward = 0.02 * sin( tt * 0.8 );
|
||||||
v -= otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_SHOULDER );
|
v -= otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_SHOULDER );
|
||||||
|
|
||||||
float distance = glm::length( v );
|
float distance = glm::length( v );
|
||||||
if ( distance < _maxArmLength + _maxArmLength ) {
|
if (distance < _distanceToNearestAvatar) { _distanceToNearestAvatar = distance; }
|
||||||
|
|
||||||
|
if (distance < _maxArmLength + _maxArmLength) {
|
||||||
|
|
||||||
_interactingOther = otherAvatar;
|
_interactingOther = otherAvatar;
|
||||||
_avatarTouch.setAbleToReachOtherAvatar(true);
|
_avatarTouch.setAbleToReachOtherAvatar(true);
|
||||||
|
@ -480,6 +488,15 @@ _head.leanForward = 0.02 * sin( tt * 0.8 );
|
||||||
// decay velocity
|
// decay velocity
|
||||||
_velocity *= ( 1.0 - LIN_VEL_DECAY * deltaTime );
|
_velocity *= ( 1.0 - LIN_VEL_DECAY * deltaTime );
|
||||||
|
|
||||||
|
// If someone is near, damp velocity as a function of closeness
|
||||||
|
const float AVATAR_BRAKING_RANGE = 1.2f;
|
||||||
|
const float AVATAR_BRAKING_STRENGTH = 25.f;
|
||||||
|
if (_isMine && (_distanceToNearestAvatar < AVATAR_BRAKING_RANGE)) {
|
||||||
|
_velocity *=
|
||||||
|
(1.f - deltaTime * AVATAR_BRAKING_STRENGTH *
|
||||||
|
(AVATAR_BRAKING_RANGE - _distanceToNearestAvatar));
|
||||||
|
}
|
||||||
|
|
||||||
// update head information
|
// update head information
|
||||||
updateHead(deltaTime);
|
updateHead(deltaTime);
|
||||||
|
|
||||||
|
@ -1359,7 +1376,9 @@ void Avatar::SetNewHeadTarget(float pitch, float yaw) {
|
||||||
_head.yawTarget = yaw;
|
_head.yawTarget = yaw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
// Process UDP interface data from Android transmitter or Google Glass
|
// Process UDP interface data from Android transmitter or Google Glass
|
||||||
|
//
|
||||||
void Avatar::processTransmitterData(unsigned char* packetData, int numBytes) {
|
void Avatar::processTransmitterData(unsigned char* packetData, int numBytes) {
|
||||||
// Read a packet from a transmitter app, process the data
|
// Read a packet from a transmitter app, process the data
|
||||||
float
|
float
|
||||||
|
@ -1371,29 +1390,42 @@ void Avatar::processTransmitterData(unsigned char* packetData, int numBytes) {
|
||||||
// rot1 = roll, ranges from -1 to 1, 0 = flat on table
|
// rot1 = roll, ranges from -1 to 1, 0 = flat on table
|
||||||
// rot2 = pitch, ranges from -1 to 1, 0 = flat on table
|
// rot2 = pitch, ranges from -1 to 1, 0 = flat on table
|
||||||
// rot3 = yaw, ranges from -1 to 1
|
// rot3 = yaw, ranges from -1 to 1
|
||||||
|
char device[100]; // Device ID
|
||||||
|
|
||||||
const bool IS_GLASS = false; // Whether to assume this is a Google glass transmitting
|
enum deviceTypes { DEVICE_GLASS, DEVICE_ANDROID, DEVICE_IPHONE, DEVICE_UNKNOWN };
|
||||||
|
|
||||||
sscanf((char *)packetData, "tacc %f %f %f gra %f %f %f gyr %f %f %f lin %f %f %f rot %f %f %f %f",
|
sscanf((char *)packetData,
|
||||||
|
"tacc %f %f %f gra %f %f %f gyr %f %f %f lin %f %f %f rot %f %f %f %f dna \"%s",
|
||||||
&accX, &accY, &accZ,
|
&accX, &accY, &accZ,
|
||||||
&graX, &graY, &graZ,
|
&graX, &graY, &graZ,
|
||||||
&gyrX, &gyrY, &gyrZ,
|
&gyrX, &gyrY, &gyrZ,
|
||||||
&linX, &linY, &linZ,
|
&linX, &linY, &linZ,
|
||||||
&rot1, &rot2, &rot3, &rot4);
|
&rot1, &rot2, &rot3, &rot4, (char *)&device);
|
||||||
|
|
||||||
|
// decode transmitter device type
|
||||||
|
deviceTypes deviceType = DEVICE_UNKNOWN;
|
||||||
|
if (strcmp(device, "ADR")) {
|
||||||
|
deviceType = DEVICE_ANDROID;
|
||||||
|
} else {
|
||||||
|
deviceType = DEVICE_GLASS;
|
||||||
|
}
|
||||||
|
|
||||||
if (_transmitterPackets++ == 0) {
|
if (_transmitterPackets++ == 0) {
|
||||||
// If first packet received, note time, turn head spring return OFF, get start rotation
|
// If first packet received, note time, turn head spring return OFF, get start rotation
|
||||||
gettimeofday(&_transmitterTimer, NULL);
|
gettimeofday(&_transmitterTimer, NULL);
|
||||||
if (IS_GLASS) {
|
if (deviceType == DEVICE_GLASS) {
|
||||||
setHeadReturnToCenter(true);
|
setHeadReturnToCenter(true);
|
||||||
setHeadSpringScale(10.f);
|
setHeadSpringScale(10.f);
|
||||||
printLog("Using Google Glass to drive head, springs ON.\n");
|
printLog("Using Google Glass to drive head, springs ON.\n");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
setHeadReturnToCenter(false);
|
setHeadReturnToCenter(false);
|
||||||
printLog("Using Transmitter to drive head, springs OFF.\n");
|
printLog("Using Transmitter %s to drive head, springs OFF.\n", device);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
//printLog("Packet: [%s]\n", packetData);
|
||||||
|
//printLog("Version: %s\n", device);
|
||||||
|
|
||||||
_transmitterInitialReading = glm::vec3( rot3,
|
_transmitterInitialReading = glm::vec3( rot3,
|
||||||
rot2,
|
rot2,
|
||||||
rot1 );
|
rot1 );
|
||||||
|
@ -1419,7 +1451,7 @@ void Avatar::processTransmitterData(unsigned char* packetData, int numBytes) {
|
||||||
if (eulerAngles.x < -180.f) { eulerAngles.x += 360.f; }
|
if (eulerAngles.x < -180.f) { eulerAngles.x += 360.f; }
|
||||||
|
|
||||||
glm::vec3 angularVelocity;
|
glm::vec3 angularVelocity;
|
||||||
if (!IS_GLASS) {
|
if (deviceType != DEVICE_GLASS) {
|
||||||
angularVelocity = glm::vec3(glm::degrees(gyrZ), glm::degrees(-gyrX), glm::degrees(gyrY));
|
angularVelocity = glm::vec3(glm::degrees(gyrZ), glm::degrees(-gyrX), glm::degrees(gyrY));
|
||||||
setHeadFromGyros( &eulerAngles, &angularVelocity,
|
setHeadFromGyros( &eulerAngles, &angularVelocity,
|
||||||
(_transmitterHz == 0.f) ? 0.f : 1.f / _transmitterHz, 1.0);
|
(_transmitterHz == 0.f) ? 0.f : 1.f / _transmitterHz, 1.0);
|
||||||
|
@ -1430,7 +1462,6 @@ void Avatar::processTransmitterData(unsigned char* packetData, int numBytes) {
|
||||||
(_transmitterHz == 0.f) ? 0.f : 1.f / _transmitterHz, 1000.0);
|
(_transmitterHz == 0.f) ? 0.f : 1.f / _transmitterHz, 1000.0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::setHeadFromGyros(glm::vec3* eulerAngles, glm::vec3* angularVelocity, float deltaTime, float smoothingTime) {
|
void Avatar::setHeadFromGyros(glm::vec3* eulerAngles, glm::vec3* angularVelocity, float deltaTime, float smoothingTime) {
|
||||||
|
@ -1477,8 +1508,13 @@ glm::vec3 Avatar::getGravity(glm::vec3 pos) {
|
||||||
// For now, we'll test this with a simple global lookup, but soon we will add getting this
|
// For now, we'll test this with a simple global lookup, but soon we will add getting this
|
||||||
// from the domain/voxelserver (or something similar)
|
// from the domain/voxelserver (or something similar)
|
||||||
//
|
//
|
||||||
if (glm::length(pos) < 5.f) {
|
if ((pos.x > 0.f) &&
|
||||||
// If near the origin sphere, turn gravity ON
|
(pos.x < 10.f) &&
|
||||||
|
(pos.z > 0.f) &&
|
||||||
|
(pos.z < 10.f) &&
|
||||||
|
(pos.y > 0.f) &&
|
||||||
|
(pos.y < 3.f)) {
|
||||||
|
// If above ground plane, turn gravity on
|
||||||
return glm::vec3(0.f, -1.f, 0.f);
|
return glm::vec3(0.f, -1.f, 0.f);
|
||||||
} else {
|
} else {
|
||||||
// If flying in space, turn gravity OFF
|
// If flying in space, turn gravity OFF
|
||||||
|
|
|
@ -243,6 +243,7 @@ private:
|
||||||
AvatarTouch _avatarTouch;
|
AvatarTouch _avatarTouch;
|
||||||
bool _displayingHead; // should be false if in first-person view
|
bool _displayingHead; // should be false if in first-person view
|
||||||
bool _returnHeadToCenter;
|
bool _returnHeadToCenter;
|
||||||
|
float _distanceToNearestAvatar; // How close is the nearest avatar?
|
||||||
|
|
||||||
// private methods...
|
// private methods...
|
||||||
void initializeSkeleton();
|
void initializeSkeleton();
|
||||||
|
|
|
@ -213,42 +213,28 @@ void drawvec3(int x, int y, float scale, float rotate, float thick, int mono, gl
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawGroundPlaneGrid( float size, int resolution )
|
void drawGroundPlaneGrid(float size)
|
||||||
{
|
{
|
||||||
|
|
||||||
glColor3f( 0.4f, 0.5f, 0.3f );
|
glColor3f( 0.4f, 0.5f, 0.3f );
|
||||||
glLineWidth(2.0);
|
glLineWidth(2.0);
|
||||||
|
|
||||||
float gridSize = 10.0;
|
for (float x = 0; x <= size; x++) {
|
||||||
int gridResolution = 20;
|
glBegin(GL_LINES);
|
||||||
|
glVertex3f(x, 0.0f, 0);
|
||||||
for (int g=0; g<gridResolution; g++)
|
glVertex3f(x, 0.0f, size);
|
||||||
{
|
glVertex3f(0, 0.0f, x);
|
||||||
float fraction = (float)g / (float)( gridResolution - 1 );
|
glVertex3f(size, 0.0f, x);
|
||||||
float inc = -gridSize * ONE_HALF + fraction * gridSize;
|
|
||||||
glBegin( GL_LINE_STRIP );
|
|
||||||
glVertex3f( inc, 0.0f, -gridSize * ONE_HALF );
|
|
||||||
glVertex3f( inc, 0.0f, gridSize * ONE_HALF );
|
|
||||||
glEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int g=0; g<gridResolution; g++)
|
|
||||||
{
|
|
||||||
float fraction = (float)g / (float)( gridResolution - 1 );
|
|
||||||
float inc = -gridSize * ONE_HALF + fraction * gridSize;
|
|
||||||
glBegin( GL_LINE_STRIP );
|
|
||||||
glVertex3f( -gridSize * ONE_HALF, 0.0f, inc );
|
|
||||||
glVertex3f( gridSize * ONE_HALF, 0.0f, inc );
|
|
||||||
glEnd();
|
glEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a translucent quad just underneath the grid.
|
// Draw a translucent quad just underneath the grid.
|
||||||
glColor4f(0.5, 0.5, 0.5, 0.4);
|
glColor4f(0.5, 0.5, 0.5, 0.4);
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
glVertex3f(-gridSize * ONE_HALF, 0, -gridSize * ONE_HALF);
|
glVertex3f(0, 0, 0);
|
||||||
glVertex3f(gridSize * ONE_HALF, 0, -gridSize * ONE_HALF);
|
glVertex3f(size, 0, 0);
|
||||||
glVertex3f(gridSize * ONE_HALF, 0, gridSize * ONE_HALF);
|
glVertex3f(size, 0, size);
|
||||||
glVertex3f(-gridSize * ONE_HALF, 0, gridSize * ONE_HALF);
|
glVertex3f(0, 0, size);
|
||||||
glEnd();
|
glEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ void drawvec3(int x, int y, float scale, float rotate, float thick, int mono, gl
|
||||||
float r=1.0, float g=1.0, float b=1.0);
|
float r=1.0, float g=1.0, float b=1.0);
|
||||||
double diffclock(timeval *clock1,timeval *clock2);
|
double diffclock(timeval *clock1,timeval *clock2);
|
||||||
|
|
||||||
void drawGroundPlaneGrid( float size, int resolution );
|
void drawGroundPlaneGrid(float size);
|
||||||
|
|
||||||
void renderOrientationDirections( glm::vec3 position, Orientation orientation, float size );
|
void renderOrientationDirections( glm::vec3 position, Orientation orientation, float size );
|
||||||
|
|
||||||
|
|
|
@ -97,8 +97,26 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
|
||||||
|
|
||||||
switch(command) {
|
switch(command) {
|
||||||
case PACKET_HEADER_VOXEL_DATA:
|
case PACKET_HEADER_VOXEL_DATA:
|
||||||
|
{
|
||||||
|
double start = usecTimestampNow();
|
||||||
// ask the VoxelTree to read the bitstream into the tree
|
// ask the VoxelTree to read the bitstream into the tree
|
||||||
_tree->readBitstreamToTree(voxelData, numBytes - 1);
|
_tree->readBitstreamToTree(voxelData, numBytes - 1);
|
||||||
|
if (_renderWarningsOn && _tree->getNodesChangedFromBitstream()) {
|
||||||
|
printLog("readBitstreamToTree()... getNodesChangedFromBitstream=%ld _tree->isDirty()=%s \n",
|
||||||
|
_tree->getNodesChangedFromBitstream(), (_tree->isDirty() ? "yes" : "no") );
|
||||||
|
}
|
||||||
|
|
||||||
|
double end = usecTimestampNow();
|
||||||
|
double elapsedmsec = (end - start)/1000.0;
|
||||||
|
if (_renderWarningsOn && elapsedmsec > 1) {
|
||||||
|
if (elapsedmsec > 1000) {
|
||||||
|
double elapsedsec = (end - start)/1000000.0;
|
||||||
|
printLog("WARNING! readBitstreamToTree() took %lf seconds\n",elapsedsec);
|
||||||
|
} else {
|
||||||
|
printLog("WARNING! readBitstreamToTree() took %lf milliseconds\n",elapsedmsec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case PACKET_HEADER_ERASE_VOXEL:
|
case PACKET_HEADER_ERASE_VOXEL:
|
||||||
// ask the tree to read the "remove" bitstream
|
// ask the tree to read the "remove" bitstream
|
||||||
|
@ -135,17 +153,48 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSystem::setupNewVoxelsForDrawing() {
|
void VoxelSystem::setupNewVoxelsForDrawing() {
|
||||||
|
double start = usecTimestampNow();
|
||||||
|
|
||||||
|
double sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished);
|
||||||
|
|
||||||
|
if (sinceLastTime <= std::max(_setupNewVoxelsForDrawingLastElapsed,SIXTY_FPS_IN_MILLISECONDS)) {
|
||||||
|
return; // bail early, it hasn't been long enough since the last time we ran
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_tree->isDirty()) {
|
||||||
|
_callsToTreesToArrays++;
|
||||||
_voxelsUpdated = newTreeToArrays(_tree->rootNode);
|
_voxelsUpdated = newTreeToArrays(_tree->rootNode);
|
||||||
|
_tree->clearDirtyBit(); // after we pull the trees into the array, we can consider the tree clean
|
||||||
|
} else {
|
||||||
|
_voxelsUpdated = 0;
|
||||||
|
}
|
||||||
if (_voxelsUpdated) {
|
if (_voxelsUpdated) {
|
||||||
_voxelsDirty=true;
|
_voxelsDirty=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_voxelsDirty) {
|
||||||
// copy the newly written data to the arrays designated for reading
|
// copy the newly written data to the arrays designated for reading
|
||||||
copyWrittenDataToReadArrays();
|
copyWrittenDataToReadArrays();
|
||||||
|
}
|
||||||
|
|
||||||
|
double end = usecTimestampNow();
|
||||||
|
double elapsedmsec = (end - start)/1000.0;
|
||||||
|
if (_renderWarningsOn && elapsedmsec > 1) {
|
||||||
|
if (elapsedmsec > 1000) {
|
||||||
|
double elapsedsec = (end - start)/1000000.0;
|
||||||
|
printLog("WARNING! newTreeToArrays() took %lf seconds %ld voxels updated\n", elapsedsec, _voxelsUpdated);
|
||||||
|
} else {
|
||||||
|
printLog("WARNING! newTreeToArrays() took %lf milliseconds %ld voxels updated\n", elapsedmsec, _voxelsUpdated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_setupNewVoxelsForDrawingLastFinished = end;
|
||||||
|
_setupNewVoxelsForDrawingLastElapsed = elapsedmsec;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSystem::copyWrittenDataToReadArrays() {
|
void VoxelSystem::copyWrittenDataToReadArrays() {
|
||||||
if (_voxelsDirty) {
|
double start = usecTimestampNow();
|
||||||
|
if (_voxelsDirty && _voxelsUpdated) {
|
||||||
// lock on the buffer write lock so we can't modify the data when the GPU is reading it
|
// lock on the buffer write lock so we can't modify the data when the GPU is reading it
|
||||||
pthread_mutex_lock(&_bufferWriteLock);
|
pthread_mutex_lock(&_bufferWriteLock);
|
||||||
int bytesOfVertices = (_voxelsInArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLfloat);
|
int bytesOfVertices = (_voxelsInArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLfloat);
|
||||||
|
@ -154,6 +203,18 @@ void VoxelSystem::copyWrittenDataToReadArrays() {
|
||||||
memcpy(_readColorsArray, _writeColorsArray, bytesOfColors );
|
memcpy(_readColorsArray, _writeColorsArray, bytesOfColors );
|
||||||
pthread_mutex_unlock(&_bufferWriteLock);
|
pthread_mutex_unlock(&_bufferWriteLock);
|
||||||
}
|
}
|
||||||
|
double end = usecTimestampNow();
|
||||||
|
double elapsedmsec = (end - start)/1000.0;
|
||||||
|
if (_renderWarningsOn && elapsedmsec > 1) {
|
||||||
|
if (elapsedmsec > 1000) {
|
||||||
|
double elapsedsec = (end - start)/1000000.0;
|
||||||
|
printLog("WARNING! copyWrittenDataToReadArrays() took %lf seconds for %ld voxels %ld updated\n",
|
||||||
|
elapsedsec, _voxelsInArrays, _voxelsUpdated);
|
||||||
|
} else {
|
||||||
|
printLog("WARNING! copyWrittenDataToReadArrays() took %lf milliseconds for %ld voxels %ld updated\n",
|
||||||
|
elapsedmsec, _voxelsInArrays, _voxelsUpdated);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int VoxelSystem::newTreeToArrays(VoxelNode* node) {
|
int VoxelSystem::newTreeToArrays(VoxelNode* node) {
|
||||||
|
@ -213,8 +274,8 @@ int VoxelSystem::newTreeToArrays(VoxelNode* node) {
|
||||||
_voxelsInArrays++; // our know vertices in the arrays
|
_voxelsInArrays++; // our know vertices in the arrays
|
||||||
}
|
}
|
||||||
voxelsUpdated++;
|
voxelsUpdated++;
|
||||||
node->clearDirtyBit();
|
|
||||||
}
|
}
|
||||||
|
node->clearDirtyBit(); // always clear the dirty bit, even if it doesn't need to be rendered
|
||||||
return voxelsUpdated;
|
return voxelsUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,6 +286,11 @@ VoxelSystem* VoxelSystem::clone() const {
|
||||||
|
|
||||||
void VoxelSystem::init() {
|
void VoxelSystem::init() {
|
||||||
|
|
||||||
|
_renderWarningsOn = false;
|
||||||
|
_callsToTreesToArrays = 0;
|
||||||
|
_setupNewVoxelsForDrawingLastFinished = 0;
|
||||||
|
_setupNewVoxelsForDrawingLastElapsed = 0;
|
||||||
|
|
||||||
// When we change voxels representations in the arrays, we'll update this
|
// When we change voxels representations in the arrays, we'll update this
|
||||||
_voxelsDirty = false;
|
_voxelsDirty = false;
|
||||||
_voxelsInArrays = 0;
|
_voxelsInArrays = 0;
|
||||||
|
@ -296,6 +362,7 @@ void VoxelSystem::init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSystem::updateVBOs() {
|
void VoxelSystem::updateVBOs() {
|
||||||
|
double start = usecTimestampNow();
|
||||||
if (_voxelsDirty) {
|
if (_voxelsDirty) {
|
||||||
glBufferIndex segmentStart = 0;
|
glBufferIndex segmentStart = 0;
|
||||||
glBufferIndex segmentEnd = 0;
|
glBufferIndex segmentEnd = 0;
|
||||||
|
@ -327,9 +394,27 @@ void VoxelSystem::updateVBOs() {
|
||||||
}
|
}
|
||||||
_voxelsDirty = false;
|
_voxelsDirty = false;
|
||||||
}
|
}
|
||||||
|
double end = usecTimestampNow();
|
||||||
|
double elapsedmsec = (end - start)/1000.0;
|
||||||
|
if (_renderWarningsOn && elapsedmsec > 1) {
|
||||||
|
if (elapsedmsec > 1) {
|
||||||
|
if (elapsedmsec > 1000) {
|
||||||
|
double elapsedsec = (end - start)/1000000.0;
|
||||||
|
printLog("WARNING! updateVBOs() took %lf seconds after %d calls to newTreeToArrays()\n",
|
||||||
|
elapsedsec, _callsToTreesToArrays);
|
||||||
|
} else {
|
||||||
|
printLog("WARNING! updateVBOs() took %lf milliseconds after %d calls to newTreeToArrays()\n",
|
||||||
|
elapsedmsec, _callsToTreesToArrays);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printLog("WARNING! updateVBOs() called after %d calls to newTreeToArrays()\n",_callsToTreesToArrays);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_callsToTreesToArrays = 0; // clear it
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSystem::render() {
|
void VoxelSystem::render() {
|
||||||
|
double start = usecTimestampNow();
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
updateVBOs();
|
updateVBOs();
|
||||||
// tell OpenGL where to find vertex and color information
|
// tell OpenGL where to find vertex and color information
|
||||||
|
@ -362,14 +447,31 @@ void VoxelSystem::render() {
|
||||||
|
|
||||||
// scale back down to 1 so heads aren't massive
|
// scale back down to 1 so heads aren't massive
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
double end = usecTimestampNow();
|
||||||
|
double elapsedmsec = (end - start)/1000.0;
|
||||||
|
if (_renderWarningsOn && elapsedmsec > 1) {
|
||||||
|
if (elapsedmsec > 1000) {
|
||||||
|
double elapsedsec = (end - start)/1000000.0;
|
||||||
|
printLog("WARNING! render() took %lf seconds\n",elapsedsec);
|
||||||
|
} else {
|
||||||
|
printLog("WARNING! render() took %lf milliseconds\n",elapsedmsec);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int VoxelSystem::_nodeCount = 0;
|
int VoxelSystem::_nodeCount = 0;
|
||||||
|
|
||||||
|
void VoxelSystem::killLocalVoxels() {
|
||||||
|
_tree->eraseAllVoxels();
|
||||||
|
_voxelsInArrays = 0; // better way to do this??
|
||||||
|
//setupNewVoxelsForDrawing();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool VoxelSystem::randomColorOperation(VoxelNode* node, void* extraData) {
|
bool VoxelSystem::randomColorOperation(VoxelNode* node, void* extraData) {
|
||||||
_nodeCount++;
|
_nodeCount++;
|
||||||
if (node->isColored()) {
|
if (node->isColored()) {
|
||||||
nodeColor newColor = { randomColorValue(150), randomColorValue(150), randomColorValue(150), 1 };
|
nodeColor newColor = { 255, randomColorValue(150), randomColorValue(150), 1 };
|
||||||
node->setColor(newColor);
|
node->setColor(newColor);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -385,7 +487,7 @@ void VoxelSystem::randomizeVoxelColors() {
|
||||||
bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, void* extraData) {
|
bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, void* extraData) {
|
||||||
_nodeCount++;
|
_nodeCount++;
|
||||||
// always false colorize
|
// always false colorize
|
||||||
node->setFalseColor(randomColorValue(150), randomColorValue(150), randomColorValue(150));
|
node->setFalseColor(255, randomColorValue(150), randomColorValue(150));
|
||||||
return true; // keep going!
|
return true; // keep going!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,14 @@ public:
|
||||||
void falseColorizeInView(ViewFrustum* viewFrustum);
|
void falseColorizeInView(ViewFrustum* viewFrustum);
|
||||||
void falseColorizeDistanceFromView(ViewFrustum* viewFrustum);
|
void falseColorizeDistanceFromView(ViewFrustum* viewFrustum);
|
||||||
|
|
||||||
|
void killLocalVoxels();
|
||||||
|
void setRenderPipelineWarnings(bool on) { _renderWarningsOn = on; };
|
||||||
|
bool getRenderPipelineWarnings() const { return _renderWarningsOn; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int _callsToTreesToArrays;
|
||||||
|
|
||||||
|
bool _renderWarningsOn;
|
||||||
// Operation functions for tree recursion methods
|
// Operation functions for tree recursion methods
|
||||||
static int _nodeCount;
|
static int _nodeCount;
|
||||||
static bool randomColorOperation(VoxelNode* node, void* extraData);
|
static bool randomColorOperation(VoxelNode* node, void* extraData);
|
||||||
|
@ -83,6 +90,10 @@ private:
|
||||||
unsigned long _voxelsUpdated;
|
unsigned long _voxelsUpdated;
|
||||||
unsigned long _voxelsInArrays;
|
unsigned long _voxelsInArrays;
|
||||||
|
|
||||||
|
|
||||||
|
double _setupNewVoxelsForDrawingLastElapsed;
|
||||||
|
double _setupNewVoxelsForDrawingLastFinished;
|
||||||
|
|
||||||
GLuint _vboVerticesID;
|
GLuint _vboVerticesID;
|
||||||
GLuint _vboNormalsID;
|
GLuint _vboNormalsID;
|
||||||
GLuint _vboColorsID;
|
GLuint _vboColorsID;
|
||||||
|
|
|
@ -130,16 +130,21 @@ glm::vec3 box(WORLD_SIZE,WORLD_SIZE,WORLD_SIZE);
|
||||||
|
|
||||||
VoxelSystem voxels;
|
VoxelSystem voxels;
|
||||||
|
|
||||||
|
bool wantToKillLocalVoxels = false;
|
||||||
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
Audio audio(&audioScope, &myAvatar);
|
Audio audio(&audioScope, &myAvatar);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define IDLE_SIMULATE_MSECS 8 // How often should call simulate and other stuff
|
#define IDLE_SIMULATE_MSECS 16 // How often should call simulate and other stuff
|
||||||
// in the idle loop?
|
// in the idle loop?
|
||||||
|
|
||||||
// Where one's own agent begins in the world (needs to become a dynamic thing passed to the program)
|
// Where one's own agent begins in the world (needs to become a dynamic thing passed to the program)
|
||||||
glm::vec3 start_location(6.1f, 0, 1.4f);
|
glm::vec3 start_location(6.1f, 0, 1.4f);
|
||||||
|
|
||||||
|
bool renderWarningsOn = false; // Whether to show render pipeline warnings
|
||||||
|
|
||||||
bool statsOn = false; // Whether to show onscreen text overlay with stats
|
bool statsOn = false; // Whether to show onscreen text overlay with stats
|
||||||
bool starsOn = false; // Whether to display the stars
|
bool starsOn = false; // Whether to display the stars
|
||||||
bool paintOn = false; // Whether to paint voxels as you fly around
|
bool paintOn = false; // Whether to paint voxels as you fly around
|
||||||
|
@ -224,37 +229,30 @@ void displayStats(void)
|
||||||
if (::menuOn == 0) {
|
if (::menuOn == 0) {
|
||||||
statsVerticalOffset = 8;
|
statsVerticalOffset = 8;
|
||||||
}
|
}
|
||||||
// bitmap chars are about 10 pels high
|
|
||||||
char legend[] = "/ - toggle this display, Q - exit, H - show head, M - show hand, T - test audio";
|
|
||||||
drawtext(10, statsVerticalOffset + 15, 0.10f, 0, 1.0, 0, legend);
|
|
||||||
|
|
||||||
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.getPosition();
|
|
||||||
|
|
||||||
char stats[200];
|
char stats[200];
|
||||||
sprintf(stats, "FPS = %3.0f Pkts/s = %d Bytes/s = %d Head(x,y,z)= %4.2f, %4.2f, %4.2f ",
|
sprintf(stats, "%3.0f FPS, %d Pkts/sec, %3.2f Mbps",
|
||||||
FPS, packetsPerSecond, bytesPerSecond, avatarPos.x,avatarPos.y,avatarPos.z);
|
FPS, packetsPerSecond, (float)bytesPerSecond * 8.f / 1000000.f);
|
||||||
drawtext(10, statsVerticalOffset + 49, 0.10f, 0, 1.0, 0, stats);
|
drawtext(10, statsVerticalOffset + 15, 0.10f, 0, 1.0, 0, stats);
|
||||||
|
|
||||||
std::stringstream voxelStats;
|
std::stringstream voxelStats;
|
||||||
voxelStats << "Voxels Rendered: " << voxels.getVoxelsRendered() << " Updated: " << voxels.getVoxelsUpdated();
|
voxelStats.precision(4);
|
||||||
drawtext(10, statsVerticalOffset + 70, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
voxelStats << "Voxels Rendered: " << voxels.getVoxelsRendered() / 1000.f << "K Updated: " << voxels.getVoxelsUpdated()/1000.f << "K";
|
||||||
|
drawtext(10, statsVerticalOffset + 230, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
||||||
|
|
||||||
voxelStats.str("");
|
voxelStats.str("");
|
||||||
voxelStats << "Voxels Created: " << voxels.getVoxelsCreated() << " (" << voxels.getVoxelsCreatedPerSecondAverage()
|
voxelStats << "Voxels Created: " << voxels.getVoxelsCreated() / 1000.f << "K (" << voxels.getVoxelsCreatedPerSecondAverage() / 1000.f
|
||||||
<< "/sec) ";
|
<< "Kps) ";
|
||||||
drawtext(10, statsVerticalOffset + 250, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
drawtext(10, statsVerticalOffset + 250, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
||||||
|
|
||||||
voxelStats.str("");
|
voxelStats.str("");
|
||||||
voxelStats << "Voxels Colored: " << voxels.getVoxelsColored() << " (" << voxels.getVoxelsColoredPerSecondAverage()
|
voxelStats << "Voxels Colored: " << voxels.getVoxelsColored() / 1000.f << "K (" << voxels.getVoxelsColoredPerSecondAverage() / 1000.f
|
||||||
<< "/sec) ";
|
<< "Kps) ";
|
||||||
drawtext(10, statsVerticalOffset + 270, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
drawtext(10, statsVerticalOffset + 270, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
||||||
|
|
||||||
voxelStats.str("");
|
voxelStats.str("");
|
||||||
voxelStats << "Voxels Bytes Read: " << voxels.getVoxelsBytesRead()
|
voxelStats << "Voxel Bits Read: " << voxels.getVoxelsBytesRead() * 8.f / 1000000.f
|
||||||
<< " (" << voxels.getVoxelsBytesReadPerSecondAverage() << " Bps)";
|
<< "M (" << voxels.getVoxelsBytesReadPerSecondAverage() * 8.f / 1000000.f << " Mbps)";
|
||||||
drawtext(10, statsVerticalOffset + 290,0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
drawtext(10, statsVerticalOffset + 290,0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
||||||
|
|
||||||
voxelStats.str("");
|
voxelStats.str("");
|
||||||
|
@ -262,13 +260,13 @@ void displayStats(void)
|
||||||
? ((float) voxels.getVoxelsBytesRead() / voxels.getVoxelsColored())
|
? ((float) voxels.getVoxelsBytesRead() / voxels.getVoxelsColored())
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
voxelStats << "Voxels Bytes per Colored: " << voxelsBytesPerColored;
|
voxelStats << "Voxels Bits per Colored: " << voxelsBytesPerColored * 8;
|
||||||
drawtext(10, statsVerticalOffset + 310, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
drawtext(10, statsVerticalOffset + 310, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str());
|
||||||
|
|
||||||
Agent *avatarMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AVATAR_MIXER);
|
Agent *avatarMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AVATAR_MIXER);
|
||||||
char avatarMixerStats[200];
|
char avatarMixerStats[200];
|
||||||
if (avatarMixer) {
|
if (avatarMixer) {
|
||||||
sprintf(avatarMixerStats, "Avatar Mixer - %.f kbps, %.f pps",
|
sprintf(avatarMixerStats, "Avatar Mixer: %.f kbps, %.f pps",
|
||||||
roundf(avatarMixer->getAverageKilobitsPerSecond()),
|
roundf(avatarMixer->getAverageKilobitsPerSecond()),
|
||||||
roundf(avatarMixer->getAveragePacketsPerSecond()));
|
roundf(avatarMixer->getAveragePacketsPerSecond()));
|
||||||
} else {
|
} else {
|
||||||
|
@ -701,7 +699,7 @@ void displaySide(Camera& whichCamera) {
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
||||||
//draw a grid ground plane....
|
//draw a grid ground plane....
|
||||||
drawGroundPlaneGrid( 5.0f, 9 );
|
drawGroundPlaneGrid(10.f);
|
||||||
|
|
||||||
// Draw voxels
|
// Draw voxels
|
||||||
if ( showingVoxels )
|
if ( showingVoxels )
|
||||||
|
@ -1217,6 +1215,14 @@ int setMenu(int state) {
|
||||||
return setValue(state, &::menuOn);
|
return setValue(state, &::menuOn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int setRenderWarnings(int state) {
|
||||||
|
int value = setValue(state, &::renderWarningsOn);
|
||||||
|
if (state == MENU_ROW_PICKED) {
|
||||||
|
::voxels.setRenderPipelineWarnings(::renderWarningsOn);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
int setDisplayFrustum(int state) {
|
int setDisplayFrustum(int state) {
|
||||||
return setValue(state, &::frustumOn);
|
return setValue(state, &::frustumOn);
|
||||||
}
|
}
|
||||||
|
@ -1250,6 +1256,13 @@ int setFrustumRenderMode(int state) {
|
||||||
return ::frustumDrawingMode;
|
return ::frustumDrawingMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int doKillLocalVoxels(int state) {
|
||||||
|
if (state == MENU_ROW_PICKED) {
|
||||||
|
::wantToKillLocalVoxels = true;
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
int doRandomizeVoxelColors(int state) {
|
int doRandomizeVoxelColors(int state) {
|
||||||
if (state == MENU_ROW_PICKED) {
|
if (state == MENU_ROW_PICKED) {
|
||||||
::voxels.randomizeVoxelColors();
|
::voxels.randomizeVoxelColors();
|
||||||
|
@ -1348,6 +1361,8 @@ void initMenu() {
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
menuColumnDebug = menu.addColumn("Debug");
|
menuColumnDebug = menu.addColumn("Debug");
|
||||||
|
menuColumnDebug->addRow("Show Render Pipeline Warnings", setRenderWarnings);
|
||||||
|
menuColumnDebug->addRow("Kill Local Voxels", doKillLocalVoxels);
|
||||||
menuColumnDebug->addRow("Randomize Voxel TRUE Colors", doRandomizeVoxelColors);
|
menuColumnDebug->addRow("Randomize Voxel TRUE Colors", doRandomizeVoxelColors);
|
||||||
menuColumnDebug->addRow("FALSE Color Voxels Randomly", doFalseRandomizeVoxelColors);
|
menuColumnDebug->addRow("FALSE Color Voxels Randomly", doFalseRandomizeVoxelColors);
|
||||||
menuColumnDebug->addRow("FALSE Color Voxels by Distance", doFalseColorizeByDistance);
|
menuColumnDebug->addRow("FALSE Color Voxels by Distance", doFalseColorizeByDistance);
|
||||||
|
@ -1593,6 +1608,12 @@ void* networkReceive(void* args)
|
||||||
ssize_t bytesReceived;
|
ssize_t bytesReceived;
|
||||||
|
|
||||||
while (!stopNetworkReceiveThread) {
|
while (!stopNetworkReceiveThread) {
|
||||||
|
// check to see if the UI thread asked us to kill the voxel tree. since we're the only thread allowed to do that
|
||||||
|
if (::wantToKillLocalVoxels) {
|
||||||
|
::voxels.killLocalVoxels();
|
||||||
|
::wantToKillLocalVoxels = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (AgentList::getInstance()->getAgentSocket().receive(&senderAddress, incomingPacket, &bytesReceived)) {
|
if (AgentList::getInstance()->getAgentSocket().receive(&senderAddress, incomingPacket, &bytesReceived)) {
|
||||||
packetCount++;
|
packetCount++;
|
||||||
bytesCount += bytesReceived;
|
bytesCount += bytesReceived;
|
||||||
|
|
|
@ -24,4 +24,5 @@ const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL;
|
||||||
typedef unsigned long int glBufferIndex;
|
typedef unsigned long int glBufferIndex;
|
||||||
const glBufferIndex GLBUFFER_INDEX_UNKNOWN = ULONG_MAX;
|
const glBufferIndex GLBUFFER_INDEX_UNKNOWN = ULONG_MAX;
|
||||||
|
|
||||||
|
const double SIXTY_FPS_IN_MILLISECONDS = 1000.0/60;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -125,7 +125,9 @@ void VoxelNode::setFalseColor(colorPart red, colorPart green, colorPart blue) {
|
||||||
_currentColor[1] = green;
|
_currentColor[1] = green;
|
||||||
_currentColor[2] = blue;
|
_currentColor[2] = blue;
|
||||||
_currentColor[3] = 1; // XXXBHG - False colors are always considered set
|
_currentColor[3] = 1; // XXXBHG - False colors are always considered set
|
||||||
|
//if (_shouldRender) {
|
||||||
_isDirty = true;
|
_isDirty = true;
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,18 +138,24 @@ void VoxelNode::setFalseColored(bool isFalseColored) {
|
||||||
memcpy(&_currentColor,&_trueColor,sizeof(nodeColor));
|
memcpy(&_currentColor,&_trueColor,sizeof(nodeColor));
|
||||||
}
|
}
|
||||||
_falseColored = isFalseColored;
|
_falseColored = isFalseColored;
|
||||||
|
//if (_shouldRender) {
|
||||||
_isDirty = true;
|
_isDirty = true;
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void VoxelNode::setColor(const nodeColor& color) {
|
void VoxelNode::setColor(const nodeColor& color) {
|
||||||
if (_trueColor[0] != color[0] || _trueColor[1] != color[1] || _trueColor[2] != color[2]) {
|
if (_trueColor[0] != color[0] || _trueColor[1] != color[1] || _trueColor[2] != color[2]) {
|
||||||
|
//printLog("VoxelNode::setColor() was: (%d,%d,%d) is: (%d,%d,%d)\n",
|
||||||
|
// _trueColor[0],_trueColor[1],_trueColor[2],color[0],color[1],color[2]);
|
||||||
memcpy(&_trueColor,&color,sizeof(nodeColor));
|
memcpy(&_trueColor,&color,sizeof(nodeColor));
|
||||||
if (!_falseColored) {
|
if (!_falseColored) {
|
||||||
memcpy(&_currentColor,&color,sizeof(nodeColor));
|
memcpy(&_currentColor,&color,sizeof(nodeColor));
|
||||||
}
|
}
|
||||||
|
//if (_shouldRender) {
|
||||||
_isDirty = true;
|
_isDirty = true;
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -234,6 +242,7 @@ bool VoxelNode::isInView(const ViewFrustum& viewFrustum) const {
|
||||||
float VoxelNode::distanceToCamera(const ViewFrustum& viewFrustum) const {
|
float VoxelNode::distanceToCamera(const ViewFrustum& viewFrustum) const {
|
||||||
AABox box;
|
AABox box;
|
||||||
getAABox(box);
|
getAABox(box);
|
||||||
|
box.scale(TREE_SCALE);
|
||||||
float distanceToVoxelCenter = sqrtf(powf(viewFrustum.getPosition().x - (box.getCorner().x + box.getSize().x), 2) +
|
float distanceToVoxelCenter = sqrtf(powf(viewFrustum.getPosition().x - (box.getCorner().x + box.getSize().x), 2) +
|
||||||
powf(viewFrustum.getPosition().y - (box.getCorner().y + box.getSize().y), 2) +
|
powf(viewFrustum.getPosition().y - (box.getCorner().y + box.getSize().y), 2) +
|
||||||
powf(viewFrustum.getPosition().z - (box.getCorner().z + box.getSize().z), 2));
|
powf(viewFrustum.getPosition().z - (box.getCorner().z + box.getSize().z), 2));
|
||||||
|
|
|
@ -35,7 +35,8 @@ VoxelTree::VoxelTree() :
|
||||||
voxelsBytesRead(0),
|
voxelsBytesRead(0),
|
||||||
voxelsCreatedStats(100),
|
voxelsCreatedStats(100),
|
||||||
voxelsColoredStats(100),
|
voxelsColoredStats(100),
|
||||||
voxelsBytesReadStats(100) {
|
voxelsBytesReadStats(100),
|
||||||
|
_isDirty(true) {
|
||||||
|
|
||||||
rootNode = new VoxelNode();
|
rootNode = new VoxelNode();
|
||||||
rootNode->octalCode = new unsigned char[1];
|
rootNode->octalCode = new unsigned char[1];
|
||||||
|
@ -127,17 +128,29 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode,
|
||||||
// check the colors mask to see if we have a child to color in
|
// check the colors mask to see if we have a child to color in
|
||||||
if (oneAtBit(*nodeData, i)) {
|
if (oneAtBit(*nodeData, i)) {
|
||||||
// create the child if it doesn't exist
|
// create the child if it doesn't exist
|
||||||
if (destinationNode->children[i] == NULL) {
|
if (!destinationNode->children[i]) {
|
||||||
destinationNode->addChildAtIndex(i);
|
destinationNode->addChildAtIndex(i);
|
||||||
this->voxelsCreated++;
|
if (destinationNode->isDirty()) {
|
||||||
this->voxelsCreatedStats.updateAverage(1);
|
_isDirty = true;
|
||||||
|
_nodesChangedFromBitstream++;
|
||||||
|
}
|
||||||
|
voxelsCreated++;
|
||||||
|
voxelsCreatedStats.updateAverage(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// pull the color for this child
|
// pull the color for this child
|
||||||
nodeColor newColor;
|
nodeColor newColor;
|
||||||
memcpy(newColor, nodeData + bytesRead, 3);
|
memcpy(newColor, nodeData + bytesRead, 3);
|
||||||
newColor[3] = 1;
|
newColor[3] = 1;
|
||||||
|
bool nodeWasDirty = destinationNode->children[i]->isDirty();
|
||||||
destinationNode->children[i]->setColor(newColor);
|
destinationNode->children[i]->setColor(newColor);
|
||||||
|
bool nodeIsDirty = destinationNode->children[i]->isDirty();
|
||||||
|
if (nodeIsDirty) {
|
||||||
|
_isDirty = true;
|
||||||
|
}
|
||||||
|
if (!nodeWasDirty && nodeIsDirty) {
|
||||||
|
_nodesChangedFromBitstream++;
|
||||||
|
}
|
||||||
this->voxelsColored++;
|
this->voxelsColored++;
|
||||||
this->voxelsColoredStats.updateAverage(1);
|
this->voxelsColoredStats.updateAverage(1);
|
||||||
|
|
||||||
|
@ -145,7 +158,15 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// average node's color based on color of children
|
// average node's color based on color of children
|
||||||
|
bool nodeWasDirty = destinationNode->isDirty();
|
||||||
destinationNode->setColorFromAverageOfChildren();
|
destinationNode->setColorFromAverageOfChildren();
|
||||||
|
bool nodeIsDirty = destinationNode->isDirty();
|
||||||
|
if (nodeIsDirty) {
|
||||||
|
_isDirty = true;
|
||||||
|
}
|
||||||
|
if (!nodeWasDirty && nodeIsDirty) {
|
||||||
|
_nodesChangedFromBitstream++;
|
||||||
|
}
|
||||||
|
|
||||||
// give this destination node the child mask from the packet
|
// give this destination node the child mask from the packet
|
||||||
unsigned char childMask = *(nodeData + bytesRead);
|
unsigned char childMask = *(nodeData + bytesRead);
|
||||||
|
@ -157,9 +178,17 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode,
|
||||||
// check the exists mask to see if we have a child to traverse into
|
// check the exists mask to see if we have a child to traverse into
|
||||||
|
|
||||||
if (oneAtBit(childMask, childIndex)) {
|
if (oneAtBit(childMask, childIndex)) {
|
||||||
if (destinationNode->children[childIndex] == NULL) {
|
if (!destinationNode->children[childIndex]) {
|
||||||
// add a child at that index, if it doesn't exist
|
// add a child at that index, if it doesn't exist
|
||||||
|
bool nodeWasDirty = destinationNode->isDirty();
|
||||||
destinationNode->addChildAtIndex(childIndex);
|
destinationNode->addChildAtIndex(childIndex);
|
||||||
|
bool nodeIsDirty = destinationNode->isDirty();
|
||||||
|
if (nodeIsDirty) {
|
||||||
|
_isDirty = true;
|
||||||
|
}
|
||||||
|
if (!nodeWasDirty && nodeIsDirty) {
|
||||||
|
_nodesChangedFromBitstream++;
|
||||||
|
}
|
||||||
this->voxelsCreated++;
|
this->voxelsCreated++;
|
||||||
this->voxelsCreatedStats.updateAverage(this->voxelsCreated);
|
this->voxelsCreatedStats.updateAverage(this->voxelsCreated);
|
||||||
}
|
}
|
||||||
|
@ -180,6 +209,8 @@ void VoxelTree::readBitstreamToTree(unsigned char * bitstream, int bufferSizeByt
|
||||||
int bytesRead = 0;
|
int bytesRead = 0;
|
||||||
unsigned char* bitstreamAt = bitstream;
|
unsigned char* bitstreamAt = bitstream;
|
||||||
|
|
||||||
|
_nodesChangedFromBitstream = 0;
|
||||||
|
|
||||||
// Keep looping through the buffer calling readNodeData() this allows us to pack multiple root-relative Octal codes
|
// Keep looping through the buffer calling readNodeData() this allows us to pack multiple root-relative Octal codes
|
||||||
// into a single network packet. readNodeData() basically goes down a tree from the root, and fills things in from there
|
// into a single network packet. readNodeData() basically goes down a tree from the root, and fills things in from there
|
||||||
// if there are more bytes after that, it's assumed to be another root relative tree
|
// if there are more bytes after that, it's assumed to be another root relative tree
|
||||||
|
@ -193,6 +224,10 @@ void VoxelTree::readBitstreamToTree(unsigned char * bitstream, int bufferSizeByt
|
||||||
// Note: we need to create this node relative to root, because we're assuming that the bitstream for the initial
|
// Note: we need to create this node relative to root, because we're assuming that the bitstream for the initial
|
||||||
// octal code is always relative to root!
|
// octal code is always relative to root!
|
||||||
bitstreamRootNode = createMissingNode(rootNode, (unsigned char*) bitstreamAt);
|
bitstreamRootNode = createMissingNode(rootNode, (unsigned char*) bitstreamAt);
|
||||||
|
if (bitstreamRootNode->isDirty()) {
|
||||||
|
_isDirty = true;
|
||||||
|
_nodesChangedFromBitstream++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int octalCodeBytes = bytesRequiredForCodeLength(*bitstreamAt);
|
int octalCodeBytes = bytesRequiredForCodeLength(*bitstreamAt);
|
||||||
|
@ -403,6 +438,12 @@ void VoxelTree::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VoxelTree::createVoxel(float x, float y, float z, float s, unsigned char red, unsigned char green, unsigned char blue) {
|
||||||
|
unsigned char* voxelData = pointToVoxel(x,y,z,s,red,green,blue);
|
||||||
|
this->readCodeColorBufferToTree(voxelData);
|
||||||
|
delete voxelData;
|
||||||
|
}
|
||||||
|
|
||||||
void VoxelTree::createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer) {
|
void VoxelTree::createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer) {
|
||||||
// About the color of the sphere... we're going to make this sphere be a gradient
|
// About the color of the sphere... we're going to make this sphere be a gradient
|
||||||
// between two RGB colors. We will do the gradient along the phi spectrum
|
// between two RGB colors. We will do the gradient along the phi spectrum
|
||||||
|
@ -498,9 +539,9 @@ int VoxelTree::searchForColoredNodesRecursion(int maxSearchLevel, int& currentSe
|
||||||
// Keep track of how deep we've searched.
|
// Keep track of how deep we've searched.
|
||||||
currentSearchLevel++;
|
currentSearchLevel++;
|
||||||
|
|
||||||
// If we've reached our max Search Level, then stop searching.
|
// If we've passed our max Search Level, then stop searching. return last level searched
|
||||||
if (currentSearchLevel >= maxSearchLevel) {
|
if (currentSearchLevel > maxSearchLevel) {
|
||||||
return currentSearchLevel;
|
return currentSearchLevel-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're at a node that is out of view, then we can return, because no nodes below us will be in view!
|
// If we're at a node that is out of view, then we can return, because no nodes below us will be in view!
|
||||||
|
|
|
@ -46,6 +46,7 @@ public:
|
||||||
void reaverageVoxelColors(VoxelNode *startNode);
|
void reaverageVoxelColors(VoxelNode *startNode);
|
||||||
void loadVoxelsFile(const char* fileName, bool wantColorRandomizer);
|
void loadVoxelsFile(const char* fileName, bool wantColorRandomizer);
|
||||||
void createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer);
|
void createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer);
|
||||||
|
void createVoxel(float x, float y, float z, float s, unsigned char red, unsigned char green, unsigned char blue);
|
||||||
|
|
||||||
void recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData=NULL);
|
void recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData=NULL);
|
||||||
|
|
||||||
|
@ -55,6 +56,10 @@ public:
|
||||||
|
|
||||||
int searchForColoredNodes(int maxSearchLevel, VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag);
|
int searchForColoredNodes(int maxSearchLevel, VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag);
|
||||||
|
|
||||||
|
bool isDirty() const { return _isDirty; };
|
||||||
|
void clearDirtyBit() { _isDirty = false; };
|
||||||
|
unsigned long int getNodesChangedFromBitstream() const { return _nodesChangedFromBitstream; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel,
|
int encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel,
|
||||||
VoxelNode* node, const ViewFrustum& viewFrustum,
|
VoxelNode* node, const ViewFrustum& viewFrustum,
|
||||||
|
@ -68,6 +73,9 @@ private:
|
||||||
VoxelNode* nodeForOctalCode(VoxelNode* ancestorNode, unsigned char* needleCode, VoxelNode** parentOfFoundNode);
|
VoxelNode* nodeForOctalCode(VoxelNode* ancestorNode, unsigned char* needleCode, VoxelNode** parentOfFoundNode);
|
||||||
VoxelNode* createMissingNode(VoxelNode* lastParentNode, unsigned char* deepestCodeToCreate);
|
VoxelNode* createMissingNode(VoxelNode* lastParentNode, unsigned char* deepestCodeToCreate);
|
||||||
int readNodeData(VoxelNode *destinationNode, unsigned char* nodeData, int bufferSizeBytes);
|
int readNodeData(VoxelNode *destinationNode, unsigned char* nodeData, int bufferSizeBytes);
|
||||||
|
|
||||||
|
bool _isDirty;
|
||||||
|
unsigned long int _nodesChangedFromBitstream;
|
||||||
};
|
};
|
||||||
|
|
||||||
int boundaryDistanceForRenderLevel(unsigned int renderLevel);
|
int boundaryDistanceForRenderLevel(unsigned int renderLevel);
|
||||||
|
|
|
@ -38,15 +38,14 @@ const float DEATH_STAR_RADIUS = 4.0;
|
||||||
const float MAX_CUBE = 0.05f;
|
const float MAX_CUBE = 0.05f;
|
||||||
|
|
||||||
const int VOXEL_SEND_INTERVAL_USECS = 100 * 1000;
|
const int VOXEL_SEND_INTERVAL_USECS = 100 * 1000;
|
||||||
const int PACKETS_PER_CLIENT_PER_INTERVAL = 20;
|
int PACKETS_PER_CLIENT_PER_INTERVAL = 20;
|
||||||
|
|
||||||
const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4;
|
const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4;
|
||||||
|
|
||||||
VoxelTree randomTree;
|
VoxelTree randomTree;
|
||||||
|
|
||||||
bool wantColorRandomizer = false;
|
bool wantColorRandomizer = false;
|
||||||
bool debugViewFrustum = false;
|
bool debugVoxelSending = false;
|
||||||
bool viewFrustumCulling = true; // for now
|
|
||||||
|
|
||||||
void addSphere(VoxelTree * tree,bool random, bool wantColorRandomizer) {
|
void addSphere(VoxelTree * tree,bool random, bool wantColorRandomizer) {
|
||||||
float r = random ? randFloatInRange(0.05,0.1) : 0.25;
|
float r = random ? randFloatInRange(0.05,0.1) : 0.25;
|
||||||
|
@ -86,13 +85,13 @@ void addSphereScene(VoxelTree * tree, bool wantColorRandomizer) {
|
||||||
|
|
||||||
|
|
||||||
printf("two spheres added...\n");
|
printf("two spheres added...\n");
|
||||||
tree->createSphere(0.030625, (1.0 - 0.030625), (1.0 - 0.030625), (1.0 - 0.06125), (1.0 / (sphereBaseSize * 2)), true, true);
|
tree->createSphere(0.030625, (0.75 - 0.030625), (0.75 - 0.030625), (0.75 - 0.06125), (1.0 / (sphereBaseSize * 2)), true, true);
|
||||||
printf("three spheres added...\n");
|
printf("three spheres added...\n");
|
||||||
tree->createSphere(0.030625, (1.0 - 0.030625), (1.0 - 0.030625), 0.06125, (1.0 / (sphereBaseSize * 2)), true, true);
|
tree->createSphere(0.030625, (0.75 - 0.030625), (0.75 - 0.030625), 0.06125, (1.0 / (sphereBaseSize * 2)), true, true);
|
||||||
printf("four spheres added...\n");
|
printf("four spheres added...\n");
|
||||||
tree->createSphere(0.030625, (1.0 - 0.030625), 0.06125, (1.0 - 0.06125), (1.0 / (sphereBaseSize * 2)), true, true);
|
tree->createSphere(0.030625, (0.75 - 0.030625), 0.06125, (0.75 - 0.06125), (1.0 / (sphereBaseSize * 2)), true, true);
|
||||||
printf("five spheres added...\n");
|
printf("five spheres added...\n");
|
||||||
tree->createSphere(0.06125, 0.125, 0.125, (1.0 - 0.125), (1.0 / (sphereBaseSize * 2)), true, true);
|
tree->createSphere(0.06125, 0.125, 0.125, (0.75 - 0.125), (1.0 / (sphereBaseSize * 2)), true, true);
|
||||||
|
|
||||||
float radius = 0.0125f;
|
float radius = 0.0125f;
|
||||||
printf("6 spheres added...\n");
|
printf("6 spheres added...\n");
|
||||||
|
@ -107,6 +106,20 @@ void addSphereScene(VoxelTree * tree, bool wantColorRandomizer) {
|
||||||
tree->createSphere(radius, 0.025, radius * 5.0f, 0.25, (1.0 / 4096), true, true);
|
tree->createSphere(radius, 0.025, radius * 5.0f, 0.25, (1.0 / 4096), true, true);
|
||||||
printf("11 spheres added...\n");
|
printf("11 spheres added...\n");
|
||||||
|
|
||||||
|
float voxelSize = 0.99f/8;
|
||||||
|
printf("creating corner points...\n");
|
||||||
|
tree->createVoxel(0 , 0 , 0 , voxelSize, 255, 255 ,255);
|
||||||
|
tree->createVoxel(1.0 - voxelSize, 0 , 0 , voxelSize, 255, 0 ,0 );
|
||||||
|
tree->createVoxel(0 , 1.0 - voxelSize, 0 , voxelSize, 0 , 255 ,0 );
|
||||||
|
tree->createVoxel(0 , 0 , 1.0 - voxelSize, voxelSize, 0 , 0 ,255);
|
||||||
|
|
||||||
|
|
||||||
|
tree->createVoxel(1.0 - voxelSize, 0 , 1.0 - voxelSize, voxelSize, 255, 0 ,255);
|
||||||
|
tree->createVoxel(0 , 1.0 - voxelSize, 1.0 - voxelSize, voxelSize, 0 , 255 ,255);
|
||||||
|
tree->createVoxel(1.0 - voxelSize, 1.0 - voxelSize, 1.0 - voxelSize, voxelSize, 255, 255 ,255);
|
||||||
|
tree->createVoxel(1.0 - voxelSize, 1.0 - voxelSize, 0 , voxelSize, 255, 255 ,0 );
|
||||||
|
printf("DONE creating corner points...\n");
|
||||||
|
|
||||||
_nodeCount=0;
|
_nodeCount=0;
|
||||||
tree->recurseTreeWithOperation(countVoxelsOperation);
|
tree->recurseTreeWithOperation(countVoxelsOperation);
|
||||||
printf("Nodes after adding scene %d nodes\n", _nodeCount);
|
printf("Nodes after adding scene %d nodes\n", _nodeCount);
|
||||||
|
@ -167,8 +180,14 @@ void eraseVoxelTreeAndCleanupAgentVisitData() {
|
||||||
|
|
||||||
|
|
||||||
void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAgentData* agentData, ViewFrustum& viewFrustum) {
|
void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAgentData* agentData, ViewFrustum& viewFrustum) {
|
||||||
// If the bag is empty, fill it...
|
bool searchReset = false;
|
||||||
if (agentData->nodeBag.isEmpty()) {
|
int searchLoops = 0;
|
||||||
|
int searchLevelWas = agentData->getMaxSearchLevel();
|
||||||
|
double start = usecTimestampNow();
|
||||||
|
while (!searchReset && agentData->nodeBag.isEmpty()) {
|
||||||
|
searchLoops++;
|
||||||
|
|
||||||
|
searchLevelWas = agentData->getMaxSearchLevel();
|
||||||
int maxLevelReached = randomTree.searchForColoredNodes(agentData->getMaxSearchLevel(), randomTree.rootNode,
|
int maxLevelReached = randomTree.searchForColoredNodes(agentData->getMaxSearchLevel(), randomTree.rootNode,
|
||||||
viewFrustum, agentData->nodeBag);
|
viewFrustum, agentData->nodeBag);
|
||||||
agentData->setMaxLevelReached(maxLevelReached);
|
agentData->setMaxLevelReached(maxLevelReached);
|
||||||
|
@ -177,17 +196,38 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge
|
||||||
if (agentData->nodeBag.isEmpty()) {
|
if (agentData->nodeBag.isEmpty()) {
|
||||||
if (agentData->getMaxLevelReached() < agentData->getMaxSearchLevel()) {
|
if (agentData->getMaxLevelReached() < agentData->getMaxSearchLevel()) {
|
||||||
agentData->resetMaxSearchLevel();
|
agentData->resetMaxSearchLevel();
|
||||||
|
searchReset = true;
|
||||||
} else {
|
} else {
|
||||||
agentData->incrementMaxSearchLevel();
|
agentData->incrementMaxSearchLevel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
double end = usecTimestampNow();
|
||||||
|
double elapsedmsec = (end - start)/1000.0;
|
||||||
|
if (elapsedmsec > 100) {
|
||||||
|
if (elapsedmsec > 1000) {
|
||||||
|
double elapsedsec = (end - start)/1000000.0;
|
||||||
|
printf("WARNING! searchForColoredNodes() took %lf seconds to identify %d nodes at level %d in %d loops\n",
|
||||||
|
elapsedsec, agentData->nodeBag.count(), searchLevelWas, searchLoops);
|
||||||
|
} else {
|
||||||
|
printf("WARNING! searchForColoredNodes() took %lf milliseconds to identify %d nodes at level %d in %d loops\n",
|
||||||
|
elapsedmsec, agentData->nodeBag.count(), searchLevelWas, searchLoops);
|
||||||
|
}
|
||||||
|
} else if (::debugVoxelSending) {
|
||||||
|
printf("searchForColoredNodes() took %lf milliseconds to identify %d nodes at level %d in %d loops\n",
|
||||||
|
elapsedmsec, agentData->nodeBag.count(), searchLevelWas, searchLoops);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// If we have something in our nodeBag, then turn them into packets and send them out...
|
// If we have something in our nodeBag, then turn them into packets and send them out...
|
||||||
if (!agentData->nodeBag.isEmpty()) {
|
if (!agentData->nodeBag.isEmpty()) {
|
||||||
static unsigned char tempOutputBuffer[MAX_VOXEL_PACKET_SIZE - 1]; // save on allocs by making this static
|
static unsigned char tempOutputBuffer[MAX_VOXEL_PACKET_SIZE - 1]; // save on allocs by making this static
|
||||||
int bytesWritten = 0;
|
int bytesWritten = 0;
|
||||||
int packetsSentThisInterval = 0;
|
int packetsSentThisInterval = 0;
|
||||||
|
int truePacketsSent = 0;
|
||||||
|
int trueBytesSent = 0;
|
||||||
|
double start = usecTimestampNow();
|
||||||
|
|
||||||
while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL) {
|
while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL) {
|
||||||
if (!agentData->nodeBag.isEmpty()) {
|
if (!agentData->nodeBag.isEmpty()) {
|
||||||
VoxelNode* subTree = agentData->nodeBag.extract();
|
VoxelNode* subTree = agentData->nodeBag.extract();
|
||||||
|
@ -200,6 +240,8 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge
|
||||||
} else {
|
} else {
|
||||||
agentList->getAgentSocket().send(agent->getActiveSocket(),
|
agentList->getAgentSocket().send(agent->getActiveSocket(),
|
||||||
agentData->getPacket(), agentData->getPacketLength());
|
agentData->getPacket(), agentData->getPacketLength());
|
||||||
|
trueBytesSent += agentData->getPacketLength();
|
||||||
|
truePacketsSent++;
|
||||||
packetsSentThisInterval++;
|
packetsSentThisInterval++;
|
||||||
agentData->resetVoxelPacket();
|
agentData->resetVoxelPacket();
|
||||||
agentData->writeToPacket(&tempOutputBuffer[0], bytesWritten);
|
agentData->writeToPacket(&tempOutputBuffer[0], bytesWritten);
|
||||||
|
@ -208,12 +250,30 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge
|
||||||
if (agentData->isPacketWaiting()) {
|
if (agentData->isPacketWaiting()) {
|
||||||
agentList->getAgentSocket().send(agent->getActiveSocket(),
|
agentList->getAgentSocket().send(agent->getActiveSocket(),
|
||||||
agentData->getPacket(), agentData->getPacketLength());
|
agentData->getPacket(), agentData->getPacketLength());
|
||||||
|
trueBytesSent += agentData->getPacketLength();
|
||||||
|
truePacketsSent++;
|
||||||
agentData->resetVoxelPacket();
|
agentData->resetVoxelPacket();
|
||||||
|
|
||||||
}
|
}
|
||||||
packetsSentThisInterval = PACKETS_PER_CLIENT_PER_INTERVAL; // done for now, no nodes left
|
packetsSentThisInterval = PACKETS_PER_CLIENT_PER_INTERVAL; // done for now, no nodes left
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
double end = usecTimestampNow();
|
||||||
|
double elapsedmsec = (end - start)/1000.0;
|
||||||
|
if (elapsedmsec > 100) {
|
||||||
|
if (elapsedmsec > 1000) {
|
||||||
|
double elapsedsec = (end - start)/1000000.0;
|
||||||
|
printf("WARNING! packetLoop() took %lf seconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n",
|
||||||
|
elapsedsec, trueBytesSent, truePacketsSent, searchLevelWas, agentData->nodeBag.count());
|
||||||
|
} else {
|
||||||
|
printf("WARNING! packetLoop() took %lf milliseconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n",
|
||||||
|
elapsedmsec, trueBytesSent, truePacketsSent, searchLevelWas, agentData->nodeBag.count());
|
||||||
|
}
|
||||||
|
} else if (::debugVoxelSending) {
|
||||||
|
printf("packetLoop() took %lf milliseconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n",
|
||||||
|
elapsedmsec, trueBytesSent, truePacketsSent, searchLevelWas, agentData->nodeBag.count());
|
||||||
|
}
|
||||||
|
|
||||||
// if during this last pass, we emptied our bag, then we want to move to the next level.
|
// if during this last pass, we emptied our bag, then we want to move to the next level.
|
||||||
if (agentData->nodeBag.isEmpty()) {
|
if (agentData->nodeBag.isEmpty()) {
|
||||||
if (agentData->getMaxLevelReached() < agentData->getMaxSearchLevel()) {
|
if (agentData->getMaxLevelReached() < agentData->getMaxSearchLevel()) {
|
||||||
|
@ -296,13 +356,9 @@ int main(int argc, const char * argv[])
|
||||||
|
|
||||||
srand((unsigned)time(0));
|
srand((unsigned)time(0));
|
||||||
|
|
||||||
const char* DEBUG_VIEW_FRUSTUM = "--DebugViewFrustum";
|
const char* DEBUG_VOXEL_SENDING = "--debugVoxelSending";
|
||||||
::debugViewFrustum = cmdOptionExists(argc, argv, DEBUG_VIEW_FRUSTUM);
|
::debugVoxelSending = cmdOptionExists(argc, argv, DEBUG_VOXEL_SENDING);
|
||||||
printf("debugViewFrustum=%s\n", (::debugViewFrustum ? "yes" : "no"));
|
printf("debugVoxelSending=%s\n", (::debugVoxelSending ? "yes" : "no"));
|
||||||
|
|
||||||
const char* NO_VIEW_FRUSTUM_CULLING = "--NoViewFrustumCulling";
|
|
||||||
::viewFrustumCulling = !cmdOptionExists(argc, argv, NO_VIEW_FRUSTUM_CULLING);
|
|
||||||
printf("viewFrustumCulling=%s\n", (::viewFrustumCulling ? "yes" : "no"));
|
|
||||||
|
|
||||||
const char* WANT_COLOR_RANDOMIZER = "--wantColorRandomizer";
|
const char* WANT_COLOR_RANDOMIZER = "--wantColorRandomizer";
|
||||||
::wantColorRandomizer = cmdOptionExists(argc, argv, WANT_COLOR_RANDOMIZER);
|
::wantColorRandomizer = cmdOptionExists(argc, argv, WANT_COLOR_RANDOMIZER);
|
||||||
|
@ -316,6 +372,17 @@ int main(int argc, const char * argv[])
|
||||||
randomTree.loadVoxelsFile(voxelsFilename,wantColorRandomizer);
|
randomTree.loadVoxelsFile(voxelsFilename,wantColorRandomizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check to see if the user passed in a command line option for setting packet send rate
|
||||||
|
const char* PACKETS_PER_SECOND = "--packetsPerSecond";
|
||||||
|
const char* packetsPerSecond = getCmdOption(argc, argv, PACKETS_PER_SECOND);
|
||||||
|
if (packetsPerSecond) {
|
||||||
|
PACKETS_PER_CLIENT_PER_INTERVAL = atoi(packetsPerSecond)/10;
|
||||||
|
if (PACKETS_PER_CLIENT_PER_INTERVAL < 1) {
|
||||||
|
PACKETS_PER_CLIENT_PER_INTERVAL = 1;
|
||||||
|
}
|
||||||
|
printf("packetsPerSecond=%s PACKETS_PER_CLIENT_PER_INTERVAL=%d\n", packetsPerSecond, PACKETS_PER_CLIENT_PER_INTERVAL);
|
||||||
|
}
|
||||||
|
|
||||||
const char* ADD_RANDOM_VOXELS = "--AddRandomVoxels";
|
const char* ADD_RANDOM_VOXELS = "--AddRandomVoxels";
|
||||||
if (cmdOptionExists(argc, argv, ADD_RANDOM_VOXELS)) {
|
if (cmdOptionExists(argc, argv, ADD_RANDOM_VOXELS)) {
|
||||||
// create an octal code buffer and load it with 0 so that the recursive tree fill can give
|
// create an octal code buffer and load it with 0 so that the recursive tree fill can give
|
||||||
|
@ -380,8 +447,6 @@ int main(int argc, const char * argv[])
|
||||||
delete []vertices;
|
delete []vertices;
|
||||||
|
|
||||||
randomTree.readCodeColorBufferToTree(pVoxelData);
|
randomTree.readCodeColorBufferToTree(pVoxelData);
|
||||||
//printf("readCodeColorBufferToTree() of size=%d atByte=%d receivedBytes=%ld\n",
|
|
||||||
// voxelDataSize,atByte,receivedBytes);
|
|
||||||
// skip to next
|
// skip to next
|
||||||
pVoxelData+=voxelDataSize;
|
pVoxelData+=voxelDataSize;
|
||||||
atByte+=voxelDataSize;
|
atByte+=voxelDataSize;
|
||||||
|
|
Loading…
Reference in a new issue