简体   繁体   中英

Aframe: smoothing position and rotation?

I have been experimenting a bit with Aframe and AR.js. For augmented reality applications, a common problem is that the object placed on a marker becomes quite 'jittery' or 'jerky'. I have done some research into the problem already and it appears that a possible way to address this issue is to smooth the rotation and the position over several frames. Unfortunately, tutorials on doing so are virtually nonexistent, and I am just starting to get to grips with Html/Javascript.

Hence my question: Would you know if it is possible to have a function in an aframe entity which extracts the position and rotation, smooths them, and then passes them on to (I imagine) a child entity which uses those smoothed values for placement?

<a-entity position="0 0 0" rotation="0 0 0" >
   <a-video Mysmoothingfunction src="#video" width="3.5" height="2"></a-video>
</a-entity>

I could imagine that the start might look something like this:

<script type="text/javascript"> 
   AFRAME.registerComponent("listener", {
    schema : 
    {
        stepFactor : {
            type : "number",
            default : 0.05
        }
    },
   tick: function() {
       this.getProperty("position"); // something like this?
      }
</script>

Would you have any idea how to tackle that issue?

Your description sounds like linear interpolation . Utilizing it here should be simple:

Once the marker is visible, get the previous video position / rotation, and make an approximation using the actual marker position / rotation. Then update the video , with the approximated values.

The approximation should ease the 'jitter'. In this case, i'll be using the THREE lerp function. If you're not familiar with linear interpolation then think of it as a method of approximation using linear functions (this may be highly imprecise, but it's how i think of it).

The code (attached to the marker) looks like this:

AFRAME.registerComponent("listener", {
  init: function() {
    this.target = document.querySelector('#target'); // your video
    this.prevPosition = null; // initially there is no position or rotation
    this.prevRotation = null;
  },

  tick: function() {
    if (this.el.object3D.visible) {
      this.target.setAttribute('visible', 'true')

      if(!this.prevPosition && !this.prevRotation) { 
        // there are no values to lerp from - set the initial values
        this.target.setAttribute('position', this.el.getAttribute('position'))
        this.target.setAttribute('rotation', this.el.getAttribute('rotation'))
      } else {
        // use the previous values to get an approximation 
        this.target.object3D.position.lerp(this.prevPosition, 0.1)

        // this (below) may seem ugly, but the rotation is a euler, not a THREE.Vector3, 
        // so to use the lerp function i'm doing some probably unnecessary conversions
        let rot = this.target.object3D.rotation.toVector3().lerp(this.prevRotation, 0.1)
        this.target.object3D.rotation.setFromVector3(rot)
      }
      // update the values
      this.prevPosition = this.el.object3D.position
      this.prevRotation = this.el.object3D.rotation
    } else {
     // the marker dissapeared - reset the values
     this.target.setAttribute('visible', 'false')
     this.prevPosition = null;
     this.prevRotation = null;
   }
  }
})

You can notice im setting the values of the object3D instead of the official API ( setAttribute() / getAttribute() ). It should be faster, which is desirable when making changes within the tick() function.

Here is a glitch (one box is interpolated, its moving quite smoothly).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM