3
0
Fork 0
mirror of https://github.com/lubosz/overte.git synced 2025-04-27 11:55:25 +02:00

Merge branch 'plugins' of github.com:highfidelity/hifi into sam/vive-hand-controllers

Conflicts:
	interface/src/Application.cpp
	libraries/input-plugins/src/input-plugins/SixenseManager.cpp
This commit is contained in:
Anthony J. Thibault 2015-07-20 15:18:23 -07:00
commit 80dea6831c
165 changed files with 2826 additions and 4520 deletions
examples
interface
libraries

265
examples/FlockOfbirds.js Normal file
View file

@ -0,0 +1,265 @@
//
// flockOfbirds.js
// examples
//
// Copyright 2014 High Fidelity, Inc.
// Creates a flock of birds that fly around and chirp, staying inside the corners of the box defined
// at the start of the script.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// The area over which the birds will fly
var lowerCorner = { x: 1, y: 1, z: 1 };
var upperCorner = { x: 10, y: 10, z: 10 };
var STARTING_FRACTION = 0.25;
var NUM_BIRDS = 50;
var playSounds = true;
var SOUND_PROBABILITY = 0.001;
var numPlaying = 0;
var BIRD_SIZE = 0.08;
var BIRD_MASTER_VOLUME = 0.1;
var FLAP_PROBABILITY = 0.005;
var RANDOM_FLAP_VELOCITY = 1.0;
var FLAP_UP = 1.0;
var BIRD_GRAVITY = -0.5;
var LINEAR_DAMPING = 0.2;
var FLAP_FALLING_PROBABILITY = 0.025;
var MIN_ALIGNMENT_VELOCITY = 0.0;
var MAX_ALIGNMENT_VELOCITY = 1.0;
var VERTICAL_ALIGNMENT_COUPLING = 0.0;
var ALIGNMENT_FORCE = 1.5;
var COHESION_FORCE = 1.0;
var MAX_COHESION_VELOCITY = 0.5;
var floor = false;
var MAKE_FLOOR = false;
var averageVelocity = { x: 0, y: 0, z: 0 };
var averagePosition = { x: 0, y: 0, z: 0 };
var birdsLoaded = false;
var birds = [];
var playing = [];
function randomVector(scale) {
return { x: Math.random() * scale - scale / 2.0, y: Math.random() * scale - scale / 2.0, z: Math.random() * scale - scale / 2.0 };
}
function updateBirds(deltaTime) {
if (!Entities.serversExist() || !Entities.canRez()) {
return;
}
if (!birdsLoaded) {
loadBirds(NUM_BIRDS);
birdsLoaded = true;
return;
}
var sumVelocity = { x: 0, y: 0, z: 0 };
var sumPosition = { x: 0, y: 0, z: 0 };
var birdPositionsCounted = 0;
var birdVelocitiesCounted = 0;
for (var i = 0; i < birds.length; i++) {
if (birds[i].entityId) {
var properties = Entities.getEntityProperties(birds[i].entityId);
// If Bird has been deleted, bail
if (properties.id != birds[i].entityId) {
birds[i].entityId = false;
return;
}
// Sum up average position and velocity
if (Vec3.length(properties.velocity) > MIN_ALIGNMENT_VELOCITY) {
sumVelocity = Vec3.sum(sumVelocity, properties.velocity);
birdVelocitiesCounted += 1;
}
sumPosition = Vec3.sum(sumPosition, properties.position);
birdPositionsCounted += 1;
var downwardSpeed = (properties.velocity.y < 0) ? -properties.velocity.y : 0.0;
if ((properties.position.y < upperCorner.y) && (Math.random() < (FLAP_PROBABILITY + (downwardSpeed * FLAP_FALLING_PROBABILITY)))) {
// More likely to flap if falling
var randomVelocity = randomVector(RANDOM_FLAP_VELOCITY);
randomVelocity.y = FLAP_UP + Math.random() * FLAP_UP;
// Alignment Velocity
var alignmentVelocityMagnitude = Math.min(MAX_ALIGNMENT_VELOCITY, Vec3.length(Vec3.multiply(ALIGNMENT_FORCE, averageVelocity)));
var alignmentVelocity = Vec3.multiply(alignmentVelocityMagnitude, Vec3.normalize(averageVelocity));
alignmentVelocity.y *= VERTICAL_ALIGNMENT_COUPLING;
// Cohesion
var distanceFromCenter = Vec3.length(Vec3.subtract(averagePosition, properties.position));
var cohesionVelocitySize = Math.min(distanceFromCenter * COHESION_FORCE, MAX_COHESION_VELOCITY);
var cohesionVelocity = Vec3.multiply(cohesionVelocitySize, Vec3.normalize(Vec3.subtract(averagePosition, properties.position)));
var newVelocity = Vec3.sum(randomVelocity, Vec3.sum(alignmentVelocity, cohesionVelocity));
Entities.editEntity(birds[i].entityId, { velocity: Vec3.sum(properties.velocity, newVelocity) });
}
// Check whether to play a chirp
if (playSounds && (!birds[i].audioId || !birds[i].audioId.isPlaying) && (Math.random() < ((numPlaying > 0) ? SOUND_PROBABILITY / numPlaying : SOUND_PROBABILITY))) {
var options = {
position: properties.position,
volume: BIRD_MASTER_VOLUME
};
// Play chirp
if (birds[i].audioId) {
birds[i].audioId.setOptions(options);
birds[i].audioId.restart();
} else {
birds[i].audioId = Audio.playSound(birds[i].sound, options);
}
numPlaying++;
// Change size
Entities.editEntity(birds[i].entityId, { dimensions: Vec3.multiply(1.5, properties.dimensions)});
} else if (birds[i].audioId) {
// If bird is playing a chirp
if (!birds[i].audioId.isPlaying) {
Entities.editEntity(birds[i].entityId, { dimensions: { x: BIRD_SIZE, y: BIRD_SIZE, z: BIRD_SIZE }});
numPlaying--;
}
}
// Keep birds in their 'cage'
var bounce = false;
var newVelocity = properties.velocity;
var newPosition = properties.position;
if (properties.position.x < lowerCorner.x) {
newPosition.x = lowerCorner.x;
newVelocity.x *= -1.0;
bounce = true;
} else if (properties.position.x > upperCorner.x) {
newPosition.x = upperCorner.x;
newVelocity.x *= -1.0;
bounce = true;
}
if (properties.position.y < lowerCorner.y) {
newPosition.y = lowerCorner.y;
newVelocity.y *= -1.0;
bounce = true;
} else if (properties.position.y > upperCorner.y) {
newPosition.y = upperCorner.y;
newVelocity.y *= -1.0;
bounce = true;
}
if (properties.position.z < lowerCorner.z) {
newPosition.z = lowerCorner.z;
newVelocity.z *= -1.0;
bounce = true;
} else if (properties.position.z > upperCorner.z) {
newPosition.z = upperCorner.z;
newVelocity.z *= -1.0;
bounce = true;
}
if (bounce) {
Entities.editEntity(birds[i].entityId, { position: newPosition, velocity: newVelocity });
}
}
}
// Update average velocity and position of flock
if (birdVelocitiesCounted > 0) {
averageVelocity = Vec3.multiply(1.0 / birdVelocitiesCounted, sumVelocity);
//print(Vec3.length(averageVelocity));
}
if (birdPositionsCounted > 0) {
averagePosition = Vec3.multiply(1.0 / birdPositionsCounted, sumPosition);
}
}
// Connect a call back that happens every frame
Script.update.connect(updateBirds);
// Delete our little friends if script is stopped
Script.scriptEnding.connect(function() {
for (var i = 0; i < birds.length; i++) {
Entities.deleteEntity(birds[i].entityId);
}
if (floor) {
Entities.deleteEntity(floor);
}
});
function loadBirds(howMany) {
while (!Entities.serversExist() || !Entities.canRez()) {
}
var sound_filenames = ["bushtit_1.raw", "bushtit_2.raw", "bushtit_3.raw"];
/* Here are more sounds/species you can use
, "mexicanWhipoorwill.raw",
"rosyfacedlovebird.raw", "saysphoebe.raw", "westernscreechowl.raw", "bandtailedpigeon.wav", "bridledtitmouse.wav",
"browncrestedflycatcher.wav", "commonnighthawk.wav", "commonpoorwill.wav", "doublecrestedcormorant.wav",
"gambelsquail.wav", "goldcrownedkinglet.wav", "greaterroadrunner.wav","groovebilledani.wav","hairywoodpecker.wav",
"housewren.wav","hummingbird.wav", "mountainchickadee.wav", "nightjar.wav", "piebilledgrieb.wav", "pygmynuthatch.wav",
"whistlingduck.wav", "woodpecker.wav"];
*/
var colors = [
{ red: 242, green: 207, blue: 013 },
{ red: 238, green: 94, blue: 11 },
{ red: 81, green: 30, blue: 7 },
{ red: 195, green: 176, blue: 81 },
{ red: 235, green: 190, blue: 152 },
{ red: 167, green: 99, blue: 52 },
{ red: 199, green: 122, blue: 108 },
{ red: 246, green: 220, blue: 189 },
{ red: 208, green: 145, blue: 65 },
{ red: 173, green: 120 , blue: 71 },
{ red: 132, green: 147, blue: 174 },
{ red: 164, green: 74, blue: 40 },
{ red: 131, green: 127, blue: 134 },
{ red: 209, green: 157, blue: 117 },
{ red: 205, green: 191, blue: 193 },
{ red: 193, green: 154, blue: 118 },
{ red: 205, green: 190, blue: 169 },
{ red: 199, green: 111, blue: 69 },
{ red: 221, green: 223, blue: 228 },
{ red: 115, green: 92, blue: 87 },
{ red: 214, green: 165, blue: 137 },
{ red: 160, green: 124, blue: 33 },
{ red: 117, green: 91, blue: 86 },
{ red: 113, green: 104, blue: 107 },
{ red: 216, green: 153, blue: 99 },
{ red: 242, green: 226, blue: 64 }
];
var SOUND_BASE_URL = "http://public.highfidelity.io/sounds/Animals/";
for (var i = 0; i < howMany; i++) {
var whichBird = Math.floor(Math.random() * sound_filenames.length);
var position = {
x: lowerCorner.x + (upperCorner.x - lowerCorner.x) / 2.0 + (Math.random() - 0.5) * (upperCorner.x - lowerCorner.x) * STARTING_FRACTION,
y: lowerCorner.y + (upperCorner.y - lowerCorner.y) / 2.0 + (Math.random() - 0.5) * (upperCorner.y - lowerCorner.y) * STARTING_FRACTION,
z: lowerCorner.z + (upperCorner.z - lowerCorner.x) / 2.0 + (Math.random() - 0.5) * (upperCorner.z - lowerCorner.z) * STARTING_FRACTION
};
birds.push({
sound: SoundCache.getSound(SOUND_BASE_URL + sound_filenames[whichBird]),
entityId: Entities.addEntity({
type: "Sphere",
position: position,
dimensions: { x: BIRD_SIZE, y: BIRD_SIZE, z: BIRD_SIZE },
gravity: { x: 0, y: BIRD_GRAVITY, z: 0 },
velocity: { x: 0, y: -0.1, z: 0 },
linearDamping: LINEAR_DAMPING,
collisionsWillMove: true,
color: colors[whichBird]
}),
audioId: false,
isPlaying: false
});
}
if (MAKE_FLOOR) {
var FLOOR_THICKNESS = 0.05;
floor = Entities.addEntity({ type: "Box", position: { x: lowerCorner.x + (upperCorner.x - lowerCorner.x) / 2.0,
y: lowerCorner.y,
z: lowerCorner.z + (upperCorner.z - lowerCorner.z) / 2.0 },
dimensions: { x: (upperCorner.x - lowerCorner.x), y: FLOOR_THICKNESS, z: (upperCorner.z - lowerCorner.z)},
color: {red: 100, green: 100, blue: 100}
});
}
}

View file

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

View file

@ -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
@ -14,32 +14,48 @@
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 swordID = 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 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 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 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 toolBar = new ToolBar(0, 0, ToolBar.vertical, "highfidelity.sword.toolbar", function () {
return {x: 100, y: 380};
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,
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 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
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 +68,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 +77,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,7 +103,9 @@ function clearFlash() {
Overlays.deleteOverlay(flasher.overlay);
flasher = null;
}
function flash(color) {
return;
clearFlash();
flasher = {};
flasher.overlay = Overlays.addOverlay("text", {
@ -86,42 +117,74 @@ function flash(color) {
flasher.timer = Script.setTimeout(clearFlash, 500);
}
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,97 +194,57 @@ 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});
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,
blue: 0
});
updateDisplay();
}
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;
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() {
// 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;
}
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() {
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);
@ -232,101 +255,219 @@ function removeSword() {
MyAvatar.collisionSoundURL = originalAvatarCollisionSound;
}
removeDisplay();
swordHeld = false;
}
function cleanUp(leaveButtons) {
removeSword();
targetIDs.forEach(function (id) {
Entities.deleteAction(id.entity, id.action);
Entities.deleteEntity(id.entity);
});
targetIDs = [];
if (!leaveButtons) {
toolBar.cleanup();
}
removeSword();
gameStarted = false;
zombieFight.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({
var swordPosition = Vec3.sum(MyAvatar.position, Vec3.multiply(5, Quat.getFront(MyAvatar.orientation)));
var orientationAdjustment = Quat.fromPitchYawRollDegrees(90, 0, 0);
swordID = Entities.addEntity({
type: "Model",
name: "sword",
modelURL: swordModel,
compoundShapeURL: swordCollisionShape,
dimensions: dimensions,
position: swordPosition,
rotation: MyAvatar.orientation,
rotation: Quat.fromPitchYawRollDegrees(90, 0, 0),
damping: 0.1,
collisionSoundURL: swordCollisionSoundURL,
restitution: 0.01,
collisionsWillMove: true
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}),
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) {
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,
timeScale: 0.05
});
if (actionID === nullActionID) {
print('*** FAILED TO MAKE SWORD ACTION ***');
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) {
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
});
case swordButton:
if (!swordID) {
makeSword();
} else {
removeSword();
}
break;
case targetButton:
if (gameStarted) {
return;
}
Script.include("https://hifi-public.s3.amazonaws.com/eric/scripts/zombieFight.js");
zombieFight = new ZombieFight();
zombieFight.initiateZombieApocalypse();
gameStarted = 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;
break;
case cleanupButton:
cleanUp('leaveButtons');
break;
}
}
Script.scriptEnding.connect(cleanUp);
Controller.mousePressEvent.connect(onClick);
Script.update.connect(update);
Controller.mousePressEvent.connect(onClick);

View file

