merge upstream/master into andrew/inertia

This commit is contained in:
Andrew Meadows 2014-04-23 08:40:48 -07:00
commit 67d0920f81
16 changed files with 313 additions and 72 deletions

View file

@ -7,6 +7,8 @@
// //
// Tools for manipulating the attributes of the AudioReflector behavior // Tools for manipulating the attributes of the AudioReflector behavior
// //
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //

View file

@ -50,7 +50,7 @@ function maybePlaySound(deltaTime) {
const CLAP_DISTANCE = 0.2; const CLAP_DISTANCE = 0.2;
if (!clapping[palm] && (distanceBetween < CLAP_DISTANCE) && (speed > CLAP_SPEED)) { if (!clapping[palm] && (distanceBetween < CLAP_DISTANCE) && (speed > CLAP_SPEED)) {
var options = new AudioInjectionOptions(); var options = new AudioInjectionOptions();
options.position = palm1Position; options.position = palm1Position;
options.volume = speed / 2.0; options.volume = speed / 2.0;
if (options.volume > 1.0) options.volume = 1.0; if (options.volume > 1.0) options.volume = 1.0;

View file

@ -61,7 +61,7 @@ function checkSticks(deltaTime) {
// Waiting for change in velocity direction or slowing to trigger drum sound // Waiting for change in velocity direction or slowing to trigger drum sound
if ((palmVelocity.y > 0.0) || (speed < STOP_SPEED)) { if ((palmVelocity.y > 0.0) || (speed < STOP_SPEED)) {
state[palm] = 0; state[palm] = 0;
var options = new AudioInjectionOptions(); var options = new AudioInjectionOptions();
options.position = Controller.getSpatialControlPosition(palm * 2 + 1); options.position = Controller.getSpatialControlPosition(palm * 2 + 1);
if (strokeSpeed[palm] > 1.0) { strokeSpeed[palm] = 1.0; } if (strokeSpeed[palm] > 1.0) { strokeSpeed[palm] = 1.0; }
options.volume = strokeSpeed[palm]; options.volume = strokeSpeed[palm];

View file

@ -9,12 +9,12 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// First, load the clap sound from a URL // First, load the clap sound from a URL
var clap = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/bushtit_1.raw"); var clap = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/bushtit_1.raw");
function maybePlaySound(deltaTime) { function maybePlaySound(deltaTime) {
if (Math.random() < 0.01) { if (Math.random() < 0.01) {
// Set the location and other info for the sound to play // Set the location and other info for the sound to play
var options = new AudioInjectionOptions(); var options = new AudioInjectionOptions();
var palmPosition = Controller.getSpatialControlPosition(0); var palmPosition = Controller.getSpatialControlPosition(0);
options.position = palmPosition; options.position = palmPosition;
options.volume = 0.5; options.volume = 0.5;

View file

@ -217,7 +217,7 @@ function update(deltaTime) {
if (invaderStepOfCycle % stepsPerSound == 0) { if (invaderStepOfCycle % stepsPerSound == 0) {
// play the move sound // play the move sound
var options = new AudioInjectionOptions(); var options = new AudioInjectionOptions();
if (soundInMyHead) { if (soundInMyHead) {
options.position = { x: MyAvatar.position.x + 0.0, options.position = { x: MyAvatar.position.x + 0.0,
y: MyAvatar.position.y + 0.1, y: MyAvatar.position.y + 0.1,
@ -329,7 +329,7 @@ function fireMissile() {
lifetime: 5 lifetime: 5
}); });
var options = new AudioInjectionOptions(); var options = new AudioInjectionOptions();
if (soundInMyHead) { if (soundInMyHead) {
options.position = { x: MyAvatar.position.x + 0.0, options.position = { x: MyAvatar.position.x + 0.0,
y: MyAvatar.position.y + 0.1, y: MyAvatar.position.y + 0.1,
@ -379,7 +379,7 @@ function deleteIfInvader(possibleInvaderParticle) {
Particles.deleteParticle(myMissile); Particles.deleteParticle(myMissile);
// play the hit sound // play the hit sound
var options = new AudioInjectionOptions(); var options = new AudioInjectionOptions();
if (soundInMyHead) { if (soundInMyHead) {
options.position = { x: MyAvatar.position.x + 0.0, options.position = { x: MyAvatar.position.x + 0.0,
y: MyAvatar.position.y + 0.1, y: MyAvatar.position.y + 0.1,
@ -417,4 +417,3 @@ initializeInvaders();
// shut down the game after 1 minute // shut down the game after 1 minute
var gameTimer = Script.setTimeout(endGame, itemLifetimes * 1000); var gameTimer = Script.setTimeout(endGame, itemLifetimes * 1000);

View file

@ -5,7 +5,8 @@
// Created by Brad Hefta-Gaub on 2/26/14 // Created by Brad Hefta-Gaub on 2/26/14
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. // Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
// //
// This is an example script // Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
var count = 0; var count = 0;

View file

@ -111,7 +111,7 @@ function checkControllerSide(whichSide) {
velocity : { x: 0, y: 0, z: 0}, inHand: true }; velocity : { x: 0, y: 0, z: 0}, inHand: true };
Particles.editParticle(closestParticle, properties); Particles.editParticle(closestParticle, properties);
var options = new AudioInjectionOptions(); var options = new AudioInjectionOptions();
options.position = ballPosition; options.position = ballPosition;
options.volume = 1.0; options.volume = 1.0;
Audio.playSound(catchSound, options); Audio.playSound(catchSound, options);
@ -152,7 +152,7 @@ function checkControllerSide(whichSide) {
} }
// Play a new ball sound // Play a new ball sound
var options = new AudioInjectionOptions(); var options = new AudioInjectionOptions();
options.position = ballPosition; options.position = ballPosition;
options.volume = 1.0; options.volume = 1.0;
Audio.playSound(catchSound, options); Audio.playSound(catchSound, options);
@ -201,7 +201,7 @@ function checkControllerSide(whichSide) {
rightHandParticle = false; rightHandParticle = false;
} }
var options = new AudioInjectionOptions(); var options = new AudioInjectionOptions();
options.position = ballPosition; options.position = ballPosition;
options.volume = 1.0; options.volume = 1.0;
Audio.playSound(throwSound, options); Audio.playSound(throwSound, options);

View file

@ -64,7 +64,7 @@ collisionBubble[1] = Overlays.addOverlay("sphere",
visible: false visible: false
}); });
var audioOptions = new AudioInjectionOptions(); var audioOptions = new AudioInjectionOptions();
audioOptions.position = { x: MyAvatar.position.x, y: MyAvatar.position.y + 1, z: MyAvatar.position.z }; audioOptions.position = { x: MyAvatar.position.x, y: MyAvatar.position.y + 1, z: MyAvatar.position.z };
audioOptions.volume = 1; audioOptions.volume = 1;

View file

@ -2651,6 +2651,8 @@ void Application::displayOverlay() {
audioMeterY, audioMeterY,
Menu::getInstance()->isOptionChecked(MenuOption::Mirror)); Menu::getInstance()->isOptionChecked(MenuOption::Mirror));
_audio.renderScope(_glWidget->width(), _glWidget->height());
glBegin(GL_QUADS); glBegin(GL_QUADS);
if (isClipping) { if (isClipping) {
glColor3f(1, 0, 0); glColor3f(1, 0, 0);

View file

@ -92,7 +92,14 @@ Audio::Audio(int16_t initialJitterBufferSamples, QObject* parent) :
_processSpatialAudio(false), _processSpatialAudio(false),
_spatialAudioStart(0), _spatialAudioStart(0),
_spatialAudioFinish(0), _spatialAudioFinish(0),
_spatialAudioRingBuffer(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL, true) // random access mode _spatialAudioRingBuffer(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL, true), // random access mode
_scopeEnabled(false),
_scopeEnabledPause(false),
_scopeInputOffset(0),
_scopeOutputOffset(0),
_scopeInput(SAMPLES_PER_SCOPE_WIDTH * sizeof(int16_t), 0),
_scopeOutputLeft(SAMPLES_PER_SCOPE_WIDTH * sizeof(int16_t), 0),
_scopeOutputRight(SAMPLES_PER_SCOPE_WIDTH * sizeof(int16_t), 0)
{ {
// clear the array of locally injected samples // clear the array of locally injected samples
memset(_localProceduralSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL); memset(_localProceduralSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL);
@ -575,6 +582,14 @@ void Audio::handleAudioInput() {
processProceduralAudio(monoAudioSamples, NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); processProceduralAudio(monoAudioSamples, NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL);
} }
if (_scopeEnabled && !_scopeEnabledPause) {
unsigned int numMonoAudioChannels = 1;
unsigned int monoAudioChannel = 0;
addBufferToScope(_scopeInput, _scopeInputOffset, monoAudioSamples, monoAudioChannel, numMonoAudioChannels);
_scopeInputOffset += NETWORK_SAMPLES_PER_FRAME;
_scopeInputOffset %= SAMPLES_PER_SCOPE_WIDTH;
}
NodeList* nodeList = NodeList::getInstance(); NodeList* nodeList = NodeList::getInstance();
SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer); SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer);
@ -813,6 +828,30 @@ void Audio::processReceivedAudio(const QByteArray& audioByteArray) {
if (_outputDevice) { if (_outputDevice) {
_outputDevice->write(outputBuffer); _outputDevice->write(outputBuffer);
} }
if (_scopeEnabled && !_scopeEnabledPause) {
unsigned int numAudioChannels = _desiredOutputFormat.channelCount();
int16_t* samples = ringBufferSamples;
for (int numSamples = numNetworkOutputSamples / numAudioChannels; numSamples > 0; numSamples -= NETWORK_SAMPLES_PER_FRAME) {
unsigned int audioChannel = 0;
addBufferToScope(
_scopeOutputLeft,
_scopeOutputOffset,
samples, audioChannel, numAudioChannels);
audioChannel = 1;
addBufferToScope(
_scopeOutputRight,
_scopeOutputOffset,
samples, audioChannel, numAudioChannels);
_scopeOutputOffset += NETWORK_SAMPLES_PER_FRAME;
_scopeOutputOffset %= SAMPLES_PER_SCOPE_WIDTH;
samples += NETWORK_SAMPLES_PER_FRAME * numAudioChannels;
}
}
delete[] ringBufferSamples; delete[] ringBufferSamples;
} }
} }
@ -1019,6 +1058,140 @@ void Audio::renderToolBox(int x, int y, bool boxed) {
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
} }
void Audio::toggleScopePause() {
_scopeEnabledPause = !_scopeEnabledPause;
}
void Audio::toggleScope() {
_scopeEnabled = !_scopeEnabled;
if (_scopeEnabled) {
static const int width = SAMPLES_PER_SCOPE_WIDTH;
_scopeInputOffset = 0;
_scopeOutputOffset = 0;
memset(_scopeInput.data(), 0, width * sizeof(int16_t));
memset(_scopeOutputLeft.data(), 0, width * sizeof(int16_t));
memset(_scopeOutputRight.data(), 0, width * sizeof(int16_t));
}
}
void Audio::addBufferToScope(
QByteArray& byteArray, unsigned int frameOffset, const int16_t* source, unsigned int sourceChannel, unsigned int sourceNumberOfChannels) {
// Constant multiplier to map sample value to vertical size of scope
float multiplier = (float)MULTIPLIER_SCOPE_HEIGHT / logf(2.0f);
// Temporary variable receives sample value
float sample;
// Temporary variable receives mapping of sample value
int16_t value;
// Short int pointer to mapped samples in byte array
int16_t* destination = (int16_t*) byteArray.data();
for (int i = 0; i < NETWORK_SAMPLES_PER_FRAME; i++) {
sample = (float)source[i * sourceNumberOfChannels + sourceChannel];
if (sample > 0) {
value = (int16_t)(multiplier * logf(sample));
} else if (sample < 0) {
value = (int16_t)(-multiplier * logf(-sample));
} else {
value = 0;
}
destination[i + frameOffset] = value;
}
}
void Audio::renderScope(int width, int height) {
if (!_scopeEnabled)
return;
static const float backgroundColor[4] = { 0.2f, 0.2f, 0.2f, 0.6f };
static const float gridColor[4] = { 0.3f, 0.3f, 0.3f, 0.6f };
static const float inputColor[4] = { 0.3f, .7f, 0.3f, 0.6f };
static const float outputLeftColor[4] = { 0.7f, .3f, 0.3f, 0.6f };
static const float outputRightColor[4] = { 0.3f, .3f, 0.7f, 0.6f };
static const int gridRows = 2;
static const int gridCols = 5;
int x = (width - SAMPLES_PER_SCOPE_WIDTH) / 2;
int y = (height - SAMPLES_PER_SCOPE_HEIGHT) / 2;
int w = SAMPLES_PER_SCOPE_WIDTH;
int h = SAMPLES_PER_SCOPE_HEIGHT;
renderBackground(backgroundColor, x, y, w, h);
renderGrid(gridColor, x, y, w, h, gridRows, gridCols);
renderLineStrip(inputColor, x, y, w, _scopeInputOffset, _scopeInput);
renderLineStrip(outputLeftColor, x, y, w, _scopeOutputOffset, _scopeOutputLeft);
renderLineStrip(outputRightColor, x, y, w, _scopeOutputOffset, _scopeOutputRight);
}
void Audio::renderBackground(const float* color, int x, int y, int width, int height) {
glColor4fv(color);
glBegin(GL_QUADS);
glVertex2i(x, y);
glVertex2i(x + width, y);
glVertex2i(x + width, y + height);
glVertex2i(x , y + height);
glEnd();
glColor4f(1, 1, 1, 1);
}
void Audio::renderGrid(const float* color, int x, int y, int width, int height, int rows, int cols) {
glColor4fv(color);
glBegin(GL_LINES);
int dx = width / cols;
int dy = height / rows;
int tx = x;
int ty = y;
// Draw horizontal grid lines
for (int i = rows + 1; --i >= 0; ) {
glVertex2i(x, ty);
glVertex2i(x + width, ty);
ty += dy;
}
// Draw vertical grid lines
for (int i = cols + 1; --i >= 0; ) {
glVertex2i(tx, y);
glVertex2i(tx, y + height);
tx += dx;
}
glEnd();
glColor4f(1, 1, 1, 1);
}
void Audio::renderLineStrip(const float* color, int x, int y, int n, int offset, const QByteArray& byteArray) {
glColor4fv(color);
glBegin(GL_LINE_STRIP);
int16_t sample;
int16_t* samples = ((int16_t*) byteArray.data()) + offset;
y += SAMPLES_PER_SCOPE_HEIGHT / 2;
for (int i = n - offset; --i >= 0; ) {
sample = *samples++;
glVertex2i(x++, y - sample);
}
samples = (int16_t*) byteArray.data();
for (int i = offset; --i >= 0; ) {
sample = *samples++;
glVertex2i(x++, y - sample);
}
glEnd();
glColor4f(1, 1, 1, 1);
}
bool Audio::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceInfo) { bool Audio::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceInfo) {
bool supportedFormat = false; bool supportedFormat = false;

View file

@ -28,6 +28,7 @@
#include <QtCore/QVector> #include <QtCore/QVector>
#include <QtMultimedia/QAudioFormat> #include <QtMultimedia/QAudioFormat>
#include <QVector> #include <QVector>
#include <QByteArray>
#include <AbstractAudioInterface.h> #include <AbstractAudioInterface.h>
#include <AudioRingBuffer.h> #include <AudioRingBuffer.h>
@ -67,6 +68,7 @@ public:
bool mousePressEvent(int x, int y); bool mousePressEvent(int x, int y);
void renderToolBox(int x, int y, bool boxed); void renderToolBox(int x, int y, bool boxed);
void renderScope(int width, int height);
int getNetworkSampleRate() { return SAMPLE_RATE; } int getNetworkSampleRate() { return SAMPLE_RATE; }
int getNetworkBufferLengthSamplesPerChannel() { return NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; } int getNetworkBufferLengthSamplesPerChannel() { return NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; }
@ -83,6 +85,8 @@ public slots:
void toggleMute(); void toggleMute();
void toggleAudioNoiseReduction(); void toggleAudioNoiseReduction();
void toggleToneInjection(); void toggleToneInjection();
void toggleScope();
void toggleScopePause();
void toggleAudioSpatialProcessing(); void toggleAudioSpatialProcessing();
virtual void handleAudioByteArray(const QByteArray& audioByteArray); virtual void handleAudioByteArray(const QByteArray& audioByteArray);
@ -196,6 +200,29 @@ private:
int calculateNumberOfFrameSamples(int numBytes); int calculateNumberOfFrameSamples(int numBytes);
float calculateDeviceToNetworkInputRatio(int numBytes); float calculateDeviceToNetworkInputRatio(int numBytes);
// Audio scope methods for data acquisition
void addBufferToScope(
QByteArray& byteArray, unsigned int frameOffset, const int16_t* source, unsigned int sourceChannel, unsigned int sourceNumberOfChannels);
// Audio scope methods for rendering
void renderBackground(const float* color, int x, int y, int width, int height);
void renderGrid(const float* color, int x, int y, int width, int height, int rows, int cols);
void renderLineStrip(const float* color, int x, int y, int n, int offset, const QByteArray& byteArray);
// Audio scope data
static const unsigned int NETWORK_SAMPLES_PER_FRAME = NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL;
static const unsigned int FRAMES_PER_SCOPE = 5;
static const unsigned int SAMPLES_PER_SCOPE_WIDTH = FRAMES_PER_SCOPE * NETWORK_SAMPLES_PER_FRAME;
static const unsigned int MULTIPLIER_SCOPE_HEIGHT = 20;
static const unsigned int SAMPLES_PER_SCOPE_HEIGHT = 2 * 15 * MULTIPLIER_SCOPE_HEIGHT;
bool _scopeEnabled;
bool _scopeEnabledPause;
int _scopeInputOffset;
int _scopeOutputOffset;
QByteArray _scopeInput;
QByteArray _scopeOutputLeft;
QByteArray _scopeOutputRight;
}; };

View file

@ -5,6 +5,9 @@
// Created by Brad Hefta-Gaub on 4/2/2014 // Created by Brad Hefta-Gaub on 4/2/2014
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. // Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
// //
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef interface_AudioReflector_h #ifndef interface_AudioReflector_h
#define interface_AudioReflector_h #define interface_AudioReflector_h

View file

@ -260,6 +260,9 @@ Menu::Menu() :
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Bandwidth, 0, true); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Bandwidth, 0, true);
addActionToQMenuAndActionHash(viewMenu, MenuOption::BandwidthDetails, 0, this, SLOT(bandwidthDetails())); addActionToQMenuAndActionHash(viewMenu, MenuOption::BandwidthDetails, 0, this, SLOT(bandwidthDetails()));
addActionToQMenuAndActionHash(viewMenu, MenuOption::OctreeStats, 0, this, SLOT(octreeStatsDetails())); addActionToQMenuAndActionHash(viewMenu, MenuOption::OctreeStats, 0, this, SLOT(octreeStatsDetails()));
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::AudioScope, 0, false,
appInstance->getAudio(),
SLOT(toggleScope()));
QMenu* developerMenu = addMenu("Developer"); QMenu* developerMenu = addMenu("Developer");
@ -386,6 +389,11 @@ Menu::Menu() :
false, false,
appInstance->getAudio(), appInstance->getAudio(),
SLOT(toggleToneInjection())); SLOT(toggleToneInjection()));
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioScopePause,
Qt::CTRL | Qt::Key_P,
false,
appInstance->getAudio(),
SLOT(toggleScopePause()));
QMenu* spatialAudioMenu = audioDebugMenu->addMenu("Spatial Audio"); QMenu* spatialAudioMenu = audioDebugMenu->addMenu("Spatial Audio");

View file

@ -259,8 +259,9 @@ namespace MenuOption {
const QString AmbientOcclusion = "Ambient Occlusion"; const QString AmbientOcclusion = "Ambient Occlusion";
const QString Atmosphere = "Atmosphere"; const QString Atmosphere = "Atmosphere";
const QString AudioNoiseReduction = "Audio Noise Reduction"; const QString AudioNoiseReduction = "Audio Noise Reduction";
const QString AudioScope = "Audio Scope";
const QString AudioScopePause = "Pause Audio Scope";
const QString AudioToneInjection = "Inject Test Tone"; const QString AudioToneInjection = "Inject Test Tone";
const QString AudioSpatialProcessing = "Audio Spatial Processing"; const QString AudioSpatialProcessing = "Audio Spatial Processing";
const QString AudioSpatialProcessingHeadOriented = "Head Oriented"; const QString AudioSpatialProcessingHeadOriented = "Head Oriented";
const QString AudioSpatialProcessingIncludeOriginal = "Includes Network Original"; const QString AudioSpatialProcessingIncludeOriginal = "Includes Network Original";

View file

@ -106,7 +106,7 @@ private:
/// Copy constructor prohibited. /// Copy constructor prohibited.
/// ///
Primitive( Primitive(
const Primitive& prim const Primitive& copy
); );
// SPI methods are defined here // SPI methods are defined here
@ -153,14 +153,14 @@ public:
/// Configuration dependency injection constructor. /// Configuration dependency injection constructor.
/// ///
Cube( Cube(
float x, float x, ///< Cube location on X-axis
float y, float y, ///< Cube location on Y-axis
float z, float z, ///< Cube location on Z-axis
float s, float s, ///< Cube size
unsigned char r, unsigned char r, ///< Cube red color component
unsigned char g, unsigned char g, ///< Cube green color component
unsigned char b, unsigned char b, ///< Cube blue color component
unsigned char faces unsigned char faces ///< Bitmask of faces of cube excluded from construction
); );
~Cube(); ~Cube();
@ -172,36 +172,48 @@ private:
const Cube& cube const Cube& cube
); );
/// Cube initialization
///
void init( void init(
float x, float x, ///< Cube location on X-axis
float y, float y, ///< Cube location on Y-axis
float z, float z, ///< Cube location on Z-axis
float s, float s, ///< Cube size
unsigned char r, unsigned char r, ///< Cube red color component
unsigned char g, unsigned char g, ///< Cube green color component
unsigned char b, unsigned char b, ///< Cube blue color component
unsigned char faceExclusions unsigned char faceExclusions ///< Bitmask of faces of cube excluded from construction
); );
/// Cube termination
///
void terminate(); void terminate();
/// Initialize cube's vertex list
///
void initializeVertices( void initializeVertices(
float x, float x, ///< Cube location on X-axis
float y, float y, ///< Cube location on Y-axis
float z, float z, ///< Cube location on Z-axis
float s, float s, ///< Cube size
unsigned char r, unsigned char r, ///< Cube red color component
unsigned char g, unsigned char g, ///< Cube green color component
unsigned char b, unsigned char b, ///< Cube blue color component
unsigned char faceExclusions unsigned char faceExclusions ///< Bitmask of faces of cube excluded from construction
); );
/// Terminate cube's vertex list
///
void terminateVertices(); void terminateVertices();
/// Initialize cube's triangle list
///
void initializeTris( void initializeTris(
unsigned char faceExclusions unsigned char faceExclusions
); );
/// Terminate cube's triangle list
///
void terminateTris(); void terminateTris();
// SPI virtual override methods go here // SPI virtual override methods go here
@ -219,11 +231,11 @@ private:
unsigned long _cpuMemoryUsage; ///< Memory allocation of object unsigned long _cpuMemoryUsage; ///< Memory allocation of object
static const int _sNumFacesPerCube = 6; static const int _sNumFacesPerCube = 6; ///< Number of faces per cube
static const int _sNumVerticesPerCube = 24; static const int _sNumVerticesPerCube = 24; ///< Number of vertices per cube
static unsigned char _sFaceIndexToHalfSpaceMask[6]; static unsigned char _sFaceIndexToHalfSpaceMask[6]; ///< index to bitmask map
static float _sVertexIndexToConstructionVector[24][3]; static float _sVertexIndexToConstructionVector[24][3]; ///< Vertex index to construction vector map
static float _sVertexIndexToNormalVector[6][3]; static float _sVertexIndexToNormalVector[6][3]; ///< Vertex index to normal vector map
}; };
@ -242,13 +254,13 @@ public:
/// Add primitive to renderer database. /// Add primitive to renderer database.
/// ///
int add( int add(
Primitive* primitive ///< Pointer to primitive Primitive* primitive ///< Primitive instance to be added
); );
/// Remove primitive from renderer database. /// Remove primitive from renderer database.
/// ///
void remove( void remove(
int id ///< Primitive id int id ///< Primitive id to be removed
); );
/// Clear all primitives from renderer database /// Clear all primitives from renderer database
@ -278,7 +290,7 @@ private:
/// Copy constructor prohibited. /// Copy constructor prohibited.
/// ///
Renderer( Renderer(
const Renderer& primitive const Renderer& copy
); );
// SPI methods are defined here // SPI methods are defined here
@ -286,10 +298,10 @@ private:
/// Add primitive to renderer database. /// Add primitive to renderer database.
/// Service implementer to provide private override for this method /// Service implementer to provide private override for this method
/// in derived class /// in derived class
/// @return primitive id /// @return Primitive id
/// ///
virtual int vAdd( virtual int vAdd(
Primitive* primitive ///< Pointer to primitive Primitive* primitive ///< Primitive instance to be added
) = 0; ) = 0;
/// Remove primitive from renderer database. /// Remove primitive from renderer database.
@ -297,7 +309,7 @@ private:
/// in derived class /// in derived class
/// ///
virtual void vRemove( virtual void vRemove(
int id ///< Primitive id int id ///< Primitive id
) = 0; ) = 0;
/// Clear all primitives from renderer database /// Clear all primitives from renderer database
@ -332,7 +344,7 @@ public:
/// Configuration dependency injection constructor. /// Configuration dependency injection constructor.
/// ///
PrimitiveRenderer( PrimitiveRenderer(
int maxCount int maxCount ///< Max count
); );
~PrimitiveRenderer(); ~PrimitiveRenderer();
@ -365,39 +377,39 @@ private:
/// Construct the elements of the faces of the primitive. /// Construct the elements of the faces of the primitive.
/// ///
void constructElements( void constructElements(
Primitive* primitive Primitive* primitive ///< Primitive instance
); );
/// Deconstruct the elements of the faces of the primitive. /// Deconstruct the elements of the faces of the primitive.
/// ///
void deconstructElements( void deconstructElements(
Primitive* primitive Primitive* primitive ///< Primitive instance
); );
/// Deconstruct the triangle element from the GL buffer. /// Deconstruct the triangle element from the GL buffer.
/// ///
void deconstructTriElement( void deconstructTriElement(
int idx int idx ///< Triangle element index
); );
/// Deconstruct the vertex element from the GL buffer. /// Deconstruct the vertex element from the GL buffer.
/// ///
void deconstructVertexElement( void deconstructVertexElement(
int idx int idx ///< Vertex element index
); );
/// Transfer the vertex element to the GL buffer. /// Transfer the vertex element to the GL buffer.
/// ///
void transferVertexElement( void transferVertexElement(
int idx, int idx, ///< Vertex element index
VertexElement *vertex VertexElement *vertex ///< Vertex element instance
); );
/// Transfer the triangle element to the GL buffer. /// Transfer the triangle element to the GL buffer.
/// ///
void transferTriElement( void transferTriElement(
int idx, int idx, ///< Triangle element index
int tri[3] int tri[3] ///< Triangle element data
); );
/// Get available primitive index. /// Get available primitive index.
@ -424,13 +436,13 @@ private:
/// Add primitive to renderer database. /// Add primitive to renderer database.
/// ///
int vAdd( int vAdd(
Primitive* primitive Primitive* primitive ///< Primitive instance to be added
); );
/// Remove primitive from renderer database. /// Remove primitive from renderer database.
/// ///
void vRemove( void vRemove(
int id int id ///< Primitive id to be removed
); );
/// Clear all primitives from renderer database /// Clear all primitives from renderer database
@ -451,7 +463,7 @@ private:
private: private:
int _maxCount; int _maxCount; ///< Maximum count of tris
// GL related parameters // GL related parameters
@ -479,8 +491,8 @@ private:
// Statistics parameters, not necessary for proper operation // Statistics parameters, not necessary for proper operation
unsigned long _gpuMemoryUsage; unsigned long _gpuMemoryUsage; ///< GPU memory used by this instance
unsigned long _cpuMemoryUsage; unsigned long _cpuMemoryUsage; ///< CPU memory used by this instance
static const int _sIndicesPerTri = 3; static const int _sIndicesPerTri = 3;

View file

@ -938,6 +938,8 @@ void VoxelSystem::copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart,
} }
void VoxelSystem::copyWrittenDataToReadArrays(bool fullVBOs) { void VoxelSystem::copyWrittenDataToReadArrays(bool fullVBOs) {
static unsigned int lockForReadAttempt = 0;
static unsigned int lockForWriteAttempt = 0;
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
"copyWrittenDataToReadArrays()"); "copyWrittenDataToReadArrays()");
@ -946,7 +948,9 @@ void VoxelSystem::copyWrittenDataToReadArrays(bool fullVBOs) {
// time around, the only side effect is the VBOs won't be updated this frame // time around, the only side effect is the VBOs won't be updated this frame
const int WAIT_FOR_LOCK_IN_MS = 5; const int WAIT_FOR_LOCK_IN_MS = 5;
if (_readArraysLock.tryLockForWrite(WAIT_FOR_LOCK_IN_MS)) { if (_readArraysLock.tryLockForWrite(WAIT_FOR_LOCK_IN_MS)) {
lockForWriteAttempt = 0;
if (_writeArraysLock.tryLockForRead(WAIT_FOR_LOCK_IN_MS)) { if (_writeArraysLock.tryLockForRead(WAIT_FOR_LOCK_IN_MS)) {
lockForReadAttempt = 0;
if (_voxelsDirty && _voxelsUpdated) { if (_voxelsDirty && _voxelsUpdated) {
if (fullVBOs) { if (fullVBOs) {
copyWrittenDataToReadArraysFullVBOs(); copyWrittenDataToReadArraysFullVBOs();
@ -956,11 +960,19 @@ void VoxelSystem::copyWrittenDataToReadArrays(bool fullVBOs) {
} }
_writeArraysLock.unlock(); _writeArraysLock.unlock();
} else { } else {
qDebug() << "couldn't get _writeArraysLock.LockForRead()..."; lockForReadAttempt++;
// only report error of first failure
if (lockForReadAttempt == 1) {
qDebug() << "couldn't get _writeArraysLock.LockForRead()...";
}
} }
_readArraysLock.unlock(); _readArraysLock.unlock();
} else { } else {
qDebug() << "couldn't get _readArraysLock.LockForWrite()..."; lockForWriteAttempt++;
// only report error of first failure
if (lockForWriteAttempt == 1) {
qDebug() << "couldn't get _readArraysLock.LockForWrite()...";
}
} }
} }
@ -1683,11 +1695,12 @@ bool VoxelSystem::inspectForExteriorOcclusionsOperation(OctreeElement* element,
//qDebug("Completely occupied voxel at %f %f %f size: %f", v.x, v.y, v.z, s); //qDebug("Completely occupied voxel at %f %f %f size: %f", v.x, v.y, v.z, s);
// TODO: All of the exterior faces of this voxel element are // All of the exterior faces of this voxel element are
// occluders, which means that this element is completely // occluders, which means that this element is completely
// occupied. Hence, the subtree from this node could be // occupied. Hence, the subtree from this node could be
// pruned and replaced by a leaf voxel, if the visible // pruned and replaced by a leaf voxel, if the visible
// properties of the children are the same // properties of the children are the same
} else if (exteriorOcclusions != OctreeElement::HalfSpace::None) { } else if (exteriorOcclusions != OctreeElement::HalfSpace::None) {
//const glm::vec3& v = voxel->getCorner(); //const glm::vec3& v = voxel->getCorner();
//float s = voxel->getScale(); //float s = voxel->getScale();