diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp
index 63b2083aae..3acd783bb0 100644
--- a/assignment-client/src/audio/AudioMixer.cpp
+++ b/assignment-client/src/audio/AudioMixer.cpp
@@ -54,7 +54,7 @@
const short JITTER_BUFFER_MSECS = 12;
const short JITTER_BUFFER_SAMPLES = JITTER_BUFFER_MSECS * (SAMPLE_RATE / 1000.0);
-const float LOUDNESS_TO_DISTANCE_RATIO = 0.00305f;
+const float LOUDNESS_TO_DISTANCE_RATIO = 0.00001f;
const QString AUDIO_MIXER_LOGGING_TARGET_NAME = "audio-mixer";
@@ -348,6 +348,16 @@ void AudioMixer::readPendingDatagrams() {
|| mixerPacketType == PacketTypeSilentAudioFrame) {
nodeList->findNodeAndUpdateWithDataFromPacket(receivedPacket);
+ } else if (mixerPacketType == PacketTypeMuteEnvironment) {
+ QByteArray packet = receivedPacket;
+ populatePacketHeader(packet, PacketTypeMuteEnvironment);
+
+ foreach (const SharedNodePointer& node, nodeList->getNodeHash()) {
+ if (node->getType() == NodeType::Agent && node->getActiveSocket() && node->getLinkedData() && node != nodeList->sendingNodeForPacket(receivedPacket)) {
+ nodeList->writeDatagram(packet, packet.size(), node);
+ }
+ }
+
} else {
// let processNodeData handle it.
nodeList->processNodeData(senderSockAddr, receivedPacket);
diff --git a/examples/airGuitar.js b/examples/airGuitar.js
new file mode 100644
index 0000000000..08898579a7
--- /dev/null
+++ b/examples/airGuitar.js
@@ -0,0 +1,96 @@
+//
+// airGuitar.js
+// examples
+//
+// Copyright 2014 High Fidelity, Inc.
+//
+// This example musical instrument script plays guitar chords based on a strum motion and hand position
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+function length(v) {
+ return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
+}
+
+
+function printVector(v) {
+ print(v.x + ", " + v.y + ", " + v.z);
+ return;
+}
+
+function vMinus(a, b) {
+ var rval = { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z };
+ return rval;
+}
+
+// First, load two percussion sounds to be used on the sticks
+
+var guitarType = 2;
+
+if (guitarType == 1) {
+ var chord1 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Guitars/Guitar+-+Nylon+A.raw");
+ var chord2 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Guitars/Guitar+-+Nylon+B.raw");
+ var chord3 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Guitars/Guitar+-+Nylon+E.raw");
+} else {
+ var chord1 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Guitars/Guitar+-+Metal+A+short.raw");
+ var chord2 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Guitars/Guitar+-+Metal+B+short.raw");
+ var chord3 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Guitars/Guitar+-+Metal+E+short.raw");
+}
+
+
+var whichChord = chord1;
+
+var leftHanded = false;
+if (leftHanded) {
+ var strumHand = 0;
+ var chordHand = 1;
+} else {
+ var strumHand = 1;
+ var chordHand = 0;
+}
+
+var lastPosition = { x: 0.0,
+ y: 0.0,
+ z: 0.0 };
+
+
+function checkHands(deltaTime) {
+ for (var palm = 0; palm < 2; palm++) {
+ var palmVelocity = Controller.getSpatialControlVelocity(palm * 2 + 1);
+ var speed = length(palmVelocity);
+ var position = Controller.getSpatialControlPosition(palm * 2 + 1);
+ var myPelvis = MyAvatar.position;
+
+ if (palm == strumHand) {
+
+ var STRUM_HEIGHT_ABOVE_PELVIS = -0.30;
+ var strumTriggerHeight = myPelvis.y + STRUM_HEIGHT_ABOVE_PELVIS;
+ //printVector(position);
+ if ((position.y < strumTriggerHeight) && (lastPosition.y >= strumTriggerHeight)) {
+ // If hand passes downward through guitar strings, play a chord!
+ var options = new AudioInjectionOptions();
+ options.position = position;
+ if (speed > 1.0) { speed = 1.0; }
+ options.volume = speed;
+ Audio.playSound(whichChord, options);
+ }
+ lastPosition = Controller.getSpatialControlPosition(palm * 2 + 1);
+ } else {
+ // This is the chord controller
+ var distanceFromPelvis = Vec3.length(Vec3.subtract(position, myPelvis));
+ //print(distanceFromPelvis);
+ if (distanceFromPelvis > 0.63) {
+ whichChord = chord3;
+ } else if (distanceFromPelvis > 0.55) {
+ whichChord = chord2;
+ } else {
+ whichChord = chord1;
+ }
+ }
+ }
+}
+
+// Connect a call back that happens every frame
+Script.update.connect(checkHands);
\ No newline at end of file
diff --git a/examples/editModels.js b/examples/editModels.js
index 50b0137c4f..384d2f75a8 100644
--- a/examples/editModels.js
+++ b/examples/editModels.js
@@ -9,6 +9,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
+var windowDimensions = Controller.getViewportDimensions();
+
var LASER_WIDTH = 4;
var LASER_COLOR = { red: 255, green: 0, blue: 0 };
var LASER_LENGTH_FACTOR = 1.5;
@@ -16,6 +18,40 @@ var LASER_LENGTH_FACTOR = 1.5;
var LEFT = 0;
var RIGHT = 1;
+
+var SPAWN_DISTANCE = 1;
+var radiusDefault = 0.10;
+
+var modelURLs = [
+ "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/Feisar_Ship.FBX",
+ "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/birarda/birarda_head.fbx",
+ "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/pug.fbx",
+ "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/newInvader16x16-large-purple.svo",
+ "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/minotaur/mino_full.fbx",
+ "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/Combat_tank_V01.FBX",
+ "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/orc.fbx",
+ "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/slimer.fbx",
+ ];
+
+var toolIconUrl = "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/tools/";
+var numberOfTools = 1;
+var toolHeight = 50;
+var toolWidth = 50;
+var toolVerticalSpacing = 4;
+var toolsHeight = toolHeight * numberOfTools + toolVerticalSpacing * (numberOfTools - 1);
+var toolsX = windowDimensions.x - 8 - toolWidth;
+var toolsY = (windowDimensions.y - toolsHeight) / 2;
+
+
+var firstModel = Overlays.addOverlay("image", {
+ x: 0, y: 0, width: toolWidth, height: toolHeight,
+ subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight },
+ imageURL: toolIconUrl + "voxel-tool.svg",
+ x: toolsX, y: toolsY + ((toolHeight + toolVerticalSpacing) * 0), width: toolWidth, height: toolHeight,
+ visible: true,
+ alpha: 0.9
+ });
+
function controller(wichSide) {
this.side = wichSide;
this.palm = 2 * wichSide;
@@ -46,7 +82,10 @@ function controller(wichSide) {
this.pressing = false; // is trigger being pressed (is pressed now but wasn't previously)
this.grabbing = false;
- this.modelID;
+ this.modelID = { isKnownID: false };
+ this.oldModelRotation;
+ this.oldModelPosition;
+ this.oldModelRadius;
this.laser = Overlays.addOverlay("line3d", {
position: this.palmPosition,
@@ -85,23 +124,19 @@ function controller(wichSide) {
- this.grab = function (modelID) {
- if (!modelID.isKnownID) {
- var identify = Models.identifyModel(modelID);
- if (!identify.isKnownID) {
- print("Unknown ID " + identify.id + "(grab)");
- return;
- }
- modelID = identify;
- }
+ this.grab = function (modelID, properties) {
print("Grabbing " + modelID.id);
this.grabbing = true;
this.modelID = modelID;
+
+ this.oldModelPosition = properties.position;
+ this.oldModelRotation = properties.modelRotation;
+ this.oldModelRadius = properties.radius;
}
this.release = function () {
this.grabbing = false;
- this.modelID = 0;
+ this.modelID.isKnownID = false;
}
this.checkTrigger = function () {
@@ -118,6 +153,34 @@ function controller(wichSide) {
}
}
+ this.checkModel = function (properties) {
+ // P P - Model
+ // /| A - Palm
+ // / | d B - unit vector toward tip
+ // / | X - base of the perpendicular line
+ // A---X----->B d - distance fom axis
+ // x x - distance from A
+ //
+ // |X-A| = (P-A).B
+ // X == A + ((P-A).B)B
+ // d = |P-X|
+
+ var A = this.palmPosition;
+ var B = this.front;
+ var P = properties.position;
+
+ var x = Vec3.dot(Vec3.subtract(P, A), B);
+ var y = Vec3.dot(Vec3.subtract(P, A), this.up);
+ var z = Vec3.dot(Vec3.subtract(P, A), this.right);
+ var X = Vec3.sum(A, Vec3.multiply(B, x));
+ var d = Vec3.length(Vec3.subtract(P, X));
+
+ if (d < properties.radius && 0 < x && x < LASER_LENGTH_FACTOR) {
+ return { valid: true, x: x, y: y, z: z };
+ }
+ return { valid: false };
+ }
+
this.moveLaser = function () {
var endPosition = Vec3.sum(this.palmPosition, Vec3.multiply(this.front, LASER_LENGTH_FACTOR));
@@ -143,44 +206,33 @@ function controller(wichSide) {
});
}
- this.checkModel = function (modelID) {
- if (!modelID.isKnownID) {
- var identify = Models.identifyModel(modelID);
- if (!identify.isKnownID) {
- print("Unknown ID " + identify.id + "(checkModel)");
- return;
- }
- modelID = identify;
+ this.moveModel = function () {
+ if (this.grabbing) {
+ var newPosition = Vec3.sum(this.palmPosition,
+ Vec3.multiply(this.front, this.x));
+ newPosition = Vec3.sum(newPosition,
+ Vec3.multiply(this.up, this.y));
+ newPosition = Vec3.sum(newPosition,
+ Vec3.multiply(this.right, this.z));
+
+ var newRotation = Quat.multiply(this.rotation,
+ Quat.inverse(this.oldRotation));
+ newRotation = Quat.multiply(newRotation,
+ this.oldModelRotation);
+
+ Models.editModel(this.modelID, {
+ position: newPosition,
+ modelRotation: newRotation
+ });
+ print("Moving " + this.modelID.id);
+// Vec3.print("Old Position: ", this.oldModelPosition);
+// Vec3.print("Sav Position: ", newPosition);
+ Quat.print("Old Rotation: ", this.oldModelRotation);
+ Quat.print("New Rotation: ", newRotation);
+
+ this.oldModelRotation = newRotation;
+ this.oldModelPosition = newPosition;
}
- // P P - Model
- // /| A - Palm
- // / | d B - unit vector toward tip
- // / | X - base of the perpendicular line
- // A---X----->B d - distance fom axis
- // x x - distance from A
- //
- // |X-A| = (P-A).B
- // X == A + ((P-A).B)B
- // d = |P-X|
-
- var A = this.palmPosition;
- var B = this.front;
- var P = Models.getModelProperties(modelID).position;
-
- this.x = Vec3.dot(Vec3.subtract(P, A), B);
- this.y = Vec3.dot(Vec3.subtract(P, A), this.up);
- this.z = Vec3.dot(Vec3.subtract(P, A), this.right);
- var X = Vec3.sum(A, Vec3.multiply(B, this.x));
- var d = Vec3.length(Vec3.subtract(P, X));
-
-// Vec3.print("A: ", A);
-// Vec3.print("B: ", B);
-// Vec3.print("Particle pos: ", P);
-// print("d: " + d + ", x: " + this.x);
- if (d < Models.getModelProperties(modelID).radius && 0 < this.x && this.x < LASER_LENGTH_FACTOR) {
- return true;
- }
- return false;
}
this.update = function () {
@@ -205,25 +257,40 @@ function controller(wichSide) {
this.checkTrigger();
- if (this.pressing) {
- Vec3.print("Looking at: ", this.palmPosition);
- var foundModels = Models.findModels(this.palmPosition, LASER_LENGTH_FACTOR);
- for (var i = 0; i < foundModels.length; i++) {
- print("Model found ID (" + foundModels[i].id + ")");
- if (this.checkModel(foundModels[i])) {
- if (this.grab(foundModels[i])) {
- return;
- }
- }
- }
- }
+ this.moveLaser();
if (!this.pressed && this.grabbing) {
// release if trigger not pressed anymore.
this.release();
}
-
- this.moveLaser();
+
+ if (this.pressing) {
+ Vec3.print("Looking at: ", this.palmPosition);
+ var foundModels = Models.findModels(this.palmPosition, LASER_LENGTH_FACTOR);
+ for (var i = 0; i < foundModels.length; i++) {
+
+ if (!foundModels[i].isKnownID) {
+ var identify = Models.identifyModel(foundModels[i]);
+ if (!identify.isKnownID) {
+ print("Unknown ID " + identify.id + "(update loop)");
+ return;
+ }
+ foundModels[i] = identify;
+ }
+
+ var properties = Models.getModelProperties(foundModels[i]);
+ print("Checking properties: " + properties.id + " " + properties.isKnownID);
+
+ var check = this.checkModel(properties);
+ if (check.valid) {
+ this.grab(foundModels[i], properties);
+ this.x = check.x;
+ this.y = check.y;
+ this.z = check.z;
+ return;
+ }
+ }
+ }
}
this.cleanup = function () {
@@ -238,78 +305,44 @@ var leftController = new controller(LEFT);
var rightController = new controller(RIGHT);
function moveModels() {
- if (leftController.grabbing) {
- if (rightController.grabbing) {
- var properties = Models.getModelProperties(leftController.modelID);
-
- var oldLeftPoint = Vec3.sum(leftController.oldPalmPosition, Vec3.multiply(leftController.oldFront, leftController.x));
- var oldRightPoint = Vec3.sum(rightController.oldPalmPosition, Vec3.multiply(rightController.oldFront, rightController.x));
-
- var oldMiddle = Vec3.multiply(Vec3.sum(oldLeftPoint, oldRightPoint), 0.5);
- var oldLength = Vec3.length(Vec3.subtract(oldLeftPoint, oldRightPoint));
-
-
- var leftPoint = Vec3.sum(leftController.palmPosition, Vec3.multiply(leftController.front, leftController.x));
- var rightPoint = Vec3.sum(rightController.palmPosition, Vec3.multiply(rightController.front, rightController.x));
-
- var middle = Vec3.multiply(Vec3.sum(leftPoint, rightPoint), 0.5);
- var length = Vec3.length(Vec3.subtract(leftPoint, rightPoint));
-
- var ratio = length / oldLength;
-
- var newPosition = Vec3.sum(middle,
- Vec3.multiply(Vec3.subtract(properties.position, oldMiddle), ratio));
- Vec3.print("Ratio : " + ratio + " New position: ", newPosition);
- var rotation = Quat.multiply(leftController.rotation,
- Quat.inverse(leftController.oldRotation));
- rotation = Quat.multiply(rotation, properties.modelRotation);
-
- Models.editModel(leftController.modelID, {
- position: newPosition,
- //modelRotation: rotation,
- radius: properties.radius * ratio
- });
-
- return;
- } else {
- var newPosition = Vec3.sum(leftController.palmPosition,
- Vec3.multiply(leftController.front, leftController.x));
- newPosition = Vec3.sum(newPosition,
- Vec3.multiply(leftController.up, leftController.y));
- newPosition = Vec3.sum(newPosition,
- Vec3.multiply(leftController.right, leftController.z));
-
- var rotation = Quat.multiply(leftController.rotation,
- Quat.inverse(leftController.oldRotation));
- rotation = Quat.multiply(rotation,
- Models.getModelProperties(leftController.modelID).modelRotation);
-
- Models.editModel(leftController.modelID, {
- position: newPosition,
- modelRotation: rotation
- });
- }
- }
-
-
- if (rightController.grabbing) {
- var newPosition = Vec3.sum(rightController.palmPosition,
- Vec3.multiply(rightController.front, rightController.x));
- newPosition = Vec3.sum(newPosition,
- Vec3.multiply(rightController.up, rightController.y));
- newPosition = Vec3.sum(newPosition,
- Vec3.multiply(rightController.right, rightController.z));
+ if (leftController.grabbing && rightController.grabbing && rightController.modelID.id == leftController.modelID.id) {
+ print("Both controllers");
+ var oldLeftPoint = Vec3.sum(leftController.oldPalmPosition, Vec3.multiply(leftController.oldFront, leftController.x));
+ var oldRightPoint = Vec3.sum(rightController.oldPalmPosition, Vec3.multiply(rightController.oldFront, rightController.x));
- var rotation = Quat.multiply(rightController.rotation,
- Quat.inverse(rightController.oldRotation));
- rotation = Quat.multiply(rotation,
- Models.getModelProperties(rightController.modelID).modelRotation);
+ var oldMiddle = Vec3.multiply(Vec3.sum(oldLeftPoint, oldRightPoint), 0.5);
+ var oldLength = Vec3.length(Vec3.subtract(oldLeftPoint, oldRightPoint));
- Models.editModel(rightController.modelID, {
+
+ var leftPoint = Vec3.sum(leftController.palmPosition, Vec3.multiply(leftController.front, leftController.x));
+ var rightPoint = Vec3.sum(rightController.palmPosition, Vec3.multiply(rightController.front, rightController.x));
+
+ var middle = Vec3.multiply(Vec3.sum(leftPoint, rightPoint), 0.5);
+ var length = Vec3.length(Vec3.subtract(leftPoint, rightPoint));
+
+ var ratio = length / oldLength;
+
+ var newPosition = Vec3.sum(middle,
+ Vec3.multiply(Vec3.subtract(leftController.oldModelPosition, oldMiddle), ratio));
+ Vec3.print("Ratio : " + ratio + " New position: ", newPosition);
+ var rotation = Quat.multiply(leftController.rotation,
+ Quat.inverse(leftController.oldRotation));
+ rotation = Quat.multiply(rotation, leftController.oldModelRotation);
+
+ Models.editModel(leftController.modelID, {
position: newPosition,
- modelRotation: rotation
+ //modelRotation: rotation,
+ radius: leftController.oldModelRadius * ratio
});
+
+ leftController.oldModelPosition = newPosition;
+ leftController.oldModelRotation = rotation;
+ leftController.oldModelRadius *= ratio;
+ return;
}
+
+ leftController.moveModel();
+ rightController.moveModel();
}
function checkController(deltaTime) {
@@ -318,6 +351,8 @@ function checkController(deltaTime) {
var numberOfSpatialControls = Controller.getNumberOfSpatialControls();
var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers;
+ moveOverlays();
+
// this is expected for hydras
if (!(numberOfButtons==12 && numberOfTriggers == 2 && controllersPerTrigger == 2)) {
//print("no hydra connected?");
@@ -329,14 +364,48 @@ function checkController(deltaTime) {
moveModels();
}
+function moveOverlays() {
+ windowDimensions = Controller.getViewportDimensions();
+
+ toolsX = windowDimensions.x - 8 - toolWidth;
+ toolsY = (windowDimensions.y - toolsHeight) / 2;
+
+ Overlays.editOverlay(firstModel, {
+ x: toolsX, y: toolsY + ((toolHeight + toolVerticalSpacing) * 0), width: toolWidth, height: toolHeight,
+ });
+}
+
+function mousePressEvent(event) {
+ var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y});
+ var url;
+
+ if (clickedOverlay == firstModel) {
+ url = Window.prompt("Model url", modelURLs[Math.floor(Math.random() * modelURLs.length)]);
+ if (url == null) {
+ return; }
+ } else {
+ print("Didn't click on anything");
+ return;
+ }
+
+ var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE));
+ Models.addModel({ position: position,
+ radius: radiusDefault,
+ modelURL: url
+ });
+}
+
function scriptEnding() {
leftController.cleanup();
rightController.cleanup();
+
+ Overlays.deleteOverlay(firstModel);
}
Script.scriptEnding.connect(scriptEnding);
// register the call back so it fires before each data send
Script.update.connect(checkController);
+Controller.mousePressEvent.connect(mousePressEvent);
diff --git a/examples/hydraMove.js b/examples/hydraMove.js
index b73f990446..ad0eeddfca 100644
--- a/examples/hydraMove.js
+++ b/examples/hydraMove.js
@@ -31,14 +31,14 @@ var grabbingWithLeftHand = false;
var wasGrabbingWithLeftHand = false;
var EPSILON = 0.000001;
var velocity = { x: 0, y: 0, z: 0};
-var THRUST_MAG_UP = 800.0;
-var THRUST_MAG_DOWN = 300.0;
-var THRUST_MAG_FWD = 500.0;
-var THRUST_MAG_BACK = 300.0;
-var THRUST_MAG_LATERAL = 250.0;
+var THRUST_MAG_UP = 100.0;
+var THRUST_MAG_DOWN = 100.0;
+var THRUST_MAG_FWD = 150.0;
+var THRUST_MAG_BACK = 100.0;
+var THRUST_MAG_LATERAL = 150.0;
var THRUST_JUMP = 120.0;
-var YAW_MAG = 500.0;
+var YAW_MAG = 100.0;
var PITCH_MAG = 100.0;
var THRUST_MAG_HAND_JETS = THRUST_MAG_FWD;
var JOYSTICK_YAW_MAG = YAW_MAG;
diff --git a/examples/placeModelsWithHands.js b/examples/placeModelsWithHands.js
index 41d9d5dc86..e1ac151fe4 100644
--- a/examples/placeModelsWithHands.js
+++ b/examples/placeModelsWithHands.js
@@ -37,7 +37,7 @@ var radiusMinimum = 0.05;
var radiusMaximum = 0.5;
var modelURLs = [
- "https://s3-us-west-1.amazonaws.com/highfidelity-public/models/music/EVHFrankenstein.fbx",
+ "https://s3-us-west-1.amazonaws.com/highfidelity-public/models/attachments/topHat.fst",
"http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/Feisar_Ship.FBX",
"http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/birarda/birarda_head.fbx",
"http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/pug.fbx",
@@ -72,7 +72,6 @@ function keyPressEvent(event) {
}
} else if (event.text == "m") {
var URL = Window.prompt("Model URL", "Enter URL, e.g. http://foo.com/model.fbx");
- Window.alert("Your response was: " + prompt);
var modelPosition = getNewVoxelPosition();
var properties = { position: { x: modelPosition.x,
y: modelPosition.y,
diff --git a/interface/resources/html/interface-welcome-allsvg.html b/interface/resources/html/interface-welcome-allsvg.html
index 0b45a4d717..d025f8059b 100644
--- a/interface/resources/html/interface-welcome-allsvg.html
+++ b/interface/resources/html/interface-welcome-allsvg.html
@@ -1,139 +1,628 @@
-
+
-