mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 07:37:31 +02:00
Merge branch 'master' of https://github.com/worklist/hifi into occlusion_culling
This commit is contained in:
commit
c26e39764a
33 changed files with 487 additions and 338 deletions
|
@ -48,11 +48,11 @@ bool wantLocalDomain = false;
|
||||||
unsigned long packetsSent = 0;
|
unsigned long packetsSent = 0;
|
||||||
unsigned long bytesSent = 0;
|
unsigned long bytesSent = 0;
|
||||||
|
|
||||||
static void sendVoxelEditMessage(PACKET_HEADER header, VoxelDetail& detail) {
|
static void sendVoxelEditMessage(PACKET_TYPE type, VoxelDetail& detail) {
|
||||||
unsigned char* bufferOut;
|
unsigned char* bufferOut;
|
||||||
int sizeOut;
|
int sizeOut;
|
||||||
|
|
||||||
if (createVoxelEditMessage(header, 0, 1, &detail, bufferOut, sizeOut)){
|
if (createVoxelEditMessage(type, 0, 1, &detail, bufferOut, sizeOut)){
|
||||||
|
|
||||||
::packetsSent++;
|
::packetsSent++;
|
||||||
::bytesSent += sizeOut;
|
::bytesSent += sizeOut;
|
||||||
|
@ -161,7 +161,7 @@ static void renderMovingBug() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// send the "erase message" first...
|
// send the "erase message" first...
|
||||||
PACKET_HEADER message = PACKET_HEADER_ERASE_VOXEL;
|
PACKET_TYPE message = PACKET_TYPE_ERASE_VOXEL;
|
||||||
if (createVoxelEditMessage(message, 0, VOXELS_PER_BUG, (VoxelDetail*)&details, bufferOut, sizeOut)){
|
if (createVoxelEditMessage(message, 0, VOXELS_PER_BUG, (VoxelDetail*)&details, bufferOut, sizeOut)){
|
||||||
|
|
||||||
::packetsSent++;
|
::packetsSent++;
|
||||||
|
@ -231,7 +231,7 @@ static void renderMovingBug() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// send the "create message" ...
|
// send the "create message" ...
|
||||||
message = PACKET_HEADER_SET_VOXEL_DESTRUCTIVE;
|
message = PACKET_TYPE_SET_VOXEL_DESTRUCTIVE;
|
||||||
if (createVoxelEditMessage(message, 0, VOXELS_PER_BUG, (VoxelDetail*)&details, bufferOut, sizeOut)){
|
if (createVoxelEditMessage(message, 0, VOXELS_PER_BUG, (VoxelDetail*)&details, bufferOut, sizeOut)){
|
||||||
|
|
||||||
::packetsSent++;
|
::packetsSent++;
|
||||||
|
@ -276,7 +276,7 @@ static void sendVoxelBlinkMessage() {
|
||||||
detail.green = 0 * ::intensity;
|
detail.green = 0 * ::intensity;
|
||||||
detail.blue = 0 * ::intensity;
|
detail.blue = 0 * ::intensity;
|
||||||
|
|
||||||
PACKET_HEADER message = PACKET_HEADER_SET_VOXEL_DESTRUCTIVE;
|
PACKET_TYPE message = PACKET_TYPE_SET_VOXEL_DESTRUCTIVE;
|
||||||
|
|
||||||
sendVoxelEditMessage(message, detail);
|
sendVoxelEditMessage(message, detail);
|
||||||
}
|
}
|
||||||
|
@ -293,7 +293,7 @@ unsigned char onColor[3] = { 0, 255, 255 };
|
||||||
const float STRING_OF_LIGHTS_SIZE = 0.125f / TREE_SCALE; // approximately 1/8th meter
|
const float STRING_OF_LIGHTS_SIZE = 0.125f / TREE_SCALE; // approximately 1/8th meter
|
||||||
|
|
||||||
static void sendBlinkingStringOfLights() {
|
static void sendBlinkingStringOfLights() {
|
||||||
PACKET_HEADER message = PACKET_HEADER_SET_VOXEL_DESTRUCTIVE; // we're a bully!
|
PACKET_TYPE message = PACKET_TYPE_SET_VOXEL_DESTRUCTIVE; // we're a bully!
|
||||||
float lightScale = STRING_OF_LIGHTS_SIZE;
|
float lightScale = STRING_OF_LIGHTS_SIZE;
|
||||||
static VoxelDetail details[LIGHTS_PER_SEGMENT];
|
static VoxelDetail details[LIGHTS_PER_SEGMENT];
|
||||||
unsigned char* bufferOut;
|
unsigned char* bufferOut;
|
||||||
|
@ -423,7 +423,7 @@ const int PACKETS_PER_DANCE_FLOOR = DANCE_FLOOR_VOXELS_PER_PACKET / (DANCE_FLOOR
|
||||||
int danceFloorColors[DANCE_FLOOR_WIDTH][DANCE_FLOOR_LENGTH];
|
int danceFloorColors[DANCE_FLOOR_WIDTH][DANCE_FLOOR_LENGTH];
|
||||||
|
|
||||||
void sendDanceFloor() {
|
void sendDanceFloor() {
|
||||||
PACKET_HEADER message = PACKET_HEADER_SET_VOXEL_DESTRUCTIVE; // we're a bully!
|
PACKET_TYPE message = PACKET_TYPE_SET_VOXEL_DESTRUCTIVE; // we're a bully!
|
||||||
float lightScale = DANCE_FLOOR_LIGHT_SIZE;
|
float lightScale = DANCE_FLOOR_LIGHT_SIZE;
|
||||||
static VoxelDetail details[DANCE_FLOOR_VOXELS_PER_PACKET];
|
static VoxelDetail details[DANCE_FLOOR_VOXELS_PER_PACKET];
|
||||||
unsigned char* bufferOut;
|
unsigned char* bufferOut;
|
||||||
|
@ -550,7 +550,7 @@ bool billboardMessage[BILLBOARD_HEIGHT][BILLBOARD_WIDTH] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void sendBillboard() {
|
static void sendBillboard() {
|
||||||
PACKET_HEADER message = PACKET_HEADER_SET_VOXEL_DESTRUCTIVE; // we're a bully!
|
PACKET_TYPE message = PACKET_TYPE_SET_VOXEL_DESTRUCTIVE; // we're a bully!
|
||||||
float lightScale = BILLBOARD_LIGHT_SIZE;
|
float lightScale = BILLBOARD_LIGHT_SIZE;
|
||||||
static VoxelDetail details[VOXELS_PER_PACKET];
|
static VoxelDetail details[VOXELS_PER_PACKET];
|
||||||
unsigned char* bufferOut;
|
unsigned char* bufferOut;
|
||||||
|
@ -726,7 +726,8 @@ int main(int argc, const char * argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nodes sending messages to us...
|
// Nodes sending messages to us...
|
||||||
if (nodeList->getNodeSocket()->receive(&nodePublicAddress, packetData, &receivedBytes)) {
|
if (nodeList->getNodeSocket()->receive(&nodePublicAddress, packetData, &receivedBytes) &&
|
||||||
|
packetVersionMatch(packetData)) {
|
||||||
NodeList::getInstance()->processNodeData(&nodePublicAddress, packetData, receivedBytes);
|
NodeList::getInstance()->processNodeData(&nodePublicAddress, packetData, receivedBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,6 @@ AvatarAudioRingBuffer::~AvatarAudioRingBuffer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int AvatarAudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) {
|
int AvatarAudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) {
|
||||||
_shouldLoopbackForNode = (sourceBuffer[0] == PACKET_HEADER_MICROPHONE_AUDIO_WITH_ECHO);
|
_shouldLoopbackForNode = (sourceBuffer[0] == PACKET_TYPE_MICROPHONE_AUDIO_WITH_ECHO);
|
||||||
return PositionalAudioRingBuffer::parseData(sourceBuffer, numBytes);
|
return PositionalAudioRingBuffer::parseData(sourceBuffer, numBytes);
|
||||||
}
|
}
|
|
@ -21,7 +21,7 @@ InjectedAudioRingBuffer::InjectedAudioRingBuffer() :
|
||||||
}
|
}
|
||||||
|
|
||||||
int InjectedAudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) {
|
int InjectedAudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) {
|
||||||
unsigned char* currentBuffer = sourceBuffer + sizeof(PACKET_HEADER_INJECT_AUDIO);
|
unsigned char* currentBuffer = sourceBuffer + numBytesForPacketHeader(sourceBuffer);
|
||||||
|
|
||||||
// pull stream identifier from the packet
|
// pull stream identifier from the packet
|
||||||
memcpy(&_streamIdentifier, currentBuffer, sizeof(_streamIdentifier));
|
memcpy(&_streamIdentifier, currentBuffer, sizeof(_streamIdentifier));
|
||||||
|
|
|
@ -22,7 +22,7 @@ PositionalAudioRingBuffer::PositionalAudioRingBuffer() :
|
||||||
}
|
}
|
||||||
|
|
||||||
int PositionalAudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) {
|
int PositionalAudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) {
|
||||||
unsigned char* currentBuffer = sourceBuffer + sizeof(PACKET_HEADER);
|
unsigned char* currentBuffer = sourceBuffer + numBytesForPacketHeader(sourceBuffer);
|
||||||
currentBuffer += parsePositionalData(currentBuffer, numBytes - (currentBuffer - sourceBuffer));
|
currentBuffer += parsePositionalData(currentBuffer, numBytes - (currentBuffer - sourceBuffer));
|
||||||
currentBuffer += parseAudioSamples(currentBuffer, numBytes - (currentBuffer - sourceBuffer));
|
currentBuffer += parseAudioSamples(currentBuffer, numBytes - (currentBuffer - sourceBuffer));
|
||||||
|
|
||||||
|
|
|
@ -6,42 +6,45 @@
|
||||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <limits>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <fcntl.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <fstream>
|
|
||||||
#include <limits>
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
#include <glm/gtx/norm.hpp>
|
|
||||||
#include <glm/gtx/vector_angle.hpp>
|
|
||||||
#include <NodeList.h>
|
|
||||||
#include <Node.h>
|
|
||||||
#include <NodeTypes.h>
|
|
||||||
#include <SharedUtil.h>
|
|
||||||
#include <StdDev.h>
|
|
||||||
#include <Logstash.h>
|
|
||||||
|
|
||||||
#include "InjectedAudioRingBuffer.h"
|
|
||||||
#include "AvatarAudioRingBuffer.h"
|
|
||||||
#include <AudioRingBuffer.h>
|
|
||||||
#include "PacketHeaders.h"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include "Syssocket.h"
|
#include "Syssocket.h"
|
||||||
#include "Systime.h"
|
#include "Systime.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#else
|
#else
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#endif //_WIN32
|
#endif //_WIN32
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtx/norm.hpp>
|
||||||
|
#include <glm/gtx/vector_angle.hpp>
|
||||||
|
|
||||||
|
#include <Logstash.h>
|
||||||
|
#include <NodeList.h>
|
||||||
|
#include <Node.h>
|
||||||
|
#include <NodeTypes.h>
|
||||||
|
#include <PacketHeaders.h>
|
||||||
|
#include <SharedUtil.h>
|
||||||
|
#include <StdDev.h>
|
||||||
|
|
||||||
|
#include <AudioRingBuffer.h>
|
||||||
|
|
||||||
|
#include "AvatarAudioRingBuffer.h"
|
||||||
|
#include "InjectedAudioRingBuffer.h"
|
||||||
|
|
||||||
const unsigned short MIXER_LISTEN_PORT = 55443;
|
const unsigned short MIXER_LISTEN_PORT = 55443;
|
||||||
|
|
||||||
const short JITTER_BUFFER_MSECS = 12;
|
const short JITTER_BUFFER_MSECS = 12;
|
||||||
|
@ -49,17 +52,8 @@ const short JITTER_BUFFER_SAMPLES = JITTER_BUFFER_MSECS * (SAMPLE_RATE / 1000.0)
|
||||||
|
|
||||||
const unsigned int BUFFER_SEND_INTERVAL_USECS = floorf((BUFFER_LENGTH_SAMPLES_PER_CHANNEL / SAMPLE_RATE) * 1000000);
|
const unsigned int BUFFER_SEND_INTERVAL_USECS = floorf((BUFFER_LENGTH_SAMPLES_PER_CHANNEL / SAMPLE_RATE) * 1000000);
|
||||||
|
|
||||||
const long MAX_SAMPLE_VALUE = std::numeric_limits<int16_t>::max();
|
const int MAX_SAMPLE_VALUE = std::numeric_limits<int16_t>::max();
|
||||||
const long MIN_SAMPLE_VALUE = std::numeric_limits<int16_t>::min();
|
const int MIN_SAMPLE_VALUE = std::numeric_limits<int16_t>::min();
|
||||||
|
|
||||||
void plateauAdditionOfSamples(int16_t &mixSample, int16_t sampleToAdd) {
|
|
||||||
long sumSample = sampleToAdd + mixSample;
|
|
||||||
|
|
||||||
long normalizedSample = std::min(MAX_SAMPLE_VALUE, sumSample);
|
|
||||||
normalizedSample = std::max(MIN_SAMPLE_VALUE, sumSample);
|
|
||||||
|
|
||||||
mixSample = normalizedSample;
|
|
||||||
}
|
|
||||||
|
|
||||||
void attachNewBufferToNode(Node *newNode) {
|
void attachNewBufferToNode(Node *newNode) {
|
||||||
if (!newNode->getLinkedData()) {
|
if (!newNode->getLinkedData()) {
|
||||||
|
@ -103,8 +97,9 @@ int main(int argc, const char* argv[]) {
|
||||||
int nextFrame = 0;
|
int nextFrame = 0;
|
||||||
timeval startTime;
|
timeval startTime;
|
||||||
|
|
||||||
unsigned char clientPacket[BUFFER_LENGTH_BYTES_STEREO + sizeof(PACKET_HEADER_MIXED_AUDIO)];
|
int numBytesPacketHeader = numBytesForPacketHeader((unsigned char*) &PACKET_TYPE_MIXED_AUDIO);
|
||||||
clientPacket[0] = PACKET_HEADER_MIXED_AUDIO;
|
unsigned char clientPacket[BUFFER_LENGTH_BYTES_STEREO + numBytesPacketHeader];
|
||||||
|
populateTypeAndVersion(clientPacket, PACKET_TYPE_MIXED_AUDIO);
|
||||||
|
|
||||||
int16_t clientSamples[BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 2] = {};
|
int16_t clientSamples[BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 2] = {};
|
||||||
|
|
||||||
|
@ -304,16 +299,23 @@ int main(int argc, const char* argv[]) {
|
||||||
// pull the earlier sample for the delayed channel
|
// pull the earlier sample for the delayed channel
|
||||||
int earlierSample = delaySamplePointer[s] * attenuationCoefficient * weakChannelAmplitudeRatio;
|
int earlierSample = delaySamplePointer[s] * attenuationCoefficient * weakChannelAmplitudeRatio;
|
||||||
|
|
||||||
plateauAdditionOfSamples(delayedChannel[s], earlierSample);
|
delayedChannel[s] = glm::clamp(delayedChannel[s] + earlierSample,
|
||||||
|
MIN_SAMPLE_VALUE,
|
||||||
|
MAX_SAMPLE_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t currentSample = stkFrameBuffer[s] * attenuationCoefficient;
|
int16_t currentSample = stkFrameBuffer[s] * attenuationCoefficient;
|
||||||
|
|
||||||
plateauAdditionOfSamples(goodChannel[s], currentSample);
|
goodChannel[s] = glm::clamp(goodChannel[s] + currentSample,
|
||||||
|
MIN_SAMPLE_VALUE,
|
||||||
|
MAX_SAMPLE_VALUE);
|
||||||
|
|
||||||
if (s + numSamplesDelay < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) {
|
if (s + numSamplesDelay < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) {
|
||||||
plateauAdditionOfSamples(delayedChannel[s + numSamplesDelay],
|
int sumSample = delayedChannel[s + numSamplesDelay]
|
||||||
currentSample * weakChannelAmplitudeRatio);
|
+ (currentSample * weakChannelAmplitudeRatio);
|
||||||
|
delayedChannel[s + numSamplesDelay] = glm::clamp(sumSample,
|
||||||
|
MIN_SAMPLE_VALUE,
|
||||||
|
MAX_SAMPLE_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s >= BUFFER_LENGTH_SAMPLES_PER_CHANNEL - PHASE_DELAY_AT_90) {
|
if (s >= BUFFER_LENGTH_SAMPLES_PER_CHANNEL - PHASE_DELAY_AT_90) {
|
||||||
|
@ -325,7 +327,7 @@ int main(int argc, const char* argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(clientPacket + sizeof(PACKET_HEADER_MIXED_AUDIO), clientSamples, sizeof(clientSamples));
|
memcpy(clientPacket + numBytesPacketHeader, clientSamples, sizeof(clientSamples));
|
||||||
nodeList->getNodeSocket()->send(node->getPublicSocket(), clientPacket, sizeof(clientPacket));
|
nodeList->getNodeSocket()->send(node->getPublicSocket(), clientPacket, sizeof(clientPacket));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -345,13 +347,14 @@ int main(int argc, const char* argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// pull any new audio data from nodes off of the network stack
|
// pull any new audio data from nodes off of the network stack
|
||||||
while (nodeList->getNodeSocket()->receive(nodeAddress, packetData, &receivedBytes)) {
|
while (nodeList->getNodeSocket()->receive(nodeAddress, packetData, &receivedBytes) &&
|
||||||
if (packetData[0] == PACKET_HEADER_MICROPHONE_AUDIO_NO_ECHO ||
|
packetVersionMatch(packetData)) {
|
||||||
packetData[0] == PACKET_HEADER_MICROPHONE_AUDIO_WITH_ECHO) {
|
if (packetData[0] == PACKET_TYPE_MICROPHONE_AUDIO_NO_ECHO ||
|
||||||
|
packetData[0] == PACKET_TYPE_MICROPHONE_AUDIO_WITH_ECHO) {
|
||||||
Node* avatarNode = nodeList->addOrUpdateNode(nodeAddress,
|
Node* avatarNode = nodeList->addOrUpdateNode(nodeAddress,
|
||||||
nodeAddress,
|
nodeAddress,
|
||||||
NODE_TYPE_AGENT,
|
NODE_TYPE_AGENT,
|
||||||
nodeList->getLastNodeID());
|
nodeList->getLastNodeID());
|
||||||
|
|
||||||
if (avatarNode->getNodeID() == nodeList->getLastNodeID()) {
|
if (avatarNode->getNodeID() == nodeList->getLastNodeID()) {
|
||||||
nodeList->increaseNodeID();
|
nodeList->increaseNodeID();
|
||||||
|
@ -363,7 +366,7 @@ int main(int argc, const char* argv[]) {
|
||||||
// kill off this node - temporary solution to mixer crash on mac sleep
|
// kill off this node - temporary solution to mixer crash on mac sleep
|
||||||
avatarNode->setAlive(false);
|
avatarNode->setAlive(false);
|
||||||
}
|
}
|
||||||
} else if (packetData[0] == PACKET_HEADER_INJECT_AUDIO) {
|
} else if (packetData[0] == PACKET_TYPE_INJECT_AUDIO) {
|
||||||
Node* matchingInjector = NULL;
|
Node* matchingInjector = NULL;
|
||||||
|
|
||||||
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
|
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
|
||||||
|
@ -382,16 +385,16 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
if (!matchingInjector) {
|
if (!matchingInjector) {
|
||||||
matchingInjector = nodeList->addOrUpdateNode(NULL,
|
matchingInjector = nodeList->addOrUpdateNode(NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NODE_TYPE_AUDIO_INJECTOR,
|
NODE_TYPE_AUDIO_INJECTOR,
|
||||||
nodeList->getLastNodeID());
|
nodeList->getLastNodeID());
|
||||||
nodeList->increaseNodeID();
|
nodeList->increaseNodeID();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// give the new audio data to the matching injector node
|
// give the new audio data to the matching injector node
|
||||||
nodeList->updateNodeWithData(matchingInjector, packetData, receivedBytes);
|
nodeList->updateNodeWithData(matchingInjector, packetData, receivedBytes);
|
||||||
} else if (packetData[0] == PACKET_HEADER_PING) {
|
} else if (packetData[0] == PACKET_TYPE_PING) {
|
||||||
|
|
||||||
// If the packet is a ping, let processNodeData handle it.
|
// If the packet is a ping, let processNodeData handle it.
|
||||||
nodeList->processNodeData(nodeAddress, packetData, receivedBytes);
|
nodeList->processNodeData(nodeAddress, packetData, receivedBytes);
|
||||||
|
|
|
@ -73,7 +73,7 @@ int main(int argc, const char* argv[]) {
|
||||||
ssize_t receivedBytes = 0;
|
ssize_t receivedBytes = 0;
|
||||||
|
|
||||||
unsigned char *broadcastPacket = new unsigned char[MAX_PACKET_SIZE];
|
unsigned char *broadcastPacket = new unsigned char[MAX_PACKET_SIZE];
|
||||||
*broadcastPacket = PACKET_HEADER_BULK_AVATAR_DATA;
|
int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_BULK_AVATAR_DATA);
|
||||||
|
|
||||||
unsigned char* currentBufferPosition = NULL;
|
unsigned char* currentBufferPosition = NULL;
|
||||||
|
|
||||||
|
@ -92,9 +92,10 @@ int main(int argc, const char* argv[]) {
|
||||||
NodeList::getInstance()->sendDomainServerCheckIn();
|
NodeList::getInstance()->sendDomainServerCheckIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodeList->getNodeSocket()->receive(nodeAddress, packetData, &receivedBytes)) {
|
if (nodeList->getNodeSocket()->receive(nodeAddress, packetData, &receivedBytes) &&
|
||||||
|
packetVersionMatch(packetData)) {
|
||||||
switch (packetData[0]) {
|
switch (packetData[0]) {
|
||||||
case PACKET_HEADER_HEAD_DATA:
|
case PACKET_TYPE_HEAD_DATA:
|
||||||
// grab the node ID from the packet
|
// grab the node ID from the packet
|
||||||
unpackNodeId(packetData + 1, &nodeID);
|
unpackNodeId(packetData + 1, &nodeID);
|
||||||
|
|
||||||
|
@ -103,8 +104,8 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
// parse positional data from an node
|
// parse positional data from an node
|
||||||
nodeList->updateNodeWithData(avatarNode, packetData, receivedBytes);
|
nodeList->updateNodeWithData(avatarNode, packetData, receivedBytes);
|
||||||
case PACKET_HEADER_INJECT_AUDIO:
|
case PACKET_TYPE_INJECT_AUDIO:
|
||||||
currentBufferPosition = broadcastPacket + 1;
|
currentBufferPosition = broadcastPacket + numHeaderBytes;
|
||||||
|
|
||||||
// send back a packet with other active node data to this node
|
// send back a packet with other active node data to this node
|
||||||
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
|
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
|
||||||
|
@ -116,9 +117,9 @@ int main(int argc, const char* argv[]) {
|
||||||
nodeList->getNodeSocket()->send(nodeAddress, broadcastPacket, currentBufferPosition - broadcastPacket);
|
nodeList->getNodeSocket()->send(nodeAddress, broadcastPacket, currentBufferPosition - broadcastPacket);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case PACKET_HEADER_AVATAR_VOXEL_URL:
|
case PACKET_TYPE_AVATAR_VOXEL_URL:
|
||||||
// grab the node ID from the packet
|
// grab the node ID from the packet
|
||||||
unpackNodeId(packetData + 1, &nodeID);
|
unpackNodeId(packetData + numBytesForPacketHeader(packetData), &nodeID);
|
||||||
|
|
||||||
// let everyone else know about the update
|
// let everyone else know about the update
|
||||||
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
|
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
|
||||||
|
@ -127,7 +128,7 @@ int main(int argc, const char* argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PACKET_HEADER_DOMAIN:
|
case PACKET_TYPE_DOMAIN:
|
||||||
// ignore the DS packet, for now nodes are added only when they communicate directly with us
|
// ignore the DS packet, for now nodes are added only when they communicate directly with us
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -70,7 +70,7 @@ int main(int argc, const char * argv[])
|
||||||
char nodeType = '\0';
|
char nodeType = '\0';
|
||||||
|
|
||||||
unsigned char broadcastPacket[MAX_PACKET_SIZE];
|
unsigned char broadcastPacket[MAX_PACKET_SIZE];
|
||||||
broadcastPacket[0] = PACKET_HEADER_DOMAIN;
|
int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_DOMAIN);
|
||||||
|
|
||||||
unsigned char* currentBufferPos;
|
unsigned char* currentBufferPos;
|
||||||
unsigned char* startPointer;
|
unsigned char* startPointer;
|
||||||
|
@ -86,11 +86,15 @@ int main(int argc, const char * argv[])
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (nodeList->getNodeSocket()->receive((sockaddr *)&nodePublicAddress, packetData, &receivedBytes) &&
|
if (nodeList->getNodeSocket()->receive((sockaddr *)&nodePublicAddress, packetData, &receivedBytes) &&
|
||||||
(packetData[0] == PACKET_HEADER_DOMAIN_REPORT_FOR_DUTY || packetData[0] == PACKET_HEADER_DOMAIN_LIST_REQUEST)) {
|
(packetData[0] == PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY || packetData[0] == PACKET_TYPE_DOMAIN_LIST_REQUEST) &&
|
||||||
|
packetVersionMatch(packetData)) {
|
||||||
|
// this is an RFD or domain list request packet, and there is a version match
|
||||||
std::map<char, Node *> newestSoloNodes;
|
std::map<char, Node *> newestSoloNodes;
|
||||||
|
|
||||||
nodeType = packetData[1];
|
int numBytesSenderHeader = numBytesForPacketHeader(packetData);
|
||||||
int numBytesSocket = unpackSocket(packetData + sizeof(PACKET_HEADER) + sizeof(NODE_TYPE),
|
|
||||||
|
nodeType = *(packetData + numBytesSenderHeader);
|
||||||
|
int numBytesSocket = unpackSocket(packetData + numBytesSenderHeader + sizeof(NODE_TYPE),
|
||||||
(sockaddr*) &nodeLocalAddress);
|
(sockaddr*) &nodeLocalAddress);
|
||||||
|
|
||||||
sockaddr* destinationSocket = (sockaddr*) &nodePublicAddress;
|
sockaddr* destinationSocket = (sockaddr*) &nodePublicAddress;
|
||||||
|
@ -108,18 +112,18 @@ int main(int argc, const char * argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* newNode = nodeList->addOrUpdateNode((sockaddr*) &nodePublicAddress,
|
Node* newNode = nodeList->addOrUpdateNode((sockaddr*) &nodePublicAddress,
|
||||||
(sockaddr*) &nodeLocalAddress,
|
(sockaddr*) &nodeLocalAddress,
|
||||||
nodeType,
|
nodeType,
|
||||||
nodeList->getLastNodeID());
|
nodeList->getLastNodeID());
|
||||||
|
|
||||||
if (newNode->getNodeID() == nodeList->getLastNodeID()) {
|
if (newNode->getNodeID() == nodeList->getLastNodeID()) {
|
||||||
nodeList->increaseNodeID();
|
nodeList->increaseNodeID();
|
||||||
}
|
}
|
||||||
|
|
||||||
currentBufferPos = broadcastPacket + sizeof(PACKET_HEADER);
|
currentBufferPos = broadcastPacket + numHeaderBytes;
|
||||||
startPointer = currentBufferPos;
|
startPointer = currentBufferPos;
|
||||||
|
|
||||||
unsigned char* nodeTypesOfInterest = packetData + sizeof(PACKET_HEADER) + sizeof(NODE_TYPE)
|
unsigned char* nodeTypesOfInterest = packetData + numBytesSenderHeader + sizeof(NODE_TYPE)
|
||||||
+ numBytesSocket + sizeof(unsigned char);
|
+ numBytesSocket + sizeof(unsigned char);
|
||||||
int numInterestTypes = *(nodeTypesOfInterest - 1);
|
int numInterestTypes = *(nodeTypesOfInterest - 1);
|
||||||
|
|
||||||
|
@ -162,7 +166,7 @@ int main(int argc, const char * argv[])
|
||||||
uint64_t timeNow = usecTimestampNow();
|
uint64_t timeNow = usecTimestampNow();
|
||||||
newNode->setLastHeardMicrostamp(timeNow);
|
newNode->setLastHeardMicrostamp(timeNow);
|
||||||
|
|
||||||
if (packetData[0] == PACKET_HEADER_DOMAIN_REPORT_FOR_DUTY
|
if (packetData[0] == PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY
|
||||||
&& memchr(SOLO_NODE_TYPES, nodeType, sizeof(SOLO_NODE_TYPES))) {
|
&& memchr(SOLO_NODE_TYPES, nodeType, sizeof(SOLO_NODE_TYPES))) {
|
||||||
newNode->setWakeMicrostamp(timeNow);
|
newNode->setWakeMicrostamp(timeNow);
|
||||||
}
|
}
|
||||||
|
@ -172,8 +176,8 @@ int main(int argc, const char * argv[])
|
||||||
|
|
||||||
// send the constructed list back to this node
|
// send the constructed list back to this node
|
||||||
nodeList->getNodeSocket()->send(destinationSocket,
|
nodeList->getNodeSocket()->send(destinationSocket,
|
||||||
broadcastPacket,
|
broadcastPacket,
|
||||||
(currentBufferPos - startPointer) + 1);
|
(currentBufferPos - startPointer) + numHeaderBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Logstash::shouldSendStats()) {
|
if (Logstash::shouldSendStats()) {
|
||||||
|
|
|
@ -49,9 +49,10 @@ void *receiveNodeData(void *args) {
|
||||||
NodeList* nodeList = NodeList::getInstance();
|
NodeList* nodeList = NodeList::getInstance();
|
||||||
|
|
||||||
while (!::stopReceiveNodeDataThread) {
|
while (!::stopReceiveNodeDataThread) {
|
||||||
if (nodeList->getNodeSocket()->receive(&senderAddress, incomingPacket, &bytesReceived)) {
|
if (nodeList->getNodeSocket()->receive(&senderAddress, incomingPacket, &bytesReceived) &&
|
||||||
|
packetVersionMatch(incomingPacket)) {
|
||||||
switch (incomingPacket[0]) {
|
switch (incomingPacket[0]) {
|
||||||
case PACKET_HEADER_BULK_AVATAR_DATA:
|
case PACKET_TYPE_BULK_AVATAR_DATA:
|
||||||
// this is the positional data for other nodes
|
// this is the positional data for other nodes
|
||||||
// pass that off to the nodeList processBulkNodeData method
|
// pass that off to the nodeList processBulkNodeData method
|
||||||
nodeList->processBulkNodeData(&senderAddress, incomingPacket, bytesReceived);
|
nodeList->processBulkNodeData(&senderAddress, incomingPacket, bytesReceived);
|
||||||
|
@ -85,9 +86,6 @@ int main(int argc, const char* argv[]) {
|
||||||
// start the node list thread that will kill off nodes when they stop talking
|
// start the node list thread that will kill off nodes when they stop talking
|
||||||
nodeList->startSilentNodeRemovalThread();
|
nodeList->startSilentNodeRemovalThread();
|
||||||
|
|
||||||
// start the ping thread that hole punches to create an active connection to other nodes
|
|
||||||
nodeList->startPingUnknownNodesThread();
|
|
||||||
|
|
||||||
pthread_t receiveNodeDataThread;
|
pthread_t receiveNodeDataThread;
|
||||||
pthread_create(&receiveNodeDataThread, NULL, receiveNodeData, NULL);
|
pthread_create(&receiveNodeDataThread, NULL, receiveNodeData, NULL);
|
||||||
|
|
||||||
|
@ -125,7 +123,7 @@ int main(int argc, const char* argv[]) {
|
||||||
nodeList->linkedDataCreateCallback = createAvatarDataForNode;
|
nodeList->linkedDataCreateCallback = createAvatarDataForNode;
|
||||||
|
|
||||||
unsigned char broadcastPacket[MAX_PACKET_SIZE];
|
unsigned char broadcastPacket[MAX_PACKET_SIZE];
|
||||||
broadcastPacket[0] = PACKET_HEADER_HEAD_DATA;
|
int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_HEAD_DATA);
|
||||||
|
|
||||||
timeval thisSend;
|
timeval thisSend;
|
||||||
int numMicrosecondsSleep = 0;
|
int numMicrosecondsSleep = 0;
|
||||||
|
@ -153,7 +151,7 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
// make sure we actually have an avatar mixer with an active socket
|
// make sure we actually have an avatar mixer with an active socket
|
||||||
if (nodeList->getOwnerID() != UNKNOWN_NODE_ID && avatarMixer && avatarMixer->getActiveSocket() != NULL) {
|
if (nodeList->getOwnerID() != UNKNOWN_NODE_ID && avatarMixer && avatarMixer->getActiveSocket() != NULL) {
|
||||||
unsigned char* packetPosition = broadcastPacket + sizeof(PACKET_HEADER);
|
unsigned char* packetPosition = broadcastPacket + numHeaderBytes;
|
||||||
packetPosition += packNodeId(packetPosition, nodeList->getOwnerID());
|
packetPosition += packNodeId(packetPosition, nodeList->getOwnerID());
|
||||||
|
|
||||||
// use the getBroadcastData method in the AvatarData class to populate the broadcastPacket buffer
|
// use the getBroadcastData method in the AvatarData class to populate the broadcastPacket buffer
|
||||||
|
@ -210,6 +208,5 @@ int main(int argc, const char* argv[]) {
|
||||||
pthread_join(receiveNodeDataThread, NULL);
|
pthread_join(receiveNodeDataThread, NULL);
|
||||||
|
|
||||||
// stop the node list's threads
|
// stop the node list's threads
|
||||||
nodeList->stopPingUnknownNodesThread();
|
|
||||||
nodeList->stopSilentNodeRemovalThread();
|
nodeList->stopSilentNodeRemovalThread();
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,7 +144,8 @@ int main(int argc, char* argv[]) {
|
||||||
nodeList->linkedDataCreateCallback = createAvatarDataForNode;
|
nodeList->linkedDataCreateCallback = createAvatarDataForNode;
|
||||||
|
|
||||||
timeval lastSend = {};
|
timeval lastSend = {};
|
||||||
unsigned char broadcastPacket = PACKET_HEADER_INJECT_AUDIO;
|
int numBytesPacketHeader = numBytesForPacketHeader((unsigned char*) &PACKET_TYPE_INJECT_AUDIO);
|
||||||
|
unsigned char* broadcastPacket = new unsigned char[numBytesPacketHeader];
|
||||||
|
|
||||||
timeval lastDomainServerCheckIn = {};
|
timeval lastDomainServerCheckIn = {};
|
||||||
|
|
||||||
|
@ -168,10 +169,10 @@ int main(int argc, char* argv[]) {
|
||||||
NodeList::getInstance()->sendDomainServerCheckIn();
|
NodeList::getInstance()->sendDomainServerCheckIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
while (nodeList->getNodeSocket()->receive(&senderAddress, incomingPacket, &bytesReceived)) {
|
while (nodeList->getNodeSocket()->receive(&senderAddress, incomingPacket, &bytesReceived) &&
|
||||||
|
packetVersionMatch(incomingPacket)) {
|
||||||
switch (incomingPacket[0]) {
|
switch (incomingPacket[0]) {
|
||||||
case PACKET_HEADER_BULK_AVATAR_DATA:
|
case PACKET_TYPE_BULK_AVATAR_DATA: // this is the positional data for other nodes
|
||||||
// this is the positional data for other nodes
|
|
||||||
// pass that off to the nodeList processBulkNodeData method
|
// pass that off to the nodeList processBulkNodeData method
|
||||||
nodeList->processBulkNodeData(&senderAddress, incomingPacket, bytesReceived);
|
nodeList->processBulkNodeData(&senderAddress, incomingPacket, bytesReceived);
|
||||||
break;
|
break;
|
||||||
|
@ -211,8 +212,8 @@ int main(int argc, char* argv[]) {
|
||||||
|
|
||||||
// use the UDPSocket instance attached to our node list to ask avatar mixer for a list of avatars
|
// use the UDPSocket instance attached to our node list to ask avatar mixer for a list of avatars
|
||||||
nodeList->getNodeSocket()->send(avatarMixer->getActiveSocket(),
|
nodeList->getNodeSocket()->send(avatarMixer->getActiveSocket(),
|
||||||
&broadcastPacket,
|
broadcastPacket,
|
||||||
sizeof(broadcastPacket));
|
numBytesPacketHeader);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!injector.isInjectingAudio() && (::shouldLoopAudio || !::hasInjectedAudioOnce)) {
|
if (!injector.isInjectingAudio() && (::shouldLoopAudio || !::hasInjectedAudioOnce)) {
|
||||||
|
|
|
@ -251,7 +251,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
||||||
|
|
||||||
// start the nodeList threads
|
// start the nodeList threads
|
||||||
NodeList::getInstance()->startSilentNodeRemovalThread();
|
NodeList::getInstance()->startSilentNodeRemovalThread();
|
||||||
NodeList::getInstance()->startPingUnknownNodesThread();
|
|
||||||
|
|
||||||
_window->setCentralWidget(_glWidget);
|
_window->setCentralWidget(_glWidget);
|
||||||
|
|
||||||
|
@ -905,14 +904,15 @@ void Application::wheelEvent(QWheelEvent* event) {
|
||||||
|
|
||||||
void Application::sendPingPackets() {
|
void Application::sendPingPackets() {
|
||||||
|
|
||||||
char nodeTypesOfInterest[] = {NODE_TYPE_VOXEL_SERVER, NODE_TYPE_AUDIO_MIXER, NODE_TYPE_AVATAR_MIXER};
|
const char nodesToPing[] = {NODE_TYPE_VOXEL_SERVER, NODE_TYPE_AUDIO_MIXER, NODE_TYPE_AVATAR_MIXER};
|
||||||
|
|
||||||
uint64_t currentTime = usecTimestampNow();
|
uint64_t currentTime = usecTimestampNow();
|
||||||
unsigned char pingPacket[1 + sizeof(currentTime)];
|
unsigned char pingPacket[numBytesForPacketHeader((unsigned char*) &PACKET_TYPE_PING) + sizeof(currentTime)];
|
||||||
pingPacket[0] = PACKET_HEADER_PING;
|
int numHeaderBytes = populateTypeAndVersion(pingPacket, PACKET_TYPE_PING);
|
||||||
|
|
||||||
memcpy(&pingPacket[1], ¤tTime, sizeof(currentTime));
|
memcpy(pingPacket + numHeaderBytes, ¤tTime, sizeof(currentTime));
|
||||||
getInstance()->controlledBroadcastToNodes(pingPacket, 1 + sizeof(currentTime),
|
getInstance()->controlledBroadcastToNodes(pingPacket, sizeof(pingPacket),
|
||||||
nodeTypesOfInterest, sizeof(nodeTypesOfInterest));
|
nodesToPing, sizeof(nodesToPing));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Every second, check the frame rates and other stuff
|
// Every second, check the frame rates and other stuff
|
||||||
|
@ -1020,7 +1020,11 @@ void Application::sendAvatarVoxelURLMessage(const QUrl& url) {
|
||||||
return; // we don't yet know who we are
|
return; // we don't yet know who we are
|
||||||
}
|
}
|
||||||
QByteArray message;
|
QByteArray message;
|
||||||
message.append(PACKET_HEADER_AVATAR_VOXEL_URL);
|
|
||||||
|
char packetHeader[MAX_PACKET_HEADER_BYTES];
|
||||||
|
int numBytesPacketHeader = populateTypeAndVersion((unsigned char*) packetHeader, PACKET_TYPE_AVATAR_VOXEL_URL);
|
||||||
|
|
||||||
|
message.append(packetHeader, numBytesPacketHeader);
|
||||||
message.append((const char*)&ownerID, sizeof(ownerID));
|
message.append((const char*)&ownerID, sizeof(ownerID));
|
||||||
message.append(url.toEncoded());
|
message.append(url.toEncoded());
|
||||||
|
|
||||||
|
@ -1029,8 +1033,9 @@ void Application::sendAvatarVoxelURLMessage(const QUrl& url) {
|
||||||
|
|
||||||
void Application::processAvatarVoxelURLMessage(unsigned char *packetData, size_t dataBytes) {
|
void Application::processAvatarVoxelURLMessage(unsigned char *packetData, size_t dataBytes) {
|
||||||
// skip the header
|
// skip the header
|
||||||
packetData++;
|
int numBytesPacketHeader = numBytesForPacketHeader(packetData);
|
||||||
dataBytes--;
|
packetData += numBytesPacketHeader;
|
||||||
|
dataBytes -= numBytesPacketHeader;
|
||||||
|
|
||||||
// read the node id
|
// read the node id
|
||||||
uint16_t nodeID = *(uint16_t*)packetData;
|
uint16_t nodeID = *(uint16_t*)packetData;
|
||||||
|
@ -1256,11 +1261,11 @@ void Application::updateVoxelModeActions() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::sendVoxelEditMessage(PACKET_HEADER header, VoxelDetail& detail) {
|
void Application::sendVoxelEditMessage(PACKET_TYPE type, VoxelDetail& detail) {
|
||||||
unsigned char* bufferOut;
|
unsigned char* bufferOut;
|
||||||
int sizeOut;
|
int sizeOut;
|
||||||
|
|
||||||
if (createVoxelEditMessage(header, 0, 1, &detail, bufferOut, sizeOut)){
|
if (createVoxelEditMessage(type, 0, 1, &detail, bufferOut, sizeOut)){
|
||||||
Application::controlledBroadcastToNodes(bufferOut, sizeOut, & NODE_TYPE_VOXEL_SERVER, 1);
|
Application::controlledBroadcastToNodes(bufferOut, sizeOut, & NODE_TYPE_VOXEL_SERVER, 1);
|
||||||
delete[] bufferOut;
|
delete[] bufferOut;
|
||||||
}
|
}
|
||||||
|
@ -1347,7 +1352,8 @@ bool Application::sendVoxelsOperation(VoxelNode* node, void* extraData) {
|
||||||
// if we have room don't have room in the buffer, then send the previously generated message first
|
// if we have room don't have room in the buffer, then send the previously generated message first
|
||||||
if (args->bufferInUse + codeAndColorLength > MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE) {
|
if (args->bufferInUse + codeAndColorLength > MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE) {
|
||||||
controlledBroadcastToNodes(args->messageBuffer, args->bufferInUse, & NODE_TYPE_VOXEL_SERVER, 1);
|
controlledBroadcastToNodes(args->messageBuffer, args->bufferInUse, & NODE_TYPE_VOXEL_SERVER, 1);
|
||||||
args->bufferInUse = sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(unsigned short int); // reset
|
args->bufferInUse = numBytesForPacketHeader((unsigned char*) &PACKET_TYPE_SET_VOXEL_DESTRUCTIVE)
|
||||||
|
+ sizeof(unsigned short int); // reset
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy this node's code color details into our buffer.
|
// copy this node's code color details into our buffer.
|
||||||
|
@ -1414,10 +1420,12 @@ void Application::importVoxels() {
|
||||||
// the server as an set voxel message, this will also rebase the voxels to the new location
|
// the server as an set voxel message, this will also rebase the voxels to the new location
|
||||||
unsigned char* calculatedOctCode = NULL;
|
unsigned char* calculatedOctCode = NULL;
|
||||||
SendVoxelsOperationArgs args;
|
SendVoxelsOperationArgs args;
|
||||||
args.messageBuffer[0] = PACKET_HEADER_SET_VOXEL_DESTRUCTIVE;
|
|
||||||
unsigned short int* sequenceAt = (unsigned short int*)&args.messageBuffer[sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE)];
|
int numBytesPacketHeader = populateTypeAndVersion(args.messageBuffer, PACKET_TYPE_SET_VOXEL_DESTRUCTIVE);
|
||||||
|
|
||||||
|
unsigned short int* sequenceAt = (unsigned short int*)&args.messageBuffer[numBytesPacketHeader];
|
||||||
*sequenceAt = 0;
|
*sequenceAt = 0;
|
||||||
args.bufferInUse = sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(unsigned short int); // set to command + sequence
|
args.bufferInUse = numBytesPacketHeader + sizeof(unsigned short int); // set to command + sequence
|
||||||
|
|
||||||
// we only need the selected voxel to get the newBaseOctCode, which we can actually calculate from the
|
// we only need the selected voxel to get the newBaseOctCode, which we can actually calculate from the
|
||||||
// voxel size/position details.
|
// voxel size/position details.
|
||||||
|
@ -1430,7 +1438,7 @@ void Application::importVoxels() {
|
||||||
importVoxels.recurseTreeWithOperation(sendVoxelsOperation, &args);
|
importVoxels.recurseTreeWithOperation(sendVoxelsOperation, &args);
|
||||||
|
|
||||||
// If we have voxels left in the packet, then send the packet
|
// If we have voxels left in the packet, then send the packet
|
||||||
if (args.bufferInUse > (sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(unsigned short int))) {
|
if (args.bufferInUse > (numBytesPacketHeader + sizeof(unsigned short int))) {
|
||||||
controlledBroadcastToNodes(args.messageBuffer, args.bufferInUse, & NODE_TYPE_VOXEL_SERVER, 1);
|
controlledBroadcastToNodes(args.messageBuffer, args.bufferInUse, & NODE_TYPE_VOXEL_SERVER, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1465,10 +1473,12 @@ void Application::pasteVoxels() {
|
||||||
// Recurse the clipboard tree, where everything is root relative, and send all the colored voxels to
|
// Recurse the clipboard tree, where everything is root relative, and send all the colored voxels to
|
||||||
// the server as an set voxel message, this will also rebase the voxels to the new location
|
// the server as an set voxel message, this will also rebase the voxels to the new location
|
||||||
SendVoxelsOperationArgs args;
|
SendVoxelsOperationArgs args;
|
||||||
args.messageBuffer[0] = PACKET_HEADER_SET_VOXEL_DESTRUCTIVE;
|
|
||||||
unsigned short int* sequenceAt = (unsigned short int*)&args.messageBuffer[sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE)];
|
int numBytesPacketHeader = populateTypeAndVersion(args.messageBuffer, PACKET_TYPE_SET_VOXEL_DESTRUCTIVE);
|
||||||
|
|
||||||
|
unsigned short int* sequenceAt = (unsigned short int*)&args.messageBuffer[numBytesPacketHeader];
|
||||||
*sequenceAt = 0;
|
*sequenceAt = 0;
|
||||||
args.bufferInUse = sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(unsigned short int); // set to command + sequence
|
args.bufferInUse = numBytesPacketHeader + sizeof(unsigned short int); // set to command + sequence
|
||||||
|
|
||||||
// we only need the selected voxel to get the newBaseOctCode, which we can actually calculate from the
|
// we only need the selected voxel to get the newBaseOctCode, which we can actually calculate from the
|
||||||
// voxel size/position details. If we don't have an actual selectedNode then use the mouseVoxel to create a
|
// voxel size/position details. If we don't have an actual selectedNode then use the mouseVoxel to create a
|
||||||
|
@ -1482,7 +1492,7 @@ void Application::pasteVoxels() {
|
||||||
_clipboardTree.recurseTreeWithOperation(sendVoxelsOperation, &args);
|
_clipboardTree.recurseTreeWithOperation(sendVoxelsOperation, &args);
|
||||||
|
|
||||||
// If we have voxels left in the packet, then send the packet
|
// If we have voxels left in the packet, then send the packet
|
||||||
if (args.bufferInUse > (sizeof(PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) + sizeof(unsigned short int))) {
|
if (args.bufferInUse > (numBytesPacketHeader + sizeof(unsigned short int))) {
|
||||||
controlledBroadcastToNodes(args.messageBuffer, args.bufferInUse, & NODE_TYPE_VOXEL_SERVER, 1);
|
controlledBroadcastToNodes(args.messageBuffer, args.bufferInUse, & NODE_TYPE_VOXEL_SERVER, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1740,6 +1750,22 @@ void Application::init() {
|
||||||
|
|
||||||
const float MAX_AVATAR_EDIT_VELOCITY = 1.0f;
|
const float MAX_AVATAR_EDIT_VELOCITY = 1.0f;
|
||||||
const float MAX_VOXEL_EDIT_DISTANCE = 20.0f;
|
const float MAX_VOXEL_EDIT_DISTANCE = 20.0f;
|
||||||
|
const float HEAD_SPHERE_RADIUS = 0.07;
|
||||||
|
|
||||||
|
bool Application::isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection, glm::vec3& eyePosition) {
|
||||||
|
NodeList* nodeList = NodeList::getInstance();
|
||||||
|
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
|
||||||
|
if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) {
|
||||||
|
Avatar* avatar = (Avatar *) node->getLinkedData();
|
||||||
|
glm::vec3 headPosition = avatar->getHead().getPosition();
|
||||||
|
if (rayIntersectsSphere(mouseRayOrigin, mouseRayDirection, headPosition, HEAD_SPHERE_RADIUS)) {
|
||||||
|
eyePosition = avatar->getHead().getEyeLevelPosition();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void Application::update(float deltaTime) {
|
void Application::update(float deltaTime) {
|
||||||
// Use Transmitter Hand to move hand if connected, else use mouse
|
// Use Transmitter Hand to move hand if connected, else use mouse
|
||||||
|
@ -1767,8 +1793,15 @@ void Application::update(float deltaTime) {
|
||||||
_myAvatar.setMouseRay(mouseRayOrigin, mouseRayDirection);
|
_myAvatar.setMouseRay(mouseRayOrigin, mouseRayDirection);
|
||||||
|
|
||||||
// Set where I am looking based on my mouse ray (so that other people can see)
|
// Set where I am looking based on my mouse ray (so that other people can see)
|
||||||
glm::vec3 myLookAtFromMouse(mouseRayOrigin + mouseRayDirection);
|
glm::vec3 eyePosition;
|
||||||
_myAvatar.getHead().setLookAtPosition(myLookAtFromMouse);
|
if (isLookingAtOtherAvatar(mouseRayOrigin, mouseRayDirection, eyePosition)) {
|
||||||
|
// If the mouse is over another avatar's head...
|
||||||
|
glm::vec3 myLookAtFromMouse(eyePosition);
|
||||||
|
_myAvatar.getHead().setLookAtPosition(myLookAtFromMouse);
|
||||||
|
} else {
|
||||||
|
glm::vec3 myLookAtFromMouse(mouseRayOrigin + mouseRayDirection);
|
||||||
|
_myAvatar.getHead().setLookAtPosition(myLookAtFromMouse);
|
||||||
|
}
|
||||||
|
|
||||||
// If we are dragging on a voxel, add thrust according to the amount the mouse is dragging
|
// If we are dragging on a voxel, add thrust according to the amount the mouse is dragging
|
||||||
const float VOXEL_GRAB_THRUST = 0.0f;
|
const float VOXEL_GRAB_THRUST = 0.0f;
|
||||||
|
@ -2004,6 +2037,18 @@ void Application::updateAvatar(float deltaTime) {
|
||||||
_headMouseY = max(_headMouseY, 0);
|
_headMouseY = max(_headMouseY, 0);
|
||||||
_headMouseY = min(_headMouseY, _glWidget->height());
|
_headMouseY = min(_headMouseY, _glWidget->height());
|
||||||
|
|
||||||
|
const float MIDPOINT_OF_SCREEN = 0.5;
|
||||||
|
|
||||||
|
// Set lookAtPosition if an avatar is at the center of the screen
|
||||||
|
glm::vec3 screenCenterRayOrigin, screenCenterRayDirection;
|
||||||
|
_viewFrustum.computePickRay(MIDPOINT_OF_SCREEN, MIDPOINT_OF_SCREEN, screenCenterRayOrigin, screenCenterRayDirection);
|
||||||
|
|
||||||
|
glm::vec3 eyePosition;
|
||||||
|
if (isLookingAtOtherAvatar(screenCenterRayOrigin, screenCenterRayDirection, eyePosition)) {
|
||||||
|
glm::vec3 myLookAtFromMouse(eyePosition);
|
||||||
|
_myAvatar.getHead().setLookAtPosition(myLookAtFromMouse);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OculusManager::isConnected()) {
|
if (OculusManager::isConnected()) {
|
||||||
|
@ -2040,7 +2085,8 @@ void Application::updateAvatar(float deltaTime) {
|
||||||
unsigned char broadcastString[200];
|
unsigned char broadcastString[200];
|
||||||
unsigned char* endOfBroadcastStringWrite = broadcastString;
|
unsigned char* endOfBroadcastStringWrite = broadcastString;
|
||||||
|
|
||||||
*(endOfBroadcastStringWrite++) = PACKET_HEADER_HEAD_DATA;
|
endOfBroadcastStringWrite += populateTypeAndVersion(endOfBroadcastStringWrite, PACKET_TYPE_HEAD_DATA);
|
||||||
|
|
||||||
endOfBroadcastStringWrite += packNodeId(endOfBroadcastStringWrite, nodeList->getOwnerID());
|
endOfBroadcastStringWrite += packNodeId(endOfBroadcastStringWrite, nodeList->getOwnerID());
|
||||||
|
|
||||||
endOfBroadcastStringWrite += _myAvatar.getBroadcastData(endOfBroadcastStringWrite);
|
endOfBroadcastStringWrite += _myAvatar.getBroadcastData(endOfBroadcastStringWrite);
|
||||||
|
@ -2070,8 +2116,8 @@ void Application::updateAvatar(float deltaTime) {
|
||||||
_paintingVoxel.y >= 0.0 && _paintingVoxel.y <= 1.0 &&
|
_paintingVoxel.y >= 0.0 && _paintingVoxel.y <= 1.0 &&
|
||||||
_paintingVoxel.z >= 0.0 && _paintingVoxel.z <= 1.0) {
|
_paintingVoxel.z >= 0.0 && _paintingVoxel.z <= 1.0) {
|
||||||
|
|
||||||
PACKET_HEADER message = (_destructiveAddVoxel->isChecked() ?
|
PACKET_TYPE message = (_destructiveAddVoxel->isChecked() ?
|
||||||
PACKET_HEADER_SET_VOXEL_DESTRUCTIVE : PACKET_HEADER_SET_VOXEL);
|
PACKET_TYPE_SET_VOXEL_DESTRUCTIVE : PACKET_TYPE_SET_VOXEL);
|
||||||
sendVoxelEditMessage(message, _paintingVoxel);
|
sendVoxelEditMessage(message, _paintingVoxel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2953,8 +2999,8 @@ void Application::shiftPaintingColor() {
|
||||||
void Application::maybeEditVoxelUnderCursor() {
|
void Application::maybeEditVoxelUnderCursor() {
|
||||||
if (_addVoxelMode->isChecked() || _colorVoxelMode->isChecked()) {
|
if (_addVoxelMode->isChecked() || _colorVoxelMode->isChecked()) {
|
||||||
if (_mouseVoxel.s != 0) {
|
if (_mouseVoxel.s != 0) {
|
||||||
PACKET_HEADER message = (_destructiveAddVoxel->isChecked() ?
|
PACKET_TYPE message = (_destructiveAddVoxel->isChecked() ?
|
||||||
PACKET_HEADER_SET_VOXEL_DESTRUCTIVE : PACKET_HEADER_SET_VOXEL);
|
PACKET_TYPE_SET_VOXEL_DESTRUCTIVE : PACKET_TYPE_SET_VOXEL);
|
||||||
sendVoxelEditMessage(message, _mouseVoxel);
|
sendVoxelEditMessage(message, _mouseVoxel);
|
||||||
|
|
||||||
// create the voxel locally so it appears immediately
|
// create the voxel locally so it appears immediately
|
||||||
|
@ -3027,7 +3073,7 @@ void Application::maybeEditVoxelUnderCursor() {
|
||||||
void Application::deleteVoxelUnderCursor() {
|
void Application::deleteVoxelUnderCursor() {
|
||||||
if (_mouseVoxel.s != 0) {
|
if (_mouseVoxel.s != 0) {
|
||||||
// sending delete to the server is sufficient, server will send new version so we see updates soon enough
|
// sending delete to the server is sufficient, server will send new version so we see updates soon enough
|
||||||
sendVoxelEditMessage(PACKET_HEADER_ERASE_VOXEL, _mouseVoxel);
|
sendVoxelEditMessage(PACKET_TYPE_ERASE_VOXEL, _mouseVoxel);
|
||||||
AudioInjector* voxelInjector = AudioInjectionManager::injectorWithCapacity(5000);
|
AudioInjector* voxelInjector = AudioInjectionManager::injectorWithCapacity(5000);
|
||||||
voxelInjector->setPosition(glm::vec3(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z));
|
voxelInjector->setPosition(glm::vec3(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z));
|
||||||
// voxelInjector->setBearing(0); //straight down the z axis
|
// voxelInjector->setBearing(0); //straight down the z axis
|
||||||
|
@ -3137,36 +3183,39 @@ void* Application::networkReceive(void* args) {
|
||||||
app->_packetCount++;
|
app->_packetCount++;
|
||||||
app->_bytesCount += bytesReceived;
|
app->_bytesCount += bytesReceived;
|
||||||
|
|
||||||
switch (app->_incomingPacket[0]) {
|
if (packetVersionMatch(app->_incomingPacket)) {
|
||||||
case PACKET_HEADER_TRANSMITTER_DATA_V2:
|
// only process this packet if we have a match on the packet version
|
||||||
// V2 = IOS transmitter app
|
switch (app->_incomingPacket[0]) {
|
||||||
app->_myTransmitter.processIncomingData(app->_incomingPacket, bytesReceived);
|
case PACKET_TYPE_TRANSMITTER_DATA_V2:
|
||||||
|
// V2 = IOS transmitter app
|
||||||
break;
|
app->_myTransmitter.processIncomingData(app->_incomingPacket, bytesReceived);
|
||||||
case PACKET_HEADER_MIXED_AUDIO:
|
|
||||||
app->_audio.addReceivedAudioToBuffer(app->_incomingPacket, bytesReceived);
|
break;
|
||||||
break;
|
case PACKET_TYPE_MIXED_AUDIO:
|
||||||
case PACKET_HEADER_VOXEL_DATA:
|
app->_audio.addReceivedAudioToBuffer(app->_incomingPacket, bytesReceived);
|
||||||
case PACKET_HEADER_VOXEL_DATA_MONOCHROME:
|
break;
|
||||||
case PACKET_HEADER_Z_COMMAND:
|
case PACKET_TYPE_VOXEL_DATA:
|
||||||
case PACKET_HEADER_ERASE_VOXEL:
|
case PACKET_TYPE_VOXEL_DATA_MONOCHROME:
|
||||||
app->_voxels.parseData(app->_incomingPacket, bytesReceived);
|
case PACKET_TYPE_Z_COMMAND:
|
||||||
break;
|
case PACKET_TYPE_ERASE_VOXEL:
|
||||||
case PACKET_HEADER_ENVIRONMENT_DATA:
|
app->_voxels.parseData(app->_incomingPacket, bytesReceived);
|
||||||
app->_environment.parseData(&senderAddress, app->_incomingPacket, bytesReceived);
|
break;
|
||||||
break;
|
case PACKET_TYPE_ENVIRONMENT_DATA:
|
||||||
case PACKET_HEADER_BULK_AVATAR_DATA:
|
app->_environment.parseData(&senderAddress, app->_incomingPacket, bytesReceived);
|
||||||
NodeList::getInstance()->processBulkNodeData(&senderAddress,
|
break;
|
||||||
app->_incomingPacket,
|
case PACKET_TYPE_BULK_AVATAR_DATA:
|
||||||
bytesReceived);
|
NodeList::getInstance()->processBulkNodeData(&senderAddress,
|
||||||
getInstance()->_bandwidthMeter.inputStream(BandwidthMeter::AVATARS).updateValue(bytesReceived);
|
app->_incomingPacket,
|
||||||
break;
|
bytesReceived);
|
||||||
case PACKET_HEADER_AVATAR_VOXEL_URL:
|
getInstance()->_bandwidthMeter.inputStream(BandwidthMeter::AVATARS).updateValue(bytesReceived);
|
||||||
processAvatarVoxelURLMessage(app->_incomingPacket, bytesReceived);
|
break;
|
||||||
break;
|
case PACKET_TYPE_AVATAR_VOXEL_URL:
|
||||||
default:
|
processAvatarVoxelURLMessage(app->_incomingPacket, bytesReceived);
|
||||||
NodeList::getInstance()->processNodeData(&senderAddress, app->_incomingPacket, bytesReceived);
|
break;
|
||||||
break;
|
default:
|
||||||
|
NodeList::getInstance()->processNodeData(&senderAddress, app->_incomingPacket, bytesReceived);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (!app->_enableNetworkThread) {
|
} else if (!app->_enableNetworkThread) {
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -171,7 +171,7 @@ private:
|
||||||
|
|
||||||
static void sendVoxelServerAddScene();
|
static void sendVoxelServerAddScene();
|
||||||
static bool sendVoxelsOperation(VoxelNode* node, void* extraData);
|
static bool sendVoxelsOperation(VoxelNode* node, void* extraData);
|
||||||
static void sendVoxelEditMessage(PACKET_HEADER header, VoxelDetail& detail);
|
static void sendVoxelEditMessage(PACKET_TYPE type, VoxelDetail& detail);
|
||||||
static void sendAvatarVoxelURLMessage(const QUrl& url);
|
static void sendAvatarVoxelURLMessage(const QUrl& url);
|
||||||
static void processAvatarVoxelURLMessage(unsigned char *packetData, size_t dataBytes);
|
static void processAvatarVoxelURLMessage(unsigned char *packetData, size_t dataBytes);
|
||||||
static void sendPingPackets();
|
static void sendPingPackets();
|
||||||
|
@ -182,6 +182,7 @@ private:
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
void update(float deltaTime);
|
void update(float deltaTime);
|
||||||
|
bool isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection, glm::vec3& eyePosition);
|
||||||
void updateAvatar(float deltaTime);
|
void updateAvatar(float deltaTime);
|
||||||
void loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum);
|
void loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum);
|
||||||
|
|
||||||
|
|
|
@ -99,16 +99,18 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o
|
||||||
glm::vec3 headPosition = interfaceAvatar->getHeadJointPosition();
|
glm::vec3 headPosition = interfaceAvatar->getHeadJointPosition();
|
||||||
glm::quat headOrientation = interfaceAvatar->getHead().getOrientation();
|
glm::quat headOrientation = interfaceAvatar->getHead().getOrientation();
|
||||||
|
|
||||||
int leadingBytes = sizeof(PACKET_HEADER_MICROPHONE_AUDIO_NO_ECHO) + sizeof(headPosition) + sizeof(headOrientation);
|
int numBytesPacketHeader = numBytesForPacketHeader((unsigned char*) &PACKET_TYPE_MICROPHONE_AUDIO_NO_ECHO);
|
||||||
|
int leadingBytes = numBytesPacketHeader + sizeof(headPosition) + sizeof(headOrientation);
|
||||||
|
|
||||||
// we need the amount of bytes in the buffer + 1 for type
|
// we need the amount of bytes in the buffer + 1 for type
|
||||||
// + 12 for 3 floats for position + float for bearing + 1 attenuation byte
|
// + 12 for 3 floats for position + float for bearing + 1 attenuation byte
|
||||||
unsigned char dataPacket[BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes];
|
unsigned char dataPacket[BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes];
|
||||||
|
|
||||||
dataPacket[0] = (Application::getInstance()->shouldEchoAudio())
|
PACKET_TYPE packetType = (Application::getInstance()->shouldEchoAudio())
|
||||||
? PACKET_HEADER_MICROPHONE_AUDIO_WITH_ECHO
|
? PACKET_TYPE_MICROPHONE_AUDIO_WITH_ECHO
|
||||||
: PACKET_HEADER_MICROPHONE_AUDIO_NO_ECHO;
|
: PACKET_TYPE_MICROPHONE_AUDIO_NO_ECHO;
|
||||||
unsigned char *currentPacketPtr = dataPacket + 1;
|
|
||||||
|
unsigned char* currentPacketPtr = dataPacket + populateTypeAndVersion(dataPacket, packetType);
|
||||||
|
|
||||||
// memcpy the three float positions
|
// memcpy the three float positions
|
||||||
memcpy(currentPacketPtr, &headPosition, sizeof(headPosition));
|
memcpy(currentPacketPtr, &headPosition, sizeof(headPosition));
|
||||||
|
@ -446,10 +448,10 @@ void Audio::addReceivedAudioToBuffer(unsigned char* receivedData, int receivedBy
|
||||||
|
|
||||||
//printf("Got audio packet %d\n", _packetsReceivedThisPlayback);
|
//printf("Got audio packet %d\n", _packetsReceivedThisPlayback);
|
||||||
|
|
||||||
_ringBuffer.parseData((unsigned char*) receivedData, PACKET_LENGTH_BYTES + sizeof(PACKET_HEADER));
|
_ringBuffer.parseData((unsigned char*) receivedData, PACKET_LENGTH_BYTES + sizeof(PACKET_TYPE));
|
||||||
|
|
||||||
Application::getInstance()->getBandwidthMeter()->inputStream(BandwidthMeter::AUDIO)
|
Application::getInstance()->getBandwidthMeter()->inputStream(BandwidthMeter::AUDIO)
|
||||||
.updateValue(PACKET_LENGTH_BYTES + sizeof(PACKET_HEADER));
|
.updateValue(PACKET_LENGTH_BYTES + sizeof(PACKET_TYPE));
|
||||||
|
|
||||||
_lastReceiveTime = currentReceiveTime;
|
_lastReceiveTime = currentReceiveTime;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
|
|
||||||
#include <GeometryUtil.h>
|
#include <GeometryUtil.h>
|
||||||
|
#include <PacketHeaders.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
#include "Camera.h"
|
#include "Camera.h"
|
||||||
|
@ -138,8 +139,10 @@ bool Environment::findCapsulePenetration(const glm::vec3& start, const glm::vec3
|
||||||
int Environment::parseData(sockaddr *senderAddress, unsigned char* sourceBuffer, int numBytes) {
|
int Environment::parseData(sockaddr *senderAddress, unsigned char* sourceBuffer, int numBytes) {
|
||||||
// push past the packet header
|
// push past the packet header
|
||||||
unsigned char* start = sourceBuffer;
|
unsigned char* start = sourceBuffer;
|
||||||
sourceBuffer++;
|
|
||||||
numBytes--;
|
int numBytesPacketHeader = numBytesForPacketHeader(sourceBuffer);
|
||||||
|
sourceBuffer += numBytesPacketHeader;
|
||||||
|
numBytes -= numBytesPacketHeader;
|
||||||
|
|
||||||
// get the lock for the duration of the call
|
// get the lock for the duration of the call
|
||||||
QMutexLocker locker(&_mutex);
|
QMutexLocker locker(&_mutex);
|
||||||
|
|
|
@ -54,6 +54,7 @@ Head::Head(Avatar* owningAvatar) :
|
||||||
_rotation(0.0f, 0.0f, 0.0f),
|
_rotation(0.0f, 0.0f, 0.0f),
|
||||||
_leftEyePosition(0.0f, 0.0f, 0.0f),
|
_leftEyePosition(0.0f, 0.0f, 0.0f),
|
||||||
_rightEyePosition(0.0f, 0.0f, 0.0f),
|
_rightEyePosition(0.0f, 0.0f, 0.0f),
|
||||||
|
_eyeLevelPosition(0.0f, 0.0f, 0.0f),
|
||||||
_leftEyeBrowPosition(0.0f, 0.0f, 0.0f),
|
_leftEyeBrowPosition(0.0f, 0.0f, 0.0f),
|
||||||
_rightEyeBrowPosition(0.0f, 0.0f, 0.0f),
|
_rightEyeBrowPosition(0.0f, 0.0f, 0.0f),
|
||||||
_leftEarPosition(0.0f, 0.0f, 0.0f),
|
_leftEarPosition(0.0f, 0.0f, 0.0f),
|
||||||
|
@ -268,6 +269,8 @@ void Head::calculateGeometry() {
|
||||||
+ up * _scale * EYE_UP_OFFSET
|
+ up * _scale * EYE_UP_OFFSET
|
||||||
+ front * _scale * EYE_FRONT_OFFSET;
|
+ front * _scale * EYE_FRONT_OFFSET;
|
||||||
|
|
||||||
|
_eyeLevelPosition = _position + up * _scale * EYE_UP_OFFSET;
|
||||||
|
|
||||||
//calculate the eyebrow positions
|
//calculate the eyebrow positions
|
||||||
_leftEyeBrowPosition = _leftEyePosition;
|
_leftEyeBrowPosition = _leftEyePosition;
|
||||||
_rightEyeBrowPosition = _rightEyePosition;
|
_rightEyeBrowPosition = _rightEyePosition;
|
||||||
|
|
|
@ -53,7 +53,8 @@ public:
|
||||||
glm::quat getOrientation() const;
|
glm::quat getOrientation() const;
|
||||||
glm::quat getCameraOrientation () const;
|
glm::quat getCameraOrientation () const;
|
||||||
|
|
||||||
glm::vec3 getPosition() const { return _position; }
|
glm::vec3 getPosition() const { return _position; }
|
||||||
|
const glm::vec3& getEyeLevelPosition() const { return _eyeLevelPosition; }
|
||||||
glm::vec3 getRightDirection() const { return getOrientation() * IDENTITY_RIGHT; }
|
glm::vec3 getRightDirection() const { return getOrientation() * IDENTITY_RIGHT; }
|
||||||
glm::vec3 getUpDirection () const { return getOrientation() * IDENTITY_UP; }
|
glm::vec3 getUpDirection () const { return getOrientation() * IDENTITY_UP; }
|
||||||
glm::vec3 getFrontDirection() const { return getOrientation() * IDENTITY_FRONT; }
|
glm::vec3 getFrontDirection() const { return getOrientation() * IDENTITY_FRONT; }
|
||||||
|
@ -88,7 +89,8 @@ private:
|
||||||
glm::vec3 _position;
|
glm::vec3 _position;
|
||||||
glm::vec3 _rotation;
|
glm::vec3 _rotation;
|
||||||
glm::vec3 _leftEyePosition;
|
glm::vec3 _leftEyePosition;
|
||||||
glm::vec3 _rightEyePosition;
|
glm::vec3 _rightEyePosition;
|
||||||
|
glm::vec3 _eyeLevelPosition;
|
||||||
glm::vec3 _leftEyeBrowPosition;
|
glm::vec3 _leftEyeBrowPosition;
|
||||||
glm::vec3 _rightEyeBrowPosition;
|
glm::vec3 _rightEyeBrowPosition;
|
||||||
glm::vec3 _leftEarPosition;
|
glm::vec3 _leftEarPosition;
|
||||||
|
|
|
@ -3,15 +3,20 @@
|
||||||
// hifi
|
// hifi
|
||||||
//
|
//
|
||||||
// Created by Philip Rosedale on 5/20/13.
|
// Created by Philip Rosedale on 5/20/13.
|
||||||
//
|
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "Transmitter.h"
|
|
||||||
#include "InterfaceConfig.h"
|
|
||||||
#include "Util.h"
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#include <PacketHeaders.h>
|
||||||
|
|
||||||
|
#include "InterfaceConfig.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "Transmitter.h"
|
||||||
|
#include "Util.h"
|
||||||
|
|
||||||
|
|
||||||
const float DELTA_TIME = 1.f / 60.f;
|
const float DELTA_TIME = 1.f / 60.f;
|
||||||
const float DECAY_RATE = 0.15f;
|
const float DECAY_RATE = 0.15f;
|
||||||
|
@ -45,7 +50,9 @@ void Transmitter::resetLevels() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Transmitter::processIncomingData(unsigned char* packetData, int numBytes) {
|
void Transmitter::processIncomingData(unsigned char* packetData, int numBytes) {
|
||||||
const int PACKET_HEADER_SIZE = 1; // Packet's first byte is 'T'
|
// Packet's first byte is 'T'
|
||||||
|
int numBytesPacketHeader = numBytesForPacketHeader(packetData);
|
||||||
|
|
||||||
const int ROTATION_MARKER_SIZE = 1; // 'R' = Rotation (clockwise about x,y,z)
|
const int ROTATION_MARKER_SIZE = 1; // 'R' = Rotation (clockwise about x,y,z)
|
||||||
const int ACCELERATION_MARKER_SIZE = 1; // 'A' = Acceleration (x,y,z)
|
const int ACCELERATION_MARKER_SIZE = 1; // 'A' = Acceleration (x,y,z)
|
||||||
if (!_lastReceivedPacket) {
|
if (!_lastReceivedPacket) {
|
||||||
|
@ -53,10 +60,10 @@ void Transmitter::processIncomingData(unsigned char* packetData, int numBytes) {
|
||||||
}
|
}
|
||||||
gettimeofday(_lastReceivedPacket, NULL);
|
gettimeofday(_lastReceivedPacket, NULL);
|
||||||
|
|
||||||
if (numBytes == PACKET_HEADER_SIZE + ROTATION_MARKER_SIZE + ACCELERATION_MARKER_SIZE
|
if (numBytes == numBytesPacketHeader + ROTATION_MARKER_SIZE + ACCELERATION_MARKER_SIZE
|
||||||
+ sizeof(_lastRotationRate) + sizeof(_lastAcceleration)
|
+ sizeof(_lastRotationRate) + sizeof(_lastAcceleration)
|
||||||
+ sizeof(_touchState.x) + sizeof(_touchState.y) + sizeof(_touchState.state)) {
|
+ sizeof(_touchState.x) + sizeof(_touchState.y) + sizeof(_touchState.state)) {
|
||||||
unsigned char* packetDataPosition = &packetData[PACKET_HEADER_SIZE + ROTATION_MARKER_SIZE];
|
unsigned char* packetDataPosition = packetData + numBytesPacketHeader + ROTATION_MARKER_SIZE;
|
||||||
memcpy(&_lastRotationRate, packetDataPosition, sizeof(_lastRotationRate));
|
memcpy(&_lastRotationRate, packetDataPosition, sizeof(_lastRotationRate));
|
||||||
packetDataPosition += sizeof(_lastRotationRate) + ACCELERATION_MARKER_SIZE;
|
packetDataPosition += sizeof(_lastRotationRate) + ACCELERATION_MARKER_SIZE;
|
||||||
memcpy(&_lastAcceleration, packetDataPosition, sizeof(_lastAcceleration));
|
memcpy(&_lastAcceleration, packetDataPosition, sizeof(_lastAcceleration));
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// hifi
|
// hifi
|
||||||
//
|
//
|
||||||
// Created by Philip Rosedale on 5/20/13.
|
// Created by Philip Rosedale on 5/20/13.
|
||||||
//
|
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef __hifi__Transmitter__
|
#ifndef __hifi__Transmitter__
|
||||||
|
|
|
@ -537,3 +537,13 @@ float loadSetting(QSettings* settings, const char* name, float defaultValue) {
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool rayIntersectsSphere(glm::vec3& rayStarting, glm::vec3& rayNormalizedDirection, glm::vec3& sphereCenter, double sphereRadius) {
|
||||||
|
glm::vec3 vecFromRayToSphereCenter = sphereCenter - rayStarting;
|
||||||
|
double projection = glm::dot(vecFromRayToSphereCenter, rayNormalizedDirection);
|
||||||
|
double shortestDistance = sqrt(glm::dot(vecFromRayToSphereCenter, vecFromRayToSphereCenter) - projection * projection);
|
||||||
|
if (shortestDistance <= sphereRadius) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -71,4 +71,6 @@ void runTimingTests();
|
||||||
|
|
||||||
float loadSetting(QSettings* settings, const char* name, float defaultValue);
|
float loadSetting(QSettings* settings, const char* name, float defaultValue);
|
||||||
|
|
||||||
|
bool rayIntersectsSphere(glm::vec3& rayStarting, glm::vec3& rayNormalizedDirection, glm::vec3& sphereCenter, double sphereRadius);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -113,32 +113,31 @@ float VoxelSystem::getVoxelsBytesReadPerSecondAverage() {
|
||||||
int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
|
int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
|
||||||
|
|
||||||
unsigned char command = *sourceBuffer;
|
unsigned char command = *sourceBuffer;
|
||||||
unsigned char *voxelData = sourceBuffer + 1;
|
int numBytesPacketHeader = numBytesForPacketHeader(sourceBuffer);
|
||||||
|
unsigned char* voxelData = sourceBuffer + numBytesPacketHeader;
|
||||||
|
|
||||||
pthread_mutex_lock(&_treeLock);
|
pthread_mutex_lock(&_treeLock);
|
||||||
|
|
||||||
switch(command) {
|
switch(command) {
|
||||||
case PACKET_HEADER_VOXEL_DATA:
|
case PACKET_TYPE_VOXEL_DATA: {
|
||||||
{
|
|
||||||
PerformanceWarning warn(_renderWarningsOn, "readBitstreamToTree()");
|
PerformanceWarning warn(_renderWarningsOn, "readBitstreamToTree()");
|
||||||
// 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, WANT_COLOR, WANT_EXISTS_BITS);
|
_tree->readBitstreamToTree(voxelData, numBytes - numBytesPacketHeader, WANT_COLOR, WANT_EXISTS_BITS);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PACKET_HEADER_VOXEL_DATA_MONOCHROME:
|
case PACKET_TYPE_VOXEL_DATA_MONOCHROME: {
|
||||||
{
|
|
||||||
PerformanceWarning warn(_renderWarningsOn, "readBitstreamToTree()");
|
PerformanceWarning warn(_renderWarningsOn, "readBitstreamToTree()");
|
||||||
// ask the VoxelTree to read the MONOCHROME bitstream into the tree
|
// ask the VoxelTree to read the MONOCHROME bitstream into the tree
|
||||||
_tree->readBitstreamToTree(voxelData, numBytes - 1, NO_COLOR, WANT_EXISTS_BITS);
|
_tree->readBitstreamToTree(voxelData, numBytes - numBytesPacketHeader, NO_COLOR, WANT_EXISTS_BITS);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PACKET_HEADER_Z_COMMAND:
|
case PACKET_TYPE_Z_COMMAND:
|
||||||
|
|
||||||
// the Z command is a special command that allows the sender to send high level semantic
|
// the Z command is a special command that allows the sender to send high level semantic
|
||||||
// requests, like erase all, or add sphere scene, different receivers may handle these
|
// requests, like erase all, or add sphere scene, different receivers may handle these
|
||||||
// messages differently
|
// messages differently
|
||||||
char* packetData = (char *)sourceBuffer;
|
char* packetData = (char *)sourceBuffer;
|
||||||
char* command = &packetData[1]; // start of the command
|
char* command = &packetData[numBytesPacketHeader]; // start of the command
|
||||||
int commandLength = strlen(command); // commands are null terminated strings
|
int commandLength = strlen(command); // commands are null terminated strings
|
||||||
int totalLength = 1+commandLength+1;
|
int totalLength = 1+commandLength+1;
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ void Webcam::setEnabled(bool enabled) {
|
||||||
QMetaObject::invokeMethod(_grabber, "grabFrame");
|
QMetaObject::invokeMethod(_grabber, "grabFrame");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_grabberThread.quit();
|
QMetaObject::invokeMethod(_grabber, "shutdown");
|
||||||
_active = false;
|
_active = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,8 +267,8 @@ FrameGrabber::FrameGrabber() : _initialized(false), _capture(0), _searchWindow(0
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameGrabber::~FrameGrabber() {
|
FrameGrabber::~FrameGrabber() {
|
||||||
if (_capture != 0) {
|
if (_initialized) {
|
||||||
cvReleaseCapture(&_capture);
|
shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,6 +366,16 @@ void FrameGrabber::reset() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FrameGrabber::shutdown() {
|
||||||
|
if (_capture != 0) {
|
||||||
|
cvReleaseCapture(&_capture);
|
||||||
|
_capture = 0;
|
||||||
|
}
|
||||||
|
_initialized = false;
|
||||||
|
|
||||||
|
thread()->quit();
|
||||||
|
}
|
||||||
|
|
||||||
void FrameGrabber::grabFrame() {
|
void FrameGrabber::grabFrame() {
|
||||||
if (!(_initialized || init())) {
|
if (!(_initialized || init())) {
|
||||||
return;
|
return;
|
||||||
|
@ -475,7 +485,7 @@ bool FrameGrabber::init() {
|
||||||
|
|
||||||
// load our face cascade
|
// load our face cascade
|
||||||
switchToResourcesParentIfRequired();
|
switchToResourcesParentIfRequired();
|
||||||
if (!_faceCascade.load("resources/haarcascades/haarcascade_frontalface_alt.xml")) {
|
if (_faceCascade.empty() && !_faceCascade.load("resources/haarcascades/haarcascade_frontalface_alt.xml")) {
|
||||||
printLog("Failed to load Haar cascade for face tracking.\n");
|
printLog("Failed to load Haar cascade for face tracking.\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,7 @@ public:
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
void shutdown();
|
||||||
void grabFrame();
|
void grabFrame();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -70,7 +70,7 @@ void AudioInjector::injectAudio(UDPSocket* injectorSocket, sockaddr* destination
|
||||||
timeval startTime;
|
timeval startTime;
|
||||||
|
|
||||||
// calculate the number of bytes required for additional data
|
// calculate the number of bytes required for additional data
|
||||||
int leadingBytes = sizeof(PACKET_HEADER)
|
int leadingBytes = numBytesForPacketHeader((unsigned char*) &PACKET_TYPE_INJECT_AUDIO)
|
||||||
+ sizeof(_streamIdentifier)
|
+ sizeof(_streamIdentifier)
|
||||||
+ sizeof(_position)
|
+ sizeof(_position)
|
||||||
+ sizeof(_orientation)
|
+ sizeof(_orientation)
|
||||||
|
@ -79,8 +79,7 @@ void AudioInjector::injectAudio(UDPSocket* injectorSocket, sockaddr* destination
|
||||||
|
|
||||||
unsigned char dataPacket[(BUFFER_LENGTH_SAMPLES_PER_CHANNEL * sizeof(int16_t)) + leadingBytes];
|
unsigned char dataPacket[(BUFFER_LENGTH_SAMPLES_PER_CHANNEL * sizeof(int16_t)) + leadingBytes];
|
||||||
|
|
||||||
dataPacket[0] = PACKET_HEADER_INJECT_AUDIO;
|
unsigned char* currentPacketPtr = dataPacket + populateTypeAndVersion(dataPacket, PACKET_TYPE_INJECT_AUDIO);
|
||||||
unsigned char *currentPacketPtr = dataPacket + sizeof(PACKET_HEADER_INJECT_AUDIO);
|
|
||||||
|
|
||||||
// copy the identifier for this injector
|
// copy the identifier for this injector
|
||||||
memcpy(currentPacketPtr, &_streamIdentifier, sizeof(_streamIdentifier));
|
memcpy(currentPacketPtr, &_streamIdentifier, sizeof(_streamIdentifier));
|
||||||
|
|
|
@ -34,7 +34,8 @@ void AudioRingBuffer::reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int AudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) {
|
int AudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) {
|
||||||
return parseAudioSamples(sourceBuffer + sizeof(PACKET_HEADER_MIXED_AUDIO), numBytes - sizeof(PACKET_HEADER_MIXED_AUDIO));
|
int numBytesPacketHeader = numBytesForPacketHeader(sourceBuffer);
|
||||||
|
return parseAudioSamples(sourceBuffer + numBytesPacketHeader, numBytes - numBytesPacketHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
int AudioRingBuffer::parseAudioSamples(unsigned char* sourceBuffer, int numBytes) {
|
int AudioRingBuffer::parseAudioSamples(unsigned char* sourceBuffer, int numBytes) {
|
||||||
|
|
|
@ -176,12 +176,13 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// increment to push past the packet header
|
// increment to push past the packet header
|
||||||
sourceBuffer += sizeof(PACKET_HEADER_HEAD_DATA);
|
int numBytesPacketHeader = numBytesForPacketHeader(sourceBuffer);
|
||||||
|
sourceBuffer += numBytesPacketHeader;
|
||||||
|
|
||||||
unsigned char* startPosition = sourceBuffer;
|
unsigned char* startPosition = sourceBuffer;
|
||||||
|
|
||||||
// push past the node ID
|
// push past the node ID
|
||||||
sourceBuffer += + sizeof(uint16_t);
|
sourceBuffer += sizeof(uint16_t);
|
||||||
|
|
||||||
// Body world position
|
// Body world position
|
||||||
memcpy(&_position, sourceBuffer, sizeof(float) * 3);
|
memcpy(&_position, sourceBuffer, sizeof(float) * 3);
|
||||||
|
|
|
@ -72,7 +72,6 @@ NodeList::~NodeList() {
|
||||||
|
|
||||||
// stop the spawned threads, if they were started
|
// stop the spawned threads, if they were started
|
||||||
stopSilentNodeRemovalThread();
|
stopSilentNodeRemovalThread();
|
||||||
stopPingUnknownNodesThread();
|
|
||||||
|
|
||||||
pthread_mutex_destroy(&mutex);
|
pthread_mutex_destroy(&mutex);
|
||||||
}
|
}
|
||||||
|
@ -81,27 +80,29 @@ void NodeList::timePingReply(sockaddr *nodeAddress, unsigned char *packetData) {
|
||||||
for(NodeList::iterator node = begin(); node != end(); node++) {
|
for(NodeList::iterator node = begin(); node != end(); node++) {
|
||||||
if (socketMatch(node->getPublicSocket(), nodeAddress) ||
|
if (socketMatch(node->getPublicSocket(), nodeAddress) ||
|
||||||
socketMatch(node->getLocalSocket(), nodeAddress)) {
|
socketMatch(node->getLocalSocket(), nodeAddress)) {
|
||||||
int pingTime = usecTimestampNow() - *(uint64_t *)(packetData + 1);
|
|
||||||
|
int pingTime = usecTimestampNow() - *(uint64_t*)(packetData + numBytesForPacketHeader(packetData));
|
||||||
|
|
||||||
node->setPingMs(pingTime / 1000);
|
node->setPingMs(pingTime / 1000);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeList::processNodeData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes) {
|
void NodeList::processNodeData(sockaddr* senderAddress, unsigned char* packetData, size_t dataBytes) {
|
||||||
switch (((char *)packetData)[0]) {
|
switch (packetData[0]) {
|
||||||
case PACKET_HEADER_DOMAIN: {
|
case PACKET_TYPE_DOMAIN: {
|
||||||
processDomainServerList(packetData, dataBytes);
|
processDomainServerList(packetData, dataBytes);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PACKET_HEADER_PING: {
|
case PACKET_TYPE_PING: {
|
||||||
char pingPacket[dataBytes];
|
char pingPacket[dataBytes];
|
||||||
memcpy(pingPacket, packetData, dataBytes);
|
memcpy(pingPacket, packetData, dataBytes);
|
||||||
pingPacket[0] = PACKET_HEADER_PING_REPLY;
|
populateTypeAndVersion((unsigned char*) pingPacket, PACKET_TYPE_PING_REPLY);
|
||||||
_nodeSocket.send(senderAddress, pingPacket, dataBytes);
|
_nodeSocket.send(senderAddress, pingPacket, dataBytes);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PACKET_HEADER_PING_REPLY: {
|
case PACKET_TYPE_PING_REPLY: {
|
||||||
timePingReply(senderAddress, packetData);
|
timePingReply(senderAddress, packetData);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -118,18 +119,23 @@ void NodeList::processBulkNodeData(sockaddr *senderAddress, unsigned char *packe
|
||||||
bulkSendNode->setLastHeardMicrostamp(usecTimestampNow());
|
bulkSendNode->setLastHeardMicrostamp(usecTimestampNow());
|
||||||
bulkSendNode->recordBytesReceived(numTotalBytes);
|
bulkSendNode->recordBytesReceived(numTotalBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int numBytesPacketHeader = numBytesForPacketHeader(packetData);
|
||||||
|
|
||||||
unsigned char *startPosition = packetData;
|
unsigned char *startPosition = packetData;
|
||||||
unsigned char *currentPosition = startPosition + 1;
|
unsigned char *currentPosition = startPosition + numBytesPacketHeader;
|
||||||
unsigned char packetHolder[numTotalBytes];
|
unsigned char packetHolder[numTotalBytes];
|
||||||
|
|
||||||
packetHolder[0] = PACKET_HEADER_HEAD_DATA;
|
// we've already verified packet version for the bulk packet, so all head data in the packet is also up to date
|
||||||
|
populateTypeAndVersion(packetHolder, PACKET_TYPE_HEAD_DATA);
|
||||||
|
|
||||||
uint16_t nodeID = -1;
|
uint16_t nodeID = -1;
|
||||||
|
|
||||||
while ((currentPosition - startPosition) < numTotalBytes) {
|
while ((currentPosition - startPosition) < numTotalBytes) {
|
||||||
unpackNodeId(currentPosition, &nodeID);
|
unpackNodeId(currentPosition, &nodeID);
|
||||||
memcpy(packetHolder + 1, currentPosition, numTotalBytes - (currentPosition - startPosition));
|
memcpy(packetHolder + numBytesPacketHeader,
|
||||||
|
currentPosition,
|
||||||
|
numTotalBytes - (currentPosition - startPosition));
|
||||||
|
|
||||||
Node* matchingNode = nodeWithID(nodeID);
|
Node* matchingNode = nodeWithID(nodeID);
|
||||||
|
|
||||||
|
@ -139,8 +145,8 @@ void NodeList::processBulkNodeData(sockaddr *senderAddress, unsigned char *packe
|
||||||
}
|
}
|
||||||
|
|
||||||
currentPosition += updateNodeWithData(matchingNode,
|
currentPosition += updateNodeWithData(matchingNode,
|
||||||
packetHolder,
|
packetHolder,
|
||||||
numTotalBytes - (currentPosition - startPosition));
|
numTotalBytes - (currentPosition - startPosition));
|
||||||
}
|
}
|
||||||
|
|
||||||
unlock();
|
unlock();
|
||||||
|
@ -213,6 +219,7 @@ void NodeList::setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNo
|
||||||
|
|
||||||
void NodeList::sendDomainServerCheckIn() {
|
void NodeList::sendDomainServerCheckIn() {
|
||||||
static bool printedDomainServerIP = false;
|
static bool printedDomainServerIP = false;
|
||||||
|
|
||||||
// Lookup the IP address of the domain server if we need to
|
// Lookup the IP address of the domain server if we need to
|
||||||
if (atoi(DOMAIN_IP) == 0) {
|
if (atoi(DOMAIN_IP) == 0) {
|
||||||
struct hostent* pHostInfo;
|
struct hostent* pHostInfo;
|
||||||
|
@ -229,26 +236,32 @@ void NodeList::sendDomainServerCheckIn() {
|
||||||
printedDomainServerIP = true;
|
printedDomainServerIP = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// construct the DS check in packet if we need to
|
|
||||||
static unsigned char* checkInPacket = NULL;
|
static unsigned char* checkInPacket = NULL;
|
||||||
static int checkInPacketSize;
|
static int checkInPacketSize = 0;
|
||||||
|
|
||||||
|
// construct the DS check in packet if we need to
|
||||||
if (!checkInPacket) {
|
if (!checkInPacket) {
|
||||||
int numBytesNodesOfInterest = _nodeTypesOfInterest ? strlen((char*) _nodeTypesOfInterest) : 0;
|
int numBytesNodesOfInterest = _nodeTypesOfInterest ? strlen((char*) _nodeTypesOfInterest) : 0;
|
||||||
|
|
||||||
|
const int IP_ADDRESS_BYTES = 4;
|
||||||
|
|
||||||
// check in packet has header, node type, port, IP, node types of interest, null termination
|
// check in packet has header, node type, port, IP, node types of interest, null termination
|
||||||
int numPacketBytes = sizeof(PACKET_HEADER) + sizeof(NODE_TYPE) + sizeof(uint16_t) + (sizeof(char) * 4) +
|
int numPacketBytes = sizeof(PACKET_TYPE) + sizeof(PACKET_VERSION) + sizeof(NODE_TYPE) + sizeof(uint16_t) +
|
||||||
numBytesNodesOfInterest + sizeof(unsigned char);
|
IP_ADDRESS_BYTES + numBytesNodesOfInterest + sizeof(unsigned char);
|
||||||
|
|
||||||
checkInPacket = new unsigned char[numPacketBytes];
|
checkInPacket = new unsigned char[numPacketBytes];
|
||||||
unsigned char* packetPosition = checkInPacket;
|
unsigned char* packetPosition = checkInPacket;
|
||||||
|
|
||||||
*(packetPosition++) = (memchr(SOLO_NODE_TYPES, _ownerType, sizeof(SOLO_NODE_TYPES)))
|
PACKET_TYPE nodePacketType = (memchr(SOLO_NODE_TYPES, _ownerType, sizeof(SOLO_NODE_TYPES)))
|
||||||
? PACKET_HEADER_DOMAIN_REPORT_FOR_DUTY
|
? PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY
|
||||||
: PACKET_HEADER_DOMAIN_LIST_REQUEST;
|
: PACKET_TYPE_DOMAIN_LIST_REQUEST;
|
||||||
|
|
||||||
|
int numHeaderBytes = populateTypeAndVersion(packetPosition, nodePacketType);
|
||||||
|
packetPosition += numHeaderBytes;
|
||||||
|
|
||||||
*(packetPosition++) = _ownerType;
|
*(packetPosition++) = _ownerType;
|
||||||
|
|
||||||
packetPosition += packSocket(checkInPacket + sizeof(PACKET_HEADER) + sizeof(NODE_TYPE),
|
packetPosition += packSocket(checkInPacket + numHeaderBytes + sizeof(NODE_TYPE),
|
||||||
getLocalAddress(),
|
getLocalAddress(),
|
||||||
htons(_nodeSocket.getListeningPort()));
|
htons(_nodeSocket.getListeningPort()));
|
||||||
|
|
||||||
|
@ -269,7 +282,7 @@ void NodeList::sendDomainServerCheckIn() {
|
||||||
_nodeSocket.send(DOMAIN_IP, DOMAINSERVER_PORT, checkInPacket, checkInPacketSize);
|
_nodeSocket.send(DOMAIN_IP, DOMAINSERVER_PORT, checkInPacket, checkInPacketSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
int NodeList::processDomainServerList(unsigned char *packetData, size_t dataBytes) {
|
int NodeList::processDomainServerList(unsigned char* packetData, size_t dataBytes) {
|
||||||
int readNodes = 0;
|
int readNodes = 0;
|
||||||
|
|
||||||
char nodeType;
|
char nodeType;
|
||||||
|
@ -281,16 +294,16 @@ int NodeList::processDomainServerList(unsigned char *packetData, size_t dataByte
|
||||||
sockaddr_in nodeLocalSocket;
|
sockaddr_in nodeLocalSocket;
|
||||||
nodeLocalSocket.sin_family = AF_INET;
|
nodeLocalSocket.sin_family = AF_INET;
|
||||||
|
|
||||||
unsigned char *readPtr = packetData + 1;
|
unsigned char* readPtr = packetData + numBytesForPacketHeader(packetData);
|
||||||
unsigned char *startPtr = packetData;
|
unsigned char* startPtr = packetData;
|
||||||
|
|
||||||
while((readPtr - startPtr) < dataBytes - sizeof(uint16_t)) {
|
while((readPtr - startPtr) < dataBytes - sizeof(uint16_t)) {
|
||||||
nodeType = *readPtr++;
|
nodeType = *readPtr++;
|
||||||
readPtr += unpackNodeId(readPtr, (uint16_t *)&nodeId);
|
readPtr += unpackNodeId(readPtr, (uint16_t*) &nodeId);
|
||||||
readPtr += unpackSocket(readPtr, (sockaddr *)&nodePublicSocket);
|
readPtr += unpackSocket(readPtr, (sockaddr*) &nodePublicSocket);
|
||||||
readPtr += unpackSocket(readPtr, (sockaddr *)&nodeLocalSocket);
|
readPtr += unpackSocket(readPtr, (sockaddr*) &nodeLocalSocket);
|
||||||
|
|
||||||
addOrUpdateNode((sockaddr *)&nodePublicSocket, (sockaddr *)&nodeLocalSocket, nodeType, nodeId);
|
addOrUpdateNode((sockaddr*) &nodePublicSocket, (sockaddr*) &nodeLocalSocket, nodeType, nodeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// read out our ID from the packet
|
// read out our ID from the packet
|
||||||
|
@ -401,46 +414,6 @@ Node* NodeList::soloNodeOfType(char nodeType) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *pingUnknownNodes(void *args) {
|
|
||||||
|
|
||||||
NodeList* nodeList = (NodeList*) args;
|
|
||||||
const int PING_INTERVAL_USECS = 1 * 1000000;
|
|
||||||
|
|
||||||
timeval lastSend;
|
|
||||||
|
|
||||||
while (!pingUnknownNodeThreadStopFlag) {
|
|
||||||
gettimeofday(&lastSend, NULL);
|
|
||||||
|
|
||||||
for(NodeList::iterator node = nodeList->begin();
|
|
||||||
node != nodeList->end();
|
|
||||||
node++) {
|
|
||||||
if (!node->getActiveSocket() && node->getPublicSocket() && node->getLocalSocket()) {
|
|
||||||
// ping both of the sockets for the node so we can figure out
|
|
||||||
// which socket we can use
|
|
||||||
nodeList->getNodeSocket()->send(node->getPublicSocket(), &PACKET_HEADER_PING, 1);
|
|
||||||
nodeList->getNodeSocket()->send(node->getLocalSocket(), &PACKET_HEADER_PING, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int usecToSleep = PING_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&lastSend));
|
|
||||||
|
|
||||||
if (usecToSleep > 0) {
|
|
||||||
usleep(usecToSleep);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NodeList::startPingUnknownNodesThread() {
|
|
||||||
pthread_create(&pingUnknownNodesThread, NULL, pingUnknownNodes, (void *)this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NodeList::stopPingUnknownNodesThread() {
|
|
||||||
pingUnknownNodeThreadStopFlag = true;
|
|
||||||
pthread_join(pingUnknownNodesThread, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *removeSilentNodes(void *args) {
|
void *removeSilentNodes(void *args) {
|
||||||
NodeList* nodeList = (NodeList*) args;
|
NodeList* nodeList = (NodeList*) args;
|
||||||
uint64_t checkTimeUSecs;
|
uint64_t checkTimeUSecs;
|
||||||
|
|
|
@ -89,8 +89,6 @@ public:
|
||||||
|
|
||||||
void startSilentNodeRemovalThread();
|
void startSilentNodeRemovalThread();
|
||||||
void stopSilentNodeRemovalThread();
|
void stopSilentNodeRemovalThread();
|
||||||
void startPingUnknownNodesThread();
|
|
||||||
void stopPingUnknownNodesThread();
|
|
||||||
|
|
||||||
friend class NodeListIterator;
|
friend class NodeListIterator;
|
||||||
private:
|
private:
|
||||||
|
@ -113,7 +111,6 @@ private:
|
||||||
uint16_t _lastNodeID;
|
uint16_t _lastNodeID;
|
||||||
pthread_t removeSilentNodesThread;
|
pthread_t removeSilentNodesThread;
|
||||||
pthread_t checkInWithDomainServerThread;
|
pthread_t checkInWithDomainServerThread;
|
||||||
pthread_t pingUnknownNodesThread;
|
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
|
|
||||||
void handlePingReply(sockaddr *nodeAddress);
|
void handlePingReply(sockaddr *nodeAddress);
|
||||||
|
|
62
libraries/shared/src/PacketHeaders.cpp
Normal file
62
libraries/shared/src/PacketHeaders.cpp
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
//
|
||||||
|
// PacketHeaders.cpp
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Stephen Birarda on 6/28/13.
|
||||||
|
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "PacketHeaders.h"
|
||||||
|
|
||||||
|
PACKET_VERSION versionForPacketType(PACKET_TYPE type) {
|
||||||
|
switch (type) {
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool packetVersionMatch(unsigned char* packetHeader) {
|
||||||
|
// currently this just checks if the version in the packet matches our return from versionForPacketType
|
||||||
|
// may need to be expanded in the future for types and versions that take > than 1 byte
|
||||||
|
if (packetHeader[1] == versionForPacketType(packetHeader[0])) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
printf("There is a packet version mismatch for packet with header %c\n", packetHeader[0]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int populateTypeAndVersion(unsigned char* destinationHeader, PACKET_TYPE type) {
|
||||||
|
destinationHeader[0] = type;
|
||||||
|
destinationHeader[1] = versionForPacketType(type);
|
||||||
|
|
||||||
|
// return the number of bytes written for pointer pushing
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int numBytesForPacketType(const unsigned char* packetType) {
|
||||||
|
if (packetType[0] == 255) {
|
||||||
|
return 1 + numBytesForPacketType(packetType + 1);
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int numBytesForPacketVersion(const unsigned char* packetVersion) {
|
||||||
|
if (packetVersion[0] == 255) {
|
||||||
|
return 1 + numBytesForPacketVersion(packetVersion + 1);
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int numBytesForPacketHeader(unsigned char* packetHeader) {
|
||||||
|
// int numBytesType = numBytesForPacketType(packetHeader);
|
||||||
|
// return numBytesType + numBytesForPacketVersion(packetHeader + numBytesType);
|
||||||
|
|
||||||
|
// currently this need not be dynamic - there are 2 bytes for each packet header
|
||||||
|
return 2;
|
||||||
|
}
|
|
@ -12,28 +12,38 @@
|
||||||
#ifndef hifi_PacketHeaders_h
|
#ifndef hifi_PacketHeaders_h
|
||||||
#define hifi_PacketHeaders_h
|
#define hifi_PacketHeaders_h
|
||||||
|
|
||||||
typedef char PACKET_HEADER;
|
typedef char PACKET_TYPE;
|
||||||
const PACKET_HEADER PACKET_HEADER_DOMAIN = 'D';
|
const PACKET_TYPE PACKET_TYPE_DOMAIN = 'D';
|
||||||
const PACKET_HEADER PACKET_HEADER_PING = 'P';
|
const PACKET_TYPE PACKET_TYPE_PING = 'P';
|
||||||
const PACKET_HEADER PACKET_HEADER_PING_REPLY = 'R';
|
const PACKET_TYPE PACKET_TYPE_PING_REPLY = 'R';
|
||||||
const PACKET_HEADER PACKET_HEADER_HEAD_DATA = 'H';
|
const PACKET_TYPE PACKET_TYPE_HEAD_DATA = 'H';
|
||||||
const PACKET_HEADER PACKET_HEADER_Z_COMMAND = 'Z';
|
const PACKET_TYPE PACKET_TYPE_Z_COMMAND = 'Z';
|
||||||
const PACKET_HEADER PACKET_HEADER_INJECT_AUDIO = 'I';
|
const PACKET_TYPE PACKET_TYPE_INJECT_AUDIO = 'I';
|
||||||
const PACKET_HEADER PACKET_HEADER_MIXED_AUDIO = 'A';
|
const PACKET_TYPE PACKET_TYPE_MIXED_AUDIO = 'A';
|
||||||
const PACKET_HEADER PACKET_HEADER_MICROPHONE_AUDIO_NO_ECHO = 'M';
|
const PACKET_TYPE PACKET_TYPE_MICROPHONE_AUDIO_NO_ECHO = 'M';
|
||||||
const PACKET_HEADER PACKET_HEADER_MICROPHONE_AUDIO_WITH_ECHO = 'm';
|
const PACKET_TYPE PACKET_TYPE_MICROPHONE_AUDIO_WITH_ECHO = 'm';
|
||||||
const PACKET_HEADER PACKET_HEADER_SET_VOXEL = 'S';
|
const PACKET_TYPE PACKET_TYPE_SET_VOXEL = 'S';
|
||||||
const PACKET_HEADER PACKET_HEADER_SET_VOXEL_DESTRUCTIVE = 'O';
|
const PACKET_TYPE PACKET_TYPE_SET_VOXEL_DESTRUCTIVE = 'O';
|
||||||
const PACKET_HEADER PACKET_HEADER_ERASE_VOXEL = 'E';
|
const PACKET_TYPE PACKET_TYPE_ERASE_VOXEL = 'E';
|
||||||
const PACKET_HEADER PACKET_HEADER_VOXEL_DATA = 'V';
|
const PACKET_TYPE PACKET_TYPE_VOXEL_DATA = 'V';
|
||||||
const PACKET_HEADER PACKET_HEADER_VOXEL_DATA_MONOCHROME = 'v';
|
const PACKET_TYPE PACKET_TYPE_VOXEL_DATA_MONOCHROME = 'v';
|
||||||
const PACKET_HEADER PACKET_HEADER_BULK_AVATAR_DATA = 'X';
|
const PACKET_TYPE PACKET_TYPE_BULK_AVATAR_DATA = 'X';
|
||||||
const PACKET_HEADER PACKET_HEADER_AVATAR_VOXEL_URL = 'U';
|
const PACKET_TYPE PACKET_TYPE_AVATAR_VOXEL_URL = 'U';
|
||||||
const PACKET_HEADER PACKET_HEADER_TRANSMITTER_DATA_V2 = 'T';
|
const PACKET_TYPE PACKET_TYPE_TRANSMITTER_DATA_V2 = 'T';
|
||||||
const PACKET_HEADER PACKET_HEADER_ENVIRONMENT_DATA = 'e';
|
const PACKET_TYPE PACKET_TYPE_ENVIRONMENT_DATA = 'e';
|
||||||
const PACKET_HEADER PACKET_HEADER_DOMAIN_LIST_REQUEST = 'L';
|
const PACKET_TYPE PACKET_TYPE_DOMAIN_LIST_REQUEST = 'L';
|
||||||
const PACKET_HEADER PACKET_HEADER_DOMAIN_REPORT_FOR_DUTY = 'C';
|
const PACKET_TYPE PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY = 'C';
|
||||||
|
|
||||||
|
typedef char PACKET_VERSION;
|
||||||
|
|
||||||
|
PACKET_VERSION versionForPacketType(PACKET_TYPE type);
|
||||||
|
|
||||||
|
bool packetVersionMatch(unsigned char* packetHeader);
|
||||||
|
|
||||||
|
int populateTypeAndVersion(unsigned char* destinationHeader, PACKET_TYPE type);
|
||||||
|
int numBytesForPacketHeader(unsigned char* packetHeader);
|
||||||
|
|
||||||
|
const int MAX_PACKET_HEADER_BYTES = sizeof(PACKET_TYPE) + sizeof(PACKET_VERSION);
|
||||||
|
|
||||||
// These are supported Z-Command
|
// These are supported Z-Command
|
||||||
#define ERASE_ALL_COMMAND "erase all"
|
#define ERASE_ALL_COMMAND "erase all"
|
||||||
|
|
|
@ -11,17 +11,20 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include "Syssocket.h"
|
#include "Syssocket.h"
|
||||||
#endif
|
#endif
|
||||||
#include "Log.h"
|
|
||||||
#include "SharedUtil.h"
|
|
||||||
#include "OctalCode.h"
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "Log.h"
|
||||||
|
#include "OctalCode.h"
|
||||||
|
#include "PacketHeaders.h"
|
||||||
|
#include "SharedUtil.h"
|
||||||
|
|
||||||
uint64_t usecTimestamp(timeval *time) {
|
uint64_t usecTimestamp(timeval *time) {
|
||||||
return (time->tv_sec * 1000000 + time->tv_usec);
|
return (time->tv_sec * 1000000 + time->tv_usec);
|
||||||
}
|
}
|
||||||
|
@ -209,13 +212,14 @@ bool createVoxelEditMessage(unsigned char command, short int sequence,
|
||||||
int messageSize = MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE; // just a guess for now
|
int messageSize = MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE; // just a guess for now
|
||||||
int actualMessageSize = 3;
|
int actualMessageSize = 3;
|
||||||
unsigned char* messageBuffer = new unsigned char[messageSize];
|
unsigned char* messageBuffer = new unsigned char[messageSize];
|
||||||
unsigned short int* sequenceAt = (unsigned short int*)&messageBuffer[1];
|
|
||||||
|
|
||||||
messageBuffer[0]=command;
|
int numBytesPacketHeader = populateTypeAndVersion(messageBuffer, command);
|
||||||
*sequenceAt=sequence;
|
unsigned short int* sequenceAt = (unsigned short int*) &messageBuffer[numBytesPacketHeader];
|
||||||
unsigned char* copyAt = &messageBuffer[3];
|
|
||||||
|
*sequenceAt = sequence;
|
||||||
|
unsigned char* copyAt = &messageBuffer[numBytesPacketHeader + sizeof(sequence)];
|
||||||
|
|
||||||
for (int i=0;i<voxelCount && success;i++) {
|
for (int i = 0; i < voxelCount && success; i++) {
|
||||||
// get the coded voxel
|
// get the coded voxel
|
||||||
unsigned char* voxelData = pointToVoxel(voxelDetails[i].x,voxelDetails[i].y,voxelDetails[i].z,
|
unsigned char* voxelData = pointToVoxel(voxelDetails[i].x,voxelDetails[i].y,voxelDetails[i].z,
|
||||||
voxelDetails[i].s,voxelDetails[i].red,voxelDetails[i].green,voxelDetails[i].blue);
|
voxelDetails[i].s,voxelDetails[i].red,voxelDetails[i].green,voxelDetails[i].blue);
|
||||||
|
@ -224,12 +228,12 @@ bool createVoxelEditMessage(unsigned char command, short int sequence,
|
||||||
|
|
||||||
// make sure we have room to copy this voxel
|
// make sure we have room to copy this voxel
|
||||||
if (actualMessageSize+lengthOfVoxelData > MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE) {
|
if (actualMessageSize+lengthOfVoxelData > MAXIMUM_EDIT_VOXEL_MESSAGE_SIZE) {
|
||||||
success=false;
|
success = false;
|
||||||
} else {
|
} else {
|
||||||
// add it to our message
|
// add it to our message
|
||||||
memcpy(copyAt,voxelData,lengthOfVoxelData);
|
memcpy(copyAt, voxelData, lengthOfVoxelData);
|
||||||
copyAt+=lengthOfVoxelData;
|
copyAt += lengthOfVoxelData;
|
||||||
actualMessageSize+=lengthOfVoxelData;
|
actualMessageSize += lengthOfVoxelData;
|
||||||
}
|
}
|
||||||
// cleanup
|
// cleanup
|
||||||
delete[] voxelData;
|
delete[] voxelData;
|
||||||
|
@ -238,9 +242,10 @@ bool createVoxelEditMessage(unsigned char command, short int sequence,
|
||||||
if (success) {
|
if (success) {
|
||||||
// finally, copy the result to the output
|
// finally, copy the result to the output
|
||||||
bufferOut = new unsigned char[actualMessageSize];
|
bufferOut = new unsigned char[actualMessageSize];
|
||||||
sizeOut=actualMessageSize;
|
sizeOut = actualMessageSize;
|
||||||
memcpy(bufferOut,messageBuffer,actualMessageSize);
|
memcpy(bufferOut, messageBuffer, actualMessageSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] messageBuffer; // clean up our temporary buffer
|
delete[] messageBuffer; // clean up our temporary buffer
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -596,7 +596,7 @@ void VoxelTree::readCodeColorBufferToTreeRecursion(VoxelNode* node, void* extraD
|
||||||
|
|
||||||
void VoxelTree::processRemoveVoxelBitstream(unsigned char * bitstream, int bufferSizeBytes) {
|
void VoxelTree::processRemoveVoxelBitstream(unsigned char * bitstream, int bufferSizeBytes) {
|
||||||
//unsigned short int itemNumber = (*((unsigned short int*)&bitstream[sizeof(PACKET_HEADER)]));
|
//unsigned short int itemNumber = (*((unsigned short int*)&bitstream[sizeof(PACKET_HEADER)]));
|
||||||
int atByte = sizeof(short int) + sizeof(PACKET_HEADER);
|
int atByte = sizeof(short int) + numBytesForPacketHeader(bitstream);
|
||||||
unsigned char* voxelCode = (unsigned char*)&bitstream[atByte];
|
unsigned char* voxelCode = (unsigned char*)&bitstream[atByte];
|
||||||
while (atByte < bufferSizeBytes) {
|
while (atByte < bufferSizeBytes) {
|
||||||
int codeLength = numberOfThreeBitSectionsInCode(voxelCode);
|
int codeLength = numberOfThreeBitSectionsInCode(voxelCode);
|
||||||
|
|
|
@ -29,13 +29,13 @@ VoxelNodeData::VoxelNodeData(Node* owningNode) :
|
||||||
|
|
||||||
|
|
||||||
void VoxelNodeData::resetVoxelPacket() {
|
void VoxelNodeData::resetVoxelPacket() {
|
||||||
|
|
||||||
// If we're moving, and the client asked for low res, then we force monochrome, otherwise, use
|
// If we're moving, and the client asked for low res, then we force monochrome, otherwise, use
|
||||||
// the clients requested color state.
|
// the clients requested color state.
|
||||||
_currentPacketIsColor = (getWantLowResMoving() && _viewFrustumChanging) ? false : getWantColor();
|
_currentPacketIsColor = (getWantLowResMoving() && _viewFrustumChanging) ? false : getWantColor();
|
||||||
_voxelPacket[0] = _currentPacketIsColor ? PACKET_HEADER_VOXEL_DATA : PACKET_HEADER_VOXEL_DATA_MONOCHROME;
|
PACKET_TYPE voxelPacketType = _currentPacketIsColor ? PACKET_TYPE_VOXEL_DATA : PACKET_TYPE_VOXEL_DATA_MONOCHROME;
|
||||||
_voxelPacketAt = &_voxelPacket[1];
|
int numBytesPacketHeader = populateTypeAndVersion(_voxelPacket, voxelPacketType);
|
||||||
_voxelPacketAvailableBytes = MAX_VOXEL_PACKET_SIZE - 1;
|
_voxelPacketAt = _voxelPacket + numBytesPacketHeader;
|
||||||
|
_voxelPacketAvailableBytes = MAX_VOXEL_PACKET_SIZE - numBytesPacketHeader;
|
||||||
_voxelPacketWaiting = false;
|
_voxelPacketWaiting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// main.cpp
|
// main.cpp
|
||||||
// Voxel Server
|
// Voxel Server
|
||||||
//
|
//
|
||||||
// Created by Stephen Birara on 03/06/13.
|
// Created by Stephen Birarda on 03/06/13.
|
||||||
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
|
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
@ -300,11 +300,13 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
||||||
}
|
}
|
||||||
// send the environment packet
|
// send the environment packet
|
||||||
if (shouldSendEnvironments) {
|
if (shouldSendEnvironments) {
|
||||||
int envPacketLength = 1;
|
int numBytesPacketHeader = populateTypeAndVersion(tempOutputBuffer, PACKET_TYPE_ENVIRONMENT_DATA);
|
||||||
*tempOutputBuffer = PACKET_HEADER_ENVIRONMENT_DATA;
|
int envPacketLength = numBytesPacketHeader;
|
||||||
for (int i = 0; i < sizeof(environmentData) / sizeof(environmentData[0]); i++) {
|
|
||||||
|
for (int i = 0; i < sizeof(environmentData) / sizeof(EnvironmentData); i++) {
|
||||||
envPacketLength += environmentData[i].getBroadcastData(tempOutputBuffer + envPacketLength);
|
envPacketLength += environmentData[i].getBroadcastData(tempOutputBuffer + envPacketLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeList->getNodeSocket()->send(node->getActiveSocket(), tempOutputBuffer, envPacketLength);
|
nodeList->getNodeSocket()->send(node->getActiveSocket(), tempOutputBuffer, envPacketLength);
|
||||||
trueBytesSent += envPacketLength;
|
trueBytesSent += envPacketLength;
|
||||||
truePacketsSent++;
|
truePacketsSent++;
|
||||||
|
@ -548,19 +550,24 @@ int main(int argc, const char * argv[]) {
|
||||||
// check to see if we need to persist our voxel state
|
// check to see if we need to persist our voxel state
|
||||||
persistVoxelsWhenDirty();
|
persistVoxelsWhenDirty();
|
||||||
|
|
||||||
if (nodeList->getNodeSocket()->receive(&nodePublicAddress, packetData, &receivedBytes)) {
|
if (nodeList->getNodeSocket()->receive(&nodePublicAddress, packetData, &receivedBytes) &&
|
||||||
if (packetData[0] == PACKET_HEADER_SET_VOXEL || packetData[0] == PACKET_HEADER_SET_VOXEL_DESTRUCTIVE) {
|
packetVersionMatch(packetData)) {
|
||||||
bool destructive = (packetData[0] == PACKET_HEADER_SET_VOXEL_DESTRUCTIVE);
|
|
||||||
|
int numBytesPacketHeader = numBytesForPacketHeader(packetData);
|
||||||
|
|
||||||
|
if (packetData[0] == PACKET_TYPE_SET_VOXEL || packetData[0] == PACKET_TYPE_SET_VOXEL_DESTRUCTIVE) {
|
||||||
|
bool destructive = (packetData[0] == PACKET_TYPE_SET_VOXEL_DESTRUCTIVE);
|
||||||
PerformanceWarning warn(::shouldShowAnimationDebug,
|
PerformanceWarning warn(::shouldShowAnimationDebug,
|
||||||
destructive ? "PACKET_HEADER_SET_VOXEL_DESTRUCTIVE" : "PACKET_HEADER_SET_VOXEL",
|
destructive ? "PACKET_TYPE_SET_VOXEL_DESTRUCTIVE" : "PACKET_TYPE_SET_VOXEL",
|
||||||
::shouldShowAnimationDebug);
|
::shouldShowAnimationDebug);
|
||||||
unsigned short int itemNumber = (*((unsigned short int*)&packetData[1]));
|
|
||||||
|
unsigned short int itemNumber = (*((unsigned short int*)(packetData + numBytesPacketHeader)));
|
||||||
if (::shouldShowAnimationDebug) {
|
if (::shouldShowAnimationDebug) {
|
||||||
printf("got %s - command from client receivedBytes=%ld itemNumber=%d\n",
|
printf("got %s - command from client receivedBytes=%ld itemNumber=%d\n",
|
||||||
destructive ? "PACKET_HEADER_SET_VOXEL_DESTRUCTIVE" : "PACKET_HEADER_SET_VOXEL",
|
destructive ? "PACKET_TYPE_SET_VOXEL_DESTRUCTIVE" : "PACKET_TYPE_SET_VOXEL",
|
||||||
receivedBytes,itemNumber);
|
receivedBytes,itemNumber);
|
||||||
}
|
}
|
||||||
int atByte = sizeof(PACKET_HEADER) + sizeof(itemNumber);
|
int atByte = numBytesPacketHeader + sizeof(itemNumber);
|
||||||
unsigned char* voxelData = (unsigned char*)&packetData[atByte];
|
unsigned char* voxelData = (unsigned char*)&packetData[atByte];
|
||||||
while (atByte < receivedBytes) {
|
while (atByte < receivedBytes) {
|
||||||
unsigned char octets = (unsigned char)*voxelData;
|
unsigned char octets = (unsigned char)*voxelData;
|
||||||
|
@ -602,21 +609,20 @@ int main(int argc, const char * argv[]) {
|
||||||
voxelData += voxelDataSize;
|
voxelData += voxelDataSize;
|
||||||
atByte += voxelDataSize;
|
atByte += voxelDataSize;
|
||||||
}
|
}
|
||||||
}
|
} else if (packetData[0] == PACKET_TYPE_ERASE_VOXEL) {
|
||||||
if (packetData[0] == PACKET_HEADER_ERASE_VOXEL) {
|
|
||||||
|
|
||||||
// Send these bits off to the VoxelTree class to process them
|
// Send these bits off to the VoxelTree class to process them
|
||||||
pthread_mutex_lock(&::treeLock);
|
pthread_mutex_lock(&::treeLock);
|
||||||
serverTree.processRemoveVoxelBitstream((unsigned char*)packetData, receivedBytes);
|
serverTree.processRemoveVoxelBitstream((unsigned char*)packetData, receivedBytes);
|
||||||
pthread_mutex_unlock(&::treeLock);
|
pthread_mutex_unlock(&::treeLock);
|
||||||
}
|
} else if (packetData[0] == PACKET_TYPE_Z_COMMAND) {
|
||||||
if (packetData[0] == PACKET_HEADER_Z_COMMAND) {
|
|
||||||
|
|
||||||
// the Z command is a special command that allows the sender to send the voxel server high level semantic
|
// the Z command is a special command that allows the sender to send the voxel server high level semantic
|
||||||
// requests, like erase all, or add sphere scene
|
// requests, like erase all, or add sphere scene
|
||||||
char* command = (char*) &packetData[1]; // start of the command
|
|
||||||
|
char* command = (char*) &packetData[numBytesPacketHeader]; // start of the command
|
||||||
int commandLength = strlen(command); // commands are null terminated strings
|
int commandLength = strlen(command); // commands are null terminated strings
|
||||||
int totalLength = sizeof(PACKET_HEADER_Z_COMMAND) + commandLength + 1; // 1 for null termination
|
int totalLength = numBytesPacketHeader + commandLength + 1; // 1 for null termination
|
||||||
printf("got Z message len(%ld)= %s\n", receivedBytes, command);
|
printf("got Z message len(%ld)= %s\n", receivedBytes, command);
|
||||||
bool rebroadcast = true; // by default rebroadcast
|
bool rebroadcast = true; // by default rebroadcast
|
||||||
|
|
||||||
|
@ -642,21 +648,20 @@ int main(int argc, const char * argv[]) {
|
||||||
printf("rebroadcasting Z message to connected nodes... nodeList.broadcastToNodes()\n");
|
printf("rebroadcasting Z message to connected nodes... nodeList.broadcastToNodes()\n");
|
||||||
nodeList->broadcastToNodes(packetData, receivedBytes, &NODE_TYPE_AGENT, 1);
|
nodeList->broadcastToNodes(packetData, receivedBytes, &NODE_TYPE_AGENT, 1);
|
||||||
}
|
}
|
||||||
}
|
} else if (packetData[0] == PACKET_TYPE_HEAD_DATA) {
|
||||||
// If we got a PACKET_HEADER_HEAD_DATA, then we're talking to an NODE_TYPE_AVATAR, and we
|
// If we got a PACKET_TYPE_HEAD_DATA, then we're talking to an NODE_TYPE_AVATAR, and we
|
||||||
// need to make sure we have it in our nodeList.
|
// need to make sure we have it in our nodeList.
|
||||||
if (packetData[0] == PACKET_HEADER_HEAD_DATA) {
|
|
||||||
uint16_t nodeID = 0;
|
uint16_t nodeID = 0;
|
||||||
unpackNodeId(packetData + sizeof(PACKET_HEADER_HEAD_DATA), &nodeID);
|
unpackNodeId(packetData + numBytesPacketHeader, &nodeID);
|
||||||
Node* node = nodeList->addOrUpdateNode(&nodePublicAddress,
|
Node* node = nodeList->addOrUpdateNode(&nodePublicAddress,
|
||||||
&nodePublicAddress,
|
&nodePublicAddress,
|
||||||
NODE_TYPE_AGENT,
|
NODE_TYPE_AGENT,
|
||||||
nodeID);
|
nodeID);
|
||||||
|
|
||||||
nodeList->updateNodeWithData(node, packetData, receivedBytes);
|
nodeList->updateNodeWithData(node, packetData, receivedBytes);
|
||||||
}
|
} else if (packetData[0] == PACKET_TYPE_PING) {
|
||||||
// If the packet is a ping, let processNodeData handle it.
|
// If the packet is a ping, let processNodeData handle it.
|
||||||
if (packetData[0] == PACKET_HEADER_PING) {
|
|
||||||
nodeList->processNodeData(&nodePublicAddress, packetData, receivedBytes);
|
nodeList->processNodeData(&nodePublicAddress, packetData, receivedBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue