mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 06:44:06 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into modelRayPick
This commit is contained in:
commit
005ce8432e
8 changed files with 2207 additions and 5990 deletions
|
@ -16,11 +16,15 @@ var AXIS_STRAFE = Joysticks.AXIS_LEFT_X;
|
|||
var AXIS_FORWARD = Joysticks.AXIS_LEFT_Y;
|
||||
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_FLY_UP = Joysticks.BUTTON_RIGHT_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_BACKWARD = Joysticks.BUTTON_DPAD_DOWN;
|
||||
|
@ -31,7 +35,8 @@ var BUTTON_WARP_RIGHT = Joysticks.BUTTON_DPAD_RIGHT;
|
|||
var WARP_DISTANCE = 1;
|
||||
|
||||
// Walk speed in m/s
|
||||
var MOVE_SPEED = 2;
|
||||
var MOVE_SPEED = 0.5;
|
||||
var MOVE_SPRINT_SPEED = 2;
|
||||
|
||||
// Amount to rotate in radians
|
||||
var ROTATE_INCREMENT = Math.PI / 8;
|
||||
|
@ -46,9 +51,14 @@ var WARP_PICK_MAX_DISTANCE = 100;
|
|||
var flyDownButtonState = 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
|
||||
// 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 sprintButtonState = false;
|
||||
|
||||
var warpActive = false;
|
||||
var warpPosition = { x: 0, y: 0, z: 0 };
|
||||
|
@ -173,6 +183,18 @@ function reportButtonValue(button, newValue, oldValue) {
|
|||
MyAvatar.orientation = Quat.multiply(
|
||||
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) {
|
||||
var direction = null;
|
||||
|
||||
|
@ -209,9 +231,10 @@ function update(dt) {
|
|||
var move = copyVec3(moveDirection);
|
||||
move.y = 0;
|
||||
if (Vec3.length(move) > 0) {
|
||||
speed = sprintButtonState ? MOVE_SPRINT_SPEED : MOVE_SPEED;
|
||||
velocity = Vec3.multiplyQbyV(Camera.getOrientation(), move);
|
||||
velocity.y = 0;
|
||||
velocity = Vec3.multiply(Vec3.normalize(velocity), MOVE_SPEED);
|
||||
velocity = Vec3.multiply(Vec3.normalize(velocity), speed);
|
||||
}
|
||||
|
||||
if (moveDirection.y != 0) {
|
||||
|
|
|
@ -33,10 +33,12 @@ SelectionManager = (function() {
|
|||
that.localRotation = Quat.fromPitchYawRollDegrees(0, 0, 0);
|
||||
that.localPosition = { x: 0, y: 0, z: 0 };
|
||||
that.localDimensions = { x: 0, y: 0, z: 0 };
|
||||
that.localRegistrationPoint = { x: 0.5, y: 0.5, z: 0.5 };
|
||||
|
||||
that.worldRotation = Quat.fromPitchYawRollDegrees(0, 0, 0);
|
||||
that.worldPosition = { x: 0, y: 0, z: 0 };
|
||||
that.worldDimensions = { x: 0, y: 0, z: 0 };
|
||||
that.worldRegistrationPoint = { x: 0.5, y: 0.5, z: 0.5 };
|
||||
that.centerPosition = { x: 0, y: 0, z: 0 };
|
||||
|
||||
that.saveProperties = function() {
|
||||
|
@ -153,6 +155,7 @@ SelectionManager = (function() {
|
|||
that.localDimensions = properties.dimensions;
|
||||
that.localPosition = properties.position;
|
||||
that.localRotation = properties.rotation;
|
||||
that.localRegistrationPoint = properties.registrationPoint;
|
||||
|
||||
that.worldDimensions = properties.boundingBox.dimensions;
|
||||
that.worldPosition = properties.boundingBox.center;
|
||||
|
@ -215,6 +218,17 @@ function normalizeDegrees(degrees) {
|
|||
return degrees;
|
||||
}
|
||||
|
||||
// Return the enter position of an entity relative to it's registrationPoint
|
||||
// A registration point of (0.5, 0.5, 0.5) will have an offset of (0, 0, 0)
|
||||
// A registration point of (1.0, 1.0, 1.0) will have an offset of (-dimensions.x / 2, -dimensions.y / 2, -dimensions.z / 2)
|
||||
function getRelativeCenterPosition(dimensions, registrationPoint) {
|
||||
return {
|
||||
x: -dimensions.x * (registrationPoint.x - 0.5),
|
||||
y: -dimensions.y * (registrationPoint.y - 0.5),
|
||||
z: -dimensions.z * (registrationPoint.z - 0.5),
|
||||
}
|
||||
}
|
||||
|
||||
SelectionDisplay = (function () {
|
||||
var that = {};
|
||||
|
||||
|
@ -982,26 +996,36 @@ SelectionDisplay = (function () {
|
|||
that.updateRotationHandles();
|
||||
that.highlightSelectable();
|
||||
|
||||
var rotation, dimensions, position;
|
||||
var rotation, dimensions, position, registrationPoint;
|
||||
|
||||
if (spaceMode == SPACE_LOCAL) {
|
||||
rotation = SelectionManager.localRotation;
|
||||
dimensions = SelectionManager.localDimensions;
|
||||
position = SelectionManager.localPosition;
|
||||
registrationPoint = SelectionManager.localRegistrationPoint;
|
||||
} else {
|
||||
rotation = Quat.fromPitchYawRollDegrees(0, 0, 0);
|
||||
dimensions = SelectionManager.worldDimensions;
|
||||
position = SelectionManager.worldPosition;
|
||||
registrationPoint = SelectionManager.worldRegistrationPoint;
|
||||
}
|
||||
|
||||
var halfDimensions = Vec3.multiply(0.5, dimensions);
|
||||
var registrationPointDimensions = {
|
||||
x: dimensions.x * registrationPoint.x,
|
||||
y: dimensions.y * registrationPoint.y,
|
||||
z: dimensions.z * registrationPoint.z,
|
||||
};
|
||||
|
||||
var left = -halfDimensions.x;
|
||||
var right = halfDimensions.x;
|
||||
var top = halfDimensions.y;
|
||||
var bottom = -halfDimensions.y;
|
||||
var front = far = halfDimensions.z;
|
||||
var near = -halfDimensions.z;
|
||||
// Center of entity, relative to registration point
|
||||
center = getRelativeCenterPosition(dimensions, registrationPoint);
|
||||
|
||||
// Distances in world coordinates relative to the registration point
|
||||
var left = -registrationPointDimensions.x;
|
||||
var right = dimensions.x - registrationPointDimensions.x;
|
||||
var bottom = -registrationPointDimensions.y;
|
||||
var top = dimensions.y - registrationPointDimensions.y;
|
||||
var near = -registrationPointDimensions.z;
|
||||
var front = far = dimensions.z - registrationPointDimensions.z;
|
||||
|
||||
var worldTop = SelectionManager.worldDimensions.y / 2;
|
||||
|
||||
|
@ -1014,25 +1038,25 @@ SelectionDisplay = (function () {
|
|||
var LTF = { x: left, y: top, z: far };
|
||||
var RTF = { x: right, y: top, z: far };
|
||||
|
||||
var TOP = { x: 0, y: top, z: 0 };
|
||||
var BOTTOM = { x: 0, y: bottom, z: 0 };
|
||||
var LEFT = { x: left, y: 0, z: 0 };
|
||||
var RIGHT = { x: right, y: 0, z: 0 };
|
||||
var NEAR = { x: 0, y: 0, z: near };
|
||||
var FAR = { x: 0, y: 0, z: far };
|
||||
var TOP = { x: center.x, y: top, z: center.z };
|
||||
var BOTTOM = { x: center.x, y: bottom, z: center.z };
|
||||
var LEFT = { x: left, y: center.y, z: center.z };
|
||||
var RIGHT = { x: right, y: center.y, z: center.z };
|
||||
var NEAR = { x: center.x, y: center.y, z: near };
|
||||
var FAR = { x: center.x, y: center.y, z: far };
|
||||
|
||||
var EdgeTR = { x: right, y: top, z: 0 };
|
||||
var EdgeTL = { x: left, y: top, z: 0 };
|
||||
var EdgeTF = { x: 0, y: top, z: front };
|
||||
var EdgeTN = { x: 0, y: top, z: near };
|
||||
var EdgeBR = { x: right, y: bottom, z: 0 };
|
||||
var EdgeBL = { x: left, y: bottom, z: 0 };
|
||||
var EdgeBF = { x: 0, y: bottom, z: front };
|
||||
var EdgeBN = { x: 0, y: bottom, z: near };
|
||||
var EdgeNR = { x: right, y: 0, z: near };
|
||||
var EdgeNL = { x: left, y: 0, z: near };
|
||||
var EdgeFR = { x: right, y: 0, z: front };
|
||||
var EdgeFL = { x: left, y: 0, z: front };
|
||||
var EdgeTR = { x: right, y: top, z: center.z };
|
||||
var EdgeTL = { x: left, y: top, z: center.z };
|
||||
var EdgeTF = { x: center.x, y: top, z: front };
|
||||
var EdgeTN = { x: center.x, y: top, z: near };
|
||||
var EdgeBR = { x: right, y: bottom, z: center.z };
|
||||
var EdgeBL = { x: left, y: bottom, z: center.z };
|
||||
var EdgeBF = { x: center.x, y: bottom, z: front };
|
||||
var EdgeBN = { x: center.x, y: bottom, z: near };
|
||||
var EdgeNR = { x: right, y: center.y, z: near };
|
||||
var EdgeNL = { x: left, y: center.y, z: near };
|
||||
var EdgeFR = { x: right, y: center.y, z: front };
|
||||
var EdgeFL = { x: left, y: center.y, z: front };
|
||||
|
||||
LBN = Vec3.multiplyQbyV(rotation, LBN);
|
||||
RBN = Vec3.multiplyQbyV(rotation, RBN);
|
||||
|
@ -1111,8 +1135,10 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(grabberNEAR, { visible: extendedStretchHandlesVisible, rotation: rotation, position: NEAR });
|
||||
Overlays.editOverlay(grabberFAR, { visible: extendedStretchHandlesVisible, rotation: rotation, position: FAR });
|
||||
|
||||
var boxPosition = Vec3.multiplyQbyV(rotation, center);
|
||||
boxPosition = Vec3.sum(position, boxPosition);
|
||||
Overlays.editOverlay(selectionBox, {
|
||||
position: position,
|
||||
position: boxPosition,
|
||||
dimensions: dimensions,
|
||||
rotation: rotation,
|
||||
visible: !(mode == "ROTATE_YAW" || mode == "ROTATE_PITCH" || mode == "ROTATE_ROLL"),
|
||||
|
@ -1140,8 +1166,17 @@ SelectionDisplay = (function () {
|
|||
if (selectionManager.selections.length > 1) {
|
||||
for (; i < selectionManager.selections.length; i++) {
|
||||
var properties = Entities.getEntityProperties(selectionManager.selections[i]);
|
||||
|
||||
// Adjust overlay position to take registrationPoint into account
|
||||
// centeredRP = registrationPoint with range [-0.5, 0.5]
|
||||
var centeredRP = Vec3.subtract(properties.registrationPoint, { x: 0.5, y: 0.5, z: 0.5 });
|
||||
var offset = vec3Mult(properties.dimensions, centeredRP);
|
||||
offset = Vec3.multiply(-1, offset);
|
||||
offset = Vec3.multiplyQbyV(properties.rotation, offset);
|
||||
var boxPosition = Vec3.sum(properties.position, offset);
|
||||
|
||||
Overlays.editOverlay(selectionBoxes[i], {
|
||||
position: properties.position,
|
||||
position: boxPosition,
|
||||
rotation: properties.rotation,
|
||||
dimensions: properties.dimensions,
|
||||
visible: true,
|
||||
|
@ -1400,6 +1435,8 @@ SelectionDisplay = (function () {
|
|||
var initialDimensions = null;
|
||||
var initialIntersection = null;
|
||||
var initialProperties = null;
|
||||
var registrationPoint = null;
|
||||
var deltaPivot = null;
|
||||
var pickRayPosition = null;
|
||||
var rotation = null;
|
||||
|
||||
|
@ -1412,18 +1449,29 @@ SelectionDisplay = (function () {
|
|||
rotation = SelectionManager.localRotation;
|
||||
initialPosition = SelectionManager.localPosition;
|
||||
initialDimensions = SelectionManager.localDimensions;
|
||||
registrationPoint = SelectionManager.localRegistrationPoint;
|
||||
} else {
|
||||
rotation = SelectionManager.worldRotation;
|
||||
initialPosition = SelectionManager.worldPosition;
|
||||
initialDimensions = SelectionManager.worldDimensions;
|
||||
registrationPoint = SelectionManager.worldRegistrationPoint;
|
||||
}
|
||||
|
||||
var scaledOffset = {
|
||||
x: initialDimensions.x * offset.x * 0.5,
|
||||
y: initialDimensions.y * offset.y * 0.5,
|
||||
z: initialDimensions.z * offset.z * 0.5,
|
||||
};
|
||||
pickRayPosition = Vec3.sum(initialPosition, Vec3.multiplyQbyV(rotation, scaledOffset));
|
||||
// Modify range of registrationPoint to be [-0.5, 0.5]
|
||||
var centeredRP = Vec3.subtract(registrationPoint, { x: 0.5, y: 0.5, z: 0.5 });
|
||||
|
||||
// Scale pivot to be in the same range as registrationPoint
|
||||
var scaledPivot = Vec3.multiply(0.5, pivot)
|
||||
deltaPivot = Vec3.subtract(centeredRP, scaledPivot);
|
||||
|
||||
var scaledOffset = Vec3.multiply(0.5, offset);
|
||||
|
||||
// Offset from the registration point
|
||||
offsetRP = Vec3.subtract(scaledOffset, centeredRP);
|
||||
|
||||
// Scaled offset in world coordinates
|
||||
var scaledOffsetWorld = vec3Mult(initialDimensions, offsetRP);
|
||||
pickRayPosition = Vec3.sum(initialPosition, Vec3.multiplyQbyV(rotation, scaledOffsetWorld));
|
||||
|
||||
if (numDimensions == 1 && mask.x) {
|
||||
var start = Vec3.multiplyQbyV(rotation, { x: -10000, y: 0, z: 0 });
|
||||
|
@ -1550,8 +1598,7 @@ SelectionDisplay = (function () {
|
|||
newDimensions.y = Math.max(newDimensions.y, MINIMUM_DIMENSION);
|
||||
newDimensions.z = Math.max(newDimensions.z, MINIMUM_DIMENSION);
|
||||
|
||||
var p = Vec3.multiply(0.5, pivot);
|
||||
var changeInPosition = Vec3.multiplyQbyV(rotation, vec3Mult(p, changeInDimensions));
|
||||
var changeInPosition = Vec3.multiplyQbyV(rotation, vec3Mult(deltaPivot, changeInDimensions));
|
||||
var newPosition = Vec3.sum(initialPosition, changeInPosition);
|
||||
|
||||
for (var i = 0; i < SelectionManager.selections.length; i++) {
|
||||
|
@ -1589,20 +1636,19 @@ SelectionDisplay = (function () {
|
|||
|
||||
function addStretchTool(overlay, mode, pivot, direction, offset) {
|
||||
if (!pivot) {
|
||||
pivot = Vec3.multiply(-1, direction);
|
||||
pivot.y = direction.y;
|
||||
pivot = direction;
|
||||
}
|
||||
var tool = makeStretchTool(mode, direction, pivot, offset);
|
||||
|
||||
addGrabberTool(overlay, tool);
|
||||
}
|
||||
|
||||
addStretchTool(grabberNEAR, "STRETCH_NEAR", { x: 0, y: 0, z: -1 }, { x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: -1 });
|
||||
addStretchTool(grabberFAR, "STRETCH_FAR", { x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: -1 }, { x: 0, y: 0, z: 1 });
|
||||
addStretchTool(grabberTOP, "STRETCH_TOP", { x: 0, y: 1, z: 0 }, { x: 0, y: -1, z: 0 }, { x: 0, y: 1, z: 0 });
|
||||
addStretchTool(grabberBOTTOM, "STRETCH_BOTTOM", { x: 0, y: -1, z: 0 }, { x: 0, y: 1, z: 0 }, { x: 0, y: -1, z: 0 });
|
||||
addStretchTool(grabberRIGHT, "STRETCH_RIGHT", { x: 1, y: 0, z: 0 }, { x: -1, y: 0, z: 0 }, { x: 1, y: 0, z: 0 });
|
||||
addStretchTool(grabberLEFT, "STRETCH_LEFT", { x: -1, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }, { x: -1, y: 0, z: 0 });
|
||||
addStretchTool(grabberNEAR, "STRETCH_NEAR", { x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: -1 });
|
||||
addStretchTool(grabberFAR, "STRETCH_FAR", { x: 0, y: 0, z: -1 }, { x: 0, y: 0, z: -1 }, { x: 0, y: 0, z: 1 });
|
||||
addStretchTool(grabberTOP, "STRETCH_TOP", { x: 0, y: -1, z: 0 }, { x: 0, y: -1, z: 0 }, { x: 0, y: 1, z: 0 });
|
||||
addStretchTool(grabberBOTTOM, "STRETCH_BOTTOM", { x: 0, y: 1, z: 0 }, { x: 0, y: 1, z: 0 }, { x: 0, y: -1, z: 0 });
|
||||
addStretchTool(grabberRIGHT, "STRETCH_RIGHT", { x: -1, y: 0, z: 0 }, { x: -1, y: 0, z: 0 }, { x: 1, y: 0, z: 0 });
|
||||
addStretchTool(grabberLEFT, "STRETCH_LEFT", { x: 1, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }, { x: -1, y: 0, z: 0 });
|
||||
|
||||
addStretchTool(grabberLBN, "STRETCH_LBN", null, {x: 1, y: 0, z: 1}, { x: -1, y: -1, z: -1 });
|
||||
addStretchTool(grabberRBN, "STRETCH_RBN", null, {x: -1, y: 0, z: 1}, { x: 1, y: -1, z: -1 });
|
||||
|
@ -1740,17 +1786,27 @@ SelectionDisplay = (function () {
|
|||
}
|
||||
|
||||
var yawChange = Quat.fromVec3Degrees({ x: 0, y: angleFromZero, z: 0 });
|
||||
|
||||
// Entities should only reposition if we are rotating multiple selections around
|
||||
// the selections center point. Otherwise, the rotation will be around the entities
|
||||
// registration point which does not need repositioning.
|
||||
var reposition = SelectionManager.selections.length > 1;
|
||||
for (var i = 0; i < SelectionManager.selections.length; i++) {
|
||||
var entityID = SelectionManager.selections[i];
|
||||
var properties = Entities.getEntityProperties(entityID);
|
||||
var initialProperties = SelectionManager.savedProperties[entityID.id];
|
||||
var dPos = Vec3.subtract(initialProperties.position, initialPosition);
|
||||
dPos = Vec3.multiplyQbyV(yawChange, dPos);
|
||||
|
||||
Entities.editEntity(entityID, {
|
||||
position: Vec3.sum(initialPosition, dPos),
|
||||
var newProperties = {
|
||||
rotation: Quat.multiply(yawChange, initialProperties.rotation),
|
||||
});
|
||||
};
|
||||
|
||||
if (reposition) {
|
||||
var dPos = Vec3.subtract(initialProperties.position, initialPosition);
|
||||
dPos = Vec3.multiplyQbyV(yawChange, dPos);
|
||||
newProperties.position = Vec3.sum(initialPosition, dPos);
|
||||
}
|
||||
|
||||
Entities.editEntity(entityID, newProperties);
|
||||
}
|
||||
|
||||
updateRotationDegreesOverlay(angleFromZero, yawHandleRotation, yawCenter);
|
||||
|
|
|
@ -90,7 +90,6 @@ Grid = function(opts) {
|
|||
}
|
||||
|
||||
that.snapToSpacing = function(delta, majorOnly) {
|
||||
print('snaptogrid? ' + snapToGrid);
|
||||
if (!snapToGrid) {
|
||||
return delta;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,225 +1,277 @@
|
|||
//
|
||||
// walkFilters.js
|
||||
//
|
||||
// version 1.001
|
||||
//
|
||||
// Created by David Wooldridge, Autumn 2014
|
||||
//
|
||||
// Provides a variety of filters for use by the walk.js script v1.1
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
AveragingFilter = function(length) {
|
||||
|
||||
//this.name = name;
|
||||
this.pastValues = [];
|
||||
|
||||
for(var i = 0; i < length; i++) {
|
||||
this.pastValues.push(0);
|
||||
}
|
||||
|
||||
// single arg is the nextInputValue
|
||||
this.process = function() {
|
||||
|
||||
if (this.pastValues.length === 0 && arguments[0]) {
|
||||
return arguments[0];
|
||||
} else if (arguments[0]) {
|
||||
// apply quick and simple LP filtering
|
||||
this.pastValues.push(arguments[0]);
|
||||
this.pastValues.shift();
|
||||
var nextOutputValue = 0;
|
||||
for (var ea in this.pastValues) nextOutputValue += this.pastValues[ea];
|
||||
return nextOutputValue / this.pastValues.length;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// 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
|
||||
ButterworthFilter = function(cutOff) {
|
||||
|
||||
// cut off frequency = 5Hz
|
||||
this.gain = 20.20612010;
|
||||
this.coeffOne = -0.4775922501;
|
||||
this.coeffTwo = 1.2796324250;
|
||||
|
||||
// initialise the arrays
|
||||
this.xv = [];
|
||||
this.yv = [];
|
||||
for(var i = 0; i < 3; i++) {
|
||||
this.xv.push(0);
|
||||
this.yv.push(0);
|
||||
}
|
||||
|
||||
// process values
|
||||
this.process = function(nextInputValue) {
|
||||
|
||||
this.xv[0] = this.xv[1];
|
||||
this.xv[1] = this.xv[2];
|
||||
this.xv[2] = nextInputValue / this.gain;
|
||||
|
||||
this.yv[0] = this.yv[1];
|
||||
this.yv[1] = this.yv[2];
|
||||
this.yv[2] = (this.xv[0] + this.xv[2]) +
|
||||
2 * this.xv[1] +
|
||||
(this.coeffOne * this.yv[0]) +
|
||||
(this.coeffTwo * this.yv[1]);
|
||||
|
||||
return this.yv[2];
|
||||
};
|
||||
}; // end Butterworth filter contructor
|
||||
|
||||
// Add harmonics to a given sine wave to form square, sawtooth or triangle waves
|
||||
// Geometric wave synthesis fundamentals taken from: http://hyperphysics.phy-astr.gsu.edu/hbase/audio/geowv.html
|
||||
WaveSynth = function(waveShape, numHarmonics, smoothing) {
|
||||
|
||||
this.numHarmonics = numHarmonics;
|
||||
this.waveShape = waveShape;
|
||||
this.averagingFilter = new AveragingFilter(smoothing);
|
||||
|
||||
// NB: frequency in radians
|
||||
this.shapeWave = function(frequency) {
|
||||
|
||||
// make some shapes
|
||||
var harmonics = 0;
|
||||
var multiplier = 0;
|
||||
var iterations = this.numHarmonics * 2 + 2;
|
||||
if (this.waveShape === TRIANGLE) {
|
||||
iterations++;
|
||||
}
|
||||
|
||||
for(var n = 2; n < iterations; n++) {
|
||||
|
||||
switch(this.waveShape) {
|
||||
|
||||
case SAWTOOTH: {
|
||||
|
||||
multiplier = 1 / n;
|
||||
harmonics += multiplier * Math.sin(n * frequency);
|
||||
break;
|
||||
}
|
||||
|
||||
case TRIANGLE: {
|
||||
|
||||
if (n % 2 === 1) {
|
||||
var mulitplier = 1 / (n * n);
|
||||
// multiply (4n-1)th harmonics by -1
|
||||
if (n === 3 || n === 7 || n === 11 || n === 15) {
|
||||
mulitplier *= -1;
|
||||
}
|
||||
harmonics += mulitplier * Math.sin(n * frequency);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SQUARE: {
|
||||
|
||||
if (n % 2 === 1) {
|
||||
multiplier = 1 / n;
|
||||
harmonics += multiplier * Math.sin(n * frequency);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// smooth the result and return
|
||||
return this.averagingFilter.process(harmonics);
|
||||
};
|
||||
};
|
||||
|
||||
// Create a wave shape by summing pre-calcualted sinusoidal harmonics
|
||||
HarmonicsFilter = function(magnitudes, phaseAngles) {
|
||||
|
||||
this.magnitudes = magnitudes;
|
||||
this.phaseAngles = phaseAngles;
|
||||
|
||||
this.calculate = function(twoPiFT) {
|
||||
|
||||
var harmonics = 0;
|
||||
var numHarmonics = magnitudes.length;
|
||||
|
||||
for(var n = 0; n < numHarmonics; n++) {
|
||||
harmonics += this.magnitudes[n] * Math.cos(n * twoPiFT - this.phaseAngles[n]);
|
||||
}
|
||||
return harmonics;
|
||||
};
|
||||
};
|
||||
|
||||
// the main filter object literal
|
||||
filter = (function() {
|
||||
|
||||
// Bezier private functions
|
||||
function _B1(t) { return t * t * t };
|
||||
function _B2(t) { return 3 * t * t * (1 - t) };
|
||||
function _B3(t) { return 3 * t * (1 - t) * (1 - t) };
|
||||
function _B4(t) { return (1 - t) * (1 - t) * (1 - t) };
|
||||
|
||||
return {
|
||||
|
||||
// helper methods
|
||||
degToRad: function(degrees) {
|
||||
|
||||
var convertedValue = degrees * Math.PI / 180;
|
||||
return convertedValue;
|
||||
},
|
||||
|
||||
radToDeg: function(radians) {
|
||||
|
||||
var convertedValue = radians * 180 / Math.PI;
|
||||
return convertedValue;
|
||||
},
|
||||
|
||||
// these filters need instantiating, as they hold arrays of previous values
|
||||
createAveragingFilter: function(length) {
|
||||
|
||||
var newAveragingFilter = new AveragingFilter(length);
|
||||
return newAveragingFilter;
|
||||
},
|
||||
|
||||
createButterworthFilter: function(cutoff) {
|
||||
|
||||
var newButterworthFilter = new ButterworthFilter(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, special case for hips y-axis skeleton offset)
|
||||
clipTrough: function(inputValue, peak, strength) {
|
||||
|
||||
var outputValue = inputValue * strength;
|
||||
if (outputValue < -peak) {
|
||||
outputValue = -peak;
|
||||
}
|
||||
return outputValue;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// walkFilters.js
|
||||
//
|
||||
// version 1.002
|
||||
//
|
||||
// Created by David Wooldridge, Autumn 2014
|
||||
//
|
||||
// Provides a variety of filters for use by the walk.js script v1.12
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
AveragingFilter = function(length) {
|
||||
|
||||
//this.name = name;
|
||||
this.pastValues = [];
|
||||
|
||||
for(var i = 0; i < length; i++) {
|
||||
this.pastValues.push(0);
|
||||
}
|
||||
|
||||
// single arg is the nextInputValue
|
||||
this.process = function() {
|
||||
|
||||
if (this.pastValues.length === 0 && arguments[0]) {
|
||||
|
||||
return arguments[0];
|
||||
|
||||
} else if (arguments[0] !== null) {
|
||||
|
||||
// apply quick and simple LP filtering
|
||||
this.pastValues.push(arguments[0]);
|
||||
this.pastValues.shift();
|
||||
var nextOutputValue = 0;
|
||||
for (var ea in this.pastValues) nextOutputValue += this.pastValues[ea];
|
||||
return nextOutputValue / this.pastValues.length;
|
||||
|
||||
} else {
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// 1st order Butterworth 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 (-3 dB @ 3 Hz)
|
||||
ButterworthFilter1 = function() {
|
||||
|
||||
this.gain = 7.313751515;
|
||||
this.coeff = 0.7265425280;
|
||||
|
||||
// initialise the arrays
|
||||
this.xv = [];
|
||||
this.yv = [];
|
||||
|
||||
for(var i = 0; i < 2; i++) {
|
||||
|
||||
this.xv.push(0);
|
||||
this.yv.push(0);
|
||||
}
|
||||
|
||||
// process values
|
||||
this.process = function(nextInputValue) {
|
||||
|
||||
this.xv[0] = this.xv[1];
|
||||
this.xv[1] = nextInputValue / this.gain;
|
||||
|
||||
this.yv[0] = this.yv[1];
|
||||
this.yv[1] = this.xv[0] + this.xv[1] + this.coeff * this.yv[0];
|
||||
|
||||
return this.yv[1];
|
||||
};
|
||||
|
||||
}; // end Butterworth filter constructor
|
||||
|
||||
// 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
|
||||
ButterworthFilter2 = function(cutOff) {
|
||||
|
||||
switch(cutOff) {
|
||||
|
||||
case 5:
|
||||
default:
|
||||
|
||||
this.gain = 20.20612010;
|
||||
this.coeffOne = -0.4775922501;
|
||||
this.coeffTwo = 1.2796324250;
|
||||
break;
|
||||
}
|
||||
|
||||
// initialise the arrays
|
||||
this.xv = [];
|
||||
this.yv = [];
|
||||
for(var i = 0; i < 3; i++) {
|
||||
|
||||
this.xv.push(0);
|
||||
this.yv.push(0);
|
||||
}
|
||||
|
||||
// process values
|
||||
this.process = function(nextInputValue) {
|
||||
|
||||
this.xv[0] = this.xv[1];
|
||||
this.xv[1] = this.xv[2];
|
||||
this.xv[2] = nextInputValue / this.gain;
|
||||
|
||||
this.yv[0] = this.yv[1];
|
||||
this.yv[1] = this.yv[2];
|
||||
this.yv[2] = (this.xv[0] + this.xv[2]) +
|
||||
2 * this.xv[1] +
|
||||
(this.coeffOne * this.yv[0]) +
|
||||
(this.coeffTwo * this.yv[1]);
|
||||
|
||||
return this.yv[2];
|
||||
};
|
||||
}; // end Butterworth filter constructor
|
||||
|
||||
|
||||
// Add harmonics to a given sine wave to form square, sawtooth or triangle waves
|
||||
// Geometric wave synthesis fundamentals taken from: http://hyperphysics.phy-astr.gsu.edu/hbase/audio/geowv.html
|
||||
WaveSynth = function(waveShape, numHarmonics, smoothing) {
|
||||
|
||||
this.numHarmonics = numHarmonics;
|
||||
this.waveShape = waveShape;
|
||||
this.smoothingFilter = new AveragingFilter(smoothing);
|
||||
|
||||
// NB: frequency in radians
|
||||
this.calculate = function(frequency) {
|
||||
|
||||
// make some shapes
|
||||
var harmonics = 0;
|
||||
var multiplier = 0;
|
||||
var iterations = this.numHarmonics * 2 + 2;
|
||||
if (this.waveShape === TRIANGLE) {
|
||||
iterations++;
|
||||
}
|
||||
|
||||
for(var n = 1; n < iterations; n++) {
|
||||
|
||||
switch(this.waveShape) {
|
||||
|
||||
case SAWTOOTH: {
|
||||
|
||||
multiplier = 1 / n;
|
||||
harmonics += multiplier * Math.sin(n * frequency);
|
||||
break;
|
||||
}
|
||||
|
||||
case TRIANGLE: {
|
||||
|
||||
if (n % 2 === 1) {
|
||||
var mulitplier = 1 / (n * n);
|
||||
// multiply (4n-1)th harmonics by -1
|
||||
if (n === 3 || n === 7 || n === 11 || n === 15) {
|
||||
mulitplier *= -1;
|
||||
}
|
||||
harmonics += mulitplier * Math.sin(n * frequency);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SQUARE: {
|
||||
|
||||
if (n % 2 === 1) {
|
||||
multiplier = 1 / n;
|
||||
harmonics += multiplier * Math.sin(n * frequency);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// smooth the result and return
|
||||
return this.smoothingFilter.process(harmonics);
|
||||
};
|
||||
};
|
||||
|
||||
// Create a motion wave by summing pre-calcualted sinusoidal harmonics
|
||||
HarmonicsFilter = function(magnitudes, phaseAngles) {
|
||||
|
||||
this.magnitudes = magnitudes;
|
||||
this.phaseAngles = phaseAngles;
|
||||
|
||||
this.calculate = function(twoPiFT) {
|
||||
|
||||
var harmonics = 0;
|
||||
var numHarmonics = magnitudes.length;
|
||||
|
||||
for(var n = 0; n < numHarmonics; n++) {
|
||||
harmonics += this.magnitudes[n] * Math.cos(n * twoPiFT - this.phaseAngles[n]);
|
||||
}
|
||||
return harmonics;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// the main filter object
|
||||
filter = (function() {
|
||||
|
||||
// Bezier private functions
|
||||
function _B1(t) { return t * t * t };
|
||||
function _B2(t) { return 3 * t * t * (1 - t) };
|
||||
function _B3(t) { return 3 * t * (1 - t) * (1 - t) };
|
||||
function _B4(t) { return (1 - t) * (1 - t) * (1 - t) };
|
||||
|
||||
return {
|
||||
|
||||
// helper methods
|
||||
degToRad: function(degrees) {
|
||||
|
||||
var convertedValue = degrees * Math.PI / 180;
|
||||
return convertedValue;
|
||||
},
|
||||
|
||||
radToDeg: function(radians) {
|
||||
|
||||
var convertedValue = radians * 180 / Math.PI;
|
||||
return convertedValue;
|
||||
},
|
||||
|
||||
// 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
|
@ -566,6 +566,10 @@ function mouseReleaseEvent(event) {
|
|||
}
|
||||
|
||||
function mouseClickEvent(event) {
|
||||
if (!isActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
var result = findClickedEntity(event);
|
||||
if (result === null) {
|
||||
if (!event.isShifted) {
|
||||
|
|
3465
examples/walk.js
3465
examples/walk.js
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue