Bläddra i källkod

New mesh.updateVerticesDataDirectly(kind, float32array) to update mesh data directly

David Catuhe 11 år sedan
förälder
incheckning
08f8d5bd30

+ 0 - 368
Babylon/Mesh/Automaton/babylon.automaton.ts

@@ -1,368 +0,0 @@
-module BABYLON {
-    export class Automaton extends Mesh {
-        public  debug = false;
-        private _engine: Engine;
-        private _positionsVBO : WebGLBuffer;
-        private _normalsVBO   : WebGLBuffer;
-        private _positions32F : Float32Array;
-        private _normals32F   : Float32Array;
-        private _shapeKeyGroups = new Array<ShapeKeyGroup>();
-        
-        // for normal processing
-        private _vertexMemberOfFaces = new Array<Array<number>>(); // outer array each vertex, inner array faces vertex is a member of
-        
-        // for passive detection of game pause
-        private _lastResumeTime = 0;
-        private _instancePaused = false;
-
-        // tracking system members
-        private _clockStart = -1;
-        private _renderCPU = 0;
-        private _totalDeformations = 0;
-        private _totalFrames = 0;
-        
-        // pov orientation
-        private _definedFacingForward : boolean = true;
-
-        constructor(name: string, scene: Scene) {
-            super(name, scene);
-            this._engine = scene.getEngine();    
-            
-            // tricky registering a prototype as a callback in constructor; cannot say 'this.beforeRender()' & must be wrappered
-            var ref = this;
-            this.registerBeforeRender(function(){ref.beforeRender();});
-        }
-        // ============================ beforeRender callback & tracking =============================
-        public beforeRender() : void {
-            if (this._positions32F === null || this._normals32F === null || Automaton._systemPaused || this._instancePaused) return;
-            var startTime = Automaton.now();            
-
-            // system resume test 
-            if (this._lastResumeTime < Automaton._systemResumeTime){
-                for (var g = this._shapeKeyGroups.length - 1; g >= 0; g--){
-                    this._shapeKeyGroups[g].resumePlay();
-                }
-                this._lastResumeTime = Automaton._systemResumeTime;
-            }
-
-            var changesMade = false;
-            for (var g = this._shapeKeyGroups.length - 1; g >= 0; g--){               
-                // do NOT combine these 2 lines or only 1 group will run!
-                var changed = this._shapeKeyGroups[g].incrementallyDeform(this._positions32F, this._normals32F);
-                changesMade = changesMade || changed;
-            }
-            
-            if (changesMade){            
-                if (this._clockStart < 0) this._resetTracking(startTime); // delay tracking until the first change is made
-
-                //recompute parts of normals where positions updated & resend
-                this._engine.updateDynamicVertexBuffer(this._normalsVBO, this._normals32F);
-                
-                // resend positions
-                this._engine.updateDynamicVertexBuffer(this._positionsVBO, this._positions32F);
-            
-                this._renderCPU += Automaton.now() - startTime;
-                this._totalDeformations++;  
-            }
-                
-            this._totalFrames ++;
-        }
-        
-        public resetTracking() : void{
-            this._resetTracking(Automaton.now());
-        }
-        private _resetTracking(startTime : number) : void{
-            this._clockStart = startTime;
-            this._renderCPU = 0;
-            this._totalDeformations = 0; 
-            this._totalFrames = 0;           
-        }
-        
-        public getTrackingReport(reset : boolean = false) : string{
-            var totalWallClock = Automaton.now() - this._clockStart;
-            var report =
-                    "\nNum Deformations: " + this._totalDeformations +
-                    "\nRender CPU milli: " + this._renderCPU.toFixed(2) +
-                    "\nRender CPU milli / Deformations: " + (this._renderCPU / this._totalDeformations).toFixed(2) +
-                    "\nWallclock milli / Deformations: " + (totalWallClock / this._totalDeformations).toFixed(2) +
-                    "\nMemo, Deformations / Sec: " + (this._totalDeformations / (totalWallClock / 1000)).toFixed(2) +
-                    "\nMemo, Frames with no deformation: " + (this._totalFrames - this._totalDeformations) +
-                    "\nMemo, Total vertices: " + this.getTotalVertices() +
-                    "\nShape keys:";
-            for (var i = 0; i < this._shapeKeyGroups.length; i++)
-                report += "\n" + this._shapeKeyGroups[i].toString();
-            
-            if (reset) this.resetTracking();
-            return report;    
-        }
-        // ======================================== Overrides ========================================
-        public clone(name: string, newParent: Node, doNotCloneChildren?: boolean): Mesh {
-             alert("Shared vertex instances not supported for Automatons");
-            return null;
-        }
-        public createInstance(name: string): InstancedMesh {
-             alert("Shared vertex instances not supported for Automatons");
-             return null;
-        }
-        public convertToFlatShadedMesh() : void {
-            alert("Flat shading not supported for Automatons");
-        }
-         
-        /* wrappered is so positions & normals vertex buffer & initial data can be captured */
-        public setVerticesData(kind: any, data: any, updatable?: boolean) : void {
-            super.setVerticesData(kind, data, updatable || kind === VertexBuffer.PositionKind || kind === VertexBuffer.NormalKind);
-            
-            var babylonVertexBuffer : VertexBuffer;
-            if (kind === VertexBuffer.PositionKind){
-                babylonVertexBuffer = this.getVertexBuffer(VertexBuffer.PositionKind);
-            
-                this._positionsVBO = babylonVertexBuffer.getBuffer();
-                this._positions32F = new Float32Array(babylonVertexBuffer.getData());
-            }
-            else if (kind === VertexBuffer.NormalKind){
-                babylonVertexBuffer = this.getVertexBuffer(VertexBuffer.NormalKind);
-            
-                this._normalsVBO = babylonVertexBuffer.getBuffer();
-                this._normals32F = new Float32Array(babylonVertexBuffer.getData());
-            }
-        }
-        
-        /** wrappered so this._vertexMemberOfFaces can be built after super.setIndices() called */
-        public setIndices(indices: number[]): void {
-            super.setIndices(indices);
-            
-            // now determine _vertexMemberOfFaces, to improve normals performance
-            var nFaces = indices.length / 3;
-            var faceOffset : number;
-            
-            // _vertexMemberOfFaces:  outer array each vertex, inner array faces vertex is a member of
-            var nVertices = super.getTotalVertices();
-
-            // possibly remove or comment out
-            var nZeroAreaFaces = this.findZeroAreaFaces();
-            if (nZeroAreaFaces > 0) console.warn("Automaton: Zero area faces found:  " + nZeroAreaFaces + ", nFaces: " + nFaces + ", nVert " + nVertices);
-            
-            for (var v = 0; v < nVertices; v++){
-                var memberOf = new Array<number>();
-                
-                for (var f = 0; f < nFaces; f++){
-                    faceOffset = f * 3;
-                    if (indices[faceOffset] === v || indices[faceOffset + 1] === v ||indices[faceOffset + 2] === v){
-                        memberOf.push(f);
-                    }
-                }
-                this._vertexMemberOfFaces.push(memberOf);
-            }       
-        }
-        /** bad things happen to normals when a face has no area.  Double check & put out warning in setIndices() if any found */
-        private findZeroAreaFaces() : number {
-            var indices = super.getIndices();
-            var nFaces = indices.length / 3;
-            var positions = super.getVerticesData(VertexBuffer.PositionKind);
-            var nZeroAreaFaces = 0;
-            var faceOffset : number;
-            var p1 = Vector3.Zero();
-            var p2 = Vector3.Zero();
-            var p3 = Vector3.Zero();
-    
-            for (var f = 0; f < nFaces; f++){
-                faceOffset = f * 3;
-                Vector3.FromArrayToRef(positions, 3 * indices[faceOffset    ], p1);
-                Vector3.FromArrayToRef(positions, 3 * indices[faceOffset + 1], p2);
-                Vector3.FromArrayToRef(positions, 3 * indices[faceOffset + 2], p3);
-                
-                if (p1.equals(p2) || p1.equals(p3) || p2.equals(p3)) nZeroAreaFaces++
-            }
-            return nZeroAreaFaces;
-        }
-        // ==================================== Normals processing ===================================
-        /**
-         * based on http://stackoverflow.com/questions/18519586/calculate-normal-per-vertex-opengl 
-         * @param {Uint16Array} vertices - the vertices which need the normals calculated, so do not have to do the entire mesh
-         * @param {Float32Array} normals - the array to place the results, size:  vertices.length * 3
-         * @param {Float32Array} futurePos - value of positions on which to base normals, passing since so does not have to be set to in mesh yet
-         */
-        public normalsforVerticesInPlace(vertices : Uint16Array, normals : Float32Array, futurePos : Float32Array) : void {
-            var indices = super.getIndices();
-            var nVertices = vertices.length;
-            
-            // Define all the reusable objects outside the for loop, so ..ToRef() & ..InPlace() versions can be used, 
-            // avoiding many single use objects to garbage collect.
-            var memberOfFaces : Array<number>;
-            var nFaces : number;
-            var faceOffset : number;
-            var vertexID : number;
-            var p1 = Vector3.Zero();
-            var p2 = Vector3.Zero();
-            var p3 = Vector3.Zero();
-            var p1p2 = Vector3.Zero();
-            var p3p2 = Vector3.Zero();
-
-            var cross = Vector3.Zero();
-            var normal = Vector3.Zero();
-            var sinAlpha :number;
-            var weightedAvgSum = Vector3.Zero();
-            
-            for (var v = 0; v < nVertices; v++){
-                memberOfFaces = this._vertexMemberOfFaces[vertices[v]];
-                nFaces = memberOfFaces.length;
-                Vector3.FromFloatsToRef(0, 0, 0, weightedAvgSum); // initialize reused vector to all zeros
-                
-                for (var f = 0; f < nFaces; f++){
-                    faceOffset = memberOfFaces[f] * 3;
-                    vertexID = this.indexOfVertInFace(indices[faceOffset], indices[faceOffset + 1], indices[faceOffset + 2], vertices[v]);
-                    if (vertexID === -1) throw "Automaton: vertex not part of face";  // should not happen, but better to check
-                    
-                    // triangleNormalFromVertex() as from example noted above
-                    Vector3.FromFloatArrayToRef(futurePos, 3 * indices[faceOffset +   vertexID], p1);
-                    Vector3.FromFloatArrayToRef(futurePos, 3 * indices[faceOffset + ((vertexID + 1) % 3)], p2);
-                    Vector3.FromFloatArrayToRef(futurePos, 3 * indices[faceOffset + ((vertexID + 2) % 3)], p3);
-                        
-                    p1.subtractToRef(p2, p1p2);
-                    p3.subtractToRef(p2, p3p2);
-                    
-                    Vector3.CrossToRef(p1p2, p3p2, cross);
-                    Vector3.NormalizeToRef(cross, normal);
-                    
-                    sinAlpha = cross.length() / (p1p2.length() * p3p2.length());
-                    
-                    // due floating point, might not be -1 ≤ sinAlpha ≤ 1, e.g. 1.0000000000000002; fix to avoid Math.asin() from returning NaN
-                    if (sinAlpha < -1) sinAlpha = -1;
-                    else if (sinAlpha > 1) sinAlpha = 1;
-                    
-                    normal.scaleInPlace(Math.asin(sinAlpha));                    
-                    weightedAvgSum.addInPlace(normal);
-                }
-                weightedAvgSum.normalize();
-                normals[ v * 3     ] = weightedAvgSum.x;
-                normals[(v * 3) + 1] = weightedAvgSum.y;
-                normals[(v * 3) + 2] = weightedAvgSum.z;
-            }
-        }
-
-        private indexOfVertInFace(idx0 : number, idx1 : number, idx2 : number, vertIdx : number) : number{
-            if (vertIdx === idx0) return 0;
-            if (vertIdx === idx1) return 1;
-            if (vertIdx === idx2) return 2;
-            return -1;
-        }
-        // ================================== ShapeKeyGroup related ==================================
-        public addShapeKeyGroup(shapeKeyGroup : ShapeKeyGroup) : void {
-            this._shapeKeyGroups.push(shapeKeyGroup);
-        }
-            
-        public queueEventSeries(eSeries : AutomatonEventSeries) : void {
-            var groupFound = false;  
-            for (var g = this._shapeKeyGroups.length - 1; g >= 0; g--){
-                if (eSeries.isShapeKeyGroupParticipating(this._shapeKeyGroups[g].getName())){
-                    this._shapeKeyGroups[g].queueEventSeries(eSeries);
-                    groupFound = true;
-                }
-            }
-            if (this.debug && !groupFound) console.warn("no shape keys groups participating in event series");
-        }
-        
-        public getShapeKeyGroup(groupName : string) : ShapeKeyGroup {
-            for (var g = this._shapeKeyGroups.length - 1; g >= 0; g--){
-                if (this._shapeKeyGroups[g].getName() === groupName){
-                    return this._shapeKeyGroups[g];
-                }
-            }
-            return null;
-        }
-        // ================================== Point of View Movement =================================
-        /**
-         * When the mesh is defined facing forward, multipliers must be set so that movePOV() is 
-         * from the point of view of behind the front of the mesh.
-         * @param {boolean} definedFacingForward - True is the default
-         */
-        public setDefinedFacingForward(definedFacingForward : boolean) : void {
-            this._definedFacingForward = definedFacingForward;
-        }
-        
-        /**
-         * Perform relative position change from the point of view of behind the front of the mesh.
-         * This is performed taking into account the meshes current rotation, so you do not have to care.
-         * Supports definition of mesh facing forward or backward.
-         * @param {number} amountRight
-         * @param {number} amountUp
-         * @param {number} amountForward
-         */
-        public movePOV(amountRight : number, amountUp : number, amountForward : number) : void {
-            this.position.addInPlace(this.calcMovePOV(amountRight, amountUp, amountForward));
-        }
-        
-        /**
-         * Calculate relative position change from the point of view of behind the front of the mesh.
-         * This is performed taking into account the meshes current rotation, so you do not have to care.
-         * Supports definition of mesh facing forward or backward.
-         * @param {number} amountRight
-         * @param {number} amountUp
-         * @param {number} amountForward
-         */
-        public calcMovePOV(amountRight : number, amountUp : number, amountForward : number) : Vector3 {
-            var rotMatrix = new Matrix();
-            var rotQuaternion = (this.rotationQuaternion) ? this.rotationQuaternion : Quaternion.RotationYawPitchRoll(this.rotation.y, this.rotation.x, this.rotation.z);
-            rotQuaternion.toRotationMatrix(rotMatrix);
-            
-            var translationDelta = Vector3.Zero();
-            var defForwardMult = this._definedFacingForward ? -1 : 1;
-            Vector3.TransformCoordinatesFromFloatsToRef(amountRight * defForwardMult, amountUp, amountForward * defForwardMult, rotMatrix, translationDelta);
-            return translationDelta;
-        }
-        // ================================== Point of View Rotation =================================
-        /**
-         * Perform relative rotation change from the point of view of behind the front of the mesh.
-         * Supports definition of mesh facing forward or backward.
-         * @param {number} flipBack
-         * @param {number} twirlClockwise
-         * @param {number} tiltRight
-         */
-        public rotatePOV(flipBack : number, twirlClockwise : number, tiltRight : number) : void {
-            this.rotation.addInPlace(this.calcRotatePOV(flipBack, twirlClockwise, tiltRight));
-        }
-        
-        /**
-         * Calculate relative rotation change from the point of view of behind the front of the mesh.
-         * Supports definition of mesh facing forward or backward.
-         * @param {number} flipBack
-         * @param {number} twirlClockwise
-         * @param {number} tiltRight
-         */
-        public calcRotatePOV(flipBack : number, twirlClockwise : number, tiltRight : number) : Vector3 {
-            var defForwardMult = this._definedFacingForward ? 1 : -1;
-            return new Vector3(flipBack * defForwardMult, twirlClockwise, tiltRight * defForwardMult);
-        }
-        // =================================== play - pause system ===================================
-        // pause & resume statics
-        private static _systemPaused = false;
-        private static _systemResumeTime = 0;
-        
-        /** system could be paused at a higher up without notification; just by stop calling beforeRender() */
-        public static pauseSystem(){ Automaton._systemPaused = true; }        
-        public static isSystemPaused() : boolean { return Automaton._systemPaused; }
-        
-        public static resumeSystem(){
-            Automaton._systemPaused = false;
-            Automaton._systemResumeTime = Automaton.now();
-        }
-        
-        // instance level methods
-        public pausePlay(){ this._instancePaused = true; }       
-        public isPaused() : boolean { return this._instancePaused; }
-        
-        public resumePlay(){
-            this._instancePaused = false;
-            this._lastResumeTime = Automaton.now();
-            
-            for (var g = this._shapeKeyGroups.length - 1; g >= 0; g--){
-                this._shapeKeyGroups[g].resumePlay();
-            }
-        }
-        // ========================================= Statics =========================================
-        /** wrapper for window.performance.now, incase not implemented, e.g. Safari */
-        public static now() : number{
-            return (typeof window.performance === "undefined") ? Date.now() : window.performance.now();
-        }
-    }
-}

+ 0 - 185
Babylon/Mesh/Automaton/babylon.automatonEventSeries.ts

@@ -1,185 +0,0 @@
-module BABYLON {
-    /** Internal helper class used by AutomatonEventSeries to support a multi-shape group EventSeries */
-    class ParticipatingGroup{
-        _indexInRun  = -99; // ensure isReady() initially returns false
-        _highestIndexInRun = -1;
-        
-        constructor (public groupName : string) {}
-        public isReady    () : boolean { return this._indexInRun === -1; }
-        public runComplete() : boolean { return this._indexInRun > this._highestIndexInRun; }
-        public activate() : void{
-            this._indexInRun = -1;
-        }
-    }
-    
-    /** Provide an action for an AutomatonEventSeries, for integration into action manager */
-    export class AutomatonEventSeriesAction extends Action{
-        constructor(triggerOptions: any, private _target: Automaton, private _eSeries : AutomatonEventSeries, condition?: Condition) {
-            super(triggerOptions, condition);
-        }
-        public execute(evt: ActionEvent): void {
-            this._target.queueEventSeries(this._eSeries);
-        }
-    }
-
-    /** main class of file */
-    export class AutomatonEventSeries {
-        private _nEvents : number; // events always loop in ascending order; reduces .length calls        
-        private _groups = new Array<ParticipatingGroup>();
-        public  nGroups : number;  // public for ShapeKeyGroup, so it can determine if it the sole sole participating, === 1
-        private _everyBodyReady : boolean;
-        private _repeatCounter : number;
-        private _proRatingThisRepeat;
-        
-        /**
-         * Validate each of the events passed and build unique shapekey groups particpating.
-         * @param {Array} _eventSeries - Elements must either be a ReferenceDeformation, Action, or function.  Min # of Deformations: 1
-         * @param {number} _nRepeats - Number of times to run through series elements.  There is sync across runs. (Default 1)
-         * @param {number} _initialWallclockProrating - The factor to multiply the duration of a Deformation before passing to a
-         *                 ShapeKeyGroup.  Amount is decreased or increased across repeats, so that it is 1 for the final repeat.
-         *                 Facilitates acceleration when > 1, & deceleration when < 1. (Default 1)
-         * @param {string} _debug - Write progress messages to console when true (Default false)
-         */
-        constructor(private _eventSeries : Array<any>, private _nRepeats = 1, private _initialWallclockProrating = 1.0, private _debug = false) {
-            this._nEvents = _eventSeries.length;
-
-            // go through each event in series, building up the unique set shape key groups participating, this._groups
-            for (var i = 0; i < this._nEvents; i++){
-                if (this._eventSeries[i] instanceof ReferenceDeformation || this._eventSeries[i] instanceof Action || typeof this._eventSeries[i] === "function"){
-                    
-                    if (this._eventSeries[i] instanceof ReferenceDeformation){
-                        var groupName = (<ReferenceDeformation> this._eventSeries[i]).shapeKeyGroupName;
-                        var pGroup : ParticipatingGroup = null;
-                    
-                        for (var g = this._groups.length - 1; g >= 0; g--){
-                            if (this._groups[g].groupName === groupName){
-                                pGroup = this._groups[g];               
-                                break;               
-                            }
-                        }
-                        if (pGroup === null){
-                            pGroup = new ParticipatingGroup(groupName);
-                            this._groups.push(pGroup);
-                        } 
-                        pGroup._highestIndexInRun = i;
-                    }
-                    else{
-                        // Actions & function()s all run from group 0 (may not have been assigned yet)
-                        if (this._groups.length > 0) this._groups[0]._highestIndexInRun = i;
-                        if (this._eventSeries[i] instanceof Action) (<Action> this._eventSeries[i])._prepare();
-                    }
-                    
-                }else{
-                     throw "AutomatonEventSeries:  eventSeries elements must either be a Deformation, Action, or function";
-                }
-            }
-            // make sure at least 1 Deformation passed, not just Actions or functions, since there will be no group to assign them to
-            this.nGroups = this._groups.length;
-            if (this.nGroups === 0) throw "AutomatonEventSeries: Must have at least 1 Deformation in series.";
-            
-            if (this._debug && this._nRepeats === 1 && this._initialWallclockProrating !== 1)
-                console.log("AutomatonEventSeries: clock prorating ignored when # of repeats is 1");
-        }
-        
-        /** 
-         * called by Automaton, to figure out which shape key group(s) this should be queued on.
-         * @param {string} groupName - This is the group name to see if it has things to do in event series.
-         */
-        public isShapeKeyGroupParticipating(groupName : string) : boolean{
-            for (var g = 0; g < this.nGroups; g++){
-                if (this._groups[g].groupName === groupName) return true;
-            }
-            return false;
-        }
-        
-        /**
-         * Signals that a ParticipatingGroup is ready to start processing.  Also evaluates if everyBodyReady.
-         * @param {string} groupName - This is the group name saying it is ready.
-         */
-        public activate(groupName : string) : void{
-            this._everyBodyReady = true;
-            for (var g = 0; g < this.nGroups; g++){
-                if (this._groups[g].groupName === groupName) 
-                    this._groups[g].activate();
-                else this._everyBodyReady = this._everyBodyReady && this._groups[g].isReady();
-            }
-            if (this._debug) console.log("series activated by " + groupName + ", _everyBodyReady: " + this._everyBodyReady);
-            this._repeatCounter = 0;
-            this._proRatingThisRepeat = (this._nRepeats > 1) ? this._initialWallclockProrating : 1.0;
-        }
-        
-        /**
-         * Called by a shape key group to know if series is complete.  nextEvent() may still
-         * return null if other groups not yet completed their events in a run, or this group has
-         * no more to do, but is being blocked from starting its next series till all are done here.
-         */
-        public hasMoreEvents(){
-            return this._repeatCounter < this._nRepeats;
-        }
-        
-        /**
-         * Called by a shape key group to get its next event of the series.  Returns null if
-         * blocked, while waiting for other groups.
-         * @param {string} groupName - Name of the group calling for its next event
-         * 
-         */
-        public nextEvent(groupName : string) : any {
-            // return nothing till all groups signal they are ready to start
-            if (!this._everyBodyReady) return null;
-            
-            var pGroup : ParticipatingGroup;
-            var isGroupForActions    = false; // actions are processed on group 0
-            var allGroupsRunComplete = true; 
-            
-            // look up the appropriate ParticipatingGroup for below & set allGroupsRunComplete
-            for (var g = 0; g < this.nGroups; g++){
-                allGroupsRunComplete = allGroupsRunComplete && this._groups[g].runComplete();   
-                         
-                // no break statement inside block, so allGroupsRunComplete is valid
-                if (this._groups[g].groupName === groupName){
-                    pGroup = this._groups[g]; 
-                    isGroupForActions = g === 0;
-                }
-            }
-            
-            if (allGroupsRunComplete){
-                // increment repeat counter, reset for next run unless no more repeats
-                if (++this._repeatCounter < this._nRepeats){
-                    for (var g = 0; g < this.nGroups; g++){
-                        this._groups[g].activate();
-                    }
-                    if (this._initialWallclockProrating !== 1){
-                        this._proRatingThisRepeat = this._initialWallclockProrating + ((1 - this._initialWallclockProrating) * ((this._repeatCounter + 1) / this._nRepeats) );
-                    }
-                    if (this._debug) console.log("set for repeat # " + this._repeatCounter);
-                }else{
-                 if (this._debug) console.log("Series complete");
-                 this._everyBodyReady = false; // ensure that nothing happens until all groups call activate() again
-                }
-            }
-            
-            if (!pGroup.runComplete()){
-                // test if should declare complete
-                if (pGroup._indexInRun === pGroup._highestIndexInRun){
-                    pGroup._indexInRun++;
-                    return null;
-                }
-                for (var i = pGroup._indexInRun + 1; i < this._nEvents; i++){
-                    if (this._eventSeries[i] instanceof ReferenceDeformation){
-                        var name = (<ReferenceDeformation> this._eventSeries[i]).shapeKeyGroupName;
-                        if (pGroup.groupName === name){
-                            pGroup._indexInRun = i;
-                            (<ReferenceDeformation>this._eventSeries[i]).setProratedWallClocks(this._proRatingThisRepeat);
-                            if (this._debug) 
-                                console.log(i + " in series returned: " + name + ", allGroupsRunComplete " + allGroupsRunComplete + ", everyBodyReady " + this._everyBodyReady);
-                            return this._eventSeries[i];
-                        }
-                    }else if (isGroupForActions){
-                        pGroup._indexInRun = i;
-                        return this._eventSeries[i];
-                    }
-                }
-            }else return null; 
-        }
-    }
-}

