From CityEngine to Unreal Engine: the journey from first design steps to high-quality real-time visualization (part 3/3)

3797
0
09-21-2021 09:24 AM

From CityEngine to Unreal Engine: the journey from first design steps to high-quality real-time visualization (part 3/3)

Part 3: 

Visualization strategies with Unreal Engine

 

StefanArisona_0-1632241218789.png

 

 

The possibility to export CityEngine projects to Unreal Engine, opens new possibilities for design. Thanks to the support for Datasmith files in both sides, this process becomes quick and simple. This ease allows to establish a bidirectional relation between generative design and visualization/animation that can inform each other through a series of design iterations and back and forth from CityEngine to Unreal Engine. Two templates exist on the Unreal Engine Marketplace for importing CityEngine projects, the CityEngineModelLoader that is for simple import, and the CityEngineVRExperience is set up for VR visualization.  They have the basic light setup and other useful functionalities tuned for visualizing large scale projects.

 

For details on the CityEngine VR Experience refer to the following documents:

> Introduction: CityEngine VR Experience for Unreal Engine 

> Additional features: CityEngine VR Experience Advanced Features

 

Other useful resources:

> ArcGIS Blog post: CityEngine VR Experience

> Webinar: Unreal and CityEngine: the future of urban design visualization

 

 

 

Default export 

 

The export-import process includes the following steps:

  • Select the shapes that you want to export in CityEngine.
  • Click on File > Export Models > Unreal Engine. The following export dialog comes up:

StefanArisona_1-1632241218790.png

 

 

  • Select name and location of file and set the parameters as in the screenshot and click on Finish.
  • Additional options: for customizing the export further and using other mesh merging and instancing parameters refer to the CityEngine Datasmith export manual.

 

In Unreal Engine, then open the CityEngine Model Loader or the CityEngine VR Experience template iand click on Import Datasmith leaving the default values on the window that comes up.

 

Materials

 

Unreal Engine 4 uses a physically based material and shading model that approximates the light’s behavior leading to more accurate and natural looking results in relation to other rendering techniques. The physically based rendering (PBR) materials have properties such as base color, roughness, metallic and specular that can be set either to values (from 0 to 1) or to texture maps. Although CityEngine does not render PBR materials, it offers the possibility to set all the necessary material properties in the CGA rules during the procedural generation of shapes. Then, during the import of the Datasmith file in the templates, PBR materials are automatically created as instances of the master materials that exist in the templates, maintaining all the properties that were set in CityEngine. This facilitates significantly the export-import process and allows for quick and easy visualization of textured CityEngine scenes.

 

> More information on Unreal Engine 4 shading model and materials 

 

Setting material properties in CityEngine

 

A category of the attributes of shapes in CityEngine are the material attributes that control the shading and texturing of the shape's geometry. All of these attributes can be defined using the set shape operation. More specifically, for PBR material shaders, CityEngine supports the following attributes: emissivemap, occlusionmap, roughnessmap, metallicmap, emissive, metallic, roughness, color, colormap, opacity, opacitymap and normalmap.

 

> Material attributes in CityEngine

> Texturing in CityEngine Tutorial

 

Properly setting the desired materials properties, textures and UV coordinates in CityEngine is necessary to ensure a smooth process. So, let’s take a look at how to do that. Firstly we need to set the shader name to "CityEnginePBRShader", and then set all the necessary material properties. Here's an example for the creation of metal (Titanium), using the measured basecolor values from the Unreal Engine documentation.

 

version "2019.0"

Metal_titanium --> 	
	set(material.shader, "CityEnginePBRShader")
	set(material.color.r, 0.542)
	set(material.color.g, 0.497)
	set(material.color.b, 0.449)
	set(material.opacity, 1)
	set(material.metallic,1)
	set(material.roughness,0.2)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

StefanArisona_2-1632241218839.png

 

Resulting material in Unreal Engine's material editor

 

If we want to use textures / maps, then we need to follow the steps of texturing (setupProjection(), projectUV()) along with setting the material attributes. Here's an example for texturing a concrete wall starting from an extrusion shape, using the following textures.

 

StefanArisona_3-1632241218841.png

 

Color map

 

StefanArisona_4-1632241218824.png

 

Metallic map

 

StefanArisona_5-1632241218898.png

 

Normal map

 

StefanArisona_6-1632241218845.png

 

Occlusion map

 

StefanArisona_7-1632241218859.png

 

Roughness map

 

version "2019.0"
attr concrete_tile = 2.5

