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