/** * Renders a scene with a camera * @param graphics GameLib.D3.Graphics * @param apiRenderer GameLib.D3.API.Renderer * @constructor */ GameLib.D3.Renderer = function ( graphics, apiRenderer ) { this.graphics = graphics; this.graphics.isNotThreeThrow(); if (GameLib.Utils.UndefinedOrNull(apiRenderer)) { apiRenderer = {}; } if (apiRenderer instanceof GameLib.D3.Renderer) { return apiRenderer; } GameLib.D3.API.Renderer.call( this, apiRenderer.id, apiRenderer.name, apiRenderer.autoClear, apiRenderer.localClipping, apiRenderer.width, apiRenderer.height, apiRenderer.preserveDrawingBuffer, apiRenderer.domElement, apiRenderer.clearColor, apiRenderer.camera, apiRenderer.scenes, apiRenderer.viewports, apiRenderer.clippingPlanes, apiRenderer.bufferScene, apiRenderer.bufferCamera, apiRenderer.renderTarget, apiRenderer.defaultScene, apiRenderer.sortObjects, apiRenderer.parentEntity ); this.clearColor = new GameLib.Color( this.graphics, this.clearColor, this ); if (this.domElement instanceof GameLib.API.DomElement) { this.domElement = new GameLib.DomElement( this.domElement ); } if (this.camera instanceof GameLib.D3.API.Camera) { this.camera = new GameLib.D3.Camera( this.graphics, this.camera ) } this.scenes = this.scenes.map(function(scene){ if (scene instanceof GameLib.D3.API.Scene) { return new GameLib.D3.Scene( this.graphics, scene ); } else { return scene; } }.bind(this)); this.viewports = this.viewports.map(function(viewport){ if (viewport instanceof GameLib.D3.API.Viewport) { return new GameLib.D3.Viewport( this.graphics, viewport ); } else { return viewport; } }.bind(this)); this.clippingPlanes = this.clippingPlanes.map(function(clippingPlane){ if (clippingPlane instanceof GameLib.D3.API.Mesh) { return new GameLib.D3.Mesh.Plane( this.graphics, clippingPlane, clippingPlane.width, clippingPlane.height, clippingPlane.widthSegments, clippingPlane.heightSegments, clippingPlane.heightMapScale, clippingPlane.isHeightMap, clippingPlane.isClippingPlane, clippingPlane.distanceFromOrigin ); } else { return clippingPlane; } }.bind(this)); if (this.bufferScene instanceof GameLib.D3.API.Scene) { this.bufferScene = new GameLib.D3.Scene( this.graphics, this.bufferScene ) } if (this.bufferCamera instanceof GameLib.D3.API.Camera) { this.bufferCamera = new GameLib.D3.Camera( this.graphics, this.bufferCamera ) } if (this.renderTarget instanceof GameLib.D3.API.RenderTarget) { this.renderTarget = new GameLib.D3.RenderTarget( this.graphics, this.renderTarget ) } GameLib.Component.call( this, GameLib.Component.COMPONENT_RENDERER, { 'domElement' : GameLib.DomElement, 'camera' : GameLib.D3.Camera, 'scenes' : [GameLib.D3.Scene], 'viewports' : [GameLib.D3.Viewport], 'clippingPlanes': [GameLib.D3.Mesh.Plane], 'bufferScene' : GameLib.D3.Scene, 'bufferCamera' : GameLib.D3.Camera, 'renderTarget' : GameLib.D3.RenderTarget, 'defaultScene' : GameLib.D3.Scene } ); }; GameLib.D3.Renderer.prototype = Object.create(GameLib.D3.API.Renderer.prototype); GameLib.D3.Renderer.prototype.constructor = GameLib.D3.Renderer; /** * Create Renderer Instance * @returns {*} */ GameLib.D3.Renderer.prototype.createInstance = function() { if (GameLib.Utils.UndefinedOrNull(this.domElement)) { throw new Error('no dom element'); } if (GameLib.Utils.UndefinedOrNull(this.domElement.instance)) { throw new Error('no dom element instance'); } this.instance = new THREE.WebGLRenderer( { canvas : this.domElement.instance } ); if (this.clippingPlanes.length > 0) { this.instance.clippingPlanes = this.clippingPlanes.map( function(clippingPlane) { if (!clippingPlane.isClippingPlane || !clippingPlane.instance || !clippingPlane.instance.clipping) { throw new Error('is not a clipping plane or no clipping plane instance'); } return clippingPlane.instance.clipping; } ) } this.instance.localClippingEnabled = this.localClipping; this.instance.setSize( this.width, this.height ); this.instance.setClearColor( new THREE.Color( this.clearColor.r, this.clearColor.g, this.clearColor.b ), 1 - this.clearColor.a ); this.instance.domElement.width = this.width; this.instance.domElement.height = this.height; this.instance.autoClear = this.autoClear; this.instance.preserveDrawingBuffer = this.preserveDrawingBuffer; this.instance.sortObjects = this.sortObjects; GameLib.Component.prototype.createInstance.call(this); }; /** * */ GameLib.D3.Renderer.prototype.updateInstance = function() { if (!this.instance) { try { this.createInstance(); } catch (error) { console.error(error.message); return; } } this.instance.localClippingEnabled = this.localClipping; this.instance.setSize( this.width, this.height ); this.instance.setClearColor( new THREE.Color( this.clearColor.r, this.clearColor.g, this.clearColor.b ), 1 - this.clearColor.a ); this.instance.domElement.width = this.width; this.instance.domElement.height = this.height; this.instance.autoClear = this.autoClear; this.instance.preserveDrawingBuffer = this.preserveDrawingBuffer; if (this.clippingPlanes.length > 0) { this.instance.clippingPlanes = this.clippingPlanes.map( function(clippingPlane) { if (!clippingPlane.isClippingPlane || !clippingPlane.instance || !clippingPlane.instance.clipping) { throw new Error('is not a clipping plane or no clipping plane instance'); } return clippingPlane.instance.clipping; } ) } else { this.instance.clippingPlanes = []; } this.instance.sortObjects = this.sortObjects; }; /** * * @returns {GameLib.D3.API.Renderer} */ GameLib.D3.Renderer.prototype.toApiObject = function() { var apiRenderer = new GameLib.D3.API.Renderer( this.id, this.name, this.autoClear, this.localClipping, this.width, this.height, this.preserveDrawingBuffer, GameLib.Utils.IdOrNull(this.domElement), this.clearColor.toApiObject(), GameLib.Utils.IdOrNull(this.camera), this.scenes.map(function(scene){ return GameLib.Utils.IdOrNull(scene); }), this.viewports.map(function(viewport){ return GameLib.Utils.IdOrNull(viewport); }), this.clippingPlanes.map( function(clippingPlane) { return GameLib.Utils.IdOrNull(clippingPlane); } ), GameLib.Utils.IdOrNull(this.bufferScene), GameLib.Utils.IdOrNull(this.bufferCamera), GameLib.Utils.IdOrNull(this.renderTarget), GameLib.Utils.IdOrNull(this.defaultScene), this.sortObjects, GameLib.Utils.IdOrNull(this.parentEntity) ); return apiRenderer; }; /** * * @param graphics * @param objectComponent * @returns {GameLib.D3.Renderer} * @constructor */ GameLib.D3.Renderer.FromObject = function(graphics, objectComponent) { var apiRenderer = GameLib.D3.API.Renderer.FromObject(objectComponent); return new GameLib.D3.Renderer( graphics, apiRenderer ); }; /** * Convenience render function */ GameLib.D3.Renderer.prototype.render = function(delta, scenes) { if (!this.instance) { return; } if (GameLib.Utils.UndefinedOrNull(scenes)) { scenes = this.scenes; } if (this.viewports.length > 1) { this.instance.autoClear = false; } if (scenes.length > 1) { this.instance.autoClear = false; } this.instance.clear(); if ( this.bufferScene && this.bufferScene.instance && this.bufferCamera && this.bufferCamera.instance && this.renderTarget && this.renderTarget.instance ) { /** * We have a buffer that should render to an offscreen render target */ this.instance.render( this.bufferScene.instance, this.bufferCamera.instance, this.renderTarget.instance ); } this.viewports.map( function(viewport) { this.instance.setViewport( viewport.x * this.width, viewport.y * this.height, viewport.width * this.width, viewport.height * this.height ); scenes.map(function(scene) { if (!scene.instance) { return; } if (!this.camera.instance && !(scene.renderCamera || scene.renderCamera.instance)) { return; } /** * A scene's renderCamera instance overrides the default renderer camera */ if (scene.renderCamera && scene.renderCamera.instance) { this.instance.render( scene.instance, scene.renderCamera.instance ) } else { this.instance.render( scene.instance, this.camera.instance ) } }.bind(this)); }.bind(this) ); }; GameLib.D3.Renderer.prototype.setSize = function(width, height) { this.width = width; this.height = height; this.updateInstance(); };