Shape --> 
    set(material.shader, "CityEnginePBRShader")
    extrude(2)
    comp(f){all: Concrete}

Concrete --> 
    setupProjection(0,scope.xy, concrete_tile, concrete_tile)
    projectUV(0)
    set(material.roughness,1.0)
    set(material.metallic,1.0)
    set(material.colormap,"concrete_material_textures/Color.jpg") 
    set(material.metallicmap, "concrete_material_textures/Metallic.jpg")
    set(material.roughnessmap, "concrete_material_textures/Roughness.jpg")
    set(material.normalmap, "concrete_material_textures/Normal.jpg")‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
    set(material.occlusionmap, "concrete_material_textures/Occlusion.png")‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

StefanArisona_8-1632241218829.png

 

Resulting material in Unreal Engine's material editor

 

Material replacement

 

After import in Unreal Engine, the materials can be manually replaced by dragging and dropping a different material on the material slots of the static meshes. While manual replacement is useful for quickly testing out alternatives, in the large scale it can be impractical. To increase the flexibility of the workflow, CityEngine materials can be automatically replaced upon import with Unreal Engine materials. In order to achieve this, we can assign Unreal Engine materials directly in the CGA rules as placeholders, so they get automatically replaced upon import. This is done by setting the material.shader to point to the desired material:

set(material.shader, “/Game/Path_to_material_in_Content_folder/Name_of_material”)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

To get the path information of a material in Unreal Engine, right click on the material asset and click Copy Reference in the menu. The information that is copied in the clipboard includes the path to the material that we need to set the material.shader. For example, in the following material reference the path that is needed for the replacement is bold and underlined.

 

Material'/Game/Materials/CityEngineMaterials/MyMaterial.MyMaterial'

 

Creating high quality PBR materials can be a challenge. There are various tutorials, libraries and plugins that offer help. A good starting point is the Substance plugin for Unreal Engine that offers a variety of materials and techniques. There are also various free libraries of PBR materials. 

 

> Detailed documentation on template materials

 

> Substance plugin

> Share Substance 3D

> FreeBPR

 

 

Actor replacement

 

A design project at urban scale can require distribution of large number of actors (e.g. for foliage) throughout the scene, which can be time consuming if done manually. To facilitate this task, we have created an Unreal Engine tool, built into the CityEngine VR Experience template, that helps with replacing actors. You can access it by clicking on CityEngine Toolbox > Replacement Tool (Beta).

 

In CityEngine we can use CGA rules to prepare these actors by using placeholders. The placeholders that bear information of the actor’s name, position and scale, can be exported from CityEngine in large numbers as instances, and exchanged in Unreal Engine with assets using the replacement tool. Using that strategy, in our project we replaced more than 100.000 placeholders to foliage or other static meshes such as doors, windows, and street furniture.

 

> You can find more information on the batch replacement in the CityEngine VR Experience Advanced Features document.

 

To illustrate the overall process, let’s look at a simple example of a garden for how to distribute and replace placeholders. In CityEngine, we need to prepare placeholders with the following information: position; orientation; scale; and id of the desired asset. The position, rotation and scale are conveyed in the geometrical characteristics of the placeholder, while the id is conveyed in its name, that comes from the name of the asset.

 

Note that sometimes it is not necessary to specify the scale, because the size of the placeholder that we use is not important (for example when we replace foliage actors). However, in other cases (for example when replacing building components such as doors and windows) the scale is important, and we need to make sure that our placeholder has the right size. In this example we demonstrate the replacement of foliage for a garden, so the scale does not concern us.

 

Creation of the placeholder

For our placeholders we created a plane in Rhino saved as an Alias Wavefront OBJ file. Note that the origin of axes during the creation of the asset is important, as the replacement in Unreal Engine will be positioned at that origin regardless of where the geometry is. For that reason, it is good practice to have the origin of axes in the center of the geometry. The OBJ file is placed in the assets folder of the CityEngine project.

StefanArisona_9-1632241218792.png

 

 

Distribution of placeholders in the CGA rules

Now, we want to insert a) small plants and b) big trees in the scene. We create two placeholders (with identical geometry, but different names), and place them in our assets folder. Our folder structure looks as follows:

 

StefanArisona_10-1632241218793.png

 

 

In addition, we write an example rule that makes garden tiles like in this image:

StefanArisona_11-1632241218815.png

 

version "2019.0"
attr extrusion_width = 0.2

