J o
J o

Reputation: 104

Three.js Object3d child lookAt camera position

I am struggling with an Object3D which child meshes should look at the camera position.
It works fine, if the camera is "far" away, but not if the camera moves towards the object.

Than, if the camera position is near to the object position, the second added plane rotates, until the camera look at the edge of the plan.

And I have know idea why this behavior appears just on the second added plane and just if the camera is near the object position.

Here is what i have so far.
Create the Object:

var obj = new THREE.Object3D();
obj.position.set( x, y, z );
var Uniforms = {
    texturePrimary:     { type: "t", value: Texture },
    textureColorGraph:  { type: "t", value: ColorGraph },
    time:               { type: "f", value: 0 },
    color:  { type: "f", value: 0 }
};

obj.Uniforms = Uniforms;
obj.add( makeplane1( 3.2, Uniforms ) );
obj.add( makeplane2( 25, Uniforms ) );

obj.update = function( pos ){
    this.Uniforms.time.value = shaderTiming;
    $.each(this.children, function(i,mesh){
        if( mesh.name === "plane1" || mesh.name === "plane2"){
            var vec = mesh.parent.worldToLocal( pos );
            mesh.lookAt( vec );
        }
    });
};

function makePlane1( radius, uniforms ){
  var Geo = new THREE.PlaneGeometry( radius, radius );
  var Material = new THREE.ShaderMaterial(
      {
        uniforms:       uniforms,
        vertexShader:   shaders[1].vertex,
        fragmentShader: shaders[1].fragment,
        blending: THREE.AdditiveBlending,
        transparent: true
      };

var plane = new THREE.Mesh( Geo, Material );
plane.name = "plane1";
return plane;
);

function makePlane2( radius, uniforms ){
  var Geo = new THREE.PlaneGeometry( radius, radius );
  var Material = new THREE.ShaderMaterial(
      {
        uniforms:       uniforms,
        vertexShader:   shaders[2].vertex,
        fragmentShader: shaders[2].fragment,
        blending: THREE.AdditiveBlending,
        transparent: true
      };
);

var plane = new THREE.Mesh( Geo, Material );
plane.name = "plane2";
return plane;
}

I could call this.lookAt( pos ) in obj.update( pos ) to rotate the whole object, but other meshes should not rotate that way, so that is sadly no option.

And a simple vertex shader for both planes:

varying vec2 vUv;
void main() {
  gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
  vUv = uv;
}

And then i call in the animationloop:

$.each(scene.children, function(i, obj){
    if( obj.update !== undefined ) {
        shaderTiming = (time - startTime )/ 1000;
        obj.update( camera.getWorldPosition() );
    }   
});

EDIT: I Just noticed that this behavior just occur, if the object's position is not (0,0,0). If so it works just like it should at any camera position.
Also a simple distance calculation, object to camera, is not working properly.

vec1 = this.position;
vec2 = camera.position;
var dist = Math.sqrt(Math.pow(vec1.x - vec2.x, 2) + Math.pow(vec1.y - vec2.y, 2) + Math.pow(vec1.z - vec2.z, 2));

Thanks for any hints.

Upvotes: 0

Views: 554

Answers (1)

WestLangley
WestLangley

Reputation: 104833

Object3D.lookAt() does not support objects with rotated and/or translated parent(s).

three.js r.85

Upvotes: 0

Related Questions