World
Wide Guide to FS Scenery Design 日本語版 | Knowledge
Bank
ScBuildやその他のソフトウェアの作者である Peter Jacobson(e-mail: paj@absoft.com)は、FS5 のカスタムビルを作成する以下の記事を書きました。元の記事は Flight-simメーリングリストに流されたもので、Peter の許可を得て公開します。これが有益であると思ったら、Peter に知らせてください。
Flight Simulator のシーナリ表示エンジンは、単純できちんとした形をしたビルを表現する Building コマンドを持っています。テクスチャをいくつか使うことができ、一日を通して色合いを上手く変えます。しかし、いくつかの理由から、Building コマンドでは複雑で複合した建造物を作ろうとすると満足な結果が得られません。この記事では、シミュレータが提供しているデフォルトのビルのテクスチャを使って複雑な建造物を作る方法について述べます。経験豊かなデザイナと同じ様に、初心者でもテクニックを使えるようにするため、私は様々な段階を十分細かくカバーするよう努めるつもりです。 私はSCASMの文法を使いますが、全てのコマンドは FSASMの文法に簡単に変換できます。
グラフィックエンジンがビルの描画順序を決定できるようにするため、ビルのサブルーチンは PerspectiveCall で開始します:
PerspectiveCall( :MyBuilding )
ビルのサブルーチンは以下のように始まります:
:MyBuilding
Perspective
RefPoint( 7 :Return 1 latitude longitude )
Perspective文はこのルーチンの最初の文でなければなりません。これを忘れるとビルは描かれず、他の問題も生じるでしょう。RefPoint文と条件分岐は良くReturn文へ分岐するので、私は普段 Return 文を一つ持つ :Returnというラベルを Area() の中に定義します。
現実の世界では真北を向いているオブジェクトはごくわずかなので、普通オブジェクトを正しい方位に回転する必要があります。一般に、シミュレータにオブジェクトを回転させることは簡単にできます:
RotatedCall( :DrawMyBuilding 0 0 30 )
Return
この場合、ビルを真北から 30 度回転し、南西-北東の方位を持つことになります。 Return文はこのサブルーチンを終了します。実際の描画ルーチンは、ビルの辺の定義から始まります:
:DrawMyBuilding
Points( 0
x1 z1 y1 ; 0
x2 z2 y2 ; 1
. . .
. . .
. . .
xn zn yn ; n
)
あなたはたぶんビルのスケッチを持っているか、グラフ用紙にビルを描いていることでしょう - 描画したものの点や、上で示したその定義に対して番号を振ると便利です。
これは複合建造物なので、使うことができる単一の描画順序はありません。言い換えれば、見る方向により別のパーツを最初に描き、別のパーツを最後に描く必要があります。 普通遠い位置にあるオブジェクトを先に描きます。順序を決定するため VectorJump命令を使います:
VectorJump( :West 32767 0 0 0 )
VectorJump( :SouthEast 0 0 32767 0
)
:NorthEast
Call( :DrawSouthWest )
Call( :DrawNorthWest )
Call( :DrawSouthEast )
Call( :DrawNorthEast
)
Return
:SouthEast
Call( :DrawNorthWest )
Call( :DrawSouthWest )
Call( :DrawNorthEast )
Call( :DrawSouthEast
)
Return
:West
VectorJump( :SouthWest 0 0 32767 0
)
:NorthWest
Call( :DrawSouthEast )
Call( :DrawNorthEast )
Call( :DrawSouthWest )
Call( :DrawNorthWest
)
Return
:SouthWest
Call( :DrawSouthEast )
Call( :DrawNorthEast )
Call( :DrawNorthWest )
Call( :DrawSouthWest )
Return
これにより異なった4つの方向 - 北東、南東、北西、南西 - から異なった順序で描画されます。オブジェクトの複雑さにより、異なった視点のために幾つかテストを加えることができます。これらのテストは2次元平面でのみテストできることに注意してください。オブジェクトが垂直方向に複雑であれば、観測者の高度によるテストを加える必要があります。
3D面はいくつかあるポリゴンコマンドの1つで描画します。ポリゴンコマンドの選択は、必要な効果により決定します。
ポリゴンを含む平面は3点以上の点で定義され、片方からしか見えません。見える側は実際にポリゴンコマンドに含まれるベクトルで定義されます。面の両側を見えるようにしたいなら、逆むきのベクトルで二回描画しなければなりません。
普通、あなたはベクトルについて心配する必要はありません。なぜなら、 SCASM と FSASM はそれを計算してくれるからです。しかし、時々ヒントを与えてやらなければならないときもあります。ベクトルは RefPoint とポリゴンを含む平面を通して計算されます。 例を示します(平面の端から見ています):
Plane
|
|
*-------------+-----------> vector
|
|
ポリゴンの定義に:
Poly( a p1 p2 p3 ... pn )
を使うなら、これは右側からのみ見えます。
もし左側から見えるようにしたいなら、コマンドを以下のように変えなければなりません:
Poly( ai p1 p2 p3 ... pn )
"a" (automatic) から "ai" (automatic inner) に変更されていることに注意してください。詳細は SCASM と FSASM のドキュメントを参照してください。
もっとも簡単なポリゴンコマンドは Poly()です。面をこれで描画する際、色と面の頂点を指定します:
:DrawSouthWest
SurfaceColor( B F0 )
Poly( a p1 p2 p3 ... pn )
.
.
.
Return
これは Points()リストで定義された点を使ってベージュ色のポリゴンを描画します。
ひとまとめにすると以下のようになります:
; Draw a simple box 32 m high and 16 m on a side
Area( B latitude longitude 255 )
PerspectiveCall( :MyBuilding )
Jump( :End
)
:MyBuilding
Perspective
RefPoint( 7 :Return 1 latitude longitude
)
RotatedCall( :DrawMyBuilding 0 0 30
)
Return
:DrawMyBuilding
Points( 0
-8 0 8 ; 0 upper left
-8 32 8 ; 1
8 0 8 ; 2 upper right
8 32 8 ; 3
8 0 -8 ; 4 lower right
8 32 -8 ; 5
-8 0 -8 ; 6 lower left
-8 32 -8 ; 7
)
SurfaceColor( B F0 )
Poly( a 1 3 5 7 ) ; roof
Poly( a 0 1 3 2 ) ; North side
Poly( a 2 3 5 4 ) ; East side
Poly( a 4 5 7 6 ) ; South side
Poly( a 6 7 1 0 ) ; West side
:Return
Return
:End
EndA
シミュレータのビルのテクスチャファイルを使うと、夜にライトアップされる窓があり、一日を通して太陽が動くにつれて色が変化するテクスチャを描くことができます。
SIDE*.R8 ファイルはビルを描画するためのテクスチャを含んでいます。 それぞれのファイルは、一日の異なる時間帯におけるビルを描画するため、異なった陰影を持つ8つの帯に分割されています。これらのテクスチャに適切な BGL コマンドを使えば、あなたのビルには陰影が付き、日中を夜を通してライトが自動的につきます:
:DrawMyBuilding
Bitmap( side.r8 0 0 0 0 )
Inst_7D
TexPolyShading( 0 0 32767 )
TexPoly( a p1 bx1 by1 p2 bx2 by2 p3 bx3 by3 ... pn bxn byn )
.
.
.
Return
Bitmap() コマンドは、シミュレータにビットマップテクスチャファイルを読込むことを指示します。この場合、ベージュ色で縦縞のあるビルのテクスチャファイルです。Inst_7D は FSASM の ResetTexture コマンドに相当します。
これは TexPoly() コマンドを使う前にテクスチャをリセットするのに使います。TexPolyShading()コマンドはこれらの特殊なビルのテクスチャファイルを 使い、8つの異なる時間帯毎に対して陰影を変えます。
この引数はベクトルであり、ポリゴンは太陽の位置により適切に陰影付けがなされます。
TexPoly() コマンドは実際のポリゴン描画コマンドです。上にしめした Poly()コマンドのように、点のリストからの点を引数に取ります。また、テクスチャファイルからのピクセルオフセット位置を引数に取ります。テクスチャファイルは 256 x 256 ピクセルです。上に示したように、8つの帯があり、それぞれは 32 ピクセルの幅があります。テクスチャは一種のゴム製のデカールです - これはポリゴンに合わせて引き伸ばすことができ、無数のビルのスタイルを提供できます。x オフセットは 31 を越えることはできず、y オフセットは 255 を越えることができません。もしより多くのテクスチャが必要なら、ビルの側面を複数のセグメントに分けて描画しなければなりません。
ピクセルからポリゴンの側面へのマッピングはビルの形状によりますが、一般的に 1 ピクセルを 4 メートルにするのが良い効果をうみます。
サンプルをベージュ色のビルに変えるためには、描画コマンドを以下のように変えます:
SurfaceColor( B F0 )
Poly( a 1 3 5 7 ) ; roof
Inst_7D
TexPolyShading( 0 0 32767 )
TexPoly( a 0 0 0 1 0 8 3 4 8 2 4 0 ) ; North
side
Inst_7D
TexPolyShading( 32767 0 0 )
TexPoly( a 2 0 0 3 0 8 5 4 8 4 4 0 ) ; East
side
Inst_7D
TexPolyShading( 0 0 -32767 )
TexPoly( a 4 0 0 5 0 8 7 4 8 6 4 0 ) ; South
side
Inst_7D
TexPolyShading( 32767 0 0 )
TexPoly( a 6 0 0 7 0 8 1 4 8 0 4 0 ) ; West side
シミュレータのグラフィックエンジンは、曲面を非常に上手くレンダリングすることができます。適切なコマンドを使って、リゾートホテルに良く見られる円柱状のビルや、円弧の形をしたビルを上手く作ることが出来ます。以下に方法を示します:
最初に、Points()コマンドの別の形をした VecPoints() を使います。 このコマンドは、シミュレータが陰影付け処理を行う際に仕様するベクトルを各点に対応付けます。曲面は平らなポリゴンの連続で構成され、適切な陰影付けにより曲面に見えるのです。円柱の場合、最低でも8つの側面が必要で、私は 16 を好みます。曲面は円弧状です。完全な円柱は 360 度の円弧で、半円は 180 度の円弧です。8面の円柱はそれぞれ 45 度(360/8)のセグメントを持ち、16面の円柱は 22.5度(360/16)のセグメントを持ちます。
実際の点を計算するには、関数電卓が便利です。式は以下の通り:
x = cos(angle) * radius
y = sin(angle) * radius
ビルが 50 メートル(直径)ならば、半径は半分の 25 メートルです。最初に 0 度の x, y 座標を計算し、続いて 22.5, 45, 67.5度, ... と全部の頂点を計算するまで続けます。計算機が "ラジアン" モードではなく "度" モードにセットされているか注意してください。
[注意: これらは極座標であり、角度は極角度です。これは右向きから始まり左回りに 90度で上向き、180度で左向き、270度で下向きです。コンパスに表示される基本方位(0度が北向き, 90度で東向き、,,)と混同しないでください]
高さ236メートル、半径25メートル、16面の円柱の最初の 90 度部分は以下のようになります。
VecPoints( a 0
25 0 0 ; 0 0.0d
25 236 0 ; 1
23 0 10 ; 2 22.5d
23 236 10 ; 3
18 0 18 ; 4 45.0d
18 236 18 ; 5
10 0 23 ; 6 67.5d
10 236 23 ; 7
0 0 25 ; 8 90.0d
0 236 25 ; 9
ここには計算が必要な点しかありません。残りの点は 90, 180, 270 度回転することで得られます。
x, y 座標を入れ替え、符号を適切にセットするだけで済みます。
次の 90 度は:
この円柱を描くとき、ShadedTexPoly 形式のポリゴンコマンドを使います。これはビットマップのオフセットも引数に取ります:
y ビットマップオフセットは単純です: 236/4 です。x オフセットはもう少し複雑です。もっとも簡単なのは円周を側面の数で割ることです。
または:
157.0795 = 2 x 25 x 3.14159
各側面のおおよその長さは以下の通り:
10 = 157/16
この場合、もっとも良い x のオフセットは 5 でした。普通は多少の実験が必要です。
ShadedTexPoly()命令はテクスチャファイル中の帯をインクリメントしません。
そのため、ライト付きの窓はTexPoly() のようには昼夜とおして変化しません。
しかし、陰影は非常にリアルに変化します。この方法の問題は、全ての面がテクスチャファイルの同じセクションを使うので、効果は単一でリアルではありません。これを解決するには、各側面に対してテクスチャファイルの異なるセクションを選ぶことです:
xビットマップオフセットまたはyビットマップオフセット(または両方とも)はランダムに選ばないと理髪店の看板柱効果(barber pole effect)を得ることになるでしょう。最後に、最初のオフセットパラメータは全て偶数(またはすべて奇数)であることに注意してください。これはセクション間の階の位置をそろえるためです。
カスタムビルを作る最も簡単な方法は、Buildingコマンドで生成したものを装飾することです。たとえば、尖った天井を付けたいときは以下のようにします:
しかし、ちょっと気を付けなければならないことがあります。Buildingコマンドで作られたビルはある程度距離が離れると垂直な棒になってしまうのです。カクテルの傘にならないようにするには、幾つか手順を踏む必要があります。装飾の視程を制限するか、Konstantin Kukushkin の最近の報告による変数をセットすることができます:
この命令を RefPoint命令の直後に挿入してください。
Points()リストをBuilding()コマンドの後に置くことにも注意してください。Building()コマンド自身が Points 配列を埋めて、上書きしてしまうからです。
TexPoly や ShadedTexPoly命令で構成されたビルは Preference ダイアログの Textured Building 設定に自動的には対応しません。Textured Building チェックボックスがチェックされないときに単純な面にしたいときは、textured building 変数(342)をテストし、Poly(), ShadedPoly()コマンドで描画しなければなりません。
この記事では、複雑なオブジェクトのデザインに置ける、最も重要で難しい局面を避けてきました: それは描画順序です。
2つのポリゴンが別の場所にあり、同一の点から見えるとき、描画順序を確立しなければなりません。多くの場合、順序は視点の位置により変わります。
2人の人がいて、2つのオブジェクトがその間にあると想像してください。左側の人からは、右のオブジェクトを先に描かねばならず、右側の人からは逆になります。視点の位置を決定するのに VectorJump()コマンドを使います。
ここで、左のオブジェクトが複雑で、特定の順序で描かなければならないとしましょう。垂直方向に複雑で、高さが 10 メートルである場合:
もしオブジェクトを回転させるのなら、RotatedCall(または TransformCall)の後で定義されるかぎり、全てのベクトルを回転しないものとして指定します。
オブジェクトの正確な位置決めには緯度・経度データが必要です。残念ながら、この情報は道路地図や、詳細な都市地図ではめったに得られません。沿岸の都市では NOAA nautical navigation charts から位置情報を得られます。US Army Cops of Engineers は US における航行可能な川のチャートに責任を持っています。両者とも marine chandleries から入手可能です。また、 DeLorme's Map'n'Go V2.0 が非常に有用です。これはカーソル位置の緯度・経度を表示し、US の主要都市の非常に良い詳細を持っています。
-10 0 23 ; 10 112.5d
-10 236 23 ; 11
-18 0 18 ; 12 135.0d
-18 236 18 ; 13
-23 0 10 ; 14 157.5d
-23 236 10 ; 15
-25 0 0 ; 16 180.0d
-25 236 0 ; 17
ShadedTexPoly を使う
Bitmap( side.r8 0 0 0 0
)
Inst_7D
ShadedTexPoly( a 0 0 0 1 0 59 3 5 59 2 5 0 )
circumference = 2 x radius x PI (3.14159)
Bitmap( side.r8 0 0 0 0
)
Inst_7D
ShadedTexPoly( a 0 0 0 1 0 59 3 5 59 2 5 0
)
Inst_7D
ShadedTexPoly( a 0 0 14 1 0 73 3 5 73 2 5 14
)
Inst_7D
ShadedTexPoly( a 2 2 2 3 2 61 5 7 61 4 7 2
)
Inst_7D
ShadedTexPoly( a 4 4 8 5 4 67 7 9 67 6 9 8 )
Part IV: さらなる trick と tips
標準ビルを装飾する
Building( 0 0 0 20 30 30 0 1F )
Points( 0
-15 80 15 ; 0
15 80 15 ; 1
15 80 -15 ; 2
-15 80 -15 ; 3
0 90 0 ; 4
)
SurfaceColor( B F0 )
Poly( a 0 1 4 )
Poly( a 1 2 4 )
Poly( a 2 3 4 )
Poly( a 3 0 4 )
Return
SetVar( 33B 0 )
"Textured Building" 設定に対応する
描画順序という言葉について
VectorJump( :LeftofCenter 32767 0 0 0
)
:RightofCenter
Call( :LeftObject )
Call( :RightObject
)
Return
:LeftofCenter
Call( :RightObject )
Call( :LeftObject )
Return
:LeftObject
VectorJump( :BelowLeftObject 0 32767 0 10
)
:AboveLeftObject
Call( :DrawLeftObject )
Call( :DrawLeftRoof
)
Return
:BelowLeftObject
Call( :DrawLeftRoof )
Call( :DrawLeftObject )
Return
緯度と経度データ
Last updated 14 August 1996 by Gene
Kraybill. All rights reserved.
日本語訳: 村上 卓弥