Merging the day after the flight back to france, getting all the fixes

This commit is contained in:
Sam Gateau 2015-06-04 23:02:05 -07:00
commit 3a93409080
38 changed files with 354 additions and 586 deletions

View file

@ -1714,12 +1714,9 @@ bool Application::acceptSnapshot(const QString& urlString) {
SnapshotMetaData* snapshotData = Snapshot::parseSnapshotData(snapshotPath);
if (snapshotData) {
if (!snapshotData->getDomain().isEmpty()) {
DependencyManager::get<NodeList>()->getDomainHandler().setHostnameAndPort(snapshotData->getDomain());
if (!snapshotData->getURL().toString().isEmpty()) {
DependencyManager::get<AddressManager>()->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<DeferredLightingEffect>()->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<GeometryCache>()->renderSphere((*args->_batch), originSphereRadius, 15, 15, glm::vec4(1.0f, 0.0f, 0.0f, 1.0f));
auto& batch = *args->_batch;
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch);
renderWorldBox(batch);
}
}
}

View file

@ -17,6 +17,9 @@
#include <QShowEvent>
#include <QHideEvent>
#include <QWindowStateChangeEvent>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QMimeData>
#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<QWindowStateChangeEvent*>(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);
}

View file

@ -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<QRect> _windowGeometry;

View file

@ -33,42 +33,44 @@
using namespace std;
void renderWorldBox(RenderArgs* renderArgs) {
void renderWorldBox(gpu::Batch& batch) {
auto geometryCache = DependencyManager::get<GeometryCache>();
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

View file

@ -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,

View file

@ -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() {

View file

@ -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

View file

@ -15,8 +15,10 @@
#include <QFileInfo>
#include <QImage>
#include <QTemporaryFile>
#include <QUrl>
#include <AccountManager.h>
#include <AddressManager.h>
#include <avatar/AvatarManager.h>
#include <avatar/MyAvatar.h>
#include <FileUtils.h>
@ -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<QString> 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<QTemporaryFile*>(savedFileForSnapshot(image, true));;
return static_cast<QTemporaryFile*>(savedFileForSnapshot(image, true));
}
QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary) {
Avatar* avatar = DependencyManager::get<AvatarManager>()->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<NodeList>()->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<AddressManager>()->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;
}
}

View file

@ -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<QString> snapshotsLocation;
private:
static QFile* savedFileForSnapshot(QImage & image, bool isTemporary);

View file

@ -9,6 +9,7 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <Application.h>
#include <GlowEffect.h>
#include "ModelOverlay.h"
@ -54,11 +55,34 @@ void ModelOverlay::update(float deltatime) {
_isLoaded = _model.isActive();
}
bool ModelOverlay::addToScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
Base3DOverlay::addToScene(overlay, scene, pendingChanges);
_model.addToScene(scene, pendingChanges);
return true;
}
void ModelOverlay::removeFromScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> 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) {

View file

@ -32,6 +32,9 @@ public:
virtual ModelOverlay* createClone() const;
virtual bool addToScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
virtual void removeFromScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
private:
Model _model;

View file

@ -228,3 +228,15 @@ float Overlay::updatePulse() {
return _pulse;
}
bool Overlay::addToScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> 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<render::Scene> scene, render::PendingChanges& pendingChanges) {
pendingChanges.removeItem(_renderItemID);
}

View file

