Speculative Articulations a methodological investigation of architecture and information technology
Christoph Zechmeister Chair for Computer Aided Architectural Design Departement for Architecture - ETH ZĂźrich
content the setting
1
the play
9
the unfolding of space
11
navigating junkspace
57
the intensity veil
75
the script
93
coding steps
94
code 95
bibliography
131
Speculative Articulations - The Setting
the setting
Movie Still from Martin Scorsese’s “Hugo” (2011)
1
Speculative Articulations - The Setting
Based on the architect as a generalist we embark on our journey with the intention to navigate a multitude of disciplines. Looking at architecture as an act of intellect we try to tackle and learn from radically different disciplines like film, philosophy, mathematics, linguistics, information technology etc .. While becoming an expert in every single one of them would probably be impossible we remember Vitruvs idea of architecture as beeing non disciplinal1 and strive for an overview, trying to grasp things in their generality. Design, conventionally conceived of as the sole performance of the designer (in this case the architect), is understood as an act of negotiation, between the architect and his (imaginary) client, as a quest for synthesizing a certain character. To articulate this character, a series of movie scenes - as a quasi infinitary source of images - acts as a “breeding ground�, constitutes a plane of consistency upon which our contrived mechanisms can operate on. Cinematic sequences are used due to their capability of providing a rich field of indices, while being easy to relate to and usually executed with great mastership. According to Gilles Deleuze, classical narration derives from the organic composition of movement images or respectively from their specification as perception images, affection images or action images. By leaving the traditionally sequential notion of narration and moving to what Deleuze calls a time image, we gain significantly more freedom and flexibility in terms of composition. 2
1 Vitruvius, The ten Books on Architecture (Morgan, 1914) 2
Gilles Deleuze, Cinema 2 The Time Image (The Athlone Press, 1989) 2
Speculative Articulations - The Setting
By infusing an image with the past or future it becomes essentially different from itself, it is virtual and can rather be characterized by its relation to other images, creating infinite possible interconnections between our array of time - images. Our image plane itself is composed in a non hierarchical way, depicted as accumulations in the sense of the Deleuzian rhizome, without beginning or an end, changing in nature every time a new story is introduced. The images posess the ability to continously form new connections on their established plane, they can create new links between different natures and therefore implicate the possibility for all other stories that might exist. By looking at images as flowing matter, as slices of the world which emphasize some aspects of the universe over others, we treat them as signs, as vectors pointing to a certain “meaningfulness�. This meaningfulness - let us call it purport from now on, as danish linguist Louis Hjelmslev suggested - we want to look at as that which circulates, that which can never be exhausted, but articulated infinitely in manifold ways conveying more or less of the purport according to the mastership of the articulator.3 Thus we find that the chains ... despite all their differences, have a factor in common, namely the purport, the thought itself. This purport, so considered exists provisionally as an amorphous mass, an unanalyzed entity ... We may imagine this purport to be analyzed from many points of view, to be subjected to many different analyses, under which it would appear as so many different objects.4
3 Louis Hjelmslev, Prolegomena to a Theory of Language (London, 1969) 4 ibid. 5
Speculative Articulations - The Setting
In order to create stabilities and maintain balance across different storylines, we need to gather several different artefacts, we need to modulate the stories that surround us, to rearticulate them and by that create new perspectives which eventually will bear new meanings. By appropriating parts of an objects “code”, by decontextualizing it, it becomes detached from its original function. Reapplied in another setting, another territory, it constitutes - in conjunction with many other codes - an object that is itself new and unique in the forms it can take compared to those objects which codes it inherits. As architects it is our task to navigate, to process the stream of possible stories and tell those, that are relevant to synthesize the desired character, in an architecturally adequate way. Thus, the main questions asked in this thesis are: •
How can we develope a design strategy able to deal with the technological complexity of the digital realm and at the same time preserve our creative freedom?
•
How can the vast stream of possiblities be negotiated?
•
What is the potential of the digital on the conceptual level in the context of architecture?
6
UNDER DTHE TREES OF VOICES
LAYERED REALITIES
THE LABYRITH OF DESPAIR
# visual richness & pattern
ETERNAL SUNSHINE
THE LABYRINTH OF DESPAIR LAYERED REALITIES
# influence dreams
ETERNAL SUNSHINE
# monumentality
CINEMA PARADISO
BARRY LYNDON # vast, mystic spaces
# interest in the paradox # intimacy
# participate in dreaming
ETERNAL SUNSHINE
# journey through memory space
# looking inside other worlds
THE LABYRINTH OF DESPAIR
LAYERED REALITIES
THE LA OF DE
# urban setting # worlds, changeable by imagination
# surreal setting
BAZOOKO CIRCUS
# architecture of infrastructure
# sarcastic / critical look at society
# sarcastic humour
NIGHTCAP AT THE KOROVA
WE’RE ALL IN IT
WE’RE ALL IN IT TOGETHER
NIGHTCAP AT THE KOROVA
# technoid aesthetics
# abstract
BAZOOKO CIRCUS
DARK CITY
EVERYTHING HAS A PURPOSE
EVERYTHING HAS A PURPOSE
EVERYTHING HAS A PURP.
# fascination of the machine
EVERYTHING HAS A PURPOSE
# exuberance
BAZOOKO CIRCUS
BAZOOKO CIRCUS
# social criticism
NIGHTC. AT THE KOROVA
# grotesque ornamentation
# complexity
# celebration of the grotesque
NIGHTCAP AT THE KOROVA
# baroque
BARRY LYNDON
# the world as machine without extra parts - each one for a specific purpose
BAZOOKO CIRCUS
LAYERED REALITIES
# interplay of light and shadow
ABYRINTH ESPAIR
# contrast
LIVE OUT OF BALANCE THE FOUNTAIN
LIVE OUT OF BALANCE
THE MAN WHO WANSN’T THERE
# dramatic lighting
# immediate relation to the outdoors
# absence of daylight
# light images
# ornamental richness
# dramaturgy of light
# vagely defined spaces
ornament # darkness
CINEMA PARADISO
CINEMA PARADISO DARK CITY
THE FOUNTAIN
UNDER THE TREES OF VOICES
UNDER THE TREES OF VOICES
UNDER THE TREES OF VOICES
CINEMA PARADISO
# ephemeral spaces
# fascination of the imaginary
# volatile formations
Speculative Articulations - The Play
the play The performative part of this project is structured in three stories. Each one is of a distinctly different kind, posessing a specific character constructed by different discourses.
9
Speculative Articulations - The Play
10
Speculative Articulations - The Unfolding Of Space
the unfolding of space Any architectural artefact - if articulated masterly - needs both geometry and arithmetics. In this first story we discuss the investigation of space in geometrical terms. Six dramatic movie scenes act as geometrical foundation, as input geometry, for a recombinational process, staged in an abstract space of possibilities. Inspired by the cinematic unfolding and dramaturgy of spaces of Koolhaas’ dutch embassy in Berlin, the question at stake here is how are the geometries involved mediated? What constitutes their mapping, what is the rhythm according to which they unfold and how can this be dramatized in an architectural performance? Thinking about the experience of space through movement, we may refer to the phenomenological ideas of Maurice Merleau Ponty, who coined concepts like the notion of the lived experience of the body in space, regarding kinesthesis as determining factor of spatial perceptions: Each voluntary movement takes place in a setting, against a background which is determined by the movement itself ... We perform our movements in a space which is not “empty� or unrelated to them, but which on the contrary, bears a highly determinate relation to them: movement and background are, in fact, only artificially separated stages of a unique totality.5
5
Maurice Merleau-Ponty, Phenomenology of Perception (The Humanities Press, 1962)
11
Speculative Articulations - The Unfolding Of Space
Spatial Dramaturgy of Rem Koolhaas’ Dutch Embassy, Berlin source: https://moreaedesign.files.wordpress.com/2010/09/netherlands-embassy-trajectory-map1.jpg
Koolhaas’ strategy for the dutch embassy celebrates the experience of space through movement too - the movement along a trajectory, a vector along which space unfolds. The viewer is provided with ever changing sensations, experienced through motion using cinematic sequencing of the narrative: an interpretation of the city of Berlin, capturing historically significant elements of the city. In our setup, as a first attempt to negotiate the multitude of parallel storylines, we have to find means do deal with the different characters of our narratives, to establish a climate where they can coexist and can be made commensurable. By abstracting in a non reductive way, the different characters become able to talk without losing their initial richness while at the same time, the possibilities for future rearrangements are preserved.
12
Speculative Articulations - The Unfolding Of Space
A Zed & Two Noughts (1985) Peter Greenaway
A Zed & Two Noughts (1985) Peter Greenaway
A Zed & Two Noughts (1985) Peter Greenaway
A Zed & Two Noughts (1985) Peter Greenaway
A Zed & Two Noughts (1985) Peter Greenaway
A Zed & Two Noughts (1985) Peter Greenaway
Dramatic Moviescenes, providing Input Geometry 13
Speculative Articulations - The Unfolding Of Space
Input Geometry, prepared for Voxelization 14
Speculative Articulations - The Unfolding Of Space
Probabilistic Space, 5.832.000 Voxels
In order to establish such an environment, all our input geometries are voxelized in a first step. A voxel (volumetric element) represents a single data point on a regularly spaced three dimensional grid, describing a highly structured design space and representing singular points in space, instead of volumes while leaving the space inbetween them unrepresented. This data points can consist of a single piece of data or of multiple data entries. Voxel technology is commonly used in the medical field, in applications like ultrasound or computer tomography (CT) scans. After voxelizing, all geometries are represented by a single row matrix, a vector, containing binary information on whether a cell is either active or inactive, constituting a cubic space of 250 x 250 x 250 cells. By loading the vectors of all our geometries, we create a space charged with information of all our stories, a breeding ground waiting for our framework, our abstract object to operate on and to create individual, one of a kind instances. This being pre-specific - a condition of minimum determinacy and maximum determinability, creates a flexible field, fostering the creation of new and unexpected results. Indeterminacy
15
Speculative Articulations - The Unfolding Of Space
here does not refer to “something missing” as in a lack of knowledge or incompleteness, it rather constitutes a horizon within perception.6 This openness manages to preserve the initial richness of an idea, essentially bypassing the reductive process of design through iterations of optimization. It does not close up at a certain point, in hope to have found what would be the most appropriate object but can accomodate future changes, additions and twists. By creating instances emanating from such a descriptive framework, articulated in a voxelspace, we leave the assumption of the object as the bearer of meaning and focus on relations between objects instead. The object itself can be considered – analogously to object oriented programming – as an instance of a class, as a member of a population governed by our abstract framework acting as a collection of rules that define the objects’ properties and behaviour. Borrowing from the field of language theory, this double articulation like setup establishes
6
Gilles Deleuze, Difference and Repetition (Columbia University Press, 1995)
16
Morphing Process, governed by Gradient Maps
Speculative Articulations - The Unfolding Of Space
a creative economy, enabling us to endlessly rearticulate, or in other words provides us with the power to cope with the infinite, not dealing with form anymore in a traditional sense but rather with a spectrum of possible forms. If we consider every instance of our abstract object a talk - a talk between different characters, able to co-exist through abstraction - those different characters need some kind of mediation, a moderator preventing them from overscreaming each other, a rhythm according to which space unfolds and can be experienced by the observer. As a first attempt, this mediation is provided by a simple colormap. By creating different gradient patterns, the spatial constellations vary dramatically, providing ever changing spaces and different agglomerations of geometries. Taking the concept of mediation one step further, we try to incorporate another layer into our story, using additional movieframes to govern the recombination of geometry. In Guy Debords map of Paris from 1959, called “The Naked City�, the observer is presented with a a map of 19 sections of Paris, linked by directional arrows. Each of them represents a specific atmosphere, a certain character while the arrows show spontaneous directions of movement, without regard to normal habitual behaviour in the city. By fragmentation of urban space, the user can experience the changing atmospheres of the city in a novel way. Coming back to our story, in a second attempt to mediate the talk between different characters, the spatial rhythm of five floorplans of existing buildings - taken from five epic
19
Speculative Articulations - The Unfolding Of Space
Guy Debord, The Naked City, 1957 source: http://imaginarymuseum.org/LPG/debordpsychogeo.jpg
movie scenes - is rearticulated by means of our input geometries, much like a situationist friend of Debord who tried to wander the Harz region in Germany with a city map of London, in a quest to inhabit the everyday realm as a passage of time trough derive and detournement.7 In order to establish relations between the floorplans of the epic movie scenes and the input geometries, both are investigated towards their local intensities. In the case of the plans, a basic shape detection algorithm identifies and measures geometric regions. The corresponding local intensities are then calculated as a formula of the region’s sizes and
7
Guy Debord, The Society of the Spectacle (Zone Books, 2006)
20
Applet for calculating Mesh Saliency
Speculative Articulations - The Unfolding Of Space
Identification of geometric Regions
Intensity Map
internal components, therefore creating a kind of intensity map for all the plans. Investigating the input meshes is a little more complicated. Using mesh saliency calculation - a technique commonly practiced in mesh simplification and automated viewport detection - areas that attract low level human attention are identified. By that, we create a measure of regional importance of meshes and gain the ability to classify the meshes according to their saliency. In a probabilistic setup - using a wheel of fortune like mechanism, mapping the probabilities of a geomtery being selected based on its match for the area of the plan under investigation - the intensity map extracted from the floorplans is then populated with the most appropriate geometry for the corresponding region. What we are left with can be considered an itinerary of intensities, governing the morphing process of our geometrical cornerstones, or in other words the mediated talk between our heroes.
23
Speculative Articulations - The Unfolding Of Space
Diagram of the Morphing Process
24
Speculative Articulations - The Unfolding Of Space
Mozart - Losey, Don Giovanni (Joseph Losey), 1979 Villa Almerico Capra Valmaran(La Rotonda) Andrea Palladio, Italy, 1592
25
Speculative Articulations - The Unfolding Of Space
26
Speculative Articulations - The Unfolding Of Space
The Fall (Tarsem Singh), 2006 Adalaj Stepwell Ahmedabad, India, 1499
31
Speculative Articulations - The Unfolding Of Space
32
Speculative Articulations - The Unfolding Of Space
House on Haunted Hill (William Castle), 1959 Ennis House Frank Lloyd Wright, California,1923
37
Speculative Articulations - The Unfolding Of Space
38
Speculative Articulations - The Unfolding Of Space
I am Love (Luca Guadagnino), 2009 Villa Necchi Campiglio Piero Portaluppi, Milan, 1935
43
Speculative Articulations - The Unfolding Of Space
44
Speculative Articulations - The Unfolding Of Space
The Young Victoria (Jean-Marc VallĂŠe), 2009 Lincoln Cathedral Remigius de FĂŠcamp, Lincoln, 1092
49
Speculative Articulations - The Unfolding Of Space
50
3D printed Model
Speculative Articulations - Navigating Junkspace
navigating junkspace If geometry is considered as epic or dramatic, as something that gives primacy to objects and their perception, textures are of a fundamentally different kind. Their lack of geometry makes them “twist” and “bend”, enabling us to morph and blend them in manifold ways. In the light of our cinematic setup that would mean that textures are on the novel side of our story. Looking at the movie “Koyaanisqatsi”, an experimental film from Godfrey Reggio featuring striking imagery and subtitled “Live out of Balance”, it seems like a cinematic manifestation of Rem Koolhaas’ essay “Junkspace”. The film shows the relation between humans, nature and technology, portraying a world of seemingly unrelated fragments devoid of any connectional framework or structure. According to Koolhaas, architecture disappeared in the 20th century. If Junkspace is what is left after modernism and the idea of independence, of the independent object as a principle, is close to modernism, than this is probably also true for junkspace. If we are left with a bunch of architectural fragments, with orphaned particles, objects take the primary role and supersede relations, with meaning directly attached to them as a kind of physical property. The idea of the primacy of the objects seems reminiscent of concepts from phenomenology, albeit occurring here in a distinctly different way. In junkspace, the independent object is of a tyrannic nature whereas in phenomenology one lives through the object, one changes the object by means of empathy.
59
Speculative Articulations - Navigating Junkspace
“In Junkspace, the tables are turned: it is subsystem only, without superstructure, orphaned particles in search of a framework or pattern.� 60
Speculative Articulations - Navigating Junkspace
Every sensuous object, in so far as it exists for me, is always the product of two components, of that which is sensuously given and of my apperceptive activity.8 Junkspace is not only everywhere, it is also pretty much self healing. No matter how hard we try to destroy it, it keeps coming back, popping up in ever new and unexpected places and in different forms. You can destroy modernism, but you cannot get rid of junkspace. If we keep playing Koolhaas’ game, there seems to be no way out, no escape of what modernism left us with. Our only chance would be to navigate - to find our way around, avoiding to get lost. To do this, we need to establish aforementioned missing relational system, we need to negotiate the isolated objects surrounding us. To see is to enter a universe of beings which display themselves, and they would not do this if they could not be hidden behind each other or behind me. In other words: to look at an object is to inhabit it, and from this habitation to grasp all things in terms of the aspect which they present to it .. Thus every object is the mirror of all others 9 If an object becomes a “mirror of all the others” by us perceiving all its perspectives coming from surrounding things, as well as all potential perspectives it has on the things around it, what would its reflection look like? According to that, our own, very personal perspective, would be capable of intrinsically carrying all other perspectives with it as well as all perspectives possible in the future.
8 9
Wilhelm Worringer, Abstraction and Empathy: A Contribution to the Psychology of Style (International Universities Press, 1967) Maurice Merleau-Ponty, Phenomenology of Perception (The Humanities Press, 1962) 63
Speculative Articulations - Navigating Junkspace
“Junkspace is fanatically maintained, the night shift undoing the damage of the day shift in an endless Sisyphean replay.� 64
Speculative Articulations - Navigating Junkspace
#old
#commercial
#hot #concrete
#dust #appartment blocks
#sunset strip #night #traffic
#airplane #aircraft #airport #plane
#social housing #pathetic #poor #wasteland
#production #industry #factory #dark #yellow
#transportation #jumbojet #boeing
#parking lot #cars #traffic
#colorful #pattern #abstract #tarmac
#deserted street #debris #ruin #waste
#grey #crowd #people
#mass #square
#trainstation #queue #usa #las vegas #billboard
#neonlight #costume #wasteland
#roads #traffic lights #dark #greenish #wet roads #highway #traffic
#cars
#usa #driving lane #traffic jam #congestion #factory #desert
Personal Perspective, formuated as Image Set equipped with Tags
To explore this idea in the context of our story, nine images of the Koyaanisqatsi movie formulate a personal perspective and are - equipped with tags - projected into the infinite in a quest to get back a reflection of all the other perspectives possible. To establish relationships between orphaned particles and therefore be able to navigate, to find our way around junkspace we utilize a self organizing map algorithm.
65
Speculative Articulations - Navigating Junkspace
“As you recover from Junkspace ...
66
Speculative Articulations - Navigating Junkspace
Personal Perspective, formuated as Image Set equipped with Tags
The self organizing map (SOM) - as a mechanism able to negotiate different natures without relying on the usage of preexisting connections - is able to adapt its connectivities and structure to the nature it is presented to, whatever it might be and by that manages to evocate new perspectives, new paths. The images, depicting our own, personal perspective, are used as samples to train a map of initially random image tags, derived from the Flickr API constituting a quasi infinitary source. The result is a reflection of our own perspective from all other perspectives that exist, by establishing relations we manage to navigate the “seamless patchwork of the permanently disjointed”10 creating meaning out of formerly unrelated “orphaned” entities.
10
Rem Koolhaas, Junkspace, October, Vol. 100, “Obsolescence” (MIT Press, 2002)
67
Speculative Articulations - Navigating Junkspace
... Junkspace recovers from you�
68
Speculative Articulations - The Intensity Veil
the intensity veil The final story is not about creating new artefacts but rather acts as a bridge, not using new movieframes but focusing on the negotiation of the first two stories and their outcomes, trying to reflect on the notion of texture, pattern and ornament and it’s significance for the creation of architecture. In “The Stones of Venice“, John Ruskin provides a description of the Mount Cervin (Matterhorn), according to “more valuable lessons being learned in the school of nature than in that of Vitruvius” with the Matterhorn being an illustrative feature of what he calls the “Wall Veil”. The rock is indeed hard beneath, but still disposed in thin courses of these cloven shales, so finely laid that they look in places more like a heap of crushed autumn leaves than a rock; and the first sensation is one of unmitigated surprise, as if the mountain were upheld by miracle; but surprise becomes more intelligent reverence for the great Builder, when we find, in the middle of the mass of these dead leaves, a course of living rock, of quartz as white as the snow that encircles it, and harder than a bed of steel.11 Ruskin apparently views the Matterhorn not as an unstructured accumulation of stones but considers it a duality of forces with geological articulation establishing structure on the
11
John Ruskin, The Stones of Venice (Da Capo Press, 2003)
75
Speculative Articulations - The Intensity Veil
The Matterhorn as painted by John Ruskin, 1849 source: https://www.artfund.org/what-to-see/exhibitions/2012/12/15/forces-of-nature-picturing-ruskins-landscape-exhibition
inside according to orientation and condition of the rocks and environmental conditions affecting the outside. ... but of thickness and strength continually varying, and with silver cornices glittering
along the edge of each, bid by the snowy winds and carved by the sunshine - stainless
ornaments of the eternal temple, by which “neither the hammer nor the axe, nor any
tool, was heard while it was in building.�12
12 ibid.
76
Speculative Articulations - The Intensity Veil
He draws a line between geometry as mass and surface as texture, with the inside being continously pushed outwards while at the same time being transformed by weathering eventually becoming the Wall Veil - an ornate surface, a texture showing incrustation, bearing and expressing internal characteristics to the outside. The veil therefore, is not merely a draping on the outside surface in the sense of textiles but exhibits an active relationship with the mountain’s mass, intertwining geometry and texture. A different take on texture and ornament can be found in Semper and his “Bekleidungsprinzip” and “Stoffwechselthese”: Ist nun ein Kunstmotiv durch irgendeine stoffliche Behandlung hin durch geführt worden, so wird sein ursprünglicher Typus durch sie modificirt worden sein, gleichsam eine bestimmte Färbung erhalten haben; der Typus steht nicht mehr” auf seiner primären Entwicklungsstufe, sondern eine mehr oder minder ausgesprochene Metamorphose ist mit ihm vorgegangen. Geht nun das Motiv aus dieser sekundären oder nach Umständen mehrfach graduirten Umbildung einen neuen Stoffwechsel ein, dann wird das sich daraus Gestaltende ein gemischtes Resultat sein, das den Urtyptus und alle Stufen seiner Umbildung die der letzten Gestaltung vorangingen in dieser ausspricht.13 Semper apparently also discusses design as occurring in transition, going from matter to
13
Gottfried Semper, Der Stil in den technischen und tektonischen Künsten (Verlag für Kunst und Wissenschaft, 1860) 77
Speculative Articulations - The Intensity Veil
form with the result being a composite of all the preliminary steps, although more on a technologogical level and more abstract: Die assyrische Skulptur hat sich offenbar innerhalb der Schranken bewegt, welche ihr durch ihren Ursprung vorgezeichnet waren, wenn auch der fremde Stoff neue Mittel des Heraushebens der Gegenstände aus dem Grunde gestattete.14 Understanding Sempers theory of “Stoffwechsel” as an abstract idea, a piece of code that through abstraction manages to be accomodated by different forms of media, makes it a very powerful and versatile concept. In the assyrian example above, the idea of an ornate piece of fabric is projected onto a solid piece of rock, inhabiting both the stone and the fabric, despite the technique of making is a fundamentally different one. The idea, the logic ceases to be attached to matter and becomes an agent for projecting material from one domain to another. Looking at Rukin and Sempers ideas on texture appears very interesting in the course of our storyline. In order to combine our SOM image with the geometrical artefact of the first story, we need some kind of mapping, a negotiation, a dialogue between geometry and image. One way would be to use a standard texture mapping technique, basically utilizing the image as a wallpaper and applying it to a surface, using a cubic projection. But that would hardly be a negotiation, more a kind of random drapery devoid of any exchange of information between image and geometry.
14 Gottfried Semper, Die Vier Elemente der Baukunst (Druck und Verlag von Friedrich Vieweg und Sohn, 1851) 78
Speculative Articulations - The Intensity Veil
UV Points in initial Position
In order to establish a dialogue with texture and geometry as our actors, we again make use of the “abstract power” of the SOM algorithm and it’s capabilities to create a climate to accomodate natures of different kind. By training the mapping coordinates of our geometry with values of a high contrast image of our soon to be texture, we are negotiating geometry and image, with the object’s uv coordinates continously transforming the placement of the image in a process of constant refinement. By that we eventually establish a two way communication between the geometry and our image which ultimately becomes texture - not unlike ruskin’s wall veil in being both drapery as it comes from the outside but at the same time an incrustation as it is informed by intensity values beeing intrinsic properties of geometry.
79
Speculative Articulations - The Intensity Veil
object space x,y,z saliency
find best match
image space x,y intensity
get UV Coords
original image
compare and adjust
parameter space u,v
contrast detection, tesselation
Diagram of the Mapping Process
The perception of the image changed - in a process of transition - from a simple wallpaper to becoming the surfaces’ texture. Speaking in the tone of Ruskin, it becomes an “Intensity Veil” or referring to Semper, by transferring the logic of negotiation by intensity from the selection of geometry to the configuration of uv coordinates and consequently the use of surface color it exhibits a kind of “Stoffwechsel”.
80
https://vimeo.com/179819727 - Sequence of the UV Coordinates trained by a SOM
Speculative Articulations - Remarks and Outlook
remarks and outlook Having conducted this research as thesis for my MAS studies in architecture, the artefacts created here - although being architectural objects - do not claim to be inhabitable structures in the sense of a traditional building, they rather are spatial dramatizations of synthesized stories, concieved of in a “theatrical” setting, becoming actors on a stage and interacting with each other according to a script. Circling around the premise that “the object of an idea is an object which can be neither given nor known but must be represented without being able to be directly determined“15 this project tries to explore the potential of the generation of architectural meaning by means of storytelling, trying to develope a design methodology by navigating and operating on the materiality of information, affirming discovery and chance encounters by relinquishing control and eventually transcending typologies. In terms of mechanism, the proposed voxel strategy seems to offer great potential and proved to be an excellent tool. As a means to non reductively abstract from geometry permitting any desired resolution up to a theoretical atom level, this concept becomes very powerful. The dutch 3d printing marketplace and service company „shapeways“ not too long ago, introduced the .svx format for directly uploading voxel files to use with their printing services. Looking at those files, they consist - much like in medical applications of multiple channels for a single voxel position, represented by a series of image slices and are organized by a simple .xml file.
15
Gilles Deleuze, Difference and Repetition (Columbia University Press, 1995)
89
Speculative Articulations - Remarks and Outlook
Using such a system, instances can be rendered directly from abstract space to a tangible fragment of reality, without the need for computationally expensive surface recreation and subsequent geometry slicing. Losing the constraints of meshing makes complexity almost come for free, enabling us to deal with high resolution detail and the possibility of material imposition not just on the object but on the voxel level, limited solely by the resolution of the printer. Looking at the way voxels are at work in medical applications, like ultrasound scans is particularly interesting with an architectural application in mind, as they capture separate channels of data relating to the same voxel position, essentially dissolving the conventional notion of materiality as materials cease to be attached to form. Materials can be synthesized on the conceptual stage, can be imposed on objects, on virtually any form and rendered to physical reality by means of 3d printing. The flexibility of multichannel systems also allows for custom IDs which would enable the use of smart voxels which, being prefabricated active components like sensors, transistors, photovoltaics and actuators, open the door to the fabrication of complex, functionally integrated systems.
90
Image Slices and XML file, derived from Voxelspace for 3d Printing
Speculative Articulations - The Script
the script The following provides insight into the coding part of the discussed concepts. For the sake of brevity, not the whole source code is covered here. A package containing all of the created applets, including modified libraries can be downloaded here: http://www.christophzechmeister.com/mas/masCode.zip
Voxelized Geometry
93
Speculative Articulations - The Script
coding steps the unfolding of space •
Calculating mesh saliency
•
Voxelizing input meshes
•
Morphing of voxelized meshes
•
Exporting voxel .txt viles
navigating junkspace •
Formulation of personal sample tags in relation to movie images
•
Training randomly retrieved tags from flickr with SOM
•
Blending and displaying image data from flickr according to result
the intensity veil •
Extracting samples from image
•
Training uv coordinates of geometry with image samples
•
Exporting geometry with new mapping coordinates
94
Speculative Articulations - The Script
package masSaliency; import import import import import import
processing.core.*; peasy.*; java.util.ArrayList; controlP5.*; masObjImporter.OBJImporter; masObjImporter.OBJPoint;
public class Main extends PApplet {
PeasyCam cam; OBJImporter importer; ImportCurvature curvature; SaliencyHandler salHandler; ArrayList<SalPoint> salPoints; ControlP5 cp5; Gui display;
// checkboxes boolean check1 boolean check2 boolean check3 boolean check4 boolean check5
float range = 1.5f;
CheckBox checkbox;
= = = = =
false; false; false; false; false;
public void setup() { size(1000, 800, P3D);
long startTime = System.nanoTime();
// GUI Stuff cam = new PeasyCam(this, 100); cp5 = new ControlP5(this); cp5.setAutoDraw(false); // Slider Slider s = cp5.addSlider(“range”); s.setPosition(100, 50); s.setRange(0.0f, 8f); s.setSize(300, 20); // Checkbox checkbox = cp5.addCheckBox(“checkBox”); checkbox.setPosition(100, 200); checkbox.setSize(40, 40); checkbox.addItem(“Saliency Map”, 1); checkbox.addItem(“Salient Mesh”, 2);
95
Speculative Articulations - The Script
checkbox.addItem(“Salient Vertices”, 3); checkbox.addItem(“Mean Curvature Map”, 4); checkbox.addItem(“Bounding Box”, 5);
importer = new OBJImporter(this, “P:\\MAS ETH AI\\Thesis\\Stories\\Unfolding Space\\ InputObjTestFiles\\duckyClean.obj”); salPoints = new ArrayList<SalPoint>(); createSalPoints(); curvature = new ImportCurvature(this, salPoints, “P:\\MAS ETH AI\\Thesis\\Stories\\Unfolding Space\\ CurvatureTestFiles\\cur_DuckyClean.txt”); salHandler = new SaliencyHandler(this, salPoints, “P:\\MAS ETH AI\\Thesis\\Stories\\Unfolding Space\\ SaliencyTestFiles\\sal_duckyClean.txt”);
println(“number of points: “ + importer.points.size());
display = new Gui(this, cam, cp5, importer, salPoints);
importer.createBoundingBox(); calculateSaliency(); salHandler.exportSal(); }
// Measure Time long timeNeeded = System.nanoTime() - startTime; println(“time needed “ + timeNeeded / 1000000000 + “ seconds”);
public void draw() { background(0); if (check1) display.displayColorFaces(range); if (check2) display.displayFaces(range); if (check3) display.displayPoints(range); if (check4) display.displayCurvatureFaces(); if (check5) importer.displayBoundingBox(); display.HUD(); display.drawGizmo(200f); }
public void controlEvent(ControlEvent theEvent) {
if (theEvent.isFrom(checkbox)) {
96
Speculative Articulations - The Script
if (checkbox.getArrayValue()[0] == 1) { check1 = true; println(“show Saliency Map”); } else { check1 = false; } if (checkbox.getArrayValue()[1] == 1) { check2 = true; println(“show salient Mesh”); } else { check2 = false; } if (checkbox.getArrayValue()[2] == 1) { check3 = true; println(“show salient Vertices”); } else { check3 = false; } if (checkbox.getArrayValue()[3] == 1) { check4 = true; println(“show Mean Curvature Map”); } else { check4 = false; } if (checkbox.getArrayValue()[4] == 1) { check5 = true; println(“show Bounding Box”); } else { check5 = false; } } }
public void createSalPoints() {
for (OBJPoint p : importer.points) { SalPoint s = new SalPoint(this, p.x, p.y, p.z, importer); salPoints.add(s); } }
public void calculateSaliency() {
for (SalPoint s : salPoints) { s.calculateSaliency(salPoints); } } public void keyPressed() { if (keyPressed) { if (key == ‘s’) {
97
Speculative Articulations - The Script
saveFrame(“P:\\MAS ETH AI\\Thesis\\Stories\\Unfolding Space\\ Production\\Saliency\\sal-####.jpg”); } } rect(25, 25, 50, 50); } } ////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////// package masSaliency; import import import import
java.util.ArrayList; java.util.Collections; masObjImporter.OBJImporter; processing.core.PApplet;
public class ImportCurvature {
PApplet parent; OBJImporter importer; ArrayList<Double> curvatureValues; ArrayList<SalPoint> salPoints; double minCurvature; double maxCurvature;
public ImportCurvature(PApplet _parent, ArrayList<SalPoint> _salPoints, String fileName) {
parent = _parent; salPoints = _salPoints; curvatureValues = new ArrayList<Double>(); String lines[] = parent.loadStrings(fileName);
parent.println(lines.length); parent.println(salPoints.size()); for (int i = 0; i < salPoints.size(); i++) { double value = Double.parseDouble(lines[i]); SalPoint p = salPoints.get(i); p.curvature = value; curvatureValues.add(value); }
maxCurvature = Collections.max(curvatureValues);
} } ////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////
98
Speculative Articulations - The Script
package masSaliency; import java.util.ArrayList; import org.apache.commons.math3.ml.distance.EuclideanDistance; import import import import
masObjImporter.OBJImporter; masObjImporter.OBJPoint; processing.core.PApplet; processing.core.PVector;
public class SalPoint extends OBJPoint {
PApplet parent; double curvature; OBJImporter importer; double[] myCoords; float epsilon; public float saliencyAggregation; PVector position;
public ArrayList<SalPoint> allPoints;
float x, y, z;
public SalPoint(PApplet _parent, float _x, float _y, float _z, OBJImporter _importer) {
super(_parent, _x, _y, _z, _importer);
importer = _importer; parent = _parent; x = _x; y = _y; z = _z;
myCoords = new double[3]; myCoords[0] = x; myCoords[1] = y; myCoords[2] = z;
}
position = new PVector(x, y, z);
public void display(float sliderValue) {
parent.pushMatrix(); parent.strokeWeight(2); parent.stroke(255, 0, 0); if (saliencyAggregation > sliderValue) { parent.point(x, y, z); }
99
Speculative Articulations - The Script
parent.popMatrix(); }
public float calculateSaliency(ArrayList<SalPoint> salPoints) {
float[] saliency = new float[5]; float sum; ArrayList<SalPoint> toInvestigate = new ArrayList<SalPoint>();
// get all other points allPoints = salPoints; epsilon = importer.diagonal * 0.003f;
// get points to investigate for (SalPoint p : allPoints) {
float distance = position.dist(p.position); float maxDistance = importer.diagonal / 15;
if (distance < maxDistance) toInvestigate.add(p); }
// loop through all points and calculate gaussian weighted average for (int i = 2; i < 6; i++) {
float sigma = i * epsilon; float doubleSigma = 2 * sigma; float[] scales = new float[2];
scales[0] = sigma; scales[1] = doubleSigma;
float[] gaussianWeightedAverage = new float[2];
for (int j = 0; j < scales.length; j++) {
float sumCurv = 0; float sumDist = 0; for (SalPoint p : toInvestigate) {
double[] otherCoords = new double[3]; otherCoords[0] = p.x; otherCoords[1] = p.y; otherCoords[2] = p.z; EuclideanDistance dist = new EuclideanDistance(); double euclDist = dist.compute(otherCoords, myCoords);
100
Speculative Articulations - The Script
PVector otherVertex = new PVector(p.x, p.y, p.z); PVector vertex = new PVector(x, y, z);
float euclideanDistance = vertex.dist(otherVertex);
sumCurv += p.curvature * parent .exp(((-1) * euclideanDistance * euclideanDistance) / (2* (scales[j] * scales[j]))); sumDist += parent.exp(((-1) * euclideanDistance* euclideanDistance) / 2 * (scales[j] * scales[j])); } }
gaussianWeightedAverage[j] = sumCurv / sumDist;
saliency[i - 2] = parent.abs(gaussianWeightedAverage[0] - gaussianWeightedAverage[1]); } sum = 0; for (int i = 0; i < saliency.length; i++) { sum += saliency[i]; } saliencyAggregation = sum / saliency.length; return saliencyAggregation; } } ////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////// package masSaliency; import java.io.PrintWriter; import java.util.ArrayList; import processing.core.PApplet; public class SaliencyHandler {
PApplet parent; String fileName; PrintWriter OUTPUT; ArrayList<SalPoint> salPoints;
public SaliencyHandler(PApplet _parent, ArrayList<SalPoint> _salPoints, String _ fileName) {
parent = _parent; fileName = _fileName; salPoints = _salPoints;
101
Speculative Articulations - The Script
}
public void importSal() {
String lines[] = parent.loadStrings(fileName);
for (int i = 0; i < lines.length; i++) { float value = Float.valueOf(lines[i]); SalPoint p = salPoints.get(i); p.saliencyAggregation = value; } parent.println(“points have been imported”); }
public void exportSal() {
OUTPUT = parent.createWriter(fileName);
for (SalPoint p : salPoints) { OUTPUT.println(p.saliencyAggregation); } OUTPUT.flush(); OUTPUT.close(); parent.println(“---”); parent.println(“points have been exported”); } } ////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////// package masSaliency; import java.util.ArrayList; import import import import import
controlP5.ControlP5; masObjImporter.OBJFace; masObjImporter.OBJImporter; peasy.PeasyCam; processing.core.PApplet;
public class Gui {
PApplet parent; PeasyCam cam; ControlP5 cp5; OBJImporter importer; ArrayList<SalPoint> salPoints;
public Gui(PApplet _parent, PeasyCam _cam, ControlP5 _cp5, OBJImporter _importer,
102
Speculative Articulations - The Script
ArrayList<SalPoint> _salPoints) { }
parent = _parent; cam = _cam; cp5 = _cp5; importer = _importer; salPoints = _salPoints;
public void HUD() {
// prevents peasyCam from rotating while using the slider if (cp5.controlWindow.isMouseOver()) { cam.setActive(false); } else { cam.setActive(true); } parent.hint(parent.DISABLE_DEPTH_TEST); cam.beginHUD(); cp5.draw(); cam.endHUD(); parent.hint(parent.ENABLE_DEPTH_TEST); } public void drawGizmo(float size) { // X axis parent.stroke(255, 0, 0); parent.line(0, 0, 0, size, 0, 0); // Y axis parent.stroke(0, 255, 0); parent.line(0, 0, 0, 0, size, 0); // Z axis parent.stroke(0, 0, 255); parent.line(0, 0, 0, 0, 0, size); }
public void displayColorFaces(float sliderValue) {
SalPoint vertex1, vertex2, vertex3;
for (OBJFace f : importer.faces) {
vertex1 = salPoints.get(Integer.parseInt(f.faceIndices[0]) - 1); vertex2 = salPoints.get(Integer.parseInt(f.faceIndices[1]) - 1); vertex3 = salPoints.get(Integer.parseInt(f.faceIndices[2]) - 1);
float sum = vertex1.saliencyAggregation + vertex2.saliencyAggregation + vertex3.saliencyAggregation; float avgSal = sum / 3; float myCol = parent.map(avgSal, importer.minSaliency, sliderValue, 0, 255);
103
Speculative Articulations - The Script
parent.pushMatrix(); parent.fill(myCol, 0, 0); parent.stroke(0); parent.strokeWeight(1); parent.beginShape(parent.TRIANGLES); parent.vertex(vertex1.x, vertex1.y, vertex1.z); parent.vertex(vertex2.x, vertex2.y, vertex2.z); parent.vertex(vertex3.x, vertex3.y, vertex3.z); parent.endShape(); parent.popMatrix(); } }
public void displayFaces(float sliderValue) {
SalPoint vertex1, vertex2, vertex3;
for (OBJFace f : importer.faces) {
vertex1 = salPoints.get(Integer.parseInt(f.faceIndices[0]) - 1); vertex2 = salPoints.get(Integer.parseInt(f.faceIndices[1]) - 1); vertex3 = salPoints.get(Integer.parseInt(f.faceIndices[2]) - 1);
if (vertex1.saliencyAggregation > sliderValue || vertex2. saliencyAggregation > sliderValue || vertex3.saliencyAggregation > sliderValue) { parent.pushMatrix(); parent.stroke(0); parent.fill(0, 255, 0); parent.strokeWeight(1); parent.beginShape(parent.TRIANGLES); parent.vertex(vertex1.x, vertex1.y, vertex1.z); parent.vertex(vertex2.x, vertex2.y, vertex2.z); parent.vertex(vertex3.x, vertex3.y, vertex3.z); parent.endShape(); parent.popMatrix(); } } }
public void displayPoints(float sliderValue) {
for (SalPoint p : salPoints) { p.display(sliderValue); } }
public void displayCurvatureFaces() {
SalPoint vertex1, vertex2, vertex3;
104
Speculative Articulations - The Script
for (OBJFace f : importer.faces) {
vertex1 = salPoints.get(Integer.parseInt(f.faceIndices[0]) - 1); vertex2 = salPoints.get(Integer.parseInt(f.faceIndices[1]) - 1); vertex3 = salPoints.get(Integer.parseInt(f.faceIndices[2]) - 1);
double curv1 = vertex1.curvature; double curv2 = vertex2.curvature; double curv3 = vertex3.curvature; double sum = Math.abs(curv1) + Math.abs(curv2) + Math.abs(curv3); double avgCurv = sum / 3; float myCol = parent.map((float) avgCurv, 0, 0.03f, 0, 255);
parent.pushMatrix(); parent.fill(0, 0, myCol); parent.stroke(0); parent.strokeWeight(1); parent.beginShape(parent.TRIANGLES); parent.vertex(vertex1.x, vertex1.y, vertex1.z); parent.vertex(vertex2.x, vertex2.y, vertex2.z); parent.vertex(vertex3.x, vertex3.y, vertex3.z); parent.endShape(); parent.popMatrix(); } } } ////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////// /* SCRIPT FOR VOXELIZING GEOMETRIES */ package masVoxelizer; import peasy.PeasyCam; import processing.core.PApplet; import toxi.geom.Vec3D; public class Main extends PApplet {
Voxelizer voxelMaker; PeasyCam cam;
public void setup() { size(900, 900, P3D); cam = new PeasyCam(this, 100);
String FileName = “intProspero”;
Vec3D min = new Vec3D(0, 0, 0);
105
Speculative Articulations - The Script
Vec3D max = new Vec3D(600, 600, 600); int resolution = 100;
voxelMaker = new Voxelizer(this, FileName, min, max, resolution); voxelMaker.importSaliency(); voxelMaker.voxelize(); voxelMaker.getSalBounds(); voxelMaker.export(); } public void draw() { background(0); voxelMaker.drawVoxels(); } public void drawGizmo(float size) { // X axis stroke(255, 0, 0); line(0, 0, 0, size, 0, 0); // Y axis stroke(0, 255, 0); line(0, 0, 0, 0, size, 0); // Z axis stroke(0, 0, 255); line(0, 0, 0, 0, 0, size); } } ////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////// package masVoxelizer; import import import import import import import import import import import import import
java.util.ArrayList; java.util.Arrays; java.util.Collections; java.util.List; masGenericFileHandler.FileHandler; masObjImporter.OBJFace; masObjImporter.OBJImporter; peasy.PeasyCam; processing.core.PApplet; processing.core.PImage; toxi.geom.*; toxi.geom.mesh.*; toxi.volume.*;
public class Voxelizer {
PApplet parent; OBJImporter importer;
106
Speculative Articulations - The Script
FileHandler salImporter; WETriangleMesh mesh; MeshVoxelizer voxelizer; FileHandler exporter; PImage img;
ArrayList<Vec3D> gridPoints; String[] saliencyValues; float[] salValues;
String fileName; int voxelCount; int resolution; float voxelSize; Vec3D min, max; float minSal, maxSal;
public Voxelizer(PApplet _parent, String _fileName, Vec3D _min, Vec3D _max, int _ resolution) {
parent = _parent; fileName = _fileName; min = _min; max = _max; resolution = _resolution;
// min and max vectors of voxelspace voxelCount = resolution * resolution * resolution; voxelSize = max.x / resolution;
// import gridPoints = new ArrayList<Vec3D>(); parent.println(“importing ...”); importer = new OBJImporter(parent, “P:\\MAS ETH AI\\Thesis\\Stories\\Unfolding Space\\ InputObjFiles\\” + “geo_” + fileName + “.obj”); mesh = new WETriangleMesh(); }
public void importSaliency() {
salImporter = new FileHandler(parent); saliencyValues = salImporter.importFile( “P:\\MAS ETH AI\\Thesis\\Stories\\Unfolding Space\\ SaliencyFiles\\sal_” + fileName + “.txt”); passFacesToToxicLibs(saliencyValues); }
public void passFacesToToxicLibs() {
// pass faces to toxiclibs TriangleMesh for (int i = 0; i < importer.faces.size(); i++) {
107
Speculative Articulations - The Script
OBJFace f = importer.faces.get(i); mesh.addFace(f.a, f.b, f.c); } }
public void passFacesToToxicLibs(String[] saliencyValues) {
// pass faces to toxiclibs TriangleMesh for (int i = 0; i < importer.faces.size(); i++) { OBJFace f = importer.faces.get(i); // get point indices from objface int idxA = f.vertexIdx1; int idxB = f.vertexIdx2; int idxC = f.vertexIdx3;
} }
// find corresponding sal values float salA = Float.parseFloat(saliencyValues[idxA]); float salB = Float.parseFloat(saliencyValues[idxB]); float salC = Float.parseFloat(saliencyValues[idxC]); // store saliency values in toxiclibs face mesh.addFace(f.a, f.b, f.c, salA, salB, salC);
public void voxelize() {
// voxelize voxelizer = new MeshVoxelizer(resolution); voxelizer.setWallThickness(1); VolumetricHashMap vol = voxelizer.voxelizeMesh(mesh, min, max); vol.closeSides(); // create VoxelGridPoints for (int z = 0; z < resolution; z++) { for (int y = 0; y < resolution; y++) { for (int x = 0; x < resolution; x++) { Vec3D p = new Vec3D(x * voxelSize, y * voxelSize, z * voxelSize); gridPoints.add(p); } } } }
public void getSalBounds() {
float[] sortSal = new float[voxelCount]; salValues = new float[voxelCount]; for (int i = 0; i < voxelCount; i++) { float val = voxelizer.avgSaliencyValues[i];
108
Speculative Articulations - The Script
salValues[i] = val; sortSal[i] = val; } Arrays.sort(sortSal);
minSal = sortSal[0]; maxSal = sortSal[sortSal.length - 1];
}
parent.println(“minimum Value is: “ + minSal); parent.println(“maximum Value is: “ + maxSal);
public void drawVoxels() {
for (int i = 0; i < gridPoints.size(); i++) { float voxelValue = voxelizer.volume.getVoxelAt(i); Vec3D p = gridPoints.get(i); float col = parent.map(salValues[i], minSal, maxSal, 0, 255);
if (voxelValue != 0) {
parent.pushMatrix(); parent.strokeWeight(2); parent.point(p.x, p.y, p.z); parent.stroke(255); parent.popMatrix(); } } }
public void export() {
String[] content = new String[voxelCount + 1]; content[0] = (int) voxelCount + “/” + (int) max.x + “/” + (int) resolution + “/” + minSal + “/” + maxSal; for (int i = 1; i < voxelCount + 1; i++) { float voxelValue = voxelizer.volume.getVoxelAt(i - 1); float saliencyValue = voxelizer.avgSaliencyValues[i - 1]; String s = voxelValue + “/” + saliencyValue; content[i] = s; } parent.println(“exporting ...”); exporter = new FileHandler(parent); exporter.exportFile( “P:\\MAS ETH AI\\Thesis\\Stories\\Unfolding Space\\ VoxelFiles\\” + fileName + “_VoxelValues.txt”, content);
109
Speculative Articulations - The Script
}
public void showVoxelSpace(Vec3D min, Vec3D max) {
parent.pushMatrix(); parent.noFill(); parent.strokeWeight(1); parent.stroke(0, 255, 0); parent.translate(min.x + max.x / 2, min.y + max.y / 2, min.z + max.z / 2); parent.box(max.x, max.y, max.z); parent.popMatrix(); }
public void plot2D() {
int X = 1000; int Y = 1000;
img = parent.createImage(X, Y, parent.RGB); img.loadPixels(); for (int i = 0; i < img.pixels.length; i++) { float voxelValue = voxelizer.volume.getVoxelAt(i); if (voxelValue == 1) { img.pixels[i] = parent.color(198, 22, 202); } else { img.pixels[i] = parent.color(77); } } img.updatePixels(); img.save(â&#x20AC;&#x153;P:\\MAS ETH AI\\Thesis\\Stories\\Unfolding Space\\data.jpgâ&#x20AC;?); }
public void drawVoxelGrid() {
for (int z = 0; z < resolution; z++) { for (int y = 0; y < resolution; y++) { for (int x = 0; x < resolution; x++) { parent.pushMatrix(); parent.translate(x * voxelSize + voxelSize / 2, y * voxelSize + voxelSize / 2, z * voxelSize + voxelSize / 2); parent.noFill(); parent.stroke(255, 20); parent.strokeWeight(1); parent.box(voxelSize); parent.popMatrix(); } }
110
Speculative Articulations - The Script
} } }
////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////// /* SCRIPT FOR MORPHING THE VOXELIZED GEOMETRIES */ package masMorpher; import import import import import import
processing.core.*; toxi.geom.Vec3D; java.io.File; java.util.ArrayList; masGenericFileHandler.FileHandler; peasy.*;
public class Main extends PApplet {
PeasyCam cam; SectionMorpher morphy; File folder; String[] filenames; String path;
ArrayList<Voxel> gridPoints; ArrayList<VoxelContainer> voxelFiles;
public void setup() { size(800, 800, P3D); cam = new PeasyCam(this, 100);
path = “P:\\MAS ETH AI\\Thesis\\Stories\\Unfolding Space\\VoxelFiles\\”; FileHandler importer = new FileHandler(this); voxelFiles = new ArrayList<VoxelContainer>();
folder = new File(path); filenames = folder.list();
for (int i = 0; i < filenames.length; i++) {
String[] data = importer.importFile(path + filenames[i]);
111
Speculative Articulations - The Script
VoxelContainer v = new VoxelContainer(this, data); voxelFiles.add(v); } createVoxelGrid(); morphy = new SectionMorpher(this, voxelFiles, gridPoints); morphy.showBlobs(); morphy.blobMorph(); morphy.isoSurface(); morphy.volumeBrush(); morphy.plot2D(); } public void draw() { background(0); drawGizmo(200); morphy.drawMesh(); }
public void createVoxelGrid() {
gridPoints = new VoxelContainer v int resolution = float voxelSize =
ArrayList<Voxel>(); = voxelFiles.get(0); v.getResolution(); v.getVoxelSize();
for (int z = 0; z < resolution; z++) { for (int y = 0; y < resolution; y++) { for (int x = 0; x < resolution; x++) { Voxel p = new Voxel(this, x * voxelSize, y * voxelSize, z * voxelSize); gridPoints.add(p); } } } } public void drawGizmo(float size) { // X axis stroke(255, 0, 0); line(0, 0, 0, size, 0, 0); // Y axis stroke(0, 255, 0); line(0, 0, 0, 0, size, 0); // Z axis stroke(0, 0, 255); line(0, 0, 0, 0, 0, size); }
public void keyPressed() {
112
Speculative Articulations - The Script
if (key == ‘s’) { saveFrame(“P:\\MAS ETH AI\\Thesis\\Stories\\Unfolding Space\\ voxelImages\\screenshot-######.jpg”); } } }
////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////// package masMorpher; import import import import import import import import import import
java.util.ArrayList; java.util.Collections; masObjImporter.OBJPoint; masSpatialRhythm.Blob; masSpatialRhythm.RhythmExtractor; processing.core.*; toxi.processing.*; toxi.geom.*; toxi.geom.mesh.*; toxi.volume.*;
public class SectionMorpher {
PApplet parent; PImage blendMap; PImage voxelImage; RhythmExtractor rhythm; WETriangleMesh isoMesh; ToxiclibsSupport gfx; ArrayList<VoxelContainer> voxelFiles; ArrayList<Voxel> gridPoints;
int resolution; int voxelCountTotal; float voxelSize; float minSal, maxSal;
public SectionMorpher(PApplet _parent, ArrayList<VoxelContainer> _voxelFiles, ArrayList<Voxel> _gridPoints) {
parent = _parent; voxelFiles = _voxelFiles; gridPoints = _gridPoints;
// get Infos on VoxelSpace VoxelContainer v = voxelFiles.get(0); resolution = v.getResolution();
113
Speculative Articulations - The Script
parent.println(“resolution is: “ + resolution);
voxelCountTotal = v.getVoxelCountTotal(); voxelSize = v.getVoxelSize();
// create RhythmExtractor rhythm = new RhythmExtractor(parent, resolution); gfx = new ToxiclibsSupport(parent); } public void blobMorph() {
// get min and max Saliencys
maxSal = voxelFiles.get(0).maxSal; minSal = voxelFiles.get(0).minSal;
for (VoxelContainer container : voxelFiles) { if (container.maxSal > maxSal) maxSal = container.maxSal; if (container.minSal < minSal) minSal = container.minSal; }
// calc averages over blob areas
for (Voxel v : gridPoints) { v.voxelValue = 0; }
ArrayList<Blob> blobs = rhythm.getBlobs();
for (VoxelContainer vC : voxelFiles) { vC.calculateBlobAverage(blobs, minSal, maxSal); }
for (int i = 0; i < blobs.size(); i++) {
Blob b = blobs.get(i);
VoxelContainer initialContainer = voxelFiles.get(0); float highScore = initialContainer.matches.get(0); int highIdx = 0; float matchSum = 0; float matchMappedSum = 0;
ArrayList<Float> scores = new ArrayList<Float>();
// get sum of matches (will likely be more than 100 % ); for (int j = 0; j < voxelFiles.size(); j++) {
VoxelContainer current = voxelFiles.get(j);
114
Speculative Articulations - The Script
float match = current.matches.get(i); matchSum += match; scores.add(match); }
// create wheel of fortune ArrayList<Integer> wheel = new ArrayList<Integer>();
for (int j = 0; j < voxelFiles.size(); j++) {
VoxelContainer current = voxelFiles.get(j); float match = current.matches.get(i); float matchMapped = parent.map(match, 0, matchSum, 0, 100); current.currentMatchMapped = matchMapped; matchMappedSum += matchMapped; parent.println(“matchmapped is: “ + matchMapped + “ for File “ + j); for (int k = 0; k < (int) matchMapped; k++) { wheel.add(j); } }
// make sure wheel is full, if not fill it with random voxel values if (wheel.size() < 100) {
int remains = 100 - wheel.size();
for (int j = 0; j < remains; j++) { wheel.add((int) parent.random(1)); } } parent.println(wheel.size());
// get the index of the winner int winner = wheel.get((int) parent.random(100));
// fill voxelGrid at blobPosition with winnervalues VoxelContainer winnerFile = voxelFiles.get(winner);
for (int j = 0; j < b.indicesScaled.size(); j++) {
int idx = b.indicesScaled.get(j); Voxel v = gridPoints.get(idx); v.voxelValue = winnerFile.voxelValues[idx]; } // contaminate scores.remove(winner); Collections.sort(scores);
115
Speculative Articulations - The Script
float matchWinner = winnerFile.matches.get(i); float error = 100 - matchWinner; float contamination = b.indicesScaled.size() / 100 * error; // divide error for other files - calculate contamination for (int j = 0; j < voxelFiles.size(); j++) {
VoxelContainer current = voxelFiles.get(j); float errorPercentage = parent.map(current.currentMatchMapped, 0, matchMappedSum, 0, 100); current.contamination = (int) (contamination / 100 * errorPercentage); }
// contaminate result with clipping masks and radius
for (int l = 0; l < voxelFiles.size(); l++) {
VoxelContainer current = voxelFiles.get(l);
int radius = current.contamination / 500; int amount = current.contamination / 10000 * 8;
for (int j = 0; j < amount; j++) {
int mappingCase = (int) parent.random(2); PImage contaminationMap = parent.loadImage( “P:\\MAS ETH AI\\Thesis\\Stories\\ Unfolding Space\\clippingmasks\\ contamination_” + l + “.jpg”); contaminationMap.loadPixels(); for (int z = 0; z < resolution; z++) { for (int y = 0; y < resolution; y++) { for (int x = 0; x < resolution; x++) { int posVoxel = 0; // get position in px array int posCol = z + (y * resolution); if (mappingCase == 0) { posVoxel = x + (z * resolution) + y * resolution * resolution; } if (mappingCase == 1) {
116
Speculative Articulations - The Script
posVoxel = z + (x * resolution) + y * resolution * resolution; } // sample the color float bright = parent. brightness(contaminationMap. pixels[posCol]); // store color Voxel v = gridPoints.get(posVoxel); v.brightness = bright; v.r = parent. red(contaminationMap. pixels[posCol]); v.g = parent. red(contaminationMap. pixels[posCol]); v.b = parent. red(contaminationMap. pixels[posCol]); } } } int randomIndex = b.indicesScaled.get((int) parent. random(b.indicesScaled.size())); Voxel randomVoxelSeed = gridPoints.get(randomIndex);
for (int idx : b.indicesScaled) {
Voxel v = gridPoints.get(idx); float dist = v.position.dist(randomVoxelSeed. position); if (dist < radius && v.brightness < 50) { v.voxelValue = current. voxelValues[idx]; } } } } } } public void showBlobs() { ArrayList<Blob> blobs = rhythm.getBlobs(); for (Blob b : blobs) { for (Integer i : b.indicesScaled) { Voxel v = gridPoints.get(i);
117
Speculative Articulations - The Script
v.voxelValue = 1; } } } public void showTheBlobs() { rhythm.drawBlobs(); }
public void displayVoxels() {
for (Voxel v : gridPoints) {
parent.pushMatrix(); if (v.voxelValue == 1) { parent.strokeWeight(10); parent.stroke(v.r, v.g, v.b); parent.point(v.x, v.y, v.z); } parent.popMatrix(); } }
public void displayVoxelGrid() {
for (Voxel v : gridPoints) {
parent.pushMatrix(); parent.translate(v.x, v.y, v.z); parent.stroke(0); parent.fill(v.r, v.g, v.b); parent.box(voxelSize); parent.popMatrix(); } }
public void isoSurface() {
VolumetricSpace vol = new VolumetricHashMap(new Vec3D(600, 600, 600), resolution, resolution, resolution, 3); int idx = 0; for (Voxel v : gridPoints) { vol.setVoxelAt(idx, v.voxelValue); idx++; } IsoSurface surface = new HashIsoSurface(vol); isoMesh = new WETriangleMesh(); surface.computeSurfaceMesh(isoMesh, 0.1f); isoMesh.computeVertexNormals(); isoMesh.saveAsSTL(“P:\\MAS ETH AI\\Thesis\\Stories\\Unfolding Space\\ objOutputFiles\\morphed_Output.stl”);
118
Speculative Articulations - The Script
}
public void volumeBrush() {
VolumetricSpace vol = new VolumetricHashMap(new Vec3D(600, 600, 600), resolution, resolution, resolution, 0.1f); VolumetricBrush brush = new RoundBrush(vol, voxelSize / 2); IsoSurface surface = new HashIsoSurface(vol); isoMesh = new WETriangleMesh(); for (int y = 0; y < resolution; y++) { for (int z = 0; z < resolution; z++) { for (int x = 0; x < resolution; x++) { int posVoxel = z + (y * resolution) + x * (resolution * resolution); Voxel v = gridPoints.get(posVoxel); if (v.voxelValue == 1) { brush.drawAtGridPos(z, y, x, 1); } } } } surface.reset(); surface.computeSurfaceMesh(isoMesh, 0.5f); isoMesh.computeVertexNormals(); isoMesh.saveAsSTL(“P:\\MAS ETH AI\\Thesis\\Stories\\Unfolding Space\\ objOutputFiles\\morphed_Output” + (int) parent.random(999) + “.stl”); }
public void plot2D() {
int X = 1800; int Y = 1800; voxelImage = parent.createImage(X, Y, parent.RGB); voxelImage.loadPixels(); for (int i = 0; i < voxelImage.pixels.length; i++) { float voxelValue = gridPoints.get(i).voxelValue; if (voxelValue == 1) { voxelImage.pixels[i] = parent.color(0); } else { voxelImage.pixels[i] = parent.color(255); } } voxelImage.updatePixels(); voxelImage.save(“P:\\MAS ETH AI\\Thesis\\Stories\\Unfolding Space\\ voxelImages\\data” + (int) parent.random(999) + “.jpg”);
119
Speculative Articulations - The Script
}
public void drawMesh() {
parent.stroke(0); parent.strokeWeight(1); parent.fill(255); gfx.mesh(isoMesh); } } ////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////// package masMorpher; import masObjImporter.OBJPoint; import processing.core.PApplet; import processing.core.PVector; public class Voxel extends OBJPoint {
public public public public public
float r, g, b; float grayScale; float saliency; PVector position; float brightness;
public Voxel(PApplet parent, float x, float y, float z) { super(parent, x, y, z); } }
position = new PVector(x, y, z);
////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////// package masMorpher; import import import import public
java.util.ArrayList; java.util.Arrays; masSpatialRhythm.Blob; processing.core.PApplet; class VoxelContainer { PApplet parent; ArrayList<Float> matches; String[] data; float[] voxelValues; float[] saliencyValues; float minSal, maxSal;
120
Speculative Articulations - The Script
int voxelCountTotal, voxelSpaceSize, resolution; int contamination; float currentMatchMapped;
public VoxelContainer(PApplet _parent, String[] _data) { parent = _parent; data = _data; parseData(); } public void parseData() {
String[] fileInfo = parent.splitTokens(data[0], “/”);
voxelCountTotal = Integer.parseInt(fileInfo[0]); voxelSpaceSize = Integer.parseInt(fileInfo[1]); resolution = Integer.parseInt(fileInfo[2]); minSal = Float.parseFloat(fileInfo[3]); maxSal = Float.parseFloat(fileInfo[4]);
voxelValues = new float[data.length - 1]; // minus 1 because of first Line with //FileInfos saliencyValues = new float[data.length - 1]; for (int i = 1; i < data.length - 1; i++) { String[] dataFields = parent.splitTokens(data[i], “/”); voxelValues[i] = Float.parseFloat(dataFields[0]); saliencyValues[i] = Float.parseFloat(dataFields[1]); } } public void calculateBlobAverage(ArrayList<Blob> blobs, float minSalTotal, float maxSalTotal) {
matches = new ArrayList<Float>();
int count = 0; float avgMapped; int countActive; for (Blob b : blobs) { int sum = 0; countActive = 0;
// get bounds of sal in blob float[] bounds = new float[b.indicesScaled.size()];
for (int i = 0; i < b.indicesScaled.size(); i++) {
int idx = b.indicesScaled.get(i); float sal = saliencyValues[idx]; bounds[i] = sal;
121
Speculative Articulations - The Script
float value = voxelValues[idx]; if (value == 1) {
countActive++; } } parent.println(“count for blob “+ count + “ is “+countActive); Arrays.sort(bounds); float blobMinSal = bounds[1]; float blobMaxSal = bounds[bounds.length - 2];
for (int i = 0; i < b.indicesScaled.size(); i++) {
int idx = b.indicesScaled.get(i); float sal = saliencyValues[idx]; sum += sal; }
float size = (float) b.indicesScaled.size(); float average = sum / size;
if (blobMinSal == 0 && blobMaxSal == 0) { avgMapped = 0; } else { avgMapped = parent.map(average, blobMinSal, blobMaxSal, 255, 0); } float deviation = Math.abs(b.intensity - avgMapped); float deviationPercentage = deviation * 100 / 255; if (deviationPercentage > 100) deviationPercentage = 100;
float match = 100 - deviationPercentage;
// multiply match with volumeweight float countActiveMapped = parent.map(countActive, 0, b.indicesScaled. size(), 0, 1); float matchWeight = match * countActiveMapped; matches.add(matchWeight); count++; } } public int getResolution() { return resolution; }
public float getVoxelSize() { float voxelSize = voxelSpaceSize / resolution;
122
Speculative Articulations - The Script
return voxelSize; } public int getVoxelCountTotal() { return voxelCountTotal; } } ////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////// package masMorpher; public class Color {
public float[] rgbValues;
public Color(float r, float g, float b) {
rgbValues = new float[3]; rgbValues[0] = r; rgbValues[1] = g; rgbValues[2] = b;
} } ////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////// package masSpatialRhythm; import processing.core.PApplet; public class Main extends PApplet { RhythmExtractor rhythm; public void setup(){ size(800, 800); int resolution = 500; rhythm = new RhythmExtractor(this, resolution); rhythm.createMap(); } public void draw(){ background(0);
123
Speculative Articulations - The Script
rhythm.drawBlobs(); } } ////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////// package masSpatialRhythm; import import import import
java.util.ArrayList; processing.core.PApplet; processing.core.PImage; processing.core.PVector;
public class Blob {
PApplet parent;
public float intensity; public ArrayList<Integer> indicesScaled;
int resolution; PImage img; PVector A, B, C, D; int idxA, idxB, idxC; int divisor;
float blobWidth, blobHeight, blobArea, biggestBlob;
/* A---------B | | | | | | C---------D */ public Blob(PApplet _parent, PImage _img, int _resolution, float _biggestBlob, PVector _A, PVector _B, PVector _C, PVector _D) {
parent = _parent; img = _img; resolution = _resolution;
parent.println(â&#x20AC;&#x153;resolution in blob is: â&#x20AC;&#x153; + resolution);
biggestBlob = _biggestBlob; A = _A; B = _B; C = _C; D = _D;
124
Speculative Articulations - The Script
indicesScaled = new ArrayList<Integer>(); blobWidth = B.dist(A); blobHeight = C.dist(A); blobArea = blobWidth * blobHeight;
measureIntensity(); scaleBlobs(); } public void measureIntensity() { int count = 0; for (int j = 0; j < (int) blobWidth; j++) { for (int k = 0; k < (int) blobHeight; k++) {
// PVector coords = blobPixelLocations[j]; int loc = (int) ((A.x + j) + ((A.y + k) * img.width));
float pixBrightness = parent.brightness(img.pixels[loc]);
// println(“brightness is: “+pixBrightness); if (pixBrightness > 10) { count++; // println(“brightness detected”); } } }
parent.println(“count is: “ + count); parent.println(“area is: “ + blobArea);
float percentage = count / blobArea * 100; parent.println(“percentage: “ + percentage);
float factor = parent.map(blobArea, 0, biggestBlob, 0, 1); float rawIntensity = percentage * factor; intensity = parent.map(rawIntensity, 0, 100, 255, 0);
} public void scaleBlobs() { // scale Blobs up to get rid of Gaps in 3D PVector extendedA, extendedB, extendedC, extendedD; float offset = 5; extendedA = new PVector(constrain(A.x-offset),constrain(A.y-offset)); extendedB = new PVector(constrain(B.x+offset),constrain(B.y-offset));
125
Speculative Articulations - The Script
extendedC = new PVector(constrain(C.x-offset),constrain(C.y+offset)); extendedD = new PVector(constrain(D.x+offset),constrain(D.y+offset)); parent.println(extendedA,extendedB, extendedC, extendedD); float float float resolution); float resolution);
extendedBlobWidth = extendedB.dist(extendedA); extendedBlobHeight = extendedC.dist(extendedA); widthScaled = parent.map(extendedBlobWidth, 0, img.width, 0, heightScaled = parent.map(extendedBlobHeight, 0, img.width, 0,
float posXScaled = parent.map(extendedA.x, 0, img.width, 0, resolution); float posYScaled = parent.map(extendedA.y, 0, img.width, 0, resolution); int posX = (int) posXScaled; int posY = (int) posYScaled;
for (int x = 0; x < (int) widthScaled; x++) { for (int y = 0; y < (int) heightScaled; y++) { for (int z = 0; z < resolution; z++) {
int loc2D = (posX + x) + ((posY + y) * resolution); int loc3D = loc2D + z * (resolution * resolution);
indicesScaled.add(loc3D); } } } } float constrain(float _value){ float value = _value; if (value < 0) value = 0; if (value > img.height) value = img.height; if (value > img.width) value = img.width; return value; } } ////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////
126
Speculative Articulations - The Script
package masSpatialRhythm; import java.util.ArrayList; import import import import
blobscanner.*; processing.core.PApplet; processing.core.PImage; processing.core.PVector;
public class RhythmExtractor {
PApplet parent;
Detector bs; PImage img; PImage imgFiltered; PImage intensityMap; int boundingBoxCol; int boundingBoxThickness; int numberOfBlobs; int resolution;
PVector aScaled; float bWidth; float bHeight;
ArrayList<Blob> blobs; PVector[] biggestBlobPixelLocations; PVector[] cornerA; PVector[] cornerB; PVector[] cornerC; PVector[] cornerD;
public RhythmExtractor(PApplet _parent, int _resolution) { parent = _parent; resolution = _resolution; imgFiltered = parent.loadImage(“P:\\MAS ETH AI\\Thesis\\Stories\\Unfolding Space\\InputFloorplans\\stepwellFloorplan.jpg”); imgFiltered.resize(parent.width, parent.height); imgFiltered.loadPixels(); img = parent.loadImage(“P:\\MAS ETH AI\\Thesis\\Stories\\Unfolding Space\\ InputFloorplans\\stepwellFloorplanAnalysis.jpg”); img.resize(parent.width, parent.height); img.loadPixels(); imgFiltered.filter(parent.THRESHOLD, .8f); analyze(); }
127
Speculative Articulations - The Script
public void analyze() {
blobs = new ArrayList<Blob>();
bs = new Detector(parent, 0); bs.imageFindBlobs(imgFiltered); bs.loadBlobsFeatures(); numberOfBlobs = bs.getBlobsNumber(); bs.weightBlobs(true);
cornerA cornerB cornerC cornerD
= = = =
bs.getA(); bs.getB(); bs.getC(); bs.getD();
parent.println(“got Vectors “ + cornerA.length);
boundingBoxCol = parent.color(255, 0, 0); boundingBoxThickness = 2;
// find biggest blob float biggestBlob = 0; int biggestIdx = 0;
for (int i = 0; i < numberOfBlobs; i++) {
PVector PVector PVector PVector
float blobWidth = B.dist(A); float blobHeight = C.dist(A); float area = blobWidth * blobHeight;
A B C D
= = = =
cornerA[i]; cornerB[i]; cornerC[i]; cornerD[i];
if (area > biggestBlob) { biggestBlob = area; biggestIdx = i; } } // create Blob Instances for (int i = 0; i < numberOfBlobs; i++) { Blob blobby = new Blob(parent, img, resolution, biggestBlob, cornerA[i], cornerB[i], cornerC[i], cornerD[i]); blobs.add(blobby); } }
public void createMap() {
intensityMap = parent.createImage(resolution, resolution, parent.RGB);
128
Speculative Articulations - The Script
intensityMap.loadPixels(); for (int i = 0; i < numberOfBlobs; i++) { Blob b = blobs.get(i); for (Integer idx : b.indicesScaled) { intensityMap.pixels[idx] = parent.color(255, 0, 0); } } intensityMap.updatePixels(); intensityMap.save(â&#x20AC;&#x153;P:\\MAS ETH AI\\Thesis\\Stories\\Unfolding Space\\maps\\ intensityMap.tifâ&#x20AC;?); } public void drawBlobs() { parent.image(intensityMap, 0, 0); } public ArrayList<Blob> getBlobs() { return blobs; } }
129
Speculative Articulations - The Script
130
Speculative Articulations - Bibliography
bibliography Vitruvius, The ten Books on Architecture (Morgan, 1914) Gilles Deleuze, Cinema 2 The Time Image (The Athlone Press, 1989) Gilles Deleuze, Felix Guattari, A Thousand Plateaus: Capitalism and Schizophrenia (University of Minnesota Press, 1987) Gilles Deleuze, Difference and Repetition (Columbia University Press, 1995) Louis Hjelmslev, Prolegomena to a Theory of Language (London, 1969) Maurice Merleau-Ponty, Phenomenology of Perception (The Humanities Press, 1962) Guy Debord, The Society of the Spectacle (Zone Books, 2006) Wilhelm Worringer, Abstraction and Empathy: A Contribution to the Psychology of Style (International Universities Press, 1967) Rem Koolhaas, Junkspace, October, Vol. 100, “Obsolescence” (MIT Press, 2002) John Ruskin, The Stones of Venice (Da Capo Press, 2003) Gottfried Semper, Der Stil in den technischen und tektonischen Künsten (Verlag für Kunst und Wissenschaft, 1860) Gottfried Semper, Die Vier Elemente der Baukunst (Druck und Verlag von Friedrich Vieweg und Sohn, 1851) Ludger Hovestadt, Vera Bühlmann, Eigen Architecture (Ambra, 2014) Rem Koolhaas, Bruce Mau, S M L XL (Monacelli Press, 1997) Vera Bühlmann, Ludger Hovestadt, Vahid Moosavi, Coding as Literacy (Birkhäuser, 2015)
131
Speculative Articulations - Bibliography
132
Chair for Computer Aided Architectural Design Departement for Architecture ETH ZĂźrich
Christoph Zechmeister