行列:効率の良い合成

OpenGLプログラミングメモ内検索 / 「行列:効率の良い合成」で検索した結果

検索 :
  • 行列:効率の良い合成
    行列同士は行列の積を行うと合成する事ができます。 しかし、4×4行列の積は16回も計算しなければなりません。 平行移動成分と回転成分、拡大縮小成分を合成するのに 32回も計算するのでしょうか? 平行移動成分は回転成分と拡大縮小成分に影響しないので3回の代入で 済ます事ができます。 回転成分と拡大縮小成分は互いに行列の要素位置がダブっているので ただ単に代入する事はできません。 平行移動成分と同様にして回転成分と拡大縮小成分に関しても計算回数を 減らす事はできないでしょうか? ここで一つの実験をしてみます。 それは、1行列(全要素が1の4×4行列)に glScalef を実行してみる という物です。 //#pragma comment(linker, /SUBSYSTEM WINDOWS /ENTRY mainCRTStartup ) #include GL/freeglut/fre...
  • 行列:行列の合成
    行列の合成です。 glMultMatrixf(); がしている事です。 これは単純に行列の積を行っているだけです。 行列 平行移動行列 のプログラムの glMultMatrixf(); を使わずに glLoadMatrixf(); で設定するように変えてみましょう。 全く同じ結果になる事がわかると思います。 ただし、行列は掛け合わせる順番が変わると全く違う物になります。 何やら回りくどい事をしているように感じるかもしれませんが、 それは今回のプログラムでは合成回数が1回だからです。 『スキンメッシュアニメーション』等、行列の合成を何回も何回も しなければならない場合に効率を上げるには glMultMatrixf(); を 使わずに手動で行列の合成をしなければなりません。 #pragma comment(linker, /SUBSYSTEM WINDOWS /ENTRY mainCRT...
  • 行列:転置行列
    転置行列です。 行列の行と列を入れ替えて作られる行列をの転置行列と言い、と表す。 行列:行列の合成 のページで //合成 glMultMatrixfの代わり void multiplication(GLfloat* src1,GLfloat* src2,GLfloat* dst) {  for(int y=0;y 4;y++){   for(int x=0;x 4;x++){    dst[y*4+x]=src2[y*4]*src1[x]+src2[y*4+1]*src1[x+4]+src2[y*4+2]*src1[x+8]+src2[y*4+3]*src1[x+12];   }  } } となっていて、 「掛け合わせる順番が逆ジャネーノ?」 と思った方もいるでしょうが、これで良いのです。 DirectXは行ベクトルのため、左から掛け合わせますがOpenGLの場合、 列ベクトルであ...
  • 行列:単位行列
    さて、最初に解説するのは 『単位行列』 という物です。 ですが、単位行列の前にまず正方行列を解説します。 正方行列というのは 2×2行列 とか 3×3行列 とか 4×4行列 のように 行と列の並び数が同じ行列の事を言います。 行と列の数がともに nである行列を  n次の正方行列といいます。 DirectX とか OpenGL では 4次の正方行列を使います。 つまり 4×4行列 の事ですね。 そして 『単位行列』 というのは正方行列の左上から右下まで全て 1 で、 それ以外の所は全て 0 の行列の事です。わかりやすくすると次の図のような物です。 2次の正方行列の単位行列 3次の正方行列の単位行列 4次の正方行列の単位行列 そもそも、『単位行列』 って何? 何故、それが必要なの? とお思いでしょう。 この 『単位行列』 というのは glLoadIdentity(); がしている事で、...
  • 行列:逆行列
    逆行列です。 逆行列とは、あるN×N行列があったときと積をとると N×N行列の単位行列になる行列の事をの逆行列と呼び、と書く。 つまり、各種アフィン変換を打ち消して単位行列(初期状態)に戻す行列の事です。 4×4行列の逆行列の公式 の時、逆行列が存在して、 で、求められます。 b は以下のようになります。
  • 行列:零行列
    零行列です。 零行列は全ての要素が 0 になっているものです。 平行移動行列、回転行列、拡大縮小行列を解説したので、やっと 単位行列の意味が解ります。 まず、平行移動成分を見てみましょう。 X軸、Y軸、Z軸全てが 0 になっていますね。 そして回転成分は cosθ の所は 1 で sinθ と -sinθ の所が 0 に なっています。   θ(シータ)には角度をラジアンに変換したものが入ります。 cos(0) の解は 1 です。 sin(0) の解は 0 です。 -sin(0) の解は 0 です。 つまり、 θ には 0 が入る事になり、回転角度は 0°という事になります。 X軸、Y軸、Z軸全てが 0 になっていますね。 そして、拡大縮小成分は見ての通り、全ての軸が 1 となっています。 つまり、拡大率は 1倍 という事ですね。 仮に零行列を掛け合わせると全てが 0 になってしま...
  • 行列:回転行列
    続いて、回転行列です。 以下にOpenGL、DirectX、双方の回転行列を示しますが、前回解説したように 行と列の方向が違うだけで結局は同じ物です。   チュートリアル 固定機能編 の トーラスの表示と回転 を置き換えてみました。 #pragma comment(linker, /SUBSYSTEM WINDOWS /ENTRY mainCRTStartup ) #include GL/freeglut/freeglut.h #include math.h #define PI 3.1415926 #define WIDTH 320 #define HEIGHT 240 //回転用 float anglex = 0.0f; //オレンジ GLfloat orange[] = { 1.0, 0.6, 0.0, 1.0 }; //ライトの位置 GLfloat lightpos[...
  • 行列:行列の適用
    では、glLoadIdentity(); を glLoadMatrixf(mat); で単位行列を設定するように 置き換えてみます。 チュートリアル 固定機能編 の 球を表示して移動する のプログラムを書き換えてみました。 全く同じに動作しています。 単位行列は GLfloat mat[]={  1,0,0,0,  0,1,0,0,  0,0,1,0,  0,0,0,1 }; という感じで16個の要素を持った変数に格納します。 #pragma comment(linker, /SUBSYSTEM WINDOWS /ENTRY mainCRTStartup ) #include GL/freeglut/freeglut.h #define WIDTH 320 #define HEIGHT 240 //平行移動用 float x = 0.0f; bool flag = false; ...
  • 行列:行列の計算方法
    単位行列が初期化なのは何故か?という事を説明するには行列の計算方法を 知らなければなりません。 行列も普通の計算と同じで和差積商(加減乗除)があります。 和は足し算、差は引き算、積はかけ算、商は割り算の事です。 行列と行列の和,差を行うには、行列の型が同じでなければなりません。 つまり、行列Aと行列Bの和(または差)を行う場合、互いの行数と列数が 等しくなければできません。 例えば以下のようになります。 続いて、行列の積ですが、まず、行列の実数倍という物があり、 そして、行列と行列の積は左行列の列数と右行列の行数が 同じでなければできません。 さらに、m行 p列の行列 と p行 n列の行列の積は m行 n列の行列となります。 具体的な計算の例を以下に示します。 行列の商というのはないそうです。(逆行列のような特殊なケースの場合のみ存在する?) では単位行列の積を行うと、どういった...
  • 行列:平行移動行列
    平行移動行列です。 まず、以下の図を見て下さい。 OpenGL と DirectX では行列の行と列の並びが違います。 ややこしいですね。 しかし、いずれも、13番目の要素がX軸、14番目の要素がY軸、15番目の要素がZ軸の 平行移動成分を表している事に変わりはありません。 glMultMatrixf();を使うと行列を掛け合わせる事ができます。 ではまた、チュートリアル 固定機能編 の 球を表示して移動する のプログラムを 平行移動行列を掛け合わせるように書き換えてみました。 全く同じに動作している事がわかると思います。 #pragma comment(linker, /SUBSYSTEM WINDOWS /ENTRY mainCRTStartup ) #include GL/freeglut/freeglut.h #define WIDTH 320 #define HEIG...
  • 行列:拡大縮小行列
    拡大縮小行列です。 OpenGL、DirectX 共に行と列の方向が変わっても同じです。 チュートリアル 固定機能編 の 円錐の表示と拡大縮小 のプログラムを置き換えました。 #pragma comment(linker, /SUBSYSTEM WINDOWS /ENTRY mainCRTStartup ) #include GL/freeglut/freeglut.h #include math.h #define PI 3.1415926 #define WIDTH 320 #define HEIGHT 240 //拡大縮小用 float size = 1.0f; bool flag = false; //水色 GLfloat aqua[] = { 0.0, 1.0, 1.0, 1.0 }; //ライトの位置 GLfloat lightpos[] = { 200.0, ...
  • メニュー
    Menu トップページ コメント板 GL Wrapper 総合サイト 初めに なぜOpenGLを使うのか? 設定の仕方 困った時は 考察 PC用語の独自調査 GitHubの使い方 Visual Studio 2022 DE Visual C++ 2015 Visual Studio 2017 Expressを入手する MESH VIEW(メッシュビューア) チュートリアルリンク ▼固定機能編へ ▼固定機能 スタティックメッシュ編へ ▼固定機能 階層メッシュアニメーション編へ ▼固定機能 スキニング編へ ▼シェーダー GLSL編へ ▼シェーダー 画像フィルタ偏へ ▼3Dライブラリ編 Irrlicht編へ ▼3Dライブラリ編 Ogre編へ ▼当たり判定 2D編へ ▼当たり判定 3D編へ ▼物理演算 Bullet Physicsへ ▼物理演算 ...
  • 行列:合成行列から拡大縮小成分を抜き出す
    平行移動、回転、拡大縮小成分が合成された行列から 拡大縮小成分だけを抽出します。  具体的なやり方は、合成行列の平行移動成分を除いた各列の3要素の ベクトルの大きさを計算すると拡大縮小成分が抽出されます。 //#pragma comment(linker, /SUBSYSTEM WINDOWS /ENTRY mainCRTStartup ) #include GL/freeglut/freeglut.h #include math.h #include stdio.h #define PI 3.1415926 #define WIDTH 320 #define HEIGHT 240 GLfloat modelview[16]; void matrix_print(char* text) {  printf(text);  glGetFloatv(GL_MODELVIE...
  • 行列(マトリックス)とは
    ここで行列(マトリックス)の解説をします。 ここで言う行列というのはお店の前に人がいっぱい並んでいる事ではありません。 数学で使う行列の事です。 行列(マトリックス)とは数字を行と列に並べて括弧でくくったものです。 3×3行列は 4×2行列は 2×5行列は のような感じです。ちなみに数字は適当です。 あくまでも、こういう物だという事だけ解ればなんとかなります。 3×3行列は3つの行と3つの列、4×2行列は4つの行と2つの列といった感じです。 行と列に分かれているイメージです。 そして、DirectX や OpenGL のような 3Dの座標変換には 4×4行列を用います。 今まで使用してきた glLoadIdentity(); や glTranslatef(x,y,z); や glRotatef(angle,x,y,z); とか glScalef(x,y,z); 等も実は内部で行列を使...
  • 同次座標系
    三次元の X,Y,Z座標に平行移動行列や回転行列を適用した後の座標を得るには どうすれば良いでしょう? 平行移動ならば単純にそれぞれのベクトルの和で済みます。 ですが回転行列となると乗算が必要になり、色々とややこしくなります。 そこで登場するのが同次座標系です。 これは X,Y,Zに1次元増やして X,Y,Z,Wにして、Wを1にしたものです。 普通の座標系ではX/W,Y/W,Z/Wとなる点を表します。   こうする事でどんなメリットがあるのでしょうか? 行列の計算方法を思い出して下さい。 3次元のベクトルでは1×3行列となり4×4行列とは計算する事すらできません。 ところが4次元のベクトルになると1×4行列となり4×4行列と積の計算をする事が可能になります。 そして、良くできた事に平行移動や回転、拡大縮小等の行列、あるいは合成行列であっても積、 つまり乗算で全て計算できるようになります...
  • ボーンオフセット行列
    以下は SkinWeights チャンクですが、最後の方にある matrixOffset は ボーンオフセット行列と呼ばれます。 SkinWeights    {     Joint_2 ;  //transformNodeName ボーン名     32;  //nWeights ボーンの影響を受ける頂点の数     0,  // ↓ vertexIndices ボーンの影響を受ける頂点のインデックス ・ ・ ・     0.001631,  // ↓ weights ボーンの影響を受ける各頂点の重み ・ ・ ・     1.000000,0.000000,-0.000000,0.000000,  // ↓ matrixOffset     0.000000,1.000000,-0.000000,0.000000,  //メッシュの頂点をボーン空間に変換する行列     -0.000...
  • キーフレーム
    キーフレームですが、.Xのアニメーションキーのキータイプ情報は 0…回転  w,x,y,zの順にクォータニオンデータ 1…拡大縮小 x,y,zの順に拡大縮小データ 2…平行移動 x,y,zの順に平行移動データ 4…合成行列 回転、拡大縮小、平行移動行列が掛け合わされた4×4行列データ となっています。 回転の情報がクォータニオンになっているのは知っての通り、ジンバルロックを 避けるためです。そして、このクォータニオンは行列を使っています。 キータイプの4が合成行列になっている事もあり、ここから先は行列の知識が 必要になると思います。 そこで、次回からは階層アニメーションからちょっと逸れて、 行列に関する解説に入ります。          
  • クォータニオンと回転行列の変換
    平行移動、拡大縮小と来たら次は回転です。 しかし、回転行列を単純に線形補間した場合は意図した結果にはなりません。 もちろん、X軸のみとかY軸のみ、Z軸のみの回転情報であった場合は上手くいきますが、 ほとんどのケースでそれらが混載していると思います。 どうすれば良いかと言うと、任意軸回転を線形補間してやると意図する結果になります。 任意軸回転と言えばクォータニオンですね。 2つの回転行列があったとして回転情報をクォータニオンに変換して、それを線形補間し、 補間されたクォータニオンを今度は回転行列に変換してやると2つの回転行列の間を 綺麗に補間できるでしょう。   //#pragma comment(linker, /SUBSYSTEM WINDOWS /ENTRY mainCRTStartup ) #include GL/freeglut/freeglut.h #include s...
  • スキンメッシュアニメーションの原理3
    スキンメッシュアニメーションの真髄、頂点に座標変換を 施す処理ですが、具体的には 頂点座標 × ボーンオフセット行列 × 座標変換行列 × バインドポーズ行列 という事になります。 スキンメッシュアニメーションの仕組みは ①ボーンが階層アニメーションを行っている。 ②頂点座標データを書き換える。 の次は ③頂点座標 × ボーンオフセット行列 × 座標変換行列 × バインドポーズ行列 と、なりそうですが、これで完全ではありません。 詳しくは言いませんが、これだけではモデルがバッキバキに変形してしまいます。 では、どうスムーズに変形させるかと言うと、頂点が各ボーンから受ける影響の 重み(ウェイト)を設定してあげれば良いですね。 解説は次回に回します。          
  • バインドポーズ
    バインドポーズの解説です。 ボーンは、グローバル座標上(絶対座標上)で、それぞれ自らの基準となる位置情報を持ちます。 その位置情報(行列)を元にボーンの基準系とも言うべきローカルな座標系が算出できる訳ですが、 そのボーンの行列の逆行列(グローバル座標の原点に戻す行列)の事を 『バインドポーズ』、あるいは『バインドポーズ行列』と呼びます。 ここまでの知識でスキンメッシュの初期姿勢(アニメーション無し)を ボーンも含めて表示する事ができるはずです。 では次回、スキンメッシュの初期姿勢を表示してみましょう。        
  • スキンメッシュアニメーションの原理2
    スタティックメッシュを変形させるにはどうすれば良いのでしょう? スタティックメッシュを構成する要素には ①頂点座標 ②法線 ③UV ④マテリアル ⑤テクスチャ 等がありますが、この中の ①頂点座標 を変更してあげれば スタティックメッシュが変形します。 頂点座標を変更すると言っても glTranslatef とか glRotatef 等では モデルビュー行列が変更されるだけで頂点座標そのものは変更できません。 では、何か、頂点座標を変更するようなものがあるかと言うと、 そのようなものは用意されていません。 スタティックメッシュの頂点座標が格納されている配列データを 直接、平行移動やら回転等をしているかのようにデータを書き換えなければなりません。 この場合、あくまでも書き換えるのは表示用のデータで、初期姿勢のデータを 変更してはいけません。 スキンメッシュアニメーションの仕組みは ①ボーンが...
  • スキンメッシュアニメーションの原理4
    ここまでのおさらいです。 ①、ボーンが階層アニメーションを行っている。 ②、頂点座標データを書き換える。 ③、(頂点座標 × ボーンオフセット行列 × 座標変換行列 × バインドポーズ行列) × 頂点ウェイト ④、 ③を影響するボーンの数だけ処理して足す(頂点ブレンド) ⑤、 ④で得られた頂点座標を元に頂点法線を再設定する 以上でスキンメッシュアニメーションの処理は完成です。          
  • 2Dと3Dの描画を切り替える
    2Dと言っても、今では3Dを平面的に扱って表示しています。 その方が高速だったからです。 そして、なんと言っても2Dを3Dの一部として扱うと、移動、回転、 拡大縮小が自由自在に行える利点もあります。 そこで2Dと3Dを同時に描画しようとした場合、工夫が必要になります。 上手く切り替えてやらないと3Dも2Dも同じように移動、回転、拡大縮小 してしまいます。 それには、まず3Dを描画してから glPushMatrix(); で階層を降ります。 そして2Dを描画して glPopMatrix(); で階層を上がります。 これを繰り返します。 つまり3Dを親階層として2Dを子階層とします。 なので、子階層で何をしようが、親階層には影響が無いのです。   ファイル main.cpp main.cpp #pragma comment(linker, /SUBSYSTEM WINDOWS /ENT...
  • ステンシルテスト
    ステンシルテストです。 ステンシルバッファの値を調べて描画するかしないかを決める事ができます。 画面の切り抜きができるようになります。   ファイル main.cpp main.cpp #pragma comment(linker, /SUBSYSTEM WINDOWS /ENTRY mainCRTStartup ) #include GL/freeglut/freeglut.h #define WIDTH 320 #define HEIGHT 240 //平行移動用 float x = 0.0f; bool flag = false; //緑 GLfloat green[] = { 0.0, 1.0, 0.0, 1.0 }; //ライトの位置 GLfloat lightpos[] = { 200.0, 150.0, -500.0, 1.0 }; void SquareF...
  • gluPerspectiveを置き換える
    gluPerspectiveを置き換えてみます。 gluPerspective(fovy, aspect, near, far) の作り出す行列は となっています。 そして と定義されます。 cotangent(余接、コタンジェント)は math.h にありませんので 自作します。 #pragma comment(linker, /SUBSYSTEM WINDOWS /ENTRY mainCRTStartup ) #include GL/freeglut/freeglut.h #include math.h #define PI 3.1415926 #define WIDTH 320 #define HEIGHT 240 //平行移動用 float x = 0.0f; bool flag = false; //緑 GLfloat green[] = { 0.0, 1.0,...
  • ソフトウェアスキニング
    これまでやってきた様に、固定機能を使ってCPUのみで行列計算を行う スキニング処理の事を「ソフトウェアスキニング」と言います。 最近のPCはCPUもパワフルになっていますが、3Dゲーム制作等では さすがにスキニングをCPUのみで行うのは無謀です。   行列計算をシェーダーを使ってGPUに行わせるスキニング処理を 「ハードウェアスキニング」と言います。                  
  • 再びキーフレーム
    長らく道を逸れましたが、ここで再びキーフレームに戻ります。 .Xのアニメーションキーのキータイプ情報 0…回転  w,x,y,zの順にクォータニオンデータ 1…拡大縮小 x,y,zの順に拡大縮小データ 2…平行移動 x,y,zの順に平行移動データ 4…合成行列 回転、拡大縮小、平行移動行列が掛け合わされた4×4行列データ まず、最初に知っておかなくてはならない事があります。 それは、当サイトで使用している Cyberdelia は、合成行列タイプの アニメーションデータは階層構造が正しく生成できないという事です。 詳しくは Cyberdelia に付属のヘルプを参照して下さい。 とは言っても、合成行列でないタイプの方は正しく出力されますので、 それを元に合成行列を作成し、単純なキーフレームアニメーションを表示して みたいと思います。 とりあえず、平行移動行列だけに対応したプログラムを作成...
  • 頂点ブレンディング
    頂点ブレンディングの解説です。 前回までの解説で各頂点が各ボーンから受ける頂点ウェイトの 影響の度合いがわかりました。   頂点ブレンディングとは、その影響を受けた頂点座標を 算出する処理の事です。   具体的には、 頂点座標 × ボーン行列 × 頂点ウェイト を、その頂点に影響するボーンの数だけ処理して それぞれの結果を足します。(ブレンドする) これが、頂点ブレンディング処理です。   ここまでの知識で、スキンメッシュアニメーションの基本的な事が できるようになっています。   次回、実際にスキンメッシュアニメーションを行ってみましょう。            
  • コメント板
    簡易掲示板です。 何かありましたらコメントを。 てすと -- 管理人 (2010-03-22 11 30 06) directXのホウノライブラリは開発中止になったんですか? -- 人間 (2010-09-26 23 25 06) OpenGL最近勢いづいてていい感じですね。C#+OpenTKの開発のしやすさもなかなかすごいし、ゲーム業界もOpenGLにシフトしないかな。 -- shocker (2010-09-29 02 37 52) カンリニンサァァアアーーーン -- 人間 (2010-10-05 21 44 33) DX Wrapperライブラリの開発は無期限停止状態です。 -- 管理人 (2010-10-10 19 40 54) ゲーム業界でもPC、XBOX、DC以外はOpenGL採用の方向になっているようです。 -- 管理人 (...
  • 同次座標系で計算
    それでは、実際に計算してみます。 正しく処理されているのがわかると思います。 //#pragma comment(linker, /SUBSYSTEM WINDOWS /ENTRY mainCRTStartup ) #include GL/freeglut/freeglut.h #include stdio.h #define WIDTH 100 #define HEIGHT 50 //マトリクス構造体 struct MATRIX {     union {         struct {             float _11, _12, _13, _14;             float _21, _22, _23, _24;             float _31, _32, _33, _34;             float _41, _42, _4...
  • .Xの階層メッシュアニメーションを読み込んでみる4
    .xの階層アニメーションを読み込んで再生するプログラムが完成したので公開します。 クォータニオンの符号の判定には皆さん、苦労されたのではないでしょうか。 ネットで広く公開されているサンプルはほとんどがDirectX用で いちいち転置しなければならなかったり。 左手座標用に作成したアニメーションXファイルはクォータニオンのY軸とZ軸を-1倍しないと OpenGLではおかしな表示になるとか。 回転角度が181度とマイナス179度ではクォータニオンの符号が反転してるけど 同じ回転行列になるとか。 いやはや、手間取りました。 最後に親階層から子階層へ脈々と行列を受け継いで完成です。 『固定機能 階層メッシュアニメーション編』の『階層構造』で作成した sample4.xを表示しています。 尚、Cyberdelia で作成したアニメーションXファイルだけに対応しています。    font.h #pr...
  • gluLookAtを置き換える
     gluLookAt を置き換えてみます。 #pragma comment(linker, /SUBSYSTEM WINDOWS /ENTRY mainCRTStartup ) #include GL/freeglut/freeglut.h #include math.h #define PI 3.1415926 #define WIDTH 320 #define HEIGHT 240 //平行移動用 float x = 0.0f; bool flag = false; //緑 GLfloat green[] = { 0.0, 1.0, 0.0, 1.0 }; //ライトの位置 GLfloat lightpos[] = { 200.0, 150.0, -500.0, 1.0 }; //単位行列 GLfloat mat[]={  1,0,0,0,  0,1,0,0,  0,0,...
  • アルファブレンディング
    アルファブレンディングです。 アルファブレンディングで注意しなければならない事があります。 いかなるグラフィック描画でも基本的には一番最後に描画したものだけが表示されて、 それまでにあった描画は全て上書きされてしまいます。 ですが、3D描画ライブラリにはデプスバッファやZバッファがあり隠面消去を使うと手前のものは 上書きされないようにすることができます。 しかし、透明度のある物体を描画するときに隠面消去を使用すると本来は色が合成されて 表示されるはずのものが隠面消去により、まるまる描画されなかったりします。 それを解決するには、 1.不透明なオブジェクトを描画 2.半透明オブジェクトをZソート(視点からの奥行き順) 3.半透明オブジェクトの、奥にあるものから描画 という手順を踏む必要があります。 今回のプログラムではスペースキーを押す度にブレンディング係数を切り替えます。   ファイル ...
  • 球面線形補間
    クォータニオンとクォータニオンを補間するには 『球面線形補間』を使います。 #pragma comment(linker, /SUBSYSTEM WINDOWS /ENTRY mainCRTStartup ) #include GL/freeglut/freeglut.h #include stdio.h #include math.h #define WIDTH 320 #define HEIGHT 240 #define PAI 3.14159 //黄色 GLfloat yellow[] = { 1.0, 1.0, 0.0, 1.0}; bool flag=true; float t=0.0f; struct Vector3f{  float x;  float y;  float z; }vec3d; //クォータニオン構造体 struct Quaternion{ ...
  • ビルボード
    ビルボードです。 ビルボードというのは常に視点(カメラ)を向く板の事です。 古くは樹木や球のポリゴン数を減らすために用いられました。 現在では火花や雪などのパーティクルとして主に使用されます。 ビルボードにはビュー行列を逆行列にする方法もありますが、 今回はもっと簡単に実装できるやり方がありましたので紹介して おきます。 3D空間のビルボードオブジェクトの中心位置を保存しておき、 glLoadIdentity(); して初期化します。 中心位置から画像サイズ分だけ+-してポリゴンを描画すると 行列計算なしでビルボードができます。   ファイル main.cpp lodepng.cpp lodepng.h tree.png map.png main.cpp #pragma comment(linker, /SUBSYSTEM WINDOWS /ENTRY mainC...
  • ウェイト
    ウェイトの解説です。 Weight は重さの事ですが、ここで言うウェイトとは、頂点ウェイトの事です。   頂点ウェイトとはモデルの頂点に関連付けられたボーンが移動した際に、 その頂点がそのボーンにどれだけ追従するかの比率の事です。   基本的には頂点ウェイトは、0.0~1.0の正規化された範囲で表されます。 場合によっては、0.0~1.0の範囲外のデータの場合もありますが、 その場合でも自前で正規化して使います。          
  • 階層ボーンアニメーション
    今回はボーンだけを階層アニメーションさせてみます。 今回も新しく box.x というファイルを作成しています。 スタティックメッシュをボーンが突き抜けていて若干、間抜けな図ですが 順番としてはこれで合っています。 次回からは、このスタティックメッシュを変形させる仕組みを考察してみます。 font.h #pragma once class GLFONT { public  HFONT Hfont;  HDC Hdc;  GLFONT(wchar_t *fontname, int size);  void DrawStringW(int x,int y,wchar_t *format, ...); }; //コンストラクタ フォント作成 GLFONT GLFONT(wchar_t *fontname, int size) {  Hfont = CreateFontW(        ...
  • .Xのスキンメッシュアニメーションを読み込んでみる1
    階層メッシュクラスを継承してスキンメッシュクラスを作成します。 ジョイントは球でボーンは四角錐にしました。 固定機能 スキニング編『スキンメッシュアニメーションの原理1』で 作成した man.x を表示しています。 Cyberdelia と ToyStudio では出力されるXファイルの書式が異なりますので 今回からは Cyberdelia で出力したXファイルには対応しない事にします。 font.h #pragma once class GLFONT { public  HFONT Hfont;  HDC Hdc;  GLFONT(wchar_t *fontname, int size);  void DrawStringW(int x,int y,wchar_t *format, ...); }; //コンストラクタ フォント作成 GLFONT GLFONT(wchar_t *...
  • 法線の再設定
    さて、前回のプログラムでは法線を再設定していないので ライトを有効にするとおかしな描画になってしまいます。 ここで言う法線とは頂点法線の事なので、前回のプログラムで 求められた頂点変換後の頂点座標がそのまま使えます。 一つ注意しないといけないのは頂点法線は正規化してデータに 納めないといけない事です。   font.h #pragma once class GLFONT { public  HFONT Hfont;  HDC Hdc;  GLFONT(wchar_t *fontname, int size);  void DrawStringW(int x,int y,wchar_t *format, ...); }; //コンストラクタ フォント作成 GLFONT GLFONT(wchar_t *fontname, int size) {  Hfont = CreateFontW(...
  • .Xのスキンメッシュアニメーションを読み込んでみる2
    .x のスキンメッシュアニメーションを読み込んで表示します。 このプログラムは box.x 専用です。 わかりやすくするために敢えて、このようにしました。      これで完成ではありません。 法線を再設定してあげないと光の反射具合が変になってしまいます。 詳しくは次回に回します。   font.h #pragma once class GLFONT { public  HFONT Hfont;  HDC Hdc;  GLFONT(wchar_t *fontname, int size);  void DrawStringW(int x,int y,wchar_t *format, ...); }; //コンストラクタ フォント作成 GLFONT GLFONT(wchar_t *fontname, int size) {  Hfont = CreateFontW(        ...
  • 視点の回転(クォータニオン)
    視点を回転させます。 回転方法にはいろいろとあります。 ロールピッチヨー、オイラー角、クォータニオンなどです。 ロールピッチヨーはZ軸、Y軸、X軸を順番に回転させて目的の角度にする方法です。 飛行機の姿勢を表す時によく使われます。最も解り易く素直な方法です。 オイラー角はZ軸、X軸(またはY軸)、Z軸と回転させて目的の角度にする方法です。 3つの軸を使わなくても2つの軸があれば目的の角度にたどり着きます。 しかし、ロールピッチヨーとオイラー角には欠点があります。ジンバルロックと呼ばれるものです。 たとえば、X軸を90度傾けると、Y軸とZ軸が同軸となってしまい、その姿勢を保存して また新たに回転をしようとしたときに問題がおきます。 X軸とY軸をそれぞれ90度傾けると全ての軸が同軸となり一つの方向にしか回せなくなります。 それを解消する方法がクォータニオンです。 クォータニオンは軸を任意に作成...
  • 3D:OBBとOBB
    OBBです。 バウンディングスフィアの応用で中心位置と半径を使い、 内積と外積を駆使して当たり判定を行います。 font.h #pragma once class GLFONT { public  HFONT Hfont;  HDC Hdc;  GLFONT(wchar_t *fontname, int size);  void DrawStringW(int x,int y,wchar_t *format, ...); }; //コンストラクタ フォント作成 GLFONT GLFONT(wchar_t *fontname, int size) {  Hfont = CreateFontW(         size,      //フォント高さ         0,       //文字幅         0,       //テキストの角度         0,       ...
  • 球を表示して移動する
    球を表示して平行移動します。 glTranslatef(x,y,z) に値をセットする事で平行移動の行列を適用できます。 glutSolidSphere(半径,経線の分割数,緯線の分割数) で球を表示できます。   ファイル main.cpp main.cpp #pragma comment(linker, /SUBSYSTEM WINDOWS /ENTRY mainCRTStartup ) #include GL/freeglut/freeglut.h #define WIDTH 320 #define HEIGHT 240 //平行移動用 float x = 0.0f; bool flag = false; //緑 GLfloat green[] = { 0.0, 1.0, 0.0, 1.0 }; //ライトの位置 GLfloat lightpos[] = { 200....
  • トーラスの表示と回転
    トーラス、ドーナツ形状を描画します。 glRotatef(回転角度,X軸の影響度,Y軸の影響度,Z軸の影響度) で回転行列を適用し、 glutSolidTorus( 内側の半径,外側の半径,断面の分割数,リングの分割数) でトーラスを描画します。   ファイル main.cpp main.cpp #pragma comment(linker, /SUBSYSTEM WINDOWS /ENTRY mainCRTStartup ) #include GL/freeglut/freeglut.h #define WIDTH 320 #define HEIGHT 240 //回転用 float anglex = 0.0f; //オレンジ GLfloat orange[] = { 1.0, 0.6, 0.0, 1.0 }; //ライトの位置 GLfloat lightpos[] = ...
  • 円錐の表示と拡大縮小
    円錐を拡大縮小表示します。 glScalef(X軸,Y軸,Z軸) で拡大縮小し、 glutSolidCone(底面の半径,円錐の高さ,円の分割数,高さの分割数) で円錐を表示します。 行列の適用順序を間違えると意図している物とは別の状態になってしまいます。 それは、それぞれが原点 (0,0,0) を基準に適用するからです。 一般的には、拡大縮小してから回転し、最後に平行移動すると意図する状態になるでしょう。 (DirectXの場合) *OpenGLの場合は逆順。   ファイル main.cpp main.cpp #pragma comment(linker, /SUBSYSTEM WINDOWS /ENTRY mainCRTStartup ) #include GL/freeglut/freeglut.h #define WIDTH 320 #define HEIGHT 240 ...
  • 固定機能:テクスチャマッピング
    テクスチャマッピングと言っても、『画像を表示する』のチュートリアルで既にやっています。 ただ、今回は、より踏み込んでテクスチャのST座標を回転してみます。 それには、テクスチャマトリックスを使用します。 マトリックスと言えば、glMatrixMode(GL_PROJECTION); とか、glMatrixMode(GL_MODELVIEW); が、あるように glMatrixMode(GL_TEXTURE); というテクスチャ用のマトリックスモードがあります。 このテクスチャ空間も,物体の空間 (x, y, z, w) と同じように4次元 (s, t, r, q)で用意されていて、 移動、回転、拡大縮小などの行列を適用できます。   ファイル main.cpp sample.png main.cpp #pragma comment(linker, /SUBSYSTEM WIN...
  • .Xの階層メッシュアニメーションの構造
    それでは、中身をメモ帳で見てみます。 例によってテンプレート部分は除去しています。 xof 0302txt 0032 Header {  1;  0;  1; } Frame obj1 {   Mesh Mesh_obj1 {    8;     -0.737684;0.370641;-1.270489;,     -0.737684;-0.370641;-1.270489;,     0.737684;0.370641;-1.270489;,     0.737684;-0.370641;-1.270489;,     0.737684;0.370641;1.270489;,     0.737684;-0.370641;1.270489;,     -0.737684;0.370641;1.270489;,     -0.737684;-0.370641;1.270489;,    ...
  • ソフトシャドウ
    ソフトシャドウです。 影の外側を、ぼやけさせます。 vertex.shader varying vec3 P; varying vec3 N; void main(void) {   P = vec3(gl_ModelViewMatrix * gl_Vertex);   N = normalize(gl_NormalMatrix * gl_Normal);     gl_TexCoord[0] = gl_TextureMatrix[0] * gl_Vertex;   gl_Position = ftransform(); } flagment.shader varying vec3 P; varying vec3 N; uniform sampler2DShadow shadowMap; uniform float dis;//サンプリング変位 float shadow = 0.3...
  • シャドウマッピング
    シャドウマッピングです。 一時的に視点を光源に移してみると光の当たる部分を見る事ができます。 その時の見えない部分=障害物=デプスバッファの値が影となります。 オブジェクトが別のオブジェクトに落とす影は、もちろんの事、 オブジェクト自身が自らに落とす影も描画する事ができます。 vertex.shader varying vec3 P; varying vec3 N; void main(void) {   P = vec3(gl_ModelViewMatrix * gl_Vertex);   N = normalize(gl_NormalMatrix * gl_Normal);     gl_TexCoord[0] = gl_TextureMatrix[0] * gl_Vertex;   gl_Position = ftransform(); } flagment.shader v...
  • .Xの階層メッシュアニメーションを読み込んでみる3
    平行移動と同じようにして拡大縮小も線形補間してみました。 新規に作成した sample3.x を表示しています。   font.h #pragma once class GLFONT { public  HFONT Hfont;  HDC Hdc;  GLFONT(wchar_t *fontname, int size);  void DrawStringW(int x,int y,wchar_t *format, ...); }; //コンストラクタ フォント作成 GLFONT GLFONT(wchar_t *fontname, int size) {  Hfont = CreateFontW(         size,      //フォント高さ         0,       //文字幅         0,       //テキストの角度         0,      ...
  • @wiki全体から「行列:効率の良い合成」で調べる

更新順にページ一覧表示 | 作成順にページ一覧表示 | ページ名順にページ一覧表示 | wiki内検索