From aac8b5616c5e88ec32ce39837bc5b16f6659b0a0 Mon Sep 17 00:00:00 2001 From: David Easter Date: Wed, 28 Jan 2015 21:30:02 -0500 Subject: [PATCH 01/21] Handle reflector actions as they arrive, without waiting for a tick. There isn't any reason to delay execution. `kernel.tick` is still called exactly once per reflector tick. Also, don't bother advancing time after the last authorized action. Nothing executes at that time if it is between actions, so nothing will see it. This is in preparation for keeping tick messages out of the queue. --- support/client/lib/vwf.js | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/support/client/lib/vwf.js b/support/client/lib/vwf.js index 36e3e758a..3992d43ba 100644 --- a/support/client/lib/vwf.js +++ b/support/client/lib/vwf.js @@ -951,7 +951,7 @@ // Update the queue. Messages in the queue are ordered by time, then by order of arrival. // Time is only advanced if the message has no action, meaning it is a tick. - queue.insert( fields, !fields.action ); // may invoke dispatch(), so call last before returning to the host + queue.insert( fields, true ); // may invoke dispatch(), so call last before returning to the host // Each message from the server allows us to move time forward. Parse the // timestamp from the message and call dispatch() to execute all queued @@ -1238,20 +1238,7 @@ this.client_ = fields.client; // ... and note the originating client this.receive( fields.node, fields.action, fields.member, fields.parameters, fields.respond, fields.origin ); } - else { - this.tick(); - } - - } - // Advance time to the most recent time received from the server. Tick if the time - // changed. - - if ( queue.ready() && this.now != queue.time ) { - this.sequence_ = undefined; // clear after the previous action - this.client_ = undefined; // clear after the previous action - this.now = queue.time; - this.tock(); } }; @@ -6868,6 +6855,10 @@ if ( ! childComponent.source ) { } ); + if ( ! fields.action ) { + vwf.tick(); + } + // Execute the simulation through the new time. // To prevent actions from executing out of order, callers should immediately return From 41229c12bdb2a534f5f6a6ff1a653d09b1ea1215 Mon Sep 17 00:00:00 2001 From: David Easter Date: Wed, 28 Jan 2015 21:40:46 -0500 Subject: [PATCH 02/21] Don't record ticks in the queue. Don't tick nodes and model drivers. If the model sees individual tick messages, then unexecuted ticks are part of the application state. All ticks must pass through the message queue, and unexecuted ticks must be included in the replication and persistence data. This adds unnecessary bulk to the state data and can increase buffer delays during poor network conditions. It also prevents the reflector from ticking clients on slower networks at a slower rate. This commit interprets reflector ticks only as authorization to move kernel time forward. Ticks are no longer placed in the queue. `model.ticking` is no longer called on model drivers, and `node.tick` is no longer called for nodes providing a `tick` function. `view.ticked` is still called for view drivers since views don't affect the application state. View ticks are still called exactly once per reflector tick message. Nodes and model drivers that make use of tick messages will need to be updated. If necessary, the kernel may be able to insert `future` calls to provide backward compatability. --- support/client/lib/vwf.js | 76 +++++++++++++++------------------------ 1 file changed, 28 insertions(+), 48 deletions(-) diff --git a/support/client/lib/vwf.js b/support/client/lib/vwf.js index 3992d43ba..1d1863b61 100644 --- a/support/client/lib/vwf.js +++ b/support/client/lib/vwf.js @@ -194,18 +194,6 @@ this.moniker_ = undefined; - /// Nodes that are receiving ticks. - /// - /// @name module:vwf.tickable - /// - /// @private - - this.tickable = { - // models: [], - // views: [], - nodeIDs: [], - }; - // == Private variables ==================================================================== /// @name module:vwf.private @@ -948,8 +936,9 @@ fields.origin = "reflector"; - // Update the queue. Messages in the queue are ordered by time, then by order of arrival. - // Time is only advanced if the message has no action, meaning it is a tick. + // Update the queue. Insert the message (unless it is only a time tick), and + // advance the queue's record of the current time. Messages in the queue are + // ordered by time, then by order of arrival. queue.insert( fields, true ); // may invoke dispatch(), so call last before returning to the host @@ -1224,20 +1213,19 @@ // Advance time to the message time. - if ( this.now != fields.time ) { - this.sequence_ = undefined; // clear after the previous action - this.client_ = undefined; // clear after the previous action + if ( this.now !== fields.time ) { this.now = fields.time; this.tock(); } + // Set the per-action kernel globals. + + this.sequence_ = fields.sequence; // note the message's queue sequence number for the duration of the action + this.client_ = fields.client; // ... and note the originating client + // Perform the action. - if ( fields.action ) { // TODO: don't put ticks on the queue but just use them to fast-forward to the current time (requires removing support for passing ticks to the drivers and nodes) - this.sequence_ = fields.sequence; // note the message's queue sequence number for the duration of the action - this.client_ = fields.client; // ... and note the originating client - this.receive( fields.node, fields.action, fields.member, fields.parameters, fields.respond, fields.origin ); - } + this.receive( fields.node, fields.action, fields.member, fields.parameters, fields.respond, fields.origin ); } @@ -1266,24 +1254,12 @@ this.tick = function() { - // Call ticking() on each model. - - this.models.forEach( function( model ) { - model.ticking && model.ticking( this.now ); // TODO: maintain a list of tickable models and only call those - }, this ); - // Call ticked() on each view. this.views.forEach( function( view ) { view.ticked && view.ticked( this.now ); // TODO: maintain a list of tickable views and only call those }, this ); - // Call tick() on each tickable node. - - this.tickable.nodeIDs.forEach( function( nodeID ) { - this.callMethod( nodeID, "tick", [ this.now ] ); - }, this ); - }; // -- tock --------------------------------------------------------------------------------- @@ -2695,13 +2671,8 @@ if ( ! childComponent.source ) { vwf.setProperty( childID, propertyName, deferredInitializations[propertyName] ); } ); - // TODO: Adding the node to the tickable list here if it contains a tick() function in JavaScript at initialization time. Replace with better control of ticks on/off and the interval by the node. - - if ( vwf.execute( childID, "Boolean( this.tick )" ) ) { - vwf.tickable.nodeIDs.push( childID ); - } - // Restore kernel reentry. + replicating && vwf.models.kernel.enable(); }, function() { @@ -5387,7 +5358,7 @@ if ( ! childComponent.source ) { // reinserted. return object.filter( function( fields ) { - return ! ( fields.origin === "reflector" && fields.sequence > vwf.sequence_ ) && fields.action; // TODO: fields.action is here to filter out tick messages // TODO: don't put ticks on the queue but just use them to fast-forward to the current time (requires removing support for passing ticks to the drivers and nodes) + return ! ( fields.origin === "reflector" && fields.sequence > vwf.sequence_ ); } ).sort( function( fieldsA, fieldsB ) { return fieldsA.sequence - fieldsB.sequence; } ); @@ -5395,8 +5366,8 @@ if ( ! childComponent.source ) { } else if ( depth == 1 ) { // Remove the sequence fields since they're just local annotations used to keep - // messages ordered by insertion order and aren't directly meaniful outside of this - // client. + // messages ordered by insertion order. They aren't directly meaningful outside of + // this client. var filtered = {}; @@ -6819,12 +6790,10 @@ if ( ! childComponent.source ) { messages.forEach( function( fields ) { - // if ( fields.action ) { // TODO: don't put ticks on the queue but just use them to fast-forward to the current time (requires removing support for passing ticks to the drivers and nodes) - + if ( fields.action ) { fields.sequence = ++this.sequence; // track the insertion order for use as a sort key this.queue.push( fields ); - - // } + } if ( chronic ) { this.time = Math.max( this.time, fields.time ); // save the latest allowed time for suspend/resume @@ -6855,8 +6824,19 @@ if ( ! childComponent.source ) { } ); - if ( ! fields.action ) { + // Tick the views on each idle message. + + if ( chronic && ! fields.action ) { + + // Clear the per-action kernel globals. `tick` isn't an action. + + vwf.sequence_ = undefined; + vwf.client_ = undefined; + + // Tick the views. + vwf.tick(); + } // Execute the simulation through the new time. From e5898aafdbae65197e56a9a80fd2f75073e556c1 Mon Sep 17 00:00:00 2001 From: Rob Chadwick Date: Mon, 9 Feb 2015 16:53:43 -0500 Subject: [PATCH 03/21] first merge test --- support/client/lib/vwf/view/threejs.js | 101 +++++++++++++++++++------ 1 file changed, 78 insertions(+), 23 deletions(-) diff --git a/support/client/lib/vwf/view/threejs.js b/support/client/lib/vwf/view/threejs.js index ff60f2c51..10bb51c3d 100644 --- a/support/client/lib/vwf/view/threejs.js +++ b/support/client/lib/vwf/view/threejs.js @@ -1020,41 +1020,96 @@ define( [ "module", var interp = goog.vec.Mat4.clone(self.state.nodes[id].threeObject.matrix.elements); return interp; } + function getAnimationFrame(id) { + var interp = vwf.getProperty(id,'animationFrame'); + return interp; + } function setTransform(id,interp) { interp = goog.vec.Mat4.clone(interp) self.state.nodes[id].threeObject.matrix.elements = interp; self.state.nodes[id].threeObject.updateMatrixWorld(true); } function setInterpolatedTransforms(deltaTime) { - var step = (self.tickTime) / (self.realTickDif); - step = Math.min(step,1); - deltaTime = Math.min(deltaTime, self.realTickDif) - self.tickTime += deltaTime || 0; - - for(var nodeID in self.nodes) { - var last = self.nodes[nodeID].lastTickTransform; - var now = self.nodes[nodeID].selfTickTransform; - if(last && now && !matCmp(last,now,.0001) ) { - var interp = matrixLerp(last, now, step || 0); - - var objectIsControlledByUser = ( ( navmode !== "none" ) && - ( ( navObject && ( nodeID === navObject.ID ) ) || - ( cameraNode && ( nodeID === cameraNode.ID ) ) ) ); - if ( !objectIsControlledByUser ) { - setTransform(nodeID, interp); - self.nodes[nodeID].needTransformRestore = true; + this.tickTime += deltaTime || 0; + var hit = 0; + while (this.tickTime > 50) { + hit++; + this.tickTime -= 50; + } + var step = (this.tickTime) / (50); + if (hit === 1) { + + var keys = Object.keys(this.nodes); + + for (var j = 0; j < keys.length; j++) { + var i = keys[j]; + if (this.nodes[i].lastTransformStep + 1 < vwf.time()) { + this.nodes[i].lastTickTransform = null; + this.nodes[i].lastFrameInterp = null; + this.nodes[i].thisTickTransform = null; + } else if (this.state.nodes[i]) { + this.nodes[i].lastTickTransform = matset(this.nodes[i].lastTickTransform, this.nodes[i].thisTickTransform); + this.nodes[i].thisTickTransform = matset(this.nodes[i].thisTickTransform, getTransform(i)); + } + if (this.state.nodes[i]) { + this.nodes[i].lastAnimationFrame = this.nodes[i].thisAnimationFrame; + this.nodes[i].thisAnimationFrame = getAnimationFrame(i); } } } + + var lerpStep = Math.min(1, .2 * (deltaTime / 16.6)); //the slower the frames ,the more we have to move per frame. Should feel the same at 60 0r 20 + var keys = Object.keys(this.nodes); + var interp = null; + for (var j = 0; j < keys.length; j++) { + var i = keys[j]; + + var last = this.nodes[i].lastTickTransform; + var now = this.nodes[i].thisTickTransform; + if (last && now) { + + interp = matset(interp, last); + interp = this.matrixLerp(last, now, step, interp); + + this.nodes[i].currentTickTransform = matset(this.nodes[i].currentTickTransform, getTransform(i)); + + if (this.nodes[i].lastFrameInterp) + interp = this.matrixLerp(this.nodes[i].lastFrameInterp, now, lerpStep, interp); + setTransform(i,interp); + this.nodes[i].lastFrameInterp = matset(this.nodes[i].lastFrameInterp || [], interp); + + } + last = this.nodes[i].lastAnimationFrame; + now = this.nodes[i].thisAnimationFrame; + if (last && now && Math.abs(now - last) < 3) { + var interpA = 0; + interpA = this.lerp(last, now, step); + this.nodes[i].currentAnimationFrame = getAnimationFrame(i); + + if (this.state.nodes[i].lastAnimationInterp) + interpA = this.lerp(this.state.nodes[i].lastAnimationInterp, now, lerpStep); + setAnimationFrame(i,interpA); + this.state.nodes[i].lastAnimationInterp = interpA || 0; + + } else if (this.state.nodes[i]) { + this.state.nodes[i].lastAnimationInterp = null; + } + } } function restoreTransforms() { - for(var nodeID in self.nodes) { - var now = self.nodes[nodeID].selfTickTransform; + var keys = Object.keys(this.nodes); + for (var j = 0; j < keys.length; j++) { + var i = keys[j]; - if(self.node != navObject && now && self.nodes[nodeID].needTransformRestore) { - self.state.nodes[nodeID].threeObject.matrix.elements = goog.vec.Mat4.clone(now); - self.state.nodes[nodeID].threeObject.updateMatrixWorld(true); - self.nodes[nodeID].needTransformRestore = false; + var now = this.nodes[i].currentTickTransform; + this.nodes[i].currentTickTransform = null; + if (now) { + setTransform(i,now); + } + now = this.nodes[i].currentAnimationFrame; + this.nodes[i].currentAnimationFrame = null; + if (now != null) { + setAnimationFrame(i,now); } } } From ed2b3c1484fefaa8600e64597736b21ac57d47f8 Mon Sep 17 00:00:00 2001 From: Rob Chadwick Date: Mon, 9 Feb 2015 17:01:47 -0500 Subject: [PATCH 04/21] change this to self --- support/client/lib/vwf/view/threejs.js | 86 +++++++++++++++----------- 1 file changed, 49 insertions(+), 37 deletions(-) diff --git a/support/client/lib/vwf/view/threejs.js b/support/client/lib/vwf/view/threejs.js index 10bb51c3d..8e58e711e 100644 --- a/support/client/lib/vwf/view/threejs.js +++ b/support/client/lib/vwf/view/threejs.js @@ -14,6 +14,18 @@ // or implied. See the License for the specific language governing permissions and limitations under // the License. +function matset(newv, old) { + if (!old) { + newv = old; + return; + } + if (!newv) + newv = []; + for (var i = 0; i < old.length; i++) + newv[i] = old[i]; + return newv; +} + define( [ "module", "vwf/view", "vwf/utility", @@ -1030,84 +1042,84 @@ define( [ "module", self.state.nodes[id].threeObject.updateMatrixWorld(true); } function setInterpolatedTransforms(deltaTime) { - this.tickTime += deltaTime || 0; + self.tickTime += deltaTime || 0; var hit = 0; - while (this.tickTime > 50) { + while (self.tickTime > 50) { hit++; - this.tickTime -= 50; + self.tickTime -= 50; } - var step = (this.tickTime) / (50); + var step = (self.tickTime) / (50); if (hit === 1) { - var keys = Object.keys(this.nodes); + var keys = Object.keys(self.nodes); for (var j = 0; j < keys.length; j++) { var i = keys[j]; - if (this.nodes[i].lastTransformStep + 1 < vwf.time()) { - this.nodes[i].lastTickTransform = null; - this.nodes[i].lastFrameInterp = null; - this.nodes[i].thisTickTransform = null; - } else if (this.state.nodes[i]) { - this.nodes[i].lastTickTransform = matset(this.nodes[i].lastTickTransform, this.nodes[i].thisTickTransform); - this.nodes[i].thisTickTransform = matset(this.nodes[i].thisTickTransform, getTransform(i)); + if (self.nodes[i].lastTransformStep + 1 < vwf.time()) { + self.nodes[i].lastTickTransform = null; + self.nodes[i].lastFrameInterp = null; + self.nodes[i].thisTickTransform = null; + } else if (self.state.nodes[i]) { + self.nodes[i].lastTickTransform = matset(self.nodes[i].lastTickTransform, self.nodes[i].thisTickTransform); + self.nodes[i].thisTickTransform = matset(self.nodes[i].thisTickTransform, getTransform(i)); } - if (this.state.nodes[i]) { - this.nodes[i].lastAnimationFrame = this.nodes[i].thisAnimationFrame; - this.nodes[i].thisAnimationFrame = getAnimationFrame(i); + if (self.state.nodes[i]) { + self.nodes[i].lastAnimationFrame = self.nodes[i].thisAnimationFrame; + self.nodes[i].thisAnimationFrame = getAnimationFrame(i); } } } var lerpStep = Math.min(1, .2 * (deltaTime / 16.6)); //the slower the frames ,the more we have to move per frame. Should feel the same at 60 0r 20 - var keys = Object.keys(this.nodes); + var keys = Object.keys(self.nodes); var interp = null; for (var j = 0; j < keys.length; j++) { var i = keys[j]; - var last = this.nodes[i].lastTickTransform; - var now = this.nodes[i].thisTickTransform; + var last = self.nodes[i].lastTickTransform; + var now = self.nodes[i].thisTickTransform; if (last && now) { interp = matset(interp, last); - interp = this.matrixLerp(last, now, step, interp); + interp = self.matrixLerp(last, now, step, interp); - this.nodes[i].currentTickTransform = matset(this.nodes[i].currentTickTransform, getTransform(i)); + self.nodes[i].currentTickTransform = matset(self.nodes[i].currentTickTransform, getTransform(i)); - if (this.nodes[i].lastFrameInterp) - interp = this.matrixLerp(this.nodes[i].lastFrameInterp, now, lerpStep, interp); + if (self.nodes[i].lastFrameInterp) + interp = self.matrixLerp(self.nodes[i].lastFrameInterp, now, lerpStep, interp); setTransform(i,interp); - this.nodes[i].lastFrameInterp = matset(this.nodes[i].lastFrameInterp || [], interp); + self.nodes[i].lastFrameInterp = matset(self.nodes[i].lastFrameInterp || [], interp); } - last = this.nodes[i].lastAnimationFrame; - now = this.nodes[i].thisAnimationFrame; + last = self.nodes[i].lastAnimationFrame; + now = self.nodes[i].thisAnimationFrame; if (last && now && Math.abs(now - last) < 3) { var interpA = 0; - interpA = this.lerp(last, now, step); - this.nodes[i].currentAnimationFrame = getAnimationFrame(i); + interpA = self.lerp(last, now, step); + self.nodes[i].currentAnimationFrame = getAnimationFrame(i); - if (this.state.nodes[i].lastAnimationInterp) - interpA = this.lerp(this.state.nodes[i].lastAnimationInterp, now, lerpStep); + if (self.state.nodes[i].lastAnimationInterp) + interpA = self.lerp(self.state.nodes[i].lastAnimationInterp, now, lerpStep); setAnimationFrame(i,interpA); - this.state.nodes[i].lastAnimationInterp = interpA || 0; + self.state.nodes[i].lastAnimationInterp = interpA || 0; - } else if (this.state.nodes[i]) { - this.state.nodes[i].lastAnimationInterp = null; + } else if (self.state.nodes[i]) { + self.state.nodes[i].lastAnimationInterp = null; } } } function restoreTransforms() { - var keys = Object.keys(this.nodes); + var keys = Object.keys(self.nodes); for (var j = 0; j < keys.length; j++) { var i = keys[j]; - var now = this.nodes[i].currentTickTransform; - this.nodes[i].currentTickTransform = null; + var now = self.nodes[i].currentTickTransform; + self.nodes[i].currentTickTransform = null; if (now) { setTransform(i,now); } - now = this.nodes[i].currentAnimationFrame; - this.nodes[i].currentAnimationFrame = null; + now = self.nodes[i].currentAnimationFrame; + self.nodes[i].currentAnimationFrame = null; if (now != null) { setAnimationFrame(i,now); } From a1b5e5df12a6765731fe2c636c00a2f3c65077c6 Mon Sep 17 00:00:00 2001 From: Rob Chadwick Date: Mon, 9 Feb 2015 17:19:32 -0500 Subject: [PATCH 05/21] fix some minor bugs --- support/client/lib/vwf/view/threejs.js | 71 +++++++++++++++----------- 1 file changed, 42 insertions(+), 29 deletions(-) diff --git a/support/client/lib/vwf/view/threejs.js b/support/client/lib/vwf/view/threejs.js index 8e58e711e..9d799dec6 100644 --- a/support/client/lib/vwf/view/threejs.js +++ b/support/client/lib/vwf/view/threejs.js @@ -534,7 +534,7 @@ define( [ "module", findNavObject(); } - lerpTick(); + }, // -- render ----------------------------------------------------------------------------------- @@ -901,22 +901,7 @@ define( [ "module", var navObject = undefined; var cameraNode = undefined; - function lerpTick () { - var now = performance.now(); - self.realTickDif = now - self.lastRealTick; - - self.lastRealTick = now; - - //reset - loading can cause us to get behind and always but up against the max prediction value - self.tickTime = 0; - - for ( var nodeID in self.nodes ) { - if ( self.state.nodes[nodeID] ) { - self.nodes[nodeID].lastTickTransform = self.nodes[nodeID].selfTickTransform; - self.nodes[nodeID].selfTickTransform = getTransform(nodeID); - } - } - } + function lerp(a,b,l,c) { if(c) l = Math.min(1,Math.max(l,0)); return (b*l) + a*(1.0-l); @@ -960,7 +945,19 @@ define( [ "module", } } - function matrixLerp( a, b, l ) { + function matset(newv, old) { + if (!old) { + newv = old; + return; + } + if (!newv) + newv = []; + for (var i = 0; i < old.length; i++) + newv[i] = old[i]; + return newv; + } + + function matrixLerp( a, b, l,n ) { // If either of the matrices is not left-handed or not orthogonal, interpolation won't work // Just return the second matrix @@ -968,7 +965,7 @@ define( [ "module", return b; } - var n = goog.vec.Mat4.clone(a); + if (!n) n = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; n[12] = lerp(a[12],b[12],l); n[13] = lerp(a[13],b[13],l); n[14] = lerp(a[14],b[14],l); @@ -1036,23 +1033,33 @@ define( [ "module", var interp = vwf.getProperty(id,'animationFrame'); return interp; } + function setAnimationFrame(id,val) { + //NOTE: this can cause state errors. Need a layer in VWF to abstract the set of this + //property from the VWF model state. + vwf.setProperty(id,'animationFrame',val); + } function setTransform(id,interp) { interp = goog.vec.Mat4.clone(interp) self.state.nodes[id].threeObject.matrix.elements = interp; self.state.nodes[id].threeObject.updateMatrixWorld(true); } function setInterpolatedTransforms(deltaTime) { + + //smooth over local time self.tickTime += deltaTime || 0; var hit = 0; + + //how many ticks has it been? while (self.tickTime > 50) { hit++; self.tickTime -= 50; } var step = (self.tickTime) / (50); + //if the tick is exactly one, we reset if (hit === 1) { + //NOTE: we use this construct because V8 will not optimize a function with a for in loop var keys = Object.keys(self.nodes); - for (var j = 0; j < keys.length; j++) { var i = keys[j]; if (self.nodes[i].lastTransformStep + 1 < vwf.time()) { @@ -1070,8 +1077,13 @@ define( [ "module", } } - var lerpStep = Math.min(1, .2 * (deltaTime / 16.6)); //the slower the frames ,the more we have to move per frame. Should feel the same at 60 0r 20 + //this is where we trade off between responsive and smooth. This is sort of a magic number picked + //empirically. + //try the duck example with this set to 1, and then again set to .01 + var LERPFACTOR = .15; + var lerpStep = Math.min(1, LERPFACTOR * (deltaTime / 16.6)); //the slower the frames ,the more we have to move per frame. Should feel the same at 60 0r 20 var keys = Object.keys(self.nodes); + //reuse local variables where possible, especially if they are arrays var interp = null; for (var j = 0; j < keys.length; j++) { var i = keys[j]; @@ -1079,27 +1091,28 @@ define( [ "module", var last = self.nodes[i].lastTickTransform; var now = self.nodes[i].thisTickTransform; if (last && now) { - + //use matset to keep data in temp variables interp = matset(interp, last); - interp = self.matrixLerp(last, now, step, interp); + interp = matrixLerp(last, now, step, interp); self.nodes[i].currentTickTransform = matset(self.nodes[i].currentTickTransform, getTransform(i)); - if (self.nodes[i].lastFrameInterp) - interp = self.matrixLerp(self.nodes[i].lastFrameInterp, now, lerpStep, interp); - setTransform(i,interp); - self.nodes[i].lastFrameInterp = matset(self.nodes[i].lastFrameInterp || [], interp); + if (self.nodes[i].lastFrameInterp) + interp = matrixLerp(self.nodes[i].lastFrameInterp, now, lerpStep, interp); + setTransform(i,interp); + self.nodes[i].lastFrameInterp = matset(self.nodes[i].lastFrameInterp || [], interp); } last = self.nodes[i].lastAnimationFrame; now = self.nodes[i].thisAnimationFrame; + //If the delta in animation frames is greater than 3, treat is as discontinuous if (last && now && Math.abs(now - last) < 3) { var interpA = 0; - interpA = self.lerp(last, now, step); + interpA = lerp(last, now, step); self.nodes[i].currentAnimationFrame = getAnimationFrame(i); if (self.state.nodes[i].lastAnimationInterp) - interpA = self.lerp(self.state.nodes[i].lastAnimationInterp, now, lerpStep); + interpA = lerp(self.state.nodes[i].lastAnimationInterp, now, lerpStep); setAnimationFrame(i,interpA); self.state.nodes[i].lastAnimationInterp = interpA || 0; From 65d401be0d4bbafd5caaa8844896b7397b63ae72 Mon Sep 17 00:00:00 2001 From: Rob Chadwick Date: Mon, 9 Feb 2015 17:21:36 -0500 Subject: [PATCH 06/21] remove twice defined matset --- support/client/lib/vwf/view/threejs.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/support/client/lib/vwf/view/threejs.js b/support/client/lib/vwf/view/threejs.js index 9d799dec6..a8963134e 100644 --- a/support/client/lib/vwf/view/threejs.js +++ b/support/client/lib/vwf/view/threejs.js @@ -14,18 +14,6 @@ // or implied. See the License for the specific language governing permissions and limitations under // the License. -function matset(newv, old) { - if (!old) { - newv = old; - return; - } - if (!newv) - newv = []; - for (var i = 0; i < old.length; i++) - newv[i] = old[i]; - return newv; -} - define( [ "module", "vwf/view", "vwf/utility", From 57b03ec17d66522893213d4bb5db032a8009db69 Mon Sep 17 00:00:00 2001 From: Scott Haynes Date: Wed, 11 Feb 2015 17:37:44 -0500 Subject: [PATCH 07/21] Adds the animatedNodes to the shared state info --- support/client/lib/vwf/model/threejs.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/support/client/lib/vwf/model/threejs.js b/support/client/lib/vwf/model/threejs.js index 2c16019b8..6966975ea 100644 --- a/support/client/lib/vwf/model/threejs.js +++ b/support/client/lib/vwf/model/threejs.js @@ -73,8 +73,9 @@ define( [ "module", checkCompatibility.call(this); - this.state.scenes = {}; // id => { glgeDocument: new GLGE.Document(), glgeRenderer: new GLGE.Renderer(), glgeScene: new GLGE.Scene() } - this.state.nodes = {}; // id => { name: string, glgeObject: GLGE.Object, GLGE.Collada, GLGE.Light, or other...? } + this.state.scenes = {}; + this.state.nodes = {}; + this.state.animatedNodes = {}; this.state.prototypes = {}; this.state.kernel = this.kernel.kernel.kernel; this.state.lights = {}; @@ -110,7 +111,8 @@ define( [ "module", "properties": false, "setting": false, "getting": false, - "prototypes": false + "prototypes": false, + "loading": true }; }, @@ -3547,7 +3549,10 @@ define( [ "module", var threeModel = this; var sceneNode = this.state.scenes[ this.kernel.application() ]; var parentObject3 = parentNode.threeObject ? parentNode.threeObject : parentNode.threeScene; - //console.info( "---- loadAsset( "+parentNode.name+", "+node.name+", "+childType+" )" ); + + if ( this.debug.loading ) { + this.logger.infox( "loadAsset", parentNode.ID, node.ID, childType ); + } node.assetLoaded = function( geometry , materials) { //console.info( "++++ assetLoaded( "+parentNode.name+", "+node.name+", "+childType+" )" ); From 563d7b895febb75a624aa324938a1d0a0d282c27 Mon Sep 17 00:00:00 2001 From: Scott Haynes Date: Wed, 11 Feb 2015 17:38:19 -0500 Subject: [PATCH 08/21] Removes old depreciated properties --- support/proxy/vwf.example.com/node3.vwf.yaml | 39 -------------------- 1 file changed, 39 deletions(-) diff --git a/support/proxy/vwf.example.com/node3.vwf.yaml b/support/proxy/vwf.example.com/node3.vwf.yaml index 574d7844d..fac18eaa5 100644 --- a/support/proxy/vwf.example.com/node3.vwf.yaml +++ b/support/proxy/vwf.example.com/node3.vwf.yaml @@ -274,45 +274,6 @@ properties: ## @name node3.vwf#vertices ## @property - vertices: - set: | - this.logger.info( "WARNING: node3 vertices cannot be set" ) - - ## Vertex indices of 3D node - ## - ## @name node3.vwf#vertexIndices - ## @property - - vertexIndices: - set: | - this.logger.info( "WARNING: node3 vertexIndices cannot be set" ) - - ## Speed value - ## - ## @name node3.vwf#speed - ## @property - - speed: 1 - - ## Playing value - ## - ## @name node3.vwf#playing - ## @property - - playing: false - - ## Looping value - ## - ## @name node3.vwf#looping - ## @property - - looping: false - - ## Look at value - ## - ## @name lookAt - ## @property - lookAt: "" ## Visible value From 3c0f3cbbe327bee36ea4d2748447cd2ca92ff8d8 Mon Sep 17 00:00:00 2001 From: Scott Haynes Date: Wed, 11 Feb 2015 17:38:43 -0500 Subject: [PATCH 09/21] Corrects the events tag --- support/proxy/vwf.example.com/node3/animation.vwf.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support/proxy/vwf.example.com/node3/animation.vwf.yaml b/support/proxy/vwf.example.com/node3/animation.vwf.yaml index 57504dd43..4492ed099 100644 --- a/support/proxy/vwf.example.com/node3/animation.vwf.yaml +++ b/support/proxy/vwf.example.com/node3/animation.vwf.yaml @@ -416,5 +416,5 @@ methods: } this.transformTo( stopTransform, duration ); //@ sourceURL=node3.animation.worldTransformTo.vwf -event: +events: changingTransformFromView: From b07308c3d510e8c404babffffe2967f983ded16c Mon Sep 17 00:00:00 2001 From: Scott Haynes Date: Wed, 11 Feb 2015 17:44:08 -0500 Subject: [PATCH 10/21] Adds the animated nodes to the shared state --- support/client/lib/vwf/view/threejs.js | 235 ++++++++++++++++--------- 1 file changed, 154 insertions(+), 81 deletions(-) diff --git a/support/client/lib/vwf/view/threejs.js b/support/client/lib/vwf/view/threejs.js index a8963134e..b18f0d807 100644 --- a/support/client/lib/vwf/view/threejs.js +++ b/support/client/lib/vwf/view/threejs.js @@ -28,6 +28,7 @@ define( [ "module", // Navigation: Private global variables for navigation var navObjectRequested; var navObjectName; + var localNavObjectID; var navmode; var touchmode; var ownerlessNavObjects = []; @@ -146,7 +147,7 @@ define( [ "module", raycaster = new THREE.Raycaster(); window._dView = this; - this.nodes = {}; + this.interpolateTransforms = true; this.tickTime = 0; this.realTickDif = 50; @@ -163,8 +164,8 @@ define( [ "module", //how/when does the model set the state object? if ( this.state.scenes[ childID ] ) { - this.canvasQuery = $(this.rootSelector).append("" - ).children(":last"); + var canvasDef = "" + this.canvasQuery = $(this.rootSelector).append( canvasDef ).children(":last"); initScene.call(this,this.state.scenes[childID]); } @@ -175,9 +176,9 @@ define( [ "module", } } - if(this.state.nodes[childID] && this.state.nodes[childID].threeObject instanceof THREE.Object3D) { - this.nodes[childID] = {id:childID,extends:childExtendsID}; - } + // if ( this.state.nodes[childID] && this.state.nodes[childID].threeObject instanceof THREE.Object3D ) { + // this.nodes[childID] = {id:childID,extends:childExtendsID}; + // } }, initializedNode: function( nodeID, childID ) { @@ -216,6 +217,7 @@ define( [ "module", // Can be removed once kernel.createChild callback works properly var initNode = this.state.nodes[ childID ]; if ( initNode && ( initNode.name == navObjectName ) ) { + localNavObjectID = childID; initNode.owner = this.kernel.moniker(); controlNavObject( initNode ); } @@ -240,7 +242,12 @@ define( [ "module", deletedNode: function(childID) { - delete this.nodes[childID]; + if ( this.state.animatedNodes[ childID ] !== undefined ) { + delete this.state.animatedNodes[ childID ]; + } + //if ( this.animatedNodes[ childID ] !== undefined ) { + // delete this.animatedNodes[ childID ]; + //} }, // -- addedChild ------------------------------------------------------------------------------- @@ -251,16 +258,18 @@ define( [ "module", //removedChild: function( nodeID, childID ) { }, - // -- createdProperty -------------------------------------------------------------------------- - - //createdProperty: function (nodeID, propertyName, propertyValue) { }, - // -- initializedProperty ---------------------------------------------------------------------- initializedProperty: function ( nodeID, propertyName, propertyValue ) { this.satProperty(nodeID, propertyName, propertyValue); }, + // -- createdProperty -------------------------------------------------------------------------- + + createdProperty: function (nodeID, propertyName, propertyValue) { + this.satProperty(nodeID, propertyName, propertyValue); + }, + // TODO: deletedProperty // -- satProperty ------------------------------------------------------------------------------ @@ -307,7 +316,8 @@ define( [ "module", if ( node ) { nodeLookAt( node ); } - } + + } }, // -- gotProperty ------------------------------------------------------------------------------ @@ -422,7 +432,21 @@ define( [ "module", // -- calledMethod ----------------------------------------------------------------------------- calledMethod: function( nodeID, methodName, methodParameters, methodValue ) { - switch(methodName) { + + switch( methodName ) { + + case "animationPlay": + if ( navObject === undefined || navObject.ID !== nodeID ) { + if ( this.state.animatedNodes[ nodeID ] === undefined ) { + this.state.animatedNodes[ nodeID ] = { + "id": nodeID, + "lastAnimationFrame": getAnimationFrame( nodeID ), + "thisAnimationFrame": getAnimationFrame( nodeID ) + } + } + } + break; + case "translateBy": case "translateTo": // No need for rotateBy or rotateTo because they call the quaternion methods @@ -434,9 +458,14 @@ define( [ "module", case "transformTo": case "worldTransformTo": // If the duration of the transform is 0, set the transforms to their final value so it doesn't interpolate - if(methodParameters.length < 2 || methodParameters[1] == 0) { - this.nodes[nodeID].lastTickTransform = getTransform(nodeID); - this.nodes[nodeID].selfTickTransform = goog.vec.Mat4.clone(this.nodes[nodeID].lastTickTransform); + if ( ( methodParameters.length >= 2 ) && ( methodParameters[ 1 ] !== 0 && methodParameters[ 1 ] !== undefined ) ) { + if ( navObject === undefined || navObject.ID !== nodeID ) { + this.state.animatedNodes[ nodeID ] = { + "id": nodeID, + "thisTickTransform": getTransform( nodeID ), + "lastTickTransform": getTransform( nodeID ) + } + } } break; } @@ -489,7 +518,7 @@ define( [ "module", // -- firedEvent ----------------------------------------------------------------------------- - firedEvent: function( nodeID, eventName ) { + firedEvent: function( nodeID, eventName, eventParameters ) { if ( eventName == "changingTransformFromView" ) { var clientThatSatProperty = self.kernel.client(); var me = self.kernel.moniker(); @@ -504,7 +533,11 @@ define( [ "module", if(this.state.scenes[nodeID]) { this.state.scenes[nodeID].renderer.setViewport(0,0,window.innerWidth,window.innerHeight); } - } + } else if ( eventName === "animationStopped" ) { + if ( this.state.animatedNodes[ nodeID ] !== undefined ) { + delete this.state.animatedNodes[ nodeID ]; + } + } }, // -- ticked ----------------------------------------------------------------------------------- @@ -1013,23 +1046,23 @@ define( [ "module", return nqm; } - function getTransform(id) { - var interp = goog.vec.Mat4.clone(self.state.nodes[id].threeObject.matrix.elements); - return interp; - } - function getAnimationFrame(id) { - var interp = vwf.getProperty(id,'animationFrame'); + function getAnimationFrame( id ) { + var interp = vwf.getProperty( id, 'animationFrame' ); return interp; } - function setAnimationFrame(id,val) { + function setAnimationFrame( id, val ) { //NOTE: this can cause state errors. Need a layer in VWF to abstract the set of this //property from the VWF model state. - vwf.setProperty(id,'animationFrame',val); + vwf.setProperty( id, 'animationFrame', val ); } - function setTransform(id,interp) { - interp = goog.vec.Mat4.clone(interp) - self.state.nodes[id].threeObject.matrix.elements = interp; - self.state.nodes[id].threeObject.updateMatrixWorld(true); + function getTransform( id ) { + var interp = goog.vec.Mat4.clone( self.state.nodes[ id ].threeObject.matrix.elements ); + return interp; + } + function setTransform( id, interp ) { + interp = goog.vec.Mat4.clone( interp ) + self.state.nodes[ id ].threeObject.matrix.elements = interp; + self.state.nodes[ id ].threeObject.updateMatrixWorld( true ); } function setInterpolatedTransforms(deltaTime) { @@ -1043,26 +1076,29 @@ define( [ "module", self.tickTime -= 50; } var step = (self.tickTime) / (50); + var keys, id, j, nd; //if the tick is exactly one, we reset if (hit === 1) { //NOTE: we use this construct because V8 will not optimize a function with a for in loop - var keys = Object.keys(self.nodes); - for (var j = 0; j < keys.length; j++) { - var i = keys[j]; - if (self.nodes[i].lastTransformStep + 1 < vwf.time()) { - self.nodes[i].lastTickTransform = null; - self.nodes[i].lastFrameInterp = null; - self.nodes[i].thisTickTransform = null; - } else if (self.state.nodes[i]) { - self.nodes[i].lastTickTransform = matset(self.nodes[i].lastTickTransform, self.nodes[i].thisTickTransform); - self.nodes[i].thisTickTransform = matset(self.nodes[i].thisTickTransform, getTransform(i)); - } - if (self.state.nodes[i]) { - self.nodes[i].lastAnimationFrame = self.nodes[i].thisAnimationFrame; - self.nodes[i].thisAnimationFrame = getAnimationFrame(i); + keys = Object.keys( self.state.animatedNodes ); + for ( j = 0; j < keys.length; j++) { + id = keys[ j ]; + nd = self.state.animatedNodes[ id ]; + + if ( self.state.nodes[ id ] ) { + if ( nd.lastTickTransform !== undefined && nd.thisTickTransform !== undefined ) { + nd.lastTickTransform = matset( nd.lastTickTransform, nd.thisTickTransform ); + nd.thisTickTransform = matset( nd.thisTickTransform, getTransform( id ) ); + } + + if ( nd.lastAnimationFrame !== undefined && nd.thisAnimationFrame !== undefined ) { + nd.lastAnimationFrame = nd.thisAnimationFrame; + nd.thisAnimationFrame = getAnimationFrame( id ); + } } } + } //this is where we trade off between responsive and smooth. This is sort of a magic number picked @@ -1070,61 +1106,98 @@ define( [ "module", //try the duck example with this set to 1, and then again set to .01 var LERPFACTOR = .15; var lerpStep = Math.min(1, LERPFACTOR * (deltaTime / 16.6)); //the slower the frames ,the more we have to move per frame. Should feel the same at 60 0r 20 - var keys = Object.keys(self.nodes); + keys = Object.keys( self.state.animatedNodes ); //reuse local variables where possible, especially if they are arrays var interp = null; - for (var j = 0; j < keys.length; j++) { - var i = keys[j]; - - var last = self.nodes[i].lastTickTransform; - var now = self.nodes[i].thisTickTransform; + var last, now; + for ( j = 0; j < keys.length; j++) { + id = keys[j]; + nd = self.state.animatedNodes[ id ]; + last = nd.lastTickTransform; + now = nd.thisTickTransform; if (last && now) { //use matset to keep data in temp variables interp = matset(interp, last); interp = matrixLerp(last, now, step, interp); - self.nodes[i].currentTickTransform = matset(self.nodes[i].currentTickTransform, getTransform(i)); - - if (self.nodes[i].lastFrameInterp) - interp = matrixLerp(self.nodes[i].lastFrameInterp, now, lerpStep, interp); - setTransform(i,interp); - self.nodes[i].lastFrameInterp = matset(self.nodes[i].lastFrameInterp || [], interp); + nd.currentTickTransform = matset( nd.currentTickTransform, getTransform( id ) ); + if ( nd.lastFrameInterp ) + interp = matrixLerp( nd.lastFrameInterp, now, lerpStep, interp ); + setTransform( id, interp ); + nd.lastFrameInterp = matset( nd.lastFrameInterp || [], interp ); } - last = self.nodes[i].lastAnimationFrame; - now = self.nodes[i].thisAnimationFrame; + + last = nd.lastAnimationFrame; + now = nd.thisAnimationFrame; //If the delta in animation frames is greater than 3, treat is as discontinuous - if (last && now && Math.abs(now - last) < 3) { + if ( last && now && Math.abs(now - last) < 3) { var interpA = 0; interpA = lerp(last, now, step); - self.nodes[i].currentAnimationFrame = getAnimationFrame(i); + nd.currentAnimationFrame = getAnimationFrame(id); - if (self.state.nodes[i].lastAnimationInterp) - interpA = lerp(self.state.nodes[i].lastAnimationInterp, now, lerpStep); - setAnimationFrame(i,interpA); - self.state.nodes[i].lastAnimationInterp = interpA || 0; + if (self.state.nodes[id].lastAnimationInterp) + interpA = lerp(self.state.nodes[id].lastAnimationInterp, now, lerpStep); + setAnimationFrame(id,interpA); + self.state.nodes[id].lastAnimationInterp = interpA || 0; - } else if (self.state.nodes[i]) { - self.state.nodes[i].lastAnimationInterp = null; + } else if (self.state.nodes[id]) { + self.state.nodes[id].lastAnimationInterp = null; } + } + + // keys = Object.keys( self.animatedNodes ); + // //reuse local variables where possible, especially if they are arrays + // interp = null; + // for ( j = 0; j < keys.length; j++) { + // id = keys[j]; + // nd = self.animatedNodes[ id ]; + // last = nd.lastAnimationFrame; + // now = nd.thisAnimationFrame; + // //If the delta in animation frames is greater than 3, treat is as discontinuous + // if ( last && now && Math.abs(now - last) < 3) { + // var interpA = 0; + // interpA = lerp(last, now, step); + // nd.currentAnimationFrame = getAnimationFrame(id); + + // if (self.state.nodes[id].lastAnimationInterp) + // interpA = lerp(self.state.nodes[id].lastAnimationInterp, now, lerpStep); + // setAnimationFrame(id,interpA); + // self.state.nodes[id].lastAnimationInterp = interpA || 0; + + // } else if (self.state.nodes[id]) { + // self.state.nodes[id].lastAnimationInterp = null; + // } + // } } function restoreTransforms() { - var keys = Object.keys(self.nodes); - for (var j = 0; j < keys.length; j++) { - var i = keys[j]; - - var now = self.nodes[i].currentTickTransform; - self.nodes[i].currentTickTransform = null; - if (now) { - setTransform(i,now); - } - now = self.nodes[i].currentAnimationFrame; - self.nodes[i].currentAnimationFrame = null; - if (now != null) { - setAnimationFrame(i,now); - } - } + var keys, id, j, now, nd; + keys = Object.keys( self.state.animatedNodes ); + for ( j = 0; j < keys.length; j++) { + id = keys[j]; + nd = self.state.animatedNodes[ id ]; + if ( nd.currentTickTransform != null ) { + now = nd.currentTickTransform; + nd.currentTickTransform = null; + setTransform( id, now ); + } + if ( nd.currentAnimationFrame != null ) { + now = nd.currentAnimationFrame; + nd.currentAnimationFrame = null; + setAnimationFrame( id, now ); + } + } + // keys = Object.keys( self.animatedNodes ); + // for ( j = 0; j < keys.length; j++) { + // id = keys[j]; + // nd = self.animatedNodes[id]; + // now = nd.currentAnimationFrame; + // nd.currentAnimationFrame = null; + // if (now != null) { + // setAnimationFrame(id,now); + // } + // } } function checkCompatibility() { From bf0b2eed8f399f0b61e51eedee8b881e50afca09 Mon Sep 17 00:00:00 2001 From: Scott Haynes Date: Wed, 11 Feb 2015 17:44:32 -0500 Subject: [PATCH 11/21] Removes the debugging info for loading assets --- support/client/lib/vwf/model/threejs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support/client/lib/vwf/model/threejs.js b/support/client/lib/vwf/model/threejs.js index 6966975ea..edb0015c8 100644 --- a/support/client/lib/vwf/model/threejs.js +++ b/support/client/lib/vwf/model/threejs.js @@ -112,7 +112,7 @@ define( [ "module", "setting": false, "getting": false, "prototypes": false, - "loading": true + "loading": false }; }, From b0ee31bc8443eaff9925a97559f0038bfd905217 Mon Sep 17 00:00:00 2001 From: Scott Haynes Date: Wed, 11 Feb 2015 17:56:59 -0500 Subject: [PATCH 12/21] Removes some commented out code --- support/client/lib/vwf/view/threejs.js | 38 -------------------------- 1 file changed, 38 deletions(-) diff --git a/support/client/lib/vwf/view/threejs.js b/support/client/lib/vwf/view/threejs.js index b18f0d807..5678e1b2b 100644 --- a/support/client/lib/vwf/view/threejs.js +++ b/support/client/lib/vwf/view/threejs.js @@ -28,7 +28,6 @@ define( [ "module", // Navigation: Private global variables for navigation var navObjectRequested; var navObjectName; - var localNavObjectID; var navmode; var touchmode; var ownerlessNavObjects = []; @@ -245,9 +244,6 @@ define( [ "module", if ( this.state.animatedNodes[ childID ] !== undefined ) { delete this.state.animatedNodes[ childID ]; } - //if ( this.animatedNodes[ childID ] !== undefined ) { - // delete this.animatedNodes[ childID ]; - //} }, // -- addedChild ------------------------------------------------------------------------------- @@ -1146,30 +1142,6 @@ define( [ "module", } } - - // keys = Object.keys( self.animatedNodes ); - // //reuse local variables where possible, especially if they are arrays - // interp = null; - // for ( j = 0; j < keys.length; j++) { - // id = keys[j]; - // nd = self.animatedNodes[ id ]; - // last = nd.lastAnimationFrame; - // now = nd.thisAnimationFrame; - // //If the delta in animation frames is greater than 3, treat is as discontinuous - // if ( last && now && Math.abs(now - last) < 3) { - // var interpA = 0; - // interpA = lerp(last, now, step); - // nd.currentAnimationFrame = getAnimationFrame(id); - - // if (self.state.nodes[id].lastAnimationInterp) - // interpA = lerp(self.state.nodes[id].lastAnimationInterp, now, lerpStep); - // setAnimationFrame(id,interpA); - // self.state.nodes[id].lastAnimationInterp = interpA || 0; - - // } else if (self.state.nodes[id]) { - // self.state.nodes[id].lastAnimationInterp = null; - // } - // } } function restoreTransforms() { var keys, id, j, now, nd; @@ -1188,16 +1160,6 @@ define( [ "module", setAnimationFrame( id, now ); } } - // keys = Object.keys( self.animatedNodes ); - // for ( j = 0; j < keys.length; j++) { - // id = keys[j]; - // nd = self.animatedNodes[id]; - // now = nd.currentAnimationFrame; - // nd.currentAnimationFrame = null; - // if (now != null) { - // setAnimationFrame(id,now); - // } - // } } function checkCompatibility() { From c159037cff042981679170aa3b4854763a590dd9 Mon Sep 17 00:00:00 2001 From: Scott Haynes Date: Thu, 12 Feb 2015 18:07:18 -0500 Subject: [PATCH 13/21] Removes the commented out node storing --- support/client/lib/vwf/view/threejs.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/support/client/lib/vwf/view/threejs.js b/support/client/lib/vwf/view/threejs.js index 5678e1b2b..c2b127e5d 100644 --- a/support/client/lib/vwf/view/threejs.js +++ b/support/client/lib/vwf/view/threejs.js @@ -175,9 +175,6 @@ define( [ "module", } } - // if ( this.state.nodes[childID] && this.state.nodes[childID].threeObject instanceof THREE.Object3D ) { - // this.nodes[childID] = {id:childID,extends:childExtendsID}; - // } }, initializedNode: function( nodeID, childID ) { From cd1ab09867cd9a758912d40ce0d55782243c8b5d Mon Sep 17 00:00:00 2001 From: Scott Haynes Date: Tue, 17 Feb 2015 12:56:05 -0500 Subject: [PATCH 14/21] Removes a node from the animated list if the duration is undefined or 0 --- support/client/lib/vwf/view/threejs.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/support/client/lib/vwf/view/threejs.js b/support/client/lib/vwf/view/threejs.js index c2b127e5d..0f9cf9ba2 100644 --- a/support/client/lib/vwf/view/threejs.js +++ b/support/client/lib/vwf/view/threejs.js @@ -434,7 +434,9 @@ define( [ "module", this.state.animatedNodes[ nodeID ] = { "id": nodeID, "lastAnimationFrame": getAnimationFrame( nodeID ), - "thisAnimationFrame": getAnimationFrame( nodeID ) + "thisAnimationFrame": getAnimationFrame( nodeID ), + "thisTickTransform": getTransform( nodeID ), + "lastTickTransform": getTransform( nodeID ) } } } @@ -459,6 +461,8 @@ define( [ "module", "lastTickTransform": getTransform( nodeID ) } } + } else if ( this.state.animatedNodes[ nodeID ] !== undefined ) { + delete this.state.animatedNodes[ nodeID ]; } break; } From 3b683c06fc6a66eaa95e779834331bc20e67e739 Mon Sep 17 00:00:00 2001 From: Scott Haynes Date: Tue, 17 Feb 2015 12:25:25 -0500 Subject: [PATCH 15/21] Removes code that was obsolete dealing with the navObject --- support/client/lib/vwf/view/threejs.js | 1 - 1 file changed, 1 deletion(-) diff --git a/support/client/lib/vwf/view/threejs.js b/support/client/lib/vwf/view/threejs.js index 0f9cf9ba2..bf6ce1867 100644 --- a/support/client/lib/vwf/view/threejs.js +++ b/support/client/lib/vwf/view/threejs.js @@ -213,7 +213,6 @@ define( [ "module", // Can be removed once kernel.createChild callback works properly var initNode = this.state.nodes[ childID ]; if ( initNode && ( initNode.name == navObjectName ) ) { - localNavObjectID = childID; initNode.owner = this.kernel.moniker(); controlNavObject( initNode ); } From 4e0c26caaad4475f138ffd6d34c88afbb24dd325 Mon Sep 17 00:00:00 2001 From: Scott Haynes Date: Thu, 19 Feb 2015 13:34:49 -0500 Subject: [PATCH 16/21] Creates a jiggle view driver to implement ticked --- support/client/lib/vwf.js | 2 + support/client/lib/vwf/model/jiglib.js | 271 ++++++++++++++----------- support/client/lib/vwf/view/jiglib.js | 144 +++++++++++++ 3 files changed, 303 insertions(+), 114 deletions(-) create mode 100644 support/client/lib/vwf/view/jiglib.js diff --git a/support/client/lib/vwf.js b/support/client/lib/vwf.js index 1d1863b61..f6b369ee0 100644 --- a/support/client/lib/vwf.js +++ b/support/client/lib/vwf.js @@ -393,6 +393,7 @@ { library: "vwf/view/cesium", active: false }, { library: "vwf/view/kineticjs", active: false }, { library: "vwf/view/mil-sym", active: false }, + { library: "vwf/view/jiglib", active: false }, { library: "vwf/view/audio", active: false }, { library: "vwf/kernel/utility", active: true }, { library: "vwf/utility", active: true }, @@ -449,6 +450,7 @@ { library: "vwf/view/kineticjs", active: false }, { library: "vwf/view/mil-sym", active: false }, { library: "vwf/view/audio", active: false }, + { library: "vwf/view/jiglib", active: false }, { library: "vwf/view/webrtc", active: false} ] }; diff --git a/support/client/lib/vwf/model/jiglib.js b/support/client/lib/vwf/model/jiglib.js index d6c85dedf..d00747633 100644 --- a/support/client/lib/vwf/model/jiglib.js +++ b/support/client/lib/vwf/model/jiglib.js @@ -16,7 +16,9 @@ /// @module vwf/model/jiglib /// @requires vwf/model -define( [ "module", "vwf/model" ], function( module, model ) { +define( [ "module", "vwf/model", "vwf/utility" ], function( module, model, utility ) { + + var modelDriver; return model.load( module, { @@ -26,13 +28,33 @@ define( [ "module", "vwf/model" ], function( module, model ) { initialize: function() { - this.nodes = {}; // maps id => { property: value, ... } - this.scenes = {}; - this.active = {}; - this.enabled = false; - this.lastTime = 0; - this.delayedProperties = {}; - this.updating = false; + modelDriver = this; + + this.state = { + "nodes": {}, + "scenes": {}, + "active": {}, + "enabled": false, + "lastTime": 0, + "delayedProperties": {}, + "updating": false, + "setProperty": function( id, propertyName, propertyValue ) { + modelDriver.kernel.setProperty( id, propertyName, propertyValue ); + } + } + + // turns on logger debugger console messages + this.debug = { + "creation": false, + "initializing": false, + "parenting": false, + "deleting": false, + "properties": false, + "setting": true, + "getting": false, + "prototypes": false, + "loading": false + }; }, @@ -44,40 +66,41 @@ define( [ "module", "vwf/model" ], function( module, model ) { childSource, childType, childIndex, childName, callback /* ( ready ) */) { var kernel = this.kernel; - //this.logger.enable = true; - //this.logger.infox( "creatingNode", nodeID, childID, childExtendsID, childImplementsIDs, - // childSource, childType, childIndex, childName ); - //this.logger.enabled = false; + + if ( this.debug.creation ) { + this.logger.infox( "creatingNode", nodeID, childID, childExtendsID, childImplementsIDs, childSource, childType, childName ); + } if ( childExtendsID && this.kernel.test( childExtendsID, "self::element(*,'http://vwf.example.com/scene.vwf')", childExtendsID ) ) { - this.scenes[ childID ] = {}; - this.scenes[ childID ].ID = childID; - this.scenes[ childID ].extendsID = childExtendsID; - this.scenes[ childID ].implementsIDs = childImplementsIDs; - this.scenes[ childID ].source = childSource; - this.scenes[ childID ].type = childType; - this.scenes[ childID ].system = jigLib.PhysicsSystem.getInstance(); - this.scenes[ childID ].initialized = false; - this.scenes[ childID ].propertyMap = {}; - + this.state.scenes[ childID ] = { + "ID": childID, + "extendsID": childExtendsID, + "implementsIDs": childImplementsIDs, + "source": childSource, + "type": childType, + "system": jigLib.PhysicsSystem.getInstance(), + "initialized": false, + "propertyMap": {} + }; } else { - switch ( childExtendsID && this.kernel.uri( childExtendsID ) ) { + switch ( childExtendsID && this.kernel.uri( childExtendsID ) ) { case "http://vwf.example.com/physics3.vwf": case "http://vwf.example.com/node3.vwf": case "http://vwf.example.com/mesh.vwf": - this.nodes[ childID ] = {}; - this.nodes[ childID ].sceneID = this.kernel.application(); - this.nodes[ childID ].name = childName; - this.nodes[ childID ].ID = childID; - this.nodes[ childID ].parentID = nodeID; - this.nodes[ childID ].extendsID = childExtendsID; - this.nodes[ childID ].implementsIDs = childImplementsIDs; - this.nodes[ childID ].source = childSource; - this.nodes[ childID ].type = childType; - + this.state.nodes[ childID ] = { + "sceneID": this.kernel.application(), + "name": childName, + "ID": childID, + "parentID": nodeID, + "extendsID": childExtendsID, + "implementsIDs": childImplementsIDs, + "source": childSource, + "type": childType + }; + break; } } @@ -90,14 +113,18 @@ define( [ "module", "vwf/model" ], function( module, model ) { initializingNode: function( nodeID, childID ) { - var scene = this.scenes[ childID ]; - var node = this.nodes[ childID ]; + var scene = this.state.scenes[ childID ]; + var node = this.state.nodes[ childID ]; + + if ( this.debug.initializing ) { + this.logger.infox( "initializingNode", nodeID, childID, childExtendsID, childImplementsIDs, childSource, childType, childName ); + } if ( scene && scene.system ) { if ( !scene.initialized ) { initializeScene.call( this, scene ); } - this.enabled = true; + this.state.enabled = true; } else if ( node ) { if ( node.jigLibObj && node.jigLibInternals ) { @@ -129,13 +156,17 @@ define( [ "module", "vwf/model" ], function( module, model ) { deletingNode: function( nodeID ) { - if ( this.active[ nodeID ] ) { - delete this.active[ nodeID ]; + if ( this.debug.deleting ) { + this.logger.infox( "deletingNode", nodeID ); + } + + if ( this.state.active[ nodeID ] ) { + delete this.state.active[ nodeID ]; } - if ( this.nodes[ nodeID ] ) { - var node = this.nodes[ nodeID ]; - var scene = this.scenes[ node.sceneID ]; + if ( this.state.nodes[ nodeID ] ) { + var node = this.state.nodes[ nodeID ]; + var scene = this.state.scenes[ node.sceneID ]; if ( node.jigLibObj ) { if ( node.jigLibObj ) { if ( scene ) scene.system.removeBody( node.jigLibObj ); @@ -148,7 +179,7 @@ define( [ "module", "vwf/model" ], function( module, model ) { } node.jigLibMeshes = undefined; } - delete this.nodes[ nodeID ]; + delete this.state.nodes[ nodeID ]; } }, @@ -171,6 +202,9 @@ define( [ "module", "vwf/model" ], function( module, model ) { // -- creatingProperty --------------------------------------------------------------------- creatingProperty: function( nodeID, propertyName, propertyValue ) { + if ( this.debug.properties ) { + this.logger.infox( "C === creatingProperty ", nodeID, propertyName, propertyValue ); + } return this.initializingProperty( nodeID, propertyName, propertyValue ); }, @@ -179,14 +213,15 @@ define( [ "module", "vwf/model" ], function( module, model ) { initializingProperty: function( nodeID, propertyName, propertyValue ) { var value = undefined; - //this.logger.enabled = true; - //this.logger.infox( "creatingProperty", nodeID, propertyName, propertyValue ); - //this.logger.enabled = false; + + if ( this.debug.properties ) { + this.logger.infox( " I === initializingProperty ", nodeID, propertyName, propertyValue ); + } if ( !( propertyValue === undefined ) ) { - var node = this.nodes[ nodeID ]; + var node = this.state.nodes[ nodeID ]; if ( node ) { - var scene = this.scenes[ node.sceneID ]; + var scene = this.state.scenes[ node.sceneID ]; if ( scene && !scene.initialized ) { var pm; if ( !scene.propertyMap[ nodeID ] ) { @@ -204,25 +239,25 @@ define( [ "module", "vwf/model" ], function( module, model ) { } else { if ( propertyName == "physics" ) { this.settingProperty( nodeID, propertyName, propertyValue ); - if ( this.delayedProperties[ nodeID ] ) { + if ( this.state.delayedProperties[ nodeID ] ) { var propValue; - for ( propName in this.delayedProperties[ nodeID ] ) { - propValue = this.delayedProperties[ nodeID ][ propName ]; + for ( propName in this.state.delayedProperties[ nodeID ] ) { + propValue = this.state.delayedProperties[ nodeID ][ propName ]; this.settingProperty( nodeID, propName, propValue ); } - delete this.delayedProperties[ nodeID ]; + delete this.state.delayedProperties[ nodeID ]; } } else { - if ( !this.delayedProperties[ nodeID ] ) { - this.delayedProperties[ nodeID ] = {}; + if ( !this.state.delayedProperties[ nodeID ] ) { + this.state.delayedProperties[ nodeID ] = {}; } - this.delayedProperties[ nodeID ][ propertyName ] = propertyValue; + this.state.delayedProperties[ nodeID ][ propertyName ] = propertyValue; } } } } else { - var scene = this.scenes[ nodeID ]; + var scene = this.state.scenes[ nodeID ]; if ( scene ) { this.settingProperty( nodeID, propertyName, propertyValue ); } @@ -240,10 +275,14 @@ define( [ "module", "vwf/model" ], function( module, model ) { var value = undefined; - if ( propertyValue === undefined ) + if ( ( this.debug.properties || this.debug.setting ) && ( propertyName !== "transform" ) ) { + this.logger.infox( " S === settingProperty ", nodeID, propertyName, propertyValue ); + } + + if ( !utility.validObject( propertyValue ) ) return value; - if ( this.updating ) { + if ( this.state.updating ) { switch ( propertyName ) { case "transform": return; @@ -251,13 +290,13 @@ define( [ "module", "vwf/model" ], function( module, model ) { } } - var activeNode = this.active[ nodeID ]; - var node = this.nodes[ nodeID ]; - var scene = this.scenes[ nodeID ]; + var activeNode = this.state.active[ nodeID ]; + var node = this.state.nodes[ nodeID ]; + var scene = this.state.scenes[ nodeID ]; if ( node && node.jigLibObj ) { - scene = this.scenes[ node.sceneID ]; + scene = this.state.scenes[ node.sceneID ]; switch ( propertyName ) { case "transform": if ( activeNode && activeNode.jlObj ) { @@ -308,7 +347,7 @@ define( [ "module", "vwf/model" ], function( module, model ) { break; } } else if ( node && !scene ) { - scene = this.scenes[ node.sceneID ]; + scene = this.state.scenes[ node.sceneID ]; if ( propertyName == "physics" ) { if ( scene && scene.system && propertyValue ) { var type = ( propertyValue.constructor == Array ) ? propertyValue[0] : propertyValue; @@ -331,21 +370,21 @@ define( [ "module", "vwf/model" ], function( module, model ) { } } - if ( this.delayedProperties[nodeID] ) { - var props = this.delayedProperties[nodeID]; + if ( this.state.delayedProperties[nodeID] ) { + var props = this.state.delayedProperties[nodeID]; for ( var propName in props ) { this.settingProperty( nodeID, propName, props[propName] ); } - delete this.delayedProperties[nodeID]; + delete this.state.delayedProperties[nodeID]; } } else { if ( node ) { var propArray; - if ( !this.delayedProperties[nodeID] ) { - this.delayedProperties[nodeID] = {}; + if ( !this.state.delayedProperties[nodeID] ) { + this.state.delayedProperties[nodeID] = {}; } - propArray = this.delayedProperties[nodeID]; + propArray = this.state.delayedProperties[nodeID]; propArray[ propertyName ] = propertyValue; } @@ -383,8 +422,12 @@ define( [ "module", "vwf/model" ], function( module, model ) { propertyValue = undefined; - if ( this.nodes[ nodeID ] ) { - var node = this.nodes[ nodeID ]; + if ( this.debug.properties || this.debug.getting ) { + this.logger.infox( " G === gettingProperty ", nodeID, propertyName ); + } + + if ( this.state.nodes[ nodeID ] ) { + var node = this.state.nodes[ nodeID ]; if ( node && node.jigLibObj ) { switch ( propertyName ) { case "physics": @@ -436,8 +479,8 @@ define( [ "module", "vwf/model" ], function( module, model ) { break; } } - } else if ( this.scenes[ nodeID ] ) { - var sceneNode = this.scenes[ nodeID ]; + } else if ( this.state.scenes[ nodeID ] ) { + var sceneNode = this.state.scenes[ nodeID ]; if ( sceneNode && sceneNode.system ) { switch ( propertyName ) { case "gravity": @@ -484,32 +527,32 @@ define( [ "module", "vwf/model" ], function( module, model ) { // == ticking ============================================================================= - ticking: function( vwfTime ) { + // ticking: function( vwfTime ) { - var elaspedTime = vwfTime - this.lastTime; - this.lastTime = vwfTime; + // var elaspedTime = vwfTime - this.state.lastTime; + // this.state.lastTime = vwfTime; - if ( this.enabled ) { - if ( elaspedTime > 0 ) { - if (elaspedTime > 0.05) elaspedTime = 0.05; - var activeObj, posRotProp, pos, rot, posRot; - var sceneNode = this.scenes[this.kernel.application()]; - - if ( sceneNode && sceneNode.system ) { - sceneNode.system.integrate( elaspedTime ); - this.updating = true; - for ( var nodeID in this.active ) { - activeObj = this.active[nodeID]; - if ( activeObj && activeObj.jlObj ) { - var trans = activeObj.jlObj.get_Transform(); - this.kernel.setProperty( nodeID, "transform", trans ); - } - } - this.updating = false; - } - } - } - }, + // if ( this.state.enabled ) { + // if ( elaspedTime > 0 ) { + // if (elaspedTime > 0.05) elaspedTime = 0.05; + // var activeObj, posRotProp, pos, rot, posRot; + // var sceneNode = this.state.scenes[ this.kernel.application() ]; + + // if ( sceneNode && sceneNode.system ) { + // sceneNode.system.integrate( elaspedTime ); + // this.state.updating = true; + // for ( var nodeID in this.state.active ) { + // activeObj = this.state.active[nodeID]; + // if ( activeObj && activeObj.jlObj ) { + // var trans = activeObj.jlObj.get_Transform(); + // this.kernel.setProperty( nodeID, "transform", trans ); + // } + // } + // this.state.updating = false; + // } + // } + // } + // } } ); @@ -537,9 +580,9 @@ define( [ "module", "vwf/model" ], function( module, model ) { function createJBox( nodeID, scale, def ) { - var node = this.nodes[ nodeID ]; + var node = this.state.nodes[ nodeID ]; if ( node ) { - var scene = this.scenes[ node.sceneID ]; + var scene = this.state.scenes[ node.sceneID ]; if ( scene ) { var v1, v2; var width = 1; @@ -569,9 +612,9 @@ define( [ "module", "vwf/model" ], function( module, model ) { if ( node.jigLibObj ) { scene.system.addBody( node.jigLibObj ); if ( pos ) node.jigLibObj.moveTo( [ pos[0], pos[1], pos[2] ] ); - this.active[ nodeID ] = {}; - this.active[ nodeID ].jlObj = node.jigLibObj; - this.active[ nodeID ].offset = offset; + this.state.active[ nodeID ] = {}; + this.state.active[ nodeID ].jlObj = node.jigLibObj; + this.state.active[ nodeID ].offset = offset; } } } @@ -582,9 +625,9 @@ define( [ "module", "vwf/model" ], function( module, model ) { function createJSphere( nodeID, scale, def ) { - var node = this.nodes[ nodeID ]; + var node = this.state.nodes[ nodeID ]; if ( node ) { - var scene = this.scenes[ node.sceneID ]; + var scene = this.state.scenes[ node.sceneID ]; if ( scene ) { var v1, v2; var verts = this.kernel.getProperty( nodeID, "vertices" ); @@ -619,10 +662,10 @@ define( [ "module", "vwf/model" ], function( module, model ) { node.jigLibObj = new jigLib.JSphere( null, raduis ); if ( node.jigLibObj ) { scene.system.addBody( node.jigLibObj ); - if ( pos ) node.jigLibObj.moveTo( [ pos[0], pos[1], pos[2] ] ); - this.active[ nodeID ] = {}; - this.active[ nodeID ].jlObj = node.jigLibObj; - this.active[ nodeID ].offset = this.kernel.getProperty( nodeID, "centerOffset" ) || [ 0, 0, 0 ]; + if ( pos ) node.jigLibObj.moveTo( [ pos[0], pos[1], pos[2] ] ); + this.state.active[ nodeID ] = {}; + this.state.active[ nodeID ].jlObj = node.jigLibObj; + this.state.active[ nodeID ].offset = this.kernel.getProperty( nodeID, "centerOffset" ) || [ 0, 0, 0 ]; } } } @@ -634,9 +677,9 @@ define( [ "module", "vwf/model" ], function( module, model ) { function createJMesh( nodeID, scale ) { - var node = this.nodes[ nodeID ]; + var node = this.state.nodes[ nodeID ]; if ( node ) { - var scene = this.scenes[ node.sceneID ]; + var scene = this.state.scenes[ node.sceneID ]; if ( scene ) { if ( node.jigLibMeshes ) { for ( var j = 0; j < node.jigLibMeshes.length; j++ ) { @@ -678,13 +721,13 @@ define( [ "module", "vwf/model" ], function( module, model ) { function createJPlane( nodeID, physicsDef ) { - var node = this.nodes[ nodeID ]; + var node = this.state.nodes[ nodeID ]; if ( node ) { - var scene = this.scenes[ node.sceneID ]; + var scene = this.state.scenes[ node.sceneID ]; if ( scene ) { var normal = [0, 0, 1, 0]; - - var pos = this.kernel.getProperty( nodeID, "translation" )|| [ 0, 0, 0 ]; + + var pos = this.kernel.getProperty( nodeID, "translation" )|| [ 0, 0, 0 ]; if ( physicsDef.constructor == Array ) { switch ( physicsDef.length ) { case 2: @@ -709,7 +752,7 @@ define( [ "module", "vwf/model" ], function( module, model ) { node.jigLibObj = new jigLib.JPlane( null, normal ); scene.system.addBody( node.jigLibObj ); - if ( pos ) node.jigLibObj.moveTo( [ pos[0], pos[1], pos[2] ] ); + if ( pos ) node.jigLibObj.moveTo( [ pos[0], pos[1], pos[2] ] ); } } } diff --git a/support/client/lib/vwf/view/jiglib.js b/support/client/lib/vwf/view/jiglib.js new file mode 100644 index 000000000..bb33550c4 --- /dev/null +++ b/support/client/lib/vwf/view/jiglib.js @@ -0,0 +1,144 @@ +"use strict"; + +/// @module vwf/view/ +/// @requires vwf/view + +define( [ + "module", + "vwf/view", + "vwf/utility" ], + + function( module, view, utility ) { + + var self; + + return view.load( module, { + + // == Module Definition ==================================================================== + + // -- initialize --------------------------------------------------------------------------- + + initialize: function( options ) { + + self = this; + + this.arguments = Array.prototype.slice.call( arguments ); + + this.options = options || {}; + }, + + // createdNode: function( nodeID, childID, childExtendsID, childImplementsIDs, + // childSource, childType, childIndex, childName, callback ) { + + // }, + + // initializedNode: function( nodeID, childID ) { + + // }, + + + // -- deletedNode -------------------------------------------------------------------------- + + // deletedNode: function( childID ) { + + // if ( this.state.nodes[ childID ] !== undefined ) { + // delete this.state.nodes[ childID ]; + // } + + // }, + + // -- addedChild --------------------------------------------------------------------------- + + //addedChild: function( nodeID, childID, childName ) { }, + + // -- removedChild ------------------------------------------------------------------------- + + //removedChild: function( nodeID, childID ) { }, + + // -- createdProperty ---------------------------------------------------------------------- + + // createdProperty: function( nodeID, propertyName, propertyValue ) { + // this.satProperty( nodeID, propertyName, propertyValue ); + // }, + + // // -- initializedProperty ------------------------------------------------------------------ + + // initializedProperty: function( nodeID, propertyName, propertyValue ) { + // this.satProperty( nodeID, propertyName, propertyValue ); + // }, + + // // TODO: deletedProperty + + // // -- satProperty -------------------------------------------------------------------------- + + // satProperty: function( nodeID, propertyName, propertyValue ) { + // var node = this.state.nodes[ nodeID ]; + + // //this driver has no representation of this node, so there is nothing to do. + // if( node === undefined ) return; + // }, + + // // -- gotProperty -------------------------------------------------------------------------- + + // gotProperty: function( nodeID, propertyName, propertyValue ) { + // var node = this.state.nodes[ nodeID ]; + + // //this driver has no representation of this node, so there is nothing to do. + // if( node === undefined ) return; + // }, + + // // -- calledMethod ------------------------------------------------------------------------- + + // calledMethod: function( nodeID, methodName, methodParameters, methodValue ) { + // }, + + // // -- firedEvent --------------------------------------------------------------------------- + + // firedEvent: function( nodeID, eventName, eventParameters ) { + // }, + + // -- ticked ------------------------------------------------------------------------------- + + ticked: function( vwfTime ) { + var elaspedTime = vwfTime - this.state.lastTime; + this.state.lastTime = vwfTime; + + if ( this.state.enabled ) { + if ( elaspedTime > 0 ) { + if ( elaspedTime > 0.05 ) { + elaspedTime = 0.05; + } + var activeObj, trans; + var sceneNode = this.state.scenes[ this.kernel.application() ]; + + if ( sceneNode && sceneNode.system ) { + sceneNode.system.integrate( elaspedTime ); + + var activeKeys = Object.keys( this.state.active ); + if ( activeKeys !== undefined ) { + this.state.updating = true; + for ( var i = 0; i < activeKeys.length; i++ ) { + activeObj = this.state.active[ activeKeys[ i ] ]; + if ( activeObj && activeObj.jlObj ) { + trans = activeObj.jlObj.get_Transform(); + this.state.setProperty( activeKeys[ i ], "transform", trans ); + //this.kernel.setProperty( activeKeys[ i ], "transform", trans ); + } + } + this.state.updating = false; + } + + } + } + return true; + } + } + + // -- render ------------------------------------------------------------------------------- + + // render: function(renderer, scene, camera) { + // }, + + } ); + +} ); From 06b34ee66f3aa13fd85fa7805b15457949dcc0fa Mon Sep 17 00:00:00 2001 From: Scott Haynes Date: Thu, 19 Feb 2015 13:37:55 -0500 Subject: [PATCH 17/21] Turns off debugging of property setting --- support/client/lib/vwf/model/jiglib.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support/client/lib/vwf/model/jiglib.js b/support/client/lib/vwf/model/jiglib.js index d00747633..76f468d55 100644 --- a/support/client/lib/vwf/model/jiglib.js +++ b/support/client/lib/vwf/model/jiglib.js @@ -50,7 +50,7 @@ define( [ "module", "vwf/model", "vwf/utility" ], function( module, model, utili "parenting": false, "deleting": false, "properties": false, - "setting": true, + "setting": false, "getting": false, "prototypes": false, "loading": false From 874f5b643116d93acee2ad7acc7d66554140ca00 Mon Sep 17 00:00:00 2001 From: Scott Haynes Date: Thu, 19 Feb 2015 15:22:11 -0500 Subject: [PATCH 18/21] Corrects calling the physics update from the model --- support/client/lib/vwf/model/jiglib.js | 83 +++++++------- support/client/lib/vwf/view/jiglib.js | 144 ------------------------- 2 files changed, 47 insertions(+), 180 deletions(-) delete mode 100644 support/client/lib/vwf/view/jiglib.js diff --git a/support/client/lib/vwf/model/jiglib.js b/support/client/lib/vwf/model/jiglib.js index 76f468d55..b8290642c 100644 --- a/support/client/lib/vwf/model/jiglib.js +++ b/support/client/lib/vwf/model/jiglib.js @@ -35,12 +35,8 @@ define( [ "module", "vwf/model", "vwf/utility" ], function( module, model, utili "scenes": {}, "active": {}, "enabled": false, - "lastTime": 0, "delayedProperties": {}, - "updating": false, - "setProperty": function( id, propertyName, propertyValue ) { - modelDriver.kernel.setProperty( id, propertyName, propertyValue ); - } + "updating": false } // turns on logger debugger console messages @@ -505,8 +501,20 @@ define( [ "module", "vwf/model", "vwf/utility" ], function( module, model, utili // -- callingMethod ------------------------------------------------------------------------ - //callingMethod: function( nodeID, methodName, methodParameters ) { - //}, + callingMethod: function( nodeID, methodName, methodParameters ) { + + var sceneID = this.kernel.application(); + if ( nodeID === sceneID ) { + switch ( methodName ) { + + case "update": + updateScene( 0.05 ); + this.kernel.callMethod( sceneID, "update", [], -0.05 ); + break; + + } + } + } // -- creatingEvent ------------------------------------------------------------------------ @@ -525,35 +533,6 @@ define( [ "module", "vwf/model", "vwf/utility" ], function( module, model, utili // return undefined; //}, - // == ticking ============================================================================= - - // ticking: function( vwfTime ) { - - // var elaspedTime = vwfTime - this.state.lastTime; - // this.state.lastTime = vwfTime; - - // if ( this.state.enabled ) { - // if ( elaspedTime > 0 ) { - // if (elaspedTime > 0.05) elaspedTime = 0.05; - // var activeObj, posRotProp, pos, rot, posRot; - // var sceneNode = this.state.scenes[ this.kernel.application() ]; - - // if ( sceneNode && sceneNode.system ) { - // sceneNode.system.integrate( elaspedTime ); - // this.state.updating = true; - // for ( var nodeID in this.state.active ) { - // activeObj = this.state.active[nodeID]; - // if ( activeObj && activeObj.jlObj ) { - // var trans = activeObj.jlObj.get_Transform(); - // this.kernel.setProperty( nodeID, "transform", trans ); - // } - // } - // this.state.updating = false; - // } - // } - // } - // } - } ); // == Private functions ================================================================== @@ -790,6 +769,7 @@ define( [ "module", "vwf/model", "vwf/utility" ], function( module, model, utili } scene.propertyMap = {}; scene.initialized = true; + this.kernel.callMethod( this.kernel.application(), "update", [], -0.05 ) } // == initializeObject =================================================================== @@ -855,4 +835,35 @@ define( [ "module", "vwf/model", "vwf/utility" ], function( module, model, utili } } + // == updateScene =================================================================== + + function updateScene( elaspedTime ) { + + if ( modelDriver.state.enabled ) { + + var activeObj, trans; + var sceneNode = modelDriver.state.scenes[ modelDriver.kernel.application() ]; + + if ( sceneNode && sceneNode.system ) { + sceneNode.system.integrate( elaspedTime ); + + var activeKeys = Object.keys( modelDriver.state.active ); + if ( activeKeys !== undefined ) { + modelDriver.state.updating = true; + for ( var i = 0; i < activeKeys.length; i++ ) { + activeObj = modelDriver.state.active[ activeKeys[ i ] ]; + if ( activeObj && activeObj.jlObj ) { + trans = activeObj.jlObj.get_Transform(); + modelDriver.kernel.setProperty( activeKeys[ i ], "transform", trans ); + } + } + modelDriver.state.updating = false; + } + + } + + } + } + + } ); diff --git a/support/client/lib/vwf/view/jiglib.js b/support/client/lib/vwf/view/jiglib.js deleted file mode 100644 index bb33550c4..000000000 --- a/support/client/lib/vwf/view/jiglib.js +++ /dev/null @@ -1,144 +0,0 @@ -"use strict"; - -/// @module vwf/view/ -/// @requires vwf/view - -define( [ - "module", - "vwf/view", - "vwf/utility" ], - - function( module, view, utility ) { - - var self; - - return view.load( module, { - - // == Module Definition ==================================================================== - - // -- initialize --------------------------------------------------------------------------- - - initialize: function( options ) { - - self = this; - - this.arguments = Array.prototype.slice.call( arguments ); - - this.options = options || {}; - }, - - // createdNode: function( nodeID, childID, childExtendsID, childImplementsIDs, - // childSource, childType, childIndex, childName, callback ) { - - // }, - - // initializedNode: function( nodeID, childID ) { - - // }, - - - // -- deletedNode -------------------------------------------------------------------------- - - // deletedNode: function( childID ) { - - // if ( this.state.nodes[ childID ] !== undefined ) { - // delete this.state.nodes[ childID ]; - // } - - // }, - - // -- addedChild --------------------------------------------------------------------------- - - //addedChild: function( nodeID, childID, childName ) { }, - - // -- removedChild ------------------------------------------------------------------------- - - //removedChild: function( nodeID, childID ) { }, - - // -- createdProperty ---------------------------------------------------------------------- - - // createdProperty: function( nodeID, propertyName, propertyValue ) { - // this.satProperty( nodeID, propertyName, propertyValue ); - // }, - - // // -- initializedProperty ------------------------------------------------------------------ - - // initializedProperty: function( nodeID, propertyName, propertyValue ) { - // this.satProperty( nodeID, propertyName, propertyValue ); - // }, - - // // TODO: deletedProperty - - // // -- satProperty -------------------------------------------------------------------------- - - // satProperty: function( nodeID, propertyName, propertyValue ) { - // var node = this.state.nodes[ nodeID ]; - - // //this driver has no representation of this node, so there is nothing to do. - // if( node === undefined ) return; - // }, - - // // -- gotProperty -------------------------------------------------------------------------- - - // gotProperty: function( nodeID, propertyName, propertyValue ) { - // var node = this.state.nodes[ nodeID ]; - - // //this driver has no representation of this node, so there is nothing to do. - // if( node === undefined ) return; - // }, - - // // -- calledMethod ------------------------------------------------------------------------- - - // calledMethod: function( nodeID, methodName, methodParameters, methodValue ) { - // }, - - // // -- firedEvent --------------------------------------------------------------------------- - - // firedEvent: function( nodeID, eventName, eventParameters ) { - // }, - - // -- ticked ------------------------------------------------------------------------------- - - ticked: function( vwfTime ) { - var elaspedTime = vwfTime - this.state.lastTime; - this.state.lastTime = vwfTime; - - if ( this.state.enabled ) { - if ( elaspedTime > 0 ) { - if ( elaspedTime > 0.05 ) { - elaspedTime = 0.05; - } - var activeObj, trans; - var sceneNode = this.state.scenes[ this.kernel.application() ]; - - if ( sceneNode && sceneNode.system ) { - sceneNode.system.integrate( elaspedTime ); - - var activeKeys = Object.keys( this.state.active ); - if ( activeKeys !== undefined ) { - this.state.updating = true; - for ( var i = 0; i < activeKeys.length; i++ ) { - activeObj = this.state.active[ activeKeys[ i ] ]; - if ( activeObj && activeObj.jlObj ) { - trans = activeObj.jlObj.get_Transform(); - this.state.setProperty( activeKeys[ i ], "transform", trans ); - //this.kernel.setProperty( activeKeys[ i ], "transform", trans ); - } - } - this.state.updating = false; - } - - } - } - return true; - } - } - - // -- render ------------------------------------------------------------------------------- - - // render: function(renderer, scene, camera) { - // }, - - } ); - -} ); From 58b77691968f741d830427d835942c807677fef4 Mon Sep 17 00:00:00 2001 From: Scott Haynes Date: Thu, 19 Feb 2015 15:47:49 -0500 Subject: [PATCH 19/21] Removes ticking from the threes model --- support/client/lib/vwf/model/threejs.js | 28 +++++++------------------ 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/support/client/lib/vwf/model/threejs.js b/support/client/lib/vwf/model/threejs.js index edb0015c8..d50b5fc4b 100644 --- a/support/client/lib/vwf/model/threejs.js +++ b/support/client/lib/vwf/model/threejs.js @@ -59,7 +59,6 @@ define( [ "module", var self; var checkLights = true; - var sceneCreated = false; return model.load( module, { @@ -182,13 +181,13 @@ define( [ "module", var kernel = this.kernel.kernel.kernel; var protos = getPrototypes.call( this, kernel, childExtendsID ); - if ( isSceneDefinition.call(this, protos) && childID == this.kernel.application() ) + if ( isSceneDefinition.call(this, protos) && childID == appID ) { var sceneNode = CreateThreeJSSceneNode( nodeID, childID, childExtendsID ); this.state.scenes[ childID ] = sceneNode; this.state.cameraInUse = sceneNode.camera.defaultCamera; - sceneCreated = true; + createDefaultLighting.call( this, sceneLights.call( this ) ); if ( childImplementsIDs && childImplementsIDs.length > 0 ) { for ( var i = 0; i < childImplementsIDs.length; i++ ) { @@ -2706,29 +2705,16 @@ define( [ "module", } return undefined; - }, + } // TODO: creatingEvent, deltetingEvent, firingEvent // -- executing ------------------------------------------------------------------------------ - executing: function( nodeID, scriptText, scriptType ) { - return undefined; - }, - - // == ticking ============================================================================= - - ticking: function( vwfTime ) { - - if ( checkLights && this.state.appInitialized && sceneCreated ) { - - var lightsInScene = sceneLights.call( this ); - - createDefaultLighting.call( this, lightsInScene ); - checkLights = false; - } - } + // executing: function( nodeID, scriptText, scriptType ) { + // return undefined; + // } } ); @@ -2737,7 +2723,7 @@ define( [ "module", function checkCompatibility() { this.compatibilityStatus = { compatible:true, errors:{} } var contextNames = ["webgl","experimental-webgl","moz-webgl","webkit-3d"]; - for(var i = 0; i < contextNames.length; i++){ + for( var i = 0; i < contextNames.length; i++){ try{ var canvas = document.createElement('canvas'); var gl = canvas.getContext(contextNames[i]); From a16b240d7d37acfa4f7c4037f63ccdd95bee3341 Mon Sep 17 00:00:00 2001 From: Scott Haynes Date: Thu, 19 Feb 2015 16:11:43 -0500 Subject: [PATCH 20/21] Removes ticking and moves the block exe to update --- support/client/lib/vwf/model/blockly.js | 121 +++++++++++++----------- 1 file changed, 67 insertions(+), 54 deletions(-) diff --git a/support/client/lib/vwf/model/blockly.js b/support/client/lib/vwf/model/blockly.js index 5bdea9eac..7e1a2026b 100644 --- a/support/client/lib/vwf/model/blockly.js +++ b/support/client/lib/vwf/model/blockly.js @@ -23,7 +23,9 @@ define( [ "module", "vwf/model", "vwf/utility", ], function( module, model, utility, acorn, Blockly ) { - var self; + var modelDriver; + var updateTime = -0.05; + var startUpdate = false; return model.load( module, { @@ -33,13 +35,13 @@ define( [ "module", "vwf/model", "vwf/utility", initialize: function( options ) { - self = this; + modelDriver = this; this.arguments = Array.prototype.slice.call( arguments ); - if ( options === undefined ) { - options = {}; - } + this.options = options || {}; + + updateTime = this.options.updateTime || -0.05; this.state = { "nodes": {}, @@ -138,6 +140,13 @@ define( [ "module", "vwf/model", "vwf/utility", this.logger.infox( "initializingNode", nodeID, childID, childExtendsID, childImplementsIDs, childSource, childType, childName ); } + var appID = this.kernel.application(); + if ( childID === appID ) { + if ( !startUpdate ) { + this.kernel.callMethod( appID, "update", [], updateTime ); + startUpdate = true; + } + } }, @@ -308,13 +317,14 @@ define( [ "module", "vwf/model", "vwf/utility", // -- callingMethod -------------------------------------------------------------------------- callingMethod: function( nodeID, methodName /* [, parameter1, parameter2, ... ] */ ) { // TODO: parameters + var appID = this.kernel.application(); var node = this.state.nodes[ nodeID ]; if ( this.debug.methods ) { this.logger.infox( " M === callingMethod ", nodeID, methodName ); } - if ( nodeID == this.kernel.application() ) { + if ( nodeID == appID ) { switch ( methodName ) { @@ -333,6 +343,11 @@ define( [ "module", "vwf/model", "vwf/utility", } break; + case "update": + executeBlocks(); + this.kernel.callMethod( appID, "update", [], updateTime ); + break; + } } else if ( node !== undefined ) { @@ -346,7 +361,7 @@ define( [ "module", "vwf/model", "vwf/utility", break; } } - }, + } // TODO: creatingEvent, deltetingEvent, firingEvent @@ -357,45 +372,6 @@ define( [ "module", "vwf/model", "vwf/utility", // return undefined; //}, - // == ticking ============================================================================= - - ticking: function( vwfTime ) { - - if ( this.state.executingBlocks !== undefined ) { - var blocklyNode = undefined; - - for ( var nodeID in this.state.executingBlocks ) { - - blocklyNode = this.state.executingBlocks[ nodeID ]; - var executeNextLine = false; - - if ( blocklyNode.interpreter === undefined || - blocklyNode.interpreterStatus === "completed" ) { - blocklyNode.interpreter = createInterpreter( acorn, blocklyNode.code ); - blocklyNode.interpreterStatus = "created"; - blocklyNode.lastLineExeTime = vwfTime; - executeNextLine = true; - } else { - var elaspedTime = vwfTime - blocklyNode.lastLineExeTime; - if ( elaspedTime >= blocklyNode.timeBetweenLines ) { - executeNextLine = true; - blocklyNode.lastLineExeTime = vwfTime; - } - } - - if ( executeNextLine ) { - - self.state.executionHalted = false; - - nextStep( blocklyNode ); - - this.kernel.fireEvent( nodeID, "blocklyExecuted", [ blocklyNode.interpreter.value ] ); - } - } - } - - } - } ); function getPrototypes( extendsID ) { @@ -404,14 +380,14 @@ define( [ "module", "vwf/model", "vwf/utility", while ( id !== undefined ) { prototypes.push( id ); - id = self.kernel.prototype( id ); + id = modelDriver.kernel.prototype( id ); } return prototypes; } function isBlockly3Node( nodeID ) { - return self.kernel.test( nodeID, + return modelDriver.kernel.test( nodeID, "self::element(*,'http://vwf.example.com/blockly/controller.vwf')", nodeID ); } @@ -426,6 +402,43 @@ define( [ "module", "vwf/model", "vwf/utility", return found; } + function executeBlocks() { + + if ( modelDriver.state.executingBlocks !== undefined ) { + var blocklyNode = undefined; + + for ( var nodeID in modelDriver.state.executingBlocks ) { + + blocklyNode = modelDriver.state.executingBlocks[ nodeID ]; + var executeNextLine = false; + + if ( blocklyNode.interpreter === undefined || + blocklyNode.interpreterStatus === "completed" ) { + blocklyNode.interpreter = createInterpreter( acorn, blocklyNode.code ); + blocklyNode.interpreterStatus = "created"; + blocklyNode.lastLineExeTime = vwfTime; + executeNextLine = true; + } else { + var elaspedTime = vwfTime - blocklyNode.lastLineExeTime; + if ( elaspedTime >= blocklyNode.timeBetweenLines ) { + executeNextLine = true; + blocklyNode.lastLineExeTime = vwfTime; + } + } + + if ( executeNextLine ) { + + modelDriver.state.executionHalted = false; + + nextStep( blocklyNode ); + + modelDriver.kernel.fireEvent( nodeID, "blocklyExecuted", [ blocklyNode.interpreter.value ] ); + } + } + } + + } + function getJavaScript( node ) { var xml = Blockly.Xml.workspaceToDom( Blockly.getMainWorkspace() ); @@ -459,10 +472,10 @@ define( [ "module", "vwf/model", "vwf/utility", if ( node.interpreter !== undefined ) { var stepType = node.interpreter.step(); - while ( stepType && !self.state.executionHalted ) { + while ( stepType && !modelDriver.state.executionHalted ) { if ( stepType === "stepProgram" ) { if ( node.interpreterStatus === "created" ) { - self.kernel.fireEvent( node.ID, "blocklyStarted", [ true ] ); + modelDriver.kernel.fireEvent( node.ID, "blocklyStarted", [ true ] ); node.interpreterStatus = "started"; } } @@ -470,8 +483,8 @@ define( [ "module", "vwf/model", "vwf/utility", } if ( stepType === false ) { if ( node.interpreterStatus === "started" ) { - self.kernel.setProperty( node.ID, "blockly_executing", false ); - self.kernel.fireEvent( node.ID, "blocklyStopped", [ true ] ); + modelDriver.kernel.setProperty( node.ID, "blockly_executing", false ); + modelDriver.kernel.fireEvent( node.ID, "blocklyStopped", [ true ] ); node.interpreterStatus = "completed"; } } @@ -495,7 +508,7 @@ define( [ "module", "vwf/model", "vwf/utility", for ( var j = 0; j < arguments.length; j++) { parms.push( arguments[ j ].toString() ); } - self.state.executionHalted = true; + modelDriver.state.executionHalted = true; return interpreter.createPrimitive( nativeFunc.apply( vwf, parms ) ); }; } )( vwf[ vwfKernelFunctions[ i ] ] ); @@ -516,7 +529,7 @@ define( [ "module", "vwf/model", "vwf/utility", parms.push( arguments[ j ].toString() ); } } - self.state.executionHalted = true; + modelDriver.state.executionHalted = true; return interpreter.createPrimitive( nativeFunc.apply( vwf, parms ) ); }; } )( vwf[ vwfKernelFunctions[ i ] ] ); From aadaea29071fdffa1ce9cc63fa88edc6e73f3471 Mon Sep 17 00:00:00 2001 From: Scott Haynes Date: Thu, 19 Feb 2015 16:12:18 -0500 Subject: [PATCH 21/21] Removes ticking from the code --- support/client/lib/vwf/model/buzz.js | 9 +-------- support/client/lib/vwf/model/cesium.js | 4 +--- support/client/lib/vwf/model/glge.js | 6 +----- support/client/lib/vwf/model/kineticjs.js | 15 ++++++--------- support/client/lib/vwf/model/mil-sym.js | 10 +--------- 5 files changed, 10 insertions(+), 34 deletions(-) diff --git a/support/client/lib/vwf/model/buzz.js b/support/client/lib/vwf/model/buzz.js index c0c010feb..ae175b85b 100644 --- a/support/client/lib/vwf/model/buzz.js +++ b/support/client/lib/vwf/model/buzz.js @@ -394,7 +394,7 @@ define( [ } - }, + } // TODO: creatingEvent, deltetingEvent, firingEvent @@ -405,13 +405,6 @@ define( [ // return undefined; // }, - // == ticking ============================================================================= - - // ticking: function( vwfTime ) { - - // } - - } ); diff --git a/support/client/lib/vwf/model/cesium.js b/support/client/lib/vwf/model/cesium.js index d47a142dd..7b912cd53 100644 --- a/support/client/lib/vwf/model/cesium.js +++ b/support/client/lib/vwf/model/cesium.js @@ -1966,7 +1966,7 @@ define( [ "module", } return value; - }, + } // TODO: deletingMethod @@ -1986,8 +1986,6 @@ define( [ "module", // return undefined; //}, - // == ticking ============================================================================= - } ); // == PRIVATE ======================================================================================== diff --git a/support/client/lib/vwf/model/glge.js b/support/client/lib/vwf/model/glge.js index 137175fa0..d6c1550d6 100644 --- a/support/client/lib/vwf/model/glge.js +++ b/support/client/lib/vwf/model/glge.js @@ -802,7 +802,7 @@ define( [ "module", "vwf/model", "vwf/utility" ], function( module, model, utili return value; - }, + } // TODO: deletingMethod @@ -822,10 +822,6 @@ define( [ "module", "vwf/model", "vwf/utility" ], function( module, model, utili // return undefined; // }, - // == ticking ============================================================================= - -// ticking: function( vwfTime ) { -// }, } ); diff --git a/support/client/lib/vwf/model/kineticjs.js b/support/client/lib/vwf/model/kineticjs.js index dd7f3bdaf..d08eedaad 100644 --- a/support/client/lib/vwf/model/kineticjs.js +++ b/support/client/lib/vwf/model/kineticjs.js @@ -2062,18 +2062,18 @@ define( [ "module", } return value; - }, + } // TODO: deletingMethod // -- callingMethod -------------------------------------------------------------------------- - callingMethod: function( nodeID, methodName, methodParameters, methodValue ) { - if ( this.debug.methods ) { - this.logger.infox( " M === callingMethod ", nodeID, methodName ); - } - }, + // callingMethod: function( nodeID, methodName, methodParameters, methodValue ) { + // if ( this.debug.methods ) { + // this.logger.infox( " M === callingMethod ", nodeID, methodName ); + // } + // }, // -- executing ------------------------------------------------------------------------------ @@ -2081,9 +2081,6 @@ define( [ "module", // return undefined; // }, - // ticking: function( vwfTime ) { - // } - } ); // == PRIVATE ======================================================================================== diff --git a/support/client/lib/vwf/model/mil-sym.js b/support/client/lib/vwf/model/mil-sym.js index f30941d0e..4566ea477 100644 --- a/support/client/lib/vwf/model/mil-sym.js +++ b/support/client/lib/vwf/model/mil-sym.js @@ -403,7 +403,7 @@ define( [ "module", } return value; - }, + } // TODO: creatingEvent, deltetingEvent, firingEvent @@ -414,14 +414,6 @@ define( [ "module", // return undefined; // }, - // == ticking ============================================================================= - - // ticking: function( vwfTime ) { - - // } - - - } ); function getPrototypes( extendsID ) {