From f10aeaffab496e2b75e6acc2467e70f8583d0678 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 28 Oct 2014 20:22:33 -0700 Subject: [PATCH 01/39] working on audio mixer muting --- assignment-client/src/audio/AudioMixer.cpp | 12 ++++++++++++ assignment-client/src/audio/AudioMixer.h | 3 +++ interface/src/Audio.cpp | 18 ++++++++++++++++++ interface/src/Audio.h | 3 +++ libraries/audio/src/PositionalAudioStream.cpp | 16 +++++++++++++++- libraries/audio/src/PositionalAudioStream.h | 6 ++++++ 6 files changed, 57 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 8d87638434..d581bbc624 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -61,6 +61,7 @@ const float LOUDNESS_TO_DISTANCE_RATIO = 0.00001f; const float DEFAULT_ATTENUATION_PER_DOUBLING_IN_DISTANCE = 0.18; +const float DEFAULT_NOISE_MUTING_THRESHOLD = 100.0f; const QString AUDIO_MIXER_LOGGING_TARGET_NAME = "audio-mixer"; const QString AUDIO_ENV_GROUP_KEY = "audio_env"; @@ -78,12 +79,18 @@ bool AudioMixer::_printStreamStats = false; bool AudioMixer::_enableFilter = true; +bool AudioMixer::shouldMute(float quietestFrame, float loudestFrame) { + return (quietestFrame > _noiseMutingThreshold); + qDebug() << "Muting, quiestest frame = " << quietestFrame; +} + AudioMixer::AudioMixer(const QByteArray& packet) : ThreadedAssignment(packet), _trailingSleepRatio(1.0f), _minAudibilityThreshold(LOUDNESS_TO_DISTANCE_RATIO / 2.0f), _performanceThrottlingRatio(0.0f), _attenuationPerDoublingInDistance(DEFAULT_ATTENUATION_PER_DOUBLING_IN_DISTANCE), + _noiseMutingThreshold(DEFAULT_NOISE_MUTING_THRESHOLD), _numStatFrames(0), _sumListeners(0), _sumMixes(0), @@ -136,6 +143,11 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(AudioMixerClientData* l return 0; } + // if the stream should be muted, bail + if (shouldMute(streamToAdd->getQuietestTrailingFrameLoudness(), streamToAdd->getLoudestTrailingFrameLoudness())) { + return 0; + } + float bearingRelativeAngleToSource = 0.0f; float attenuationCoefficient = 1.0f; int numSamplesDelay = 0; diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index ff976dec61..836554c44a 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -59,6 +59,8 @@ private: int16_t _mixSamples[NETWORK_BUFFER_LENGTH_SAMPLES_STEREO + (SAMPLE_PHASE_DELAY_AT_90 * 2)]; void perSecondActions(); + + bool shouldMute(float quietestFrame, float loudestFrame); QString getReadPendingDatagramsCallsPerSecondsStatsString() const; QString getReadPendingDatagramsPacketsPerCallStatsString() const; @@ -71,6 +73,7 @@ private: float _minAudibilityThreshold; float _performanceThrottlingRatio; float _attenuationPerDoublingInDistance; + float _noiseMutingThreshold; int _numStatFrames; int _sumListeners; int _sumMixes; diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index dd84eb3211..b8e881bc48 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -77,6 +77,9 @@ Audio::Audio(QObject* parent) : _isStereoInput(false), _averagedLatency(0.0), _lastInputLoudness(0), + _inputFrameCounter(0), + _quietestFrame(std::numeric_limits::max()), + _loudestFrame(0.0f), _timeSinceLastClip(-1.0), _dcOffset(0), _noiseGateMeasuredFloor(0), @@ -717,6 +720,21 @@ void Audio::handleAudioInput() { } _lastInputLoudness = fabs(loudness / NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); + + if (_quietestFrame > _lastInputLoudness) { + _quietestFrame = _lastInputLoudness; + } + if (_loudestFrame < _lastInputLoudness) { + _loudestFrame = _lastInputLoudness; + } + + const int FRAMES_FOR_NOISE_DETECTION = 300; + if (_inputFrameCounter++ > FRAMES_FOR_NOISE_DETECTION) { + qDebug() << "Quietest/loudest frame: " << _quietestFrame << " / " << _loudestFrame << " NGfloor: " << _noiseGateMeasuredFloor; + _quietestFrame = std::numeric_limits::max(); + _loudestFrame = 0.0f; + _inputFrameCounter = 0; + } // If Noise Gate is enabled, check and turn the gate on and off if (!_audioSourceInjectEnabled && _noiseGateEnabled) { diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 900b6ce0d6..fcbfb0d34a 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -212,6 +212,9 @@ private: QElapsedTimer _timeSinceLastReceived; float _averagedLatency; float _lastInputLoudness; + int _inputFrameCounter; + float _quietestFrame; + float _loudestFrame; float _timeSinceLastClip; float _dcOffset; float _noiseGateMeasuredFloor; diff --git a/libraries/audio/src/PositionalAudioStream.cpp b/libraries/audio/src/PositionalAudioStream.cpp index 6334ac0efb..49129659b6 100644 --- a/libraries/audio/src/PositionalAudioStream.cpp +++ b/libraries/audio/src/PositionalAudioStream.cpp @@ -30,7 +30,10 @@ PositionalAudioStream::PositionalAudioStream(PositionalAudioStream::Type type, b _shouldLoopbackForNode(false), _isStereo(isStereo), _lastPopOutputTrailingLoudness(0.0f), - _lastPopOutputLoudness(0.0f) + _lastPopOutputLoudness(0.0f), + _quietestTrailingFrameLoudness(std::numeric_limits::max()), + _loudestTrailingFrameLoudness(0.0f), + _frameCounter(0) { } @@ -56,6 +59,17 @@ void PositionalAudioStream::updateLastPopOutputLoudnessAndTrailingLoudness() { _lastPopOutputTrailingLoudness = 0; } } + if (_frameCounter++ == TRAILING_AVERAGE_FRAMES) { + _frameCounter = 0; + _quietestTrailingFrameLoudness = std::numeric_limits::max(); + _loudestTrailingFrameLoudness = 0.0f; + } + if (_lastPopOutputLoudness < _quietestTrailingFrameLoudness) { + _quietestTrailingFrameLoudness = _lastPopOutputLoudness; + } + if (_lastPopOutputLoudness > _loudestTrailingFrameLoudness) { + _loudestTrailingFrameLoudness = _lastPopOutputLoudness; + } } int PositionalAudioStream::parsePositionalData(const QByteArray& positionalByteArray) { diff --git a/libraries/audio/src/PositionalAudioStream.h b/libraries/audio/src/PositionalAudioStream.h index 6ac189352b..f8028cba3d 100644 --- a/libraries/audio/src/PositionalAudioStream.h +++ b/libraries/audio/src/PositionalAudioStream.h @@ -36,12 +36,15 @@ public: void updateLastPopOutputLoudnessAndTrailingLoudness(); float getLastPopOutputTrailingLoudness() const { return _lastPopOutputTrailingLoudness; } float getLastPopOutputLoudness() const { return _lastPopOutputLoudness; } + float getQuietestTrailingFrameLoudness() const { return _quietestTrailingFrameLoudness; } + float getLoudestTrailingFrameLoudness() const { return _loudestTrailingFrameLoudness; } bool shouldLoopbackForNode() const { return _shouldLoopbackForNode; } bool isStereo() const { return _isStereo; } PositionalAudioStream::Type getType() const { return _type; } const glm::vec3& getPosition() const { return _position; } const glm::quat& getOrientation() const { return _orientation; } + protected: // disallow copying of PositionalAudioStream objects @@ -60,6 +63,9 @@ protected: float _lastPopOutputTrailingLoudness; float _lastPopOutputLoudness; + float _quietestTrailingFrameLoudness; + float _loudestTrailingFrameLoudness; + int _frameCounter; }; #endif // hifi_PositionalAudioStream_h From 53c0c4074a15abc06a7e1dfe442115a05351fdb5 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 29 Oct 2014 12:47:27 -0700 Subject: [PATCH 02/39] see yourself before/after moving --- examples/headMove.js | 61 +++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/examples/headMove.js b/examples/headMove.js index f377409cb8..2c49847864 100644 --- a/examples/headMove.js +++ b/examples/headMove.js @@ -18,10 +18,11 @@ var warpActive = false; var warpPosition = { x: 0, y: 0, z: 0 }; var hipsToEyes; +var restoreCountdownTimer; // Overlays to show target location -var WARP_SPHERE_SIZE = 0.15; +var WARP_SPHERE_SIZE = 0.085; var warpSphere = Overlays.addOverlay("sphere", { position: { x: 0, y: 0, z: 0 }, size: WARP_SPHERE_SIZE, @@ -67,10 +68,7 @@ function activateWarp() { updateWarp(); } -var TRIGGER_PULLBACK_DISTANCE = 0.04; -var WATCH_AVATAR_DISTANCE = 1.5; -var MAX_PULLBACK_YAW = 5.0; -var MAX_PULLBACK_PITCH = 5.0; +var WATCH_AVATAR_DISTANCE = 2.5; var sound = new Sound("http://public.highfidelity.io/sounds/Footsteps/FootstepW2Right-12db.wav"); function playSound() { @@ -80,9 +78,20 @@ function playSound() { options.volume = 1.0; Audio.playSound(sound, options); } + + + +function pullBack() { + saveCameraState(); + cameraPosition = Vec3.subtract(MyAvatar.position, Vec3.multiplyQbyV(Camera.getOrientation(), { x: 0, y: -hipsToEyes, z: -hipsToEyes * WATCH_AVATAR_DISTANCE })); + Camera.setPosition(cameraPosition); + cameraPosition = Camera.getPosition(); + startPullbackPosition = cameraPosition; +} + var WARP_SMOOTHING = 0.90; -var WARP_START_TIME = 0.50; -var WARP_START_DISTANCE = 1.5; +var WARP_START_TIME = 0.25; +var WARP_START_DISTANCE = 2.5; var WARP_SENSITIVITY = 0.15; var fixedHeight = true; @@ -106,18 +115,10 @@ function updateWarp() { warpPosition = Vec3.mix(Vec3.sum(startPosition, Vec3.multiply(warpDirection, distance)), warpPosition, WARP_SMOOTHING); } - var height = MyAvatar.getEyePosition().y - MyAvatar.position.y; var cameraPosition; - if (!watchAvatar && - (Math.abs(deltaYaw) < MAX_PULLBACK_YAW) && - (Math.abs(deltaPitch) < MAX_PULLBACK_PITCH) && - (Vec3.length(deltaPosition) > TRIGGER_PULLBACK_DISTANCE)) { - saveCameraState(); - cameraPosition = Vec3.subtract(MyAvatar.position, Vec3.multiplyQbyV(Camera.getOrientation(), { x: 0, y: -height, z: -height * WATCH_AVATAR_DISTANCE })); - Camera.setPosition(cameraPosition); - cameraPosition = Camera.getPosition(); - startPullbackPosition = cameraPosition; + if (!watchAvatar && willMove) { + pullBack(); watchAvatar = true; } @@ -143,8 +144,15 @@ function finishWarp() { visible: false, }); if (willMove) { - warpPosition.y -= hipsToEyes; + if (fixedHeight) { + warpPosition.y = MyAvatar.position.y; + } else { + warpPosition.y -= hipsToEyes; + } + MyAvatar.position = warpPosition; + cameraPosition = Vec3.subtract(MyAvatar.position, Vec3.multiplyQbyV(Camera.getOrientation(), { x: 0, y: -hipsToEyes, z: -hipsToEyes * WATCH_AVATAR_DISTANCE })); + Camera.setPosition(cameraPosition); playSound(); } } @@ -155,6 +163,14 @@ function update(deltaTime) { keyDownTime += deltaTime; updateWarp(); } + if (restoreCountdownTimer > 0.0) { + restoreCountdownTimer -= deltaTime; + if (restoreCountdownTimer <= 0.0) { + restoreCameraState(); + watchAvatar = false; + restoreCountDownTimer = 0.0; + } + } } Controller.keyPressEvent.connect(function(event) { @@ -173,10 +189,10 @@ Controller.keyPressEvent.connect(function(event) { activateWarp(); } }); - -var TIME_FOR_TURN = 0.25; + var DOUBLE_CLICK_TIME = 0.50; var TURN_AROUND = 180.0; +var RESTORE_TIME = 0.50; Controller.keyReleaseEvent.connect(function(event) { if (event.text == "SPACE" && !event.isAutoRepeat) { @@ -187,7 +203,7 @@ Controller.keyReleaseEvent.connect(function(event) { lastYawTurned = 0.0; MyAvatar.orientation = Quat.multiply(Quat.fromPitchYawRollDegrees(0, TURN_AROUND, 0), MyAvatar.orientation); playSound(); - } else if (keyDownTime < TIME_FOR_TURN) { + } else if (keyDownTime < WARP_START_TIME) { var currentYaw = MyAvatar.getHeadFinalYaw(); lastYawTurned = currentYaw; MyAvatar.orientation = Quat.multiply(Quat.fromPitchYawRollDegrees(0, currentYaw, 0), MyAvatar.orientation); @@ -196,8 +212,7 @@ Controller.keyReleaseEvent.connect(function(event) { timeSinceLastUp = 0.0; finishWarp(); if (watchAvatar) { - restoreCameraState(); - watchAvatar = false; + restoreCountdownTimer = RESTORE_TIME; } } }); From 2390559969daa3efac8b01417d8e50c4de02eb00 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 31 Oct 2014 10:02:26 -0700 Subject: [PATCH 03/39] INtroducing the stream format and the Stream and making it work for the model mesh --- interface/src/gpu/Batch.cpp | 38 ++- interface/src/gpu/Batch.h | 26 +- interface/src/gpu/GLBackend.cpp | 345 ++++++++++++++++++++--- interface/src/gpu/GLBackend.h | 26 ++ interface/src/renderer/GeometryCache.cpp | 99 ++++++- interface/src/renderer/GeometryCache.h | 7 + interface/src/renderer/Model.cpp | 53 +++- interface/src/ui/TextRenderer.cpp | 22 +- interface/src/ui/TextRenderer.h | 4 + 9 files changed, 547 insertions(+), 73 deletions(-) diff --git a/interface/src/gpu/Batch.cpp b/interface/src/gpu/Batch.cpp index 40b2646418..c91aa7816a 100644 --- a/interface/src/gpu/Batch.cpp +++ b/interface/src/gpu/Batch.cpp @@ -12,11 +12,38 @@ #include -//#define ADD_COMMAND(call) _commands.push_back(COMMAND_##call); _commandCalls.push_back(&gpu::Batch::do_##call); _commandOffsets.push_back(_params.size()); #define ADD_COMMAND(call) _commands.push_back(COMMAND_##call); _commandOffsets.push_back(_params.size()); using namespace gpu; +const int Element::TYPE_SIZE[Element::NUM_TYPES] = { + 4, + 4, + 4, + 2, + 2, + 2, + 1, + 1, + 4, + 4, + 4, + 2, + 2, + 2, + 1, + 1 +}; + +const int Element::DIMENSION_COUNT[Element::NUM_DIMENSIONS] = { + 1, + 2, + 3, + 4, + 9, + 16 +}; + Batch::Batch() : _commands(), _commandOffsets(), @@ -95,5 +122,14 @@ void Batch::drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, in _params.push_back(nbInstances); } +void Batch::setInputStream(const Stream* stream) { + ADD_COMMAND(setInputStream); + _params.push_back(cacheResource(stream)); +} +void Batch::setInputFormat(const StreamFormat* format) { + ADD_COMMAND(setInputFormat); + + _params.push_back(cacheResource(format)); +} \ No newline at end of file diff --git a/interface/src/gpu/Batch.h b/interface/src/gpu/Batch.h index 8078d33d0c..f47f83e961 100644 --- a/interface/src/gpu/Batch.h +++ b/interface/src/gpu/Batch.h @@ -16,6 +16,9 @@ #include +#include "gpu/Format.h" +#include "gpu/Stream.h" + #if defined(NSIGHT_FOUND) #include "nvToolsExt.h" class ProfileRange { @@ -37,9 +40,9 @@ namespace gpu { class Buffer; class Resource; + typedef int Stamp; -typedef unsigned int uint32; -typedef int int32; + enum Primitive { PRIMITIVE_POINTS = 0, @@ -48,6 +51,8 @@ enum Primitive { PRIMITIVE_TRIANGLES, PRIMITIVE_TRIANGLE_STRIP, PRIMITIVE_QUADS, + + NUM_PRIMITIVES, }; class Batch { @@ -59,11 +64,15 @@ public: void clear(); - void draw(Primitive primitiveType, int nbVertices, int startVertex = 0); + void draw(Primitive primitiveType, int numVertices, int startVertex = 0); void drawIndexed(Primitive primitiveType, int nbIndices, int startIndex = 0); void drawInstanced(uint32 nbInstances, Primitive primitiveType, int nbVertices, int startVertex = 0, int startInstance = 0); void drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, int nbIndices, int startIndex = 0, int startInstance = 0); + void setInputStream(const Stream* stream); + void setInputFormat(const StreamFormat* format); + + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API @@ -127,13 +136,10 @@ public: COMMAND_drawIndexed, COMMAND_drawInstanced, COMMAND_drawIndexedInstanced, - - COMMAND_SET_PIPE_STATE, - COMMAND_SET_VIEWPORT, - COMMAND_SET_FRAMEBUFFER, - COMMAND_SET_RESOURCE, - COMMAND_SET_VERTEX_STREAM, - COMMAND_SET_INDEX_STREAM, + + COMMAND_setInputStream, + COMMAND_setInputFormat, + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long diff --git a/interface/src/gpu/GLBackend.cpp b/interface/src/gpu/GLBackend.cpp index bf9298ad72..ea88194706 100644 --- a/interface/src/gpu/GLBackend.cpp +++ b/interface/src/gpu/GLBackend.cpp @@ -18,6 +18,14 @@ using namespace gpu; GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = { + (&::gpu::GLBackend::do_draw), + (&::gpu::GLBackend::do_drawIndexed), + (&::gpu::GLBackend::do_drawInstanced), + (&::gpu::GLBackend::do_drawIndexedInstanced), + + (&::gpu::GLBackend::do_setInputStream), + (&::gpu::GLBackend::do_setInputFormat), + (&::gpu::GLBackend::do_glEnable), (&::gpu::GLBackend::do_glDisable), @@ -70,8 +78,42 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_glMaterialfv), }; +const GLenum GLBackend::_primitiveToGLmode[NUM_PRIMITIVES] = { + GL_POINTS, + GL_LINES, + GL_LINE_STRIP, + GL_TRIANGLES, + GL_TRIANGLE_STRIP, + GL_QUADS, +}; -GLBackend::GLBackend() { +static const GLenum _elementTypeToGLType[Element::NUM_TYPES]= { + GL_FLOAT, + GL_INT, + GL_UNSIGNED_INT, + GL_HALF_FLOAT, + GL_SHORT, + GL_UNSIGNED_SHORT, + GL_BYTE, + GL_UNSIGNED_BYTE, + GL_FLOAT, + GL_INT, + GL_UNSIGNED_INT, + GL_HALF_FLOAT, + GL_SHORT, + GL_UNSIGNED_SHORT, + GL_BYTE, + GL_UNSIGNED_BYTE +}; + + +GLBackend::GLBackend() : + _inputFormat(0), + _inputStream(0), + _needInputFormatUpdate(true), + _needInputStreamUpdate(true), + _inputAttributeActivation(0) +{ } @@ -87,7 +129,7 @@ void GLBackend::renderBatch(Batch& batch) { GLBackend backend; for (int i = 0; i < numCommands; i++) { - CommandCall call = _commandCalls[((*command) - Batch::COMMAND_glEnable)]; + CommandCall call = _commandCalls[(*command)]; (backend.*(call))(batch, *offset); command++; offset++; @@ -126,24 +168,239 @@ void GLBackend::checkGLError() { } } +#define CHECK_GL_ERROR() ::gpu::GLBackend::checkGLError() +//#define CHECK_GL_ERROR() + +void GLBackend::do_draw(Batch& batch, uint32 paramOffset) { + updateInput(); + + Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint; + GLenum mode = _primitiveToGLmode[primitiveType]; + uint32 numVertices = batch._params[paramOffset + 1]._uint; + uint32 startVertex = batch._params[paramOffset + 0]._uint; + + glDrawArrays(mode, startVertex, numVertices); + CHECK_GL_ERROR(); +} + +void GLBackend::do_drawIndexed(Batch& batch, uint32 paramOffset) { + updateInput(); + + Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint; + GLenum mode = _primitiveToGLmode[primitiveType]; + uint32 numIndices = batch._params[paramOffset + 1]._uint; + uint32 startIndex = batch._params[paramOffset + 0]._uint; + + glDrawElements(mode, numIndices, GL_UNSIGNED_INT, (GLvoid*) startIndex); + CHECK_GL_ERROR(); +} + +void GLBackend::do_drawInstanced(Batch& batch, uint32 paramOffset) { + CHECK_GL_ERROR(); +} + +void GLBackend::do_drawIndexedInstanced(Batch& batch, uint32 paramOffset) { + CHECK_GL_ERROR(); +} + + +void GLBackend::do_setInputStream(Batch& batch, uint32 paramOffset) { + const Stream* stream = reinterpret_cast(batch.editResource(batch._params[paramOffset]._uint)->_pointer); + + if (stream != _inputStream) { + _inputStream = stream; + _needInputStreamUpdate = true; + } +} + +void GLBackend::do_setInputFormat(Batch& batch, uint32 paramOffset) { + const StreamFormat* format = reinterpret_cast(batch.editResource(batch._params[paramOffset]._uint)->_pointer); + + if (format != _inputFormat) { + _inputFormat = format; + _needInputFormatUpdate = true; + } +} + +#define SUPPORT_LEGACY_OPENGL +#if defined(SUPPORT_LEGACY_OPENGL) +static const int NUM_CLASSIC_ATTRIBS = StreamFormat::SLOT_TANGENT; +static const GLenum attributeSlotToClassicAttribName[NUM_CLASSIC_ATTRIBS] = { + GL_VERTEX_ARRAY, + GL_NORMAL_ARRAY, + GL_TEXTURE_COORD_ARRAY, + GL_COLOR_ARRAY +}; +#endif + +void GLBackend::updateInput() { + if (_needInputFormatUpdate || _needInputStreamUpdate) { + + if (_needInputFormatUpdate) { + InputActivationCache newActivation; + + // Check expected activation + if (_inputFormat) { + const StreamFormat::AttributeMap& attributes = _inputFormat->getAttributes(); + for (StreamFormat::AttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); it++) { + const StreamFormat::Attribute& attrib = (*it).second; + newActivation.set(attrib._slot); + } + } + + // Manage Activation what was and what is expected now + for (int i = 0; i < newActivation.size(); i++) { + bool newState = newActivation[i]; + if (newState != _inputAttributeActivation[i]) { +#if defined(SUPPORT_LEGACY_OPENGL) + if (i < NUM_CLASSIC_ATTRIBS) { + if (newState) { + glEnableClientState(attributeSlotToClassicAttribName[i]); + } + else { + glDisableClientState(attributeSlotToClassicAttribName[i]); + } + } else { +#else + { +#endif + if (newState) { + glEnableVertexAttribArray(i); + } else { + glDisableVertexAttribArray(i); + } + } + CHECK_GL_ERROR(); + + _inputAttributeActivation.flip(i); + } + } + } + + // now we need to bind the buffers and assign the attrib pointers + if (_inputStream && _inputFormat) { + const Stream::Buffers& buffers = _inputStream->getBuffers(); + const Stream::Offsets& offsets = _inputStream->getOffsets(); + const Stream::Strides& strides = _inputStream->getStrides(); + + const StreamFormat::AttributeMap& attributes = _inputFormat->getAttributes(); + + for (StreamFormat::ChannelMap::const_iterator channelIt = _inputFormat->getChannels().begin(); + channelIt != _inputFormat->getChannels().end(); + channelIt++) { + const StreamFormat::ChannelMap::value_type::second_type& channel = (*channelIt).second; + if ((*channelIt).first < buffers.size()) { + int bufferNum = (*channelIt).first; + GLuint vbo = gpu::GLBackend::getBufferID((*buffers[bufferNum])); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + CHECK_GL_ERROR(); + + for (int i = 0; i < channel._slots.size(); i++) { + const StreamFormat::Attribute& attrib = attributes.at(channel._slots[i]); + GLuint count = attrib._element.getDimensionCount(); + GLenum type = _elementTypeToGLType[attrib._element.getType()]; + GLuint stride = strides[bufferNum]; + GLuint pointer = attrib._offset + offsets[bufferNum]; +#if defined(SUPPORT_LEGACY_OPENGL) + if (attrib._slot < NUM_CLASSIC_ATTRIBS) { + switch (attrib._slot) { + case StreamFormat::SLOT_POSITION: + glVertexPointer(count, type, stride, (GLvoid*)pointer); + break; + case StreamFormat::SLOT_COLOR: + glColorPointer(count, type, stride, (GLvoid*)pointer); + break; + case StreamFormat::SLOT_TEXCOORD: + glTexCoordPointer(count, type, stride, (GLvoid*)pointer); + break; + case StreamFormat::SLOT_NORMAL: + glNormalPointer(type, stride, (GLvoid*)pointer); + break; + }; + } else { +#else + { +#endif + glVertexAttribPointer(attrib._slot, count, type, attrib._element.isNormalized(), stride, (GLvoid*)pointer); + } + CHECK_GL_ERROR(); + } + } + } + } + + _needInputStreamUpdate = false; + _needInputFormatUpdate = false; + } + +/* Fancy version GL4.4 + if (_needInputFormatUpdate) { + + InputActivationCache newActivation; + + // Assign the vertex format required + if (_inputFormat) { + const StreamFormat::AttributeMap& attributes = _inputFormat->getAttributes(); + for (StreamFormat::AttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); it++) { + const StreamFormat::Attribute& attrib = (*it).second; + newActivation.set(attrib._slot); + glVertexAttribFormat( + attrib._slot, + attrib._element.getDimensionCount(), + _elementTypeToGLType[attrib._element.getType()], + attrib._element.isNormalized(), + attrib._stride); + } + CHECK_GL_ERROR(); + } + + // Manage Activation what was and what is expected now + for (int i = 0; i < newActivation.size(); i++) { + bool newState = newActivation[i]; + if (newState != _inputAttributeActivation[i]) { + if (newState) { + glEnableVertexAttribArray(i); + } else { + glDisableVertexAttribArray(i); + } + _inputAttributeActivation.flip(i); + } + } + CHECK_GL_ERROR(); + + _needInputFormatUpdate = false; + } + + if (_needInputStreamUpdate) { + if (_inputStream) { + const Stream::Buffers& buffers = _inputStream->getBuffers(); + const Stream::Offsets& offsets = _inputStream->getOffsets(); + const Stream::Strides& strides = _inputStream->getStrides(); + + for (int i = 0; i < buffers.size(); i++) { + GLuint vbo = gpu::GLBackend::getBufferID((*buffers[i])); + glBindVertexBuffer(i, vbo, offsets[i], strides[i]); + } + + CHECK_GL_ERROR(); + } + _needInputStreamUpdate = false; + } +*/ +} // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API -//#define ADD_COMMAND(call) _commands.push_back(COMMAND_##call); _commandCalls.push_back(&gpu::Batch::do_##call); _commandOffsets.push_back(_params.size()); -#define ADD_COMMAND(call) _commands.push_back(COMMAND_##call); _commandOffsets.push_back(_params.size()); -//#define ADD_COMMAND_GL(call) _commands.push_back(COMMAND_##call); _commandCalls.push_back(&gpu::GLBackend::do_##call); _commandOffsets.push_back(_params.size()); #define ADD_COMMAND_GL(call) _commands.push_back(COMMAND_##call); _commandOffsets.push_back(_params.size()); //#define DO_IT_NOW(call, offset) runLastCommand(); #define DO_IT_NOW(call, offset) -//#define CHECK_GL_ERROR() ::gpu::backend::checkGLError() -#define CHECK_GL_ERROR() void Batch::_glEnable(GLenum cap) { - ADD_COMMAND(glEnable); + ADD_COMMAND_GL(glEnable); _params.push_back(cap); @@ -155,7 +412,7 @@ void GLBackend::do_glEnable(Batch& batch, uint32 paramOffset) { } void Batch::_glDisable(GLenum cap) { - ADD_COMMAND(glDisable); + ADD_COMMAND_GL(glDisable); _params.push_back(cap); @@ -167,7 +424,7 @@ void GLBackend::do_glDisable(Batch& batch, uint32 paramOffset) { } void Batch::_glEnableClientState(GLenum array) { - ADD_COMMAND(glEnableClientState); + ADD_COMMAND_GL(glEnableClientState); _params.push_back(array); @@ -179,7 +436,7 @@ void GLBackend::do_glEnableClientState(Batch& batch, uint32 paramOffset) { } void Batch::_glDisableClientState(GLenum array) { - ADD_COMMAND(glDisableClientState); + ADD_COMMAND_GL(glDisableClientState); _params.push_back(array); @@ -191,7 +448,7 @@ void GLBackend::do_glDisableClientState(Batch& batch, uint32 paramOffset) { } void Batch::_glCullFace(GLenum mode) { - ADD_COMMAND(glCullFace); + ADD_COMMAND_GL(glCullFace); _params.push_back(mode); @@ -203,7 +460,7 @@ void GLBackend::do_glCullFace(Batch& batch, uint32 paramOffset) { } void Batch::_glAlphaFunc(GLenum func, GLclampf ref) { - ADD_COMMAND(glAlphaFunc); + ADD_COMMAND_GL(glAlphaFunc); _params.push_back(ref); _params.push_back(func); @@ -218,7 +475,7 @@ void GLBackend::do_glAlphaFunc(Batch& batch, uint32 paramOffset) { } void Batch::_glDepthFunc(GLenum func) { - ADD_COMMAND(glDepthFunc); + ADD_COMMAND_GL(glDepthFunc); _params.push_back(func); @@ -230,7 +487,7 @@ void GLBackend::do_glDepthFunc(Batch& batch, uint32 paramOffset) { } void Batch::_glDepthMask(GLboolean flag) { - ADD_COMMAND(glDepthMask); + ADD_COMMAND_GL(glDepthMask); _params.push_back(flag); @@ -242,7 +499,7 @@ void GLBackend::do_glDepthMask(Batch& batch, uint32 paramOffset) { } void Batch::_glDepthRange(GLclampd zNear, GLclampd zFar) { - ADD_COMMAND(glDepthRange); + ADD_COMMAND_GL(glDepthRange); _params.push_back(zFar); _params.push_back(zNear); @@ -257,7 +514,7 @@ void GLBackend::do_glDepthRange(Batch& batch, uint32 paramOffset) { } void Batch::_glBindBuffer(GLenum target, GLuint buffer) { - ADD_COMMAND(glBindBuffer); + ADD_COMMAND_GL(glBindBuffer); _params.push_back(buffer); _params.push_back(target); @@ -272,7 +529,7 @@ void GLBackend::do_glBindBuffer(Batch& batch, uint32 paramOffset) { } void Batch::_glBindTexture(GLenum target, GLuint texture) { - ADD_COMMAND(glBindTexture); + ADD_COMMAND_GL(glBindTexture); _params.push_back(texture); _params.push_back(target); @@ -287,7 +544,7 @@ void GLBackend::do_glBindTexture(Batch& batch, uint32 paramOffset) { } void Batch::_glActiveTexture(GLenum texture) { - ADD_COMMAND(glActiveTexture); + ADD_COMMAND_GL(glActiveTexture); _params.push_back(texture); @@ -299,7 +556,7 @@ void GLBackend::do_glActiveTexture(Batch& batch, uint32 paramOffset) { } void Batch::_glDrawBuffers(GLsizei n, const GLenum* bufs) { - ADD_COMMAND(glDrawBuffers); + ADD_COMMAND_GL(glDrawBuffers); _params.push_back(cacheData(n * sizeof(GLenum), bufs)); _params.push_back(n); @@ -314,7 +571,7 @@ void GLBackend::do_glDrawBuffers(Batch& batch, uint32 paramOffset) { } void Batch::_glUseProgram(GLuint program) { - ADD_COMMAND(glUseProgram); + ADD_COMMAND_GL(glUseProgram); _params.push_back(program); @@ -326,7 +583,7 @@ void GLBackend::do_glUseProgram(Batch& batch, uint32 paramOffset) { } void Batch::_glUniform1f(GLint location, GLfloat v0) { - ADD_COMMAND(glUniform1f); + ADD_COMMAND_GL(glUniform1f); _params.push_back(v0); _params.push_back(location); @@ -341,7 +598,7 @@ void GLBackend::do_glUniform1f(Batch& batch, uint32 paramOffset) { } void Batch::_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - ADD_COMMAND(glUniformMatrix4fv); + ADD_COMMAND_GL(glUniformMatrix4fv); const int MATRIX4_SIZE = 16 * sizeof(float); _params.push_back(cacheData(count * MATRIX4_SIZE, value)); @@ -361,7 +618,7 @@ void GLBackend::do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset) { } void Batch::_glMatrixMode(GLenum mode) { - ADD_COMMAND(glMatrixMode); + ADD_COMMAND_GL(glMatrixMode); _params.push_back(mode); @@ -373,7 +630,7 @@ void GLBackend::do_glMatrixMode(Batch& batch, uint32 paramOffset) { } void Batch::_glPushMatrix() { - ADD_COMMAND(glPushMatrix); + ADD_COMMAND_GL(glPushMatrix); DO_IT_NOW(_glPushMatrix, 0); } @@ -383,7 +640,7 @@ void GLBackend::do_glPushMatrix(Batch& batch, uint32 paramOffset) { } void Batch::_glPopMatrix() { - ADD_COMMAND(glPopMatrix); + ADD_COMMAND_GL(glPopMatrix); DO_IT_NOW(_glPopMatrix, 0); } @@ -393,7 +650,7 @@ void GLBackend::do_glPopMatrix(Batch& batch, uint32 paramOffset) { } void Batch::_glMultMatrixf(const GLfloat *m) { - ADD_COMMAND(glMultMatrixf); + ADD_COMMAND_GL(glMultMatrixf); const int MATRIX4_SIZE = 16 * sizeof(float); _params.push_back(cacheData(MATRIX4_SIZE, m)); @@ -406,7 +663,7 @@ void GLBackend::do_glMultMatrixf(Batch& batch, uint32 paramOffset) { } void Batch::_glLoadMatrixf(const GLfloat *m) { - ADD_COMMAND(glLoadMatrixf); + ADD_COMMAND_GL(glLoadMatrixf); const int MATRIX4_SIZE = 16 * sizeof(float); _params.push_back(cacheData(MATRIX4_SIZE, m)); @@ -419,7 +676,7 @@ void GLBackend::do_glLoadMatrixf(Batch& batch, uint32 paramOffset) { } void Batch::_glLoadIdentity(void) { - ADD_COMMAND(glLoadIdentity); + ADD_COMMAND_GL(glLoadIdentity); DO_IT_NOW(_glLoadIdentity, 0); } @@ -429,7 +686,7 @@ void GLBackend::do_glLoadIdentity(Batch& batch, uint32 paramOffset) { } void Batch::_glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { - ADD_COMMAND(glRotatef); + ADD_COMMAND_GL(glRotatef); _params.push_back(z); _params.push_back(y); @@ -448,7 +705,7 @@ void GLBackend::do_glRotatef(Batch& batch, uint32 paramOffset) { } void Batch::_glScalef(GLfloat x, GLfloat y, GLfloat z) { - ADD_COMMAND(glScalef); + ADD_COMMAND_GL(glScalef); _params.push_back(z); _params.push_back(y); @@ -465,7 +722,7 @@ void GLBackend::do_glScalef(Batch& batch, uint32 paramOffset) { } void Batch::_glTranslatef(GLfloat x, GLfloat y, GLfloat z) { - ADD_COMMAND(glTranslatef); + ADD_COMMAND_GL(glTranslatef); _params.push_back(z); _params.push_back(y); @@ -482,7 +739,7 @@ void GLBackend::do_glTranslatef(Batch& batch, uint32 paramOffset) { } void Batch::_glDrawArrays(GLenum mode, GLint first, GLsizei count) { - ADD_COMMAND(glDrawArrays); + ADD_COMMAND_GL(glDrawArrays); _params.push_back(count); _params.push_back(first); @@ -499,7 +756,7 @@ void GLBackend::do_glDrawArrays(Batch& batch, uint32 paramOffset) { } void Batch::_glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices) { - ADD_COMMAND(glDrawRangeElements); + ADD_COMMAND_GL(glDrawRangeElements); _params.push_back(cacheResource(indices)); _params.push_back(type); @@ -522,7 +779,7 @@ void GLBackend::do_glDrawRangeElements(Batch& batch, uint32 paramOffset) { } void Batch::_glColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) { - ADD_COMMAND(glColorPointer); + ADD_COMMAND_GL(glColorPointer); _params.push_back(cacheResource(pointer)); _params.push_back(stride); @@ -541,7 +798,7 @@ void GLBackend::do_glColorPointer(Batch& batch, uint32 paramOffset) { } void Batch::_glNormalPointer(GLenum type, GLsizei stride, const void *pointer) { - ADD_COMMAND(glNormalPointer); + ADD_COMMAND_GL(glNormalPointer); _params.push_back(cacheResource(pointer)); _params.push_back(stride); @@ -558,7 +815,7 @@ void GLBackend::do_glNormalPointer(Batch& batch, uint32 paramOffset) { } void Batch::_glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) { - ADD_COMMAND(glTexCoordPointer); + ADD_COMMAND_GL(glTexCoordPointer); _params.push_back(cacheResource(pointer)); _params.push_back(stride); @@ -577,7 +834,7 @@ void GLBackend::do_glTexCoordPointer(Batch& batch, uint32 paramOffset) { } void Batch::_glVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) { - ADD_COMMAND(glVertexPointer); + ADD_COMMAND_GL(glVertexPointer); _params.push_back(cacheResource(pointer)); _params.push_back(stride); @@ -597,7 +854,7 @@ void GLBackend::do_glVertexPointer(Batch& batch, uint32 paramOffset) { void Batch::_glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) { - ADD_COMMAND(glVertexAttribPointer); + ADD_COMMAND_GL(glVertexAttribPointer); _params.push_back(cacheResource(pointer)); _params.push_back(stride); @@ -620,7 +877,7 @@ void GLBackend::do_glVertexAttribPointer(Batch& batch, uint32 paramOffset) { } void Batch::_glEnableVertexAttribArray(GLint location) { - ADD_COMMAND(glEnableVertexAttribArray); + ADD_COMMAND_GL(glEnableVertexAttribArray); _params.push_back(location); @@ -632,7 +889,7 @@ void GLBackend::do_glEnableVertexAttribArray(Batch& batch, uint32 paramOffset) { } void Batch::_glDisableVertexAttribArray(GLint location) { - ADD_COMMAND(glDisableVertexAttribArray); + ADD_COMMAND_GL(glDisableVertexAttribArray); _params.push_back(location); @@ -644,7 +901,7 @@ void GLBackend::do_glDisableVertexAttribArray(Batch& batch, uint32 paramOffset) } void Batch::_glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { - ADD_COMMAND(glColor4f); + ADD_COMMAND_GL(glColor4f); _params.push_back(alpha); _params.push_back(blue); @@ -663,7 +920,7 @@ void GLBackend::do_glColor4f(Batch& batch, uint32 paramOffset) { } void Batch::_glMaterialf(GLenum face, GLenum pname, GLfloat param) { - ADD_COMMAND(glMaterialf); + ADD_COMMAND_GL(glMaterialf); _params.push_back(param); _params.push_back(pname); @@ -680,7 +937,7 @@ void GLBackend::do_glMaterialf(Batch& batch, uint32 paramOffset) { } void Batch::_glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) { - ADD_COMMAND(glMaterialfv); + ADD_COMMAND_GL(glMaterialfv); _params.push_back(cacheData(4 * sizeof(float), params)); _params.push_back(pname); diff --git a/interface/src/gpu/GLBackend.h b/interface/src/gpu/GLBackend.h index a28ffb3dcc..35d95628f9 100644 --- a/interface/src/gpu/GLBackend.h +++ b/interface/src/gpu/GLBackend.h @@ -16,6 +16,8 @@ #include "gpu/Context.h" #include "gpu/Batch.h" +#include + namespace gpu { @@ -43,8 +45,27 @@ public: static GLuint getBufferID(const Buffer& buffer); + static const int MAX_NUM_ATTRIBUTES = StreamFormat::NUM_SLOTS; + protected: + bool _needInputFormatUpdate; + bool _needInputStreamUpdate; + const StreamFormat* _inputFormat; + const Stream* _inputStream; + + typedef std::bitset InputActivationCache; + InputActivationCache _inputAttributeActivation; + + void do_draw(Batch& batch, uint32 paramOffset); + void do_drawIndexed(Batch& batch, uint32 paramOffset); + void do_drawInstanced(Batch& batch, uint32 paramOffset); + void do_drawIndexedInstanced(Batch& batch, uint32 paramOffset); + + void updateInput(); + void do_setInputStream(Batch& batch, uint32 paramOffset); + void do_setInputFormat(Batch& batch, uint32 paramOffset); + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API @@ -102,6 +123,11 @@ protected: typedef void (GLBackend::*CommandCall)(Batch&, uint32); static CommandCall _commandCalls[Batch::NUM_COMMANDS]; + static const GLenum _primitiveToGLmode[NUM_PRIMITIVES]; + + static const GLenum _elementTypeToGLtype[Element::NUM_TYPES]; + + }; diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index c3b0a58263..ffbb8bf34f 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -773,7 +773,7 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { totalIndices += (part.quadIndices.size() + part.triangleIndices.size()); } - + /* networkMesh.indexBuffer.create(); networkMesh.indexBuffer.bind(); networkMesh.indexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); @@ -788,8 +788,25 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { offset += part.triangleIndices.size() * sizeof(int); } networkMesh.indexBuffer.release(); - - networkMesh.vertexBuffer.create(); + */ + { + networkMesh._indexBuffer = gpu::BufferPtr(new gpu::Buffer()); + //networkMesh._indexBuffer.bind(); + //networkMesh._indexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + networkMesh._indexBuffer->resize(totalIndices * sizeof(int)); + int offset = 0; + foreach(const FBXMeshPart& part, mesh.parts) { + networkMesh._indexBuffer->setSubData(offset, part.quadIndices.size() * sizeof(int), + (gpu::Resource::Byte*) part.quadIndices.constData()); + offset += part.quadIndices.size() * sizeof(int); + networkMesh._indexBuffer->setSubData(offset, part.triangleIndices.size() * sizeof(int), + (gpu::Resource::Byte*) part.triangleIndices.constData()); + offset += part.triangleIndices.size() * sizeof(int); + } + // networkMesh.indexBuffer.release(); + } + + /* networkMesh.vertexBuffer.create(); networkMesh.vertexBuffer.bind(); networkMesh.vertexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); @@ -833,6 +850,82 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { } networkMesh.vertexBuffer.release(); +*/ + { + networkMesh._vertexBuffer = gpu::BufferPtr(new gpu::Buffer()); + // if we don't need to do any blending, the positions/normals can be static + if (mesh.blendshapes.isEmpty()) { + int normalsOffset = mesh.vertices.size() * sizeof(glm::vec3); + int tangentsOffset = normalsOffset + mesh.normals.size() * sizeof(glm::vec3); + int colorsOffset = tangentsOffset + mesh.tangents.size() * sizeof(glm::vec3); + int texCoordsOffset = colorsOffset + mesh.colors.size() * sizeof(glm::vec3); + int clusterIndicesOffset = texCoordsOffset + mesh.texCoords.size() * sizeof(glm::vec2); + int clusterWeightsOffset = clusterIndicesOffset + mesh.clusterIndices.size() * sizeof(glm::vec4); + + networkMesh._vertexBuffer->resize(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4)); + //networkMesh.vertexBuffer.allocate(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4)); + + networkMesh._vertexBuffer->setSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.vertices.constData()); + networkMesh._vertexBuffer->setSubData(normalsOffset, mesh.normals.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.normals.constData()); + networkMesh._vertexBuffer->setSubData(tangentsOffset, + mesh.tangents.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.tangents.constData()); + networkMesh._vertexBuffer->setSubData(colorsOffset, mesh.colors.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.colors.constData()); + networkMesh._vertexBuffer->setSubData(texCoordsOffset, + mesh.texCoords.size() * sizeof(glm::vec2), (gpu::Resource::Byte*) mesh.texCoords.constData()); + networkMesh._vertexBuffer->setSubData(clusterIndicesOffset, + mesh.clusterIndices.size() * sizeof(glm::vec4), (gpu::Resource::Byte*) mesh.clusterIndices.constData()); + networkMesh._vertexBuffer->setSubData(clusterWeightsOffset, + mesh.clusterWeights.size() * sizeof(glm::vec4), (gpu::Resource::Byte*) mesh.clusterWeights.constData()); + + // otherwise, at least the cluster indices/weights can be static + networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, 0, sizeof(glm::vec3)); + if (mesh.normals.size()) networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, normalsOffset, sizeof(glm::vec3)); + if (mesh.tangents.size()) networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, tangentsOffset, sizeof(glm::vec3)); + if (mesh.colors.size()) networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, colorsOffset, sizeof(glm::vec3)); + if (mesh.texCoords.size()) networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, texCoordsOffset, sizeof(glm::vec2)); + if (mesh.clusterIndices.size()) networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, clusterIndicesOffset, sizeof(glm::vec4)); + if (mesh.clusterWeights.size()) networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, clusterWeightsOffset, sizeof(glm::vec4)); + + int channelNum = 0; + networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_POSITION, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.normals.size()) networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_NORMAL, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.tangents.size()) networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_TANGENT, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.colors.size()) networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_COLOR, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.texCoords.size()) networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_TEXCOORD, channelNum++, gpu::Element(gpu::Element::DIM_VEC2, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.clusterIndices.size()) networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.clusterWeights.size()) networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + } + else { + int colorsOffset = mesh.tangents.size() * sizeof(glm::vec3); + int texCoordsOffset = colorsOffset + mesh.colors.size() * sizeof(glm::vec3); + int clusterIndicesOffset = texCoordsOffset + mesh.texCoords.size() * sizeof(glm::vec2); + int clusterWeightsOffset = clusterIndicesOffset + mesh.clusterIndices.size() * sizeof(glm::vec4); + + networkMesh._vertexBuffer->resize(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4)); + networkMesh._vertexBuffer->setSubData(0, mesh.tangents.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.tangents.constData()); + networkMesh._vertexBuffer->setSubData(colorsOffset, mesh.colors.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.colors.constData()); + networkMesh._vertexBuffer->setSubData(texCoordsOffset, + mesh.texCoords.size() * sizeof(glm::vec2), (gpu::Resource::Byte*) mesh.texCoords.constData()); + networkMesh._vertexBuffer->setSubData(clusterIndicesOffset, + mesh.clusterIndices.size() * sizeof(glm::vec4), (gpu::Resource::Byte*) mesh.clusterIndices.constData()); + networkMesh._vertexBuffer->setSubData(clusterWeightsOffset, + mesh.clusterWeights.size() * sizeof(glm::vec4), (gpu::Resource::Byte*) mesh.clusterWeights.constData()); + + if (mesh.tangents.size()) networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, 0, sizeof(glm::vec3)); + if (mesh.colors.size()) networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, colorsOffset, sizeof(glm::vec3)); + if (mesh.texCoords.size()) networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, texCoordsOffset, sizeof(glm::vec2)); + if (mesh.clusterIndices.size()) networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, clusterIndicesOffset, sizeof(glm::vec4)); + if (mesh.clusterWeights.size()) networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, clusterWeightsOffset, sizeof(glm::vec4)); + + int channelNum = 0; + if (mesh.tangents.size()) networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_TANGENT, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.colors.size()) networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_COLOR, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.texCoords.size()) networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_TEXCOORD, channelNum++, gpu::Element(gpu::Element::DIM_VEC2, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.clusterIndices.size()) networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.clusterWeights.size()) networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + + } + } _meshes.append(networkMesh); } diff --git a/interface/src/renderer/GeometryCache.h b/interface/src/renderer/GeometryCache.h index 4ed6c9943d..2f4fab8d92 100644 --- a/interface/src/renderer/GeometryCache.h +++ b/interface/src/renderer/GeometryCache.h @@ -24,6 +24,8 @@ #include +#include "gpu/Stream.h" + class Model; class NetworkGeometry; class NetworkMesh; @@ -156,6 +158,11 @@ public: QOpenGLBuffer indexBuffer; QOpenGLBuffer vertexBuffer; + gpu::BufferPtr _indexBuffer; + gpu::BufferPtr _vertexBuffer; + + gpu::Stream _vertexStream; + gpu::StreamFormat _vertexFormat; QVector parts; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 2248b377ae..b740e0e5bb 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1812,7 +1812,10 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl const FBXMesh& mesh = geometry.meshes.at(i); //const_cast(networkMesh.indexBuffer).bind(); - GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, const_cast(networkMesh.indexBuffer).bufferId()); + // GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, const_cast(networkMesh.indexBuffer).bufferId()); + // if (!mesh.blendshapes.isEmpty()) { + GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, gpu::GLBackend::getBufferID((*networkMesh._indexBuffer))); + // } int vertexCount = mesh.vertices.size(); if (vertexCount == 0) { @@ -1848,8 +1851,10 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl } //const_cast(networkMesh.vertexBuffer).bind(); - GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, const_cast(networkMesh.vertexBuffer).bufferId()); - + // GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, const_cast(networkMesh.vertexBuffer).bufferId()); + if (!mesh.blendshapes.isEmpty()) { + GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, gpu::GLBackend::getBufferID((*networkMesh._vertexBuffer))); + } GLBATCH(glPushMatrix)(); //Application::getInstance()->loadTranslatedViewMatrix(_translation); GLBATCH(glLoadMatrixf)((const GLfloat*)&Application::getInstance()->getUntranslatedViewMatrix()); @@ -1869,17 +1874,20 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl reinterpret_cast(offset)); //skinProgram->setAttributeBuffer(skinLocations->clusterWeights, GL_FLOAT, // offset + vertexCount * sizeof(glm::vec4), 4); - GLBATCH(glVertexAttribPointer)(skinLocations->clusterWeights, 4, GL_FLOAT, GL_TRUE, 0, (const void*) (offset + vertexCount * sizeof(glm::vec4))); - //skinProgram->enableAttributeArray(skinLocations->clusterIndices); - GLBATCH(glEnableVertexAttribArray)(skinLocations->clusterIndices); - //skinProgram->enableAttributeArray(skinLocations->clusterWeights); - GLBATCH(glEnableVertexAttribArray)(skinLocations->clusterWeights); + + if (!mesh.blendshapes.isEmpty()) { + GLBATCH(glVertexAttribPointer)(skinLocations->clusterWeights, 4, GL_FLOAT, GL_TRUE, 0, (const void*) (offset + vertexCount * sizeof(glm::vec4))); + //skinProgram->enableAttributeArray(skinLocations->clusterIndices); + GLBATCH(glEnableVertexAttribArray)(skinLocations->clusterIndices); + //skinProgram->enableAttributeArray(skinLocations->clusterWeights); + GLBATCH(glEnableVertexAttribArray)(skinLocations->clusterWeights); + } } else { GLBATCH(glMultMatrixf)((const GLfloat*)&state.clusterMatrices[0]); } if (mesh.blendshapes.isEmpty()) { - if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) { + /* if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) { //activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, vertexCount * 2 * sizeof(glm::vec3), 3); GLBATCH(glVertexAttribPointer)(activeLocations->tangent, 3, GL_FLOAT, GL_TRUE, 0, (const void*)(vertexCount * 2 * sizeof(glm::vec3))); //activeProgram->enableAttributeArray(activeLocations->tangent); @@ -1889,7 +1897,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl mesh.tangents.size() * sizeof(glm::vec3))); GLBATCH(glTexCoordPointer)(2, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3) + (mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3))); - + */ } else { if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) { //activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, 0, 3); @@ -1902,9 +1910,11 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl // _blendedVertexBuffers[i].bind(); GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, _blendedVertexBuffers[i].bufferId()); } + if (!mesh.blendshapes.isEmpty()) { + GLBATCH(glVertexPointer)(3, GL_FLOAT, 0, 0); GLBATCH(glNormalPointer)(GL_FLOAT, 0, (void*)(vertexCount * sizeof(glm::vec3))); - + if (!mesh.colors.isEmpty()) { GLBATCH(glEnableClientState)(GL_COLOR_ARRAY); } else { @@ -1913,7 +1923,13 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl if (!mesh.texCoords.isEmpty()) { GLBATCH(glEnableClientState)(GL_TEXTURE_COORD_ARRAY); } + } + else{ + batch.setInputFormat(&(networkMesh._vertexFormat)); + batch.setInputStream(&(networkMesh._vertexStream)); + } + qint64 offset = 0; for (int j = 0; j < networkMesh.parts.size(); j++) { const NetworkMeshPart& networkPart = networkMesh.parts.at(j); @@ -1980,13 +1996,24 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl meshPartsRendered++; if (part.quadIndices.size() > 0) { + if (!mesh.blendshapes.isEmpty()) { GLBATCH(glDrawRangeElements)(GL_QUADS, 0, vertexCount - 1, part.quadIndices.size(), GL_UNSIGNED_INT, (void*)offset); - offset += part.quadIndices.size() * sizeof(int); + } + else { + batch.drawIndexed(gpu::PRIMITIVE_QUADS, part.quadIndices.size(), offset); + } + offset += part.quadIndices.size() * sizeof(int); + + } if (part.triangleIndices.size() > 0) { - GLBATCH(glDrawRangeElements)(GL_TRIANGLES, 0, vertexCount - 1, part.triangleIndices.size(), + if (!mesh.blendshapes.isEmpty()) { + GLBATCH(glDrawRangeElements)(GL_TRIANGLES, 0, vertexCount - 1, part.triangleIndices.size(), GL_UNSIGNED_INT, (void*)offset); + } else { + batch.drawIndexed(gpu::PRIMITIVE_TRIANGLES, part.triangleIndices.size(), offset); + } offset += part.triangleIndices.size() * sizeof(int); } diff --git a/interface/src/ui/TextRenderer.cpp b/interface/src/ui/TextRenderer.cpp index 0db1ab5f00..b791cd3198 100644 --- a/interface/src/ui/TextRenderer.cpp +++ b/interface/src/ui/TextRenderer.cpp @@ -25,6 +25,7 @@ #include #include "gpu/GLBackend.h" +#include "gpu/Stream.h" // the width/height of the cached glyph textures @@ -181,6 +182,16 @@ TextRenderer::TextRenderer(const Properties& properties) : _glyphsBuffer(), _numGlyphsBatched(0) { + _glyphsStreamFormat.setAttribute(gpu::StreamFormat::SLOT_POSITION, 0, gpu::Element(gpu::Element::DIM_VEC2, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + const int NUM_POS_COORDS = 2; + const int VERTEX_TEXCOORD_OFFSET = NUM_POS_COORDS * sizeof(float); + _glyphsStreamFormat.setAttribute(gpu::StreamFormat::SLOT_TEXCOORD, 0, gpu::Element(gpu::Element::DIM_VEC2, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_UV), VERTEX_TEXCOORD_OFFSET); + + _glyphsStreamFormat.setAttribute(gpu::StreamFormat::SLOT_COLOR, 1, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_UINT8, gpu::Element::SEMANTIC_RGBA)); + + _glyphsStream.addBuffer(gpu::BufferPtr(&_glyphsBuffer), 0, _glyphsStreamFormat.getChannels().at(0)._stride); + _glyphsStream.addBuffer(gpu::BufferPtr(&_glyphsColorBuffer), 0, _glyphsStreamFormat.getChannels().at(1)._stride); + _font.setKerning(false); } @@ -295,13 +306,15 @@ void TextRenderer::drawBatch() { glLoadIdentity(); */ + gpu::Batch batch; + glEnable(GL_TEXTURE_2D); // TODO: Apply the correct font atlas texture, for now only one texture per TextRenderer so it should be good glBindTexture(GL_TEXTURE_2D, _currentTextureID); +/* GLuint vbo = gpu::GLBackend::getBufferID(_glyphsBuffer); GLuint colorvbo = gpu::GLBackend::getBufferID(_glyphsColorBuffer); - glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); @@ -317,8 +330,13 @@ void TextRenderer::drawBatch() { glBindBuffer(GL_ARRAY_BUFFER, colorvbo); glColorPointer(4, GL_UNSIGNED_BYTE, 0, (GLvoid*) 0 ); +*/ + batch.setInputFormat(&_glyphsStreamFormat); + batch.setInputStream(&_glyphsStream); + batch.draw(gpu::PRIMITIVE_QUADS, _numGlyphsBatched * 4, 0); - glDrawArrays(GL_QUADS, 0, _numGlyphsBatched * 4); + gpu::GLBackend::renderBatch(batch); + // glDrawArrays(GL_QUADS, 0, _numGlyphsBatched * 4); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); diff --git a/interface/src/ui/TextRenderer.h b/interface/src/ui/TextRenderer.h index 1953dda422..362c9920d1 100644 --- a/interface/src/ui/TextRenderer.h +++ b/interface/src/ui/TextRenderer.h @@ -20,6 +20,8 @@ #include #include "gpu/Resource.h" +#include "gpu/Stream.h" + #include "InterfaceConfig.h" @@ -107,6 +109,8 @@ private: // Graphics Buffer containing the current accumulated glyphs to render gpu::Buffer _glyphsBuffer; gpu::Buffer _glyphsColorBuffer; + gpu::StreamFormat _glyphsStreamFormat; + gpu::Stream _glyphsStream; int _numGlyphsBatched; static QHash _instances; From cadfd7e197e273462dbf736d9078fc2097c40669 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 31 Oct 2014 10:04:19 -0700 Subject: [PATCH 04/39] INtroducing the format descriptor for element attribute and stream, and the Stream and making it work for the model mesh --- interface/src/gpu/Format.h | 116 ++++++++++++++++++++++++++++ interface/src/gpu/Stream.cpp | 50 ++++++++++++ interface/src/gpu/Stream.h | 142 +++++++++++++++++++++++++++++++++++ 3 files changed, 308 insertions(+) create mode 100644 interface/src/gpu/Format.h create mode 100644 interface/src/gpu/Stream.cpp create mode 100644 interface/src/gpu/Stream.h diff --git a/interface/src/gpu/Format.h b/interface/src/gpu/Format.h new file mode 100644 index 0000000000..d069e08817 --- /dev/null +++ b/interface/src/gpu/Format.h @@ -0,0 +1,116 @@ +// +// Format.h +// interface/src/gpu +// +// Created by Sam Gateau on 10/29/2014. +// Copyright 2014 High Fidelity, Inc. +// +// 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_gpu_Format_h +#define hifi_gpu_Format_h + +#include +#include "InterfaceConfig.h" + + +namespace gpu { + + + typedef unsigned int uint32; + typedef int int32; + typedef unsigned short uint16; + typedef short int16; + typedef unsigned char uint8; + typedef char int8; + +// Format is a simple 32bit value that contains everything we need to know about an element +// of a buffer, a pixel of a texture, a varying input/output or uniform from a shader pipeline. +// Type and dimension of the element, and semantic +class Element { +public: + + enum Type { + + TYPE_FLOAT = 0, + TYPE_INT32, + TYPE_UINT32, + TYPE_HALF, + TYPE_INT16, + TYPE_UINT16, + TYPE_INT8, + TYPE_UINT8, + + TYPE_NFLOAT, + TYPE_NINT32, + TYPE_NUINT32, + TYPE_NHALF, + TYPE_NINT16, + TYPE_NUINT16, + TYPE_NINT8, + TYPE_NUINT8, + + NUM_TYPES, + }; + static const int TYPE_SIZE[NUM_TYPES]; + + enum Dimension { + DIM_SCALAR = 0, + DIM_VEC2, + DIM_VEC3, + DIM_VEC4, + DIM_MAT3, + DIM_MAT4, + + NUM_DIMENSIONS, + }; + static const int DIMENSION_COUNT[NUM_DIMENSIONS]; + + enum Semantic { + SEMANTIC_RGB = 0, + SEMANTIC_RGBA, + SEMANTIC_XYZ, + SEMANTIC_XYZW, + SEMANTIC_POS_XYZ, + SEMANTIC_POS_XYZW, + SEMANTIC_QUAT, + SEMANTIC_DIR_XYZ, + SEMANTIC_UV, + SEMANTIC_R8, + + NUM_SEMANTICS, + }; + + Element(Dimension dim, Type type, Semantic sem) : + _semantic(sem), + _dimension(dim), + _type(type) + {} + Element() : + _semantic(SEMANTIC_R8), + _dimension(DIM_SCALAR), + _type(TYPE_INT8) + {} + + Semantic getSemantic() const { return (Semantic)_semantic; } + + Dimension getDimension() const { return (Dimension)_dimension; } + uint8 getDimensionCount() const { return DIMENSION_COUNT[(Dimension)_dimension]; } + + Type getType() const { return (Type)_type; } + bool isNormalized() const { return (getType() >= TYPE_NFLOAT); } + + uint32 getSize() const { return DIMENSION_COUNT[_dimension] * TYPE_SIZE[_type]; } + +protected: + uint8 _semantic; + uint8 _dimension : 4; + uint8 _type : 4; +}; + + +}; + + +#endif diff --git a/interface/src/gpu/Stream.cpp b/interface/src/gpu/Stream.cpp new file mode 100644 index 0000000000..3bdf56f295 --- /dev/null +++ b/interface/src/gpu/Stream.cpp @@ -0,0 +1,50 @@ +// +// Stream.cpp +// interface/src/gpu +// +// Created by Sam Gateau on 10/29/2014. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "Stream.h" + +using namespace gpu; + +void StreamFormat::evaluateCache() { + _channels.clear(); + _elementTotalSize = 0; + for(AttributeMap::iterator it = _attributes.begin(); it != _attributes.end(); it++) { + Attribute& attrib = (*it).second; + Channel& channel = _channels[attrib._channel]; + channel._slots.push_back(attrib._slot); + channel._stride = std::max(channel._stride, attrib.getSize() + attrib._offset); + channel._netSize += attrib.getSize(); + _elementTotalSize += attrib.getSize(); + } +} + +bool StreamFormat::setAttribute(Slot slot, uint8 channel, Element element, uint32 offset, Frequency frequency) { + _attributes[slot] = Attribute(slot, channel, element, offset, frequency); + evaluateCache(); + return true; +} + +Stream::Stream() : + _buffers(), + _offsets() +{} + +Stream::~Stream() +{ + _buffers.clear(); + _offsets.clear(); +} + +void Stream::addBuffer(BufferPtr& buffer, uint32 offset, uint32 stride) { + _buffers.push_back(buffer); + _offsets.push_back(offset); + _strides.push_back(stride); +} diff --git a/interface/src/gpu/Stream.h b/interface/src/gpu/Stream.h new file mode 100644 index 0000000000..f0e3cecf17 --- /dev/null +++ b/interface/src/gpu/Stream.h @@ -0,0 +1,142 @@ +// +// Stream.h +// interface/src/gpu +// +// Created by Sam Gateau on 10/29/2014. +// Copyright 2014 High Fidelity, Inc. +// +// 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_gpu_Stream_h +#define hifi_gpu_Stream_h + +#include +#include "InterfaceConfig.h" + +#include "gpu/Resource.h" +#include "gpu/Format.h" +#include +#include + +#include + +namespace gpu { + +typedef QSharedPointer BufferPtr; + +class StreamFormat { +public: + + enum Slot { + SLOT_POSITION = 0, + SLOT_NORMAL, + SLOT_TEXCOORD, + SLOT_COLOR, + SLOT_TANGENT, + SLOT_SKIN_CLUSTER_WEIGHT, + SLOT_SKIN_CLUSTER_INDEX, + + NUM_SLOTS, + }; + + enum Frequency { + FREQUENCY_PER_VERTEX = 0, + FREQUENCY_PER_INSTANCE, + }; + + class Attribute { + public: + typedef std::vector< Attribute > vector; + + Attribute(Slot slot, uint8 channel, Element element, uint32 offset = 0, Frequency frequency = FREQUENCY_PER_VERTEX) : + _slot(slot), + _channel(channel), + _element(element), + _offset(offset), + _frequency(frequency) + {} + Attribute() : + _slot(SLOT_POSITION), + _channel(0), + _element(), + _offset(0), + _frequency(FREQUENCY_PER_VERTEX) + {} + + + uint8 _slot; // Logical slot assigned to the attribute + uint8 _channel; // index of the channel where to get the data from + Element _element; + + uint32 _offset; + uint32 _frequency; + + uint32 getSize() const { return _element.getSize(); } + + }; + + typedef std::map< uint8, Attribute > AttributeMap; + + class Channel { + public: + std::vector< uint8 > _slots; + std::vector< uint32 > _offsets; + uint32 _stride; + uint32 _netSize; + + Channel() : _stride(0), _netSize(0) {} + }; + typedef std::map< uint8, Channel > ChannelMap; + + StreamFormat() : + _attributes(), + _elementTotalSize(0) {} + ~StreamFormat() {} + + uint32 getNumAttributes() const { return _attributes.size(); } + const AttributeMap& getAttributes() const { return _attributes; } + + uint8 getNumChannels() const { return _channels.size(); } + const ChannelMap& getChannels() const { return _channels; } + + uint32 getElementTotalSize() const { return _elementTotalSize; } + + bool setAttribute(Slot slot, uint8 channel, Element element, uint32 offset = 0, Frequency frequency = FREQUENCY_PER_VERTEX); + +protected: + AttributeMap _attributes; + ChannelMap _channels; + uint32 _elementTotalSize; + + void evaluateCache(); +}; + +class Stream { +public: + typedef std::vector< BufferPtr > Buffers; + typedef std::vector< uint32 > Offsets; + typedef std::vector< uint32 > Strides; + + Stream(); + ~Stream(); + + void addBuffer(BufferPtr& buffer, uint32 offset, uint32 stride); + + const Buffers& getBuffers() const { return _buffers; } + const Offsets& getOffsets() const { return _offsets; } + const Strides& getStrides() const { return _strides; } + uint8 getNumBuffers() const { return _buffers.size(); } + +protected: + Buffers _buffers; + Offsets _offsets; + Strides _strides; +}; +typedef QSharedPointer StreamFormatPtr; +typedef QSharedPointer StreamPtr; + +}; + + +#endif From fba1526389f4e5910bd6069909572c2f9211e2f4 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 3 Nov 2014 09:56:14 -0800 Subject: [PATCH 05/39] Migrating the model rendering code to use the new gpu api for input buffers and stream format --- interface/src/gpu/Batch.cpp | 51 ++++++--- interface/src/gpu/Batch.h | 69 ++++++++++-- interface/src/gpu/Format.h | 3 +- interface/src/gpu/GLBackend.cpp | 138 ++++++++++++++--------- interface/src/gpu/GLBackend.h | 24 +++- interface/src/gpu/Resource.h | 7 ++ interface/src/gpu/Stream.cpp | 2 +- interface/src/gpu/Stream.h | 10 +- interface/src/renderer/GeometryCache.cpp | 54 +++++---- interface/src/renderer/GeometryCache.h | 5 +- interface/src/renderer/Model.cpp | 102 +++++++++++------ interface/src/renderer/Model.h | 4 + interface/src/ui/TextRenderer.cpp | 31 ++--- interface/src/ui/TextRenderer.h | 8 +- 14 files changed, 343 insertions(+), 165 deletions(-) diff --git a/interface/src/gpu/Batch.cpp b/interface/src/gpu/Batch.cpp index c91aa7816a..7e36854769 100644 --- a/interface/src/gpu/Batch.cpp +++ b/interface/src/gpu/Batch.cpp @@ -60,6 +60,7 @@ void Batch::clear() { _commandOffsets.clear(); _params.clear(); _resources.clear(); + _buffers.clear(); _data.clear(); } @@ -86,7 +87,7 @@ uint32 Batch::cacheData(uint32 size, const void* data) { return offset; } -void Batch::draw(Primitive primitiveType, int nbVertices, int startVertex) { +void Batch::draw(Primitive primitiveType, uint32 nbVertices, uint32 startVertex) { ADD_COMMAND(draw); _params.push_back(startVertex); @@ -94,7 +95,7 @@ void Batch::draw(Primitive primitiveType, int nbVertices, int startVertex) { _params.push_back(primitiveType); } -void Batch::drawIndexed(Primitive primitiveType, int nbIndices, int startIndex) { +void Batch::drawIndexed(Primitive primitiveType, uint32 nbIndices, uint32 startIndex) { ADD_COMMAND(drawIndexed); _params.push_back(startIndex); @@ -102,7 +103,7 @@ void Batch::drawIndexed(Primitive primitiveType, int nbIndices, int startIndex) _params.push_back(primitiveType); } -void Batch::drawInstanced(uint32 nbInstances, Primitive primitiveType, int nbVertices, int startVertex, int startInstance) { +void Batch::drawInstanced(uint32 nbInstances, Primitive primitiveType, uint32 nbVertices, uint32 startVertex, uint32 startInstance) { ADD_COMMAND(drawInstanced); _params.push_back(startInstance); @@ -112,7 +113,7 @@ void Batch::drawInstanced(uint32 nbInstances, Primitive primitiveType, int nbVer _params.push_back(nbInstances); } -void Batch::drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, int nbIndices, int startIndex, int startInstance) { +void Batch::drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, uint32 nbIndices, uint32 startIndex, uint32 startInstance) { ADD_COMMAND(drawIndexedInstanced); _params.push_back(startInstance); @@ -122,14 +123,38 @@ void Batch::drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, in _params.push_back(nbInstances); } -void Batch::setInputStream(const Stream* stream) { - ADD_COMMAND(setInputStream); - - _params.push_back(cacheResource(stream)); -} - -void Batch::setInputFormat(const StreamFormat* format) { +void Batch::setInputFormat(const StreamFormatPtr format) { ADD_COMMAND(setInputFormat); - _params.push_back(cacheResource(format)); -} \ No newline at end of file + _params.push_back(_streamFormats.cache(format)); +} + +void Batch::setInputStream(uint8 startChannel, const StreamPtr& stream) { + if (!stream.isNull()) { + if (stream->getNumBuffers()) { + const Buffers& buffers = stream->getBuffers(); + const Offsets& offsets = stream->getOffsets(); + const Offsets& strides = stream->getStrides(); + for (int i = 0; i < buffers.size(); i++) { + setInputBuffer(startChannel + i, buffers[i], offsets[i], strides[i]); + } + } + } +} + +void Batch::setInputBuffer(uint8 channel, const BufferPtr& buffer, Offset offset, Offset stride) { + ADD_COMMAND(setInputBuffer); + + _params.push_back(stride); + _params.push_back(offset); + _params.push_back(_buffers.cache(buffer)); + _params.push_back(channel); +} + +void Batch::setIndexBuffer(Element::Type type, const BufferPtr& buffer, Offset offset) { + ADD_COMMAND(setIndexBuffer); + + _params.push_back(offset); + _params.push_back(_buffers.cache(buffer)); + _params.push_back(type); +} diff --git a/interface/src/gpu/Batch.h b/interface/src/gpu/Batch.h index f47f83e961..fc789320b8 100644 --- a/interface/src/gpu/Batch.h +++ b/interface/src/gpu/Batch.h @@ -17,6 +17,7 @@ #include #include "gpu/Format.h" +#include "gpu/Resource.h" #include "gpu/Stream.h" #if defined(NSIGHT_FOUND) @@ -55,6 +56,9 @@ enum Primitive { NUM_PRIMITIVES, }; +typedef std::vector< BufferPtr > Buffers; +typedef std::vector< Offset > Offsets; + class Batch { public: @@ -64,13 +68,17 @@ public: void clear(); - void draw(Primitive primitiveType, int numVertices, int startVertex = 0); - void drawIndexed(Primitive primitiveType, int nbIndices, int startIndex = 0); - void drawInstanced(uint32 nbInstances, Primitive primitiveType, int nbVertices, int startVertex = 0, int startInstance = 0); - void drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, int nbIndices, int startIndex = 0, int startInstance = 0); + void draw(Primitive primitiveType, uint32 numVertices, uint32 startVertex = 0); + void drawIndexed(Primitive primitiveType, uint32 nbIndices, uint32 startIndex = 0); + void drawInstanced(uint32 nbInstances, Primitive primitiveType, uint32 nbVertices, uint32 startVertex = 0, uint32 startInstance = 0); + void drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, uint32 nbIndices, uint32 startIndex = 0, uint32 startInstance = 0); - void setInputStream(const Stream* stream); - void setInputFormat(const StreamFormat* format); + void setInputFormat(const StreamFormatPtr format); + + void setInputStream(uint8 startChannel, const StreamPtr& stream); // not a command, just multiples + void setInputBuffer(uint8 channel, const BufferPtr& buffer, Offset offset, Offset stride); + + void setIndexBuffer(Element::Type type, const BufferPtr& buffer, Offset offset); // TODO: As long as we have gl calls explicitely issued from interface @@ -137,9 +145,11 @@ public: COMMAND_drawInstanced, COMMAND_drawIndexedInstanced, - COMMAND_setInputStream, COMMAND_setInputFormat, + COMMAND_setInputBuffer, + + COMMAND_setIndexBuffer, // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long @@ -232,6 +242,39 @@ public: }; typedef std::vector Resources; + template + class Cache { + public: + typedef QSharedPointer Pointer; + Pointer _pointer; + Cache(const Pointer& pointer) : _pointer(pointer) {} + + class Vector { + public: + std::vector> _pointers; + + uint32 cache(const Pointer& pointer) { + uint32 offset = _pointers.size(); + _pointers.push_back(Cache(pointer)); + return offset; + } + + Pointer get(uint32 offset) { + if (offset >= _pointers.size()) + return Pointer(); + return (_pointers.data() + offset)->_pointer; + } + + void clear() { + _pointers.clear(); + } + }; + }; + + typedef Cache::Vector BufferCaches; + typedef Cache::Vector StreamCaches; + typedef Cache::Vector StreamFormatCaches; + typedef unsigned char Byte; typedef std::vector Bytes; @@ -243,6 +286,13 @@ public: return (_resources.data() + offset); } + template < typename T > + T* editResourcePointer(uint32 offset) { + if (offset >= _resources.size()) + return 0; + return reinterpret_cast((_resources.data() + offset)->_pointer); + } + uint32 cacheData(uint32 size, const void* data); Byte* editData(uint32 offset) { if (offset >= _data.size()) @@ -254,6 +304,11 @@ public: CommandOffsets _commandOffsets; Params _params; Resources _resources; + + BufferCaches _buffers; + StreamCaches _streams; + StreamFormatCaches _streamFormats; + Bytes _data; protected: }; diff --git a/interface/src/gpu/Format.h b/interface/src/gpu/Format.h index d069e08817..f0cfe52ddf 100644 --- a/interface/src/gpu/Format.h +++ b/interface/src/gpu/Format.h @@ -17,7 +17,6 @@ namespace gpu { - typedef unsigned int uint32; typedef int int32; typedef unsigned short uint16; @@ -25,6 +24,8 @@ namespace gpu { typedef unsigned char uint8; typedef char int8; + typedef uint32 Offset; + // Format is a simple 32bit value that contains everything we need to know about an element // of a buffer, a pixel of a texture, a varying input/output or uniform from a shader pipeline. // Type and dimension of the element, and semantic diff --git a/interface/src/gpu/GLBackend.cpp b/interface/src/gpu/GLBackend.cpp index ea88194706..8c54ea682c 100644 --- a/interface/src/gpu/GLBackend.cpp +++ b/interface/src/gpu/GLBackend.cpp @@ -23,9 +23,12 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_drawInstanced), (&::gpu::GLBackend::do_drawIndexedInstanced), - (&::gpu::GLBackend::do_setInputStream), (&::gpu::GLBackend::do_setInputFormat), + (&::gpu::GLBackend::do_setInputBuffer), + + (&::gpu::GLBackend::do_setIndexBuffer), + (&::gpu::GLBackend::do_glEnable), (&::gpu::GLBackend::do_glDisable), @@ -108,11 +111,18 @@ static const GLenum _elementTypeToGLType[Element::NUM_TYPES]= { GLBackend::GLBackend() : + _inputFormat(0), - _inputStream(0), + _inputAttributeActivation(0), _needInputFormatUpdate(true), - _needInputStreamUpdate(true), - _inputAttributeActivation(0) + + _vertexBuffersState(0), + _vertexBuffers(_vertexBuffersState.size(), BufferPtr(0)), + _vertexBufferOffsets(_vertexBuffersState.size(), 0), + _vertexBufferStrides(_vertexBuffersState.size(), 0), + + _indexBuffer(0), + _indexBufferOffset(0) { } @@ -191,7 +201,7 @@ void GLBackend::do_drawIndexed(Batch& batch, uint32 paramOffset) { uint32 numIndices = batch._params[paramOffset + 1]._uint; uint32 startIndex = batch._params[paramOffset + 0]._uint; - glDrawElements(mode, numIndices, GL_UNSIGNED_INT, (GLvoid*) startIndex); + glDrawElements(mode, numIndices, GL_UNSIGNED_INT, (GLvoid*)(startIndex + _indexBufferOffset)); CHECK_GL_ERROR(); } @@ -203,18 +213,8 @@ void GLBackend::do_drawIndexedInstanced(Batch& batch, uint32 paramOffset) { CHECK_GL_ERROR(); } - -void GLBackend::do_setInputStream(Batch& batch, uint32 paramOffset) { - const Stream* stream = reinterpret_cast(batch.editResource(batch._params[paramOffset]._uint)->_pointer); - - if (stream != _inputStream) { - _inputStream = stream; - _needInputStreamUpdate = true; - } -} - void GLBackend::do_setInputFormat(Batch& batch, uint32 paramOffset) { - const StreamFormat* format = reinterpret_cast(batch.editResource(batch._params[paramOffset]._uint)->_pointer); + StreamFormatPtr format = batch._streamFormats.get(batch._params[paramOffset]._uint); if (format != _inputFormat) { _inputFormat = format; @@ -222,6 +222,20 @@ void GLBackend::do_setInputFormat(Batch& batch, uint32 paramOffset) { } } +void GLBackend::do_setInputBuffer(Batch& batch, uint32 paramOffset) { + Offset stride = batch._params[paramOffset + 0]._uint; + Offset offset = batch._params[paramOffset + 1]._uint; + BufferPtr buffer = batch._buffers.get(batch._params[paramOffset + 2]._uint); + uint32 channel = batch._params[paramOffset + 3]._uint; + + if (channel < getNumInputBuffers()) { + _vertexBuffers[channel] = buffer; + _vertexBufferOffsets[channel] = offset; + _vertexBufferStrides[channel] = stride; + _vertexBuffersState.set(channel); + } +} + #define SUPPORT_LEGACY_OPENGL #if defined(SUPPORT_LEGACY_OPENGL) static const int NUM_CLASSIC_ATTRIBS = StreamFormat::SLOT_TANGENT; @@ -234,7 +248,7 @@ static const GLenum attributeSlotToClassicAttribName[NUM_CLASSIC_ATTRIBS] = { #endif void GLBackend::updateInput() { - if (_needInputFormatUpdate || _needInputStreamUpdate) { + if (_needInputFormatUpdate || _vertexBuffersState.any()) { if (_needInputFormatUpdate) { InputActivationCache newActivation; @@ -278,10 +292,10 @@ void GLBackend::updateInput() { } // now we need to bind the buffers and assign the attrib pointers - if (_inputStream && _inputFormat) { - const Stream::Buffers& buffers = _inputStream->getBuffers(); - const Stream::Offsets& offsets = _inputStream->getOffsets(); - const Stream::Strides& strides = _inputStream->getStrides(); + if (_inputFormat) { + const Buffers& buffers = _vertexBuffers; + const Offsets& offsets = _vertexBufferOffsets; + const Offsets& strides = _vertexBufferStrides; const StreamFormat::AttributeMap& attributes = _inputFormat->getAttributes(); @@ -291,45 +305,48 @@ void GLBackend::updateInput() { const StreamFormat::ChannelMap::value_type::second_type& channel = (*channelIt).second; if ((*channelIt).first < buffers.size()) { int bufferNum = (*channelIt).first; - GLuint vbo = gpu::GLBackend::getBufferID((*buffers[bufferNum])); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - CHECK_GL_ERROR(); - for (int i = 0; i < channel._slots.size(); i++) { - const StreamFormat::Attribute& attrib = attributes.at(channel._slots[i]); - GLuint count = attrib._element.getDimensionCount(); - GLenum type = _elementTypeToGLType[attrib._element.getType()]; - GLuint stride = strides[bufferNum]; - GLuint pointer = attrib._offset + offsets[bufferNum]; -#if defined(SUPPORT_LEGACY_OPENGL) - if (attrib._slot < NUM_CLASSIC_ATTRIBS) { - switch (attrib._slot) { - case StreamFormat::SLOT_POSITION: - glVertexPointer(count, type, stride, (GLvoid*)pointer); - break; - case StreamFormat::SLOT_COLOR: - glColorPointer(count, type, stride, (GLvoid*)pointer); - break; - case StreamFormat::SLOT_TEXCOORD: - glTexCoordPointer(count, type, stride, (GLvoid*)pointer); - break; - case StreamFormat::SLOT_NORMAL: - glNormalPointer(type, stride, (GLvoid*)pointer); - break; - }; - } else { -#else - { -#endif - glVertexAttribPointer(attrib._slot, count, type, attrib._element.isNormalized(), stride, (GLvoid*)pointer); - } + if (_vertexBuffersState.at(bufferNum) || _needInputFormatUpdate) { + GLuint vbo = gpu::GLBackend::getBufferID((*buffers[bufferNum])); + glBindBuffer(GL_ARRAY_BUFFER, vbo); CHECK_GL_ERROR(); + _vertexBuffersState[bufferNum] = false; + + for (int i = 0; i < channel._slots.size(); i++) { + const StreamFormat::Attribute& attrib = attributes.at(channel._slots[i]); + GLuint count = attrib._element.getDimensionCount(); + GLenum type = _elementTypeToGLType[attrib._element.getType()]; + GLuint stride = strides[bufferNum]; + GLuint pointer = attrib._offset + offsets[bufferNum]; + #if defined(SUPPORT_LEGACY_OPENGL) + if (attrib._slot < NUM_CLASSIC_ATTRIBS) { + switch (attrib._slot) { + case StreamFormat::SLOT_POSITION: + glVertexPointer(count, type, stride, (GLvoid*)pointer); + break; + case StreamFormat::SLOT_COLOR: + glColorPointer(count, type, stride, (GLvoid*)pointer); + break; + case StreamFormat::SLOT_TEXCOORD: + glTexCoordPointer(count, type, stride, (GLvoid*)pointer); + break; + case StreamFormat::SLOT_NORMAL: + glNormalPointer(type, stride, (GLvoid*)pointer); + break; + }; + } else { + #else + { + #endif + glVertexAttribPointer(attrib._slot, count, type, attrib._element.isNormalized(), stride, (GLvoid*)pointer); + } + CHECK_GL_ERROR(); + } } } } } - - _needInputStreamUpdate = false; + // everything format related should be in sync now _needInputFormatUpdate = false; } @@ -389,6 +406,19 @@ void GLBackend::updateInput() { */ } + +void GLBackend::do_setIndexBuffer(Batch& batch, uint32 paramOffset) { + GLenum type = _elementTypeToGLType[ batch._params[paramOffset + 2]._uint ]; + BufferPtr indexBuffer = batch._buffers.get(batch._params[paramOffset + 1]._uint); + _indexBufferOffset = batch._params[paramOffset + 0]._uint; + _indexBuffer = indexBuffer; + if (indexBuffer) { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, getBufferID(*indexBuffer)); + } else { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } +} + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API diff --git a/interface/src/gpu/GLBackend.h b/interface/src/gpu/GLBackend.h index 35d95628f9..07a71c3c17 100644 --- a/interface/src/gpu/GLBackend.h +++ b/interface/src/gpu/GLBackend.h @@ -46,13 +46,23 @@ public: static GLuint getBufferID(const Buffer& buffer); static const int MAX_NUM_ATTRIBUTES = StreamFormat::NUM_SLOTS; + static const int MAX_NUM_INPUT_BUFFERS = 16; + + uint32 getNumInputBuffers() const { return _vertexBuffersState.size(); } protected: bool _needInputFormatUpdate; - bool _needInputStreamUpdate; - const StreamFormat* _inputFormat; - const Stream* _inputStream; + StreamFormatPtr _inputFormat; + + typedef std::bitset InputBuffersState; + InputBuffersState _vertexBuffersState; + Buffers _vertexBuffers; + Offsets _vertexBufferOffsets; + Offsets _vertexBufferStrides; + + BufferPtr _indexBuffer; + Offset _indexBufferOffset; typedef std::bitset InputActivationCache; InputActivationCache _inputAttributeActivation; @@ -63,8 +73,12 @@ protected: void do_drawIndexedInstanced(Batch& batch, uint32 paramOffset); void updateInput(); - void do_setInputStream(Batch& batch, uint32 paramOffset); - void do_setInputFormat(Batch& batch, uint32 paramOffset); + void do_setInputFormat(Batch& batch, uint32 paramOffset); + + void do_setInputBuffer(Batch& batch, uint32 paramOffset); + + void do_setVertexBuffer(Batch& batch, uint32 paramOffset); + void do_setIndexBuffer(Batch& batch, uint32 paramOffset); // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long diff --git a/interface/src/gpu/Resource.h b/interface/src/gpu/Resource.h index d4527cac4f..d5305744ac 100644 --- a/interface/src/gpu/Resource.h +++ b/interface/src/gpu/Resource.h @@ -14,6 +14,11 @@ #include #include "InterfaceConfig.h" +#include "gpu/Format.h" + +#include + +#include namespace gpu { @@ -142,6 +147,8 @@ protected: friend class Backend; }; +typedef QSharedPointer BufferPtr; +typedef std::vector< BufferPtr > Buffers; }; diff --git a/interface/src/gpu/Stream.cpp b/interface/src/gpu/Stream.cpp index 3bdf56f295..953efd57a2 100644 --- a/interface/src/gpu/Stream.cpp +++ b/interface/src/gpu/Stream.cpp @@ -26,7 +26,7 @@ void StreamFormat::evaluateCache() { } } -bool StreamFormat::setAttribute(Slot slot, uint8 channel, Element element, uint32 offset, Frequency frequency) { +bool StreamFormat::setAttribute(Slot slot, uint8 channel, Element element, Offset offset, Frequency frequency) { _attributes[slot] = Attribute(slot, channel, element, offset, frequency); evaluateCache(); return true; diff --git a/interface/src/gpu/Stream.h b/interface/src/gpu/Stream.h index f0e3cecf17..9aa667b845 100644 --- a/interface/src/gpu/Stream.h +++ b/interface/src/gpu/Stream.h @@ -19,12 +19,8 @@ #include #include -#include - namespace gpu { -typedef QSharedPointer BufferPtr; - class StreamFormat { public: @@ -49,7 +45,7 @@ public: public: typedef std::vector< Attribute > vector; - Attribute(Slot slot, uint8 channel, Element element, uint32 offset = 0, Frequency frequency = FREQUENCY_PER_VERTEX) : + Attribute(Slot slot, uint8 channel, Element element, Offset offset = 0, Frequency frequency = FREQUENCY_PER_VERTEX) : _slot(slot), _channel(channel), _element(element), @@ -69,7 +65,7 @@ public: uint8 _channel; // index of the channel where to get the data from Element _element; - uint32 _offset; + Offset _offset; uint32 _frequency; uint32 getSize() const { return _element.getSize(); } @@ -102,7 +98,7 @@ public: uint32 getElementTotalSize() const { return _elementTotalSize; } - bool setAttribute(Slot slot, uint8 channel, Element element, uint32 offset = 0, Frequency frequency = FREQUENCY_PER_VERTEX); + bool setAttribute(Slot slot, uint8 channel, Element element, Offset offset = 0, Frequency frequency = FREQUENCY_PER_VERTEX); protected: AttributeMap _attributes; diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index ffbb8bf34f..64e4bbb9d5 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -878,22 +878,24 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { mesh.clusterWeights.size() * sizeof(glm::vec4), (gpu::Resource::Byte*) mesh.clusterWeights.constData()); // otherwise, at least the cluster indices/weights can be static - networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, 0, sizeof(glm::vec3)); - if (mesh.normals.size()) networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, normalsOffset, sizeof(glm::vec3)); - if (mesh.tangents.size()) networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, tangentsOffset, sizeof(glm::vec3)); - if (mesh.colors.size()) networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, colorsOffset, sizeof(glm::vec3)); - if (mesh.texCoords.size()) networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, texCoordsOffset, sizeof(glm::vec2)); - if (mesh.clusterIndices.size()) networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, clusterIndicesOffset, sizeof(glm::vec4)); - if (mesh.clusterWeights.size()) networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, clusterWeightsOffset, sizeof(glm::vec4)); + networkMesh._vertexStream = gpu::StreamPtr(new gpu::Stream()); + networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, 0, sizeof(glm::vec3)); + if (mesh.normals.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, normalsOffset, sizeof(glm::vec3)); + if (mesh.tangents.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, tangentsOffset, sizeof(glm::vec3)); + if (mesh.colors.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, colorsOffset, sizeof(glm::vec3)); + if (mesh.texCoords.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, texCoordsOffset, sizeof(glm::vec2)); + if (mesh.clusterIndices.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, clusterIndicesOffset, sizeof(glm::vec4)); + if (mesh.clusterWeights.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, clusterWeightsOffset, sizeof(glm::vec4)); int channelNum = 0; - networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_POSITION, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.normals.size()) networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_NORMAL, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.tangents.size()) networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_TANGENT, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.colors.size()) networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_COLOR, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.texCoords.size()) networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_TEXCOORD, channelNum++, gpu::Element(gpu::Element::DIM_VEC2, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.clusterIndices.size()) networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.clusterWeights.size()) networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + networkMesh._vertexFormat = gpu::StreamFormatPtr(new gpu::StreamFormat()); + networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_POSITION, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.normals.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_NORMAL, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.tangents.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_TANGENT, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.colors.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_COLOR, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.texCoords.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_TEXCOORD, channelNum++, gpu::Element(gpu::Element::DIM_VEC2, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.clusterIndices.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.clusterWeights.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); } else { int colorsOffset = mesh.tangents.size() * sizeof(glm::vec3); @@ -911,18 +913,22 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { networkMesh._vertexBuffer->setSubData(clusterWeightsOffset, mesh.clusterWeights.size() * sizeof(glm::vec4), (gpu::Resource::Byte*) mesh.clusterWeights.constData()); - if (mesh.tangents.size()) networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, 0, sizeof(glm::vec3)); - if (mesh.colors.size()) networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, colorsOffset, sizeof(glm::vec3)); - if (mesh.texCoords.size()) networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, texCoordsOffset, sizeof(glm::vec2)); - if (mesh.clusterIndices.size()) networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, clusterIndicesOffset, sizeof(glm::vec4)); - if (mesh.clusterWeights.size()) networkMesh._vertexStream.addBuffer(networkMesh._vertexBuffer, clusterWeightsOffset, sizeof(glm::vec4)); + networkMesh._vertexStream = gpu::StreamPtr(new gpu::Stream()); + if (mesh.tangents.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, 0, sizeof(glm::vec3)); + if (mesh.colors.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, colorsOffset, sizeof(glm::vec3)); + if (mesh.texCoords.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, texCoordsOffset, sizeof(glm::vec2)); + if (mesh.clusterIndices.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, clusterIndicesOffset, sizeof(glm::vec4)); + if (mesh.clusterWeights.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, clusterWeightsOffset, sizeof(glm::vec4)); int channelNum = 0; - if (mesh.tangents.size()) networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_TANGENT, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.colors.size()) networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_COLOR, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.texCoords.size()) networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_TEXCOORD, channelNum++, gpu::Element(gpu::Element::DIM_VEC2, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.clusterIndices.size()) networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.clusterWeights.size()) networkMesh._vertexFormat.setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + networkMesh._vertexFormat = gpu::StreamFormatPtr(new gpu::StreamFormat()); + networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_POSITION, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.normals.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_NORMAL, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.tangents.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_TANGENT, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.colors.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_COLOR, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.texCoords.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_TEXCOORD, channelNum++, gpu::Element(gpu::Element::DIM_VEC2, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.clusterIndices.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.clusterWeights.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); } } diff --git a/interface/src/renderer/GeometryCache.h b/interface/src/renderer/GeometryCache.h index 2f4fab8d92..b968b64d9a 100644 --- a/interface/src/renderer/GeometryCache.h +++ b/interface/src/renderer/GeometryCache.h @@ -161,8 +161,9 @@ public: gpu::BufferPtr _indexBuffer; gpu::BufferPtr _vertexBuffer; - gpu::Stream _vertexStream; - gpu::StreamFormat _vertexFormat; + gpu::StreamPtr _vertexStream; + + gpu::StreamFormatPtr _vertexFormat; QVector parts; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index b740e0e5bb..e2a8c2c6fc 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -137,6 +137,10 @@ void Model::initProgram(ProgramObject& program, Model::Locations& locations, int + glBindAttribLocation(program.programId(), gpu::StreamFormat::SLOT_TANGENT, "tangent"); + + glLinkProgram(program.programId()); + locations.tangent = program.attributeLocation("tangent"); locations.alphaThreshold = program.uniformLocation("alphaThreshold"); @@ -171,7 +175,13 @@ void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locati #endif + // HACK: Assign explicitely the attribute channel to avoid a bug on Yosemite + glBindAttribLocation(program.programId(), gpu::StreamFormat::SLOT_SKIN_CLUSTER_INDEX, "clusterIndices"); + + glBindAttribLocation(program.programId(), gpu::StreamFormat::SLOT_SKIN_CLUSTER_WEIGHT, "clusterWeights"); + + glLinkProgram(program.programId()); program.bind(); @@ -408,6 +418,19 @@ bool Model::updateGeometry() { buffer.release(); } _blendedVertexBuffers.append(buffer); + + gpu::BufferPtr buffer2(new gpu::Buffer()); + if (!mesh.blendshapes.isEmpty()) { + //buffer.setUsagePattern(QOpenGLBuffer::DynamicDraw); + //buffer.create(); + //buffer.bind(); + buffer2->resize((mesh.vertices.size() + mesh.normals.size()) * sizeof(glm::vec3)); + buffer2->setSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.vertices.constData()); + buffer2->setSubData(mesh.vertices.size() * sizeof(glm::vec3), + mesh.normals.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.normals.constData()); + // buffer.release(); + } + _blendedVertexBuffers2.push_back(buffer2); } foreach (const FBXAttachment& attachment, fbxGeometry.attachments) { Model* model = new Model(this); @@ -549,8 +572,8 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) { // Let's introduce a gpu::Batch to capture all the calls to the graphics api gpu::Batch batch; - GLBATCH(glEnableClientState)(GL_VERTEX_ARRAY); - GLBATCH(glEnableClientState)(GL_NORMAL_ARRAY); + // GLBATCH(glEnableClientState)(GL_VERTEX_ARRAY); + // GLBATCH(glEnableClientState)(GL_NORMAL_ARRAY); GLBATCH(glDisable)(GL_COLOR_MATERIAL); @@ -1408,6 +1431,13 @@ void Model::setBlendedVertices(int blendNumber, const QWeakPointersetSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) vertices.constData() + index); + buffer2->setSubData(mesh.vertices.size() * sizeof(glm::vec3), + mesh.normals.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) normals.constData() + index); + index += mesh.vertices.size(); } } @@ -1432,6 +1462,7 @@ void Model::deleteGeometry() { } _attachments.clear(); _blendedVertexBuffers.clear(); + _blendedVertexBuffers2.clear(); _jointStates.clear(); _meshStates.clear(); clearShapes(); @@ -1813,10 +1844,8 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl //const_cast(networkMesh.indexBuffer).bind(); // GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, const_cast(networkMesh.indexBuffer).bufferId()); - // if (!mesh.blendshapes.isEmpty()) { - GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, gpu::GLBackend::getBufferID((*networkMesh._indexBuffer))); - // } - + // GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, gpu::GLBackend::getBufferID((*networkMesh._indexBuffer))); + batch.setIndexBuffer(gpu::Element::TYPE_UINT32, (networkMesh._indexBuffer), 0); int vertexCount = mesh.vertices.size(); if (vertexCount == 0) { // sanity check @@ -1852,9 +1881,9 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl //const_cast(networkMesh.vertexBuffer).bind(); // GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, const_cast(networkMesh.vertexBuffer).bufferId()); - if (!mesh.blendshapes.isEmpty()) { - GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, gpu::GLBackend::getBufferID((*networkMesh._vertexBuffer))); - } + // if (!mesh.blendshapes.isEmpty()) { + // GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, gpu::GLBackend::getBufferID((*networkMesh._vertexBuffer))); + // } GLBATCH(glPushMatrix)(); //Application::getInstance()->loadTranslatedViewMatrix(_translation); GLBATCH(glLoadMatrixf)((const GLfloat*)&Application::getInstance()->getUntranslatedViewMatrix()); @@ -1870,18 +1899,18 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl mesh.texCoords.size() * sizeof(glm::vec2) + (mesh.blendshapes.isEmpty() ? vertexCount * 2 * sizeof(glm::vec3) : 0); //skinProgram->setAttributeBuffer(skinLocations->clusterIndices, GL_FLOAT, offset, 4); - GLBATCH(glVertexAttribPointer)(skinLocations->clusterIndices, 4, GL_FLOAT, GL_TRUE, 0, + /* GLBATCH(glVertexAttribPointer)(skinLocations->clusterIndices, 4, GL_FLOAT, GL_TRUE, 0, reinterpret_cast(offset)); - //skinProgram->setAttributeBuffer(skinLocations->clusterWeights, GL_FLOAT, + */ //skinProgram->setAttributeBuffer(skinLocations->clusterWeights, GL_FLOAT, // offset + vertexCount * sizeof(glm::vec4), 4); - if (!mesh.blendshapes.isEmpty()) { + /* if (!mesh.blendshapes.isEmpty()) { GLBATCH(glVertexAttribPointer)(skinLocations->clusterWeights, 4, GL_FLOAT, GL_TRUE, 0, (const void*) (offset + vertexCount * sizeof(glm::vec4))); //skinProgram->enableAttributeArray(skinLocations->clusterIndices); GLBATCH(glEnableVertexAttribArray)(skinLocations->clusterIndices); //skinProgram->enableAttributeArray(skinLocations->clusterWeights); GLBATCH(glEnableVertexAttribArray)(skinLocations->clusterWeights); - } + }*/ } else { GLBATCH(glMultMatrixf)((const GLfloat*)&state.clusterMatrices[0]); } @@ -1899,7 +1928,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl (mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3))); */ } else { - if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) { + /* if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) { //activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, 0, 3); GLBATCH(glVertexAttribPointer)(activeLocations->tangent, 3, GL_FLOAT, GL_TRUE, 0, 0); //activeProgram->enableAttributeArray(activeLocations->tangent); @@ -1907,14 +1936,19 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl } GLBATCH(glColorPointer)(3, GL_FLOAT, 0, (void*)(mesh.tangents.size() * sizeof(glm::vec3))); GLBATCH(glTexCoordPointer)(2, GL_FLOAT, 0, (void*)((mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3))); - // _blendedVertexBuffers[i].bind(); - GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, _blendedVertexBuffers[i].bufferId()); + */ + // _blendedVertexBuffers[i].bind(); + // GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, _blendedVertexBuffers[i].bufferId()); + GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, gpu::GLBackend::getBufferID(*_blendedVertexBuffers2[i])); + batch.setInputBuffer(0, _blendedVertexBuffers2[i], 0, 0); + batch.setInputBuffer(1, _blendedVertexBuffers2[i], vertexCount * sizeof(glm::vec3), 0); + } if (!mesh.blendshapes.isEmpty()) { - GLBATCH(glVertexPointer)(3, GL_FLOAT, 0, 0); - GLBATCH(glNormalPointer)(GL_FLOAT, 0, (void*)(vertexCount * sizeof(glm::vec3))); - + // GLBATCH(glVertexPointer)(3, GL_FLOAT, 0, 0); + // GLBATCH(glNormalPointer)(GL_FLOAT, 0, (void*)(vertexCount * sizeof(glm::vec3))); + /* if (!mesh.colors.isEmpty()) { GLBATCH(glEnableClientState)(GL_COLOR_ARRAY); } else { @@ -1922,11 +1956,13 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl } if (!mesh.texCoords.isEmpty()) { GLBATCH(glEnableClientState)(GL_TEXTURE_COORD_ARRAY); - } + }*/ + batch.setInputFormat(networkMesh._vertexFormat); + batch.setInputStream(2, networkMesh._vertexStream); } else{ - batch.setInputFormat(&(networkMesh._vertexFormat)); - batch.setInputStream(&(networkMesh._vertexStream)); + batch.setInputFormat(networkMesh._vertexFormat); + batch.setInputStream(0, networkMesh._vertexStream); } @@ -1996,24 +2032,24 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl meshPartsRendered++; if (part.quadIndices.size() > 0) { - if (!mesh.blendshapes.isEmpty()) { + /* if (!mesh.blendshapes.isEmpty()) { GLBATCH(glDrawRangeElements)(GL_QUADS, 0, vertexCount - 1, part.quadIndices.size(), GL_UNSIGNED_INT, (void*)offset); } - else { + else {*/ batch.drawIndexed(gpu::PRIMITIVE_QUADS, part.quadIndices.size(), offset); - } + // } offset += part.quadIndices.size() * sizeof(int); } if (part.triangleIndices.size() > 0) { - if (!mesh.blendshapes.isEmpty()) { + /* if (!mesh.blendshapes.isEmpty()) { GLBATCH(glDrawRangeElements)(GL_TRIANGLES, 0, vertexCount - 1, part.triangleIndices.size(), GL_UNSIGNED_INT, (void*)offset); - } else { + } else {*/ batch.drawIndexed(gpu::PRIMITIVE_TRIANGLES, part.triangleIndices.size(), offset); - } + // } offset += part.triangleIndices.size() * sizeof(int); } @@ -2024,21 +2060,21 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl args->_quadsRendered += part.quadIndices.size() / INDICES_PER_QUAD; } } - + /** if (!mesh.colors.isEmpty()) { GLBATCH(glDisableClientState)(GL_COLOR_ARRAY); } if (!mesh.texCoords.isEmpty()) { GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY); } - + */ if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) { GLBATCH(glActiveTexture)(GL_TEXTURE1); GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); GLBATCH(glActiveTexture)(GL_TEXTURE0); // activeProgram->disableAttributeArray(activeLocations->tangent); - GLBATCH(glDisableVertexAttribArray)(activeLocations->tangent); + // GLBATCH(glDisableVertexAttribArray)(activeLocations->tangent); } if (specularTextureUnit) { @@ -2049,9 +2085,9 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl if (state.clusterMatrices.size() > 1) { // skinProgram->disableAttributeArray(skinLocations->clusterIndices); - GLBATCH(glDisableVertexAttribArray)(skinLocations->clusterIndices); + // GLBATCH(glDisableVertexAttribArray)(skinLocations->clusterIndices); // skinProgram->disableAttributeArray(skinLocations->clusterWeights); - GLBATCH(glDisableVertexAttribArray)(skinLocations->clusterWeights); + // GLBATCH(glDisableVertexAttribArray)(skinLocations->clusterWeights); } GLBATCH(glPopMatrix)(); diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 9892a12c9d..e8b3c0a298 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -40,6 +40,8 @@ namespace gpu { class Batch; } +#include "gpu/Stream.h" + /// A generic 3D model displaying geometry loaded from a URL. class Model : public QObject, public PhysicsEntity { Q_OBJECT @@ -281,6 +283,8 @@ private: QUrl _url; QVector _blendedVertexBuffers; + + gpu::Buffers _blendedVertexBuffers2; QVector > > _dilatedTextures; diff --git a/interface/src/ui/TextRenderer.cpp b/interface/src/ui/TextRenderer.cpp index b791cd3198..fe109752fe 100644 --- a/interface/src/ui/TextRenderer.cpp +++ b/interface/src/ui/TextRenderer.cpp @@ -133,12 +133,12 @@ int TextRenderer::draw(int x, int y, const char* str) { gpu::Buffer::Size offset = sizeof(vertexBuffer) * _numGlyphsBatched; gpu::Buffer::Size colorOffset = sizeof(colorBuffer) * _numGlyphsBatched; - if ((offset + sizeof(vertexBuffer)) > _glyphsBuffer.getSize()) { - _glyphsBuffer.append(sizeof(vertexBuffer), (gpu::Buffer::Byte*) vertexBuffer); - _glyphsColorBuffer.append(sizeof(colorBuffer), (gpu::Buffer::Byte*) colorBuffer); + if ((offset + sizeof(vertexBuffer)) > _glyphsBuffer->getSize()) { + _glyphsBuffer->append(sizeof(vertexBuffer), (gpu::Buffer::Byte*) vertexBuffer); + _glyphsColorBuffer->append(sizeof(colorBuffer), (gpu::Buffer::Byte*) colorBuffer); } else { - _glyphsBuffer.setSubData(offset, sizeof(vertexBuffer), (gpu::Buffer::Byte*) vertexBuffer); - _glyphsColorBuffer.setSubData(colorOffset, sizeof(colorBuffer), (gpu::Buffer::Byte*) colorBuffer); + _glyphsBuffer->setSubData(offset, sizeof(vertexBuffer), (gpu::Buffer::Byte*) vertexBuffer); + _glyphsColorBuffer->setSubData(colorOffset, sizeof(colorBuffer), (gpu::Buffer::Byte*) colorBuffer); } _numGlyphsBatched++; @@ -179,18 +179,21 @@ TextRenderer::TextRenderer(const Properties& properties) : _y(IMAGE_SIZE), _rowHeight(0), _color(properties.color), - _glyphsBuffer(), - _numGlyphsBatched(0) + _glyphsBuffer(new gpu::Buffer()), + _glyphsColorBuffer(new gpu::Buffer()), + _numGlyphsBatched(0), + _glyphsStreamFormat(new gpu::StreamFormat()), + _glyphsStream(new gpu::Stream()) { - _glyphsStreamFormat.setAttribute(gpu::StreamFormat::SLOT_POSITION, 0, gpu::Element(gpu::Element::DIM_VEC2, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + _glyphsStreamFormat->setAttribute(gpu::StreamFormat::SLOT_POSITION, 0, gpu::Element(gpu::Element::DIM_VEC2, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); const int NUM_POS_COORDS = 2; const int VERTEX_TEXCOORD_OFFSET = NUM_POS_COORDS * sizeof(float); - _glyphsStreamFormat.setAttribute(gpu::StreamFormat::SLOT_TEXCOORD, 0, gpu::Element(gpu::Element::DIM_VEC2, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_UV), VERTEX_TEXCOORD_OFFSET); + _glyphsStreamFormat->setAttribute(gpu::StreamFormat::SLOT_TEXCOORD, 0, gpu::Element(gpu::Element::DIM_VEC2, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_UV), VERTEX_TEXCOORD_OFFSET); - _glyphsStreamFormat.setAttribute(gpu::StreamFormat::SLOT_COLOR, 1, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_UINT8, gpu::Element::SEMANTIC_RGBA)); + _glyphsStreamFormat->setAttribute(gpu::StreamFormat::SLOT_COLOR, 1, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_UINT8, gpu::Element::SEMANTIC_RGBA)); - _glyphsStream.addBuffer(gpu::BufferPtr(&_glyphsBuffer), 0, _glyphsStreamFormat.getChannels().at(0)._stride); - _glyphsStream.addBuffer(gpu::BufferPtr(&_glyphsColorBuffer), 0, _glyphsStreamFormat.getChannels().at(1)._stride); + _glyphsStream->addBuffer(_glyphsBuffer, 0, _glyphsStreamFormat->getChannels().at(0)._stride); + _glyphsStream->addBuffer(_glyphsColorBuffer, 0, _glyphsStreamFormat->getChannels().at(1)._stride); _font.setKerning(false); } @@ -331,8 +334,8 @@ void TextRenderer::drawBatch() { glBindBuffer(GL_ARRAY_BUFFER, colorvbo); glColorPointer(4, GL_UNSIGNED_BYTE, 0, (GLvoid*) 0 ); */ - batch.setInputFormat(&_glyphsStreamFormat); - batch.setInputStream(&_glyphsStream); + batch.setInputFormat(_glyphsStreamFormat); + batch.setInputStream(0, _glyphsStream); batch.draw(gpu::PRIMITIVE_QUADS, _numGlyphsBatched * 4, 0); gpu::GLBackend::renderBatch(batch); diff --git a/interface/src/ui/TextRenderer.h b/interface/src/ui/TextRenderer.h index 362c9920d1..552ac5b158 100644 --- a/interface/src/ui/TextRenderer.h +++ b/interface/src/ui/TextRenderer.h @@ -107,10 +107,10 @@ private: QColor _color; // Graphics Buffer containing the current accumulated glyphs to render - gpu::Buffer _glyphsBuffer; - gpu::Buffer _glyphsColorBuffer; - gpu::StreamFormat _glyphsStreamFormat; - gpu::Stream _glyphsStream; + gpu::BufferPtr _glyphsBuffer; + gpu::BufferPtr _glyphsColorBuffer; + gpu::StreamFormatPtr _glyphsStreamFormat; + gpu::StreamPtr _glyphsStream; int _numGlyphsBatched; static QHash _instances; From 48769928c5a2cfd2c80a1665cc2406386fb089e2 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 3 Nov 2014 13:20:12 -0800 Subject: [PATCH 06/39] Trying to fix the skinning issue --- interface/src/gpu/GLBackend.cpp | 6 ++++-- interface/src/gpu/GLBackend.h | 1 + interface/src/gpu/Stream.h | 4 ++-- interface/src/renderer/Model.cpp | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/interface/src/gpu/GLBackend.cpp b/interface/src/gpu/GLBackend.cpp index 8c54ea682c..e0d803572b 100644 --- a/interface/src/gpu/GLBackend.cpp +++ b/interface/src/gpu/GLBackend.cpp @@ -201,7 +201,9 @@ void GLBackend::do_drawIndexed(Batch& batch, uint32 paramOffset) { uint32 numIndices = batch._params[paramOffset + 1]._uint; uint32 startIndex = batch._params[paramOffset + 0]._uint; - glDrawElements(mode, numIndices, GL_UNSIGNED_INT, (GLvoid*)(startIndex + _indexBufferOffset)); + GLenum glType = _elementTypeToGLType[_indexBufferType]; + + glDrawElements(mode, numIndices, glType, (GLvoid*)(startIndex + _indexBufferOffset)); CHECK_GL_ERROR(); } @@ -408,7 +410,7 @@ void GLBackend::updateInput() { void GLBackend::do_setIndexBuffer(Batch& batch, uint32 paramOffset) { - GLenum type = _elementTypeToGLType[ batch._params[paramOffset + 2]._uint ]; + _indexBufferType = (Element::Type) batch._params[paramOffset + 2]._uint; BufferPtr indexBuffer = batch._buffers.get(batch._params[paramOffset + 1]._uint); _indexBufferOffset = batch._params[paramOffset + 0]._uint; _indexBuffer = indexBuffer; diff --git a/interface/src/gpu/GLBackend.h b/interface/src/gpu/GLBackend.h index 07a71c3c17..a3bd483f89 100644 --- a/interface/src/gpu/GLBackend.h +++ b/interface/src/gpu/GLBackend.h @@ -63,6 +63,7 @@ protected: BufferPtr _indexBuffer; Offset _indexBufferOffset; + Element::Type _indexBufferType; typedef std::bitset InputActivationCache; InputActivationCache _inputAttributeActivation; diff --git a/interface/src/gpu/Stream.h b/interface/src/gpu/Stream.h index 9aa667b845..81ca344199 100644 --- a/interface/src/gpu/Stream.h +++ b/interface/src/gpu/Stream.h @@ -27,11 +27,11 @@ public: enum Slot { SLOT_POSITION = 0, SLOT_NORMAL, - SLOT_TEXCOORD, SLOT_COLOR, + SLOT_TEXCOORD, SLOT_TANGENT, - SLOT_SKIN_CLUSTER_WEIGHT, SLOT_SKIN_CLUSTER_INDEX, + SLOT_SKIN_CLUSTER_WEIGHT, NUM_SLOTS, }; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index e2a8c2c6fc..69fd30df89 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1939,7 +1939,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl */ // _blendedVertexBuffers[i].bind(); // GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, _blendedVertexBuffers[i].bufferId()); - GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, gpu::GLBackend::getBufferID(*_blendedVertexBuffers2[i])); + // GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, gpu::GLBackend::getBufferID(*_blendedVertexBuffers2[i])); batch.setInputBuffer(0, _blendedVertexBuffers2[i], 0, 0); batch.setInputBuffer(1, _blendedVertexBuffers2[i], vertexCount * sizeof(glm::vec3), 0); From ed067791f21b4d1b14aa2a14197c6678504fbea4 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 3 Nov 2014 14:29:11 -0800 Subject: [PATCH 07/39] Fixing format for skin attributes float need to be NFloat --- interface/src/gpu/GLBackend.cpp | 12 +++++++----- interface/src/renderer/GeometryCache.cpp | 8 ++++---- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/interface/src/gpu/GLBackend.cpp b/interface/src/gpu/GLBackend.cpp index e0d803572b..8a38b30ae2 100644 --- a/interface/src/gpu/GLBackend.cpp +++ b/interface/src/gpu/GLBackend.cpp @@ -244,8 +244,8 @@ static const int NUM_CLASSIC_ATTRIBS = StreamFormat::SLOT_TANGENT; static const GLenum attributeSlotToClassicAttribName[NUM_CLASSIC_ATTRIBS] = { GL_VERTEX_ARRAY, GL_NORMAL_ARRAY, - GL_TEXTURE_COORD_ARRAY, - GL_COLOR_ARRAY + GL_COLOR_ARRAY, + GL_TEXTURE_COORD_ARRAY }; #endif @@ -316,13 +316,14 @@ void GLBackend::updateInput() { for (int i = 0; i < channel._slots.size(); i++) { const StreamFormat::Attribute& attrib = attributes.at(channel._slots[i]); + GLuint slot = attrib._slot; GLuint count = attrib._element.getDimensionCount(); GLenum type = _elementTypeToGLType[attrib._element.getType()]; GLuint stride = strides[bufferNum]; GLuint pointer = attrib._offset + offsets[bufferNum]; #if defined(SUPPORT_LEGACY_OPENGL) - if (attrib._slot < NUM_CLASSIC_ATTRIBS) { - switch (attrib._slot) { + if (slot < NUM_CLASSIC_ATTRIBS) { + switch (slot) { case StreamFormat::SLOT_POSITION: glVertexPointer(count, type, stride, (GLvoid*)pointer); break; @@ -340,7 +341,8 @@ void GLBackend::updateInput() { #else { #endif - glVertexAttribPointer(attrib._slot, count, type, attrib._element.isNormalized(), stride, (GLvoid*)pointer); + GLboolean isNormalized = attrib._element.isNormalized(); + glVertexAttribPointer(slot, count, type, isNormalized, stride, (GLvoid*)pointer); } CHECK_GL_ERROR(); } diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 64e4bbb9d5..85cbba585a 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -894,8 +894,8 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { if (mesh.tangents.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_TANGENT, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); if (mesh.colors.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_COLOR, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); if (mesh.texCoords.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_TEXCOORD, channelNum++, gpu::Element(gpu::Element::DIM_VEC2, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.clusterIndices.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.clusterWeights.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.clusterIndices.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_NFLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.clusterWeights.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_NFLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); } else { int colorsOffset = mesh.tangents.size() * sizeof(glm::vec3); @@ -927,8 +927,8 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { if (mesh.tangents.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_TANGENT, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); if (mesh.colors.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_COLOR, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); if (mesh.texCoords.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_TEXCOORD, channelNum++, gpu::Element(gpu::Element::DIM_VEC2, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.clusterIndices.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.clusterWeights.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.clusterIndices.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_NFLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + if (mesh.clusterWeights.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_NFLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); } } From f413f93c62bac269e5246e0b104c1f931aa1663e Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 3 Nov 2014 23:26:39 -0800 Subject: [PATCH 08/39] fix the bug for blend shape when more than one and clean the model rendering with the new stream and buffer gpu api --- interface/src/gpu/Resource.cpp | 4 +- interface/src/renderer/GeometryCache.cpp | 69 +-------- interface/src/renderer/GeometryCache.h | 3 - interface/src/renderer/Model.cpp | 179 ++++------------------- interface/src/renderer/Model.h | 4 +- 5 files changed, 38 insertions(+), 221 deletions(-) diff --git a/interface/src/gpu/Resource.cpp b/interface/src/gpu/Resource.cpp index 3579f7145a..cd1b4ef84b 100644 --- a/interface/src/gpu/Resource.cpp +++ b/interface/src/gpu/Resource.cpp @@ -120,7 +120,7 @@ Resource::Size Resource::Sysmem::resize(Size size) { Resource::Size Resource::Sysmem::setData( Size size, const Byte* bytes ) { if (allocate(size) == size) { - if (bytes) { + if (size && bytes) { memcpy( _data, bytes, _size ); _stamp++; } @@ -129,7 +129,7 @@ Resource::Size Resource::Sysmem::setData( Size size, const Byte* bytes ) { } Resource::Size Resource::Sysmem::setSubData( Size offset, Size size, const Byte* bytes) { - if (((offset + size) <= getSize()) && bytes) { + if (size && ((offset + size) <= getSize()) && bytes) { memcpy( _data + offset, bytes, size ); _stamp++; return size; diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 85cbba585a..be00eebfea 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -743,7 +743,7 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { _geometry = geometry; foreach (const FBXMesh& mesh, _geometry.meshes) { - NetworkMesh networkMesh = { QOpenGLBuffer(QOpenGLBuffer::IndexBuffer), QOpenGLBuffer(QOpenGLBuffer::VertexBuffer) }; + NetworkMesh networkMesh; int totalIndices = 0; foreach (const FBXMeshPart& part, mesh.parts) { @@ -773,26 +773,9 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { totalIndices += (part.quadIndices.size() + part.triangleIndices.size()); } - /* - networkMesh.indexBuffer.create(); - networkMesh.indexBuffer.bind(); - networkMesh.indexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); - networkMesh.indexBuffer.allocate(totalIndices * sizeof(int)); - int offset = 0; - foreach (const FBXMeshPart& part, mesh.parts) { - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, part.quadIndices.size() * sizeof(int), - part.quadIndices.constData()); - offset += part.quadIndices.size() * sizeof(int); - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, part.triangleIndices.size() * sizeof(int), - part.triangleIndices.constData()); - offset += part.triangleIndices.size() * sizeof(int); - } - networkMesh.indexBuffer.release(); - */ + { networkMesh._indexBuffer = gpu::BufferPtr(new gpu::Buffer()); - //networkMesh._indexBuffer.bind(); - //networkMesh._indexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); networkMesh._indexBuffer->resize(totalIndices * sizeof(int)); int offset = 0; foreach(const FBXMeshPart& part, mesh.parts) { @@ -803,54 +786,8 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { (gpu::Resource::Byte*) part.triangleIndices.constData()); offset += part.triangleIndices.size() * sizeof(int); } - // networkMesh.indexBuffer.release(); } - /* networkMesh.vertexBuffer.create(); - networkMesh.vertexBuffer.bind(); - networkMesh.vertexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); - - // if we don't need to do any blending, the positions/normals can be static - if (mesh.blendshapes.isEmpty()) { - int normalsOffset = mesh.vertices.size() * sizeof(glm::vec3); - int tangentsOffset = normalsOffset + mesh.normals.size() * sizeof(glm::vec3); - int colorsOffset = tangentsOffset + mesh.tangents.size() * sizeof(glm::vec3); - int texCoordsOffset = colorsOffset + mesh.colors.size() * sizeof(glm::vec3); - int clusterIndicesOffset = texCoordsOffset + mesh.texCoords.size() * sizeof(glm::vec2); - int clusterWeightsOffset = clusterIndicesOffset + mesh.clusterIndices.size() * sizeof(glm::vec4); - - networkMesh.vertexBuffer.allocate(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4)); - networkMesh.vertexBuffer.write(0, mesh.vertices.constData(), mesh.vertices.size() * sizeof(glm::vec3)); - networkMesh.vertexBuffer.write(normalsOffset, mesh.normals.constData(), mesh.normals.size() * sizeof(glm::vec3)); - networkMesh.vertexBuffer.write(tangentsOffset, mesh.tangents.constData(), - mesh.tangents.size() * sizeof(glm::vec3)); - networkMesh.vertexBuffer.write(colorsOffset, mesh.colors.constData(), mesh.colors.size() * sizeof(glm::vec3)); - networkMesh.vertexBuffer.write(texCoordsOffset, mesh.texCoords.constData(), - mesh.texCoords.size() * sizeof(glm::vec2)); - networkMesh.vertexBuffer.write(clusterIndicesOffset, mesh.clusterIndices.constData(), - mesh.clusterIndices.size() * sizeof(glm::vec4)); - networkMesh.vertexBuffer.write(clusterWeightsOffset, mesh.clusterWeights.constData(), - mesh.clusterWeights.size() * sizeof(glm::vec4)); - - // otherwise, at least the cluster indices/weights can be static - } else { - int colorsOffset = mesh.tangents.size() * sizeof(glm::vec3); - int texCoordsOffset = colorsOffset + mesh.colors.size() * sizeof(glm::vec3); - int clusterIndicesOffset = texCoordsOffset + mesh.texCoords.size() * sizeof(glm::vec2); - int clusterWeightsOffset = clusterIndicesOffset + mesh.clusterIndices.size() * sizeof(glm::vec4); - networkMesh.vertexBuffer.allocate(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4)); - networkMesh.vertexBuffer.write(0, mesh.tangents.constData(), mesh.tangents.size() * sizeof(glm::vec3)); - networkMesh.vertexBuffer.write(colorsOffset, mesh.colors.constData(), mesh.colors.size() * sizeof(glm::vec3)); - networkMesh.vertexBuffer.write(texCoordsOffset, mesh.texCoords.constData(), - mesh.texCoords.size() * sizeof(glm::vec2)); - networkMesh.vertexBuffer.write(clusterIndicesOffset, mesh.clusterIndices.constData(), - mesh.clusterIndices.size() * sizeof(glm::vec4)); - networkMesh.vertexBuffer.write(clusterWeightsOffset, mesh.clusterWeights.constData(), - mesh.clusterWeights.size() * sizeof(glm::vec4)); - } - - networkMesh.vertexBuffer.release(); -*/ { networkMesh._vertexBuffer = gpu::BufferPtr(new gpu::Buffer()); // if we don't need to do any blending, the positions/normals can be static @@ -932,7 +869,7 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { } } - + _meshes.append(networkMesh); } diff --git a/interface/src/renderer/GeometryCache.h b/interface/src/renderer/GeometryCache.h index b968b64d9a..307c957511 100644 --- a/interface/src/renderer/GeometryCache.h +++ b/interface/src/renderer/GeometryCache.h @@ -155,9 +155,6 @@ public: /// The state associated with a single mesh. class NetworkMesh { public: - - QOpenGLBuffer indexBuffer; - QOpenGLBuffer vertexBuffer; gpu::BufferPtr _indexBuffer; gpu::BufferPtr _vertexBuffer; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 69fd30df89..758039b32a 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -405,32 +405,15 @@ bool Model::updateGeometry() { MeshState state; state.clusterMatrices.resize(mesh.clusters.size()); _meshStates.append(state); - - QOpenGLBuffer buffer; - if (!mesh.blendshapes.isEmpty()) { - buffer.setUsagePattern(QOpenGLBuffer::DynamicDraw); - buffer.create(); - buffer.bind(); - buffer.allocate((mesh.vertices.size() + mesh.normals.size()) * sizeof(glm::vec3)); - buffer.write(0, mesh.vertices.constData(), mesh.vertices.size() * sizeof(glm::vec3)); - buffer.write(mesh.vertices.size() * sizeof(glm::vec3), mesh.normals.constData(), - mesh.normals.size() * sizeof(glm::vec3)); - buffer.release(); - } - _blendedVertexBuffers.append(buffer); - gpu::BufferPtr buffer2(new gpu::Buffer()); + gpu::BufferPtr buffer(new gpu::Buffer()); if (!mesh.blendshapes.isEmpty()) { - //buffer.setUsagePattern(QOpenGLBuffer::DynamicDraw); - //buffer.create(); - //buffer.bind(); - buffer2->resize((mesh.vertices.size() + mesh.normals.size()) * sizeof(glm::vec3)); - buffer2->setSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.vertices.constData()); - buffer2->setSubData(mesh.vertices.size() * sizeof(glm::vec3), + buffer->resize((mesh.vertices.size() + mesh.normals.size()) * sizeof(glm::vec3)); + buffer->setSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.vertices.constData()); + buffer->setSubData(mesh.vertices.size() * sizeof(glm::vec3), mesh.normals.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.normals.constData()); - // buffer.release(); } - _blendedVertexBuffers2.push_back(buffer2); + _blendedVertexBuffers.push_back(buffer); } foreach (const FBXAttachment& attachment, fbxGeometry.attachments) { Model* model = new Model(this); @@ -572,8 +555,6 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) { // Let's introduce a gpu::Batch to capture all the calls to the graphics api gpu::Batch batch; - // GLBATCH(glEnableClientState)(GL_VERTEX_ARRAY); - // GLBATCH(glEnableClientState)(GL_NORMAL_ARRAY); GLBATCH(glDisable)(GL_COLOR_MATERIAL); @@ -688,6 +669,10 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) { GLBATCH(glDisableClientState)(GL_NORMAL_ARRAY); GLBATCH(glDisableClientState)(GL_VERTEX_ARRAY); GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY); + GLBATCH(glDisableClientState)(GL_COLOR_ARRAY); + GLBATCH(glDisableVertexAttribArray)(gpu::StreamFormat::SLOT_TANGENT); + GLBATCH(glDisableVertexAttribArray)(gpu::StreamFormat::SLOT_SKIN_CLUSTER_INDEX); + GLBATCH(glDisableVertexAttribArray)(gpu::StreamFormat::SLOT_SKIN_CLUSTER_WEIGHT); // bind with 0 to switch back to normal operation GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, 0); @@ -1414,7 +1399,7 @@ bool Model::maybeStartBlender() { void Model::setBlendedVertices(int blendNumber, const QWeakPointer& geometry, const QVector& vertices, const QVector& normals) { - if (_geometry != geometry || _blendedVertexBuffers.isEmpty() || blendNumber < _appliedBlendNumber) { + if (_geometry != geometry || _blendedVertexBuffers.empty() || blendNumber < _appliedBlendNumber) { return; } _appliedBlendNumber = blendNumber; @@ -1425,18 +1410,11 @@ void Model::setBlendedVertices(int blendNumber, const QWeakPointersetSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) vertices.constData() + index); - buffer2->setSubData(mesh.vertices.size() * sizeof(glm::vec3), - mesh.normals.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) normals.constData() + index); + gpu::BufferPtr& buffer = _blendedVertexBuffers[i]; + buffer->setSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) vertices.constData() + index*sizeof(glm::vec3)); + buffer->setSubData(mesh.vertices.size() * sizeof(glm::vec3), + mesh.normals.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) normals.constData() + index*sizeof(glm::vec3)); index += mesh.vertices.size(); } @@ -1462,7 +1440,6 @@ void Model::deleteGeometry() { } _attachments.clear(); _blendedVertexBuffers.clear(); - _blendedVertexBuffers2.clear(); _jointStates.clear(); _meshStates.clear(); clearShapes(); @@ -1822,11 +1799,8 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl activeProgram->link(); } GLBATCH(glUseProgram)(activeProgram->programId()); - // activeProgram->setUniformValue(activeLocations->alphaThreshold, alphaThreshold); GLBATCH(glUniform1f)(activeLocations->alphaThreshold, alphaThreshold); - - // i is the "index" from the original networkMeshes QVector... foreach (int i, list) { @@ -1842,9 +1816,6 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl const NetworkMesh& networkMesh = networkMeshes.at(i); const FBXMesh& mesh = geometry.meshes.at(i); - //const_cast(networkMesh.indexBuffer).bind(); - // GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, const_cast(networkMesh.indexBuffer).bufferId()); - // GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, gpu::GLBackend::getBufferID((*networkMesh._indexBuffer))); batch.setIndexBuffer(gpu::Element::TYPE_UINT32, (networkMesh._indexBuffer), 0); int vertexCount = mesh.vertices.size(); if (vertexCount == 0) { @@ -1878,12 +1849,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl continue; // skip this mesh } } - - //const_cast(networkMesh.vertexBuffer).bind(); - // GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, const_cast(networkMesh.vertexBuffer).bufferId()); - // if (!mesh.blendshapes.isEmpty()) { - // GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, gpu::GLBackend::getBufferID((*networkMesh._vertexBuffer))); - // } + GLBATCH(glPushMatrix)(); //Application::getInstance()->loadTranslatedViewMatrix(_translation); GLBATCH(glLoadMatrixf)((const GLfloat*)&Application::getInstance()->getUntranslatedViewMatrix()); @@ -1895,76 +1861,23 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl if (state.clusterMatrices.size() > 1) { GLBATCH(glUniformMatrix4fv)(skinLocations->clusterMatrices, state.clusterMatrices.size(), false, (const float*)state.clusterMatrices.constData()); - int offset = (mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3) + - mesh.texCoords.size() * sizeof(glm::vec2) + - (mesh.blendshapes.isEmpty() ? vertexCount * 2 * sizeof(glm::vec3) : 0); - //skinProgram->setAttributeBuffer(skinLocations->clusterIndices, GL_FLOAT, offset, 4); - /* GLBATCH(glVertexAttribPointer)(skinLocations->clusterIndices, 4, GL_FLOAT, GL_TRUE, 0, - reinterpret_cast(offset)); - */ //skinProgram->setAttributeBuffer(skinLocations->clusterWeights, GL_FLOAT, - // offset + vertexCount * sizeof(glm::vec4), 4); - - /* if (!mesh.blendshapes.isEmpty()) { - GLBATCH(glVertexAttribPointer)(skinLocations->clusterWeights, 4, GL_FLOAT, GL_TRUE, 0, (const void*) (offset + vertexCount * sizeof(glm::vec4))); - //skinProgram->enableAttributeArray(skinLocations->clusterIndices); - GLBATCH(glEnableVertexAttribArray)(skinLocations->clusterIndices); - //skinProgram->enableAttributeArray(skinLocations->clusterWeights); - GLBATCH(glEnableVertexAttribArray)(skinLocations->clusterWeights); - }*/ } else { GLBATCH(glMultMatrixf)((const GLfloat*)&state.clusterMatrices[0]); } if (mesh.blendshapes.isEmpty()) { - /* if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) { - //activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, vertexCount * 2 * sizeof(glm::vec3), 3); - GLBATCH(glVertexAttribPointer)(activeLocations->tangent, 3, GL_FLOAT, GL_TRUE, 0, (const void*)(vertexCount * 2 * sizeof(glm::vec3))); - //activeProgram->enableAttributeArray(activeLocations->tangent); - GLBATCH(glEnableVertexAttribArray)(activeLocations->tangent); - } - GLBATCH(glColorPointer)(3, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3) + - mesh.tangents.size() * sizeof(glm::vec3))); - GLBATCH(glTexCoordPointer)(2, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3) + - (mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3))); - */ - } else { - /* if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) { - //activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, 0, 3); - GLBATCH(glVertexAttribPointer)(activeLocations->tangent, 3, GL_FLOAT, GL_TRUE, 0, 0); - //activeProgram->enableAttributeArray(activeLocations->tangent); - GLBATCH(glEnableVertexAttribArray)(activeLocations->tangent); - } - GLBATCH(glColorPointer)(3, GL_FLOAT, 0, (void*)(mesh.tangents.size() * sizeof(glm::vec3))); - GLBATCH(glTexCoordPointer)(2, GL_FLOAT, 0, (void*)((mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3))); - */ - // _blendedVertexBuffers[i].bind(); - // GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, _blendedVertexBuffers[i].bufferId()); - // GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, gpu::GLBackend::getBufferID(*_blendedVertexBuffers2[i])); - batch.setInputBuffer(0, _blendedVertexBuffers2[i], 0, 0); - batch.setInputBuffer(1, _blendedVertexBuffers2[i], vertexCount * sizeof(glm::vec3), 0); - - } - if (!mesh.blendshapes.isEmpty()) { - - // GLBATCH(glVertexPointer)(3, GL_FLOAT, 0, 0); - // GLBATCH(glNormalPointer)(GL_FLOAT, 0, (void*)(vertexCount * sizeof(glm::vec3))); - /* - if (!mesh.colors.isEmpty()) { - GLBATCH(glEnableClientState)(GL_COLOR_ARRAY); - } else { - GLBATCH(glColor4f)(1.0f, 1.0f, 1.0f, 1.0f); - } - if (!mesh.texCoords.isEmpty()) { - GLBATCH(glEnableClientState)(GL_TEXTURE_COORD_ARRAY); - }*/ - batch.setInputFormat(networkMesh._vertexFormat); - batch.setInputStream(2, networkMesh._vertexStream); - } - else{ batch.setInputFormat(networkMesh._vertexFormat); batch.setInputStream(0, networkMesh._vertexStream); + } else { + batch.setInputFormat(networkMesh._vertexFormat); + batch.setInputBuffer(0, _blendedVertexBuffers[i], 0, sizeof(glm::vec3)); + batch.setInputBuffer(1, _blendedVertexBuffers[i], vertexCount * sizeof(glm::vec3), sizeof(glm::vec3)); + batch.setInputStream(2, networkMesh._vertexStream); + } + + if (mesh.colors.isEmpty()) { + GLBATCH(glColor4f)(1.0f, 1.0f, 1.0f, 1.0f); } - qint64 offset = 0; for (int j = 0; j < networkMesh.parts.size(); j++) { @@ -2032,24 +1945,12 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl meshPartsRendered++; if (part.quadIndices.size() > 0) { - /* if (!mesh.blendshapes.isEmpty()) { - GLBATCH(glDrawRangeElements)(GL_QUADS, 0, vertexCount - 1, part.quadIndices.size(), GL_UNSIGNED_INT, (void*)offset); - } - else {*/ - batch.drawIndexed(gpu::PRIMITIVE_QUADS, part.quadIndices.size(), offset); - // } - offset += part.quadIndices.size() * sizeof(int); - - + batch.drawIndexed(gpu::PRIMITIVE_QUADS, part.quadIndices.size(), offset); + offset += part.quadIndices.size() * sizeof(int); } - + if (part.triangleIndices.size() > 0) { - /* if (!mesh.blendshapes.isEmpty()) { - GLBATCH(glDrawRangeElements)(GL_TRIANGLES, 0, vertexCount - 1, part.triangleIndices.size(), - GL_UNSIGNED_INT, (void*)offset); - } else {*/ - batch.drawIndexed(gpu::PRIMITIVE_TRIANGLES, part.triangleIndices.size(), offset); - // } + batch.drawIndexed(gpu::PRIMITIVE_TRIANGLES, part.triangleIndices.size(), offset); offset += part.triangleIndices.size() * sizeof(int); } @@ -2060,39 +1961,23 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl args->_quadsRendered += part.quadIndices.size() / INDICES_PER_QUAD; } } - /** - if (!mesh.colors.isEmpty()) { - GLBATCH(glDisableClientState)(GL_COLOR_ARRAY); - } - if (!mesh.texCoords.isEmpty()) { - GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY); - } - */ + if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) { GLBATCH(glActiveTexture)(GL_TEXTURE1); GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); GLBATCH(glActiveTexture)(GL_TEXTURE0); - - // activeProgram->disableAttributeArray(activeLocations->tangent); - // GLBATCH(glDisableVertexAttribArray)(activeLocations->tangent); } - + if (specularTextureUnit) { GLBATCH(glActiveTexture)(specularTextureUnit); GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); GLBATCH(glActiveTexture)(GL_TEXTURE0); } - - if (state.clusterMatrices.size() > 1) { - // skinProgram->disableAttributeArray(skinLocations->clusterIndices); - // GLBATCH(glDisableVertexAttribArray)(skinLocations->clusterIndices); - // skinProgram->disableAttributeArray(skinLocations->clusterWeights); - // GLBATCH(glDisableVertexAttribArray)(skinLocations->clusterWeights); - } + GLBATCH(glPopMatrix)(); } - //activeProgram->release(); + GLBATCH(glUseProgram)(0); return meshPartsRendered; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index e8b3c0a298..34d6a34c06 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -281,10 +281,8 @@ private: QVector _blendshapeCoefficients; QUrl _url; - - QVector _blendedVertexBuffers; - gpu::Buffers _blendedVertexBuffers2; + gpu::Buffers _blendedVertexBuffers; QVector > > _dilatedTextures; From c7b8f7a792ec067c6d510c4611e8c3a17b6a9b44 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 4 Nov 2014 14:00:02 +0100 Subject: [PATCH 09/39] remove debug #if --- assignment-client/src/audio/AudioMixer.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 6ca93a7b11..d3729536f6 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -400,15 +400,12 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(AudioMixerClientData* l penumbraFilterGainR += (1.f - penumbraFilterGainR) * (1.f - distanceBetween / RADIUS_OF_HEAD); } - -#if 0 - qDebug() << "gainL=" - << penumbraFilterGainL - << "gainR=" - << penumbraFilterGainR - << "angle=" - << -bearingRelativeAngleToSource; -#endif + bool wantDebug = false; + if (wantDebug) { + qDebug() << "gainL=" << penumbraFilterGainL + << "gainR=" << penumbraFilterGainR + << "angle=" << -bearingRelativeAngleToSource; + } // Get our per listener/source data so we can get our filter AudioFilterHSF1s& penumbraFilter = listenerNodeData->getListenerSourcePairData(streamUUID)->getPenumbraFilter(); From fb33634171aa9d4430e6afd84caa565d1b3994bb Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 4 Nov 2014 16:44:39 +0100 Subject: [PATCH 10/39] ignore penumbra member variable --- assignment-client/src/audio/AudioMixer.cpp | 2 +- libraries/audio/src/InboundAudioStream.cpp | 3 ++- libraries/audio/src/InboundAudioStream.h | 8 ++++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index d3729536f6..4cf97b79ca 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -353,7 +353,7 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(AudioMixerClientData* l } } - if (!sourceIsSelf && _enableFilter) { + if (!sourceIsSelf && _enableFilter && !streamToAdd->ignorePenumbraFilter()) { const float TWO_OVER_PI = 2.0f / PI; diff --git a/libraries/audio/src/InboundAudioStream.cpp b/libraries/audio/src/InboundAudioStream.cpp index 366659b633..5cb7697de6 100644 --- a/libraries/audio/src/InboundAudioStream.cpp +++ b/libraries/audio/src/InboundAudioStream.cpp @@ -45,7 +45,8 @@ InboundAudioStream::InboundAudioStream(int numFrameSamples, int numFramesCapacit _currentJitterBufferFrames(0), _timeGapStatsForStatsPacket(0, STATS_FOR_STATS_PACKET_WINDOW_SECONDS), _repetitionWithFade(settings._repetitionWithFade), - _hasReverb(false) + _hasReverb(false), + _ignorePenumbra(false) { } diff --git a/libraries/audio/src/InboundAudioStream.h b/libraries/audio/src/InboundAudioStream.h index ad2b7266ed..94ee9ce43e 100644 --- a/libraries/audio/src/InboundAudioStream.h +++ b/libraries/audio/src/InboundAudioStream.h @@ -47,6 +47,7 @@ const bool DEFAULT_REPETITION_WITH_FADE = true; // Audio Env bitset const int HAS_REVERB_BIT = 0; // 1st bit +const int IGNORE_PENUMBRA = 1; // 2nd bit class InboundAudioStream : public NodeData { Q_OBJECT @@ -113,10 +114,8 @@ public: bool lastPopSucceeded() const { return _lastPopSucceeded; }; const AudioRingBuffer::ConstIterator& getLastPopOutput() const { return _lastPopOutput; } - void setToStarved(); - void setSettings(const Settings& settings); void setMaxFramesOverDesired(int maxFramesOverDesired) { _maxFramesOverDesired = maxFramesOverDesired; } @@ -164,6 +163,8 @@ public: void setReverb(float reverbTime, float wetLevel); void clearReverb() { _hasReverb = false; } + bool ignorePenumbraFilter() { return _ignorePenumbra; } + public slots: /// This function should be called every second for all the stats to function properly. If dynamic jitter buffers /// is enabled, those stats are used to calculate _desiredJitterBufferFrames. @@ -257,6 +258,9 @@ protected: bool _hasReverb; float _reverbTime; float _wetLevel; + + // Ignore penumbra filter + bool _ignorePenumbra; }; float calculateRepeatedFrameFadeFactor(int indexOfRepeat); From c842060dc5057b8e5871af38ceb6823261591c3b Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 4 Nov 2014 14:51:57 -0800 Subject: [PATCH 11/39] fix names for stream and Batch interface --- interface/src/gpu/Batch.cpp | 26 ++-- interface/src/gpu/Batch.h | 22 +--- interface/src/gpu/Format.h | 150 ++++++++++++++--------- interface/src/gpu/GLBackend.cpp | 70 +++++------ interface/src/gpu/GLBackend.h | 23 ++-- interface/src/gpu/Resource.h | 4 +- interface/src/gpu/Stream.cpp | 12 +- interface/src/gpu/Stream.h | 124 ++++++++++--------- interface/src/renderer/GeometryCache.cpp | 40 +++--- interface/src/renderer/GeometryCache.h | 8 +- interface/src/renderer/Model.cpp | 22 ++-- interface/src/ui/TextRenderer.cpp | 12 +- interface/src/ui/TextRenderer.h | 8 +- 13 files changed, 273 insertions(+), 248 deletions(-) diff --git a/interface/src/gpu/Batch.cpp b/interface/src/gpu/Batch.cpp index 7e36854769..e213007191 100644 --- a/interface/src/gpu/Batch.cpp +++ b/interface/src/gpu/Batch.cpp @@ -16,7 +16,7 @@ using namespace gpu; -const int Element::TYPE_SIZE[Element::NUM_TYPES] = { +const int TYPE_SIZE[NUM_TYPES] = { 4, 4, 4, @@ -35,7 +35,7 @@ const int Element::TYPE_SIZE[Element::NUM_TYPES] = { 1 }; -const int Element::DIMENSION_COUNT[Element::NUM_DIMENSIONS] = { +const int DIMENSION_COUNT[NUM_DIMENSIONS] = { 1, 2, 3, @@ -123,26 +123,24 @@ void Batch::drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, ui _params.push_back(nbInstances); } -void Batch::setInputFormat(const StreamFormatPtr format) { +void Batch::setInputFormat(const Stream::FormatPointer& format) { ADD_COMMAND(setInputFormat); _params.push_back(_streamFormats.cache(format)); } -void Batch::setInputStream(uint8 startChannel, const StreamPtr& stream) { - if (!stream.isNull()) { - if (stream->getNumBuffers()) { - const Buffers& buffers = stream->getBuffers(); - const Offsets& offsets = stream->getOffsets(); - const Offsets& strides = stream->getStrides(); - for (int i = 0; i < buffers.size(); i++) { - setInputBuffer(startChannel + i, buffers[i], offsets[i], strides[i]); - } +void Batch::setInputStream(Slot startChannel, const BufferStream& stream) { + if (stream.getNumBuffers()) { + const Buffers& buffers = stream.getBuffers(); + const Offsets& offsets = stream.getOffsets(); + const Offsets& strides = stream.getStrides(); + for (int i = 0; i < buffers.size(); i++) { + setInputBuffer(startChannel + i, buffers[i], offsets[i], strides[i]); } } } -void Batch::setInputBuffer(uint8 channel, const BufferPtr& buffer, Offset offset, Offset stride) { +void Batch::setInputBuffer(Slot channel, const BufferPointer& buffer, Offset offset, Offset stride) { ADD_COMMAND(setInputBuffer); _params.push_back(stride); @@ -151,7 +149,7 @@ void Batch::setInputBuffer(uint8 channel, const BufferPtr& buffer, Offset offset _params.push_back(channel); } -void Batch::setIndexBuffer(Element::Type type, const BufferPtr& buffer, Offset offset) { +void Batch::setIndexBuffer(Type type, const BufferPointer& buffer, Offset offset) { ADD_COMMAND(setIndexBuffer); _params.push_back(offset); diff --git a/interface/src/gpu/Batch.h b/interface/src/gpu/Batch.h index fc789320b8..c894afc99a 100644 --- a/interface/src/gpu/Batch.h +++ b/interface/src/gpu/Batch.h @@ -39,12 +39,6 @@ namespace gpu { -class Buffer; -class Resource; - -typedef int Stamp; - - enum Primitive { PRIMITIVE_POINTS = 0, PRIMITIVE_LINES, @@ -56,11 +50,9 @@ enum Primitive { NUM_PRIMITIVES, }; -typedef std::vector< BufferPtr > Buffers; -typedef std::vector< Offset > Offsets; - class Batch { public: + typedef Stream::Slot Slot; Batch(); Batch(const Batch& batch); @@ -73,12 +65,12 @@ public: void drawInstanced(uint32 nbInstances, Primitive primitiveType, uint32 nbVertices, uint32 startVertex = 0, uint32 startInstance = 0); void drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, uint32 nbIndices, uint32 startIndex = 0, uint32 startInstance = 0); - void setInputFormat(const StreamFormatPtr format); + void setInputFormat(const Stream::FormatPointer& format); - void setInputStream(uint8 startChannel, const StreamPtr& stream); // not a command, just multiples - void setInputBuffer(uint8 channel, const BufferPtr& buffer, Offset offset, Offset stride); + void setInputStream(Slot startChannel, const BufferStream& stream); // not a command, just unroll into a loop of setInputBuffer + void setInputBuffer(Slot channel, const BufferPointer& buffer, Offset offset, Offset stride); - void setIndexBuffer(Element::Type type, const BufferPtr& buffer, Offset offset); + void setIndexBuffer(Type type, const BufferPointer& buffer, Offset offset); // TODO: As long as we have gl calls explicitely issued from interface @@ -272,8 +264,7 @@ public: }; typedef Cache::Vector BufferCaches; - typedef Cache::Vector StreamCaches; - typedef Cache::Vector StreamFormatCaches; + typedef Cache::Vector StreamFormatCaches; typedef unsigned char Byte; typedef std::vector Bytes; @@ -306,7 +297,6 @@ public: Resources _resources; BufferCaches _buffers; - StreamCaches _streams; StreamFormatCaches _streamFormats; Bytes _data; diff --git a/interface/src/gpu/Format.h b/interface/src/gpu/Format.h index f0cfe52ddf..a372d4086e 100644 --- a/interface/src/gpu/Format.h +++ b/interface/src/gpu/Format.h @@ -17,72 +17,102 @@ namespace gpu { - typedef unsigned int uint32; - typedef int int32; - typedef unsigned short uint16; - typedef short int16; - typedef unsigned char uint8; - typedef char int8; +typedef unsigned int uint32; +typedef int int32; +typedef unsigned short uint16; +typedef short int16; +typedef unsigned char uint8; +typedef char int8; - typedef uint32 Offset; +typedef uint32 Offset; -// Format is a simple 32bit value that contains everything we need to know about an element +// Description of a scalar type +enum Type { + + TYPE_FLOAT = 0, + TYPE_INT32, + TYPE_UINT32, + TYPE_HALF, + TYPE_INT16, + TYPE_UINT16, + TYPE_INT8, + TYPE_UINT8, + + TYPE_NFLOAT, + TYPE_NINT32, + TYPE_NUINT32, + TYPE_NHALF, + TYPE_NINT16, + TYPE_NUINT16, + TYPE_NINT8, + TYPE_NUINT8, + + NUM_TYPES, +}; +// Array providing the size in bytes for a given scalar type +static const int TYPE_SIZE[NUM_TYPES] = { + 4, + 4, + 4, + 2, + 2, + 2, + 1, + 1, + 4, + 4, + 4, + 2, + 2, + 2, + 1, + 1 +}; + + +// Dimension of an Element +enum Dimension { + DIM_SCALAR = 0, + DIM_VEC2, + DIM_VEC3, + DIM_VEC4, + DIM_MAT3, + DIM_MAT4, + + NUM_DIMENSIONS, +}; +// Count (of scalars) in an Element for a given Dimension +static const int DIMENSION_COUNT[NUM_DIMENSIONS] = { + 1, + 2, + 3, + 4, + 9, + 16 +}; + +// Semantic of an Element +// Provide information on how to use the element +enum Semantic { + SEMANTIC_RGB = 0, + SEMANTIC_RGBA, + SEMANTIC_XYZ, + SEMANTIC_XYZW, + SEMANTIC_POS_XYZ, + SEMANTIC_POS_XYZW, + SEMANTIC_QUAT, + SEMANTIC_DIR_XYZ, + SEMANTIC_UV, + SEMANTIC_R8, + + NUM_SEMANTICS, +}; + +// Element is a simple 16bit value that contains everything we need to know about an element // of a buffer, a pixel of a texture, a varying input/output or uniform from a shader pipeline. // Type and dimension of the element, and semantic class Element { public: - - enum Type { - - TYPE_FLOAT = 0, - TYPE_INT32, - TYPE_UINT32, - TYPE_HALF, - TYPE_INT16, - TYPE_UINT16, - TYPE_INT8, - TYPE_UINT8, - - TYPE_NFLOAT, - TYPE_NINT32, - TYPE_NUINT32, - TYPE_NHALF, - TYPE_NINT16, - TYPE_NUINT16, - TYPE_NINT8, - TYPE_NUINT8, - - NUM_TYPES, - }; - static const int TYPE_SIZE[NUM_TYPES]; - - enum Dimension { - DIM_SCALAR = 0, - DIM_VEC2, - DIM_VEC3, - DIM_VEC4, - DIM_MAT3, - DIM_MAT4, - - NUM_DIMENSIONS, - }; - static const int DIMENSION_COUNT[NUM_DIMENSIONS]; - - enum Semantic { - SEMANTIC_RGB = 0, - SEMANTIC_RGBA, - SEMANTIC_XYZ, - SEMANTIC_XYZW, - SEMANTIC_POS_XYZ, - SEMANTIC_POS_XYZW, - SEMANTIC_QUAT, - SEMANTIC_DIR_XYZ, - SEMANTIC_UV, - SEMANTIC_R8, - - NUM_SEMANTICS, - }; - Element(Dimension dim, Type type, Semantic sem) : _semantic(sem), _dimension(dim), diff --git a/interface/src/gpu/GLBackend.cpp b/interface/src/gpu/GLBackend.cpp index 8a38b30ae2..6d9676ac68 100644 --- a/interface/src/gpu/GLBackend.cpp +++ b/interface/src/gpu/GLBackend.cpp @@ -81,7 +81,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_glMaterialfv), }; -const GLenum GLBackend::_primitiveToGLmode[NUM_PRIMITIVES] = { +static const GLenum _primitiveToGLmode[NUM_PRIMITIVES] = { GL_POINTS, GL_LINES, GL_LINE_STRIP, @@ -90,7 +90,7 @@ const GLenum GLBackend::_primitiveToGLmode[NUM_PRIMITIVES] = { GL_QUADS, }; -static const GLenum _elementTypeToGLType[Element::NUM_TYPES]= { +static const GLenum _elementTypeToGLType[NUM_TYPES]= { GL_FLOAT, GL_INT, GL_UNSIGNED_INT, @@ -116,10 +116,10 @@ GLBackend::GLBackend() : _inputAttributeActivation(0), _needInputFormatUpdate(true), - _vertexBuffersState(0), - _vertexBuffers(_vertexBuffersState.size(), BufferPtr(0)), - _vertexBufferOffsets(_vertexBuffersState.size(), 0), - _vertexBufferStrides(_vertexBuffersState.size(), 0), + _inputBuffersState(0), + _inputBuffers(_inputBuffersState.size(), BufferPointer(0)), + _inputBufferOffsets(_inputBuffersState.size(), 0), + _inputBufferStrides(_inputBuffersState.size(), 0), _indexBuffer(0), _indexBufferOffset(0) @@ -216,7 +216,7 @@ void GLBackend::do_drawIndexedInstanced(Batch& batch, uint32 paramOffset) { } void GLBackend::do_setInputFormat(Batch& batch, uint32 paramOffset) { - StreamFormatPtr format = batch._streamFormats.get(batch._params[paramOffset]._uint); + Stream::FormatPointer format = batch._streamFormats.get(batch._params[paramOffset]._uint); if (format != _inputFormat) { _inputFormat = format; @@ -227,20 +227,20 @@ void GLBackend::do_setInputFormat(Batch& batch, uint32 paramOffset) { void GLBackend::do_setInputBuffer(Batch& batch, uint32 paramOffset) { Offset stride = batch._params[paramOffset + 0]._uint; Offset offset = batch._params[paramOffset + 1]._uint; - BufferPtr buffer = batch._buffers.get(batch._params[paramOffset + 2]._uint); + BufferPointer buffer = batch._buffers.get(batch._params[paramOffset + 2]._uint); uint32 channel = batch._params[paramOffset + 3]._uint; if (channel < getNumInputBuffers()) { - _vertexBuffers[channel] = buffer; - _vertexBufferOffsets[channel] = offset; - _vertexBufferStrides[channel] = stride; - _vertexBuffersState.set(channel); + _inputBuffers[channel] = buffer; + _inputBufferOffsets[channel] = offset; + _inputBufferStrides[channel] = stride; + _inputBuffersState.set(channel); } } #define SUPPORT_LEGACY_OPENGL #if defined(SUPPORT_LEGACY_OPENGL) -static const int NUM_CLASSIC_ATTRIBS = StreamFormat::SLOT_TANGENT; +static const int NUM_CLASSIC_ATTRIBS = Stream::INPUT_SLOT_TANGENT; static const GLenum attributeSlotToClassicAttribName[NUM_CLASSIC_ATTRIBS] = { GL_VERTEX_ARRAY, GL_NORMAL_ARRAY, @@ -250,16 +250,16 @@ static const GLenum attributeSlotToClassicAttribName[NUM_CLASSIC_ATTRIBS] = { #endif void GLBackend::updateInput() { - if (_needInputFormatUpdate || _vertexBuffersState.any()) { + if (_needInputFormatUpdate || _inputBuffersState.any()) { if (_needInputFormatUpdate) { InputActivationCache newActivation; // Check expected activation if (_inputFormat) { - const StreamFormat::AttributeMap& attributes = _inputFormat->getAttributes(); - for (StreamFormat::AttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); it++) { - const StreamFormat::Attribute& attrib = (*it).second; + const Stream::Format::AttributeMap& attributes = _inputFormat->getAttributes(); + for (Stream::Format::AttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); it++) { + const Stream::Attribute& attrib = (*it).second; newActivation.set(attrib._slot); } } @@ -295,27 +295,27 @@ void GLBackend::updateInput() { // now we need to bind the buffers and assign the attrib pointers if (_inputFormat) { - const Buffers& buffers = _vertexBuffers; - const Offsets& offsets = _vertexBufferOffsets; - const Offsets& strides = _vertexBufferStrides; + const Buffers& buffers = _inputBuffers; + const Offsets& offsets = _inputBufferOffsets; + const Offsets& strides = _inputBufferStrides; - const StreamFormat::AttributeMap& attributes = _inputFormat->getAttributes(); + const Stream::Format::AttributeMap& attributes = _inputFormat->getAttributes(); - for (StreamFormat::ChannelMap::const_iterator channelIt = _inputFormat->getChannels().begin(); + for (Stream::Format::ChannelMap::const_iterator channelIt = _inputFormat->getChannels().begin(); channelIt != _inputFormat->getChannels().end(); channelIt++) { - const StreamFormat::ChannelMap::value_type::second_type& channel = (*channelIt).second; + const Stream::Format::ChannelMap::value_type::second_type& channel = (*channelIt).second; if ((*channelIt).first < buffers.size()) { int bufferNum = (*channelIt).first; - if (_vertexBuffersState.at(bufferNum) || _needInputFormatUpdate) { + if (_inputBuffersState.at(bufferNum) || _needInputFormatUpdate) { GLuint vbo = gpu::GLBackend::getBufferID((*buffers[bufferNum])); glBindBuffer(GL_ARRAY_BUFFER, vbo); CHECK_GL_ERROR(); - _vertexBuffersState[bufferNum] = false; + _inputBuffersState[bufferNum] = false; for (int i = 0; i < channel._slots.size(); i++) { - const StreamFormat::Attribute& attrib = attributes.at(channel._slots[i]); + const Stream::Attribute& attrib = attributes.at(channel._slots[i]); GLuint slot = attrib._slot; GLuint count = attrib._element.getDimensionCount(); GLenum type = _elementTypeToGLType[attrib._element.getType()]; @@ -324,18 +324,18 @@ void GLBackend::updateInput() { #if defined(SUPPORT_LEGACY_OPENGL) if (slot < NUM_CLASSIC_ATTRIBS) { switch (slot) { - case StreamFormat::SLOT_POSITION: + case Stream::INPUT_SLOT_POSITION: glVertexPointer(count, type, stride, (GLvoid*)pointer); break; - case StreamFormat::SLOT_COLOR: + case Stream::INPUT_SLOT_NORMAL: + glNormalPointer(type, stride, (GLvoid*)pointer); + break; + case Stream::INPUT_SLOT_COLOR: glColorPointer(count, type, stride, (GLvoid*)pointer); break; - case StreamFormat::SLOT_TEXCOORD: + case Stream::INPUT_SLOT_TEXCOORD: glTexCoordPointer(count, type, stride, (GLvoid*)pointer); break; - case StreamFormat::SLOT_NORMAL: - glNormalPointer(type, stride, (GLvoid*)pointer); - break; }; } else { #else @@ -354,7 +354,7 @@ void GLBackend::updateInput() { _needInputFormatUpdate = false; } -/* Fancy version GL4.4 +/* TODO: Fancy version GL4.4 if (_needInputFormatUpdate) { InputActivationCache newActivation; @@ -412,8 +412,8 @@ void GLBackend::updateInput() { void GLBackend::do_setIndexBuffer(Batch& batch, uint32 paramOffset) { - _indexBufferType = (Element::Type) batch._params[paramOffset + 2]._uint; - BufferPtr indexBuffer = batch._buffers.get(batch._params[paramOffset + 1]._uint); + _indexBufferType = (Type) batch._params[paramOffset + 2]._uint; + BufferPointer indexBuffer = batch._buffers.get(batch._params[paramOffset + 1]._uint); _indexBufferOffset = batch._params[paramOffset + 0]._uint; _indexBuffer = indexBuffer; if (indexBuffer) { diff --git a/interface/src/gpu/GLBackend.h b/interface/src/gpu/GLBackend.h index a3bd483f89..2cce6cbedc 100644 --- a/interface/src/gpu/GLBackend.h +++ b/interface/src/gpu/GLBackend.h @@ -45,25 +45,25 @@ public: static GLuint getBufferID(const Buffer& buffer); - static const int MAX_NUM_ATTRIBUTES = StreamFormat::NUM_SLOTS; + static const int MAX_NUM_ATTRIBUTES = Stream::NUM_INPUT_SLOTS; static const int MAX_NUM_INPUT_BUFFERS = 16; - uint32 getNumInputBuffers() const { return _vertexBuffersState.size(); } + uint32 getNumInputBuffers() const { return _inputBuffersState.size(); } protected: bool _needInputFormatUpdate; - StreamFormatPtr _inputFormat; + Stream::FormatPointer _inputFormat; typedef std::bitset InputBuffersState; - InputBuffersState _vertexBuffersState; - Buffers _vertexBuffers; - Offsets _vertexBufferOffsets; - Offsets _vertexBufferStrides; + InputBuffersState _inputBuffersState; + Buffers _inputBuffers; + Offsets _inputBufferOffsets; + Offsets _inputBufferStrides; - BufferPtr _indexBuffer; + BufferPointer _indexBuffer; Offset _indexBufferOffset; - Element::Type _indexBufferType; + Type _indexBufferType; typedef std::bitset InputActivationCache; InputActivationCache _inputAttributeActivation; @@ -138,11 +138,6 @@ protected: typedef void (GLBackend::*CommandCall)(Batch&, uint32); static CommandCall _commandCalls[Batch::NUM_COMMANDS]; - static const GLenum _primitiveToGLmode[NUM_PRIMITIVES]; - - static const GLenum _elementTypeToGLtype[Element::NUM_TYPES]; - - }; diff --git a/interface/src/gpu/Resource.h b/interface/src/gpu/Resource.h index d5305744ac..52108c215a 100644 --- a/interface/src/gpu/Resource.h +++ b/interface/src/gpu/Resource.h @@ -147,8 +147,8 @@ protected: friend class Backend; }; -typedef QSharedPointer BufferPtr; -typedef std::vector< BufferPtr > Buffers; +typedef QSharedPointer BufferPointer; +typedef std::vector< BufferPointer > Buffers; }; diff --git a/interface/src/gpu/Stream.cpp b/interface/src/gpu/Stream.cpp index 953efd57a2..68b1392f73 100644 --- a/interface/src/gpu/Stream.cpp +++ b/interface/src/gpu/Stream.cpp @@ -13,7 +13,7 @@ using namespace gpu; -void StreamFormat::evaluateCache() { +void Stream::Format::evaluateCache() { _channels.clear(); _elementTotalSize = 0; for(AttributeMap::iterator it = _attributes.begin(); it != _attributes.end(); it++) { @@ -26,24 +26,24 @@ void StreamFormat::evaluateCache() { } } -bool StreamFormat::setAttribute(Slot slot, uint8 channel, Element element, Offset offset, Frequency frequency) { - _attributes[slot] = Attribute(slot, channel, element, offset, frequency); +bool Stream::Format::setAttribute(Slot slot, Slot channel, Element element, Offset offset, Frequency frequency) { + _attributes[slot] = Attribute((InputSlot) slot, channel, element, offset, frequency); evaluateCache(); return true; } -Stream::Stream() : +BufferStream::BufferStream() : _buffers(), _offsets() {} -Stream::~Stream() +BufferStream::~BufferStream() { _buffers.clear(); _offsets.clear(); } -void Stream::addBuffer(BufferPtr& buffer, uint32 offset, uint32 stride) { +void BufferStream::addBuffer(BufferPointer& buffer, Offset offset, Offset stride) { _buffers.push_back(buffer); _offsets.push_back(offset); _strides.push_back(stride); diff --git a/interface/src/gpu/Stream.h b/interface/src/gpu/Stream.h index 81ca344199..21d4ea422c 100644 --- a/interface/src/gpu/Stream.h +++ b/interface/src/gpu/Stream.h @@ -21,31 +21,36 @@ namespace gpu { -class StreamFormat { +// Stream namespace class +class Stream { public: - enum Slot { - SLOT_POSITION = 0, - SLOT_NORMAL, - SLOT_COLOR, - SLOT_TEXCOORD, - SLOT_TANGENT, - SLOT_SKIN_CLUSTER_INDEX, - SLOT_SKIN_CLUSTER_WEIGHT, + // Possible input slots identifiers + enum InputSlot { + INPUT_SLOT_POSITION = 0, + INPUT_SLOT_NORMAL, + INPUT_SLOT_COLOR, + INPUT_SLOT_TEXCOORD, + INPUT_SLOT_TANGENT, + INPUT_SLOT_SKIN_CLUSTER_INDEX, + INPUT_SLOT_SKIN_CLUSTER_WEIGHT, - NUM_SLOTS, + NUM_INPUT_SLOTS, }; + typedef uint8 Slot; + + // Frequency describer enum Frequency { FREQUENCY_PER_VERTEX = 0, FREQUENCY_PER_INSTANCE, }; + // The attribute description + // Every thing that is needed to detail a stream attribute and how to interpret it class Attribute { public: - typedef std::vector< Attribute > vector; - - Attribute(Slot slot, uint8 channel, Element element, Offset offset = 0, Frequency frequency = FREQUENCY_PER_VERTEX) : + Attribute(Slot slot, Slot channel, Element element, Offset offset = 0, Frequency frequency = FREQUENCY_PER_VERTEX) : _slot(slot), _channel(channel), _element(element), @@ -53,7 +58,7 @@ public: _frequency(frequency) {} Attribute() : - _slot(SLOT_POSITION), + _slot(INPUT_SLOT_POSITION), _channel(0), _element(), _offset(0), @@ -61,63 +66,71 @@ public: {} - uint8 _slot; // Logical slot assigned to the attribute - uint8 _channel; // index of the channel where to get the data from + Slot _slot; // Logical slot assigned to the attribute + Slot _channel; // index of the channel where to get the data from Element _element; Offset _offset; uint32 _frequency; + // Size of the uint32 getSize() const { return _element.getSize(); } - }; - typedef std::map< uint8, Attribute > AttributeMap; - - class Channel { + // Stream Format is describing how to feed a list of attributes from a bunch of stream buffer channels + class Format { public: - std::vector< uint8 > _slots; - std::vector< uint32 > _offsets; - uint32 _stride; - uint32 _netSize; + typedef std::map< Slot, Attribute > AttributeMap; - Channel() : _stride(0), _netSize(0) {} + class Channel { + public: + std::vector< Slot > _slots; + std::vector< Offset > _offsets; + Offset _stride; + uint32 _netSize; + + Channel() : _stride(0), _netSize(0) {} + }; + typedef std::map< Slot, Channel > ChannelMap; + + Format() : + _attributes(), + _elementTotalSize(0) {} + ~Format() {} + + uint32 getNumAttributes() const { return _attributes.size(); } + const AttributeMap& getAttributes() const { return _attributes; } + + uint8 getNumChannels() const { return _channels.size(); } + const ChannelMap& getChannels() const { return _channels; } + + uint32 getElementTotalSize() const { return _elementTotalSize; } + + bool setAttribute(Slot slot, Slot channel, Element element, Offset offset = 0, Frequency frequency = FREQUENCY_PER_VERTEX); + + protected: + AttributeMap _attributes; + ChannelMap _channels; + uint32 _elementTotalSize; + + void evaluateCache(); }; - typedef std::map< uint8, Channel > ChannelMap; - StreamFormat() : - _attributes(), - _elementTotalSize(0) {} - ~StreamFormat() {} - - uint32 getNumAttributes() const { return _attributes.size(); } - const AttributeMap& getAttributes() const { return _attributes; } - - uint8 getNumChannels() const { return _channels.size(); } - const ChannelMap& getChannels() const { return _channels; } - - uint32 getElementTotalSize() const { return _elementTotalSize; } - - bool setAttribute(Slot slot, uint8 channel, Element element, Offset offset = 0, Frequency frequency = FREQUENCY_PER_VERTEX); - -protected: - AttributeMap _attributes; - ChannelMap _channels; - uint32 _elementTotalSize; - - void evaluateCache(); + typedef QSharedPointer FormatPointer; }; -class Stream { +typedef std::vector< Offset > Offsets; + +// Buffer Stream is a container of N Buffers and their respective Offsets and Srides representing N consecutive channels. +// A Buffer Stream can be assigned to the Batch to set several stream channels in one call +class BufferStream { public: - typedef std::vector< BufferPtr > Buffers; - typedef std::vector< uint32 > Offsets; - typedef std::vector< uint32 > Strides; + typedef Offsets Strides; - Stream(); - ~Stream(); + BufferStream(); + ~BufferStream(); - void addBuffer(BufferPtr& buffer, uint32 offset, uint32 stride); + void addBuffer(BufferPointer& buffer, Offset offset, Offset stride); const Buffers& getBuffers() const { return _buffers; } const Offsets& getOffsets() const { return _offsets; } @@ -129,8 +142,7 @@ protected: Offsets _offsets; Strides _strides; }; -typedef QSharedPointer StreamFormatPtr; -typedef QSharedPointer StreamPtr; +typedef QSharedPointer BufferStreamPointer; }; diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index be00eebfea..9249b33031 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -775,7 +775,7 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { } { - networkMesh._indexBuffer = gpu::BufferPtr(new gpu::Buffer()); + networkMesh._indexBuffer = gpu::BufferPointer(new gpu::Buffer()); networkMesh._indexBuffer->resize(totalIndices * sizeof(int)); int offset = 0; foreach(const FBXMeshPart& part, mesh.parts) { @@ -789,7 +789,7 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { } { - networkMesh._vertexBuffer = gpu::BufferPtr(new gpu::Buffer()); + networkMesh._vertexBuffer = gpu::BufferPointer(new gpu::Buffer()); // if we don't need to do any blending, the positions/normals can be static if (mesh.blendshapes.isEmpty()) { int normalsOffset = mesh.vertices.size() * sizeof(glm::vec3); @@ -815,7 +815,7 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { mesh.clusterWeights.size() * sizeof(glm::vec4), (gpu::Resource::Byte*) mesh.clusterWeights.constData()); // otherwise, at least the cluster indices/weights can be static - networkMesh._vertexStream = gpu::StreamPtr(new gpu::Stream()); + networkMesh._vertexStream = gpu::BufferStreamPointer(new gpu::BufferStream()); networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, 0, sizeof(glm::vec3)); if (mesh.normals.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, normalsOffset, sizeof(glm::vec3)); if (mesh.tangents.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, tangentsOffset, sizeof(glm::vec3)); @@ -825,14 +825,14 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { if (mesh.clusterWeights.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, clusterWeightsOffset, sizeof(glm::vec4)); int channelNum = 0; - networkMesh._vertexFormat = gpu::StreamFormatPtr(new gpu::StreamFormat()); - networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_POSITION, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.normals.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_NORMAL, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.tangents.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_TANGENT, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.colors.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_COLOR, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.texCoords.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_TEXCOORD, channelNum++, gpu::Element(gpu::Element::DIM_VEC2, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.clusterIndices.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_NFLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.clusterWeights.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_NFLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + networkMesh._vertexFormat = gpu::Stream::FormatPointer(new gpu::Stream::Format()); + networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_POSITION, channelNum++, gpu::Element(gpu::DIM_VEC3, gpu::TYPE_FLOAT, gpu::SEMANTIC_POS_XYZ), 0); + if (mesh.normals.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_NORMAL, channelNum++, gpu::Element(gpu::DIM_VEC3, gpu::TYPE_FLOAT, gpu::SEMANTIC_XYZ), 0); + if (mesh.tangents.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_TANGENT, channelNum++, gpu::Element(gpu::DIM_VEC3, gpu::TYPE_FLOAT, gpu::SEMANTIC_XYZ), 0); + if (mesh.colors.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_COLOR, channelNum++, gpu::Element(gpu::DIM_VEC3, gpu::TYPE_FLOAT, gpu::SEMANTIC_RGB), 0); + if (mesh.texCoords.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_TEXCOORD, channelNum++, gpu::Element(gpu::DIM_VEC2, gpu::TYPE_FLOAT, gpu::SEMANTIC_UV), 0); + if (mesh.clusterIndices.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::DIM_VEC4, gpu::TYPE_NFLOAT, gpu::SEMANTIC_XYZW), 0); + if (mesh.clusterWeights.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::DIM_VEC4, gpu::TYPE_NFLOAT, gpu::SEMANTIC_XYZW), 0); } else { int colorsOffset = mesh.tangents.size() * sizeof(glm::vec3); @@ -850,7 +850,7 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { networkMesh._vertexBuffer->setSubData(clusterWeightsOffset, mesh.clusterWeights.size() * sizeof(glm::vec4), (gpu::Resource::Byte*) mesh.clusterWeights.constData()); - networkMesh._vertexStream = gpu::StreamPtr(new gpu::Stream()); + networkMesh._vertexStream = gpu::BufferStreamPointer(new gpu::BufferStream()); if (mesh.tangents.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, 0, sizeof(glm::vec3)); if (mesh.colors.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, colorsOffset, sizeof(glm::vec3)); if (mesh.texCoords.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, texCoordsOffset, sizeof(glm::vec2)); @@ -858,14 +858,14 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { if (mesh.clusterWeights.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, clusterWeightsOffset, sizeof(glm::vec4)); int channelNum = 0; - networkMesh._vertexFormat = gpu::StreamFormatPtr(new gpu::StreamFormat()); - networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_POSITION, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.normals.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_NORMAL, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.tangents.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_TANGENT, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.colors.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_COLOR, channelNum++, gpu::Element(gpu::Element::DIM_VEC3, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.texCoords.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_TEXCOORD, channelNum++, gpu::Element(gpu::Element::DIM_VEC2, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.clusterIndices.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_NFLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); - if (mesh.clusterWeights.size()) networkMesh._vertexFormat->setAttribute(gpu::StreamFormat::SLOT_SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_NFLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + networkMesh._vertexFormat = gpu::Stream::FormatPointer(new gpu::Stream::Format()); + networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_POSITION, channelNum++, gpu::Element(gpu::DIM_VEC3, gpu::TYPE_FLOAT, gpu::SEMANTIC_POS_XYZ), 0); + if (mesh.normals.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_NORMAL, channelNum++, gpu::Element(gpu::DIM_VEC3, gpu::TYPE_FLOAT, gpu::SEMANTIC_XYZ), 0); + if (mesh.tangents.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_TANGENT, channelNum++, gpu::Element(gpu::DIM_VEC3, gpu::TYPE_FLOAT, gpu::SEMANTIC_XYZ), 0); + if (mesh.colors.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_COLOR, channelNum++, gpu::Element(gpu::DIM_VEC3, gpu::TYPE_FLOAT, gpu::SEMANTIC_RGB), 0); + if (mesh.texCoords.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_TEXCOORD, channelNum++, gpu::Element(gpu::DIM_VEC2, gpu::TYPE_FLOAT, gpu::SEMANTIC_UV), 0); + if (mesh.clusterIndices.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::DIM_VEC4, gpu::TYPE_NFLOAT, gpu::SEMANTIC_XYZW), 0); + if (mesh.clusterWeights.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::DIM_VEC4, gpu::TYPE_NFLOAT, gpu::SEMANTIC_XYZW), 0); } } diff --git a/interface/src/renderer/GeometryCache.h b/interface/src/renderer/GeometryCache.h index 307c957511..0fb04cf028 100644 --- a/interface/src/renderer/GeometryCache.h +++ b/interface/src/renderer/GeometryCache.h @@ -155,12 +155,12 @@ public: /// The state associated with a single mesh. class NetworkMesh { public: - gpu::BufferPtr _indexBuffer; - gpu::BufferPtr _vertexBuffer; + gpu::BufferPointer _indexBuffer; + gpu::BufferPointer _vertexBuffer; - gpu::StreamPtr _vertexStream; + gpu::BufferStreamPointer _vertexStream; - gpu::StreamFormatPtr _vertexFormat; + gpu::Stream::FormatPointer _vertexFormat; QVector parts; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 758039b32a..7ae4bb4a7d 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -137,7 +137,7 @@ void Model::initProgram(ProgramObject& program, Model::Locations& locations, int - glBindAttribLocation(program.programId(), gpu::StreamFormat::SLOT_TANGENT, "tangent"); + glBindAttribLocation(program.programId(), gpu::Stream::INPUT_SLOT_TANGENT, "tangent"); glLinkProgram(program.programId()); @@ -177,9 +177,9 @@ void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locati // HACK: Assign explicitely the attribute channel to avoid a bug on Yosemite - glBindAttribLocation(program.programId(), gpu::StreamFormat::SLOT_SKIN_CLUSTER_INDEX, "clusterIndices"); + glBindAttribLocation(program.programId(), gpu::Stream::INPUT_SLOT_SKIN_CLUSTER_INDEX, "clusterIndices"); - glBindAttribLocation(program.programId(), gpu::StreamFormat::SLOT_SKIN_CLUSTER_WEIGHT, "clusterWeights"); + glBindAttribLocation(program.programId(), gpu::Stream::INPUT_SLOT_SKIN_CLUSTER_WEIGHT, "clusterWeights"); glLinkProgram(program.programId()); @@ -406,7 +406,7 @@ bool Model::updateGeometry() { state.clusterMatrices.resize(mesh.clusters.size()); _meshStates.append(state); - gpu::BufferPtr buffer(new gpu::Buffer()); + gpu::BufferPointer buffer(new gpu::Buffer()); if (!mesh.blendshapes.isEmpty()) { buffer->resize((mesh.vertices.size() + mesh.normals.size()) * sizeof(glm::vec3)); buffer->setSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.vertices.constData()); @@ -670,9 +670,9 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) { GLBATCH(glDisableClientState)(GL_VERTEX_ARRAY); GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY); GLBATCH(glDisableClientState)(GL_COLOR_ARRAY); - GLBATCH(glDisableVertexAttribArray)(gpu::StreamFormat::SLOT_TANGENT); - GLBATCH(glDisableVertexAttribArray)(gpu::StreamFormat::SLOT_SKIN_CLUSTER_INDEX); - GLBATCH(glDisableVertexAttribArray)(gpu::StreamFormat::SLOT_SKIN_CLUSTER_WEIGHT); + GLBATCH(glDisableVertexAttribArray)(gpu::Stream::INPUT_SLOT_TANGENT); + GLBATCH(glDisableVertexAttribArray)(gpu::Stream::INPUT_SLOT_SKIN_CLUSTER_INDEX); + GLBATCH(glDisableVertexAttribArray)(gpu::Stream::INPUT_SLOT_SKIN_CLUSTER_WEIGHT); // bind with 0 to switch back to normal operation GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, 0); @@ -1411,7 +1411,7 @@ void Model::setBlendedVertices(int blendNumber, const QWeakPointersetSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) vertices.constData() + index*sizeof(glm::vec3)); buffer->setSubData(mesh.vertices.size() * sizeof(glm::vec3), mesh.normals.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) normals.constData() + index*sizeof(glm::vec3)); @@ -1816,7 +1816,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl const NetworkMesh& networkMesh = networkMeshes.at(i); const FBXMesh& mesh = geometry.meshes.at(i); - batch.setIndexBuffer(gpu::Element::TYPE_UINT32, (networkMesh._indexBuffer), 0); + batch.setIndexBuffer(gpu::TYPE_UINT32, (networkMesh._indexBuffer), 0); int vertexCount = mesh.vertices.size(); if (vertexCount == 0) { // sanity check @@ -1867,12 +1867,12 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl if (mesh.blendshapes.isEmpty()) { batch.setInputFormat(networkMesh._vertexFormat); - batch.setInputStream(0, networkMesh._vertexStream); + batch.setInputStream(0, *networkMesh._vertexStream); } else { batch.setInputFormat(networkMesh._vertexFormat); batch.setInputBuffer(0, _blendedVertexBuffers[i], 0, sizeof(glm::vec3)); batch.setInputBuffer(1, _blendedVertexBuffers[i], vertexCount * sizeof(glm::vec3), sizeof(glm::vec3)); - batch.setInputStream(2, networkMesh._vertexStream); + batch.setInputStream(2, *networkMesh._vertexStream); } if (mesh.colors.isEmpty()) { diff --git a/interface/src/ui/TextRenderer.cpp b/interface/src/ui/TextRenderer.cpp index fe109752fe..ff366d50c6 100644 --- a/interface/src/ui/TextRenderer.cpp +++ b/interface/src/ui/TextRenderer.cpp @@ -182,15 +182,15 @@ TextRenderer::TextRenderer(const Properties& properties) : _glyphsBuffer(new gpu::Buffer()), _glyphsColorBuffer(new gpu::Buffer()), _numGlyphsBatched(0), - _glyphsStreamFormat(new gpu::StreamFormat()), - _glyphsStream(new gpu::Stream()) + _glyphsStreamFormat(new gpu::Stream::Format()), + _glyphsStream(new gpu::BufferStream()) { - _glyphsStreamFormat->setAttribute(gpu::StreamFormat::SLOT_POSITION, 0, gpu::Element(gpu::Element::DIM_VEC2, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_POS_XYZ), 0); + _glyphsStreamFormat->setAttribute(gpu::Stream::INPUT_SLOT_POSITION, 0, gpu::Element(gpu::DIM_VEC2, gpu::TYPE_FLOAT, gpu::SEMANTIC_POS_XYZ), 0); const int NUM_POS_COORDS = 2; const int VERTEX_TEXCOORD_OFFSET = NUM_POS_COORDS * sizeof(float); - _glyphsStreamFormat->setAttribute(gpu::StreamFormat::SLOT_TEXCOORD, 0, gpu::Element(gpu::Element::DIM_VEC2, gpu::Element::TYPE_FLOAT, gpu::Element::SEMANTIC_UV), VERTEX_TEXCOORD_OFFSET); + _glyphsStreamFormat->setAttribute(gpu::Stream::INPUT_SLOT_TEXCOORD, 0, gpu::Element(gpu::DIM_VEC2, gpu::TYPE_FLOAT, gpu::SEMANTIC_UV), VERTEX_TEXCOORD_OFFSET); - _glyphsStreamFormat->setAttribute(gpu::StreamFormat::SLOT_COLOR, 1, gpu::Element(gpu::Element::DIM_VEC4, gpu::Element::TYPE_UINT8, gpu::Element::SEMANTIC_RGBA)); + _glyphsStreamFormat->setAttribute(gpu::Stream::INPUT_SLOT_COLOR, 1, gpu::Element(gpu::DIM_VEC4, gpu::TYPE_UINT8, gpu::SEMANTIC_RGBA)); _glyphsStream->addBuffer(_glyphsBuffer, 0, _glyphsStreamFormat->getChannels().at(0)._stride); _glyphsStream->addBuffer(_glyphsColorBuffer, 0, _glyphsStreamFormat->getChannels().at(1)._stride); @@ -335,7 +335,7 @@ void TextRenderer::drawBatch() { glColorPointer(4, GL_UNSIGNED_BYTE, 0, (GLvoid*) 0 ); */ batch.setInputFormat(_glyphsStreamFormat); - batch.setInputStream(0, _glyphsStream); + batch.setInputStream(0, *_glyphsStream); batch.draw(gpu::PRIMITIVE_QUADS, _numGlyphsBatched * 4, 0); gpu::GLBackend::renderBatch(batch); diff --git a/interface/src/ui/TextRenderer.h b/interface/src/ui/TextRenderer.h index 552ac5b158..bcb0ce8890 100644 --- a/interface/src/ui/TextRenderer.h +++ b/interface/src/ui/TextRenderer.h @@ -107,10 +107,10 @@ private: QColor _color; // Graphics Buffer containing the current accumulated glyphs to render - gpu::BufferPtr _glyphsBuffer; - gpu::BufferPtr _glyphsColorBuffer; - gpu::StreamFormatPtr _glyphsStreamFormat; - gpu::StreamPtr _glyphsStream; + gpu::BufferPointer _glyphsBuffer; + gpu::BufferPointer _glyphsColorBuffer; + gpu::Stream::FormatPointer _glyphsStreamFormat; + gpu::BufferStreamPointer _glyphsStream; int _numGlyphsBatched; static QHash _instances; From 4afa0b4188e5d93861f241b2ae046cfffaa8d721 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 4 Nov 2014 15:52:25 -0800 Subject: [PATCH 12/39] more GL error checking --- interface/src/gpu/GLBackend.cpp | 3 +++ interface/src/ui/TextRenderer.cpp | 22 ++-------------------- 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/interface/src/gpu/GLBackend.cpp b/interface/src/gpu/GLBackend.cpp index 6d9676ac68..66e2846861 100644 --- a/interface/src/gpu/GLBackend.cpp +++ b/interface/src/gpu/GLBackend.cpp @@ -421,6 +421,7 @@ void GLBackend::do_setIndexBuffer(Batch& batch, uint32 paramOffset) { } else { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } + CHECK_GL_ERROR(); } // TODO: As long as we have gl calls explicitely issued from interface @@ -1010,6 +1011,7 @@ void GLBackend::syncGPUObject(const Buffer& buffer) { if (!object) { object = new GLBuffer(); glGenBuffers(1, &object->_buffer); + CHECK_GL_ERROR(); Backend::setGPUObject(buffer, object); } @@ -1022,6 +1024,7 @@ void GLBackend::syncGPUObject(const Buffer& buffer) { object->_stamp = buffer.getSysmem().getStamp(); object->_size = buffer.getSysmem().getSize(); //} + CHECK_GL_ERROR(); } diff --git a/interface/src/ui/TextRenderer.cpp b/interface/src/ui/TextRenderer.cpp index ff366d50c6..c7e21eb44a 100644 --- a/interface/src/ui/TextRenderer.cpp +++ b/interface/src/ui/TextRenderer.cpp @@ -295,6 +295,8 @@ void TextRenderer::drawBatch() { return; } + gpu::GLBackend::checkGLError(); + // TODO: Right now the drawBatch is called while calling the draw() function but in the future we'll need to apply the correct transform stack /* GLint matrixMode; @@ -315,31 +317,11 @@ void TextRenderer::drawBatch() { // TODO: Apply the correct font atlas texture, for now only one texture per TextRenderer so it should be good glBindTexture(GL_TEXTURE_2D, _currentTextureID); -/* - GLuint vbo = gpu::GLBackend::getBufferID(_glyphsBuffer); - GLuint colorvbo = gpu::GLBackend::getBufferID(_glyphsColorBuffer); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - - const int NUM_POS_COORDS = 2; - const int NUM_TEX_COORDS = 2; - const int VERTEX_STRIDE = (NUM_POS_COORDS + NUM_TEX_COORDS) * sizeof(float); - const int VERTEX_TEXCOORD_OFFSET = NUM_POS_COORDS * sizeof(float); - - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glVertexPointer(2, GL_FLOAT, VERTEX_STRIDE, 0); - glTexCoordPointer(2, GL_FLOAT, VERTEX_STRIDE, (GLvoid*) VERTEX_TEXCOORD_OFFSET ); - - glBindBuffer(GL_ARRAY_BUFFER, colorvbo); - glColorPointer(4, GL_UNSIGNED_BYTE, 0, (GLvoid*) 0 ); -*/ batch.setInputFormat(_glyphsStreamFormat); batch.setInputStream(0, *_glyphsStream); batch.draw(gpu::PRIMITIVE_QUADS, _numGlyphsBatched * 4, 0); gpu::GLBackend::renderBatch(batch); - // glDrawArrays(GL_QUADS, 0, _numGlyphsBatched * 4); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); From 441d09a46034dc632755923432b7022b7594c90c Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 4 Nov 2014 16:42:58 -0800 Subject: [PATCH 13/39] debugiing the mysterious glError coming from glFrustum --- interface/src/Application.cpp | 2 ++ interface/src/gpu/GLBackend.cpp | 8 ++++++-- interface/src/renderer/Model.cpp | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1209774806..da182c0953 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -81,6 +81,7 @@ #include "renderer/ProgramObject.h" #include "gpu/Batch.h" +#include "gpu/GLBackend.h" #include "scripting/AccountScriptingInterface.h" #include "scripting/AudioDeviceScriptingInterface.h" @@ -786,6 +787,7 @@ void Application::updateProjectionMatrix(Camera& camera, bool updateViewFrustum) tempViewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); } glFrustum(left, right, bottom, top, nearVal, farVal); + gpu::GLBackend::checkGLError(); // save matrix glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat*)&_projectionMatrix); diff --git a/interface/src/gpu/GLBackend.cpp b/interface/src/gpu/GLBackend.cpp index 66e2846861..f1d9423caf 100644 --- a/interface/src/gpu/GLBackend.cpp +++ b/interface/src/gpu/GLBackend.cpp @@ -132,6 +132,8 @@ GLBackend::~GLBackend() { } void GLBackend::renderBatch(Batch& batch) { + checkGLError(); + uint32 numCommands = batch.getCommands().size(); const Batch::Commands::value_type* command = batch.getCommands().data(); const Batch::CommandOffsets::value_type* offset = batch.getCommandOffsets().data(); @@ -144,6 +146,8 @@ void GLBackend::renderBatch(Batch& batch) { command++; offset++; } + + checkGLError(); } void GLBackend::checkGLError() { @@ -178,8 +182,8 @@ void GLBackend::checkGLError() { } } -#define CHECK_GL_ERROR() ::gpu::GLBackend::checkGLError() -//#define CHECK_GL_ERROR() +//#define CHECK_GL_ERROR() ::gpu::GLBackend::checkGLError() +#define CHECK_GL_ERROR() void GLBackend::do_draw(Batch& batch, uint32 paramOffset) { updateInput(); diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 7ae4bb4a7d..a3fd3374a0 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -522,6 +522,7 @@ void Model::recalcuateMeshBoxes() { bool Model::render(float alpha, RenderMode mode, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); + // render the attachments foreach (Model* attachment, _attachments) { attachment->render(alpha, mode); From 99eb46f218c6962a2f8984fe11c7b98b109a499d Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 4 Nov 2014 17:10:17 -0800 Subject: [PATCH 14/39] Removed any checkGLError so they do not show --- interface/src/Application.cpp | 1 - interface/src/gpu/GLBackend.cpp | 4 ---- interface/src/ui/TextRenderer.cpp | 2 -- 3 files changed, 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index dafc61d8a7..e082b22765 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -787,7 +787,6 @@ void Application::updateProjectionMatrix(Camera& camera, bool updateViewFrustum) tempViewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); } glFrustum(left, right, bottom, top, nearVal, farVal); - gpu::GLBackend::checkGLError(); // save matrix glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat*)&_projectionMatrix); diff --git a/interface/src/gpu/GLBackend.cpp b/interface/src/gpu/GLBackend.cpp index f1d9423caf..b6cf8d04cd 100644 --- a/interface/src/gpu/GLBackend.cpp +++ b/interface/src/gpu/GLBackend.cpp @@ -132,8 +132,6 @@ GLBackend::~GLBackend() { } void GLBackend::renderBatch(Batch& batch) { - checkGLError(); - uint32 numCommands = batch.getCommands().size(); const Batch::Commands::value_type* command = batch.getCommands().data(); const Batch::CommandOffsets::value_type* offset = batch.getCommandOffsets().data(); @@ -146,8 +144,6 @@ void GLBackend::renderBatch(Batch& batch) { command++; offset++; } - - checkGLError(); } void GLBackend::checkGLError() { diff --git a/interface/src/ui/TextRenderer.cpp b/interface/src/ui/TextRenderer.cpp index c7e21eb44a..1e4565d83a 100644 --- a/interface/src/ui/TextRenderer.cpp +++ b/interface/src/ui/TextRenderer.cpp @@ -295,8 +295,6 @@ void TextRenderer::drawBatch() { return; } - gpu::GLBackend::checkGLError(); - // TODO: Right now the drawBatch is called while calling the draw() function but in the future we'll need to apply the correct transform stack /* GLint matrixMode; From 1eb49d3763a4dd3eddb5033eb255a08539ed3f4b Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 4 Nov 2014 17:54:54 -0800 Subject: [PATCH 15/39] fixing template bracket issues --- interface/src/gpu/Batch.h | 4 ++-- interface/src/gpu/GLBackend.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/gpu/Batch.h b/interface/src/gpu/Batch.h index c894afc99a..4149d88233 100644 --- a/interface/src/gpu/Batch.h +++ b/interface/src/gpu/Batch.h @@ -243,7 +243,7 @@ public: class Vector { public: - std::vector> _pointers; + std::vector< Cache > _pointers; uint32 cache(const Pointer& pointer) { uint32 offset = _pointers.size(); @@ -277,7 +277,7 @@ public: return (_resources.data() + offset); } - template < typename T > + template T* editResourcePointer(uint32 offset) { if (offset >= _resources.size()) return 0; diff --git a/interface/src/gpu/GLBackend.cpp b/interface/src/gpu/GLBackend.cpp index b6cf8d04cd..66e2846861 100644 --- a/interface/src/gpu/GLBackend.cpp +++ b/interface/src/gpu/GLBackend.cpp @@ -178,8 +178,8 @@ void GLBackend::checkGLError() { } } -//#define CHECK_GL_ERROR() ::gpu::GLBackend::checkGLError() -#define CHECK_GL_ERROR() +#define CHECK_GL_ERROR() ::gpu::GLBackend::checkGLError() +//#define CHECK_GL_ERROR() void GLBackend::do_draw(Batch& batch, uint32 paramOffset) { updateInput(); From a344d46871db54e49322afd631da2a6a89486745 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 4 Nov 2014 18:05:04 -0800 Subject: [PATCH 16/39] fix std::bitset method --- interface/src/gpu/GLBackend.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/gpu/GLBackend.cpp b/interface/src/gpu/GLBackend.cpp index 66e2846861..5a159d920d 100644 --- a/interface/src/gpu/GLBackend.cpp +++ b/interface/src/gpu/GLBackend.cpp @@ -178,8 +178,8 @@ void GLBackend::checkGLError() { } } -#define CHECK_GL_ERROR() ::gpu::GLBackend::checkGLError() -//#define CHECK_GL_ERROR() +//#define CHECK_GL_ERROR() ::gpu::GLBackend::checkGLError() +#define CHECK_GL_ERROR() void GLBackend::do_draw(Batch& batch, uint32 paramOffset) { updateInput(); @@ -308,7 +308,7 @@ void GLBackend::updateInput() { if ((*channelIt).first < buffers.size()) { int bufferNum = (*channelIt).first; - if (_inputBuffersState.at(bufferNum) || _needInputFormatUpdate) { + if (_inputBuffersState.test(bufferNum) || _needInputFormatUpdate) { GLuint vbo = gpu::GLBackend::getBufferID((*buffers[bufferNum])); glBindBuffer(GL_ARRAY_BUFFER, vbo); CHECK_GL_ERROR(); From 562ecc8e3ad777daf22cba1e63e14f4676aa60b6 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 4 Nov 2014 18:18:24 -0800 Subject: [PATCH 17/39] fix glLight attenuation bad values by filtering before glcall --- interface/src/renderer/DeferredLightingEffect.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index f1668629da..d4e83776d8 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -234,9 +234,9 @@ void DeferredLightingEffect::render() { glLightfv(GL_LIGHT1, GL_DIFFUSE, (const GLfloat*)&light.diffuse); glLightfv(GL_LIGHT1, GL_SPECULAR, (const GLfloat*)&light.specular); glLightfv(GL_LIGHT1, GL_POSITION, (const GLfloat*)&light.position); - glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, light.constantAttenuation); - glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, light.linearAttenuation); - glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, light.quadraticAttenuation); + glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, (light.constantAttenuation > 0.f ? light.constantAttenuation : 0.f)); + glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, (light.linearAttenuation > 0.f ? light.linearAttenuation : 0.f)); + glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, (light.quadraticAttenuation > 0.f ? light.quadraticAttenuation : 0.f)); renderFullscreenQuad(); } @@ -258,9 +258,9 @@ void DeferredLightingEffect::render() { glLightfv(GL_LIGHT1, GL_DIFFUSE, (const GLfloat*)&light.diffuse); glLightfv(GL_LIGHT1, GL_SPECULAR, (const GLfloat*)&light.specular); glLightfv(GL_LIGHT1, GL_POSITION, (const GLfloat*)&light.position); - glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, light.constantAttenuation); - glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, light.linearAttenuation); - glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, light.quadraticAttenuation); + glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, (light.constantAttenuation > 0.f ? light.constantAttenuation : 0.f)); + glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, (light.linearAttenuation > 0.f ? light.linearAttenuation : 0.f)); + glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, (light.quadraticAttenuation > 0.f ? light.quadraticAttenuation : 0.f)); glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, (const GLfloat*)&light.direction); glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, light.exponent); glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, glm::degrees(light.cutoff)); From 85a59249df488b9aefa7439a271168559841a969 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 5 Nov 2014 16:19:26 +0100 Subject: [PATCH 18/39] Move ignorePenumbra to positional audio --- libraries/audio/src/InboundAudioStream.cpp | 3 +-- libraries/audio/src/InboundAudioStream.h | 6 ------ libraries/audio/src/PositionalAudioStream.cpp | 1 + libraries/audio/src/PositionalAudioStream.h | 3 +++ 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/libraries/audio/src/InboundAudioStream.cpp b/libraries/audio/src/InboundAudioStream.cpp index 5cb7697de6..366659b633 100644 --- a/libraries/audio/src/InboundAudioStream.cpp +++ b/libraries/audio/src/InboundAudioStream.cpp @@ -45,8 +45,7 @@ InboundAudioStream::InboundAudioStream(int numFrameSamples, int numFramesCapacit _currentJitterBufferFrames(0), _timeGapStatsForStatsPacket(0, STATS_FOR_STATS_PACKET_WINDOW_SECONDS), _repetitionWithFade(settings._repetitionWithFade), - _hasReverb(false), - _ignorePenumbra(false) + _hasReverb(false) { } diff --git a/libraries/audio/src/InboundAudioStream.h b/libraries/audio/src/InboundAudioStream.h index 94ee9ce43e..a9ebc70072 100644 --- a/libraries/audio/src/InboundAudioStream.h +++ b/libraries/audio/src/InboundAudioStream.h @@ -47,7 +47,6 @@ const bool DEFAULT_REPETITION_WITH_FADE = true; // Audio Env bitset const int HAS_REVERB_BIT = 0; // 1st bit -const int IGNORE_PENUMBRA = 1; // 2nd bit class InboundAudioStream : public NodeData { Q_OBJECT @@ -162,8 +161,6 @@ public: float getWetLevel() const { return _wetLevel; } void setReverb(float reverbTime, float wetLevel); void clearReverb() { _hasReverb = false; } - - bool ignorePenumbraFilter() { return _ignorePenumbra; } public slots: /// This function should be called every second for all the stats to function properly. If dynamic jitter buffers @@ -258,9 +255,6 @@ protected: bool _hasReverb; float _reverbTime; float _wetLevel; - - // Ignore penumbra filter - bool _ignorePenumbra; }; float calculateRepeatedFrameFadeFactor(int indexOfRepeat); diff --git a/libraries/audio/src/PositionalAudioStream.cpp b/libraries/audio/src/PositionalAudioStream.cpp index 6334ac0efb..d61edcb30d 100644 --- a/libraries/audio/src/PositionalAudioStream.cpp +++ b/libraries/audio/src/PositionalAudioStream.cpp @@ -29,6 +29,7 @@ PositionalAudioStream::PositionalAudioStream(PositionalAudioStream::Type type, b _orientation(0.0f, 0.0f, 0.0f, 0.0f), _shouldLoopbackForNode(false), _isStereo(isStereo), + _ignorePenumbra(false), _lastPopOutputTrailingLoudness(0.0f), _lastPopOutputLoudness(0.0f) { diff --git a/libraries/audio/src/PositionalAudioStream.h b/libraries/audio/src/PositionalAudioStream.h index 6ac189352b..c2a16367c4 100644 --- a/libraries/audio/src/PositionalAudioStream.h +++ b/libraries/audio/src/PositionalAudioStream.h @@ -39,6 +39,7 @@ public: bool shouldLoopbackForNode() const { return _shouldLoopbackForNode; } bool isStereo() const { return _isStereo; } + bool ignorePenumbraFilter() { return _ignorePenumbra; } PositionalAudioStream::Type getType() const { return _type; } const glm::vec3& getPosition() const { return _position; } const glm::quat& getOrientation() const { return _orientation; } @@ -57,6 +58,8 @@ protected: bool _shouldLoopbackForNode; bool _isStereo; + // Ignore penumbra filter + bool _ignorePenumbra; float _lastPopOutputTrailingLoudness; float _lastPopOutputLoudness; From 49526e69f843284180c7461990fdbec2ea2a0187 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 5 Nov 2014 16:21:06 +0100 Subject: [PATCH 19/39] Added ignorePenumbra option to injected stream --- libraries/audio/src/AudioInjectorOptions.cpp | 3 +++ libraries/audio/src/AudioInjectorOptions.h | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/libraries/audio/src/AudioInjectorOptions.cpp b/libraries/audio/src/AudioInjectorOptions.cpp index eab4eb3848..a930e761ab 100644 --- a/libraries/audio/src/AudioInjectorOptions.cpp +++ b/libraries/audio/src/AudioInjectorOptions.cpp @@ -18,6 +18,7 @@ AudioInjectorOptions::AudioInjectorOptions(QObject* parent) : _loop(false), _orientation(glm::vec3(0.0f, 0.0f, 0.0f)), _isStereo(false), + _ignorePenumbra(false), _loopbackAudioInterface(NULL) { } @@ -28,6 +29,7 @@ AudioInjectorOptions::AudioInjectorOptions(const AudioInjectorOptions& other) { _loop = other._loop; _orientation = other._orientation; _isStereo = other._isStereo; + _ignorePenumbra = other._ignorePenumbra; _loopbackAudioInterface = other._loopbackAudioInterface; } @@ -37,5 +39,6 @@ void AudioInjectorOptions::operator=(const AudioInjectorOptions& other) { _loop = other._loop; _orientation = other._orientation; _isStereo = other._isStereo; + _ignorePenumbra = other._ignorePenumbra; _loopbackAudioInterface = other._loopbackAudioInterface; } \ No newline at end of file diff --git a/libraries/audio/src/AudioInjectorOptions.h b/libraries/audio/src/AudioInjectorOptions.h index 66e8f1550b..e59517c10b 100644 --- a/libraries/audio/src/AudioInjectorOptions.h +++ b/libraries/audio/src/AudioInjectorOptions.h @@ -29,6 +29,7 @@ class AudioInjectorOptions : public QObject { Q_PROPERTY(float volume READ getVolume WRITE setVolume) Q_PROPERTY(bool loop READ getLoop WRITE setLoop) Q_PROPERTY(bool isStereo READ isStereo WRITE setIsStereo) + Q_PROPERTY(bool ignorePenumbra READ ignorePenumbra WRITE setIgnorePenumbra) public: AudioInjectorOptions(QObject* parent = 0); AudioInjectorOptions(const AudioInjectorOptions& other); @@ -49,6 +50,9 @@ public: const bool isStereo() const { return _isStereo; } void setIsStereo(const bool isStereo) { _isStereo = isStereo; } + const bool ignorePenumbra() const {return _ignorePenumbra; } + void setIgnorePenumbra(bool ignorePenumbra) { _ignorePenumbra = ignorePenumbra; } + AbstractAudioInterface* getLoopbackAudioInterface() const { return _loopbackAudioInterface; } void setLoopbackAudioInterface(AbstractAudioInterface* loopbackAudioInterface) { _loopbackAudioInterface = loopbackAudioInterface; } @@ -58,6 +62,7 @@ private: bool _loop; glm::quat _orientation; bool _isStereo; + bool _ignorePenumbra; AbstractAudioInterface* _loopbackAudioInterface; }; From 4b73a5ac358fba374828b2cae0b2bd3936da076c Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 5 Nov 2014 16:22:06 +0100 Subject: [PATCH 20/39] Modify injected audio stream to send the ignore penumbra option --- libraries/audio/src/AudioInjector.cpp | 2 ++ libraries/audio/src/InjectedAudioStream.cpp | 4 +++- libraries/networking/src/PacketHeaders.cpp | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 31c135fd58..b4b5ad5ffb 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -100,6 +100,8 @@ void AudioInjector::injectAudio() { quint8 volume = MAX_INJECTOR_VOLUME * _options.getVolume(); packetStream << volume; + packetStream << _options.ignorePenumbra(); + QElapsedTimer timer; timer.start(); int nextFrame = 0; diff --git a/libraries/audio/src/InjectedAudioStream.cpp b/libraries/audio/src/InjectedAudioStream.cpp index 873b32cc40..2811e857db 100644 --- a/libraries/audio/src/InjectedAudioStream.cpp +++ b/libraries/audio/src/InjectedAudioStream.cpp @@ -63,7 +63,9 @@ int InjectedAudioStream::parseStreamProperties(PacketType type, quint8 attenuationByte = 0; packetStream >> attenuationByte; _attenuationRatio = attenuationByte / (float)MAX_INJECTOR_VOLUME; - + + packetStream >> _ignorePenumbra; + int numAudioBytes = packetAfterSeqNum.size() - packetStream.device()->pos(); numAudioSamples = numAudioBytes / sizeof(int16_t); diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 73671295df..b5cf84ee28 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -54,6 +54,8 @@ PacketVersion versionForPacketType(PacketType type) { return 4; case PacketTypeMixedAudio: return 1; + case PacketTypeInjectAudio: + return 1; case PacketTypeAvatarData: return 3; case PacketTypeAvatarIdentity: From 2c667d209d3b99a04aaebe2dfdcf8bd4178fb0a5 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Nov 2014 10:10:05 -0800 Subject: [PATCH 21/39] make the AudioInjectorScriptingInterface a singleton --- interface/src/Application.cpp | 3 ++ .../audio/src/AudioScriptingInterface.cpp | 47 +++++++++---------- libraries/audio/src/AudioScriptingInterface.h | 18 +++++-- libraries/script-engine/src/ScriptEngine.cpp | 2 +- libraries/script-engine/src/ScriptEngine.h | 4 +- 5 files changed, 40 insertions(+), 34 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6d8b612bc3..f62a9e8e30 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -450,6 +450,9 @@ Application::~Application() { _audio.thread()->quit(); _audio.thread()->wait(); + // kill any audio injectors that are still around + + _octreeProcessor.terminate(); _voxelHideShowThread.terminate(); _voxelEditSender.terminate(); diff --git a/libraries/audio/src/AudioScriptingInterface.cpp b/libraries/audio/src/AudioScriptingInterface.cpp index 43c7d35c1d..ac0d3751bd 100644 --- a/libraries/audio/src/AudioScriptingInterface.cpp +++ b/libraries/audio/src/AudioScriptingInterface.cpp @@ -11,6 +11,15 @@ #include "AudioScriptingInterface.h" +AudioScriptingInterface& AudioScriptingInterface::getInstance() { + static AudioScriptingInterface staticInstance; + return staticInstance; +} + +void AudioScriptingInterface::stopAllInjectors() { + +} + AudioInjector* AudioScriptingInterface::playSound(Sound* sound, const AudioInjectorOptions* injectorOptions) { if (sound->isStereo()) { @@ -23,15 +32,18 @@ AudioInjector* AudioScriptingInterface::playSound(Sound* sound, const AudioInjec injector->moveToThread(injectorThread); // start injecting when the injector thread starts - connect(injectorThread, SIGNAL(started()), injector, SLOT(injectAudio())); + connect(injectorThread, &QThread::started, injector, &AudioInjector::injectAudio); // connect the right slots and signals so that the AudioInjector is killed once the injection is complete - connect(injector, SIGNAL(finished()), injector, SLOT(deleteLater())); - connect(injector, SIGNAL(finished()), injectorThread, SLOT(quit())); - connect(injectorThread, SIGNAL(finished()), injectorThread, SLOT(deleteLater())); + connect(injector, &AudioInjector::finished, injector, &AudioInjector::deleteLater); + connect(injector, &AudioInjector::finished, injectorThread, &QThread::quit); + connect(injector, &AudioInjector::finished, this, &AudioScriptingInterface::injectorStopped); + connect(injectorThread, &QThread::finished, injectorThread, &QThread::deleteLater); injectorThread->start(); + _activeInjectors.insert(injector); + return injector; } @@ -45,24 +57,9 @@ bool AudioScriptingInterface::isInjectorPlaying(AudioInjector* injector) { return (injector != NULL); } -void AudioScriptingInterface::startDrumSound(float volume, float frequency, float duration, float decay, - const AudioInjectorOptions* injectorOptions) { - - Sound* sound = new Sound(volume, frequency, duration, decay); - AudioInjector* injector = new AudioInjector(sound, *injectorOptions); - sound->setParent(injector); - - QThread* injectorThread = new QThread(); - - injector->moveToThread(injectorThread); - - // start injecting when the injector thread starts - connect(injectorThread, SIGNAL(started()), injector, SLOT(injectAudio())); - - // connect the right slots and signals so that the AudioInjector is killed once the injection is complete - connect(injector, SIGNAL(finished()), injector, SLOT(deleteLater())); - connect(injector, SIGNAL(finished()), injectorThread, SLOT(quit())); - connect(injectorThread, SIGNAL(finished()), injectorThread, SLOT(deleteLater())); - - injectorThread->start(); -} +void AudioScriptingInterface::injectorStopped() { + qDebug() << "Removing" << sender() << "from active injectors"; + qDebug() << _activeInjectors.size(); + _activeInjectors.remove(static_cast(sender())); + qDebug() << _activeInjectors.size(); +} \ No newline at end of file diff --git a/libraries/audio/src/AudioScriptingInterface.h b/libraries/audio/src/AudioScriptingInterface.h index 343eac304c..3655aff766 100644 --- a/libraries/audio/src/AudioScriptingInterface.h +++ b/libraries/audio/src/AudioScriptingInterface.h @@ -19,12 +19,20 @@ const AudioInjectorOptions DEFAULT_INJECTOR_OPTIONS; class AudioScriptingInterface : public QObject { Q_OBJECT +public: + static AudioScriptingInterface& getInstance(); + + void stopAllInjectors(); public slots: - static AudioInjector* playSound(Sound* sound, const AudioInjectorOptions* injectorOptions = NULL); - static void stopInjector(AudioInjector* injector); - static bool isInjectorPlaying(AudioInjector* injector); - static void startDrumSound(float volume, float frequency, float duration, float decay, - const AudioInjectorOptions* injectorOptions = NULL); + AudioInjector* playSound(Sound* sound, const AudioInjectorOptions* injectorOptions = NULL); + void stopInjector(AudioInjector* injector); + bool isInjectorPlaying(AudioInjector* injector); + + void injectorStopped(); + +private: + AudioScriptingInterface() {}; + QSet _activeInjectors; }; #endif // hifi_AudioScriptingInterface_h diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index fb98124fc9..7445822f55 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -290,7 +290,7 @@ void ScriptEngine::init() { qScriptRegisterMetaType(this, animationDetailsToScriptValue, animationDetailsFromScriptValue); registerGlobalObject("Script", this); - registerGlobalObject("Audio", &_audioScriptingInterface); + registerGlobalObject("Audio", &AudioScriptingInterface::getInstance()); registerGlobalObject("Controller", _controllerScriptingInterface); registerGlobalObject("Entities", &_entityScriptingInterface); registerGlobalObject("Quat", &_quatLibrary); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index d556475859..456134dd5c 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -141,9 +141,7 @@ private: static VoxelsScriptingInterface _voxelsScriptingInterface; static EntityScriptingInterface _entityScriptingInterface; - AbstractControllerScriptingInterface* _controllerScriptingInterface; - AudioScriptingInterface _audioScriptingInterface; - AvatarData* _avatarData; + AbstractControllerScriptingInterface* _controllerScriptingInterface; AvatarData* _avatarData; QString _scriptName; QString _fileNameString; Quat _quatLibrary; From f8874daab6375119d6ad69c721358bc2a8ef2f6f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Nov 2014 10:10:22 -0800 Subject: [PATCH 22/39] remove the voxel drumming script --- examples/voxelDrumming.js | 167 -------------------------------------- 1 file changed, 167 deletions(-) delete mode 100644 examples/voxelDrumming.js diff --git a/examples/voxelDrumming.js b/examples/voxelDrumming.js deleted file mode 100644 index 1b320ed755..0000000000 --- a/examples/voxelDrumming.js +++ /dev/null @@ -1,167 +0,0 @@ -// -// voxelDrumming.js -// examples -// -// Created by Brad Hefta-Gaub on 2/14/14. -// Copyright 2014 High Fidelity, Inc. -// -// This is an example script that demonstrates use of the Overlays, Controller, and Audio classes -// -// It adds Hydra controller "fingertip on voxels" drumming -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -Menu.addMenuItem({ - menuName: "Developer > Hand Options", - menuItemName: "Voxel Drumming", - isCheckable: true, - isChecked: false - }); - -var collisionCenter = new Array(); -collisionCenter[0] = { x: 0, y: 0, z: 0}; -collisionCenter[1] = { x: 0, y: 0, z: 0}; - -var collisionAge = new Array(); -collisionAge[0] = 0; -collisionAge[1] = 0; - -var collisionDuration = new Array(); -collisionDuration[0] = 0; -collisionDuration[1] = 0; - -var isColliding = new Array(); -isColliding[0] = false; -isColliding[1] = false; - -var highlightVoxel = Overlays.addOverlay("cube", - { - position: { x: 0, y: 0, z: 0}, - size: 0, - color: { red: 0, green: 0, blue: 0 }, - visible: false, - lineWidth: 3, - solid: false - }); - -var collisionBubble = new Array(); -collisionBubble[0] = Overlays.addOverlay("sphere", - { - position: { x: 0, y: 0, z: 0}, - size: 0, - color: { red: 0, green: 0, blue: 0 }, - alpha: 0.5, - visible: false - }); -collisionBubble[1] = Overlays.addOverlay("sphere", - { - position: { x: 0, y: 0, z: 0}, - size: 0, - color: { red: 0, green: 0, blue: 0 }, - alpha: 0.5, - visible: false - }); - -var audioOptions = new AudioInjectionOptions(); -audioOptions.position = { x: MyAvatar.position.x, y: MyAvatar.position.y + 1, z: MyAvatar.position.z }; -audioOptions.volume = 1; - - -function clamp(valueToClamp, minValue, maxValue) { - return Math.max(minValue, Math.min(maxValue, valueToClamp)); -} - -function produceCollisionSound(deltaTime, palm, voxelDetail) { - // Collision between finger and a voxel plays sound - - var palmVelocity = Controller.getSpatialControlVelocity(palm * 2); - var speed = Vec3.length(palmVelocity); - var fingerTipPosition = Controller.getSpatialControlPosition(palm * 2 + 1); - - var LOWEST_FREQUENCY = 100.0; - var HERTZ_PER_RGB = 3.0; - var DECAY_PER_SAMPLE = 0.0005; - var DURATION_MAX = 2.0; - var MIN_VOLUME = 0.1; - var volume = MIN_VOLUME + clamp(speed, 0.0, (1.0 - MIN_VOLUME)); - var duration = volume; - - collisionCenter[palm] = fingerTipPosition; - collisionAge[palm] = deltaTime; - collisionDuration[palm] = duration; - - var voxelBrightness = voxelDetail.red + voxelDetail.green + voxelDetail.blue; - var frequency = LOWEST_FREQUENCY + (voxelBrightness * HERTZ_PER_RGB); - - audioOptions.position = fingerTipPosition; - Audio.startDrumSound(volume, frequency, DURATION_MAX, DECAY_PER_SAMPLE, audioOptions); -} - -function update(deltaTime) { - // Voxel Drumming with fingertips if enabled - if (Menu.isOptionChecked("Voxel Drumming")) { - - for (var palm = 0; palm < 2; palm++) { - var fingerTipPosition = Controller.getSpatialControlPosition(palm * 2 + 1); - - var voxel = Voxels.getVoxelEnclosingPoint(fingerTipPosition); - if (voxel.s > 0) { - if (!isColliding[palm]) { - // Collision has just started - isColliding[palm] = true; - produceCollisionSound(deltaTime, palm, voxel); - - // Set highlight voxel - Overlays.editOverlay(highlightVoxel, - { - position: { x: voxel.x, y: voxel.y, z: voxel.z}, - size: voxel.s + 0.002, - color: { red: voxel.red + 128, green: voxel.green + 128, blue: voxel.blue + 128 }, - visible: true - }); - } - } else { - if (isColliding[palm]) { - // Collision has just ended - isColliding[palm] = false; - Overlays.editOverlay(highlightVoxel, { visible: false }); - } - } - - if (collisionAge[palm] > 0) { - collisionAge[palm] += deltaTime; - } - - // If hand/voxel collision has happened, render a little expanding sphere - if (collisionAge[palm] > 0) { - var opacity = clamp(1 - (collisionAge[palm] / collisionDuration[palm]), 0, 1); - var size = collisionAge[palm] * 0.25; - - Overlays.editOverlay(collisionBubble[palm], - { - position: { x: collisionCenter[palm].x, y: collisionCenter[palm].y, z: collisionCenter[palm].z}, - size: size, - color: { red: 255, green: 0, blue: 0 }, - alpha: 0.5 * opacity, - visible: true - }); - - if (collisionAge[palm] > collisionDuration[palm]) { - collisionAge[palm] = 0; - Overlays.editOverlay(collisionBubble[palm], { visible: false }); - } - } - } // palm loop - } // menu item check -} -Script.update.connect(update); - -function scriptEnding() { - Overlays.deleteOverlay(highlightVoxel); - Overlays.deleteOverlay(collisionBubble[0]); - Overlays.deleteOverlay(collisionBubble[1]); - Menu.removeMenuItem("Developer > Hand Options","Voxel Drumming"); -} -Script.scriptEnding.connect(scriptEnding); From 663167d6844f1d7b63e3b71149c6bf0644f34e8b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Nov 2014 10:37:22 -0800 Subject: [PATCH 23/39] wait on AudioInjectors when shutting down interface --- interface/src/Application.cpp | 2 +- libraries/audio/src/AudioInjector.cpp | 3 +++ libraries/audio/src/AudioInjector.h | 2 ++ .../audio/src/AudioScriptingInterface.cpp | 20 +++++++++++++------ libraries/audio/src/AudioScriptingInterface.h | 4 +++- 5 files changed, 23 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f62a9e8e30..ff4a23ceaf 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -451,7 +451,7 @@ Application::~Application() { _audio.thread()->wait(); // kill any audio injectors that are still around - + AudioScriptingInterface::getInstance().stopAllInjectors(); _octreeProcessor.terminate(); _voxelHideShowThread.terminate(); diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 31c135fd58..87de9ede8b 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -26,6 +26,7 @@ AudioInjector::AudioInjector(QObject* parent) : _sound(NULL), _options(), _shouldStop(false), + _isFinished(false), _currentSendPosition(0) { } @@ -34,6 +35,7 @@ AudioInjector::AudioInjector(Sound* sound, const AudioInjectorOptions& injectorO _sound(sound), _options(injectorOptions), _shouldStop(false), + _isFinished(false), _currentSendPosition(0) { } @@ -161,5 +163,6 @@ void AudioInjector::injectAudio() { } } + _isFinished = true; emit finished(); } diff --git a/libraries/audio/src/AudioInjector.h b/libraries/audio/src/AudioInjector.h index af9b5e55d1..1f070a77b0 100644 --- a/libraries/audio/src/AudioInjector.h +++ b/libraries/audio/src/AudioInjector.h @@ -27,6 +27,7 @@ public: AudioInjector(QObject* parent); AudioInjector(Sound* sound, const AudioInjectorOptions& injectorOptions); + bool isFinished() const { return _isFinished; } int getCurrentSendPosition() const { return _currentSendPosition; } public slots: void injectAudio(); @@ -39,6 +40,7 @@ private: Sound* _sound; AudioInjectorOptions _options; bool _shouldStop; + bool _isFinished; int _currentSendPosition; }; diff --git a/libraries/audio/src/AudioScriptingInterface.cpp b/libraries/audio/src/AudioScriptingInterface.cpp index ac0d3751bd..f78bdb0614 100644 --- a/libraries/audio/src/AudioScriptingInterface.cpp +++ b/libraries/audio/src/AudioScriptingInterface.cpp @@ -17,7 +17,18 @@ AudioScriptingInterface& AudioScriptingInterface::getInstance() { } void AudioScriptingInterface::stopAllInjectors() { - + QList >::iterator injector = _activeInjectors.begin(); + while (injector != _activeInjectors.end()) { + if (!injector->isNull()) { + injector->data()->stop(); + + while (injector->data() && !injector->data()->isFinished()) { + // wait for this injector to go down + } + } + + injector = _activeInjectors.erase(injector); + } } AudioInjector* AudioScriptingInterface::playSound(Sound* sound, const AudioInjectorOptions* injectorOptions) { @@ -42,7 +53,7 @@ AudioInjector* AudioScriptingInterface::playSound(Sound* sound, const AudioInjec injectorThread->start(); - _activeInjectors.insert(injector); + _activeInjectors.append(QPointer(injector)); return injector; } @@ -58,8 +69,5 @@ bool AudioScriptingInterface::isInjectorPlaying(AudioInjector* injector) { } void AudioScriptingInterface::injectorStopped() { - qDebug() << "Removing" << sender() << "from active injectors"; - qDebug() << _activeInjectors.size(); - _activeInjectors.remove(static_cast(sender())); - qDebug() << _activeInjectors.size(); + _activeInjectors.removeAll(QPointer(reinterpret_cast(sender()))); } \ No newline at end of file diff --git a/libraries/audio/src/AudioScriptingInterface.h b/libraries/audio/src/AudioScriptingInterface.h index 3655aff766..6179111f59 100644 --- a/libraries/audio/src/AudioScriptingInterface.h +++ b/libraries/audio/src/AudioScriptingInterface.h @@ -12,6 +12,8 @@ #ifndef hifi_AudioScriptingInterface_h #define hifi_AudioScriptingInterface_h +#include + #include "AudioInjector.h" #include "Sound.h" @@ -32,7 +34,7 @@ public slots: private: AudioScriptingInterface() {}; - QSet _activeInjectors; + QList< QPointer > _activeInjectors; }; #endif // hifi_AudioScriptingInterface_h From 2e8118300faa9596df88f693f4a794958f2c61e3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Nov 2014 11:11:37 -0800 Subject: [PATCH 24/39] fix for two member variable declarations on same line --- libraries/script-engine/src/ScriptEngine.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 456134dd5c..f96b4655a9 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -141,7 +141,8 @@ private: static VoxelsScriptingInterface _voxelsScriptingInterface; static EntityScriptingInterface _entityScriptingInterface; - AbstractControllerScriptingInterface* _controllerScriptingInterface; AvatarData* _avatarData; + AbstractControllerScriptingInterface* _controllerScriptingInterface; + AvatarData* _avatarData; QString _scriptName; QString _fileNameString; Quat _quatLibrary; From e9a332de4d4e7b03551e8f4b23e81559b4db12be Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 5 Nov 2014 12:12:17 -0800 Subject: [PATCH 25/39] make entity and voxel servers support domain based configuration --- assignment-client/src/entities/EntityServer.h | 1 + assignment-client/src/octree/OctreeServer.cpp | 298 +++++++++++------- assignment-client/src/octree/OctreeServer.h | 6 + assignment-client/src/voxels/VoxelServer.cpp | 16 +- assignment-client/src/voxels/VoxelServer.h | 5 +- .../resources/describe-settings.json | 82 ++++- 6 files changed, 284 insertions(+), 124 deletions(-) diff --git a/assignment-client/src/entities/EntityServer.h b/assignment-client/src/entities/EntityServer.h index dc19f33fab..563efed288 100644 --- a/assignment-client/src/entities/EntityServer.h +++ b/assignment-client/src/entities/EntityServer.h @@ -34,6 +34,7 @@ public: virtual const char* getMyLoggingServerTargetName() const { return MODEL_SERVER_LOGGING_TARGET_NAME; } virtual const char* getMyDefaultPersistFilename() const { return LOCAL_MODELS_PERSIST_FILE; } virtual PacketType getMyEditNackType() const { return PacketTypeEntityEditNack; } + virtual QString getMyDomainSettingsKey() const { return QString("entity_server_settings"); } // subclass may implement these method virtual void beforeRun(); diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 121cac0273..26cf94269b 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -900,85 +900,206 @@ void OctreeServer::setupDatagramProcessingThread() { // start the datagram processing thread _datagramProcessingThread->start(); +} +bool OctreeServer::readOptionBool(const QString& optionName, const QJsonObject& settingsSectionObject, bool& result) { + result = false; // assume it doesn't exist + bool optionAvailable = false; + QString argName = "--" + optionName; + bool argExists = cmdOptionExists(_argc, _argv, qPrintable(argName)); + if (argExists) { + optionAvailable = true; + result = argExists; + qDebug() << "From payload arguments: " << qPrintable(argName) << ":" << result; + } else if (settingsSectionObject.contains(optionName)) { + optionAvailable = true; + result = settingsSectionObject[optionName].toBool(); + qDebug() << "From domain settings: " << qPrintable(optionName) << ":" << result; + } + return optionAvailable; +} + +bool OctreeServer::readOptionInt(const QString& optionName, const QJsonObject& settingsSectionObject, int& result) { + bool optionAvailable = false; + QString argName = "--" + optionName; + const char* argValue = getCmdOption(_argc, _argv, qPrintable(argName)); + if (argValue) { + optionAvailable = true; + result = atoi(argValue); + qDebug() << "From payload arguments: " << qPrintable(argName) << ":" << result; + } else if (settingsSectionObject.contains(optionName)) { + optionAvailable = true; + result = settingsSectionObject[optionName].toString().toInt(&optionAvailable); + if (optionAvailable) { + qDebug() << "From domain settings: " << qPrintable(optionName) << ":" << result; + } + } + return optionAvailable; +} + +bool OctreeServer::readOptionString(const QString& optionName, const QJsonObject& settingsSectionObject, QString& result) { + bool optionAvailable = false; + QString argName = "--" + optionName; + const char* argValue = getCmdOption(_argc, _argv, qPrintable(argName)); + if (argValue) { + optionAvailable = true; + result = QString(argValue); + qDebug() << "From payload arguments: " << qPrintable(argName) << ":" << qPrintable(result); + } else if (settingsSectionObject.contains(optionName)) { + optionAvailable = true; + result = settingsSectionObject[optionName].toString(); + qDebug() << "From domain settings: " << qPrintable(optionName) << ":" << qPrintable(result); + } + return optionAvailable; +} + +void OctreeServer::readConfiguration() { + // if the assignment had a payload, read and parse that + if (getPayload().size() > 0) { + parsePayload(); + } + + // wait until we have the domain-server settings, otherwise we bail + NodeList* nodeList = NodeList::getInstance(); + DomainHandler& domainHandler = nodeList->getDomainHandler(); + + qDebug() << "Waiting for domain settings from domain-server."; + + // block until we get the settingsRequestComplete signal + QEventLoop loop; + connect(&domainHandler, &DomainHandler::settingsReceived, &loop, &QEventLoop::quit); + connect(&domainHandler, &DomainHandler::settingsReceiveFail, &loop, &QEventLoop::quit); + domainHandler.requestDomainSettings(); + loop.exec(); + + if (domainHandler.getSettingsObject().isEmpty()) { + qDebug() << "No settings object from domain-server."; + } + const QJsonObject& settingsObject = domainHandler.getSettingsObject(); + QString settingsKey = getMyDomainSettingsKey(); + QJsonObject settingsSectionObject = settingsObject[settingsKey].toObject(); + + if (!readOptionString(QString("statusHost"), settingsSectionObject, _statusHost) || _statusHost.isEmpty()) { + _statusHost = getLocalAddress().toString(); + } + qDebug("statusHost=%s", qPrintable(_statusHost)); + + if (readOptionInt(QString("statusPort"), settingsSectionObject, _statusPort)) { + initHTTPManager(_statusPort); + qDebug() << "statusPort=" << _statusPort; + } else { + qDebug() << "statusPort= DISABLED"; + } + + QString jurisdictionFile; + if (readOptionString(QString("jurisdictionFile"), settingsSectionObject, jurisdictionFile)) { + qDebug("jurisdictionFile=%s", qPrintable(jurisdictionFile)); + qDebug("about to readFromFile().... jurisdictionFile=%s", qPrintable(jurisdictionFile)); + _jurisdiction = new JurisdictionMap(qPrintable(jurisdictionFile)); + qDebug("after readFromFile().... jurisdictionFile=%s", qPrintable(jurisdictionFile)); + } else { + QString jurisdictionRoot; + bool hasRoot = readOptionString(QString("jurisdictionRoot"), settingsSectionObject, jurisdictionRoot); + QString jurisdictionEndNodes; + bool hasEndNodes = readOptionString(QString("jurisdictionEndNodes"), settingsSectionObject, jurisdictionEndNodes); + + if (hasRoot || hasEndNodes) { + _jurisdiction = new JurisdictionMap(qPrintable(jurisdictionRoot), qPrintable(jurisdictionEndNodes)); + } + } + + readOptionBool(QString("verboseDebug"), settingsSectionObject, _verboseDebug); + qDebug("verboseDebug=%s", debug::valueOf(_verboseDebug)); + + readOptionBool(QString("debugSending"), settingsSectionObject, _debugSending); + qDebug("debugSending=%s", debug::valueOf(_debugSending)); + + readOptionBool(QString("debugReceiving"), settingsSectionObject, _debugReceiving); + qDebug("debugReceiving=%s", debug::valueOf(_debugReceiving)); + + bool noPersist; + readOptionBool(QString("NoPersist"), settingsSectionObject, noPersist); + _wantPersist = !noPersist; + qDebug("wantPersist=%s", debug::valueOf(_wantPersist)); + + if (_wantPersist) { + QString persistFilename; + if (!readOptionString(QString("persistFilename"), settingsSectionObject, persistFilename)) { + persistFilename = getMyDefaultPersistFilename(); + } + strcpy(_persistFilename, qPrintable(persistFilename)); + qDebug("persistFilename=%s", _persistFilename); + } else { + qDebug("persistFilename= DISABLED"); + } + + // Debug option to demonstrate that the server's local time does not + // need to be in sync with any other network node. This forces clock + // skew for the individual server node + int clockSkew; + if (readOptionInt(QString("clockSkew"), settingsSectionObject, clockSkew)) { + usecTimestampNowForceClockSkew(clockSkew); + qDebug("clockSkew=%d", clockSkew); + } + + // Check to see if the user passed in a command line option for setting packet send rate + int packetsPerSecondPerClientMax = -1; + if (readOptionInt(QString("packetsPerSecondPerClientMax"), settingsSectionObject, packetsPerSecondPerClientMax)) { + _packetsPerClientPerInterval = packetsPerSecondPerClientMax / INTERVALS_PER_SECOND; + if (_packetsPerClientPerInterval < 1) { + _packetsPerClientPerInterval = 1; + } + } + qDebug("packetsPerSecondPerClientMax=%d _packetsPerClientPerInterval=%d", + packetsPerSecondPerClientMax, _packetsPerClientPerInterval); + + // Check to see if the user passed in a command line option for setting packet send rate + int packetsPerSecondTotalMax = -1; + if (readOptionInt(QString("packetsPerSecondTotalMax"), settingsSectionObject, packetsPerSecondTotalMax)) { + _packetsTotalPerInterval = packetsPerSecondTotalMax / INTERVALS_PER_SECOND; + if (_packetsTotalPerInterval < 1) { + _packetsTotalPerInterval = 1; + } + } + qDebug("packetsPerSecondTotalMax=%d _packetsTotalPerInterval=%d", + packetsPerSecondTotalMax, _packetsTotalPerInterval); + + + readAdditionalConfiguration(settingsSectionObject); } void OctreeServer::run() { + qInstallMessageHandler(LogHandler::verboseMessageHandler); + _safeServerName = getMyServerName(); - + // Before we do anything else, create our tree... OctreeElement::resetPopulationStatistics(); _tree = createTree(); _tree->setIsServer(true); + + // make sure our NodeList knows what type we are + NodeList* nodeList = NodeList::getInstance(); + nodeList->setOwnerType(getMyNodeType()); + // use common init to setup common timers and logging commonInit(getMyLoggingServerTargetName(), getMyNodeType()); setupDatagramProcessingThread(); - - // Now would be a good time to parse our arguments, if we got them as assignment - if (getPayload().size() > 0) { - parsePayload(); - } + // read the configuration from either the payload or the domain server configuration + readConfiguration(); + beforeRun(); // after payload has been processed - qInstallMessageHandler(LogHandler::verboseMessageHandler); - - const char* STATUS_PORT = "--statusPort"; - const char* statusPort = getCmdOption(_argc, _argv, STATUS_PORT); - if (statusPort) { - _statusPort = atoi(statusPort); - initHTTPManager(_statusPort); - } - - const char* STATUS_HOST = "--statusHost"; - const char* statusHost = getCmdOption(_argc, _argv, STATUS_HOST); - if (statusHost) { - qDebug("--statusHost=%s", statusHost); - _statusHost = statusHost; - } else { - _statusHost = getLocalAddress().toString(); - } - qDebug("statusHost=%s", qPrintable(_statusHost)); - - - const char* JURISDICTION_FILE = "--jurisdictionFile"; - const char* jurisdictionFile = getCmdOption(_argc, _argv, JURISDICTION_FILE); - if (jurisdictionFile) { - qDebug("jurisdictionFile=%s", jurisdictionFile); - - qDebug("about to readFromFile().... jurisdictionFile=%s", jurisdictionFile); - _jurisdiction = new JurisdictionMap(jurisdictionFile); - qDebug("after readFromFile().... jurisdictionFile=%s", jurisdictionFile); - } else { - const char* JURISDICTION_ROOT = "--jurisdictionRoot"; - const char* jurisdictionRoot = getCmdOption(_argc, _argv, JURISDICTION_ROOT); - if (jurisdictionRoot) { - qDebug("jurisdictionRoot=%s", jurisdictionRoot); - } - - const char* JURISDICTION_ENDNODES = "--jurisdictionEndNodes"; - const char* jurisdictionEndNodes = getCmdOption(_argc, _argv, JURISDICTION_ENDNODES); - if (jurisdictionEndNodes) { - qDebug("jurisdictionEndNodes=%s", jurisdictionEndNodes); - } - - if (jurisdictionRoot || jurisdictionEndNodes) { - _jurisdiction = new JurisdictionMap(jurisdictionRoot, jurisdictionEndNodes); - } - } - - NodeList* nodeList = NodeList::getInstance(); - nodeList->setOwnerType(getMyNodeType()); - connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), SLOT(nodeAdded(SharedNodePointer))); connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)),SLOT(nodeKilled(SharedNodePointer))); // we need to ask the DS about agents so we can ping/reply with them nodeList->addNodeTypeToInterestSet(NodeType::Agent); - + #ifndef WIN32 setvbuf(stdout, NULL, _IOLBF, 0); #endif @@ -987,39 +1108,9 @@ void OctreeServer::run() { srand((unsigned)time(0)); - const char* VERBOSE_DEBUG = "--verboseDebug"; - _verboseDebug = cmdOptionExists(_argc, _argv, VERBOSE_DEBUG); - qDebug("verboseDebug=%s", debug::valueOf(_verboseDebug)); - - const char* DEBUG_SENDING = "--debugSending"; - _debugSending = cmdOptionExists(_argc, _argv, DEBUG_SENDING); - qDebug("debugSending=%s", debug::valueOf(_debugSending)); - - const char* DEBUG_RECEIVING = "--debugReceiving"; - _debugReceiving = cmdOptionExists(_argc, _argv, DEBUG_RECEIVING); - qDebug("debugReceiving=%s", debug::valueOf(_debugReceiving)); - - // By default we will persist, if you want to disable this, then pass in this parameter - const char* NO_PERSIST = "--NoPersist"; - if (cmdOptionExists(_argc, _argv, NO_PERSIST)) { - _wantPersist = false; - } - qDebug("wantPersist=%s", debug::valueOf(_wantPersist)); - // if we want Persistence, set up the local file and persist thread if (_wantPersist) { - // Check to see if the user passed in a command line option for setting packet send rate - const char* PERSIST_FILENAME = "--persistFilename"; - const char* persistFilenameParameter = getCmdOption(_argc, _argv, PERSIST_FILENAME); - if (persistFilenameParameter) { - strcpy(_persistFilename, persistFilenameParameter); - } else { - strcpy(_persistFilename, getMyDefaultPersistFilename()); - } - - qDebug("persistFilename=%s", _persistFilename); - // now set up PersistThread _persistThread = new OctreePersistThread(_tree, _persistFilename); if (_persistThread) { @@ -1027,41 +1118,6 @@ void OctreeServer::run() { } } - // Debug option to demonstrate that the server's local time does not - // need to be in sync with any other network node. This forces clock - // skew for the individual server node - const char* CLOCK_SKEW = "--clockSkew"; - const char* clockSkewOption = getCmdOption(_argc, _argv, CLOCK_SKEW); - if (clockSkewOption) { - int clockSkew = atoi(clockSkewOption); - usecTimestampNowForceClockSkew(clockSkew); - qDebug("clockSkewOption=%s clockSkew=%d", clockSkewOption, clockSkew); - } - - // Check to see if the user passed in a command line option for setting packet send rate - const char* PACKETS_PER_SECOND_PER_CLIENT_MAX = "--packetsPerSecondPerClientMax"; - const char* packetsPerSecondPerClientMax = getCmdOption(_argc, _argv, PACKETS_PER_SECOND_PER_CLIENT_MAX); - if (packetsPerSecondPerClientMax) { - _packetsPerClientPerInterval = atoi(packetsPerSecondPerClientMax) / INTERVALS_PER_SECOND; - if (_packetsPerClientPerInterval < 1) { - _packetsPerClientPerInterval = 1; - } - } - qDebug("packetsPerSecondPerClientMax=%s _packetsPerClientPerInterval=%d", - packetsPerSecondPerClientMax, _packetsPerClientPerInterval); - - // Check to see if the user passed in a command line option for setting packet send rate - const char* PACKETS_PER_SECOND_TOTAL_MAX = "--packetsPerSecondTotalMax"; - const char* packetsPerSecondTotalMax = getCmdOption(_argc, _argv, PACKETS_PER_SECOND_TOTAL_MAX); - if (packetsPerSecondTotalMax) { - _packetsTotalPerInterval = atoi(packetsPerSecondTotalMax) / INTERVALS_PER_SECOND; - if (_packetsTotalPerInterval < 1) { - _packetsTotalPerInterval = 1; - } - } - qDebug("packetsPerSecondTotalMax=%s _packetsTotalPerInterval=%d", - packetsPerSecondTotalMax, _packetsTotalPerInterval); - HifiSockAddr senderSockAddr; // set up our jurisdiction broadcaster... diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index 2fcaae8c78..b05896596c 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -69,6 +69,7 @@ public: virtual const char* getMyLoggingServerTargetName() const = 0; virtual const char* getMyDefaultPersistFilename() const = 0; virtual PacketType getMyEditNackType() const = 0; + virtual QString getMyDomainSettingsKey() const { return QString("octree_server_settings"); } // subclass may implement these method virtual void beforeRun() { } @@ -131,6 +132,11 @@ public slots: void readPendingDatagram(const QByteArray& receivedPacket, const HifiSockAddr& senderSockAddr); protected: + bool readOptionBool(const QString& optionName, const QJsonObject& settingsSectionObject, bool& result); + bool readOptionInt(const QString& optionName, const QJsonObject& settingsSectionObject, int& result); + bool readOptionString(const QString& optionName, const QJsonObject& settingsSectionObject, QString& result); + void readConfiguration(); + virtual void readAdditionalConfiguration(const QJsonObject& settingsSectionObject) { }; void parsePayload(); void initHTTPManager(int port); void resetSendingStats(); diff --git a/assignment-client/src/voxels/VoxelServer.cpp b/assignment-client/src/voxels/VoxelServer.cpp index b021ddd9f6..237b6d5006 100644 --- a/assignment-client/src/voxels/VoxelServer.cpp +++ b/assignment-client/src/voxels/VoxelServer.cpp @@ -82,8 +82,9 @@ int VoxelServer::sendSpecialPacket(const SharedNodePointer& node, OctreeQueryNod } -void VoxelServer::beforeRun() { +void VoxelServer::readAdditionalConfiguration(const QJsonObject& settingsSectionObject) { // should we send environments? Default is yes, but this command line suppresses sending + /* const char* SEND_ENVIRONMENTS = "--sendEnvironments"; bool dontSendEnvironments = !cmdOptionExists(_argc, _argv, SEND_ENVIRONMENTS); if (dontSendEnvironments) { @@ -96,6 +97,19 @@ void VoxelServer::beforeRun() { _sendMinimalEnvironment = cmdOptionExists(_argc, _argv, MINIMAL_ENVIRONMENT); qDebug("Using Minimal Environment=%s", debug::valueOf(_sendMinimalEnvironment)); } + */ + readOptionBool(QString("sendEnvironments"), settingsSectionObject, _sendEnvironments); + bool dontSendEnvironments = !_sendEnvironments; + if (dontSendEnvironments) { + qDebug("Sending environments suppressed..."); + } else { + // should we send environments? Default is yes, but this command line suppresses sending + //const char* MINIMAL_ENVIRONMENT = "--minimalEnvironment"; + //_sendMinimalEnvironment = cmdOptionExists(_argc, _argv, MINIMAL_ENVIRONMENT); + + readOptionBool(QString("minimalEnvironment"), settingsSectionObject, _sendMinimalEnvironment); + qDebug("Using Minimal Environment=%s", debug::valueOf(_sendMinimalEnvironment)); + } qDebug("Sending environments=%s", debug::valueOf(_sendEnvironments)); NodeList::getInstance()->addNodeTypeToInterestSet(NodeType::AnimationServer); diff --git a/assignment-client/src/voxels/VoxelServer.h b/assignment-client/src/voxels/VoxelServer.h index fadcca2d19..f4b6bd3a42 100644 --- a/assignment-client/src/voxels/VoxelServer.h +++ b/assignment-client/src/voxels/VoxelServer.h @@ -43,12 +43,15 @@ public: virtual const char* getMyLoggingServerTargetName() const { return VOXEL_SERVER_LOGGING_TARGET_NAME; } virtual const char* getMyDefaultPersistFilename() const { return LOCAL_VOXELS_PERSIST_FILE; } virtual PacketType getMyEditNackType() const { return PacketTypeVoxelEditNack; } + virtual QString getMyDomainSettingsKey() const { return QString("voxel_server_settings"); } // subclass may implement these method - virtual void beforeRun(); virtual bool hasSpecialPacketToSend(const SharedNodePointer& node); virtual int sendSpecialPacket(const SharedNodePointer& node, OctreeQueryNode* queryNode, int& packetsSent); +protected: + virtual void readAdditionalConfiguration(const QJsonObject& settingsSectionObject); + private: bool _sendEnvironments; bool _sendMinimalEnvironment; diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 026fe252b2..602a9b4a1e 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -262,5 +262,85 @@ "advanced": true } ] - } + }, + { + "name": "entity_server_settings", + "label": "Entity Server Settings", + "assignment-types": [6], + "settings": [ + { + "name": "statusHost", + "label": "Status Hostname", + "help": "host name or IP address of the server for accessing the status page", + "placeholder": "", + "default": "", + "advanced": true + }, + { + "name": "statusPort", + "label": "Status Port", + "help": "port of the server for accessing the status page", + "placeholder": "", + "default": "", + "advanced": true + }, + { + "name": "clockSkew", + "label": "Clock Skew", + "help": "Number of msecs to skew the server clock by to test clock skew", + "placeholder": "0", + "default": "0", + "advanced": true + } + ] + }, + + + { + "name": "voxel_server_settings", + "label": "Voxel Server Settings", + "assignment-types": [3], + "settings": [ + + { + "name": "statusHost", + "label": "Status Hostname", + "help": "host name or IP address of the server for accessing the status page", + "placeholder": "", + "default": "", + "advanced": true + }, + { + "name": "statusPort", + "label": "Status Port", + "help": "port of the server for accessing the status page", + "placeholder": "", + "default": "", + "advanced": true + }, + { + "name": "clockSkew", + "label": "Clock Skew", + "help": "Number of msecs to skew the server clock by to test clock skew", + "placeholder": "0", + "default": "0", + "advanced": true + }, + { + "name": "sendEnvironments", + "type": "checkbox", + "help": "send environmental data", + "default": false, + "advanced": true + }, + { + "name": "minimalEnvironment", + "type": "checkbox", + "help": "send minimal environmental data if sending environmental data", + "default": false, + "advanced": true + } + ] + } + ] \ No newline at end of file From 4ea0d32c8c1e09ea59a04b2bac5bd72221cdf3be Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 5 Nov 2014 12:14:09 -0800 Subject: [PATCH 26/39] dead code --- assignment-client/src/voxels/VoxelServer.cpp | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/assignment-client/src/voxels/VoxelServer.cpp b/assignment-client/src/voxels/VoxelServer.cpp index 237b6d5006..a83e3e99e3 100644 --- a/assignment-client/src/voxels/VoxelServer.cpp +++ b/assignment-client/src/voxels/VoxelServer.cpp @@ -84,20 +84,6 @@ int VoxelServer::sendSpecialPacket(const SharedNodePointer& node, OctreeQueryNod void VoxelServer::readAdditionalConfiguration(const QJsonObject& settingsSectionObject) { // should we send environments? Default is yes, but this command line suppresses sending - /* - const char* SEND_ENVIRONMENTS = "--sendEnvironments"; - bool dontSendEnvironments = !cmdOptionExists(_argc, _argv, SEND_ENVIRONMENTS); - if (dontSendEnvironments) { - qDebug("Sending environments suppressed..."); - _sendEnvironments = false; - } else { - _sendEnvironments = true; - // should we send environments? Default is yes, but this command line suppresses sending - const char* MINIMAL_ENVIRONMENT = "--minimalEnvironment"; - _sendMinimalEnvironment = cmdOptionExists(_argc, _argv, MINIMAL_ENVIRONMENT); - qDebug("Using Minimal Environment=%s", debug::valueOf(_sendMinimalEnvironment)); - } - */ readOptionBool(QString("sendEnvironments"), settingsSectionObject, _sendEnvironments); bool dontSendEnvironments = !_sendEnvironments; if (dontSendEnvironments) { From 13e358549dae6c26f1bf647668176e14488a0b6f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 5 Nov 2014 14:56:38 -0800 Subject: [PATCH 27/39] add periodic pruning of the octree on load and save --- libraries/entities/src/EntityTree.cpp | 18 ++++++++++++++++++ libraries/entities/src/EntityTree.h | 1 + libraries/entities/src/EntityTreeElement.cpp | 19 ++++++++++++++----- libraries/octree/src/Octree.h | 1 + libraries/octree/src/OctreePersistThread.cpp | 9 +++++++-- 5 files changed, 41 insertions(+), 7 deletions(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 61dbbda698..21df5498ec 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1069,6 +1069,24 @@ void EntityTree::dumpTree() { recurseTreeWithOperator(&theOperator); } +class PruneOperator : public RecurseOctreeOperator { +public: + virtual bool preRecursion(OctreeElement* element) { return true; } + virtual bool postRecursion(OctreeElement* element); +}; + +bool PruneOperator::postRecursion(OctreeElement* element) { + EntityTreeElement* entityTreeElement = static_cast(element); + entityTreeElement->pruneChildren(); + return true; +} + +void EntityTree::pruneTree() { + // First, look for the existing entity in the tree.. + PruneOperator theOperator; + recurseTreeWithOperator(&theOperator); +} + void EntityTree::sendEntities(EntityEditPacketSender* packetSender, EntityTree* localTree, float x, float y, float z) { SendEntitiesOperationArgs args; args.packetSender = packetSender; diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 634a04a688..53b407c7f5 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -131,6 +131,7 @@ public: void resetContainingElement(const EntityItemID& entityItemID, EntityTreeElement* element); void debugDumpMap(); virtual void dumpTree(); + virtual void pruneTree(); void sendEntities(EntityEditPacketSender* packetSender, EntityTree* localTree, float x, float y, float z); diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index da7d5db226..59dce80ecc 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -812,11 +812,20 @@ bool EntityTreeElement::pruneChildren() { void EntityTreeElement::debugDump() { qDebug() << "EntityTreeElement..."; - qDebug() << "entity count:" << _entityItems->size(); - qDebug() << "cube:" << getAACube(); - for (uint16_t i = 0; i < _entityItems->size(); i++) { - EntityItem* entity = (*_entityItems)[i]; - entity->debugDump(); + AACube temp = getAACube(); + temp.scale((float)TREE_SCALE); + qDebug() << " cube:" << temp; + qDebug() << " has child elements:" << getChildCount(); + if (_entityItems->size()) { + qDebug() << " has entities:" << _entityItems->size(); + qDebug() << "--------------------------------------------------"; + for (uint16_t i = 0; i < _entityItems->size(); i++) { + EntityItem* entity = (*_entityItems)[i]; + entity->debugDump(); + } + qDebug() << "--------------------------------------------------"; + } else { + qDebug() << " NO entities!"; } } diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index da0e483e1e..42cbb3c38d 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -352,6 +352,7 @@ public: void setIsClient(bool isClient) { _isServer = !isClient; } virtual void dumpTree() { }; + virtual void pruneTree() { }; signals: void importSize(float x, float y, float z); diff --git a/libraries/octree/src/OctreePersistThread.cpp b/libraries/octree/src/OctreePersistThread.cpp index 7613e2332b..406681c2c5 100644 --- a/libraries/octree/src/OctreePersistThread.cpp +++ b/libraries/octree/src/OctreePersistThread.cpp @@ -36,6 +36,7 @@ bool OctreePersistThread::process() { { PerformanceWarning warn(true, "Loading Octree File", true); persistantFileRead = _tree->readFromSVOFile(_filename.toLocal8Bit().constData()); + _tree->pruneTree(); } _tree->unlock(); @@ -80,10 +81,14 @@ bool OctreePersistThread::process() { // check the dirty bit and persist here... _lastCheck = usecTimestampNow(); if (_tree->isDirty()) { - qDebug() << "saving Octrees to file " << _filename << "..."; + qDebug() << "pruning Octree before saving..."; + _tree->pruneTree(); + qDebug() << "DONE pruning Octree before saving..."; + + qDebug() << "saving Octree to file " << _filename << "..."; _tree->writeToSVOFile(_filename.toLocal8Bit().constData()); _tree->clearDirtyBit(); // tree is clean after saving - qDebug("DONE saving Octrees to file..."); + qDebug("DONE saving Octree to file..."); } } } From fd00461b4e73fc6d8dcb8f16e3c83f2a3024bf31 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 5 Nov 2014 16:50:34 -0800 Subject: [PATCH 28/39] Perspective correction fix (lets us use lower tesselation on light volumes). --- .../resources/shaders/deferred_light_limited.vert | 3 ++- interface/resources/shaders/point_light.frag | 11 ++++++----- interface/resources/shaders/spot_light.frag | 11 ++++++----- interface/src/renderer/DeferredLightingEffect.cpp | 4 ++-- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/interface/resources/shaders/deferred_light_limited.vert b/interface/resources/shaders/deferred_light_limited.vert index 849d14bda4..f360f0307d 100644 --- a/interface/resources/shaders/deferred_light_limited.vert +++ b/interface/resources/shaders/deferred_light_limited.vert @@ -14,5 +14,6 @@ void main(void) { gl_Position = ftransform(); vec4 projected = gl_Position / gl_Position.w; - gl_TexCoord[0] = vec4(dot(projected, gl_ObjectPlaneS[3]), dot(projected, gl_ObjectPlaneT[3]), 0.0, 1.0); + gl_TexCoord[0] = vec4(dot(projected, gl_ObjectPlaneS[3]) * gl_Position.w, + dot(projected, gl_ObjectPlaneT[3]) * gl_Position.w, 0.0, gl_Position.w); } diff --git a/interface/resources/shaders/point_light.frag b/interface/resources/shaders/point_light.frag index b9ba638885..1d1b4f4073 100644 --- a/interface/resources/shaders/point_light.frag +++ b/interface/resources/shaders/point_light.frag @@ -40,16 +40,17 @@ uniform float radius; void main(void) { // get the depth and exit early if it doesn't pass the test - float depth = texture2D(depthMap, gl_TexCoord[0].st).r; + vec2 texCoord = gl_TexCoord[0].st / gl_TexCoord[0].q; + float depth = texture2D(depthMap, texCoord).r; if (depth < gl_FragCoord.z) { discard; } // compute the view space position using the depth float z = near / (depth * depthScale - 1.0); - vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 1.0); + vec4 position = vec4((depthTexCoordOffset + texCoord * depthTexCoordScale) * z, z, 1.0); // get the normal from the map - vec4 normal = texture2D(normalMap, gl_TexCoord[0].st); + vec4 normal = texture2D(normalMap, texCoord); vec4 normalizedNormal = normalize(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0)); // compute the base color based on OpenGL lighting model @@ -58,7 +59,7 @@ void main(void) { lightVector = lightVector / lightDistance; float diffuse = dot(normalizedNormal, lightVector); float facingLight = step(0.0, diffuse); - vec4 baseColor = texture2D(diffuseMap, gl_TexCoord[0].st) * (gl_FrontLightProduct[1].ambient + + vec4 baseColor = texture2D(diffuseMap, texCoord) * (gl_FrontLightProduct[1].ambient + gl_FrontLightProduct[1].diffuse * (diffuse * facingLight)); // compute attenuation based on distance, etc. @@ -69,6 +70,6 @@ void main(void) { // add base to specular, modulate by attenuation float specular = facingLight * max(0.0, dot(normalize(lightVector - normalize(vec4(position.xyz, 0.0))), normalizedNormal)); - vec4 specularColor = texture2D(specularMap, gl_TexCoord[0].st); + vec4 specularColor = texture2D(specularMap, texCoord); gl_FragColor = vec4((baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb) * attenuation, 0.0); } diff --git a/interface/resources/shaders/spot_light.frag b/interface/resources/shaders/spot_light.frag index a496abd7b2..590ed8b6ac 100644 --- a/interface/resources/shaders/spot_light.frag +++ b/interface/resources/shaders/spot_light.frag @@ -40,16 +40,17 @@ uniform float radius; void main(void) { // get the depth and exit early if it doesn't pass the test - float depth = texture2D(depthMap, gl_TexCoord[0].st).r; + vec2 texCoord = gl_TexCoord[0].st / gl_TexCoord[0].q; + float depth = texture2D(depthMap, texCoord).r; if (depth < gl_FragCoord.z) { discard; } // compute the view space position using the depth float z = near / (depth * depthScale - 1.0); - vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 1.0); + vec4 position = vec4((depthTexCoordOffset + texCoord * depthTexCoordScale) * z, z, 1.0); // get the normal from the map - vec4 normal = texture2D(normalMap, gl_TexCoord[0].st); + vec4 normal = texture2D(normalMap, texCoord); vec4 normalizedNormal = normalize(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0)); // compute the base color based on OpenGL lighting model @@ -58,7 +59,7 @@ void main(void) { lightVector = lightVector / lightDistance; float diffuse = dot(normalizedNormal, lightVector); float facingLight = step(0.0, diffuse); - vec4 baseColor = texture2D(diffuseMap, gl_TexCoord[0].st) * (gl_FrontLightProduct[1].ambient + + vec4 baseColor = texture2D(diffuseMap, texCoord) * (gl_FrontLightProduct[1].ambient + gl_FrontLightProduct[1].diffuse * (diffuse * facingLight)); // compute attenuation based on spot angle, distance, etc. @@ -71,6 +72,6 @@ void main(void) { // add base to specular, modulate by attenuation float specular = facingLight * max(0.0, dot(normalize(lightVector - normalize(vec4(position.xyz, 0.0))), normalizedNormal)); - vec4 specularColor = texture2D(specularMap, gl_TexCoord[0].st); + vec4 specularColor = texture2D(specularMap, texCoord); gl_FragColor = vec4((baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb) * attenuation, 0.0); } diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index 6e96d106cc..fa07bf419d 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -269,7 +269,7 @@ void DeferredLightingEffect::render() { } else { glTranslatef(light.position.x, light.position.y, light.position.z); - Application::getInstance()->getGeometryCache()->renderSphere(expandedRadius, 64, 64); + Application::getInstance()->getGeometryCache()->renderSphere(expandedRadius, 32, 32); } glPopMatrix(); @@ -323,7 +323,7 @@ void DeferredLightingEffect::render() { glRotatef(glm::degrees(glm::angle(spotRotation)), axis.x, axis.y, axis.z); glTranslatef(0.0f, 0.0f, -light.radius * (1.0f + SCALE_EXPANSION * 0.5f)); Application::getInstance()->getGeometryCache()->renderCone(expandedRadius * glm::tan(light.cutoff), - expandedRadius, 64, 32); + expandedRadius, 32, 1); } glPopMatrix(); From 688bd0f34f53170a4af6c84e3cfa833971bb7c10 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 5 Nov 2014 16:58:58 -0800 Subject: [PATCH 29/39] first pass audio mixer automatic muting of noisy streams, tour guide improvements, new lightExample.js, hair hangs over cone 'body' --- assignment-client/src/audio/AudioMixer.cpp | 16 +++++-- .../resources/describe-settings.json | 8 ++++ examples/guidedTour.js | 11 ++--- examples/lightExample.js | 46 +++++++++++++++++++ interface/src/Audio.cpp | 3 +- interface/src/Hair.cpp | 21 ++++++--- interface/src/entities/EntityTreeRenderer.cpp | 2 +- libraries/audio/src/AudioInjector.cpp | 19 +++++++- libraries/audio/src/AudioInjector.h | 3 ++ .../audio/src/AudioScriptingInterface.cpp | 10 +++- libraries/audio/src/AudioScriptingInterface.h | 1 + libraries/audio/src/PositionalAudioStream.cpp | 7 +-- 12 files changed, 121 insertions(+), 26 deletions(-) create mode 100644 examples/lightExample.js diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 25e21b5d3a..61ad111574 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -61,8 +61,7 @@ const float LOUDNESS_TO_DISTANCE_RATIO = 0.00001f; const float DEFAULT_ATTENUATION_PER_DOUBLING_IN_DISTANCE = 0.18; -const float DEFAULT_NOISE_MUTING_THRESHOLD = 100.0f; - +const float DEFAULT_NOISE_MUTING_THRESHOLD = 0.003f; const QString AUDIO_MIXER_LOGGING_TARGET_NAME = "audio-mixer"; const QString AUDIO_ENV_GROUP_KEY = "audio_env"; const QString AUDIO_BUFFER_GROUP_KEY = "audio_buffer"; @@ -81,7 +80,6 @@ bool AudioMixer::_enableFilter = true; bool AudioMixer::shouldMute(float quietestFrame, float loudestFrame) { return (quietestFrame > _noiseMutingThreshold); - qDebug() << "Muting, quiestest frame = " << quietestFrame; } AudioMixer::AudioMixer(const QByteArray& packet) : @@ -1015,7 +1013,17 @@ void AudioMixer::parseSettingsObject(const QJsonObject &settingsObject) { qDebug() << "Attenuation per doubling in distance changed to" << _attenuationPerDoublingInDistance; } } - + + const QString NOISE_MUTING_THRESHOLD = "noise_muting_threshold"; + if (audioEnvGroupObject[NOISE_MUTING_THRESHOLD].isString()) { + bool ok = false; + float noiseMutingThreshold = audioEnvGroupObject[NOISE_MUTING_THRESHOLD].toString().toFloat(&ok); + if (ok) { + _noiseMutingThreshold = noiseMutingThreshold; + qDebug() << "Noise muting threshold changed to" << _noiseMutingThreshold; + } + } + const QString FILTER_KEY = "enable_filter"; if (audioEnvGroupObject[FILTER_KEY].isBool()) { _enableFilter = audioEnvGroupObject[FILTER_KEY].toBool(); diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 026fe252b2..c044126a80 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -89,6 +89,14 @@ "default": "0.18", "advanced": false }, + { + "name": "noise_muting_threshold", + "label": "Noise Muting Threshold", + "help": "Loudness value for noise background between 0 and 1.0 (0: mute everyone, 1.0: never mute)", + "placeholder": "0.003", + "default": "0.003", + "advanced": false + }, { "name": "enable_filter", "type": "checkbox", diff --git a/examples/guidedTour.js b/examples/guidedTour.js index 1882b527d7..8729850927 100644 --- a/examples/guidedTour.js +++ b/examples/guidedTour.js @@ -12,6 +12,8 @@ var MIN_CHANGE = 2.0; var LANDING_DISTANCE = 2.0; var LANDING_RANDOM = 0.2; +var relativePosition; + function update(deltaTime) { if (Math.random() < deltaTime) { @@ -26,20 +28,15 @@ function update(deltaTime) { } if (guide) { + relativePosition = Vec3.subtract(MyAvatar.position, lastGuidePosition); // Check whether guide has moved, update if so if (Vec3.length(lastGuidePosition) == 0.0) { lastGuidePosition = guide.position; } else { if (Vec3.length(Vec3.subtract(lastGuidePosition, guide.position)) > MIN_CHANGE) { - var meToGuide = Vec3.multiply(Vec3.normalize(Vec3.subtract(guide.position, MyAvatar.position)), LANDING_DISTANCE); - var newPosition = Vec3.subtract(guide.position, meToGuide); - newPosition = Vec3.sum(newPosition, { x: Math.random() * LANDING_RANDOM - LANDING_RANDOM / 2.0, - y: 0, - z: Math.random() * LANDING_RANDOM - LANDING_RANDOM / 2.0 }); + var newPosition = Vec3.sum(guide.position, relativePosition); MyAvatar.position = newPosition; - lastGuidePosition = guide.position; - MyAvatar.orientation = guide.orientation; } } } diff --git a/examples/lightExample.js b/examples/lightExample.js new file mode 100644 index 0000000000..3781a2bc7e --- /dev/null +++ b/examples/lightExample.js @@ -0,0 +1,46 @@ +// +// spotlightExample.js +// examples +// +// Created by Brad Hefta-Gaub on 10/28/14. +// Copyright 2014 High Fidelity, Inc. +// +// This is an example script that demonstrates creating and editing a particle +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var position = Vec3.sum(MyAvatar.position, Quat.getFront(Camera.getOrientation())); + +var sphereID = Entities.addEntity({ + type: "Sphere", + position: position, + dimensions: { x: 0.1, y: 0.1, z: 0.1 }, + color: { red: 255, green: 255, blue: 0 } + }); + +var lightID = Entities.addEntity({ + type: "Light", + position: position, + dimensions: { x: 1, y: 1, z: 1 }, + angularVelocity: { x: 0, y: 0, z: 0 }, + angularDamping: 0, + + isSpotlight: false, + diffuseColor: { red: 255, green: 255, blue: 0 }, + ambientColor: { red: 0, green: 0, blue: 0 }, + specularColor: { red: 255, green: 255, blue: 255 }, + + constantAttenuation: 0, + linearAttenuation: 1, + quadraticAttenuation: 0, + exponent: 0, + cutoff: 180, // in degrees +}); + +Script.scriptEnding.connect(function() { + print("Deleted sphere and light"); + Entities.deleteEntity(sphereID); + Entities.deleteEntity(lightID); +}); diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 0c28f0a943..8c207c3d21 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -728,9 +728,8 @@ void Audio::handleAudioInput() { _loudestFrame = _lastInputLoudness; } - const int FRAMES_FOR_NOISE_DETECTION = 300; + const int FRAMES_FOR_NOISE_DETECTION = 400; if (_inputFrameCounter++ > FRAMES_FOR_NOISE_DETECTION) { - qDebug() << "Quietest/loudest frame: " << _quietestFrame << " / " << _loudestFrame << " NGfloor: " << _noiseGateMeasuredFloor; _quietestFrame = std::numeric_limits::max(); _loudestFrame = 0.0f; _inputFrameCounter = 0; diff --git a/interface/src/Hair.cpp b/interface/src/Hair.cpp index acc00c14b0..637e00a8bc 100644 --- a/interface/src/Hair.cpp +++ b/interface/src/Hair.cpp @@ -52,12 +52,10 @@ Hair::Hair(int strands, glm::vec3 thisVertex; for (int strand = 0; strand < _strands; strand++) { float strandAngle = randFloat() * PI; - float azimuth; - float elevation = - (randFloat() * PI); - azimuth = PI_OVER_TWO; - if (randFloat() < 0.5f) { - azimuth *= -1.0f; - } + + float azimuth = (float)strand / (float)_strands * PI * 2.0f; + float elevation = 0.0f; + glm::vec3 thisStrand(sinf(azimuth) * cosf(elevation), sinf(elevation), -cosf(azimuth) * cosf(elevation)); thisStrand *= _radius; @@ -115,11 +113,22 @@ void Hair::simulate(float deltaTime) { glm::vec3 diff = thisPosition - _hairLastPosition[vertexIndex]; _hairPosition[vertexIndex] += diff * HAIR_DAMPING; + /* // Resolve collisions with sphere if (glm::length(_hairPosition[vertexIndex]) < _radius) { _hairPosition[vertexIndex] += glm::normalize(_hairPosition[vertexIndex]) * (_radius - glm::length(_hairPosition[vertexIndex])); + } */ + + // Collide with a conical body descending from the root of the hair + glm::vec3 thisVertex = _hairPosition[vertexIndex]; + float depth = -thisVertex.y; + thisVertex.y = 0.0f; + const float BODY_CONE_ANGLE = 0.30; + if (glm::length(thisVertex) < depth * BODY_CONE_ANGLE) { + _hairPosition[vertexIndex] += glm::normalize(thisVertex) * (depth * BODY_CONE_ANGLE - glm::length(thisVertex)); } + // Add random thing driven by loudness float loudnessFactor = (_loudness > SOUND_THRESHOLD) ? logf(_loudness - SOUND_THRESHOLD) / 2000.0f : 0.0f; diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index e447c703fb..3b31fef0ee 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -1,4 +1,4 @@ -// + // // EntityTreeRenderer.cpp // interface/src // diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 31c135fd58..fe58de578f 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -26,7 +26,8 @@ AudioInjector::AudioInjector(QObject* parent) : _sound(NULL), _options(), _shouldStop(false), - _currentSendPosition(0) + _currentSendPosition(0), + _loudness(0.0f) { } @@ -34,7 +35,8 @@ AudioInjector::AudioInjector(Sound* sound, const AudioInjectorOptions& injectorO _sound(sound), _options(injectorOptions), _shouldStop(false), - _currentSendPosition(0) + _currentSendPosition(0), + _loudness(0.0f) { } @@ -42,6 +44,10 @@ void AudioInjector::setOptions(AudioInjectorOptions& options) { _options = options; } +float AudioInjector::getLoudness() { + return _loudness; +} + const uchar MAX_INJECTOR_VOLUME = 0xFF; void AudioInjector::injectAudio() { @@ -113,6 +119,15 @@ void AudioInjector::injectAudio() { int bytesToCopy = std::min(((_options.isStereo()) ? 2 : 1) * NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL, soundByteArray.size() - _currentSendPosition); + + // Measure the loudness of this frame + _loudness = 0.0f; + for (int i = 0; i < bytesToCopy; i += sizeof(int16_t)) { + _loudness += abs(*reinterpret_cast(soundByteArray.data() + _currentSendPosition + i)) / + (MAX_SAMPLE_VALUE / 2.0f); + } + _loudness /= (float)(bytesToCopy / sizeof(int16_t)); + memcpy(injectAudioPacket.data() + positionOptionOffset, &_options.getPosition(), sizeof(_options.getPosition())); diff --git a/libraries/audio/src/AudioInjector.h b/libraries/audio/src/AudioInjector.h index af9b5e55d1..6465337a47 100644 --- a/libraries/audio/src/AudioInjector.h +++ b/libraries/audio/src/AudioInjector.h @@ -33,6 +33,8 @@ public slots: void stop() { _shouldStop = true; } void setOptions(AudioInjectorOptions& options); void setCurrentSendPosition(int currentSendPosition) { _currentSendPosition = currentSendPosition; } + float getLoudness(); + signals: void finished(); private: @@ -40,6 +42,7 @@ private: AudioInjectorOptions _options; bool _shouldStop; int _currentSendPosition; + float _loudness; }; Q_DECLARE_METATYPE(AudioInjector*) diff --git a/libraries/audio/src/AudioScriptingInterface.cpp b/libraries/audio/src/AudioScriptingInterface.cpp index 43c7d35c1d..b1499b2e01 100644 --- a/libraries/audio/src/AudioScriptingInterface.cpp +++ b/libraries/audio/src/AudioScriptingInterface.cpp @@ -45,7 +45,15 @@ bool AudioScriptingInterface::isInjectorPlaying(AudioInjector* injector) { return (injector != NULL); } -void AudioScriptingInterface::startDrumSound(float volume, float frequency, float duration, float decay, +float AudioScriptingInterface::getLoudness(AudioInjector* injector) { + if (injector) { + return injector->getLoudness(); + } else { + return 0.0f; + } +} + +void AudioScriptingInterface::startDrumSound(float volume, float frequency, float duration, float decay, const AudioInjectorOptions* injectorOptions) { Sound* sound = new Sound(volume, frequency, duration, decay); diff --git a/libraries/audio/src/AudioScriptingInterface.h b/libraries/audio/src/AudioScriptingInterface.h index 343eac304c..4f9f87ea21 100644 --- a/libraries/audio/src/AudioScriptingInterface.h +++ b/libraries/audio/src/AudioScriptingInterface.h @@ -23,6 +23,7 @@ public slots: static AudioInjector* playSound(Sound* sound, const AudioInjectorOptions* injectorOptions = NULL); static void stopInjector(AudioInjector* injector); static bool isInjectorPlaying(AudioInjector* injector); + static float getLoudness(AudioInjector* injector); static void startDrumSound(float volume, float frequency, float duration, float decay, const AudioInjectorOptions* injectorOptions = NULL); diff --git a/libraries/audio/src/PositionalAudioStream.cpp b/libraries/audio/src/PositionalAudioStream.cpp index 49129659b6..8a6bcb629f 100644 --- a/libraries/audio/src/PositionalAudioStream.cpp +++ b/libraries/audio/src/PositionalAudioStream.cpp @@ -45,8 +45,9 @@ void PositionalAudioStream::resetStats() { void PositionalAudioStream::updateLastPopOutputLoudnessAndTrailingLoudness() { _lastPopOutputLoudness = _ringBuffer.getFrameLoudness(_lastPopOutput); - const int TRAILING_AVERAGE_FRAMES = 100; - const float CURRENT_FRAME_RATIO = 1.0f / TRAILING_AVERAGE_FRAMES; + const int TRAILING_MUTE_THRESHOLD_FRAMES = 400; + const int TRAILING_LOUDNESS_FRAMES = 200; + const float CURRENT_FRAME_RATIO = 1.0f / TRAILING_LOUDNESS_FRAMES; const float PREVIOUS_FRAMES_RATIO = 1.0f - CURRENT_FRAME_RATIO; const float LOUDNESS_EPSILON = 0.000001f; @@ -59,7 +60,7 @@ void PositionalAudioStream::updateLastPopOutputLoudnessAndTrailingLoudness() { _lastPopOutputTrailingLoudness = 0; } } - if (_frameCounter++ == TRAILING_AVERAGE_FRAMES) { + if (_frameCounter++ == TRAILING_MUTE_THRESHOLD_FRAMES) { _frameCounter = 0; _quietestTrailingFrameLoudness = std::numeric_limits::max(); _loudestTrailingFrameLoudness = 0.0f; From 0b205f3f1619d91a6ead9e98d6db01dc8014f1fb Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 5 Nov 2014 17:06:00 -0800 Subject: [PATCH 30/39] fix bad spaces --- interface/src/entities/EntityTreeRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index 3b31fef0ee..e447c703fb 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -1,4 +1,4 @@ - // +// // EntityTreeRenderer.cpp // interface/src // From 291767fd9e3dc93e6b35db5f710f3df827bd970c Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 5 Nov 2014 17:09:26 -0800 Subject: [PATCH 31/39] updated header --- examples/lightExample.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/lightExample.js b/examples/lightExample.js index 3781a2bc7e..7a90eb8714 100644 --- a/examples/lightExample.js +++ b/examples/lightExample.js @@ -1,11 +1,11 @@ // -// spotlightExample.js +// lightExample.js // examples // -// Created by Brad Hefta-Gaub on 10/28/14. +// Created by Philip Rosedale on November 5, 2014 // Copyright 2014 High Fidelity, Inc. // -// This is an example script that demonstrates creating and editing a particle +// Makes a light right in front of your avatar, as well as a sphere at that location. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html From bcec14b0f4640a30aa472dd799bccf9efca0d3a4 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 5 Nov 2014 19:37:08 -0800 Subject: [PATCH 32/39] adjust the sentAt times in packets by the receiving side's clockskew so that it can calculate proper flight times --- .../octree/OctreeInboundPacketProcessor.cpp | 19 ++++++++++++++--- .../resources/describe-settings.json | 21 +++++++++++++++++++ .../octree/src/OctreeEditPacketSender.cpp | 10 ++++----- libraries/octree/src/OctreeEditPacketSender.h | 2 +- 4 files changed, 42 insertions(+), 10 deletions(-) diff --git a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp index bd3a7ceee5..b9bde8d544 100644 --- a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp +++ b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp @@ -98,15 +98,28 @@ void OctreeInboundPacketProcessor::processPacket(const SharedNodePointer& sendin unsigned short int sequence = (*((unsigned short int*)(packetData + numBytesPacketHeader))); quint64 sentAt = (*((quint64*)(packetData + numBytesPacketHeader + sizeof(sequence)))); quint64 arrivedAt = usecTimestampNow(); + if (sentAt > arrivedAt) { + if (debugProcessPacket || _myServer->wantsDebugReceiving()) { + qDebug() << "unreasonable sentAt=" << sentAt << " usecs"; + qDebug() << "setting sentAt to arrivedAt=" << arrivedAt << " usecs"; + } + sentAt = arrivedAt; + } quint64 transitTime = arrivedAt - sentAt; int editsInPacket = 0; quint64 processTime = 0; quint64 lockWaitTime = 0; if (debugProcessPacket || _myServer->wantsDebugReceiving()) { - qDebug() << "PROCESSING THREAD: got '" << packetType << "' packet - " << _receivedPacketCount - << " command from client receivedBytes=" << packet.size() - << " sequence=" << sequence << " transitTime=" << transitTime << " usecs"; + qDebug() << "PROCESSING THREAD: got '" << packetType << "' packet - " << _receivedPacketCount << " command from client"; + qDebug() << " receivedBytes=" << packet.size(); + qDebug() << " sequence=" << sequence; + qDebug() << " sentAt=" << sentAt << " usecs"; + qDebug() << " arrivedAt=" << arrivedAt << " usecs"; + qDebug() << " transitTime=" << transitTime << " usecs"; + qDebug() << " sendingNode->getClockSkewUsec()=" << sendingNode->getClockSkewUsec() << " usecs"; + + } if (debugProcessPacket) { diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 602a9b4a1e..0a93136507 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -284,6 +284,27 @@ "default": "", "advanced": true }, + { + "name": "verboseDebug", + "type": "checkbox", + "help": "lots of debugging", + "default": false, + "advanced": true + }, + { + "name": "debugReceiving", + "type": "checkbox", + "help": "extra debugging on receiving", + "default": false, + "advanced": true + }, + { + "name": "debugSending", + "type": "checkbox", + "help": "extra debugging on sending", + "default": false, + "advanced": true + }, { "name": "clockSkew", "label": "Clock Skew", diff --git a/libraries/octree/src/OctreeEditPacketSender.cpp b/libraries/octree/src/OctreeEditPacketSender.cpp index 65308f906f..df52e85c5e 100644 --- a/libraries/octree/src/OctreeEditPacketSender.cpp +++ b/libraries/octree/src/OctreeEditPacketSender.cpp @@ -246,9 +246,7 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PacketType type, unsigned ch // But we can't really do that with a packed message, since each edit message could be destined // for a different server... So we need to actually manage multiple queued packets... one // for each server - _packetsQueueLock.lock(); - foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { // only send to the NodeTypes that are getMyNodeType() if (node->getActiveSocket() && node->getType() == getMyNodeType()) { @@ -277,12 +275,12 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PacketType type, unsigned ch if ((type != packetBuffer._currentType && packetBuffer._currentSize > 0) || (packetBuffer._currentSize + length >= (size_t)_maxPacketSize)) { releaseQueuedPacket(packetBuffer); - initializePacket(packetBuffer, type); + initializePacket(packetBuffer, type, node->getClockSkewUsec()); } // If the buffer is empty and not correctly initialized for our type... if (type != packetBuffer._currentType && packetBuffer._currentSize == 0) { - initializePacket(packetBuffer, type); + initializePacket(packetBuffer, type, node->getClockSkewUsec()); } // This is really the first time we know which server/node this particular edit message @@ -330,14 +328,14 @@ void OctreeEditPacketSender::releaseQueuedPacket(EditPacketBuffer& packetBuffer) _releaseQueuedPacketMutex.unlock(); } -void OctreeEditPacketSender::initializePacket(EditPacketBuffer& packetBuffer, PacketType type) { +void OctreeEditPacketSender::initializePacket(EditPacketBuffer& packetBuffer, PacketType type, int nodeClockSkew) { packetBuffer._currentSize = populatePacketHeader(reinterpret_cast(&packetBuffer._currentBuffer[0]), type); // skip over sequence number for now; will be packed when packet is ready to be sent out packetBuffer._currentSize += sizeof(quint16); // pack in timestamp - quint64 now = usecTimestampNow(); + quint64 now = usecTimestampNow() + nodeClockSkew; quint64* timeAt = (quint64*)&packetBuffer._currentBuffer[packetBuffer._currentSize]; *timeAt = now; packetBuffer._currentSize += sizeof(quint64); // nudge past timestamp diff --git a/libraries/octree/src/OctreeEditPacketSender.h b/libraries/octree/src/OctreeEditPacketSender.h index 9ba6a0243c..79b7a43ac4 100644 --- a/libraries/octree/src/OctreeEditPacketSender.h +++ b/libraries/octree/src/OctreeEditPacketSender.h @@ -101,7 +101,7 @@ protected: void queuePacketToNode(const QUuid& nodeID, unsigned char* buffer, size_t length, qint64 satoshiCost = 0); void queuePendingPacketToNodes(PacketType type, unsigned char* buffer, size_t length, qint64 satoshiCost = 0); void queuePacketToNodes(unsigned char* buffer, size_t length, qint64 satoshiCost = 0); - void initializePacket(EditPacketBuffer& packetBuffer, PacketType type); + void initializePacket(EditPacketBuffer& packetBuffer, PacketType type, int nodeClockSkew); void releaseQueuedPacket(EditPacketBuffer& packetBuffer); // releases specific queued packet void processPreServerExistsPackets(); From b103c62df99fb45f0f9891a0d076cc0bed12815b Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 6 Nov 2014 08:30:33 -0800 Subject: [PATCH 33/39] add new birdSongs.js --- examples/birdSongs.js | 164 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 examples/birdSongs.js diff --git a/examples/birdSongs.js b/examples/birdSongs.js new file mode 100644 index 0000000000..94e013d92b --- /dev/null +++ b/examples/birdSongs.js @@ -0,0 +1,164 @@ +// +// birdSongs.js +// examples +// +// Copyright 2014 High Fidelity, Inc. +// Plays a sample audio file at the avatar's current location +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +// First, load a sample sound from a URL +var birds = []; +var playing = []; + +var lowerCorner = { x: 0, y: 8, z: 0 }; +var upperCorner = { x: 10, y: 10, z: 10 }; + +var RATE = 0.035; +var numPlaying = 0; +var BIRD_SIZE = 0.1; +var BIRD_VELOCITY = 2.0; +var LIGHT_RADIUS = 10.0; +var BIRD_MASTER_VOLUME = 0.5; + +var useLights = true; + +function randomVector(scale) { + return { x: Math.random() * scale - scale / 2.0, y: Math.random() * scale - scale / 2.0, z: Math.random() * scale - scale / 2.0 }; +} + +function maybePlaySound(deltaTime) { + if (Math.random() < RATE) { + // Set the location and other info for the sound to play + var whichBird = Math.floor(Math.random() * birds.length); + //print("playing sound # " + whichBird); + var options = new AudioInjectionOptions(); + var position = { x: lowerCorner.x + Math.random() * (upperCorner.x - lowerCorner.x), + y: lowerCorner.y + Math.random() * (upperCorner.y - lowerCorner.y), + z: lowerCorner.z + Math.random() * (upperCorner.z - lowerCorner.z) }; + options.position = position; + options.volume = BIRD_MASTER_VOLUME; + // + var entityId = Entities.addEntity({ + type: "Sphere", + position: position, + dimensions: { x: BIRD_SIZE, y: BIRD_SIZE, z: BIRD_SIZE }, + color: birds[whichBird].color, + lifetime: 10 + }); + + if (useLights) { + var lightId = Entities.addEntity({ + type: "Light", + position: position, + dimensions: { x: LIGHT_RADIUS, y: LIGHT_RADIUS, z: LIGHT_RADIUS }, + + isSpotlight: false, + diffuseColor: birds[whichBird].color, + ambientColor: { red: 0, green: 0, blue: 0 }, + specularColor: { red: 255, green: 255, blue: 255 }, + + constantAttenuation: 0, + linearAttenuation: 4.0, + quadraticAttenuation: 2.0, + lifetime: 10 + }); + } + + playing.push({ audioId: Audio.playSound(birds[whichBird].sound, options), entityId: entityId, lightId: lightId, color: birds[whichBird].color }); + } + if (playing.length != numPlaying) { + numPlaying = playing.length; + //print("number playing = " + numPlaying); + } + for (var i = 0; i < playing.length; i++) { + if (!Audio.isInjectorPlaying(playing[i].audioId)) { + Entities.deleteEntity(playing[i].entityId); + if (useLights) { + Entities.deleteEntity(playing[i].lightId); + } + playing.splice(i, 1); + } else { + var loudness = Audio.getLoudness(playing[i].audioId); + var newColor = { red: playing[i].color.red, green: playing[i].color.green, blue: playing[i].color.blue }; + if (loudness > 0.05) { + newColor.red *= (1.0 - loudness); + newColor.green *= (1.0 - loudness); + newColor.blue *= (1.0 - loudness); + } + var properties = Entities.getEntityProperties(playing[i].entityId); + var newPosition = Vec3.sum(properties.position, randomVector(BIRD_VELOCITY * deltaTime)); + if (properties) { + properties.position = newPosition; + Entities.editEntity(playing[i].entityId, { position: properties.position, color: newColor }); + } + if (useLights) { + var lightProperties = Entities.getEntityProperties(playing[i].lightId); + if (lightProperties) { + Entities.editEntity(playing[i].lightId, { position: newPosition, diffuseColor: newColor }); + } + } + } + } +} + +loadBirds(); +// Connect a call back that happens every frame +Script.update.connect(maybePlaySound); + +// Delete our little friends if script is stopped +Script.scriptEnding.connect(function() { + for (var i = 0; i < playing.length; i++) { + Entities.deleteEntity(playing[i].entityId); + if (useLights) { + Entities.deleteEntity(playing[i].lightId); + } + } +}); + +function loadBirds() { + var sound_filenames = ["bushtit_1.raw", "bushtit_2.raw", "bushtit_3.raw", "mexicanWhipoorwill.raw", + "rosyfacedlovebird.raw", "saysphoebe.raw", "westernscreechowl.raw", "bandtailedpigeon.wav", "bridledtitmouse.wav", + "browncrestedflycatcher.wav", "commonnighthawk.wav", "commonpoorwill.wav", "doublecrestedcormorant.wav", + "gambelsquail.wav", "goldcrownedkinglet.wav", "greaterroadrunner.wav","groovebilledani.wav","hairywoodpecker.wav", + "housewren.wav","hummingbird.wav", "mountainchickadee.wav", "nightjar.wav", "piebilledgrieb.wav", "pygmynuthatch.wav", + "whistlingduck.wav", "woodpecker.wav"]; + + var colors = [ + { red: 242, green: 207, blue: 013 }, + { red: 238, green: 94, blue: 11 }, + { red: 81, green: 30, blue: 7 }, + { red: 195, green: 176, blue: 81 }, + { red: 235, green: 190, blue: 152 }, + { red: 167, green: 99, blue: 52 }, + { red: 199, green: 122, blue: 108 }, + { red: 246, green: 220, blue: 189 }, + { red: 208, green: 145, blue: 65 }, + { red: 173, green: 120 , blue: 71 }, + { red: 132, green: 147, blue: 174 }, + { red: 164, green: 74, blue: 40 }, + { red: 131, green: 127, blue: 134 }, + { red: 209, green: 157, blue: 117 }, + { red: 205, green: 191, blue: 193 }, + { red: 193, green: 154, blue: 118 }, + { red: 205, green: 190, blue: 169 }, + { red: 199, green: 111, blue: 69 }, + { red: 221, green: 223, blue: 228 }, + { red: 115, green: 92, blue: 87 }, + { red: 214, green: 165, blue: 137 }, + { red: 160, green: 124, blue: 33 }, + { red: 117, green: 91, blue: 86 }, + { red: 113, green: 104, blue: 107 }, + { red: 216, green: 153, blue: 99 }, + { red: 242, green: 226, blue: 64 } + ]; + + var SOUND_BASE_URL = "http://public.highfidelity.io/sounds/Animals/"; + + for (var i = 0; i < sound_filenames.length; i++) { + birds.push({ sound: new Sound(SOUND_BASE_URL + sound_filenames[i]), + color: colors[i] + } ); + } +} \ No newline at end of file From 5a51a99f762980209f85995def83dc097d37435d Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 6 Nov 2014 10:40:06 -0800 Subject: [PATCH 34/39] Fixing missing brackets after if --- interface/src/gpu/Batch.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/interface/src/gpu/Batch.h b/interface/src/gpu/Batch.h index 4149d88233..6dc7fc13ec 100644 --- a/interface/src/gpu/Batch.h +++ b/interface/src/gpu/Batch.h @@ -252,8 +252,9 @@ public: } Pointer get(uint32 offset) { - if (offset >= _pointers.size()) + if (offset >= _pointers.size()) { return Pointer(); + } return (_pointers.data() + offset)->_pointer; } @@ -272,22 +273,25 @@ public: uint32 cacheResource(Resource* res); uint32 cacheResource(const void* pointer); ResourceCache* editResource(uint32 offset) { - if (offset >= _resources.size()) + if (offset >= _resources.size()) { return 0; + } return (_resources.data() + offset); } template T* editResourcePointer(uint32 offset) { - if (offset >= _resources.size()) + if (offset >= _resources.size()) { return 0; + } return reinterpret_cast((_resources.data() + offset)->_pointer); } uint32 cacheData(uint32 size, const void* data); Byte* editData(uint32 offset) { - if (offset >= _data.size()) + if (offset >= _data.size()) { return 0; + } return (_data.data() + offset); } From 2d06e71e32d07359017f2da8da500f34b1f51f86 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 6 Nov 2014 10:42:14 -0800 Subject: [PATCH 35/39] Remove double definition of static const arrays for Types and Dimensions --- interface/src/gpu/Batch.cpp | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/interface/src/gpu/Batch.cpp b/interface/src/gpu/Batch.cpp index e213007191..e02a0a551e 100644 --- a/interface/src/gpu/Batch.cpp +++ b/interface/src/gpu/Batch.cpp @@ -16,34 +16,6 @@ using namespace gpu; -const int TYPE_SIZE[NUM_TYPES] = { - 4, - 4, - 4, - 2, - 2, - 2, - 1, - 1, - 4, - 4, - 4, - 2, - 2, - 2, - 1, - 1 -}; - -const int DIMENSION_COUNT[NUM_DIMENSIONS] = { - 1, - 2, - 3, - 4, - 9, - 16 -}; - Batch::Batch() : _commands(), _commandOffsets(), From 820c0798aad5f1fb17064a71f298b2e3372b6dda Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 6 Nov 2014 10:43:54 -0800 Subject: [PATCH 36/39] In BufferStream, clean up the constructor and destructor --- interface/src/gpu/Stream.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/interface/src/gpu/Stream.cpp b/interface/src/gpu/Stream.cpp index 68b1392f73..099cbde24a 100644 --- a/interface/src/gpu/Stream.cpp +++ b/interface/src/gpu/Stream.cpp @@ -34,13 +34,11 @@ bool Stream::Format::setAttribute(Slot slot, Slot channel, Element element, Offs BufferStream::BufferStream() : _buffers(), - _offsets() + _offsets(), + _strides() {} -BufferStream::~BufferStream() -{ - _buffers.clear(); - _offsets.clear(); +BufferStream::~BufferStream() { } void BufferStream::addBuffer(BufferPointer& buffer, Offset offset, Offset stride) { From 2c0b8c9172a616dbf9b9e12c48a0c96e9d559738 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 6 Nov 2014 12:45:02 -0800 Subject: [PATCH 37/39] Winding order fixes. --- interface/src/renderer/GeometryCache.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 5aa4012cc3..88d1894fa8 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -173,12 +173,12 @@ void GeometryCache::renderSphere(float radius, int slices, int stacks) { for (int j = 0; j < slices; j++) { int next = (j + 1) % slices; - *(index++) = bottom + j; *(index++) = top + next; + *(index++) = bottom + j; *(index++) = top + j; - *(index++) = bottom + j; *(index++) = bottom + next; + *(index++) = bottom + j; *(index++) = top + next; } } @@ -187,8 +187,8 @@ void GeometryCache::renderSphere(float radius, int slices, int stacks) { bottom = (stacks - 2) * slices + 1; top = bottom + slices; for (int i = 0; i < slices; i++) { - *(index++) = bottom + i; *(index++) = bottom + (i + 1) % slices; + *(index++) = bottom + i; *(index++) = top; } @@ -408,8 +408,8 @@ void GeometryCache::renderCone(float base, float height, int slices, int stacks) GLushort* index = indexData; for (int i = 0; i < baseTriangles; i++) { *(index++) = 0; - *(index++) = i + 1; *(index++) = i + 2; + *(index++) = i + 1; } for (int i = 1; i <= stacks; i++) { GLushort bottom = i * slices; From 788f1b91c0edfe73687fc74ffbc29bf31ae6b163 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 6 Nov 2014 12:54:49 -0800 Subject: [PATCH 38/39] Use near radius as threshold, since we need to switch to full screen rendering whenever any point of the near window intersects the light volume. --- interface/src/renderer/DeferredLightingEffect.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index fa07bf419d..f8baf15b7e 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -230,9 +230,10 @@ void DeferredLightingEffect::render() { glTexGenfv(GL_T, GL_OBJECT_PLANE, (const GLfloat*)&tCoefficients); // enlarge the scales slightly to account for tesselation - const float SCALE_EXPANSION = 0.1f; + const float SCALE_EXPANSION = 0.05f; const glm::vec3& eyePoint = Application::getInstance()->getDisplayViewFrustum()->getPosition(); + float nearRadius = glm::distance(eyePoint, Application::getInstance()->getDisplayViewFrustum()->getNearTopLeft()); if (!_pointLights.isEmpty()) { _pointLight.bind(); @@ -254,7 +255,7 @@ void DeferredLightingEffect::render() { glPushMatrix(); float expandedRadius = light.radius * (1.0f + SCALE_EXPANSION); - if (glm::distance(eyePoint, glm::vec3(light.position)) < expandedRadius) { + if (glm::distance(eyePoint, glm::vec3(light.position)) < expandedRadius + nearRadius) { glLoadIdentity(); glTranslatef(0.0f, 0.0f, -1.0f); @@ -303,7 +304,7 @@ void DeferredLightingEffect::render() { float expandedRadius = light.radius * (1.0f + SCALE_EXPANSION); float edgeRadius = expandedRadius / glm::cos(light.cutoff); - if (glm::distance(eyePoint, glm::vec3(light.position)) < edgeRadius) { + if (glm::distance(eyePoint, glm::vec3(light.position)) < edgeRadius + nearRadius) { glLoadIdentity(); glTranslatef(0.0f, 0.0f, -1.0f); From bed524716db0831e54d0ab4032c03df06466ae80 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 6 Nov 2014 14:01:43 -0800 Subject: [PATCH 39/39] Removed all the prefix to the enum values, since all the enums are in the gpu scope we consider its good to avoid name colisions --- interface/src/gpu/Batch.h | 12 ++-- interface/src/gpu/Format.h | 72 ++++++++++++------------ interface/src/gpu/GLBackend.cpp | 10 ++-- interface/src/gpu/Stream.h | 26 ++++----- interface/src/renderer/GeometryCache.cpp | 28 ++++----- interface/src/renderer/Model.cpp | 18 +++--- interface/src/ui/TextRenderer.cpp | 8 +-- 7 files changed, 87 insertions(+), 87 deletions(-) diff --git a/interface/src/gpu/Batch.h b/interface/src/gpu/Batch.h index 6dc7fc13ec..f9db3b9a40 100644 --- a/interface/src/gpu/Batch.h +++ b/interface/src/gpu/Batch.h @@ -40,12 +40,12 @@ namespace gpu { enum Primitive { - PRIMITIVE_POINTS = 0, - PRIMITIVE_LINES, - PRIMITIVE_LINE_STRIP, - PRIMITIVE_TRIANGLES, - PRIMITIVE_TRIANGLE_STRIP, - PRIMITIVE_QUADS, + POINTS = 0, + LINES, + LINE_STRIP, + TRIANGLES, + TRIANGLE_STRIP, + QUADS, NUM_PRIMITIVES, }; diff --git a/interface/src/gpu/Format.h b/interface/src/gpu/Format.h index a372d4086e..8faa995924 100644 --- a/interface/src/gpu/Format.h +++ b/interface/src/gpu/Format.h @@ -29,23 +29,23 @@ typedef uint32 Offset; // Description of a scalar type enum Type { - TYPE_FLOAT = 0, - TYPE_INT32, - TYPE_UINT32, - TYPE_HALF, - TYPE_INT16, - TYPE_UINT16, - TYPE_INT8, - TYPE_UINT8, + FLOAT = 0, + INT32, + UINT32, + HALF, + INT16, + UINT16, + INT8, + UINT8, - TYPE_NFLOAT, - TYPE_NINT32, - TYPE_NUINT32, - TYPE_NHALF, - TYPE_NINT16, - TYPE_NUINT16, - TYPE_NINT8, - TYPE_NUINT8, + NFLOAT, + NINT32, + NUINT32, + NHALF, + NINT16, + NUINT16, + NINT8, + NUINT8, NUM_TYPES, }; @@ -72,12 +72,12 @@ static const int TYPE_SIZE[NUM_TYPES] = { // Dimension of an Element enum Dimension { - DIM_SCALAR = 0, - DIM_VEC2, - DIM_VEC3, - DIM_VEC4, - DIM_MAT3, - DIM_MAT4, + SCALAR = 0, + VEC2, + VEC3, + VEC4, + MAT3, + MAT4, NUM_DIMENSIONS, }; @@ -94,16 +94,16 @@ static const int DIMENSION_COUNT[NUM_DIMENSIONS] = { // Semantic of an Element // Provide information on how to use the element enum Semantic { - SEMANTIC_RGB = 0, - SEMANTIC_RGBA, - SEMANTIC_XYZ, - SEMANTIC_XYZW, - SEMANTIC_POS_XYZ, - SEMANTIC_POS_XYZW, - SEMANTIC_QUAT, - SEMANTIC_DIR_XYZ, - SEMANTIC_UV, - SEMANTIC_R8, + RGB = 0, + RGBA, + XYZ, + XYZW, + POS_XYZ, + POS_XYZW, + QUAT, + DIR_XYZ, + UV, + R8, NUM_SEMANTICS, }; @@ -119,9 +119,9 @@ public: _type(type) {} Element() : - _semantic(SEMANTIC_R8), - _dimension(DIM_SCALAR), - _type(TYPE_INT8) + _semantic(R8), + _dimension(SCALAR), + _type(INT8) {} Semantic getSemantic() const { return (Semantic)_semantic; } @@ -130,7 +130,7 @@ public: uint8 getDimensionCount() const { return DIMENSION_COUNT[(Dimension)_dimension]; } Type getType() const { return (Type)_type; } - bool isNormalized() const { return (getType() >= TYPE_NFLOAT); } + bool isNormalized() const { return (getType() >= NFLOAT); } uint32 getSize() const { return DIMENSION_COUNT[_dimension] * TYPE_SIZE[_type]; } diff --git a/interface/src/gpu/GLBackend.cpp b/interface/src/gpu/GLBackend.cpp index 5a159d920d..5e13d03ff4 100644 --- a/interface/src/gpu/GLBackend.cpp +++ b/interface/src/gpu/GLBackend.cpp @@ -240,7 +240,7 @@ void GLBackend::do_setInputBuffer(Batch& batch, uint32 paramOffset) { #define SUPPORT_LEGACY_OPENGL #if defined(SUPPORT_LEGACY_OPENGL) -static const int NUM_CLASSIC_ATTRIBS = Stream::INPUT_SLOT_TANGENT; +static const int NUM_CLASSIC_ATTRIBS = Stream::TANGENT; static const GLenum attributeSlotToClassicAttribName[NUM_CLASSIC_ATTRIBS] = { GL_VERTEX_ARRAY, GL_NORMAL_ARRAY, @@ -324,16 +324,16 @@ void GLBackend::updateInput() { #if defined(SUPPORT_LEGACY_OPENGL) if (slot < NUM_CLASSIC_ATTRIBS) { switch (slot) { - case Stream::INPUT_SLOT_POSITION: + case Stream::POSITION: glVertexPointer(count, type, stride, (GLvoid*)pointer); break; - case Stream::INPUT_SLOT_NORMAL: + case Stream::NORMAL: glNormalPointer(type, stride, (GLvoid*)pointer); break; - case Stream::INPUT_SLOT_COLOR: + case Stream::COLOR: glColorPointer(count, type, stride, (GLvoid*)pointer); break; - case Stream::INPUT_SLOT_TEXCOORD: + case Stream::TEXCOORD: glTexCoordPointer(count, type, stride, (GLvoid*)pointer); break; }; diff --git a/interface/src/gpu/Stream.h b/interface/src/gpu/Stream.h index 21d4ea422c..84b2edc5f3 100644 --- a/interface/src/gpu/Stream.h +++ b/interface/src/gpu/Stream.h @@ -27,13 +27,13 @@ public: // Possible input slots identifiers enum InputSlot { - INPUT_SLOT_POSITION = 0, - INPUT_SLOT_NORMAL, - INPUT_SLOT_COLOR, - INPUT_SLOT_TEXCOORD, - INPUT_SLOT_TANGENT, - INPUT_SLOT_SKIN_CLUSTER_INDEX, - INPUT_SLOT_SKIN_CLUSTER_WEIGHT, + POSITION = 0, + NORMAL, + COLOR, + TEXCOORD, + TANGENT, + SKIN_CLUSTER_INDEX, + SKIN_CLUSTER_WEIGHT, NUM_INPUT_SLOTS, }; @@ -42,15 +42,15 @@ public: // Frequency describer enum Frequency { - FREQUENCY_PER_VERTEX = 0, - FREQUENCY_PER_INSTANCE, + PER_VERTEX = 0, + PER_INSTANCE, }; // The attribute description // Every thing that is needed to detail a stream attribute and how to interpret it class Attribute { public: - Attribute(Slot slot, Slot channel, Element element, Offset offset = 0, Frequency frequency = FREQUENCY_PER_VERTEX) : + Attribute(Slot slot, Slot channel, Element element, Offset offset = 0, Frequency frequency = PER_VERTEX) : _slot(slot), _channel(channel), _element(element), @@ -58,11 +58,11 @@ public: _frequency(frequency) {} Attribute() : - _slot(INPUT_SLOT_POSITION), + _slot(POSITION), _channel(0), _element(), _offset(0), - _frequency(FREQUENCY_PER_VERTEX) + _frequency(PER_VERTEX) {} @@ -106,7 +106,7 @@ public: uint32 getElementTotalSize() const { return _elementTotalSize; } - bool setAttribute(Slot slot, Slot channel, Element element, Offset offset = 0, Frequency frequency = FREQUENCY_PER_VERTEX); + bool setAttribute(Slot slot, Slot channel, Element element, Offset offset = 0, Frequency frequency = PER_VERTEX); protected: AttributeMap _attributes; diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 59180dcf9d..c8b821b87b 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -923,13 +923,13 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { int channelNum = 0; networkMesh._vertexFormat = gpu::Stream::FormatPointer(new gpu::Stream::Format()); - networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_POSITION, channelNum++, gpu::Element(gpu::DIM_VEC3, gpu::TYPE_FLOAT, gpu::SEMANTIC_POS_XYZ), 0); - if (mesh.normals.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_NORMAL, channelNum++, gpu::Element(gpu::DIM_VEC3, gpu::TYPE_FLOAT, gpu::SEMANTIC_XYZ), 0); - if (mesh.tangents.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_TANGENT, channelNum++, gpu::Element(gpu::DIM_VEC3, gpu::TYPE_FLOAT, gpu::SEMANTIC_XYZ), 0); - if (mesh.colors.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_COLOR, channelNum++, gpu::Element(gpu::DIM_VEC3, gpu::TYPE_FLOAT, gpu::SEMANTIC_RGB), 0); - if (mesh.texCoords.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_TEXCOORD, channelNum++, gpu::Element(gpu::DIM_VEC2, gpu::TYPE_FLOAT, gpu::SEMANTIC_UV), 0); - if (mesh.clusterIndices.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::DIM_VEC4, gpu::TYPE_NFLOAT, gpu::SEMANTIC_XYZW), 0); - if (mesh.clusterWeights.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::DIM_VEC4, gpu::TYPE_NFLOAT, gpu::SEMANTIC_XYZW), 0); + networkMesh._vertexFormat->setAttribute(gpu::Stream::POSITION, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::POS_XYZ), 0); + if (mesh.normals.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::NORMAL, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); + if (mesh.tangents.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TANGENT, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); + if (mesh.colors.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::COLOR, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RGB)); + if (mesh.texCoords.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TEXCOORD, channelNum++, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV)); + if (mesh.clusterIndices.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::VEC4, gpu::NFLOAT, gpu::XYZW)); + if (mesh.clusterWeights.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::VEC4, gpu::NFLOAT, gpu::XYZW)); } else { int colorsOffset = mesh.tangents.size() * sizeof(glm::vec3); @@ -956,13 +956,13 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { int channelNum = 0; networkMesh._vertexFormat = gpu::Stream::FormatPointer(new gpu::Stream::Format()); - networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_POSITION, channelNum++, gpu::Element(gpu::DIM_VEC3, gpu::TYPE_FLOAT, gpu::SEMANTIC_POS_XYZ), 0); - if (mesh.normals.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_NORMAL, channelNum++, gpu::Element(gpu::DIM_VEC3, gpu::TYPE_FLOAT, gpu::SEMANTIC_XYZ), 0); - if (mesh.tangents.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_TANGENT, channelNum++, gpu::Element(gpu::DIM_VEC3, gpu::TYPE_FLOAT, gpu::SEMANTIC_XYZ), 0); - if (mesh.colors.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_COLOR, channelNum++, gpu::Element(gpu::DIM_VEC3, gpu::TYPE_FLOAT, gpu::SEMANTIC_RGB), 0); - if (mesh.texCoords.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_TEXCOORD, channelNum++, gpu::Element(gpu::DIM_VEC2, gpu::TYPE_FLOAT, gpu::SEMANTIC_UV), 0); - if (mesh.clusterIndices.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::DIM_VEC4, gpu::TYPE_NFLOAT, gpu::SEMANTIC_XYZW), 0); - if (mesh.clusterWeights.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::INPUT_SLOT_SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::DIM_VEC4, gpu::TYPE_NFLOAT, gpu::SEMANTIC_XYZW), 0); + networkMesh._vertexFormat->setAttribute(gpu::Stream::POSITION, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::POS_XYZ)); + if (mesh.normals.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::NORMAL, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); + if (mesh.tangents.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TANGENT, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); + if (mesh.colors.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::COLOR, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RGB)); + if (mesh.texCoords.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TEXCOORD, channelNum++, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV)); + if (mesh.clusterIndices.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::VEC4, gpu::NFLOAT, gpu::XYZW)); + if (mesh.clusterWeights.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::VEC4, gpu::NFLOAT, gpu::XYZW)); } } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index a3fd3374a0..38562df696 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -137,7 +137,7 @@ void Model::initProgram(ProgramObject& program, Model::Locations& locations, int - glBindAttribLocation(program.programId(), gpu::Stream::INPUT_SLOT_TANGENT, "tangent"); + glBindAttribLocation(program.programId(), gpu::Stream::TANGENT, "tangent"); glLinkProgram(program.programId()); @@ -177,9 +177,9 @@ void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locati // HACK: Assign explicitely the attribute channel to avoid a bug on Yosemite - glBindAttribLocation(program.programId(), gpu::Stream::INPUT_SLOT_SKIN_CLUSTER_INDEX, "clusterIndices"); + glBindAttribLocation(program.programId(), gpu::Stream::SKIN_CLUSTER_INDEX, "clusterIndices"); - glBindAttribLocation(program.programId(), gpu::Stream::INPUT_SLOT_SKIN_CLUSTER_WEIGHT, "clusterWeights"); + glBindAttribLocation(program.programId(), gpu::Stream::SKIN_CLUSTER_WEIGHT, "clusterWeights"); glLinkProgram(program.programId()); @@ -671,9 +671,9 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) { GLBATCH(glDisableClientState)(GL_VERTEX_ARRAY); GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY); GLBATCH(glDisableClientState)(GL_COLOR_ARRAY); - GLBATCH(glDisableVertexAttribArray)(gpu::Stream::INPUT_SLOT_TANGENT); - GLBATCH(glDisableVertexAttribArray)(gpu::Stream::INPUT_SLOT_SKIN_CLUSTER_INDEX); - GLBATCH(glDisableVertexAttribArray)(gpu::Stream::INPUT_SLOT_SKIN_CLUSTER_WEIGHT); + GLBATCH(glDisableVertexAttribArray)(gpu::Stream::TANGENT); + GLBATCH(glDisableVertexAttribArray)(gpu::Stream::SKIN_CLUSTER_INDEX); + GLBATCH(glDisableVertexAttribArray)(gpu::Stream::SKIN_CLUSTER_WEIGHT); // bind with 0 to switch back to normal operation GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, 0); @@ -1817,7 +1817,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl const NetworkMesh& networkMesh = networkMeshes.at(i); const FBXMesh& mesh = geometry.meshes.at(i); - batch.setIndexBuffer(gpu::TYPE_UINT32, (networkMesh._indexBuffer), 0); + batch.setIndexBuffer(gpu::UINT32, (networkMesh._indexBuffer), 0); int vertexCount = mesh.vertices.size(); if (vertexCount == 0) { // sanity check @@ -1946,12 +1946,12 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl meshPartsRendered++; if (part.quadIndices.size() > 0) { - batch.drawIndexed(gpu::PRIMITIVE_QUADS, part.quadIndices.size(), offset); + batch.drawIndexed(gpu::QUADS, part.quadIndices.size(), offset); offset += part.quadIndices.size() * sizeof(int); } if (part.triangleIndices.size() > 0) { - batch.drawIndexed(gpu::PRIMITIVE_TRIANGLES, part.triangleIndices.size(), offset); + batch.drawIndexed(gpu::TRIANGLES, part.triangleIndices.size(), offset); offset += part.triangleIndices.size() * sizeof(int); } diff --git a/interface/src/ui/TextRenderer.cpp b/interface/src/ui/TextRenderer.cpp index 1e4565d83a..69df609ba9 100644 --- a/interface/src/ui/TextRenderer.cpp +++ b/interface/src/ui/TextRenderer.cpp @@ -185,12 +185,12 @@ TextRenderer::TextRenderer(const Properties& properties) : _glyphsStreamFormat(new gpu::Stream::Format()), _glyphsStream(new gpu::BufferStream()) { - _glyphsStreamFormat->setAttribute(gpu::Stream::INPUT_SLOT_POSITION, 0, gpu::Element(gpu::DIM_VEC2, gpu::TYPE_FLOAT, gpu::SEMANTIC_POS_XYZ), 0); + _glyphsStreamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::POS_XYZ), 0); const int NUM_POS_COORDS = 2; const int VERTEX_TEXCOORD_OFFSET = NUM_POS_COORDS * sizeof(float); - _glyphsStreamFormat->setAttribute(gpu::Stream::INPUT_SLOT_TEXCOORD, 0, gpu::Element(gpu::DIM_VEC2, gpu::TYPE_FLOAT, gpu::SEMANTIC_UV), VERTEX_TEXCOORD_OFFSET); + _glyphsStreamFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), VERTEX_TEXCOORD_OFFSET); - _glyphsStreamFormat->setAttribute(gpu::Stream::INPUT_SLOT_COLOR, 1, gpu::Element(gpu::DIM_VEC4, gpu::TYPE_UINT8, gpu::SEMANTIC_RGBA)); + _glyphsStreamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA)); _glyphsStream->addBuffer(_glyphsBuffer, 0, _glyphsStreamFormat->getChannels().at(0)._stride); _glyphsStream->addBuffer(_glyphsColorBuffer, 0, _glyphsStreamFormat->getChannels().at(1)._stride); @@ -317,7 +317,7 @@ void TextRenderer::drawBatch() { batch.setInputFormat(_glyphsStreamFormat); batch.setInputStream(0, *_glyphsStream); - batch.draw(gpu::PRIMITIVE_QUADS, _numGlyphsBatched * 4, 0); + batch.draw(gpu::QUADS, _numGlyphsBatched * 4, 0); gpu::GLBackend::renderBatch(batch);