mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 05:17:02 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into huffman-batch-param
This commit is contained in:
commit
90935d550d
15 changed files with 785 additions and 355 deletions
180
examples/dice.js
180
examples/dice.js
|
@ -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);
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
77
examples/pointer.js
Normal file
77
examples/pointer.js
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
|
||||||
|
var lineEntityID = null;
|
||||||
|
var lineIsRezzed = false;
|
||||||
|
|
||||||
|
|
||||||
|
function nearLinePoint(targetPosition) {
|
||||||
|
var handPosition = MyAvatar.getRightPalmPosition();
|
||||||
|
var along = Vec3.subtract(targetPosition, handPosition);
|
||||||
|
along = Vec3.normalize(along);
|
||||||
|
along = Vec3.multiply(along, 0.4);
|
||||||
|
return Vec3.sum(handPosition, along);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function removeLine() {
|
||||||
|
if (lineIsRezzed) {
|
||||||
|
Entities.deleteEntity(lineEntityID);
|
||||||
|
lineEntityID = null;
|
||||||
|
lineIsRezzed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function createOrUpdateLine(event) {
|
||||||
|
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||||
|
var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking
|
||||||
|
var props = Entities.getEntityProperties(intersection.entityID);
|
||||||
|
|
||||||
|
if (intersection.intersects) {
|
||||||
|
var dim = Vec3.subtract(intersection.intersection, nearLinePoint(intersection.intersection));
|
||||||
|
if (lineIsRezzed) {
|
||||||
|
Entities.editEntity(lineEntityID, {
|
||||||
|
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 {
|
||||||
|
removeLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function mousePressEvent(event) {
|
||||||
|
if (!event.isLeftButton) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|
||||||
|
createOrUpdateLine(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function mouseMoveEvent(event) {
|
||||||
|
createOrUpdateLine(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function mouseReleaseEvent(event) {
|
||||||
|
if (!event.isLeftButton) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Controller.mouseMoveEvent.disconnect(mouseMoveEvent);
|
||||||
|
removeLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Controller.mousePressEvent.connect(mousePressEvent);
|
||||||
|
Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -1111,6 +1111,9 @@ void EntityTreeRenderer::changingEntityID(const EntityItemID& oldEntityID, const
|
||||||
|
|
||||||
void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityTree* entityTree, const EntityItemID& id, const Collision& collision) {
|
void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityTree* entityTree, const EntityItemID& id, const Collision& collision) {
|
||||||
EntityItem* entity = entityTree->findEntityByEntityItemID(id);
|
EntityItem* entity = entityTree->findEntityByEntityItemID(id);
|
||||||
|
if (!entity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
QUuid simulatorID = entity->getSimulatorID();
|
QUuid simulatorID = entity->getSimulatorID();
|
||||||
if (simulatorID.isNull() || (simulatorID != myNodeID)) {
|
if (simulatorID.isNull() || (simulatorID != myNodeID)) {
|
||||||
return; // Only one injector per simulation, please.
|
return; // Only one injector per simulation, please.
|
||||||
|
@ -1124,20 +1127,24 @@ void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityT
|
||||||
const float linearVelocity = glm::length(collision.penetration) * COLLISION_PENTRATION_TO_VELOCITY;
|
const float linearVelocity = glm::length(collision.penetration) * COLLISION_PENTRATION_TO_VELOCITY;
|
||||||
const float energy = mass * linearVelocity * linearVelocity / 2.0f;
|
const float energy = mass * linearVelocity * linearVelocity / 2.0f;
|
||||||
const glm::vec3 position = collision.contactPoint;
|
const glm::vec3 position = collision.contactPoint;
|
||||||
const float COLLISION_ENERGY_AT_FULL_VOLUME = 1.0f;
|
const float COLLISION_ENERGY_AT_FULL_VOLUME = 0.5f;
|
||||||
const float COLLISION_MINIMUM_VOLUME = 0.001f;
|
const float COLLISION_MINIMUM_VOLUME = 0.001f;
|
||||||
const float energyFactorOfFull = fmin(1.0f, energy / COLLISION_ENERGY_AT_FULL_VOLUME);
|
const float energyFactorOfFull = fmin(1.0f, energy / COLLISION_ENERGY_AT_FULL_VOLUME);
|
||||||
if (energyFactorOfFull < COLLISION_MINIMUM_VOLUME) {
|
if (energyFactorOfFull < COLLISION_MINIMUM_VOLUME) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedSoundPointer sound = DependencyManager::get<SoundCache>().data()->getSound(QUrl(collisionSoundURL));
|
auto soundCache = DependencyManager::get<SoundCache>();
|
||||||
if (!sound->isReady()) {
|
if (soundCache.isNull()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SharedSoundPointer sound = soundCache.data()->getSound(QUrl(collisionSoundURL));
|
||||||
|
if (sound.isNull() || !sound->isReady()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a hack. Quiet sound aren't really heard at all, so we compress everything to the range [1-c, 1], if we play it all.
|
// This is a hack. Quiet sound aren't really heard at all, so we compress everything to the range [1-c, 1], if we play it all.
|
||||||
const float COLLISION_SOUND_COMPRESSION_RANGE = 0.95f;
|
const float COLLISION_SOUND_COMPRESSION_RANGE = 0.7f;
|
||||||
float volume = energyFactorOfFull;
|
float volume = energyFactorOfFull;
|
||||||
volume = (volume * COLLISION_SOUND_COMPRESSION_RANGE) + (1.0f - COLLISION_SOUND_COMPRESSION_RANGE);
|
volume = (volume * COLLISION_SOUND_COMPRESSION_RANGE) + (1.0f - COLLISION_SOUND_COMPRESSION_RANGE);
|
||||||
|
|
||||||
|
@ -1148,6 +1155,7 @@ void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityT
|
||||||
options.volume = volume;
|
options.volume = volume;
|
||||||
AudioInjector* injector = new AudioInjector(sound.data(), options);
|
AudioInjector* injector = new AudioInjector(sound.data(), options);
|
||||||
injector->setLocalAudioInterface(_localAudioInterface);
|
injector->setLocalAudioInterface(_localAudioInterface);
|
||||||
|
injector->triggerDeleteAfterFinish();
|
||||||
QThread* injectorThread = new QThread();
|
QThread* injectorThread = new QThread();
|
||||||
injectorThread->setObjectName("Audio Injector Thread");
|
injectorThread->setObjectName("Audio Injector Thread");
|
||||||
injector->moveToThread(injectorThread);
|
injector->moveToThread(injectorThread);
|
||||||
|
@ -1168,7 +1176,7 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons
|
||||||
}
|
}
|
||||||
// Don't respond to small continuous contacts. It causes deadlocks when locking the entityTree.
|
// Don't respond to small continuous contacts. It causes deadlocks when locking the entityTree.
|
||||||
// Note that any entity script is likely to Entities.getEntityProperties(), which locks the tree.
|
// Note that any entity script is likely to Entities.getEntityProperties(), which locks the tree.
|
||||||
const float COLLISION_MINUMUM_PENETRATION = 0.001;
|
const float COLLISION_MINUMUM_PENETRATION = 0.005;
|
||||||
if ((collision.type != CONTACT_EVENT_TYPE_START) && (glm::length(collision.penetration) < COLLISION_MINUMUM_PENETRATION)) {
|
if ((collision.type != CONTACT_EVENT_TYPE_START) && (glm::length(collision.penetration) < COLLISION_MINUMUM_PENETRATION)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QEventLoop>
|
#include <QEventLoop>
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QNetworkConfiguration>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
|
@ -35,7 +36,7 @@ QString ScriptCache::getScript(const QUrl& url, ScriptUser* scriptUser, bool& is
|
||||||
isPending = true;
|
isPending = true;
|
||||||
bool alreadyWaiting = _scriptUsers.contains(url);
|
bool alreadyWaiting = _scriptUsers.contains(url);
|
||||||
_scriptUsers.insert(url, scriptUser);
|
_scriptUsers.insert(url, scriptUser);
|
||||||
|
|
||||||
if (alreadyWaiting) {
|
if (alreadyWaiting) {
|
||||||
qCDebug(scriptengine) << "Already downloading script at:" << url.toString();
|
qCDebug(scriptengine) << "Already downloading script at:" << url.toString();
|
||||||
} else {
|
} else {
|
||||||
|
@ -43,7 +44,7 @@ QString ScriptCache::getScript(const QUrl& url, ScriptUser* scriptUser, bool& is
|
||||||
QNetworkRequest networkRequest = QNetworkRequest(url);
|
QNetworkRequest networkRequest = QNetworkRequest(url);
|
||||||
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
|
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
|
||||||
|
|
||||||
qCDebug(scriptengine) << "Downloading script at:" << url.toString();
|
qCDebug(scriptengine) << "Downloading script at" << url.toString();
|
||||||
QNetworkReply* reply = networkAccessManager.get(networkRequest);
|
QNetworkReply* reply = networkAccessManager.get(networkRequest);
|
||||||
connect(reply, &QNetworkReply::finished, this, &ScriptCache::scriptDownloaded);
|
connect(reply, &QNetworkReply::finished, this, &ScriptCache::scriptDownloaded);
|
||||||
}
|
}
|
||||||
|
@ -56,7 +57,7 @@ void ScriptCache::scriptDownloaded() {
|
||||||
QUrl url = reply->url();
|
QUrl url = reply->url();
|
||||||
QList<ScriptUser*> scriptUsers = _scriptUsers.values(url);
|
QList<ScriptUser*> scriptUsers = _scriptUsers.values(url);
|
||||||
_scriptUsers.remove(url);
|
_scriptUsers.remove(url);
|
||||||
|
|
||||||
if (reply->error() == QNetworkReply::NoError && reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 200) {
|
if (reply->error() == QNetworkReply::NoError && reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 200) {
|
||||||
_scriptCache[url] = reply->readAll();
|
_scriptCache[url] = reply->readAll();
|
||||||
qCDebug(scriptengine) << "Done downloading script at:" << url.toString();
|
qCDebug(scriptengine) << "Done downloading script at:" << url.toString();
|
||||||
|
@ -65,7 +66,9 @@ void ScriptCache::scriptDownloaded() {
|
||||||
user->scriptContentsAvailable(url, _scriptCache[url]);
|
user->scriptContentsAvailable(url, _scriptCache[url]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
qCDebug(scriptengine) << "ERROR Loading file:" << reply->url().toString();
|
qCWarning(scriptengine) << "Error loading script from URL " << reply->url().toString()
|
||||||
|
<< "- HTTP status code is" << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt()
|
||||||
|
<< "and error from QNetworkReply is" << reply->errorString();
|
||||||
foreach(ScriptUser* user, scriptUsers) {
|
foreach(ScriptUser* user, scriptUsers) {
|
||||||
user->errorInLoadingScript(url);
|
user->errorInLoadingScript(url);
|
||||||
}
|
}
|
||||||
|
@ -73,4 +76,4 @@ void ScriptCache::scriptDownloaded() {
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue