Jabi, Wassim - Parametric Design For Architecture-Laurence King Publishing (2013)

Download as pdf or txt
Download as pdf or txt
You are on page 1of 209

Parametric Design

for Architecture
To Vassiliki, Maye and Sarah

Published in 2013
by Laurence King Publishing Ltd
361–373 City Road
London EC1V 1LR
Tel +44 20 7841 6900
Fax +44 20 7841 6910
E [email protected]
www.laurenceking.com

Design copyright ©2013 Laurence King Publishing Limited


Text copyright ©2013 Wassim Jabi

Wassim Jabi has asserted his right under the Copyright, Designs and
Patent Act 1988 to be identified as the Author of this work.

All rights reserved. No part of this publication may be reproduced


or transmitted in any form or by any means, electronic or mechanical,
including photocopy, recording or any information storage and retrieval
system, without prior permission in writing from the publisher.

A catalogue record for this book is available from the British Library

ISBN 978 178067 314 1


Designed by John Round Design
Printed in China
Parametric Design
for Architecture
WASSIM JABI

Laurence King Publishing


Contents
06 Preface 48 Repetition
49 Tutorial: Fibonacci number generator
08 Foreword by Robert Woodbury
53 Tutorial: Nested polygons
09 Introduction
58 Tiling
09 Versioning
59 Tutorial: Hexagonal tiling pattern
09 Iteration 64 Case study: RK4 Tiles

09 Mass-customization 68 Recursion
70 Tutorial: Nested geometry
10 Continuous differentiation
72 Tutorial: Simple fractals
10 The characteristics of a parametric 78 Case study: Genetic Stair
design system
10 Object-orientation 82 Subdivision
11 Families and inheritance 84 Tutorial: Simple diagrid mesh
11 Methods 93 Tutorial: Deriving a diagrid mesh from
11 Parameters a NURBS surface
12 Case study: Austrian Pavilion 104 Case study: Screen for Eurocont Headquarters

110 Packing
20 PART I: ALGORITHMIC THINKING 112 Tutorial: Circle packing
124 Case study: The Beast
22 Introduction
126 Weaving
22 Overall structure
128 Tutorial: A simple ribbon
23 Data types and variables 136 Tutorial: Weaving a NURBS surface

23 Expressions 152 Case study: nonLin/Lin Pavilion

23 Logic and control 156 Branching


158 Tutorial: Recursive branching
24 Functions
168 Case study: PS_Canopy
24 Iteration and recursion

24 Objects, classes, attributes and methods 174 PART III: NEXT STEPS
25 Events and callback functions 176 Towards a programming language for design
180 Tutorial: Diagrid

26 PART II: PARAMETRIC PATTERNS 190 Tutorial: Weaving

30 Controller 196 A taxonomy of parameters


32 Tutorial: A parametric circle
198 Afterword by Brian Johnson
36 Case study: Aviva Stadium
200 Glossary
42 Force field
202 Bibliography
43 Tutorial: Attractor
204 Index
208 Picture credits
Related study material is available on the Laurence King website at
www.laurenceking.com 208 Acknowledgements
6 Preface

Preface
This book is, in part, the result of a particular frustration for all popular scripting environments. However, one should
that I have harboured for many years. Like many of you, keep an important fact in mind: parametric and algorithmic
I love books about digital design, and I am always impressed thinking is not about any one piece of computer software
by the wizardry of their beautifully illustrated projects and or any one particular syntax, but about logic, geometry,
examples. But by the time I reach the concluding chapters, topology and interaction. If you approach this book with that
I am invariably frustrated to find that these books never idea in mind, then you will benefit from it regardless of the
reveal the mechanisms that yielded such spectacular scripting environment and programming language it uses.
results. The question on my mind – and which I am sure In the first two parts of this book, I decided to present
is often also on yours – is ‘How did they do that?’ the examples using two scripting environments: Processing
When I was approached to write a book about and MAXScript. Processing is a free and open-source Java-
parametric design in architecture, I did not quite know what based programming environment for visual designers. Its
kind of book it would be, but I knew what kind of book it ease of use and simple interface make it suitable for the
would not be. It would not resemble a magician’s show, beginner scripter. It excels in 2D visual design without the
where the magic tricks are spectacular but the secrets of need for any external plug-ins. That is why I chose it for the
their creation are well kept. Instead, I wanted to write a book tutorial on generating the Fibonacci series and a golden
that would explain the algorithmic techniques in parametric rectangle. However, for advanced 3D parametric scripts,
design as well as analyze contemporary case studies that Processing pales in comparison to the power of MAXScript
take advantage of such techniques. I also decided, perhaps and that is why I use MAXScript for the remainder of the
against conventional wisdom, to include full source code for tutorials. I conclude the tutorials with a brief discussion of a
the examples I discuss. This presents three major problems new universal and hybrid programming language for design
(in addition to the fact that the included scripts may not be called DesignScript that was originated by Dr Robert Aish
the most elegant or the most efficient). First, to paraphrase from Autodesk. DesignScript, although still in beta at the
Robert Woodbury’s words, books are a difficult medium time of writing, promises to combine the power of several
in which to discuss computer code. I have to agree; books scripting and visual programming approaches. As in any
are not (yet) interactive and I am hoping electronic books other situation, always look at the problem at hand carefully
will soon solve this problem. Second, there is a danger that and choose the best tool and environment for solving it.
inexperienced readers will simply copy the included scripts To start experimenting with the ideas in this book, one
without investigating them. Third, the scripting environments of the first things you need to do is download Processing
for various 3D platforms differ in their syntax. There isn’t from http://processing.org. MAXScript is the built-in scripting
enough space in a book of this type to present the scripts language of Autodesk’s 3ds Max, a powerful engine for
modelling, visualization and animation. At this point,
even those of you who are familiar with those uses for 3ds
Max might be thinking, ‘I didn’t know 3ds Max even has
a scripting language.’ In the field of parametric design in
architecture, MAXScript is perhaps 3ds Max’s best-kept secret.
It is an extremely useful language that has the ability to
expose and extend 3ds Max’s functionality in powerful ways.
I have to note here that I have no affiliation with Autodesk nor
would I derive any benefit from recommending its software.
The fact that I have chosen Processing, MAXScript and
DesignScript as the scripting platforms for the tutorials should
be of little consequence. Any code, if well explained, can be
generalized into an algorithm and that algorithm, in turn, can
be re-written using a different syntax for a different system.
In this book, I will give you both the code and the algorithms,
first by presenting functional scripts for a particular platform,
so that you can try them out and see immediate results,

fig. 1 A systematic design exploration of


two parameters: tapering and twisting.
Preface 7

fig. 2 Soumaya museum, 2011, Mexico


City, Mexico, Fernando Romero.

and second by explaining them in detail, so that you can Once you have mastered these tutorials, you are expected
generalize and expand on them regardless of your computing to find ways to expand and customize the provided code
environment. This book does not assume that you are a casual and use the presented ideas to suit your purpose.
and passive reader, but an active one looking to solve a design Finally, you might be wondering why this book does
problem in your practice or school using an algorithmic not include any visual programming techniques. There are
approach. However, becoming an expert in parametric two reasons for that: a) the web is teeming with resources
design – and scripting in particular – is a journey that can take and ready-made examples for visual programming, and
months, if not years. This book should be thought of as only b) when you hit the limits of these systems and require
one step in that process and a tool in your chest of resources. customized code, you will find that there is a dearth of
This is a book for what I would call advanced beginners. well-explained online resources for architects and visual
To get the most of out it, you should already be familiar designers. This is where books such as this one are most
with 3D modelling and geometry. It does not include any effective. They teach you the algorithmic logic behind built-
discussion of what a coordinate system is, what vector in parametric and generative components so that you can
maths is or what matrix transformations are. It covers the write your own or augment them with custom scripting.
concepts of programming at a basic level that allows the Before you embark on this journey, I want to offer my
reader to follow the tutorials, but not much more. To gain apology in advance for any errors or omissions in the book
a better understanding in this area, I highly recommend and for any lack of clarity you may encounter. Scripting,
three books in addition to this one: Elements of Parametric algorithmic thinking, parametric design, programming
Design by Woodbury, Architectural Geometry by Pottman logic, geometry and trigonometry are all not easy things to
et al, and Processing: A Programming Handbook for Visual absorb in the span of one book, but once you have mastered
Designers and Artists by Reas and Fry. Yet, the tutorials in them they are incredibly powerful design tools. I wish you
this book are purposely kept simple and self-contained so a productive and, most importantly, enjoyable journey.
that they are instructional, clear and can be completed in
one session without a need to reference outside resources.
8 Foreword

Foreword by Robert Woodbury


To design well is to be in joyful flow. All good designers explicitly as the central form-making idea in a design. If you
make copious – indeed massive – piles of media as they can do all these things, you are beginning to understand.
work. Somehow, from this mass of sketches, models and Be even more careful with the second gift! It shows
prototypes, something new emerges. To be a good designer, you success, but not the hours of joyful work invested in it.
it has always been necessary to become an expert in the Look beyond the surface glitz. Contemporary computer-
crafting of many different media, and today those crafts aided design and visualization systems make enticing
are mostly digital. Craft is always learned by doing and renderings easy. Look for depth, for places and forms in
polished by practice, but these tacit acts are not sufficient. which parametric ideas meet the design situation to create
Designers must know the concepts that underlie the forms the ineffable ‘good’ in ‘good design’. Then try it yourself.
of media they use. In today’s digital media, it is primarily Let parametric models tell you the most they can. To do
symbols, algorithms and programs that form the language this, you enter the cycle of design, in which you make, look,
through which we come to know what we are doing. In reflect, change and make some more. Eventually, you will
this book, Wassim Jabi gives two gifts to the field of design. find a resolution and will be a stronger designer for it.
First, through many code examples, he builds a crucial and There are too few books like this one. It lies between
explicit practical knowledge that can be used to navigate the mass of user manuals that show technique without
the complex computer-aided design system. Second, he design and the picture books that show design without
takes us on a wisely guided tour of contemporary design technique. By joining the two, Jabi opens a gate to
that has been shaped by the new parametric craft. new possibilities. He does not – and cannot – show
Be wary of the first gift – indeed you should be wary what lies beyond the gate. That is for you to discover,
of any computer program so offered! Using code well through joyful work with parametric design.
requires thought and work. In the hurly-burly of design,
you will be tempted to use Jabi’s code quickly, as it is or
with slight modification. This is fine, as long as you also,
at some point, take the time to understand why the code
works and, more importantly, why Jabi chose it and how he
explains it. Try this. Explain it to yourself. If you think you
understand it, explain it to a friend. If you can do that, use it

fig. 3 Antoni Gaudí's hanging chain catenary


model at Casa Milà, Barcelona, Catalonia,
Spain. Gaudí frequently used hanging chain
models to derive the structure of his projects.
View the image upside down to see how this
model translates into the actual project.
Introduction 9

Introduction
The architectural design process is almost always iterative. all the way, penetrating into all corners of the discipline.
Designers create solutions that, in turn, pose new questions, Systematic, adaptive variation and continuous differentiation
which are then investigated to generate more refined or (rather than mere variety) concern all architectural design
even entirely new solutions. Designers often use computer- tasks from urbanism to the level of tectonic detail. This
aided tools to build models and help them visualize ideas. implies total fluidity on all scales.’2 He points out that
However, the vast majority of these models are still built in the fundamental themes in parametric design include
such a way that they are difficult to modify interactively. versioning, iteration, mass-customization and continuous
The problem becomes more severe when bespoke 3D models differentiation. It is helpful to briefly define these terms.
are geometrically complex. Changing one aspect of such a
model usually requires extensive low-level modifications to
many of its other parts. To address this problem, designers
Versioning
have begun using parametric design software, which allows Borrowed from the software development field, the term
them to specify relationships among various parameters of versioning refers to the process of creating versions – or
their design model. The advantage of such an approach variations on a theme, if you will – of a certain design
is that a designer can then change only a few parameters solution based on varying conditions. Parametric software
and the remainder of the model can react and update allows the designer to create a prototype solution that,
accordingly. These derivative changes are handled by the rather than being cast in a static CAD file format, is wired –
software, but are based on associative rules set by the almost as a string puppet would be. This wiring allows the
designer. Associative and parametric geometry, in essence, design solution to be tweaked and manipulated, creating
describe the logic and intent of such design proposals rather new versions when new forces and conditions arise.
than just the form of the proposal itself. This kind of design
both requires and helps to create powerful interactive tools
that allow designers to explore and optimize a multitude
Iteration
of possibilities while reducing the amount of time it takes Again borrowed from the software development field (see a
to do so in a rigorous manner. Engaging these parametric pattern here?), the term iteration refers to cycling through or
and algorithmic processes requires a fundamental mindset repeating a set of steps. In the case of parametric architecture,
shift from a process of manipulating design representations iteration can, in principle, create variation at every pass
to that of encoding design intent using systematic logic. through the same set of instructions. Examples may include
Algorithmic thinking calls for a shift of focus from achieving varying the size and shape of a floor plate as one builds a
a high fidelity in the representation of the appearance of a skyscraper, or changing the angle of a modular cladding
design to that of achieving a high fidelity in the representation system as it is tiled over an undulating surface. In addition
of its internal logic. The advantage of algorithmic thinking to producing variation, iteration can be a powerful tool for
is that it can build ‘... consistency, structure, coherence, both optimization and for minimizing the time needed to
traceability and intelligence into computerized 3D form’.1 achieve that optimization. Using a fluid parametric system,
Parametrically and algorithmically built models can react with which can give immediate feedback, a designer can generate
high fidelity to their real-life counterparts when subjected not solutions and test them rapidly by iterating through many
only to user changes of geometric parameters, but also to possibilities, each created with a different set of parameters.
structural forces, material behaviour and thermal and lighting
variations, as well as contextual conditions. Because they
accurately represent the internal construction logic of the
Mass-customization
structure at hand, parametric models can also be unfolded or One of the main successes of the industrial revolution
translated into geometries that can be digitally fabricated. is the idea of mass production. Factories and robots
This powerful digital workflow of parametric form- are able to produce thousands of copies of the same
finding that is influenced by design intentions as well prototype. However, given the advent of digital fabrication
as performance analysis and digital fabrication logic technologies, we are now able to change the manufacturing
is one of the defining characteristics of current digital instructions between each object. Given that the process
architectural practice. Contemporary architects, such as
Patrik Schumacher, partner at Zaha Hadid Architects, have
1 Terzidis, K. Expressive Form: A Conceptual Approach to Computational Design.
gone as far as coining parametricism as the name of a
Routledge, 2003.
new movement in architecture following modernism. He 2 Schumacher, P. Parametricism – A New Global Style for Architecture and Urban
writes: ‘We must pursue the parametric design paradigm Design, AD/Architectural Design – Digital Cities, Vol. 79, Iss. 4, July/August 2009
10 Introduction

is parameterized and robotic, it often costs the same to A parametric system usually stores these objects in an object-
mass-customize the manufactured products as it does to oriented database that can be accessed, searched
mass-produce the same quantity of identical products. and modified.
Each object then has values that determine its attributes.

Continuous differentiation For example, a circle will almost always contain an attribute
called centre or position and another one called radius [fig.
Another borrowed term, this time from the field of 4]. It will also probably contain an attribute called name
calculus, continuous differentiation alludes to a feature of that identifies the circle. It is usual for a certain value of an
versioned, iterative and mass-customized parametric work object to be represented with reference to the object and
that allows for difference to occur within a continuous attribute with which it is associated. A popular notation is
field or rhythm. As opposed to mere variety, parametrically to use a full stop to separate an attribute from its parent
varied instances within an overall group, curve or field object: object.attribute. Thus, if one wishes to reference
maintain their continuity to other instances before and the value of the radius of a circle named circleC, one might
after them while uniquely responding to local conditions. encounter the following term: circleC.radius. Similarly, the
X-axis position of the same circle could be the X attribute of

The characteristics of a the position attribute of the circle, as in circleC.Position.X, and


the Y-axis value could logically follow as circleC.Position.Y.
parametric design system Values can either be constants (e.g. 100 m) or functions,
which need to be evaluated to compute a final value.
The question then becomes, what is a parametric design The power of a function in the value placeholder of an
system, and how can it help improve the design process attribute is that it can derive its value from the values of
or more rigorously explore possible design alternatives? other attributes, which can belong to other objects. Consider
In addition to the themes defined above, all parametric the following hypothetical function of a radius of a circle:
design systems share several characteristics and have similar
constructs: object-orientation, classes or families, methods and, C.Radius = distance(PointA, PointB)
of course, parameters. Let us briefly define these concepts.
The above expression specifies that the radius of a circle is not
Object-orientation a constant number, but is derived from the distance between
Modern parametric software usually uses an object-oriented two points (PointA and PointB). In such a case, we call the
approach in its design. Object-oriented programming is a variable C.Radius a dependent variable as it depends on other
well-established computer science topic that is beyond the values. We also describe such constructs as associative – as
scope of this book, but a brief description is in order. in associative geometry. Association of parameters with one
The user interacts with a parametric system in a manner another allows us to derive unknown entities from known
that reflects its internal algorithmic structure, by creating and ones. In the above example, if the distance between the
modifying objects such as circles, spheres, doors and walls. two points ever changes, the circle’s radius will change

Objects
CirdeC
Transform : Position/Rotation/Scale
Position : Position XYZ
X Position : Bezier Float
Y Position : Bezier Float
Z Position : Bezier Float
Rotation : Euler XYZ
Scale : Bezier Scale
Object (Cirde)
render_thickness
render_sides
render_angle
render_width
render_length
render_angle2
render_threshold
Radius

fig. 4 The attributes of a circle in fig. 5 A family of Scottish doors.


Autodesk’s 3ds Max software.
Introduction 11

accordingly. We call this feature of updating the value of one The system can simply tell a circle to draw itself – or it can
object based on changes in other values propagation. Imagine ask a door to reverse its opening. In a modern parametric
a large network of wired or associated values. A change system a typical object, even one as simple as a sphere,
in one or few parameters would propagate through the can have many parameters and methods [fig. 6].
whole network, modifying the values of attributes and
changing the characteristics of the final design solution. Parameters
This is the power of an associative parametric system. At the heart of any modern parametric system is the
Objects, attributes and values are associated with one term parameter and so it would be wise to define that
another and parameterized so that a change in the value of term at this point. The word parameter derives from the
one parameter can have ripple effects throughout the design. Greek for para (besides, before or instead of) + metron
(measure). If we look at the Greek origin of the word, it
Families and inheritance becomes clear that the word means a term that stands in
Objects that share certain characteristics can be organized for or determines another measure. The word parameter
as members of a class or family of objects. A class or family is often confused with variable, but it is more specific. In
of doors [fig. 5], for example, can contain many individual mathematics parameter is defined as a variable term in a
family members (hinged doors, sliding doors, folding function that ‘determines the specific form of the function
doors, etc.). The advantage of grouping several objects but not its general nature, as a in f (x) = ax, where a
into a family is that they can then share certain attributes determines only the slope of the line described by f (x)’.3
with their siblings and inherit certain attributes from their In parametric CAD software, the term parameter
parents. It is much more efficient to organize these shared usually signifies a variable term in equations that determine
attributes only once, in a parent object, than to have to other values. A parameter, as opposed to a constant, is
customize all the attributes and values for each offspring. characterized by having a range of possible values. One
of the most seductive powers of a parametric system is
Methods the ability to explore many design variations by modifying
In an object-oriented system, methods are functions and the value of a few controlling parameters [fig. 7].
algorithms that act on an object by modifying its attributes. The remainder of this book presents a series of
Rather than have a large set of centralized instructions that parametric design patterns of increasing complexity followed
specify how to draw circles, squares and triangles, an object- by exemplar case studies that reflect the potential of the
oriented system delegates, encapsulating these instructions associated patterns. The book ends with a discussion of
in the class or family of each object. How an object is to the future of parametric design and its potential to form
be constructed or modified is thus encoded as a method a language of design. The afterword by Brian Johnson
in the object itself. In the case of a circle, one such method closes the discussion with advice on how to craft new
could be to construct the circle by specifying the position solutions, based on knowledge gleaned from this book.
of its centre and the value of its radius attribute. Another
method could be to specify three points that circumscribe it. 3 From http://dictionary.com

Parameters

Radius: 0.0m
Segments: 32

Smooth

Hemisphere: 0.0

Chop Squash

Slice On

Slice From: 0.0


Slice To: 0.0

Base To Pivot
Generate Mapping Coords.
Real-World Map Size

fig. 6 The parameters and creation method fig. 7 In the Matière à Rétro-projeter! (Material Projects)
options of a sphere in Autodesk’s 3ds Max. exhibition at the Centre Pompidou, Paris, France, young
visitors affect a regular field of light and shadow patterns as
they move in front of it.
12 Introduction

Case study Austrian Pavilion, Shanghai, China


Designer SPAN Architecture & Design
Client Austrian Government
Design 2008–09
Construction 2010

The Austrian Pavilion was designed and built Baroque formal tradition, which is characterized Above
for the Shanghai Expo 2010, a forum that has by a sensual, curvilinear iconography, and by a Night view of the pavilion from the southeast.

traditionally served as a scene for the trial and new ability to extend these forms to infinity. Finally,
Opposite
display of experimental forms and avant-garde computer technology, with its ability to reveal Daytime view of the pavilion from the southwest.
architectural ideas. The pavilion was designed by dormant forms through algorithmic and generative
SPAN (Matias del Campo & Sandra Manninger), processes, is the main method they use in order
in collaboration with Zeytonoglu, a Vienna- to generate and compose their design proposals.
based architectural firm. SPAN brings a new The firm’s general views, outlined above, have
approach, informed by contemporary issues, found an expression in the design of the Austrian
to an appreciation of the ‘opulent repertoire of Pavilion, a project for which it was commissioned
formations’ that they find in nature. This approach after winning an architectural competition in 2008.
derives from the firm’s close attention to three ‘The main driving force behind the design’, the
‘desires’, as they put it. First, they strive to firm argues, ‘can be described as acoustic forces
explore architectural form and its corresponding or more accurately as music. Music as a concept
underlying geometry in relation to animated matter that reflects continuity in terms of architectural
and material. Second, they are inspired by the articulation that seamlessly connects the various
14 Introduction

Right
View of the staircase.

Below
The pavilion’s red room.
Introduction 15

Below
Ground, first-floor, and roof plan drawings.
16 Introduction

Right
Sectional drawings.

spaces within the programme.’ Beginning with this fluidity. This is most clearly expressed in the spatial skin. The organic fluid form of the building
thesis, and using TopMod software, the designers continuity of the interior and in the seamlessly resulted in a continuous, curvilinear surface
devised a topology: a computerized mathematical flowing surface between the interior and the that is interrupted only at the points of entry.
construct endowed with spatial properties (such exterior. It is also present in the smooth functional For the cladding of this surface, the designers
as seamless circulation, a recessed entrance transition between some of the interior spaces as applied a tessellation method. This led them to
and roof garden, and a separate entrance for a well as in the arrangement of the core spaces, the adoption of very small, hexagonal porcelain
restaurant) that could be maintained even while the including the exhibition spaces of the ground floor tiles, and it also allowed them to manipulate the
topology underwent subtly varying transformations and the restaurant facilities on the first floor. colour of the tiles across the surface. The final
such as deformations, stretching or twisting. The Employing a comprehensive approach, the exterior comprised ten million tiles, transitioning
software produced a number of alternatives that architects designed and produced the main from white to red over the building’s surface,
were evaluated according to functional, structural pieces of furniture and other interior features emphasizing both its stable placement on
and aesthetic requirements. This process greatly (ceilings, openings, etc.) using CNC-milled the ground and its biomorphic curvature.
reduced the number of acceptable solutions; polyurethane that was first coated with a synthetic
the remaining designs were again run through resin and then highly polished. The process
a series of algorithms (various re-meshings, allowed a precise construction of highly complex
subdivisions, optimizing the size of spatial pockets) curved objects that had been initially digitally
that led to the final layout of the pavilion. designed and then visualized in 3D models.
The main aesthetic quality with which the The designers also employed an algorithmic
designers sought to endow their project was approach to the treatment of the pavilion’s
Introduction 17

Right
View of the main hall.

Below
View of the VIP bar.
18 Introduction

Right
View of the gift shop.

Below
View of the restaurant.
Introduction 19

Above
View of the exit space.
PART I ALGORITHMIC
THINKING

22 INTRODUCTION

22 OVERALL STRUCTURE

23 DATA TYPES AND VARIABLES

23 EXPRESSIONS

23 LOGIC AND CONTROL

24 FUNCTIONS

24 ITERATION AND RECURSION

24 OBJECTS, CLASSES, ATTRIBUTES AND METHODS

25 EVENTS AND CALLBACK FUNCTIONS


22 Algorithmic thinking

Introduction
‘From the time of ancient Vitruvian geometric ideals clear and readable, and this is where a book such as this
to modern Corbusian regulating lines and Miesian becomes useful. The elegance, modularity and readability
modular grids, architecture has always been bound of an algorithm usually have a direct relationship to its
to (if not by) a conscious use of numbers.’ ability not only to produce elegant design solutions,
Brett Steele (‘Weapons of the Gods’ in The New Mathematics but also to be understood and modified by others.
of Architecture by Jane Burry and Mark Burry) The good news, however, is that most designers
wishing to use parametric techniques usually need
Rather than rely on an intuitive search for a solution, to solve a relatively small and well-bounded design
parametric design often involves precise, step-by- problem (unlike software developers, who create large
step techniques that yield a result according to rules and complex software products). For example, they
and inputs. This way of thinking about the process of might need to create a parametric building façade or
design as a rigorous rule-based system is referred to a roof structure. They might need to mimic a natural
as algorithmic thinking. As Steele’s quote above hints, phenomenon to create a design concept for their
mathematical knowledge and algorithmic thinking project. Algorithmic thinking allows designers to
have always been the traits of an architect, certainly rationalize, control, iterate, analyze, and search for
at least since the times of the ancient Egyptians and alternatives within a defined solution space. In the
Greeks. Today, individuals who wish to use parametric next section, we will explore the basics of algorithms.
design in architecture find themselves faced with the This brief introduction cannot replace a full discussion
challenge of learning algorithmic concepts (as well of algorithms and the inner workings of computer
as mathematics) that are more familiar to software programming languages. For that information, there is
programmers than to designers. Behind every piece of a plethora of books on programming, online resources
software is a set of precise instructions and techniques and university courses that are dedicated to this topic.
that interact with the user, respond to events, and read,
manipulate and display data. Collectively, we call these
instructions and techniques algorithms. Derived from
Overall structure
the name of a Persian mathematician (Muhammad A traditional scripting environment is usually text-
ibn Musa Al-Kwarizmi), an algorithm is defined as a based. It provides an empty file to write out algorithms
set of precise instructions to calculate a function. An (steps) to perform a variety of operations. You type in the
algorithm usually takes input (which can be empty algorithm using very precise syntax. Any omissions, even
or undefined), goes through a number of successive something as small as a parenthesis or a semi-colon, can
states, and ends with a final state and a set of outputs. cause errors. The help files will instruct you in the syntax
Learning programming concepts does not necessarily and peculiarities of the computer language you choose
ensure that a designer will learn algorithmic thinking. (e.g. C, C++, Java, Python or MAXScript). All computer
The challenge is not dissimilar to learning cooking: languages will allow you to insert comments that are
one can learn the basics of mixing ingredients, heating, not interpreted as computer instructions. Comments
baking and so on, yet there is no guarantee of becoming are usually enclosed by the notation /* and */ (/* this is
an accomplished chef. As with most things, it takes a a comment */ ) or, for single lines, by the characters -- (
love for the craft, a methodical mind, some talent and, -- this is a comment). Each language will have its own
most importantly, practice. The metaphor also applies to syntax for how to indicate that something is a comment.
the process itself: in the same way that cooking recipes Comments allow you to explain to yourself and others
vary in complexity, elegance and the taste of the final what the code is doing at that point. I made the difficult
result, algorithms also vary in complexity, elegance, decision to remove the comments in some of the provided
and the aesthetic and performative characteristics code examples due to space limitations, but also because
of the resulting design solution. While some recipes the code is explained in the main text of the book. Your
are invented from scratch, most are modifications of code, however, should always be clearly documented with
and variations on older recipes. The same applies in comments within the code itself. Computer languages
parametric design. The Internet is teeming with open- differ in their readability and some lines of code may look
source algorithms that are offered for others to learn very cryptic, so comments can explain what is going on.
from, modify and expand. Beware, however, of the Once complete, the scripting environment will
microwave variety: algorithms and definitions that are provide you with a menu item or button to execute the
pre-packaged such that you cannot investigate and script. When a script is executed, it is interpreted by a
modify them. These types of algorithms are not always computer interpreter or compiler in order to produce
Overall structure 23

machine code that runs and does all the things you have Array (or list) a special container that stores many
asked it to do (e.g. display buttons and checkboxes, variables and items. An array can be examined for how
accept user input, create and draw geometries). If the many items it has, what item exists in a certain row
interpreter encounters an error, it usually will report that location, etc.
to the user and stop the interpretation process. Robust
computing environments also give you debugging Boolean this is a special number that can have one of
environments that allow you to pause and examine two values: true or false. This is useful to do logic
the code as it is running in order to find errors. operations, as we will see below.
A script is usually made of standard parts: a declaration
of what the script is and does, variables (think of variables Pointer think of a pointer as an address of something
as storage units to store information), functions (specialized else. For example, if you create a box or a circle you can
and self-contained algorithms that accept input, act on it store a pointer to these objects in variables (e.g. b = box(),
and produce output) and interfaces (declarations of what c = circle()). You can then access the attributes of the box
buttons, sliders and checkboxes to display and how to react and the circle by using the variables b and c respectively.
to them). In more modern scripting environments the shift
has been to what is called object-oriented programming There are many other types of variable, as well as
(OOP). In OOP systems, instead of variables and functions larger structures and objects that you may encounter,
you declare full objects that store in themselves their own such as queues, stacks and sets, but the variables
variables and functions (called methods). For example, you above are the most commonly used for storing and
can declare a door object that knows its own dimensions manipulating information.
and what material it is made of. You can ask it to open
and close itself using its publically declared methods and
even enquire of it whether it is closed or open. In addition,
Expressions
objects that are similar are placed in families or classes, In programming languages, an expression is a contiguous
which share overall characteristics that can be inherited series of tokens, variable, and constants that specifies
and, if needed, customized, by the individual object. This how a value is to be computed. For example, if I stored
method of writing scripts has proven to be very powerful, the value 4 in a variable called n then the expression
elegant, modular and capable of being generalized. 2+n will return 6 and the expression 2(n+1) would return
10. In this book, you will encounter code that may look

Data types and variables unintuitive, such as a = a + 1. That does not mean that
a is equal to itself plus 1 (which is impossible), but that
As we said above, a variable is a storage unit in which the interpreter should add 1 to a and then store the result
to place a value. When we store that value in a variable, back in a itself. This is very useful for counting numbers.
we can recall it later in the code by using the name of
the variable. The script will remember what we stored
in it earlier. You can also change its value at any time.
Logic and control
When writing scripts, we will need to store different As we said earlier, algorithmic thinking is mainly about
types of information: numbers, words, lists of things, logic. When we use logic, we need to be able to assess
circles, rectangles, etc. Thus computer languages a situation and, based on the presented conditions,
allow you to specify what type a variable is when choose from a menu of available decisions. In order
you declare it. Different languages use different code for this to happen, the programming language needs
words for specifying a variable’s type, so you need to to allow us to do two things: first, compare values
consult the user manual to find out what code word to one another and report back the result (which we
to use. The most common types of variable are: call the predicate) and, second, execute one of several
groups of code based on these results. In order to
Integer a whole number that does not have a compare values, computer languages allow you to use
decimal point. This is useful for counting objects. notation for equality (==), inequality (=/ or !=), greater
than (>), less than (<), the logical opposite (not(n) or
Float (or real) a number that does have a decimal !(n)), and the Boolean set operations (and(), or()) that
point. This is useful for measuring things. test whether both values are true, if at least one or the
other is true, and so on. Notice that for testing equality
String (or characters) a string of characters we use two equal signs (==) in order to differentiate
(e.g. words, sentences). This is useful for storing, it from the assignment operation as discussed in the
manipulating and displaying textual information. previous section. If you make a mistake and use one
24 Algorithmic thinking

equal sign in a predicate, then the variable will be


assigned the value and a true result would be returned
Iteration and recursion
regardless. This can lead to serious errors in the script. In many situations, we would need to repeat the same
Making a decision based on a predicate is usually block of code many times. Programming languages
done through what is called an if-then or an if-then- provide special notation for iteration usually called
else statement. That is, if something is true, do this, for loops or while loops. Imagine, for example, creating
else (i.e. otherwise) do that. Here is an example: a row of squares. Each square is drawn with the
same code but given a different location. In such a
1 If (n < 4) then case, we can combine a for loop with the notation
to increment the location variable. For example:
2 (
3 do something here
1 n=4
4 )
2 for i = 1 to n by 1 do
5 else
3 (
6 (
4 drawASquare i*10
7 do something else here
5 )
8 )

The above code would iterate the variable i from 1 to

Functions 4 and execute the code that exists between ( and ) four
times – each time with the value of i automatically
In order to keep the code manageable and readable, increased by 1. The imaginary function drawASquare
we often need to combine several coding steps in one would then draw a square at a location that is 10
group. If you find yourself repeating the same code multiplied by i (i.e. 10, 20, 30 and 40). Much as the
multiple times, that is an indication that you should moon orbits around the earth while the earth orbits
write it once as a function and call it on demand as around the sun, you can nest for loops inside one
many times as you need. A function is assigned a name, another to create multi-dimensional solutions (fig. 8).
accepts input in the form of function arguments, and Recursion is a special case of repetition and
produces a result via return values as well as by storing function calling where a function calls itself for the
values in global variables. For example, imagine that next iteration. Recursion can be difficult to grasp; it is
you repeatedly need to write a function that squares somewhat akin to placing two mirrors opposite each
a number, adds another number to it and returns the other and creating a theoretically infinite number of
result. You could write a function that you would give a reflections. Recursion, as you will see later in this book,
name to such as squareAndAdd and define it as such: is essential for fractal geometry and branching.

1 fn squareAndAdd x y = Objects, classes, attributes


2 (
and methods
3 return (x*x) + y
4 ) As mentioned above, modern scripting environments are
object-oriented. They encapsulate attributes and methods
in larger structures that are called objects. Objects that share
Once the function is defined, we can call it and assign similar features are grouped in classes. Rather than storing
the result to a variable by writing z = squareAndAdd x y. an attribute or a method in each object, these can be stored
The function would then take the value x and multiply in the higher-level class and inherited by the member of the
it by itself, then add y to it and return a value that would class when needed. Consider, for example, the MAXScript
then be stored in z. In MAXScript a function is defined object box. Assume you have asked MAXScript to create a
using the built-in word fn. The actual syntax varies from box and you stored a pointer to that box in a variable called
one programming language to another, but the basic b. We can then ask b for its width and height by evaluating
principle holds true: you can encapsulate any number the expression b.width and b.height. This dot notation
of steps in one function, which can then be called with allows us access to the pre-defined attributes of an object.
input arguments and evaluated for return values. We can use the same dot notation to change the value of
the attribute (e.g. b.width = 10). Some objects also have
Objects, classes, attributes and methods 25

methods associated with them, and these methods can be example, if you have defined a button called generate,
inherited. For example, in MAXScript, all objects belong MAXScript allows you to react to the event of the button
to a class called node. A node knows how to move itself. So having been pressed, using the following syntax:
you could ask a box named b to move itself 10 units in the
x direction, 5 units in the y direction and 20 units in the z 1 On generate_button pressed do
direction, by issuing the command move b [10,5,20]. You
2 (
could issue the same command to cylinders and spheres
because they too belong to the node class of object. 3 generate the geometry
4 )

Events and callback


functions This function, in your own code, would only be called
and executed if the user presses the generate button.
A modern scripting environment that has a graphical user As mentioned earlier, this chapter covers only
interface usually gives you the ability, in your own code, the basics of algorithmic concepts at the simplest
to react to user events or actions (e.g. the user has clicked level. In no way does it substitute for a full study
a button or changed a value in the interface). In order of programming languages, syntax, object-oriented
to respond to these events, the scripting environment methodology and the capabilities of the particular
asks you to define a function that is given a pre-defined scripting environment. However, if pressed for time,
name. This is called a callback function because it gets you now know enough to read and understand
called back from the system into your own code. For the tutorials discussed in the next chapter.

for i = 0 to 4 by 1 do
(
fig. for j = 0 to
8 Composed 4 by 1 do
of two
nested for loops, this algorithm
(
creates an array of cubes that
b = box()
increasingly taper and twist
along two dimensions.
b.length = 10
b.width = 10
b.height = 10
b.lengthsegs = 10
1 for i = 0 to 4 by 1 do
b.widthsegs = 10
2 (
b.heightsegs = 10
3 for j = 0 to 4 by 1 do
4 (
5
b.pos = b[i*17,
= box()
j*17, 0]
6 ) b.length = 10
7) b.width = 10
8 b.height = 10
9 b.lengthsegs = 10
10 b.widthsegs = 10
11 b.heightsegs = 10
12 addModifier b (taper amount:(-0.1*j))
13 addModifier b (twist angle:(10*i))
14 b.pos = [i*17, j*17, 0]
15 )
16 )
PaRT ii ParamEtriC
PattErNS

30 CoNtrollEr

42 ForCE FiEld

48 rEPEtitioN

58 tiliNg

68 rECurSioN

82 SubdiViSioN

110 PaCkiNg

126 WEaViNg

156 braNCHiNg
28 Parametric patterns

In his 1977 book, A Pattern Language: Towns, Buildings, published in his book, Elements of Parametric Design.
Construction, Christopher Alexander pioneered the use of Other authors have also attempted to describe reusable
generative design patterns. He created an architectural parametric and generative strategies for the derivation of
system (or language) with the intention of creating form and organizational structures. Many other books,
practical and beautiful classical spaces and forms. this one included, build on that kind of foundational
(This built on his earlier work, including his doctoral work to develop higher-level patterns and algorithmic
dissertation in architecture, which was published in 1964 strategies for the derivation of form and the definition of
as Notes on the Synthesis of Form, a book which was widely topologies. Benjamin Aranda and Chris Lasch produced
read by students of computer science.) In 1994, inspired a concise and intriguing set of patterns in their book,
by his work, computer scientists Erich Gamma, Richard Tooling, which provides succinct and high-level recipes for
Helm, Ralph Johnson and John Vissides wrote a book constructs such as spirals, cracks and flocks. Jane and Mark
titled Design Patterns: Elements of Reusable Object-Oriented Burry, in their book, The New Mathematics of Architecture,
Software. The book ushered in a new way of creating also organize the chapters of their book around parametric
algorithms that focused, in particular, on the idea that themes such as packing and tiling, optimization and topology.
one can recognize and thus more efficiently and quickly This book follows in the same long tradition started
deploy repeating patterns that have a consistent logic by Christopher Alexander and builds on the work of
and structure. For example, think of a queue at the local Woodbury, Aranda/Lasch and the Burrys. The selection
supermarket. The first person to enter the queue is the of high-level parametric patterns in this book includes:
first person to be served at the till and to exit the queue. controller, force field, repetition, tiling, recursion,
Now think of a librarian returning a stack of books piled subdivision, packing, weaving and branching. In trying to
vertically to their original location. The book that was guide the reader from simpler patterns to more complex
placed last on top of the stack is the first one to be taken ones, I decided that a good progression might be one
out of the stack. In order to reach a book in the middle that starts with patterns that are mainly 2D and leads to
of the stack, you would have to take out the ones that are ones that are mainly 3D. Many design problems are 2D
stacked above it. Thus, a stack behaves in the opposite in nature. Whether it is finding a planar organizational
way to a queue. These patterns have exact counterparts solution or modifying a field of elements based on
in software programming. Once a pattern is defined and perceived site forces, 2D parametric patterns can serve
understood, it can be put to good and consistent use in as excellent sources of interesting and rigorous solutions
developing an algorithm. Since parametric design relies (fig. 9). Not surprisingly, a clear separation between 2D
heavily on algorithmic concepts, it is not surprising that and 3D patterns is not as clear-cut as one might predict.
it too has patterns. Parametric design patterns are still Many 3D parametric solutions actually start with a 2D
in development. Robert Woodbury and his team, for parametric technique that then gets developed (or folded
example, are collecting and systematically developing or expanded) into a 3D parametric design. For example,
a comprehensive set of parametric patterns using a the geometric basis for the 2002 Serpentine Gallery
consistent template. You can see some of these patterns Pavilion in Hyde Park, London, by Toyo Ito and Arup was
a simple recursive subdivision of the square plan, repeated
seven times, resulting in a spiral of truncated squares
that were then extended to create the overall planar
pattern. The 2D pattern lines were then folded in the third
dimension, draped over each side of the pavilion and
thickened to create a structural system with the desired
3D spatial complexity (fig. 10). Alternatively, 3D form can
yield interesting 2D patterns as illustrated by the elegant
recursive features of the double helicoidal snail staircase
at the Vatican Museum (fig 11). When this 3D structure
is viewed from above, it compresses into a 2D fractal
pattern. We seem to be intrinsically drawn to these types
of fractal growth formations that result from the iterative
application of rules at different scales. It is interesting

fig. 9 Constellations, MATSYS


Design (Andrew Kudless).
Parametric patterns 29

to note that this staircase, built in 1932, predates the


discovery of the identical double helical structure of DNA.
In this book, you will find discussions of patterns that blur
the line between 2D and 3D. For example, the patterns
for repetition and recursion both produce similar results
in 2D and 3D. The discussion of subdivision includes the
creation of a diagonal grid (a diagrid) as a 2D diamond-
shaped pattern, as well as a 3D tessellation method
for non-uniform rational b-spline surfaces (NURBS).
As architects and designers, we continuously navigate
between 2D and 3D representations, transforming one
into the other as needed. CNC and laser cutting digital
fabrication, for example, requires the flattening of
3D forms into unfolded or sectioned 2D cut patterns.
These patterns, in turn, are re-assembled into physical fig. 10 2002 Serpentine fig. 11 Looking down the snail
Gallery Pavilion, Hyde Park, staircase, Vatican Museum, Rome,
3D form. Therefore, I expect the reader will use the
London, Toyo Ito and Arup. Italy, Giuseppe Momo.
knowledge gleaned from this book to create and
follow digital workflows that combine and alternate
between 2D patterns and 3D constructs as needed.
30 Parametric patterns

Controller
In woodworking, one usually creates a rig that controls the can be thought of as a handle: the main interface to
construction of the desired object. For example, in order the model in the same way that a door handle is the
to create picture frames of different sizes, one might devise interface controller of a door. Similarly, the undulation
a modifiable picture frame rig (fig. 12). By modifying of a NURBS surface could be changed by repositioning a
the parameters of the rig, different sizes of frames can be few controlling vertices (CVs), which are interlinked with
made. Parametric systems work in a very similar manner. the model, but the undulation could also be controlled
Association allows us to create rigs that control the overall by changing the weight setting of those CVs. Think of
design by modifying a few of their controlling parameters. the weight setting as the strength of the magnetic field
The basic concept behind the controller pattern is that of the CVs (fig. 13). In this example, the weight setting
it separates and clarifies the process by which the main can be thought of as an independent controller that
model will change. In certain situations, a controller clarifies the rules by which the surface will change shape.

fig. 12 A woodworking rig


that creates picture frames
of different sizes.
Controller 31

CV
fig. 13 The effect of modifying
Selection the weight-setting controller of a
set of NURBS controlling vertices.
Name : Multiple CVs Selected
Weight: 10.0

Hide Unhide All

Fuse Unfuse
Remove Animation
Constrained Motion
U V Normal

Delete
Row Col. Both

Refine
Row Col. Both

Insert
Row Col. Both

Display Lattice
CVs Selected: 4

Soft Selection

CV
Selection

Name : Multiple CVs Selected


Weight: 5.0

Hide Unhide All

Fuse Unfuse
Remove Animation
Constrained Motion
U V Normal

Delete
Row Col. Both

Refine
Row Col. Both

Insert
Row Col. Both

Display Lattice
CVs Selected: 4

Soft Selection

CV
Selection

Name : Multiple CVs Selected


Weight: 2.0

Hide Unhide All

Fuse Unfuse
Remove Animation
Constrained Motion
U V Normal

Delete
Row Col. Both

Refine
Row Col. Both

Insert
Row Col. Both

Display Lattice
CVs Selected: 4

Soft Selection
TuToRial a ParamEtriC CirClE

In this tutorial, you will create a very simple controller rig in and show you how you can build a rig to precisely control the
which the location and radius of a circle is derived from the parameters of one object through the attributes of another. The
location of, and distance between, two points. (In another power of such rigs will become apparent later in the book. In
tutorial, we will use this whole construct of the two points this example, the task is to create two points, A and B, and a
and the circle as a rig that will define a radius of influence circle, C. The circle’s centre will coincide with point A and its
on an array of elements – but more on that later.) radius will be equal to the distance between point A and point
Obviously, any simple CAD program can create a circle B. The result will be a circle that will dynamically move when
and allow you to define the location of its centre and specify we move points A and B. Its centre will always follow point
the length of its radius. However, the objective of this tutorial A while its circumference will always pass through point B.
is to introduce you to the concept of parametric association

Step 1 creating the Main obJects


start 3ds Max. if the default configuration shows one viewport, press the
Maximize Viewport toggle in the lower right corner to show the four viewports.
Press the Create tab, then Helpers and then Point (fig. 14).
Press inside the viewport titled top to create and locate the first point.
on the right side, rename the point to Point a.
repeat the process to create a second point and name it Point b.
Press the Create tab, then Shapes and then Circle (fig. 15).
hold the mouse button down and drag in the viewport titled top to create
a circle.
on the right side, rename the circle to circle c.
now you should have two points and a circle in your viewport (fig. 16).

Type a Keyword or phrase


3DS Edit Tools Group Views Create Modifiers Animation Graph Editors Rendering Lighting Analysis Customize MAXScript Help
All View Create Selection Se

Graphite Modeling Tools Freeform Selection Object Paint


Polygon Modeling

Object Type
AutoGrid Splines

Dummy Container Object Type


AutoGrid
Crowd Delegate Start New Shape
Line Rectangle
ExposeTm Grid Cirde Ellipse

Point LightMeter Arc Donut


NGon Star
Tape Protractor Text Helix
Section
Compass
Name and Color

Cirde001

fig.14 Creating a point. Rendering


Interpolation
Creation Method
Edge Center

Keyboard Entry
Parameters

Radius: 1.08m

Splines

Object Type
AutoGrid
Start New Shape
Line Rectangle
Cirde Ellipse
Arc Donut 0 /100

NGon Star 0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100


1 Shape Selected X: 2.843m Y: –1.749m Z: 0.0m Grid = 0.254m Auto Key Selected
Text Helix Welcome to M Click and drag to begin creation process Add Time Tag Set Key Key Filters... 0

Section

fig. 15 Creating a circle. fig. 16 Two points and a circle in the viewport.
Controller 33

Step 2 associating the Position oF the circLe


With the Position oF the Point
We now need to instruct circle c to derive its position from the position of
Point a. 3ds Max uses the term Parameter Wiring for associating parameters.
You can find the Parameter Wiring command under the animation menu.
Press the Select object button (a mouse arrow and a cube),
then press on the circle in the viewport to select it.
choose animation Wire Parameters Parameter Wire Dialog… (fig. 17).

Type a Keyword or phrase


3DS Edit Tools Group Views Create Modifiers Animation Graph Editors Rendering Lighting Analysis Customize MAXScript Help
All Load Animation... Create Selection Se
Save Animation...
Graphite Modeling Tools Freeform Selection
Polygon Modeling IK Solvers ▶

[ + ] [ Top ] [ Wireframe ] Constraints ▶

Transform Controllers ▶

Position Controllers ▶
Splines
Rotation Controllers ▶

Scale Controllers ▶
Object Type
AutoGrid
Animation – CAT ▶
Start New Shape
Parameter Editer... Alt+1 Line Rectangle

Parameter Collector... Cirde Ellipse


Alt+2
Arc Donut
Wire Parameters ▶ Wire Parameters... Ctrl+5 NGon Star
Parameter Wire Dialog... Alt+5 Text Helix
Animation Layers...
Section
Reaction Manager...
Name and Color
Bone Tools...
Cirde001
Set ad Skin Pose
Assume Skin Pose
Skin Pose Mode

Toggle Limits

Delete Selected Animation

Walkthrough Assistant...

reactor

0 /100

0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100
1 Shape Selected X: 1.944m Y: –1.15m Z: 0.0m Grid = 0.254m Auto Key Selected
Welcome to M Parameter Wiring Dialog... Add Time Tag Set Key Key Filters... 0

fig. 17 The Parameter Wire Dialog… menu item.

in the presented dialog box, in the left-hand window, Parameter Wiring #1

locate and select the parameter titled Position: World World


Objects Scene Materials
Position XYZ for circle c. in the right-hand window Point A
Point B
Medit Materials
Objects
locate and select the parameter titled Position: Cirde C
Transform : Position/Rotation/Scale
Point A
Transform : Position/Rotation/Scale

Position XYZ of the first of the two Points (Point a). Position : Position XYZ
X Position : Bezier Float
Position : Position XYZ
X Position : Bezier Float
Y Position : Bezier Float Y Position : Bezier Float

With both parameters selected, press on the Z Position : Bezier Float


Rotation : Euler XYZ
control
direction
Z Position : Bezier Float
Rotation : Euler XYZ

arrow pointing from right to left (). then, Scale : Bezier Scale
Object (Cirde)
Scale : Bezier Scale
Object (Point Helper)
Point B
press the button titled Connect (fig. 18). Transform : Position/Rotation/Scale
Position : Position XYZ

You will now see that the circle has moved and centred Master Master
itself on the first point. in order to test that this Expression for Position
Connect

Disconnect Make a new connection or update current connection expressions


has worked, select Point a and move it around the Position Position

screen. Verify that the circle moves along with it.

fig. 18 Wiring the parameters.


a ParamEtriC CirClE/CoNtiNuEd

Step 3 creating the distance attribUte Parameter Editor

the next task is to compute and store the distance between Add to Type:
Attribute

the two points. 3ds Max includes a modifier called attribute Selected Object’s Current Modifier

Holder that can store and share custom attributes and their Pick Explicit Track

values. in this part of the tutorial, we will create a custom Add/Edit/Delete

attribute called distance and store it in Point b. Add Edit/Delete ...

Parameter Type:

select Point b in the viewport and then press the Modify tab. Float

UI Type
From the Modifier list drop down menu, under object- Spinner

Space Modifiers, select attribute Holder. Name: distance

choose animation Parameter Editor (fig. 19). Size


Float UI Options

Width: 160
Make sure the Parameter type is Float. Range
From: 0.0 5000.0
change the name to distance. Default: 0.0

Alignment
change the Range To: value to a large number (e.g. 5,000 ). this will Left Right Center

be the maximum value that this parameter can attain. Make sure it is Offsets: X: 0 0

Orientation and Ticks


larger than the expected maximum distance between the two points. Vertical Ticks: 10

Press add to add the distance attribute to Point b. You should see Testing Attribute
distance: 0.0
the custom attribute on the right-hand side of the interface.
the next step is to compute the actual value of this attribute
as the distance between Point a and Point b. fig. 19 Parameter Editor.

Place your cursor inside the text field next to


Selected
the word distance and right-click. Modes Controller Tracks Keys Curves Options Display View Utilities

choose Show in Track View.


Medit Materials
in the track View window choose Controller assign or right-click Objects
Point B 20

on the distance variable itself and choose assign Controller (fig. 20). Transform
Position
X Position
choose Float Expression as the controller of this attribute and Y Position
Z Position
10

press oK. this will allow us to specify a mathematical expression Rotation


X Rotation

(i.e. a function) that will define how this attribute is evaluated. Y Rotation
Z Rotation
0
Scale
in the Expression Controller dialog box, next to Name type Modified Object
Attribute Holder
in dist, choose the Scalar type and press Create. Custom_Attributes
distance
–10

Point Helper (Object)


repeat the process. type in posa, choose
the Vector type and press Create. –20
0 30 60 90

type in posb, choose the Vector type and press Create (fig. 21).
From the list of vectors, select posa and press assign to Controller.
From the next window find and select Point a Transform: fig. 20 Track View Editor.
Position/Rotation/Scale Position: Position XYZ. Press oK.
Expression Controller : Point B\distance
repeat for posb by selecting the Position of Point b and Create Variables Expression
assigning it as the controller for this variable. Name: posB
Scalar
Vector
length(posA-posB)

Create Delete Rename


next, select the dist variable and type the following Variable Parameters

expression under the Expression text field: Tick Offset : 0

Scalars Vectors
dist posA
length(posa – posb) posB
Description

the length function finds the length of a vector, which in


this case is the difference between posa and posb. T = ticks F = frames Function List
S = secs NT = normalized time

Press the Evaluate button. You should see on the right side of the Assigned to: $’Point B’.transform.controller.Position

Assign to Constant Assign to Controller Save Load Debug Evaluate Close


interface that the distance attribute is no longer zero. it is actually
the distance between Point a and Point b expressed in the default
units. to experiment with this attribute, move Point b around fig. 21 Expression Controller.
the screen and verify that the distance changes accordingly.
Controller 35

Step 4 controLLing the radiUs oF the circLe


Using the distance attribUte
the last step in this tutorial is to control the radius of the circle
using this distance attribute. to accomplish this, we will reuse the
same technique as in step 2 above, but will associate the radius of
the circle, rather than its position, to the distance attribute.
select the circle.
choose animation Wire Parameters Parameter Wire Dialog…
in the presented dialog box, in the left-hand window, locate and select
the parameter titled radius for circle c. in the right-hand window
locate and select the parameter titled distance of Point b.
With both parameters selected, press on the arrow pointing
from right to left ( ). then, press the Connect button.
You will now see that the circle has changed radius so that its
circumference passes through Point b. in order to test that this has
indeed worked, move Point a and Point b independently around the
screen and verify that the circle always stays centred on Point a
and its circumference always passes through Point b (fig. 22).

Type a keyword or phrase


3DS Edit Tools Group Views Create Modifiers Animation Graph Editors Rendering Lighting Analysis Customize MAXScript Help

All View Create Selection Se

Graphite Modeling Tools Freeform Selection Object Paint


Polygon Modeling

Point A

Modifier List

Point Helper

Parameters
Display :
Center Marker
Axis Tripod
Cross
Box

Size: 0. 508m

Constant Screen Size


Draw On Top

0 /100

0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100
1 Helper Selected X: –0.219m Y: 0.13m Z: 0.0m Grid = 0.254m Auto Key Selected
Welcome to M Click and drag to select and move objects Add Time Tag Set Key Key Filters... 0

fig. 22 Parametric circle – final design.


Point a Point b

congratulations, you have created your first parametric object. Position


symbolically, you have created a network of associated attributes using Position distance
direct controllers as well as computed expressions (fig. 23). Keep the
file you have created as you will need to use it for the next tutorial.

Circle C

Position
radius

fig. 23 A symbolic view of the associated attributes.


36 Parametric patterns

Case study Aviva Stadium, Dublin, Ireland


Designer Populous (formerly HOK Sports Architecture)
Client LRSDC (Lansdowne Road Stadium Development Company)
Design 2005–2007
Construction 2007–2010

Aviva Stadium was designed to replace an earlier As the designers assert, the parametric Above
stadium located on the same site and to provide design process constituted the most General view of the stadium at night.

a modern facility that could accommodate important aspect of the project. It allowed
Opposite
50,000 seated spectators and the home games them to maximize the efficiency of the overall View looking up at the mullion structure.
of the Irish International Rugby and the Irish design and the refinement of the building’s
Football teams. A project requirement, from exterior skin, as well as ensuring a smooth
the outset, was to respect the historic site of collaboration between Populous and Buro
Lansdowne Road by minimizing the impact of Happold, the engineering firm for the project,
the new facility on surrounding buildings. helping to avoid errors and save time.
Populous (formerly HOK Sports Architecture) At the initial stages of the project’s design,
was commissioned for the project and it dedicated concepts and studies were explored through
nearly two years to the planning and design static 3D computer models implemented
of the new stadium. Their proposal consists of mainly in McNeel’s Rhinoceros platform. The
a flowing, organic, translucent form that they basic geometry of the building consisted of
describe as ‘both responsive and empathetic to three elements: the footprint of the stadium,
the surrounding neighbourhood’. The designers composed of eight tangential arcs; the plan of
did not attempt to produce a building that would the inner roofline or drip line, also composed
formally blend in with its immediate surroundings. of eight tangential arcs; and a radial structural
Instead, they sought to find a design with grid that eventually became the supporting
a contemporary geometry and language of system of the stadium’s outer surface or skin,
expression that, through its transparency and which functions as a façade as well as a roof.
flowing shape, still allowed maximum daylight The design of each section of the stadium’s
to reach the surrounding built environment. radial structural grid was particularly important
38 Parametric patterns

x
y x
y
North South North
Controller 39

Opposite
Parametric development of the stadium’s geometry,
structural elements and cladding system.

Right
The mullion and bracket system.

Below
The stadium under construction, showing the
attachment of the bracket to the underlying structure.
40 Parametric patterns

Plan rotation

Elevation rotation

because it needed to vary around the perimeter product and complete control over the design Above
to create the overall flowing form. Each section of the stadium’s outer skin, and it also acted A study of the mullions and brackets
illustrating rotational flexibility, which
consisted of a large, shallow arc beginning as the main controlling geometry for the many
accommodates various cladding conditions.
at the base of the building and composing team members working on the project. Populous
its façade; a second, smaller and deeper arc, and Buro Happold agreed a common format
tangential to the first and making the transition for an Excel spreadsheet that would drive the
between the façade and the roof; and, finally, solution of the structural system. Any changes to
a straight line also tangential to the smaller the parametric model were exported to a single
arc and functioning as the roof. The exact spreadsheet and given to the structural engineers.
configuration of each of these tripartite sections The new data in the spreadsheet would then
had to be manipulated to correspond to the trigger automatic changes to the structural system
general plan of the stadium (footprint, drip solution, thus ‘not allowing for any deviations
line and seating bowl) and to accommodate from the base geometry to go unnoticed’.
the functional requirements of the interior. The Aviva Stadium is an exemplary case
After the initial static model was complete, study of a project executed during a transitional
the data from it were employed to build a second, period in computer-aided design technology –
parametric model using Bentley’s Generative one that saw a shift from static and bespoke
Components (GC) software. First, the coordinates 3D models to fully parametric and associative
of the initial Rhinoceros model were extracted ones – and it demonstrates two important
and imported into a spreadsheet, so that they aspects of this shift. First, without the adoption
could be referenced in the GC model. Through of a fully parametric approach, Aviva Stadium
this process, the form of each radial structural and projects like it would have been more
section could be manipulated and varied. The error-prone and more expensive to construct.
transfer to a parametric model was, according to Second, it demonstrates how parametric tools
the designers, ‘the most critical single aspect of can allow designers to widen their exploration
the … design’. It allowed the designers further of architectural form while maintaining rigorous
aesthetic control over the overall shape of the control over all aspects of their design proposal.
Controller 41

Above Above right Below


The mullion and bracket system under construction. A close-up view of the mullion and bracket system. A wide perspective view of the stadium’s
interior showing the undulating roofline.
42 Parametric patterns

Force field
A prevalent pattern in parametric design algorithms is that For example, architect Jürgen Mayer-Hermann and Arup
of the force field. When thinking about what affects the Engineering negotiated the extreme constraints of an
form of an object or building, it is natural to imagine the archaeological site, an urban plaza and the need for shade
metaphor of various forces that are pushing and pulling in the design of their Metropol Parasol in the Plaza de la
on it. These vectors rhythmically change direction, Encarnación, Seville, Spain (fig. 25). The glue-laminated
shape or intensity based on their location in the force structure appears as a malleable cloud-like form that has
field and the presence or absence of various forces acting been moulded into and deformed by the forces of its
on them (fig. 24). As Nicholas Negroponte observed, surroundings. Fundamental to a successful application of
‘Physical form is the resolution at one instant of time forces in parametric design is the rigorous definition of the
of many forces that are governed by rates of change.’1 internal topological constraints of the object being acted
Gaudi's use of catenary curves is a prime example. A on such that it deforms and adapts in a rich, graceful and
catenary curve is derived directly from the force of gravity consistent manner. Structures that have not been thus
applied to a chain when hanging under its own weight defined tend to create awkward moments and difficult
and suspended only at its ends. Linking hanging chains and illogical details. In the next tutorial, we will create
together creates a negotiation of forces and resulting a field of circular panels that have internal constraints
structure that exhibits a graceful form constrained by on their size, but are affected by an overall external force
internal topological connections and external forces acting that yields a rhythmic pattern of circles with varying radii
upon it. Designers are drawn to these subtle but complex within a specified minimum and maximum dimension.
interpolations of form, which result from the application
of competing force vectors. Examples can be found in
rhythmic façade apertures as well as undulating surfaces. 1 Negroponte, N. The Architecture Machine. MIT Press. 1970.

fig. 24 Magnetic field.

fig. 25 Metropol Parasol, Seville,


Spain, Jürgen Mayer-Hermann
and Arup Engineering.
TuToRial attraCtor

In what has become a standard basic tutorial in parametric of influence (fig. 26). In order to accomplish this, we will have
techniques, the attractor tutorial will show you how to build to define the location of the attractor point and a maximum
a field of circular panels that change in size based on their radius of influence, and then connect that information to the
distance from, and the maximum radius of influence of, an size of the circle in question. The previous tutorial is a good
attractor point. The net effect is akin to using a magnifying starting point for this one, since we can reuse the parametric
glass where objects near the centre of the magnifier are circle we have already created as our magnifying glass.
largest, tapering off to smaller objects at the periphery while
not affecting objects that are outside the maximum radius

Step 1 creating the basic ModULe


open your 3ds Max file from the previous tutorial.
to start, we will create our basic module as a simple circle and
specify its parameters. in this tutorial, we will create a circle with a
radius that varies in size between 0.2 m and 1.0 m, and which has an
initial default radius (defr ) of 0.2 m. in order to change the size of
the radius, we will create a multiplying factor (mFactor ) that we will
compute based on the distance between the circle and the centre of
the magnifying glass. We will then multiply this factor by a specified
default radius of the circle to arrive at its final radius size, r :
r = mFactor × defr
create a circle and define its custom attributes: a default radius, a fig. 26 The concept of a magnifying glass affecting a field
minimum radius, a maximum radius and a multiplication factor. of circular panels.
create a circle of radius size 1 m.
add an attribute Holder modifier.
Parameter Editor

choose animation Parameter Editor… (or press alt+1) (fig. 27) Attribute Cirde001
Add to Type:
create a minr float attribute with a minimum of 0.2, a Modifier List
Selected Object’s Current Modfier
maximum of 1.0 and a default value of 0.2, then add it. Pick Explicit Track
Attribute Holder
Cirde

create a maxr float attribute with a minimum of 0.2, a Add/Edit/Delete


maximum of 1.0 and a default value of 1.0, then add it. Add Edit/Delete ...

create a mFactor float attribute with a minimum of 1.0, a Parameter Type:


Float
maximum of 5.0 and a default value of 1.0, then add it.
UI Type
create a defr float attribute with a minimum of 0.2, a Spinner
Custom Attributes
maximum of 1.0 and a default value of 0.2, then add it. Name: minR
minR : 0. 2
maxR: 1.0
at this point, you should have four custom attributes stored in Float UI Options
Size mFactor: 1.0
the attribute Holder modifier of the circle object (fig. 28). Width: 160 defR: 0. 2

click on the word Circle under the attribute Holder modifier Range
From: 0.2 1.0
to examine the main parameters of the circle. Default: 0.2 fig. 28 Attribute Holder
Alignment modifier.
Left Right Center
Offsets: X: 0 0

Orientation and Ticks


Vertical Ticks: 10

0.2

fig. 27 Parameter Editor.


attraCtor/CoNtiNuEd

Selected Expression Controller : Circle001\Radius Track View Pick


Modes Controller Tracks Keys Curves Options Display View Utilities
Create Variables
World OK
Scalar
Name: minR Sound
Vector
Objects Video Post Cancel
110 Create Delete Rename
Cirde001 Global Tracks
Transform Biped
100 Variable Parameters
Position Anim Layer Control Manager : MASTER _LAYER _MANAGER
X Position Tick Offset: 0 SME
90
Y Position Environment
Scalars Vectors
Z Position Render Effects
Rotation
80 defR
maxR Render Elements
X Rotation
70 mFactor Render er
Y Rotation minR Global Shadow Parameters
Z Rotation
Scale 60 Scene Materials
Modified Object Medit Materials
Attribute Holder 50 Objects
Cirde ( Object ) Cirde C
render _thickness 40 Point A
render _sides Point B
render _angle 30 Cirde001
render _width Transform : Position/Rotation/Scale
render _length 20 Modified Object
render _angle2
Attribute Holder
render _threshold
10 Custom_Attributes
Radius
minR
0 maxR
0 30 60 90 mFactor
Assigned to: Constant: 0 defR
Cirde (Object )
Assign to Constant Assign to Controller

Assign to Controller

fig. 29 Track View. fig. 30 Assigning a Controller.

right-click on the main radius value of the circle (not


defr) and choose Show in Track View (fig. 29).
in the track View window choose Controller assign.
as in the first tutorial, create four scalar variables
named: minr, maxr, mFactor and defr.
choose each variable in turn and press assign to Controller to
assign its controller. choose from the circle object the corresponding
custom attribute that you created above (e.g. assign the minr
custom attribute to the minr scalar variable, etc.) (fig. 30).
We have now created four variables that derive their values from the custom
attributes we had defined earlier, and which together can affect the size of the
circular panel. assuming that this panel would eventually be manufactured, we
need to make sure that its size remains within a minimum and a maximum size
regardless of the value of the multiplication factor. thus we need to create a
mathematical expression for the radius of the circular panel that multiplies mFactor
by defr but maintains the final result between the minr and maxr values (fig. 31).

TiP Units
Expression Controller : Circle001\Radius internally, 3ds Max maps one unit of
Create Variables Expression drawing measure to a known measuring
Scalar
Name: minR
Vector
min(max(defR*mFacter/0.0254 , minR/0.0254) , maxR/0.0254) unit (e.g. inch, centimetre, metre). this
Create Delete Rename is different from how it handles drawing
Variable Parameters scale and input values and affects how
Tick Offset: 0
it carries out its internal computations.
Scalars Vectors
defR
in this tutorial, 3ds Max was set to map
maxR
mFactor
Description 1 unit to 1 inch resulting in the need to
minR
divide by 0.0254 to convert to metres.
if you wish to change the default unit
system in 3ds Max, choose Customize
T = ticks F = frames
units Setup and then press the
Function List
S = secs NT = normalized time button titled System unit Setup. You can
Assigned to: $Cirde001.modifiers[=Attribute_Holder] .Custom_Attributes.minR

Assign to Constant Assign to Controller Save Load Debug Evaluate Close


then customize the system unit scale in
the presented dialog box.

fig. 31 The Expression Controller.


Force field 45

the mathematical expression in fig. 31 reads:


min(max(defr × mFactor/0.0254 , minr/0.0254) , maxr/0.0254)
how was the above expression reached? Let us decode it step by step:
a. compute an initial radius by multiplying mFactor by the default radius, defr:
defr × mFactor
We could have stopped here and defined the radius as the result of multiplying a default
value by a multiplication factor. however, the above expression has no minimum or
maximum boundaries. if this were a real situation, where these are manufactured
panels, we would need to limit their minimum and maximum sizes. We will do so next.
b. compare the value of the above expression with the desired minimum
radius and return the greater of the two values. this assures us that if the
above expression yields a value less than the desired minimum, we then
use the desired minimum value instead. the max(arg1, arg2) function
computes the greater value of the two arguments passed to it.
max(defr × mFactor , minr )
c. compare the value of the above expression with the desired maximum
radius and return the lesser of the two values. this assures us that if
the above expression yields a value greater than the desired maximum,
we then use the desired maximum value instead. the min(arg1, arg2)
function computes the lesser value of the two arguments passed to it.
min(max(defr × mFactor , minr ) , maxr )
d. Finally, to convert the default internal 3ds Max unit
system, divide where appropriate by 0.0254.
min(max(defr × mFactor/0.0254 , minr/0.0254) , maxr/0.0254)
at this stage, you should have your circular panel defined and appearing in
the viewport next to the magnifying glass circle (fig. 32).

TiP cUrVe editor


Type a Keyword or phrase
3DS Edit Tools Group Views Create Modifiers Animation Graph Editors Rendering Lighting Analysis Customize MAXScript Help

All Create Selection Se

Graphite Modeling Tools Freeform Selection Object Paint


Polygon Modeling
[ + ] [ Top ] [ Wireframe ]
if you want to re-examine the expression
Cirde001 controller window of a variable and
Modifier List

Attribute Holder
right-clicking on the value does not
Cirde
Cirde
work, choose Graph Editors Track
View – Curve Editor…

Name and Color


Custom Attributes
minR: 0.2
maxR: 1.0
mFactor : 1.0
defR: 0.2

0 /100

0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100
1 Shape Selected X: Y: Z: Grid = 0.254m Auto Key Selected
Welcome to M Click or click–and-drag to select objects Add Time Tag Set Key Key Filters... 0

fig. 32 Magnifying glass and circular panel.


attraCtor/CoNtiNuEd

Step 2 Wiring the circULar PaneL’s radiUs to its


distance FroM the MagniFYing gLass
the next step is to derive the radius of the circular panel, based on its distance
from the centre of the magnifying glass. Follow a similar procedure as in Step 3
of the previous tutorial to control the panel’s mFactor custom attribute. create
a scalar variable called radius (controlled by the radius of the magnifying
glass), a vector variable called posc (controlled by the position of the panel
itself) and a vector variable called posMg (controlled by the position of the
magnifying glass). the panel itself already limits how much it can grow or
shrink; we have assigned its mFactor attribute a minimum value of 1 and a
maximum value of 5 and, as a result, the maximum size of the panel is 1 m
(0.2 × 5.0). therefore, we can write a mathematical expression that maps the fig. 33 Magnification concept.
distance between the centre of the magnifying glass and the circular panel to
a number between 1 and 5, where 1 is the factor at the outer circumference of
the magnifying glass and 5 is the multiplication factor at its centre (fig. 33).

the mathematical expression to achieve this effect is:


((radius - length(posc-posMg))/radius) × 5.0
We calculate the distance from the circular panel to the centre of the magnifying glass (length(posc-posMg)
). We then subtract that value from the radius of the magnifying glass and divide the result by the same
radius. Finally, we multiply the result by 5 to get us the 1x to 5x magnification that we are looking for.
if you examine the above equation carefully, you find that, essentially, it yields a fraction of the radius. if the
circular panel is at the centre of the magnifying glass we get a ratio of 1 (then multiplied by 5). if the distance
is equal to the radius (i.e. the circular panel is at the circumference of the magnifying glass we get a ratio
of zero. if the circular panel is outside the magnifying glass (i.e. distance is larger than the radius) we get a
negative number. We obviously do not want a negative multiplication factor, but we are protected from that
by the fact that the mFactor attribute has a defined minimum value of 1. however, you may want to pass the
result of the above expression to a max(arg1, arg2) function to limit explicitly the minimum value to 1 (fig. 34).
if you do this, the final mathematical expression then becomes:
max(1, ((radius - length(posc-posMg))/radius) × 5.0)

Expression Controller : Circle001\mFactor

Create Variables Expression


Scalar
Name: max(1,((radius – 1ength(posC–posMG))/radius) *5.0)
Vector
Create Delete Rename

Variable Parameters
Tick Offset: 0

Scalars Vectors
radius posC
posMG
Description
minR

T = ticks F = frames Function List


S = secs NT = normalized time
Assigned to:

Assign to Constant Assign to Controller Save Load Debug Evaluate Close

fig. 34 Expression Controller dialog box.


Force field 47

Step 3 generating a FieLd oF ParaMetric


circULar PaneLs
You can now move the circular panel around and verify that it
indeed changes radius based on its distance from the centre of
the magnifying glass. You can also use the array command (Tools
array) to create an array of circles that respond individually
and uniquely to the location of the magnifying glass (fig. 35).
note, however, that in order for that effect to be successful you
need to create independent copies and not instances of the
original (choose the Copy option from the array dialog box).

Array

Array Transformation: Screen Coordinates (Use Pivot Point Center)


Incremental Totals
X Y Z X Y Z
2.2m 0.0m 0.0m Move 44.0m 0.0m 0.0m units

0.0 0.0 0.0 Rotate 0.0 0.0 0.0 degrees Re–Orient

100.0 100.0 100.0 Scale 100.0 100.0 100.0 percent Uniform

Type of Object Array Dimensions


Total in Array: 400
Count
Incremental Row
Copy 1D 20 Preview
X Y Z
Instance Preview
2D 20 0.0m 2.2m 0.0m
Reference
3D 1 0.0m 0.0m 0.0m Display as Box

Reset All Parameters OK Cancel

fig. 35 Array dialog box.

once you have created an array of circular panels, you can now
move the magnifying glass around and change its radius to create
endless variations (fig. 36). here, it is interesting to note that
although we have been creating 2d parametric patterns, the work
is readily applicable to 3d investigations and elaboration (fig. 37). fig. 36 Parametric variations.

fig. 37 Boole’s Lattice, Ronnie


Parsons and Gil Akos, Studio Mode,
Brooklyn, New York, USA. Boole’s
Lattice is a research project with the
aim of producing a thickened screen
wall through subtractive processes that
take advantage of the movements of
a 6-axis articulated robot arm. The
geometric system utilizes multiple
series of circular volumes of different
scales within a regular box grid to
create opportunities for the penetration
of light and sight on the oblique.

congratulations, you have created a field of modular objects that responds


dynamically to the location and size of a controlling object. You can
customize this tutorial by modifying the circular panel – try different
shapes and affect different attributes of that shape – or by investigating
how to affect the panels by more than one controlling object.
48 Parametric patterns

Repetition
Repetition can be thought of as the simple act of copying
an element multiple times (fig. 38). In parametric systems,
repetition can become more interesting, because a repeated
element can maintain the basic topology of its predecessor
without having to be exactly identical to it. Using a rule-
based system, one can vary the repeated element according
to any number of parameters (e.g. distance, time, location,
etc.). In mathematical terms, a simple repetition could
be in the form of 2, 2, 2, 2, 2 ... and so on. However, a
repetition that uses the Fibonacci rule, which states that,
given the first two numbers 0 and 1, any subsequent
number is the sum of the two preceding numbers (0, 1,
1, 2, 3, 5, 8, 13, 21 ...), can become more interesting –
and potentially more useful from a design perspective.

fig. 38 Clay tiles.


Tutorial Fibonacci number generator

For this tutorial, we will use a piece of free open-source software Processing from Processing.org, and follow some of the basic
called Processing. The Processing software is an environment examples on the Processing.org website. For this first simple
for creating images, animations and interactive media. Before tutorial, we will not draw any shapes. We will simply create an
commencing this tutorial, you should download and install algorithm that prints out a Fibonacci sequence of numbers.

Step 1 Listing the Fibonacci series


Start a new Sketch in Processing (File New)
Type the following text exactly in the sketch window. Any errors, misspellings
or even a single missing semi-colon will make the script fail. So, be careful
that you type it exactly as it is listed below (without the line numbers):

1 int a = 0;
2 int b = 0;
3 int fibonacci = 0;
4 int total = 14;
5 int i = 0;
6 for (i=0; i < total; i++) {
7 if (i == 0) {
8 fibonacci = 0;
9 }
10 else if(i == 1) {
11 fibonacci = 1;
12 }
13 else {
14 a = b;
15 b = fibonacci;
16 fibonacci = a + b;
17 }
18 print (fibonacci+” “);
19 }

Press the Run button in the top left corner of the sketch window to run this
script. You should see, at the bottom of the window, the first 14 numbers
of the Fibonacci series (0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233).
Let’s examine this script in detail. At the top of the script, we
declare some variables that we will use in this script.
• a is an integer variable that will store the number prior to last
in the Fibonacci series. It has an initial value of 0.
• b is an integer variable that will store the number prior to the
current Fibonacci number. It has an initial value of 0.
• fibonacci is an integer variable that will store the current Fibonacci
number that we are trying to compute. The first two occurrences
of Fibonacci numbers are 0 and 1 respectively. After that we will
compute it using the following formula: fibonacci = a + b.
• total is an integer variable that will store how many
Fibonacci numbers we wish to compute.
FiboNaCCi NumbEr gENErator/CoNtiNuEd

• i is an integer variable that will store the current index of the Fibonacci
number we are computing. think of i as a counter that starts out as 0 and then
increments by 1 every time we repeat the loop until it reaches total. indices
are useful because they tell us how many times we have repeated a loop, so
we can customize the actions of the algorithm for that particular iteration.
next, we create the actual loop that will repeat as long as i is less
than total. in this loop i starts out at 0 and then is incremented by
1 at the start of each subsequent iteration through the loop.

Step 2 draWing a goLden rectangLe


if we apply the Fibonacci numbers to geometry, we can get complex shapes,
such as the Fibonacci golden rectangle and the golden spiral, which is
composed of circular arcs connecting the opposite corners of squares sized
according to the Fibonacci numbers. the above algorithm can be easily
modified to draw the golden rectangle and golden spiral. Let’s start by drawing
the golden rectangle. the changes are highlighted in bold below:

1 int a = 0;
2 int b = 0;
3 int fibonacci = 0;
4 int total = 14;
5 int i = 0;
6 size(600,400);
7 background(255,255,255);
8 fill(0,0,0,0);
9 smooth();
10 translate(384,148);
11 for (i=0; i < total; i++) {
12 if (i == 0) {
13 fibonacci = 0;
14 }
15 else if(i == 1) {
16 fibonacci = 1;
17 }
18 else {
19 a = b;
20 b = fibonacci;
21 fibonacci = a + b;
22 }
23 print (fibonacci+” “);
24 rotate(Pi/2);
25 translate(b,-b);
26 rect(0,0,fibonacci, fibonacci);
27 }
repetition 51

Let’s examine the script changes in detail. after the declaration of the variables as
before, we specify the size of the window in which to draw the rectangle. in this case,
we specified the size to be 600 pixels wide and 400 pixels high. We then specify the
background to be white by specifying the maximum value (255) for the red, green and
blue components of the background colour. We also specify the fill to be transparent
and to draw using smooth lines and curves. next, we shift the centre of the cartesian
coordinate system to the location (384, 148). these coordinates are specific to this
example, and simply specify a good starting point for the 14 squares we are about to
draw. at the bottom of the script, we actually set up the drawing. the first step is to
define the rules by which we draw the next square in the Fibonacci series. the first rule
is that for each square, we need to rotate the coordinate system. this is akin to manually
rotating the whole piece of paper on which you are drawing. then, we translate (i.e. move)
the whole coordinate system by b in the horizontal direction and negative b in the vertical
direction. if you recall, the variable b is the Fibonacci number just before the current
one. Lastly, we draw a square starting at the origin of the newly rotated and translated
coordinate system and with dimensions equal to those of the current Fibonacci number.
the repetition of this basic procedure is what creates the golden rectangle (fig. 39).

fig. 39 The golden rectangle.

Step 3 draWing a goLden sPiraL


adding the golden spiral is not difficult, but requires temporarily
mirroring and moving the coordinate system before drawing the arc.
the changes to the script are highlighted in bold below:

1 int a = 0;
2 int b = 0;
3 int fibonacci = 0;
4 int total = 14;
5 int i = 0;
6 size(600,400);
7 background(255,255,255);
8 fill(0,0,0,0);
9 smooth();
10 translate(384,148);
11 for (i=0; i < total; i++) {
12 if (i == 0) {
FiboNaCCi NumbEr gENErator/CoNtiNuEd

13 fibonacci = 0;
14 }
15 else if(i == 1) {
16 fibonacci = 1;
17 }
18 else {
19 a = b;
20 b = fibonacci;
21 fibonacci = a + b;
22 }
23 print (fibonacci+” “);
24 rotate(Pi/2);
25 translate(b,-b);
26 rect(0,0,fibonacci, fibonacci);
27 scale(1,-1);
28 translate(0,-fibonacci);
29 arc(0, 0, fibonacci*2, fibonacci*2, 0, Pi/2);
30 translate(0,fibonacci);
31 scale(1,-1);
32 }

after drawing the current square, the coordinate system is mirrored on the horizontal
axis (thus the scale(1,-1) command), then moved by the amount fibonacci in the
negative direction. then a 90-degree arc is drawn at the origin of the new coordinate
system, with dimensions fibonacci*2 and from 0 to 90 degrees (90 degrees is
equal to Π/2 in radians). after the arc is drawn, we need to reverse the operation
we did on the coordinate system so we can continue to draw the squares at their
proper location, thus we translate it back in the opposite direction and mirror it
back again to get the original coordinate system before we drew the arc (fig. 40).

fig. 40 The golden rectangle and golden spiral.


TuToRial NEStEd PolygoNS

For this next tutorial on repetition, we will continue to use book, it is highly recommended that you install the ControlP5
the Processing software. We will create an algorithm that library and learn how to use it in conjunction with Processing.
displays a set of 2D nested polygons using an iterative For the purposes of this simpler tutorial, any changes to the
process. For each step of the iteration, the polygon to be parameters will require you to modify the numbers in the
drawn will be rotated and scaled down in size compared code window itself and re-run the sketch to see the result.
to the previous polygon. This will generate a spiral effect.
Later in this book, we will create a similar construct, but we
will use a recursive method rather than an iterative one. The
defining parameters of this algorithm include the total number
of polygons to draw, the number of vertices of the polygon
(so we can choose to display triangles, squares, pentagons,
etc.) and the degree of rotation for each iterative step, as
well as the desired starting and end sizes of the polygons.
It is important to note that while the basic installation of the
Processing software does not include interactive sliders to
allow the user to modify the parameters dynamically, there are
several free third-party tools and libraries that can be added
to Processing to allow that functionality. A complete version
of this algorithm, which includes interactive sliders, is available
from the publisher’s website (fig. 41). That version uses a
library called ControlP5 that provides various user interface
elements such as sliders, buttons and dials, which display
within the Processing window and allow the user to affect the fig. 41 The full interface of the algorithm with interactive sliders for parametric
drawing interactively. Although it is beyond the scope of this variation.

start a new sketch in Processing (File New)


type the following text exactly in the sketch window. any errors,
misspellings or even a single missing semi-colon will make the script
fail. so, be careful that you type it exactly as it is listed below:

1 int windowWidth = 950;


2 int windowHeight = 600;
3
4 int polygons;
5 float angle;
6 int vertices;
7 float minradius;
8 float maxradius;
9
10 void setup() {
11 size(windowWidth, windowHeight);
12 polygons = 40;
13 angle = 3.50;
14 vertices = 3;
15 minradius = 100.0;
16 maxradius = 300.0;
17 }
18
Nested Polygons/CONTINUED

19 void draw () {
20 translate (width/2,height/2);
21 for(int i = 0; i<polygons; i++)
22 {
23 rotate(PI*angle/180.0);
24 drawPolygon (vertices, (float) minRadius + i*(maxRadius-minRadius)/polygons);
25 }
26 }
27
28 void drawPolygon(int numVerts, float radius) {
29 float vxorig = 0.0;
30 float vyorig = 0.0;
31 float vxa = 0.0;
32 float vya = 0.0;
33 float vxb = 0.0;
34 float vyb = 0.0;
35
36 vxorig = cos(0.0 * TWO_PI) * radius;
37 vyorig = sin(0.0 * TWO_PI) * radius;
38
39 for(int i = 0; i < (numVerts-1); i++) {
40 vxa = cos((float)i / numVerts * TWO_PI) * radius;
41 vya = sin((float)i / numVerts * TWO_PI) * radius;
42 vxb = cos((float)(i+1) / numVerts * TWO_PI) * radius;
43 vyb = sin((float)(i+1) / numVerts * TWO_PI) * radius;
44 line(vxa, vya, vxb, vyb);
45 }
46 line(vxb,vyb,vxorig, vyorig);
47 }

Press the Run button in the top left corner of the sketch window to run this
script. A new window will open and in it you will see an image of the nested
polygons (fig. 42).

fig. 42 A series of nested triangles produced by


the algorithm.
Repetition 55

Let’s examine this script in detail:

1 int windowWidth = 950;


2 int windowHeight = 600;
3
4 int polygons;
5 float angle;
6 int vertices;
7 float minRadius;
8 float maxRadius;

At the top of the script, we declare some variables that we will use in this script.
These are the width and height of the display window, the number of polygons we
wish to display, the angle of rotation for each polygon, the number of vertices of
the polygons, and the minimum and maximum sizes (or radius) of the polygons.

10 void setup() {
11 size(windowWidth, windowHeight);
12 polygons = 40;
13 angle = 3.50;
14 vertices = 3;
15 minRadius = 100.0;
16 maxRadius = 300.0;
17 }

The setup function does exactly what the name implies. It is called by the software
at the start of the execution of the code to set up the drawing window and store
initial amounts in any variables we wish to use later. In this case, we have
initialized the values of the various parameters for our geometric construction.

19 void draw () {
20 translate (width/2,height/2);
21 for(int i = 0; i<polygons; i++)
22 {
23 rotate(PI*angle/180.0);
24 drawPolygon (vertices, (float) minRadius + i*(maxRadius-minRadius)/polygons);
25 }
26 }

The draw function gets called repeatedly to redraw the contents of the screen. Although
the image will look static (because the contents do not change), it is actually being
redrawn several times a second. The draw function starts by shifting the origin of the
drawing to the centre of the window (width/2 and height/2 ). This allows us to display the
polygons neatly in the centre of the window regardless of its actual width and height.
The function then starts a repetitive for loop that repeats for exactly the number of
polygons we have set. At the start of each iteration in this loop, we rotate the canvas
of the drawing (imagine rotating the paper you are drawing on, rather than rotating
your hand in order to draw a rotated shape more easily). Since the rotate function in
Processing expects the value in radians and not in degrees, we multiply the increment
Nested Polygons/CONTINUED

by the constant PI (π). We then call a function, called drawPolygon (which we will write
next), to draw a single polygon. We will examine the drawPolygon function in detail,
but for now just assume that it draws a polygon at the specified size and rotation. At
the end of this loop we would have drawn all the needed polygons, each time rotating
the canvas by an angular increment just before drawing the polygon on it. We pass two
values to this function: first, the number of vertices that the polygon will possess and
second, the size of the polygon, calculated as the radius of an imaginary circle that
circumscribes the polygon. We calculate this radius through a simple mathematical
formula that incrementally increases the size with each iteration through this loop.

28 void drawPolygon(int numVerts, float radius) {


29 float vxorig = 0.0;
30 float vyorig = 0.0;
31 float vxa = 0.0;
32 float vya = 0.0;
33 float vxb = 0.0;
34 float vyb = 0.0;

The drawPolygon function expects to receive the number of vertices and the
radius of the polygon to draw. Since the background canvas has already been
rotated, drawPolygon only needs to draw the polygon, without worrying about
rotating it. This function draws the polygon by deciding on the location of its
vertices and then connecting a line between them. Since it will repeat this
process for each side, we can limit the number of vertices we need to two, plus an
additional two for the first vertex so that we can return to it in order to close the
polygon. We start the function by assigning initial (0.0) values to all variables.

36 vxorig = cos(0.0 * TWO_PI) * radius;


37 vyorig = sin(0.0 * TWO_PI) * radius;

Using trigonometry, we can derive the x-coordinate of the first vertex by


multiplying the cosine of the angle connecting the centre of the polygon to this
first vertex by the length of the side. In this case, the result is the same as the
radius, because the cosine of 0 is 1. Similarly, the sine of 0 is 0 and thus the
y-coordinate of the first vertex is 0. Therefore, a distance of radius horizontally
distances the first vertex from the origin along the positive x direction.

39 for(int i = 0; i < (numVerts-1); i++) {


40 vxa = cos((float)i / numVerts * TWO_PI) * radius;
41 vya = sin((float)i / numVerts * TWO_PI) * radius;
42 vxb = cos((float)(i+1) / numVerts * TWO_PI) * radius;
43 vyb = sin((float)(i+1) / numVerts * TWO_PI) * radius;
44 line(vxa, vya, vxb, vyb);
45 }
Repetition 57

Next, we create another for loop to iterate through the number of vertices. We calculate
the x-coordinate and the y-coordinate of the endpoints of the current line, using the
same trigonometric formula that is explained above. We then draw a line that connects
these points.

46 line(vxb,vyb,vxorig, vyorig);
47 }

The last instruction in this function, before returning to the parent algorithm, is to draw
the last line back to the first vertex of the polygon in order to close it.
By modifying the parameters at the top of this algorithm you can achieve almost endless
parametric variations (fig. 43).

fig. 43 A series of parametric results produced by


varying only the number of sides of the polygon.
58 Parametric patterns

Tiling
In mathematics, tiling is defined as the arrangement of over the required number of columns. This will result in
identical planar shapes to completely cover a given area a 2D plane of tiling units. Parametrically, any aspects of
without overlapping (fig. 44). Thus, one can think of tiling the tile can be varied as it repeats. For this introductory
as a natural extension of the concept of repetition, but tutorial, however, we will specify only a few standard
in 2D. Often, the tiling pattern relies on an underlying parameters: the size of the individual tile, the number
grid of rows and columns. As we have seen previously, of rows and columns, and the spacing between the tiles.
we can use loops to create repetition. In order to create a In order to create a more interesting and challenging
tiling pattern, we can take advantage of a nested loop (or pattern, we will use a hexagonal tile as our module. The
a loop within a loop) to repeat a script that creates a single geometry of the hexagon creates a mild challenge in
tile unit over the required number of rows but that also, that as the tiles are aggregated, they need to be offset in
within each row-creating repetition, iterates the tile unit order to match one edge of the hexagon to the other.

fig. 44 Mosaic dome interior, Nasir


al-Mulk mosque, Shiraz, Iran.
Tutorial Hexagonal tiling pattern

In order to write a parametric script that creates a hexagonal


tiling pattern, we need to understand the geometric relationship h

between the various elements of a hexagon (fig. 45). If you


inscribe a regular hexagon in a circle with radius r then the
length of each side of the hexagon is also equal to r. The 120º
interior angle of each vertex of any polygon is given by the
formula: a = ((180° × n – 360°) / n) where a is the interior d
r
angle and n is the number of sides of the polygon. Thus, the 30º
interior angle of a regular hexagon is (180° × 6 – 360°) / 6 =
120°. The distance d of the line drawn from the centre of the r
hexagon to the midpoint of one of its chords can be derived,
using trigonometry, as d = cos(30°) × r. These simple geometric
relationships will help us compute the location of hexagonal tiles
as we loop through the rows and columns of the tiling pattern.
Horizontally, the distance between each tile is r + r/2 = 1½ r.
Vertically, the distance between each tile is 2d, but additionally,
the algorithm to generate the hexagonal tiles will need to
offset the tiles vertically by d on alternating columns (fig. 46).
We can test if the column we are drawing is an even or odd-
numbered one to either include or exclude this additional offset. fig. 45 The geometry of a regular hexagon inscribed in a circle.

Step 1 Creating a basic hexagonal grid


We now have all the information we need to write the script to generate the basic
hexagonal tiling pattern. Open 3ds Max, save and close prior scenes, create a new empty
scene and choose MAXScript New Script from the top menu. In the script window
that opens, type the following basic algorithm:

1 radius = 20.0
2 columns = 5
3 rows = 5
4 offset = (cos 30)*radius
5 for i = 0 to (columns - 1) do
6 (
7 for j = 0 to (rows - 1) do
8 (
9 hex = Ngon radius:radius nsides:6 scribe:1 pos:[0,0,0]
10 case of
11 (
12 (mod i 2 == 0) : move hex[(i*1.5*radius), ((j*2*offset) + offset), 0]
13 (mod i 2 != 0) : move hex[(i*1.5*radius), (j*2*offset), 0]
14 )
15 )
16 )

Save your script and then choose Tools Evaluate All to run the script. You should
see a hexagonal grid made out of 25 hexagons. Let’s take a closer look at the script:
Hexagonal tiling pattern/CONTINUED

The first few lines define the variables we will use to construct the grid: radius,
columns, rows and the offset, as discussed earlier. Next, we create two nested
loops. The outer loop generates the columns while the inner loop generates the
rows for each column. A hexagon, stored in the variable called hex, is created using
the Ngon command with 6 specified as the number of sides (nsides ), inscribed in
a circle by specifying 1 as the value of the scribe parameter and positioned initially
at [0,0,0]. Next, we test if the variable i (i.e. the current column) is even or odd.
The modulo operation, mod, computes the remainder after a number is divided
by another number. In this case, if the remainder after division by 2 is not 0 then
that means that the number is odd. If the remainder is 0 then the number is even.
Based on this test (using the case of syntax) one of the two move operations is
carried out. If you look closely at the x (horizontal) and y (vertical) coordinates
for the move operation, they are the same as those depicted in the hexagonal
tiling figure below (fig. 46), with the additional offset amount applied to alternating
columns. For each tile, we have to multiply the x and y offset distance by the number
of the current row and current column to get the correct overall offset distance
(i.e. if the x and y spacing between tiles should be 10 mm, then the tile at the
fifth column and second row should be positioned at x = 50 mm and y = 20 mm.
While the above algorithm achieves the basic functionality, it is cumbersome to
use: to generate a new hexagonal grid, one has to change the values manually,
erase the current geometries and re-evaluate the script. One main advantage of
parametric systems is their ability to generate alternatives quickly and fluidly.
Another advantage is that once you set the parameters, some of the generated
alternatives could be unanticipated and positively surprise you. If you can predict
all the possible iterations, then the parametric system is hardly informative. In
this particular case, adding an additional spacing amount to further separate
the hexagons, or overlapping them by using a negative spacing amount, could
yield some interesting results. The spacing factor needs a bit of attention,
as it is easy to assume that it should be the perpendicular distance between
the edges of the hexagons, rather than the horizontal and vertical offset the
algorithm actually requires. Using the Pythagorean theorem regarding the
relationship between the three sides of a right-angled triangle, we can derive
the desired horizontal offset as follows: a2 + (s/2)2 = s2; thus a = s√0.75 (fig. 47).
You will find this applied in the expanded algorithm in the following script.

C1 C2

R2
s
S/2
2d S
a

R1

r r/2

fig. 46 The tiling distances for creating edge-to-edge hexagonal tiling. fig. 47 Computing the horizontal and vertical offsets for additional
spacing between the tiles.
Tiling 61

Step 2 Creating a parametric hexagonal grid


To make our hexagonal grid parametric, we need to enhance the above script.
First, we need to add an additional parameter (to be called spacing). Then, we
need to create an interface that presents the desired parameters to the user,
who can then view different alternatives in real time by changing the values of the
parameters. This can be achieved simply in 3ds Max by creating a utility script
with a rollout user interface. We can encapsulate the above basic algorithm
in a function that is called upon when the interface reports back that the user
has changed the value of a certain parameter. In order to update the hexagonal
grid fluidly, the function should erase the grid and redraw it with the new
parameters. On modern computers, this happens so quickly that the resulting
effect is that of instantaneous change. The expanded script is found below:

1 utility Hexagons “Hexagons”


2 (
3 global radius = 20.0
4 global spacing = 0
5 global rows = 5
6 global columns = 5
7 global myHexagons = #() -- an array of hexagons
8
9 -- This function erases the previous grid and creates a new one.
10 fn generateHexagons =
11 (
12 -- Empty the myHexagons array and delete all the hexagons in it.
13 hexCount = myHexagons.count
14 for i = 1 to hexCount by 1 do
15 (
16 tobedeleted = myHexagons[1]
17 deleteItem myHexagons 1
18 if(isDeleted tobedeleted != true) then
19 (
20 delete tobedeleted
21 )
22 )
23 myHexagons.count = 0
24
25 offset = (cos 30)*(radius) + (spacing / 2.0)
26
27 for i = 0 to (columns - 1) by 1 do
28 (
29 for j = 0 to (rows - 1) by 1 do
30 (
31 hex = Ngon radius:radius nsides:6 scribe:1 pos:[0,0,0]
32 hex.wirecolor = white
33 case of
34 (
Hexagonal tiling pattern/CONTINUED

35 (mod i 2 == 0) : move hex [(i*((radius*1.5) + (spacing * (sqrt 0.75)))), ((j*2*offset) + offset), 0]


36 (mod i 2 != 0) : move hex [(i*((radius*1.5) + (spacing * (sqrt 0.75)))), (j*2*offset), 0]
37 )
38 append myHexagons hex
39 )
40 )
41 )
42
43 -- Create the User Interface
44
45 spinner radius_spinner “Radius: “ range:[1,5000,radius] type:#WorldUnits
46 spinner spacing_spinner “Spacing: “ range:[-5000,5000,spacing] type:#WorldUnits
47 spinner rows_spinner “Rows: “ range:[0,5000, rows] type:#integer
48 spinner columns_spinner “Columns: “ range:[0,5000, columns] type:#integer
49 button generate_button “Generate” enabled:true
50
51 on radius_spinner changed amt do -- when spinner value changes...
52 (
53 radius = amt
54 generateHexagons()
55 )
56
57 on spacing_spinner changed amt do -- when spinner value changes...
58 (
59 spacing = amt
60 generateHexagons()
61 )
62
63 on rows_spinner changed amt do -- when spinner value changes...
64 (
65 rows = amt
66 generateHexagons()
67 )
68
69 on columns_spinner changed amt do -- when spinner value changes...
70 (
71 columns = amt
72 generateHexagons()
73 )
74
75 on generate_button pressed do
Tiling 63

76 (
77 generateHexagons()
78 )
79 )
80 -- end of utility

Save your script and then choose Tools Evaluate All to run the script. The actual
interface can be found by clicking on the utilities icon (the hammer), then by clicking
on the MAXScript button and choosing the Hexagons utility from the Utilities menu
in the MAXScript rollout that appears. You can experiment with various values
to the parameters to generate interesting hexagonal tiling patterns (fig. 48).

fig. 48 Different parametric hexagonal tiling patterns generated by the same script
using positive and negative spacing.
64 Parametric patterns

Case study RK4 Tiles, New York, USA


Designer Studio Mode (Ronnie Parsons and Gil Akos)
Client Private Commission
Design and Construction 2010

Left
A single RK4 tile made of highly
reflective polyurethane.

Opposite
Close-up view of the RK4 tile
showing its flowing plasticity.

Studio Mode, a Brooklyn, New York research iconography based on the digital manipulation
and design studio, is actively engaged in the of a traditional tiling pattern, called Cairo
employment of digital technologies in order to tessellation. The tiles designed by the studio
investigate form-making. The studio defines its were used to compose a relief panel for a
main focus as ‘material and the processes by residential entry foyer, in which the original
which it is formed and informed’. Their projects pattern of the Cairo tiling is also maintained,
constitute formal explorations of broader, but only as a geometric background.
long-standing issues in architectural theory, For the design of the tiles, the firm began with
which are now enhanced by the new potentials a 30-degree tilted square grid that underwent
of the computer. In their diPloids project, for four stages of tessellation. The result was a grid of
example, they used a single, flexible shape as irregular pentagons that maintained the topology
a stitching or weaving unit to produce multiple of the original tiles. The studio identified five
iterations of a new architectural skin iconography. focal points on each pentagon, inspired by the
In their ParaGrove installation, the studio pattern of the Cairo tiling, and applied a network
investigated the technique of stitching as both of curvilinear streamlines – a visualization of
a design tool and a methodology for creating a flows – between those points. The pattern that
contemporary interpretation of the relationship was produced in this manner visually suggested a
between structure, surface and enclosure. 3D interpretation of the original 2D floral pattern
Here we will make a more detailed reference of the Cairo tiles. The designers took advantage
to their RK4 Tiles. In this project, the studio of this quality to produce tiles with a surface
focused on the implementation of a new surface that embodied both the flowing plasticity and
66 Parametric patterns

Above Below
Segmentation of the pattern into pentagonal tiles. Derivation of the curvilinear streamlines based
on an underlying Cairo tessellation pattern.

the sculptural quality of the streamlines. The final tiles are made from polyurethane and they
choice of the focal points was instrumental in possess a highly reflective, undulating surface that
making possible the surface continuity across lacks any classical geometric clarity or symmetry,
the edge of the tiles and thus turning the 2D but which echoes the repetitive geometry of
pattern of the streamlines into a fluid, 3D relief the traditional Cairo tile. In the final product,
that moves seamlessly across the tiles. the geometric essence of the Cairo tile pattern
Using a computer model that was built has been morphed into a freer, more seductive
according to the process described above, they form, which extends into the third dimension.
were able to accurately calculate the cross-
section profile of the designed tiles and therefore
the exact form of their 3D surface. Based on
this model, a positive milled mould was made
using CNC equipment and was then employed
to produce a silicon negative mould. In the final
stage of the process, the silicon negative mould
facilitated the production of the final tiles. These
tiling 67

Pour hole Expansion hole


E
Clamp position Clamp position
A
D
C
B

EE

DD

CC

BB

AA
D
C
B
E

milled positive
E

A
D
C
B

EE

DD Cast position
CC

BB

AA

Jig peg Jig position


D
C
B
E

Cast silicon negative


milled Negative mould
E

A
D
C
B

positive
EE

DD

CC

BB

AA
D
C
B
E

Cast polyurethane positive mould making jig assembly tile making jig assembly

Above Below
A set of drawings illustrating the process Measured elevation drawing of the full panel of tiles.
of digitally fabricating and assembling the
mould for pouring the polyurethane tiles.

3.7 m (12’ 3 1/2”)


2 m (6’ 61/2”)
1.5 m (5’ 0”)

111/8”)
0.6 m (1’
68 Parametric patterns

Recursion
Recursion is a special case of repetition in which the square that is half the size of the original square, then at
repetition is achieved by having a process call upon the next iteration, the newly generated square would be
itself to generate the next iteration. Formally, recursion half of the size of the one that preceded it and thus one
is defined as the process of repeating items in self- quarter of the size of its grandparent square. In nature, the
similar ways. A Menger sponge is a classic example of recursive pattern is usually distorted and limited by the
a mathematical construct that exhibits clear recursion. environment in which it is taking place. As the pattern
A Menger sponge, named after Karl Menger who repeats, it parametrically takes into consideration the
described it in 1926, is said to have an infinitely large conditions of the parent pattern as well as the forces of
surface area while simultaneously and paradoxically nature operating on it, as seen in the Brassica Romanesco
enveloping a null volume. To create a Menger sponge, plant (fig. 51). However, in an ideal situation where the
you start with a cube. You then subdivide this cube into recursive function can continue unhindered, we can
27 identical smaller cubes (9 squares on each side). You imagine infinitely small or infinitely large self-similar
then delete the cube at the very centre of its parent cube patterns. Thinking of the metaphor of the branching
as well as the six cubes that occupy the centre of each hierarchy of a family tree or the nesting of Russian
of the faces of the parent cube. This creates a hollow matryoshka dolls is useful in understanding how recursion
3D cross shape in the centre of the parent cube. Then, works algorithmically (fig. 52). One important step
you recursively apply the above steps to each of the in writing a recursive algorithm is to always specify a
remaining 20 smaller cubes as many times as you wish. limiting factor lest the function recursively repeat itself
This recursive operation results in the characteristic an infinite amount of times. The algorithm would thus
self-similar pattern of a Menger sponge (fig. 49). never stop and never yield a result and would have to be
Fractals are another classic example of recursion; the interrupted. This limiting factor could be in the form of
propagation of this kind of pattern depends on the same testing the size of the pattern to be generated (i.e. defining
action being performed on the root pattern, on all its a minimum size), the total number of generated elements
descendants, on all their descendants and so on (fig. or the level of recursion that has taken place thus far (i.e.
50). For example, if a pattern calls for creating a second defining a maximum number of recursive iterations).

fig. 49 Three recursive iterations of


constructing a Menger sponge.
Recursion 69

fig. 50 A Magnet Julia fractal


set rendered as a landscape.

fig. 51 The Brassica fig. 52 Russian matryoshka dolls.


Romanesco plant.
Tutorial Nested geometry

In this introductory tutorial, we will create a simple recursive be easily converted into an interactive and parametric 3ds Max
function that starts with an initial geometry – in this case a utility, following the same procedure as step 2 of the tutorial to
box – which is then copied, rotated and scaled. This process is create a hexagonal tiling pattern (see page 61).
recursively repeated to build a helical form. This algorithm can

To start, open 3ds Max, save and close any prior scenes, create a new empty scene
and choose MAXScript New Script from the top menu. In the script window that
opens, type the following basic algorithm:

1 resetMaxFile #noPrompt
2 level = 1
3 parentBox = box width:100 length:100 height:10
4 fn createChild arg currentLevel =
5 (
6 if currentLevel < 50 then
7 (
8 child = copy arg
9 child.width = (arg.width)*0.95
10 child.length = (arg.length)*0.95
11 child.height = (arg.height)*0.95
12 child.pos.z = arg.pos.z + arg.height
13 rot = eulerangles 0 0 3.5
14 rotate child rot
15 currentLevel = currentLevel + 1
16 child.parent = arg
17 createChild child currentLevel
18 )
19 )
20 createChild parentBox level

Save your script and then choose Tools Evaluate All to run the
script. You should see a helical form made of 50 boxes (fig. 53).
Recursion 71

fig. 53 Recursive helical form.

Let’s take a closer look at the script:


The first step is to reset 3ds Max. This step erases all existing objects and
resets 3ds Max, so be careful not to have any prior scene objects that you
wish to keep. Next, we create a variable called level to store the current
level of recursion. We will use this variable as the limiting factor for our
recursion. At the start of each recursive iteration, we will add 1 to this
variable and then test whether it has reached a pre-defined maximum. If it
has, then we will stop the algorithm at that level. Then we create the initial
geometry that will be copied. In this case, it is a simple box of dimensions
100 x 100 x 10. Next, the recursive function, createChild, is defined. This
function accepts two arguments: the first, called arg, is the geometry to be
copied. This geometry will be updated for each consequent iteration. The
second argument is the current recursion level. We will use that variable to
stop the recursion. In this function, we have chosen to execute it only if the
recursion level is less than 50. The actual function is simple: it copies arg
into a new geometry, scales it down by 5%, lifts it up to sit on top of the prior
geometry and rotates it by 3.5°. The recursion level is then incremented by
1. The next (optional) step is to link the child object to its parent by setting
the parent attribute of the new geometry to be arg. This step makes it easy
to drag the final result in 3ds Max as if it is a single geometry. It creates
a chain link from the topmost box of the helical form to the lowest one at
its base. The actual recursion happens at the last step, where the function
calls itself, but with the newly created child object and the new recursion
level. The whole procedure is kick-started at the last line of the code,
by calling createChild with the original parent object and a level of 1.
Tutorial Simple fractals

In this slightly more advanced tutorial, we will write a recursive However, the second and subsequent iterations pose a
function that creates square-shaped fractal geometry. It starts slight problem. If not modified, the rule would result in one
with an initial geometry – in this case a box – that is then of the three boxes being embedded inside its grandparent
propagated into four smaller children boxes to be placed box (fig. 55). Thus, for each of the four boxes, we need to
at the four corners of the parent box (fig. 54). The operation test for intersection with the grandparent box and, if true,
is then recursively repeated on each of these four boxes. we need to delete the intersecting grandchild box.

fig. 54 Initial propagation rule. fig. 55 Second recursive iteration rule.

Open 3ds Max, save and close any prior scenes, create a new empty scene and
choose MAXScript New Script from the top menu. In the script window that
opens, type the following algorithm:

1 resetMaxFile #noPrompt
2 myLevel = 1
3 global rootBox = box width:20 length:20 height:10
4
5 fn intersect newBox rBox =
6 (
7 result = false
8
9 if(rBox == undefined) then
10 (
11 return false
12 )
13
14 if(newBox == undefined) then
15 (
16 return false
17 )
18 d1 = distance newBox.pos rBox.pos
19 d2 = (newBox.width)*0.5 + (rBox.width)*0.5
20 if(d1 < d2) then
21 (
22 result = true
23 )
24 return result
Recursion 73

25 )
26
27 fn createChildren arg currentLevel =
28 (
29 if currentLevel < 6 then
30 (
31 child01 = copy arg
32 child01.width = (arg.width)*0.5
33 child01.length = (arg.length)*0.5
34 child01.height = (arg.height)*0.75
35 child01.pos.x = arg.pos.x + (arg.width)*0.75
36 child01.pos.y = arg.pos.y + (arg.length)*0.75
37
38 result01 = intersect child01 arg.parent
39 if (result01 == false) then
40 (
41 child01.parent = arg
42 )
43 else
44 (
45 delete child01
46 )
47
48 child02 = copy arg
49 child02.width = (arg.width)*0.5
50 child02.length = (arg.length)*0.5
51 child02.height = (arg.height)*0.75
52 child02.pos.x = arg.pos.x - (arg.width)*0.75
53 child02.pos.y = arg.pos.y + (arg.length)*0.75
54
55 result02 = intersect child02 arg.parent
56 if (result02 == false) then
57 (
58 child02.parent = arg
59 )
60 else
61 (
62 delete child02
63 )
64
65 child03 = copy arg
66 child03.width = (arg.width)*0.5
67 child03.length = (arg.length)*0.5
Simple fractals/CONTINUED

68 child03.height = (arg.height)*0.75
69 child03.pos.x = arg.pos.x + (arg.width)*0.75
70 child03.pos.y = arg.pos.y - (arg.length)*0.75
71
72 result03 = intersect child03 arg.parent
73 if (result03 == false) then
74 (
75 child03.parent = arg
76 )
77 else
78 (
79 delete child03
80 )
81
82 child04 = copy arg
83 child04.width = (arg.width)*0.5
84 child04.length = (arg.length)*0.5
85 child04.height = (arg.height)*0.75
86 child04.pos.x = arg.pos.x - (arg.width)*0.75
87 child04.pos.y = arg.pos.y - (arg.length)*0.75
88
89 result04 = intersect child04 arg.parent
90 if (result04 == false) then
91 (
92 child04.parent = arg
93 )
94 else
95 (
96 delete child04
97 )
98
99 currentLevel = currentLevel + 1
100 for i = 1 to arg.children.count by 1 do
101 (
102 createChildren arg.children[i] currentLevel
103 )
104 )
105 )
106
107 createChildren rootBox myLevel
recursion 75

save your script and then choose Tools Evaluate all to run the
script. You should see a fractal form made of many boxes (fig. 56).

fig. 56 The recursion script is used to create an imaginary fractal city.

Let’s take a closer look at the script:

1 resetmaxFile #noPrompt
2 mylevel = 1
3 global rootbox = box width:20 length:20 height:10

the first step is to reset 3ds Max. this step erases all existing objects and resets 3ds
Max so be careful not to have any prior scene objects that you wish to keep. next, we
create a variable called myLevel to store the current level of recursion. We will use this
variable as a limiting factor for our recursion. at the start of each recursive iteration,
we will add 1 to this variable and then test if it has reached a pre-defined maximum.
if it has, then we will stop the algorithm at that level. then, we create the initial
geometry that will be copied. in this case, it is a simple box of dimensions 20 x 20 x 10.

5 fn intersect newbox rbox =


6 (
7 result = false
8
9 if(rbox == undefined) then
10 (
11 return false
12 )
13
14 if(newbox == undefined) then
15 (
16 return false
17 )
18 d1 = distance newbox.pos rbox.pos
SimPlE FraCtalS/CoNtiNuEd

19 d2 = (newbox.width)*0.5 + (rbox.width)*0.5
20 if(d1 < d2) then
21 (
22 result = true
23 )
24 return result
25 )

the intersect function accepts two arguments (newbox and rbox ). the function
returns true if the two boxes intersect and false if they do not. if either of the two
boxes is undefined for any reason, it also returns false. next, it carries out a simplified
intersection test that compares the distance between the centroids of the boxes (d ) to the
sum of half of their widths ((w1 + w2) /2). While not a true intersection test, we can use
this simplified method to determine if the box lies inside its grandparent box, because
in this case, d will always be less than (w1 + w2) /2 (fig. 57).

w2

w2
d

w1 w1

d > (w1 + w2) / 2 => boxes do not intersect d < (w1 + w2) / 2 => boxes do intersect

fig. 57 A simplified intersection test.


w1/2
w1/2
++w2/2
w2/2==
d1d1 w1/2
w1/2
++w2/2
w2/2==
d1d1
d1d1
>>d2d2
=>=>
Boxes
Boxes
dodo
not
not
intersect
intersect d1d1
<<d2d2
=>=>
Boxes
Boxes
dodo
intersect
intersect
Recursion 77

27 fn createChildren arg currentLevel =


28 (
29 if currentLevel < 6 then
30 (
31 child01 = copy arg
32 child01.width = (arg.width)*0.5
33 child01.length = (arg.length)*0.5
34 child01.height = (arg.height)*0.75
35 child01.pos.x = arg.pos.x + (arg.width)*0.75
36 child01.pos.y = arg.pos.y + (arg.length)*0.75
37
38 result01 = intersect child01 arg.parent
39 if (result01 == false) then
40 (
41 child01.parent = arg
42 )
43 else
44 (
45 delete child01
46 )

The createChildren function is the recursive function that creates four children boxes
at each corner of the box it receives through the arg argument. It will only execute its
code if the current recursion level (currentLevel ) is less than 6. Thus, it will create a
maximum of 5 levels of recursion. A child (child01 ) is created as a copy of the current
arg box, reduced in size, and placed at a corner vertex. Once it is created, the simplified
intersection test is called in order to determine whether the child box intersects its
grandparent (i.e. the parent of the arg box). If the intersection test returns false, then
the arg box is defined as the parent of the child. Otherwise, the child is deleted.
This process is repeated for the other three boxes.

99 currentLevel = currentLevel + 1
100 for i = 1 to arg.children.count by 1 do
101 (
102 createChildren arg.children[i] currentLevel
103 )

After the four children have been created (one always having been deleted because
it intersected its grandparent, leaving three new boxes), the current recursion level is
incremented by 1. Next, we loop through the newly created children of arg and, for each
of them, we recursively call the createChildren function to create three more children,
and so on.

107 createChildren rootBox myLevel

The recursive cycle is actually started at the very last line of code where the createChildren
is called with the initial central box (rootBox ) and a level of 1 (myLevel ).
78 Parametric patterns

Case study Genetic Stair, Upper West Side, New York, USA
Designer Caliper Studio, Brooklyn, New York, USA
Client Private Commission
Design and Construction 2009

The Genetic Stair was designed to be the for the stainless-steel hollow pipes and solid rods Above
centrepiece of a renovated apartment and art that formed the structural latticework under the Genetic Stair within the space.
Photograph © Ty Cole.
gallery in New York’s Upper West Side. The stair. The candidate solution was then passed,
goal was to create a slender stair that would as a series of centrelines, to a structural finite Opposite
only be supported at the bottom and top, and elements analysis (FEA) system. The customized Approach from below.
that would turn three times to climb 4.6 m. software used the FEA results within a genetic Photograph © Ty Cole.

The design required a rethinking of both the algorithm to ‘breed’ strong members and remove
design process and the role of the architect. weaker ones. The final form of the stair was
At the beginning of the process, agreed reached after several iterations of this analysis of
design details and their limiting factors became the structural performance of members, which
the driving geometric constraints for the stair’s selected strong ones and eliminated weaker ones
overall parametric model. Custom software was while adhering to strict fabrication constraints.
created and integrated with McNeel’s Rhinoceros With this process, the architectural team
3D software to generate potential arrangements was able to remove the design and fabrication
80 Parametric patterns

Left
makeFirstGeneration Creates one generation of completely random stair configurations. Flowchart of the algorithm that
generates and analyzes the structural
RHINO 4.0 + RhinoScript

DO until number of individuals reached


members of the staircase.
DO until allowable number of rods reached
addRandomRod
Adds random diaganol element that meets
predetermined fabrication constraints and
does not intersect previously created elements.
LOOP until allowable number of rods reached

exportTextFile
Converts software-specific 3D information into nodes,
connections and material identities. Writes data to a
newly created text file.
LOOP until number of individuals reached

TEXT FILES DESCRIBING GEOMETRIC AND MATERIAL


INFO FOR EACH INDIVIDUAL IN GENERATION

evaluateStairConfigurations Imports text files and evaluates configurations for structural performance.

FOR EACH stair configuration in generation


importStairConfiguration
Converts text-based node and connection
data to 3D geometry.
applyMaterials
Assigns material properties (strength, stiffness,
etc.) to 3D members.

FOR EACH node in structural model


constrainNode
CADRE Lite 3.2 + VBscript

Assigns degrees of freedom, including


completely fixed connections at the top
and bottom.
applyLoads
Assigns units of force acting on node
due to dead weight and live load.
NEXT node in structural model

solveModel
Performs finite element analysis on fully
constrained and loaded 3D model.
exportResults
Writes results of finite element analysis
to separate text files.
NEXT stair configuration in generation

TEXT FILES DESCRIBING STRUCTURAL PERFORMANCE


OF EACH INDIVIDUAL IN GENERATION

makeNextGeneration Creates a new generation based on weighted selection of genetic material.

DO until number of individuals reached


importStair_1
Selects and imports text file of configuration from
previous generation. Probability of selection is
determined based on structural performance.
importStair_2
Selects and imports text file of configuration from
previous generation. Probability of selection is
determined based on structural performance.
assignCrossoverPoint
Location chosen at random between top and
bottom of stair layout.
removeRodsFromStair_1
Rods above Crossover Point are removed from
the Stair_1 configuration.
removeRodsFromStair_2
Rods below Crossover Point are removed from
the Stair_2 configuration.
RHINO 4.0 + RhinoScript

removeIntersectingRods
Conflicts in the new configuration that would
have a negative impact on constructability are
resolved with an eye towards minimal disruption
to the new arrangement.
mutationFunction
Occasionally adds, removes or alters one or
more rods in random fashion.
exportTextFile
Converts software-specific 3D information into
nodes, connections and material identities.
Writes data to a newly created text file.
UNTIL number of individuals reached

TEXT FILES DESCRIBING GEOMETRIC AND MATERIAL


INFO FOR EACH INDIVIDUAL IN GENERATION
Recursion 81

Left
Section-perspective drawing of stair.

Top
CNC-milled guide for tubes placement.

Above
Tubes placed in guide and ready for welding.

of the stair from the purview of the contractor templates, which were then wrapped around frame is punctuated by varying densities of
– a rarity in traditional architectural projects. the steel members to act as guidelines for hole diagonal struts as it turns its way unsupported
More importantly, however, and in a reversal and edge cutting. This resulted in very accurate through 270 degrees in a visual language that
of a traditional design process, the fabrication and clean joinery of the structural elements. speaks to a controlled complexity inherent
team collaborated on the details of the stair The result is a beautiful, free-standing to the process by which it was designed.’
from the outset of the project, and the designers structure, which integrates parametric, material,
were active throughout the fabrication phase. structural and aesthetic concerns. As Caliper
In order to build the complex intersecting Studio’s Nicholas Desbiens explains, the Genetic
latticework with sufficent accuracy, formwork Stair is made of ‘48 unique stainless-steel pipes
panels were digitally derived and fabricated to with 1,400 angled holes, 253 connecting steel
guide the placement of pipes and rods. Intricate rods cut to length, 22 translucent Corian treads,
intersections between pipes and rods were 18 plates of glass and over 250 miscellaneous
unfolded from the 3D model and printed on paper connecting components. The tubular-steel
82 Parametric patterns

Subdivision
In many cases, designers working with smooth scripting, one would have little control over the method
surfaces and forms need to subdivide them in order of subdivision and would have to accept what the software
to unfold them into planar components that can be offers. For example, converting a NURBS surface in 3ds
digitally fabricated on CNC machines or laser cutters. Max using one of the standard surface approximation
Subdivision of a surface is something like the cracks techniques could yield several interesting topological
found in deserts (fig. 58). It is a process of separating an subdivisions, but can also create undesirable ones (fig.
otherwise continuous surface into smaller components 60). If precise control over topological subdivision
by tracing, scoring or cutting lines through the surface. is desired and, in particular, if the desired solution
Most modern 3D modelling software can render smooth is one that is not easily achievable by manipulating
surfaces and allow for their automatic subdivision and the user interface of the modelling environment,
approximation (fig. 59). However, without the power of then a custom script needs to be written (fig. 61).

fig. 58 Desert cracks.


Subdivision 83

fig. 59 A smooth NURBS surface.

fig. 60 Subdivided NURBS surface


using several built-in methods.

fig. 61 Subdivided NURBS surface


using a custom diagrid script.
Tutorial Simple diagrid mesh

In this introductory tutorial, we will create a flat mesh surface 3D point with X, Y and Z coordinates. (One requirement for a
that is subdivided using a diagonal grid (diagrid). While this may well-formed mesh surface is that vertices should not coincide.
seem an easy task, creating a properly formed mesh surface That is, if a vertex exists at a certain location, no other vertex
in 3ds Max MAXScript requires careful planning. To start, should exist at that same location.) Each row in the faces array
we need to understand how 3ds Max creates and stores a contains three integers, which are the indices of three 3D points
mesh data structure. A mesh surface in 3ds Max is made of in the vertices array that, together, make up one triangle. For
two lists, or, more precisely, two arrays: a vertices array and example, if one wishes to create a triangular face that connects
a faces array. The vertices array contains all the vertices of the fifth, second and fourth points in the vertices array, then
the surface, stored as 3D points. That is, each row contains a one would store [5, 2, 4] in one row of the faces array (fig. 62).

Faces
Faces Vertices
Vertices

1 2 3 X Y Z 5

1 5 2 4 1 32.567 24.674 45.041


4
1
2 4 2 6 2 63.592 23.562 42.691

3 55.667 22.569 51.099

2 2
4 32.444 76.002 61.563

5 31.136 25.665 41.988

6 50.023 21.459 63.989 6

fig. 62 Mesh data structure. fig. 63 Vertex organization in a diagrid mesh.

Now that we understand the internal data structure of meshes, we can start building our
own mesh. If we look closely at the vertices of a diagrid mesh, we notice that every other
row has one less vertex than the one before it. Moreover, the vertices are also shifted by
half the unit grid size (fig. 63).
We are now ready to create the script. In this case, we are going to create a true
parametric geometry that can be modified at will in exactly the same manner as other
geometries in 3ds Max.
Open 3ds Max, save and close any prior scenes, create a new empty scene and
choose MAXScript New Script from the top menu. In the script window that
opens, type the following algorithm:

1 plugin simpleObject diagridmesh_plugin_def


2 name:”Diagrid Mesh”
3 classID:#(0x43771d8e, 0x561950f2)
4 category:”Scripted Primitives”
5 (
6 parameters main rollout:params
7 (
8 u type:#integer ui:u_spinner default:5
9 v type:#integer ui: v_spinner default:5
10 meshLength type:#worldunits ui:meshLength_spinner default:50
11 meshWidth type:#worldunits ui:meshWidth_spinner default:50
12 rotated type:#boolean ui:rotated_checkbox default:false
13 )
Subdivision 85

14
15 rollout params “Parameters”
16 (
17 spinner u_spinner “U:” type:#integer range:[1,10000,10]
18 spinner v_spinner “V:” type:#integer range:[1,10000,10]
19 spinner meshLength_spinner “Length” type:#worldunits range:[-10000,10000,0]
20 spinner meshWidth_spinner “Width” type:#worldunits range:[-10000,10000,0]
21 checkbox rotated_checkbox “Rotated” checked:rotated
22 )
23
24 on buildMesh do
25 (
26 vertices = #()
27 faces = #()
28 nc = u
29 nr = v*2
30
31 case of(
32 (rotated == true) : (unitLength = meshWidth/ nr; unitWidth = meshLength/ nc)
33 (rotated == false) : (unitLength = meshLength/ nr; unitWidth = meshWidth/ nc)
34 )
35
36 -- Create Vertices.
37 for i = 0 to nr by 1 do
38 (
39 case of(
40 (mod i 2 != 0) : (hoffset = 0.5; deduct = 1)
41 (mod i 2 == 0) : (hoffset = 0.0; deduct = 0)
42 )
43 for j = 0 to (nc - deduct) by 1 do
44 (
45 vx = (j + hoffset)*unitWidth
46 vy = i*unitLength
47 case of(
48 (rotated == true) : append vertices [vy, vx, 0]
49 (rotated == false) : append vertices [vx, vy, 0]
50 )
51 )
52 )
53
54 -- Create first set of triangles.
55 for i = 1 to nr by 2 do
56 (
Simple diagrid mesh/continued

57 for j = 1 to nc by 1 do
58 (
59 v1 = (i - 1)*(nc + 1) - ((i - 1)/2) + j
60 v2 = (i - 1)*(nc + 1) - ((i - 1)/2) + j + 1
61 v3 = (i - 1)*(nc + 1) - ((i - 1)/2) + j + (nc + 1)
62 append faces [v1, v2, v3]
63
64 if (j < nc) then
65 (
66 v1 = (i - 1)*(nc + 1) - ((i - 1)/2) + j + (nc + 1)
67 v2 = (i - 1)*(nc + 1) - ((i - 1)/2) + j + 1
68 v3 = (i - 1)*(nc + 1) - ((i - 1)/2) + j + (nc + 2)
69 append faces [v1, v2, v3]
70 )
71 )
72 )
73
74 -- Create second set of triangles.
75 for i = 3 to (nr+1) by 2 do
76 (
77 for j = 1 to nc by 1 do
78 (
79 v1 = (i - 1)*(nc + 1) - ((i - 1)/2) + j + 1
80 v2 = (i - 1)*(nc + 1) - ((i - 1)/2) + j
81 v3 = (i - 3)*(nc + 1) - ((i - 3)/2) + j + (nc + 1)
82 append faces [v1, v2, v3]
83
84 if (j < nc) then
85 (
86 v1 = (i - 3)*(nc + 1) - ((i - 3)/2) + j + (nc + 1)
87 v2 = (i - 3)*(nc + 1) - ((i - 3)/2) + j + 1 + (nc + 1)
88 v3 = (i - 1)*(nc + 1) - ((i - 1)/2) + j + 1
89 append faces [v1, v2, v3]
90 )
91 )
92 )
93
94 -- Create left and right triangular edges
95 for i = 1 to nr by 2 do
96 (
97 v1 = (i - 1)*(nc + 1) - ((i - 1)/2) + 1
Subdivision 87

98 v2 = (i - 1)*(nc + 1) - ((i - 1)/2) + 1 + (nc + 1)


99 v3 = (i + 1)*(nc + 1) - ((i + 1)/2) + 1
100 append faces [v1, v2, v3]
101
102 v1 = (i + 1)*(nc + 1) - ((i + 1)/2) + nc + 1
103 v2 = (i - 1)*(nc + 1) - ((i - 1)/2) + nc + (nc + 1)
104 v3 = (i - 1)*(nc + 1) - ((i - 1)/2) + nc + 1
105 append faces [v1, v2, v3]
106 )
107
108 -- Create the mesh
109 setMesh mesh verts:vertices faces:faces
110 )
111
112 -- Respond to user interaction events
113 tool create
114 (
115 on mousePoint click do
116 (
117 case click of
118 (
119 1: nodeTM.translation = gridPoint
120 2: #stop
121 )
122 )
123
124 on mouseMove click do
125 (
126 case click of
127 (
128 2: (meshWidth = gridDist.x; meshLength = gridDist.y)
129 3: #stop
130 )
131 )
132 )
133 )

Save your script and then choose Tools Evaluate All to run the script. Set the
viewport to display face edges by clicking on the display mode (e.g. Realistic or
Smooth+Highlights in the upper left corner of the viewport) and choosing that option.
This will enable you to see the diagrid lines as you create the surface. Since we created
an actual scripted geometry you will find the button to create the diagrid mesh under
Create Geometry Scripted Primitives. This option is available at the bottom of the
pull-down geometry categories menu. Next, click on the Diagrid Mesh button and drag a
rectangle in the viewport. Press the Escape key to end the creation process. You should
see a rectangle in the viewport subdivided using a diagrid.
Simple diagrid mesh/continued

Let’s take a closer look at the script:

1 plugin simpleObject diagridmesh_plugin_def


2 name:”Diagrid Mesh”
3 classID:#(0x43771d8e, 0x561950f2)
4 category:”Scripted Primitives”
5 (

This creates a simple object plugin that we are naming diagridmesh_plugin. We then
define the actual button title that is displayed in the user interface as ‘Diagrid Mesh’.
Each plugin in 3ds Max requires a unique class ID. This ID can be generated at any
time. Choose MAXScript  MAXScript Listener… then type genClassID() into the
lower portion of the window. A number similar to :#(0x43771d8e, 0x561950f2) will be
displayed. Copy and paste that number in your script to create your own unique ID for
your plugin. Alternatively, you can also keep the above ID as it is. Next, we create a new
class of geometries called ‘Scripted Primitives’, in order to distinguish it from other
categories such as ‘Standard Primitives’, ‘Extended Primitives’, etc.

6 parameters main rollout:params


7 (
8 u type:#integer ui:u_spinner default:5
9 v type:#integer ui: v_spinner default:5
10 meshLength type:#worldunits ui:meshLength_spinner default:50
11 meshWidth type:#worldunits ui:meshWidth_spinner default:50
12 rotated type:#boolean ui:rotated_checkbox default:false
13 )

In the next section of the script we create the parameters for our scripted geometry. In
this case, we specify u and v values (think of u and v as rows and columns), the overall
mesh length and width, and whether we wish to rotate the diagrid 90 degrees. This
last parameter is a true/false option that will be represented using a checkbox. Each
parameter specifies a user interface (ui ) element from which it derives its value.

15 rollout params “Parameters”


16 (
17 spinner u_spinner “U:” type:#integer range:[1,10000,10]
18 spinner v_spinner “V:” type:#integer range:[1,10000,10]
19 spinner meshLength_spinner “Length” type:#worldunits range:[-10000,10000,0]
20 spinner meshWidth_spinner “Width” type:#worldunits range:[-10000,10000,0]
21 checkbox rotated_checkbox “Rotated” checked:rotated
22 )

The next section, titled rollout, specifies and connects each parameter to its user
interface element. We are careful to use the same name for the user interface elements
that we specified in the prior section. The u and v parameters are integers (no decimal
point). The mesh length and width are of type #worldunits (so they will display
measurement units per the user preference). And lastly, the rotated_checkbox user
interface is simply a checkbox. When it is checked, the diagrid is rotated 90 degrees.
Subdivision 89

24 on buildMesh do
25 (
26 vertices = #()
27 faces = #()
28 nc = u
29 nr = v*2
30
31 case of(
32 (rotated == true) : (unitLength = meshWidth/ nr; unitWidth = meshLength/ nc)
33 (rotated == false) : (unitLength = meshLength/ nr; unitWidth = meshWidth/ nc)
34 )

The next section is a callback function. It needs to be named buildMesh because it gets
automatically called by 3ds Max whenever it needs to re-build and display the mesh (e.g.
if the user changed the parameters or hid and then re-displayed the mesh). The code in
this section includes full instructions on how to create the resulting mesh. At the start
of this function we specify two arrays called vertices and faces to store the data for the
diagrid mesh. We also define two variables for the number of columns (nc ) and number
of rows (nr ) that are derived from the specified u and v values. In order to create a well-
formed diagrid, we restrict the number of rows to an even number by multiplying the
given v value by 2. What remains to be done is to derive the unit length and unit width by
dividing the overall length by the number of rows and the overall width by the number of
columns. We swap these values if the user has chosen to rotate the grid.
As you will see later, at the end of this function, you will store the mesh in a specific
variable called, unsurprisingly, mesh. It is this data structure that 3ds Max will use to
display the mesh.

36 -- Create Vertices
37 for i = 0 to nr by 1 do
38 (
39 case of(
40 (mod i 2 != 0) : (hoffset = 0.5; deduct = 1)
41 (mod i 2 == 0) : (hoffset = 0.0; deduct = 0)
42 )
43 for j = 0 to (nc - deduct) by 1 do
44 (
45 vx = (j + hoffset)*unitWidth
46 vy = i*unitLength
47 case of(
48 (rotated == true) : append vertices [vy, vx, 0]
49 (rotated == false) : append vertices [vx, vy, 0]
50 )
51 )
52 )
Simple diagrid mesh/continued

In this section we create two nested for loops in order to 42 43 44 45


specify the location of the rows and columns of vertices. We
use the mod function, as we have done previously in step 37 38 39 40 41
1 of the tutorial to create a hexagonal tiling pattern (see
page 59) to determine if we are on an odd or even numbered 33 34 35 36
iteration. For an odd-numbered iteration (which translates
into an even-numbered row, since we are counting from 0), 28 29 30 31 32
we shift the vertices by half the original unit distance and
deduct one vertex from the total number of columns to create. 24 25 26 27
If the user has chosen to rotate the grid, we also swap the
values for x and y. Finally, we append the calculated x and y
19 20 21 22 23
coordinates to the vertices array. Since this is a flat surface,
the z coordinate is zero. It is important to map the index of
15 16 17 18
the vertices in the array to their spatial location in order
to correctly create triangles that connect them (fig. 64).
10 11 12 13 14

6 7 8 9

1 2 3 4 5

fig. 64 Vertex indices in a diagrid mesh.

54 -- Create first set of triangles.


55 for i = 1 to nr by 2 do
56 (
57 for j = 1 to nc by 1 do
58 (
59 v1 = (i - 1)*(nc + 1) - ((i - 1)/2) + j
60 v2 = (i - 1)*(nc + 1) - ((i - 1)/2) + j + 1
61 v3 = (i - 1)*(nc + 1) - ((i - 1)/2) + j + (nc + 1)
62 append faces [v1, v2, v3]
63
64 if (j < nc) then
65 (
66 v1 = (i - 1)*(nc + 1) - ((i - 1)/2) + j + (nc + 1)
67 v2 = (i - 1)*(nc + 1) - ((i - 1)/2) + j + 1
68 v3 = (i - 1)*(nc + 1) - ((i - 1)/2) + j + (nc + 2)
69 append faces [v1, v2, v3]
70 )
71 )
72 )
Subdivision 91

In this section we create two nested for loops, in order to specify 42 43 44 45


triangles that connect sets of three vertices (fig. 65). In this 37 38 39 40 41
section we actually create only half the necessary triangles,
by skipping a row. Three vertices, v1, v2 and v3, are calculated
33 34 35 36
based on where we are in the iteration of rows and columns. As
long as we are not at the last column ( j < nc) then we also create
another, upside-down triangle that fits with the one before it. 28 29 30 31 32
A similar approach is used to create the second set of rows,
as well as the left and right triangles to finish off the surface. 24 25 26 27

19 20 21 22 23

15 16 17 18

10 11 12 13 14

6 7 8 9

1 2 3 4 5

fig. 65 Connecting vertex indices in a


diagrid mesh.
108 -- Create the mesh
109 setMesh mesh verts:vertices faces:faces

The last step in the buildMesh function is to set the mesh using the vertices
and faces arrays. This will allow 3ds Max to display it on-demand.

112 -- Respond to user interaction events


113 tool create
114 (
115 on mousePoint click do
116 (
117 case click of
118 (
119 1: nodeTM.translation = gridPoint
120 2: #stop
121 )
122 )
123
124 on mouseMove click do
125 (
126 case click of
127 (
128 2: (meshWidth = gridDist.x; meshLength = gridDist.y)
129 3: #stop
130 )
131 )
132 )
133 )
SimPlE diagrid mESH/CoNtiNuEd

the last section of the code specifies how a user creates Untitled Type a Keyword or phrase

the diagrid and how the software should react to mouse 3DS Edit Tools
MAXScript
Group
Help
Views Create Modifiers Animation Graph Editors Rendering Lighting Analysis Customize

clicks and drags. When a user clicks the mouse, the All View Create Selection

location of the click (gridPoint) is considered the origin of Graphite Modeling Tools
Polygon Modeling
Freeform Selection Object Paint

the mesh. When the user moves the mouse, the second
Diagrid Mesh002
click is used to derive the width and the length of the mesh. Modifier List

this is identical to how a user creates a 2d rectangle. FFD 3x3x3


Control Points

Pressing the escape key stops the creation of the diagrid. Lattice
Set Volume

since the diagrid mesh is created as a scripted plugin, it


behaves exactly like other geometries. its parameters can
FFD Parameters
Display:

be modified in the modify panel as well as animated using


Lattice

Source Volume

the timeline. Finally, the mesh surface can be manipulated Deform:

Only In Volume
by adding modifiers such as edit Mesh or FFd 3x3x3 (fig. All Ver tices

66). a complex organic form can be similarly achieved (fig. Control Points:
Reset

67). in this case, a hollowed out diagrid mesh was distorted Animate All

using the bend and spherify built-in modifiers. to achieve Conform to Shape

Inside Points

the final organic form, the geometry was then thickened and Outside Points

smoothed using the built-in shell and turbosmooth modifiers. Offset : 0.05

About
35 / 100

0 10 20 30 40 50 60 70 80 90 100
modPanel.setCurrent0bject $.m X: Y: Auto Key Selected
diagridmesh_plugin_def Click and drag to pan a non Set Key Key Filters... 35

fig. 66 A modified diagrid mesh using the FFD 3x3x3 modifier.

fig. 67 A process of modifying a simple diagrid into a


curvilinear, organic form, using geometry modifiers.
Tutorial Deriving a diagrid mesh
from a NURBS surface
In this second tutorial on subdivision, we will derive a diagrid u and v as horizontal and vertical increments in the case of a
mesh from any NURBS surface. The MAXScript environment simple flat rectangular plane, in reality, they are normalized (i.e. 0
allows procedural access to its built-in NURBS representations, to 1) parametric offsets along two directions on any undulating
facilitating the construction of new geometries that can surface. We can iterate through the u and v parameters of a
subdivide the surface according to any desired topology. NURBS surface and request the 3D coordinates of a point on
As we have seen above, 3ds Max provides some built-in the surface that exists at that particular u and v parametric
topologies, but in this case we would like to create our own. coordinate. This allows us to create a pattern of vertices of our
NURBS surfaces contain formulas for surface and curve choosing and a set of triangular faces that connect them.
interpolation and approximation based on a derivation of points
in the u and v directions of the surface. While you can think of

Unlike the previous tutorial, we will create a scripted utility called DiagridMesh rather than a scripted plugin.
Open 3ds Max, save and close any prior scenes, create a new empty scene and choose MAXScript
New Script from the top menu. In the script window that opens, type the following algorithm:

1 utility DiagridMesh “Diagrid Mesh”


2 (
3 global u = 10 -- the number of u steps.
4 global v = 10 -- the number of v steps.
5 global vertices = #() -- the array of vertices.
6 global faces = #() -- the array of faces.
7 global nc -- the number of columns.
8 global nr -- the number of rows.
9 global selectedObject = undefined -- the selected object.
10 global ns -- the NURBS set (derived from the selected object).
11 global minu, maxu -- the minimum and maximum u values for the surface.
12 global minv, maxv -- the minimum and maximum v values for the surface.
13 global udist, vdist -- the unit u and unit v distances.
14 global resultingMesh
15
16 global globalCounter = 1 -- a counter we will use to generate a unique name.
17
18 -- A function to select only NURBS surfaces.
19 fn nurbs_filt obj = (classOf obj == NURBSSurf)
20
21 pickbutton selectNURBS “Select NURBS” width:140 filter:nurbs_filt
22 edittext selectedObject_tf “NURBS: “ text:”NONE” readonly:true width:138
23
24 group “Parameters”
25 (
26 spinner u_spinner “U:” type:#integer range:[1,10000,u]
27 spinner v_spinner “V:” type:#integer range:[1,10000,v]
28 )
Deriving a diagrid mesh from a NURBS surface
/CONTINUED
29
30 button generate_button “Generate Diagrid” enabled:true
31
32 on selectNURBS picked obj do
33 (
34 --see if the user did not cancel the picking.
35 if obj != undefined do
36 (
37 selectedObject = obj
38 -- display the name of the object on the button.
39 selectedObject_tf.text = obj.name
40 )
41 )
42
43 on u_spinner changed amt do
44 (
45 u = amt
46 )
47
48 on v_spinner changed amt do
49 (
50 v = amt
51 )
52
53 on generate_button pressed do
54 (
55 resultingMesh = undefined
56 nc = u*2
57 nr = v
58
59 if (selectedObject == undefined) then
60 (
61 return false
62 )
63
64 if (isDeleted selectedObject) then
65 (
66 return false
67 )
68
69 -- Get the NURBS set from the selected object.
Subdivision 95

70 ns = getnurbsset selectedObject #relational


71
72 for k = 1 to ns.count by 1 do
73 (
74
75 if ((superClassOf ns[k]) == NURBSSurface) then
76 (
77
78 -- Delete any pre-existing vertices.
79 for i = 1 to vertices.count by 1 do
80 (
81 deleteItem vertices 1
82 )
83
84 -- Delete any pre-existing faces.
85 for i = 1 to faces.count by 1 do
86 (
87 deleteItem faces 1
88 )
89
90 minu = ns[k].uParameterRangeMin
91 maxu = ns[k].uParameterRangeMax
92
93 minv = ns[k].vParameterRangeMin
94 maxv = ns[k].vParameterRangeMax
95
96 udist = 1.0 / (float) nc
97 vdist = 1.0 / (float) nr
98 oddeven = 2
99
100 -- Create Vertices.
101 for i = 0 to nc by 1 do
102 (
103 case of(
104 (mod oddeven 2 != 0) : (offset = 0.5; deduct = 1)
105 (mod oddeven 2 == 0) : (offset = 0.0; deduct = 0)
106 )
107 for j = 0 to (nr - deduct) by 1 do
108 (
109 vx = i/(float) nc
110 vy = (j+offset)/(float) nr
111 append vertices (evalpos ns[k] (minu + (maxu-minu)*vx) (minv + (maxv-minv)*vy))
112 )
Deriving a diagrid mesh from a NURBS surface
/CONTINUED
113 oddeven = oddeven + 1
114 )
115
116 if(ns[k].closedInV == false) then
117 (
118 -- Create left and right triangular edges for open NURBS surfaces.
119 for i = 1 to nc by 2 do
120 (
121 v1 = (i - 1)*(nr + 1) - ((i - 1)/2) + 1
122 v2 = (i - 1)*(nr + 1) - ((i - 1)/2) + 1 + (nr + 1)
123 v3 = (i + 1)*(nr + 1) - ((i + 1)/2) + 1
124 append faces [v1, v2, v3]
125
126 v1 = (i + 1)*(nr + 1) - ((i + 1)/2) + nr + 1
127 v2 = (i - 1)*(nr + 1) - ((i - 1)/2) + nr + (nr + 1)
128 v3 = (i - 1)*(nr + 1) - ((i - 1)/2) + nr + 1
129 append faces [v1, v2, v3]
130 )
131 )
132 else
133 (
134 -- Create triangles for closed NURBS surfaces.
135 for i = 1 to nc by 2 do
136 (
137 v1 = (i - 1)*(nr + 1) - ((i - 1)/2) + 1
138 v2 = (i - 1)*(nr + 1) - ((i - 1)/2) + 1 + (nr + 1)
139 v3 = (i - 1)*(nr + 1) - ((i - 1)/2) + nr + (nr + 1)
140 append faces [v1, v2, v3]
141
142 v1 = (i - 1)*(nr + 1) - ((i - 1)/2) + nr + (nr + 1)
143 v2 = (i - 1)*(nr + 1) - ((i - 1)/2) + 1 + (nr + 1)
144 v3 = (i + 1)*(nr + 1) - ((i + 1)/2) + nr + 1
145 append faces [v1, v2, v3]
146 )
147 )
148
149 -- Create first set of triangles.
150 for i = 1 to nc by 2 do
151 (
152 for j = 1 to nr by 1 do
153 (
Subdivision 97

154 v1 = (i - 1)*(nr + 1) - ((i - 1)/2) + j


155 v2 = (i - 1)*(nr + 1) - ((i - 1)/2) + j + 1
156 v3 = (i - 1)*(nr + 1) - ((i - 1)/2) + j + (nr + 1)
157 append faces [v1, v2, v3]
158
159 if (j < nr) then
160 (
161 v1 = (i - 1)*(nr + 1) - ((i - 1)/2) + j + (nr + 1)
162 v2 = (i - 1)*(nr + 1) - ((i - 1)/2) + j + 1
163 v3 = (i - 1)*(nr + 1) - ((i - 1)/2) + j + (nr + 2)
164 append faces [v1, v2, v3]
165 )
166 )
167 )
168
169 -- Create second set of triangles.
170 for i = 3 to (nc+1) by 2 do
171 (
172 for j = 1 to nr by 1 do
173 (
174 v1 = (i - 1)*(nr + 1) - ((i - 1)/2) + j + 1
175 v2 = (i - 1)*(nr + 1) - ((i - 1)/2) + j
176 v3 = (i - 3)*(nr + 1) - ((i - 3)/2) + j + (nr + 1)
177 append faces [v1, v2, v3]
178
179 if (j < nr) then
180 (
181 v1 = (i - 3)*(nr + 1) - ((i - 3)/2) + j + (nr + 1)
182 v2 = (i - 3)*(nr + 1) - ((i - 3)/2) + j + 1 + (nr + 1)
183 v3 = (i - 1)*(nr + 1) - ((i - 1)/2) + j + 1
184 append faces [v1, v2, v3]
185 )
186 )
187 )
188
189 -- Create the mesh.
190 m = mesh vertices:vertices faces:faces
191
192 -- Weld any congruent vertices.
193 allVerts = #{1..(m.numVerts)} -- get all verts list.
194 meshop.weldVertsByThreshold m allVerts 0.001
195
196 -- Set the mesh properties and position at same location as original surface.
Deriving a diagrid mesh from a NURBS surface
/CONTINUED
197 m.name = selectedObject.name+”-”+(k as string)+”-diagrid”
198 m.rotation = selectedObject.rotation
199 m.scale = selectedObject.scale
200 m.pos = selectedObject.pos
201
202 if((resultingMesh == undefined) or (isDeleted resultingMesh)) then
203 (
204 resultingMesh = copy m
205 )
206 else
207 (
208 resultingMesh += m
209 )
210 delete m
211
212 -- Make the mesh the current selection.
213 resultingMesh.name = selectedObject.name+”-Diagrid”+(formattedPrint globalCounter format:”03d”)+”-
”+(u as string)+”X”+(v as string)
214 select resultingMesh
215 )
216 )
217 globalCounter = globalCounter + 1
218 )
219 )

Save your script and then choose Tools Evaluate All to run the script.
Set the viewport display to display face edges by clicking on the display
mode (e.g. Realistic or Smooth+Highlights in the upper left corner of the
viewport) and choosing that option. This will enable you to see the diagrid
lines when you derive the surface. Next, create a NURBS surface.
To run the actual script utility, go to Utilities (hammer icon)  MAXScript 
Utilities (Pull-down menu) Diagrid Mesh. Use the pick button, titled Select tip CREATING A NURBS
NURBS, to select the NURBS surface from the scene. You can choose any SURFACE
number of u and v sections (rows and columns). Once you have selected the
desired parameters, press the Generate Diagrid button. This will generate To create a NURBS surface, select
an editable mesh diagrid at the same location as the original NURBS surface. Create Geometry NURBS
Select the move command and move the diagrid so you can view it (fig. Surfaces CV Surf and drag a rectangle
68). The diagrid will have the same name as the original NURBS surface in the viewport. If you wish to undulate the
surface, select it, go to the modify panel,
followed by the suffix “-Diagrid” and additional identifying numbers.
click on the + sign next to the word ‘NURBS
Surfaces’ to open the sub-objects list and
then choose Surface CV. You can then select
one or more of the yellow control vertices in
the viewport and move them in any direction
to undulate the surface. Once done,
deselect Surface CV and select the whole
NURBS surface.
Subdivision 99

Type a Keyword or phrase


3DS Edit Tools Group Views Create Modifiers Animation Graph Editors Rendering Lighting Analysis Customize MAXScript Help

All View Create Selection Se

Graphite Modeling Tools Freeform Selection Object Paint


Polygon Modeling

3 Objects Selected

Collapse
Color Clipboard
Measure
Motion Capture
Reset XForm

MAXScript
Flight Studio (c)

MAXScript

Open Listener

New Script

Open Script

Run Script

Utilities
Convert to mr Area L

Close

Diagrid Mesh

Select NURBS
NURBS: Surface001
Parameters
U: 8
V: 12

Generate Diagrid

0 / 100 Close

0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100
actionMan.executeAction 0 “40 3 Objects Selected X: Y: Z: Grid = 10.0mm Auto Key Selected
Rollout:DiagridMesh Click and drag to pan a non–camera view Add Time Tag Set Key Key Filters... 0

fig. 68 A diagrid mesh (left) derived from a NURBS surface (right).

Let’s take a closer look at the script:

1 utility DiagridMesh “Diagrid Mesh”


2 (
3 global u = 10 -- the number of U steps
4 global v = 10 -- the number of V steps
5 global vertices = #() -- the array of vertices
6 global faces = #() -- the array of faces
7 global nc -- the number of columns
8 global nr -- the number of rows
9 global selectedObject = undefined -- the selected object
10 global ns -- the NURBS set (derived from the selected object)
11 global minu, maxu -- the minimum and maximum U values for the surface
12 global minv, maxv -- the minimum and maximum V values for the surface
13 global udist, vdist -- the unit U and unit V distance
14 global resultingMesh
15
16 global globalCounter = 1 -- a counter we will use to generate a unique name
Deriving a diagrid mesh from a NURBS surface
/CONTINUED
We declare a scripted utility that we name DiagridMesh. We give it the title ‘Diagrid
Mesh’. This scripted utility will be stored under the Utilities (hammer icon) tab under
the MAXScript category of utilities. We declare four main global variables. The u and
v values are the number of rows and columns we wish to divide the surface into. The
vertices and faces arrays will store the resulting mesh information. Last, we declare
the global variable resultingMesh to store the resulting diagrid mesh.

19 fn nurbs_filt obj = (classOf obj == NURBSSurf)

The above function returns a value of true only if the selected object belongs to the
NURBSSurf class.

21 pickbutton selectNURBS “Select NURBS” width:140 filter:nurbs_filt


22 edittext selectedObject_tf “NURBS: “ text:”NONE” readonly:true width:138
23
24 group “Parameters”
25 (
26 spinner u_spinner “U:” type:#integer range:[1,10000,u]
27 spinner v_spinner “V:” type:#integer range:[1,10000,v]
28 )
29
30 button generate_button “Generate Diagrid” enabled:true

We then define the rollout interface with a pick button to select the NURBS surface from
the scene, two spinners for defining the u and v subdivisions, and a button to generate
the mesh when pressed.

43 on u_spinner changed amt do


44 (
45 u = amt
46 )
47
48 on v_spinner changed amt do
49 (
50 v = amt
51 )

This section specifies what happens when the user changes the amount in the spinner
field (i.e. changes the amount of the u and v). The code simply updates the amount saved
in the variables with the new amount from the user interface.

53 on generate_button pressed do
54 (
55 resultingMesh = undefined
56 nc = u*2
57 nr = v
Subdivision 101

The remainder of the script executes only when the Generate Diagrad button is pressed.
The script starts by setting the resulting mesh to the value undefined and specifying
two new variables: nc (number of columns) and nr (number of rows). To ensure a proper
result for the diagrid, we ensure an even number of columns by multiplying the specified
u value by 2.

59 if (selectedObject == undefined) then


60 (
61 return false
62 )
63
64 if (isDeleted selectedObject) then
65 (
66 return false
67 )

The above code ensures that we continue to generate a diagrid only if the selected object
is defined and has not been deleted. If these conditions are not met, the code returns the
value false and stops executing.

70 ns = getnurbsset selectedObject #relational

The built-in getnurbset function returns an idealized version of the selected NURBS
object that can be queried for its components (vertices, curves, surfaces, etc.). We store
this set in the ns variable.

72 for k = 1 to ns.count by 1 do
73 (
74
75 if ((superClassOf ns[k]) == NURBSSurface) then
76 (

We then create a large loop to iterate through all the elements of the ns NURBS
construct. We consider a sub-object only if it is a NURBSSurface.

90 minu = ns[k].uParameterRangeMin
91 maxu = ns[k].uParameterRangeMax
92
93 minv = ns[k].vParameterRangeMin
94 maxv = ns[k].vParameterRangeMax
95
96 udist = 1.0 / (float) nc
97 vdist = 1.0 / (float) nr

We then compute the minimum and maximum extents of the surface. Since u and v
are normalized (i.e. span between 0 and 1), we define the unit udist and vdist distance
as 1 divided by the number of rows and columns. The remainder of the script is almost
identical to the previous tutorial, so we will cover only the differences between the
two scripts.
dEriViNg a diagrid mESH From a NurbS SurFaCE
/CoNtiNuEd
109 vx = i/(float) nc
110 vy = (j+offset)/(float) nr
111 append vertices (evalpos ns[k] (minu + (maxu-minu)*vx) (minv + (maxv-minv)*vy))

in the above snippet of code, we call the evalpos function with an offset in the u
and v parametric space of the surface to obtain an actual 3d point at that location.
this is computed by adding a factor of the u and v dimension (e.g. maxu – minu) to
the minimum value of each dimension (e.g. minu). however, we first adjust for any
horizontal offsets due to the shifting of the vertices on odd-numbered rows. after we
obtain that point, we append it to the vertices array (this is done in one step in the
code, using nesting of functions). the faces are created in exactly the same way as in
the previous tutorial: finding the index of the relevant vertices in the vertices array,
connecting them and adding the resulting three-point array to the faces array.

116 if(ns[k].closedinV == false) then

fig. 69 Examples of closed and open diagrids.

a nUrbs surface in 3ds Max can tell us if it is closed or open in either of its u or
v directions (fig. 69). the built-in method/attribute closedinV reports back if the
surface is closed in the v direction, information that we need in order to make sure
that we do not replicate the edges of our diagrid. imagine a ribbon that is closed
into a circle. at the seam, where the ribbon meets itself, we need to ensure that
only one edge exists. in our case, the triangles at the seam need to be constructed
from one set of edges rather than two to ensure a properly configured mesh.
Subdivision 103

190 m = mesh vertices:vertices faces:faces


191
192 -- Weld any congruent vertices.
193 allVerts = #{1..(m.numVerts)} -- get all verts list
194 meshop.weldVertsbythreshold m allVerts 0.001
195

in this section of the code, the mesh is created from the two arrays of vertices
and faces. its vertices are then welded to make sure there are no redundancies.
the remainder of the code involves setting the properties of the mesh and completing
some housekeeping operations. it should be self-explanatory. the resulting mesh can
be modified in 3ds Max to extract its vertices, edges and surfaces to create a skin and
a structure (fig. 70).

fig. 70 The diagrid script is used to create an


imaginary metal and glass pavilion concept.
104 Parametric patterns

Case study Screen for Eurocont Headquarters,


Badalona, Spain
Designer HYBRIDa scp
Client Eurocomercial de Neuvas Tecnología (Eurocont), Spain
Design and Construction 2010

Eurocont is a Barcelona-based company defined three methods for the subdivision of Above
specializing in innovative technological products the screen surface. The resulting geometries, View from lower level.
for the building industry. Their headquarters is arranged in separate layers, were then selectively
Opposite
an industrial building that combines extensive collapsed to produce a variety of patterns, which Light filtration qualities of the screen.
workshop areas with the company’s offices. The varied depending on the layers that had been
project under consideration here is a partition juxtaposed to produce them. This led to an
screen intended to separate the company’s overwhelming proliferation of geometry, which
ground-level workshop space from the office needed to be subjected to a selection process.
areas, which are mostly located on a mezzanine The designers chose several criteria (including
level. The functional requirements for this project the number of sides of the polygons, the area
were rather mundane: the completed screen of perforation and the number of connections
had to provide a controlled visual connection between vertices) and treated them as parameters
between the two areas, to insulate the office to include in a script. The script calculated and
area acoustically, and to ensure proper lighting drafted panels with varying degrees of opacity
and temperature conditions. For the designers, (0% to 100%), which could then be positioned
however, the project was an opportunity to create on the partition screen according to acoustic and
an iterative geometric process that satisfied these visual connection requirements. Multiple iterations
requirements while creating an ‘apparent chaos’. were run, and the emerging patterns were
Beginning with a study of the texture of an then evaluated and adjusted according to the
eggshell, the designers, J. Truco and S. Felipe, functions taking place behind different sections
106 Parametric patterns

Below
Establishing the main generative rules of
the design.

Bottom
Juxtaposition of geometric lines to
achieve varying degrees of opacity.

a b c

a a ab b abc c

2,4 pr 2,4 pr 2,4 pr

10% opacity

35% opacity

building blocks 55% opacity

resultants
a
10% opacity 100% opacity
90% opacity
b 65% opacity
35% opacity
55% opacity
45% opacity
c 35% opacity
55% opacity
10% opacity
0% opacity

10% opacity

35% opacity

55% opacity
Subdivision 107

of the partition screen. The designers stopped


b+c a+b b+c a+b b+c b+c b+c a+b b+c
the iterative process once they were satisfied
with the effect and the function of the emergent
pattern. This method eventually determined
the algorithm that produced the final design.
The completed screen measured 27 m wide.
It was digitally fabricated by a CNC machine and
consisted of 70 methacrylate panels, 12 mm
thick, with varying porosities. Each of these panels
was encased between two insulation glass panes
and mounted within a metal frame. Running
across these panels are unique polygons that are
the result of a common geometric manipulation. b+c a+b a+b a+b+c a+b a+b a+b+c a+b

This process, as the designers argue, ‘links


them all and makes them understandable as a
whole’. It is important to note that the language
of expression that characterizes the Eurocont
screen does not depend on formal manipulation
by the designers. Instead, it is a direct result of the
process by which it was designed. The end result
reflects the employment of geometric patterns,
formalistic criteria and the determination of a
specific algorithm – all of which, however, have
been placed in the service of the very pragmatic b+c a+b b+c a+b b+c b+c b+c a+b+c a+b
functional requirements prescribed by the brief.

Above right
Pattern analysis based on occupancy B4 C4 C6 C8

and space functions. B4 C4

C6 C8

Right B5 C5 C7 C9

B5 C5

Segmentation of pattern into individual panels. C7 C9

C10
B6 C10

B6
C4 C5 C6 C7 C8 C9 C10

E2 E3 E4 E5 E6 E7 E8 E9 E10 E11 E12 E13 E14 E15 E16 E17 E18 E19 E20 E21 E22

B7

D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 D14 D15 D16 D17 D18 D19 D20 D21 D22

B4 B5 B6 B7 B8 B9 B10

D1

B7
C1 C2 C4 C5 C6 C7 C8 C9 C10

B1 B2 B4 B5 B6 B7 B8 B9 B10

A7
A4 A5 A6 A7 A8 A9 A10
A7
A1 A2 A4 A5 A6 A7 A8 A9 A10

A7

B8 A10

B8
A7

A10
1327
A7
B9 A5 A7 A9

1802
B9 A7 A9

A5

A7

B10 A4 A8

A4
A8
B10 A6
108 Parametric patterns

Above Above right Below left and right


Digital fabrication of methacrylate panels. Installation of panels. Close-up views of completed panels.
Subdivision 109

Below
Varying degrees of visual separation.
110 Parametric patterns

Packing
Closely related to the concepts of tiling and subdivision humans employ packing techniques on a geographical
is the concept of packing: the placement of many objects scale, given constraints in the terrain, climate and
in a space, such that little or nothing of it is left over. production technology (fig. 75). In architecture, we have
Packing in nature happens at many different scales. The seen an interest in packing for both spatial organization as
natural force of growth within a constrained space leads well as structural strength (fig. 76). However, unlike tiling
to packing in both the cellular structure of charcoal (fig. and subdivision, both of which are likely to have a global
71) and the seeds of a pomegranate (fig. 72). Weathering ordering system that governs their form, packing is often
and erosion can be viewed as the inverse of packing — one an opportunistic process. That is, components in a packing
can think of void pockets as the packed material, as seen system seek empty space to occupy, and a first-come,
at a molecular level in Biochar (fig. 73) and at a much first-served process governs the growth pattern. Thus, the
larger scale in Tafoni structures (fig. 74). Humans have results of packing are not always regularly tiled or fully
long been interested in packing techniques to ensure an optimized. Packing algorithms also vary in their efficiency
economy of means and the efficient use of resources. The as they contain trade-offs between the number of objects
pivot point irrigation system is a good example of how to pack and the time needed to generate a solution.

fig. 71 Microscope photo of fig. 72 An open pomegranate


charcoal at high magnification. showing packed seeds.

fig. 73 Microscope photo of fig. 74 Tafoni structure at Pebble Beach,


Biochar at high magnification. San Mateo Coast, California.
Packing 111

fig. 75 Irrigation and land surface


temperature in Oregon.

fig. 76 Packed Pavilion, Shanghai,


China (2010). Project designed
by Michele Leidi, Min-Chieh Chen
and Dominik Zausinger with the
help of Jeannette Kuo and the
supervision of Tom Pawlofsky.
Tutorial Circle packing

In this tutorial on packing we will create a generative it as many circles as it can (up to a specified maximum,
algorithm that takes any 2D shape as input and packs into and within the specified time limit and other parameters).

Open 3ds Max, save and close any prior scenes, create a new empty
scene. Choose MAXScript New Script from the top menu. In
the script window that opens, type the following algorithm:

1 utility circlePacking “Circle Packing”


2 (
3 global selectedShape
4 global maxCircles = 600
5 global minRadius = 1
6 global maxRadius = 5
7 global maxAttempts = 10000
8 global minX = 0
9 global maxX = 100
10 global minY = 0
11 global maxY = 100
12 global circles = #()
13 global radius = 10
14 global accuracy = 32
15
16 fn shape_filt obj = ((superClassOf obj) == Shape)
17
18 pickbutton selectShape “Select Shape” width:140 filter:shape_filt
19 edittext selectedShape_tf “Shape: “ text:”NONE” readonly:true width:138
20
21 spinner maxCircles_spinner “Circles: “ range:[1,10000,maxCircles] type:#integer
22 spinner minRadius_spinner “Min. Radius: “ range:[0.1,10000,minRadius] type:#worldunits
23 spinner maxRadius_spinner “Max. Radius: “ range:[0.1,10000,maxRadius] type:#worldunits
24 spinner maxAttempts_spinner “Attempts: “ range:[1,100000,maxAttempts] type:#integer
25 spinner accuracy_spinner “Accuracy: “ range:[4,64,accuracy] type:#integer
26 button generate_button “Generate” enabled:false width: 140 height:20
27 progressbar Attempts_prog color:red
28 progressbar generate_prog color:green
29 edittext packedCircles “ Packed: “ text:”0 Circles” readonly:true width:138
30 edittext coverage “ Coverage: “ text:”0 %” readonly:true width:138
31
32 on selectShape picked obj do
33 (
34 --see if the user did not cancel the picking.
35 if obj != undefined do
36 (
Packing 113

37 -- display the name of the object on the button:


38 selectedShape_tf.text = obj.name
39 selectedShape = obj
40 generate_button.enabled = true
41 )
42 )
43
44 fn overlaps aCircle circles =
45 (
46 if(circles.count < 1) then
47 (
48 return false
49 )
50 for i=1 to i=circles.count do
51 (
52 result = (distance aCircle.pos circles[i].pos) <= (aCircle.radius + circles[i].radius)
53 if result then return result
54 )
55 return false
56 )
57
58 fn outside_mesh aCircle aMesh =
59 (
60
61 for i = 0 to accuracy by 1 do
62 (
63 ang = (i/accuracy as float)*360
64 vx = aCircle.pos.x + cos(ang) * aCircle.radius
65 vy = aCircle.pos.y + sin(ang) * aCircle.radius
66 testRay = ray [vx, vy, 1] [0, 0, -10]
67 if (intersectRay aMesh testRay == undefined) then
68 (
69 return true
70 )
71 )
72 return false
73 )
74
75 fn createCircle minRadius maxRadius ratio =
76 (
77 radius = random minRadius (maxRadius - ((maxRadius*ratio/maxAttempts) as float))
78 x = random (minX + radius) (maxX - radius)
79 y = random (minY + radius) (maxY - radius)
Circle packing/CONTINUED

80 newCircle = circle radius:radius


81 newCircle.pos = [x,y,0]
82 return newCircle
83 )
84
85 on generate_button pressed do
86 (
87 if (selectedShape == undefined) then return false
88 if (isDeleted selectedShape) then
89 (
90 selectedShape_tf.text = “NONE”
91 return false
92 )
93
94 coverageArea = 0
95
96 ep_mod = edit_poly()
97 addModifier selectedShape ep_mod
98
99 totalArea=0
100 for i=1 to selectedShape.numfaces do totalArea+=(polyop.getfacearea selectedShape i)
101
102 bb = nodeGetBoundingBox selectedShape (matrix3 1)
103 minX = bb[1].x
104 maxX = bb[2].x
105 minY = bb[1].y
106 maxY = bb[2].y
107
108 -- Empty the circles array and delete all the circles in it.
109 circlesCount = circles.count
110 for i = 1 to circlesCount by 1 do
111 (
112 tobedeleted = circles[1]
113 deleteItem circles 1
114 if(isDeleted tobedeleted != true) then
115 (
116 delete tobedeleted
117 )
118 )
119 circles.count = 0
120 packedCircles.text = “0/”+(maxCircles as string)+” Circles”
Packing 115

121 coverage.text = “0 %”
122 redrawViews()
123
124 j=1
125 attempts = 0
126 while (circles.count < maxCircles) and (attempts < maxAttempts) do
127 (
128 aCircle = createCircle minRadius maxRadius j
129 if ((overlaps aCircle circles) or (outside_mesh aCircle selectedShape)) then
130 (
131 delete aCircle
132 )
133 else
134 (
135 append circles aCircle
136 j=j+1
137 coverageArea = coverageArea + pi*radius*radius
138 )
139 attempts = attempts + 1
140 attempts_prog.value = 100.*attempts/maxAttempts
141 generate_prog.value = 100.*j/maxCircles
142 ) --end of the for loop.
143
144 for m in selectedShape.modifiers do
145 (
146 if classOf m==Edit_Poly do deleteModifier selectedShape m
147 )
148
149 packedCircles.text = (circles.count as string)+”/”+(maxCircles as string)+” Circles”
150 coverage.text = ((coverageArea/totalArea*100) as string)+” %”
151 )
152
153 on maxCircles_spinner changed amt do
154 (
155 maxCircles = amt
156 )
157 on maxAttempts_spinner changed amt do
158 (
159 maxAttempts = amt
160 )
161 on minRadius_spinner changed amt do
162 (
163 minRadius = amt
Circle packing/CONTINUED

164 if(maxRadius < minRadius) then


165 (
166 maxRadius = minRadius
167 maxRadius_spinner.value = minRadius
168 )
169 )
170 on maxRadius_spinner changed amt do
171 (
172 maxRadius = amt
173 if(minRadius > maxRadius) then
174 (
175 minRadius = maxRadius
176 minRadius_spinner.value = maxRadius
177 )
178 )
179 on accuracy_spinner changed amt do
180 (
181 accuracy = amt
182 )
183 )

Save your script and then choose Tools Evaluate All to run the script. You
will find the script utility under Utilities (hammer icon). Click on the MAXScript
button and then choose Circle Packing from the Utilities pull down menu (fig. 77).

Type a Keyword or phrase


3DS Edit Tools Group Views Create Modifiers Animation Graph Editors Rendering Lighting Analysis Customize MAXScript Help
All View Create Selection Se

Graphite Modeling Tools Freeform Selection Object Paint


Polygon Modeling

MAXScript
Flight Studio (c)

MAXScript

Open Listener

New Script

Open Script

Run Script

Utilities
Cirde Packing

Close

Cirde Packing

Select Shape
Shape: Line001
Cirdes: 600
Min. Radius: 1.0mm
Max. Radius: 5.0mm
Attempts: 10000
Accuracy: 32

Generate

Packed: 329/600 Cirdes


Coverage: 48.806 %

0 / 100 Close

0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100
clearSelection ( ) None Selected X: Y: Z: Grid = 10.0mm Auto Key Selected
OK Click or click–and–drag to select objects Add Time Tag Set Key Key Filters... 0

fig. 77 Circle Packing Utility Script.


Packing 117

To run the script, create any 2D closed spline in the TOP view. Then click on
the Select Shape button and select the spline. Specify the parameters for the
maximum number of circles, the minimum and maximum radii for the generated
circles, the maximum allowed number of attempts, and the accuracy of the
intersection test. The latter equates to the number of points on the circle to
intersect with the surface to test if it lies within it. For simpler shapes (such as
a rectangle) testing only 4 points on a circle may be sufficient and would speed
up the algorithm. Once all the parameters are set, click on the Generate button
to generate the circles. The 2D spline will be filled with a solid colour and two
progress bars will appear. The top, red progress bar is an indication of the
number of attempts tried thus far. The lower, green progress bar is an indication
of the number of circles successfully packed into the selected shape. The two
progress bars will appear to be in a race against each other. Ideally, you would
want the green bar to be farther ahead. If you find that it isn’t, then the total
amount of allowed attempts needs to be increased. Once the algorithm is done
packing the circles, it reports the total number of circles it could successfully
pack as well as the coverage area percentage of the original 2D surface.

Let’s take a closer look at the script:

1 utility circlePacking “Circle Packing”


2 (
3 global selectedShape
4 global maxCircles = 600
5 global minRadius = 1
6 global maxRadius = 5
7 global maxAttempts = 10000
8 global minX = 0
9 global maxX = 100
10 global minY = 0
11 global maxY = 100
12 global circles = #()
13 global radius = 10
14 global accuracy = 32

We define a utility script called circlePacking and titled with the same name. We define
several global variables to store the selected shape, the desired maximum number of
circles to pack, the minimum and maximum radius for a generated circle (the script will
randomly choose a number in this range), the maximum allowed number of attempts
to generate and pack a circle, and an accuracy setting for the intersection test that
determines if a circle is inside or outside a shape. Other variables are also needed
for various other functions, as we will see below.

16 fn shape_filt obj = ((superClassOf obj) == Shape)

This function acts as a selection filter so that the user is restricted only to selecting a 2D shape.

18 pickbutton selectShape “Select Shape” width:140 filter:shape_filt


19 edittext selectedShape_tf “Shape: “ text:”NONE” readonly:true width:138
20
21 spinner maxCircles_spinner “Circles: “ range:[1,10000,maxCircles] type:#integer
22 spinner minRadius_spinner “Min. Radius: “ range:[0.1,10000,minRadius] type:#worldunits
Circle packing/CONTINUED

23 spinner maxRadius_spinner “Max. Radius: “ range:[0.1,10000,maxRadius] type:#worldunits


24 spinner maxAttempts_spinner “Attempts: “ range:[1,100000,maxAttempts] type:#integer
25 spinner accuracy_spinner “Accuracy: “ range:[4,64,accuracy] type:#integer
26 button generate_button “Generate” enabled:false width: 140 height:20
27 progressbar Attempts_prog color:red
28 progressbar generate_prog color:green
29 edittext packedCircles “ Packed: “ text:”0 Circles” readonly:true width:138
30 edittext coverage “ Coverage: “ text:”0 %” readonly:true width:138

This block of code defines a user interface rollout with the necessary spinners, buttons,
text fields and progress bars.

32 on selectShape picked obj do


33 (
34 --see if the user did not cancel the picking...
35 if obj != undefined do
36 (
37 -- display the name of the object on the button:
38 selectedShape_tf.text = obj.name
39 selectedShape = obj
40 generate_button.enabled = true
41 )
42 )

Once a shape is selected, this callback function is executed. If the selected object is
defined it places its name in the rollout user interface, copies its address into another
variable for later use and enables the generate button, so that it can be clicked by the
user to generate the circles.

44 fn overlaps aCircle circles =


45 (
46 if(circles.count < 1) then
47 (
48 return false
49 )
50 for i=1 to i=circles.count do
51 (
52 result = (distance aCircle.pos circles[i].pos) <= (aCircle.radius + circles[i].radius)
53 if result then return result
54 )
55 return false
56 )
Packing 119

This function tests if a circle overlaps any of the previous circles that have already been
generated (and stored in the circles array). The test is simple: if the distance between
the two centres of the circles is less than the sum of their radii, then the two circles
overlap (fig. 78).

r2
r2

d
d

r1 r1

d < (r1 + r2) => Circles overlap d > (r1 + r2) => Circles do not overlap

fig. 78 Circle intersection test.

58 fn outside_mesh aCircle aMesh =


59 (
60
61 for i = 0 to accuracy by 1 do
62 (
63 ang = (i/accuracy as float)*360
64 vx = aCircle.pos.x + cos(ang) * aCircle.radius
65 vy = aCircle.pos.y + sin(ang) * aCircle.radius
66 testRay = ray [vx, vy, 1] [0, 0, -10]
67 if (intersectRay aMesh testRay == undefined) then
68 (
69 return true
70 )
71 )
72 return false
73 )

This function tests whether the circle is inside or outside


the selected shape. In order to do so, the script actually
temporarily applies an Edit Poly modifier to the shape
to turn it into a meshed surface that can be tested for (vx, vy, 1)
intersections. The method of intersection is simple. Several
rays (i.e. vectors) are drawn from the circle down to the
surface. 3ds Max has a built-in function, called intersectRay,
to test if a ray intersects a surface. The ray vectors we
(vx, vy, -9)
construct trace the circumference of the circle (but start
1 unit above) and have a z-length of -10 so that they are
guaranteed to cross the XY ground plane. Any positive z fig. 79 Ray to surface intersection test.
coordinate for the start of the ray and a negative z coordinate
for its end would suffice to test the intersection with a flat
surface on the XY plane (fig. 79).
Circle packing/CONTINUED

75 fn createCircle minRadius maxRadius ratio =


76 (
77 radius = random minRadius (maxRadius - ((maxRadius*ratio/maxAttempts) as float))
78 x = random (minX + radius) (maxX - radius)
79 y = random (minY + radius) (maxY - radius)
80 newCircle = circle radius:radius
81 newCircle.pos = [x,y,0]
82 return newCircle
83 )

This function simply creates a circle within the minimum and maximum ranges for
radius and position. It uses the built-in random function to create a circle within the
specified radius range and the specified position boundary. The position boundary is
determined as the bounding box of the surface, because anything beyond that would
obviously result in a circle outside the shape. Once a circle is created inside the
bounding box of the shape, it is tested more accurately for overlap with other circles
and for location within the shape itself, using the above functions. The ratio parameter
incrementally decreases the maximum radius of a circle as more circles are generated.
As the shape gets filled up with circles it becomes more and more unlikely that large
circles would fit. Thus, with every circle that is successfully generated, we decrease
the maximum allowed radius to force the algorithm to generate smaller and smaller
circles as it progresses.

85 on generate_button pressed do
86 (

This is the main callback function to generate the circles once the Generate button
is pressed.

87 if (selectedShape == undefined) then return false


88 if (isDeleted selectedShape) then
89 (
90 selectedShape_tf.text = “NONE”
91 return false
92 )

If the selected shape is undefined or has been deleted before the button is pressed,
we stop the script, update the interface text field with ‘NONE’ as the name of the
selected shape and return false.

94 coverageArea = 0
95
96 ep_mod = edit_poly()
97 addModifier selectedShape ep_mod
98
99 totalArea=0
100 for i=1 to selectedShape.numfaces do totalArea+=(polyop.getfacearea selectedShape i)
Packing 121

We then set the coverage area variable to 0 and apply the Edit Poly modifier to the
shape to transform it into a polygon. This allows us to test for intersections as well as
to compute its total area.

102 bb = nodeGetBoundingBox selectedShape (matrix3 1)


103 minX = bb[1].x
104 maxX = bb[2].x
105 minY = bb[1].y
106 maxY = bb[2].y

Next, we compute the shape’s bounding box in order to restrict the zone within which
we create circles. This helps us increase the likelihood that a generated circle will fall
within the boundaries of the selected shape.

109 circlesCount = circles.count


110 for i = 1 to circlesCount by 1 do
111 (
112 tobedeleted = circles[1]
113 deleteItem circles 1
114 if(isDeleted tobedeleted != true) then
115 (
116 delete tobedeleted
117 )
118 )
119 circles.count = 0
120 packedCircles.text = “0/”+(maxCircles as string)+” Circles”
121 coverage.text = “0 %”
122 redrawViews()

Next, we empty the current array of circles to start anew. If the user has not manually
deleted any circle, we delete it ourselves. At the end of this block of code, we set the
count of the circles array to 0, update the user interface and redraw the scene.

124 j=1
125 attempts = 0
126 while (circles.count < maxCircles) and (attempts < maxAttempts) do
127 (
128 aCircle = createCircle minRadius maxRadius j
129 if ((overlaps aCircle circles) or (outside_mesh aCircle selectedShape)) then
130 (
131 delete aCircle
132 )
133 else
134 (
135 append circles aCircle
136 j=j+1
137 coverageArea = coverageArea + pi*radius*radius
Circle packing/CONTINUED

138 )
139 attempts = attempts + 1
140 attempts_prog.value = 100.*attempts/maxAttempts
141 generate_prog.value = 100.*j/maxCircles
142 ) --end of the for loop

We then start the main loop of this script. While we have not reached the
maximum number of circles and the maximum number of attempts, we
continue to generate a circle and test its intersection with prior circles and
with the selected shape. If it does overlap with other circles or is fully or
partially outside the shape, we delete it. Otherwise, we append it to the array
of circles and increment the coverage area. Next, we increment the number
of attempts and update both progress bars in the user interface.

144 for m in selectedShape.modifiers do


145 (
146 if classOf m==Edit_Poly do deleteModifier selectedShape m
147 )

At the end of the algorithm we remove the temporary Edit Poly modifier by searching for
it in the list of modifiers that have been applied to the selected shape and deleting it.

149 packedCircles.text = (circles.count as string)+”/”+(maxCircles as string)+” Circles”


150 coverage.text = ((coverageArea/totalArea*100) as string)+” %”
151 )

Finally, we update the interface to inform the user of the number of circles that
have been successfully packed and the total percentage of area coverage.
The last section of the script contains the usual callback functions for the user
interface elements that we use to update the various parameters. Make note of
how the minimum and maximum radius parameters are linked to each other
such that the maximum radius can never be smaller than the minimum radius
and the minimum radius can never be larger than the maximum radius.
This packing algorithm is one of the simplest, as it does not optimize the generation
of the circles (fig. 80). You could enhance it by, for instance, making sure that any
generated circle touches another circle, or by ensuring a minimum separation distance
from all other circles. Once the script has generated a 2D pattern, we can easily
use 3ds Max’s built-in functionality to apply the circles to 3D constructs (fig. 81).
Packing 123

fig. 80 Circle packing within a circular shape.

fig. 81 The Circle Packing script is used to create an imaginary pavilion structure.
124 Parametric patterns

Case study The Beast, Museum of Science, Boston, USA


Designer Neri Oxman in collaboration with Craig Carter
Client Museum of Science, Boston, USA
Design 2009
Construction 2010

Left
Monocoque 1.

Neri Oxman is a researcher and designer whose tools not just to create forms using existing with customized performance and behaviour.
work focuses on the exploration of a new materials but also to help create new materials One such assembly is a resin-impregnated
language of architecture that emerges from the with new formal expressions and behaviour. latex membrane. Oxman has investigated the
usage of modern digital tools, a project that she For Oxman, nature constitutes a source not behaviour of this new material in both physical
calls ‘material ecology’. In her work, computing only of formal inspiration, but also of technical and digital models, and has designed and
is an integral part of the design process, from solutions. Oxman has focused in particular on fabricated a number of innovative projects
conception to fabrication. The form of a designed the fibre composition of biological materials and with it. Monocoque 1 and 2 (2007) constitute
artefact is determined by the digital methodology their ability to map the performance requirements explorations of the structural behaviour of a
that produced it, but that methodology itself may of material structuring and allocation. In order to material in relation to its geometric configuration.
draw on natural processes: Oxman advocates emulate this attribute of natural materials, she Employing a Voronoi algorithm (which also
‘a synergetic approach to design whereby has created what she calls the variable property supplied the iconography of the surface), the
material organization and behaviour, as they design (VPD) method, which allows her to model, designer produced vein-like networks made of a
appear in the physical world, may be integrated simulate and fabricate material assemblies stiff material. Both the distribution and density of
into digital tools for design exploration’. This with varying properties. This allows her to avoid the cellular entities in between these networks
intimate connection between digital tool and default material choices and fabrication methods. and the variation of the surfaces’ overall thickness
designed artefact must be maintained through the Instead, she combines well-known materials, became means of expressing the structure of
production phase of design. ‘The tool, technique such as latex and resin, and manipulates them in the final project. In Monocoque 1, for instance,
or technology has as much value and meaning order to produce responsive surfaces. These new the stiff, black resin composite networks become
as the artefact itself, inherently promoting explicit assemblies exhibit anisotropic qualities that can denser and thicker in vertical areas that perform
effects’, she states. To this end, she uses digital be used to design responsive surfaces and entities under compression, while the soft, white, acrylic-
Packing 125

Above Below
Close-up of black resin composite and When The Beast is positioned vertically, the
white acrylic-based cellular elements. kneeling female figure becomes clearly visible.

based photopolymer cellular elements take more the user, and which attains a greater material
space in the horizontal parts, providing greater sophistication than the Monocoque projects.
flexibility in areas working under tension. The However, the main objective of the project was
arrangement is similar in Monocoque 2. In this to apply a tiling algorithm, using Voronoi cell
case, however, the cellular elements remain tessellation, which implemented the results of a
empty, resulting in an open, 3D framework. quantitative categorization and analysis. Through
In The Beast, which is the prototype for a this project, Oxman points to a new direction for
chaise longue, the designer expanded on the future architecture that tightly couples material
ideas of the Monocoque projects. Resembling a research with digital form-finding processes.
kneeling female figure, The Beast again uses the This approach, which we might understand to
Voronoi pattern, and the single undulating surface be material-as-parameter, combines innovative
has the appearance of a stiff, dark, vein-like parametric design and digital fabrication
network. In order to determine the composition techniques with new, synthetically engineered and
of this surface, a digital analysis of its structural fabricated materials, resulting in an increase in
function identified the requirements of strain, structural and environmental performance and the
stress and comfort in each area, and an algorithm optimization of material efficiency and distribution.
assigned one of five materials for its construction.
The materials vary in softness and flexibility, as
well as in translucency and colour, resulting in
a chair that seems to respond to the needs of
126 Parametric patterns

Weaving
Weaving was known in the Palaeolithic era and continues He writes: ‘Style, as far as it is dependent on the purpose
to this day. In its simplest form, weaving creates a fabric of a thing, can be more easily formulated into principles
from the interlacing of two threads at right angles to each than can the speculative theory of form be deduced
other. The lateral threads do not undulate and are called in those areas where the form must be considered as a
the weft while the longitudinal threads interlace the weft function of the technical means that come into play.’
and are called the warp. This basic method of giving a In this passage, he is advocating the idea that the form
surface structural strength is still used today for basket of an object or building should reflect the process of its
weaving (fig. 82), and it is also employed metaphorically creation; if it does so, this will give rise to theories of form
in architectural screens (fig. 83) and façades (fig. 84). and ultimately the principles of a style. It is exactly this
In his seminal book, The Four Elements of Architecture, notion of encoding the process of design in its final result
the nineteenth-century German architectural theorist that attracts designers to parametric processes. Parametric
and philosopher Gottfried Semper dedicates a chapter digital weaving is an excellent example; the form is not
to the textile arts (at the beginning of which he laments created intuitively, but rather it results from an intelligent
not having an entire book to devote to the discussion). understanding and encoding of its process of creation.
At the start of the chapter, he explains the architectural However, digitally creating a weave is a challenge, as it
reason for his keen interest: ‘All operations in the textile must fulfil several conditions. First, the weave should
arts seek to transform raw materials with the appropriate
properties into products, whose common features are
fig. 82 A basket weave with fig. 83 Design 3 continuous
great pliancy and considerable strength … used as pliant weft and warp threads. interwoven screen for the
surfaces to cover, to hold, to dress, to enclose and so church in Leising, Vienna,
forth.’ In the section on weaving, Semper makes an Austria, Erwin Hauer.
important point, which still fascinates designers today.
Weaving 127

be able to populate any curved or undulating surface basis for creating another parametric system, in the second
and not just simple flat planes. Second, the threads of tutorial, that will accept any NURBS surface as input and
a weave need to maintain their continuity along the generate a matching woven surface made of weft and warp
surface. Unlike tiling and subdivision, a weave – especially threads. As in any parametric system, we will enable the
the warp component – cannot segment the surface into user to specify the parameters of the system, in this case
repeatable, identical modular units. Instead, it has to the thread count in each direction, and the amount of
simultaneously take into consideration the global and undulation as well as the shape and size of the threads.
local conditions of the surface (curvature, orientation) in
order to continually thread the entire surface in a smooth
manner. To add even more to the complexity, a warp
reverses its orientation with every row. Finally, the weave
threads cannot intersect – a situation which happens all
too easily in the non-physical world of 3D modelling.
Starting from these principles and challenges, we will
embark on two tutorials on digital weaving, where the
fig. 84 Aragon Pavilion, Saragossa,
second tutorial will build on the one before it. The first Spain (2008), Olando and Mendo
tutorial will construct a simple parametric ribbon that Architects.
undulates smoothly along a curved spline. This will be the
Tutorial A simple ribbon

In this first tutorial on digital weaving, we will derive an the sweep profile (e.g. the sweep cross-section shape,
undulating ribbon from any line or curve. The script allows size, etc.) can be adjusted independently using the built-
the user to select a line from the scene, dynamically in sweep modifier. This script will be created as a utility.
define the parameters of the ribbon and generate a sweep
profile along the generated spline. The parameters for

Open 3ds Max, save and close any prior scenes, create a new empty
scene. Create an undulating smooth line in the FRONT viewport. For a
smooth line, make sure you choose Bezier as the drag type. Once you
have created a curved line, choose MAXScript New Script from the top
menu. In the script window that opens, type the following algorithm:

1 utility Ribbon “Ribbon”


2 (
3 global mySplineShape
4 global myRibbon
5 global amplitude = 10
6 global steps = 20
7 global sweepMod
8
9 --filter all objects of class Spline or line:
10 fn spline_filt obj = ((classof obj == SplineShape) or (classof obj == line))
11
12 pickbutton selectSpline “Select Spline” width:140 filter:spline_filt
13 edittext selectedObject “Spline: “ text:”NONE” readonly:true width:138
14 spinner steps_spinner “Steps: “ range:[1,1000,steps] type:#integer
15 spinner amplitude_spinner “Amplitude: “ range:[1,1000,amplitude] type:#worldunits
16 button generate_button “Generate” enabled:true width: 140 height:50
17
18 on selectSpline picked obj do
19 (
20 --see if the user did not cancel the picking...
21 if obj != undefined do
22 (
23 -- display the name of the object on the button:
24 selectedObject.text = obj.name
25 mySplineShape = obj
26 )
27 )
28 fn generateRibbon = (
29
30 if (mySplineShape == undefined) then
31 (
32 return false
Weaving 129

33 )
34
35 if (myRibbon != undefined) then
36 (
37 if (not (isDeleted myRibbon)) then
38 (
39 sweepMod = myRibbon.modifiers[“sweep”]
40 delete myRibbon
41 )
42 )
43 myRibbon = SplineShape pos:[0,0,0]
44 addNewSpline myRibbon
45
46 for i = 0 to steps by 1 do
47 (
48 case of (
49 (mod (i+2) 2 == 0): multFact = 1;
50 (mod (i+2) 2 != 0): multFact = -1;
51 )
52
53 unitDist = 1.0/(float) steps
54 currentDist = abs ((float)i/(float)steps)
55
56 if (currentDist > 1) then
57 (
58 currentDist = 1
59 )
60
61 pointPos = pathInterp mySplineShape 1 currentDist
62
63 tangent = normalize (pathTangent mySplineShape 1 currentDist)
64 offsetVect = (normalize (cross tangent y_axis) )* amplitude* multFact
65 offsetPos1 = pointPos + offsetVect
66
67 interpolationInValue = (currentDist - (unitDist/2))
68 if (interpolationInValue < 0) then
69 (
70 interpolationInValue = 0
71 )
72
73 interpolationOutValue = (currentDist + (unitDist/2))
74 if (interpolationOutValue > 1) then
75 (
A simple ribbon/CONTINUED

76 interpolationOutValue = 1
77 )
78
79 inpoint = pathInterp mySplineShape 1 interpolationInValue
80 outpoint = pathInterp mySplineShape 1 interpolationOutValue
81 invector = inpoint + offsetVect
82 outvector = outpoint + offsetVect
83
84 addKnot myRibbon 1 #bezier #curve offsetPos1 invector outvector
85 )
86
87 if (sweepMod == undefined) then
88 (
89 sweepMod = sweep()
90 sweepMod.currentbuiltinshape = 4
91 )
92 addmodifier myRibbon sweepMod
93 updateShape myRibbon
94 )
95
96 on amplitude_spinner changed amt do -- when spinner value changes...
97 (
98 amplitude = amt
99 generateRibbon();
100 )
101
102 on steps_spinner changed amt do -- when spinner value changes...
103 (
104 steps = amt
105 generateRibbon();
106 )
107
108 on generate_button pressed do
109 (
111 generateRibbon();
111 )
112 )
Weaving 131

save your script and then choose Tools Evaluate all to run the script. You will
find the script utility under the utilities tab (hammer icon). click on the MaXScript
button and then choose Ribbon from the utilities pull down menu (fig. 85).
Press the Select Spline button and click on the spline in your scene to select it.
its name should show up under that button. next, click on the Generate button to
generate an initial ribbon. You can then vary the parameters for amplitude and steps
to dynamically change the ribbon. if you wish to change the sweep profile, click on
the actual ribbon to select it, then choose the Modify tab. You will see the sweep
modifier listed so you can change all its parameters there (fig. 86). You can still go
back to the utilities tab and the Ribbon utility to change the amplitude and the
number of steps.

Type a Keyword or phrase


3DS Edit Tools Group Views Create Modifiers Animation Graph Editors Rendering Lighting Analysis Customize MAXScript Help

All View Create Selection Se

Graphite Modeling Tools Freeform Selection Object Paint


Polygon Modeling

Line001

Color Clipboard

Measure

Motion Capture
Reset XForm

MAXScript
Flight Studio (c)

MAXScript

Open Listener

New Script

Open Script

Run Script

Utilities
Convert to mr Area L
Convert to mr Area Light
Ribbon
Sectioning

Ribbon

Select Spline
Spline: NONE
Wiggle Radius: 10.0mm
Steps: 20

Generate

0 /100 Close

0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100
actionMan.executaAction 0 “40. 1 Shape Selected X: 20.557mm Y: –0.0mm Z: 4.164mm Grid = 10.0mm Auto Key Selected
Rollout:Ribbon Click and drag to select and move objects Add Time Tag Set Key Key Filters... 0

fig. 85 Ribbon Utility Script.

Type a Keyword or phrase


3DS Edit Tools Group Views Create Modifiers Animation Graph Editors Rendering Lighting Analysis Customize MAXScript Help

All View Create Selection Se

Graphite Modeling Tools Freeform Selection Object Paint


Polygon Modeling

Shape001

Modifier List

Sweep
Editable Spline

Section Type

Use Built–In Section


Built–In Section

Bar

Use Custom Section


Custom Section Types
Section:
Pick Extract

Merge From File...

Move Instance
Copy Reference

Interpolation
Parameters

Length: 1.62mm
Width: 22.14mm
Corner Radius: 0.0mm

Sweep Parameters
0 /100
Mirror on XZ Plane
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100
$.wirecolor = color 176 26 26 1 Object Selected X: 0.0mm Y: 0.0mm Z: 0.0mm Grid = 10.0mm Auto Key Selected
0 Click and drag to select and move objects Add Time Tag Set Key Key Filters... 0

fig. 86 The sweep modifier.


A simple ribbon/CONTINUED

Let’s take a closer look at the script:

1 utility Ribbon “Ribbon”


2 (
3 global mySplineShape
4 global myRibbon
5 global amplitude = 10
6 global steps = 20
7 global sweepMod

We start by declaring a scripted utility called Ribbon and titled with the same
name. The global variables are mySplineShape (this is the selected spline around
which we will weave a ribbon); myRibbon, which is the resulting ribbon generated
by the script; amplitude, which is the amount of undulation of the ribbon; steps,
which are the number of undulations that the ribbon will have along the curve;
and, finally, sweepMod, which is the sweep modifier that will sweep a cross-
section of our choosing along the ribbon to create a 3D object with thickness.

9 --filter all objects of class Spline or line:


10 fn spline_filt obj = ((classof obj == SplineShape) or (classof obj == line))

Next, we declare a function called spline_filt that accepts an object and


returns either true or false depending on the type (class) of the object.
This function is used to restrict the user to selecting only splines or lines.
Any other object will not be accepted as a selection in the next step.

12 pickbutton selectSpline “Select Spline” width:140 filter:spline_filt


13 edittext selectedObject “Spline: “ text:”NONE” readonly:true width:138
14 spinner steps_spinner “Steps: “ range:[1,1000,steps] type:#integer
15 spinner amplitude_spinner “Amplitude: “ range:[1,1000,amplitude] type:#worldunits
16 button generate_button “Generate” enabled:true width: 140 height:50

Next, we declare a series of user interface elements that will be shown in a rollout
once the user selects the Ribbon utility. The first, a pick button, is a special button
that allows the user to select an object from the scene. One of its arguments is a
filter that will refuse to select an object if the function returns false. This is where
we specify our previously declared spline_filt function. Next, we specify a text field to
display the name of the selected spline, two spinners for specifying the amplitude and
the number of steps, and, last, a button that, when pressed, generates the ribbon.

28 fn generateRibbon = (
29
30 if (mySplineShape == undefined) then
31 (
32 return false
33 )
34
35 if (myRibbon != undefined) then
Weaving 133

36 (
37 if (not (isDeleted myRibbon)) then
38 (
39 sweepMod = myRibbon.modifiers[“sweep”]
40 delete myRibbon
41 )
42 )

We then declare the actual function to generate the ribbon. The function starts out
by testing if the spline shape is undefined (i.e. whether the user has pressed the
generate button before selecting a spline). In this case, the function does nothing
but return the value false. Next, we check whether myRibbon is undefined and, if
so, we check whether it exists. If it does exist (i.e. if it was generated in a previous
cycle), we save its sweep modifier before deleting it to start fresh. We save the
sweep modifier so that we can keep and reuse any prior customization the user
has done to the default ribbon (e.g. changing the sweep shape or its size).

43 myRibbon = SplineShape pos:[0,0,0]


44 addNewSpline myRibbon

Next, we declare a new spline shape and we store it in a variable called myRibbon.
We start by adding a new spline to myRibbon (a spline shape can be made of
many sub-splines).

46 for i = 0 to steps by 1 do
47 (
48 case of (
49 (mod (i+2) 2 == 0): multFact = 1;
50 (mod (i+2) 2 != 0): multFact = -1;
51 )
52
53 unitDist = 1.0/(float) steps
54 currentDist = abs ((float)i/(float)steps)
55
56 if (currentDist > 1) then
57 (
58 currentDist = 1
59 )

In the next section, we start a loop from 0 to the desired number of steps. Within
this loop, we compute whether we are at an odd or an even numbered cycle,
by using the mod command, in order to specify a multiplication factor. Later
in the code, this will be used to create the undulating effect of the ribbon. We
then compute the normalized unit distance (which we can think of as a wave
length) by dividing 1 by the number of steps. We also compute how far we have
travelled along the ribbon’s normalized length by dividing i by the number of
steps (this will give us a number between 0 and 1). In order to avoid any decimal
point inaccuracy we make sure that the current distance never exceeds 1.
A simple ribbon/CONTINUED

61 pointPos = pathInterp mySplineShape 1 currentDist

The above line of code is perhaps the most relevant to this algorithm. The function
pathInterp computes the location of a point on a path based on a parametric normalized
distance (from 0 to 1).

63 tangent = normalize (pathTangent mySplineShape 1 currentDist)


64 offsetVect = (normalize (cross tangent y_axis) )* amplitude* multFact
65 offsetPos1 = pointPos + offsetVect

Once we have computed the point on the curve, we need to compute the location of a
second offset point, which will go either above or below the curve. The challenge here
is that the point should be offset along a line perpendicular to the curve at that location
(fig. 87). Therefore, we need to calculate the tangent at that location before specifying
the perpendicular vector. This is done with an operation called the vector cross product,
which examines two vectors and results in a third vector perpendicular to them.

Unit distance
Amplitude

fig. 87 The basic parameters for curve interpolation.

67 interpolationInValue = (currentDist - (unitDist/2))


68 if (interpolationInValue < 0) then
69 (
70 interpolationInValue = 0
71 )
72
73 interpolationOutValue = (currentDist + (unitDist/2))
74 if (interpolationOutValue > 1) then
75 (
76 interpolationOutValue = 1
77 )
78
79 inpoint = pathInterp mySplineShape 1 interpolationInValue
80 outpoint = pathInterp mySplineShape 1 interpolationOutValue
81 invector = inpoint + offsetVect
82 outvector = outpoint + offsetVect
Weaving 135

We then compute two additional values to specify handles for the Bezier curve tangent.
These points are located half the unit distance on each side of the current point and then
offset using the same offset vector. As we did before, we ensure that the values do not
go outside the 0 to 1 limits.

84 addKnot myRibbon 1 #bezier #curve offsetPos1 invector outvector

Finally, we are able to add a knot (i.e. a vertex) to our ribbon spline. We specify this
vertex as type #bezier, using the two vectors we have just computed, such that the
curve is smooth and tangent to that vertex.

87 if (sweepMod == undefined) then


88 (
89 sweepMod = sweep()
90 sweepMod.currentbuiltinshape = 4
91 )
92 addmodifier myRibbon sweepMod
93 updateShape myRibbon
94 )

In this last step, we define a sweep modifier and add it to the shape. We leave the
specification of the modifier to the user, who can modify the ribbon in the user interface.
In the remainder of the script, we respond to changes in values of the parameters
by re-generating the ribbon in real-time (fig. 88). This is similar to prior tutorials.

fig. 88 Parametric variation of the ribbon.


TuToRial WEaViNg a NurbS SurFaCE

In this second tutorial on digital weaving, we will derive a other attributes in order to avoid self-intersection. Many of the
woven mesh from any NURBS surface. The script allows the algorithmic techniques in this script derive from the previous
user to select a NURBS surface and to specify the thread one. In particular, the distance along a curve is expanded in
counts for the weft and the warp as well as the weave’s this script to the parametric u and v values, as we have seen in
amplitude, to create a mesh with smoothly interlaced weft and prior tutorials. The tangent at the curve in the previous tutorial
warp threads (fig. 89). These threads are created as single- is expanded to a u-tangent and a v-tangent in this tutorial.
line spline curves. A sweep modifier is then applied to them Luckily, MAXScript gives us built-in functions to calculate the u
to create a thickened mesh. Applying the sweep modifier and v tangents at any location on the surface. These tangents
provides the user with the greatest flexibility in parametrically will be essential to the calculation of a perpendicular (normal)
modifying the cross-section and size of the sweep as well as vector to offset the warp threads in alternating directions.

fig. 89 Deriving surface points, woven lines and solids from an initial surface.
Weaving 137

Open 3ds Max, save and close any prior scenes, and create a new empty scene.
Create an undulating NURBS surface (if you need help with this, see the tutorial on
deriving a diagrid mesh from a NURBS surface on page 93). Once you have created
the surface, choose MAXScript New Script from the top menu. In the script
window that opens, type the following algorithm:

1 utility Weave “Weave”


2 (
3 global selectedSurface
4 global myNURBSSurface
5 global myWeft
6 global myWarp
7 global weftThreadCount = 10
8 global warpThreadCount =10
9 global amplitude = 1
10 global multFact = 1
11 global weftSweepMod
12 global warpSweepMod
13 global hideNURBS
14 global swapUV = false
15 global closedInU = 0
16 global closedInV = 0
17
18 -- A function to filter all objects that are not of class NURBS Surface:
19 fn nurbs_filt obj = (classOf obj == NURBSSurf)
20
21 pickbutton selectNURBS “Select NURBS” width:140 filter:nurbs_filt
22 edittext selectedObject “NURBS: “ text:”NONE” readonly:true width:138
23 spinner weftThreadCount_spinner “Weft: “ range:[1,10000,weftThreadCount] type:#integer
24 spinner warpThreadCount_spinner “Warp: “ range:[1,10000,warpThreadCount] type:#integer
25 spinner amplitude_spinner “Amplitude: “ range:[0,10000,amplitude] type:#worldunits
26 checkbox swapUV_cb “Swap” checked:false tooltip:”Swap U and V directions”
27 checkbox hideNURBS_cb “Hide NURBS” checked:false tooltip:”Hide Parent NURBS Surface”
28 button generate_button “Generate” enabled:true width: 140 height:50
29
30 on selectNURBS picked obj do
31 (
32 --see if the user did not cancel the picking...
33 if obj != undefined do
34 (
35 -- display the name of the object on the button:
36 selectedObject.text = obj.name
37 myNURBSSurface = getnurbsset obj #relational
38 selectedSurface = obj
39 )
Weaving a NURBS surface/CONTINUED

40 )
41
42 fn generateWeave = (
43
44 if (myNURBSSurface == undefined) then
45 (
46 return false
47 )
48
49 if (myWeft != undefined) then
50 (
51 if (not (isDeleted myWeft)) then
52 (
53 weftSweepMod = myWeft.modifiers[“sweep”]
54 delete myWeft
55 )
56 )
57
58 if (myWarp != undefined) then
59 (
60 if (not (isDeleted myWarp)) then
61 (
62 warpSweepMod = myWarp.modifiers[“sweep”]
63 delete myWarp
64 )
65 )
66
67 for m = 1 to myNURBSSurface.count by 1 do
68 (
69 if ((superClassOf myNURBSSurface[m]) == NURBSSurface) then
70 (
71 -- Find the min and max values for the u and v range.
72 minu = (myNURBSSurface[m].uParameterRangeMin)
73 maxu = (myNURBSSurface[m].uParameterRangeMax)
74 minv = (myNURBSSurface[m].vParameterRangeMin)
75 maxv = (myNURBSSurface[m].vParameterRangeMax)
76
77 case of (
78 (myNURBSSurface[m].closedInU == true): (format “shape closed in U\n”;closedInU = 1)
79 (myNURBSSurface[m].closedInU == false): (format “shape open in U\n”; closedInU = 0)
80 )
Weaving 139

81
82 case of (
83 (myNURBSSurface[m].closedInV == true): closedInV = 1
84 (myNURBSSurface[m].closedInV == false): closedInV = 0
85 )
86
87 myWarp = SplineShape pos:[0,0,0]
88 for i = 0 to (warpThreadCount - 1) by 1 do
89 (
90 case of (
91 (mod (i+2) 2 == 0): xmultFact = 1;
92 (mod (i+2) 2 != 0): xmultFact = -1;
93 )
94
95 xposition = (i/(warpThreadCount - 1) as float)
96 if (xposition > 1) then
97 (
98 xposition = 1
99 )
100
101 addNewSpline myWarp
102
103 for j = 0 to (weftThreadCount - 1 - closedInV) by 1 do
104 (
105 case of (
106 (mod (j+2) 2 == 0): ymultFact = 1;
107 (mod (j+2) 2 != 0): ymultFact = -1;
108 )
109
110 unitDist = (1/(weftThreadCount - 1) as float)
111 yposition = (j/(weftThreadCount - 1) as float)
112 uposition = (minu + (maxu-minu)*xposition)
113 vposition = (minv + (maxv-minv)*yposition)
114
115 case of (
116 (swapUV == false): pointPos = evalpos myNURBSSurface[m] uposition vposition
117 (swapUV == true): pointPos = evalpos myNURBSSurface[m] vposition uposition
118 )
119
120 uTangent = evalUTangent myNURBSSurface[m] uposition vposition
121 vTangent = evalVTangent myNURBSSurface[m] uposition vposition
122 offsetVect = (normalize (cross uTangent vTangent))*xmultFact*ymultFact*amplitude
123 offsetPos = pointPos + offsetVect
Weaving a NURBS surface/CONTINUED

124 addKnot myWarp (i+1) #smooth #curve offsetPos


125 )
126 if (myNURBSSurface[m].closedInV) then
127 (
128 close myWarp (i+1)
129 )
130 )
131
132 if (warpSweepMod == undefined) then
133 (
134 warpSweepMod = sweep()
135 warpSweepMod.currentbuiltinshape = 4
136 )
137 addmodifier myWarp warpSweepMod
138 myWarp.rotation = selectedSurface.rotation
139 myWarp.scale = selectedSurface.scale
140 myWarp.pos = selectedSurface.pos
141 myWarp.name = selectedSurface.name + “-Warp” + (m as string)
142 Updateshape myWarp
143
144 myWeft = SplineShape pos:[0,0,0]
145 for i = 0 to (weftThreadCount - 1 - closedInV) by 1 do
146 (
147 yposition = (i/(weftThreadCount - 1) as float)
148 addNewSpline myWeft
149 for j = 0 to (warpThreadCount - 1 - closedInU) by 1 do
150 (
151 xposition = (j/(warpThreadCount - 1) as float)
152 uposition = (minu + (maxu-minu)*xposition)
153 vposition = (minv + (maxv-minv)*yposition)
154
155 case of (
156 (swapUV == false): pointPos = evalpos myNURBSSurface[m] uposition vposition
157 (swapUV == true):pointPos = evalpos myNURBSSurface[m] vposition uposition
158 )
159
160 addKnot myWeft (i+1) #smooth #curve pointPos
161 )
162 if (myNURBSSurface[m].closedInU) then
163 (
164 close myWeft (i+1)
Weaving 141

165 )
166 )
167 myWeft.rotation = selectedSurface.rotation
168 myWeft.scale = selectedSurface.scale
169 myWeft.pos = selectedSurface.pos
170 myWeft.name = selectedSurface.name + “-Weft” + (m as string)
171
172 if (weftSweepMod == undefined) then
173 (
174 weftSweepMod = sweep()
175 weftSweepMod.currentbuiltinshape = 4
176 )
177 addmodifier myWeft weftSweepMod
178 updateShape myWeft
179 )
180 else
181 (
182 format “Could not find a NURBS surface.\n”
183 )
184 )
185 )
186
187 -- Handle the user interface events.
188 on weftThreadCount_spinner changed amt do
189 (
190 weftThreadCount = amt
191 generateWeave();
192 )
193 on warpThreadCount_spinner changed amt do
194 (
195 warpThreadCount = amt
196 generateWeave();
197 )
198 on amplitude_spinner changed amt do
199 (
200 amplitude = amt
201 generateWeave();
202 )
203 on swapUV_cb changed state do
204 (
205 swapUV = state
206 generateWeave()
207 )
Weaving a NURBS surface/CONTINUED

208 on hideNURBS_cb changed state do


209 (
210 if (selectedSurface != undefined) then
211 (
212 case of (
213 (state == true): hide selectedSurface
214 (state == false): unhide selectedSurface
215 )
216 )
217 )
218 on generate_button pressed do
219 (
220 generateWeave()
221 )
222 )

Save your script and then choose Tools Evaluate All to run the script.
You will find the script utility under Utilities (hammer icon). Click on the
MAXScript button and then choose Weave from the Utilities pull down menu.

Workspace: Default Type a Keyword or phrase


3DS Edit Tools Group Views Create Modifiers Animation Graph Editors Rendering Lighting Analysis Civil View Customize MAXScript Help

All View Create Selection Se


SelMatIDEdges

Graphite Modeling Tools Freeform Selection Object Paint


Polygon Modeling

Modifier List

0 /100

0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100
clearSelecti None Selected X: -416.538m Y: -136.056m Z: 0.0mm Grid = 10.0mm Auto Key Selected
shape open i Click or click–and–drag to select objects Add Time Tag Set Key Key Filters... 0

fig. 90 A parametric woven surface generated by the script.


Weaving 143

Press the Select NURBS button and click on the NURBS surface in your scene to
select it. Its name should show up under that button. Next, specify the number of
weft and warp threads, and the amplitude of the undulation of the warp thread.
Here you can also swap the direction of the threads and hide or show the selected
NURBS surface. Once you are ready, click on the Generate button to generate
an initial woven mesh (fig. 90). You can then vary the parameters for amplitude
and steps to dynamically change the weave. If you wish to change the sweep
profile, click on the actual weft or warp threads in the scene to select them,
then choose the Modify tab. You will see the sweep modifier listed and you can
change all its parameters there (fig. 91). You can still go back to the Utilities tab
and the Weave utility in order to change the amplitude and the number of steps.

Workspace: Default Type a Keyword or phrase


3DS Edit Tools Group Views Create Modifiers Animation Graph Editors Rendering Lighting Analysis Civil View Customize MAXScript Help

All View Create Selection Se


SelMatIDEdges

Graphite Modeling Tools Freeform Selection Object Paint


Polygon Modeling

Modifier List

0 /100

0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100
clearSelecti None Selected X: 138.461m Y: –428.592m Z: 0.0mm Grid = 10.0mm Auto Key Selected
shape open i Click or click–and–drag to select objects Add Time Tag Set Key Key Filters... 0

fig. 91 The sweep modifier.

Let’s take a closer look at the script:

1 utility Weave “Weave”


2 (
3 global selectedSurface
4 global myNURBSSurface
5 global myWeft
6 global myWarp
7 global weftThreadCount = 10
8 global warpThreadCount =10
9 global amplitude = 1
Weaving a NURBS surface/CONTINUED

10 global multFact = 1
11 global weftSweepMod
12 global warpSweepMod
13 global hideNURBS
14 global swapUV = false
15 global closedInU = 0
16 global closedInV = 0

We start by declaring a scripted utility called Weave and titled with the same name.
The global variables are selectedSurface (the NURBS surface the user selects from the
scene), myNURBSSurface (the internal representation of the NURBS surface), myWeft
and myWarp (the generated splines for the weft and warp), the thread counts, the
amplitude of the weave, a multiplying factor to decide on the direction of the offset, the
weft and warp sweep modifiers, a Boolean variable for deciding if the NURBS surface is
to be shown or hidden, a flag to switch the u and v directions, and two last variables to
indicate if the NURBS surface is closed (joined end-to-end) or open (e.g. a sheet of paper).

19 fn nurbs_filt obj = (classOf obj == NURBSSurf)

This function is used as a filter to make sure only NURBS surfaces are selected for weaving.

21 pickbutton selectNURBS “Select NURBS” width:140 filter:nurbs_filt


22 edittext selectedObject “NURBS: “ text:”NONE” readonly:true width:138
23 spinner weftThreadCount_spinner “Weft: “ range:[1,10000,weftThreadCount] type:#integer
24 spinner warpThreadCount_spinner “Warp: “ range:[1,10000,warpThreadCount] type:#integer
25 spinner amplitude_spinner “Amplitude: “ range:[0,10000,amplitude] type:#worldunits
26 checkbox swapUV_cb “Swap” checked:false tooltip:”Swap U and V directions”
27 checkbox hideNURBS_cb “Hide NURBS” checked:false tooltip:”Hide Parent NURBS Surface”
28 button generate_button “Generate” enabled:true width: 140 height:50

Then we define the user interface: a pick button to select the NURBS surface from the
scene, a text field to display the name of the selected surface, three spinners to input
the values for the weft and warp thread counts and the amplitude of the warp, and two
checkboxes, one to specify if the u and v need to be swapped and one for whether to
hide the parent NURBS surface. Finally, we provide a button to generate the weave.
Changing any value in the interface triggers a re-generation of the weave. This results
in real-time updating and a smoother user experience, where the effect of changing a
parameter can be seen instantly.

30 on selectNURBS picked obj do


31 (
32 --see if the user did not cancel the picking...
33 if obj != undefined do
34 (
35 -- display the name of the object on the button:
36 selectedObject.text = obj.name
37 myNURBSSurface = getnurbsset obj #relational
Weaving 145

38 selectedSurface = obj
39 )
40 )

The callback function above is triggered once the user picks an object from the scene.
The function copies the name of the object, retrieves 3ds Max’s internal representation
of the NURBS surface and stores a pointer to it in the variable selectedSurface.

42 fn generateWeave = (

We then start the main function to generate the weave.

44 if (myNURBSSurface == undefined) then


45 (
46 return false
47 )

If the surface is undefined, then stop the algorithm and return the value false.

49 if (myWeft != undefined) then


50 (
51 if (not (isDeleted myWeft)) then
52 (
53 weftSweepMod = myWeft.modifiers[“sweep”]
54 delete myWeft
55 )
56 )
57
58 if (myWarp != undefined) then
59 (
60 if (not (isDeleted myWarp)) then
61 (
62 warpSweepMod = myWarp.modifiers[“sweep”]
63 delete myWarp
64 )
65 )

If the weft and warp exist and have not been deleted by the user, then, before deleting
them, save a copy of their sweep modifiers to reuse for the new weft and warp.

67 for m = 1 to myNURBSSurface.count by 1 do
68 (

A NURBS can have many sub-surfaces. Loop through them one by one to weave each.

69 if ((superClassOf myNURBSSurface[m]) == NURBSSurface) then


70 (
Weaving a NURBS surface/CONTINUED

A NURBS structure can be made of surfaces, curves and vertices. We make sure
we only weave surfaces by examining the superclass of the current surface.

72 minu = (myNURBSSurface[m].uParameterRangeMin)
73 maxu = (myNURBSSurface[m].uParameterRangeMax)
74 minv = (myNURBSSurface[m].vParameterRangeMin)
75 maxv = (myNURBSSurface[m].vParameterRangeMax)

We then find the parametric range for the surface (the minimum and maximum u and v
values).

77 case of (
78 (myNURBSSurface[m].closedInU == true): (format “shape closed in U\n”;closedInU = 1)
79 (myNURBSSurface[m].closedInU == false): (format “shape open in U\n”; closedInU = 0)
80 )
81
82 case of (
83 (myNURBSSurface[m].closedInV == true): closedInV = 1
84 (myNURBSSurface[m].closedInV == false): closedInV = 0
85 )

Next, we check if the NURBS surface is open or closed. This will help us to avoid
overlapping vertices if it is closed.

87 myWarp = SplineShape pos:[0,0,0]

We define a new spline shape for the warp.

88 for i = 0 to (warpThreadCount - 1) by 1 do
89 (

We create two nested loops to generate the warp. The outer loop iterates from 0 to
the warp tread count (minus 1).

90 case of (
91 (mod (i+2) 2 == 0): xmultFact = 1;
92 (mod (i+2) 2 != 0): xmultFact = -1;
93 )

We test if we are on an even or an odd iteration to reverse the direction of the warp.

95 xposition = (i/(warpThreadCount - 1) as float)


96 if (xposition > 1) then
97 (
98 xposition = 1
99 )
Weaving 147

We then calculate the xposition as a factor from 0 to 1 based on the current iteration.
We will use xposition later to calculate the coordinates of the current point on the surface.

101 addNewSpline myWarp

We add a new spline to the myWarp spline structure.

103 for j = 0 to (weftThreadCount - 1 - closedInV) by 1 do


104 (

We then start the inner nested loop to go through the weft threads. We deduct 1 if it
is a closed NURBS surface to avoid overlapping vertices.

105 case of (
106 (mod (j+2) 2 == 0): ymultFact = 1;
107 (mod (j+2) 2 != 0): ymultFact = -1;
108 )

We then test if we are on an even or an odd inner iteration to set the direction of the
warp.

110 unitDist = (1/(weftThreadCount - 1) as float)


111 yposition = (j/(weftThreadCount - 1) as float)
112 uposition = (minu + (maxu-minu)*xposition)
113 vposition = (minv + (maxv-minv)*yposition)

Next, we calculate a normalized unit distance, a yposition, a uposition and a vposition.


The latter two positions will enable us to derive the coordinates of the current point on
the surface.

115 case of (
116 (swapUV == false): pointPos = evalpos myNURBSSurface[m] uposition vposition
117 (swapUV == true): pointPos = evalpos myNURBSSurface[m] vposition uposition
118 )

We detect whether the user wishes to swap the u and v directions and then we use the
built-in evalpos function to derive the coordinates of the current point on the surface,
based on the calculated u and v positions.

120 uTangent = evalUTangent myNURBSSurface[m] uposition vposition


121 vTangent = evalVTangent myNURBSSurface[m] uposition vposition
122 offsetVect = (normalize (cross uTangent vTangent))*xmultFact*ymultFact*amplitude
123 offsetPos = pointPos + offsetVect
Weaving a NURBS surface/CONTINUED

We compute the u and v tangents at the current point. We then compute a vector
perpendicular to these two tangents and add that offset to the current point (fig. 92).

ct
du
pro nt
ss
ge
cro

an
ut
ta
n
v

ge
nt

ce
an
ist
ud

fig. 92 u & v tangents and cross-product vector.

124 addKnot myWarp (i+1) #smooth #curve offsetPos

We are finally ready to add a knot (vertex) to the spline. We specify the vertex to be smooth and part of a curve.

126 if (myNURBSSurface[m].closedInV) then


127 (
128 close myWarp (i+1)
129 )

If the curve is a closed NURBS, we close the spline as well.

132 if (warpSweepMod == undefined) then


133 (
134 warpSweepMod = sweep()
135 warpSweepMod.currentbuiltinshape = 4
136 )
137 addmodifier myWarp warpSweepMod
138 myWarp.rotation = selectedSurface.rotation
139 myWarp.scale = selectedSurface.scale
140 myWarp.pos = selectedSurface.pos
141 myWarp.name = selectedSurface.name + “-Warp” + (m as string)
142 Updateshape myWarp
Weaving 149

In this section we apply the sweep modifier; position the warp with the same location, rotation
and scale as the selected surface; give it a name; and update the shape on the screen.

144 myWeft = SplineShape pos:[0,0,0]

We are now ready to create the weft thread. The weft is simpler as it does not undulate.

145 for i = 0 to (weftThreadCount - 1 - closedInV) by 1 do


146 (

As we have seen before, we create a nested loop to draw all the weft threads and all
the vertices on each thread. We deduct one iteration if the NURBS surface is closed.

147 yposition = (i/(weftThreadCount - 1) as float)

We then calculate the normalized yposition.

148 addNewSpline myWeft

Then we add a new spline that we call myWeft.

149 for j = 0 to (warpThreadCount - 1 - closedInU) by 1 do


150 (

The inner nested loop iterates through the number of warp threads. We deduct 1
if the NURBS surface is closed to avoid overlapping vertices.

151 xposition = (j/(warpThreadCount - 1) as float)


152 uposition = (minu + (maxu-minu)*xposition)
153 vposition = (minv + (maxv-minv)*yposition)

Next, we calculate the xposition and derive the u and v positions for the current point.

155 case of (
156 (swapUV == false): pointPos = evalpos myNURBSSurface[m] uposition vposition
157 (swapUV == true):pointPos = evalpos myNURBSSurface[m] vposition uposition
158 )

We check if the user wishes to swap the u and v directions, and then evaluate
the position of the current point based on the current u and v positions.

160 addKnot myWeft (i+1) #smooth #curve pointPos

We are now ready to add a knot (vertex) to the current spline.

162 if (myNURBSSurface[m].closedInU) then


163 (
164 close myWeft (i+1)
165 )
Weaving a NURBS surface/CONTINUED

If the NURBS surface is closed, we close the weft spline as well.

167 myWeft.rotation = selectedSurface.rotation


168 myWeft.scale = selectedSurface.scale
169 myWeft.pos = selectedSurface.pos
170 myWeft.name = selectedSurface.name + “-Weft” + (m as string)

Once we have created all the weft threads, we position the weft at the same location as
the selected surface and give it a name.

172 if (weftSweepMod == undefined) then


173 (
174 weftSweepMod = sweep()
175 weftSweepMod.currentbuiltinshape = 4
176 )
177 addmodifier myWeft weftSweepMod
178 updateShape myWeft

We add the sweep modifier to the weft spline and update the shape on the screen.

180 else
181 (
182 format “Could not find a NURBS surface.\n”
183 )

The above is the else clause of the top if statement. That is, if the surface is not
a NURBS surface, we simply display a message and stop the algorithm.
The last section of the code handles the user interface callback functions and triggers
the generateWeave() function as needed.
By varying the number of threads and the parameters of the sweep profile, you can
create almost endless variations and explore the structural qualities of the generated
solution (fig. 93). The iterative, real-time nature of the script allows it to be used as a
form-finding tool in the design process and moves us away from static modelling into
truly parametric form generation (fig. 94).
Weaving 151

fig. 93 Example renderings of the weaving script.

fig. 94 The weaving script is used to create an imaginary woven stadium structure.
152 Parametric patterns

Case study nonLin/Lin Pavilion, FRAC Centre,


Orleans, France
Designer Marc Fornes/THEVERYMANY
Client FRAC Centre, Orleans, France
Design 2010
Construction 2011

A prolific and inventive designer, Marc Fornes potentials and, of course, as a material with Above
produces large-scale installations and sculptural specific spatial and aesthetic possibilities. General view of the pavilion fully assembled.

pieces of public art, but his work constitutes The complex, organic curvatures
Opposite
an investigation of fundamentally architectural incorporated in his installations serve as Close-up view of the pavilion
issues, and the coral-like and floral creations structural reinforcement; their form takes into showing its star-like pattern.
that have come to identify his formal vocabulary consideration the material’s natural stiffness
raise questions that belong firmly in the as well as the conditions in which a particular
discipline of architecture. As is the case with project will be displayed. That is, the exact forms
many other contemporary designers, Fornes of his projects depend on whether they will be
is fascinated with the issue of the surface. set on the floor, hung from a wall or ceiling, or
He approaches it not as an undulating plane placed in an interior or exterior space. Fornes
that simply embodies a formalistic treatment, approaches even this aspect of his work in a
but as a constituent member of his projects, daring, experimental manner. In a composition for
with specific structural qualities and functional Union Square, New York, he selected thin, fragile
154 Parametric patterns

007

008 000 024

009 001 025

010 002 026

011 003 027

012 004 028

013 005 029

014 006 030

015 031

016

017
020
018
021
019
022

023

080 086
Name: 17148 Name: 17-3
Type: Stripe Type: Edge
Holes: 26 Holes: 20
081 087 093
Name: 17153 Name: 17.5+ Name: 17145
Type: Stripe Type: Ring+ Type: Stripe
Holes: 14 Holes: 54 Holes: 28
082 088 094 099
Name: 1751 Name: 2.1.0 Name: 1766 Name: 1781
Type: Stripe Type: Ring+ Type: Stripe Type: Stripe
Holes: 49 Holes: 56 Holes: 39 Holes: 64
083 089 095 100 103
000 Name: 1757 Name: 17.3 Name: 17155 Name: 17.6+ Name: 17149
Name: 26-2 Type: Stripe Type: Ring+ Type: Stripe Type: Ring+ Type: Stripe
Type: Edge Holes: 46 Holes: 72 Holes: 10 Holes: 54 Holes: 5
Holes: 20 084 090 096 101 104
001 010 Name: 17151 Name: 1760 Name: 1796 Name: 17-2 Name: 17157
Name: 26.6+ Name: 26162 Type: Stripe Type: Stripe Type: Stripe Type: Edge Type: Stripe
Type: Ring+ Type: Stripe Holes: 10 Holes: 10 Holes: 56 Holes: 38 Holes: 6
Holes: 6 Holes: 6 085 091 097 102 105
002 011 019 Name: 1765 Name: 1758 Name: 17105 Name: 17147 Name: 17156
Name: 26.4+ Name: 26.0+ Name: 26-1.1 Type: Stripe Type: Stripe Type: Stripe Type: Stripe Type: Stripe
Type: Ring+ Type: Ring+ Type: Edge Holes: 46 Holes: 30 Holes: 36 Holes: 7 Holes: 6
Holes: 51 Holes: 64 Holes: 8 092 098
003 012 020 026 Name: 1773 Name: 17120
Name: 26155 Name: 26103 Name: 2646 Name: 26143 Type: Stripe Type: Stripe
Type: Stripe Type: Stripe Type: Stripe Type: Stripe Holes: 23 Holes: 14
Holes: 31 Holes: 56 Holes: 44 Holes: 10
004 013 021 027
Name: 26166 Name: 26104 Name: 2644 Name: 2651
Type: Stripe Type: Stripe Type: Stripe Type: Stripe 080
Holes: 24 Holes: 12 Holes: 46 Holes: 41
005 014 022 028
Name: 26178 Name: 26135 Name: 2672 Name: 26146 081
Type: Stripe Type: Stripe Type: Stripe Type: Stripe
Holes: 8 Holes: 12 Holes: 24 Holes: 10
006 015 023 029 082
Name: 26141 Name: 26110 Name: 26.5.0 Name: 2636
Type: Stripe Type: Stripe Type: Ring Type: Stripe
Holes: 35 Holes: 42 Holes: 47 Holes: 46 083
007 016 024 030
Name: 26-0 Name: 26.4.0 Name: 26.0.0 Name: 2643
Type: Edge Type: Ring Type: Ring Type: Stripe 084
Holes: 56 Holes: 105 Holes: 41 Holes: 46
008 017 025 031 085
Name: 26.1+ Name: 26.4.1 Name: 26147 Name: 2648
Type: Ring+ Type: Ring Type: Stripe Type: Stripe
Holes: 6 Holes: 12 Holes: 5 Holes: 52
009 018
Name: 26.2+ Name: 26-1.0
Type: Ring+ Type: Edge
Holes: 64 Holes: 50 086
032
087
033
102
034
103
035
104

105

Above
036
View showing the forest-like character of the pavilion.
037
088
038

Left
039
093
089
094

Exploded axonometric drawing showing the pavilion’s


090
095
091
096
055
092

various parts in preparation for digital fabrication.


097
056

098
057

099
040 058
066 072
100 Name: 0281 Name: 02190
041 051 059 Type: Stripe Type: Stripe
Holes: 18 Holes: 8
101 060
042 052 060 067 073 077
Name: 2.1+ Name: 0290 Name: 0279 Name: 2.4+
Type: Ring+ Type: Stripe Type: Stripe Type: Ring+
Holes: 52 Holes: 22 Holes: 38 Holes: 63
043 053 061
055 061 068 074 078
Name: 0284 Name: 2.2+ Name: 2.0+ Name: 02112 Name: 2.3+
038 054 062 Type: Stripe Type: Ring+ Type: Ring+ Type: Stripe Type: Ring+
Name: 00108 Holes: 26 Holes: 6 Holes: 54 Holes: 26 Holes: 6
Type: Stripe 056
044 Holes: 8 062 069 075 079
Name: 0293 Name: 2-4 Name: 2-2 Name: 02139 Name: 2-3
032 039 045 Type: Stripe Type: Edge Type: Edge Type: Stripe Type: Edge
Name: 0075 Name: 0082 Name: 005 Holes: 24 Holes: 20 Holes: 23 Holes: 20 Holes: 30
045 Type: Stripe Type: Stripe Type: Stripe 057 063 070 076
Holes: 35 Holes: 31 Holes: 12 Name: 02102 Name: 0264 Name: 0278 Name: 02181
046 033 040 046 051 Type: Stripe Type: Stripe Type: Stripe Type: Stripe
Name: 00118 Name: 0.3.0 Name: 002 Name: 0074 Holes: 6 Holes: 38 Holes: 43 Holes: 8
Type: Stripe Type: Ring Type: Stripe Type: Stripe 058
Holes: 20 Holes: 74 Holes: 45 Holes: 25 064 071
047 Name: 02101 Name: 0263 Name: 0273
034 041 047 052 Type: Stripe Type: Stripe Type: Stripe
Name: 0.3+ Name: 0.3.1 Name: 001 Name: 0072 Holes: 14 Holes: 36 Holes: 47
048 Type: Rings+ Type: Ring Type: Stripe Type: Stripe 059
Holes: 66 Holes: 10 Holes: 50 Holes: 26 065
070 Name: 02100 Name: 0297
035 042 048 053 Type: Stripe Type: Stripe
049 Name: 0-4 Name: 0-1.0 Name: 004 Name: 0038 Holes: 24 Holes: 8
Type: Edge Type: Edge Type: Stripe Type: Stripe 071
Holes: 20 Holes: 39 Holes: 17 Holes: 52
050 036 043 049 054 063
Name: 0017 Name: 0-1.1 Name: 0018 Name: 0012 072
Type: Stripe Type: Edge Type: Stripe Type: Stripe
Holes: 37 Holes: 6 Holes: 8 Holes: 58 064
037 044 050 073
Name: 0087 Name: 003 Name: 0.0+
Type: Stripe Type: Stripe Type: Rings+ 065
Holes: 27 Holes: 58 Holes: 60 074
066
075
067
076
068
077
069
078

079

sheets of walnut veneer, and sought to enhance permanent collection of FRAC Centre in Orleans, organization allowed Fornes to derive and re-
their strength by curving them in two directions. France. The elaborate
MARC form:: THEVERYMANY
FORNES of the pavilion 2011 TM assemble the information and numerical data
While, unfortunately, the whole composition ended originated from a ‘Y’ model, which transformed necessary for the final production of the project.
up collapsing under its own weight, it was a true in its dimensions as it was repeated in multiple The topological model for this project was
test of the limits of material experimentation. directions. Because this type of form cannot sufficiently powerful to generate a completed
Fornes also addresses issues of utility be modelled with a bi-directional surface, an pavilion consisting of 6,000 different strips of
in his work. Due to their large scale, some of important computational change was to move aluminium, less than 1 mm thick, which are
his installations provide enclosures in which away from (bi-directional) NURBS surfaces connected to one another through 75,000 rivets
traditional architectural elements (such as and towards visualizing the project’s form as a and are adorned with 150,000 star-shaped
walls, ceilings and openings) acquire new, topology. This approach allowed Fornes to follow holes. More important than the numbers,
unconventional forms. Some of his other projects a cohesive sequence from the initial conception however, are the architectural concepts that
have served utilitarian functions, such as the to the final production of the project. Working with the 10 m long pavilion is able to communicate
centrepiece of a playground and a display for custom computational protocols, he implemented to its viewers. Issues of structural behaviour,
jewellery. Fornes is very careful to note the a form-finding parametric algorithm that allowed spatial enclosure, aperture and applied
experimental, prototypical nature of his work, but surface smoothing and relaxation and which ornamentation come together to compose a
he has also stated that standardized production resulted in the organic form of the pavilion. comprehensive statement of future architecture.
of his projects is one of his objectives. The topological model was then put through
All of Fornes’s projects begin with code. additional processes, including tessellation and
His use of digital technologies is clearly visible the derivation of planar developable surfaces, in
in the nonLin/Lin Pavilion, which is part of the order to facilitate production. Finally, the model’s
Weaving 155

Above Above right Below


The pavilion fully assembled at the site. Close-up view of the extremities of the pavilion. View of the pavilion under construction.
156 Parametric patterns

Branching
Whether it is the limbs of a tree, the fibrous root system as a plant or tree (fig. 96), is determined by phototropism
of an onion, human lungs or coralline algae, branching or heliotropism (seeking light and sun, respectively) and
is a basic topological growth mechanism in nature for gravitropism (resisting the forces of gravity), as well as wind
maximizing surface area, channelling resources and direction, physical obstacles, the availability of nutrients,
responding to structural forces (fig. 95). Branching systems and many other factors. In architecture, branching is
in nature are self-similar and recursive and so tend to be most vividly illustrated in structural systems that use it
fractal. To borrow the words of Benoit Mandelbrot, in a to satisfy both practical and evocative design goals (figs.
recursive branching system the geometry of the part is 97 and 98). We can also use hierarchical branching as
similar to the geometry of the whole. In reality, several an organizational instrument for ordering information,
forces or, more accurately, tropisms affect the overall space, flow of resources or even the logic of a piece of
growth direction and geometry of a branching system. The software, as we have seen in previous algorithms.
idiosyncratic form of a natural branching system, such

fig. 95 An anatomically based


computational model of a
pulmonary arterial network.

fig. 96 Windswept tree,


south coast of England.
Branching 157

fig. 97 Branching columns at


the Sagrada Familia church,
Barcelona, Spain, Antoni Gaudí.

fig. 98 The Tote, Mumbai,


India, Serie Architects.
Tutorial Recursive branching

In the following tutorial, we will create a very simple yet value. For a more regular result, the user can reduce the range
parametrically flexible branching system using a recursive all the way to the point where the minimum and maximum
technique similar to those in prior tutorials. The logic of fractal values are equal in order to force the algorithm to always
recursion will be directly reflected in the recursive fractal choose a single value. There are many generative branching
geometry of the resulting design. The algorithm provides the systems that are far more advanced than the basic algorithm
possibility for either orthogonal/regular or randomized/organic presented here (e.g. ones that consider several tropisms),
branching, by allowing the user to specify ranges for parameters but the purpose of the following tutorial is to introduce you to
such as the number of branches at each recursive step, their the basics of generative branching algorithms. You can then
angle of rotation and their length. For organic-looking results, use it as a stepping stone to a more refined and advanced
the user can specify a range of numbers with minimum and script for creating more complex parametric constructs.
maximum values, from which the algorithm chooses a random

Open 3ds Max, save and close any prior scenes, and create a new
empty scene. Choose MAXScript New Script from the top menu.
In the script window that opens, type the following algorithm:

1 utility Branching “Branching”


2 (
3 global rootTree
4 global branchesArray = #()
5
6 -- Parameters
7
8 -- Branch Shape
9 global trunkHeight = 200
10 global trunkRadius = 2
11 global trunkSides = 12
12 global taperingFactorMin = 0.4
13 global taperingFactorMax = 0.6
14
15 -- Branching
16 global branchingDepth = 5
17 global branchingNumberMin = 4
18 global branchingNumberMax = 8
19
20 -- Offset/Translation
21 global offsetFactorMin = 0.0
22 global offsetFactorMax = 0.5
23
24 -- Unfolding/Rotation
25 global branchingXAngleMin = 10
26 global branchingXAngleMax = 15
27 global branchingZAngleMin = 2
28 global branchingZAngleMax = 6
Branching 159

29
30 -- Height/Scale
31 global heightFactorMin = 0.2
32 global heightFactorMax = 0.8
33
34 group “Branch Shape”
35 (
36 spinner trunkHeight_spinner “Height: “ type:#worldunits range:[0.0001,100000,trunkHeight] toolTip:”Initial Trunk
Height”
37 spinner trunkRadius_spinner “Radius: “ type:#worldunits range:[0.0001,100000,trunkRadius] toolTip:”Initial Trunk
Radius (at base)”
38 spinner trunkSides_spinner “Sides: “ type:#integer range:[3,36,trunkSides] toolTip:”Number of Sides”
39 spinner taperingFactorMin_spinner “Taper Min: “ type:#float range:[0.0,1.0,taperingFactorMin] toolTip:”Minimum
Tapering Factor”
40 spinner taperingFactorMax_spinner “Taper Max: “ type:#float range:[0.0,1.0, taperingFactorMax]
toolTip:”Maximum Tapering Factor”
41 )
42
43 group “Branching”
44 (
45 spinner branchingDepth_spinner “Depth: “ type:#integer range:[1,1000,branchingDepth] toolTip:”Total recursion
steps”
46 spinner branchingNumberMin_spinner “Min: “ type:#integer range:[0,100000,branchingNumberMin]
toolTip:”Minimum number to branch out at each step”
47 spinner branchingNumberMax_spinner “Max: “ type:#integer range:[0,100000,branchingNumberMax]
toolTip:”Maximum number to branch out at each step”
48 )
49
50 group “Offset/Translation”
51 (
52 spinner offsetFactorMin_spinner “Min: “ type:#float range:[0.0,100000,heightFactorMin] toolTip:”Minimum
distance offset factor to slide child along parent”
53 spinner offsetFactorMax_spinner “Max: “ type:#float range:[0.0,100000,heightFactorMax] toolTip:”Maximum
distance offset factor to slide child along parent”
54 )
55
56 group “Unfolding/Rotation”
57 (
58 spinner branchingXAngleMin_spinner “X Min: “ type:#float range:[0,360,branchingXAngleMin] toolTip:”Minimum X
rotation angle of each branch”
59 spinner branchingXAngleMax_spinner “X Max: “ type:#float range:[0,360,branchingXAngleMax] toolTip:”Maximum
X rotation angle of each branch”
60 spinner branchingZAngleMin_spinner “Z Min: “ type:#float range:[0,360,branchingZAngleMin] toolTip:”Minimum
Recursive branching/CONTINUED

additional Z rotation angle offset”


61 spinner branchingZAngleMax_spinner “Z Max: “ type:#float range:[0,360,branchingZAngleMax] toolTip:”Maximum
additional Z rotation angle offset”
62 )
63
64 group “Height/Scale”
65 (
66 spinner heightFactorMin_spinner “Scale Min: “ type:#float range:[0.0,100000,heightFactorMin] toolTip:”Minimum
scale factor of child to parent”
67 spinner heightFactorMax_spinner “Scale Max: “ type:#float range:[0.0,100000,heightFactorMax] toolTip:”Maximum
scale factor of child to parent”
68 )
69
70 button generate_button “Generate” enabled:true
71
72 fn branch parent depth =
73 (
74 if (depth < branchingDepth) then
75 (
76 numberOfBranches = (random branchingNumberMin branchingNumberMax)
77 for i = 1 to numberofBranches do
78 (
79 myBranch = copy parent
80 myBranch.parent = parent
81 myBranch.height = (parent.height)*(random heightFactorMin heightFactorMax)
82 myBranch.radius1 = parent.radius2
83 myBranch.radius2 = myBranch.radius1*(random taperingFactorMin taperingFactorMax)
84 in coordsys parent move myBranch [0,0,parent.height]
85 myRot = eulerAngles (random branchingXAngleMin branchingXAngleMax) 0 0
86 in coordsys parent rotate myBranch myRot
87 myRot = eulerAngles 0 0 (((360/numberOfBranches)*i) + (random branchingZAngleMin
branchingZAngleMax))
88 in coordsys parent rotate myBranch myRot
89 in coordsys parent move myBranch [0,0, ((random offSetFactorMin offSetFactorMax)*-parent.height)]
90 myBranch.wirecolor = (color (255 - (255/branchingDepth*depth)) 0 0)
91 append branchesArray myBranch
92 branch myBranch (depth + 1)
93 )
94 )
95 )
96
Branching 161

97 fn deleteTree anArray=
98 (
99 for i = 1 to branchesArray.count by 1 do
100 (
101 if((isDeleted branchesArray[i]) == false) then
102 (
103 delete branchesArray[i]
104 )
105 )
106 branchesArray.count = 0
107 )
108
109 on generate_button pressed do
110 (
111 deleteTree branchingArray
112 rootTree = cone()
113 rootTree.height = trunkHeight
114 rootTree.radius1 = trunkRadius
115 rootTree.radius2 = rootTree.radius1*(random taperingFactorMin taperingFactorMax)
116 rootTree.sides = trunkSides
117 rootTree.heightsegs = 1
118 rootTree.wirecolor = (color 255 0 0)
119 append branchesArray rootTree
120 branch rootTree 1
121 )
122
123 on trunkHeight_spinner changed amt do
124 (
125 trunkHeight = amt
126 )
127
128 on trunkRadius_spinner changed amt do
129 (
130 trunkRadius = amt
131 )
132
133 on trunkSides_spinner changed amt do
134 (
135 trunkSides = amt
136 )
137
138 on taperingFactorMin_spinner changed amt do
139 (
Recursive branching/CONTINUED

140 taperingFactorMin = amt


141 )
142
143 on taperingFactorMax_spinner changed amt do
144 (
145 taperingFactorMax = amt
146 )
147
148 on branchingDepth_spinner changed amt do
149 (
150 branchingDepth = amt
151 )
152
153 on branchingNumberMin_spinner changed amt do
154 (
155 branchingNumberMin = amt
156 )
157
158 on branchingNumberMax_spinner changed amt do
159 (
160 branchingNumberMax = amt
161 )
162
163 on offsetFactorMin_spinner changed amt do
164 (
165 offsetFactorMin = amt
166 )
167
168 on offsetFactorMax_spinner changed amt do
169 (
170 offsetFactorMax = amt
171 )
172
173 on branchingXAngleMin_spinner changed amt do
174 (
175 branchingXAngleMin = amt
176 )
177
178 on branchingXAngleMax_spinner changed amt do
179 (
180 branchingXAngleMax = amt
Branching 163

181 )
182
183 on branchingZAngleMin_spinner changed amt do
184 (
185 branchingZAngleMin = amt
186 )
187
188 on branchingZAngleMax_spinner changed amt do
189 (
190 branchingZAngleMax = amt
191 )
192
193 on heightFactorMin_spinner changed amt do
194 (
195 heightFactorMin = amt
196 )
197
198 on heightFactorMax_spinner changed amt do
199 (
200 heightFactorMax = amt
201 )
202 )

Save your script and then choose Tools Evaluate All to run the script. You
will find the script utility under Utilities (hammer icon). Click on the MAXScript
button and then choose Branching from the Utilities pull down menu. Select the
desired parameters and then press the Generate button to view the result (fig.
99). Increasing the depth parameter creates a more detailed result, but also takes
an exponentially longer time to complete (fig. 100). As mentioned earlier, forcing
the minimum and maximum parameter ranges to be equal and using 90-degree
angles creates a more orthogonal result. In contrast, allowing the script to choose a
random value from a range of values creates a more organic-looking result (fig. 101).

Type a Keyword or phrase


3DS Edit Tools Group Views Create Modifiers Animation Graph Editors Rendering Lighting Analysis Customize MAXScript Help
All View Create Selection Se

Graphite Modeling Tools Freeform Selection Object Paint


Polygon Modeling

Utilities
Branching

Close

Branching
Branch Shape
Height: 200.0mm
Radius: 4.0mm
Sides: 12
Taper Min: 0.4
Taper Max: 0.6

Branching
Depth: 5
Min: 4
Max: 8

Offset/Translation
Min: 0.0
Max: 0.5

Unfolding/Rotation
X Min: 10.0
X Max: 15.0
Z Min: 2.0
Z Max: 6.0

Height/Scale
Scale Min: 0.2
Scale Max: 0.8

0 / 100 Generate

0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 Close

actionMan.executeAction 0 “55’ None Selected X: Y: Z: Grid = 10.0mm Auto Key Selected

Click or click–and–drag to select objects Add Time Tag Set Key Key Filters... 0

fig. 99 Branching utility script.


rECurSiVE braNCHiNg/CoNtiNuEd

fig. 100 Recursive branching with depths 2, 3, 4, 5 and 6.


branching 165

fig. 101 Orthogonal and organic branching by varying the values of parameters.

Let’s take a closer look at the script. here, we will not look at how to create the
user interface and respond to user events, since this information is given in prior
tutorials. instead, we will concentrate on the actual recursive branching algorithm.
For more information on recursion, please consult the prior section on recursion.

72 fn branch parent depth =


73 (
74 if (depth < branchingdepth) then
75 (

in this section, we define a recursive function called branch that accepts two arguments:
a parent branch and the current depth level of the branching. We use the user-
specified branchingdepth number as a maximum value beyond which this function
will not execute its steps. this prevents the algorithm from infinite recursion.

76 numberofbranches = (random branchingNumbermin branchingNumbermax)

We define a variable called numberofbranches, which is a random number within


the range specified by the user. this variable will determine how many children
branches will sprout from the parent branch for this particular branching step.

77 for i = 1 to numberofbranches do
78 (
Recursive branching/CONTINUED

Next, we start a for loop, which runs from 1 up to the generated number of branches,
in order to create each branch in turn.

79 myBranch = copy parent


80 myBranch.parent = parent
81 myBranch.height = (parent.height)*(random heightFactorMin heightFactorMax)
82 myBranch.radius1 = parent.radius2
83 myBranch.radius2 = myBranch.radius1*(random taperingFactorMin taperingFactorMax)

We then start by creating a copy of the parent and setting it as the parent of this new
branch. This will allow the user to move branches by dragging the root branch. The
height (length) of the branch is set as a fraction of the height (length) of its parent
based on a user-specified number or range. Since the branch is made out of a cone
with a base radius and a top radius (radius1 and radius2), we set the base radius
of the child to be the same as the top radius of the parent. This ensures a smooth
transition at the junction between branches. We then set the top radius of the child
to be a fraction of its bottom radius based on a user-specified number or range.

84 in coordsys parent move myBranch [0,0,parent.height]

The 3ds Max built-in term in coordsys <node> allows us to move the new branch using
the coordinate system of its parent rather than the world’s coordinate system. This
is very important to the overall positioning and rotation of the new branches, as they
need to be offset from their parent’s coordinate system rather than that of the world.
In the statement above, we simply slide the new branch so that its base matches the
tip of its parent branch (i.e. we move it by exactly the height (length) of its parent).

85 myRot = eulerAngles (random branchingXAngleMin branchingXAngleMax) 0 0


86 in coordsys parent rotate myBranch myRot

The next step is to rotate the branch. We achieve this by first creating a
rotation object for the X-axis and applying that rotation to the new branch.

87 myRot = eulerAngles 0 0 (((360/numberOfBranches)*i) + (random branchingZAngleMin


branchingZAngleMax))
88 in coordsys parent rotate myBranch myRot

We repeat the process to create a second, Z-rotation. However, for the Z-rotation,
we divide 360 by the desired number of branches to calculate the angle increment
for each branch and we multiply that value by the current index of the iteration.
For example, if we are to generate four branches, then we divide 360 by 4 to yield
90. Based on the formula above, the first branch will be rotated 90 degrees, the
second branch will be rotated 180 degrees, the third will be rotated 270 and the
fourth will be rotated 360 degrees. In addition to this rotation, the script allows
for an optional random addition to the Z-rotation angle. If set, this will ensure
that the branches are not regularly distributed around the parent branch.

89 in coordsys parent move myBranch [0,0, ((random offSetFactorMin offSetFactorMax)*-parent.height)]


branching 167

fig. 102 Branching with an offset.

if the user has specified an offset factor, we slide the branch by that offset (or
a random number from a range) down along its parent branch. this parameter
yields a more organic and randomized branching of the model (fig. 102).

90 mybranch.wirecolor = (color (255 - (255/branchingdepth*depth)) 0 0)

in this purely cosmetic step, we assign a colour to the


branch based on its current branching depth.

91 append branchesarray mybranch

next, we append the current branch to the array of branches. We keep track
of all the created branches by storing them in this array, so that we can
delete them once the user decides to vary the parameters and generate
a new tree. it is important to note that if you wish to keep the generated
tree, you must make a copy of it before generating a new one.

92 branch mybranch (depth + 1)

in this last step, the function calls itself, but this time with the parent argument
specified to be the current branch and the depth incremented by 1. the process then
starts again unless the depth has reached the user-specified maximum value.
the whole process starts when the user presses the generate button.
Please consult the callback function on generate_button pressed to
see how the root tree trunk is created and the branching processes
are started. the code is simple enough to be self-explanatory.
168 Parametric patterns

Case study PS_Canopy


Designer su11 architecture+design
Partners in Charge Ferda Kolatan, Erich Schoenenberger
Design Team Richard Baxley, Hart Marlow
Design and Construction 2009

Left
Side view rendering.

Opposite
Close-up of petals with varying apertures.

su11 architecture+design is a New York-based process to building, su11 employ traditional


architecture firm. Their design investigations architectural concepts, including geometric
draw inspiration from an organic understanding principles, structural constraints and functional
of natural systems. One of their goals is to requirements, but they vary (activate or deactivate)
break down what they see as the ‘categorical localized relationships within those concepts in
barrier’ of traditional building components. order to produce a multiplicity of novel designs.
In order to do this, they employ digital and At the same time, like a body part, their designs
parametric methodologies to produce what must maintain an overall topological coherence.
they call ‘pluripotent structures’: adaptive The firm’s design sensibility is exemplified
formal and structural organizations that can in the PS_Canopy conceptual project, which was
yield multiple possibilities while maintaining exhibited at the 2009 SIGGRAPH Generative
an overall cohesive consistency. Fabrication Conference in New Orleans,
The work of biologist S.B. Carroll provides Louisiana, USA. PS_Canopy employed the
the theoretical framework for the firm’s design metaphor of a flower, assigning utilitarian
explorations. According to Carroll, innovation in aspects such as interior height, shading and
body parts does not depend on novel genes but seating to different aspects of this biomimetic
rather on the ‘modification of existing structures ‘flower’, which was then manipulated through
and on teaching old genes how to learn new parametric and modelling techniques to produce
tricks’.1 Innovation, Carroll asserts, is achieved multiple variations of the proposed canopy.
by switching so-called ‘tool-kit genes’ on and For the design of the canopy, the firm used
off at different times and places throughout the Bentley’s Generative Components software to
course of development. In order to adapt this create a randomized point-branching, parametric
170 Parametric patterns

Above Below
Development of the branching algorithm. Parametric variation of petal aperture.
Branching 171

Top Above
Study of various conglomeration patterns. Second study of various conglomeration patterns.
172 Parametric patterns

script that is akin to a type of fractal called of this process was a geometric arrangement
L-Systems.2 This script allowed the firm to create made up of points, lines and surfaces. In order
a master model in which scaling and clustering to give this underlying structure its final 3D
could be parametrically controlled. The initial form and iconography, the firm used traditional
network created by this script was then put digital meshing techniques that were inspired
through a process of triangulation, resulting in by nineteenth-century flower engravings.
clusters of triangular cells that function as the su11 continue to work with these ideas as
basic geometric ingredient of the final canopy. they explore how elements can populate
Each cell was then populated with individual complex surface geometries, including façades.
canopy pieces, which can either close, to provide Developing a parametric system based on
a more continuous surface, or open, to become a branching floral morphology, they state, is
more structural. The designers continued to critical to their design methodology because
work with a floral metaphor through a second it helps them to ‘visualize and conceptualize
parametric model, which mapped stems, petals systems that focus on the transitory
and leaves into the functional elements necessary moments and details in a design project’.
for support, shading and seating. Thus, the
1 Carroll, S.B. (2006). Endless Forms Most
stem constituted a vertical extrusion of a node
Beautiful: The New Science of Evo
and determined the height of the canopy; the Devo. W.W. Norton & Company.
opening or closing of the petals determined 2 Prusinkiewicz, P. and Lindenmayer, A. (1996). The
Algorithmic Beauty of Plants. Springer-Verlag.
shading in different regions; and finally horizontal
extrusions along the stems became leaves, which
could function as seating or tables. The result
Branching 173

Opposite Above Below


3D printed model. Front view showing petals (canopy), stems
(structure) and leaves (seating and tables).
Opposite Below
Close-up view of 3D printed model.
PArT III NEXT STEPS

176 TOWARDS A PROGRAMMING LANGUAGE FOR DESIGN

196 A TAXONOMY OF PARAMETERS

198 AFTERWORD BY BRIAN JOHNSON


176 Next steps

Towards a programming
language for design
Traditionally, programming languages have been written computer-aided design and visualization systems (e.g.
for general-purpose problem solving of almost any AutoCAD, Rhino, Microstation and 3ds Max). While the
type. Languages such as LISP, FORTRAN, BASIC, C, C++, situation may be different by the time you are reading
Objective-C, C# and Python were not specifically written for this book, building information modelling (BIM) software
designers. They were originated by computer scientists, such as Revit is in urgent need of a scripting language
looking to solve computing problems, who found they that is specifically geared to its core functionality (Iron
needed something more readable and logical than Python is an independent effort to provide a scripting
the numeric codes of native machine language and so language for Revit, but is not supported by Autodesk, the
invented these higher-order languages. As we saw in the makers of Revit). I predict that as the areas of BIM and
chapter on algorithmic thinking, these languages share parametric design mature, we will witness the arrival of
many properties. They all represent variables (which can design-specific languages that contain built-in knowledge
be integers, float numbers or strings of characters). They of design elements and processes. In fact, we already have
all allow for logical flow control, using if statements or one language that moves us closer to the idea of a unified
for loops that repeat a block of code instructions as many programming language for design. This language is called
times as desired. In order to solve a domain-specific DesignScript. It was originated by Dr Robert Aish from
problem, however, programmers sometimes write a Autodesk, who had previously originated GC while he was
collection of functions (sometimes called libraries) or, in with Bentley. DesignScript has some similarities with GC,
the case of object-oriented programming, a set of classes, but unlike both GC and Grasshopper it goes beyond the
objects and methods, which represent specific objects and visual association of parameters, with the aim of creating
functionalities. The question then becomes: do we have a a hybrid and universal programming language for design.
language specifically invented for designers? The Processing DesignScript aims to combine the power of GC, Grasshopper
language from MIT, which focuses on programming and Processing into one language that focuses on solving
for visual design, comes close to that specification. design problems. At a practical level, DesignScript starts
While Processing can be used like any other traditional with geometric form-finding operations (fig. 103), and
programming language (and many have done just that), then links those forms to parametric analysis software,
it has gained popularity with designers and visual artists such as Autodesk's Robot for structural analysis and Green
because of its specialized orientation towards graphics Building Studio for energy and thermal analysis (fig.
and the visual arts. There are very few languages that 104). DesignScript is a versatile language that promises to
have been specifically written for designers and architects. streamline the digital workflow of parametric design, so
Some of these, such as AutoLISP, Maya Embedded Language that eventually building performance analysis can directly
(MEL), Rhinoscript, Grasshopper, Generative Components influence geometric form exploration, which can then be
(GC) and MAXScript, are suitable for geometric problems, directly translated into digital fabrication data. As Robert
because they contain built-in functions that create and Aish explains, his team developed DesignScript with the
edit geometric entities, and because they are linked to objective of answering the following question: ‘How can

fig. 103 A generative parametric


geometry created in DesignScript.
Towards a programming language for design 177

fig. 104 Colour-coded 3D


information as a result of linking
DesignScript to Autodesk's Robot
structural analysis software.

the designer explore complex algorithmic geometric forms graph, they are not totally under the control of the
and build the lightest possible model, with the least effort, user; in both GC and Grasshopper these relationships are
which will provide him with the most feedback, earliest partially or completely masked from the user, meaning
in the design process?’ From that mission statement, it is that the concept of associative language is not made
clear that DesignScript is a design-specific language rather explicit. One strength of DesignScript is that it does makes
than a general-purpose one. While the scope of this book associative programming explicit and, at the same time,
does not allow for a full discussion of all the capabilities of combines it with imperative programming. This enables
DesignScript, in the next section we will look more closely the user to consciously choose the appropriate style of
at some of the features that make it a unique example of a programming to solve a particular type of computation
language written specifically for designers. The optimistic design problem. Even more importantly, DesignScript
assumption is that designers will more readily accept a allows associative and imperative programming to
programming language that focuses on design-specific be combined in the form of a hybrid script, which
needs and will use it to create sophisticated parametric can solve more interesting and complex design tasks
models. To that end, we will compare DesignScript to than each type of programing can solve by itself.
MAXScript, in order to clarify the issues surrounding Let’s focus first on imperative programming. The
the introduction of the complexities of algorithmic word imperative comes from the Latin word imperativus,
thinking to designers and to explore areas of similarity which means ‘specially ordered’. Thus, as one can
and difference between the two scripting environments. imagine, imperative programming languages execute
their instructions in a specially ordered manner. Let us
Imperative vs. Associative Programming look at the following piece of imperative pseudo-code:
It is possible to understand programming as having
two distinct traditions. First, there is the established 1 a=1
tradition of imperative programming, as found in such
2 b=2
languages as Python, C#, Java and Processing. Imperative
languages are based on what is called explicit ‘flow 3 c=a+b
control’, and they use special syntax such as the for 4 b=4
loop and if statement. Second, there is the tradition of
5 print c
associative programming found in such systems as GC and
Grasshopper. In these systems, ‘flow control’ is defined
by a graph of dependencies, which shows relationships In the above code, a is assigned the value 1, b the value
between variables – usually how variables are used within 2, and c is computed as the sum of a and b – thus it will
other operations or statements to define other variables. be assigned the value 3. After that step, we change the
Because these relationships are represented by a visual value of b to 4. However, c has already been computed,
178 Next steps

and so the change in the value of b does not affect the generate geometry. Some aspects of the UI are still under
value of c. Thus, when we print out the value of c it will development, specifically those involving interaction and
continue to display the number 3. The code has been the development of customised UIs. For the purposes of
executed in an imperative manner from top to bottom. this book, the important point is that the DesignScript
If, however, we executed this code in DesignScript, language has the concepts and syntax to capture such
the printed value of c would display 5 rather than 3. This interaction, including selection, modification and
happens because c was defined associatively as the sum customized controls. It is therefore not too difficult
of a and b, so a change in the value of these parameters to imagine that, in the near future, these language
necessitates a change in the value of c. This behaviour facilities will be presented to the user in the form of a
is like a spreadsheet computation where one cell’s value more intuitive user interface, enabling a truly fluid and
can be derived from the values found in other cells, interactive parametric design system. What DesignScript
regardless of where the cells are in relation to one another. represents at the current stage is a solid foundation for
Incorporating associative behaviour in a scripting language a universal design-oriented programming language.
requires a fundamental shift in our algorithmic thinking. One of the most powerful aspects of DesignScript is
For example, we can no longer casually store new values collections. You have already learned about the concept
in variables later in our code, as this will affect all other of arrays: a list of values or objects that you can query,
variables that derive their value from these variables. in order to retrieve and/or set its individual members. A
I mentioned earlier that both GC and Grasshopper collection in DesignScript is similar to an array, but it is, in
are essentially associative programming systems, but a way, easier to use. Almost any parameter or variable in
with the associative notation masked by the graph- DesignScript can be either an individual object or value
based user interface (UI). Interestingly, spreadsheet or a collection of objects or values. While in traditional
applications such as Excel are also associative programming imperative programming you have to iterate through
systems, but again this fact is almost completely masked an array to get access to an individual member of the
from the users by the traditional spreadsheet UI. array, in DesignScript this is done for you behind the
Associative scripting in DesignScript has an explicit scenes. Consider the following example: imagine that
purpose, which is to handle the relationships between you wish to define a line that connects two points. In
variables, including variables that represent collections DesignScript, you would create point A, then point B and
(an important concept, which we will examine closely in then define a line L that connects point A to point B. If
a moment). Sometimes it is important to iterate explicitly any of these points move, line L will dutifully move in
through such a collection using for loops and conditional order to continue to connect them together because line
if statements. For these functionalities, the DesignScript L is associatively linked to points A and B. This in itself
language offers the ability to switch to an imperative mode is the beginning of a powerful parametric construct.
of programming using a special [Imperative] keyword. However, there is an even more interesting aspect to
Code within the imperative block is executed sequentially, this associative behaviour when it is combined with
so modifications to a variable later within that block of the notion of a collection. If, later in the code, point A
code would have no effect on the code that preceded it. changes from a single point to a collection of multiple
The initial development of DesignScript has been points, then line L will also automatically change,
focused on the language and the use of the language to from a single line to a collection of multiple lines that

fig. 105 The effect of B B


replacing a single point
with a collection of points.

L L L L L
1 2 3 4

A A A A A
1 2 3 4
Towards a programming language for design 179

connect the single point B to all the points defined by To illustrate the power of focusing on algorithm
the collection A (fig. 105). The developer of the script rather than on syntax, as well as to illustrate the power of
does not have to manually create multiple lines and then associativity, collections and replication in DesignScript, we
re-define the relationships between them and the control will undertake the re-writing of the diagrid and weaving
points. The power of collections and associativity also tutorials in DesignScript. In the first tutorial, the diagrid
extends to functions. For example, if you have written script, we port the code almost as is from MAXScript
a function that computes the distance between a point to DesignScript, with minor syntactical modifications.
A and a point B, and later in the code point A becomes However, the tutorial in DesignScript combines the two
a collection of points, then DesignScript will repeatedly scripts in MAXScript into one universal diagrid class, which
and automatically call this function for each point in the can generate either flat diagrids or doubly-curved diagrids
collection and compute the distance from each of those that are derived from a host NURBS surface. The second
points to point B. Through the concept of replication tutorial, the weaving script, illustrates the ability of the
DesignScript can handle not only two-dimensional but replication and associativity concepts not only to reduce
also three-dimensional collections. Replication guides the coding burden, but also to clarify the code and link
are special additions to the syntax of the language that it more closely to design intent. As has been suggested
accept two or three one-dimensional collections and pair several times in this book, once you have mastered
the members of these collections together to generate algorithmic thinking and designed your algorithm
a one-, two- or three-dimensional collection. In these in a logical and universal manner, you will be able to
cases, DesignScript can either connect the first member of translate its syntax to other scripting environments. The
a collection to the first member of the second collection, necessary elements of an algorithmic approach are the
and so on, or connect each member of the first collection clarification of design thinking, the establishment of the
to every member of the second collection. These concepts proper parametric associations and ensuring the precise
may be difficult to understand at first, but once you see expression in the appropriate language. This method of
a few visual examples of how they are implemented, working enables efficient and creative exploration of the
their power and simplicity become apparent (fig. 106). design space, regardless of the details of implementation.

1 // Import the Geometry library that allows us to fig. 106 The effect of
using replication guides
2 // create and display geometries to create 3D replication.
3
4 import("ProtoGeometry.dll");
5
// Import the Geometry library that allows us to
6 // Generate three collections each with 10
// create and display geometries
7 // coordinates wth a range 0 to 9
import("ProtoGeometry.dll");
8 // The default interval of the range is 1
9
// Generate three collections each with 10
10 //x_coords = 0..9;
coordinates wth a range 0 to 9
// The default interval
11 y_coords = 0..9; of the range is 1

12 x_coords
z_coords= =0..9;
0..9;
13 y_coords = 0..9;
z_coords = 0..9;
14 // Use replication guides to assign the x values
15 // to the first dimension, y values to the second
// Use replication guides to assign the x values
16 ////todimension and z values
the first dimension, to the
y values third
to the dimension.
second
// dimension, and z values to the third dimension.
17 ////The
Theresult
result
is ais3D
a matrix
3D matrix of points.
of points.
18
p = Point.ByCoordinates(x_coords<1>, y_coords<2>, z_coords<3>);
19 p = Point.ByCoordinates(x_coords<1>, y_coords<2>, z_
coords<3>);
Tutorial Diagrid

In rewriting the diagrid example for DesignScript, we will understand the following tutorial and compare it to the two
combine the two MAXScript tutorials (the simple diagrid mesh MAXScript tutorials on pages 84 and 93. Much of the code
on a flat surface and the curved, NURBS-based diagrid mesh) you will see below should be already familiar to you: because
into one integrated diagrid class that can generate both types the basic algorithm remains constant, code can be copied
on demand. Although this would be feasible in MAXScript and pasted from MAXScript before minor modifications to
through custom coding, because MAXScript does not explicitly syntax are made. Please note that the diagrid class in this
implement the concept of a class, it would not be easy to new tutorial does not correctly handle closed surfaces, as
do. However, when we shift to DesignScript, re-encoding the the MAXScript one does. Once you have familiarized yourself
basic algorithm from MAXScript as an encapsulated class with DesignScript syntax, a good exercise would be to apply
of diagrid objects makes our algorithmic thinking even more what you learned from the MAXScript tutorial and expand
precise. This shift from a basic set of functions to an object- the capabilities of the diagrid class in this tutorial to derive a
oriented mode of working will become clearer as you study and diagrid from closed surfaces, such as cylinders and spheres.

We will assume that you have downloaded and installed AutoCAD and
DesignScript on your computer. Launch AutoCAD and DesignScript
and type the following script into the DesignScript window:

1 import(“ProtoGeometry.dll”);
2
3 class Diagrid
4 {
5 length : double;
6 width : double;
7 rows : int;
8 columns : int;
9 diagrid : SubDivisionMesh;
10 folded : double;
11
12 constructor ByLengthWidthRowsColumns(length : double, width : double, rows : int, columns : int, folded : double)
13 {
14 nr : int = rows * 2;
15 nc : int = columns;
16 unitLength = length / nr;
17 unitWidth = width / nc;
18
19 vertices = buildVertices(nr, nc, unitLength, unitWidth, folded);
20 faces = buildFaces(nr, nc);
21 diagrid = SubDivisionMesh.ByVerticesFaceIndices(vertices, faces, 0);
22 }
23
24 constructor BySurfaceRowsColumns(surface : Surface, rows : int, columns : int, folded : double)
25 {
26 nr : int = rows * 2;
27 nc : int = columns;
28
Towards a programming language for design 181

29 vertices = buildSurfaceVertices(surface, nr, nc, folded);


30 faces = buildFaces(nr, nc);
31 diagrid = SubDivisionMesh.ByVerticesFaceIndices(vertices, faces, 0);
32 }
33
34 def buildSurfaceVertices(surface, nr, nc, folded) {
35 vertices = { };
36 oddeven = 0;
37 deduct = 0;
38 offset = 0;
39 vertIndex = 0;
40 voffset = 0;
41 testing = [Imperative]
42 {
43 for(i in 0..nr) {
44 if (oddeven % 2 == 0)
45 { offset = 0.0; deduct = 0;}
46 else
47 { offset = 0.5; deduct = 1;}
48
49 for(j in 0..(nc - deduct)..1) {
50 u = i / nr;
51 v = (j + offset) / nc;
52 cs1 = surface.CoordinateSystemAtParameter(u, v);
53 ptemp = Point.ByCartesianCoordinates(cs1, 0, 0, folded*(j%2));
54 vertices[vertIndex] = ptemp;
55 vertIndex = vertIndex + 1;
56 }
57 oddeven = oddeven + 1;
58 }
59 }
60 return = vertices;
61 }
62
63 def buildVertices(nr, nc, unitLength, unitWidth, folded) {
64 vertices = { };
65 testing = [Imperative]
66 {
67 vertIndex = 0;
68 deduct = 0;
69 hoffset = 0.0;
70 vx = 0.0;
71 vy = 0.0;
Diagrid/CONTINUED

72 for(i in 0..nr) {
73 if ((i % 2) == 0)
74 { hoffset = 0.0; deduct = 0; voffset = 2; }
75 else
76 { hoffset = 0.5; deduct = 1; voffset = -2; }
77 for(j in 0..(nc - deduct)) {
78 vx = (j + hoffset) * unitWidth;
79 vy = i * unitLength;
80 vertices[vertIndex] = Point.ByCoordinates(vx, vy, folded *(j%2));
81 vertIndex = vertIndex + 1;
82 }
83 }
84 }
85 return = vertices;
86 }
87
88 def buildFaces(nr, nc) {
89 faces = { };
90 testing = [Imperative]
91 {
92 v1 : int = 0;
93 v2 : int = 0;
94 v3 : int = 0;
95 i = 0;
96
97 // Create left and right triangular edges.
98 faceIndex = 0;
99 for(i in 1..nr..2) {
100 v1 = (i - 1) * (nc + 1) - ((i - 1) / 2) + 1;
101 v2 = (i - 1) * (nc + 1) - ((i - 1) / 2) + (nc + 1) + 1;
102 v3 = (i + 1) * (nc + 1) - ((i + 1) / 2) + 1;
103 faces[faceIndex] = { (v1 - 1), (v2 - 1), (v3 - 1) };
104 faceIndex = faceIndex + 1;
105 v1 = (i + 1) * (nc + 1) - ((i + 1) / 2) + nc + 1;
106 v2 = (i - 1) * (nc + 1) - ((i - 1) / 2) + nc + (nc + 1);
107 v3 = (i - 1) * (nc + 1) - ((i - 1) / 2) + nc + 1;
108 faces[faceIndex] = { (v3 - 1), (v2 - 1), (v1 - 1) };
109 faceIndex = faceIndex + 1;
110 }
111
112 // Create first set of triangles.
Towards a programming language for design 183

113 for(i in 1..nr..2) {


114 for(j in 1..nc..1) {
115 v1 = (i - 1) * (nc + 1) - ((i - 1) / 2) + j;
116 v2 = (i - 1) * (nc + 1) - ((i - 1) / 2) + j + 1;
117 v3 = (i - 1) * (nc + 1) - ((i - 1) / 2) + j + (nc + 1);
118 faces[faceIndex] = { (v1 - 1), (v2 - 1), (v3 - 1) };
119 faceIndex = faceIndex + 1;
120
121 if (j < nc)
122 {
123 v1 = (i - 1) * (nc + 1) - ((i - 1) / 2) + j + (nc + 1);
124 v2 = (i - 1) * (nc + 1) - ((i - 1) / 2) + j + 1;
125 v3 = (i - 1) * (nc + 1) - ((i - 1) / 2) + j + (nc + 2);
126 faces[faceIndex] = { (v1 - 1), (v2 - 1), (v3 - 1) };
127 faceIndex = faceIndex + 1;
128 }
129 }
130 }
131
132 // Create second set of triangles.
133 for(i in 3..nr + 1..2) {
134 for(j in 1..nc..1) {
135 v1 = (i - 1) * (nc + 1) - ((i - 1) / 2) + j + 1;
136 v2 = (i - 1) * (nc + 1) - ((i - 1) / 2) + j;
137 v3 = (i - 3) * (nc + 1) - ((i - 3) / 2) + j + (nc + 1);
138 faces[faceIndex] = { (v1 - 1), (v2 - 1), (v3 - 1) };
139 faceIndex = faceIndex + 1;
140 if (j < nc)
141 {
142 v1 = (i - 3) * (nc + 1) - ((i - 3) / 2) + j + (nc + 1);
143 v2 = (i - 3) * (nc + 1) - ((i - 3) / 2) + j + 1 + (nc + 1);
144 v3 = (i - 1) * (nc + 1) - ((i - 1) / 2) + j + 1;
145 faces[faceIndex] = { (v1 - 1), (v2 - 1), (v3 - 1) };
146 faceIndex = faceIndex + 1;
147 }
148 }
149 }
150 }
151 return = faces;
152 }
153 }
154
155 // Create a flat diagrid.
Diagrid/CONTINUED

156 width1 = 30;


157 length1 = 30;
158 u1 = 10;
159 v1 = 10;
160 folded1 = 0;
161 flatGrid = Diagrid.ByLengthWidthRowsColumns(width1, length1, u1, v1, folded1);
162
163 // Create a diagrid derived from a host surface.
164 // Create points.
165 p1 = Point.ByCoordinates(40, 0, 0);
166 p2 = Point.ByCoordinates(70, 5, 10);
167 p3 = Point.ByCoordinates(35, 10, 20);
168 p4 = Point.ByCoordinates(60, 10, 0);
169 p5 = Point.ByCoordinates(40, 30, 0);
170 p6 = Point.ByCoordinates(70, 25, 10);
171 // Create lines that connect the points.
172 l1 = Line.ByStartPointEndPoint(p1, p2);
173 l2 = Line.ByStartPointEndPoint(p3, p4);
174 l3 = Line.ByStartPointEndPoint(p5, p6);
175 // loft between cross section lines to create a surface.
176 hostSurface = Surface.LoftFromCrossSections({ l1, l2, l3 });
177
178 //Hide the points, lines and host surface.
179 p1.Visible = false;
180 p2.Visible = false;
181 p3.Visible = false;
182 p4.Visible = false;
183 p5.Visible = false;
184 p6.Visible = false;
185 l1.Visible = false;
186 l2.Visible = false;
187 l3.Visible = false;
188 hostSurface.Visible = false;
189
190 // Create a diagrid on the host surface.
191 u2 = 8;
192 v2 = 10;
193 folded2 = 0;
194 surfaceGrid = Diagrid.BySurfaceRowsColumns(hostSurface, u2, v2, folded2);
Towards a programming language for design 185

Save your script and then press the Play button at the top of the DesignScript
window in order to run the script. The script will then generate two diagrid
meshes: a flat one and a doubly-curved one. You may need to zoom in on the
extents of the resulting geometry in AutoCAD and rotate the view in order to
see it in 3D. Once done, you should see the two resulting geometries (fig. 107).

Drafting & Annotation Type a Keyword or phrase


Home Insert Annotate Layout Parametric View Manage Output Plug–ins Online Express Tools DesignScript

Line Polyline Circle Arc


Move
Copy
Rotate
Mirror
Trim
Fillet Unsaved Layer State
A
Text
Linear
Leader
Insert
Create
Edit
ByLayer
ByLayer
Group Measure Paste
Stretch Scale Array Table Edit Attributes ByLayer
Draw Modify Layers Annotation Block Properties Groups Utilities Clipboard

DesignScript Editor
File Edit Run Set Help

DiagridTestClass03.ds

Build: 0 error(s), 0 warning(s)


Time elapsed: 1239 ms

Output Watch Errors


Typ e a comm and
Line: 1 Col: 1
Model Layout1 Layout2
227638, 95.1193 , 0.0000 MODEL 1:1

fig. 107 The DesignScript environment within AutoCAD showing the diagrid
geometries.

Let’s take a closer look at the script:

1 import(“ProtoGeometry.dll”);

The first step in the script is to import a dynamically linked library (dll) called
ProtoGeometry.dll. This pre-packaged library includes the classes and functions
needed to create and analyze the built-in geometrical entities in DesignScript.

3 class Diagrid
4 {
5 length : double;
6 width : double;
7 rows : int;
8 columns : int;
9 diagrid : SubDivisionMesh;
10 folded : double;
Diagrid/CONTINUED

Next, we create our own new customized class of geometry that we call Diagrid. As
stated earlier, a class in object-oriented programming software encapsulates attributes
(parameters) and methods (functions) in one structure, so that you can logically ask it to
do things such as to create copies or instances of itself, conduct operations on itself and
give you information about its own state or parameters. In this case, the diagrid class
has certain basic parameters, many of which should be familiar from the MAXScript
tutorials. (Keep in mind that, in this case, the diagrid class creates both rectangular
diagrids as well as ones that are derived from a host NURBS surface, and some of the
parameters are particular to one type or the other.) For a flat diagrid, the class stores
its own length and width. For both types of diagrids, the class stores the number of
rows and the number of columns in the grid, as well as a pointer to the actual created
diagrid object. The class also stores a new parameter, called folded, which is a numeric
parameter with a value between 0 and 1; a value of 0 signifies a flat diagrid, while larger
values signify a folded diagrid that resembles a piece of origami (fig. 108). (This was
not implemented in the MAXScript tutorials, and a useful exercise might be to go back
to that tutorial and add it in, after you have learned how it works in DesignScript.)

fig. 108 Flat and folded diagrid meshes generated by the same script.
Towards a programming language for design 187

12 constructor ByLengthWidthRowsColumns(length : double, width : double, rows : int, columns : int, folded : double)
13 {
14 nr : int = rows * 2;
15 nc : int = columns;
16 unitLength = length / nr;
17 unitWidth = width / nc;
18
19 vertices = buildVertices(nr, nc, unitLength, unitWidth, folded);
20 faces = buildFaces(nr, nc);
21 diagrid = SubDivisionMesh.ByVerticesFaceIndices(vertices, faces, 0);
22 }

In order to create the actual geometry, a class defines one or more special constructor
methods. We call the first constructor method ByLengthWidthRowsColumns. As
the name implies, this method can construct a rectangular diagrid, if you provide it
with the desired length, width, number of rows and columns, and degree of folding.
This method calculates the unit distances for width and length, and then calls one
function to create a set of vertices and another function to create triangular faces
from these vertices. These functions are the same as the ones implemented in
MAXScript so we will not cover them in this tutorial. The final step in this method is
to construct the diagrid by constructing an internal DesignScript geometry called
SubDivisionMesh. We use one of its constructor methods, called ByVerticesFaceIndices,
and we pass it the array of vertices and faces that we have created.

24 constructor BySurfaceRowsColumns(surface : Surface, rows : int, columns : int, folded : double)


25 {
26 nr : int = rows * 2;
27 nc : int = columns;
28
29 vertices = buildSurfaceVertices(surface, nr, nc, folded);
30 faces = buildFaces(nr, nc);
31 diagrid = SubDivisionMesh.ByVerticesFaceIndices(vertices, faces, 0);
32 }

The second constructor method builds a diagrid that is derived from a host surface. To
maintain the consistency of the DesignScript naming convention, we call this constructor
method BySurfaceRowsColumns. For the construction to be successful, the method needs
to be given a host surface as well as the desired number of rows and columns for the
diagrid. In a manner similar to that of the previous method, we build an array of vertices,
but this time we use the function buildSurfaceVertices, rather than the simpler buildVertices
function. It is important to note here that the buildVertices function is a direct translation
from the first MAXScript tutorial (simple diagrid mesh) while the buildSurfaceVertices is a
direct translation from the second tutorial (deriving a diagrid from a NURBS surface). A flat
and a NURBS-based diagrid differ in their geometric coordinates but not in the topology
connecting those coordinates. Thus, both constructor methods call the same function,
buildFaces, in order to create the triangular faces that connect the vertices. Similarly, both
constructor methods call the built-in DesignScript method to create a subdivision mesh.
Diagrid/CONTINUED

34 def buildSurfaceVertices(surface, nr, nc, folded) {


63 def buildVertices(nr, nc, unitLength, unitWidth, folded) {
88 def buildFaces(nr, nc) {

The above three functions are the ones that have been directly imported from
MAXScript and thus differ only in minor syntactical ways. The code in this
tutorial has comments to help you better understand it, and you might also want
to go back to the previous MAXScript tutorials to compare them directly.

52 cs1 = surface.CoordinateSystemAtParameter(u, v);


53 ptemp = Point.ByCartesianCoordinates(cs1, 0, 0, folded*(j%2));

The above two lines of code are useful to examine in more detail; they achieve similar
results to the MAXScript code but differ slightly in how those results are achieved.
In addition, the code indicates how and where we added the folding parameter
discussed above. In order to find the Cartesian coordinates of a point on a surface,
we create a coordinate system, cs1, on that surface at the parametric points u and
v. We then create another point, which is placed at the origin of cs1 (giving us the x
and y coordinates of that point on the surface). It is particularly useful to note that a
coordinate system at a parametric point on a surface is always oriented such that its
Z-axis is normal (perpendicular) to the surface at that point. Thus, to find a point that
is offset from that surface along that Z-axis, we simply add a value to the z coordinate
of that point. The use of (j%2 ) as a multiplier simply means that if j is even, then the
modulus (j%2 ) is 0 and thus the derived point will be on the surface. If j is odd, then
(j%2 ) will be 1 and thus we offset the point by the amount specified by the parameter
folded. This allows us to offset every other row to achieve the folded effect.

155 // Create a flat diagrid.


156 width1 = 30;
157 length1 = 30;
158 u1 = 10;
159 v1 = 10;
160 folded1 = 0;
161 flatGrid = Diagrid.ByLengthWidthRowsColumns(width1, length1, u1, v1, folded1);

The above code, towards the end of the script, sets the desired parameters
for the flat diagrid and then creates a new instance of the Diagrid class
using its ByLengthWidthRowsColumns constructor method.

190 // Create a diagrid on the host surface.


191 u2 = 8;
192 v2 = 10;
193 folded2 = 0;
194 surfaceGrid = Diagrid.BySurfaceRowsColumns(hostSurface, u2, v2, folded2);
Towards a programming language for design 189

After creating a sample host surface and hiding it (since we are only interested in the
resulting diagrid), the above code sets the desired parameters for the second grid and
then creates a new instance of the Diagrid class, using its BySurfaceRowsColumns
constructor method. Since the resulting geometry is created in AutoCAD, it
can be easily exported to 3ds Max or other rendering software (fig. 109).
In summary, the diagrid tutorial, as implemented in DesignScript, illustrates two main
concepts: the generalization of algorithms and the advantages of object-oriented
thinking. Having understood the geometric and topological properties of diagrids, it
was relatively easy to translate the algorithm from the syntax used by MAXScript to
that used by DesignScript. The translation was relatively easy because we maintained
an imperative mode of programming, so the associative capabilities of DesignScript
did not play a major role in this tutorial. However, we took advantage of DesignScript’s
ability to encapsulate algorithms in an object-oriented manner and we combined
what used to be two separate algorithms into one more universal class of objects
that we can expand in modular ways. The next tutorial translation from MAXScript
to DesignScript – the generation of a woven geometry based on a host surface – will
illustrate how the combination of associative and imperative methods of scripting
can fundamentally change our view of a design problem and more closely relate the
algorithm to our intuitive understanding of its geometric and topological relationships.

fig. 109 A rudimentary folded diagrid pavilion, created in DesignScript and exported to
3ds Max for material mapping and rendering.
Tutorial Weaving

For this tutorial, we will use the experience we gained of some of the powerful capabilities in DesignScript,
from writing the weaving script in MAXScript to rewrite such as replication and associative scripting.
it in DesignScript. In doing so, we will take advantage

Launch AutoCAD and DesignScript and type the following


script into the DesignScript window:

1 import(“ProtoGeometry.dll”);
2 import(“Math.dll”);
3
4 // Create a host surface.
5 // Create points.
6 p1 = Point.ByCoordinates(3, 10, 2);
7 p2 = Point.ByCoordinates(-15, 7, 0.5);
8 p3 = Point.ByCoordinates(5, -3, 5);
9 p4 = Point.ByCoordinates(-5, -6, 2);
10 p5 = Point.ByCoordinates(9, -10, -2);
11 p6 = Point.ByCoordinates(-11, -12, -4);
12
13 // Create lines that join the above points.
14 l1 = Line.ByStartPointEndPoint(p1, p2);
15 l2 = Line.ByStartPointEndPoint(p3, p4);
16 l3 = Line.ByStartPointEndPoint(p5, p6);
17
18 // Create a surface from the above lines.
19 hostSurface = Surface.LoftFromCrossSections({ l1, l2, l3 });
20
21 // Create the weave.
22 // Define the number of threads for each direction.
23 weftThreads = 40;
24 warpThreads = 20;
25
26 // Define the amplitude scaling factor of the height of the warp.
27 amplitude = 0.3;
28
29 // Define the thread radius.
30 threadRadius = 0.25;
31
32 // Define the weft and warp parametric steps (from 0 to 1)
33 // based on the number of threads.
34 weftParam = 0..1..#weftThreads;
35 warpParam = 0..1..#warpThreads;
36
Towards a programming language for design 191

37 // Derive the weft and warp grid of points on the host surface.
38 weftPoints = hostSurface.PointAtParameters(weftParam<2>, warpParam<1>);
39 warpPoints = hostSurface.PointAtParameters(weftParam<1>, warpParam<2>);
40
41 def buildWarp(dummy) {
42 impCode = [Imperative] {
43 xMultFac = -1;
44 yMultFac = -1;
45 cs1 = CoordinateSystem.Identity();
46 for (i in 0..(weft-1)) {
47 if ((i % 2) == 0) {
48 xMultFac = 1;
49 }
50 else {
51 xMultFac = -1;
52 }
53 for (j in 0..(warp-1)) {
54 if ((j % 2) == 0) {
55 yMultFac = 1;
56 }
57 else {
58 yMultFac = -1;
59 }
60 cs1 = hostSurface.CoordinateSystemAtParameters(weftParam[i], warpParam[j]);
61 ptemp = Point.ByCartesianCoordinates(cs1, 0, 0, xMultFac*yMultFac*amplitude);
62 warpPoints[i][j] = ptemp;
63 }
64 }
65 }
66 return = 1;
67 }
68
69 // Build the weave geometry (warp variable and “1” are unused dummy variables).
70 warp = buildWarp(1);
71
72 // Create the weft and warp BSpline curves from points.
73 weftCurves = BSplineCurve.ByPoints(weftPoints);
74 warpCurves = BSplineCurve.ByPoints(warpPoints);
75
76 // Create the weft and warp solid ‘pipes’.
77 baseCircle = Circle.ByCenterPointRadius(Point.ByCoordinates(0, 0, 0), threadRadius);
78 warpSolids = baseCircle.SweepAsSolid(warpCurves);
79 weftSolids = baseCircle.SweepAsSolid(weftCurves);
WEAVING/CONTINUED

80
81 // Hide the points, lines, curves, and host surface.
82 p1.Visible = false;
83 p2.Visible = false;
84 p3.Visible = false;
85 p4.Visible = false;
86 p5.Visible = false;
87 p6.Visible = false;
88 l1.Visible = false;
89 l2.Visible = false;
90 l3.Visible = false;
91 hostSurface.Visible = false;
92 warpPoints.Visible = false;
93 weftPoints.Visible = false;
94 warpCurves.Visible = false;
95 weftCurves.Visible = false;
96 baseCircle.Visible = false;

Save your script and then press the Play button at the top of the DesignScript
window to run the script. You should see a woven surface (fig. 110).

Drafting & Annotation Type a Keyword or phrase Sign In


Home Insert Annotate Layout Parametric View Manage Output Plug–ins Online Express Tools DesignScript

Line Polyline Circle Arc


Move
Copy
Rotate
Mirror
Trim
Fillet Unsaved Layer State
A
Text
Linear
Leader
Insert
Create
Edit
ByLayer
ByLayer
Group Measure Paste
Stretch Scale Array Table Edit Attributes ByLayer
Draw Modify Layers Annotation Block Properties Groups Utilities Clipboard

DesignScript Editor
File Edit Run Set Help

WeavingTest01.ds

Build: 0 error(s), 0 warnings(s)


Time elapsed: 33749 ms

Output Watch Errors


Typ e a comm and
Line: 35 Col: 16
Model Layout1 Layout2
–9.0203, 228355, 0.0000 MODEL 1:1

fig. 110 The DesignScript environment within AutoCAD showing the woven geometry.
Towards a programming language for design 193

The first step is to import two dynamically linked libraries (dll),


which contain functions that allow DesignScript to create and
edit geometry and to conduct mathematical operations.
Since the beta version of DesignScript does not allow the user to select a
pre-existing geometry from the host CAD environment, this script creates
its own host surface on which the woven pattern can be based.

4 // Create a host surface.


5 // Create points.
6 p1 = Point.ByCoordinates(3, 10, 2);
7 p2 = Point.ByCoordinates(-15, 7, 0.5);
8 p3 = Point.ByCoordinates(5, -3, 5);
9 p4 = Point.ByCoordinates(-5, -6, 2);
10 p5 = Point.ByCoordinates(9, -10, -2);
11 p6 = Point.ByCoordinates(-11, -12, -4);
12
13 // Create lines that join the above points.
14 l1 = Line.ByStartPointEndPoint(p1, p2);
15 l2 = Line.ByStartPointEndPoint(p3, p4);
16 l3 = Line.ByStartPointEndPoint(p5, p6);
17
18 // Create a surface from the above lines.
19 hostSurface = Surface.LoftFromCrossSections({ l1, l2, l3 });

The code above creates six points by specifying their Cartesian coordinates, then
creates three lines, each joining one pair of two points. Finally, this section of code
creates a lofted surface based on these three cross-sectional lines (fig. 111).

fig. 111 The process of creating a lofted surface from points and lines.

Next, the script starts the process of creating the weave.

23 weftThreads = 40;
24 warpThreads = 20;

27 amplitude = 0.3;

30 threadRadius = 0.25;
Weaving/CONTINUED

We define the desired input parameters: the number of weft and warp
threads, the amplitude of the weave’s undulation, and the thickness
or radius of the threads themselves. These parameters can then be
presented to the user as sliders or numerical input fields:

34 weftParam = 0..1..#weftThreads;
35 warpParam = 0..1..#warpThreads;

The above code may look like unfamiliar syntax. It is a simple definition of a range
of values. For example, if we specify that x = 0..10..#2 then x will be a collection of
values ranging from 0 to 10 and varying in increments of 2. Thus, x would be equal to
{0, 2, 4, 6, 8, 10}. If you recall, NURBS surfaces are parametric surfaces. A point on
the surface can be located by traversing the u and v parameters of the surface. The
parameters u and v vary from 0 to 1 where (0,0) signifies one corner of the surface
and (1,1) signifies the opposite corner of the surface. In the above code we are doing
something similar by creating the parameters for two collections, one for the weft
and one for the warp, each with a range from 0 to 1, but we are also dividing each
collection into the specified number of threads we want running in that direction.

38 weftPoints = hostSurface.PointAtParameters(weftParam<2>, warpParam<1>);


39 warpPoints = hostSurface.PointAtParameters(weftParam<1>, warpParam<2>);

Next, we derive a grid of points on the surface that are based on the range of the weft
and warp parameters. The above code is a powerful example of both associativity and
replication guides. The function PointAtParameters returns a 3D point on a surface
based on a set of u and v parameters. However, because we pass it a collection of
parameters, the function automatically returns a collection of points. Furthermore,
because we wish to weave the surface in two directions that are perpendicular to
each other (a weft and a warp), we use reversed replication guides (<1> and <2>)
for each direction. Think of these guides as assigning the order of the points: in
one case we order them first in rows and then in columns and in the second case
we order them first in columns and then in rows. Later, when we ask DesignScript
to thread a line through these points, it will respect the ordering of the points and
thread horizontal lines in the first case and vertical lines in the second case. These
two simply-constructed lines of code save us the burden of writing iterative for loops
that would step through the weft and warp parameters in order to derive an ordered
list of points. Code statements such as give me back all the points on the surface
at these parameters are far more intuitive to a designer than a statement such as
for a variable that ranges from 1 to 10, step through each value of this variable and
derive the point at the current value and add it to a collection and repeat the cycle.
The language constructs of DesignScript, while still esoteric to the uninitiated,
bring us closer to a more design-oriented computer programming language.

41 def buildWarp(dummy) {
42 impCode = [Imperative] {

The next step is to move the control points above and below the surface in an alternating
manner (based on odd and even row numbers) in order to create the wave-like
pattern of the weave. For that, we write a function called buildWarp that we will call
later in the code. Unfortunately, given the complexity and the procedural nature of
what we need this function to achieve, the function reverts to traditional imperative
coding very similar to the code written for the tutorial done in MAXScript. Thus, in this
section we will not rehash how it works, but note that in order to instruct DesignScript
to function in an imperative mode, we use the special [Imperative] keyword.
Towards a programming language for design 195

70 warp = buildWarp(1);

The above statement instructs DesignScript to call the buildWarp function that
undulates the points. Since DesignScript is associative, all function calls need to
be stored in a variable (warp) even if it is not needed anywhere else in the code.

73 weftCurves = BSplineCurve.ByPoints(weftPoints);
74 warpCurves = BSplineCurve.ByPoints(warpPoints);

Once the points have been moved, it becomes trivial to derive the undulating
splines. DesignScript has built-in functions to create a BSplineCurve
from a set of points. As mentioned earlier, the points are already
ordered in two directions that are perpendicular to each other. Thus,
there is no need for any nested for loops to iterate through them.

77 baseCircle = Circle.ByCenterPointRadius(Point.ByCoordinates(0, 0, 0), threadRadius);


78 warpSolids = baseCircle.SweepAsSolid(warpCurves);
79 weftSolids = baseCircle.SweepAsSolid(weftCurves);

In order to create solid pipes, we create a base circle with the specified
thread radius parameter and sweep it as a solid using built-in functions.
We pass to this function the curves we created in the prior step.

82 p1.Visible = false;
83 p2.Visible = false;
84 p3.Visible = false;
85 p4.Visible = false;
86 p5.Visible = false;
87 p6.Visible = false;
88 l1.Visible = false;
89 l2.Visible = false;
90 l3.Visible = false;
91 hostSurface.Visible = false;
92 warpPoints.Visible = false;
93 weftPoints.Visible = false;
94 warpCurves.Visible = false;
95 weftCurves.Visible = false;
96 baseCircle.Visible = false;

The last step is optional. It simply hides the geometries we have used to construct
the weave, leaving visible only the final weft and warp solids.
As you would have noticed, compared to the MAXScript code, this code is significantly
pithier and more understandable. The associativity of points, lines, surfaces and
solids, as well as the power of replication guides, allow us to focus more intently
on the design problem at hand. They also allow us to be more explicit about how
various design elements relate to one another. While DesignScript is still in the
very early stages of its development as a fully featured and interactive parametric
system, it illustrates the pressing need to invent a higher-order universal language
of computational design that allows us to shed some of the complexities of computer
science concepts and couple the system more closely with our design intent.
196 Next steps

A taxonomy of parameters
Parametric design is a process based on algorithmic is near to, looking at, is within, is outside of, etc. Most
thinking that enables the expression of parameters modern parametric systems excel at precisely these types
and rules that, together, define, encode and clarify the of parameters. For example, a diagrid pattern is a topology
relationship between design intent and design response. that divides a surface in a consistent manner regardless of
It is only natural that computer-based parametric systems the exact geometry of the parent surface or the resulting
focus mainly on geometry and topology. After all, pattern. This allows us to disassociate topology from
parametric systems are usually attached to, or built on geometry while maintaining the consistency of our
top of, more traditional 3D solids modelling software. design intents. Most of the examples in this book fall
It is a good starting point for anyone interested in under this category. Topological parameters allow us to
implementing a parametric approach to form-finding consider issues of form, composition and fabrication,
in his or her design workflow. Yet, at times, this can and they open the possibility of further analysis as
reduce the whole design process to a series of fantastic, they more precisely define our design intent for how
self-congratulatory mathematical acts of acrobatics. As the parts relate to each other and to the whole.
any other system, a parametric design system is defined
by its input, algorithm, and output. We have matured Representational parameters describe and abstract
in the area of geometric algorithms and can invent as entities outside themselves. Examples include computer
well as physically build very complex geometry. The real representations of walls, windows or columns. Building
challenge in parametric design is not how clever the Information Modelling (BIM) was invented in large part
algorithm is, or how complicated the output is, but in the to address the need to represent ‘real’ objects. In BIM,
selection of the initial input parameters. What parameters a distinction is made between an isolated geometric
exist beyond the geometric one? Very few architects construct such as a cuboid, and a brick wall, which
and software developers have taken on the challenge knows how many bricks it has, its own weight, structural
to classify, let alone invent, systems that can accept strength, cost, etc. Representational parameters allow us to
fundamentally different types of parameters. In order to describe some if not all of the physical properties of what
truly connect parametric design to the everyday activities we are modelling. They also allow us to aggregate that
of designers, they need to understand and represent the information so we can report overall values and quantities.
same issues the designers are working with: geometry and
topology, but also architectural components, materials, the Material parameters build on mathematical, geometric,
environment and people. Below is an attempt to classify topological and representational parameters by adding and
and explain these parameters, in the hope that it will serve connecting several physical attributes: weight, tension,
as the foundation of future research projects with the goal friction, elasticity, structural strength, U-value, reflection,
of inventing more versatile tools to address this glaring refraction, etc. This class of parameter begins to remove
deficiency in the current generation of parametric systems. us from the realm of self-referential geometric games and
into the physical world of materiality. Good examples of
Mathematical parameters are the most basic type of parametric systems that accept and consider topological
parameter that are already understood by 3D modelling parameters are tensile membrane form-finders, biomimetic
software: numbers, logical values and even strings explorations, and particle and physics engines that can
of characters (which are represented internally using encode, almost at a cellular level, the physical properties,
numbers). Many parametric systems, such as spreadsheets collision, velocity, gravity and structural stresses that a
(which are undeniably powerful parametric systems system is undergoing. Future systems for parametric design
in their own right), only need this level of parametric in architecture should encode materiality and physical
input in order to calculate very useful outputs. parameters, as this will allow us to model, predict and
thus parametrically explore the performative aspects of
Geometric parameters are higher-level entities our design proposals before they are actually physically
that are built out of the lower-level mathematical built. Analysis software that precisely models structural
parameters. Examples include points, lines, or thermal properties should more fully integrate the
surfaces and solids. Most current 3D modelling essential material and physical properties in our geometric
software can represent and parametrically modify and representational constructs, such that they fluidly
geometric constructs of various types. react to, propagate and give us feedback on constraints
and interactions within the overall parametric system
Topological parameters describe how two or more in real or near-real time. For example, very few current
entities relate to each other: connected to, above, below, parametric systems can represent the time-based effect
A taxonomy of parameters 197

of prolonged exposure to fire on a structural system or


a particular building material. Physics-based computer
games and bioengineering research, however, have
reached that stage and we would be wise to learn
from their techniques in the field of architecture.

Environmental parameters include the frequently


invisible and fluid forces that surround us. Time, wind,
thermal variation, vistas and views, the movement
of light and shadow, magnetic fields, Wi-Fi and
GPS signals, growth and erosion are all examples of
environmental parameters. Not many of us can easily
imagine the path of a shadow as it travels during the
day or the undulations of a field of sunflowers as they
follow the path of the sun; this is why we find time-
lapse photography so fascinating. Interactive façades
that respond to environmental conditions (usually the
path of the sun) are a good start. However, we need a
deeper understanding of the totality and complexity of
environmental factors so that we can optimize our design
solutions, given complex and competing constraints.

Human parameters form the seventh and most


challenging class of parameters. Architecture’s purpose is,
after all, to shelter humans from the elements. While we
share many physical attributes and needs, we also differ in
profound ways both ergonomically and psychologically. If
we are to create humane architecture and one that creates
truly customizable spaces, we need to be able to model
our clients, their intents and desires, and incorporate that
information as parameters in our design systems. It is truly
shocking that, in many cases, incorporating the human
parameter in our design projects and renderings does not
go beyond the inclusion of a scale model of a person. That fig. 112 Le Corbusier's Le Modulor
is only a start; masterful architects know how to address cast in concrete at the Unité
d'Habitation (1965), Firminy, France.
and resolve multivalent parameters (fig. 112). We truly need
to learn from the field of ergonomics and especially the
advanced systems that office furniture, automobile and are included is part of our irreplaceable skill as designers.
medical equipment manufacturers use to model human Parametric modelling lets you capture that conceptual
beings. A good development in our field is the increasing model and make it explicit. This shifts the conversation.
incorporation of simulated crowd systems. Sadly, The challenge is not one we can shy away from if we aim
while effective at simulated fire egress, the simplifying to be precise about our design intent and, perhaps more
assumptions of such systems, which reduce the complexity importantly, strive to understand the consequences of
of human behaviour to that of a robot, render them our decisions before we actually build them. Parametric
useless to predict common human behaviour such as systems are only one step in that endeavour.
where clusters of people might gather or pause on a sunny
afternoon. As the computational capability of our systems
grows, so will the sophistication of these simulations.

Incorporating all seven classes in a parametric design


system is not only a tall order, but not always advisable
given the design situation. Knowing how to abstract
a situation and build a conceptual model in which
extraneous parameters are excluded but essential ones
198 Next steps

Afterword by Brian Johnson


Congratulations! You have arrived at the beginning! fall on the circle defined by the distance between bolt
Not the beginning of this book, but the beginning holes. The ideal parametric system allows us to explicitly
of your own ownership and mastery of the manifest the physical truths of the mechanism as well
material covered here. There are just a few more as the geometric intentions of the designer (fig. 113).
words to review or consider before you go. Remember that, as some materials cause corrosion
when used together, some computations need
Patterns on the wall special handling as well. A classic in the realm of
In the preceding pages you’ve seen many examples of computational geometry can be found in the ‘inverse’
how the logic of geometry and the magic of creative trigonometry functions (arcSine and arcCosine).
intent can be combined and then embedded through Computing the arcsine of the sine of an angle doesn’t
code and variables into parametric design. These always get you back to where you started. Test
have been presented as a collection of ‘patterns’ – your details and use them in the right context.
paradigms or prototypes, rather than recipes. How Be careful of assumptions. Computers work
should you make the best use of this material? with numbers, but don’t generally understand units.
Pattern languages are not meant to ease design by reducing If you prompt for a dimension, specify the units in
it to a matter of selection and arrangement. These patterns which it should be entered. If your software system
are the ‘concept diagrams’ of code, not a catalogue from supports multiple base units, state up front what
which to pick and choose. They are the material from your assumptions are, or find out how your script can
which to craft new solutions to new problems. Just as enquire and convert appropriately between units.
Christopher Alexander’s patterns are meant to suggest the
Platonic ‘ideal forms’ of good environmental design, the Praxis
patterns presented here illustrate many of the ideal forms As with any craft, the application of code to design
of parametric design. As in Plato’s cave, the particular requires experience, insight and practice, as well as care,
examples we see are always projections, reductions of the judgement and attention to detail. Gain experience
ideal necessitated by the available systems and syntaxes of and confidence by using these patterns. Don’t just
expression, but their repeated emergence in new settings copy the code, work with the code to understand
has demonstrated their persistence. Whether they serve the ‘ideal form’ or combine it with other fragments
your particular circumstance will depend on other issues. and then use that to create your own designs.
Not all code is created equal, even if the results are
Tectonics of code equivalent. Occam’s Razor says you should be suspicious
The patterns are not the end of the story. Tectonics – of messy code, but density and cleverness of expression
the ‘art and science of construction’ – has a place in can be misleading as well, if it masks what’s really going
this discipline too, alongside the patterns. Buildings on. If clear expression isn’t apparent in the result, it
and scripts are both made of parts, put together to may indicate muddied thinking in the intent or a weak
form systems, and the joints are often quite important. understanding of fundamentals. Good code can be elegant!
Thinking about parts and systems and their impact Add comments to your code, to remind yourself
on designs is often challenging for students. Learning what clever or mundane thing your code is doing. Your
to ‘see’ (sometimes literally) the important parts can code won’t have the benefit of the explanations this
be critical. Constraints arising from systems are often book provides to remind you what your script is doing
viewed as negatives by beginner students, but are seen as and why. Use meaningful names for variables wherever
opportunities by more mature designers. Parametric design possible. Reading your own scripts some months after
is one way of learning to think about parts and systems you created them can be a humbling experience.
and the opportunities inherent in their various logics. Watch for repeating units, within a design or across
Consider the design of a mechanism of some sort. multiple designs. These are the signs of an emerging
We know that two points define a line. But does the pattern, an opportunity to leverage your creativity
line represent a rubber band connecting two points and save time, or perhaps a chance to give back to the
in space? Or is it supposed to be a piece of steel with a community of practice into which you are now entering.
bolt in each end? The difference is whether the script
preserves or enforces the constancy of length in the steel,
or allows the points to move as if it’s a rubber band.
If one end of the steel is fixed in place, the other end
must always be the same distance away. That is, it must
Afterword 199

Parametric Designs and Designing


Available direct-manipulation drafting or modelling
programs are efficient editors of geometry, but good
design involves a complex interplay of ideas, relationships
and intent. Geometry is just the most visible product
of the design process. Parametric design tools offer you
the opportunity to express and explore design intent
itself, not just the geometry of a project. These tools
present the opportunity to engage the deep questions
about the influences that shape your individual
designs, and about what it means to design, elevating
design discourse generally. Parametric design, along
with sophisticated building information models and
digitally enhanced construction techniques, will be
a core component of practice in the 21st century.

fig. 113 Glimpse the Future.


Hinting at things to come,
this parameterized, sinusoidal
displacement of points along
one edge of a set of surface
strips was generated by a
Processing script. The resulting
gill-like surface is thickened and
rendered with a backlight.
200

Glossary
Algorithm
A step-by-step procedure for solving a problem. An algorithm CV
usually takes an input, performs a process and creates an output. An abbreviation for Control Vertex. A CV is a point that is used
to compute the geometric shape of a NURBS surface. Think
Argument of a CV as a magnet that pulls on a surface. The location and
In computer programming, a piece of information or a variable weighting assigned to several CVs determine the final curvature
that is passed on to a function as input to that function. of the surface.

Developable Surface
Associative Programming
A surface that can be unfolded without distortion and
This type of programming differs from traditional (imperative)
manufactured from flat sheets. Developable surfaces are useful
programming in that it associates variables with one another,
for easing digital fabrication.
such that a change in one variable automatically triggers an
update in other variables that are associated with it.
Encapsulation
In object-oriented programming, a class of objects that
Boolean Algebra
contains within itself both methods and attributes.
Named after George Boole, Boolean algebra deals with the
Encapsulation allows for a more structured and modular
algebra of only two integers: 0 and 1. These can also be thought
method of computer programming.
of as false and true. These values can be combined in conjunction
(AND), disjunction (OR) and complement (NOT). Using
Fibonacci Series
these Boolean operations, an algorithm can compute logical
A sequence of numbers named after Leonardo de Pisa,
expressions and handle set theory. The term is also used in 3D
a thirteenth-century mathematician known as Fibonacci.
modelling as the operation of union (addition), intersection and
A Fibonacci sequence starts with the numbers 0 and 1 and
subtraction of solids.
then each subsequent number is the addition of the previous
two. Fibonacci series occur in nature (notably, in certain plants,
Bounding Box
in the arrangement of leaves on the stem, known as phyllotaxis)
The smallest cuboid in which all the points of a geometrical
and are used by architects as a system for achieving
object lie. It is useful for knowing the maximum and minimum
elegant proportions.
extents of an object.
Flowchart
Building Information Modelling (BIM) In computer programming, a diagram that represents an
A computer-aided method of conducting design, construction, algorithm. Computer programmers use flowcharts to test the
facility management, renovation and even demolition. It relies logic and robustness of their algorithms and to explain them
on an integrated information model of the project that encodes to others.
not just the geometry of the project, but other aspects of it, such
as spatial relationships, building components, manufacturers’ Genetic Algorithm
data, etc. In computer programming, a genetic algorithm (GA) uses the
metaphor of natural evolution to search for the fittest solution to
CNC a problem. A GA represents the input data as a population that
An abbreviation for Computer Numerical Control. A CNC can breed a new generation. Genetic crossover and mutation is
machine interprets geometric data as a series of machine cyclically used to improve the fitness of the next generation until
operations that act on raw material. CNC machines such as the population reaches an overall satisfactory solution.
routers and milling machines are used for digital fabrication.
Global Variable
Coordinate System A variable in an algorithm that can be accessed and modified by
In geometry, a coordinate system uses one or more numbers all its functions.
to determine the location of a point. A 3D Cartesian coordinate
system, named after René Descartes, uses a set of three Golden Rectangle
intersecting axes (x, y, z) that are usually perpendicular to A rectangle whose sides form a golden ratio. Golden rectangles
one another. Their point of intersection is called the origin. A and spirals are closely related to Fibonacci numbers. A distinctive
Cartesian coordinate system uses coordinates along the x, y and feature of this shape is that it is fractal. In particular, when
z axes to determine the location of points in 3D space. a square shape is removed from the original rectangle, the
remaining rectangle also forms a golden rectangle.
Cross Product
In geometry, an operation performed on two vectors that results GUI
in a third vector that is perpendicular to the plane formed by the An abbreviation for Graphical User Interface. Basically, this is the
first two vectors. A cross product is useful when trying to find the set of all the visual elements (windows, buttons, menu items,
direction of a location on a surface. sliders, etc.) that allow a user to interact with a computer.
Glossary 201

Imperative Programming Script


A style of computer programming in which statements or Usually a short algorithm written to solve a problem. A script
instructions are made that change the current state. Imperative is usually interpreted and executed immediately rather than
programming is usually contrasted with declarative or associative compiled and linked.
programming, which declares the relationships between
variables, but does not specify the sequences of how a state Spinner
change should take place. In 3ds Max, a user interface element that allows a user to either
type in a value or use up and down arrows to change the value.
Modifier
In 3ds Max and similar 3D modelling software, an encapsulated Sweep Profile
method that modifies a base object. A bend modifier, for In 3ds Max and similar 3D modelling software, a 2D shape that
example, bends an object. Several modifiers can be applied to an gets extruded along a line, creating an extruded solid object.
object in sequence, forming a modifier stack.
Tessellate
Normal In geometry, a process of tiling a repeating a geometric shape on
In geometry, normal basically means ‘perpendicular to’. a surface with no overlaps and no gaps.

Normalized Vector Topology


In mathematics, a vector that maintains the same direction as In mathematics, topology describes how things are connected to
the original, but has a length of 1. each other without regard to their actual geometry.

NURBS Transformation
An abbreviation of Non-Uniform Rational Basis Spline (or A process of changing the geometry of a shape or object.
Surface). A NURBS is a mathematical model for generating and Standard transformations include translation (movement),
representing curves and surfaces. rotation and scaling.

Object-Oriented Programming Transformation Matrix


Object-Oriented Programming (OOP) is a programming style A matrix of numbers that encapsulate standard transformations.
that represents concepts as objects that encapsulate attributes Transformation matrices allow the combination of several
and methods. Attributes describe the features of the object transformations through matrix multiplication.
and methods are functions and procedures that can act on the
object when called. OOP has many advantages over traditional Translate
programming methods mainly in maintaining modularity, In geometry, to translate an object is to move it from one
readability and extensibility of the computer code. location to another location. Translation, rotation and scale are
called standard transformations.
Parametric Design
A process based on algorithmic thinking that enables the Tropism
expression of parameters and rules that, together, define, In botany, the direction an organism takes in response to external
encode and clarify the relationship between design intent factors such as light, gravity, wind or water.
and design response.
Vector
Pi (π) In geometry, a line with a magnitude (distance) and a direction.
A mathematical constant that is the ratio of a circle’s
circumference to its diameter. It is approximately equal Visual Programming Environment
to 3.1415926. In computing, a visual programming environment allows users to
create computer programs by manipulating and linking elements
Primitive graphically rather than by specifying them textually. Grasshopper
In 3D modelling, a basic geometry such as a cube, is an example of a visual programming environment.
cylinder or sphere.

Radian
A unit of angular measurement. One radian is equal to
180/π degrees.

Rollout
In 3ds Max, a group of user interface elements that can
be hidden or shown (rolled out) on demand.
202

Bibliography
Aish, R. and Woodbury, R. (2005). ‘Multi-level Interaction in Explorations of Fractals, Chaos, Complex Systems and Adaptation.
Parametric Design’. Smart Graphics, Proceedings of the 5th MIT Press.
International Symposium, SG 2005, Frauenwörth Cloister, Germany, Fornes, M. (2011). 11 FRAC Centre. Accessed at http://theverymany.
August 22–24, 2005, 151-162. Springer. com on 4 April 2012.
Alexander, C. (1974). Notes on the Synthesis of Form. Harvard Gamma, E. et al (1994). Design Patterns: Elements of Reusable Object-
University Press. Oriented Software. Addison Wesley.
Alexander, C. (1978). A Pattern Language: Towns, Buildings, Garcia, M. (2009). The Patterns of Architecture: Architectural Design.
Construction. OUP USA. John Wiley & Sons.
Antonelli, P. and Legendre, G. (2011). Pasta by Design. Thames Grobman, Y. and Neuman, E. (eds.) (2011). Performalism: Form and
& Hudson. Performance in Digital Architecture. Routledge.
Aranda, B. and Lasch, C. (2006). Tooling (Pamphlet Architecture). Harris, J. (2012). Fractal Architecture: Organic Design Philosophy in
Princeton Architectural Press. Theory and Practice. University of New Mexico Press.
Arnold, K. and Gosling, J. (1996). The Java Programming Language. Hauer, E. (2004). Erwin Hauer: Continua – Architectural Screens and
Addison-Wesley Publishing Company. Walls. Princeton Architectural Press.
Batty, M. (2007). Cities and Complexity: Understanding Cities with Hensel, M. and Menges, A. (2008). Versatility and Vicissitude:
Cellular Automata, Agent-Based Models, and Fractals. MIT Press. Performance in Morpho Ecological Design. John Wiley & Sons.
Beckmann, J. (ed.) (1998). The Virtual Dimension: Architecture, Hensel, M. Menges, A. and Weinstock, M. (2004). Emergence:
Representation and Crash Culture. Princeton Architectural Press. Morphogenetic Design Strategies. John Wiley & Sons.
Beesley, P. et al (eds.) (2006). Responsive Architectures: Subtle Hensel, M. Menges, A. and Weinstock, M. (2010). Emergent
Technologies 2006. Riverside Architectural Press. Technologies and Design: Towards a Biological Paradigm for
Benedikt, M. (ed.) (1992). Cyberspace: First Steps. MIT Press. Architecture. Routledge.
Bovill, C. (1996). Fractal Geometry in Architecture & Design. Hensel, M., Menges A. and Weinstock M. (eds.) (2006). ‘Techniques
Birkhäuser. and Technologies in Morphogenetic Design’. AD Profile 180,
Bridges, A. (1996). The Construction Net: Online Information Sources Wiley-Academy.
for the Construction Industry. E & FN Spon. Hesselgren, L. et al (2012). Advances in Architectural Geometry 2012.
Burden, E. (2000). Visionary Architecture: Unbuilt Works of the Springer.
Imagination. McGraw–Hill. Holme, A. (2002). Geometry: Our Cultural Heritage. Springer.
Burrowes, K.S. et al (2011). Pulmonary Embolism: Predicting Disease Iwamoto, L. (2009). Digital Fabrications: Architectural and Material
Severity. Philosophical Transactions of the Royal Society. Vol. 369, Techniques. Princeton Architectural Press.
4255–4277. Kieran, S. and Timberlake, J. (2004). Refabricating Architecture: How
Burrowes, K.S., Hunter, P.J. and Tawhai, M.H. (2005). ‘Anatomically Manufacturing Methodologies are Poised to Transform Building
Based Finite Element Models of the Human Pulmonary Arterial Construction. McGraw-Hill.
and Venous Trees Including Supernumerary Vessels’. Journal of Kolarevic, B. (ed.) (2003). Architecture in the Digital Age – Design and
Applied Physiology. Vol. 99, 731–738. Manufacturing. Taylor & Francis.
Burry, J. and Burry, M. (eds.) (2010). The New Mathematics of Kolarevic, B. and Klinger, K. (eds.) (2008). Manufacturing Material
Architecture. Thames & Hudson. Effects. Routledge.
Burry, M. (2011). Scripting Cultures: Architectural Design and Kolarevic, B. and Malkawi, A. (eds.) (2004). Performative Architecture:
Programming (Architectural Design Primer). John Wiley & Sons. Beyond Instrumentality. Routledge.
Carroll, S.B. (2006). Endless Forms Most Beautiful: The New Science of Krawczyk, R. (2009). The Codewriting Workbook. Princeton
Evo Devo. W.W. Norton & Company. Architectural Press.
Ceccato, C. et al (eds.) (2010). Advances in Architectural Geometry Lawson, B. (1990). How Designers Think: The Design Process
2010. Springer. Demystified. Butterworth Architecture.
Coates, P. (2010). Programming.Architecture. Routledge. Leach, N., Turnbull, D. and Williams, C. (eds.) (2004). Digital
Daniele, T. (2009). Poly-modeling with 3ds Max: Thinking Outside of Tectonics. Wiley-Academy.
the Box. Focal Press. Legendre, G. (2011). Mathematics of Space: Architectural Design.
Del Campo, M. and Manniger, S. (2011). ‘Performative Surfaces: John Wiley & Sons.
Computational Form Finding Processes for the Inclusion of Detail Lima, M. (2011). Visual Complexity: Mapping Patterns of Information.
in the Surface Condition. Computational Design Modeling’, Princeton Architectural Press.
Proceedings of the Design Modeling Symposium, Berlin, 2011. Littlefield, D. (ed.) (2008). Space Craft: Developments in Architectural
Springer, 225-238. Computing. RIBA Publishing.
Derakhshani, R. and Derakhshani, D. (2011). Autodesk 3ds Max Liu, Y. (2007). Distinguishing Digital Architecture: 6th Far Eastern
2012 Essentials. John Wiley & Sons. International Digital Architectural Design Award. Birkhäuser.
Eglash, R. (1999). African Fractals: Modern Computing and Indigenous Lunenfeld, P. (ed.) (1999). The Digital Dialectic: New Essays on New
Design. Rutgers University Press. Media. MIT Press.
Ehn, P. (1989). Work-Oriented Design of Computer Artifacts. Lynn, G. (1999). Animated Form. Princeton Architectural Press.
Arbetslivscentrum. Mandelbrot, B. (1982). The Fractal Geometry of Nature. W.H.
Evans, R. (2000). The Projective Cast: Architecture and Its Three Freeman & Co Ltd.
Geometrics. MIT Press. McCullough, M. (1996). Abstracting Craft: The Practiced Digital
Flake, G.W. (2000). The Computational Beauty of Nature: Computer Hand. MIT Press.
Bibliography 203

McCullough, M. (2004). Digital Ground: Architecture, Pervasive Reas, C. and Fry, B. (2007). Processing: A Programming Handbook for
Computing, and Environmental Knowing. MIT Press. Visual Designers and Artists. MIT Press.
McLuhan, M. (1994). Understanding Media: The Extensions of Man. Reas, C. and Fry, B. (2010). Getting Started with Processing: A Hands-
MIT Press. on Introduction to Making Interactive Graphics. Make.
Menges, A. (2012). Material Computation: Higher Integration in Rowe, P. (1995). Design Thinking. MIT Press.
Morphogenetic Design. John Wiley & Sons. Sakamoto, T., Ferre, A. and Kubo M. (eds.) (2008). From Control to
Menges, A. and Ahlquist, S. (eds.) (2011). Computational Design Design: Parametric/Algorithmic Architecture. Actar.
Thinking. John Wiley & Sons Ltd. Schodek, D. et al (2005). Digital Design and Manufacturing: CAD/
Mitchell, W. (2003). ME++: The Cyborg Self and the Networked City. CAM Applications in Architecture and Design. John Wiley & Sons.
MIT Press. Schön, D. (1983). The Reflective Practitioner: How Professionals Think
Mitchell, W. and McCullough, M. (1995). Digital Design Media. Van in Action. Basic Books.
Nostrand Reinhold. Schumacher, P. (2004). Digital Hadid: Landscapes in Motion.
Moussavi, F. et al (2009). The Function of Form. Actar and Harvard Birkhäuser.
Graduate School of Design. Schumacher, P. (2009). Parametricism–A New Global Style for
Moussavi, F. (2011). ‘Parametric Software is no Substitute for Architecture and Urban Design, AD/Architectural Design – Digital
Parametric Thinking’, Architectural Review. October 2011, 39. Cities, Vol. 79, Iss. 4, July/August 2009.
Moussavi, F. and Kubo, M. (eds.) (2006). The Function of Ornament. Schumacher, P. (2011). The Autopoiesis of Architecture: v. 1: A New
Actar and Harvard Graduate School of Design. Framework for Architecture. John Wiley & Sons.
Murdock, K. (2011). 3ds Max 2012 Bible. John Wiley & Sons. Schumacher, P. (2012). The Autopoiesis of Architecture: v. 2: A New
Negroponte, N. (1970). The Architecture Machine. MIT Press. Agenda for Architecture. John Wiley & Sons.
Negroponte, N. (1995). Being Digital. Vintage Books. Semper, G. (2011). The Four Elements of Architecture and other
Neumann, O. and Beesley, P. (eds.) (2007). FutureWood: Innovation Writings. Cambridge University Press.
in Building Design and Manufacturing. Riverside Architectural Press. Sheil, B. (2012). Manufacturing the Bespoke: Making and Prototyping
Otto, F. (2008). Occupying and Connecting: Thoughts on Territories Architecture. John Wiley & Sons.
and Spheres of Influence with Particular Reference to Human Sherwood, S. (2011). The Shape of Things to Come: Marc Fornes
Settlement. Axel Menges. Conducts a Spatial Experiment for the FRAC Centre in Orleans,
Otto, F. and Rasch, B. (1996). Finding Form: Towards an Architecture France. Accessed at http://www.interiordesign.net on 4 April
of the Minimal. Axel Menges. 2012.
Oxman, N. (2007). ‘Get Real: Towards Performance-Driven Snodgrass, A. and Coyne, R. (2006). Interpretation in Architecture:
Computational Geometry’. International Journal of Architectural Design as a Way of Thinking. Routledge.
Computing, Vol. 5, Iss. 4, Multi-science, 663–684. Spiller, N. (1998). Digital Dreams: Architecture and the New Alchemic
Oxman, N. (2007). ‘Material-based Design Computation: An Inquiry Technologies. Whitney Library of Design.
into Digital Simulation of Physical Material Properties as Design Spuybroek, L. (ed.) (2009). Research and Design: The Architecture of
Generators’. International Journal of Architectural Computing, Vol. 5, Variation. Thames & Hudson.
Iss. 1, Multi-science, 26–44. Spuybroek, L. (2011). Textile Tectonics – Research and Design. NAI
Oxman, N. (2010). ‘Structuring Materiality: Design Fabrication of Publishers.
Heterogeneous Materials’. AD/Architectural Design, Vol. 80, Iss. 4, Szalapaj, P. (2005). Contemporary Architecture and the Digital Design
Wiley-Academy. Process. Elsevier Architectural Press.
Oxman, R. (2008). ‘Performance Based Design: Current Practices Taimina, D. (2009). Crocheting Adventures with Hyperbolic Planes. A K
and Research Issues’. International Journal of Architectural Peters/CRC Press.
Computing, Vol. 6, Iss. 1, Multi-science, 1–17. Tedeschi, A. (2011). Parametric Architecture with Grasshopper. Le
Oxman, R. and Oxman, R. (2010). The New Structuralism: Design, Penseur.
Engineering and Architectural Technologies (Architectural Design). Terzidis, K. (2003). Expressive Form: A Conceptual Approach to
John Wiley & Sons. Computational Design. Routledge.
Pawlyn, M. (2011). Biomimicry in Architecture. RIBA Publishing. Terzidis, K. (2006). Algorithmic Architecture. Architectural Press.
Pearson, M. (2011). Generative Art: A Practical Guide Using Tschumi, B., and Cheng, I. (eds.) (2003). The State of Architecture at
Processing. Manning Publications. the Beginning of the 21st Century. The Monacelli Press.
Perella, S. (ed.) (1998). Hypersurface Architecture (Architectural Umemoto, N. and Reiser, J. (2006). Atlas of Novel Tectonics.
Design). John Wiley & Sons. Princeton Architectural Press.
Plauger, P.J. (1992). The Standard C Library. Prentice Hall. Weinstock, M. (2010). The Architecture of Emergence: The Evolution of
Pottmann, H. et al (2007). Architectural Geometry. Bentley Institute Form in Nature and Civilization. John Wiley & Sons Ltd.
Press. Weishar, P. (1998). Digital Space: Designing Virtual Environments.
Prusinkiewicz, P. and Lindenmayer, A. (1996). The Algorithmic Beauty McGraw-Hill.
of Plants. Springer-Verlag. Woodbury, R. (2010). Elements of Parametric Design. Routledge.
Rahim, A. (2000). Contemporary Processes in Architecture. AD Profile
145, Wiley-Academy.
Rahim, A. (ed.) (2002). Contemporary Techniques in Architecture. AD
Profile 155, Wiley-Academy.
Rajchman, J. (1998). Constructions. MIT Press.
Reas, C. (2010). Form+Code in Design, Art, and Architecture (Design
Briefs). Princeton Architectural Press.
204

Index
Page numbers in italics refer to picture captions ControlP5 library 53
coordinate systems 51–2, 166, 188, 200
A cross products 134, 148, 200
Aish, Dr Robert (Autodesk) 6, 176–7 curve editor (tip) 45
Akos, Gil (Studio Mode) 47, 64–7 CV (Control Vertex) 30, 31, 200
Alexander, Christopher 28, 198
algorithmic thinking D
advantages 9, 22, 179 deformation 16, 42 see also tapering; twisting
defined 9, 22, 196, 201 del Camp, Matias (SPAN) 12
and scripting 6–7, 22–5, 178, 180 Desblens, Nicholas (Caliper Studio) 81
algorithms Descartes, René 200
defined 6, 22, 200 Design Patterns (Gamma, Helm, Johnson and Vissides) 28
genetic algorithms 78, 200 Design 3 screen, Leising church, Vienna (Hauer) 126
Voronoi algorithms 124, 125 DesignScript (Autodesk) 6, 176–95
see also algorithmic thinking developable surfaces 154, 200
Aranda, Benjamin 28 diagrids 29, 82–92, 179, 180–9, 196
arguments 24, 71, 76, 77, 167, 200 from NURBS surface 82, 83, 93–103, 179, 180, 186, 187
arrays 23, 25, 32, 47, 84, 89–90, 178 digital fabrication 9–10, 29, 108, 124–5, 156, 176, 200 see also CNC
Arup Engineering 28, 29, 42 machines
associative programming diPloids project (Studio Mode) 64
advantages 9, 10–11, 30, 40, 178–9
and controller patterns 30, 32, 33, 35, 40 E
defined 9, 200 Elements of Parametric Design (Woodbury) 28
imperative programming compared 177–9, 200 encapsulation 11, 24, 186, 200, 201
attributes 10–11, 23, 24–5, 32, 34–5, 43–4, 47, 187, 201 environmental parameters 197
Austrian Pavilion, Shanghai Expo 2010, China (SPAN) 12–19 Eurocont Headquarters screen, Badalona, Spain (HYBRIDa scp) 104–9
AutoCAD 176, 185, 189, 192
AutoLISP 176 F
Aviva Stadium, Dublin (Populous) 36–41 families 10, 11, 23 see also class
Felipe, S. (HYBRIDa scp) 104
B Fibonacci Series 48, 49–52, 200
The Beast, Museum of Science, Boston, USA (Oxman with Carter) finite elements analysis (FEA) 78
124–5 floats 23, 176
boolean algebra 23, 200 flowcharts 80, 200
Boole’s Lattice (Parsons and Akos) 47 Fornes, Marc (THEVERYMANY) 152–5
bounding boxes 120, 121, 200 The Four Elements of Architecture (Semper) 126
branching 68, 156–73 fractals 24, 28, 68, 69, 72–7, 156, 158, 172, 200
building information modelling (BIM) 176, 196, 200 functions 10, 11, 22, 23, 24, 176
Buro Happold 36, 40 recursive 68, 70–1, 72, 165
Burry, Jane and Mark 28 see also callback functions; methods

C G
C# 176, 177 Gamma, Erich 28
Cairo tiling 64, 66 Gaudí, Antoni 8, 42, 157
Caliper Studio 78–81 Generative Components (GC) (Bentley) 40, 168, 172, 176, 177, 178
callback functions 25, 89, 118, 120, 122, 144–5, 150, 167 genetic algorithms (GAs) 78, 200
Carroll, S.B. 168 Genetic Stair, Upper West Side, New York (Caliper Studio) 78–81
Carter, Craig 124 geometrical parameters 196
Cartesian coordinate system 51, 188, 193, 200 global variables 24, 100, 117, 132, 144, 200
Casa Milà, Barcelona (Gaudí) 8 golden rectangle 50–1, 52, 200
catenary curves 8, 42 golden spiral 50, 51–2, 200
circles in parametric design 10–11, 32–5, 112–23 graphical user interface (GUI) 25, 200
cladding systems 9, 16, 39, 40 Grasshopper 176, 177, 178, 201
classes 11, 23, 24–5, 176, 179, 180, 186, 187, 196–7 Green Building Studio 176
CNC (Computer Numerical Control) machines 16, 66, 81, 82, 107,
200 H
collections (DesignScript) 178–9, 195 hanging chain models 8, 42
continuous differentiation 9, 10 Hauer, Erwin 126
controller patterns 30–41, 44, 45, 46 Helm, Richard 28
Index 205

hexagons 16, 58, 59–63 N


HOK Sports Architecture see Populous Nasir al-Mulik mosque, Shiraz, Iran 58
human parameters 197 nature and parametric design 12, 68, 69, 82, 110, 124–5, 156,
HYBRIDa scp 104–9 168–73, 200
Negroponte, Nicholas 42
I nested geometry 68, 70–1
imperative programming 177–9, 200 nested loops 24, 25, 58, 60, 89, 91, 146–7, 149
inheritance 11, 23, 24, 25 nested polygons 53–7
integers 23, 176 Network Growth (MATSYS Design) 28
interfaces 6, 23, 30, 53, 82, 122, 178, 201 see also graphical user The New Mathematics of Architure (Burry) 28
interface; rollout user interface nodes 25
Iron Python 176 nonLin/Lin Pavilion, FRAC Centre, Orleans, France (Fornes) 152–5
iteration 9, 24, 53, 93, 104, 107, 176, 177, 178 ‘normal’ (perpendicular) 136, 188, 201
recursive 68, 71, 72, 75 NURBS (Non-Uniform Rational Spline/Surface) surfaces
see also repetition creating (tip) 98
Ito, Toyo 28, 29 defined 201
and diagrids 82, 83, 93–103, 179, 180, 186, 187
J and parametric patterns 29, 30, 31, 82, 83, 93–103, 127, 136–51,
Java 22, 176, 177 200
Johnson, Brian 198–9 weaving 127, 136–51, 194
Johnson, Ralph 28
O
K object-oriented programming (OOP) 10–11, 23, 24, 176, 186, 189,
Kudless, Andrew (MATSYS Design) 28 200, 201
Kuo, Jeannette 111 objects 10, 11, 16, 23, 24–5, 32, 47, 176, 178
Oxman, Neri 124–5
L
L-Systems fractal 172 P
Lasch, Chris 28 Packed Pavilion, Shanghai Expo 2010, China (Leidi, Min-Chieh Chen
laser cutting 29, 82 and Zausinger) 111
Le Corbusier 197 packing 110–25
Le Modulor, Unité d’Habitation, Firminy, France (Le Corbusier) 197 ParaGrove installation (Studio Mode) 64
Leidi, Michele 111 parameters 9, 11, 30, 32, 48, 58, 104, 196–7
Leonardo de Pisa (Fibonacci) 200 parametric design
loops advantages 9, 10–11, 36, 40, 198
‘for loops’ (‘while loops’) 24, 25, 55, 57, 89, 91, 176, 177, 178 characteristics 10–11, 22–5, 196
nested 24, 25, 58, 60, 89, 91, 146–7, 149 defined 9, 196, 201
repetition 50, 55, 56–7, 58 the future 11, 125, 154, 176, 178, 196, 199
practice 7, 9, 22, 198–9
M taxonomy of parameters 196–7
Magnet Julia fractal 69 see also circles; nature; pattern; ribbons
magnetic fields 30, 42, 197 parametricism 9
Mandelbrot, Benoit 156 Parsons, Ronnie (Studio Mode) 47, 64–7
Manninger, Sandra (SPAN) 12 pattern in parametric design 28–9, 198
mass-customization 9–10 attractors 43–7
material parameters 196–7 branching 68, 156–73
mathematical parameters 196 controllers 30–41, 44, 45, 46
Matière à Rétro-projeter! exhibition, Centre Pompidou, Paris 11 force fields 42
MATSYS Design 28 fractals 24, 28, 68, 69, 72–7, 156, 158, 172, 200
MAXScript 6, 24–5, 84, 93, 136, 176, 179, 180–95 hexagonal tiling 16, 58, 59–63, 89
Maya Embedded Language (MEL) 176 iteration 68, 71, 72, 75, 93, 104, 107
Mayer-Hermann, Jürgen 42 natural patterns 68, 69, 82, 110, 124–5, 156, 168–73, 200
Menger sponge 68 NURBS surfaces 29, 30, 31, 82, 83, 93–103, 127, 136–51, 200
methods 11, 23, 24, 176, 186–9, 200, 201 see also functions packing 110–25
Metropol Parasol, Seville, Spain (Mayer-Hermann and Arup) 42 recursion 29, 68–81, 158–67
Microstation 176 repetition 29, 48–57, 58, 68, 154
Min-Chieh Chen 111 subdivision 16, 28, 29, 68, 82–109, 110, 126, 179, 180–9
modelling see Building Information Modelling; 3D modelling 3D modelling 40, 81, 82, 127
modifiers 43, 92, 201 3D parametric patterns 28–9, 47, 64, 66
sweep modifiers 128, 131, 132–3, 135, 136, 143, 144 tiling 16, 48, 58–67, 89, 110, 125, 127
Momo, Giuseppe 28–9 2D parametric patterns 28–9, 47, 53, 58, 64
206 Index

weaving 126–55, 179, 190–5 SPAN Architecture & Design 12–19


A Pattern Language (Alexander) 28 spreadsheets 40, 178, 196
Pawlofsky, Tom 111 Steele, Brett 22
pointers 23, 24, 145, 186 strings 23, 176
polygons 59, 104, 107, 121 Studio Mode 47, 64–7
nested 53–7 su11 architecture+design 168–73
Populous 36–41 subdivision 16, 28, 29, 68, 82–109, 110, 127, 179, 180–9
primitive 201 sweep modifiers 128, 131, 132–3, 135, 136, 143, 144
Processing (MIT) 6, 49, 53, 176, 177, 199 sweep profile 128, 131, 143, 150, 201
programming see associative programming; imperative
programming; object-oriented programming T
programming languages tapering 6, 25
classes 23, 24–5, 176 tessellation 16, 29, 64, 66, 125, 154, 201
data types and variables 11, 23, 24–5, 44, 71, 176, 177, 178, 198 3D modelling
events 22, 25 controllers 30, 40
examples 6, 49, 84, 93, 136, 176–9 see also DesignScript; MAXScript; and parametric patterns 40, 81, 82, 127
Processing software 9, 36, 40, 78, 82, 168, 172, 196, 201
expressions 23, 24, 34, 46, 179, 196, 198, 200, 201 3D parametric patterns 28–9, 47, 64, 66
iteration and recursion 9, 24, 53, 93, 176, 177, 178 3ds Max (Autodesk) 6, 10, 11, 44, 82, 84, 176, 189, 201
logic and control 9, 23–4 tiles and tiling 16, 48, 58–67, 89, 110, 125, 127 see also tessellation
objects 10, 11, 23, 24–5, 176, 178 Tooling (Aranda and Lasch) 28
structure 22–3, 198 TopMod software 16
see also scripts and scripting topology 16, 42, 48, 64, 82, 154, 187, 189, 201
propagation 10–11, 68, 72, 196 topological parameters 196
PS_Canopy (su11 architecture+design) 168–73 The Tote, Mumbai (Serie Architects) 157
Python 22, 176, 177 transformations 16, 154, 201
translate 9, 51, 90, 179, 201
R tropisms 156, 158, 201
radians 55, 201 Truco, J. (HYBRIDa scp) 104
recursion 24, 29, 68–81 twisting 6, 16, 25
branching 158–67 2D parametric patterns 28–9, 47, 53, 58, 64
and functions 68, 70–1, 72, 165
iterative 68, 71, 72, 75 U
repetition 29, 48–57, 58, 68, 154 see also iteration Union Square installation, New York (Fornes) 152, 154
replication (DesignScript) 179, 190, 194, 195 units (tip) 44, 198
representational parameters 196
Revit (Autodesk) 176 V
Rhino 176 values 10–11, 23, 24–5, 177–8
Rhinoceros (McNeel) 36, 40, 78 variable property design (VPD) method 124
Rhinoscript 176 variables 11, 23, 24–5, 44, 71, 176, 177, 178, 198 see also global
ribbons in parametric design 102, 128–35 variables
RK4 Tiles, New York (Studio Mode) 64–7 Vatican Museum, Rome (Momo) 28–9
Robot (Autodesk) 176, 177 vectors 42, 119, 134, 201
rollout user interface 61, 100, 118, 201 cross product 134, 148, 200
Romero, Fernando 7 normalized 136, 201
versioning 9, 10
S Vissides, John 28
Sagrada Familia church, Barcelona, Spain (Gaudí) 157 Visual Programming Environment 201
Schumacher, Patrik (Zaha Hadid Architects) 9 Voronoi algorithms 124, 125
scripts and scripting
and algorithmic thinking 6–7, 22–5, 178, 180 W
defined 201 weaving 126–55, 179, 190–5
functions 22, 23, 24, 68, 70–1, 72, 165, 176 see also callback ‘while loops’ see under loops
functions; methods Woodbury, Robert 6, 28
methods 11, 23, 24, 176, 186–9, 200, 201
structure 22–3, 198 Z
see also programming languages Zausinger, Dominik 111
Semper, Gottfried 126 Zeytonoglu 12
Serie Architects 157
Serpentine Gallery Pavilion, Hyde Park, London (Ito and Arup) 28, 29
Soumaya Museum, Mexico City, Mexico (Romero) 7
207

Picture credits
Images are by the author except on the pages 80–81 Caliper Studio (Stephen Lynch, Jonathan Taylor, Michael
specified below: Conlon and Nicholas Desbiens)
82 (fig. 58) Michael Rygel
7 (fig. 2) Beeeh Photography 104–109 HYBRIDa scp (J. Truco and S. Felipe)
8 (fig. 3) Etan J. Tal 110 (fig. 71) Henri-Georges Naton
10 (fig. 5) Scottish Doors (Ross Sampson) 110 (fig. 72) Srini G. via Wikimedia Commons
12–19 SPAN (Matias del Campo & Sandra Manninger) 110 (fig. 73) Dr Jocelyn via http://biocharproject.org
26 THEVERYMANY (Marc Fornes) 110 (fig. 74) Dawn Endico
28 (fig. 9) MATSYS Design (Andrew Kudless) 111 (fig. 75) NASA
29 (fig. 10) Frankie Roberto 111 (fig. 76) Tom Pawlofsky
29 (fig. 11) Andreas Tille 124–125 Neri Oxman (photo: Mikey Siegel)
30 (fig. 12) Stephen Lee 127 (fig. 84) Olando and Mendo Architects
36–37 Populous (David Hines) 128 (fig. 85) Sergis via Wikimedia Commons
38 Roly Hudson 152–155 THEVERYMANY (Marc Fornes)
39 Populous (David Hines) 156 (fig. 95) Kelly Burrowes
40 Roly Hudson 156 (fig. 96) R. Neil Marshman
41 Populous (David Hines) 157 (fig. 97) Zhang Wenjie
42 (fig. 24) Nevit Dilmen 157 (fig. 98) Serie Architects (Photographer: Edmund Sumner/VIEW)
42 (fig. 25) Rocío Ruiz 168–173 su11 architecture+design (Ferda Kolatan & Erich
47 Studio Mode (Ronnie Parsons and Gil Akos) Schoenenberger)
48 (fig. 38) Tomas Castelazo 174 SPAN (Matias del Campo & Sandra Manninger)
58 (fig. 44) Pentocelo 176 (fig. 103) Autodesk (Robert Aish, Patrick Tierney, Luke Church)
64–67 Studio Mode (Ronnie Parsons and Gil Akos) 177 (fig. 104) Autodesk (Robert Aish, Patrick Tierney, Luke Church)
69 (fig. 50) Alexis Monnerot-Dumaine 197 (fig. 112) www.mr-erno.blogspot.com
69 (fig. 51) Richard Bartz 199 (fig. 113) Brian Johnson
69 (fig. 52) Gnomz007 and Túrelio
78–79 Images © Ty Cole. Caliper Studio (Stephen Lynch, Jonathan
Taylor, Michael Conlon and Nicholas Desbiens)
208

Acknowledgements
I could not have completed this book without the invaluable help of intent. My thanks also go to Neil Katz of SOM who read a draft
my family, friends and colleagues. I would like to offer my sincerest of the book and provided many invaluable comments. There is
gratitude to Dr Robert Woodbury who gave of his generous time no space in this book to individually thank the many researchers,
to read the book and provide a thoughtful foreword to it. I am designers and programmers who have selflessly contributed
also very grateful to the friendship and insight that Professor Brian inspirational ideas and open source code online for all of us to
Johnson offered me over the many months leading to the publication learn from. I am also immensely grateful to those who contributed
of this book. Brian kindly agreed to provide the afterword for images and descriptions of their work for inclusion in this book.
this book, but I am also grateful for his patient advice laced with I would also like to thank my colleagues as well as my students
humour in the numerous e-mail exchanges we had about this book at the Welsh School of Architecture at Cardiff University who
and parametric design in general. My thanks also go to three old warmly welcomed me and provided the intellectual and collegial
friends, Dr Theodore Hall, Dr Scott Johnson and Jeremy Kargon. Ted environment that enabled me to dedicate the time and effort
is truly a walking encyclopedia of algorithmic knowledge. If I am needed to complete this book. In particular, I would like to
ever at a loss on how to solve a problem, I can always rely on his sincerely thank Professor Richard Weston, who recommended
help. Through years of friendship, Scott has offered me invaluable me to Laurence King Publishing, for his friendship and for
advice on issues of digital design, building-information systems stimulating discussions about all things digital and parametric.
and representation. Jeremy, on the other hand, collaborated with I offer my deep gratitude to the team at Laurence King Publishing,
me on the first visual online archive on the Internet before the especially Philip Cooper, Liz Faber and Sara Goldsmith, for their
World-Wide Web was invented. Over the years, he remained a wise advice, tireless efforts and patience while they waited for the
loyal friend always pushing me in new directions. I am also deeply completed manuscript.
grateful to Professor Harold Borkin and Professor James Turner, my Finally, I would like to give a very heartfelt thanks to my two
Ph.D. advisors, who taught me how to think algorithmically and daughters, Maye and Sarah, for their unconditional love and
how to code early on at the University of Michigan. I will always especially to my wife, Dr Vassiliki Mangana. Her unwavering support
be indebted to them for the knowledge they imparted on me. over the years gave me the strength to continue working on several
My heartfelt gratitude goes to Carl Luckenbach who, apart from projects when I would have otherwise given up. Her expertise as
sponsoring my application for U.S. citizenship, offered me my a historian of architecture was invaluable in helping me properly
first digital design job in practice and allowed me to realize the research, understand and describe the case studies in this book.
amazing potential of using digital tools to communicate design

You might also like