Jump to content

Animation Bones IK


Chris Paulson
 Share

Recommended Posts

Hi,

 

I've started looking a footplacement of an NPC so it's feet are on the ground instead of floating.

 

I've tried modifying a foot bone position (using EntityPosition) believing LE had IK to sort out all the other bone positions/rotations, however what I saw was the mesh messed up.

 

I'm I doing something wrong?

Has LE really got IK?

Link to comment
Share on other sites

No, it doesn't. It has forward kinematics (higher bones influence lower bones), but not IK. I am just getting to this now too, as we have an animated main character who has floating feet as well.

  • Upvote 1
  • Downvote 1

52t__nvidia.png nVidia 530M cpu.gif Intel Core i7 - 2.3Ghz 114229_30245_16_hardware_memory_ram_icon.png 8GB DDR3 RAM Windows7_Start.gif Windows 7 Ultimate (64x)

-----

IconVisualStudio16.png Visual Studio 2010 Ultimate google-Chrome.png Google Chrome PhotoshopLinkIndicator.png Creative Suite 5 icon28.gif FL Studio 10 MicrosoftOfficeLive.png Office 15

-----

csharp.png Expert cpp.png Professional lua_icon.png Expert BMX Programmer

-----

i-windows-live-messenger-2009.pngskype-icon16.pngaim_online.pnggmail.pngicon_48x48_prism-facebook.pngtunein-web.pngyahoo.giftwitter16.png

Link to comment
Share on other sites

The maths for those rotations are in fact what an Inverse Kinematics Solver would do.

 

What is does, is determine how much you have to rotate and move the parents of a given bone in order to move it to where you are trying to, and give it proper influence.

  • Upvote 1

52t__nvidia.png nVidia 530M cpu.gif Intel Core i7 - 2.3Ghz 114229_30245_16_hardware_memory_ram_icon.png 8GB DDR3 RAM Windows7_Start.gif Windows 7 Ultimate (64x)

-----

IconVisualStudio16.png Visual Studio 2010 Ultimate google-Chrome.png Google Chrome PhotoshopLinkIndicator.png Creative Suite 5 icon28.gif FL Studio 10 MicrosoftOfficeLive.png Office 15

-----

csharp.png Expert cpp.png Professional lua_icon.png Expert BMX Programmer

-----

i-windows-live-messenger-2009.pngskype-icon16.pngaim_online.pnggmail.pngicon_48x48_prism-facebook.pngtunein-web.pngyahoo.giftwitter16.png

Link to comment
Share on other sites

If trying to implement your own IK solver turns out to be a pain you could take a look at trying to integrate havok animation. It has a lot of nice features, including IK solvers.

Windows 7 x64 - Q6700 @ 2.66GHz - 4GB RAM - 8800 GTX

ZBrush - Blender

Link to comment
Share on other sites

Havok Animation is something I have been wanting to try out in Leadwerks, but it seems like it will be a pain to get it working.

52t__nvidia.png nVidia 530M cpu.gif Intel Core i7 - 2.3Ghz 114229_30245_16_hardware_memory_ram_icon.png 8GB DDR3 RAM Windows7_Start.gif Windows 7 Ultimate (64x)

-----

IconVisualStudio16.png Visual Studio 2010 Ultimate google-Chrome.png Google Chrome PhotoshopLinkIndicator.png Creative Suite 5 icon28.gif FL Studio 10 MicrosoftOfficeLive.png Office 15

-----

csharp.png Expert cpp.png Professional lua_icon.png Expert BMX Programmer

-----

i-windows-live-messenger-2009.pngskype-icon16.pngaim_online.pnggmail.pngicon_48x48_prism-facebook.pngtunein-web.pngyahoo.giftwitter16.png

Link to comment
Share on other sites

I'm sure you could use a couple of static bodies for the feet, a static body for the pelvis, and a body with mass for the knees. Connect the knees to the pelvis with a ball joint with limits, and the feet to the knees with a hinge. Move the feet wherever you want them to be, and the knees will follow. Parent the knee bones to the knee bodies, and you have IK animation.

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

Yeah, today a good physics ragdoll setup would simulate the IK better than a solver may.

52t__nvidia.png nVidia 530M cpu.gif Intel Core i7 - 2.3Ghz 114229_30245_16_hardware_memory_ram_icon.png 8GB DDR3 RAM Windows7_Start.gif Windows 7 Ultimate (64x)

-----

IconVisualStudio16.png Visual Studio 2010 Ultimate google-Chrome.png Google Chrome PhotoshopLinkIndicator.png Creative Suite 5 icon28.gif FL Studio 10 MicrosoftOfficeLive.png Office 15

-----

csharp.png Expert cpp.png Professional lua_icon.png Expert BMX Programmer

-----

i-windows-live-messenger-2009.pngskype-icon16.pngaim_online.pnggmail.pngicon_48x48_prism-facebook.pngtunein-web.pngyahoo.giftwitter16.png

Link to comment
Share on other sites

I'm sure you could use a couple of static bodies for the feet, a static body for the pelvis, and a body with mass for the knees. Connect the knees to the pelvis with a ball joint with limits, and the feet to the knees with a hinge. Move the feet wherever you want them to be, and the knees will follow. Parent the knee bones to the knee bodies, and you have IK animation.

 

Great idea however bit confused by combination of bodies etc. I would have thought: -

 

Ball joint - parented to hip pivot

Body box for thigh

Ball joint for knee

Body box for shin

Hinge for ankle

Body box for foot

 

To give:-

 

.

|

.

|

.-

 

 

but I'm probably wrong as I haven't done this before.

Link to comment
Share on other sites

As always you are correct. That setup seems great actually :)

52t__nvidia.png nVidia 530M cpu.gif Intel Core i7 - 2.3Ghz 114229_30245_16_hardware_memory_ram_icon.png 8GB DDR3 RAM Windows7_Start.gif Windows 7 Ultimate (64x)

-----

IconVisualStudio16.png Visual Studio 2010 Ultimate google-Chrome.png Google Chrome PhotoshopLinkIndicator.png Creative Suite 5 icon28.gif FL Studio 10 MicrosoftOfficeLive.png Office 15

-----

csharp.png Expert cpp.png Professional lua_icon.png Expert BMX Programmer

-----

i-windows-live-messenger-2009.pngskype-icon16.pngaim_online.pnggmail.pngicon_48x48_prism-facebook.pngtunein-web.pngyahoo.giftwitter16.png

Link to comment
Share on other sites

hmm...think you might want to change the ball-joint in knee to a hinge joint,

and the hinge joint in the ankle to a ball-joint...

 

in traditional DCC packages you'd also have an 'up-vector' object controlling the

alignment of where the knee/hinge joint should be directed.

 

but I'm no animation expert </legal clause> :)

Vista Ultimate SP1 64bit | Q6600 2.40 GHZ | 8GB RAM | 320MB Nvidia 8800GTS

Link to comment
Share on other sites

Your right about the hinges etc.

 

I'm struggling though, you can't get the rotation of a hinge/joint and you can't get it's position. If I do any of the mentioned calls LE GPFs. So I am having to try and work out these values which kind of defeats the object of using it as an easy replacement for an IK solver.

Link to comment
Share on other sites

After a lot of fiddling I have got this working.

 

Here's a blitz example: -

 

Strict

Framework leadwerks.engine 

Graphics 800,600

RegisterAbstractPath AppDir
'RegisterAbstractPath ".."

If Not CreateWorld() RuntimeError "Failed to create world." 

Local cam:TCamera=CreateCamera() 
MoveEntity cam,Vec3(-0.2,0,-1) 

'Local mesh:TMesh=CreateCube()
'Local sphere:TMesh=CreateSphere()



Local hip:TBody = CreateBodyPivot( )
PositionEntity(hip,Vec3(0))
Local thigh:TBody = CreateBodyBox( 0.001, 0.2, 0.001 )
Local shin:TBody = CreateBodyBox( 0.001, 0.2, 0.001 )
Local foot:TBody = CreateBodyBox( 0.08, 0.02, 0.001 )
EntityType(thigh,1)
EntityType(shin,1)
EntityType(foot,1)
Collisions(1,1,0)

SetBodyDamping( thigh, 0, 0 )
SetBodyDamping( shin, 0, 0 )
SetBodyDamping( foot, 0, 0 )

MoveEntity(hip,Vec3(0,0.1,0))
MoveEntity(shin,Vec3(0,-0.2,0))
MoveEntity(foot,Vec3(0,-0.3,0))
SetBodyMass(thigh,10)
SetBodyMass(shin,10)
SetBodyMass(foot,10)
SetBodyGravityMode( thigh,0)
SetBodyGravityMode( shin,0)
SetBodyGravityMode( foot,0)

