デジタル・デザイン・ラボラトリーな日々

アラフィフプログラマーが数学と物理を基礎からやり直す

3Dを基礎から勉強する 複数モデルの表示

前回の「3Dを基礎から勉強する カリング処理」から2ヶ月経ってしまいましたが、また再開したいと思います。

今回は複数モデル(立方体、球、円柱、円錐、トーラス)の表示となります。
基礎からなのでライブラリを使わないで自前で表示するのが今回の目的です。

3Dモデルを表示するJavaアプレットの作成 (1/3):CodeZine

3Dモデルは上記記事のモデルデータを使いました。そのモデルデータは5つのモデルが一体になっていましたが、1モデル単位でも表示できるようにデータの位置を調べて分解しました。

■モデルの表示について
すべての多角形は三角形の組み合わせで表現できます。ゲームのキャラクターのような複雑な形状も突き詰めれば三角形の塊で表現できるのです。
f:id:Yaju3D:20141101202403j:plain

立方体のモデルデータは下記のようになっています。(実際の頂点データを分かりやすく説明する為に1のみにしています)
頂点(vertices)データと面番号(faces)データを組み合わせてモデルを表示します。

// 立方体
var Cube: ModelData = {

    "vertices": [
        1,  1, -1,
       -1,  1, -1,
        1,  1,  1,
       -1,  1,  1,
        1, -1,  1,
       -1, -1,  1,
        1, -1, -1,
       -1, -1, -1
    ],
    "faces": [
        2, 4, 3, // 6
        2, 3, 1,
        4, 6, 5, // 2
        4, 5, 3,
        6, 8, 7, // 5
        6, 7, 5,
        8, 2, 1, // 1
        8, 1, 7,
        8, 6, 4, // 4
        8, 4, 2,
        1, 3, 5, // 3
        1, 5, 7
    ]
}

立方体の頂点は8つで構成され、面は6つになりますが、データ的には下図で表すように三角形2つで1つの面にしています。その為、面データは2×6=12個あります。
f:id:Yaju3D:20141101234115j:plain
面番号(faces)は、下図では①~⑧で表しています。
面に大きく書かれている番号1が面データ(⑧,②,①と⑧,①,⑦)となっているのが分かりますでしょうか。
f:id:Yaju3D:20141102013653j:plain

他のモデルデータもこのような仕組みとなっております。


■プログラム
オリジナルとは違い、各モデルの表示有無や軸の表示を追加しています。
また、「モデルの大きさが原点を中心とする1辺が2の立方体に収まるようにする」とのコメントがソースリストにあったのですが、そのイメージが実際に分かるように立方体を表示してみました。

var modelSize = Math.max(maxV.x - minV.x, maxV.y - minV.y);
modelSize = Math.max(modelSize, maxV.z - minV.z);

// モデルの大きさが原点を中心とする1辺が2の立方体に収まるようにする
for (var i = 0; i < this.vertices.length; i++) {
   var v = this.vertices[i];
   v.x = (v.x - (minV.x + maxV.x) / 2) / modelSize * 2;
   v.y = (v.y - (minV.y + maxV.y) / 2) / modelSize * 2;
   v.z = (v.z - (minV.z + maxV.z) / 2) / modelSize * 2;
}

f:id:Yaju3D:20141102015907j:plain
モデルを1つのみ表示するとサイズも合わせて大きくなるのですが、何故かトーラスのみ表示した際に他と違いサイズが大きくならないという課題が残っています。データの問題なんではないかと推測していますが…。


Typescriptで組んだソースリストは、github/Study3Dに公開しました。