Merge branch 'primitives_batch' into remove_gl_transform

This commit is contained in:
Atlante45 2015-05-16 05:22:12 +02:00
commit 4725d5e676
22 changed files with 1090 additions and 608 deletions

View file

@ -12,17 +12,17 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
var isDice = false; var isDice = false;
var NUMBER_OF_DICE = 4; var NUMBER_OF_DICE = 4;
var LIFETIME = 10000; // Dice will live for about 3 hours var LIFETIME = 10000; // Dice will live for about 3 hours
var dice = []; var dice = [];
var DIE_SIZE = 0.20; var DIE_SIZE = 0.20;
var madeSound = true; // Set false at start of throw to look for collision var madeSound = true; // Set false at start of throw to look for collision
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
SoundCache.getSound("http://s3.amazonaws.com/hifi-public/sounds/dice/diceCollide.wav");
var rollSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/dice/diceRoll.wav");
var INSUFFICIENT_PERMISSIONS_ERROR_MSG = "You do not have the necessary permissions to create new objects." var INSUFFICIENT_PERMISSIONS_ERROR_MSG = "You do not have the necessary permissions to create new objects."
@ -32,34 +32,46 @@ var BUTTON_SIZE = 32;
var PADDING = 3; var PADDING = 3;
var offButton = Overlays.addOverlay("image", { var offButton = Overlays.addOverlay("image", {
x: screenSize.x / 2 - BUTTON_SIZE * 2 + PADDING, x: screenSize.x / 2 - BUTTON_SIZE * 2 + PADDING,
y: screenSize.y- (BUTTON_SIZE + PADDING), y: screenSize.y - (BUTTON_SIZE + PADDING),
width: BUTTON_SIZE, width: BUTTON_SIZE,
height: BUTTON_SIZE, height: BUTTON_SIZE,
imageURL: HIFI_PUBLIC_BUCKET + "images/close.png", imageURL: HIFI_PUBLIC_BUCKET + "images/close.png",
color: { red: 255, green: 255, blue: 255}, color: {
alpha: 1 red: 255,
}); green: 255,
blue: 255
},
alpha: 1
});
var deleteButton = Overlays.addOverlay("image", { var deleteButton = Overlays.addOverlay("image", {
x: screenSize.x / 2 - BUTTON_SIZE, x: screenSize.x / 2 - BUTTON_SIZE,
y: screenSize.y- (BUTTON_SIZE + PADDING), y: screenSize.y - (BUTTON_SIZE + PADDING),
width: BUTTON_SIZE, width: BUTTON_SIZE,
height: BUTTON_SIZE, height: BUTTON_SIZE,
imageURL: HIFI_PUBLIC_BUCKET + "images/delete.png", imageURL: HIFI_PUBLIC_BUCKET + "images/delete.png",
color: { red: 255, green: 255, blue: 255}, color: {
alpha: 1 red: 255,
}); green: 255,
blue: 255
},
alpha: 1
});
var diceButton = Overlays.addOverlay("image", { var diceButton = Overlays.addOverlay("image", {
x: screenSize.x / 2 + PADDING, x: screenSize.x / 2 + PADDING,
y: screenSize.y - (BUTTON_SIZE + PADDING), y: screenSize.y - (BUTTON_SIZE + PADDING),
width: BUTTON_SIZE, width: BUTTON_SIZE,
height: BUTTON_SIZE, height: BUTTON_SIZE,
imageURL: HIFI_PUBLIC_BUCKET + "images/die.png", imageURL: HIFI_PUBLIC_BUCKET + "images/die.png",
color: { red: 255, green: 255, blue: 255}, color: {
alpha: 1 red: 255,
}); green: 255,
blue: 255
},
alpha: 1
});
var GRAVITY = -3.5; var GRAVITY = -3.5;
@ -68,74 +80,70 @@ var MAX_ANGULAR_SPEED = Math.PI;
function shootDice(position, velocity) { function shootDice(position, velocity) {
if (!Entities.canRez()) { if (!Entities.canRez()) {
Window.alert(INSUFFICIENT_PERMISSIONS_ERROR_MSG); Window.alert(INSUFFICIENT_PERMISSIONS_ERROR_MSG);
} else { } else {
for (var i = 0; i < NUMBER_OF_DICE; i++) { for (var i = 0; i < NUMBER_OF_DICE; i++) {
dice.push(Entities.addEntity( dice.push(Entities.addEntity(
{ type: "Model", {
modelURL: HIFI_PUBLIC_BUCKET + "models/props/Dice/goldDie.fbx", type: "Model",
position: position, modelURL: HIFI_PUBLIC_BUCKET + "models/props/Dice/goldDie.fbx",
velocity: velocity, position: position,
rotation: Quat.fromPitchYawRollDegrees(Math.random() * 360, Math.random() * 360, Math.random() * 360), velocity: velocity,
angularVelocity: { x: Math.random() * MAX_ANGULAR_SPEED, rotation: Quat.fromPitchYawRollDegrees(Math.random() * 360, Math.random() * 360, Math.random() * 360),
y: Math.random() * MAX_ANGULAR_SPEED, angularVelocity: {
z: Math.random() * MAX_ANGULAR_SPEED }, x: Math.random() * MAX_ANGULAR_SPEED,
lifetime: LIFETIME, y: Math.random() * MAX_ANGULAR_SPEED,
gravity: { x: 0, y: GRAVITY, z: 0 }, z: Math.random() * MAX_ANGULAR_SPEED
shapeType: "box", },
collisionsWillMove: true gravity: {
})); x: 0,
position = Vec3.sum(position, Vec3.multiply(DIE_SIZE, Vec3.normalize(Quat.getRight(Camera.getOrientation())))); y: GRAVITY,
} z: 0
},
lifetime: LIFETIME,
shapeType: "box",
collisionsWillMove: true,
collisionSoundURL: "http://s3.amazonaws.com/hifi-public/sounds/dice/diceCollide.wav"
}));
position = Vec3.sum(position, Vec3.multiply(DIE_SIZE, Vec3.normalize(Quat.getRight(Camera.getOrientation()))));
} }
}
} }
function deleteDice() { function deleteDice() {
while(dice.length > 0) { while (dice.length > 0) {
Entities.deleteEntity(dice.pop()); Entities.deleteEntity(dice.pop());
} }
} }
function entityCollisionWithEntity(entity1, entity2, collision) {
if (!madeSound) {
// Is it one of our dice?
for (var i = 0; i < dice.length; i++) {
if (!dice[i].isKnownID) {
dice[i] = Entities.identifyEntity(dice[i]);
}
if ((entity1.id == dice[i].id) || (entity2.id == dice[i].id)) {
madeSound = true;
Audio.playSound(rollSound, { position: collision.contactPoint, localOnly: true });
}
}
}
}
function mousePressEvent(event) { function mousePressEvent(event) {
var clickedText = false; var clickedText = false;
var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); var clickedOverlay = Overlays.getOverlayAtPoint({
if (clickedOverlay == offButton) { x: event.x,
deleteDice(); y: event.y
Script.stop(); });
} else if (clickedOverlay == deleteButton) { if (clickedOverlay == offButton) {
deleteDice(); deleteDice();
} else if (clickedOverlay == diceButton) { Script.stop();
var HOW_HARD = 2.0; } else if (clickedOverlay == deleteButton) {
var position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())); deleteDice();
var velocity = Vec3.multiply(HOW_HARD, Quat.getFront(Camera.getOrientation())); } else if (clickedOverlay == diceButton) {
shootDice(position, velocity); var HOW_HARD = 2.0;
madeSound = false; var position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation()));
} var velocity = Vec3.multiply(HOW_HARD, Quat.getFront(Camera.getOrientation()));
shootDice(position, velocity);
madeSound = false;
}
} }
function scriptEnding() { function scriptEnding() {
Overlays.deleteOverlay(offButton); Overlays.deleteOverlay(offButton);
Overlays.deleteOverlay(diceButton); Overlays.deleteOverlay(diceButton);
Overlays.deleteOverlay(deleteButton); Overlays.deleteOverlay(deleteButton);
} }
Entities.entityCollisionWithEntity.connect(entityCollisionWithEntity);
Controller.mousePressEvent.connect(mousePressEvent); Controller.mousePressEvent.connect(mousePressEvent);
Script.scriptEnding.connect(scriptEnding); Script.scriptEnding.connect(scriptEnding);

View file

