Merge branch 'master' of https://github.com/highfidelity/hifi into modelRayPick

This commit is contained in:
ZappoMan 2014-12-04 16:48:29 -08:00
commit 005ce8432e
8 changed files with 2207 additions and 5990 deletions

View file

@ -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) {

View file

@ -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 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, {
position: Vec3.sum(initialPosition, dPos),
rotation: Quat.multiply(yawChange, initialProperties.rotation),
});
Entities.editEntity(entityID, newProperties);
}
updateRotationDegreesOverlay(angleFromZero, yawHandleRotation, yawCenter);

View file

@ -90,7 +90,6 @@ Grid = function(opts) {
}
that.snapToSpacing = function(delta, majorOnly) {
print('snaptogrid? ' + snapToGrid);
if (!snapToGrid) {
return delta;
}

View file

@ -1,11 +1,11 @@
//
// walkObjects.js
//
// version 1.001
// version 1.003
//
// Created by David Wooldridge, Autumn 2014
//
// Motion, state and Transition objects for use by the walk.js script v1.1
// Motion, state and Transition objects 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
@ -14,41 +14,21 @@
// constructor for the Motion object
Motion = function() {
this.setGender = function(gender) {
this.avatarGender = gender;
switch(this.avatarGender) {
case MALE:
this.selWalk = walkAssets.maleStandardWalk;
this.selStand = walkAssets.maleStandOne;
this.selFlyUp = walkAssets.maleFlyingUp;
this.selFly = walkAssets.maleFlying;
this.selFlyDown = walkAssets.maleFlyingDown;
this.selSideStepLeft = walkAssets.maleSideStepLeft;
this.selSideStepRight = walkAssets.maleSideStepRight;
this.curAnim = this.selStand;
return;
case FEMALE:
this.selWalk = walkAssets.femaleStandardWalk;
this.selStand = walkAssets.femaleStandOne;
this.selFlyUp = walkAssets.femaleFlyingUp;
this.selFly = walkAssets.femaleFlying;
this.selFlyDown = walkAssets.femaleFlyingDown;
this.selSideStepLeft = walkAssets.femaleSideStepLeft;
this.selSideStepRight = walkAssets.femaleSideStepRight;
this.curAnim = this.selStand;
return;
}
}
// selected animations
this.selectedWalk = undefined;
this.selectedStand = undefined;
this.selectedFly = undefined;
this.selectedFlyUp = undefined;
this.selectedFlyDown = undefined;
this.selectedFlyBlend = undefined;
this.selectedHovering = undefined;
this.selectedSideStepLeft = undefined;
this.selectedSideStepRight = undefined;
// if Hydras are connected, the only way to enable use is by never setting any rotations on the arm joints
this.hydraCheck = function() {
// function courtesy of Thijs Wenker, frisbee.js
// function courtesy of Thijs Wenker (frisbee.js)
var numberOfButtons = Controller.getNumberOfButtons();
var numberOfTriggers = Controller.getNumberOfTriggers();
var numberOfSpatialControls = Controller.getNumberOfSpatialControls();
@ -60,33 +40,65 @@ Motion = function() {
// settings
this.armsFree = this.hydraCheck(); // automatically sets true for Hydra support - temporary fix
this.makesFootStepSounds = true;
this.avatarGender = MALE;
this.motionPitchMax = 60;
this.motionRollMax = 40;
this.avatarGender = undefined;
this.setGender = function(gender) {
// timing
this.frameStartTime = 0; // used for measuring frame execution times
this.frameExecutionTimeMax = 0; // keep track of the longest frame execution time
this.cumulativeTime = 0.0;
this.lastWalkStartTime = 0;
this.avatarGender = gender;
// selected animations
this.selWalk = walkAssets.maleStandardWalk;
this.selStand = walkAssets.maleStandOne;
this.selFlyUp = walkAssets.maleFlyingUp;
this.selFly = walkAssets.maleFlying;
this.selFlyDown = walkAssets.maleFlyingDown;
this.selSideStepLeft = walkAssets.maleSideStepLeft;
this.selSideStepRight = walkAssets.maleSideStepRight;
switch(this.avatarGender) {
// the currently selected animation, joint and transition
this.curAnim = this.selStand;
this.curJointIndex = 0;
this.curTransition = null;
case MALE:
// zero out avi's joints, curl the fingers nicely then take some measurements
this.selectedWalk = walkAssets.maleStandardWalk;
this.selectedStand = walkAssets.maleStandOne;
this.selectedFlyUp = walkAssets.maleFlyingUp;
this.selectedFly = walkAssets.maleFlying;
this.selectedFlyDown = walkAssets.maleFlyingDown;
this.selectedFlyBlend = walkAssets.maleFlyingBlend;
this.selectedHovering = walkAssets.maleHovering;
this.selectedSideStepLeft = walkAssets.maleSideStepLeft;
this.selectedSideStepRight = walkAssets.maleSideStepRight;
this.currentAnimation = this.selectedStand;
return;
case FEMALE:
this.selectedWalk = walkAssets.femaleStandardWalk;
this.selectedStand = walkAssets.femaleStandOne;
this.selectedFlyUp = walkAssets.femaleFlyingUp;
this.selectedFly = walkAssets.femaleFlying;
this.selectedFlyDown = walkAssets.femaleFlyingDown;
this.selectedFlyBlend = walkAssets.femaleFlyingBlend;
this.selectedHovering = walkAssets.femaleHovering;
this.selectedSideStepLeft = walkAssets.femaleSideStepLeft;
this.selectedSideStepRight = walkAssets.femaleSideStepRight;
this.currentAnimation = this.selectedStand;
return;
}
}
this.setGender(MALE);
// calibration
this.calibration = {
pitchMax: 8,
maxWalkAcceleration: 5,
maxWalkDeceleration: 25,
rollMax: 80,
angularVelocityMax: 70,
hipsToFeet: MyAvatar.getJointPosition("Hips").y - MyAvatar.getJointPosition("RightFoot").y,
}
// used to make sure at least one step has been taken when transitioning from a walk cycle
this.elapsedFTDegrees = 0;
// the current animation and transition
this.currentAnimation = this.selectedStand;
this.currentTransition = null;
// zero out avi's joints and pose the fingers
this.avatarJointNames = MyAvatar.getJointNames();
if (!this.armsFree) {
this.poseFingers = function() {
for (var i = 0; i < this.avatarJointNames.length; i++) {
@ -102,38 +114,138 @@ Motion = function() {
} else if (i > 57 || i < 62) {
// right hand thumb
MyAvatar.setJointData(this.avatarJointNames[i], Quat.fromPitchYawRollDegrees(4, 0, 0));
} else {
// zero out the remaining joints
MyAvatar.clearJointData(this.avatarJointNames[i]);
}
}
};
if (!this.armsFree) {
this.poseFingers();
}
this.footRPos = MyAvatar.getJointPosition("RightFoot");
this.hipsToFeet = MyAvatar.getJointPosition("Hips").y - this.footRPos.y;
// walkwheel (foot / ground speed matching)
// frequency time wheel (foot / ground speed matching)
this.direction = FORWARDS;
this.nextStep = RIGHT;
this.nFrames = 0;
this.strideLength = this.selWalk.calibration.strideLengthForwards;
this.walkWheelPos = 0;
this.strideLength = this.selectedWalk.calibration.strideLengthForwards;
this.frequencyTimeWheelPos = 0;
this.frequencyTimeWheelRadius = 0.5;
this.recentFrequencyTimeIncrements = [];
for(var i = 0; i < 8; i++) {
this.advanceWalkWheel = function(angle){
this.walkWheelPos += angle;
if (motion.walkWheelPos >= 360) {
this.walkWheelPos = this.walkWheelPos % 360;
this.recentFrequencyTimeIncrements.push(0);
}
this.averageFrequencyTimeIncrement = 0;
this.advanceFrequencyTimeWheel = function(angle){
this.elapsedFTDegrees += angle;
this.recentFrequencyTimeIncrements.push(angle);
this.recentFrequencyTimeIncrements.shift();
for(increment in this.recentFrequencyTimeIncrements) {
this.averageFrequencyTimeIncrement += this.recentFrequencyTimeIncrements[increment];
}
this.averageFrequencyTimeIncrement /= this.recentFrequencyTimeIncrements.length;
this.frequencyTimeWheelPos += angle;
if (this.frequencyTimeWheelPos >= 360) {
this.frequencyTimeWheelPos = this.frequencyTimeWheelPos % 360;
}
}
// last frame history
// currently disabled due to breaking changes in js audio native objects
this.playFootStepSound = function(side) {
//var options = new AudioInjectionOptions();
//options.position = Camera.getPosition();
//options.volume = 0.3;
//var soundNumber = 2; // 0 to 2
//if (side === RIGHT && motion.makesFootStepSounds) {
// Audio.playS ound(walkAssets.footsteps[soundNumber + 1], options);
//} else if (side === LEFT && motion.makesFootStepSounds) {
// Audio.playSound(walkAssets.footsteps[soundNumber], options);
//}
}
// history
this.lastDirection = 0;
this.lastVelocity = 0;
this.lastStrideLength = 0; // kept for use during transitions
this.lastSpeed = 0;
this.transitionCount = 0;
this.lastDistanceToVoxels = 0;
}; // end Motion constructor
// finite state machine
spatialInformation = (function() {
return {
distanceToVoxels: function() {
// use the blocking version of findRayIntersection to avoid errors
var pickRay = {origin: MyAvatar.position, direction: {x:0, y:-1, z:0}};
return Voxels.findRayIntersectionBlocking(pickRay).distance - motion.calibration.hipsToFeet;;
}
}
})(); // end spatialInformation object literal
// animation file manipulation
animation = (function() {
return {
zeroAnimation: function(animation) {
for (i in animation.joints) {
animation.joints[i].pitch = 0;
animation.joints[i].yaw = 0;
animation.joints[i].roll = 0;
animation.joints[i].pitchPhase = 0;
animation.joints[i].yawPhase = 0;
animation.joints[i].rollPhase = 0;
animation.joints[i].pitchOffset = 0;
animation.joints[i].yawOffset = 0;
animation.joints[i].rollOffset = 0;
if (i === 0) {
// Hips only
animation.joints[i].thrust = 0;
animation.joints[i].sway = 0;
animation.joints[i].bob = 0;
animation.joints[i].thrustPhase = 0;
animation.joints[i].swayPhase = 0;
animation.joints[i].bobPhase = 0;
}
}
},
blendAnimation: function(sourceAnimation, targetAnimation, percent) {
for (i in targetAnimation.joints) {
targetAnimation.joints[i].pitch += percent * sourceAnimation.joints[i].pitch;
targetAnimation.joints[i].yaw += percent * sourceAnimation.joints[i].yaw;
targetAnimation.joints[i].roll += percent * sourceAnimation.joints[i].roll;
targetAnimation.joints[i].pitchPhase += percent * sourceAnimation.joints[i].pitchPhase;
targetAnimation.joints[i].yawPhase += percent * sourceAnimation.joints[i].yawPhase;
targetAnimation.joints[i].rollPhase += percent * sourceAnimation.joints[i].rollPhase;
targetAnimation.joints[i].pitchOffset += percent * sourceAnimation.joints[i].pitchOffset;
targetAnimation.joints[i].yawOffset += percent * sourceAnimation.joints[i].yawOffset;
targetAnimation.joints[i].rollOffset += percent * sourceAnimation.joints[i].rollOffset;
if (i === 0) {
// Hips only
targetAnimation.joints[i].thrust += percent * sourceAnimation.joints[i].thrust;
targetAnimation.joints[i].sway += percent * sourceAnimation.joints[i].sway;
targetAnimation.joints[i].bob += percent * sourceAnimation.joints[i].bob;
targetAnimation.joints[i].thrustPhase += percent * sourceAnimation.joints[i].thrustPhase;
targetAnimation.joints[i].swayPhase += percent * sourceAnimation.joints[i].swayPhase;
targetAnimation.joints[i].bobPhase += percent * sourceAnimation.joints[i].bobPhase;
}
}
}
}
})(); // end animation object literal
// finite state machine. Avatar locomotion modes represent states in the FSM
state = (function () {
return {
@ -143,151 +255,36 @@ state = (function () {
WALKING: 2,
SIDE_STEP: 3,
FLYING: 4,
EDIT_WALK_STYLES: 5,
EDIT_WALK_TWEAKS: 6,
EDIT_WALK_JOINTS: 7,
EDIT_STANDING: 8,
EDIT_FLYING: 9,
EDIT_FLYING_UP: 10,
EDIT_FLYING_DOWN: 11,
EDIT_SIDESTEP_LEFT: 12,
EDIT_SIDESTEP_RIGHT: 14,
currentState: this.STANDING,
// status vars
powerOn: true,
minimised: true,
editing: false,
editingTranslation: false,
setInternalState: function(newInternalState) {
motion.elapsedFTDegrees = 0;
switch (newInternalState) {
case this.WALKING:
this.currentState = this.WALKING;
this.editing = false;
motion.lastWalkStartTime = new Date().getTime();
walkInterface.updateMenu();
return;
case this.FLYING:
this.currentState = this.FLYING;
this.editing = false;
motion.lastWalkStartTime = 0;
walkInterface.updateMenu();
return;
case this.SIDE_STEP:
this.currentState = this.SIDE_STEP;
this.editing = false;
motion.lastWalkStartTime = new Date().getTime();
walkInterface.updateMenu();
return;
case this.EDIT_WALK_STYLES:
this.currentState = this.EDIT_WALK_STYLES;
this.editing = true;
motion.lastWalkStartTime = new Date().getTime();
motion.curAnim = motion.selWalk;
walkInterface.updateMenu();
return;
case this.EDIT_WALK_TWEAKS:
this.currentState = this.EDIT_WALK_TWEAKS;
this.editing = true;
motion.lastWalkStartTime = new Date().getTime();
motion.curAnim = motion.selWalk;
walkInterface.updateMenu();
return;
case this.EDIT_WALK_JOINTS:
this.currentState = this.EDIT_WALK_JOINTS;
this.editing = true;
motion.lastWalkStartTime = new Date().getTime();
motion.curAnim = motion.selWalk;
walkInterface.updateMenu();
return;
case this.EDIT_STANDING:
this.currentState = this.EDIT_STANDING;
this.editing = true;
motion.lastWalkStartTime = 0;
motion.curAnim = motion.selStand;
walkInterface.updateMenu();
return;
case this.EDIT_SIDESTEP_LEFT:
this.currentState = this.EDIT_SIDESTEP_LEFT;
this.editing = true;
motion.lastWalkStartTime = new Date().getTime();
motion.curAnim = motion.selSideStepLeft;
walkInterface.updateMenu();
return;
case this.EDIT_SIDESTEP_RIGHT:
this.currentState = this.EDIT_SIDESTEP_RIGHT;
this.editing = true;
motion.lastWalkStartTime = new Date().getTime();
motion.curAnim = motion.selSideStepRight;
walkInterface.updateMenu();
return;
case this.EDIT_FLYING:
this.currentState = this.EDIT_FLYING;
this.editing = true;
motion.lastWalkStartTime = 0;
motion.curAnim = motion.selFly;
walkInterface.updateMenu();
return;
case this.EDIT_FLYING_UP:
this.currentState = this.EDIT_FLYING_UP;
this.editing = true;
motion.lastWalkStartTime = 0;
motion.curAnim = motion.selFlyUp;
walkInterface.updateMenu();
return;
case this.EDIT_FLYING_DOWN:
this.currentState = this.EDIT_FLYING_DOWN;
this.editing = true;
motion.lastWalkStartTime = 0;
motion.curAnim = motion.selFlyDown;
walkInterface.updateMenu();
return;
case this.STANDING:
default:
this.currentState = this.STANDING;
this.editing = false;
motion.lastWalkStartTime = 0;
motion.curAnim = motion.selStand;
walkInterface.updateMenu();
// initialisation - runs at script startup only
if (motion.strideLength === 0) {
motion.setGender(MALE);
if (motion.direction === BACKWARDS) {
motion.strideLength = motion.selWalk.calibration.strideLengthBackwards;
} else {
motion.strideLength = motion.selWalk.calibration.strideLengthForwards;
}
}
return;
}
}
@ -295,109 +292,302 @@ state = (function () {
})(); // end state object literal
// constructor for animation Transition
Transition = function(lastAnimation, nextAnimation, reachPoses, transitionDuration, easingLower, easingUpper) {
Transition = function(nextAnimation, lastAnimation, lastTransition) {
this.lastAnim = lastAnimation; // name of last animation
this.nextAnimation = nextAnimation; // name of next animation
if (lastAnimation === motion.selWalk ||
nextAnimation === motion.selSideStepLeft ||
nextAnimation === motion.selSideStepRight) {
// boolean - is the last animation a walking animation?
this.walkingAtStart = true;
} else {
this.walkingAtStart = false;
// record the current state of animation
this.nextAnimation = nextAnimation;
this.lastAnimation = lastAnimation;
this.lastTransition = lastTransition;
// deal with transition recursion (overlapping transitions)
this.id = motion.transitionCount++; // serial number for this transition
this.recursionDepth = 0;
this.incrementRecursion = function() {
this.recursionDepth += 1;
if(this.lastTransition !== nullTransition) {
this.lastTransition.incrementRecursion();
if(this.lastTransition.recursionDepth > 5) {
delete this.lastTransition;
this.lastTransition = nullTransition;
}
if (nextAnimation === motion.selWalk ||
nextAnimation === motion.selSideStepLeft ||
nextAnimation === motion.selSideStepRight) {
// boolean - is the next animation a walking animation?
this.walkingAtEnd = true;
} else {
this.walkingAtEnd = false;
}
this.reachPoses = reachPoses; // placeholder / stub: array of reach poses for squash and stretch techniques
this.transitionDuration = transitionDuration; // length of transition (seconds)
this.easingLower = easingLower; // Bezier curve handle (normalised)
this.easingUpper = easingUpper; // Bezier curve handle (normalised)
}
if(lastTransition !== nullTransition) {
this.lastTransition.incrementRecursion();
}
this.reachPoses = []; // placeholder / stub: work in progress - array of reach poses for squash and stretch techniques
this.transitionDuration = 0.5; // length of transition (seconds)
this.easingLower = {x:0.60, y:0.03}; // Bezier curve handle
this.easingUpper = {x:0.87, y:1.35}; // Bezier curve handle
this.startTime = new Date().getTime(); // Starting timestamp (seconds)
this.progress = 0; // how far are we through the transition?
this.walkWheelIncrement = 3; // how much to turn the walkwheel each frame when transitioning to / from walking
this.walkWheelAdvance = 0; // how many degrees the walk wheel has been advanced during the transition
this.walkStopAngle = 0; // what angle should we stop the walk cycle?
this.lastDirection = motion.lastDirection;
// collect information about the currently playing animation
this.lastDirection = motion.lastDirection;
this.lastFrequencyTimeWheelPos = motion.frequencyTimeWheelPos;
this.lastFrequencyTimeIncrement = motion.averageFrequencyTimeIncrement;
this.lastFrequencyTimeWheelRadius = motion.frequencyTimeWheelRadius;
this.stopAngle = 0; // what angle should we stop turning this frequency time wheel?
this.percentToMove = 0; // if we need to keep moving to complete a step, this will be set to 100
this.lastElapsedFTDegrees = motion.elapsedFTDegrees;
this.advancePreviousFrequencyTimeWheel = function() {
this.lastFrequencyTimeWheelPos += this.lastFrequencyTimeIncrement;
if (this.lastFrequencyTimeWheelPos >= 360) {
this.lastFrequencyTimeWheelPos = this.lastFrequencyTimeWheelPos % 360;
}
if(this.lastTransition !== nullTransition) {
this.lastTransition.advancePreviousFrequencyTimeWheel();
}
};
this.updateProgress = function() {
var elapasedTime = (new Date().getTime() - this.startTime) / 1000;
this.progress = elapasedTime / this.transitionDuration;
this.progress = filter.bezier((1 - this.progress),
{x: 0, y: 0},
this.easingLower,
this.easingUpper,
{x: 1, y: 1}).y;
// ensure there is at least some progress
if(this.progress <= 0) {
this.progress = VERY_SHORT_TIME;
}
if(this.lastTransition !== nullTransition) {
if(this.lastTransition.updateProgress() >= 1) {
// the previous transition is now complete
delete this.lastTransition;
this.lastTransition = nullTransition;
}
}
return this.progress;
};
this.blendTranslations = function(frequencyTimeWheelPos, direction) {
var lastTranslations = {x:0, y:0, z:0};
if(!isDefined(this.nextAnimation)) {
return lastTranslations;
}
var nextTranslations = calculateTranslations(this.nextAnimation,
frequencyTimeWheelPos,
direction);
// are we blending with a previous, still live transition?
if(this.lastTransition !== nullTransition) {
lastTranslations = this.lastTransition.blendTranslations(this.lastFrequencyTimeWheelPos,
this.lastDirection);
} else {
lastTranslations = calculateTranslations(this.lastAnimation,
this.lastFrequencyTimeWheelPos,
this.lastDirection);
}
nextTranslations.x = this.progress * nextTranslations.x +
(1 - this.progress) * lastTranslations.x;
nextTranslations.y = this.progress * nextTranslations.y +
(1 - this.progress) * lastTranslations.y;
nextTranslations.z = this.progress * nextTranslations.z +
(1 - this.progress) * lastTranslations.z;
return nextTranslations;
};
this.blendRotations = function(jointName, frequencyTimeWheelPos, direction) {
var lastRotations = {x:0, y:0, z:0};
var nextRotations = calculateRotations(jointName,
this.nextAnimation,
frequencyTimeWheelPos,
direction);
// are we blending with a previous, still live transition?
if(this.lastTransition !== nullTransition) {
lastRotations = this.lastTransition.blendRotations(jointName,
this.lastFrequencyTimeWheelPos,
this.lastDirection);
} else {
lastRotations = calculateRotations(jointName,
this.lastAnimation,
this.lastFrequencyTimeWheelPos,
this.lastDirection);
}
nextRotations.x = this.progress * nextRotations.x +
(1 - this.progress) * lastRotations.x;
nextRotations.y = this.progress * nextRotations.y +
(1 - this.progress) * lastRotations.y;
nextRotations.z = this.progress * nextRotations.z +
(1 - this.progress) * lastRotations.z;
return nextRotations;
};
}; // end Transition constructor
// individual joint modiers (mostly used to provide symmetry between left and right limbs)
JointModifiers = function(joint, direction) {
// gather modifiers and multipliers
this.pitchFrequencyMultiplier = 1;
this.pitchPhaseModifier = 0;
this.pitchReverseModifier = 0;
this.yawReverseModifier = 0;
this.rollReverseModifier = 0;
this.pitchSign = 1; // for sidestepping and incorrectly rigged Ron ToeBases
this.yawSign = 1;
this.rollSign = 1;
this.pitchReverseInvert = 1;
this.pitchOffsetSign = 1;
this.yawOffsetSign = 1;
this.rollOffsetSign = 1;
this.bobReverseModifier = 0;
this.bobFrequencyMultiplier = 1;
this.thrustFrequencyMultiplier = 1;
if (isDefined(joint.pitchFrequencyMultiplier)) {
this.pitchFrequencyMultiplier = joint.pitchFrequencyMultiplier;
}
if (isDefined(joint.pitchPhaseModifier)) {
this.pitchPhaseModifier = joint.pitchPhaseModifier;
}
if (isDefined(joint.pitchSign)) {
this.pitchSign = joint.pitchSign;
}
if (isDefined(joint.yawSign)) {
this.yawSign = joint.yawSign;
}
if (isDefined(joint.rollSign)) {
this.rollSign = joint.rollSign;
}
if (isDefined(joint.pitchReverseInvert) && direction === BACKWARDS) {
this.pitchReverseInvert = joint.pitchReverseInvert;
}
if (isDefined(joint.pitchReverseModifier) && direction === BACKWARDS) {
this.pitchReverseModifier = joint.pitchReverseModifier;
}
if (isDefined(joint.yawReverseModifier) && direction === BACKWARDS) {
this.yawReverseModifier = joint.yawReverseModifier;
}
if (isDefined(joint.rollReverseModifier) && direction === BACKWARDS) {
this.rollReverseModifier = joint.rollReverseModifier;
}
if (isDefined(joint.pitchOffsetSign)) {
this.pitchOffsetSign = joint.pitchOffsetSign;
}
if (isDefined(joint.yawOffsetSign)) {
this.yawOffsetSign = joint.yawOffsetSign;
}
if (isDefined(joint.rollOffsetSign)) {
this.rollOffsetSign = joint.rollOffsetSign;
}
if (isDefined(joint.bobReverseModifier) && direction === BACKWARDS) {
this.bobReverseModifier = joint.bobReverseModifier;
}
if (isDefined(joint.bobFrequencyMultiplier)) {
this.bobFrequencyMultiplier = joint.bobFrequencyMultiplier;
}
if (isDefined(joint.thrustFrequencyMultiplier)) {
this.thrustFrequencyMultiplier = joint.thrustFrequencyMultiplier;
}
};
walkAssets = (function () {
// path to the sounds used for the footsteps
var _pathToSounds = 'https://s3.amazonaws.com/hifi-public/sounds/Footsteps/';
// load the sounds - currently disabled due to breaking changes in js audio native objects
//var _pathToSounds = 'https://s3.amazonaws.com/hifi-public/sounds/Footsteps/';
// read in the sounds
var _footsteps = [];
_footsteps.push(SoundCache.getSound(_pathToSounds+"FootstepW2Left-12db.wav"));
_footsteps.push(SoundCache.getSound(_pathToSounds+"FootstepW2Right-12db.wav"));
_footsteps.push(SoundCache.getSound(_pathToSounds+"FootstepW3Left-12db.wav"));
_footsteps.push(SoundCache.getSound(_pathToSounds+"FootstepW3Right-12db.wav"));
_footsteps.push(SoundCache.getSound(_pathToSounds+"FootstepW5Left-12db.wav"));
_footsteps.push(SoundCache.getSound(_pathToSounds+"FootstepW5Right-12db.wav"));
//var _footsteps = [];
//_footsteps.push(new Sound(_pathToSounds+"FootstepW2Left-12db.wav"));
//_footsteps.push(new Sound(_pathToSounds+"FootstepW2Right-12db.wav"));
//_footsteps.push(new Sound(_pathToSounds+"FootstepW3Left-12db.wav"));
//_footsteps.push(new Sound(_pathToSounds+"FootstepW3Right-12db.wav"));
//_footsteps.push(new Sound(_pathToSounds+"FootstepW5Left-12db.wav"));
//_footsteps.push(new Sound(_pathToSounds+"FootstepW5Right-12db.wav"));
// load the animation datafiles
Script.include(pathToAssets+"animations/dd-female-standard-walk-animation.js");
Script.include(pathToAssets+"animations/dd-female-standing-one-animation.js");
Script.include(pathToAssets+"animations/dd-female-flying-up-animation.js");
Script.include(pathToAssets+"animations/dd-female-flying-animation.js");
Script.include(pathToAssets+"animations/dd-female-flying-down-animation.js");
Script.include(pathToAssets+"animations/dd-female-standing-one-animation.js");
Script.include(pathToAssets+"animations/dd-female-flying-blend-animation.js");
Script.include(pathToAssets+"animations/dd-female-hovering-animation.js");
Script.include(pathToAssets+"animations/dd-female-sidestep-left-animation.js");
Script.include(pathToAssets+"animations/dd-female-sidestep-right-animation.js");
Script.include(pathToAssets+"animations/dd-male-standard-walk-animation.js");
Script.include(pathToAssets+"animations/dd-male-standing-one-animation.js");
Script.include(pathToAssets+"animations/dd-male-flying-up-animation.js");
Script.include(pathToAssets+"animations/dd-male-flying-animation.js");
Script.include(pathToAssets+"animations/dd-male-flying-down-animation.js");
Script.include(pathToAssets+"animations/dd-male-standing-one-animation.js");
Script.include(pathToAssets+"animations/dd-male-flying-blend-animation.js");
Script.include(pathToAssets+"animations/dd-male-hovering-animation.js");
Script.include(pathToAssets+"animations/dd-male-sidestep-left-animation.js");
Script.include(pathToAssets+"animations/dd-male-sidestep-right-animation.js");
Script.include(pathToAssets+"animations/dd-animation-reference.js");
// read in the animation files
var _FemaleStandardWalkFile = new FemaleStandardWalk();
var _femaleStandardWalk = _FemaleStandardWalkFile.loadAnimation();
var _FemaleFlyingUpFile = new FemaleFlyingUp();
var _femaleFlyingUp = _FemaleFlyingUpFile.loadAnimation();
var _FemaleFlyingFile = new FemaleFlying();
var _femaleFlying = _FemaleFlyingFile.loadAnimation();
var _FemaleFlyingDownFile = new FemaleFlyingDown();
var _femaleFlyingDown = _FemaleFlyingDownFile.loadAnimation();
var _FemaleStandOneFile = new FemaleStandingOne();
var _femaleStandOne = _FemaleStandOneFile.loadAnimation();
var _FemaleSideStepLeftFile = new FemaleSideStepLeft();
var _femaleSideStepLeft = _FemaleSideStepLeftFile.loadAnimation();
var _FemaleSideStepRightFile = new FemaleSideStepRight();
var _femaleSideStepRight = _FemaleSideStepRightFile.loadAnimation();
var _MaleStandardWalkFile = new MaleStandardWalk(filter);
var _maleStandardWalk = _MaleStandardWalkFile.loadAnimation();
var _MaleFlyingUpFile = new MaleFlyingUp();
var _maleFlyingUp = _MaleFlyingUpFile.loadAnimation();
var _MaleFlyingFile = new MaleFlying();
var _maleFlying = _MaleFlyingFile.loadAnimation();
var _MaleFlyingDownFile = new MaleFlyingDown();
var _maleFlyingDown = _MaleFlyingDownFile.loadAnimation();
var _MaleStandOneFile = new MaleStandingOne();
var _maleStandOne = _MaleStandOneFile.loadAnimation();
var _MaleSideStepLeftFile = new MaleSideStepLeft();
var _maleSideStepLeft = _MaleSideStepLeftFile.loadAnimation();
var _MaleSideStepRightFile = new MaleSideStepRight();
var _maleSideStepRight = _MaleSideStepRightFile.loadAnimation();
var _femaleStandardWalk = new FemaleStandardWalk();
var _femaleFlyingUp = new FemaleFlyingUp();
var _femaleFlying = new FemaleFlying();
var _femaleFlyingDown = new FemaleFlyingDown();
var _femaleStandOne = new FemaleStandingOne();
var _femaleSideStepLeft = new FemaleSideStepLeft();
var _femaleSideStepRight = new FemaleSideStepRight();
var _femaleFlyingBlend = new FemaleFlyingBlend();
var _femaleHovering = new FemaleHovering();
var _maleStandardWalk = new MaleStandardWalk(filter);
var _maleStandOne = new MaleStandingOne();
var _maleSideStepLeft = new MaleSideStepLeft();
var _maleSideStepRight = new MaleSideStepRight();
var _maleFlying = new MaleFlying();
var _maleFlyingDown = new MaleFlyingDown();
var _maleFlyingUp = new MaleFlyingUp();
var _maleFlyingBlend = new MaleFlyingBlend();
var _maleHovering = new MaleHovering();
var _animationReference = new AnimationReference();
return {
// expose the sound assets
footsteps: _footsteps,
//footsteps: _footsteps,
// expose the animation assets
femaleStandardWalk: _femaleStandardWalk,
femaleFlyingUp: _femaleFlyingUp,
femaleFlying: _femaleFlying,
femaleFlyingDown: _femaleFlyingDown,
femaleFlyingBlend: _femaleFlyingBlend,
femaleHovering: _femaleHovering,
femaleStandOne: _femaleStandOne,
femaleSideStepLeft: _femaleSideStepLeft,
femaleSideStepRight: _femaleSideStepRight,
@ -405,8 +595,12 @@ walkAssets = (function () {
maleFlyingUp: _maleFlyingUp,
maleFlying: _maleFlying,
maleFlyingDown: _maleFlyingDown,
maleFlyingBlend: _maleFlyingBlend,
maleHovering: _maleHovering,
maleStandOne: _maleStandOne,
maleSideStepLeft: _maleSideStepLeft,
maleSideStepRight: _maleSideStepRight,
animationReference: _animationReference,
}
})();

View file

@ -1,11 +1,11 @@
//
// walkFilters.js
//
// version 1.001
// version 1.002
//
// 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.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@ -24,33 +24,77 @@ AveragingFilter = function(length) {
this.process = function() {
if (this.pastValues.length === 0 && arguments[0]) {
return arguments[0];
} else if (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
ButterworthFilter = function(cutOff) {
ButterworthFilter2 = function(cutOff) {
switch(cutOff) {
case 5:
default:
// cut off frequency = 5Hz
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);
}
@ -71,7 +115,8 @@ ButterworthFilter = function(cutOff) {
return this.yv[2];
};
}; // end Butterworth filter contructor
}; // 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
@ -79,10 +124,10 @@ WaveSynth = function(waveShape, numHarmonics, smoothing) {
this.numHarmonics = numHarmonics;
this.waveShape = waveShape;
this.averagingFilter = new AveragingFilter(smoothing);
this.smoothingFilter = new AveragingFilter(smoothing);
// NB: frequency in radians
this.shapeWave = function(frequency) {
this.calculate = function(frequency) {
// make some shapes
var harmonics = 0;
@ -92,7 +137,7 @@ WaveSynth = function(waveShape, numHarmonics, smoothing) {
iterations++;
}
for(var n = 2; n < iterations; n++) {
for(var n = 1; n < iterations; n++) {
switch(this.waveShape) {
@ -128,11 +173,11 @@ WaveSynth = function(waveShape, numHarmonics, smoothing) {
}
// smooth the result and return
return this.averagingFilter.process(harmonics);
return this.smoothingFilter.process(harmonics);
};
};
// Create a wave shape by summing pre-calcualted sinusoidal harmonics
// Create a motion wave by summing pre-calcualted sinusoidal harmonics
HarmonicsFilter = function(magnitudes, phaseAngles) {
this.magnitudes = magnitudes;
@ -150,7 +195,8 @@ HarmonicsFilter = function(magnitudes, phaseAngles) {
};
};
// the main filter object literal
// the main filter object
filter = (function() {
// Bezier private functions
@ -181,9 +227,15 @@ filter = (function() {
return newAveragingFilter;
},
createButterworthFilter: function(cutoff) {
createButterworthFilter1: function() {
var newButterworthFilter = new ButterworthFilter(cutoff);
var newButterworthFilter = new ButterworthFilter1();
return newButterworthFilter;
},
createButterworthFilter2: function(cutoff) {
var newButterworthFilter = new ButterworthFilter2(cutoff);
return newButterworthFilter;
},
@ -211,7 +263,7 @@ filter = (function() {
return pos;
},
// simple clipping filter (clips bottom of wave only, special case for hips y-axis skeleton offset)
// simple clipping filter (clips bottom of wave only)
clipTrough: function(inputValue, peak, strength) {
var outputValue = inputValue * strength;

File diff suppressed because it is too large Load diff

View file

@ -566,6 +566,10 @@ function mouseReleaseEvent(event) {
}
function mouseClickEvent(event) {
if (!isActive) {
return;
}
var result = findClickedEntity(event);
if (result === null) {
if (!event.isShifted) {

File diff suppressed because it is too large Load diff