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.
- data/CHANGELOG +26 -1
- data/Rakefile +3 -1
- data/builtin/shaders/picking/common.ejs +2 -0
- data/builtin/shaders/picking/fragment.ejs +4 -0
- data/builtin/shaders/picking/material.js +14 -0
- data/builtin/shaders/picking/vertex.ejs +24 -0
- data/lib/jax/generators/app/templates/public/javascripts/jax.js +289 -681
- data/lib/jax/generators/app/templates/spec/javascripts/support/spec_layout.html.erb +55 -2
- data/lib/jax/generators/shader/templates/common.ejs.tt +2 -2
- data/lib/jax/packager/sprockets_template.rb +1 -4
- data/lib/jax/routes.rb +3 -0
- data/lib/jax/version.rb +1 -1
- data/spec/example_app/app/controllers/noise_controller.js +37 -5
- data/spec/example_app/app/controllers/picking_controller.js +32 -0
- data/spec/example_app/app/helpers/picking_helper.js +3 -0
- data/spec/example_app/app/models/blob.js +38 -0
- data/spec/example_app/app/resources/blobs/default.yml +2 -0
- data/spec/example_app/app/resources/materials/blob.yml +2 -2
- data/spec/example_app/app/shaders/blob/common.ejs +8 -13
- data/spec/example_app/app/shaders/blob/fragment.ejs +1 -1
- data/spec/example_app/app/shaders/blob/material.js +15 -12
- data/spec/example_app/app/shaders/blob/vertex.ejs +33 -8
- data/spec/example_app/app/views/picking/index.js +4 -0
- data/spec/example_app/config/routes.rb +1 -0
- data/spec/example_app/spec/javascripts/controllers/picking_controller_spec.js +11 -0
- data/spec/example_app/spec/javascripts/helpers/picking_helper_spec.js +12 -0
- data/spec/example_app/spec/javascripts/models/blob_spec.js +11 -0
- data/spec/example_app/spec/javascripts/support/spec_layout.html.erb +40 -2
- data/spec/javascripts/jax/model_spec.js +10 -0
- data/spec/javascripts/jax/world_spec.js +74 -1
- data/spec/javascripts/shaders/preprocessor_spec.js +35 -0
- data/src/constants.yml +1 -1
- data/src/jax.js +30 -8
- data/src/jax/anim_frame.js +6 -2
- data/src/jax/builtin/meshes/cube.js +22 -1
- data/src/jax/builtin/meshes/plane.js +27 -0
- data/src/jax/builtin/meshes/quad.js +7 -1
- data/src/jax/builtin/meshes/sphere.js +20 -1
- data/src/jax/builtin/meshes/teapot.js +10 -0
- data/src/jax/builtin/meshes/torus.js +18 -0
- data/src/jax/compatibility.js +165 -2
- data/src/jax/context.js +176 -9
- data/src/jax/core.js +6 -3
- data/src/jax/core/math.js +18 -3
- data/src/jax/core/matrix_stack.js +4 -3
- data/src/jax/core/util.js +15 -0
- data/src/jax/events.js +67 -12
- data/src/jax/geometry.js +5 -1
- data/src/jax/geometry/plane.js +59 -5
- data/src/jax/{controller.js → mvc/controller.js} +38 -0
- data/src/jax/mvc/helper.js +35 -0
- data/src/jax/mvc/model.js +301 -0
- data/src/jax/{route_set.js → mvc/route_set.js} +0 -0
- data/src/jax/{view.js → mvc/view.js} +6 -0
- data/src/jax/{view_manager.js → mvc/view_manager.js} +1 -0
- data/src/jax/noise.js +13 -0
- data/src/jax/prototype/class.js +3 -0
- data/src/jax/prototype/extensions.js +26 -8
- data/src/jax/webgl/camera.js +6 -6
- data/src/jax/webgl/core/framebuffer.js +4 -4
- data/src/jax/webgl/material.js +16 -0
- data/src/jax/webgl/mesh.js +19 -4
- data/src/jax/webgl/scene/light_manager.js +8 -0
- data/src/jax/webgl/scene/light_source.js +3 -3
- data/src/jax/webgl/shader.js +4 -2
- data/src/jax/webgl/shader_chain.js +1 -0
- data/src/jax/webgl/world.js +157 -6
- data/vendor/glmatrix/glMatrix.js +365 -408
- metadata +32 -10
- data/src/jax/helper.js +0 -8
- data/src/jax/model.js +0 -163
File without changes
|
data/src/jax/noise.js
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
/**
|
2
|
+
* class Jax.Noise
|
3
|
+
* Constructs several textures to be used in vertex shaders involving Perlin noise.
|
4
|
+
*
|
5
|
+
* Example:
|
6
|
+
*
|
7
|
+
* var noise = new Jax.Noise();
|
8
|
+
* var program = new Jax.Shader.Program({...});
|
9
|
+
* program.manifest.set('perm', noise.perm);
|
10
|
+
* program.manifest.set('simplex', noise.simplex);
|
11
|
+
* program.manifest.set('grad', noise.grad);
|
12
|
+
*
|
13
|
+
**/
|
1
14
|
Jax.Noise = (function() {
|
2
15
|
var perm/*[256]*/ = [151,160,137,91,90,15,
|
3
16
|
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
|
data/src/jax/prototype/class.js
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
/* My own custom extensions to Prototype */
|
2
|
-
|
3
1
|
//= require "class"
|
4
2
|
|
5
3
|
(function() {
|
@@ -112,12 +110,32 @@
|
|
112
110
|
return klass;
|
113
111
|
};
|
114
112
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
113
|
+
/**
|
114
|
+
* Jax.Class.delegate() -> undefined
|
115
|
+
*
|
116
|
+
* This is a class method of all Jax classes.
|
117
|
+
*
|
118
|
+
* Delegates one or more methods into properties of the class. For instance,
|
119
|
+
* the following:
|
120
|
+
*
|
121
|
+
* MyClass.delegate("sayHello").into("person");
|
122
|
+
*
|
123
|
+
* will create a +sayHello+ method in the +MyClass+ class that internally calls
|
124
|
+
*
|
125
|
+
* this.person.sayHello(...)
|
126
|
+
*
|
127
|
+
* and returns the results.
|
128
|
+
*
|
129
|
+
* There are several other variants:
|
130
|
+
*
|
131
|
+
* klass.delegate(/regular expression/).into("property_name");
|
132
|
+
* // delegates any method name in +property_name+ that matches the expression
|
133
|
+
*
|
134
|
+
* klass.delegate("one", "two").into("property_name");
|
135
|
+
* // delegates both 'one' and 'two' methods into +property_name+
|
136
|
+
*
|
137
|
+
*
|
138
|
+
**/
|
121
139
|
Jax.Class.Methods.delegate = function() {
|
122
140
|
return new Delegator(this, arguments);
|
123
141
|
};
|
data/src/jax/webgl/camera.js
CHANGED
@@ -361,12 +361,12 @@ Jax.Camera = (function() {
|
|
361
361
|
},
|
362
362
|
|
363
363
|
/**
|
364
|
-
* Jax.Camera#
|
364
|
+
* Jax.Camera#getTransformationMatrix() -> mat4
|
365
365
|
*
|
366
|
-
* Returns the
|
366
|
+
* Returns the transformation matrix. This matrix represents the camera's position and
|
367
367
|
* orientation in the world.
|
368
368
|
**/
|
369
|
-
|
369
|
+
getTransformationMatrix: function() { return this.matrices.mv; },
|
370
370
|
|
371
371
|
/**
|
372
372
|
* Jax.Camera#getProjectionMatrix() -> mat4
|
@@ -377,16 +377,16 @@ Jax.Camera = (function() {
|
|
377
377
|
getProjectionMatrix: function() { return this.matrices.p; },
|
378
378
|
|
379
379
|
/**
|
380
|
-
* Jax.Camera#getNormalMatrix() ->
|
380
|
+
* Jax.Camera#getNormalMatrix() -> mat3
|
381
381
|
*
|
382
382
|
* Returns the normal matrix, which is defined as the transpose of the inverse of the
|
383
|
-
*
|
383
|
+
* transformation matrix.
|
384
384
|
*
|
385
385
|
* This matrix is commonly used in lighting calculations.
|
386
386
|
**/
|
387
387
|
getNormalMatrix: function() {
|
388
388
|
if (!this.normal_matrix_up_to_date) {
|
389
|
-
mat4.toInverseMat3(this.
|
389
|
+
mat4.toInverseMat3(this.getTransformationMatrix(), this.matrices.n);
|
390
390
|
mat3.transpose(this.matrices.n);
|
391
391
|
}
|
392
392
|
this.normal_matrix_up_to_date = true;
|
@@ -114,12 +114,12 @@ Jax.Framebuffer = (function() {
|
|
114
114
|
*
|
115
115
|
* * color: optionally, in place of a colors array, a single color format as above. If both
|
116
116
|
* _color_ and _colors_ are specified, _color_ is simply added to the _colors_ array.
|
117
|
-
* * depth: true if a depth attachment is required, false otherwise.
|
118
|
-
* * stencil: true if a stencil attachment is required, false otherwise.
|
117
|
+
* * depth: true if a depth attachment is required, false otherwise. Defaults to false.
|
118
|
+
* * stencil: true if a stencil attachment is required, false otherwise. Defaults to false.
|
119
119
|
* * width: the width of the render and color buffers. All render and color buffers for a given
|
120
|
-
* framebuffer must have the same width. Defaults to
|
120
|
+
* framebuffer must have the same width. Defaults to 512.
|
121
121
|
* * height: the height of the render and color buffers. All render and color buffers for a given
|
122
|
-
* framebuffer must have the same height. Defaults to
|
122
|
+
* framebuffer must have the same height. Defaults to 512.
|
123
123
|
*
|
124
124
|
**/
|
125
125
|
initialize: function(options) {
|
data/src/jax/webgl/material.js
CHANGED
@@ -83,6 +83,20 @@ Jax.Material = (function() {
|
|
83
83
|
}
|
84
84
|
},
|
85
85
|
|
86
|
+
/**
|
87
|
+
* Jax.Material#supportsLighting() -> Boolean
|
88
|
+
*
|
89
|
+
* Returns true if this material supports lighting effects.
|
90
|
+
**/
|
91
|
+
supportsLighting: function() {
|
92
|
+
if (this.getName() == "lighting")
|
93
|
+
return true;
|
94
|
+
for (var i = 0; i < this.layers.length; i++)
|
95
|
+
if (this.layers[i].getName() == "lighting")
|
96
|
+
return true;
|
97
|
+
return false;
|
98
|
+
},
|
99
|
+
|
86
100
|
getName: function() { return this.name; },
|
87
101
|
|
88
102
|
addTextureLayer: function(tex) {
|
@@ -369,8 +383,10 @@ Jax.Material.addResources = function(resources) {
|
|
369
383
|
//= require "../../../builtin/shaders/depthmap/material"
|
370
384
|
//= require "../../../builtin/shaders/paraboloid/material"
|
371
385
|
//= require "../../../builtin/shaders/fog/material"
|
386
|
+
//= require "../../../builtin/shaders/picking/material"
|
372
387
|
|
373
388
|
Jax.Material.create("basic");
|
374
389
|
Jax.Material.create("default", {default_shader:'basic'});
|
375
390
|
Jax.Material.create("depthmap", {default_shader:"depthmap"});
|
376
391
|
Jax.Material.create("paraboloid-depthmap", {type:"Paraboloid",default_shader:"paraboloid",layers:[{type:"Depthmap"}]});
|
392
|
+
Jax.Material.create("picking", {type:"Picking"});
|
data/src/jax/webgl/mesh.js
CHANGED
@@ -225,6 +225,24 @@ Jax.Mesh = (function() {
|
|
225
225
|
if (!this.draw_mode)
|
226
226
|
this.draw_mode = GL_TRIANGLES;
|
227
227
|
},
|
228
|
+
|
229
|
+
/**
|
230
|
+
* Jax.Mesh#setColor(red, green, blue, alpha) -> Jax.Mesh
|
231
|
+
* Sets the color of this mesh. This will set the color at each vertex, regardless
|
232
|
+
* of the original color of that vertex. The result will be that the entire mesh
|
233
|
+
* takes on the specified color (not just a particular vertex).
|
234
|
+
**/
|
235
|
+
setColor: function(red, green, blue, alpha) {
|
236
|
+
var buf = this.getColorBuffer();
|
237
|
+
for (var i = 0; i < buf.js.length; i += 4) {
|
238
|
+
buf.js[i] = red;
|
239
|
+
buf.js[i+1] = green;
|
240
|
+
buf.js[i+2] = blue;
|
241
|
+
buf.js[i+3] = alpha;
|
242
|
+
}
|
243
|
+
buf.refresh();
|
244
|
+
return this;
|
245
|
+
},
|
228
246
|
|
229
247
|
/**
|
230
248
|
* Jax.Mesh#dispose() -> undefined
|
@@ -302,14 +320,11 @@ Jax.Mesh = (function() {
|
|
302
320
|
var result = Jax.Util.normalizeOptions(options, {
|
303
321
|
material: this.material,
|
304
322
|
default_material: this.default_material,
|
305
|
-
// default_shader: this.default_shader,
|
306
|
-
// shader: this.shader,
|
307
323
|
draw_mode: this.draw_mode || GL_TRIANGLES
|
308
324
|
});
|
309
325
|
|
310
326
|
if (!result.material) result.material = result.default_material;
|
311
|
-
|
312
|
-
|
327
|
+
|
313
328
|
result.material = findMaterial(result.material);
|
314
329
|
|
315
330
|
return result;
|
@@ -38,11 +38,15 @@ Jax.Scene.LightManager = (function() {
|
|
38
38
|
},
|
39
39
|
|
40
40
|
illuminate: function(context, objects, options) {
|
41
|
+
options = Jax.Util.normalizeOptions(options, {});
|
42
|
+
|
41
43
|
// Use alpha blending for the first pass, and additive blending for subsequent passes.
|
42
44
|
this.context.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
43
45
|
for (var i = 0; i < this._lights.length; i++) {
|
44
46
|
for (var j = 0; j < objects.length; j++) {
|
45
47
|
this._current_light = i;
|
48
|
+
options.model_index = j;
|
49
|
+
|
46
50
|
/* TODO optimization: see if objects[j] is even affected by this._lights[i] (based on attenuation) */
|
47
51
|
if (objects[j].isLit())
|
48
52
|
objects[j].render(context, options);
|
@@ -53,9 +57,13 @@ Jax.Scene.LightManager = (function() {
|
|
53
57
|
},
|
54
58
|
|
55
59
|
ambient: function(context, objects, options) {
|
60
|
+
options = Jax.Util.normalizeOptions(options, {});
|
61
|
+
|
56
62
|
for (var i = 0; i < this._lights.length; i++) {
|
57
63
|
this._current_light = i;
|
58
64
|
for (var j = 0; j < objects.length; j++) {
|
65
|
+
options.model_index = j;
|
66
|
+
|
59
67
|
/* TODO optimization: see if objects[j] is even affected by this._lights[i] (based on attenuation) */
|
60
68
|
if (objects[j].isLit())
|
61
69
|
objects[j].render(context, options);
|
@@ -167,7 +167,7 @@ Jax.Scene.LightSource = (function() {
|
|
167
167
|
// front paraboloid
|
168
168
|
self.framebuffers[0].viewport(context);
|
169
169
|
context.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
170
|
-
context.loadViewMatrix(self.camera.
|
170
|
+
context.loadViewMatrix(self.camera.getTransformationMatrix());
|
171
171
|
mat4.set(context.getInverseViewMatrix(), sm);
|
172
172
|
|
173
173
|
for (var i = 0; i < objects.length; i++) {
|
@@ -179,7 +179,7 @@ Jax.Scene.LightSource = (function() {
|
|
179
179
|
// back paraboloid
|
180
180
|
self.framebuffers[1].viewport(context);
|
181
181
|
context.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
182
|
-
context.loadViewMatrix(self.camera.
|
182
|
+
context.loadViewMatrix(self.camera.getTransformationMatrix());
|
183
183
|
for (var i = 0; i < objects.length; i++) {
|
184
184
|
objects[i].render(context, {material:paraboloid_depthmap,direction:-1});
|
185
185
|
}
|
@@ -203,7 +203,7 @@ Jax.Scene.LightSource = (function() {
|
|
203
203
|
context.pushMatrix(function() {
|
204
204
|
self.framebuffers[0].viewport(context);
|
205
205
|
context.matrix_stack.loadProjectionMatrix(self.camera.getProjectionMatrix());
|
206
|
-
context.matrix_stack.loadViewMatrix(self.camera.
|
206
|
+
context.matrix_stack.loadViewMatrix(self.camera.getTransformationMatrix());
|
207
207
|
mat4.identity(sm);
|
208
208
|
sm[0] = sm[5] = sm[10] = sm[12] = sm[13] = sm[14] = 0.5;
|
209
209
|
mat4.multiply(sm, context.getModelViewProjectionMatrix());
|
data/src/jax/webgl/shader.js
CHANGED
@@ -103,12 +103,13 @@ Jax.Shader = (function() {
|
|
103
103
|
for (var i in map) {
|
104
104
|
if (map[i].shared) {
|
105
105
|
if (options.skip_global_definitions && options.skip_global_definitions.indexOf(map[i].full_name) != -1) {
|
106
|
-
var rx = new RegExp("(shared\\s+)
|
106
|
+
var rx = new RegExp("(shared\\s+)"+map[i].scope+"\\s*"+map[i].type+"[^;]*?"+map[i].full_name+"[^;]*?;\n?", "g");
|
107
107
|
source = source.replace(rx, "");
|
108
108
|
}
|
109
109
|
// else source = source.replace(rx, map[i].scope+" "+map[i].type+" "+map[i].full_name+";\n");
|
110
110
|
}
|
111
111
|
}
|
112
|
+
|
112
113
|
return source.replace(/shared\s+/, '');
|
113
114
|
}
|
114
115
|
|
@@ -121,6 +122,7 @@ Jax.Shader = (function() {
|
|
121
122
|
source = applyExports(self, options, source);
|
122
123
|
source = applyImports(self, options, source);
|
123
124
|
source = mangleUniformsAndAttributes(self, options, source);
|
125
|
+
|
124
126
|
return source;
|
125
127
|
}
|
126
128
|
|
@@ -234,7 +236,7 @@ Jax.Shader = (function() {
|
|
234
236
|
(this.getRawSource(options, 'fragment') || "");
|
235
237
|
|
236
238
|
// if it's not a "shared" uniform, mangle its name.
|
237
|
-
var rx = new RegExp("(^|\\n|\\s+)((shared\\s+)?)(uniform|attribute|varying)
|
239
|
+
var rx = new RegExp("(^|\\n|\\s+)((shared\\s+)?)(uniform|attribute|varying)\\s+(\\w+)\\s+((?!"+prefix+")[^;]*);"), result;
|
238
240
|
while (result = rx.exec(source)) {
|
239
241
|
var shared = /shared/.test(result[2]);
|
240
242
|
var scope = result[4];
|
data/src/jax/webgl/world.js
CHANGED
@@ -1,6 +1,23 @@
|
|
1
1
|
//= require "scene"
|
2
2
|
|
3
|
+
/**
|
4
|
+
* class Jax.World
|
5
|
+
*
|
6
|
+
* A +Jax.World+ represents a scene in the graphics engine. All objects to be rendered (or at least,
|
7
|
+
* all objects that you do not want to manually control!) should be added to the world. Each instance
|
8
|
+
* of +Jax.Context+ has its own +Jax.World+, and the currently-active +Jax.World+ is delegated into
|
9
|
+
* controllers and views as the +this.world+ property.
|
10
|
+
*
|
11
|
+
**/
|
3
12
|
Jax.World = (function() {
|
13
|
+
function getPickBuffer(self) {
|
14
|
+
if (self.pickBuffer) return self.pickBuffer;
|
15
|
+
return self.pickBuffer = new Jax.Framebuffer({
|
16
|
+
width:self.context.canvas.width,
|
17
|
+
height:self.context.canvas.height
|
18
|
+
});
|
19
|
+
}
|
20
|
+
|
4
21
|
return Jax.Class.create({
|
5
22
|
initialize: function(context) {
|
6
23
|
this.context = context;
|
@@ -9,12 +26,38 @@ Jax.World = (function() {
|
|
9
26
|
this.shadow_casters = [];
|
10
27
|
},
|
11
28
|
|
29
|
+
/**
|
30
|
+
* Jax.World#addLightSource(light) -> Jax.Scene.LightSource
|
31
|
+
* - light (Jax.Scene.LightSource) : the instance of Jax.Scene.LightSource to add to this world.
|
32
|
+
*
|
33
|
+
* Adds the light to the world and then returns the light itself unchanged.
|
34
|
+
**/
|
12
35
|
addLightSource: function(light) { this.lighting.add(light); },
|
13
36
|
|
37
|
+
/**
|
38
|
+
* Jax.World#addObject(object) -> Jax.Model
|
39
|
+
* - object (Jax.Model) : the instance of Jax.Model to add to this world.
|
40
|
+
*
|
41
|
+
* Adds the model to the world and then returns the model itself unchanged.
|
42
|
+
*
|
43
|
+
**/
|
14
44
|
addObject: function(object) { this.objects.push(object); this.invalidate(); return object; },
|
15
45
|
|
46
|
+
/**
|
47
|
+
* Jax.World#getObject(index) -> Jax.Model
|
48
|
+
* - index (Number) : the world index of this object
|
49
|
+
*
|
50
|
+
* Returns the object with the specified world index, or undefined.
|
51
|
+
**/
|
16
52
|
getObject: function(index) { return this.objects[index]; },
|
17
53
|
|
54
|
+
/**
|
55
|
+
* Jax.World#removeObject(object_or_index) -> Jax.Model
|
56
|
+
* - object_or_index (Number|Jax.Model) : the model instance to remove, or its world index
|
57
|
+
*
|
58
|
+
* If the model or its index cannot be found, nothing happens and the return value is undefined.
|
59
|
+
* Otherwise, the object is removed from this World and then returned.
|
60
|
+
**/
|
18
61
|
removeObject: function(object_or_index) {
|
19
62
|
if (this.objects[object_or_index]) {
|
20
63
|
var obj = this.objects[object_or_index];
|
@@ -32,6 +75,110 @@ Jax.World = (function() {
|
|
32
75
|
}
|
33
76
|
},
|
34
77
|
|
78
|
+
/**
|
79
|
+
* Jax.World#pickRegionalIndices(x1, y1, x2, y2[, ary]) -> Array
|
80
|
+
* - x1 (Number): the screen X coordinate of the first corner of the 2D rectangle within which to pick
|
81
|
+
* - y1 (Number): the screen Y coordinate of the first corner of the 2D rectangle within which to pick
|
82
|
+
* - x2 (Number): the screen X coordinate of the second corner of the 2D rectangle within which to pick
|
83
|
+
* - y2 (Number): the screen Y coordinate of the second corner of the 2D rectangle within which to pick
|
84
|
+
* - ary (Array): an optional array to populate. A new one will be created if this is not specified.
|
85
|
+
* (Note: the array's contents will be cleared.)
|
86
|
+
*
|
87
|
+
* Picks all visible object indices within the specified rectangular regions and returns them as elements in
|
88
|
+
* an array.
|
89
|
+
*
|
90
|
+
* An object's index matches its position in the world's object list. That is, the following code is
|
91
|
+
* valid:
|
92
|
+
*
|
93
|
+
* this.world.getObjects(this.world.pickRegionalIDs(0,0, 100,100));
|
94
|
+
*
|
95
|
+
**/
|
96
|
+
pickRegionalIndices: function(x1, y1, x2, y2, ary) {
|
97
|
+
var w = Math.abs(x2 - x1), h = Math.abs(y2 - y1);
|
98
|
+
if (ary) ary.clear();
|
99
|
+
else ary = new Array();
|
100
|
+
var world = this, pickBuffer = getPickBuffer(this), context = this.context;
|
101
|
+
var data = new Uint8Array(w*h*4);
|
102
|
+
|
103
|
+
pickBuffer.bind(context, function() {
|
104
|
+
pickBuffer.viewport(context);
|
105
|
+
context.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
106
|
+
context.glDisable(GL_BLEND);
|
107
|
+
world.render({material:"picking"});
|
108
|
+
// read it back in
|
109
|
+
context.glReadPixels(x1, y1, w, h, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
110
|
+
if (data.data) data = data.data;
|
111
|
+
});
|
112
|
+
|
113
|
+
// restore the visible viewport and blending
|
114
|
+
context.glViewport(0, 0, context.canvas.width, context.canvas.height);
|
115
|
+
context.glEnable(GL_BLEND);
|
116
|
+
|
117
|
+
var index;
|
118
|
+
for (var i = 2; i < data.length; i += 4) {
|
119
|
+
if (data[i] > 0) { // blue key exists, we've found an object
|
120
|
+
index = Jax.Util.decodePickingColor(data[i-2], data[i-1], data[i], data[i+1]);
|
121
|
+
if (index != undefined) {
|
122
|
+
ary.push(index);
|
123
|
+
}
|
124
|
+
}
|
125
|
+
}
|
126
|
+
|
127
|
+
return ary;
|
128
|
+
},
|
129
|
+
|
130
|
+
/**
|
131
|
+
* Jax.World#pickRegion(x1, y1, x2, y2) -> Array
|
132
|
+
* - x1 (Number): the screen X coordinate of the first corner of the 2D rectangle within which to pick
|
133
|
+
* - y1 (Number): the screen Y coordinate of the first corner of the 2D rectangle within which to pick
|
134
|
+
* - x2 (Number): the screen X coordinate of the second corner of the 2D rectangle within which to pick
|
135
|
+
* - y2 (Number): the screen Y coordinate of the second corner of the 2D rectangle within which to pick
|
136
|
+
* - ary (Array): an optional array to populate. A new one will be created if this is not specified.
|
137
|
+
* (Note: the array's contents will be cleared.)
|
138
|
+
*
|
139
|
+
* Picks all visible objects within the specified rectangular regions and returns them as elements in
|
140
|
+
* an array.
|
141
|
+
**/
|
142
|
+
pickRegion: function(x1, y1, x2, y2, ary) {
|
143
|
+
var result = this.pickRegionalIndices(x1, y1, x2, y2);
|
144
|
+
for (var i = 0; i < result.length; i++)
|
145
|
+
result[i] = this.getObject(i);
|
146
|
+
return result;
|
147
|
+
},
|
148
|
+
|
149
|
+
/**
|
150
|
+
* Jax.World#pickIndex(x, y) -> Number | undefined
|
151
|
+
* - x (Number): the screen X coordinate to pick at
|
152
|
+
* - y (Number): the screen Y coordinate to pick at
|
153
|
+
*
|
154
|
+
* Picks the visible object at the specified position and returns its index as used by
|
155
|
+
* +Jax.World#getObject+. If no object is visible at the given position, the special value
|
156
|
+
* +undefined+ is returned.
|
157
|
+
**/
|
158
|
+
pickIndex: function(x, y) {
|
159
|
+
this._pick_ary = this._pick_ary || new Array();
|
160
|
+
return this.pickRegionalIndices(x, y, x+1, y+1, this._pick_ary)[0];
|
161
|
+
},
|
162
|
+
|
163
|
+
/**
|
164
|
+
* Jax.World#pick(x, y) -> Jax.Model | undefined
|
165
|
+
* - x (Number): the screen X coordinate to pick at
|
166
|
+
* - y (Number): the screen Y coordinate to pick at
|
167
|
+
*
|
168
|
+
* Picks the visible object at the specified position and returns it. If no object is visible
|
169
|
+
* at the given position, the special value +undefined+ is returned.
|
170
|
+
**/
|
171
|
+
pick: function(x, y) {
|
172
|
+
var index = this.pickIndex(x, y);
|
173
|
+
if (index != undefined)
|
174
|
+
return this.getObject(index);
|
175
|
+
return index;
|
176
|
+
},
|
177
|
+
|
178
|
+
/**
|
179
|
+
* Jax.World#countObjects() -> Number
|
180
|
+
* Returns the number of objects currently registered with this World.
|
181
|
+
**/
|
35
182
|
countObjects: function() {
|
36
183
|
return this.objects.length;
|
37
184
|
},
|
@@ -63,16 +210,16 @@ Jax.World = (function() {
|
|
63
210
|
|
64
211
|
getShadowCasters: function() { return this.shadow_casters; },
|
65
212
|
|
66
|
-
render: function() {
|
213
|
+
render: function(options) {
|
67
214
|
var i;
|
68
215
|
|
69
216
|
/* this.current_pass is used by the material */
|
70
217
|
|
71
218
|
this.context.current_pass = Jax.Scene.AMBIENT_PASS;
|
72
219
|
this.context.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
73
|
-
var unlit = {unlit:true};
|
220
|
+
var unlit = Jax.Util.normalizeOptions(options, {unlit:true});
|
74
221
|
|
75
|
-
if (this.lighting.isEnabled()) {
|
222
|
+
if (this.lighting.isEnabled() && (!unlit.material || unlit.material.supportsLighting())) {
|
76
223
|
/* ambient pass */
|
77
224
|
/*
|
78
225
|
So.... I see a legit need for an ambient pass for A) unlit objects and B)
|
@@ -81,8 +228,10 @@ Jax.World = (function() {
|
|
81
228
|
lighting take care of (ambient + diffuse + specular) all at once?
|
82
229
|
*/
|
83
230
|
for (i = 0; i < this.objects.length; i++)
|
84
|
-
if (!this.objects[i].lit)
|
231
|
+
if (!this.objects[i].lit) {
|
232
|
+
unlit.model_index = i;
|
85
233
|
this.objects[i].render(this.context, unlit);
|
234
|
+
}
|
86
235
|
// this.lighting.ambient(this.context, this.objects);
|
87
236
|
|
88
237
|
/* shadowgen pass */
|
@@ -94,10 +243,12 @@ Jax.World = (function() {
|
|
94
243
|
|
95
244
|
/* illumination pass */
|
96
245
|
this.context.current_pass = Jax.Scene.ILLUMINATION_PASS;
|
97
|
-
this.lighting.illuminate(this.context, this.objects);
|
246
|
+
this.lighting.illuminate(this.context, this.objects, options);
|
98
247
|
} else {
|
99
|
-
for (i = 0; i < this.objects.length; i++)
|
248
|
+
for (i = 0; i < this.objects.length; i++) {
|
249
|
+
unlit.model_index = i;
|
100
250
|
this.objects[i].render(this.context, unlit);
|
251
|
+
}
|
101
252
|
}
|
102
253
|
},
|
103
254
|
|