mirror of
https://github.com/overte-org/overte.git
synced 2025-07-26 08:15:21 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into metavoxels
Conflicts: interface/src/MetavoxelSystem.cpp
This commit is contained in:
commit
ace415b138
29 changed files with 2293 additions and 5998 deletions
|
@ -2807,6 +2807,7 @@ function mouseReleaseEvent(event) {
|
||||||
// exists. If it doesn't they add it. If it does they don't. They also only delete the menu item if they were the one that
|
// exists. If it doesn't they add it. If it does they don't. They also only delete the menu item if they were the one that
|
||||||
// added it.
|
// added it.
|
||||||
var modelMenuAddedDelete = false;
|
var modelMenuAddedDelete = false;
|
||||||
|
var originalLightsArePickable = Entities.getLightsArePickable();
|
||||||
function setupModelMenus() {
|
function setupModelMenus() {
|
||||||
print("setupModelMenus()");
|
print("setupModelMenus()");
|
||||||
// adj our menuitems
|
// adj our menuitems
|
||||||
|
@ -2824,15 +2825,18 @@ function setupModelMenus() {
|
||||||
|
|
||||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Model List...", afterItem: "Models" });
|
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Model List...", afterItem: "Models" });
|
||||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Edit Properties..." });
|
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Edit Properties..." });
|
||||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Large Models", shortcutKey: "CTRL+META+L",
|
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Large Models", shortcutKey: "CTRL+META+L",
|
||||||
afterItem: "Paste Models", isCheckable: true });
|
afterItem: "Paste Models", isCheckable: true });
|
||||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Small Models", shortcutKey: "CTRL+META+S",
|
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Small Models", shortcutKey: "CTRL+META+S",
|
||||||
afterItem: "Allow Select Large Models", isCheckable: true });
|
afterItem: "Allow Selecting of Large Models", isCheckable: true });
|
||||||
|
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Lights", shortcutKey: "CTRL+SHIFT+META+L",
|
||||||
|
afterItem: "Allow Selecting of Small Models", isCheckable: true });
|
||||||
|
|
||||||
Menu.addMenuItem({ menuName: "File", menuItemName: "Models", isSeparator: true, beforeItem: "Settings" });
|
Menu.addMenuItem({ menuName: "File", menuItemName: "Models", isSeparator: true, beforeItem: "Settings" });
|
||||||
Menu.addMenuItem({ menuName: "File", menuItemName: "Export Models", shortcutKey: "CTRL+META+E", afterItem: "Models" });
|
Menu.addMenuItem({ menuName: "File", menuItemName: "Export Models", shortcutKey: "CTRL+META+E", afterItem: "Models" });
|
||||||
Menu.addMenuItem({ menuName: "File", menuItemName: "Import Models", shortcutKey: "CTRL+META+I", afterItem: "Export Models" });
|
Menu.addMenuItem({ menuName: "File", menuItemName: "Import Models", shortcutKey: "CTRL+META+I", afterItem: "Export Models" });
|
||||||
|
|
||||||
|
Entities.setLightsArePickable(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2846,8 +2850,9 @@ function cleanupModelMenus() {
|
||||||
|
|
||||||
Menu.removeMenuItem("Edit", "Model List...");
|
Menu.removeMenuItem("Edit", "Model List...");
|
||||||
Menu.removeMenuItem("Edit", "Paste Models");
|
Menu.removeMenuItem("Edit", "Paste Models");
|
||||||
Menu.removeMenuItem("Edit", "Allow Select Large Models");
|
Menu.removeMenuItem("Edit", "Allow Selecting of Large Models");
|
||||||
Menu.removeMenuItem("Edit", "Allow Select Small Models");
|
Menu.removeMenuItem("Edit", "Allow Selecting of Small Models");
|
||||||
|
Menu.removeMenuItem("Edit", "Allow Selecting of Lights");
|
||||||
|
|
||||||
Menu.removeSeparator("File", "Models");
|
Menu.removeSeparator("File", "Models");
|
||||||
Menu.removeMenuItem("File", "Export Models");
|
Menu.removeMenuItem("File", "Export Models");
|
||||||
|
@ -2865,6 +2870,7 @@ function scriptEnding() {
|
||||||
if (exportMenu) {
|
if (exportMenu) {
|
||||||
exportMenu.close();
|
exportMenu.close();
|
||||||
}
|
}
|
||||||
|
Entities.setLightsArePickable(originalLightsArePickable);
|
||||||
}
|
}
|
||||||
Script.scriptEnding.connect(scriptEnding);
|
Script.scriptEnding.connect(scriptEnding);
|
||||||
|
|
||||||
|
@ -2890,10 +2896,12 @@ function showPropertiesForm(editModelID) {
|
||||||
|
|
||||||
function handeMenuEvent(menuItem) {
|
function handeMenuEvent(menuItem) {
|
||||||
print("menuItemEvent() in JS... menuItem=" + menuItem);
|
print("menuItemEvent() in JS... menuItem=" + menuItem);
|
||||||
if (menuItem == "Allow Select Small Models") {
|
if (menuItem == "Allow Selecting of Small Models") {
|
||||||
allowSmallModels = Menu.isOptionChecked("Allow Select Small Models");
|
allowSmallModels = Menu.isOptionChecked("Allow Selecting of Small Models");
|
||||||
} else if (menuItem == "Allow Select Large Models") {
|
} else if (menuItem == "Allow Selecting of Large Models") {
|
||||||
allowLargeModels = Menu.isOptionChecked("Allow Select Large Models");
|
allowLargeModels = Menu.isOptionChecked("Allow Selecting of Large Models");
|
||||||
|
} else if (menuItem == "Allow Selecting of Lights") {
|
||||||
|
Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights"));
|
||||||
} else if (menuItem == "Delete") {
|
} else if (menuItem == "Delete") {
|
||||||
if (leftController.grabbing) {
|
if (leftController.grabbing) {
|
||||||
print(" Delete Entity.... leftController.entityID="+ leftController.entityID);
|
print(" Delete Entity.... leftController.entityID="+ leftController.entityID);
|
||||||
|
|
|
@ -16,11 +16,15 @@ var AXIS_STRAFE = Joysticks.AXIS_LEFT_X;
|
||||||
var AXIS_FORWARD = Joysticks.AXIS_LEFT_Y;
|
var AXIS_FORWARD = Joysticks.AXIS_LEFT_Y;
|
||||||
var AXIS_ROTATE = Joysticks.AXIS_RIGHT_X;
|
var AXIS_ROTATE = Joysticks.AXIS_RIGHT_X;
|
||||||
|
|
||||||
|
var BUTTON_SPRINT = Joysticks.BUTTON_LEFT_STICK;
|
||||||
|
|
||||||
|
var BUTTON_TOGGLE_MIRROR = Joysticks.BUTTON_FACE_LEFT;
|
||||||
|
|
||||||
var BUTTON_TURN_AROUND = Joysticks.BUTTON_RIGHT_STICK;
|
var BUTTON_TURN_AROUND = Joysticks.BUTTON_RIGHT_STICK;
|
||||||
|
|
||||||
var BUTTON_FLY_UP = Joysticks.BUTTON_RIGHT_SHOULDER;
|
var BUTTON_FLY_UP = Joysticks.BUTTON_RIGHT_SHOULDER;
|
||||||
var BUTTON_FLY_DOWN = Joysticks.BUTTON_LEFT_SHOULDER;
|
var BUTTON_FLY_DOWN = Joysticks.BUTTON_LEFT_SHOULDER;
|
||||||
var BUTTON_WARP = Joysticks.BUTTON_FACE_RIGHT;
|
var BUTTON_WARP = null; // Disable for now
|
||||||
|
|
||||||
var BUTTON_WARP_FORWARD = Joysticks.BUTTON_DPAD_UP;
|
var BUTTON_WARP_FORWARD = Joysticks.BUTTON_DPAD_UP;
|
||||||
var BUTTON_WARP_BACKWARD = Joysticks.BUTTON_DPAD_DOWN;
|
var BUTTON_WARP_BACKWARD = Joysticks.BUTTON_DPAD_DOWN;
|
||||||
|
@ -31,7 +35,8 @@ var BUTTON_WARP_RIGHT = Joysticks.BUTTON_DPAD_RIGHT;
|
||||||
var WARP_DISTANCE = 1;
|
var WARP_DISTANCE = 1;
|
||||||
|
|
||||||
// Walk speed in m/s
|
// Walk speed in m/s
|
||||||
var MOVE_SPEED = 2;
|
var MOVE_SPEED = 0.5;
|
||||||
|
var MOVE_SPRINT_SPEED = 2;
|
||||||
|
|
||||||
// Amount to rotate in radians
|
// Amount to rotate in radians
|
||||||
var ROTATE_INCREMENT = Math.PI / 8;
|
var ROTATE_INCREMENT = Math.PI / 8;
|
||||||
|
@ -46,9 +51,14 @@ var WARP_PICK_MAX_DISTANCE = 100;
|
||||||
var flyDownButtonState = false;
|
var flyDownButtonState = false;
|
||||||
var flyUpButtonState = false;
|
var flyUpButtonState = false;
|
||||||
|
|
||||||
|
// When toggling to mirror mode, this stores the mode the user was previously in
|
||||||
|
// so it can be toggled back to.
|
||||||
|
var toggledFromCameraMode = 'first person';
|
||||||
|
|
||||||
// Current move direction, axis aligned - that is, looking down and moving forward
|
// Current move direction, axis aligned - that is, looking down and moving forward
|
||||||
// will not move you into the ground, but instead will keep you on the horizontal plane.
|
// will not move you into the ground, but instead will keep you on the horizontal plane.
|
||||||
var moveDirection = { x: 0, y: 0, z: 0 };
|
var moveDirection = { x: 0, y: 0, z: 0 };
|
||||||
|
var sprintButtonState = false;
|
||||||
|
|
||||||
var warpActive = false;
|
var warpActive = false;
|
||||||
var warpPosition = { x: 0, y: 0, z: 0 };
|
var warpPosition = { x: 0, y: 0, z: 0 };
|
||||||
|
@ -173,6 +183,18 @@ function reportButtonValue(button, newValue, oldValue) {
|
||||||
MyAvatar.orientation = Quat.multiply(
|
MyAvatar.orientation = Quat.multiply(
|
||||||
Quat.fromPitchYawRollRadians(0, Math.PI, 0), MyAvatar.orientation);
|
Quat.fromPitchYawRollRadians(0, Math.PI, 0), MyAvatar.orientation);
|
||||||
}
|
}
|
||||||
|
} else if (button == BUTTON_SPRINT) {
|
||||||
|
sprintButtonState = newValue;
|
||||||
|
} else if (button == BUTTON_TOGGLE_MIRROR) {
|
||||||
|
if (newValue) {
|
||||||
|
var currentMode = Camera.mode;
|
||||||
|
if (currentMode != "mirror") {
|
||||||
|
toggledFromCameraMode = currentMode;
|
||||||
|
}
|
||||||
|
Camera.mode = "mirror";
|
||||||
|
} else {
|
||||||
|
Camera.mode = toggledFromCameraMode;
|
||||||
|
}
|
||||||
} else if (newValue) {
|
} else if (newValue) {
|
||||||
var direction = null;
|
var direction = null;
|
||||||
|
|
||||||
|
@ -209,9 +231,10 @@ function update(dt) {
|
||||||
var move = copyVec3(moveDirection);
|
var move = copyVec3(moveDirection);
|
||||||
move.y = 0;
|
move.y = 0;
|
||||||
if (Vec3.length(move) > 0) {
|
if (Vec3.length(move) > 0) {
|
||||||
|
speed = sprintButtonState ? MOVE_SPRINT_SPEED : MOVE_SPEED;
|
||||||
velocity = Vec3.multiplyQbyV(Camera.getOrientation(), move);
|
velocity = Vec3.multiplyQbyV(Camera.getOrientation(), move);
|
||||||
velocity.y = 0;
|
velocity.y = 0;
|
||||||
velocity = Vec3.multiply(Vec3.normalize(velocity), MOVE_SPEED);
|
velocity = Vec3.multiply(Vec3.normalize(velocity), speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (moveDirection.y != 0) {
|
if (moveDirection.y != 0) {
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,225 +1,277 @@
|
||||||
//
|
//
|
||||||
// walkFilters.js
|
// walkFilters.js
|
||||||
//
|
//
|
||||||
// version 1.001
|
// version 1.002
|
||||||
//
|
//
|
||||||
// Created by David Wooldridge, Autumn 2014
|
// Created by David Wooldridge, Autumn 2014
|
||||||
//
|
//
|
||||||
// Provides a variety of filters for use by the walk.js script v1.1
|
// Provides a variety of filters for use by the walk.js script v1.12
|
||||||
//
|
//
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
AveragingFilter = function(length) {
|
AveragingFilter = function(length) {
|
||||||
|
|
||||||
//this.name = name;
|
//this.name = name;
|
||||||
this.pastValues = [];
|
this.pastValues = [];
|
||||||
|
|
||||||
for(var i = 0; i < length; i++) {
|
for(var i = 0; i < length; i++) {
|
||||||
this.pastValues.push(0);
|
this.pastValues.push(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// single arg is the nextInputValue
|
// single arg is the nextInputValue
|
||||||
this.process = function() {
|
this.process = function() {
|
||||||
|
|
||||||
if (this.pastValues.length === 0 && arguments[0]) {
|
if (this.pastValues.length === 0 && arguments[0]) {
|
||||||
return arguments[0];
|
|
||||||
} else if (arguments[0]) {
|
return arguments[0];
|
||||||
// apply quick and simple LP filtering
|
|
||||||
this.pastValues.push(arguments[0]);
|
} else if (arguments[0] !== null) {
|
||||||
this.pastValues.shift();
|
|
||||||
var nextOutputValue = 0;
|
// apply quick and simple LP filtering
|
||||||
for (var ea in this.pastValues) nextOutputValue += this.pastValues[ea];
|
this.pastValues.push(arguments[0]);
|
||||||
return nextOutputValue / this.pastValues.length;
|
this.pastValues.shift();
|
||||||
} else {
|
var nextOutputValue = 0;
|
||||||
return 0;
|
for (var ea in this.pastValues) nextOutputValue += this.pastValues[ea];
|
||||||
}
|
return nextOutputValue / this.pastValues.length;
|
||||||
};
|
|
||||||
};
|
} else {
|
||||||
|
|
||||||
// 2nd order Butterworth LP filter - calculate coeffs here: http://www-users.cs.york.ac.uk/~fisher/mkfilter/trad.html
|
return 0;
|
||||||
// provides LP filtering with a more stable frequency / phase response
|
}
|
||||||
ButterworthFilter = function(cutOff) {
|
};
|
||||||
|
};
|
||||||
// cut off frequency = 5Hz
|
|
||||||
this.gain = 20.20612010;
|
|
||||||
this.coeffOne = -0.4775922501;
|
// 1st order Butterworth filter - calculate coeffs here: http://www-users.cs.york.ac.uk/~fisher/mkfilter/trad.html
|
||||||
this.coeffTwo = 1.2796324250;
|
// provides LP filtering with a more stable frequency / phase response (-3 dB @ 3 Hz)
|
||||||
|
ButterworthFilter1 = function() {
|
||||||
// initialise the arrays
|
|
||||||
this.xv = [];
|
this.gain = 7.313751515;
|
||||||
this.yv = [];
|
this.coeff = 0.7265425280;
|
||||||
for(var i = 0; i < 3; i++) {
|
|
||||||
this.xv.push(0);
|
// initialise the arrays
|
||||||
this.yv.push(0);
|
this.xv = [];
|
||||||
}
|
this.yv = [];
|
||||||
|
|
||||||
// process values
|
for(var i = 0; i < 2; i++) {
|
||||||
this.process = function(nextInputValue) {
|
|
||||||
|
this.xv.push(0);
|
||||||
this.xv[0] = this.xv[1];
|
this.yv.push(0);
|
||||||
this.xv[1] = this.xv[2];
|
}
|
||||||
this.xv[2] = nextInputValue / this.gain;
|
|
||||||
|
// process values
|
||||||
this.yv[0] = this.yv[1];
|
this.process = function(nextInputValue) {
|
||||||
this.yv[1] = this.yv[2];
|
|
||||||
this.yv[2] = (this.xv[0] + this.xv[2]) +
|
this.xv[0] = this.xv[1];
|
||||||
2 * this.xv[1] +
|
this.xv[1] = nextInputValue / this.gain;
|
||||||
(this.coeffOne * this.yv[0]) +
|
|
||||||
(this.coeffTwo * this.yv[1]);
|
this.yv[0] = this.yv[1];
|
||||||
|
this.yv[1] = this.xv[0] + this.xv[1] + this.coeff * this.yv[0];
|
||||||
return this.yv[2];
|
|
||||||
};
|
return this.yv[1];
|
||||||
}; // end Butterworth filter contructor
|
};
|
||||||
|
|
||||||
// Add harmonics to a given sine wave to form square, sawtooth or triangle waves
|
}; // end Butterworth filter constructor
|
||||||
// Geometric wave synthesis fundamentals taken from: http://hyperphysics.phy-astr.gsu.edu/hbase/audio/geowv.html
|
|
||||||
WaveSynth = function(waveShape, numHarmonics, smoothing) {
|
// 2nd order Butterworth LP filter - calculate coeffs here: http://www-users.cs.york.ac.uk/~fisher/mkfilter/trad.html
|
||||||
|
// provides LP filtering with a more stable frequency / phase response
|
||||||
this.numHarmonics = numHarmonics;
|
ButterworthFilter2 = function(cutOff) {
|
||||||
this.waveShape = waveShape;
|
|
||||||
this.averagingFilter = new AveragingFilter(smoothing);
|
switch(cutOff) {
|
||||||
|
|
||||||
// NB: frequency in radians
|
case 5:
|
||||||
this.shapeWave = function(frequency) {
|
default:
|
||||||
|
|
||||||
// make some shapes
|
this.gain = 20.20612010;
|
||||||
var harmonics = 0;
|
this.coeffOne = -0.4775922501;
|
||||||
var multiplier = 0;
|
this.coeffTwo = 1.2796324250;
|
||||||
var iterations = this.numHarmonics * 2 + 2;
|
break;
|
||||||
if (this.waveShape === TRIANGLE) {
|
}
|
||||||
iterations++;
|
|
||||||
}
|
// initialise the arrays
|
||||||
|
this.xv = [];
|
||||||
for(var n = 2; n < iterations; n++) {
|
this.yv = [];
|
||||||
|
for(var i = 0; i < 3; i++) {
|
||||||
switch(this.waveShape) {
|
|
||||||
|
this.xv.push(0);
|
||||||
case SAWTOOTH: {
|
this.yv.push(0);
|
||||||
|
}
|
||||||
multiplier = 1 / n;
|
|
||||||
harmonics += multiplier * Math.sin(n * frequency);
|
// process values
|
||||||
break;
|
this.process = function(nextInputValue) {
|
||||||
}
|
|
||||||
|
this.xv[0] = this.xv[1];
|
||||||
case TRIANGLE: {
|
this.xv[1] = this.xv[2];
|
||||||
|
this.xv[2] = nextInputValue / this.gain;
|
||||||
if (n % 2 === 1) {
|
|
||||||
var mulitplier = 1 / (n * n);
|
this.yv[0] = this.yv[1];
|
||||||
// multiply (4n-1)th harmonics by -1
|
this.yv[1] = this.yv[2];
|
||||||
if (n === 3 || n === 7 || n === 11 || n === 15) {
|
this.yv[2] = (this.xv[0] + this.xv[2]) +
|
||||||
mulitplier *= -1;
|
2 * this.xv[1] +
|
||||||
}
|
(this.coeffOne * this.yv[0]) +
|
||||||
harmonics += mulitplier * Math.sin(n * frequency);
|
(this.coeffTwo * this.yv[1]);
|
||||||
}
|
|
||||||
break;
|
return this.yv[2];
|
||||||
}
|
};
|
||||||
|
}; // end Butterworth filter constructor
|
||||||
case SQUARE: {
|
|
||||||
|
|
||||||
if (n % 2 === 1) {
|
// Add harmonics to a given sine wave to form square, sawtooth or triangle waves
|
||||||
multiplier = 1 / n;
|
// Geometric wave synthesis fundamentals taken from: http://hyperphysics.phy-astr.gsu.edu/hbase/audio/geowv.html
|
||||||
harmonics += multiplier * Math.sin(n * frequency);
|
WaveSynth = function(waveShape, numHarmonics, smoothing) {
|
||||||
}
|
|
||||||
break;
|
this.numHarmonics = numHarmonics;
|
||||||
}
|
this.waveShape = waveShape;
|
||||||
}
|
this.smoothingFilter = new AveragingFilter(smoothing);
|
||||||
}
|
|
||||||
|
// NB: frequency in radians
|
||||||
// smooth the result and return
|
this.calculate = function(frequency) {
|
||||||
return this.averagingFilter.process(harmonics);
|
|
||||||
};
|
// make some shapes
|
||||||
};
|
var harmonics = 0;
|
||||||
|
var multiplier = 0;
|
||||||
// Create a wave shape by summing pre-calcualted sinusoidal harmonics
|
var iterations = this.numHarmonics * 2 + 2;
|
||||||
HarmonicsFilter = function(magnitudes, phaseAngles) {
|
if (this.waveShape === TRIANGLE) {
|
||||||
|
iterations++;
|
||||||
this.magnitudes = magnitudes;
|
}
|
||||||
this.phaseAngles = phaseAngles;
|
|
||||||
|
for(var n = 1; n < iterations; n++) {
|
||||||
this.calculate = function(twoPiFT) {
|
|
||||||
|
switch(this.waveShape) {
|
||||||
var harmonics = 0;
|
|
||||||
var numHarmonics = magnitudes.length;
|
case SAWTOOTH: {
|
||||||
|
|
||||||
for(var n = 0; n < numHarmonics; n++) {
|
multiplier = 1 / n;
|
||||||
harmonics += this.magnitudes[n] * Math.cos(n * twoPiFT - this.phaseAngles[n]);
|
harmonics += multiplier * Math.sin(n * frequency);
|
||||||
}
|
break;
|
||||||
return harmonics;
|
}
|
||||||
};
|
|
||||||
};
|
case TRIANGLE: {
|
||||||
|
|
||||||
// the main filter object literal
|
if (n % 2 === 1) {
|
||||||
filter = (function() {
|
var mulitplier = 1 / (n * n);
|
||||||
|
// multiply (4n-1)th harmonics by -1
|
||||||
// Bezier private functions
|
if (n === 3 || n === 7 || n === 11 || n === 15) {
|
||||||
function _B1(t) { return t * t * t };
|
mulitplier *= -1;
|
||||||
function _B2(t) { return 3 * t * t * (1 - t) };
|
}
|
||||||
function _B3(t) { return 3 * t * (1 - t) * (1 - t) };
|
harmonics += mulitplier * Math.sin(n * frequency);
|
||||||
function _B4(t) { return (1 - t) * (1 - t) * (1 - t) };
|
}
|
||||||
|
break;
|
||||||
return {
|
}
|
||||||
|
|
||||||
// helper methods
|
case SQUARE: {
|
||||||
degToRad: function(degrees) {
|
|
||||||
|
if (n % 2 === 1) {
|
||||||
var convertedValue = degrees * Math.PI / 180;
|
multiplier = 1 / n;
|
||||||
return convertedValue;
|
harmonics += multiplier * Math.sin(n * frequency);
|
||||||
},
|
}
|
||||||
|
break;
|
||||||
radToDeg: function(radians) {
|
}
|
||||||
|
}
|
||||||
var convertedValue = radians * 180 / Math.PI;
|
}
|
||||||
return convertedValue;
|
|
||||||
},
|
// smooth the result and return
|
||||||
|
return this.smoothingFilter.process(harmonics);
|
||||||
// these filters need instantiating, as they hold arrays of previous values
|
};
|
||||||
createAveragingFilter: function(length) {
|
};
|
||||||
|
|
||||||
var newAveragingFilter = new AveragingFilter(length);
|
// Create a motion wave by summing pre-calcualted sinusoidal harmonics
|
||||||
return newAveragingFilter;
|
HarmonicsFilter = function(magnitudes, phaseAngles) {
|
||||||
},
|
|
||||||
|
this.magnitudes = magnitudes;
|
||||||
createButterworthFilter: function(cutoff) {
|
this.phaseAngles = phaseAngles;
|
||||||
|
|
||||||
var newButterworthFilter = new ButterworthFilter(cutoff);
|
this.calculate = function(twoPiFT) {
|
||||||
return newButterworthFilter;
|
|
||||||
},
|
var harmonics = 0;
|
||||||
|
var numHarmonics = magnitudes.length;
|
||||||
createWaveSynth: function(waveShape, numHarmonics, smoothing) {
|
|
||||||
|
for(var n = 0; n < numHarmonics; n++) {
|
||||||
var newWaveSynth = new WaveSynth(waveShape, numHarmonics, smoothing);
|
harmonics += this.magnitudes[n] * Math.cos(n * twoPiFT - this.phaseAngles[n]);
|
||||||
return newWaveSynth;
|
}
|
||||||
},
|
return harmonics;
|
||||||
|
};
|
||||||
createHarmonicsFilter: function(magnitudes, phaseAngles) {
|
};
|
||||||
|
|
||||||
var newHarmonicsFilter = new HarmonicsFilter(magnitudes, phaseAngles);
|
|
||||||
return newHarmonicsFilter;
|
// the main filter object
|
||||||
},
|
filter = (function() {
|
||||||
|
|
||||||
|
// Bezier private functions
|
||||||
// the following filters do not need separate instances, as they hold no previous values
|
function _B1(t) { return t * t * t };
|
||||||
bezier: function(percent, C1, C2, C3, C4) {
|
function _B2(t) { return 3 * t * t * (1 - t) };
|
||||||
|
function _B3(t) { return 3 * t * (1 - t) * (1 - t) };
|
||||||
// Bezier functions for more natural transitions
|
function _B4(t) { return (1 - t) * (1 - t) * (1 - t) };
|
||||||
// based on script by Dan Pupius (www.pupius.net) http://13thparallel.com/archive/bezier-curves/
|
|
||||||
var pos = {x: 0, y: 0};
|
return {
|
||||||
pos.x = C1.x * _B1(percent) + C2.x * _B2(percent) + C3.x * _B3(percent) + C4.x * _B4(percent);
|
|
||||||
pos.y = C1.y * _B1(percent) + C2.y * _B2(percent) + C3.y * _B3(percent) + C4.y * _B4(percent);
|
// helper methods
|
||||||
return pos;
|
degToRad: function(degrees) {
|
||||||
},
|
|
||||||
|
var convertedValue = degrees * Math.PI / 180;
|
||||||
// simple clipping filter (clips bottom of wave only, special case for hips y-axis skeleton offset)
|
return convertedValue;
|
||||||
clipTrough: function(inputValue, peak, strength) {
|
},
|
||||||
|
|
||||||
var outputValue = inputValue * strength;
|
radToDeg: function(radians) {
|
||||||
if (outputValue < -peak) {
|
|
||||||
outputValue = -peak;
|
var convertedValue = radians * 180 / Math.PI;
|
||||||
}
|
return convertedValue;
|
||||||
return outputValue;
|
},
|
||||||
}
|
|
||||||
}
|
// these filters need instantiating, as they hold arrays of previous values
|
||||||
|
createAveragingFilter: function(length) {
|
||||||
|
|
||||||
|
var newAveragingFilter = new AveragingFilter(length);
|
||||||
|
return newAveragingFilter;
|
||||||
|
},
|
||||||
|
|
||||||
|
createButterworthFilter1: function() {
|
||||||
|
|
||||||
|
var newButterworthFilter = new ButterworthFilter1();
|
||||||
|
return newButterworthFilter;
|
||||||
|
},
|
||||||
|
|
||||||
|
createButterworthFilter2: function(cutoff) {
|
||||||
|
|
||||||
|
var newButterworthFilter = new ButterworthFilter2(cutoff);
|
||||||
|
return newButterworthFilter;
|
||||||
|
},
|
||||||
|
|
||||||
|
createWaveSynth: function(waveShape, numHarmonics, smoothing) {
|
||||||
|
|
||||||
|
var newWaveSynth = new WaveSynth(waveShape, numHarmonics, smoothing);
|
||||||
|
return newWaveSynth;
|
||||||
|
},
|
||||||
|
|
||||||
|
createHarmonicsFilter: function(magnitudes, phaseAngles) {
|
||||||
|
|
||||||
|
var newHarmonicsFilter = new HarmonicsFilter(magnitudes, phaseAngles);
|
||||||
|
return newHarmonicsFilter;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// the following filters do not need separate instances, as they hold no previous values
|
||||||
|
bezier: function(percent, C1, C2, C3, C4) {
|
||||||
|
|
||||||
|
// Bezier functions for more natural transitions
|
||||||
|
// based on script by Dan Pupius (www.pupius.net) http://13thparallel.com/archive/bezier-curves/
|
||||||
|
var pos = {x: 0, y: 0};
|
||||||
|
pos.x = C1.x * _B1(percent) + C2.x * _B2(percent) + C3.x * _B3(percent) + C4.x * _B4(percent);
|
||||||
|
pos.y = C1.y * _B1(percent) + C2.y * _B2(percent) + C3.y * _B3(percent) + C4.y * _B4(percent);
|
||||||
|
return pos;
|
||||||
|
},
|
||||||
|
|
||||||
|
// simple clipping filter (clips bottom of wave only)
|
||||||
|
clipTrough: function(inputValue, peak, strength) {
|
||||||
|
|
||||||
|
var outputValue = inputValue * strength;
|
||||||
|
if (outputValue < -peak) {
|
||||||
|
outputValue = -peak;
|
||||||
|
}
|
||||||
|
return outputValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
})();
|
})();
|
File diff suppressed because it is too large
Load diff
|
@ -640,6 +640,7 @@ Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
|
||||||
// exists. If it doesn't they add it. If it does they don't. They also only delete the menu item if they were the one that
|
// exists. If it doesn't they add it. If it does they don't. They also only delete the menu item if they were the one that
|
||||||
// added it.
|
// added it.
|
||||||
var modelMenuAddedDelete = false;
|
var modelMenuAddedDelete = false;
|
||||||
|
var originalLightsArePickable = Entities.getLightsArePickable();
|
||||||
function setupModelMenus() {
|
function setupModelMenus() {
|
||||||
print("setupModelMenus()");
|
print("setupModelMenus()");
|
||||||
// adj our menuitems
|
// adj our menuitems
|
||||||
|
@ -657,10 +658,12 @@ function setupModelMenus() {
|
||||||
|
|
||||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Model List...", afterItem: "Models" });
|
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Model List...", afterItem: "Models" });
|
||||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Edit Properties..." });
|
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Edit Properties..." });
|
||||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Large Models", shortcutKey: "CTRL+META+L",
|
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Large Models", shortcutKey: "CTRL+META+L",
|
||||||
afterItem: "Paste Models", isCheckable: true, isChecked: true });
|
afterItem: "Paste Models", isCheckable: true, isChecked: true });
|
||||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Small Models", shortcutKey: "CTRL+META+S",
|
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Small Models", shortcutKey: "CTRL+META+S",
|
||||||
afterItem: "Allow Select Large Models", isCheckable: true, isChecked: true });
|
afterItem: "Allow Selecting of Large Models", isCheckable: true, isChecked: true });
|
||||||
|
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Lights", shortcutKey: "CTRL+SHIFT+META+L",
|
||||||
|
afterItem: "Allow Selecting of Small Models", isCheckable: true });
|
||||||
|
|
||||||
Menu.addMenuItem({ menuName: "File", menuItemName: "Models", isSeparator: true, beforeItem: "Settings" });
|
Menu.addMenuItem({ menuName: "File", menuItemName: "Models", isSeparator: true, beforeItem: "Settings" });
|
||||||
Menu.addMenuItem({ menuName: "File", menuItemName: "Export Models", shortcutKey: "CTRL+META+E", afterItem: "Models" });
|
Menu.addMenuItem({ menuName: "File", menuItemName: "Export Models", shortcutKey: "CTRL+META+E", afterItem: "Models" });
|
||||||
|
@ -669,6 +672,8 @@ function setupModelMenus() {
|
||||||
|
|
||||||
Menu.addMenuItem({ menuName: "View", menuItemName: MENU_EASE_ON_FOCUS, afterItem: MENU_INSPECT_TOOL_ENABLED,
|
Menu.addMenuItem({ menuName: "View", menuItemName: MENU_EASE_ON_FOCUS, afterItem: MENU_INSPECT_TOOL_ENABLED,
|
||||||
isCheckable: true, isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true" });
|
isCheckable: true, isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true" });
|
||||||
|
|
||||||
|
Entities.setLightsArePickable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
setupModelMenus(); // do this when first running our script.
|
setupModelMenus(); // do this when first running our script.
|
||||||
|
@ -683,8 +688,9 @@ function cleanupModelMenus() {
|
||||||
|
|
||||||
Menu.removeMenuItem("Edit", "Model List...");
|
Menu.removeMenuItem("Edit", "Model List...");
|
||||||
Menu.removeMenuItem("Edit", "Paste Models");
|
Menu.removeMenuItem("Edit", "Paste Models");
|
||||||
Menu.removeMenuItem("Edit", "Allow Select Large Models");
|
Menu.removeMenuItem("Edit", "Allow Selecting of Large Models");
|
||||||
Menu.removeMenuItem("Edit", "Allow Select Small Models");
|
Menu.removeMenuItem("Edit", "Allow Selecting of Small Models");
|
||||||
|
Menu.removeMenuItem("Edit", "Allow Selecting of Lights");
|
||||||
|
|
||||||
Menu.removeSeparator("File", "Models");
|
Menu.removeSeparator("File", "Models");
|
||||||
Menu.removeMenuItem("File", "Export Models");
|
Menu.removeMenuItem("File", "Export Models");
|
||||||
|
@ -708,6 +714,7 @@ Script.scriptEnding.connect(function() {
|
||||||
if (exportMenu) {
|
if (exportMenu) {
|
||||||
exportMenu.close();
|
exportMenu.close();
|
||||||
}
|
}
|
||||||
|
Entities.setLightsArePickable(originalLightsArePickable);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Do some stuff regularly, like check for placement of various overlays
|
// Do some stuff regularly, like check for placement of various overlays
|
||||||
|
@ -718,10 +725,12 @@ Script.update.connect(function (deltaTime) {
|
||||||
});
|
});
|
||||||
|
|
||||||
function handeMenuEvent(menuItem) {
|
function handeMenuEvent(menuItem) {
|
||||||
if (menuItem == "Allow Select Small Models") {
|
if (menuItem == "Allow Selecting of Small Models") {
|
||||||
allowSmallModels = Menu.isOptionChecked("Allow Select Small Models");
|
allowSmallModels = Menu.isOptionChecked("Allow Selecting of Small Models");
|
||||||
} else if (menuItem == "Allow Select Large Models") {
|
} else if (menuItem == "Allow Selecting of Large Models") {
|
||||||
allowLargeModels = Menu.isOptionChecked("Allow Select Large Models");
|
allowLargeModels = Menu.isOptionChecked("Allow Selecting of Large Models");
|
||||||
|
} else if (menuItem == "Allow Selecting of Lights") {
|
||||||
|
Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights"));
|
||||||
} else if (menuItem == "Delete") {
|
} else if (menuItem == "Delete") {
|
||||||
if (SelectionManager.hasSelection()) {
|
if (SelectionManager.hasSelection()) {
|
||||||
print(" Delete Entities");
|
print(" Delete Entities");
|
||||||
|
|
3465
examples/walk.js
3465
examples/walk.js
File diff suppressed because it is too large
Load diff
|
@ -896,6 +896,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
||||||
case Qt::Key_Greater:
|
case Qt::Key_Greater:
|
||||||
case Qt::Key_Comma:
|
case Qt::Key_Comma:
|
||||||
case Qt::Key_Period:
|
case Qt::Key_Period:
|
||||||
|
case Qt::Key_QuoteDbl:
|
||||||
Menu::getInstance()->handleViewFrustumOffsetKeyModifier(event->key());
|
Menu::getInstance()->handleViewFrustumOffsetKeyModifier(event->key());
|
||||||
break;
|
break;
|
||||||
case Qt::Key_L:
|
case Qt::Key_L:
|
||||||
|
@ -2089,12 +2090,6 @@ void Application::updateMouseRay() {
|
||||||
_mouseRayDirection -= 2.0f * (_viewFrustum.getDirection() * glm::dot(_viewFrustum.getDirection(), _mouseRayDirection) +
|
_mouseRayDirection -= 2.0f * (_viewFrustum.getDirection() * glm::dot(_viewFrustum.getDirection(), _mouseRayDirection) +
|
||||||
_viewFrustum.getRight() * glm::dot(_viewFrustum.getRight(), _mouseRayDirection));
|
_viewFrustum.getRight() * glm::dot(_viewFrustum.getRight(), _mouseRayDirection));
|
||||||
}
|
}
|
||||||
|
|
||||||
// tell my avatar if the mouse is being pressed...
|
|
||||||
_myAvatar->setMousePressed(_mousePressed);
|
|
||||||
|
|
||||||
// tell my avatar the posiion and direction of the ray projected ino the world based on the mouse position
|
|
||||||
_myAvatar->setMouseRay(_mouseRayOrigin, _mouseRayDirection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::updateFaceshift() {
|
void Application::updateFaceshift() {
|
||||||
|
@ -2915,7 +2910,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderAr
|
||||||
// transform by eye offset
|
// transform by eye offset
|
||||||
|
|
||||||
// load the view frustum
|
// load the view frustum
|
||||||
loadViewFrustum(whichCamera, _displayViewFrustum);
|
loadViewFrustum(whichCamera, _viewFrustum);
|
||||||
|
|
||||||
// flip x if in mirror mode (also requires reversing winding order for backface culling)
|
// flip x if in mirror mode (also requires reversing winding order for backface culling)
|
||||||
if (whichCamera.getMode() == CAMERA_MODE_MIRROR) {
|
if (whichCamera.getMode() == CAMERA_MODE_MIRROR) {
|
||||||
|
@ -3189,7 +3184,7 @@ void Application::computeOffAxisFrustum(float& left, float& right, float& bottom
|
||||||
float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const {
|
float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const {
|
||||||
|
|
||||||
// allow 3DTV/Oculus to override parameters from camera
|
// allow 3DTV/Oculus to override parameters from camera
|
||||||
_displayViewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
|
_viewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
|
||||||
if (OculusManager::isConnected()) {
|
if (OculusManager::isConnected()) {
|
||||||
OculusManager::overrideOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
|
OculusManager::overrideOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
|
||||||
|
|
||||||
|
|
|
@ -196,7 +196,6 @@ public:
|
||||||
const AudioReflector* getAudioReflector() const { return &_audioReflector; }
|
const AudioReflector* getAudioReflector() const { return &_audioReflector; }
|
||||||
Camera* getCamera() { return &_myCamera; }
|
Camera* getCamera() { return &_myCamera; }
|
||||||
ViewFrustum* getViewFrustum() { return &_viewFrustum; }
|
ViewFrustum* getViewFrustum() { return &_viewFrustum; }
|
||||||
ViewFrustum* getDisplayViewFrustum() { return &_displayViewFrustum; }
|
|
||||||
ViewFrustum* getShadowViewFrustum() { return &_shadowViewFrustum; }
|
ViewFrustum* getShadowViewFrustum() { return &_shadowViewFrustum; }
|
||||||
VoxelImporter* getVoxelImporter() { return &_voxelImporter; }
|
VoxelImporter* getVoxelImporter() { return &_voxelImporter; }
|
||||||
VoxelSystem* getVoxels() { return &_voxels; }
|
VoxelSystem* getVoxels() { return &_voxels; }
|
||||||
|
@ -518,7 +517,6 @@ private:
|
||||||
|
|
||||||
ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc.
|
ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc.
|
||||||
ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels)
|
ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels)
|
||||||
ViewFrustum _displayViewFrustum;
|
|
||||||
ViewFrustum _shadowViewFrustum;
|
ViewFrustum _shadowViewFrustum;
|
||||||
quint64 _lastQueriedTime;
|
quint64 _lastQueriedTime;
|
||||||
|
|
||||||
|
|
|
@ -835,6 +835,14 @@ void Menu::handleViewFrustumOffsetKeyModifier(int key) {
|
||||||
const float VIEW_FRUSTUM_OFFSET_UP_DELTA = 0.05f;
|
const float VIEW_FRUSTUM_OFFSET_UP_DELTA = 0.05f;
|
||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
|
case Qt::Key_QuoteDbl:
|
||||||
|
_viewFrustumOffset.yaw = 0.0f;
|
||||||
|
_viewFrustumOffset.pitch = 0.0f;
|
||||||
|
_viewFrustumOffset.roll = 0.0f;
|
||||||
|
_viewFrustumOffset.up = 0.0f;
|
||||||
|
_viewFrustumOffset.distance = 0.0f;
|
||||||
|
break;
|
||||||
|
|
||||||
case Qt::Key_BracketLeft:
|
case Qt::Key_BracketLeft:
|
||||||
_viewFrustumOffset.yaw -= VIEW_FRUSTUM_OFFSET_DELTA;
|
_viewFrustumOffset.yaw -= VIEW_FRUSTUM_OFFSET_DELTA;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -192,7 +192,7 @@ static const float EIGHT_BIT_MAXIMUM_RECIPROCAL = 1.0f / EIGHT_BIT_MAXIMUM;
|
||||||
|
|
||||||
void MetavoxelSystem::render() {
|
void MetavoxelSystem::render() {
|
||||||
// update the frustum
|
// update the frustum
|
||||||
ViewFrustum* viewFrustum = Application::getInstance()->getDisplayViewFrustum();
|
ViewFrustum* viewFrustum = Application::getInstance()->getViewFrustum();
|
||||||
_frustum.set(viewFrustum->getFarTopLeft(), viewFrustum->getFarTopRight(), viewFrustum->getFarBottomLeft(),
|
_frustum.set(viewFrustum->getFarTopLeft(), viewFrustum->getFarTopRight(), viewFrustum->getFarBottomLeft(),
|
||||||
viewFrustum->getFarBottomRight(), viewFrustum->getNearTopLeft(), viewFrustum->getNearTopRight(),
|
viewFrustum->getFarBottomRight(), viewFrustum->getNearTopLeft(), viewFrustum->getNearTopRight(),
|
||||||
viewFrustum->getNearBottomLeft(), viewFrustum->getNearBottomRight());
|
viewFrustum->getNearBottomLeft(), viewFrustum->getNearBottomRight());
|
||||||
|
@ -600,7 +600,7 @@ protected:
|
||||||
SpannerRenderVisitor::SpannerRenderVisitor(const MetavoxelLOD& lod) :
|
SpannerRenderVisitor::SpannerRenderVisitor(const MetavoxelLOD& lod) :
|
||||||
SpannerVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannersAttribute(),
|
SpannerVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannersAttribute(),
|
||||||
QVector<AttributePointer>(), QVector<AttributePointer>(), lod,
|
QVector<AttributePointer>(), QVector<AttributePointer>(), lod,
|
||||||
encodeOrder(Application::getInstance()->getDisplayViewFrustum()->getDirection())),
|
encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())),
|
||||||
_containmentDepth(INT_MAX) {
|
_containmentDepth(INT_MAX) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1953,7 +1953,7 @@ private:
|
||||||
|
|
||||||
BufferRenderVisitor::BufferRenderVisitor(const AttributePointer& attribute) :
|
BufferRenderVisitor::BufferRenderVisitor(const AttributePointer& attribute) :
|
||||||
MetavoxelVisitor(QVector<AttributePointer>() << attribute),
|
MetavoxelVisitor(QVector<AttributePointer>() << attribute),
|
||||||
_order(encodeOrder(Application::getInstance()->getDisplayViewFrustum()->getDirection())),
|
_order(encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())),
|
||||||
_containmentDepth(INT_MAX) {
|
_containmentDepth(INT_MAX) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,8 +66,6 @@ Avatar::Avatar() :
|
||||||
_leanScale(0.5f),
|
_leanScale(0.5f),
|
||||||
_scale(1.0f),
|
_scale(1.0f),
|
||||||
_worldUpDirection(DEFAULT_UP_DIRECTION),
|
_worldUpDirection(DEFAULT_UP_DIRECTION),
|
||||||
_mouseRayOrigin(0.0f, 0.0f, 0.0f),
|
|
||||||
_mouseRayDirection(0.0f, 0.0f, 0.0f),
|
|
||||||
_moving(false),
|
_moving(false),
|
||||||
_collisionGroups(0),
|
_collisionGroups(0),
|
||||||
_initialized(false),
|
_initialized(false),
|
||||||
|
@ -250,11 +248,6 @@ void Avatar::measureMotionDerivatives(float deltaTime) {
|
||||||
_lastOrientation = getOrientation();
|
_lastOrientation = getOrientation();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction) {
|
|
||||||
_mouseRayOrigin = origin;
|
|
||||||
_mouseRayDirection = direction;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum TextRendererType {
|
enum TextRendererType {
|
||||||
CHAT,
|
CHAT,
|
||||||
DISPLAYNAME
|
DISPLAYNAME
|
||||||
|
|
|
@ -85,7 +85,6 @@ public:
|
||||||
|
|
||||||
//setters
|
//setters
|
||||||
void setDisplayingLookatVectors(bool displayingLookatVectors) { getHead()->setRenderLookatVectors(displayingLookatVectors); }
|
void setDisplayingLookatVectors(bool displayingLookatVectors) { getHead()->setRenderLookatVectors(displayingLookatVectors); }
|
||||||
void setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction);
|
|
||||||
void setIsLookAtTarget(const bool isLookAtTarget) { _isLookAtTarget = isLookAtTarget; }
|
void setIsLookAtTarget(const bool isLookAtTarget) { _isLookAtTarget = isLookAtTarget; }
|
||||||
bool getIsLookAtTarget() const { return _isLookAtTarget; }
|
bool getIsLookAtTarget() const { return _isLookAtTarget; }
|
||||||
//getters
|
//getters
|
||||||
|
@ -213,8 +212,6 @@ protected:
|
||||||
float _leanScale;
|
float _leanScale;
|
||||||
float _scale;
|
float _scale;
|
||||||
glm::vec3 _worldUpDirection;
|
glm::vec3 _worldUpDirection;
|
||||||
glm::vec3 _mouseRayOrigin;
|
|
||||||
glm::vec3 _mouseRayDirection;
|
|
||||||
float _stringLength;
|
float _stringLength;
|
||||||
bool _moving; ///< set when position is changing
|
bool _moving; ///< set when position is changing
|
||||||
|
|
||||||
|
|
|
@ -68,10 +68,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
||||||
PerformanceWarning warn(showWarnings, "Application::updateAvatars()");
|
PerformanceWarning warn(showWarnings, "Application::updateAvatars()");
|
||||||
|
|
||||||
PerformanceTimer perfTimer("otherAvatars");
|
PerformanceTimer perfTimer("otherAvatars");
|
||||||
Application* applicationInstance = Application::getInstance();
|
|
||||||
glm::vec3 mouseOrigin = applicationInstance->getMouseRayOrigin();
|
|
||||||
glm::vec3 mouseDirection = applicationInstance->getMouseRayDirection();
|
|
||||||
|
|
||||||
// simulate avatars
|
// simulate avatars
|
||||||
AvatarHash::iterator avatarIterator = _avatarHash.begin();
|
AvatarHash::iterator avatarIterator = _avatarHash.begin();
|
||||||
while (avatarIterator != _avatarHash.end()) {
|
while (avatarIterator != _avatarHash.end()) {
|
||||||
|
@ -87,7 +84,6 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
||||||
if (!shouldKillAvatar(sharedAvatar)) {
|
if (!shouldKillAvatar(sharedAvatar)) {
|
||||||
// this avatar's mixer is still around, go ahead and simulate it
|
// this avatar's mixer is still around, go ahead and simulate it
|
||||||
avatar->simulate(deltaTime);
|
avatar->simulate(deltaTime);
|
||||||
avatar->setMouseRay(mouseOrigin, mouseDirection);
|
|
||||||
++avatarIterator;
|
++avatarIterator;
|
||||||
} else {
|
} else {
|
||||||
// the mixer that owned this avatar is gone, give it to the vector of fades and kill it
|
// the mixer that owned this avatar is gone, give it to the vector of fades and kill it
|
||||||
|
|
|
@ -67,7 +67,6 @@ const int SCRIPTED_MOTOR_WORLD_FRAME = 2;
|
||||||
|
|
||||||
MyAvatar::MyAvatar() :
|
MyAvatar::MyAvatar() :
|
||||||
Avatar(),
|
Avatar(),
|
||||||
_mousePressed(false),
|
|
||||||
_turningKeyPressTime(0.0f),
|
_turningKeyPressTime(0.0f),
|
||||||
_gravity(0.0f, 0.0f, 0.0f),
|
_gravity(0.0f, 0.0f, 0.0f),
|
||||||
_distanceToNearestAvatar(std::numeric_limits<float>::max()),
|
_distanceToNearestAvatar(std::numeric_limits<float>::max()),
|
||||||
|
|
|
@ -55,15 +55,12 @@ public:
|
||||||
void renderHeadMouse(int screenWidth, int screenHeight) const;
|
void renderHeadMouse(int screenWidth, int screenHeight) const;
|
||||||
|
|
||||||
// setters
|
// setters
|
||||||
void setMousePressed(bool mousePressed) { _mousePressed = mousePressed; }
|
|
||||||
void setLeanScale(float scale) { _leanScale = scale; }
|
void setLeanScale(float scale) { _leanScale = scale; }
|
||||||
void setLocalGravity(glm::vec3 gravity);
|
void setLocalGravity(glm::vec3 gravity);
|
||||||
void setShouldRenderLocally(bool shouldRender) { _shouldRender = shouldRender; }
|
void setShouldRenderLocally(bool shouldRender) { _shouldRender = shouldRender; }
|
||||||
|
|
||||||
// getters
|
// getters
|
||||||
float getLeanScale() const { return _leanScale; }
|
float getLeanScale() const { return _leanScale; }
|
||||||
const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; }
|
|
||||||
const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; }
|
|
||||||
glm::vec3 getGravity() const { return _gravity; }
|
glm::vec3 getGravity() const { return _gravity; }
|
||||||
glm::vec3 getDefaultEyePosition() const;
|
glm::vec3 getDefaultEyePosition() const;
|
||||||
bool getShouldRenderLocally() const { return _shouldRender; }
|
bool getShouldRenderLocally() const { return _shouldRender; }
|
||||||
|
@ -203,7 +200,6 @@ protected:
|
||||||
virtual void renderAttachments(RenderMode renderMode);
|
virtual void renderAttachments(RenderMode renderMode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _mousePressed;
|
|
||||||
float _turningKeyPressTime;
|
float _turningKeyPressTime;
|
||||||
glm::vec3 _gravity;
|
glm::vec3 _gravity;
|
||||||
float _distanceToNearestAvatar; // How close is the nearest avatar?
|
float _distanceToNearestAvatar; // How close is the nearest avatar?
|
||||||
|
|
|
@ -90,3 +90,14 @@ void RenderableLightEntityItem::render(RenderArgs* args) {
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool RenderableLightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
|
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
|
||||||
|
void** intersectedObject) const {
|
||||||
|
|
||||||
|
// TODO: this isn't really correct because we don't know if we actually live in the main tree of the applications's
|
||||||
|
// EntityTreeRenderer. But we probably do. Technically we could be on the clipboard and someone might be trying to
|
||||||
|
// use the ray intersection API there. Anyway... if you ever try to do ray intersection testing off of trees other
|
||||||
|
// than the main tree of the main entity renderer, then you'll need to fix this mechanism.
|
||||||
|
return Application::getInstance()->getEntities()->getTree()->getLightsArePickable();
|
||||||
|
}
|
||||||
|
|
|
@ -34,6 +34,10 @@ public:
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual void render(RenderArgs* args);
|
virtual void render(RenderArgs* args);
|
||||||
|
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) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -232,8 +232,8 @@ void DeferredLightingEffect::render() {
|
||||||
// enlarge the scales slightly to account for tesselation
|
// enlarge the scales slightly to account for tesselation
|
||||||
const float SCALE_EXPANSION = 0.05f;
|
const float SCALE_EXPANSION = 0.05f;
|
||||||
|
|
||||||
const glm::vec3& eyePoint = Application::getInstance()->getDisplayViewFrustum()->getPosition();
|
const glm::vec3& eyePoint = Application::getInstance()->getViewFrustum()->getPosition();
|
||||||
float nearRadius = glm::distance(eyePoint, Application::getInstance()->getDisplayViewFrustum()->getNearTopLeft());
|
float nearRadius = glm::distance(eyePoint, Application::getInstance()->getViewFrustum()->getNearTopLeft());
|
||||||
|
|
||||||
if (!_pointLights.isEmpty()) {
|
if (!_pointLights.isEmpty()) {
|
||||||
_pointLight.bind();
|
_pointLight.bind();
|
||||||
|
|
|
@ -134,6 +134,11 @@ public:
|
||||||
virtual SimulationState computeSimulationState() const;
|
virtual SimulationState computeSimulationState() const;
|
||||||
|
|
||||||
virtual void debugDump() const;
|
virtual void debugDump() const;
|
||||||
|
|
||||||
|
virtual bool supportsDetailedRayIntersection() const { return false; }
|
||||||
|
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
|
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
|
||||||
|
void** intersectedObject) const { return true; }
|
||||||
|
|
||||||
// attributes applicable to all entity types
|
// attributes applicable to all entity types
|
||||||
EntityTypes::EntityType getType() const { return _type; }
|
EntityTypes::EntityType getType() const { return _type; }
|
||||||
|
|
|
@ -221,6 +221,19 @@ RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionWorke
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EntityScriptingInterface::setLightsArePickable(bool value) {
|
||||||
|
if (_entityTree) {
|
||||||
|
_entityTree->setLightsArePickable(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EntityScriptingInterface::getLightsArePickable() const {
|
||||||
|
if (_entityTree) {
|
||||||
|
return _entityTree->getLightsArePickable();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
RayToEntityIntersectionResult::RayToEntityIntersectionResult() :
|
RayToEntityIntersectionResult::RayToEntityIntersectionResult() :
|
||||||
intersects(false),
|
intersects(false),
|
||||||
|
|
|
@ -96,6 +96,8 @@ public slots:
|
||||||
/// order to return an accurate result
|
/// order to return an accurate result
|
||||||
Q_INVOKABLE RayToEntityIntersectionResult findRayIntersectionBlocking(const PickRay& ray);
|
Q_INVOKABLE RayToEntityIntersectionResult findRayIntersectionBlocking(const PickRay& ray);
|
||||||
|
|
||||||
|
Q_INVOKABLE void setLightsArePickable(bool value);
|
||||||
|
Q_INVOKABLE bool getLightsArePickable() const;
|
||||||
|
|
||||||
Q_INVOKABLE void dumpTree() const;
|
Q_INVOKABLE void dumpTree() const;
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
EntityTree::EntityTree(bool shouldReaverage) : Octree(shouldReaverage), _simulation(NULL) {
|
EntityTree::EntityTree(bool shouldReaverage) : Octree(shouldReaverage), _simulation(NULL) {
|
||||||
_rootElement = createNewElement();
|
_rootElement = createNewElement();
|
||||||
|
_lightsArePickable = true; // assume they are by default
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityTree::~EntityTree() {
|
EntityTree::~EntityTree() {
|
||||||
|
|
|
@ -144,6 +144,8 @@ public:
|
||||||
|
|
||||||
void emitEntityScriptChanging(const EntityItemID& entityItemID);
|
void emitEntityScriptChanging(const EntityItemID& entityItemID);
|
||||||
|
|
||||||
|
bool getLightsArePickable() const { return _lightsArePickable; }
|
||||||
|
void setLightsArePickable(bool value) { _lightsArePickable = value; }
|
||||||
void setSimulation(EntitySimulation* simulation);
|
void setSimulation(EntitySimulation* simulation);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -169,6 +171,8 @@ private:
|
||||||
EntityItemFBXService* _fbxService;
|
EntityItemFBXService* _fbxService;
|
||||||
|
|
||||||
QHash<EntityItemID, EntityTreeElement*> _entityToElementMap;
|
QHash<EntityItemID, EntityTreeElement*> _entityToElementMap;
|
||||||
|
|
||||||
|
bool _lightsArePickable;
|
||||||
EntitySimulation* _simulation;
|
EntitySimulation* _simulation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -511,10 +511,28 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con
|
||||||
// and testing intersection there.
|
// and testing intersection there.
|
||||||
if (entityFrameBox.findRayIntersection(entityFrameOrigin, entityFrameDirection, localDistance, localFace)) {
|
if (entityFrameBox.findRayIntersection(entityFrameOrigin, entityFrameDirection, localDistance, localFace)) {
|
||||||
if (localDistance < distance) {
|
if (localDistance < distance) {
|
||||||
distance = localDistance;
|
// now ask the entity if we actually intersect
|
||||||
face = localFace;
|
if (entity->supportsDetailedRayIntersection()) {
|
||||||
*intersectedObject = (void*)entity;
|
|
||||||
somethingIntersected = true;
|
if (entity->findDetailedRayIntersection(origin, direction, keepSearching, element, localDistance,
|
||||||
|
localFace, intersectedObject)) {
|
||||||
|
|
||||||
|
if (localDistance < distance) {
|
||||||
|
distance = localDistance;
|
||||||
|
face = localFace;
|
||||||
|
*intersectedObject = (void*)entity;
|
||||||
|
somethingIntersected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// if the entity type doesn't support a detailed intersection, then just return the non-AABox results
|
||||||
|
if (localDistance < distance) {
|
||||||
|
distance = localDistance;
|
||||||
|
face = localFace;
|
||||||
|
*intersectedObject = (void*)entity;
|
||||||
|
somethingIntersected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,3 +93,26 @@ void SphereEntityItem::recalculateCollisionShape() {
|
||||||
float largestDiameter = glm::max(dimensionsInMeters.x, dimensionsInMeters.y, dimensionsInMeters.z);
|
float largestDiameter = glm::max(dimensionsInMeters.x, dimensionsInMeters.y, dimensionsInMeters.z);
|
||||||
_sphereShape.setRadius(largestDiameter / 2.0f);
|
_sphereShape.setRadius(largestDiameter / 2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
|
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
|
||||||
|
void** intersectedObject) const {
|
||||||
|
|
||||||
|
// NOTE: origin and direction are in tree units. But our _sphereShape is in meters, so we need to
|
||||||
|
// do a little math to make these match each other.
|
||||||
|
RayIntersectionInfo rayInfo;
|
||||||
|
rayInfo._rayStart = origin * (float)TREE_SCALE;
|
||||||
|
rayInfo._rayDirection = direction;
|
||||||
|
|
||||||
|
// TODO: Note this is really doing ray intersections against a sphere, which is fine except in cases
|
||||||
|
// where our dimensions actually make us an ellipsoid. But we'll live with this for now until we
|
||||||
|
// get a more full fledged physics library
|
||||||
|
if (_sphereShape.findRayIntersection(rayInfo)) {
|
||||||
|
distance = rayInfo._hitDistance / (float)TREE_SCALE;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,11 @@ public:
|
||||||
// TODO: implement proper contains for 3D ellipsoid
|
// TODO: implement proper contains for 3D ellipsoid
|
||||||
//virtual bool contains(const glm::vec3& point) const;
|
//virtual bool contains(const glm::vec3& point) const;
|
||||||
|
|
||||||
|
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) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void recalculateCollisionShape();
|
virtual void recalculateCollisionShape();
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,12 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
|
#include <glm/gtx/transform.hpp>
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include <ByteCountCoding.h>
|
#include <ByteCountCoding.h>
|
||||||
|
#include <PlaneShape.h>
|
||||||
|
|
||||||
#include "EntityTree.h"
|
#include "EntityTree.h"
|
||||||
#include "EntityTreeElement.h"
|
#include "EntityTreeElement.h"
|
||||||
|
@ -110,4 +113,48 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits
|
||||||
APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, appendValue, getLineHeight());
|
APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, appendValue, getLineHeight());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_TEXT_COLOR, appendColor, getTextColor());
|
APPEND_ENTITY_PROPERTY(PROP_TEXT_COLOR, appendColor, getTextColor());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, appendColor, getBackgroundColor());
|
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, appendColor, getBackgroundColor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
|
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
|
||||||
|
void** intersectedObject) const {
|
||||||
|
|
||||||
|
RayIntersectionInfo rayInfo;
|
||||||
|
rayInfo._rayStart = origin;
|
||||||
|
rayInfo._rayDirection = direction;
|
||||||
|
rayInfo._rayLength = std::numeric_limits<float>::max();
|
||||||
|
|
||||||
|
PlaneShape plane;
|
||||||
|
|
||||||
|
const glm::vec3 UNROTATED_NORMAL(0.0f, 0.0f, -1.0f);
|
||||||
|
glm::vec3 normal = _rotation * UNROTATED_NORMAL;
|
||||||
|
plane.setNormal(normal);
|
||||||
|
plane.setPoint(_position); // the position is definitely a point on our plane
|
||||||
|
|
||||||
|
bool intersects = plane.findRayIntersection(rayInfo);
|
||||||
|
|
||||||
|
if (intersects) {
|
||||||
|
glm::vec3 hitAt = origin + (direction * rayInfo._hitDistance);
|
||||||
|
// now we know the point the ray hit our plane
|
||||||
|
|
||||||
|
glm::mat4 rotation = glm::mat4_cast(getRotation());
|
||||||
|
glm::mat4 translation = glm::translate(getPosition());
|
||||||
|
glm::mat4 entityToWorldMatrix = translation * rotation;
|
||||||
|
glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix);
|
||||||
|
|
||||||
|
glm::vec3 dimensions = getDimensions();
|
||||||
|
glm::vec3 registrationPoint = getRegistrationPoint();
|
||||||
|
glm::vec3 corner = -(dimensions * registrationPoint);
|
||||||
|
AABox entityFrameBox(corner, dimensions);
|
||||||
|
|
||||||
|
glm::vec3 entityFrameHitAt = glm::vec3(worldToEntityMatrix * glm::vec4(hitAt, 1.0f));
|
||||||
|
|
||||||
|
intersects = entityFrameBox.contains(entityFrameHitAt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intersects) {
|
||||||
|
distance = rayInfo._hitDistance;
|
||||||
|
}
|
||||||
|
return intersects;
|
||||||
|
}
|
||||||
|
|
|
@ -41,6 +41,11 @@ public:
|
||||||
ReadBitstreamToTreeParams& args,
|
ReadBitstreamToTreeParams& args,
|
||||||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
|
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
|
||||||
|
|
||||||
|
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) const;
|
||||||
|
|
||||||
static const QString DEFAULT_TEXT;
|
static const QString DEFAULT_TEXT;
|
||||||
void setText(const QString& value) { _text = value; }
|
void setText(const QString& value) { _text = value; }
|
||||||
const QString& getText() const { return _text; }
|
const QString& getText() const { return _text; }
|
||||||
|
|
Loading…
Reference in a new issue