UNPKG

20.5 kBHTMLView Raw
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="utf-8">
5 <title>FluxRenderer.js - Documentation</title>
6
7 <script src="scripts/prettify/prettify.js"></script>
8 <script src="scripts/prettify/lang-css.js"></script>
9 <!--[if lt IE 9]>
10 <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
11 <![endif]-->
12 <link type="text/css" rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
13 <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
14 <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
15</head>
16<body>
17
18<input type="checkbox" id="nav-trigger" class="nav-trigger" />
19<label for="nav-trigger" class="navicon-button x">
20 <div class="navicon"></div>
21</label>
22
23<label for="nav-trigger" class="overlay"></label>
24
25<nav>
26 <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="EdgesHelper.html">EdgesHelper</a><ul class='methods'><li data-type='method'><a href="EdgesHelper.html#.AddEdges">AddEdges</a></li></ul></li><li><a href="FluxCameras.html">FluxCameras</a><ul class='methods'><li data-type='method'><a href="FluxCameras.html#.cameraFromJSON">cameraFromJSON</a></li><li data-type='method'><a href="FluxCameras.html#.cameraToJSON">cameraToJSON</a></li><li data-type='method'><a href="FluxCameras.html#fromJSON">fromJSON</a></li><li data-type='method'><a href="FluxCameras.html#getCamera">getCamera</a></li><li data-type='method'><a href="FluxCameras.html#setView">setView</a></li><li data-type='method'><a href="FluxCameras.html#toJSON">toJSON</a></li><li data-type='method'><a href="FluxCameras.html#updateCamera">updateCamera</a></li></ul></li><li><a href="FluxRenderContext.html">FluxRenderContext</a><ul class='methods'><li data-type='method'><a href="FluxRenderContext.html#.getNextContext">getNextContext</a></li></ul></li><li><a href="FluxRenderer.html">FluxRenderer</a><ul class='methods'><li data-type='method'><a href="FluxRenderer.html#addControls">addControls</a></li><li data-type='method'><a href="FluxRenderer.html#anyValidPrims">anyValidPrims</a></li><li data-type='method'><a href="FluxRenderer.html#detach">detach</a></li><li data-type='method'><a href="FluxRenderer.html#doRender">doRender</a></li><li data-type='method'><a href="FluxRenderer.html#focus">focus</a></li><li data-type='method'><a href="FluxRenderer.html#fromJSON">fromJSON</a></li><li data-type='method'><a href="FluxRenderer.html#getGlCanvas">getGlCanvas</a></li><li data-type='method'><a href="FluxRenderer.html#getSelection">getSelection</a></li><li data-type='method'><a href="FluxRenderer.html#homeCamera">homeCamera</a></li><li data-type='method'><a href="FluxRenderer.html#setClearColor">setClearColor</a></li><li data-type='method'><a href="FluxRenderer.html#setEdgesMode">setEdgesMode</a></li><li data-type='method'><a href="FluxRenderer.html#setHelpersVisible">setHelpersVisible</a></li><li data-type='method'><a href="FluxRenderer.html#setLights">setLights</a></li><li data-type='method'><a href="FluxRenderer.html#setModel">setModel</a></li><li data-type='method'><a href="FluxRenderer.html#setSelection">setSelection</a></li><li data-type='method'><a href="FluxRenderer.html#setSelectionMaterial">setSelectionMaterial</a></li><li data-type='method'><a href="FluxRenderer.html#setSize">setSize</a></li><li data-type='method'><a href="FluxRenderer.html#setView">setView</a></li><li data-type='method'><a href="FluxRenderer.html#toJSON">toJSON</a></li></ul></li><li><a href="FluxViewport.html">FluxViewport</a><ul class='methods'><li data-type='method'><a href="FluxViewport.html#.getChangeEvent">getChangeEvent</a></li><li data-type='method'><a href="FluxViewport.html#.getEdgesModes">getEdgesModes</a></li><li data-type='method'><a href="FluxViewport.html#.getEvents">getEvents</a></li><li data-type='method'><a href="FluxViewport.html#.getSelectionModes">getSelectionModes</a></li><li data-type='method'><a href="FluxViewport.html#.getViews">getViews</a></li><li data-type='method'><a href="FluxViewport.html#.isKnownGeom">isKnownGeom</a></li><li data-type='method'><a href="FluxViewport.html#activateShadows">activateShadows</a></li><li data-type='method'><a href="FluxViewport.html#addControls">addControls</a></li><li data-type='method'><a href="FluxViewport.html#downloadState">downloadState</a></li><li data-type='method'><a href="FluxViewport.html#focus">focus</a></li><li data-type='method'><a href="FluxViewport.html#fromJSON">fromJSON</a></li><li data-type='method'><a href="FluxViewport.html#getAutoFocus">getAutoFocus</a></li><li data-type='method'><a href="FluxViewport.html#getGlCanvas">getGlCanvas</a></li><li data-type='method'><a href="FluxViewport.html#getJson">getJson</a></li><li data-type='method'><a href="FluxViewport.html#getObjectMap">getObjectMap</a></li><li data-type='method'><a href="FluxViewport.html#getSelection">getSelection</a></li><li data-type='method'><a href="FluxViewport.html#homeCamera">homeCamera</a></li><li data-type='method'><a href="FluxViewport.html#render">render</a></li><li data-type='method'><a href="FluxViewport.html#setAutoFocus">setAutoFocus</a></li><li data-type='method'><a href="FluxViewport.html#setClearColor">setClearColor</a></li><li data-type='method'><a href="FluxViewport.html#setEdgesMode">setEdgesMode</a></li><li data-type='method'><a href="FluxViewport.html#setFogDensity">setFogDensity</a></li><li data-type='method'><a href="FluxViewport.html#setGeometryEntity">setGeometryEntity</a></li><li data-type='method'><a href="FluxViewport.html#setGeometryJson">setGeometryJson</a></li><li data-type='method'><a href="FluxViewport.html#setHelpersVisible">setHelpersVisible</a></li><li data-type='method'><a href="FluxViewport.html#setSelection">setSelection</a></li><li data-type='method'><a href="FluxViewport.html#setSelectionMaterial">setSelectionMaterial</a></li><li data-type='method'><a href="FluxViewport.html#setSize">setSize</a></li><li data-type='method'><a href="FluxViewport.html#setTessUrl">setTessUrl</a></li><li data-type='method'><a href="FluxViewport.html#setupDefaultLighting">setupDefaultLighting</a></li><li data-type='method'><a href="FluxViewport.html#setView">setView</a></li><li data-type='method'><a href="FluxViewport.html#toJSON">toJSON</a></li></ul></li></ul><h3>Global</h3><ul><li><a href="global.html#_deleteFromScene">_deleteFromScene</a></li><li><a href="global.html#_removeGeometries">_removeGeometries</a></li></ul>
27</nav>
28
29<div id="main">
30
31 <h1 class="page-title">FluxRenderer.js</h1>
32
33
34
35
36
37
38
39 <section>
40 <article>
41 <pre class="prettyprint source linenums"><code>'use strict';
42
43import * as THREE from 'three';
44import EdgesHelper from './EdgesHelper.js';
45import FluxCameras from './FluxCameras.js';
46import FluxHelpers from './helpers/FluxHelpers.js';
47import FluxRenderContext from './FluxRenderContext.js';
48import CameraControls from './controls/CameraControls.js';
49import SelectionControls from './controls/SelectionControls.js';
50import * as constants from './controls/constants.js';
51
52/**
53 * Class wrapping the three.js renderer with more build in functionality.
54 * Context swapping lets a single OpenGL context and canvas be used for multiple renderers.
55 * @class FluxRenderer
56 * @param {Element} domParent The div container for the canvas
57 * @param {Number} width The width of the canvas
58 * @param {Number} height The height of the canvas
59 * @param {Enumeration} selection Whether to enable user selection
60 */
61export default function FluxRenderer(domParent, width, height, selection) {
62 this.id = FluxRenderer.nextId++;
63
64 // Dom element that wraps the canvas
65 this._domParent = domParent;
66
67 // Current three.js geometry to render
68 this._model = null;
69
70 // The object containing the lights in the scene
71 this._lights = null;
72
73 // The context that contains the renderer and corresponds to a canvas
74 // Create renderer for the first time.
75 this._context = FluxRenderContext.getNewContext();
76
77 this._width = width;
78 this._height = height;
79
80 this._createCacheCanvas(width, height);
81
82 this.setClearColor(0xC5CDCC);
83
84 this._cameras = new FluxCameras(width, height);
85 this._helpers = new FluxHelpers();
86 this._helpersScene = new THREE.Scene();
87 this._helpersScene.add(this._helpers);
88
89 // Scene containing geometry to be rendered in this viewport THREE.Scene
90 this._scene = new THREE.Scene();
91
92 this._controls = [];
93 // Camera to be rendered with.Any instance of `THREE.Camera` can be set here.
94 var _this = this;
95 this._editorControls = this.addControls(CameraControls);
96 this._editorControls.addEventListener(constants.Events.CHANGE, function(event) {
97 _this._cameras.updateCamera(_this._width, _this._height);
98 _this.dispatchEvent(event);
99 });
100 this._selectionControls = this.addControls(SelectionControls);
101 this._selectionControls.setMode(selection);
102
103 // Fog object for this viewport constructed from color and density
104 this._fog = new THREE.FogExp2( this._clearColor, 0.0 );
105 this._scene.fog = this._fog;
106
107 // Scene containing edges geometry for hidden line rendering
108 this._edgesScene = new THREE.Scene();
109 this._edgesMode = EdgesHelper.EDGES_MODES.NONE;
110}
111
112FluxRenderer.prototype = Object.create( THREE.EventDispatcher.prototype );
113FluxRenderer.prototype.constructor = FluxRenderer;
114
115// Used for debugging issues with _setHost
116FluxRenderer.nextId = 0;
117
118/**
119 * Set the lights used to illuminate the scene.
120 * @param {THREE.Object3D} lights Object with lights as children
121 */
122FluxRenderer.prototype.setLights = function(lights) {
123 if (this._lights) {
124 this._scene.remove(this._lights);
125 }
126 this._lights = lights;
127 this._scene.add(this._lights);
128};
129
130/**
131 * Remove the geometry objects from the THREE registry so they can be garbage collected
132 * @param {THREE.Object3D} obj The object being removed
133 */
134function _removeGeometries(obj) {
135 if (obj.geometry) {
136 obj.geometry.dispose();
137 }
138}
139
140/**
141 * Remove an object from the scene and clean up memory
142 * @param {THREE.Scene} scene Scene containing the model
143 * @param {THREE.Object3D} model The geometry to remove
144 */
145function _deleteFromScene(scene, model) {
146 if (!model || !scene) return;
147 scene.remove(model);
148 model.traverse(_removeGeometries);
149}
150
151/**
152 * Add a new plugin for user interaction controls.
153 * See ViewportControls.js for more information.
154 * @param {ViewportControls} CustomControls A constructor that implements the controls interface.
155 * @return {CustomControls} The new instance
156 */
157FluxRenderer.prototype.addControls = function(CustomControls) {
158 var customControls = new CustomControls(this._cameras.getCamera(), this._scene, this._domParent, this._width, this._height);
159 var _this = this;
160 customControls.addEventListener(constants.Events.CHANGE, function (event) {
161 _this.dispatchEvent(event);
162 });
163 this._controls.push(customControls);
164 return customControls;
165};
166
167/**
168 * Define the material that is applied on selected objects
169 * @param {Object} data Flux json description of a material
170 */
171FluxRenderer.prototype.setSelectionMaterial = function(data) {
172 this._selectionControls.setMaterial(data);
173};
174
175/**
176 * Get the currently selected geometry
177 * @return {THREE.Object3D} Current selection
178 */
179FluxRenderer.prototype.getSelection = function() {
180 return this._selectionControls.getSelection();
181};
182
183/**
184 * set the currently selected geometry
185 * @param {THREE.Object3D} object New selection
186 */
187FluxRenderer.prototype.setSelection = function(object) {
188 this._selectionControls.setSelection(object);
189};
190
191/**
192 * Set the object to render
193 * Replaces old render contents
194 * @param {THREE.Object3D} model What to render
195 */
196FluxRenderer.prototype.setModel = function(model) {
197 if (this._model) {
198 _deleteFromScene(this._scene, this._model);
199 _deleteFromScene(this._edgesScene, this._model.edgesHelper);
200 }
201 this._model = model;
202 if (this._model) {
203 this._scene.add(this._model);
204 if (EdgesHelper.AddEdges(this._model, this._edgesMode)) {
205 this._edgesScene.add(this._model.edgesHelper);
206 }
207 }
208};
209
210/**
211 * Set the edges rendering mode for hidden line rendering
212 * @param {EdgesHelper.EDGES_MODES} mode Whether to render front, back, both or none
213 */
214FluxRenderer.prototype.setEdgesMode = function(mode) {
215 this._edgesMode = mode;
216};
217
218/**
219 * Restore the camera to a default location
220 */
221FluxRenderer.prototype.homeCamera = function() {
222 this._editorControls.focus(this._helpers);
223};
224
225/**
226* Focus the controls' current camera on an object.
227* This function will focus on the union of object and all of it's visible children.
228* @param {THREE.Object3D} [obj] The scene object to focus on.
229*/
230FluxRenderer.prototype.focus = function(obj) {
231 if (!this._model &amp;&amp; !obj) return;
232 if (obj) {
233 this._editorControls.focus(obj);
234 } else {
235 var selection = this._selectionControls.getSelectionSphere();
236 if (selection) {
237 this._editorControls.focus(selection);
238 } else {
239 this._editorControls.focus(this._model);
240 }
241 }
242 // Changing the controls here triggers a render
243};
244
245/**
246 * Set the clear color (background) for WebGL canvas
247 * @param {String|Number} color Hexadecimal or a CSS-style string
248 * @param {Number} alpha Opacity
249 */
250FluxRenderer.prototype.setClearColor = function(color, alpha) {
251 this._clearColor = new THREE.Color(color);
252 this._clearAlpha = alpha;
253};
254
255/**
256 * Whether to draw helpers (axis and grid)
257 *
258 * @param {Boolean} visible False to hide them
259 */
260FluxRenderer.prototype.setHelpersVisible = function(visible) {
261 this._helpersScene.visible = !!visible;
262};
263
264/**
265 * Set up a new canvas used for storing a cached image.
266 * The cache image is populated when this renderer loses it's context.
267 * @private
268 * @param {Number} width The width of the canvas
269 * @param {Number} height The height of the canvas
270 */
271FluxRenderer.prototype._createCacheCanvas = function(width, height) {
272 if (this._cacheCanvas) return;
273 // The canvas used to store a cached image of the previous render when all the WebGL contexts are in use with other renderers
274 this._cacheCanvas = document.createElement('canvas');
275 this._cacheCanvas.width = width;
276 this._cacheCanvas.height = height;
277 this._cacheCanvas.style.position = 'absolute';
278 this._cacheCanvas.style['user-select'] = 'none';
279 this._cacheCanvas.style['-webkit-user-select'] = 'none';
280 this._domParent.appendChild(this._cacheCanvas);
281
282 // Canvas2D used to store framebuffer pixels after renderer.domElement migration.
283 this.ctx = this._cacheCanvas.getContext('2d');
284};
285
286/**
287 * Destructor to prevent future rendering after being unloaded
288 */
289FluxRenderer.prototype.detach = function() {
290 if (this._context &amp;&amp; this._context.currentHost === this) {
291 this._context.currentHost = null;
292 }
293};
294
295/**
296 * Set which camera view to use (ex perspective, top etc.).
297 * @param {FluxCameras.VIEWS} view The new view mode
298 */
299FluxRenderer.prototype.setView = function(view) {
300 this._cameras.setView(view);
301 this._cameras.updateCamera(this._width, this._height);
302 // Update the camera for each controls object
303 for (var i=0;i&lt;this._controls.length;i++) {
304 this._controls[i].setCamera(this._cameras.getCamera());
305 }
306 this._helpers.setView(view);
307};
308
309/**
310 * Creates depth, normal materials and depth, normal render targets.
311 * @private
312 */
313FluxRenderer.prototype._addRenderTargets = function() {
314 // depth render target (uses THREE.js depth shader)
315 this._depthTarget = new THREE.WebGLRenderTarget(
316 window.innerWidth, //TODO(kyle) Why does this use window!?
317 window.innerHeight,
318 {
319 minFilter: THREE.NearestFilter,
320 magFilter: THREE.NearestFilter,
321 format: THREE.RGBAFormat
322 }
323 );
324
325 // normal render target
326 this._normalTarget = this._depthTarget.clone();
327};
328
329/**
330* Render the scene with its geometry.
331*/
332FluxRenderer.prototype.doRender = function () {
333 this._setHost();
334 this._update();
335 this._context.renderer.clear();
336 this._context.renderer.render(this._scene, this._cameras.getCamera());
337 this._context.renderer.render(this._edgesScene, this._cameras.getCamera());
338 this._context.renderer.render(this._helpersScene, this._cameras.getCamera());
339};
340
341/**
342 * Say whether there are any objects to render in the model
343 * @return {Boolean} True if there are objects to render
344 */
345FluxRenderer.prototype.anyValidPrims = function() {
346 return this._model ? this._model.children.length > 0 : false;
347};
348
349/**
350 * Copy the image that is in the render canvas to this renderer's cache canvas.
351 * This allows the rendered image to persist even when the renderer is not available.
352 * This happens when the user moves the mouse away from this viewport to another one.
353 * @private
354 */
355FluxRenderer.prototype._cacheImageToCanvas = function () {
356 this.doRender();
357 this.ctx.drawImage(this._context.renderer.domElement, 0, 0, this._cacheCanvas.width, this._cacheCanvas.height);
358};
359
360/**
361 * Get the canvas for use in QA scripts
362 * @return {Canvas} WebGL canvas dom element
363 */
364FluxRenderer.prototype.getGlCanvas = function() {
365 return this._context.renderer.domElement;
366};
367
368/**
369* Migrate renderer.domElement to this host if necessary
370* and copy framebuffer into Canvas2D element of the previous host.
371 * @private
372*/
373FluxRenderer.prototype._setHost = function() {
374 if (this === this._context.currentHost) return;
375 if (this._context.currentHost) {
376 // Copy the image from domElement (THREE's interactive canvas)
377 // to the 2D context for this element's canvas
378 // This image will remain up until the user interacts with the old viewport again
379 this._context.currentHost._cacheImageToCanvas();
380 }
381 this._context.currentHost = this;
382 this.setSize(this._width, this._height);
383 // Move the THREE.WebGLRenderer's canvas under the new host
384 this._domParent.appendChild(this._context.renderer.domElement);
385};
386
387/**
388 * Set the WebGLRenderer parameters to match this renderer.
389 * @private
390 */
391FluxRenderer.prototype._update = function() {
392 this._context.renderer.autoClearColor = false;
393 this._context.renderer.autoClearDepth = false;
394 this._context.renderer.setSize(this._width, this._height);
395 this._context.renderer.setClearColor(this._clearColor, this._clearAlpha);
396};
397
398/**
399 * Set the size of things that are per viewport.
400 * @param {Number} width The canvas width in pixels
401 * @param {Number} height The canvas height in pixels
402 */
403FluxRenderer.prototype.setSize = function(width, height) {
404 if (width &lt;= 0 || height &lt;= 0 || (width === this._width &amp;&amp; height === this.height)) return;
405 this._width = width;
406 this._height = height;
407
408 this._cameras.updateCamera(this._width, this._height);
409
410 for (var i=0;i&lt;this._controls.length;i++) {
411 this._controls[i].setSize(this._width, this._height);
412 }
413
414 this._cacheCanvas.height = height;
415 this._cacheCanvas.width = width;
416};
417
418/**
419 * Make serializable by pruning all references and building an object property tree
420 * @return {Object} Data to stringify
421 */
422FluxRenderer.prototype.toJSON = function() {
423 var serializableState = {
424 cameras: this._cameras.toJSON(), // camera pos and view
425 controls: this._editorControls.toJSON() // center point
426 };
427 //TODO(Kyle): Transition to serializing all controls objets
428 return serializableState;
429};
430
431/**
432 * Take a data object and use it to update the internal state
433 * @param {Object} state The properties to set
434 */
435FluxRenderer.prototype.fromJSON = function(state) {
436 if (!state) return;
437 if (state.cameras != null) {
438 this.setView(state.cameras.view);
439 this._cameras.fromJSON(state.cameras);
440 }
441 if (state.controls) {
442 //TODO(Kyle): Transition to deserializing all controls objets
443 this._editorControls.fromJSON(state.controls);
444 }
445};
446</code></pre>
447 </article>
448 </section>
449
450
451
452
453</div>
454
455<br class="clear">
456
457<footer>
458 Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Thu Jan 05 2017 16:26:56 GMT-0800 (PST) using the Minami theme.
459</footer>
460
461<script>prettyPrint();</script>
462<script src="scripts/linenumber.js"></script>
463</body>
464</html>