/* The MIT License (MIT) Copyright (c) 2014-2018 Nikolai Suslov and the Krestianstvo.org project contributors. (https://github.com/NikolaySuslov/livecodingspace/blob/master/LICENSE.md) */ if (typeof AFRAME === 'undefined') { throw new Error('Component attempted to register before AFRAME was available.'); } AFRAME.registerComponent('interpolation', { schema: { enabled: { default: true }, deltaPos: { default: 0.001 }, deltaRot: { default: 0.1 } }, init: function () { this.driver = vwf.views["vwf/view/aframeComponent"]; this.tickTime = 0; }, update: function (oldData) { if (!this.interpolation) { this.deltaPos = parseFloat(this.data.deltaPos); this.deltaRot = THREE.Math.degToRad(parseFloat(this.data.deltaRot)); this.enabled = JSON.parse(this.data.enabled); if (this.enabled) { } } }, /** * Called when a component is removed (e.g., via removeAttribute). * Generally undoes all modifications to the entity. */ remove: function () { }, /** * Called on each scene tick. */ tick: function (t, dt) { if (!this.node) { let interNode = Object.entries(this.driver.state.nodes).find(el => el[1].parentID == this.el.id && el[1].extendsID == "http://vwf.example.com/aframe/interpolation-component.vwf" ); this.node = this.driver.nodes[interNode[0]]; this.nodeState = interNode[1]; } if (this.enabled && this.node && this.node.interpolate) { this.setInterpolatedTransformsNew(dt); //this.applyViewTransformOverridesNew(timepassed); //this.setInterpolatedTransforms(dt); //this.restoreTransforms(); } }, setInterpolatedTransformsNew: function(deltaTime) { //deltaTime = Math.min(deltaTime,this.realTickDif) this.tickTime += deltaTime || 0; var hit = 0; while (this.tickTime > 50) { hit++; this.tickTime -= 50; } var step = (this.tickTime) / (50); if (hit === 1) { this.resetInterpolationNew(); } 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.interpolateOneNode(lerpStep,step); }, resetInterpolationNew: function() { //don't do interpolation for static objects //if (this.nodes[i].isStatic) continue; if (this.node.lastTransformStep + 1 < vwf.time()) { this.node.lastTickTransform = null; this.node.lastFrameInterp = null; this.node.thisTickTransform = null; } else if (this.nodeState) { if(!this.node.thisTickTransform) this.node.thisTickTransform = new THREE.Vector3(); this.node.lastTickTransform = (new THREE.Vector3()).copy(this.node.thisTickTransform); //matset(this.nodes[i].lastTickTransform, this.nodes[i].thisTickTransform); this.node.thisTickTransform = (new THREE.Vector3()).copy(this.nodeState.aframeObj.el.object3D.position)//this.nodeState.gettingProperty('position')); //matset(this.nodes[i].thisTickTransform, this.state.nodes[i].gettingProperty('transform')); } }, interpolateOneNode:function(lerpStep,step) { //don't do interpolation for static objects //if (this.nodes[i].isStatic) return; if(this.node.lastTickTransform && this.node.thisTickTransform) { var interp = null; var last = (new THREE.Vector3()).copy(this.node.lastTickTransform); var now = (new THREE.Vector3()).copy(this.node.thisTickTransform); if (last && now) { interp = (new THREE.Vector3()).copy(last); //matset(interp, last); interp = last.lerp(now, step); //interp = this.matrixLerp(last, now, step, interp); this.node.currentTickTransform = (new THREE.Vector3()).copy(this.nodeState.aframeObj.el.object3D.position)//this.nodeState.gettingProperty('position'))//matset(this.nodes[i].currentTickTransform, this.state.nodes[i].gettingProperty('transform')); if (this.node.lastFrameInterp) // interp = this.matrixLerp(this.node.lastFrameInterp, now, lerpStep, interp); interp = this.node.lastFrameInterp.lerp(now, lerpStep); //this.state.node.setTransformInternal(interp, false); this.el.object3D.position.set(interp.x, interp.y, interp.z); this.node.lastFrameInterp = (new THREE.Vector3()).copy(interp) //matset(this.nodes[i].lastFrameInterp || [], interp); } } }, vecCmp: function (a, b, delta) { let distance = a.distanceTo(b); if (distance > delta) { return false; } return true; }, restoreTransforms: function () { let r = new THREE.Euler(); let rot = r.copy(this.node.interpolate.rotation.selfTick); if (rot && this.node.needTransformRestore) { this.el.object3D.rotation.set(rot.x, rot.y, rot.z) this.node.needTransformRestore = false; } }, setInterpolatedTransforms: function (deltaTime) { var step = (this.node.tickTime) / (this.driver.realTickDif); step = Math.min(step, 1); deltaTime = Math.min(deltaTime, this.driver.realTickDif) this.node.tickTime += deltaTime || 0; this.interpolatePosition(step); this.interpolateRotation(step); }, radians: function (degrees) { // return degrees * Math.PI / 180.0; return THREE.Math.degToRad(degrees) }, interpolateRotation: function (step) { let last = this.node.interpolate.rotation.lastTick; let now = this.node.interpolate.rotation.selfTick; if (last && now) { let comp = this.vecCmp(last.toVector3(), now.toVector3(), this.deltaRot); if (!comp) { // console.log('Last:', last, ' Now: ', now); let lastV = (new THREE.Quaternion()).setFromEuler(new THREE.Euler( (last.x), (last.y), (last.z), 'YXZ' )); let nowV = (new THREE.Quaternion()).setFromEuler(new THREE.Euler( (now.x), (now.y), (now.z), 'YXZ' )); let q = new THREE.Quaternion(); let e = new THREE.Euler(); THREE.Quaternion.slerp(lastV, nowV, q, step || 0); let interp = e.setFromQuaternion(q, 'YXZ'); this.el.object3D.rotation.set(interp.x, interp.y, interp.z); this.node.needTransformRestore = true; } } }, interpolatePosition: function (step) { var last = this.node.interpolate.position.lastTick; //this.node.lastTickTransform; var now = this.node.interpolate.position.selfTick; //Transform; if (last && now) { let comp = this.vecCmp(last, now, this.deltaPos); if (!comp) { var lastV = (new THREE.Vector3()).copy(last); var nowV = (new THREE.Vector3()).copy(now); var interp = lastV.lerp(nowV, step || 0); //this.el.setAttribute('position',interp); this.el.object3D.position.set(interp.x, interp.y, interp.z); this.node.needTransformRestore = true; } } }, pause: function () { }, play: function () { } });