+ 0 - 22
Babylon/Mesh/Automaton/babylon.deformation.ts

@@ -1,22 +0,0 @@
-module BABYLON {
-    /**
-     * sub-class of ReferenceDeformation, where the referenceStateName is Fixed to "BASIS"
-     */ 
-    export class Deformation extends ReferenceDeformation{
-        /**
-         * @param {string} shapeKeyGroupName -  Used by Automaton to place in the correct ShapeKeyGroup queue(s).
-         * @param {string} endStateName - Name of state key to deform to
-         * @param {number} milliDuration - The number of milli seconds the deformation is to be completed in
-         * @param {number} millisBefore - Fixed wait period, once a syncPartner (if any) is also ready (default 0)
-         * @param {number} endStateRatio - ratio of the end state to be obtained from reference state: -1 (mirror) to 1 (default 1)
-         * @param {Vector3} movePOV - Mesh movement relative to its current position/rotation to be performed at the same time  (default null)
-         *                  right-up-forward
-         * @param {Vector3} rotatePOV - Incremental Mesh rotation to be performed at the same time  (default null)
-         *                  flipBack-twirlClockwise-tiltRight
-         * @param {Pace} pace - Any Object with the function: getCompletionMilestone(currentDurationRatio) (default Pace.LINEAR)
-         */
-        constructor(shapeKeyGroupName : string, endStateName : string, milliDuration : number, millisBefore : number, endStateRatio : number, movePOV : Vector3, rotatePOV : Vector3, pace : Pace){
-            super(shapeKeyGroupName, "BASIS", endStateName, milliDuration, millisBefore, endStateRatio, movePOV, rotatePOV, pace);
-        }   
-    }
-}