@ -286,6 +286,8 @@ var usersWindow = (function () {
MENU_ITEM = "Users Online",
MENU_ITEM_AFTER = "Chat...",
SETTING_USERS_WINDOW_MINIMIZED = "UsersWindow.Minimized",
isVisible = true,
isMinimized = false,
@ -869,9 +871,13 @@ var usersWindow = (function () {
pollUsers();
// Set minimized at end - setup code does not handle `minimized == false` correctly
setMinimized(Settings.getValue(SETTING_USERS_WINDOW_MINIMIZED, false));
}
function tearDown() {
Settings.setValue(SETTING_USERS_WINDOW_MINIMIZED, isMinimized);
Menu.removeMenuItem(MENU_NAME, MENU_ITEM);
Script.clearTimeout(usersTimer);

View file

@ -22,20 +22,11 @@ else ()
set(BUILD_SEQ "dev")
endif ()
if (APPLE)
set(GL_HEADERS "#include <OpenGL/glext.h>")
elseif (UNIX)
# include the right GL headers for UNIX
set(GL_HEADERS "#include <GL/gl.h>\n#include <GL/glext.h>")
elseif (WIN32)
add_definitions(-D_USE_MATH_DEFINES) # apparently needed to get M_PI and other defines from cmath/math.h
add_definitions(-DWINDOWS_LEAN_AND_MEAN) # needed to make sure windows doesn't go to crazy with its defines
if (WIN32)
add_definitions(-D_USE_MATH_DEFINES) # apparently needed to get M_PI and other defines from cmath/math.h
add_definitions(-DWINDOWS_LEAN_AND_MEAN) # needed to make sure windows doesn't go to crazy with its defines
endif()
set(GL_HEADERS "#include <windowshacks.h>\n#include <GL/glew.h>\n#include <GL/wglew.h>")
endif ()
# create the InterfaceConfig.h file based on GL_HEADERS above
configure_file(InterfaceConfig.h.in "${PROJECT_BINARY_DIR}/includes/InterfaceConfig.h")
configure_file(InterfaceVersion.h.in "${PROJECT_BINARY_DIR}/includes/InterfaceVersion.h")
# grab the implementation and header files from src dirs

View file

@ -0,0 +1,23 @@
import Hifi 1.0
import QtQuick 2.3
import QtQuick.Controls 1.2
TextOverlayElement {
id: root
Rectangle {
color: root.backgroundColor
anchors.fill: parent
Text {
x: root.leftMargin
y: root.topMargin
id: text
objectName: "textElement"
text: root.text
color: root.textColor
font.family: root.fontFamily
font.pixelSize: root.fontSize
lineHeightMode: Text.FixedHeight
lineHeight: root.lineHeight
}
}
}

View file

@ -21,9 +21,6 @@
#include <glm/gtx/vector_angle.hpp>
#include <glm/gtc/type_ptr.hpp>
// include this before QGLWidget, which includes an earlier version of OpenGL
#include "InterfaceConfig.h"
#include <QAbstractNativeEventFilter>
#include <QActionGroup>
#include <QColorDialog>
@ -58,7 +55,6 @@
#include <AccountManager.h>
#include <AddressManager.h>
#include <CursorManager.h>
#include <AmbientOcclusionEffect.h>
#include <AudioInjector.h>
#include <AutoUpdater.h>
#include <DeferredLightingEffect.h>
@ -89,7 +85,6 @@
#include <PathUtils.h>
#include <PerfStat.h>
#include <PhysicsEngine.h>
#include <ProgramObject.h>
#include <RenderDeferredTask.h>
#include <ResourceCache.h>
#include <SceneScriptingInterface.h>
@ -97,7 +92,6 @@
#include <SettingHandle.h>
#include <SimpleAverage.h>
#include <SoundCache.h>
#include <TextRenderer.h>
#include <Tooltip.h>
#include <UserActivityLogger.h>
#include <UUID.h>
@ -124,7 +118,7 @@
#include "devices/Leapmotion.h"
#include "devices/RealSense.h"
#include "devices/MIDIManager.h"
#include "RenderDeferredTask.h"
#include "scripting/AccountScriptingInterface.h"
#include "scripting/AudioDeviceScriptingInterface.h"
#include "scripting/ClipboardScriptingInterface.h"
@ -175,27 +169,9 @@ public:
};
template <typename F>
void with_stable_stack_check(F f) {
GLint mvDepth, prDepth;
glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &mvDepth);
glGetIntegerv(GL_PROJECTION_STACK_DEPTH, &prDepth);
f();
GLint mvDepthFinal, prDepthFinal;
glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &mvDepthFinal);
glGetIntegerv(GL_PROJECTION_STACK_DEPTH, &prDepthFinal);
Q_ASSERT(mvDepth == mvDepthFinal);
Q_ASSERT(prDepth == prDepthFinal);
if (mvDepth != mvDepthFinal || prDepth != prDepthFinal) {
qFatal("Failed to preserve GL stack depth");
}
}
using namespace std;
// Starfield information
static unsigned STARFIELD_NUM_STARS = 50000;
static unsigned STARFIELD_SEED = 1;
static uint8_t THROTTLED_IDLE_TIMER_DELAY = 10;
const qint64 MAXIMUM_CACHE_SIZE = 10 * BYTES_PER_GIGABYTES; // 10GB
@ -291,7 +267,6 @@ bool setupEssentials(int& argc, char** argv) {
auto audio = DependencyManager::set<AudioClient>();
auto audioScope = DependencyManager::set<AudioScope>();
auto deferredLightingEffect = DependencyManager::set<DeferredLightingEffect>();
auto ambientOcclusionEffect = DependencyManager::set<AmbientOcclusionEffect>();
auto textureCache = DependencyManager::set<TextureCache>();
auto animationCache = DependencyManager::set<AnimationCache>();
auto ddeFaceTracker = DependencyManager::set<DdeFaceTracker>();
@ -342,6 +317,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
_previousScriptLocation("LastScriptLocation"),
_scriptsLocationHandle("scriptsLocation"),
_fieldOfView("fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES),
_viewTransform(),
_scaleMirror(1.0f),
_rotateMirror(0.0f),
_raiseMirror(0.0f),
@ -358,6 +334,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
_lastNackTime(usecTimestampNow()),
_lastSendDownstreamAudioStats(usecTimestampNow()),
_isVSyncOn(true),
_isThrottleFPSEnabled(false),
_aboutToQuit(false),
_notifiedPacketVersionMismatchThisDomain(false),
_domainConnectionRefusals(QList<QString>()),
@ -365,7 +342,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
_lastFaceTrackerUpdate(0),
_applicationOverlay()
{
_offscreenContext = new OffscreenGlCanvas();
setInstance(this);
#ifdef Q_OS_WIN
installNativeEventFilter(&MyNativeEventFilter::getInstance());
@ -541,6 +517,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
ResourceCache::setRequestLimit(3);
_offscreenContext = new OffscreenGlCanvas();
_offscreenContext->create();
_offscreenContext->makeCurrent();
@ -582,16 +559,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
// enable mouse tracking; otherwise, we only get drag events
container->setMouseTracking(true);
_menuBarHeight = Menu::getInstance()->height();
#if 0
_fullscreenMenuWidget->setParent(_glWidget);
if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) {
setFullscreen(true); // Initialize menu bar show/hide
}
#endif
_toolWindow = new ToolWindow();
_toolWindow->setWindowFlags(_toolWindow->windowFlags() | Qt::WindowStaysOnTopHint);
_toolWindow->setWindowTitle("Tools");
@ -915,20 +882,17 @@ void Application::initializeUi() {
offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/"));
offscreenUi->load("Root.qml");
offscreenUi->load("RootMenu.qml");
VrMenu::load();
VrMenu::executeQueuedLambdas();
offscreenUi->setMouseTranslator([=](const QPointF& pt) {
QPointF result = pt;
auto displayPlugin = getActiveDisplayPlugin();
if (displayPlugin->isHmd()) {
auto resultVec = _compositor.screenToOverlay(toGlm(pt));
result = QPointF(resultVec.x, resultVec.y);
} else if (displayPlugin->isStereo()) {
}
}
return result;
});
VrMenu::load();
VrMenu::executeQueuedLambdas();
offscreenUi->resume();
connect(_window, &MainWindow::windowGeometryChanged, [this](const QRect & r){
static qreal oldDevicePixelRatio = 0;
@ -942,13 +906,9 @@ void Application::initializeUi() {
}
void Application::paintGL() {
if (getCanvasSize() == uvec2(0)) {
return;
}
PROFILE_RANGE(__FUNCTION__);
auto displayPlugin = getActiveDisplayPlugin();
displayPlugin->preRender();
_offscreenContext->makeCurrent();
auto lodManager = DependencyManager::get<LODManager>();
@ -967,10 +927,10 @@ void Application::paintGL() {
{
PerformanceTimer perfTimer("renderOverlay");
gpu::Context context(new gpu::GLBackend());
RenderArgs renderArgs(&context, nullptr, getViewFrustum(), lodManager->getOctreeSizeScale(),
lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE,
RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
// 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);
}
@ -1035,29 +995,42 @@ void Application::paintGL() {
renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE;
// Primary rendering pass
auto textureCache = DependencyManager::get<TextureCache>();
QSize size = textureCache->getFrameBufferSize();
{
PROFILE_RANGE(__FUNCTION__ "/mainRender");
auto primaryFbo = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
GLuint fbo = gpu::GLBackend::getFramebufferID(primaryFbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Viewport is assigned to the size of the framebuffer
QSize size = DependencyManager::get<TextureCache>()->getFrameBufferSize();
auto clearLambda = [&](const gpu::Vec4i& vp) {
gpu::Batch batch;
auto primaryFbo = textureCache->getPrimaryFramebuffer();
batch.setFramebuffer(primaryFbo);
// Viewport is assigned to the size of the framebuffer
renderArgs._viewport = vp;
batch.setViewportTransform(renderArgs._viewport);
batch.setStateScissorRect(renderArgs._viewport);
// clear the normal and specular buffers
batch.clearFramebuffer(
gpu::Framebuffer::BUFFER_COLOR0 |
gpu::Framebuffer::BUFFER_COLOR1 |
gpu::Framebuffer::BUFFER_COLOR2 |
gpu::Framebuffer::BUFFER_DEPTH,
vec4(vec3(0), 1), 1.0, 0.0, true);
renderArgs._context->render(batch);
};
if (displayPlugin->isStereo()) {
QRect r(QPoint(0, 0), QSize(size.width() / 2, size.height()));
glEnable(GL_SCISSOR_TEST);
for_each_eye([&](Eye eye){
// FIXME we need to let the display plugin decide how the geometry works for stereo rendering
// for instance, an interleaved display should have half the vertical resolution, while a side
// by side display for a temporal interleave should have full resolution
glViewport(r.x(), r.y(), r.width(), r.height());
glScissor(r.x(), r.y(), r.width(), r.height());
// Load the view frustum, used by meshes
Camera eyeCamera;
eyeCamera.setTransform(displayPlugin->getModelview(eye, _myCamera.getTransform()));
eyeCamera.setProjection(displayPlugin->getProjection(eye, _myCamera.getProjection()));
clearLambda(glm::ivec4(r.x(), r.y(), r.width(), r.height()));
displaySide(&renderArgs, eyeCamera);
if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror) &&
!Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) {
@ -1068,7 +1041,7 @@ void Application::paintGL() {
});
glDisable(GL_SCISSOR_TEST);
} else {
glViewport(0, 0, size.width(), size.height());
clearLambda(glm::ivec4(0, 0, size.width(), size.height()));
displaySide(&renderArgs, _myCamera);
if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror) &&
!Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) {
@ -1082,9 +1055,7 @@ void Application::paintGL() {
PROFILE_RANGE(__FUNCTION__ "/compositor");
auto primaryFbo = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFbo));
QSize size = DependencyManager::get<TextureCache>()->getFrameBufferSize();
if (displayPlugin->isStereo()) {
QSize size = DependencyManager::get<TextureCache>()->getFrameBufferSize();
QRect r(QPoint(0, 0), QSize(size.width() / 2, size.height()));
glClear(GL_DEPTH_BUFFER_BIT);
for_each_eye([&](Eye eye) {
@ -1101,14 +1072,12 @@ void Application::paintGL() {
glViewport(0, 0, size.width(), size.height());
_compositor.displayOverlayTexture(&renderArgs);
}
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
// deliver final composited scene to the display plugin
{
PROFILE_RANGE(__FUNCTION__ "/pluginOutput");
auto primaryFbo = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
QSize size = DependencyManager::get<TextureCache>()->getFrameBufferSize();
GLuint finalTexture = gpu::GLBackend::getTextureID(primaryFbo->getRenderBuffer(0));
uvec2 finalSize = toGlm(size);
#ifdef Q_OS_MAC
@ -1192,17 +1161,30 @@ void Application::resizeGL() {
// Possible change in aspect ratio
_myCamera.setProjection(glm::perspective(glm::radians(_fieldOfView.get()),
aspect(getCanvasSize()), DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP));
updateProjectionMatrix();
}
auto offscreenUi = DependencyManager::get<OffscreenUi>();
auto uiSize = displayPlugin->getRecommendedUiSize();
if (offscreenUi->getWindow()->geometry().size() != fromGlm(uiSize)) {
if (offscreenUi->size() != fromGlm(uiSize)) {
offscreenUi->resize(fromGlm(uiSize));
_offscreenContext->makeCurrent();
}
}
void Application::updateProjectionMatrix() {
updateProjectionMatrix(_myCamera);
}
void Application::updateProjectionMatrix(Camera& camera, bool updateViewFrustum) {
_projectionMatrix = camera.getProjection();
// Tell our viewFrustum about this change, using the application camera
if (updateViewFrustum) {
camera.loadViewFrustum(_viewFrustum);
}
}
void Application::controlledBroadcastToNodes(const QByteArray& packet, const NodeSet& destinationNodeTypes) {
foreach(NodeType_t type, destinationNodeTypes) {
// Perform the broadcast for one type
@ -1289,8 +1271,7 @@ bool Application::event(QEvent* event) {
bool Application::eventFilter(QObject* object, QEvent* event) {
if (event->type() == QEvent::ShortcutOverride) {
auto offscreenUi = DependencyManager::get<OffscreenUi>();
if (offscreenUi->shouldSwallowShortcut(event)) {
if (DependencyManager::get<OffscreenUi>()->shouldSwallowShortcut(event)) {
event->accept();
return true;
}
@ -1406,12 +1387,6 @@ void Application::keyPressEvent(QKeyEvent* event) {
Menu::getInstance()->triggerOption(MenuOption::Stars);
break;
case Qt::Key_W:
if (isOption && !isShifted && !isMeta) {
Menu::getInstance()->triggerOption(MenuOption::Wireframe);
}
break;
case Qt::Key_S:
if (isShifted && isMeta && !isOption) {
Menu::getInstance()->triggerOption(MenuOption::SuppressShortTimings);
@ -1503,11 +1478,6 @@ void Application::keyPressEvent(QKeyEvent* event) {
case Qt::Key_J:
if (isShifted) {
_viewFrustum.setFocalLength(_viewFrustum.getFocalLength() - 0.1f);
#if 0
if (TV3DManager::isConnected()) {
TV3DManager::configureCamera(_myCamera, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight());
}
#endif
} else {
_myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(-0.001, 0, 0));
}
@ -1517,11 +1487,6 @@ void Application::keyPressEvent(QKeyEvent* event) {
case Qt::Key_M:
if (isShifted) {
_viewFrustum.setFocalLength(_viewFrustum.getFocalLength() + 0.1f);
#if 0
if (TV3DManager::isConnected()) {
TV3DManager::configureCamera(_myCamera, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight());
}
#endif
} else {
_myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0.001, 0, 0));
}
@ -1691,23 +1656,10 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) {
if (!_lastMouseMoveWasSimulated) {
_lastMouseMove = usecTimestampNow();
}
if (_aboutToQuit) {
return;
}
#if 0
if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) {
// Show/hide menu bar in fullscreen
if (event->globalY() > _menuBarHeight) {
_fullscreenMenuWidget->setFixedHeight(0);
Menu::getInstance()->setFixedHeight(0);
} else {
_fullscreenMenuWidget->setFixedHeight(_menuBarHeight);
Menu::getInstance()->setFixedHeight(_menuBarHeight);
}
}
#endif
_entities.mouseMoveEvent(event, deviceID);
@ -2040,94 +1992,6 @@ void Application::idle() {
lastIdleEnd = usecTimestampNow();
}
#if 0
void Application::setFullscreen(bool fullscreen) {
if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen) != fullscreen) {
Menu::getInstance()->getActionForOption(MenuOption::Fullscreen)->setChecked(fullscreen);
}
// The following code block is useful on platforms that can have a visible
// app menu in a fullscreen window. However the OSX mechanism hides the
// application menu for fullscreen apps, so the check is not required.
#ifndef Q_OS_MAC
if (getActiveDisplayPlugin()->isHmd()) {
if (fullscreen) {
// Menu hide() disables menu commands, and show() after hide() doesn't work with Rift VR display.
// So set height instead.
_window->menuBar()->setMaximumHeight(0);
} else {
_window->menuBar()->setMaximumHeight(QWIDGETSIZE_MAX);
}
} else {
if (fullscreen) {
// Move menu to a QWidget floating above _glWidget so that show/hide doesn't adjust viewport.
_menuBarHeight = Menu::getInstance()->height();
Menu::getInstance()->setParent(_fullscreenMenuWidget);
Menu::getInstance()->setFixedWidth(_window->windowHandle()->screen()->size().width());
_fullscreenMenuWidget->show();
} else {
// Restore menu to being part of MainWindow.
_fullscreenMenuWidget->hide();
_window->setMenuBar(Menu::getInstance());
_window->menuBar()->setMaximumHeight(QWIDGETSIZE_MAX);
}
}
#endif
// Work around Qt bug that prevents floating menus being shown when in fullscreen mode.
// https://bugreports.qt.io/browse/QTBUG-41883
// Known issue: Top-level menu items don't highlight when cursor hovers. This is probably a side-effect of the work-around.
// TODO: Remove this work-around once the bug has been fixed and restore the following lines.
//_window->setWindowState(fullscreen ? (_window->windowState() | Qt::WindowFullScreen) :
// (_window->windowState() & ~Qt::WindowFullScreen));
_window->hide();
if (fullscreen) {
_window->setWindowState(_window->windowState() | Qt::WindowFullScreen);
// The next line produces the following warning in the log:
// [WARNING][03 / 06 12:17 : 58] QWidget::setMinimumSize: (/ MainWindow) Negative sizes
// (0, -1) are not possible
// This is better than the alternative which is to have the window slightly less than fullscreen with a visible line
// of pixels for the remainder of the screen.
_window->setContentsMargins(0, 0, 0, -1);
} else {
_window->setWindowState(_window->windowState() & ~Qt::WindowFullScreen);
_window->setContentsMargins(0, 0, 0, 0);
}
if (!_aboutToQuit) {
_window->show();
}
}
void Application::setEnable3DTVMode(bool enable3DTVMode) {
resizeGL();
}
void Application::setEnableVRMode(bool enableVRMode) {
if (Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode) != enableVRMode) {
Menu::getInstance()->getActionForOption(MenuOption::EnableVRMode)->setChecked(enableVRMode);
}
if (enableVRMode) {
if (!OculusManager::isConnected()) {
// attempt to reconnect the Oculus manager - it's possible this was a workaround
// for the sixense crash
OculusManager::disconnect();
OculusManager::connect(_glWidget->context()->contextHandle());
_glWidget->setFocus();
_glWidget->makeCurrent();
glClear(GL_COLOR_BUFFER_BIT);
}
OculusManager::recalibrate();
} else {
OculusManager::abandonCalibration();
OculusManager::disconnect();
}
resizeGL();
}
#endif
void Application::setLowVelocityFilter(bool lowVelocityFilter) {
InputDevice::setLowVelocityFilter(lowVelocityFilter);
}
@ -2201,13 +2065,6 @@ void Application::setActiveFaceTracker() {
#endif
}
void Application::toggleFaceTrackerMute() {
FaceTracker* faceTracker = getSelectedFaceTracker();
if (faceTracker) {
faceTracker->toggleMute();
}
}
bool Application::exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs) {
QVector<EntityItemPointer> entities;
@ -2316,12 +2173,6 @@ QVector<EntityItemID> Application::pasteEntities(float x, float y, float z) {
}
void Application::initDisplay() {
glEnable(GL_BLEND);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
glShadeModel(GL_SMOOTH);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
}
void Application::init() {
@ -2329,10 +2180,8 @@ void Application::init() {
DependencyManager::get<DialogsManager>()->toggleLoginDialog();
_environment.init();
Q_ASSERT(_offscreenContext->getContext() == QOpenGLContext::currentContext());
DependencyManager::get<DeferredLightingEffect>()->init(this);
DependencyManager::get<AmbientOcclusionEffect>()->init(this);
// TODO: move _myAvatar out of Application. Move relevant code to MyAvataar or AvatarManager
DependencyManager::get<AvatarManager>()->init();
@ -2340,15 +2189,6 @@ void Application::init() {
_mirrorCamera.setMode(CAMERA_MODE_MIRROR);
#if 0
TV3DManager::connect();
if (TV3DManager::isConnected()) {
QMetaObject::invokeMethod(Menu::getInstance()->getActionForOption(MenuOption::Fullscreen),
"trigger",
Qt::QueuedConnection);
}
#endif
_timerStart.start();
_lastTimeUpdated.start();
@ -2472,16 +2312,13 @@ void Application::updateMyAvatarLookAtPosition() {
bool isLookingAtSomeone = false;
glm::vec3 lookAtSpot;
if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
// When I am in mirror mode, just look right at the camera (myself)
lookAtSpot = _myCamera.getPosition();
#if 0
// FIXME is this really necessary?
// When I am in mirror mode, just look right at the camera (myself); don't switch gaze points because when physically
// looking in a mirror one's eyes appear steady.
if (isHMDMode()) {
lookAtSpot = _myCamera.getPosition() + OculusManager::getMidEyePosition();
if (!isHMDMode()) {
lookAtSpot = _myCamera.getPosition();
} else {
lookAtSpot = _myCamera.getPosition() + transformPoint(_myAvatar->getSensorToWorldMatrix(), extractTranslation(getHMDSensorPose()));
}
#endif
} else {
AvatarSharedPointer lookingAt = _myAvatar->getLookAtTargetAvatar().lock();
if (lookingAt && _myAvatar != lookingAt.get()) {
@ -2602,6 +2439,12 @@ void Application::updateDialogs(float deltaTime) {
PerformanceWarning warn(showWarnings, "Application::updateDialogs()");
auto dialogsManager = DependencyManager::get<DialogsManager>();
// Update audio stats dialog, if any
AudioStatsDialog* audioStatsDialog = dialogsManager->getAudioStatsDialog();
if(audioStatsDialog) {
audioStatsDialog->update();
}
// Update bandwidth dialog, if any
BandwidthDialog* bandwidthDialog = dialogsManager->getBandwidthDialog();
if (bandwidthDialog) {
@ -2641,7 +2484,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);
@ -3316,28 +3165,7 @@ bool Application::isHMDMode() const {
}
QRect Application::getDesirableApplicationGeometry() {
QRect applicationGeometry = getWindow()->geometry();
#if 0
// If our parent window is on the HMD, then don't use its geometry, instead use
// the "main screen" geometry.
HMDToolsDialog* hmdTools = DependencyManager::get<DialogsManager>()->getHMDToolsDialog();
if (hmdTools && hmdTools->hasHMDScreen()) {
QScreen* hmdScreen = hmdTools->getHMDScreen();
QWindow* appWindow = getWindow()->windowHandle();
QScreen* appScreen = appWindow->screen();
// if our app's screen is the hmd screen, we don't want to place the
// running scripts widget on it. So we need to pick a better screen.
// we will use the screen for the HMDTools since it's a guarenteed
// better screen.
if (appScreen == hmdScreen) {
QScreen* betterScreen = hmdTools->windowHandle()->screen();
applicationGeometry = betterScreen->geometry();
}
}
#endif
return applicationGeometry;
return getWindow()->geometry();
}
glm::vec3 Application::getSunDirection() {
@ -3350,155 +3178,9 @@ glm::vec3 Application::getSunDirection() {
static QThread * activeRenderingThread = nullptr;
void Application::updateShadowMap(RenderArgs* renderArgs) {
activeRenderingThread = QThread::currentThread();
PerformanceTimer perfTimer("shadowMap");
auto shadowFramebuffer = DependencyManager::get<TextureCache>()->getShadowFramebuffer();
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(shadowFramebuffer));
glEnable(GL_DEPTH_TEST);
glClear(GL_DEPTH_BUFFER_BIT);
glm::vec3 lightDirection = getSunDirection();
glm::quat rotation = rotationBetween(IDENTITY_FRONT, lightDirection);
glm::quat inverseRotation = glm::inverse(rotation);
const float SHADOW_MATRIX_DISTANCES[] = { 0.0f, 2.0f, 6.0f, 14.0f, 30.0f };
const glm::vec2 MAP_COORDS[] = { glm::vec2(0.0f, 0.0f), glm::vec2(0.5f, 0.0f),
glm::vec2(0.0f, 0.5f), glm::vec2(0.5f, 0.5f) };
float frustumScale = 1.0f / (_viewFrustum.getFarClip() - _viewFrustum.getNearClip());
_myCamera.loadViewFrustum(_viewFrustum);
int matrixCount = 1;
//int targetSize = fbo->width();
int sourceSize = shadowFramebuffer->getWidth();
int targetSize = shadowFramebuffer->getWidth();
float targetScale = 1.0f;
if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) {
matrixCount = CASCADED_SHADOW_MATRIX_COUNT;
targetSize = sourceSize / 2;
targetScale = 0.5f;
}
for (int i = 0; i < matrixCount; i++) {
const glm::vec2& coord = MAP_COORDS[i];
glViewport(coord.s * sourceSize, coord.t * sourceSize, targetSize, targetSize);
// if simple shadow then since the resolution is twice as much as with cascaded, cover 2 regions with the map, not just one
int regionIncrement = (matrixCount == 1 ? 2 : 1);
float nearScale = SHADOW_MATRIX_DISTANCES[i] * frustumScale;
float farScale = SHADOW_MATRIX_DISTANCES[i + regionIncrement] * frustumScale;
glm::vec3 points[] = {
glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), nearScale),
glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), nearScale),
glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), nearScale),
glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), nearScale),
glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), farScale),
glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), farScale),
glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), farScale),
glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), farScale) };
glm::vec3 center;
for (size_t j = 0; j < sizeof(points) / sizeof(points[0]); j++) {
center += points[j];
}
center /= (float)(sizeof(points) / sizeof(points[0]));
float radius = 0.0f;
for (size_t j = 0; j < sizeof(points) / sizeof(points[0]); j++) {
radius = qMax(radius, glm::distance(points[j], center));
}
if (i < 3) {
const float RADIUS_SCALE = 0.5f;
_shadowDistances[i] = -glm::distance(_viewFrustum.getPosition(), center) - radius * RADIUS_SCALE;
}
center = inverseRotation * center;
// to reduce texture "shimmer," move in texel increments
float texelSize = (2.0f * radius) / targetSize;
center = glm::vec3(roundf(center.x / texelSize) * texelSize, roundf(center.y / texelSize) * texelSize,
roundf(center.z / texelSize) * texelSize);
glm::vec3 minima(center.x - radius, center.y - radius, center.z - radius);
glm::vec3 maxima(center.x + radius, center.y + radius, center.z + radius);
// stretch out our extents in z so that we get all of the avatars
minima.z -= _viewFrustum.getFarClip() * 0.5f;
maxima.z += _viewFrustum.getFarClip() * 0.5f;
// save the combined matrix for rendering
_shadowMatrices[i] = glm::transpose(glm::translate(glm::vec3(coord, 0.0f)) *
glm::scale(glm::vec3(targetScale, targetScale, 1.0f)) *
glm::translate(glm::vec3(0.5f, 0.5f, 0.5f)) * glm::scale(glm::vec3(0.5f, 0.5f, 0.5f)) *
glm::ortho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z) * glm::mat4_cast(inverseRotation));
// update the shadow view frustum
// glm::vec3 shadowFrustumCenter = glm::vec3((minima.x + maxima.x) * 0.5f, (minima.y + maxima.y) * 0.5f, (minima.z + maxima.z) * 0.5f);
glm::vec3 shadowFrustumCenter = rotation * ((minima + maxima) * 0.5f);
_shadowViewFrustum.setPosition(shadowFrustumCenter);
_shadowViewFrustum.setOrientation(rotation);
_shadowViewFrustum.setProjection(glm::ortho(minima.x, maxima.x, minima.y, maxima.y, minima.z, maxima.z));
_shadowViewFrustum.calculate();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glm::mat4 proj = glm::ortho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z);
glLoadMatrixf(glm::value_ptr(proj));
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadMatrixf(glm::value_ptr(glm::mat4_cast(inverseRotation)));
// Equivalent to what is happening with _untranslatedViewMatrix and the _viewMatrixTranslation
// the viewTransofmr object is updatded with the correct values and saved,
// this is what is used for rendering the Entities and avatars
Transform viewTransform;
viewTransform.setRotation(rotation);
setViewTransform(viewTransform);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.1f, 4.0f); // magic numbers courtesy http://www.eecs.berkeley.edu/~ravir/6160/papers/shadowmaps.ppt
{
PerformanceTimer perfTimer("entities");
_entities.render(renderArgs);
}
glDisable(GL_POLYGON_OFFSET_FILL);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
glViewport(0, 0, getDeviceSize().width(), getDeviceSize().height());
activeRenderingThread = nullptr;
}
const GLfloat WORLD_AMBIENT_COLOR[] = { 0.525f, 0.525f, 0.6f };
const GLfloat WORLD_DIFFUSE_COLOR[] = { 0.6f, 0.525f, 0.525f };
const GLfloat WORLD_SPECULAR_COLOR[] = { 0.08f, 0.08f, 0.08f, 1.0f };
const glm::vec3 GLOBAL_LIGHT_COLOR = { 0.6f, 0.525f, 0.525f };
void Application::setupWorldLight() {
// Setup 3D lights (after the camera transform, so that they are positioned in world space)
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glm::vec3 sunDirection = getSunDirection();
GLfloat light_position0[] = { sunDirection.x, sunDirection.y, sunDirection.z, 0.0 };
glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
glLightfv(GL_LIGHT0, GL_AMBIENT, WORLD_AMBIENT_COLOR);
glLightfv(GL_LIGHT0, GL_DIFFUSE, WORLD_DIFFUSE_COLOR);
glLightfv(GL_LIGHT0, GL_SPECULAR, WORLD_SPECULAR_COLOR);
glMaterialfv(GL_FRONT, GL_SPECULAR, WORLD_SPECULAR_COLOR);
glMateriali(GL_FRONT, GL_SHININESS, 96);
void Application::setupWorldLight(RenderArgs* renderArgs) {
}
bool Application::shouldRenderMesh(float largestDimension, float distanceToCamera) {
@ -3656,9 +3338,6 @@ namespace render {
PerformanceTimer perfTimer("stars");
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
"Application::payloadRender<BackgroundRenderData>() ... stars...");
if (!background->_stars.isStarsLoaded()) {
background->_stars.generate(STARFIELD_NUM_STARS, STARFIELD_SEED);
}
// should be the first rendering pass - w/o depth buffer / lighting
// compute starfield alpha based on distance from atmosphere
@ -3706,7 +3385,7 @@ namespace render {
// finally render the starfield
if (hasStars) {
background->_stars.render(args->_viewFrustum->getFieldOfView(), args->_viewFrustum->getAspectRatio(), args->_viewFrustum->getNearClip(), alpha);
background->_stars.render(args, alpha);
}
// draw the sky dome
@ -3714,7 +3393,8 @@ namespace render {
PerformanceTimer perfTimer("atmosphere");
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
"Application::displaySide() ... atmosphere...");
background->_environment->renderAtmospheres(batch, args->_viewFrustum->getPosition());
background->_environment->renderAtmospheres(batch, *(args->_viewFrustum));
}
}
@ -3733,6 +3413,7 @@ namespace render {
}
}
void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool selfAvatarOnly, bool billboard) {
// FIXME: This preRender call is temporary until we create a separate render::scene for the mirror rendering.
@ -3747,44 +3428,22 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
// load the view frustum
theCamera.loadViewFrustum(_displayViewFrustum);
// Load the legacy GL stacks, used by entities (for now)
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadMatrixf(glm::value_ptr(theCamera.getProjection()));
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadMatrixf(glm::value_ptr(glm::inverse(theCamera.getTransform())));
glm::quat rotation = theCamera.getRotation();
// Equivalent to what is happening with _untranslatedViewMatrix and the _viewMatrixTranslation
// the viewTransofmr object is updatded with the correct values and saved,
// this is what is used for rendering the Entities and avatars
Transform viewTransform;
viewTransform.setTranslation(theCamera.getPosition());
viewTransform.setRotation(rotation);
viewTransform.setRotation(theCamera.getRotation());
setViewTransform(viewTransform);
// Setup 3D lights (after the camera transform, so that they are positioned in world space)
{
PerformanceTimer perfTimer("lights");
setupWorldLight();
}
// setup shadow matrices (again, after the camera transform)
int shadowMatrixCount = 0;
if (Menu::getInstance()->isOptionChecked(MenuOption::SimpleShadows)) {
shadowMatrixCount = 1;
} else if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) {
shadowMatrixCount = CASCADED_SHADOW_MATRIX_COUNT;
}
for (int i = shadowMatrixCount - 1; i >= 0; i--) {
glActiveTexture(GL_TEXTURE0 + i);
glTexGenfv(GL_S, GL_EYE_PLANE, (const GLfloat*)&_shadowMatrices[i][0]);
glTexGenfv(GL_T, GL_EYE_PLANE, (const GLfloat*)&_shadowMatrices[i][1]);
glTexGenfv(GL_R, GL_EYE_PLANE, (const GLfloat*)&_shadowMatrices[i][2]);
setupWorldLight(renderArgs);
}
// TODO fix shadows and make them use the GPU library
// The pending changes collecting the changes here
render::PendingChanges pendingChanges;
@ -3799,15 +3458,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
}
if (Menu::getInstance()->isOptionChecked(MenuOption::Wireframe)) {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
// Assuming nothing get's rendered through that
if (!selfAvatarOnly) {
if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderEntities()) {
// render models...
@ -3828,14 +3479,6 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
_entities.render(renderArgs);
//ViveControllerManager::getInstance().updateRendering(renderArgs, _main3DScene, pendingChanges);
}
// render the ambient occlusion effect if enabled
if (Menu::getInstance()->isOptionChecked(MenuOption::AmbientOcclusion)) {
PerformanceTimer perfTimer("ambientOcclusion");
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
"Application::displaySide() ... AmbientOcclusion...");
DependencyManager::get<AmbientOcclusionEffect>()->render();
}
}
// Make sure the WorldBox is in the scene
@ -3926,16 +3569,6 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
}
}
if (Menu::getInstance()->isOptionChecked(MenuOption::Wireframe)) {
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glLoadMatrixf(glm::value_ptr(theCamera.getProjection()));
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
activeRenderingThread = nullptr;
}
@ -3943,22 +3576,6 @@ void Application::setViewTransform(const Transform& view) {
_viewTransform = view;
}
//void Application::updateUntranslatedViewMatrix(const glm::vec3& viewMatrixTranslation) {
// glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat*)&_untranslatedViewMatrix);
// _viewMatrixTranslation = viewMatrixTranslation;
//}
//
//void Application::loadTranslatedViewMatrix(const glm::vec3& translation) {
// glLoadMatrixf((const GLfloat*)&_untranslatedViewMatrix);
// glTranslatef(translation.x + _viewMatrixTranslation.x, translation.y + _viewMatrixTranslation.y,
// translation.z + _viewMatrixTranslation.z);
//}
//
//void Application::getModelViewMatrix(glm::dmat4* modelViewMatrix) {
// (*modelViewMatrix) =_untranslatedViewMatrix;
// (*modelViewMatrix)[3] = _untranslatedViewMatrix * glm::vec4(_viewMatrixTranslation, 1);
//}
void Application::getModelViewMatrix(glm::dmat4* modelViewMatrix) {
(*modelViewMatrix) = glm::inverse(_displayViewFrustum.getView());
}
@ -3978,9 +3595,8 @@ bool Application::getCascadeShadowsEnabled() {
}
void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& region, bool billboard) {
auto originalViewport = renderArgs->_viewport;
// Grab current viewport to reset it at the end
int viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
float aspect = (float)region.width() / region.height();
float fov = MIRROR_FIELD_OF_VIEW;
@ -4017,34 +3633,37 @@ void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& regi
_mirrorCamera.setProjection(glm::perspective(glm::radians(fov), aspect, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP));
_mirrorCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI, 0.0f)));
// set the bounds of rear mirror view
gpu::Vec4i viewport;
if (billboard) {
QSize size = DependencyManager::get<TextureCache>()->getFrameBufferSize();
glViewport(region.x(), size.height() - region.y() - region.height(), region.width(), region.height());
glScissor(region.x(), size.height() - region.y() - region.height(), region.width(), region.height());
renderArgs->_viewport = glm::ivec4(region.x(), size.height() - region.y() - region.height(), region.width(), region.height());
viewport = gpu::Vec4i(region.x(), size.height() - region.y() - region.height(), region.width(), region.height());
} else {
// if not rendering the billboard, the region is in device independent coordinates; must convert to device
QSize size = DependencyManager::get<TextureCache>()->getFrameBufferSize();
float ratio = (float)QApplication::desktop()->windowHandle()->devicePixelRatio() * getRenderResolutionScale();
int x = region.x() * ratio, y = region.y() * ratio, width = region.width() * ratio, height = region.height() * ratio;
glViewport(x, size.height() - y - height, width, height);
glScissor(x, size.height() - y - height, width, height);
renderArgs->_viewport = glm::ivec4(x, size.height() - y - height, width, height);
viewport = gpu::Vec4i(x, size.height() - y - height, width, height);
}
glEnable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
renderArgs->_viewport = viewport;
// render rear mirror view
glPushMatrix();
{
gpu::Batch batch;
batch.setViewportTransform(viewport);
batch.setStateScissorRect(viewport);
batch.clearFramebuffer(
gpu::Framebuffer::BUFFER_COLOR0 |
gpu::Framebuffer::BUFFER_COLOR1 |
gpu::Framebuffer::BUFFER_COLOR2 |
gpu::Framebuffer::BUFFER_DEPTH,
vec4(vec3(0), 1), 1.0, 0.0, true);
renderArgs->_context->render(batch);
}
bool updateViewFrustum = false;
updateProjectionMatrix(_mirrorCamera, updateViewFrustum);
displaySide(renderArgs, _mirrorCamera, true, billboard);
glPopMatrix();
// reset Viewport and projection matrix
renderArgs->_viewport = glm::ivec4(viewport[0], viewport[1], viewport[2], viewport[3]);
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
glDisable(GL_SCISSOR_TEST);
}
void Application::resetSensors() {
@ -4054,13 +3673,6 @@ void Application::resetSensors() {
getActiveDisplayPlugin()->resetSensors();
//_leapmotion.reset();
#if 0
QScreen* currentScreen = _window->windowHandle()->screen();
QWindow* mainWindow = _window->windowHandle();
QPoint windowCenter = mainWindow->geometry().center();
_glWidget->cursor().setPos(currentScreen, windowCenter);
#endif
_myAvatar->reset();
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(), "reset", Qt::QueuedConnection);
@ -4907,6 +4519,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")) {

View file

@ -12,8 +12,6 @@
#ifndef hifi_Application_h
#define hifi_Application_h
#include <gpu/GPUConfig.h>
#include <QApplication>
#include <QHash>
#include <QImage>
@ -57,6 +55,7 @@
#include <input-plugins/KeyboardMouseDevice.h>
#include "scripting/ControllerScriptingInterface.h"
#include "scripting/WebWindowClass.h"
#include "ui/AudioStatsDialog.h"
#include "ui/BandwidthDialog.h"
#include "ui/ModelsBrowser.h"
#include "ui/OctreeStatsDialog.h"
@ -82,10 +81,10 @@ class QTouchEvent;
class QWheelEvent;
class OffscreenGlCanvas;
class GLCanvas;
class FaceTracker;
class MainWindow;
class Node;
class ProgramObject;
class ScriptEngine;
class GlWindow;
@ -262,7 +261,7 @@ public:
void controlledBroadcastToNodes(const QByteArray& packet, const NodeSet& destinationNodeTypes);
virtual void setupWorldLight();
virtual void setupWorldLight(RenderArgs* renderArgs);
virtual bool shouldRenderMesh(float largestDimension, float distanceToCamera);
QImage renderAvatarBillboard(RenderArgs* renderArgs);
@ -348,9 +347,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();
@ -414,10 +410,12 @@ public slots:
void domainSettingsReceived(const QJsonObject& domainSettingsObject);
void setVSyncEnabled();
void setThrottleFPSEnabled();
bool isThrottleFPSEnabled() { return _isThrottleFPSEnabled; }
void resetSensors();
void setActiveFaceTracker();
void toggleFaceTrackerMute();
void aboutApp();
void showEditEntitiesHelp();
@ -627,6 +625,7 @@ private:
quint64 _lastSendDownstreamAudioStats;
bool _isVSyncOn;
bool _isThrottleFPSEnabled;
bool _aboutToQuit;
@ -638,11 +637,9 @@ private:
QTimer _settingsTimer;
GlWindow* _glWindow{ nullptr };
void checkSkeleton();
QWidget* _fullscreenMenuWidget = new QWidget();
int _menuBarHeight;
QHash<QString, AcceptURLMethod> _acceptedExtensions;
QList<QString> _domainConnectionRefusals;

View file

@ -97,13 +97,6 @@ void MainWindow::changeEvent(QEvent* event) {
} else {
emit windowShown(true);
}
#if 0
if (isFullScreen() != Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) {
Menu::getInstance()->setIsOptionChecked(MenuOption::Fullscreen, isFullScreen());
}
#endif
} else if (event->type() == QEvent::ActivationChange) {
if (isActiveWindow()) {
emit windowShown(true);

View file

@ -9,9 +9,6 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// include this before QGLWidget, which includes an earlier version of OpenGL
#include "InterfaceConfig.h"
#include <QFileDialog>
#include <QMenuBar>
#include <QShortcut>
@ -267,19 +264,6 @@ Menu::Menu() {
addActionToQMenuAndActionHash(viewMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches()));
#if 0
addCheckableActionToQMenuAndActionHash(viewMenu,
MenuOption::Fullscreen,
#ifdef Q_OS_MAC
Qt::CTRL | Qt::META | Qt::Key_F,
#else
Qt::CTRL | Qt::Key_F,
#endif
false,
qApp,
SLOT(setFullscreen(bool)));
#endif
MenuWrapper* cameraModeMenu = viewMenu->addMenu("Camera Mode");
QActionGroup* cameraModeGroup = new QActionGroup(cameraModeMenu);
cameraModeGroup->setExclusive(true);
@ -306,17 +290,6 @@ Menu::Menu() {
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::CenterPlayerInView,
0, false, qApp, SLOT(rotationModeChanged()));
#if 0
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::HMDTools,
#ifdef Q_OS_MAC
Qt::META | Qt::Key_H,
#else
Qt::CTRL | Qt::Key_H,
#endif
false,
dialogsManager.data(),
SLOT(hmdTools(bool)));
#endif
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::TurnWithHead, 0, false);
@ -327,6 +300,8 @@ Menu::Menu() {
addActionToQMenuAndActionHash(viewMenu, MenuOption::Log,
Qt::CTRL | Qt::SHIFT | Qt::Key_L,
qApp, SLOT(toggleLogDialog()));
addActionToQMenuAndActionHash(viewMenu, MenuOption::AudioNetworkStats, 0,
dialogsManager.data(), SLOT(audioStatsDetails()));
addActionToQMenuAndActionHash(viewMenu, MenuOption::BandwidthDetails, 0,
dialogsManager.data(), SLOT(bandwidthDetails()));
addActionToQMenuAndActionHash(viewMenu, MenuOption::OctreeStats, 0,
@ -377,6 +352,8 @@ Menu::Menu() {
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::RenderTargetFramerateVSyncOn, 0, true,
qApp, SLOT(setVSyncEnabled()));
#endif
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ThrottleFPSIfNotFocus, 0, false,
qApp, SLOT(setThrottleFPSEnabled()));
}
@ -393,7 +370,6 @@ Menu::Menu() {
0, // QML Qt::Key_Asterisk,
true);
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Wireframe, Qt::ALT | Qt::Key_W, false);
addActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::LodTools,
0, // QML Qt::SHIFT | Qt::Key_L,
dialogsManager.data(), SLOT(lodTools()));
@ -441,8 +417,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
@ -581,15 +556,6 @@ Menu::Menu() {
audioScopeFramesGroup->addAction(fiftyFrames);
}
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioStats,
Qt::CTRL | Qt::SHIFT | Qt::Key_A,
false); //, statsRenderer.data(), SLOT(toggle())); // TODO: convert to dialogbox
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioStatsShowInjectedStreams,
0,
false); //, statsRenderer.data(), SLOT(toggleShowInjectedStreams)); // TODO: convert to dialogbox
MenuWrapper* physicsOptionsMenu = developerMenu->addMenu("Physics");
addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowOwned);
addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowHulls);

