enguerranws
enguerranws

Reputation: 8233

Three.js : Best way to translate the projection?

I'm currently using threex.webar (https://github.com/jeromeetienne/threex.webar) on a project (Three.js with ArucoJS). Right now, I'm trying to make a projection (markerObject3D) based on a AR marker, but I want it to be next to the marker, not on it.

Here's how I achieved that, using Three.js translatex() :

function render() {

    translateMarker3D(markerObject3D);
        movieMaterial.update();
        backgroundTexture.update();
        effect.render(scene, camera)
}
function translateMarker3D(marker3D) {
       marker3D.translateX( 80 );
}  

The thing is : it kinda work. It flickers a lot, when it's great without translation (so : it flickers when it's next to the marker, but great when it's on it).

I also tried to change aruco's returning values (in threex.jsarucomarker.js):

object3d.position.x = translation[0] + 80;

But it renders exactly the same, flickering.

So my question is: what is the best way to make a projection next to an AR marker with Three.js?

EDIT :

As live demo would be hard to set up, I just uploaded a video on Youtube to illustrate my point : https://www.youtube.com/watch?v=SM1dZ29SZRk&feature=youtu.be

However, you can see the full code here : https://github.com/cned-di-dev/three-ar-proto/blob/master/tests/stereoscopic/index.html

What I am missing :

Things to know: I'm not really good in 3D stuff (geometry, matrix, etc.).

Upvotes: 1

Views: 1178

Answers (1)

micnil
micnil

Reputation: 4805

It was a bit hard to understand what you mean by "flickering". But after some testing, I think I know what you mean. I think the problem is that the detectMarkers() function can not find the exact same marker position every frame and that the markerObject is first rotated and then translated.

Since the marker will get a small variation in rotation each frame, and is translated along its new x-axis, the markerObject will jump up and down, and the amplitude of this will be greater the further you translate it.

Now, the solution depends on what requirements you have for the behaviour of this translation. One way would be to just translate the markerObject along the global x-axis instead. This can be achieved by giving the markerObject a parent and translate that instead:

var markerParent = new THREE.Object3D();
var markerObject3D = new THREE.Object3D();
markerParent.add(markerObject3D);
markerParent.translateX(80); // you can do this just one time
scene.add(markerParent)

Another way is to change the order of transformation in the source of markerToObject3D(marker, object3d), so that the translation is done before the rotation (and add your transation to object3d.position.x).

If you do not want to translate the markerObject along the global x-axis, but along its local, it will be a bit harder to get rid of the flickering. One way would be to give the markerObject the average translation of the last few frames instead of letting JsArucoMarker calculate a new one for you each frame. Or, maybe even better, giving it an average rotation of the last few frames.

Another way to make the movement smoother could be to interpolate its positions each frames, this will make it alot less "jumpy"

EDIT

I watched your video which confirmed one of the problems with the translation as illustrated in this picture: enter image description here

This only illustrates the leverage of the rotation around the local z-axis, but the same happens with the rotation around the x and y axis. The translation will make the error of the markerdetection look greater. And as I said before, you can hide this effect a little by giving the markerObject an average translation of the last few frames.

I also noticed that the marker sometimes "swooshed" to the side. This is also because the markerDetection is not perfect, and during some frames, it does not find the marker at all. When it does not find the marker, you still translate the markerObject by 40, adding upon the translation that was done last frame. What you should do is:

remove line 359:

translateMarker3D(markerObject3D);

and add this to line 323:

markerObject3D.translateX(40);

By doing this, you translate the markerObject only if it can detect the marker.

Upvotes: 2

Related Questions