scenejs_on_rails 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -5
  3. data/app/controllers/scenejs_controller.rb +53 -0
  4. data/app/views/scenejs/get_scenejs_data.html.erb +3 -0
  5. data/lib/scenejs_on_rails.rb +1 -1
  6. data/lib/scenejs_on_rails/rails.rb +5 -0
  7. data/lib/scenejs_on_rails/version.rb +1 -1
  8. data/vendor/assets/javascripts/scenejs.js +17307 -0
  9. data/vendor/assets/javascripts/scenejs_extras/gui.js +478 -0
  10. data/vendor/assets/javascripts/scenejs_extras/gui/README.md +4 -0
  11. data/vendor/assets/javascripts/scenejs_extras/gui/dat.gui.min.js +94 -0
  12. data/vendor/assets/javascripts/scenejs_extras/gui/gui.js +385 -0
  13. data/vendor/assets/javascripts/scenejs_lib/cityBuilder.js +457 -0
  14. data/vendor/assets/javascripts/scenejs_lib/dat.gui.min.js +94 -0
  15. data/vendor/assets/javascripts/scenejs_lib/gl-matrix-min.js +28 -0
  16. data/vendor/assets/javascripts/scenejs_lib/gl-matrix.js +4078 -0
  17. data/vendor/assets/javascripts/scenejs_lib/require.js +36 -0
  18. data/vendor/assets/javascripts/scenejs_lib/requireConfig.js +18 -0
  19. data/vendor/assets/javascripts/scenejs_lib/requireWrapperEnd.js +1 -0
  20. data/vendor/assets/javascripts/scenejs_lib/requireWrapperStart.js +2 -0
  21. data/vendor/assets/javascripts/scenejs_lib/stats.min.js +6 -0
  22. data/vendor/assets/javascripts/scenejs_lib/sylvester.js +1 -0
  23. data/vendor/assets/javascripts/scenejs_lib/webgl-debug-utils.js +839 -0
  24. data/vendor/assets/javascripts/scenejs_plugins/geometry/boundary.js +59 -0
  25. data/vendor/assets/javascripts/scenejs_plugins/geometry/box.js +72 -0
  26. data/vendor/assets/javascripts/scenejs_plugins/geometry/plane.js +126 -0
  27. data/vendor/assets/javascripts/scenejs_plugins/geometry/quad.js +37 -0
  28. data/vendor/assets/javascripts/scenejs_plugins/geometry/skybox.js +86 -0
  29. data/vendor/assets/javascripts/scenejs_plugins/geometry/sphere.js +82 -0
  30. data/vendor/assets/javascripts/scenejs_plugins/geometry/teapot.js +5853 -0
  31. data/vendor/assets/javascripts/scenejs_plugins/geometry/torus.js +139 -0
  32. data/vendor/assets/javascripts/scenejs_plugins/geometry/vectorText.js +1499 -0
  33. data/vendor/assets/javascripts/scenejs_plugins/geometry/wobblyBox.js +44 -0
  34. data/vendor/assets/javascripts/scenejs_plugins/lib/canvas2image.js +198 -0
  35. data/vendor/assets/javascripts/scenejs_plugins/lib/frustum/frustumCullEngine.js +810 -0
  36. data/vendor/assets/javascripts/scenejs_plugins/lib/frustum/frustumCullSystem.js +185 -0
  37. data/vendor/assets/javascripts/scenejs_plugins/lib/frustum/frustumCullSystemPool.js +174 -0
  38. data/vendor/assets/javascripts/scenejs_plugins/lib/frustum/frustumCullWorker.js +142 -0
  39. data/vendor/assets/javascripts/scenejs_plugins/lib/gl-matrix-min.js +28 -0
  40. data/vendor/assets/javascripts/scenejs_plugins/lib/jquery-1.8.3.min.js +2 -0
  41. data/vendor/assets/javascripts/scenejs_plugins/lib/k3d.js +1029 -0
  42. data/vendor/assets/javascripts/scenejs_plugins/lib/physics/jiglib.all.min.js +3 -0
  43. data/vendor/assets/javascripts/scenejs_plugins/lib/physics/physics.js +223 -0
  44. data/vendor/assets/javascripts/scenejs_plugins/lib/physics/worker.js +330 -0
  45. data/vendor/assets/javascripts/scenejs_plugins/node/alpha/orbitTracking.js +295 -0
  46. data/vendor/assets/javascripts/scenejs_plugins/node/alpha/orbitTrackingTarget.js +43 -0
  47. data/vendor/assets/javascripts/scenejs_plugins/node/backgrounds/gradient.js +148 -0
  48. data/vendor/assets/javascripts/scenejs_plugins/node/cameras/orbit.js +172 -0
  49. data/vendor/assets/javascripts/scenejs_plugins/node/cameras/pickFlyOrbit.js +409 -0
  50. data/vendor/assets/javascripts/scenejs_plugins/node/canvas/capture.js +107 -0
  51. data/vendor/assets/javascripts/scenejs_plugins/node/demos/color.js +30 -0
  52. data/vendor/assets/javascripts/scenejs_plugins/node/demos/redTeapot.js +52 -0
  53. data/vendor/assets/javascripts/scenejs_plugins/node/demos/spinningTeapot.js +43 -0
  54. data/vendor/assets/javascripts/scenejs_plugins/node/effects/crt.js +36 -0
  55. data/vendor/assets/javascripts/scenejs_plugins/node/effects/fog.js +159 -0
  56. data/vendor/assets/javascripts/scenejs_plugins/node/effects/snowyPeaks.js +50 -0
  57. data/vendor/assets/javascripts/scenejs_plugins/node/effects/wobble.js +42 -0
  58. data/vendor/assets/javascripts/scenejs_plugins/node/effects/xray.js +126 -0
  59. data/vendor/assets/javascripts/scenejs_plugins/node/frustum/body.js +112 -0
  60. data/vendor/assets/javascripts/scenejs_plugins/node/frustum/cull.js +42 -0
  61. data/vendor/assets/javascripts/scenejs_plugins/node/frustum/lod.js +125 -0
  62. data/vendor/assets/javascripts/scenejs_plugins/node/heightmaps/custom.js +185 -0
  63. data/vendor/assets/javascripts/scenejs_plugins/node/import/3ds.js +91 -0
  64. data/vendor/assets/javascripts/scenejs_plugins/node/import/md2.js +139 -0
  65. data/vendor/assets/javascripts/scenejs_plugins/node/import/obj.js +100 -0
  66. data/vendor/assets/javascripts/scenejs_plugins/node/objects/buildings/building.js +352 -0
  67. data/vendor/assets/javascripts/scenejs_plugins/node/objects/buildings/building/HighRiseGlass.jpg +0 -0
  68. data/vendor/assets/javascripts/scenejs_plugins/node/objects/buildings/building/HighRiseGlassSpecular.jpg +0 -0
  69. data/vendor/assets/javascripts/scenejs_plugins/node/objects/buildings/building/highrise-windows.jpg +0 -0
  70. data/vendor/assets/javascripts/scenejs_plugins/node/objects/buildings/building/pixelcity_windows7.jpg +0 -0
  71. data/vendor/assets/javascripts/scenejs_plugins/node/objects/buildings/city.js +26 -0
  72. data/vendor/assets/javascripts/scenejs_plugins/node/objects/plants/ghostTree.js +387 -0
  73. data/vendor/assets/javascripts/scenejs_plugins/node/objects/space/planets/earth.js +168 -0
  74. data/vendor/assets/javascripts/scenejs_plugins/node/objects/space/planets/earth/earth-lights.gif +0 -0
  75. data/vendor/assets/javascripts/scenejs_plugins/node/objects/space/planets/earth/earth-specular.gif +0 -0
  76. data/vendor/assets/javascripts/scenejs_plugins/node/objects/space/planets/earth/earth-specular.jpg +0 -0
  77. data/vendor/assets/javascripts/scenejs_plugins/node/objects/space/planets/earth/earth.jpg +0 -0
  78. data/vendor/assets/javascripts/scenejs_plugins/node/objects/space/planets/earth/earthbump.jpg +0 -0
  79. data/vendor/assets/javascripts/scenejs_plugins/node/objects/space/planets/earth/earthclouds.jpg +0 -0
  80. data/vendor/assets/javascripts/scenejs_plugins/node/objects/toys/drinkingBird.js +632 -0
  81. data/vendor/assets/javascripts/scenejs_plugins/node/objects/vehicles/tank.js +77670 -0
  82. data/vendor/assets/javascripts/scenejs_plugins/node/objects/vehicles/tank.js~ +77636 -0
  83. data/vendor/assets/javascripts/scenejs_plugins/node/physics/body.js +85 -0
  84. data/vendor/assets/javascripts/scenejs_plugins/node/physics/box.js +30 -0
  85. data/vendor/assets/javascripts/scenejs_plugins/node/physics/material.js +35 -0
  86. data/vendor/assets/javascripts/scenejs_plugins/node/physics/plane.js +47 -0
  87. data/vendor/assets/javascripts/scenejs_plugins/node/physics/sphere.js +32 -0
  88. data/vendor/assets/javascripts/scenejs_plugins/node/physics/system.js +44 -0
  89. data/vendor/assets/javascripts/scenejs_plugins/node/physics/teapot.js +29 -0
  90. data/vendor/assets/javascripts/scenejs_plugins/node/prims/boundary.js +73 -0
  91. data/vendor/assets/javascripts/scenejs_plugins/node/prims/box.js +87 -0
  92. data/vendor/assets/javascripts/scenejs_plugins/node/prims/cylinder.js +186 -0
  93. data/vendor/assets/javascripts/scenejs_plugins/node/prims/grid.js +47 -0
  94. data/vendor/assets/javascripts/scenejs_plugins/node/prims/plane.js +137 -0
  95. data/vendor/assets/javascripts/scenejs_plugins/node/prims/quad.js +43 -0
  96. data/vendor/assets/javascripts/scenejs_plugins/node/prims/sphere.js +107 -0
  97. data/vendor/assets/javascripts/scenejs_plugins/node/prims/teapot.js +5846 -0
  98. data/vendor/assets/javascripts/scenejs_plugins/node/prims/torus.js +149 -0
  99. data/vendor/assets/javascripts/scenejs_plugins/node/prims/vectorText.js +1508 -0
  100. data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/clouds.js +19 -0
  101. data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/cloudySea.js +19 -0
  102. data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/custom.js +150 -0
  103. data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/grimmNight.js +19 -0
  104. data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/interstellarClouds.js +19 -0
  105. data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/miramarClouds.js +19 -0
  106. data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/stormyDays.js +19 -0
  107. data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/textures/clouds.jpg +0 -0
  108. data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/textures/cloudySea.jpg +0 -0
  109. data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/textures/grimmNight.jpg +0 -0
  110. data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/textures/interstellarClouds.jpg +0 -0
  111. data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/textures/miramarClouds.jpg +0 -0
  112. data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/textures/stormyDays.jpg +0 -0
  113. data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/textures/violentDays.jpg +0 -0
  114. data/vendor/assets/javascripts/scenejs_plugins/node/skyboxes/violentDays.js +19 -0
  115. data/vendor/assets/javascripts/scenejs_plugins/texture/image.js +67 -0
  116. data/vendor/assets/javascripts/scenejs_plugins/texture/video.js +105 -0
  117. metadata +113 -1
@@ -0,0 +1,352 @@
1
+ (function () {
2
+
3
+ var buildingTypes = initBuildingTypes();
4
+
5
+ SceneJS.Types.addType("objects/buildings/building", {
6
+
7
+ construct:function (params) {
8
+ var type = params.buildingType || 0;
9
+ var buildingType = buildingTypes[type];
10
+ if (!buildingType) {
11
+ throw "unsupported building type: " + type;
12
+ }
13
+ var pos = params.pos || {};
14
+ createBuilding(buildingType, this, {
15
+ xmin:(pos.x || 0) - 10,
16
+ zmin:(pos.z || 0) - 10,
17
+ xmax:(pos.x || 0) + 10,
18
+ zmax:(pos.z || 0) + 10
19
+ });
20
+ }
21
+ });
22
+
23
+ function initBuildingTypes() {
24
+
25
+ var texturePath = SceneJS.getConfigs("pluginPath") + "/node/objects/buildings/building/";
26
+
27
+ return [
28
+ // Building 1
29
+ {
30
+ freq:50,
31
+ material:{
32
+ type:"material",
33
+ coreId:"building.1.material",
34
+ baseColor:{
35
+ r:1.0,
36
+ g:1.0,
37
+ b:1.0
38
+ },
39
+ specularColor:[ 1.0, 1.0, 1.0 ],
40
+ specular:0.4,
41
+ shine:20.0
42
+ },
43
+ texture:{
44
+ type:"texture",
45
+ coreId:"building.1.texture",
46
+ layers:[
47
+ {
48
+ src:texturePath + "highrise-windows.jpg",
49
+ applyTo:"baseColor",
50
+ blendMode:"multiply",
51
+ wrapS:"repeat",
52
+ wrapT:"repeat",
53
+ scale:{
54
+ x:0.04,
55
+ y:0.05
56
+ }
57
+ }
58
+ ]
59
+ },
60
+ roof:{
61
+ height:1,
62
+ material:{
63
+ type:"material",
64
+ coreId:"building.1.roof",
65
+ baseColor:{
66
+ r:1.0,
67
+ g:1.0,
68
+ b:1.0
69
+ }
70
+ }
71
+ }
72
+ },
73
+ // Building 2
74
+ {
75
+ freq:30,
76
+ material:{
77
+ type:"material",
78
+ coreId:"building.2.material",
79
+ baseColor:{
80
+ r:1.0,
81
+ g:1.0,
82
+ b:1.0
83
+ },
84
+ specularColor:[ 1.0, 1.0, 1.0 ],
85
+ specular:1.0,
86
+ shine:5.0
87
+ },
88
+ texture:{
89
+ type:"texture",
90
+ coreId:"building.2.texture",
91
+ layers:[
92
+ {
93
+ src:texturePath + "HighRiseGlass.jpg",
94
+ applyTo:"baseColor",
95
+ blendMode:"multiply",
96
+ wrapS:"repeat",
97
+ wrapT:"repeat",
98
+ scale:{
99
+ x:0.25,
100
+ y:0.2
101
+ }
102
+ },
103
+ {
104
+ src:texturePath + "HighRiseGlassSpecular.jpg",
105
+ applyTo:"specular",
106
+ blendMode:"multiply",
107
+ wrapS:"repeat",
108
+ wrapT:"repeat",
109
+ scale:{
110
+ x:0.25,
111
+ y:0.2
112
+ }
113
+ }
114
+ ]
115
+ },
116
+ roof:{
117
+ height:1,
118
+ material:{
119
+ type:"material",
120
+ coreId:"building.2.roof",
121
+ baseColor:{
122
+ r:0.4,
123
+ g:0.4,
124
+ b:0.4
125
+ }
126
+ }
127
+ }
128
+ },
129
+ // Building 3
130
+ {
131
+ freq:20,
132
+ material:{
133
+ type:"material",
134
+ coreId:"building.3.material",
135
+ baseColor:{
136
+ r:1.0,
137
+ g:1.0,
138
+ b:1.0
139
+ },
140
+ specularColor:[ 1.0, 1.0, 1.0 ],
141
+ specular:0.4,
142
+ shine:20.0
143
+ },
144
+ texture:{
145
+ type:"texture",
146
+ coreId:"building.3.texture",
147
+ layers:[
148
+ {
149
+ src:texturePath + "pixelcity_windows7.jpg",
150
+ applyTo:"baseColor",
151
+ blendMode:"multiply",
152
+ wrapS:"repeat",
153
+ wrapT:"repeat",
154
+ scale:{
155
+ x:0.015,
156
+ y:0.01
157
+ }
158
+ }
159
+ ]
160
+ },
161
+ roof:{
162
+ height:1,
163
+ material:{
164
+ type:"material",
165
+ coreId:"building.3.roof",
166
+ baseColor:{
167
+ r:0.0,
168
+ g:0.0,
169
+ b:0.0
170
+ }
171
+ }
172
+ }
173
+ }
174
+ ];
175
+ }
176
+
177
+ function createBuilding(buildingType, node, footprint) {
178
+
179
+ var xpos = (footprint.xmin + footprint.xmax) * 0.5;
180
+ var ypos = 0;
181
+ var zpos = (footprint.zmin + footprint.zmax) * 0.5;
182
+
183
+ /* Base
184
+ */
185
+
186
+ var baseWidth = 0.6;
187
+
188
+ addBase(
189
+ buildingType,
190
+ node,
191
+ xpos, zpos,
192
+ footprint.xmax - footprint.xmin,
193
+ baseWidth / 2,
194
+ footprint.zmax - footprint.zmin);
195
+
196
+ var xmin;
197
+ var ymin;
198
+ var zmin;
199
+ var xmax;
200
+ var ymax;
201
+ var zmax;
202
+
203
+ var width;
204
+ var axis;
205
+ var sign;
206
+
207
+ var yMaxSize = (Math.random() * 30) + 15;
208
+ var ySize = yMaxSize + baseWidth;
209
+
210
+ while (ySize > 5) {
211
+
212
+ width = (Math.random() * 3) + 2;
213
+
214
+ axis = Math.round(Math.random());
215
+ sign = Math.round(Math.random());
216
+
217
+ ymin = baseWidth;
218
+ ymax = ySize;
219
+
220
+ switch (axis) {
221
+
222
+ case 0:
223
+
224
+ if (sign == 0) {
225
+
226
+ xmin = footprint.xmin;
227
+ zmin = zpos - width;
228
+
229
+ xmax = xpos + width;
230
+ zmax = zpos + width;
231
+
232
+ } else {
233
+
234
+ xmin = xpos - width;
235
+ zmin = zpos - width;
236
+
237
+ xmax = footprint.xmax;
238
+ zmax = zpos + width;
239
+ }
240
+
241
+ break;
242
+
243
+ case 1:
244
+
245
+
246
+ if (sign == 0) {
247
+
248
+ xmin = xpos - width;
249
+ zmin = footprint.zmin;
250
+
251
+ xmax = xpos + width;
252
+ zmax = zpos + width;
253
+
254
+ } else {
255
+
256
+ xmin = xpos - width;
257
+ zmin = zpos - width;
258
+
259
+ xmax = xpos + width;
260
+ zmax = footprint.zmax;
261
+ }
262
+
263
+ break;
264
+ }
265
+
266
+ addBox(
267
+ buildingType,
268
+ node,
269
+ (xmin + xmax) * 0.5,
270
+ ySize + baseWidth,
271
+ (zmin + zmax) * 0.5,
272
+
273
+ xmax - xmin,
274
+ ySize,
275
+ zmax - zmin);
276
+
277
+ ySize -= (Math.random() * 5) + 2;
278
+ }
279
+ }
280
+
281
+
282
+ function addBase(buildingType, node, xpos, zpos, xsize, ysize, zsize) {
283
+ node.addNode({
284
+ type:"translate",
285
+ x:xpos,
286
+ y:ysize,
287
+ z:zpos,
288
+ nodes:[
289
+ {
290
+ type:"material",
291
+ baseColor:{
292
+ r:0.6, g:.6, b:0.6
293
+ },
294
+ coreId:"building.base",
295
+ nodes:[
296
+ {
297
+ type:"geometry",
298
+ source:{
299
+ type:"box",
300
+ xSize:xsize,
301
+ ySize:ysize,
302
+ zSize:zsize
303
+ }
304
+ }
305
+ ]
306
+ }
307
+ ]
308
+ });
309
+ }
310
+
311
+ function addBox(buildingType, node, xpos, ypos, zpos, xsize, ysize, zsize) {
312
+
313
+ /* Roof cap
314
+ */
315
+ node.addNode(buildingType.roof.material)
316
+ .addNode({
317
+ type:"translate",
318
+ x:xpos,
319
+ y:ypos + ysize + buildingType.roof.height,
320
+ z:zpos
321
+ })
322
+ .addNode({
323
+ type:"geometry",
324
+ source:{
325
+ type:"box",
326
+ xSize:xsize,
327
+ ySize:buildingType.roof.height,
328
+ zSize:zsize
329
+ }
330
+ });
331
+
332
+ /* Body with texture
333
+ */
334
+ node.addNode(buildingType.material)// Current material
335
+ .addNode(buildingType.texture)// Current texture
336
+ .addNode({
337
+ type:"translate",
338
+ x:xpos,
339
+ y:ypos,
340
+ z:zpos
341
+ })
342
+ .addNode({
343
+ type:"geometry",
344
+ source:{
345
+ type:"box",
346
+ xSize:xsize,
347
+ ySize:ysize,
348
+ zSize:zsize
349
+ }
350
+ });
351
+ }
352
+ })();
@@ -0,0 +1,26 @@
1
+ SceneJS.Types.addType("objects/buildings/city", {
2
+
3
+ construct:function (params) {
4
+
5
+ var width = params.width || 600;
6
+ if (width < 100) {
7
+ throw "city width must be at least 100";
8
+ }
9
+ var halfWidth = width / 2;
10
+
11
+ // Add a grid of buildings
12
+ for (var x = -halfWidth; x < halfWidth; x += 50) {
13
+ for (var z = -halfWidth; z < halfWidth; z += 50) {
14
+ this.addNode({
15
+ type:"objects/buildings/building",
16
+ buildingType:Math.floor(Math.random() * 3), // Three building types
17
+ pos:{
18
+ x:x,
19
+ y:0,
20
+ z:z
21
+ }
22
+ });
23
+ }
24
+ }
25
+ }
26
+ });
@@ -0,0 +1,387 @@
1
+ /**
2
+ * A procedurally-generated tree
3
+ *
4
+ * This is a quick bit of fun that borrows the procedural tree generation
5
+ * code from the "Ghost Trees" Chrome Experiment by Marek Kapolka:
6
+ *
7
+ * http://www.chromeexperiments.com/detail/ghost-trees/
8
+ *
9
+ * Tree generation code is wrapped in a custom SceneJS node type defined in:
10
+ * http://scenejs.org/api/latest/plugins/node/objects/plants/ghostTree.js
11
+ *
12
+ * All the parameters for the tree generator are exposed as configurations
13
+ * for the node type.
14
+ *
15
+ */
16
+
17
+ (function () {
18
+
19
+ require([
20
+ SceneJS.getConfigs("pluginPath") + "/lib/gl-matrix-min.js"
21
+ ],
22
+ function (glmat) {
23
+
24
+ SceneJS.Types.addType("objects/plants/ghostTree", {
25
+
26
+ construct:function (params) {
27
+
28
+ if (params.minSegmentLength == undefined) params.minSegmentLength = 1;
29
+ if (params.maxSegmentLength == undefined) params.maxSegmentLength = 2;
30
+ if (params.minSegmentAngle == undefined) params.minSegmentAngle = Math.PI / 16;
31
+ if (params.maxSegmentAngle == undefined) params.maxSegmentAngle = Math.PI / 8;
32
+ if (params.minNumBranches == undefined) params.minNumBranches = 1;
33
+ if (params.maxNumBranches == undefined) params.maxNumBranches = 4;
34
+ if (params.segments == undefined) params.segments = 9;
35
+ if (params.branchLengthFactor == undefined) params.branchLengthFactor = 2;
36
+ if (params.branchAngleFactor == undefined) params.branchAngleFactor = 1.5;
37
+ if (params.branchSegmentFactor == undefined) params.branchSegmentFactor = 1;
38
+ if (params.branchBranchFactor == undefined) params.branchBranchFactor = .5;
39
+ if (params.color == undefined) params.color = [1, 1, 1];
40
+
41
+ var segment = generateSegment(null, params);
42
+ var height = countSegmentMaxHeight(segment);
43
+
44
+ this.addNode(buildGeometry(segment));
45
+ }
46
+ });
47
+
48
+ function buildGeometry(segment) {
49
+
50
+ var templateVertices = [];
51
+
52
+ for (var i = 0; i < 6; i++) {
53
+ var v = glmat.vec3.create();
54
+ glmat.vec3.set(v, Math.cos(i * Math.PI / 3), 0, Math.sin(i * Math.PI / 3));
55
+ templateVertices.push(v);
56
+ }
57
+
58
+ var vertexArray = templateVertices.slice(0);
59
+ var elementArray = [];
60
+ var colorArray = [];
61
+ //Initialize color array
62
+ for (var i = 0; i < vertexArray.length; i++) {
63
+ colorArray.push([1, 1, 1, 1]);
64
+ }
65
+ var rootMatrix = glmat.mat4.create();
66
+ glmat.mat4.identity(rootMatrix);
67
+
68
+ addSegmentToRenderable(vertexArray, elementArray, colorArray, 0, templateVertices, segment, rootMatrix, 0);
69
+
70
+ return {
71
+ type:"geometry",
72
+ primitive:"triangle-strip",
73
+ positions:unpackArray(vertexArray),
74
+ indices:elementArray,
75
+ colors:unpackArray(colorArray)
76
+ };
77
+ }
78
+
79
+ function Segment() {
80
+
81
+ //type: Segment
82
+ //The segment that precedes this one
83
+ this.prevSegment = null;
84
+
85
+ //type: Segment
86
+ //The segment that succeeds this one
87
+ this.nextSegment = null;
88
+
89
+ //Type: Array (of Segments)
90
+ //Contains the root segments of the branches connected to this Segment.
91
+ this.branches = [];
92
+
93
+ //Type: float
94
+ //The length of this segment in distance units
95
+ this.segmentLength = 1;
96
+
97
+ //Type: float (radians)
98
+ //The angle of this segment's rotation along the X/Y axis
99
+ this.angle = 0;
100
+
101
+ //Type: float (radians)
102
+ //The angle of this segment's rotation along the local Z axis
103
+ this.direction = 0;
104
+ }
105
+
106
+ function SegmentParameters() {
107
+
108
+ //Type: float
109
+ //The minimum and maximum lengths of a segment to use
110
+ //when generating a new segment
111
+ this.minSegmentLength = 1;
112
+ this.maxSegmentLength = 1;
113
+
114
+ //Type: float (radians)
115
+ //The minimum and maximum values of a segment's angle
116
+ //when generating a new segment
117
+ this.minSegmentAngle = 0;
118
+ this.maxSegmentAngle = 0;
119
+
120
+ //Type: int
121
+ //The minimum and maxiumum amount of branches to have on this segment
122
+ this.minNumBranches = 0;
123
+ this.maxNumBranches = 0;
124
+
125
+ //Type: int
126
+ //This value represents how many segments are left to be generated
127
+ //along this particular length of tree.
128
+ this.segments = 0;
129
+
130
+ //Type: float
131
+ //When generating a branch, the the min and max values of the branch's length
132
+ //will be multiplied by this value.
133
+ this.branchLengthFactor = 1;
134
+
135
+ //Type: float
136
+ //When generating a branch, the min and max value of the branch's angle will be
137
+ //multiplied by this factor
138
+ this.branchAngleFactor = 1;
139
+
140
+ //Type: float
141
+ //When generating a branch, the number of segments in the branch will be taken
142
+ //from it's root and multiplied by this factor.
143
+ this.branchSegmentFactor = 1;
144
+
145
+ //Type: float
146
+ //When generating a branch, the number of branches branching out from that branch
147
+ //Will be multiplied by this factor.
148
+ this.branchBranchFactor = 1;
149
+ }
150
+
151
+ //Generates a random value between min and max (inclusive)
152
+
153
+ function randomRange(min, max) {
154
+ return min + Math.random() * (max - min);
155
+ }
156
+
157
+ //Parameters:
158
+ //--root--
159
+ //Type: Segment
160
+ //The generated segment will stem from this segment
161
+ //--params--
162
+ //Type: SegmentParameters
163
+ //The values to use when generating this Segment
164
+
165
+ function generateSegment(root, params) {
166
+ var segment = new Segment();
167
+ segment.previousSegment = root;
168
+ segment.segmentLength = randomRange(params.minSegmentLength, params.maxSegmentLength);
169
+ segment.angle = randomRange(params.minSegmentAngle, params.maxSegmentAngle);
170
+ segment.direction = Math.random() * Math.PI * 2;
171
+
172
+ var numBranches = Math.floor(randomRange(params.minNumBranches, params.maxNumBranches));
173
+ var branchParams = branchSegmentParams(params);
174
+ for (var i = 0; i < numBranches; i++) {
175
+ var branch = generateSegment(segment, branchParams);
176
+ branch.prevSegment = segment;
177
+ segment.branches.push(branch);
178
+ }
179
+
180
+ if (params.segments > 1) {
181
+ //params.segments -= 1;
182
+ segment.nextSegment = generateSegment(segment, branchParams);
183
+ segment.nextSegment.prevSegment = segment;
184
+ }
185
+
186
+ return segment;
187
+ }
188
+
189
+ //Returns the root-most segment connected to the input Segment
190
+
191
+ function getBaseSegment(segment) {
192
+ if (segment.prevSegment === null) {
193
+ return segment;
194
+ } else {
195
+ return getBaseSegment(segment.prevSegment);
196
+ }
197
+ }
198
+
199
+ //Creates a new SegmentParameters object
200
+ //by shrinking the min and max values of the
201
+ //given SegmentParameters object by the factors specified
202
+ //in that object.
203
+ //Parameters:
204
+ //--params--
205
+ //Type: SegmentParameters
206
+ //The input SegmentParameters object that will have its values
207
+ //shrunk
208
+
209
+ function branchSegmentParams(params) {
210
+ var sp2 = new SegmentParameters();
211
+ sp2.minSegmentLength = params.minSegmentLength * params.branchLengthFactor;
212
+ sp2.maxSegmentLength = params.maxSegmentLength * params.branchLengthFactor;
213
+
214
+ sp2.minSegmentAngle = params.minSegmentAngle * params.branchAngleFactor;
215
+ sp2.maxSegmentAngle = params.maxSegmentAngle * params.branchAngleFactor;
216
+
217
+ sp2.minNumBranches = Math.floor(params.minNumBranches * params.branchBranchFactor);
218
+ sp2.maxNumBranches = Math.floor(params.maxNumBranches * params.branchBranchFactor);
219
+
220
+ sp2.segments = Math.floor(params.segments * params.branchSegmentFactor);
221
+ sp2.segments -= 1;
222
+
223
+ return sp2;
224
+ }
225
+
226
+ //Unpacks an array of vectors into an array of values.
227
+ //This is useful because the addSegmentToRenderable method
228
+ //expects the values in its vertexArray to be glMatrix vec3s, but
229
+ //WebGL buffers should be filled with primative values
230
+
231
+ function unpackArray(input) {
232
+ var output = [];
233
+
234
+ for (var child in input) {
235
+ for (var i = 0; i < input[child].length; i++) {
236
+ output.push(input[child][i]);
237
+ }
238
+ }
239
+
240
+ return output;
241
+ }
242
+
243
+ //Generates the vertex, element, and color array data for a tree segment
244
+ //and its children recursively.
245
+
246
+ function addSegmentToRenderable(vertexArray, elementArray, colorArray, rootIndexStart, templateVertices, segment, rootMatrix, level) {
247
+ var m = glmat.mat4.clone(rootMatrix);
248
+
249
+ var vUp = glmat.vec3.create();
250
+ glmat.vec3.set(vUp, 0, 1, 0);
251
+ var vFor = glmat.vec3.create();
252
+ glmat.vec3.set(vFor, Math.cos(segment.direction), 0, Math.sin(segment.direction));
253
+ var vRot = glmat.vec3.create();
254
+ vRot = glmat.vec3.cross(vRot, vUp, vFor);
255
+
256
+ glmat.mat4.rotate(m, m, segment.angle, vRot);
257
+ glmat.mat4.translate(m, m, [0, segment.segmentLength, 0]);
258
+
259
+ var startIndex = vertexArray.length;
260
+
261
+ var scaleMatrix = glmat.mat4.create();
262
+ glmat.mat4.identity(scaleMatrix);
263
+ //var dist = countSegmentMaxHeight(getBaseSegment(segment)) - countSegmentMaxHeight(segment);
264
+ var dist = getBaseSegment(segment).maxHeight - segment.maxHeight;
265
+ glmat.mat4.scale(scaleMatrix, scaleMatrix, [Math.pow(.6, dist), 1, Math.pow(.6, dist)]);
266
+ //Add vertices
267
+ for (var i in templateVertices) {
268
+ //Vertex Location
269
+ var v = glmat.vec3.clone(templateVertices[i]);
270
+ glmat.vec3.transformMat4(v, v, scaleMatrix);
271
+ glmat.vec3.transformMat4(v, v, m);
272
+ vertexArray.push(v);
273
+
274
+ //Color
275
+ var c = Math.pow(.8, level);
276
+ colorArray.push([c, c, c, 1]);
277
+ }
278
+
279
+ //Elements
280
+ for (var i = 0; i < templateVertices.length; i++) {
281
+ elementArray.push(rootIndexStart + i);
282
+ elementArray.push(startIndex + i);
283
+ }
284
+ //loop around
285
+ elementArray.push(rootIndexStart);
286
+ elementArray.push(startIndex);
287
+ //Degenerate
288
+ elementArray.push(startIndex);
289
+
290
+ //Up first
291
+ if (segment.nextSegment != null) {
292
+ addSegmentToRenderable(vertexArray, elementArray, colorArray, startIndex, templateVertices, segment.nextSegment, m, level + 1);
293
+ }
294
+
295
+ for (var branch in segment.branches) {
296
+ //discontinuous degenerate
297
+ elementArray.push(rootIndexStart);
298
+ elementArray.push(rootIndexStart);
299
+ addSegmentToRenderable(vertexArray, elementArray, colorArray, rootIndexStart, templateVertices, segment.branches[branch], rootMatrix, level);
300
+ }
301
+ }
302
+
303
+ //Generates the pattern of vertices that will be used for each ring of the tree
304
+
305
+ function makeTemplateVertices() {
306
+ var templateVertices = [];
307
+
308
+ for (var i = 0; i < 6; i++) {
309
+ var v = glmat.vec3.create();
310
+ glmat.vec3.set(v, Math.cos(i * Math.PI / 3), 0, Math.sin(i * Math.PI / 3));
311
+ templateVertices.push(v);
312
+ }
313
+
314
+ return templateVertices;
315
+ }
316
+
317
+ //Generates a Renderable tree from this segment and its children.
318
+
319
+ function makeSegmentRenderable(segment, glContext) {
320
+ var templateVertices = makeTemplateVertices();
321
+
322
+ var vertexArray = templateVertices.slice(0);
323
+ var elementArray = [];
324
+ var colorArray = [];
325
+ //Initialize color array
326
+ for (var i = 0; i < vertexArray.length; i++) {
327
+ colorArray.push([1, 1, 1, 1]);
328
+ }
329
+ var rootMatrix = glmat.mat4.create();
330
+ mat4.identity(rootMatrix);
331
+
332
+ var renderable = new Renderable(glContext);
333
+ renderable.mvMatrix = rootMatrix;
334
+
335
+ addSegmentToRenderable(vertexArray, elementArray, colorArray, 0, templateVertices, segment, rootMatrix, 0);
336
+
337
+ var upColors = unpackArray(colorArray);
338
+ var upVerts = unpackArray(vertexArray);
339
+ var upElements = elementArray;
340
+
341
+ renderable.setVertices(upVerts);
342
+ renderable.setElements(upElements);
343
+ renderable.setColors(upColors);
344
+
345
+ return renderable;
346
+ }
347
+
348
+ //Returns the maxiumum number of segments that follow this one
349
+ //Before a leaf segment is found
350
+
351
+ function countSegmentMaxHeight(segment) {
352
+ if (segment.nextSegment === null && segment.branches.length === 0) {
353
+ return 1;
354
+ } else {
355
+ var max = 0;
356
+ if (segment.nextSegment != null) {
357
+ max = countSegmentMaxHeight(segment.nextSegment) + 1;
358
+ } else {
359
+ max = 1;
360
+ }
361
+ for (var child in segment.branches) {
362
+ var ch = countSegmentMaxHeight(segment.branches[child]);
363
+ if (ch > max) {
364
+ max = ch;
365
+ }
366
+ }
367
+ segment.maxHeight = max;
368
+ return max;
369
+ }
370
+ }
371
+
372
+ //Counts the total number of segments below this segment in a tree.
373
+
374
+ function countNumSegments(segment) {
375
+ var output;
376
+ if (segment.nextSegment != null) {
377
+ output = countNumSegments(segment.nextSegment) + 1;
378
+ } else {
379
+ output = 1;
380
+ }
381
+ for (var branch in segment.branches) {
382
+ output += countNumSegments(branch);
383
+ }
384
+ return output;
385
+ }
386
+ });
387
+ })();