Page 1

rough on the top

Computation and aesthetics

decorate in the middle

Kao, Ting-chun portfolio 2008-2013 most elegant in the bottom


CONTENT Project

Coding Thesis Design The Digital Lamp of Architecture Page 24

Fishing Agents Mathematical Function Subdivision Church

Parametric

Nature System School Design

Handmade Sculpture

Page 36 Page 34

Coffee Shop

Page 42

Tool Developments

Logo Component for 3D Printing

Teamworks Projects Competitions

Museum Home for all

Page 38 Page 44

Workshops

ARM Theatre construction Factory Tenon house

Page 48

Fabrication

Page 50

In Charge

ETH Cupolas Material bending pavilion (Green Expo)

Page 2

Page 52


Personal Website +GENEATCG www.geneatcg.com

Page 2

Page 16

Page 20

Page 22

Page 40

Design

Artworks

Complexity from rules Magnify structure Boundary

Photos & Sketches

Travel & church research Life Sketches

Page 46

Work In Progress

Page 56

Interlocking Testing Material bending pavilion (Green Expo)

Appendix

Page 54

Personal info

Page 58

CV

Curriculum Vitae

Page 60

Code

Thesis Design

Scripting

Page 1


Coding Thesis Design The Digital Lamp of Architecture Special thanks to:

Advice: Chen-Cheng Chen Chi-Fu Hsiao Jared Counts Benjamin Dillenburger 3dPrinting & Video: Che-Wei Liu Shih-Yu Pan Yi-Chen Shih Szu-Hsuan Lee

Software:

Eclipse + Processing ZBrush + Maya meshlab netfabb 3D Printing

Page 2

Instructor:

Sheng-Ming Wu

Project type:

Personal project / Academy Thesis Design 2013

Reference:

John Ruskin’s “The Seven Lamps of Architecture” Gaudí’s Structuralism Jared Counts’ Curtain Coding Structure in BlueThen.com


Introduction The Digital Lamp of Architecture - A New Church Prototype In the past, human beings were known for having strong faiths and devoted minds. As a result, church architecture became the bridge between humans and the Creator, the sacred and the secular, as well as darkness and lightness. The best technology at the time was used to deeply affect believers, stimulating them with the powerful ambiance of church architecture, and allowing them to ultimately realize that men were as insignificant as a drop in the bucket. Referencing John Ruskin’s “The Seven Lamps of Architecture,” the most significant element of good architecture is the feature of sublimity. The same majestic grandness is also present in gothic architecture. By combining classical elements with modern computing technology, one can now capture features such as vastness of space, optimized structures and detailed ornamentations, while approaching them with a strong sense of beauty and aesthetics. In the Digital Lamp of Architecture - A New Church Prototype, Antoni Gaudî’s hanging chain methodology is implemented, updated and extended using computing technology. Multi-forces are used in the process of programming. These forces stretch more than one surface at a time and, as the programming process reaches an end, a sense of balance is achieved. At any time, these forces are stretching the surface in multiple locations until a sense of balance is achieved. This balance encompasses a dynamic display of uncertainty as well as physical rules that represent the religious and scientific system, ultimately combining both top-down and bottom-up approaches to architectural design. Page 3


Gaudi Structure Methodology & Ruskin’s Ornamentation criteria Modern and Classical Architectures are different in many aspects. The two most significant aspects are surface and structural system. Most Architecture after modernism has been pursuing purism, focusing on functionality and efficiency. During this time, ornamentation was widely considered unimportant and secondary, sometimes even regarded sinful. Unlike contemporary architecture, my thesis uses computing methods to redefine classical architecture through the re-design of ornamental surface and structural system. Computing system is based on physical simulation, such as particle-string system and cloth simulation, and implements code interpretation of ornamental graphics and surfaces. The final goal is to use soft material to construct the architectural structure and ornamentation. This thesis is separated into three parts: 1. The Seven Lamps of Architecture and its theory development. 2. Computing simulation . 3. Physical model.

Structure

Structure Model made by Gaudi

Ornamentation

John Ruskin Ornamentation Page 4

Molding test using soft material


Fabric simulation using Processing programming language

Plaster model casting for the ornamentation surface

Plaster model without structural implement Page 5


Plaster Model Machine Easy to assemble, easy to reuse

Machine

Structure + Ornamentation

One quick trial: result number 1

Page 6

Different positioning of holes create different forces and patterns on the fabric


One quick trial: result number 2

Simulation programming In the plaster casting model, surfaces are shaped by creating grids and attaching points with one another. By using various cloth materials the structure will be slightly different every time. The softer the cloth, the more structure phenomena occur. These processes are similar to the process Antoni Gaudi used. The hanging model creates smart geometry that once the computer finishes its calculation, the cloth will turn into a sculpture and decorate the space. In the simulation program, each point weight can be differently from one another. Furthermore, GUI is designed for communication between top-down and bottom-up approach, so users can control unpredictable outcomes through experiments. Now using this new system, structure simulation and ornamentation can be created in the same approach at the same time.

Page 7


Final software with GUI

Slider Bar Contorling GUI

Top View

A brief testing of church nave part using fabric simulation

Page 8

Perspective

Crossing and Narthex part simulated by program


m

Surface Testing physical model

Surface Testing computation model - Mapping painting as stitching points.

Page 9


Final model generated separately in different parts Surface on the top are more roughly decorated, these elements include twist columns and pattern mosaic, but with more opening to improve the light of crossing

Tower: top Results

Process

Page 10

Surface in the middle are usually settled with statues. Choir on the top can improve the overall acoustics and service feeling

Tower: middle Choir

Surface at the bottom usually has the most elegant moldings, because they are closest to eyes

Tower: bottom


Iconostasis, where pastor give messages This underground is directly connected a sacred water source where Christians can be baptized.

Crossing & Baptize Area

Entrance from the land Chevet as a praying area on Sea

Aisle and nave can determine the deep of the church

Entrance & Chevet

Aisle and Nave

Page 11


Digital Architecture is often criticized for its form manipulation. Through 3D software, designers can always create any form they want, even forms that cannot be designed by hand. However, as boundless as it may seem, everything has its limitation, even Digital Architecture itself. What Digital Architecture needs is a personal Bible to follow with, a solid rock to construct its tenets on. Ruskin’s “the Seven Lamps of Architecture” is a prime example of such theory; it is a classic that has endured through time; and even though the world changes and the technology changes, “the Seven Lamps of Architecture” has always remained faithful to good architecture in its spirit. In his own book, “The Seven Lamps of the Architecture,” Ruskin mention architecture should achieve at lest some points in seven elements; Devotion, Truth, Power, Beauty, Life, Memory and Obedience .

Rendering Location: Nave - the middle and the main part of the church. Normally determine the deep of space.

Page 12


Page 13


3D Print Final Model Duration: 24Hours * 7 days. (The first UP! Plus machine was used to print model from the beginning. Then the second UP! Plus was involved in productions) Separated Pieces: 84 parts.

Final Model: A section model that can be separated into two parts. Page 14


Page 15


Coding Flocking Agent Reference:

plethora-project.com

Project type: Personal coding / For Fun 3D / Processing / Simulation 2012

Flocking Agent is based on three rules: 1. Separation 2. Alignment 3. Cohesion

Page 16


DrawLineFish3D import import import import

toxi.geom.*; processing.opengl.*; peasy.*; controlP5.*;

Manage man; PeasyCam jCam; ControlP5 jControl;

Fish(Vec3D loc, int num) { }

void run() {

ArrayList fishes; PMatrix3D currCameraMatrix; PGraphics3D g3; int c1 = 0; int c2 = 0; int c3 = 0; boolean attractor = false; boolean stop = false; void setup() {

}

size(1200, 800, P3D); smooth(); g3 = (PGraphics3D)g; jCam = new PeasyCam(this, 100); Slider(); man = new Manage(400, 50); man.createFish();

void draw() {

}

}

displayTail(); display(); turnback(); flock();

void initial() {

}

for (int x[i] = y[i] = z[i] = }

i = 0; i < 1000; i++) { loc.x; loc.y; loc.z;

void display() { strokeWeight(7); stroke(155, 25, 25, 220); point(loc.x, loc.y, loc.z); strokeWeight(15); stroke(155, 25, 25); if (attractor == true) { stroke(100, 200); strokeWeight(20); }

background(240); }

displayTail(); display(); swim(); turnback(); flock(); lineBetween();

void run2() {

if (jControl.window(this).isMouseOver()) { jCam.setActive(false); } else { jCam.setActive(true); } man.display(); gui();

this.loc = loc; this.num = num;

}

point(c1, c2, c3);

void displayTail() { Fish class Fish { Vec3D loc; Vec3D speed = new Vec3D(random(-2, 2), random(-2, 2), random(-2,2)); Vec3D acc = new Vec3D(); int num = 1000; float[] x = new float[num]; float[] y = new float[num]; float[] z = new float[num]; int indexPosition = 0;

if (stop == false) { x[indexPosition] = loc.x; y[indexPosition] = loc.y; z[indexPosition] = loc.z; indexPosition = (indexPosition + 1) % num; } for (int i = 20; i < num; i++) { int pos = (indexPosition + i) % num; int posb = (indexPosition + (i-10)) % num; if (i%10 == 1) { stroke(0, 110); Page 17


}

} }

strokeWeight(3); point(x[pos], y[pos], z[pos]); stroke(100, 100); strokeWeight(1); line(x[pos], y[pos], z[pos], x[posb], y[posb], z[posb]);

void swim() {

}

speed.addSelf(acc); speed.limit(2); loc.addSelf(speed); acc.clear();

void turnback() {

}

void setVel(Vec3D vel) { }

void setAcc(Vec3D acc) { }

}

}