SetBodyFriction( thigh,0,0)
SetBodyFriction( shin,0,0)
SetBodyFriction( foot,0,0)



Local knee:TBody = CreateBodyPivot( )
MoveEntity(knee,Vec3(0,-0.1,0))
EntityParent( knee, thigh )
SetBodyDamping( knee, 0, 0 )

Local kneeorb:TEntity = CreateSphere( 8, knee )
ScaleEntity( kneeorb, Vec3(0.01) )

Local ankle:TBody = CreateBodyPivot()
MoveEntity(ankle,Vec3(0,-0.3,0),1)
EntityParent( ankle, shin )
'SetBodyMass(ankle,1)

Local footorb:TEntity = CreateSphere( 8, ankle )
PositionEntity(footorb, Vec3(0,-0.3,0),1)
ScaleEntity( footorb, Vec3(0.01) )


''EntityParent( foot, shin )

Local ballhip:TJoint = CreateJointBall( hip, thigh, Vec3(0,0.1,0) )
SetBallJointLimits( ballhip, Vec3(0,0,0), 150, 1) 
'Local ballhip:TJoint = CreateJointHinge( hip, thigh, Vec3(0,-0.1,0), Vec3(1,0,0) )
'SetHingeJointLimits( ballhip, -90, 90 ) 


Local ballknee:TJoint = CreateJointHinge( thigh, shin, Vec3(0,-0.1,0), Vec3(0,0,1) )
SetHingeJointLimits( ballknee, -100, -5 ) 


'Local ballknee:TJoint = CreateJointBall( thigh, shin, Vec3(0,-0.1,0) )
Local ballankle:TJoint = CreateJointHinge( shin, foot, Vec3(0,-0.3,0), Vec3(0,0,1) )
SetHingeJointLimits( ballankle, -40, 40 ) 

SetJointCollisionMode(ballhip,0)
SetJointCollisionMode(ballknee,0)
SetJointCollisionMode(ballankle,0)
Local position:TVec3
Local lastposition:TVec3 = vec3(0,0,0)

DebugPhysics(True)
While Not KeyHit(KEY_ESCAPE) 

position=CameraProject(cam,vec3(MouseX(),MouseY(),1))

PositionEntity( foot, position)
SetBodyVelocity(foot, vec3(0))

' This is needed to make stuff solve IK at decent speed
lastposition = EntityPosition(footorb,1) 
SetBodyVelocity(foot, vec3((position.x - lastposition.x) *5, (position.y - lastposition.y)*5, (position.z - lastposition.z)*5))
lastposition = position

UpdateWorld( AppSpeed() )
'	UpdateWorld(100 )
RenderWorld
DrawText "Move the mouse around.",0,0
Flip
Wend

Link to comment
Share on other sites

Pretty interesting. I had to remove the Vec3(0,0,0) from SetBallJointLimits for it to compile though.

52t__nvidia.png nVidia 530M cpu.gif Intel Core i7 - 2.3Ghz 114229_30245_16_hardware_memory_ram_icon.png 8GB DDR3 RAM Windows7_Start.gif Windows 7 Ultimate (64x)

-----

IconVisualStudio16.png Visual Studio 2010 Ultimate google-Chrome.png Google Chrome PhotoshopLinkIndicator.png Creative Suite 5 icon28.gif FL Studio 10 MicrosoftOfficeLive.png Office 15

-----

csharp.png Expert cpp.png Professional lua_icon.png Expert BMX Programmer

-----

i-windows-live-messenger-2009.pngskype-icon16.pngaim_online.pnggmail.pngicon_48x48_prism-facebook.pngtunein-web.pngyahoo.giftwitter16.png

Link to comment
Share on other sites

The good news:-

 

I got a animated model moving it's limbs in sync with the physics bodies.

 

The bad news:-

 

I think this is a dead end as the physics solves the IK too slow and if you try to speed it up it oscillates. I think I need to write a proper IK solves, it will probably be easier than flogging the physics to death.

Link to comment
Share on other sites

It isn't done, but this will IK solve hella-fast:

 

void IKSimple::Solve(std::vector<Transform> bones, Vector3 target)
{
float num6;
float num7;
Transform transform = bones[bones.size() - 1];
std::vector<Vector3> vectorArray;
std::vector<float> numArray;
std::vector<Quaternion> quaternionArray;
for (int i = 0; i < (bones.size() - 2); i++)
{
	vectorArray[i] = (bones[i + 1].position - bones[i].position).Cross(bones[i + 2].position - bones[i + 1].position);
	vectorArray[i] = (Vector3) ((bones[i].rotation.Inverse()) * vectorArray[i]);
	vectorArray[i].Normalize();
	numArray[i] = (bones[i + 1].position - bones[i].position).Angle(bones[i + 1].position - bones[i + 2].position);
	quaternionArray[i] = bones[i + 1].localRotation;
}
std::vector<float> numArray2;
float num2 = 0.0f;
for (int j = 0; j < (bones.size() - 1); j++)
{
	Vector3 vector = bones[j + 1].position - bones[j].position;
	numArray2[j] = vector.Magnitude();
	num2 += numArray2[j];
}
this->positionAccuracy = num2 * 0.001f;
Vector3 vector2 = transform.position - bones[0].position;
float magnitude = vector2.Magnitude();
Vector3 vector3 = target - bones[0].position;
float num5 = vector3.Magnitude();
bool flag = false;
bool flag2 = false;
if (num5 > magnitude)
{
	flag = true;
	num7 = 1.0f;
	num6 = 0.0f;
}
else
{
	flag2 = true;
	num7 = 1.0f;
	num6 = 0.0f;
}
int num8 = 0;
while ((abs((float) (magnitude - num5)) > this->positionAccuracy) && (num8 < this->maxIterations))
{
	float num9;
	num8++;
	if (!flag)
	{
	num9 = num7;
	}
	else
	{
	num9 = (num6 + num7) / 2.0f;
	}
	for (int k = 0; k < (bones.size() - 2); k++)
	{
	float num11;
	if (!flag2)
	{
			num11 = math::Lerp(180.0f, numArray[k], num9);
	}
	else
	{
	num11 = (numArray[k] * (1.0f - num9)) + ((numArray[k] - 30.0f) * num9);
	}
	float angle = numArray[k] - num11;
		Quaternion quaternion2 = Quaternion::Quaternion(vectorArray[k],angle) * quaternionArray[k];
	bones[k + 1].localRotation = quaternion2;
	}
	Vector3 vector4 = transform.position - bones[0].position;
	magnitude = vector4.Magnitude();
	if (num5 > magnitude)
	{
	flag = true;
	}
	if (flag)
	{
	if (num5 > magnitude)
	{
	num7 = num9;
	}
	else
	{
	num6 = num9;
	}
	if (num7 >= 0.01f)
	{
	continue;
	}
	break;
	}
	num6 = num7;
	num7++;
}
bones[0].rotation = Quaternion::Quaternion(AngleAxis::AngleAxis((transform.position - bones[0].position).Cross(target - bones[0].position), (transform.position - bones[0].position).Angle(target - bones[0].position))) * bones[0].rotation;
}

52t__nvidia.png nVidia 530M cpu.gif Intel Core i7 - 2.3Ghz 114229_30245_16_hardware_memory_ram_icon.png 8GB DDR3 RAM Windows7_Start.gif Windows 7 Ultimate (64x)

-----

IconVisualStudio16.png Visual Studio 2010 Ultimate google-Chrome.png Google Chrome PhotoshopLinkIndicator.png Creative Suite 5 icon28.gif FL Studio 10 MicrosoftOfficeLive.png Office 15

-----

csharp.png Expert cpp.png Professional lua_icon.png Expert BMX Programmer

-----

i-windows-live-messenger-2009.pngskype-icon16.pngaim_online.pnggmail.pngicon_48x48_prism-facebook.pngtunein-web.pngyahoo.giftwitter16.png

Link to comment
Share on other sites

You need the Transform struct as well:

 

#include "SVector3.h"
#include "SQuaternion.h"

