チュートリアル データは、[Help] メニュー → [Download Tutorials and Examples…] を選択し、[CityEngine Tutorial] からダウンロードできます。
本チュートリアルでは、シェープグラマー、およびマスモデリングについて学習します。
演習 |
---|
・Part 1 : L 字型およびU字型シェープ |
・Part 2 : 再帰を使用したマスモデリング |
・Part 3 : セットバックによる区画の調整 |
・Part 4 : マスモデルとセットバックの組み合わせ |
・Part 5 : テクスチャ付きファサードの追加 |
このチュートリアルでは、建物のマスモデルがどのようにシェープ グラマーにより作成されるのかを説明します。L 字型や U 字型マスのような典型的な建築物の立体シェープを作成します。
新しい CGA ファイルが作成され、[CGA Rule Editor] ウィンドウが開きます。
まずはとてもシンプルな L 字型の生成から始めます。以下のルールを記述し、保存します。
attr height = rand(30, 60)
attr wingWidth = rand(10, 20)
Lot --> LShape
LShape -->
shapeL(wingWidth, wingWidth) { shape : LFootprint }
LFootprint --> extrude(height) Mass
LotInner --> OpenSpace
shapeL コマンドは、サイズが 10 から 20 の範囲で L 字型のフットプリントを作成します。そして二番目のルール LFootprint は、height 値まで L 字型を立ち上げます。LotInner ではシンプルに OpenSpace を適用し、区画シェープをそのまま維持します。
属性は @Group や @Range のようなオプションのアノテーションを持つことができ、これにより [Inspector] ウィンドウでの属性の表示を制御します。CGA アノテーションの詳細については、[Help] メニュー → [CityEngine Help] の CGA Rule Referenceを参照してください。
区画にルールを適用します。
建物を生成します。
L 字型マスモデルはこれで良いように見えますが、単調であまり現実的なものとは言えません。もっと変化をつける必要があります。
現在の L 字型のサイドウィングは常に区画全体の左側のみに位置していますが、rotateScope を使用すれば、L 字型を右側にも配置することができます。LShape ルールの赤色の行を確率オペレーター % を使用して以下のように変更し、L 字型がその左側か右側どちらかにサイドウィングを持つように改善します。
LShape -->
50% : shapeL(wingWidth, wingWidth) { shape : LFootprint }
else : rotateScope(0, 90, 0)
shapeL(wingWidth, wingWidth) { shape : LFootprint }
convexify コマンドを使用することにより、L 字型を両ウィングに分割し、これらの高さを変化させることができます。ここでも変化をつけるためにランダム確率を使用します。LFootprint ルールも以下のように変更します。
LShape -->
50% : shapeL(wingWidth, wingWidth) { shape : LFootprint }
else : rotateScope(0, 90, 0)
shapeL(wingWidth, wingWidth) { shape : LFootprint }
U 字型のシェープを追加します。スタートの Lot ルールで、先ほどの LShape の代わりに UShape を呼び出します。
Lot --> UShape
同様に、shapeU コマンドを使用します。
UShape -->
shapeU(wingWidth, wingWidth * 0.7, wingWidth * 0.7){ shape : UFootprint }
UFootprint --> extrude(height) Mass
そして以下のように変更し、変化もつけます。
UShape -->
80% : rotateScope(0, 180, 0) shapeU(wingWidth, wingWidth * 0.7,
wingWidth * 0.7) { shape : UFootprint }
else: shapeU(wingWidth, wingWidth * 0.7, wingWidth * 0.7)
{ shape : UFootprint }
結果画像の中の建物を見ると、すべての区画で U 字型になっているわけではないことが分かります。次にこれを修正します。
この高さの分布はあまり現実的ではありません。建物の高さをより良く制御するために、[height] 属性に対して条件を与えます。つまり、面積の大きな区画のみが高い建物になるようにします。[height] 属性の定義を以下のように変更します。
attr height =
case geometry.area < 1000: rand(20, 50)
else: rand(50, 150)
どの区画にどの形状が作成されるかを制御するための新しいルール LUShapes を追加します。U 字型は奥行よりも幅の方が長いシェープに適しています。CGA 言語で言えば、scope.sx が scope.sy よりも大きい場合です。これ以外の場合は L 字型を生成するようにします。Lot ルールを以下のように変更します。
Lot --> LUShape
また、以下のルールを追加します。
LUShapes -->
case scope.sx > scope.sz :
60% : UShape
else : LShape
else: LShape
矩形でない区画では U 字型も L 字型も適していません。次の case 文では、およそ矩形 (許容値15°) の区画においてのみ U 字型および L 字型が作成されることを条件付けします。この条件を満たさない場合は新しいフットプリント ルールを呼び出します。以下のように変更します。
LUShapes -->
case geometry.isRectangular(15):
case scope.sx > scope.sz :
60% :UShape
else : LShape
else: LShape
else: BasicFootprint
これにより押し出された区画シェープは、L 字型や U 字型に比べて大き過ぎてしまいます。そこで、BasicFootprint に対してマイナスのオフセットを追加します。これにより、各建物の間にいくらかスペースを作ることにもなります。
BasicFootprint --> offset(-5,inside) extrude(height) Mass
続いての Part 2 では、シェープグラマーで再帰を使用してマスモデリングを行う方法を学習します。
本チュートリアルでは、シェープ グラマーの中で再帰を使用することにより建物要素の繰り返しをモデリングする方法を学習します。 Part 1 からの続きまたは、シーン01_MassModeling.cej を開きます。
height 属性は建物の高さとしてランダム値を生成します。スタートルール Lot は Envelope を呼び出し、これがフットプリントをタワーの包絡面 (エンベロープ) まで押し出します。Envelope は Recursion ルールを呼び出します。
height =
case geometry.area > 1000: rand(50, 200)
else: rand(20, 50)
Lot --> Tower
Tower --> extrude(height) Envelope
Envelope --> RecursiveSetbacks
この後の再帰ルールのために、2 つの変数を追加する必要があります。lowHeight と scale です。後者は 1 つの建物に対して一定値となるので、属性として定義します。
// これら 2 つの値の間で切り替えることにより、視覚的にアピールするセットバックを作成:
lowHeight = 50%: 0.4 else: 0.6
// 必ず定数:
attr scale = rand(0.75, 0.9)
RecursiveSetbacks ルールは、マスモデルが 2 階分の高さよりも高ければマスを分割し、相対的高さ lowHeight を持った下の部分が Mass となります。残りの部分は Setback シェープを生成します。RecursiveSetbacks シェープの高さが 2 階分よりも低い場合は、残りの部分の高さは floorheight に設定され、Mass シェープが生成されます。
attr floorheight = rand(4, 5)
RecursiveSetbacks -->
case scope.sy > 2 * floorheight :
split(y){ 'lowHeight : Mass | ~1: Setback }
else:
s('1, floorheight, '1) Mass
Setback ルールはシェープを拡大縮小および移動し、再帰的に RecursiveSetbacks ルールを呼び出します。
Setback -->
s('scale, '1, 'scale) center(xz) RecursiveSetbacks
区画にルールを適用します。
外部のラウンド (円筒) アセットを使用すれば、非常に簡単に先ほどの再帰タワーの円筒バージョンを作成することができます。Tower ルールを以下のように変更します。
Tower --> extrude(height) Envelope
Envelope -->
case geometry.isRectangular(20):
20% : i("cyl.obj") RecursiveSetbacks
else: RecursiveSetbacks
else: RecursiveSetbacks
タワー全体の 20 % について、シェープで生成される元々の立方体の代わりに円筒アセットを挿入します。
次の Part 3 ではセットバックにより区画内を変更する方法を学習します。
本パートでは区画のシェープに対してセットバックを適用します。
シーン Tutorial_08_Mass_Modeling/scenes/MassModeling_01.cej を開きます。
Parcel ルールは区画のすべての道路側の辺にセットバックを適用し、このエリアを OpenSpace ルールに転送します。道路側から離れた区画内部は Footprint に転送され、ランダムな高さに押し出します。
attr height =
case geometry.area > 1000: rand(50, 200)
else: rand(20, 50)
attr distanceStreet =
20%: 0
else: rand(3, 6)
Lot --> Parcel
LotInner --> OpenSpace
Parcel -->
setback(distanceStreet)
{ street.front: OpenSpace
| remainder: Footprint }
Footprint --> extrude(height)
OpenSpace --> color("#77ff77")
street.front セレクターは streetWidth シェープのオブジェクト属性をチェックします。この属性は、ブロックから作成された区画に対して自動的に設定されているもので、手動で作成されたシェープには存在しません。
ここでは同様のセットバックを建物間の距離を制御するために追加します。以下に示すように、属性 distanceBuildings を追加し、Parcel ルールを変更し、新しいルール SubParcel を追加します。
attr distanceBuildings =
30%: 0
else: rand(4, 8)
Parcel -->
setback(distanceStreet)
{ street.front: OpenSpace
| remainder: SubParcel }
SubParcel -->
setback(distanceBuildings / 2)
{ street.back: OpenSpace
| remainder: Footprint }
SubParcel では再度セットバックが適用されますが、今回は道路ではない側の辺になります。
次の Part 4 では、Part 1 と Part 2 で作成したマスモデルをセットバックした区画と結合します。
ここでは、Part 1 から 3 の結果を組み合わせます。シーン Tutorial_08_Mass_Modeling/scenes/01_MassModeling.cej を開きます。
ルール ファイル massmodeling_03.cga を開き、 myMass_04.cga として保存します。
import lushapes : "massmodeling_01.cga"
import towers : "massmodeling_02.cga"
Footprint -->
case geometry.isRectangular(15):
25% : towers.Tower
else : lushapes.LUShape
else:
25%: towers.Tower
else : offset(-5,inside) lushapes.BasicFootprint
次の Part 5 では、テクスチャ付けしたファサードを追加します。
ここまでに作成したマスモデルにシンプルなテクスチャ付きファサードを追加する方法を学習します。 シーン Tutorial_08_Mass_Modeling/scenes/01_MassModeling.cej を開きます。
ルール ファイル massmodeling_04.cga を開き、myMass_05.cga として保存します。 これまでに作成したマスモデルにシンプルなテクスチャ付きファサードを追加したいと思います。12 個のファサード テクスチャ タイルの中からランダムに 1 つを選択する関数が必要になります。
const randomFacadeTexture = fileRandom("*facade_textures/f*.tif")
テクスチャ タイルをファサードに正しくマッピングするために、実際のフロアの高さとタイルの幅を計算する 2 つの関数を定義します。これら 2 つの関数により、テクスチャのないタイルがファサードのエッジで確実に切り落とされるようになります。
attr floorheight = rand(4,5)
actualFloorHeight =
case scope.sy >= floorheight : scope.sy/rint(scope.sy/floorheight)
else : scope.sy
actualTileWidth =
case scope.sx >= 2 : scope.sx/rint(scope.sx/4)
else : scope.sx
要素分割コマンド (comp) により、マスモデルのファサード要素を取得します。
Mass -->
comp(f){ side: Facade | top: Roof. }
ここで、インポートされているルールにこの Mass ルールを使用するように指示します。
towers.Mass --> Mass
lushapes.Mass --> Mass
最後に、ファサードに対して UV 座標を設定し、randomFacadeTexture 関数によりテクスチャ ファイルを定義し、UV を投影します。
Facade -->
setupProjection(0, scope.xy, 8*actualTileWidth, 8*actualFloorHeight)
texture(randomFacadeTexture)
projectUV(0)
建物を生成します。