content/hifi-public/alan/WC/rules/International City.cga
Dale Glass 0d14e5a379 Initial data.
Needs a lot of cleanup. Data has been de-duplicated, and where identical copies existed, one of them
has been replaced with a symlink.

Some files have been excluded, such as binaries, installers and debug dumps. Some of that may still
be present.
2022-02-13 18:59:11 +01:00

666 lines
26 KiB
Text

/**
* File: International City.cga
* Created: 6 Nov 2013
* Updated: 11 April 2014
* Author: Esri R&D Center Zurich
*/
version "2014.0"
#
# City Wizard Example Rule
#
# Notes:
# - since city wizard examples have to run on arbitrary lot sizes, lots might be subdivided further in the grammar
# - the different building types are depending on the distance to origin (usually this is controlled via landuse maps etc)
#
import Street_Modern_Standard: "/ESRI.lib/rules/Streets/Street_Modern_Standard.cga"
@Hidden
import Facade_Textures : "/ESRI.lib/rules/Facades/Facade_Textures.cga" () # completely controlled in rules below
@Hidden
import Roof_Textures : "/ESRI.lib/rules/Roofs/Roof_Textures.cga" () # completely controlled in rules below
@Hidden
import Plant_Loader : "/ESRI.lib/rules/Plants/Plant_Loader.cga" () # completely controlled in rules below
######################################################
# control attributes (set by user or mapped)
#
@Group("Building",1)
@Order(1) @Range("Highrise Building","Office Building","Apartment Building","Residential","Open Space") @Order(1)
attr Type = getType
@Order(2) @Range(0.5,2)
attr HeightFactor = 1
@Group("Trees",3)
@Order(1) @Range("None","Fan","Model","Analytical") @Description("Do not generate Models for whole city i.e. take care with polygon counts!")
attr ShowTrees = "Fan"
@Order(2) @Range("Random Forest","Tropical","Zone 6 Trees")
attr Mix = "Zone 6 Trees"
# Mapped Attributes for Streets (comming from graph)
@Hidden @Order(1) @Range(0,30)
attr streetWidth = geometry.dv(0,unitSpace) # REALWORLD-distance in V-direction corresponds to width of street (in case the geometry does not contain rounded entry geometry)
@Hidden @Order(2) @Range(1,6)
attr laneWidth = streetWidth/geometry.dv(0,uvSpace) # note that TEXTURE-distance in V-direction corresponds to number of lanes (as generated by CityEngine)
@Hidden @Order(3)
attr connectionEnd = "STREET" # built in value attributes, needs to be sourced as Object (parent)
@Hidden @Order(4)
attr connectionStart = "STREET" # built in value attributes, needs to be sourced as Object (parent)
@Hidden @Order(5)
attr valency = 0
# Constants
const getType =
case distanceToCenter < radiusHighriseArea : 80%: "Highrise Building" 15%: "Office Building" 2%: "Apartment Building" else: "Open Space" # mainly highrises and commercial
case distanceToCenter < radiusCommercialArea : 29%: "Highrise Building" 60%: "Office Building" 10%: "Apartment Building" else: "Open Space" # mainly offices
case distanceToCenter < radiusApartmentArea : 20%: "Office Building" 76%: "Apartment Building" 3%: "Residential" else: "Open Space" # mainly apartments
case distanceToCenter < radiusResidentialArea: 5%: "Office Building" 40%: "Apartment Building" 53%: "Residential" else: "Open Space" # mainly residential and apartments
else : 1%: "Office Building" 4%: "Apartment Building" 90%: "Residential" else: "Open Space" # more or less only residential
const radiusHighriseArea = 500
const radiusCommercialArea = 900
const radiusApartmentArea = 1300
const radiusResidentialArea = 1600
const distanceToCenter = sqrt(initialShape.origin.px*initialShape.origin.px +initialShape.origin.pz*initialShape.origin.pz)
###################################################
###################################################
##
## RULES
##
##
@StartRule
Lot -->
translate(rel,world,0,Street_Modern_Standard.SidewalkHeight,0)
LotAligned
LotInner -->
translate(rel,world,0,Street_Modern_Standard.SidewalkHeight,0)
LotInnerAligned
LotCorner -->
Street_Modern_Standard.Pavement
###################################################3
# Type Distribution
#
LotAligned -->
case Type == "Open Space" : GreenGround Trees
case Type == "Residential" : ResidentialBlock
case Type == "Apartment Building" : ApartmentBlock
case Type == "Office Building" : CommercialBlock
else : HighriseBlock
LotInnerAligned -->
case Type == "Open Space" : GreenGround Trees
case Type == "Residential" : 5%: ResidentialBlock else: GreenGround Trees
case Type == "Apartment Building" : 5%: ApartmentBlock 10%: ParkingGround else: GreenGround Trees
case Type == "Office Building" : 10%: CommercialBlock 20%: ParkingGround else: GreenGround Trees
else : 30%: HighriseBlock 20%: ParkingGround else: GreenGround Trees
###################################################3
# Residential
#
@Hidden
attr buildingHeight = 0
@Hidden
attr groundFloorHeight = 0
@Hidden
attr roofAngle = rand(15,25)
@Hidden
attr roofOverhang = 10%: 0 else: rand(0.2,0.6)
extensionRoofType = 70%: "gable" else: "hip"
garageRoofType = 20%: "gable" else: "flat"
getUpperfloorHeight = case buildingHeight-groundFloorHeight > 2: buildingHeight-groundFloorHeight else: 2.5
# Block Parceling (in case needed) ########
ResidentialBlock --> # here we subdivide the initial shape further in case it is too big (to get kind of row housing...)
case scope.sx > 20 : setback(rand(20,35)){ front: ResidentialBlockStripe | remainder: ResidentialBlockBack }
else : ResidentialBlockBack
ResidentialBlockBack -->
case scope.sz > 20 : setback(rand(20,35)){ left: ResidentialBlockStripe | remainder: ResidentialBlockRight }
else : ResidentialBlockStripe
ResidentialBlockRight -->
case scope.sz > 20 : setback(rand(20,35)){ right: ResidentialBlockStripe | remainder: GreenGround Trees Trees }
else : ResidentialBlockStripe
ResidentialBlockStripe -->
alignScopeToGeometry(yUp, 0, longest)
ResidentialBlockStripeSubdivide
ResidentialBlockStripeSubdivide -->
case scope.sx > 30:
split(x){ ~rand(16,30): ResidentialBlockStripeSubdivide }*
case geometry.isConcave && scope.sx > 25: # concaves are subdivided further (trying to get rid of the concavity)
split(x){ ~rand(14,23): ResidentialBlockStripeSubdivide }*
case p(0.3) && geometry.isConcave && scope.sz > 25:
split(z){ ~rand(14,23): ResidentialBlockStripeSubdivide }*
case p(0.3) && geometry.isRectangular(25) && scope.sz > scope.sx*3:
split(z){ ~1: alignScopeToGeometry(yUp,2) ResidentialLot | ~1: ResidentialLot }
else:
ResidentialLot
# Lot Preperation ########
ResidentialLot -->
GreenGround ResidentialLotAlign
ResidentialLotAlign -->
case geometry.nVertices < 4:
Trees
case !geometry.isRectangular(10):
innerRect
split(x){ 1 : NIL
| 'rand(.85,.9): split(z){ ~rand(1,3): Trees | (rand(15,20)): ResidentialBuildingArea | ~1: Trees }
| 1 : NIL }
else:
split(x){ 1 : NIL
| 'rand(.85,.9): split(z){ ~rand(1,3): Trees | (rand(15,20)): ResidentialBuildingArea | ~1: Trees }
| 1 : NIL }
ResidentialBuildingArea -->
case scope.sx < 10 || scope.sz < 10: # too small to build a house
NIL
else:
alignScopeToAxes(y) s('1,0,'1) # there are different possibilites to handle non-horizontal lots... scaling it to zero in the y-direction like here is the simplest way to handle it
ResidentialBuilding
# Building Generation ########
ResidentialBuilding -->
# building settings
set(buildingHeight, 20%: rand(3,3.5) else: rand(5,6.5))
set(groundFloorHeight, rand(2.9,3.4))
set(roofAngle, rand(15,25))
set(roofOverhang, 20%: 0 else: rand(0.2,0.6))
# facade settings
set(Facade_Textures.Usage, "Residential")
set(Facade_Textures.BuildingHeight, buildingHeight*HeightFactor)
set(Facade_Textures.UpperfloorsTexture, Facade_Textures.getUpperfloorsTexture)
set(Facade_Textures.GroundfloorTexture, Facade_Textures.getGroundfloorTexture)
set(Facade_Textures.UpperfloorHeight, getUpperfloorHeight)
set(Facade_Textures.GroundfloorHeight, groundFloorHeight)
set(Facade_Textures.TileWidth, rand(2.6,3))
# roof settings
set(Roof_Textures.FlatRoofTexture, Roof_Textures.getFlatRoofTexture)
set(Roof_Textures.SlopedRoofTexture, Roof_Textures.getSlopedRoofTexture)
# invoke geometry creation
ResidentialShape
set(Facade_Textures.GroundfloorHeight, 0)
ResidentialExtension
ResidentialGarage
# Stochastic Mass Model Composition ########
ResidentialShape -->
s('rand(0.6,0.8),0,'rand(0.45,0.6)) center(xz) ResidentialShape(buildingHeight)
ResidentialShape(h) -->
15% : Mass(h,"gable")
5% : Mass(h,"hip")
17% : [ s('1.0,0,'0.8) Mass(h,"gable") ] split(x){ 'rand(0.35,0.6): t(0,0,'0.4) s('1,0,'rand(0.45,0.65)) Mass(h,"gable2") } # L-shape left for gable roofs
17% : [ s('1.0,0,'0.8) Mass(h,"hip") ] split(x){ 'rand(0.35,0.6): t(0,0,'0.1) s('1,0,'rand(0.8,0.95)) Mass(h,"hip") } # L-shape left for hip roofs
17% : [ s('1.0,0,'0.8) Mass(h,"gable") ] split(x){ ~1: NIL | 'rand(0.35,0.6): t(0,0,'0.4) s('1,0,'rand(0.45,0.65)) Mass(h,"gable2") } # L-shape right for gable roofs
17% : [ s('1.0,0,'0.8) Mass(h,"hip") ] split(x){ ~1: NIL | 'rand(0.35,0.6): t(0,0,'0.1) s('1,0,'rand(0.8,0.95)) Mass(h,"hip") } # L-shape right for hip roofs
5% : [ s('1.0,0,'0.8) Mass(h,"gable") ] split(x){ ~1: NIL | 'rand(0.35,0.6): t(0,0,'0.4) s('1,0,'rand(0.55,0.65)) Mass(h,"gable2") | ~1: NIL } # T-shape for gable roofs
5% : [ s('1.0,0,'0.8) Mass(h,"hip") ] split(x){ ~1: NIL | 'rand(0.35,0.6): t(0,0,'0.1) s('1,0,'rand(0.8,0.95)) Mass(h,"hip") | ~1: NIL } # T-shape for hip roofs
1% : [ s('1.0,0,'0.8) Mass(h,"gable") ] t(0,0,'0.4) s('1,0,'rand(0.55,0.65)) split(x){ 'rand(0.3,0.4): Mass(h,"gable2") | ~1: NIL | 'rand(0.3,0.4): Mass(h,"gable2") } # U-shape for gable roofs
else: [ s('1.0,0,'0.8) Mass(h,"hip") ] t(0,0,'0.1) s('1,0,'rand(0.8,0.95)) split(x){ 'rand(0.3,0.4): Mass(h,"hip") | ~1: NIL | 'rand(0.3,0.4): Mass(h,"hip") } # U-shape for hip roofs
ResidentialExtension -->
7% : split(z){ (rand(1,3)): NIL | ~1: Mass(rand(3,4),extensionRoofType) | (rand(1,3)): NIL }
18% : split(z){ '(rand(.4,.7)): split(x){ '(rand(.3,.7)): Mass(rand(3,4.5),extensionRoofType) } }
18% : split(z){ '(rand(.2)): NIL | '(rand(.2,.5)): split(x){ '(rand(.3,.7)): Mass(rand(3,4.5),extensionRoofType) } }
18% : split(z){ '(rand(.4,.7)): split(x){ ~1: NIL | '(rand(.3,.7)): Mass(rand(3,4.5),extensionRoofType) } }
18% : split(z){ '(rand(.2)): NIL | '(rand(.2,.5)): split(x){ ~1: NIL | '(rand(.3,.7)): Mass(rand(3,4.5),extensionRoofType) } }
else: NIL
ResidentialGarage -->
46% : split(z){ ~1: NIL | '(rand(.3,.6)): split(x){ (rand(5,8)): Mass(groundFloorHeight,garageRoofType) } | '(rand(.05,.25)): NIL }
46% : split(z){ ~1: NIL | '(rand(.3,.6)): split(x){ ~1: NIL | (rand(5,8)): Mass(groundFloorHeight,garageRoofType) } | '(rand(.05,.25)): NIL }
else: NIL
# Mass Model ########
Mass(h,rooftype) -->
extrude(h*HeightFactor) Stories comp(f){top: Roof(rooftype) }
Stories -->
comp(f){ side: Facade }
Facade -->
Facade_Textures.Generate
###################################################3
# Appartments
#
ApartmentBlock -->
case scope.sx > 60:
split(x){ (rand(35,50)): ApartmentLot | ~1: ApartmentBlock }
else:
ApartmentLot
ApartmentLot -->
GreenGround ApartmentLotAlign
ApartmentLotAlign -->
cleanupGeometry(all, 1)
offset(-rand(2,4), inside)
split(z){ ~rand(1,3): Trees | (rand(20,30)): ApartmentBuildingArea | ~1: FewTrees }
ApartmentBuildingArea -->
case scope.sx < 20: # too small to build a house
NIL
else:
alignScopeToAxes(y) s('1,0,'1) # there are different possibilites to handle non-horizontal lots... scaling it to zero in the y-direction like here is the simplest way to handle it
ApartmentBuilding
ApartmentBuilding -->
# building settings
set(buildingHeight, rand(8,14))
set(groundFloorHeight, rand(3.1,4))
set(roofAngle, rand(15,25))
set(roofOverhang, 10%: 0 else: rand(0.5,1))
# facade settings
set(Facade_Textures.Usage, "")
set(Facade_Textures.BuildingHeight, buildingHeight*HeightFactor)
set(Facade_Textures.UpperfloorsTexture, Facade_Textures.getUpperfloorsTexture)
set(Facade_Textures.GroundfloorTexture, Facade_Textures.getGroundfloorTexture)
set(Facade_Textures.UpperfloorHeight, rand(2.7,3.2))
set(Facade_Textures.GroundfloorHeight, groundFloorHeight)
set(Facade_Textures.TileWidth, rand(2.7,3.5))
# roof settings
set(Roof_Textures.FlatRoofTexture, Roof_Textures.getFlatRoofTexture)
set(Roof_Textures.SlopedRoofTexture, Roof_Textures.getSlopedRoofTexture)
# invoke geometry creation
ApartmentShape(buildingHeight)
ApartmentShape(h) -->
25% : shapeL(scope.sz*rand(0.4,0.8),scope.sx*rand(0.3,0.4)){ shape: ApartmentMass(h) }
25% : shapeU(scope.sz*rand(0.4,0.8),scope.sx*rand(0.3,0.4),0){ shape: ApartmentMass(h) }
25% : shapeU(scope.sz*rand(0.4,0.7),scope.sx*rand(0.2,0.4),scope.sx*rand(0.2,0.4)){ shape: ApartmentMass(h) }
else: shapeO(0,scope.sx*rand(0.2,0.4),scope.sz*rand(0.4,0.7),scope.sx*rand(0.2,0.4)){ shape: ApartmentMass(h) }
ApartmentMass(h) -->
30% : Mass(h,"gable")
25% : Mass(h,"hip")
else: Mass(h,"flat")
###################################################3
# Office Buildings
#
commercialBuildingWidth = 70%: rand(15,25) else: rand(25,80)
CommercialBlock -->
case scope.sz > 40:
setback(rand(40,80)){ front: CommercialRow | remainder: rotateScope(0,180,0) CommercialRow }
else:
CommercialRow
CommercialRow -->
case scope.sx > 30:
split(x){ commercialBuildingWidth: CommercialLot | ~1: CommercialRow }
else:
CommercialLot
CommercialLot -->
40% : split(z){ '(rand(0.2,0.4)): ParkingGround | ~1: ParkingGround CommercialBuildingArea(1) | (rand(4)): GreenGround } # 20% with a setback
30% : GreenGround split(z){ '(rand(0.2,0.4)): FewTrees | ~1: CommercialBuildingArea(1) }
else: GreenGround split(z){ '(rand(0.2,0.4)): Trees | ~1: CommercialBuildingArea(1) }
CommercialBuildingArea(count) -->
case scope.sx < 10 || scope.sz < 10: # too small to build a house
NIL
else:
alignScopeToAxes(y) s('1,0,'1) # there are different possibilites to handle non-horizontal lots... scaling it to zero in the y-direction like here is the simplest way to handle it
CommercialBuilding(count)
CommercialBuilding(count) -->
cleanupGeometry(all, 1)
# building settings
set(buildingHeight, case scope.sx>40: rand(16,30) else: rand(10,20))
set(groundFloorHeight, rand(4,5.5))
set(roofAngle, rand(20,30))
set(roofOverhang, 0)
# facade settings
set(Facade_Textures.Usage, "")
set(Facade_Textures.BuildingHeight, buildingHeight*HeightFactor)
set(Facade_Textures.UpperfloorsTexture, Facade_Textures.getUpperfloorsTexture)
set(Facade_Textures.GroundfloorTexture, Facade_Textures.getGroundfloorTexture)
set(Facade_Textures.UpperfloorHeight, rand(2.8,3.3))
set(Facade_Textures.GroundfloorHeight, groundFloorHeight)
set(Facade_Textures.TileWidth, rand(2.2,3.7))
# roof settings
set(Roof_Textures.FlatRoofTexture, Roof_Textures.getFlatRoofTexture)
set(Roof_Textures.SlopedRoofTexture, Roof_Textures.getSlopedRoofTexture)
# invoke geometry creation
offset(case scope.sx>30 && p(0.6): -rand(2,6) else: 0,inside)
CommercialShape(buildingHeight)
CommercialShape(h) -->
35% : shapeL(scope.sz*rand(0.7,0.95),scope.sx*rand(0.2,0.8)){ shape: CommercialMass(h) }
35% : shapeU(scope.sz*rand(0.7,0.95),scope.sx*rand(0.2,0.8),0){ shape: CommercialMass(h) }
else: shapeU(scope.sz*rand(0.8,0.95),scope.sx*rand(0.2,0.45),scope.sx*rand(0.2,0.45)){ shape: CommercialMass(h) }
CommercialMass(h) -->
99% : Mass(h,"rooffloor")
else: Mass(h,"flat")
###################################################3
# Highrise
#
# function: distance to center controls the building height
highriseBuildingHeight =
case distanceToCenter < radiusHighriseArea/4 && geometry.area > 2000 : rand(200,350) //rand(100,250)
case distanceToCenter < radiusHighriseArea/4 && geometry.area > 600 : rand(120,250) //rand(100,250)
case distanceToCenter < radiusHighriseArea/2 && geometry.area > 300 : rand(80,200) //rand(80,150)
case distanceToCenter < radiusHighriseArea && geometry.area > 150 : rand(20,100) //rand(40,80)
case distanceToCenter < (radiusHighriseArea+radiusCommercialArea)/2 : rand(30,60)
else : rand(20,50)
HighriseBlock -->
HighriseBlock(0)
HighriseBlock(index) -->
case index >= geometry.nEdges || geometry.nVertices == 3:
CommercialLot
case scope.sz > 50:
split(z){ ~1: alignScopeToGeometry(yUp,index+1) HighriseBlock(index+1) | (rand(40,80)): HighriseRow }
else:
alignScopeToGeometry(yUp,index+1) HighriseRow
HighriseRow -->
case scope.sx > 60:
split(x){ (rand(40,80)): HighriseLot | ~1: HighriseRow }
else:
HighriseLot
HighriseLot -->
case scope.sx < 30 || scope.sz < 30: # too small to build a house
CommercialLot
else:
ParkingGround
alignScopeToAxes(y) s('1,0,'1) # there are different possibilites to handle non-horizontal lots... scaling it to zero in the y-direction like here is the simplest way to handle it
HighriseBuilding(rand(7,12))
HighriseBuilding(lowerH) -->
cleanupGeometry(all, 1)
# building settings
set(buildingHeight, highriseBuildingHeight)
set(groundFloorHeight, rand(4.5,6))
set(roofAngle, rand(20,30))
set(roofOverhang, 0)
# facade settings
set(Facade_Textures.Usage, "")
set(Facade_Textures.BuildingHeight, buildingHeight*HeightFactor)
set(Facade_Textures.UpperfloorsTexture, Facade_Textures.getUpperfloorsTexture)
set(Facade_Textures.GroundfloorTexture, Facade_Textures.getGroundfloorTexture)
set(Facade_Textures.UpperfloorHeight, rand(2.9,3.4))
set(Facade_Textures.GroundfloorHeight, groundFloorHeight)
set(Facade_Textures.TileWidth, rand(2.2,3.9))
# roof settings
set(Roof_Textures.FlatRoofTexture, Roof_Textures.getFlatRoofTexture)
set(Roof_Textures.SlopedRoofTexture, Roof_Textures.getSlopedRoofTexture)
# invoke geometry creation
offset(30%: -sqrt(geometry.area)*rand(0.05,0.1) else: 0, inside)
Mass(lowerH/HeightFactor,"flat") t(0,lowerH,0)
offset(50%: -sqrt(geometry.area)*rand(0.05,0.1) else: 0, inside)
HighriseUpper
# Highrise Type Decision #####
HighriseUpper -->
case distanceToCenter < radiusHighriseArea/2 : 45%: InternationalTower 45%: SetbackTower 5%: HighriseShape else: LShape(highriseBuildingHeight*0.5)
case distanceToCenter < radiusHighriseArea/2 : 40%: InternationalTower 30%: SetbackTower 25%: HighriseShape else: LShape(highriseBuildingHeight*0.5)
case distanceToCenter < radiusHighriseArea : 45%: InternationalTower 5%: SetbackTower 40%: HighriseShape else: LShape(highriseBuildingHeight*0.5)
else : 40%: InternationalTower 1%: SetbackTower 55%: HighriseShape else: LShape(highriseBuildingHeight*0.5)
# Highrise L/U-Shape #####
HighriseShape -->
case scope.sz > 40 && p(0.5):
split(z){ 'rand(.1,.3): NIL | ~1: HighriseShape }
else:
70% : LShape(highriseBuildingHeight)
20% : UShape(highriseBuildingHeight)
else: split(z){ ~1: NIL | 'rand(.4,.6): HighriseMass }
LShape(h) -->
split(z){ ~1: LShapeWing(h) | 'rand(.4,.6): HighriseMass(h) }
LShapeWing(h) -->
50% : split(x){ ~1 : NIL | 'rand(0.4,0.6) : Wing(h) } // right side
else: split(x){ 'rand(0.4,0.6) : Wing(h) } // left side
UShape(h) -->
case scope.sx > scope.sz:
split(z){ ~1: UShapeWings(h) | 'rand(0.4,0.7): HighriseMass(h) }
else:
split(z){ 'rand(.3,.4): HighriseMass(h) | ~1: CHWing(h) | 'rand(.3,.4): HighriseMass(h) }
UShapeWings(h) -->
split(x){ 'rand(0.3,0.4): Wing(h) | ~1: NIL | 'rand(0.3,0.4): Wing(h) }
Wing(h) -->
30% : HighriseMass(h) // same height
30% : HighriseMass(h*rand(0.5,0.9)) // lower height 1
else: HighriseMass(highriseBuildingHeight*rand(0.5,0.7)) // lower height 2
CHWing(h) -->
40% : split(x){ ~1: NIL | 'rand(0.5,0.7): HighriseMass(h) | ~1: NIL }
30% : split(x){ 'rand(0.5,0.7): HighriseMass(h) }
else: split(x){ ~1: NIL | 'rand(0.5,0.7): HighriseMass(h) }
HighriseMass -->
Mass(buildingHeight,"rooffloor")
HighriseMass(h) -->
Mass(h,"rooffloor")
# Setback Tower #####
lowHeight = 50% : 0.3 else: 0.7 // switching between these two values creates visually appealing setbacks
const offset = rand(0.05,0.1)
SetbackTower -->
case scope.sx < 20 || scope.sz < 20:
LShape(highriseBuildingHeight*0.3)
case scope.sx < 30:
shapeO(scope.sz*0.1,0,scope.sz*0.1,0){ remainder: extrude(buildingHeight*HeightFactor*rand(0.9,1)) RecursiveSetbacks }
shapeO(0,scope.sx*0.21,0,scope.sx*0.21){ remainder: extrude(buildingHeight*HeightFactor) RecursiveSetbacks }
case p(0.5):
shapeO(scope.sz*0.15,0,scope.sz*0.15,0){ remainder: extrude(buildingHeight*HeightFactor*rand(0.9,1)) RecursiveSetbacks }
shapeO(0,scope.sx*0.21,0,scope.sx*0.21){ remainder: extrude(buildingHeight*HeightFactor) RecursiveSetbacks }
else:
shapeO(scope.sz*0.21,0,scope.sz*0.21,0){ remainder: extrude(buildingHeight*HeightFactor) RecursiveSetbacks }
shapeO(0,scope.sx*0.1,0,scope.sx*0.1){ remainder: extrude(buildingHeight*HeightFactor*rand(0.9,1)) RecursiveSetbacks }
RecursiveSetbacks -->
case scope.sy > 10 && scope.sx > 10 && scope.sz > 10:
split(y){ 'lowHeight : Stories comp(f){top: Roof("flat") } | ~1: RecursiveSetbacksCall(scope.sy) }
else:
s('1,5,'1)
Stories comp(f){top: Roof("rooffloor") }
RecursiveSetbacksCall(h) -->
t(0,-h,0)
comp(f){top: alignScopeToAxes(y)
shapeO(scope.sz*offset,scope.sx*offset,scope.sz*offset,scope.sx*offset)
{ remainder: extrude(h) RecursiveSetbacks } }
# International Style #####
InternationalTower -->
case sqrt(geometry.area) < 35:
split(z){ (sqrt(geometry.area)): HighriseMass(buildingHeight*0.7) }
case p(0.7):
split(z){ (sqrt(geometry.area)*0.4): HighriseMass
| ~1: [ extrude(0.2) GreenGround ] t(0,0.2,0) Trees }
case p(0.1):
split(z){ (sqrt(geometry.area)*0.4): HighriseMass }
else:
LShape(highriseBuildingHeight*0.7)
###################################################3
# Roof Generation
#
Roof(rooftype) -->
case rooftype == "rooffloor":
RoofPlane alignScopeToGeometry(yUp,auto) RoofFloor
case rooftype == "gable1":
roofGable(roofAngle,roofOverhang,roofOverhang,false,1) comp(f){ bottom: NIL | vertical: Facade | all: RoofPlane }
case rooftype == "gable2":
roofGable(roofAngle,0,roofOverhang,false,0) comp(f){ bottom: NIL | vertical: Facade | all: RoofPlane }
case rooftype == "gable":
roofGable(roofAngle,roofOverhang) comp(f){ bottom: NIL | vertical: Facade | all: RoofPlane }
case rooftype == "hip":
roofHip(roofAngle,roofOverhang) comp(f){ bottom: NIL | all: RoofPlane }
else:
RoofPlane
RoofFloor -->
21% : offset(-scope.sz*rand(0.0,0.35),inside)
shapeL(scope.sz*rand(0.2,0.7),scope.sx*rand(0.2,0.8)){ shape: rotateScope(0,90,0) Mass(rand(1,3)/HeightFactor,"flat") }
21% : offset(-scope.sz*rand(0.0,0.35),inside)
shapeL(scope.sz*rand(0.2,0.7),scope.sx*rand(0.2,0.8)){ shape: rotateScope(0,90,0) Mass(rand(1,3)/HeightFactor,"flat") }
26% : innerRect [ s('(rand(0.6,0.9)),'(rand(0.6,0.9)),'1) center(xy) RoofFloorShape(rand(3,4)/HeightFactor) ]
21% : innerRect [ s('(rand(0.6,0.9)),'(rand(0.6,0.9)),'1) center(xy) RoofFloorShape(rand(1,2)/HeightFactor) ]
10% : set(Roof_Textures.SlopedRoofTexture, Roof_Textures.getFlatRoofTexture)
innerRect
[ s('(rand(0.2,0.4)),'1,'(rand(0.2,0.4))) center(xz) t('rand(-0.5,0.5),0,'rand(-0.5,0.5)) ResidentialShape(rand(2,3)/HeightFactor) ]
[ s('(rand(0.6,0.9)),'1,'1) center(xz) RoofFloorShape(rand(1,2)/HeightFactor) ]
else: NIL
RoofFloorShape(h) -->
split(z){ ~1: RoofFloorBack(h) | 'rand(0.5,0.7): Mass(h,"flat") }
RoofFloorBack(h) -->
20% : split(x){ 'rand(0.2,0.8): Mass(h,"flat") } # L-shape left
20% : split(x){ ~1: NIL | 'rand(0.2,0.8): Mass(h,"flat") } # L-shape right
40% : split(x){ ~(rand): NIL | (rand(0.8,1.5)*scope.sz): Mass(h,"flat") | ~(rand): NIL } # T-shape
10% : split(x){ 'rand(0.2,0.45): Mass(h,"flat") | ~1: NIL | 'rand(0.2,0.45): Mass(h,"flat") } # U-shape
else: NIL
RoofPlane -->
Roof_Textures.Generate
###################################################3
# Ground Cover
#
const getDirtmapTexture = fileRandom("/ESRI.lib/assets/General/Dirtmap/dirtmap*.jpg")
const getParkingTexture = fileRandom("/ESRI.lib/assets/Groundcover/Parking/parking*.jpg")
getGreenSpaceTexture = imageBestRatio("/ESRI.lib/assets/Groundcover/Green/green*.jpg","yx")
ParkingGround -->
alignScopeToGeometry(zUp,0,longest)
setupProjection(0,scope.yx,20,35) projectUV(0)
texture(getParkingTexture)
setupProjection(2,scope.yx,'1,'1) projectUV(2)
set(material.dirtmap,getDirtmapTexture)
GreenGround -->
alignScopeToGeometry(zUp,0,longest)
setupProjection(0,scope.yx,'1,'1) projectUV(0)
texture(getGreenSpaceTexture)
setupProjection(2,scope.yx,'1,'1) projectUV(2)
set(material.dirtmap,getDirtmapTexture)
###################################################3
# Trees
#
getTreeTropical = listRandom("Coconut Palm;Date Palm;Palm Lily;Mexican Palmetto;California Palm;Ruffle Palm;Banana Tree;Bamboo;Cabbage Palm Fern;")
getTreeRandomForest = listRandom("American Chestnut;Red Hickory;Southern Magnolia;Sugar Maple;Northern Red Oak;White Oak;Scots Pine;Douglas Fir;Lodgepole Pine;California Redwood;Giant Sequoia;American Sycamore;Sassafras;California Walnut;")
getTreeZone06Tree = listRandom("Sugar Maple;California Incense Cedar;Red Hickory;American Chestnut;Western Juniper;American Sycamore;Northern Red Oak;Basswood;Field Elm;Lawson Cypress;Honey Locust;Yellow Poplar;Black Tupelo;")
getTree =
case Mix == "Tropical" : getTreeTropical
case Mix == "Random Forest" : getTreeRandomForest
case Mix == "Zone 6 Trees" : getTreeZone06Tree
else : ""
FewTrees -->
case ShowTrees != "None":
set(Plant_Loader.Representation,ShowTrees)
scatter(surface, floor(geometry.area/250), uniform){ Plant_Loader.Generate(getTree) }
NIL
else:
NIL
Trees -->
case ShowTrees != "None":
set(Plant_Loader.Representation,ShowTrees)
scatter(surface, floor(geometry.area/300), uniform){ Plant_Loader.Generate(getTree) }
scatter(surface, floor(geometry.area/200), uniform){ Plant_Loader.Generate(getTree) }
scatter(surface, floor(geometry.area/400), uniform){ Plant_Loader.Generate(getTree) }
NIL
else:
NIL
###################################################3
# Street
#
Street --> Street_Modern_Standard.Street
Joint --> Street_Modern_Standard.Joint
Crossing --> Street_Modern_Standard.Crossing
Junction --> Street_Modern_Standard.Junction
Freeway --> Street_Modern_Standard.Freeway
FreewayEntry --> Street_Modern_Standard.FreewayEntry
Roundabout --> Street_Modern_Standard.Roundabout
RoundaboutIsland --> Street_Modern_Standard.RoundaboutIsland
Sidewalk --> Street_Modern_Standard.Sidewalk
/*
*/