From f1543a9d36a149d9b9cf9d9b90fcf150701add8f Mon Sep 17 00:00:00 2001 From: Adrianl3d Date: Wed, 19 Nov 2014 04:36:57 +1000 Subject: [PATCH 01/24] Added notifications.js Creates overlay notifications from events and key strokes. improved fading. --- examples/notifications.js | 378 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 378 insertions(+) create mode 100644 examples/notifications.js diff --git a/examples/notifications.js b/examples/notifications.js new file mode 100644 index 0000000000..6eb5e25566 --- /dev/null +++ b/examples/notifications.js @@ -0,0 +1,378 @@ +// +// notifications.js +// Created by Adrian +// +// Adrian McCarlie 8-10-14 +// This script demonstrates on-screen overlay type notifications. +// 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 + +// This script demonstrates notifications created via a number of ways, such as: +// Simple key press alerts, which only depend on a key being pressed, +// dummy examples of this are "q", "w", "e", "r", and "SPACEBAR". +// actual working examples are "a" for left turn, "d" for right turn and Ctrl/s for snapshot. + +// System generated alerts such as users joining and leaving and chat messages which mention this user. +// System generated alerts which originate with a user interface event such as Window Resize, and Mic Mute/Unmute. +// Mic Mute/Unmute may appear to be a key press alert, but it actually gets the call from the system as mic is muted and unmuted, +// so the mic mute/unmute will also trigger the notification by clicking the Mic Mute button at the top of the screen. + + +// To add a new System notification type: +// +// 1. Set the Event Connector at the bottom of the script. +// example: +// GlobalServices.incomingMessage.connect(onIncomingMessage); +// +// 2. Create a new function to produce a text string, do not include new line returns. +// example: +// function onIncomingMessage(user, message) { +// //do stuff here; +// var text = "This is a notification"; +// wordWrap(text); +// } +// +// This new function must call wordWrap(text) if the length of message is longer than 42 chars or unknown. +// wordWrap() will format the text to fit the notifications overlay and send it to createNotification(text). +// If the message is 42 chars or less you should bypass wordWrap() and call createNotification() directly. + + +// To add a keypress driven notification: +// +// 1. Add a key to the keyPressEvent(key). +// 2. Declare a text string. +// 3. Call createNotifications(text) parsing the text. +// example: +// if (key.text == "a") { +// var noteString = "Turning to the Left"; +// createNotification(noteString); +// } + + +var width = 340.0; //width of notification overlay +var height = 40.0; // height of a single line notification overlay +var windowDimensions = Controller.getViewportDimensions(); // get the size of the interface window +var overlayLocationX = (windowDimensions.x - (width + 60.0));// positions window 60px from the right of the interface window +var buttonLocationX = overlayLocationX + (width - 28.0); +var locationY = 20.0; // position down from top of interface window +var topMargin = 13.0; +var leftMargin = 10.0; +var textColor = { red: 228, green: 228, blue: 228}; // text color +var backColor = { red: 38, green: 38, blue: 38}; // background color +var backgroundAlpha = 0; +var fontSize = 12.0; +var persistTime = 5.0; // time in seconds before notification fades +var clickedText = false; +var frame = 0; +var ourWidth = Window.innerWidth; +var ourHeight = Window.innerHeight; +var text = "placeholder"; +var last_users = GlobalServices.onlineUsers; +var users =[]; +var ctrlIsPressed = false; +var ready = true; + +// When our script shuts down, we should clean up all of our overlays +function scriptEnding() { + for (i = 0; i < notifications.length; i++){ + Overlays.deleteOverlay(notifications[i]); + Overlays.deleteOverlay(buttons[i]); + } +} +Script.scriptEnding.connect(scriptEnding); + +var notifications = []; +var buttons = []; +var times = []; +var heights = []; +var myAlpha = []; +var arrays = []; + +// This function creates and sizes the overlays +function createNotification(text){ + var count = (text.match(/\n/g) || []).length; + var breakPoint = 43.0; // length when new line is added + var extraLine = 0; + var breaks = 0; + var height = 40.0; + var stack = 0; + if (text.length >= breakPoint){ + breaks = count; + } + var extraLine = breaks * 16.0; + for (i = 0; i < heights.length; i++){ + stack = stack + heights[i]; + } + var level = (stack + 20.0 ); + height = height + extraLine; + var overlayProperties = { + x: overlayLocationX, + y: level, + width: width, + height: height, + color: textColor, + backgroundColor: backColor, + alpha: backgroundAlpha, + topargin: topMargin, + leftMargin: leftMargin, + font: {size: fontSize}, + text: text, + }; + var bLevel = level + 12.0; + var buttonProperties = { + x: buttonLocationX, + y: bLevel, + width: 15.0,//37 + height: 15.0,//35 + subImage: { x: 0, y: 0, width: 10, height: 10 }, + imageURL: "http://hifi-public.s3.amazonaws.com/images/close-small-light.svg", + color: { red: 255, green: 255, blue: 255}, + visible: true, + alpha: backgroundAlpha, + }; + + Notify(overlayProperties, buttonProperties, height); + +} + +// Pushes data to each array and sets up data for 2nd dimension array +// to handle auxiliary data not carried by the overlay class +// specifically notification "heights", "times" of creation, and . +function Notify (notice, button, height ){ + + notifications.push((Overlays.addOverlay("text",notice))); + buttons.push((Overlays.addOverlay("image",button))); + times.push(new Date().getTime() / 1000); + height = height + 1.0; + heights.push(height); + myAlpha.push(0); + var last = notifications.length - 1; + createArrays(notifications[last], buttons[last], times[last], heights[last], myAlpha[last]); + fadeIn(notifications[last], buttons[last]) +} + +function fadeIn(noticeIn, buttonIn){ + var myLength = arrays.length; + var q = 0; + var pauseTimer = null; + pauseTimer = Script.setInterval(function() { + q++; + qFade = q / 10.0; + Overlays.editOverlay(noticeIn, {alpha: qFade}); + Overlays.editOverlay(buttonIn, {alpha: qFade}); + if (q >= 9.0) { + Script.clearInterval(pauseTimer); + } + }, 10); +} + + +// push data from above to the 2 dimensional array +function createArrays(notice, button, createTime, height, myAlpha){ + arrays.push([notice, button, createTime, height, myAlpha]); +} +// handles mouse clicks on buttons +function mousePressEvent(event) { + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); //identify which overlay was clicked + for (i = 0; i < buttons.length; i++){ //if user clicked a button + if(clickedOverlay == buttons[i]){ + Overlays.deleteOverlay(notifications[i]); + Overlays.deleteOverlay(buttons[i]); + notifications.splice(i, 1); + buttons.splice(i, 1); + times.splice(i, 1); + heights.splice(i, 1); + myAlpha.splice(i, 1); + arrays.splice(i, 1); + } + } +} + +// Control key remains active only while key is held down +function keyReleaseEvent(key){ + if (key.key == 16777249){ + ctrlIsPressed = false; + } +} + +// Triggers notification on specific key driven events +function keyPressEvent(key) { + if (key.key == 16777249){ + ctrlIsPressed = true; + } + if (key.text == "a") { + var noteString = "Turning to the Left"; + createNotification(noteString); + } + if (key.text == "d") { + var noteString = "Turning to the Right"; + createNotification(noteString); + } + if (key.text == "s") { + if (ctrlIsPressed == true){ + var noteString = "You have taken a snapshot"; + createNotification(noteString); + } + } + if (key.text == "q") { + var noteString = "Enable Scripted Motor control is now on."; + wordWrap(noteString); + } + if (key.text == "w") { + var noteString = "This notification spans 2 lines. The overlay will resize to fit new lines."; + var noteString = "editVoxels.js stopped, editModels.js stopped, selectAudioDevice.js stopped."; + wordWrap(noteString); + } + if (key.text == "e") { + var noteString = "This is an example of a multiple line notification. This notification will span 3 lines." + wordWrap(noteString); + } + if (key.text == "r") { + var noteString = "This is a very long line of text that we are going to use in this example to divide it into rows of maximum 43 chars and see how many lines we use."; + wordWrap(noteString); + } + if (key.text == "SPACE") { + var noteString = "You have pressed the Spacebar, This is an example of a multiple line notification. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam."; + wordWrap(noteString); + } +} + +// formats string to add newline every 43 chars +function wordWrap(str){ + var result = stringDivider(str, 43.0, "\n"); + createNotification(result); +} +// wraps whole word to newline +function stringDivider(str, slotWidth, spaceReplacer) { + if (str.length>slotWidth) { + var p=slotWidth; + for (; p > 0 && str[p] != ' '; p--) { + } + if (p > 0) { + var left = str.substring(0, p); + var right = str.substring(p + 1); + return left + spaceReplacer + stringDivider(right, slotWidth, spaceReplacer); + } + } + return str; +} + +//This fires a notification on window resize +function checkSize(){ + if((Window.innerWidth!=ourWidth)||(Window.innerHeight!=ourHeight)){ + var windowResize = "Window has been resized"; + ourWidth = Window.innerWidth; + ourHeight = Window.innerHeight; + windowDimensions = Controller.getViewportDimensions(); + overlayLocationX = (windowDimensions.x - (width + 60.0)); + buttonLocationX = overlayLocationX + (width - 35.0); + createNotification(windowResize) + } +} + +// Triggers notification if a user logs on or off +function onOnlineUsersChanged(users) { + var joiners = []; + var leavers = []; + for (user in users) { + if (last_users.indexOf(users[user]) == -1.0) { + joiners.push(users[user]); + createNotification(users[user] + " Has joined"); + } + } + for (user in last_users) { + if (users.indexOf(last_users[user]) == -1.0) { + leavers.push(last_users[user]); + createNotification(last_users[user] + " Has left"); + } + } + last_users = users; +} + +// Triggers notification if @MyUserName is mentioned in chat and returns the message to the notification. +function onIncomingMessage(user, message) { + var myMessage = message; + var alertMe = "@" + GlobalServices.myUsername; + var thisAlert = user + ": " + myMessage; + if (myMessage.indexOf(alertMe) > -1.0) { + wordWrap(thisAlert); + } +} +// Triggers mic mute notification +function onMuteStateChanged() { + var muteState = AudioDevice.getMuted() ? "Muted" : "Unmuted"; + var muteString = "Microphone is set to " + muteState; + createNotification(muteString); +} + +function update(){ + frame++; + if ((frame % 60.0) == 0) { // only update once a second + checkSize(); // checks for size change to trigger windowResize notification + locationY = 20.0; + for (var i = 0; i < arrays.length; i++){ //repositions overlays as others fade + var nextOverlay = Overlays.getOverlayAtPoint({x: overlayLocationX, y: locationY }); + Overlays.editOverlay(notifications[i], { x:overlayLocationX, y:locationY}); + Overlays.editOverlay(buttons[i], { x:buttonLocationX, y:locationY + 12.0}); + locationY=locationY + arrays[i][3]; + } + } + + // This checks the age of the notification and prepares to fade it after 9.0 seconds (var persistTime - 1) + for (var i = 0; i < arrays.length; i++){ + if (ready){ + var j = arrays[i][2]; + var k = j + persistTime; + if (k < (new Date().getTime() / 1000)){ + ready = false; + noticeOut = arrays[i][0]; + buttonOut = arrays[i][1]; + var arraysOut = i; + fadeOut(noticeOut, buttonOut, arraysOut); + } + } + } +} + +// this fades the notification ready for dismissal, and removes it from the arrays +function fadeOut(noticeOut, buttonOut, arraysOut){ + var myLength = arrays.length; + var r = 9.0; + var pauseTimer = null; + pauseTimer = Script.setInterval(function() { + r--; + rFade = r / 10.0; + Overlays.editOverlay(noticeOut, {alpha: rFade}); + Overlays.editOverlay(buttonOut, {alpha: rFade}); + if (r < 0) { + dismiss(noticeOut, buttonOut, arraysOut); + arrays.splice(arraysOut, 1); + ready = true; + Script.clearInterval(pauseTimer); + } + }, 20); +} + +// This handles the final dismissal of a notification after fading +function dismiss(firstNoteOut, firstButOut, firstOut){ +var working = firstOut + Overlays.deleteOverlay(firstNoteOut); + Overlays.deleteOverlay(firstButOut); + notifications.splice(firstOut, 1); + buttons.splice(firstOut, 1); + times.splice(firstOut, 1); + heights.splice(firstOut, 1); + myAlpha.splice(firstOut,1); + +} + +onMuteStateChanged(); +AudioDevice.muteToggled.connect(onMuteStateChanged); +Controller.keyPressEvent.connect(keyPressEvent); +Controller.mousePressEvent.connect(mousePressEvent); +GlobalServices.onlineUsersChanged.connect(onOnlineUsersChanged); +GlobalServices.incomingMessage.connect(onIncomingMessage); +Controller.keyReleaseEvent.connect(keyReleaseEvent); +Script.update.connect(update); From 764ad724711e6cd5285af19a34b48e0afec2afd2 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 20 Nov 2014 09:54:41 -0800 Subject: [PATCH 02/24] adding the light map support from FBX --- .../resources/shaders/model_normal_map.frag | 2 +- interface/src/ModelUploader.cpp | 8 + interface/src/renderer/GeometryCache.cpp | 28 +- interface/src/renderer/GeometryCache.h | 4 +- interface/src/renderer/Model.cpp | 520 +++++++++++++----- interface/src/renderer/Model.h | 58 +- interface/src/renderer/TextureCache.h | 4 +- libraries/fbx/src/FBXReader.cpp | 37 ++ libraries/fbx/src/FBXReader.h | 2 + 9 files changed, 525 insertions(+), 138 deletions(-) diff --git a/interface/resources/shaders/model_normal_map.frag b/interface/resources/shaders/model_normal_map.frag index f5a1047b2b..af107e9d3c 100644 --- a/interface/resources/shaders/model_normal_map.frag +++ b/interface/resources/shaders/model_normal_map.frag @@ -4,7 +4,7 @@ // model_normal_map.frag // fragment shader // -// Created by Andrzej Kapolka on 10/29/13. +// Created by Andrzej Kapolka on 10/14/13. // Copyright 2013 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index 2599f39e83..d9e8ed0c40 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -522,6 +522,14 @@ bool ModelUploader::addTextures(const QString& texdir, const FBXGeometry& geomet } _textureFilenames.insert(part.specularTexture.filename); } + if (!part.emissiveTexture.filename.isEmpty() && part.emissiveTexture.content.isEmpty() && + !_textureFilenames.contains(part.emissiveTexture.filename)) { + if (!addPart(texdir + "/" + part.emissiveTexture.filename, + QString("texture%1").arg(++_texturesCount), true)) { + return false; + } + _textureFilenames.insert(part.emissiveTexture.filename); + } } } diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 9052ec910f..cca0d120c2 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -575,7 +575,8 @@ bool NetworkGeometry::isLoadedWithTextures() const { foreach (const NetworkMeshPart& part, mesh.parts) { if ((part.diffuseTexture && !part.diffuseTexture->isLoaded()) || (part.normalTexture && !part.normalTexture->isLoaded()) || - (part.specularTexture && !part.specularTexture->isLoaded())) { + (part.specularTexture && !part.specularTexture->isLoaded()) || + (part.emissiveTexture && !part.emissiveTexture->isLoaded())) { return false; } } @@ -668,6 +669,9 @@ void NetworkGeometry::setLoadPriority(const QPointer& owner, float prio if (part.specularTexture) { part.specularTexture->setLoadPriority(owner, priority); } + if (part.emissiveTexture) { + part.emissiveTexture->setLoadPriority(owner, priority); + } } } } @@ -688,6 +692,9 @@ void NetworkGeometry::setLoadPriorities(const QHash, float>& p if (part.specularTexture) { part.specularTexture->setLoadPriorities(priorities); } + if (part.emissiveTexture) { + part.emissiveTexture->setLoadPriorities(priorities); + } } } } @@ -708,6 +715,9 @@ void NetworkGeometry::clearLoadPriority(const QPointer& owner) { if (part.specularTexture) { part.specularTexture->clearLoadPriority(owner); } + if (part.emissiveTexture) { + part.emissiveTexture->clearLoadPriority(owner); + } } } } @@ -733,6 +743,10 @@ void NetworkGeometry::setTextureWithNameToURL(const QString& name, const QUrl& u part.specularTexture = Application::getInstance()->getTextureCache()->getTexture(url, DEFAULT_TEXTURE, false, QByteArray()); part.specularTexture->setLoadPriorities(_loadPriorities); + } else if (part.emissiveTextureName == name) { + part.emissiveTexture = Application::getInstance()->getTextureCache()->getTexture(url, DEFAULT_TEXTURE, + false, QByteArray()); + part.emissiveTexture->setLoadPriorities(_loadPriorities); } } } @@ -764,6 +778,11 @@ QStringList NetworkGeometry::getTextureNames() const { QString textureURL = part.specularTexture->getURL().toString(); result << part.specularTextureName + ":" + textureURL; } + + if (!part.emissiveTextureName.isEmpty()) { + QString textureURL = part.emissiveTexture->getURL().toString(); + result << part.emissiveTextureName + ":" + textureURL; + } } } return result; @@ -911,6 +930,13 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { networkPart.specularTextureName = part.specularTexture.name; networkPart.specularTexture->setLoadPriorities(_loadPriorities); } + if (!part.emissiveTexture.filename.isEmpty()) { + networkPart.emissiveTexture = Application::getInstance()->getTextureCache()->getTexture( + _textureBase.resolved(QUrl(part.emissiveTexture.filename)), EMISSIVE_TEXTURE, + false, part.emissiveTexture.content); + networkPart.emissiveTextureName = part.emissiveTexture.name; + networkPart.emissiveTexture->setLoadPriorities(_loadPriorities); + } networkMesh.parts.append(networkPart); totalIndices += (part.quadIndices.size() + part.triangleIndices.size()); diff --git a/interface/src/renderer/GeometryCache.h b/interface/src/renderer/GeometryCache.h index e58177533c..6faad93fe4 100644 --- a/interface/src/renderer/GeometryCache.h +++ b/interface/src/renderer/GeometryCache.h @@ -155,7 +155,9 @@ public: QSharedPointer normalTexture; QString specularTextureName; QSharedPointer specularTexture; - + QString emissiveTextureName; + QSharedPointer emissiveTexture; + bool isTranslucent() const; }; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index fc3845d94f..c3e21aea7c 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -70,6 +70,11 @@ ProgramObject Model::_specularMapProgram; ProgramObject Model::_normalSpecularMapProgram; ProgramObject Model::_translucentProgram; +ProgramObject Model::_emissiveProgram; +ProgramObject Model::_emissiveNormalMapProgram; +ProgramObject Model::_emissiveSpecularMapProgram; +ProgramObject Model::_emissiveNormalSpecularMapProgram; + ProgramObject Model::_shadowProgram; ProgramObject Model::_skinProgram; @@ -78,6 +83,11 @@ ProgramObject Model::_skinSpecularMapProgram; ProgramObject Model::_skinNormalSpecularMapProgram; ProgramObject Model::_skinTranslucentProgram; +ProgramObject Model::_skinEmissiveProgram; +ProgramObject Model::_skinEmissiveNormalMapProgram; +ProgramObject Model::_skinEmissiveSpecularMapProgram; +ProgramObject Model::_skinEmissiveNormalSpecularMapProgram; + ProgramObject Model::_skinShadowProgram; Model::Locations Model::_locations; @@ -86,6 +96,11 @@ Model::Locations Model::_specularMapLocations; Model::Locations Model::_normalSpecularMapLocations; Model::Locations Model::_translucentLocations; +Model::Locations Model::_emissiveLocations; +Model::Locations Model::_emissiveNormalMapLocations; +Model::Locations Model::_emissiveSpecularMapLocations; +Model::Locations Model::_emissiveNormalSpecularMapLocations; + Model::SkinLocations Model::_skinLocations; Model::SkinLocations Model::_skinNormalMapLocations; Model::SkinLocations Model::_skinSpecularMapLocations; @@ -93,6 +108,11 @@ Model::SkinLocations Model::_skinNormalSpecularMapLocations; Model::SkinLocations Model::_skinShadowLocations; Model::SkinLocations Model::_skinTranslucentLocations; +Model::SkinLocations Model::_skinEmissiveLocations; +Model::SkinLocations Model::_skinEmissiveNormalMapLocations; +Model::SkinLocations Model::_skinEmissiveSpecularMapLocations; +Model::SkinLocations Model::_skinEmissiveNormalSpecularMapLocations; + void Model::setScale(const glm::vec3& scale) { setScaleInternal(scale); // if anyone sets scale manually, then we are no longer scaled to fit @@ -268,6 +288,39 @@ void Model::init() { _translucentProgram.link(); initProgram(_translucentProgram, _translucentLocations); + + // Emissive + _emissiveProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model.vert"); + _emissiveProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_emissive.frag"); + _emissiveProgram.link(); + + initProgram(_emissiveProgram, _emissiveLocations); + + _emissiveNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model_normal_map.vert"); + _emissiveNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_emissive_normal_map.frag"); + _emissiveNormalMapProgram.link(); + + initProgram(_emissiveNormalMapProgram, _emissiveNormalMapLocations); + + _emissiveSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model.vert"); + _emissiveSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_emissive_specular_map.frag"); + _emissiveSpecularMapProgram.link(); + + initProgram(_emissiveSpecularMapProgram, _emissiveSpecularMapLocations); + + _emissiveNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model_normal_map.vert"); + _emissiveNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_emissive_normal_specular_map.frag"); + _emissiveNormalSpecularMapProgram.link(); + + initProgram(_emissiveNormalSpecularMapProgram, _emissiveNormalSpecularMapLocations, 2); + // end emissive + _shadowProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_shadow.vert"); _shadowProgram.addShaderFromSourceFile(QGLShader::Fragment, @@ -319,6 +372,38 @@ void Model::init() { _skinTranslucentProgram.link(); initSkinProgram(_skinTranslucentProgram, _skinTranslucentLocations); + + + _skinEmissiveProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/skin_model.vert"); + _skinEmissiveProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_emissive.frag"); + _skinEmissiveProgram.link(); + + initSkinProgram(_skinEmissiveProgram, _skinEmissiveLocations); + + _skinEmissiveNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/skin_model_normal_map.vert"); + _skinEmissiveNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_emissive_normal_map.frag"); + _skinEmissiveNormalMapProgram.link(); + + initSkinProgram(_skinEmissiveNormalMapProgram, _skinEmissiveNormalMapLocations); + + _skinEmissiveSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/skin_model.vert"); + _skinEmissiveSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_emissive_specular_map.frag"); + _skinEmissiveSpecularMapProgram.link(); + + initSkinProgram(_skinEmissiveSpecularMapProgram, _skinEmissiveSpecularMapLocations); + + _skinEmissiveNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/skin_model_normal_map.vert"); + _skinEmissiveNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_emissive_normal_specular_map.frag"); + _skinEmissiveNormalSpecularMapProgram.link(); + + initSkinProgram(_skinEmissiveNormalSpecularMapProgram, _skinEmissiveNormalSpecularMapLocations, 2); + } } @@ -621,14 +706,23 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { //renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, book isSkinned, args); int opaqueMeshPartsRendered = 0; - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, true, args); + + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, true, args); // render translucent meshes afterwards //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); @@ -642,14 +736,14 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { int translucentMeshPartsRendered = 0; const float MOSTLY_OPAQUE_THRESHOLD = 0.75f; - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args); GLBATCH(glDisable)(GL_ALPHA_TEST); GLBATCH(glEnable)(GL_BLEND); @@ -666,14 +760,14 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, args); } GLBATCH(glDepthMask)(true); @@ -1562,15 +1656,24 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { 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, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, args); - + /* opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, true, args); +*/ + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, true, args); + // render translucent meshes afterwards //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); { @@ -1583,15 +1686,15 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { int translucentParts = 0; const float MOSTLY_OPAQUE_THRESHOLD = 0.75f; - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, true, args); - + /* translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args); + */ GLBATCH(glDisable)(GL_ALPHA_TEST); GLBATCH(glEnable)(GL_BLEND); GLBATCH(glDepthMask)(false); @@ -1607,15 +1710,15 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, true, args); - } + /* translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, args); + */ } GLBATCH(glDepthMask)(true); GLBATCH(glDepthFunc)(GL_LESS); @@ -1689,7 +1792,17 @@ void Model::segregateMeshGroups() { _meshesOpaqueSkinned.clear(); _meshesOpaqueTangentsSpecularSkinned.clear(); _meshesOpaqueSpecularSkinned.clear(); - + + _meshesOpaqueEmissiveTangents.clear(); + _meshesOpaqueEmissive.clear(); + _meshesOpaqueEmissiveTangentsSpecular.clear(); + _meshesOpaqueEmissiveSpecular.clear(); + + _meshesOpaqueEmissiveTangentsSkinned.clear(); + _meshesOpaqueEmissiveSkinned.clear(); + _meshesOpaqueEmissiveTangentsSpecularSkinned.clear(); + _meshesOpaqueEmissiveSpecularSkinned.clear(); + _unsortedMeshesTranslucentTangents.clear(); _unsortedMeshesTranslucent.clear(); _unsortedMeshesTranslucentTangentsSpecular.clear(); @@ -1710,6 +1823,16 @@ void Model::segregateMeshGroups() { _unsortedMeshesOpaqueTangentsSpecularSkinned.clear(); _unsortedMeshesOpaqueSpecularSkinned.clear(); + _unsortedMeshesOpaqueEmissiveTangents.clear(); + _unsortedMeshesOpaqueEmissive.clear(); + _unsortedMeshesOpaqueEmissiveTangentsSpecular.clear(); + _unsortedMeshesOpaqueEmissiveSpecular.clear(); + + _unsortedMeshesOpaqueEmissiveTangentsSkinned.clear(); + _unsortedMeshesOpaqueEmissiveSkinned.clear(); + _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned.clear(); + _unsortedMeshesOpaqueEmissiveSpecularSkinned.clear(); + const FBXGeometry& geometry = _geometry->getFBXGeometry(); const QVector& networkMeshes = _geometry->getMeshes(); @@ -1723,6 +1846,7 @@ void Model::segregateMeshGroups() { bool translucentMesh = networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size(); bool hasTangents = !mesh.tangents.isEmpty(); bool hasSpecular = mesh.hasSpecularTexture(); + bool hasEmissive = mesh.hasEmissiveTexture(); bool isSkinned = state.clusterMatrices.size() > 1; QString materialID; @@ -1741,71 +1865,108 @@ void Model::segregateMeshGroups() { qDebug() << "materialID:" << materialID << "parts:" << mesh.parts.size(); } - if (translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { + if ( !hasEmissive) { + if (translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { - _unsortedMeshesTranslucent.insertMulti(materialID, i); + _unsortedMeshesTranslucent.insertMulti(materialID, i); - } else if (translucentMesh && hasTangents && !hasSpecular && !isSkinned) { + } else if (translucentMesh && hasTangents && !hasSpecular && !isSkinned) { - _unsortedMeshesTranslucentTangents.insertMulti(materialID, i); + _unsortedMeshesTranslucentTangents.insertMulti(materialID, i); - } else if (translucentMesh && hasTangents && hasSpecular && !isSkinned) { + } else if (translucentMesh && hasTangents && hasSpecular && !isSkinned) { - _unsortedMeshesTranslucentTangentsSpecular.insertMulti(materialID, i); + _unsortedMeshesTranslucentTangentsSpecular.insertMulti(materialID, i); - } else if (translucentMesh && !hasTangents && hasSpecular && !isSkinned) { + } else if (translucentMesh && !hasTangents && hasSpecular && !isSkinned) { - _unsortedMeshesTranslucentSpecular.insertMulti(materialID, i); + _unsortedMeshesTranslucentSpecular.insertMulti(materialID, i); - } else if (translucentMesh && hasTangents && !hasSpecular && isSkinned) { + } else if (translucentMesh && hasTangents && !hasSpecular && isSkinned) { - _unsortedMeshesTranslucentTangentsSkinned.insertMulti(materialID, i); + _unsortedMeshesTranslucentTangentsSkinned.insertMulti(materialID, i); - } else if (translucentMesh && !hasTangents && !hasSpecular && isSkinned) { + } else if (translucentMesh && !hasTangents && !hasSpecular && isSkinned) { - _unsortedMeshesTranslucentSkinned.insertMulti(materialID, i); + _unsortedMeshesTranslucentSkinned.insertMulti(materialID, i); - } else if (translucentMesh && hasTangents && hasSpecular && isSkinned) { + } else if (translucentMesh && hasTangents && hasSpecular && isSkinned) { - _unsortedMeshesTranslucentTangentsSpecularSkinned.insertMulti(materialID, i); + _unsortedMeshesTranslucentTangentsSpecularSkinned.insertMulti(materialID, i); - } else if (translucentMesh && !hasTangents && hasSpecular && isSkinned) { + } else if (translucentMesh && !hasTangents && hasSpecular && isSkinned) { - _unsortedMeshesTranslucentSpecularSkinned.insertMulti(materialID, i); + _unsortedMeshesTranslucentSpecularSkinned.insertMulti(materialID, i); - } else if (!translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { + } else if (!translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { - _unsortedMeshesOpaque.insertMulti(materialID, i); + _unsortedMeshesOpaque.insertMulti(materialID, i); - } else if (!translucentMesh && hasTangents && !hasSpecular && !isSkinned) { + } else if (!translucentMesh && hasTangents && !hasSpecular && !isSkinned) { - _unsortedMeshesOpaqueTangents.insertMulti(materialID, i); + _unsortedMeshesOpaqueTangents.insertMulti(materialID, i); - } else if (!translucentMesh && hasTangents && hasSpecular && !isSkinned) { + } else if (!translucentMesh && hasTangents && hasSpecular && !isSkinned) { - _unsortedMeshesOpaqueTangentsSpecular.insertMulti(materialID, i); + _unsortedMeshesOpaqueTangentsSpecular.insertMulti(materialID, i); - } else if (!translucentMesh && !hasTangents && hasSpecular && !isSkinned) { + } else if (!translucentMesh && !hasTangents && hasSpecular && !isSkinned) { - _unsortedMeshesOpaqueSpecular.insertMulti(materialID, i); + _unsortedMeshesOpaqueSpecular.insertMulti(materialID, i); - } else if (!translucentMesh && hasTangents && !hasSpecular && isSkinned) { + } else if (!translucentMesh && hasTangents && !hasSpecular && isSkinned) { - _unsortedMeshesOpaqueTangentsSkinned.insertMulti(materialID, i); + _unsortedMeshesOpaqueTangentsSkinned.insertMulti(materialID, i); - } else if (!translucentMesh && !hasTangents && !hasSpecular && isSkinned) { + } else if (!translucentMesh && !hasTangents && !hasSpecular && isSkinned) { - _unsortedMeshesOpaqueSkinned.insertMulti(materialID, i); + _unsortedMeshesOpaqueSkinned.insertMulti(materialID, i); - } else if (!translucentMesh && hasTangents && hasSpecular && isSkinned) { + } else if (!translucentMesh && hasTangents && hasSpecular && isSkinned) { - _unsortedMeshesOpaqueTangentsSpecularSkinned.insertMulti(materialID, i); + _unsortedMeshesOpaqueTangentsSpecularSkinned.insertMulti(materialID, i); - } else if (!translucentMesh && !hasTangents && hasSpecular && isSkinned) { + } else if (!translucentMesh && !hasTangents && hasSpecular && isSkinned) { - _unsortedMeshesOpaqueSpecularSkinned.insertMulti(materialID, i); + _unsortedMeshesOpaqueSpecularSkinned.insertMulti(materialID, i); + } else { + qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???"; + } } else { - qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???"; + if (!translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { + + _unsortedMeshesOpaqueEmissive.insertMulti(materialID, i); + + } else if (!translucentMesh && hasTangents && !hasSpecular && !isSkinned) { + + _unsortedMeshesOpaqueEmissiveTangents.insertMulti(materialID, i); + + } else if (!translucentMesh && hasTangents && hasSpecular && !isSkinned) { + + _unsortedMeshesOpaqueEmissiveTangentsSpecular.insertMulti(materialID, i); + + } else if (!translucentMesh && !hasTangents && hasSpecular && !isSkinned) { + + _unsortedMeshesOpaqueEmissiveSpecular.insertMulti(materialID, i); + + } else if (!translucentMesh && hasTangents && !hasSpecular && isSkinned) { + + _unsortedMeshesOpaqueEmissiveTangentsSkinned.insertMulti(materialID, i); + + } else if (!translucentMesh && !hasTangents && !hasSpecular && isSkinned) { + + _unsortedMeshesOpaqueEmissiveSkinned.insertMulti(materialID, i); + + } else if (!translucentMesh && hasTangents && hasSpecular && isSkinned) { + + _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned.insertMulti(materialID, i); + + } else if (!translucentMesh && !hasTangents && hasSpecular && isSkinned) { + + _unsortedMeshesOpaqueEmissiveSpecularSkinned.insertMulti(materialID, i); + } else { + qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???"; + } } } @@ -1873,6 +2034,38 @@ void Model::segregateMeshGroups() { _meshesOpaqueSpecularSkinned.append(i); } + foreach(int i, _unsortedMeshesOpaqueEmissive) { + _meshesOpaqueEmissive.append(i); + } + + foreach(int i, _unsortedMeshesOpaqueEmissiveTangents) { + _meshesOpaqueEmissiveTangents.append(i); + } + + foreach(int i, _unsortedMeshesOpaqueEmissiveTangentsSpecular) { + _meshesOpaqueEmissiveTangentsSpecular.append(i); + } + + foreach(int i, _unsortedMeshesOpaqueEmissiveSpecular) { + _meshesOpaqueEmissiveSpecular.append(i); + } + + foreach(int i, _unsortedMeshesOpaqueEmissiveSkinned) { + _meshesOpaqueEmissiveSkinned.append(i); + } + + foreach(int i, _unsortedMeshesOpaqueEmissiveTangentsSkinned) { + _meshesOpaqueEmissiveTangentsSkinned.append(i); + } + + foreach(int i, _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned) { + _meshesOpaqueEmissiveTangentsSpecularSkinned.append(i); + } + + foreach(int i, _unsortedMeshesOpaqueEmissiveSpecularSkinned) { + _meshesOpaqueEmissiveSpecularSkinned.append(i); + } + _unsortedMeshesTranslucentTangents.clear(); _unsortedMeshesTranslucent.clear(); _unsortedMeshesTranslucentTangentsSpecular.clear(); @@ -1893,10 +2086,20 @@ void Model::segregateMeshGroups() { _unsortedMeshesOpaqueTangentsSpecularSkinned.clear(); _unsortedMeshesOpaqueSpecularSkinned.clear(); + _unsortedMeshesOpaqueEmissiveTangents.clear(); + _unsortedMeshesOpaqueEmissive.clear(); + _unsortedMeshesOpaqueEmissiveTangentsSpecular.clear(); + _unsortedMeshesOpaqueEmissiveSpecular.clear(); + + _unsortedMeshesOpaqueEmissiveTangentsSkinned.clear(); + _unsortedMeshesOpaqueEmissiveSkinned.clear(); + _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned.clear(); + _unsortedMeshesOpaqueEmissiveSpecularSkinned.clear(); + _meshGroupsKnown = true; } -QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned) { +QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned) { PROFILE_RANGE(__FUNCTION__); // depending on which parameters we were called with, pick the correct mesh group to render @@ -1917,22 +2120,41 @@ QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool h whichList = &_meshesTranslucentTangentsSpecularSkinned; } else if (translucent && !hasTangents && hasSpecular && isSkinned) { whichList = &_meshesTranslucentSpecularSkinned; - } else if (!translucent && !hasTangents && !hasSpecular && !isSkinned) { + + } else if (!translucent && !hasEmissive && !hasTangents && !hasSpecular && !isSkinned) { whichList = &_meshesOpaque; - } else if (!translucent && hasTangents && !hasSpecular && !isSkinned) { + } else if (!translucent && !hasEmissive && hasTangents && !hasSpecular && !isSkinned) { whichList = &_meshesOpaqueTangents; - } else if (!translucent && hasTangents && hasSpecular && !isSkinned) { + } else if (!translucent && !hasEmissive && hasTangents && hasSpecular && !isSkinned) { whichList = &_meshesOpaqueTangentsSpecular; - } else if (!translucent && !hasTangents && hasSpecular && !isSkinned) { + } else if (!translucent && !hasEmissive && !hasTangents && hasSpecular && !isSkinned) { whichList = &_meshesOpaqueSpecular; - } else if (!translucent && hasTangents && !hasSpecular && isSkinned) { + } else if (!translucent && !hasEmissive && hasTangents && !hasSpecular && isSkinned) { whichList = &_meshesOpaqueTangentsSkinned; - } else if (!translucent && !hasTangents && !hasSpecular && isSkinned) { + } else if (!translucent && !hasEmissive && !hasTangents && !hasSpecular && isSkinned) { whichList = &_meshesOpaqueSkinned; - } else if (!translucent && hasTangents && hasSpecular && isSkinned) { + } else if (!translucent && !hasEmissive && hasTangents && hasSpecular && isSkinned) { whichList = &_meshesOpaqueTangentsSpecularSkinned; - } else if (!translucent && !hasTangents && hasSpecular && isSkinned) { + } else if (!translucent && !hasEmissive && !hasTangents && hasSpecular && isSkinned) { whichList = &_meshesOpaqueSpecularSkinned; + + } else if (!translucent && hasEmissive && !hasTangents && !hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueEmissive; + } else if (!translucent && hasEmissive && hasTangents && !hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueEmissiveTangents; + } else if (!translucent && hasEmissive && hasTangents && hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueEmissiveTangentsSpecular; + } else if (!translucent && hasEmissive && !hasTangents && hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueEmissiveSpecular; + } else if (!translucent && hasEmissive && hasTangents && !hasSpecular && isSkinned) { + whichList = &_meshesOpaqueEmissiveTangentsSkinned; + } else if (!translucent && hasEmissive && !hasTangents && !hasSpecular && isSkinned) { + whichList = &_meshesOpaqueEmissiveSkinned; + } else if (!translucent && hasEmissive && hasTangents && hasSpecular && isSkinned) { + whichList = &_meshesOpaqueEmissiveTangentsSpecularSkinned; + } else if (!translucent && hasEmissive && !hasTangents && hasSpecular && isSkinned) { + whichList = &_meshesOpaqueEmissiveSpecularSkinned; + } else { qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???"; } @@ -1940,14 +2162,15 @@ QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool h } void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, - SkinLocations*& skinLocations, GLenum& specularTextureUnit) { + bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, + SkinLocations*& skinLocations, GLenum& specularTextureUnit, GLenum& emissiveTextureUnit) { ProgramObject* program = &_program; Locations* locations = &_locations; ProgramObject* skinProgram = &_skinProgram; skinLocations = &_skinLocations; specularTextureUnit = 0; + emissiveTextureUnit = 0; if (mode == SHADOW_RENDER_MODE) { program = &_shadowProgram; skinProgram = &_skinShadowProgram; @@ -1958,27 +2181,59 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f skinProgram = &_skinTranslucentProgram; skinLocations = &_skinTranslucentLocations; - } else if (hasTangents) { - if (hasSpecular) { - program = &_normalSpecularMapProgram; - locations = &_normalSpecularMapLocations; - skinProgram = &_skinNormalSpecularMapProgram; - skinLocations = &_skinNormalSpecularMapLocations; - specularTextureUnit = GL_TEXTURE2; + } else if (hasEmissive) { + if (hasTangents) { + if (hasSpecular) { + program = &_emissiveNormalSpecularMapProgram; + locations = &_emissiveNormalSpecularMapLocations; + skinProgram = &_skinEmissiveNormalSpecularMapProgram; + skinLocations = &_skinEmissiveNormalSpecularMapLocations; + specularTextureUnit = GL_TEXTURE2; + emissiveTextureUnit = GL_TEXTURE3; + } else { + program = &_emissiveNormalMapProgram; + locations = &_emissiveNormalMapLocations; + skinProgram = &_skinEmissiveNormalMapProgram; + skinLocations = &_skinEmissiveNormalMapLocations; + emissiveTextureUnit = GL_TEXTURE3; + } + } else if (hasSpecular) { + program = &_emissiveSpecularMapProgram; + locations = &_emissiveSpecularMapLocations; + skinProgram = &_skinEmissiveSpecularMapProgram; + skinLocations = &_skinEmissiveSpecularMapLocations; + specularTextureUnit = GL_TEXTURE1; + emissiveTextureUnit = GL_TEXTURE3; } else { - program = &_normalMapProgram; - locations = &_normalMapLocations; - skinProgram = &_skinNormalMapProgram; - skinLocations = &_skinNormalMapLocations; + program = &_emissiveProgram; + locations = &_emissiveLocations; + skinProgram = &_skinEmissiveProgram; + skinLocations = &_skinEmissiveLocations; + emissiveTextureUnit = GL_TEXTURE3; } - } else if (hasSpecular) { - program = &_specularMapProgram; - locations = &_specularMapLocations; - skinProgram = &_skinSpecularMapProgram; - skinLocations = &_skinSpecularMapLocations; - specularTextureUnit = GL_TEXTURE1; - } - + } else { + if (hasTangents) { + if (hasSpecular) { + program = &_normalSpecularMapProgram; + locations = &_normalSpecularMapLocations; + skinProgram = &_skinNormalSpecularMapProgram; + skinLocations = &_skinNormalSpecularMapLocations; + specularTextureUnit = GL_TEXTURE2; + } else { + program = &_normalMapProgram; + locations = &_normalMapLocations; + skinProgram = &_skinNormalMapProgram; + skinLocations = &_skinNormalMapLocations; + } + } else if (hasSpecular) { + program = &_specularMapProgram; + locations = &_specularMapLocations; + skinProgram = &_skinSpecularMapProgram; + skinLocations = &_skinSpecularMapLocations; + specularTextureUnit = GL_TEXTURE1; + } + } + ProgramObject* activeProgram = program; Locations* activeLocations = locations; @@ -1996,7 +2251,7 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f } int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { + bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); int meshPartsRendered = 0; @@ -2004,18 +2259,19 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool bool pickProgramsNeeded = true; SkinLocations* skinLocations; GLenum specularTextureUnit; + GLenum emissiveTextureUnit; foreach(Model* model, _modelsInScene) { - QVector* whichList = model->pickMeshList(translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned); + QVector* whichList = model->pickMeshList(translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned); if (whichList) { QVector& list = *whichList; if (list.size() > 0) { if (pickProgramsNeeded) { - pickPrograms(batch, mode, translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit); + pickPrograms(batch, mode, translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit, emissiveTextureUnit); pickProgramsNeeded = false; } model->setupBatchTransform(batch); - meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit); + meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit, emissiveTextureUnit); GLBATCH(glPopMatrix)(); } } @@ -2028,12 +2284,12 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool } int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { + bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); int meshPartsRendered = 0; - QVector* whichList = pickMeshList(translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned); + QVector* whichList = pickMeshList(translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned); if (!whichList) { qDebug() << "unexpected!!! we don't know which list of meshes to render..."; @@ -2048,8 +2304,9 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl SkinLocations* skinLocations; GLenum specularTextureUnit; - pickPrograms(batch, mode, translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit); - meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit); + GLenum emissiveTextureUnit; + pickPrograms(batch, mode, translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit, emissiveTextureUnit); + meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit, emissiveTextureUnit); GLBATCH(glUseProgram)(0); return meshPartsRendered; @@ -2057,7 +2314,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args, - SkinLocations* skinLocations, GLenum specularTextureUnit) { + SkinLocations* skinLocations, GLenum specularTextureUnit, GLenum emissiveTextureUnit) { PROFILE_RANGE(__FUNCTION__); bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts); bool cullTooSmallMeshParts = !Menu::getInstance()->isOptionChecked(MenuOption::DontCullTooSmallMeshParts); @@ -2198,6 +2455,15 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod Application::getInstance()->getTextureCache()->getWhiteTextureID() : specularMap->getID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } + + if (emissiveTextureUnit) { + GLBATCH(glActiveTexture)(emissiveTextureUnit); + Texture* emissiveMap = networkPart.emissiveTexture.data(); + GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ? + Application::getInstance()->getTextureCache()->getWhiteTextureID() : emissiveMap->getID()); + GLBATCH(glActiveTexture)(GL_TEXTURE0); + } + if (args) { args->_materialSwitches++; } @@ -2238,6 +2504,12 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glActiveTexture)(GL_TEXTURE0); } + if (emissiveTextureUnit) { + GLBATCH(glActiveTexture)(emissiveTextureUnit); + GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); + GLBATCH(glActiveTexture)(GL_TEXTURE0); + } + GLBATCH(glPopMatrix)(); } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 4dceb07655..c1ae190a1e 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -303,7 +303,12 @@ private: static ProgramObject _specularMapProgram; static ProgramObject _normalSpecularMapProgram; static ProgramObject _translucentProgram; - + + static ProgramObject _emissiveProgram; + static ProgramObject _emissiveNormalMapProgram; + static ProgramObject _emissiveSpecularMapProgram; + static ProgramObject _emissiveNormalSpecularMapProgram; + static ProgramObject _shadowProgram; static ProgramObject _skinProgram; @@ -311,7 +316,12 @@ private: static ProgramObject _skinSpecularMapProgram; static ProgramObject _skinNormalSpecularMapProgram; static ProgramObject _skinTranslucentProgram; - + + static ProgramObject _skinEmissiveProgram; + static ProgramObject _skinEmissiveNormalMapProgram; + static ProgramObject _skinEmissiveSpecularMapProgram; + static ProgramObject _skinEmissiveNormalSpecularMapProgram; + static ProgramObject _skinShadowProgram; static int _normalMapTangentLocation; @@ -328,6 +338,11 @@ private: static Locations _specularMapLocations; static Locations _normalSpecularMapLocations; static Locations _translucentLocations; + + static Locations _emissiveLocations; + static Locations _emissiveNormalMapLocations; + static Locations _emissiveSpecularMapLocations; + static Locations _emissiveNormalSpecularMapLocations; static void initProgram(ProgramObject& program, Locations& locations, int specularTextureUnit = 1); @@ -344,7 +359,12 @@ private: static SkinLocations _skinNormalSpecularMapLocations; static SkinLocations _skinShadowLocations; static SkinLocations _skinTranslucentLocations; - + + static SkinLocations _skinEmissiveLocations; + static SkinLocations _skinEmissiveNormalMapLocations; + static SkinLocations _skinEmissiveSpecularMapLocations; + static SkinLocations _skinEmissiveNormalSpecularMapLocations; + static void initSkinProgram(ProgramObject& program, SkinLocations& locations, int specularTextureUnit = 1); QVector _calculatedMeshBoxes; @@ -376,6 +396,16 @@ private: QMap _unsortedMeshesOpaqueTangentsSpecularSkinned; QMap _unsortedMeshesOpaqueSpecularSkinned; + QMap _unsortedMeshesOpaqueEmissive; + QMap _unsortedMeshesOpaqueEmissiveTangents; + QMap _unsortedMeshesOpaqueEmissiveTangentsSpecular; + QMap _unsortedMeshesOpaqueEmissiveSpecular; + + QMap _unsortedMeshesOpaqueEmissiveSkinned; + QMap _unsortedMeshesOpaqueEmissiveTangentsSkinned; + QMap _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned; + QMap _unsortedMeshesOpaqueEmissiveSpecularSkinned; + QVector _meshesTranslucent; QVector _meshesTranslucentTangents; QVector _meshesTranslucentTangentsSpecular; @@ -396,6 +426,16 @@ private: QVector _meshesOpaqueTangentsSpecularSkinned; QVector _meshesOpaqueSpecularSkinned; + QVector _meshesOpaqueEmissive; + QVector _meshesOpaqueEmissiveTangents; + QVector _meshesOpaqueEmissiveTangentsSpecular; + QVector _meshesOpaqueEmissiveSpecular; + + QVector _meshesOpaqueEmissiveSkinned; + QVector _meshesOpaqueEmissiveTangentsSkinned; + QVector _meshesOpaqueEmissiveTangentsSpecularSkinned; + QVector _meshesOpaqueEmissiveSpecularSkinned; + // Scene rendering support static QVector _modelsInScene; static gpu::Batch _sceneRenderBatch; @@ -407,19 +447,19 @@ private: void renderSetup(RenderArgs* args); bool renderCore(float alpha, RenderMode mode, RenderArgs* args); int renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL); + bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL); void setupBatchTransform(gpu::Batch& batch); - QVector* pickMeshList(bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned); + QVector* pickMeshList(bool translucent, float alphaThreshold, bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned); int renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - RenderArgs* args, SkinLocations* skinLocations, GLenum specularTextureUnit); + RenderArgs* args, SkinLocations* skinLocations, GLenum specularTextureUnit, GLenum emissiveTextureUnit); static void pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, - SkinLocations*& skinLocations, GLenum& specularTextureUnit); + bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, + SkinLocations*& skinLocations, GLenum& specularTextureUnit, GLenum& emissiveTextureUnit); static int renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args); + bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args); }; diff --git a/interface/src/renderer/TextureCache.h b/interface/src/renderer/TextureCache.h index fd9131fe23..66734da9cd 100644 --- a/interface/src/renderer/TextureCache.h +++ b/interface/src/renderer/TextureCache.h @@ -25,7 +25,7 @@ class NetworkTexture; typedef QSharedPointer NetworkTexturePointer; -enum TextureType { DEFAULT_TEXTURE, NORMAL_TEXTURE, SPECULAR_TEXTURE, SPLAT_TEXTURE }; +enum TextureType { DEFAULT_TEXTURE, NORMAL_TEXTURE, SPECULAR_TEXTURE, EMISSIVE_TEXTURE, SPLAT_TEXTURE }; /// Stores cached textures, including render-to-texture targets. class TextureCache : public ResourceCache { @@ -67,7 +67,7 @@ public: /// Returns the ID of the primary framebuffer object's specular texture. GLuint getPrimarySpecularTextureID(); - + /// Enables or disables draw buffers on the primary framebuffer. Note: the primary framebuffer must be bound. void setPrimaryDrawBuffers(bool color, bool normal = false, bool specular = false); diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 4ffd3f6286..7c71bd6c15 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -41,6 +41,15 @@ bool FBXMesh::hasSpecularTexture() const { return false; } +bool FBXMesh::hasEmissiveTexture() const { + foreach (const FBXMeshPart& part, parts) { + if (!part.emissiveTexture.filename.isEmpty()) { + return true; + } + } + return false; +} + QStringList FBXGeometry::getJointNames() const { QStringList names; foreach (const FBXJoint& joint, joints) { @@ -1045,6 +1054,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) QHash diffuseTextures; QHash bumpTextures; QHash specularTextures; + QHash emissiveTextures; QHash localRotations; QHash xComponents; QHash yComponents; @@ -1417,6 +1427,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) ooChildToParent.insert(childID, parentID); } if (connection.properties.at(0) == "OP") { + int counter = 0; QByteArray type = connection.properties.at(3).toByteArray().toLower(); if (type.contains("diffuse")) { diffuseTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); @@ -1438,6 +1449,15 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } else if (type == "d|z") { zComponents.insert(getID(connection.properties, 2), getID(connection.properties, 1)); + + } else if (type.contains("shininess")) { + counter++; + + } else if (type.contains("emissive")) { + emissiveTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); + + } else { + counter++; } } parentMap.insert(getID(connection.properties, 1), getID(connection.properties, 2)); @@ -1666,6 +1686,20 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) if (!specularTextureID.isNull()) { specularTexture = getTexture(specularTextureID, textureNames, textureFilenames, textureContent); } + + FBXTexture emissiveTexture; + QString emissiveTextureID = emissiveTextures.value(childID); + if (!emissiveTextureID.isNull()) { + emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent); + + // FBX files generated by 3DSMax have an intermediate texture parent, apparently + foreach (const QString& childTextureID, childMap.values(diffuseTextureID)) { + if (textureFilenames.contains(childTextureID)) { + emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent); + } + } + } + for (int j = 0; j < extracted.partMaterialTextures.size(); j++) { if (extracted.partMaterialTextures.at(j).first == materialIndex) { @@ -1684,6 +1718,9 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) if (!specularTexture.filename.isNull()) { part.specularTexture = specularTexture; } + if (!emissiveTexture.filename.isNull()) { + part.emissiveTexture = emissiveTexture; + } part.materialID = material.id; } } diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 3c9e918686..9299b88b5a 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -120,6 +120,7 @@ public: FBXTexture diffuseTexture; FBXTexture normalTexture; FBXTexture specularTexture; + FBXTexture emissiveTexture; QString materialID; }; @@ -147,6 +148,7 @@ public: QVector blendshapes; bool hasSpecularTexture() const; + bool hasEmissiveTexture() const; }; /// A single animation frame extracted from an FBX document. From ab2fa16be3f2f600b36803d61d7752877e119546 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 21 Nov 2014 12:06:46 -0800 Subject: [PATCH 03/24] Update edit entities moveUp arrow position --- examples/libraries/entitySelectionTool.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index e760fb0463..b0fc68b60c 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -260,6 +260,7 @@ SelectionDisplay = (function () { var grabberColorFace = { red: 120, green: 120, blue: 120 }; var grabberLineWidth = 0.5; var grabberSolid = true; + var grabberMoveUpPosition = { x: 0, y: 0, z: 0 }; var grabberPropertiesCorner = { position: { x:0, y: 0, z: 0}, @@ -1093,7 +1094,8 @@ SelectionDisplay = (function () { Overlays.editOverlay(grabberEdgeFL, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeFL }); var grabberMoveUpOffset = 0.1; - Overlays.editOverlay(grabberMoveUp, { visible: activeTool == null || mode == "TRANSLATE_UP_DOWN", position: { x: position.x, y: position.y + worldTop + grabberMoveUpOffset, z: position.z } }); + grabberMoveUpPosition = { x: position.x, y: position.y + worldTop + grabberMoveUpOffset, z: position.z } + Overlays.editOverlay(grabberMoveUp, { visible: activeTool == null || mode == "TRANSLATE_UP_DOWN" }); }; that.setOverlaysVisible = function(isVisible) { @@ -2297,8 +2299,10 @@ SelectionDisplay = (function () { Overlays.editOverlay(rollHandle, { scale: handleSize, }); + var pos = Vec3.sum(grabberMoveUpPosition, { x: 0, y: Vec3.length(diff) * GRABBER_DISTANCE_TO_SIZE_RATIO * 3, z: 0 }); Overlays.editOverlay(grabberMoveUp, { - scale: handleSize, + position: pos, + scale: handleSize / 2, }); } } From 6a66351e7f87c286ea5bfa8a477e56c23fbcdb32 Mon Sep 17 00:00:00 2001 From: Adrianl3d Date: Sat, 22 Nov 2014 10:39:34 +1000 Subject: [PATCH 04/24] Clean up code Fix indentations, whitespace, and layout --- examples/notifications.js | 487 +++++++++++++++++++------------------- 1 file changed, 243 insertions(+), 244 deletions(-) diff --git a/examples/notifications.js b/examples/notifications.js index 6eb5e25566..3357d55096 100644 --- a/examples/notifications.js +++ b/examples/notifications.js @@ -1,54 +1,54 @@ // -// notifications.js -// Created by Adrian +// notifications.js +// Created by Adrian // -// Adrian McCarlie 8-10-14 -// This script demonstrates on-screen overlay type notifications. +// Adrian McCarlie 8-10-14 +// This script demonstrates on-screen overlay type notifications. // 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 -// This script demonstrates notifications created via a number of ways, such as: -// Simple key press alerts, which only depend on a key being pressed, -// dummy examples of this are "q", "w", "e", "r", and "SPACEBAR". -// actual working examples are "a" for left turn, "d" for right turn and Ctrl/s for snapshot. +// This script demonstrates notifications created via a number of ways, such as: +// Simple key press alerts, which only depend on a key being pressed, +// dummy examples of this are "q", "w", "e", "r", and "SPACEBAR". +// actual working examples are "a" for left turn, "d" for right turn and Ctrl/s for snapshot. -// System generated alerts such as users joining and leaving and chat messages which mention this user. -// System generated alerts which originate with a user interface event such as Window Resize, and Mic Mute/Unmute. -// Mic Mute/Unmute may appear to be a key press alert, but it actually gets the call from the system as mic is muted and unmuted, -// so the mic mute/unmute will also trigger the notification by clicking the Mic Mute button at the top of the screen. +// System generated alerts such as users joining and leaving and chat messages which mention this user. +// System generated alerts which originate with a user interface event such as Window Resize, and Mic Mute/Unmute. +// Mic Mute/Unmute may appear to be a key press alert, but it actually gets the call from the system as mic is muted and unmuted, +// so the mic mute/unmute will also trigger the notification by clicking the Mic Mute button at the top of the screen. -// To add a new System notification type: +// To add a new System notification type: // -// 1. Set the Event Connector at the bottom of the script. -// example: -// GlobalServices.incomingMessage.connect(onIncomingMessage); +// 1. Set the Event Connector at the bottom of the script. +// example: +// GlobalServices.incomingMessage.connect(onIncomingMessage); // -// 2. Create a new function to produce a text string, do not include new line returns. -// example: -// function onIncomingMessage(user, message) { -// //do stuff here; -// var text = "This is a notification"; -// wordWrap(text); -// } +// 2. Create a new function to produce a text string, do not include new line returns. +// example: +// function onIncomingMessage(user, message) { +// //do stuff here; +// var text = "This is a notification"; +// wordWrap(text); +// } // -// This new function must call wordWrap(text) if the length of message is longer than 42 chars or unknown. -// wordWrap() will format the text to fit the notifications overlay and send it to createNotification(text). -// If the message is 42 chars or less you should bypass wordWrap() and call createNotification() directly. +// This new function must call wordWrap(text) if the length of message is longer than 42 chars or unknown. +// wordWrap() will format the text to fit the notifications overlay and send it to createNotification(text). +// If the message is 42 chars or less you should bypass wordWrap() and call createNotification() directly. -// To add a keypress driven notification: +// To add a keypress driven notification: // -// 1. Add a key to the keyPressEvent(key). -// 2. Declare a text string. -// 3. Call createNotifications(text) parsing the text. -// example: -// if (key.text == "a") { -// var noteString = "Turning to the Left"; -// createNotification(noteString); -// } +// 1. Add a key to the keyPressEvent(key). +// 2. Declare a text string. +// 3. Call createNotifications(text) parsing the text. +// example: +// if (key.text == "a") { +// var noteString = "Turning to the Left"; +// createNotification(noteString); +// } var width = 340.0; //width of notification overlay @@ -70,16 +70,16 @@ var ourWidth = Window.innerWidth; var ourHeight = Window.innerHeight; var text = "placeholder"; var last_users = GlobalServices.onlineUsers; -var users =[]; +var users = []; var ctrlIsPressed = false; var ready = true; -// When our script shuts down, we should clean up all of our overlays +// When our script shuts down, we should clean up all of our overlays function scriptEnding() { - for (i = 0; i < notifications.length; i++){ - Overlays.deleteOverlay(notifications[i]); - Overlays.deleteOverlay(buttons[i]); - } + for (i = 0; i < notifications.length; i++){ + Overlays.deleteOverlay(notifications[i]); + Overlays.deleteOverlay(buttons[i]); + } } Script.scriptEnding.connect(scriptEnding); @@ -90,164 +90,164 @@ var heights = []; var myAlpha = []; var arrays = []; -// This function creates and sizes the overlays +// This function creates and sizes the overlays function createNotification(text){ - var count = (text.match(/\n/g) || []).length; - var breakPoint = 43.0; // length when new line is added - var extraLine = 0; - var breaks = 0; - var height = 40.0; - var stack = 0; - if (text.length >= breakPoint){ - breaks = count; - } - var extraLine = breaks * 16.0; - for (i = 0; i < heights.length; i++){ - stack = stack + heights[i]; - } - var level = (stack + 20.0 ); - height = height + extraLine; - var overlayProperties = { - x: overlayLocationX, - y: level, - width: width, - height: height, - color: textColor, - backgroundColor: backColor, - alpha: backgroundAlpha, - topargin: topMargin, - leftMargin: leftMargin, - font: {size: fontSize}, - text: text, - }; - var bLevel = level + 12.0; - var buttonProperties = { - x: buttonLocationX, - y: bLevel, - width: 15.0,//37 - height: 15.0,//35 - subImage: { x: 0, y: 0, width: 10, height: 10 }, - imageURL: "http://hifi-public.s3.amazonaws.com/images/close-small-light.svg", - color: { red: 255, green: 255, blue: 255}, - visible: true, - alpha: backgroundAlpha, - }; + var count = (text.match(/\n/g) || []).length; + var breakPoint = 43.0; // length when new line is added + var extraLine = 0; + var breaks = 0; + var height = 40.0; + var stack = 0; + if (text.length >= breakPoint){ + breaks = count; + } + var extraLine = breaks * 16.0; + for (i = 0; i < heights.length; i++){ + stack = stack + heights[i]; + } + var level = (stack + 20.0 ); + height = height + extraLine; + var overlayProperties = { + x: overlayLocationX, + y: level, + width: width, + height: height, + color: textColor, + backgroundColor: backColor, + alpha: backgroundAlpha, + topMargin: topMargin, + leftMargin: leftMargin, + font: {size: fontSize}, + text: text, + }; + var bLevel = level + 12.0; + var buttonProperties = { + x: buttonLocationX, + y: bLevel, + width: 15.0, + height: 15.0, + subImage: { x: 0, y: 0, width: 10, height: 10 }, + imageURL: "http://hifi-public.s3.amazonaws.com/images/close-small-light.svg", + color: { red: 255, green: 255, blue: 255}, + visible: true, + alpha: backgroundAlpha, + }; - Notify(overlayProperties, buttonProperties, height); + Notify(overlayProperties, buttonProperties, height); } -// Pushes data to each array and sets up data for 2nd dimension array -// to handle auxiliary data not carried by the overlay class -// specifically notification "heights", "times" of creation, and . -function Notify (notice, button, height ){ +// Pushes data to each array and sets up data for 2nd dimension array +// to handle auxiliary data not carried by the overlay class +// specifically notification "heights", "times" of creation, and . +function Notify(notice, button, height){ - notifications.push((Overlays.addOverlay("text",notice))); - buttons.push((Overlays.addOverlay("image",button))); - times.push(new Date().getTime() / 1000); - height = height + 1.0; - heights.push(height); - myAlpha.push(0); - var last = notifications.length - 1; - createArrays(notifications[last], buttons[last], times[last], heights[last], myAlpha[last]); - fadeIn(notifications[last], buttons[last]) + notifications.push((Overlays.addOverlay("text",notice))); + buttons.push((Overlays.addOverlay("image",button))); + times.push(new Date().getTime() / 1000); + height = height + 1.0; + heights.push(height); + myAlpha.push(0); + var last = notifications.length - 1; + createArrays(notifications[last], buttons[last], times[last], heights[last], myAlpha[last]); + fadeIn(notifications[last], buttons[last]) } function fadeIn(noticeIn, buttonIn){ - var myLength = arrays.length; - var q = 0; - var pauseTimer = null; - pauseTimer = Script.setInterval(function() { - q++; - qFade = q / 10.0; - Overlays.editOverlay(noticeIn, {alpha: qFade}); - Overlays.editOverlay(buttonIn, {alpha: qFade}); - if (q >= 9.0) { - Script.clearInterval(pauseTimer); - } - }, 10); + var myLength = arrays.length; + var q = 0; + var pauseTimer = null; + pauseTimer = Script.setInterval(function() { + q++; + qFade = q / 10.0; + Overlays.editOverlay(noticeIn, {alpha: qFade}); + Overlays.editOverlay(buttonIn, {alpha: qFade}); + if (q >= 9.0) { + Script.clearInterval(pauseTimer); + } + }, 10); } -// push data from above to the 2 dimensional array +// push data from above to the 2 dimensional array function createArrays(notice, button, createTime, height, myAlpha){ - arrays.push([notice, button, createTime, height, myAlpha]); + arrays.push([notice, button, createTime, height, myAlpha]); } -// handles mouse clicks on buttons +// handles mouse clicks on buttons function mousePressEvent(event) { - var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); //identify which overlay was clicked - for (i = 0; i < buttons.length; i++){ //if user clicked a button - if(clickedOverlay == buttons[i]){ - Overlays.deleteOverlay(notifications[i]); - Overlays.deleteOverlay(buttons[i]); - notifications.splice(i, 1); - buttons.splice(i, 1); - times.splice(i, 1); - heights.splice(i, 1); - myAlpha.splice(i, 1); - arrays.splice(i, 1); - } - } + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); //identify which overlay was clicked + for (i = 0; i < buttons.length; i++){ //if user clicked a button + if(clickedOverlay == buttons[i]){ + Overlays.deleteOverlay(notifications[i]); + Overlays.deleteOverlay(buttons[i]); + notifications.splice(i, 1); + buttons.splice(i, 1); + times.splice(i, 1); + heights.splice(i, 1); + myAlpha.splice(i, 1); + arrays.splice(i, 1); + } + } } -// Control key remains active only while key is held down +// Control key remains active only while key is held down function keyReleaseEvent(key){ - if (key.key == 16777249){ - ctrlIsPressed = false; - } + if (key.key == 16777249){ + ctrlIsPressed = false; + } } -// Triggers notification on specific key driven events +// Triggers notification on specific key driven events function keyPressEvent(key) { - if (key.key == 16777249){ - ctrlIsPressed = true; - } - if (key.text == "a") { - var noteString = "Turning to the Left"; - createNotification(noteString); - } - if (key.text == "d") { - var noteString = "Turning to the Right"; - createNotification(noteString); - } - if (key.text == "s") { - if (ctrlIsPressed == true){ - var noteString = "You have taken a snapshot"; - createNotification(noteString); - } - } - if (key.text == "q") { - var noteString = "Enable Scripted Motor control is now on."; - wordWrap(noteString); - } - if (key.text == "w") { - var noteString = "This notification spans 2 lines. The overlay will resize to fit new lines."; - var noteString = "editVoxels.js stopped, editModels.js stopped, selectAudioDevice.js stopped."; - wordWrap(noteString); - } - if (key.text == "e") { - var noteString = "This is an example of a multiple line notification. This notification will span 3 lines." - wordWrap(noteString); - } - if (key.text == "r") { - var noteString = "This is a very long line of text that we are going to use in this example to divide it into rows of maximum 43 chars and see how many lines we use."; - wordWrap(noteString); - } - if (key.text == "SPACE") { - var noteString = "You have pressed the Spacebar, This is an example of a multiple line notification. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam."; - wordWrap(noteString); - } + if (key.key == 16777249){ + ctrlIsPressed = true; + } + if (key.text == "a") { + var noteString = "Turning to the Left"; + createNotification(noteString); + } + if (key.text == "d") { + var noteString = "Turning to the Right"; + createNotification(noteString); + } + if (key.text == "s") { + if (ctrlIsPressed == true){ + var noteString = "You have taken a snapshot"; + createNotification(noteString); + } + } + if (key.text == "q") { + var noteString = "Enable Scripted Motor control is now on."; + wordWrap(noteString); + } + if (key.text == "w") { + var noteString = "This notification spans 2 lines. The overlay will resize to fit new lines."; + var noteString = "editVoxels.js stopped, editModels.js stopped, selectAudioDevice.js stopped."; + wordWrap(noteString); + } + if (key.text == "e") { + var noteString = "This is an example of a multiple line notification. This notification will span 3 lines." + wordWrap(noteString); + } + if (key.text == "r") { + var noteString = "This is a very long line of text that we are going to use in this example to divide it into rows of maximum 43 chars and see how many lines we use."; + wordWrap(noteString); + } + if (key.text == "SPACE") { + var noteString = "You have pressed the Spacebar, This is an example of a multiple line notification. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam."; + wordWrap(noteString); + } } -// formats string to add newline every 43 chars +// formats string to add newline every 43 chars function wordWrap(str){ - var result = stringDivider(str, 43.0, "\n"); - createNotification(result); + var result = stringDivider(str, 43.0, "\n"); + createNotification(result); } -// wraps whole word to newline +// wraps whole word to newline function stringDivider(str, slotWidth, spaceReplacer) { - if (str.length>slotWidth) { - var p=slotWidth; + if (str.length > slotWidth) { + var p = slotWidth; for (; p > 0 && str[p] != ' '; p--) { } if (p > 0) { @@ -259,27 +259,27 @@ function stringDivider(str, slotWidth, spaceReplacer) { return str; } -//This fires a notification on window resize +// This fires a notification on window resize function checkSize(){ - if((Window.innerWidth!=ourWidth)||(Window.innerHeight!=ourHeight)){ - var windowResize = "Window has been resized"; - ourWidth = Window.innerWidth; - ourHeight = Window.innerHeight; - windowDimensions = Controller.getViewportDimensions(); - overlayLocationX = (windowDimensions.x - (width + 60.0)); - buttonLocationX = overlayLocationX + (width - 35.0); - createNotification(windowResize) - } + if((Window.innerWidth!=ourWidth)||(Window.innerHeight!=ourHeight)){ + var windowResize = "Window has been resized"; + ourWidth = Window.innerWidth; + ourHeight = Window.innerHeight; + windowDimensions = Controller.getViewportDimensions(); + overlayLocationX = (windowDimensions.x - (width + 60.0)); + buttonLocationX = overlayLocationX + (width - 35.0); + createNotification(windowResize) + } } -// Triggers notification if a user logs on or off +// Triggers notification if a user logs on or off function onOnlineUsersChanged(users) { var joiners = []; var leavers = []; for (user in users) { - if (last_users.indexOf(users[user]) == -1.0) { - joiners.push(users[user]); - createNotification(users[user] + " Has joined"); + if (last_users.indexOf(users[user]) == -1.0) { + joiners.push(users[user]); + createNotification(users[user] + " Has joined"); } } for (user in last_users) { @@ -291,81 +291,80 @@ function onOnlineUsersChanged(users) { last_users = users; } -// Triggers notification if @MyUserName is mentioned in chat and returns the message to the notification. +// Triggers notification if @MyUserName is mentioned in chat and returns the message to the notification. function onIncomingMessage(user, message) { var myMessage = message; var alertMe = "@" + GlobalServices.myUsername; var thisAlert = user + ": " + myMessage; if (myMessage.indexOf(alertMe) > -1.0) { - wordWrap(thisAlert); - } + wordWrap(thisAlert); + } } -// Triggers mic mute notification +// Triggers mic mute notification function onMuteStateChanged() { - var muteState = AudioDevice.getMuted() ? "Muted" : "Unmuted"; - var muteString = "Microphone is set to " + muteState; - createNotification(muteString); + var muteState = AudioDevice.getMuted() ? "Muted" : "Unmuted"; + var muteString = "Microphone is set to " + muteState; + createNotification(muteString); } function update(){ - frame++; - if ((frame % 60.0) == 0) { // only update once a second - checkSize(); // checks for size change to trigger windowResize notification - locationY = 20.0; - for (var i = 0; i < arrays.length; i++){ //repositions overlays as others fade - var nextOverlay = Overlays.getOverlayAtPoint({x: overlayLocationX, y: locationY }); - Overlays.editOverlay(notifications[i], { x:overlayLocationX, y:locationY}); - Overlays.editOverlay(buttons[i], { x:buttonLocationX, y:locationY + 12.0}); - locationY=locationY + arrays[i][3]; - } - } + frame++; + if ((frame % 60.0) == 0) { // only update once a second + checkSize(); // checks for size change to trigger windowResize notification + locationY = 20.0; + for (var i = 0; i < arrays.length; i++){ //repositions overlays as others fade + var nextOverlay = Overlays.getOverlayAtPoint({x: overlayLocationX, y: locationY }); + Overlays.editOverlay(notifications[i], { x:overlayLocationX, y:locationY}); + Overlays.editOverlay(buttons[i], { x:buttonLocationX, y:locationY + 12.0}); + locationY=locationY + arrays[i][3]; + } + } - // This checks the age of the notification and prepares to fade it after 9.0 seconds (var persistTime - 1) - for (var i = 0; i < arrays.length; i++){ - if (ready){ - var j = arrays[i][2]; - var k = j + persistTime; - if (k < (new Date().getTime() / 1000)){ - ready = false; - noticeOut = arrays[i][0]; - buttonOut = arrays[i][1]; - var arraysOut = i; - fadeOut(noticeOut, buttonOut, arraysOut); - } - } - } +// This checks the age of the notification and prepares to fade it after 9.0 seconds (var persistTime - 1) + for (var i = 0; i < arrays.length; i++){ + if (ready){ + var j = arrays[i][2]; + var k = j + persistTime; + if (k < (new Date().getTime() / 1000)){ + ready = false; + noticeOut = arrays[i][0]; + buttonOut = arrays[i][1]; + var arraysOut = i; + fadeOut(noticeOut, buttonOut, arraysOut); + } + } + } } -// this fades the notification ready for dismissal, and removes it from the arrays +// this fades the notification ready for dismissal, and removes it from the arrays function fadeOut(noticeOut, buttonOut, arraysOut){ - var myLength = arrays.length; - var r = 9.0; - var pauseTimer = null; - pauseTimer = Script.setInterval(function() { - r--; - rFade = r / 10.0; - Overlays.editOverlay(noticeOut, {alpha: rFade}); - Overlays.editOverlay(buttonOut, {alpha: rFade}); - if (r < 0) { - dismiss(noticeOut, buttonOut, arraysOut); - arrays.splice(arraysOut, 1); - ready = true; - Script.clearInterval(pauseTimer); - } - }, 20); + var myLength = arrays.length; + var r = 9.0; + var pauseTimer = null; + pauseTimer = Script.setInterval(function() { + r--; + rFade = r / 10.0; + Overlays.editOverlay(noticeOut, {alpha: rFade}); + Overlays.editOverlay(buttonOut, {alpha: rFade}); + if (r < 0) { + dismiss(noticeOut, buttonOut, arraysOut); + arrays.splice(arraysOut, 1); + ready = true; + Script.clearInterval(pauseTimer); + } + }, 20); } -// This handles the final dismissal of a notification after fading +// This handles the final dismissal of a notification after fading function dismiss(firstNoteOut, firstButOut, firstOut){ var working = firstOut - Overlays.deleteOverlay(firstNoteOut); - Overlays.deleteOverlay(firstButOut); - notifications.splice(firstOut, 1); - buttons.splice(firstOut, 1); - times.splice(firstOut, 1); - heights.splice(firstOut, 1); - myAlpha.splice(firstOut,1); - + Overlays.deleteOverlay(firstNoteOut); + Overlays.deleteOverlay(firstButOut); + notifications.splice(firstOut, 1); + buttons.splice(firstOut, 1); + times.splice(firstOut, 1); + heights.splice(firstOut, 1); + myAlpha.splice(firstOut,1); } onMuteStateChanged(); From 87471df7a193a114ed77bf14b8a1e72c4c86fcff Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 21 Nov 2014 18:08:34 -0800 Subject: [PATCH 05/24] First version of the lighmap working --- interface/resources/shaders/model.vert | 6 +- .../resources/shaders/model_normal_map.vert | 6 +- interface/resources/shaders/skin_model.vert | 4 +- .../shaders/skin_model_normal_map.vert | 4 +- interface/src/gpu/Stream.h | 1 + interface/src/renderer/GeometryCache.cpp | 7 +- interface/src/renderer/Model.cpp | 384 +++++++----------- interface/src/renderer/Model.h | 68 ++-- libraries/fbx/src/FBXReader.cpp | 260 +++++++++++- libraries/fbx/src/FBXReader.h | 8 +- libraries/shared/src/Transform.h | 20 +- 11 files changed, 468 insertions(+), 300 deletions(-) diff --git a/interface/resources/shaders/model.vert b/interface/resources/shaders/model.vert index a304187591..5ae6ea1cb6 100644 --- a/interface/resources/shaders/model.vert +++ b/interface/resources/shaders/model.vert @@ -11,6 +11,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +const int MAX_TEXCOORDS = 2; + +uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; + // the interpolated normal varying vec4 normal; @@ -22,7 +26,7 @@ void main(void) { gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = gl_MultiTexCoord0; + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); // use standard pipeline transform gl_Position = ftransform(); diff --git a/interface/resources/shaders/model_normal_map.vert b/interface/resources/shaders/model_normal_map.vert index 9fde196b06..2e98b8c4fc 100644 --- a/interface/resources/shaders/model_normal_map.vert +++ b/interface/resources/shaders/model_normal_map.vert @@ -11,6 +11,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +const int MAX_TEXCOORDS = 2; + +uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; + // the tangent vector attribute vec3 tangent; @@ -29,7 +33,7 @@ void main(void) { gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = gl_MultiTexCoord0; + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); // use standard pipeline transform gl_Position = ftransform(); diff --git a/interface/resources/shaders/skin_model.vert b/interface/resources/shaders/skin_model.vert index 072bf3c336..a8c25e885b 100644 --- a/interface/resources/shaders/skin_model.vert +++ b/interface/resources/shaders/skin_model.vert @@ -11,10 +11,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +const int MAX_TEXCOORDS = 2; const int MAX_CLUSTERS = 128; const int INDICES_PER_VERTEX = 4; uniform mat4 clusterMatrices[MAX_CLUSTERS]; +uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; attribute vec4 clusterIndices; attribute vec4 clusterWeights; @@ -38,7 +40,7 @@ void main(void) { gl_FrontColor = gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = gl_MultiTexCoord0; + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); gl_Position = gl_ModelViewProjectionMatrix * position; } diff --git a/interface/resources/shaders/skin_model_normal_map.vert b/interface/resources/shaders/skin_model_normal_map.vert index ac6c77f7cb..bbe5da35af 100644 --- a/interface/resources/shaders/skin_model_normal_map.vert +++ b/interface/resources/shaders/skin_model_normal_map.vert @@ -11,10 +11,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +const int MAX_TEXCOORDS = 2; const int MAX_CLUSTERS = 128; const int INDICES_PER_VERTEX = 4; uniform mat4 clusterMatrices[MAX_CLUSTERS]; +uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; // the tangent vector attribute vec3 tangent; @@ -46,7 +48,7 @@ void main(void) { gl_FrontColor = gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = gl_MultiTexCoord0; + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); gl_Position = gl_ModelViewProjectionMatrix * interpolatedPosition; } diff --git a/interface/src/gpu/Stream.h b/interface/src/gpu/Stream.h index 84b2edc5f3..d024182531 100644 --- a/interface/src/gpu/Stream.h +++ b/interface/src/gpu/Stream.h @@ -34,6 +34,7 @@ public: TANGENT, SKIN_CLUSTER_INDEX, SKIN_CLUSTER_WEIGHT, + TEXCOORD1, NUM_INPUT_SLOTS, }; diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index b0636d3321..04ff7bdecd 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -964,7 +964,8 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { int tangentsOffset = normalsOffset + mesh.normals.size() * sizeof(glm::vec3); int colorsOffset = tangentsOffset + mesh.tangents.size() * sizeof(glm::vec3); int texCoordsOffset = colorsOffset + mesh.colors.size() * sizeof(glm::vec3); - int clusterIndicesOffset = texCoordsOffset + mesh.texCoords.size() * sizeof(glm::vec2); + int texCoords1Offset = texCoordsOffset + mesh.texCoords.size() * sizeof(glm::vec2); + int clusterIndicesOffset = texCoords1Offset + mesh.texCoords1.size() * sizeof(glm::vec2); int clusterWeightsOffset = clusterIndicesOffset + mesh.clusterIndices.size() * sizeof(glm::vec4); networkMesh._vertexBuffer->resize(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4)); @@ -977,6 +978,8 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { networkMesh._vertexBuffer->setSubData(colorsOffset, mesh.colors.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.colors.constData()); networkMesh._vertexBuffer->setSubData(texCoordsOffset, mesh.texCoords.size() * sizeof(glm::vec2), (gpu::Resource::Byte*) mesh.texCoords.constData()); + networkMesh._vertexBuffer->setSubData(texCoords1Offset, + mesh.texCoords1.size() * sizeof(glm::vec2), (gpu::Resource::Byte*) mesh.texCoords1.constData()); networkMesh._vertexBuffer->setSubData(clusterIndicesOffset, mesh.clusterIndices.size() * sizeof(glm::vec4), (gpu::Resource::Byte*) mesh.clusterIndices.constData()); networkMesh._vertexBuffer->setSubData(clusterWeightsOffset, @@ -989,6 +992,7 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { if (mesh.tangents.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, tangentsOffset, sizeof(glm::vec3)); if (mesh.colors.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, colorsOffset, sizeof(glm::vec3)); if (mesh.texCoords.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, texCoordsOffset, sizeof(glm::vec2)); + if (mesh.texCoords1.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, texCoords1Offset, sizeof(glm::vec2)); if (mesh.clusterIndices.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, clusterIndicesOffset, sizeof(glm::vec4)); if (mesh.clusterWeights.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, clusterWeightsOffset, sizeof(glm::vec4)); @@ -999,6 +1003,7 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { if (mesh.tangents.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TANGENT, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); if (mesh.colors.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::COLOR, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RGB)); if (mesh.texCoords.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TEXCOORD, channelNum++, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV)); + if (mesh.texCoords1.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TEXCOORD1, channelNum++, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV)); if (mesh.clusterIndices.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::VEC4, gpu::NFLOAT, gpu::XYZW)); if (mesh.clusterWeights.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::VEC4, gpu::NFLOAT, gpu::XYZW)); } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index a4c4e51d69..d2a2378689 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -70,10 +70,10 @@ ProgramObject Model::_specularMapProgram; ProgramObject Model::_normalSpecularMapProgram; ProgramObject Model::_translucentProgram; -ProgramObject Model::_emissiveProgram; -ProgramObject Model::_emissiveNormalMapProgram; -ProgramObject Model::_emissiveSpecularMapProgram; -ProgramObject Model::_emissiveNormalSpecularMapProgram; +ProgramObject Model::_lightmapProgram; +ProgramObject Model::_lightmapNormalMapProgram; +ProgramObject Model::_lightmapSpecularMapProgram; +ProgramObject Model::_lightmapNormalSpecularMapProgram; ProgramObject Model::_shadowProgram; @@ -83,11 +83,6 @@ ProgramObject Model::_skinSpecularMapProgram; ProgramObject Model::_skinNormalSpecularMapProgram; ProgramObject Model::_skinTranslucentProgram; -ProgramObject Model::_skinEmissiveProgram; -ProgramObject Model::_skinEmissiveNormalMapProgram; -ProgramObject Model::_skinEmissiveSpecularMapProgram; -ProgramObject Model::_skinEmissiveNormalSpecularMapProgram; - ProgramObject Model::_skinShadowProgram; Model::Locations Model::_locations; @@ -96,10 +91,10 @@ Model::Locations Model::_specularMapLocations; Model::Locations Model::_normalSpecularMapLocations; Model::Locations Model::_translucentLocations; -Model::Locations Model::_emissiveLocations; -Model::Locations Model::_emissiveNormalMapLocations; -Model::Locations Model::_emissiveSpecularMapLocations; -Model::Locations Model::_emissiveNormalSpecularMapLocations; +Model::Locations Model::_lightmapLocations; +Model::Locations Model::_lightmapNormalMapLocations; +Model::Locations Model::_lightmapSpecularMapLocations; +Model::Locations Model::_lightmapNormalSpecularMapLocations; Model::SkinLocations Model::_skinLocations; Model::SkinLocations Model::_skinNormalMapLocations; @@ -108,11 +103,6 @@ Model::SkinLocations Model::_skinNormalSpecularMapLocations; Model::SkinLocations Model::_skinShadowLocations; Model::SkinLocations Model::_skinTranslucentLocations; -Model::SkinLocations Model::_skinEmissiveLocations; -Model::SkinLocations Model::_skinEmissiveNormalMapLocations; -Model::SkinLocations Model::_skinEmissiveSpecularMapLocations; -Model::SkinLocations Model::_skinEmissiveNormalSpecularMapLocations; - void Model::setScale(const glm::vec3& scale) { setScaleInternal(scale); // if anyone sets scale manually, then we are no longer scaled to fit @@ -160,17 +150,40 @@ void Model::initProgram(ProgramObject& program, Model::Locations& locations, int glBindAttribLocation(program.programId(), gpu::Stream::TANGENT, "tangent"); + glBindAttribLocation(program.programId(), gpu::Stream::TEXCOORD1, "texcoord1"); + glLinkProgram(program.programId()); locations.tangent = program.attributeLocation("tangent"); locations.alphaThreshold = program.uniformLocation("alphaThreshold"); + locations.texcoordMatrices = program.uniformLocation("texcoordMatrices"); + + program.setUniformValue("diffuseMap", 0); program.setUniformValue("normalMap", 1); - program.setUniformValue("specularMap", specularTextureUnit); + int loc = program.uniformLocation("specularMap"); + if (loc >= 0) { + program.setUniformValue("specularMap", 2); + locations.specularTextureUnit = 2; + } else { + locations.specularTextureUnit = -1; + } + + loc = program.uniformLocation("emissiveMap"); + if (loc >= 0) { + program.setUniformValue("emissiveMap", 3); + locations.emissiveTextureUnit = 3; + } else { + locations.emissiveTextureUnit = -1; + } + + if (!program.isLinked()) { + program.release(); + } program.release(); @@ -289,37 +302,37 @@ void Model::init() { initProgram(_translucentProgram, _translucentLocations); - // Emissive - _emissiveProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model.vert"); - _emissiveProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_emissive.frag"); - _emissiveProgram.link(); + // Lightmap + _lightmapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_lightmap.vert"); + _lightmapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_lightmap.frag"); + _lightmapProgram.link(); - initProgram(_emissiveProgram, _emissiveLocations); + initProgram(_lightmapProgram, _lightmapLocations); - _emissiveNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/model_normal_map.vert"); - _emissiveNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_emissive_normal_map.frag"); - _emissiveNormalMapProgram.link(); + _lightmapNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model_lightmap_normal_map.vert"); + _lightmapNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_lightmap_normal_map.frag"); + _lightmapNormalMapProgram.link(); - initProgram(_emissiveNormalMapProgram, _emissiveNormalMapLocations); + initProgram(_lightmapNormalMapProgram, _lightmapNormalMapLocations); - _emissiveSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/model.vert"); - _emissiveSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_emissive_specular_map.frag"); - _emissiveSpecularMapProgram.link(); + _lightmapSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model_lightmap.vert"); + _lightmapSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_lightmap_specular_map.frag"); + _lightmapSpecularMapProgram.link(); - initProgram(_emissiveSpecularMapProgram, _emissiveSpecularMapLocations); + initProgram(_lightmapSpecularMapProgram, _lightmapSpecularMapLocations); - _emissiveNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/model_normal_map.vert"); - _emissiveNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_emissive_normal_specular_map.frag"); - _emissiveNormalSpecularMapProgram.link(); + _lightmapNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model_lightmap_normal_map.vert"); + _lightmapNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_lightmap_normal_specular_map.frag"); + _lightmapNormalSpecularMapProgram.link(); - initProgram(_emissiveNormalSpecularMapProgram, _emissiveNormalSpecularMapLocations, 2); - // end emissive + initProgram(_lightmapNormalSpecularMapProgram, _lightmapNormalSpecularMapLocations, 2); + // end lightmap _shadowProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_shadow.vert"); @@ -374,36 +387,6 @@ void Model::init() { initSkinProgram(_skinTranslucentProgram, _skinTranslucentLocations); - _skinEmissiveProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/skin_model.vert"); - _skinEmissiveProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_emissive.frag"); - _skinEmissiveProgram.link(); - - initSkinProgram(_skinEmissiveProgram, _skinEmissiveLocations); - - _skinEmissiveNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/skin_model_normal_map.vert"); - _skinEmissiveNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_emissive_normal_map.frag"); - _skinEmissiveNormalMapProgram.link(); - - initSkinProgram(_skinEmissiveNormalMapProgram, _skinEmissiveNormalMapLocations); - - _skinEmissiveSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/skin_model.vert"); - _skinEmissiveSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_emissive_specular_map.frag"); - _skinEmissiveSpecularMapProgram.link(); - - initSkinProgram(_skinEmissiveSpecularMapProgram, _skinEmissiveSpecularMapLocations); - - _skinEmissiveNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, - Application::resourcesPath() + "shaders/skin_model_normal_map.vert"); - _skinEmissiveNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, - Application::resourcesPath() + "shaders/model_emissive_normal_specular_map.frag"); - _skinEmissiveNormalSpecularMapProgram.link(); - - initSkinProgram(_skinEmissiveNormalSpecularMapProgram, _skinEmissiveNormalSpecularMapLocations, 2); - } } @@ -716,13 +699,9 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, true, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, true, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, true, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, true, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, true, args); // render translucent meshes afterwards //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); @@ -1666,13 +1645,9 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, true, args); */ opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, true, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, true, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, true, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, true, args); // render translucent meshes afterwards //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); @@ -1793,15 +1768,10 @@ void Model::segregateMeshGroups() { _meshesOpaqueTangentsSpecularSkinned.clear(); _meshesOpaqueSpecularSkinned.clear(); - _meshesOpaqueEmissiveTangents.clear(); - _meshesOpaqueEmissive.clear(); - _meshesOpaqueEmissiveTangentsSpecular.clear(); - _meshesOpaqueEmissiveSpecular.clear(); - - _meshesOpaqueEmissiveTangentsSkinned.clear(); - _meshesOpaqueEmissiveSkinned.clear(); - _meshesOpaqueEmissiveTangentsSpecularSkinned.clear(); - _meshesOpaqueEmissiveSpecularSkinned.clear(); + _meshesOpaqueLightmapTangents.clear(); + _meshesOpaqueLightmap.clear(); + _meshesOpaqueLightmapTangentsSpecular.clear(); + _meshesOpaqueLightmapSpecular.clear(); _unsortedMeshesTranslucentTangents.clear(); _unsortedMeshesTranslucent.clear(); @@ -1823,15 +1793,10 @@ void Model::segregateMeshGroups() { _unsortedMeshesOpaqueTangentsSpecularSkinned.clear(); _unsortedMeshesOpaqueSpecularSkinned.clear(); - _unsortedMeshesOpaqueEmissiveTangents.clear(); - _unsortedMeshesOpaqueEmissive.clear(); - _unsortedMeshesOpaqueEmissiveTangentsSpecular.clear(); - _unsortedMeshesOpaqueEmissiveSpecular.clear(); - - _unsortedMeshesOpaqueEmissiveTangentsSkinned.clear(); - _unsortedMeshesOpaqueEmissiveSkinned.clear(); - _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned.clear(); - _unsortedMeshesOpaqueEmissiveSpecularSkinned.clear(); + _unsortedMeshesOpaqueLightmapTangents.clear(); + _unsortedMeshesOpaqueLightmap.clear(); + _unsortedMeshesOpaqueLightmapTangentsSpecular.clear(); + _unsortedMeshesOpaqueLightmapSpecular.clear(); const FBXGeometry& geometry = _geometry->getFBXGeometry(); const QVector& networkMeshes = _geometry->getMeshes(); @@ -1846,7 +1811,7 @@ void Model::segregateMeshGroups() { bool translucentMesh = networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size(); bool hasTangents = !mesh.tangents.isEmpty(); bool hasSpecular = mesh.hasSpecularTexture(); - bool hasEmissive = mesh.hasEmissiveTexture(); + bool haslightmap = mesh.hasEmissiveTexture(); bool isSkinned = state.clusterMatrices.size() > 1; QString materialID; @@ -1865,7 +1830,7 @@ void Model::segregateMeshGroups() { qDebug() << "materialID:" << materialID << "parts:" << mesh.parts.size(); } - if ( !hasEmissive) { + if ( !haslightmap) { if (translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { _unsortedMeshesTranslucent.insertMulti(materialID, i); @@ -1935,35 +1900,20 @@ void Model::segregateMeshGroups() { } else { if (!translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { - _unsortedMeshesOpaqueEmissive.insertMulti(materialID, i); + _unsortedMeshesOpaqueLightmap.insertMulti(materialID, i); } else if (!translucentMesh && hasTangents && !hasSpecular && !isSkinned) { - _unsortedMeshesOpaqueEmissiveTangents.insertMulti(materialID, i); + _unsortedMeshesOpaqueLightmapTangents.insertMulti(materialID, i); } else if (!translucentMesh && hasTangents && hasSpecular && !isSkinned) { - _unsortedMeshesOpaqueEmissiveTangentsSpecular.insertMulti(materialID, i); + _unsortedMeshesOpaqueLightmapTangentsSpecular.insertMulti(materialID, i); } else if (!translucentMesh && !hasTangents && hasSpecular && !isSkinned) { - _unsortedMeshesOpaqueEmissiveSpecular.insertMulti(materialID, i); + _unsortedMeshesOpaqueLightmapSpecular.insertMulti(materialID, i); - } else if (!translucentMesh && hasTangents && !hasSpecular && isSkinned) { - - _unsortedMeshesOpaqueEmissiveTangentsSkinned.insertMulti(materialID, i); - - } else if (!translucentMesh && !hasTangents && !hasSpecular && isSkinned) { - - _unsortedMeshesOpaqueEmissiveSkinned.insertMulti(materialID, i); - - } else if (!translucentMesh && hasTangents && hasSpecular && isSkinned) { - - _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned.insertMulti(materialID, i); - - } else if (!translucentMesh && !hasTangents && hasSpecular && isSkinned) { - - _unsortedMeshesOpaqueEmissiveSpecularSkinned.insertMulti(materialID, i); } else { qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???"; } @@ -2034,36 +1984,20 @@ void Model::segregateMeshGroups() { _meshesOpaqueSpecularSkinned.append(i); } - foreach(int i, _unsortedMeshesOpaqueEmissive) { - _meshesOpaqueEmissive.append(i); + foreach(int i, _unsortedMeshesOpaqueLightmap) { + _meshesOpaqueLightmap.append(i); } - foreach(int i, _unsortedMeshesOpaqueEmissiveTangents) { - _meshesOpaqueEmissiveTangents.append(i); + foreach(int i, _unsortedMeshesOpaqueLightmapTangents) { + _meshesOpaqueLightmapTangents.append(i); } - foreach(int i, _unsortedMeshesOpaqueEmissiveTangentsSpecular) { - _meshesOpaqueEmissiveTangentsSpecular.append(i); + foreach(int i, _unsortedMeshesOpaqueLightmapTangentsSpecular) { + _meshesOpaqueLightmapTangentsSpecular.append(i); } - foreach(int i, _unsortedMeshesOpaqueEmissiveSpecular) { - _meshesOpaqueEmissiveSpecular.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueEmissiveSkinned) { - _meshesOpaqueEmissiveSkinned.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueEmissiveTangentsSkinned) { - _meshesOpaqueEmissiveTangentsSkinned.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned) { - _meshesOpaqueEmissiveTangentsSpecularSkinned.append(i); - } - - foreach(int i, _unsortedMeshesOpaqueEmissiveSpecularSkinned) { - _meshesOpaqueEmissiveSpecularSkinned.append(i); + foreach(int i, _unsortedMeshesOpaqueLightmapSpecular) { + _meshesOpaqueLightmapSpecular.append(i); } _unsortedMeshesTranslucentTangents.clear(); @@ -2086,20 +2020,15 @@ void Model::segregateMeshGroups() { _unsortedMeshesOpaqueTangentsSpecularSkinned.clear(); _unsortedMeshesOpaqueSpecularSkinned.clear(); - _unsortedMeshesOpaqueEmissiveTangents.clear(); - _unsortedMeshesOpaqueEmissive.clear(); - _unsortedMeshesOpaqueEmissiveTangentsSpecular.clear(); - _unsortedMeshesOpaqueEmissiveSpecular.clear(); - - _unsortedMeshesOpaqueEmissiveTangentsSkinned.clear(); - _unsortedMeshesOpaqueEmissiveSkinned.clear(); - _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned.clear(); - _unsortedMeshesOpaqueEmissiveSpecularSkinned.clear(); + _unsortedMeshesOpaqueLightmapTangents.clear(); + _unsortedMeshesOpaqueLightmap.clear(); + _unsortedMeshesOpaqueLightmapTangentsSpecular.clear(); + _unsortedMeshesOpaqueLightmapSpecular.clear(); _meshGroupsKnown = true; } -QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned) { +QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned) { PROFILE_RANGE(__FUNCTION__); // depending on which parameters we were called with, pick the correct mesh group to render @@ -2121,39 +2050,31 @@ QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool h } else if (translucent && !hasTangents && hasSpecular && isSkinned) { whichList = &_meshesTranslucentSpecularSkinned; - } else if (!translucent && !hasEmissive && !hasTangents && !hasSpecular && !isSkinned) { + } else if (!translucent && !hasLightmap && !hasTangents && !hasSpecular && !isSkinned) { whichList = &_meshesOpaque; - } else if (!translucent && !hasEmissive && hasTangents && !hasSpecular && !isSkinned) { + } else if (!translucent && !hasLightmap && hasTangents && !hasSpecular && !isSkinned) { whichList = &_meshesOpaqueTangents; - } else if (!translucent && !hasEmissive && hasTangents && hasSpecular && !isSkinned) { + } else if (!translucent && !hasLightmap && hasTangents && hasSpecular && !isSkinned) { whichList = &_meshesOpaqueTangentsSpecular; - } else if (!translucent && !hasEmissive && !hasTangents && hasSpecular && !isSkinned) { + } else if (!translucent && !hasLightmap && !hasTangents && hasSpecular && !isSkinned) { whichList = &_meshesOpaqueSpecular; - } else if (!translucent && !hasEmissive && hasTangents && !hasSpecular && isSkinned) { + } else if (!translucent && !hasLightmap && hasTangents && !hasSpecular && isSkinned) { whichList = &_meshesOpaqueTangentsSkinned; - } else if (!translucent && !hasEmissive && !hasTangents && !hasSpecular && isSkinned) { + } else if (!translucent && !hasLightmap && !hasTangents && !hasSpecular && isSkinned) { whichList = &_meshesOpaqueSkinned; - } else if (!translucent && !hasEmissive && hasTangents && hasSpecular && isSkinned) { + } else if (!translucent && !hasLightmap && hasTangents && hasSpecular && isSkinned) { whichList = &_meshesOpaqueTangentsSpecularSkinned; - } else if (!translucent && !hasEmissive && !hasTangents && hasSpecular && isSkinned) { + } else if (!translucent && !hasLightmap && !hasTangents && hasSpecular && isSkinned) { whichList = &_meshesOpaqueSpecularSkinned; - } else if (!translucent && hasEmissive && !hasTangents && !hasSpecular && !isSkinned) { - whichList = &_meshesOpaqueEmissive; - } else if (!translucent && hasEmissive && hasTangents && !hasSpecular && !isSkinned) { - whichList = &_meshesOpaqueEmissiveTangents; - } else if (!translucent && hasEmissive && hasTangents && hasSpecular && !isSkinned) { - whichList = &_meshesOpaqueEmissiveTangentsSpecular; - } else if (!translucent && hasEmissive && !hasTangents && hasSpecular && !isSkinned) { - whichList = &_meshesOpaqueEmissiveSpecular; - } else if (!translucent && hasEmissive && hasTangents && !hasSpecular && isSkinned) { - whichList = &_meshesOpaqueEmissiveTangentsSkinned; - } else if (!translucent && hasEmissive && !hasTangents && !hasSpecular && isSkinned) { - whichList = &_meshesOpaqueEmissiveSkinned; - } else if (!translucent && hasEmissive && hasTangents && hasSpecular && isSkinned) { - whichList = &_meshesOpaqueEmissiveTangentsSpecularSkinned; - } else if (!translucent && hasEmissive && !hasTangents && hasSpecular && isSkinned) { - whichList = &_meshesOpaqueEmissiveSpecularSkinned; + } else if (!translucent && hasLightmap && !hasTangents && !hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueLightmap; + } else if (!translucent && hasLightmap && hasTangents && !hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueLightmapTangents; + } else if (!translucent && hasLightmap && hasTangents && hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueLightmapTangentsSpecular; + } else if (!translucent && hasLightmap && !hasTangents && hasSpecular && !isSkinned) { + whichList = &_meshesOpaqueLightmapSpecular; } else { qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???"; @@ -2162,15 +2083,13 @@ QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool h } void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, - SkinLocations*& skinLocations, GLenum& specularTextureUnit, GLenum& emissiveTextureUnit) { + bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, + Locations*& locations, SkinLocations*& skinLocations) { ProgramObject* program = &_program; - Locations* locations = &_locations; + locations = &_locations; ProgramObject* skinProgram = &_skinProgram; skinLocations = &_skinLocations; - specularTextureUnit = 0; - emissiveTextureUnit = 0; if (mode == SHADOW_RENDER_MODE) { program = &_shadowProgram; skinProgram = &_skinShadowProgram; @@ -2181,35 +2100,29 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f skinProgram = &_skinTranslucentProgram; skinLocations = &_skinTranslucentLocations; - } else if (hasEmissive) { + } else if (hasLightmap) { if (hasTangents) { if (hasSpecular) { - program = &_emissiveNormalSpecularMapProgram; - locations = &_emissiveNormalSpecularMapLocations; - skinProgram = &_skinEmissiveNormalSpecularMapProgram; - skinLocations = &_skinEmissiveNormalSpecularMapLocations; - specularTextureUnit = GL_TEXTURE2; - emissiveTextureUnit = GL_TEXTURE3; + program = &_lightmapNormalSpecularMapProgram; + locations = &_lightmapNormalSpecularMapLocations; + skinProgram = NULL; + skinLocations = NULL; } else { - program = &_emissiveNormalMapProgram; - locations = &_emissiveNormalMapLocations; - skinProgram = &_skinEmissiveNormalMapProgram; - skinLocations = &_skinEmissiveNormalMapLocations; - emissiveTextureUnit = GL_TEXTURE3; + program = &_lightmapNormalMapProgram; + locations = &_lightmapNormalMapLocations; + skinProgram = NULL; + skinLocations = NULL; } } else if (hasSpecular) { - program = &_emissiveSpecularMapProgram; - locations = &_emissiveSpecularMapLocations; - skinProgram = &_skinEmissiveSpecularMapProgram; - skinLocations = &_skinEmissiveSpecularMapLocations; - specularTextureUnit = GL_TEXTURE1; - emissiveTextureUnit = GL_TEXTURE3; + program = &_lightmapSpecularMapProgram; + locations = &_lightmapSpecularMapLocations; + skinProgram = NULL; + skinLocations = NULL; } else { - program = &_emissiveProgram; - locations = &_emissiveLocations; - skinProgram = &_skinEmissiveProgram; - skinLocations = &_skinEmissiveLocations; - emissiveTextureUnit = GL_TEXTURE3; + program = &_lightmapProgram; + locations = &_lightmapLocations; + skinProgram = NULL; + skinLocations = NULL; } } else { if (hasTangents) { @@ -2218,7 +2131,6 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f locations = &_normalSpecularMapLocations; skinProgram = &_skinNormalSpecularMapProgram; skinLocations = &_skinNormalSpecularMapLocations; - specularTextureUnit = GL_TEXTURE2; } else { program = &_normalMapProgram; locations = &_normalMapLocations; @@ -2230,7 +2142,6 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f locations = &_specularMapLocations; skinProgram = &_skinSpecularMapProgram; skinLocations = &_skinSpecularMapLocations; - specularTextureUnit = GL_TEXTURE1; } } @@ -2240,6 +2151,7 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f if (isSkinned) { activeProgram = skinProgram; activeLocations = skinLocations; + locations = skinLocations; } // This code replace the "bind()" on the QGLProgram if (!activeProgram->isLinked()) { @@ -2251,27 +2163,26 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f } int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { + bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); int meshPartsRendered = 0; bool pickProgramsNeeded = true; + Locations* locations; SkinLocations* skinLocations; - GLenum specularTextureUnit; - GLenum emissiveTextureUnit; foreach(Model* model, _modelsInScene) { - QVector* whichList = model->pickMeshList(translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned); + QVector* whichList = model->pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned); if (whichList) { QVector& list = *whichList; if (list.size() > 0) { if (pickProgramsNeeded) { - pickPrograms(batch, mode, translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit, emissiveTextureUnit); + pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, args, locations, skinLocations); pickProgramsNeeded = false; } model->setupBatchTransform(batch); - meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit, emissiveTextureUnit); + meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, locations, skinLocations); GLBATCH(glPopMatrix)(); } } @@ -2284,12 +2195,12 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool } int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { + bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); int meshPartsRendered = 0; - QVector* whichList = pickMeshList(translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned); + QVector* whichList = pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned); if (!whichList) { qDebug() << "unexpected!!! we don't know which list of meshes to render..."; @@ -2302,11 +2213,10 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl return 0; } + Locations* locations; SkinLocations* skinLocations; - GLenum specularTextureUnit; - GLenum emissiveTextureUnit; - pickPrograms(batch, mode, translucent, alphaThreshold, hasEmissive, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit, emissiveTextureUnit); - meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit, emissiveTextureUnit); + pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, args, locations, skinLocations); + meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, locations, skinLocations); GLBATCH(glUseProgram)(0); return meshPartsRendered; @@ -2314,7 +2224,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args, - SkinLocations* skinLocations, GLenum specularTextureUnit, GLenum emissiveTextureUnit) { + Locations* locations, SkinLocations* skinLocations) { PROFILE_RANGE(__FUNCTION__); bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts); bool cullTooSmallMeshParts = !Menu::getInstance()->isOptionChecked(MenuOption::DontCullTooSmallMeshParts); @@ -2431,7 +2341,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glMaterialfv)(GL_FRONT, GL_DIFFUSE, (const float*)&diffuse); GLBATCH(glMaterialfv)(GL_FRONT, GL_SPECULAR, (const float*)&specular); GLBATCH(glMaterialf)(GL_FRONT, GL_SHININESS, (part.shininess > 128.0f ? 128.0f: part.shininess)); - + Texture* diffuseMap = networkPart.diffuseTexture.data(); if (mesh.isEye && diffuseMap) { diffuseMap = (_dilatedTextures[i][j] = @@ -2439,7 +2349,18 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod } GLBATCH(glBindTexture)(GL_TEXTURE_2D, !diffuseMap ? Application::getInstance()->getTextureCache()->getWhiteTextureID() : diffuseMap->getID()); - + + 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()) { GLBATCH(glActiveTexture)(GL_TEXTURE1); Texture* normalMap = networkPart.normalTexture.data(); @@ -2448,19 +2369,20 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glActiveTexture)(GL_TEXTURE0); } - if (specularTextureUnit) { - GLBATCH(glActiveTexture)(specularTextureUnit); + if (locations->specularTextureUnit >= 0) { + GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->specularTextureUnit); Texture* specularMap = networkPart.specularTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !specularMap ? Application::getInstance()->getTextureCache()->getWhiteTextureID() : specularMap->getID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } - if (emissiveTextureUnit) { - GLBATCH(glActiveTexture)(emissiveTextureUnit); + if (locations->emissiveTextureUnit >= 0) { + GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit); Texture* emissiveMap = networkPart.emissiveTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ? Application::getInstance()->getTextureCache()->getWhiteTextureID() : emissiveMap->getID()); + // GLBATCH(glBindTexture)(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getWhiteTextureID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } @@ -2498,14 +2420,14 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod GLBATCH(glActiveTexture)(GL_TEXTURE0); } - if (specularTextureUnit) { - GLBATCH(glActiveTexture)(specularTextureUnit); + if (locations->specularTextureUnit >= 0) { + GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->specularTextureUnit); GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); GLBATCH(glActiveTexture)(GL_TEXTURE0); } - if (emissiveTextureUnit) { - GLBATCH(glActiveTexture)(emissiveTextureUnit); + if (locations->emissiveTextureUnit >= 0) { + GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit); GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); GLBATCH(glActiveTexture)(GL_TEXTURE0); } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index c1ae190a1e..7a3457423e 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -304,10 +304,10 @@ private: static ProgramObject _normalSpecularMapProgram; static ProgramObject _translucentProgram; - static ProgramObject _emissiveProgram; - static ProgramObject _emissiveNormalMapProgram; - static ProgramObject _emissiveSpecularMapProgram; - static ProgramObject _emissiveNormalSpecularMapProgram; + static ProgramObject _lightmapProgram; + static ProgramObject _lightmapNormalMapProgram; + static ProgramObject _lightmapSpecularMapProgram; + static ProgramObject _lightmapNormalSpecularMapProgram; static ProgramObject _shadowProgram; @@ -317,11 +317,6 @@ private: static ProgramObject _skinNormalSpecularMapProgram; static ProgramObject _skinTranslucentProgram; - static ProgramObject _skinEmissiveProgram; - static ProgramObject _skinEmissiveNormalMapProgram; - static ProgramObject _skinEmissiveSpecularMapProgram; - static ProgramObject _skinEmissiveNormalSpecularMapProgram; - static ProgramObject _skinShadowProgram; static int _normalMapTangentLocation; @@ -331,6 +326,9 @@ private: public: int tangent; int alphaThreshold; + int texcoordMatrices; + int specularTextureUnit; + int emissiveTextureUnit; }; static Locations _locations; @@ -339,10 +337,10 @@ private: static Locations _normalSpecularMapLocations; static Locations _translucentLocations; - static Locations _emissiveLocations; - static Locations _emissiveNormalMapLocations; - static Locations _emissiveSpecularMapLocations; - static Locations _emissiveNormalSpecularMapLocations; + static Locations _lightmapLocations; + static Locations _lightmapNormalMapLocations; + static Locations _lightmapSpecularMapLocations; + static Locations _lightmapNormalSpecularMapLocations; static void initProgram(ProgramObject& program, Locations& locations, int specularTextureUnit = 1); @@ -350,7 +348,7 @@ private: public: int clusterMatrices; int clusterIndices; - int clusterWeights; + int clusterWeights; }; static SkinLocations _skinLocations; @@ -360,11 +358,6 @@ private: static SkinLocations _skinShadowLocations; static SkinLocations _skinTranslucentLocations; - static SkinLocations _skinEmissiveLocations; - static SkinLocations _skinEmissiveNormalMapLocations; - static SkinLocations _skinEmissiveSpecularMapLocations; - static SkinLocations _skinEmissiveNormalSpecularMapLocations; - static void initSkinProgram(ProgramObject& program, SkinLocations& locations, int specularTextureUnit = 1); QVector _calculatedMeshBoxes; @@ -396,15 +389,10 @@ private: QMap _unsortedMeshesOpaqueTangentsSpecularSkinned; QMap _unsortedMeshesOpaqueSpecularSkinned; - QMap _unsortedMeshesOpaqueEmissive; - QMap _unsortedMeshesOpaqueEmissiveTangents; - QMap _unsortedMeshesOpaqueEmissiveTangentsSpecular; - QMap _unsortedMeshesOpaqueEmissiveSpecular; - - QMap _unsortedMeshesOpaqueEmissiveSkinned; - QMap _unsortedMeshesOpaqueEmissiveTangentsSkinned; - QMap _unsortedMeshesOpaqueEmissiveTangentsSpecularSkinned; - QMap _unsortedMeshesOpaqueEmissiveSpecularSkinned; + QMap _unsortedMeshesOpaqueLightmap; + QMap _unsortedMeshesOpaqueLightmapTangents; + QMap _unsortedMeshesOpaqueLightmapTangentsSpecular; + QMap _unsortedMeshesOpaqueLightmapSpecular; QVector _meshesTranslucent; QVector _meshesTranslucentTangents; @@ -426,15 +414,11 @@ private: QVector _meshesOpaqueTangentsSpecularSkinned; QVector _meshesOpaqueSpecularSkinned; - QVector _meshesOpaqueEmissive; - QVector _meshesOpaqueEmissiveTangents; - QVector _meshesOpaqueEmissiveTangentsSpecular; - QVector _meshesOpaqueEmissiveSpecular; + QVector _meshesOpaqueLightmap; + QVector _meshesOpaqueLightmapTangents; + QVector _meshesOpaqueLightmapTangentsSpecular; + QVector _meshesOpaqueLightmapSpecular; - QVector _meshesOpaqueEmissiveSkinned; - QVector _meshesOpaqueEmissiveTangentsSkinned; - QVector _meshesOpaqueEmissiveTangentsSpecularSkinned; - QVector _meshesOpaqueEmissiveSpecularSkinned; // Scene rendering support static QVector _modelsInScene; @@ -447,19 +431,19 @@ private: void renderSetup(RenderArgs* args); bool renderCore(float alpha, RenderMode mode, RenderArgs* args); int renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL); + bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL); void setupBatchTransform(gpu::Batch& batch); - QVector* pickMeshList(bool translucent, float alphaThreshold, bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned); + QVector* pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned); int renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - RenderArgs* args, SkinLocations* skinLocations, GLenum specularTextureUnit, GLenum emissiveTextureUnit); + RenderArgs* args, Locations* locations, SkinLocations* skinLocations); static void pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, - SkinLocations*& skinLocations, GLenum& specularTextureUnit, GLenum& emissiveTextureUnit); + bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, + Locations*& locations, SkinLocations*& skinLocations); static int renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - bool hasEmissive, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args); + bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args); }; diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 2a97c50fea..130f1db550 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -32,6 +32,48 @@ using namespace std; +struct TextureParam { + glm::vec2 UVTranslation; + glm::vec2 UVScaling; + glm::vec4 cropping; + std::string UVSet; + + glm::vec3 translation; + glm::vec3 rotation; + glm::vec3 scaling; + uint8_t alphaSource; + uint8_t currentTextureBlendMode; + bool useMaterial; + + template + bool assign(T& ref, const T& v) { + if (ref == v) { + return false; + } else { + ref = v; + isDefault = false; + return true; + } + } + + bool isDefault; + + TextureParam() : + UVTranslation(0.0f), + UVScaling(1.0f), + cropping(0.0f), + UVSet("map1"), + translation(0.0f), + rotation(0.0f), + scaling(1.0f), + alphaSource(0), + currentTextureBlendMode(0), + useMaterial(true), + isDefault(true) + {} +}; + + bool FBXMesh::hasSpecularTexture() const { foreach (const FBXMeshPart& part, parts) { if (!part.specularTexture.filename.isEmpty()) { @@ -718,6 +760,7 @@ class Vertex { public: int originalIndex; glm::vec2 texCoord; + glm::vec2 texCoord1; }; uint qHash(const Vertex& vertex, uint seed = 0) { @@ -725,7 +768,7 @@ uint qHash(const Vertex& vertex, uint seed = 0) { } bool operator==(const Vertex& v1, const Vertex& v2) { - return v1.originalIndex == v2.originalIndex && v1.texCoord == v2.texCoord; + return v1.originalIndex == v2.originalIndex && v1.texCoord == v2.texCoord && v1.texCoord1 == v2.texCoord1; } class ExtractedMesh { @@ -734,6 +777,16 @@ public: QMultiHash newIndices; QVector > blendshapeIndexMaps; QVector > partMaterialTextures; + QHash texcoordSetMap; + std::map texcoordSetMap2; +}; + +class AttributeData { +public: + QVector texCoords; + QVector texCoordIndices; + std::string name; + int index; }; class MeshData { @@ -748,6 +801,8 @@ public: QVector texCoordIndices; QHash indices; + + std::vector attributes; }; void appendIndex(MeshData& data, QVector& indices, int index) { @@ -789,6 +844,20 @@ void appendIndex(MeshData& data, QVector& indices, int index) { vertex.texCoord = data.texCoords.at(texCoordIndex); } } + + bool hasMoreTexcoords = (data.attributes.size() > 1); + if (hasMoreTexcoords) { + if (data.attributes[1].texCoordIndices.empty()) { + if (index < data.attributes[1].texCoords.size()) { + vertex.texCoord1 = data.attributes[1].texCoords.at(index); + } + } else if (index < data.attributes[1].texCoordIndices.size()) { + int texCoordIndex = data.attributes[1].texCoordIndices.at(index); + if (texCoordIndex >= 0 && texCoordIndex < data.attributes[1].texCoords.size()) { + vertex.texCoord1 = data.attributes[1].texCoords.at(texCoordIndex); + } + } + } QHash::const_iterator it = data.indices.find(vertex); if (it == data.indices.constEnd()) { @@ -799,7 +868,7 @@ void appendIndex(MeshData& data, QVector& indices, int index) { data.extracted.mesh.vertices.append(position); data.extracted.mesh.normals.append(normal); data.extracted.mesh.texCoords.append(vertex.texCoord); - + if (hasMoreTexcoords) { data.extracted.mesh.texCoords1.append(vertex.texCoord1); } } else { indices.append(*it); data.extracted.mesh.normals[*it] += normal; @@ -838,13 +907,61 @@ ExtractedMesh extractMesh(const FBXNode& object) { // hack to work around wacky Makehuman exports data.normalsByVertex = true; } - } else if (child.name == "LayerElementUV" && child.properties.at(0).toInt() == 0) { - foreach (const FBXNode& subdata, child.children) { - if (subdata.name == "UV") { - data.texCoords = createVec2Vector(getDoubleVector(subdata)); + } else if (child.name == "LayerElementUV") { + if (child.properties.at(0).toInt() == 0) { + AttributeData attrib; + attrib.index = child.properties.at(0).toInt(); + int unknown = 0; + foreach (const FBXNode& subdata, child.children) { + if (subdata.name == "UV") { + data.texCoords = createVec2Vector(getDoubleVector(subdata)); + attrib.texCoords = createVec2Vector(getDoubleVector(subdata)); + } else if (subdata.name == "UVIndex") { + data.texCoordIndices = getIntVector(subdata); + attrib.texCoordIndices = getIntVector(subdata); + } else if (subdata.name == "Name") { + attrib.name = subdata.properties.at(0).toString().toStdString(); + } else { + std::string subname = subdata.name.data(); + if (subdata.name == "Version") { + } else if (subdata.name == "MappingInformationType") { + } else if (subdata.name == "ReferenceInformationType") { + } else { + unknown++; + } + } + } + data.extracted.texcoordSetMap.insert(QString(attrib.name.c_str()), data.attributes.size()); + data.attributes.push_back(attrib); + } else { + AttributeData attrib; + attrib.index = child.properties.at(0).toInt(); + int unknown = 0; + foreach (const FBXNode& subdata, child.children) { + if (subdata.name == "UV") { + attrib.texCoords = createVec2Vector(getDoubleVector(subdata)); + } else if (subdata.name == "UVIndex") { + attrib.texCoordIndices = getIntVector(subdata); + } else if (subdata.name == "Name") { + attrib.name = subdata.properties.at(0).toString().toStdString(); + } else { + std::string subname = subdata.name.data(); + if (subdata.name == "Version") { + } else if (subdata.name == "MappingInformationType") { + } else if (subdata.name == "ReferenceInformationType") { + } else { + unknown++; + } + } + } - } else if (subdata.name == "UVIndex") { - data.texCoordIndices = getIntVector(subdata); + QHash::iterator it = data.extracted.texcoordSetMap.find(QString(attrib.name.c_str())); + if (it == data.extracted.texcoordSetMap.end()) { + data.extracted.texcoordSetMap.insert(QString(attrib.name.c_str()), data.attributes.size()); + data.attributes.push_back(attrib); + } else { + // WTF same names for different UVs? + unknown = data.attributes.size(); } } } else if (child.name == "LayerElementMaterial") { @@ -1014,11 +1131,27 @@ public: FBXTexture getTexture(const QString& textureID, const QHash& textureNames, const QHash& textureFilenames, - const QHash& textureContent) { + const QHash& textureContent, + const QHash& textureParams) { FBXTexture texture; texture.filename = textureFilenames.value(textureID); texture.name = textureNames.value(textureID); texture.content = textureContent.value(texture.filename); + texture.transform.setIdentity(); + texture.texcoordSet = 0; + QHash::const_iterator it = textureParams.constFind(textureID); + if (it != textureParams.end()) { + const TextureParam& p = (*it); + texture.transform.setTranslation(p.translation); + texture.transform.setRotation(glm::quat(glm::radians(p.rotation))); + texture.transform.setScale(p.scaling); + if (p.UVSet != "map1" || (p.UVSet != "UVSet0")) { + texture.texcoordSet = 1; + } + + texture.texcoordSetName = p.UVSet; + + } return texture; } @@ -1034,6 +1167,23 @@ bool checkMaterialsHaveTextures(const QHash& materials, return false; } +int matchTextureUVSetToAttributeChannel(const std::string& texUVSetName, const QHash& texcoordChannels) { + if (texUVSetName.empty()) { + return 0; + } else { + QHash::const_iterator tcUnit = texcoordChannels.find(QString(texUVSetName.c_str())); + if (tcUnit != texcoordChannels.end()) { + int channel = (*tcUnit); + if (channel >= 2) { + channel = 0; + } + return channel; + } else { + return 0; + } + } +} + FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) { QHash meshes; QHash modelIDsToNames; @@ -1048,6 +1198,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) QHash animationCurves; QHash textureNames; QHash textureFilenames; + QHash textureParams; QHash textureContent; QHash materials; QHash typeFlags; @@ -1109,7 +1260,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } } QMultiHash blendshapeChannelIndices; - + int unknown = 0; FBXGeometry geometry; float unitScaleFactor = 1.0f; foreach (const FBXNode& child, node.children) { @@ -1312,7 +1463,10 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) models.insert(getID(object.properties), model); } else if (object.name == "Texture") { + TextureParam tex; + bool texparam = false; foreach (const FBXNode& subobject, object.children) { + std::string subname = subobject.name.data(); if (subobject.name == "RelativeFilename") { // trim off any path information QByteArray filename = subobject.properties.at(0).toByteArray(); @@ -1323,8 +1477,60 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) QString name = QString(subobject.properties.at(0).toByteArray()); name = name.left(name.indexOf('[')); textureNames.insert(getID(object.properties), name); + } else if (subobject.name == "Texture_Alpha_Source") { + tex.assign(tex.alphaSource, subobject.properties.at(0).value()); + } else if (subobject.name == "ModelUVTranslation") { + tex.assign(tex.UVTranslation, glm::vec2(subobject.properties.at(0).value(), + subobject.properties.at(1).value())); + } else if (subobject.name == "ModelUVScaling") { + tex.assign(tex.UVScaling, glm::vec2(subobject.properties.at(0).value(), + subobject.properties.at(1).value())); + } else if (subobject.name == "Cropping") { + tex.assign(tex.cropping, glm::vec4(subobject.properties.at(0).value(), + subobject.properties.at(1).value(), + subobject.properties.at(2).value(), + subobject.properties.at(3).value())); + } else if (subobject.name == "Properties70") { + + QByteArray propertyName; + int index; + propertyName = "P"; + index = 4; + foreach (const FBXNode& property, subobject.children) { + if (property.name == propertyName) { + QString v = property.properties.at(0).toString(); + std::string propName = v.toStdString(); + if (property.properties.at(0) == "UVSet") { + tex.assign(tex.UVSet, property.properties.at(index).toString().toStdString()); + } else if (property.properties.at(0) == "CurrentTextureBlendMode") { + tex.assign(tex.currentTextureBlendMode, property.properties.at(index).value()); + } else if (property.properties.at(0) == "UseMaterial") { + tex.assign(tex.useMaterial, property.properties.at(index).value()); + } else if (property.properties.at(0) == "Translation") { + tex.assign(tex.translation, getVec3(property.properties, index)); + } else if (property.properties.at(0) == "Rotation") { + tex.assign(tex.rotation, getVec3(property.properties, index)); + } else if (property.properties.at(0) == "Scaling") { + tex.assign(tex.scaling, getVec3(property.properties, index)); + } else { + unknown++; + } + } + } + } else { + if (subobject.name == "Type") { + } else if (subobject.name == "Version") { + } else if (subobject.name == "FileName") { + } else if (subobject.name == "Media") { + } else { + unknown++; + } } } + + if (!tex.isDefault) { + textureParams.insert(getID(object.properties), tex); + } } else if (object.name == "Video") { QByteArray filename; QByteArray content; @@ -1670,47 +1876,63 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) const QString& childID = children.at(i); if (materials.contains(childID)) { Material material = materials.value(childID); - + bool detectDifferentUVs = false; FBXTexture diffuseTexture; QString diffuseTextureID = diffuseTextures.value(childID); if (!diffuseTextureID.isNull()) { - diffuseTexture = getTexture(diffuseTextureID, textureNames, textureFilenames, textureContent); + diffuseTexture = getTexture(diffuseTextureID, textureNames, textureFilenames, textureContent, textureParams); // FBX files generated by 3DSMax have an intermediate texture parent, apparently foreach (const QString& childTextureID, childMap.values(diffuseTextureID)) { if (textureFilenames.contains(childTextureID)) { - diffuseTexture = getTexture(diffuseTextureID, textureNames, textureFilenames, textureContent); + diffuseTexture = getTexture(diffuseTextureID, textureNames, textureFilenames, textureContent, textureParams); } } + diffuseTexture.texcoordSet = matchTextureUVSetToAttributeChannel(diffuseTexture.texcoordSetName, extracted.texcoordSetMap); + + detectDifferentUVs = (diffuseTexture.texcoordSet != 0) || (!diffuseTexture.transform.isIdentity()); } FBXTexture normalTexture; QString bumpTextureID = bumpTextures.value(childID); if (!bumpTextureID.isNull()) { - normalTexture = getTexture(bumpTextureID, textureNames, textureFilenames, textureContent); + normalTexture = getTexture(bumpTextureID, textureNames, textureFilenames, textureContent, textureParams); generateTangents = true; + + normalTexture.texcoordSet = matchTextureUVSetToAttributeChannel(normalTexture.texcoordSetName, extracted.texcoordSetMap); + + detectDifferentUVs |= (normalTexture.texcoordSet != 0) || (!normalTexture.transform.isIdentity()); } FBXTexture specularTexture; QString specularTextureID = specularTextures.value(childID); if (!specularTextureID.isNull()) { - specularTexture = getTexture(specularTextureID, textureNames, textureFilenames, textureContent); + specularTexture = getTexture(specularTextureID, textureNames, textureFilenames, textureContent, textureParams); + specularTexture.texcoordSet = matchTextureUVSetToAttributeChannel(specularTexture.texcoordSetName, extracted.texcoordSetMap); + detectDifferentUVs |= (specularTexture.texcoordSet != 0) || (!specularTexture.transform.isIdentity()); } FBXTexture emissiveTexture; QString emissiveTextureID = emissiveTextures.value(childID); if (!emissiveTextureID.isNull()) { - emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent); + emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent, textureParams); // FBX files generated by 3DSMax have an intermediate texture parent, apparently foreach (const QString& childTextureID, childMap.values(diffuseTextureID)) { if (textureFilenames.contains(childTextureID)) { - emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent); + emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent, textureParams); } } + + emissiveTexture.texcoordSet = matchTextureUVSetToAttributeChannel(emissiveTexture.texcoordSetName, extracted.texcoordSetMap); + + detectDifferentUVs |= (emissiveTexture.texcoordSet != 0) || (!emissiveTexture.transform.isIdentity()); + } + + if (detectDifferentUVs) { + detectDifferentUVs = false; } - for (int j = 0; j < extracted.partMaterialTextures.size(); j++) { if (extracted.partMaterialTextures.at(j).first == materialIndex) { FBXMeshPart& part = extracted.mesh.parts[j]; @@ -1737,7 +1959,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) materialIndex++; } else if (textureFilenames.contains(childID)) { - FBXTexture texture = getTexture(childID, textureNames, textureFilenames, textureContent); + FBXTexture texture = getTexture(childID, textureNames, textureFilenames, textureContent, textureParams); for (int j = 0; j < extracted.partMaterialTextures.size(); j++) { int partTexture = extracted.partMaterialTextures.at(j).second; if (partTexture == textureIndex && !(partTexture == 0 && materialsHaveTextures)) { diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 892dd7a2fd..60e8ea2448 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -102,6 +103,10 @@ public: QString name; QByteArray filename; QByteArray content; + + Transform transform; + int texcoordSet; + std::string texcoordSetName; }; /// A single part of a mesh (with the same material). @@ -136,13 +141,14 @@ public: QVector tangents; QVector colors; QVector texCoords; + QVector texCoords1; QVector clusterIndices; QVector clusterWeights; QVector clusters; Extents meshExtents; - + bool isEye; QVector blendshapes; diff --git a/libraries/shared/src/Transform.h b/libraries/shared/src/Transform.h index 5ce5667a81..4adeccb46f 100644 --- a/libraries/shared/src/Transform.h +++ b/libraries/shared/src/Transform.h @@ -136,7 +136,10 @@ protected: void invalidCache() const { _flags.set(FLAG_CACHE_INVALID, true); } void flagTranslation() { _flags.set(FLAG_TRANSLATION, true); } + void unflagTranslation() { _flags.set(FLAG_TRANSLATION, false); } + void flagRotation() { _flags.set(FLAG_ROTATION, true); } + void unflagRotation() { _flags.set(FLAG_ROTATION, false); } void flagScaling() { _flags.set(FLAG_SCALING, true); } void unflagScaling() { _flags.set(FLAG_SCALING, false); } @@ -162,17 +165,23 @@ inline const Transform::Vec3& Transform::getTranslation() const { inline void Transform::setTranslation(const Vec3& translation) { invalidCache(); - flagTranslation(); + if (translation == Vec3()) { + unflagTranslation(); + } else { + flagTranslation(); + } _translation = translation; } inline void Transform::preTranslate(const Vec3& translation) { + if (translation == Vec3() ) return; invalidCache(); flagTranslation(); _translation += translation; } inline void Transform::postTranslate(const Vec3& translation) { + if (translation == Vec3() ) return; invalidCache(); flagTranslation(); @@ -192,11 +201,16 @@ inline const Transform::Quat& Transform::getRotation() const { inline void Transform::setRotation(const Quat& rotation) { invalidCache(); - flagRotation(); + if (rotation == Quat()) { + unflagRotation(); + } else { + flagRotation(); + } _rotation = rotation; } inline void Transform::preRotate(const Quat& rotation) { + if (rotation == Quat()) return; invalidCache(); if (isRotating()) { _rotation = rotation * _rotation; @@ -204,10 +218,12 @@ inline void Transform::preRotate(const Quat& rotation) { _rotation = rotation; } flagRotation(); + _translation = glm::rotate(rotation, _translation); } inline void Transform::postRotate(const Quat& rotation) { + if (rotation == Quat()) return; invalidCache(); if (isNonUniform()) { From 2edd2525763245693e8aa693a5fe8394b95e6a83 Mon Sep 17 00:00:00 2001 From: Adrianl3d Date: Sat, 22 Nov 2014 21:47:14 +1000 Subject: [PATCH 06/24] Fix persist time Set persist time to 10 secs --- examples/notifications.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/notifications.js b/examples/notifications.js index 3357d55096..3d0b05521d 100644 --- a/examples/notifications.js +++ b/examples/notifications.js @@ -63,7 +63,7 @@ var textColor = { red: 228, green: 228, blue: 228}; // text color var backColor = { red: 38, green: 38, blue: 38}; // background color var backgroundAlpha = 0; var fontSize = 12.0; -var persistTime = 5.0; // time in seconds before notification fades +var persistTime = 10.0; // time in seconds before notification fades var clickedText = false; var frame = 0; var ourWidth = Window.innerWidth; From ffe66cd5c5b8e1d658c09739fcf37111ac7953d3 Mon Sep 17 00:00:00 2001 From: Adrianl3d Date: Tue, 25 Nov 2014 04:23:00 +1000 Subject: [PATCH 07/24] Clean up code Fix code to standards --- examples/notifications.js | 72 +++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/examples/notifications.js b/examples/notifications.js index 3d0b05521d..16e9dd70b2 100644 --- a/examples/notifications.js +++ b/examples/notifications.js @@ -76,7 +76,7 @@ var ready = true; // When our script shuts down, we should clean up all of our overlays function scriptEnding() { - for (i = 0; i < notifications.length; i++){ + for (i = 0; i < notifications.length; i++) { Overlays.deleteOverlay(notifications[i]); Overlays.deleteOverlay(buttons[i]); } @@ -91,23 +91,23 @@ var myAlpha = []; var arrays = []; // This function creates and sizes the overlays -function createNotification(text){ +function createNotification(text) { var count = (text.match(/\n/g) || []).length; var breakPoint = 43.0; // length when new line is added var extraLine = 0; - var breaks = 0; + var breaks = 0; var height = 40.0; var stack = 0; - if (text.length >= breakPoint){ + if (text.length >= breakPoint) { breaks = count; } - var extraLine = breaks * 16.0; - for (i = 0; i < heights.length; i++){ + var extraLine = breaks * 16.0; + for (i = 0; i < heights.length; i++) { stack = stack + heights[i]; } - var level = (stack + 20.0 ); + var level = (stack + 20.0); height = height + extraLine; - var overlayProperties = { + var overlayProperties = { x: overlayLocationX, y: level, width: width, @@ -142,18 +142,18 @@ function createNotification(text){ // specifically notification "heights", "times" of creation, and . function Notify(notice, button, height){ - notifications.push((Overlays.addOverlay("text",notice))); + notifications.push((Overlays.addOverlay("text", notice))); buttons.push((Overlays.addOverlay("image",button))); times.push(new Date().getTime() / 1000); height = height + 1.0; heights.push(height); myAlpha.push(0); var last = notifications.length - 1; - createArrays(notifications[last], buttons[last], times[last], heights[last], myAlpha[last]); + createArrays(notifications[last], buttons[last], times[last], heights[last], myAlpha[last]); fadeIn(notifications[last], buttons[last]) } -function fadeIn(noticeIn, buttonIn){ +function fadeIn(noticeIn, buttonIn) { var myLength = arrays.length; var q = 0; var pauseTimer = null; @@ -170,14 +170,14 @@ function fadeIn(noticeIn, buttonIn){ // push data from above to the 2 dimensional array -function createArrays(notice, button, createTime, height, myAlpha){ +function createArrays(notice, button, createTime, height, myAlpha) { arrays.push([notice, button, createTime, height, myAlpha]); } // handles mouse clicks on buttons function mousePressEvent(event) { var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); //identify which overlay was clicked - for (i = 0; i < buttons.length; i++){ //if user clicked a button - if(clickedOverlay == buttons[i]){ + for (i = 0; i < buttons.length; i++) { //if user clicked a button + if(clickedOverlay == buttons[i]) { Overlays.deleteOverlay(notifications[i]); Overlays.deleteOverlay(buttons[i]); notifications.splice(i, 1); @@ -191,25 +191,25 @@ function mousePressEvent(event) { } // Control key remains active only while key is held down -function keyReleaseEvent(key){ - if (key.key == 16777249){ +function keyReleaseEvent(key) { + if (key.key == 16777249) { ctrlIsPressed = false; } } // Triggers notification on specific key driven events function keyPressEvent(key) { - if (key.key == 16777249){ + if (key.key == 16777249) { ctrlIsPressed = true; } if (key.text == "a") { - var noteString = "Turning to the Left"; + var noteString = "Turning to the Left"; createNotification(noteString); } if (key.text == "d") { - var noteString = "Turning to the Right"; + var noteString = "Turning to the Right"; createNotification(noteString); - } + } if (key.text == "s") { if (ctrlIsPressed == true){ var noteString = "You have taken a snapshot"; @@ -219,20 +219,20 @@ function keyPressEvent(key) { if (key.text == "q") { var noteString = "Enable Scripted Motor control is now on."; wordWrap(noteString); - } + } if (key.text == "w") { var noteString = "This notification spans 2 lines. The overlay will resize to fit new lines."; var noteString = "editVoxels.js stopped, editModels.js stopped, selectAudioDevice.js stopped."; wordWrap(noteString); - } + } if (key.text == "e") { var noteString = "This is an example of a multiple line notification. This notification will span 3 lines." wordWrap(noteString); - } + } if (key.text == "r") { var noteString = "This is a very long line of text that we are going to use in this example to divide it into rows of maximum 43 chars and see how many lines we use."; wordWrap(noteString); - } + } if (key.text == "SPACE") { var noteString = "You have pressed the Spacebar, This is an example of a multiple line notification. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam."; wordWrap(noteString); @@ -240,7 +240,7 @@ function keyPressEvent(key) { } // formats string to add newline every 43 chars -function wordWrap(str){ +function wordWrap(str) { var result = stringDivider(str, 43.0, "\n"); createNotification(result); } @@ -261,7 +261,7 @@ function stringDivider(str, slotWidth, spaceReplacer) { // This fires a notification on window resize function checkSize(){ - if((Window.innerWidth!=ourWidth)||(Window.innerHeight!=ourHeight)){ + if((Window.innerWidth != ourWidth)||(Window.innerHeight != ourHeight)) { var windowResize = "Window has been resized"; ourWidth = Window.innerWidth; ourHeight = Window.innerHeight; @@ -285,7 +285,7 @@ function onOnlineUsersChanged(users) { for (user in last_users) { if (users.indexOf(last_users[user]) == -1.0) { leavers.push(last_users[user]); - createNotification(last_users[user] + " Has left"); + createNotification(last_users[user] + " Has left"); } } last_users = users; @@ -312,20 +312,20 @@ function update(){ if ((frame % 60.0) == 0) { // only update once a second checkSize(); // checks for size change to trigger windowResize notification locationY = 20.0; - for (var i = 0; i < arrays.length; i++){ //repositions overlays as others fade - var nextOverlay = Overlays.getOverlayAtPoint({x: overlayLocationX, y: locationY }); + for (var i = 0; i < arrays.length; i++) { //repositions overlays as others fade + var nextOverlay = Overlays.getOverlayAtPoint({x: overlayLocationX, y: locationY}); Overlays.editOverlay(notifications[i], { x:overlayLocationX, y:locationY}); Overlays.editOverlay(buttons[i], { x:buttonLocationX, y:locationY + 12.0}); - locationY=locationY + arrays[i][3]; + locationY = locationY + arrays[i][3]; } } // This checks the age of the notification and prepares to fade it after 9.0 seconds (var persistTime - 1) - for (var i = 0; i < arrays.length; i++){ + for (var i = 0; i < arrays.length; i++) { if (ready){ var j = arrays[i][2]; var k = j + persistTime; - if (k < (new Date().getTime() / 1000)){ + if (k < (new Date().getTime() / 1000)) { ready = false; noticeOut = arrays[i][0]; buttonOut = arrays[i][1]; @@ -337,8 +337,8 @@ function update(){ } // this fades the notification ready for dismissal, and removes it from the arrays -function fadeOut(noticeOut, buttonOut, arraysOut){ - var myLength = arrays.length; +function fadeOut(noticeOut, buttonOut, arraysOut) { + var myLength = arrays.length; var r = 9.0; var pauseTimer = null; pauseTimer = Script.setInterval(function() { @@ -356,8 +356,8 @@ function fadeOut(noticeOut, buttonOut, arraysOut){ } // This handles the final dismissal of a notification after fading -function dismiss(firstNoteOut, firstButOut, firstOut){ -var working = firstOut +function dismiss(firstNoteOut, firstButOut, firstOut) { + var working = firstOut Overlays.deleteOverlay(firstNoteOut); Overlays.deleteOverlay(firstButOut); notifications.splice(firstOut, 1); From 8b23a2cd1ee95f0b0648361350827a18cc8be060 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 24 Nov 2014 10:33:31 -0800 Subject: [PATCH 08/24] adding the shader files for the lightmap case --- .../resources/shaders/model_lightmap.frag | 36 +++++++++++++ .../resources/shaders/model_lightmap.vert | 40 ++++++++++++++ .../shaders/model_lightmap_normal_map.frag | 49 +++++++++++++++++ .../shaders/model_lightmap_normal_map.vert | 46 ++++++++++++++++ .../model_lightmap_normal_specular_map.frag | 53 +++++++++++++++++++ .../shaders/model_lightmap_specular_map.frag | 39 ++++++++++++++ 6 files changed, 263 insertions(+) create mode 100644 interface/resources/shaders/model_lightmap.frag create mode 100644 interface/resources/shaders/model_lightmap.vert create mode 100644 interface/resources/shaders/model_lightmap_normal_map.frag create mode 100644 interface/resources/shaders/model_lightmap_normal_map.vert create mode 100644 interface/resources/shaders/model_lightmap_normal_specular_map.frag create mode 100644 interface/resources/shaders/model_lightmap_specular_map.frag diff --git a/interface/resources/shaders/model_lightmap.frag b/interface/resources/shaders/model_lightmap.frag new file mode 100644 index 0000000000..0b7798f610 --- /dev/null +++ b/interface/resources/shaders/model_lightmap.frag @@ -0,0 +1,36 @@ +#version 120 + +// +// model_lightmap.frag +// fragment shader +// +// Created by Samuel Gateau on 11/19/14. +// Copyright 2013 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 +// + +// the diffuse texture +uniform sampler2D diffuseMap; + +// the emissive map texture +uniform sampler2D emissiveMap; + +// the alpha threshold +uniform float alphaThreshold; + +// the interpolated normal +varying vec4 normal; + +// the interpolated texcoord1 +varying vec2 interpolatedTexcoord1; + +void main(void) { + // set the diffuse, normal, specular data + vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); + vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); + gl_FragData[0] = vec4(diffuse.rgb * (vec3(0.3) + emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); + gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); +} diff --git a/interface/resources/shaders/model_lightmap.vert b/interface/resources/shaders/model_lightmap.vert new file mode 100644 index 0000000000..021db11796 --- /dev/null +++ b/interface/resources/shaders/model_lightmap.vert @@ -0,0 +1,40 @@ +#version 120 + +// +// model_lightmap.vert +// vertex shader +// +// Created by Sam Gateau on 11/21/14. +// Copyright 2013 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 +// + +const int MAX_TEXCOORDS = 2; + +uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; + +attribute vec2 texcoord1; + +// the interpolated normal +varying vec4 normal; + +// the interpolated texcoord1 +varying vec2 interpolatedTexcoord1; + +void main(void) { + // transform and store the normal for interpolation + normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); + + // pass along the diffuse color + gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; + + // and the texture coordinates + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); + interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.f, 1.f)).xy; + + // use standard pipeline transform + gl_Position = ftransform(); +} + diff --git a/interface/resources/shaders/model_lightmap_normal_map.frag b/interface/resources/shaders/model_lightmap_normal_map.frag new file mode 100644 index 0000000000..d63fd91fd0 --- /dev/null +++ b/interface/resources/shaders/model_lightmap_normal_map.frag @@ -0,0 +1,49 @@ +#version 120 + +// +// model_lightmap_normal_map.frag +// fragment shader +// +// Created by Samuel Gateau on 11/19/14. +// Copyright 2013 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 +// + +// the diffuse texture +uniform sampler2D diffuseMap; + +// the normal map texture +uniform sampler2D normalMap; + +// the emissive map texture +uniform sampler2D emissiveMap; + +// the alpha threshold +uniform float alphaThreshold; + +// the interpolated normal +varying vec4 interpolatedNormal; + +// the interpolated tangent +varying vec4 interpolatedTangent; + +varying vec2 interpolatedTexcoord1; + +void main(void) { + // compute the view normal from the various bits + vec3 normalizedNormal = normalize(vec3(interpolatedNormal)); + vec3 normalizedTangent = normalize(vec3(interpolatedTangent)); + vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent)); + vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) - vec3(0.5, 0.5, 0.5); + vec4 viewNormal = vec4(normalizedTangent * localNormal.x + + normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0); + + // set the diffuse, normal, specular data + vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); + vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); + gl_FragData[0] = vec4(gl_Color.rgb * emissive.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0); + gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); +} diff --git a/interface/resources/shaders/model_lightmap_normal_map.vert b/interface/resources/shaders/model_lightmap_normal_map.vert new file mode 100644 index 0000000000..08eca835c9 --- /dev/null +++ b/interface/resources/shaders/model_lightmap_normal_map.vert @@ -0,0 +1,46 @@ +#version 120 + +// +// model_lightmap_normal_map.vert +// vertex shader +// +// Created by Sam Gateau on 11/21/14. +// Copyright 2013 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 +// + +const int MAX_TEXCOORDS = 2; + +uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; + +// the tangent vector +attribute vec3 tangent; + +attribute vec2 texcoord1; + +// the interpolated normal +varying vec4 interpolatedNormal; + +// the interpolated tangent +varying vec4 interpolatedTangent; + +// the interpolated texcoord1 +varying vec2 interpolatedTexcoord1; + +void main(void) { + // transform and store the normal and tangent for interpolation + interpolatedNormal = gl_ModelViewMatrix * vec4(gl_Normal, 0.0); + interpolatedTangent = gl_ModelViewMatrix * vec4(tangent, 0.0); + + // pass along the diffuse color + gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; + + // and the texture coordinates + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); + interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.f, 1.f)).xy; + + // use standard pipeline transform + gl_Position = ftransform(); +} diff --git a/interface/resources/shaders/model_lightmap_normal_specular_map.frag b/interface/resources/shaders/model_lightmap_normal_specular_map.frag new file mode 100644 index 0000000000..9b602c5a3b --- /dev/null +++ b/interface/resources/shaders/model_lightmap_normal_specular_map.frag @@ -0,0 +1,53 @@ +#version 120 + +// +// model_lightmap_normal_specular_map.frag +// fragment shader +// +// Created by Samuel Gateau on 11/19/14. +// 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 +// + +// the diffuse texture +uniform sampler2D diffuseMap; + +// the emissive map texture +uniform sampler2D emissiveMap; + +// the normal map texture +uniform sampler2D normalMap; + +// the specular map texture +uniform sampler2D specularMap; + +// the alpha threshold +uniform float alphaThreshold; + +// the interpolated normal +varying vec4 interpolatedNormal; + +// the interpolated tangent +varying vec4 interpolatedTangent; + +varying vec2 interpolatedTexcoord1; + +void main(void) { + // compute the view normal from the various bits + vec3 normalizedNormal = normalize(vec3(interpolatedNormal)); + vec3 normalizedTangent = normalize(vec3(interpolatedTangent)); + vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent)); + vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) - vec3(0.5, 0.5, 0.5); + vec4 viewNormal = vec4(normalizedTangent * localNormal.x + + normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0); + + // set the diffuse, normal, specular data + vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); + vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); + gl_FragData[0] = vec4(gl_Color.rgb * emissive.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0); + gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, + gl_FrontMaterial.shininess / 128.0); +} diff --git a/interface/resources/shaders/model_lightmap_specular_map.frag b/interface/resources/shaders/model_lightmap_specular_map.frag new file mode 100644 index 0000000000..d60f21dffb --- /dev/null +++ b/interface/resources/shaders/model_lightmap_specular_map.frag @@ -0,0 +1,39 @@ +#version 120 + +// +// model_lightmap_specular_map.frag +// fragment shader +// +// Created by Samuel Gateau on 11/19/14. +// 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 +// + +// the diffuse texture +uniform sampler2D diffuseMap; + +// the emissive map texture +uniform sampler2D emissiveMap; + +// the specular texture +uniform sampler2D specularMap; + +// the alpha threshold +uniform float alphaThreshold; + +// the interpolated normal +varying vec4 normal; + +varying vec2 interpolatedTexcoord1; + +void main(void) { + // set the diffuse, normal, specular data + vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); + vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); + gl_FragData[0] = vec4(gl_Color.rgb * emissive.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); + gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, + gl_FrontMaterial.shininess / 128.0); +} From 6591f4dac296ce51dc23b307a766dbf9d061c3d3 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 24 Nov 2014 11:18:21 -0800 Subject: [PATCH 09/24] adjust lighmap shading equation --- interface/resources/shaders/model_lightmap.frag | 2 +- interface/resources/shaders/model_lightmap_normal_map.frag | 2 +- .../resources/shaders/model_lightmap_normal_specular_map.frag | 2 +- interface/resources/shaders/model_lightmap_specular_map.frag | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/resources/shaders/model_lightmap.frag b/interface/resources/shaders/model_lightmap.frag index 0b7798f610..67d9cd0218 100644 --- a/interface/resources/shaders/model_lightmap.frag +++ b/interface/resources/shaders/model_lightmap.frag @@ -30,7 +30,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(diffuse.rgb * (vec3(0.3) + emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); } diff --git a/interface/resources/shaders/model_lightmap_normal_map.frag b/interface/resources/shaders/model_lightmap_normal_map.frag index d63fd91fd0..6d3e3aa861 100644 --- a/interface/resources/shaders/model_lightmap_normal_map.frag +++ b/interface/resources/shaders/model_lightmap_normal_map.frag @@ -43,7 +43,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * emissive.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); } diff --git a/interface/resources/shaders/model_lightmap_normal_specular_map.frag b/interface/resources/shaders/model_lightmap_normal_specular_map.frag index 9b602c5a3b..89333bbcef 100644 --- a/interface/resources/shaders/model_lightmap_normal_specular_map.frag +++ b/interface/resources/shaders/model_lightmap_normal_specular_map.frag @@ -46,7 +46,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * emissive.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, gl_FrontMaterial.shininess / 128.0); diff --git a/interface/resources/shaders/model_lightmap_specular_map.frag b/interface/resources/shaders/model_lightmap_specular_map.frag index d60f21dffb..3526ecdf9c 100644 --- a/interface/resources/shaders/model_lightmap_specular_map.frag +++ b/interface/resources/shaders/model_lightmap_specular_map.frag @@ -32,7 +32,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * emissive.rgb, mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, gl_FrontMaterial.shininess / 128.0); From f67b4b9ff4fa043e9805944110594c5d4346615a Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 24 Nov 2014 11:44:54 -0800 Subject: [PATCH 10/24] clean out comments so the 2 rendering modes for entities work, scene batch or per model batch --- interface/src/renderer/Model.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index d2a2378689..3f68201386 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1635,7 +1635,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { 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, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, false, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, true, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, false, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, true, args); @@ -1643,7 +1643,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, true, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, false, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, true, args); -*/ + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, false, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, false, args); opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, args); @@ -1661,7 +1661,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { int translucentParts = 0; const float MOSTLY_OPAQUE_THRESHOLD = 0.75f; - /* translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, false, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, true, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, false, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, true, args); @@ -1669,7 +1669,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, true, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args); - */ + GLBATCH(glDisable)(GL_ALPHA_TEST); GLBATCH(glEnable)(GL_BLEND); GLBATCH(glDepthMask)(false); @@ -1685,7 +1685,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; - /* translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, false, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, true, args); @@ -1693,7 +1693,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, false, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, args); - */ } + } GLBATCH(glDepthMask)(true); GLBATCH(glDepthFunc)(GL_LESS); From 08772bbae0fef5b79f49a03c5a7a996126d4f463 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 24 Nov 2014 13:07:22 -0800 Subject: [PATCH 11/24] remove spatial audio menu items --- interface/src/Audio.cpp | 6 ++-- interface/src/AudioReflector.cpp | 48 +++++++++++++++++------------ interface/src/Menu.cpp | 52 -------------------------------- interface/src/Menu.h | 12 -------- interface/src/ui/Stats.cpp | 43 +++++++++++++------------- 5 files changed, 55 insertions(+), 106 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 75b8c252f7..167c44111e 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -989,7 +989,8 @@ void Audio::processReceivedSamples(const QByteArray& inputBuffer, QByteArray& ou QByteArray buffer = inputBuffer; // Accumulate direct transmission of audio from sender to receiver - if (Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingIncludeOriginal)) { + bool includeOriginal = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingIncludeOriginal) + if (includeOriginal) { emit preProcessOriginalInboundAudio(sampleTime, buffer, _desiredOutputFormat); addSpatialAudioToBuffer(sampleTime, buffer, numNetworkOutputSamples); } @@ -1264,7 +1265,8 @@ void Audio::selectAudioSourceSine440() { } void Audio::toggleAudioSpatialProcessing() { - _processSpatialAudio = !_processSpatialAudio; + // spatial audio disabled for now + _processSpatialAudio = false; //!_processSpatialAudio; if (_processSpatialAudio) { _spatialAudioStart = 0; _spatialAudioFinish = 0; diff --git a/interface/src/AudioReflector.cpp b/interface/src/AudioReflector.cpp index e18a0ad36e..8a23ecee79 100644 --- a/interface/src/AudioReflector.cpp +++ b/interface/src/AudioReflector.cpp @@ -66,10 +66,15 @@ AudioReflector::AudioReflector(QObject* parent) : } bool AudioReflector::haveAttributesChanged() { - bool withDiffusion = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingWithDiffusions); - bool dontDistanceAttenuate = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingDontDistanceAttenuate); - bool alternateDistanceAttenuate = Menu::getInstance()->isOptionChecked( - MenuOption::AudioSpatialProcessingAlternateDistanceAttenuate); + + // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingWithDiffusions); + bool withDiffusion = true; + + // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingDontDistanceAttenuate); + bool dontDistanceAttenuate = false; + + //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingAlternateDistanceAttenuate); + bool alternateDistanceAttenuate = false; bool attributesChange = (_withDiffusion != withDiffusion || _lastPreDelay != _preDelay @@ -107,7 +112,8 @@ void AudioReflector::render() { calculateAllReflections(); // only render if we've been asked to do so - if (Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingRenderPaths)) { + bool renderPaths = false; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingRenderPaths) + if (renderPaths) { drawRays(); } } @@ -116,7 +122,8 @@ void AudioReflector::render() { // = 3ms per meter float AudioReflector::getDelayFromDistance(float distance) { float delay = (_soundMsPerMeter * distance); - if (Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingPreDelay)) { + bool includePreDelay = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingPreDelay) + if (includePreDelay) { delay += _preDelay; } return delay; @@ -126,12 +133,11 @@ float AudioReflector::getDelayFromDistance(float distance) { float AudioReflector::getDistanceAttenuationCoefficient(float distance) { - bool doDistanceAttenuation = !Menu::getInstance()->isOptionChecked( - MenuOption::AudioSpatialProcessingDontDistanceAttenuate); + //!Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingDontDistanceAttenuate); + bool doDistanceAttenuation = true; - bool originalFormula = !Menu::getInstance()->isOptionChecked( - MenuOption::AudioSpatialProcessingAlternateDistanceAttenuate); - + //!Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingAlternateDistanceAttenuate); + bool originalFormula = true; float distanceCoefficient = 1.0f; @@ -170,7 +176,8 @@ float AudioReflector::getDistanceAttenuationCoefficient(float distance) { } glm::vec3 AudioReflector::getFaceNormal(BoxFace face) { - bool wantSlightRandomness = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingSlightlyRandomSurfaces); + // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingSlightlyRandomSurfaces); + bool wantSlightRandomness = true; glm::vec3 faceNormal; const float MIN_RANDOM_LENGTH = 0.99f; const float MAX_RANDOM_LENGTH = 1.0f; @@ -202,8 +209,8 @@ const int NUMBER_OF_CHANNELS = 2; void AudioReflector::injectAudiblePoint(AudioSource source, const AudiblePoint& audiblePoint, const QByteArray& samples, unsigned int sampleTime, int sampleRate) { - bool wantEarSeparation = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingSeparateEars); - bool wantStereo = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingStereoSource); + bool wantEarSeparation = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingSeparateEars); + bool wantStereo = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingStereoSource); glm::vec3 rightEarPosition = wantEarSeparation ? _myAvatar->getHead()->getRightEarPosition() : _myAvatar->getHead()->getPosition(); glm::vec3 leftEarPosition = wantEarSeparation ? _myAvatar->getHead()->getLeftEarPosition() : @@ -316,7 +323,8 @@ void AudioReflector::preProcessOriginalInboundAudio(unsigned int sampleTime, } void AudioReflector::processLocalAudio(unsigned int sampleTime, const QByteArray& samples, const QAudioFormat& format) { - if (Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingProcessLocalAudio)) { + bool processLocalAudio = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingProcessLocalAudio) + if (processLocalAudio) { const int NUM_CHANNELS_INPUT = 1; const int NUM_CHANNELS_OUTPUT = 2; const int EXPECTED_SAMPLE_RATE = 24000; @@ -458,7 +466,7 @@ void AudioReflector::identifyAudioSources() { void AudioReflector::calculateAllReflections() { // only recalculate when we've moved, or if the attributes have changed // TODO: what about case where new voxels are added in front of us??? - bool wantHeadOrientation = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingHeadOriented); + bool wantHeadOrientation = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingHeadOriented); glm::quat orientation = wantHeadOrientation ? _myAvatar->getHead()->getFinalOrientationInWorldFrame() : _myAvatar->getOrientation(); glm::vec3 origin = _myAvatar->getHead()->getPosition(); glm::vec3 listenerPosition = _myAvatar->getHead()->getPosition(); @@ -505,7 +513,8 @@ void AudioReflector::drawRays() { } } - if (Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingProcessLocalAudio)) { + bool processLocalAudio = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingProcessLocalAudio) + if (processLocalAudio) { // draw the paths for local audio foreach(AudioPath* const& path, _localAudioPaths) { // if this is an original reflection, draw it in RED @@ -575,7 +584,8 @@ void AudioReflector::analyzePaths() { float initialAttenuation = 1.0f; - float preDelay = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingPreDelay) ? _preDelay : 0.0f; + bool wantPreDelay = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingPreDelay) + float preDelay = wantPreDelay ? _preDelay : 0.0f; // NOTE: we're still calculating our initial paths based on the listeners position. But the analysis code has been // updated to support individual sound sources (which is how we support diffusion), we can use this new paradigm to @@ -701,7 +711,7 @@ void AudioReflector::handlePathPoint(AudioPath* path, float distance, OctreeElem float reflectiveAttenuation = currentReflectiveAttenuation * material.reflectiveRatio; float totalDiffusionAttenuation = currentReflectiveAttenuation * material.diffusionRatio; - bool wantDiffusions = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingWithDiffusions); + bool wantDiffusions = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingWithDiffusions); int fanout = wantDiffusions ? _diffusionFanout : 0; float partialDiffusionAttenuation = fanout < 1 ? 0.0f : totalDiffusionAttenuation / (float)fanout; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index db5cd5170d..baac3629ac 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -620,58 +620,6 @@ Menu::Menu() : audioScopeFramesGroup->addAction(fiftyFrames); } - QMenu* spatialAudioMenu = audioDebugMenu->addMenu("Spatial Audio"); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessing, - Qt::CTRL | Qt::SHIFT | Qt::Key_M, - false, - appInstance->getAudio(), - SLOT(toggleAudioSpatialProcessing())); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingIncludeOriginal, - Qt::CTRL | Qt::SHIFT | Qt::Key_O, - true); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingSeparateEars, - Qt::CTRL | Qt::SHIFT | Qt::Key_E, - true); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingPreDelay, - Qt::CTRL | Qt::SHIFT | Qt::Key_D, - true); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingStereoSource, - Qt::CTRL | Qt::SHIFT | Qt::Key_S, - true); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingHeadOriented, - Qt::CTRL | Qt::SHIFT | Qt::Key_H, - true); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingWithDiffusions, - Qt::CTRL | Qt::SHIFT | Qt::Key_W, - true); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingRenderPaths, - Qt::CTRL | Qt::SHIFT | Qt::Key_R, - true); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingSlightlyRandomSurfaces, - Qt::CTRL | Qt::SHIFT | Qt::Key_X, - true); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingProcessLocalAudio, - Qt::CTRL | Qt::SHIFT | Qt::Key_A, - true); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingDontDistanceAttenuate, - Qt::CTRL | Qt::SHIFT | Qt::Key_Y, - false); - - addCheckableActionToQMenuAndActionHash(spatialAudioMenu, MenuOption::AudioSpatialProcessingAlternateDistanceAttenuate, - Qt::CTRL | Qt::SHIFT | Qt::Key_U, - false); - addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioStats, Qt::CTRL | Qt::Key_A, false, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 7e153eba5e..6ba34ca2b9 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -341,18 +341,6 @@ namespace MenuOption { const QString AudioScopeTwentyFrames = "Twenty"; const QString AudioStats = "Audio Stats"; const QString AudioStatsShowInjectedStreams = "Audio Stats Show Injected Streams"; - const QString AudioSpatialProcessingAlternateDistanceAttenuate = "Alternate distance attenuation"; - const QString AudioSpatialProcessing = "Audio Spatial Processing"; - const QString AudioSpatialProcessingDontDistanceAttenuate = "Don't calculate distance attenuation"; - const QString AudioSpatialProcessingHeadOriented = "Head Oriented"; - const QString AudioSpatialProcessingIncludeOriginal = "Includes Network Original"; - const QString AudioSpatialProcessingPreDelay = "Add Pre-Delay"; - const QString AudioSpatialProcessingProcessLocalAudio = "Process Local Audio"; - const QString AudioSpatialProcessingRenderPaths = "Render Paths"; - const QString AudioSpatialProcessingSeparateEars = "Separate Ears"; - const QString AudioSpatialProcessingSlightlyRandomSurfaces = "Slightly Random Surfaces"; - const QString AudioSpatialProcessingStereoSource = "Stereo Source"; - const QString AudioSpatialProcessingWithDiffusions = "With Diffusions"; const QString AudioSourceInject = "Generated Audio"; const QString AudioSourcePinkNoise = "Pink Noise"; const QString AudioSourceSine440 = "Sine 440hz"; diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index e0e589b627..953c964afd 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -460,7 +460,8 @@ void Stats::display( VoxelSystem* voxels = Application::getInstance()->getVoxels(); lines = _expanded ? 14 : 3; - if (_expanded && Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessing)) { + bool wantSpatialProcessing = false; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessing) + if (_expanded && wantSpatialProcessing) { lines += 10; // spatial audio processing adds 1 spacing line and 8 extra lines of info } @@ -652,7 +653,7 @@ void Stats::display( drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color); } - if (_expanded && Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessing)) { + if (_expanded && wantSpatialProcessing) { verticalOffset += STATS_PELS_PER_LINE; // space one line... const AudioReflector* audioReflector = Application::getInstance()->getAudioReflector(); @@ -660,23 +661,24 @@ void Stats::display( // add some reflection stats char reflectionsStatus[128]; + bool includeOriginal = true; //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingIncludeOriginal) + bool separateEars = true; //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingSeparateEars) + bool stereoSource = true; //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingStereoSource) + bool randomSurfaces = true; //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingSlightlyRandomSurfaces) + sprintf(reflectionsStatus, "Reflections: %d, Original: %s, Ears: %s, Source: %s, Normals: %s", audioReflector->getReflections(), - (Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingIncludeOriginal) - ? "included" : "silent"), - (Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingSeparateEars) - ? "two" : "one"), - (Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingStereoSource) - ? "stereo" : "mono"), - (Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingSlightlyRandomSurfaces) - ? "random" : "regular") + (includeOriginal ? "included" : "silent"), + (separateEars ? "two" : "one"), + (stereoSource ? "stereo" : "mono"), + (randomSurfaces ? "random" : "regular") ); verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, reflectionsStatus, color); - float preDelay = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingPreDelay) ? - audioReflector->getPreDelay() : 0.0f; + bool wantPreDelay = true; //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingPreDelay) + float preDelay = wantPreDelay ? audioReflector->getPreDelay() : 0.0f; sprintf(reflectionsStatus, "Delay: pre: %6.3f, average %6.3f, max %6.3f, min %6.3f, speed: %6.3f", preDelay, @@ -688,12 +690,12 @@ void Stats::display( verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, reflectionsStatus, color); - - bool distanceAttenuationDisabled = Menu::getInstance()->isOptionChecked( - MenuOption::AudioSpatialProcessingDontDistanceAttenuate); - bool alternateDistanceAttenuationEnabled = Menu::getInstance()->isOptionChecked( - MenuOption::AudioSpatialProcessingAlternateDistanceAttenuate); + //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingDontDistanceAttenuate); + bool distanceAttenuationDisabled = false; + + // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingAlternateDistanceAttenuate); + bool alternateDistanceAttenuationEnabled = false; sprintf(reflectionsStatus, "Attenuation: average %5.3f, max %5.3f, min %5.3f, %s: %5.3f", audioReflector->getAverageAttenuation(), @@ -706,15 +708,14 @@ void Stats::display( verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, reflectionsStatus, color); - sprintf(reflectionsStatus, "Local Audio: %s Attenuation: %5.3f", - (Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingProcessLocalAudio) - ? "yes" : "no"), + bool localAudio = true; // Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingProcessLocalAudio); + sprintf(reflectionsStatus, "Local Audio: %s Attenuation: %5.3f", (localAudio ? "yes" : "no"), audioReflector->getLocalAudioAttenuationFactor()); verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, reflectionsStatus, color); - bool diffusionEnabled = Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingWithDiffusions); + bool diffusionEnabled = true; //Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessingWithDiffusions); int fanout = diffusionEnabled ? audioReflector->getDiffusionFanout() : 0; int diffusionPaths = diffusionEnabled ? audioReflector->getDiffusionPathCount() : 0; sprintf(reflectionsStatus, "Diffusion: %s, Fanout: %d, Paths: %d", From 68e2df8fc2e02dc0223ebe271ac90a48726936b9 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 24 Nov 2014 14:35:42 -0800 Subject: [PATCH 12/24] add a emissive parameter value to the lightmap shaders --- interface/resources/shaders/model.vert | 2 +- .../resources/shaders/model_lightmap.frag | 5 +++-- .../resources/shaders/model_lightmap.vert | 4 ++-- .../shaders/model_lightmap_normal_map.frag | 5 +++-- .../model_lightmap_normal_specular_map.frag | 5 +++-- .../shaders/model_lightmap_specular_map.frag | 5 +++-- .../resources/shaders/model_normal_map.vert | 2 +- interface/src/gpu/Batch.h | 2 ++ interface/src/gpu/GLBackend.cpp | 18 ++++++++++++++++++ interface/src/gpu/GLBackend.h | 1 + interface/src/renderer/GeometryCache.cpp | 2 ++ interface/src/renderer/Model.cpp | 5 +++++ interface/src/renderer/Model.h | 1 + 13 files changed, 45 insertions(+), 12 deletions(-) diff --git a/interface/resources/shaders/model.vert b/interface/resources/shaders/model.vert index 5ae6ea1cb6..bb0cb32d05 100644 --- a/interface/resources/shaders/model.vert +++ b/interface/resources/shaders/model.vert @@ -26,7 +26,7 @@ void main(void) { gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); // use standard pipeline transform gl_Position = ftransform(); diff --git a/interface/resources/shaders/model_lightmap.frag b/interface/resources/shaders/model_lightmap.frag index 67d9cd0218..b93f0abc6f 100644 --- a/interface/resources/shaders/model_lightmap.frag +++ b/interface/resources/shaders/model_lightmap.frag @@ -14,8 +14,9 @@ // the diffuse texture uniform sampler2D diffuseMap; -// the emissive map texture +// the emissive map texture and parameters uniform sampler2D emissiveMap; +uniform vec2 emissiveParams; // the alpha threshold uniform float alphaThreshold; @@ -30,7 +31,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); } diff --git a/interface/resources/shaders/model_lightmap.vert b/interface/resources/shaders/model_lightmap.vert index 021db11796..ff1b07e503 100644 --- a/interface/resources/shaders/model_lightmap.vert +++ b/interface/resources/shaders/model_lightmap.vert @@ -31,8 +31,8 @@ void main(void) { gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); - interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.f, 1.f)).xy; + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); + interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.0, 1.0)).xy; // use standard pipeline transform gl_Position = ftransform(); diff --git a/interface/resources/shaders/model_lightmap_normal_map.frag b/interface/resources/shaders/model_lightmap_normal_map.frag index 6d3e3aa861..475126eb0c 100644 --- a/interface/resources/shaders/model_lightmap_normal_map.frag +++ b/interface/resources/shaders/model_lightmap_normal_map.frag @@ -17,8 +17,9 @@ uniform sampler2D diffuseMap; // the normal map texture uniform sampler2D normalMap; -// the emissive map texture +// the emissive map texture and parameters uniform sampler2D emissiveMap; +uniform vec2 emissiveParams; // the alpha threshold uniform float alphaThreshold; @@ -43,7 +44,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0); } diff --git a/interface/resources/shaders/model_lightmap_normal_specular_map.frag b/interface/resources/shaders/model_lightmap_normal_specular_map.frag index 89333bbcef..4d0d29ed71 100644 --- a/interface/resources/shaders/model_lightmap_normal_specular_map.frag +++ b/interface/resources/shaders/model_lightmap_normal_specular_map.frag @@ -14,8 +14,9 @@ // the diffuse texture uniform sampler2D diffuseMap; -// the emissive map texture +// the emissive map texture and parameters uniform sampler2D emissiveMap; +uniform vec2 emissiveParams; // the normal map texture uniform sampler2D normalMap; @@ -46,7 +47,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, gl_FrontMaterial.shininess / 128.0); diff --git a/interface/resources/shaders/model_lightmap_specular_map.frag b/interface/resources/shaders/model_lightmap_specular_map.frag index 3526ecdf9c..c616764cae 100644 --- a/interface/resources/shaders/model_lightmap_specular_map.frag +++ b/interface/resources/shaders/model_lightmap_specular_map.frag @@ -14,8 +14,9 @@ // the diffuse texture uniform sampler2D diffuseMap; -// the emissive map texture +// the emissive map texture and parameters uniform sampler2D emissiveMap; +uniform vec2 emissiveParams; // the specular texture uniform sampler2D specularMap; @@ -32,7 +33,7 @@ void main(void) { // set the diffuse, normal, specular data vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st); vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st); - gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(0.1) + 4 * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); + gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold))); gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, gl_FrontMaterial.shininess / 128.0); diff --git a/interface/resources/shaders/model_normal_map.vert b/interface/resources/shaders/model_normal_map.vert index 2e98b8c4fc..3d91a75c63 100644 --- a/interface/resources/shaders/model_normal_map.vert +++ b/interface/resources/shaders/model_normal_map.vert @@ -33,7 +33,7 @@ void main(void) { gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); // use standard pipeline transform gl_Position = ftransform(); diff --git a/interface/src/gpu/Batch.h b/interface/src/gpu/Batch.h index d006473b50..5304740dd3 100644 --- a/interface/src/gpu/Batch.h +++ b/interface/src/gpu/Batch.h @@ -116,6 +116,7 @@ public: void _glUseProgram(GLuint program); void _glUniform1f(GLint location, GLfloat v0); + void _glUniform2f(GLint location, GLfloat v0, GLfloat v1); void _glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); void _glMatrixMode(GLenum mode); @@ -185,6 +186,7 @@ public: COMMAND_glUseProgram, COMMAND_glUniform1f, + COMMAND_glUniform2f, COMMAND_glUniformMatrix4fv, COMMAND_glMatrixMode, diff --git a/interface/src/gpu/GLBackend.cpp b/interface/src/gpu/GLBackend.cpp index d6e1a011a3..1f8e7bf99f 100644 --- a/interface/src/gpu/GLBackend.cpp +++ b/interface/src/gpu/GLBackend.cpp @@ -53,6 +53,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_glUseProgram), (&::gpu::GLBackend::do_glUniform1f), + (&::gpu::GLBackend::do_glUniform2f), (&::gpu::GLBackend::do_glUniformMatrix4fv), (&::gpu::GLBackend::do_glMatrixMode), @@ -691,6 +692,23 @@ void GLBackend::do_glUniform1f(Batch& batch, uint32 paramOffset) { CHECK_GL_ERROR(); } +void Batch::_glUniform2f(GLint location, GLfloat v0, GLfloat v1) { + ADD_COMMAND_GL(glUniform2f); + + _params.push_back(v1); + _params.push_back(v0); + _params.push_back(location); + + DO_IT_NOW(_glUniform2f, 1); +} +void GLBackend::do_glUniform2f(Batch& batch, uint32 paramOffset) { + glUniform2f( + batch._params[paramOffset + 2]._int, + batch._params[paramOffset + 1]._float, + batch._params[paramOffset + 0]._float); + CHECK_GL_ERROR(); +} + void Batch::_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { ADD_COMMAND_GL(glUniformMatrix4fv); diff --git a/interface/src/gpu/GLBackend.h b/interface/src/gpu/GLBackend.h index 71869229fd..0e4b38d89e 100644 --- a/interface/src/gpu/GLBackend.h +++ b/interface/src/gpu/GLBackend.h @@ -147,6 +147,7 @@ protected: void do_glUseProgram(Batch& batch, uint32 paramOffset); void do_glUniform1f(Batch& batch, uint32 paramOffset); + void do_glUniform2f(Batch& batch, uint32 paramOffset); void do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset); void do_glMatrixMode(Batch& batch, uint32 paramOffset); diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 04ff7bdecd..ab27678546 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -830,6 +830,8 @@ void GeometryReader::run() { } try { QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&, + + _url.path().toLower().endsWith(".svo") ? readSVO(_reply->readAll()) : readFBX(_reply->readAll(), _mapping))); } catch (const QString& error) { diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 3f68201386..2c43113b62 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -160,6 +160,8 @@ void Model::initProgram(ProgramObject& program, Model::Locations& locations, int locations.texcoordMatrices = program.uniformLocation("texcoordMatrices"); + locations.emissiveParams = program.uniformLocation("emissiveParams"); + program.setUniformValue("diffuseMap", 0); @@ -2378,6 +2380,9 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod } if (locations->emissiveTextureUnit >= 0) { + assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader + GLBATCH(glUniform2f)(locations->emissiveParams, 0.1f, 4.0f); + GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit); Texture* emissiveMap = networkPart.emissiveTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ? diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 7a3457423e..d24e4d9f2e 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -329,6 +329,7 @@ private: int texcoordMatrices; int specularTextureUnit; int emissiveTextureUnit; + int emissiveParams; }; static Locations _locations; From 6a63099a0f339b4aae9d792b804209cec8bfeed0 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 24 Nov 2014 15:24:20 -0800 Subject: [PATCH 13/24] Fixed syntax issues and review critics, put all the debugging code in a #define block --- interface/src/renderer/GeometryCache.cpp | 1 - interface/src/renderer/Model.cpp | 7 +-- libraries/fbx/src/FBXReader.cpp | 57 +++++++++++++++--------- 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index ab27678546..c7d8b7fc8a 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -971,7 +971,6 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) { int clusterWeightsOffset = clusterIndicesOffset + mesh.clusterIndices.size() * sizeof(glm::vec4); networkMesh._vertexBuffer->resize(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4)); - //networkMesh.vertexBuffer.allocate(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4)); networkMesh._vertexBuffer->setSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.vertices.constData()); networkMesh._vertexBuffer->setSubData(normalsOffset, mesh.normals.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.normals.constData()); diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 2c43113b62..ddcdfe3a84 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -387,8 +387,6 @@ void Model::init() { _skinTranslucentProgram.link(); initSkinProgram(_skinTranslucentProgram, _skinTranslucentLocations); - - } } @@ -1813,7 +1811,7 @@ void Model::segregateMeshGroups() { bool translucentMesh = networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size(); bool hasTangents = !mesh.tangents.isEmpty(); bool hasSpecular = mesh.hasSpecularTexture(); - bool haslightmap = mesh.hasEmissiveTexture(); + bool hasLightmap = mesh.hasEmissiveTexture(); bool isSkinned = state.clusterMatrices.size() > 1; QString materialID; @@ -1832,7 +1830,7 @@ void Model::segregateMeshGroups() { qDebug() << "materialID:" << materialID << "parts:" << mesh.parts.size(); } - if ( !haslightmap) { + if (!hasLightmap) { if (translucentMesh && !hasTangents && !hasSpecular && !isSkinned) { _unsortedMeshesTranslucent.insertMulti(materialID, i); @@ -2387,7 +2385,6 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod Texture* emissiveMap = networkPart.emissiveTexture.data(); GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ? Application::getInstance()->getTextureCache()->getWhiteTextureID() : emissiveMap->getID()); - // GLBATCH(glBindTexture)(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getWhiteTextureID()); GLBATCH(glActiveTexture)(GL_TEXTURE0); } diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 130f1db550..0cebacf51a 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -30,6 +30,10 @@ #include "FBXReader.h" + +// TOOL: Uncomment the following line to enable the filtering of all the unkwnon fields of a node so we can break point easily while loading a model with problems... +//#define DEBUG_FBXREADER + using namespace std; struct TextureParam { @@ -868,7 +872,9 @@ void appendIndex(MeshData& data, QVector& indices, int index) { data.extracted.mesh.vertices.append(position); data.extracted.mesh.normals.append(normal); data.extracted.mesh.texCoords.append(vertex.texCoord); - if (hasMoreTexcoords) { data.extracted.mesh.texCoords1.append(vertex.texCoord1); } + if (hasMoreTexcoords) { + data.extracted.mesh.texCoords1.append(vertex.texCoord1); + } } else { indices.append(*it); data.extracted.mesh.normals[*it] += normal; @@ -911,7 +917,6 @@ ExtractedMesh extractMesh(const FBXNode& object) { if (child.properties.at(0).toInt() == 0) { AttributeData attrib; attrib.index = child.properties.at(0).toInt(); - int unknown = 0; foreach (const FBXNode& subdata, child.children) { if (subdata.name == "UV") { data.texCoords = createVec2Vector(getDoubleVector(subdata)); @@ -921,22 +926,25 @@ ExtractedMesh extractMesh(const FBXNode& object) { attrib.texCoordIndices = getIntVector(subdata); } else if (subdata.name == "Name") { attrib.name = subdata.properties.at(0).toString().toStdString(); - } else { + } +#if defined(DEBUG_FBXREADER) + else { + int unknown = 0; std::string subname = subdata.name.data(); - if (subdata.name == "Version") { - } else if (subdata.name == "MappingInformationType") { - } else if (subdata.name == "ReferenceInformationType") { + if ( (subdata.name == "Version") + || (subdata.name == "MappingInformationType") + || (subdata.name == "ReferenceInformationType") ) { } else { unknown++; } } +#endif } data.extracted.texcoordSetMap.insert(QString(attrib.name.c_str()), data.attributes.size()); data.attributes.push_back(attrib); } else { AttributeData attrib; attrib.index = child.properties.at(0).toInt(); - int unknown = 0; foreach (const FBXNode& subdata, child.children) { if (subdata.name == "UV") { attrib.texCoords = createVec2Vector(getDoubleVector(subdata)); @@ -944,15 +952,19 @@ ExtractedMesh extractMesh(const FBXNode& object) { attrib.texCoordIndices = getIntVector(subdata); } else if (subdata.name == "Name") { attrib.name = subdata.properties.at(0).toString().toStdString(); - } else { + } +#if defined(DEBUG_FBXREADER) + else { + int unknown = 0; std::string subname = subdata.name.data(); - if (subdata.name == "Version") { - } else if (subdata.name == "MappingInformationType") { - } else if (subdata.name == "ReferenceInformationType") { + if ( (subdata.name == "Version") + || (subdata.name == "MappingInformationType") + || (subdata.name == "ReferenceInformationType") ) { } else { unknown++; } } +#endif } QHash::iterator it = data.extracted.texcoordSetMap.find(QString(attrib.name.c_str())); @@ -961,7 +973,7 @@ ExtractedMesh extractMesh(const FBXNode& object) { data.attributes.push_back(attrib); } else { // WTF same names for different UVs? - unknown = data.attributes.size(); + qDebug() << "LayerElementUV #" << attrib.index << " is reusing the same name as #" << (*it) << ". Skip this texcoord attribute."; } } } else if (child.name == "LayerElementMaterial") { @@ -1145,12 +1157,10 @@ FBXTexture getTexture(const QString& textureID, texture.transform.setTranslation(p.translation); texture.transform.setRotation(glm::quat(glm::radians(p.rotation))); texture.transform.setScale(p.scaling); - if (p.UVSet != "map1" || (p.UVSet != "UVSet0")) { + if ((p.UVSet != "map1") || (p.UVSet != "UVSet0")) { texture.texcoordSet = 1; } - texture.texcoordSetName = p.UVSet; - } return texture; } @@ -1260,7 +1270,9 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } } QMultiHash blendshapeChannelIndices; +#if defined(DEBUG_FBXREADER) int unknown = 0; +#endif FBXGeometry geometry; float unitScaleFactor = 1.0f; foreach (const FBXNode& child, node.children) { @@ -1466,7 +1478,6 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) TextureParam tex; bool texparam = false; foreach (const FBXNode& subobject, object.children) { - std::string subname = subobject.name.data(); if (subobject.name == "RelativeFilename") { // trim off any path information QByteArray filename = subobject.properties.at(0).toByteArray(); @@ -1491,7 +1502,6 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) subobject.properties.at(2).value(), subobject.properties.at(3).value())); } else if (subobject.name == "Properties70") { - QByteArray propertyName; int index; propertyName = "P"; @@ -1499,7 +1509,6 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) foreach (const FBXNode& property, subobject.children) { if (property.name == propertyName) { QString v = property.properties.at(0).toString(); - std::string propName = v.toStdString(); if (property.properties.at(0) == "UVSet") { tex.assign(tex.UVSet, property.properties.at(index).toString().toStdString()); } else if (property.properties.at(0) == "CurrentTextureBlendMode") { @@ -1512,20 +1521,28 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) tex.assign(tex.rotation, getVec3(property.properties, index)); } else if (property.properties.at(0) == "Scaling") { tex.assign(tex.scaling, getVec3(property.properties, index)); - } else { + } +#if defined(DEBUG_FBXREADER) + else { + std::string propName = v.toStdString(); unknown++; } +#endif } } - } else { + } +#if defined(DEBUG_FBXREADER) + else { if (subobject.name == "Type") { } else if (subobject.name == "Version") { } else if (subobject.name == "FileName") { } else if (subobject.name == "Media") { } else { + std::string subname = subobject.name.data(); unknown++; } } +#endif } if (!tex.isDefault) { From 1f10a44ae496d7017450e145c916e86891377a54 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 24 Nov 2014 15:38:12 -0800 Subject: [PATCH 14/24] More typos in glsl --- interface/resources/shaders/model_lightmap_normal_map.vert | 4 ++-- interface/resources/shaders/skin_model.vert | 2 +- interface/resources/shaders/skin_model_normal_map.vert | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/resources/shaders/model_lightmap_normal_map.vert b/interface/resources/shaders/model_lightmap_normal_map.vert index 08eca835c9..4faf5688cf 100644 --- a/interface/resources/shaders/model_lightmap_normal_map.vert +++ b/interface/resources/shaders/model_lightmap_normal_map.vert @@ -38,8 +38,8 @@ void main(void) { gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); - interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.f, 1.f)).xy; + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); + interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.0, 1.0)).xy; // use standard pipeline transform gl_Position = ftransform(); diff --git a/interface/resources/shaders/skin_model.vert b/interface/resources/shaders/skin_model.vert index a8c25e885b..fd4dea51bb 100644 --- a/interface/resources/shaders/skin_model.vert +++ b/interface/resources/shaders/skin_model.vert @@ -40,7 +40,7 @@ void main(void) { gl_FrontColor = gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); gl_Position = gl_ModelViewProjectionMatrix * position; } diff --git a/interface/resources/shaders/skin_model_normal_map.vert b/interface/resources/shaders/skin_model_normal_map.vert index bbe5da35af..5814dfc584 100644 --- a/interface/resources/shaders/skin_model_normal_map.vert +++ b/interface/resources/shaders/skin_model_normal_map.vert @@ -48,7 +48,7 @@ void main(void) { gl_FrontColor = gl_FrontMaterial.diffuse; // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.f, 1.f); + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); gl_Position = gl_ModelViewProjectionMatrix * interpolatedPosition; } From 1c636fe6b281f4e4549e1bcb82529691123b7893 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 24 Nov 2014 20:37:09 -0800 Subject: [PATCH 15/24] more correct entity list maintenance --- libraries/entities/src/EntityTree.cpp | 49 ++++++++++++++++++++------- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index b25b153f44..bb201b6f86 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -653,7 +653,6 @@ void EntityTree::update() { } void EntityTree::updateChangedEntities(quint64 now, QSet& entitiesToDelete) { - // TODO: switch these to iterators so we can remove items that get deleted foreach (EntityItem* thisEntity, _changedEntities) { // check to see if the lifetime has expired, for immortal entities this is always false if (thisEntity->lifetimeHasExpired()) { @@ -675,15 +674,17 @@ void EntityTree::updateMovingEntities(quint64 now, QSet& entitiesT { PerformanceTimer perfTimer("_movingEntities"); - // TODO: switch these to iterators so we can remove items that get deleted - for (int i = 0; i < _movingEntities.size(); i++) { - EntityItem* thisEntity = _movingEntities[i]; + QList::iterator item_itr = _movingEntities.begin(); + while (item_itr != _movingEntities.end()) { + EntityItem* thisEntity = *item_itr; // always check to see if the lifetime has expired, for immortal entities this is always false if (thisEntity->lifetimeHasExpired()) { qDebug() << "Lifetime has expired for entity:" << thisEntity->getEntityItemID(); entitiesToDelete << thisEntity->getEntityItemID(); - clearEntityState(thisEntity); + // remove thisEntity from the list + item_itr = _movingEntities.erase(item_itr); + thisEntity->setSimulationState(EntityItem::Static); } else { AACube oldCube = thisEntity->getMaximumAACube(); thisEntity->update(now); @@ -694,10 +695,22 @@ void EntityTree::updateMovingEntities(quint64 now, QSet& entitiesT if (!domainBounds.touches(newCube)) { qDebug() << "Entity " << thisEntity->getEntityItemID() << " moved out of domain bounds."; entitiesToDelete << thisEntity->getEntityItemID(); - clearEntityState(thisEntity); + // remove thisEntity from the list + item_itr = _movingEntities.erase(item_itr); + thisEntity->setSimulationState(EntityItem::Static); } else { moveOperator.addEntityToMoveList(thisEntity, oldCube, newCube); - updateEntityState(thisEntity); + EntityItem::SimulationState newState = thisEntity->computeSimulationState(); + if (newState != EntityItem::Moving) { + if (newState == EntityItem::Mortal) { + _mortalEntities.push_back(thisEntity); + } + // remove thisEntity from the list + item_itr = _movingEntities.erase(item_itr); + thisEntity->setSimulationState(newState); + } else { + ++item_itr; + } } } } @@ -710,18 +723,30 @@ void EntityTree::updateMovingEntities(quint64 now, QSet& entitiesT } void EntityTree::updateMortalEntities(quint64 now, QSet& entitiesToDelete) { - // TODO: switch these to iterators so we can remove items that get deleted - for (int i = 0; i < _mortalEntities.size(); i++) { - EntityItem* thisEntity = _mortalEntities[i]; + QList::iterator item_itr = _mortalEntities.begin(); + while (item_itr != _mortalEntities.end()) { + EntityItem* thisEntity = *item_itr; thisEntity->update(now); // always check to see if the lifetime has expired, for immortal entities this is always false if (thisEntity->lifetimeHasExpired()) { qDebug() << "Lifetime has expired for entity:" << thisEntity->getEntityItemID(); entitiesToDelete << thisEntity->getEntityItemID(); - clearEntityState(thisEntity); + // remove thisEntity from the list + item_itr = _mortalEntities.erase(item_itr); + thisEntity->setSimulationState(EntityItem::Static); } else { // check to see if this entity is no longer moving - updateEntityState(thisEntity); + EntityItem::SimulationState newState = thisEntity->computeSimulationState(); + if (newState != EntityItem::Mortal) { + if (newState == EntityItem::Moving) { + _movingEntities.push_back(thisEntity); + } + // remove thisEntity from the list + item_itr = _mortalEntities.erase(item_itr); + thisEntity->setSimulationState(newState); + } else { + ++item_itr; + } } } } From 8966ab32d8cb0b40f77b19d65c15ef3d2f748ed1 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 24 Nov 2014 20:37:52 -0800 Subject: [PATCH 16/24] add lifetime to gun bullets --- examples/gun.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/gun.js b/examples/gun.js index fff78496b2..2386e61539 100644 --- a/examples/gun.js +++ b/examples/gun.js @@ -96,6 +96,7 @@ function printVector(string, vector) { function shootBullet(position, velocity) { var BULLET_SIZE = 0.01; + var BULLET_LIFETIME = 20.0; var BULLET_GRAVITY = -0.02; Entities.addEntity( { type: "Sphere", @@ -103,6 +104,7 @@ function shootBullet(position, velocity) { dimensions: { x: BULLET_SIZE, y: BULLET_SIZE, z: BULLET_SIZE }, color: { red: 10, green: 10, blue: 10 }, velocity: velocity, + lifetime: BULLET_LIFETIME, gravity: { x: 0, y: BULLET_GRAVITY, z: 0 }, damping: 0 }); @@ -118,6 +120,7 @@ function shootBullet(position, velocity) { function shootTarget() { var TARGET_SIZE = 0.25; var TARGET_GRAVITY = -0.6; + var TARGET_LIFETIME = 300.0; var TARGET_UP_VELOCITY = 3.0; var TARGET_FWD_VELOCITY = 5.0; var DISTANCE_TO_LAUNCH_FROM = 3.0; @@ -140,7 +143,7 @@ function shootTarget() { color: { red: 0, green: 200, blue: 200 }, velocity: velocity, gravity: { x: 0, y: TARGET_GRAVITY, z: 0 }, - lifetime: 1000.0, + lifetime: TARGET_LIFETIME, damping: 0.99 }); // Record start time From 1b1482bab3c28e78e871a67584062b2e59ea0bb2 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 24 Nov 2014 21:00:04 -0800 Subject: [PATCH 17/24] Adjust size of stretch overlays to be smaller --- examples/libraries/entitySelectionTool.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index b0fc68b60c..08ac077a34 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -205,7 +205,7 @@ SelectionDisplay = (function () { var MINIMUM_DIMENSION = 0.001; - var GRABBER_DISTANCE_TO_SIZE_RATIO = 0.015; + var GRABBER_DISTANCE_TO_SIZE_RATIO = 0.0075; var spaceMode = SPACE_LOCAL; var mode = "UNKNOWN"; From 1d865ace9d41bd5336cee93d4a16f014df6c6772 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 24 Nov 2014 21:16:29 -0800 Subject: [PATCH 18/24] Add drawInFront property to Base3DOverlay --- interface/src/ui/overlays/Base3DOverlay.cpp | 16 +++++++++++++++- interface/src/ui/overlays/Base3DOverlay.h | 6 ++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index 5a5bfcd937..5c6af97bf1 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -27,7 +27,8 @@ Base3DOverlay::Base3DOverlay() : _rotation(), _isSolid(DEFAULT_IS_SOLID), _isDashedLine(DEFAULT_IS_DASHED_LINE), - _ignoreRayIntersection(false) + _ignoreRayIntersection(false), + _drawInFront(false) { } @@ -45,9 +46,22 @@ Base3DOverlay::Base3DOverlay(const Base3DOverlay* base3DOverlay) : Base3DOverlay::~Base3DOverlay() { } +void Base3DOverlay::setDrawInFront(bool value) { + _drawInFront = value; + emit drawInFrontUpdated(value); +} + void Base3DOverlay::setProperties(const QScriptValue& properties) { Overlay::setProperties(properties); + QScriptValue drawInFront = properties.property("drawInFront"); + + if (drawInFront.isValid()) { + bool value = drawInFront.toVariant().toBool(); + setDrawInFront(value); + _drawInFront = value; + } + QScriptValue position = properties.property("position"); // if "position" property was not there, check to see if they included aliases: start, point, p1 diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index 8304883e3c..46d99cf3de 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -36,6 +36,7 @@ public: bool getIsSolidLine() const { return !_isDashedLine; } const glm::quat& getRotation() const { return _rotation; } bool getIgnoreRayIntersection() const { return _ignoreRayIntersection; } + bool getDrawInFront() const { return _drawInFront; } // setters void setPosition(const glm::vec3& position) { _position = position; } @@ -44,6 +45,7 @@ public: void setIsDashedLine(bool isDashedLine) { _isDashedLine = isDashedLine; } void setRotation(const glm::quat& value) { _rotation = value; } void setIgnoreRayIntersection(bool value) { _ignoreRayIntersection = value; } + void setDrawInFront(bool value); virtual void setProperties(const QScriptValue& properties); virtual QScriptValue getProperty(const QString& property); @@ -55,6 +57,9 @@ public: return findRayIntersection(origin, direction, distance, face); } +signals: + void drawInFrontUpdated(bool newValue); + protected: void drawDashedLine(const glm::vec3& start, const glm::vec3& end); @@ -64,6 +69,7 @@ protected: bool _isSolid; bool _isDashedLine; bool _ignoreRayIntersection; + bool _drawInFront; }; #endif // hifi_Base3DOverlay_h From 0b46e35f31df467faf1c698adc429a3156025b89 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 24 Nov 2014 23:19:13 -0800 Subject: [PATCH 19/24] Add support for separate list of 3d overlays to be drawn in front --- interface/src/ui/overlays/Base3DOverlay.cpp | 7 +- interface/src/ui/overlays/Overlays.cpp | 99 ++++++++++++++++----- interface/src/ui/overlays/Overlays.h | 12 +++ 3 files changed, 92 insertions(+), 26 deletions(-) diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index 5c6af97bf1..b3dc377282 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -47,8 +47,10 @@ Base3DOverlay::~Base3DOverlay() { } void Base3DOverlay::setDrawInFront(bool value) { - _drawInFront = value; - emit drawInFrontUpdated(value); + if (value != _drawInFront) { + _drawInFront = value; + emit drawInFrontUpdated(value); + } } void Base3DOverlay::setProperties(const QScriptValue& properties) { @@ -59,7 +61,6 @@ void Base3DOverlay::setProperties(const QScriptValue& properties) { if (drawInFront.isValid()) { bool value = drawInFront.toVariant().toBool(); setDrawInFront(value); - _drawInFront = value; } QScriptValue position = properties.property("position"); diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index d6dbb0861e..5de410c1d9 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -29,7 +29,8 @@ #include "TextOverlay.h" #include "Text3DOverlay.h" -Overlays::Overlays() : _nextOverlayID(1) { +Overlays::Overlays() : _nextOverlayID(1), _overlaySignalMapper() { + connect(&_overlaySignalMapper, SIGNAL(mapped(int)), this, SLOT(handleOverlayDrawInFrontUpdated(unsigned int))); } Overlays::~Overlays() { @@ -70,6 +71,9 @@ void Overlays::update(float deltatime) { foreach(Overlay* thisOverlay, _overlays3D) { thisOverlay->update(deltatime); } + foreach(Overlay* thisOverlay, _overlays3DFront) { + thisOverlay->update(deltatime); + } } if (!_overlaysToDelete.isEmpty()) { @@ -94,8 +98,16 @@ void Overlays::render2D() { } void Overlays::render3D(RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) { + render3DOverlays(_overlays3D, renderMode, renderSide); +} + +void Overlays::render3DFront(RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) { + render3DOverlays(_overlays3DFront, renderMode, renderSide); +} + +void Overlays::render3DOverlays(QMap& overlays, RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) { QReadLocker lock(&_lock); - if (_overlays3D.size() == 0) { + if (overlays.size() == 0) { return; } bool myAvatarComputed = false; @@ -111,7 +123,7 @@ void Overlays::render3D(RenderArgs::RenderMode renderMode, RenderArgs::RenderSid renderMode, renderSide, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - foreach(Overlay* thisOverlay, _overlays3D) { + foreach(Overlay* thisOverlay, overlays) { glPushMatrix(); switch (thisOverlay->getAnchor()) { case Overlay::MY_AVATAR: @@ -188,7 +200,15 @@ unsigned int Overlays::addOverlay(Overlay* overlay) { unsigned int thisID = _nextOverlayID; _nextOverlayID++; if (overlay->is3D()) { - _overlays3D[thisID] = overlay; + Base3DOverlay* overlay3D = static_cast(overlay); + if (overlay3D->getDrawInFront()) { + _overlays3DFront[thisID] = overlay; + } else { + _overlays3D[thisID] = overlay; + } + + _overlaySignalMapper.setMapping(overlay3D, thisID); + connect(overlay3D, SIGNAL(drawInFrontUpdated(bool)), &_overlaySignalMapper, SLOT(map())); } else { _overlays2D[thisID] = overlay; } @@ -213,6 +233,8 @@ bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) { thisOverlay = _overlays2D[id]; } else if (_overlays3D.contains(id)) { thisOverlay = _overlays3D[id]; + } else if (_overlays3DFront.contains(id)) { + thisOverlay = _overlays3DFront[id]; } if (thisOverlay) { thisOverlay->setProperties(properties); @@ -230,6 +252,8 @@ void Overlays::deleteOverlay(unsigned int id) { overlayToDelete = _overlays2D.take(id); } else if (_overlays3D.contains(id)) { overlayToDelete = _overlays3D.take(id); + } else if (_overlays3DFront.contains(id)) { + overlayToDelete = _overlays3DFront.take(id); } else { return; } @@ -239,6 +263,22 @@ void Overlays::deleteOverlay(unsigned int id) { _overlaysToDelete.push_back(overlayToDelete); } +void Overlays::handleOverlayDrawInFrontUpdated(int overlayID) { + if (_overlays3D.contains(overlayID)) { + Base3DOverlay* overlay = static_cast(_overlays3D[overlayID]); + if (overlay->getDrawInFront()) { + _overlays3D.remove(overlayID); + _overlays3DFront[overlayID] = overlay; + } + } else if (_overlays3DFront.contains(overlayID)) { + Base3DOverlay* overlay = static_cast(_overlays3DFront[overlayID]); + if (!overlay->getDrawInFront()) { + _overlays3DFront.remove(overlayID); + _overlays3D[overlayID] = overlay; + } + } +} + unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { QReadLocker lock(&_lock); QMapIterator i(_overlays2D); @@ -262,6 +302,8 @@ OverlayPropertyResult Overlays::getProperty(unsigned int id, const QString& prop thisOverlay = _overlays2D[id]; } else if (_overlays3D.contains(id)) { thisOverlay = _overlays3D[id]; + } else if (_overlays3DFront.contains(id)) { + thisOverlay = _overlays3DFront[id]; } if (thisOverlay) { result.value = thisOverlay->getProperty(property); @@ -300,30 +342,39 @@ void OverlayPropertyResultFromScriptValue(const QScriptValue& value, OverlayProp } RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray) { + QMap overlayMaps[] = { _overlays3DFront, _overlays3D }; + float bestDistance = std::numeric_limits::max(); RayToOverlayIntersectionResult result; - QMapIterator i(_overlays3D); - i.toBack(); - while (i.hasPrevious()) { - i.previous(); - unsigned int thisID = i.key(); - Base3DOverlay* thisOverlay = static_cast(i.value()); - if (thisOverlay->getVisible() && !thisOverlay->getIgnoreRayIntersection() && thisOverlay->isLoaded()) { - float thisDistance; - BoxFace thisFace; - QString thisExtraInfo; - if (thisOverlay->findRayIntersectionExtraInfo(ray.origin, ray.direction, thisDistance, thisFace, thisExtraInfo)) { - if (thisDistance < bestDistance) { - bestDistance = thisDistance; - result.intersects = true; - result.distance = thisDistance; - result.face = thisFace; - result.overlayID = thisID; - result.intersection = ray.origin + (ray.direction * thisDistance); - result.extraInfo = thisExtraInfo; + for (int idx = 0; idx < 2; idx++) { + QMapIterator i(overlayMaps[idx]); + i.toBack(); + while (i.hasPrevious()) { + i.previous(); + unsigned int thisID = i.key(); + Base3DOverlay* thisOverlay = static_cast(i.value()); + if (thisOverlay->getVisible() && !thisOverlay->getIgnoreRayIntersection() && thisOverlay->isLoaded()) { + float thisDistance; + BoxFace thisFace; + QString thisExtraInfo; + if (thisOverlay->findRayIntersectionExtraInfo(ray.origin, ray.direction, thisDistance, thisFace, thisExtraInfo)) { + if (thisDistance < bestDistance) { + bestDistance = thisDistance; + result.intersects = true; + result.distance = thisDistance; + result.face = thisFace; + result.overlayID = thisID; + result.intersection = ray.origin + (ray.direction * thisDistance); + result.extraInfo = thisExtraInfo; + } } } } + if (result.intersects) { + // We first check the front overlays - if one has been intersected, prefer + // it over any other overlays and return it immediately. + break; + } } return result; } @@ -412,6 +463,8 @@ bool Overlays::isLoaded(unsigned int id) { thisOverlay = _overlays2D[id]; } else if (_overlays3D.contains(id)) { thisOverlay = _overlays3D[id]; + } else if (_overlays3DFront.contains(id)) { + thisOverlay = _overlays3DFront[id]; } else { return false; // not found } diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 2cd80041cd..c46d9474da 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -13,6 +13,7 @@ #include #include +#include #include "Overlay.h" @@ -53,6 +54,8 @@ public: void update(float deltatime); void render3D(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::RenderSide renderSide = RenderArgs::MONO); + void render3DFront(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE, + RenderArgs::RenderSide renderSide = RenderArgs::MONO); void render2D(); public slots: @@ -88,10 +91,19 @@ public slots: /// overlay; in meters if it is a 3D text overlay float textWidth(unsigned int id, const QString& text) const; +protected: + void render3DOverlays(QMap& overlays, RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide); + +private slots: + /// QSignalMapper unfortunately does not work with unsigned integers. + void handleOverlayDrawInFrontUpdated(int overlayID); + private: QMap _overlays2D; QMap _overlays3D; + QMap _overlays3DFront; QList _overlaysToDelete; + QSignalMapper _overlaySignalMapper; unsigned int _nextOverlayID; QGLWidget* _parent; QReadWriteLock _lock; From 8b982872c2d59370e7de9cd22abbea7d53da8467 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 24 Nov 2014 23:19:53 -0800 Subject: [PATCH 20/24] Add calls to Overlays::render3DFront() --- interface/src/Application.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4e8b95862a..8d1e77ed25 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2839,6 +2839,11 @@ void Application::updateShadowMap() { _overlays.render3D(RenderArgs::SHADOW_RENDER_MODE); } + { + PerformanceTimer perfTimer("3dOverlaysFront"); + _overlays.render3DFront(RenderArgs::SHADOW_RENDER_MODE); + } + glDisable(GL_POLYGON_OFFSET_FILL); glPopMatrix(); @@ -3135,6 +3140,13 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderAr if (Menu::getInstance()->isOptionChecked(MenuOption::Wireframe)) { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } + + // Render 3D overlays that should be drawn in front + { + PerformanceTimer perfTimer("3dOverlaysFront"); + glClear(GL_DEPTH_BUFFER_BIT); + _overlays.render3DFront(); + } } void Application::updateUntranslatedViewMatrix(const glm::vec3& viewMatrixTranslation) { From 925c2a8f6c10bcd568e4131b3b76f5d67716874e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 25 Nov 2014 08:34:44 -0800 Subject: [PATCH 21/24] Update array to use pointers --- interface/src/ui/overlays/Overlays.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 5de410c1d9..2d4edca781 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -342,12 +342,12 @@ void OverlayPropertyResultFromScriptValue(const QScriptValue& value, OverlayProp } RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray) { - QMap overlayMaps[] = { _overlays3DFront, _overlays3D }; + QMap* overlayMaps[] = { &_overlays3DFront, &_overlays3D }; float bestDistance = std::numeric_limits::max(); RayToOverlayIntersectionResult result; for (int idx = 0; idx < 2; idx++) { - QMapIterator i(overlayMaps[idx]); + QMapIterator i(*overlayMaps[idx]); i.toBack(); while (i.hasPrevious()) { i.previous(); From 4febc45b6a04d2e9cd2fe3fc7091802de8f30666 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 25 Nov 2014 08:44:38 -0800 Subject: [PATCH 22/24] Add drawInFront to Base3DOverlay::getProperty --- interface/src/ui/overlays/Base3DOverlay.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index b3dc377282..1c80b62782 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -166,6 +166,9 @@ QScriptValue Base3DOverlay::getProperty(const QString& property) { if (property == "ignoreRayIntersection") { return _ignoreRayIntersection; } + if (property == "drawInFront") { + return _drawInFront; + } return Overlay::getProperty(property); } From 649ae4a4485398843842d35c33ecdb4118a6aebf Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 25 Nov 2014 09:49:10 -0800 Subject: [PATCH 23/24] Update 3D overlays to only use one list --- interface/src/Application.cpp | 8 +- interface/src/ui/overlays/Base3DOverlay.cpp | 7 -- interface/src/ui/overlays/Base3DOverlay.h | 5 +- interface/src/ui/overlays/Overlays.cpp | 108 ++++++-------------- interface/src/ui/overlays/Overlays.h | 13 +-- 5 files changed, 37 insertions(+), 104 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8d1e77ed25..de889c7f61 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2836,12 +2836,12 @@ void Application::updateShadowMap() { // render JS/scriptable overlays { PerformanceTimer perfTimer("3dOverlays"); - _overlays.render3D(RenderArgs::SHADOW_RENDER_MODE); + _overlays.render3D(false, RenderArgs::SHADOW_RENDER_MODE); } { PerformanceTimer perfTimer("3dOverlaysFront"); - _overlays.render3DFront(RenderArgs::SHADOW_RENDER_MODE); + _overlays.render3D(true, RenderArgs::SHADOW_RENDER_MODE); } glDisable(GL_POLYGON_OFFSET_FILL); @@ -3056,7 +3056,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderAr // render JS/scriptable overlays { PerformanceTimer perfTimer("3dOverlays"); - _overlays.render3D(); + _overlays.render3D(false); } // render the ambient occlusion effect if enabled @@ -3145,7 +3145,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderAr { PerformanceTimer perfTimer("3dOverlaysFront"); glClear(GL_DEPTH_BUFFER_BIT); - _overlays.render3DFront(); + _overlays.render3D(true); } } diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index 1c80b62782..55b4c88812 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -46,13 +46,6 @@ Base3DOverlay::Base3DOverlay(const Base3DOverlay* base3DOverlay) : Base3DOverlay::~Base3DOverlay() { } -void Base3DOverlay::setDrawInFront(bool value) { - if (value != _drawInFront) { - _drawInFront = value; - emit drawInFrontUpdated(value); - } -} - void Base3DOverlay::setProperties(const QScriptValue& properties) { Overlay::setProperties(properties); diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index 46d99cf3de..d57f9731c4 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -45,7 +45,7 @@ public: void setIsDashedLine(bool isDashedLine) { _isDashedLine = isDashedLine; } void setRotation(const glm::quat& value) { _rotation = value; } void setIgnoreRayIntersection(bool value) { _ignoreRayIntersection = value; } - void setDrawInFront(bool value); + void setDrawInFront(bool value) { _drawInFront = value; } virtual void setProperties(const QScriptValue& properties); virtual QScriptValue getProperty(const QString& property); @@ -57,9 +57,6 @@ public: return findRayIntersection(origin, direction, distance, face); } -signals: - void drawInFrontUpdated(bool newValue); - protected: void drawDashedLine(const glm::vec3& start, const glm::vec3& end); diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 2d4edca781..151e3c3ba7 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -29,8 +29,7 @@ #include "TextOverlay.h" #include "Text3DOverlay.h" -Overlays::Overlays() : _nextOverlayID(1), _overlaySignalMapper() { - connect(&_overlaySignalMapper, SIGNAL(mapped(int)), this, SLOT(handleOverlayDrawInFrontUpdated(unsigned int))); +Overlays::Overlays() : _nextOverlayID(1) { } Overlays::~Overlays() { @@ -71,9 +70,6 @@ void Overlays::update(float deltatime) { foreach(Overlay* thisOverlay, _overlays3D) { thisOverlay->update(deltatime); } - foreach(Overlay* thisOverlay, _overlays3DFront) { - thisOverlay->update(deltatime); - } } if (!_overlaysToDelete.isEmpty()) { @@ -97,17 +93,9 @@ void Overlays::render2D() { } } -void Overlays::render3D(RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) { - render3DOverlays(_overlays3D, renderMode, renderSide); -} - -void Overlays::render3DFront(RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) { - render3DOverlays(_overlays3DFront, renderMode, renderSide); -} - -void Overlays::render3DOverlays(QMap& overlays, RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) { +void Overlays::render3D(bool drawFront, RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) { QReadLocker lock(&_lock); - if (overlays.size() == 0) { + if (_overlays3D.size() == 0) { return; } bool myAvatarComputed = false; @@ -123,7 +111,11 @@ void Overlays::render3DOverlays(QMap& overlays, RenderAr renderMode, renderSide, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - foreach(Overlay* thisOverlay, overlays) { + foreach(Overlay* thisOverlay, _overlays3D) { + Base3DOverlay* overlay3D = static_cast(thisOverlay); + if (overlay3D->getDrawInFront() != drawFront) { + continue; + } glPushMatrix(); switch (thisOverlay->getAnchor()) { case Overlay::MY_AVATAR: @@ -200,15 +192,7 @@ unsigned int Overlays::addOverlay(Overlay* overlay) { unsigned int thisID = _nextOverlayID; _nextOverlayID++; if (overlay->is3D()) { - Base3DOverlay* overlay3D = static_cast(overlay); - if (overlay3D->getDrawInFront()) { - _overlays3DFront[thisID] = overlay; - } else { - _overlays3D[thisID] = overlay; - } - - _overlaySignalMapper.setMapping(overlay3D, thisID); - connect(overlay3D, SIGNAL(drawInFrontUpdated(bool)), &_overlaySignalMapper, SLOT(map())); + _overlays3D[thisID] = overlay; } else { _overlays2D[thisID] = overlay; } @@ -233,8 +217,6 @@ bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) { thisOverlay = _overlays2D[id]; } else if (_overlays3D.contains(id)) { thisOverlay = _overlays3D[id]; - } else if (_overlays3DFront.contains(id)) { - thisOverlay = _overlays3DFront[id]; } if (thisOverlay) { thisOverlay->setProperties(properties); @@ -252,8 +234,6 @@ void Overlays::deleteOverlay(unsigned int id) { overlayToDelete = _overlays2D.take(id); } else if (_overlays3D.contains(id)) { overlayToDelete = _overlays3D.take(id); - } else if (_overlays3DFront.contains(id)) { - overlayToDelete = _overlays3DFront.take(id); } else { return; } @@ -263,22 +243,6 @@ void Overlays::deleteOverlay(unsigned int id) { _overlaysToDelete.push_back(overlayToDelete); } -void Overlays::handleOverlayDrawInFrontUpdated(int overlayID) { - if (_overlays3D.contains(overlayID)) { - Base3DOverlay* overlay = static_cast(_overlays3D[overlayID]); - if (overlay->getDrawInFront()) { - _overlays3D.remove(overlayID); - _overlays3DFront[overlayID] = overlay; - } - } else if (_overlays3DFront.contains(overlayID)) { - Base3DOverlay* overlay = static_cast(_overlays3DFront[overlayID]); - if (!overlay->getDrawInFront()) { - _overlays3DFront.remove(overlayID); - _overlays3D[overlayID] = overlay; - } - } -} - unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { QReadLocker lock(&_lock); QMapIterator i(_overlays2D); @@ -302,8 +266,6 @@ OverlayPropertyResult Overlays::getProperty(unsigned int id, const QString& prop thisOverlay = _overlays2D[id]; } else if (_overlays3D.contains(id)) { thisOverlay = _overlays3D[id]; - } else if (_overlays3DFront.contains(id)) { - thisOverlay = _overlays3DFront[id]; } if (thisOverlay) { result.value = thisOverlay->getProperty(property); @@ -342,39 +304,33 @@ void OverlayPropertyResultFromScriptValue(const QScriptValue& value, OverlayProp } RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray) { - QMap* overlayMaps[] = { &_overlays3DFront, &_overlays3D }; - float bestDistance = std::numeric_limits::max(); + float bestIsFront = false; RayToOverlayIntersectionResult result; - for (int idx = 0; idx < 2; idx++) { - QMapIterator i(*overlayMaps[idx]); - i.toBack(); - while (i.hasPrevious()) { - i.previous(); - unsigned int thisID = i.key(); - Base3DOverlay* thisOverlay = static_cast(i.value()); - if (thisOverlay->getVisible() && !thisOverlay->getIgnoreRayIntersection() && thisOverlay->isLoaded()) { - float thisDistance; - BoxFace thisFace; - QString thisExtraInfo; - if (thisOverlay->findRayIntersectionExtraInfo(ray.origin, ray.direction, thisDistance, thisFace, thisExtraInfo)) { - if (thisDistance < bestDistance) { - bestDistance = thisDistance; - result.intersects = true; - result.distance = thisDistance; - result.face = thisFace; - result.overlayID = thisID; - result.intersection = ray.origin + (ray.direction * thisDistance); - result.extraInfo = thisExtraInfo; - } + QMapIterator i(_overlays3D); + i.toBack(); + while (i.hasPrevious()) { + i.previous(); + unsigned int thisID = i.key(); + Base3DOverlay* thisOverlay = static_cast(i.value()); + if (thisOverlay->getVisible() && !thisOverlay->getIgnoreRayIntersection() && thisOverlay->isLoaded()) { + float thisDistance; + BoxFace thisFace; + QString thisExtraInfo; + if (thisOverlay->findRayIntersectionExtraInfo(ray.origin, ray.direction, thisDistance, thisFace, thisExtraInfo)) { + bool isDrawInFront = thisOverlay->getDrawInFront(); + if (thisDistance < bestDistance && (!bestIsFront || isDrawInFront)) { + bestIsFront = isDrawInFront; + bestDistance = thisDistance; + result.intersects = true; + result.distance = thisDistance; + result.face = thisFace; + result.overlayID = thisID; + result.intersection = ray.origin + (ray.direction * thisDistance); + result.extraInfo = thisExtraInfo; } } } - if (result.intersects) { - // We first check the front overlays - if one has been intersected, prefer - // it over any other overlays and return it immediately. - break; - } } return result; } @@ -463,8 +419,6 @@ bool Overlays::isLoaded(unsigned int id) { thisOverlay = _overlays2D[id]; } else if (_overlays3D.contains(id)) { thisOverlay = _overlays3D[id]; - } else if (_overlays3DFront.contains(id)) { - thisOverlay = _overlays3DFront[id]; } else { return false; // not found } diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index c46d9474da..7acc2c7878 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -52,9 +52,7 @@ public: ~Overlays(); void init(QGLWidget* parent); void update(float deltatime); - void render3D(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE, - RenderArgs::RenderSide renderSide = RenderArgs::MONO); - void render3DFront(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE, + void render3D(bool drawFront, RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::RenderSide renderSide = RenderArgs::MONO); void render2D(); @@ -91,19 +89,10 @@ public slots: /// overlay; in meters if it is a 3D text overlay float textWidth(unsigned int id, const QString& text) const; -protected: - void render3DOverlays(QMap& overlays, RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide); - -private slots: - /// QSignalMapper unfortunately does not work with unsigned integers. - void handleOverlayDrawInFrontUpdated(int overlayID); - private: QMap _overlays2D; QMap _overlays3D; - QMap _overlays3DFront; QList _overlaysToDelete; - QSignalMapper _overlaySignalMapper; unsigned int _nextOverlayID; QGLWidget* _parent; QReadWriteLock _lock; From f8c8ed868e2a652459c6a2646493bc8b842ef25b Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 25 Nov 2014 12:08:48 -0800 Subject: [PATCH 24/24] Update float that should be bool --- interface/src/ui/overlays/Overlays.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 151e3c3ba7..455b73fb80 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -305,7 +305,7 @@ void OverlayPropertyResultFromScriptValue(const QScriptValue& value, OverlayProp RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray) { float bestDistance = std::numeric_limits::max(); - float bestIsFront = false; + bool bestIsFront = false; RayToOverlayIntersectionResult result; QMapIterator i(_overlays3D); i.toBack();