View file

@ -144,7 +144,7 @@ namespace MenuOption {
const QString AudioScopeFrames = "Display Frames";
const QString AudioScopePause = "Pause Scope";
const QString AudioScopeTwentyFrames = "Twenty";
const QString AudioStats = "Audio Stats";
const QString AudioNetworkStats = "Audio Network Stats";
const QString AudioStatsShowInjectedStreams = "Audio Stats Show Injected Streams";
const QString AutoMuteAudio = "Auto Mute Microphone";
const QString AvatarReceiveStats = "Show Receive Stats";
@ -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";
@ -289,7 +290,6 @@ namespace MenuOption {
const QString VisibleToEveryone = "Everyone";
const QString VisibleToFriends = "Friends";
const QString VisibleToNoOne = "No one";
const QString Wireframe = "Wireframe";
}
#endif // hifi_Menu_h

View file

@ -11,39 +11,173 @@
#include "Stars.h"
#include <mutex>
#include <QElapsedTimer>
#include <gpu/Batch.h>
#include <gpu/Context.h>
#include <NumericalConstants.h>
#include <DependencyManager.h>
#include <GeometryCache.h>
#include <TextureCache.h>
#include <RenderArgs.h>
#include <ViewFrustum.h>
#include "InterfaceConfig.h"
#include "starfield/Controller.h"
#include "../../libraries/render-utils/standardTransformPNTC_vert.h"
#include "../../libraries/render-utils/stars_frag.h"
Stars::Stars() :
_controller(0l), _starsLoaded(false) {
_controller = new starfield::Controller;
//static const float TILT = 0.23f;
static const float TILT = 0.0f;
static const unsigned int STARFIELD_NUM_STARS = 50000;
static const unsigned int STARFIELD_SEED = 1;
static const float STAR_COLORIZATION = 0.1f;
static const float TAU = 6.28318530717958f;
static const float HALF_TAU = TAU / 2.0f;
static const float QUARTER_TAU = TAU / 4.0f;
static const float MILKY_WAY_WIDTH = TAU / 30.0f; // width in radians of one half of the Milky Way
static const float MILKY_WAY_INCLINATION = 0.0f; // angle of Milky Way from horizontal in degrees
static const float MILKY_WAY_RATIO = 0.4f;
static const char* UNIFORM_TIME_NAME = "iGlobalTime";
Stars::Stars() {
}
Stars::~Stars() {
delete _controller;
}
bool Stars::generate(unsigned numStars, unsigned seed) {
_starsLoaded = _controller->computeStars(numStars, seed);
return _starsLoaded;
// Produce a random float value between 0 and 1
static float frand() {
return (float)rand() / (float)RAND_MAX;
}
bool Stars::setResolution(unsigned k) {
return _controller->setResolution(k);
// Produce a random radian value between 0 and 2 PI (TAU)
static float rrand() {
return frand() * TAU;
}
void Stars::render(float fovY, float aspect, float nearZ, float alpha) {
// determine length of screen diagonal from quadrant height and aspect ratio
float quadrantHeight = nearZ * tanf(RADIANS_PER_DEGREE * fovY * 0.5f);
float halfDiagonal = sqrt(quadrantHeight * quadrantHeight * (1.0f + aspect * aspect));
// determine fov angle in respect to the diagonal
float fovDiagonal = atanf(halfDiagonal / nearZ) * 2.0f;
// pull the modelview matrix off the GL stack
glm::mat4 view; glGetFloatv(GL_MODELVIEW_MATRIX, glm::value_ptr(view));
_controller->render(fovDiagonal, aspect, glm::affineInverse(view), alpha);
// http://mathworld.wolfram.com/SpherePointPicking.html
static vec2 randPolar() {
vec2 result(frand(), frand());
result.x *= TAU;
result.y = powf(result.y, 2.0) / 2.0f;
if (frand() > 0.5f) {
result.y = 0.5f - result.y;
} else {
result.y += 0.5f;
}
result.y = acos((2.0f * result.y) - 1.0f);
return result;
}
static vec3 fromPolar(const vec2& polar) {
float sinTheta = sin(polar.x);
float cosTheta = cos(polar.x);
float sinPhi = sin(polar.y);
float cosPhi = cos(polar.y);
return vec3(
cosTheta * sinPhi,
cosPhi,
sinTheta * sinPhi);
}
// computeStarColor
// - Generate a star color.
//
// colorization can be a value between 0 and 1 specifying how colorful the resulting star color is.
//
// 0 = completely black & white
// 1 = very colorful
unsigned computeStarColor(float colorization) {
unsigned char red, green, blue;
if (randFloat() < 0.3f) {
// A few stars are colorful
red = 2 + (rand() % 254);
green = 2 + round((red * (1 - colorization)) + ((rand() % 254) * colorization));
blue = 2 + round((red * (1 - colorization)) + ((rand() % 254) * colorization));
} else {
// Most stars are dimmer and white
red = green = blue = 2 + (rand() % 128);
}
return red | (green << 8) | (blue << 16);
}
// FIXME star colors
void Stars::render(RenderArgs* renderArgs, float alpha) {
static gpu::BufferPointer vertexBuffer;
static gpu::Stream::FormatPointer streamFormat;
static gpu::Element positionElement, colorElement;
static gpu::PipelinePointer _pipeline;
static int32_t _timeSlot{ -1 };
static std::once_flag once;
const int VERTICES_SLOT = 0;
const int COLOR_SLOT = 2;
std::call_once(once, [&] {
QElapsedTimer startTime;
startTime.start();
vertexBuffer.reset(new gpu::Buffer);
srand(STARFIELD_SEED);
unsigned limit = STARFIELD_NUM_STARS;
std::vector<vec3> points;
points.resize(limit);
for (size_t star = 0; star < limit; ++star) {
points[star] = fromPolar(randPolar());
//auto color = computeStarColor(STAR_COLORIZATION);
//vertexBuffer->append(sizeof(color), (const gpu::Byte*)&color);
}
vertexBuffer->append(sizeof(vec3) * limit, (const gpu::Byte*)&points[0]);
streamFormat.reset(new gpu::Stream::Format()); // 1 for everyone
streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
positionElement = streamFormat->getAttributes().at(gpu::Stream::POSITION)._element;
double timeDiff = (double)startTime.nsecsElapsed() / 1000000.0; // ns to ms
qDebug() << "Total time to generate stars: " << timeDiff << " msec";
auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(standardTransformPNTC_vert)));
auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(stars_frag)));
auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps));
gpu::Shader::makeProgram((*program));
_timeSlot = program->getBuffers().findLocation(UNIFORM_TIME_NAME);
if (_timeSlot == gpu::Shader::INVALID_LOCATION) {
_timeSlot = program->getUniforms().findLocation(UNIFORM_TIME_NAME);
}
auto state = gpu::StatePointer(new gpu::State());
// enable decal blend
state->setDepthTest(gpu::State::DepthTest(false));
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
_pipeline.reset(gpu::Pipeline::create(program, state));
});
auto geometryCache = DependencyManager::get<GeometryCache>();
auto textureCache = DependencyManager::get<TextureCache>();
gpu::Batch batch;
batch.setViewTransform(Transform());
batch.setProjectionTransform(renderArgs->_viewFrustum->getProjection());
batch.setModelTransform(Transform().setRotation(glm::inverse(renderArgs->_viewFrustum->getOrientation()) *
quat(vec3(TILT, 0, 0))));
batch.setResourceTexture(0, textureCache->getWhiteTexture());
// Render the world lines
batch.setPipeline(_pipeline);
static auto start = usecTimestampNow();
float msecs = (float)(usecTimestampNow() - start) / (float)USECS_PER_MSEC;
float secs = msecs / (float)MSECS_PER_SECOND;
batch._glUniform1f(_timeSlot, secs);
geometryCache->renderUnitCube(batch);
// Render the stars
geometryCache->useSimpleDrawPipeline(batch);
batch.setInputFormat(streamFormat);
batch.setInputBuffer(VERTICES_SLOT, gpu::BufferView(vertexBuffer, positionElement));
batch.draw(gpu::Primitive::POINTS, STARFIELD_NUM_STARS);
renderArgs->_context->render(batch);
}

