• Create Account

## Control Of Bone

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

38 replies to this topic

### #1VitaliBR  Members

Posted 09 January 2011 - 12:41 PM

I'm trying to control your character's arm, and make it point to where your cursor is on the screen (so it aim the gun where the mouse)

So:
void SKINNEDMESH::UpdateMatrices(bool bones, BONE* bone, D3DXMATRIX *parentMatrix)
{
if(bones)
{
if(parentMatrix != NULL)
{
if(bone->Name != NULL && strcmp(bone->Name,"Bip01_L_UpperArm")==0)
{
D3DXMATRIX ident;
D3DXMatrixIdentity(&ident);
D3DXMATRIX final = bone->TransformationMatrix*(*parentMatrix);
D3DXVECTOR3 boneLocation(final._41,final._42,final._43);
D3DXVec3Project(&boneLocation,&boneLocation,&m_vp,&m_pm,&m_vm,&ident); // use YOUR viewport, projection and view matrices in this call
D3DXVECTOR3 dir = mouseLocation - boneLocation;
if(mouseLocation.x > m_Width/2)
{
float offset = D3DX_PI/2.0f;
float angle = offset - atan2(dir.y,dir.x); // change this when you rotate the model
D3DXMATRIX rot;
D3DXMatrixRotationY(&rot,angle);
bone->CombinedTransformationMatrix = rot*final;
}
else
{
float offset = -D3DX_PI/2.0f;
float angle = offset + atan2(dir.y,dir.x); // change this when you rotate the model
D3DXMATRIX rot;
D3DXMatrixRotationY(&rot,angle);
bone->CombinedTransformationMatrix = rot*final;
}
}
else
{
D3DXMatrixMultiply(&bone->CombinedTransformationMatrix,
&bone->TransformationMatrix,
parentMatrix);
}
}
else
bone->CombinedTransformationMatrix = bone->TransformationMatrix;

if(bone->pFrameSibling)
{
UpdateMatrices(bones, (BONE*)bone->pFrameSibling, parentMatrix);
}
if(bone->pFrameFirstChild)
{
UpdateMatrices(bones, (BONE*)bone->pFrameFirstChild, &bone->CombinedTransformationMatrix);
}
}
else
{
if(bone != NULL)
D3DXMatrixMultiply(&bone->CombinedTransformationMatrix,
&bone->TransformationMatrix,
parentMatrix);
else
bone->CombinedTransformationMatrix = bone->TransformationMatrix;

if(bone->pFrameSibling)
UpdateMatrices(bones, (BONE*)bone->pFrameSibling, parentMatrix);
if(bone->pFrameFirstChild)
UpdateMatrices(bones, (BONE*)bone->pFrameFirstChild, &bone->CombinedTransformationMatrix);
}}

But he does not move properly in the direction that the mouse cursor is, why?
as, I move the mouse, it moves very little, but in reverse (back)

Thanks

I'm sending a video to youtube with my problem, wait

### #2VitaliBR  Members

Posted 09 January 2011 - 01:24 PM

The video with problem:

Thanks

### #3Buckeye  GDNet+

Posted 09 January 2011 - 01:42 PM

The video with problem:

Thanks

In your "world" (as shown in the video), which direction is the Y axis? You're adding a rotation about the Y axis to "aim" the bone. Is that the correct axis?

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

### #4VitaliBR  Members

Posted 09 January 2011 - 01:59 PM

In your "world" (as shown in the video), which direction is the Y axis? You're adding a rotation about the Y axis to "aim" the bone. Is that the correct axis?

The Y-Axis is "up" and "down",
I used another class for SkinnedMesh, and it worked perfectly, but I had to create a new class, because there was conflict with my octree and now this new class as it is going wrong in the video

### #5VitaliBR  Members

Posted 10 January 2011 - 07:38 AM

Anyone?

### #6Buckeye  GDNet+

Posted 10 January 2011 - 08:51 AM

You add a rotation about the Y axis to move the arm. As asked above but not answered: is that the correct axis for your model's local arm? You might try changing to D3DXMatrixRotationX or Z.

EDIT: The method you're using assumes the local Y axis for the bone is into/out-of the screen.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

### #7VitaliBR  Members

Posted 10 January 2011 - 09:03 AM

You add a rotation about the Y axis to move the arm. As asked above but not answered: is that the correct axis for your model's local arm? You might try changing to D3DXMatrixRotationX or Z.

EDIT: The method you're using assumes the local Y axis for the bone is into/out-of the screen.

I tried using the axis X or Z, but the results were wrong, if you watch the video (720p in fullscreen), you will see that the arm moves in the right direction, but it moves very little,
and when it is facing to the left, the arm is back

### #8Buckeye  GDNet+

Posted 10 January 2011 - 12:05 PM

First, solve one problem at a time. You're apparently changing the facing direction of the entire model based on the location of the mouse. Until you can get the arm to point to the correct location, don't do that!.

