Showing posts with label structure. Show all posts
Showing posts with label structure. Show all posts

Monday, 30 January 2017

Future City: Update 11 - Block Interfacing

Progress on Future City has been slowed by web-site and release preparation work at the moment.  I've split my time about 2:2:1 between Web site, Future City, and Alpha Release preparations.
January push towards Web Site, City demo, and Alpha Release.
This split in attention as well as the pressure of the approaching alpha release means blog posts have been slower forming.  Let's just squeeze out a quick update on the Future City progress...

Future City

At the moment I've been focusing on the support of variable elevation across the city, with each city block having its own height.
Example of blocks with shared connectivity but height discontinuities
This feature results in rather complicated requirements at the interfaces between blocks as well as complicating the process of sub-dividing up the space within them.  As such, it's been quite slow progress working out (a) exactly what is required, (b) how to perform this, and (c) how to implement this.

Requirements

Based on the previous connectivity work which sub-divided the city up into districts/zones and finally blocks, we have already decided on what the connectivity between each block looks like.
Now we need to decide on what the content of the block should be such that it is possible to guarantee that adjacent, separately generated content aligns properly, functions as a seamless transition, and looks plausible.

Inputs

We have the following information about each block boundary:
  • Block location/bounds/size.
  • Access along each side (left/right of opening within any barrier present).
  • Follow the underlying landscape shape, or both share flat ground level at a given height.
  • Connectivity via each side (to the outer most city sides).
  • Variation seed to drive arbitrary design decisions.

Outputs

From this we need to populate the block with rectangular sub regions.  The main problem we are trying to solve here is to transition from a boundary with zero, one, or two accessibility transitions along each side into spaces for content to go that all have single accessibility along each side, these being simpler requirements to satisfy.  Thus the outputs are of the form of Content Spaces with the following properties:
  • Bounds size, orientation and location
  • Surface height within the space (or if we are to follow the landscape)
  • Is it an interfacing piece, i.e. responsible for handling transition to neighbouring block interface? (Edge - one interface along block boundary, Corner - two interfaces along block boundary, Side - three interfaces along block boundary)
  • If not an interface, then an interior piece, with same type all round (flat or landscape)
  • For each boundary interface: Specific flat elevation or landscape following. Do we 'own' this side (are responsible for interfacing geometry). Is this a barrier, i.e. will access be blocked? Is there a barrier to the left/right that we may need to provide transition geometry for?

Test Rig

Since there are a lot of combinations to test in forming this system it is worth generating a set of 'unit tests' with clear visualisation of the inputs and outputs.  By creating a hierarchy of test procedures we can quickly generate tests for all the major side and access combinations.
  • Ownership - all, none, adjacent, opposite
  • Surfaces - all landscape, all flat, mixture
  • Access - Closed corners, all open, all closed (bar one), some on left, some narrow, mixture
Unit tests for a lot of the block interfacing cases
For cases where a specific issue is being resolved there is the option to switch out all but one test scenario.
Example test rig showing corner results produced

Algorithms

I spent a lot of time in Excel playing with block boundary examples and possible approaches.
Playing with block algorithm ideas in Excel
From this I've come up with a lot of ideas, but they seem to be heading towards this sequence of calculations:
First pass at the content space and interfacing algorithm
There are bound to be some changes as implementation proceeds, but this is a good starting point.

Lists

Structured Data

The amount of structured information and variability in generated output finally became too much and I had to stop to add some functionality to help support this.  Previously where several properties about a single thing needed to be conveyed through several procedures it had to be passed individually, and explicitly.  This leads to this specific flavour of spaghetti:
A specific flavour of spaghetti: arrays of connections
The algorithms that were forming to perform the interfacing and content-space generation were heading towards an awful lot of this.  From the requirement analysis above we can see each block has at least seven properties that go together, and each potential output content space has at least six.
Traditionally these would be encapsulated in structures, where a single type is used to express an explicit collection of typed data.  This is something that Apparance will natively support in the future, but it's quite a lot of work, especially on the tooling side where composition/decomposition of structures needs to be handled elegantly.

Variable Quantities