Vec3D steer = new Vec3D(); int count = 0; for (int i = 0; i < fishes.size(); i++) { Fish other = (Fish) fishes.get(i); float distance = loc.distanceTo(other.loc); if (distance > 0 && distance < 40) { steer.addSelf(other.speed); count++; } } if (count > 0) { steer.scaleSelf(1.0/count); }

stroke(100); strokeWeight(1); noFill(); box(400);

return loc.x;

}

steer.scaleSelf(magnitude); acc.addSelf(steer);

void cohesion(float magnitude) { Vec3D sum = new Vec3D(); int count = 0;

float getLocY() { }

separate(4); cohesion(0.001); align(0.1);

void align(float magnitude) {

if (loc.x > 200 || loc.x < -200) { speed.x *= -1.5; } if (loc.y > 200 || loc.y < -200) { speed.y *= -1.5; } if ((loc.z > 200) || (loc.z < -200)) { speed.z *= -1.5; }

float getLocX() {

this.acc = acc;

void flock() {

void fishbox() {

}

this.speed = speed;

for (int i = 0; i < fishes.size(); i++) {

return loc.y;

Fish other = (Fish) fishes.get(i); float distance = loc.distanceTo(other.loc);

Vec3D getVel() { }

return speed;

if (distance > 0 && distance < 60) {

Vec3D getAcc() { return acc; }

}

Vec3D getLoc() { }

if (count > 0) { sum.scaleSelf(1.0/count); }

return loc;

void setLoc(Vec3D loc) { } Page 18

this.loc = loc;

}

sum.addSelf(other.loc); count++;

}

Vec3D steer = sum.sub(loc); steer.scaleSelf(magnitude); acc.addSelf(steer);


random(-200, Vec3D vel = new Vec3D(random(-0.2, random(-0.2, random(-0.2,

void separate(float maganitude) { Vec3D steer = new Vec3D(); int count = 0; for (int i = 0; i < fishes.size(); i++) { Fish other = (Fish) fishes.get(i); float distance = loc.distanceTo(other.loc); if (distance > 0 && distance < 30) { Vec3D diff = loc.sub(other.loc); diff.normalizeTo(1.0/distance); steer.addSelf(diff); count++; } } if (count > 0) { steer.scaleSelf(1.0/count); } }

steer.scaleSelf(maganitude); acc.addSelf(steer);

void lineBetween() {

}

}

for (int i = 0; i < fishes.size(); i++) { Fish other = (Fish) fishes.get(i); float distance = loc.distanceTo(other.loc); if (distance > 0 && distance < 80) { stroke(200, 100); strokeWeight(0.1); line(loc.x, loc.y, loc.z,other.loc.x, other.loc.y, other.loc.z); } }

200)); 0.2), 0.2), 0.2));

Vec3D acc = new Vec3D(0, 0, 0); Fish myfish = new Fish(loc, tail); fishes.add(myfish);

}

} for (int i = 0; i < fishes.size(); i++) { Fish a = (Fish)fishes.get(i); a.initial(); }

void display() { myfish.fishbox(); for (int i = 0; i < fishes.size(); i++) { Fish myfish = (Fish) fishes.get(i); if (attractor == true) { Vec3D m = new Vec3D(c1, c2, c3); Vec3D diff = m.subSelf(myfish.getLoc()); Vec3D velPlus = diff.addSelf(myfish.getVel()); Vec3D accPlus = velPlus.addSelf(myfish.getAcc()); accPlus.normalizeTo(0.1); myfish.setAcc(diff); } if (stop == false) { myfish.run(); } else { myfish.run2(); } } } }

Manage

Slider

