ArcGIS CityEngine Blog

Showing results for 
Show  only  | Search instead for 
Did you mean: 

Other Boards in This Place

Latest Activity

(50 Posts)
Esri Contributor

The CityEngine team is happy to announce the release of PyPRT 1.5, a maintenance update which adds support for the latest CGA features from CityEngine 2021.1 (and PRT/CE SDK 2.6).

Happy Python hacking ;)

0 0 115
Esri Contributor

Vitruvio 1.1 for Unreal Engine 4.27 using CityEngine SDK 2.4 (CityEngine 2021.0)  is officially released. You can find the latest downloads, documentation, examples and source code on GitHub

Note: Invitation to participate in our Vitruvio survey.


1 0 264
Esri Contributor

We are happy to announce the release of ArcGIS 360 VR for ArcGIS Online 9.4.

In addition, note that CityEngine 2021.1 included usability enhancements for the 3VR exporter, see release notes below.


Release Notes for ArcGIS 360 VR


ArcGIS 360 VR (ArcGIS Online 9.1, April 2021)

  • Initial release of ArcGIS 360 VR as web application


ArcGIS 360 VR (ArcGIS Online 9.2, July 2021)

  • Improved loading experience (e.g. avoid flickering)
  • Minor UX/UI adjustments
  • Bug fixes


ArcGIS 360 VR (ArcGIS Online 9.3, September 2021)

  • Improved handling of subtitles
  • Flipped up/down arrow key direction for scenario selection on desktop
  • Minor UX/UI adjustments
  • Bug fixes


ArcGIS 360 VR (ArcGIS Online 9.4, December 2021)

  • Keep search in gallery when launching and closing an experience
  • Minor UX/UI adjustments
  • Dependency updates
  • Bug fixes


Release Notes for CityEngine 3VR Export


CityEngine 2021.0

  • Preview local 3vr files
  • Export now maintains bookmark order
  • Increased export resolution: cubemap from 1536x1536px to 2048x2048px, preview from 256x256px to 1024x1024px
  • Updated icons
  • Updated documentation
  • Export by default now shares as privet to ArcGIS Online

CityEngine 2021.1

  • Improved render quality; use well-defined render settings
  • Export dialog now allow users to select a viewport to use its settings for rendering

0 0 348
Esri Regular Contributor

Important information about CityEngine 2021.0 workflows involving ArcGIS Urban


2 1 693
by Anonymous User
Not applicable

A simple CityEngine version of tri-planar materials


1 3 1,316
by Anonymous User
Not applicable

Rule that creates a simple pipe network from the street network using primitive shapes. Only attribute is the pipe diameter in meters.



0 0 561
Esri Regular Contributor

Symptoms and Affected Systems:

We experienced rendering issues causing (amongst others)

  • artefacts in the viewport
  • no labels in model hierarchy
  • transparent textures missing or being fully opaque

The issues seem to be related to certain newer AMD graphics cards like the Radeon RX 5XXX series and platform specific drivers. Affected systems include late 2019 MacBook Pro 16-inch models.

If you experience problems like the issues above try the following workaround (needs CityEngine 2020.0 or newer):



  1. Make sure the latest graphics driver is installed.
    If rendering issues are still present, continue with step 2.
  2. Open the configurations file CityEngine.ini  (requires admin privileges)
    1. Windows: Open the C:\Program Files\ArcGIS\CityEngine2020.0\CityEngine.ini  in a text editor.
    2. Mac: In the Finder, Right Click on the CityEngine2020.0 application > Show Package Contents
      then navigate to
      Contents > MacOS > CityEngine.ini  and open in a text editor.
  3. Enforce blending transparent content, by adding the following line to the CityEngine.ini  file:
  4. Start the CityEngine application

0 0 2,202
by Anonymous User
Not applicable

Updated May 6, 2020 - scroll down

Had City Engine for close to 3 months now, and one of my early CityEngine ideas was to create a procedural stream restoration code.  With just a few hours of work, I have been able to figure out some code that gives me a lot of promise that City Engine can in fact be of major use to stream restoration project planning.   Just would like to share and maybe gather some ideas from those interested.   I do intend to share my code at some point, minus the textures and assets because they are not mine.

Just to preface this work, Cincinnati, Ohio had the Army Corps come through and destroy our Mill Creek in the name of flood control.  My version of stream restoration is an intervention to this:

Concrete Channelized Mill Creek

To start,  I envisioned that the street creation tools could simply be transformed into stream creation tools.   And to my delight they can.

Using Street Creation tools for Stream Creation

