チュートリアル 7 : ファサード モデリング
チュートリアル データ
チュートリアル データは、[Help] メニュー → [Download Tutorials and Examples…] を選択し、[CityEngine Tutorial] からダウンロードできます。
概要
このチュートリアルでは、ファサード構造の作成、アセットの挿入、建物へのテクスチャの追加など、写真から建物をモデリングする方法を学習します。また、複雑な CGA のテクニックについても学習します。

Part 1 :ファサードの構造をモデリング
ファサード モデリング
以下のワークフローでは、実際の写真からファサードを再作成するための CGA ルール セットを記述する方法を示します

このセッションでは、CGA ルールでファサードの基本構造を作成します。ルール セットの拡張を進めながら、写真をより詳細に分析し、CGA ルールでプリモデルされたアセットをどのように使用できるかを学習します。
ルール ファイルの作成
ルール ファイルを作成するために、以下の手順を行います。
- [Navigator] ウィンドウ で Tutorial_07_Facade_Modeling フォルダーを展開します。
- scenes フォルダー の FacadeModeling_01.cej シーンを開きます。
- [File] メニュー → [New] → [CityEngine] → [CGA Rule File] をクリックして、新規ルール ファイルを作成します。
- [Next] をクリックします。
- ルール名を「facade_01.cga」と入力します。
- [Finish] をクリックします。
新しい CGA ルール ファイルが作成され、[CGA Editor] ウィンドウが起動します。CityEngine の現在のバージョンの記述以外は空の状態です。
ボリュームとファサード
これから建物の作成を始めます。まず押し出し操作によりマス モデルを作成します。建物の height 属性を使用します。
- ルール ファイルの最初に height 属性を追加します。
attr height = 24- スタート ルールを extrude 操作を使用して記述し、その結果の形状に Building と名前を付けます。
Lot --> extrude(height)
Building- ファサードのみが必要なので、Building ルールで component split を使用して正面を除くすべての面を削除し、Frontfacade ルールを呼び出します。
Building -->
comp(f) { front : Frontfacade }フロアの追加
上記のファサードの写真を見ると、以下の画像のように、異なるタイプのフロアを分析することができます

- はじめに高さと床寸法についての属性を定義していきます。
attr groundfloor_height = 5.5
attr floor_height = 4.5- Frontfacade ルールを Building ルールの下に追加します。
Frontfacade -->
split(y) { groundfloor_height : Floor(split.index) // 地上フロア
| floor_height : Floor(split.index) // 第一フロア (二階)
| floor_height : Floor(split.index) // 第二フロア (三階)
| { ~floor_height : Floor(split.index) }* // 中間階
| floor_height : Floor(999) // 最上階、インデックスは999
| 0.5 : s('1, '1, 0.3) LedgeAsset } // 屋根直下のトップレッジ前面のファサードは水平方向に分割されて、各フロアに floor_height (フロアの高さ) の属性が設定されます。Floor 形状はフロアのインデックスである split.index によってパラメータで制御されます。このパラメータはサブ ルールに渡され、特定のフロアに対して何のエレメントを作成するかを決定します。
最上階の場合、フロア インデックスは 999 に設定されます。これにより、このフロアを識別することができます。また、中層階は繰り返し分割されているため、建物は異なる高さに動的に適応し、中層階で残りの垂直スペースを埋めることができます。
なお、[CGA Editor] ウィンドウには、未定義の Floor ルールと LedgeAsset ルールに対する警告が表示されます。チュートリアルの後半で、このルールを参照するため問題ありません。
Ctrl + S キーを押し、ルールを保存します。
[Navigator] ウィンドウの facade_01.cga ルールを [3D View] ウィンドウの区画の上にドラッグします。 これによって、はじめてファサードが生成されます。

Z キーを押すと、ファサードの正面に移動できます。
ルールを割り当てて別の方法でモデルを生成するには、[Inspector] ウィンドウで [Assign] をクリックし、facade_01.cga ルールを選択して [Generate models of selected shapes] ボタンをクリックします (Ctrl+G キーを押します)。
フロア レッジ (水平方向の張り出し) の追加
現在、フロアはレッジとタイルの形状に分割されています。