View file

@ -12,9 +12,7 @@
#ifndef hifi_Stars_h
#define hifi_Stars_h
#include <glm/glm.hpp>
namespace starfield { class Controller; }
class RenderArgs;
// Starfield rendering component.
class Stars {
@ -22,33 +20,13 @@ public:
Stars();
~Stars();
// Generate stars from random number
// The numStars parameter sets the number of stars to generate.
bool generate(unsigned numStars, unsigned seed);
// Renders the starfield from a local viewer's perspective.
// The parameters specifiy the field of view.
void render(float fovY, float aspect, float nearZ, float alpha);
// Sets the resolution for FOV culling.
//
// The parameter determines the number of tiles in azimuthal
// and altitudinal directions.
//
// GPU resources are updated upon change in which case 'true'
// is returned.
bool setResolution(unsigned k);
// Returns true when stars have been loaded
bool isStarsLoaded() const { return _starsLoaded; };
void render(RenderArgs* args, float alpha);
private:
// don't copy/assign
Stars(Stars const&); // = delete;
Stars& operator=(Stars const&); // delete;
starfield::Controller* _controller;
bool _starsLoaded;
};

View file

@ -23,9 +23,7 @@
#include <ByteCountCoding.h>
#include <SharedUtil.h>
#include <TextRenderer.h>
#include "InterfaceConfig.h"
#include "world.h"
#include "Application.h"
#include "InterfaceLogging.h"
@ -79,27 +77,6 @@ const glm::vec3 randVector() {
return glm::vec3(randFloat() - 0.5f, randFloat() - 0.5f, randFloat() - 0.5f) * 2.0f;
}
static TextRenderer* textRenderer(int mono) {
static TextRenderer* monoRenderer = TextRenderer::getInstance(MONO_FONT_FAMILY);
static TextRenderer* proportionalRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY,
-1, -1, false, TextRenderer::SHADOW_EFFECT);
static TextRenderer* inconsolataRenderer = TextRenderer::getInstance(INCONSOLATA_FONT_FAMILY, -1, INCONSOLATA_FONT_WEIGHT,
false);
switch (mono) {
case 1:
return monoRenderer;
case 2:
return inconsolataRenderer;
case 0:
default:
return proportionalRenderer;
}
}
int widthText(float scale, int mono, char const* string) {
return textRenderer(mono)->computeExtent(string).x; // computeWidth(string) * (scale / 0.10);
}
void renderCollisionOverlay(int width, int height, float magnitude, float red, float blue, float green) {
const float MIN_VISIBLE_COLLISION = 0.01f;
if (magnitude > MIN_VISIBLE_COLLISION) {

View file

@ -22,7 +22,6 @@ float randFloat();
const glm::vec3 randVector();
void renderWorldBox(gpu::Batch& batch);
int widthText(float scale, int mono, char const* string);
void renderCollisionOverlay(int width, int height, float magnitude, float red = 0, float blue = 0, float green = 0);

View file

@ -9,8 +9,6 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <gpu/GPUConfig.h>
#include <limits>
#include <AudioClient.h>
@ -38,6 +36,7 @@ AudioScope::AudioScope() :
_scopeOutputLeft(NULL),
_scopeOutputRight(NULL),
_scopeLastFrame(),
_audioScopeBackground(DependencyManager::get<GeometryCache>()->allocateID()),
_audioScopeGrid(DependencyManager::get<GeometryCache>()->allocateID()),
_inputID(DependencyManager::get<GeometryCache>()->allocateID()),
_outputLeftID(DependencyManager::get<GeometryCache>()->allocateID()),
@ -126,22 +125,24 @@ 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>();
geometryCache->useSimpleDrawPipeline(batch);
auto textureCache = DependencyManager::get<TextureCache>();
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);
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);
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) {

View file

@ -69,6 +69,7 @@ private:
QByteArray* _scopeOutputRight;
QByteArray _scopeLastFrame;
int _audioScopeBackground;
int _audioScopeGrid;
int _inputID;
int _outputLeftID;

View file

@ -11,8 +11,6 @@
#include <vector>
#include <gpu/GPUConfig.h>
#include <QDesktopWidget>
#include <QWindow>
@ -281,7 +279,7 @@ enum TextRendererType {
static TextRenderer3D* textRenderer(TextRendererType type) {
static TextRenderer3D* chatRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, -1,
false, TextRenderer3D::SHADOW_EFFECT);
false, SHADOW_EFFECT);
static TextRenderer3D* displayNameRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY);
switch(type) {

View file

@ -24,7 +24,6 @@
#include "Hand.h"
#include "Head.h"
#include "InterfaceConfig.h"
#include "SkeletonModel.h"
#include "world.h"

View file

@ -8,13 +8,10 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <gpu/GPUConfig.h> // hack to get windows to build
#include <QImage>
#include <GeometryUtil.h>
#include <NodeList.h>
#include <ProgramObject.h>
#include "AvatarManager.h"
#include "Hand.h"

View file

@ -11,8 +11,6 @@
#ifndef hifi_Hand_h
#define hifi_Hand_h
#include "InterfaceConfig.h"
#include <vector>
#include <QAction>
@ -30,7 +28,6 @@
class Avatar;
class ProgramObject;
const float HAND_PADDLE_OFFSET = 0.1f;
const float HAND_PADDLE_THICKNESS = 0.01f;

View file

@ -9,7 +9,6 @@
//
#include <glm/gtx/quaternion.hpp>
#include <gpu/GPUConfig.h>
#include <gpu/Batch.h>
#include <DependencyManager.h>

View file

@ -19,14 +19,12 @@
#include <HeadData.h>
#include "FaceModel.h"
#include "InterfaceConfig.h"
#include "world.h"
const float EYE_EAR_GAP = 0.08f;
class Avatar;
class ProgramObject;
class Head : public HeadData {
public:

View file

@ -31,7 +31,7 @@
#include <PerfStat.h>
#include <ShapeCollider.h>
#include <SharedUtil.h>
#include <TextRenderer.h>
#include <TextRenderer3D.h>
#include <UserActivityLogger.h>
#include "devices/Faceshift.h"

View file

@ -103,4 +103,3 @@ void OctreePacketProcessor::processPacket(const SharedNodePointer& sendingNode,
}
}
}

View file

@ -1,62 +0,0 @@
//
// Config.h
// interface/src/starfield
//
// Created by Tobias Schwinger on 3/29/13.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_Config_h
#define hifi_Config_h
#include "InterfaceConfig.h"
#include <cstddef>
#include <cfloat>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cctype>
#include <stdint.h>
#include <new>
#include <vector>
#include <memory>
#include <algorithm>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_inverse.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/matrix_access.hpp>
#include <ProgramObject.h>
#include "AngleUtil.h"
#include "Radix2InplaceSort.h"
#include "Radix2IntegerScanner.h"
#include "FloodFill.h"
// Namespace configuration:
namespace starfield {
using glm::vec3;
using glm::vec4;
using glm::dot;
using glm::normalize;
using glm::mat4;
using glm::row;
using namespace std;
typedef uint32_t nuint;
typedef quint64 wuint;
}
#endif // hifi_Config_h

View file

@ -1,70 +0,0 @@
//
// Controller.cpp
// interface/src/starfield
//
// Created by Chris Barnard on 10/16/13.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QElapsedTimer>
#include "InterfaceLogging.h"
#include "starfield/Controller.h"
using namespace starfield;
bool Controller::computeStars(unsigned numStars, unsigned seed) {
QElapsedTimer startTime;
startTime.start();
Generator::computeStarPositions(_inputSequence, numStars, seed);
this->retile(numStars, _tileResolution);
double NSEC_TO_MSEC = 1.0 / 1000000.0;
double timeDiff = (double)startTime.nsecsElapsed() * NSEC_TO_MSEC;
qCDebug(interfaceapp) << "Total time to retile and generate stars: " << timeDiff << "msec";
return true;
}
bool Controller::setResolution(unsigned tileResolution) {
if (tileResolution <= 3) {
return false;
}
if (tileResolution != _tileResolution) {
this->retile(_numStars, tileResolution);
return true;
} else {
return false;
}
}
void Controller::render(float perspective, float angle, mat4 const& orientation, float alpha) {
Renderer* renderer = _renderer;
if (renderer != 0l) {
renderer->render(perspective, angle, orientation, alpha);
}
}
void Controller::retile(unsigned numStars, unsigned tileResolution) {
Tiling tiling(tileResolution);
VertexOrder scanner(tiling);
radix2InplaceSort(_inputSequence.begin(), _inputSequence.end(), scanner);
recreateRenderer(numStars, tileResolution);
_tileResolution = tileResolution;
}
void Controller::recreateRenderer(unsigned numStars, unsigned tileResolution) {
delete _renderer;
_renderer = new Renderer(_inputSequence, numStars, tileResolution);
}

View file

@ -1,44 +0,0 @@
//
// Controller.h
// interface/src/starfield
//
// Created by Tobias Schwinger on 3/29/13.
// Modified by Chris Barnard on 10/16/13.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_Controller_h
#define hifi_Controller_h
#include <time.h>
#include "starfield/Generator.h"
#include "starfield/data/InputVertex.h"
#include "starfield/renderer/Renderer.h"
#include "starfield/renderer/VertexOrder.h"
namespace starfield {
class Controller {
public:
Controller() : _tileResolution(20), _renderer(0l) { }
~Controller() { delete _renderer; }
bool computeStars(unsigned numStars, unsigned seed);
bool setResolution(unsigned tileResolution);
void render(float perspective, float angle, mat4 const& orientation, float alpha);
private:
void retile(unsigned numStars, unsigned tileResolution);
void recreateRenderer(unsigned numStars, unsigned tileResolution);
InputVertices _inputSequence;
unsigned _tileResolution;
unsigned _numStars;
Renderer* _renderer;
};
}
#endif // hifi_Controller_h

View file

@ -1,94 +0,0 @@
//
// Generator.cpp
// interface/src/starfield
//
// Created by Chris Barnard on 10/13/13.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QElapsedTimer>
#include "starfield/Generator.h"
using namespace starfield;
const float Generator::STAR_COLORIZATION = 0.1f;
const float PI_OVER_180 = 3.14159265358979f / 180.0f;
void Generator::computeStarPositions(InputVertices& destination, unsigned limit, unsigned seed) {
InputVertices* vertices = & destination;
//_limit = limit;
QElapsedTimer startTime;
startTime.start();
srand(seed);
vertices->clear();
vertices->reserve(limit);
const unsigned MILKY_WAY_WIDTH = 12.0; // width in degrees of one half of the Milky Way
const float MILKY_WAY_INCLINATION = 0.0f; // angle of Milky Way from horizontal in degrees
const float MILKY_WAY_RATIO = 0.4f;
const unsigned NUM_DEGREES = 360;
for(int star = 0; star < floor(limit * (1 - MILKY_WAY_RATIO)); ++star) {
float azimuth, altitude;
azimuth = (((float)rand() / (float) RAND_MAX) * NUM_DEGREES) - (NUM_DEGREES / 2);
altitude = (acos((2.0f * ((float)rand() / (float)RAND_MAX)) - 1.0f) / PI_OVER_180) + 90;
vertices->push_back(InputVertex(azimuth, altitude, computeStarColor(STAR_COLORIZATION)));
}
for(int star = 0; star < ceil(limit * MILKY_WAY_RATIO); ++star) {
float azimuth = ((float)rand() / (float) RAND_MAX) * NUM_DEGREES;
float altitude = powf(randFloat()*0.5f, 2.0f)/0.25f * MILKY_WAY_WIDTH;
if (randFloat() > 0.5f) {
altitude *= -1.0f;
}
// we need to rotate the Milky Way band to the correct orientation in the sky
// convert from spherical coordinates to cartesian, rotate the point and then convert back.
// An improvement would be to convert all stars to cartesian at this point and not have to convert back.
float tempX = sin(azimuth * PI_OVER_180) * cos(altitude * PI_OVER_180);
float tempY = sin(altitude * PI_OVER_180);
float tempZ = -cos(azimuth * PI_OVER_180) * cos(altitude * PI_OVER_180);
float xangle = MILKY_WAY_INCLINATION * PI_OVER_180;
float newX = (tempX * cos(xangle)) - (tempY * sin(xangle));
float newY = (tempX * sin(xangle)) + (tempY * cos(xangle));
float newZ = tempZ;
azimuth = (atan2(newX,-newZ) + Radians::pi()) / PI_OVER_180;
altitude = atan2(-newY, hypotf(newX, newZ)) / PI_OVER_180;
vertices->push_back(InputVertex(azimuth, altitude, computeStarColor(STAR_COLORIZATION)));
}
double timeDiff = (double)startTime.nsecsElapsed() / 1000000.0; // ns to ms
qDebug() << "Total time to generate stars: " << timeDiff << " msec";
}
// computeStarColor
// - Generate a star color.
//
// colorization can be a value between 0 and 1 specifying how colorful the resulting star color is.
//
// 0 = completely black & white
// 1 = very colorful
unsigned Generator::computeStarColor(float colorization) {
unsigned char red, green, blue;
if (randFloat() < 0.3f) {
// A few stars are colorful
red = 2 + (rand() % 254);
green = 2 + round((red * (1 - colorization)) + ((rand() % 254) * colorization));
blue = 2 + round((red * (1 - colorization)) + ((rand() % 254) * colorization));
} else {
// Most stars are dimmer and white
red = green = blue = 2 + (rand() % 128);
}
return red | (green << 8) | (blue << 16);
}

View file

@ -1,40 +0,0 @@
//
// Generator.h
// interface/src/starfield
//
// Created by Chris Barnard on 10/13/13.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_Generator_h
#define hifi_Generator_h
#include <locale.h>
#include <time.h>
#include "Config.h"
#include "SharedUtil.h"
#include "starfield/data/InputVertex.h"
namespace starfield {
class Generator {
public:
Generator() {}
~Generator() {}
static void computeStarPositions(InputVertices& destination, unsigned limit, unsigned seed);
static unsigned computeStarColor(float colorization);
private:
static const float STAR_COLORIZATION;
};
}
#endif // hifi_Generator_h

View file

@ -1,26 +0,0 @@
//
// GpuVertex.cpp
// interface/src/starfield/data
//
// Created by Chris Barnard on 10/17/13.
// Based on code by Tobias Schwinger on 3/29/13.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "starfield/data/GpuVertex.h"
using namespace starfield;
GpuVertex::GpuVertex(InputVertex const& inputVertex) {
_color = inputVertex.getColor();
float azimuth = inputVertex.getAzimuth();
float altitude = inputVertex.getAltitude();
// compute altitude/azimuth into X/Y/Z point on a sphere
_valX = sin(azimuth) * cos(altitude);
_valY = sin(altitude);
_valZ = -cos(azimuth) * cos(altitude);
}

View file

@ -1,37 +0,0 @@
//
// GpuVertex.h
// interface/src/starfield/data
//
// Created by Tobias Schwinger on 3/29/13.
// Modified by Chris Barnard on 10/17/13.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_GpuVertex_h
#define hifi_GpuVertex_h
#include "starfield/data/InputVertex.h"
namespace starfield {
class GpuVertex {
public:
GpuVertex() { }
GpuVertex(InputVertex const& inputVertex);
unsigned getColor() const { return _color; }
private:
unsigned _color;
float _valX;
float _valY;
float _valZ;
};
}
#endif // hifi_GpuVertex_h

View file

@ -1,27 +0,0 @@
//
// InputVertex.cpp
// interface/src/starfield/data
//
// Created by Chris Barnard on 10/17/13.
// Based on code by Tobias Schwinger 3/29/13.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "starfield/data/InputVertex.h"
using namespace starfield;
InputVertex::InputVertex(float azimuth, float altitude, unsigned color) {
_color = color | 0xff000000u;
azimuth = angleConvert<Degrees,Radians>(azimuth);
altitude = angleConvert<Degrees,Radians>(altitude);
angleHorizontalPolar<Radians>(azimuth, altitude);
_azimuth = azimuth;
_altitude = altitude;
}

View file

@ -1,39 +0,0 @@
//
// InputVertex.h
// interface/src/starfield/data
//
// Created by Tobias Schwinger on 3/29/13.
// Modified by Chris Barnard on 10/17/13.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_InputVertex_h
#define hifi_InputVertex_h
#include "starfield/Config.h"
namespace starfield {
class InputVertex {
public:
InputVertex(float azimuth, float altitude, unsigned color);
float getAzimuth() const { return _azimuth; }
float getAltitude() const { return _altitude; }
unsigned getColor() const { return _color; }
private:
unsigned _color;
float _azimuth;
float _altitude;
};
typedef std::vector<InputVertex> InputVertices;
}
#endif // hifi_InputVertex_h

View file

@ -1,32 +0,0 @@
//
// Tile.h
// interface/src/starfield/data
//
// Created by Tobias Schwinger on 3/22/13.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_Tile_h
#define hifi_Tile_h
#include "starfield/Config.h"
namespace starfield {
struct Tile {
nuint offset;
nuint count;
nuint flags;
// flags
static uint16_t const checked = 1;
static uint16_t const visited = 2;
static uint16_t const render = 4;
};
}
#endif // hifi_Tile_h

View file