The sloped stream banks are handled quite effectively by a CGA roofshed operation.

The next important step was seeing how the street handled the variations in street widths and sidewalk widths.  I've had to adjust the street junction precision between 0.1 and 1 to get the best results depending on the connection.  The image below shows a precision of 0.1, which equals one shape per intersection. 

Stream Width and Riparian Width Tests

I also wondered how the street tools would look when using them to merge streams:

Streams merging in CityEngine

It's kinda clunky, just like the streets are but I think I might be able to play around with the "freeway merge" to get more natural looking stream merges.   

Another important step towards getting the stream and riparian corridor interventions I would like to incorporate was seeing how the sidewalk splits would work.    I took a quick look at the Complete Streets sidewalk code and a simple split(v,unitSpace,0) was all that was necessary to get some divisions between the stream bank and a riparian corridor (and a second bank and riparian area).

Stream Bank UV splits

The scatter tool is quite effective for creation of stream boulders and stream-side vegetation instances.  For the boulders it sort of simulates the riffle --> pool --> riffle --> pool patterns of streams.  And for the plants it can be used to put them at streams edge (like a surbmersed plant) or top of stream bank.

Stream Restoration image

Where I envision spending a lot more time is on finding textures and 3D models that  represent the local stream bank conditions (plants, stream hydrology, infrastructure).   We have vertical crib walls and other unique stream bank conditions that could be modeled and textured.  I also have a list of about 20 stream interventions that I plan to model:  j-hooks, cross-vanes, canopy structures, live stake plantings, rip-rap, log/brush shelters, wetlands, vegetated gabions, etc.    Also, I want to add some color coded themes for riparian invasive species scenarios  (red plants = bad invasives / green plants = natives).   So much to do...

Textures representing Wood Slatted Crib Wall

Another quick trick I learned, put a little water caustic texture in your waters "material.bumpmap" to get a slightly better looking water in City Engine.  That's probably 3D "class 101" to some, but not to an urban planner like myself.

Lastly,  I haven't exported anything to Unreal Engine yet, but I fully expect to and to use the vegetation and rock instances so they can be replaced with higher quality models and textures.  At some point, I also hope to figure out the water mechanics of UE4 to simulate a flowing stream with the particle effects of water hitting the rocks. 

 I'll update this blog at some point to feature my progress.

Thanks for looking!  Your thoughts are appreciated.


May 6, 2020 Update:

Made a few updates to my vision of a Stream Restoration CE Code that I felt like sharing...

Before Covid hit I was planning to meet with some stream restoration experts to go through this program as a tool for their work.   Collaboration with them will make this even better and give me more direction for modeling and metrics.

Rip Rap Banks

Rip-rap banks were kind of a breeze using CityEngine.   Just did a uniform scatter operation based on the shapes geometric area to fill the space. 

Purpose:  reducing flow velocity, stabilizing bank, providing spaces for sedimentation deposition, etc.

Potential metrics for Dashboard:   number of rocks needed to fill area, total cost of rocks, increased roughage of stream bank, other?

Rip Rap Bank in CE

Vegetated Geogrids

Vegetated geogrids in CE required me to model a shape in Blender that could be repeated.   I imported the model into CE as a textured fbx.

Purpose: stabilizing the stream bank, re-establishing bank vegetation, reducing flow velocity, etc.

Potential metrics for Dashboard:  area of Geogrid,  costs of Geogrid for project, increased roughage of stream bank, habitat index improvement,  other?

Vegetated Geogrid in CE

Vegetated Geogrid Image

Brush Mattress

Brush mattresses required some outside modeling for insert objects. 

Purpose: stabilizing bank, re-establishing bank vegetation, reducing flow velocity, etc.

Potential metrics for Dashboard:  number and cost of live branches,  number and cost of dead log toe or rock toe, roughage of stream, habitat index improvement, other?.

Brush Mattress

Brush Mattress Example

(still want to animate the change over time on this one and create a toe rock variant)


Purpose: J-Hooks used to deflect flow away from eroded banks and creates a pooling featuring behind the hook for fish habitat.

Potential metrics for Dashboard:  number of j-hooks per section of stream, number and cost of rocks, habitat index improvement, other?



Purpose: cross vanes channel water toward the center of the stream and create a pool feature.

Potential metrics for Dashboard:  number of cross-hooks per section of stream, number and cost of rocks, habitat index improvement,  pool-riffle pattern change, other?

Cross Vane Example CE

Stream Bank Regrading

