I have the following scene:

enter image description here

And I have two 3D vectors, the camera position, and the focus position. The focus vector is always behind the monster. I know how to rotate the camera around the focus with the help of my mouse, but the monster is always facing the same direction, and I'd like to change that!

I'd like it to work almost as in World of Warcraft; while I'm standing still I can move the camera around freely, but as soon as I move, the monster should change the direction according to the camera.position >>> focus vector. Also, I need to make it move in that direction, I guess I could have a 2D vector called speed, which I should change accordingly (it would look like a rotating radius of a circle I guess).

How do I do this?

For reference, I'm working in Three.js, and this is the code with which I rotate the camera:

onDocumentMouseDown = function(event) 

    game.isMouseDown = true;

    game.onMouseDownTheta = game.theta;
    game.onMouseDownPhi = game.phi;
    game.onMouseDownPosition.x = event.clientX;
    game.onMouseDownPosition.y = event.clientY;

onDocumentMouseMove = function(event) 

    if (game.isMouseDown)
        game.theta = -((event.clientX - game.onMouseDownPosition.x) * 0.5) + game.onMouseDownTheta;
        game.phi = ((event.clientY - game.onMouseDownPosition.y) * 0.5) + game.onMouseDownPhi;
        game.phi = Math.min(160, Math.max(20, game.phi));

        game.cameraBuff.x = game.radious * Math.sin(game.theta * Math.PI / 360 ) * Math.cos( game.phi * Math.PI / 360 );
        game.cameraBuff.y = game.radious * Math.sin(game.phi * Math.PI / 360 );
        game.cameraBuff.z = game.radious * Math.cos(game.theta * Math.PI / 360 ) * Math.cos( game.phi * Math.PI / 360 );

And at render time I do this:

self.camera.position.x += self.cameraBuff.x;
self.camera.position.y += self.cameraBuff.y;
self.camera.position.z += self.cameraBuff.z;

self.renderer.render(self.scene, self.camera);

self.camera.position.x -= self.cameraBuff.x;
self.camera.position.y -= self.cameraBuff.y;
self.camera.position.z -= self.cameraBuff.z;
  • \$\begingroup\$ are you storing camera's and player's direction as a vector? this should help a lot. \$\endgroup\$ – Gustavo Maciel May 26 '12 at 18:10
  • \$\begingroup\$ No, there's no direction at all! \$\endgroup\$ – jcora May 26 '12 at 18:19
  • \$\begingroup\$ (I mean, only positions are stored. The objects have a rotation vector, but that doesn't affect direction at all.) \$\endgroup\$ – jcora May 26 '12 at 18:58
  • \$\begingroup\$ the rotation vector IS the direction vector. Try making direction = normalize(position - focus) should work. \$\endgroup\$ – Gustavo Maciel May 26 '12 at 23:16

If you know how to turn the mesh to a desired rotation vector, you can just get the direction the object should walk with the following formula direction = normalize(position - focus) Where position is the mesh position and focus is your focus position. If the focus is really behind the mesh as you said, just multiply it by -1.

If as you said, you can't use the focus here, you can do the same with the camera position direction = normalize(position - camera) Multiply by -1, and as you want to move just on the XZ plane, set Y to 0. Should look like this:

direction = position - camera;
direction.Y = 0;
direction = normalize(direction);
direction *= -1;
  • \$\begingroup\$ But the focus point is the mesh position! So I'd just get [0, 0, 0]... Maybe I should do it with the camera position, that makes sense. \$\endgroup\$ – jcora May 27 '12 at 9:38
  • \$\begingroup\$ Haven't you said the focus point is behind the position? You can still make it with the camera position, true, but you should set your Y component to 0. \$\endgroup\$ – Gustavo Maciel May 27 '12 at 16:04
  • \$\begingroup\$ Focus point = mesh position, forgot to mention, which is technically a bit "behind" the actual mesh. I did it like this: var c = Math.sqrt(cameraPos.x*cameraPos.x + cameraPos.z*cameraPos.z); var rat = 1/c; mesh.direction.x = cameraPos.x*rat; mesh.monster.direction.z = cameraPos.z*rat; Assuming that the mesh's position is 0, I translate it so it is. \$\endgroup\$ – jcora May 27 '12 at 16:07
  • \$\begingroup\$ Also, I'm not sure if this works. If I were to rotate it, it would paint a square, that is, the speed would vary depending on the direction. I need it to paint a circle, so I'm using the Pythagora's theorem. \$\endgroup\$ – jcora May 27 '12 at 16:09
  • \$\begingroup\$ that's why we have the normalize function there. \$\endgroup\$ – Gustavo Maciel May 27 '12 at 17:11

I assume you still want the monster to stand upright, so if you want it to face away from the camera while aligned to the ground, simply create a LookAt rotation matrix like so: LookAt(eyePos, targetPos, up) where eyePos would be monster.pos, targetPos would be [monster.pos.x - camera.pos.x, monster.pos.y - camera.pos.y, monster.pos.z] (ignoring the camera's height), and up would be [0,0,1] , assuming z is the "up" axis. If there is no LookAt matrix function provided, you find find an implementation here


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.