mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 05:17:02 +02:00
resolve conflicts on merge with upstream master
This commit is contained in:
commit
6b11495a20
20 changed files with 627 additions and 310 deletions
|
@ -53,6 +53,10 @@ var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/";
|
||||||
var toolHeight = 50;
|
var toolHeight = 50;
|
||||||
var toolWidth = 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 MIN_ANGULAR_SIZE = 2;
|
||||||
var MAX_ANGULAR_SIZE = 45;
|
var MAX_ANGULAR_SIZE = 45;
|
||||||
var allowLargeModels = true;
|
var allowLargeModels = true;
|
||||||
|
@ -658,7 +662,7 @@ function handleIdleMouse() {
|
||||||
idleMouseTimerId = null;
|
idleMouseTimerId = null;
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
highlightEntityUnderCursor(lastMousePosition, true);
|
highlightEntityUnderCursor(lastMousePosition, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function highlightEntityUnderCursor(position, accurateRay) {
|
function highlightEntityUnderCursor(position, accurateRay) {
|
||||||
|
@ -1207,6 +1211,49 @@ PropertiesTool = function(opts) {
|
||||||
webView.setVisible(visible);
|
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() {
|
selectionManager.addEventListener(function() {
|
||||||
data = {
|
data = {
|
||||||
type: 'update',
|
type: 'update',
|
||||||
|
@ -1216,7 +1263,12 @@ PropertiesTool = function(opts) {
|
||||||
var entity = {};
|
var entity = {};
|
||||||
entity.id = selectionManager.selections[i];
|
entity.id = selectionManager.selections[i];
|
||||||
entity.properties = Entities.getEntityProperties(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);
|
selections.push(entity);
|
||||||
}
|
}
|
||||||
data.selections = selections;
|
data.selections = selections;
|
||||||
|
@ -1244,6 +1296,9 @@ PropertiesTool = function(opts) {
|
||||||
var rotation = data.properties.rotation;
|
var rotation = data.properties.rotation;
|
||||||
data.properties.rotation = Quat.fromPitchYawRollDegrees(rotation.x, rotation.y, rotation.z);
|
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);
|
Entities.editEntity(selectionManager.selections[0], data.properties);
|
||||||
if (data.properties.name != undefined) {
|
if (data.properties.name != undefined) {
|
||||||
entityListTool.sendUpdate();
|
entityListTool.sendUpdate();
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
// stick.js
|
// sword.js
|
||||||
// examples
|
// examples
|
||||||
//
|
//
|
||||||
// Created by Seth Alves on 2015-6-10
|
// Created by Seth Alves on 2015-6-10
|
||||||
// Copyright 2015 High Fidelity, Inc.
|
// 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.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
@ -14,32 +14,48 @@
|
||||||
var Script, Entities, MyAvatar, Window, Overlays, Controller, Vec3, Quat, print, ToolBar, Settings; // Referenced globals provided by High Fidelity.
|
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");
|
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 nullActionID = "00000000-0000-0000-0000-000000000000";
|
||||||
var controllerID;
|
var controllerID;
|
||||||
var controllerActive;
|
var controllerActive;
|
||||||
var stickID = null;
|
var swordID = null;
|
||||||
var actionID = nullActionID;
|
var actionID = nullActionID;
|
||||||
var targetIDs = [];
|
var dimensions = {
|
||||||
var dimensions = { x: 0.3, y: 0.15, z: 2.0 };
|
x: 0.3,
|
||||||
|
y: 0.15,
|
||||||
|
z: 2.0
|
||||||
|
};
|
||||||
var BUTTON_SIZE = 32;
|
var BUTTON_SIZE = 32;
|
||||||
|
|
||||||
var stickModel = "https://hifi-public.s3.amazonaws.com/eric/models/stick.fbx";
|
var health = 100;
|
||||||
|
var healthLossOnHit = 10;
|
||||||
|
|
||||||
var swordModel = "https://hifi-public.s3.amazonaws.com/ozan/props/sword/sword.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?=v2";
|
||||||
var swordCollisionSoundURL = "http://public.highfidelity.io/sounds/Collisions-hitsandslaps/swordStrike1.wav";
|
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 whichModel = "sword";
|
||||||
var originalAvatarCollisionSound;
|
var originalAvatarCollisionSound;
|
||||||
|
|
||||||
var toolBar = new ToolBar(0, 0, ToolBar.vertical, "highfidelity.sword.toolbar", function () {
|
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")];
|
||||||
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 gameStarted = false;
|
||||||
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 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", {
|
var swordButton = toolBar.addOverlay("image", {
|
||||||
width: BUTTON_SIZE,
|
width: BUTTON_SIZE,
|
||||||
height: BUTTON_SIZE,
|
height: BUTTON_SIZE,
|
||||||
|
@ -52,12 +68,7 @@ var targetButton = toolBar.addOverlay("image", {
|
||||||
imageURL: TARGET_IMAGE,
|
imageURL: TARGET_IMAGE,
|
||||||
alpha: 1
|
alpha: 1
|
||||||
});
|
});
|
||||||
var switchHandsButton = toolBar.addOverlay("image", {
|
|
||||||
width: BUTTON_SIZE,
|
|
||||||
height: BUTTON_SIZE,
|
|
||||||
imageURL: SWITCH_HANDS_IMAGE,
|
|
||||||
alpha: 1
|
|
||||||
});
|
|
||||||
var cleanupButton = toolBar.addOverlay("image", {
|
var cleanupButton = toolBar.addOverlay("image", {
|
||||||
width: BUTTON_SIZE,
|
width: BUTTON_SIZE,
|
||||||
height: BUTTON_SIZE,
|
height: BUTTON_SIZE,
|
||||||
|
@ -66,6 +77,24 @@ var cleanupButton = toolBar.addOverlay("image", {
|
||||||
});
|
});
|
||||||
|
|
||||||
var flasher;
|
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() {
|
function clearFlash() {
|
||||||
if (!flasher) {
|
if (!flasher) {
|
||||||
return;
|
return;
|
||||||
|
@ -74,7 +103,9 @@ function clearFlash() {
|
||||||
Overlays.deleteOverlay(flasher.overlay);
|
Overlays.deleteOverlay(flasher.overlay);
|
||||||
flasher = null;
|
flasher = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function flash(color) {
|
function flash(color) {
|
||||||
|
return;
|
||||||
clearFlash();
|
clearFlash();
|
||||||
flasher = {};
|
flasher = {};
|
||||||
flasher.overlay = Overlays.addOverlay("text", {
|
flasher.overlay = Overlays.addOverlay("text", {
|
||||||
|
@ -86,42 +117,74 @@ function flash(color) {
|
||||||
flasher.timer = Script.setTimeout(clearFlash, 500);
|
flasher.timer = Script.setTimeout(clearFlash, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
var health = 100;
|
|
||||||
var display2d, display3d;
|
var display2d, display3d;
|
||||||
|
|
||||||
function trackAvatarWithText() {
|
function trackAvatarWithText() {
|
||||||
Entities.editEntity(display3d, {
|
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))
|
rotation: Quat.multiply(MyAvatar.orientation, Quat.fromPitchYawRollDegrees(0, 180, 0))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateDisplay() {
|
function updateDisplay() {
|
||||||
var text = health.toString();
|
var text = health.toString();
|
||||||
if (!display2d) {
|
if (!display2d) {
|
||||||
health = 100;
|
|
||||||
display2d = Overlays.addOverlay("text", {
|
display2d = Overlays.addOverlay("text", {
|
||||||
text: text,
|
text: text,
|
||||||
font: { size: 20 },
|
font: {
|
||||||
color: {red: 0, green: 255, blue: 0},
|
size: 20
|
||||||
backgroundColor: {red: 100, green: 100, blue: 100}, // Why doesn't this and the next work?
|
},
|
||||||
|
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,
|
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).
|
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.
|
y: toolBar.y - 30 // So next best thing is to position it each time as if it were on top.
|
||||||
});
|
});
|
||||||
display3d = Entities.addEntity({
|
display3d = Entities.addEntity({
|
||||||
name: MyAvatar.displayName + " score",
|
name: MyAvatar.displayName + " score",
|
||||||
textColor: {red: 255, green: 255, blue: 255},
|
textColor: {
|
||||||
|
red: 255,
|
||||||
|
green: 255,
|
||||||
|
blue: 255
|
||||||
|
},
|
||||||
type: "Text",
|
type: "Text",
|
||||||
text: text,
|
text: text,
|
||||||
lineHeight: 0.14,
|
lineHeight: 0.14,
|
||||||
backgroundColor: {red: 64, green: 64, blue: 64},
|
backgroundColor: {
|
||||||
dimensions: {x: 0.3, y: 0.2, z: 0.01},
|
red: 64,
|
||||||
|
green: 64,
|
||||||
|
blue: 64
|
||||||
|
},
|
||||||
|
dimensions: {
|
||||||
|
x: 0.3,
|
||||||
|
y: 0.2,
|
||||||
|
z: 0.01
|
||||||
|
},
|
||||||
});
|
});
|
||||||
Script.update.connect(trackAvatarWithText);
|
Script.update.connect(trackAvatarWithText);
|
||||||
} else {
|
} else {
|
||||||
Overlays.editOverlay(display2d, {text: text});
|
Overlays.editOverlay(display2d, {
|
||||||
Entities.editEntity(display3d, {text: text});
|
text: text
|
||||||
|
});
|
||||||
|
Entities.editEntity(display3d, {
|
||||||
|
text: text
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeDisplay() {
|
function removeDisplay() {
|
||||||
if (display2d) {
|
if (display2d) {
|
||||||
Overlays.deleteOverlay(display2d);
|
Overlays.deleteOverlay(display2d);
|
||||||
|
@ -131,97 +194,57 @@ function removeDisplay() {
|
||||||
display3d = null;
|
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) {
|
function gotHit(collision) {
|
||||||
var energy = computeEnergy(collision);
|
Audio.playSound(avatarCollisionSounds[randInt(0, avatarCollisionSounds.length)], {
|
||||||
print("Got hit - " + energy + " from " + collision.idA + " " + collision.idB);
|
position: MyAvatar.position,
|
||||||
health -= energy;
|
volume: 0.5
|
||||||
flash({red: 255, green: 0, blue: 0});
|
});
|
||||||
updateDisplay();
|
health -= healthLossOnHit;
|
||||||
}
|
if (health <= 30) {
|
||||||
function scoreHit(idA, idB, collision) {
|
Overlays.editOverlay(display2d, {
|
||||||
var energy = computeEnergy(collision, idA);
|
color: {
|
||||||
print("Score + " + energy + " from " + JSON.stringify(idA) + " " + JSON.stringify(idB));
|
red: 200,
|
||||||
health += energy;
|
green: 10,
|
||||||
flash({red: 0, green: 255, blue: 0});
|
blue: 10
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (health <= 0 && zombieFight) {
|
||||||
|
zombieFight.loseGame();
|
||||||
|
}
|
||||||
|
flash({
|
||||||
|
red: 255,
|
||||||
|
green: 0,
|
||||||
|
blue: 0
|
||||||
|
});
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function isFighting() {
|
function isFighting() {
|
||||||
return stickID && (actionID !== nullActionID);
|
return swordID && (actionID !== nullActionID);
|
||||||
}
|
}
|
||||||
|
|
||||||
function initControls() {
|
|
||||||
print("Sword hand is " + hand);
|
|
||||||
if (hand === "right") {
|
|
||||||
controllerID = 3; // right handed
|
|
||||||
} else {
|
|
||||||
controllerID = 4; // left handed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var inHand = false;
|
var inHand = false;
|
||||||
function positionStick(stickOrientation) {
|
|
||||||
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);
|
|
||||||
inHand = false;
|
|
||||||
Entities.updateAction(stickID, actionID, {
|
|
||||||
relativePosition: offset,
|
|
||||||
relativeRotation: stickOrientation,
|
|
||||||
hand: "right"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function resetToHand() { // For use with controllers, puts the sword in contact with the hand.
|
|
||||||
// Maybe coordinate with positionStick?
|
|
||||||
if (inHand) { // Optimization: bail if we're already inHand.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
print('Reset to hand');
|
|
||||||
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
|
|
||||||
timeScale: 0.05 // they do not retain their earlier values if you don't repeat them.
|
|
||||||
});
|
|
||||||
inHand = true;
|
|
||||||
}
|
|
||||||
function isControllerActive() {
|
function isControllerActive() {
|
||||||
// I don't think the hydra API provides any reliable way to know whether a particular controller is active. Ask for both.
|
// 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;
|
controllerActive = (Vec3.length(Controller.getSpatialControlPosition(3)) > 0) || Vec3.length(Controller.getSpatialControlPosition(4)) > 0;
|
||||||
return controllerActive;
|
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;
|
|
||||||
}
|
|
||||||
var windowCenterX = Window.innerWidth / 2;
|
|
||||||
var windowCenterY = Window.innerHeight / 2;
|
|
||||||
var mouseXCenterOffset = event.x - windowCenterX;
|
|
||||||
var mouseYCenterOffset = event.y - windowCenterY;
|
|
||||||
var mouseXRatio = mouseXCenterOffset / windowCenterX;
|
|
||||||
var mouseYRatio = mouseYCenterOffset / windowCenterY;
|
|
||||||
|
|
||||||
var stickOrientation = Quat.fromPitchYawRollDegrees(mouseYRatio * 90, mouseXRatio * 90, 0);
|
|
||||||
positionStick(stickOrientation);
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeSword() {
|
function removeSword() {
|
||||||
if (stickID) {
|
if (swordID) {
|
||||||
print('deleting action ' + actionID + ' and entity ' + stickID);
|
print('deleting action ' + actionID + ' and entity ' + swordID);
|
||||||
Entities.deleteAction(stickID, actionID);
|
Entities.deleteAction(swordID, actionID);
|
||||||
Entities.deleteEntity(stickID);
|
Entities.deleteEntity(swordID);
|
||||||
stickID = null;
|
swordID = null;
|
||||||
actionID = nullActionID;
|
actionID = nullActionID;
|
||||||
Controller.mouseMoveEvent.disconnect(mouseMoveEvent);
|
Controller.mouseMoveEvent.disconnect(mouseMoveEvent);
|
||||||
MyAvatar.collisionWithEntity.disconnect(gotHit);
|
MyAvatar.collisionWithEntity.disconnect(gotHit);
|
||||||
|
@ -232,101 +255,219 @@ function removeSword() {
|
||||||
MyAvatar.collisionSoundURL = originalAvatarCollisionSound;
|
MyAvatar.collisionSoundURL = originalAvatarCollisionSound;
|
||||||
}
|
}
|
||||||
removeDisplay();
|
removeDisplay();
|
||||||
|
swordHeld = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanUp(leaveButtons) {
|
function cleanUp(leaveButtons) {
|
||||||
removeSword();
|
|
||||||
targetIDs.forEach(function (id) {
|
|
||||||
Entities.deleteAction(id.entity, id.action);
|
|
||||||
Entities.deleteEntity(id.entity);
|
|
||||||
});
|
|
||||||
targetIDs = [];
|
|
||||||
if (!leaveButtons) {
|
if (!leaveButtons) {
|
||||||
toolBar.cleanup();
|
toolBar.cleanup();
|
||||||
}
|
}
|
||||||
|
removeSword();
|
||||||
|
gameStarted = false;
|
||||||
|
zombieFight.cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeSword() {
|
function makeSword() {
|
||||||
initControls();
|
var swordPosition = Vec3.sum(MyAvatar.position, Vec3.multiply(5, Quat.getFront(MyAvatar.orientation)));
|
||||||
var swordPosition;
|
var orientationAdjustment = Quat.fromPitchYawRollDegrees(90, 0, 0);
|
||||||
if (!isControllerActive()) { // Dont' knock yourself with sword
|
|
||||||
swordPosition = Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getFront(MyAvatar.orientation)));
|
swordID = Entities.addEntity({
|
||||||
} else if (hand === 'right') {
|
|
||||||
swordPosition = MyAvatar.getRightPalmPosition();
|
|
||||||
} else {
|
|
||||||
swordPosition = MyAvatar.getLeftPalmPosition();
|
|
||||||
}
|
|
||||||
stickID = Entities.addEntity({
|
|
||||||
type: "Model",
|
type: "Model",
|
||||||
|
name: "sword",
|
||||||
modelURL: swordModel,
|
modelURL: swordModel,
|
||||||
compoundShapeURL: swordCollisionShape,
|
compoundShapeURL: swordCollisionShape,
|
||||||
dimensions: dimensions,
|
dimensions: dimensions,
|
||||||
position: swordPosition,
|
position: swordPosition,
|
||||||
rotation: MyAvatar.orientation,
|
rotation: Quat.fromPitchYawRollDegrees(90, 0, 0),
|
||||||
damping: 0.1,
|
damping: 0.1,
|
||||||
collisionSoundURL: swordCollisionSoundURL,
|
collisionSoundURL: swordCollisionSoundURL,
|
||||||
restitution: 0.01,
|
restitution: 0.01,
|
||||||
collisionsWillMove: true
|
collisionsWillMove: true,
|
||||||
});
|
});
|
||||||
actionID = Entities.addAction("hold", stickID, {
|
|
||||||
relativePosition: {x: 0.0, y: 0.0, z: -dimensions.z * 0.5},
|
if (originalAvatarCollisionSound === undefined) {
|
||||||
relativeRotation: Quat.fromVec3Degrees({x: 45.0, y: 0.0, z: 0.0}),
|
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) {
|
||||||
|
if (!swordID) {
|
||||||
|
print("Create a sword by clicking on sword icon!")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var handRotation;
|
||||||
|
if (hand === "right") {
|
||||||
|
handRotation = MyAvatar.getRightPalmRotation();
|
||||||
|
|
||||||
|
} else if (hand === "left") {
|
||||||
|
handRotation = MyAvatar.getLeftPalmRotation();
|
||||||
|
}
|
||||||
|
var swordRotation = Entities.getEntityProperties(swordID).rotation;
|
||||||
|
var offsetRotation = Quat.multiply(Quat.inverse(handRotation), swordRotation);
|
||||||
|
actionID = Entities.addAction("hold", swordID, {
|
||||||
|
relativePosition: {
|
||||||
|
x: 0.0,
|
||||||
|
y: 0.0,
|
||||||
|
z: -dimensions.z * 0.5
|
||||||
|
},
|
||||||
|
relativeRotation: offsetRotation,
|
||||||
hand: hand,
|
hand: hand,
|
||||||
timeScale: 0.05
|
timeScale: 0.05
|
||||||
});
|
});
|
||||||
if (actionID === nullActionID) {
|
if (actionID === nullActionID) {
|
||||||
print('*** FAILED TO MAKE SWORD ACTION ***');
|
print('*** FAILED TO MAKE SWORD ACTION ***');
|
||||||
cleanUp();
|
cleanUp();
|
||||||
|
} else {
|
||||||
|
swordHeld = 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?)
|
|
||||||
}
|
|
||||||
MyAvatar.collisionSoundURL = avatarCollisionSoundURL;
|
|
||||||
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|
|
||||||
MyAvatar.collisionWithEntity.connect(gotHit);
|
|
||||||
Script.addEventHandler(stickID, 'collisionWithEntity', scoreHit);
|
|
||||||
updateDisplay();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function releaseSword() {
|
||||||
|
Entities.deleteAction(swordID, actionID);
|
||||||
|
actionID = nullActionID;
|
||||||
|
Entities.editEntity(swordID, {
|
||||||
|
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 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);
|
||||||
|
swordOrientation = Quat.multiply(reorient, swordOrientation);
|
||||||
|
inHand = false;
|
||||||
|
Entities.updateAction(swordID, actionID, {
|
||||||
|
relativePosition: offset,
|
||||||
|
relativeRotation: 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.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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.
|
||||||
|
});
|
||||||
|
inHand = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
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()) {
|
||||||
|
resetToHand();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var windowCenterX = Window.innerWidth / 2;
|
||||||
|
var windowCenterY = Window.innerHeight / 2;
|
||||||
|
var mouseXCenterOffset = event.x - windowCenterX;
|
||||||
|
var mouseYCenterOffset = event.y - windowCenterY;
|
||||||
|
var mouseXRatio = mouseXCenterOffset / windowCenterX;
|
||||||
|
var mouseYRatio = mouseYCenterOffset / windowCenterY;
|
||||||
|
|
||||||
|
var swordOrientation = Quat.fromPitchYawRollDegrees(mouseYRatio * 90, mouseXRatio * 90, 0);
|
||||||
|
positionSword(swordOrientation);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function onClick(event) {
|
function onClick(event) {
|
||||||
switch (Overlays.getOverlayAtPoint(event)) {
|
switch (Overlays.getOverlayAtPoint(event)) {
|
||||||
case swordButton:
|
case swordButton:
|
||||||
if (!stickID) {
|
if (!swordID) {
|
||||||
makeSword();
|
makeSword();
|
||||||
} else {
|
} else {
|
||||||
removeSword();
|
removeSword();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case targetButton:
|
case targetButton:
|
||||||
var position = Vec3.sum(MyAvatar.position, {x: 1.0, y: 0.4, z: 0.0});
|
if (gameStarted) {
|
||||||
var boxId = Entities.addEntity({
|
return;
|
||||||
type: "Box",
|
}
|
||||||
name: "dummy",
|
Script.include("https://hifi-public.s3.amazonaws.com/eric/scripts/zombieFight.js");
|
||||||
position: position,
|
zombieFight = new ZombieFight();
|
||||||
dimensions: {x: 0.3, y: 0.7, z: 0.3},
|
zombieFight.initiateZombieApocalypse();
|
||||||
gravity: {x: 0.0, y: -3.0, z: 0.0},
|
gameStarted = true;
|
||||||
damping: 0.2,
|
|
||||||
collisionsWillMove: true
|
|
||||||
});
|
|
||||||
|
|
||||||
var pointToOffsetFrom = Vec3.sum(position, {x: 0.0, y: 2.0, z: 0.0});
|
break;
|
||||||
var action = Entities.addAction("offset", boxId, {pointToOffsetFrom: pointToOffsetFrom,
|
case cleanupButton:
|
||||||
linearDistance: 2.0,
|
cleanUp('leaveButtons');
|
||||||
// linearTimeScale: 0.005
|
break;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Script.scriptEnding.connect(cleanUp);
|
Script.scriptEnding.connect(cleanUp);
|
||||||
Controller.mousePressEvent.connect(onClick);
|
Script.update.connect(update);
|
||||||
|
Controller.mousePressEvent.connect(onClick);
|
|
@ -337,6 +337,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
||||||
_lastNackTime(usecTimestampNow()),
|
_lastNackTime(usecTimestampNow()),
|
||||||
_lastSendDownstreamAudioStats(usecTimestampNow()),
|
_lastSendDownstreamAudioStats(usecTimestampNow()),
|
||||||
_isVSyncOn(true),
|
_isVSyncOn(true),
|
||||||
|
_isThrottleFPSEnabled(false),
|
||||||
_aboutToQuit(false),
|
_aboutToQuit(false),
|
||||||
_notifiedPacketVersionMismatchThisDomain(false),
|
_notifiedPacketVersionMismatchThisDomain(false),
|
||||||
_domainConnectionRefusals(QList<QString>()),
|
_domainConnectionRefusals(QList<QString>()),
|
||||||
|
@ -904,6 +905,11 @@ void Application::paintGL() {
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("renderOverlay");
|
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);
|
_applicationOverlay.renderOverlay(&renderArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2053,13 +2059,6 @@ void Application::setActiveFaceTracker() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::toggleFaceTrackerMute() {
|
|
||||||
FaceTracker* faceTracker = getSelectedFaceTracker();
|
|
||||||
if (faceTracker) {
|
|
||||||
faceTracker->toggleMute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Application::exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs) {
|
bool Application::exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs) {
|
||||||
QVector<EntityItemPointer> entities;
|
QVector<EntityItemPointer> entities;
|
||||||
|
|
||||||
|
@ -2498,7 +2497,13 @@ void Application::update(float deltaTime) {
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("devices");
|
PerformanceTimer perfTimer("devices");
|
||||||
DeviceTracker::updateAll();
|
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()) {
|
if (tracker && !tracker->isMuted()) {
|
||||||
tracker->update(deltaTime);
|
tracker->update(deltaTime);
|
||||||
|
|
||||||
|
@ -4612,6 +4617,10 @@ void Application::setVSyncEnabled() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::setThrottleFPSEnabled() {
|
||||||
|
_isThrottleFPSEnabled = Menu::getInstance()->isOptionChecked(MenuOption::ThrottleFPSIfNotFocus);
|
||||||
|
}
|
||||||
|
|
||||||
bool Application::isVSyncOn() const {
|
bool Application::isVSyncOn() const {
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
if (wglewGetExtension("WGL_EXT_swap_control")) {
|
if (wglewGetExtension("WGL_EXT_swap_control")) {
|
||||||
|
|
|
@ -356,9 +356,6 @@ signals:
|
||||||
/// Fired when we're rendering in-world interface elements; allows external parties to hook in.
|
/// Fired when we're rendering in-world interface elements; allows external parties to hook in.
|
||||||
void renderingInWorldInterface();
|
void renderingInWorldInterface();
|
||||||
|
|
||||||
/// Fired when we're rendering the overlay.
|
|
||||||
void renderingOverlay();
|
|
||||||
|
|
||||||
/// Fired when the import window is closed
|
/// Fired when the import window is closed
|
||||||
void importDone();
|
void importDone();
|
||||||
|
|
||||||
|
@ -420,10 +417,12 @@ public slots:
|
||||||
void domainSettingsReceived(const QJsonObject& domainSettingsObject);
|
void domainSettingsReceived(const QJsonObject& domainSettingsObject);
|
||||||
|
|
||||||
void setVSyncEnabled();
|
void setVSyncEnabled();
|
||||||
|
|
||||||
|
void setThrottleFPSEnabled();
|
||||||
|
bool isThrottleFPSEnabled() { return _isThrottleFPSEnabled; }
|
||||||
|
|
||||||
void resetSensors();
|
void resetSensors();
|
||||||
void setActiveFaceTracker();
|
void setActiveFaceTracker();
|
||||||
void toggleFaceTrackerMute();
|
|
||||||
|
|
||||||
void aboutApp();
|
void aboutApp();
|
||||||
void showEditEntitiesHelp();
|
void showEditEntitiesHelp();
|
||||||
|
@ -634,7 +633,8 @@ private:
|
||||||
quint64 _lastSendDownstreamAudioStats;
|
quint64 _lastSendDownstreamAudioStats;
|
||||||
|
|
||||||
bool _isVSyncOn;
|
bool _isVSyncOn;
|
||||||
|
bool _isThrottleFPSEnabled;
|
||||||
|
|
||||||
bool _aboutToQuit;
|
bool _aboutToQuit;
|
||||||
|
|
||||||
Bookmarks* _bookmarks;
|
Bookmarks* _bookmarks;
|
||||||
|
|
|
@ -35,7 +35,8 @@ void GLCanvas::stopFrameTimer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLCanvas::isThrottleRendering() const {
|
bool GLCanvas::isThrottleRendering() const {
|
||||||
return _throttleRendering || Application::getInstance()->getWindow()->isMinimized();
|
return (_throttleRendering
|
||||||
|
|| (Application::getInstance()->getWindow()->isMinimized() && Application::getInstance()->isThrottleFPSEnabled()));
|
||||||
}
|
}
|
||||||
|
|
||||||
int GLCanvas::getDeviceWidth() const {
|
int GLCanvas::getDeviceWidth() const {
|
||||||
|
@ -59,7 +60,8 @@ void GLCanvas::initializeGL() {
|
||||||
|
|
||||||
void GLCanvas::paintGL() {
|
void GLCanvas::paintGL() {
|
||||||
PROFILE_RANGE(__FUNCTION__);
|
PROFILE_RANGE(__FUNCTION__);
|
||||||
if (!_throttleRendering && !Application::getInstance()->getWindow()->isMinimized()) {
|
if (!_throttleRendering
|
||||||
|
&& (!Application::getInstance()->getWindow()->isMinimized()) || !Application::getInstance()->isThrottleFPSEnabled()) {
|
||||||
Application::getInstance()->paintGL();
|
Application::getInstance()->paintGL();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,7 +87,8 @@ void GLCanvas::activeChanged(Qt::ApplicationState state) {
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Otherwise, throttle.
|
// Otherwise, throttle.
|
||||||
if (!_throttleRendering && !Application::getInstance()->isAboutToQuit()) {
|
if (!_throttleRendering && !Application::getInstance()->isAboutToQuit()
|
||||||
|
&& Application::getInstance()->isThrottleFPSEnabled()) {
|
||||||
_frameTimer.start(_idleRenderInterval);
|
_frameTimer.start(_idleRenderInterval);
|
||||||
_throttleRendering = true;
|
_throttleRendering = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -373,6 +373,8 @@ Menu::Menu() {
|
||||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::RenderTargetFramerateVSyncOn, 0, true,
|
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::RenderTargetFramerateVSyncOn, 0, true,
|
||||||
qApp, SLOT(setVSyncEnabled()));
|
qApp, SLOT(setVSyncEnabled()));
|
||||||
#endif
|
#endif
|
||||||
|
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ThrottleFPSIfNotFocus, 0, false,
|
||||||
|
qApp, SLOT(setThrottleFPSEnabled()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -437,8 +439,7 @@ Menu::Menu() {
|
||||||
#if defined(HAVE_FACESHIFT) || defined(HAVE_DDE)
|
#if defined(HAVE_FACESHIFT) || defined(HAVE_DDE)
|
||||||
faceTrackingMenu->addSeparator();
|
faceTrackingMenu->addSeparator();
|
||||||
addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::MuteFaceTracking,
|
addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::MuteFaceTracking,
|
||||||
Qt::CTRL | Qt::SHIFT | Qt::Key_F, true, // DDE face tracking is on by default
|
Qt::CTRL | Qt::SHIFT | Qt::Key_F, true); // DDE face tracking is on by default
|
||||||
qApp, SLOT(toggleFaceTrackerMute()));
|
|
||||||
addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::AutoMuteAudio, 0, false);
|
addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::AutoMuteAudio, 0, false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -280,6 +280,7 @@ namespace MenuOption {
|
||||||
const QString SuppressShortTimings = "Suppress Timings Less than 10ms";
|
const QString SuppressShortTimings = "Suppress Timings Less than 10ms";
|
||||||
const QString TestPing = "Test Ping";
|
const QString TestPing = "Test Ping";
|
||||||
const QString ThirdPerson = "Third Person";
|
const QString ThirdPerson = "Third Person";
|
||||||
|
const QString ThrottleFPSIfNotFocus = "Throttle FPS If Not Focus";
|
||||||
const QString ToolWindow = "Tool Window";
|
const QString ToolWindow = "Tool Window";
|
||||||
const QString TransmitterDrive = "Transmitter Drive";
|
const QString TransmitterDrive = "Transmitter Drive";
|
||||||
const QString TurnWithHead = "Turn using Head";
|
const QString TurnWithHead = "Turn using Head";
|
||||||
|
|
|
@ -38,6 +38,7 @@ AudioScope::AudioScope() :
|
||||||
_scopeOutputLeft(NULL),
|
_scopeOutputLeft(NULL),
|
||||||
_scopeOutputRight(NULL),
|
_scopeOutputRight(NULL),
|
||||||
_scopeLastFrame(),
|
_scopeLastFrame(),
|
||||||
|
_audioScopeBackground(DependencyManager::get<GeometryCache>()->allocateID()),
|
||||||
_audioScopeGrid(DependencyManager::get<GeometryCache>()->allocateID()),
|
_audioScopeGrid(DependencyManager::get<GeometryCache>()->allocateID()),
|
||||||
_inputID(DependencyManager::get<GeometryCache>()->allocateID()),
|
_inputID(DependencyManager::get<GeometryCache>()->allocateID()),
|
||||||
_outputLeftID(DependencyManager::get<GeometryCache>()->allocateID()),
|
_outputLeftID(DependencyManager::get<GeometryCache>()->allocateID()),
|
||||||
|
@ -126,22 +127,24 @@ void AudioScope::render(RenderArgs* renderArgs, int width, int height) {
|
||||||
int w = (int)SCOPE_WIDTH;
|
int w = (int)SCOPE_WIDTH;
|
||||||
int h = (int)SCOPE_HEIGHT;
|
int h = (int)SCOPE_HEIGHT;
|
||||||
|
|
||||||
gpu::Batch batch;
|
gpu::Batch& batch = *renderArgs->_batch;
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
geometryCache->useSimpleDrawPipeline(batch);
|
geometryCache->useSimpleDrawPipeline(batch);
|
||||||
auto textureCache = DependencyManager::get<TextureCache>();
|
auto textureCache = DependencyManager::get<TextureCache>();
|
||||||
batch.setResourceTexture(0, textureCache->getWhiteTexture());
|
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<float>(0, width, height, 0, -1000, 1000);
|
mat4 legacyProjection = glm::ortho<float>(0, width, height, 0, -1000, 1000);
|
||||||
batch.setProjectionTransform(legacyProjection);
|
batch.setProjectionTransform(legacyProjection);
|
||||||
batch.setModelTransform(Transform());
|
batch.setModelTransform(Transform());
|
||||||
batch.setViewTransform(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);
|
geometryCache->renderGrid(batch, x, y, w, h, gridRows, gridCols, gridColor, _audioScopeGrid);
|
||||||
renderLineStrip(batch, _inputID, inputColor, x, y, _samplesPerScope, _scopeInputOffset, _scopeInput);
|
renderLineStrip(batch, _inputID, inputColor, x, y, _samplesPerScope, _scopeInputOffset, _scopeInput);
|
||||||
renderLineStrip(batch, _outputLeftID, outputLeftColor, x, y, _samplesPerScope, _scopeOutputOffset, _scopeOutputLeft);
|
renderLineStrip(batch, _outputLeftID, outputLeftColor, x, y, _samplesPerScope, _scopeOutputOffset, _scopeOutputLeft);
|
||||||
renderLineStrip(batch, _outputRightD, outputRightColor, x, y, _samplesPerScope, _scopeOutputOffset, _scopeOutputRight);
|
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) {
|
void AudioScope::renderLineStrip(gpu::Batch& batch, int id, const glm::vec4& color, int x, int y, int n, int offset, const QByteArray* byteArray) {
|
||||||
|
|
|
@ -69,6 +69,7 @@ private:
|
||||||
QByteArray* _scopeOutputRight;
|
QByteArray* _scopeOutputRight;
|
||||||
QByteArray _scopeLastFrame;
|
QByteArray _scopeLastFrame;
|
||||||
|
|
||||||
|
int _audioScopeBackground;
|
||||||
int _audioScopeGrid;
|
int _audioScopeGrid;
|
||||||
int _inputID;
|
int _inputID;
|
||||||
int _outputLeftID;
|
int _outputLeftID;
|
||||||
|
|
|
@ -189,8 +189,8 @@ void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint texture = qApp->getApplicationOverlay().getOverlayTexture();
|
gpu::FramebufferPointer overlayFramebuffer = qApp->getApplicationOverlay().getOverlayFramebuffer();
|
||||||
if (!texture) {
|
if (!overlayFramebuffer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,9 +209,7 @@ void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) {
|
||||||
batch.setModelTransform(Transform());
|
batch.setModelTransform(Transform());
|
||||||
batch.setViewTransform(Transform());
|
batch.setViewTransform(Transform());
|
||||||
batch.setProjectionTransform(mat4());
|
batch.setProjectionTransform(mat4());
|
||||||
batch._glBindTexture(GL_TEXTURE_2D, texture);
|
batch.setResourceTexture(0, overlayFramebuffer->getRenderBuffer(0));
|
||||||
batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
geometryCache->renderUnitQuad(batch, vec4(vec3(1), _alpha));
|
geometryCache->renderUnitQuad(batch, vec4(vec3(1), _alpha));
|
||||||
|
|
||||||
// Doesn't actually render
|
// Doesn't actually render
|
||||||
|
@ -258,8 +256,8 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint texture = qApp->getApplicationOverlay().getOverlayTexture();
|
gpu::FramebufferPointer overlayFramebuffer = qApp->getApplicationOverlay().getOverlayFramebuffer();
|
||||||
if (!texture) {
|
if (!overlayFramebuffer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,9 +273,12 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int
|
||||||
geometryCache->useSimpleDrawPipeline(batch);
|
geometryCache->useSimpleDrawPipeline(batch);
|
||||||
batch._glDisable(GL_DEPTH_TEST);
|
batch._glDisable(GL_DEPTH_TEST);
|
||||||
batch._glDisable(GL_CULL_FACE);
|
batch._glDisable(GL_CULL_FACE);
|
||||||
batch._glBindTexture(GL_TEXTURE_2D, texture);
|
//batch._glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
//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_MIN_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
batch.setResourceTexture(0, overlayFramebuffer->getRenderBuffer(0));
|
||||||
|
|
||||||
batch.setViewTransform(Transform());
|
batch.setViewTransform(Transform());
|
||||||
batch.setProjectionTransform(qApp->getEyeProjection(eye));
|
batch.setProjectionTransform(qApp->getEyeProjection(eye));
|
||||||
|
|
||||||
|
|
|
@ -40,12 +40,6 @@ const float CONNECTION_STATUS_BORDER_LINE_WIDTH = 4.0f;
|
||||||
static const float ORTHO_NEAR_CLIP = -10000;
|
static const float ORTHO_NEAR_CLIP = -10000;
|
||||||
static const float ORTHO_FAR_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()
|
ApplicationOverlay::ApplicationOverlay()
|
||||||
{
|
{
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
|
@ -82,63 +76,97 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) {
|
||||||
AvatarInputs::getInstance()->update();
|
AvatarInputs::getInstance()->update();
|
||||||
|
|
||||||
buildFramebufferObject();
|
buildFramebufferObject();
|
||||||
|
|
||||||
|
if (!_overlayFramebuffer) {
|
||||||
|
return; // we can't do anything without our frame buffer.
|
||||||
|
}
|
||||||
|
|
||||||
// Execute the batch into our framebuffer
|
// Execute the batch into our framebuffer
|
||||||
_overlayFramebuffer->bind();
|
gpu::Batch batch;
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
renderArgs->_batch = &batch;
|
||||||
fboViewport(_overlayFramebuffer);
|
|
||||||
|
int width = _overlayFramebuffer->getWidth();
|
||||||
|
int height = _overlayFramebuffer->getHeight();
|
||||||
|
|
||||||
|
batch.setViewportTransform(glm::ivec4(0, 0, width, height));
|
||||||
|
batch.setFramebuffer(_overlayFramebuffer);
|
||||||
|
|
||||||
|
glm::vec4 color { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
float depth = 1.0f;
|
||||||
|
int stencil = 0;
|
||||||
|
batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH, color, depth, stencil);
|
||||||
|
|
||||||
// Now render the overlay components together into a single texture
|
// Now render the overlay components together into a single texture
|
||||||
renderOverlays(renderArgs);
|
renderDomainConnectionStatusBorder(renderArgs); // renders the connected domain line
|
||||||
renderStatsAndLogs(renderArgs);
|
renderAudioScope(renderArgs); // audio scope in the very back
|
||||||
renderDomainConnectionStatusBorder(renderArgs);
|
renderQmlUi(renderArgs); // renders a unit quad with the QML UI texture, and the text overlays from scripts
|
||||||
renderQmlUi(renderArgs);
|
renderOverlays(renderArgs); // renders Scripts Overlay and AudioScope
|
||||||
_overlayFramebuffer->release();
|
renderStatsAndLogs(renderArgs); // currently renders nothing
|
||||||
|
|
||||||
|
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();
|
CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) {
|
void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) {
|
||||||
PROFILE_RANGE(__FUNCTION__);
|
PROFILE_RANGE(__FUNCTION__);
|
||||||
if (_uiTexture) {
|
if (_uiTexture) {
|
||||||
gpu::Batch batch;
|
gpu::Batch& batch = *renderArgs->_batch;
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
|
|
||||||
geometryCache->useSimpleDrawPipeline(batch);
|
geometryCache->useSimpleDrawPipeline(batch);
|
||||||
batch.setProjectionTransform(mat4());
|
batch.setProjectionTransform(mat4());
|
||||||
batch.setModelTransform(mat4());
|
batch.setModelTransform(Transform());
|
||||||
|
batch.setViewTransform(Transform());
|
||||||
batch._glBindTexture(GL_TEXTURE_2D, _uiTexture);
|
batch._glBindTexture(GL_TEXTURE_2D, _uiTexture);
|
||||||
|
|
||||||
geometryCache->renderUnitQuad(batch, glm::vec4(1));
|
geometryCache->renderUnitQuad(batch, glm::vec4(1));
|
||||||
renderArgs->_context->syncCache();
|
|
||||||
renderArgs->_context->render(batch);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ApplicationOverlay::renderAudioScope(RenderArgs* renderArgs) {
|
||||||
|
PROFILE_RANGE(__FUNCTION__);
|
||||||
|
|
||||||
|
gpu::Batch& batch = *renderArgs->_batch;
|
||||||
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
|
geometryCache->useSimpleDrawPipeline(batch);
|
||||||
|
auto textureCache = DependencyManager::get<TextureCache>();
|
||||||
|
batch.setResourceTexture(0, textureCache->getWhiteTexture());
|
||||||
|
int width = renderArgs->_viewport.z;
|
||||||
|
int height = renderArgs->_viewport.w;
|
||||||
|
mat4 legacyProjection = glm::ortho<float>(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<AudioScope>()->render(renderArgs, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
void ApplicationOverlay::renderOverlays(RenderArgs* renderArgs) {
|
void ApplicationOverlay::renderOverlays(RenderArgs* renderArgs) {
|
||||||
PROFILE_RANGE(__FUNCTION__);
|
PROFILE_RANGE(__FUNCTION__);
|
||||||
glm::vec2 size = qApp->getCanvasSize();
|
|
||||||
|
|
||||||
mat4 legacyProjection = glm::ortho<float>(0, size.x, size.y, 0, ORTHO_NEAR_CLIP, ORTHO_FAR_CLIP);
|
gpu::Batch& batch = *renderArgs->_batch;
|
||||||
glMatrixMode(GL_PROJECTION);
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
glPushMatrix();
|
geometryCache->useSimpleDrawPipeline(batch);
|
||||||
glLoadMatrixf(glm::value_ptr(legacyProjection));
|
auto textureCache = DependencyManager::get<TextureCache>();
|
||||||
glMatrixMode(GL_MODELVIEW);
|
batch.setResourceTexture(0, textureCache->getWhiteTexture());
|
||||||
|
int width = renderArgs->_viewport.z;
|
||||||
glDisable(GL_DEPTH_TEST);
|
int height = renderArgs->_viewport.w;
|
||||||
glDisable(GL_LIGHTING);
|
mat4 legacyProjection = glm::ortho<float>(0, width, height, 0, -1000, 1000);
|
||||||
glEnable(GL_BLEND);
|
batch.setProjectionTransform(legacyProjection);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
batch.setModelTransform(Transform());
|
||||||
glUseProgram(0);
|
batch.setViewTransform(Transform());
|
||||||
|
batch._glLineWidth(1.0f); // default
|
||||||
// give external parties a change to hook in
|
|
||||||
emit qApp->renderingOverlay();
|
// 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);
|
qApp->getOverlays().renderHUD(renderArgs);
|
||||||
|
|
||||||
DependencyManager::get<AudioScope>()->render(renderArgs, _overlayFramebuffer->size().width(), _overlayFramebuffer->size().height());
|
|
||||||
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glPopMatrix();
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
|
|
||||||
fboViewport(_overlayFramebuffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplicationOverlay::renderRearViewToFbo(RenderArgs* renderArgs) {
|
void ApplicationOverlay::renderRearViewToFbo(RenderArgs* renderArgs) {
|
||||||
|
@ -183,7 +211,7 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder(RenderArgs* renderAr
|
||||||
});
|
});
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
if (nodeList && !nodeList->getDomainHandler().isConnected()) {
|
if (nodeList && !nodeList->getDomainHandler().isConnected()) {
|
||||||
gpu::Batch batch;
|
gpu::Batch& batch = *renderArgs->_batch;
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
geometryCache->useSimpleDrawPipeline(batch);
|
geometryCache->useSimpleDrawPipeline(batch);
|
||||||
batch.setProjectionTransform(mat4());
|
batch.setProjectionTransform(mat4());
|
||||||
|
@ -198,37 +226,40 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder(RenderArgs* renderAr
|
||||||
//batch.setModelTransform(glm::scale(mat4(), vec3(scaleAmount)));
|
//batch.setModelTransform(glm::scale(mat4(), vec3(scaleAmount)));
|
||||||
|
|
||||||
geometryCache->renderVertices(batch, gpu::LINE_STRIP, _domainStatusBorder);
|
geometryCache->renderVertices(batch, gpu::LINE_STRIP, _domainStatusBorder);
|
||||||
renderArgs->_context->syncCache();
|
|
||||||
renderArgs->_context->render(batch);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint ApplicationOverlay::getOverlayTexture() {
|
|
||||||
if (!_overlayFramebuffer) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return _overlayFramebuffer->texture();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ApplicationOverlay::buildFramebufferObject() {
|
void ApplicationOverlay::buildFramebufferObject() {
|
||||||
PROFILE_RANGE(__FUNCTION__);
|
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
|
// Already built
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_overlayFramebuffer) {
|
if (_overlayFramebuffer) {
|
||||||
delete _overlayFramebuffer;
|
_overlayFramebuffer.reset();
|
||||||
|
_overlayDepthTexture.reset();
|
||||||
|
_overlayColorTexture.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
_overlayFramebuffer = new QOpenGLFramebufferObject(fboSize, QOpenGLFramebufferObject::Depth);
|
_overlayFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
|
||||||
glBindTexture(GL_TEXTURE_2D, getOverlayTexture());
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
auto colorFormat = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
auto width = desiredSize.width();
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
auto height = desiredSize.height();
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
|
||||||
GLfloat borderColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR);
|
||||||
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
|
_overlayColorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width, height, defaultSampler));
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
_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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,8 @@ public:
|
||||||
~ApplicationOverlay();
|
~ApplicationOverlay();
|
||||||
|
|
||||||
void renderOverlay(RenderArgs* renderArgs);
|
void renderOverlay(RenderArgs* renderArgs);
|
||||||
GLuint getOverlayTexture();
|
|
||||||
|
gpu::FramebufferPointer getOverlayFramebuffer() const { return _overlayFramebuffer; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void renderStatsAndLogs(RenderArgs* renderArgs);
|
void renderStatsAndLogs(RenderArgs* renderArgs);
|
||||||
|
@ -33,6 +34,7 @@ private:
|
||||||
void renderRearViewToFbo(RenderArgs* renderArgs);
|
void renderRearViewToFbo(RenderArgs* renderArgs);
|
||||||
void renderRearView(RenderArgs* renderArgs);
|
void renderRearView(RenderArgs* renderArgs);
|
||||||
void renderQmlUi(RenderArgs* renderArgs);
|
void renderQmlUi(RenderArgs* renderArgs);
|
||||||
|
void renderAudioScope(RenderArgs* renderArgs);
|
||||||
void renderOverlays(RenderArgs* renderArgs);
|
void renderOverlays(RenderArgs* renderArgs);
|
||||||
void buildFramebufferObject();
|
void buildFramebufferObject();
|
||||||
|
|
||||||
|
@ -44,7 +46,11 @@ private:
|
||||||
int _magnifierBorder;
|
int _magnifierBorder;
|
||||||
|
|
||||||
ivec2 _previousBorderSize{ -1 };
|
ivec2 _previousBorderSize{ -1 };
|
||||||
QOpenGLFramebufferObject* _overlayFramebuffer{ nullptr };
|
|
||||||
|
gpu::TexturePointer _overlayDepthTexture;
|
||||||
|
gpu::TexturePointer _overlayColorTexture;
|
||||||
|
gpu::FramebufferPointer _overlayFramebuffer;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_ApplicationOverlay_h
|
#endif // hifi_ApplicationOverlay_h
|
||||||
|
|
|
@ -98,16 +98,29 @@ void Overlays::cleanupOverlaysToDelete() {
|
||||||
void Overlays::renderHUD(RenderArgs* renderArgs) {
|
void Overlays::renderHUD(RenderArgs* renderArgs) {
|
||||||
PROFILE_RANGE(__FUNCTION__);
|
PROFILE_RANGE(__FUNCTION__);
|
||||||
QReadLocker lock(&_lock);
|
QReadLocker lock(&_lock);
|
||||||
gpu::Batch batch;
|
gpu::Batch& batch = *renderArgs->_batch;
|
||||||
renderArgs->_batch = &batch;
|
|
||||||
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
|
auto textureCache = DependencyManager::get<TextureCache>();
|
||||||
|
|
||||||
|
auto size = qApp->getCanvasSize();
|
||||||
|
int width = size.x;
|
||||||
|
int height = size.y;
|
||||||
|
mat4 legacyProjection = glm::ortho<float>(0, width, height, 0, -1000, 1000);
|
||||||
|
|
||||||
|
|
||||||
foreach(Overlay::Pointer thisOverlay, _overlaysHUD) {
|
foreach(Overlay::Pointer thisOverlay, _overlaysHUD) {
|
||||||
|
|
||||||
|
// Reset all batch pipeline settings between overlay
|
||||||
|
geometryCache->useSimpleDrawPipeline(batch);
|
||||||
|
batch.setResourceTexture(0, textureCache->getWhiteTexture()); // FIXME - do we really need to do this??
|
||||||
|
batch.setProjectionTransform(legacyProjection);
|
||||||
|
batch.setModelTransform(Transform());
|
||||||
|
batch.setViewTransform(Transform());
|
||||||
|
batch._glLineWidth(1.0f); // default
|
||||||
|
|
||||||
thisOverlay->render(renderArgs);
|
thisOverlay->render(renderArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderArgs->_context->syncCache();
|
|
||||||
renderArgs->_context->render(batch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& properties) {
|
unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& properties) {
|
||||||
|
|
|
@ -102,9 +102,10 @@ void Batch::drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, ui
|
||||||
_params.push_back(nbInstances);
|
_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);
|
ADD_COMMAND(clearFramebuffer);
|
||||||
|
|
||||||
|
_params.push_back(enableScissor);
|
||||||
_params.push_back(stencil);
|
_params.push_back(stencil);
|
||||||
_params.push_back(depth);
|
_params.push_back(depth);
|
||||||
_params.push_back(color.w);
|
_params.push_back(color.w);
|
||||||
|
@ -114,20 +115,20 @@ void Batch::clearFramebuffer(Framebuffer::Masks targets, const Vec4& color, floa
|
||||||
_params.push_back(targets);
|
_params.push_back(targets);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::clearColorFramebuffer(Framebuffer::Masks targets, const Vec4& color) {
|
void Batch::clearColorFramebuffer(Framebuffer::Masks targets, const Vec4& color, bool enableScissor) {
|
||||||
clearFramebuffer(targets & Framebuffer::BUFFER_COLORS, color, 1.0f, 0);
|
clearFramebuffer(targets & Framebuffer::BUFFER_COLORS, color, 1.0f, 0, enableScissor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::clearDepthFramebuffer(float depth) {
|
void Batch::clearDepthFramebuffer(float depth, bool enableScissor) {
|
||||||
clearFramebuffer(Framebuffer::BUFFER_DEPTH, Vec4(0.0f), depth, 0);
|
clearFramebuffer(Framebuffer::BUFFER_DEPTH, Vec4(0.0f), depth, 0, enableScissor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::clearStencilFramebuffer(int stencil) {
|
void Batch::clearStencilFramebuffer(int stencil, bool enableScissor) {
|
||||||
clearFramebuffer(Framebuffer::BUFFER_STENCIL, Vec4(0.0f), 1.0f, stencil);
|
clearFramebuffer(Framebuffer::BUFFER_STENCIL, Vec4(0.0f), 1.0f, stencil, enableScissor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Batch::clearDepthStencilFramebuffer(float depth, int stencil) {
|
void Batch::clearDepthStencilFramebuffer(float depth, int stencil, bool enableScissor) {
|
||||||
clearFramebuffer(Framebuffer::BUFFER_DEPTHSTENCIL, Vec4(0.0f), depth, stencil);
|
clearFramebuffer(Framebuffer::BUFFER_DEPTHSTENCIL, Vec4(0.0f), depth, stencil, enableScissor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -212,6 +213,14 @@ void Batch::setStateBlendFactor(const Vec4& factor) {
|
||||||
_params.push_back(factor.w);
|
_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) {
|
void Batch::setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size) {
|
||||||
ADD_COMMAND(setUniformBuffer);
|
ADD_COMMAND(setUniformBuffer);
|
||||||
|
|
|
@ -62,11 +62,12 @@ public:
|
||||||
|
|
||||||
// Clear framebuffer layers
|
// Clear framebuffer layers
|
||||||
// Targets can be any of the render buffers contained in the Framebuffer
|
// Targets can be any of the render buffers contained in the Framebuffer
|
||||||
void clearFramebuffer(Framebuffer::Masks targets, const Vec4& color, float depth, int stencil);
|
// 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 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 clearFramebuffer(Framebuffer::Masks targets, const Vec4& color, float depth, int stencil, bool enableScissor = false);
|
||||||
void clearDepthFramebuffer(float depth); // not a command, just a shortcut for clearFramebuffer, it touches only depth target
|
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 clearStencilFramebuffer(int stencil); // not a command, just a shortcut for clearFramebuffer, it touches only stencil target
|
void clearDepthFramebuffer(float depth, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, it touches only depth target
|
||||||
void clearDepthStencilFramebuffer(float depth, int stencil); // not a command, just a shortcut for clearFramebuffer, it touches depth and stencil 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
|
// Input Stage
|
||||||
// InputFormat
|
// InputFormat
|
||||||
|
@ -90,13 +91,18 @@ public:
|
||||||
void setModelTransform(const Transform& model);
|
void setModelTransform(const Transform& model);
|
||||||
void setViewTransform(const Transform& view);
|
void setViewTransform(const Transform& view);
|
||||||
void setProjectionTransform(const Mat4& proj);
|
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
|
// Pipeline Stage
|
||||||
void setPipeline(const PipelinePointer& pipeline);
|
void setPipeline(const PipelinePointer& pipeline);
|
||||||
|
|
||||||
void setStateBlendFactor(const Vec4& factor);
|
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 BufferPointer& buffer, Offset offset, Offset size);
|
||||||
void setUniformBuffer(uint32 slot, const BufferView& view); // not a command, just a shortcut from a BufferView
|
void setUniformBuffer(uint32 slot, const BufferView& view); // not a command, just a shortcut from a BufferView
|
||||||
|
|
||||||
|
@ -173,6 +179,7 @@ public:
|
||||||
|
|
||||||
COMMAND_setPipeline,
|
COMMAND_setPipeline,
|
||||||
COMMAND_setStateBlendFactor,
|
COMMAND_setStateBlendFactor,
|
||||||
|
COMMAND_setStateScissorRect,
|
||||||
|
|
||||||
COMMAND_setUniformBuffer,
|
COMMAND_setUniformBuffer,
|
||||||
COMMAND_setResourceTexture,
|
COMMAND_setResourceTexture,
|
||||||
|
|
|
@ -33,6 +33,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
|
||||||
|
|
||||||
(&::gpu::GLBackend::do_setPipeline),
|
(&::gpu::GLBackend::do_setPipeline),
|
||||||
(&::gpu::GLBackend::do_setStateBlendFactor),
|
(&::gpu::GLBackend::do_setStateBlendFactor),
|
||||||
|
(&::gpu::GLBackend::do_setStateScissorRect),
|
||||||
|
|
||||||
(&::gpu::GLBackend::do_setUniformBuffer),
|
(&::gpu::GLBackend::do_setUniformBuffer),
|
||||||
(&::gpu::GLBackend::do_setResourceTexture),
|
(&::gpu::GLBackend::do_setResourceTexture),
|
||||||
|
@ -217,17 +218,18 @@ void GLBackend::do_drawIndexedInstanced(Batch& batch, uint32 paramOffset) {
|
||||||
|
|
||||||
void GLBackend::do_clearFramebuffer(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;
|
Vec4 color;
|
||||||
color.x = batch._params[paramOffset + 5]._float;
|
color.x = batch._params[paramOffset + 6]._float;
|
||||||
color.y = batch._params[paramOffset + 4]._float;
|
color.y = batch._params[paramOffset + 5]._float;
|
||||||
color.z = batch._params[paramOffset + 3]._float;
|
color.z = batch._params[paramOffset + 4]._float;
|
||||||
color.w = batch._params[paramOffset + 2]._float;
|
color.w = batch._params[paramOffset + 3]._float;
|
||||||
float depth = batch._params[paramOffset + 1]._float;
|
float depth = batch._params[paramOffset + 2]._float;
|
||||||
int stencil = batch._params[paramOffset + 0]._float;
|
int stencil = batch._params[paramOffset + 1]._int;
|
||||||
|
int useScissor = batch._params[paramOffset + 0]._int;
|
||||||
|
|
||||||
GLuint glmask = 0;
|
GLuint glmask = 0;
|
||||||
if (masks & Framebuffer::BUFFER_DEPTH) {
|
if (masks & Framebuffer::BUFFER_STENCIL) {
|
||||||
glClearStencil(stencil);
|
glClearStencil(stencil);
|
||||||
glmask |= GL_STENCIL_BUFFER_BIT;
|
glmask |= GL_STENCIL_BUFFER_BIT;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
glClear(glmask);
|
||||||
|
|
||||||
|
// Restore scissor if needed
|
||||||
|
if (doEnableScissor) {
|
||||||
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
}
|
||||||
|
|
||||||
// Restore the color draw buffers only if a frmaebuffer is bound
|
// Restore the color draw buffers only if a frmaebuffer is bound
|
||||||
if (_output._framebuffer && !drawBuffers.empty()) {
|
if (_output._framebuffer && !drawBuffers.empty()) {
|
||||||
auto glFramebuffer = syncGPUObject(*_output._framebuffer);
|
auto glFramebuffer = syncGPUObject(*_output._framebuffer);
|
||||||
|
|
|
@ -350,6 +350,7 @@ protected:
|
||||||
// Pipeline Stage
|
// Pipeline Stage
|
||||||
void do_setPipeline(Batch& batch, uint32 paramOffset);
|
void do_setPipeline(Batch& batch, uint32 paramOffset);
|
||||||
void do_setStateBlendFactor(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
|
// Standard update pipeline check that the current Program and current State or good to go for a
|
||||||
void updatePipeline();
|
void updatePipeline();
|
||||||
|
|
|
@ -753,3 +753,14 @@ void GLBackend::do_setStateBlendFactor(Batch& batch, uint32 paramOffset) {
|
||||||
glBlendColor(factor.x, factor.y, factor.z, factor.w);
|
glBlendColor(factor.x, factor.y, factor.z, factor.w);
|
||||||
(void) CHECK_GL_ERROR();
|
(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();
|
||||||
|
}
|
||||||
|
|
|
@ -392,7 +392,6 @@ void GeometryCache::renderGrid(int x, int y, int width, int height, int rows, in
|
||||||
gpu::GLBackend::renderBatch(batch);
|
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??
|
// 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) {
|
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
|
#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));
|
Vec3Pair colorKey(glm::vec3(color.x, color.y, rows), glm::vec3(color.z, color.y, cols));
|
||||||
|
|
||||||
int vertices = (cols + 1 + rows + 1) * 2;
|
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());
|
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* vertexData = new GLfloat[vertices * 2];
|
||||||
GLfloat* vertex = vertexData;
|
GLfloat* vertex = vertexData;
|
||||||
|
@ -433,6 +447,8 @@ void GeometryCache::renderGrid(gpu::Batch& batch, int x, int y, int width, int h
|
||||||
}
|
}
|
||||||
// Draw vertical grid lines
|
// Draw vertical grid lines
|
||||||
for (int i = cols + 1; --i >= 0; ) {
|
for (int i = cols + 1; --i >= 0; ) {
|
||||||
|
//glVertex2i(tx, y);
|
||||||
|
//glVertex2i(tx, y + height);
|
||||||
*(vertex++) = tx;
|
*(vertex++) = tx;
|
||||||
*(vertex++) = y;
|
*(vertex++) = y;
|
||||||
|
|
||||||
|
@ -443,12 +459,6 @@ void GeometryCache::renderGrid(gpu::Batch& batch, int x, int y, int width, int h
|
||||||
|
|
||||||
verticesBuffer->append(sizeof(GLfloat) * vertices * 2, (gpu::Byte*) vertexData);
|
verticesBuffer->append(sizeof(GLfloat) * vertices * 2, (gpu::Byte*) vertexData);
|
||||||
delete[] vertexData;
|
delete[] vertexData;
|
||||||
|
|
||||||
if (registered) {
|
|
||||||
_registeredAlternateGridBuffers[id] = verticesBuffer;
|
|
||||||
} else {
|
|
||||||
_alternateGridBuffers[key] = verticesBuffer;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_gridColors.contains(colorKey)) {
|
if (!_gridColors.contains(colorKey)) {
|
||||||
|
|
|
@ -337,8 +337,9 @@ private:
|
||||||
QHash<int, BatchItemDetails> _registeredDashedLines;
|
QHash<int, BatchItemDetails> _registeredDashedLines;
|
||||||
|
|
||||||
QHash<IntPair, gpu::BufferPointer> _gridBuffers;
|
QHash<IntPair, gpu::BufferPointer> _gridBuffers;
|
||||||
QHash<int, gpu::BufferPointer> _registeredAlternateGridBuffers;
|
|
||||||
QHash<Vec3Pair, gpu::BufferPointer> _alternateGridBuffers;
|
QHash<Vec3Pair, gpu::BufferPointer> _alternateGridBuffers;
|
||||||
|
QHash<int, gpu::BufferPointer> _registeredAlternateGridBuffers;
|
||||||
|
QHash<int, Vec3Pair> _lastRegisteredAlternateGridBuffers;
|
||||||
QHash<Vec3Pair, gpu::BufferPointer> _gridColors;
|
QHash<Vec3Pair, gpu::BufferPointer> _gridColors;
|
||||||
|
|
||||||
QHash<Vec2Pair, gpu::BufferPointer> _sphereVertices;
|
QHash<Vec2Pair, gpu::BufferPointer> _sphereVertices;
|
||||||
|
|
Loading…
Reference in a new issue