class Manage {

void Slider() { jControl = new ControlP5(this); jControl.addSlider("c1", -200,200,10,610,100,10); jControl.addSlider("c2", -200,200,10,630,100,10); jControl.addSlider("c3", -200,200,10,650,100,10); jControl.addToggle("attractor", false, 10, 680, 100, 10) .setMode(ControlP5.SWITCH); jControl.addToggle("stop", false, 10, 715, 45, 10); jControl.setAutoDraw(false); }

Vec3D loc; Vec3D vel; Vec3D acc; int tail; Fish myfish = new Fish(loc, tail); int num; Manage(int num, int tail) {

}

this.tail = tail; this.num = num; fishes = new ArrayList();

void createFish() { for (int i = 0; i < num; i++) { Vec3D loc = new Vec3D(random(-200, 200), random(-200, 200),

void gui() { currCameraMatrix =

}

new PMatrix3D(g3.camera); camera(); jControl.draw(); g3.camera = currCameraMatrix; Page 19


Coding Mathematical Function Project type: Personal coding / For Fun 3D / Processing / Mathematical Function 2012

int t = 0; float z; void setup() {   size(650, 450,P2D);   smooth();   noStroke(); }  void draw() {   background(200);   for (int i = 10; i < width; i+= 10) {     for (int j = 10; j < height; j+= 10 { float x = i/10;       float y = j/10;           float d = dist(mouseX/10, mouseY/10, x, y); z = cos(d - 0.2*t);       ellipse(i, j, 10*z, 10*z);     }   }   t++; }

Wave A Cosine Function is used in this small program. d = the distance between our mouse position and all points (grid). The radius of ellipse is positive with Cos(d). In the End, “t” is used as time parameter. Page 20


SineWave import toxi.geom.*; import toxi.geom.mesh.*; import toxi.volume.*; import toxi.processing.*; import processing.opengl.*; import peasy.*; ArrayList ballCollection; int DIMX=10; int DIMY=10; int DIMZ=10; float ISO_THRESHOLD = 0.1; float NS=0.035; Vec3D SCALE=new Vec3D(1, 1, 1).scaleSelf(300); boolean isWireframe=false; VolumetricSpaceArray volume=new VolumetricSpaceArray(SCALE, DIMX, DIMY, DIMZ); IsoSurface surface=new ArrayIsoSurface(volume); TriangleMesh mesh; ToxiclibsSupport gfx; PeasyCam jCam; Matrix env = new Matrix(); void setup() { size(1024, 576, OPENGL); jCam = new PeasyCam(this, 100); noFill(); strokeWeight(0.5); stroke(255); gfx=new ToxiclibsSupport(this); ballCollection = new ArrayList(); for (int i = 0; i < 50; i++) { Vec3D origin = new Vec3D(random(-150, 150), random(-150, 150), random(-150, 150)); } } void draw() {

}

float[] volumeData=volume.getData(); for (int i = 0; i < DIMX*DIMY*DIMZ-3; i++) volumeData[i] = sin(frameCount*i*0.0003); background(220); volume.closeSides(); surface.reset(); mesh=(TriangleMesh)surface.computeSurfaceMesh(mesh, ISO_THRESHOLD); stroke(255); strokeWeight(1); box(330); fill(167, 0, 62, 150); gfx.mesh(mesh, true); noFill();

class Matrix { void run() { matrix(); }

}

void matrix() { stroke(255); for (int z = -150, index = 0; z <= 150; z+=30) for (int y = -150; y <= 150; y+=30) for (int x = -150; x <= 150; x+=30) { point(x, y, z); } } Page 21


Coding Subdivision Church Project type: Personal coding / For Fun 3D / Processing / Mathematical Function 2012

Church import processing.opengl.*; import peasy.*; import toxi.geom.*; PeasyCam cam; Face subFace; void setup() { size(1200, 800, OPENGL); cam = new PeasyCam(this, 600); int int int int

Subdivision Subdivision is a kind of recursive drawing. Church created by subdivision using noise value as its height value in the each point. Page 22

}

x0 x1 y0 y1

Vec3D a Vec3D b Vec3D c Vec3D d subFace

= = = = = = = = =

-100; 100; 400; 100; new new new new new

Vec3D(x0, y0, Vec3D(x1, y0, Vec3D(x1, y1, Vec3D(x1, y1, Face(a, b, c,

0); 0); 0); 0); d);


void draw() { background(220); subFace.run(); }

Vec3D mdPt(Vec3D v1, Vec3D v2) { Vec3D md1 = v2.sub(v1); md1.scaleSelf(1.0/2); md1.addSelf(v1); return md1; }

Face

Vec3D mdPtUP(Vec3D v1, Vec3D v2, Vec3D v, float sca) { Vec3D md1 = mdPt(v1, v2); Vec3D mdPtUP = v.copy(); mdPtUP.scaleSelf(sca); mdPtUP.addSelf(md1); return mdPtUP; }

class Face { Vec3D a; Vec3D b; Vec3D c; Vec3D d; Face(Vec3D a, Vec3D b, Vec3D c, Vec3D d) { this.a = a; this.b = b; this.c = c; this.d = d; } void run() { iterate(a, b, c, d, 5); displayPlan(a, b, c, d); }

float calcLen(Vec3D v1, Vec3D v2, Vec3D v3, Vec3D v4){ Vec3D dif1 = v1.sub(v2); Vec3D dif2 = v2.sub(v3); Vec3D dif3 = v3.sub(v4); Vec3D dif4 = v4.sub(v1); float len = dif1.magnitude() + dif2.magnitude() + dif3.magnitude() + dif4.magnitude(); return len; }

void iterate(Vec3D v1, Vec3D v2, Vec3D v3, Vec3D v4, int gens){ Vec3D cen = calcCentroid2(v1, v2, v3, v4); Vec3D nor = calcNormal(v1, v2, v3, v4); float len = calcLen(v1, v2, v3, v4); Vec3D dispPt = drawVector(cen, nor, len/50); Vec3D exZ = new Vec3D(0, 0, 4); Vec3D md1 = mdPtUP(v1, v2, exZ, len/30); Vec3D md2 = mdPtUP(v2, v3, exZ, len/30); Vec3D md3 = mdPtUP(v3, v4, exZ, len/15); Vec3D md4 = mdPtUP(v4, v1, exZ, len/30); if (gens == 0) { display(v1, v2, v3, v4); }

}

if (gens > 0) iterate(v1, iterate(v2, iterate(v3, iterate(v4, }

{ md1, md2, md3, md4,

dispPt, dispPt, dispPt, dispPt,

md4, md1, md2, md3,

gens-1); gens-1); gens-1); gens-1);

Vec3D calcCentroid2(Vec3D v1, Vec3D v2, Vec3D v3, Vec3D v4) { Vec3D md1 = mdPt(v1, v2); Vec3D md2 = mdPt(v2, v3); Vec3D md3 = mdPt(v3, v4); Vec3D md4 = mdPt(v4, v1); Vec3D sum = new Vec3D();

}

sum.addSelf(md1); sum.addSelf(md2); sum.addSelf(md3); sum.addSelf(md4); sum.scaleSelf(1.0/4.0); return sum;

}

Vec3D drawVector(Vec3D p, Vec3D v, float sca) { Vec3D vec = v.copy(); vec.scaleSelf(sca); vec.addSelf(p); return vec; } Vec3D calcNormal(Vec3D v1, Vec3D v2, Vec3D v3, Vec3D v4) { Vec3D dif1 = v4.sub(v2); Vec3D dif2 = v3.sub(v1); Vec3D cros = dif2.cross(dif1); cros.normalize(); return cros; } void display(Vec3D v1, Vec3D v2, Vec3D v3, Vec3D v4) { stroke(255, 90); fill(0, 82, 167, 80); beginShape(QUADS); vex(v1); vex(v2); vex(v3); vex(v4); vex(v1); endShape(); } void vex(Vec3D v) { vertex(v.x, v.y, v.z); } void displayPlan(Vec3D a, Vec3D b, Vec3D c, Vec3D d) { stroke(250); line(a.x, a.y, a.z, b.x, b.y, b.z); line(b.x, b.y, b.z, c.x, c.y, c.z); line(c.x, c.y, c.z, d.x, d.y, d.z); line(d.x, d.y, d.z, a.x, a.y, a.z); } Page 23


Project Nature System Instructor:

Chen-Cheng Chen

Project type: Personal project / Academy / Parametric / Fabrication Fourth year Studio 2011

Nature system is separated into three parts. Step 1: 4 conceptual model i. pupa ii. ant nest iii. honey comb iv. spider web Step 2: Fabricating conceptional model using popular digital fabrication methods like staking, slicing, and reassembling. Step 3: Applying natural methodology into four conceptional ideas and to form a space design.

Page 24


pupa

ant nest

honeycomb

web

Page 25


Minimal Surface Method

The best way to find symmetric surface is to find the geometric centre and connect the corner to the surface centre. The diagram on the right shows how to create the definition between formal geometry boxes. However, this usage can not only be applied to symmetric shape but also to organic brep boxes. Using this method, many three Dimensional spaces can quickly and easily be generated. The minimal surface can be created through any closing geometry.

Page 26


Page 27


Page 28


Honeycomb geometry can normally be noticed through its facade 2d geometries. Using fishing houses as our working spaces, my design used inflatable materials and careful manipulation to design movable housing for the poor. The diagram on the left hows the typology and morphology in parametric methods.

Page 29


Minimal Surface Church In this project minimal surface was implemented into several bounding box system. So by adjusting boxes patterns, the outcome will c`hange at the same time.

Top & Perspective

Page 30


Page 31


Page 32


Page 33


Project Campus Design Instructor:

Chow-Ying Chen

Project type: Personal project / Academy / Parametric / Architecture Site: Sanxia District Fourth year Studio 2011

Page 34


The site is located just beside two high way roads, so the most important problem in this project was to reduce the noise pollution. Being an architect, we can use space to effectively influence student study habits in our buildings. Thus, we can provide student with a better learning environment so they can educate themselves. My design strategy is to create a double hyperbola wall first, in order to reflect all noise. I then organized all the different kinds of curriculums; putting the same type class together and opposite types farther away. In considering many kinds of factors, I decided to use a computing method to assist me with these problems. For example, I used the computer to calculate the total floor are and based on the same floor areas, I strategically designed spaces that triggered student communicated during class breaks, because I think interaction during break time is more important than active participation in class. So in this project, I was trying to use a simple way of calculation to define many basic problems more clearly. We can simply use this kind of calculation to effectively design better architecture.

Page 35


Project Coffee Shop Instructor:

Deng-Gui Yang

Project type: Personal project / Academy / Hnadmade/ Handrendering / Architecture Site: Dihua Street n.127 2nd year Studio 2009 2011 This shop is located on the famous Dihua Street where we usually buy things for Chinese New Year. The concept was based on the commercial system in Dihua Street, using two kinds of coffee beans from nature, Using two kinds of coffee beans, peaberry and flat beans, I want to create a â&#x20AC;&#x153;bean space.â&#x20AC;? By entering the bean space, my intention was to allow the customers to experience a different atmosphere as compared to the outside.

hand drawing with color pencel Page 36

handmade plaster model


Page 37


Tool Developments LEGO Component for 3D Printing Project type: For Fun / 3D Printing / Coding / LEGO component 2013

Taking Time: One night

Page 38


import rhinoscriptsyntax as rs objSelect = rs.GetObject("Object", 16) faces = rs.ExplodePolysurfaces(objSelect) faceSelect = rs.GetObject("face", 8, rs.filter.surface) border = rs.DuplicateSurfaceBorder(faceSelect) borderLines = rs.ExplodeCurves(border, True) U = rs.GetObject("UV select_U", 4) V = rs.GetObject("UV select_v", 4) uLen = rs.CurveLength(U) vLen = rs.CurveLength(V) udomain = rs.SurfaceDomain(faceSelect, 0) vdomain = rs.SurfaceDomain(faceSelect, 1) head = [] rs.EnableRedraw(False) u = udomain[0]+4 while u<=udomain[1]-2.75: v = vdomain[0]+4 while v<=vdomain[1]-2.75: pt = rs.EvaluateSurface(faceSelect, u, v) if rs.Distance(pt, rs.BrepClosestPoint(faceSelect, pt)[0])<0.1: srf_frame = rs.SurfaceFrame(faceSelect, [u, v]) circle = rs.AddCircle(srf_frame, 2.45) head.append(circle) v+=8 u+=8 UendPt = rs.CurveEndPoint(U) UStPt = rs.CurveStartPoint(U) UVector = rs.VectorCreate(UendPt, UStPt) VendPt = rs.CurveEndPoint(V) VStPt = rs.CurveStartPoint(V) VVector = rs.VectorCreate(VendPt, VStPt) path = rs.VectorUnitize(rs.VectorCrossProduct(UVector, VVector)) extrudeFace = [] cut = rs.AddLine( [0, 0 ,0 ], [ path[0]*1.7, path[1]*1.7, path[2]*1.7 ]

for i in range(len(head)): cutter = rs.ExtrudeCurve(head[i], cut) rs.MoveObject(cutter, [ -path[0]*1.7, -path[1]*1.7, -path[2]*1.7 ] ) extrudeFace.append(cutter) f = rs.TrimBrep(faceSelect, cutter)

)

body = rs.JoinSurfaces(faces, f) extrudeFace.append(body) preFinal = rs.JoinSurfaces(extrudeFace) rs.CapPlanarHoles(preFinal) rs.DeleteObjects(faces) rs.DeleteObjects(border) rs.DeleteObject(f) rs.DeleteObject(body) rs.DeleteObject(cut) rs.DeleteObjects(circle) rs.DeleteObjects(objSelect) rs.DeleteObjects(borderLines) for j in range(len(extrudeFace)): rs.DeleteObject(extrudeFace[j]) for k in range(len(head)): rs.DeleteObject(head[k]) rs.EnableRedraw(True) Page 39


Design Complexity from Basic Rules Instructor:

Shung-Chung Wu

Project type: Personal project / Academy / Creation / Artworks / handmade / hand drawing/ Freshman year 2008

The technical drawing above, named “Heart Beating,” consists of several circles. When those circles interact with each other, it becomes with a ripple-like effect, visually influencing observers and arousing dizzy and echo-like feelings. Along the lines of the visual effect idea, in the project on the right, I tried hard to test the friction, force and arrangements between wood sticks. Whenever I push the sticks below, the above components will also be moved by friction between them and will also be controlled. So basically, it just like swarm system, we control and define the relationship between one unit and the other. Sometimes we don’t know what will the final result will be, but sometimes, if we lucky or smart enough, we can find out a good way to define the rules between small units and from the button-up and the result can be predict in someway. Both projects were done using the same design strategy, which comes from basic components and finally causes purity, simplicity and some complexity.

Page 40


Page 41


Design Magnify the Object Instructor:

Shung-Ching Wu / Dpc Lee

Project type: Personal project / Academy / Creation / Artworks / handmade / hand drawing/ Freshman year 2008 / 2009

In the project â&#x20AC;&#x153;Magnify the Objectâ&#x20AC;&#x153;, the possibilities of scaling, magnifying and representing small objects has been discussed then turned into architectural scale. The goal of this practice is to carefully balance aesthetics and structure. The foam board was used as the main project material and connected as pieces without the use of glue.

Page 42


Page 43


Design Boundary & Limitation Instructor: Dpc Lee

Project type: Personal project / Academy / Creation / Artworks / handmade Freshman year 2009

Page 44


In the â&#x20AC;&#x153;Tree Spaceâ&#x20AC;? project a boundary was used to limit a volume within a 60x60x60cm3 box. First, a concrete cube is splitted into 7 pieces so the section can be seen easily. The inner space is just like an atmosphere with black and white parts. The white part (Object) should be designed and black part (Space) is the rest space. Finally, each piece can be reassembled in different angles. The boundary and limitation is is less strict and more free forming in this way, allowing freedom to shine through.

Page 45


Competition Home For all Members

Addison Ow Chia Wei Kao, Ting Chun

Project type:

Competition project / Social Care / Temporary refuge Design 2011 Site: Japan after Tsunami

Attending as: Partner

Competition ArtLink Museum

- A Floating Museum of Nine City Blocks Teamwork leader: Jr-Gang Chi Ian Shao

Project type: Teamwork project / competition / Architecture 2012

Attending as: Design Member

Design Description:

Page 46

This floating museum is a micro-city of great dynamism. ArtLink correlates an art museum which a dynamic city. By synchronizing the major components of the city, the nature, and arts, this 21 st-century museum improvises a dialogue between apace and culture, which it provides rooms for exhibitions and recreations. To optimize the connection between the urban and cultural elements, our proposal significantly redefines and expands the boundary of the site. The new museum encompasses nice â&#x20AC;&#x153;urban blocks,â&#x20AC;&#x153; which include the existing Yingge train station and the Yingge agriculture association. In addition, new blocks are created-courtyard block, passage block, village block, square block, and waterfront block....


Page 47


Workshop Theatre Instructor:

Xuan-Cheng Chen

Project type: Workshop / Teamworks / TA / Architecture / Building Construction 2010 Summer

Attending as: Construction Member

ARM + [uto] Instructor:

Ursula Frick University Innsbruck [uto] Austria Thomas Grabner University Innsbruck [uto] Austria William She Cheng Yang Product Design Co. Ltd Taiwan Shih-Yuan Wang EPFL - Lausanne Switzerland Tsung-Hsien Wang Sheffeld University United Kingdom Prof. Chen Chen Cheng Tamkang University Taiwan

Project type:

Workshop / Teamworks / TA / Robotic Control 2013

Attending as: Page 48

Teaching Assistant


Page 49


Workshop Factory Instructor: Jr-Gang Chi

Project type: Workshop / Teamworks / TA / Architecture / 2010 winter

Attending as: Design Member

Workshop Japanese Tenon House Instructor:

Xuan-Cheng Chen

Project type: Workshop / Teamworks / TA / Architecture / 2008

Attending as: Construction Member

Page 50


Page 51


Fabrication ETH Copulas Designers:

Michael Hansmeyer Benjamin Dillenburger

Project type: Fabrication / Teamworks / RA / Architecture / Exhibition 2013

Attendant as: Fabrication Team Leader

Page 52


Page 53


Work In Progress Material Bending Pavilion(Green Expo) Interlocking Burr Puzzle Instructor:

Cheng-Chen Cheng

Project type: Fabrication / Research / RA / Architecture / Pavilion / Green Expo 2013 - until now

Page 54


Page 55


Photos & Sketches Travel and Church Reaserch Life Sketches

Page 56


Page 57


CV

Appendix Personal Info Curriculum Vitae

BASIC INFOMATION: date of birth: place of birth:

18/02/1990 Taipei, Taiwan

residence: phone: E-mail:

Taiwan +886910188990 kao.gene@gmail.com

UNDERGRADUATE EDUCATION: 09/2008 â&#x20AC;&#x201C; 06/2013:

Tamkang University Dept. of Architecture Average 81.76 out of 100.00 Cumulative GPA 3.550 Cumulative rank in class: 3rd / 83 Cumulative rank in department: 3rd / 83

SOFTWARE: Editors: Programmes:

Advanced: Ms Office, Mac iWork, Emacs, Vim, SublimeText2 Advanced: AutoCAD, Rhino (+ plugin Grasshopper), Abode Photoshop, Abode InDesign, Abode Illustrator Intermediate: Vray Redering, Maxwell Rendering, Maya, Abode Premiere, Abode After Effects, Adobe Lightroom, MeshLab, netfabb, Eclipse, meshMixer, SketchUp, TopMod

Programming Languages: HARDWARE: Fabrication skills:

Basic: Radiance Rendering, ZBrush, ImageMagick, Autodesk Ecotect, Blender Java, Processing, Python, bash

Intermediate: Laser Cutting, CNC(up to 4-Axis), 3D-Printing(Rep Prototyping), Zund Digital Cutter System, Vacuum Forming, 3D Scanning. Basic: ABB robot arm

Page 58


TEACHING & WORK EXPERIENCE: 07/2008 – 09/2008:

Group member participating in Ian Yan-Wen Shao New Taipei City Museum of Art Conceptual Design International Competition project, Honorable Mentions.

02/2012 – 05/2012

Leadership in ETH Copera fabrication project.

08/2013

TA in AA Visiting School in Tamkang University.

09/2013

TA in ARM workshop + [uto] in Tamkang University.

RESEARCH EXPERIENCE: 01/2012 – 08/2012: Part time RA in Tamkang University 07/2013 – until now:

Full time RA in Tamkang University

HONOURS, PRIZES, AWARDS AND FELLOWSHIPS: HIGH SCHOOL 10/2002, 12/2003:

High School Fine Art Award, the 3rd. Price, Taipei Area.

12/2004:

An Excellent Work Award of Ink Painting, Taipei Area.

07/2007:

High School Student Physics Completion, the 3rd. Price.

UNDERGRADUATE: 09/2008 – 06/2013:

Excellent Performance Award of Overall Academic Performance.

10/2009 – 04/2010:

National Intercollegiate Athletic Games - the 6th & 7th & 8th place.

12/2012:

Young College Elite of 2012 - China Youth Corps Certificate.

08/2011 – 09/2011:

Completed the Symposium of Leaders in Students Associations of Tamkang

06/2011 – 06/2012:

University 2011.

09/2012 – 05/2013:

49th. President of student association in TKU Architecture Dept.

2013:

Outstanding Performance Award of Architecture Thesis Design. Best Project Award of Undergraduate Design Thesis 2013.

WORKSHOPS: 08/2008 – 09/2008:

Japanese Tenon House Reassemble, in Taiwan.

01/2010 – 02/2010:

Architecture Dept. Factory Design.

06/2010 – 09/2010:

Theatre Build-Up Project.

2011, 2012, 2013:

ARM Workshop in Taipei.

OTHER EXPERIENCE: 08/2009 – 10/2009:

Backpacking to Denmark, Germany.

01/2013 – 03/2013:

Backpacking to Spain, French, Italy, Swiss to see and research John Ruskin mentioned 50 Churches. Page 59


Appendix

Code

Thesis Design Script Java + Processing

DigitalLampThesisGUI_v0a01.java package digitallampthesisgui_v0a01; import import import import import import import import import import import

java.util.ArrayList; processing.core.PApplet; peasy.*; controlP5.*; toxi.geom.*; toxi.processing.*; toxi.geom.mesh.*; toxi.util.datatypes.*; toxi.volume.*; geomerative.*; javax.swing.JFrame;

public class DigitalLampThesisGUI_v0a01 extends PApplet { /** * This is GUI software of Project of “The Digital Lamp of Architecture” * Written by Gene Ting-Chun Kao +GENEATCG http://www.geneatcg.com all right * reserve. Code credit to Jared Counts’ Curtain Coding Structure in * BlueThen.com */ private static final long serialVersionUID = 1L; PeasyCam cam, cam2; ControlP5 cp5; ControlWindow fcp; Textarea ParticleData; Group g1, g2, g3, g4, g5; Accordion accordion; RadioButton ParticleForce; RadioButton multiLock; RadioButton webStitchType; RadioButton FileType; RadioButton webSwitch; RadioButton webSwitchTo; RadioButton Export; public int stitchID = 2; public boolean together = false; float float float float float Page 60

StitchLength = 0; Xpan = 0; Ypan = 0; Zpan = 0; Mass = 0.5f;

DigitalLampThesisGUI_v0a01.java Link.java Particle.java Web.java


float Scale = 1.0f; float Xto = 0; float Yto = 0; float Zto = 0; int gravity1 = 392; int gravity2 = -392; boolean voxel = false; boolean modifyPin = true; public boolean meshExport = true; public boolean record = false; String PdataTxt = “”; boolean toggle = false; int normalValue1 = 10; int normalValue2 = 10; boolean lockedpMulti = true; int webStitchDiff = 0; // 0 same, 1 diff, 2 all int exState = 0; ArrayList<Particle> lockedp; Particle selectedp; EmbeddedSketch eSketch; ChildApplet child = new ChildApplet(); boolean mousePressedOnParent = false; float ISO_THRESHOLD = 3; float density = 0.5f; int voxelRes = 240; ToxiclibsSupport gfx; WETriangleMesh mesh, vMesh, fMesh; VolumetricSpace volume; IsoSurface surface; VolumetricBrush brush; AABB bounds3D; MeshLatticeBuilder builder; public boolean pause = false; boolean showNormals; public int co = color(235, 57, 174, 200); Web w, w1, w2, w3, w4, w5, w6; public Vec3D c2; public Vec3D extent; public float ww; public void setup() { size(600, 700, OPENGL); frame.setLocation(800, 100); Page 61


smooth(); lockedp = new ArrayList<Particle>(); gui(); cam = new PeasyCam(this, 1000); w = new Web(); w1 = new Web(this, 25, 25); w2 = new Web(this, 25, 25); eSketch = new EmbeddedSketch(child); mesh = new WETriangleMesh(“meshy”); gfx = new ToxiclibsSupport(this); setupVMesh(); fMesh = new WETriangleMesh(“test”); } public void draw() { background(200); mesh.clear(); noStroke(); if (record) { beginRaw(“superCAD.” + “Rhino”, “oneDome” + (System.currentTimeMillis() / 1000) + “.rvb”); w1.draw(gravity1, normalValue1); w2.draw(gravity2, normalValue2); endRaw(); record = false; } else { w1.draw(gravity1, normalValue1); w2.draw(gravity2, normalValue2); } fill(191, 202, 212, 100); if (pause && voxel) { // pause seem more intuitive drawVMesh(); } } public void keyPressed() { if (key == RETURN || key == ENTER) { pause = !pause; } if (key == ‘e’) { vMesh.saveAsSTL(sketchPath(mesh.name + (System.currentTimeMillis() / 1000) + “.stl”)); } if (key == ‘m’) { record = true; Page 62


} if (key == ‘c’) { volume.clear(); } if (key == ‘l’) new LaplacianSmooth().filter(fMesh, 1); if (key == ‘n’) { showNormals = !showNormals; } } private void setupVMesh() { bounds3D = new AABB(); float ww = w1.webWidth * w1.restingDistances; float wh = w1.webHeight * w1.restingDistances; Vec3D c1 = new Vec3D(ww / 2, ww / 2, ww * 2); Vec3D c2 = new Vec3D(-wh / 2, -wh / 2, -wh * 2); bounds3D.growToContainPoint(c1); bounds3D.growToContainPoint(c2); extent = bounds3D.getExtent(); float maxAxis = max(extent.x, extent.y, extent.z); int resX = (int) (extent.x / maxAxis * voxelRes); int resY = (int) (extent.y / maxAxis * voxelRes); int resZ = (int) (extent.z / maxAxis * voxelRes); builder = new MeshLatticeBuilder(extent.scale(2), resX, resY, resZ, new FloatRange(1, 1)); builder.setInputBounds(new AABB(bounds3D, extent.scale(1))); volume = builder.getVolume(); surface = new ArrayIsoSurface(volume); brush = new BoxBrush(volume, 0.20f); brush.setMode(VolumetricBrush.MODE_PEAK); // ////////////// vMesh = new WETriangleMesh(“dome”); } private void drawVMesh() { volume.closeSides(); new HashIsoSurface(volume).computeSurfaceMesh(vMesh, 1f); // new LaplacianSmooth().filter(vMesh, 2); gfx.mesh(vMesh, true, showNormals ? 10 : 0); exportVMesh(); } private void exportVMesh() { if (meshExport) { vMesh.saveAsSTL(sketchPath(vMesh.name + (System.currentTimeMillis() / 1000) + “.stl”)); } meshExport = false; Page 63


} // ////////////////////////////////////////////////////////////////////// public static void main(String _args[]) { PApplet.main(new String[] { digitallampthesisgui_v0a01.DigitalLampThesisGUI_v0a01.class .getName() }); } // ////////////////////////////////////////////////////////////////////// public class EmbeddedSketch extends JFrame { /** * this is GUI top view */ private static final long serialVersionUID = 1L; PApplet sketch; public EmbeddedSketch(PApplet p) { setTitle(“plane”); setBounds(0, 0, 600, 720); setLocation(200, 100); setResizable(false); add(p); p.init(); sketch = p; // Program exits setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); } } public class ChildApplet extends PApplet { /** * This Class is GUI Top View and GUI Slider */ private static final long serialVersionUID = 1L; RGeomElem mo; Vec3D mouseP; public void setup() { size(600, 700, OPENGL); smooth(); RG.init(this); cam2 = new PeasyCam(this, 0, 0, 0, 550); cam2.setRollRotationMode(); cam2.setLeftDragHandler(null); cam2.setRightDragHandler(null); cam2.reset(); w = w1; } public void draw() { background(200); Page 64


w.drawApplet(this); fill(255, 255, 0); mouseP = Mouse_Applet(this, mouseX, mouseY); mo = RShape.createCircle(mouseP.x, mouseP.y, 5).toShape(); mo.draw(child); interaction(); } public void interaction() { for (Particle p : w.particles) { try { if (p.rge.toShape().intersects(mo)) { if (p.getpState() != 2 && p.getpState() != 3) p.setpState(1); selectedp = p; if (mousePressed && mouseButton == LEFT) { p.position = new Vec3D(mouseP.x, mouseP.y, p.position.z); } PdataTxt = “Cooridernate: “ + round(selectedp.position.x) + “,” + round(selectedp.position.y) + “,” + round(selectedp.position.z) + ‘\n’ + “Statue: “ + selectedp.getpState() + “ Pinned: “ + selectedp.isPinned() + ‘\n’ + “Mass: “ + selectedp.mass + “ ID = “ + selectedp.getUV()[0] + “, “ + selectedp.getUV()[1] + ‘\n’ + “Force Driection: “ + round(selectedp.fg.x) + “,” + round(selectedp.fg.y) + “,” + round(selectedp.fg.z); ParticleData.setText(PdataTxt); } else { if (p.getpState() != 2 && p.getpState() != 3) p.setpState(0); } } catch (NullPointerException e) { println(“catch, What the fuck! Why Stop?”); } } } private Vec3D Mouse_Applet(ChildApplet a, float x, float y) { Vec3D mouse = new Vec3D(x - a.width / 2, y - a.height / 2, 0); Vec3D mousePV = new Vec3D(20, 0, 0); Vec3D screenPV = new Vec3D(a.g.screenX(20, 0) - a.g.screenX(0, 0), 0, 0); float rMS = mousePV.magnitude() / screenPV.magnitude(); Vec3D mouseNew = mouse.copy(); mouseNew.scaleSelf(rMS); mouseNew.addSelf(new Vec3D(cam2.getLookAt()[0], Page 65


cam2.getLookAt()[1], 0)); return mouseNew; } public void keyPressed() { if (key == RETURN || key == ENTER) { pause = !pause; } if (key == ‘e’) { vMesh.saveAsSTL(sketchPath(mesh.name + (System.currentTimeMillis() / 1000) + “.stl”)); } if (key == ‘c’) { volume.clear(); } if (key == ‘r’) { if (selectedp.links.size() > 1) selectedp.links.remove(selectedp.links.size() - 1); } if (key == ‘t’) { together = true; selectedp.together(); } if (key == CODED) { if (keyCode == SHIFT) { if (selectedp.getpState() == 2 || selectedp.getpState() == 3) selectedp .pinTo(new Vec3D(selectedp.position.x, selectedp.position.y, selectedp.position.z + 2)); else selectedp.position.add(new Vec3D(0, 0, 1)); } else if (keyCode == ALT) { if (selectedp.getpState() == 2 || selectedp.getpState() == 3) selectedp .pinTo(new Vec3D(selectedp.position.x, selectedp.position.y, selectedp.position.z - 2)); else selectedp.position.add(new Vec3D(0, 0, -1)); } else if (keyCode == RIGHT) { if (selectedp.getpState() == 2 || selectedp.getpState() == 3) selectedp.pinTo(new Vec3D(selectedp.position.x + 2, selectedp.position.y, selectedp.position.z)); else selectedp.position.add(new Vec3D(-1, 0, 0)); } else if (keyCode == LEFT) { if (selectedp.getpState() == 2 || selectedp.getpState() == 3) selectedp.pinTo(new Vec3D(selectedp.position.x - 2, selectedp.position.y, selectedp.position.z)); else Page 66


selectedp.position.add(new Vec3D(1, 0, 0)); } else if (keyCode == DOWN) { if (selectedp.getpState() == 2 || selectedp.getpState() == 3) selectedp .pinTo(new Vec3D(selectedp.position.x, selectedp.position.y + 2, selectedp.position.z)); else selectedp.position.add(new Vec3D(0, 1, 0)); } else if (keyCode == UP) { if (selectedp.getpState() == 2 || selectedp.getpState() == 3) selectedp .pinTo(new Vec3D(selectedp.position.x, selectedp.position.y - 2, selectedp.position.z)); else selectedp.position.add(new Vec3D(0, -1, 0)); } } if (key == ‘p’) { if (selectedp != null) { if (selectedp.isPinned() || selectedp.getpState() == 2) { selectedp.setpState(0); selectedp.setPinned(false); } else if (selectedp.getpState() == 3) { if (selectedp.isPinned() == false) selectedp.pinTo(new Vec3D(mouseP.x, mouseP.y, selectedp.position.z)); else { selectedp.setPinned(false); selectedp.setpState(3); } } else { selectedp.pinTo(new Vec3D(mouseP.x, mouseP.y, selectedp.position.z)); selectedp.setpState(2); } } } if (key == ‘l’) { if (lockedpMulti) { // multi points if (lockedp.isEmpty() && (selectedp.getpState() == 1 || selectedp .getpState() == 2)) { selectedp.setpState(3); lockedp.add(selectedp); } else if (selectedp.getpState() == 1 || selectedp.getpState() == 3 || selectedp.getpState() == 2) { if (lockedp.contains(selectedp)) { if (selectedp.isPinned()) { lockedp.remove(selectedp); Page 67


selectedp.setpState(2); selectedp.setPinned(true); } else { lockedp.remove(selectedp); selectedp.setpState(0); selectedp.setPinned(false); } } else { selectedp.setpState(3); lockedp.add(selectedp); } } println(lockedp.size()); } else if (!lockedpMulti) { // single point if (lockedp.isEmpty() && (selectedp.getpState() == 1 || selectedp .getpState() == 2)) { lockedp.add(selectedp); selectedp.setpState(3); } else if (lockedp.isEmpty() && selectedp.getpState() != 1) { println(“select nothing”); } else if (lockedp.size() == 1 && selectedp.getpState() != 1) { lockedp.get(0).setpState(0); lockedp.clear(); } else if (lockedp.size() == 1 && selectedp.getpState() == 1) { if (lockedp.get(0) == selectedp) { lockedp.get(0).setpState(1); lockedp.clear(); } else { lockedp.get(0).setpState(1); lockedp.clear(); lockedp.add(selectedp); } } } } lockedpanel(); } public void lockedpanel() { boolean b; b = true; selectedSliderActive(cp5, “StitchLength”, b, g2); selectedSliderActive(cp5, “Xpan”, b, g3); selectedSliderActive(cp5, “Ypan”, b, g3); selectedSliderActive(cp5, “Zpan”, b, g3); selectedSliderActive(cp5, “Mass”, b, g3); selectedSliderActive(cp5, “Scale”, b, g3); selectedSliderActive(cp5, “Xto”, b, g3); selectedSliderActive(cp5, “Yto”, b, g3); selectedSliderActive(cp5, “Zto”, b, g3); selectedBangActive(cp5, “Apply”, b, g3); Page 68


selectedBangActive(cp5, “MoveTo”, b, g3); selectedBangActive(cp5, “ScaleA”, b, g3); selectedBangActive(cp5, “Stitch”, b, g2); selectedBangActive(cp5, “Clear”, b, g2); selectedSliderActive(cp5, “gravity1”, b, g4); selectedSliderActive(cp5, “gravity2”, b, g4); selectedToggleActive(cp5, “voxel”, b, g4); selectedBangActive(cp5, “Export”, b, g4); } public void selectedSliderActive(ControlP5 cp, String n, boolean b, Group g) { Slider s = (Slider) cp.getController(n); // general slider color setting if (b) { s.unlock().setGroup(g); } else { s.setColorForeground(color(255, 150)).setValue(0).lock() .setGroup(g); } } public void selectedBangActive(ControlP5 cp, String n, boolean b, Group g) { Bang ba = (Bang) cp.getController(n); // general slider color setting if (b) { ba.unlock().setGroup(g); } else if (n == ba.getName()) { ba.setColorForeground(color(255, 150)).setValue(0).lock() .setGroup(g); } } public void selectedToggleActive(ControlP5 cp, String n, boolean b, Group g) { Toggle ba = (Toggle) cp.getController(n); // general slider color setting if (b) { ba.unlock().setGroup(g); } else if (n == ba.getName()) { ba.setColorForeground(color(255, 150)).setValue(0).lock() .setGroup(g); } } public void Stitch() { if (!lockedp.isEmpty()) { Vec3D np = new Vec3D(); if (webStitchDiff == 1) { // DiffWeb for (Particle p : lockedp) { Particle wp = w2.getUV(p.getUV()[0], p.getUV()[1]); if (wp != null) { if (stitchID == 1) Page 69


wp = w1.getUV(p.getUV()[0], p.getUV()[1]); else if (stitchID == 2) wp = w2.getUV(p.getUV()[0], p.getUV()[1]); else if (stitchID == 3) wp = w3.getUV(p.getUV()[0], p.getUV()[1]); else if (stitchID == 4) wp = w4.getUV(p.getUV()[0], p.getUV()[1]); else if (stitchID == 5) wp = w5.getUV(p.getUV()[0], p.getUV()[1]); else if (stitchID == 6) wp = w6.getUV(p.getUV()[0], p.getUV()[1]); // np = p.position.add(wp.position); // np.scale(0.5f); // p.pinTo(np); p.attachTo(wp, StitchLength, 1); p.setpState(0); p.setPinned(false); } } } else if (webStitchDiff == 0) { // same for (Particle p : lockedp) { np = np.addSelf(p.position); } np.scaleSelf(1.0f / lockedp.size()); lockedp.get(0).pinTo(np); int id = 0; for (Particle p : lockedp) { if (id != 0) p.attachTo(lockedp.get(0), StitchLength, 1); p.setpState(0); id++; } lockedp.get(0).setPinned(false); } else if (webStitchDiff == 2) { // all Kind if (lockedp.size() > 1) for (int i = 1; i < lockedp.size(); i++) { Particle p = lockedp.get(i - 1); Particle q = lockedp.get(i); p.attachTo(q, StitchLength, 1); p.setpState(0); p.setPinned(false); q.setpState(0); q.setPinned(false); } } lockedp.clear(); } } public void Clear() { if (!lockedp.isEmpty()) { lockedp.clear(); } println(“lockedp clear!”); } Page 70


public void Apply() { if (!lockedp.isEmpty()) { for (Particle p : lockedp) { p.pinTo(new Vec3D(p.position.x + Xpan, p.position.y + Ypan, p.position.z + Zpan)); p.setpState(3); p.setMass(Mass); } } } public void MoveTo() { if (!lockedp.isEmpty()) { for (Particle p : lockedp) { p.pinTo(new Vec3D(Xto, Yto, Zto)); p.setpState(3); p.setMass(Mass); } } } public void ScaleA() { if (!lockedp.isEmpty()) { Vec3D sum = new Vec3D(); for (Particle p : lockedp) { sum.addSelf(p.position); } sum.scale(1.0f / lockedp.size()); println(sum); for (Particle p : lockedp) { Vec3D newP = new Vec3D(p.position.add((sum.sub(p.position)) .scale(Scale))); Vec3D newPXY = new Vec3D(newP.x, newP.y, 0); p.pinTo(newPXY); p.setpState(3); } } } public void Export() { meshExport = true; } } public void gui() { cp5 = new ControlP5(this); fcp = cp5.addControlWindow(“panel”, 0, 100, 200, 700); fcp.setBackground(200); Page 71


// g1 g1 = cp5.addGroup(“Particle Data”).setBackgroundColor(color(50, 64)) .moveTo(fcp); ParticleData = cp5.addTextarea(“ParticleData”).setPosition(5, 5) .setWidth(170).setLineHeight(12).setGroup(g1); ParticleForce = cp5.addRadioButton(“ParticleForce”).setPosition(5, 75) .setItemWidth(15).setItemHeight(15).setItemsPerRow(3) .setSpacingColumn(40).addItem(“Gravity”, 0) .addItem(“Center”, 1).addItem(“Specific”, 2) .setNoneSelectedAllowed(false).activate(0).setGroup(g1); multiLock = cp5.addRadioButton(“multiLock”).setPosition(5, 55) .setItemWidth(15).setItemHeight(15).setItemsPerRow(3) .setSpacingColumn(40).addItem(“Single”, 0) .addItem(“MultiPoint”, 1).setNoneSelectedAllowed(false) .activate(0).setGroup(g1); // g2 g2 = cp5.addGroup(“StitchParameter”).setBackgroundColor(color(50, 64)) .setBackgroundHeight(170).moveTo(fcp); webStitchType = cp5.addRadioButton(“webStitchType”).setPosition(5, 5) .setItemWidth(15).setItemHeight(15).setItemsPerRow(3) .setSpacingColumn(40).addItem(“Same”, 0).addItem(“Diff”, 1) .addItem(“All Kind”, 2).setNoneSelectedAllowed(false) .activate(0).setGroup(g2); cp5.addBang(“Stitch”).setPosition(5, 110).setSize(15, 15) .setColorForeground(color(100, 150)).plugTo(child, “Stitch”) .setGroup(g2); cp5.addBang(“Clear”).setPosition(60, 110).setSize(15, 15) .setColorForeground(color(100, 150)).plugTo(child, “Clear”) .setGroup(g2); webSwitch = cp5.addRadioButton(“webSwitch”).setPosition(5, 30) .setItemWidth(15).setItemHeight(15).setItemsPerRow(3) .setSpacingColumn(40).addItem(“Web1”, 0).addItem(“Web2”, 1) .setNoneSelectedAllowed(false).activate(0).setGroup(g2); webSwitchTo = cp5.addRadioButton(“webSwitchTo”).setPosition(5, 70) .setItemWidth(15).setItemHeight(15).setItemsPerRow(3) .setSpacingColumn(40).addItem(“WebTo1”, 0).addItem(“WebTo2”, 1) .setNoneSelectedAllowed(false).activate(0).setGroup(g2); cp5.addSlider(“StitchLength”).setPosition(5, 145).setSize(100, 15) .setRange(0, 500).setValue(0) .setColorForeground(color(100, 150)).setGroup(g2); // g3 g3 = cp5.addGroup(“ParticleParameter”).setWidth(180) .setBackgroundHeight(200).setBackgroundColor(color(50, 64)) .moveTo(fcp); cp5.addSlider(“Xpan”).setPosition(5, 5).setSize(100, 15) .setRange(-10, 10).setValue(0) .setColorForeground(color(100, 150)).setGroup(g3); Page 72


cp5.addSlider(“Ypan”).setPosition(5, 25).setSize(100, 15) .setRange(-10, 10).setValue(0) .setColorForeground(color(100, 150)).setGroup(g3); cp5.addSlider(“Zpan”).setPosition(5, 45).setSize(100, 15) .setRange(-10, 10).setValue(0) .setColorForeground(color(100, 150)).setGroup(g3); cp5.addSlider(“Mass”).setPosition(5, 65).setSize(100, 15) .setRange(-10, 10).setValue(0.5f) .setColorForeground(color(100, 150)).setGroup(g3); cp5.addSlider(“Scale”).setPosition(5, 95).setSize(100, 15) .setRange(0.5f, 2).setValue(1.0f) .setColorForeground(color(100, 150)).setGroup(g3); cp5.addSlider(“Xto”).setPosition(5, 125).setSize(100, 15) .setRange(-300, 300).setValue(0) .setColorForeground(color(100, 150)).setGroup(g3); cp5.addSlider(“Yto”).setPosition(5, 145).setSize(100, 15) .setRange(-300, 300).setValue(0) .setColorForeground(color(100, 150)).setGroup(g3); cp5.addSlider(“Zto”).setPosition(5, 165).setSize(100, 15) .setRange(-1000, 1000).setValue(0) .setColorForeground(color(100, 150)).setGroup(g3); // bang cp5.addBang(“Apply”).setPosition(145, 5).setSize(15, 15) .setColorForeground(color(100, 150)).plugTo(child, “Apply”) .setGroup(g3); cp5.addBang(“MoveTo”).setPosition(145, 125).setSize(15, 15) .setColorForeground(color(100, 150)).plugTo(child, “MoveTo”) .setGroup(g3); cp5.addBang(“ScaleA”).setPosition(145, 95).setSize(15, 15) .setColorForeground(color(100, 150)).plugTo(child, “ScaleA”) .setGroup(g3); // g4 g4 = cp5.addGroup(“GravityTest”).setBackgroundColor(color(50, 64)) .moveTo(fcp); cp5.addSlider(“gravity1”).setPosition(5, 5).setSize(100, 15) .setRange(-392, 392).setValue(392).setGroup(g4); cp5.addSlider(“gravity2”).setPosition(5, 25).setSize(100, 15) .setRange(-392, 392).setValue(-392).setGroup(g4); cp5.addToggle(“voxel”).setPosition(5, 55).setSize(15, 15) .setValue(false).setColorForeground(color(100, 150)) .setGroup(g4).unlock(); cp5.addBang(“Export”).setPosition(45, 55).setSize(15, 15) .setColorForeground(color(100, 150)).plugTo(child, “Export”) .setGroup(g4); // g5 g5 = cp5.addGroup(“GravityApply”).setWidth(180).setPosition(10, 630) .setBackgroundColor(color(50, 64)).moveTo(fcp); cp5.addToggle(“toggle”).setPosition(5, 35).setSize(15, 15) .setColorForeground(color(100, 150)).setGroup(g5).unlock(); cp5.addSlider(“normalValue1”).setPosition(5, 5).setSize(100, 10) Page 73


.setRange(-100, 100).setColorForeground(color(100, 150)) .setGroup(g5); cp5.addSlider(“normalValue2”).setPosition(5, 20).setSize(100, 10) .setRange(-100, 100).setColorForeground(color(100, 150)) .setGroup(g5); // groups setting accordion = cp5.addAccordion(“Data”).setPosition(10, 20).setWidth(180) .addItem(g1).addItem(g2).addItem(g3).addItem(g4); accordion.moveTo(fcp).open(0, 1, 2, 3, 4) .setCollapseMode(Accordion.MULTI); cp5.setAutoDraw(false); } public int radioPick(ControlEvent ev) { int id = 0; for (float v : ev.getGroup().getArrayValue()) { if (v == 1) break; id++; } return id; } public void controlEvent(ControlEvent theEvent) { if (theEvent.isFrom(ParticleForce)) { int id = radioPick(theEvent); for (Particle p : w.particles) { p.setfState(id); } } else if (theEvent.isFrom(multiLock)) { int id = radioPick(theEvent); if (id == 0) lockedpMulti = false; else if (id == 1) lockedpMulti = true; } else if (theEvent.isFrom(webStitchType)) { int id = radioPick(theEvent); if (id == 0) webStitchDiff = 0; else if (id == 1) webStitchDiff = 1; else if (id == 2) webStitchDiff = 2; } else if (theEvent.isFrom(FileType)) { int id = radioPick(theEvent); if (id == 0) exState = 0; else if (id == 1) exState = 1; } else if (theEvent.isFrom(webSwitch)) { w = new Web(); if (w != null) { int id = radioPick(theEvent); cam2 = new PeasyCam(child, 0, 0, 0, 350); Page 74


cam2.setRollRotationMode(); cam2.setLeftDragHandler(null); cam2.setRightDragHandler(null); cam2.reset(); if (id == 0) w = w1; else if (id == 1) w = w2; } } else if (theEvent.isFrom(webSwitchTo)) { int id = radioPick(theEvent); if (id == 0) stitchID = 1; else if (id == 1) stitchID = 2; } } }

Link.java package digitallampthesisgui_v0a01; import processing.core.PApplet; import toxi.geom.Line3D; import toxi.geom.Vec3D; public class Link { DigitalLampThesisGUI_v0a01 p5; float stiff; float restingDist; Particle p1; Particle p2; float scalarP1; float scalarP2; Line3D segment; public Link(DigitalLampThesisGUI_v0a01 p5, Particle p1, Particle p2, float restingDist, float stiff) { this.p5 = p5; this.p1 = p1; this.p2 = p2; this.restingDist = restingDist; this.stiff = stiff; float im1 = 1 / this.p1.mass; float im2 = 1 / this.p2.mass; scalarP1 = (im1 / (im1 + im2)) * stiff; scalarP2 = (im2 / (im1 + im2)) * stiff; }

Page 75


public void draw() { segment = new Line3D(p1.position, p2.position); p5.gfx.line(segment); if (p5.pause && (p1.getUV()[0] % 2 == 0 || p1.getUV()[1] % 2 == 0)) { p5.builder.createLattice(p5.brush, segment, 0.9f); } } public void drawApplet(PApplet a) { a.stroke(235, 57, 174, 200); a.line(p1.position.x, p1.position.y, p2.position.x, p2.position.y); } public void constraintSolve() { Vec3D delta = p1.position.sub(p2.position); float d = p1.position.distanceTo(p2.position); if (d != 0) { float difference = (restingDist - d) / d; p1.position.addSelf(delta.scale(scalarP1 * difference)); p2.position.subSelf(delta.scale(scalarP2 * difference)); } } }

Particle.java package digitallampthesisgui_v0a01; import geomerative.RGeomElem; import geomerative.RShape; import java.util.ArrayList; import processing.core.PApplet; import toxi.geom.Vec3D; public class Particle { DigitalLampThesisGUI_v0a01 p5; Vec3D position; Vec3D lastPosition; Vec3D acceleration; float mass = 1.0f; float damping = 20.0f; Vec3D fg; RGeomElem rge; float psize = 5; private int[] uv = new int[2]; private int pState = 0; // none = 0; over = 1; pinned = 2; locked = 3; Page 76


private int fState = 0; Vec3D fc = new Vec3D(); private boolean pinned = false; private boolean pinnedZ = false; Vec3D pinLocation = new Vec3D(); ArrayList<Link> links = new ArrayList<Link>(); public Particle(DigitalLampThesisGUI_v0a01 p5, Vec3D pos) { this.p5 = p5; position = pos.copy(); lastPosition = pos.copy(); acceleration = new Vec3D(); } public Particle(DigitalLampThesisGUI_v0a01 p5) { this.p5 = p5; } public void draw() { p5.stroke(p5.co); if (links.size() > 0) { for (int i = 0; i < links.size(); i++) { Link currentLink = links.get(i); currentLink.draw(); } } p5.strokeWeight(5); checkpColor(p5); p5.strokeWeight(1); p5.stroke(74, 84, 94); drawMassDiagram(); } public void drawApplet(PApplet a) { if (links.size() > 0) { for (int i = 0; i < links.size(); i++) { Link currentLink = links.get(i); currentLink.drawApplet(a); } } rge = RShape.createCircle(position.x, position.y, psize).toShape(); a.noStroke(); checkpColorChild(a); a.stroke(100); rge.draw(a); } Page 77


public void checkpColor(PApplet t) { switch (getpState()) { case 0: t.stroke(74, 84, 94); break; case 1: t.stroke(0, 200, 200); break; case 2: t.stroke(255, 0, 0); break; case 3: t.stroke(255, 150, 0); break; } } public void checkpColorChild(PApplet t) { switch (getpState()) { case 0: psize = 5;// + mass/ 100; if ((this.getUV()[0] + this.getUV()[1]) % 2 == 0) t.fill(255); else t.fill(200); break; case 1: psize = 5; t.fill(0, 200, 200); break; case 2: psize = 5; t.fill(255, 0, 0); break; case 3: psize = 10; t.fill(255, 150, 0); break; } } public void drawMassDiagram() { p5.pushMatrix(); p5.strokeWeight(0.3f); p5.stroke(100); p5.noFill(); p5.translate(position.x, position.y, position.z); p5.ellipse(0, 0, mass / 10 + 5, mass / 10 + 5); p5.popMatrix(); p5.strokeWeight(1); } public void attachTo(Particle P, float restingDist, float stiff) { Page 78


Link lnk = new Link(p5, this, P, restingDist, stiff); links.add(lnk); } public void pinTo(Vec3D location) { this.setPinned(true); pinLocation.set(location); } public void pinToZ(float z) { this.setPinnedZ(true); pinLocation.z = z; } public void setMass(float mass) { this.mass += mass; } private void forceCalculate(float gravity) { switch (fState) { case 0: fg = new Vec3D(0, 0, mass * gravity); break; case 1: fg = position.sub(fc); fg.limit(mass * gravity); break; case 2: fg = position.sub(fc); fg.limit(mass * gravity); break; } } public void updatePhysics(float timeStep, float gravity) { forceCalculate(gravity); applyForce(fg); Vec3D velocity = position.sub(lastPosition); acceleration.subSelf(velocity.scale(damping / mass)); Vec3D nextPos = acceleration.scale(0.5f).scale(timeStep * timeStep) .add(position.add(velocity)); lastPosition.set(position); position.set(nextPos); acceleration.set(0, 0, 0); } public void applyForce(Vec3D f) { acceleration.addSelf(f.scaleSelf(1.0f / 1)); // scaleSelf(1.0f/mass); } public void solveConstraints() { for (Link l : links) { l.constraintSolve(); Page 79


} if (isPinned()) position.set(pinLocation); if (isPinnedZ()) position.z = 0; } public int[] getUV() { return uv; } public void setUV(int x, int y) { uv[0] = x; uv[1] = y; } public int getpState() { return pState; } public void setpState(int pState) { this.pState = pState; } public int getfState() { return fState; } public void setfState(int fState) { this.fState = fState; } public boolean isPinned() { return pinned; } public void setPinned(boolean pinned) { this.pinned = pinned; } public void removeLink(Link lnk) { links.remove(lnk); } public Vec3D ptNormal(Particle a, Particle b, Particle c, Particle d) { Vec3D ac = a.position.sub(c.position); Vec3D bd = b.position.sub(d.position); Vec3D cros = bd.cross(ac); cros.normalize(); return cros; } public float ptGetCurvature(Particle a, Particle b) { Vec3D u = a.position.sub(this.position); Vec3D v = b.position.sub(this.position); Page 80


float deg = u.angleBetween(v, true); return deg; } public void updatePhysicsNormal(float timeStep, Vec3D gNormal) { Vec3D no = gNormal.copy(); this.applyForce(no); Vec3D velocity = position.sub(lastPosition); acceleration.subSelf(velocity.scale(damping / mass)); Vec3D nextPos = acceleration.scale(0.5f).scale(timeStep * timeStep) .add(position.add(velocity)); lastPosition.set(position); position.set(nextPos); acceleration.set(0, 0, 0); } public void drawMeshPt() { if (p5.pause) { Vec3D mousePos = new Vec3D(position.x, position.y, position.z); p5.brush.drawAtAbsolutePos(mousePos, p5.density); } } public boolean isPinnedZ() { return pinnedZ; } public void setPinnedZ(boolean pinnedZ) { this.pinnedZ = pinnedZ; } public void together() { if (p5.together) { Vec3D u = new Vec3D(); for (Particle t : p5.lockedp) { u.addSelf(t.position); u.scale(p5.lockedp.size()); } for (Particle t : p5.lockedp) t.pinTo(u); p5.together = false; } } }

Page 81


Web.java package digitallampthesisgui_v0a01; import java.util.ArrayList; import processing.core.PApplet; import processing.core.PConstants; import toxi.geom.Vec3D; public class Web { DigitalLampThesisGUI_v0a01 p5; int webWidth; int webHeight; ArrayList<Particle> particles = new ArrayList<Particle>(); private int fState = 0; float restingDistances = 20; float stiffnesses = 0.01f; int constraintAccuracy = 20; int fixedDeltaTime = 15; float fixedDeltaTimeSeconds = (float) fixedDeltaTime / 1000.0f; public Web() { } public Web(DigitalLampThesisGUI_v0a01 p5, int sW, int sH) { this.p5 = p5; webWidth = sW; webHeight = sH; for (int y = 0; y < webHeight; y++) { for (int x = 0; x < webWidth; x++) { Particle particle = new Particle(p5, new Vec3D( (x - webWidth / 2) * restingDistances, (y - webHeight / 2) * restingDistances, 0)); // initial position particle.setUV(x, y); particles.add(particle); } } attachEven(); pinCorner(); } public void draw(int gravity, int normalValue) { for (Particle p : particles) p.draw(); if (!p5.pause) { for (int x = 0; x < constraintAccuracy; x++) for (Particle p : particles) p.solveConstraints(); for (Particle p : particles) Page 82


p.updatePhysics(fixedDeltaTimeSeconds, gravity); normalForceApply(normalValue); } if (!p5.pause) drawMesh(); } public void drawApplet(PApplet a) { for (Particle p : particles) p.drawApplet(a); } private void pinCorner() { for (Particle p : particles) { if ((p.getUV()[0] == 0 && (p.getUV()[1] == 0 || (p.getUV()[1] == webHeight - 1))) || (p.getUV()[0] == webWidth - 1 && (p.getUV()[1] == 0 || (p .getUV()[1] == webHeight - 1)))) { p.pinTo(p.position.scale(0.7f)); p.setpState(2); } } } private void attachEven() { for (Particle p : particles) { if ((p.getUV()[0] + p.getUV()[1]) % 2 == 0) { if (p.getUV()[1] != 0) // / attach to up p.attachTo( particles.get((p.getUV()[1] - 1) * (webWidth) + p.getUV()[0]), restingDistances, stiffnesses); if (p.getUV()[0] != 0) // / attach to left p.attachTo( particles.get((p.getUV()[1]) * (webWidth) + p.getUV()[0] - 1), restingDistances, stiffnesses); if (p.getUV()[1] != webHeight - 1) // / attach to down p.attachTo( particles.get((p.getUV()[1] + 1) * (webWidth) + p.getUV()[0]), restingDistances, stiffnesses); if (p.getUV()[0] != webWidth - 1) // / attach to right p.attachTo( particles.get((p.getUV()[1]) * (webWidth) + p.getUV()[0] + 1), restingDistances, stiffnesses); } } } public void reConstruct(int sW, int sH) { webWidth = sW; webHeight = sH; Page 83


for (int y = 0; y < webHeight; y++) { for (int x = 0; x < webWidth; x++) { Particle particle = new Particle(p5, new Vec3D( (x - webWidth / 2) * restingDistances, (y - webHeight / 2) * restingDistances, 0)); particle.setUV(x, y); particles.add(particle); } } attachEven(); pinCorner(); } private void drawMesh() { for (Particle p : particles) { if (p.getUV()[1] != 0 && p.getUV()[0] != 0) { Particle p0 = particles.get((p.getUV()[1]) * (webWidth) + p.getUV()[0]); Particle p1 = particles.get((p.getUV()[1]) * (webWidth) + p.getUV()[0] - 1); Particle p2 = particles.get((p.getUV()[1] - 1) * (webWidth) + p.getUV()[0] - 1); Particle p3 = particles.get((p.getUV()[1] - 1) * (webWidth) + p.getUV()[0]); p5.noStroke(); p5.fill(191, 202, 212, 100); p5.mesh.addFace(p0.position, p1.position, p2.position); p5.mesh.addFace(p0.position, p2.position, p3.position); } } } public void normalForceApply(float normalValue) { if (p5.toggle) { for (Particle p : particles) { int[] t = p.getUV(); if ((t[0] > 0 && t[1] > 0 && t[0] < webWidth - 1 && t[1] < webHeight - 1) && p.links.size() > 3) { Particle a = particles .get((webWidth) Particle b = particles .get((webWidth) Particle c = particles .get((webWidth) Particle d = particles .get((webWidth)

* (t[1] - 1) + (t[0])); * (t[1]) + (t[0] - 1)); * (t[1] + 1) + (t[0])); * (t[1]) + (t[0] + 1));

float deg1 = p.ptGetCurvature(a, c); float deg2 = p.ptGetCurvature(b, d); if (deg1 > PConstants.PI / 3 && deg2 > PConstants.PI / 3) { Vec3D n = p.ptNormal(a, b, c, d); n.normalizeTo(normalValue); Page 84


n.scaleSelf(p.position.z); Vec3D show = n.copy(); show.scaleSelf(1.0f / 30); Vec3D ad = p.position.add(show); p5.stroke(n.magnitude() / 6, 0, n.magnitude() / 12, n.magnitude() / 6 - 100); p5.line(p.position.x, p.position.y, p.position.z, ad.x, ad.y, ad.z); p.updatePhysicsNormal(fixedDeltaTimeSeconds, n); } } } } } public Particle getUV(int u, int v) { Particle np = new Particle(p5); for (Particle p : particles) { if (p.getUV()[0] == u && p.getUV()[1] == v) { np = p; break; } } return np; } public int getfState() { return fState; } public void setfState(int fState) { for (Particle p : particles) p.setfState(fState); } }

Page 85

Profile for Gene Kao

Computation and Aesthetics  

Gene Kao, Ting-Chun portfolio 2008-2013

Computation and Aesthetics  

Gene Kao, Ting-Chun portfolio 2008-2013

Profile for kao.gene
Advertisement