@@ -10,7 +10,6 @@ define([
10
10
'math3d/Picking' ,
11
11
'mesh/Background' ,
12
12
'mesh/Selection' ,
13
- 'mesh/Grid' ,
14
13
'mesh/Mesh' ,
15
14
'mesh/multiresolution/Multimesh' ,
16
15
'mesh/Primitive' ,
@@ -20,21 +19,31 @@ define([
20
19
'render/Rtt' ,
21
20
'render/shaders/ShaderMatcap' ,
22
21
'render/WebGLCaps'
23
- ] , function ( glm , getUrlOptions , Utils , Sculpt , Subdivision , Import , Gui , Camera , Picking , Background , Selection , Grid , Mesh , Multimesh , Primitive , States , Contour , Render , Rtt , ShaderMatcap , WebGLCaps ) {
22
+ ] , function ( glm , getUrlOptions , Utils , Sculpt , Subdivision , Import , Gui , Camera , Picking , Background , Selection , Mesh , Multimesh , Primitive , States , Contour , Render , Rtt , ShaderMatcap , WebGLCaps ) {
24
23
25
24
'use strict' ;
26
25
26
+ var vec3 = glm . vec3 ;
27
+ var mat4 = glm . mat4 ;
28
+
27
29
var Scene = function ( ) {
28
30
this . _gl = null ; // webgl context
29
31
this . _canvas = document . getElementById ( 'canvas' ) ;
30
32
31
33
// core of the app
32
34
this . _states = new States ( this ) ; // for undo-redo
33
- this . _sculpt = new Sculpt ( this ) ;
35
+ this . _sculpt = null ;
34
36
this . _camera = new Camera ( this ) ;
35
37
this . _picking = new Picking ( this ) ; // the ray picking
36
38
this . _pickingSym = new Picking ( this , true ) ; // the symmetrical picking
37
39
40
+ this . _meshPreview = null ;
41
+ this . _torusLength = 0.5 ;
42
+ this . _torusWidth = 0.1 ;
43
+ this . _torusRadius = Math . PI * 2 ;
44
+ this . _torusRadial = 32 ;
45
+ this . _torusTubular = 128 ;
46
+
38
47
// renderable stuffs
39
48
var opts = getUrlOptions ( ) ;
40
49
this . _showContour = opts . outline ;
@@ -58,16 +67,17 @@ define([
58
67
} ;
59
68
60
69
Scene . prototype = {
61
- /** Initialization */
62
70
start : function ( ) {
63
71
this . initWebGL ( ) ;
64
72
if ( ! this . _gl )
65
73
return ;
74
+ this . _sculpt = new Sculpt ( this ) ;
66
75
this . _background = new Background ( this . _gl , this ) ;
67
76
this . _selection = new Selection ( this . _gl ) ;
68
- this . _grid = new Grid ( this . _gl ) ;
69
77
this . _rtt = new Rtt ( this . _gl ) ;
70
78
this . _contour = new Contour ( this . _gl ) ;
79
+ this . _grid = Primitive . createGrid ( this . _gl ) ;
80
+ this . initGrid ( ) ;
71
81
72
82
this . loadTextures ( ) ;
73
83
this . _gui . initGui ( ) ;
@@ -110,6 +120,16 @@ define([
110
120
setMesh : function ( mesh ) {
111
121
return this . setOrUnsetMesh ( mesh ) ;
112
122
} ,
123
+ initGrid : function ( ) {
124
+ var grid = this . _grid ;
125
+ grid . normalizeSize ( ) ;
126
+ var gridm = grid . getMatrix ( ) ;
127
+ mat4 . translate ( gridm , gridm , [ 0.0 , - 0.45 , 0.0 ] ) ;
128
+ var scale = 2.5 ;
129
+ mat4 . scale ( gridm , gridm , [ scale , scale , scale ] ) ;
130
+ this . _grid . setShader ( 'FLAT' ) ;
131
+ grid . setFlatColor ( [ 0.2140 , 0.2140 , 0.2140 ] ) ;
132
+ } ,
113
133
setOrUnsetMesh : function ( mesh , multiSelect ) {
114
134
if ( ! mesh ) {
115
135
this . _selectMeshes . length = 0 ;
@@ -152,31 +172,60 @@ define([
152
172
/** Render the scene */
153
173
applyRender : function ( ) {
154
174
this . _preventRender = false ;
155
- this . computeMatricesAndSort ( ) ;
175
+ this . updateMatricesAndSort ( ) ;
156
176
var gl = this . _gl ;
177
+ if ( ! gl ) return ;
157
178
158
179
if ( this . _drawFullScene ) {
159
180
gl . disable ( gl . DEPTH_TEST ) ;
160
- // gl.enable(gl.CULL_FACE);
161
181
162
182
var showContour = this . _selectMeshes . length > 0 && this . _showContour && this . _contour . isEffective ( ) ;
163
183
if ( showContour ) {
184
+ // flat color RTT for contours
164
185
gl . bindFramebuffer ( gl . FRAMEBUFFER , this . _contour . getFramebuffer ( ) ) ;
165
186
gl . clear ( gl . COLOR_BUFFER_BIT ) ;
166
187
for ( var s = 0 , sel = this . _selectMeshes , nbSel = sel . length ; s < nbSel ; ++ s )
167
188
sel [ s ] . renderFlatColor ( this ) ;
168
189
}
169
190
191
+ // main scene RTT
170
192
gl . bindFramebuffer ( gl . FRAMEBUFFER , this . _rtt . getFramebuffer ( ) ) ;
171
193
gl . clear ( gl . COLOR_BUFFER_BIT | gl . DEPTH_BUFFER_BIT ) ;
194
+
195
+ // BACKGROUND
172
196
this . _background . render ( ) ;
173
197
174
198
gl . enable ( gl . DEPTH_TEST ) ;
199
+ // GRID
175
200
if ( this . _showGrid )
176
- this . _grid . render ( ) ;
177
- for ( var i = 0 , meshes = this . _meshes , nb = meshes . length ; i < nb ; ++ i )
201
+ this . _grid . render ( this ) ;
202
+
203
+ // MESHES
204
+ var i = 0 ;
205
+ var meshes = this . _meshes ;
206
+ var nbMeshes = meshes . length ;
207
+ // OPAQUE
208
+ gl . disable ( gl . CULL_FACE ) ;
209
+ for ( i = 0 ; i < nbMeshes ; ++ i ) {
210
+ if ( meshes [ i ] . isTransparent ( ) )
211
+ break ;
212
+ meshes [ i ] . render ( this ) ;
213
+ }
214
+ if ( this . _meshPreview )
215
+ this . _meshPreview . render ( this ) ;
216
+ gl . enable ( gl . CULL_FACE ) ;
217
+
218
+ // TRANSPARENCY
219
+ for ( ; i < nbMeshes ; ++ i ) {
220
+ gl . cullFace ( gl . FRONT ) ; // draw back first
178
221
meshes [ i ] . render ( this ) ;
222
+ gl . cullFace ( gl . BACK ) ; // ... and then front
223
+ meshes [ i ] . render ( this ) ;
224
+ }
225
+ // We can also draw all the transparent meshes backfaces first and then the front faces
226
+ // it would be better for intersected transparent meshes but worse for separated meshes
179
227
228
+ // draw sobel contour
180
229
if ( showContour )
181
230
this . _contour . render ( ) ;
182
231
}
@@ -186,18 +235,25 @@ define([
186
235
gl . disable ( gl . DEPTH_TEST ) ;
187
236
this . _rtt . render ( ) ;
188
237
this . _selection . render ( this ) ;
238
+
239
+ gl . enable ( gl . DEPTH_TEST ) ;
240
+ // draw sculpt gizmos
241
+ this . _sculpt . postRender ( ) ;
189
242
} ,
190
243
/** Pre compute matrices and sort meshes */
191
- computeMatricesAndSort : function ( ) {
244
+ updateMatricesAndSort : function ( ) {
192
245
var meshes = this . _meshes ;
193
246
var cam = this . _camera ;
194
247
if ( meshes . length > 0 )
195
248
cam . optimizeNearFar ( this . computeBoundingBoxScene ( ) ) ;
196
- this . _grid . computeMatrices ( cam ) ;
197
249
for ( var i = 0 , nb = meshes . length ; i < nb ; ++ i )
198
- meshes [ i ] . computeMatrices ( cam ) ;
199
- this . _selection . computeMatrices ( this ) ;
250
+ meshes [ i ] . updateMatrices ( cam ) ;
200
251
meshes . sort ( Mesh . sortFunction ) ;
252
+
253
+ if ( this . _meshPreview )
254
+ this . _meshPreview . updateMatrices ( cam ) ;
255
+ if ( this . _grid )
256
+ this . _grid . updateMatrices ( cam ) ;
201
257
} ,
202
258
/** Load webgl context */
203
259
initWebGL : function ( ) {
@@ -223,6 +279,7 @@ define([
223
279
gl . frontFace ( gl . CCW ) ;
224
280
gl . depthFunc ( gl . LEQUAL ) ;
225
281
gl . cullFace ( gl . BACK ) ;
282
+ gl . enable ( gl . CULL_FACE ) ;
226
283
gl . clearColor ( 0.033 , 0.033 , 0.033 , 1 ) ;
227
284
gl . clear ( gl . COLOR_BUFFER_BIT | gl . DEPTH_BUFFER_BIT ) ;
228
285
} ,
@@ -253,67 +310,46 @@ define([
253
310
this . initAlphaTextures ( ) ;
254
311
} ,
255
312
initAlphaTextures : function ( ) {
256
- var self = this ;
257
- var alphas = Picking . ALPHAS_PATHS ;
258
- var loadAlpha = function ( alphas , id ) {
313
+ var alphas = Picking . INIT_ALPHAS_PATHS ;
314
+ var names = Picking . INIT_ALPHAS_NAMES ;
315
+ for ( var i = 0 , nbA = alphas . length ; i < nbA ; ++ i ) {
259
316
var am = new Image ( ) ;
260
- am . src = 'resources/alpha/' + alphas [ id ] ;
261
- am . onload = function ( ) {
262
- self . onLoadAlphaImage ( am ) ;
263
- if ( id < alphas . length - 1 )
264
- loadAlpha ( alphas , id + 1 ) ;
265
- } ;
266
- } ;
267
- loadAlpha ( alphas , 0 ) ;
317
+ am . src = 'resources/alpha/' + alphas [ i ] ;
318
+ am . onload = this . onLoadAlphaImage . bind ( this , am , names [ i ] ) ;
319
+ }
268
320
} ,
269
321
/** Called when the window is resized */
270
322
onCanvasResize : function ( ) {
271
- var newWidth = this . _gl . viewportWidth = this . _camera . _width = this . _canvas . width ;
272
- var newHeight = this . _gl . viewportHeight = this . _camera . _height = this . _canvas . height ;
323
+ var newWidth = this . _gl . viewportWidth = this . _canvas . width ;
324
+ var newHeight = this . _gl . viewportHeight = this . _canvas . height ;
273
325
274
326
this . _background . onResize ( newWidth , newHeight ) ;
275
327
this . _rtt . onResize ( newWidth , newHeight ) ;
276
328
this . _contour . onResize ( newWidth , newHeight ) ;
277
329
this . _gl . viewport ( 0 , 0 , newWidth , newHeight ) ;
278
- this . _camera . updateProjection ( ) ;
330
+ this . _camera . onResize ( newWidth , newHeight ) ;
279
331
this . render ( ) ;
280
332
} ,
281
333
computeBoundingBoxMeshes : function ( meshes ) {
282
- var bigBound = [ Infinity , Infinity , Infinity , - Infinity , - Infinity , - Infinity ] ;
283
- var vec3 = glm . vec3 ;
284
- var min = [ 0.0 , 0.0 , 0.0 ] ;
285
- var max = [ 0.0 , 0.0 , 0.0 ] ;
334
+ var bound = [ Infinity , Infinity , Infinity , - Infinity , - Infinity , - Infinity ] ;
286
335
for ( var i = 0 , l = meshes . length ; i < l ; ++ i ) {
287
- var bound = meshes [ i ] . getBound ( ) ;
288
- var mat = meshes [ i ] . getMatrix ( ) ;
289
- vec3 . transformMat4 ( min , bound , mat ) ;
290
- max [ 0 ] = bound [ 3 ] ;
291
- max [ 1 ] = bound [ 4 ] ;
292
- max [ 2 ] = bound [ 5 ] ;
293
- vec3 . transformMat4 ( max , max , mat ) ;
294
- if ( min [ 0 ] < bigBound [ 0 ] ) bigBound [ 0 ] = min [ 0 ] ;
295
- if ( min [ 1 ] < bigBound [ 1 ] ) bigBound [ 1 ] = min [ 1 ] ;
296
- if ( min [ 2 ] < bigBound [ 2 ] ) bigBound [ 2 ] = min [ 2 ] ;
297
- if ( max [ 0 ] > bigBound [ 3 ] ) bigBound [ 3 ] = max [ 0 ] ;
298
- if ( max [ 1 ] > bigBound [ 4 ] ) bigBound [ 4 ] = max [ 1 ] ;
299
- if ( max [ 2 ] > bigBound [ 5 ] ) bigBound [ 5 ] = max [ 2 ] ;
336
+ var bi = meshes [ i ] . getWorldBound ( ) ;
337
+ if ( bi [ 0 ] < bound [ 0 ] ) bound [ 0 ] = bi [ 0 ] ;
338
+ if ( bi [ 1 ] < bound [ 1 ] ) bound [ 1 ] = bi [ 1 ] ;
339
+ if ( bi [ 2 ] < bound [ 2 ] ) bound [ 2 ] = bi [ 2 ] ;
340
+ if ( bi [ 3 ] > bound [ 3 ] ) bound [ 3 ] = bi [ 3 ] ;
341
+ if ( bi [ 4 ] > bound [ 4 ] ) bound [ 4 ] = bi [ 4 ] ;
342
+ if ( bi [ 5 ] > bound [ 5 ] ) bound [ 5 ] = bi [ 5 ] ;
300
343
}
301
- return bigBound ;
344
+ return bound ;
302
345
} ,
303
346
computeBoundingBoxScene : function ( ) {
304
- var bb = this . computeBoundingBoxMeshes ( this . _meshes ) ;
305
- var gb = this . _grid . getBound ( ) ;
306
- if ( gb [ 0 ] < bb [ 0 ] ) bb [ 0 ] = gb [ 0 ] ;
307
- if ( gb [ 1 ] < bb [ 1 ] ) bb [ 1 ] = gb [ 1 ] ;
308
- if ( gb [ 2 ] < bb [ 2 ] ) bb [ 2 ] = gb [ 2 ] ;
309
- if ( gb [ 3 ] > bb [ 3 ] ) bb [ 3 ] = gb [ 3 ] ;
310
- if ( gb [ 4 ] > bb [ 4 ] ) bb [ 4 ] = gb [ 4 ] ;
311
- if ( gb [ 5 ] > bb [ 5 ] ) bb [ 5 ] = gb [ 5 ] ;
312
- return bb ;
313
- } ,
314
- scaleAndCenterMeshes : function ( meshes ) {
315
- var vec3 = glm . vec3 ;
316
- var mat4 = glm . mat4 ;
347
+ var scene = this . _meshes . slice ( ) ;
348
+ scene . push ( this . _grid ) ;
349
+ this . _sculpt . addSculptToScene ( scene ) ;
350
+ return this . computeBoundingBoxMeshes ( scene ) ;
351
+ } ,
352
+ normalizeAndCenterMeshes : function ( meshes ) {
317
353
var box = this . computeBoundingBoxMeshes ( meshes ) ;
318
354
var scale = Utils . SCALE / vec3 . dist ( [ box [ 0 ] , box [ 1 ] , box [ 2 ] ] , [ box [ 3 ] , box [ 4 ] , box [ 5 ] ] ) ;
319
355
@@ -322,35 +358,53 @@ define([
322
358
mat4 . translate ( mCen , mCen , [ - ( box [ 0 ] + box [ 3 ] ) * 0.5 , - ( box [ 1 ] + box [ 4 ] ) * 0.5 , - ( box [ 2 ] + box [ 5 ] ) * 0.5 ] ) ;
323
359
324
360
for ( var i = 0 , l = meshes . length ; i < l ; ++ i ) {
325
- var mesh = meshes [ i ] ;
326
- var mat = mesh . getMatrix ( ) ;
361
+ var mat = meshes [ i ] . getMatrix ( ) ;
327
362
mat4 . mul ( mat , mCen , mat ) ;
328
363
}
329
364
} ,
330
365
/** Load the sphere */
331
366
addSphere : function ( ) {
332
367
// make a cube and subdivide it
333
368
var mesh = new Multimesh ( Primitive . createCube ( this . _gl ) ) ;
334
- while ( mesh . getNbFaces ( ) < 50000 )
335
- mesh . addLevel ( ) ;
336
- // discard the very low res
337
- mesh . _meshes . splice ( 0 , 4 ) ;
338
- mesh . _sel -= 4 ;
339
-
369
+ mesh . normalizeSize ( ) ;
370
+ this . subdivideClamp ( mesh ) ;
340
371
return this . addNewMesh ( mesh ) ;
341
372
} ,
342
373
addCube : function ( ) {
343
374
var mesh = new Multimesh ( Primitive . createCube ( this . _gl ) ) ;
344
- glm . mat4 . scale ( mesh . getMatrix ( ) , mesh . getMatrix ( ) , [ 0.7 , 0.7 , 0.7 ] ) ;
345
- Subdivision . LINEAR = true ;
375
+ mesh . normalizeSize ( ) ;
376
+ mat4 . scale ( mesh . getMatrix ( ) , mesh . getMatrix ( ) , [ 0.7 , 0.7 , 0.7 ] ) ;
377
+ this . subdivideClamp ( mesh , true ) ;
378
+ return this . addNewMesh ( mesh ) ;
379
+ } ,
380
+ addCylinder : function ( ) {
381
+ var mesh = new Multimesh ( Primitive . createCylinder ( this . _gl ) ) ;
382
+ mesh . normalizeSize ( ) ;
383
+ mat4 . scale ( mesh . getMatrix ( ) , mesh . getMatrix ( ) , [ 0.7 , 0.7 , 0.7 ] ) ;
384
+ this . subdivideClamp ( mesh ) ;
385
+ return this . addNewMesh ( mesh ) ;
386
+ } ,
387
+ addTorus : function ( preview ) {
388
+ var mesh = new Multimesh ( Primitive . createTorus ( this . _gl , this . _torusLength , this . _torusWidth , this . _torusRadius , this . _torusRadial , this . _torusTubular ) ) ;
389
+ if ( preview ) {
390
+ mesh . setShowWireframe ( true ) ;
391
+ var scale = 0.3 * Utils . SCALE ;
392
+ mat4 . scale ( mesh . getMatrix ( ) , mesh . getMatrix ( ) , [ scale , scale , scale ] ) ;
393
+ this . _meshPreview = mesh ;
394
+ return ;
395
+ }
396
+ mesh . normalizeSize ( ) ;
397
+ this . subdivideClamp ( mesh ) ;
398
+ this . addNewMesh ( mesh ) ;
399
+ } ,
400
+ subdivideClamp : function ( mesh , linear ) {
401
+ Subdivision . LINEAR = ! ! linear ;
346
402
while ( mesh . getNbFaces ( ) < 50000 )
347
403
mesh . addLevel ( ) ;
348
- // discard the very low res
349
- mesh . _meshes . splice ( 0 , 4 ) ;
350
- mesh . _sel -= 4 ;
404
+ // keep at max 4 multires
405
+ mesh . _meshes . splice ( 0 , Math . min ( mesh . _meshes . length - 4 , 4 ) ) ;
406
+ mesh . _sel = mesh . _meshes . length - 1 ;
351
407
Subdivision . LINEAR = false ;
352
-
353
- return this . addNewMesh ( mesh ) ;
354
408
} ,
355
409
addNewMesh : function ( mesh ) {
356
410
this . _meshes . push ( mesh ) ;
@@ -377,7 +431,7 @@ define([
377
431
}
378
432
379
433
if ( autoMatrix )
380
- this . scaleAndCenterMeshes ( newMeshes ) ;
434
+ this . normalizeAndCenterMeshes ( newMeshes ) ;
381
435
this . _states . pushStateAdd ( newMeshes ) ;
382
436
this . setMesh ( meshes [ meshes . length - 1 ] ) ;
383
437
this . _camera . resetView ( ) ;
@@ -392,7 +446,7 @@ define([
392
446
this . _showContour = opts . outline ;
393
447
this . _autoMatrix = opts . scalecenter ;
394
448
this . setMesh ( null ) ;
395
- this . _mouseButton = 0 ;
449
+ this . _action = 'NOTHING' ;
396
450
} ,
397
451
deleteCurrentSelection : function ( ) {
398
452
if ( ! this . _mesh )
@@ -439,19 +493,13 @@ define([
439
493
for ( var i = 0 , j = 0 , n = u8lum . length ; i < n ; ++ i , j += 4 )
440
494
u8lum [ i ] = Math . round ( ( u8rgba [ j ] + u8rgba [ j + 1 ] + u8rgba [ j + 2 ] ) / 3 ) ;
441
495
442
- this . loadAlphaTexture ( u8lum , img . width , img . height , name ) ;
496
+ name = Picking . addAlpha ( u8lum , img . width , img . height , name ) . _name ;
443
497
444
- if ( ! name ) return ;
445
- var id = Picking . ALPHAS . length - 1 ;
446
498
var entry = { } ;
447
- entry [ id ] = name ;
499
+ entry [ name ] = name ;
448
500
this . getGui ( ) . addAlphaOptions ( entry ) ;
449
- if ( tool && tool . _ctrlAlpha ) tool . _ctrlAlpha . setValue ( id ) ;
450
- } ,
451
- loadAlphaTexture : function ( u8 , w , h , name ) {
452
- var ans = Picking . ALPHAS_NAMES ;
453
- ans . push ( name || 'alpha_' + ans . length ) ;
454
- return Picking . addAlpha ( u8 , w , h ) ;
501
+ if ( tool && tool . _ctrlAlpha )
502
+ tool . _ctrlAlpha . setValue ( name ) ;
455
503
}
456
504
} ;
457
505
0 commit comments