Second, double-check that the mouse location you're using is in client (not screen) coordinates.

Then, you need to determine the local axis for the bone which, when multiplied by the bone's parent's matrices, points into/out-of the screen. That's the axis about which you want to add the rotation based on the mouse position. You can experiment a bit by guessing at various axes - something like:
D3DXVECTOR3 guessAxis(0,0,1);
D3DXVec3TransformNormal(&guessAxis,&guessAxis,&final);
// Now check if guessAxis is the axis for your system that points into/out-of the screen


When you find the correct axis, use that for your D3DXRotation function. Then you can play around with changing the direction of the model.

EDIT: More simply, determine the axis that points into/out-of your screen. Then:
D3DXVECTOR3 screenAxis(...); // set this to the axis in/out of screen - USE A UNIT VECTOR
D3DXMATRIX invFinal;
D3DXMatrixInverse(&invFinal,NULL,&final);
D3DXVec3TransformNormal(&screenAxis,&screenAxis,&invFinal);

After the conversion, screenAxis will be the axis about which you need to rotate with respect to the mouse position.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

### #9VitaliBR  Members

Posted 11 January 2011 - 11:35 AM

I'm not rotating the model as the mouse position (as you told me not to do)
See how it's the code:
if(bone->Name != NULL && strcmp(bone->Name,"Bip01_L_UpperArm")==0)
{
D3DXMATRIX ident;
D3DXMatrixIdentity(&ident);
D3DXMATRIX final = bone->TransformationMatrix*(*parentMatrix);
D3DXVECTOR3 boneLocation(final._41,final._42,final._43);
D3DXVec3Project(&boneLocation,&boneLocation,&m_vp,&m_pm,&m_vm,&ident); // use YOUR viewport, projection and view matrices in this cal
D3DXVECTOR3 dir = mouseLocation - boneLocation;

float offset = D3DX_PI/2.0f;
float angle = offset - atan2(dir.y,dir.x); // change this when you rotate the model
D3DXMATRIX rot;
D3DXMatrixRotationY(&rot,angle);
bone->CombinedTransformationMatrix = rot*final;]
}

But still the same problem, and now I realized that as I move the player up or down, I'mcontrolling the bone moves alone, see the video when the player starts to fly upwardsLook:

And I'm passing the Coordinators of the mouse as follows:
GetCursorPos(&absCursor);
///////////////////////////////////////////////////////
// Get matrices and the viewport
///////////////////////////////////////////////////////
D3DXMATRIX pm; // projection matrix
D3DXMATRIX vm; // view matrix
D3DVIEWPORT9 vp; //viewport

m_pDevice->GetTransform(D3DTS_PROJECTION, &pm);
m_pDevice->GetTransform(D3DTS_VIEW, &vm);
m_pDevice->GetViewport(&vp);

D3DXVECTOR3 mouseLocation((float)absCursor.x,(float)absCursor.y,0);
player->mouselocal(mouseLocation, WIDTH, pm, vm,vp);

### #10Buckeye  GDNet+

Posted 11 January 2011 - 11:59 AM

You're trying to solve too many problems at once. Work on one problem at a time. You apparently haven't gotten the arm rotation fixed, so you shouldn't be worrying about "flying." When you introduce new functions and variables, it's too difficult to help you, particularly since you don't answer questions that're necessary to understand what you're doing.

For instance, I don't know what player->mouselocal(...) does. I would suggest, for clarity:
GetCursorPos(&absCursor);
ScreenToClient(hWnd,&absCursor); // hWnd = the handle to your DirectX window
D3DXVECTOR3 mouseLocation( absCursor.x, absCursor.y, 0 ); // mouse in client coordinates

Also, you're still rotating the arm about the Y axis. Did you determine that's the correct axis to rotate about?

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

### #11VitaliBR  Members

Posted 11 January 2011 - 12:23 PM

For instance, I don't know what player->mouselocal(...) does.

the player->mouselocal(...) given parameters such as viewport, etc...
void SKINNEDMESH::mouselocal(D3DXVECTOR3 pos, int Width, D3DXMATRIX pm, D3DXMATRIX vm, D3DVIEWPORT9 vp)
{
mouseLocation = pos;
m_Width = Width;
m_pm = pm;
m_vm = vm;
m_vp = vp;}

Also, you're still rotating the arm about the Y axis. Did you determine that's the correct axis to rotate about?

Yes, I tested the three axis and the axis is correct to rotate the Y

I would suggest, for clarity:

I need to study a way of passing 'the handle' for my class, so I can use theScreenToClient

### #12Buckeye  GDNet+

Posted 11 January 2011 - 12:40 PM

Your "mouselocal" function doesn't convert from screen to client coordinates. I would suspect that's part of the problem. If you're going to calculate angles using mouse and bone locations, both vectors need to be in the same "space."

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

### #13VitaliBR  Members

Posted 11 January 2011 - 03:20 PM