@ -207,8 +207,8 @@ var toolBar = (function () {
}); });
newWebButton = toolBar.addTool({ newWebButton = toolBar.addTool({
imageURL: "https://s3.amazonaws.com/Oculus/earth17.svg", imageURL: "https://hifi-public.s3.amazonaws.com/images/www.svg",
subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, subImage: { x: 0, y: 0, width: 128, height: 128 },
width: toolWidth, width: toolWidth,
height: toolHeight, height: toolHeight,
alpha: 0.9, alpha: 0.9,

View file

@ -10,29 +10,43 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
var debugVisible = false; var debugVisible = false;
var FIELD_WIDTH = 1.21; var FIELD_WIDTH = 1.21;
var FIELD_LENGTH = 1.92; var FIELD_LENGTH = 1.92;
var FLOOR_THICKNESS = 0.20; var FLOOR_THICKNESS = 0.20;
var EDGE_THICKESS = 0.10; var EDGE_THICKESS = 0.10;
var EDGE_HEIGHT = 0.10; var EDGE_HEIGHT = 0.10;
var DROP_HEIGHT = 0.3; var DROP_HEIGHT = 0.3;
var PUCK_SIZE = 0.15; var PUCK_SIZE = 0.15;
var PUCK_THICKNESS = 0.05; var PUCK_THICKNESS = 0.05;
var PADDLE_SIZE = 0.15; var PADDLE_SIZE = 0.15;
var PADDLE_THICKNESS = 0.05; var PADDLE_THICKNESS = 0.05;
var ENTITY_SEARCH_RANGE = 500;
var GOAL_WIDTH = 0.35; var GOAL_WIDTH = 0.35;
var GRAVITY = -9.8; var GRAVITY = -9.8;
var LIFETIME = 6000; var LIFETIME = 6000;
var PUCK_DAMPING = 0.02; var PUCK_DAMPING = 0.02;
var PADDLE_DAMPING = 0.35; var PADDLE_DAMPING = 0.35;
var ANGULAR_DAMPING = 0.4; var ANGULAR_DAMPING = 0.4;
var PADDLE_ANGULAR_DAMPING = 0.75; var PADDLE_ANGULAR_DAMPING = 0.75;
var MODEL_SCALE = 1.52; var MODEL_SCALE = 1.52;
var MODEL_OFFSET = { x: 0, y: -0.19, z: 0 }; var MODEL_OFFSET = {
x: 0,
y: -0.19,
z: 0
};
var LIGHT_OFFSET = {
x: 0,
y: 0.2,
z: 0
};
var LIGHT_FLASH_TIME = 700;
var scoreSound = SoundCache.getSound("https://s3.amazonaws.com/hifi-public/sounds/Collisions-hitsandslaps/airhockey_score.wav"); var scoreSound = SoundCache.getSound("https://s3.amazonaws.com/hifi-public/sounds/Collisions-hitsandslaps/airhockey_score.wav");
@ -46,221 +60,551 @@ var puckCollisionModel = "http://headache.hungry.com/~seth/hifi/airHockeyPuck-hu
var paddleModel = "https://hifi-public.s3.amazonaws.com/ozan/props/airHockeyTable/airHockeyPaddle.obj" var paddleModel = "https://hifi-public.s3.amazonaws.com/ozan/props/airHockeyTable/airHockeyPaddle.obj"
var paddleCollisionModel = "http://headache.hungry.com/~seth/hifi/paddle-hull.obj" var paddleCollisionModel = "http://headache.hungry.com/~seth/hifi/paddle-hull.obj"
var center = Vec3.sum(MyAvatar.position, Vec3.multiply((FIELD_WIDTH + FIELD_LENGTH) * 0.60, Quat.getFront(Camera.getOrientation()))); HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
var screenSize = Controller.getViewportDimensions();
var BUTTON_SIZE = 32;
var PADDING = 3;
var center;
var edgeRestitution = 0.9; var edgeRestitution = 0.9;
var floorFriction = 0.01; var floorFriction = 0.01;
var floor = Entities.addEntity( var paddle1Pos, paddle2Pos;
{ type: "Box", var names = ['floor', 'table', 'paddle', 'edge', 'puck', 'hockeyLight'];
position: Vec3.subtract(center, { x: 0, y: 0, z: 0 }),
dimensions: { x: FIELD_WIDTH, y: FLOOR_THICKNESS, z: FIELD_LENGTH },
color: { red: 128, green: 128, blue: 128 },
gravity: { x: 0, y: 0, z: 0 },
ignoreCollisions: false,
locked: true,
friction: floorFriction,
visible: debugVisible,
lifetime: LIFETIME });
var edge1 = Entities.addEntity( var deleteButton = Overlays.addOverlay("image", {
{ type: "Box", x: screenSize.x / 2 - BUTTON_SIZE,
collisionSoundURL: hitSideSound, y: screenSize.y - (BUTTON_SIZE * 2 + PADDING),
position: Vec3.sum(center, { x: FIELD_WIDTH / 2.0, y: FLOOR_THICKNESS / 2.0, z: 0 }), width: BUTTON_SIZE,
dimensions: { x: EDGE_THICKESS, y: EDGE_HEIGHT, z: FIELD_LENGTH + EDGE_THICKESS }, height: BUTTON_SIZE,
color: { red: 100, green: 100, blue: 100 }, imageURL: HIFI_PUBLIC_BUCKET + "images/delete.png",
gravity: { x: 0, y: 0, z: 0 }, color: {
ignoreCollisions: false, red: 255,
visible: debugVisible, green: 255,
restitution: edgeRestitution, blue: 255
locked: true, },
lifetime: LIFETIME }); alpha: 1
});
var edge2 = Entities.addEntity( var spawnButton = Overlays.addOverlay("image", {
{ type: "Box", x: screenSize.x / 2 + PADDING,
collisionSoundURL: hitSideSound, y: screenSize.y - (BUTTON_SIZE * 2 + PADDING),
position: Vec3.sum(center, { x: -FIELD_WIDTH / 2.0, y: FLOOR_THICKNESS / 2.0, z: 0 }), width: BUTTON_SIZE,
dimensions: { x: EDGE_THICKESS, y: EDGE_HEIGHT, z: FIELD_LENGTH + EDGE_THICKESS }, height: BUTTON_SIZE,
color: { red: 100, green: 100, blue: 100 }, imageURL: HIFI_PUBLIC_BUCKET + "images/puck.png",
gravity: { x: 0, y: 0, z: 0 }, color: {
ignoreCollisions: false, red: 255,
visible: debugVisible, green: 255,
restitution: edgeRestitution, blue: 255
locked: true, },
lifetime: LIFETIME }); alpha: 1
});
var edge3a = Entities.addEntity(
{ type: "Box",
collisionSoundURL: hitSideSound,
position: Vec3.sum(center, { x: FIELD_WIDTH / 4.0 + (GOAL_WIDTH / 4.0), y: FLOOR_THICKNESS / 2.0, z: -FIELD_LENGTH / 2.0 }),
dimensions: { x: FIELD_WIDTH / 2.0 - GOAL_WIDTH / 2.0, y: EDGE_HEIGHT, z: EDGE_THICKESS },
color: { red: 100, green: 100, blue: 100 },
gravity: { x: 0, y: 0, z: 0 },
ignoreCollisions: false,
visible: debugVisible,
restitution: edgeRestitution,
locked: true,
lifetime: LIFETIME });
var edge3b = Entities.addEntity(
{ type: "Box",
collisionSoundURL: hitSideSound,
position: Vec3.sum(center, { x: -FIELD_WIDTH / 4.0 - (GOAL_WIDTH / 4.0), y: FLOOR_THICKNESS / 2.0, z: -FIELD_LENGTH / 2.0 }),
dimensions: { x: FIELD_WIDTH / 2.0 - GOAL_WIDTH / 2.0, y: EDGE_HEIGHT, z: EDGE_THICKESS },
color: { red: 100, green: 100, blue: 100 },
gravity: { x: 0, y: 0, z: 0 },
ignoreCollisions: false,
visible: debugVisible,
restitution: edgeRestitution,
locked: true,
lifetime: LIFETIME });
var edge4a = Entities.addEntity(
{ type: "Box",
collisionSoundURL: hitSideSound,
position: Vec3.sum(center, { x: FIELD_WIDTH / 4.0 + (GOAL_WIDTH / 4.0), y: FLOOR_THICKNESS / 2.0, z: FIELD_LENGTH / 2.0 }),
dimensions: { x: FIELD_WIDTH / 2.0 - GOAL_WIDTH / 2.0, y: EDGE_HEIGHT, z: EDGE_THICKESS },
color: { red: 100, green: 100, blue: 100 },
gravity: { x: 0, y: 0, z: 0 },
ignoreCollisions: false,
visible: debugVisible,
restitution: edgeRestitution,
locked: true,
lifetime: LIFETIME });
var edge4b = Entities.addEntity(
{ type: "Box",
collisionSoundURL: hitSideSound,
position: Vec3.sum(center, { x: -FIELD_WIDTH / 4.0 - (GOAL_WIDTH / 4.0), y: FLOOR_THICKNESS / 2.0, z: FIELD_LENGTH / 2.0 }),
dimensions: { x: FIELD_WIDTH / 2.0 - GOAL_WIDTH / 2.0, y: EDGE_HEIGHT, z: EDGE_THICKESS },
color: { red: 100, green: 100, blue: 100 },
gravity: { x: 0, y: 0, z: 0 },
ignoreCollisions: false,
visible: debugVisible,
restitution: edgeRestitution,
locked: true,
lifetime: LIFETIME });
var table = Entities.addEntity(
{ type: "Model",
modelURL: polyTable,
dimensions: Vec3.multiply({ x: 0.8, y: 0.45, z: 1.31 }, MODEL_SCALE),
position: Vec3.sum(center, MODEL_OFFSET),
ignoreCollisions: false,
visible: true,
locked: true,
lifetime: LIFETIME });
var floor, edge1, edge2, edge3a, edge3b, edge4a, edge4b, light;
var puck; var puck;
var paddle1, paddle2; var paddle1, paddle2;
// Create pucks // Create pucks
function makeNewProp(which) { function makeNewProp(which, position) {
if (which == "puck") { if (which == "puck") {
return Entities.addEntity( return Entities.addEntity({
{ type: "Model", name: 'puck',
modelURL: puckModel, type: "Model",
compoundShapeURL: puckCollisionModel, modelURL: puckModel,
collisionSoundURL: hitSound1, compoundShapeURL: puckCollisionModel,
position: Vec3.sum(center, { x: 0, y: DROP_HEIGHT, z: 0 }), collisionSoundURL: hitSound1,
dimensions: { x: PUCK_SIZE, y: PUCK_THICKNESS, z: PUCK_SIZE }, position: Vec3.sum(center, {
gravity: { x: 0, y: GRAVITY, z: 0 }, x: 0,
velocity: { x: 0, y: 0.05, z: 0 }, y: DROP_HEIGHT,
ignoreCollisions: false, z: 0
damping: PUCK_DAMPING, }),
angularDamping: ANGULAR_DAMPING, dimensions: {
lifetime: LIFETIME, x: PUCK_SIZE,
collisionsWillMove: true }); y: PUCK_THICKNESS,
} z: PUCK_SIZE
else if (which == "paddle1") { },
return Entities.addEntity( gravity: {
{ type: "Model", x: 0,
modelURL: paddleModel, y: GRAVITY,
compoundShapeURL: paddleCollisionModel, z: 0
collisionSoundURL: hitSound2, },
position: Vec3.sum(center, { x: 0, y: DROP_HEIGHT * 1.5, z: FIELD_LENGTH * 0.35 }), velocity: {
dimensions: { x: PADDLE_SIZE, y: PADDLE_THICKNESS, z: PADDLE_SIZE }, x: 0,
gravity: { x: 0, y: GRAVITY, z: 0 }, y: 0.05,
velocity: { x: 0, y: 0.07, z: 0 }, z: 0
ignoreCollisions: false, },
damping: PADDLE_DAMPING, ignoreCollisions: false,
angularDamping: PADDLE_ANGULAR_DAMPING, damping: PUCK_DAMPING,
lifetime: LIFETIME, angularDamping: ANGULAR_DAMPING,
collisionsWillMove: true }); lifetime: LIFETIME,
} collisionsWillMove: true
else if (which == "paddle2") { });
return Entities.addEntity( } else if (which == "paddle1") {
{ type: "Model", paddle1Pos = Vec3.sum(center, {
modelURL: paddleModel, x: 0,
compoundShapeURL: paddleCollisionModel, y: DROP_HEIGHT * 1.5,
collisionSoundURL: hitSound2, z: FIELD_LENGTH * 0.35
position: Vec3.sum(center, { x: 0, y: DROP_HEIGHT * 1.5, z: -FIELD_LENGTH * 0.35 }), });
dimensions: { x: PADDLE_SIZE, y: PADDLE_THICKNESS, z: PADDLE_SIZE }, return Entities.addEntity({
gravity: { x: 0, y: GRAVITY, z: 0 }, name: "paddle",
velocity: { x: 0, y: 0.07, z: 0 }, type: "Model",
ignoreCollisions: false, modelURL: paddleModel,
damping: PADDLE_DAMPING, compoundShapeURL: paddleCollisionModel,
angularDamping: PADDLE_ANGULAR_DAMPING, collisionSoundURL: hitSound2,
lifetime: LIFETIME, position: paddle1Pos,
collisionsWillMove: true }); dimensions: {
} x: PADDLE_SIZE,
y: PADDLE_THICKNESS,
z: PADDLE_SIZE
},
gravity: {
x: 0,
y: GRAVITY,
z: 0
},
velocity: {
x: 0,
y: 0.07,
z: 0
},
ignoreCollisions: false,
damping: PADDLE_DAMPING,
angularDamping: PADDLE_ANGULAR_DAMPING,
lifetime: LIFETIME,
collisionsWillMove: true
});
} else if (which == "paddle2") {
paddle2Pos = Vec3.sum(center, {
x: 0,
y: DROP_HEIGHT * 1.5,
z: -FIELD_LENGTH * 0.35
});
return Entities.addEntity({
name: "paddle",
type: "Model",
modelURL: paddleModel,
compoundShapeURL: paddleCollisionModel,
collisionSoundURL: hitSound2,
position: paddle2Pos,
dimensions: {
x: PADDLE_SIZE,
y: PADDLE_THICKNESS,
z: PADDLE_SIZE
},
gravity: {
x: 0,
y: GRAVITY,
z: 0
},
velocity: {
x: 0,
y: 0.07,
z: 0
},
ignoreCollisions: false,
damping: PADDLE_DAMPING,
angularDamping: PADDLE_ANGULAR_DAMPING,
lifetime: LIFETIME,
collisionsWillMove: true
});
}
} }
puck = makeNewProp("puck");
paddle1 = makeNewProp("paddle1");
paddle2 = makeNewProp("paddle2");
function update(deltaTime) { function update(deltaTime) {
if (Math.random() < 0.1) { if (Math.random() < 0.1) {
puckProps = Entities.getEntityProperties(puck); puckProps = Entities.getEntityProperties(puck);
paddle1Props = Entities.getEntityProperties(paddle1); paddle1Props = Entities.getEntityProperties(paddle1);
paddle2Props = Entities.getEntityProperties(paddle2); paddle2Props = Entities.getEntityProperties(paddle2);
if (puckProps.position.y < (center.y - DROP_HEIGHT)) { if (puckProps.position.y < (center.y - DROP_HEIGHT)) {
Audio.playSound(scoreSound, { score();
position: center, }
volume: 1.0
}); if (paddle1Props.position.y < (center.y - DROP_HEIGHT)) {
Entities.deleteEntity(puck); Entities.deleteEntity(paddle1);
puck = makeNewProp("puck"); paddle1 = makeNewProp("paddle1");
} }
if (paddle2Props.position.y < (center.y - DROP_HEIGHT)) {
if (paddle1Props.position.y < (center.y - DROP_HEIGHT)) { Entities.deleteEntity(paddle2);
Entities.deleteEntity(paddle1); paddle2 = makeNewProp("paddle2");
paddle1 = makeNewProp("paddle1"); }
} }
if (paddle2Props.position.y < (center.y - DROP_HEIGHT)) { }
Entities.deleteEntity(paddle2);
paddle2 = makeNewProp("paddle2"); function score() {
} Audio.playSound(scoreSound, {
} position: center,
volume: 1.0
});
puckDropPosition = Entities.getEntityProperties(puck).position;
var newPosition;
if (Vec3.distance(puckDropPosition, paddle1Pos) > Vec3.distance(puckDropPosition, paddle2Pos)) {
newPosition = paddle2Pos;
} else {
newPosition = paddle1Pos;
}
Entities.editEntity(puck, {
position: newPosition,
velocity: {
x: 0,
y: 0.05,
z: 0
}
});
Entities.editEntity(light, {
visible: true
});
Script.setTimeout(function() {
Entities.editEntity(light, {
visible: false
});
}, LIGHT_FLASH_TIME);
}
function mousePressEvent(event) {
var clickedOverlay = Overlays.getOverlayAtPoint({
x: event.x,
y: event.y
});
if (clickedOverlay == spawnButton) {
spawnAllTheThings();
} else if (clickedOverlay == deleteButton) {
deleteAllTheThings();
}
}
function spawnAllTheThings() {
center = Vec3.sum(MyAvatar.position, Vec3.multiply((FIELD_WIDTH + FIELD_LENGTH) * 0.60, Quat.getFront(Camera.getOrientation())));
floor = Entities.addEntity({
name: "floor",
type: "Box",
position: Vec3.subtract(center, {
x: 0,
y: 0,
z: 0
}),
dimensions: {
x: FIELD_WIDTH,
y: FLOOR_THICKNESS,
z: FIELD_LENGTH
},
color: {
red: 128,
green: 128,
blue: 128
},
gravity: {
x: 0,
y: 0,
z: 0
},
ignoreCollisions: false,
locked: true,
friction: floorFriction,
visible: debugVisible,
lifetime: LIFETIME
});
edge1 = Entities.addEntity({
name: 'edge',
type: "Box",
collisionSoundURL: hitSideSound,
position: Vec3.sum(center, {
x: FIELD_WIDTH / 2.0,
y: FLOOR_THICKNESS / 2.0,
z: 0
}),
dimensions: {
x: EDGE_THICKESS,
y: EDGE_HEIGHT,
z: FIELD_LENGTH + EDGE_THICKESS
},
color: {
red: 100,
green: 100,
blue: 100
},
gravity: {
x: 0,
y: 0,
z: 0
},
ignoreCollisions: false,
visible: debugVisible,
restitution: edgeRestitution,
locked: true,
lifetime: LIFETIME
});
edge2 = Entities.addEntity({
name: 'edge',
type: "Box",
collisionSoundURL: hitSideSound,
position: Vec3.sum(center, {
x: -FIELD_WIDTH / 2.0,
y: FLOOR_THICKNESS / 2.0,
z: 0
}),
dimensions: {
x: EDGE_THICKESS,
y: EDGE_HEIGHT,
z: FIELD_LENGTH + EDGE_THICKESS
},
color: {
red: 100,
green: 100,
blue: 100
},
gravity: {
x: 0,
y: 0,
z: 0
},
ignoreCollisions: false,
visible: debugVisible,
restitution: edgeRestitution,
locked: true,
lifetime: LIFETIME
});
edge3a = Entities.addEntity({
name: 'edge',
type: "Box",
collisionSoundURL: hitSideSound,
position: Vec3.sum(center, {
x: FIELD_WIDTH / 4.0 + (GOAL_WIDTH / 4.0),
y: FLOOR_THICKNESS / 2.0,
z: -FIELD_LENGTH / 2.0
}),
dimensions: {
x: FIELD_WIDTH / 2.0 - GOAL_WIDTH / 2.0,
y: EDGE_HEIGHT,
z: EDGE_THICKESS
},
color: {
red: 100,
green: 100,
blue: 100
},
gravity: {
x: 0,
y: 0,
z: 0
},
ignoreCollisions: false,
visible: debugVisible,
restitution: edgeRestitution,
locked: true,
lifetime: LIFETIME
});
edge3b = Entities.addEntity({
name: 'edge',
type: "Box",
collisionSoundURL: hitSideSound,
position: Vec3.sum(center, {
x: -FIELD_WIDTH / 4.0 - (GOAL_WIDTH / 4.0),
y: FLOOR_THICKNESS / 2.0,
z: -FIELD_LENGTH / 2.0
}),
dimensions: {
x: FIELD_WIDTH / 2.0 - GOAL_WIDTH / 2.0,
y: EDGE_HEIGHT,
z: EDGE_THICKESS
},
color: {
red: 100,
green: 100,
blue: 100
},
gravity: {
x: 0,
y: 0,
z: 0
},
ignoreCollisions: false,
visible: debugVisible,
restitution: edgeRestitution,
locked: true,
lifetime: LIFETIME
});
edge4a = Entities.addEntity({
name: 'edge',
type: "Box",
collisionSoundURL: hitSideSound,
position: Vec3.sum(center, {
x: FIELD_WIDTH / 4.0 + (GOAL_WIDTH / 4.0),
y: FLOOR_THICKNESS / 2.0,
z: FIELD_LENGTH / 2.0
}),
dimensions: {
x: FIELD_WIDTH / 2.0 - GOAL_WIDTH / 2.0,
y: EDGE_HEIGHT,
z: EDGE_THICKESS
},
color: {
red: 100,
green: 100,
blue: 100
},
gravity: {
x: 0,
y: 0,
z: 0
},
ignoreCollisions: false,
visible: debugVisible,
restitution: edgeRestitution,
locked: true,
lifetime: LIFETIME
});
edge4b = Entities.addEntity({
name: 'edge',
type: "Box",
collisionSoundURL: hitSideSound,
position: Vec3.sum(center, {
x: -FIELD_WIDTH / 4.0 - (GOAL_WIDTH / 4.0),
y: FLOOR_THICKNESS / 2.0,
z: FIELD_LENGTH / 2.0
}),
dimensions: {
x: FIELD_WIDTH / 2.0 - GOAL_WIDTH / 2.0,
y: EDGE_HEIGHT,
z: EDGE_THICKESS
},
color: {
red: 100,
green: 100,
blue: 100
},
gravity: {
x: 0,
y: 0,
z: 0
},
ignoreCollisions: false,
visible: debugVisible,
restitution: edgeRestitution,
locked: true,
lifetime: LIFETIME
});
table = Entities.addEntity({
name: "table",
type: "Model",
modelURL: polyTable,
dimensions: Vec3.multiply({
x: 0.8,
y: 0.45,
z: 1.31
}, MODEL_SCALE),
position: Vec3.sum(center, MODEL_OFFSET),
ignoreCollisions: false,
visible: true,
locked: true,
lifetime: LIFETIME
});
light = Entities.addEntity({
name: "hockeyLight",
type: "Light",
dimensions: {
x: 5,
y: 5,
z: 5
},
position: Vec3.sum(center, LIGHT_OFFSET),
intensity: 5,
color: {
red: 200,
green: 20,
blue: 200
},
visible: false
});
puck = makeNewProp("puck");
paddle1 = makeNewProp("paddle1");
paddle2 = makeNewProp("paddle2");
Script.update.connect(update);
}
function deleteAllTheThings() {
Script.update.disconnect(update);
//delete all nearby entitites that are named any the names from our names array
var nearbyEntities = Entities.findEntities(MyAvatar.position, ENTITY_SEARCH_RANGE);
for (var i = 0; i < nearbyEntities.length; i++) {
var entityName = Entities.getEntityProperties(nearbyEntities[i]).name;
for (var j = 0; j < names.length; j++) {
if (names[j] === entityName) {
//We have a mach- delete this entity
Entities.editEntity(nearbyEntities[i], {
locked: false
});
Entities.deleteEntity(nearbyEntities[i]);
}
}
}
} }
function scriptEnding() { function scriptEnding() {
Entities.editEntity(edge1, { locked: false }); Overlays.deleteOverlay(spawnButton);
Entities.editEntity(edge2, { locked: false }); Overlays.deleteOverlay(deleteButton);
Entities.editEntity(edge3a, { locked: false });
Entities.editEntity(edge3b, { locked: false }); Entities.editEntity(edge1, {
Entities.editEntity(edge4a, { locked: false }); locked: false
Entities.editEntity(edge4b, { locked: false }); });
Entities.editEntity(floor, { locked: false }); Entities.editEntity(edge2, {
Entities.editEntity(table, { locked: false }); locked: false
});
Entities.editEntity(edge3a, {
locked: false
});
Entities.editEntity(edge3b, {
locked: false
});
Entities.editEntity(edge4a, {
locked: false
});
Entities.editEntity(edge4b, {
locked: false
});
Entities.editEntity(floor, {
locked: false
});
Entities.editEntity(table, {
locked: false
});
Entities.deleteEntity(edge1);
Entities.deleteEntity(edge2); Entities.deleteEntity(edge1);
Entities.deleteEntity(edge3a); Entities.deleteEntity(edge2);
Entities.deleteEntity(edge3b); Entities.deleteEntity(edge3a);
Entities.deleteEntity(edge4a); Entities.deleteEntity(edge3b);
Entities.deleteEntity(edge4b); Entities.deleteEntity(edge4a);
Entities.deleteEntity(floor); Entities.deleteEntity(edge4b);
Entities.deleteEntity(puck); Entities.deleteEntity(floor);
Entities.deleteEntity(paddle1); Entities.deleteEntity(puck);
Entities.deleteEntity(paddle2); Entities.deleteEntity(paddle1);
Entities.deleteEntity(table); Entities.deleteEntity(paddle2);
Entities.deleteEntity(table);
Entities.deleteEntity(light);
} }
Script.update.connect(update); Controller.mousePressEvent.connect(mousePressEvent);
Script.scriptEnding.connect(scriptEnding); Script.scriptEnding.connect(scriptEnding);

View file

@ -13,7 +13,6 @@
var isGrabbing = false; var isGrabbing = false;
var grabbedEntity = null; var grabbedEntity = null;
var lineEntityID = null;
var prevMouse = {}; var prevMouse = {};
var deltaMouse = { var deltaMouse = {
z: 0 z: 0
@ -39,9 +38,9 @@ var angularVelocity = {
var grabSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/CloseClamp.wav"); var grabSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/CloseClamp.wav");
var releaseSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/ReleaseClamp.wav"); var releaseSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/ReleaseClamp.wav");
var VOLUME = 0.10; var VOLUME = 0.0;
var DROP_DISTANCE = 5.0; var DROP_DISTANCE = 0.10;
var DROP_COLOR = { var DROP_COLOR = {
red: 200, red: 200,
green: 200, green: 200,
@ -92,14 +91,6 @@ function mousePressEvent(event) {
gravity: {x: 0, y: 0, z: 0} gravity: {x: 0, y: 0, z: 0}
}); });
lineEntityID = Entities.addEntity({
type: "Line",
position: nearLinePoint(targetPosition),
dimensions: Vec3.subtract(targetPosition, nearLinePoint(targetPosition)),
color: { red: 255, green: 255, blue: 255 },
lifetime: 300 // if someone crashes while moving something, don't leave the line there forever.
});
Audio.playSound(grabSound, { Audio.playSound(grabSound, {
position: props.position, position: props.position,
volume: VOLUME volume: VOLUME
@ -145,8 +136,6 @@ function mouseReleaseEvent() {
}); });
targetPosition = null; targetPosition = null;
Entities.deleteEntity(lineEntityID);
Audio.playSound(releaseSound, { Audio.playSound(releaseSound, {
position: entityProps.position, position: entityProps.position,
volume: VOLUME volume: VOLUME
@ -193,10 +182,6 @@ function mouseMoveEvent(event) {
angularVelocity = Vec3.multiply((theta / dT), axisAngle); angularVelocity = Vec3.multiply((theta / dT), axisAngle);
} }
Entities.editEntity(lineEntityID, {
position: nearLinePoint(targetPosition),
dimensions: Vec3.subtract(targetPosition, nearLinePoint(targetPosition))
});
} }
prevMouse.x = event.x; prevMouse.x = event.x;
prevMouse.y = event.y; prevMouse.y = event.y;

View file

@ -13,7 +13,6 @@
var isGrabbing = false; var isGrabbing = false;
var grabbedEntity = null; var grabbedEntity = null;
var lineEntityID = null;
var prevMouse = {}; var prevMouse = {};
var deltaMouse = { var deltaMouse = {
z: 0 z: 0
@ -91,14 +90,6 @@ function mousePressEvent(event) {
gravity: {x: 0, y: 0, z: 0} gravity: {x: 0, y: 0, z: 0}
}); });
lineEntityID = Entities.addEntity({
type: "Line",
position: nearLinePoint(targetPosition),
dimensions: Vec3.subtract(targetPosition, nearLinePoint(targetPosition)),
color: { red: 255, green: 255, blue: 255 },
lifetime: 300 // if someone crashes while moving something, don't leave the line there forever.
});
Audio.playSound(grabSound, { Audio.playSound(grabSound, {
position: props.position, position: props.position,
volume: 0.4 volume: 0.4
@ -144,8 +135,6 @@ function mouseReleaseEvent() {
}); });
targetPosition = null; targetPosition = null;
Entities.deleteEntity(lineEntityID);
Audio.playSound(grabSound, { Audio.playSound(grabSound, {
position: entityProps.position, position: entityProps.position,
volume: 0.25 volume: 0.25
@ -191,11 +180,6 @@ function mouseMoveEvent(event) {
axisAngle = Quat.axis(dQ); axisAngle = Quat.axis(dQ);
angularVelocity = Vec3.multiply((theta / dT), axisAngle); angularVelocity = Vec3.multiply((theta / dT), axisAngle);
} }
Entities.editEntity(lineEntityID, {
position: nearLinePoint(targetPosition),
dimensions: Vec3.subtract(targetPosition, nearLinePoint(targetPosition))
});
} }
prevMouse.x = event.x; prevMouse.x = event.x;
prevMouse.y = event.y; prevMouse.y = event.y;

View file

@ -24,23 +24,28 @@ function removeLine() {
function createOrUpdateLine(event) { function createOrUpdateLine(event) {
var pickRay = Camera.computePickRay(event.x, event.y); var pickRay = Camera.computePickRay(event.x, event.y);
var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking
var props = Entities.getEntityProperties(intersection.entityID);
if (lineIsRezzed) { if (intersection.intersects) {
Entities.editEntity(lineEntityID, { var dim = Vec3.subtract(intersection.intersection, nearLinePoint(intersection.intersection));
position: nearLinePoint(intersection.intersection), if (lineIsRezzed) {
dimensions: Vec3.subtract(intersection.intersection, nearLinePoint(intersection.intersection)), Entities.editEntity(lineEntityID, {
lifetime: 30 // renew lifetime position: nearLinePoint(intersection.intersection),
}); dimensions: dim,
lifetime: 15 + props.lifespan // renew lifetime
});
} else {
lineIsRezzed = true;
lineEntityID = Entities.addEntity({
type: "Line",
position: nearLinePoint(intersection.intersection),
dimensions: dim,
color: { red: 255, green: 255, blue: 255 },
lifetime: 15 // if someone crashes while pointing, don't leave the line there forever.
});
}
} else { } else {
lineIsRezzed = true; removeLine();
lineEntityID = Entities.addEntity({
type: "Line",
position: nearLinePoint(intersection.intersection),
dimensions: Vec3.subtract(intersection.intersection, nearLinePoint(intersection.intersection)),
color: { red: 255, green: 255, blue: 255 },
lifetime: 30 // if someone crashes while pointing, don't leave the line there forever.
});
} }
} }
@ -49,13 +54,8 @@ function mousePressEvent(event) {
if (!event.isLeftButton) { if (!event.isLeftButton) {
return; return;
} }
if (lineIsRezzed) { Controller.mouseMoveEvent.connect(mouseMoveEvent);
return;
}
createOrUpdateLine(event); createOrUpdateLine(event);
if (lineIsRezzed) {
Controller.mouseMoveEvent.connect(mouseMoveEvent);
}
} }
@ -64,10 +64,11 @@ function mouseMoveEvent(event) {
} }
function mouseReleaseEvent() { function mouseReleaseEvent(event) {
if (lineIsRezzed) { if (!event.isLeftButton) {
Controller.mouseMoveEvent.disconnect(mouseMoveEvent); return;
} }
Controller.mouseMoveEvent.disconnect(mouseMoveEvent);
removeLine(); removeLine();
} }

View file

@ -3077,13 +3077,10 @@ PickRay Application::computePickRay(float x, float y) const {
y /= size.y; y /= size.y;
PickRay result; PickRay result;
if (isHMDMode()) { if (isHMDMode()) {
ApplicationOverlay::computeHmdPickRay(glm::vec2(x, y), result.origin, result.direction); getApplicationOverlay().computeHmdPickRay(glm::vec2(x, y), result.origin, result.direction);
} else { } else {
if (activeRenderingThread) { auto frustum = activeRenderingThread ? getDisplayViewFrustum() : getViewFrustum();
getDisplayViewFrustum()->computePickRay(x, y, result.origin, result.direction); frustum->computePickRay(x, y, result.origin, result.direction);
} else {
getViewFrustum()->computePickRay(x, y, result.origin, result.direction);
}
} }
return result; return result;
} }
@ -3111,8 +3108,8 @@ QImage Application::renderAvatarBillboard() {
ViewFrustum* Application::getViewFrustum() { ViewFrustum* Application::getViewFrustum() {
#ifdef DEBUG #ifdef DEBUG
if (QThread::currentThread() == activeRenderingThread) { if (QThread::currentThread() == activeRenderingThread) {
// FIXME, should this be an assert? // FIXME, figure out a better way to do this
qWarning() << "Calling Application::getViewFrustum() from the active rendering thread, did you mean Application::getDisplayViewFrustum()?"; //qWarning() << "Calling Application::getViewFrustum() from the active rendering thread, did you mean Application::getDisplayViewFrustum()?";
} }
#endif #endif
return &_viewFrustum; return &_viewFrustum;
@ -3121,8 +3118,8 @@ ViewFrustum* Application::getViewFrustum() {
const ViewFrustum* Application::getViewFrustum() const { const ViewFrustum* Application::getViewFrustum() const {
#ifdef DEBUG #ifdef DEBUG
if (QThread::currentThread() == activeRenderingThread) { if (QThread::currentThread() == activeRenderingThread) {
// FIXME, should this be an assert? // FIXME, figure out a better way to do this
qWarning() << "Calling Application::getViewFrustum() from the active rendering thread, did you mean Application::getDisplayViewFrustum()?"; //qWarning() << "Calling Application::getViewFrustum() from the active rendering thread, did you mean Application::getDisplayViewFrustum()?";
} }
#endif #endif
return &_viewFrustum; return &_viewFrustum;
@ -3131,8 +3128,8 @@ const ViewFrustum* Application::getViewFrustum() const {
ViewFrustum* Application::getDisplayViewFrustum() { ViewFrustum* Application::getDisplayViewFrustum() {
#ifdef DEBUG #ifdef DEBUG
if (QThread::currentThread() != activeRenderingThread) { if (QThread::currentThread() != activeRenderingThread) {
// FIXME, should this be an assert? // FIXME, figure out a better way to do this
qWarning() << "Calling Application::getDisplayViewFrustum() from outside the active rendering thread or outside rendering, did you mean Application::getViewFrustum()?"; // qWarning() << "Calling Application::getDisplayViewFrustum() from outside the active rendering thread or outside rendering, did you mean Application::getViewFrustum()?";
} }
#endif #endif
return &_displayViewFrustum; return &_displayViewFrustum;
@ -3141,8 +3138,8 @@ ViewFrustum* Application::getDisplayViewFrustum() {
const ViewFrustum* Application::getDisplayViewFrustum() const { const ViewFrustum* Application::getDisplayViewFrustum() const {
#ifdef DEBUG #ifdef DEBUG
if (QThread::currentThread() != activeRenderingThread) { if (QThread::currentThread() != activeRenderingThread) {
// FIXME, should this be an assert? // FIXME, figure out a better way to do this
qWarning() << "Calling Application::getDisplayViewFrustum() from outside the active rendering thread or outside rendering, did you mean Application::getViewFrustum()?"; // qWarning() << "Calling Application::getDisplayViewFrustum() from outside the active rendering thread or outside rendering, did you mean Application::getViewFrustum()?";
} }
#endif #endif
return &_displayViewFrustum; return &_displayViewFrustum;

View file

@ -393,7 +393,7 @@ Menu::Menu() {
#ifdef HAVE_DDE #ifdef HAVE_DDE
faceTrackingMenu->addSeparator(); faceTrackingMenu->addSeparator();
QAction* binaryEyelidControl = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::BinaryEyelidControl, 0, true); QAction* binaryEyelidControl = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::BinaryEyelidControl, 0, true);
binaryEyelidControl->setVisible(false); binaryEyelidControl->setVisible(true); // DDE face tracking is on by default
QAction* useAudioForMouth = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::UseAudioForMouth, 0, true); QAction* useAudioForMouth = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::UseAudioForMouth, 0, true);
useAudioForMouth->setVisible(true); // DDE face tracking is on by default useAudioForMouth->setVisible(true); // DDE face tracking is on by default
QAction* ddeFiltering = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::VelocityFilter, 0, true); QAction* ddeFiltering = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::VelocityFilter, 0, true);

View file

@ -388,7 +388,7 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
// Compute relative rotation // Compute relative rotation
rotation = glm::inverse(_referenceRotation) * rotation; rotation = glm::inverse(_referenceRotation) * rotation;
if (isFiltering) { if (isFiltering) {
glm::quat r = rotation * glm::inverse(_headRotation); glm::quat r = glm::normalize(rotation * glm::inverse(_headRotation));
float theta = 2 * acos(r.w); float theta = 2 * acos(r.w);
glm::vec3 angularVelocity; glm::vec3 angularVelocity;
if (theta > EPSILON) { if (theta > EPSILON) {

View file

@ -213,7 +213,7 @@ void Faceshift::receive(const QByteArray& buffer) {
glm::quat newRotation = glm::quat(data.m_headRotation.w, -data.m_headRotation.x, glm::quat newRotation = glm::quat(data.m_headRotation.w, -data.m_headRotation.x,
data.m_headRotation.y, -data.m_headRotation.z); data.m_headRotation.y, -data.m_headRotation.z);
// Compute angular velocity of the head // Compute angular velocity of the head
glm::quat r = newRotation * glm::inverse(_headRotation); glm::quat r = glm::normalize(newRotation * glm::inverse(_headRotation));
float theta = 2 * acos(r.w); float theta = 2 * acos(r.w);
if (theta > EPSILON) { if (theta > EPSILON) {
float rMag = glm::length(glm::vec3(r.x, r.y, r.z)); float rMag = glm::length(glm::vec3(r.x, r.y, r.z));

View file

@ -301,9 +301,14 @@ void ApplicationOverlay::displayOverlayTextureHmd(Camera& whichCamera) {
//Update and draw the magnifiers //Update and draw the magnifiers
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar(); MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
const glm::quat& orientation = myAvatar->getOrientation(); const glm::quat& orientation = myAvatar->getOrientation();
const glm::vec3& position = myAvatar->getDefaultEyePosition(); // Always display the HMD overlay relative to the camera position but
// remove the HMD pose offset. This results in an overlay that sticks with you
// even in third person mode, but isn't drawn at a fixed distance.
glm::vec3 position = whichCamera.getPosition();
position -= qApp->getCamera()->getHmdPosition();
const float scale = myAvatar->getScale() * _oculusUIRadius; const float scale = myAvatar->getScale() * _oculusUIRadius;
// glm::vec3 eyeOffset = setEyeOffsetPosition;
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glPushMatrix(); { glPushMatrix(); {
glTranslatef(position.x, position.y, position.z); glTranslatef(position.x, position.y, position.z);
@ -453,19 +458,32 @@ void ApplicationOverlay::displayOverlayTextureStereo(Camera& whichCamera, float
glEnable(GL_LIGHTING); glEnable(GL_LIGHTING);
} }
void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) { void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const {
const MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar(); cursorPos *= qApp->getCanvasSize();
cursorPos = 0.5f - cursorPos; const glm::vec2 projection = screenToSpherical(cursorPos);
cursorPos *= MOUSE_RANGE; // The overlay space orientation of the mouse coordinates
const glm::quat orientation(glm::vec3(cursorPos, 0.0f)); const glm::quat orientation(glm::vec3(-projection.y, projection.x, 0.0f));
const glm::vec3 localDirection = orientation * IDENTITY_FRONT; // FIXME We now have the direction of the ray FROM THE DEFAULT HEAD POSE.
// Now we need to account for the actual camera position relative to the overlay
glm::vec3 overlaySpaceDirection = glm::normalize(orientation * IDENTITY_FRONT);
// Get cursor position
const glm::vec3 cursorDir = myAvatar->getDefaultEyePosition() + myAvatar->getOrientation() * localDirection;
// Ray start where the eye position is and stop where the cursor is const glm::vec3& hmdPosition = qApp->getCamera()->getHmdPosition();
origin = myAvatar->getEyePosition(); const glm::quat& hmdOrientation = qApp->getCamera()->getHmdRotation();
direction = cursorDir - origin;
// We need the RAW camera orientation and position, because this is what the overlay is
// rendered relative to
const glm::vec3 overlayPosition = qApp->getCamera()->getPosition() - hmdPosition;
const glm::quat overlayOrientation = qApp->getCamera()->getRotation() * glm::inverse(hmdOrientation);
// Intersection UI overlay space
glm::vec3 worldSpaceDirection = overlayOrientation * overlaySpaceDirection;
glm::vec3 intersectionWithUi = glm::normalize(worldSpaceDirection) * _oculusUIRadius;
intersectionWithUi += overlayPosition;
// Intersection in world space
origin = overlayPosition + hmdPosition;
direction = glm::normalize(intersectionWithUi - origin);
} }
//Caculate the click location using one of the sixense controllers. Scale is not applied //Caculate the click location using one of the sixense controllers. Scale is not applied

View file

@ -58,12 +58,12 @@ public:
glm::vec2 overlayToSpherical(const glm::vec2 & overlayPos) const; glm::vec2 overlayToSpherical(const glm::vec2 & overlayPos) const;
glm::vec2 screenToOverlay(const glm::vec2 & screenPos) const; glm::vec2 screenToOverlay(const glm::vec2 & screenPos) const;
glm::vec2 overlayToScreen(const glm::vec2 & overlayPos) const; glm::vec2 overlayToScreen(const glm::vec2 & overlayPos) const;
void computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const;
static glm::vec2 directionToSpherical(const glm::vec3 & direction); static glm::vec2 directionToSpherical(const glm::vec3 & direction);
static glm::vec3 sphericalToDirection(const glm::vec2 & sphericalPos); static glm::vec3 sphericalToDirection(const glm::vec2 & sphericalPos);
static glm::vec2 screenToSpherical(const glm::vec2 & screenPos); static glm::vec2 screenToSpherical(const glm::vec2 & screenPos);
static glm::vec2 sphericalToScreen(const glm::vec2 & sphericalPos); static glm::vec2 sphericalToScreen(const glm::vec2 & sphericalPos);
static void computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction);
private: private:
// Interleaved vertex data // Interleaved vertex data

View file

@ -392,6 +392,87 @@ void EntityTreeRenderer::leaveAllEntities() {
_lastAvatarPosition = _viewState->getAvatarPosition() + glm::vec3((float)TREE_SCALE); _lastAvatarPosition = _viewState->getAvatarPosition() + glm::vec3((float)TREE_SCALE);
} }
} }
void EntityTreeRenderer::applyZonePropertiesToScene(const ZoneEntityItem* zone) {
QSharedPointer<SceneScriptingInterface> scene = DependencyManager::get<SceneScriptingInterface>();
if (zone) {
if (!_hasPreviousZone) {
_previousKeyLightColor = scene->getKeyLightColor();
_previousKeyLightIntensity = scene->getKeyLightIntensity();
_previousKeyLightAmbientIntensity = scene->getKeyLightAmbientIntensity();
_previousKeyLightDirection = scene->getKeyLightDirection();
_previousStageSunModelEnabled = scene->isStageSunModelEnabled();
_previousStageLongitude = scene->getStageLocationLongitude();
_previousStageLatitude = scene->getStageLocationLatitude();
_previousStageAltitude = scene->getStageLocationAltitude();
_previousStageHour = scene->getStageDayTime();
_previousStageDay = scene->getStageYearTime();
_hasPreviousZone = true;
}
scene->setKeyLightColor(zone->getKeyLightColorVec3());
scene->setKeyLightIntensity(zone->getKeyLightIntensity());
scene->setKeyLightAmbientIntensity(zone->getKeyLightAmbientIntensity());
scene->setKeyLightDirection(zone->getKeyLightDirection());
scene->setStageSunModelEnable(zone->getStageProperties().getSunModelEnabled());
scene->setStageLocation(zone->getStageProperties().getLongitude(), zone->getStageProperties().getLatitude(),
zone->getStageProperties().getAltitude());
scene->setStageDayTime(zone->getStageProperties().calculateHour());
scene->setStageYearTime(zone->getStageProperties().calculateDay());
if (zone->getBackgroundMode() == BACKGROUND_MODE_ATMOSPHERE) {
EnvironmentData data = zone->getEnvironmentData();
glm::vec3 keyLightDirection = scene->getKeyLightDirection();
glm::vec3 inverseKeyLightDirection = keyLightDirection * -1.0f;
// NOTE: is this right? It seems like the "sun" should be based on the center of the
// atmosphere, not where the camera is.
glm::vec3 keyLightLocation = _viewState->getAvatarPosition()
+ (inverseKeyLightDirection * data.getAtmosphereOuterRadius());
data.setSunLocation(keyLightLocation);
const float KEY_LIGHT_INTENSITY_TO_SUN_BRIGHTNESS_RATIO = 20.0f;
float sunBrightness = scene->getKeyLightIntensity() * KEY_LIGHT_INTENSITY_TO_SUN_BRIGHTNESS_RATIO;
data.setSunBrightness(sunBrightness);
_viewState->overrideEnvironmentData(data);
scene->getSkyStage()->setBackgroundMode(model::SunSkyStage::SKY_DOME);
} else {
_viewState->endOverrideEnvironmentData();
auto stage = scene->getSkyStage();
if (zone->getBackgroundMode() == BACKGROUND_MODE_SKYBOX) {
stage->getSkybox()->setColor(zone->getSkyboxProperties().getColorVec3());
if (zone->getSkyboxProperties().getURL().isEmpty()) {
stage->getSkybox()->clearCubemap();
} else {
// Update the Texture of the Skybox with the one pointed by this zone
auto cubeMap = DependencyManager::get<TextureCache>()->getTexture(zone->getSkyboxProperties().getURL(), CUBE_TEXTURE);
stage->getSkybox()->setCubemap(cubeMap->getGPUTexture());
}
stage->setBackgroundMode(model::SunSkyStage::SKY_BOX);
} else {
stage->setBackgroundMode(model::SunSkyStage::SKY_DOME); // let the application atmosphere through
}
}
} else {
if (_hasPreviousZone) {
scene->setKeyLightColor(_previousKeyLightColor);
scene->setKeyLightIntensity(_previousKeyLightIntensity);
scene->setKeyLightAmbientIntensity(_previousKeyLightAmbientIntensity);
scene->setKeyLightDirection(_previousKeyLightDirection);
scene->setStageSunModelEnable(_previousStageSunModelEnabled);
scene->setStageLocation(_previousStageLongitude, _previousStageLatitude,
_previousStageAltitude);
scene->setStageDayTime(_previousStageHour);
scene->setStageYearTime(_previousStageDay);
_hasPreviousZone = false;
}
_viewState->endOverrideEnvironmentData();
scene->getSkyStage()->setBackgroundMode(model::SunSkyStage::SKY_DOME); // let the application atmosphere through
}
}
void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode, void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode,
RenderArgs::RenderSide renderSide, RenderArgs::RenderSide renderSide,
RenderArgs::DebugFlags renderDebugFlags) { RenderArgs::DebugFlags renderDebugFlags) {
@ -411,85 +492,7 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode,
_bestZoneVolume = std::numeric_limits<float>::max(); _bestZoneVolume = std::numeric_limits<float>::max();
_tree->recurseTreeWithOperation(renderOperation, &args); _tree->recurseTreeWithOperation(renderOperation, &args);
QSharedPointer<SceneScriptingInterface> scene = DependencyManager::get<SceneScriptingInterface>(); applyZonePropertiesToScene(_bestZone);
if (_bestZone) {
if (!_hasPreviousZone) {
_previousKeyLightColor = scene->getKeyLightColor();
_previousKeyLightIntensity = scene->getKeyLightIntensity();
_previousKeyLightAmbientIntensity = scene->getKeyLightAmbientIntensity();
_previousKeyLightDirection = scene->getKeyLightDirection();
_previousStageSunModelEnabled = scene->isStageSunModelEnabled();
_previousStageLongitude = scene->getStageLocationLongitude();
_previousStageLatitude = scene->getStageLocationLatitude();
_previousStageAltitude = scene->getStageLocationAltitude();
_previousStageHour = scene->getStageDayTime();
_previousStageDay = scene->getStageYearTime();
_hasPreviousZone = true;
}
scene->setKeyLightColor(_bestZone->getKeyLightColorVec3());
scene->setKeyLightIntensity(_bestZone->getKeyLightIntensity());
scene->setKeyLightAmbientIntensity(_bestZone->getKeyLightAmbientIntensity());
scene->setKeyLightDirection(_bestZone->getKeyLightDirection());
scene->setStageSunModelEnable(_bestZone->getStageProperties().getSunModelEnabled());
scene->setStageLocation(_bestZone->getStageProperties().getLongitude(), _bestZone->getStageProperties().getLatitude(),
_bestZone->getStageProperties().getAltitude());
scene->setStageDayTime(_bestZone->getStageProperties().calculateHour());
scene->setStageYearTime(_bestZone->getStageProperties().calculateDay());
if (_bestZone->getBackgroundMode() == BACKGROUND_MODE_ATMOSPHERE) {
EnvironmentData data = _bestZone->getEnvironmentData();
glm::vec3 keyLightDirection = scene->getKeyLightDirection();
glm::vec3 inverseKeyLightDirection = keyLightDirection * -1.0f;
// NOTE: is this right? It seems like the "sun" should be based on the center of the
// atmosphere, not where the camera is.
glm::vec3 keyLightLocation = _viewState->getAvatarPosition()
+ (inverseKeyLightDirection * data.getAtmosphereOuterRadius());
data.setSunLocation(keyLightLocation);
const float KEY_LIGHT_INTENSITY_TO_SUN_BRIGHTNESS_RATIO = 20.0f;
float sunBrightness = scene->getKeyLightIntensity() * KEY_LIGHT_INTENSITY_TO_SUN_BRIGHTNESS_RATIO;
data.setSunBrightness(sunBrightness);
_viewState->overrideEnvironmentData(data);
scene->getSkyStage()->setBackgroundMode(model::SunSkyStage::SKY_DOME);
} else {
_viewState->endOverrideEnvironmentData();
auto stage = scene->getSkyStage();
if (_bestZone->getBackgroundMode() == BACKGROUND_MODE_SKYBOX) {
stage->getSkybox()->setColor(_bestZone->getSkyboxProperties().getColorVec3());
if (_bestZone->getSkyboxProperties().getURL().isEmpty()) {
stage->getSkybox()->clearCubemap();
} else {
// Update the Texture of the Skybox with the one pointed by this zone
auto cubeMap = DependencyManager::get<TextureCache>()->getTexture(_bestZone->getSkyboxProperties().getURL(), CUBE_TEXTURE);
stage->getSkybox()->setCubemap(cubeMap->getGPUTexture());
}
stage->setBackgroundMode(model::SunSkyStage::SKY_BOX);
} else {
stage->setBackgroundMode(model::SunSkyStage::SKY_DOME); // let the application atmosphere through
}
}
} else {
if (_hasPreviousZone) {
scene->setKeyLightColor(_previousKeyLightColor);
scene->setKeyLightIntensity(_previousKeyLightIntensity);
scene->setKeyLightAmbientIntensity(_previousKeyLightAmbientIntensity);
scene->setKeyLightDirection(_previousKeyLightDirection);
scene->setStageSunModelEnable(_previousStageSunModelEnabled);
scene->setStageLocation(_previousStageLongitude, _previousStageLatitude,
_previousStageAltitude);
scene->setStageDayTime(_previousStageHour);
scene->setStageYearTime(_previousStageDay);
_hasPreviousZone = false;
}
_viewState->endOverrideEnvironmentData();
scene->getSkyStage()->setBackgroundMode(model::SunSkyStage::SKY_DOME); // let the application atmosphere through
}
// we must call endScene while we still have the tree locked so that no one deletes a model // we must call endScene while we still have the tree locked so that no one deletes a model
// on us while rendering the scene // on us while rendering the scene

View file

@ -125,6 +125,7 @@ protected:
virtual Octree* createTree() { return new EntityTree(true); } virtual Octree* createTree() { return new EntityTree(true); }
private: private:
void applyZonePropertiesToScene(const ZoneEntityItem* zone);
void renderElementProxy(EntityTreeElement* entityTreeElement); void renderElementProxy(EntityTreeElement* entityTreeElement);
void checkAndCallPreload(const EntityItemID& entityID); void checkAndCallPreload(const EntityItemID& entityID);
void checkAndCallUnload(const EntityItemID& entityID); void checkAndCallUnload(const EntityItemID& entityID);

View file

@ -53,6 +53,12 @@ class LineEntityItem : public EntityItem {
virtual ShapeType getShapeType() const { return SHAPE_TYPE_LINE; } virtual ShapeType getShapeType() const { return SHAPE_TYPE_LINE; }
// never have a ray intersection pick a LineEntityItem.
virtual bool supportsDetailedRayIntersection() const { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) const { return false; }
virtual void debugDump() const; virtual void debugDump() const;
protected: protected:

View file

@ -99,41 +99,85 @@ void DeferredLightingEffect::bindSimpleProgram() {
glDisable(GL_BLEND); glDisable(GL_BLEND);
} }
void DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch) {
DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(batch, true, true, true);
batch._glUseProgram(_simpleProgram.programId());
batch._glUniform1f(_glowIntensityLocation, DependencyManager::get<GlowEffect>()->getIntensity());
batch._glDisable(GL_BLEND);
}
void DeferredLightingEffect::releaseSimpleProgram() { void DeferredLightingEffect::releaseSimpleProgram() {
glEnable(GL_BLEND); glEnable(GL_BLEND);
_simpleProgram.release(); _simpleProgram.release();
DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true, false, false); DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(true, false, false);
} }
void DeferredLightingEffect::releaseSimpleProgram(gpu::Batch& batch) {
batch._glEnable(GL_BLEND);
batch._glUseProgram(0);
DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(batch, true, false, false);
}
void DeferredLightingEffect::renderSolidSphere(float radius, int slices, int stacks, const glm::vec4& color) { void DeferredLightingEffect::renderSolidSphere(float radius, int slices, int stacks, const glm::vec4& color) {
bindSimpleProgram(); gpu::Batch batch;
DependencyManager::get<GeometryCache>()->renderSphere(radius, slices, stacks, color); renderSolidSphere(batch, radius, slices, stacks, color);
releaseSimpleProgram(); gpu::GLBackend::renderBatch(batch);
}
void DeferredLightingEffect::renderSolidSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color) {
bindSimpleProgram(batch);
DependencyManager::get<GeometryCache>()->renderSphere(batch, radius, slices, stacks, color);
releaseSimpleProgram(batch);
} }
void DeferredLightingEffect::renderWireSphere(float radius, int slices, int stacks, const glm::vec4& color) { void DeferredLightingEffect::renderWireSphere(float radius, int slices, int stacks, const glm::vec4& color) {
bindSimpleProgram(); gpu::Batch batch;
DependencyManager::get<GeometryCache>()->renderSphere(radius, slices, stacks, color, false); renderWireSphere(batch, radius, slices, stacks, color);
releaseSimpleProgram(); gpu::GLBackend::renderBatch(batch);
}
void DeferredLightingEffect::renderWireSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color) {
bindSimpleProgram(batch);
DependencyManager::get<GeometryCache>()->renderSphere(batch, radius, slices, stacks, color, false);
releaseSimpleProgram(batch);
} }
void DeferredLightingEffect::renderSolidCube(float size, const glm::vec4& color) { void DeferredLightingEffect::renderSolidCube(float size, const glm::vec4& color) {
bindSimpleProgram(); gpu::Batch batch;
DependencyManager::get<GeometryCache>()->renderSolidCube(size, color); renderSolidCube(batch, size, color);
releaseSimpleProgram(); gpu::GLBackend::renderBatch(batch);
}
void DeferredLightingEffect::renderSolidCube(gpu::Batch& batch, float size, const glm::vec4& color) {
bindSimpleProgram(batch);
DependencyManager::get<GeometryCache>()->renderSolidCube(batch, size, color);
releaseSimpleProgram(batch);
} }
void DeferredLightingEffect::renderWireCube(float size, const glm::vec4& color) { void DeferredLightingEffect::renderWireCube(float size, const glm::vec4& color) {
bindSimpleProgram(); gpu::Batch batch;
DependencyManager::get<GeometryCache>()->renderWireCube(size, color); renderWireCube(batch, size, color);
releaseSimpleProgram(); gpu::GLBackend::renderBatch(batch);
}
void DeferredLightingEffect::renderWireCube(gpu::Batch& batch, float size, const glm::vec4& color) {
bindSimpleProgram(batch);
DependencyManager::get<GeometryCache>()->renderWireCube(batch, size, color);
releaseSimpleProgram(batch);
} }
void DeferredLightingEffect::renderLine(const glm::vec3& p1, const glm::vec3& p2, void DeferredLightingEffect::renderLine(const glm::vec3& p1, const glm::vec3& p2,
const glm::vec4& color1, const glm::vec4& color2) { const glm::vec4& color1, const glm::vec4& color2) {
bindSimpleProgram(); gpu::Batch batch;
DependencyManager::get<GeometryCache>()->renderLine(p1, p2, color1, color2); renderLine(batch, p1, p2, color1, color2);
releaseSimpleProgram(); gpu::GLBackend::renderBatch(batch);
}
void DeferredLightingEffect::renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2,
const glm::vec4& color1, const glm::vec4& color2) {
bindSimpleProgram(batch);
DependencyManager::get<GeometryCache>()->renderLine(batch, p1, p2, color1, color2);
releaseSimpleProgram(batch);
} }

View file

@ -38,25 +38,33 @@ public:
/// Sets up the state necessary to render static untextured geometry with the simple program. /// Sets up the state necessary to render static untextured geometry with the simple program.
void bindSimpleProgram(); void bindSimpleProgram();
void bindSimpleProgram(gpu::Batch& batch);
/// Tears down the state necessary to render static untextured geometry with the simple program. /// Tears down the state necessary to render static untextured geometry with the simple program.
void releaseSimpleProgram(); void releaseSimpleProgram();
void releaseSimpleProgram(gpu::Batch& batch);
//// Renders a solid sphere with the simple program. //// Renders a solid sphere with the simple program.
void renderSolidSphere(float radius, int slices, int stacks, const glm::vec4& color); void renderSolidSphere(float radius, int slices, int stacks, const glm::vec4& color);
void renderSolidSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color);
//// Renders a wireframe sphere with the simple program. //// Renders a wireframe sphere with the simple program.
void renderWireSphere(float radius, int slices, int stacks, const glm::vec4& color); void renderWireSphere(float radius, int slices, int stacks, const glm::vec4& color);
void renderWireSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color);
//// Renders a solid cube with the simple program. //// Renders a solid cube with the simple program.
void renderSolidCube(float size, const glm::vec4& color); void renderSolidCube(float size, const glm::vec4& color);
void renderSolidCube(gpu::Batch& batch, float size, const glm::vec4& color);
//// Renders a wireframe cube with the simple program. //// Renders a wireframe cube with the simple program.
void renderWireCube(float size, const glm::vec4& color); void renderWireCube(float size, const glm::vec4& color);
void renderWireCube(gpu::Batch& batch, float size, const glm::vec4& color);
//// Renders a line with the simple program. //// Renders a line with the simple program.
void renderLine(const glm::vec3& p1, const glm::vec3& p2, void renderLine(const glm::vec3& p1, const glm::vec3& p2,
const glm::vec4& color1, const glm::vec4& color2); const glm::vec4& color1, const glm::vec4& color2);
void renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2,
const glm::vec4& color1, const glm::vec4& color2);
//// Renders a solid cone with the simple program. //// Renders a solid cone with the simple program.
void renderSolidCone(float base, float height, int slices, int stacks); void renderSolidCone(float base, float height, int slices, int stacks);

View file

@ -56,6 +56,12 @@ const int NUM_BYTES_PER_VERTEX = NUM_COORDS_PER_VERTEX * sizeof(GLfloat);
const int NUM_BYTES_PER_INDEX = sizeof(GLushort); const int NUM_BYTES_PER_INDEX = sizeof(GLushort);
void GeometryCache::renderSphere(float radius, int slices, int stacks, const glm::vec4& color, bool solid, int id) { void GeometryCache::renderSphere(float radius, int slices, int stacks, const glm::vec4& color, bool solid, int id) {
gpu::Batch batch;
renderSphere(batch, radius, slices, stacks, color, solid, id);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color, bool solid, int id) {
bool registered = (id != UNKNOWN_ID); bool registered = (id != UNKNOWN_ID);
Vec2Pair radiusKey(glm::vec2(radius, slices), glm::vec2(stacks, 0)); Vec2Pair radiusKey(glm::vec2(radius, slices), glm::vec2(stacks, 0));
@ -279,8 +285,6 @@ void GeometryCache::renderSphere(float radius, int slices, int stacks, const glm
gpu::BufferView normalsView(verticesBuffer, streamFormat->getAttributes().at(gpu::Stream::NORMAL)._element); gpu::BufferView normalsView(verticesBuffer, streamFormat->getAttributes().at(gpu::Stream::NORMAL)._element);
gpu::BufferView colorView(colorBuffer, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element); gpu::BufferView colorView(colorBuffer, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element);
gpu::Batch batch;
batch.setInputFormat(streamFormat); batch.setInputFormat(streamFormat);
batch.setInputBuffer(VERTICES_SLOT, verticesView); batch.setInputBuffer(VERTICES_SLOT, verticesView);
batch.setInputBuffer(NORMALS_SLOT, normalsView); batch.setInputBuffer(NORMALS_SLOT, normalsView);
@ -292,14 +296,12 @@ void GeometryCache::renderSphere(float radius, int slices, int stacks, const glm
} else { } else {
batch.drawIndexed(gpu::LINES, indices); batch.drawIndexed(gpu::LINES, indices);
} }
gpu::GLBackend::renderBatch(batch); batch._glDisableClientState(GL_VERTEX_ARRAY);
batch._glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY); batch._glBindBuffer(GL_ARRAY_BUFFER, 0);
batch._glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
} }
void GeometryCache::renderCone(float base, float height, int slices, int stacks) { void GeometryCache::renderCone(float base, float height, int slices, int stacks) {
@ -402,7 +404,14 @@ void GeometryCache::renderCone(float base, float height, int slices, int stacks)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
} }
void GeometryCache::renderGrid(int xDivisions, int yDivisions, const glm::vec4& color) { void GeometryCache::renderGrid(int xDivisions, int yDivisions, const glm::vec4& color) {
gpu::Batch batch;
renderGrid(batch, xDivisions, yDivisions, color);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderGrid(gpu::Batch& batch, int xDivisions, int yDivisions, const glm::vec4& color) {
IntPair key(xDivisions, yDivisions); IntPair key(xDivisions, yDivisions);
Vec3Pair colorKey(glm::vec3(color.x, color.y, yDivisions), glm::vec3(color.z, color.y, xDivisions)); Vec3Pair colorKey(glm::vec3(color.x, color.y, yDivisions), glm::vec3(color.z, color.y, xDivisions));
@ -470,25 +479,26 @@ void GeometryCache::renderGrid(int xDivisions, int yDivisions, const glm::vec4&
gpu::BufferView verticesView(verticesBuffer, 0, verticesBuffer->getSize(), streamFormat->getAttributes().at(gpu::Stream::POSITION)._element); gpu::BufferView verticesView(verticesBuffer, 0, verticesBuffer->getSize(), streamFormat->getAttributes().at(gpu::Stream::POSITION)._element);
gpu::BufferView colorView(colorBuffer, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element); gpu::BufferView colorView(colorBuffer, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element);
gpu::Batch batch;
batch.setInputFormat(streamFormat); batch.setInputFormat(streamFormat);
batch.setInputBuffer(VERTICES_SLOT, verticesView); batch.setInputBuffer(VERTICES_SLOT, verticesView);
batch.setInputBuffer(COLOR_SLOT, colorView); batch.setInputBuffer(COLOR_SLOT, colorView);
batch.draw(gpu::LINES, vertices, 0); batch.draw(gpu::LINES, vertices, 0);
batch._glDisableClientState(GL_VERTEX_ARRAY);
batch._glDisableClientState(GL_COLOR_ARRAY);
batch._glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void GeometryCache::renderGrid(int x, int y, int width, int height, int rows, int cols, const glm::vec4& color, int id) {
gpu::Batch batch;
renderGrid(batch, x, y, width, height, rows, cols, color, id);
gpu::GLBackend::renderBatch(batch); gpu::GLBackend::renderBatch(batch);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
} }
// TODO: properly handle the x,y,w,h changing for an ID // TODO: properly handle the x,y,w,h changing for an ID
// TODO: why do we seem to create extra BatchItemDetails when we resize the window?? what's that?? // TODO: why do we seem to create extra BatchItemDetails when we resize the window?? what's that??
void GeometryCache::renderGrid(int x, int y, int width, int height, int rows, int cols, const glm::vec4& color, int id) { void GeometryCache::renderGrid(gpu::Batch& batch, int x, int y, int width, int height, int rows, int cols, const glm::vec4& color, int id) {
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
qCDebug(renderutils) << "GeometryCache::renderGrid(x["<<x<<"], " qCDebug(renderutils) << "GeometryCache::renderGrid(x["<<x<<"], "
"y["<<y<<"]," "y["<<y<<"],"
@ -580,20 +590,16 @@ void GeometryCache::renderGrid(int x, int y, int width, int height, int rows, in
gpu::BufferView verticesView(verticesBuffer, 0, verticesBuffer->getSize(), streamFormat->getAttributes().at(gpu::Stream::POSITION)._element); gpu::BufferView verticesView(verticesBuffer, 0, verticesBuffer->getSize(), streamFormat->getAttributes().at(gpu::Stream::POSITION)._element);
gpu::BufferView colorView(colorBuffer, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element); gpu::BufferView colorView(colorBuffer, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element);
gpu::Batch batch;
batch.setInputFormat(streamFormat); batch.setInputFormat(streamFormat);
batch.setInputBuffer(VERTICES_SLOT, verticesView); batch.setInputBuffer(VERTICES_SLOT, verticesView);
batch.setInputBuffer(COLOR_SLOT, colorView); batch.setInputBuffer(COLOR_SLOT, colorView);
batch.draw(gpu::LINES, vertices, 0); batch.draw(gpu::LINES, vertices, 0);
gpu::GLBackend::renderBatch(batch); batch._glDisableClientState(GL_VERTEX_ARRAY);
batch._glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY); batch._glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
} }
void GeometryCache::updateVertices(int id, const QVector<glm::vec2>& points, const glm::vec4& color) { void GeometryCache::updateVertices(int id, const QVector<glm::vec2>& points, const glm::vec4& color) {
@ -792,24 +798,32 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, con
} }
void GeometryCache::renderVertices(gpu::Primitive primitiveType, int id) { void GeometryCache::renderVertices(gpu::Primitive primitiveType, int id) {
gpu::Batch batch;
renderVertices(batch, primitiveType, id);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderVertices(gpu::Batch& batch, gpu::Primitive primitiveType, int id) {
BatchItemDetails& details = _registeredVertices[id]; BatchItemDetails& details = _registeredVertices[id];
if (details.isCreated) { if (details.isCreated) {
gpu::Batch batch;
batch.setInputFormat(details.streamFormat); batch.setInputFormat(details.streamFormat);
batch.setInputStream(0, *details.stream); batch.setInputStream(0, *details.stream);
batch.draw(primitiveType, details.vertices, 0); batch.draw(primitiveType, details.vertices, 0);
gpu::GLBackend::renderBatch(batch); batch._glDisableClientState(GL_VERTEX_ARRAY);
batch._glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY); batch._glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
} }
} }
void GeometryCache::renderSolidCube(float size, const glm::vec4& color) { void GeometryCache::renderSolidCube(float size, const glm::vec4& color) {
gpu::Batch batch;
renderSolidCube(batch, size, color);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderSolidCube(gpu::Batch& batch, float size, const glm::vec4& color) {
Vec2Pair colorKey(glm::vec2(color.x, color.y), glm::vec2(color.z, color.y)); Vec2Pair colorKey(glm::vec2(color.x, color.y), glm::vec2(color.z, color.y));
const int FLOATS_PER_VERTEX = 3; const int FLOATS_PER_VERTEX = 3;
const int VERTICES_PER_FACE = 4; const int VERTICES_PER_FACE = 4;
@ -915,25 +929,27 @@ void GeometryCache::renderSolidCube(float size, const glm::vec4& color) {
gpu::BufferView normalsView(verticesBuffer, NORMALS_OFFSET, verticesBuffer->getSize(), VERTEX_STRIDE, streamFormat->getAttributes().at(gpu::Stream::NORMAL)._element); gpu::BufferView normalsView(verticesBuffer, NORMALS_OFFSET, verticesBuffer->getSize(), VERTEX_STRIDE, streamFormat->getAttributes().at(gpu::Stream::NORMAL)._element);
gpu::BufferView colorView(colorBuffer, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element); gpu::BufferView colorView(colorBuffer, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element);
gpu::Batch batch;
batch.setInputFormat(streamFormat); batch.setInputFormat(streamFormat);
batch.setInputBuffer(VERTICES_SLOT, verticesView); batch.setInputBuffer(VERTICES_SLOT, verticesView);
batch.setInputBuffer(NORMALS_SLOT, normalsView); batch.setInputBuffer(NORMALS_SLOT, normalsView);
batch.setInputBuffer(COLOR_SLOT, colorView); batch.setInputBuffer(COLOR_SLOT, colorView);
batch.setIndexBuffer(gpu::UINT8, _solidCubeIndexBuffer, 0); batch.setIndexBuffer(gpu::UINT8, _solidCubeIndexBuffer, 0);
batch.drawIndexed(gpu::TRIANGLES, indices); batch.drawIndexed(gpu::TRIANGLES, indices);
gpu::GLBackend::renderBatch(batch); batch._glDisableClientState(GL_VERTEX_ARRAY);
batch._glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY); batch._glBindBuffer(GL_ARRAY_BUFFER, 0);
batch._glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
} }
void GeometryCache::renderWireCube(float size, const glm::vec4& color) { void GeometryCache::renderWireCube(float size, const glm::vec4& color) {
gpu::Batch batch;
renderWireCube(batch, size, color);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderWireCube(gpu::Batch& batch, float size, const glm::vec4& color) {
Vec2Pair colorKey(glm::vec2(color.x, color.y),glm::vec2(color.z, color.y)); Vec2Pair colorKey(glm::vec2(color.x, color.y),glm::vec2(color.z, color.y));
const int FLOATS_PER_VERTEX = 3; const int FLOATS_PER_VERTEX = 3;
const int VERTICES_PER_EDGE = 2; const int VERTICES_PER_EDGE = 2;
@ -1003,24 +1019,26 @@ void GeometryCache::renderWireCube(float size, const glm::vec4& color) {
gpu::BufferView verticesView(verticesBuffer, streamFormat->getAttributes().at(gpu::Stream::POSITION)._element); gpu::BufferView verticesView(verticesBuffer, streamFormat->getAttributes().at(gpu::Stream::POSITION)._element);
gpu::BufferView colorView(colorBuffer, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element); gpu::BufferView colorView(colorBuffer, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element);
gpu::Batch batch;
batch.setInputFormat(streamFormat); batch.setInputFormat(streamFormat);
batch.setInputBuffer(VERTICES_SLOT, verticesView); batch.setInputBuffer(VERTICES_SLOT, verticesView);
batch.setInputBuffer(COLOR_SLOT, colorView); batch.setInputBuffer(COLOR_SLOT, colorView);
batch.setIndexBuffer(gpu::UINT8, _wireCubeIndexBuffer, 0); batch.setIndexBuffer(gpu::UINT8, _wireCubeIndexBuffer, 0);
batch.drawIndexed(gpu::LINES, indices); batch.drawIndexed(gpu::LINES, indices);
gpu::GLBackend::renderBatch(batch); batch._glDisableClientState(GL_VERTEX_ARRAY);
batch._glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY); batch._glBindBuffer(GL_ARRAY_BUFFER, 0);
batch._glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
} }
void GeometryCache::renderBevelCornersRect(int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id) { void GeometryCache::renderBevelCornersRect(int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id) {
gpu::Batch batch;
renderBevelCornersRect(batch, x, y, width, height, bevelDistance, color, id);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderBevelCornersRect(gpu::Batch& batch, int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id) {
bool registered = (id != UNKNOWN_ID); bool registered = (id != UNKNOWN_ID);
Vec3Pair key(glm::vec3(x, y, 0.0f), glm::vec3(width, height, bevelDistance)); Vec3Pair key(glm::vec3(x, y, 0.0f), glm::vec3(width, height, bevelDistance));
BatchItemDetails& details = registered ? _registeredBevelRects[id] : _bevelRects[key]; BatchItemDetails& details = registered ? _registeredBevelRects[id] : _bevelRects[key];
@ -1113,21 +1131,23 @@ void GeometryCache::renderBevelCornersRect(int x, int y, int width, int height,
delete[] vertexBuffer; delete[] vertexBuffer;
} }
gpu::Batch batch;
batch.setInputFormat(details.streamFormat); batch.setInputFormat(details.streamFormat);
batch.setInputStream(0, *details.stream); batch.setInputStream(0, *details.stream);
batch.draw(gpu::QUADS, 4, 0); batch.draw(gpu::QUADS, 4, 0);
gpu::GLBackend::renderBatch(batch); batch._glDisableClientState(GL_VERTEX_ARRAY);
batch._glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY); batch._glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
} }
void GeometryCache::renderQuad(const glm::vec2& minCorner, const glm::vec2& maxCorner, const glm::vec4& color, int id) { void GeometryCache::renderQuad(const glm::vec2& minCorner, const glm::vec2& maxCorner, const glm::vec4& color, int id) {
gpu::Batch batch;
renderQuad(batch, minCorner, maxCorner, color, id);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner, const glm::vec4& color, int id) {
bool registered = (id != UNKNOWN_ID); bool registered = (id != UNKNOWN_ID);
Vec4Pair key(glm::vec4(minCorner.x, minCorner.y, maxCorner.x, maxCorner.y), color); Vec4Pair key(glm::vec4(minCorner.x, minCorner.y, maxCorner.x, maxCorner.y), color);
BatchItemDetails& details = registered ? _registeredQuad2D[id] : _quad2D[key]; BatchItemDetails& details = registered ? _registeredQuad2D[id] : _quad2D[key];
@ -1193,23 +1213,27 @@ void GeometryCache::renderQuad(const glm::vec2& minCorner, const glm::vec2& maxC
details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors); details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors);
} }
gpu::Batch batch;
batch.setInputFormat(details.streamFormat); batch.setInputFormat(details.streamFormat);
batch.setInputStream(0, *details.stream); batch.setInputStream(0, *details.stream);
batch.draw(gpu::QUADS, 4, 0); batch.draw(gpu::QUADS, 4, 0);
gpu::GLBackend::renderBatch(batch); batch._glDisableClientState(GL_VERTEX_ARRAY);
batch._glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY); batch._glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
} }
void GeometryCache::renderQuad(const glm::vec2& minCorner, const glm::vec2& maxCorner, void GeometryCache::renderQuad(const glm::vec2& minCorner, const glm::vec2& maxCorner,
const glm::vec2& texCoordMinCorner, const glm::vec2& texCoordMaxCorner, const glm::vec2& texCoordMinCorner, const glm::vec2& texCoordMaxCorner,
const glm::vec4& color, int id) { const glm::vec4& color, int id) {
gpu::Batch batch;
renderQuad(batch, minCorner, maxCorner, texCoordMinCorner, texCoordMaxCorner, color, id);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner,
const glm::vec2& texCoordMinCorner, const glm::vec2& texCoordMaxCorner,
const glm::vec4& color, int id) {
bool registered = (id != UNKNOWN_ID); bool registered = (id != UNKNOWN_ID);
Vec4PairVec4 key(Vec4Pair(glm::vec4(minCorner.x, minCorner.y, maxCorner.x, maxCorner.y), Vec4PairVec4 key(Vec4Pair(glm::vec4(minCorner.x, minCorner.y, maxCorner.x, maxCorner.y),
@ -1282,27 +1306,24 @@ void GeometryCache::renderQuad(const glm::vec2& minCorner, const glm::vec2& maxC
details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors); details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors);
} }
gpu::Batch batch;
// glEnable(GL_TEXTURE_2D);
//glBindTexture(GL_TEXTURE_2D, _currentTextureID); // this is quad specific...
batch.setInputFormat(details.streamFormat); batch.setInputFormat(details.streamFormat);
batch.setInputStream(0, *details.stream); batch.setInputStream(0, *details.stream);
batch.draw(gpu::QUADS, 4, 0); batch.draw(gpu::QUADS, 4, 0);
gpu::GLBackend::renderBatch(batch); batch._glDisableClientState(GL_VERTEX_ARRAY);
batch._glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY); batch._glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY); batch._glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// glBindTexture(GL_TEXTURE_2D, 0);
// glDisable(GL_TEXTURE_2D);
} }
void GeometryCache::renderQuad(const glm::vec3& minCorner, const glm::vec3& maxCorner, const glm::vec4& color, int id) { void GeometryCache::renderQuad(const glm::vec3& minCorner, const glm::vec3& maxCorner, const glm::vec4& color, int id) {
gpu::Batch batch;
renderQuad(batch, minCorner, maxCorner, color, id);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, const glm::vec3& maxCorner, const glm::vec4& color, int id) {
bool registered = (id != UNKNOWN_ID); bool registered = (id != UNKNOWN_ID);
Vec3PairVec4 key(Vec3Pair(minCorner, maxCorner), color); Vec3PairVec4 key(Vec3Pair(minCorner, maxCorner), color);
BatchItemDetails& details = registered ? _registeredQuad3D[id] : _quad3D[key]; BatchItemDetails& details = registered ? _registeredQuad3D[id] : _quad3D[key];
@ -1368,18 +1389,14 @@ void GeometryCache::renderQuad(const glm::vec3& minCorner, const glm::vec3& maxC
details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors); details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors);
} }
gpu::Batch batch;
batch.setInputFormat(details.streamFormat); batch.setInputFormat(details.streamFormat);
batch.setInputStream(0, *details.stream); batch.setInputStream(0, *details.stream);
batch.draw(gpu::QUADS, 4, 0); batch.draw(gpu::QUADS, 4, 0);
gpu::GLBackend::renderBatch(batch); batch._glDisableClientState(GL_VERTEX_ARRAY);
batch._glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY); batch._glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
} }
void GeometryCache::renderQuad(const glm::vec3& topLeft, const glm::vec3& bottomLeft, void GeometryCache::renderQuad(const glm::vec3& topLeft, const glm::vec3& bottomLeft,
@ -1387,6 +1404,17 @@ void GeometryCache::renderQuad(const glm::vec3& topLeft, const glm::vec3& bottom
const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomLeft, const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomLeft,
const glm::vec2& texCoordBottomRight, const glm::vec2& texCoordTopRight, const glm::vec2& texCoordBottomRight, const glm::vec2& texCoordTopRight,
const glm::vec4& color, int id) { const glm::vec4& color, int id) {
gpu::Batch batch;
renderQuad(batch, topLeft, bottomLeft, bottomRight, topRight, texCoordTopLeft, texCoordBottomLeft,
texCoordBottomRight, texCoordTopRight, color, id);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, const glm::vec3& bottomLeft,
const glm::vec3& bottomRight, const glm::vec3& topRight,
const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomLeft,
const glm::vec2& texCoordBottomRight, const glm::vec2& texCoordTopRight,
const glm::vec4& color, int id) {
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
qCDebug(renderutils) << "renderQuad() vec3 + texture VBO..."; qCDebug(renderutils) << "renderQuad() vec3 + texture VBO...";
@ -1469,32 +1497,27 @@ void GeometryCache::renderQuad(const glm::vec3& topLeft, const glm::vec3& bottom
details.verticesBuffer->append(sizeof(vertexBuffer), (gpu::Byte*) vertexBuffer); details.verticesBuffer->append(sizeof(vertexBuffer), (gpu::Byte*) vertexBuffer);
details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors); details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors);
} }
gpu::Batch batch; batch._glEnable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_2D);
//glBindTexture(GL_TEXTURE_2D, _currentTextureID); // this is quad specific...
batch.setInputFormat(details.streamFormat); batch.setInputFormat(details.streamFormat);
batch.setInputStream(0, *details.stream); batch.setInputStream(0, *details.stream);
batch.draw(gpu::QUADS, 4, 0); batch.draw(gpu::QUADS, 4, 0);
gpu::GLBackend::renderBatch(batch);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// TODO: The callers of this method (renderMagnifier and renderReticle) assume that we won't disable an unbind batch._glDisableClientState(GL_VERTEX_ARRAY);
// the texture after rendering. I'm not sure if this is correct in general but it's currently required for the batch._glDisableClientState(GL_TEXTURE_COORD_ARRAY);
// oculus overlay to work. batch._glDisableClientState(GL_COLOR_ARRAY);
//glBindTexture(GL_TEXTURE_2D, 0);
//glDisable(GL_TEXTURE_2D); batch._glBindBuffer(GL_ARRAY_BUFFER, 0);
} }
void GeometryCache::renderDashedLine(const glm::vec3& start, const glm::vec3& end, const glm::vec4& color, int id) { void GeometryCache::renderDashedLine(const glm::vec3& start, const glm::vec3& end, const glm::vec4& color, int id) {
gpu::Batch batch;
renderDashedLine(batch, start, end, color, id);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderDashedLine(gpu::Batch& batch, const glm::vec3& start, const glm::vec3& end, const glm::vec4& color, int id) {
bool registered = (id != UNKNOWN_ID); bool registered = (id != UNKNOWN_ID);
Vec3PairVec2Pair key(Vec3Pair(start, end), Vec2Pair(glm::vec2(color.x, color.y), glm::vec2(color.z, color.w))); Vec3PairVec2Pair key(Vec3Pair(start, end), Vec2Pair(glm::vec2(color.x, color.y), glm::vec2(color.z, color.w)));
BatchItemDetails& details = registered ? _registeredDashedLines[id] : _dashedLines[key]; BatchItemDetails& details = registered ? _registeredDashedLines[id] : _dashedLines[key];
@ -1594,18 +1617,14 @@ void GeometryCache::renderDashedLine(const glm::vec3& start, const glm::vec3& en
#endif #endif
} }
gpu::Batch batch;
batch.setInputFormat(details.streamFormat); batch.setInputFormat(details.streamFormat);
batch.setInputStream(0, *details.stream); batch.setInputStream(0, *details.stream);
batch.draw(gpu::LINES, details.vertices, 0); batch.draw(gpu::LINES, details.vertices, 0);
gpu::GLBackend::renderBatch(batch); batch._glDisableClientState(GL_VERTEX_ARRAY);
batch._glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY); batch._glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
} }
@ -1659,6 +1678,13 @@ void GeometryCache::BatchItemDetails::clear() {
void GeometryCache::renderLine(const glm::vec3& p1, const glm::vec3& p2, void GeometryCache::renderLine(const glm::vec3& p1, const glm::vec3& p2,
const glm::vec4& color1, const glm::vec4& color2, int id) { const glm::vec4& color1, const glm::vec4& color2, int id) {
gpu::Batch batch;
renderLine(batch, p1, p2, color1, color2, id);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2,
const glm::vec4& color1, const glm::vec4& color2, int id) {
bool registered = (id != UNKNOWN_ID); bool registered = (id != UNKNOWN_ID);
Vec3Pair key(p1, p2); Vec3Pair key(p1, p2);
@ -1735,21 +1761,24 @@ void GeometryCache::renderLine(const glm::vec3& p1, const glm::vec3& p2,
#endif #endif
} }
gpu::Batch batch;
// this is what it takes to render a quad // this is what it takes to render a quad
batch.setInputFormat(details.streamFormat); batch.setInputFormat(details.streamFormat);
batch.setInputStream(0, *details.stream); batch.setInputStream(0, *details.stream);
batch.draw(gpu::LINES, 2, 0); batch.draw(gpu::LINES, 2, 0);
gpu::GLBackend::renderBatch(batch); batch._glDisableClientState(GL_VERTEX_ARRAY);
batch._glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY); batch._glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
} }
void GeometryCache::renderLine(const glm::vec2& p1, const glm::vec2& p2, void GeometryCache::renderLine(const glm::vec2& p1, const glm::vec2& p2, const glm::vec4& color1, const glm::vec4& color2, int id) {
gpu::Batch batch;
renderLine(batch, p1, p2, color1, color2, id);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm::vec2& p2,
const glm::vec4& color1, const glm::vec4& color2, int id) { const glm::vec4& color1, const glm::vec4& color2, int id) {
bool registered = (id != UNKNOWN_ID); bool registered = (id != UNKNOWN_ID);
@ -1827,18 +1856,15 @@ void GeometryCache::renderLine(const glm::vec2& p1, const glm::vec2& p2,
#endif #endif
} }
gpu::Batch batch;
// this is what it takes to render a quad // this is what it takes to render a quad
batch.setInputFormat(details.streamFormat); batch.setInputFormat(details.streamFormat);
batch.setInputStream(0, *details.stream); batch.setInputStream(0, *details.stream);
batch.draw(gpu::LINES, 2, 0); batch.draw(gpu::LINES, 2, 0);
gpu::GLBackend::renderBatch(batch); batch._glDisableClientState(GL_VERTEX_ARRAY);
batch._glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY); batch._glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
} }

View file

@ -135,70 +135,113 @@ public:
void renderCone(float base, float height, int slices, int stacks); void renderCone(float base, float height, int slices, int stacks);
void renderSphere(float radius, int slices, int stacks, const glm::vec3& color, bool solid = true, int id = UNKNOWN_ID) void renderSphere(float radius, int slices, int stacks, const glm::vec3& color, bool solid = true, int id = UNKNOWN_ID)
{ renderSphere(radius, slices, stacks, glm::vec4(color, 1.0f), solid, id); } { renderSphere(radius, slices, stacks, glm::vec4(color, 1.0f), solid, id); }
void renderSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec3& color, bool solid = true, int id = UNKNOWN_ID)
{ renderSphere(batch, radius, slices, stacks, glm::vec4(color, 1.0f), solid, id); }
void renderSphere(float radius, int slices, int stacks, const glm::vec4& color, bool solid = true, int id = UNKNOWN_ID); void renderSphere(float radius, int slices, int stacks, const glm::vec4& color, bool solid = true, int id = UNKNOWN_ID);
void renderSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color, bool solid = true, int id = UNKNOWN_ID);
void renderGrid(int xDivisions, int yDivisions, const glm::vec4& color); void renderGrid(int xDivisions, int yDivisions, const glm::vec4& color);
void renderGrid(gpu::Batch& batch, int xDivisions, int yDivisions, const glm::vec4& color);
void renderGrid(int x, int y, int width, int height, int rows, int cols, const glm::vec4& color, int id = UNKNOWN_ID); void renderGrid(int x, int y, int width, int height, int rows, int cols, const glm::vec4& color, int id = UNKNOWN_ID);
void renderGrid(gpu::Batch& batch, int x, int y, int width, int height, int rows, int cols, const glm::vec4& color, int id = UNKNOWN_ID);
void renderSolidCube(float size, const glm::vec4& color); void renderSolidCube(float size, const glm::vec4& color);
void renderSolidCube(gpu::Batch& batch, float size, const glm::vec4& color);
void renderWireCube(float size, const glm::vec4& color); void renderWireCube(float size, const glm::vec4& color);
void renderWireCube(gpu::Batch& batch, float size, const glm::vec4& color);
void renderBevelCornersRect(int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id = UNKNOWN_ID); void renderBevelCornersRect(int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id = UNKNOWN_ID);
void renderBevelCornersRect(gpu::Batch& batch, int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id = UNKNOWN_ID);
void renderQuad(int x, int y, int width, int height, const glm::vec4& color, int id = UNKNOWN_ID) void renderQuad(int x, int y, int width, int height, const glm::vec4& color, int id = UNKNOWN_ID)
{ renderQuad(glm::vec2(x,y), glm::vec2(x + width, y + height), color, id); } { renderQuad(glm::vec2(x,y), glm::vec2(x + width, y + height), color, id); }
void renderQuad(gpu::Batch& batch, int x, int y, int width, int height, const glm::vec4& color, int id = UNKNOWN_ID)
{ renderQuad(batch, glm::vec2(x,y), glm::vec2(x + width, y + height), color, id); }
// TODO: I think there's a bug in this version of the renderQuad() that's not correctly rebuilding the vbos // TODO: I think there's a bug in this version of the renderQuad() that's not correctly rebuilding the vbos
// if the color changes by the corners are the same, as evidenced by the audio meter which should turn white // if the color changes by the corners are the same, as evidenced by the audio meter which should turn white
// when it's clipping // when it's clipping
void renderQuad(const glm::vec2& minCorner, const glm::vec2& maxCorner, const glm::vec4& color, int id = UNKNOWN_ID); void renderQuad(const glm::vec2& minCorner, const glm::vec2& maxCorner, const glm::vec4& color, int id = UNKNOWN_ID);
void renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner, const glm::vec4& color, int id = UNKNOWN_ID);
void renderQuad(const glm::vec2& minCorner, const glm::vec2& maxCorner, void renderQuad(const glm::vec2& minCorner, const glm::vec2& maxCorner,
const glm::vec2& texCoordMinCorner, const glm::vec2& texCoordMaxCorner, const glm::vec2& texCoordMinCorner, const glm::vec2& texCoordMaxCorner,
const glm::vec4& color, int id = UNKNOWN_ID); const glm::vec4& color, int id = UNKNOWN_ID);
void renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner,
const glm::vec2& texCoordMinCorner, const glm::vec2& texCoordMaxCorner,
const glm::vec4& color, int id = UNKNOWN_ID);
void renderQuad(const glm::vec3& minCorner, const glm::vec3& maxCorner, const glm::vec4& color, int id = UNKNOWN_ID); void renderQuad(const glm::vec3& minCorner, const glm::vec3& maxCorner, const glm::vec4& color, int id = UNKNOWN_ID);
void renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, const glm::vec3& maxCorner, const glm::vec4& color, int id = UNKNOWN_ID);
void renderQuad(const glm::vec3& topLeft, const glm::vec3& bottomLeft, void renderQuad(const glm::vec3& topLeft, const glm::vec3& bottomLeft,
const glm::vec3& bottomRight, const glm::vec3& topRight, const glm::vec3& bottomRight, const glm::vec3& topRight,
const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomLeft, const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomLeft,
const glm::vec2& texCoordBottomRight, const glm::vec2& texCoordTopRight, const glm::vec2& texCoordBottomRight, const glm::vec2& texCoordTopRight,
const glm::vec4& color, int id = UNKNOWN_ID); const glm::vec4& color, int id = UNKNOWN_ID);
void renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, const glm::vec3& bottomLeft,
const glm::vec3& bottomRight, const glm::vec3& topRight,
const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomLeft,
const glm::vec2& texCoordBottomRight, const glm::vec2& texCoordTopRight,
const glm::vec4& color, int id = UNKNOWN_ID);
void renderLine(const glm::vec3& p1, const glm::vec3& p2, const glm::vec3& color, int id = UNKNOWN_ID) void renderLine(const glm::vec3& p1, const glm::vec3& p2, const glm::vec3& color, int id = UNKNOWN_ID)
{ renderLine(p1, p2, color, color, id); } { renderLine(p1, p2, color, color, id); }
void renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2, const glm::vec3& color, int id = UNKNOWN_ID)
{ renderLine(batch, p1, p2, color, color, id); }
void renderLine(const glm::vec3& p1, const glm::vec3& p2, void renderLine(const glm::vec3& p1, const glm::vec3& p2,
const glm::vec3& color1, const glm::vec3& color2, int id = UNKNOWN_ID) const glm::vec3& color1, const glm::vec3& color2, int id = UNKNOWN_ID)
{ renderLine(p1, p2, glm::vec4(color1, 1.0f), glm::vec4(color2, 1.0f), id); } { renderLine(p1, p2, glm::vec4(color1, 1.0f), glm::vec4(color2, 1.0f), id); }
void renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2,
const glm::vec3& color1, const glm::vec3& color2, int id = UNKNOWN_ID)
{ renderLine(batch, p1, p2, glm::vec4(color1, 1.0f), glm::vec4(color2, 1.0f), id); }
void renderLine(const glm::vec3& p1, const glm::vec3& p2, void renderLine(const glm::vec3& p1, const glm::vec3& p2,
const glm::vec4& color, int id = UNKNOWN_ID) const glm::vec4& color, int id = UNKNOWN_ID)
{ renderLine(p1, p2, color, color, id); } { renderLine(p1, p2, color, color, id); }
void renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2,
const glm::vec4& color, int id = UNKNOWN_ID)
{ renderLine(batch, p1, p2, color, color, id); }
void renderLine(const glm::vec3& p1, const glm::vec3& p2, void renderLine(const glm::vec3& p1, const glm::vec3& p2,
const glm::vec4& color1, const glm::vec4& color2, int id = UNKNOWN_ID); const glm::vec4& color1, const glm::vec4& color2, int id = UNKNOWN_ID);
void renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2,
const glm::vec4& color1, const glm::vec4& color2, int id = UNKNOWN_ID);
void renderDashedLine(const glm::vec3& start, const glm::vec3& end, const glm::vec4& color, int id = UNKNOWN_ID); void renderDashedLine(const glm::vec3& start, const glm::vec3& end, const glm::vec4& color, int id = UNKNOWN_ID);
void renderDashedLine(gpu::Batch& batch, const glm::vec3& start, const glm::vec3& end, const glm::vec4& color, int id = UNKNOWN_ID);
void renderLine(const glm::vec2& p1, const glm::vec2& p2, const glm::vec3& color, int id = UNKNOWN_ID) void renderLine(const glm::vec2& p1, const glm::vec2& p2, const glm::vec3& color, int id = UNKNOWN_ID)
{ renderLine(p1, p2, glm::vec4(color, 1.0f), id); } { renderLine(p1, p2, glm::vec4(color, 1.0f), id); }
void renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm::vec2& p2, const glm::vec3& color, int id = UNKNOWN_ID)
{ renderLine(batch, p1, p2, glm::vec4(color, 1.0f), id); }
void renderLine(const glm::vec2& p1, const glm::vec2& p2, const glm::vec4& color, int id = UNKNOWN_ID) void renderLine(const glm::vec2& p1, const glm::vec2& p2, const glm::vec4& color, int id = UNKNOWN_ID)
{ renderLine(p1, p2, color, color, id); } { renderLine(p1, p2, color, color, id); }
void renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm::vec2& p2, const glm::vec4& color, int id = UNKNOWN_ID)
{ renderLine(batch, p1, p2, color, color, id); }
void renderLine(const glm::vec2& p1, const glm::vec2& p2, void renderLine(const glm::vec2& p1, const glm::vec2& p2,
const glm::vec3& color1, const glm::vec3& color2, int id = UNKNOWN_ID) const glm::vec3& color1, const glm::vec3& color2, int id = UNKNOWN_ID)
{ renderLine(p1, p2, glm::vec4(color1, 1.0f), glm::vec4(color2, 1.0f), id); } { renderLine(p1, p2, glm::vec4(color1, 1.0f), glm::vec4(color2, 1.0f), id); }
void renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm::vec2& p2,
const glm::vec3& color1, const glm::vec3& color2, int id = UNKNOWN_ID)
{ renderLine(batch, p1, p2, glm::vec4(color1, 1.0f), glm::vec4(color2, 1.0f), id); }
void renderLine(const glm::vec2& p1, const glm::vec2& p2, void renderLine(const glm::vec2& p1, const glm::vec2& p2,
const glm::vec4& color1, const glm::vec4& color2, int id = UNKNOWN_ID); const glm::vec4& color1, const glm::vec4& color2, int id = UNKNOWN_ID);
void renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm::vec2& p2,
const glm::vec4& color1, const glm::vec4& color2, int id = UNKNOWN_ID);
void updateVertices(int id, const QVector<glm::vec2>& points, const glm::vec4& color); void updateVertices(int id, const QVector<glm::vec2>& points, const glm::vec4& color);
void updateVertices(int id, const QVector<glm::vec3>& points, const glm::vec4& color); void updateVertices(int id, const QVector<glm::vec3>& points, const glm::vec4& color);
void updateVertices(int id, const QVector<glm::vec3>& points, const QVector<glm::vec2>& texCoords, const glm::vec4& color); void updateVertices(int id, const QVector<glm::vec3>& points, const QVector<glm::vec2>& texCoords, const glm::vec4& color);
void renderVertices(gpu::Batch& batch, gpu::Primitive primitiveType, int id);
void renderVertices(gpu::Primitive primitiveType, int id); void renderVertices(gpu::Primitive primitiveType, int id);
/// Loads geometry from the specified URL. /// Loads geometry from the specified URL.

View file

@ -247,6 +247,12 @@ GLuint TextureCache::getPrimarySpecularTextureID() {
} }
void TextureCache::setPrimaryDrawBuffers(bool color, bool normal, bool specular) { void TextureCache::setPrimaryDrawBuffers(bool color, bool normal, bool specular) {
gpu::Batch batch;
setPrimaryDrawBuffers(batch, color, normal, specular);
gpu::GLBackend::renderBatch(batch);
}
void TextureCache::setPrimaryDrawBuffers(gpu::Batch& batch, bool color, bool normal, bool specular) {
GLenum buffers[3]; GLenum buffers[3];
int bufferCount = 0; int bufferCount = 0;
if (color) { if (color) {
@ -258,7 +264,7 @@ void TextureCache::setPrimaryDrawBuffers(bool color, bool normal, bool specular)
if (specular) { if (specular) {
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
} }
glDrawBuffers(bufferCount, buffers); batch._glDrawBuffers(bufferCount, buffers);
} }
gpu::FramebufferPointer TextureCache::getSecondaryFramebuffer() { gpu::FramebufferPointer TextureCache::getSecondaryFramebuffer() {

View file

@ -12,6 +12,7 @@
#ifndef hifi_TextureCache_h #ifndef hifi_TextureCache_h
#define hifi_TextureCache_h #define hifi_TextureCache_h
#include <gpu/Batch.h>
#include <gpu/GPUConfig.h> #include <gpu/GPUConfig.h>
#include <gpu/Texture.h> #include <gpu/Texture.h>
#include <gpu/Framebuffer.h> #include <gpu/Framebuffer.h>
@ -78,6 +79,7 @@ public:
/// Enables or disables draw buffers on the primary framebuffer. Note: the primary framebuffer must be bound. /// Enables or disables draw buffers on the primary framebuffer. Note: the primary framebuffer must be bound.
void setPrimaryDrawBuffers(bool color, bool normal = false, bool specular = false); void setPrimaryDrawBuffers(bool color, bool normal = false, bool specular = false);
void setPrimaryDrawBuffers(gpu::Batch& batch, bool color, bool normal = false, bool specular = false);
/// Returns a pointer to the secondary framebuffer object, used as an additional render target when performing full /// Returns a pointer to the secondary framebuffer object, used as an additional render target when performing full
/// screen effects. /// screen effects.

View file

@ -14,6 +14,9 @@
class ViewFrustum; class ViewFrustum;
class OctreeRenderer; class OctreeRenderer;
namespace gpu {
class Batch;
}
class RenderArgs { class RenderArgs {
public: public:
@ -34,6 +37,7 @@ public:
RenderMode renderMode = DEFAULT_RENDER_MODE, RenderMode renderMode = DEFAULT_RENDER_MODE,
RenderSide renderSide = MONO, RenderSide renderSide = MONO,
DebugFlags debugFlags = RENDER_DEBUG_NONE, DebugFlags debugFlags = RENDER_DEBUG_NONE,
gpu::Batch* batch = nullptr,
int elementsTouched = 0, int elementsTouched = 0,
int itemsRendered = 0, int itemsRendered = 0,
@ -58,6 +62,7 @@ public:
_renderMode(renderMode), _renderMode(renderMode),
_renderSide(renderSide), _renderSide(renderSide),
_debugFlags(debugFlags), _debugFlags(debugFlags),
_batch(batch),
_elementsTouched(elementsTouched), _elementsTouched(elementsTouched),
_itemsRendered(itemsRendered), _itemsRendered(itemsRendered),
@ -84,6 +89,7 @@ public:
RenderMode _renderMode; RenderMode _renderMode;
RenderSide _renderSide; RenderSide _renderSide;
DebugFlags _debugFlags; DebugFlags _debugFlags;
gpu::Batch* _batch;
int _elementsTouched; int _elementsTouched;
int _itemsRendered; int _itemsRendered;