- floorindex パラメータを持つ Floor ルールを追加します。
Floor(floorindex) -->
case floorindex == 0 :
Subfloor(floorindex)
case floorindex == 2 :
split(y) { ~1 : Subfloor(floorindex)
| 0.5 : TopLedge }
else :
split(y) { 1 : BottomLedge(floorindex)
| ~1 : Subfloor(floorindex)
| 0.5 : TopLedge }フロア インデックスは、異なるフロアの特定のレッジを処理するために使用します。
地上階 (floorindex 0) にはレッジはないため、タイルのみを呼び出します。
二番目のフロア (Floor 2) については、窓領域がフロアの一番下の高さから開始されるため、ボトム レッジはありません。このフロアのバルコニーは後のステップで作成します。
それ以外のフロアにはボトム レッジ、タイルおよびトップ レッジ領域があります。
- ルール ファイルを保存し、モデルを生成します。

サブフロアの追加
サブフロアは各フロアの左右端に位置する小さな壁領域とそれらの間の繰り返しタイルで構成されています。

- ルール ファイルの先頭に他の属性と一緒に以下の属性を追加します。
attr tile_width = 3.1- Subfloor ルールをルール ファイルの一番下に追加します。
Subfloor(floorindex) -->
split(x){ 0.5 : Wall(1)
| { ~tile_width : Tile(floorindex) }*
| 0.5 : Wall(1) }これにより、フロアが繰り返しのタイルと両側の壁に水平に分割されます。
- 他の属性の次に wallcolor 属性を追加します。
attr wallColor = "#ffffff"- 続いて、ルール ファイルの一番下に walltype パラメータを持つ Wall ルールを追加します。
Wall(walltype) -->
case walltype == 1 :
color(wallColor)
case walltype == 2 :
color(wallColor)
else :
color(wallColor)パラメータ化された Wall 形状を追加しました。これは後のステップでファサードにテクスチャを貼り付ける際に重要です。ファサードの写真を見ると、3 つの異なる壁のタイプがあることが分かります。
暗いブロックのダート テクスチャ
明るいブロックのダート テクスチャ
ダート テクスチャのみ。これは主にブロック構造を持たないファサード アセットに対して必要となります。
- ルール ファイルを保存し、モデルを生成します。

上記の Wall ルールの壁スタイルは、同一の出力を生成します。前述したように、後のステップで壁のタイプごとに異なるテクスチャを追加することで変更されます。
タイルの追加
このファサードのタイルは均質になっています。ここで地上フロアのタイルとそれより上の階のタイルを区別する必要があります。

- door_width 属性と window_width 属性を使用して異なる分割サイズを設定します。
attr door_width = 2.1
attr window_width = 1.4- Subfloor ルールの後に Tile ルールを追加します。
Tile(floorindex) -->
case floorindex == 0 :
split(x){ ~1 : SolidWall
| door_width : DoorTile
| ~1 : SolidWall }
else :
split(x){ ~1 : Wall(getWalltype(floorindex))
| window_width : WindowTile(floorindex)
| ~1 : Wall(getWalltype(floorindex)) }地上フロアのタイルでは、Wall 形状の代わりに SolidWall 形状が追加されます。これは、地上フロアのドアがファサードからめり込んだ状態になっているために必要になります。ドアと壁の間に穴ができるのを防ぐために、特定の厚さを持った立体を挿入することにより、壁エレメントを作ります。この厚さは後の Door ルールでも使用するため、これを定数変数 wall_inset として定義します。
複数回使用される値を宣言しておくと、同じ値が別のルールで使用されることを確認できることにもなり、便利です。
- 属性と Lot ルールの間に wall_inset const を追加します。
const wall_inset = 0.4- SolidWall ルールを Wall ルールの下に追加します。
SolidWall -->
s('1, '1, wall_inset)
t(0, 0, -wall_inset)
i("builtin:cube:notex")
Wall(1)- Wall ルールの上に関数を宣言して、フロア インデックスから壁のタイプを取得します。
getWalltype(floorindex) =
case floorindex == 0 : 1
case floorindex == 1 : 1
else : 2ファサードの写真を見ると、地上フロアおよび一番目のフロア (二階) は暗いテクスチャ、それ以外には明るいテクスチャとなっているのが分かります。getWallstyle 関数はフロア インデックスを対応する壁のタイプに割り当てます。
- ルール ファイルを保存し、モデルを生成します。

