fixed sounds. fixed constants

This commit is contained in:
DaveDubUK 2015-06-25 12:40:51 +07:00
parent ececf68f06
commit ce31e586b0
6 changed files with 121 additions and 134 deletions

View file

@ -2,16 +2,16 @@
<head>
<link rel="stylesheet" type="text/css" href="walkStyle.css">
<script>
function emitUpdate() {
EventBridge.emitWebEvent(JSON.stringify({
type: "update",
armsFree: elArmsFree.checked,
footstepSounds: elFootstepSounds.checked,
makesFootStepSounds: elFootstepSounds.checked,
blenderPreRotations: elBlenderPreRotations.checked
}));
}
function loaded() {
// assign form elements to vars
var powerOn = true;
@ -23,17 +23,17 @@
if (window.EventBridge !== undefined) {
EventBridge.scriptEventReceived.connect(function(data) {
data = JSON.parse(data);
if (data.type == "update") {
if (data.armsFree !== undefined) {
elArmsFree.checked = data.armsFree;
}
if (data.footstepSounds !== undefined) {
elFootstepSounds.checked = data.footstepSounds;
if (data.makesFootStepSounds !== undefined) {
elFootstepSounds.checked = data.makesFootStepSounds;
}
if (data.blenderPreRotations !== undefined) {
elBlenderPreRotations.checked = data.blenderPreRotations;
}
}
}
});
}
@ -50,8 +50,8 @@
} else {
elPower.value = "Turn Animation On";
}
});
// request initial values
});
// request initial values
EventBridge.emitWebEvent(JSON.stringify({ type: 'init' }));
}
</script>
@ -62,7 +62,7 @@
<div id="walk-settings-header">
<input type="button" id="power" value="Turn Animation Off" style="margin-left:30px; margin-top:10px"></button>
</div>
<div class="settings-section">
<label>Arms free</label>
<span>

View file

