jax 0.0.0.5 → 0.0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/CHANGELOG +26 -1
  2. data/Rakefile +3 -1
  3. data/builtin/shaders/picking/common.ejs +2 -0
  4. data/builtin/shaders/picking/fragment.ejs +4 -0
  5. data/builtin/shaders/picking/material.js +14 -0
  6. data/builtin/shaders/picking/vertex.ejs +24 -0
  7. data/lib/jax/generators/app/templates/public/javascripts/jax.js +289 -681
  8. data/lib/jax/generators/app/templates/spec/javascripts/support/spec_layout.html.erb +55 -2
  9. data/lib/jax/generators/shader/templates/common.ejs.tt +2 -2
  10. data/lib/jax/packager/sprockets_template.rb +1 -4
  11. data/lib/jax/routes.rb +3 -0
  12. data/lib/jax/version.rb +1 -1
  13. data/spec/example_app/app/controllers/noise_controller.js +37 -5
  14. data/spec/example_app/app/controllers/picking_controller.js +32 -0
  15. data/spec/example_app/app/helpers/picking_helper.js +3 -0
  16. data/spec/example_app/app/models/blob.js +38 -0
  17. data/spec/example_app/app/resources/blobs/default.yml +2 -0
  18. data/spec/example_app/app/resources/materials/blob.yml +2 -2
  19. data/spec/example_app/app/shaders/blob/common.ejs +8 -13
  20. data/spec/example_app/app/shaders/blob/fragment.ejs +1 -1
  21. data/spec/example_app/app/shaders/blob/material.js +15 -12
  22. data/spec/example_app/app/shaders/blob/vertex.ejs +33 -8
  23. data/spec/example_app/app/views/picking/index.js +4 -0
  24. data/spec/example_app/config/routes.rb +1 -0
  25. data/spec/example_app/spec/javascripts/controllers/picking_controller_spec.js +11 -0
  26. data/spec/example_app/spec/javascripts/helpers/picking_helper_spec.js +12 -0
  27. data/spec/example_app/spec/javascripts/models/blob_spec.js +11 -0
  28. data/spec/example_app/spec/javascripts/support/spec_layout.html.erb +40 -2
  29. data/spec/javascripts/jax/model_spec.js +10 -0
  30. data/spec/javascripts/jax/world_spec.js +74 -1
  31. data/spec/javascripts/shaders/preprocessor_spec.js +35 -0
  32. data/src/constants.yml +1 -1
  33. data/src/jax.js +30 -8
  34. data/src/jax/anim_frame.js +6 -2
  35. data/src/jax/builtin/meshes/cube.js +22 -1
  36. data/src/jax/builtin/meshes/plane.js +27 -0
  37. data/src/jax/builtin/meshes/quad.js +7 -1
  38. data/src/jax/builtin/meshes/sphere.js +20 -1
  39. data/src/jax/builtin/meshes/teapot.js +10 -0
  40. data/src/jax/builtin/meshes/torus.js +18 -0
  41. data/src/jax/compatibility.js +165 -2
  42. data/src/jax/context.js +176 -9
  43. data/src/jax/core.js +6 -3
  44. data/src/jax/core/math.js +18 -3
  45. data/src/jax/core/matrix_stack.js +4 -3
  46. data/src/jax/core/util.js +15 -0
  47. data/src/jax/events.js +67 -12
  48. data/src/jax/geometry.js +5 -1
  49. data/src/jax/geometry/plane.js +59 -5
  50. data/src/jax/{controller.js → mvc/controller.js} +38 -0
  51. data/src/jax/mvc/helper.js +35 -0
  52. data/src/jax/mvc/model.js +301 -0
  53. data/src/jax/{route_set.js → mvc/route_set.js} +0 -0
  54. data/src/jax/{view.js → mvc/view.js} +6 -0
  55. data/src/jax/{view_manager.js → mvc/view_manager.js} +1 -0
  56. data/src/jax/noise.js +13 -0
  57. data/src/jax/prototype/class.js +3 -0
  58. data/src/jax/prototype/extensions.js +26 -8
  59. data/src/jax/webgl/camera.js +6 -6
  60. data/src/jax/webgl/core/framebuffer.js +4 -4
  61. data/src/jax/webgl/material.js +16 -0
  62. data/src/jax/webgl/mesh.js +19 -4
  63. data/src/jax/webgl/scene/light_manager.js +8 -0
  64. data/src/jax/webgl/scene/light_source.js +3 -3
  65. data/src/jax/webgl/shader.js +4 -2
  66. data/src/jax/webgl/shader_chain.js +1 -0
  67. data/src/jax/webgl/world.js +157 -6
  68. data/vendor/glmatrix/glMatrix.js +365 -408
  69. metadata +32 -10
  70. data/src/jax/helper.js +0 -8
  71. data/src/jax/model.js +0 -163
data/CHANGELOG CHANGED
@@ -1,3 +1,27 @@
1
+ * 0.0.0.6 *
2
+
3
+ * Introduced Jax.uptime, a running total of number of seconds since the Jax subsystem
4
+ was _loaded_ (not necessarily instantiated). This is now used in place of various
5
+ timers in Jax, e.g. for calculating the +timechange+ argument to #update methods.
6
+
7
+ * Added 'picking' support via Jax.World#pick(x,y); Jax.World#pickIndex(x,y);
8
+ Jax.World#pickRegion(x1,y1, x2,y2); Jax.World#pickRegionalIndices(x1,y1, x2,y2).
9
+ This is the last milestone prior to v1.0 release.
10
+
11
+ * Lots of new JavaScript API documentation
12
+
13
+ * Renamed Jax.Camera#getModelViewMatrix() to Jax.Camera#getTransformationMatrix().
14
+ The latter is more accurate. THIS WILL BREAK EXISTING APPS but since Jax is still
15
+ considered pre-release I'm not taking the extra step to deprecate it.
16
+
17
+ * Added Jax version number and framerate counter to spec layouts
18
+
19
+ * Added perlin noise example to /spec/example_app
20
+
21
+ * Added aliases for Math.radToDeg / Math.rad2deg and Math.degToRad / Math.deg2rad
22
+
23
+
24
+
1
25
  * 0.0.0.5 *
2
26
 
3
27
  * Jax now checks JS version against gem version and reports on mismatches
@@ -9,6 +33,7 @@
9
33
  This makes it possible to reuse paraboloids for environment mapping.
10
34
 
11
35
  * Shader dependencies are now loaded via Jax.shader_load_paths, which can be multiple
12
- different directories (e.g. Jax builtin + app/shaders)
36
+ different directories (e.g. Jax builtin + app/shaders) This makes functions used by
37
+ Jax available for reuse in custom shaders.
13
38
 
14
39
  * Added CHANGELOG. :)
data/Rakefile CHANGED
@@ -95,7 +95,9 @@ namespace :doc do
95
95
  FileUtils.rm_rf 'doc'
96
96
 