Purpose:  increase cross-section stream capacity and regrade stream banks to prevent erosion.

Potential metrics for Dashboard:  difference between current and project stream cross section volume capacity, created spaces for bio-engineering (new vegetation).

Overflow Wetland

Purpose:  engineered high flow spill over in heavily hydro-modified stream.

Potential metrics for Dashboard:  volume capacity (diverted flood flows), spill over height, number and cost of vegetation, other? 

Overflow Wetland

I might have a few other things to share but I'll end it here for now.    

Things I am working on or curious about still in relation to Stream Restoration Code:

  • riparian corridors - basing their widths on local stream protection codes or protected status for modeling starting point
  • riparian corridors - basing the canopy on an existing canopy study in infrared and planimetric formats and how best to import or program that data into something CE can use (maybe just as a % canopy per section).
  • riparian corridors - incorporating a prominent invasive plant species (honeysuckle) and modeling its impact by section and across the entire stream.  Incorporating its removal into a habitat improvement index.
  • starting point - what stream data would be the best starting point for a wide audience (to base this code on)
  • stream access - modeling stream access locations for water recreation use - to include canoe and kayak ramps

 I'll update this blog at some point to feature my progress.

Thanks for looking!  Your thoughts are appreciated.

2 1 828
by Anonymous User
Not applicable

Trying to use CGA to create a "rounded N-Sided polygon" turned into a hobby.   One I haven't solved it yet but maybe somebody else will.  I thought I would share my findings to give the next person a head start and so I could remove this "sticky" thought of mine and move on.  At least along the way, I got a bit better understanding of recursive code and parameter initiating.   Understanding parameters seems like the key to breaking apart the intense Complete Streets code so that I can make my own modifications.   

So what's end goal for a rounded n-sided polygon?  Maybe that leftover shape in your parking lot needs to be rounded curbs?  That's my endpoint I guess.  Not quite worth the attention I gave this problem.   Probably much better work-arounds given the tool sets available internal/externally.

From my half circle project I found out that you could rotate the scope after the half circle split but before the "quarter circle" split to produce any obtuse angle.

	split(x){'.5: quarterCircleA|'.5: quarterCircleB}‍‍‍

Angled Cuts

Obtuse Angle

I thought that might be the key to unlocking the next step, an N-Sided Polygon.

As for dividing up the shape to set up the angle splits, intuitively I know it involves radius offset (shown by image below).  And then finding where the circle touches the sides to calculate a angle and applying that back to the angled circle for a cut (including rotation, translation, scope).

Rounded Corner Technique

Image: Stackoverflow - user "dbc"

I dove into the CGA recursive coding techniques and finally started to grasp some of the CGA reference.   After some trial and error I was able to produce this:

Recursive Test on 3 shapes

The red is the starting point for the first shape edge offset, which you have to treat differently than the recursive shapes.  This is because it will create two corners (the one at "0" starting).  The yellow sides are the offsets produced by recursive scope pivots.  The grey is the yellow with a radius/remainder split.  Green circles are inserted into the resulting shapes.  And the light purple is the quarter circle split with no scopeRotation, translation, or rotation applied yet.  I need to figure out how to get the angles and parameter them.  Notice I didn't include a concave polygon.  I think that would require a case/else and maybe a geometryIsConcave test.  Also, the final rotation isn't quite working as the final shapes scope goes beyond the original shape.   Maybe this could be useful itself - for placing something on the inside space of each corner, like a patch of trees?   

Here is the CGA:

 * File:    N-Gon_Rounder.cga
 * Created: 9 Jan 2020 14:45:20 GMT
 * Author:  bwamsley

version "2019.1"

attr CornerRadius = 10
edgeN = geometry.nEdges 
verticemover = 0 



PolygonN(edgeN, verticemover)-->
	case (edgeN) > 1 :
		split(z){~1: RemainderShape(edgeN, verticemover) |CornerRadius : CornerMaker(edgeN,verticemover)}
	else: InteriorShape 

RemainderShape(edgeN, verticemover)--> 
	PolygonN(edgeN - 1, verticemover + 1)

###Creating offsets for Circles

	case (verticemover) > 0:
		split(z){~1: InteriorEdgeShapes (edgeN,verticemover)	|CornerRadius: CircleSpace (edgeN,verticemover)}
		#split(z){CornerRadius: CircleSpace(edgeN,verticemover) | ~1: InteriorEdgeShapes} 
		#split(x){~1: InteriorEdgeShapes	|CornerRadius: CircleSpace} 
		#split(x){CornerRadius: CircleSpace | ~1: InteriorEdgeShapes} 
	else:  StartShape (edgeN,verticemover)

