« 凄いぞぉ | トップページ | 数学が苦手でも、C.O.F.F.E.E.のMatrixを使えるのか?Matrixクラス-2 »

数学が苦手でも、C.O.F.F.E.E.のMatrixを使えるのか?Matrixクラス

v0,v1,v2,v3のSet/Getは、もう良いね。
SetTrans(v)/SetScale(v)/SetRotX(f)/SetRotY(f)/SetRotZ(f)、これは確か座標変換用のマトリクスを作成するんじゃなかったかな。

まずは、テスト。適当に位置/回転/スケールを与えられたオブジェクトを選択してスクリプトを実行。

/*
SetTrans()を確認する
2008.12.28
*/


VecString(v)//ベクトル型変数を文字列に
{
  if(typeof(v) != DT_VECTOR)return;//ベクトル型以外は中断

  //x,y,zを小数点第3位までを文字列で返す
  return "[" + tostring(v.x , ".3f") +
       " , " + tostring(v.y , ".3f") +
       " , " + tostring(v.z , ".3f") + "]";
}

PrintMatrix(m)//マトリクスの表示
{
  if(!instanceof(m , Matrix))return;//マトリクスクラス以外は中断

  //マトリクスの表示
  println("v0 : " , VecString(m->GetV0()));
  println("v1 : " , VecString(m->GetV1()));
  println("v2 : " , VecString(m->GetV2()));
  println("v3 : " , VecString(m->GetV3()));
}



main(doc , op)
{
  if(!op)return;//オブジェクトが選択されていなければ終了

  var mg = op->GetMg();//opのグローバルマトリクスを取得

  println("******");
  PrintMatrix(mg);//マトリクスの表示

  println("******");
  mg->SetTrans(vector(100 , 0 , 0));
  PrintMatrix(mg);//マトリクスの表示
}

選択されたオブジェクトのグローバルマトリクスに、それのSetTrans(v)を適用。適用前と後でマトリクスを表示。結果は…
Matrix_09
適用前のv0のみが変更されている。ただのSetV0(v)じゃないか。
てっきり
v0[100.0 , 0.0 , 0.0]
v1[1.0 , 0.0 , 0.0]
v2[0.0 , 1.0 , 0.0]
v3[0.0 , 0.0 , 1.0]
ってなってるかな、なんて思ったけど。もしくはv0のみが[938.186 + 100.0 , -537.844 , -120.650]に変更されると思ったけどどれでもなかったなぁ。こんなんだったかなぁ。こんなんだから、こうなんだよね。
じゃあ一気にSetScale(v)/SetRotX(f)/SetRotY(f)/SetRotZ(f)行ってみよう。

/*
SetTrans(v)/SetScale(v)/SetRotX(f)/SetRotY(f)/SetRotZ(f)を確認する
2008.12.28
*/


VecString(v)//ベクトル型変数を文字列に
{
  if(typeof(v) != DT_VECTOR)return;//ベクトル型以外は中断

  //x,y,zを小数点第3位までを文字列で返す
  return "[" + tostring(v.x , ".3f") +
       " , " + tostring(v.y , ".3f") +
       " , " + tostring(v.z , ".3f") + "]";
}

PrintMatrix(m)//マトリクスの表示
{
  if(!instanceof(m , Matrix))return;//マトリクスクラス以外は中断

  //マトリクスの表示
  println("v0 : " , VecString(m->GetV0()));
  println("v1 : " , VecString(m->GetV1()));
  println("v2 : " , VecString(m->GetV2()));
  println("v3 : " , VecString(m->GetV3()));
}



main(doc , op)
{
  if(!op)return;//オブジェクトが選択されていなければ終了

  var mg = op->GetMg();//opのグローバルマトリクスを取得

  println("*** mg ***");
  PrintMatrix(mg);//マトリクスの表示

  println("*** SetTrans(100.0 , 0.0 , 0.0) ***"); 
  mg->SetTrans(vector(100 , 0 , 0));
  PrintMatrix(mg);//マトリクスの表示

  println("*** SetScale(0.5 , 0.2 , 0.6) ***");
  mg = op->GetMg();//オブジェクトのグローバルマトリクスを再取得
  mg->SetScale(vector(0.5 , 0.2 , 0.6));
  PrintMatrix(mg);//マトリクスの表示

  println("*** SetRotX(45.0°) ***");
  mg = op->GetMg();//オブジェクトのグローバルマトリクスを再取得
  mg->SetRotX(Radians(45.0));
  PrintMatrix(mg);//マトリクスの表示

  println("*** SetRotY(45.0°) ***");
  mg = op->GetMg();//オブジェクトのグローバルマトリクスを再取得
  mg->SetRotY(Radians(45.0));
  PrintMatrix(mg);//マトリクスの表示

  println("*** SetRotZ(45.0°) ***");
  mg = op->GetMg();//オブジェクトのグローバルマトリクスを再取得
  mg->SetRotZ(Radians(45.0));
  PrintMatrix(mg);//マトリクスの表示
}

