Head Rotation + Looking at Characters
by Trevor "PointDestruction" · in Torque Game Engine · 06/08/2004 (4:32 am) · 21 replies
K, i'm making an RPG (if you havnt read my client map loading post). And my problem is that i'm trying to get my character's to actually look at eachother by just rotating their head to view the other characters.
Now, this is basically all I know. I know that I need to get the direction vector between the two characters, then adjust their head to that rotation. The problem is that if the vector has no rotation, the head is looking straight forward (like you are looking at your comp screen right now).
I separated mHead into 2 parts: mHead and mHeadVect. mHeadVect is the actual physical vector of the head. mHead then has the actual look vector so that the camera stuff all stayed good to go.
Thats basically how i've kind of started out, but I'm really having troubles understanding the math. Anyone have any ideas?
For those that are going to help, just assume that mHeadVect is a VectorF and that is the correct orientation of the head. (remember that no orientation is perfectly center looking straight forward). Also assume that mLookAtTarget is the ShapeBase object that i'm supposed to be looking at.
Now, this is basically all I know. I know that I need to get the direction vector between the two characters, then adjust their head to that rotation. The problem is that if the vector has no rotation, the head is looking straight forward (like you are looking at your comp screen right now).
I separated mHead into 2 parts: mHead and mHeadVect. mHeadVect is the actual physical vector of the head. mHead then has the actual look vector so that the camera stuff all stayed good to go.
VectorF vec = getPosition() - mLookAtTarget->getPosition();
vec.normalize();
mHeadVect.z = mRot.z - vec.y;
mHeadVect.x = vec.z;Thats basically how i've kind of started out, but I'm really having troubles understanding the math. Anyone have any ideas?
For those that are going to help, just assume that mHeadVect is a VectorF and that is the correct orientation of the head. (remember that no orientation is perfectly center looking straight forward). Also assume that mLookAtTarget is the ShapeBase object that i'm supposed to be looking at.
About the author
#2
In any case, yes, the subtraction gives you a vector that describes the direction and distance from the looker's position to the target's position. Normalizing it makes that vector 1 unit long, but it still describes the direction.
06/08/2004 (8:51 am)
You've got your vector backwards. Do this instead:VectorF vec = mLookAtTarget->getPosition() - getPosition(); vec.normalize();I don't understand quite what you mean by mHeadVect. Too bad you can't just walk over to my whiteboard and draw it.
In any case, yes, the subtraction gives you a vector that describes the direction and distance from the looker's position to the target's position. Normalizing it makes that vector 1 unit long, but it still describes the direction.
#3
06/08/2004 (2:27 pm)
Well ... I'm not sure that I have it backwards because i'll be describing the angles from me to the other character?
#4
06/08/2004 (2:34 pm)
Oh, and mHeadVect is the vector that the head will look at. (0,0,0) means his head is looking straightforward - so its sort of a "local rotation" to each character.
#5
Does anybody even know what im trying to do?
06/08/2004 (4:59 pm)
Does ANYBODY know how to do this??Does anybody even know what im trying to do?
#6
06/08/2004 (9:54 pm)
I think Eric is right... and I don't really see what question you're asking... :-/
#7
06/08/2004 (10:22 pm)
Ok so all together you want your characters to be able to 'look' at each other with out turning their bodies as they are walking past or just standing there? I've seen this before in some games, can't think of what they are called now. Not sure how to do it though!
#8
if you want to get a vector from a position to a target, it's
06/08/2004 (11:07 pm)
Yeah, you have the vector backwards... if you want to get a vector from a position to a target, it's
target - positionso it would be
VectorF vec = mLookAtTarget->getPosition() - getPosition();Not quite what you want but I have a function to aim the camera at a certain position, maybe it can give you some ideas...
void Camera::lookAt(Point3F &dir, const Point3F &pos, const Point3F &lookAtPos)
{
// get the vector from pos to the lookAtPos
Point3F vec = lookAtPos - pos;
// create a full matrix out of the vector
MatrixF m = MathUtils::createOrientFromDir(vec);
// set the position
m.setColumn(3,pos);
// set the camera transform
setTransform(m);
}
ConsoleMethod( Camera, lookAt, void, 4, 4, "")
{
Point3F dir, pos, lookAtPos;
Camera *camObj = (Camera *) object;
camObj->setControlDirty();
dSscanf(argv[2],"%f %f %f",
&pos.x,&pos.y,&pos.z);
dSscanf(argv[3],"%f %f %f",
&lookAtPos.x,&lookAtPos.y,&lookAtPos.z);
camObj->lookAt(dir, pos, lookAtPos);
}%eyeTransform = %client.player.getEyeTransform(); %eyePoint = firstWord(%eyeTransform) SPC getWord(%eyeTransform, 1) SPC getWord(%eyeTransform, 2); %client.camera.lookAt(%eyePoint, %objPos); %client.setControlObject(%client.camera);
#9
The biggest problem about all of this is that a normal vector isn't going to work. That gives me the vector between the two characters, but I cant use that to set the head rotation.
Reason: Ok, imagine I have two characters. Their bodies are faced 100% toward eachother. Now, the head rotation would be 0 0 0 because their body is already facing the other character fine, and at 0 0 0 head rotation your head is looking straight forward.
However, if I took the second character left or right, but kept their bodies facing the same direction, their heads would have to turn to face eachother. So that would be rotation on the Z axis.
What i've gotta figure out is how to get the correct rotation like that.
I was thinking something like this:
Now, assume mHeadVect is the vector for the head rotation, and mRot is the vector of the character's body rotation.
mRot.z goes from 0 to 6.28 (360 degrees).
Any ideas from that? (And no that doesnt work, i've tried it a LOT of times).
06/09/2004 (1:06 am)
Thx for your guys' help, and I see what you mean by the vector.The biggest problem about all of this is that a normal vector isn't going to work. That gives me the vector between the two characters, but I cant use that to set the head rotation.
Reason: Ok, imagine I have two characters. Their bodies are faced 100% toward eachother. Now, the head rotation would be 0 0 0 because their body is already facing the other character fine, and at 0 0 0 head rotation your head is looking straight forward.
However, if I took the second character left or right, but kept their bodies facing the same direction, their heads would have to turn to face eachother. So that would be rotation on the Z axis.
What i've gotta figure out is how to get the correct rotation like that.
I was thinking something like this:
//gives me directional vector Point3F vec = mLookAtTarget->getPosition() - getPosition(); vec.normalize(); //takes the x and y value in vec // and subs them from our current z rotation. mHeadVect.z = mRot.z - (-vec.x + vec.y);
Now, assume mHeadVect is the vector for the head rotation, and mRot is the vector of the character's body rotation.
mRot.z goes from 0 to 6.28 (360 degrees).
Any ideas from that? (And no that doesnt work, i've tried it a LOT of times).
#10
You have a player model that is just the body, but has a mount point for the head. You have a head that is a separate model and mount it on the body. Then you can adjust the head position by changing its transform.
As a simple starter, you could instantiate such a beast and then use torque script to rotate the head around the z axis. In torquescript, that'd look something like:
Edit: Now that I think of it the aiming at a location is exactly what AIPlayer::setAimLocation / Object does.
06/09/2004 (7:00 am)
Let's back up here. I'm new to Torque myself, so this may be way off, but I think this is basically what needs to be done:You have a player model that is just the body, but has a mount point for the head. You have a head that is a separate model and mount it on the body. Then you can adjust the head position by changing its transform.
As a simple starter, you could instantiate such a beast and then use torque script to rotate the head around the z axis. In torquescript, that'd look something like:
%xfrm = %head.getTransform(); %xfrm = setWord(%xfrm, 3, "0"); // rotate around z axis %xfrm = setWord(%xfrm, 4, "0"); // " %xfrm = setWord(%xfrm, 5, "1"); // " %xfrm = setWord(%xfrm, 6, %angle); // degrees? radians? ... don't know %head.setTransform(%xfrm);
Edit: Now that I think of it the aiming at a location is exactly what AIPlayer::setAimLocation / Object does.
#11
06/09/2004 (2:51 pm)
Er I dont want to use scripts: if I did that I would have functions rescursing over and over really fast creating major lag. I actually have mounted the head on as a separate model, but thats besides the point.
#12
06/10/2004 (2:45 am)
So I take it i'm the pioneer in this field, or does nobody still know what I want? :P
#13
or you could look into the aimLocation stuff in AIPlayer as Eric suggested.
06/10/2004 (6:11 am)
Well, if you have your head as a separate object, you can use something like the "lookat()" function I posted above... get the vector, get the matrix out of that, set the position, and then set the transform of your head with that ...or you could look into the aimLocation stuff in AIPlayer as Eric suggested.
#14
When you get the vector and set it into a matrix, is it better to then get the vector out of the matrix instead of just normalizing "vec" and using that?
I have already gotten some of this to work - sometimes. Basically, i'll put this as simple as I can. I got the math to work when the looking character is facing a certain direction. As soon as hes facing a different direction (< or > than 90 or something) the vector goes crazy and messes up.
For example if I have a projectile moving somewhere, and then it targets someone, I could just make it face the target and move toward it using the same idea as this. However, if the vector is in a certain directions, it messes up and aims wrong and stuff.
Know what I mean?
06/10/2004 (7:50 am)
Ok, let me ask this then.When you get the vector and set it into a matrix, is it better to then get the vector out of the matrix instead of just normalizing "vec" and using that?
I have already gotten some of this to work - sometimes. Basically, i'll put this as simple as I can. I got the math to work when the looking character is facing a certain direction. As soon as hes facing a different direction (< or > than 90 or something) the vector goes crazy and messes up.
For example if I have a projectile moving somewhere, and then it targets someone, I could just make it face the target and move toward it using the same idea as this. However, if the vector is in a certain directions, it messes up and aims wrong and stuff.
Know what I mean?
#15
(And yes, I just now figured out it has to be between 0 and 1 lol).
It's hard to explain, and hard to figure out O.o.
This is the method that changes the rotation of the head and stuff found in Player::updateLookAnimation()
Now remember that mHeadVect.z is the variable stored in Player (which is a Point3F).
Thats why if right when this is called, mHeadVect.z is 0, then the head is straight forward - because the thread is made that at 0 the head is looking straight forward (I think).
Haha ... i'm glad you guys are helping me out because I am pretty much lost on my own words ..
06/10/2004 (8:27 am)
I dont know, maybe i'm not being clear enough. I just dont really understand the math for what im trying to accomplish. I mean I understand why you get the vector from the two positions, then normalize it. I get all that - what I dont understand is getting a 0 to 1 value for the .z rotation for the head so that its looking at an object.(And yes, I just now figured out it has to be between 0 and 1 lol).
It's hard to explain, and hard to figure out O.o.
This is the method that changes the rotation of the head and stuff found in Player::updateLookAnimation()
if (mHeadHThread) {
F32 dt = 2 * mDataBlock->maxLookAngle;
F32 tp = (mHeadVect.z + mDataBlock->maxLookAngle) / dt;
mShapeInstance->setPos(mHeadHThread,mClampF(tp,0,1));
}Now remember that mHeadVect.z is the variable stored in Player (which is a Point3F).
Thats why if right when this is called, mHeadVect.z is 0, then the head is straight forward - because the thread is made that at 0 the head is looking straight forward (I think).
Haha ... i'm glad you guys are helping me out because I am pretty much lost on my own words ..
#16
Once character is facing (for our example) north. The other is facing south (so he is looking right at the other character). The first character's head if fine, but the other character's head is messed up. So say their offset like this:
person 1
(*)....(&) - ghost
...(*)
person 2
person 1 will be looking at person 2 fine
but person 2 will be looking at person 1's ghost.
CODE:
Any idea of how to fix this friggin thing?
06/10/2004 (9:09 am)
OK heres the deal: I got it mainly working except for this darn bug:Once character is facing (for our example) north. The other is facing south (so he is looking right at the other character). The first character's head if fine, but the other character's head is messed up. So say their offset like this:
person 1
(*)....(&) - ghost
...(*)
person 2
person 1 will be looking at person 2 fine
but person 2 will be looking at person 1's ghost.
CODE:
VectorF vec = mLookAtTarget->getPosition() - getPosition();
vec.normalize();
vec.neg();
//treat vec.y is a -1 to 1 multiplier
//vec.y is now a percent -
mHeadVect.z = mDataBlock->maxLookAngle * mClampF(vec.y, -1, 1);Any idea of how to fix this friggin thing?
#17
06/15/2004 (6:02 am)
Ok apparently i've stumped everyone - and myself. I've given up. If anyone knows what my prob is, or just happens to know a solution - post away.
#18
In Rune if you played that game characters looking at each other and looking at desired pickups.
Is this the basic function you are after ?
Or do you want the camera change with the head look to or only rotate the head ?
06/15/2004 (6:07 am)
You want the characters look at each other if im not wrong.In Rune if you played that game characters looking at each other and looking at desired pickups.
Is this the basic function you are after ?
Or do you want the camera change with the head look to or only rotate the head ?
#19
06/15/2004 (9:07 am)
This is the first time I've looked at this post, but I did have one idea... check the packUpdate() method inside Player, and see if you're transmitting everything you need for the rotation to work... i.e. the mHeadVect. In addition to that, make sure the masks are being updated. I remember in Torque v.1.1 or thereabouts the demo had a blue guy who you could make free-look (head separate from body) using the mouse. There were just some look variables, and the head animation was done using blend animations. If you were to check out an older version of Torque, I think it would be fairly simple to see how they did it... it was part of a function inside Player... if I remember right (from 1 year ago) it was inside updateMove(). To use that, of course, you'd need to create models with blend animations.
#20
@Billy - I made two vectors: one for the actual physical rotation of the head, and the other for all other stuff like camera rotation. So now, the camera will not rotate with his head too.
06/15/2004 (9:10 am)
Actually John, I am in fact using torque 1.1.1 for the head stuff lol.@Billy - I made two vectors: one for the actual physical rotation of the head, and the other for all other stuff like camera rotation. So now, the camera will not rotate with his head too.
Torque Owner Trevor "PointDestruction"
Ok, first off - I get my position and my target's position and sub them. Then Normalize. That gives me a vector that goes from my position toward the target position.
Am I correct so far?