@ -1,324 +0,0 @@
//
// Renderer.cpp
// interface/src/starfield/renderer
//
// Created by Chris Barnard on 10/17/13.
// Based on earlier work by Tobias Schwinger 3/22/13.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "starfield/renderer/Renderer.h"
#include "Application.h"
using namespace starfield;
Renderer::Renderer(InputVertices const& stars, unsigned numStars, unsigned tileResolution) : _dataArray(0l),
_tileArray(0l), _tiling(tileResolution) {
this->glAlloc();
Tiling tiling(tileResolution);
size_t numTiles = tiling.getTileCount();
// REVISIT: batch arrays are probably oversized, but - hey - they
// are not very large (unless for insane tiling) and we're better
// off safe than sorry
_dataArray = new GpuVertex[numStars];
_tileArray = new Tile[numTiles + 1];
_batchOffs = new GLint[numTiles * 2];
_batchCountArray = new GLsizei[numTiles * 2];
prepareVertexData(stars, numStars, tiling);
this->glUpload(numStars);
}
Renderer::~Renderer() {
delete[] _dataArray;
delete[] _tileArray;
delete[] _batchCountArray;
delete[] _batchOffs;
this->glFree();
}
void Renderer::render(float perspective, float aspect, mat4 const& orientation, float alpha) {
float halfPersp = perspective * 0.5f;
// cancel all translation
mat4 matrix = orientation;
matrix[3][0] = 0.0f;
matrix[3][1] = 0.0f;
matrix[3][2] = 0.0f;
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadMatrixf(glm::value_ptr(qApp->getDisplayViewFrustum()->getProjection()));
glMatrixMode(GL_MODELVIEW);
// extract local z vector
vec3 ahead = vec3(matrix[2]);
float azimuth = atan2(ahead.x,-ahead.z) + Radians::pi();
float altitude = atan2(-ahead.y, hypotf(ahead.x, ahead.z));
angleHorizontalPolar<Radians>(azimuth, altitude);
float const eps = 0.002f;
altitude = glm::clamp(altitude, -Radians::halfPi() + eps, Radians::halfPi() - eps);
matrix = glm::affineInverse(matrix);
this->_outIndexPos = (unsigned*) _batchOffs;
this->_wRowVec = -vec3(row(matrix, 2));
this->_halfPerspectiveAngle = halfPersp;
TileSelection::Cursor cursor;
cursor.current = _tileArray + _tiling.getTileIndex(azimuth, altitude);
cursor.firstInRow = _tileArray + _tiling.getTileIndex(0.0f, altitude);
floodFill(cursor, TileSelection(*this, _tileArray, _tileArray + _tiling.getTileCount(), (TileSelection::Cursor*) _batchCountArray));
this->glBatch(glm::value_ptr(matrix), prepareBatch((unsigned*) _batchOffs, _outIndexPos), alpha);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
// renderer construction
void Renderer::prepareVertexData(InputVertices const& vertices, unsigned numStars, Tiling const& tiling) {
size_t nTiles = tiling.getTileCount();
size_t vertexIndex = 0u, currTileIndex = 0u, count_active = 0u;
_tileArray[0].offset = 0u;
_tileArray[0].flags = 0u;
for (InputVertices::const_iterator i = vertices.begin(), e = vertices.end(); i != e; ++i) {
size_t tileIndex = tiling.getTileIndex(i->getAzimuth(), i->getAltitude());
assert(tileIndex >= currTileIndex);
// moved on to another tile? -> flush
if (tileIndex != currTileIndex) {
Tile* tile = _tileArray + currTileIndex;
Tile* lastTile = _tileArray + tileIndex;
// set count of active vertices (upcoming lod)
tile->count = count_active;
// generate skipped, empty tiles
for(size_t offset = vertexIndex; ++tile != lastTile ;) {
tile->offset = offset, tile->count = 0u, tile->flags = 0u;
}
// initialize next (as far as possible here)
lastTile->offset = vertexIndex;
lastTile->flags = 0u;
currTileIndex = tileIndex;
count_active = 0u;
}
++count_active;
// write converted vertex
_dataArray[vertexIndex++] = *i;
}
assert(vertexIndex == numStars);
// flush last tile (see above)
Tile* tile = _tileArray + currTileIndex;
tile->count = count_active;
for (Tile* e = _tileArray + nTiles + 1; ++tile != e;) {
tile->offset = vertexIndex, tile->count = 0u, tile->flags = 0;
}
}
bool Renderer::visitTile(Tile* tile) {
unsigned index = tile - _tileArray;
*_outIndexPos++ = index;
return isTileVisible(index);
}
bool Renderer::isTileVisible(unsigned index) {
float slice = _tiling.getSliceAngle();
float halfSlice = 0.5f * slice;
unsigned stride = _tiling.getAzimuthalTiles();
float azimuth = (index % stride) * slice;
float altitude = (index / stride) * slice - Radians::halfPi();
float groundX = sin(azimuth);
float groundZ = -cos(azimuth);
float elevation = cos(altitude);
vec3 tileCenter = vec3(groundX * elevation, sin(altitude), groundZ * elevation);
float w = dot(_wRowVec, tileCenter);
float daz = halfSlice * cos(std::max(0.0f, abs(altitude) - halfSlice));
float dal = halfSlice;
float adjustedNear = cos(_halfPerspectiveAngle + sqrt(daz * daz + dal * dal));
return w >= adjustedNear;
}
unsigned Renderer::prepareBatch(unsigned const* indices, unsigned const* indicesEnd) {
unsigned nRanges = 0u;
GLint* offs = _batchOffs;
GLsizei* count = _batchCountArray;
for (unsigned* i = (unsigned*) _batchOffs; i != indicesEnd; ++i) {
Tile* t = _tileArray + *i;
if ((t->flags & Tile::render) > 0u && t->count > 0u) {
*offs++ = t->offset;
*count++ = t->count;
++nRanges;
}
t->flags = 0;
}
return nRanges;
}
// GL API handling
void Renderer::glAlloc() {
GLchar const* const VERTEX_SHADER =
"#version 120\n"
"uniform float alpha;\n"
"void main(void) {\n"
" vec3 c = gl_Color.rgb * 1.22;\n"
" float s = min(max(tan((c.r + c.g + c.b) / 3), 1.0), 3.0);\n"
" gl_Position = ftransform();\n"
" gl_FrontColor= gl_Color * alpha * 1.5;\n"
" gl_PointSize = s;\n"
"}\n";
_program.addShaderFromSourceCode(QGLShader::Vertex, VERTEX_SHADER);
GLchar const* const FRAGMENT_SHADER =
"#version 120\n"
"void main(void) {\n"
" gl_FragColor = gl_Color;\n"
"}\n";
_program.addShaderFromSourceCode(QGLShader::Fragment, FRAGMENT_SHADER);
_program.link();
_alphaLocationHandle = _program.uniformLocation("alpha");
glGenBuffersARB(1, & _vertexArrayHandle);
}
void Renderer::glFree() {
glDeleteBuffersARB(1, & _vertexArrayHandle);
}
void Renderer::glUpload(GLsizei numStars) {
glBindBufferARB(GL_ARRAY_BUFFER, _vertexArrayHandle);
glBufferData(GL_ARRAY_BUFFER, numStars * sizeof(GpuVertex), _dataArray, GL_STATIC_DRAW);
glBindBufferARB(GL_ARRAY_BUFFER, 0);
}
void Renderer::glBatch(GLfloat const* matrix, GLsizei n_ranges, float alpha) {
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glEnable(GL_BLEND);
// setup modelview matrix
glPushMatrix();
glLoadMatrixf(matrix);
// set point size and smoothing + shader control
glPointSize(1.0f);
glEnable(GL_POINT_SMOOTH);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
// select shader and vertex array
_program.bind();
_program.setUniformValue(_alphaLocationHandle, alpha);
glBindBufferARB(GL_ARRAY_BUFFER, _vertexArrayHandle);
glInterleavedArrays(GL_C4UB_V3F, sizeof(GpuVertex), 0l);
// render
glMultiDrawArrays(GL_POINTS, _batchOffs, _batchCountArray, n_ranges);
// restore state
glBindBufferARB(GL_ARRAY_BUFFER, 0);
_program.release();
glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
glDisable(GL_POINT_SMOOTH);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glPopMatrix();
}
// flood fill strategy
bool Renderer::TileSelection::select(Renderer::TileSelection::Cursor const& cursor) {
Tile* tile = cursor.current;
if (tile < _tileArray || tile >= _tilesEnd || !! (tile->flags & Tile::checked)) {
// out of bounds or been here already
return false;
}
// will check now and never again
tile->flags |= Tile::checked;
if (_rendererRef.visitTile(tile)) {
// good one -> remember (for batching) and propagate
tile->flags |= Tile::render;
return true;
}
return false;
}
bool Renderer::TileSelection::process(Renderer::TileSelection::Cursor const& cursor) {
Tile* tile = cursor.current;
if (! (tile->flags & Tile::visited)) {
tile->flags |= Tile::visited;
return true;
}
return false;
}
void Renderer::TileSelection::right(Renderer::TileSelection::Cursor& cursor) const {
cursor.current += 1;
if (cursor.current == cursor.firstInRow + _rendererRef._tiling.getAzimuthalTiles()) {
cursor.current = cursor.firstInRow;
}
}
void Renderer::TileSelection::left(Renderer::TileSelection::Cursor& cursor) const {
if (cursor.current == cursor.firstInRow) {
cursor.current = cursor.firstInRow + _rendererRef._tiling.getAzimuthalTiles();
}
cursor.current -= 1;
}
void Renderer::TileSelection::up(Renderer::TileSelection::Cursor& cursor) const {
unsigned numTiles = _rendererRef._tiling.getAzimuthalTiles();
cursor.current += numTiles;
cursor.firstInRow += numTiles;
}
void Renderer::TileSelection::down(Renderer::TileSelection::Cursor& cursor) const {
unsigned numTiles = _rendererRef._tiling.getAzimuthalTiles();
cursor.current -= numTiles;
cursor.firstInRow -= numTiles;
}
void Renderer::TileSelection::defer(Renderer::TileSelection::Cursor const& cursor) {
*_stackPos++ = cursor;
}
bool Renderer::TileSelection::deferred(Renderer::TileSelection::Cursor& cursor) {
if (_stackPos != _stackArray) {
cursor = *--_stackPos;
return true;
}
return false;
}

View file

@ -1,142 +0,0 @@
//
// Renderer.h
// interface/src/starfield/renderer
//
// Created by Tobias Schwinger on 3/22/13.
// Modified by Chris Barnard on 10/17/13.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_Renderer_h
#define hifi_Renderer_h
#include "starfield/Config.h"
#include "starfield/data/InputVertex.h"
#include "starfield/data/Tile.h"
#include "starfield/data/GpuVertex.h"
#include "starfield/renderer/Tiling.h"
//
// FOV culling
// ===========
//
// As stars can be thought of as at infinity distance, the field of view only
// depends on perspective and rotation:
//
// _----_ <-- visible stars
// from above +-near-+ - -
// \ / |
// near width: \ / | cos(p/2)
// 2sin(p/2) \/ _
// center
//
//
// Now it is important to note that a change in altitude maps uniformly to a
// distance on a sphere. This is NOT the case for azimuthal angles: In this
// case a factor of 'cos(alt)' (the orbital radius) applies:
//
//
// |<-cos alt ->| | |<-|<----->|->| d_azi cos(alt)
// |
// __--* | --------- -
// __-- * | | | ^ d_alt
// __-- alt) * | | | v
// --------------*- | ------------- -
// |
// side view | tile on sphere
//
//
// This lets us find a worst-case (Eigen) angle from the center to the edge
// of a tile as
//
// hypot( 0.5 d_alt, 0.5 d_azi cos(alt_absmin) ).
//
// This angle must be added to 'p' (the perspective angle) in order to find
// an altered near plane for the culling decision.
//
namespace starfield {
class Renderer {
public:
Renderer(InputVertices const& src, unsigned numStars, unsigned tileResolution);
~Renderer();
void render(float perspective, float aspect, mat4 const& orientation, float alpha);
private:
// renderer construction
void prepareVertexData(InputVertices const& vertices, unsigned numStars, Tiling const& tiling);
// FOV culling / LOD
class TileSelection;
friend class Renderer::TileSelection;
class TileSelection {
public:
struct Cursor { Tile* current, * firstInRow; };
private:
Renderer& _rendererRef;
Cursor* const _stackArray;
Cursor* _stackPos;
Tile const* const _tileArray;
Tile const* const _tilesEnd;
public:
TileSelection(Renderer& renderer, Tile const* tiles, Tile const* tiles_end, Cursor* stack) :
_rendererRef(renderer),
_stackArray(stack),
_stackPos(stack),
_tileArray(tiles),
_tilesEnd(tiles_end) { }
protected:
bool select(Cursor const& cursor);
bool process(Cursor const& cursor);
void right(Cursor& cursor) const;
void left(Cursor& cursor) const;
void up(Cursor& cursor) const;
void down(Cursor& cursor) const;
void defer(Cursor const& cursor);
bool deferred(Cursor& cursor);
};
bool visitTile(Tile* tile);
bool isTileVisible(unsigned index);
unsigned prepareBatch(unsigned const* indices, unsigned const* indicesEnd);
// GL API handling
void glAlloc();
void glFree();
void glUpload(GLsizei numStars);
void glBatch(GLfloat const* matrix, GLsizei n_ranges, float alpha);
// variables
GpuVertex* _dataArray;
Tile* _tileArray;
GLint* _batchOffs;
GLsizei* _batchCountArray;
GLuint _vertexArrayHandle;
ProgramObject _program;
int _alphaLocationHandle;
Tiling _tiling;
unsigned* _outIndexPos;
vec3 _wRowVec;
float _halfPerspectiveAngle;
};
}
#endif // hifi_Renderer_h

View file

@ -1,48 +0,0 @@
//
// Tiling.h
// interface/src/starfield/renderer
//
// Created by Tobias Schwinger on 3/22/13.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_Tiling_h
#define hifi_Tiling_h
#include "starfield/Config.h"
namespace starfield {
const float LOG2 = 1.4426950408889634f;
class Tiling {
public:
Tiling(unsigned tileResolution) : _tileResolution(tileResolution), _rcpSlice(tileResolution / Radians::twicePi()) {
_nBits = ceil(log((float)getTileCount()) * LOG2); }
unsigned getAzimuthalTiles() const { return _tileResolution; }
unsigned getAltitudinalTiles() const { return _tileResolution / 2 + 1; }
unsigned getTileIndexBits() const { return _nBits; }
unsigned getTileCount() const { return getAzimuthalTiles() * getAltitudinalTiles(); }
unsigned getTileIndex(float azimuth, float altitude) const { return discreteAzimuth(azimuth) +
_tileResolution * discreteAltitude(altitude); }
float getSliceAngle() const { return 1.0f / _rcpSlice; }
private:
unsigned discreteAngle(float unsigned_angle) const { return unsigned(floor(unsigned_angle * _rcpSlice + 0.5f)); }
unsigned discreteAzimuth(float angle) const { return discreteAngle(angle) % _tileResolution; }
unsigned discreteAltitude(float angle) const { return min( getAltitudinalTiles() - 1,
discreteAngle(angle + Radians::halfPi()) ); }
// variables
unsigned _tileResolution;
float _rcpSlice;
unsigned _nBits;
};
}
#endif // hifi_Tiling_h

View file

@ -1,20 +0,0 @@
//
// VertexOrder.cpp
// interface/src/starfield/renderer
//
// Created by Chris Barnard on 10/17/13.
// Based on code by Tobias Schwinger on 3/22/13.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "starfield/renderer/VertexOrder.h"
using namespace starfield;
bool VertexOrder::bit(InputVertex const& vertex, state_type const& state) const {
unsigned key = _tiling.getTileIndex(vertex.getAzimuth(), vertex.getAltitude());
return base::bit(key, state);
}

View file

@ -1,41 +0,0 @@
//
// VertexOrder.h
// interface/src/starfield/renderer
//
// Created by Tobias Schwinger on 3/22/13.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_VertexOrder_h
#define hifi_VertexOrder_h
#include "starfield/Config.h"
#include "starfield/data/InputVertex.h"
#include "starfield/renderer/Tiling.h"
namespace starfield {
// Defines the vertex order for the renderer as a bit extractor for
//binary in-place Radix Sort.
class VertexOrder : public Radix2IntegerScanner<unsigned>
{
public:
explicit VertexOrder(Tiling const& tiling) :
base(tiling.getTileIndexBits()), _tiling(tiling) { }
bool bit(InputVertex const& vertex, state_type const& state) const;
private:
Tiling _tiling;
typedef Radix2IntegerScanner<unsigned> base;
};
} // anonymous namespace
#endif // hifi_VertexOrder_h

View file

@ -9,14 +9,13 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "InterfaceConfig.h"
#include "ApplicationCompositor.h"
#include <glm/gtc/type_ptr.hpp>
#include <avatar/AvatarManager.h>
#include <gpu/GLBackend.h>
#include <NumericalConstants.h>
#include "CursorManager.h"
#include "Tooltip.h"
@ -191,8 +190,8 @@ void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) {
return;
}
GLuint texture = qApp->getApplicationOverlay().getOverlayTexture();
if (!texture) {
gpu::FramebufferPointer overlayFramebuffer = qApp->getApplicationOverlay().getOverlayFramebuffer();
if (!overlayFramebuffer) {
return;
}
@ -203,6 +202,7 @@ void ApplicationCompositor::displayOverlayTexture(RenderArgs* renderArgs) {
//Handle fading and deactivation/activation of UI
gpu::Batch batch;
renderArgs->_context->syncCache();
auto geometryCache = DependencyManager::get<GeometryCache>();
geometryCache->useSimpleDrawPipeline(batch);
@ -210,9 +210,7 @@ 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.setResourceTexture(0, overlayFramebuffer->getRenderBuffer(0));
geometryCache->renderUnitQuad(batch, vec4(vec3(1), _alpha));
// Doesn't actually render
@ -259,8 +257,8 @@ void ApplicationCompositor::displayOverlayTextureHmd(RenderArgs* renderArgs, int
return;
}
GLuint texture = qApp->getApplicationOverlay().getOverlayTexture();
if (!texture) {
gpu::FramebufferPointer overlayFramebuffer = qApp->getApplicationOverlay().getOverlayFramebuffer();
if (!overlayFramebuffer) {
return;
}
@ -276,9 +274,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));
@ -501,8 +502,8 @@ void ApplicationCompositor::renderControllerPointers(gpu::Batch& batch) {
glm::vec3 direction = glm::inverse(myAvatar->getOrientation()) * palmData->getFingerDirection();
// Get the angles, scaled between (-0.5,0.5)
float xAngle = (atan2(direction.z, direction.x) + M_PI_2);
float yAngle = 0.5f - ((atan2f(direction.z, direction.y) + (float)M_PI_2));
float xAngle = (atan2(direction.z, direction.x) + PI_OVER_TWO);
float yAngle = 0.5f - ((atan2f(direction.z, direction.y) + (float)PI_OVER_TWO));
// Get the pixel range over which the xAngle and yAngle are scaled
float cursorRange = canvasSize.x * InputDevice::getCursorPixelRangeMult();

View file

@ -62,7 +62,7 @@ public:
glm::vec2 screenToOverlay(const glm::vec2 & screenPos) const;
glm::vec2 overlayToScreen(const glm::vec2 & overlayPos) const;
void computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const;
GLuint getOverlayTexture() const;
uint32_t getOverlayTexture() const;
static glm::vec2 directionToSpherical(const glm::vec3 & direction);
static glm::vec3 sphericalToDirection(const glm::vec2 & sphericalPos);

View file

@ -9,11 +9,6 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "InterfaceConfig.h"
#include <QOpenGLFramebufferObject>
#include <QOpenGLTexture>
#include <glm/gtc/type_ptr.hpp>
#include <avatar/AvatarManager.h>
@ -40,12 +35,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<GeometryCache>();
@ -60,7 +49,6 @@ ApplicationOverlay::ApplicationOverlay()
connect(offscreenUi.data(), &OffscreenUi::textureUpdated, this, [&](GLuint textureId) {
auto offscreenUi = DependencyManager::get<OffscreenUi>();
offscreenUi->lockTexture(textureId);
assert(!glGetError());
std::swap(_uiTexture, textureId);
if (textureId) {
offscreenUi->releaseTexture(textureId);
@ -82,63 +70,97 @@ 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
_overlayFramebuffer->bind();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
fboViewport(_overlayFramebuffer);
gpu::Batch batch;
renderArgs->_batch = &batch;
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
renderOverlays(renderArgs);
renderStatsAndLogs(renderArgs);
renderDomainConnectionStatusBorder(renderArgs);
renderQmlUi(renderArgs);
_overlayFramebuffer->release();
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
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();
}
void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) {
PROFILE_RANGE(__FUNCTION__);
if (_uiTexture) {
gpu::Batch batch;
gpu::Batch& batch = *renderArgs->_batch;
auto geometryCache = DependencyManager::get<GeometryCache>();
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);
}
}
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) {
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);
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();
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 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);
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) {
@ -148,6 +170,7 @@ void ApplicationOverlay::renderRearView(RenderArgs* renderArgs) {
}
void ApplicationOverlay::renderStatsAndLogs(RenderArgs* renderArgs) {
// Display stats and log text onscreen
// Determine whether to compute timing details
@ -182,7 +205,7 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder(RenderArgs* renderAr
});
auto nodeList = DependencyManager::get<NodeList>();
if (nodeList && !nodeList->getDomainHandler().isConnected()) {
gpu::Batch batch;
gpu::Batch& batch = *renderArgs->_batch;
auto geometryCache = DependencyManager::get<GeometryCache>();
geometryCache->useSimpleDrawPipeline(batch);
batch.setProjectionTransform(mat4());
@ -197,37 +220,40 @@ 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);
}
}
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 = new QOpenGLFramebufferObject(fboSize, QOpenGLFramebufferObject::Depth);
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);
_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_LINEAR);
_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);
}

View file

