mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 18:25:52 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into metavoxels
This commit is contained in:
commit
ec1e168423
42 changed files with 756 additions and 227 deletions
12
BUILD.md
12
BUILD.md
|
@ -104,9 +104,7 @@ We don't currently have a Windows installer, so before running Interface, you wi
|
||||||
|
|
||||||
CMake will need to know where the headers and libraries for required external dependencies are. If you installed ZLIB using the installer, the FindZLIB cmake module will be able to find it. This isn't the case for the others.
|
CMake will need to know where the headers and libraries for required external dependencies are. If you installed ZLIB using the installer, the FindZLIB cmake module will be able to find it. This isn't the case for the others.
|
||||||
|
|
||||||
You have the choice of setting a variable specific to each library, or having a folder using a defined structure that contains all of the libs.
|
The recommended route for CMake to find external dependencies is to place all of the dependencies in one folder and set one ENV variable - HIFI_LIB_DIR. That ENV variable should point to a directory with the following structure:
|
||||||
|
|
||||||
The recommended route is to place all of the dependencies in one place and set one ENV variable - HIFI_LIB_DIR. That ENV variable should point to a directory with the following structure:
|
|
||||||
|
|
||||||
root_lib_dir
|
root_lib_dir
|
||||||
-> glm
|
-> glm
|
||||||
|
@ -128,14 +126,6 @@ The recommended route is to place all of the dependencies in one place and set o
|
||||||
|
|
||||||
For many of the external libraries where precompiled binaries are readily available you should be able to simply copy the extracted folder that you get from the download links provided at the top of the guide. Otherwise you may need to build from source and install the built product to this directory. The `root_lib_dir` in the above example can be wherever you choose on your system - as long as the environment variable HIFI_LIB_DIR is set to it.
|
For many of the external libraries where precompiled binaries are readily available you should be able to simply copy the extracted folder that you get from the download links provided at the top of the guide. Otherwise you may need to build from source and install the built product to this directory. The `root_lib_dir` in the above example can be wherever you choose on your system - as long as the environment variable HIFI_LIB_DIR is set to it.
|
||||||
|
|
||||||
Should you want to define a location for each library, these are the associated variables you will want to set:
|
|
||||||
|
|
||||||
`GLM_ROOT_DIR, GLUT_ROOT_DIR, GLEW_ROOT_DIR`
|
|
||||||
|
|
||||||
They can be set in your ENV or by passing them to the cmake command on the command line. (There is an example of this in the CMake section earlier in this guide.)
|
|
||||||
|
|
||||||
Each of those designates the root directory that contains the sub-folders for each library. For example, if the GLEW_ROOT_DIR is `C:\libs\glew`, then we would expect to find an `include` folder and a `lib` folder inside `C:\libs\glew`.
|
|
||||||
|
|
||||||
*NOTE: Qt does not support 64-bit builds on Windows 7, so you must use the 32-bit version of libraries for interface.exe to run. The 32-bit version of the static library is the one linked by our CMake find modules*
|
*NOTE: Qt does not support 64-bit builds on Windows 7, so you must use the 32-bit version of libraries for interface.exe to run. The 32-bit version of the static library is the one linked by our CMake find modules*
|
||||||
|
|
||||||
#### DLLs
|
#### DLLs
|
||||||
|
|
|
@ -40,13 +40,13 @@ bool waitForVoxelServer = true;
|
||||||
const int ANIMATION_LISTEN_PORT = 40107;
|
const int ANIMATION_LISTEN_PORT = 40107;
|
||||||
int ANIMATE_FPS = 60;
|
int ANIMATE_FPS = 60;
|
||||||
double ANIMATE_FPS_IN_MILLISECONDS = 1000.0/ANIMATE_FPS; // determines FPS from our desired FPS
|
double ANIMATE_FPS_IN_MILLISECONDS = 1000.0/ANIMATE_FPS; // determines FPS from our desired FPS
|
||||||
int ANIMATE_VOXELS_INTERVAL_USECS = (ANIMATE_FPS_IN_MILLISECONDS * 1000.0); // converts from milliseconds to usecs
|
quint64 ANIMATE_VOXELS_INTERVAL_USECS = (ANIMATE_FPS_IN_MILLISECONDS * 1000); // converts from milliseconds to usecs
|
||||||
|
|
||||||
|
|
||||||
int PROCESSING_FPS = 60;
|
int PROCESSING_FPS = 60;
|
||||||
double PROCESSING_FPS_IN_MILLISECONDS = 1000.0/PROCESSING_FPS; // determines FPS from our desired FPS
|
double PROCESSING_FPS_IN_MILLISECONDS = 1000.0/PROCESSING_FPS; // determines FPS from our desired FPS
|
||||||
int FUDGE_USECS = 650; // a little bit of fudge to actually do some processing
|
int FUDGE_USECS = 650; // a little bit of fudge to actually do some processing
|
||||||
int PROCESSING_INTERVAL_USECS = (PROCESSING_FPS_IN_MILLISECONDS * 1000.0) - FUDGE_USECS; // converts from milliseconds to usecs
|
quint64 PROCESSING_INTERVAL_USECS = (PROCESSING_FPS_IN_MILLISECONDS * 1000) - FUDGE_USECS; // converts from milliseconds to usecs
|
||||||
|
|
||||||
bool wantLocalDomain = false;
|
bool wantLocalDomain = false;
|
||||||
|
|
||||||
|
@ -611,9 +611,6 @@ void* animateVoxels(void* args) {
|
||||||
}
|
}
|
||||||
lastProcessTime = usecTimestampNow();
|
lastProcessTime = usecTimestampNow();
|
||||||
|
|
||||||
int packetsStarting = 0;
|
|
||||||
int packetsEnding = 0;
|
|
||||||
|
|
||||||
// The while loop will be running at PROCESSING_FPS, but we only want to call these animation functions at
|
// The while loop will be running at PROCESSING_FPS, but we only want to call these animation functions at
|
||||||
// ANIMATE_FPS. So we check out last animate time and only call these if we've elapsed that time.
|
// ANIMATE_FPS. So we check out last animate time and only call these if we've elapsed that time.
|
||||||
quint64 now = usecTimestampNow();
|
quint64 now = usecTimestampNow();
|
||||||
|
@ -627,8 +624,6 @@ void* animateVoxels(void* args) {
|
||||||
animateLoopsPerAnimate++;
|
animateLoopsPerAnimate++;
|
||||||
|
|
||||||
lastAnimateTime = now;
|
lastAnimateTime = now;
|
||||||
packetsStarting = ::voxelEditPacketSender->packetsToSendCount();
|
|
||||||
|
|
||||||
// some animations
|
// some animations
|
||||||
//sendVoxelBlinkMessage();
|
//sendVoxelBlinkMessage();
|
||||||
|
|
||||||
|
@ -652,8 +647,6 @@ void* animateVoxels(void* args) {
|
||||||
doBuildStreet();
|
doBuildStreet();
|
||||||
}
|
}
|
||||||
|
|
||||||
packetsEnding = ::voxelEditPacketSender->packetsToSendCount();
|
|
||||||
|
|
||||||
if (animationElapsed > ANIMATE_VOXELS_INTERVAL_USECS) {
|
if (animationElapsed > ANIMATE_VOXELS_INTERVAL_USECS) {
|
||||||
animationElapsed -= ANIMATE_VOXELS_INTERVAL_USECS; // credit ourselves one animation frame
|
animationElapsed -= ANIMATE_VOXELS_INTERVAL_USECS; // credit ourselves one animation frame
|
||||||
} else {
|
} else {
|
||||||
|
@ -670,9 +663,9 @@ void* animateVoxels(void* args) {
|
||||||
processesPerAnimate++;
|
processesPerAnimate++;
|
||||||
}
|
}
|
||||||
// dynamically sleep until we need to fire off the next set of voxels
|
// dynamically sleep until we need to fire off the next set of voxels
|
||||||
quint64 usecToSleep = PROCESSING_INTERVAL_USECS - (usecTimestampNow() - lastProcessTime);
|
quint64 usecToSleep = ::PROCESSING_INTERVAL_USECS - (usecTimestampNow() - lastProcessTime);
|
||||||
if (usecToSleep > PROCESSING_INTERVAL_USECS) {
|
if (usecToSleep > ::PROCESSING_INTERVAL_USECS) {
|
||||||
usecToSleep = PROCESSING_INTERVAL_USECS;
|
usecToSleep = ::PROCESSING_INTERVAL_USECS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usecToSleep > 0) {
|
if (usecToSleep > 0) {
|
||||||
|
@ -758,7 +751,7 @@ AnimationServer::AnimationServer(int &argc, char **argv) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("ANIMATE_FPS=%d\n",ANIMATE_FPS);
|
printf("ANIMATE_FPS=%d\n",ANIMATE_FPS);
|
||||||
printf("ANIMATE_VOXELS_INTERVAL_USECS=%d\n",ANIMATE_VOXELS_INTERVAL_USECS);
|
printf("ANIMATE_VOXELS_INTERVAL_USECS=%llu\n",ANIMATE_VOXELS_INTERVAL_USECS);
|
||||||
|
|
||||||
const char* processingFPSCommand = getCmdOption(argc, (const char**) argv, "--ProcessingFPS");
|
const char* processingFPSCommand = getCmdOption(argc, (const char**) argv, "--ProcessingFPS");
|
||||||
const char* processingIntervalCommand = getCmdOption(argc, (const char**) argv, "--ProcessingInterval");
|
const char* processingIntervalCommand = getCmdOption(argc, (const char**) argv, "--ProcessingInterval");
|
||||||
|
@ -774,7 +767,7 @@ AnimationServer::AnimationServer(int &argc, char **argv) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("PROCESSING_FPS=%d\n",PROCESSING_FPS);
|
printf("PROCESSING_FPS=%d\n",PROCESSING_FPS);
|
||||||
printf("PROCESSING_INTERVAL_USECS=%d\n",PROCESSING_INTERVAL_USECS);
|
printf("PROCESSING_INTERVAL_USECS=%llu\n",PROCESSING_INTERVAL_USECS);
|
||||||
|
|
||||||
nodeList->linkedDataCreateCallback = NULL; // do we need a callback?
|
nodeList->linkedDataCreateCallback = NULL; // do we need a callback?
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <mmintrin.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
@ -73,13 +74,10 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
|
||||||
float attenuationCoefficient = 1.0f;
|
float attenuationCoefficient = 1.0f;
|
||||||
int numSamplesDelay = 0;
|
int numSamplesDelay = 0;
|
||||||
float weakChannelAmplitudeRatio = 1.0f;
|
float weakChannelAmplitudeRatio = 1.0f;
|
||||||
|
|
||||||
const int PHASE_DELAY_AT_90 = 20;
|
|
||||||
|
|
||||||
if (bufferToAdd != listeningNodeBuffer) {
|
if (bufferToAdd != listeningNodeBuffer) {
|
||||||
// if the two buffer pointers do not match then these are different buffers
|
// if the two buffer pointers do not match then these are different buffers
|
||||||
|
|
||||||
glm::vec3 listenerPosition = listeningNodeBuffer->getPosition();
|
|
||||||
glm::vec3 relativePosition = bufferToAdd->getPosition() - listeningNodeBuffer->getPosition();
|
glm::vec3 relativePosition = bufferToAdd->getPosition() - listeningNodeBuffer->getPosition();
|
||||||
glm::quat inverseOrientation = glm::inverse(listeningNodeBuffer->getOrientation());
|
glm::quat inverseOrientation = glm::inverse(listeningNodeBuffer->getOrientation());
|
||||||
|
|
||||||
|
@ -149,7 +147,7 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
|
||||||
// figure out the number of samples of delay and the ratio of the amplitude
|
// figure out the number of samples of delay and the ratio of the amplitude
|
||||||
// in the weak channel for audio spatialization
|
// in the weak channel for audio spatialization
|
||||||
float sinRatio = fabsf(sinf(bearingRelativeAngleToSource));
|
float sinRatio = fabsf(sinf(bearingRelativeAngleToSource));
|
||||||
numSamplesDelay = PHASE_DELAY_AT_90 * sinRatio;
|
numSamplesDelay = SAMPLE_PHASE_DELAY_AT_90 * sinRatio;
|
||||||
weakChannelAmplitudeRatio = 1 - (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio);
|
weakChannelAmplitudeRatio = 1 - (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,26 +155,130 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
|
||||||
// if the bearing relative angle to source is > 0 then the delayed channel is the right one
|
// if the bearing relative angle to source is > 0 then the delayed channel is the right one
|
||||||
int delayedChannelOffset = (bearingRelativeAngleToSource > 0.0f) ? 1 : 0;
|
int delayedChannelOffset = (bearingRelativeAngleToSource > 0.0f) ? 1 : 0;
|
||||||
int goodChannelOffset = delayedChannelOffset == 0 ? 1 : 0;
|
int goodChannelOffset = delayedChannelOffset == 0 ? 1 : 0;
|
||||||
|
|
||||||
|
const int16_t* nextOutputStart = bufferToAdd->getNextOutput();
|
||||||
|
|
||||||
|
const int16_t* bufferStart = bufferToAdd->getBuffer();
|
||||||
|
int ringBufferSampleCapacity = bufferToAdd->getSampleCapacity();
|
||||||
|
|
||||||
for (int s = 0; s < NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; s += 2) {
|
int16_t correctBufferSample[2], delayBufferSample[2];
|
||||||
if ((s / 2) < numSamplesDelay) {
|
int delayedChannelIndex = 0;
|
||||||
// pull the earlier sample for the delayed channel
|
|
||||||
int earlierSample = (*bufferToAdd)[(s / 2) - numSamplesDelay] * attenuationCoefficient * weakChannelAmplitudeRatio;
|
const int SINGLE_STEREO_OFFSET = 2;
|
||||||
_clientSamples[s + delayedChannelOffset] = glm::clamp(_clientSamples[s + delayedChannelOffset] + earlierSample,
|
|
||||||
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
for (int s = 0; s < NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; s += 4) {
|
||||||
|
|
||||||
|
// setup the int16_t variables for the two sample sets
|
||||||
|
correctBufferSample[0] = nextOutputStart[s / 2] * attenuationCoefficient;
|
||||||
|
correctBufferSample[1] = nextOutputStart[(s / 2) + 1] * attenuationCoefficient;
|
||||||
|
|
||||||
|
delayedChannelIndex = s + (numSamplesDelay * 2) + delayedChannelOffset;
|
||||||
|
|
||||||
|
delayBufferSample[0] = correctBufferSample[0] * weakChannelAmplitudeRatio;
|
||||||
|
delayBufferSample[1] = correctBufferSample[1] * weakChannelAmplitudeRatio;
|
||||||
|
|
||||||
|
__m64 bufferSamples = _mm_set_pi16(_clientSamples[s + goodChannelOffset],
|
||||||
|
_clientSamples[s + goodChannelOffset + SINGLE_STEREO_OFFSET],
|
||||||
|
_clientSamples[delayedChannelIndex],
|
||||||
|
_clientSamples[delayedChannelIndex + SINGLE_STEREO_OFFSET]);
|
||||||
|
__m64 addedSamples = _mm_set_pi16(correctBufferSample[0], correctBufferSample[1],
|
||||||
|
delayBufferSample[0], delayBufferSample[1]);
|
||||||
|
|
||||||
|
// perform the MMX add (with saturation) of two correct and delayed samples
|
||||||
|
__m64 mmxResult = _mm_adds_pi16(bufferSamples, addedSamples);
|
||||||
|
int16_t* shortResults = reinterpret_cast<int16_t*>(&mmxResult);
|
||||||
|
|
||||||
|
// assign the results from the result of the mmx arithmetic
|
||||||
|
_clientSamples[s + goodChannelOffset] = shortResults[3];
|
||||||
|
_clientSamples[s + goodChannelOffset + SINGLE_STEREO_OFFSET] = shortResults[2];
|
||||||
|
_clientSamples[delayedChannelIndex] = shortResults[1];
|
||||||
|
_clientSamples[delayedChannelIndex + SINGLE_STEREO_OFFSET] = shortResults[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// The following code is pretty gross and redundant, but AFAIK it's the best way to avoid
|
||||||
|
// too many conditionals in handling the delay samples at the beginning of _clientSamples.
|
||||||
|
// Basically we try to take the samples in batches of four, and then handle the remainder
|
||||||
|
// conditionally to get rid of the rest.
|
||||||
|
|
||||||
|
const int DOUBLE_STEREO_OFFSET = 4;
|
||||||
|
const int TRIPLE_STEREO_OFFSET = 6;
|
||||||
|
|
||||||
|
if (numSamplesDelay > 0) {
|
||||||
|
// if there was a sample delay for this buffer, we need to pull samples prior to the nextOutput
|
||||||
|
// to stick at the beginning
|
||||||
|
float attenuationAndWeakChannelRatio = attenuationCoefficient * weakChannelAmplitudeRatio;
|
||||||
|
const int16_t* delayNextOutputStart = nextOutputStart - numSamplesDelay;
|
||||||
|
if (delayNextOutputStart < bufferStart) {
|
||||||
|
delayNextOutputStart = bufferStart + ringBufferSampleCapacity - numSamplesDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
// pull the current sample for the good channel
|
int i = 0;
|
||||||
int16_t currentSample = (*bufferToAdd)[s / 2] * attenuationCoefficient;
|
|
||||||
_clientSamples[s + goodChannelOffset] = glm::clamp(_clientSamples[s + goodChannelOffset] + currentSample,
|
while (i + 3 < numSamplesDelay) {
|
||||||
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
// handle the first cases where we can MMX add four samples at once
|
||||||
|
int parentIndex = i * 2;
|
||||||
if ((s / 2) + numSamplesDelay < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL) {
|
__m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset],
|
||||||
// place the current sample at the right spot in the delayed channel
|
_clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset],
|
||||||
int16_t clampedSample = glm::clamp((int) (_clientSamples[s + (numSamplesDelay * 2) + delayedChannelOffset]
|
_clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset],
|
||||||
+ (currentSample * weakChannelAmplitudeRatio)),
|
_clientSamples[parentIndex + TRIPLE_STEREO_OFFSET + delayedChannelOffset]);
|
||||||
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
__m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio,
|
||||||
_clientSamples[s + (numSamplesDelay * 2) + delayedChannelOffset] = clampedSample;
|
delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio,
|
||||||
|
delayNextOutputStart[i + 2] * attenuationAndWeakChannelRatio,
|
||||||
|
delayNextOutputStart[i + 3] * attenuationAndWeakChannelRatio);
|
||||||
|
__m64 mmxResult = _mm_adds_pi16(bufferSamples, addSamples);
|
||||||
|
int16_t* shortResults = reinterpret_cast<int16_t*>(&mmxResult);
|
||||||
|
|
||||||
|
_clientSamples[parentIndex + delayedChannelOffset] = shortResults[3];
|
||||||
|
_clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[2];
|
||||||
|
_clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[1];
|
||||||
|
_clientSamples[parentIndex + TRIPLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[0];
|
||||||
|
|
||||||
|
// push the index
|
||||||
|
i += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
int parentIndex = i * 2;
|
||||||
|
|
||||||
|
if (i + 2 < numSamplesDelay) {
|
||||||
|
// MMX add only three delayed samples
|
||||||
|
|
||||||
|
__m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset],
|
||||||
|
_clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset],
|
||||||
|
_clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset],
|
||||||
|
0);
|
||||||
|
__m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio,
|
||||||
|
delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio,
|
||||||
|
delayNextOutputStart[i + 2] * attenuationAndWeakChannelRatio,
|
||||||
|
0);
|
||||||
|
__m64 mmxResult = _mm_adds_pi16(bufferSamples, addSamples);
|
||||||
|
int16_t* shortResults = reinterpret_cast<int16_t*>(&mmxResult);
|
||||||
|
|
||||||
|
_clientSamples[parentIndex + delayedChannelOffset] = shortResults[3];
|
||||||
|
_clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[2];
|
||||||
|
_clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[1];
|
||||||
|
|
||||||
|
} else if (i + 1 < numSamplesDelay) {
|
||||||
|
// MMX add two delayed samples
|
||||||
|
__m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset],
|
||||||
|
_clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset], 0, 0);
|
||||||
|
__m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio,
|
||||||
|
delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio, 0, 0);
|
||||||
|
|
||||||
|
__m64 mmxResult = _mm_adds_pi16(bufferSamples, addSamples);
|
||||||
|
int16_t* shortResults = reinterpret_cast<int16_t*>(&mmxResult);
|
||||||
|
|
||||||
|
_clientSamples[parentIndex + delayedChannelOffset] = shortResults[3];
|
||||||
|
_clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[2];
|
||||||
|
|
||||||
|
} else if (i < numSamplesDelay) {
|
||||||
|
// MMX add a single delayed sample
|
||||||
|
__m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], 0, 0, 0);
|
||||||
|
__m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, 0, 0, 0);
|
||||||
|
|
||||||
|
__m64 mmxResult = _mm_adds_pi16(bufferSamples, addSamples);
|
||||||
|
int16_t* shortResults = reinterpret_cast<int16_t*>(&mmxResult);
|
||||||
|
|
||||||
|
_clientSamples[parentIndex + delayedChannelOffset] = shortResults[3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -199,7 +301,8 @@ void AudioMixer::prepareMixForListeningNode(Node* node) {
|
||||||
|
|
||||||
if ((*otherNode != *node
|
if ((*otherNode != *node
|
||||||
|| otherNodeBuffer->shouldLoopbackForNode())
|
|| otherNodeBuffer->shouldLoopbackForNode())
|
||||||
&& otherNodeBuffer->willBeAddedToMix()) {
|
&& otherNodeBuffer->willBeAddedToMix()
|
||||||
|
&& otherNodeClientData->getNextOutputLoudness() > 0) {
|
||||||
addBufferToMixForListeningNodeWithBuffer(otherNodeBuffer, nodeRingBuffer);
|
addBufferToMixForListeningNodeWithBuffer(otherNodeBuffer, nodeRingBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -253,12 +356,6 @@ void AudioMixer::run() {
|
||||||
|
|
||||||
while (!_isFinished) {
|
while (!_isFinished) {
|
||||||
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
|
|
||||||
if (_isFinished) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
|
foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
|
||||||
if (node->getLinkedData()) {
|
if (node->getLinkedData()) {
|
||||||
((AudioMixerClientData*) node->getLinkedData())->checkBuffersBeforeFrameSend(JITTER_BUFFER_SAMPLES);
|
((AudioMixerClientData*) node->getLinkedData())->checkBuffersBeforeFrameSend(JITTER_BUFFER_SAMPLES);
|
||||||
|
@ -270,7 +367,7 @@ void AudioMixer::run() {
|
||||||
&& ((AudioMixerClientData*) node->getLinkedData())->getAvatarAudioRingBuffer()) {
|
&& ((AudioMixerClientData*) node->getLinkedData())->getAvatarAudioRingBuffer()) {
|
||||||
prepareMixForListeningNode(node.data());
|
prepareMixForListeningNode(node.data());
|
||||||
|
|
||||||
memcpy(_clientMixBuffer.data() + numBytesPacketHeader, _clientSamples, sizeof(_clientSamples));
|
memcpy(_clientMixBuffer.data() + numBytesPacketHeader, _clientSamples, NETWORK_BUFFER_LENGTH_BYTES_STEREO);
|
||||||
nodeList->writeDatagram(_clientMixBuffer, node);
|
nodeList->writeDatagram(_clientMixBuffer, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -281,6 +378,12 @@ void AudioMixer::run() {
|
||||||
((AudioMixerClientData*) node->getLinkedData())->pushBuffersAfterFrameSend();
|
((AudioMixerClientData*) node->getLinkedData())->pushBuffersAfterFrameSend();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
|
if (_isFinished) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
int usecToSleep = usecTimestamp(&startTime) + (++nextFrame * BUFFER_SEND_INTERVAL_USECS) - usecTimestampNow();
|
int usecToSleep = usecTimestamp(&startTime) + (++nextFrame * BUFFER_SEND_INTERVAL_USECS) - usecTimestampNow();
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
class PositionalAudioRingBuffer;
|
class PositionalAudioRingBuffer;
|
||||||
class AvatarAudioRingBuffer;
|
class AvatarAudioRingBuffer;
|
||||||
|
|
||||||
|
const int SAMPLE_PHASE_DELAY_AT_90 = 20;
|
||||||
|
|
||||||
/// Handles assignments of type AudioMixer - mixing streams of audio and re-distributing to various clients.
|
/// Handles assignments of type AudioMixer - mixing streams of audio and re-distributing to various clients.
|
||||||
class AudioMixer : public ThreadedAssignment {
|
class AudioMixer : public ThreadedAssignment {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -38,7 +40,8 @@ private:
|
||||||
|
|
||||||
QByteArray _clientMixBuffer;
|
QByteArray _clientMixBuffer;
|
||||||
|
|
||||||
int16_t _clientSamples[NETWORK_BUFFER_LENGTH_SAMPLES_STEREO];
|
// client samples capacity is larger than what will be sent to optimize mixing
|
||||||
|
int16_t _clientSamples[NETWORK_BUFFER_LENGTH_SAMPLES_STEREO + SAMPLE_PHASE_DELAY_AT_90];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* defined(__hifi__AudioMixer__) */
|
#endif /* defined(__hifi__AudioMixer__) */
|
||||||
|
|
|
@ -13,6 +13,13 @@
|
||||||
|
|
||||||
#include "AudioMixerClientData.h"
|
#include "AudioMixerClientData.h"
|
||||||
|
|
||||||
|
AudioMixerClientData::AudioMixerClientData() :
|
||||||
|
_ringBuffers(),
|
||||||
|
_nextOutputLoudness(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
AudioMixerClientData::~AudioMixerClientData() {
|
AudioMixerClientData::~AudioMixerClientData() {
|
||||||
for (unsigned int i = 0; i < _ringBuffers.size(); i++) {
|
for (unsigned int i = 0; i < _ringBuffers.size(); i++) {
|
||||||
// delete this attached PositionalAudioRingBuffer
|
// delete this attached PositionalAudioRingBuffer
|
||||||
|
@ -80,6 +87,10 @@ void AudioMixerClientData::checkBuffersBeforeFrameSend(int jitterBufferLengthSam
|
||||||
// this is a ring buffer that is ready to go
|
// this is a ring buffer that is ready to go
|
||||||
// set its flag so we know to push its buffer when all is said and done
|
// set its flag so we know to push its buffer when all is said and done
|
||||||
_ringBuffers[i]->setWillBeAddedToMix(true);
|
_ringBuffers[i]->setWillBeAddedToMix(true);
|
||||||
|
|
||||||
|
// calculate the average loudness for the next NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL
|
||||||
|
// that would be mixed in
|
||||||
|
_nextOutputLoudness = _ringBuffers[i]->averageLoudnessForBoundarySamples(NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,16 +18,20 @@
|
||||||
|
|
||||||
class AudioMixerClientData : public NodeData {
|
class AudioMixerClientData : public NodeData {
|
||||||
public:
|
public:
|
||||||
|
AudioMixerClientData();
|
||||||
~AudioMixerClientData();
|
~AudioMixerClientData();
|
||||||
|
|
||||||
const std::vector<PositionalAudioRingBuffer*> getRingBuffers() const { return _ringBuffers; }
|
const std::vector<PositionalAudioRingBuffer*> getRingBuffers() const { return _ringBuffers; }
|
||||||
AvatarAudioRingBuffer* getAvatarAudioRingBuffer() const;
|
AvatarAudioRingBuffer* getAvatarAudioRingBuffer() const;
|
||||||
|
|
||||||
|
float getNextOutputLoudness() const { return _nextOutputLoudness; }
|
||||||
|
|
||||||
int parseData(const QByteArray& packet);
|
int parseData(const QByteArray& packet);
|
||||||
void checkBuffersBeforeFrameSend(int jitterBufferLengthSamples);
|
void checkBuffersBeforeFrameSend(int jitterBufferLengthSamples);
|
||||||
void pushBuffersAfterFrameSend();
|
void pushBuffersAfterFrameSend();
|
||||||
private:
|
private:
|
||||||
std::vector<PositionalAudioRingBuffer*> _ringBuffers;
|
std::vector<PositionalAudioRingBuffer*> _ringBuffers;
|
||||||
|
float _nextOutputLoudness;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* defined(__hifi__AudioMixerClientData__) */
|
#endif /* defined(__hifi__AudioMixerClientData__) */
|
||||||
|
|
|
@ -156,7 +156,7 @@ void OctreeQueryNode::resetOctreePacket(bool lastWasSurpressed) {
|
||||||
_octreePacketWaiting = false;
|
_octreePacketWaiting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OctreeQueryNode::writeToPacket(const unsigned char* buffer, int bytes) {
|
void OctreeQueryNode::writeToPacket(const unsigned char* buffer, unsigned int bytes) {
|
||||||
// compressed packets include lead bytes which contain compressed size, this allows packing of
|
// compressed packets include lead bytes which contain compressed size, this allows packing of
|
||||||
// multiple compressed portions together
|
// multiple compressed portions together
|
||||||
if (_currentPacketIsCompressed) {
|
if (_currentPacketIsCompressed) {
|
||||||
|
|
|
@ -31,16 +31,16 @@ public:
|
||||||
|
|
||||||
void resetOctreePacket(bool lastWasSurpressed = false); // resets octree packet to after "V" header
|
void resetOctreePacket(bool lastWasSurpressed = false); // resets octree packet to after "V" header
|
||||||
|
|
||||||
void writeToPacket(const unsigned char* buffer, int bytes); // writes to end of packet
|
void writeToPacket(const unsigned char* buffer, unsigned int bytes); // writes to end of packet
|
||||||
|
|
||||||
const unsigned char* getPacket() const { return _octreePacket; }
|
const unsigned char* getPacket() const { return _octreePacket; }
|
||||||
int getPacketLength() const { return (MAX_PACKET_SIZE - _octreePacketAvailableBytes); }
|
unsigned int getPacketLength() const { return (MAX_PACKET_SIZE - _octreePacketAvailableBytes); }
|
||||||
bool isPacketWaiting() const { return _octreePacketWaiting; }
|
bool isPacketWaiting() const { return _octreePacketWaiting; }
|
||||||
|
|
||||||
bool packetIsDuplicate() const;
|
bool packetIsDuplicate() const;
|
||||||
bool shouldSuppressDuplicatePacket();
|
bool shouldSuppressDuplicatePacket();
|
||||||
|
|
||||||
int getAvailable() const { return _octreePacketAvailableBytes; }
|
unsigned int getAvailable() const { return _octreePacketAvailableBytes; }
|
||||||
int getMaxSearchLevel() const { return _maxSearchLevel; }
|
int getMaxSearchLevel() const { return _maxSearchLevel; }
|
||||||
void resetMaxSearchLevel() { _maxSearchLevel = 1; }
|
void resetMaxSearchLevel() { _maxSearchLevel = 1; }
|
||||||
void incrementMaxSearchLevel() { _maxSearchLevel++; }
|
void incrementMaxSearchLevel() { _maxSearchLevel++; }
|
||||||
|
@ -92,11 +92,11 @@ private:
|
||||||
bool _viewSent;
|
bool _viewSent;
|
||||||
unsigned char* _octreePacket;
|
unsigned char* _octreePacket;
|
||||||
unsigned char* _octreePacketAt;
|
unsigned char* _octreePacketAt;
|
||||||
int _octreePacketAvailableBytes;
|
unsigned int _octreePacketAvailableBytes;
|
||||||
bool _octreePacketWaiting;
|
bool _octreePacketWaiting;
|
||||||
|
|
||||||
unsigned char* _lastOctreePacket;
|
unsigned char* _lastOctreePacket;
|
||||||
int _lastOctreePacketLength;
|
unsigned int _lastOctreePacketLength;
|
||||||
int _duplicatePacketCount;
|
int _duplicatePacketCount;
|
||||||
quint64 _firstSuppressedPacket;
|
quint64 _firstSuppressedPacket;
|
||||||
|
|
||||||
|
|
|
@ -54,15 +54,13 @@ bool OctreeSendThread::process() {
|
||||||
|
|
||||||
nodeData = (OctreeQueryNode*) node->getLinkedData();
|
nodeData = (OctreeQueryNode*) node->getLinkedData();
|
||||||
|
|
||||||
int packetsSent = 0;
|
|
||||||
|
|
||||||
// Sometimes the node data has not yet been linked, in which case we can't really do anything
|
// Sometimes the node data has not yet been linked, in which case we can't really do anything
|
||||||
if (nodeData) {
|
if (nodeData) {
|
||||||
bool viewFrustumChanged = nodeData->updateCurrentViewFrustum();
|
bool viewFrustumChanged = nodeData->updateCurrentViewFrustum();
|
||||||
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
|
if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
|
||||||
printf("nodeData->updateCurrentViewFrustum() changed=%s\n", debug::valueOf(viewFrustumChanged));
|
printf("nodeData->updateCurrentViewFrustum() changed=%s\n", debug::valueOf(viewFrustumChanged));
|
||||||
}
|
}
|
||||||
packetsSent = packetDistributor(node, nodeData, viewFrustumChanged);
|
packetDistributor(node, nodeData, viewFrustumChanged);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_nodeMissingCount++;
|
_nodeMissingCount++;
|
||||||
|
@ -143,9 +141,10 @@ int OctreeSendThread::handlePacketSend(const SharedNodePointer& node, OctreeQuer
|
||||||
// Send the stats message to the client
|
// Send the stats message to the client
|
||||||
unsigned char* statsMessage = nodeData->stats.getStatsMessage();
|
unsigned char* statsMessage = nodeData->stats.getStatsMessage();
|
||||||
int statsMessageLength = nodeData->stats.getStatsMessageLength();
|
int statsMessageLength = nodeData->stats.getStatsMessageLength();
|
||||||
|
int piggyBackSize = nodeData->getPacketLength() + statsMessageLength;
|
||||||
|
|
||||||
// If the size of the stats message and the voxel message will fit in a packet, then piggyback them
|
// If the size of the stats message and the voxel message will fit in a packet, then piggyback them
|
||||||
if (nodeData->getPacketLength() + statsMessageLength < MAX_PACKET_SIZE) {
|
if (piggyBackSize < MAX_PACKET_SIZE) {
|
||||||
|
|
||||||
// copy voxel message to back of stats message
|
// copy voxel message to back of stats message
|
||||||
memcpy(statsMessage + statsMessageLength, nodeData->getPacket(), nodeData->getPacketLength());
|
memcpy(statsMessage + statsMessageLength, nodeData->getPacket(), nodeData->getPacketLength());
|
||||||
|
@ -494,7 +493,7 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue
|
||||||
// if for some reason the finalized size is greater than our available size, then probably the "compressed"
|
// if for some reason the finalized size is greater than our available size, then probably the "compressed"
|
||||||
// form actually inflated beyond our padding, and in this case we will send the current packet, then
|
// form actually inflated beyond our padding, and in this case we will send the current packet, then
|
||||||
// write to out new packet...
|
// write to out new packet...
|
||||||
int writtenSize = _packetData.getFinalizedSize()
|
unsigned int writtenSize = _packetData.getFinalizedSize()
|
||||||
+ (nodeData->getCurrentPacketIsCompressed() ? sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE) : 0);
|
+ (nodeData->getCurrentPacketIsCompressed() ? sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE) : 0);
|
||||||
|
|
||||||
|
|
||||||
|
@ -508,7 +507,7 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue
|
||||||
}
|
}
|
||||||
|
|
||||||
if (forceDebugging || (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug())) {
|
if (forceDebugging || (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug())) {
|
||||||
qDebug(">>>>>> calling writeToPacket() available=%d compressedSize=%d uncompressedSize=%d target=%d",
|
qDebug(">>>>>> calling writeToPacket() available=%d compressedSize=%d uncompressedSize=%d target=%u",
|
||||||
nodeData->getAvailable(), _packetData.getFinalizedSize(),
|
nodeData->getAvailable(), _packetData.getFinalizedSize(),
|
||||||
_packetData.getUncompressedSize(), _packetData.getTargetSize());
|
_packetData.getUncompressedSize(), _packetData.getTargetSize());
|
||||||
}
|
}
|
||||||
|
|
|
@ -423,17 +423,25 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
|
||||||
QDataStream broadcastDataStream(&broadcastPacket, QIODevice::Append);
|
QDataStream broadcastDataStream(&broadcastPacket, QIODevice::Append);
|
||||||
broadcastDataStream << node->getUUID();
|
broadcastDataStream << node->getUUID();
|
||||||
|
|
||||||
|
int numBroadcastPacketLeadBytes = broadcastDataStream.device()->pos();
|
||||||
|
|
||||||
DomainServerNodeData* nodeData = reinterpret_cast<DomainServerNodeData*>(node->getLinkedData());
|
DomainServerNodeData* nodeData = reinterpret_cast<DomainServerNodeData*>(node->getLinkedData());
|
||||||
|
|
||||||
NodeList* nodeList = NodeList::getInstance();
|
NodeList* nodeList = NodeList::getInstance();
|
||||||
|
|
||||||
|
|
||||||
if (nodeInterestList.size() > 0) {
|
if (nodeInterestList.size() > 0) {
|
||||||
// if the node has any interest types, send back those nodes as well
|
// if the node has any interest types, send back those nodes as well
|
||||||
foreach (const SharedNodePointer& otherNode, nodeList->getNodeHash()) {
|
foreach (const SharedNodePointer& otherNode, nodeList->getNodeHash()) {
|
||||||
|
|
||||||
|
// reset our nodeByteArray and nodeDataStream
|
||||||
|
QByteArray nodeByteArray;
|
||||||
|
QDataStream nodeDataStream(&nodeByteArray, QIODevice::Append);
|
||||||
|
|
||||||
if (otherNode->getUUID() != node->getUUID() && nodeInterestList.contains(otherNode->getType())) {
|
if (otherNode->getUUID() != node->getUUID() && nodeInterestList.contains(otherNode->getType())) {
|
||||||
|
|
||||||
// don't send avatar nodes to other avatars, that will come from avatar mixer
|
// don't send avatar nodes to other avatars, that will come from avatar mixer
|
||||||
broadcastDataStream << *otherNode.data();
|
nodeDataStream << *otherNode.data();
|
||||||
|
|
||||||
// pack the secret that these two nodes will use to communicate with each other
|
// pack the secret that these two nodes will use to communicate with each other
|
||||||
QUuid secretUUID = nodeData->getSessionSecretHash().value(otherNode->getUUID());
|
QUuid secretUUID = nodeData->getSessionSecretHash().value(otherNode->getUUID());
|
||||||
|
@ -450,11 +458,26 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
broadcastDataStream << secretUUID;
|
nodeDataStream << secretUUID;
|
||||||
|
|
||||||
|
if (broadcastPacket.size() + nodeByteArray.size() > MAX_PACKET_SIZE) {
|
||||||
|
// we need to break here and start a new packet
|
||||||
|
// so send the current one
|
||||||
|
|
||||||
|
nodeList->writeDatagram(broadcastPacket, node, senderSockAddr);
|
||||||
|
|
||||||
|
// reset the broadcastPacket structure
|
||||||
|
broadcastPacket.resize(numBroadcastPacketLeadBytes);
|
||||||
|
broadcastDataStream.device()->seek(numBroadcastPacketLeadBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// append the nodeByteArray to the current state of broadcastDataStream
|
||||||
|
broadcastPacket.append(nodeByteArray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// always write the last broadcastPacket
|
||||||
nodeList->writeDatagram(broadcastPacket, node, senderSockAddr);
|
nodeList->writeDatagram(broadcastPacket, node, senderSockAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ configure_file(InterfaceVersion.h.in "${PROJECT_BINARY_DIR}/includes/InterfaceVe
|
||||||
|
|
||||||
# grab the implementation and header files from src dirs
|
# grab the implementation and header files from src dirs
|
||||||
file(GLOB INTERFACE_SRCS src/*.cpp src/*.h)
|
file(GLOB INTERFACE_SRCS src/*.cpp src/*.h)
|
||||||
foreach(SUBDIR avatar devices renderer ui starfield)
|
foreach(SUBDIR avatar devices renderer ui starfield location)
|
||||||
file(GLOB_RECURSE SUBDIR_SRCS src/${SUBDIR}/*.cpp src/${SUBDIR}/*.h)
|
file(GLOB_RECURSE SUBDIR_SRCS src/${SUBDIR}/*.cpp src/${SUBDIR}/*.h)
|
||||||
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${SUBDIR_SRCS}")
|
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${SUBDIR_SRCS}")
|
||||||
endforeach(SUBDIR)
|
endforeach(SUBDIR)
|
||||||
|
|
|
@ -160,7 +160,7 @@ void fsBinaryStream::received(long int sz, const char *data) {
|
||||||
new_end = m_end + sz;
|
new_end = m_end + sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_end > Size(m_buffer.size())) m_buffer.resize(1.5*new_end);
|
if (new_end > Size(m_buffer.size())) m_buffer.resize((int)(1.5f * (float)new_end)); // HIFI: to get 1.5 without warnings
|
||||||
|
|
||||||
memcpy(&m_buffer[0] + m_end, data, sz);
|
memcpy(&m_buffer[0] + m_end, data, sz);
|
||||||
m_end += sz;
|
m_end += sz;
|
||||||
|
@ -172,7 +172,7 @@ static bool decodeInfo(fsTrackingData & _trackingData, const std::string &buffer
|
||||||
success &= read_pod<double>(_trackingData.m_timestamp, buffer, start);
|
success &= read_pod<double>(_trackingData.m_timestamp, buffer, start);
|
||||||
unsigned char tracking_successfull = 0;
|
unsigned char tracking_successfull = 0;
|
||||||
success &= read_pod<unsigned char>( tracking_successfull, buffer, start );
|
success &= read_pod<unsigned char>( tracking_successfull, buffer, start );
|
||||||
_trackingData.m_trackingSuccessful = bool(tracking_successfull);
|
_trackingData.m_trackingSuccessful = bool(tracking_successfull != 0); // HIFI: get rid of windows warning
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,18 +113,18 @@
|
||||||
<context>
|
<context>
|
||||||
<name>Menu</name>
|
<name>Menu</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="src/Menu.cpp" line="429"/>
|
<location filename="src/Menu.cpp" line="437"/>
|
||||||
<source>Open .ini config file</source>
|
<source>Open .ini config file</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="src/Menu.cpp" line="431"/>
|
<location filename="src/Menu.cpp" line="439"/>
|
||||||
<location filename="src/Menu.cpp" line="443"/>
|
<location filename="src/Menu.cpp" line="451"/>
|
||||||
<source>Text files (*.ini)</source>
|
<source>Text files (*.ini)</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="src/Menu.cpp" line="441"/>
|
<location filename="src/Menu.cpp" line="449"/>
|
||||||
<source>Save .ini config file</source>
|
<source>Save .ini config file</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
|
|
@ -1607,8 +1607,8 @@ bool Application::isLookingAtMyAvatar(Avatar* avatar) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::updateLOD() {
|
void Application::updateLOD() {
|
||||||
// adjust it unless we were asked to disable this feature
|
// adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode
|
||||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableAutoAdjustLOD)) {
|
if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableAutoAdjustLOD) && !isThrottleRendering()) {
|
||||||
Menu::getInstance()->autoAdjustLOD(_fps);
|
Menu::getInstance()->autoAdjustLOD(_fps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,6 +147,7 @@ public:
|
||||||
glm::vec3 getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVoxel);
|
glm::vec3 getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVoxel);
|
||||||
|
|
||||||
QGLWidget* getGLWidget() { return _glWidget; }
|
QGLWidget* getGLWidget() { return _glWidget; }
|
||||||
|
bool isThrottleRendering() const { return _glWidget->isThrottleRendering(); }
|
||||||
MyAvatar* getAvatar() { return _myAvatar; }
|
MyAvatar* getAvatar() { return _myAvatar; }
|
||||||
Audio* getAudio() { return &_audio; }
|
Audio* getAudio() { return &_audio; }
|
||||||
Camera* getCamera() { return &_myCamera; }
|
Camera* getCamera() { return &_myCamera; }
|
||||||
|
@ -339,7 +340,7 @@ private:
|
||||||
void displayRearMirrorTools();
|
void displayRearMirrorTools();
|
||||||
|
|
||||||
QMainWindow* _window;
|
QMainWindow* _window;
|
||||||
QGLWidget* _glWidget;
|
GLCanvas* _glWidget; // our GLCanvas has a couple extra features
|
||||||
|
|
||||||
bool _statsExpanded;
|
bool _statsExpanded;
|
||||||
BandwidthMeter _bandwidthMeter;
|
BandwidthMeter _bandwidthMeter;
|
||||||
|
|
|
@ -21,6 +21,10 @@ GLCanvas::GLCanvas() : QGLWidget(QGLFormat(QGL::NoDepthBuffer)),
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GLCanvas::isThrottleRendering() const {
|
||||||
|
return _throttleRendering || Application::getInstance()->getWindow()->isMinimized();
|
||||||
|
}
|
||||||
|
|
||||||
void GLCanvas::initializeGL() {
|
void GLCanvas::initializeGL() {
|
||||||
Application::getInstance()->initializeGL();
|
Application::getInstance()->initializeGL();
|
||||||
setAttribute(Qt::WA_AcceptTouchEvents);
|
setAttribute(Qt::WA_AcceptTouchEvents);
|
||||||
|
|
|
@ -17,6 +17,7 @@ class GLCanvas : public QGLWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
GLCanvas();
|
GLCanvas();
|
||||||
|
bool isThrottleRendering() const;
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
QTimer _frameTimer;
|
QTimer _frameTimer;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QMenuBar>
|
#include <QMenuBar>
|
||||||
|
#include <QMessageBox>
|
||||||
#include <QShortcut>
|
#include <QShortcut>
|
||||||
#include <QSlider>
|
#include <QSlider>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
@ -36,6 +37,7 @@
|
||||||
#include "InfoView.h"
|
#include "InfoView.h"
|
||||||
#include "ui/MetavoxelEditor.h"
|
#include "ui/MetavoxelEditor.h"
|
||||||
|
|
||||||
|
|
||||||
Menu* Menu::_instance = NULL;
|
Menu* Menu::_instance = NULL;
|
||||||
|
|
||||||
Menu* Menu::getInstance() {
|
Menu* Menu::getInstance() {
|
||||||
|
@ -78,7 +80,7 @@ Menu::Menu() :
|
||||||
_loginAction(NULL)
|
_loginAction(NULL)
|
||||||
{
|
{
|
||||||
Application *appInstance = Application::getInstance();
|
Application *appInstance = Application::getInstance();
|
||||||
|
|
||||||
QMenu* fileMenu = addMenu("File");
|
QMenu* fileMenu = addMenu("File");
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
|
@ -116,13 +118,18 @@ Menu::Menu() :
|
||||||
addActionToQMenuAndActionHash(fileMenu,
|
addActionToQMenuAndActionHash(fileMenu,
|
||||||
MenuOption::GoToDomain,
|
MenuOption::GoToDomain,
|
||||||
Qt::CTRL | Qt::Key_D,
|
Qt::CTRL | Qt::Key_D,
|
||||||
this,
|
this,
|
||||||
SLOT(goToDomainDialog()));
|
SLOT(goToDomainDialog()));
|
||||||
addActionToQMenuAndActionHash(fileMenu,
|
addActionToQMenuAndActionHash(fileMenu,
|
||||||
MenuOption::GoToLocation,
|
MenuOption::GoToLocation,
|
||||||
Qt::CTRL | Qt::SHIFT | Qt::Key_L,
|
Qt::CTRL | Qt::SHIFT | Qt::Key_L,
|
||||||
this,
|
this,
|
||||||
SLOT(goToLocation()));
|
SLOT(goToLocation()));
|
||||||
|
addActionToQMenuAndActionHash(fileMenu,
|
||||||
|
MenuOption::NameLocation,
|
||||||
|
Qt::CTRL | Qt::Key_N,
|
||||||
|
this,
|
||||||
|
SLOT(nameLocation()));
|
||||||
addActionToQMenuAndActionHash(fileMenu,
|
addActionToQMenuAndActionHash(fileMenu,
|
||||||
MenuOption::GoTo,
|
MenuOption::GoTo,
|
||||||
Qt::Key_At,
|
Qt::Key_At,
|
||||||
|
@ -421,6 +428,7 @@ void Menu::saveSettings(QSettings* settings) {
|
||||||
scanMenuBar(&saveAction, settings);
|
scanMenuBar(&saveAction, settings);
|
||||||
Application::getInstance()->getAvatar()->saveData(settings);
|
Application::getInstance()->getAvatar()->saveData(settings);
|
||||||
NodeList::getInstance()->saveData(settings);
|
NodeList::getInstance()->saveData(settings);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::importSettings() {
|
void Menu::importSettings() {
|
||||||
|
@ -864,67 +872,11 @@ void Menu::goToDomainDialog() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::goToOrientation(QString orientation) {
|
void Menu::goToOrientation(QString orientation) {
|
||||||
|
LocationManager::getInstance().goToDestination(orientation);
|
||||||
if (orientation.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList orientationItems = orientation.split(QRegExp("_|,"), QString::SkipEmptyParts);
|
|
||||||
|
|
||||||
const int NUMBER_OF_ORIENTATION_ITEMS = 4;
|
|
||||||
const int W_ITEM = 0;
|
|
||||||
const int X_ITEM = 1;
|
|
||||||
const int Y_ITEM = 2;
|
|
||||||
const int Z_ITEM = 3;
|
|
||||||
|
|
||||||
if (orientationItems.size() == NUMBER_OF_ORIENTATION_ITEMS) {
|
|
||||||
|
|
||||||
double w = replaceLastOccurrence('-', '.', orientationItems[W_ITEM].trimmed()).toDouble();
|
|
||||||
double x = replaceLastOccurrence('-', '.', orientationItems[X_ITEM].trimmed()).toDouble();
|
|
||||||
double y = replaceLastOccurrence('-', '.', orientationItems[Y_ITEM].trimmed()).toDouble();
|
|
||||||
double z = replaceLastOccurrence('-', '.', orientationItems[Z_ITEM].trimmed()).toDouble();
|
|
||||||
|
|
||||||
glm::quat newAvatarOrientation(w, x, y, z);
|
|
||||||
|
|
||||||
MyAvatar* myAvatar = Application::getInstance()->getAvatar();
|
|
||||||
glm::quat avatarOrientation = myAvatar->getOrientation();
|
|
||||||
if (newAvatarOrientation != avatarOrientation) {
|
|
||||||
myAvatar->setOrientation(newAvatarOrientation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Menu::goToDestination(QString destination) {
|
bool Menu::goToDestination(QString destination) {
|
||||||
|
return LocationManager::getInstance().goToDestination(destination);
|
||||||
QStringList coordinateItems = destination.split(QRegExp("_|,"), QString::SkipEmptyParts);
|
|
||||||
|
|
||||||
const int NUMBER_OF_COORDINATE_ITEMS = 3;
|
|
||||||
const int X_ITEM = 0;
|
|
||||||
const int Y_ITEM = 1;
|
|
||||||
const int Z_ITEM = 2;
|
|
||||||
if (coordinateItems.size() == NUMBER_OF_COORDINATE_ITEMS) {
|
|
||||||
|
|
||||||
double x = replaceLastOccurrence('-', '.', coordinateItems[X_ITEM].trimmed()).toDouble();
|
|
||||||
double y = replaceLastOccurrence('-', '.', coordinateItems[Y_ITEM].trimmed()).toDouble();
|
|
||||||
double z = replaceLastOccurrence('-', '.', coordinateItems[Z_ITEM].trimmed()).toDouble();
|
|
||||||
|
|
||||||
glm::vec3 newAvatarPos(x, y, z);
|
|
||||||
|
|
||||||
MyAvatar* myAvatar = Application::getInstance()->getAvatar();
|
|
||||||
glm::vec3 avatarPos = myAvatar->getPosition();
|
|
||||||
if (newAvatarPos != avatarPos) {
|
|
||||||
// send a node kill request, indicating to other clients that they should play the "disappeared" effect
|
|
||||||
MyAvatar::sendKillAvatar();
|
|
||||||
|
|
||||||
qDebug("Going To Location: %f, %f, %f...", x, y, z);
|
|
||||||
myAvatar->setPosition(newAvatarPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// no coordinates were parsed
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::goTo() {
|
void Menu::goTo() {
|
||||||
|
@ -939,25 +891,33 @@ void Menu::goTo() {
|
||||||
|
|
||||||
int dialogReturn = gotoDialog.exec();
|
int dialogReturn = gotoDialog.exec();
|
||||||
if (dialogReturn == QDialog::Accepted && !gotoDialog.textValue().isEmpty()) {
|
if (dialogReturn == QDialog::Accepted && !gotoDialog.textValue().isEmpty()) {
|
||||||
|
LocationManager* manager = &LocationManager::getInstance();
|
||||||
destination = gotoDialog.textValue();
|
manager->goTo(gotoDialog.textValue());
|
||||||
|
connect(manager, &LocationManager::multipleDestinationsFound, this, &Menu::multipleDestinationsDecision);
|
||||||
// go to coordinate destination or to Username
|
|
||||||
if (!goToDestination(destination)) {
|
|
||||||
JSONCallbackParameters callbackParams;
|
|
||||||
callbackParams.jsonCallbackReceiver = Application::getInstance()->getAvatar();
|
|
||||||
callbackParams.jsonCallbackMethod = "goToLocationFromResponse";
|
|
||||||
|
|
||||||
// there's a username entered by the user, make a request to the data-server for the associated location
|
|
||||||
AccountManager::getInstance().authenticatedRequest("/api/v1/users/" + gotoDialog.textValue() + "/address",
|
|
||||||
QNetworkAccessManager::GetOperation,
|
|
||||||
callbackParams);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sendFakeEnterEvent();
|
sendFakeEnterEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Menu::multipleDestinationsDecision(const QJsonObject& userData, const QJsonObject& placeData) {
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setText("Both user and location exists with same name");
|
||||||
|
msgBox.setInformativeText("Where you wanna go?");
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Open);
|
||||||
|
msgBox.button(QMessageBox::Ok)->setText("User");
|
||||||
|
msgBox.button(QMessageBox::Open)->setText("Place");
|
||||||
|
int userResponse = msgBox.exec();
|
||||||
|
|
||||||
|
if (userResponse == QMessageBox::Ok) {
|
||||||
|
Application::getInstance()->getAvatar()->goToLocationFromResponse(userData);
|
||||||
|
} else if (userResponse == QMessageBox::Open) {
|
||||||
|
Application::getInstance()->getAvatar()->goToLocationFromResponse(userData);
|
||||||
|
}
|
||||||
|
|
||||||
|
LocationManager* manager = reinterpret_cast<LocationManager*>(sender());
|
||||||
|
disconnect(manager, &LocationManager::multipleDestinationsFound, this, &Menu::multipleDestinationsDecision);
|
||||||
|
}
|
||||||
|
|
||||||
void Menu::goToLocation() {
|
void Menu::goToLocation() {
|
||||||
MyAvatar* myAvatar = Application::getInstance()->getAvatar();
|
MyAvatar* myAvatar = Application::getInstance()->getAvatar();
|
||||||
glm::vec3 avatarPos = myAvatar->getPosition();
|
glm::vec3 avatarPos = myAvatar->getPosition();
|
||||||
|
@ -980,6 +940,69 @@ void Menu::goToLocation() {
|
||||||
sendFakeEnterEvent();
|
sendFakeEnterEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Menu::namedLocationCreated(LocationManager::NamedLocationCreateResponse response) {
|
||||||
|
|
||||||
|
if (response == LocationManager::Created) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMessageBox msgBox;
|
||||||
|
switch (response) {
|
||||||
|
case LocationManager::AlreadyExists:
|
||||||
|
msgBox.setText("That name has been already claimed, try something else.");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
msgBox.setText("An unexpected error has occurred, please try again later.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
msgBox.exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Menu::nameLocation() {
|
||||||
|
// check if user is logged in or show login dialog if not
|
||||||
|
|
||||||
|
AccountManager& accountManager = AccountManager::getInstance();
|
||||||
|
if (!accountManager.isLoggedIn()) {
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setText("We need to tie this location to your username.");
|
||||||
|
msgBox.setInformativeText("Please login first, then try naming the location again.");
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
|
||||||
|
msgBox.button(QMessageBox::Ok)->setText("Login");
|
||||||
|
if (msgBox.exec() == QMessageBox::Ok) {
|
||||||
|
loginForCurrentDomain();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QInputDialog nameDialog(Application::getInstance()->getWindow());
|
||||||
|
nameDialog.setWindowTitle("Name this location");
|
||||||
|
nameDialog.setLabelText("Name this location, then share that name with others.\n"
|
||||||
|
"When they come here, they'll be in the same location and orientation\n"
|
||||||
|
"(wherever you are standing and looking now) as you.\n\n"
|
||||||
|
"Location name:");
|
||||||
|
|
||||||
|
nameDialog.setWindowFlags(Qt::Sheet);
|
||||||
|
nameDialog.resize((int) (nameDialog.parentWidget()->size().width() * 0.30), nameDialog.size().height());
|
||||||
|
|
||||||
|
if (nameDialog.exec() == QDialog::Accepted) {
|
||||||
|
|
||||||
|
QString locationName = nameDialog.textValue().trimmed();
|
||||||
|
if (locationName.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MyAvatar* myAvatar = Application::getInstance()->getAvatar();
|
||||||
|
LocationManager* manager = new LocationManager();
|
||||||
|
connect(manager, &LocationManager::creationCompleted, this, &Menu::namedLocationCreated);
|
||||||
|
NamedLocation* location = new NamedLocation(locationName,
|
||||||
|
myAvatar->getPosition(), myAvatar->getOrientation(),
|
||||||
|
NodeList::getInstance()->getDomainInfo().getHostname());
|
||||||
|
manager->createNamedLocation(location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Menu::pasteToVoxel() {
|
void Menu::pasteToVoxel() {
|
||||||
QInputDialog pasteToOctalCodeDialog(Application::getInstance()->getWindow());
|
QInputDialog pasteToOctalCodeDialog(Application::getInstance()->getWindow());
|
||||||
pasteToOctalCodeDialog.setWindowTitle("Paste to Voxel");
|
pasteToOctalCodeDialog.setWindowTitle("Paste to Voxel");
|
||||||
|
@ -1246,17 +1269,6 @@ void Menu::addAvatarCollisionSubMenu(QMenu* overMenu) {
|
||||||
0, true, avatar, SLOT(updateCollisionFlags()));
|
0, true, avatar, SLOT(updateCollisionFlags()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Menu::replaceLastOccurrence(QChar search, QChar replace, QString string) {
|
|
||||||
int lastIndex;
|
|
||||||
lastIndex = string.lastIndexOf(search);
|
|
||||||
if (lastIndex > 0) {
|
|
||||||
lastIndex = string.lastIndexOf(search);
|
|
||||||
string.replace(lastIndex, 1, replace);
|
|
||||||
}
|
|
||||||
|
|
||||||
return string;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAction* Menu::getActionFromName(const QString& menuName, QMenu* menu) {
|
QAction* Menu::getActionFromName(const QString& menuName, QMenu* menu) {
|
||||||
QList<QAction*> menuActions;
|
QList<QAction*> menuActions;
|
||||||
if (menu) {
|
if (menu) {
|
||||||
|
|
|
@ -18,7 +18,8 @@
|
||||||
#include <MenuItemProperties.h>
|
#include <MenuItemProperties.h>
|
||||||
#include <OctreeConstants.h>
|
#include <OctreeConstants.h>
|
||||||
|
|
||||||
#include <ui/ChatWindow.h>
|
#include "location/LocationManager.h"
|
||||||
|
#include "ui/ChatWindow.h"
|
||||||
|
|
||||||
const float ADJUST_LOD_DOWN_FPS = 40.0;
|
const float ADJUST_LOD_DOWN_FPS = 40.0;
|
||||||
const float ADJUST_LOD_UP_FPS = 55.0;
|
const float ADJUST_LOD_UP_FPS = 55.0;
|
||||||
|
@ -138,6 +139,7 @@ private slots:
|
||||||
void editPreferences();
|
void editPreferences();
|
||||||
void goToDomainDialog();
|
void goToDomainDialog();
|
||||||
void goToLocation();
|
void goToLocation();
|
||||||
|
void nameLocation();
|
||||||
void bandwidthDetailsClosed();
|
void bandwidthDetailsClosed();
|
||||||
void octreeStatsDetailsClosed();
|
void octreeStatsDetailsClosed();
|
||||||
void lodToolsClosed();
|
void lodToolsClosed();
|
||||||
|
@ -147,6 +149,8 @@ private slots:
|
||||||
void showChat();
|
void showChat();
|
||||||
void toggleChat();
|
void toggleChat();
|
||||||
void audioMuteToggled();
|
void audioMuteToggled();
|
||||||
|
void namedLocationCreated(LocationManager::NamedLocationCreateResponse response);
|
||||||
|
void multipleDestinationsDecision(const QJsonObject& userData, const QJsonObject& placeData);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Menu* _instance;
|
static Menu* _instance;
|
||||||
|
@ -248,6 +252,7 @@ namespace MenuOption {
|
||||||
const QString GlowMode = "Cycle Glow Mode";
|
const QString GlowMode = "Cycle Glow Mode";
|
||||||
const QString GoToDomain = "Go To Domain...";
|
const QString GoToDomain = "Go To Domain...";
|
||||||
const QString GoToLocation = "Go To Location...";
|
const QString GoToLocation = "Go To Location...";
|
||||||
|
const QString NameLocation = "Name this location";
|
||||||
const QString GoTo = "Go To...";
|
const QString GoTo = "Go To...";
|
||||||
const QString IncreaseAvatarSize = "Increase Avatar Size";
|
const QString IncreaseAvatarSize = "Increase Avatar Size";
|
||||||
const QString IncreaseVoxelSize = "Increase Voxel Size";
|
const QString IncreaseVoxelSize = "Increase Voxel Size";
|
||||||
|
|
|
@ -535,7 +535,7 @@ void runTimingTests() {
|
||||||
}
|
}
|
||||||
gettimeofday(&endTime, NULL);
|
gettimeofday(&endTime, NULL);
|
||||||
elapsedMsecs = diffclock(&startTime, &endTime);
|
elapsedMsecs = diffclock(&startTime, &endTime);
|
||||||
qDebug("rand() stored in array usecs: %f", 1000.0f * elapsedMsecs / (float) numTests);
|
qDebug("rand() stored in array usecs: %f, first result:%d", 1000.0f * elapsedMsecs / (float) numTests, iResults[0]);
|
||||||
|
|
||||||
// Random number generation using randFloat()
|
// Random number generation using randFloat()
|
||||||
gettimeofday(&startTime, NULL);
|
gettimeofday(&startTime, NULL);
|
||||||
|
@ -544,7 +544,7 @@ void runTimingTests() {
|
||||||
}
|
}
|
||||||
gettimeofday(&endTime, NULL);
|
gettimeofday(&endTime, NULL);
|
||||||
elapsedMsecs = diffclock(&startTime, &endTime);
|
elapsedMsecs = diffclock(&startTime, &endTime);
|
||||||
qDebug("randFloat() stored in array usecs: %f", 1000.0f * elapsedMsecs / (float) numTests);
|
qDebug("randFloat() stored in array usecs: %f, first result: %f", 1000.0f * elapsedMsecs / (float) numTests, fResults[0]);
|
||||||
|
|
||||||
// PowF function
|
// PowF function
|
||||||
fTest = 1145323.2342f;
|
fTest = 1145323.2342f;
|
||||||
|
@ -567,8 +567,8 @@ void runTimingTests() {
|
||||||
}
|
}
|
||||||
gettimeofday(&endTime, NULL);
|
gettimeofday(&endTime, NULL);
|
||||||
elapsedMsecs = diffclock(&startTime, &endTime);
|
elapsedMsecs = diffclock(&startTime, &endTime);
|
||||||
qDebug("vector math usecs: %f [%f msecs total for %d tests]",
|
qDebug("vector math usecs: %f [%f msecs total for %d tests], last result:%f",
|
||||||
1000.0f * elapsedMsecs / (float) numTests, elapsedMsecs, numTests);
|
1000.0f * elapsedMsecs / (float) numTests, elapsedMsecs, numTests, distance);
|
||||||
|
|
||||||
// Vec3 test
|
// Vec3 test
|
||||||
glm::vec3 vecA(randVector()), vecB(randVector());
|
glm::vec3 vecA(randVector()), vecB(randVector());
|
||||||
|
@ -581,7 +581,7 @@ void runTimingTests() {
|
||||||
}
|
}
|
||||||
gettimeofday(&endTime, NULL);
|
gettimeofday(&endTime, NULL);
|
||||||
elapsedMsecs = diffclock(&startTime, &endTime);
|
elapsedMsecs = diffclock(&startTime, &endTime);
|
||||||
qDebug("vec3 assign and dot() usecs: %f", 1000.0f * elapsedMsecs / (float) numTests);
|
qDebug("vec3 assign and dot() usecs: %f, last result:%f", 1000.0f * elapsedMsecs / (float) numTests, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
float loadSetting(QSettings* settings, const char* name, float defaultValue) {
|
float loadSetting(QSettings* settings, const char* name, float defaultValue) {
|
||||||
|
|
|
@ -243,7 +243,7 @@ VoxelSystem::~VoxelSystem() {
|
||||||
|
|
||||||
// This is called by the main application thread on both the initialization of the application and when
|
// This is called by the main application thread on both the initialization of the application and when
|
||||||
// the preferences dialog box is called/saved
|
// the preferences dialog box is called/saved
|
||||||
void VoxelSystem::setMaxVoxels(int maxVoxels) {
|
void VoxelSystem::setMaxVoxels(unsigned long maxVoxels) {
|
||||||
if (maxVoxels == _maxVoxels) {
|
if (maxVoxels == _maxVoxels) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -550,7 +550,7 @@ int VoxelSystem::parseData(const QByteArray& packet) {
|
||||||
int flightTime = arrivedAt - sentAt;
|
int flightTime = arrivedAt - sentAt;
|
||||||
|
|
||||||
OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0;
|
OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0;
|
||||||
int dataBytes = packet.size() - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE);
|
unsigned int dataBytes = packet.size() - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE);
|
||||||
|
|
||||||
int subsection = 1;
|
int subsection = 1;
|
||||||
while (dataBytes > 0) {
|
while (dataBytes > 0) {
|
||||||
|
@ -576,7 +576,7 @@ int VoxelSystem::parseData(const QByteArray& packet) {
|
||||||
packetData.loadFinalizedContent(dataAt, sectionLength);
|
packetData.loadFinalizedContent(dataAt, sectionLength);
|
||||||
if (Application::getInstance()->getLogger()->extraDebugging()) {
|
if (Application::getInstance()->getLogger()->extraDebugging()) {
|
||||||
qDebug("VoxelSystem::parseData() ... Got Packet Section"
|
qDebug("VoxelSystem::parseData() ... Got Packet Section"
|
||||||
" color:%s compressed:%s sequence: %u flight:%d usec size:%d data:%d"
|
" color:%s compressed:%s sequence: %u flight:%d usec size:%d data:%u"
|
||||||
" subsection:%d sectionLength:%d uncompressed:%d",
|
" subsection:%d sectionLength:%d uncompressed:%d",
|
||||||
debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed),
|
debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed),
|
||||||
sequence, flightTime, packet.size(), dataBytes, subsection, sectionLength,
|
sequence, flightTime, packet.size(), dataBytes, subsection, sectionLength,
|
||||||
|
@ -919,13 +919,11 @@ void VoxelSystem::copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart,
|
||||||
// Depending on if we're using per vertex normals, we will need more or less vertex points per voxel
|
// Depending on if we're using per vertex normals, we will need more or less vertex points per voxel
|
||||||
int vertexPointsPerVoxel = GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL;
|
int vertexPointsPerVoxel = GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL;
|
||||||
|
|
||||||
GLintptr segmentStartAt = segmentStart * vertexPointsPerVoxel * sizeof(GLfloat);
|
|
||||||
GLsizeiptr segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLfloat);
|
GLsizeiptr segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLfloat);
|
||||||
GLfloat* readVerticesAt = _readVerticesArray + (segmentStart * vertexPointsPerVoxel);
|
GLfloat* readVerticesAt = _readVerticesArray + (segmentStart * vertexPointsPerVoxel);
|
||||||
GLfloat* writeVerticesAt = _writeVerticesArray + (segmentStart * vertexPointsPerVoxel);
|
GLfloat* writeVerticesAt = _writeVerticesArray + (segmentStart * vertexPointsPerVoxel);
|
||||||
memcpy(readVerticesAt, writeVerticesAt, segmentSizeBytes);
|
memcpy(readVerticesAt, writeVerticesAt, segmentSizeBytes);
|
||||||
|
|
||||||
segmentStartAt = segmentStart * vertexPointsPerVoxel * sizeof(GLubyte);
|
|
||||||
segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLubyte);
|
segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLubyte);
|
||||||
GLubyte* readColorsAt = _readColorsArray + (segmentStart * vertexPointsPerVoxel);
|
GLubyte* readColorsAt = _readColorsArray + (segmentStart * vertexPointsPerVoxel);
|
||||||
GLubyte* writeColorsAt = _writeColorsArray + (segmentStart * vertexPointsPerVoxel);
|
GLubyte* writeColorsAt = _writeColorsArray + (segmentStart * vertexPointsPerVoxel);
|
||||||
|
@ -1958,10 +1956,8 @@ bool VoxelSystem::showAllSubTreeOperation(OctreeElement* element, void* extraDat
|
||||||
// If we've culled at least once, then we will use the status of this voxel in the last culled frustum to determine
|
// If we've culled at least once, then we will use the status of this voxel in the last culled frustum to determine
|
||||||
// how to proceed. If we've never culled, then we just consider all these voxels to be UNKNOWN so that we will not
|
// how to proceed. If we've never culled, then we just consider all these voxels to be UNKNOWN so that we will not
|
||||||
// consider that case.
|
// consider that case.
|
||||||
ViewFrustum::location inLastCulledFrustum;
|
|
||||||
|
|
||||||
if (args->culledOnce && args->wantDeltaFrustums) {
|
if (args->culledOnce && args->wantDeltaFrustums) {
|
||||||
inLastCulledFrustum = voxel->inFrustum(args->lastViewFrustum);
|
ViewFrustum::location inLastCulledFrustum = voxel->inFrustum(args->lastViewFrustum);
|
||||||
|
|
||||||
// if this node is fully inside our last culled view frustum, then we don't need to recurse further
|
// if this node is fully inside our last culled view frustum, then we don't need to recurse further
|
||||||
if (inLastCulledFrustum == ViewFrustum::INSIDE) {
|
if (inLastCulledFrustum == ViewFrustum::INSIDE) {
|
||||||
|
@ -2001,7 +1997,7 @@ bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData
|
||||||
// If we've culled at least once, then we will use the status of this voxel in the last culled frustum to determine
|
// If we've culled at least once, then we will use the status of this voxel in the last culled frustum to determine
|
||||||
// how to proceed. If we've never culled, then we just consider all these voxels to be UNKNOWN so that we will not
|
// how to proceed. If we've never culled, then we just consider all these voxels to be UNKNOWN so that we will not
|
||||||
// consider that case.
|
// consider that case.
|
||||||
ViewFrustum::location inLastCulledFrustum;
|
ViewFrustum::location inLastCulledFrustum = ViewFrustum::OUTSIDE; // assume outside, but should get reset to actual value
|
||||||
|
|
||||||
if (args->culledOnce && args->wantDeltaFrustums) {
|
if (args->culledOnce && args->wantDeltaFrustums) {
|
||||||
inLastCulledFrustum = voxel->inFrustum(args->lastViewFrustum);
|
inLastCulledFrustum = voxel->inFrustum(args->lastViewFrustum);
|
||||||
|
|
|
@ -67,7 +67,7 @@ public:
|
||||||
|
|
||||||
ViewFrustum* getLastCulledViewFrustum() { return &_lastCulledViewFrustum; }
|
ViewFrustum* getLastCulledViewFrustum() { return &_lastCulledViewFrustum; }
|
||||||
|
|
||||||
void setMaxVoxels(int maxVoxels);
|
void setMaxVoxels(unsigned long maxVoxels);
|
||||||
long int getMaxVoxels() const { return _maxVoxels; }
|
long int getMaxVoxels() const { return _maxVoxels; }
|
||||||
unsigned long getVoxelMemoryUsageRAM() const { return _memoryUsageRAM; }
|
unsigned long getVoxelMemoryUsageRAM() const { return _memoryUsageRAM; }
|
||||||
unsigned long getVoxelMemoryUsageVBO() const { return _memoryUsageVBO; }
|
unsigned long getVoxelMemoryUsageVBO() const { return _memoryUsageVBO; }
|
||||||
|
@ -263,7 +263,7 @@ private:
|
||||||
bool _usePrimitiveRenderer; ///< Flag primitive renderer for use
|
bool _usePrimitiveRenderer; ///< Flag primitive renderer for use
|
||||||
PrimitiveRenderer* _renderer; ///< Voxel renderer
|
PrimitiveRenderer* _renderer; ///< Voxel renderer
|
||||||
|
|
||||||
static const int _sNumOctantsPerHemiVoxel = 4;
|
static const unsigned int _sNumOctantsPerHemiVoxel = 4;
|
||||||
static int _sCorrectedChildIndex[8];
|
static int _sCorrectedChildIndex[8];
|
||||||
static unsigned short _sSwizzledOcclusionBits[64]; ///< Swizzle value of bit pairs of the value of index
|
static unsigned short _sSwizzledOcclusionBits[64]; ///< Swizzle value of bit pairs of the value of index
|
||||||
static unsigned char _sOctantIndexToBitMask[8]; ///< Map octant index to partition mask
|
static unsigned char _sOctantIndexToBitMask[8]; ///< Map octant index to partition mask
|
||||||
|
|
227
interface/src/location/LocationManager.cpp
Normal file
227
interface/src/location/LocationManager.cpp
Normal file
|
@ -0,0 +1,227 @@
|
||||||
|
//
|
||||||
|
// LocationManager.cpp
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Stojce Slavkovski on 2/7/14.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
|
#include "LocationManager.h"
|
||||||
|
|
||||||
|
const QString GET_USER_ADDRESS = "/api/v1/users/%1/address";
|
||||||
|
const QString GET_PLACE_ADDRESS = "/api/v1/places/%1/address";
|
||||||
|
const QString POST_PLACE_CREATE = "/api/v1/places/";
|
||||||
|
|
||||||
|
|
||||||
|
LocationManager::LocationManager() : _userData(), _placeData() {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
LocationManager& LocationManager::getInstance() {
|
||||||
|
static LocationManager sharedInstance;
|
||||||
|
return sharedInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocationManager::namedLocationDataReceived(const QJsonObject& data) {
|
||||||
|
if (data.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.contains("status") && data["status"].toString() == "success") {
|
||||||
|
emit creationCompleted(LocationManager::Created);
|
||||||
|
} else {
|
||||||
|
emit creationCompleted(LocationManager::AlreadyExists);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocationManager::errorDataReceived(QNetworkReply::NetworkError error, const QString& message) {
|
||||||
|
emit creationCompleted(LocationManager::SystemError);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocationManager::createNamedLocation(NamedLocation* namedLocation) {
|
||||||
|
AccountManager& accountManager = AccountManager::getInstance();
|
||||||
|
if (accountManager.isLoggedIn()) {
|
||||||
|
JSONCallbackParameters callbackParams;
|
||||||
|
callbackParams.jsonCallbackReceiver = this;
|
||||||
|
callbackParams.jsonCallbackMethod = "namedLocationDataReceived";
|
||||||
|
callbackParams.errorCallbackReceiver = this;
|
||||||
|
callbackParams.errorCallbackMethod = "errorDataReceived";
|
||||||
|
|
||||||
|
accountManager.authenticatedRequest(POST_PLACE_CREATE, QNetworkAccessManager::PostOperation,
|
||||||
|
callbackParams, namedLocation->toJsonString().toUtf8());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocationManager::goTo(QString destination) {
|
||||||
|
|
||||||
|
if (destination.startsWith("@")) {
|
||||||
|
// remove '@' and go to user
|
||||||
|
goToUser(destination.remove(0, 1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destination.startsWith("#")) {
|
||||||
|
// remove '#' and go to named place
|
||||||
|
goToPlace(destination.remove(0, 1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// go to coordinate destination or to Username
|
||||||
|
if (!goToDestination(destination)) {
|
||||||
|
// reset data on local variables
|
||||||
|
_userData = QJsonObject();
|
||||||
|
_placeData = QJsonObject();
|
||||||
|
|
||||||
|
destination = QString(QUrl::toPercentEncoding(destination));
|
||||||
|
JSONCallbackParameters callbackParams;
|
||||||
|
callbackParams.jsonCallbackReceiver = this;
|
||||||
|
callbackParams.jsonCallbackMethod = "goToUserFromResponse";
|
||||||
|
AccountManager::getInstance().authenticatedRequest(GET_USER_ADDRESS.arg(destination),
|
||||||
|
QNetworkAccessManager::GetOperation,
|
||||||
|
callbackParams);
|
||||||
|
|
||||||
|
callbackParams.jsonCallbackMethod = "goToLocationFromResponse";
|
||||||
|
AccountManager::getInstance().authenticatedRequest(GET_PLACE_ADDRESS.arg(destination),
|
||||||
|
QNetworkAccessManager::GetOperation,
|
||||||
|
callbackParams);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocationManager::goToUserFromResponse(const QJsonObject& jsonObject) {
|
||||||
|
_userData = jsonObject;
|
||||||
|
checkForMultipleDestinations();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocationManager::goToLocationFromResponse(const QJsonObject& jsonObject) {
|
||||||
|
_placeData = jsonObject;
|
||||||
|
checkForMultipleDestinations();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocationManager::checkForMultipleDestinations() {
|
||||||
|
if (!_userData.isEmpty() && !_placeData.isEmpty()) {
|
||||||
|
if (_userData.contains("status") && _userData["status"].toString() == "success" &&
|
||||||
|
_placeData.contains("status") && _placeData["status"].toString() == "success") {
|
||||||
|
emit multipleDestinationsFound(_userData, _placeData);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_userData.contains("status") && _userData["status"].toString() == "success") {
|
||||||
|
Application::getInstance()->getAvatar()->goToLocationFromResponse(_userData);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_placeData.contains("status") && _placeData["status"].toString() == "success") {
|
||||||
|
Application::getInstance()->getAvatar()->goToLocationFromResponse(_placeData);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit locationChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocationManager::goToUser(QString userName) {
|
||||||
|
|
||||||
|
JSONCallbackParameters callbackParams;
|
||||||
|
callbackParams.jsonCallbackReceiver = Application::getInstance()->getAvatar();
|
||||||
|
callbackParams.jsonCallbackMethod = "goToLocationFromResponse";
|
||||||
|
|
||||||
|
userName = QString(QUrl::toPercentEncoding(userName));
|
||||||
|
AccountManager::getInstance().authenticatedRequest(GET_USER_ADDRESS.arg(userName),
|
||||||
|
QNetworkAccessManager::GetOperation,
|
||||||
|
callbackParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocationManager::goToPlace(QString placeName) {
|
||||||
|
JSONCallbackParameters callbackParams;
|
||||||
|
callbackParams.jsonCallbackReceiver = Application::getInstance()->getAvatar();
|
||||||
|
callbackParams.jsonCallbackMethod = "goToLocationFromResponse";
|
||||||
|
|
||||||
|
placeName = QString(QUrl::toPercentEncoding(placeName));
|
||||||
|
AccountManager::getInstance().authenticatedRequest(GET_PLACE_ADDRESS.arg(placeName),
|
||||||
|
QNetworkAccessManager::GetOperation,
|
||||||
|
callbackParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocationManager::goToOrientation(QString orientation) {
|
||||||
|
if (orientation.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList orientationItems = orientation.remove(' ').split(QRegExp("_|,"), QString::SkipEmptyParts);
|
||||||
|
|
||||||
|
const int NUMBER_OF_ORIENTATION_ITEMS = 4;
|
||||||
|
const int W_ITEM = 0;
|
||||||
|
const int X_ITEM = 1;
|
||||||
|
const int Y_ITEM = 2;
|
||||||
|
const int Z_ITEM = 3;
|
||||||
|
|
||||||
|
if (orientationItems.size() == NUMBER_OF_ORIENTATION_ITEMS) {
|
||||||
|
|
||||||
|
// replace last occurrence of '_' with decimal point
|
||||||
|
replaceLastOccurrence('-', '.', orientationItems[W_ITEM]);
|
||||||
|
replaceLastOccurrence('-', '.', orientationItems[X_ITEM]);
|
||||||
|
replaceLastOccurrence('-', '.', orientationItems[Y_ITEM]);
|
||||||
|
replaceLastOccurrence('-', '.', orientationItems[Z_ITEM]);
|
||||||
|
|
||||||
|
double w = orientationItems[W_ITEM].toDouble();
|
||||||
|
double x = orientationItems[X_ITEM].toDouble();
|
||||||
|
double y = orientationItems[Y_ITEM].toDouble();
|
||||||
|
double z = orientationItems[Z_ITEM].toDouble();
|
||||||
|
|
||||||
|
glm::quat newAvatarOrientation(w, x, y, z);
|
||||||
|
|
||||||
|
MyAvatar* myAvatar = Application::getInstance()->getAvatar();
|
||||||
|
glm::quat avatarOrientation = myAvatar->getOrientation();
|
||||||
|
if (newAvatarOrientation != avatarOrientation) {
|
||||||
|
myAvatar->setOrientation(newAvatarOrientation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LocationManager::goToDestination(QString destination) {
|
||||||
|
|
||||||
|
QStringList coordinateItems = destination.remove(' ').split(QRegExp("_|,"), QString::SkipEmptyParts);
|
||||||
|
|
||||||
|
const int NUMBER_OF_COORDINATE_ITEMS = 3;
|
||||||
|
const int X_ITEM = 0;
|
||||||
|
const int Y_ITEM = 1;
|
||||||
|
const int Z_ITEM = 2;
|
||||||
|
if (coordinateItems.size() == NUMBER_OF_COORDINATE_ITEMS) {
|
||||||
|
|
||||||
|
// replace last occurrence of '_' with decimal point
|
||||||
|
replaceLastOccurrence('-', '.', coordinateItems[X_ITEM]);
|
||||||
|
replaceLastOccurrence('-', '.', coordinateItems[Y_ITEM]);
|
||||||
|
replaceLastOccurrence('-', '.', coordinateItems[Z_ITEM]);
|
||||||
|
|
||||||
|
double x = coordinateItems[X_ITEM].toDouble();
|
||||||
|
double y = coordinateItems[Y_ITEM].toDouble();
|
||||||
|
double z = coordinateItems[Z_ITEM].toDouble();
|
||||||
|
|
||||||
|
glm::vec3 newAvatarPos(x, y, z);
|
||||||
|
|
||||||
|
MyAvatar* myAvatar = Application::getInstance()->getAvatar();
|
||||||
|
glm::vec3 avatarPos = myAvatar->getPosition();
|
||||||
|
if (newAvatarPos != avatarPos) {
|
||||||
|
// send a node kill request, indicating to other clients that they should play the "disappeared" effect
|
||||||
|
MyAvatar::sendKillAvatar();
|
||||||
|
|
||||||
|
qDebug("Going To Location: %f, %f, %f...", x, y, z);
|
||||||
|
myAvatar->setPosition(newAvatarPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no coordinates were parsed
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocationManager::replaceLastOccurrence(const QChar search, const QChar replace, QString& string) {
|
||||||
|
int lastIndex;
|
||||||
|
lastIndex = string.lastIndexOf(search);
|
||||||
|
if (lastIndex > 0) {
|
||||||
|
lastIndex = string.lastIndexOf(search);
|
||||||
|
string.replace(lastIndex, 1, replace);
|
||||||
|
}
|
||||||
|
}
|
58
interface/src/location/LocationManager.h
Normal file
58
interface/src/location/LocationManager.h
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
//
|
||||||
|
// LocationManager.h
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Stojce Slavkovski on 2/7/14.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __hifi__LocationManager__
|
||||||
|
#define __hifi__LocationManager__
|
||||||
|
|
||||||
|
#include <QtCore>
|
||||||
|
|
||||||
|
#include "AccountManager.h"
|
||||||
|
#include "NamedLocation.h"
|
||||||
|
|
||||||
|
class LocationManager : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
static LocationManager& getInstance();
|
||||||
|
|
||||||
|
enum NamedLocationCreateResponse {
|
||||||
|
Created,
|
||||||
|
AlreadyExists,
|
||||||
|
SystemError
|
||||||
|
};
|
||||||
|
|
||||||
|
LocationManager();
|
||||||
|
void createNamedLocation(NamedLocation* namedLocation);
|
||||||
|
|
||||||
|
void goTo(QString destination);
|
||||||
|
void goToUser(QString userName);
|
||||||
|
void goToPlace(QString placeName);
|
||||||
|
void goToOrientation(QString orientation);
|
||||||
|
bool goToDestination(QString destination);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QJsonObject _userData;
|
||||||
|
QJsonObject _placeData;
|
||||||
|
|
||||||
|
void replaceLastOccurrence(const QChar search, const QChar replace, QString& string);
|
||||||
|
void checkForMultipleDestinations();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void creationCompleted(LocationManager::NamedLocationCreateResponse response);
|
||||||
|
void multipleDestinationsFound(const QJsonObject& userData, const QJsonObject& placeData);
|
||||||
|
void locationChanged();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void namedLocationDataReceived(const QJsonObject& data);
|
||||||
|
void errorDataReceived(QNetworkReply::NetworkError error, const QString& message);
|
||||||
|
void goToLocationFromResponse(const QJsonObject& jsonObject);
|
||||||
|
void goToUserFromResponse(const QJsonObject& jsonObject);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* defined(__hifi__LocationManager__) */
|
24
interface/src/location/NamedLocation.cpp
Normal file
24
interface/src/location/NamedLocation.cpp
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
//
|
||||||
|
// LocationManager.cpp
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Stojce Slavkovski on 2/1/14.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "NamedLocation.h"
|
||||||
|
|
||||||
|
const QString JSON_FORMAT = "{\"address\":{\"position\":\"%1,%2,%3\","
|
||||||
|
"\"orientation\":\"%4,%5,%6,%7\",\"domain\":\"%8\"},\"name\":\"%9\"}";
|
||||||
|
|
||||||
|
QString NamedLocation::toJsonString() {
|
||||||
|
return JSON_FORMAT.arg(QString::number(_location.x),
|
||||||
|
QString::number(_location.y),
|
||||||
|
QString::number(_location.z),
|
||||||
|
QString::number(_orientation.w),
|
||||||
|
QString::number(_orientation.x),
|
||||||
|
QString::number(_orientation.y),
|
||||||
|
QString::number(_orientation.z),
|
||||||
|
_domain,
|
||||||
|
_locationName);
|
||||||
|
}
|
58
interface/src/location/NamedLocation.h
Normal file
58
interface/src/location/NamedLocation.h
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
//
|
||||||
|
// NamedLocation.h
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Stojce Slavkovski on 2/1/14.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __hifi__NamedLocation__
|
||||||
|
#define __hifi__NamedLocation__
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtx/string_cast.hpp>
|
||||||
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
|
||||||
|
#include <QtCore>
|
||||||
|
|
||||||
|
class NamedLocation : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
NamedLocation(QString locationName, glm::vec3 location, glm::quat orientation, QString domain) {
|
||||||
|
_locationName = locationName;
|
||||||
|
_location = location;
|
||||||
|
_orientation = orientation;
|
||||||
|
_domain = domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString toJsonString();
|
||||||
|
|
||||||
|
bool isEmpty() { return _locationName.isNull() || _locationName.isEmpty(); }
|
||||||
|
|
||||||
|
void setLocationName(QString locationName) { _locationName = locationName; }
|
||||||
|
QString locationName() { return _locationName; }
|
||||||
|
|
||||||
|
void setLocation(glm::vec3 location) { _location = location; }
|
||||||
|
glm::vec3 location() { return _location; }
|
||||||
|
|
||||||
|
void setOrientation(glm::quat orentation) { _orientation = orentation; }
|
||||||
|
glm::quat orientation() { return _orientation; }
|
||||||
|
|
||||||
|
void setDomain(QString domain) { _domain = domain; }
|
||||||
|
QString domain() { return _domain; }
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void dataReceived(bool locationExists);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
QString _locationName;
|
||||||
|
QString _createdBy;
|
||||||
|
glm::vec3 _location;
|
||||||
|
glm::quat _orientation;
|
||||||
|
QString _domain;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* defined(__hifi__NamedLocation__) */
|
|
@ -41,7 +41,7 @@ void LocalVoxelsOverlay::update(float deltatime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
_tree->lockForRead();
|
_tree->lockForRead();
|
||||||
if (_visible && _voxelCount != (int)_tree->getOctreeElementsCount()) {
|
if (_visible && _voxelCount != _tree->getOctreeElementsCount()) {
|
||||||
_voxelCount = _tree->getOctreeElementsCount();
|
_voxelCount = _tree->getOctreeElementsCount();
|
||||||
_voxelSystem->forceRedrawEntireTree();
|
_voxelSystem->forceRedrawEntireTree();
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ private:
|
||||||
|
|
||||||
QString _treeName;
|
QString _treeName;
|
||||||
StrongVoxelTreePointer _tree; // so that the tree doesn't get freed
|
StrongVoxelTreePointer _tree; // so that the tree doesn't get freed
|
||||||
int _voxelCount;
|
unsigned long _voxelCount;
|
||||||
StrongVoxelSystemPointer _voxelSystem;
|
StrongVoxelSystemPointer _voxelSystem;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,20 @@ int AudioRingBuffer::parseData(const QByteArray& packet) {
|
||||||
return writeData(packet.data() + numBytesPacketHeader, packet.size() - numBytesPacketHeader);
|
return writeData(packet.data() + numBytesPacketHeader, packet.size() - numBytesPacketHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float AudioRingBuffer::averageLoudnessForBoundarySamples(int numSamples) {
|
||||||
|
// ForBoundarySamples means that we expect the number of samples not to roll of the end of the ring buffer
|
||||||
|
float averageLoudness = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < numSamples; ++i) {
|
||||||
|
averageLoudness += fabsf(_nextOutput[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
averageLoudness /= numSamples;
|
||||||
|
averageLoudness /= MAX_SAMPLE_VALUE;
|
||||||
|
|
||||||
|
return averageLoudness;
|
||||||
|
}
|
||||||
|
|
||||||
qint64 AudioRingBuffer::readSamples(int16_t* destination, qint64 maxSamples) {
|
qint64 AudioRingBuffer::readSamples(int16_t* destination, qint64 maxSamples) {
|
||||||
return readData((char*) destination, maxSamples * sizeof(int16_t));
|
return readData((char*) destination, maxSamples * sizeof(int16_t));
|
||||||
}
|
}
|
||||||
|
@ -121,9 +135,6 @@ qint64 AudioRingBuffer::writeData(const char* data, qint64 maxSize) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t& AudioRingBuffer::operator[](const int index) {
|
int16_t& AudioRingBuffer::operator[](const int index) {
|
||||||
// make sure this is a valid index
|
|
||||||
assert(index > -_sampleCapacity && index < _sampleCapacity);
|
|
||||||
|
|
||||||
return *shiftedPositionAccomodatingWrap(_nextOutput, index);
|
return *shiftedPositionAccomodatingWrap(_nextOutput, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,12 @@ public:
|
||||||
int getSampleCapacity() const { return _sampleCapacity; }
|
int getSampleCapacity() const { return _sampleCapacity; }
|
||||||
|
|
||||||
int parseData(const QByteArray& packet);
|
int parseData(const QByteArray& packet);
|
||||||
|
|
||||||
|
// assume callers using this will never wrap around the end
|
||||||
|
const int16_t* getNextOutput() { return _nextOutput; }
|
||||||
|
const int16_t* getBuffer() { return _buffer; }
|
||||||
|
|
||||||
|
float averageLoudnessForBoundarySamples(int numSamples);
|
||||||
|
|
||||||
qint64 readSamples(int16_t* destination, qint64 maxSamples);
|
qint64 readSamples(int16_t* destination, qint64 maxSamples);
|
||||||
qint64 writeSamples(const int16_t* source, qint64 maxSamples);
|
qint64 writeSamples(const int16_t* source, qint64 maxSamples);
|
||||||
|
|
|
@ -288,7 +288,7 @@ int AvatarData::parseData(const QByteArray& packet) {
|
||||||
// joint data
|
// joint data
|
||||||
int jointCount = *sourceBuffer++;
|
int jointCount = *sourceBuffer++;
|
||||||
_jointData.resize(jointCount);
|
_jointData.resize(jointCount);
|
||||||
unsigned char validity;
|
unsigned char validity = 0; // although always set below, this fixes a warning of potential uninitialized use
|
||||||
int validityBit = 0;
|
int validityBit = 0;
|
||||||
for (int i = 0; i < jointCount; i++) {
|
for (int i = 0; i < jointCount; i++) {
|
||||||
if (validityBit == 0) {
|
if (validityBit == 0) {
|
||||||
|
|
|
@ -217,11 +217,12 @@ int HandData::decodeRemoteData(const QByteArray& dataByteArray) {
|
||||||
palm.setActive(false);
|
palm.setActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// One byte for error checking safety.
|
// One byte for error checking safety. Last byte contains the expected length (less itself)
|
||||||
unsigned char requiredLength = (unsigned char)(sourceBuffer - startPosition);
|
// actualLength less expected byte = (sourceBuffer - startPosition)
|
||||||
unsigned char checkLength = *sourceBuffer++;
|
// expectedLength less expected byte = (*sourceBuffer)
|
||||||
assert(checkLength == requiredLength);
|
assert((unsigned char)(sourceBuffer - startPosition) == (unsigned char)(*sourceBuffer));
|
||||||
|
sourceBuffer++; // skip the trailing byte which is expected length
|
||||||
|
|
||||||
return sourceBuffer - startPosition;
|
return sourceBuffer - startPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -807,13 +807,14 @@ int Octree::encodeTreeBitstream(OctreeElement* node,
|
||||||
|
|
||||||
// write the octal code
|
// write the octal code
|
||||||
bool roomForOctalCode = false; // assume the worst
|
bool roomForOctalCode = false; // assume the worst
|
||||||
int codeLength;
|
int codeLength = 1; // assume root
|
||||||
if (params.chopLevels) {
|
if (params.chopLevels) {
|
||||||
unsigned char* newCode = chopOctalCode(node->getOctalCode(), params.chopLevels);
|
unsigned char* newCode = chopOctalCode(node->getOctalCode(), params.chopLevels);
|
||||||
roomForOctalCode = packetData->startSubTree(newCode);
|
roomForOctalCode = packetData->startSubTree(newCode);
|
||||||
|
|
||||||
if (newCode) {
|
if (newCode) {
|
||||||
delete newCode;
|
delete newCode;
|
||||||
|
codeLength = numberOfThreeBitSectionsInCode(newCode);
|
||||||
} else {
|
} else {
|
||||||
codeLength = 1;
|
codeLength = 1;
|
||||||
}
|
}
|
||||||
|
@ -1559,14 +1560,13 @@ void Octree::copySubTreeIntoNewTree(OctreeElement* startNode, Octree* destinatio
|
||||||
}
|
}
|
||||||
|
|
||||||
static OctreePacketData packetData;
|
static OctreePacketData packetData;
|
||||||
int bytesWritten = 0;
|
|
||||||
|
|
||||||
while (!nodeBag.isEmpty()) {
|
while (!nodeBag.isEmpty()) {
|
||||||
OctreeElement* subTree = nodeBag.extract();
|
OctreeElement* subTree = nodeBag.extract();
|
||||||
packetData.reset(); // reset the packet between usage
|
packetData.reset(); // reset the packet between usage
|
||||||
// ask our tree to write a bitsteam
|
// ask our tree to write a bitsteam
|
||||||
EncodeBitstreamParams params(INT_MAX, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS, chopLevels);
|
EncodeBitstreamParams params(INT_MAX, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS, chopLevels);
|
||||||
bytesWritten = encodeTreeBitstream(subTree, &packetData, nodeBag, params);
|
encodeTreeBitstream(subTree, &packetData, nodeBag, params);
|
||||||
// ask destination tree to read the bitstream
|
// ask destination tree to read the bitstream
|
||||||
ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS);
|
ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS);
|
||||||
destinationTree->readBitstreamToTree(packetData.getUncompressedData(), packetData.getUncompressedSize(), args);
|
destinationTree->readBitstreamToTree(packetData.getUncompressedData(), packetData.getUncompressedSize(), args);
|
||||||
|
@ -1595,7 +1595,6 @@ void Octree::copyFromTreeIntoSubTree(Octree* sourceTree, OctreeElement* destinat
|
||||||
nodeBag.insert(sourceTree->_rootNode);
|
nodeBag.insert(sourceTree->_rootNode);
|
||||||
|
|
||||||
static OctreePacketData packetData;
|
static OctreePacketData packetData;
|
||||||
int bytesWritten = 0;
|
|
||||||
|
|
||||||
while (!nodeBag.isEmpty()) {
|
while (!nodeBag.isEmpty()) {
|
||||||
OctreeElement* subTree = nodeBag.extract();
|
OctreeElement* subTree = nodeBag.extract();
|
||||||
|
@ -1604,7 +1603,7 @@ void Octree::copyFromTreeIntoSubTree(Octree* sourceTree, OctreeElement* destinat
|
||||||
|
|
||||||
// ask our tree to write a bitsteam
|
// ask our tree to write a bitsteam
|
||||||
EncodeBitstreamParams params(INT_MAX, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS);
|
EncodeBitstreamParams params(INT_MAX, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS);
|
||||||
bytesWritten = sourceTree->encodeTreeBitstream(subTree, &packetData, nodeBag, params);
|
sourceTree->encodeTreeBitstream(subTree, &packetData, nodeBag, params);
|
||||||
|
|
||||||
// ask destination tree to read the bitstream
|
// ask destination tree to read the bitstream
|
||||||
bool wantImportProgress = true;
|
bool wantImportProgress = true;
|
||||||
|
|
|
@ -23,7 +23,7 @@ OctreePacketData::OctreePacketData(bool enableCompression, int targetSize) {
|
||||||
changeSettings(enableCompression, targetSize); // does reset...
|
changeSettings(enableCompression, targetSize); // does reset...
|
||||||
}
|
}
|
||||||
|
|
||||||
void OctreePacketData::changeSettings(bool enableCompression, int targetSize) {
|
void OctreePacketData::changeSettings(bool enableCompression, unsigned int targetSize) {
|
||||||
_enableCompression = enableCompression;
|
_enableCompression = enableCompression;
|
||||||
_targetSize = std::min(MAX_OCTREE_UNCOMRESSED_PACKET_SIZE, targetSize);
|
_targetSize = std::min(MAX_OCTREE_UNCOMRESSED_PACKET_SIZE, targetSize);
|
||||||
reset();
|
reset();
|
||||||
|
@ -369,7 +369,7 @@ bool OctreePacketData::compressContent() {
|
||||||
|
|
||||||
QByteArray compressedData = qCompress(uncompressedData, uncompressedSize, MAX_COMPRESSION);
|
QByteArray compressedData = qCompress(uncompressedData, uncompressedSize, MAX_COMPRESSION);
|
||||||
|
|
||||||
if (compressedData.size() < MAX_OCTREE_PACKET_DATA_SIZE) {
|
if (compressedData.size() < (int)MAX_OCTREE_PACKET_DATA_SIZE) {
|
||||||
_compressedBytes = compressedData.size();
|
_compressedBytes = compressedData.size();
|
||||||
for (int i = 0; i < _compressedBytes; i++) {
|
for (int i = 0; i < _compressedBytes; i++) {
|
||||||
_compressed[i] = compressedData[i];
|
_compressed[i] = compressedData[i];
|
||||||
|
|
|
@ -30,15 +30,15 @@ typedef uint16_t OCTREE_PACKET_INTERNAL_SECTION_SIZE;
|
||||||
const int MAX_OCTREE_PACKET_SIZE = MAX_PACKET_SIZE;
|
const int MAX_OCTREE_PACKET_SIZE = MAX_PACKET_SIZE;
|
||||||
|
|
||||||
// this is overly conservative - sizeof(PacketType) is 8 bytes but a packed PacketType could be as small as one byte
|
// this is overly conservative - sizeof(PacketType) is 8 bytes but a packed PacketType could be as small as one byte
|
||||||
const int OCTREE_PACKET_EXTRA_HEADERS_SIZE = sizeof(OCTREE_PACKET_FLAGS)
|
const unsigned int OCTREE_PACKET_EXTRA_HEADERS_SIZE = sizeof(OCTREE_PACKET_FLAGS)
|
||||||
+ sizeof(OCTREE_PACKET_SEQUENCE) + sizeof(OCTREE_PACKET_SENT_TIME);
|
+ sizeof(OCTREE_PACKET_SEQUENCE) + sizeof(OCTREE_PACKET_SENT_TIME);
|
||||||
|
|
||||||
const int MAX_OCTREE_PACKET_DATA_SIZE = MAX_PACKET_SIZE - (MAX_PACKET_HEADER_BYTES + OCTREE_PACKET_EXTRA_HEADERS_SIZE);
|
const unsigned int MAX_OCTREE_PACKET_DATA_SIZE = MAX_PACKET_SIZE - (MAX_PACKET_HEADER_BYTES + OCTREE_PACKET_EXTRA_HEADERS_SIZE);
|
||||||
|
|
||||||
const int MAX_OCTREE_UNCOMRESSED_PACKET_SIZE = MAX_OCTREE_PACKET_DATA_SIZE;
|
const unsigned int MAX_OCTREE_UNCOMRESSED_PACKET_SIZE = MAX_OCTREE_PACKET_DATA_SIZE;
|
||||||
|
|
||||||
const int MINIMUM_ATTEMPT_MORE_PACKING = sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE) + 40;
|
const unsigned int MINIMUM_ATTEMPT_MORE_PACKING = sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE) + 40;
|
||||||
const int COMPRESS_PADDING = 15;
|
const unsigned int COMPRESS_PADDING = 15;
|
||||||
const int REASONABLE_NUMBER_OF_PACKING_ATTEMPTS = 5;
|
const int REASONABLE_NUMBER_OF_PACKING_ATTEMPTS = 5;
|
||||||
|
|
||||||
const int PACKET_IS_COLOR_BIT = 0;
|
const int PACKET_IS_COLOR_BIT = 0;
|
||||||
|
@ -69,7 +69,7 @@ public:
|
||||||
~OctreePacketData();
|
~OctreePacketData();
|
||||||
|
|
||||||
/// change compression and target size settings
|
/// change compression and target size settings
|
||||||
void changeSettings(bool enableCompression = false, int targetSize = MAX_OCTREE_PACKET_DATA_SIZE);
|
void changeSettings(bool enableCompression = false, unsigned int targetSize = MAX_OCTREE_PACKET_DATA_SIZE);
|
||||||
|
|
||||||
/// reset completely, all data is discarded
|
/// reset completely, all data is discarded
|
||||||
void reset();
|
void reset();
|
||||||
|
@ -168,7 +168,7 @@ public:
|
||||||
bool isCompressed() const { return _enableCompression; }
|
bool isCompressed() const { return _enableCompression; }
|
||||||
|
|
||||||
/// returns the target uncompressed size
|
/// returns the target uncompressed size
|
||||||
int getTargetSize() const { return _targetSize; }
|
unsigned int getTargetSize() const { return _targetSize; }
|
||||||
|
|
||||||
/// displays contents for debugging
|
/// displays contents for debugging
|
||||||
void debugContent();
|
void debugContent();
|
||||||
|
@ -186,7 +186,7 @@ private:
|
||||||
/// append a single byte, might fail if byte would cause packet to be too large
|
/// append a single byte, might fail if byte would cause packet to be too large
|
||||||
bool append(unsigned char byte);
|
bool append(unsigned char byte);
|
||||||
|
|
||||||
int _targetSize;
|
unsigned int _targetSize;
|
||||||
bool _enableCompression;
|
bool _enableCompression;
|
||||||
|
|
||||||
unsigned char _uncompressed[MAX_OCTREE_UNCOMRESSED_PACKET_SIZE];
|
unsigned char _uncompressed[MAX_OCTREE_UNCOMRESSED_PACKET_SIZE];
|
||||||
|
|
|
@ -57,9 +57,9 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar
|
||||||
bool showTimingDetails = false; // Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
bool showTimingDetails = false; // Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||||
PerformanceWarning warn(showTimingDetails, "OctreeRenderer::processDatagram()",showTimingDetails);
|
PerformanceWarning warn(showTimingDetails, "OctreeRenderer::processDatagram()",showTimingDetails);
|
||||||
|
|
||||||
int packetLength = dataByteArray.size();
|
unsigned int packetLength = dataByteArray.size();
|
||||||
PacketType command = packetTypeForPacket(dataByteArray);
|
PacketType command = packetTypeForPacket(dataByteArray);
|
||||||
int numBytesPacketHeader = numBytesForPacketHeader(dataByteArray);
|
unsigned int numBytesPacketHeader = numBytesForPacketHeader(dataByteArray);
|
||||||
QUuid sourceUUID = uuidFromPacketHeader(dataByteArray);
|
QUuid sourceUUID = uuidFromPacketHeader(dataByteArray);
|
||||||
PacketType expectedType = getExpectedPacketType();
|
PacketType expectedType = getExpectedPacketType();
|
||||||
|
|
||||||
|
@ -86,11 +86,11 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar
|
||||||
int flightTime = arrivedAt - sentAt + clockSkew;
|
int flightTime = arrivedAt - sentAt + clockSkew;
|
||||||
|
|
||||||
OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0;
|
OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0;
|
||||||
int dataBytes = packetLength - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE);
|
unsigned int dataBytes = packetLength - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE);
|
||||||
|
|
||||||
if (extraDebugging) {
|
if (extraDebugging) {
|
||||||
qDebug("OctreeRenderer::processDatagram() ... Got Packet Section"
|
qDebug("OctreeRenderer::processDatagram() ... Got Packet Section"
|
||||||
" color:%s compressed:%s sequence: %u flight:%d usec size:%d data:%d",
|
" color:%s compressed:%s sequence: %u flight:%d usec size:%u data:%u",
|
||||||
debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed),
|
debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed),
|
||||||
sequence, flightTime, packetLength, dataBytes);
|
sequence, flightTime, packetLength, dataBytes);
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar
|
||||||
packetData.loadFinalizedContent(dataAt, sectionLength);
|
packetData.loadFinalizedContent(dataAt, sectionLength);
|
||||||
if (extraDebugging) {
|
if (extraDebugging) {
|
||||||
qDebug("OctreeRenderer::processDatagram() ... Got Packet Section"
|
qDebug("OctreeRenderer::processDatagram() ... Got Packet Section"
|
||||||
" color:%s compressed:%s sequence: %u flight:%d usec size:%d data:%d"
|
" color:%s compressed:%s sequence: %u flight:%d usec size:%u data:%u"
|
||||||
" subsection:%d sectionLength:%d uncompressed:%d",
|
" subsection:%d sectionLength:%d uncompressed:%d",
|
||||||
debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed),
|
debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed),
|
||||||
sequence, flightTime, packetLength, dataBytes, subsection, sectionLength,
|
sequence, flightTime, packetLength, dataBytes, subsection, sectionLength,
|
||||||
|
|
|
@ -919,13 +919,13 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet,
|
||||||
if (wantExtraDebugging) {
|
if (wantExtraDebugging) {
|
||||||
qDebug() << "too many _missingSequenceNumbers:" << _missingSequenceNumbers.size();
|
qDebug() << "too many _missingSequenceNumbers:" << _missingSequenceNumbers.size();
|
||||||
}
|
}
|
||||||
foreach(unsigned int missingItem, _missingSequenceNumbers) {
|
foreach(uint16_t missingItem, _missingSequenceNumbers) {
|
||||||
if (wantExtraDebugging) {
|
if (wantExtraDebugging) {
|
||||||
qDebug() << "checking item:" << missingItem << "is it in need of pruning?";
|
qDebug() << "checking item:" << missingItem << "is it in need of pruning?";
|
||||||
qDebug() << "(_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE):"
|
qDebug() << "(_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE):"
|
||||||
<< (_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE);
|
<< (_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE);
|
||||||
}
|
}
|
||||||
if (missingItem <= (unsigned int)std::max(0, (int)_incomingLastSequence - (int)MAX_MISSING_SEQUENCE_OLD_AGE)) {
|
if (missingItem <= std::max(0, _incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE)) {
|
||||||
if (wantExtraDebugging) {
|
if (wantExtraDebugging) {
|
||||||
qDebug() << "pruning really old missing sequence:" << missingItem;
|
qDebug() << "pruning really old missing sequence:" << missingItem;
|
||||||
}
|
}
|
||||||
|
|
|
@ -269,7 +269,7 @@ private:
|
||||||
unsigned int _incomingLate; /// out of order later than expected
|
unsigned int _incomingLate; /// out of order later than expected
|
||||||
unsigned int _incomingReallyLate; /// out of order and later than MAX_MISSING_SEQUENCE_OLD_AGE late
|
unsigned int _incomingReallyLate; /// out of order and later than MAX_MISSING_SEQUENCE_OLD_AGE late
|
||||||
unsigned int _incomingPossibleDuplicate; /// out of order possibly a duplicate
|
unsigned int _incomingPossibleDuplicate; /// out of order possibly a duplicate
|
||||||
QSet<unsigned int> _missingSequenceNumbers;
|
QSet<uint16_t> _missingSequenceNumbers;
|
||||||
SimpleMovingAverage _incomingFlightTimeAverage;
|
SimpleMovingAverage _incomingFlightTimeAverage;
|
||||||
|
|
||||||
// features related items
|
// features related items
|
||||||
|
|
|
@ -348,7 +348,7 @@ void NodeList::addSetOfNodeTypesToNodeInterestSet(const NodeSet& setOfNodeTypes)
|
||||||
|
|
||||||
const uint32_t RFC_5389_MAGIC_COOKIE = 0x2112A442;
|
const uint32_t RFC_5389_MAGIC_COOKIE = 0x2112A442;
|
||||||
const int NUM_BYTES_STUN_HEADER = 20;
|
const int NUM_BYTES_STUN_HEADER = 20;
|
||||||
const int NUM_STUN_REQUESTS_BEFORE_FALLBACK = 5;
|
const unsigned int NUM_STUN_REQUESTS_BEFORE_FALLBACK = 5;
|
||||||
|
|
||||||
void NodeList::sendSTUNRequest() {
|
void NodeList::sendSTUNRequest() {
|
||||||
const char STUN_SERVER_HOSTNAME[] = "stun.highfidelity.io";
|
const char STUN_SERVER_HOSTNAME[] = "stun.highfidelity.io";
|
||||||
|
|
|
@ -313,7 +313,7 @@ bool capsuleCapsule(const CapsuleShape* capsuleA, const CapsuleShape* capsuleB,
|
||||||
|
|
||||||
// Since there are only three comparisons to do we unroll the sort algorithm...
|
// Since there are only three comparisons to do we unroll the sort algorithm...
|
||||||
// and use a fifth slot as temp during swap.
|
// and use a fifth slot as temp during swap.
|
||||||
if (points[4] > points[2]) {
|
if (points[1] > points[2]) {
|
||||||
points[4] = points[1];
|
points[4] = points[1];
|
||||||
points[1] = points[2];
|
points[1] = points[2];
|
||||||
points[2] = points[4];
|
points[2] = points[4];
|
||||||
|
|
|
@ -631,8 +631,7 @@ void debug::setDeadBeef(void* memoryVoid, int size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void debug::checkDeadBeef(void* memoryVoid, int size) {
|
void debug::checkDeadBeef(void* memoryVoid, int size) {
|
||||||
unsigned char* memoryAt = (unsigned char*)memoryVoid;
|
assert(memcmp((unsigned char*)memoryVoid, DEADBEEF, std::min(size, DEADBEEF_SIZE)) != 0);
|
||||||
assert(memcmp(memoryAt, DEADBEEF, std::min(size, DEADBEEF_SIZE)) != 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safe version of glm::eulerAngles; uses the factorization method described in David Eberly's
|
// Safe version of glm::eulerAngles; uses the factorization method described in David Eberly's
|
||||||
|
|
|
@ -178,13 +178,14 @@ void VoxelTreeElement::calculateAverageFromChildren() {
|
||||||
bool VoxelTreeElement::collapseChildren() {
|
bool VoxelTreeElement::collapseChildren() {
|
||||||
// scan children, verify that they are ALL present and accounted for
|
// scan children, verify that they are ALL present and accounted for
|
||||||
bool allChildrenMatch = true; // assume the best (ottimista)
|
bool allChildrenMatch = true; // assume the best (ottimista)
|
||||||
int red,green,blue;
|
int red = 0;
|
||||||
|
int green = 0;
|
||||||
|
int blue = 0;
|
||||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||||
VoxelTreeElement* childAt = getChildAtIndex(i);
|
VoxelTreeElement* childAt = getChildAtIndex(i);
|
||||||
// if no child, child isn't a leaf, or child doesn't have a color
|
// if no child, child isn't a leaf, or child doesn't have a color
|
||||||
if (!childAt || !childAt->isLeaf() || !childAt->isColored()) {
|
if (!childAt || !childAt->isLeaf() || !childAt->isColored()) {
|
||||||
allChildrenMatch=false;
|
allChildrenMatch = false;
|
||||||
//qDebug("SADNESS child missing or not colored! i=%d\n",i);
|
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
if (i==0) {
|
if (i==0) {
|
||||||
|
|
Loading…
Reference in a new issue