@ -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<render::Scene> scene, render::PendingChanges& pendingChanges);
virtual void removeFromScene(Overlay::Pointer overlay, std::shared_ptr<render::Scene> 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

View file

@ -33,49 +33,6 @@
#include "Text3DOverlay.h"
namespace render {
template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay) {
if (overlay->is3D() && !static_cast<Base3DOverlay*>(overlay.get())->getDrawOnHUD()) {
if (static_cast<Base3DOverlay*>(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<Base3DOverlay*>(overlay.get())->getBounds();
} else {
QRect bounds = static_cast<Overlay2D*>(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<AvatarManager>()->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);
}

View file

@ -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 <QScriptValueIterator>
#include <limits>
#include <typeinfo>
#include <Application.h>
#include <avatar/AvatarManager.h>
#include <LODManager.h>
#include <render/Scene.h>
#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<Base3DOverlay*>(overlay.get())->getDrawOnHUD()) {
if (static_cast<Base3DOverlay*>(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<Base3DOverlay*>(overlay.get())->getBounds();
} else {
QRect bounds = static_cast<Overlay2D*>(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<AvatarManager>()->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();
}
}
}

View file

@ -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<float>::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<EntityItemPointer> 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) {

View file

@ -123,9 +123,7 @@ protected:
virtual Octree* createTree() { return new EntityTree(true); }
private:
void checkPendingAddToScene(RenderArgs* renderArgs);
void addEntityToScene(EntityItemPointer entity);
QSet<EntityItemPointer> _pendingAddToScene;
void applyZonePropertiesToScene(std::shared_ptr<ZoneEntityItem> zone);
void renderElementProxy(EntityTreeElement* entityTreeElement, RenderArgs* args);

View file

@ -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);
}
}
}

View file

@ -56,7 +56,6 @@ private:
#define SIMPLE_RENDERABLE() \
public: \
virtual bool canRenderInScene() { return true; } \
virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) { return _renderHelper.addToScene(self, scene, pendingChanges); } \
virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) { _renderHelper.removeFromScene(self, scene, pendingChanges); } \
private: \

View file

@ -13,6 +13,7 @@
#define hifi_RenderableLightEntityItem_h
#include <LightEntityItem.h>
#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();
};

View file

@ -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<GeometryCache>();
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<GeometryCache>()->renderVertices(batch, gpu::LINE_STRIP, _lineVerticesID);
batch._glLineWidth(1.0f);
RenderableDebugableEntityItem::render(this, args);
};

View file

@ -28,9 +28,11 @@ public:
virtual void render(RenderArgs* args);
SIMPLE_RENDERABLE()
SIMPLE_RENDERABLE();
protected:
void updateGeometry();
int _lineVerticesID;
};

View file

@ -15,6 +15,7 @@
#include <QJsonDocument>
#include <AbstractViewStateInterface.h>
#include <DeferredLightingEffect.h>
#include <Model.h>
#include <PerfStat.h>
@ -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();

View file

@ -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<render::Scene> scene, render::PendingChanges& pendingChanges);
virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);

View file

@ -23,7 +23,7 @@ public:
void updateQuads(RenderArgs* args, bool textured);
SIMPLE_RENDERABLE()
SIMPLE_RENDERABLE();
protected:

View file

@ -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

View file

@ -26,7 +26,7 @@ public:
virtual void render(RenderArgs* args);
SIMPLE_RENDERABLE()
SIMPLE_RENDERABLE();
};

View file

@ -15,6 +15,8 @@
#include <TextEntityItem.h>
#include <TextRenderer3D.h>
#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);

View file

@ -13,6 +13,8 @@
#include <WebEntityItem.h>
#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 };

View file

@ -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;
}

View file

@ -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<render::Scene> scene,
render::PendingChanges& pendingChanges) { return false; } // by default entity items don't add to scene
virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,

View file

@ -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,
};

View file

@ -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));

View file

@ -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];

View file

@ -925,6 +925,7 @@ void Model::removeFromScene(std::shared_ptr<render::Scene> 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*> 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<TextureCache>()->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<TextureCache>()->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<TextureCache>()->getPrimaryTransparentFramebuffer());
}
// if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE) {
if (mode != RenderArgs::SHADOW_RENDER_MODE) {
// batch.setFramebuffer(DependencyManager::get<TextureCache>()->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<TextureCache>()->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<int>* whichList = model->pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, isWireframe);
if (whichList) {
QVector<int>& 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) {

View file

@ -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<Model*> _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<std::shared_ptr<OpaqueMeshPart>> _opaqueRenderItems;
QSet<render::ItemID> _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<Model>)

View file

@ -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();

View file

@ -20,6 +20,7 @@ class QOpenGLDebugLogger;
class OffscreenGlCanvas : public QObject {
public:
OffscreenGlCanvas();
~OffscreenGlCanvas();
void create(QOpenGLContext* sharedContext = nullptr);
bool makeCurrent();
void doneCurrent();