@ -25,7 +25,8 @@ public:
~ApplicationOverlay();
void renderOverlay(RenderArgs* renderArgs);
GLuint getOverlayTexture();
gpu::FramebufferPointer getOverlayFramebuffer() const { return _overlayFramebuffer; }
private:
void renderStatsAndLogs(RenderArgs* renderArgs);
@ -33,18 +34,23 @@ private:
void renderRearViewToFbo(RenderArgs* renderArgs);
void renderRearView(RenderArgs* renderArgs);
void renderQmlUi(RenderArgs* renderArgs);
void renderAudioScope(RenderArgs* renderArgs);
void renderOverlays(RenderArgs* renderArgs);
void buildFramebufferObject();
float _alpha{ 1.0f };
float _trailingAudioLoudness{ 0.0f };
GLuint _uiTexture{ 0 };
uint32_t _uiTexture{ 0 };
int _domainStatusBorder;
int _magnifierBorder;
ivec2 _previousBorderSize{ -1 };
QOpenGLFramebufferObject* _overlayFramebuffer{ nullptr };
gpu::TexturePointer _overlayDepthTexture;
gpu::TexturePointer _overlayColorTexture;
gpu::FramebufferPointer _overlayFramebuffer;
};
#endif // hifi_ApplicationOverlay_h

View file

@ -0,0 +1,268 @@
//
// AudioStatsDialog.cpp
// interface/src/ui
//
// Created by Bridget Went on 7/9/15.
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "AudioStatsDialog.h"
#include <cstdio>
#include <AudioClient.h>
#include <AudioConstants.h>
#include <AudioIOStats.h>
#include <DependencyManager.h>
#include <GeometryCache.h>
#include <NodeList.h>
#include <Util.h>
const unsigned COLOR0 = 0x33cc99ff;
const unsigned COLOR1 = 0xffef40c0;
const unsigned COLOR2 = 0xd0d0d0a0;
const unsigned COLOR3 = 0x01DD7880;
AudioStatsDisplay::AudioStatsDisplay(QFormLayout* form,
QString text, unsigned colorRGBA) :
_text(text),
_colorRGBA(colorRGBA)
{
_label = new QLabel();
_label->setAlignment(Qt::AlignCenter);
QPalette palette = _label->palette();
unsigned rgb = colorRGBA >> 8;
rgb = ((rgb & 0xfefefeu) >> 1) + ((rgb & 0xf8f8f8) >> 3);
palette.setColor(QPalette::WindowText, QColor::fromRgb(rgb));
_label->setPalette(palette);
form->addRow(_label);
}
void AudioStatsDisplay::paint() {
_label->setText(_strBuf);
}
void AudioStatsDisplay::updatedDisplay(QString str) {
_strBuf = str;
}
AudioStatsDialog::AudioStatsDialog(QWidget* parent) :
QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint) {
_shouldShowInjectedStreams = false;
setWindowTitle("Audio Network Statistics");
// Get statistics from the Audio Client
_stats = &DependencyManager::get<AudioClient>()->getStats();
// Create layouter
_form = new QFormLayout();
QDialog::setLayout(_form);
// Load and initilize all channels
renderStats();
_audioDisplayChannels = QVector<QVector<AudioStatsDisplay*>>(1);
_audioMixerID = addChannel(_form, _audioMixerStats, COLOR0);
_upstreamClientID = addChannel(_form, _upstreamClientStats, COLOR1);
_upstreamMixerID = addChannel(_form, _upstreamMixerStats, COLOR2);
_downstreamID = addChannel(_form, _downstreamStats, COLOR3);
_upstreamInjectedID = addChannel(_form, _upstreamInjectedStats, COLOR0);
connect(averageUpdateTimer, SIGNAL(timeout()), this, SLOT(updateTimerTimeout()));
averageUpdateTimer->start(1000);
}
int AudioStatsDialog::addChannel(QFormLayout* form, QVector<QString>& stats, const unsigned color) {
int channelID = _audioDisplayChannels.size() - 1;
for (int i = 0; i < stats.size(); i++)
// Create new display label
_audioDisplayChannels[channelID].push_back(new AudioStatsDisplay(form, stats.at(i), color));
// Expand vector to fit next channel
_audioDisplayChannels.resize(_audioDisplayChannels.size() + 1);
return channelID;
}
void AudioStatsDialog::updateStats(QVector<QString>& stats, int channelID) {
// Update all stat displays at specified channel
for (int i = 0; i < stats.size(); i++)
_audioDisplayChannels[channelID].at(i)->updatedDisplay(stats.at(i));
}
void AudioStatsDialog::renderStats() {
// Clear current stats from all vectors
clearAllChannels();
double audioInputBufferLatency = 0.0,
inputRingBufferLatency = 0.0,
networkRoundtripLatency = 0.0,
mixerRingBufferLatency = 0.0,
outputRingBufferLatency = 0.0,
audioOutputBufferLatency = 0.0;
AudioStreamStats downstreamAudioStreamStats = _stats->getMixerDownstreamStats();
SharedNodePointer audioMixerNodePointer = DependencyManager::get<NodeList>()->soloNodeOfType(NodeType::AudioMixer);
if (!audioMixerNodePointer.isNull()) {
audioInputBufferLatency = (double)_stats->getAudioInputMsecsReadStats().getWindowAverage();
inputRingBufferLatency = (double)_stats->getInputRungBufferMsecsAvailableStats().getWindowAverage();
networkRoundtripLatency = (double) audioMixerNodePointer->getPingMs();
mixerRingBufferLatency = (double)_stats->getMixerAvatarStreamStats()._framesAvailableAverage * AudioConstants::NETWORK_FRAME_MSECS;
outputRingBufferLatency = (double)downstreamAudioStreamStats._framesAvailableAverage * AudioConstants::NETWORK_FRAME_MSECS;
audioOutputBufferLatency = (double)_stats->getAudioOutputMsecsUnplayedStats().getWindowAverage();
}
double totalLatency = audioInputBufferLatency + inputRingBufferLatency + networkRoundtripLatency + mixerRingBufferLatency
+ outputRingBufferLatency + audioOutputBufferLatency;
_audioMixerStats.push_back(QString("Audio input buffer: %1ms").arg(
QString::number(audioInputBufferLatency, 'f', 2)) + QString(" - avg msecs of samples read to the audio input buffer in last 10s"));
_audioMixerStats.push_back(QString("Input ring buffer: %1ms").arg(
QString::number(inputRingBufferLatency, 'f', 2)) + QString(" - avg msecs of samples read to the input ring buffer in last 10s"));
_audioMixerStats.push_back(QString("Network to mixer: %1ms").arg(
QString::number((networkRoundtripLatency / 2.0), 'f', 2)) + QString(" - half of last ping value calculated by the node list"));
_audioMixerStats.push_back(QString("Network to client: %1ms").arg(
QString::number((mixerRingBufferLatency / 2.0),'f', 2)) + QString(" - half of last ping value calculated by the node list"));
_audioMixerStats.push_back(QString("Output ring buffer: %1ms").arg(
QString::number(outputRingBufferLatency,'f', 2)) + QString(" - avg msecs of samples in output ring buffer in last 10s"));
_audioMixerStats.push_back(QString("Audio output buffer: %1ms").arg(
QString::number(mixerRingBufferLatency,'f', 2)) + QString(" - avg msecs of samples in audio output buffer in last 10s"));
_audioMixerStats.push_back(QString("TOTAL: %1ms").arg(
QString::number(totalLatency, 'f', 2)) +QString(" - avg msecs of samples in audio output buffer in last 10s"));
const MovingMinMaxAvg<quint64>& packetSentTimeGaps = _stats->getPacketSentTimeGaps();
_upstreamClientStats.push_back(
QString("\nUpstream Mic Audio Packets Sent Gaps (by client):"));
_upstreamClientStats.push_back(
QString("Inter-packet timegaps (overall) | min: %1, max: %2, avg: %3").arg(formatUsecTime(packetSentTimeGaps.getMin()).toLatin1().data()).arg(formatUsecTime( packetSentTimeGaps.getMax()).toLatin1().data()).arg(formatUsecTime( packetSentTimeGaps.getAverage()).toLatin1().data()));
_upstreamClientStats.push_back(
QString("Inter-packet timegaps (last 30s) | min: %1, max: %2, avg: %3").arg(formatUsecTime(packetSentTimeGaps.getWindowMin()).toLatin1().data()).arg(formatUsecTime(packetSentTimeGaps.getWindowMax()).toLatin1().data()).arg(formatUsecTime(packetSentTimeGaps.getWindowAverage()).toLatin1().data()));
_upstreamMixerStats.push_back(QString("\nUpstream mic audio stats (received and reported by audio-mixer):"));
renderAudioStreamStats(&_stats->getMixerAvatarStreamStats(), &_upstreamMixerStats, true);
_downstreamStats.push_back(QString("\nDownstream mixed audio stats:"));
AudioStreamStats downstreamStats = _stats->getMixerDownstreamStats();
renderAudioStreamStats(&downstreamStats, &_downstreamStats, true);
if (_shouldShowInjectedStreams) {
foreach(const AudioStreamStats& injectedStreamAudioStats, _stats->getMixerInjectedStreamStatsMap()) {
_upstreamInjectedStats.push_back(QString("\nUpstream injected audio stats: stream ID: %1").arg( injectedStreamAudioStats._streamIdentifier.toString().toLatin1().data()));
renderAudioStreamStats(&injectedStreamAudioStats, &_upstreamInjectedStats, true);
}
}
}
void AudioStatsDialog::renderAudioStreamStats(const AudioStreamStats* streamStats, QVector<QString>* audioStreamStats, bool isDownstreamStats) {
audioStreamStats->push_back(
QString("Packet loss | overall: %1% (%2 lost), last_30s: %3% (%4 lost)").arg(QString::number((int)(streamStats->_packetStreamStats.getLostRate() * 100.0f))).arg(QString::number((int)(streamStats->_packetStreamStats._lost))).arg(QString::number((int)(streamStats->_packetStreamWindowStats.getLostRate() * 100.0f))).arg(QString::number((int)(streamStats->_packetStreamWindowStats._lost)))
);
if (isDownstreamStats) {
audioStreamStats->push_back(
QString("Ringbuffer frames | desired: %1, avg_available(10s): %2 + %3, available: %4+%5").arg(QString::number(streamStats->_desiredJitterBufferFrames)).arg(QString::number(streamStats->_framesAvailableAverage)).arg(QString::number((int)((float)_stats->getAudioInputMsecsReadStats().getWindowAverage() / AudioConstants::NETWORK_FRAME_MSECS))).arg(QString::number(streamStats->_framesAvailable)).arg(QString::number((int)(_stats->getAudioOutputMsecsUnplayedStats().getCurrentIntervalLastSample() / AudioConstants::NETWORK_FRAME_MSECS))));
} else {
audioStreamStats->push_back(
QString("Ringbuffer frames | desired: %1, avg_available(10s): %2, available: %3").arg(QString::number(streamStats->_desiredJitterBufferFrames)).arg(QString::number(streamStats->_framesAvailableAverage)).arg(QString::number(streamStats->_framesAvailable)));
}
audioStreamStats->push_back(
QString("Ringbuffer stats | starves: %1, prev_starve_lasted: %2, frames_dropped: %3, overflows: %4").arg(QString::number(streamStats->_starveCount)).arg(QString::number(streamStats->_consecutiveNotMixedCount)).arg(QString::number(streamStats->_framesDropped)).arg(QString::number(streamStats->_overflowCount)));
audioStreamStats->push_back(
QString("Inter-packet timegaps (overall) | min: %1, max: %2, avg: %3").arg(formatUsecTime(streamStats->_timeGapMin).toLatin1().data()).arg(formatUsecTime(streamStats->_timeGapMax).toLatin1().data()).arg(formatUsecTime(streamStats->_timeGapAverage).toLatin1().data()));
audioStreamStats->push_back(
QString("Inter-packet timegaps (last 30s) | min: %1, max: %2, avg: %3").arg(formatUsecTime(streamStats->_timeGapWindowMin).toLatin1().data()).arg(formatUsecTime(streamStats->_timeGapWindowMax).toLatin1().data()).arg(QString::number(streamStats->_timeGapWindowAverage).toLatin1().data()));
}
void AudioStatsDialog::clearAllChannels() {
_audioMixerStats.clear();
_upstreamClientStats.clear();
_upstreamMixerStats.clear();
_downstreamStats.clear();
_upstreamInjectedStats.clear();
}
void AudioStatsDialog::updateTimerTimeout() {
renderStats();
// Update all audio stats
updateStats(_audioMixerStats, _audioMixerID);
updateStats(_upstreamClientStats, _upstreamClientID);
updateStats(_upstreamMixerStats, _upstreamMixerID);
updateStats(_downstreamStats, _downstreamID);
updateStats(_upstreamInjectedStats, _upstreamInjectedID);
}
void AudioStatsDialog::paintEvent(QPaintEvent* event) {
// Repaint each stat in each channel
for (int i = 0; i < _audioDisplayChannels.size(); i++) {
for(int j = 0; j < _audioDisplayChannels[i].size(); j++) {
_audioDisplayChannels[i].at(j)->paint();
}
}
QDialog::paintEvent(event);
setFixedSize(width(), height());
}
void AudioStatsDialog::reject() {
// Just regularly close upon ESC
QDialog::close();
}
void AudioStatsDialog::closeEvent(QCloseEvent* event) {
QDialog::closeEvent(event);
emit closed();
}
AudioStatsDialog::~AudioStatsDialog() {
clearAllChannels();
for (int i = 0; i < _audioDisplayChannels.size(); i++) {
_audioDisplayChannels[i].clear();
for(int j = 0; j < _audioDisplayChannels[i].size(); j++) {
delete _audioDisplayChannels[i].at(j);
}
}
}

View file

@ -0,0 +1,113 @@
//
// AudioStatsDialog.h
// hifi
//
// Created by Bridget Went on 7/9/15.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef __hifi__AudioStatsDialog__
#define __hifi__AudioStatsDialog__
#include <stdio.h>
#include <QDialog>
#include <QLabel>
#include <QFormLayout>
#include <QVector>
#include <QTimer>
#include <QString>
#include <QObject>
#include <DependencyManager.h>
class AudioIOStats;
class AudioStreamStats;
//display
class AudioStatsDisplay : public QObject, public Dependency {
Q_OBJECT
SINGLETON_DEPENDENCY
public:
AudioStatsDisplay(QFormLayout* form, QString text, unsigned colorRGBA);
void updatedDisplay(QString str);
void paint();
private:
QString _strBuf;
QLabel* _label;
QString _text;
unsigned _colorRGBA;
};
//dialog
class AudioStatsDialog : public QDialog {
Q_OBJECT
public:
AudioStatsDialog(QWidget* parent);
~AudioStatsDialog();
void paintEvent(QPaintEvent*);
private:
// audio stats methods for rendering
QVector<QString> _audioMixerStats;
QVector<QString> _upstreamClientStats;
QVector<QString> _upstreamMixerStats;
QVector<QString> _downstreamStats;
QVector<QString> _upstreamInjectedStats;
int _audioMixerID;
int _upstreamClientID;
int _upstreamMixerID;
int _downstreamID;
int _upstreamInjectedID;
QVector<QVector<AudioStatsDisplay*>> _audioDisplayChannels;
int addChannel(QFormLayout* form, QVector<QString>& stats, const unsigned color);
void updateStats(QVector<QString>& stats, const int channelID);
void renderStats();
void clearAllChannels();
void renderAudioStreamStats(const AudioStreamStats* streamStats, QVector<QString>* audioStreamstats, bool isDownstreamStats);
const AudioIOStats* _stats;
QFormLayout* _form;
bool _isEnabled;
bool _shouldShowInjectedStreams;
signals:
void closed();
public slots:
void reject();
void updateTimerTimeout();
protected:
// Emits a 'closed' signal when this dialog is closed.
void closeEvent(QCloseEvent*);
private:
QTimer* averageUpdateTimer = new QTimer(this);
};
#endif /* defined(__hifi__AudioStatsDialog__) */

View file

@ -57,11 +57,6 @@ void DialogsManager::showUpdateDialog() {
void DialogsManager::octreeStatsDetails() {
if (!_octreeStatsDialog) {
_octreeStatsDialog = new OctreeStatsDialog(qApp->getWindow(), qApp->getOcteeSceneStats());
#if 0
if (_hmdToolsDialog) {
_hmdToolsDialog->watchWindow(_octreeStatsDialog->windowHandle());
}
#endif
connect(_octreeStatsDialog, SIGNAL(closed()), _octreeStatsDialog, SLOT(deleteLater()));
_octreeStatsDialog->show();
}
@ -114,15 +109,20 @@ void DialogsManager::editAnimations() {
}
}
void DialogsManager::audioStatsDetails() {
if (! _audioStatsDialog) {
_audioStatsDialog = new AudioStatsDialog(qApp->getWindow());
connect(_audioStatsDialog, SIGNAL(closed()), _audioStatsDialog, SLOT(deleteLater()));
_audioStatsDialog->show();
}
_audioStatsDialog->raise();
}
void DialogsManager::bandwidthDetails() {
if (! _bandwidthDialog) {
_bandwidthDialog = new BandwidthDialog(qApp->getWindow());
connect(_bandwidthDialog, SIGNAL(closed()), _bandwidthDialog, SLOT(deleteLater()));
#if 0
if (_hmdToolsDialog) {
_hmdToolsDialog->watchWindow(_bandwidthDialog->windowHandle());
}
#endif
_bandwidthDialog->show();
}
_bandwidthDialog->raise();
@ -143,29 +143,6 @@ void DialogsManager::toggleToolWindow() {
toolWindow->setVisible(!toolWindow->isVisible());
}
void DialogsManager::hmdTools(bool showTools) {
#if 0
if (showTools) {
if (!_hmdToolsDialog) {
maybeCreateDialog(_hmdToolsDialog);
connect(_hmdToolsDialog, SIGNAL(closed()), SLOT(hmdToolsClosed()));
}
_hmdToolsDialog->show();
_hmdToolsDialog->raise();
} else {
hmdToolsClosed();
}
qApp->getWindow()->activateWindow();
#endif
}
void DialogsManager::hmdToolsClosed() {
#if 0
Menu::getInstance()->getActionForOption(MenuOption::HMDTools)->setChecked(false);
_hmdToolsDialog->hide();
#endif
}
void DialogsManager::showScriptEditor() {
maybeCreateDialog(_scriptEditor);
_scriptEditor->show();

View file

@ -22,6 +22,7 @@ class QAction;
class AddressBarDialog;
class AnimationsDialog;
class AttachmentsDialog;
class AudioStatsDialog;
class BandwidthDialog;
class CachesSizeDialog;
class DiskCacheEditor;
@ -40,8 +41,8 @@ class DialogsManager : public QObject, public Dependency {
SINGLETON_DEPENDENCY
public:
QPointer<AudioStatsDialog> getAudioStatsDialog() const { return _audioStatsDialog; }
QPointer<BandwidthDialog> getBandwidthDialog() const { return _bandwidthDialog; }
// QPointer<HMDToolsDialog> getHMDToolsDialog() const { return _hmdToolsDialog; }
QPointer<LodToolsDialog> getLodToolsDialog() const { return _lodToolsDialog; }
QPointer<OctreeStatsDialog> getOctreeStatsDialog() const { return _octreeStatsDialog; }
QPointer<PreferencesDialog> getPreferencesDialog() const { return _preferencesDialog; }
@ -56,9 +57,9 @@ public slots:
void editPreferences();
void editAttachments();
void editAnimations();
void audioStatsDetails();
void bandwidthDetails();
void lodTools();
void hmdTools(bool showTools);
void showScriptEditor();
void showIRCLink();
void changeAvatarAppearance();
@ -69,7 +70,6 @@ public slots:
private slots:
void toggleToolWindow();
void hmdToolsClosed();
private:
DialogsManager() {}
@ -81,23 +81,17 @@ private:
Q_CHECK_PTR(parent);
member = new T(parent);
Q_CHECK_PTR(member);
#if 0
if (_hmdToolsDialog && member->windowHandle()) {
_hmdToolsDialog->watchWindow(member->windowHandle());
}
#endif
}
}
QPointer<AddressBarDialog> _addressBarDialog;
QPointer<AnimationsDialog> _animationsDialog;
QPointer<AttachmentsDialog> _attachmentsDialog;
QPointer<AudioStatsDialog> _audioStatsDialog;
QPointer<BandwidthDialog> _bandwidthDialog;
QPointer<CachesSizeDialog> _cachesSizeDialog;
QPointer<DiskCacheEditor> _diskCacheEditor;
QPointer<QMessageBox> _ircInfoBox;
// QPointer<HMDToolsDialog> _hmdToolsDialog;
QPointer<LodToolsDialog> _lodToolsDialog;
QPointer<LoginDialog> _loginDialog;
QPointer<OctreeStatsDialog> _octreeStatsDialog;

View file

@ -1,222 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdouble-promotion"
#endif
#include <QtWidgets>
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#include "FlowLayout.h"
//! [1]
FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing)
: QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
{
setContentsMargins(margin, margin, margin, margin);
}
FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing)
: m_hSpace(hSpacing), m_vSpace(vSpacing)
{
setContentsMargins(margin, margin, margin, margin);
}
//! [1]
//! [2]
FlowLayout::~FlowLayout()
{
QLayoutItem *item;
while ((item = takeAt(0)))
delete item;
}
//! [2]
//! [3]
void FlowLayout::addItem(QLayoutItem *item)
{
itemList.append(item);
}
//! [3]
//! [4]
int FlowLayout::horizontalSpacing() const
{
if (m_hSpace >= 0) {
return m_hSpace;
} else {
return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
}
}
int FlowLayout::verticalSpacing() const
{
if (m_vSpace >= 0) {
return m_vSpace;
} else {
return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
}
}
//! [4]
//! [5]
int FlowLayout::count() const
{
return itemList.size();
}
QLayoutItem *FlowLayout::itemAt(int index) const
{
return itemList.value(index);
}
QLayoutItem *FlowLayout::takeAt(int index)
{
if (index >= 0 && index < itemList.size())
return itemList.takeAt(index);
else
return 0;
}
//! [5]
//! [6]
Qt::Orientations FlowLayout::expandingDirections() const
{
return 0;
}
//! [6]
//! [7]
bool FlowLayout::hasHeightForWidth() const
{
return true;
}
int FlowLayout::heightForWidth(int width) const
{
int height = doLayout(QRect(0, 0, width, 0), true);
return height;
}
//! [7]
//! [8]
void FlowLayout::setGeometry(const QRect &rect)
{
QLayout::setGeometry(rect);
doLayout(rect, false);
}
QSize FlowLayout::sizeHint() const
{
return minimumSize();
}
QSize FlowLayout::minimumSize() const
{
QSize size;
QLayoutItem *item;
foreach (item, itemList)
size = size.expandedTo(item->minimumSize());
size += QSize(2*margin(), 2*margin());
return size;
}
//! [8]
//! [9]
int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
{
int left, top, right, bottom;
getContentsMargins(&left, &top, &right, &bottom);
QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
int x = effectiveRect.x();
int y = effectiveRect.y();
int lineHeight = 0;
//! [9]
//! [10]
QLayoutItem *item;
foreach (item, itemList) {
QWidget *wid = item->widget();
int spaceX = horizontalSpacing();
if (spaceX == -1)
spaceX = wid->style()->layoutSpacing(
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
int spaceY = verticalSpacing();
if (spaceY == -1)
spaceY = wid->style()->layoutSpacing(
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
//! [10]
//! [11]
int nextX = x + item->sizeHint().width() + spaceX;
if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
x = effectiveRect.x();
y = y + lineHeight + spaceY;
nextX = x + item->sizeHint().width() + spaceX;
lineHeight = 0;
}
if (!testOnly)
item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));
x = nextX;
lineHeight = qMax(lineHeight, item->sizeHint().height());
}
return y + lineHeight - rect.y() + bottom;
}
//! [11]
//! [12]
int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
{
QObject *parent = this->parent();
if (!parent) {
return -1;
} else if (parent->isWidgetType()) {
QWidget *pw = static_cast<QWidget *>(parent);
return pw->style()->pixelMetric(pm, 0, pw);
} else {
return static_cast<QLayout *>(parent)->spacing();
}
}
//! [12]