###Starting Edge needs special treatment (two circle spaces required)
StartShape (edgeN,verticemover)-->
	alignScopeToGeometry(yUp,0,1) ###special case
	split(z){~1: StartShape2 (edgeN,verticemover)   ///Goes back to Scope Origin for Split
	|CornerRadius : CircleSpace(edgeN,verticemover)} 

StartShape2 (edgeN,verticemover)--> 
	split(z){~1: InteriorEdgeShape0(edgeN,verticemover)
	|CornerRadius : CircleSpace(edgeN,verticemover)}	
	color("#006994")  ##Blue		

InteriorEdgeShape0 (edgeN,verticemover)--> 	
 	color("#e32636")  ##Crimson

InteriorEdgeShapes (edgeN,verticemover)--> 	
 	color("#FFAA00")  ##Gold	 

####Circle Making
	color("#8db600")  ##Green
	primitiveDisk(32, CornerRadius/2)
	split(x){'.5: halfCircleA (edgeN,verticemover) | '.5: halfCircleB(edgeN,verticemover)}
halfCircleA (edgeN,verticemover)-->
	split(z){'.5: qCircleA (edgeN,verticemover) | '.5: qCircleB(edgeN,verticemover)}
qCircleA (edgeN,verticemover)-->
	color("#b19cd9")  ##LightPurple	‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍


I guess one thing I learned about parameters - just carry them the whole way to make sure.  Also, notice that you can see the actual parameter data in the inspector tree per object as you hover your cursor over it!  That kinda helps to see what your recursive code is doing as you write it and test it.   I didn't see that listed anywhere in the reference.

This is where I got too and maybe someone will figure it out.   

Please share with me if you do!!

P.S. - I don't intend to become a blog writer here!!  Just trying to help others who find the CGA reference as confusing as I do.

0 0 506
by Anonymous User
Not applicable

#CityEngine #quarterCircle #roundedSquares #CGA #roundedBuildings

Once again, I'm a new CityEngine user and didn't see anything describing these findings so I'm going to share:

Taking my "quarter circle" (32 sided disc) studies a step further, I developed CGA for a footprint with four 90 degree corners.  I don't know if I did the best coding ever (more on that) but I got the result I intended in the end.  The code works on squares, rectangles and even circles(?).  But not on oddly angled rectangles or triangles (see bottom and bottom left).  I think this code would work well inside of another "grided" code (x and z splits so that it's all very "sqaure").

To create these shapes I used the primitiveDisc splits as described in my first post.  But each corner gave me some problems so I separated them individually "Z1,Z2,Z3,Z4" and tweaked any translation/pivot issues individually.

Rounded corners on various footprint shapes

 * File:    FourBldgCorners.cga
 * Created: 17 Dec 2019 20:40:03 GMT
 * Author:  bwamsley

version "2019.1"

@Range(min=1,max=100, restricted = false)
attr CornerBendRadius = 20
@Range(min=1,max=100, restricted = false)
attr BuildingH = 20
@Range(min=1,max=100, restricted = false)
attr CornerH = 20


	split(x){CornerBendRadius: CornerBendX1
			|~1				:  BuildingWidth
			|CornerBendRadius: CornerBendX2}
	split(z){CornerBendRadius: CornerBendZ1
			|~1				:  BuildingWidth
			|CornerBendRadius: CornerBendZ2}
	split(z){CornerBendRadius: CornerBendZ3
			|~1				:  BuildingWidth
			|CornerBendRadius: CornerBendZ4}			
/////CornerZ1 (DARK BLUE)

	split(x){'.5 : halfCircleZ1
	|'.5 : NIL}
	split(z){'.5 : quarterCircle1
	|'.5 : NIL}	

/////CornerZ2 (TEAL)
	split(x){'.5 : halfCircleZ2
	|'.5 : NIL}
	split(z){'.5 : NIL
	|'.5 : quarterCircle2}

/////CornerZ3 (RED)

	split(x){'.5 : NIL
	|'.5 : halfCircleZ3}
	split(z){'.5 : quarterCircle3
	|'.5 : NIL}	

/////CornerZ4 (PURPLE)	
	split(x){'.5 : NIL
	|'.5 : halfCircleZ4}
	split(z){'.5 : NIL
	|'.5 : quarterCircle4}

If any one knows of a better way to organize the scopes and pivots to simplify my code, I would be grateful to learn.

Hope this helps some one!!

0 0 468
61 Subscribers