mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 05:58:35 +02:00
added support for command line option to use OLD or NEW voxel distribution schemes
- moved new voxel distribution strategy to helper function - added back old technique - added "--newVoxelDistributor" command line option - fixed crashing bug for derefrencing NULL pointer in case where server is started which interface agents already in the domain. Basically agentData may not yet be setup properly - added proper cleanup support to node bag in case where voxel tree is erased - first cut at new version of sphere scene, we will make it richer in case of new distribution - bumped packets per interval to 5
This commit is contained in:
parent
82c5c3706a
commit
2fb172f3db
1 changed files with 157 additions and 121 deletions
|
@ -41,7 +41,7 @@ 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 = 2;
|
const int PACKETS_PER_CLIENT_PER_INTERVAL = 5;
|
||||||
|
|
||||||
const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4;
|
const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4;
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@ VoxelTree randomTree;
|
||||||
bool wantColorRandomizer = false;
|
bool wantColorRandomizer = false;
|
||||||
bool debugViewFrustum = false;
|
bool debugViewFrustum = false;
|
||||||
bool viewFrustumCulling = true; // for now
|
bool viewFrustumCulling = true; // for now
|
||||||
|
bool newVoxelDistributor = false; // 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;
|
||||||
|
@ -72,12 +73,25 @@ void addSphere(VoxelTree * tree,bool random, bool wantColorRandomizer) {
|
||||||
|
|
||||||
void addSphereScene(VoxelTree * tree, bool wantColorRandomizer) {
|
void addSphereScene(VoxelTree * tree, bool wantColorRandomizer) {
|
||||||
printf("adding scene of spheres...\n");
|
printf("adding scene of spheres...\n");
|
||||||
tree->createSphere(0.25,0.5,0.5,0.5,(1.0/256),true,wantColorRandomizer);
|
|
||||||
tree->createSphere(0.030625,0.5,0.5,(0.25-0.06125),(1.0/512),true,true);
|
// The old voxel distributor has a hard time with smaller voxels and more
|
||||||
tree->createSphere(0.030625,(1.0-0.030625),(1.0-0.030625),(1.0-0.06125),(1.0/512),true,true);
|
// complex scenes... so if we're using the old distributor make our scene
|
||||||
tree->createSphere(0.030625,(1.0-0.030625),(1.0-0.030625),0.06125,(1.0/512),true,true);
|
// simple with larger sized voxels
|
||||||
tree->createSphere(0.030625,(1.0-0.030625),0.06125,(1.0-0.06125),(1.0/512),true,true);
|
//int sphereBaseSize = ::newVoxelDistributor ? 512 : 256;
|
||||||
tree->createSphere(0.06125,0.125,0.125,(1.0-0.125),(1.0/512),true,true);
|
int sphereBaseSize = 256;
|
||||||
|
|
||||||
|
tree->createSphere(0.25,0.5,0.5,0.5,(1.0/sphereBaseSize),true,wantColorRandomizer);
|
||||||
|
printf("one sphere added...\n");
|
||||||
|
tree->createSphere(0.030625,0.5,0.5,(0.25-0.06125),(1.0/(sphereBaseSize*2)),true,true);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
printf("five spheres added...\n");
|
||||||
|
tree->createSphere(0.06125,0.125,0.125,(1.0-0.125),(1.0/(sphereBaseSize*2)),true,true);
|
||||||
|
printf("DONE adding scene of spheres...\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -127,15 +141,96 @@ void eraseVoxelTreeAndCleanupAgentVisitData() {
|
||||||
|
|
||||||
//printf("eraseVoxelTreeAndCleanupAgentVisitData() agent[%d]\n",i);
|
//printf("eraseVoxelTreeAndCleanupAgentVisitData() agent[%d]\n",i);
|
||||||
|
|
||||||
VoxelAgentData *agentData = (VoxelAgentData *)agent->getLinkedData();
|
VoxelAgentData* agentData = (VoxelAgentData *)agent->getLinkedData();
|
||||||
|
|
||||||
// clean up the agent visit data
|
if (agentData) {
|
||||||
delete agentData->rootMarkerNode;
|
// clean up the agent visit data
|
||||||
agentData->rootMarkerNode = new MarkerNode();
|
agentData->nodeBag.deleteAll();
|
||||||
|
// old way
|
||||||
|
delete agentData->rootMarkerNode;
|
||||||
|
agentData->rootMarkerNode = new MarkerNode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void* distributeVoxelsToListeners(void *args) {
|
|
||||||
|
void newDistributeHelper(AgentList* agentList, AgentList::iterator& agent, VoxelAgentData* agentData, ViewFrustum& viewFrustum) {
|
||||||
|
// If we don't have nodes already in our agent's node bag, then fill the node bag
|
||||||
|
if (agentData->nodeBag.isEmpty()) {
|
||||||
|
|
||||||
|
printf("agent calling searchForColoredNodes()\n");
|
||||||
|
randomTree.searchForColoredNodes(randomTree.rootNode, viewFrustum, agentData->nodeBag);
|
||||||
|
|
||||||
|
// this would add the whole tree
|
||||||
|
//agentData->nodeBag.insert(randomTree.rootNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have something in our nodeBag, then turn them into packets and send them out...
|
||||||
|
if (!agentData->nodeBag.isEmpty()) {
|
||||||
|
unsigned char* tempOutputBuffer = new unsigned char[MAX_VOXEL_PACKET_SIZE-1]; // save 1 for "V" in final
|
||||||
|
int bytesWritten = 0;
|
||||||
|
|
||||||
|
// NOTE: we can assume the voxelPacket has already been set up with a "V"
|
||||||
|
int packetsSentThisInterval = 0;
|
||||||
|
|
||||||
|
while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL) {
|
||||||
|
if (!agentData->nodeBag.isEmpty()) {
|
||||||
|
VoxelNode* subTree = agentData->nodeBag.extract();
|
||||||
|
|
||||||
|
// Only let this guy create at largest packets equal to the amount of space we have left in our final???
|
||||||
|
// Or let it create the largest possible size (minus 1 for the "V")
|
||||||
|
bytesWritten = randomTree.encodeTreeBitstream(subTree, viewFrustum,
|
||||||
|
tempOutputBuffer, MAX_VOXEL_PACKET_SIZE-1, agentData->nodeBag);
|
||||||
|
|
||||||
|
// if we have room in our final packet, add this buffer to the final packet
|
||||||
|
if (agentData->getAvailable() >= bytesWritten) {
|
||||||
|
agentData->writeToPacket(tempOutputBuffer, bytesWritten);
|
||||||
|
} else {
|
||||||
|
// otherwise "send" the packet because it's as full as we can make it for now
|
||||||
|
agentList->getAgentSocket().send(agent->getActiveSocket(),
|
||||||
|
agentData->getPacket(), agentData->getPacketLength());
|
||||||
|
|
||||||
|
// keep track that we sent it
|
||||||
|
packetsSentThisInterval++;
|
||||||
|
|
||||||
|
//printf("main loop send... this packetSize=%d packetsSentThisInterval=%d \n",
|
||||||
|
// agentData->getPacketLength(), packetsSentThisInterval);
|
||||||
|
//outputBufferBits((unsigned char*)agentData->getPacket(), agentData->getPacketLength(), true);
|
||||||
|
|
||||||
|
// reset our finalOutputBuffer (keep the 'V')
|
||||||
|
agentData->resetVoxelPacket();
|
||||||
|
|
||||||
|
// we also need to stick the last created partial packet in here!!
|
||||||
|
agentData->writeToPacket(tempOutputBuffer, bytesWritten);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// we're here, if there are no more nodes in our bag waiting to be sent.
|
||||||
|
// If we have a partial packet ready, then send it...
|
||||||
|
if (agentData->isPacketWaiting()) {
|
||||||
|
agentList->getAgentSocket().send(agent->getActiveSocket(),
|
||||||
|
agentData->getPacket(), agentData->getPacketLength());
|
||||||
|
|
||||||
|
//printf("isPacketWaiting() send... this packetSize=%d packetsSentThisInterval=%d \n",
|
||||||
|
// agentData->getPacketLength(), packetsSentThisInterval);
|
||||||
|
//outputBufferBits((unsigned char*)agentData->getPacket(), agentData->getPacketLength(), true);
|
||||||
|
|
||||||
|
// reset our finalOutputBuffer (keep the 'V')
|
||||||
|
agentData->resetVoxelPacket();
|
||||||
|
}
|
||||||
|
|
||||||
|
// and we're done now for this interval, because we know we have not nodes in our
|
||||||
|
// bag, and we just sent the last waiting packet if we had one, so tell ourselves
|
||||||
|
// we done for the interval
|
||||||
|
packetsSentThisInterval = PACKETS_PER_CLIENT_PER_INTERVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// end
|
||||||
|
delete[] tempOutputBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *distributeVoxelsToListeners(void *args) {
|
||||||
|
|
||||||
AgentList* agentList = AgentList::getInstance();
|
AgentList* agentList = AgentList::getInstance();
|
||||||
timeval lastSendTime;
|
timeval lastSendTime;
|
||||||
|
@ -145,6 +240,9 @@ void* distributeVoxelsToListeners(void *args) {
|
||||||
|
|
||||||
int totalBytesSent;
|
int totalBytesSent;
|
||||||
|
|
||||||
|
unsigned char *voxelPacket = new unsigned char[MAX_VOXEL_PACKET_SIZE];
|
||||||
|
unsigned char *voxelPacketEnd;
|
||||||
|
|
||||||
float treeRoot[3] = {0, 0, 0};
|
float treeRoot[3] = {0, 0, 0};
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -152,10 +250,10 @@ void* distributeVoxelsToListeners(void *args) {
|
||||||
|
|
||||||
// enumerate the agents to send 3 packets to each
|
// enumerate the agents to send 3 packets to each
|
||||||
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
|
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
|
||||||
VoxelAgentData* agentData = (VoxelAgentData*)agent->getLinkedData();
|
VoxelAgentData* agentData = (VoxelAgentData *)agent->getLinkedData();
|
||||||
|
|
||||||
// If we don't have nodes already in our agent's node bag, then fill the node bag
|
// Sometimes the agent data has not yet been linked, in which case we can't really do anything
|
||||||
if (agentData->nodeBag.isEmpty()) {
|
if (agentData) {
|
||||||
ViewFrustum viewFrustum;
|
ViewFrustum viewFrustum;
|
||||||
// get position and orientation details from the camera
|
// get position and orientation details from the camera
|
||||||
viewFrustum.setPosition(agentData->getCameraPosition());
|
viewFrustum.setPosition(agentData->getCameraPosition());
|
||||||
|
@ -169,114 +267,48 @@ void* distributeVoxelsToListeners(void *args) {
|
||||||
|
|
||||||
viewFrustum.calculate();
|
viewFrustum.calculate();
|
||||||
|
|
||||||
randomTree.searchForColoredNodes(randomTree.rootNode, viewFrustum, agentData->nodeBag);
|
if (::newVoxelDistributor) {
|
||||||
}
|
newDistributeHelper(agentList, agent, agentData, viewFrustum);
|
||||||
|
} else {
|
||||||
|
stopOctal = NULL;
|
||||||
|
packetCount = 0;
|
||||||
|
totalBytesSent = 0;
|
||||||
|
randomTree.leavesWrittenToBitstream = 0;
|
||||||
|
|
||||||
// If we have something in our nodeBag, then turn them into packets and send them out...
|
for (int j = 0; j < PACKETS_PER_CLIENT_PER_INTERVAL; j++) {
|
||||||
if (!agentData->nodeBag.isEmpty()) {
|
voxelPacketEnd = voxelPacket;
|
||||||
|
stopOctal = randomTree.loadBitstreamBuffer(voxelPacketEnd,
|
||||||
unsigned char* tempOutputBuffer = new unsigned char[MAX_VOXEL_PACKET_SIZE-1]; // save 1 for "V" in final
|
randomTree.rootNode,
|
||||||
int bytesWritten = 0;
|
agentData->rootMarkerNode,
|
||||||
|
agentData->getPosition(),
|
||||||
// NOTE: we can assume the voxelPacket has already been set up with a "V"
|
treeRoot,
|
||||||
|
viewFrustum,
|
||||||
int packetsSentThisInterval = 0;
|
::viewFrustumCulling,
|
||||||
|
stopOctal);
|
||||||
while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL) {
|
|
||||||
|
agentList->getAgentSocket().send(agent->getActiveSocket(), voxelPacket, voxelPacketEnd - voxelPacket);
|
||||||
if (!agentData->nodeBag.isEmpty()) {
|
|
||||||
|
packetCount++;
|
||||||
VoxelNode* subTree = agentData->nodeBag.extract();
|
totalBytesSent += voxelPacketEnd - voxelPacket;
|
||||||
|
|
||||||
// Only let this guy create at largest packets equal to the amount of space we have left in our final???
|
// XXXBHG Hack Attack: This is temporary code to help debug an issue.
|
||||||
// Or let it create the largest possible size (minus 1 for the "V")
|
// Normally we use this break to prevent resending voxels that an agent has
|
||||||
bytesWritten = randomTree.encodeTreeBitstream(subTree, viewFrustum,
|
// already visited. But since we might be modifying the voxel tree we might
|
||||||
tempOutputBuffer, MAX_VOXEL_PACKET_SIZE-1, agentData->nodeBag);
|
// want to always send. This is a hack to test the behavior
|
||||||
|
bool alwaysSend = true;
|
||||||
//printf("this tree size=%d\n", bytesWritten);
|
if (!alwaysSend && agentData->rootMarkerNode->childrenVisitedMask == 255) {
|
||||||
|
break;
|
||||||
// if we have room in our final packet, add this buffer to the final packet
|
|
||||||
if (agentData->getAvailable() >= bytesWritten) {
|
|
||||||
agentData->writeToPacket(tempOutputBuffer, bytesWritten);
|
|
||||||
} else {
|
|
||||||
// otherwise "send" the packet because it's as full as we can make it for now
|
|
||||||
|
|
||||||
//outputBufferBits(agentData->getPacket(), agentData->getPacketLength(), true);
|
|
||||||
agentList->getAgentSocket().send(thisAgent->getActiveSocket(),
|
|
||||||
agentData->getPacket(), agentData->getPacketLength());
|
|
||||||
|
|
||||||
// keep track that we sent it
|
|
||||||
packetsSentThisInterval++;
|
|
||||||
|
|
||||||
// reset our finalOutputBuffer (keep the 'V')
|
|
||||||
agentData->resetVoxelPacket();
|
|
||||||
|
|
||||||
// we also need to stick the last created partial packet in here!!
|
|
||||||
agentData->writeToPacket(tempOutputBuffer, bytesWritten);
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
// we're here, if there are no more nodes in our bag waiting to be sent.
|
|
||||||
|
// for any agent that has a root marker node with 8 visited children
|
||||||
// If we have a partial packet ready, then send it...
|
// recursively delete its marker nodes so we can revisit
|
||||||
if (agentData->isPacketWaiting()) {
|
if (agentData->rootMarkerNode->childrenVisitedMask == 255) {
|
||||||
//outputBufferBits(agentData->getPacket(), agentData->getPacketLength(), true);
|
delete agentData->rootMarkerNode;
|
||||||
agentList->getAgentSocket().send(thisAgent->getActiveSocket(),
|
agentData->rootMarkerNode = new MarkerNode();
|
||||||
agentData->getPacket(), agentData->getPacketLength());
|
|
||||||
}
|
|
||||||
|
|
||||||
// and we're done now for this interval, because we know we have not nodes in our
|
|
||||||
// bag, and we just sent the last waiting packet if we had one, so tell ourselves
|
|
||||||
// we done for the interval
|
|
||||||
packetsSentThisInterval = PACKETS_PER_CLIENT_PER_INTERVAL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// end
|
|
||||||
delete[] tempOutputBuffer;
|
|
||||||
}
|
}
|
||||||
/***
|
|
||||||
|
|
||||||
unsigned char *voxelPacket = new unsigned char[MAX_VOXEL_PACKET_SIZE];
|
|
||||||
unsigned char *voxelPacketEnd;
|
|
||||||
|
|
||||||
stopOctal = NULL;
|
|
||||||
packetCount = 0;
|
|
||||||
totalBytesSent = 0;
|
|
||||||
randomTree.leavesWrittenToBitstream = 0;
|
|
||||||
|
|
||||||
for (int j = 0; j < PACKETS_PER_CLIENT_PER_INTERVAL; j++) {
|
|
||||||
voxelPacketEnd = voxelPacket;
|
|
||||||
stopOctal = randomTree.loadBitstreamBuffer(voxelPacketEnd,
|
|
||||||
randomTree.rootNode,
|
|
||||||
agentData->rootMarkerNode,
|
|
||||||
agentData->getPosition(),
|
|
||||||
treeRoot,
|
|
||||||
viewFrustum,
|
|
||||||
::viewFrustumCulling,
|
|
||||||
stopOctal);
|
|
||||||
|
|
||||||
agentList->getAgentSocket().send(thisAgent->getActiveSocket(), voxelPacket, voxelPacketEnd - voxelPacket);
|
|
||||||
|
|
||||||
packetCount++;
|
|
||||||
totalBytesSent += voxelPacketEnd - voxelPacket;
|
|
||||||
|
|
||||||
// XXXBHG Hack Attack: This is temporary code to help debug an issue.
|
|
||||||
// Normally we use this break to prevent resending voxels that an agent has
|
|
||||||
// already visited. But since we might be modifying the voxel tree we might
|
|
||||||
// want to always send. This is a hack to test the behavior
|
|
||||||
bool alwaysSend = true;
|
|
||||||
if (!alwaysSend && agentData->rootMarkerNode->childrenVisitedMask == 255) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// for any agent that has a root marker node with 8 visited children
|
|
||||||
// recursively delete its marker nodes so we can revisit
|
|
||||||
if (agentData->rootMarkerNode->childrenVisitedMask == 255) {
|
|
||||||
delete agentData->rootMarkerNode;
|
|
||||||
agentData->rootMarkerNode = new MarkerNode();
|
|
||||||
}
|
|
||||||
***/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// dynamically sleep until we need to fire off the next set of voxels
|
// dynamically sleep until we need to fire off the next set of voxels
|
||||||
|
@ -327,10 +359,14 @@ int main(int argc, const char * argv[])
|
||||||
::viewFrustumCulling = !cmdOptionExists(argc, argv, NO_VIEW_FRUSTUM_CULLING);
|
::viewFrustumCulling = !cmdOptionExists(argc, argv, NO_VIEW_FRUSTUM_CULLING);
|
||||||
printf("viewFrustumCulling=%s\n", (::viewFrustumCulling ? "yes" : "no"));
|
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);
|
||||||
printf("wantColorRandomizer=%s\n", (::wantColorRandomizer ? "yes" : "no"));
|
printf("wantColorRandomizer=%s\n", (::wantColorRandomizer ? "yes" : "no"));
|
||||||
|
|
||||||
|
const char* NEW_VOXEL_DISTRIBUTOR = "--newVoxelDistributor";
|
||||||
|
::newVoxelDistributor = cmdOptionExists(argc, argv, NEW_VOXEL_DISTRIBUTOR);
|
||||||
|
printf("newVoxelDistributor=%s\n", (::newVoxelDistributor ? "yes" : "no"));
|
||||||
|
|
||||||
// Check to see if the user passed in a command line option for loading a local
|
// Check to see if the user passed in a command line option for loading a local
|
||||||
// Voxel File. If so, load it now.
|
// Voxel File. If so, load it now.
|
||||||
const char* INPUT_FILE = "-i";
|
const char* INPUT_FILE = "-i";
|
||||||
|
|
Loading…
Reference in a new issue