View file

@ -1,78 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef FLOWLAYOUT_H
#define FLOWLAYOUT_H
#include <QLayout>
#include <QRect>
#include <QStyle>
//! [0]
class FlowLayout : public QLayout
{
public:
explicit FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1);
explicit FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);
~FlowLayout();
void addItem(QLayoutItem *item);
int horizontalSpacing() const;
int verticalSpacing() const;
Qt::Orientations expandingDirections() const;
bool hasHeightForWidth() const;
int heightForWidth(int) const;
int count() const;
QLayoutItem *itemAt(int index) const;
QSize minimumSize() const;
void setGeometry(const QRect &rect);
QSize sizeHint() const;
QLayoutItem *takeAt(int index);
private:
int doLayout(const QRect &rect, bool testOnly) const;
int smartSpacing(QStyle::PixelMetric pm) const;
QList<QLayoutItem *> itemList;
int m_hSpace;
int m_vSpace;
};
//! [0]
#endif // FLOWLAYOUT_H

View file

@ -9,8 +9,6 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "InterfaceConfig.h"
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdouble-promotion"
@ -18,7 +16,6 @@
#include <QDesktopWidget>
#include <QTextBlock>
#include <QtGui>
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop

View file

@ -12,8 +12,6 @@
#ifndef hifi_LogDialog_h
#define hifi_LogDialog_h
#include "InterfaceConfig.h"
#include <QDialog>
#include <QMutex>
#include <QPlainTextEdit>

View file

