# Copyright 2012 United States Government, as represented by the Secretary of Defense, Under # Secretary of Defense (Personnel & Readiness). # # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except # in compliance with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software distributed under the License # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express # or implied. See the License for the specific language governing permissions and limitations under # the License. ## @name node3.animation.vwf ## @namespace --- extends: http://vwf.example.com/animation/animation.vwf methods: animationUpdate: parameters: - time - duration ## Translate by given translation over duration. ## ## @name node3.animation.vwf#translateBy ## @function ## ## @param {Array} translation ## @param {Number} duration ## ## @returns undefined translateBy: parameters: - translation - duration body: | this.startTranslation$ = this.translation || goog.vec.Vec3.create(); var deltaTranslation = this.translationFromValue( translation ); this.stopTranslation$ = goog.vec.Vec3.add( this.startTranslation$, deltaTranslation, goog.vec.Vec3.create() ); if(duration > 0) { this.animationDuration = duration; this.animationUpdate = function(time, duration) { this.translation = goog.vec.Vec3.lerp( this.startTranslation$, this.stopTranslation$, time >= duration ? 1 : time / duration, goog.vec.Vec3.create() ); } this.animationPlay(0, duration); } else { this.translation = this.stopTranslation$; } //@ sourceURL=node3.animation.translateBy.vwf ## Translate to given translation over duration. ## ## @name node3.animation.vwf#translateTo ## @function ## ## @param {Array} translation ## @param {Number} duration ## ## @returns undefined translateTo: parameters: - translation - duration body: | this.startTranslation$ = this.translation || goog.vec.Vec3.create(); this.stopTranslation$ = this.translationFromValue( translation ); if(duration > 0) { this.animationDuration = duration; this.animationUpdate = function(time, duration) { this.translation = goog.vec.Vec3.lerp( this.startTranslation$, this.stopTranslation$, duration == 0 ? duration : time / duration, goog.vec.Vec3.create() ); } this.animationPlay(0, duration); } else { this.translation = this.stopTranslation$; } //@ sourceURL=node3.animation.translateTo.vwf ## Rotate by given rotation over duration. ## ## @name node3.animation.vwf#rotateBy ## @function ## ## @param {Array} rotation ## @param {Number} [duration] ## @param {String} [frame] ## ## @returns undefined rotateBy: parameters: - rotation - duration - frame body: | var rotation = this.rotationFromValue( rotation ); var deltaQuaternion = goog.vec.Quaternion.fromAngleAxis( rotation[3] * Math.PI / 180, goog.vec.Vec3.createFromValues( rotation[0], rotation[1], rotation[2] ), goog.vec.Quaternion.create() ); this.quaterniateBy( deltaQuaternion, duration, frame ); //@ sourceURL=node3.animation.rotateBy.vwf ## Rotate to given rotation over duration. ## ## @name node3.animation.vwf#rotateTo ## @function ## ## @param {Array} rotation ## @param {Number} duration ## ## @returns undefined rotateTo: parameters: - rotation - duration body: | var rotation = this.rotationFromValue( rotation ); var stopQuaternion = goog.vec.Quaternion.fromAngleAxis( rotation[3] * Math.PI / 180, goog.vec.Vec3.createFromValues( rotation[0], rotation[1], rotation[2] ), goog.vec.Quaternion.create() ); this.quaterniateTo( stopQuaternion, duration ); //@ sourceURL=node3.animation.rotateTo.vwf ## Rotate by given quaternion over duration. ## ## @name node3.animation.vwf#quaterniateBy ## @function ## ## @param {Array} quaternion ## @param {Number} [duration] ## @param {String} [frame] ## ## @returns undefined quaterniateBy: parameters: - quaternion - duration - frame body: | this.startQuaternion$ = this.quaternion || goog.vec.Quaternion.createFromValues( 0, 0, 0, 1 ); var deltaQuaternion = this.quaternionFromValue( quaternion ); if ( ! frame || frame == "rotated" ) { this.stopQuaternion$ = goog.vec.Quaternion.concat( deltaQuaternion, this.startQuaternion$, goog.vec.Quaternion.create() ); } else if ( frame == "scaled" ) { this.stopQuaternion$ = goog.vec.Quaternion.concat( this.startQuaternion$, deltaQuaternion, goog.vec.Quaternion.create() ); } if(duration > 0) { this.animationDuration = duration; this.animationUpdate = function(time, duration) { this.quaternion = goog.vec.Quaternion.slerp( this.startQuaternion$, this.stopQuaternion$, time >= duration ? 1 : time / duration, goog.vec.Quaternion.create() ); } this.animationPlay(0, duration); } else { this.quaternion = this.stopQuaternion$; } //@ sourceURL=node3.animation.quaterniateBy.vwf ## Rotate to given quaternion over duration. ## ## @name node3.animation.vwf#quaterniateTo ## @function ## ## @param {Array} quaternion ## @param {Number} duration ## ## @returns undefined quaterniateTo: parameters: - quaternion - duration body: | this.startQuaternion$ = this.quaternion || goog.vec.Quaternion.createFromValues( 0, 0, 0, 1 ); this.stopQuaternion$ = this.quaternionFromValue( quaternion ); if(duration > 0) { this.animationDuration = duration; this.animationUpdate = function(time, duration) { this.quaternion = goog.vec.Quaternion.slerp( this.startQuaternion$, this.stopQuaternion$, duration == 0 ? duration : time / duration, goog.vec.Quaternion.create() ); } this.animationPlay(0, duration); } else { this.quaternion = this.stopQuaternion$; } //@ sourceURL=node3.animation.quaterniateTo.vwf ## Scale by given scale over duration. ## ## @name node3.animation.vwf#scaleBy ## @function ## ## @param {Array} scale ## @param {Number} duration ## ## @returns undefined scaleBy: parameters: - scale - duration body: | this.startScale$ = this.scale || goog.vec.Vec3.createFromValues( 1, 1, 1 ); var deltaScale = this.scaleFromValue( scale ); this.stopScale$ = goog.vec.Vec3.createFromValues( this.startScale$[0] * deltaScale[0], this.startScale$[1] * deltaScale[1], this.startScale$[2] * deltaScale[2] ); if(duration > 0) { this.animationDuration = duration; this.animationUpdate = function(time, duration) { this.scale = goog.vec.Vec3.lerp( // TODO: should be geometric interpolation this.startScale$, this.stopScale$, duration == 0 ? duration : time / duration, goog.vec.Vec3.create() ); } this.animationPlay(0, duration); } else { this.scale = this.stopScale$; } //@ sourceURL=node3.animation.scaleBy.vwf ## Scale to given scale over duration. ## ## @name node3.animation.vwf#scaleTo ## @function ## ## @param {Array} scale ## @param {Number} duration ## ## @returns undefined scaleTo: parameters: - scale - duration body: | this.startScale$ = this.scale || goog.vec.Vec3.createFromValues( 1, 1, 1 ); this.stopScale$ = this.scaleFromValue( scale ); if(duration > 0) { this.animationDuration = duration; this.animationUpdate = function(time, duration) { this.scale = goog.vec.Vec3.lerp( // TODO: should be geometric interpolation this.startScale$, this.stopScale$, duration == 0 ? duration : time / duration, goog.vec.Vec3.create() ); } this.animationPlay(0, duration); } else { this.scale = this.stopScale$; }//@ sourceURL=node3.animation.scaleTo.vwf ## Transform by the given amount over duration. ## ## @name node3.animation.vwf#transformBy ## @function ## ## @param {Array} transform ## @param {Number} duration ## ## @returns undefined transformBy: parameters: - transform - duration body: | var startTransform = this.transform || goog.vec.Vec3.create(); var deltaTransform = this.transformFromValue( transform ); // Left multiply by the delta var stopTransform = goog.vec.Mat4.multMat( deltaTransform, startTransform, goog.vec.Mat4.createFloat32() ); this.transformTo( stopTransform, duration ); //@ sourceURL=node3.animation.transformBy.vwf ## Transform to given transform over duration. ## ## @name node3.animation.vwf#transformTo ## @function ## ## @param {Array} transform ## @param {Number} duration ## ## @returns undefined transformTo: parameters: - transform - duration body: | var stopTransform = this.transformFromValue( transform ) || goog.vec.Mat4.createIdentity(); if ( duration > 0 ) { // Calculate the start and stop translations this.startTranslation$ = this.translation || goog.vec.Vec3.create(); this.stopTranslation$ = goog.vec.Vec3.create(); goog.vec.Mat4.getColumn( stopTransform, 3, this.stopTranslation$ ); // Calculate the start and stop quaternion and scale this.startScale$ = this.scale || goog.vec.Vec3.createFromValues( 1, 1, 1 ); this.stopScale$ = goog.vec.Vec3.create(); this.startQuaternion$ = this.quaternion || goog.vec.Quaternion.createFromValues( 0, 0, 0, 1 ); this.stopQuaternion$ = goog.vec.Quaternion.fromRotationMatrix4( this.unscaledTransform( stopTransform || goog.vec.Mat4.createIdentity(), this.stopScale$, goog.vec.Mat4.create() ), goog.vec.Quaternion.create() ); this.animationDuration = duration; // Call the appropriate functions to do the translation and quaterniation (that is totally a word) this.animationUpdate = function(time, duration) { this.translation = goog.vec.Vec3.lerp( this.startTranslation$, this.stopTranslation$, duration == 0 ? duration : time / duration, goog.vec.Vec3.create() ); this.quaternion = goog.vec.Quaternion.slerp( this.startQuaternion$, this.stopQuaternion$, duration == 0 ? duration : time / duration, goog.vec.Quaternion.create() ); this.scale = goog.vec.Vec3.lerp( // TODO: should be geometric interpolation this.startScale$, this.stopScale$, duration == 0 ? duration : time / duration, goog.vec.Vec3.create() ); } this.animationPlay(0, duration); } else { this.transform = stopTransform; } //@ sourceURL=node3.animation.transformTo.vwf ## Transform the world transform by the given amount over duration. ## ## @name node3.animation.vwf#worldTransformBy ## @function ## ## @param {Array} transform ## @param {Number} duration ## ## @returns undefined worldTransformBy: parameters: - transform - duration body: | var startWorldTransform = this.worldTransform || goog.vec.Mat4.create(); var deltaTransform = this.transformFromValue( transform ); // Left multiply by the delta var stopWorldTransform = goog.vec.Mat4.multMat( deltaTransform, startWorldTransform, goog.vec.Mat4.createFloat32() ); this.worldTransformTo( stopWorldTransform, duration ) //@ sourceURL=node3.animation.worldTransformBy.vwf ## Transform the world transform to given transform over duration. ## ## @name node3.animation.vwf#worldTransformTo ## @function ## ## @param {Array} transform ## @param {Number} duration ## ## @returns undefined worldTransformTo: parameters: - transform - duration body: | var stopWorldTransform = this.transformFromValue( transform ); var stopTransform; if ( this.parent && this.parent.worldTransform ) { // We need to find the local transform that will bring about the desired world transform // The math for this looks like - // (new worldTransform) = (parentWorldTransform) * (transform) // So, if we left multiply both sides by the inverse of the parentWorldTransform... // inv(parentWorldTransform) * (new worldTransform) = (transform) // Find the inverse parent worldTransform var inverseParentWorldTransform = goog.vec.Mat4.createFloat32(); if ( goog.vec.Mat4.invert( this.parent.worldTransform, inverseParentWorldTransform ) ) { // Left multiply the new worldTransform by the inverse parent worldTransform stopTransform = goog.vec.Mat4.multMat( inverseParentWorldTransform, stopWorldTransform, goog.vec.Mat4.createFloat32() ); } else { stopTransform = goog.vec.Mat4.createIdentity(); this.logger.error( "Parent '" + this.parent.id + "' transform matrix is not invertible: " + this.parent.transform ); } } else { stopTransform = stopWorldTransform; } this.transformTo( stopTransform, duration ); //@ sourceURL=node3.animation.worldTransformTo.vwf event: changingTransformFromView: