/
README.html
200 lines (140 loc) · 10.8 KB
/
README.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
<div style = "padding-left:100px;padding-right:100px;font-family:sans-serif">
<h1>Turbine 0.2</h1>
<img src="http://tileableart.com/code/thesis/images/squibble.png">
<h2>A parametric animation and modeling tool for threejs</h2>
<p>This document briefly outlines some of the basic functionality of Turbine. I built this tool for myself for two reasons: parametric modeling for 3D prints and animation. It is low level, general purpose and possibly somewhat obtuse. It is also possible to make extremely complex and elegant animating sculptures with relatively little code. It is called Turbine because that's how my head feels when after I've stuck it into a recursive function. </p>
<h2>Interface</h2>
<p>orbit controls for mouse - zoom and rotate</p>
<p>h hides sliders <br />
ctrl-c shows editor <br />
ctrl-v runs code <br />
ctrl-i inverts colors <br />
ctrl-shift-i makes code background opaque <br />
ctrl-space pauses animation <br />
ctrl-r slider values copied to code <br />
ctrl < and > makes code bigger and smaller <br />
ctrl - and + makes code window bigger and smaller <br />
arrows move tree when code view is invisible <br />
ctrl-shift-s saves file </p>
<h3>variables</h3>
<p><code>codeName = "string"</code> name of code to save with ctrl+shift+s <br />
<code>frameRate = 1000/30</code> by default <br />
<code>noLights = boolean</code> (removes default lights) </p>
<h4>GUI</h4>
<p><code>h</code> hides dat.gui - you can access the values on the sliders like this: </p>
<pre><code>var thing = data.var1;
</code></pre>
<p>Once you have values you like ctrl+r will copy those to your code. <br />
You can easily customize the gui. </p>
<pre><code>setSliders({"var1":1,"var2":2,etc});
rebuildGui({values:{customVal1:0,customVal2:0},sliders:31});
</code></pre>
<h3>Functions</h3>
<ul>
<li><p>Branching <br />
* <code>generate()</code> generate complex, usually symmetrical tree structures <br />
* <code>branch()</code> create one branch <br />
<code>appendBranch()</code> attach a branch to a joint <br />
<code>appendTree()</code> generate a tree from a specified joint </p></li>
<li><p>Organization <br />
* <code>makeInfo()</code> takes an array [[0,0,0],{rz:0}] like that and makes an object which can be passed along <br />
* <code>makeList()</code> takes an array [0,0,-1] and returns a list of many arrays <br />
* <code>makeDictionary()</code> Assigns a name to each joint <br />
* <code>FIND()</code> will return one joint given an array <br />
<code>report()</code> creates a list of joints <br />
<code>reportLayers()</code> a list of joints organized by their branch level <br />
<code>worldPositionsArray()</code> makes an array of vectors in the world positions of the joints </p></li>
<li><p>Transforming <br />
* <code>transform()</code> a function designed to move joint chains in every imaginable way <br />
* <code>passFunc()</code> works well with <code>makeInfo()</code> to pass functions to joints on the fly <br />
* <code>applyFunc()</code> works well with <code>makeDictionary()</code> othewise does the same as <code>passFunc()</code> <br />
<code>aimAt()</code> slow and janky - will aim at an object in world space <br />
<code>axisRotate()</code> will rotate joints in an arbitrary axis in world space <br />
<code>setJointLength()</code> <br />
<code>setJointWidth()</code> </p></li>
<li><p>Modeling <br />
* <code>makeTubes()</code> converts joint chains to extruded tubes (3d printable!) <br />
<code>solidSurface()</code> generates a surface, using joints as cross sections, and gives the surface thickness <br />
<code>openSurface()</code> same, but doesn't extrude the geometry <br />
<code>metaBalls{}</code> a set of tools to generate implicit surfaces <br />
<code>mergeMeshes()</code> takes a joint and merges all the geometry under it in the hierarchy <br />
<code>setGeo()</code> swap out the default geometry on each joint <br />
<code>nurbsishSurface()</code> makes an array of vectors which can be used as splines <br />
<code>makeSkinnedGeo()</code> janky - this will convert geo to skinned, accelerated geo </p></li>
</ul>
<h4>Basics</h4>
<p><em>this command will create a single branch with 100 joints by default</em> </p>
<p><code>tree = new TREE(); <br />
tree.branch(); <br />
scene.add(tree);</code> </p>
<p><em>this slightly more complicated example demonstrates the creation of a sierpinski like branching structure</em> </p>
<p><code>tree = new TREE(); <br />
tree.generate({joints:[1],angles:[1],rads:[3,3,3,3,3,3],length:[10]}) <br />
scene.add(tree);</code> </p>
<p><em><code>generate</code> accepts an object as an argument, any arguments that are not passed will be filled in by default:</em> </p>
<p><code>{ joints:[], divs:[], start:[], angles:[], length:[], rads:[], width:[], end:[]};</code></p>
<p>joints: The number of joints on a particular branch layer <br />
divs: how often the branch sprouts new branches (every 1st, 2nd, 5th joint etc) <br />
start: at which joint the branch starts branching <br />
angles: the angle that new branches will be rotated to <br />
length: how long each joint on a branch is <br />
rads: how many branches sprout from each joint <br />
width: width of the branches <br />
end: the last joint on a branch that will sprout </p>
<h4>A Lesson</h4>
<p>Once a tree has been created you will want to do things to it. In order to accomplish this you must be able to access parts of the tree. There are a variety of ways to do this. <code>FIND</code> is the most fundamental way. If you want to follow along with this example start by branching a tree as shown above: </p>
<p><code>tree = new TREE(); <br />
tree.branch(); <br />
scene.add(tree);</code> </p>
<p>and then we can find one joint and assign it to a variable: </p>
<p><code>var myJoint = tree.FIND([0,0,50]);</code> </p>
<p>myJoint is now a threejs Object3D which can be manipulated by normal means. </p>
<p><code>myJoint.rotation.z = 1;</code> </p>
<p>You should now have a stick with a crook in it. </p>
<p><em>But what does this mean: [0,0,50] ???</em> </p>
<p>Finding each joint in a chain relies on recursive functions. The arguments the search functions get work like this: </p>
<p><code>[0,0,50]</code> </p>
<p>The first item in the array always refers to the root and it is <em>always</em> <code>0</code>. The second item in the array refers to which of potentially lots of branches we're referring to. Imagine a yucca plant, there are lots of leaves coming from the root, the first element refers to the origin of the yucca plant, and the second item refers to which leaf (branch) we want to select (0 indexed always). In this case, we've only grown one branch from the origin. The last item in the array refers to which joint along that chosen branch we want to refer to. Please make sure you're getting this concept as everything else depends on this. </p>
<p>Now that we have our joint selected and assigned to a variable we can start to do things with it, add other branches for instance. Add this line to your code:</p>
<pre><code>tree.passFunc(tree.makeInfo([
[0,0,49], {rz:-1, amount:50}
]),tree.appendBranch);
</code></pre>
<p>If all is well you should have a Y shaped tree now. Let's select a joint on the second branch and transform that. We'll find it again. </p>
<p><code>var myOtherJoint = tree.FIND([0,0,0,0,25]);</code> </p>
<p>and we'll rotate this in the same way: </p>
<p><code>myOtherJoint.rotation.z = 1;</code> </p>
<p>Notice how much longer the search array has become - there are now 5 items. </p>
<p>[root,which branch, which joint with branches, which branch, which joint on the branch] </p>
<p>In this case there is just one branch branching from the first branch. So we select the root, the first (and only) branch, then the joint which has branches (there is only one), then which of potentially several branches come off of that joint (in this case there is only one) and then finally - the last number in the array is always the number of the joint we're selecting. Magic. </p>
<p>Let's get fancy. </p>
<pre><code>tree.passFunc(tree.makeInfo([
[0,0,0,0,-1], {rz:-1, amount:5,sc:10}
]),tree.appendBranch);
</code></pre>
<p>Zounds! By using <code>-1</code> we've selected <em>all</em> the joints on that branch, and appended branches to each joint! How can we possibly even think about controlling all of those joints? We just added 50 branches with 5 joints each, that's just scads of joints. Now we can start using the <code>tree.transform</code> function. </p>
<pre><code>tree.passFunc(tree.makeInfo([
[0,0,0,0,-2], {rz:.04},
[0,0,0,0,-1,0,-2], {rz:.3,sc:.6}
]),tree.transform);
</code></pre>
<p>Notice the use of <code>-2</code> - this will select all the joints except the first one, useful if you want to do things to the root of a joint separately from the rest. By rotating each joint we can start to make curves. Looking at the second line I'm selecting the root, then the first joint (as before), and then I'm using <code>-1</code> to select <em>all</em> of the joints on that branch which have branches coming out of them - which in this case is <em>all</em> of them! The very last number of course is all of the joints (except the first) of all of the branches that we've selected. Easy! </p>
<p><code>tree.transform()</code> is intended to be an all purpose method for transforming objects but you don't need to use it - it may make more sense for you to do things yourself. Here is how you can pass your own custom function with <code>passFunc()</code> </p>
<pre><code>tree.passFunc(tree.makeInfo([
[0,0,0,0,-1,0,-1], {custom:.1}
]),
function(obj,args){
obj.rotation.x = Math.random();
obj.rotation.y = args.custom;
});
</code></pre>
<p>Notice that while I'm passing this function it is not overwriting what I did before. You can also define your own functions elsewhere, generally you want the first argument to be the joint and the second argument to be an object with arguments related to what you want that joint to do. </p>
<p>Before moving on I want to show you another way to access joints. This method is faster and is better for animating. Check it: </p>
<pre><code>tree.makeDictionary();
myJointList = tree.makeList([0,0,-1]);
tree.applyFunc([
myJointList, {rz:.02}
],tree.transform);
</code></pre>
<p>In this case we make a dictionary of all the joint names, then we make a variable which contains all the names of the joints we want, and then we apply the function to those items. Notice I'm using <code>applyFunc</code> instead of <code>passFunc</code>. This method is nice because you know what parts you're referring to (lots of lists of numbers can get confusing), it's faster and simpler. </p>
<p>This example turned out to be quite ugly but you can access it from the presets, it's called <code>basics</code>.</p>