@ -94,7 +94,6 @@ void OctreeStatsDialog::moreless(const QString& link) {
int OctreeStatsDialog::AddStatItem(const char* caption, unsigned colorRGBA) {
char strBuf[64];
const int STATS_LABEL_WIDTH = 600;
_statCount++; // increment our current stat count
@ -115,8 +114,7 @@ int OctreeStatsDialog::AddStatItem(const char* caption, unsigned colorRGBA) {
rgb = ((rgb & colorpart1) >> 1) + ((rgb & colorpart2) >> 3);
palette.setColor(QPalette::WindowText, QColor::fromRgb(rgb));
label->setPalette(palette);
snprintf(strBuf, sizeof(strBuf), " %s:", caption);
_form->addRow(strBuf, label);
_form->addRow(QString(" %1:").arg(caption), label);
label->setFixedWidth(STATS_LABEL_WIDTH);
return _statCount;

View file

@ -28,7 +28,6 @@
#include <QWidget>
#include "Application.h"
#include "FlowLayout.h"
#include "JSConsole.h"
#include "PathUtils.h"

View file

@ -6,8 +6,6 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <gpu/GPUConfig.h>
#include "Stats.h"
#include <sstream>
@ -25,7 +23,6 @@
#include <PerfStat.h>
#include "BandwidthRecorder.h"
#include "InterfaceConfig.h"
#include "Menu.h"
#include "Util.h"
#include "SequenceNumberStats.h"

View file

@ -9,12 +9,9 @@
#ifndef hifi_Stats_h
#define hifi_Stats_h
#include <QObject>
#include <QQuickItem>
#include <QVector3D>
#include <OffscreenUi.h>
#include <OffscreenQmlElement.h>
#include <RenderArgs.h>
#include <QVector3D>
#define STATS_PROPERTY(type, name, initialValue) \
Q_PROPERTY(type name READ name NOTIFY name##Changed) \

View file

@ -8,13 +8,14 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// include this before QGLWidget, which includes an earlier version of OpenGL
#include "InterfaceConfig.h"
#include "Base3DOverlay.h"
#include <QScriptValue>
#include <RegisteredMetaTypes.h>
#include <SharedUtil.h>
#include "Application.h"
#include "Base3DOverlay.h"
const float DEFAULT_LINE_WIDTH = 1.0f;
const bool DEFAULT_IS_SOLID = false;

View file

@ -11,6 +11,12 @@
#include "BillboardOverlay.h"
#include <QScriptValue>
#include <DependencyManager.h>
#include <GeometryCache.h>
#include <gpu/Batch.h>
#include "Application.h"
#include "GeometryUtil.h"

View file

@ -12,8 +12,6 @@
#define hifi_Circle3DOverlay_h
// include this before QGLWidget, which includes an earlier version of OpenGL
#include "InterfaceConfig.h"
#include "Planar3DOverlay.h"
class Circle3DOverlay : public Planar3DOverlay {

View file

@ -9,14 +9,15 @@
//
// include this before QGLWidget, which includes an earlier version of OpenGL
#include "InterfaceConfig.h"
#include "Cube3DOverlay.h"
#include <QScriptValue>
#include <DeferredLightingEffect.h>
#include <SharedUtil.h>
#include <StreamUtils.h>
#include "Application.h"
#include "Cube3DOverlay.h"
#include <GeometryCache.h>
#include <DependencyManager.h>
Cube3DOverlay::Cube3DOverlay(const Cube3DOverlay* cube3DOverlay) :
Volume3DOverlay(cube3DOverlay)

View file

@ -9,16 +9,14 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// include this before QGLWidget, which includes an earlier version of OpenGL
#include "InterfaceConfig.h"
#include "Grid3DOverlay.h"
#include <QScriptValue>
#include <DependencyManager.h>
#include <GeometryCache.h>
#include <PathUtils.h>
#include "Application.h"
ProgramObject Grid3DOverlay::_gridProgram;
#include <ViewFrustum.h>
Grid3DOverlay::Grid3DOverlay() :
_minorGridWidth(1.0),
@ -42,7 +40,7 @@ void Grid3DOverlay::render(RenderArgs* args) {
const float MAX_COLOR = 255.0f;
// center the grid around the camera position on the plane
glm::vec3 rotated = glm::inverse(getRotation()) * Application::getInstance()->getCamera()->getPosition();
glm::vec3 rotated = glm::inverse(getRotation()) * args->_viewFrustum->getPosition();
float spacing = _minorGridWidth;
@ -118,3 +116,4 @@ QScriptValue Grid3DOverlay::getProperty(const QString& property) {
Grid3DOverlay* Grid3DOverlay::createClone() const {
return new Grid3DOverlay(this);
}

View file

@ -12,11 +12,6 @@
#ifndef hifi_Grid3DOverlay_h
#define hifi_Grid3DOverlay_h
// include this before QGLWidget, which includes an earlier version of OpenGL
#include "InterfaceConfig.h"
#include <ProgramObject.h>
#include "Planar3DOverlay.h"
class Grid3DOverlay : public Planar3DOverlay {
@ -35,8 +30,6 @@ public:
private:
float _minorGridWidth;
int _majorGridEvery;
static ProgramObject _gridProgram;
};
#endif // hifi_Grid3DOverlay_h

View file

@ -12,13 +12,10 @@
#include <DependencyManager.h>
#include <GeometryCache.h>
#include <gpu/Context.h>
#include <gpu/StandardShaderLib.h>
#include <RegisteredMetaTypes.h>
#include "qapplication.h"
#include "gpu/Context.h"
#include "gpu/StandardShaderLib.h"
ImageOverlay::ImageOverlay() :
_imageURL(),
_renderImage(false),
@ -55,15 +52,15 @@ void ImageOverlay::render(RenderArgs* args) {
_isLoaded = true;
_texture = DependencyManager::get<TextureCache>()->getTexture(_imageURL);
}
// If we are not visible or loaded, return. If we are trying to render an
// image but the texture hasn't loaded, return.
if (!_visible || !_isLoaded || (_renderImage && !_texture->isLoaded())) {
return;
}
auto geometryCache = DependencyManager::get<GeometryCache>();
gpu::Batch& batch = *args->_batch;
geometryCache->useSimpleDrawPipeline(batch);
if (_renderImage) {
batch.setResourceTexture(0, _texture->getGPUTexture());
} else {

View file

@ -12,8 +12,6 @@
#define hifi_ImageOverlay_h
// include this before QGLWidget, which includes an earlier version of OpenGL
#include "InterfaceConfig.h"
#include <QImage>
#include <QRect>
#include <QUrl>

View file

@ -8,15 +8,11 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// include this before QGLWidget, which includes an earlier version of OpenGL
#include "InterfaceConfig.h"
#include "Line3DOverlay.h"
#include <GeometryCache.h>
#include <RegisteredMetaTypes.h>
#include "Line3DOverlay.h"
Line3DOverlay::Line3DOverlay() :
_geometryCacheID(DependencyManager::get<GeometryCache>()->allocateID())
{

View file

@ -9,10 +9,11 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "Application.h"
#include "LocalModelsOverlay.h"
#include <EntityTreeRenderer.h>
#include <gpu/Batch.h>
LocalModelsOverlay::LocalModelsOverlay(EntityTreeRenderer* entityTreeRenderer) :
Volume3DOverlay(),
_entityTreeRenderer(entityTreeRenderer) {
@ -33,13 +34,11 @@ void LocalModelsOverlay::render(RenderArgs* args) {
float glowLevel = getGlowLevel(); // FIXME, glowing removed for now
auto batch = args ->_batch;
Application* app = Application::getInstance();
glm::vec3 oldTranslation = app->getViewFrustum()->getPosition();
Transform transform = Transform();
transform.setTranslation(oldTranslation + getPosition());
transform.setTranslation(args->_viewFrustum->getPosition() + getPosition());
batch->setViewTransform(transform);
_entityTreeRenderer->render(args);
transform.setTranslation(oldTranslation);
transform.setTranslation(args->_viewFrustum->getPosition());
batch->setViewTransform(transform);
}
}

View file

@ -11,7 +11,7 @@
#include "ModelOverlay.h"
#include <Application.h>
#include "Application.h"
ModelOverlay::ModelOverlay()
: _model(),

View file

@ -12,8 +12,6 @@
#define hifi_Overlay_h
// include this before QGLWidget, which includes an earlier version of OpenGL
#include "InterfaceConfig.h"
#include <SharedUtil.h> // for xColor
#include <render/Scene.h>

View file

@ -11,9 +11,6 @@
#ifndef hifi_Overlay2D_h
#define hifi_Overlay2D_h
// include this before QGLWidget, which includes an earlier version of OpenGL
#include "InterfaceConfig.h"
#include <QRect>
#include "Overlay.h"

View file

@ -14,10 +14,11 @@
#include <limits>
#include <Application.h>
#include <render/Scene.h>
#include <gpu/GLBackend.h>
#include <RegisteredMetaTypes.h>
#include "Application.h"
#include "BillboardOverlay.h"
#include "Circle3DOverlay.h"
#include "Cube3DOverlay.h"
@ -98,16 +99,29 @@ 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<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) {
// 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);
}
renderArgs->_context->syncCache();
renderArgs->_context->render(batch);
}
unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& properties) {

View file

@ -11,9 +11,6 @@
#ifndef hifi_Planar3DOverlay_h
#define hifi_Planar3DOverlay_h
// include this before QGLWidget, which includes an earlier version of OpenGL
#include "InterfaceConfig.h"
#include "Base3DOverlay.h"
class Planar3DOverlay : public Base3DOverlay {

View file

@ -8,9 +8,6 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// include this before QGLWidget, which includes an earlier version of OpenGL
#include "InterfaceConfig.h"
#include "Rectangle3DOverlay.h"
#include <GeometryCache.h>

View file

@ -8,14 +8,12 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// include this before QGLWidget, which includes an earlier version of OpenGL
#include "InterfaceConfig.h"
#include <SharedUtil.h>
#include "Sphere3DOverlay.h"
#include "Application.h"
#include <DependencyManager.h>
#include <GeometryCache.h>
#include <gpu/Batch.h>
#include <SharedUtil.h>
Sphere3DOverlay::Sphere3DOverlay(const Sphere3DOverlay* Sphere3DOverlay) :
Volume3DOverlay(Sphere3DOverlay)

View file

@ -8,9 +8,6 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// include this before QGLWidget, which includes an earlier version of OpenGL
#include "InterfaceConfig.h"
#include "Text3DOverlay.h"
#include <DeferredLightingEffect.h>

View file

@ -11,9 +11,6 @@
#ifndef hifi_Text3DOverlay_h
#define hifi_Text3DOverlay_h
// include this before QGLWidget, which includes an earlier version of OpenGL
#include "InterfaceConfig.h"
#include <QString>
#include "Planar3DOverlay.h"

View file

@ -8,17 +8,75 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// include this before QGLWidget, which includes an earlier version of OpenGL
#include "InterfaceConfig.h"
#include "TextOverlay.h"
#include <QQuickItem>
#include <DependencyManager.h>
#include <GeometryCache.h>
#include <GLMHelpers.h>
#include <gpu/GLBackend.h>
#include <OffscreenUi.h>
#include <RegisteredMetaTypes.h>
#include <SharedUtil.h>
#include <TextRenderer.h>
#include <TextureCache.h>
#include <ViewFrustum.h>
#include "Application.h"
#include "text/FontFamilies.h"
#define TEXT_OVERLAY_PROPERTY(type, name, initialValue) \
Q_PROPERTY(type name READ name WRITE set##name NOTIFY name##Changed) \
public: \
type name() { return _##name; }; \
void set##name(const type& name) { \
if (name != _##name) { \
_##name = name; \
emit name##Changed(); \
} \
} \
private: \
type _##name{ initialValue };
class TextOverlayElement : public QQuickItem {
Q_OBJECT
HIFI_QML_DECL
private:
TEXT_OVERLAY_PROPERTY(QString, text, "")
TEXT_OVERLAY_PROPERTY(QString, fontFamily, SANS_FONT_FAMILY)
TEXT_OVERLAY_PROPERTY(QString, textColor, "#ffffffff")
TEXT_OVERLAY_PROPERTY(QString, backgroundColor, "#B2000000")
TEXT_OVERLAY_PROPERTY(qreal, fontSize, 18)
TEXT_OVERLAY_PROPERTY(qreal, lineHeight, 18)
TEXT_OVERLAY_PROPERTY(qreal, leftMargin, 0)
TEXT_OVERLAY_PROPERTY(qreal, topMargin, 0)
public:
TextOverlayElement(QQuickItem* parent = nullptr) : QQuickItem(parent) {
}
signals:
void textChanged();
void fontFamilyChanged();
void fontSizeChanged();
void lineHeightChanged();
void leftMarginChanged();
void topMarginChanged();
void textColorChanged();
void backgroundColorChanged();
};
HIFI_QML_DEF(TextOverlayElement)
QString toQmlColor(const glm::vec4& v) {
QString templat("#%1%2%3%4");
return templat.
arg((int)(v.a * 255), 2, 16, QChar('0')).
arg((int)(v.r * 255), 2, 16, QChar('0')).
arg((int)(v.g * 255), 2, 16, QChar('0')).
arg((int)(v.b * 255), 2, 16, QChar('0'));
}
TextOverlay::TextOverlay() :
_backgroundColor(DEFAULT_BACKGROUND_COLOR),
@ -27,7 +85,20 @@ TextOverlay::TextOverlay() :
_topMargin(DEFAULT_MARGIN),
_fontSize(DEFAULT_FONTSIZE)
{
_textRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, _fontSize, DEFAULT_FONT_WEIGHT);
qApp->postLambdaEvent([=] {
static std::once_flag once;
std::call_once(once, [] {
TextOverlayElement::registerType();
});
auto offscreenUi = DependencyManager::get<OffscreenUi>();
TextOverlayElement::show([=](QQmlContext* context, QObject* object) {
_qmlElement = static_cast<TextOverlayElement*>(object);
});
});
while (!_qmlElement) {
QThread::msleep(1);
}
}
TextOverlay::TextOverlay(const TextOverlay* textOverlay) :
@ -39,11 +110,21 @@ TextOverlay::TextOverlay(const TextOverlay* textOverlay) :
_topMargin(textOverlay->_topMargin),
_fontSize(textOverlay->_fontSize)
{
_textRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, _fontSize, DEFAULT_FONT_WEIGHT);
qApp->postLambdaEvent([=] {
auto offscreenUi = DependencyManager::get<OffscreenUi>();
TextOverlayElement::show([this](QQmlContext* context, QObject* object) {
_qmlElement = static_cast<TextOverlayElement*>(object);
});
});
while (!_qmlElement) {
QThread::sleep(1);
}
}
TextOverlay::~TextOverlay() {
delete _textRenderer;
if (_qmlElement) {
_qmlElement->deleteLater();
}
}
xColor TextOverlay::getBackgroundColor() {
@ -65,45 +146,34 @@ xColor TextOverlay::getBackgroundColor() {
return result;
}
void TextOverlay::render(RenderArgs* args) {
if (!_visible) {
return; // do nothing if we're not visible
if (_visible != _qmlElement->isVisible()) {
_qmlElement->setVisible(_visible);
}
float pulseLevel = updatePulse();
static float _oldPulseLevel = 0.0f;
if (pulseLevel != _oldPulseLevel) {
const float MAX_COLOR = 255.0f;
xColor backgroundColor = getBackgroundColor();
glm::vec4 quadColor(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR, backgroundColor.blue / MAX_COLOR,
getBackgroundAlpha());
int left = _bounds.left();
int right = _bounds.right() + 1;
int top = _bounds.top();
int bottom = _bounds.bottom() + 1;
glm::vec2 topLeft(left, top);
glm::vec2 bottomRight(right, bottom);
glBindTexture(GL_TEXTURE_2D, 0);
DependencyManager::get<GeometryCache>()->renderQuad(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
int x = _bounds.left() + _leftMargin + leftAdjust;
int y = _bounds.top() + _topMargin + topAdjust;
float alpha = getAlpha();
glm::vec4 textColor = {_color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR, alpha };
_textRenderer->draw(x, y, _text, textColor);
}
}
void TextOverlay::setProperties(const QScriptValue& properties) {
Overlay2D::setProperties(properties);
_qmlElement->setX(_bounds.left());
_qmlElement->setY(_bounds.top());
_qmlElement->setWidth(_bounds.width());
_qmlElement->setHeight(_bounds.height());
_qmlElement->settextColor(toQmlColor(vec4(toGlm(_color), _alpha)));
QScriptValue font = properties.property("font");
if (font.isObject()) {
if (font.property("size").isValid()) {
setFontSize(font.property("size").toInt32());
}
QFont font(_qmlElement->fontFamily());
font.setPixelSize(_qmlElement->fontSize());
QFontMetrics fm(font);
_qmlElement->setlineHeight(fm.lineSpacing() * 1.2);
}
QScriptValue text = properties.property("text");
@ -126,6 +196,7 @@ void TextOverlay::setProperties(const QScriptValue& properties) {
if (properties.property("backgroundAlpha").isValid()) {
_backgroundAlpha = properties.property("backgroundAlpha").toVariant().toFloat();
}
_qmlElement->setbackgroundColor(toQmlColor(vec4(toGlm(_backgroundColor), _backgroundAlpha)));
if (properties.property("leftMargin").isValid()) {
setLeftMargin(properties.property("leftMargin").toVariant().toInt());
@ -166,15 +237,37 @@ QScriptValue TextOverlay::getProperty(const QString& property) {
}
QSizeF TextOverlay::textSize(const QString& text) const {
auto extents = _textRenderer->computeExtent(text);
return QSizeF(extents.x, extents.y);
int lines = 1;
foreach(QChar c, text) {
if (c == QChar('\n')) {
++lines;
}
}
QFont font(_qmlElement->fontFamily());
font.setPixelSize(_qmlElement->fontSize());
QFontMetrics fm(font);
QSizeF result = QSizeF(fm.width(text), _qmlElement->lineHeight() * lines);
return result;
}
void TextOverlay::setFontSize(int fontSize) {
_fontSize = fontSize;
auto oldTextRenderer = _textRenderer;
_textRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, _fontSize, DEFAULT_FONT_WEIGHT);
delete oldTextRenderer;
_qmlElement->setfontSize(fontSize);
}
void TextOverlay::setText(const QString& text) {
_text = text;
_qmlElement->settext(text);
}
void TextOverlay::setLeftMargin(int margin) {
_leftMargin = margin;
_qmlElement->setleftMargin(margin);
}
void TextOverlay::setTopMargin(int margin) {
_topMargin = margin;
_qmlElement->settopMargin(margin);
}
#include "TextOverlay.moc"

View file

@ -11,9 +11,6 @@
#ifndef hifi_TextOverlay_h
#define hifi_TextOverlay_h
// include this before QGLWidget, which includes an earlier version of OpenGL
#include "InterfaceConfig.h"
#include <QString>
#include <SharedUtil.h>
@ -26,7 +23,7 @@ const int DEFAULT_MARGIN = 10;
const int DEFAULT_FONTSIZE = 12;
const int DEFAULT_FONT_WEIGHT = 50;
class TextRenderer;
class TextOverlayElement;
class TextOverlay : public Overlay2D {
Q_OBJECT
@ -45,9 +42,9 @@ public:
float getBackgroundAlpha() const { return _backgroundAlpha; }
// setters
void setText(const QString& text) { _text = text; }
void setLeftMargin(int margin) { _leftMargin = margin; }
void setTopMargin(int margin) { _topMargin = margin; }
void setText(const QString& text);
void setLeftMargin(int margin);
void setTopMargin(int margin);
void setFontSize(int fontSize);
virtual void setProperties(const QScriptValue& properties);
@ -57,9 +54,7 @@ public:
QSizeF textSize(const QString& text) const; // Pixels
private:
TextRenderer* _textRenderer = nullptr;
TextOverlayElement* _qmlElement{ nullptr };
QString _text;
xColor _backgroundColor;
float _backgroundAlpha;

View file

@ -11,9 +11,6 @@
#ifndef hifi_Volume3DOverlay_h
#define hifi_Volume3DOverlay_h
// include this before QGLWidget, which includes an earlier version of OpenGL
#include "InterfaceConfig.h"
#include "Base3DOverlay.h"
class Volume3DOverlay : public Base3DOverlay {

View file

@ -93,6 +93,7 @@ void AudioInjector::injectAudio() {
}
void AudioInjector::restart() {
_isPlaying = true;
connect(this, &AudioInjector::finished, this, &AudioInjector::restartPortionAfterFinished);
if (!_isStarted || _isFinished) {
emit finished();
@ -270,6 +271,7 @@ void AudioInjector::injectToMixer() {
}
setIsFinished(true);
_isPlaying = !_isFinished; // Which can be false if a restart was requested
}
void AudioInjector::stop() {
@ -277,6 +279,7 @@ void AudioInjector::stop() {
if (_options.localOnly) {
// we're only a local injector, so we can say we are finished right away too
_isPlaying = false;
setIsFinished(true);
}
}
@ -334,6 +337,7 @@ AudioInjector* AudioInjector::playSound(const QByteArray& buffer, const AudioInj
injectorThread->setObjectName("Audio Injector Thread");
AudioInjector* injector = new AudioInjector(buffer, options);
injector->_isPlaying = true;
injector->setLocalAudioInterface(localInterface);
injector->moveToThread(injectorThread);

View file

@ -62,7 +62,7 @@ public slots:
void setCurrentSendPosition(int currentSendPosition) { _currentSendPosition = currentSendPosition; }
float getLoudness() const { return _loudness; }
bool isPlaying() const { return !_isFinished; }
bool isPlaying() const { return _isPlaying; }
void restartPortionAfterFinished();
signals:
@ -78,6 +78,7 @@ private:
AudioInjectorOptions _options;
bool _shouldStop = false;
float _loudness = 0.0f;
bool _isPlaying = false;
bool _isStarted = false;
bool _isFinished = false;
bool _shouldDeleteAfterFinish = false;

View file

@ -52,18 +52,18 @@ bool Oculus_0_5_DisplayPlugin::isSupported() const {
static const char* OVR_DISTORTION_VS = R"SHADER(#version 120
#pragma line __LINE__
uniform vec2 EyeToSourceUVScale;
//uniform vec2 EyeToSourceUVScale;
const vec2 EyeToSourceUVScale = vec2(0.232447237, 0.375487238);
uniform vec2 EyeToSourceUVOffset;
uniform mat4 EyeRotationStart;
uniform mat4 EyeRotationEnd;
attribute vec2 Position;
attribute vec4 Color;
attribute vec4 Position;
attribute vec2 TexCoord0;
attribute vec2 TexCoord1;
attribute vec2 TexCoord2;
varying vec4 oColor;
varying vec2 oTexCoord0;
varying vec2 oTexCoord1;
varying vec2 oTexCoord2;
@ -73,6 +73,10 @@ void main() {
gl_Position.y = Position.y;
gl_Position.z = 0.0;
gl_Position.w = 1.0;
oTexCoord0 = TexCoord0;
oTexCoord1 = TexCoord1;
oTexCoord2 = TexCoord2;
// Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion).
// These are now "real world" vectors in direction (x,y,1) relative to the eye of the HMD.
vec3 TanEyeAngleR = vec3 ( TexCoord0.x, TexCoord0.y, 1.0 );
@ -86,9 +90,9 @@ void main() {
vec3 TransformedGEnd = (EyeRotationEnd * vec4(TanEyeAngleG, 0)).xyz;
vec3 TransformedBEnd = (EyeRotationEnd * vec4(TanEyeAngleB, 0)).xyz;
// And blend between them.
vec3 TransformedR = mix ( TransformedRStart, TransformedREnd, Color.a );
vec3 TransformedG = mix ( TransformedGStart, TransformedGEnd, Color.a );
vec3 TransformedB = mix ( TransformedBStart, TransformedBEnd, Color.a );
vec3 TransformedR = mix ( TransformedRStart, TransformedREnd, Position.z );
vec3 TransformedG = mix ( TransformedGStart, TransformedGEnd, Position.z );
vec3 TransformedB = mix ( TransformedBStart, TransformedBEnd, Position.z );
// Project them back onto the Z=1 plane of the rendered images.
float RecipZR = 1.0 / TransformedR.z;
@ -103,10 +107,13 @@ void main() {
vec2 SrcCoordR = FlattenedR * EyeToSourceUVScale + EyeToSourceUVOffset;
vec2 SrcCoordG = FlattenedG * EyeToSourceUVScale + EyeToSourceUVOffset;
vec2 SrcCoordB = FlattenedB * EyeToSourceUVScale + EyeToSourceUVOffset;
// vec2 SrcCoordR = FlattenedR + EyeToSourceUVOffset;
// vec2 SrcCoordG = FlattenedG + EyeToSourceUVOffset;
// vec2 SrcCoordB = FlattenedB + EyeToSourceUVOffset;
oTexCoord0 = SrcCoordR;
oTexCoord1 = SrcCoordG;
oTexCoord2 = SrcCoordB;
oColor = vec4(Color.r, Color.r, Color.r, Color.r); // Used for vignette fade.
}
)SHADER";
@ -118,11 +125,13 @@ uniform sampler2D Texture0;
#extension GL_ARB_draw_buffers : enable
#extension GL_EXT_gpu_shader4 : enable
varying vec4 oColor;
varying vec2 oTexCoord0;
varying vec2 oTexCoord1;
varying vec2 oTexCoord2;
void main() {
gl_FragColor = vec4(0, 0, 0, 1); // texture2D(Texture0, oTexCoord0, 0.0);
gl_FragColor = vec4(oTexCoord0, 0, 1);
gl_FragColor = texture2D(Texture0, oTexCoord0, 0.0);
//gl_FragColor.a = 1.0;
}
)SHADER";
@ -147,8 +156,8 @@ void Oculus_0_5_DisplayPlugin::activate(PluginContainer * container) {
_hmdWindow->setFlags(Qt::FramelessWindowHint);
_hmdWindow->setFormat(format);
_hmdWindow->create();
//_hmdWindow->setGeometry(_hmd->WindowsPos.x, _hmd->WindowsPos.y, _hmd->Resolution.w, _hmd->Resolution.h);
_hmdWindow->setGeometry(0, -1080, _hmd->Resolution.w, _hmd->Resolution.h);
_hmdWindow->setGeometry(_hmd->WindowsPos.x, _hmd->WindowsPos.y, _hmd->Resolution.w, _hmd->Resolution.h);
//_hmdWindow->setGeometry(0, -1080, _hmd->Resolution.w, _hmd->Resolution.h);
_hmdWindow->show();
_hmdWindow->installEventFilter(this);
_hmdWindow->makeCurrent();
@ -180,7 +189,7 @@ void Oculus_0_5_DisplayPlugin::activate(PluginContainer * container) {
compileProgram(_distortProgram, OVR_DISTORTION_VS, OVR_DISTORTION_FS);
auto uniforms = _distortProgram->ActiveUniforms();
for (int i = 0; i < uniforms.Size(); ++i) {
for (size_t i = 0; i < uniforms.Size(); ++i) {
auto uniform = uniforms.At(i);
qDebug() << uniform.Name().c_str() << " @ " << uniform.Index();
if (uniform.Name() == String("EyeToSourceUVScale")) {
@ -195,7 +204,7 @@ void Oculus_0_5_DisplayPlugin::activate(PluginContainer * container) {
}
auto attribs = _distortProgram->ActiveAttribs();
for (int i = 0; i < attribs.Size(); ++i) {
for (size_t i = 0; i < attribs.Size(); ++i) {
auto attrib = attribs.At(i);
qDebug() << attrib.Name().c_str() << " @ " << attrib.Index();
if (attrib.Name() == String("Position")) {
@ -230,7 +239,7 @@ void Oculus_0_5_DisplayPlugin::activate(PluginContainer * container) {
}
ovrHmd_DestroyDistortionMesh(&meshData);
const auto& header = _eyeTextures[eye].Header;
ovrHmd_GetRenderScaleAndOffset(_eyeFovs[eye], header.TextureSize, header.RenderViewport, _offsetAndScale[eye]);
ovrHmd_GetRenderScaleAndOffset(_eyeFovs[eye], header.TextureSize, header.RenderViewport, _scaleAndOffset[eye]);
});
#endif
@ -283,19 +292,35 @@ void Oculus_0_5_DisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sc
_distortProgram->Bind();
glBindTexture(GL_TEXTURE_2D, finalTexture);
glViewport(0, 0, _hmd->Resolution.w, _hmd->Resolution.h);
// Generates internal compiler error on MSVC 12
ovr_for_each_eye([&](ovrEyeType eye){
glUniform2fv(_uniformOffset, 1, &_offsetAndScale[eye][0].x);
glUniform2fv(_uniformScale, 1, &_offsetAndScale[eye][1].x);
// ovrMatrix4f timeWarpMatrices[2];
// ovrHmd_GetEyeTimewarpMatrices(_hmd, eye, _eyePoses[eye], timeWarpMatrices);
// glUniformMatrix4fv(_uniformEyeRotStart, 1, GL_TRUE, &(timeWarpMatrices[0].M[0][0]));
// glUniformMatrix4fv(_uniformEyeRotEnd, 1, GL_TRUE, &(timeWarpMatrices[1].M[0][0]));
mat4 identity;
glUniformMatrix4fv(_uniformEyeRotStart, 1, GL_FALSE, &identity[0][0]);
glUniformMatrix4fv(_uniformEyeRotEnd, 1, GL_FALSE, &identity[0][0]);
vec2 scale(1);
// glUniform2fv(_uniformScale, 1, &_scaleAndOffset[eye][0].x);
glUniform2fv(_uniformScale, 1, &scale.x);
glUniform2fv(_uniformOffset, 1, &_scaleAndOffset[eye][1].x);
_eyeVertexBuffers[eye]->Bind(Buffer::Target::Array);
glEnableVertexAttribArray(_attrPosition);
glVertexAttribPointer(_attrPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ovrDistortionVertex), (void*)offsetof(ovrDistortionVertex, ScreenPosNDC));
size_t offset;
offset = offsetof(ovrDistortionVertex, ScreenPosNDC);
glVertexAttribPointer(_attrPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ovrDistortionVertex), (void*)offset);
glEnableVertexAttribArray(_attrTexCoord0);
glVertexAttribPointer(_attrTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(ovrDistortionVertex), (void*)offsetof(ovrDistortionVertex, TanEyeAnglesR));
offset = offsetof(ovrDistortionVertex, TanEyeAnglesR);
glVertexAttribPointer(_attrTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(ovrDistortionVertex), (void*)offset);
glEnableVertexAttribArray(_attrTexCoord1);
glVertexAttribPointer(_attrTexCoord1, 2, GL_FLOAT, GL_FALSE, sizeof(ovrDistortionVertex), (void*)offsetof(ovrDistortionVertex, TanEyeAnglesG));
offset = offsetof(ovrDistortionVertex, TanEyeAnglesG);
glVertexAttribPointer(_attrTexCoord1, 2, GL_FLOAT, GL_FALSE, sizeof(ovrDistortionVertex), (void*)offset);
glEnableVertexAttribArray(_attrTexCoord2);
glVertexAttribPointer(_attrTexCoord2, 2, GL_FLOAT, GL_FALSE, sizeof(ovrDistortionVertex), (void*)offsetof(ovrDistortionVertex, TanEyeAnglesB));
offset = offsetof(ovrDistortionVertex, TanEyeAnglesB);
glVertexAttribPointer(_attrTexCoord2, 2, GL_FLOAT, GL_FALSE, sizeof(ovrDistortionVertex), (void*)offset);
_eyeIndexBuffers[eye]->Bind(Buffer::Target::ElementArray);
glDrawElements(GL_TRIANGLES, _indexCount[eye], GL_UNSIGNED_SHORT, 0);
glDisableVertexAttribArray(_attrPosition);

View file

@ -42,20 +42,20 @@ private:
ovrTexture _eyeTextures[2];
#if RIFT_SDK_DISTORTION
#else
ovrVector2f _offsetAndScale[2][2];
ovrVector2f _scaleAndOffset[2][2];
ProgramPtr _distortProgram;
BufferPtr _eyeIndexBuffers[2];
BufferPtr _eyeVertexBuffers[2];
GLuint _indexCount[2];
GLuint _uniformScale{ -1 };
GLuint _uniformOffset{ -1 };
GLuint _uniformEyeRotStart{ -1 };
GLuint _uniformEyeRotEnd{ -1 };
GLuint _attrPosition{ -1 };
GLuint _attrTexCoord0{ -1 };
GLuint _attrTexCoord1{ -1 };
GLuint _attrTexCoord2{ -1 };
GLint _uniformScale{ -1 };
GLint _uniformOffset{ -1 };
GLint _uniformEyeRotStart{ -1 };
GLint _uniformEyeRotEnd{ -1 };
GLint _attrPosition{ -1 };
GLint _attrTexCoord0{ -1 };
GLint _attrTexCoord1{ -1 };
GLint _attrTexCoord2{ -1 };
#endif
static const QString NAME;

View file

@ -9,9 +9,6 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <gpu/GPUConfig.h>
#include <gpu/GLBackend.h>
#include <glm/gtx/quaternion.hpp>
#include <QEventLoop>

View file

@ -13,7 +13,6 @@
#include <glm/gtx/quaternion.hpp>
#include <gpu/GPUConfig.h>
#include <gpu/Batch.h>
#include <DeferredLightingEffect.h>

View file

@ -14,7 +14,6 @@
#include <glm/gtx/quaternion.hpp>
#include <gpu/GPUConfig.h>
#include <gpu/Batch.h>
#include <DeferredLightingEffect.h>
#include <ObjectMotionState.h>

View file

@ -11,7 +11,6 @@
#include <glm/gtx/quaternion.hpp>
#include <gpu/GPUConfig.h>
#include <gpu/Batch.h>
#include <DeferredLightingEffect.h>

View file

@ -11,7 +11,6 @@
#include <glm/gtx/quaternion.hpp>
#include <gpu/GPUConfig.h>
#include <gpu/Batch.h>
#include <GeometryCache.h>

View file

@ -11,8 +11,6 @@
#include <glm/gtx/quaternion.hpp>
#include <gpu/GPUConfig.h>
#include <QJsonDocument>
#include <AbstractViewStateInterface.h>

View file

@ -10,8 +10,6 @@
#include <glm/gtx/quaternion.hpp>
#include <gpu/GPUConfig.h>
#include <DependencyManager.h>
#include <DeferredLightingEffect.h>
#include <PerfStat.h>

View file

@ -23,8 +23,6 @@
#pragma GCC diagnostic pop
#endif
#include <gpu/GPUConfig.h>
#include <DeferredLightingEffect.h>
#include <Model.h>
#include <PerfStat.h>

View file

@ -13,7 +13,6 @@
#include <glm/gtx/quaternion.hpp>
#include <gpu/GPUConfig.h>
#include <gpu/Batch.h>
#include <DependencyManager.h>

View file

@ -11,8 +11,6 @@
#include <glm/gtx/quaternion.hpp>
#include <gpu/GPUConfig.h>
#include <DeferredLightingEffect.h>
#include <GeometryCache.h>
#include <PerfStat.h>

View file

@ -8,16 +8,17 @@
#include "RenderableWebEntityItem.h"
#include <gpu/GPUConfig.h>
#include <QMouseEvent>
#include <QQuickItem>
#include <QQuickWindow>
#include <QOpenGLContext>
#include <glm/gtx/quaternion.hpp>
#include <gpu/GPUConfig.h>
#include <DeferredLightingEffect.h>
#include <GeometryCache.h>
#include <PerfStat.h>
#include <TextRenderer.h>
#include <OffscreenQmlSurface.h>
#include <AbstractViewStateInterface.h>
#include <GLMHelpers.h>

View file

@ -11,7 +11,6 @@
#include "RenderableZoneEntityItem.h"
#include <gpu/GPUConfig.h>
#include <gpu/Batch.h>
#include <AbstractViewStateInterface.h>

View file

@ -29,7 +29,6 @@ BoxEntityItem::BoxEntityItem(const EntityItemID& entityItemID, const EntityItemP
EntityItem(entityItemID)
{
_type = EntityTypes::Box;
_created = properties.getCreated();
setProperties(properties);
}

View file

@ -45,9 +45,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) :
_lastEditedFromRemoteInRemoteTime(0),
_created(UNKNOWN_CREATED_TIME),
_changedOnServer(0),
_transform(ENTITY_ITEM_DEFAULT_ROTATION,
ENTITY_ITEM_DEFAULT_DIMENSIONS,
ENTITY_ITEM_DEFAULT_POSITION),
_transform(),
_glowLevel(ENTITY_ITEM_DEFAULT_GLOW_LEVEL),
_localRenderAlpha(ENTITY_ITEM_DEFAULT_LOCAL_RENDER_ALPHA),
_density(ENTITY_ITEM_DEFAULT_DENSITY),
@ -80,16 +78,15 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) :
_physicsInfo(nullptr),
_simulated(false)
{
// explicitly set transform parts to set dirty flags used by batch rendering
_transform.setTranslation(ENTITY_ITEM_DEFAULT_POSITION);
_transform.setRotation(ENTITY_ITEM_DEFAULT_ROTATION);
_transform.setScale(ENTITY_ITEM_DEFAULT_DIMENSIONS);
quint64 now = usecTimestampNow();
_lastSimulated = now;
_lastUpdated = now;
}
EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : EntityItem(entityItemID)
{
setProperties(properties);
}
EntityItem::~EntityItem() {
// clear out any left-over actions
EntityTree* entityTree = _element ? _element->getTree() : nullptr;

View file

@ -119,7 +119,6 @@ public:
DONT_ALLOW_INSTANTIATION // This class can not be instantiated directly
EntityItem(const EntityItemID& entityItemID);
EntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
virtual ~EntityItem();
// ID and EntityItemID related methods

View file

@ -772,6 +772,9 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int
entityItemID = entityItem->getEntityItemID();
_myTree->setContainingElement(entityItemID, this);
_myTree->postAddEntity(entityItem);
if (entityItem->getCreated() == UNKNOWN_CREATED_TIME) {
entityItem->recordCreationTime();
}
}
}
// Move the buffer forward to read more entities

View file

@ -29,7 +29,7 @@ EntityItemPointer LightEntityItem::factory(const EntityItemID& entityID, const E
// our non-pure virtual subclass for now...
LightEntityItem::LightEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
EntityItem(entityItemID, properties)
EntityItem(entityItemID)
{
_type = EntityTypes::Light;

View file

@ -38,7 +38,6 @@ LineEntityItem::LineEntityItem(const EntityItemID& entityItemID, const EntityIte
_points(QVector<glm::vec3>(0))
{
_type = EntityTypes::Line;
_created = properties.getCreated();
setProperties(properties);

Some files were not shown because too many files have changed in this diff Show more