+ 0 - 72
Babylon/Mesh/Automaton/babylon.pace.ts

@@ -1,72 +0,0 @@
-module BABYLON {
-    /** 
-     *  Class used to coorelate duration ratio to completion ratio.  Enables Deformations to have
-     *  characteristics like accelation, deceleration, & linear.
-     */    
-    export class Pace {
-        // Constants
-        public static LINEAR = new Pace([1.0], [1.0]);
-
-        // Members
-        public steps : number; 
-        public incremetalCompletionBetweenSteps : Array<number>;
-        public incremetalDurationBetweenSteps   : Array<number>;
-
-        /**
-         * @immutable, reusable
-         * @param {Array} completionRatios - values from (> 0 to 1.0), not required to increase from left to right, for 'hicup' effects
-         * @param {Array} durationRatios - values from (> 0 to 1.0), MUST increase from left to right
-         */
-        constructor(public completionRatios : Array<number>, public durationRatios : Array<number>) {
-            // argument validations for JavaScript
-            if (!(completionRatios instanceof Array) || !(durationRatios instanceof Array)) throw "Pace: ratios not arrays";
-            if (completionRatios.length !== durationRatios.length) throw "Pace: ratio arrays not of equal length";
-
-            if (completionRatios.length === 0) throw "Pace: ratio arrays cannot be empty";
-        
-            var cRatio : number, dRatio : number, prevD : number = -1;
-            for (var i = 0; i < completionRatios.length; i++){
-                cRatio = completionRatios[i];
-                dRatio = durationRatios  [i];
-                if (cRatio <= 0 || dRatio <= 0) throw "Pace: ratios must be > 0";
-                if (cRatio >  1 || dRatio >  1) throw "Pace: ratios must be <= 1";
-                if (prevD >= dRatio) throw "Pace: durationRatios must be in increasing order";
-                prevD = dRatio;
-            }
-            if (cRatio !== 1 || dRatio !== 1) throw "Pace: final ratios must be 1";
-        
-            // public member assignment for all, since immutable
-            this.steps = completionRatios.length;        
-        
-            this.incremetalCompletionBetweenSteps = [completionRatios[0]]; // elements can be negative for 'hicups'
-            this.incremetalDurationBetweenSteps   = [durationRatios  [0]];
-            for (var i = 1; i < this.steps; i++){
-                this.incremetalCompletionBetweenSteps.push(completionRatios[i] - completionRatios[i - 1]);
-                this.incremetalDurationBetweenSteps  .push(durationRatios  [i] - durationRatios  [i - 1]);
-            }       
-            Object.freeze(this);  // make immutable
-        }
-    
-        /**
-         * Determine based on time since beginning,  return what should be ration of completion
-         * @param{number} currentDurationRatio - How much time has elapse / how long it is supposed to take
-         */
-        public getCompletionMilestone(currentDurationRatio : number) : number{
-            // breakout start & running late cases, no need to take into account later
-            if (currentDurationRatio <= 0) return 0;
-            else if (currentDurationRatio >= 1) return 1;
-        
-            var upperIdx = 0;  // ends up being an index into durationRatios, 1 greater than highest obtained
-            for (; upperIdx < this.steps; upperIdx++){
-                if (currentDurationRatio < this.durationRatios[upperIdx]) 
-                    break;
-            }
-
-            var baseCompletion = (upperIdx > 0) ? this.completionRatios[upperIdx - 1] : 0;        
-            var baseDuration   = (upperIdx > 0) ? this.durationRatios  [upperIdx - 1] : 0; 
-            var interStepRatio = (currentDurationRatio - baseDuration) / this.incremetalDurationBetweenSteps[upperIdx];
-        
-            return baseCompletion + (interStepRatio * this.incremetalCompletionBetweenSteps[upperIdx]);
-        }  
-    }    
-}

+ 0 - 160
Babylon/Mesh/Automaton/babylon.referenceDeformation.ts