Lot -->
    setupProjection(0, scope.xz, 3, 3) 
    projectUV(0) 
    split(x){~7: split(z){~7: Tiles}*}*
 
Tiles --> 
    25% : Randomise_scope("G1") #full garden
    15% : Randomise_scope("G2") #stripes
    25% : Randomise_scope("G3") #plain floor
    else: Randomise_scope("G4") #half garden half floor
 
Randomise_scope(type) --> 
    25% : rotateScope(0,90,0) Create_tile(type)
    25% : rotateScope(0,-90,0) Create_tile(type)
    25% : rotateScope(0,180,0) Create_tile(type)
    else: rotateScope(0,0,0) Create_tile(type)

Create_tile(type) -->
    case type == "G1": #full garden
        Green_area 
    case type == "G2": #stripes
        split(x){~1.3 : Green_area
                |~0.6 : Floor}*
    case type == "G3": #plain floor
        Floor  
    else: #half garden half floor
        split(x){~1: Green_area
                |~1: Floor}

Green_area -->
    offset(-extrusion_width)
    comp(f){inside: Grass  
           |border: Border}

Border --> 
    extrude(0.12)
    comp(f){all: setupProjection(0, scope.xy, 3, 3) 
                 projectUV(0)
                 rotateUV(0, -90) 
                 Floor}
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

We further assign Unreal Engine materials available from the free collection of materials offered by the Substance plugin, so that they are automatically replaced upon export, as discussed in the previous paragraphs. In order for the material replacement to work, the downloaded materials need to be placed in the path that is specified in the material.shader of the CGA rule

Floor --> 
    color("#C8CBCC")
    set(material.name, "Vertical_Tiles_MAT")
    set(material.shader, "/Game/Materials/CityEngineMaterials/Vertical_Tiles_MAT")

Grass --> 
    color("#68A620")
    setupProjection(0, scope.xz, 2.5, 2.5)
    set(material.name, "Grass_Countryside_MAT")
    set(material.shader, "/Game/Materials/CityEngineMaterials/Grass_Countryside_MAT")‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Now we want to distribute the placeholders in the green areas. We want to scatter small plants in all the green areas, and place a big tree in the center of each green area that has sufficient area for that. The scatter operation is an easy way distribute points in a uniform or Gaussian distribution type on a surface, while the split operation is useful when we want more control on the position (here for the big trees). Then the OBJs can be imported in CGA using the insert operation, which reads a geometry asset (3D model, polygon mesh) from a file and inserts it into the scope of the current shape. We modify the Green_area rule to insert the placeholders:

 

Green_area -->
    case geometry.area > 10: # small plants and big tree
        offset(-extrusion_width)
        comp(f){inside: Grass 
                        Distribute_small_plants 
                        Tree_position
               |border: Border}
    else:                    # only small plants   
        offset(-extrusion_width)
        comp(f){inside: Grass 
                        Distribute_small_plants
               |border: Border}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

 

And finally we specify the Distribute_small_plants and the Tree_position rules. 

attr density = 0.5

Distribute_small_plants  --> 
    scatter (surface, geometry.area * density, uniform){Plant_position}
	
Plant_position --> 
    primitiveQuad(0.2,0.2)	
    i("garden_plant.obj") 

Tree_position --> 
    split(x){~1 : NIL
            |0.3: split(y){~1 : NIL
                          |0.3: color(1,0,0) 
                                alignScopeToAxes(y) 
                                i("tree_position.obj") 
                                Tree_pos.
                          |~1 : NIL}
            |~1 : NIL}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

 

Export to Datasmith

During export to Unreal Engine, in Geometry settings > Instancing chose either Disabled or Use Instancing so that each placeholder is imported as a separate actor in the scene, named after the asset that created them (in this case the garden_plant.obj or the tree_position.obj). Here’s what the result of the import in Unreal Engine looks like:

 

StefanArisona_12-1632241218861.png

 

 

Replacement of placeholders

To open the replacement tool, click on CityEngine Toolbox > Replacement Tool (remember that this is only available in the VR Experience template):

 

StefanArisona_13-1632241218805.png

 

 

After selecting the menu item, a dialog with a number of options opens:

 

StefanArisona_14-1632241218806.png

 

 

We replace our placeholders using the name as a filter criterion. The image shows assets downloaded from Epic Games' Open World Demo Collection:

 

StefanArisona_15-1632241218925.png

 

 

 

Bringing the city to life

 