FacadeModeling_02.cej シーンと facade_02.cga ルール ファイルを開いて、この時点でシーンとルールがどのようになっているか確認できます。
Part 2 :ファサード アセットの挿入
次にファサードで事前にモデル化されたアセットを使用する方法を学習します。
アセット
現在モデリングしているファサードの写真を見ると、以下の項目についてアセットが必要であることが分かります。
窓: 窓エレメントとして使用
丸い窓上部: 窓上部の装飾
三角の窓上部: 窓上部の装飾
半円弧: 地上フロアのアーチとして使用
レッジ: すべてのレッジとして使用
モディリオン: 窓や地上フロアのアーチの装飾として使用

これらのアセットはすでにチュートリアル プロジェクトの asset フォルダーに含まれています。これらのアセットをプレビューするには、[Navigator] ウィンドウで目的のアセットを選択して右クリックし、[File Preview] を選択します。

以下の行をルール ファイルの属性の宣言の下にアセットへの参照を追加します。
const window_asset = "facades/elem.window.frame.obj"
const round_wintop_asset = "facades/round_windowtop.obj"
const tri_wintop_asset = "facades/triangle_windowtop.obj"
const halfarc_asset = "facades/arc_thin.obj"
const ledge_asset =
"facades/ledge.03.twopart_lessprojection.obj"
const modillion_asset =
"facades/ledge_modillion.03.for_cornice_ledge_closed.lod0.obj"窓の追加
窓を追加をするために以下の手順を行います。
- Window asset を正確に配置するためのルールが準備できました。Tile ルールの後に WindowTile ルールを追加して、Window 形状を呼び出します。
WindowTile(floorindex) -->
Window- そして次の Window ルールを追加して、window asset とその背後のガラス面をサイズ調整、配置、挿入します。
Window -->
s('1,'1,0.2) t(0,0,-0.2)
t(0,0,0.02)
[ i(window_asset) Wall(0) ]
Glass- ルール ファイルを保存し、モデルを生成します。

窓の装飾の追加
ファサードの写真をもう一度見みると、フロアによって異なる窓 (または窓のエレメント) があることに気づきます。