@@ -1,160 +0,0 @@
-module BABYLON{
-   /**
-    * Class to store Deformation info & evaluate how complete it should be.
-    */
-    export class ReferenceDeformation {
-        private _syncPartner : ReferenceDeformation; // not part of constructor, since cannot be in both partners constructors, use setSyncPartner()
-
-        // time and state management members
-        private _startTime = -1;
-        private _currentDurationRatio = ReferenceDeformation._COMPLETE;
-        
-        // wallclock prorating members, used for acceleration / deceleration across AutomaonEventSeries runs
-        private _proratedMilliDuration : number;
-        private _proratedMillisBefore : number;
-
-        /**
-         * @param {string} shapeKeyGroupName -  Used by Automaton to place in the correct ShapeKeyGroup queue(s).
-         * @param {string} referenceStateName - Name of state key to be used as a reference, so that a endStateRatio can be used
-         * @param {string} endStateName - Name of state key to deform to
-         * @param {number} milliDuration - The number of milli seconds the deformation is to be completed in
-         * @param {number} millisBefore - Fixed wait period, once a syncPartner (if any) is also ready (default 0)
-         * @param {number} endStateRatio - ratio of the end state to be obtained from reference state: -1 (mirror) to 1 (default 1)
-         * @param {Vector3} movePOV - Mesh movement relative to its current position/rotation to be performed at the same time (default null)
-         *                  right-up-forward
-         * @param {Vector3} rotatePOV - Incremental Mesh rotation to be performed at the same time (default null)
-         *                  flipBack-twirlClockwise-tiltRight
-         * @param {Pace} pace - Any Object with the function: getCompletionMilestone(currentDurationRatio) (default Pace.LINEAR)
-         */
-        constructor(
-            public  shapeKeyGroupName   : string, 
-            private _referenceStateName : string, 
-            private _endStateName       : string, 
-            private _milliDuration      : number, 
-            private _millisBefore       : number = 0, 
-            private _endStateRatio      : number = 1, 
-            public  movePOV             : Vector3 = null, 
-            public  rotatePOV           : Vector3 = null,  
-            private _pace               : Pace = Pace.LINEAR)
-        {
-            // argument validations
-            if (this._referenceStateName === this._endStateName) throw "Deformation: reference state cannot be the same as the end state";
-            if (this._milliDuration <= 0) throw "Deformation: milliDuration must > 0";
-            if (this._millisBefore < 0) throw "Deformation: millisBefore cannot be negative";
-            if (this._endStateRatio < -1 || this._endStateRatio > 1) throw "Deformation: endStateRatio range  > -1 and < 1";
-
-            // mixed case group & state names not supported
-            this.shapeKeyGroupName   = this.shapeKeyGroupName  .toUpperCase(); 
-            this._referenceStateName = this._referenceStateName.toUpperCase();
-            this._endStateName       = this._endStateName      .toUpperCase();
-            
-            this.setProratedWallClocks(1); // ensure values actually used for timings are initialized
-        }
-        // =================================== run time processing ===================================    
-        /**
-         * Indicate readiness by caller to start processing event.  
-         * @param {number} lateStartMilli - indication of how far behind already 
-         */
-        public activate(lateStartMilli = 0) : void {
-            this._startTime = Automaton.now();
-            if (lateStartMilli > 0){
-                // apply 20% of the late start or 10% of duration which ever is less
-                lateStartMilli /= 5;
-                this._startTime -= (lateStartMilli < this._milliDuration / 10) ? lateStartMilli : this._milliDuration / 10;
-            }
-            this._currentDurationRatio = (this._syncPartner) ? ReferenceDeformation._BLOCKED : 
-                                         ((this._proratedMillisBefore > 0) ? ReferenceDeformation._WAITING : ReferenceDeformation._READY);
-        }
-    
-        /** called by ShapeKeyGroup.incrementallyDeform() to determine how much of the deformation should be performed right now */
-        public getCompletionMilestone() : number {
-            if (this._currentDurationRatio === ReferenceDeformation._COMPLETE){
-                return ReferenceDeformation._COMPLETE;
-            }
-
-            // BLOCK only occurs when there is a sync partner
-            if (this._currentDurationRatio === ReferenceDeformation._BLOCKED){                
-                // change both to WAITING & start clock, once both are BLOCKED
-                if (this._syncPartner.isBlocked() ){
-                    this._startTime = Automaton.now(); // reset the start clock
-                    this._currentDurationRatio = ReferenceDeformation._WAITING;
-                    this._syncPartner.syncReady(this._startTime);
-                }
-                else return ReferenceDeformation._BLOCKED;
-            }
-        
-            var millisSoFar = Automaton.now() - this._startTime;
-        
-            if (this._currentDurationRatio === ReferenceDeformation._WAITING){
-                millisSoFar -= this._proratedMillisBefore;
-                if (millisSoFar >= 0){
-                    this._startTime = Automaton.now() - millisSoFar;  // prorate start for time served   
-                }
-                else return ReferenceDeformation._WAITING;
-            }
-        
-            this._currentDurationRatio = millisSoFar / this._proratedMilliDuration;
-            if (this._currentDurationRatio > ReferenceDeformation._COMPLETE)
-                this._currentDurationRatio = ReferenceDeformation._COMPLETE;
-        
-            return this._pace.getCompletionMilestone(this._currentDurationRatio);
-        }
-       
-        /** support game pausing / resuming.  There is no need to actively pause a Deformation. */
-        public resumePlay() : void {
-            if (this._currentDurationRatio === ReferenceDeformation._COMPLETE ||
-                this._currentDurationRatio === ReferenceDeformation._BLOCKED  ||
-                this._currentDurationRatio === ReferenceDeformation._COMPLETE) return;
-            
-            // back into a start time which reflects the currentDurationRatio
-            this._startTime = Automaton.now() - (this._proratedMilliDuration * this._currentDurationRatio);            
-        }
-        // =================================== sync partner methods ===================================    
-        /**
-         * @param {Deformation} syncPartner - Deformation which should start at the same time as this one.  MUST be in a different shape key group!
-         */
-        public setSyncPartner(syncPartner : ReferenceDeformation) : void{
-            this._syncPartner = syncPartner;            
-        }
-        /** 
-         *  Called by the first of the syncPartners to detect that both are waiting for each other.
-         *  Only intended to be called from getCompletionMilestone() of the partner.
-         *  @param {number} startTime - passed from partner, so both are in sync as close as possible.
-         */
-        public syncReady(startTime : number) : void{
-            this._startTime = startTime;
-            this._currentDurationRatio = ReferenceDeformation._WAITING;
-        }
-        // ==================================== Getters & setters ====================================    
-        public isBlocked () : boolean { return this._currentDurationRatio === ReferenceDeformation._BLOCKED ; }
-        public isComplete() : boolean { return this._currentDurationRatio === ReferenceDeformation._COMPLETE; }
-       
-        public getReferenceStateName() : string { return this._referenceStateName; }     
-        public getEndStateName() : string { return this._endStateName; }     
-        public getMilliDuration() : number { return this._milliDuration; }      
-        public getMillisBefore() : number { return this._millisBefore; }     
-        public getEndStateRatio() :number {return this._endStateRatio; }
-        public getPace() : Pace {return this._pace; }
-        public getSyncPartner() : ReferenceDeformation{return this._syncPartner; }
-       
-        /**
-         * Called by the Automaton Event Series, before Deformation is passed to the ShapeKeyGroup.  This
-         * is to support acceleration / deceleration across event series repeats.
-         * @param {number} factor - amount to multiply the constructor supplied duration & time before by.
-         */
-        public setProratedWallClocks(factor : number) : void {
-            this._proratedMilliDuration = this._milliDuration * factor;
-            this._proratedMillisBefore = this._millisBefore * factor;
-        }
-        // ========================================== Enums  =========================================    
-        private static _BLOCKED  = -20;
-        private static _WAITING  = -10;
-        private static _READY    =   0;
-        private static _COMPLETE =   1;
-
-        public static get BLOCKED (): number { return ReferenceDeformation._BLOCKED ; }
-        public static get WAITING (): number { return ReferenceDeformation._WAITING ; }
-        public static get READY   (): number { return ReferenceDeformation._READY   ; }
-        public static get COMPLETE(): number { return ReferenceDeformation._COMPLETE; }
-    }
-}

+ 0 - 375
Babylon/Mesh/Automaton/babylon.shapeKeyGroup.ts

