bone interpolation?

Posted By: darkinferno

bone interpolation? - 02/14/10 19:05

i have an angle, lets say vector(20.80,-10.85,-2.55)

and i want to smoothly rotate a bone to that angle, i've been trying some stuff with vec_lerp and such but i guess i must be doing something wrong, this isnt for ragdolls or anything, i just want to smoothly blend a bone to a certain angle
Posted By: muffel

Re: bone interpolation? - 02/14/10 19:38

my first idea to this is that you scale the ANGLE
ANGLE target;
var percent =0;
ANGLE temp;
while(1)
{
percent += time_step;
if(percent<1)
{
vec_set(temp,target
vec_scale(temp,percent);
ent_bonereset(me,"theBone");
ent_bonerotate(me,"theBone",temp);
}
else
{
ent_bonereset(me,"theBone");
ent_bonerotate(me,"theBone",target);
break;
}
wait(1);
}

something like this
muffel
Posted By: darkinferno

Re: bone interpolation? - 02/14/10 20:06

well am not sure if am playing with this correctly however it also seems to just snap the bone to the angle
Posted By: MrGuest

Re: bone interpolation? - 02/14/10 20:36

is it always rotated to that position from 0,0,0 or can it be at different angles before it's required to get to that angle?
Posted By: darkinferno

Re: bone interpolation? - 02/14/10 21:03

it will be at different angles
Posted By: MrGuest

Re: bone interpolation? - 02/14/10 21:15

here's a code i wrote for rotating an entity, it passes the entity and the desired angles
Code:
void ai_rotate(ENTITY* ent, int degrees){
	
	while(ent.z < 40){
		if(int_game_state != game_state_playing){
			return;
		}
		
		ent.z = minv(ent.z + (time_step * 8), 40);
		wait(1);
	}
	
	int pan = ent.pan + degrees;
	while(ent.pan != pan){
		
		if(int_game_state != game_state_playing){
			return;
		}
		
		if(degrees < 0){
			
			ent.pan = maxv(ent.pan - (3 * time_step), pan);
		}else{
			
			ent.pan = minv(ent.pan + (3 * time_step), pan);
		}
		wait(1);
	}
	ent.pan = ang(ent.pan);
	
	while(ent.z > 0){
		if(int_game_state != game_state_playing){
			return;
		}
		
		ent.z = maxv(ent.z - (time_step * 8), 0);
		wait(1);
	}
}

I'm sure you'll be able to work it out from there, otherwise gimme a shout

the 2 other angles will just be proporionate to the percentage the 1st angle has rotated
Posted By: darkinferno

Re: bone interpolation? - 02/14/10 21:42

sadly am not seeing the result of this? basically this is saying if the angle is lower than degree, add to it, if higher than degree, subtract from it? remember am trying to rotate bones not an entity, am not sure the same principles apply
Posted By: MrGuest

Re: bone interpolation? - 02/15/10 00:49

ok, a bit more work, i've come up with this

moves around the biggest angle and calculates the scale for the other angles

Code:
#include <acknex.h>
#include <default.c>


#define bone_pan skill1
#define bone_tilt skill2
#define bone_roll skill3


STRING* str_model = "dummy_man.mdl";
STRING* str_bone = "waist";

//rotate angle by
void bone_rotate(ENTITY* ent, ANGLE* ang_temp){
	
	ANGLE ang_target;
	
	vec_set(ang_target, ent.bone_pan); //current bone position
	vec_add(ang_target, ang_temp);
	
	int int_maxpivot = 0;
	
	//find which is moving the most
	if(abs(ang_temp.pan) > abs(ang_temp.tilt)){
		
		if(abs(ang_temp.pan) > abs(ang_temp.roll)){
			
			int_maxpivot = 1; //biggest is pan
		}else{
			
			int_maxpivot = 3; //biggest is roll
		}
	}else{
		
		if(abs(ang_temp.tilt) > abs(ang_temp.roll)){
			
			int_maxpivot = 2; //biggest is tilt
		}else{
			
			int_maxpivot = 3; //biggest is roll
		}
	}
	
	var var_pandiff = 1;
	var var_tiltdiff = 1;
	var var_rolldiff = 1;
	
	//calculate percentages based on biggest pivot
	switch(int_maxpivot){
		
		case 1: //pan
			var_tiltdiff = ang_temp.tilt / ang_temp.pan;
			var_rolldiff = ang_temp.roll / ang_temp.pan;
		break;
		
		case 2: //tilt
			var_pandiff = ang_temp.pan / ang_temp.tilt;
			var_rolldiff = ang_temp.roll / ang_temp.tilt;
		break;
		
		case 3: //roll
			var_pandiff = ang_temp.pan / ang_temp.roll;
			var_tiltdiff = ang_temp.tilt / ang_temp.roll;
		break;
	}
	
	
	while(ent.bone_pan != ang_target.pan){
		
		if(ent.bone_pan < ang_target.pan){
			
			ent.bone_pan = minv(ent.bone_pan + (1 * var_pandiff * time_step), ang_target.pan);
			
		}else{
			
			ent.bone_pan = maxv(ent.bone_pan - (1 * var_pandiff * time_step), ang_target.pan);
		}
		
		if(ent.bone_tilt < ang_target.tilt){
			
			ent.bone_tilt = minv(ent.bone_tilt + (1 * var_tiltdiff * time_step), ang_target.tilt);
			
		}else{
			
			ent.bone_tilt = maxv(ent.bone_tilt - (1 * var_tiltdiff * time_step), ang_target.tilt);
		}
		
		if(ent.bone_roll < ang_target.roll){
			
			ent.bone_roll = minv(ent.bone_roll + (1 * var_rolldiff * time_step), ang_target.roll);
			
		}else{
			
			ent.bone_roll = maxv(ent.bone_roll - (1 * var_rolldiff * time_step), ang_target.roll);
		}
		
		ent_bonereset(ent, str_bone);
		ent_bonerotate(ent, str_bone, ent.bone_pan);
		wait(1);
	}
}


//rotate angle to
void bone_rotate_to(ENTITY* ent, ANGLE* ang_temp){
	
	ANGLE ang_target;
	
//	vec_set(ang_target, ent.bone_pan); //current bone position
//	vec_add(ang_target, ang_temp);
	
	vec_set(ang_target, ang_temp);
	
	int int_maxpivot = 0;
	
	//find which is moving the most
	if(abs(ang_temp.pan) > abs(ang_temp.tilt)){
		
		if(abs(ang_temp.pan) > abs(ang_temp.roll)){
			
			int_maxpivot = 1; //biggest is pan
		}else{
			
			int_maxpivot = 3; //biggest is roll
		}
	}else{
		
		if(abs(ang_temp.tilt) > abs(ang_temp.roll)){
			
			int_maxpivot = 2; //biggest is tilt
		}else{
			
			int_maxpivot = 3; //biggest is roll
		}
	}
	
	var var_pandiff = 1;
	var var_tiltdiff = 1;
	var var_rolldiff = 1;
	
	//calculate percentages based on biggest pivot
	switch(int_maxpivot){
		
		case 1: //pan
			var_tiltdiff = ang_temp.tilt / ang_temp.pan;
			var_rolldiff = ang_temp.roll / ang_temp.pan;
		break;
		
		case 2: //tilt
			var_pandiff = ang_temp.pan / ang_temp.tilt;
			var_rolldiff = ang_temp.roll / ang_temp.tilt;
		break;
		
		case 3: //roll
			var_pandiff = ang_temp.pan / ang_temp.roll;
			var_tiltdiff = ang_temp.tilt / ang_temp.roll;
		break;
	}
	
	
	while(ent.bone_pan != ang_target.pan){
		
		if(ent.bone_pan < ang_target.pan){
			
			ent.bone_pan = minv(ent.bone_pan + (1 * var_pandiff * time_step), ang_target.pan);
			
		}else{
			
			ent.bone_pan = maxv(ent.bone_pan - (1 * var_pandiff * time_step), ang_target.pan);
		}
		
		if(ent.bone_tilt < ang_target.tilt){
			
			ent.bone_tilt = minv(ent.bone_tilt + (1 * var_tiltdiff * time_step), ang_target.tilt);
			
		}else{
			
			ent.bone_tilt = maxv(ent.bone_tilt - (1 * var_tiltdiff * time_step), ang_target.tilt);
		}
		
		if(ent.bone_roll < ang_target.roll){
			
			ent.bone_roll = minv(ent.bone_roll + (1 * var_rolldiff * time_step), ang_target.roll);
			
		}else{
			
			ent.bone_roll = maxv(ent.bone_roll - (1 * var_rolldiff * time_step), ang_target.roll);
		}
		
		ent_bonereset(ent, str_bone);
		ent_bonerotate(ent, str_bone, ent.bone_pan);
		wait(1);
	}
}


void main(){
	
	wait(1);
	
	level_load(NULL);
	
	me = ent_create(str_model, vector(150, 0, 0), NULL);
	
	vec_set(my.bone_pan, vector(45, 0, 0));
	ent_bonerotate(me, str_bone, my.bone_pan);
	
//	bone_rotate(me, vector(90, 0, 0));
	bone_rotate_to(me, vector(90, 0, 0));
}

change the strings at the top for the entity and bone you want to spawn and move,

ent_rotate() will rotate the bone that distance,
ent_rotate_to() will rotate the bone to that angle,

hopefully linear interpolation is enough, have a look at the cinematic swooping camera if you wanted polynomial interpolation

hope this helps


*No consideration for negative numbers or use of ang()*
Posted By: darkinferno

Re: bone interpolation? - 02/15/10 13:26

lol, that seems like a really huge amount of code to do what i want and i want to rotate every bone of a model to a certain angle, think of it as:

i have a leg thats straight and i want to smoothly interpolate it to an angle that would make it seem like the knees bent, as said, i though vec_lerping would work but i didnt get any accurate results
Posted By: MrGuest

Re: bone interpolation? - 02/15/10 17:10

ahhh inverse kinematics, never got that to work either frown
Posted By: darkinferno

Re: bone interpolation? - 02/15/10 19:57

yes, but is it really innverse kinematic if i know the current bone angle plus the destination bone angle and wish to rotate from the current angle to destination.. i thought some vector maths could accomplish that?
Posted By: KDuke

Re: bone interpolation? - 02/15/10 20:42

Well I wouldn't say this has to be IK as this would be to have a recursive relationship between every bone. Though you just want to rotate a single bone and don't need this relationship of bones taken into account as far as I understand.

Well I'd say that's tricky anyways. Doing this directly with vectors would require a rotation matrix if I remember correctly. Therefore working with pan, tilt and roll would be more appropriate.

Here's some untested pseudo-code for you.
Code:
/**
 * First of get the euler angles we start from!
 **/
ANGLE* StartAngle = nullvector;
ang_for_bone(StartAngle, player, "BoneName");

/**
 * Alright now get the euler angles of the destination.
 **/
VECTOR* DestVec = vector(you.x, you.y, you.z);
ANGLE* DestAngle = nullvector;
vec_to_ang(DestAngle, DestVec);

/**
 * Calculate the difference of the start and destination position.
 **/
ANGLE* DiffAngle = nullvector;
ang_diff(DiffAngle, StartAngle, DestAngle);

/**
 * Now we have everything we need! Rotate the bone.
 **/
ANGLE* StillToRotate = nullvector;
while(1) {
    ent_bonerotate(player, "BoneName", vector(
                     DiffAngle.pan * time_step,
                     DiffAngle.tilt * time_step,
                     DiffAngle.roll * time_step)
    );

    /**
     * We gotta check if we are close to our destination.
     **/

    /**
     * For that we first get the angle we still have to journey
     **/
    ang_for_bone(StartAngle, player, "BoneName");
    ang_diff(StillToRotate, StartAngle, DestAngle);

    /**
     * Now we see if we are near the destination.
     **/
    if( StillToRotate.pan < 1.0 && StillToRotate.pan > -1.0 &&
        StillToRotate.tilt < 1.0 && StillToRotate.tilt > -1.0 &&
        StillToRotate.roll < 1.0 && StillToRotate.roll > -1.0) {
        /**
         * We are pretty close to our destination! Though to make sure
         * we really reach the destination just snap the bone to it.
         **/
        <Your Bone snap code>
        // Don't forget to exit the while-loop!
        break;
    }
    wait(1);
}

/**
 * (Hopefully) be happy
 **/



This would be the way I would approach this stuff! Neither don't know if it really works nor if it is fast enough in realtime. Though I hope this gives you an idea how to approach the problem.

EDIT: By the way. Why do you actually want to interpolate bones manually?

greetings
K-Duke
© 2024 lite-C Forums