A great advantage of using a game engine is that it offers both spatial and temporal dimensions for design. As a result, by linking CityEngine and Unreal Engine we can explore temporal aspects of the city using procedural design tools side by side with Unreal Engine blueprints. This opens a lot of space for exploration for vehicle traffic and human movement simulation, or shadow studies to name a few.

 

Day-night cycle

 

The changing light conditions of an urban scene play a vital role in its atmosphere, and their integration in the design workflow has long been a target of architects and planners. The latest versions of Unreal Engine allow to compute the accurate position of the sun based on the location, date and time zone. Building up on the basic sun position calculator and sky sphere, we created an extension that controls the environment actors of the scene such as lights, sky sphere and fog, and allows to visualize the full day-night cycle, either as a time-lapse or by stopping in specific hours of the day. This comes with default ready-to-use parameters but it’s also fully customizable, in order to be able to achieve the desired atmosphere for each project. The CityEngine VR Experience also supports replacing the builtin day light system with light provided by trueSKY.

 

> You can find more information on the sun position in the CityEngine VR Experience Advanced Features document.

 

StefanArisona_16-1632241218935.png

 

 

StefanArisona_17-1632241218863.jpeg

 

 

 

Moving actors

 

Moving actors can create a lively urban scene, give a reliable reference of scale, as well as help in the simulation behaviors, flows or traffic. Here we share the results of our experimentation with moving people. For the animation of the figures, we used Mixamo, a free and user-friendly online platform that enables auto-rigging (i.e., automatic animation) of static figures and exports animated figures in FBX format, compatible for import into Unreal Engine. From a visualization point of view, we wanted to avoid over-detailed characters that can be distracting from the design and contrast with the aesthetics of the environment. As a result, we opted for ‘ghost’ representations of fully detailed figures, to achieve the desired realism without clashing with the overall atmosphere. This was achieved by applying to the animated characters a custom translucent material instead of the default skin and clothes, that can be adjusted from translucent to opaque to give the characters the desired visual importance.

 

StefanArisona_18-1632241218871.jpeg

 

 

StefanArisona_19-1632241218911.png

 

 

StefanArisona_20-1632241218889.png

 

 

 

Exploration of the project in Virtual Reality (VR) 

 

The possibility to explore the 3D city in a VR environment offers a lot of potential both for the creation of new design workflows and as a means to communicate a project with other people in an immersive experience. 

 

 

To see a project in VR, we open the CityEngine VR Experience template and import the project. After the geometry has been imported and all the materials are in the scene, we need to click on CityEngine Toolbox > Create VR Materials.

 

StefanArisona_21-1632241218856.png

 

 

Then we press Play and the VR experience begins in a virtual planning office with a table that has the 3D model of the city placed on top. While in the office, we can pan, rotate and scale the model as well as change the time of day and sun direction.

 

StefanArisona_22-1632241218904.png

 

 

The experience continues with the possibility to immerse in the model either on the street level, or on top of a building, by pointing and teleporting to desired locations. Also, predefined points-of-interest can be set, and they appear as portals so that we can easily teleport there. While in the city we can explore the design by teleporting around, an experience similar to walking, as well as change the hour of day and light conditions. In addition, different scenarios can be switched and explored during the VR session.

 

StefanArisona_23-1632241218881.jpeg

 

 

StefanArisona_24-1632241218917.png

 

 

Metadata

 

Metadata is information that describes geometric or non-geometric characteristics of specific objects, providing detail and analysis during design workflows. In CityEngine, metadata such as information about cost of elements, material, area, volume type and so on, can be embedded on the shapes during their generation. All reports and object attributes in CityEngine can be converted to metadata upon export, depending on the selection at the General Settings > Export Metadata of the export window.

 

Once the Datasmith file has been imported in Unreal Engine, the metadata of each shape can be found by selecting in the World Outliner the Shape_Root and then in the Details again the Shape_Root (note: not the Shape_Root(Instance)). The metadata information can also be displayed as a pop-up during play-time (option only supported for the CEModelLoader template for the moment). In order to see the pop-ups open the level ‘CEMetadataTemplateScene’ the CEModelLoader Template and that is in the Content folder.

 

StefanArisona_25-1632241218798.png

 

 

Then we import the Datasmith files on that level and click on Play. Once we left click on a shape that has embedded metadata, a pop-up window comes up that displays the embedded information.

 

StefanArisona_26-1632241218848.jpeg

 

 

> You can find more information on metadata in the CityEngine VR Experience Advanced Features document.

Version history
Last update:
‎09-21-2021 09:37 AM
Updated by:
Contributors