@@ -1,375 +0,0 @@
-module BABYLON {
-    export class ShapeKeyGroup {
-        // position elements converted to typed array
-        private _affectedPositionElements : Uint16Array;
-        private _nPosElements : number;
-        
-        // arrays for the storage of each state
-        private _states  = new Array<Float32Array>();
-        private _normals = new Array<Float32Array>();
-        private _stateNames = new Array<string>();      
-
-        // event series queue & reference vars for current seris & step within
-        private _queue = new Array<AutomatonEventSeries>();
-        private _currentSeries : AutomatonEventSeries = null;
-        private _currentStepInSeries : ReferenceDeformation = null;
-        private _endOfLastFrameTs = -1;
-
-        // affected vertices are used for normals, since all the entire vertex is involved, even if only the x of a position is affected
-        private _affectedVertices : Uint16Array;
-        private _nVertices;
-            
-        // reference vars for the current & prior deformation; assigned either an item of (_states / _normals) or one of the reusables
-        private _currFinalPositionVals  : Float32Array; 
-        private _priorFinalPositionVals : Float32Array;
-        private _currFinalNormalVals    : Float32Array;
-        private _priorFinalNormalVals   : Float32Array;
-        
-        // typed arrays are more expense to create, pre-allocate pairs for reuse
-        private _reusablePositionFinals = new Array<Float32Array>();  
-        private _reusableNormalFinals   = new Array<Float32Array>();  
-        private _lastReusablePosUsed  = 0;
-        private _lastReusableNormUsed = 0;
-        
-        // rotation control members
-        private _doingRotation = false;
-        private _rotationStartVec : Vector3;
-        private _rotationEndVec   : Vector3;
-        
-        // position control members
-        private _doingMovePOV = false;
-        private _positionStartVec : Vector3;  // for lerp(ing) when NOT also rotating too
-        private _positionEndVec   : Vector3;  // for lerp(ing) when NOT also rotating too
-        private _fullAmtRight     : number;   // for when also rotating
-        private _fullAmtUp        : number;   // for when also rotating
-        private _fullAmtForward   : number;   // for when also rotating
-        private _amtRightSoFar    : number;   // for when also rotating
-        private _amtUpSoFar       : number;   // for when also rotating
-        private _amtForwardSoFar  : number;   // for when also rotating
-        
-        // misc
-        private _activeLockedCamera : any = null; // any, or would require casting to FreeCamera & no point in JavaScript
-        private _mirrorAxis = -1; // when in use x = 1, y = 2, z = 3
- 
-        /**
-         * @param {Automaton} _automaton - reference of Automaton this ShapeKeyGroup is a part of
-         * @param {String} _name - Name of the Key Group, upper case only
-         * @param {Array} affectedPositionElements - index of either an x, y, or z of positions.  Not all 3 of a vertex need be present.  Ascending order.
-         * @param {Array} basisState - original state of the affectedPositionElements of positions
-         */
-        constructor(private _automaton : Automaton, private _name : string, affectedPositionElements : Array<number>, basisState : Array<number>){
-            if (!(affectedPositionElements instanceof Array) || affectedPositionElements.length === 0                ) throw "ShapeKeyGroup: invalid affectedPositionElements arg";
-            if (!(basisState               instanceof Array) || basisState.length !== affectedPositionElements.length) throw "ShapeKeyGroup: invalid basisState arg";
-
-            // validation that position elements are in ascending order; normals relies on this being true
-            this._affectedPositionElements = new Uint16Array(affectedPositionElements);        
-            this._nPosElements = affectedPositionElements.length;
-            for (var i = 0; i + 1 < this._nPosElements; i++)
-                if (!(this._affectedPositionElements[i] < this._affectedPositionElements[i + 1])) throw "ShapeKeyGroup: affectedPositionElements must be in ascending order";
-            
-            // initialize 2 position reusables, the size needed
-            this._reusablePositionFinals.push(new Float32Array(this._nPosElements));
-            this._reusablePositionFinals.push(new Float32Array(this._nPosElements));
-            
-            // determine affectedVertices for updating cooresponding normals
-            var affectedVert = new Array<number>(); // final size unknown, so use a push-able array & convert to Uint16Array at end
-            var vertIdx  = -1;
-            var nextVertIdx : number;
-            
-            // go through each position element 
-            for (var i = 0; i < this._nPosElements; i++){
-                // the vertex index is 1/3 the position element index
-                nextVertIdx = Math.floor(this._affectedPositionElements[i] / 3);
-                
-                // since position element indexes in ascending order, check if vertex not already added by the x, or y elements
-                if (vertIdx !== nextVertIdx){
-                    vertIdx = nextVertIdx;
-                    affectedVert.push(vertIdx);
-                }
-            }
-            this._affectedVertices = new Uint16Array(affectedVert);
-            this._nVertices = this._affectedVertices.length;
-            
-            // initialize 2 normal reusables, the size needed
-            this._reusableNormalFinals.push(new Float32Array(this._nVertices * 3));
-            this._reusableNormalFinals.push(new Float32Array(this._nVertices * 3));               
-        
-            // push 'BASIS' to _states & _stateNames, then initialize _currFinalVals to 'BASIS' state
-            this.addShapeKey("BASIS", basisState);
-            this._currFinalPositionVals  = this._states [0];       
-            this._currFinalNormalVals    = this._normals[0];   
-        }
-        // =============================== Shape-Key adding & deriving ===============================
-        private getDerivedName(referenceIdx : number, endStateIdx : number, endStateRatio : number) : string{
-            return referenceIdx + "-" + endStateIdx + "@" + endStateRatio;
-        }
-        /**
-         * add a derived key from the data contained in a deformation; wrapper for addDerivedKey()
-         * @param {ReferenceDeformation} deformation - mined for its reference & end state names, and end state ratio
-         */
-        public addDerivedKeyFromDeformation(deformation : ReferenceDeformation) : void{
-            this.addDerivedKey(deformation.getReferenceStateName(), deformation.getEndStateName(), deformation.getEndStateRatio());
-        }
-        
-        /**
-         * add a derived key from the arguments
-         * @param {string} referenceStateName - Name of the reference state to be based on
-         * @param {string} endStateName - Name of the end state to be based on
-         * @param {number} endStateRatio - Unvalidated, but if -1 < or > 1, then can never be called, since Deformation validates
-         */
-        public addDerivedKey(referenceStateName : string, endStateName : string, endStateRatio : number) : void{
-            var referenceIdx = this.getIdxForState(referenceStateName.toUpperCase());
-            var endStateIdx  = this.getIdxForState(endStateName      .toUpperCase());
-            if (referenceIdx === -1 || endStateIdx === -1) throw "ShapeKeyGroup: invalid source state name(s)";
-            if (endStateRatio === 1) throw "ShapeKeyGroup: deriving a shape key where the endStateRatio is 1 is pointless";
-            
-            var stateName = this.getDerivedName(referenceIdx, endStateIdx, endStateRatio);
-            var stateKey  = new Float32Array(this._nPosElements);
-            this.buildPosEndPoint(stateKey, referenceIdx, endStateIdx, endStateRatio);
-            this.addShapeKeyInternal(stateName, stateKey);
-        }
-        
-        /** called in construction code from TOB, but outside the constructor, except for 'BASIS'.  Unlikely to be called by application code. */
-        public addShapeKey(stateName : string, stateKey : Array<number>) : void {
-            if (!(stateKey instanceof Array) || stateKey.length !== this._nPosElements) throw "ShapeKeyGroup: invalid stateKey arg";
-            this.addShapeKeyInternal(stateName, new Float32Array(stateKey) );
-        }
-
-        /** worker method for both the addShapeKey() & addDerivedKey() methods */
-        private addShapeKeyInternal(stateName : string, stateKey : Float32Array) : void {
-            if (typeof stateName !== 'string' || stateName.length === 0) throw "ShapeKeyGroup: invalid stateName arg";
-            if (this.getIdxForState(stateName) !== -1) throw "ShapeKeyGroup: stateName " + stateName + " is a duplicate";
-
-            this._states.push(stateKey);
-            this._stateNames.push(stateName);
-                                
-            var coorespondingNormals = new Float32Array(this._nVertices * 3);
-            this.buildNormEndPoint(coorespondingNormals, stateKey);
-            this._normals.push(coorespondingNormals);
-
-            if (this._automaton.debug) console.log("Shape key: " + stateName + " added to group: " + this._name + " on Automaton: " + this._automaton.name);
-        }
-        // =================================== inside before render ==================================
-        /**
-         * Called by the beforeRender() registered by this._automaton
-         * @param {Float32Array} positions - Array of the positions for the entire mesh, portion updated based on _affectedIndices
-         * @param {Float32Array } normals  - Array of the normals for the entire mesh, if not null, portion updated based on _affectedVertices
-         */
-        public incrementallyDeform(positions : Float32Array, normals :Float32Array) : boolean {
-            // series level of processing; get another series from the queue when none or last is done
-            if (this._currentSeries === null || !this._currentSeries.hasMoreEvents() ){
-                if (! this._nextEventSeries()) return false;
-            }
-            
-            // ok, have an active event series, now get the next deformation in series if required
-            while (this._currentStepInSeries === null || this._currentStepInSeries.isComplete() ){
-                var next : any = this._currentSeries.nextEvent(this._name);
-                
-                if (next === null) return false; // being blocked, this must be a multi-group series, not ready for us
-                if (next instanceof Action){
-                    (<Action> next).execute(ActionEvent.CreateNew(this._automaton));    
-                }
-                else if (typeof next === "function"){
-                    next.call();
-                }
-                else{
-                   this._nextDeformation(<ReferenceDeformation> next);  // must be a new deformation. _currentStepInSeries assigned if valid
-                }  
-            }
-            
-            // have a deformation to process
-            var ratioComplete = this._currentStepInSeries.getCompletionMilestone();
-            if (ratioComplete < 0) return false; // Deformation.BLOCKED or Deformation.WAITING
-        
-            // update the positions
-            for (var i = 0; i < this._nPosElements; i++){
-                positions[this._affectedPositionElements[i]] = this._priorFinalPositionVals[i] + ((this._currFinalPositionVals[i] - this._priorFinalPositionVals[i]) * ratioComplete);
-            }
-            
-            // update the normals
-            var mIdx : number, kIdx : number;
-            for (var i = 0; i < this._nVertices; i++){
-                mIdx = 3 * this._affectedVertices[i] // offset for this vertex in the entire mesh
-                kIdx = 3 * i;                        // offset for this vertex in the shape key group
-                normals[mIdx    ] = this._priorFinalNormalVals[kIdx    ] + ((this._currFinalNormalVals[kIdx    ] - this._priorFinalNormalVals[kIdx    ]) * ratioComplete);
-                normals[mIdx + 1] = this._priorFinalNormalVals[kIdx + 1] + ((this._currFinalNormalVals[kIdx + 1] - this._priorFinalNormalVals[kIdx + 1]) * ratioComplete);
-                normals[mIdx + 2] = this._priorFinalNormalVals[kIdx + 2] + ((this._currFinalNormalVals[kIdx + 2] - this._priorFinalNormalVals[kIdx + 2]) * ratioComplete);
-            }
-            
-            if (this._doingRotation){
-                this._automaton.rotation = BABYLON.Vector3.Lerp(this._rotationStartVec, this._rotationEndVec, ratioComplete);
-            }
-            
-            if (this._doingMovePOV === true){
-                if (this._doingRotation){
-                    // some of these amounts, could be negative, if has a Pace with a hiccup
-                    var amtRight   = (this._fullAmtRight   * ratioComplete) - this._amtRightSoFar;
-                    var amtUp      = (this._fullAmtUp      * ratioComplete) - this._amtUpSoFar;
-                    var amtForward = (this._fullAmtForward * ratioComplete) - this._amtForwardSoFar;
-                    
-                    this._automaton.movePOV(amtRight, amtUp, amtForward);
-                    
-                    this._amtRightSoFar   += amtRight;
-                    this._amtUpSoFar      += amtUp;
-                    this._amtForwardSoFar += amtForward;
-                }else{
-                    this._automaton.position = BABYLON.Vector3.Lerp(this._positionStartVec, this._positionEndVec, ratioComplete);
-                }
-                
-                if (this._activeLockedCamera !== null) this._activeLockedCamera._getViewMatrix();
-            }
-            this._endOfLastFrameTs = Automaton.now();       
-            return true;
-        }
-       
-        public resumePlay() : void {
-            if (this._currentStepInSeries !== null) this._currentStepInSeries.resumePlay();
-        }
-        // ============================ Event Series Queueing & retrieval ============================
-        public queueEventSeries(eSeries : AutomatonEventSeries) :void {
-            this._queue.push(eSeries);
-        }
-    
-        private _nextEventSeries() : boolean {
-            var ret = this._queue.length > 0;
-            if (ret){
-                this._currentSeries = this._queue.shift();
-                this._currentSeries.activate(this._name);
-            }
-            return ret;
-        }
-        // ===================================== deformation prep ====================================    
-        private _nextDeformation(deformation : ReferenceDeformation) : void {
-            // do this as soon as possible to get the clock started, retroactively, when sole group in the series, and within 50 millis of last deform
-            var lateStart = Automaton.now() - this._endOfLastFrameTs;
-            deformation.activate((this._currentSeries.nGroups === 1 && lateStart - this._endOfLastFrameTs < 50) ? lateStart : 0);
-            
-            this._currentStepInSeries = deformation;
-            this._priorFinalPositionVals = this._currFinalPositionVals;
-            this._priorFinalNormalVals   = this._currFinalNormalVals  ;
-            
-            var referenceIdx = this.getIdxForState(deformation.getReferenceStateName() );
-            var endStateIdx  = this.getIdxForState(deformation.getEndStateName      () );
-            if (referenceIdx === -1 || endStateIdx === -1) throw "ShapeKeyGroup " + this._name + ": invalid deformation, source state name(s) not found";
-
-            var endStateRatio = deformation.getEndStateRatio();
-            if (endStateRatio < 0 && this._mirrorAxis === -1) throw "ShapeKeyGroup " + this._name + ": invalid deformation, negative end state ratios when not mirroring";
-           
-            // when endStateRatio is 1 or 0, just assign _currFinalVals directly from _states
-            if (endStateRatio === 1 || endStateRatio === 0){
-                 if (endStateRatio === 0) endStateIdx = referenceIdx; // really just the reference when 0
-                 this._currFinalPositionVals = this._states [endStateIdx];
-                 this._currFinalNormalVals   = this._normals[endStateIdx];
-            }else{
-                // check there was not a pre-built derived key to assign
-                var derivedIdx = this.getIdxForState(this.getDerivedName(referenceIdx, endStateIdx, endStateRatio) );
-                if (derivedIdx !== -1){
-                    this._currFinalPositionVals = this._states [derivedIdx];
-                    this._currFinalNormalVals   = this._normals[derivedIdx];
-                } else{
-                    // need to build _currFinalVals, toggling the _lastReusableUsed
-                    this._lastReusablePosUsed = (this._lastReusablePosUsed === 1) ? 0 : 1;
-                    this.buildPosEndPoint(this._reusablePositionFinals[this._lastReusablePosUsed], referenceIdx, endStateIdx, endStateRatio, this._automaton.debug);
-                    this._currFinalPositionVals = this._reusablePositionFinals[this._lastReusablePosUsed];
-                    
-                    // need to build _currFinalNormalVals, toggling the _lastReusableUsed
-                    this._lastReusableNormUsed = (this._lastReusableNormUsed === 1) ? 0 : 1;
-                    this.buildNormEndPoint(this._reusableNormalFinals[this._lastReusableNormUsed], this._currFinalPositionVals);
-                    this._currFinalNormalVals = this._reusableNormalFinals[this._lastReusableNormUsed];
-                }
-            }
-
-            // prepare for rotation, if deformation calls for
-            this._doingRotation = deformation.rotatePOV !== null;
-            if (this._doingRotation){
-                this._rotationStartVec = this._automaton.rotation; // no clone required, since Lerp() returns a new Vec3 written over .rotation
-                this._rotationEndVec   = this._rotationStartVec.add(this._automaton.calcRotatePOV(deformation.rotatePOV.x, deformation.rotatePOV.y, deformation.rotatePOV.z));
-            }
-            
-            // prepare for POV move, if deformation calls for
-            this._doingMovePOV = deformation.movePOV !== null;
-            if (this._doingMovePOV){
-                this._fullAmtRight   = deformation.movePOV.x; this._amtRightSoFar   = 0;
-                this._fullAmtUp      = deformation.movePOV.y; this._amtUpSoFar      = 0;
-                this._fullAmtForward = deformation.movePOV.z; this._amtForwardSoFar = 0;
-                
-                // less resources to calcMovePOV() once then Lerp(), but calcMovePOV() uses rotation, so can only go fast when not rotating too
-                if (!this._doingRotation){
-                    this._positionStartVec = this._automaton.position; // no clone required, since Lerp() returns a new Vec3 written over .position
-                    this._positionEndVec   = this._positionStartVec.add(this._automaton.calcMovePOV(this._fullAmtRight, this._fullAmtUp, this._fullAmtForward));
-                }
-            }
-            
-            // determine if camera needs to be woke up for tracking
-            this._activeLockedCamera = null; // assigned for failure
-            
-            if (this._doingRotation || this._doingMovePOV){
-                var activeCamera = <any> this._automaton.getScene().activeCamera;
-                if(activeCamera.lockedTarget && activeCamera.lockedTarget === this._automaton)
-                     this._activeLockedCamera = activeCamera;
-            }
-        }
-        /**
-         * Called by addShapeKeyInternal() & _nextDeformation() to build the positions for an end point
-         * @param {Float32Array} targetArray - location of output. One of the _reusablePositionFinals for _nextDeformation().  Bound for: _states[], if addShapeKeyInternal().
-         * @param {number} referenceIdx - the index into _states[] to use as a reference
-         * @param {number} endStateIdx - the index into _states[] to use as a target
-         * @param {number} endStateRatio - the ratio of the target state to achive, relative to the reference state
-         * @param {boolean} log - write console message of action, when true (Default false)
-         * 
-         */
-        private buildPosEndPoint(targetArray : Float32Array, referenceIdx: number, endStateIdx : number, endStateRatio : number, log = false) : void {            
-            var refEndState = this._states[referenceIdx];
-            var newEndState = this._states[endStateIdx];
-            
-            // compute each of the new final values of positions
-            var deltaToRefState : number;
-            for (var i = 0; i < this._nPosElements; i++){
-                deltaToRefState = (newEndState[i] - refEndState[i]) * endStateRatio;
-                
-                // reverse sign on appropriate elements of referenceDelta when ratio neg & mirroring
-                if (endStateRatio < 0 && this._mirrorAxis !== (i + 1) % 3){
-                    deltaToRefState *= -1;
-                }            
-                targetArray[i] = refEndState[i] + deltaToRefState;            
-            }
-            if (log) console.log(this._name + " end Point built for referenceIdx: " + referenceIdx + ",  endStateIdx: " + endStateIdx + ", endStateRatio: " + endStateRatio);
-        }
-        
-        /**
-         * Called by addShapeKeyInternal() & _nextDeformation() to build the normals for an end point
-         * @param {Float32Array} targetArray - location of output. One of the _reusableNormalFinals for _nextDeformation().  Bound for: _normals[], if addShapeKeyInternal().
-         * @param {Float32Array} endStatePos - postion data to build the normals for.  Output from buildPosEndPoint, or data passed in from addShapeKey()
-         */
-        private buildNormEndPoint(targetArray : Float32Array, endStatePos : Float32Array) : void {
-            // build a full, mesh sized, set of positions & populate with the left-over initial data 
-            var futurePos = new Float32Array(this._automaton.getVerticesData(VertexBuffer.PositionKind));
-            
-            // populate the changes that this state has
-            for (var i = 0; i < this._nPosElements; i++){
-                futurePos[this._affectedPositionElements[i]] = endStatePos[i];
-            }
-            
-            // compute using method in _automaton
-            this._automaton.normalsforVerticesInPlace(this._affectedVertices, targetArray, futurePos);
-        }
-        // ==================================== Getters & setters ====================================    
-        private getIdxForState(stateName : string) : number{
-            for (var i = this._stateNames.length - 1; i >= 0; i--){
-                if (this._stateNames[i] === stateName){
-                    return i;
-                }
-            }
-            return -1;
-        }
-
-        public getName() : string { return this._name; }
-        public getNPosElements() : number { return this._nPosElements; }
-        public getNStates() : number { return this._stateNames.length; }
-        public toString() : string { return 'ShapeKeyGroup: ' + this._name + ', n position elements: ' + this._nPosElements + ',\nStates: ' + this._stateNames; }
-       
-        public mirrorAxisOnX() : void {this._mirrorAxis = 1;}
-        public mirrorAxisOnY() : void {this._mirrorAxis = 2;}
-        public mirrorAxisOnZ() : void {this._mirrorAxis = 3;}
-    }
-}

+ 10 - 0
Babylon/Mesh/babylon.geometry.js

@@ -74,6 +74,16 @@ var BABYLON;
             }
         };
 
+        Geometry.prototype.updateVerticesDataDirectly = function (kind, data) {
+            var vertexBuffer = this.getVertexBuffer(kind);
+
+            if (!vertexBuffer) {
+                return;
+            }
+
+            vertexBuffer.updateDirectly(data);
+        };
+
         Geometry.prototype.updateVerticesData = function (kind, data, updateExtends) {
             var vertexBuffer = this.getVertexBuffer(kind);
 

+ 10 - 0
Babylon/Mesh/babylon.geometry.ts

@@ -83,6 +83,16 @@
             }
         }
 
+        public updateVerticesDataDirectly(kind: string, data: Float32Array): void {
+            var vertexBuffer = this.getVertexBuffer(kind);
+
+            if (!vertexBuffer) {
+                return;
+            }
+
+            vertexBuffer.updateDirectly(data);
+        }
+
         public updateVerticesData(kind: string, data: number[], updateExtends?: boolean): void {
             var vertexBuffer = this.getVertexBuffer(kind);
 

+ 12 - 0
Babylon/Mesh/babylon.mesh.js

@@ -212,6 +212,18 @@ var BABYLON;
             }
         };
 
