mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 12:17:45 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into metavoxels
This commit is contained in:
commit
2decfb9561
19 changed files with 306 additions and 238 deletions
|
@ -33,7 +33,10 @@
|
||||||
#include <glm/gtx/vector_angle.hpp>
|
#include <glm/gtx/vector_angle.hpp>
|
||||||
|
|
||||||
#include <QtCore/QCoreApplication>
|
#include <QtCore/QCoreApplication>
|
||||||
|
#include <QtCore/QJsonArray>
|
||||||
|
#include <QtCore/QJsonDocument>
|
||||||
#include <QtCore/QJsonObject>
|
#include <QtCore/QJsonObject>
|
||||||
|
#include <QtCore/QJsonValue>
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
|
|
||||||
#include <Logging.h>
|
#include <Logging.h>
|
||||||
|
@ -71,11 +74,18 @@ AudioMixer::AudioMixer(const QByteArray& packet) :
|
||||||
_performanceThrottlingRatio(0.0f),
|
_performanceThrottlingRatio(0.0f),
|
||||||
_numStatFrames(0),
|
_numStatFrames(0),
|
||||||
_sumListeners(0),
|
_sumListeners(0),
|
||||||
_sumMixes(0)
|
_sumMixes(0),
|
||||||
|
_sourceUnattenuatedZone(NULL),
|
||||||
|
_listenerUnattenuatedZone(NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AudioMixer::~AudioMixer() {
|
||||||
|
delete _sourceUnattenuatedZone;
|
||||||
|
delete _listenerUnattenuatedZone;
|
||||||
|
}
|
||||||
|
|
||||||
void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuffer* bufferToAdd,
|
void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuffer* bufferToAdd,
|
||||||
AvatarAudioRingBuffer* listeningNodeBuffer) {
|
AvatarAudioRingBuffer* listeningNodeBuffer) {
|
||||||
float bearingRelativeAngleToSource = 0.0f;
|
float bearingRelativeAngleToSource = 0.0f;
|
||||||
|
@ -83,7 +93,9 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
|
||||||
int numSamplesDelay = 0;
|
int numSamplesDelay = 0;
|
||||||
float weakChannelAmplitudeRatio = 1.0f;
|
float weakChannelAmplitudeRatio = 1.0f;
|
||||||
|
|
||||||
if (bufferToAdd != listeningNodeBuffer) {
|
bool shouldAttenuate = (bufferToAdd != listeningNodeBuffer);
|
||||||
|
|
||||||
|
if (shouldAttenuate) {
|
||||||
// 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 relativePosition = bufferToAdd->getPosition() - listeningNodeBuffer->getPosition();
|
glm::vec3 relativePosition = bufferToAdd->getPosition() - listeningNodeBuffer->getPosition();
|
||||||
|
|
||||||
|
@ -101,82 +113,88 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
|
||||||
|
|
||||||
++_sumMixes;
|
++_sumMixes;
|
||||||
|
|
||||||
glm::quat inverseOrientation = glm::inverse(listeningNodeBuffer->getOrientation());
|
if (bufferToAdd->getListenerUnattenuatedZone()) {
|
||||||
|
shouldAttenuate = !bufferToAdd->getListenerUnattenuatedZone()->contains(listeningNodeBuffer->getPosition());
|
||||||
float distanceSquareToSource = glm::dot(relativePosition, relativePosition);
|
|
||||||
float radius = 0.0f;
|
|
||||||
|
|
||||||
if (bufferToAdd->getType() == PositionalAudioRingBuffer::Injector) {
|
|
||||||
InjectedAudioRingBuffer* injectedBuffer = (InjectedAudioRingBuffer*) bufferToAdd;
|
|
||||||
radius = injectedBuffer->getRadius();
|
|
||||||
attenuationCoefficient *= injectedBuffer->getAttenuationRatio();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (radius == 0 || (distanceSquareToSource > radius * radius)) {
|
if (shouldAttenuate) {
|
||||||
// this is either not a spherical source, or the listener is outside the sphere
|
glm::quat inverseOrientation = glm::inverse(listeningNodeBuffer->getOrientation());
|
||||||
|
|
||||||
if (radius > 0) {
|
float distanceSquareToSource = glm::dot(relativePosition, relativePosition);
|
||||||
// this is a spherical source - the distance used for the coefficient
|
float radius = 0.0f;
|
||||||
// needs to be the closest point on the boundary to the source
|
|
||||||
|
if (bufferToAdd->getType() == PositionalAudioRingBuffer::Injector) {
|
||||||
// ovveride the distance to the node with the distance to the point on the
|
InjectedAudioRingBuffer* injectedBuffer = (InjectedAudioRingBuffer*) bufferToAdd;
|
||||||
// boundary of the sphere
|
radius = injectedBuffer->getRadius();
|
||||||
distanceSquareToSource -= (radius * radius);
|
attenuationCoefficient *= injectedBuffer->getAttenuationRatio();
|
||||||
|
}
|
||||||
} else {
|
|
||||||
// calculate the angle delivery for off-axis attenuation
|
if (radius == 0 || (distanceSquareToSource > radius * radius)) {
|
||||||
glm::vec3 rotatedListenerPosition = glm::inverse(bufferToAdd->getOrientation()) * relativePosition;
|
// this is either not a spherical source, or the listener is outside the sphere
|
||||||
|
|
||||||
float angleOfDelivery = glm::angle(glm::vec3(0.0f, 0.0f, -1.0f),
|
if (radius > 0) {
|
||||||
glm::normalize(rotatedListenerPosition));
|
// this is a spherical source - the distance used for the coefficient
|
||||||
|
// needs to be the closest point on the boundary to the source
|
||||||
const float MAX_OFF_AXIS_ATTENUATION = 0.2f;
|
|
||||||
const float OFF_AXIS_ATTENUATION_FORMULA_STEP = (1 - MAX_OFF_AXIS_ATTENUATION) / 2.0f;
|
// ovveride the distance to the node with the distance to the point on the
|
||||||
|
// boundary of the sphere
|
||||||
float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION +
|
distanceSquareToSource -= (radius * radius);
|
||||||
(OFF_AXIS_ATTENUATION_FORMULA_STEP * (angleOfDelivery / PI_OVER_TWO));
|
|
||||||
|
} else {
|
||||||
// multiply the current attenuation coefficient by the calculated off axis coefficient
|
// calculate the angle delivery for off-axis attenuation
|
||||||
attenuationCoefficient *= offAxisCoefficient;
|
glm::vec3 rotatedListenerPosition = glm::inverse(bufferToAdd->getOrientation()) * relativePosition;
|
||||||
|
|
||||||
|
float angleOfDelivery = glm::angle(glm::vec3(0.0f, 0.0f, -1.0f),
|
||||||
|
glm::normalize(rotatedListenerPosition));
|
||||||
|
|
||||||
|
const float MAX_OFF_AXIS_ATTENUATION = 0.2f;
|
||||||
|
const float OFF_AXIS_ATTENUATION_FORMULA_STEP = (1 - MAX_OFF_AXIS_ATTENUATION) / 2.0f;
|
||||||
|
|
||||||
|
float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION +
|
||||||
|
(OFF_AXIS_ATTENUATION_FORMULA_STEP * (angleOfDelivery / PI_OVER_TWO));
|
||||||
|
|
||||||
|
// multiply the current attenuation coefficient by the calculated off axis coefficient
|
||||||
|
attenuationCoefficient *= offAxisCoefficient;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 rotatedSourcePosition = inverseOrientation * relativePosition;
|
||||||
|
|
||||||
|
const float DISTANCE_SCALE = 2.5f;
|
||||||
|
const float GEOMETRIC_AMPLITUDE_SCALAR = 0.3f;
|
||||||
|
const float DISTANCE_LOG_BASE = 2.5f;
|
||||||
|
const float DISTANCE_SCALE_LOG = logf(DISTANCE_SCALE) / logf(DISTANCE_LOG_BASE);
|
||||||
|
|
||||||
|
// calculate the distance coefficient using the distance to this node
|
||||||
|
float distanceCoefficient = powf(GEOMETRIC_AMPLITUDE_SCALAR,
|
||||||
|
DISTANCE_SCALE_LOG +
|
||||||
|
(0.5f * logf(distanceSquareToSource) / logf(DISTANCE_LOG_BASE)) - 1);
|
||||||
|
distanceCoefficient = std::min(1.0f, distanceCoefficient);
|
||||||
|
|
||||||
|
// multiply the current attenuation coefficient by the distance coefficient
|
||||||
|
attenuationCoefficient *= distanceCoefficient;
|
||||||
|
|
||||||
|
// project the rotated source position vector onto the XZ plane
|
||||||
|
rotatedSourcePosition.y = 0.0f;
|
||||||
|
|
||||||
|
// produce an oriented angle about the y-axis
|
||||||
|
bearingRelativeAngleToSource = glm::orientedAngle(glm::vec3(0.0f, 0.0f, -1.0f),
|
||||||
|
glm::normalize(rotatedSourcePosition),
|
||||||
|
glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
|
|
||||||
|
const float PHASE_AMPLITUDE_RATIO_AT_90 = 0.5;
|
||||||
|
|
||||||
|
// figure out the number of samples of delay and the ratio of the amplitude
|
||||||
|
// in the weak channel for audio spatialization
|
||||||
|
float sinRatio = fabsf(sinf(bearingRelativeAngleToSource));
|
||||||
|
numSamplesDelay = SAMPLE_PHASE_DELAY_AT_90 * sinRatio;
|
||||||
|
weakChannelAmplitudeRatio = 1 - (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio);
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 rotatedSourcePosition = inverseOrientation * relativePosition;
|
|
||||||
|
|
||||||
const float DISTANCE_SCALE = 2.5f;
|
|
||||||
const float GEOMETRIC_AMPLITUDE_SCALAR = 0.3f;
|
|
||||||
const float DISTANCE_LOG_BASE = 2.5f;
|
|
||||||
const float DISTANCE_SCALE_LOG = logf(DISTANCE_SCALE) / logf(DISTANCE_LOG_BASE);
|
|
||||||
|
|
||||||
// calculate the distance coefficient using the distance to this node
|
|
||||||
float distanceCoefficient = powf(GEOMETRIC_AMPLITUDE_SCALAR,
|
|
||||||
DISTANCE_SCALE_LOG +
|
|
||||||
(0.5f * logf(distanceSquareToSource) / logf(DISTANCE_LOG_BASE)) - 1);
|
|
||||||
distanceCoefficient = std::min(1.0f, distanceCoefficient);
|
|
||||||
|
|
||||||
// multiply the current attenuation coefficient by the distance coefficient
|
|
||||||
attenuationCoefficient *= distanceCoefficient;
|
|
||||||
|
|
||||||
// project the rotated source position vector onto the XZ plane
|
|
||||||
rotatedSourcePosition.y = 0.0f;
|
|
||||||
|
|
||||||
// produce an oriented angle about the y-axis
|
|
||||||
bearingRelativeAngleToSource = glm::orientedAngle(glm::vec3(0.0f, 0.0f, -1.0f),
|
|
||||||
glm::normalize(rotatedSourcePosition),
|
|
||||||
glm::vec3(0.0f, 1.0f, 0.0f));
|
|
||||||
|
|
||||||
const float PHASE_AMPLITUDE_RATIO_AT_90 = 0.5;
|
|
||||||
|
|
||||||
// figure out the number of samples of delay and the ratio of the amplitude
|
|
||||||
// in the weak channel for audio spatialization
|
|
||||||
float sinRatio = fabsf(sinf(bearingRelativeAngleToSource));
|
|
||||||
numSamplesDelay = SAMPLE_PHASE_DELAY_AT_90 * sinRatio;
|
|
||||||
weakChannelAmplitudeRatio = 1 - (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const int16_t* nextOutputStart = bufferToAdd->getNextOutput();
|
const int16_t* nextOutputStart = bufferToAdd->getNextOutput();
|
||||||
|
|
||||||
if (!bufferToAdd->isStereo()) {
|
if (!bufferToAdd->isStereo() && shouldAttenuate) {
|
||||||
// this is a mono buffer, which means it gets full attenuation and spatialization
|
// this is a mono buffer, which means it gets full attenuation and spatialization
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -285,7 +303,8 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
|
||||||
} else if (i + 1 < numSamplesDelay) {
|
} else if (i + 1 < numSamplesDelay) {
|
||||||
// MMX add two delayed samples
|
// MMX add two delayed samples
|
||||||
__m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset],
|
__m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset],
|
||||||
_clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset], 0, 0);
|
_clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset],
|
||||||
|
0, 0);
|
||||||
__m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio,
|
__m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio,
|
||||||
delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio, 0, 0);
|
delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio, 0, 0);
|
||||||
|
|
||||||
|
@ -307,16 +326,29 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// stereo buffer - do attenuation but no sample delay for spatialization
|
// this is a stereo buffer or an unattenuated buffer, don't perform spatialization
|
||||||
for (int s = 0; s < NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; s += 4) {
|
for (int s = 0; s < NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; s += 4) {
|
||||||
// use MMX to clamp four additions at a time
|
|
||||||
_clientSamples[s] = glm::clamp(_clientSamples[s] + (int) (nextOutputStart[s] * attenuationCoefficient),
|
int stereoDivider = bufferToAdd->isStereo() ? 1 : 2;
|
||||||
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
|
||||||
_clientSamples[s + 1] = glm::clamp(_clientSamples[s + 1] + (int) (nextOutputStart[s + 1] * attenuationCoefficient),
|
if (!shouldAttenuate) {
|
||||||
|
attenuationCoefficient = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
_clientSamples[s] = glm::clamp(_clientSamples[s]
|
||||||
|
+ (int) (nextOutputStart[(s / stereoDivider)] * attenuationCoefficient),
|
||||||
|
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
||||||
|
_clientSamples[s + 1] = glm::clamp(_clientSamples[s + 1]
|
||||||
|
+ (int) (nextOutputStart[(s / stereoDivider) + (1 / stereoDivider)]
|
||||||
|
* attenuationCoefficient),
|
||||||
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
||||||
_clientSamples[s + 2] = glm::clamp(_clientSamples[s + 2] + (int) (nextOutputStart[s + 2] * attenuationCoefficient),
|
_clientSamples[s + 2] = glm::clamp(_clientSamples[s + 2]
|
||||||
|
+ (int) (nextOutputStart[(s / stereoDivider) + (2 / stereoDivider)]
|
||||||
|
* attenuationCoefficient),
|
||||||
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
||||||
_clientSamples[s + 3] = glm::clamp(_clientSamples[s + 3] + (int) (nextOutputStart[s + 3] * attenuationCoefficient),
|
_clientSamples[s + 3] = glm::clamp(_clientSamples[s + 3]
|
||||||
|
+ (int) (nextOutputStart[(s / stereoDivider) + (3 / stereoDivider)]
|
||||||
|
* attenuationCoefficient),
|
||||||
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,6 +444,32 @@ void AudioMixer::run() {
|
||||||
nodeList->addNodeTypeToInterestSet(NodeType::Agent);
|
nodeList->addNodeTypeToInterestSet(NodeType::Agent);
|
||||||
|
|
||||||
nodeList->linkedDataCreateCallback = attachNewBufferToNode;
|
nodeList->linkedDataCreateCallback = attachNewBufferToNode;
|
||||||
|
|
||||||
|
// check the payload to see if we have any unattenuated zones
|
||||||
|
const QString UNATTENUATED_ZONE_REGEX_STRING = "--unattenuated-zone ([\\d.,-]+)";
|
||||||
|
QRegExp unattenuatedZoneMatch(UNATTENUATED_ZONE_REGEX_STRING);
|
||||||
|
|
||||||
|
if (unattenuatedZoneMatch.indexIn(_payload) != -1) {
|
||||||
|
QString unattenuatedZoneString = unattenuatedZoneMatch.cap(1);
|
||||||
|
QStringList zoneStringList = unattenuatedZoneString.split(',');
|
||||||
|
|
||||||
|
glm::vec3 sourceCorner(zoneStringList[0].toFloat(), zoneStringList[1].toFloat(), zoneStringList[2].toFloat());
|
||||||
|
glm::vec3 sourceDimensions(zoneStringList[3].toFloat(), zoneStringList[4].toFloat(), zoneStringList[5].toFloat());
|
||||||
|
|
||||||
|
glm::vec3 listenerCorner(zoneStringList[6].toFloat(), zoneStringList[7].toFloat(), zoneStringList[8].toFloat());
|
||||||
|
glm::vec3 listenerDimensions(zoneStringList[9].toFloat(), zoneStringList[10].toFloat(), zoneStringList[11].toFloat());
|
||||||
|
|
||||||
|
_sourceUnattenuatedZone = new AABox(sourceCorner, sourceDimensions);
|
||||||
|
_listenerUnattenuatedZone = new AABox(listenerCorner, listenerDimensions);
|
||||||
|
|
||||||
|
glm::vec3 sourceCenter = _sourceUnattenuatedZone->calcCenter();
|
||||||
|
glm::vec3 destinationCenter = _listenerUnattenuatedZone->calcCenter();
|
||||||
|
|
||||||
|
qDebug() << "There is an unattenuated zone with source center at"
|
||||||
|
<< QString("%1, %2, %3").arg(sourceCenter.x).arg(sourceCenter.y).arg(sourceCenter.z);
|
||||||
|
qDebug() << "Buffers inside this zone will not be attenuated inside a box with center at"
|
||||||
|
<< QString("%1, %2, %3").arg(destinationCenter.x).arg(destinationCenter.y).arg(destinationCenter.z);
|
||||||
|
}
|
||||||
|
|
||||||
int nextFrame = 0;
|
int nextFrame = 0;
|
||||||
QElapsedTimer timer;
|
QElapsedTimer timer;
|
||||||
|
@ -429,7 +487,9 @@ void AudioMixer::run() {
|
||||||
|
|
||||||
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,
|
||||||
|
_sourceUnattenuatedZone,
|
||||||
|
_listenerUnattenuatedZone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
#ifndef hifi_AudioMixer_h
|
#ifndef hifi_AudioMixer_h
|
||||||
#define hifi_AudioMixer_h
|
#define hifi_AudioMixer_h
|
||||||
|
|
||||||
|
#include <AABox.h>
|
||||||
#include <AudioRingBuffer.h>
|
#include <AudioRingBuffer.h>
|
||||||
|
|
||||||
#include <ThreadedAssignment.h>
|
#include <ThreadedAssignment.h>
|
||||||
|
|
||||||
class PositionalAudioRingBuffer;
|
class PositionalAudioRingBuffer;
|
||||||
|
@ -26,6 +26,7 @@ class AudioMixer : public ThreadedAssignment {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
AudioMixer(const QByteArray& packet);
|
AudioMixer(const QByteArray& packet);
|
||||||
|
~AudioMixer();
|
||||||
public slots:
|
public slots:
|
||||||
/// threaded run of assignment
|
/// threaded run of assignment
|
||||||
void run();
|
void run();
|
||||||
|
@ -51,6 +52,8 @@ private:
|
||||||
int _numStatFrames;
|
int _numStatFrames;
|
||||||
int _sumListeners;
|
int _sumListeners;
|
||||||
int _sumMixes;
|
int _sumMixes;
|
||||||
|
AABox* _sourceUnattenuatedZone;
|
||||||
|
AABox* _listenerUnattenuatedZone;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_AudioMixer_h
|
#endif // hifi_AudioMixer_h
|
||||||
|
|
|
@ -98,7 +98,8 @@ int AudioMixerClientData::parseData(const QByteArray& packet) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioMixerClientData::checkBuffersBeforeFrameSend(int jitterBufferLengthSamples) {
|
void AudioMixerClientData::checkBuffersBeforeFrameSend(int jitterBufferLengthSamples,
|
||||||
|
AABox* checkSourceZone, AABox* listenerZone) {
|
||||||
for (int i = 0; i < _ringBuffers.size(); i++) {
|
for (int i = 0; i < _ringBuffers.size(); i++) {
|
||||||
if (_ringBuffers[i]->shouldBeAddedToMix(jitterBufferLengthSamples)) {
|
if (_ringBuffers[i]->shouldBeAddedToMix(jitterBufferLengthSamples)) {
|
||||||
// this is a ring buffer that is ready to go
|
// this is a ring buffer that is ready to go
|
||||||
|
@ -108,6 +109,12 @@ void AudioMixerClientData::checkBuffersBeforeFrameSend(int jitterBufferLengthSam
|
||||||
// calculate the average loudness for the next NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL
|
// calculate the average loudness for the next NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL
|
||||||
// that would be mixed in
|
// that would be mixed in
|
||||||
_ringBuffers[i]->updateNextOutputTrailingLoudness();
|
_ringBuffers[i]->updateNextOutputTrailingLoudness();
|
||||||
|
|
||||||
|
if (checkSourceZone && checkSourceZone->contains(_ringBuffers[i]->getPosition())) {
|
||||||
|
_ringBuffers[i]->setListenerUnattenuatedZone(listenerZone);
|
||||||
|
} else {
|
||||||
|
_ringBuffers[i]->setListenerUnattenuatedZone(NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,7 @@
|
||||||
#ifndef hifi_AudioMixerClientData_h
|
#ifndef hifi_AudioMixerClientData_h
|
||||||
#define hifi_AudioMixerClientData_h
|
#define hifi_AudioMixerClientData_h
|
||||||
|
|
||||||
#include <vector>
|
#include <AABox.h>
|
||||||
|
|
||||||
#include <NodeData.h>
|
#include <NodeData.h>
|
||||||
#include <PositionalAudioRingBuffer.h>
|
#include <PositionalAudioRingBuffer.h>
|
||||||
|
|
||||||
|
@ -28,7 +27,8 @@ public:
|
||||||
AvatarAudioRingBuffer* getAvatarAudioRingBuffer() const;
|
AvatarAudioRingBuffer* getAvatarAudioRingBuffer() const;
|
||||||
|
|
||||||
int parseData(const QByteArray& packet);
|
int parseData(const QByteArray& packet);
|
||||||
void checkBuffersBeforeFrameSend(int jitterBufferLengthSamples);
|
void checkBuffersBeforeFrameSend(int jitterBufferLengthSamples,
|
||||||
|
AABox* checkSourceZone = NULL, AABox* listenerZone = NULL);
|
||||||
void pushBuffersAfterFrameSend();
|
void pushBuffersAfterFrameSend();
|
||||||
private:
|
private:
|
||||||
QList<PositionalAudioRingBuffer*> _ringBuffers;
|
QList<PositionalAudioRingBuffer*> _ringBuffers;
|
||||||
|
|
|
@ -184,7 +184,8 @@ void OctreeInboundPacketProcessor::trackInboundPacket(const QUuid& nodeUUID, uns
|
||||||
int OctreeInboundPacketProcessor::sendNackPackets() {
|
int OctreeInboundPacketProcessor::sendNackPackets() {
|
||||||
|
|
||||||
int packetsSent = 0;
|
int packetsSent = 0;
|
||||||
|
char packet[MAX_PACKET_SIZE];
|
||||||
|
|
||||||
NodeToSenderStatsMapIterator i = _singleSenderStats.begin();
|
NodeToSenderStatsMapIterator i = _singleSenderStats.begin();
|
||||||
while (i != _singleSenderStats.end()) {
|
while (i != _singleSenderStats.end()) {
|
||||||
|
|
||||||
|
@ -206,15 +207,10 @@ int OctreeInboundPacketProcessor::sendNackPackets() {
|
||||||
|
|
||||||
const SharedNodePointer& destinationNode = NodeList::getInstance()->getNodeHash().value(nodeUUID);
|
const SharedNodePointer& destinationNode = NodeList::getInstance()->getNodeHash().value(nodeUUID);
|
||||||
const QSet<unsigned short int>& missingSequenceNumbers = nodeStats.getMissingSequenceNumbers();
|
const QSet<unsigned short int>& missingSequenceNumbers = nodeStats.getMissingSequenceNumbers();
|
||||||
|
|
||||||
// check if there are any sequence numbers that need to be nacked
|
|
||||||
int numSequenceNumbersAvailable = missingSequenceNumbers.size();
|
|
||||||
|
|
||||||
// construct nack packet(s) for this node
|
// construct nack packet(s) for this node
|
||||||
|
int numSequenceNumbersAvailable = missingSequenceNumbers.size();
|
||||||
QSet<unsigned short int>::const_iterator missingSequenceNumberIterator = missingSequenceNumbers.begin();
|
QSet<unsigned short int>::const_iterator missingSequenceNumberIterator = missingSequenceNumbers.constBegin();
|
||||||
char packet[MAX_PACKET_SIZE];
|
|
||||||
|
|
||||||
while (numSequenceNumbersAvailable > 0) {
|
while (numSequenceNumbersAvailable > 0) {
|
||||||
|
|
||||||
char* dataAt = packet;
|
char* dataAt = packet;
|
||||||
|
@ -243,8 +239,7 @@ int OctreeInboundPacketProcessor::sendNackPackets() {
|
||||||
numSequenceNumbersAvailable -= numSequenceNumbers;
|
numSequenceNumbersAvailable -= numSequenceNumbers;
|
||||||
|
|
||||||
// send it
|
// send it
|
||||||
qint64 bytesWritten = NodeList::getInstance()->writeUnverifiedDatagram(packet, dataAt - packet, destinationNode);
|
NodeList::getInstance()->writeUnverifiedDatagram(packet, dataAt - packet, destinationNode);
|
||||||
|
|
||||||
packetsSent++;
|
packetsSent++;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
|
|
|
@ -851,7 +851,6 @@ void OctreeServer::readPendingDatagrams() {
|
||||||
// If we got a nack packet, then we're talking to an agent, and we
|
// If we got a nack packet, then we're talking to an agent, and we
|
||||||
// need to make sure we have it in our nodeList.
|
// need to make sure we have it in our nodeList.
|
||||||
if (matchingNode) {
|
if (matchingNode) {
|
||||||
nodeList->updateNodeWithDataFromPacket(matchingNode, receivedPacket);
|
|
||||||
OctreeQueryNode* nodeData = (OctreeQueryNode*)matchingNode->getLinkedData();
|
OctreeQueryNode* nodeData = (OctreeQueryNode*)matchingNode->getLinkedData();
|
||||||
if (nodeData) {
|
if (nodeData) {
|
||||||
nodeData->parseNackPacket(receivedPacket);
|
nodeData->parseNackPacket(receivedPacket);
|
||||||
|
|
|
@ -974,17 +974,27 @@ function mouseMoveEvent(event) {
|
||||||
|
|
||||||
var pixelPerDegrees = windowDimensions.y / (1 * 360); // the entire height of the window allow you to make 2 full rotations
|
var pixelPerDegrees = windowDimensions.y / (1 * 360); // the entire height of the window allow you to make 2 full rotations
|
||||||
|
|
||||||
var STEP = 15;
|
//compute delta in pixel
|
||||||
var delta = Math.floor((event.x - mouseLastPosition.x) / pixelPerDegrees);
|
var cameraForward = Quat.getFront(Camera.getOrientation());
|
||||||
|
var rotationAxis = (!zIsPressed && xIsPressed) ? { x: 1, y: 0, z: 0 } :
|
||||||
|
(!zIsPressed && !xIsPressed) ? { x: 0, y: 1, z: 0 } :
|
||||||
|
{ x: 0, y: 0, z: 1 };
|
||||||
|
rotationAxis = Vec3.multiplyQbyV(selectedModelProperties.modelRotation, rotationAxis);
|
||||||
|
var orthogonalAxis = Vec3.cross(cameraForward, rotationAxis);
|
||||||
|
var mouseDelta = { x: event.x - mouseLastPosition
|
||||||
|
.x, y: mouseLastPosition.y - event.y, z: 0 };
|
||||||
|
var transformedMouseDelta = Vec3.multiplyQbyV(Camera.getOrientation(), mouseDelta);
|
||||||
|
var delta = Math.floor(Vec3.dot(transformedMouseDelta, Vec3.normalize(orthogonalAxis)) / pixelPerDegrees);
|
||||||
|
|
||||||
|
var STEP = 15;
|
||||||
if (!event.isShifted) {
|
if (!event.isShifted) {
|
||||||
delta = Math.floor(delta / STEP) * STEP;
|
delta = Math.round(delta / STEP) * STEP;
|
||||||
}
|
}
|
||||||
|
|
||||||
var rotation = Quat.fromVec3Degrees({
|
var rotation = Quat.fromVec3Degrees({
|
||||||
x: (!zIsPressed && xIsPressed) ? delta : 0, // z is pressed
|
x: (!zIsPressed && xIsPressed) ? delta : 0, // x is pressed
|
||||||
y: (!zIsPressed && !xIsPressed) ? delta : 0, // x is pressed
|
y: (!zIsPressed && !xIsPressed) ? delta : 0, // neither is pressed
|
||||||
z: (zIsPressed && !xIsPressed) ? delta : 0 // neither is pressed
|
z: (zIsPressed && !xIsPressed) ? delta : 0 // z is pressed
|
||||||
});
|
});
|
||||||
rotation = Quat.multiply(selectedModelProperties.oldRotation, rotation);
|
rotation = Quat.multiply(selectedModelProperties.oldRotation, rotation);
|
||||||
|
|
||||||
|
|
|
@ -2123,19 +2123,19 @@ void Application::updateMyAvatar(float deltaTime) {
|
||||||
const quint64 TOO_LONG_SINCE_LAST_NACK = 1 * USECS_PER_SECOND;
|
const quint64 TOO_LONG_SINCE_LAST_NACK = 1 * USECS_PER_SECOND;
|
||||||
if (sinceLastNack > TOO_LONG_SINCE_LAST_NACK) {
|
if (sinceLastNack > TOO_LONG_SINCE_LAST_NACK) {
|
||||||
_lastNackTime = now;
|
_lastNackTime = now;
|
||||||
sendNack();
|
sendNackPackets();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::sendNack() {
|
int Application::sendNackPackets() {
|
||||||
|
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::DisableNackPackets)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::DisableNackPackets)) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int packetsSent = 0;
|
||||||
char packet[MAX_PACKET_SIZE];
|
char packet[MAX_PACKET_SIZE];
|
||||||
NodeList* nodeList = NodeList::getInstance();
|
|
||||||
|
|
||||||
// iterates thru all nodes in NodeList
|
// iterates thru all nodes in NodeList
|
||||||
foreach(const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
|
foreach(const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
|
||||||
|
@ -2146,14 +2146,14 @@ void Application::sendNack() {
|
||||||
|| node->getType() == NodeType::ModelServer)
|
|| node->getType() == NodeType::ModelServer)
|
||||||
) {
|
) {
|
||||||
|
|
||||||
// if there are octree packets from this node that are waiting to be processed,
|
|
||||||
// don't send a NACK since the missing packets may be among those waiting packets.
|
|
||||||
if (_octreeProcessor.hasPacketsToProcessFrom(node)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
QUuid nodeUUID = node->getUUID();
|
QUuid nodeUUID = node->getUUID();
|
||||||
|
|
||||||
|
// if there are octree packets from this node that are waiting to be processed,
|
||||||
|
// don't send a NACK since the missing packets may be among those waiting packets.
|
||||||
|
if (_octreeProcessor.hasPacketsToProcessFrom(nodeUUID)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
_octreeSceneStatsLock.lockForRead();
|
_octreeSceneStatsLock.lockForRead();
|
||||||
|
|
||||||
// retreive octree scene stats of this node
|
// retreive octree scene stats of this node
|
||||||
|
@ -2163,40 +2163,48 @@ void Application::sendNack() {
|
||||||
}
|
}
|
||||||
OctreeSceneStats& stats = _octreeServerSceneStats[nodeUUID];
|
OctreeSceneStats& stats = _octreeServerSceneStats[nodeUUID];
|
||||||
|
|
||||||
// check if there are any sequence numbers that need to be nacked
|
// make copy of missing sequence numbers from stats
|
||||||
int numSequenceNumbersAvailable = stats.getNumSequenceNumbersToNack();
|
const QSet<OCTREE_PACKET_SEQUENCE> missingSequenceNumbers = stats.getMissingSequenceNumbers();
|
||||||
if (numSequenceNumbersAvailable == 0) {
|
|
||||||
_octreeSceneStatsLock.unlock();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* dataAt = packet;
|
|
||||||
int bytesRemaining = MAX_PACKET_SIZE;
|
|
||||||
|
|
||||||
// pack header
|
|
||||||
int numBytesPacketHeader = populatePacketHeader(packet, PacketTypeOctreeDataNack);
|
|
||||||
dataAt += numBytesPacketHeader;
|
|
||||||
bytesRemaining -= numBytesPacketHeader;
|
|
||||||
int numSequenceNumbersRoomFor = (bytesRemaining - sizeof(uint16_t)) / sizeof(OCTREE_PACKET_SEQUENCE);
|
|
||||||
|
|
||||||
// calculate and pack the number of sequence numbers
|
|
||||||
uint16_t numSequenceNumbers = min(numSequenceNumbersAvailable, numSequenceNumbersRoomFor);
|
|
||||||
uint16_t* numSequenceNumbersAt = (uint16_t*)dataAt;
|
|
||||||
*numSequenceNumbersAt = numSequenceNumbers;
|
|
||||||
dataAt += sizeof(uint16_t);
|
|
||||||
|
|
||||||
// pack sequence numbers
|
|
||||||
for (int i = 0; i < numSequenceNumbers; i++) {
|
|
||||||
OCTREE_PACKET_SEQUENCE* sequenceNumberAt = (OCTREE_PACKET_SEQUENCE*)dataAt;
|
|
||||||
*sequenceNumberAt = stats.getNextSequenceNumberToNack();
|
|
||||||
dataAt += sizeof(OCTREE_PACKET_SEQUENCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
_octreeSceneStatsLock.unlock();
|
_octreeSceneStatsLock.unlock();
|
||||||
|
|
||||||
nodeList->writeUnverifiedDatagram(packet, dataAt - packet, node);
|
// construct nack packet(s) for this node
|
||||||
|
int numSequenceNumbersAvailable = missingSequenceNumbers.size();
|
||||||
|
QSet<OCTREE_PACKET_SEQUENCE>::const_iterator missingSequenceNumbersIterator = missingSequenceNumbers.constBegin();
|
||||||
|
while (numSequenceNumbersAvailable > 0) {
|
||||||
|
|
||||||
|
char* dataAt = packet;
|
||||||
|
int bytesRemaining = MAX_PACKET_SIZE;
|
||||||
|
|
||||||
|
// pack header
|
||||||
|
int numBytesPacketHeader = populatePacketHeader(packet, PacketTypeOctreeDataNack);
|
||||||
|
dataAt += numBytesPacketHeader;
|
||||||
|
bytesRemaining -= numBytesPacketHeader;
|
||||||
|
|
||||||
|
// calculate and pack the number of sequence numbers
|
||||||
|
int numSequenceNumbersRoomFor = (bytesRemaining - sizeof(uint16_t)) / sizeof(OCTREE_PACKET_SEQUENCE);
|
||||||
|
uint16_t numSequenceNumbers = min(numSequenceNumbersAvailable, numSequenceNumbersRoomFor);
|
||||||
|
uint16_t* numSequenceNumbersAt = (uint16_t*)dataAt;
|
||||||
|
*numSequenceNumbersAt = numSequenceNumbers;
|
||||||
|
dataAt += sizeof(uint16_t);
|
||||||
|
|
||||||
|
// pack sequence numbers
|
||||||
|
for (int i = 0; i < numSequenceNumbers; i++) {
|
||||||
|
OCTREE_PACKET_SEQUENCE* sequenceNumberAt = (OCTREE_PACKET_SEQUENCE*)dataAt;
|
||||||
|
*sequenceNumberAt = *missingSequenceNumbersIterator;
|
||||||
|
dataAt += sizeof(OCTREE_PACKET_SEQUENCE);
|
||||||
|
|
||||||
|
missingSequenceNumbersIterator++;
|
||||||
|
}
|
||||||
|
numSequenceNumbersAvailable -= numSequenceNumbers;
|
||||||
|
|
||||||
|
// send it
|
||||||
|
NodeList::getInstance()->writeUnverifiedDatagram(packet, dataAt - packet, node);
|
||||||
|
packetsSent++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return packetsSent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::queryOctree(NodeType_t serverType, PacketType packetType, NodeToJurisdictionMap& jurisdictions) {
|
void Application::queryOctree(NodeType_t serverType, PacketType packetType, NodeToJurisdictionMap& jurisdictions) {
|
||||||
|
|
|
@ -413,7 +413,7 @@ private:
|
||||||
static void attachNewHeadToNode(Node *newNode);
|
static void attachNewHeadToNode(Node *newNode);
|
||||||
static void* networkReceive(void* args); // network receive thread
|
static void* networkReceive(void* args); // network receive thread
|
||||||
|
|
||||||
void sendNack();
|
int sendNackPackets();
|
||||||
|
|
||||||
MainWindow* _window;
|
MainWindow* _window;
|
||||||
GLCanvas* _glWidget; // our GLCanvas has a couple extra features
|
GLCanvas* _glWidget; // our GLCanvas has a couple extra features
|
||||||
|
|
|
@ -28,14 +28,12 @@ PositionalAudioRingBuffer::PositionalAudioRingBuffer(PositionalAudioRingBuffer::
|
||||||
_willBeAddedToMix(false),
|
_willBeAddedToMix(false),
|
||||||
_shouldLoopbackForNode(false),
|
_shouldLoopbackForNode(false),
|
||||||
_shouldOutputStarveDebug(true),
|
_shouldOutputStarveDebug(true),
|
||||||
_isStereo(isStereo)
|
_isStereo(isStereo),
|
||||||
|
_listenerUnattenuatedZone(NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PositionalAudioRingBuffer::~PositionalAudioRingBuffer() {
|
|
||||||
}
|
|
||||||
|
|
||||||
int PositionalAudioRingBuffer::parseData(const QByteArray& packet) {
|
int PositionalAudioRingBuffer::parseData(const QByteArray& packet) {
|
||||||
|
|
||||||
// skip the packet header (includes the source UUID)
|
// skip the packet header (includes the source UUID)
|
||||||
|
|
|
@ -12,9 +12,10 @@
|
||||||
#ifndef hifi_PositionalAudioRingBuffer_h
|
#ifndef hifi_PositionalAudioRingBuffer_h
|
||||||
#define hifi_PositionalAudioRingBuffer_h
|
#define hifi_PositionalAudioRingBuffer_h
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <glm/gtx/quaternion.hpp>
|
#include <glm/gtx/quaternion.hpp>
|
||||||
|
|
||||||
|
#include <AABox.h>
|
||||||
|
|
||||||
#include "AudioRingBuffer.h"
|
#include "AudioRingBuffer.h"
|
||||||
|
|
||||||
class PositionalAudioRingBuffer : public AudioRingBuffer {
|
class PositionalAudioRingBuffer : public AudioRingBuffer {
|
||||||
|
@ -25,7 +26,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
PositionalAudioRingBuffer(PositionalAudioRingBuffer::Type type, bool isStereo = false);
|
PositionalAudioRingBuffer(PositionalAudioRingBuffer::Type type, bool isStereo = false);
|
||||||
~PositionalAudioRingBuffer();
|
|
||||||
|
|
||||||
int parseData(const QByteArray& packet);
|
int parseData(const QByteArray& packet);
|
||||||
int parsePositionalData(const QByteArray& positionalByteArray);
|
int parsePositionalData(const QByteArray& positionalByteArray);
|
||||||
|
@ -47,6 +47,9 @@ public:
|
||||||
const glm::vec3& getPosition() const { return _position; }
|
const glm::vec3& getPosition() const { return _position; }
|
||||||
const glm::quat& getOrientation() const { return _orientation; }
|
const glm::quat& getOrientation() const { return _orientation; }
|
||||||
|
|
||||||
|
AABox* getListenerUnattenuatedZone() const { return _listenerUnattenuatedZone; }
|
||||||
|
void setListenerUnattenuatedZone(AABox* listenerUnattenuatedZone) { _listenerUnattenuatedZone = listenerUnattenuatedZone; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// disallow copying of PositionalAudioRingBuffer objects
|
// disallow copying of PositionalAudioRingBuffer objects
|
||||||
PositionalAudioRingBuffer(const PositionalAudioRingBuffer&);
|
PositionalAudioRingBuffer(const PositionalAudioRingBuffer&);
|
||||||
|
@ -61,6 +64,7 @@ protected:
|
||||||
bool _isStereo;
|
bool _isStereo;
|
||||||
|
|
||||||
float _nextOutputTrailingLoudness;
|
float _nextOutputTrailingLoudness;
|
||||||
|
AABox* _listenerUnattenuatedZone;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_PositionalAudioRingBuffer_h
|
#endif // hifi_PositionalAudioRingBuffer_h
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
//
|
|
||||||
// AABox.h
|
|
||||||
// libraries/octree/src
|
|
||||||
//
|
|
||||||
// Created by Brad Hefta-Gaub on 04/11/13.
|
|
||||||
// Copyright 2013 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards
|
|
||||||
// Simple axis aligned box class.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef hifi_AABox_h
|
|
||||||
#define hifi_AABox_h
|
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
|
|
||||||
#include "BoxBase.h"
|
|
||||||
|
|
||||||
class AACube;
|
|
||||||
|
|
||||||
class AABox {
|
|
||||||
|
|
||||||
public:
|
|
||||||
AABox(const glm::vec3& corner, float size);
|
|
||||||
AABox(const glm::vec3& corner, const glm::vec3& dimensions);
|
|
||||||
AABox();
|
|
||||||
~AABox() {};
|
|
||||||
|
|
||||||
void setBox(const glm::vec3& corner, const glm::vec3& scale);
|
|
||||||
|
|
||||||
void setBox(const glm::vec3& corner, float scale);
|
|
||||||
glm::vec3 getVertexP(const glm::vec3& normal) const;
|
|
||||||
glm::vec3 getVertexN(const glm::vec3& normal) const;
|
|
||||||
void scale(float scale);
|
|
||||||
const glm::vec3& getCorner() const { return _corner; }
|
|
||||||
const glm::vec3& getScale() const { return _scale; }
|
|
||||||
const glm::vec3& getDimensions() const { return _scale; }
|
|
||||||
|
|
||||||
glm::vec3 calcCenter() const;
|
|
||||||
glm::vec3 calcTopFarLeft() const;
|
|
||||||
glm::vec3 getVertex(BoxVertex vertex) const;
|
|
||||||
bool contains(const glm::vec3& point) const;
|
|
||||||
bool contains(const AABox& otherBox) const;
|
|
||||||
bool touches(const AABox& otherBox) const;
|
|
||||||
|
|
||||||
bool contains(const AACube& otherCube) const;
|
|
||||||
bool touches(const AACube& otherCube) const;
|
|
||||||
|
|
||||||
bool expandedContains(const glm::vec3& point, float expansion) const;
|
|
||||||
bool expandedIntersectsSegment(const glm::vec3& start, const glm::vec3& end, float expansion) const;
|
|
||||||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const;
|
|
||||||
bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const;
|
|
||||||
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
glm::vec3 getClosestPointOnFace(const glm::vec3& point, BoxFace face) const;
|
|
||||||
glm::vec3 getClosestPointOnFace(const glm::vec4& origin, const glm::vec4& direction, BoxFace face) const;
|
|
||||||
glm::vec4 getPlane(BoxFace face) const;
|
|
||||||
|
|
||||||
static BoxFace getOppositeFace(BoxFace face);
|
|
||||||
|
|
||||||
glm::vec3 _corner;
|
|
||||||
glm::vec3 _scale;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // hifi_AABox_h
|
|
|
@ -47,7 +47,6 @@ OctreeSceneStats::OctreeSceneStats() :
|
||||||
_incomingReallyLate(0),
|
_incomingReallyLate(0),
|
||||||
_incomingPossibleDuplicate(0),
|
_incomingPossibleDuplicate(0),
|
||||||
_missingSequenceNumbers(),
|
_missingSequenceNumbers(),
|
||||||
_sequenceNumbersToNack(),
|
|
||||||
_incomingFlightTimeAverage(samples),
|
_incomingFlightTimeAverage(samples),
|
||||||
_jurisdictionRoot(NULL)
|
_jurisdictionRoot(NULL)
|
||||||
{
|
{
|
||||||
|
@ -160,7 +159,6 @@ void OctreeSceneStats::copyFromOther(const OctreeSceneStats& other) {
|
||||||
_incomingPossibleDuplicate = other._incomingPossibleDuplicate;
|
_incomingPossibleDuplicate = other._incomingPossibleDuplicate;
|
||||||
|
|
||||||
_missingSequenceNumbers = other._missingSequenceNumbers;
|
_missingSequenceNumbers = other._missingSequenceNumbers;
|
||||||
_sequenceNumbersToNack = other._sequenceNumbersToNack;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -946,7 +944,6 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet,
|
||||||
qDebug() << "found it in _missingSequenceNumbers";
|
qDebug() << "found it in _missingSequenceNumbers";
|
||||||
}
|
}
|
||||||
_missingSequenceNumbers.remove(sequence);
|
_missingSequenceNumbers.remove(sequence);
|
||||||
_sequenceNumbersToNack.remove(sequence);
|
|
||||||
_incomingLikelyLost--;
|
_incomingLikelyLost--;
|
||||||
_incomingRecovered++;
|
_incomingRecovered++;
|
||||||
}
|
}
|
||||||
|
@ -986,7 +983,6 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet,
|
||||||
for (int missingSequenceInt = expectedInt; missingSequenceInt < sequenceInt; missingSequenceInt++) {
|
for (int missingSequenceInt = expectedInt; missingSequenceInt < sequenceInt; missingSequenceInt++) {
|
||||||
OCTREE_PACKET_SEQUENCE missingSequence = missingSequenceInt >= 0 ? missingSequenceInt : missingSequenceInt + UINT16_RANGE;
|
OCTREE_PACKET_SEQUENCE missingSequence = missingSequenceInt >= 0 ? missingSequenceInt : missingSequenceInt + UINT16_RANGE;
|
||||||
_missingSequenceNumbers << missingSequence;
|
_missingSequenceNumbers << missingSequence;
|
||||||
_sequenceNumbersToNack << missingSequence;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_incomingLastSequence = sequence;
|
_incomingLastSequence = sequence;
|
||||||
|
@ -1025,7 +1021,6 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet,
|
||||||
qDebug() << "pruning really old missing sequence:" << missingItem;
|
qDebug() << "pruning really old missing sequence:" << missingItem;
|
||||||
}
|
}
|
||||||
_missingSequenceNumbers.remove(missingItem);
|
_missingSequenceNumbers.remove(missingItem);
|
||||||
_sequenceNumbersToNack.remove(missingItem);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1037,14 +1032,3 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet,
|
||||||
_incomingWastedBytes += (MAX_PACKET_SIZE - packet.size());
|
_incomingWastedBytes += (MAX_PACKET_SIZE - packet.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int OctreeSceneStats::getNumSequenceNumbersToNack() const {
|
|
||||||
return _sequenceNumbersToNack.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t OctreeSceneStats::getNextSequenceNumberToNack() {
|
|
||||||
QSet<uint16_t>::Iterator it = _sequenceNumbersToNack.begin();
|
|
||||||
uint16_t sequenceNumber = *it;
|
|
||||||
_sequenceNumbersToNack.remove(sequenceNumber);
|
|
||||||
return sequenceNumber;
|
|
||||||
}
|
|
||||||
|
|
|
@ -172,9 +172,8 @@ public:
|
||||||
quint32 getIncomingReallyLate() const { return _incomingReallyLate; }
|
quint32 getIncomingReallyLate() const { return _incomingReallyLate; }
|
||||||
quint32 getIncomingPossibleDuplicate() const { return _incomingPossibleDuplicate; }
|
quint32 getIncomingPossibleDuplicate() const { return _incomingPossibleDuplicate; }
|
||||||
float getIncomingFlightTimeAverage() { return _incomingFlightTimeAverage.getAverage(); }
|
float getIncomingFlightTimeAverage() { return _incomingFlightTimeAverage.getAverage(); }
|
||||||
|
|
||||||
int getNumSequenceNumbersToNack() const;
|
const QSet<OCTREE_PACKET_SEQUENCE>& getMissingSequenceNumbers() const { return _missingSequenceNumbers; }
|
||||||
OCTREE_PACKET_SEQUENCE getNextSequenceNumberToNack();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -277,7 +276,6 @@ private:
|
||||||
quint32 _incomingReallyLate; /// out of order and later than MAX_MISSING_SEQUENCE_OLD_AGE late
|
quint32 _incomingReallyLate; /// out of order and later than MAX_MISSING_SEQUENCE_OLD_AGE late
|
||||||
quint32 _incomingPossibleDuplicate; /// out of order possibly a duplicate
|
quint32 _incomingPossibleDuplicate; /// out of order possibly a duplicate
|
||||||
QSet<OCTREE_PACKET_SEQUENCE> _missingSequenceNumbers;
|
QSet<OCTREE_PACKET_SEQUENCE> _missingSequenceNumbers;
|
||||||
QSet<OCTREE_PACKET_SEQUENCE> _sequenceNumbersToNack;
|
|
||||||
SimpleMovingAverage _incomingFlightTimeAverage;
|
SimpleMovingAverage _incomingFlightTimeAverage;
|
||||||
|
|
||||||
// features related items
|
// features related items
|
||||||
|
|
71
libraries/shared/src/AABox.h
Normal file
71
libraries/shared/src/AABox.h
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
//
|
||||||
|
// AABox.h
|
||||||
|
// libraries/octree/src
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 04/11/13.
|
||||||
|
// Copyright 2013 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards
|
||||||
|
// Simple axis aligned box class.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef hifi_AABox_h
|
||||||
|
#define hifi_AABox_h
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#include "BoxBase.h"
|
||||||
|
|
||||||
|
class AACube;
|
||||||
|
|
||||||
|
class AABox {
|
||||||
|
|
||||||
|
public:
|
||||||
|
AABox(const glm::vec3& corner, float size);
|
||||||
|
AABox(const glm::vec3& corner, const glm::vec3& dimensions);
|
||||||
|
AABox();
|
||||||
|
~AABox() {};
|
||||||
|
|
||||||
|
void setBox(const glm::vec3& corner, const glm::vec3& scale);
|
||||||
|
|
||||||
|
void setBox(const glm::vec3& corner, float scale);
|
||||||
|
glm::vec3 getVertexP(const glm::vec3& normal) const;
|
||||||
|
glm::vec3 getVertexN(const glm::vec3& normal) const;
|
||||||
|
void scale(float scale);
|
||||||
|
const glm::vec3& getCorner() const { return _corner; }
|
||||||
|
const glm::vec3& getScale() const { return _scale; }
|
||||||
|
const glm::vec3& getDimensions() const { return _scale; }
|
||||||
|
|
||||||
|
glm::vec3 calcCenter() const;
|
||||||
|
glm::vec3 calcTopFarLeft() const;
|
||||||
|
glm::vec3 getVertex(BoxVertex vertex) const;
|
||||||
|
bool contains(const glm::vec3& point) const;
|
||||||
|
bool contains(const AABox& otherBox) const;
|
||||||
|
bool touches(const AABox& otherBox) const;
|
||||||
|
|
||||||
|
bool contains(const AACube& otherCube) const;
|
||||||
|
bool touches(const AACube& otherCube) const;
|
||||||
|
|
||||||
|
bool expandedContains(const glm::vec3& point, float expansion) const;
|
||||||
|
bool expandedIntersectsSegment(const glm::vec3& start, const glm::vec3& end, float expansion) const;
|
||||||
|
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const;
|
||||||
|
bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const;
|
||||||
|
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) const;
|
||||||
|
|
||||||
|
bool isNull() const { return _scale == glm::vec3(0.0f, 0.0f, 0.0f); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
glm::vec3 getClosestPointOnFace(const glm::vec3& point, BoxFace face) const;
|
||||||
|
glm::vec3 getClosestPointOnFace(const glm::vec4& origin, const glm::vec4& direction, BoxFace face) const;
|
||||||
|
glm::vec4 getPlane(BoxFace face) const;
|
||||||
|
|
||||||
|
static BoxFace getOppositeFace(BoxFace face);
|
||||||
|
|
||||||
|
glm::vec3 _corner;
|
||||||
|
glm::vec3 _scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_AABox_h
|
Loading…
Reference in a new issue