|
@@ -1,4 +1,9 @@
|
|
-/* Interpolate component for A-Frame VR. https://github.com/scenevr/aframe-interpolate-component.git
|
|
|
|
|
|
+/*
|
|
|
|
+The MIT License (MIT)
|
|
|
|
+Copyright (c) 2017 Nikolai Suslov
|
|
|
|
+Updated for using in LiveCoding.space and A-Frame 0.6.x
|
|
|
|
+
|
|
|
|
+Interpolate component for A-Frame VR. https://github.com/scenevr/aframe-interpolate-component.git
|
|
|
|
|
|
The MIT License (MIT)
|
|
The MIT License (MIT)
|
|
|
|
|
|
@@ -30,93 +35,121 @@ if (typeof AFRAME === 'undefined') {
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-function radians(degrees) {
|
|
|
|
- // return degrees * Math.PI / 180.0;
|
|
|
|
- return THREE.Math.degToRad(degrees)
|
|
|
|
-}
|
|
|
|
|
|
+class Interpolator {
|
|
|
|
+ constructor(comp) {
|
|
|
|
+ this.component = comp;
|
|
|
|
+ this.time = this.getMillis();
|
|
|
|
+ }
|
|
|
|
|
|
-function RotationInterpolator(timestep, entity) {
|
|
|
|
- var time = getMillis();
|
|
|
|
- var previous;
|
|
|
|
- var next;
|
|
|
|
- var e = new THREE.Euler();
|
|
|
|
- var q = new THREE.Quaternion();
|
|
|
|
|
|
+ active() {
|
|
|
|
+ return this.previous && this.next && (this.getTime() < 1);
|
|
|
|
+ }
|
|
|
|
|
|
- entity.el.addEventListener('componentchanged', function (event) {
|
|
|
|
- if (getTime() < 0.5 || getTime() == 0) {
|
|
|
|
- // fixme - ignore multiple calls
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+ getMillis() {
|
|
|
|
+ return new Date().getTime();
|
|
|
|
+ }
|
|
|
|
|
|
- if (event.detail.name === 'rotation') {
|
|
|
|
- if (!previous) {
|
|
|
|
- previous = new THREE.Quaternion();
|
|
|
|
- next = new THREE.Quaternion();
|
|
|
|
- }
|
|
|
|
|
|
+ getTime() {
|
|
|
|
+ return (this.getMillis() - this.time) / this.component.timestep;
|
|
|
|
+ }
|
|
|
|
|
|
- time = getMillis();
|
|
|
|
- previous.copy(next);
|
|
|
|
- next.setFromEuler(new THREE.Euler(
|
|
|
|
- radians(event.detail.newData.x),
|
|
|
|
- radians(event.detail.newData.y),
|
|
|
|
- radians(event.detail.newData.z), 'YXZ'
|
|
|
|
- ));
|
|
|
|
|
|
+ vecCmp(a, b, delta) {
|
|
|
|
+
|
|
|
|
+ let distance = a.distanceTo(b);
|
|
|
|
+ if (distance > delta) {
|
|
|
|
+ return false;
|
|
}
|
|
}
|
|
- });
|
|
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+class RotationInterpolator extends Interpolator {
|
|
|
|
|
|
- // var data = this.data;
|
|
|
|
- // var object3D = this.el.object3D;
|
|
|
|
- // object3D.rotation.set(degToRad(data.x), degToRad(data.y), degToRad(data.z));
|
|
|
|
- // object3D.rotation.order = 'YXZ';
|
|
|
|
|
|
+ constructor(comp) {
|
|
|
|
+ super(comp);
|
|
|
|
|
|
|
|
+ this.lastRotation = this.component.el.getAttribute('rotation');
|
|
|
|
+ this.previous = (new THREE.Quaternion()).setFromEuler(new THREE.Euler(
|
|
|
|
+ this.radians(this.lastRotation.x),
|
|
|
|
+ this.radians(this.lastRotation.y),
|
|
|
|
+ this.radians(this.lastRotation.z), 'YXZ'
|
|
|
|
+ ));
|
|
|
|
+ this.next = (new THREE.Quaternion()).setFromEuler(new THREE.Euler(
|
|
|
|
+ this.radians(this.lastRotation.x),
|
|
|
|
+ this.radians(this.lastRotation.y),
|
|
|
|
+ this.radians(this.lastRotation.z), 'YXZ'
|
|
|
|
+ ));
|
|
|
|
|
|
|
|
|
|
- function getTime() {
|
|
|
|
- return (getMillis() - time) / timestep;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- this.active = function () {
|
|
|
|
- return previous && next && (getTime() < 1);
|
|
|
|
- };
|
|
|
|
|
|
+ radians(degrees) {
|
|
|
|
+ // return degrees * Math.PI / 180.0;
|
|
|
|
+ return THREE.Math.degToRad(degrees)
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ makeInterpolation() {
|
|
|
|
+ let q = new THREE.Quaternion();
|
|
|
|
+ let e = new THREE.Euler();
|
|
|
|
|
|
- this.get = function () {
|
|
|
|
- THREE.Quaternion.slerp(previous, next, q, getTime());
|
|
|
|
|
|
+ THREE.Quaternion.slerp(this.previous, this.next, q, this.getTime());
|
|
return e.setFromQuaternion(q);
|
|
return e.setFromQuaternion(q);
|
|
- };
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-class Interpolator {
|
|
|
|
- constructor(comp) {
|
|
|
|
- this.component = comp;
|
|
|
|
- this.time = this.getMillis();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- active() {
|
|
|
|
- return this.previous && this.next && (this.getTime() < 1);
|
|
|
|
- }
|
|
|
|
|
|
+ testForLerp() {
|
|
|
|
|
|
- getMillis() {
|
|
|
|
- return new Date().getTime();
|
|
|
|
- }
|
|
|
|
|
|
+ if (this.component.deltaRot == 0) {
|
|
|
|
+ return true
|
|
|
|
+ }
|
|
|
|
|
|
- getTime() {
|
|
|
|
- return (this.getMillis() - this.time) / this.component.timestep;
|
|
|
|
|
|
+ let prev = (new THREE.Euler()).setFromQuaternion(this.previous).toVector3();
|
|
|
|
+ let next = (new THREE.Euler()).setFromQuaternion(this.next).toVector3();
|
|
|
|
+
|
|
|
|
+ if (prev && next && this.vecCmp(prev, next, this.component.deltaRot)) {
|
|
|
|
+ return true
|
|
|
|
+ }
|
|
|
|
+ return false
|
|
}
|
|
}
|
|
|
|
|
|
-}
|
|
|
|
|
|
|
|
-// class RotationInterpolator extends Interpolator {
|
|
|
|
-
|
|
|
|
-// constructor(comp) {
|
|
|
|
-// super(comp);
|
|
|
|
|
|
+ inTick(currentRotation) {
|
|
|
|
+
|
|
|
|
+ if (this.getTime() < 0.5) {
|
|
|
|
+ // fixme - ignore multiple calls
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ if (!this.previous) {
|
|
|
|
+ // this.previous = new THREE.Quaternion();
|
|
|
|
+ // this.next = new THREE.Quaternion();
|
|
|
|
+ this.previous = (new THREE.Quaternion()).setFromEuler(new THREE.Euler(
|
|
|
|
+ this.radians(this.lastRotation.x),
|
|
|
|
+ this.radians(this.lastRotation.y),
|
|
|
|
+ this.radians(this.lastRotation.z), 'YXZ'
|
|
|
|
+ ));
|
|
|
|
+
|
|
|
|
+ this.next = (new THREE.Quaternion()).setFromEuler(new THREE.Euler(
|
|
|
|
+ this.radians(currentRotation.x),
|
|
|
|
+ this.radians(currentRotation.y),
|
|
|
|
+ this.radians(currentRotation.z), 'YXZ'
|
|
|
|
+ ));
|
|
|
|
+ }
|
|
|
|
|
|
-// this.previous = new THREE.Quaternion();
|
|
|
|
-// this.next = new THREE.Quaternion();
|
|
|
|
|
|
+ this.time = this.getMillis();
|
|
|
|
+ this.previous.copy(this.next);
|
|
|
|
+ this.next.setFromEuler(new THREE.Euler(
|
|
|
|
+ this.radians(currentRotation.x),
|
|
|
|
+ this.radians(currentRotation.y),
|
|
|
|
+ this.radians(currentRotation.z), 'YXZ'
|
|
|
|
+ ));
|
|
|
|
|
|
-
|
|
|
|
-// }
|
|
|
|
-// }
|
|
|
|
|
|
+ this.lastRotation = currentRotation;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
|
|
|
|
|
|
class PositionInterpolator extends Interpolator {
|
|
class PositionInterpolator extends Interpolator {
|
|
@@ -129,27 +162,24 @@ class PositionInterpolator extends Interpolator {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- vecCmp(a, b, delta) {
|
|
|
|
|
|
|
|
- let distance = a.distanceTo(b);
|
|
|
|
- if (distance > delta) {
|
|
|
|
- return false;
|
|
|
|
|
|
+ testForLerp() {
|
|
|
|
+
|
|
|
|
+ if (this.component.deltaPos == 0) {
|
|
|
|
+ return true
|
|
}
|
|
}
|
|
- return true;
|
|
|
|
- }
|
|
|
|
|
|
|
|
- testForLerp() {
|
|
|
|
- if (this.previous && this.next && this.vecCmp(this.previous, this.next, this.component.delta)) {
|
|
|
|
|
|
+ if (this.previous && this.next && this.vecCmp(this.previous, this.next, this.component.deltaPos)) {
|
|
return true
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
return false
|
|
}
|
|
}
|
|
|
|
|
|
- get() {
|
|
|
|
|
|
+ makeInterpolation() {
|
|
return this.previous.lerp(this.next, this.getTime());
|
|
return this.previous.lerp(this.next, this.getTime());
|
|
}
|
|
}
|
|
|
|
|
|
- tick(currentPosition) {
|
|
|
|
|
|
+ inTick(currentPosition) {
|
|
|
|
|
|
if (this.getTime() < 0.5) {
|
|
if (this.getTime() < 0.5) {
|
|
// fixme - ignore multiple calls
|
|
// fixme - ignore multiple calls
|
|
@@ -178,7 +208,8 @@ AFRAME.registerComponent('interpolation', {
|
|
schema: {
|
|
schema: {
|
|
duration: { default: 50 },
|
|
duration: { default: 50 },
|
|
enabled: { default: true },
|
|
enabled: { default: true },
|
|
- delta: { default: 0.5 }
|
|
|
|
|
|
+ deltaPos: { default: 0 },
|
|
|
|
+ deltaRot: { default: 0 }
|
|
},
|
|
},
|
|
|
|
|
|
|
|
|
|
@@ -214,10 +245,15 @@ AFRAME.registerComponent('interpolation', {
|
|
|
|
|
|
if (!this.interpolation) {
|
|
if (!this.interpolation) {
|
|
this.timestep = parseInt(this.data.duration, 10);
|
|
this.timestep = parseInt(this.data.duration, 10);
|
|
- this.delta = parseFloat(this.data.delta);
|
|
|
|
|
|
+ this.deltaPos = parseFloat(this.data.deltaPos);
|
|
|
|
+ this.deltaRot = THREE.Math.degToRad(parseFloat(this.data.deltaRot));
|
|
|
|
|
|
- this.posInterpolator = new PositionInterpolator(this);
|
|
|
|
|
|
+ this.enabled = JSON.parse(this.data.enabled);
|
|
|
|
|
|
|
|
+ if (this.enabled) {
|
|
|
|
+ this.posInterpolator = new PositionInterpolator(this);
|
|
|
|
+ this.rotInterpolator = new RotationInterpolator(this);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
// if (!this.interpolation) {
|
|
// if (!this.interpolation) {
|
|
@@ -240,20 +276,26 @@ AFRAME.registerComponent('interpolation', {
|
|
tick: function (t, dt) {
|
|
tick: function (t, dt) {
|
|
|
|
|
|
let currentPosition = this.el.getAttribute('position');
|
|
let currentPosition = this.el.getAttribute('position');
|
|
|
|
+ let currentRotation = this.el.getAttribute('rotation');
|
|
|
|
|
|
- //if (this.checkForLerp(this.lastPosition, currentPosition)) {
|
|
|
|
-
|
|
|
|
- if (this.posInterpolator.lastPosition != currentPosition) {
|
|
|
|
- this.posInterpolator.tick(currentPosition)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
|
|
+ if (this.enabled) {
|
|
|
|
|
|
- if (this.posInterpolator.active() && this.posInterpolator.testForLerp()) {
|
|
|
|
- this.el.object3D.position.copy(this.posInterpolator.get());
|
|
|
|
- }
|
|
|
|
|
|
+ if (this.posInterpolator.lastPosition != currentPosition) {
|
|
|
|
+ this.posInterpolator.inTick(currentPosition)
|
|
|
|
+ }
|
|
|
|
+ if (this.posInterpolator.active() && this.posInterpolator.testForLerp()) {
|
|
|
|
+ this.el.object3D.position.copy(this.posInterpolator.makeInterpolation());
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
|
|
+ if (this.rotInterpolator.lastRotation != currentRotation) {
|
|
|
|
+ this.rotInterpolator.inTick(currentRotation)
|
|
|
|
+ }
|
|
|
|
+ if (this.rotInterpolator.active() && this.rotInterpolator.testForLerp()) {
|
|
|
|
+ this.el.object3D.rotation.copy(this.rotInterpolator.makeInterpolation());
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ }
|
|
|
|
|
|
// if (this.positionInterpolator && this.positionInterpolator.active()) {
|
|
// if (this.positionInterpolator && this.positionInterpolator.active()) {
|
|
// this.el.object3D.position.copy(this.positionInterpolator.get());
|
|
// this.el.object3D.position.copy(this.positionInterpolator.get());
|