Apply textures to facades based on building attributes

2882
9
10-15-2014 09:16 AM
AishaPasha
New Contributor

Hi all, I'm just getting started with City Engine and am trying to apply textures to facades based on building attributes (i.e. brick, wood, stone etc.). Can anyone give an example of how to write the code for this? Thx.

0 Kudos
9 Replies
by Anonymous User
Not applicable

Put in your assets folder: (find attached CGA and Assets)

brick.jpg, wood.jpg, and stone.jpg

BrickWoodStone.cga:

version "2014.0"

const facadeDirectory = "assets/BrickWoodStone/"

attr buildingHeight = 10

@Range("brick", "wood", "stone")

attr facadeTexture = "brick"

attr textureScaleX = 4

attr textureScaleY = 4

BuildingFootprint -->

  # Make footprint flat by scaling to zero in y direction.

  s('1,0,'1)

  # Make footprint into mass.

  extrude(buildingHeight)

  # Pop off sides and top.

  comp(f) {top: Roof | side: Facade}

Roof -->

  roofGable(30)

Facade -->

  setupProjection(0, scope.xy, textureScaleX, textureScaleY)

  projectUV(0)

  texture(facadeDirectory + facadeTexture + ".jpg")

MatthiasBuehler
Regular Contributor

great help here, Chris !

Matt

Matthias Buehler

Head of 3D Technologies

twitter: @MattB3D

------------------------------

Garsdale Design Limited

matthias.buehler@garsdaledesign.co.uk

www.garsdaledesign.co.uk

AishaPasha
New Contributor

Great! Thanks for this. I was wondering though how exactly do I assign textures based on attributes already specified to the object? I have a set of historic building footprints that have information attached to them (height, # of stories, material etc) and I've been able to extrude them to correspond with their height, but I'm still not sure how to link textures to the given material.

0 Kudos
by Anonymous User
Not applicable

Can you give a brief example...pseudo-code or just explain the logic/goal? How do the attribute values correspond to the material choices. Is random involved, or exact/unique textures per building or per attribute value?

Chris

0 Kudos
AishaPasha
New Contributor

Sure. There are no random values. I imported a shapefile of historic building footprints that have a field called "material", which specifies whether the building was constructed from brick, wood, metal, etc. I'd like to assign textures to the facades based on the material specified in that field, which are just recorded as "brick", "wood", "metal" etc. The outcome would be that all buildings specified as "brick" in the material field would receive a brick textured facade, and so on.

0 Kudos
by Anonymous User
Not applicable

So it seems this is the same rule as earlier in the post (see above CGA), but you need to use the Connection Editor. See the small icon to the left of the values in the Inspector. Clicking into that, you will see the third option is "object attribute". That is how you connect your rule to object attributes of the shapes that the rule is running on. To enable this linkage, the object attribute name must match the attribute name in your rule.

So in the rule above, change this line, so that "facadeTexture" matches you object attributes on the shapes:

attr facadeTexture = "brick"

Is this what you meant?

0 Kudos
AishaPasha
New Contributor

Okay thanks. So this is what I have (note LAYER is the name of the attribute field):

const facadeDirectory = "assets/brick_facade_01/"

attr LAYER = "brick"

@Range("brick", "stone", "frame", "iron", "special frame")

attr facadeTexture = LAYER

attr textureScaleX = 4

attr textureScaleY = 4

Facade -->

  setupProjection(0, scope.xy, textureScaleX, textureScaleY)

  projectUV(0)

  texture(facadeDirectory + facadeTexture + "brick_facade_01.jpg")

This worked in that it changed the value in the connection editor to the individual prescribed attribute for every object. I'm still not sure about facade texture though. This code didn't project anything and I'm not sure how to make it more specific to differentiate between the attributes. So far I only included one image (brick) just to test.

0 Kudos
by Anonymous User
Not applicable

One easy way to test this is change this:

texture(facadeDirectory + facadeTexture + "brick_facade_01.jpg")

To this:

print(facadeDirectory + facadeTexture + "brick_facade_01.jpg")

It should display this in the CGA console:

assets/brick_facade_01/brickbrick_facade_01.jpg

This shows the file you are asking for. Notice you need a slash before the file name, so then change the line to this:

texture(facadeDirectory + facadeTexture + "/" + "brick_facade_01.jpg")

Or if you weren't using a literal file name:

texture(facadeDirectory + facadeTexture + "/" + yourFileNameHere)

0 Kudos
AishaPasha
New Contributor

Hmm, okay this actually didn't change anything. Nothing still projects. Also, just to be clear, this the correct line of code: "assets/brick_facade_01/brickbrick_facade_01.jpg"

0 Kudos