struct Transform
{
Transform(TEntity entity)
{
	this->entity = entity;

	TVec3 v;

	v = EntityPosition(entity,1);
	this->position = Vector3(v.X,v.Y,v.Z);

	v = EntityPosition(entity,0);
	this->localPosition = Vector3(v.X,v.Y,v.Z);

	v = EntityScale(entity);
	this->scale = Vector3(v.X,v.Y,v.Z);

	v = Vec3(0,1,0);
	v = TFormVector(v, entity, NULL);
	this->up = Vector3(v.X,v.Y,v.Z);

	v = Vec3(0,0,1);
	v = TFormVector(v, entity, NULL);
	this->forward = Vector3(v.X,v.Y,v.Z);

	v = Vec3(1,0,0);
	v = TFormVector(v, entity, NULL);
	this->right = Vector3(v.X,v.Y,v.Z);

	v = EntityRotation(entity,1);
	this->rotation = Quaternion(Vector3(v.X,v.Y,v.Z));

	v = EntityRotation(entity,0);
	this->localRotation = Quaternion(Vector3(v.X,v.Y,v.Z));
}

TEntity entity;

Vector3 position;
Vector3 localPosition;
Vector3 scale;
Vector3 up;
Vector3 forward;
Vector3 right;
Quaternion rotation;
Quaternion localRotation;	
};

 

And the math classes too. So if you don't have any, let me know and I will zip them up for you.

52t__nvidia.png nVidia 530M cpu.gif Intel Core i7 - 2.3Ghz 114229_30245_16_hardware_memory_ram_icon.png 8GB DDR3 RAM Windows7_Start.gif Windows 7 Ultimate (64x)

-----

IconVisualStudio16.png Visual Studio 2010 Ultimate google-Chrome.png Google Chrome PhotoshopLinkIndicator.png Creative Suite 5 icon28.gif FL Studio 10 MicrosoftOfficeLive.png Office 15

-----

csharp.png Expert cpp.png Professional lua_icon.png Expert BMX Programmer

-----

i-windows-live-messenger-2009.pngskype-icon16.pngaim_online.pnggmail.pngicon_48x48_prism-facebook.pngtunein-web.pngyahoo.giftwitter16.png

Link to comment
Share on other sites

I'm struggling to get this to work. My code is:-

 

void ikRanger( TVec3 position, TModel npc )
{

TEntity lhip = FindChild( npc, "Frame3_figure_v05_Layer35");
TEntity lknee = FindChild( npc, "R_Knee");
TEntity lfoot = FindChild( npc, "R_Foot");

Transform thip( lhip );
Transform tknee( lknee );
Transform tfoot( lfoot );

vector<Transform> bones;

bones.push_back( thip );
bones.push_back( tknee );
bones.push_back( tfoot );

IKSimple iknpc;

iknpc.Solve( bones, Vector3( position.X, position.Y, position.Z ));

Vector3 rot = thip.localRotation.ToAngleAxis().Axis;
RotateEntity( lhip, Vec3( rot.X, rot.Y, rot.Z ) );
rot = tknee.localRotation.ToAngleAxis().Axis;
RotateEntity( lknee, Vec3( rot.X, rot.Y, rot.Z ) );
rot = tfoot.localRotation.ToAngleAxis().Axis;
RotateEntity( lfoot, Vec3( rot.X, rot.Y, rot.Z ) );

/*	RotateEntity( lhip, Vec3( rad2deg(rot.X), rad2deg(rot.Y), rad2deg(rot.Z) ) );
rot = tknee.localRotation.ToAngleAxis().Axis;
RotateEntity( lknee, Vec3( rad2deg(rot.X), rad2deg(rot.Y), rad2deg(rot.Z) ) );
rot = tfoot.localRotation.ToAngleAxis().Axis;
RotateEntity( lfoot, Vec3( rad2deg(rot.X), rad2deg(rot.Y), rad2deg(rot.Z) ) ); */
}

 

Is "thip.localRotation.ToAngleAxis().Axis" the correct thing to get back the rotations with?

 

The transform class does: -

 

	v = EntityRotation(entity,1);
	this->rotation = Quaternion(Vector3(v.X,v.Y,v.Z));

 

 

Isn't EntityRotation in degrees and Quaternion in rads? Should there not be a conversion?

 

 

Pity thrown at someone as bad at maths as me would be appreciated.

Link to comment
Share on other sites

Thought I'd post a progress update on this as I'm still trying to get this to work...

 

The quaternion class did need to convert to/from radian/degrees.

 

The class needed a new method for converting the quaternion to eualer angles.

 

I wish you could get/set quaternions in LE (at present there's only a get).

 

Somewhere in the code there is a math error because it's not IK'ing properly.

 

If anyone is best mates with Pythagoras or his brother Trig feel free to pitch in...

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...