Your "mouselocal" function doesn't convert from screen to client coordinates. I would suspect that's part of the problem. If you're going to calculate angles using mouse and bone locations, both vectors need to be in the same "space."

There is no function where I can "get" the handle? such as I "get" the viewport:
	D3DVIEWPORT9 vp; //viewport

m_pDevice->GetViewport(&vp);

### #14Buckeye  GDNet+

Posted 11 January 2011 - 04:30 PM

There is no function where I can "get" the handle? such as I "get" the viewport:

    D3DVIEWPORT9 vp; //viewport

m_pDevice->GetViewport(&vp);

When you setup your device present parameters, don't you use a window handle?

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

### #15VitaliBR  Members

Posted 11 January 2011 - 04:42 PM

When you setup your device present parameters, don't you use a window handle?

Yes, I use, but i use ScreenManager, and in class I'm using is derived from this abstract class:
class IGameScreen
{
public:
IGameScreen() { }
~IGameScreen() { }

virtual bool Initialize(IDirect3DDevice9 *pDevice) = 0;

virtual void Update() = 0;
virtual void Draw() = 0;
};

And I would be very complicated to have to go through the handler parameter in allclasses of the management screens
If there was a function to get the handler, would be much easier

EDIT:
This function does exactly what?
http://msdn.microsoft.com/en-us/library/aa344214(v=vs.85).aspx

### #16Buckeye  GDNet+

Posted 11 January 2011 - 06:47 PM

Yes, I use, but i use ScreenManager
<snippet removed>
EDIT:
This function does exactly what?
http://msdn.microsof...4(v=vs.85).aspx

Sounds like you should be using an interface that helps you rather than hinders you. So why not change the interface to do what you want it to do? E.g., add a GetWindowHandle function to the interface.

Re: The GetHandle function - it apparently has something to do with transactions.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

### #17VitaliBR  Members

Posted 11 January 2011 - 09:16 PM

I modified my class and now I'm doing this:
GetCursorPos(&absCursor);
ScreenToClient(hWnd,&absCursor); // hWnd = the handle to your DirectX window
D3DXVECTOR3 mouseLocation( absCursor.x, absCursor.y, 0 ); // mouse in client coordinates

The hand is straight and now moves toward the table as the mouse moves, but is moving very little

### #18Buckeye  GDNet+

Posted 11 January 2011 - 09:41 PM

You haven't described how you determined that the Y axis is the correct axis to rotate about. If the local Y axis of the bone doesn't transform to the axis that points in/out of the screen, it won't work correctly.

There're a couple things you can do. I suggest that, first, you confirm you have the right axis by rotating the arm continuously to see if that works. Something like:
static float angle = 0;
if( bone != NULL && ... )
{
angle += 0.01f;
D3DXMATRIX rot;
D3DXMatrixRotationY(&rot,angle);
D3DXMATRIX final = bone->TransformationMatrix * (*parentMatrix);
bone->CombinedTransformationMatrix = rot * final;
// etc.
}

That should cause the arm to rotate continuously, assuming you're updating and rendering continuously.

If that works, output some data from the routine you posted in post #9 above to your debug output window - things like mouse location, bone location, angle, etc., and see if the values are correct as you move the mouse.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

### #19VitaliBR  Members

Posted 12 January 2011 - 05:01 PM

Just anticipating some results, I took the test asyou said in the Y axis:
static float angle = 0;
if(bone->Name != NULL && strcmp(bone->Name,"Bip01_L_UpperArm")==0)
{
D3DXMATRIX ident;
D3DXMatrixIdentity(&ident);
D3DXMATRIX final = bone->TransformationMatrix*(*parentMatrix);
D3DXVECTOR3 boneLocation(final._41,final._42,final._43);
D3DXVec3Project(&boneLocation,&boneLocation,&m_vp,&m_pm,&m_vm,&ident); // use YOUR viewport, projection and view matrices in this call
D3DXVECTOR3 dir = mouseLocation - boneLocation

float offset = D3DX_PI/2.0f;
angle += 0.1;
D3DXMATRIX rot;
D3DXMatrixRotationY(&rot,angle);
bone->CombinedTransformationMatrix = rot*final;
}

See how it:

### #20Buckeye  GDNet+

Posted 12 January 2011 - 08:36 PM

Good job. It appears that the bone's local Y axis is pointing out of the screen - the rotation is clockwise with increasing angle.

For the model, what do you set for the world transform when you render it? The equations you're using assume the model is rendered with an identity world matrix. You need to use the same world matrix for D3DXVec3Project as you do when you render it, to ensure that the projected bone location is in screen space with the mouse location.

I.e., if you render the model something like:
dev->SetTransform(D3DTS_WORLD, &modelWorld);
// draw the model

then you need to use the same modelWorld in the D3DXVec3Project call:
D3DXVec3Project(&boneLocation,&boneLocation,&m_vp,&m_pm,&m_vm,&modelWorld);


Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.