Added wantResIn and wantColor feature between client and server

- Updated Voxel Server to support non-res-in version of voxel distribution
- Updated agent data to allow client to send desired res-in and color state
- added menu items to client debug menu to toggle wantResIn and wantColor
This commit is contained in:
ZappoMan 2013-05-13 15:02:46 -07:00
parent dd4303800d
commit b196227385
7 changed files with 180 additions and 28 deletions

View file

@ -104,6 +104,13 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
_tree->readBitstreamToTree(voxelData, numBytes - 1);
}
break;
case PACKET_HEADER_VOXEL_DATA_MONOCHROME:
{
PerformanceWarning warn(_renderWarningsOn, "readBitstreamToTree()");
// ask the VoxelTree to read the MONOCHROME bitstream into the tree
_tree->readBitstreamToTree(voxelData, numBytes - 1, false);
}
break;
case PACKET_HEADER_ERASE_VOXEL:
// ask the tree to read the "remove" bitstream
_tree->processRemoveVoxelBitstream(sourceBuffer, numBytes);

View file

@ -163,6 +163,8 @@ bool paintOn = false; // Whether to paint voxels as you fly aroun
VoxelDetail paintingVoxel; // The voxel we're painting if we're painting
unsigned char dominantColor = 0; // The dominant color of the voxel we're painting
bool perfStatsOn = false; // Do we want to display perfStats?
bool wantMonochrome = false; // ask server to send us in monochrome
bool wantResIn = false; // ask server to res in
bool logOn = true; // Whether to show on-screen log
@ -1278,6 +1280,22 @@ int setRenderWarnings(int state) {
return value;
}
int setWantResIn(int state) {
int value = setValue(state, &::wantResIn);
if (state == MENU_ROW_PICKED) {
::myAvatar.setWantResIn(::wantResIn);
}
return value;
}
int setWantMonochrome(int state) {
int value = setValue(state, &::wantMonochrome);
if (state == MENU_ROW_PICKED) {
::myAvatar.setWantColor(!::wantMonochrome);
}
return value;
}
int setDisplayFrustum(int state) {
return setValue(state, &::frustumOn);
}
@ -1370,6 +1388,8 @@ int doFalseColorizeInView(int state) {
return state;
}
const char* modeAll = " - All ";
const char* modeVectors = " - Vectors ";
const char* modePlanes = " - Planes ";
@ -1441,6 +1461,8 @@ void initMenu() {
menuColumnDebug->addRow("FALSE Color Voxel Out of View", doFalseColorizeInView);
menuColumnDebug->addRow("Show TRUE Colors", doTrueVoxelColors);
menuColumnDebug->addRow("Calculate Tree Stats", doTreeStats);
menuColumnDebug->addRow("Wants Res-In", setWantResIn);
menuColumnDebug->addRow("Wants Monochrome", setWantMonochrome);
}
void testPointToVoxel() {
@ -1728,6 +1750,7 @@ void* networkReceive(void* args) {
myAvatar.processTransmitterData(incomingPacket, bytesReceived);
break;
case PACKET_HEADER_VOXEL_DATA:
case PACKET_HEADER_VOXEL_DATA_MONOCHROME:
case PACKET_HEADER_Z_COMMAND:
case PACKET_HEADER_ERASE_VOXEL:
voxels.parseData(incomingPacket, bytesReceived);

View file

@ -34,29 +34,6 @@ int unpackFloatAngleFromTwoByte(uint16_t* byteAnglePointer, float* destinationPo
return sizeof(uint16_t);
}
AvatarData::AvatarData() :
_handPosition(0,0,0),
_bodyYaw(-90.0),
_bodyPitch(0.0),
_bodyRoll(0.0),
_headYaw(0),
_headPitch(0),
_headRoll(0),
_headLeanSideways(0),
_headLeanForward(0),
_handState(0),
_cameraPosition(0,0,0),
_cameraDirection(0,0,0),
_cameraUp(0,0,0),
_cameraRight(0,0,0),
_cameraFov(0.0f),
_cameraAspectRatio(0.0f),
_cameraNearClip(0.0f),
_cameraFarClip(0.0f),
_keyState(NO_KEY_DOWN) {
}
AvatarData::~AvatarData() {
}
@ -130,6 +107,10 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
memcpy(destinationBuffer, _chatMessage.data(), _chatMessage.size() * sizeof(char));
destinationBuffer += _chatMessage.size() * sizeof(char);
// voxel sending features...
*destinationBuffer++ = _wantResIn;
*destinationBuffer++ = _wantColor;
return destinationBuffer - bufferStart;
}
@ -201,6 +182,10 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
int chatMessageSize = *sourceBuffer++;
_chatMessage = string((char*)sourceBuffer, chatMessageSize);
sourceBuffer += chatMessageSize * sizeof(char);
// voxel sending features...
_wantResIn = (bool)*sourceBuffer++;
_wantColor = (bool)*sourceBuffer++;
return sourceBuffer - startPosition;
}

View file

@ -24,7 +24,30 @@ enum KeyState
class AvatarData : public AgentData {
public:
AvatarData();
AvatarData() :
_handPosition(0,0,0),
_bodyYaw(-90.0),
_bodyPitch(0.0),
_bodyRoll(0.0),
_headYaw(0),
_headPitch(0),
_headRoll(0),
_headLeanSideways(0),
_headLeanForward(0),
_handState(0),
_cameraPosition(0,0,0),
_cameraDirection(0,0,0),
_cameraUp(0,0,0),
_cameraRight(0,0,0),
_cameraFov(0.0f),
_cameraAspectRatio(0.0f),
_cameraNearClip(0.0f),
_cameraFarClip(0.0f),
_keyState(NO_KEY_DOWN),
_wantResIn(false),
_wantColor(true) { };
~AvatarData();
AvatarData* clone() const;
@ -96,6 +119,12 @@ public:
// chat message
void setChatMessage(const std::string& msg) { _chatMessage = msg; }
const std::string& chatMessage () const { return _chatMessage; }
// related to Voxel Sending strategies
bool getWantResIn() const { return _wantResIn; }
bool getWantColor() const { return _wantColor; }
void setWantResIn(bool wantResIn) { _wantResIn = wantResIn; }
void setWantColor(bool wantColor) { _wantColor = wantColor; }
protected:
glm::vec3 _position;
@ -137,6 +166,9 @@ protected:
// chat message
std::string _chatMessage;
bool _wantResIn;
bool _wantColor;
};
#endif /* defined(__hifi__AvatarData__) */

View file

@ -23,6 +23,7 @@ const PACKET_HEADER PACKET_HEADER_INJECT_AUDIO = 'I';
const PACKET_HEADER PACKET_HEADER_SET_VOXEL = 'S';
const PACKET_HEADER PACKET_HEADER_ERASE_VOXEL = 'E';
const PACKET_HEADER PACKET_HEADER_VOXEL_DATA = 'V';
const PACKET_HEADER PACKET_HEADER_VOXEL_DATA_MONOCHROME = 'v';
const PACKET_HEADER PACKET_HEADER_BULK_AVATAR_DATA = 'X';
const PACKET_HEADER PACKET_HEADER_TRANSMITTER_DATA = 't';
const PACKET_HEADER PACKET_HEADER_ENVIRONMENT_DATA = 'e';

View file

@ -25,7 +25,7 @@ void VoxelAgentData::init() {
}
void VoxelAgentData::resetVoxelPacket() {
_voxelPacket[0] = PACKET_HEADER_VOXEL_DATA;
_voxelPacket[0] = getWantColor() ? PACKET_HEADER_VOXEL_DATA : PACKET_HEADER_VOXEL_DATA_MONOCHROME;
_voxelPacketAt = &_voxelPacket[1];
_voxelPacketAvailableBytes = MAX_VOXEL_PACKET_SIZE - 1;
_voxelPacketWaiting = false;

View file

@ -104,7 +104,13 @@ void eraseVoxelTreeAndCleanupAgentVisitData() {
}
void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAgentData* agentData, ViewFrustum& viewFrustum) {
// Version of voxel distributor that sends each LOD level at a time
void resInVoxelDistributor(AgentList* agentList,
AgentList::iterator& agent,
VoxelAgentData* agentData,
ViewFrustum& viewFrustum) {
printf("resInVoxelDistributor()\n");
bool searchReset = false;
int searchLoops = 0;
int searchLevelWas = agentData->getMaxSearchLevel();
@ -158,7 +164,8 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge
VoxelNode* subTree = agentData->nodeBag.extract();
bytesWritten = randomTree.encodeTreeBitstream(agentData->getMaxSearchLevel(), subTree,
&tempOutputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1,
agentData->nodeBag, &viewFrustum);
agentData->nodeBag, &viewFrustum,
agentData->getWantColor());
if (agentData->getAvailable() >= bytesWritten) {
agentData->writeToPacket(&tempOutputBuffer[0], bytesWritten);
@ -216,6 +223,99 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge
}
}
// Version of voxel distributor that sends each LOD level at a time
void deepestLevelVoxelDistributor(AgentList* agentList,
AgentList::iterator& agent,
VoxelAgentData* agentData,
ViewFrustum& viewFrustum) {
printf("deepestLevelVoxelDistributor()\n");
int maxLevelReached = 0;
double start = usecTimestampNow();
if (agentData->nodeBag.isEmpty()) {
maxLevelReached = randomTree.searchForColoredNodes(INT_MAX, randomTree.rootNode, viewFrustum, agentData->nodeBag);
}
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\n",
elapsedsec, agentData->nodeBag.count(), maxLevelReached);
} else {
printf("WARNING! searchForColoredNodes() took %lf milliseconds to identify %d nodes at level %d\n",
elapsedmsec, agentData->nodeBag.count(), maxLevelReached);
}
} else if (::debugVoxelSending) {
printf("searchForColoredNodes() took %lf milliseconds to identify %d nodes at level %d\n",
elapsedmsec, agentData->nodeBag.count(), maxLevelReached);
}
// If we have something in our nodeBag, then turn them into packets and send them out...
if (!agentData->nodeBag.isEmpty()) {
static unsigned char tempOutputBuffer[MAX_VOXEL_PACKET_SIZE - 1]; // save on allocs by making this static
int bytesWritten = 0;
int packetsSentThisInterval = 0;
int truePacketsSent = 0;
int trueBytesSent = 0;
double start = usecTimestampNow();
while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL - 1) {
if (!agentData->nodeBag.isEmpty()) {
VoxelNode* subTree = agentData->nodeBag.extract();
bytesWritten = randomTree.encodeTreeBitstream(INT_MAX, subTree,
&tempOutputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1,
agentData->nodeBag, &viewFrustum,
agentData->getWantColor());
if (agentData->getAvailable() >= bytesWritten) {
agentData->writeToPacket(&tempOutputBuffer[0], bytesWritten);
} else {
agentList->getAgentSocket().send(agent->getActiveSocket(),
agentData->getPacket(), agentData->getPacketLength());
trueBytesSent += agentData->getPacketLength();
truePacketsSent++;
packetsSentThisInterval++;
agentData->resetVoxelPacket();
agentData->writeToPacket(&tempOutputBuffer[0], bytesWritten);
}
} else {
if (agentData->isPacketWaiting()) {
agentList->getAgentSocket().send(agent->getActiveSocket(),
agentData->getPacket(), agentData->getPacketLength());
trueBytesSent += agentData->getPacketLength();
truePacketsSent++;
agentData->resetVoxelPacket();
}
packetsSentThisInterval = PACKETS_PER_CLIENT_PER_INTERVAL; // done for now, no nodes left
}
}
// send the environment packet
int envPacketLength = environmentData.getBroadcastData(tempOutputBuffer);
agentList->getAgentSocket().send(agent->getActiveSocket(), tempOutputBuffer, envPacketLength);
trueBytesSent += envPacketLength;
truePacketsSent++;
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 %d nodes still to send\n",
elapsedsec, trueBytesSent, truePacketsSent, agentData->nodeBag.count());
} else {
printf("WARNING! packetLoop() took %lf milliseconds to generate %d bytes in %d packets, %d nodes still to send\n",
elapsedmsec, trueBytesSent, truePacketsSent, agentData->nodeBag.count());
}
} else if (::debugVoxelSending) {
printf("packetLoop() took %lf milliseconds to generate %d bytes in %d packets, %d nodes still to send\n",
elapsedmsec, trueBytesSent, truePacketsSent, agentData->nodeBag.count());
}
}
}
void persistVoxelsWhenDirty() {
// check the dirty bit and persist here...
if (::wantVoxelPersist && ::randomTree.isDirty()) {
@ -253,7 +353,11 @@ void *distributeVoxelsToListeners(void *args) {
viewFrustum.calculate();
voxelDistributor(agentList, agent, agentData, viewFrustum);
if (agentData->getWantResIn()) {
resInVoxelDistributor(agentList, agent, agentData, viewFrustum);
} else {
deepestLevelVoxelDistributor(agentList, agent, agentData, viewFrustum);
}
}
}