Skip to content
This repository was archived by the owner on Sep 16, 2023. It is now read-only.

Commit 2fe8922

Browse files
committed
Adds gizmo and primitives
1 parent 16b1b13 commit 2fe8922

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1890
-1232
lines changed

src/Scene.js

+133-85
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ define([
1010
'math3d/Picking',
1111
'mesh/Background',
1212
'mesh/Selection',
13-
'mesh/Grid',
1413
'mesh/Mesh',
1514
'mesh/multiresolution/Multimesh',
1615
'mesh/Primitive',
@@ -20,21 +19,31 @@ define([
2019
'render/Rtt',
2120
'render/shaders/ShaderMatcap',
2221
'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) {
2423

2524
'use strict';
2625

26+
var vec3 = glm.vec3;
27+
var mat4 = glm.mat4;
28+
2729
var Scene = function () {
2830
this._gl = null; // webgl context
2931
this._canvas = document.getElementById('canvas');
3032

3133
// core of the app
3234
this._states = new States(this); // for undo-redo
33-
this._sculpt = new Sculpt(this);
35+
this._sculpt = null;
3436
this._camera = new Camera(this);
3537
this._picking = new Picking(this); // the ray picking
3638
this._pickingSym = new Picking(this, true); // the symmetrical picking
3739

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+
3847
// renderable stuffs
3948
var opts = getUrlOptions();
4049
this._showContour = opts.outline;
@@ -58,16 +67,17 @@ define([
5867
};
5968

6069
Scene.prototype = {
61-
/** Initialization */
6270
start: function () {
6371
this.initWebGL();
6472
if (!this._gl)
6573
return;
74+
this._sculpt = new Sculpt(this);
6675
this._background = new Background(this._gl, this);
6776
this._selection = new Selection(this._gl);
68-
this._grid = new Grid(this._gl);
6977
this._rtt = new Rtt(this._gl);
7078
this._contour = new Contour(this._gl);
79+
this._grid = Primitive.createGrid(this._gl);
80+
this.initGrid();
7181

7282
this.loadTextures();
7383
this._gui.initGui();
@@ -110,6 +120,16 @@ define([
110120
setMesh: function (mesh) {
111121
return this.setOrUnsetMesh(mesh);
112122
},
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+
},
113133
setOrUnsetMesh: function (mesh, multiSelect) {
114134
if (!mesh) {
115135
this._selectMeshes.length = 0;
@@ -152,31 +172,60 @@ define([
152172
/** Render the scene */
153173
applyRender: function () {
154174
this._preventRender = false;
155-
this.computeMatricesAndSort();
175+
this.updateMatricesAndSort();
156176
var gl = this._gl;
177+
if (!gl) return;
157178

158179
if (this._drawFullScene) {
159180
gl.disable(gl.DEPTH_TEST);
160-
// gl.enable(gl.CULL_FACE);
161181

162182
var showContour = this._selectMeshes.length > 0 && this._showContour && this._contour.isEffective();
163183
if (showContour) {
184+
// flat color RTT for contours
164185
gl.bindFramebuffer(gl.FRAMEBUFFER, this._contour.getFramebuffer());
165186
gl.clear(gl.COLOR_BUFFER_BIT);
166187
for (var s = 0, sel = this._selectMeshes, nbSel = sel.length; s < nbSel; ++s)
167188
sel[s].renderFlatColor(this);
168189
}
169190

191+
// main scene RTT
170192
gl.bindFramebuffer(gl.FRAMEBUFFER, this._rtt.getFramebuffer());
171193
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
194+
195+
// BACKGROUND
172196
this._background.render();
173197

174198
gl.enable(gl.DEPTH_TEST);
199+
// GRID
175200
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
178221
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
179227

228+
// draw sobel contour
180229
if (showContour)
181230
this._contour.render();
182231
}
@@ -186,18 +235,25 @@ define([
186235
gl.disable(gl.DEPTH_TEST);
187236
this._rtt.render();
188237
this._selection.render(this);
238+
239+
gl.enable(gl.DEPTH_TEST);
240+
// draw sculpt gizmos
241+
this._sculpt.postRender();
189242
},
190243
/** Pre compute matrices and sort meshes */
191-
computeMatricesAndSort: function () {
244+
updateMatricesAndSort: function () {
192245
var meshes = this._meshes;
193246
var cam = this._camera;
194247
if (meshes.length > 0)
195248
cam.optimizeNearFar(this.computeBoundingBoxScene());
196-
this._grid.computeMatrices(cam);
197249
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);
200251
meshes.sort(Mesh.sortFunction);
252+
253+
if (this._meshPreview)
254+
this._meshPreview.updateMatrices(cam);
255+
if (this._grid)
256+
this._grid.updateMatrices(cam);
201257
},
202258
/** Load webgl context */
203259
initWebGL: function () {
@@ -223,6 +279,7 @@ define([
223279
gl.frontFace(gl.CCW);
224280
gl.depthFunc(gl.LEQUAL);
225281
gl.cullFace(gl.BACK);
282+
gl.enable(gl.CULL_FACE);
226283
gl.clearColor(0.033, 0.033, 0.033, 1);
227284
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
228285
},
@@ -253,67 +310,46 @@ define([
253310
this.initAlphaTextures();
254311
},
255312
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) {
259316
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+
}
268320
},
269321
/** Called when the window is resized */
270322
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;
273325

274326
this._background.onResize(newWidth, newHeight);
275327
this._rtt.onResize(newWidth, newHeight);
276328
this._contour.onResize(newWidth, newHeight);
277329
this._gl.viewport(0, 0, newWidth, newHeight);
278-
this._camera.updateProjection();
330+
this._camera.onResize(newWidth, newHeight);
279331
this.render();
280332
},
281333
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];
286335
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];
300343
}
301-
return bigBound;
344+
return bound;
302345
},
303346
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) {
317353
var box = this.computeBoundingBoxMeshes(meshes);
318354
var scale = Utils.SCALE / vec3.dist([box[0], box[1], box[2]], [box[3], box[4], box[5]]);
319355

@@ -322,35 +358,53 @@ define([
322358
mat4.translate(mCen, mCen, [-(box[0] + box[3]) * 0.5, -(box[1] + box[4]) * 0.5, -(box[2] + box[5]) * 0.5]);
323359

324360
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();
327362
mat4.mul(mat, mCen, mat);
328363
}
329364
},
330365
/** Load the sphere */
331366
addSphere: function () {
332367
// make a cube and subdivide it
333368
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);
340371
return this.addNewMesh(mesh);
341372
},
342373
addCube: function () {
343374
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;
346402
while (mesh.getNbFaces() < 50000)
347403
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;
351407
Subdivision.LINEAR = false;
352-
353-
return this.addNewMesh(mesh);
354408
},
355409
addNewMesh: function (mesh) {
356410
this._meshes.push(mesh);
@@ -377,7 +431,7 @@ define([
377431
}
378432

379433
if (autoMatrix)
380-
this.scaleAndCenterMeshes(newMeshes);
434+
this.normalizeAndCenterMeshes(newMeshes);
381435
this._states.pushStateAdd(newMeshes);
382436
this.setMesh(meshes[meshes.length - 1]);
383437
this._camera.resetView();
@@ -392,7 +446,7 @@ define([
392446
this._showContour = opts.outline;
393447
this._autoMatrix = opts.scalecenter;
394448
this.setMesh(null);
395-
this._mouseButton = 0;
449+
this._action = 'NOTHING';
396450
},
397451
deleteCurrentSelection: function () {
398452
if (!this._mesh)
@@ -439,19 +493,13 @@ define([
439493
for (var i = 0, j = 0, n = u8lum.length; i < n; ++i, j += 4)
440494
u8lum[i] = Math.round((u8rgba[j] + u8rgba[j + 1] + u8rgba[j + 2]) / 3);
441495

442-
this.loadAlphaTexture(u8lum, img.width, img.height, name);
496+
name = Picking.addAlpha(u8lum, img.width, img.height, name)._name;
443497

444-
if (!name) return;
445-
var id = Picking.ALPHAS.length - 1;
446498
var entry = {};
447-
entry[id] = name;
499+
entry[name] = name;
448500
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);
455503
}
456504
};
457505

0 commit comments

Comments
 (0)