97
97
  PDoc.run({
98
- :source_files => [File.join('src', 'jax.js')] + Dir[File.join('src', 'jax', '**', '*.js')],
98
+ :source_files => (['src/jax.js', 'vendor/glmatrix/glMatrix.js'] +
99
+ # Dir['vendor/ejs/src/**/*.js'] +
100
+ Dir['src/jax/**/*.js']),
99
101
  :destination => "doc",
100
102
  # :index_page => 'src/README.markdown',
101
103
  :syntax_highlighter => 'coderay',
@@ -0,0 +1,2 @@
1
+ uniform float INDEX;
2
+ varying vec4 vColor;
@@ -0,0 +1,4 @@
1
+ void main(void) {
2
+ if (INDEX == -1.0) discard;
3
+ gl_FragColor = vColor;
4
+ }
@@ -0,0 +1,14 @@
1
+ Jax.Material.Picking = Jax.Class.create(Jax.Material, {
2
+ initialize: function($super) {
3
+ $super({shader:"picking"});
4
+ },
5
+
6
+ setUniforms: function($super, context, mesh, options, uniforms) {
7
+ $super(context, mesh, options, uniforms);
8
+
9
+ model_index = options.model_index;
10
+ if (model_index == undefined) model_index = -1;
11
+
12
+ uniforms.set('INDEX', model_index);
13
+ }
14
+ });
@@ -0,0 +1,24 @@
1
+ shared attribute vec4 VERTEX_POSITION;
2
+
3
+ shared uniform mat4 mvMatrix, pMatrix;
4
+
5
+ void main(void) {
6
+ gl_Position = pMatrix * mvMatrix * VERTEX_POSITION;
7
+
8
+ /*
9
+ Note that the agorithm here must be followed exactly on the JS side in order
10
+ to reconstitute the index when it is read.
11
+
12
+ This supports 65,535 objects. If more are needed, we could feasibly open up
13
+ the alpha channel, as long as blending is disabled. Need to do more tests
14
+ on this first, however.
15
+ */
16
+
17
+
18
+ // equivalent to [ int(INDEX/256), INDEX % 256 ] / 255. The last division
19
+ // is necessary to scale to the [0..1] range.
20
+
21
+ float d = 1.0 / 255.0;
22
+ float f = floor(INDEX / 256.0);
23
+ vColor = vec4(f * d, (INDEX - 256.0 * f) * d, 1.0, 1.0);
24
+ }
@@ -1,4 +1,5 @@
1
- var Jax = { PRODUCTION: 1, VERSION: "0.0.0.5" };
1
+
2
+ var Jax = { PRODUCTION: 1, VERSION: "0.0.0.6" };
2
3
 
3
4
  /* Called by Jax applications as of version 0.0.0.5 to alert the user to incomplete upgrades */
4
5
  Jax.doVersionCheck = function(targetVersion) {
@@ -14,6 +15,16 @@ Jax.doVersionCheck = function(targetVersion) {
14
15
  Jax.default_shader = "basic";
15
16
 
16
17
  /* Defines constants, functions, etc. that may exist in one browser but not in another */
18
+ Jax.Compatibility = (function() {
19
+ var offsetTop = 1;
20
+ var offsetLeft = 1;
21
+
22
+ return {
23
+ offsetTop: offsetTop,
24
+
25
+ offsetLeft: offsetLeft,
26
+ };
27
+ })();
17
28
 
18
29
  /*
19
30
  Object.keys defined only in the newest browsers. If they're going to fail, let them fail due to HTML5 incompatibility
@@ -28,6 +39,11 @@ if (!Object.keys) {
28
39
  };
29
40
  }
30
41
 
42
+ Array.prototype.clear = Array.prototype.clear || function() {
43
+ this.splice(0, this.length);
44
+ return this;
45
+ };
46
+
31
47
 
32
48
  /* KeyEvent in Firefox contains various keyCode constants, but they are missing in Chrome. */
33
49
  if (typeof(KeyEvent) == "undefined") {
@@ -890,22 +906,8 @@ if(typeof Float32Array != 'undefined') {
890
906
  glMatrixArrayType = Array;
891
907
  }
892
908
 
893
- /*
894
- * vec3 - 3 Dimensional Vector
895
- */
896
909
  var vec3 = {};
897
910
 
898
- /*
899
- * vec3.create
900
- * Creates a new instance of a vec3 using the default array type
901
- * Any javascript array containing at least 3 numeric elements can serve as a vec3
902
- *
903
- * Params:
904
- * vec - Optional, vec3 containing values to initialize with
905
- *
906
- * Returns:
907
- * New vec3
908
- */
909
911
  vec3.create = function(vec) {
910
912
  var dest = new glMatrixArrayType(3);
911
913
 
@@ -918,17 +920,6 @@ vec3.create = function(vec) {
918
920
  return dest;
919
921
  };
920
922
 
921
- /*
922
- * vec3.set
923
- * Copies the values of one vec3 to another
924
- *
925
- * Params:
926
- * vec - vec3 containing values to copy
927
- * dest - vec3 receiving copied values
928
- *
929
- * Returns:
930
- * dest
931
- */
932
923
  vec3.set = function(vec, dest) {
933
924
  dest[0] = vec[0];
934
925
  dest[1] = vec[1];
@@ -937,18 +928,6 @@ vec3.set = function(vec, dest) {
937
928
  return dest;
938
929
  };
939
930
 
940
- /*
941
- * vec3.add
942
- * Performs a vector addition
943
- *
944
- * Params:
945
- * vec - vec3, first operand
946
- * vec2 - vec3, second operand
947
- * dest - Optional, vec3 receiving operation result. If not specified result is written to vec
948
- *
949
- * Returns:
950
- * dest if specified, vec otherwise
951
- */
952
931
  vec3.add = function(vec, vec2, dest) {
953
932
  if(!dest || vec == dest) {
954
933
  vec[0] += vec2[0];
@@ -963,18 +942,6 @@ vec3.add = function(vec, vec2, dest) {
963
942
  return dest;
964
943
  };
965
944
 
966
- /*
967
- * vec3.subtract
968
- * Performs a vector subtraction
969
- *
970
- * Params:
971
- * vec - vec3, first operand
972
- * vec2 - vec3, second operand
973
- * dest - Optional, vec3 receiving operation result. If not specified result is written to vec
974
- *
975
- * Returns:
976
- * dest if specified, vec otherwise
977
- */
978
945
  vec3.subtract = function(vec, vec2, dest) {
979
946
  if(!dest || vec == dest) {
980
947
  vec[0] -= vec2[0];
@@ -989,17 +956,6 @@ vec3.subtract = function(vec, vec2, dest) {
989
956
  return dest;
990
957
  };
991
958
 
992
- /*
993
- * vec3.negate
994
- * Negates the components of a vec3
995
- *
996
- * Params:
997
- * vec - vec3 to negate
998
- * dest - Optional, vec3 receiving operation result. If not specified result is written to vec
999
- *
1000
- * Returns:
1001
- * dest if specified, vec otherwise
1002
- */
1003
959
  vec3.negate = function(vec, dest) {
1004
960
  if(!dest) { dest = vec; }
1005
961
 
@@ -1009,18 +965,6 @@ vec3.negate = function(vec, dest) {
1009
965
  return dest;
1010
966
  };
1011
967
 
1012
- /*
1013
- * vec3.scale
1014
- * Multiplies the components of a vec3 by a scalar value
1015
- *
1016
- * Params:
1017
- * vec - vec3 to scale
1018
- * val - Numeric value to scale by
1019
- * dest - Optional, vec3 receiving operation result. If not specified result is written to vec
1020
- *
1021
- * Returns:
1022
- * dest if specified, vec otherwise
1023
- */
1024
968
  vec3.scale = function(vec, val, dest) {
1025
969
  if(!dest || vec == dest) {
1026
970
  vec[0] *= val;
@@ -1035,18 +979,6 @@ vec3.scale = function(vec, val, dest) {
1035
979
  return dest;
1036
980
  };
1037
981
 
1038
- /*
1039
- * vec3.normalize
1040
- * Generates a unit vector of the same direction as the provided vec3
1041
- * If vector length is 0, returns [0, 0, 0]
1042
- *
1043
- * Params:
1044
- * vec - vec3 to normalize
1045
- * dest - Optional, vec3 receiving operation result. If not specified result is written to vec
1046
- *
1047
- * Returns:
1048
- * dest if specified, vec otherwise
1049
- */
1050
982
  vec3.normalize = function(vec, dest) {
1051
983
  if(!dest) { dest = vec; }
1052
984
 
@@ -1072,18 +1004,6 @@ vec3.normalize = function(vec, dest) {
1072
1004
  return dest;
1073
1005
  };
1074
1006
 
1075
- /*
1076
- * vec3.cross
1077
- * Generates the cross product of two vec3s
1078
- *
1079
- * Params:
1080
- * vec - vec3, first operand
1081
- * vec2 - vec3, second operand
1082
- * dest - Optional, vec3 receiving operation result. If not specified result is written to vec
1083
- *
1084
- * Returns:
1085
- * dest if specified, vec otherwise
1086
- */
1087
1007
  vec3.cross = function(vec, vec2, dest){
1088
1008
  if(!dest) { dest = vec; }
1089
1009
 
@@ -1096,48 +1016,15 @@ vec3.cross = function(vec, vec2, dest){
1096
1016
  return dest;
1097
1017
  };
1098
1018
 
1099
- /*
1100
- * vec3.length
1101
- * Caclulates the length of a vec3
1102
- *
1103
- * Params:
1104
- * vec - vec3 to calculate length of
1105
- *
1106
- * Returns:
1107
- * Length of vec
1108
- */
1109
1019
  vec3.length = function(vec){
1110
1020
  var x = vec[0], y = vec[1], z = vec[2];
1111
1021
  return Math.sqrt(x*x + y*y + z*z);
1112
1022
  };
1113
1023
 
1114
- /*
1115
- * vec3.dot
1116
- * Caclulates the dot product of two vec3s
1117
- *
1118
- * Params:
1119
- * vec - vec3, first operand
1120
- * vec2 - vec3, second operand
1121
- *
1122
- * Returns:
1123
- * Dot product of vec and vec2
1124
- */
1125
1024
  vec3.dot = function(vec, vec2){
1126
1025
  return vec[0]*vec2[0] + vec[1]*vec2[1] + vec[2]*vec2[2];
1127
1026
  };
1128
1027
 
1129
- /*
1130
- * vec3.direction
1131
- * Generates a unit vector pointing from one vector to another
1132
- *
1133
- * Params:
1134
- * vec - origin vec3
1135
- * vec2 - vec3 to point to
1136
- * dest - Optional, vec3 receiving operation result. If not specified result is written to vec
1137
- *
1138
- * Returns:
1139
- * dest if specified, vec otherwise
1140
- */
1141
1028
  vec3.direction = function(vec, vec2, dest) {
1142
1029
  if(!dest) { dest = vec; }
1143
1030
 
@@ -1160,19 +1047,6 @@ vec3.direction = function(vec, vec2, dest) {
1160
1047
  return dest;
1161
1048
  };
1162
1049
 
1163
- /*
1164
- * vec3.lerp
1165
- * Performs a linear interpolation between two vec3
1166
- *
1167
- * Params:
1168
- * vec - vec3, first vector
1169
- * vec2 - vec3, second vector
1170
- * lerp - interpolation amount between the two inputs
1171
- * dest - Optional, vec3 receiving operation result. If not specified result is written to vec
1172
- *
1173
- * Returns:
1174
- * dest if specified, vec otherwise
1175
- */
1176
1050
  vec3.lerp = function(vec, vec2, lerp, dest){
1177
1051
  if(!dest) { dest = vec; }
1178
1052
 
@@ -1183,36 +1057,12 @@ vec3.lerp = function(vec, vec2, lerp, dest){
1183
1057
  return dest;
1184
1058
  }
1185
1059
 
1186
- /*
1187
- * vec3.str
1188
- * Returns a string representation of a vector
1189
- *
1190
- * Params:
1191
- * vec - vec3 to represent as a string
1192
- *
1193
- * Returns:
1194
- * string representation of vec
1195
- */
1196
1060
  vec3.str = function(vec) {
1197
1061
  return '[' + vec[0] + ', ' + vec[1] + ', ' + vec[2] + ']';
1198
1062
  };
1199
1063
 
1200
- /*
1201
- * mat3 - 3x3 Matrix
1202
- */
1203
1064
  var mat3 = {};
1204
1065
 
1205
- /*
1206
- * mat3.create
1207
- * Creates a new instance of a mat3 using the default array type
1208
- * Any javascript array containing at least 9 numeric elements can serve as a mat3
1209
- *
1210
- * Params:
1211
- * mat - Optional, mat3 containing values to initialize with
1212
- *
1213
- * Returns:
1214
- * New mat3
1215
- */
1216
1066
  mat3.create = function(mat) {
1217
1067
  var dest = new glMatrixArrayType(9);
1218
1068
 
@@ -1232,17 +1082,6 @@ mat3.create = function(mat) {
1232
1082
  return dest;
1233
1083
  };
1234
1084
 
1235
- /*
1236
- * mat3.set
1237
- * Copies the values of one mat3 to another
1238
- *
1239
- * Params:
1240
- * mat - mat3 containing values to copy
1241
- * dest - mat3 receiving copied values
1242
- *
1243
- * Returns:
1244
- * dest
1245
- */
1246
1085
  mat3.set = function(mat, dest) {
1247
1086
  dest[0] = mat[0];
1248
1087
  dest[1] = mat[1];
@@ -1256,16 +1095,6 @@ mat3.set = function(mat, dest) {
1256
1095
  return dest;
1257
1096
  };
1258
1097
 
1259
- /*
1260
- * mat3.identity
1261
- * Sets a mat3 to an identity matrix
1262
- *
1263
- * Params:
1264
- * dest - mat3 to set
1265
- *
1266
- * Returns:
1267
- * dest
1268
- */
1269
1098
  mat3.identity = function(dest) {
1270
1099
  dest[0] = 1;
1271
1100
  dest[1] = 0;
@@ -1279,17 +1108,6 @@ mat3.identity = function(dest) {
1279
1108
  return dest;
1280
1109
  };
1281
1110
 
1282
- /*
1283
- * mat4.transpose
1284
- * Transposes a mat3 (flips the values over the diagonal)
1285
- *
1286
- * Params:
1287
- * mat - mat3 to transpose
1288
- * dest - Optional, mat3 receiving transposed values. If not specified result is written to mat
1289
- *
1290
- * Returns:
1291
- * dest is specified, mat otherwise
1292
- */
1293
1111
  mat3.transpose = function(mat, dest) {
1294
1112
  if(!dest || mat == dest) {
1295
1113
  var a01 = mat[1], a02 = mat[2];
@@ -1316,17 +1134,6 @@ mat3.transpose = function(mat, dest) {
1316
1134
  return dest;
1317
1135
  };
1318
1136
 
1319
- /*
1320
- * mat3.toMat4
1321
- * Copies the elements of a mat3 into the upper 3x3 elements of a mat4
1322
- *
1323
- * Params:
1324
- * mat - mat3 containing values to copy
1325
- * dest - Optional, mat4 receiving copied values
1326
- *
1327
- * Returns:
1328
- * dest if specified, a new mat4 otherwise
1329
- */
1330
1137
  mat3.toMat4 = function(mat, dest) {
1331
1138
  if(!dest) { dest = mat4.create(); }
1332
1139
 
@@ -1353,38 +1160,14 @@ mat3.toMat4 = function(mat, dest) {
1353
1160
  return dest;
1354
1161
  }
1355
1162
 
1356
- /*
1357
- * mat3.str
1358
- * Returns a string representation of a mat3
1359
- *
1360
- * Params:
1361
- * mat - mat3 to represent as a string
1362
- *
1363
- * Returns:
1364
- * string representation of mat
1365
- */
1366
1163
  mat3.str = function(mat) {
1367
1164
  return '[' + mat[0] + ', ' + mat[1] + ', ' + mat[2] +
1368
1165
  ', ' + mat[3] + ', '+ mat[4] + ', ' + mat[5] +
1369
1166
  ', ' + mat[6] + ', ' + mat[7] + ', '+ mat[8] + ']';
1370
1167
  };
1371
1168
 
1372
- /*
1373
- * mat4 - 4x4 Matrix
1374
- */
1375
1169
  var mat4 = {};
1376
1170
 
1377
- /*
1378
- * mat4.create
1379
- * Creates a new instance of a mat4 using the default array type
1380
- * Any javascript array containing at least 16 numeric elements can serve as a mat4
1381
- *
1382
- * Params:
1383
- * mat - Optional, mat4 containing values to initialize with
1384
- *
1385
- * Returns:
1386
- * New mat4
1387
- */
1388
1171
  mat4.create = function(mat) {
1389
1172
  var dest = new glMatrixArrayType(16);
1390
1173
 
@@ -1410,17 +1193,6 @@ mat4.create = function(mat) {
1410
1193
  return dest;
1411
1194
  };
1412
1195
 
1413
- /*
1414
- * mat4.set
1415
- * Copies the values of one mat4 to another
1416
- *
1417
- * Params:
1418
- * mat - mat4 containing values to copy
1419
- * dest - mat4 receiving copied values
1420
- *
1421
- * Returns:
1422
- * dest
1423
- */
1424
1196
  mat4.set = function(mat, dest) {
1425
1197
  dest[0] = mat[0];
1426
1198
  dest[1] = mat[1];
@@ -1441,16 +1213,6 @@ mat4.set = function(mat, dest) {
1441
1213
  return dest;
1442
1214
  };
1443
1215
 
1444
- /*
1445
- * mat4.identity
1446
- * Sets a mat4 to an identity matrix
1447
- *
1448
- * Params:
1449
- * dest - mat4 to set
1450
- *
1451
- * Returns:
1452
- * dest
1453
- */
1454
1216
  mat4.identity = function(dest) {
1455
1217
  dest[0] = 1;
1456
1218
  dest[1] = 0;
@@ -1471,17 +1233,6 @@ mat4.identity = function(dest) {
1471
1233
  return dest;
1472
1234
  };
1473
1235
 
1474
- /*
1475
- * mat4.transpose
1476
- * Transposes a mat4 (flips the values over the diagonal)
1477
- *
1478
- * Params:
1479
- * mat - mat4 to transpose
1480
- * dest - Optional, mat4 receiving transposed values. If not specified result is written to mat
1481
- *
1482
- * Returns:
1483
- * dest is specified, mat otherwise
1484
- */
1485
1236
  mat4.transpose = function(mat, dest) {
1486
1237
  if(!dest || mat == dest) {
1487
1238
  var a01 = mat[1], a02 = mat[2], a03 = mat[3];
@@ -1522,16 +1273,6 @@ mat4.transpose = function(mat, dest) {
1522
1273
  return dest;
1523
1274
  };
1524
1275
 
1525
- /*
1526
- * mat4.determinant
1527
- * Calculates the determinant of a mat4
1528
- *
1529
- * Params:
1530
- * mat - mat4 to calculate determinant of
1531
- *
1532
- * Returns:
1533
- * determinant of mat
1534
- */
1535
1276
  mat4.determinant = function(mat) {
1536
1277
  var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3];
1537
1278
  var a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7];
@@ -1546,17 +1287,6 @@ mat4.determinant = function(mat) {
1546
1287
  a20*a01*a12*a33 - a00*a21*a12*a33 - a10*a01*a22*a33 + a00*a11*a22*a33;
1547
1288
  };
1548
1289
 
1549
- /*
1550
- * mat4.inverse
1551
- * Calculates the inverse matrix of a mat4
1552
- *
1553
- * Params:
1554
- * mat - mat4 to calculate inverse of
1555
- * dest - Optional, mat4 receiving inverse matrix. If not specified result is written to mat
1556
- *
1557
- * Returns:
1558
- * dest is specified, mat otherwise
1559
- */
1560
1290
  mat4.inverse = function(mat, dest) {
1561
1291
  if(!dest) { dest = mat; }
1562
1292
 
@@ -1600,17 +1330,6 @@ mat4.inverse = function(mat, dest) {
1600
1330
  return dest;
1601
1331
  };
1602
1332
 
1603
- /*
1604
- * mat4.toRotationMat
1605
- * Copies the upper 3x3 elements of a mat4 into another mat4
1606
- *
1607
- * Params:
1608
- * mat - mat4 containing values to copy
1609
- * dest - Optional, mat4 receiving copied values
1610
- *
1611
- * Returns:
1612
- * dest is specified, a new mat4 otherwise
1613
- */
1614
1333
  mat4.toRotationMat = function(mat, dest) {
1615
1334
  if(!dest) { dest = mat4.create(); }
1616
1335
 
@@ -1634,17 +1353,6 @@ mat4.toRotationMat = function(mat, dest) {
1634
1353
  return dest;
1635
1354
  };
1636
1355
 
1637
- /*
1638
- * mat4.toMat3
1639
- * Copies the upper 3x3 elements of a mat4 into a mat3
1640
- *
1641
- * Params:
1642
- * mat - mat4 containing values to copy
1643
- * dest - Optional, mat3 receiving copied values
1644
- *
1645
- * Returns:
1646
- * dest is specified, a new mat3 otherwise
1647
- */
1648
1356
  mat4.toMat3 = function(mat, dest) {
1649
1357
  if(!dest) { dest = mat3.create(); }
1650
1358
 
@@ -1661,18 +1369,6 @@ mat4.toMat3 = function(mat, dest) {
1661
1369
  return dest;
1662
1370
  };
1663
1371
 
1664
- /*
1665
- * mat4.toInverseMat3
1666
- * Calculates the inverse of the upper 3x3 elements of a mat4 and copies the result into a mat3
1667
- * The resulting matrix is useful for calculating transformed normals
1668
- *
1669
- * Params:
1670
- * mat - mat4 containing values to invert and copy
1671
- * dest - Optional, mat3 receiving values
1672
- *
1673
- * Returns:
1674
- * dest is specified, a new mat3 otherwise
1675
- */
1676
1372
  mat4.toInverseMat3 = function(mat, dest) {
1677
1373
  var a00 = mat[0], a01 = mat[1], a02 = mat[2];
1678
1374
  var a10 = mat[4], a11 = mat[5], a12 = mat[6];
@@ -1701,18 +1397,6 @@ mat4.toInverseMat3 = function(mat, dest) {
1701
1397
  return dest;
1702
1398
  };
1703
1399
 
1704
- /*
1705
- * mat4.multiply
1706
- * Performs a matrix multiplication
1707
- *
1708
- * Params:
1709
- * mat - mat4, first operand
1710
- * mat2 - mat4, second operand
1711
- * dest - Optional, mat4 receiving operation result. If not specified result is written to mat
1712
- *
1713
- * Returns:
1714
- * dest if specified, mat otherwise
1715
- */
1716
1400
  mat4.multiply = function(mat, mat2, dest) {
1717
1401
  if(!dest) { dest = mat }
1718
1402
 
@@ -1746,19 +1430,6 @@ mat4.multiply = function(mat, mat2, dest) {
1746
1430
  return dest;
1747
1431
  };
1748
1432
 
1749
- /*
1750
- * mat4.multiplyVec3
1751
- * Transforms a vec3 with the given matrix
1752
- * 4th vector component is implicitly '1'
1753
- *
1754
- * Params:
1755
- * mat - mat4 to transform the vector with
1756
- * vec - vec3 to transform
1757
- * dest - Optional, vec3 receiving operation result. If not specified result is written to vec
1758
- *
1759
- * Returns:
1760
- * dest if specified, vec otherwise
1761
- */
1762
1433
  mat4.multiplyVec3 = function(mat, vec, dest) {
1763
1434
  if(!dest) { dest = vec }
1764
1435
 
@@ -1771,18 +1442,6 @@ mat4.multiplyVec3 = function(mat, vec, dest) {
1771
1442
  return dest;
1772
1443
  };
1773
1444
 
1774
- /*
1775
- * mat4.multiplyVec4
1776
- * Transforms a vec4 with the given matrix
1777
- *
1778
- * Params:
1779
- * mat - mat4 to transform the vector with
1780
- * vec - vec4 to transform
1781
- * dest - Optional, vec4 receiving operation result. If not specified result is written to vec
1782
- *
1783
- * Returns:
1784
- * dest if specified, vec otherwise
1785
- */
1786
1445
  mat4.multiplyVec4 = function(mat, vec, dest) {
1787
1446
  if(!dest) { dest = vec }
1788
1447
 
@@ -1796,18 +1455,6 @@ mat4.multiplyVec4 = function(mat, vec, dest) {
1796
1455
  return dest;
1797
1456
  };
1798
1457
 
1799
- /*
1800
- * mat4.translate
1801
- * Translates a matrix by the given vector
1802
- *
1803
- * Params:
1804
- * mat - mat4 to translate
1805
- * vec - vec3 specifying the translation
1806
- * dest - Optional, mat4 receiving operation result. If not specified result is written to mat
1807
- *
1808
- * Returns:
1809
- * dest if specified, mat otherwise
1810
- */
1811
1458
  mat4.translate = function(mat, vec, dest) {
1812
1459
  var x = vec[0], y = vec[1], z = vec[2];
1813
1460
 
@@ -1843,18 +1490,6 @@ mat4.translate = function(mat, vec, dest) {
1843
1490
  return dest;
1844
1491
  };
1845
1492
 
1846
- /*
1847
- * mat4.scale
1848
- * Scales a matrix by the given vector
1849
- *
1850
- * Params:
1851
- * mat - mat4 to scale
1852
- * vec - vec3 specifying the scale for each axis
1853
- * dest - Optional, mat4 receiving operation result. If not specified result is written to mat
1854
- *
1855
- * Returns:
1856
- * dest if specified, mat otherwise
1857
- */
1858
1493
  mat4.scale = function(mat, vec, dest) {
1859
1494
  var x = vec[0], y = vec[1], z = vec[2];
1860
1495
 
@@ -1893,20 +1528,6 @@ mat4.scale = function(mat, vec, dest) {
1893
1528
  return dest;
1894
1529
  };
1895
1530
 
1896
- /*
1897
- * mat4.rotate
1898
- * Rotates a matrix by the given angle around the specified axis
1899
- * If rotating around a primary axis (X,Y,Z) one of the specialized rotation functions should be used instead for performance
1900
- *
1901
- * Params:
1902
- * mat - mat4 to rotate
1903
- * angle - angle (in radians) to rotate
1904
- * axis - vec3 representing the axis to rotate around
1905
- * dest - Optional, mat4 receiving operation result. If not specified result is written to mat
1906
- *
1907
- * Returns:
1908
- * dest if specified, mat otherwise
1909
- */
1910
1531
  mat4.rotate = function(mat, angle, axis, dest) {
1911
1532
  var x = axis[0], y = axis[1], z = axis[2];
1912
1533
  var len = Math.sqrt(x*x + y*y + z*z);
@@ -1956,18 +1577,6 @@ mat4.rotate = function(mat, angle, axis, dest) {
1956
1577
  return dest;
1957
1578
  };
1958
1579
 
1959
- /*
1960
- * mat4.rotateX
1961
- * Rotates a matrix by the given angle around the X axis
1962
- *
1963
- * Params:
1964
- * mat - mat4 to rotate
1965
- * angle - angle (in radians) to rotate
1966
- * dest - Optional, mat4 receiving operation result. If not specified result is written to mat
1967
- *
1968
- * Returns:
1969
- * dest if specified, mat otherwise
1970
- */
1971
1580
  mat4.rotateX = function(mat, angle, dest) {
1972
1581
  var s = Math.sin(angle);
1973
1582
  var c = Math.cos(angle);
@@ -2001,18 +1610,6 @@ mat4.rotateX = function(mat, angle, dest) {
2001
1610
  return dest;
2002
1611
  };
2003
1612
 
2004
- /*
2005
- * mat4.rotateY
2006
- * Rotates a matrix by the given angle around the Y axis
2007
- *
2008
- * Params:
2009
- * mat - mat4 to rotate
2010
- * angle - angle (in radians) to rotate
2011
- * dest - Optional, mat4 receiving operation result. If not specified result is written to mat
2012
- *
2013
- * Returns:
2014
- * dest if specified, mat otherwise
2015
- */
2016
1613
  mat4.rotateY = function(mat, angle, dest) {
2017
1614
  var s = Math.sin(angle);
2018
1615
  var c = Math.cos(angle);
@@ -2046,18 +1643,6 @@ mat4.rotateY = function(mat, angle, dest) {
2046
1643
  return dest;
2047
1644
  };
2048
1645
 
2049
- /*
2050
- * mat4.rotateZ
2051
- * Rotates a matrix by the given angle around the Z axis
2052
- *
2053
- * Params:
2054
- * mat - mat4 to rotate
2055
- * angle - angle (in radians) to rotate
2056
- * dest - Optional, mat4 receiving operation result. If not specified result is written to mat
2057
- *
2058
- * Returns:
2059
- * dest if specified, mat otherwise
2060
- */
2061
1646
  mat4.rotateZ = function(mat, angle, dest) {
2062
1647
  var s = Math.sin(angle);
2063
1648
  var c = Math.cos(angle);
@@ -2092,19 +1677,6 @@ mat4.rotateZ = function(mat, angle, dest) {
2092
1677
  return dest;
2093
1678
  };
2094
1679
 
2095
- /*
2096
- * mat4.frustum
2097
- * Generates a frustum matrix with the given bounds
2098
- *
2099
- * Params:
2100
- * left, right - scalar, left and right bounds of the frustum
2101
- * bottom, top - scalar, bottom and top bounds of the frustum
2102
- * near, far - scalar, near and far bounds of the frustum
2103
- * dest - Optional, mat4 frustum matrix will be written into
2104
- *
2105
- * Returns:
2106
- * dest if specified, a new mat4 otherwise
2107
- */
2108
1680
  mat4.frustum = function(left, right, bottom, top, near, far, dest) {
2109
1681
  if(!dest) { dest = mat4.create(); }
2110
1682
  var rl = (right - left);
@@ -2129,38 +1701,12 @@ mat4.frustum = function(left, right, bottom, top, near, far, dest) {
2129
1701
  return dest;
2130
1702
  };
2131
1703
 
2132
- /*
2133
- * mat4.perspective
2134
- * Generates a perspective projection matrix with the given bounds
2135
- *
2136
- * Params:
2137
- * fovy - scalar, vertical field of view
2138
- * aspect - scalar, aspect ratio. typically viewport width/height
2139
- * near, far - scalar, near and far bounds of the frustum
2140
- * dest - Optional, mat4 frustum matrix will be written into
2141
- *
2142
- * Returns:
2143
- * dest if specified, a new mat4 otherwise
2144
- */
2145
1704
  mat4.perspective = function(fovy, aspect, near, far, dest) {
2146
1705
  var top = near*Math.tan(fovy*Math.PI / 360.0);
2147
1706
  var right = top*aspect;
2148
1707
  return mat4.frustum(-right, right, -top, top, near, far, dest);
2149
1708
  };
2150
1709
 
2151
- /*
2152
- * mat4.ortho
2153
- * Generates a orthogonal projection matrix with the given bounds
2154
- *
2155
- * Params:
2156
- * left, right - scalar, left and right bounds of the frustum
2157
- * bottom, top - scalar, bottom and top bounds of the frustum
2158
- * near, far - scalar, near and far bounds of the frustum
2159
- * dest - Optional, mat4 frustum matrix will be written into
2160
- *
2161
- * Returns:
2162
- * dest if specified, a new mat4 otherwise
2163
- */
2164
1710
  mat4.ortho = function(left, right, bottom, top, near, far, dest) {
2165
1711
  if(!dest) { dest = mat4.create(); }
2166
1712
  var rl = (right - left);
@@ -2185,19 +1731,6 @@ mat4.ortho = function(left, right, bottom, top, near, far, dest) {
2185
1731
  return dest;
2186
1732
  };
2187
1733
 
2188
- /*
2189
- * mat4.ortho
2190
- * Generates a look-at matrix with the given eye position, focal point, and up axis
2191
- *
2192
- * Params:
2193
- * eye - vec3, position of the viewer
2194
- * center - vec3, point the viewer is looking at
2195
- * up - vec3 pointing "up"
2196
- * dest - Optional, mat4 frustum matrix will be written into
2197
- *
2198
- * Returns:
2199
- * dest if specified, a new mat4 otherwise
2200
- */
2201
1734
  mat4.lookAt = function(eye, center, up, dest) {
2202
1735
  if(!dest) { dest = mat4.create(); }
2203
1736
 
@@ -2277,16 +1810,6 @@ mat4.lookAt = function(eye, center, up, dest) {
2277
1810
  return dest;
2278
1811
  };
2279
1812
 
2280
- /*
2281
- * mat4.str
2282
- * Returns a string representation of a mat4
2283
- *
2284
- * Params:
2285
- * mat - mat4 to represent as a string
2286
- *
2287
- * Returns:
2288
- * string representation of mat
2289
- */
2290
1813
  mat4.str = function(mat) {
2291
1814
  return '[' + mat[0] + ', ' + mat[1] + ', ' + mat[2] + ', ' + mat[3] +
2292
1815
  ', '+ mat[4] + ', ' + mat[5] + ', ' + mat[6] + ', ' + mat[7] +
@@ -2294,22 +1817,8 @@ mat4.str = function(mat) {
2294
1817
  ', '+ mat[12] + ', ' + mat[13] + ', ' + mat[14] + ', ' + mat[15] + ']';
2295
1818
  };
2296
1819
 
2297
- /*
2298
- * quat4 - Quaternions
2299
- */
2300
1820
  quat4 = {};
2301
1821
 
2302
- /*
2303
- * quat4.create
2304
- * Creates a new instance of a quat4 using the default array type
2305
- * Any javascript array containing at least 4 numeric elements can serve as a quat4
2306
- *
2307
- * Params:
2308
- * quat - Optional, quat4 containing values to initialize with
2309
- *
2310
- * Returns:
2311
- * New quat4
2312
- */
2313
1822
  quat4.create = function(quat) {
2314
1823
  var dest = new glMatrixArrayType(4);
2315
1824
 
@@ -2323,17 +1832,6 @@ quat4.create = function(quat) {
2323
1832
  return dest;
2324
1833
  };
2325
1834
 
2326
- /*
2327
- * quat4.set
2328
- * Copies the values of one quat4 to another
2329
- *
2330
- * Params:
2331
- * quat - quat4 containing values to copy
2332
- * dest - quat4 receiving copied values
2333
- *
2334
- * Returns:
2335
- * dest
2336
- */
2337
1835
  quat4.set = function(quat, dest) {
2338
1836
  dest[0] = quat[0];
2339
1837
  dest[1] = quat[1];
@@ -2343,19 +1841,6 @@ quat4.set = function(quat, dest) {
2343
1841
  return dest;
2344
1842
  };
2345
1843
 
2346
- /*
2347
- * quat4.calculateW
2348
- * Calculates the W component of a quat4 from the X, Y, and Z components.
2349
- * Assumes that quaternion is 1 unit in length.
2350
- * Any existing W component will be ignored.
2351
- *
2352
- * Params:
2353
- * quat - quat4 to calculate W component of
2354
- * dest - Optional, quat4 receiving calculated values. If not specified result is written to quat
2355
- *
2356
- * Returns:
2357
- * dest if specified, quat otherwise
2358
- */
2359
1844
  quat4.calculateW = function(quat, dest) {
2360
1845
  var x = quat[0], y = quat[1], z = quat[2];
2361
1846
 
@@ -2370,17 +1855,6 @@ quat4.calculateW = function(quat, dest) {
2370
1855
  return dest;
2371
1856
  }
2372
1857
 
2373
- /*
2374
- * quat4.inverse
2375
- * Calculates the inverse of a quat4
2376
- *
2377
- * Params:
2378
- * quat - quat4 to calculate inverse of
2379
- * dest - Optional, quat4 receiving inverse values. If not specified result is written to quat
2380
- *
2381
- * Returns:
2382
- * dest if specified, quat otherwise
2383
- */
2384
1858
  quat4.inverse = function(quat, dest) {
2385
1859
  if(!dest || quat == dest) {
2386
1860
  quat[0] *= 1;
@@ -2395,33 +1869,11 @@ quat4.inverse = function(quat, dest) {
2395
1869
  return dest;
2396
1870
  }
2397
1871
 
2398
- /*
2399
- * quat4.length
2400
- * Calculates the length of a quat4
2401
- *
2402
- * Params:
2403
- * quat - quat4 to calculate length of
2404
- *
2405
- * Returns:
2406
- * Length of quat
2407
- */
2408
1872
  quat4.length = function(quat) {
2409
1873
  var x = quat[0], y = quat[1], z = quat[2], w = quat[3];
2410
1874
  return Math.sqrt(x*x + y*y + z*z + w*w);
2411
1875
  }
2412
1876
 
2413
- /*
2414
- * quat4.normalize
2415
- * Generates a unit quaternion of the same direction as the provided quat4
2416
- * If quaternion length is 0, returns [0, 0, 0, 0]
2417
- *
2418
- * Params:
2419
- * quat - quat4 to normalize
2420
- * dest - Optional, quat4 receiving operation result. If not specified result is written to quat
2421
- *
2422
- * Returns:
2423
- * dest if specified, quat otherwise
2424
- */
2425
1877
  quat4.normalize = function(quat, dest) {
2426
1878
  if(!dest) { dest = quat; }
2427
1879
 
@@ -2443,18 +1895,6 @@ quat4.normalize = function(quat, dest) {
2443
1895
  return dest;
2444
1896
  }
2445
1897
 
2446
- /*
2447
- * quat4.multiply
2448
- * Performs a quaternion multiplication
2449
- *
2450
- * Params:
2451
- * quat - quat4, first operand
2452
- * quat2 - quat4, second operand
2453
- * dest - Optional, quat4 receiving operation result. If not specified result is written to quat
2454
- *
2455
- * Returns:
2456
- * dest if specified, quat otherwise
2457
- */
2458
1898
  quat4.multiply = function(quat, quat2, dest) {
2459
1899
  if(!dest) { dest = quat; }
2460
1900
 
@@ -2469,18 +1909,6 @@ quat4.multiply = function(quat, quat2, dest) {
2469
1909
  return dest;
2470
1910
  }
2471
1911
 
2472
- /*
2473
- * quat4.multiplyVec3
2474
- * Transforms a vec3 with the given quaternion
2475
- *
2476
- * Params:
2477
- * quat - quat4 to transform the vector with
2478
- * vec - vec3 to transform
2479
- * dest - Optional, vec3 receiving operation result. If not specified result is written to vec
2480
- *
2481
- * Returns:
2482
- * dest if specified, vec otherwise
2483
- */
2484
1912
  quat4.multiplyVec3 = function(quat, vec, dest) {
2485
1913
  if(!dest) { dest = vec; }
2486
1914
 
@@ -2499,17 +1927,6 @@ quat4.multiplyVec3 = function(quat, vec, dest) {
2499
1927
  return dest;
2500
1928
  }
2501
1929
 
2502
- /*
2503
- * quat4.toMat3
2504
- * Calculates a 3x3 matrix from the given quat4
2505
- *
2506
- * Params:
2507
- * quat - quat4 to create matrix from
2508
- * dest - Optional, mat3 receiving operation result
2509
- *
2510
- * Returns:
2511
- * dest if specified, a new mat3 otherwise
2512
- */
2513
1930
  quat4.toMat3 = function(quat, dest) {
2514
1931
  if(!dest) { dest = mat3.create(); }
2515
1932
 
@@ -2546,17 +1963,6 @@ quat4.toMat3 = function(quat, dest) {
2546
1963
  return dest;
2547
1964
  }
2548
1965
 
2549
- /*
2550
- * quat4.toMat4
2551
- * Calculates a 4x4 matrix from the given quat4
2552
- *
2553
- * Params:
2554
- * quat - quat4 to create matrix from
2555
- * dest - Optional, mat4 receiving operation result
2556
- *
2557
- * Returns:
2558
- * dest if specified, a new mat4 otherwise
2559
- */
2560
1966
  quat4.toMat4 = function(quat, dest) {
2561
1967
  if(!dest) { dest = mat4.create(); }
2562
1968
 
@@ -2601,19 +2007,6 @@ quat4.toMat4 = function(quat, dest) {
2601
2007
  return dest;
2602
2008
  }
2603
2009
 
2604
- /*
2605
- * quat4.slerp
2606
- * Performs a spherical linear interpolation between two quat4
2607
- *
2608
- * Params:
2609
- * quat - quat4, first quaternion
2610
- * quat2 - quat4, second quaternion
2611
- * lerp - interpolation amount between the two inputs
2612
- * dest - Optional, quat4 receiving operation result. If not specified result is written to quat
2613
- *
2614
- * Returns:
2615
- * dest if specified, quat otherwise
2616
- */
2617
2010
  quat4.slerp = function(quat, quat2, lerp, dest) {
2618
2011
  if(!dest) { dest = quat; }
2619
2012
 
@@ -2632,16 +2025,6 @@ quat4.slerp = function(quat, quat2, lerp, dest) {
2632
2025
  return dest;
2633
2026
  }
2634
2027
 
2635
- /*
2636
- * quat4.str
2637
- * Returns a string representation of a quaternion
2638
- *
2639
- * Params:
2640
- * quat - quat4 to represent as a string
2641
- *
2642
- * Returns:
2643
- * string representation of quat
2644
- */
2645
2028
  quat4.str = function(quat) {
2646
2029
  return '[' + quat[0] + ', ' + quat[1] + ', ' + quat[2] + ', ' + quat[3] + ']';
2647
2030
  }
@@ -2843,10 +2226,14 @@ Math.radToDeg = Math.radToDeg || function(rad) {
2843
2226
  return rad * 180.0 / Math.PI;
2844
2227
  };
2845
2228
 
2229
+ Math.rad2deg = Math.rad2deg || Math.radToDeg;
2230
+
2846
2231
  Math.degToRad = Math.degToRad || function(deg) {
2847
2232
  return deg * Math.PI / 180.0;
2848
2233
  };
2849
2234
 
2235
+ Math.deg2rad = Math.deg2rad || Math.degToRad;
2236
+
2850
2237
  Math.equalish = Math.equalish || function(a, b) {
2851
2238
  if (!a.length && !b.length)
2852
2239
  return Math.abs(a - b) <= Math.EPSILON;
@@ -2857,6 +2244,15 @@ Math.equalish = Math.equalish || function(a, b) {
2857
2244
  return true;
2858
2245
  };
2859
2246
  Jax.Util = {
2247
+ decodePickingColor: function(red, green, blue, alpha) {
2248
+ /* blue is a key. It is always max. So if it's 1, we're dealing with floats; else, bytes. */
2249
+ if (blue == 1.0) {
2250
+ red *= 255;
2251
+ green *= 255;
2252
+ }
2253
+ return red * 256 + green;
2254
+ },
2255
+
2860
2256
  vectorize: function(data) {
2861
2257
  if (data) {
2862
2258
  var res = vec3.create();
@@ -3202,9 +2598,6 @@ if (glMatrixArrayType.prototype.toString != Array.prototype.toString) {
3202
2598
  */
3203
2599
 
3204
2600
 
3205
- /*
3206
- * Provides requestAnimationFrame in a cross browser way.
3207
- */
3208
2601
  window.requestAnimFrame = (function() {
3209
2602
  return window.requestAnimationFrame ||
3210
2603
  window.webkitRequestAnimationFrame ||
@@ -3217,8 +2610,6 @@ window.requestAnimFrame = (function() {
3217
2610
  })();
3218
2611
 
3219
2612
 
3220
- /* My own custom extensions to Prototype */
3221
-
3222
2613
 
3223
2614
  (function() {
3224
2615
  /*
@@ -3330,12 +2721,6 @@ window.requestAnimFrame = (function() {
3330
2721
  return klass;
3331
2722
  };
3332
2723
 
3333
- /*
3334
- class method #delegate
3335
- usages:
3336
- klass.delegate(/^(get|load|mult)(.*)Matrix$/).into("matrix_stack");
3337
- klass.delegate("getProjectionMatrix", "loadModelMatrix").into("matrix_stack");
3338
- */
3339
2724
  Jax.Class.Methods.delegate = function() {
3340
2725
  return new Delegator(this, arguments);
3341
2726
  };
@@ -3390,7 +2775,7 @@ Jax.Helper = {
3390
2775
  {
3391
2776
  var self = this;
3392
2777
  context.pushMatrix(function() {
3393
- context.multModelMatrix(self.camera.getModelViewMatrix());
2778
+ context.multModelMatrix(self.camera.getTransformationMatrix());
3394
2779
  self.mesh.render(context, options);
3395
2780
  });
3396
2781
  }
@@ -3488,11 +2873,13 @@ Jax.Helper = {
3488
2873
 
3489
2874
  if (!this.rendered_or_redirected)
3490
2875
  setViewKey(this);
2876
+ return this;
3491
2877
  },
3492
2878
 
3493
2879
  eraseResult: function() {
3494
2880
  this.rendered_or_redirected = false;
3495
2881
  this.view_key = null;
2882
+ return this;
3496
2883
  }
3497
2884
  });
3498
2885
  })();
@@ -3629,6 +3016,7 @@ Jax.View = (function() {
3629
3016
 
3630
3017
  render: function() {
3631
3018
  this.view_func();
3019
+ return this;
3632
3020
  }
3633
3021
  });
3634
3022
  })();
@@ -3813,11 +3201,12 @@ Jax.Shader = (function() {
3813
3201
  for (var i in map) {
3814
3202
  if (map[i].shared) {
3815
3203
  if (options.skip_global_definitions && options.skip_global_definitions.indexOf(map[i].full_name) != -1) {
3816
- var rx = new RegExp("(shared\\s+)?"+map[i].scope+"\\s*"+map[i].type+"[^;]*?"+map[i].full_name+"[^;]*?;\n?", "g");
3204
+ var rx = new RegExp("(shared\\s+)"+map[i].scope+"\\s*"+map[i].type+"[^;]*?"+map[i].full_name+"[^;]*?;\n?", "g");
3817
3205
  source = source.replace(rx, "");
3818
3206
  }
3819
3207
  }
3820
3208
  }
3209
+
3821
3210
  return source.replace(/shared\s+/, '');
3822
3211
  }
3823
3212
 
@@ -3827,6 +3216,7 @@ Jax.Shader = (function() {
3827
3216
  source = applyExports(self, options, source);
3828
3217
  source = applyImports(self, options, source);
3829
3218
  source = mangleUniformsAndAttributes(self, options, source);
3219
+
3830
3220
  return source;
3831
3221
  }
3832
3222
 
@@ -3938,7 +3328,7 @@ Jax.Shader = (function() {
3938
3328
  (this.getRawSource(options, 'vertex') || "") + "\n\n" +
3939
3329
  (this.getRawSource(options, 'fragment') || "");
3940
3330
 
3941
- var rx = new RegExp("(^|\\n|\\s+)((shared\\s+)?)(uniform|attribute|varying) (\\w+) ((?!"+prefix+")[^;]*);"), result;
3331
+ var rx = new RegExp("(^|\\n|\\s+)((shared\\s+)?)(uniform|attribute|varying)\\s+(\\w+)\\s+((?!"+prefix+")[^;]*);"), result;
3942
3332
  while (result = rx.exec(source)) {
3943
3333
  var shared = /shared/.test(result[2]);
3944
3334
  var scope = result[4];
@@ -4545,6 +3935,7 @@ Jax.ShaderChain = (function() {
4545
3935
  else map[variable.full_name] = variable;
4546
3936
  }
4547
3937
  }
3938
+
4548
3939
  return map;
4549
3940
  },
4550
3941
 
@@ -4642,6 +4033,15 @@ Jax.Material = (function() {
4642
4033
  }
4643
4034
  },
4644
4035
 
4036
+ supportsLighting: function() {
4037
+ if (this.getName() == "lighting")
4038
+ return true;
4039
+ for (var i = 0; i < this.layers.length; i++)
4040
+ if (this.layers[i].getName() == "lighting")
4041
+ return true;
4042
+ return false;
4043
+ },
4044
+
4645
4045
  getName: function() { return this.name; },
4646
4046
 
4647
4047
  addTextureLayer: function(tex) {
@@ -4971,11 +4371,26 @@ Jax.Material.Fog = Jax.Class.create(Jax.Material, {
4971
4371
  uniforms.set('FogColor', this.color);
4972
4372
  }
4973
4373
  });
4374
+ Jax.Material.Picking = Jax.Class.create(Jax.Material, {
4375
+ initialize: function($super) {
4376
+ $super({shader:"picking"});
4377
+ },
4378
+
4379
+ setUniforms: function($super, context, mesh, options, uniforms) {
4380
+ $super(context, mesh, options, uniforms);
4381
+
4382
+ model_index = options.model_index;
4383
+ if (model_index == undefined) model_index = -1;
4384
+
4385
+ uniforms.set('INDEX', model_index);
4386
+ }
4387
+ });
4974
4388
 
4975
4389
  Jax.Material.create("basic");
4976
4390
  Jax.Material.create("default", {default_shader:'basic'});
4977
4391
  Jax.Material.create("depthmap", {default_shader:"depthmap"});
4978
4392
  Jax.Material.create("paraboloid-depthmap", {type:"Paraboloid",default_shader:"paraboloid",layers:[{type:"Depthmap"}]});
4393
+ Jax.Material.create("picking", {type:"Picking"});
4979
4394
  Jax.Core = {};
4980
4395
 
4981
4396
  Jax.Core.Face = Jax.Class.create({
@@ -5401,6 +4816,18 @@ Jax.Mesh = (function() {
5401
4816
  this.draw_mode = GL_TRIANGLES;
5402
4817
  },
5403
4818
 
4819
+ setColor: function(red, green, blue, alpha) {
4820
+ var buf = this.getColorBuffer();
4821
+ for (var i = 0; i < buf.js.length; i += 4) {
4822
+ buf.js[i] = red;
4823
+ buf.js[i+1] = green;
4824
+ buf.js[i+2] = blue;
4825
+ buf.js[i+3] = alpha;
4826
+ }
4827
+ buf.refresh();
4828
+ return this;
4829
+ },
4830
+
5404
4831
  dispose: function() {
5405
4832
  while (this.faces && this.faces.length) this.faces.pop();
5406
4833
  while (this.edges && this.edges.length) this.edges.pop();
@@ -5565,6 +4992,8 @@ Jax.Geometry.Plane = (function() {
5565
4992
 
5566
4993
  this.point = points[1];
5567
4994
  this.d = -innerProduct(this.normal, this.point[0], this.point[1], this.point[2]);
4995
+
4996
+ return this;
5568
4997
  },
5569
4998
 
5570
4999
  setCoefficients: function(a, b, c, d) {
@@ -5573,6 +5002,7 @@ Jax.Geometry.Plane = (function() {
5573
5002
  this.normal[1] = b/len;
5574
5003
  this.normal[2] = c/len;
5575
5004
  this.d = d/len;
5005
+ return this;
5576
5006
  },
5577
5007
 
5578
5008
  distance: function(point)
@@ -5585,7 +5015,7 @@ Jax.Geometry.Plane = (function() {
5585
5015
 
5586
5016
  whereis: function(point)
5587
5017
  {
5588
- if (arguments.length == 3) points = [arguments[0], arguments[1], arguments[2]];
5018
+ if (arguments.length == 3) point = [arguments[0], arguments[1], arguments[2]];
5589
5019
  var d = this.distance(point);
5590
5020
  if (d > 0) return Jax.Geometry.Plane.FRONT;
5591
5021
  if (d < 0) return Jax.Geometry.Plane.BACK;
@@ -6012,7 +5442,7 @@ Jax.Scene.LightSource = (function() {
6012
5442
  self.framebuffers[0].bind(context, function() {
6013
5443
  self.framebuffers[0].viewport(context);
6014
5444
  context.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
6015
- context.loadViewMatrix(self.camera.getModelViewMatrix());
5445
+ context.loadViewMatrix(self.camera.getTransformationMatrix());
6016
5446
  mat4.set(context.getInverseViewMatrix(), sm);
6017
5447
 
6018
5448
  for (var i = 0; i < objects.length; i++) {
@@ -6023,7 +5453,7 @@ Jax.Scene.LightSource = (function() {
6023
5453
  self.framebuffers[1].bind(context, function() {
6024
5454
  self.framebuffers[1].viewport(context);
6025
5455
  context.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
6026
- context.loadViewMatrix(self.camera.getModelViewMatrix());
5456
+ context.loadViewMatrix(self.camera.getTransformationMatrix());
6027
5457
  for (var i = 0; i < objects.length; i++) {
6028
5458
  objects[i].render(context, {material:paraboloid_depthmap,direction:-1});
6029
5459
  }
@@ -6046,7 +5476,7 @@ Jax.Scene.LightSource = (function() {
6046
5476
  context.pushMatrix(function() {
6047
5477
  self.framebuffers[0].viewport(context);
6048
5478
  context.matrix_stack.loadProjectionMatrix(self.camera.getProjectionMatrix());
6049
- context.matrix_stack.loadViewMatrix(self.camera.getModelViewMatrix());
5479
+ context.matrix_stack.loadViewMatrix(self.camera.getTransformationMatrix());
6050
5480
  mat4.identity(sm);
6051
5481
  sm[0] = sm[5] = sm[10] = sm[12] = sm[13] = sm[14] = 0.5;
6052
5482
  mat4.multiply(sm, context.getModelViewProjectionMatrix());
@@ -6128,10 +5558,14 @@ Jax.Scene.LightManager = (function() {
6128
5558
  },
6129
5559
 
6130
5560
  illuminate: function(context, objects, options) {
5561
+ options = Jax.Util.normalizeOptions(options, {});
5562
+
6131
5563
  this.context.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6132
5564
  for (var i = 0; i < this._lights.length; i++) {
6133
5565
  for (var j = 0; j < objects.length; j++) {
6134
5566
  this._current_light = i;
5567
+ options.model_index = j;
5568
+
6135
5569
  /* TODO optimization: see if objects[j] is even affected by this._lights[i] (based on attenuation) */
6136
5570
  if (objects[j].isLit())
6137
5571
  objects[j].render(context, options);
@@ -6142,9 +5576,13 @@ Jax.Scene.LightManager = (function() {
6142
5576
  },
6143
5577
 
6144
5578
  ambient: function(context, objects, options) {
5579
+ options = Jax.Util.normalizeOptions(options, {});
5580
+
6145
5581
  for (var i = 0; i < this._lights.length; i++) {
6146
5582
  this._current_light = i;
6147
5583
  for (var j = 0; j < objects.length; j++) {
5584
+ options.model_index = j;
5585
+
6148
5586
  /* TODO optimization: see if objects[j] is even affected by this._lights[i] (based on attenuation) */
6149
5587
  if (objects[j].isLit())
6150
5588
  objects[j].render(context, options);
@@ -6428,13 +5866,13 @@ Jax.Camera = (function() {
6428
5866
  this.fireEvent('matrixUpdated');
6429
5867
  },
6430
5868
 
6431
- getModelViewMatrix: function() { return this.matrices.mv; },
5869
+ getTransformationMatrix: function() { return this.matrices.mv; },
6432
5870
 
6433
5871
  getProjectionMatrix: function() { return this.matrices.p; },
6434
5872
 
6435
5873
  getNormalMatrix: function() {
6436
5874
  if (!this.normal_matrix_up_to_date) {
6437
- mat4.toInverseMat3(this.getModelViewMatrix(), this.matrices.n);
5875
+ mat4.toInverseMat3(this.getTransformationMatrix(), this.matrices.n);
6438
5876
  mat3.transpose(this.matrices.n);
6439
5877
  }
6440
5878
  this.normal_matrix_up_to_date = true;
@@ -6519,6 +5957,14 @@ Jax.Camera = (function() {
6519
5957
  Jax.Camera.addMethods(Jax.Events.Methods);
6520
5958
 
6521
5959
  Jax.World = (function() {
5960
+ function getPickBuffer(self) {
5961
+ if (self.pickBuffer) return self.pickBuffer;
5962
+ return self.pickBuffer = new Jax.Framebuffer({
5963
+ width:self.context.canvas.width,
5964
+ height:self.context.canvas.height
5965
+ });
5966
+ }
5967
+
6522
5968
  return Jax.Class.create({
6523
5969
  initialize: function(context) {
6524
5970
  this.context = context;
@@ -6550,6 +5996,57 @@ Jax.World = (function() {
6550
5996
  }
6551
5997
  },
6552
5998
 
5999
+ pickRegionalIndices: function(x1, y1, x2, y2, ary) {
6000
+ var w = Math.abs(x2 - x1), h = Math.abs(y2 - y1);
6001
+ if (ary) ary.clear();
6002
+ else ary = new Array();
6003
+ var world = this, pickBuffer = getPickBuffer(this), context = this.context;
6004
+ var data = new Uint8Array(w*h*4);
6005
+
6006
+ pickBuffer.bind(context, function() {
6007
+ pickBuffer.viewport(context);
6008
+ context.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
6009
+ context.glDisable(GL_BLEND);
6010
+ world.render({material:"picking"});
6011
+ context.glReadPixels(x1, y1, w, h, GL_RGBA, GL_UNSIGNED_BYTE, data);
6012
+ if (data.data) data = data.data;
6013
+ });
6014
+
6015
+ context.glViewport(0, 0, context.canvas.width, context.canvas.height);
6016
+ context.glEnable(GL_BLEND);
6017
+
6018
+ var index;
6019
+ for (var i = 2; i < data.length; i += 4) {
6020
+ if (data[i] > 0) { // blue key exists, we've found an object
6021
+ index = Jax.Util.decodePickingColor(data[i-2], data[i-1], data[i], data[i+1]);
6022
+ if (index != undefined) {
6023
+ ary.push(index);
6024
+ }
6025
+ }
6026
+ }
6027
+
6028
+ return ary;
6029
+ },
6030
+
6031
+ pickRegion: function(x1, y1, x2, y2, ary) {
6032
+ var result = this.pickRegionalIndices(x1, y1, x2, y2);
6033
+ for (var i = 0; i < result.length; i++)
6034
+ result[i] = this.getObject(i);
6035
+ return result;
6036
+ },
6037
+
6038
+ pickIndex: function(x, y) {
6039
+ this._pick_ary = this._pick_ary || new Array();
6040
+ return this.pickRegionalIndices(x, y, x+1, y+1, this._pick_ary)[0];
6041
+ },
6042
+
6043
+ pick: function(x, y) {
6044
+ var index = this.pickIndex(x, y);
6045
+ if (index != undefined)
6046
+ return this.getObject(index);
6047
+ return index;
6048
+ },
6049
+
6553
6050
  countObjects: function() {
6554
6051
  return this.objects.length;
6555
6052
  },
@@ -6581,16 +6078,16 @@ Jax.World = (function() {
6581
6078
 
6582
6079
  getShadowCasters: function() { return this.shadow_casters; },
6583
6080
 
6584
- render: function() {
6081
+ render: function(options) {
6585
6082
  var i;
6586
6083
 
6587
6084
  /* this.current_pass is used by the material */
6588
6085
 
6589
6086
  this.context.current_pass = Jax.Scene.AMBIENT_PASS;
6590
6087
  this.context.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6591
- var unlit = {unlit:true};
6088
+ var unlit = Jax.Util.normalizeOptions(options, {unlit:true});
6592
6089
 
6593
- if (this.lighting.isEnabled()) {
6090
+ if (this.lighting.isEnabled() && (!unlit.material || unlit.material.supportsLighting())) {
6594
6091
  /* ambient pass */
6595
6092
  /*
6596
6093
  So.... I see a legit need for an ambient pass for A) unlit objects and B)
@@ -6599,8 +6096,10 @@ Jax.World = (function() {
6599
6096
  lighting take care of (ambient + diffuse + specular) all at once?
6600
6097
  */
6601
6098
  for (i = 0; i < this.objects.length; i++)
6602
- if (!this.objects[i].lit)
6099
+ if (!this.objects[i].lit) {
6100
+ unlit.model_index = i;
6603
6101
  this.objects[i].render(this.context, unlit);
6102
+ }
6604
6103
 
6605
6104
  /* shadowgen pass */
6606
6105
  this.context.current_pass = Jax.Scene.SHADOWMAP_PASS;
@@ -6611,10 +6110,12 @@ Jax.World = (function() {
6611
6110
 
6612
6111
  /* illumination pass */
6613
6112
  this.context.current_pass = Jax.Scene.ILLUMINATION_PASS;
6614
- this.lighting.illuminate(this.context, this.objects);
6113
+ this.lighting.illuminate(this.context, this.objects, options);
6615
6114
  } else {
6616
- for (i = 0; i < this.objects.length; i++)
6115
+ for (i = 0; i < this.objects.length; i++) {
6116
+ unlit.model_index = i;
6617
6117
  this.objects[i].render(this.context, unlit);
6118
+ }
6618
6119
  }
6619
6120
  },
6620
6121
 
@@ -6922,6 +6423,8 @@ Jax.EVENT_METHODS = (function() {
6922
6423
  do {
6923
6424
  valueT += element.offsetTop || 0;
6924
6425
  valueL += element.offsetLeft || 0;
6426
+ valueT += Jax.Compatibility.offsetTop;
6427
+ valueL += Jax.Compatibility.offsetLeft;
6925
6428
  element = element.offsetParent;
6926
6429
  } while (element);
6927
6430
 
@@ -6944,10 +6447,56 @@ Jax.EVENT_METHODS = (function() {
6944
6447
  return evt;
6945
6448
  }
6946
6449
 
6450
+ function fixEvent(event) {
6451
+ var originalEvent = event;
6452
+ event = {type:originalEvent.type};
6453
+ var props = "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" ");
6454
+
6455
+ for ( var i = props.length, prop; i; ) {
6456
+ prop = props[ --i ];
6457
+ event[ prop ] = originalEvent[ prop ];
6458
+ }
6459
+
6460
+ if ( !event.target ) {
6461
+ event.target = event.srcElement || document;
6462
+ }
6463
+
6464
+ if ( event.target.nodeType === 3 ) {
6465
+ event.target = event.target.parentNode;
6466
+ }
6467
+
6468
+ if ( !event.relatedTarget && event.fromElement ) {
6469
+ event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
6470
+ }
6471
+
6472
+ if ( event.pageX == null && event.clientX != null ) {
6473
+ var eventDocument = event.target.ownerDocument || document,
6474
+ doc = eventDocument.documentElement,
6475
+ body = eventDocument.body;
6476
+
6477
+ event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
6478
+ event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
6479
+ }
6480
+
6481
+ if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {
6482
+ event.which = event.charCode != null ? event.charCode : event.keyCode;
6483
+ }
6484
+
6485
+ if ( !event.metaKey && event.ctrlKey ) {
6486
+ event.metaKey = event.ctrlKey;
6487
+ }
6488
+
6489
+ if ( !event.which && event.button !== undefined ) {
6490
+ event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
6491
+ }
6492
+
6493
+ return event;
6494
+ }
6495
+
6947
6496
  function buildMouseEvent(self, evt) {
6948
6497
  var mouse = self.mouse;
6949
6498
 
6950
- evt = evt || window.event || {};
6499
+ evt = fixEvent(evt || window.event);
6951
6500
  evt.context = self;
6952
6501
  evt.canvas = self.canvas;
6953
6502
  evt.offsetx = mouse.x;
@@ -6958,18 +6507,10 @@ Jax.EVENT_METHODS = (function() {
6958
6507
  mouse.offsety = evt.offsety || 0;
6959
6508
 
6960
6509
  var cumulativeOffset = getCumulativeOffset(self.canvas);
6961
- mouse.x = evt.clientX - cumulativeOffset[0];
6962
- mouse.y = evt.clientY - cumulativeOffset[1];
6510
+ mouse.x = evt.pageX - cumulativeOffset[0];
6511
+ mouse.y = evt.pageY - cumulativeOffset[1];
6963
6512
  mouse.y = self.canvas.height - mouse.y; // invert y
6964
6513
 
6965
- if (window.pageXOffset) {
6966
- mouse.x += window.pageXOffset;
6967
- mouse.y += window.pageYOffset;
6968
- } else {
6969
- mouse.x += document.body.scrollLeft;
6970
- mouse.y += document.body.scrollTop;
6971
- }
6972
-
6973
6514
  mouse.diffx = mouse.x - mouse.offsetx;
6974
6515
  mouse.diffy = mouse.y - mouse.offsety;
6975
6516
 
@@ -7093,12 +6634,43 @@ Jax.Context = (function() {
7093
6634
  if (!self.gl) throw new Error("WebGL could not be initialized!");
7094
6635
  }
7095
6636
 
6637
+ function updateFramerate(self) {
6638
+ var current_render_start = Jax.uptime;
6639
+ if (!self.last_render_start) self.last_render_start = Jax.uptime;
6640
+ var time_to_render_this_frame = current_render_start - self.last_render_start;
6641
+
6642
+ self.time_to_render = (self.time_to_render || 0) * self.framerate_sample_ratio
6643
+ + time_to_render_this_frame * (1 - self.framerate_sample_ratio);
6644
+
6645
+ self.framerate = self.frames_per_second = 1.0 / self.time_to_render;
6646
+ self.last_render_start = current_render_start;
6647
+ }
6648
+
6649
+ function updateUpdateRate(self) {
6650
+ var current_update_start = Jax.uptime;
6651
+ if (!self.last_update_start) self.last_update_start = current_update_start;
6652
+ var time_to_update_this_frame = current_update_start - self.last_update_start;
6653
+
6654
+ if (self.calculateUpdateRate) {
6655
+ self.time_to_update = (self.time_to_update || 0) * self.framerate_sample_ratio
6656
+ + time_to_update_this_frame * (1 - self.framerate_sample_ratio);
6657
+
6658
+ self.updates_per_second = 1.0 / self.time_to_update;
6659
+ }
6660
+
6661
+ var timechange = current_update_start - self.last_update_start;
6662
+ self.last_update_start = current_update_start;
6663
+ return timechange;
6664
+ }
6665
+
7096
6666
  function startRendering(self) {
7097
6667
  function render() {
6668
+ if (self.calculateFramerate) updateFramerate(self);
7098
6669
  if (self.current_view) {
7099
- reloadMatrices(self);
7100
- self.glViewport(0, 0, self.canvas.width, self.canvas.height);
6670
+ self.prepare();
7101
6671
  self.current_view.render();
6672
+ var len = self.afterRenderFuncs.length;
6673
+ for (var i = 0; i < len; i++) self.afterRenderFuncs[i].call(self);
7102
6674
  self.render_interval = requestAnimFrame(render, self.canvas);
7103
6675
  }
7104
6676
  else {
@@ -7116,12 +6688,11 @@ Jax.Context = (function() {
7116
6688
 
7117
6689
  function startUpdating(self) {
7118
6690
  function updateFunc() {
7119
- if (!self.lastUpdate) self.lastUpdate = new Date();
7120
- var now = new Date();
7121
- var timechange = (now - self.lastUpdate) / 1000.0;
7122
- self.lastUpdate = now;
6691
+ var timechange = updateUpdateRate(self);
7123
6692
 
7124
6693
  self.update(timechange);
6694
+ var len = self.afterUpdateFuncs.length;
6695
+ for (var i = 0; i < len; i++) self.afterUpdateFuncs[i].call(self);
7125
6696
  self.update_interval = setTimeout(updateFunc, Jax.update_speed);
7126
6697
  }
7127
6698
  updateFunc();
@@ -7147,7 +6718,7 @@ Jax.Context = (function() {
7147
6718
  function reloadMatrices(self) {
7148
6719
  self.matrix_stack.reset(); // reset depth
7149
6720
  self.matrix_stack.loadModelMatrix(Jax.IDENTITY_MATRIX);
7150
- self.matrix_stack.loadViewMatrix(self.player.camera.getModelViewMatrix());
6721
+ self.matrix_stack.loadViewMatrix(self.player.camera.getTransformationMatrix());
7151
6722
  self.matrix_stack.loadProjectionMatrix(self.player.camera.getProjectionMatrix());
7152
6723
  }
7153
6724
 
@@ -7172,12 +6743,35 @@ Jax.Context = (function() {
7172
6743
  this.player.camera.perspective({width:canvas.width, height:canvas.height});
7173
6744
  this.matrix_stack = new Jax.MatrixStack();
7174
6745
  this.current_pass = Jax.Scene.AMBIENT_PASS;
6746
+ this.afterRenderFuncs = [];
6747
+ this.afterUpdateFuncs = [];
6748
+ this.framerate = 0;
6749
+ this.frames_per_second = 0;
6750
+ this.updates_per_second = 0;
6751
+
6752
+ this.framerate_sample_ratio = 0.9;
7175
6753
 
7176
6754
  startUpdating(this);
7177
6755
  if (Jax.routes.isRouted("/"))
7178
6756
  this.redirectTo("/");
7179
6757
  },
7180
6758
 
6759
+ getFramesPerSecond: function() { this.calculateFramerate = true; return this.frames_per_second; },
6760
+
6761
+ getUpdatesPerSecond: function() { this.calculateUpdateRate = true; return this.updates_per_second; },
6762
+
6763
+ disableFrameSpeedCalculations: function() { this.calculateFramerate = false; },
6764
+
6765
+ disableUpdateSpeedCalculations: function() { this.caclulateUpdateRate = false; },
6766
+
6767
+ afterRender: function(func) {
6768
+ this.afterRenderFuncs.push(func);
6769
+ },
6770
+
6771
+ afterUpdate: function(func) {
6772
+ this.afterUpdateFuncs.push(func);
6773
+ },
6774
+
7181
6775
  hasStencil: function() {
7182
6776
  return !!this.gl.stencil;
7183
6777
  },
@@ -7200,10 +6794,16 @@ Jax.Context = (function() {
7200
6794
  return this.current_controller;
7201
6795
  },
7202
6796
 
6797
+ prepare: function() {
6798
+ reloadMatrices(this);
6799
+ this.glViewport(0, 0, this.canvas.width, this.canvas.height);
6800
+ },
6801
+
7203
6802
  update: function(timechange) {
7204
6803
  if (this.current_controller && this.current_controller.update)
7205
6804
  this.current_controller.update(timechange);
7206
6805
  this.world.update(timechange);
6806
+ return this;
7207
6807
  },
7208
6808
 
7209
6809
  isRendering: function() {
@@ -7224,6 +6824,7 @@ Jax.Context = (function() {
7224
6824
  this.matrix_stack.push();
7225
6825
  yield_to();
7226
6826
  this.matrix_stack.pop();
6827
+ return this;
7227
6828
  },
7228
6829
 
7229
6830
  getViewMatrix: function() { return this.matrix_stack.getViewMatrix(); },
@@ -7261,6 +6862,8 @@ Jax.Context = (function() {
7261
6862
  /* set up matrix stack delegation */
7262
6863
  klass.delegate(/^(get|load|mult)(.*)Matrix$/).into("matrix_stack");
7263
6864
 
6865
+ klass.prototype.getFramerate = klass.prototype.getFramesPerSecond;
6866
+
7264
6867
  return klass;
7265
6868
  })();
7266
6869
 
@@ -7443,13 +7046,18 @@ Jax.routes = new Jax.RouteSet();
7443
7046
 
7444
7047
  Jax.loaded = true;
7445
7048
 
7446
- Jax.render_speed = 15;
7049
+ Jax.render_speed = 16;
7447
7050
 
7448
- Jax.update_speed = 15;
7051
+ Jax.update_speed = 33;
7449
7052
 
7450
7053
 
7451
7054
  Jax.max_lights = undefined;
7452
7055
 
7056
+ Jax.uptime = 0.0;
7057
+ Jax.uptime_tracker = new Date();
7058
+
7059
+ /* TODO: verify : is setInterval better for updates, or should be we using requestAnimFrame? */
7060
+ setInterval(function() { Jax.uptime = (new Date() - Jax.uptime_tracker) / 1000; }, 33);
7453
7061
 
7454
7062
  /* meshes */
7455
7063
  Jax.Mesh.Quad = (function() {
@@ -7543,7 +7151,7 @@ Jax.Mesh.Cube = Jax.Class.create(Jax.Mesh, {
7543
7151
  {
7544
7152
  var qverts = [], qcolor = [], qtex = [], qnorm = [];
7545
7153
  this.sides[i].mesh.init(qverts, qcolor, qtex, qnorm, []);
7546
- matrix = this.sides[i].camera.getModelViewMatrix();
7154
+ matrix = this.sides[i].camera.getTransformationMatrix();
7547
7155
 
7548
7156
  function push(verti) {
7549
7157
  var i1 = verti*3, i2 = verti*3+1, i3 = verti*3+2;