From f51feca37d54ddbd0202738090925da412ee0457 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 8 Jun 2015 11:29:35 -0700 Subject: [PATCH 01/11] Add directory button --- examples/defaultScripts.js | 1 + examples/directory.js | 86 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 examples/directory.js diff --git a/examples/defaultScripts.js b/examples/defaultScripts.js index 8f32b80bba..61bed8d9b1 100644 --- a/examples/defaultScripts.js +++ b/examples/defaultScripts.js @@ -18,3 +18,4 @@ Script.load("notifications.js"); Script.load("users.js"); Script.load("grab.js"); Script.load("pointer.js"); +Script.load("directory.js"); diff --git a/examples/directory.js b/examples/directory.js new file mode 100644 index 0000000000..965abf1453 --- /dev/null +++ b/examples/directory.js @@ -0,0 +1,86 @@ +// +// directory.js +// examples +// +// Created by David Rowe on 8 Jun 2015 +// Copyright 2015 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 +// + +Script.include("libraries/globals.js"); + +var directory = (function () { + + var DIRECTORY_URL = "https://metaverse.highfidelity.com/directory", + directoryWindow, + DIRECTORY_BUTTON_URL = HIFI_PUBLIC_BUCKET + "images/tools/directory.svg", + BUTTON_WIDTH = 50, + BUTTON_HEIGHT = 50, + BUTTON_ALPHA = 0.9, + BUTTON_MARGIN = 8, + directoryButton, + viewport; + + function updateButtonPosition() { + Overlays.editOverlay(directoryButton, { + x: viewport.x - BUTTON_WIDTH - BUTTON_MARGIN, + y: BUTTON_MARGIN + }); + } + + function onMousePressEvent(event) { + var clickedOverlay; + + clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); + + if (clickedOverlay === directoryButton) { + if (directoryWindow.url !== DIRECTORY_URL) { + directoryWindow.setURL(DIRECTORY_URL); + } + directoryWindow.setVisible(true); + directoryWindow.raise(); + } + } + + function onScriptUpdate() { + var oldViewport = viewport; + + viewport = Controller.getViewportDimensions(); + + if (viewport.x !== oldViewport.x || viewport.y !== oldViewport.y) { + updateButtonPosition(); + } + } + + function setUp() { + viewport = Controller.getViewportDimensions(); + + directoryWindow = new WebWindow('Directory', DIRECTORY_URL, 900, 700, false); + directoryWindow.setVisible(false); + + directoryButton = Overlays.addOverlay("image", { + imageURL: DIRECTORY_BUTTON_URL, + width: BUTTON_WIDTH, + height: BUTTON_HEIGHT, + x: viewport.x - BUTTON_WIDTH - BUTTON_MARGIN, + y: BUTTON_MARGIN, + alpha: BUTTON_ALPHA, + visible: true + }); + + updateButtonPosition(); + + Controller.mousePressEvent.connect(onMousePressEvent); + + Script.update.connect(onScriptUpdate); + } + + function tearDown() { + Overlays.deleteOverlay(directoryButton); + } + + setUp(); + Script.scriptEnding.connect(tearDown); +}()); \ No newline at end of file From 9e3ce344fbdd9b5419d14404bb3945c379aba40d Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 9 Jun 2015 07:26:18 -0700 Subject: [PATCH 02/11] Display directory button just above edit toobar --- examples/directory.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/directory.js b/examples/directory.js index 965abf1453..03d352e024 100644 --- a/examples/directory.js +++ b/examples/directory.js @@ -21,12 +21,13 @@ var directory = (function () { BUTTON_ALPHA = 0.9, BUTTON_MARGIN = 8, directoryButton, + EDIT_TOOLBAR_BUTTONS = 10, // Number of buttons in edit.js toolbar viewport; function updateButtonPosition() { Overlays.editOverlay(directoryButton, { x: viewport.x - BUTTON_WIDTH - BUTTON_MARGIN, - y: BUTTON_MARGIN + y: (viewport.y - (EDIT_TOOLBAR_BUTTONS + 1) * (BUTTON_HEIGHT + BUTTON_MARGIN) - BUTTON_MARGIN) / 2 - 1 }); } From ba0cecb3561c6b47be665354d082a6918b3df034 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 9 Jun 2015 12:32:37 -0700 Subject: [PATCH 03/11] remove attachments from Model - only supported at avatar layer --- libraries/fbx/src/FBXReader.cpp | 28 ------------- libraries/fbx/src/FBXReader.h | 15 +------ libraries/fbx/src/FSTReader.cpp | 4 +- libraries/fbx/src/OBJReader.cpp | 1 - libraries/render-utils/src/Model.cpp | 60 ---------------------------- libraries/render-utils/src/Model.h | 2 - 6 files changed, 4 insertions(+), 106 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 464deb1059..76108730e8 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -2646,34 +2646,6 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping, } } geometry.palmDirection = parseVec3(mapping.value("palmDirection", "0, -1, 0").toString()); - - // process attachments - QVariantHash attachments = mapping.value("attach").toHash(); - for (QVariantHash::const_iterator it = attachments.constBegin(); it != attachments.constEnd(); it++) { - FBXAttachment attachment; - attachment.jointIndex = modelIDs.indexOf(processID(it.key())); - attachment.scale = glm::vec3(1.0f, 1.0f, 1.0f); - - QVariantList properties = it->toList(); - if (properties.isEmpty()) { - attachment.url = it->toString(); - } else { - attachment.url = properties.at(0).toString(); - - if (properties.size() >= 2) { - attachment.translation = parseVec3(properties.at(1).toString()); - - if (properties.size() >= 3) { - attachment.rotation = glm::quat(glm::radians(parseVec3(properties.at(2).toString()))); - - if (properties.size() >= 4) { - attachment.scale = parseVec3(properties.at(3).toString()); - } - } - } - } - geometry.attachments.append(attachment); - } // Add sitting points QVariantHash sittingPoints = mapping.value("sit").toHash(); diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 08ac0e308c..200cd4a121 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -189,17 +189,6 @@ public: Q_DECLARE_METATYPE(FBXAnimationFrame) Q_DECLARE_METATYPE(QVector) -/// An attachment to an FBX document. -class FBXAttachment { -public: - - int jointIndex; - QUrl url; - glm::vec3 translation; - glm::quat rotation; - glm::vec3 scale; -}; - /// A point where an avatar can sit class SittingPoint { public: @@ -256,9 +245,7 @@ public: Extents meshExtents; QVector animationFrames; - - QVector attachments; - + int getJointIndex(const QString& name) const { return jointIndices.value(name) - 1; } QStringList getJointNames() const; diff --git a/libraries/fbx/src/FSTReader.cpp b/libraries/fbx/src/FSTReader.cpp index 32be82b392..a62c0fcea2 100644 --- a/libraries/fbx/src/FSTReader.cpp +++ b/libraries/fbx/src/FSTReader.cpp @@ -124,7 +124,9 @@ FSTReader::ModelType FSTReader::getTypeFromName(const QString& name) { _namesToTypes["head"] = HEAD_MODEL ; _namesToTypes["body"] = BODY_ONLY_MODEL; _namesToTypes["body+head"] = HEAD_AND_BODY_MODEL; - _namesToTypes["attachment"] = ATTACHMENT_MODEL; + + // NOTE: this is not yet implemented, but will be used to allow you to attach fully independent models to your avatar + _namesToTypes["attachment"] = ATTACHMENT_MODEL; } return _namesToTypes[name]; } diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index 4a8a2fc53d..f0d3ecf517 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -544,7 +544,6 @@ void fbxDebugDump(const FBXGeometry& fbxgeo) { qCDebug(modelformat) << "---------------- fbxGeometry ----------------"; qCDebug(modelformat) << " hasSkeletonJoints =" << fbxgeo.hasSkeletonJoints; qCDebug(modelformat) << " offset =" << fbxgeo.offset; - qCDebug(modelformat) << " attachments.count() = " << fbxgeo.attachments.count(); qCDebug(modelformat) << " meshes.count() =" << fbxgeo.meshes.count(); foreach (FBXMesh mesh, fbxgeo.meshes) { qCDebug(modelformat) << " vertices.count() =" << mesh.vertices.count(); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index c578015b9f..824f100d46 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -405,9 +405,6 @@ void Model::reset() { if (_jointStates.isEmpty()) { return; } - foreach (Model* attachment, _attachments) { - attachment->reset(); - } const FBXGeometry& geometry = _geometry->getFBXGeometry(); for (int i = 0; i < _jointStates.size(); i++) { _jointStates[i].setRotationInConstrainedFrame(geometry.joints.at(i).rotation, 0.0f); @@ -419,14 +416,7 @@ void Model::reset() { } bool Model::updateGeometry() { - // NOTE: this is a recursive call that walks all attachments, and their attachments bool needFullUpdate = false; - for (int i = 0; i < _attachments.size(); i++) { - Model* model = _attachments.at(i); - if (model->updateGeometry()) { - needFullUpdate = true; - } - } bool needToRebuild = false; if (_nextGeometry) { @@ -499,12 +489,6 @@ bool Model::updateGeometry() { } _blendedVertexBuffers.push_back(buffer); } - foreach (const FBXAttachment& attachment, fbxGeometry.attachments) { - Model* model = new Model(this); - model->init(); - model->setURL(attachment.url); - _attachments.append(model); - } needFullUpdate = true; } return needFullUpdate; @@ -913,12 +897,6 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan bool somethingAdded = false; - // allow the attachments to add to scene - foreach (Model* attachment, _attachments) { - bool attachementSomethingAdded = attachment->addToScene(scene, pendingChanges); - somethingAdded = somethingAdded || attachementSomethingAdded; - } - foreach (auto renderItem, _transparentRenderItems) { auto item = scene->allocateID(); auto renderData = TransparentMeshPart::Pointer(renderItem); @@ -942,11 +920,6 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan } void Model::removeFromScene(std::shared_ptr scene, render::PendingChanges& pendingChanges) { - // allow the attachments to remove to scene - foreach (Model* attachment, _attachments) { - attachment->removeFromScene(scene, pendingChanges); - } - foreach (auto item, _renderItems.keys()) { pendingChanges.removeItem(item); } @@ -958,10 +931,6 @@ bool Model::render(RenderArgs* renderArgs, float alpha) { return true; // PROFILE_RANGE(__FUNCTION__); - // render the attachments - foreach (Model* attachment, _attachments) { - attachment->render(renderArgs, alpha); - } if (_meshStates.isEmpty()) { return false; } @@ -1623,7 +1592,6 @@ void Model::simulate(float deltaTime, bool fullUpdate) { } void Model::simulateInternal(float deltaTime) { - // NOTE: this is a recursive call that walks all attachments, and their attachments // update the world space transforms for all joints // update animations @@ -1640,31 +1608,7 @@ void Model::simulateInternal(float deltaTime) { _shapesAreDirty = !_shapes.isEmpty(); - // update the attachment transforms and simulate them const FBXGeometry& geometry = _geometry->getFBXGeometry(); - for (int i = 0; i < _attachments.size(); i++) { - const FBXAttachment& attachment = geometry.attachments.at(i); - Model* model = _attachments.at(i); - - glm::vec3 jointTranslation = _translation; - glm::quat jointRotation = _rotation; - if (_showTrueJointTransforms) { - getJointPositionInWorldFrame(attachment.jointIndex, jointTranslation); - getJointRotationInWorldFrame(attachment.jointIndex, jointRotation); - } else { - getVisibleJointPositionInWorldFrame(attachment.jointIndex, jointTranslation); - getVisibleJointRotationInWorldFrame(attachment.jointIndex, jointRotation); - } - - model->setTranslation(jointTranslation + jointRotation * attachment.translation * _scale); - model->setRotation(jointRotation * attachment.rotation); - model->setScale(_scale * attachment.scale); - - if (model->isActive()) { - model->simulateInternal(deltaTime); - } - } - glm::mat4 modelToWorld = glm::mat4_cast(_rotation); for (int i = 0; i < _meshStates.size(); i++) { MeshState& state = _meshStates[i]; @@ -2002,10 +1946,6 @@ void Model::applyNextGeometry() { } void Model::deleteGeometry() { - foreach (Model* attachment, _attachments) { - delete attachment; - } - _attachments.clear(); _blendedVertexBuffers.clear(); _jointStates.clear(); _meshStates.clear(); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 6f751a5f8d..043b7e659b 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -350,8 +350,6 @@ private: QVector > > _dilatedTextures; - QVector _attachments; - QSet _animationHandles; QList _runningAnimations; From 01b1e9c4ed29d1c92aebb8330ade9592984814d1 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 9 Jun 2015 12:33:14 -0700 Subject: [PATCH 04/11] Signal domain changes for those handled by ICE as well as not --- interface/src/scripting/WindowScriptingInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 3aae6a4d4a..6be67a7261 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -31,7 +31,7 @@ WindowScriptingInterface::WindowScriptingInterface() : _formResult(QDialog::Rejected) { const DomainHandler& domainHandler = DependencyManager::get()->getDomainHandler(); - connect(&domainHandler, &DomainHandler::hostnameChanged, this, &WindowScriptingInterface::domainChanged); + connect(&domainHandler, &DomainHandler::connectedToDomain, this, &WindowScriptingInterface::domainChanged); connect(Application::getInstance(), &Application::svoImportRequested, this, &WindowScriptingInterface::svoImportRequested); connect(Application::getInstance(), &Application::domainConnectionRefused, this, &WindowScriptingInterface::domainConnectionRefused); } From a4885ff38ce896f2d71ee57b33009856c5045f02 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 9 Jun 2015 12:33:30 -0700 Subject: [PATCH 05/11] Close directory window after domain change --- examples/directory.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/directory.js b/examples/directory.js index 03d352e024..b1fac19e8b 100644 --- a/examples/directory.js +++ b/examples/directory.js @@ -45,6 +45,10 @@ var directory = (function () { } } + function onDomainChanged() { + directoryWindow.setVisible(false); + } + function onScriptUpdate() { var oldViewport = viewport; @@ -74,6 +78,7 @@ var directory = (function () { updateButtonPosition(); Controller.mousePressEvent.connect(onMousePressEvent); + Window.domainChanged.connect(onDomainChanged); Script.update.connect(onScriptUpdate); } From e0adb8e38ac1d899509f39f21721f650281e21f4 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 9 Jun 2015 12:57:04 -0700 Subject: [PATCH 06/11] render avatar attachments as model payload items --- interface/src/avatar/Avatar.cpp | 31 ++++++++++++++------------- interface/src/avatar/Avatar.h | 1 - interface/src/avatar/MyAvatar.cpp | 35 ++++++------------------------- interface/src/avatar/MyAvatar.h | 3 --- 4 files changed, 23 insertions(+), 47 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 8708a2b2b0..022c0262e0 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -298,12 +298,22 @@ bool Avatar::addToScene(AvatarSharedPointer self, std::shared_ptr pendingChanges.resetItem(_renderItemID, avatarPayloadPointer); _skeletonModel.addToScene(scene, pendingChanges); getHead()->getFaceModel().addToScene(scene, pendingChanges); + + for (auto attachmentModel : _attachmentModels) { + attachmentModel->addToScene(scene, pendingChanges); + } + return true; } void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { pendingChanges.removeItem(_renderItemID); _skeletonModel.removeFromScene(scene, pendingChanges); + getHead()->getFaceModel().removeFromScene(scene, pendingChanges); + for (auto attachmentModel : _attachmentModels) { + attachmentModel->removeFromScene(scene, pendingChanges); + } + } void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, bool postLighting) { @@ -529,6 +539,12 @@ void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool getHead()->getFaceModel().removeFromScene(scene, pendingChanges); getHead()->getFaceModel().addToScene(scene, pendingChanges); } + for (auto attachmentModel : _attachmentModels) { + if (attachmentModel->needsFixupInScene()) { + attachmentModel->removeFromScene(scene, pendingChanges); + attachmentModel->addToScene(scene, pendingChanges); + } + } scene->enqueuePendingChanges(pendingChanges); { @@ -544,10 +560,6 @@ void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool if (postLighting) { getHand()->render(renderArgs, false); - } else { - // NOTE: we no longer call this here, because we've added all the model parts as renderable items in the scene - //_skeletonModel.render(renderArgs, 1.0f); - renderAttachments(renderArgs); } } getHead()->render(renderArgs, 1.0f, renderFrustum, postLighting); @@ -577,16 +589,6 @@ 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() { // no-op; joint mappings come from skeleton model } @@ -949,6 +951,7 @@ void Avatar::setAttachmentData(const QVector& attachmentData) { _attachmentModels.append(model); } while (_attachmentModels.size() > attachmentData.size()) { + // NOTE: what's really going to happen here? This seems dangerous... has the model been removed from the scene? delete _attachmentModels.takeLast(); } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index dbc59f7d9c..1113496080 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -236,7 +236,6 @@ protected: virtual bool shouldRenderHead(const RenderArgs* renderArgs, const glm::vec3& cameraPosition) const; void simulateAttachments(float deltaTime); - virtual void renderAttachments(RenderArgs* args); virtual void updateJointMappings(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 8a49d69129..afe0311a29 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1188,6 +1188,12 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bo getHead()->getFaceModel().removeFromScene(scene, pendingChanges); getHead()->getFaceModel().addToScene(scene, pendingChanges); } + for (auto attachmentModel : _attachmentModels) { + if (attachmentModel->needsFixupInScene()) { + attachmentModel->removeFromScene(scene, pendingChanges); + attachmentModel->addToScene(scene, pendingChanges); + } + } scene->enqueuePendingChanges(pendingChanges); Camera *camera = Application::getInstance()->getCamera(); @@ -1208,14 +1214,6 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bo } }*/ - // Render the body's voxels and head - if (!postLighting) { - - // NOTE: we no longer call this here, because we've added all the model parts as renderable items in the scene - //_skeletonModel.render(renderArgs, 1.0f); - renderAttachments(renderArgs); - } - // Render head so long as the camera isn't inside it if (shouldRenderHead(renderArgs, cameraPos)) { getHead()->render(renderArgs, 1.0f, renderFrustum, postLighting); @@ -1571,27 +1569,6 @@ void MyAvatar::updateMotionBehavior() { _feetTouchFloor = menu->isOptionChecked(MenuOption::ShiftHipsForIdleAnimations); } -void MyAvatar::renderAttachments(RenderArgs* args) { - if (Application::getInstance()->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON || args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { - Avatar::renderAttachments(args); - return; - } - const FBXGeometry& geometry = _skeletonModel.getGeometry()->getFBXGeometry(); - 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 void MyAvatar::renderLaserPointers() { const float PALM_TIP_ROD_RADIUS = 0.002f; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index c8d16e8cb0..a3dc34e6e0 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -197,9 +197,6 @@ public slots: signals: void transformChanged(); -protected: - virtual void renderAttachments(RenderArgs* args); - private: // These are made private for MyAvatar so that you will use the "use" methods instead From 2c6ebcb06a90b8f4e9d82a9ad94c2c60ec7785f7 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 9 Jun 2015 12:57:14 -0700 Subject: [PATCH 07/11] remove a bunch of cruft from Model --- libraries/render-utils/src/Model.cpp | 422 --------------------------- libraries/render-utils/src/Model.h | 19 +- 2 files changed, 1 insertion(+), 440 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 824f100d46..3026efceb2 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -927,206 +927,6 @@ void Model::removeFromScene(std::shared_ptr scene, render::Pendin _readyWhenAdded = false; } -bool Model::render(RenderArgs* renderArgs, float alpha) { - return true; // - PROFILE_RANGE(__FUNCTION__); - - if (_meshStates.isEmpty()) { - return false; - } - - renderSetup(renderArgs); - return renderCore(renderArgs, alpha); -} - -bool Model::renderCore(RenderArgs* args, float alpha) { - return true; - - PROFILE_RANGE(__FUNCTION__); - if (!_viewState) { - return false; - } - - auto mode = args->_renderMode; - - // Let's introduce a gpu::Batch to capture all the calls to the graphics api - _renderBatch.clear(); - gpu::Batch& batch = _renderBatch; - - // Setup the projection matrix - if (args && args->_viewFrustum) { - 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); - } - batch.setProjectionTransform(proj); - } - - // Capture the view matrix once for the rendering of this model - if (_transforms.empty()) { - _transforms.push_back(Transform()); - } - - _transforms[0] = _viewState->getViewTransform(); - - // apply entity translation offset to the viewTransform in one go (it's a preTranslate because viewTransform goes from world to eye space) - _transforms[0].preTranslate(-_translation); - - batch.setViewTransform(_transforms[0]); - - /*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; - - - //renderMeshes(batch, mode, translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned, args, forceRenderMeshes); - int opaqueMeshPartsRendered = 0; - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, false, false, args, true); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, true, false, args, true); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, false, false, args, true); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, true, false, args, true); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, false, false, args, true); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, true, false, args, true); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, false, false, args, true); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, true, false, args, true); - - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, false, false, args, true); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, false, false, args, true); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, false, args, true); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, false, args, true); - - // render translucent meshes afterwards - //DependencyManager::get()->setPrimaryDrawBuffers(false, true, true); - { - GLenum buffers[2]; - int bufferCount = 0; - buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; - buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; - GLBATCH(glDrawBuffers)(bufferCount, buffers); - } - - int translucentMeshPartsRendered = 0; - const float MOSTLY_OPAQUE_THRESHOLD = 0.75f; - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, false, false, args, true); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, true, false, args, true); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, false, false, args, true); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, true, false, args, true); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, false, false, args, true); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, true, false, args, true); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, false, args, true); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, false, args, true); - - { - GLenum buffers[1]; - int bufferCount = 0; - buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; - GLBATCH(glDrawBuffers)(bufferCount, buffers); - } - - // 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; - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, false, args, true); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, false, args, true); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, false, false, args, true); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, true, false, args, true); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, false, false, args, true); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, false, args, true); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, false, false, args, true); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, false, args, true); - - // 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); - - // Render! - { - PROFILE_RANGE("render Batch"); - - #if defined(ANDROID) - #else - glPushMatrix(); - #endif - - ::gpu::GLBackend::renderBatch(batch, true); // force sync with gl state here - - #if defined(ANDROID) - #else - glPopMatrix(); - #endif - } - - // restore all the default material settings - _viewState->setupWorldLight(); - - #ifdef WANT_DEBUG_MESHBOXES - renderDebugMeshBoxes(); - #endif - - return true; -} - void Model::renderDebugMeshBoxes() { int colorNdx = 0; _mutex.lock(); @@ -2295,22 +2095,6 @@ void Model::segregateMeshGroups() { _meshGroupsKnown = true; } -QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe) { - PROFILE_RANGE(__FUNCTION__); - - // depending on which parameters we were called with, pick the correct mesh group to render - QVector* whichList = NULL; - - RenderKey key(translucent, hasLightmap, hasTangents, hasSpecular, isSkinned, isWireframe); - - auto bucket = _renderBuckets.find(key.getRaw()); - if (bucket != _renderBuckets.end()) { - whichList = &(*bucket).second._meshes; - } - - return whichList; -} - void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args, Locations*& locations) { @@ -2339,212 +2123,6 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f } } -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) { - - PROFILE_RANGE(__FUNCTION__); - int meshPartsRendered = 0; - - //Pick the mesh list with the requested render flags - QVector* whichList = pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, isWireframe); - if (!whichList) { - return 0; - } - QVector& list = *whichList; - - // If this list has nothing to render, then don't bother proceeding. This saves us on binding to programs - if (list.empty()) { - return 0; - } - - Locations* locations = nullptr; - pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, isWireframe, - args, locations); - meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, - args, locations, forceRenderSomeMeshes); - - return meshPartsRendered; -} - - -int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args, - Locations* locations, bool forceRenderMeshes) { - PROFILE_RANGE(__FUNCTION__); - - auto textureCache = DependencyManager::get(); - - QString lastMaterialID; - int meshPartsRendered = 0; - updateVisibleJointStates(); - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - const QVector& networkMeshes = _geometry->getMeshes(); - - // i is the "index" from the original networkMeshes QVector... - foreach (int i, list) { - - // if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown - // to false to rebuild out mesh groups. - - if (i < 0 || i >= networkMeshes.size() || i > geometry.meshes.size()) { - _meshGroupsKnown = false; // regenerate these lists next time around. - _readyWhenAdded = false; // in case any of our users are using scenes - invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid - continue; - } - - // exit early if the translucency doesn't match what we're drawing - const NetworkMesh& networkMesh = networkMeshes.at(i); - const FBXMesh& mesh = geometry.meshes.at(i); - - batch.setIndexBuffer(gpu::UINT32, (networkMesh._indexBuffer), 0); - int vertexCount = mesh.vertices.size(); - if (vertexCount == 0) { - // sanity check - continue; - } - - // if we got here, then check to see if this mesh is in view - if (args) { - bool shouldRender = true; - if (args->_viewFrustum) { - - shouldRender = forceRenderMeshes || - args->_viewFrustum->boxInFrustum(_calculatedMeshBoxes.at(i)) != ViewFrustum::OUTSIDE; - - if (shouldRender && !forceRenderMeshes) { - float distance = args->_viewFrustum->distanceToCamera(_calculatedMeshBoxes.at(i).calcCenter()); - shouldRender = !_viewState ? false : _viewState->shouldRenderMesh(_calculatedMeshBoxes.at(i).getLargestDimension(), - distance); - } - } - - if (!shouldRender) { - continue; // skip this mesh - } - } - - const MeshState& state = _meshStates.at(i); - if (state.clusterMatrices.size() > 1) { - GLBATCH(glUniformMatrix4fv)(locations->clusterMatrices, state.clusterMatrices.size(), false, - (const float*)state.clusterMatrices.constData()); - batch.setModelTransform(Transform()); - } else { - batch.setModelTransform(Transform(state.clusterMatrices[0])); - } - - if (mesh.blendshapes.isEmpty()) { - batch.setInputFormat(networkMesh._vertexFormat); - batch.setInputStream(0, *networkMesh._vertexStream); - } else { - batch.setInputFormat(networkMesh._vertexFormat); - batch.setInputBuffer(0, _blendedVertexBuffers[i], 0, sizeof(glm::vec3)); - batch.setInputBuffer(1, _blendedVertexBuffers[i], vertexCount * sizeof(glm::vec3), sizeof(glm::vec3)); - batch.setInputStream(2, *networkMesh._vertexStream); - } - - if (mesh.colors.isEmpty()) { - GLBATCH(glColor4f)(1.0f, 1.0f, 1.0f, 1.0f); - } - - qint64 offset = 0; - for (int j = 0; j < networkMesh.parts.size(); j++) { - const NetworkMeshPart& networkPart = networkMesh.parts.at(j); - const FBXMeshPart& part = mesh.parts.at(j); - model::MaterialPointer material = part._material; - if ((networkPart.isTranslucent() || part.opacity != 1.0f) != translucent) { - offset += (part.quadIndices.size() + part.triangleIndices.size()) * sizeof(int); - continue; - } - - // apply material properties - if (mode == RenderArgs::SHADOW_RENDER_MODE) { - /// GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); - - } else { - if (lastMaterialID != part.materialID) { - const bool wantDebug = false; - if (wantDebug) { - qCDebug(renderutils) << "Material Changed ---------------------------------------------"; - qCDebug(renderutils) << "part INDEX:" << j; - qCDebug(renderutils) << "NEW part.materialID:" << part.materialID; - } - - if (locations->materialBufferUnit >= 0) { - batch.setUniformBuffer(locations->materialBufferUnit, material->getSchemaBuffer()); - } - - Texture* diffuseMap = networkPart.diffuseTexture.data(); - if (mesh.isEye && diffuseMap) { - diffuseMap = (_dilatedTextures[i][j] = - static_cast(diffuseMap)->getDilatedTexture(_pupilDilation)).data(); - } - static bool showDiffuse = true; - if (showDiffuse && diffuseMap) { - batch.setUniformTexture(0, diffuseMap->getGPUTexture()); - - } else { - batch.setUniformTexture(0, textureCache->getWhiteTexture()); - } - - if (locations->texcoordMatrices >= 0) { - glm::mat4 texcoordTransform[2]; - if (!part.diffuseTexture.transform.isIdentity()) { - part.diffuseTexture.transform.getMatrix(texcoordTransform[0]); - } - if (!part.emissiveTexture.transform.isIdentity()) { - part.emissiveTexture.transform.getMatrix(texcoordTransform[1]); - } - GLBATCH(glUniformMatrix4fv)(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform); - } - - if (!mesh.tangents.isEmpty()) { - Texture* normalMap = networkPart.normalTexture.data(); - batch.setUniformTexture(1, !normalMap ? - textureCache->getBlueTexture() : normalMap->getGPUTexture()); - - } - - if (locations->specularTextureUnit >= 0) { - Texture* specularMap = networkPart.specularTexture.data(); - batch.setUniformTexture(locations->specularTextureUnit, !specularMap ? - textureCache->getWhiteTexture() : specularMap->getGPUTexture()); - } - } - - // HACK: For unkwon reason (yet!) this code that should be assigned only if the material changes need to be called for every - // drawcall with an emissive, so let's do it for now. - if (locations->emissiveTextureUnit >= 0) { - // assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader - float emissiveOffset = part.emissiveParams.x; - float emissiveScale = part.emissiveParams.y; - GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale); - - Texture* emissiveMap = networkPart.emissiveTexture.data(); - batch.setUniformTexture(locations->emissiveTextureUnit, !emissiveMap ? - textureCache->getWhiteTexture() : emissiveMap->getGPUTexture()); - } - - lastMaterialID = part.materialID; - } - - meshPartsRendered++; - - if (part.quadIndices.size() > 0) { - batch.drawIndexed(gpu::QUADS, part.quadIndices.size(), offset); - offset += part.quadIndices.size() * sizeof(int); - } - - if (part.triangleIndices.size() > 0) { - batch.drawIndexed(gpu::TRIANGLES, part.triangleIndices.size(), offset); - offset += part.triangleIndices.size() * sizeof(int); - } - - } - } - - return meshPartsRendered; -} ModelBlender::ModelBlender() : _pendingBlenders(0) { diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 043b7e659b..c96e006aa8 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -399,18 +399,8 @@ private: int _debugMeshBoxesID = GeometryCache::UNKNOWN_ID; // 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, - bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args = NULL, - bool forceRenderMeshes = false); - + void setupBatchTransform(gpu::Batch& batch, RenderArgs* args); - QVector* pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe); - - int renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, float alphaThreshold, - RenderArgs* args, Locations* locations, - bool forceRenderSomeMeshes = false); - static void pickPrograms(gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args, Locations*& locations); @@ -543,13 +533,6 @@ private: bool _readyWhenAdded = false; bool _needsReload = true; - -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) From e06422825a54a0ee186b579760261dbf4813a8c9 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 10 Jun 2015 15:46:54 -0700 Subject: [PATCH 08/11] mostly getting attachments working again --- interface/src/avatar/Avatar.cpp | 4 +- interface/src/avatar/MyAvatar.cpp | 18 +--- libraries/render-utils/src/Model.cpp | 124 ++++++++------------------- libraries/render-utils/src/Model.h | 29 ++----- 4 files changed, 43 insertions(+), 132 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 627c42ffa8..f644968ff8 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -582,7 +582,9 @@ void Avatar::simulateAttachments(float deltaTime) { _skeletonModel.getJointCombinedRotation(jointIndex, jointRotation)) { model->setTranslation(jointPosition + jointRotation * attachment.translation * _scale); model->setRotation(jointRotation * attachment.rotation); - model->setScaleToFit(true, _scale * attachment.scale); + model->setScaleToFit(true, _scale * attachment.scale, true); // hack to force rescale + model->setSnapModelToCenter(false); // hack to force resnap + model->setSnapModelToCenter(true); model->simulate(deltaTime); } } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index afe0311a29..65b927c2c0 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1196,23 +1196,7 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bo } scene->enqueuePendingChanges(pendingChanges); - Camera *camera = Application::getInstance()->getCamera(); - const glm::vec3 cameraPos = camera->getPosition(); - - - // HACK: comment this block which possibly change the near and break the rendering 5/6/2015 - // Only tweak the frustum near far if it's not shadow - /* if (renderMode != RenderArgs::SHADOW_RENDER_MODE) { - // Set near clip distance according to skeleton model dimensions if first person and there is no separate head model. - if (shouldRenderHead(cameraPos, renderMode) || !getHead()->getFaceModel().getURL().isEmpty()) { - renderFrustum->setNearClip(DEFAULT_NEAR_CLIP); - } else { - float clipDistance = _skeletonModel.getHeadClipDistance(); - clipDistance = glm::length(getEyePosition() - + camera->getOrientation() * glm::vec3(0.0f, 0.0f, -clipDistance) - cameraPos); - renderFrustum->setNearClip(clipDistance); - } - }*/ + const glm::vec3 cameraPos = Application::getInstance()->getCamera()->getPosition(); // Render head so long as the camera isn't inside it if (shouldRenderHead(renderArgs, cameraPos)) { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 3cea5c9777..8d234cdef5 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -435,6 +435,7 @@ bool Model::updateGeometry() { QSharedPointer geometry = _geometry->getLODOrFallback(_lodDistance, _lodHysteresis); if (_geometry != geometry) { + // NOTE: it is theoretically impossible to reach here after passing through the applyNextGeometry() call above. // Which means we don't need to worry about calling deleteGeometry() below immediately after creating new geometry. @@ -811,71 +812,41 @@ void Model::renderSetup(RenderArgs* args) { } -class TransparentMeshPart { +class MeshPartPayload { public: - TransparentMeshPart(Model* model, int meshIndex, int partIndex) : model(model), meshIndex(meshIndex), partIndex(partIndex) { } - typedef render::Payload Payload; + MeshPartPayload(bool transparent, Model* model, int meshIndex, int partIndex) : + transparent(transparent), model(model), url(model->getURL()), meshIndex(meshIndex), partIndex(partIndex) { } + typedef render::Payload Payload; typedef Payload::DataPointer Pointer; - Model* model; + bool transparent; + Model* model; + QUrl url; int meshIndex; int partIndex; }; namespace render { - template <> const ItemKey payloadGetKey(const TransparentMeshPart::Pointer& payload) { + template <> const ItemKey payloadGetKey(const MeshPartPayload::Pointer& payload) { if (!payload->model->isVisible()) { return ItemKey::Builder().withInvisible().build(); } - return ItemKey::Builder::transparentShape(); + return payload->transparent ? ItemKey::Builder::transparentShape() : ItemKey::Builder::opaqueShape(); } - template <> const Item::Bound payloadGetBound(const TransparentMeshPart::Pointer& payload) { + template <> const Item::Bound payloadGetBound(const MeshPartPayload::Pointer& payload) { if (payload) { return payload->model->getPartBounds(payload->meshIndex, payload->partIndex); } return render::Item::Bound(); } - template <> void payloadRender(const TransparentMeshPart::Pointer& payload, RenderArgs* args) { + template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderArgs* args) { if (args) { - return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, true); + return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, payload->transparent); } } -} -class OpaqueMeshPart { -public: - OpaqueMeshPart(Model* model, int meshIndex, int partIndex) : model(model), meshIndex(meshIndex), partIndex(partIndex) { } - typedef render::Payload Payload; - typedef Payload::DataPointer Pointer; - - Model* model; - int meshIndex; - int partIndex; -}; - -namespace render { - template <> const ItemKey payloadGetKey(const OpaqueMeshPart::Pointer& payload) { - if (!payload->model->isVisible()) { - return ItemKey::Builder().withInvisible().build(); - } - return ItemKey::Builder::opaqueShape(); - } - - template <> const Item::Bound payloadGetBound(const OpaqueMeshPart::Pointer& payload) { - if (payload) { - Item::Bound result = payload->model->getPartBounds(payload->meshIndex, payload->partIndex); - //qDebug() << "payloadGetBound(OpaqueMeshPart) " << result; - return result; - } - return render::Item::Bound(); - } - template <> void payloadRender(const OpaqueMeshPart::Pointer& payload, RenderArgs* args) { - if (args) { - return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, false); - } - } - /* template <> const model::MaterialKey& shapeGetMaterialKey(const OpaqueMeshPart::Pointer& payload) { + /* template <> const model::MaterialKey& shapeGetMaterialKey(const MeshPartPayload::Pointer& payload) { return payload->model->getPartMaterial(payload->meshIndex, payload->partIndex); }*/ } @@ -902,16 +873,17 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan foreach (auto renderItem, _transparentRenderItems) { auto item = scene->allocateID(); - auto renderData = TransparentMeshPart::Pointer(renderItem); - auto renderPayload = render::PayloadPointer(new TransparentMeshPart::Payload(renderData)); + auto renderData = MeshPartPayload::Pointer(renderItem); + auto renderPayload = render::PayloadPointer(new MeshPartPayload::Payload(renderData)); pendingChanges.resetItem(item, renderPayload); _renderItems.insert(item, renderPayload); somethingAdded = true; } + foreach (auto renderItem, _opaqueRenderItems) { auto item = scene->allocateID(); - auto renderData = OpaqueMeshPart::Pointer(renderItem); - auto renderPayload = render::PayloadPointer(new OpaqueMeshPart::Payload(renderData)); + auto renderData = MeshPartPayload::Pointer(renderItem); + auto renderPayload = render::PayloadPointer(new MeshPartPayload::Payload(renderData)); pendingChanges.resetItem(item, renderPayload); _renderItems.insert(item, renderPayload); somethingAdded = true; @@ -1036,12 +1008,12 @@ Extents Model::calculateScaledOffsetExtents(const Extents& extents) const { Extents translatedExtents = { rotatedExtents.minimum + _translation, rotatedExtents.maximum + _translation }; + return translatedExtents; } /// Returns the world space equivalent of some box in model space. AABox Model::calculateScaledOffsetAABox(const AABox& box) const { - return AABox(calculateScaledOffsetExtents(Extents(box))); } @@ -1110,9 +1082,10 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo if (_url == url && _geometry && _geometry->getURL() == url) { return; } - + _readyWhenAdded = false; // reset out render items. _needsReload = true; + invalidCalculatedMeshBoxes(); _url = url; @@ -1301,7 +1274,7 @@ void Model::setScaleToFit(bool scaleToFit, const glm::vec3& dimensions) { } } -void Model::setScaleToFit(bool scaleToFit, float largestDimension) { +void Model::setScaleToFit(bool scaleToFit, float largestDimension, bool forceRescale) { // NOTE: if the model is not active, then it means we don't actually know the true/natural dimensions of the // mesh, and so we can't do the needed calculations for scaling to fit to a single largest dimension. In this // case we will record that we do want to do this, but we will stick our desired single dimension into the @@ -1314,7 +1287,7 @@ void Model::setScaleToFit(bool scaleToFit, float largestDimension) { return; } - if (_scaleToFit != scaleToFit || glm::length(_scaleToFitDimensions) != largestDimension) { + if (forceRescale || _scaleToFit != scaleToFit || glm::length(_scaleToFitDimensions) != largestDimension) { _scaleToFit = scaleToFit; // we only need to do this work if we're "turning on" scale to fit. @@ -1324,7 +1297,7 @@ void Model::setScaleToFit(bool scaleToFit, float largestDimension) { float maxScale = largestDimension / maxDimension; glm::vec3 modelMeshDimensions = modelMeshExtents.maximum - modelMeshExtents.minimum; glm::vec3 dimensions = modelMeshDimensions * maxScale; - + _scaleToFitDimensions = dimensions; _scaledToFit = false; // force rescaling } @@ -1822,7 +1795,6 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran glm::mat4 scale = glm::scale(partBounds.getDimensions()); glm::mat4 modelToWorldMatrix = translation * scale; batch.setModelTransform(modelToWorldMatrix); - //qDebug() << "partBounds:" << partBounds; DependencyManager::get()->renderWireCube(batch, 1.0f, cubeColor); } #endif //def DEBUG_BOUNDING_PARTS @@ -1912,16 +1884,18 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran // guard against partially loaded meshes if (partIndex >= networkMesh.parts.size() || partIndex >= mesh.parts.size()) { - return; + return; } const NetworkMeshPart& networkPart = networkMesh.parts.at(partIndex); const FBXMeshPart& part = mesh.parts.at(partIndex); model::MaterialPointer material = part._material; + #ifdef WANT_DEBUG if (material == nullptr) { - // qCDebug(renderutils) << "WARNING: material == nullptr!!!"; + qCDebug(renderutils) << "WARNING: material == nullptr!!!"; } + #endif if (material != nullptr) { @@ -2023,8 +1997,6 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran } void Model::segregateMeshGroups() { - _renderBuckets.clear(); - const FBXGeometry& geometry = _geometry->getFBXGeometry(); const QVector& networkMeshes = _geometry->getMeshes(); @@ -2034,6 +2006,9 @@ void Model::segregateMeshGroups() { qDebug() << "WARNING!!!! Mesh Sizes don't match! We will not segregate mesh groups yet."; return; } + + _transparentRenderItems.clear(); + _opaqueRenderItems.clear(); // Run through all of the meshes, and place them into their segregated, but unsorted buckets for (int i = 0; i < networkMeshes.size(); i++) { @@ -2058,43 +2033,12 @@ void Model::segregateMeshGroups() { for (int partIndex = 0; partIndex < totalParts; partIndex++) { // this is a good place to create our renderPayloads if (translucentMesh) { - _transparentRenderItems << std::shared_ptr(new TransparentMeshPart(this, i, partIndex)); + _transparentRenderItems << std::shared_ptr(new MeshPartPayload(true, this, i, partIndex)); } else { - _opaqueRenderItems << std::shared_ptr(new OpaqueMeshPart(this, i, partIndex)); + _opaqueRenderItems << std::shared_ptr(new MeshPartPayload(false, this, i, partIndex)); } } - - - QString materialID; - - // create a material name from all the parts. If there's one part, this will be a single material and its - // true name. If however the mesh has multiple parts the name will be all the part's materials mashed together - // which will result in those parts being sorted away from single material parts. - QString lastPartMaterialID; - foreach(FBXMeshPart part, mesh.parts) { - if (part.materialID != lastPartMaterialID) { - materialID += part.materialID; - } - lastPartMaterialID = part.materialID; - } - const bool wantDebug = false; - if (wantDebug) { - qCDebug(renderutils) << "materialID:" << materialID << "parts:" << mesh.parts.size(); - } - - RenderKey key(translucentMesh, hasLightmap, hasTangents, hasSpecular, isSkinned, wireframe); - - // reuse or create the bucket corresponding to that key and insert the mesh as unsorted - _renderBuckets[key.getRaw()]._unsortedMeshes.insertMulti(materialID, i); } - - for(auto& b : _renderBuckets) { - foreach(auto i, b.second._unsortedMeshes) { - b.second._meshes.append(i); - } - b.second._unsortedMeshes.clear(); - } - _meshGroupsKnown = true; } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index c96e006aa8..7c1572418e 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -51,17 +51,11 @@ namespace render { class PendingChanges; typedef unsigned int ItemID; } -class OpaqueMeshPart; -class TransparentMeshPart; +class MeshPartPayload; -inline uint qHash(const std::shared_ptr& a, uint seed) { +inline uint qHash(const std::shared_ptr& a, uint seed) { return qHash(a.get(), seed); } -inline uint qHash(const std::shared_ptr& a, uint seed) { - return qHash(a.get(), seed); -} - - /// A generic 3D model displaying geometry loaded from a URL. class Model : public QObject, public PhysicsEntity { @@ -77,7 +71,7 @@ public: virtual ~Model(); /// enables/disables scale to fit behavior, the model will be automatically scaled to the specified largest dimension - void setScaleToFit(bool scaleToFit, float largestDimension = 0.0f); + void setScaleToFit(bool scaleToFit, float largestDimension = 0.0f, bool forceRescale = false); bool getScaleToFit() const { return _scaleToFit; } /// is scale to fit enabled bool getIsScaledToFit() const { return _scaledToFit; } /// is model scaled to fit const glm::vec3& getScaleToFitDimensions() const { return _scaleToFitDimensions; } /// the dimensions model is scaled to @@ -511,24 +505,11 @@ private: }; static RenderPipelineLib _renderPipelineLib; - - class RenderBucket { - public: - QVector _meshes; - QMap _unsortedMeshes; - }; - typedef std::unordered_map BaseRenderBucketMap; - class RenderBucketMap : public BaseRenderBucketMap { - public: - typedef RenderKey Key; - }; - RenderBucketMap _renderBuckets; - bool _renderCollisionHull; - QSet> _transparentRenderItems; - QSet> _opaqueRenderItems; + QSet> _transparentRenderItems; + QSet> _opaqueRenderItems; QMap _renderItems; bool _readyWhenAdded = false; bool _needsReload = true; From 139855f48792594c5e6b5ea2a51557b0b0a5f515 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 10 Jun 2015 16:13:17 -0700 Subject: [PATCH 09/11] handle remove attachment case --- interface/src/avatar/Avatar.cpp | 26 ++++++++++++++++++++++---- interface/src/avatar/Avatar.h | 3 +++ interface/src/avatar/MyAvatar.cpp | 18 +----------------- 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index f644968ff8..dbe7d52a3f 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -107,6 +107,9 @@ Avatar::Avatar() : } Avatar::~Avatar() { + for(auto attachment : _unusedAttachments) { + delete attachment; + } } const float BILLBOARD_LOD_DISTANCE = 40.0f; @@ -525,7 +528,7 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const { return glm::angleAxis(angle * proportion, axis); } -void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel) { +void Avatar::fixupModelsInScene() { // 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 = Application::getInstance()->getMain3DScene(); @@ -544,8 +547,18 @@ void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool attachmentModel->addToScene(scene, pendingChanges); } } + for (auto attachmentModelToRemove : _attachmentsToRemove) { + attachmentModelToRemove->removeFromScene(scene, pendingChanges); + _unusedAttachments << attachmentModelToRemove; + } + _attachmentsToRemove.clear(); scene->enqueuePendingChanges(pendingChanges); +} +void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel) { + + fixupModelsInScene(); + { Glower glower(renderArgs, glowLevel); @@ -947,13 +960,18 @@ void Avatar::setAttachmentData(const QVector& attachmentData) { } // make sure we have as many models as attachments while (_attachmentModels.size() < attachmentData.size()) { - Model* model = new Model(this); + Model* model = nullptr; + if (_unusedAttachments.size() > 0) { + model = _unusedAttachments.takeFirst(); + } else { + model = new Model(this); + } model->init(); _attachmentModels.append(model); } while (_attachmentModels.size() > attachmentData.size()) { - // NOTE: what's really going to happen here? This seems dangerous... has the model been removed from the scene? - delete _attachmentModels.takeLast(); + auto attachmentModel = _attachmentModels.takeLast(); + _attachmentsToRemove << attachmentModel; } // update the urls diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 1113496080..b198d12a6e 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -195,6 +195,8 @@ protected: SkeletonModel _skeletonModel; glm::vec3 _skeletonOffset; QVector _attachmentModels; + QVector _attachmentsToRemove; + QVector _unusedAttachments; float _bodyYawDelta; // These position histories and derivatives are in the world-frame. @@ -234,6 +236,7 @@ protected: void renderDisplayName(RenderArgs* renderArgs); virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel = 0.0f); virtual bool shouldRenderHead(const RenderArgs* renderArgs, const glm::vec3& cameraPosition) const; + virtual void fixupModelsInScene(); void simulateAttachments(float deltaTime); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 65b927c2c0..c4e08b5dba 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1178,23 +1178,7 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bo // 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 = Application::getInstance()->getMain3DScene(); - render::PendingChanges pendingChanges; - if (_skeletonModel.needsFixupInScene()) { - _skeletonModel.removeFromScene(scene, pendingChanges); - _skeletonModel.addToScene(scene, pendingChanges); - } - if (getHead()->getFaceModel().needsFixupInScene()) { - getHead()->getFaceModel().removeFromScene(scene, pendingChanges); - getHead()->getFaceModel().addToScene(scene, pendingChanges); - } - for (auto attachmentModel : _attachmentModels) { - if (attachmentModel->needsFixupInScene()) { - attachmentModel->removeFromScene(scene, pendingChanges); - attachmentModel->addToScene(scene, pendingChanges); - } - } - scene->enqueuePendingChanges(pendingChanges); + fixupModelsInScene(); const glm::vec3 cameraPos = Application::getInstance()->getCamera()->getPosition(); From 7d0000c5377febd3fc3307b840f5fe020f3d7bfa Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 11 Jun 2015 08:38:03 -0700 Subject: [PATCH 10/11] fix warning about returning ref to temp variable --- libraries/render/src/render/Scene.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 8cb29609ba..b9481d367e 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -245,7 +245,7 @@ public: void update(const UpdateFunctorPointer& updateFunctor) { _payload->update(updateFunctor); } // Shape Type Interface - const model::MaterialKey& getMaterialKey() const { return _payload->getMaterialKey(); } + const model::MaterialKey getMaterialKey() const { return _payload->getMaterialKey(); } protected: PayloadPointer _payload; From f77f3f1e1e46eea210f9bbefad2befe182177359 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 11 Jun 2015 08:43:19 -0700 Subject: [PATCH 11/11] fix bug where grab.js moves mouse to screen corner when CTRL is pressed --- examples/grab.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/grab.js b/examples/grab.js index 306af86c68..c6b1b884b7 100644 --- a/examples/grab.js +++ b/examples/grab.js @@ -140,6 +140,10 @@ function mouseIntersectionWithPlane(pointOnPlane, planeNormal, event) { } function computeNewGrabPlane() { + if (!gIsGrabbing) { + return; + } + var maybeResetMousePosition = false; if (gGrabMode !== "rotate") { gMouseAtRotateStart = gMouseCursorLocation;