/** * Scene Superset - The apiScene properties get moved into the Scene object itself, and then the instance is * created * @param graphics * @param apiScene GameLib.D3.API.Scene * @param computeNormals * @constructor */ GameLib.D3.Scene = function ( graphics, apiScene, imageFactory, computeNormals ) { this.graphics = graphics; this.graphics.isNotThreeThrow(); if (GameLib.Utils.UndefinedOrNull(apiScene)) { apiScene = {}; } if (GameLib.Utils.UndefinedOrNull(computeNormals)) { computeNormals = true; } this.computeNormals = computeNormals; GameLib.D3.API.Scene.call( this, apiScene.id, apiScene.name, apiScene.meshes, apiScene.position, apiScene.quaternion, apiScene.scale, apiScene.parentGameId, apiScene.lights, apiScene.materials, apiScene.textures, apiScene.parentEntity ); if (GameLib.Utils.UndefinedOrNull(imageFactory)) { console.warn('Cannot create a Scene without specifying an ImageFactory'); throw new Error('Cannot create a Scene without specifying an ImageFactory'); } this.imageFactory = imageFactory; this.idToObject = {}; this.meshes = this.meshes.map( function(apiMesh) { var mesh = new GameLib.D3.Mesh( this.graphics, apiMesh, this.computeNormals, this.imageFactory ); this.idToObject[mesh.id] = mesh; if (mesh.skeleton) { this.idToObject[mesh.skeleton.id] = mesh.skeleton; mesh.skeleton.bones.map( function (bone) { this.idToObject[bone.id] = bone; }.bind(this) ) } mesh.materials.map( function(material) { this.idToObject[material.id] = material; for (var property in material) { if (material.hasOwnProperty(property)) { if (material[property] instanceof GameLib.D3.Texture) { this.idToObject[material[property].id] = material[property]; } } } }.bind(this) ); return mesh; }.bind(this) ); this.position = new GameLib.Vector3( this.graphics, this.position, this ); this.quaternion = new GameLib.Quaternion( this.graphics, this.quaternion, this ); this.scale = new GameLib.Vector3( this.graphics, this.scale, this ); this.lights = this.lights.map( function(apiLight) { if (apiLight instanceof GameLib.D3.API.Light) { var light = new GameLib.D3.Light( this.graphics, apiLight ); this.idToObject[light.id] = light; return light; } else { } }.bind(this) ); this.idToObject[this.id] = this; this.instance = this.createInstance(); }; GameLib.D3.Scene.prototype = Object.create(GameLib.D3.API.Scene.prototype); GameLib.D3.Scene.prototype.constructor = GameLib.D3.Scene; /** * Creates an instance scene * @returns {THREE.Scene} */ GameLib.D3.Scene.prototype.createInstance = function() { var instance = new THREE.Scene(); instance.name = this.name; instance.position = this.position.instance; instance.scale = this.scale.instance; instance.quaternion = this.quaternion.instance; for (var im = 0; im < this.meshes.length; im++) { instance.add(this.meshes[im].instance); } for (var l = 0; l < this.lights.length; l++) { instance.add(this.lights[l].instance); } return instance; }; /** * Converts a GameLib.D3.Scene to a GameLib.D3.API.Scene * @returns {GameLib.D3.API.Scene} */ GameLib.D3.Scene.prototype.toApiScene = function() { var apiMeshes = this.meshes.map( function(mesh) { return mesh.toApiMesh(); } ); var apiLights = this.lights.map( function(light) { return light.toApiLight(); } ); return new GameLib.D3.API.Scene( this.id, this.name, apiMeshes, this.position.toApiVector(), this.quaternion.toApiQuaternion(), this.scale.toApiVector(), this.parentGameId, apiLights, GameLib.Utils.IdOrNull(this.parentEntity) ); }; /** * Converts a scene Object to a GameLib.D3.Scene object * @param graphics GameLib.D3.Graphics * @param objectScene Object * @param computeNormals boolean to indicate whether or not to recalculate normals * @param imageFactory GameLib.D3.ImageFactory * @returns {GameLib.D3.Scene} * @constructor */ GameLib.D3.Scene.FromObjectScene = function( graphics, objectScene, computeNormals, imageFactory ) { var apiScene = GameLib.D3.API.Scene.FromObjectScene(objectScene); return new GameLib.D3.Scene( graphics, apiScene, imageFactory, computeNormals ); }; /** * Transforms raw scene data into a GameLib.D3.Scene * @param graphics * @param objectScene Object (as it comes from the API) * @param computeNormals * @param onLoaded * @param imageFactory GameLib.D3.ImageFactory * @constructor */ GameLib.D3.Scene.LoadScene = function( graphics, objectScene, computeNormals, onLoaded, imageFactory ) { var scene = GameLib.D3.Scene.FromObjectScene( graphics, objectScene, computeNormals, imageFactory ); onLoaded(scene); }; /** * Loads a scene directly from the API * @param graphics GameLib.D3.Graphics * @param partialSceneObject Object {path: '', name: ''} * @param apiUrl * @param onLoaded * @param imageFactory GameLib.D3.ImageFactory */ GameLib.D3.Scene.LoadSceneFromApi = function( graphics, partialSceneObject, apiUrl, onLoaded, imageFactory ) { /** * First check if this is a client or server side request */ if (typeof XMLHttpRequest == 'undefined') { console.warn('implement server side loading from API here'); return onLoaded(null, new Error('not implemented')); } var xhr = new XMLHttpRequest(); xhr.open( 'GET', apiUrl + '/scene/load' + partialSceneObject.path + '/' + partialSceneObject.name ); xhr.onreadystatechange = function(xhr) { return function() { if (xhr.readyState == 4) { try { var response = JSON.parse(xhr.responseText); } catch (e) { return onLoaded(null, new Error('Could not load scene : ' + e.message)); } if (!response.scene || response.scene.length == 0) { return onLoaded(null, new Error('Could not load scene')); } var objectScene = response.scene[0]; GameLib.D3.Scene.LoadScene( graphics, objectScene, true, onLoaded, imageFactory ); } } }(xhr); xhr.send(); };