@ -3,7 +3,7 @@
// version 1.3
//
// Created by David Wooldridge, June 2015
// Copyright © 2014 - 2015 High Fidelity, Inc.
// Copyright © 2014 - 2015 High Fidelity, Inc.
//
// Exposes API for use by walk.js version 1.2+.
//
@ -13,46 +13,11 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// locomotion states
const STATIC = 1;
const SURFACE_MOTION = 2;
const AIR_MOTION = 4;
// directions
const UP = 1;
const DOWN = 2;
const LEFT = 4;
const RIGHT = 8;
const FORWARDS = 16;
const BACKWARDS = 32;
const NONE = 64;
// waveshapes
const SAWTOOTH = 1;
const TRIANGLE = 2;
const SQUARE = 4;
// constants used by walk.js and walkApi.js
const MAX_WALK_SPEED = 2.9; // peak, by observation
const MAX_FT_WHEEL_INCREMENT = 25; // avoid fast walk when landing
const TOP_SPEED = 300;
const ON_SURFACE_THRESHOLD = 0.1; // height above surface to be considered as on the surface
const TRANSITION_COMPLETE = 1000;
const HIFI_PUBLIC_BUCKET = "https://hifi-public.s3.amazonaws.com/";
// constants used by walkApi.js
const MOVE_THRESHOLD = 0.075;
const ACCELERATION_THRESHOLD = 0.2; // detect stop to walking
const DECELERATION_THRESHOLD = -6; // detect walking to stop
const FAST_DECELERATION_THRESHOLD = -150; // detect flying to stop
const BOUNCE_ACCELERATION_THRESHOLD = 25; // used to ignore gravity influence fluctuations after landing
const GRAVITY_THRESHOLD = 3.0; // height above surface where gravity is in effect
const OVERCOME_GRAVITY_SPEED = 0.5; // reaction sensitivity to jumping under gravity
const LANDING_THRESHOLD = 0.35; // metres from a surface below which need to prepare for impact
const MAX_TRANSITION_RECURSION = 10; // how many nested transitions are permitted
// included here to ensure walkApi.js can be used as an API, separate from walk.js
Script.include("./libraries/walkConstants.js");
Avatar = function() {
// if Hydras are connected, the only way to enable use is by never setting any rotations on the arm joints
// if Hydras are connected, the only way to enable use is to never set any arm joint rotation
this.hydraCheck = function() {
// function courtesy of Thijs Wenker (frisbee.js)
var numberOfButtons = Controller.getNumberOfButtons();
@ -75,8 +40,8 @@ Avatar = function() {
// settings
this.headFree = true;
this.armsFree = this.hydraCheck(); // automatically sets true to enable Hydra support - temporary fix
this.makesFootStepSounds = false;
this.isBlenderExport = false; // temporary fix
this.makesFootStepSounds = true;
this.blenderPreRotations = false; // temporary fix
this.animationSet = undefined; // currently just one animation set
this.setAnimationSet = function(animationSet) {
this.animationSet = animationSet;
@ -123,7 +88,7 @@ Avatar = function() {
this.calibration.hipsToFeet = MyAvatar.getJointPosition("Hips").y - MyAvatar.getJointPosition("RightToeBase").y;
// maybe measuring before Blender pre-rotations have been applied?
if (this.calibration.hipsToFeet < 0 && this.isBlenderExport) {
if (this.calibration.hipsToFeet < 0 && this.blenderPreRotations) {
this.calibration.hipsToFeet *= -1;
}
@ -165,7 +130,6 @@ Avatar = function() {
// footsteps
this.nextStep = RIGHT; // the first step is right, because the waveforms say so
this.leftAudioInjector = null;
this.rightAudioInjector = null;
this.makeFootStepSound = function() {
@ -173,16 +137,18 @@ Avatar = function() {
const SPEED_THRESHOLD = 0.4;
const VOLUME_ATTENUATION = 0.8;
const MIN_VOLUME = 0.5;
var volume = Vec3.length(motion.velocity) > SPEED_THRESHOLD ?
VOLUME_ATTENUATION * Vec3.length(motion.velocity) / MAX_WALK_SPEED : MIN_VOLUME;
volume = volume > 1 ? 1 : volume; // occurs when landing at speed - can walk faster than max walking speed
var options = {
position: Vec3.sum(MyAvatar.position, {x:0, y: -this.calibration.hipsToFeet, z:0}),
volume: Vec3.length(motion.velocity) > SPEED_THRESHOLD ?
VOLUME_ATTENUATION * Vec3.length(motion.velocity) / MAX_WALK_SPEED : MIN_VOLUME
volume: volume
};
if (this.nextStep === RIGHT) {
if (this.rightAudioInjector === null) {
this.rightAudioInjector = Audio.playSound(walkAssets.footsteps[0], options);
} else {
//this.rightAudioInjector.setOptions(options);
this.rightAudioInjector.setOptions(options);
this.rightAudioInjector.restart();
}
this.nextStep = LEFT;
@ -190,7 +156,7 @@ Avatar = function() {
if (this.leftAudioInjector === null) {
this.leftAudioInjector = Audio.playSound(walkAssets.footsteps[1], options);
} else {
//this.leftAudioInjector.setOptions(options);
this.leftAudioInjector.setOptions(options);
this.leftAudioInjector.restart();
}
this.nextStep = RIGHT;
@ -200,6 +166,7 @@ Avatar = function() {
// constructor for the Motion object
Motion = function() {
this.isLive = true;
// locomotion status
this.state = STATIC;
this.nextState = STATIC;
@ -212,14 +179,6 @@ Motion = function() {
this.isComingToHalt = false;
this.directedAcceleration = 0;
// settings
this.isLive = true;
this.calibration = {
PITCH_MAX: 60,
ROLL_MAX: 80,
DELTA_YAW_MAX: 1.7
}
// used to make sure at least one step has been taken when transitioning from a walk cycle
this.elapsedFTDegrees = 0;
@ -360,6 +319,7 @@ Motion = function() {
(movingDirectlyUpOrDown && !isOnSurface));
var staticToSurfaceMotion = surfaceMotion && !motion.isComingToHalt && !movingDirectlyUpOrDown &&
!this.isDecelerating && lateralVelocity > MOVE_THRESHOLD;
if (staticToAirMotion) {
this.nextState = AIR_MOTION;
} else if (staticToSurfaceMotion) {
@ -376,6 +336,7 @@ Motion = function() {
var surfaceMotionToAirMotion = (acceleratingAndAirborne || goingTooFastToWalk || movingDirectlyUpOrDown) &&
(!surfaceMotion && isTakingOff) ||
(!surfaceMotion && this.isMoving && !isComingInToLand);
if (surfaceMotionToStatic) {
// working on the assumption that stopping is now inevitable
if (!motion.isComingToHalt && isOnSurface) {
@ -392,6 +353,7 @@ Motion = function() {
case AIR_MOTION:
var airMotionToSurfaceMotion = (surfaceMotion || aboutToLand) && !movingDirectlyUpOrDown;
var airMotionToStatic = !this.isMoving && this.direction === this.lastDirection;
if (airMotionToSurfaceMotion){
this.nextState = SURFACE_MOTION;
} else if (airMotionToStatic) {
@ -492,7 +454,7 @@ animationOperations = (function() {
var joint = animation.joints[jointName];
var jointRotations = {x:0, y:0, z:0};
if (avatar.isBlenderExport) {
if (avatar.blenderPreRotations) {
jointRotations = Vec3.sum(jointRotations, walkAssets.blenderPreRotations.joints[jointName]);
}
@ -670,7 +632,7 @@ TransitionParameters = function() {
this.duration = 0.5;
this.easingLower = {x:0.25, y:0.75};
this.easingUpper = {x:0.75, y:0.25};
this.reachPoseNames = [];
this.reachPoses = [];
}
const QUARTER_CYCLE = 90;
@ -710,8 +672,8 @@ Transition = function(nextAnimation, lastAnimation, lastTransition, playTransiti
walkAssets.getTransitionParameters(lastAnimation, nextAnimation, this.parameters);
// fire up any reach poses for this transition
if (playTransitionReachPoses) {
for (poseName in this.parameters.reachPoseNames) {
this.liveReachPoses.push(new ReachPose(this.parameters.reachPoseNames[poseName]));
for (poseName in this.parameters.reachPoses) {
this.liveReachPoses.push(new ReachPose(this.parameters.reachPoses[poseName]));
}
}
}

View file

@ -0,0 +1,54 @@
//
// walkConstants.js
// version 1.0
//
// Created by David Wooldridge, June 2015
// Copyright © 2015 High Fidelity, Inc.
//
// Provides constants necessary for the operation of the walk.js script and the walkApi.js script
//
// Editing tools for animation data files available here: https://github.com/DaveDubUK/walkTools
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// locomotion states
STATIC = 1;
SURFACE_MOTION = 2;
AIR_MOTION = 4;
// directions
UP = 1;
DOWN = 2;
LEFT = 4;
RIGHT = 8;
FORWARDS = 16;
BACKWARDS = 32;
NONE = 64;
// waveshapes
SAWTOOTH = 1;
TRIANGLE = 2;
SQUARE = 4;
// used by walk.js and walkApi.js
MAX_WALK_SPEED = 2.9; // peak, by observation
MAX_FT_WHEEL_INCREMENT = 25; // avoid fast walk when landing
TOP_SPEED = 300;
ON_SURFACE_THRESHOLD = 0.1; // height above surface to be considered as on the surface
TRANSITION_COMPLETE = 1000;
PITCH_MAX = 60; // maximum speed induced pitch
ROLL_MAX = 80; // maximum speed induced leaning / banking
DELTA_YAW_MAX = 1.7; // maximum change in yaw in rad/s
// used by walkApi.js only
MOVE_THRESHOLD = 0.075; // movement dead zone
ACCELERATION_THRESHOLD = 0.2; // detect stop to walking
DECELERATION_THRESHOLD = -6; // detect walking to stop
FAST_DECELERATION_THRESHOLD = -150; // detect flying to stop
BOUNCE_ACCELERATION_THRESHOLD = 25; // used to ignore gravity influence fluctuations after landing
GRAVITY_THRESHOLD = 3.0; // height above surface where gravity is in effect
OVERCOME_GRAVITY_SPEED = 0.5; // reaction sensitivity to jumping under gravity
LANDING_THRESHOLD = 0.35; // metres from a surface below which need to prepare for impact
MAX_TRANSITION_RECURSION = 10; // how many nested transitions are permitted

View file

@ -2,8 +2,8 @@
// walkFilters.js
// version 1.1
//
// Created by David Wooldridge, Autumn 2014
// Copyright © 2014 - 2015 High Fidelity, Inc.
// Created by David Wooldridge, June 2015
// Copyright © 2014 - 2015 High Fidelity, Inc.
//
// Provides a variety of filters for use by the walk.js script v1.2+
//

View file

@ -3,7 +3,7 @@
// version 0.1
//
// Created by David Wooldridge, June 2015
// Copyright © 2014 - 2015 High Fidelity, Inc.
// Copyright © 2015 High Fidelity, Inc.
//
// Presents settings for walk.js
//
@ -31,7 +31,7 @@ WalkSettings = function() {
function mousePressEvent(event) {
if (Overlays.getOverlayAtPoint(event) === minimisedTab) {
_visible = !_visible;
_webView.setVisible(_visible);
_webWindow.setVisible(_visible);
}
}
Controller.mousePressEvent.connect(mousePressEvent);
@ -55,7 +55,7 @@ WalkSettings = function() {
}
if (_shift && (event.text === 'o' || event.text === 'O')) {
_visible = !_visible;
_webView.setVisible(_visible);
_webWindow.setVisible(_visible);
}
}
function keyReleaseEvent(event) {
@ -67,30 +67,29 @@ WalkSettings = function() {
Controller.keyReleaseEvent.connect(keyReleaseEvent);
// web window
var _url = Script.resolvePath('html/walkSettings.html');
const PANEL_WIDTH = 200;
const PANEL_HEIGHT = 180;
var _webView = new WebWindow('Walk Settings', _url, PANEL_WIDTH, PANEL_HEIGHT, false);
_webView.setVisible(false);
_webView.eventBridge.webEventReceived.connect(function(data) {
var _url = Script.resolvePath('html/walkSettings.html');
var _webWindow = new WebWindow('Walk Settings', _url, PANEL_WIDTH, PANEL_HEIGHT, false);
_webWindow.setVisible(false);
_webWindow.eventBridge.webEventReceived.connect(function(data) {
data = JSON.parse(data);
if (data.type == "init") {
// send the current settings to the window
_webView.eventBridge.emitScriptEvent(JSON.stringify({
_webWindow.eventBridge.emitScriptEvent(JSON.stringify({
type: "update",
armsFree: avatar.armsFree,
footstepSounds: avatar.makesFootStepSounds,
blenderPreRotations: avatar.isBlenderExport
makesFootStepSounds: avatar.makesFootStepSounds,
blenderPreRotations: avatar.blenderPreRotations
}));
} else if (data.type == "powerToggle") {
motion.isLive = !motion.isLive;
} else if (data.type == "update") {
// receive settings from the window
avatar.armsFree = data.armsFree;
avatar.makesFootStepSounds = data.footstepSounds;
avatar.isBlenderExport = data.blenderPreRotations;
avatar.makesFootStepSounds = data.makesFootStepSounds;
avatar.blenderPreRotations = data.blenderPreRotations;
}
});
};

View file

@ -3,7 +3,7 @@
// version 1.25
//
// Created by David Wooldridge, June 2015
// Copyright © 2014 - 2015 High Fidelity, Inc.
// Copyright © 2014 - 2015 High Fidelity, Inc.
//
// Animates an avatar using procedural animation techniques.
//
@ -13,61 +13,25 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// locomotion states
var STATIC = 1;
var SURFACE_MOTION = 2;
var AIR_MOTION = 4;
// directions
var UP = 1;
var DOWN = 2;
var LEFT = 4;
var RIGHT = 8;
var FORWARDS = 16;
var BACKWARDS = 32;
var NONE = 64;
// waveshapes
var SAWTOOTH = 1;
var TRIANGLE = 2;
var SQUARE = 4;
// constants
const MAX_WALK_SPEED = 2.9; // peak, by observation
const MAX_FT_WHEEL_INCREMENT = 25; // avoid fast walk when landing
const TOP_SPEED = 300;
const ON_SURFACE_THRESHOLD = 0.1; // height above surface to be considered as on the surface
const TRANSITION_COMPLETE = 1000;
// animations, reach poses, reach pose parameters, transitions, transition parameters, sounds, image/s and reference files
const HIFI_PUBLIC_BUCKET = "https://hifi-public.s3.amazonaws.com/";
// path to animations, reach-poses, reachPoses, transitions, overlay images and reference files
var pathToAssets = HIFI_PUBLIC_BUCKET + "procedural-animator/assets/";
Script.include([
"./libraries/walkConstants.js",
"./libraries/walkFilters.js",
"./libraries/walkApi.js",
pathToAssets + "walkAssets.js"
]);
// construct Avatar and Motion
// construct Avatar, Motion and (null) Transition
var avatar = new Avatar();
var motion = new Motion();
// create settings dialog
Script.include("./libraries/walkSettings.js");
// create and initialise Transition
var nullTransition = new Transition();
motion.currentTransition = nullTransition;
// motion smoothing / damping filters
var FLY_BLEND_DAMPING = 50;
var leanPitchSmoothingFilter = filter.createButterworthFilter();
var leanRollSmoothingFilter = filter.createButterworthFilter();
var flyUpFilter = filter.createAveragingFilter(FLY_BLEND_DAMPING);
var flyDownFilter = filter.createAveragingFilter(FLY_BLEND_DAMPING);
var flyForwardFilter = filter.createAveragingFilter(FLY_BLEND_DAMPING);
var flyBackwardFilter = filter.createAveragingFilter(FLY_BLEND_DAMPING);
// create settings (gets initial values from avatar)
Script.include("./libraries/walkSettings.js");
// Main loop
Script.update.connect(function(deltaTime) {
@ -80,8 +44,8 @@ Script.update.connect(function(deltaTime) {
// decide which animation should be playing
selectAnimation();
// turn the frequency time wheels and determine stride length
determineStride();
// advance the animation cycle/s by the correct amount/s
advanceAnimations();
// update the progress of any live transitions
updateTransitions();
@ -89,7 +53,7 @@ Script.update.connect(function(deltaTime) {
// apply translation and rotations
renderMotion();
// record this frame's parameters
// save this frame's parameters
motion.saveHistory();
}
});
@ -130,6 +94,13 @@ function setTransition(nextAnimation, playTransitionReachPoses) {
}
}
// fly animation blending: smoothing / damping filters
const FLY_BLEND_DAMPING = 50;
var flyUpFilter = filter.createAveragingFilter(FLY_BLEND_DAMPING);
var flyDownFilter = filter.createAveragingFilter(FLY_BLEND_DAMPING);
var flyForwardFilter = filter.createAveragingFilter(FLY_BLEND_DAMPING);
var flyBackwardFilter = filter.createAveragingFilter(FLY_BLEND_DAMPING);
// select / blend the appropriate animation for the current state of motion
function selectAnimation() {
var playTransitionReachPoses = true;
@ -259,7 +230,7 @@ function selectAnimation() {
}
// determine the length of stride. advance the frequency time wheels. advance frequency time wheels for any live transitions
function determineStride() {
function advanceAnimations() {
var wheelAdvance = 0;
// turn the frequency time wheel
@ -338,7 +309,6 @@ function updateTransitions() {
}
}
}
// update the Transition progress
if (motion.currentTransition.updateProgress() === TRANSITION_COMPLETE) {
motion.currentTransition = nullTransition;
}
@ -346,6 +316,7 @@ function updateTransitions() {
}
// helper function for renderMotion(). calculate the amount to lean forwards (or backwards) based on the avi's velocity
var leanPitchSmoothingFilter = filter.createButterworthFilter();
function getLeanPitch() {
var leanProgress = 0;
@ -356,10 +327,11 @@ function getLeanPitch() {
}
// use filters to shape the walking acceleration response
leanProgress = leanPitchSmoothingFilter.process(leanProgress);
return motion.calibration.PITCH_MAX * leanProgress;
return PITCH_MAX * leanProgress;
}
// helper function for renderMotion(). calculate the angle at which to bank into corners whilst turning
var leanRollSmoothingFilter = filter.createButterworthFilter();
function getLeanRoll() {
var leanRollProgress = 0;
var linearContribution = 0;
@ -368,7 +340,7 @@ function getLeanRoll() {
if (Vec3.length(motion.velocity) > 0) {
linearContribution = (Math.log(Vec3.length(motion.velocity) / TOP_SPEED) + LOG_SCALER) / LOG_SCALER;
}
var angularContribution = Math.abs(motion.yawDelta) / motion.calibration.DELTA_YAW_MAX;
var angularContribution = Math.abs(motion.yawDelta) / DELTA_YAW_MAX;
leanRollProgress = linearContribution;
leanRollProgress *= angularContribution;
// shape the response curve
@ -382,7 +354,7 @@ function getLeanRoll() {
}
// filter progress
leanRollProgress = leanRollSmoothingFilter.process(turnSign * leanRollProgress);
return motion.calibration.ROLL_MAX * leanRollProgress;
return ROLL_MAX * leanRollProgress;
}
// animate the avatar using sine waves, geometric waveforms and harmonic generators