From adbd995695ee199f371f834a5b1632d8202c5a25 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 16 Jul 2015 11:18:37 -0700 Subject: [PATCH 01/26] updated sword script so users can grab sword with hydra to adjust relative rotation of sword --- examples/example/games/sword.js | 449 ++++++++++++++++++++------------ 1 file changed, 284 insertions(+), 165 deletions(-) diff --git a/examples/example/games/sword.js b/examples/example/games/sword.js index 178a48f35a..6504bd0494 100644 --- a/examples/example/games/sword.js +++ b/examples/example/games/sword.js @@ -14,16 +14,46 @@ var Script, Entities, MyAvatar, Window, Overlays, Controller, Vec3, Quat, print, ToolBar, Settings; // Referenced globals provided by High Fidelity. Script.include("http://s3.amazonaws.com/hifi-public/scripts/libraries/toolBars.js"); -var hand = Settings.getValue("highfidelity.sword.hand", "right"); +var zombieFight; + +var hand = "right"; + var nullActionID = "00000000-0000-0000-0000-000000000000"; var controllerID; var controllerActive; var stickID = null; var actionID = nullActionID; -var targetIDs = []; -var dimensions = { x: 0.3, y: 0.15, z: 2.0 }; +var dimensions = { + x: 0.3, + y: 0.15, + z: 2.0 +}; var BUTTON_SIZE = 32; +var Y_AXIS = { + x: 0, + y: 1, + z: 0 +}; +var X_AXIS = { + x: 1, + y: 0, + z: 0 +}; + +var theta = 0.0; + +var RAD_TO_DEG = 180.0 / Math.PI; + +function orientationOf(vector) { + var direction, yaw, pitch; + direction = Vec3.normalize(vector); + yaw = Quat.angleAxis(Math.atan2(direction.x, direction.z) * RAD_TO_DEG, Y_AXIS); + pitch = Quat.angleAxis(Math.asin(-direction.y) * RAD_TO_DEG, X_AXIS); + return Quat.multiply(yaw, pitch); +} + + var stickModel = "https://hifi-public.s3.amazonaws.com/eric/models/stick.fbx"; var swordModel = "https://hifi-public.s3.amazonaws.com/ozan/props/sword/sword.fbx"; var swordCollisionShape = "https://hifi-public.s3.amazonaws.com/ozan/props/sword/sword.obj"; @@ -32,14 +62,16 @@ var avatarCollisionSoundURL = "https://s3.amazonaws.com/hifi-public/sounds/Colli var whichModel = "sword"; var originalAvatarCollisionSound; -var toolBar = new ToolBar(0, 0, ToolBar.vertical, "highfidelity.sword.toolbar", function () { - return {x: 100, y: 380}; +var toolBar = new ToolBar(0, 0, ToolBar.vertical, "highfidelity.sword.toolbar", function() { + return { + x: 100, + y: 380 + }; }); -var SWORD_IMAGE = "http://s3.amazonaws.com/hifi-public/images/billiardsReticle.png"; // Toggle between brandishing/sheathing sword (creating if necessary) -var TARGET_IMAGE = "http://s3.amazonaws.com/hifi-public/images/puck.png"; // Create a target dummy +var SWORD_IMAGE = "https://hifi-public.s3.amazonaws.com/images/sword/sword.svg"; // Toggle between brandishing/sheathing sword (creating if necessary) +var TARGET_IMAGE = "https://hifi-public.s3.amazonaws.com/images/sword/dummy2.svg"; // Create a target dummy var CLEANUP_IMAGE = "http://s3.amazonaws.com/hifi-public/images/delete.png"; // Remove sword and all target dummies.f -var SWITCH_HANDS_IMAGE = "http://s3.amazonaws.com/hifi-public/images/up-arrow.svg"; // Toggle left vs right hand. Persists in settings. var swordButton = toolBar.addOverlay("image", { width: BUTTON_SIZE, height: BUTTON_SIZE, @@ -52,12 +84,7 @@ var targetButton = toolBar.addOverlay("image", { imageURL: TARGET_IMAGE, alpha: 1 }); -var switchHandsButton = toolBar.addOverlay("image", { - width: BUTTON_SIZE, - height: BUTTON_SIZE, - imageURL: SWITCH_HANDS_IMAGE, - alpha: 1 -}); + var cleanupButton = toolBar.addOverlay("image", { width: BUTTON_SIZE, height: BUTTON_SIZE, @@ -66,6 +93,24 @@ var cleanupButton = toolBar.addOverlay("image", { }); var flasher; + +var leftTriggerButton = 0; +var leftTriggerValue = 0; +var prevLeftTriggerValue = 0; + + +var LEFT = 0; +var RIGHT = 1; + +var leftPalm = 2 * LEFT; +var rightPalm = 2 * RIGHT; +var rightTriggerButton = 1; +var prevRightTriggerValue = 0; +var rightTriggerValue = 0; +var TRIGGER_THRESHOLD = 0.2; + +var swordHeld = false; + function clearFlash() { if (!flasher) { return; @@ -74,6 +119,7 @@ function clearFlash() { Overlays.deleteOverlay(flasher.overlay); flasher = null; } + function flash(color) { clearFlash(); flasher = {}; @@ -88,40 +134,73 @@ function flash(color) { var health = 100; var display2d, display3d; + function trackAvatarWithText() { Entities.editEntity(display3d, { - position: Vec3.sum(MyAvatar.position, {x: 0, y: 1.5, z: 0}), + position: Vec3.sum(MyAvatar.position, { + x: 0, + y: 1.5, + z: 0 + }), rotation: Quat.multiply(MyAvatar.orientation, Quat.fromPitchYawRollDegrees(0, 180, 0)) }); } + function updateDisplay() { var text = health.toString(); if (!display2d) { health = 100; display2d = Overlays.addOverlay("text", { text: text, - font: { size: 20 }, - color: {red: 0, green: 255, blue: 0}, - backgroundColor: {red: 100, green: 100, blue: 100}, // Why doesn't this and the next work? + font: { + size: 20 + }, + color: { + red: 0, + green: 255, + blue: 0 + }, + backgroundColor: { + red: 100, + green: 100, + blue: 100 + }, // Why doesn't this and the next work? backgroundAlpha: 0.9, x: toolBar.x - 5, // I'd like to add the score to the toolBar and have it drag with it, but toolBar doesn't support text (just buttons). y: toolBar.y - 30 // So next best thing is to position it each time as if it were on top. }); display3d = Entities.addEntity({ name: MyAvatar.displayName + " score", - textColor: {red: 255, green: 255, blue: 255}, + textColor: { + red: 255, + green: 255, + blue: 255 + }, type: "Text", text: text, lineHeight: 0.14, - backgroundColor: {red: 64, green: 64, blue: 64}, - dimensions: {x: 0.3, y: 0.2, z: 0.01}, + backgroundColor: { + red: 64, + green: 64, + blue: 64 + }, + dimensions: { + x: 0.3, + y: 0.2, + z: 0.01 + }, }); Script.update.connect(trackAvatarWithText); } else { - Overlays.editOverlay(display2d, {text: text}); - Entities.editEntity(display3d, {text: text}); + Overlays.editOverlay(display2d, { + text: text + }); + Entities.editEntity(display3d, { + text: text + }); } } + function removeDisplay() { if (display2d) { Overlays.deleteOverlay(display2d); @@ -131,42 +210,176 @@ function removeDisplay() { display3d = null; } } -function computeEnergy(collision, entityID) { - var id = entityID || collision.idA || collision.idB; - var entity = id && Entities.getEntityProperties(id); - var mass = entity ? (entity.density * entity.dimensions.x * entity.dimensions.y * entity.dimensions.z) : 1; - var linearVelocityChange = Vec3.length(collision.velocityChange); - var energy = 0.5 * mass * linearVelocityChange * linearVelocityChange; - return Math.min(Math.max(1.0, Math.round(energy)), 20); -} + + function gotHit(collision) { - var energy = computeEnergy(collision); - print("Got hit - " + energy + " from " + collision.idA + " " + collision.idB); - health -= energy; - flash({red: 255, green: 0, blue: 0}); - updateDisplay(); -} -function scoreHit(idA, idB, collision) { - var energy = computeEnergy(collision, idA); - print("Score + " + energy + " from " + JSON.stringify(idA) + " " + JSON.stringify(idB)); - health += energy; - flash({red: 0, green: 255, blue: 0}); + health -= 1; + flash({ + red: 255, + green: 0, + blue: 0 + }); updateDisplay(); } + function isFighting() { return stickID && (actionID !== nullActionID); } -function initControls() { - print("Sword hand is " + hand); + +var inHand = false; + + +function isControllerActive() { + // I don't think the hydra API provides any reliable way to know whether a particular controller is active. Ask for both. + controllerActive = (Vec3.length(Controller.getSpatialControlPosition(3)) > 0) || Vec3.length(Controller.getSpatialControlPosition(4)) > 0; + return controllerActive; +} + + +function removeSword() { + if (stickID) { + print('deleting action ' + actionID + ' and entity ' + stickID); + Entities.deleteAction(stickID, actionID); + Entities.deleteEntity(stickID); + stickID = null; + actionID = nullActionID; + Controller.mouseMoveEvent.disconnect(mouseMoveEvent); + MyAvatar.collisionWithEntity.disconnect(gotHit); + // removeEventhHandler happens automatically when the entity is deleted. + } + inHand = false; + if (originalAvatarCollisionSound !== undefined) { + MyAvatar.collisionSoundURL = originalAvatarCollisionSound; + } + removeDisplay(); + swordHeld = false; +} + +function cleanUp(leaveButtons) { + if (!leaveButtons) { + toolBar.cleanup(); + } + removeSword(); + zombieFight.cleanup(); +} + +function makeSword() { + var swordPosition = Vec3.sum(MyAvatar.position, Vec3.multiply(5, Quat.getFront(MyAvatar.orientation))); + var orientationAdjustment = Quat.fromPitchYawRollDegrees(90, 0, 0); + + stickID = Entities.addEntity({ + type: "Model", + name: "sword", + modelURL: swordModel, + compoundShapeURL: swordCollisionShape, + dimensions: dimensions, + position: swordPosition, + rotation: Quat.fromPitchYawRollDegrees(90, 0, 0), + damping: 0.1, + collisionSoundURL: swordCollisionSoundURL, + restitution: 0.01, + collisionsWillMove: true, + collideWithMyAvatar: true + }); + + if (originalAvatarCollisionSound === undefined) { + originalAvatarCollisionSound = MyAvatar.collisionSoundURL; // We won't get MyAvatar.collisionWithEntity unless there's a sound URL. (Bug.) + SoundCache.getSound(avatarCollisionSoundURL); // Interface does not currently "preload" this? (Bug?) + } + + if(!isControllerActive()) { + grabSword("right"); + } + MyAvatar.collisionSoundURL = avatarCollisionSoundURL; + Controller.mouseMoveEvent.connect(mouseMoveEvent); + MyAvatar.collisionWithEntity.connect(gotHit); + updateDisplay(); +} + + + +function grabSword(hand) { + var handRotation; if (hand === "right") { - controllerID = 3; // right handed + handRotation = MyAvatar.getRightPalmRotation(); + + } else if (hand === "left") { + handRotation = MyAvatar.getLeftPalmRotation(); + } + var swordRotation = Entities.getEntityProperties(stickID).rotation; + var offsetRotation = Quat.multiply(Quat.inverse(handRotation), swordRotation); + actionID = Entities.addAction("hold", stickID, { + relativePosition: { + x: 0.0, + y: 0.0, + z: -dimensions.z * 0.7 + }, + relativeRotation:offsetRotation, + hand: hand, + timeScale: 0.05 + }); + if (actionID === nullActionID) { + print('*** FAILED TO MAKE SWORD ACTION ***'); + cleanUp(); } else { - controllerID = 4; // left handed + swordHeld = true; } } -var inHand = false; + +function releaseSword() { + Entities.deleteAction(stickID, actionID); + actionID = nullActionID; + Entities.editEntity(stickID, { + velocity: { + x: 0, + y: 0, + z: 0 + }, + angularVelocity: { + x: 0, + y: 0, + z: 0 + } + }); + swordHeld = false; +} + +function update() { + updateControllerState(); + +} + +function updateControllerState() { + rightTriggerValue = Controller.getTriggerValue(rightTriggerButton); + leftTriggerValue = Controller.getTriggerValue(leftTriggerButton); + + if (rightTriggerValue > TRIGGER_THRESHOLD && !swordHeld) { + grabSword("right") + } else if (rightTriggerValue < TRIGGER_THRESHOLD && prevRightTriggerValue > TRIGGER_THRESHOLD && swordHeld) { + releaseSword(); + } + + if (leftTriggerValue > TRIGGER_THRESHOLD && !swordHeld) { + grabSword("left") + } else if (leftTriggerValue < TRIGGER_THRESHOLD && prevLeftTriggerValue > TRIGGER_THRESHOLD && swordHeld) { + releaseSword(); + } + + prevRightTriggerValue = rightTriggerValue; + prevLeftTriggerValue = leftTriggerValue; +} + +randFloat = function(low, high) { + return low + Math.random() * (high - low); +} + + +randInt = function(low, high) { + return Math.floor(randFloat(low, high)); +} + function positionStick(stickOrientation) { var reorient = Quat.fromPitchYawRollDegrees(0, -90, 0); var baseOffset = {x: -dimensions.z * 0.8, y: 0, z: 0}; @@ -188,23 +401,19 @@ function resetToHand() { // For use with controllers, puts the sword in contact Entities.updateAction(stickID, actionID, { relativePosition: {x: 0.0, y: 0.0, z: -dimensions.z * 0.5}, relativeRotation: Quat.fromVec3Degrees({x: 45.0, y: 0.0, z: 0.0}), - hand: hand, // It should not be necessary to repeat these two, but there seems to be a bug in that that + hand: "right", // It should not be necessary to repeat these two, but there seems to be a bug in that that timeScale: 0.05 // they do not retain their earlier values if you don't repeat them. }); inHand = true; } -function isControllerActive() { - // I don't think the hydra API provides any reliable way to know whether a particular controller is active. Ask for both. - controllerActive = (Vec3.length(Controller.getSpatialControlPosition(3)) > 0) || Vec3.length(Controller.getSpatialControlPosition(4)) > 0; - return controllerActive; -} + function mouseMoveEvent(event) { // When a controller like the hydra gives a mouse event, the x/y is not meaningful to us, but we can detect with a truty deviceID - if (event.deviceID || !isFighting() || isControllerActive()) { - print('Attempting attachment reset'); - resetToHand(); - return; - } + // if (event.deviceID || !isFighting() || isControllerActive()) { + // print('Attempting attachment reset'); + // resetToHand(); + // return; + // } var windowCenterX = Window.innerWidth / 2; var windowCenterY = Window.innerHeight / 2; var mouseXCenterOffset = event.x - windowCenterX; @@ -216,117 +425,27 @@ function mouseMoveEvent(event) { positionStick(stickOrientation); } -function removeSword() { - if (stickID) { - print('deleting action ' + actionID + ' and entity ' + stickID); - Entities.deleteAction(stickID, actionID); - Entities.deleteEntity(stickID); - stickID = null; - actionID = nullActionID; - Controller.mouseMoveEvent.disconnect(mouseMoveEvent); - MyAvatar.collisionWithEntity.disconnect(gotHit); - // removeEventhHandler happens automatically when the entity is deleted. - } - inHand = false; - if (originalAvatarCollisionSound !== undefined) { - MyAvatar.collisionSoundURL = originalAvatarCollisionSound; - } - removeDisplay(); -} -function cleanUp(leaveButtons) { - removeSword(); - targetIDs.forEach(function (id) { - Entities.deleteAction(id.entity, id.action); - Entities.deleteEntity(id.entity); - }); - targetIDs = []; - if (!leaveButtons) { - toolBar.cleanup(); - } -} -function makeSword() { - initControls(); - var swordPosition; - if (!isControllerActive()) { // Dont' knock yourself with sword - swordPosition = Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getFront(MyAvatar.orientation))); - } else if (hand === 'right') { - swordPosition = MyAvatar.getRightPalmPosition(); - } else { - swordPosition = MyAvatar.getLeftPalmPosition(); - } - stickID = Entities.addEntity({ - type: "Model", - modelURL: swordModel, - compoundShapeURL: swordCollisionShape, - dimensions: dimensions, - position: swordPosition, - rotation: MyAvatar.orientation, - damping: 0.1, - collisionSoundURL: swordCollisionSoundURL, - restitution: 0.01, - collisionsWillMove: true - }); - actionID = Entities.addAction("hold", stickID, { - relativePosition: {x: 0.0, y: 0.0, z: -dimensions.z * 0.5}, - relativeRotation: Quat.fromVec3Degrees({x: 45.0, y: 0.0, z: 0.0}), - hand: hand, - timeScale: 0.05 - }); - if (actionID === nullActionID) { - print('*** FAILED TO MAKE SWORD ACTION ***'); - cleanUp(); - } - if (originalAvatarCollisionSound === undefined) { - originalAvatarCollisionSound = MyAvatar.collisionSoundURL; // We won't get MyAvatar.collisionWithEntity unless there's a sound URL. (Bug.) - SoundCache.getSound(avatarCollisionSoundURL); // Interface does not currently "preload" this? (Bug?) - } - MyAvatar.collisionSoundURL = avatarCollisionSoundURL; - Controller.mouseMoveEvent.connect(mouseMoveEvent); - MyAvatar.collisionWithEntity.connect(gotHit); - Script.addEventHandler(stickID, 'collisionWithEntity', scoreHit); - updateDisplay(); -} function onClick(event) { switch (Overlays.getOverlayAtPoint(event)) { - case swordButton: - if (!stickID) { - makeSword(); - } else { - removeSword(); - } - break; - case targetButton: - var position = Vec3.sum(MyAvatar.position, {x: 1.0, y: 0.4, z: 0.0}); - var boxId = Entities.addEntity({ - type: "Box", - name: "dummy", - position: position, - dimensions: {x: 0.3, y: 0.7, z: 0.3}, - gravity: {x: 0.0, y: -3.0, z: 0.0}, - damping: 0.2, - collisionsWillMove: true - }); - - var pointToOffsetFrom = Vec3.sum(position, {x: 0.0, y: 2.0, z: 0.0}); - var action = Entities.addAction("offset", boxId, {pointToOffsetFrom: pointToOffsetFrom, - linearDistance: 2.0, - // linearTimeScale: 0.005 - linearTimeScale: 0.1 - }); - targetIDs.push({entity: boxId, action: action}); - break; - case switchHandsButton: - cleanUp('leaveButtons'); - hand = hand === "right" ? "left" : "right"; - Settings.setValue("highfidelity.sword.hand", hand); - makeSword(); - break; - case cleanupButton: - cleanUp('leaveButtons'); - break; + case swordButton: + if (!stickID) { + makeSword(); + } else { + removeSword(); + } + break; + case targetButton: + Script.include("zombieFight.js?v1"); + zombieFight = new ZombieFight(); + zombieFight.initiateZombieApocalypse(); + break; + case cleanupButton: + cleanUp('leaveButtons'); + break; } } Script.scriptEnding.connect(cleanUp); -Controller.mousePressEvent.connect(onClick); +Script.update.connect(update); +Controller.mousePressEvent.connect(onClick); \ No newline at end of file From 4ca333efe1f2f70f8a1794b50049e547383bd1b1 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 16 Jul 2015 12:38:11 -0700 Subject: [PATCH 02/26] Adding the scissor rect in the Batch and a way to enable the scissor test locally for clear commands --- libraries/gpu/src/gpu/Batch.cpp | 19 +++++++++-------- libraries/gpu/src/gpu/Batch.h | 19 +++++++++++------ libraries/gpu/src/gpu/GLBackend.cpp | 27 ++++++++++++++++++------ libraries/gpu/src/gpu/GLBackend.h | 1 + libraries/gpu/src/gpu/GLBackendState.cpp | 11 ++++++++++ 5 files changed, 55 insertions(+), 22 deletions(-) diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 5fbac3bc6c..68a6a2d6f5 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -102,9 +102,10 @@ void Batch::drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, ui _params.push_back(nbInstances); } -void Batch::clearFramebuffer(Framebuffer::Masks targets, const Vec4& color, float depth, int stencil) { +void Batch::clearFramebuffer(Framebuffer::Masks targets, const Vec4& color, float depth, int stencil, bool enableScissor) { ADD_COMMAND(clearFramebuffer); + _params.push_back(enableScissor); _params.push_back(stencil); _params.push_back(depth); _params.push_back(color.w); @@ -114,20 +115,20 @@ void Batch::clearFramebuffer(Framebuffer::Masks targets, const Vec4& color, floa _params.push_back(targets); } -void Batch::clearColorFramebuffer(Framebuffer::Masks targets, const Vec4& color) { - clearFramebuffer(targets & Framebuffer::BUFFER_COLORS, color, 1.0f, 0); +void Batch::clearColorFramebuffer(Framebuffer::Masks targets, const Vec4& color, bool enableScissor) { + clearFramebuffer(targets & Framebuffer::BUFFER_COLORS, color, 1.0f, 0, enableScissor); } -void Batch::clearDepthFramebuffer(float depth) { - clearFramebuffer(Framebuffer::BUFFER_DEPTH, Vec4(0.0f), depth, 0); +void Batch::clearDepthFramebuffer(float depth, bool enableScissor) { + clearFramebuffer(Framebuffer::BUFFER_DEPTH, Vec4(0.0f), depth, 0, enableScissor); } -void Batch::clearStencilFramebuffer(int stencil) { - clearFramebuffer(Framebuffer::BUFFER_STENCIL, Vec4(0.0f), 1.0f, stencil); +void Batch::clearStencilFramebuffer(int stencil, bool enableScissor) { + clearFramebuffer(Framebuffer::BUFFER_STENCIL, Vec4(0.0f), 1.0f, stencil, enableScissor); } -void Batch::clearDepthStencilFramebuffer(float depth, int stencil) { - clearFramebuffer(Framebuffer::BUFFER_DEPTHSTENCIL, Vec4(0.0f), depth, stencil); +void Batch::clearDepthStencilFramebuffer(float depth, int stencil, bool enableScissor) { + clearFramebuffer(Framebuffer::BUFFER_DEPTHSTENCIL, Vec4(0.0f), depth, stencil, enableScissor); } diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index bf6883e3a9..f202186963 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -62,11 +62,12 @@ public: // Clear framebuffer layers // Targets can be any of the render buffers contained in the Framebuffer - void clearFramebuffer(Framebuffer::Masks targets, const Vec4& color, float depth, int stencil); - void clearColorFramebuffer(Framebuffer::Masks targets, const Vec4& color); // not a command, just a shortcut for clearFramebuffer, mask out targets to make sure it touches only color targets - void clearDepthFramebuffer(float depth); // not a command, just a shortcut for clearFramebuffer, it touches only depth target - void clearStencilFramebuffer(int stencil); // not a command, just a shortcut for clearFramebuffer, it touches only stencil target - void clearDepthStencilFramebuffer(float depth, int stencil); // not a command, just a shortcut for clearFramebuffer, it touches depth and stencil target + // Optionally the scissor test can be enabled locally for this command and to restrict the clearing command to the pixels contained in the scissor rectangle + void clearFramebuffer(Framebuffer::Masks targets, const Vec4& color, float depth, int stencil, bool enableScissor = false); + void clearColorFramebuffer(Framebuffer::Masks targets, const Vec4& color, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, mask out targets to make sure it touches only color targets + void clearDepthFramebuffer(float depth, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, it touches only depth target + void clearStencilFramebuffer(int stencil, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, it touches only stencil target + void clearDepthStencilFramebuffer(float depth, int stencil, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, it touches depth and stencil target // Input Stage // InputFormat @@ -90,13 +91,18 @@ public: void setModelTransform(const Transform& model); void setViewTransform(const Transform& view); void setProjectionTransform(const Mat4& proj); - void setViewportTransform(const Vec4i& viewport); // Viewport is xy = low left corner in the framebuffer, zw = width height of the viewport + // Viewport is xy = low left corner in framebuffer, zw = width height of the viewport, expressed in pixels + void setViewportTransform(const Vec4i& viewport); // Pipeline Stage void setPipeline(const PipelinePointer& pipeline); void setStateBlendFactor(const Vec4& factor); + // Set the Scissor rect + // the rect coordinates are xy for the low left corner of the rect and zw for the width and height of the rect, expressed in pixels + void setStateScissorRect(const Vec4i& rect); + void setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size); void setUniformBuffer(uint32 slot, const BufferView& view); // not a command, just a shortcut from a BufferView @@ -173,6 +179,7 @@ public: COMMAND_setPipeline, COMMAND_setStateBlendFactor, + COMMAND_setStateScissorRect, COMMAND_setUniformBuffer, COMMAND_setResourceTexture, diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index adbef7cb31..1cabba2ebf 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -33,6 +33,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_setPipeline), (&::gpu::GLBackend::do_setStateBlendFactor), + (&::gpu::GLBackend::do_setStateScissorRect), (&::gpu::GLBackend::do_setUniformBuffer), (&::gpu::GLBackend::do_setResourceTexture), @@ -217,14 +218,15 @@ void GLBackend::do_drawIndexedInstanced(Batch& batch, uint32 paramOffset) { void GLBackend::do_clearFramebuffer(Batch& batch, uint32 paramOffset) { - uint32 masks = batch._params[paramOffset + 6]._uint; + uint32 masks = batch._params[paramOffset + 7]._uint; Vec4 color; - color.x = batch._params[paramOffset + 5]._float; - color.y = batch._params[paramOffset + 4]._float; - color.z = batch._params[paramOffset + 3]._float; - color.w = batch._params[paramOffset + 2]._float; - float depth = batch._params[paramOffset + 1]._float; - int stencil = batch._params[paramOffset + 0]._float; + color.x = batch._params[paramOffset + 6]._float; + color.y = batch._params[paramOffset + 5]._float; + color.z = batch._params[paramOffset + 4]._float; + color.w = batch._params[paramOffset + 3]._float; + float depth = batch._params[paramOffset + 2]._float; + int stencil = batch._params[paramOffset + 1]._int; + int useScissor = batch._params[paramOffset + 0]._int; GLuint glmask = 0; if (masks & Framebuffer::BUFFER_DEPTH) { @@ -252,8 +254,19 @@ void GLBackend::do_clearFramebuffer(Batch& batch, uint32 paramOffset) { } } + // Apply scissor if needed and if not already on + bool doEnableScissor = (useScissor && (!_pipeline._stateCache.scissorEnable)); + if (doEnableScissor) { + glEnable(GL_SCISSOR_TEST); + } + glClear(glmask); + // Restore scissor if needed + if (doEnableScissor) { + glDisable(GL_SCISSOR_TEST); + } + // Restore the color draw buffers only if a frmaebuffer is bound if (_output._framebuffer && !drawBuffers.empty()) { auto glFramebuffer = syncGPUObject(*_output._framebuffer); diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 491897b281..aedf058c82 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -350,6 +350,7 @@ protected: // Pipeline Stage void do_setPipeline(Batch& batch, uint32 paramOffset); void do_setStateBlendFactor(Batch& batch, uint32 paramOffset); + void do_setStateScissorRect(Batch& batch, uint32 paramOffset); // Standard update pipeline check that the current Program and current State or good to go for a void updatePipeline(); diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp index e898a29245..787fb35a4b 100644 --- a/libraries/gpu/src/gpu/GLBackendState.cpp +++ b/libraries/gpu/src/gpu/GLBackendState.cpp @@ -753,3 +753,14 @@ void GLBackend::do_setStateBlendFactor(Batch& batch, uint32 paramOffset) { glBlendColor(factor.x, factor.y, factor.z, factor.w); (void) CHECK_GL_ERROR(); } + +void GLBackend::do_setStateScissorRect(Batch& batch, uint32 paramOffset) { + + Vec4 rect(batch._params[paramOffset + 0]._float, + batch._params[paramOffset + 1]._float, + batch._params[paramOffset + 2]._float, + batch._params[paramOffset + 3]._float); + + glScissor(rect.x, rect.y, rect.z, rect.w); + (void) CHECK_GL_ERROR(); +} From f7108ccff80776c48b8300d0fa1b99b0c0717d49 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 16 Jul 2015 13:27:59 -0700 Subject: [PATCH 03/26] modified collision-hull model to not include the handle. This prevents the sword handle from pushing the brandishing avatar around, while still letting the sword sit in said avatar's hand in a more aesthetically pleasing manner than floating off in space --- examples/example/games/sword.js | 90 ++++++++++++--------------------- 1 file changed, 33 insertions(+), 57 deletions(-) diff --git a/examples/example/games/sword.js b/examples/example/games/sword.js index 6504bd0494..e09e25bcdc 100644 --- a/examples/example/games/sword.js +++ b/examples/example/games/sword.js @@ -1,10 +1,10 @@ -// stick.js +// sword.js // examples // // Created by Seth Alves on 2015-6-10 // Copyright 2015 High Fidelity, Inc. // -// Allow avatar to hold a stick +// Allow avatar to hold a sword // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -21,7 +21,7 @@ var hand = "right"; var nullActionID = "00000000-0000-0000-0000-000000000000"; var controllerID; var controllerActive; -var stickID = null; +var swordID = null; var actionID = nullActionID; var dimensions = { x: 0.3, @@ -30,33 +30,9 @@ var dimensions = { }; var BUTTON_SIZE = 32; -var Y_AXIS = { - x: 0, - y: 1, - z: 0 -}; -var X_AXIS = { - x: 1, - y: 0, - z: 0 -}; - -var theta = 0.0; - -var RAD_TO_DEG = 180.0 / Math.PI; - -function orientationOf(vector) { - var direction, yaw, pitch; - direction = Vec3.normalize(vector); - yaw = Quat.angleAxis(Math.atan2(direction.x, direction.z) * RAD_TO_DEG, Y_AXIS); - pitch = Quat.angleAxis(Math.asin(-direction.y) * RAD_TO_DEG, X_AXIS); - return Quat.multiply(yaw, pitch); -} - - -var stickModel = "https://hifi-public.s3.amazonaws.com/eric/models/stick.fbx"; var swordModel = "https://hifi-public.s3.amazonaws.com/ozan/props/sword/sword.fbx"; -var swordCollisionShape = "https://hifi-public.s3.amazonaws.com/ozan/props/sword/sword.obj"; +// var swordCollisionShape = "https://hifi-public.s3.amazonaws.com/ozan/props/sword/sword.obj"; +var swordCollisionShape = "https://hifi-public.s3.amazonaws.com/eric/models/noHandleSwordCollisionShape.obj?=v1"; var swordCollisionSoundURL = "http://public.highfidelity.io/sounds/Collisions-hitsandslaps/swordStrike1.wav"; var avatarCollisionSoundURL = "https://s3.amazonaws.com/hifi-public/sounds/Collisions-hitsandslaps/airhockey_hit1.wav"; var whichModel = "sword"; @@ -121,6 +97,7 @@ function clearFlash() { } function flash(color) { + return; clearFlash(); flasher = {}; flasher.overlay = Overlays.addOverlay("text", { @@ -224,7 +201,7 @@ function gotHit(collision) { function isFighting() { - return stickID && (actionID !== nullActionID); + return swordID && (actionID !== nullActionID); } @@ -239,11 +216,11 @@ function isControllerActive() { function removeSword() { - if (stickID) { - print('deleting action ' + actionID + ' and entity ' + stickID); - Entities.deleteAction(stickID, actionID); - Entities.deleteEntity(stickID); - stickID = null; + if (swordID) { + print('deleting action ' + actionID + ' and entity ' + swordID); + Entities.deleteAction(swordID, actionID); + Entities.deleteEntity(swordID); + swordID = null; actionID = nullActionID; Controller.mouseMoveEvent.disconnect(mouseMoveEvent); MyAvatar.collisionWithEntity.disconnect(gotHit); @@ -269,7 +246,7 @@ function makeSword() { var swordPosition = Vec3.sum(MyAvatar.position, Vec3.multiply(5, Quat.getFront(MyAvatar.orientation))); var orientationAdjustment = Quat.fromPitchYawRollDegrees(90, 0, 0); - stickID = Entities.addEntity({ + swordID = Entities.addEntity({ type: "Model", name: "sword", modelURL: swordModel, @@ -281,7 +258,6 @@ function makeSword() { collisionSoundURL: swordCollisionSoundURL, restitution: 0.01, collisionsWillMove: true, - collideWithMyAvatar: true }); if (originalAvatarCollisionSound === undefined) { @@ -308,13 +284,13 @@ function grabSword(hand) { } else if (hand === "left") { handRotation = MyAvatar.getLeftPalmRotation(); } - var swordRotation = Entities.getEntityProperties(stickID).rotation; + var swordRotation = Entities.getEntityProperties(swordID).rotation; var offsetRotation = Quat.multiply(Quat.inverse(handRotation), swordRotation); - actionID = Entities.addAction("hold", stickID, { + actionID = Entities.addAction("hold", swordID, { relativePosition: { x: 0.0, y: 0.0, - z: -dimensions.z * 0.7 + z: -dimensions.z * 0.5 }, relativeRotation:offsetRotation, hand: hand, @@ -329,9 +305,9 @@ function grabSword(hand) { } function releaseSword() { - Entities.deleteAction(stickID, actionID); + Entities.deleteAction(swordID, actionID); actionID = nullActionID; - Entities.editEntity(stickID, { + Entities.editEntity(swordID, { velocity: { x: 0, y: 0, @@ -380,25 +356,25 @@ randInt = function(low, high) { return Math.floor(randFloat(low, high)); } -function positionStick(stickOrientation) { +function positionSword(swordOrientation) { var reorient = Quat.fromPitchYawRollDegrees(0, -90, 0); var baseOffset = {x: -dimensions.z * 0.8, y: 0, z: 0}; var offset = Vec3.multiplyQbyV(reorient, baseOffset); - stickOrientation = Quat.multiply(reorient, stickOrientation); + swordOrientation = Quat.multiply(reorient, swordOrientation); inHand = false; - Entities.updateAction(stickID, actionID, { + Entities.updateAction(swordID, actionID, { relativePosition: offset, - relativeRotation: stickOrientation, + relativeRotation: swordOrientation, hand: "right" }); } function resetToHand() { // For use with controllers, puts the sword in contact with the hand. - // Maybe coordinate with positionStick? + // Maybe coordinate with positionSword? if (inHand) { // Optimization: bail if we're already inHand. return; } print('Reset to hand'); - Entities.updateAction(stickID, actionID, { + Entities.updateAction(swordID, actionID, { relativePosition: {x: 0.0, y: 0.0, z: -dimensions.z * 0.5}, relativeRotation: Quat.fromVec3Degrees({x: 45.0, y: 0.0, z: 0.0}), hand: "right", // It should not be necessary to repeat these two, but there seems to be a bug in that that @@ -408,12 +384,12 @@ function resetToHand() { // For use with controllers, puts the sword in contact } function mouseMoveEvent(event) { - // When a controller like the hydra gives a mouse event, the x/y is not meaningful to us, but we can detect with a truty deviceID - // if (event.deviceID || !isFighting() || isControllerActive()) { - // print('Attempting attachment reset'); - // resetToHand(); - // return; - // } + //When a controller like the hydra gives a mouse event, the x/y is not meaningful to us, but we can detect with a truty deviceID + if (event.deviceID || !isFighting() || isControllerActive()) { + print('Attempting attachment reset'); + resetToHand(); + return; + } var windowCenterX = Window.innerWidth / 2; var windowCenterY = Window.innerHeight / 2; var mouseXCenterOffset = event.x - windowCenterX; @@ -421,15 +397,15 @@ function mouseMoveEvent(event) { var mouseXRatio = mouseXCenterOffset / windowCenterX; var mouseYRatio = mouseYCenterOffset / windowCenterY; - var stickOrientation = Quat.fromPitchYawRollDegrees(mouseYRatio * 90, mouseXRatio * 90, 0); - positionStick(stickOrientation); + var swordOrientation = Quat.fromPitchYawRollDegrees(mouseYRatio * 90, mouseXRatio * 90, 0); + positionSword(swordOrientation); } function onClick(event) { switch (Overlays.getOverlayAtPoint(event)) { case swordButton: - if (!stickID) { + if (!swordID) { makeSword(); } else { removeSword(); From 66154d20e06cba54642f753342c88b2c30d2607c Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 16 Jul 2015 13:38:39 -0700 Subject: [PATCH 04/26] deleted unnessary log message --- examples/example/games/sword.js | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/example/games/sword.js b/examples/example/games/sword.js index e09e25bcdc..361ec71f42 100644 --- a/examples/example/games/sword.js +++ b/examples/example/games/sword.js @@ -386,7 +386,6 @@ function resetToHand() { // For use with controllers, puts the sword in contact function mouseMoveEvent(event) { //When a controller like the hydra gives a mouse event, the x/y is not meaningful to us, but we can detect with a truty deviceID if (event.deviceID || !isFighting() || isControllerActive()) { - print('Attempting attachment reset'); resetToHand(); return; } From 398075e45aa32775988e671857f012b518fa08da Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 16 Jul 2015 16:26:28 -0700 Subject: [PATCH 05/26] hacking on more naked GL --- interface/src/Application.cpp | 5 + interface/src/Application.h | 3 - interface/src/audio/AudioScope.cpp | 4 +- interface/src/audio/AudioScope.h | 1 + interface/src/ui/ApplicationCompositor.cpp | 31 ++-- interface/src/ui/ApplicationOverlay.cpp | 180 +++++++++++++------ interface/src/ui/ApplicationOverlay.h | 9 +- interface/src/ui/overlays/Overlays.cpp | 17 +- libraries/render-utils/src/GeometryCache.cpp | 2 + 9 files changed, 185 insertions(+), 67 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 056490806a..71eabd2d6d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -895,6 +895,11 @@ void Application::paintGL() { { PerformanceTimer perfTimer("renderOverlay"); + + // NOTE: the ApplicationOverlay class assumes it's viewport is setup to be the device size + // There is no batch associated with this renderArgs + QSize size = qApp->getDeviceSize(); + renderArgs._viewport = glm::ivec4(0, 0, size.width(), size.height()); _applicationOverlay.renderOverlay(&renderArgs); } diff --git a/interface/src/Application.h b/interface/src/Application.h index 44ead54563..d2a55fbf70 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -359,9 +359,6 @@ signals: /// Fired when we're rendering in-world interface elements; allows external parties to hook in. void renderingInWorldInterface(); - /// Fired when we're rendering the overlay. - void renderingOverlay(); - /// Fired when the import window is closed void importDone(); diff --git a/interface/src/audio/AudioScope.cpp b/interface/src/audio/AudioScope.cpp index 4b4e86e7f4..d9ceb82eef 100644 --- a/interface/src/audio/AudioScope.cpp +++ b/interface/src/audio/AudioScope.cpp @@ -38,6 +38,7 @@ AudioScope::AudioScope() : _scopeOutputLeft(NULL), _scopeOutputRight(NULL), _scopeLastFrame(), + _audioScopeBackground(DependencyManager::get()->allocateID()), _audioScopeGrid(DependencyManager::get()->allocateID()), _inputID(DependencyManager::get()->allocateID()), _outputLeftID(DependencyManager::get()->allocateID()), @@ -135,7 +136,8 @@ void AudioScope::render(RenderArgs* renderArgs, int width, int height) { batch.setProjectionTransform(legacyProjection); batch.setModelTransform(Transform()); batch.setViewTransform(Transform()); - geometryCache->renderQuad(batch, x, y, w, h, backgroundColor); + batch._glLineWidth(1.0f); // default + geometryCache->renderQuad(batch, x, y, w, h, backgroundColor, _audioScopeBackground); geometryCache->renderGrid(batch, x, y, w, h, gridRows, gridCols, gridColor, _audioScopeGrid); renderLineStrip(batch, _inputID, inputColor, x, y, _samplesPerScope, _scopeInputOffset, _scopeInput); renderLineStrip(batch, _outputLeftID, outputLeftColor, x, y, _samplesPerScope, _scopeOutputOffset, _scopeOutputLeft); diff --git a/interface/src/audio/AudioScope.h b/interface/src/audio/AudioScope.h index 4ff4b55c29..0b716d7666 100644 --- a/interface/src/audio/AudioScope.h +++ b/interface/src/audio/AudioScope.h @@ -69,6 +69,7 @@ private: QByteArray* _scopeOutputRight; QByteArray _scopeLastFrame; + int _audioScopeBackground; int _audioScopeGrid; int _inputID; int _outputLeftID; diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 4623109cdd..56735111c1 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -189,8 +189,9 @@ void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) { return; } - GLuint texture = qApp->getApplicationOverlay().getOverlayTexture(); - if (!texture) { + //GLuint texture = 0; // FIXME -- qApp->getApplicationOverlay().getOverlayTexture(); + gpu::FramebufferPointer overlayFramebuffer = qApp->getApplicationOverlay().getOverlayFramebuffer(); + if (!overlayFramebuffer) { return; } @@ -209,9 +210,12 @@ void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) { batch.setModelTransform(Transform()); batch.setViewTransform(Transform()); batch.setProjectionTransform(mat4()); - batch._glBindTexture(GL_TEXTURE_2D, texture); - batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + //batch._glBindTexture(GL_TEXTURE_2D, texture); + //batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + //batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + batch.setResourceTexture(0, overlayFramebuffer->getRenderBuffer(0)); + geometryCache->renderUnitQuad(batch, vec4(vec3(1), _alpha)); // Doesn't actually render @@ -258,8 +262,12 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int return; } - GLuint texture = qApp->getApplicationOverlay().getOverlayTexture(); - if (!texture) { + //GLuint texture = 0; // FIXME -- qApp->getApplicationOverlay().getOverlayTexture(); + //if (!texture) { + // return; + //} + gpu::FramebufferPointer overlayFramebuffer = qApp->getApplicationOverlay().getOverlayFramebuffer(); + if (!overlayFramebuffer) { return; } @@ -275,9 +283,12 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int geometryCache->useSimpleDrawPipeline(batch); batch._glDisable(GL_DEPTH_TEST); batch._glDisable(GL_CULL_FACE); - batch._glBindTexture(GL_TEXTURE_2D, texture); - batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + //batch._glBindTexture(GL_TEXTURE_2D, texture); + //batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + //batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + batch.setResourceTexture(0, overlayFramebuffer->getRenderBuffer(0)); + batch.setViewTransform(Transform()); batch.setProjectionTransform(qApp->getEyeProjection(eye)); diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 63dcba9d5d..f89867c70d 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -40,12 +40,6 @@ const float CONNECTION_STATUS_BORDER_LINE_WIDTH = 4.0f; static const float ORTHO_NEAR_CLIP = -10000; static const float ORTHO_FAR_CLIP = 10000; -// TODO move somewhere useful -static void fboViewport(QOpenGLFramebufferObject* fbo) { - auto size = fbo->size(); - glViewport(0, 0, size.width(), size.height()); -} - ApplicationOverlay::ApplicationOverlay() { auto geometryCache = DependencyManager::get(); @@ -84,16 +78,41 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { buildFramebufferObject(); // Execute the batch into our framebuffer - _overlayFramebuffer->bind(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - fboViewport(_overlayFramebuffer); + + gpu::Batch batch; + + // 1) bind the framebuffer + //_overlayFramebuffer->bind(); + batch.setFramebuffer(_overlayFramebuffer); + + // 2) clear it... + //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glm::vec4 color { 0.0f, 0.0f, 0.0f, 0.0f }; + float depth = 1.0f; + int stencil = 0; + //batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLORS | gpu::Framebuffer::BUFFER_DEPTH, color, depth, stencil); + batch.clearColorFramebuffer(_overlayFramebuffer->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f)); + + int width = _overlayFramebuffer ? _overlayFramebuffer->getWidth() : 0; + int height = _overlayFramebuffer ? _overlayFramebuffer->getHeight() : 0; + + glViewport(0, 0, width, height); + + qDebug() << "ApplicationOverlay::renderOverlay()... "; + qDebug() << " renderArgs->batch:" << (void*)renderArgs->_batch; + qDebug() << " renderArgs->_viewport:" << renderArgs->_viewport.z << "," << renderArgs->_viewport.w; + qDebug() << " getDeviceSize:" << qApp->getDeviceSize(); + qDebug() << " getCanvasSize:" << qApp->getCanvasSize(); + qDebug() << " _overlayFramebuffer size:" << width << "," << height; // Now render the overlay components together into a single texture - renderOverlays(renderArgs); - renderStatsAndLogs(renderArgs); - renderDomainConnectionStatusBorder(renderArgs); - renderQmlUi(renderArgs); - _overlayFramebuffer->release(); + renderOverlays(renderArgs); // renders Scripts Overlay and AudioScope + renderStatsAndLogs(renderArgs); // currently renders nothing + renderDomainConnectionStatusBorder(renderArgs); // renders the connected domain line + renderQmlUi(renderArgs); // renders a unit quad with the QML UI texture + + //_overlayFramebuffer->release(); // now we're done for later composition + batch.setFramebuffer(nullptr); CHECK_GL_ERROR(); } @@ -102,11 +121,15 @@ void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) { if (_uiTexture) { gpu::Batch batch; auto geometryCache = DependencyManager::get(); + geometryCache->useSimpleDrawPipeline(batch); batch.setProjectionTransform(mat4()); - batch.setModelTransform(mat4()); + batch.setModelTransform(Transform()); + batch.setViewTransform(Transform()); batch._glBindTexture(GL_TEXTURE_2D, _uiTexture); + geometryCache->renderUnitQuad(batch, glm::vec4(1)); + renderArgs->_context->syncCache(); renderArgs->_context->render(batch); } @@ -114,31 +137,34 @@ void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) { void ApplicationOverlay::renderOverlays(RenderArgs* renderArgs) { PROFILE_RANGE(__FUNCTION__); - glm::vec2 size = qApp->getCanvasSize(); - mat4 legacyProjection = glm::ortho(0, size.x, size.y, 0, ORTHO_NEAR_CLIP, ORTHO_FAR_CLIP); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadMatrixf(glm::value_ptr(legacyProjection)); - glMatrixMode(GL_MODELVIEW); - - glDisable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glUseProgram(0); - - // give external parties a change to hook in - emit qApp->renderingOverlay(); - qApp->getOverlays().renderHUD(renderArgs); - - DependencyManager::get()->render(renderArgs, _overlayFramebuffer->size().width(), _overlayFramebuffer->size().height()); - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - - fboViewport(_overlayFramebuffer); + gpu::Batch batch; + auto geometryCache = DependencyManager::get(); + geometryCache->useSimpleDrawPipeline(batch); + auto textureCache = DependencyManager::get(); + batch.setResourceTexture(0, textureCache->getWhiteTexture()); + int width = renderArgs->_viewport.z; + int height = renderArgs->_viewport.w; + mat4 legacyProjection = glm::ortho(0, width, height, 0, -1000, 1000); + batch.setProjectionTransform(legacyProjection); + batch.setModelTransform(Transform()); + batch.setViewTransform(Transform()); + batch._glLineWidth(1.0f); // default + + { + // Render all of the Script based "HUD" aka 2D overlays. + // note: we call them HUD, as opposed to 2D, only because there are some cases of 3D HUD overlays, like the + // cameral controls for the edit.js + qApp->getOverlays().renderHUD(renderArgs); + + // Render the audio scope + int width = _overlayFramebuffer ? _overlayFramebuffer->getWidth() : 0; + int height = _overlayFramebuffer ? _overlayFramebuffer->getHeight() : 0; + DependencyManager::get()->render(renderArgs, width, height); + } + + renderArgs->_context->syncCache(); + renderArgs->_context->render(batch); } void ApplicationOverlay::renderRearViewToFbo(RenderArgs* renderArgs) { @@ -202,32 +228,86 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder(RenderArgs* renderAr } } -GLuint ApplicationOverlay::getOverlayTexture() { - if (!_overlayFramebuffer) { - return 0; - } - return _overlayFramebuffer->texture(); -} - void ApplicationOverlay::buildFramebufferObject() { PROFILE_RANGE(__FUNCTION__); - QSize fboSize = qApp->getDeviceSize(); - if (_overlayFramebuffer && fboSize == _overlayFramebuffer->size()) { + + QSize desiredSize = qApp->getDeviceSize(); + int currentWidth = _overlayFramebuffer ? _overlayFramebuffer->getWidth() : 0; + int currentHeight = _overlayFramebuffer ? _overlayFramebuffer->getHeight() : 0; + QSize frameBufferCurrentSize(currentWidth, currentHeight); + + if (_overlayFramebuffer && desiredSize == frameBufferCurrentSize) { // Already built return; } if (_overlayFramebuffer) { - delete _overlayFramebuffer; + _overlayFramebuffer.reset(); + _overlayDepthTexture.reset(); + _overlayColorTexture.reset(); } + + _overlayFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); + + auto colorFormat = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); + auto width = desiredSize.width(); + auto height = desiredSize.height(); + + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); + _overlayColorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); + _overlayFramebuffer->setRenderBuffer(0, _overlayColorTexture); + + + auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); + _overlayDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, width, height, defaultSampler)); + + _overlayFramebuffer->setDepthStencilBuffer(_overlayDepthTexture, depthFormat); + + + /* + // This code essentially created a frame buffer, then sets a bunch of the parameters for that texture. _overlayFramebuffer = new QOpenGLFramebufferObject(fboSize, QOpenGLFramebufferObject::Depth); + + GLfloat borderColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + + gpu::Batch batch; + batch._glBindTexture(GL_TEXTURE_2D, getOverlayTexture()); + batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + batch._glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); + batch._glBindTexture(GL_TEXTURE_2D, 0); + */ + + /* glBindTexture(GL_TEXTURE_2D, getOverlayTexture()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - GLfloat borderColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); glBindTexture(GL_TEXTURE_2D, 0); + */ + + + + /**** Example code... + batch._glBindTexture(GL_TEXTURE_2D, texture); + batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + + // this stuff is what would actually render from the texture + + geometryCache->useSimpleDrawPipeline(batch); + batch.setViewportTransform(glm::ivec4(0, 0, deviceSize.width(), deviceSize.height())); + batch.setModelTransform(Transform()); + batch.setViewTransform(Transform()); + batch.setProjectionTransform(mat4()); + batch._glBindTexture(GL_TEXTURE_2D, texture); + geometryCache->renderUnitQuad(batch, vec4(vec3(1), _alpha)); + ****/ + } diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index 2f434ed7e1..0bbe4e3f77 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -25,7 +25,8 @@ public: ~ApplicationOverlay(); void renderOverlay(RenderArgs* renderArgs); - GLuint getOverlayTexture(); + + gpu::FramebufferPointer getOverlayFramebuffer() const { return _overlayFramebuffer; } private: void renderStatsAndLogs(RenderArgs* renderArgs); @@ -44,7 +45,11 @@ private: int _magnifierBorder; ivec2 _previousBorderSize{ -1 }; - QOpenGLFramebufferObject* _overlayFramebuffer{ nullptr }; + + gpu::TexturePointer _overlayDepthTexture; + gpu::TexturePointer _overlayColorTexture; + gpu::FramebufferPointer _overlayFramebuffer; + }; #endif // hifi_ApplicationOverlay_h diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index e4401b32ef..8a1aa1014e 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -100,9 +100,24 @@ void Overlays::renderHUD(RenderArgs* renderArgs) { QReadLocker lock(&_lock); gpu::Batch batch; renderArgs->_batch = &batch; - + + auto geometryCache = DependencyManager::get(); + auto textureCache = DependencyManager::get(); + int width = renderArgs->_viewport.z; + int height = renderArgs->_viewport.w; + mat4 legacyProjection = glm::ortho(0, width, height, 0, -1000, 1000); + foreach(Overlay::Pointer thisOverlay, _overlaysHUD) { + + // Reset all batch pipeline settings between overlay + geometryCache->useSimpleDrawPipeline(batch); + batch.setResourceTexture(0, textureCache->getWhiteTexture()); + batch.setProjectionTransform(legacyProjection); + batch.setModelTransform(Transform()); + batch.setViewTransform(Transform()); + batch._glLineWidth(1.0f); // default + thisOverlay->render(renderArgs); } diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 2bf41bc9b3..7cb882acc1 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -433,6 +433,8 @@ void GeometryCache::renderGrid(gpu::Batch& batch, int x, int y, int width, int h } // Draw vertical grid lines for (int i = cols + 1; --i >= 0; ) { + //glVertex2i(tx, y); + //glVertex2i(tx, y + height); *(vertex++) = tx; *(vertex++) = y; From 09430b6596107f9fbdf7dfd76ed6851dcc2411a7 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 16 Jul 2015 16:27:41 -0700 Subject: [PATCH 06/26] hacking on more naked GL --- interface/src/ui/ApplicationOverlay.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index f89867c70d..cfa0390e73 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -90,8 +90,8 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { glm::vec4 color { 0.0f, 0.0f, 0.0f, 0.0f }; float depth = 1.0f; int stencil = 0; - //batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLORS | gpu::Framebuffer::BUFFER_DEPTH, color, depth, stencil); - batch.clearColorFramebuffer(_overlayFramebuffer->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f)); + batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLORS | gpu::Framebuffer::BUFFER_DEPTH, color, depth, stencil); + //batch.clearColorFramebuffer(_overlayFramebuffer->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f)); int width = _overlayFramebuffer ? _overlayFramebuffer->getWidth() : 0; int height = _overlayFramebuffer ? _overlayFramebuffer->getHeight() : 0; From 069620b2d9cdfc7c840dbdae2a4df43b38fb2b8f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 16 Jul 2015 16:36:48 -0700 Subject: [PATCH 07/26] hacking on more naked GL --- interface/src/ui/ApplicationOverlay.cpp | 23 ++++++++++++++--------- interface/src/ui/overlays/Overlays.cpp | 7 +++---- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index cfa0390e73..4fa6cbcb92 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -80,6 +80,7 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { // Execute the batch into our framebuffer gpu::Batch batch; + renderArgs->_batch = &batch; // 1) bind the framebuffer //_overlayFramebuffer->bind(); @@ -113,13 +114,17 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { //_overlayFramebuffer->release(); // now we're done for later composition batch.setFramebuffer(nullptr); + + renderArgs->_context->syncCache(); + renderArgs->_context->render(batch); + CHECK_GL_ERROR(); } void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) { PROFILE_RANGE(__FUNCTION__); if (_uiTexture) { - gpu::Batch batch; + gpu::Batch& batch = *renderArgs->_batch; auto geometryCache = DependencyManager::get(); geometryCache->useSimpleDrawPipeline(batch); @@ -130,15 +135,15 @@ void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) { geometryCache->renderUnitQuad(batch, glm::vec4(1)); - renderArgs->_context->syncCache(); - renderArgs->_context->render(batch); + //renderArgs->_context->syncCache(); + //renderArgs->_context->render(batch); } } void ApplicationOverlay::renderOverlays(RenderArgs* renderArgs) { PROFILE_RANGE(__FUNCTION__); - gpu::Batch batch; + gpu::Batch& batch = *renderArgs->_batch; auto geometryCache = DependencyManager::get(); geometryCache->useSimpleDrawPipeline(batch); auto textureCache = DependencyManager::get(); @@ -163,8 +168,8 @@ void ApplicationOverlay::renderOverlays(RenderArgs* renderArgs) { DependencyManager::get()->render(renderArgs, width, height); } - renderArgs->_context->syncCache(); - renderArgs->_context->render(batch); + //renderArgs->_context->syncCache(); + //renderArgs->_context->render(batch); } void ApplicationOverlay::renderRearViewToFbo(RenderArgs* renderArgs) { @@ -208,7 +213,7 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder(RenderArgs* renderAr }); auto nodeList = DependencyManager::get(); if (nodeList && !nodeList->getDomainHandler().isConnected()) { - gpu::Batch batch; + gpu::Batch& batch = *renderArgs->_batch; auto geometryCache = DependencyManager::get(); geometryCache->useSimpleDrawPipeline(batch); batch.setProjectionTransform(mat4()); @@ -223,8 +228,8 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder(RenderArgs* renderAr //batch.setModelTransform(glm::scale(mat4(), vec3(scaleAmount))); geometryCache->renderVertices(batch, gpu::LINE_STRIP, _domainStatusBorder); - renderArgs->_context->syncCache(); - renderArgs->_context->render(batch); + //renderArgs->_context->syncCache(); + //renderArgs->_context->render(batch); } } diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 8a1aa1014e..343e571bfe 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -98,8 +98,7 @@ void Overlays::cleanupOverlaysToDelete() { void Overlays::renderHUD(RenderArgs* renderArgs) { PROFILE_RANGE(__FUNCTION__); QReadLocker lock(&_lock); - gpu::Batch batch; - renderArgs->_batch = &batch; + gpu::Batch& batch = *renderArgs->_batch; auto geometryCache = DependencyManager::get(); auto textureCache = DependencyManager::get(); @@ -121,8 +120,8 @@ void Overlays::renderHUD(RenderArgs* renderArgs) { thisOverlay->render(renderArgs); } - renderArgs->_context->syncCache(); - renderArgs->_context->render(batch); + //renderArgs->_context->syncCache(); + //renderArgs->_context->render(batch); } unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& properties) { From 410e0a99ad58b8c2d26a8ac10432d42ab5038868 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 16 Jul 2015 16:45:58 -0700 Subject: [PATCH 08/26] hacking on more naked GL --- interface/src/ui/ApplicationOverlay.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 4fa6cbcb92..f2d00512ae 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -89,7 +89,7 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { // 2) clear it... //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glm::vec4 color { 0.0f, 0.0f, 0.0f, 0.0f }; - float depth = 1.0f; + float depth = 0.0f; int stencil = 0; batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLORS | gpu::Framebuffer::BUFFER_DEPTH, color, depth, stencil); //batch.clearColorFramebuffer(_overlayFramebuffer->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f)); @@ -97,14 +97,8 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { int width = _overlayFramebuffer ? _overlayFramebuffer->getWidth() : 0; int height = _overlayFramebuffer ? _overlayFramebuffer->getHeight() : 0; - glViewport(0, 0, width, height); - - qDebug() << "ApplicationOverlay::renderOverlay()... "; - qDebug() << " renderArgs->batch:" << (void*)renderArgs->_batch; - qDebug() << " renderArgs->_viewport:" << renderArgs->_viewport.z << "," << renderArgs->_viewport.w; - qDebug() << " getDeviceSize:" << qApp->getDeviceSize(); - qDebug() << " getCanvasSize:" << qApp->getCanvasSize(); - qDebug() << " _overlayFramebuffer size:" << width << "," << height; + //glViewport(0, 0, width, height); + batch.setViewportTransform(glm::ivec4(0, 0, width, height)); // Now render the overlay components together into a single texture renderOverlays(renderArgs); // renders Scripts Overlay and AudioScope @@ -113,7 +107,7 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { renderQmlUi(renderArgs); // renders a unit quad with the QML UI texture //_overlayFramebuffer->release(); // now we're done for later composition - batch.setFramebuffer(nullptr); + //batch.setFramebuffer(nullptr); renderArgs->_context->syncCache(); renderArgs->_context->render(batch); From 220b54e5f7cb5596f0f0cf5c1e0da70d0e45ef00 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 16 Jul 2015 18:30:24 -0700 Subject: [PATCH 09/26] added reference to correct zombie game script --- examples/example/games/sword.js | 73 +++++++++++++++++++++++++++------ 1 file changed, 60 insertions(+), 13 deletions(-) diff --git a/examples/example/games/sword.js b/examples/example/games/sword.js index 361ec71f42..41223401c3 100644 --- a/examples/example/games/sword.js +++ b/examples/example/games/sword.js @@ -30,14 +30,20 @@ var dimensions = { }; var BUTTON_SIZE = 32; +var health = 100; +var healthLossOnHit = 10; + var swordModel = "https://hifi-public.s3.amazonaws.com/ozan/props/sword/sword.fbx"; // var swordCollisionShape = "https://hifi-public.s3.amazonaws.com/ozan/props/sword/sword.obj"; -var swordCollisionShape = "https://hifi-public.s3.amazonaws.com/eric/models/noHandleSwordCollisionShape.obj?=v1"; +var swordCollisionShape = "https://hifi-public.s3.amazonaws.com/eric/models/noHandleSwordCollisionShape.obj?=v2"; var swordCollisionSoundURL = "http://public.highfidelity.io/sounds/Collisions-hitsandslaps/swordStrike1.wav"; -var avatarCollisionSoundURL = "https://s3.amazonaws.com/hifi-public/sounds/Collisions-hitsandslaps/airhockey_hit1.wav"; +var avatarCollisionSoundURL = "https://hifi-public.s3.amazonaws.com/eric/sounds/blankSound.wav"; //Just to avoid no collision callback bug +var zombieGameScriptURL = "https://hifi-public.s3.amazonaws.com/eric/scripts/zombieFight.js"; var whichModel = "sword"; var originalAvatarCollisionSound; +var avatarCollisionSounds = [SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/avatarHit.wav"), SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/avatarHit2.wav?=v2")]; + var toolBar = new ToolBar(0, 0, ToolBar.vertical, "highfidelity.sword.toolbar", function() { return { x: 100, @@ -45,6 +51,8 @@ var toolBar = new ToolBar(0, 0, ToolBar.vertical, "highfidelity.sword.toolbar", }; }); +var gameStarted = false; + var SWORD_IMAGE = "https://hifi-public.s3.amazonaws.com/images/sword/sword.svg"; // Toggle between brandishing/sheathing sword (creating if necessary) var TARGET_IMAGE = "https://hifi-public.s3.amazonaws.com/images/sword/dummy2.svg"; // Create a target dummy var CLEANUP_IMAGE = "http://s3.amazonaws.com/hifi-public/images/delete.png"; // Remove sword and all target dummies.f @@ -109,7 +117,7 @@ function flash(color) { flasher.timer = Script.setTimeout(clearFlash, 500); } -var health = 100; + var display2d, display3d; function trackAvatarWithText() { @@ -126,7 +134,6 @@ function trackAvatarWithText() { function updateDisplay() { var text = health.toString(); if (!display2d) { - health = 100; display2d = Overlays.addOverlay("text", { text: text, font: { @@ -190,7 +197,24 @@ function removeDisplay() { function gotHit(collision) { - health -= 1; + Audio.playSound(avatarCollisionSounds[randInt(0, avatarCollisionSounds.length)], { + position: MyAvatar.position, + volume: 0.5 + }); + health -= healthLossOnHit; + if (health <= 30) { + Overlays.editOverlay(display2d, { + color: { + red: 200, + green: 10, + blue: 10 + } + }); + } + + if (health <= 0 && zombieFight) { + zombieFight.loseGame(); + } flash({ red: 255, green: 0, @@ -239,6 +263,7 @@ function cleanUp(leaveButtons) { toolBar.cleanup(); } removeSword(); + gameStarted = false; zombieFight.cleanup(); } @@ -265,7 +290,7 @@ function makeSword() { SoundCache.getSound(avatarCollisionSoundURL); // Interface does not currently "preload" this? (Bug?) } - if(!isControllerActive()) { + if (!isControllerActive()) { grabSword("right"); } MyAvatar.collisionSoundURL = avatarCollisionSoundURL; @@ -277,6 +302,10 @@ function makeSword() { function grabSword(hand) { + if (!swordID) { + print("Create a sword by clicking on sword icon!") + return; + } var handRotation; if (hand === "right") { handRotation = MyAvatar.getRightPalmRotation(); @@ -292,7 +321,7 @@ function grabSword(hand) { y: 0.0, z: -dimensions.z * 0.5 }, - relativeRotation:offsetRotation, + relativeRotation: offsetRotation, hand: hand, timeScale: 0.05 }); @@ -358,7 +387,11 @@ randInt = function(low, high) { function positionSword(swordOrientation) { var reorient = Quat.fromPitchYawRollDegrees(0, -90, 0); - var baseOffset = {x: -dimensions.z * 0.8, y: 0, z: 0}; + var baseOffset = { + x: -dimensions.z * 0.8, + y: 0, + z: 0 + }; var offset = Vec3.multiplyQbyV(reorient, baseOffset); swordOrientation = Quat.multiply(reorient, swordOrientation); inHand = false; @@ -368,6 +401,7 @@ function positionSword(swordOrientation) { hand: "right" }); } + function resetToHand() { // For use with controllers, puts the sword in contact with the hand. // Maybe coordinate with positionSword? if (inHand) { // Optimization: bail if we're already inHand. @@ -375,10 +409,18 @@ function resetToHand() { // For use with controllers, puts the sword in contact } print('Reset to hand'); Entities.updateAction(swordID, actionID, { - relativePosition: {x: 0.0, y: 0.0, z: -dimensions.z * 0.5}, - relativeRotation: Quat.fromVec3Degrees({x: 45.0, y: 0.0, z: 0.0}), - hand: "right", // It should not be necessary to repeat these two, but there seems to be a bug in that that - timeScale: 0.05 // they do not retain their earlier values if you don't repeat them. + relativePosition: { + x: 0.0, + y: 0.0, + z: -dimensions.z * 0.5 + }, + relativeRotation: Quat.fromVec3Degrees({ + x: 45.0, + y: 0.0, + z: 0.0 + }), + hand: "right", // It should not be necessary to repeat these two, but there seems to be a bug in that that + timeScale: 0.05 // they do not retain their earlier values if you don't repeat them. }); inHand = true; } @@ -411,9 +453,14 @@ function onClick(event) { } break; case targetButton: - Script.include("zombieFight.js?v1"); + if (gameStarted) { + return; + } + Script.include("https://hifi-public.s3.amazonaws.com/eric/scripts/zombieFight.js"); zombieFight = new ZombieFight(); zombieFight.initiateZombieApocalypse(); + gameStarted = true; + break; case cleanupButton: cleanUp('leaveButtons'); From c46533d9a675613998346671f5b2a98507ec4190 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 16 Jul 2015 21:05:14 -0700 Subject: [PATCH 10/26] Make renderGrid handle changing position and dimensions So that audio scope grid moves when Interface window is resized. --- libraries/render-utils/src/GeometryCache.cpp | 24 +++++++++++++------- libraries/render-utils/src/GeometryCache.h | 3 ++- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 2bf41bc9b3..30ee7a2108 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -392,7 +392,6 @@ void GeometryCache::renderGrid(int x, int y, int width, int height, int rows, in gpu::GLBackend::renderBatch(batch); } -// TODO: properly handle the x,y,w,h changing for an ID // TODO: why do we seem to create extra BatchItemDetails when we resize the window?? what's that?? void GeometryCache::renderGrid(gpu::Batch& batch, int x, int y, int width, int height, int rows, int cols, const glm::vec4& color, int id) { #ifdef WANT_DEBUG @@ -410,8 +409,23 @@ void GeometryCache::renderGrid(gpu::Batch& batch, int x, int y, int width, int h Vec3Pair colorKey(glm::vec3(color.x, color.y, rows), glm::vec3(color.z, color.y, cols)); int vertices = (cols + 1 + rows + 1) * 2; - if ((registered && !_registeredAlternateGridBuffers.contains(id)) || (!registered && !_alternateGridBuffers.contains(key))) { + if ((registered && (!_registeredAlternateGridBuffers.contains(id) || _lastRegisteredAlternateGridBuffers[id] != key)) + || (!registered && !_alternateGridBuffers.contains(key))) { + + if (registered && _registeredAlternateGridBuffers.contains(id)) { + _registeredAlternateGridBuffers[id].reset(); + #ifdef WANT_DEBUG + qCDebug(renderutils) << "renderGrid()... RELEASING REGISTERED VERTICES BUFFER"; + #endif + } + gpu::BufferPointer verticesBuffer(new gpu::Buffer()); + if (registered) { + _registeredAlternateGridBuffers[id] = verticesBuffer; + _lastRegisteredAlternateGridBuffers[id] = key; + } else { + _alternateGridBuffers[key] = verticesBuffer; + } GLfloat* vertexData = new GLfloat[vertices * 2]; GLfloat* vertex = vertexData; @@ -443,12 +457,6 @@ void GeometryCache::renderGrid(gpu::Batch& batch, int x, int y, int width, int h verticesBuffer->append(sizeof(GLfloat) * vertices * 2, (gpu::Byte*) vertexData); delete[] vertexData; - - if (registered) { - _registeredAlternateGridBuffers[id] = verticesBuffer; - } else { - _alternateGridBuffers[key] = verticesBuffer; - } } if (!_gridColors.contains(colorKey)) { diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index 2e64489c3e..47490bca0d 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -337,8 +337,9 @@ private: QHash _registeredDashedLines; QHash _gridBuffers; - QHash _registeredAlternateGridBuffers; QHash _alternateGridBuffers; + QHash _registeredAlternateGridBuffers; + QHash _lastRegisteredAlternateGridBuffers; QHash _gridColors; QHash _sphereVertices; From 33464dfd6c5d27fdb22959da619c5c3caedadef3 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 17 Jul 2015 11:35:42 -0700 Subject: [PATCH 11/26] cleanup dead code --- interface/src/ui/ApplicationCompositor.cpp | 4 +- interface/src/ui/ApplicationOverlay.cpp | 81 +++++----------------- 2 files changed, 19 insertions(+), 66 deletions(-) diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 56735111c1..d98ddf7d5a 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -210,10 +210,12 @@ void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) { batch.setModelTransform(Transform()); batch.setViewTransform(Transform()); batch.setProjectionTransform(mat4()); + + // FIXME - Is this the proper technique for selecting the source 2D texture used by the renderUnitQuad??? + // And, how do we make sure we're getting the right blend/resampler? //batch._glBindTexture(GL_TEXTURE_2D, texture); //batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - batch.setResourceTexture(0, overlayFramebuffer->getRenderBuffer(0)); geometryCache->renderUnitQuad(batch, vec4(vec3(1), _alpha)); diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index f2d00512ae..ea18867844 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -76,14 +76,16 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { AvatarInputs::getInstance()->update(); buildFramebufferObject(); + + if (!_overlayFramebuffer) { + return; // we can't do anything without our frame buffer. + } // Execute the batch into our framebuffer - gpu::Batch batch; renderArgs->_batch = &batch; // 1) bind the framebuffer - //_overlayFramebuffer->bind(); batch.setFramebuffer(_overlayFramebuffer); // 2) clear it... @@ -94,10 +96,9 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLORS | gpu::Framebuffer::BUFFER_DEPTH, color, depth, stencil); //batch.clearColorFramebuffer(_overlayFramebuffer->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f)); - int width = _overlayFramebuffer ? _overlayFramebuffer->getWidth() : 0; - int height = _overlayFramebuffer ? _overlayFramebuffer->getHeight() : 0; + int width = _overlayFramebuffer->getWidth(); + int height = _overlayFramebuffer->getHeight(); - //glViewport(0, 0, width, height); batch.setViewportTransform(glm::ivec4(0, 0, width, height)); // Now render the overlay components together into a single texture @@ -106,12 +107,11 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { renderDomainConnectionStatusBorder(renderArgs); // renders the connected domain line renderQmlUi(renderArgs); // renders a unit quad with the QML UI texture - //_overlayFramebuffer->release(); // now we're done for later composition - //batch.setFramebuffer(nullptr); - renderArgs->_context->syncCache(); renderArgs->_context->render(batch); + renderArgs->_batch = nullptr; // so future users of renderArgs don't try to use our batch + CHECK_GL_ERROR(); } @@ -128,9 +128,6 @@ void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) { batch._glBindTexture(GL_TEXTURE_2D, _uiTexture); geometryCache->renderUnitQuad(batch, glm::vec4(1)); - - //renderArgs->_context->syncCache(); - //renderArgs->_context->render(batch); } } @@ -161,9 +158,6 @@ void ApplicationOverlay::renderOverlays(RenderArgs* renderArgs) { int height = _overlayFramebuffer ? _overlayFramebuffer->getHeight() : 0; DependencyManager::get()->render(renderArgs, width, height); } - - //renderArgs->_context->syncCache(); - //renderArgs->_context->render(batch); } void ApplicationOverlay::renderRearViewToFbo(RenderArgs* renderArgs) { @@ -222,8 +216,6 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder(RenderArgs* renderAr //batch.setModelTransform(glm::scale(mat4(), vec3(scaleAmount))); geometryCache->renderVertices(batch, gpu::LINE_STRIP, _domainStatusBorder); - //renderArgs->_context->syncCache(); - //renderArgs->_context->render(batch); } } @@ -252,61 +244,20 @@ void ApplicationOverlay::buildFramebufferObject() { auto width = desiredSize.width(); auto height = desiredSize.height(); + // NOTE: I need to make sure this gpu::Sampler is using these values... + // + // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + // glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); _overlayColorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); _overlayFramebuffer->setRenderBuffer(0, _overlayColorTexture); - auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); _overlayDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, width, height, defaultSampler)); _overlayFramebuffer->setDepthStencilBuffer(_overlayDepthTexture, depthFormat); - - - /* - - // This code essentially created a frame buffer, then sets a bunch of the parameters for that texture. - _overlayFramebuffer = new QOpenGLFramebufferObject(fboSize, QOpenGLFramebufferObject::Depth); - - GLfloat borderColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - - gpu::Batch batch; - batch._glBindTexture(GL_TEXTURE_2D, getOverlayTexture()); - batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - batch._glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); - batch._glBindTexture(GL_TEXTURE_2D, 0); - */ - - /* - glBindTexture(GL_TEXTURE_2D, getOverlayTexture()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); - glBindTexture(GL_TEXTURE_2D, 0); - */ - - - - /**** Example code... - batch._glBindTexture(GL_TEXTURE_2D, texture); - batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - - // this stuff is what would actually render from the texture - - geometryCache->useSimpleDrawPipeline(batch); - batch.setViewportTransform(glm::ivec4(0, 0, deviceSize.width(), deviceSize.height())); - batch.setModelTransform(Transform()); - batch.setViewTransform(Transform()); - batch.setProjectionTransform(mat4()); - batch._glBindTexture(GL_TEXTURE_2D, texture); - geometryCache->renderUnitQuad(batch, vec4(vec3(1), _alpha)); - ****/ - } From 550e9224c5b65bedd321eb1248940f991d1eab47 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 17 Jul 2015 11:45:15 -0700 Subject: [PATCH 12/26] Mute / un-mute face tracking when menu item is changed from script --- interface/src/Application.cpp | 15 +++++++-------- interface/src/Application.h | 1 - interface/src/Menu.cpp | 3 +-- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 027ad159d0..b5b847ec16 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2041,13 +2041,6 @@ void Application::setActiveFaceTracker() { #endif } -void Application::toggleFaceTrackerMute() { - FaceTracker* faceTracker = getSelectedFaceTracker(); - if (faceTracker) { - faceTracker->toggleMute(); - } -} - bool Application::exportEntities(const QString& filename, const QVector& entityIDs) { QVector entities; @@ -2480,7 +2473,13 @@ void Application::update(float deltaTime) { { PerformanceTimer perfTimer("devices"); DeviceTracker::updateAll(); - FaceTracker* tracker = getActiveFaceTracker(); + + FaceTracker* tracker = getSelectedFaceTracker(); + if (tracker && Menu::getInstance()->isOptionChecked(MenuOption::MuteFaceTracking) != tracker->isMuted()) { + tracker->toggleMute(); + } + + tracker = getActiveFaceTracker(); if (tracker && !tracker->isMuted()) { tracker->update(deltaTime); diff --git a/interface/src/Application.h b/interface/src/Application.h index 44ead54563..3b1f41dd73 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -426,7 +426,6 @@ public slots: void resetSensors(); void setActiveFaceTracker(); - void toggleFaceTrackerMute(); void aboutApp(); void showEditEntitiesHelp(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 8b14830c2d..d31110b344 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -435,8 +435,7 @@ Menu::Menu() { #if defined(HAVE_FACESHIFT) || defined(HAVE_DDE) faceTrackingMenu->addSeparator(); addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::MuteFaceTracking, - Qt::CTRL | Qt::SHIFT | Qt::Key_F, true, // DDE face tracking is on by default - qApp, SLOT(toggleFaceTrackerMute())); + Qt::CTRL | Qt::SHIFT | Qt::Key_F, true); // DDE face tracking is on by default addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::AutoMuteAudio, 0, false); #endif From 4dadf60724c57bc60b411fcd23569da8edf55779 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 17 Jul 2015 12:50:20 -0700 Subject: [PATCH 13/26] some tweaks from Sam --- interface/src/ui/ApplicationOverlay.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index ea18867844..5d0e8cfa05 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -91,7 +91,7 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { // 2) clear it... //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glm::vec4 color { 0.0f, 0.0f, 0.0f, 0.0f }; - float depth = 0.0f; + float depth = 1.0f; int stencil = 0; batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLORS | gpu::Framebuffer::BUFFER_DEPTH, color, depth, stencil); //batch.clearColorFramebuffer(_overlayFramebuffer->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f)); @@ -252,7 +252,7 @@ void ApplicationOverlay::buildFramebufferObject() { // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); // glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); - auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR); _overlayColorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); _overlayFramebuffer->setRenderBuffer(0, _overlayColorTexture); From 5ba82faa4b672d5541c3e74623e0f4580c54b285 Mon Sep 17 00:00:00 2001 From: bwent Date: Fri, 17 Jul 2015 13:52:00 -0700 Subject: [PATCH 14/26] keyLightDirection displays in degrees in edit.js UI --- examples/edit.js | 59 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/examples/edit.js b/examples/edit.js index dfbace7be6..544f3c94b6 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -53,6 +53,10 @@ var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/"; var toolHeight = 50; var toolWidth = 50; +var DEGREES_TO_RADIANS = Math.PI / 180.0; +var RADIANS_TO_DEGREES = 180.0 / Math.PI; +var epsilon = 0.001; + var MIN_ANGULAR_SIZE = 2; var MAX_ANGULAR_SIZE = 45; var allowLargeModels = true; @@ -658,7 +662,7 @@ function handleIdleMouse() { idleMouseTimerId = null; if (isActive) { highlightEntityUnderCursor(lastMousePosition, true); - } + } } function highlightEntityUnderCursor(position, accurateRay) { @@ -1207,6 +1211,49 @@ PropertiesTool = function(opts) { webView.setVisible(visible); }; + vecToPolar = function(direction) { + var x = direction.x; + var y = direction.y; + var z = direction.z; + var pitch, yaw; + pitch = -Math.asin(y); + var c = Math.cos(-pitch); + if (Math.abs(pitch) > (Math.PI / 2.0 - epsilon)) { + //handle gymbal lock + if (pitch > 0) { + pitch = Math.PI / 2.0; + } else { + pitch = -Math.PI / 2.0; + } + yaw = 0.0; + } else { + if (z < 0) { + if(x > 0 && x < 1) { + yaw = Math.PI - Math.asin(x / c); + } else { + yaw = -Math.asin(x / c) - Math.PI; + } + } else { + yaw = Math.asin(x / c); + } + } + return { + x: pitch * RADIANS_TO_DEGREES, + y: yaw * RADIANS_TO_DEGREES, + z: 0.0 //discard roll component + }; + }; + + polarToVec = function(orientation) { + var pitch = orientation.x * DEGREES_TO_RADIANS; + var yaw = orientation.y * DEGREES_TO_RADIANS; + return { + x: Math.cos(pitch) * Math.sin(yaw), + y: Math.sin(-pitch), + z: Math.cos(pitch) * Math.cos(yaw) + }; + } + selectionManager.addEventListener(function() { data = { type: 'update', @@ -1216,7 +1263,12 @@ PropertiesTool = function(opts) { var entity = {}; entity.id = selectionManager.selections[i]; entity.properties = Entities.getEntityProperties(selectionManager.selections[i]); - entity.properties.rotation = Quat.safeEulerAngles(entity.properties.rotation); + if (entity.properties.rotation !== undefined) { + entity.properties.rotation = Quat.safeEulerAngles(entity.properties.rotation); + } + if (entity.properties.keyLightDirection !== undefined) { + entity.properties.keyLightDirection = vecToPolar(entity.properties.keyLightDirection); + } selections.push(entity); } data.selections = selections; @@ -1244,6 +1296,9 @@ PropertiesTool = function(opts) { var rotation = data.properties.rotation; data.properties.rotation = Quat.fromPitchYawRollDegrees(rotation.x, rotation.y, rotation.z); } + if (data.properties.keyLightDirection !== undefined) { + data.properties.keyLightDirection = polarToVec(data.properties.keyLightDirection); + } Entities.editEntity(selectionManager.selections[0], data.properties); if (data.properties.name != undefined) { entityListTool.sendUpdate(); From ccd2f98a76db96ffd53e02786ad80e181efec0fa Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 17 Jul 2015 15:28:25 -0700 Subject: [PATCH 15/26] one more try --- interface/src/ui/ApplicationOverlay.cpp | 13 ++++++------- libraries/gpu/src/gpu/GLBackend.cpp | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 5d0e8cfa05..2cf7c508ec 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -85,6 +85,11 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { gpu::Batch batch; renderArgs->_batch = &batch; + int width = _overlayFramebuffer->getWidth(); + int height = _overlayFramebuffer->getHeight(); + + batch.setViewportTransform(glm::ivec4(0, 0, width, height)); + // 1) bind the framebuffer batch.setFramebuffer(_overlayFramebuffer); @@ -93,13 +98,7 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { glm::vec4 color { 0.0f, 0.0f, 0.0f, 0.0f }; float depth = 1.0f; int stencil = 0; - batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLORS | gpu::Framebuffer::BUFFER_DEPTH, color, depth, stencil); - //batch.clearColorFramebuffer(_overlayFramebuffer->getBufferMask(), glm::vec4(0.0f, 0.0f, 0.0f, 0.0f)); - - int width = _overlayFramebuffer->getWidth(); - int height = _overlayFramebuffer->getHeight(); - - batch.setViewportTransform(glm::ivec4(0, 0, width, height)); + batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH, color, depth, stencil); // Now render the overlay components together into a single texture renderOverlays(renderArgs); // renders Scripts Overlay and AudioScope diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index adbef7cb31..b14f9afc97 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -227,7 +227,7 @@ void GLBackend::do_clearFramebuffer(Batch& batch, uint32 paramOffset) { int stencil = batch._params[paramOffset + 0]._float; GLuint glmask = 0; - if (masks & Framebuffer::BUFFER_DEPTH) { + if (masks & Framebuffer::BUFFER_STENCIL) { glClearStencil(stencil); glmask |= GL_STENCIL_BUFFER_BIT; } From 03a44a1c80cf7e816201f02944d3a585dd3b295e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 17 Jul 2015 15:45:42 -0700 Subject: [PATCH 16/26] fix retina --- interface/src/Application.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d815329602..b3270332f4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -898,8 +898,8 @@ void Application::paintGL() { // NOTE: the ApplicationOverlay class assumes it's viewport is setup to be the device size // There is no batch associated with this renderArgs - QSize size = qApp->getDeviceSize(); - renderArgs._viewport = glm::ivec4(0, 0, size.width(), size.height()); + glm::vec2 size = getCanvasSize(); + renderArgs._viewport = glm::ivec4(0, 0, size.x, size.y); _applicationOverlay.renderOverlay(&renderArgs); } From 9eff19b0f75aee0053326576928b4dc18156203b Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 17 Jul 2015 15:47:17 -0700 Subject: [PATCH 17/26] add th emissing function --- libraries/gpu/src/gpu/Batch.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 68a6a2d6f5..9f75f9a94f 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -213,6 +213,14 @@ void Batch::setStateBlendFactor(const Vec4& factor) { _params.push_back(factor.w); } +void Batch::setStateScissorRect(const Vec4i& rect) { + ADD_COMMAND(setStateScissorRect); + + _params.push_back(rect.x); + _params.push_back(rect.y); + _params.push_back(rect.z); + _params.push_back(rect.w); +} void Batch::setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size) { ADD_COMMAND(setUniformBuffer); From c20c6e4b90081b4b36310e830fcb3789678ce2af Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 17 Jul 2015 16:01:32 -0700 Subject: [PATCH 18/26] fix retina in an Austin approved manner --- interface/src/Application.cpp | 5 +---- interface/src/ui/overlays/Overlays.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b3270332f4..002ba68a86 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -896,10 +896,7 @@ void Application::paintGL() { { PerformanceTimer perfTimer("renderOverlay"); - // NOTE: the ApplicationOverlay class assumes it's viewport is setup to be the device size - // There is no batch associated with this renderArgs - glm::vec2 size = getCanvasSize(); - renderArgs._viewport = glm::ivec4(0, 0, size.x, size.y); + // NOTE: There is no batch associated with this renderArgs _applicationOverlay.renderOverlay(&renderArgs); } diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 343e571bfe..0d40c60ca4 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -102,8 +102,10 @@ void Overlays::renderHUD(RenderArgs* renderArgs) { auto geometryCache = DependencyManager::get(); auto textureCache = DependencyManager::get(); - int width = renderArgs->_viewport.z; - int height = renderArgs->_viewport.w; + + auto size = qApp->getCanvasSize(); + int width = size.x; + int height = size.y; mat4 legacyProjection = glm::ortho(0, width, height, 0, -1000, 1000); From 8692f51399ca69cbb0302509c14c10359b4b4e82 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 17 Jul 2015 16:15:02 -0700 Subject: [PATCH 19/26] dead code cleanup --- interface/src/Application.cpp | 3 +++ interface/src/ui/ApplicationCompositor.cpp | 12 ------------ interface/src/ui/ApplicationOverlay.cpp | 12 ------------ interface/src/ui/overlays/Overlays.cpp | 3 --- 4 files changed, 3 insertions(+), 27 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 002ba68a86..d36392d61d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -897,6 +897,9 @@ void Application::paintGL() { PerformanceTimer perfTimer("renderOverlay"); // NOTE: There is no batch associated with this renderArgs + // the ApplicationOverlay class assumes it's viewport is setup to be the device size + QSize size = qApp->getDeviceSize(); + renderArgs._viewport = glm::ivec4(0, 0, size.width(), size.height()); _applicationOverlay.renderOverlay(&renderArgs); } diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index d98ddf7d5a..cd28ca0732 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -189,7 +189,6 @@ void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) { return; } - //GLuint texture = 0; // FIXME -- qApp->getApplicationOverlay().getOverlayTexture(); gpu::FramebufferPointer overlayFramebuffer = qApp->getApplicationOverlay().getOverlayFramebuffer(); if (!overlayFramebuffer) { return; @@ -210,14 +209,7 @@ void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) { batch.setModelTransform(Transform()); batch.setViewTransform(Transform()); batch.setProjectionTransform(mat4()); - - // FIXME - Is this the proper technique for selecting the source 2D texture used by the renderUnitQuad??? - // And, how do we make sure we're getting the right blend/resampler? - //batch._glBindTexture(GL_TEXTURE_2D, texture); - //batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - //batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); batch.setResourceTexture(0, overlayFramebuffer->getRenderBuffer(0)); - geometryCache->renderUnitQuad(batch, vec4(vec3(1), _alpha)); // Doesn't actually render @@ -264,10 +256,6 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int return; } - //GLuint texture = 0; // FIXME -- qApp->getApplicationOverlay().getOverlayTexture(); - //if (!texture) { - // return; - //} gpu::FramebufferPointer overlayFramebuffer = qApp->getApplicationOverlay().getOverlayFramebuffer(); if (!overlayFramebuffer) { return; diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 2cf7c508ec..afcccc4776 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -89,12 +89,8 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { int height = _overlayFramebuffer->getHeight(); batch.setViewportTransform(glm::ivec4(0, 0, width, height)); - - // 1) bind the framebuffer batch.setFramebuffer(_overlayFramebuffer); - // 2) clear it... - //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glm::vec4 color { 0.0f, 0.0f, 0.0f, 0.0f }; float depth = 1.0f; int stencil = 0; @@ -243,14 +239,6 @@ void ApplicationOverlay::buildFramebufferObject() { auto width = desiredSize.width(); auto height = desiredSize.height(); - // NOTE: I need to make sure this gpu::Sampler is using these values... - // - // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - // glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); - auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR); _overlayColorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler)); _overlayFramebuffer->setRenderBuffer(0, _overlayColorTexture); diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 0d40c60ca4..e801de4484 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -121,9 +121,6 @@ void Overlays::renderHUD(RenderArgs* renderArgs) { thisOverlay->render(renderArgs); } - - //renderArgs->_context->syncCache(); - //renderArgs->_context->render(batch); } unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& properties) { From 695470b1c1bf7ba7a1ebd7ab0d7812841ab1fd5f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 17 Jul 2015 16:30:10 -0700 Subject: [PATCH 20/26] fix audio scope --- interface/src/audio/AudioScope.cpp | 7 ++++--- interface/src/ui/ApplicationOverlay.cpp | 9 +++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/interface/src/audio/AudioScope.cpp b/interface/src/audio/AudioScope.cpp index d9ceb82eef..75a5137ca4 100644 --- a/interface/src/audio/AudioScope.cpp +++ b/interface/src/audio/AudioScope.cpp @@ -127,11 +127,14 @@ void AudioScope::render(RenderArgs* renderArgs, int width, int height) { int w = (int)SCOPE_WIDTH; int h = (int)SCOPE_HEIGHT; - gpu::Batch batch; + gpu::Batch& batch = *renderArgs->_batch; auto geometryCache = DependencyManager::get(); geometryCache->useSimpleDrawPipeline(batch); auto textureCache = DependencyManager::get(); batch.setResourceTexture(0, textureCache->getWhiteTexture()); + + // FIXME - do we really need to reset this here? we know that we're called inside of ApplicationOverlay::renderOverlays + // which already set up our batch for us to have these settings mat4 legacyProjection = glm::ortho(0, width, height, 0, -1000, 1000); batch.setProjectionTransform(legacyProjection); batch.setModelTransform(Transform()); @@ -142,8 +145,6 @@ void AudioScope::render(RenderArgs* renderArgs, int width, int height) { renderLineStrip(batch, _inputID, inputColor, x, y, _samplesPerScope, _scopeInputOffset, _scopeInput); renderLineStrip(batch, _outputLeftID, outputLeftColor, x, y, _samplesPerScope, _scopeOutputOffset, _scopeOutputLeft); renderLineStrip(batch, _outputRightD, outputRightColor, x, y, _samplesPerScope, _scopeOutputOffset, _scopeOutputRight); - renderArgs->_context->syncCache(); - renderArgs->_context->render(batch); } void AudioScope::renderLineStrip(gpu::Batch& batch, int id, const glm::vec4& color, int x, int y, int n, int offset, const QByteArray* byteArray) { diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index afcccc4776..f455b1dc62 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -143,15 +143,16 @@ void ApplicationOverlay::renderOverlays(RenderArgs* renderArgs) { batch._glLineWidth(1.0f); // default { + // Render the audio scope + //int width = _overlayFramebuffer ? _overlayFramebuffer->getWidth() : 0; + //int height = _overlayFramebuffer ? _overlayFramebuffer->getHeight() : 0; + DependencyManager::get()->render(renderArgs, width, height); + // Render all of the Script based "HUD" aka 2D overlays. // note: we call them HUD, as opposed to 2D, only because there are some cases of 3D HUD overlays, like the // cameral controls for the edit.js qApp->getOverlays().renderHUD(renderArgs); - // Render the audio scope - int width = _overlayFramebuffer ? _overlayFramebuffer->getWidth() : 0; - int height = _overlayFramebuffer ? _overlayFramebuffer->getHeight() : 0; - DependencyManager::get()->render(renderArgs, width, height); } } From eb989fd7250d690f1c92c821416c230d4f6a696a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 17 Jul 2015 16:38:05 -0700 Subject: [PATCH 21/26] fix the backround colors for text overlays, pending austins PR to really fix them --- interface/src/ui/overlays/Overlays.cpp | 2 +- interface/src/ui/overlays/TextOverlay.cpp | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index e801de4484..63b87a30ae 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -113,7 +113,7 @@ void Overlays::renderHUD(RenderArgs* renderArgs) { // Reset all batch pipeline settings between overlay geometryCache->useSimpleDrawPipeline(batch); - batch.setResourceTexture(0, textureCache->getWhiteTexture()); + batch.setResourceTexture(0, textureCache->getWhiteTexture()); // FIXME - do we really need to do this?? batch.setProjectionTransform(legacyProjection); batch.setModelTransform(Transform()); batch.setViewTransform(Transform()); diff --git a/interface/src/ui/overlays/TextOverlay.cpp b/interface/src/ui/overlays/TextOverlay.cpp index 3f033d9266..a2f0f13e82 100644 --- a/interface/src/ui/overlays/TextOverlay.cpp +++ b/interface/src/ui/overlays/TextOverlay.cpp @@ -71,6 +71,12 @@ void TextOverlay::render(RenderArgs* args) { return; // do nothing if we're not visible } + if (!args->_batch) { + return; // do nothing if the batch is not valid + } + + gpu::Batch& batch = *args->_batch; + const float MAX_COLOR = 255.0f; xColor backgroundColor = getBackgroundColor(); glm::vec4 quadColor(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR, backgroundColor.blue / MAX_COLOR, @@ -84,7 +90,7 @@ void TextOverlay::render(RenderArgs* args) { glm::vec2 topLeft(left, top); glm::vec2 bottomRight(right, bottom); glBindTexture(GL_TEXTURE_2D, 0); - DependencyManager::get()->renderQuad(topLeft, bottomRight, quadColor); + DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, quadColor); const int leftAdjust = -1; // required to make text render relative to left edge of bounds const int topAdjust = -2; // required to make text render relative to top edge of bounds From ecab2538d76ef58bf675d27ec1d353b41b0ab885 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 17 Jul 2015 17:27:15 -0700 Subject: [PATCH 22/26] quick hack to fix overlay ordering --- interface/src/ui/ApplicationOverlay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 2717a7fa8f..77a87a2b4b 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -97,10 +97,10 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH, color, depth, stencil); // Now render the overlay components together into a single texture + renderQmlUi(renderArgs); // renders a unit quad with the QML UI texture renderOverlays(renderArgs); // renders Scripts Overlay and AudioScope renderStatsAndLogs(renderArgs); // currently renders nothing renderDomainConnectionStatusBorder(renderArgs); // renders the connected domain line - renderQmlUi(renderArgs); // renders a unit quad with the QML UI texture renderArgs->_context->syncCache(); renderArgs->_context->render(batch); From 98c078d995656d4dec3339c30189f87d60345a40 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 17 Jul 2015 17:44:29 -0700 Subject: [PATCH 23/26] move audio scope to the back --- interface/src/ui/ApplicationOverlay.cpp | 41 ++++++++++++++++--------- interface/src/ui/ApplicationOverlay.h | 1 + 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 77a87a2b4b..da76e9c032 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -97,10 +97,11 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH, color, depth, stencil); // Now render the overlay components together into a single texture - renderQmlUi(renderArgs); // renders a unit quad with the QML UI texture + renderDomainConnectionStatusBorder(renderArgs); // renders the connected domain line + renderAudioScope(renderArgs); // audio scope in the very back + renderQmlUi(renderArgs); // renders a unit quad with the QML UI texture, and the text overlays from scripts renderOverlays(renderArgs); // renders Scripts Overlay and AudioScope renderStatsAndLogs(renderArgs); // currently renders nothing - renderDomainConnectionStatusBorder(renderArgs); // renders the connected domain line renderArgs->_context->syncCache(); renderArgs->_context->render(batch); @@ -126,6 +127,26 @@ void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) { } } +void ApplicationOverlay::renderAudioScope(RenderArgs* renderArgs) { + PROFILE_RANGE(__FUNCTION__); + + gpu::Batch& batch = *renderArgs->_batch; + auto geometryCache = DependencyManager::get(); + geometryCache->useSimpleDrawPipeline(batch); + auto textureCache = DependencyManager::get(); + batch.setResourceTexture(0, textureCache->getWhiteTexture()); + int width = renderArgs->_viewport.z; + int height = renderArgs->_viewport.w; + mat4 legacyProjection = glm::ortho(0, width, height, 0, -1000, 1000); + batch.setProjectionTransform(legacyProjection); + batch.setModelTransform(Transform()); + batch.setViewTransform(Transform()); + batch._glLineWidth(1.0f); // default + + // Render the audio scope + DependencyManager::get()->render(renderArgs, width, height); +} + void ApplicationOverlay::renderOverlays(RenderArgs* renderArgs) { PROFILE_RANGE(__FUNCTION__); @@ -142,18 +163,10 @@ void ApplicationOverlay::renderOverlays(RenderArgs* renderArgs) { batch.setViewTransform(Transform()); batch._glLineWidth(1.0f); // default - { - // Render the audio scope - //int width = _overlayFramebuffer ? _overlayFramebuffer->getWidth() : 0; - //int height = _overlayFramebuffer ? _overlayFramebuffer->getHeight() : 0; - DependencyManager::get()->render(renderArgs, width, height); - - // Render all of the Script based "HUD" aka 2D overlays. - // note: we call them HUD, as opposed to 2D, only because there are some cases of 3D HUD overlays, like the - // cameral controls for the edit.js - qApp->getOverlays().renderHUD(renderArgs); - - } + // Render all of the Script based "HUD" aka 2D overlays. + // note: we call them HUD, as opposed to 2D, only because there are some cases of 3D HUD overlays, like the + // cameral controls for the edit.js + qApp->getOverlays().renderHUD(renderArgs); } void ApplicationOverlay::renderRearViewToFbo(RenderArgs* renderArgs) { diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index 0bbe4e3f77..6aa5d2a9e8 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -34,6 +34,7 @@ private: void renderRearViewToFbo(RenderArgs* renderArgs); void renderRearView(RenderArgs* renderArgs); void renderQmlUi(RenderArgs* renderArgs); + void renderAudioScope(RenderArgs* renderArgs); void renderOverlays(RenderArgs* renderArgs); void buildFramebufferObject(); From d0489bf2a0bdc39b5f071959b263ddf2dc48c33c Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 17 Jul 2015 16:30:01 -0700 Subject: [PATCH 24/26] Add menu item, Developer > Render > Throttle FPS If Not Focus --- interface/src/Application.cpp | 5 +++++ interface/src/Application.h | 4 ++++ interface/src/GLCanvas.cpp | 9 ++++++--- interface/src/Menu.cpp | 2 ++ interface/src/Menu.h | 1 + 5 files changed, 18 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1aa9fe0427..eea35a2edf 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -338,6 +338,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _lastNackTime(usecTimestampNow()), _lastSendDownstreamAudioStats(usecTimestampNow()), _isVSyncOn(true), + _isThrottleFPSEnabled(true), _aboutToQuit(false), _notifiedPacketVersionMismatchThisDomain(false), _domainConnectionRefusals(QList()), @@ -4612,6 +4613,10 @@ void Application::setVSyncEnabled() { #endif } +void Application::setThrottleFPSEnabled() { + _isThrottleFPSEnabled = Menu::getInstance()->isOptionChecked(MenuOption::ThrottleFPSIfNotFocus); +} + bool Application::isVSyncOn() const { #if defined(Q_OS_WIN) if (wglewGetExtension("WGL_EXT_swap_control")) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 1fe1acb25a..0cdae2289f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -421,6 +421,9 @@ public slots: void domainSettingsReceived(const QJsonObject& domainSettingsObject); void setVSyncEnabled(); + + void setThrottleFPSEnabled(); + bool isThrottleFPSEnabled() { return _isThrottleFPSEnabled; } void resetSensors(); void setActiveFaceTracker(); @@ -637,6 +640,7 @@ private: quint64 _lastSendDownstreamAudioStats; bool _isVSyncOn; + bool _isThrottleFPSEnabled; bool _aboutToQuit; diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index aff7c75cc9..be7ed6ec72 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -35,7 +35,8 @@ void GLCanvas::stopFrameTimer() { } bool GLCanvas::isThrottleRendering() const { - return _throttleRendering || Application::getInstance()->getWindow()->isMinimized(); + return (_throttleRendering + || (Application::getInstance()->getWindow()->isMinimized() && Application::getInstance()->isThrottleFPSEnabled())); } int GLCanvas::getDeviceWidth() const { @@ -59,7 +60,8 @@ void GLCanvas::initializeGL() { void GLCanvas::paintGL() { PROFILE_RANGE(__FUNCTION__); - if (!_throttleRendering && !Application::getInstance()->getWindow()->isMinimized()) { + if (!_throttleRendering + && (!Application::getInstance()->getWindow()->isMinimized()) || !Application::getInstance()->isThrottleFPSEnabled()) { Application::getInstance()->paintGL(); } } @@ -85,7 +87,8 @@ void GLCanvas::activeChanged(Qt::ApplicationState state) { default: // Otherwise, throttle. - if (!_throttleRendering && !Application::getInstance()->isAboutToQuit()) { + if (!_throttleRendering && !Application::getInstance()->isAboutToQuit() + && Application::getInstance()->isThrottleFPSEnabled()) { _frameTimer.start(_idleRenderInterval); _throttleRendering = true; } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 7213d4eb79..6115cb673e 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -373,6 +373,8 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::RenderTargetFramerateVSyncOn, 0, true, qApp, SLOT(setVSyncEnabled())); #endif + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ThrottleFPSIfNotFocus, 0, true, + qApp, SLOT(setThrottleFPSEnabled())); } diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 22f07699a0..bd67c09f55 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -280,6 +280,7 @@ namespace MenuOption { const QString SuppressShortTimings = "Suppress Timings Less than 10ms"; const QString TestPing = "Test Ping"; const QString ThirdPerson = "Third Person"; + const QString ThrottleFPSIfNotFocus = "Throttle FPS If Not Focus"; const QString ToolWindow = "Tool Window"; const QString TransmitterDrive = "Transmitter Drive"; const QString TurnWithHead = "Turn using Head"; From 7b11d02eb2dfa0ad2ca26a6706ef53f6b9090935 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 18 Jul 2015 14:16:10 -0700 Subject: [PATCH 25/26] Default Throttle FPS to disabled --- interface/src/Menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6115cb673e..fcc5c84c90 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -373,7 +373,7 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::RenderTargetFramerateVSyncOn, 0, true, qApp, SLOT(setVSyncEnabled())); #endif - addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ThrottleFPSIfNotFocus, 0, true, + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ThrottleFPSIfNotFocus, 0, false, qApp, SLOT(setThrottleFPSEnabled())); } From 47fdbedfb278956cc22ad5509703615cbe7bf060 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 18 Jul 2015 15:22:47 -0700 Subject: [PATCH 26/26] Fix FPS throttle default --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index eea35a2edf..7605ee8f39 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -338,7 +338,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _lastNackTime(usecTimestampNow()), _lastSendDownstreamAudioStats(usecTimestampNow()), _isVSyncOn(true), - _isThrottleFPSEnabled(true), + _isThrottleFPSEnabled(false), _aboutToQuit(false), _notifiedPacketVersionMismatchThisDomain(false), _domainConnectionRefusals(QList()),