このスクリプトは、Matrixのメンバ関数を実行する前にオブジェクトのグローバルマトリクスを再取得しています。new(Matrix)でもいいのですが、どのレベルで変化するのかを確認したかったので、あえてオブジェクトから再取得しました。では結果を…
Matrix_10
オブジェクトから再取得したにもかかわらずSetTrans()以外のv0~v3が完璧に変化しています。v0はどれも[0.0 , 0.0 , 0.0]ですね。

Scaleは指定した値が
[scx , 0.0 , 0.0]
[0.0 , scy , 0.0]
[0.0 , 0.0 , scz]
各ベクトルの長さがScaleなのであってますね。

RotX
[1.0 , 0.0 , 0.0]
[0.0 , cos(45) , -sin(45)]
[0.0 , sin(45) , cos(45)]
数値はもっともな数値だね。

RotY
[cos(45) , 0.0 , sin(45)]
[0.0 , 1.0 , 0.0]
[-sin(45) , 0.0 , cos(45)]

RotZ
[cos(45) , -sin(45) , 0.0]
[sin(45) , cos(45) , 0.0]
[0.0 , 0.0 , 1.0]

と大昔に学習した座標変換の数値そのものだ…
ん?テーマは「数学が苦手でもMatrixは使えるのか?」だったね。じゃぁcosだのsinは忘れよう。こんな風に変化しましたよー。みたいな感じでね。あ、丸暗記って書いたけどsin/cosの並びなんて覚えなくて良いよ。
じゃあオブジェクトを1個だけワールドの原点に置いて移動も回転も何もしないで次のスクリプトを実行。

/*
SetRotX()を確認する
2008.12.28
*/


if(!op)return;//オブジェクトが選択されていなければ終了

var mg = new(Matrix);

mg->SetRotX(Radians(45.0));
op->SetMg(mg);//グローバルマトリクスを適用

実行結果の確認は座標マネージャでオブジェクトの回転がHPB[0.0 , 45.0 , 0.0]になっています。SetRotY()もSetRotZ()も同じように、それぞれの軸を中心に回転されます。本来の使い方ではないんですけどね。SetScale()も変化します。
では、SetTrans()/SetScale()/SetRotX()/SetRotY()/SetRotZ()は、次のメンバ関数GetMulM()と組み合わせて使います。
このGetMulM()はマトリクスをマトリクスで変換します。(だんだん思い出してきたよ。)
ちょっと具体的に、でも一言で言うと、オブジェクトのマトリクスを変換マトリクスで変換します。では次のスクリプトを実行するとなんとなくわかります。

/*
GetMulM()テスト
2008.12.28
*/


var mg = op->GetMg();//オブジェクトのグローバルマトリクスを取得
var m = new(Matrix);//新規のマトリクスの取得

m->SetRotX(Radians(30.0));//X軸回り30度変換マトリクス
mg = m->GetMulM(mg);//オブジェクトのマトリクスをX軸回り30度変換マトリクスで変換

op->SetMg(mg);//変換されたマトリクスをオブジェクトに適用

実行する前にオブジェクトを追加して適当に空間に配置してください。回転/スケールも付けてください。
それでは実行してください。結果は実行するたびワールドのX軸回りを30度づつ回っていきます。
Matrix_11
要するに先ほどのSetTrans()/SetScale()/SetRotX()/SetRotY()/SetRotZ()は、変換するためのマトリクスを生成します。変換するときは、生成したマトリクスのGetMulM()に変換したいマトリクスを渡し、返ってきたマトリクスが変換されたマトリクスになります。
SetRotX()のみ試しましたが、他のTrans/Scale/RotY/RotZも試してみてください。
先ほども言いましたが、オブジェクトを軸周りを回すのにsinもcosも順番も覚える必要はまったくありません。覚えるのは、

変換後のマトリクス = 変換マトリクス->GetMulM(変換したいマトリクス)

と、今のところ5個のメンバ関数。
更に続く。

|

« 凄いぞぉ | トップページ | 数学が苦手でも、C.O.F.F.E.E.のMatrixを使えるのか?Matrixクラス-2 »

コメント

この記事へのコメントは終了しました。