From 6cf833cf987e6c424ddd21bdc2f15529dac61997 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 11 Nov 2014 17:31:49 -0800 Subject: [PATCH 01/15] Add text overlay textWidth() method --- interface/src/ui/overlays/Overlays.cpp | 16 ++++++++++++++++ interface/src/ui/overlays/Overlays.h | 4 ++++ interface/src/ui/overlays/Text3DOverlay.cpp | 12 +++++++++--- interface/src/ui/overlays/Text3DOverlay.h | 2 ++ interface/src/ui/overlays/TextOverlay.cpp | 10 +++++++--- interface/src/ui/overlays/TextOverlay.h | 3 +++ 6 files changed, 41 insertions(+), 6 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index df7a5fbcea..b65fe6d286 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -9,6 +9,7 @@ // #include +#include #include #include @@ -357,3 +358,18 @@ bool Overlays::isLoaded(unsigned int id) { return overlay->isLoaded(); } +float Overlays::textWidth(unsigned int id, const QString& text) { + if (_overlays2D.contains(id)) { + Overlay* thisOverlay = _overlays2D[id]; + if (typeid(*thisOverlay) == typeid(TextOverlay)) { + return static_cast(thisOverlay)->textWidth(text); + } + } + if (_overlays3D.contains(id)) { + Overlay* thisOverlay = _overlays3D[id]; + if (typeid(*thisOverlay) == typeid(Text3DOverlay)) { + return static_cast(thisOverlay)->textWidth(text); + } + } + return 0.f; +} diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 686b998267..dcda9a8ed7 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -65,6 +65,10 @@ public slots: /// returns whether the overlay's assets are loaded or not bool isLoaded(unsigned int id); + /// returns the width of the given text in the specified overlay if it is a text overlay: in pixels if it is a 2D text + /// overlay; in meters if it is a 3D text overlay + float textWidth(unsigned int id, const QString& text); + private: QMap _overlays2D; QMap _overlays3D; diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index d8febbf0eb..5928e328ba 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -17,6 +17,8 @@ const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 }; const float DEFAULT_MARGIN = 0.1f; +const int FIXED_FONT_POINT_SIZE = 40; +const float LINE_SCALE_RATIO = 1.2f; Text3DOverlay::Text3DOverlay() : _backgroundColor(DEFAULT_BACKGROUND_COLOR), @@ -87,11 +89,10 @@ void Text3DOverlay::render(RenderArgs* args) { glVertex3f(-halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND); glEnd(); - const int FIXED_FONT_POINT_SIZE = 40; const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 40.0f; // this is a ratio determined through experimentation + // Same font properties as textWidth() TextRenderer* textRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); - float LINE_SCALE_RATIO = 1.2f; float maxHeight = (float)textRenderer->calculateHeight("Xy") * LINE_SCALE_RATIO; float scaleFactor = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight; @@ -179,4 +180,9 @@ void Text3DOverlay::setProperties(const QScriptValue& properties) { } - +float Text3DOverlay::textWidth(const QString& text) { + QFont font(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); // Same font properties as render() + QFontMetrics fontMetrics(font); + float scaleFactor = _lineHeight * LINE_SCALE_RATIO / (float)FIXED_FONT_POINT_SIZE; + return scaleFactor * (float)fontMetrics.width(qPrintable(text)); +} diff --git a/interface/src/ui/overlays/Text3DOverlay.h b/interface/src/ui/overlays/Text3DOverlay.h index 45e311c554..f0369b4206 100644 --- a/interface/src/ui/overlays/Text3DOverlay.h +++ b/interface/src/ui/overlays/Text3DOverlay.h @@ -48,6 +48,8 @@ public: virtual void setProperties(const QScriptValue& properties); + float textWidth(const QString& text); // Meters + private: void enableClipPlane(GLenum plane, float x, float y, float z, float w); diff --git a/interface/src/ui/overlays/TextOverlay.cpp b/interface/src/ui/overlays/TextOverlay.cpp index 530b30a856..9f194b75dd 100644 --- a/interface/src/ui/overlays/TextOverlay.cpp +++ b/interface/src/ui/overlays/TextOverlay.cpp @@ -66,9 +66,8 @@ void TextOverlay::render(RenderArgs* args) { glVertex2f(_bounds.left(), _bounds.bottom()); glEnd(); - //TextRenderer(const char* family, int pointSize = -1, int weight = -1, bool italic = false, - // EffectType effect = NO_EFFECT, int effectThickness = 1); - TextRenderer* textRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, _fontSize, 50); + // Same font properties as textWidth() + TextRenderer* textRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, _fontSize, DEFAULT_FONT_WEIGHT); const int leftAdjust = -1; // required to make text render relative to left edge of bounds const int topAdjust = -2; // required to make text render relative to top edge of bounds @@ -126,3 +125,8 @@ void TextOverlay::setProperties(const QScriptValue& properties) { } +float TextOverlay::textWidth(const QString& text) { + QFont font(SANS_FONT_FAMILY, _fontSize, DEFAULT_FONT_WEIGHT); // Same font properties as render() + QFontMetrics fontMetrics(font); + return fontMetrics.width(qPrintable(text)); +} diff --git a/interface/src/ui/overlays/TextOverlay.h b/interface/src/ui/overlays/TextOverlay.h index f7ff83e542..2922d747ca 100644 --- a/interface/src/ui/overlays/TextOverlay.h +++ b/interface/src/ui/overlays/TextOverlay.h @@ -30,6 +30,7 @@ const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 }; const int DEFAULT_MARGIN = 10; const int DEFAULT_FONTSIZE = 11; +const int DEFAULT_FONT_WEIGHT = 50; class TextOverlay : public Overlay2D { Q_OBJECT @@ -53,6 +54,8 @@ public: virtual void setProperties(const QScriptValue& properties); + float textWidth(const QString& text); // Pixels + private: QString _text; From f0f12b047951eaf9bfdbdb6c622dfa98b78a38ca Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 11 Nov 2014 17:32:37 -0800 Subject: [PATCH 02/15] Auto-size load URL and file menu items in editModels and newEditEntities And fix a couple of typos --- examples/editModels.js | 15 +++++++++------ examples/newEditEntities.js | 15 +++++++++------ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/examples/editModels.js b/examples/editModels.js index d26a6e14b0..7538a83fef 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -1125,12 +1125,12 @@ var toolBar = (function () { browseModelsButton, loadURLMenuItem, loadFileMenuItem, - menuItemWidth = 125, + menuItemWidth, menuItemOffset, menuItemHeight, menuItemMargin = 5, menuTextColor = { red: 255, green: 255, blue: 255 }, - menuBackgoundColor = { red: 18, green: 66, blue: 66 }; + menuBackgroundColor = { red: 18, green: 66, blue: 66 }; function initialize() { toolBar = new ToolBar(0, 0, ToolBar.VERTICAL); @@ -1167,9 +1167,8 @@ var toolBar = (function () { loadURLMenuItem = Overlays.addOverlay("text", { x: newModelButton.x - menuItemWidth, y: newModelButton.y + menuItemOffset, - width: menuItemWidth, height: menuItemHeight, - backgroundColor: menuBackgoundColor, + backgroundColor: menuBackgroundColor, topMargin: menuItemMargin, text: "Model URL", alpha: 0.9, @@ -1179,15 +1178,19 @@ var toolBar = (function () { loadFileMenuItem = Overlays.addOverlay("text", { x: newModelButton.x - menuItemWidth, y: newModelButton.y + menuItemOffset + menuItemHeight, - width: menuItemWidth, height: menuItemHeight, - backgroundColor: menuBackgoundColor, + backgroundColor: menuBackgroundColor, topMargin: menuItemMargin, text: "Model File", alpha: 0.9, visible: false }); + menuItemWidth = Math.max(Overlays.textWidth(loadURLMenuItem, "Model URL"), + Overlays.textWidth(loadFileMenuItem, "Model File")) + 20; + Overlays.editOverlay(loadURLMenuItem, { width: menuItemWidth }); + Overlays.editOverlay(loadFileMenuItem, { width: menuItemWidth }); + newCubeButton = toolBar.addTool({ imageURL: toolIconUrl + "add-cube.svg", subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index 57f3f29670..20359d9718 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -83,12 +83,12 @@ var toolBar = (function () { browseModelsButton, loadURLMenuItem, loadFileMenuItem, - menuItemWidth = 125, + menuItemWidth, menuItemOffset, menuItemHeight, menuItemMargin = 5, menuTextColor = { red: 255, green: 255, blue: 255 }, - menuBackgoundColor = { red: 18, green: 66, blue: 66 }; + menuBackgroundColor = { red: 18, green: 66, blue: 66 }; function initialize() { toolBar = new ToolBar(0, 0, ToolBar.VERTICAL); @@ -125,9 +125,8 @@ var toolBar = (function () { loadURLMenuItem = Overlays.addOverlay("text", { x: newModelButton.x - menuItemWidth, y: newModelButton.y + menuItemOffset, - width: menuItemWidth, height: menuItemHeight, - backgroundColor: menuBackgoundColor, + backgroundColor: menuBackgroundColor, topMargin: menuItemMargin, text: "Model URL", alpha: 0.9, @@ -137,15 +136,19 @@ var toolBar = (function () { loadFileMenuItem = Overlays.addOverlay("text", { x: newModelButton.x - menuItemWidth, y: newModelButton.y + menuItemOffset + menuItemHeight, - width: menuItemWidth, height: menuItemHeight, - backgroundColor: menuBackgoundColor, + backgroundColor: menuBackgroundColor, topMargin: menuItemMargin, text: "Model File", alpha: 0.9, visible: false }); + menuItemWidth = Math.max(Overlays.textWidth(loadURLMenuItem, "Model URL"), + Overlays.textWidth(loadFileMenuItem, "Model File")) + 20; + Overlays.editOverlay(loadURLMenuItem, { width: menuItemWidth }); + Overlays.editOverlay(loadFileMenuItem, { width: menuItemWidth }); + newCubeButton = toolBar.addTool({ imageURL: toolIconUrl + "add-cube.svg", subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, From 7e2c4c05615d9300f26a1182e50f444ece003892 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 13 Nov 2014 10:57:32 -0800 Subject: [PATCH 03/15] SImplified the Transform usage in the gpu::api, no more pointers, just values. Improved the Transform by compressing the memory footprint --- interface/src/Application.cpp | 10 ++--- interface/src/Application.h | 6 +-- interface/src/gpu/Batch.cpp | 6 +-- interface/src/gpu/Batch.h | 40 ++++++++---------- interface/src/gpu/GLBackend.cpp | 36 ++++++---------- interface/src/gpu/GLBackend.h | 12 +++--- interface/src/renderer/Model.cpp | 17 ++++---- interface/src/renderer/Model.h | 2 +- libraries/shared/src/Transform.h | 70 ++++++++++++++++++++------------ 9 files changed, 101 insertions(+), 98 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c3ab4fe115..f11ac14d40 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -160,7 +160,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _lastQueriedViewFrustum(), _lastQueriedTime(usecTimestampNow()), _mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)), - _viewTransform(new gpu::Transform()), + _viewTransform(), _scaleMirror(1.0f), _rotateMirror(0.0f), _raiseMirror(0.0f), @@ -2911,13 +2911,13 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { // Equivalent to what is happening with _untranslatedViewMatrix and the _viewMatrixTranslation // the viewTransofmr object is updatded with the correct values and saved, // this is what is used for rendering the Entities and avatars - gpu::Transform viewTransform; + Transform viewTransform; viewTransform.setTranslation(whichCamera.getPosition()); viewTransform.setRotation(rotation); viewTransform.postTranslate(eyeOffsetPos); viewTransform.postRotate(eyeOffsetOrient); if (whichCamera.getMode() == CAMERA_MODE_MIRROR) { - viewTransform.setScale(gpu::Transform::Vec3(-1.0f, 1.0f, 1.0f)); + viewTransform.setScale(Transform::Vec3(-1.0f, 1.0f, 1.0f)); } setViewTransform(viewTransform); @@ -3117,8 +3117,8 @@ void Application::updateUntranslatedViewMatrix(const glm::vec3& viewMatrixTransl _viewMatrixTranslation = viewMatrixTranslation; } -void Application::setViewTransform(const gpu::Transform& view) { - (*_viewTransform) = view; +void Application::setViewTransform(const Transform& view) { + _viewTransform = view; } void Application::loadTranslatedViewMatrix(const glm::vec3& translation) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 9ce857ee8a..cba39317a5 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -232,8 +232,8 @@ public: const glm::vec3& getViewMatrixTranslation() const { return _viewMatrixTranslation; } void setViewMatrixTranslation(const glm::vec3& translation) { _viewMatrixTranslation = translation; } - const gpu::TransformPointer& getViewTransform() const { return _viewTransform; } - void setViewTransform(const gpu::Transform& view); + const Transform& getViewTransform() const { return _viewTransform; } + void setViewTransform(const Transform& view); /// if you need to access the application settings, use lockSettings()/unlockSettings() QSettings* lockSettings() { _settingsMutex.lock(); return _settings; } @@ -526,7 +526,7 @@ private: QRect _mirrorViewRect; RearMirrorTools* _rearMirrorTools; - gpu::TransformPointer _viewTransform; + Transform _viewTransform; glm::mat4 _untranslatedViewMatrix; glm::vec3 _viewMatrixTranslation; glm::mat4 _projectionMatrix; diff --git a/interface/src/gpu/Batch.cpp b/interface/src/gpu/Batch.cpp index 2bf92f43cf..30e591cc60 100644 --- a/interface/src/gpu/Batch.cpp +++ b/interface/src/gpu/Batch.cpp @@ -135,19 +135,19 @@ void Batch::setIndexBuffer(Type type, const BufferPointer& buffer, Offset offset _params.push_back(type); } -void Batch::setModelTransform(const TransformPointer& model) { +void Batch::setModelTransform(const Transform& model) { ADD_COMMAND(setModelTransform); _params.push_back(_transforms.cache(model)); } -void Batch::setViewTransform(const TransformPointer& view) { +void Batch::setViewTransform(const Transform& view) { ADD_COMMAND(setViewTransform); _params.push_back(_transforms.cache(view)); } -void Batch::setProjectionTransform(const TransformPointer& proj) { +void Batch::setProjectionTransform(const Transform& proj) { ADD_COMMAND(setProjectionTransform); _params.push_back(_transforms.cache(proj)); diff --git a/interface/src/gpu/Batch.h b/interface/src/gpu/Batch.h index 3c15fef63b..d006473b50 100644 --- a/interface/src/gpu/Batch.h +++ b/interface/src/gpu/Batch.h @@ -50,10 +50,6 @@ enum Primitive { NUM_PRIMITIVES, }; -typedef ::Transform Transform; -typedef QSharedPointer< ::gpu::Transform > TransformPointer; -typedef std::vector< TransformPointer > Transforms; - class Batch { public: typedef Stream::Slot Slot; @@ -87,9 +83,9 @@ public: // finaly projected into the clip space by the projection transform // WARNING: ViewTransform transform from eye space to world space, its inverse is composed // with the ModelTransformu to create the equivalent of the glModelViewMatrix - void setModelTransform(const TransformPointer& model); - void setViewTransform(const TransformPointer& view); - void setProjectionTransform(const TransformPointer& proj); + void setModelTransform(const Transform& model); + void setViewTransform(const Transform& view); + void setProjectionTransform(const Transform& proj); // TODO: As long as we have gl calls explicitely issued from interface @@ -258,35 +254,35 @@ public: template class Cache { public: - typedef QSharedPointer Pointer; - Pointer _pointer; - Cache(const Pointer& pointer) : _pointer(pointer) {} + typedef T Data; + Data _data; + Cache(const Data& data) : _data(data) {} class Vector { public: - std::vector< Cache > _pointers; + std::vector< Cache > _items; - uint32 cache(const Pointer& pointer) { - uint32 offset = _pointers.size(); - _pointers.push_back(Cache(pointer)); + uint32 cache(const Data& data) { + uint32 offset = _items.size(); + _items.push_back(Cache(data)); return offset; } - Pointer get(uint32 offset) { - if (offset >= _pointers.size()) { - return Pointer(); + Data get(uint32 offset) { + if (offset >= _items.size()) { + return Data(); } - return (_pointers.data() + offset)->_pointer; + return (_items.data() + offset)->_data; } void clear() { - _pointers.clear(); + _items.clear(); } }; }; - - typedef Cache::Vector BufferCaches; - typedef Cache::Vector StreamFormatCaches; + + typedef Cache::Vector BufferCaches; + typedef Cache::Vector StreamFormatCaches; typedef Cache::Vector TransformCaches; typedef unsigned char Byte; diff --git a/interface/src/gpu/GLBackend.cpp b/interface/src/gpu/GLBackend.cpp index 8921dc6d1c..539ac69b8d 100644 --- a/interface/src/gpu/GLBackend.cpp +++ b/interface/src/gpu/GLBackend.cpp @@ -430,30 +430,18 @@ void GLBackend::do_setIndexBuffer(Batch& batch, uint32 paramOffset) { // Transform Stage void GLBackend::do_setModelTransform(Batch& batch, uint32 paramOffset) { - TransformPointer modelTransform = batch._transforms.get(batch._params[paramOffset]._uint); - - if (_transform._model.isNull() || (modelTransform != _transform._model)) { - _transform._model = modelTransform; - _transform._invalidModel = true; - } + _transform._model = batch._transforms.get(batch._params[paramOffset]._uint); + _transform._invalidModel = true; } void GLBackend::do_setViewTransform(Batch& batch, uint32 paramOffset) { - TransformPointer viewTransform = batch._transforms.get(batch._params[paramOffset]._uint); - - if (_transform._view.isNull() || (viewTransform != _transform._view)) { - _transform._view = viewTransform; - _transform._invalidView = true; - } + _transform._view = batch._transforms.get(batch._params[paramOffset]._uint); + _transform._invalidView = true; } void GLBackend::do_setProjectionTransform(Batch& batch, uint32 paramOffset) { - TransformPointer projectionTransform = batch._transforms.get(batch._params[paramOffset]._uint); - - if (_transform._projection.isNull() || (projectionTransform != _transform._projection)) { - _transform._projection = projectionTransform; - _transform._invalidProj = true; - } + _transform._projection = batch._transforms.get(batch._params[paramOffset]._uint); + _transform._invalidProj = true; } void GLBackend::updateTransform() { @@ -468,28 +456,28 @@ void GLBackend::updateTransform() { } if (_transform._invalidModel || _transform._invalidView) { - if (!_transform._model.isNull()) { + if (!_transform._model.isIdentity()) { if (_transform._lastMode != GL_MODELVIEW) { glMatrixMode(GL_MODELVIEW); _transform._lastMode = GL_MODELVIEW; } Transform::Mat4 modelView; - if (!_transform._view.isNull()) { + if (!_transform._view.isIdentity()) { Transform mvx; - Transform::inverseMult(mvx, (*_transform._view), (*_transform._model)); + Transform::inverseMult(mvx, _transform._view, _transform._model); mvx.getMatrix(modelView); } else { - _transform._model->getMatrix(modelView); + _transform._model.getMatrix(modelView); } glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView)); } else { - if (!_transform._view.isNull()) { + if (!_transform._view.isIdentity()) { if (_transform._lastMode != GL_MODELVIEW) { glMatrixMode(GL_MODELVIEW); _transform._lastMode = GL_MODELVIEW; } Transform::Mat4 modelView; - _transform._view->getInverseMatrix(modelView); + _transform._view.getInverseMatrix(modelView); glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView)); } else { // TODO: eventually do something about the matrix when neither view nor model is specified? diff --git a/interface/src/gpu/GLBackend.h b/interface/src/gpu/GLBackend.h index 0f58ec192d..8524722e75 100644 --- a/interface/src/gpu/GLBackend.h +++ b/interface/src/gpu/GLBackend.h @@ -86,9 +86,9 @@ protected: void updateTransform(); struct TransformStageState { - TransformPointer _model; - TransformPointer _view; - TransformPointer _projection; + Transform _model; + Transform _view; + Transform _projection; bool _invalidModel; bool _invalidView; bool _invalidProj; @@ -96,9 +96,9 @@ protected: GLenum _lastMode; TransformStageState() : - _model(0), - _view(0), - _projection(0), + _model(), + _view(), + _projection(), _invalidModel(true), _invalidView(true), _invalidProj(true), diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 8b3c656ae7..8cbcbaa959 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -567,11 +567,11 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { // Capture the view matrix once for the rendering of this model if (_transforms.empty()) { - _transforms.push_back(gpu::TransformPointer(new gpu::Transform())); + _transforms.push_back(Transform()); } - (*_transforms[0]) = gpu::Transform((*Application::getInstance()->getViewTransform())); + _transforms[0] = Application::getInstance()->getViewTransform(); // apply entity translation offset to the viewTransform in one go (it's a preTranslate because viewTransform goes from world to eye space) - _transforms[0]->preTranslate(-_translation); + _transforms[0].preTranslate(-_translation); batch.setViewTransform(_transforms[0]); @@ -1493,10 +1493,10 @@ void Model::setupBatchTransform(gpu::Batch& batch) { // Capture the view matrix once for the rendering of this model if (_transforms.empty()) { - _transforms.push_back(gpu::TransformPointer(new gpu::Transform())); + _transforms.push_back(Transform()); } - (*_transforms[0]) = gpu::Transform((*Application::getInstance()->getViewTransform())); - _transforms[0]->preTranslate(-_translation); + _transforms[0] = Application::getInstance()->getViewTransform(); + _transforms[0].preTranslate(-_translation); batch.setViewTransform(_transforms[0]); } @@ -2149,10 +2149,9 @@ 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()); - batch.setModelTransform(gpu::TransformPointer()); + batch.setModelTransform(Transform()); } else { - gpu::TransformPointer modelTransform(new gpu::Transform(state.clusterMatrices[0])); - batch.setModelTransform(modelTransform); + batch.setModelTransform(Transform(state.clusterMatrices[0])); } if (mesh.blendshapes.isEmpty()) { diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 8c74b1a222..e6454a964a 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -283,7 +283,7 @@ private: QUrl _url; gpu::Buffers _blendedVertexBuffers; - gpu::Transforms _transforms; + std::vector _transforms; gpu::Batch _renderBatch; QVector > > _dilatedTextures; diff --git a/libraries/shared/src/Transform.h b/libraries/shared/src/Transform.h index 6ad106063f..3c668adcd6 100644 --- a/libraries/shared/src/Transform.h +++ b/libraries/shared/src/Transform.h @@ -20,6 +20,8 @@ #include +#include + class Transform { public: typedef glm::mat4 Mat4; @@ -30,16 +32,16 @@ public: typedef glm::quat Quat; Transform() : - _translation(0), _rotation(1.0f, 0, 0, 0), _scale(1.0f), + _translation(0), _flags(FLAG_CACHE_INVALID_BITSET) // invalid cache { } Transform(const Transform& transform) : - _translation(transform._translation), _rotation(transform._rotation), _scale(transform._scale), + _translation(transform._translation), _flags(transform._flags) { invalidCache(); @@ -49,6 +51,15 @@ public: } ~Transform() {} + Transform& operator=(const Transform& transform) { + _rotation = transform._rotation; + _scale = transform._scale; + _translation = transform._translation; + _flags = transform._flags; + invalidCache(); + return (*this); + } + void setIdentity(); const Vec3& getTranslation() const; @@ -89,7 +100,6 @@ public: // Left will be inversed before the multiplication static Transform& inverseMult(Transform& result, const Transform& left, const Transform& right); - protected: enum Flag { @@ -111,14 +121,15 @@ protected: // TRS - Vec3 _translation; Quat _rotation; Vec3 _scale; + Vec3 _translation; mutable Flags _flags; // Cached transform - mutable Mat4 _matrix; + // TODO: replace this auto ptr by a "unique ptr" as soon as we are compiling in C++11 + mutable std::auto_ptr _matrix; bool isCacheInvalid() const { return _flags[FLAG_CACHE_INVALID]; } void validCache() const { _flags.set(FLAG_CACHE_INVALID, false); } @@ -135,6 +146,7 @@ protected: void flagNonUniform() { _flags.set(FLAG_NON_UNIFORM, true); } void updateCache() const; + Mat4& getCachedMatrix(Mat4& result) const; }; inline void Transform::setIdentity() { @@ -271,8 +283,25 @@ inline void Transform::postScale(const Vec3& scale) { } inline Transform::Mat4& Transform::getMatrix(Transform::Mat4& result) const { - updateCache(); - result = _matrix; + if (isRotating()) { + Mat3 rot = glm::mat3_cast(_rotation); + + if (isScaling()) { + rot[0] *= _scale.x; + rot[1] *= _scale.y; + rot[2] *= _scale.z; + } + + result[0] = Vec4(rot[0], 0.f); + result[1] = Vec4(rot[1], 0.f); + result[2] = Vec4(rot[2], 0.f); + } else { + result[0] = Vec4(_scale.x, 0.f, 0.f, 0.f); + result[1] = Vec4(0.f, _scale.y, 0.f, 0.f); + result[2] = Vec4(0.f, 0.f, _scale.z, 0.f); + } + + result[3] = Vec4(_translation, 1.0f); return result; } @@ -369,27 +398,18 @@ inline Transform& Transform::inverseMult( Transform& result, const Transform& le return result; } +inline Transform::Mat4& Transform::getCachedMatrix(Transform::Mat4& result) const { + updateCache(); + result = (*_matrix); + return result; +} + inline void Transform::updateCache() const { if (isCacheInvalid()) { - if (isRotating()) { - Mat3 rot = glm::mat3_cast(_rotation); - - if (isScaling()) { - rot[0] *= _scale.x; - rot[1] *= _scale.y; - rot[2] *= _scale.z; - } - - _matrix[0] = Vec4(rot[0], 0.f); - _matrix[1] = Vec4(rot[1], 0.f); - _matrix[2] = Vec4(rot[2], 0.f); - } else { - _matrix[0] = Vec4(_scale.x, 0.f, 0.f, 0.f); - _matrix[1] = Vec4(0.f, _scale.y, 0.f, 0.f); - _matrix[2] = Vec4(0.f, 0.f, _scale.z, 0.f); + if (!_matrix.get()) { + _matrix.reset(new Mat4()); } - - _matrix[3] = Vec4(_translation, 1.0f); + getMatrix((*_matrix)); validCache(); } } From 8d4cecda6241dd8bdfec6ef29418aa32a50227bb Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 13 Nov 2014 11:06:40 -0800 Subject: [PATCH 04/15] Optimization and coding standard --- interface/src/ui/overlays/Overlays.cpp | 19 ++++++++++--------- interface/src/ui/overlays/Overlays.h | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index b65fe6d286..d208658e8b 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -358,18 +358,19 @@ bool Overlays::isLoaded(unsigned int id) { return overlay->isLoaded(); } -float Overlays::textWidth(unsigned int id, const QString& text) { - if (_overlays2D.contains(id)) { - Overlay* thisOverlay = _overlays2D[id]; +const float Overlays::textWidth(unsigned int id, const QString& text) { + Overlay* thisOverlay = _overlays2D[id]; + if (thisOverlay) { if (typeid(*thisOverlay) == typeid(TextOverlay)) { return static_cast(thisOverlay)->textWidth(text); } - } - if (_overlays3D.contains(id)) { - Overlay* thisOverlay = _overlays3D[id]; - if (typeid(*thisOverlay) == typeid(Text3DOverlay)) { - return static_cast(thisOverlay)->textWidth(text); + } else { + thisOverlay = _overlays3D[id]; + if (thisOverlay) { + if (typeid(*thisOverlay) == typeid(Text3DOverlay)) { + return static_cast(thisOverlay)->textWidth(text); + } } } - return 0.f; + return 0.0f; } diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index dcda9a8ed7..4e11526f23 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -67,7 +67,7 @@ public slots: /// returns the width of the given text in the specified overlay if it is a text overlay: in pixels if it is a 2D text /// overlay; in meters if it is a 3D text overlay - float textWidth(unsigned int id, const QString& text); + const float textWidth(unsigned int id, const QString& text); private: QMap _overlays2D; From 493455fdacb8edbeb23d6d2d251150a300a93f79 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 13 Nov 2014 11:34:40 -0800 Subject: [PATCH 05/15] Fix const --- interface/src/ui/overlays/Overlays.cpp | 2 +- interface/src/ui/overlays/Overlays.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index d208658e8b..029b0d90a1 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -358,7 +358,7 @@ bool Overlays::isLoaded(unsigned int id) { return overlay->isLoaded(); } -const float Overlays::textWidth(unsigned int id, const QString& text) { +float Overlays::textWidth(unsigned int id, const QString& text) const { Overlay* thisOverlay = _overlays2D[id]; if (thisOverlay) { if (typeid(*thisOverlay) == typeid(TextOverlay)) { diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 4e11526f23..66232196f2 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -67,7 +67,7 @@ public slots: /// returns the width of the given text in the specified overlay if it is a text overlay: in pixels if it is a 2D text /// overlay; in meters if it is a 3D text overlay - const float textWidth(unsigned int id, const QString& text); + float textWidth(unsigned int id, const QString& text) const; private: QMap _overlays2D; From 6f4952c7d52fe733cc0a7b36c06b0c57f2ebd38d Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 13 Nov 2014 12:25:15 -0800 Subject: [PATCH 06/15] More consts --- interface/src/ui/overlays/Text3DOverlay.cpp | 2 +- interface/src/ui/overlays/Text3DOverlay.h | 2 +- interface/src/ui/overlays/TextOverlay.cpp | 2 +- interface/src/ui/overlays/TextOverlay.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index 5928e328ba..3a3a23e828 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -180,7 +180,7 @@ void Text3DOverlay::setProperties(const QScriptValue& properties) { } -float Text3DOverlay::textWidth(const QString& text) { +float Text3DOverlay::textWidth(const QString& text) const { QFont font(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); // Same font properties as render() QFontMetrics fontMetrics(font); float scaleFactor = _lineHeight * LINE_SCALE_RATIO / (float)FIXED_FONT_POINT_SIZE; diff --git a/interface/src/ui/overlays/Text3DOverlay.h b/interface/src/ui/overlays/Text3DOverlay.h index f0369b4206..e9969b1cad 100644 --- a/interface/src/ui/overlays/Text3DOverlay.h +++ b/interface/src/ui/overlays/Text3DOverlay.h @@ -48,7 +48,7 @@ public: virtual void setProperties(const QScriptValue& properties); - float textWidth(const QString& text); // Meters + float textWidth(const QString& text) const; // Meters private: void enableClipPlane(GLenum plane, float x, float y, float z, float w); diff --git a/interface/src/ui/overlays/TextOverlay.cpp b/interface/src/ui/overlays/TextOverlay.cpp index 9f194b75dd..356ba419b0 100644 --- a/interface/src/ui/overlays/TextOverlay.cpp +++ b/interface/src/ui/overlays/TextOverlay.cpp @@ -125,7 +125,7 @@ void TextOverlay::setProperties(const QScriptValue& properties) { } -float TextOverlay::textWidth(const QString& text) { +float TextOverlay::textWidth(const QString& text) const { QFont font(SANS_FONT_FAMILY, _fontSize, DEFAULT_FONT_WEIGHT); // Same font properties as render() QFontMetrics fontMetrics(font); return fontMetrics.width(qPrintable(text)); diff --git a/interface/src/ui/overlays/TextOverlay.h b/interface/src/ui/overlays/TextOverlay.h index 2922d747ca..9fc6480eb7 100644 --- a/interface/src/ui/overlays/TextOverlay.h +++ b/interface/src/ui/overlays/TextOverlay.h @@ -54,7 +54,7 @@ public: virtual void setProperties(const QScriptValue& properties); - float textWidth(const QString& text); // Pixels + float textWidth(const QString& text) const; // Pixels private: From 5c9c78e62b2bbbe1b6fdfd128faafac3447efc32 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 13 Nov 2014 12:32:48 -0800 Subject: [PATCH 07/15] Moving all the variables for the Input stage cache into a struct just like for transformStage --- interface/src/gpu/GLBackend.cpp | 68 +++++++++++++++------------------ interface/src/gpu/GLBackend.h | 43 ++++++++++++++------- 2 files changed, 60 insertions(+), 51 deletions(-) diff --git a/interface/src/gpu/GLBackend.cpp b/interface/src/gpu/GLBackend.cpp index 539ac69b8d..d6e1a011a3 100644 --- a/interface/src/gpu/GLBackend.cpp +++ b/interface/src/gpu/GLBackend.cpp @@ -113,15 +113,7 @@ static const GLenum _elementTypeToGLType[NUM_TYPES]= { GLBackend::GLBackend() : - _needInputFormatUpdate(true), - _inputFormat(0), - _inputBuffersState(0), - _inputBuffers(_inputBuffersState.size(), BufferPointer(0)), - _inputBufferOffsets(_inputBuffersState.size(), 0), - _inputBufferStrides(_inputBuffersState.size(), 0), - _indexBuffer(0), - _indexBufferOffset(0), - _inputAttributeActivation(0), + _input(), _transform() { @@ -203,9 +195,9 @@ void GLBackend::do_drawIndexed(Batch& batch, uint32 paramOffset) { uint32 numIndices = batch._params[paramOffset + 1]._uint; uint32 startIndex = batch._params[paramOffset + 0]._uint; - GLenum glType = _elementTypeToGLType[_indexBufferType]; + GLenum glType = _elementTypeToGLType[_input._indexBufferType]; - glDrawElements(mode, numIndices, glType, reinterpret_cast(startIndex + _indexBufferOffset)); + glDrawElements(mode, numIndices, glType, reinterpret_cast(startIndex + _input._indexBufferOffset)); CHECK_GL_ERROR(); } @@ -220,9 +212,9 @@ void GLBackend::do_drawIndexedInstanced(Batch& batch, uint32 paramOffset) { void GLBackend::do_setInputFormat(Batch& batch, uint32 paramOffset) { Stream::FormatPointer format = batch._streamFormats.get(batch._params[paramOffset]._uint); - if (format != _inputFormat) { - _inputFormat = format; - _needInputFormatUpdate = true; + if (format != _input._format) { + _input._format = format; + _input._invalidFormat = true; } } @@ -233,10 +225,10 @@ void GLBackend::do_setInputBuffer(Batch& batch, uint32 paramOffset) { uint32 channel = batch._params[paramOffset + 3]._uint; if (channel < getNumInputBuffers()) { - _inputBuffers[channel] = buffer; - _inputBufferOffsets[channel] = offset; - _inputBufferStrides[channel] = stride; - _inputBuffersState.set(channel); + _input._buffers[channel] = buffer; + _input._bufferOffsets[channel] = offset; + _input._bufferStrides[channel] = stride; + _input._buffersState.set(channel); } } @@ -252,14 +244,14 @@ static const GLenum attributeSlotToClassicAttribName[NUM_CLASSIC_ATTRIBS] = { #endif void GLBackend::updateInput() { - if (_needInputFormatUpdate || _inputBuffersState.any()) { + if (_input._invalidFormat || _input._buffersState.any()) { - if (_needInputFormatUpdate) { - InputActivationCache newActivation; + if (_input._invalidFormat) { + InputStageState::ActivationCache newActivation; // Check expected activation - if (_inputFormat) { - const Stream::Format::AttributeMap& attributes = _inputFormat->getAttributes(); + if (_input._format) { + const Stream::Format::AttributeMap& attributes = _input._format->getAttributes(); for (Stream::Format::AttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); it++) { const Stream::Attribute& attrib = (*it).second; newActivation.set(attrib._slot); @@ -269,7 +261,7 @@ void GLBackend::updateInput() { // Manage Activation what was and what is expected now for (unsigned int i = 0; i < newActivation.size(); i++) { bool newState = newActivation[i]; - if (newState != _inputAttributeActivation[i]) { + if (newState != _input._attributeActivation[i]) { #if defined(SUPPORT_LEGACY_OPENGL) if (i < NUM_CLASSIC_ATTRIBS) { if (newState) { @@ -290,31 +282,31 @@ void GLBackend::updateInput() { } CHECK_GL_ERROR(); - _inputAttributeActivation.flip(i); + _input._attributeActivation.flip(i); } } } // now we need to bind the buffers and assign the attrib pointers - if (_inputFormat) { - const Buffers& buffers = _inputBuffers; - const Offsets& offsets = _inputBufferOffsets; - const Offsets& strides = _inputBufferStrides; + if (_input._format) { + const Buffers& buffers = _input._buffers; + const Offsets& offsets = _input._bufferOffsets; + const Offsets& strides = _input._bufferStrides; - const Stream::Format::AttributeMap& attributes = _inputFormat->getAttributes(); + const Stream::Format::AttributeMap& attributes = _input._format->getAttributes(); - for (Stream::Format::ChannelMap::const_iterator channelIt = _inputFormat->getChannels().begin(); - channelIt != _inputFormat->getChannels().end(); + for (Stream::Format::ChannelMap::const_iterator channelIt = _input._format->getChannels().begin(); + channelIt != _input._format->getChannels().end(); channelIt++) { const Stream::Format::ChannelMap::value_type::second_type& channel = (*channelIt).second; if ((*channelIt).first < buffers.size()) { int bufferNum = (*channelIt).first; - if (_inputBuffersState.test(bufferNum) || _needInputFormatUpdate) { + if (_input._buffersState.test(bufferNum) || _input._invalidFormat) { GLuint vbo = gpu::GLBackend::getBufferID((*buffers[bufferNum])); glBindBuffer(GL_ARRAY_BUFFER, vbo); CHECK_GL_ERROR(); - _inputBuffersState[bufferNum] = false; + _input._buffersState[bufferNum] = false; for (unsigned int i = 0; i < channel._slots.size(); i++) { const Stream::Attribute& attrib = attributes.at(channel._slots[i]); @@ -354,7 +346,7 @@ void GLBackend::updateInput() { } } // everything format related should be in sync now - _needInputFormatUpdate = false; + _input._invalidFormat = false; } /* TODO: Fancy version GL4.4 @@ -415,10 +407,10 @@ void GLBackend::updateInput() { void GLBackend::do_setIndexBuffer(Batch& batch, uint32 paramOffset) { - _indexBufferType = (Type) batch._params[paramOffset + 2]._uint; + _input._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; + _input._indexBufferOffset = batch._params[paramOffset + 0]._uint; + _input._indexBuffer = indexBuffer; if (indexBuffer) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, getBufferID(*indexBuffer)); } else { diff --git a/interface/src/gpu/GLBackend.h b/interface/src/gpu/GLBackend.h index 8524722e75..71869229fd 100644 --- a/interface/src/gpu/GLBackend.h +++ b/interface/src/gpu/GLBackend.h @@ -48,7 +48,7 @@ public: static const int MAX_NUM_ATTRIBUTES = Stream::NUM_INPUT_SLOTS; static const int MAX_NUM_INPUT_BUFFERS = 16; - uint32 getNumInputBuffers() const { return _inputBuffersState.size(); } + uint32 getNumInputBuffers() const { return _input._buffersState.size(); } protected: @@ -62,22 +62,39 @@ protected: void do_setInputFormat(Batch& batch, uint32 paramOffset); void do_setInputBuffer(Batch& batch, uint32 paramOffset); void do_setIndexBuffer(Batch& batch, uint32 paramOffset); + void updateInput(); - bool _needInputFormatUpdate; - Stream::FormatPointer _inputFormat; - typedef std::bitset InputBuffersState; - InputBuffersState _inputBuffersState; + struct InputStageState { + bool _invalidFormat; + Stream::FormatPointer _format; - Buffers _inputBuffers; - Offsets _inputBufferOffsets; - Offsets _inputBufferStrides; + typedef std::bitset BuffersState; + BuffersState _buffersState; - BufferPointer _indexBuffer; - Offset _indexBufferOffset; - Type _indexBufferType; + Buffers _buffers; + Offsets _bufferOffsets; + Offsets _bufferStrides; - typedef std::bitset InputActivationCache; - InputActivationCache _inputAttributeActivation; + BufferPointer _indexBuffer; + Offset _indexBufferOffset; + Type _indexBufferType; + + typedef std::bitset ActivationCache; + ActivationCache _attributeActivation; + + InputStageState() : + _invalidFormat(true), + _format(0), + _buffersState(0), + _buffers(_buffersState.size(), BufferPointer(0)), + _bufferOffsets(_buffersState.size(), 0), + _bufferStrides(_buffersState.size(), 0), + _indexBuffer(0), + _indexBufferOffset(0), + _indexBufferType(UINT32), + _attributeActivation(0) + {} + } _input; // Transform Stage void do_setModelTransform(Batch& batch, uint32 paramOffset); From 7ba3c74bc0c6840af70ce72e467c8afbd5bef1e0 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 13 Nov 2014 14:47:02 -0800 Subject: [PATCH 08/15] more work on render model scenes --- interface/src/renderer/Model.cpp | 260 ++++++++++++++----------------- interface/src/renderer/Model.h | 12 ++ 2 files changed, 125 insertions(+), 147 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 8b3c656ae7..d10ce80126 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1553,46 +1553,18 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { int opaqueMeshPartsRendered = 0; // now, for each model in the scene, render the mesh portions - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - opaqueMeshPartsRendered += model->renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args); - GLBATCH(glPopMatrix)(); - } - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - opaqueMeshPartsRendered += model->renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args); - GLBATCH(glPopMatrix)(); - } - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - opaqueMeshPartsRendered += model->renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args); - GLBATCH(glPopMatrix)(); - } - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - opaqueMeshPartsRendered += model->renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args); - GLBATCH(glPopMatrix)(); - } - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - opaqueMeshPartsRendered += model->renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args); - GLBATCH(glPopMatrix)(); - } - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - opaqueMeshPartsRendered += model->renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); - GLBATCH(glPopMatrix)(); - } - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - opaqueMeshPartsRendered += model->renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args); - GLBATCH(glPopMatrix)(); - } - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - opaqueMeshPartsRendered += model->renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); - GLBATCH(glPopMatrix)(); - } + //bool pickProgramsNeeded = true; + //SkinLocations* skinLocations; + //GLenum specularTextureUnit; + + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, args); // render translucent meshes afterwards //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); @@ -1606,46 +1578,14 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { int translucentParts = 0; const float MOSTLY_OPAQUE_THRESHOLD = 0.75f; - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args); - GLBATCH(glPopMatrix)(); - } - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args); - GLBATCH(glPopMatrix)(); - } - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args); - GLBATCH(glPopMatrix)(); - } - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args); - GLBATCH(glPopMatrix)(); - } - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args); - GLBATCH(glPopMatrix)(); - } - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); - GLBATCH(glPopMatrix)(); - } - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args); - GLBATCH(glPopMatrix)(); - } - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); - GLBATCH(glPopMatrix)(); - } + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, true, args); GLBATCH(glDisable)(GL_ALPHA_TEST); GLBATCH(glEnable)(GL_BLEND); @@ -1662,46 +1602,14 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args); - GLBATCH(glPopMatrix)(); - } - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args); - GLBATCH(glPopMatrix)(); - } - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args); - GLBATCH(glPopMatrix)(); - } - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args); - GLBATCH(glPopMatrix)(); - } - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args); - GLBATCH(glPopMatrix)(); - } - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); - GLBATCH(glPopMatrix)(); - } - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args); - GLBATCH(glPopMatrix)(); - } - foreach(Model* model, _modelsInScene) { - model->setupBatchTransform(batch); - translucentParts += model->renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); - GLBATCH(glPopMatrix)(); - } + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, true, args); } GLBATCH(glDepthMask)(true); @@ -1981,19 +1889,8 @@ void Model::segregateMeshGroups() { _meshGroupsKnown = true; } -int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { - +QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned) { PROFILE_RANGE(__FUNCTION__); - bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts); - bool cullTooSmallMeshParts = !Menu::getInstance()->isOptionChecked(MenuOption::DontCullTooSmallMeshParts); - bool dontReduceMaterialSwitches = Menu::getInstance()->isOptionChecked(MenuOption::DontReduceMaterialSwitches); - - QString lastMaterialID; - int meshPartsRendered = 0; - updateVisibleJointStates(); - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - const QVector& networkMeshes = _geometry->getMeshes(); // depending on which parameters we were called with, pick the correct mesh group to render QVector* whichList = NULL; @@ -2032,23 +1929,18 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl } else { qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???"; } - - if (!whichList) { - qDebug() << "unexpected!!! we don't know which list of meshes to render..."; - return 0; - } - QVector& list = *whichList; - - // If this list has nothing to render, then don't bother proceeding. This saves us on binding to programs - if (list.size() == 0) { - return 0; - } + return whichList; +} +void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, + bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, + SkinLocations*& skinLocations, GLenum& specularTextureUnit) { + ProgramObject* program = &_program; Locations* locations = &_locations; ProgramObject* skinProgram = &_skinProgram; - SkinLocations* skinLocations = &_skinLocations; - GLenum specularTextureUnit = 0; + skinLocations = &_skinLocations; + specularTextureUnit = 0; if (mode == SHADOW_RENDER_MODE) { program = &_shadowProgram; skinProgram = &_skinShadowProgram; @@ -2091,8 +1983,84 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl if (!activeProgram->isLinked()) { activeProgram->link(); } + GLBATCH(glUseProgram)(activeProgram->programId()); GLBATCH(glUniform1f)(activeLocations->alphaThreshold, alphaThreshold); +} + +int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, + bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { + + PROFILE_RANGE(__FUNCTION__); + int meshPartsRendered = 0; + + bool pickProgramsNeeded = true; + SkinLocations* skinLocations; + GLenum specularTextureUnit; + + foreach(Model* model, _modelsInScene) { + QVector* whichList = model->pickMeshList(translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned); + if (whichList) { + QVector& list = *whichList; + if (list.size() > 0) { + //if (pickProgramsNeeded) { + pickPrograms(batch, mode, translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit); + pickProgramsNeeded = false; + //} + model->setupBatchTransform(batch); + meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit); + GLBATCH(glPopMatrix)(); + } + } + } + // if we selected a program, then unselect it + if (!pickProgramsNeeded) { + //GLBATCH(glUseProgram)(0); + } + return meshPartsRendered; +} + +int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, + bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { + + PROFILE_RANGE(__FUNCTION__); + int meshPartsRendered = 0; + + QVector* whichList = pickMeshList(translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned); + + if (!whichList) { + qDebug() << "unexpected!!! we don't know which list of meshes to render..."; + return 0; + } + QVector& list = *whichList; + + // If this list has nothing to render, then don't bother proceeding. This saves us on binding to programs + if (list.size() == 0) { + return 0; + } + + SkinLocations* skinLocations; + GLenum specularTextureUnit; + pickPrograms(batch, mode, translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit); + meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit); + GLBATCH(glUseProgram)(0); + + return meshPartsRendered; +} + + +int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args, + SkinLocations* skinLocations, GLenum specularTextureUnit) { + PROFILE_RANGE(__FUNCTION__); + bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts); + bool cullTooSmallMeshParts = !Menu::getInstance()->isOptionChecked(MenuOption::DontCullTooSmallMeshParts); + bool dontReduceMaterialSwitches = Menu::getInstance()->isOptionChecked(MenuOption::DontReduceMaterialSwitches); + + QString lastMaterialID; + int meshPartsRendered = 0; + updateVisibleJointStates(); + const FBXGeometry& geometry = _geometry->getFBXGeometry(); + const QVector& networkMeshes = _geometry->getMeshes(); // i is the "index" from the original networkMeshes QVector... foreach (int i, list) { @@ -2268,7 +2236,5 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl } - GLBATCH(glUseProgram)(0); - return meshPartsRendered; } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 8c74b1a222..ab6b990eb2 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -409,6 +409,18 @@ private: int renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL); void setupBatchTransform(gpu::Batch& batch); + QVector* pickMeshList(bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned); + + int renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, + RenderArgs* args, SkinLocations* skinLocations, GLenum specularTextureUnit); + + static void pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, + bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, + SkinLocations*& skinLocations, GLenum& specularTextureUnit); + + static int renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, + bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args); + }; From 3ff89be3fdb6fe05fee801c29508ca55c1f6521a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 13 Nov 2014 14:51:47 -0800 Subject: [PATCH 09/15] actually only pick programs once --- interface/src/renderer/Model.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index d9e29dba7c..997322637c 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -2003,10 +2003,10 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool if (whichList) { QVector& list = *whichList; if (list.size() > 0) { - //if (pickProgramsNeeded) { + if (pickProgramsNeeded) { pickPrograms(batch, mode, translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit); pickProgramsNeeded = false; - //} + } model->setupBatchTransform(batch); meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit); GLBATCH(glPopMatrix)(); From 49ef6f8be087f85b146d219b3081a351d9168110 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 13 Nov 2014 14:53:37 -0800 Subject: [PATCH 10/15] some cleanup --- interface/src/renderer/Model.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 997322637c..c007f44f2e 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1553,10 +1553,6 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { int opaqueMeshPartsRendered = 0; // now, for each model in the scene, render the mesh portions - //bool pickProgramsNeeded = true; - //SkinLocations* skinLocations; - //GLenum specularTextureUnit; - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args); @@ -2015,7 +2011,7 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool } // if we selected a program, then unselect it if (!pickProgramsNeeded) { - //GLBATCH(glUseProgram)(0); + GLBATCH(glUseProgram)(0); } return meshPartsRendered; } From f47620231e1f7d30a784119eb64e63ef74050628 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 13 Nov 2014 16:16:20 -0800 Subject: [PATCH 11/15] Entities have user data --- libraries/entities/src/EntityItem.cpp | 7 +++++++ libraries/entities/src/EntityItem.h | 6 ++++++ libraries/entities/src/EntityItemProperties.cpp | 8 ++++++++ libraries/entities/src/EntityItemProperties.h | 10 +++++++++- libraries/networking/src/PacketHeaders.cpp | 2 +- libraries/networking/src/PacketHeaders.h | 1 + 6 files changed, 32 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index ef02aafbc8..8228ebc8ce 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -28,6 +28,7 @@ const float EntityItem::DEFAULT_GLOW_LEVEL = 0.0f; const float EntityItem::DEFAULT_LOCAL_RENDER_ALPHA = 1.0f; const float EntityItem::DEFAULT_MASS = 1.0f; const float EntityItem::DEFAULT_LIFETIME = EntityItem::IMMORTAL; +const QString EntityItem::DEFAULT_USER_DATA = QString(""); const float EntityItem::DEFAULT_DAMPING = 0.5f; const glm::vec3 EntityItem::NO_VELOCITY = glm::vec3(0, 0, 0); const float EntityItem::EPSILON_VELOCITY_LENGTH = (1.0f / 1000.0f) / (float)TREE_SCALE; // really small: 1mm/second @@ -71,6 +72,7 @@ void EntityItem::initFromEntityItemID(const EntityItemID& entityItemID) { _gravity = DEFAULT_GRAVITY; _damping = DEFAULT_DAMPING; _lifetime = DEFAULT_LIFETIME; + _userData = DEFAULT_USER_DATA; _registrationPoint = DEFAULT_REGISTRATION_POINT; _angularVelocity = DEFAULT_ANGULAR_VELOCITY; _angularDamping = DEFAULT_ANGULAR_DAMPING; @@ -115,6 +117,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_GRAVITY; requestedProperties += PROP_DAMPING; requestedProperties += PROP_LIFETIME; + requestedProperties += PROP_USER_DATA; requestedProperties += PROP_SCRIPT; requestedProperties += PROP_REGISTRATION_POINT; requestedProperties += PROP_ANGULAR_VELOCITY; @@ -231,6 +234,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_GRAVITY, appendValue, getGravity()); APPEND_ENTITY_PROPERTY(PROP_DAMPING, appendValue, getDamping()); APPEND_ENTITY_PROPERTY(PROP_LIFETIME, appendValue, getLifetime()); + APPEND_ENTITY_PROPERTY(PROP_USER_DATA, appendValue, getUserData()); APPEND_ENTITY_PROPERTY(PROP_SCRIPT, appendValue, getScript()); APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, appendValue, getRegistrationPoint()); APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, appendValue, getAngularVelocity()); @@ -502,6 +506,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, bool, _ignoreForCollisions); READ_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, bool, _collisionsWillMove); READ_ENTITY_PROPERTY(PROP_LOCKED, bool, _locked); + READ_ENTITY_PROPERTY(PROP_USER_DATA, QString, _userData); if (wantDebug) { qDebug() << " readEntityDataFromBuffer() _registrationPoint:" << _registrationPoint; @@ -758,6 +763,7 @@ EntityItemProperties EntityItem::getProperties() const { COPY_ENTITY_PROPERTY_TO_PROPERTIES(ignoreForCollisions, getIgnoreForCollisions); COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionsWillMove, getCollisionsWillMove); COPY_ENTITY_PROPERTY_TO_PROPERTIES(locked, getLocked); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(userData, getUserData); properties._defaultSettings = false; @@ -794,6 +800,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties, bool forc SET_ENTITY_PROPERTY_FROM_PROPERTIES(ignoreForCollisions, setIgnoreForCollisions); SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionsWillMove, setCollisionsWillMove); SET_ENTITY_PROPERTY_FROM_PROPERTIES(locked, setLocked); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(userData, setUserData); if (somethingChanged) { somethingChangedNotification(); // notify derived classes that something has changed diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index adf72198be..51accd2a4f 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -196,6 +196,11 @@ public: static const float DEFAULT_LIFETIME; float getLifetime() const { return _lifetime; } /// get the lifetime in seconds for the entity void setLifetime(float value) { _lifetime = value; } /// set the lifetime in seconds for the entity + + /// User-specified data stored in a variant map + static const QString DEFAULT_USER_DATA; + const QString& getUserData() const { return _userData; } + void setUserData(const QString& value) { _userData = value; } /// is this entity immortal, in that it has no lifetime set, and will exist until manually deleted bool isImmortal() const { return _lifetime == IMMORTAL; } @@ -284,6 +289,7 @@ protected: glm::vec3 _gravity; float _damping; float _lifetime; + QString _userData; QString _script; glm::vec3 _registrationPoint; glm::vec3 _angularVelocity; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 0c184d5e35..86bf81f6e2 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -37,6 +37,7 @@ EntityItemProperties::EntityItemProperties() : _gravity(EntityItem::DEFAULT_GRAVITY), _damping(EntityItem::DEFAULT_DAMPING), _lifetime(EntityItem::DEFAULT_LIFETIME), + _userData(EntityItem::DEFAULT_USER_DATA), _script(EntityItem::DEFAULT_SCRIPT), _registrationPoint(EntityItem::DEFAULT_REGISTRATION_POINT), _angularVelocity(EntityItem::DEFAULT_ANGULAR_VELOCITY), @@ -53,6 +54,7 @@ EntityItemProperties::EntityItemProperties() : _gravityChanged(false), _dampingChanged(false), _lifetimeChanged(false), + _userDataChanged(false), _scriptChanged(false), _registrationPointChanged(false), _angularVelocityChanged(false), @@ -198,6 +200,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_GRAVITY, gravity); CHECK_PROPERTY_CHANGE(PROP_DAMPING, damping); CHECK_PROPERTY_CHANGE(PROP_LIFETIME, lifetime); + CHECK_PROPERTY_CHANGE(PROP_USER_DATA, userData); CHECK_PROPERTY_CHANGE(PROP_SCRIPT, script); CHECK_PROPERTY_CHANGE(PROP_COLOR, color); CHECK_PROPERTY_CHANGE(PROP_MODEL_URL, modelURL); @@ -247,6 +250,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons COPY_PROPERTY_TO_QSCRIPTVALUE(damping); COPY_PROPERTY_TO_QSCRIPTVALUE(mass); COPY_PROPERTY_TO_QSCRIPTVALUE(lifetime); + COPY_PROPERTY_TO_QSCRIPTVALUE(userData); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(age, getAge()); // gettable, but not settable COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(ageAsText, formatSecondsElapsed(getAge())); // gettable, but not settable COPY_PROPERTY_TO_QSCRIPTVALUE(script); @@ -350,6 +354,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(cutoff, setCutoff); COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(locked, setLocked); COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(textures, setTextures); + COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(userData, setUserData); _lastEdited = usecTimestampNow(); } @@ -512,6 +517,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem APPEND_ENTITY_PROPERTY(PROP_LOCKED, appendValue, properties.getLocked()); APPEND_ENTITY_PROPERTY(PROP_TEXTURES, appendValue, properties.getTextures()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, appendValue, properties.getAnimationSettings()); + APPEND_ENTITY_PROPERTY(PROP_USER_DATA, appendValue, properties.getUserData()); } if (propertyCount > 0) { int endOfEntityItemData = packetData->getUncompressedByteOffset(); @@ -722,6 +728,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCKED, bool, setLocked); READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_TEXTURES, setTextures); READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_ANIMATION_SETTINGS, setAnimationSettings); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_USER_DATA, QString, setUserData); return valid; } @@ -764,6 +771,7 @@ void EntityItemProperties::markAllChanged() { _gravityChanged = true; _dampingChanged = true; _lifetimeChanged = true; + _userDataChanged = true; _scriptChanged = true; _registrationPointChanged = true; _angularVelocityChanged = true; diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index d6b8181c28..534ed7615f 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -47,6 +47,7 @@ enum EntityPropertyList { PROP_GRAVITY, PROP_DAMPING, PROP_LIFETIME, + PROP_USER_DATA, PROP_SCRIPT, // these properties are supported by some derived classes @@ -156,9 +157,13 @@ public: float getDamping() const { return _damping; } void setDamping(float value) { _damping = value; _dampingChanged = true; } - + float getLifetime() const { return _lifetime; } /// get the lifetime in seconds for the entity void setLifetime(float value) { _lifetime = value; _lifetimeChanged = true; } /// set the lifetime in seconds for the entity + + const QString& getUserData() const { return _userData; } + void setUserData(const QString& value) { _userData = value; _userDataChanged = true; } + float getAge() const { return (float)(usecTimestampNow() - _created) / (float)USECS_PER_SECOND; } quint64 getCreated() const { return _created; } void setCreated(quint64 usecTime) { _created = usecTime; } @@ -216,6 +221,7 @@ public: bool gravityChanged() const { return _gravityChanged; } bool dampingChanged() const { return _dampingChanged; } bool lifetimeChanged() const { return _lifetimeChanged; } + bool userDataChanged() const { return _userDataChanged; } bool scriptChanged() const { return _scriptChanged; } bool dimensionsChanged() const { return _dimensionsChanged; } bool registrationPointChanged() const { return _registrationPointChanged; } @@ -315,6 +321,7 @@ private: glm::vec3 _gravity; float _damping; float _lifetime; + QString _userData; QString _script; glm::vec3 _registrationPoint; glm::vec3 _angularVelocity; @@ -331,6 +338,7 @@ private: bool _gravityChanged; bool _dampingChanged; bool _lifetimeChanged; + bool _userDataChanged; bool _scriptChanged; bool _registrationPointChanged; bool _angularVelocityChanged; diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index a5fdd86e3d..e200d82e9d 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -75,7 +75,7 @@ PacketVersion versionForPacketType(PacketType type) { return 1; case PacketTypeEntityAddOrEdit: case PacketTypeEntityData: - return VERSION_ENTITIES_MODELS_HAVE_ANIMATION_SETTINGS; + return VERSION_ENTITIES_HAVE_USER_DATA; case PacketTypeEntityErase: return 2; case PacketTypeAudioStreamStats: diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index 466aebd36b..d617f2243a 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -125,6 +125,7 @@ const PacketVersion VERSION_ENTITIES_SUPPORT_SPLIT_MTU = 3; const PacketVersion VERSION_ENTITIES_HAS_FILE_BREAKS = VERSION_ENTITIES_SUPPORT_SPLIT_MTU; const PacketVersion VERSION_ENTITIES_SUPPORT_DIMENSIONS = 4; const PacketVersion VERSION_ENTITIES_MODELS_HAVE_ANIMATION_SETTINGS = 5; +const PacketVersion VERSION_ENTITIES_HAVE_USER_DATA = 6; const PacketVersion VERSION_VOXELS_HAS_FILE_BREAKS = 1; #endif // hifi_PacketHeaders_h From f8be98260cf87984c3bcbbe41de8c354f072d8e6 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 13 Nov 2014 16:32:15 -0800 Subject: [PATCH 12/15] String specific macros --- libraries/entities/src/EntityItem.cpp | 2 +- libraries/entities/src/EntityItemProperties.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 8228ebc8ce..a73bd486c9 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -506,7 +506,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, bool, _ignoreForCollisions); READ_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, bool, _collisionsWillMove); READ_ENTITY_PROPERTY(PROP_LOCKED, bool, _locked); - READ_ENTITY_PROPERTY(PROP_USER_DATA, QString, _userData); + READ_ENTITY_PROPERTY_STRING(PROP_USER_DATA,setUserData); if (wantDebug) { qDebug() << " readEntityDataFromBuffer() _registrationPoint:" << _registrationPoint; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 86bf81f6e2..305507ead9 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -728,7 +728,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCKED, bool, setLocked); READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_TEXTURES, setTextures); READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_ANIMATION_SETTINGS, setAnimationSettings); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_USER_DATA, QString, setUserData); + READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_USER_DATA, setUserData); return valid; } From 40576b3c03d03965d36cf87704f859578c335c68 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 13 Nov 2014 17:02:45 -0800 Subject: [PATCH 13/15] moved append to the end --- libraries/entities/src/EntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index a73bd486c9..e17bfb362a 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -234,7 +234,6 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_GRAVITY, appendValue, getGravity()); APPEND_ENTITY_PROPERTY(PROP_DAMPING, appendValue, getDamping()); APPEND_ENTITY_PROPERTY(PROP_LIFETIME, appendValue, getLifetime()); - APPEND_ENTITY_PROPERTY(PROP_USER_DATA, appendValue, getUserData()); APPEND_ENTITY_PROPERTY(PROP_SCRIPT, appendValue, getScript()); APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, appendValue, getRegistrationPoint()); APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, appendValue, getAngularVelocity()); @@ -243,6 +242,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, appendValue, getIgnoreForCollisions()); APPEND_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, appendValue, getCollisionsWillMove()); APPEND_ENTITY_PROPERTY(PROP_LOCKED, appendValue, getLocked()); + APPEND_ENTITY_PROPERTY(PROP_USER_DATA, appendValue, getUserData()); appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, From 9fc74515818357755512fe60b5124c29b68940bd Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 13 Nov 2014 17:06:57 -0800 Subject: [PATCH 14/15] Move macros to the end --- libraries/entities/src/EntityItem.cpp | 2 +- libraries/entities/src/EntityItemProperties.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index e17bfb362a..d5790d88a7 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -117,7 +117,6 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_GRAVITY; requestedProperties += PROP_DAMPING; requestedProperties += PROP_LIFETIME; - requestedProperties += PROP_USER_DATA; requestedProperties += PROP_SCRIPT; requestedProperties += PROP_REGISTRATION_POINT; requestedProperties += PROP_ANGULAR_VELOCITY; @@ -126,6 +125,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_IGNORE_FOR_COLLISIONS; requestedProperties += PROP_COLLISIONS_WILL_MOVE; requestedProperties += PROP_LOCKED; + requestedProperties += PROP_USER_DATA; return requestedProperties; } diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 305507ead9..75fa05032a 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -200,7 +200,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_GRAVITY, gravity); CHECK_PROPERTY_CHANGE(PROP_DAMPING, damping); CHECK_PROPERTY_CHANGE(PROP_LIFETIME, lifetime); - CHECK_PROPERTY_CHANGE(PROP_USER_DATA, userData); CHECK_PROPERTY_CHANGE(PROP_SCRIPT, script); CHECK_PROPERTY_CHANGE(PROP_COLOR, color); CHECK_PROPERTY_CHANGE(PROP_MODEL_URL, modelURL); @@ -226,6 +225,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_CUTOFF, cutoff); CHECK_PROPERTY_CHANGE(PROP_LOCKED, locked); CHECK_PROPERTY_CHANGE(PROP_TEXTURES, textures); + CHECK_PROPERTY_CHANGE(PROP_USER_DATA, userData); return changedProperties; } @@ -250,7 +250,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons COPY_PROPERTY_TO_QSCRIPTVALUE(damping); COPY_PROPERTY_TO_QSCRIPTVALUE(mass); COPY_PROPERTY_TO_QSCRIPTVALUE(lifetime); - COPY_PROPERTY_TO_QSCRIPTVALUE(userData); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(age, getAge()); // gettable, but not settable COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(ageAsText, formatSecondsElapsed(getAge())); // gettable, but not settable COPY_PROPERTY_TO_QSCRIPTVALUE(script); @@ -280,6 +279,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons COPY_PROPERTY_TO_QSCRIPTVALUE(cutoff); COPY_PROPERTY_TO_QSCRIPTVALUE(locked); COPY_PROPERTY_TO_QSCRIPTVALUE(textures); + COPY_PROPERTY_TO_QSCRIPTVALUE(userData); // Sitting properties support QScriptValue sittingPoints = engine->newObject(); From f914f02a0b39ad82f07f44a09802a72bb3b0b963 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 13 Nov 2014 17:44:22 -0800 Subject: [PATCH 15/15] Move user data to end of enum --- libraries/entities/src/EntityItem.h | 11 +++++------ libraries/entities/src/EntityItemProperties.h | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 51accd2a4f..cb153dee60 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -196,11 +196,6 @@ public: static const float DEFAULT_LIFETIME; float getLifetime() const { return _lifetime; } /// get the lifetime in seconds for the entity void setLifetime(float value) { _lifetime = value; } /// set the lifetime in seconds for the entity - - /// User-specified data stored in a variant map - static const QString DEFAULT_USER_DATA; - const QString& getUserData() const { return _userData; } - void setUserData(const QString& value) { _userData = value; } /// is this entity immortal, in that it has no lifetime set, and will exist until manually deleted bool isImmortal() const { return _lifetime == IMMORTAL; } @@ -257,6 +252,10 @@ public: bool getLocked() const { return _locked; } void setLocked(bool value) { _locked = value; } + static const QString DEFAULT_USER_DATA; + const QString& getUserData() const { return _userData; } + void setUserData(const QString& value) { _userData = value; } + // TODO: We need to get rid of these users of getRadius()... float getRadius() const; @@ -289,7 +288,6 @@ protected: glm::vec3 _gravity; float _damping; float _lifetime; - QString _userData; QString _script; glm::vec3 _registrationPoint; glm::vec3 _angularVelocity; @@ -298,6 +296,7 @@ protected: bool _ignoreForCollisions; bool _collisionsWillMove; bool _locked; + QString _userData; // NOTE: Radius support is obsolete, but these private helper functions are available for this class to // parse old data streams diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 534ed7615f..273aedb18a 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -47,7 +47,6 @@ enum EntityPropertyList { PROP_GRAVITY, PROP_DAMPING, PROP_LIFETIME, - PROP_USER_DATA, PROP_SCRIPT, // these properties are supported by some derived classes @@ -82,8 +81,9 @@ enum EntityPropertyList { // used by Model entities PROP_TEXTURES, PROP_ANIMATION_SETTINGS, + PROP_USER_DATA, - PROP_LAST_ITEM = PROP_ANIMATION_SETTINGS + PROP_LAST_ITEM = PROP_USER_DATA }; typedef PropertyFlags EntityPropertyFlags;