Street Asset Placement  Help

08-16-2012 07:27 PM
New Contributor III
Here's the puzzel..

I have a street of length x.
I have three models I can randomly select from to insert on that street, the models are of known length (units of 25m).
100, 50 and 25.

I would like to effectively iterate along the road and fill it with assets(inserted at realworld size s(0,0,0)) until the road is full.
Additionally the intention is to have randomly sized gaps between each model.

Here's the bit I'm struggling with..
I would like after each asset placement to the randomly choose from the three models again before the next insert.

How would I do this?
0 Kudos
7 Replies
Frequent Contributor
Placing assets on a street is done easily like that :

Since street shapes have nicely layouted UVs already, use UV-splits to split them along the length and across. Since CGA always must have geometry to work on, the best thing for placement is to cut a thin stripe (give it some room to work on, don't go below 1 cm) on which the assets are supposed to be placed.

markerDim = 0.03

Street --> # or Lane
 split(v,unitSpace,0) { ~1 : NIL | markerDim : Stripe | ~1 : NIL }

Then split this stripe again along it's length, e.g. :

markerDist = 15

Stripe -->
 split(u,unitSpace,0) {{  ~ markerDist : NIL | markerDim : AssetPosition. | }* | ~ markerDist : NIL}

Of course, you want to place the assets in certain distances, so you could come up with a rule ( even recursive ) which uses 'geometry.du' or 'geometry.dv' ( arclength, check docs ).

Let me know if there's questions.

Concerning asset rotation along the curvature, get back to me. That's done fast.

0 Kudos
New Contributor III
Thanks for the response,
but I guess I am not using it as you would regularly. 😉
Okay so I understood the insert rules for streets having studied the modern streets examples they were helpful, and tally with your post.

I needed to create broken streets, I am not using the city engine street geometry as output. 

This is almost the solution, I need to work on the spacing of the instances I am placing as they are currently butted to each other.I would like to space them out a little more, so adding some random variance to one of the splits should do it.

The importance here is the random selection of a new instance at each recursion whilst filling the street.

This is also interesting as it shows how cityEngines Rules generate nodes and get added to the execution stack and how different it is to normal code execution.

 * File:    streetTest.cga
 * Created: 20 Aug 2012 18:28:49 GMT
 * Author:  rhexter

version "2011.2"

//attribute and function to randomly select a street section for insertion
//- lengths are unitized to 25m sections
//- x4 represents the number of lanes, could be a varible
attr streetAsset = "asset"
setStreetAsset = "assets/road_details/Street_"+listRandom("Short;Medium;Long")+"_x4" + ".obj"

// attribute to kick off our knowledge of streetsectionlength
attr streetModelUDim=0

PlaceInstance(asset) -->
  Inserts the selected model asset 
 //Provide some Feedback 
 print ("PlaceInstance: In")
 print ("Placing \"asset\": \n\t" + asset)
 print ("InstanceLength: \n\t" + assetInfo(asset, sz))
 alignScopeToGeometry(yUp, 0, 0)
 r(scopeCenter, 0, 89, 0) // skew'd for easy visual reading of section placements
 print ("PlaceInstance: Out")

PlaceStreetPiece(streetModel, streetModelLen, remainingStreetUDim) -->
  This leaf is recursive:
  In one side of the split it:
   - inserts a preselected model, 
   (because we know the udimension of it and it fits the street) 
   - in the other:
    - it chooses a new random model
    - checks if it fits the remaining street udimension
    - passes it to its-self to place
 print ("*-----------------------------------------*")// iterator section feedback break
 print ("PlaceStreetPiece: In")
   //Place the streetModel previously choosen here, cos we know it fits
   print ("RemainingStreetLength: \n\t" + remainingStreetUDim)
  |// split 

  remainingStreetUDim :
   //Work out our next model to place that will fit within our remaining streetUDimension
   print ("-----------------------------------------")// iterator section feedback break
   print ("-----Try to pick a new Random \"Model\"----")
   set(streetAsset, setStreetAsset) // randomly pick a new model for next iteration placement
   print ("Chosen streetModel: " + streetModel)
    case assetInfo(streetAsset, sz) < remainingStreetUDim:
     // if our chosen model fits, place it
         streetAsset, //the next chosen streetModel
         assetInfo(streetAsset, sz), // streetModelLength
         (remainingStreetUDim-assetInfo(streetAsset, sz)) // the remaining StreetUDimension
     print ("-----------------------------------------")// iterator section feedback break
     print ("StreetModel Did not fit " + streetAsset)
     print ("-----------------------------------------")// iterator section feedback break
 print ("PlaceStreetPiece: Out")
 print ("*-----------------------------------------*")// iterator section feedback break

attr dim = 1.0
attr markerDim=2.0
Street -->
  Begin to fill the streets with streetAssets
  Set an initialModel here:
  - we need know its length
  -- we need this information to setup and pass in 
  the recursive leaf's values
 set(streetAsset, setStreetAsset)
 set(streetModelUDim, assetInfo(streetAsset, sz))
 print ("Start streetAsset: " + streetAsset)
 print ("Start streetModelUDim: " + streetModelUDim)
  ~dim: NIL
   // PlaceStreetPiece(streetAsset, streetModelUDim, remainingStreetUDim)
   PlaceStreetPiece(streetAsset, streetModelUDim, geometry.du(0,unitSpace)- assetInfo(streetAsset, sz))
  ~dim: NIL

0 Kudos
Frequent Contributor
other inputs :

- use fileRandom()
- use modulo function ( 5 % 2 = 1 ) with a recursion index
- if you cannot have overlapping instances, choose a split(x){{split(z)}* }*, then a p() to place stuff on those tiles
- if you cannot have overlapping instances, you could also do a recursive split(x){alignScopeToGeometry "longest edge"} until your shards are small enough ( escape case : case < minSize )
( = strategies from here : )

in general, it depends a little on what you're distributing. if it's stull like bullet holes or rubble, I'd also use scatter(). maybe check the code in the DownTown Damage example too for inspiration. 🙂

if you place stuff 'along a road', I'd rather use my original input plus a certain delta value to distribute 'to the sides'.

lemme know if you need other inputs.
0 Kudos
New Contributor III
Hey was just looking over this again not so sure I understood this specifcally.

- use modulo function ( 5 % 2 = 1 ) with a recursion index
0 Kudos
Frequent Contributor
Had to think a second what I meant. 🙂

It should say 'Recursion index or split.index', meaning just an index which incrementally grows.

If you have 3 assets which need be repeated, you could for example use that index and test :

case index % 3 == 0 : i(asset1)
case index % 3 == 1 : i(asset2)
case index % 3 == 2 : i(asset3)

From what I understood it was your idea to always place the same specific assets regularly among a certain street shape. My input here was to either use a repetitive UVsplit [producing split.index indices] here, or just a recursion which UVsplits the street until e.g. a certain minimal length is reached [producing indices].

Makes sense ?
0 Kudos
New Contributor III
Ah okay I see,
Thanks this could be a useful approach elsewhere!

Strikes me that you could certainly create a set of specific example design patterns for use with the cga language.
It could be most helpful for those wanting to discover possible rule approaches to solve their required outcomes.

"to always place the same specific assets regularly among a certain street shape"
Actually the solution above was too randomly select and place an asset from a given selection set along a street shape with irregular random offset spacings. 😉
Thus the code setups an initial selection(to prime the pump, so to speak) then the next leaf is recursively selecting and placing. But I'm pretty sure there are many ways to approach a similar solution, some probably more elegant that this. 🙂
0 Kudos
Frequent Contributor

It could be most helpful for those wanting to discover possible rule approaches to solve their required outcomes.

That's what I'm here for .. 😉

And yes .. there's many possibilities to do things in CGA. It just takes time to stumple upon them.

Have fun !
0 Kudos