インバース・キネマティクス

アバター
GRAM
記事: 164
登録日時: 14年前
住所: 大阪

インバース・キネマティクス

投稿記事 by GRAM » 14年前

インバース・キネマティクス…ってちょっとカッコイイ響きがする^^;
インバース・キネマティクスとは日本語で逆運動学というものでWikipedia曰く
足の裏が自転車のペダルにくっついたままペダルが回転運動をするアニメーションを作る場合に、ペダルの回転運動に合うように股・そしてひざや足の角度の変更を行なっていくのではなく、足部分の移動に追随する形で、逆に足-ひざ-股の順に各関節の動きを順次割りだして決定する方が、見た目も自然なアニメーションが作成できる。
らしい。
どうも握手したりするのにも使えるみたいですね
[album]151[/album]
↑みたいな感じで考えれば、関節が1つの場合には考えるのは難しくない
► スポイラーを表示
よし、いけるな…と思ったから作ってみた。
しかしこのバカ正直なやり方には本質的に問題があることが判明。それは関節が2個以上になった場合に役に立たないこと。
この場合では、方程式で座標が定まらないから簡単な方法で解けない。つまり適当に補間しなくてはいけないらしい…
ということで諦めてGoogle先生に聞いてみた。
やはり英語の論文をあさる必要があるか…と思っていたんですが、数は少ないですけど日本語の解説ページも見つけました。
取り敢えずなんちゃってコードでプログラミングしてみる

CODE:

#include "DxLib.h"
#include 
#include "MyVector.h"
using namespace std;
using namespace MyVector;
char Key[256];

class Arm{
private:
	enum Constant{
	NUMBONE = 10
	};
	struct Bone{
		Vector position;
		double sin;
		double cos;
		double length;
		Bone():sin(0),cos(1),length(0){}
	};
	vector BoneList;
	Vector target;
public:        
	Arm():BoneList(NUMBONE){
		for(unsigned int i=0;i::iterator it=BoneList.begin();it!=BoneList.end();++it){
			Vector dlt= target-it->position;
			double rad = atan2(dlt.y,dlt.x);
			it->sin = sin(rad);
			it->cos = cos(rad);
			target=target-dlt*(it->length/dlt.Length());
		}
	}      
	void CalculatePosition(){
		for(vector::reverse_iterator it=BoneList.rbegin();it!=BoneList.rend()-1;){
			(++it)->position=it->position+VRotate2D(Vector(1,0),it->sin,it->cos)*(it->length);
		}
	}   
	void Draw(){
		for(vector::iterator it=BoneList.begin();it!=BoneList.end();++it){
			DrawCircle(it->position.x , it->position.y, 10 , 0x00ff00);
			DrawLine(it->position.x,it->position.y,it->position.x+it->cos*it->length,it->position.y+it->sin*it->length,0x00ff00);
		}
	}
};
class Arm_honest_to_a_fault{
	Vector target;
	Vector position[3];
	enum{Length = 100};
public:
	Arm_honest_to_a_fault(){
		for(int i=0;i
#define VTOL 0.000001
namespace MyVector{
	class Vector{
	public:
		double x;
		double y;
		double z;

		inline Vector():x(0),y(0),z(0){}
		inline Vector(double init_x, double init_y, double init_z = 0)
			:x(init_x),y(init_y),z(init_z){
		}
		inline void SetValue(double init_x, double init_y, double init_z = 0){
			x=init_x;
			y=init_y;
			z=init_z;
		}
		inline Vector(const Vector& other){
			x=other.x;
			y=other.y;
			z=other.z;
		}
		inline Vector& operator=(const Vector& other){
			x=other.x;
			y=other.y;
			z=other.z;
			return *this;
		}
		inline ~Vector(){}

		inline operator bool() const {return x||y||z;};
		inline bool operator==(const Vector& other) const{
			return abs(other.x-x)VTOL||abs(other.y-y)>VTOL||abs(other.z-z)>VTOL;
		}
		//以下固有メンバ関数
		inline double Length() const{ //ベクトルの大きさ
			return sqrt(x*x+y*y+z*z);
		}
		inline double Magnitude() const{
			return sqrt(x*x+y*y+z*z);
		}
		inline void Normalize(){	//ベクトルの正規化
			double m = sqrt(x*x+y*y+z*z);
			if(mMagnitude();
			if(abs(mag1)x=v->x*cos-v->y*sin;
		v->y=v->x*sin+v->y*cos;
		return *v;
	}
	inline double VDistanceSq(const Vector& v1, const Vector& v2){
		return (v1-v2)*(v1-v2);
	}
	
	inline double VEuclideanDistance(const Vector& v1, const Vector& v2){
		return (v1-v2).Length();
	}
	
	inline double VManhattanDistance(const Vector& v1, const Vector& v2){
		double x = v1.x-v2.x;
		double y = v1.y-v2.y;
		double z = v1.z-v2.z;
		if(x<0)x=-x;
		if(y<0)y=-y;
		if(z<0)y=-z;
		return x+y+z;
	}
}
これで2Dでは見た目うまくいっているが、3Dでは自由度が格段に増えるため簡単には拡張できない…
でも取り敢えずは比較的速く目的の成果が出せたのでよしとしよう^^;
・・・久々にMyVector.hを使ったけど、今改めてみるとちょっとひどいコードがたくさんある(笑)
気が向いたら修正しよう・・・
添付ファイル

[拡張子 zip は無効化されているため、表示できません]


ああ
記事: 49
登録日時: 14年前

Re: インバース・キネマティクス

投稿記事 by ああ » 14年前

確かにカッコいい!

てか何か凄い事やってますねぇ!!

この先の期待が膨らみます♪

アバター
GRAM
記事: 164
登録日時: 14年前
住所: 大阪

Re: インバース・キネマティクス

投稿記事 by GRAM » 14年前

あんまり期待しないでくださいw
ただの知りたがりな人間の戯言ですw