4
\$\begingroup\$

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) 
{
    event.preventDefault();

    game.isMouseDown = true;

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

onDocumentMouseMove = function(event) 
{
    event.preventDefault();

    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.camera.lookAt(self.focus);
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;
\$\endgroup\$
4
  • \$\begingroup\$ are you storing camera's and player's direction as a vector? this should help a lot. \$\endgroup\$ May 26, 2012 at 18:10
  • \$\begingroup\$ No, there's no direction at all! \$\endgroup\$
    – jcora
    May 26, 2012 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, 2012 at 18:58
  • \$\begingroup\$ the rotation vector IS the direction vector. Try making direction = normalize(position - focus) should work. \$\endgroup\$ May 26, 2012 at 23:16

2 Answers 2

2
\$\begingroup\$

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;
\$\endgroup\$
5
  • \$\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, 2012 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\$ May 27, 2012 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, 2012 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, 2012 at 16:09
  • \$\begingroup\$ that's why we have the normalize function there. \$\endgroup\$ May 27, 2012 at 17:11
0
\$\begingroup\$

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

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .