diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c8f7cedf6c..a4ef5579f0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1714,12 +1714,9 @@ bool Application::acceptSnapshot(const QString& urlString) { SnapshotMetaData* snapshotData = Snapshot::parseSnapshotData(snapshotPath); if (snapshotData) { - if (!snapshotData->getDomain().isEmpty()) { - DependencyManager::get()->getDomainHandler().setHostnameAndPort(snapshotData->getDomain()); + if (!snapshotData->getURL().toString().isEmpty()) { + DependencyManager::get()->handleLookupString(snapshotData->getURL().toString()); } - - _myAvatar->setPosition(snapshotData->getLocation()); - _myAvatar->setOrientation(snapshotData->getOrientation()); } else { QMessageBox msgBox; msgBox.setText("No location details were found in the file " @@ -3188,17 +3185,12 @@ namespace render { template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape(); } template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff) { return Item::Bound(); } template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) { - if (args->_renderMode != CAMERA_MODE_MIRROR && Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { + if (args->_renderMode != RenderArgs::MIRROR_RENDER_MODE && Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { PerformanceTimer perfTimer("worldBox"); - - DependencyManager::get()->bindSimpleProgram((*args->_batch)); - - renderWorldBox(args); - // FIXME: there's currently a bug in the new render engine, if this origin dot is rendered out of view it will - // screw up the state of textures on models so they all end up rendering in the incorrect tint/color/texture - float originSphereRadius = 0.05f; - DependencyManager::get()->renderSphere((*args->_batch), originSphereRadius, 15, 15, glm::vec4(1.0f, 0.0f, 0.0f, 1.0f)); + auto& batch = *args->_batch; + DependencyManager::get()->bindSimpleProgram(batch); + renderWorldBox(batch); } } } diff --git a/interface/src/MainWindow.cpp b/interface/src/MainWindow.cpp index f60716dc48..e30de96890 100644 --- a/interface/src/MainWindow.cpp +++ b/interface/src/MainWindow.cpp @@ -17,6 +17,9 @@ #include #include #include +#include +#include +#include #include "MainWindow.h" #include "Menu.h" @@ -27,6 +30,7 @@ MainWindow::MainWindow(QWidget* parent) : _windowGeometry("WindowGeometry"), _windowState("WindowState", 0) { + setAcceptDrops(true); } void MainWindow::restoreGeometry() { @@ -87,13 +91,13 @@ void MainWindow::changeEvent(QEvent* event) { if (event->type() == QEvent::WindowStateChange) { QWindowStateChangeEvent* stateChangeEvent = static_cast(event); if ((stateChangeEvent->oldState() == Qt::WindowNoState || - stateChangeEvent->oldState() == Qt::WindowMaximized) && - windowState() == Qt::WindowMinimized) { + stateChangeEvent->oldState() == Qt::WindowMaximized) && + windowState() == Qt::WindowMinimized) { emit windowShown(false); } else { emit windowShown(true); } - + if (isFullScreen() != Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) { Menu::getInstance()->setIsOptionChecked(MenuOption::Fullscreen, isFullScreen()); } @@ -106,3 +110,13 @@ void MainWindow::changeEvent(QEvent* event) { } QMainWindow::changeEvent(event); } + +void MainWindow::dragEnterEvent(QDragEnterEvent* event) { + if (event->mimeData()) { + event->acceptProposedAction(); + } +} + +void MainWindow::dropEvent(QDropEvent* event) { + QCoreApplication::sendEvent(QCoreApplication::instance(), event); +} diff --git a/interface/src/MainWindow.h b/interface/src/MainWindow.h index c6faf8e01a..eb262e0f97 100644 --- a/interface/src/MainWindow.h +++ b/interface/src/MainWindow.h @@ -36,6 +36,8 @@ protected: virtual void showEvent(QShowEvent* event); virtual void hideEvent(QHideEvent* event); virtual void changeEvent(QEvent* event); + virtual void dragEnterEvent(QDragEnterEvent *e); + virtual void dropEvent(QDropEvent *e); private: Setting::Handle _windowGeometry; diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 44ee38187c..f3449f9eb8 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -33,42 +33,44 @@ using namespace std; -void renderWorldBox(RenderArgs* renderArgs) { +void renderWorldBox(gpu::Batch& batch) { auto geometryCache = DependencyManager::get(); - auto batch = renderArgs->_batch; // Show edge of world glm::vec3 red(1.0f, 0.0f, 0.0f); glm::vec3 green(0.0f, 1.0f, 0.0f); glm::vec3 blue(0.0f, 0.0f, 1.0f); glm::vec3 grey(0.5f, 0.5f, 0.5f); - - geometryCache->renderLine(*batch, glm::vec3(0, 0, 0), glm::vec3(TREE_SCALE, 0, 0), red); - geometryCache->renderLine(*batch, glm::vec3(0, 0, 0), glm::vec3(0, TREE_SCALE, 0), green); - geometryCache->renderLine(*batch, glm::vec3(0, 0, 0), glm::vec3(0, 0, TREE_SCALE), blue); - geometryCache->renderLine(*batch, glm::vec3(0, 0, TREE_SCALE), glm::vec3(TREE_SCALE, 0, TREE_SCALE), grey); - geometryCache->renderLine(*batch, glm::vec3(TREE_SCALE, 0, TREE_SCALE), glm::vec3(TREE_SCALE, 0, 0), grey); + + auto transform = Transform{}; + batch.setModelTransform(transform); + geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(TREE_SCALE, 0.0f, 0.0f), red); + geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, TREE_SCALE, 0.0f), green); + geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, TREE_SCALE), blue); + geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, TREE_SCALE), glm::vec3(TREE_SCALE, 0.0f, TREE_SCALE), grey); + geometryCache->renderLine(batch, glm::vec3(TREE_SCALE, 0.0f, TREE_SCALE), glm::vec3(TREE_SCALE, 0.0f, 0.0f), grey); // Draw meter markers along the 3 axis to help with measuring things const float MARKER_DISTANCE = 1.0f; const float MARKER_RADIUS = 0.05f; + + geometryCache->renderSphere(batch, MARKER_RADIUS, 10, 10, red); + + transform.setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, 0.0f)); + batch.setModelTransform(transform); + geometryCache->renderSphere(batch, MARKER_RADIUS, 10, 10, red); - Transform transform; - transform.setTranslation(glm::vec3(MARKER_DISTANCE, 0, 0)); - batch->setModelTransform(transform); - geometryCache->renderSphere(*batch, MARKER_RADIUS, 10, 10, red); + transform.setTranslation(glm::vec3(0.0f, MARKER_DISTANCE, 0.0f)); + batch.setModelTransform(transform); + geometryCache->renderSphere(batch, MARKER_RADIUS, 10, 10, green); - transform.setTranslation(glm::vec3(0, MARKER_DISTANCE, 0)); - batch->setModelTransform(transform); - geometryCache->renderSphere(*batch, MARKER_RADIUS, 10, 10, green); + transform.setTranslation(glm::vec3(0.0f, 0.0f, MARKER_DISTANCE)); + batch.setModelTransform(transform); + geometryCache->renderSphere(batch, MARKER_RADIUS, 10, 10, blue); - transform.setTranslation(glm::vec3(0, 0, MARKER_DISTANCE)); - batch->setModelTransform(transform); - geometryCache->renderSphere(*batch, MARKER_RADIUS, 10, 10, blue); - - transform.setTranslation(glm::vec3(MARKER_DISTANCE, 0, MARKER_DISTANCE)); - batch->setModelTransform(transform); - geometryCache->renderSphere(*batch, MARKER_RADIUS, 10, 10, grey); + transform.setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, MARKER_DISTANCE)); + batch.setModelTransform(transform); + geometryCache->renderSphere(batch, MARKER_RADIUS, 10, 10, grey); } // Return a random vector of average length 1 diff --git a/interface/src/Util.h b/interface/src/Util.h index a4a1595d6b..90debbffe5 100644 --- a/interface/src/Util.h +++ b/interface/src/Util.h @@ -21,7 +21,7 @@ float randFloat(); const glm::vec3 randVector(); -void renderWorldBox(RenderArgs* renderArgs); +void renderWorldBox(gpu::Batch& batch); int widthText(float scale, int mono, char const* string); void drawText(int x, int y, float scale, float radians, int mono, diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 429a375f03..9656fa45fd 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -581,9 +581,11 @@ void Avatar::simulateAttachments(float deltaTime) { void Avatar::renderAttachments(RenderArgs* args) { // RenderArgs::RenderMode modelRenderMode = (renderMode == RenderArgs::SHADOW_RENDER_MODE) ? // RenderArgs::SHADOW_RENDER_MODE : RenderArgs::DEFAULT_RENDER_MODE; + /* foreach (Model* model, _attachmentModels) { model->render(args, 1.0f); } + */ } void Avatar::updateJointMappings() { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 8407824750..8a49d69129 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1580,12 +1580,16 @@ void MyAvatar::renderAttachments(RenderArgs* args) { QString headJointName = (geometry.headJointIndex == -1) ? QString() : geometry.joints.at(geometry.headJointIndex).name; // RenderArgs::RenderMode modelRenderMode = (renderMode == RenderArgs::SHADOW_RENDER_MODE) ? // RenderArgs::SHADOW_RENDER_MODE : RenderArgs::DEFAULT_RENDER_MODE; + + // FIX ME - attachments need to be added to scene too... + /* for (int i = 0; i < _attachmentData.size(); i++) { const QString& jointName = _attachmentData.at(i).jointName; if (jointName != headJointName && jointName != "Head") { _attachmentModels.at(i)->render(args, 1.0f); } } + */ } //Renders sixense laser pointers for UI selection with controllers diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index 0d91f4e7ba..2bfe92a504 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -15,8 +15,10 @@ #include #include #include +#include #include +#include #include #include #include @@ -28,131 +30,101 @@ // filename format: hifi-snap-by-%username%-on-%date%_%time%_@-%location%.jpg // %1 <= username, %2 <= date and time, %3 <= current location -const QString FILENAME_PATH_FORMAT = "hifi-snap-by-%1-on-%2@%3.jpg"; +const QString FILENAME_PATH_FORMAT = "hifi-snap-by-%1-on-%2.jpg"; const QString DATETIME_FORMAT = "yyyy-MM-dd_hh-mm-ss"; const QString SNAPSHOTS_DIRECTORY = "Snapshots"; -const QString LOCATION_X = "location-x"; -const QString LOCATION_Y = "location-y"; -const QString LOCATION_Z = "location-z"; - -const QString ORIENTATION_X = "orientation-x"; -const QString ORIENTATION_Y = "orientation-y"; -const QString ORIENTATION_Z = "orientation-z"; -const QString ORIENTATION_W = "orientation-w"; - -const QString DOMAIN_KEY = "domain"; +const QString URL = "highfidelity_url"; Setting::Handle Snapshot::snapshotsLocation("snapshotsLocation", - QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); + QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); SnapshotMetaData* Snapshot::parseSnapshotData(QString snapshotPath) { - + if (!QFile(snapshotPath).exists()) { return NULL; } - + QImage shot(snapshotPath); - + // no location data stored - if (shot.text(LOCATION_X).isEmpty() || shot.text(LOCATION_Y).isEmpty() || shot.text(LOCATION_Z).isEmpty()) { + if (shot.text(URL).isEmpty()) { return NULL; } - + + // parsing URL + QUrl url = QUrl(shot.text(URL), QUrl::ParsingMode::StrictMode); + SnapshotMetaData* data = new SnapshotMetaData(); - data->setLocation(glm::vec3(shot.text(LOCATION_X).toFloat(), - shot.text(LOCATION_Y).toFloat(), - shot.text(LOCATION_Z).toFloat())); - - data->setOrientation(glm::quat(shot.text(ORIENTATION_W).toFloat(), - shot.text(ORIENTATION_X).toFloat(), - shot.text(ORIENTATION_Y).toFloat(), - shot.text(ORIENTATION_Z).toFloat())); - - data->setDomain(shot.text(DOMAIN_KEY)); - + data->setURL(url); + return data; } QString Snapshot::saveSnapshot(QImage image) { + QFile* snapshotFile = savedFileForSnapshot(image, false); - + // we don't need the snapshot file, so close it, grab its filename and delete it snapshotFile->close(); - + QString snapshotPath = QFileInfo(*snapshotFile).absoluteFilePath(); - + delete snapshotFile; - + return snapshotPath; } QTemporaryFile* Snapshot::saveTempSnapshot(QImage image) { // return whatever we get back from saved file for snapshot - return static_cast(savedFileForSnapshot(image, true));; + return static_cast(savedFileForSnapshot(image, true)); } QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary) { - - Avatar* avatar = DependencyManager::get()->getMyAvatar(); - - glm::vec3 location = avatar->getPosition(); - glm::quat orientation = avatar->getHead()->getOrientation(); - - // add metadata - shot.setText(LOCATION_X, QString::number(location.x)); - shot.setText(LOCATION_Y, QString::number(location.y)); - shot.setText(LOCATION_Z, QString::number(location.z)); - - shot.setText(ORIENTATION_X, QString::number(orientation.x)); - shot.setText(ORIENTATION_Y, QString::number(orientation.y)); - shot.setText(ORIENTATION_Z, QString::number(orientation.z)); - shot.setText(ORIENTATION_W, QString::number(orientation.w)); - - shot.setText(DOMAIN_KEY, DependencyManager::get()->getDomainHandler().getHostname()); - QString formattedLocation = QString("%1_%2_%3").arg(location.x).arg(location.y).arg(location.z); - // replace decimal . with '-' - formattedLocation.replace('.', '-'); - + // adding URL to snapshot + QUrl currentURL = DependencyManager::get()->currentAddress(); + shot.setText(URL, currentURL.toString()); + QString username = AccountManager::getInstance().getAccountInfo().getUsername(); // normalize username, replace all non alphanumeric with '-' username.replace(QRegExp("[^A-Za-z0-9_]"), "-"); - + QDateTime now = QDateTime::currentDateTime(); - - QString filename = FILENAME_PATH_FORMAT.arg(username, now.toString(DATETIME_FORMAT), formattedLocation); - + + QString filename = FILENAME_PATH_FORMAT.arg(username, now.toString(DATETIME_FORMAT)); + const int IMAGE_QUALITY = 100; - + if (!isTemporary) { QString snapshotFullPath = snapshotsLocation.get(); - + if (!snapshotFullPath.endsWith(QDir::separator())) { snapshotFullPath.append(QDir::separator()); } - + snapshotFullPath.append(filename); - + QFile* imageFile = new QFile(snapshotFullPath); imageFile->open(QIODevice::WriteOnly); - + shot.save(imageFile, 0, IMAGE_QUALITY); imageFile->close(); - + return imageFile; + } else { QTemporaryFile* imageTempFile = new QTemporaryFile(QDir::tempPath() + "/XXXXXX-" + filename); - + if (!imageTempFile->open()) { qDebug() << "Unable to open QTemporaryFile for temp snapshot. Will not save."; return NULL; } - + shot.save(imageTempFile, 0, IMAGE_QUALITY); imageTempFile->close(); - + return imageTempFile; } } diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h index e83f8b3ec4..5856743141 100644 --- a/interface/src/ui/Snapshot.h +++ b/interface/src/ui/Snapshot.h @@ -24,20 +24,12 @@ class QTemporaryFile; class SnapshotMetaData { public: - - QString getDomain() { return _domain; } - void setDomain(QString domain) { _domain = domain; } - - glm::vec3 getLocation() { return _location; } - void setLocation(glm::vec3 location) { _location = location; } - - glm::quat getOrientation() { return _orientation; } - void setOrientation(glm::quat orientation) { _orientation = orientation; } - + + QUrl getURL() { return _URL; } + void setURL(QUrl URL) { _URL = URL; } + private: - QString _domain; - glm::vec3 _location; - glm::quat _orientation;; + QUrl _URL; }; class Snapshot { @@ -45,7 +37,7 @@ public: static QString saveSnapshot(QImage image); static QTemporaryFile* saveTempSnapshot(QImage image); static SnapshotMetaData* parseSnapshotData(QString snapshotPath); - + static Setting::Handle snapshotsLocation; private: static QFile* savedFileForSnapshot(QImage & image, bool isTemporary); diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 73774759e7..822fff9808 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include #include #include "ModelOverlay.h" @@ -54,11 +55,34 @@ void ModelOverlay::update(float deltatime) { _isLoaded = _model.isActive(); } +bool ModelOverlay::addToScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges) { + Base3DOverlay::addToScene(overlay, scene, pendingChanges); + _model.addToScene(scene, pendingChanges); + return true; +} + +void ModelOverlay::removeFromScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges) { + Base3DOverlay::removeFromScene(overlay, scene, pendingChanges); + _model.removeFromScene(scene, pendingChanges); +} + void ModelOverlay::render(RenderArgs* args) { + + // check to see if when we added our model to the scene they were ready, if they were not ready, then + // fix them up in the scene + render::ScenePointer scene = Application::getInstance()->getMain3DScene(); + render::PendingChanges pendingChanges; + if (_model.needsFixupInScene()) { + _model.removeFromScene(scene, pendingChanges); + _model.addToScene(scene, pendingChanges); + } + scene->enqueuePendingChanges(pendingChanges); + if (!_visible) { return; } - + + /* if (_model.isActive()) { if (_model.isRenderable()) { float glowLevel = getGlowLevel(); @@ -72,6 +96,7 @@ void ModelOverlay::render(RenderArgs* args) { } } } + */ } void ModelOverlay::setProperties(const QScriptValue &properties) { diff --git a/interface/src/ui/overlays/ModelOverlay.h b/interface/src/ui/overlays/ModelOverlay.h index 8cd095f778..a81cae530a 100644 --- a/interface/src/ui/overlays/ModelOverlay.h +++ b/interface/src/ui/overlays/ModelOverlay.h @@ -32,6 +32,9 @@ public: virtual ModelOverlay* createClone() const; + virtual bool addToScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges); + virtual void removeFromScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges); + private: Model _model; diff --git a/interface/src/ui/overlays/Overlay.cpp b/interface/src/ui/overlays/Overlay.cpp index 99f59810cb..745c2b4a10 100644 --- a/interface/src/ui/overlays/Overlay.cpp +++ b/interface/src/ui/overlays/Overlay.cpp @@ -228,3 +228,15 @@ float Overlay::updatePulse() { return _pulse; } +bool Overlay::addToScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges) { + auto overlayPayload = new Overlay::Payload(overlay); + auto overlayPayloadPointer = Overlay::PayloadPointer(overlayPayload); + _renderItemID = scene->allocateID(); + pendingChanges.resetItem(_renderItemID, overlayPayloadPointer); + return true; +} + +void Overlay::removeFromScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges) { + pendingChanges.removeItem(_renderItemID); +} + diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index 74ffff9d24..1a808bc15c 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -48,6 +48,9 @@ public: virtual void update(float deltatime) {} virtual void render(RenderArgs* args) = 0; + virtual bool addToScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges); + virtual void removeFromScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges); + // getters virtual bool is3D() const = 0; bool isLoaded() { return _isLoaded; } @@ -117,5 +120,11 @@ protected: QScriptEngine* _scriptEngine; }; +namespace render { + template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay); + template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay); + template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args); +} + #endif // hifi_Overlay_h diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 5964596395..6e579ed4c4 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -33,49 +33,6 @@ #include "Text3DOverlay.h" -namespace render { - template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay) { - if (overlay->is3D() && !static_cast(overlay.get())->getDrawOnHUD()) { - if (static_cast(overlay.get())->getDrawInFront()) { - return ItemKey::Builder().withTypeShape().withNoDepthSort().build(); - } else { - return ItemKey::Builder::opaqueShape(); - } - } else { - return ItemKey::Builder().withTypeShape().withViewSpace().build(); - } - } - template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay) { - if (overlay->is3D()) { - return static_cast(overlay.get())->getBounds(); - } else { - QRect bounds = static_cast(overlay.get())->getBounds(); - return AABox(glm::vec3(bounds.x(), bounds.y(), 0.0f), glm::vec3(bounds.width(), bounds.height(), 0.1f)); - } - } - template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args) { - if (args) { - args->_elementsTouched++; - - glPushMatrix(); - if (overlay->getAnchor() == Overlay::MY_AVATAR) { - MyAvatar* avatar = DependencyManager::get()->getMyAvatar(); - glm::quat myAvatarRotation = avatar->getOrientation(); - glm::vec3 myAvatarPosition = avatar->getPosition(); - float angle = glm::degrees(glm::angle(myAvatarRotation)); - glm::vec3 axis = glm::axis(myAvatarRotation); - float myAvatarScale = avatar->getScale(); - - glTranslatef(myAvatarPosition.x, myAvatarPosition.y, myAvatarPosition.z); - glRotatef(angle, axis.x, axis.y, axis.z); - glScalef(myAvatarScale, myAvatarScale, myAvatarScale); - } - overlay->render(args); - glPopMatrix(); - } - } -} - Overlays::Overlays() : _nextOverlayID(1) { } @@ -118,6 +75,7 @@ void Overlays::update(float deltatime) { void Overlays::cleanupOverlaysToDelete() { if (!_overlaysToDelete.isEmpty()) { + render::ScenePointer scene = Application::getInstance()->getMain3DScene(); render::PendingChanges pendingChanges; { @@ -128,13 +86,12 @@ void Overlays::cleanupOverlaysToDelete() { auto itemID = overlay->getRenderItemID(); if (itemID != render::Item::INVALID_ITEM_ID) { - pendingChanges.removeItem(itemID); + overlay->removeFromScene(overlay, scene, pendingChanges); } } while (!_overlaysToDelete.isEmpty()); } if (pendingChanges._removedItems.size() > 0) { - render::ScenePointer scene = Application::getInstance()->getMain3DScene(); scene->enqueuePendingChanges(pendingChanges); } } @@ -216,13 +173,9 @@ unsigned int Overlays::addOverlay(Overlay* overlay) { _overlaysWorld[thisID] = overlayPointer; render::ScenePointer scene = Application::getInstance()->getMain3DScene(); - auto overlayPayload = new Overlay::Payload(overlayPointer); - auto overlayPayloadPointer = Overlay::PayloadPointer(overlayPayload); - render::ItemID itemID = scene->allocateID(); - overlay->setRenderItemID(itemID); - render::PendingChanges pendingChanges; - pendingChanges.resetItem(itemID, overlayPayloadPointer); + + overlayPointer->addToScene(overlayPointer, scene, pendingChanges); scene->enqueuePendingChanges(pendingChanges); } diff --git a/interface/src/ui/overlays/OverlaysPayload.cpp b/interface/src/ui/overlays/OverlaysPayload.cpp new file mode 100644 index 0000000000..b4be515a46 --- /dev/null +++ b/interface/src/ui/overlays/OverlaysPayload.cpp @@ -0,0 +1,77 @@ +// +// OverlaysPayload.cpp +// interface/src/ui/overlays +// +// 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 + +#include +#include + +#include +#include +#include +#include + +#include "BillboardOverlay.h" +#include "Circle3DOverlay.h" +#include "Cube3DOverlay.h" +#include "ImageOverlay.h" +#include "Line3DOverlay.h" +#include "LocalModelsOverlay.h" +#include "ModelOverlay.h" +#include "Overlays.h" +#include "Rectangle3DOverlay.h" +#include "Sphere3DOverlay.h" +#include "Grid3DOverlay.h" +#include "TextOverlay.h" +#include "Text3DOverlay.h" + + +namespace render { + template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay) { + if (overlay->is3D() && !static_cast(overlay.get())->getDrawOnHUD()) { + if (static_cast(overlay.get())->getDrawInFront()) { + return ItemKey::Builder().withTypeShape().withNoDepthSort().build(); + } else { + return ItemKey::Builder::opaqueShape(); + } + } else { + return ItemKey::Builder().withTypeShape().withViewSpace().build(); + } + } + template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay) { + if (overlay->is3D()) { + return static_cast(overlay.get())->getBounds(); + } else { + QRect bounds = static_cast(overlay.get())->getBounds(); + return AABox(glm::vec3(bounds.x(), bounds.y(), 0.0f), glm::vec3(bounds.width(), bounds.height(), 0.1f)); + } + } + template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args) { + if (args) { + args->_elementsTouched++; + + glPushMatrix(); + if (overlay->getAnchor() == Overlay::MY_AVATAR) { + MyAvatar* avatar = DependencyManager::get()->getMyAvatar(); + glm::quat myAvatarRotation = avatar->getOrientation(); + glm::vec3 myAvatarPosition = avatar->getPosition(); + float angle = glm::degrees(glm::angle(myAvatarRotation)); + glm::vec3 axis = glm::axis(myAvatarRotation); + float myAvatarScale = avatar->getScale(); + + glTranslatef(myAvatarPosition.x, myAvatarPosition.y, myAvatarPosition.z); + glRotatef(angle, axis.x, axis.y, axis.z); + glScalef(myAvatarScale, myAvatarScale, myAvatarScale); + } + overlay->render(args); + glPopMatrix(); + } + } +} diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index cc6693133f..213a8de9a0 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -493,45 +493,22 @@ void EntityTreeRenderer::render(RenderArgs* renderArgs) { if (_tree && !_shuttingDown) { renderArgs->_renderer = this; - checkPendingAddToScene(renderArgs); - - Model::startScene(renderArgs->_renderSide); - - ViewFrustum* frustum = (renderArgs->_renderMode == RenderArgs::SHADOW_RENDER_MODE) ? - _viewState->getShadowViewFrustum() : _viewState->getCurrentViewFrustum(); - - // Setup batch transform matrices - gpu::Batch batch; // FIX ME - this is very suspicious! - glm::mat4 projMat; - Transform viewMat; - frustum->evalProjectionMatrix(projMat); - frustum->evalViewTransform(viewMat); - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewMat); - - renderArgs->_batch = &batch; // FIX ME - this is very suspicious! - _tree->lockForRead(); // Whenever you're in an intersection between zones, we will always choose the smallest zone. _bestZone = NULL; // NOTE: Is this what we want? _bestZoneVolume = std::numeric_limits::max(); + + // FIX ME: right now the renderOperation does the following: + // 1) determining the best zone (not really rendering) + // 2) render the debug cell details + // we should clean this up _tree->recurseTreeWithOperation(renderOperation, renderArgs); applyZonePropertiesToScene(_bestZone); - // we must call endScene while we still have the tree locked so that no one deletes a model - // on us while rendering the scene - Model::endScene(renderArgs); _tree->unlock(); - // FIX ME - this is very suspicious! - // glPushMatrix(); - // renderArgs->_context->render(batch); - // glPopMatrix(); - - renderArgs->_batch = nullptr; - // stats... _meshesConsidered = renderArgs->_meshesConsidered; _meshesRendered = renderArgs->_meshesRendered; @@ -715,39 +692,6 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) } } } - - // hack for models and other entities that don't yet play well with others. :( - if (!entityItem->canRenderInScene()) { - // render entityItem - AABox entityBox = entityItem->getAABox(); - - // TODO: some entity types (like lights) might want to be rendered even - // when they are outside of the view frustum... - float distance = args->_viewFrustum->distanceToCamera(entityBox.calcCenter()); - - bool outOfView = args->_viewFrustum->boxInFrustum(entityBox) == ViewFrustum::OUTSIDE; - if (!outOfView) { - bool bigEnoughToRender = _viewState->shouldRenderMesh(entityBox.getLargestDimension(), distance); - - if (bigEnoughToRender) { - renderProxies(entityItem, args); - - Glower* glower = NULL; - if (entityItem->getGlowLevel() > 0.0f) { - glower = new Glower(args, entityItem->getGlowLevel()); - } - entityItem->render(args); - args->_itemsRendered++; - if (glower) { - delete glower; - } - } else { - args->_itemsTooSmall++; - } - } else { - args->_itemsOutOfView++; - } - } } } } @@ -1093,34 +1037,14 @@ void EntityTreeRenderer::addingEntity(const EntityItemID& entityID) { void EntityTreeRenderer::addEntityToScene(EntityItemPointer entity) { // here's where we add the entity payload to the scene - if (entity && entity->canRenderInScene()) { - if (entity->readyToAddToScene()) { - render::PendingChanges pendingChanges; - auto scene = _viewState->getMain3DScene(); - if (entity->addToScene(entity, scene, pendingChanges)) { - _entitiesInScene.insert(entity); - } - scene->enqueuePendingChanges(pendingChanges); - } else { - if (!_pendingAddToScene.contains(entity)) { - _pendingAddToScene << entity; - } - } + render::PendingChanges pendingChanges; + auto scene = _viewState->getMain3DScene(); + if (entity->addToScene(entity, scene, pendingChanges)) { + _entitiesInScene.insert(entity); } + scene->enqueuePendingChanges(pendingChanges); } -void EntityTreeRenderer::checkPendingAddToScene(RenderArgs* renderArgs) { - QSet addedToScene; - foreach (auto entity, _pendingAddToScene) { - if (entity->readyToAddToScene(renderArgs)) { - addEntityToScene(entity); - addedToScene << entity; - } - } - foreach (auto addedEntity, addedToScene) { - _pendingAddToScene.remove(addedEntity); - } -} void EntityTreeRenderer::entitySciptChanging(const EntityItemID& entityID) { if (_tree && !_shuttingDown) { diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 2c1c5ef928..55c889d1c1 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -123,9 +123,7 @@ protected: virtual Octree* createTree() { return new EntityTree(true); } private: - void checkPendingAddToScene(RenderArgs* renderArgs); void addEntityToScene(EntityItemPointer entity); - QSet _pendingAddToScene; void applyZonePropertiesToScene(std::shared_ptr zone); void renderElementProxy(EntityTreeElement* entityTreeElement, RenderArgs* args); diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 926889ccac..e5e0f2ff85 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -32,9 +32,7 @@ namespace render { if (args) { args->_elementsTouched++; if (payload && payload->entity) { - if (payload->entity->getType() != EntityTypes::Model) { - payload->entity->render(args); - } + payload->entity->render(args); } } } diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 92eef7e8ea..2037788ace 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -56,7 +56,6 @@ private: #define SIMPLE_RENDERABLE() \ public: \ - virtual bool canRenderInScene() { return true; } \ virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { return _renderHelper.addToScene(self, scene, pendingChanges); } \ virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { _renderHelper.removeFromScene(self, scene, pendingChanges); } \ private: \ diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.h b/libraries/entities-renderer/src/RenderableLightEntityItem.h index a90bb0baad..a0c424e240 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.h +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.h @@ -13,6 +13,7 @@ #define hifi_RenderableLightEntityItem_h #include +#include "RenderableEntityItem.h" class RenderableLightEntityItem : public LightEntityItem { public: @@ -22,12 +23,13 @@ public: LightEntityItem(entityItemID, properties) { } - virtual bool canRenderInScene() { return false; } // we don't yet play well with others virtual void render(RenderArgs* args); virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, void** intersectedObject, bool precisionPicking) const; + + SIMPLE_RENDERABLE(); }; diff --git a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp index 45abe36fdb..01926675c6 100644 --- a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp @@ -24,32 +24,32 @@ EntityItemPointer RenderableLineEntityItem::factory(const EntityItemID& entityID return EntityItemPointer(new RenderableLineEntityItem(entityID, properties)); } -void RenderableLineEntityItem::render(RenderArgs* args) { - PerformanceTimer perfTimer("RenderableLineEntityItem::render"); - Q_ASSERT(getType() == EntityTypes::Line); - glm::vec3 p1 = ENTITY_ITEM_ZERO_VEC3; - glm::vec3 p2 = getDimensions(); - glm::vec4 lineColor(toGlm(getXColor()), getLocalRenderAlpha()); - - Q_ASSERT(args->_batch); - gpu::Batch& batch = *args->_batch; - batch.setModelTransform(getTransformToCenter()); - - glLineWidth(getLineWidth()); +void RenderableLineEntityItem::updateGeometry() { auto geometryCache = DependencyManager::get(); if (_lineVerticesID == GeometryCache::UNKNOWN_ID) { _lineVerticesID = geometryCache ->allocateID(); } - - //TODO: Figure out clean , efficient way to do relative line positioning. For now we'll just use absolute positioning. - //glTranslatef(position.x, position.y, position.z); - //glm::vec3 axis = glm::axis(rotation); - //glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); if (_pointsChanged) { - geometryCache->updateVertices(_lineVerticesID, getLinePoints(), lineColor); + glm::vec4 lineColor(toGlm(getXColor()), getLocalRenderAlpha()); + geometryCache->updateVertices(_lineVerticesID, getLinePoints(), lineColor); _pointsChanged = false; } - geometryCache->renderVertices(gpu::LINE_STRIP, _lineVerticesID); +} + +void RenderableLineEntityItem::render(RenderArgs* args) { + PerformanceTimer perfTimer("RenderableLineEntityItem::render"); + Q_ASSERT(getType() == EntityTypes::Line); + updateGeometry(); + + Q_ASSERT(args->_batch); + gpu::Batch& batch = *args->_batch; + // TODO: Figure out clean , efficient way to do relative line positioning. For now we'll just use absolute positioning. + //batch.setModelTransform(getTransformToCenter()); + batch.setModelTransform(Transform()); + + batch._glLineWidth(getLineWidth()); + DependencyManager::get()->renderVertices(batch, gpu::LINE_STRIP, _lineVerticesID); + batch._glLineWidth(1.0f); RenderableDebugableEntityItem::render(this, args); }; diff --git a/libraries/entities-renderer/src/RenderableLineEntityItem.h b/libraries/entities-renderer/src/RenderableLineEntityItem.h index 8a25196ec5..09f98ca364 100644 --- a/libraries/entities-renderer/src/RenderableLineEntityItem.h +++ b/libraries/entities-renderer/src/RenderableLineEntityItem.h @@ -28,9 +28,11 @@ public: virtual void render(RenderArgs* args); - SIMPLE_RENDERABLE() + SIMPLE_RENDERABLE(); protected: + void updateGeometry(); + int _lineVerticesID; }; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index c4930f1225..29da23702c 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -15,6 +15,7 @@ #include +#include #include #include #include @@ -210,6 +211,19 @@ void RenderableModelEntityItem::render(RenderArgs* args) { } if (hasModel()) { + if (_model) { + // check to see if when we added our models to the scene they were ready, if they were not ready, then + // fix them up in the scene + render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); + render::PendingChanges pendingChanges; + if (_model->needsFixupInScene()) { + _model->removeFromScene(scene, pendingChanges); + _model->addToScene(scene, pendingChanges); + } + scene->enqueuePendingChanges(pendingChanges); + } + + remapTextures(); { float alpha = getLocalRenderAlpha(); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 837890a960..ac1d4b494f 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -43,7 +43,6 @@ public: virtual void somethingChangedNotification() { _needsInitialSimulation = true; } - virtual bool canRenderInScene() { return true; } virtual bool readyToAddToScene(RenderArgs* renderArgs = nullptr); virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges); virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges); diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index 66505a2cd2..4ecea45ad0 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -23,7 +23,7 @@ public: void updateQuads(RenderArgs* args, bool textured); - SIMPLE_RENDERABLE() + SIMPLE_RENDERABLE(); protected: diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index c8f1b4a49d..77aeb24f2a 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -16,6 +16,7 @@ #include "PolyVoxEntityItem.h" #include "RenderableDebugableEntityItem.h" +#include "RenderableEntityItem.h" class RenderablePolyVoxEntityItem : public PolyVoxEntityItem { public: @@ -70,6 +71,8 @@ public: virtual void setAll(uint8_t toValue); virtual void setVoxelInVolume(glm::vec3 position, uint8_t toValue); + + SIMPLE_RENDERABLE(); private: // The PolyVoxEntityItem class has _voxelData which contains dimensions and compressed voxel data. The dimensions diff --git a/libraries/entities-renderer/src/RenderableSphereEntityItem.h b/libraries/entities-renderer/src/RenderableSphereEntityItem.h index b6f7ff996e..6331b35706 100644 --- a/libraries/entities-renderer/src/RenderableSphereEntityItem.h +++ b/libraries/entities-renderer/src/RenderableSphereEntityItem.h @@ -26,7 +26,7 @@ public: virtual void render(RenderArgs* args); - SIMPLE_RENDERABLE() + SIMPLE_RENDERABLE(); }; diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.h b/libraries/entities-renderer/src/RenderableTextEntityItem.h index 5db22f3045..de1d745875 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.h +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.h @@ -15,6 +15,8 @@ #include #include +#include "RenderableEntityItem.h" + const int FIXED_FONT_POINT_SIZE = 40; class RenderableTextEntityItem : public TextEntityItem { @@ -27,7 +29,8 @@ public: ~RenderableTextEntityItem() { delete _textRenderer; } virtual void render(RenderArgs* args); - virtual bool canRenderInScene() { return false; } // we don't yet play well with others + + SIMPLE_RENDERABLE(); private: TextRenderer3D* _textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE / 2.0f); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index 2ad4d799b6..05ad3a4088 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -13,6 +13,8 @@ #include +#include "RenderableEntityItem.h" + class OffscreenQmlSurface; class RenderableWebEntityItem : public WebEntityItem { @@ -24,7 +26,8 @@ public: virtual void render(RenderArgs* args); virtual void setSourceUrl(const QString& value); - virtual bool canRenderInScene() { return false; } // we don't yet play well with others + + SIMPLE_RENDERABLE(); private: OffscreenQmlSurface* _webSurface{ nullptr }; diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index e320925045..9c4f8ae0bb 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -102,7 +102,8 @@ void RenderableZoneEntityItem::render(RenderArgs* args) { updateGeometry(); if (_model && _model->isActive()) { - _model->renderInScene(getLocalRenderAlpha(), args); + // FIX ME: this is no longer available... we need to switch to payloads + //_model->renderInScene(getLocalRenderAlpha(), args); } break; } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 878d0bed7c..a189c944ae 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -157,8 +157,6 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData) { return 0; } - virtual bool canRenderInScene() { return false; } // does your entity property render using Render Items and Payloads - virtual bool readyToAddToScene(RenderArgs* renderArgs = nullptr) { return true; } // we assume you're ready to add virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { return false; } // by default entity items don't add to scene virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index b91dea6b05..405ea9459d 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -157,6 +157,7 @@ public: void _glDisableVertexAttribArray(GLint location); void _glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); + void _glLineWidth(GLfloat width); enum Command { COMMAND_draw = 0, @@ -216,6 +217,7 @@ public: COMMAND_glDisableVertexAttribArray, COMMAND_glColor4f, + COMMAND_glLineWidth, NUM_COMMANDS, }; diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index c26564a338..da6979fb27 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -66,8 +66,9 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_glEnableVertexAttribArray), (&::gpu::GLBackend::do_glDisableVertexAttribArray), - + (&::gpu::GLBackend::do_glColor4f), + (&::gpu::GLBackend::do_glLineWidth), }; GLBackend::GLBackend() : @@ -566,6 +567,18 @@ void GLBackend::do_glColor4f(Batch& batch, uint32 paramOffset) { (void) CHECK_GL_ERROR(); } +void Batch::_glLineWidth(GLfloat width) { + ADD_COMMAND_GL(glLineWidth); + + _params.push_back(width); + + DO_IT_NOW(_glLineWidth, 1); +} +void GLBackend::do_glLineWidth(Batch& batch, uint32 paramOffset) { + glLineWidth(batch._params[paramOffset]._float); + (void) CHECK_GL_ERROR(); +} + void GLBackend::loadMatrix(GLenum target, const glm::mat4 & m) { glMatrixMode(target); glLoadMatrixf(glm::value_ptr(m)); diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index d1ba7714e9..5e3177c6ea 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -370,8 +370,9 @@ protected: void do_glEnableVertexAttribArray(Batch& batch, uint32 paramOffset); void do_glDisableVertexAttribArray(Batch& batch, uint32 paramOffset); - + void do_glColor4f(Batch& batch, uint32 paramOffset); + void do_glLineWidth(Batch& batch, uint32 paramOffset); typedef void (GLBackend::*CommandCall)(Batch&, uint32); static CommandCall _commandCalls[Batch::NUM_COMMANDS]; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 782b9f0143..e7c3aa43e7 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -925,6 +925,7 @@ void Model::removeFromScene(std::shared_ptr scene, render::Pendin } bool Model::render(RenderArgs* renderArgs, float alpha) { + return true; // PROFILE_RANGE(__FUNCTION__); // render the attachments @@ -1994,15 +1995,6 @@ void Model::deleteGeometry() { _blendedBlendshapeCoefficients.clear(); } -// Scene rendering support -QVector Model::_modelsInScene; -gpu::Batch Model::_sceneRenderBatch; -void Model::startScene(RenderArgs::RenderSide renderSide) { - if (renderSide != RenderArgs::STEREO_RIGHT) { - _modelsInScene.clear(); - } -} - void Model::setupBatchTransform(gpu::Batch& batch, RenderArgs* args) { // Capture the view matrix once for the rendering of this model @@ -2019,231 +2011,6 @@ void Model::setupBatchTransform(gpu::Batch& batch, RenderArgs* args) { batch.setViewTransform(_transforms[0]); } -void Model::endScene(RenderArgs* args) { - // Now that we migrated everything to the new RENDER/SCENE no more work to do! - return; - PROFILE_RANGE(__FUNCTION__); - - - -#if (GPU_TRANSFORM_PROFILE == GPU_LEGACY) - // with legacy transform profile, we still to protect that transform stack... - glPushMatrix(); -#endif - - auto mode = args->_renderMode; - - RenderArgs::RenderSide renderSide = RenderArgs::MONO; - if (args) { - renderSide = args->_renderSide; - } - - - gpu::GLBackend backend; - backend.syncCache(); // force sync with gl state here - - if (args) { - glm::mat4 proj; - // If for easier debug depending on the pass - if (mode == RenderArgs::SHADOW_RENDER_MODE) { - args->_viewFrustum->evalProjectionMatrix(proj); - } else { - args->_viewFrustum->evalProjectionMatrix(proj); - } - gpu::Batch batch; - batch.setProjectionTransform(proj); - backend.render(batch); - } - - // Do the rendering batch creation for mono or left eye, not for right eye - if (renderSide != RenderArgs::STEREO_RIGHT) { - // Let's introduce a gpu::Batch to capture all the calls to the graphics api - _sceneRenderBatch.clear(); - gpu::Batch& batch = _sceneRenderBatch; - - /*DependencyManager::get()->setPrimaryDrawBuffers( - mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE, - mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE, - mode == RenderArgs::DEFAULT_RENDER_MODE); - */ - - /* if (mode != RenderArgs::SHADOW_RENDER_MODE) */{ - GLenum buffers[3]; - - int bufferCount = 0; - // if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE) { - if (mode != RenderArgs::SHADOW_RENDER_MODE) { - buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; - } - //if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE) { - if (mode != RenderArgs::SHADOW_RENDER_MODE) { - buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; - } - // if (mode == RenderArgs::DEFAULT_RENDER_MODE) { - if (mode != RenderArgs::SHADOW_RENDER_MODE) { - buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; - } - GLBATCH(glDrawBuffers)(bufferCount, buffers); - - // batch.setFramebuffer(DependencyManager::get()->getPrimaryOpaqueFramebuffer()); - } - - const float DEFAULT_ALPHA_THRESHOLD = 0.5f; - - int opaqueMeshPartsRendered = 0; - - // now, for each model in the scene, render the mesh portions - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, false, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, true, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, false, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, true, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, false, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, true, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, false, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, true, false, args); - - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, false, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, false, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, false, args); - - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, false, true, args); - - // render translucent meshes afterwards - { - GLenum buffers[2]; - int bufferCount = 0; - buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; - buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; - GLBATCH(glDrawBuffers)(bufferCount, buffers); - } - - int translucentParts = 0; - const float MOSTLY_OPAQUE_THRESHOLD = 0.75f; - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, true, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, true, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, true, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, false, args); - - - { - GLenum buffers[1]; - int bufferCount = 0; - buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; - GLBATCH(glDrawBuffers)(bufferCount, buffers); - // batch.setFramebuffer(DependencyManager::get()->getPrimaryTransparentFramebuffer()); - } - - // if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE) { - if (mode != RenderArgs::SHADOW_RENDER_MODE) { - // batch.setFramebuffer(DependencyManager::get()->getPrimaryTransparentFramebuffer()); - - const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, true, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, false, args); - - // batch.setFramebuffer(DependencyManager::get()->getPrimaryOpaqueFramebuffer()); - } - - GLBATCH(glDepthMask)(true); - GLBATCH(glDepthFunc)(GL_LESS); - GLBATCH(glDisable)(GL_CULL_FACE); - - if (mode == RenderArgs::SHADOW_RENDER_MODE) { - GLBATCH(glCullFace)(GL_BACK); - } - - - GLBATCH(glActiveTexture)(GL_TEXTURE0 + 1); - GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); - GLBATCH(glActiveTexture)(GL_TEXTURE0 + 2); - GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); - GLBATCH(glActiveTexture)(GL_TEXTURE0 + 3); - GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); - GLBATCH(glActiveTexture)(GL_TEXTURE0); - GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); - - - // deactivate vertex arrays after drawing - GLBATCH(glDisableClientState)(GL_NORMAL_ARRAY); - GLBATCH(glDisableClientState)(GL_VERTEX_ARRAY); - GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY); - GLBATCH(glDisableClientState)(GL_COLOR_ARRAY); - 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); - GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, 0); - GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); - - // Back to no program - GLBATCH(glUseProgram)(0); - - if (args) { - args->_translucentMeshPartsRendered = translucentParts; - args->_opaqueMeshPartsRendered = opaqueMeshPartsRendered; - } - - } - - // Render! - { - PROFILE_RANGE("render Batch"); - backend.render(_sceneRenderBatch); - } - - -#if (GPU_TRANSFORM_PROFILE == GPU_LEGACY) - // with legacy transform profile, we still to protect that transform stack... - glPopMatrix(); -#endif - - // restore all the default material settings - _viewState->setupWorldLight(); - -} - -bool Model::renderInScene(float alpha, RenderArgs* args) { - // render the attachments - foreach (Model* attachment, _attachments) { - attachment->renderInScene(alpha); - } - if (_meshStates.isEmpty()) { - return false; - } - - if (args->_debugFlags == RenderArgs::RENDER_DEBUG_HULLS && _renderCollisionHull == false) { - // turning collision hull rendering on - _renderCollisionHull = true; - _nextGeometry = _collisionGeometry; - _saveNonCollisionGeometry = _geometry; - updateGeometry(); - simulate(0.0, true); - } else if (args->_debugFlags != RenderArgs::RENDER_DEBUG_HULLS && _renderCollisionHull == true) { - // turning collision hull rendering off - _renderCollisionHull = false; - _nextGeometry = _saveNonCollisionGeometry; - _saveNonCollisionGeometry.clear(); - updateGeometry(); - simulate(0.0, true); - } - - renderSetup(args); - _modelsInScene.push_back(this); - return true; -} AABox Model::getPartBounds(int meshIndex, int partIndex) { if (!_calculatedMeshPartBoxesValid) { @@ -2320,19 +2087,14 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran if (isSkinned) { GLBATCH(glUniformMatrix4fv)(locations->clusterMatrices, state.clusterMatrices.size(), false, (const float*)state.clusterMatrices.constData()); - - _transforms[0].setIdentity(); - _transforms[0].setTranslation(_translation); - batch.setModelTransform(_transforms[0]); + _transforms[0] = Transform(); + _transforms[0].preTranslate(_translation); } else { _transforms[0] = Transform(state.clusterMatrices[0]); _transforms[0].preTranslate(_translation); - - //batch.setModelTransform(Transform(state.clusterMatrices[0])); - batch.setModelTransform(_transforms[0]); } - - // Input stage + batch.setModelTransform(_transforms[0]); + if (mesh.blendshapes.isEmpty()) { batch.setInputFormat(networkMesh._vertexFormat); batch.setInputStream(0, *networkMesh._vertexStream); @@ -2347,8 +2109,6 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran GLBATCH(glColor4f)(1.0f, 1.0f, 1.0f, 1.0f); } - qint64 offset = 0; - // guard against partially loaded meshes if (partIndex >= networkMesh.parts.size() || partIndex >= mesh.parts.size()) { return; @@ -2439,6 +2199,20 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran meshPartsRendered++; + // FIX ME This is very unefficient + qint64 offset = 0; + for (int j = 0; j < partIndex; j++) { + const NetworkMeshPart& networkPart = networkMesh.parts.at(j); + const FBXMeshPart& part = mesh.parts.at(j); + if ((networkPart.isTranslucent() || part.opacity != 1.0f) != translucent) { + offset += (part.quadIndices.size() + part.triangleIndices.size()) * sizeof(int); + continue; + } + + offset += part.quadIndices.size() * sizeof(int); + offset += part.triangleIndices.size() * sizeof(int); + } + if (part.quadIndices.size() > 0) { batch.drawIndexed(gpu::QUADS, part.quadIndices.size(), offset); offset += part.quadIndices.size() * sizeof(int); @@ -2577,34 +2351,6 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f } } -int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args) { - - PROFILE_RANGE(__FUNCTION__); - int meshPartsRendered = 0; - - bool pickProgramsNeeded = true; - Locations* locations = nullptr; - - foreach(Model* model, _modelsInScene) { - QVector* whichList = model->pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, isWireframe); - if (whichList) { - QVector& list = *whichList; - if (list.size() > 0) { - if (pickProgramsNeeded) { - pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, isWireframe, args, locations); - pickProgramsNeeded = false; - } - - model->setupBatchTransform(batch, args); - meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, locations); - } - } - } - - return meshPartsRendered; -} - int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args, bool forceRenderSomeMeshes) { diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 08385ffb61..3795dc8731 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -114,14 +114,8 @@ public: void reset(); virtual void simulate(float deltaTime, bool fullUpdate = true); - bool render(RenderArgs* renderArgs, float alpha = 1.0f); void renderSetup(RenderArgs* args); - // Scene rendering support - static void startScene(RenderArgs::RenderSide renderSide); - bool renderInScene(float alpha = 1.0f, RenderArgs* args = NULL); - static void endScene(RenderArgs* args); - // new Scene/Engine rendering support bool needsFixupInScene() { return !_readyWhenAdded && readyToAddToScene(); } bool readyToAddToScene(RenderArgs* renderArgs = nullptr) { return isRenderable() && isActive() && isLoadedWithTextures(); } @@ -393,13 +387,6 @@ private: void renderDebugMeshBoxes(); int _debugMeshBoxesID = GeometryCache::UNKNOWN_ID; - // Scene rendering support - static QVector _modelsInScene; - static gpu::Batch _sceneRenderBatch; - - static void endSceneSimple(RenderArgs::RenderMode mode = RenderArgs::DEFAULT_RENDER_MODE, RenderArgs* args = NULL); - static void endSceneSplitPass(RenderArgs::RenderMode mode = RenderArgs::DEFAULT_RENDER_MODE, RenderArgs* args = NULL); - // helper functions used by render() or renderInScene() bool renderCore(RenderArgs* args, float alpha); int renderMeshes(gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, float alphaThreshold, @@ -417,10 +404,6 @@ private: bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args, Locations*& locations); - static int renderMeshesForModelsInScene(gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, float alphaThreshold, - bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args); - - static AbstractViewStateInterface* _viewState; class RenderKey { @@ -547,6 +530,14 @@ private: QSet> _opaqueRenderItems; QSet _renderItems; bool _readyWhenAdded = false; + + +private: + // FIX ME - We want to get rid of this interface for rendering... + // right now the only remaining user are Avatar attachments. + // that usage has been temporarily disabled... + bool render(RenderArgs* renderArgs, float alpha = 1.0f); + }; Q_DECLARE_METATYPE(QPointer) diff --git a/libraries/render-utils/src/OffscreenGlCanvas.cpp b/libraries/render-utils/src/OffscreenGlCanvas.cpp index a3025bc3f6..e41209a40c 100644 --- a/libraries/render-utils/src/OffscreenGlCanvas.cpp +++ b/libraries/render-utils/src/OffscreenGlCanvas.cpp @@ -16,6 +16,17 @@ OffscreenGlCanvas::OffscreenGlCanvas() { } +OffscreenGlCanvas::~OffscreenGlCanvas() { +#ifdef DEBUG + if (_logger) { + makeCurrent(); + delete _logger; + _logger = nullptr; + } +#endif + _context.doneCurrent(); +} + void OffscreenGlCanvas::create(QOpenGLContext* sharedContext) { if (nullptr != sharedContext) { sharedContext->doneCurrent(); diff --git a/libraries/render-utils/src/OffscreenGlCanvas.h b/libraries/render-utils/src/OffscreenGlCanvas.h index 399737ddb8..7a69e276e4 100644 --- a/libraries/render-utils/src/OffscreenGlCanvas.h +++ b/libraries/render-utils/src/OffscreenGlCanvas.h @@ -20,6 +20,7 @@ class QOpenGLDebugLogger; class OffscreenGlCanvas : public QObject { public: OffscreenGlCanvas(); + ~OffscreenGlCanvas(); void create(QOpenGLContext* sharedContext = nullptr); bool makeCurrent(); void doneCurrent();