Another aspect of the block interfacing implementation problem is that there are several places where we need to pass a variable number of structures.  At the moment there is no concept of this and we would have to pass a fixed (maximum) number of structures (as individual properties) along with an additional flag expressing whether it was in use.  This forms a very, very unwieldy situation where all sorts of operations, such as combining two variable sized collections, become incredibly complicated, expensive and error prone.  We really need some form of list or array to handle this.

Solution

Both these prospects are really going to cause too much of a headache to work on the already complex problem, so we need support to help this.
Looking at other language for inspiration, we find that both these problems can be addressed by using lists of dynamically typed objects.  If a list happens to contain all the same type, then it is effectively a traditional list or array, i.e. a variable sized collection.  If a list happens to contain a fixed number, of different typed elements then it can be used as a structure.  Adding support for lists as just another base data-type to Apparance is fairly straight-forward and then means we can have lists of lists, or put another way, lists of structures.

Implementation

The List data type was added along with an initial set of basic operators to support what we would need, as follows:
  • Append - take a list and add another element (any type).
  • Get - index a list, returning the element value (any type).
  • Set - replace a value at a specific index with a new value (any type).
  • Count - query how many elements are in the list.
Part of the implementation that took a bit of effort was that I wanted type information to be maintained with them as the lists are constructed.  With this, a lot of validation can be performed during synthesis that would catch problems that would otherwise be very difficult to diagnose and have potential to crash the engine.
Whilst a bit tricky to implement, lists are proving very useful so far and make a lot of the block interfacing problem much more pleasant to work with.
Passing structures and collections around as lists
I am even now using them in the web site building procedures for all sorts of things.

Progress

I'm about half way through the Block Boundary -to- Content Space processing system and have promising results so far.
Some of the content space generation results so far

I'll post more results as I progress.  In the mean-time I have an Alpha Release to get out!

Monday, 31 October 2016

Future City: Update 9 - Apartment Construction

Apartments

I've been thinking about how to build interesting residential apartment buildings, that look more futuristic than just boxes with windows.  A few ideas come to mind:
  • Surface objects  - balconies, air-con units, ducting, etc.
  • Surface projections - bits that stick out, and in-turn have windows/etc.
  • Multi-part buildings - intersecting parts in a cluster, at different heights.
  • Non-right-angle intersections - should be do-able.
  • Buildings on buildings - large rooftops can recursively have smaller/similar buildings on top.
  • Styling - design seed can keep same style among a cluster but different between
We'll see how far this gets us.

Building Units

I started on the apartment buildings by properly subdividing a building block into obvious parts: windows, faces, friezes, separators, corners, parapets, roof, etc.
Procedure injection points on a general building structure.
This can later have a variety of proper alternatives and parts switched in and out to give them their final look.  I wanted the buildings to support intersection, so I added 'opening' parameters on each side, spending some time getting the various combinations of opening needed working.
Rig to test support for openings in the sides of buildings. 'Unit testing for procedures' in a way.
Two main ways to intersect building faces occurred to me:
  1. Clipping - Intersect, working out where the join is and just filling each part with the usual facade (window grid, etc), making some changes to the edges to fit better.
  2. Culling - Intersect, but this time just cull any windows that would become split where the join should bee (replacing them with basic wall).

Clipping has the limitation that you need to intersect at quantised positions otherwise the windows beside and above the intersecting building won't line up, but Culling means you will get areas with no windows.
I thought I'd try clipping first, and with some calculation I was able to get the intersection working.
The clipping approach in action.  Windows scale to fit space.
To support arbitrary angle intersections though the quantising requirement is going to be really hard to meet, so I also implemented the culling approach for comparison.
The culling approach in action.  Windows are removed when not enough space.
Seeing these in operation show's up the main pro's and con's.
The main differences between the clipping and culling approaches to building intersection.
On balance I think the culling approach will be less messy, especially with proper surface materials and objects.

Proper Facade

Switching the placeholder geometry for more interesting design produced some promising results:
Basic design variation examples

Next

 Now I need to look at arranging these together in interesting ways for use in the city:
  • Generating building clusters to fill the city blocks.
  • Populating the surfaces with proper features.
  • Adding some LOD support for full city use.