FireMonkey 3D

提供: Appmethod Topics
移動先: 案内検索

FireMonkey アプリケーション ガイド への移動


3D 入門

FireMonkey を利用すると、3 次元(3D)空間内のオブジェクトを 2 次元(2D)で表示できます。TViewport3D には 3D コンテンツが 2D 形式で表示されるのに対して、TForm3D は 3D コンテンツから始まります。2D と 3D をネストさせることができます。

FireMonkey 3D では、プラットフォーム固有の次のライブラリを使用します。

  • Windows の場合は Direct3D ライブラリ(DirectX の一部で、Winapi ユニット スコープで提供されています)
  • Mac の場合は OpenGL ライブラリ(Macapi ユニット スコープで提供されています)

3D オブジェクト

FireMonkey には、以下のようないくつかの種類の 3D オブジェクトが用意されています。

  • TCubeTSphereTCone などの 3D プリミティブ図形。
  • 複雑な 3D オブジェクト用の TMesh
  • TText3D などの、3D 空間に押し出された 2D オブジェクト。押し出されたオブジェクトには 3 つの面があります。前面(元の 2D 図形)、背面((その図形の鏡像)、それら両面間の押し出しのシャフトです。
  • TImage3DTTextLayer3D などの、3D 空間における平らな 2D オブジェクト。

3D 空間におけるオブジェクトの位置は、TPosition3D を使って、X 座標、Y 座標、Z 座標で指定されます。高さ(Height)と幅(Width)に加えて、オブジェクトには奥行き(Depth)もあります。3D 空間における平らな 2D オブジェクトの薄さは任意で、奥行き(Depth)0.01 としてハードコードされています。3D オブジェクトには、3D 回転角拡大縮小率があります。位置、サイズ、回転角、拡大縮小率はすべて、オブジェクトの中心点からの相対的なものです。

2D コントロールの場合と同様に、FireMonkey における任意の 3D コントロールも他の任意の 3D コントロールの親になることができます。子の位置と回転角はその親からの相対的なものになります。親を移動したり回転すると、そのコンポーネント サブツリーは再配置されます。TLayout3D を、他にこれと言って特徴のない親として使用して、他のオブジェクトを整理することができます。

2D 平面に配置された 2D オブジェクトでは、それらの階層を決定するために "Z オーダー" という考え方が必要なのに対して、3D 空間内のオブジェクトにはもともと順序があるため、見通しの利く地点から見たときに、より近いオブジェクトは同じ視線上のより遠いオブジェクトを遮ります。

カメラ

3D 空間のあらゆるビューはカメラで制御されます。カメラの位置と向き(3D 回転)で、表示されるものが決まります。フォーム デザイナには常に設計カメラがあり、実行時にはそれがデフォルトで使用されます。設計カメラは(-Y 方向に向かって)-Z 軸の真上にあり、X-Z 面と直交し、位置 (0,0,0) がビューの中心になるようにやや下方を向いています。別のカメラを使用するには、TViewport3D または TForm3D の UsingDesignCamera プロパティを False に設定し、TCamera インスタンスを Camera プロパティに割り当てます。1 つのシーンにカメラが複数あってもかまいません。別のカメラを Camera プロパティに割り当てたあと、Repaint を手動で呼び出す必要があります。

目に見える空間領域は錐(すい)台で、近接した平面がカメラの少し前にあります。カメラとその前方平面の間にあるものはすべて、ビューからクリップされます。視野の角度は垂直に固定されています。ビューポート/フォームの高さを増やすとあらゆるものが大きくなり、幅を増やすと左右に広がります。位置とサイズの単位は、視野の尺度を基準に決まります。

画面投影

オブジェクトの表示(または非表示)はカメラで決まるだけでなく、3D ゲームにある固定の状態表示のように、カメラがどこを向いていてもオブジェクトが見えるように設定することもできます。それには、Projection プロパティをデフォルトの Camera から Screen に変更します。その結果、

  • Position.Z がゼロの場合:
    • XY 0,0 は、2D の場合と同様に、左上隅になります。なお、3D 位置は、2D の場合のようにオブジェクトの左上ではなく、依然として、オブジェクトの中心の位置を表しています。
    • Height、Width、Depth の大きさは、視野の尺度によらず、ピクセル数に等しくなります。
    • 単位がピクセル数になるので、画面投影を使用した場合のオブジェクトのサイズは、カメラ投影を使用して同じサイズとして表示された場合よりもずっと大きくなります。
    • オブジェクトは、錐台の前方のクリッピング平面の少し後ろに表示されます。カメラ投影を使用した場合、オブジェクトには小さいすき間があり、前方の平面でクリップされる前に、画面投影されるオブジェクトの前に表示できます。
  • Position.Z がゼロより大きい(見る者から離れている)場合:
    • 表示されるサイズは小さくなります。
    • ビューを縮小すると、オブジェクトが後方に遠のき、さらに小さくなります。
    • ビューを拡大すると、オブジェクトが近づき、大きくなります。
  • Position.Z がゼロより小さい(見る者の近くにある)場合:
    • 表示されるサイズは大きくなります。
    • ビューを縮小すると、オブジェクトが近づき、さらに大きくなります。
    • ビューを縮小するか Position.Z を直接設定してオブジェクトを近づけすぎると、オブジェクトは錐台の前方平面を通過し、その結果見えなくなります。
    • ビューを拡大すると、オブジェクトが後方に遠のき、小さくなります。

フォーム デザイナでは、オブジェクトの Projection プロパティを変更しても、位置が再計算されるため、オブジェクトは移動せず、サイズも調整されます。

カメラ ブーム

オブジェクトやシーンをユーザーによる制御で任意の方向から表示するのは、よくある 3D アプリケーションです。位置と向きを計算してカメラの適切な角度を求めることもできますが、以下のようにして、仮想的なカメラ ブームを作成する方が簡単です。

  1. 対象となるオブジェクトまたはシーンの中心と同じ場所に、TDummy などの非表示オブジェクトを作成します。
  2. そのオブジェクトの子として TCamera インスタンスを作成します。
    1. その Position プロパティに、1 つの軸上の希望距離を設定します。
    2. 必要であれば、カメラが軸に沿ってその場所を指すように RotationAngle プロパティを設定します。カメラが上下逆さまでないことを確かめてください。
  3. これで、ダミー オブジェクトの RotationAngle を変更するだけで、カメラをオブジェクトの周りに回転させることができます。カメラは的確な距離を保ち、中心の方向を自動的に指します。
  4. カメラの子としてライトを追加すると、カメラの移動に合わせて、ライトの距離と向きが保たれます。

光線の当たり方

一般に、3D オブジェクトは、光が当たらなければ、特徴のない黒い塊にすぎません。1 つ以上の TLight オブジェクトが、それらの LightType プロパティ値(以下のいずれか)に応じて、3D 空間における光線を定義します。

Directional
平行光線は一定の角度から一様にやってきます。太陽の光が、これと類似したものとしてよく引き合いに出されます。太陽の光は非常に遠いところから来るので、地球上の局在する地点(差し渡し数マイルではなく、数ヤード程度)では、すべてのものは同じように照らされます。平行光線の(光源の)位置は効果には関係ありません (フォーム デザイナでクリックしようとした場合には、位置が関係してきます)。重要なのは、光線が指す方向(自分自身の RotationAngle と親の RotationAngle で定義される)です。
Point
点光源は、むき出しの電球のようなものです(ただし、細長い部分がないもの)。あらゆる方向に光線が放射し、距離と共に弱くなります。点光源の RotationAngle は何も効果はありません。重要なのは光源の位置ですが、これは親の位置と回転角に左右されます。
Spot
スポット ライトは、位置と回転角の両方に左右され、距離と共に弱くなります。

3D 空間における平らな 2D オブジェクトは、光を必要としませんし、光に左右されることもありません。これらは、3D の遠近感が付加されている以外は、通常どおりに表示されます。

材質

FireMonkey 3D オブジェクトの表面は、その材質で定義されます。FireMonkey の 3D 材質はシェーダに基づいています。そのため、1 つのアプリケーション中で照明と材質をさまざまに変えることができます。使用可能な材質は、[ツール パレット][Materials]カテゴリの下に表示されます。どの FireMonkey 3D オブジェクトにも MaterialSource プロパティがあり、それが材質ソースを現在のオブジェクトにリンクしています。材質のライブラリを保持するには TMaterialBook を使用します。1 つの材質を使用する場合には、ソースから必要な数のオブジェクトにリンクすることができます。

押し出されたオブジェクトには、さらに MaterialShaftSource プロパティと MaterialBackSource プロパティがあります。それぞれは TMaterialSource 型です。

光線の影響でオブジェクトの材質がどう表示されるかを制御するには、TLightMaterialSource にリンクします。

  • Emissive(放射色)は、表面自体が光を放つのか(つまり輝くのか)どうかを決定します。デフォルトは null(不透明度ゼロの黒)です。つまり、オブジェクトは通常、輝かず、見るには光が必要です。色を設定することで、光がないときに表面がその色で見えます。光が当たると、放射色は、光線からもたらされた他の色と混ざります。
  • Ambient(環境色)は、表面が見えるように基調色を提供するためのものです。現実の世界では、いろいろな方向から光が表面に反射しますが、3D シーンで、そうした光をすべて定義するのは困難です。そのため、環境色は空間における任意の光で活性化します。つまり、光がなければ、効果はありません。表面は、その色でほとんど一様に彩色されます。平行光線の場合は(必ずしも表面に向かっている必要はありません)、すべて平らに見えます。点光源またはスポット ライトの場合、色は距離と共に弱まります。
  • Diffuse(拡散反射色)は、入射角も含め、光と直接相互作用します。光がなければ、効果はありません。AmbientDiffuse は同じ色に設定するのが一般的です。
  • Specular(鏡面反射色)は、入射光をいろいろな角度で散乱させるのではなく特定の角度で反射させることで、光沢のある表面をシミュレートしたものです。光がなければ、Specular の効果はありません。デフォルトは白色で、その場合は、色を変えずに光を反射させます。

2D と 3D の混在

3D オブジェクトは 3D コンテナに格納する必要があります。(TCube のような)3D オブジェクトは、(TForm のような)2D コンテナに直接格納された場合には描画されませんが、[構造]ビューには子コントロールとして表示されます。逆に、(TButton のような)2D オブジェクトは、(TForm3D のような)3D コンテナに直接格納された場合には描画されませんが、やはり[構造]ビューには子コントロールとして表示されます。以下の 2 つのクラスにより、2D コンテンツと 3D コンテンツをネストさせて混在させることが可能になります。

  • TLayer3D は、2D コンテンツを格納する 3D オブジェクトです。これは、3D 空間に存在する四角形のガラス板のようなものです。
  • TViewport3D は、3D コンテンツを格納する 2D オブジェクトです。TForm3D のように、これは 3D 空間への "窓" になります。

これらのコンテナはネストしてもかまいません。たとえば、以下のようなオブジェクト階層も可能です。

  • TForm3D
    • TCube
    • TLayer3D
      • TButton
      • TViewport3D
        • TCube

さらに、以下のように、いくつかのクラスでは 2D コンテンツを 3D で直接ホストします。

  • TTextLayer3D はテキストを表示
  • TImage3D はビットマップ画像を表示
  • TVideo3D はビデオを表示

3D モデルのインポート

FireMonkey フレームワークでは、3D モデルのインポートをサポートしています。3D モデルは 3D コンテナ内でしか描画できません。3D モデルをインポートするには、TModel3D オブジェクトを使用します。TModel3D は、[ツール パレット]に含まれています。オブジェクトを読み込むには、TModel3DMeshCollection プロパティを使用します。サポートされている 3D ファイルは、.obj.dae、および .ase です。

モデルは、テクスチャを使用してインポートされ表示されます。シーンに光線がなければテクスチャは見えません。インポートされたモデルは、他の 3D オブジェクトと同様に、基本的な方法で操作できます(回転、移動、拡大縮小、サイズ変更)。

読み込んだモデルを正しく表示できるかどうかは、読み込んだファイルの整合性や正確さによって決まります。

関連項目

コード例