- WindowTile ルールを拡張し、フロア インデックスに固有の形状を以下のようにトリガーします。
WindowTile(floorindex) -->
case floorindex == 1 || floorindex == 999 :
Window
case floorindex == 2 :
Window
t(0, '1, 0)
WindowOrnamentRound
else :
Window
WindowLedge
t(0, '1, 0)
WindowOrnamentTriangle第一フロア (二階) と最上階には特別な装飾はないため、Window 形状のみが呼び出されます。
第二フロア (三階) には新しい形状 WindowOrnamentRound を追加します。このエレメントは窓の上の境界線に配置されるため、現在のスコープを y 軸方向に '1 移動します。
他の窓タイル (中間階) には、WindowLedge 形状と WindowOrnamentTriangle 装飾が追加されます。
最終的なアセットを直接使用せずに、最初に代用となる立方体を挿入します。 実際のアセットのサイズをより設定し易くなります。この場合、組み込みの立方体 アセットを使用できます。
- WindowTile ルールの後に以下のルールを追加して、サイズを設定し、X 軸でスコープをセンタリングします。立方体を挿入して、見やすくするために色をつけ、代用となる立法体を作成します。
WindowOrnamentTriangle -->
s('1.7, 1.2, 0.3)
center(x)
i("builtin:cube")
color("#ff0000")
WindowOrnamentRound -->
s('1.7, 1.2, 0.4)
center(x)
i("builtin:cube")
color("#00ff00")
WindowLedge -->
s('1.5, 0.2, 0.1)
t(0, -0.2, 0)
center(x)
i("builtin:cube")
color("#0000ff")- ルール ファイルを保存し、モデルを生成します。


代用となる立方体を実際のアセットに交換
代用となる立方体を実際のアセットと交換するために、以下の手順を実行します。
- 窓の装飾のサイズは妥当なようなので、立方体の代わりにアセットを挿入し、(WindowLedge については立方体のまま) 色を各ルールの Wall 形状の呼び出しに置き換えます。
WindowOrnamentTriangle -->
s('1.7, 1.2, 0.3)
center(x)
i(tri_wintop_asset)
Wall(0)
WindowOrnamentRound -->
s('1.7, 1.2, 0.4)
center(x)
i(round_wintop_asset)
Wall(0)
WindowLedge -->
s('1.5, 0.2, 0.1)
t(0, -0.2, 0)
center(x)
i("builtin:cube")
Wall(0)- ルール ファイルを保存し、モデルを適用します。


- 丸い窓の装飾には、第二フロアの側面の柱がないため、分割操作で WindowOrnamentRound ルールを拡張します。これにより、以下のモディリオン アセット用のスコープが準備されます。
WindowOrnamentRound -->
s('1.7, 1.2, 0.4)
center(x)
i(round_wintop_asset)
Wall(0)
split(x) { ~1 : WindowMod
| window_width : NIL
| ~1 : WindowMod }- WindowOrnamentRound ルールの後に WindowMod ルールを追加します。サイズはモディリオンを挿入する前に設定されます。
WindowMod -->
s(0.2, '1.3, '0.6)
t(0, '-1, 0)
center(x)
i(modillion_asset)
Wall(0)y 方向に相対的な負の移動 ('-1) を適用すると、アセットの上面が装飾の下面に揃えられることに注意してください。
5. ルール ファイルを保存し、モデルを生成します。

ドアの追加
ドア タイルは垂直方向に分割されて、ドア、アーチおよび上部エリアに分割されます。

続いて、以下のルールを Window ルールの下に追加します。
- 楕円形のアーチにならないようにするために、アーチ部の高さはドア (現在の x スコープ) の幅の半分にする必要があります。
DoorTile -->
split(y) { ~1 : Door
| scope.sx/2 : Arcs
| 0.5 : Arctop }- ドアの上部エリアでは、壁のエレメントとその上に重なったモディリオン アセットが挿入されます。
Arctop -->
Wall(1)
s(0.5, '1, 0.3)
center(x)
i(modillion_asset)
Wall(1)- アーチ エリアはさらに分割され、2 つのアーチ アセットが挿入されます。インセットに対して事前に定義した変数 wall_inset を使用します。また、アーチの右半分を回転して正しい向きにする必要があります。
Arcs -->
s('1, '1, wall_inset)
t(0, 0, -wall_inset)
Doortop
i("builtin:cube")
split(x) { ~1 : ArcAsset
| ~1 : r(scopeCenter,0,0,-90) ArcAsset }- 実際のアーチ アセットを ArcAsset ルールに挿入し、Doortop ルールと Door ルールに Wall タイプを設定します。
ArcAsset -->
i(halfarc_asset)
Wall(1)
Doortop -->
Wall(0)
Door -->
t(0,0,-wall_inset)
Wall(0)Door ルールでは、ドアは壁からセット バックしています。
5. ルール ファイルを保存し、モデルを生成します。

レッジの追加
トップ レッジにはシンプルな壁のストライプを使用し、ボトム レッジにはレッジ アセットを挿入して他のフロアとの区別がつくようにする必要があります。
- トップとボトムのレッジにルールを追加します。
TopLedge -->
WallStripe
BottomLedge(floorindex) -->
case floorindex == 1 :
split(y) { ~1 : Wall(0)
| ~1 : s('1, '1, 0.2) LedgeAsset }
case floorindex == 999 :
split(y) { ~1 : WallStripe
| ~1 : s('1, '1, 0.2) LedgeAsset }
else : WallStripe
WallStripe -->
split(x) { 0.5 : Wall(1)
| ~1 : Wall(2)
| 0.5 : Wall(1) }
LedgeAsset -->
i(ledge_asset)
Wall(0)- ルール ファイルを保存し、モデルを生成します。


バルコニーの追加
今度は、バルコニーの作成をしていきます。
- Floor ルールを編集し、Balcony 形状を case floorindex == 2 : に追加します。
case floorindex == 2 :
split(y) { ~1 : Subfloor(floorindex) Balcony
| 0.5 : TopLedge }- LedgeAsset ルールの後に Balcony ルールを追加し、バルコニーの配置とサイズを確保するために、色を追加した単純な代用の立方体を作成します。
Balcony -->
s('1, 2, 1)
t(0, -0.3, 0)
i("builtin:cube")
color("#99ff55")- ルール ファイルを保存し、モデルを生成します。

- 以下の図のように、バルコニー ボックスを 3 つの要素に分割します。:梁 (Beams)、床 (Floor)、手すり (Railing)

a. バルコニーを BalconyBeams、BalconyFloor、および RailingBox エレメントに分割して、Balcony ルールの緑色を置き換えます。
Balcony -->
s('1, 2, 1)
t(0, -0.3, 0)
i("builtin:cube")
split(y) { 0.2 : BalconyBeams
| 0.3 : BalconyFloor
| 1 : RailingBox }b. ルール ファイルを保存し、モデルを生成します。

- 繰り返し分割してバルコニーを支える梁を作成します。
BalconyBeams -->
split(x) { ~0.4 : s(0.2, '1, '0.9) center(x) Wall(0) }*BalconyFloor 形状は Wall ルールのみを定義します。
BalconyFloor --> Wall(0)- RailingBox ルールに対して component split を使用し、バルコニーの手すりとして使用する面を抽出します。
RailingBox -->
comp(f) { front : Rail | left : Rail | right : Rail }- バルコニー ボックスのサイズを設定するには、立方体を挿入してバルコニー レールを作成します。
Rail -->
s('1.1, '1, 0.1)
t(0, 0, -0.1)
center(x)
i("builtin:cube")
Wall(0)- ルール ファイルを保存し、モデルを生成します。


これで、ジオメトリ アセットが挿入された最終モデルが完成しました。ルールを様々な区画に適用したり、[Inspector] ウィンドウにあるユーザー属性を変更してファサードのデザインを変えることができます。
最終結果については、FacadeModeling_03.cej シーンと facade_03.cga ルールを開くことで確認できます。
次のセクションでは、ファサードにテクスチャを適用する方法を学習します。
Part 3 :ファサードのテクスチャを作成
次に、ファサードにテクスチャを適用します。
テクスチャ アセットの作成
テクスチャ アセットを作成するには、以下の手順を実行します。
- アセットを定義した後に、ルール ファイルの先頭に使用するテクスチャを追加します。
const wall_tex = "facades/textures/brickwall.jpg"
const wall2_tex = "facades/textures/brickwall_bright.jpg"
const dirt_tex = "facades/textures/dirtmap.15.tif"
const doortop_tex = "facades/textures/doortoptex.jpg"- 窓とドアのテクスチャについては、それぞれのアセット フォルダーからランダムなテクスチャ文字列を取得する関数を定義することでテクスチャを個別にリストする必要がなくなります。テクスチャの後に以下の行を追加します。
randomWindowTex = fileRandom("*facades/textures/window.*.jpg")
randomDoorTex = fileRandom("*facades/textures/doortex.*.jpg")グローバル UV 座標の設定
CGA を使用したテクスチャリングは、以下の 3 つの手順で行われます。
setupProjection () - UV 座標空間を定義します。
set (material.map) またはtexture () - テクスチャ ファイルを設定します。
projectUV () - UV 座標を適用します。
テクスチャ レイヤーの追加
レンガのテクスチャとダート マップという 2 つのテクスチャ レイヤーをファサードに追加します。ファサード全体で一貫したテクスチャ座標を維持するには、ファサード ルールに UV 設定を追加する必要があります。テクスチャ設定を事前にテストするために、新しい中間的なルール FrontfacadeTex を追加します。
- Building ルールを以下のように変更します。
Building -->
comp(f) { front : FrontfacadeTex }- Building ルールの後に新しい FrontfacadeTex ルールを作成します。
FrontfacadeTex -->
setupProjection(0, scope.xy, 2.25, 1.5, 0, 0, 1)
texture("builtin:uvtest.png")
projectUV(0)setupProjection (0,scope.xy,2.25,1.5,0,0,1) は、テクスチャ チャネル 0 (カラー チャネル) のテクスチャ座標を定義します。UV 座標はスコープの x、y 平面に沿って投影され、x 方向には 2.25 単位ごと、y 方向には 1.5 単位ごとに繰り返されます。texture () 操作は set (material.map) のショートカットです。この場合、カラー マップを builtin:uvtest.png に設定します。これは、UV 座標をすばやく確認するためのテクスチャです。最後に、チャンネル 0 の UV 座標をベイクし、UV 座標を適用します。
- ルール ファイルを保存しファサードを生成して、 UV 設定を確認します。

- ダート チャンネルの UV セットアップを追加します。
FrontfacadeTex -->
setupProjection(0, scope.xy, 2.25, 1.5, 0, 0, 1)
texture("builtin:uvtest.png")
projectUV(0)
setupProjection(2, scope.xy, '1, '1)
set(material.dirtmap, ("builtin:uvtest.png"))
projectUV(2)このテクスチャはファサード全体に広がる必要があるため、ファサードの寸法である UV 設定には相対演算子 ‘1 と ‘1 を使用します。
- ルール ファイルを再度保存して、生成します。

- ファサードがテクスチャでどのように見えるかを確認するために、builtin:uvtest.png テクスチャを実際のテクスチャと交換します。
FrontfacadeTex -->
setupProjection(0, scope.xy, 2.25, 1.5, 0, 0, 1)
texture(wall_tex)
projectUV(0)
setupProjection(2, scope.xy, '1, '1)
set(material.dirtmap, dirt_tex)
projectUV(2)
UV 座標はファサードに適しています。
- 建物の場合、この時点では UV のセットアップのみが必要なため、FrontfacadeTex ルールを以下のように変更します。
FrontfacadeTex -->
setupProjection(0, scope.xy, 2.25, 1.5, 0, 0, 1)
setupProjection(2, scope.xy, '1, '1)
FrontfacadeFrontfacade ルールでは、後続のエレメントに対して UV 座標が正しく設定されるようになりました。
詳細については、Texturing: Essential knowledge の CGA reference を参照してください。
壁にテクスチャを貼り付ける
ワークフローの前半で、walltype パラメータを Wall ルールに追加しました。これを使用して、壁のタイプごとに異なるテクスチャを割り当てます。
- Wall ルールを探して以下のように変更します。
Wall(walltype) -->
// dark bricks with dirt
case walltype == 1 :
color(wallColor)
texture(wall_tex)
set(material.dirtmap, dirt_tex)
projectUV(0) projectUV(2)
// bright bricks with dirt
case walltype == 2 :
color(wallColor)
texture(wall2_tex)
set(material.dirtmap, dirt_tex)
projectUV(0) projectUV(2)
// dirt only
else :
color(wallColor)
set(material.dirtmap, dirt_tex)
projectUV(2)- ルール ファイルを保存してモデルを再生します。

すべての壁エレメントは、いずれかのタイプの壁でテクスチャされます。
窓アセットのテクスチャを設定する
窓アセットの場合、一連の窓テクスチャを使用してガラス板に色を付けるため、ガラス形状全体にわたるように UV 座標を設定する必要があります。これを行うには、x 方向と y 方向の両方に ‘1 を使用します。テクスチャ操作では、前に定義した randomWindowTex 関数を呼び出すことによって、ランダムなガラスのテクスチャが選択されます。
- Window ルールの後に Glass ルールを追加します。
Glass -->
setupProjection(0, scope.xy, '1, '1)
projectUV(0)
texture(randomWindowTex)- ルール ファイルを保存して、モデルを生成します。

- 次に、ガラスに鏡面光沢を追加します。
Glass -->
setupProjection(0, scope.xy, '1, '1)
projectUV(0)
texture(randomWindowTex)
set(material.specular.r, 1)
set(material.specular.g, 1)
set(material.specular.b, 1)
set(material.shininess, 4)- ルール ファイルを保存してモデルを生成します。

ドア形状にテクスチャを貼り付ける
ドア面は窓ガラスと同じテクスチャになっています。Doortop ルールと Door ルールを以下のように置き換えます。
Doortop -->
setupProjection(0, scope.xy, '1, '1)
texture(doortop_tex)
projectUV(0)
Door -->
t(0, 0, -wall_inset)
setupProjection(0, scope.xy, '1, '1)
texture(randomDoorTex)
projectUV(0)
FacadeModeling_04.cej シーンと facade_04.cga ルールを開いて、最終結果を確認します。
このチュートリアルでは、以下の方法を学習しました。
- ファサードの構造をモデル化
- 窓、ドア、レッジなどのアセットを挿入
- 壁、窓、ドアにテクスチャを適用
CGA 形状文法の詳細については、 Rule-based modeling tutorial、および Rule-based modeling と CGA modeling のヘルプ トピックを参照してください。