+        Mesh.prototype.updateVerticesDataDirectly = function (kind, data, makeItUnique) {
+            if (!this._geometry) {
+                return;
+            }
+            if (!makeItUnique) {
+                this._geometry.updateVerticesDataDirectly(kind, data);
+            } else {
+                this.makeGeometryUnique();
+                this.updateVerticesDataDirectly(kind, data, false);
+            }
+        };
+
         Mesh.prototype.makeGeometryUnique = function () {
             if (!this._geometry) {
                 return;

+ 13 - 0
Babylon/Mesh/babylon.mesh.ts

@@ -216,6 +216,19 @@
             }
         }
 
+        public updateVerticesDataDirectly(kind: string, data: Float32Array, makeItUnique?: boolean): void {
+            if (!this._geometry) {
+                return;
+            }
+            if (!makeItUnique) {
+                this._geometry.updateVerticesDataDirectly(kind, data);
+            }
+            else {
+                this.makeGeometryUnique();
+                this.updateVerticesDataDirectly(kind, data, false);
+            }
+        }
+
         public makeGeometryUnique() {
             if (!this._geometry) {
                 return;

+ 11 - 0
Babylon/Mesh/babylon.vertexBuffer.js

@@ -85,6 +85,17 @@
             this.create(data);
         };
 
+        VertexBuffer.prototype.updateDirectly = function (data) {
+            if (!this._buffer) {
+                return;
+            }
+
+            if (this._updatable) {
+                this._engine.updateDynamicVertexBuffer(this._buffer, data);
+                this._data = null;
+            }
+        };
+
         VertexBuffer.prototype.dispose = function () {
             if (!this._buffer) {
                 return;

+ 11 - 0
Babylon/Mesh/babylon.vertexBuffer.ts

@@ -94,6 +94,17 @@
             this.create(data);
         }
 
+        public updateDirectly(data: Float32Array): void {
+            if (!this._buffer) {
+                return;
+            }
+
+            if (this._updatable) { // update buffer
+                this._engine.updateDynamicVertexBuffer(this._buffer, data);
+                this._data = null;
+            }
+        }
+
         public dispose(): void {
             if (!this._buffer) {
                 return;

+ 0 - 5
Tools/Gulp/gulpfile.js

@@ -82,11 +82,6 @@ gulp.task('scripts', ['shaders'] ,function() {
       '../../Babylon/Mesh/babylon.InstancedMesh.js',
       '../../Babylon/Mesh/babylon.mesh.js',
       '../../Babylon/Mesh/babylon.subMesh.js',
-      '../../Babylon/Mesh/Automaton/babylon.automaton.js',
-      '../../Babylon/Mesh/Automaton/babylon.referenceDeformation.js',
-      '../../Babylon/Mesh/Automaton/babylon.deformation.js',
-      '../../Babylon/Mesh/Automaton/babylon.pace.js',
-      '../../Babylon/Mesh/Automaton/babylon.shapeKeyGroup.js',
       '../../Babylon/Materials/textures/babylon.baseTexture.js',
       '../../Babylon/Materials/textures/babylon.texture.js',
       '../../Babylon/Materials/textures/babylon.cubeTexture.js',

+ 33 - 0
babylon.1.14-RC-debug.js

@@ -9091,6 +9091,17 @@ var BABYLON;
             this.create(data);
         };
 
+        VertexBuffer.prototype.updateDirectly = function (data) {
+            if (!this._buffer) {
+                return;
+            }
+
+            if (this._updatable) {
+                this._engine.updateDynamicVertexBuffer(this._buffer, data);
+                this._data = null;
+            }
+        };
+
         VertexBuffer.prototype.dispose = function () {
             if (!this._buffer) {
                 return;
@@ -10180,6 +10191,18 @@ var BABYLON;
             }
         };
 
+        Mesh.prototype.updateVerticesDataDirectly = function (kind, data, makeItUnique) {
+            if (!this._geometry) {
+                return;
+            }
+            if (!makeItUnique) {
+                this._geometry.updateVerticesDataDirectly(kind, data);
+            } else {
+                this.makeGeometryUnique();
+                this.updateVerticesDataDirectly(kind, data, false);
+            }
+        };
+
         Mesh.prototype.makeGeometryUnique = function () {
             if (!this._geometry) {
                 return;
@@ -24038,6 +24061,16 @@ var BABYLON;
             }
         };
 
+        Geometry.prototype.updateVerticesDataDirectly = function (kind, data) {
+            var vertexBuffer = this.getVertexBuffer(kind);
+
+            if (!vertexBuffer) {
+                return;
+            }
+
+            vertexBuffer.updateDirectly(data);
+        };
+
         Geometry.prototype.updateVerticesData = function (kind, data, updateExtends) {
             var vertexBuffer = this.getVertexBuffer(kind);
 

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 7 - 7
babylon.1.14-RC.js


+ 3 - 0
babylon.d.ts

@@ -2274,6 +2274,7 @@ declare module BABYLON {
         public isReady(): boolean;
         public setAllVerticesData(vertexData: VertexData, updatable?: boolean): void;
         public setVerticesData(kind: string, data: number[], updatable?: boolean): void;
+        public updateVerticesDataDirectly(kind: string, data: Float32Array): void;
         public updateVerticesData(kind: string, data: number[], updateExtends?: boolean): void;
         public getTotalVertices(): number;
         public getVerticesData(kind: string): number[];
@@ -2481,6 +2482,7 @@ declare module BABYLON {
         public subdivide(count: number): void;
         public setVerticesData(kind: any, data: any, updatable?: boolean): void;
         public updateVerticesData(kind: string, data: number[], updateExtends?: boolean, makeItUnique?: boolean): void;
+        public updateVerticesDataDirectly(kind: string, data: Float32Array, makeItUnique?: boolean): void;
         public makeGeometryUnique(): void;
         public setIndices(indices: number[]): void;
         public _bind(subMesh: SubMesh, effect: Effect, wireframe?: boolean): void;
@@ -2634,6 +2636,7 @@ declare module BABYLON {
         public getStrideSize(): number;
         public create(data?: number[]): void;
         public update(data: number[]): void;
+        public updateDirectly(data: Float32Array): void;
         public dispose(): void;
         private static _PositionKind;
         private static _NormalKind;