From 0dbc266191147a430fc0242433b35faaa05afd55 Mon Sep 17 00:00:00 2001 From: "Mr.doob" Date: Thu, 23 Nov 2017 20:07:27 +0900 Subject: [PATCH] Removed unit builds. --- test/unit/three.editor.unit.js | 9435 ----- test/unit/three.example.unit.js | 15 - test/unit/three.source.unit.js | 66084 ------------------------------ 3 files changed, 75534 deletions(-) delete mode 100644 test/unit/three.editor.unit.js delete mode 100644 test/unit/three.example.unit.js delete mode 100644 test/unit/three.source.unit.js diff --git a/test/unit/three.editor.unit.js b/test/unit/three.editor.unit.js deleted file mode 100644 index a23638efa6..0000000000 --- a/test/unit/three.editor.unit.js +++ /dev/null @@ -1,9435 +0,0 @@ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory() : - typeof define === 'function' && define.amd ? define(factory) : - (factory()); -}(this, (function () { 'use strict'; - - QUnit.module( "Editor", () => { - - /** - * @author dforrer / https://github.com/dforrer - * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch) - */ - - /** - * @param editorRef pointer to main editor object used to initialize - * each command object with a reference to the editor - * @constructor - */ - - var Command$1 = function ( editorRef ) { - - this.id = - 1; - this.inMemory = false; - this.updatable = false; - this.type = ''; - this.name = ''; - - if ( editorRef !== undefined ) { - - Command$1.editor = editorRef; - - } - this.editor = Command$1.editor; - - - }; - - Command$1.prototype.toJSON = function () { - - var output = {}; - output.type = this.type; - output.id = this.id; - output.name = this.name; - return output; - - }; - - Command$1.prototype.fromJSON = function ( json ) { - - this.inMemory = true; - this.type = json.type; - this.id = json.id; - this.name = json.name; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Command', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Config', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - var Editor = function () { - - this.DEFAULT_CAMERA = new THREE.PerspectiveCamera( 50, 1, 0.1, 10000 ); - this.DEFAULT_CAMERA.name = 'Camera'; - this.DEFAULT_CAMERA.position.set( 20, 10, 20 ); - this.DEFAULT_CAMERA.lookAt( new THREE.Vector3() ); - - var Signal = signals.Signal; - - this.signals = { - - // script - - editScript: new Signal(), - - // player - - startPlayer: new Signal(), - stopPlayer: new Signal(), - - // actions - - showModal: new Signal(), - - // notifications - - editorCleared: new Signal(), - - savingStarted: new Signal(), - savingFinished: new Signal(), - - themeChanged: new Signal(), - - transformModeChanged: new Signal(), - snapChanged: new Signal(), - spaceChanged: new Signal(), - rendererChanged: new Signal(), - - sceneBackgroundChanged: new Signal(), - sceneFogChanged: new Signal(), - sceneGraphChanged: new Signal(), - - cameraChanged: new Signal(), - - geometryChanged: new Signal(), - - objectSelected: new Signal(), - objectFocused: new Signal(), - - objectAdded: new Signal(), - objectChanged: new Signal(), - objectRemoved: new Signal(), - - helperAdded: new Signal(), - helperRemoved: new Signal(), - - materialChanged: new Signal(), - - scriptAdded: new Signal(), - scriptChanged: new Signal(), - scriptRemoved: new Signal(), - - windowResize: new Signal(), - - showGridChanged: new Signal(), - refreshSidebarObject3D: new Signal(), - historyChanged: new Signal() - - }; - - this.config = new Config( 'threejs-editor' ); - this.history = new History( this ); - this.storage = new Storage(); - this.loader = new Loader( this ); - - this.camera = this.DEFAULT_CAMERA.clone(); - - this.scene = new THREE.Scene(); - this.scene.name = 'Scene'; - this.scene.background = new THREE.Color( 0xaaaaaa ); - - this.sceneHelpers = new THREE.Scene(); - - this.object = {}; - this.geometries = {}; - this.materials = {}; - this.textures = {}; - this.scripts = {}; - - this.selected = null; - this.helpers = {}; - - }; - - Editor.prototype = { - - setTheme: function ( value ) { - - document.getElementById( 'theme' ).href = value; - - this.signals.themeChanged.dispatch( value ); - - }, - - // - - setScene: function ( scene ) { - - this.scene.uuid = scene.uuid; - this.scene.name = scene.name; - - if ( scene.background !== null ) this.scene.background = scene.background.clone(); - if ( scene.fog !== null ) this.scene.fog = scene.fog.clone(); - - this.scene.userData = JSON.parse( JSON.stringify( scene.userData ) ); - - // avoid render per object - - this.signals.sceneGraphChanged.active = false; - - while ( scene.children.length > 0 ) { - - this.addObject( scene.children[ 0 ] ); - - } - - this.signals.sceneGraphChanged.active = true; - this.signals.sceneGraphChanged.dispatch(); - - }, - - // - - addObject: function ( object ) { - - var scope = this; - - object.traverse( function ( child ) { - - if ( child.geometry !== undefined ) scope.addGeometry( child.geometry ); - if ( child.material !== undefined ) scope.addMaterial( child.material ); - - scope.addHelper( child ); - - } ); - - this.scene.add( object ); - - this.signals.objectAdded.dispatch( object ); - this.signals.sceneGraphChanged.dispatch(); - - }, - - moveObject: function ( object, parent, before ) { - - if ( parent === undefined ) { - - parent = this.scene; - - } - - parent.add( object ); - - // sort children array - - if ( before !== undefined ) { - - var index = parent.children.indexOf( before ); - parent.children.splice( index, 0, object ); - parent.children.pop(); - - } - - this.signals.sceneGraphChanged.dispatch(); - - }, - - nameObject: function ( object, name ) { - - object.name = name; - this.signals.sceneGraphChanged.dispatch(); - - }, - - removeObject: function ( object ) { - - if ( object.parent === null ) return; // avoid deleting the camera or scene - - var scope = this; - - object.traverse( function ( child ) { - - scope.removeHelper( child ); - - } ); - - object.parent.remove( object ); - - this.signals.objectRemoved.dispatch( object ); - this.signals.sceneGraphChanged.dispatch(); - - }, - - addGeometry: function ( geometry ) { - - this.geometries[ geometry.uuid ] = geometry; - - }, - - setGeometryName: function ( geometry, name ) { - - geometry.name = name; - this.signals.sceneGraphChanged.dispatch(); - - }, - - addMaterial: function ( material ) { - - this.materials[ material.uuid ] = material; - - }, - - setMaterialName: function ( material, name ) { - - material.name = name; - this.signals.sceneGraphChanged.dispatch(); - - }, - - addTexture: function ( texture ) { - - this.textures[ texture.uuid ] = texture; - - }, - - // - - addHelper: function () { - - var geometry = new THREE.SphereBufferGeometry( 2, 4, 2 ); - var material = new THREE.MeshBasicMaterial( { color: 0xff0000, visible: false } ); - - return function ( object ) { - - var helper; - - if ( object instanceof THREE.Camera ) { - - helper = new THREE.CameraHelper( object, 1 ); - - } else if ( object instanceof THREE.PointLight ) { - - helper = new THREE.PointLightHelper( object, 1 ); - - } else if ( object instanceof THREE.DirectionalLight ) { - - helper = new THREE.DirectionalLightHelper( object, 1 ); - - } else if ( object instanceof THREE.SpotLight ) { - - helper = new THREE.SpotLightHelper( object, 1 ); - - } else if ( object instanceof THREE.HemisphereLight ) { - - helper = new THREE.HemisphereLightHelper( object, 1 ); - - } else if ( object instanceof THREE.SkinnedMesh ) { - - helper = new THREE.SkeletonHelper( object ); - - } else { - - // no helper for this object type - return; - - } - - var picker = new THREE.Mesh( geometry, material ); - picker.name = 'picker'; - picker.userData.object = object; - helper.add( picker ); - - this.sceneHelpers.add( helper ); - this.helpers[ object.id ] = helper; - - this.signals.helperAdded.dispatch( helper ); - - }; - - }(), - - removeHelper: function ( object ) { - - if ( this.helpers[ object.id ] !== undefined ) { - - var helper = this.helpers[ object.id ]; - helper.parent.remove( helper ); - - delete this.helpers[ object.id ]; - - this.signals.helperRemoved.dispatch( helper ); - - } - - }, - - // - - addScript: function ( object, script ) { - - if ( this.scripts[ object.uuid ] === undefined ) { - - this.scripts[ object.uuid ] = []; - - } - - this.scripts[ object.uuid ].push( script ); - - this.signals.scriptAdded.dispatch( script ); - - }, - - removeScript: function ( object, script ) { - - if ( this.scripts[ object.uuid ] === undefined ) return; - - var index = this.scripts[ object.uuid ].indexOf( script ); - - if ( index !== - 1 ) { - - this.scripts[ object.uuid ].splice( index, 1 ); - - } - - this.signals.scriptRemoved.dispatch( script ); - - }, - - getObjectMaterial: function ( object, slot ) { - - var material = object.material; - - if ( Array.isArray( material ) ) { - - material = material[ slot ]; - - } - - return material; - - }, - - setObjectMaterial: function ( object, slot, newMaterial ) { - - if ( Array.isArray( object.material ) ) { - - object.material[ slot ] = newMaterial; - - } else { - - object.material = newMaterial; - - } - - }, - - // - - select: function ( object ) { - - if ( this.selected === object ) return; - - var uuid = null; - - if ( object !== null ) { - - uuid = object.uuid; - - } - - this.selected = object; - - this.config.setKey( 'selected', uuid ); - this.signals.objectSelected.dispatch( object ); - - }, - - selectById: function ( id ) { - - if ( id === this.camera.id ) { - - this.select( this.camera ); - return; - - } - - this.select( this.scene.getObjectById( id, true ) ); - - }, - - selectByUuid: function ( uuid ) { - - var scope = this; - - this.scene.traverse( function ( child ) { - - if ( child.uuid === uuid ) { - - scope.select( child ); - - } - - } ); - - }, - - deselect: function () { - - this.select( null ); - - }, - - focus: function ( object ) { - - this.signals.objectFocused.dispatch( object ); - - }, - - focusById: function ( id ) { - - this.focus( this.scene.getObjectById( id, true ) ); - - }, - - clear: function () { - - this.history.clear(); - this.storage.clear(); - - this.camera.copy( this.DEFAULT_CAMERA ); - this.scene.background.setHex( 0xaaaaaa ); - this.scene.fog = null; - - var objects = this.scene.children; - - while ( objects.length > 0 ) { - - this.removeObject( objects[ 0 ] ); - - } - - this.geometries = {}; - this.materials = {}; - this.textures = {}; - this.scripts = {}; - - this.deselect(); - - this.signals.editorCleared.dispatch(); - - }, - - // - - fromJSON: function ( json ) { - - var loader = new THREE.ObjectLoader(); - - // backwards - - if ( json.scene === undefined ) { - - this.setScene( loader.parse( json ) ); - return; - - } - - var camera = loader.parse( json.camera ); - - this.camera.copy( camera ); - this.camera.aspect = this.DEFAULT_CAMERA.aspect; - this.camera.updateProjectionMatrix(); - - this.history.fromJSON( json.history ); - this.scripts = json.scripts; - - this.setScene( loader.parse( json.scene ) ); - - }, - - toJSON: function () { - - // scripts clean up - - var scene = this.scene; - var scripts = this.scripts; - - for ( var key in scripts ) { - - var script = scripts[ key ]; - - if ( script.length === 0 || scene.getObjectByProperty( 'uuid', key ) === undefined ) { - - delete scripts[ key ]; - - } - - } - - // - - return { - - metadata: {}, - project: { - gammaInput: this.config.getKey( 'project/renderer/gammaInput' ), - gammaOutput: this.config.getKey( 'project/renderer/gammaOutput' ), - shadows: this.config.getKey( 'project/renderer/shadows' ), - vr: this.config.getKey( 'project/vr' ) - }, - camera: this.camera.toJSON(), - scene: this.scene.toJSON(), - scripts: this.scripts, - history: this.history.toJSON() - - }; - - }, - - objectByUuid: function ( uuid ) { - - return this.scene.getObjectByProperty( 'uuid', uuid, true ); - - }, - - execute: function ( cmd, optionalName ) { - - this.history.execute( cmd, optionalName ); - - }, - - undo: function () { - - this.history.undo(); - - }, - - redo: function () { - - this.history.redo(); - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Editor', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author dforrer / https://github.com/dforrer - * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch) - */ - - History = function ( editor ) { - - this.editor = editor; - this.undos = []; - this.redos = []; - this.lastCmdTime = new Date(); - this.idCounter = 0; - - this.historyDisabled = false; - this.config = editor.config; - - //Set editor-reference in Command - - Command( editor ); - - // signals - - var scope = this; - - this.editor.signals.startPlayer.add( function () { - - scope.historyDisabled = true; - - } ); - - this.editor.signals.stopPlayer.add( function () { - - scope.historyDisabled = false; - - } ); - - }; - - History.prototype = { - - execute: function ( cmd, optionalName ) { - - var lastCmd = this.undos[ this.undos.length - 1 ]; - var timeDifference = new Date().getTime() - this.lastCmdTime.getTime(); - - var isUpdatableCmd = lastCmd && - lastCmd.updatable && - cmd.updatable && - lastCmd.object === cmd.object && - lastCmd.type === cmd.type && - lastCmd.script === cmd.script && - lastCmd.attributeName === cmd.attributeName; - - if ( isUpdatableCmd && cmd.type === "SetScriptValueCommand" ) { - - // When the cmd.type is "SetScriptValueCommand" the timeDifference is ignored - - lastCmd.update( cmd ); - cmd = lastCmd; - - } else if ( isUpdatableCmd && timeDifference < 500 ) { - - lastCmd.update( cmd ); - cmd = lastCmd; - - } else { - - // the command is not updatable and is added as a new part of the history - - this.undos.push( cmd ); - cmd.id = ++ this.idCounter; - - } - cmd.name = ( optionalName !== undefined ) ? optionalName : cmd.name; - cmd.execute(); - cmd.inMemory = true; - - if ( this.config.getKey( 'settings/history' ) ) { - - cmd.json = cmd.toJSON(); // serialize the cmd immediately after execution and append the json to the cmd - - } - this.lastCmdTime = new Date(); - - // clearing all the redo-commands - - this.redos = []; - this.editor.signals.historyChanged.dispatch( cmd ); - - }, - - undo: function () { - - if ( this.historyDisabled ) { - - alert( "Undo/Redo disabled while scene is playing." ); - return; - - } - - var cmd = undefined; - - if ( this.undos.length > 0 ) { - - cmd = this.undos.pop(); - - if ( cmd.inMemory === false ) { - - cmd.fromJSON( cmd.json ); - - } - - } - - if ( cmd !== undefined ) { - - cmd.undo(); - this.redos.push( cmd ); - this.editor.signals.historyChanged.dispatch( cmd ); - - } - - return cmd; - - }, - - redo: function () { - - if ( this.historyDisabled ) { - - alert( "Undo/Redo disabled while scene is playing." ); - return; - - } - - var cmd = undefined; - - if ( this.redos.length > 0 ) { - - cmd = this.redos.pop(); - - if ( cmd.inMemory === false ) { - - cmd.fromJSON( cmd.json ); - - } - - } - - if ( cmd !== undefined ) { - - cmd.execute(); - this.undos.push( cmd ); - this.editor.signals.historyChanged.dispatch( cmd ); - - } - - return cmd; - - }, - - toJSON: function () { - - var history = {}; - history.undos = []; - history.redos = []; - - if ( ! this.config.getKey( 'settings/history' ) ) { - - return history; - - } - - // Append Undos to History - - for ( var i = 0 ; i < this.undos.length; i ++ ) { - - if ( this.undos[ i ].hasOwnProperty( "json" ) ) { - - history.undos.push( this.undos[ i ].json ); - - } - - } - - // Append Redos to History - - for ( var i = 0 ; i < this.redos.length; i ++ ) { - - if ( this.redos[ i ].hasOwnProperty( "json" ) ) { - - history.redos.push( this.redos[ i ].json ); - - } - - } - - return history; - - }, - - fromJSON: function ( json ) { - - if ( json === undefined ) return; - - for ( var i = 0; i < json.undos.length; i ++ ) { - - var cmdJSON = json.undos[ i ]; - var cmd = new window[ cmdJSON.type ](); // creates a new object of type "json.type" - cmd.json = cmdJSON; - cmd.id = cmdJSON.id; - cmd.name = cmdJSON.name; - this.undos.push( cmd ); - this.idCounter = ( cmdJSON.id > this.idCounter ) ? cmdJSON.id : this.idCounter; // set last used idCounter - - } - - for ( var i = 0; i < json.redos.length; i ++ ) { - - var cmdJSON = json.redos[ i ]; - var cmd = new window[ cmdJSON.type ](); // creates a new object of type "json.type" - cmd.json = cmdJSON; - cmd.id = cmdJSON.id; - cmd.name = cmdJSON.name; - this.redos.push( cmd ); - this.idCounter = ( cmdJSON.id > this.idCounter ) ? cmdJSON.id : this.idCounter; // set last used idCounter - - } - - // Select the last executed undo-command - this.editor.signals.historyChanged.dispatch( this.undos[ this.undos.length - 1 ] ); - - }, - - clear: function () { - - this.undos = []; - this.redos = []; - this.idCounter = 0; - - this.editor.signals.historyChanged.dispatch(); - - }, - - goToState: function ( id ) { - - if ( this.historyDisabled ) { - - alert( "Undo/Redo disabled while scene is playing." ); - return; - - } - - this.editor.signals.sceneGraphChanged.active = false; - this.editor.signals.historyChanged.active = false; - - var cmd = this.undos.length > 0 ? this.undos[ this.undos.length - 1 ] : undefined; // next cmd to pop - - if ( cmd === undefined || id > cmd.id ) { - - cmd = this.redo(); - while ( cmd !== undefined && id > cmd.id ) { - - cmd = this.redo(); - - } - - } else { - - while ( true ) { - - cmd = this.undos[ this.undos.length - 1 ]; // next cmd to pop - - if ( cmd === undefined || id === cmd.id ) break; - - this.undo(); - - } - - } - - this.editor.signals.sceneGraphChanged.active = true; - this.editor.signals.historyChanged.active = true; - - this.editor.signals.sceneGraphChanged.dispatch(); - this.editor.signals.historyChanged.dispatch( cmd ); - - }, - - enableSerialization: function ( id ) { - - /** - * because there might be commands in this.undos and this.redos - * which have not been serialized with .toJSON() we go back - * to the oldest command and redo one command after the other - * while also calling .toJSON() on them. - */ - - this.goToState( - 1 ); - - this.editor.signals.sceneGraphChanged.active = false; - this.editor.signals.historyChanged.active = false; - - var cmd = this.redo(); - while ( cmd !== undefined ) { - - if ( ! cmd.hasOwnProperty( "json" ) ) { - - cmd.json = cmd.toJSON(); - - } - cmd = this.redo(); - - } - - this.editor.signals.sceneGraphChanged.active = true; - this.editor.signals.historyChanged.active = true; - - this.goToState( id ); - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'History', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Loader', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Player', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Script', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Menubar', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Menubar.Add = function ( editor ) { - - var container = new UI.Panel(); - container.setClass( 'menu' ); - - var title = new UI.Panel(); - title.setClass( 'title' ); - title.setTextContent( 'Add' ); - container.add( title ); - - var options = new UI.Panel(); - options.setClass( 'options' ); - container.add( options ); - - // - - var meshCount = 0; - var lightCount = 0; - var cameraCount = 0; - - editor.signals.editorCleared.add( function () { - - meshCount = 0; - lightCount = 0; - cameraCount = 0; - - } ); - - // Group - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Group' ); - option.onClick( function () { - - var mesh = new THREE.Group(); - mesh.name = 'Group ' + ( ++ meshCount ); - - editor.execute( new AddObjectCommand( mesh ) ); - - } ); - options.add( option ); - - // - - options.add( new UI.HorizontalRule() ); - - // Plane - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Plane' ); - option.onClick( function () { - - var geometry = new THREE.PlaneBufferGeometry( 1, 1, 1, 1 ); - var material = new THREE.MeshStandardMaterial(); - var mesh = new THREE.Mesh( geometry, material ); - mesh.name = 'Plane ' + ( ++ meshCount ); - - editor.execute( new AddObjectCommand( mesh ) ); - - } ); - options.add( option ); - - // Box - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Box' ); - option.onClick( function () { - - var geometry = new THREE.BoxBufferGeometry( 1, 1, 1, 1, 1, 1 ); - var mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() ); - mesh.name = 'Box ' + ( ++ meshCount ); - - editor.execute( new AddObjectCommand( mesh ) ); - - } ); - options.add( option ); - - // Circle - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Circle' ); - option.onClick( function () { - - var geometry = new THREE.CircleBufferGeometry( 1, 8, 0, Math.PI * 2 ); - var mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() ); - mesh.name = 'Circle ' + ( ++ meshCount ); - - editor.execute( new AddObjectCommand( mesh ) ); - - } ); - options.add( option ); - - // Cylinder - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Cylinder' ); - option.onClick( function () { - - var geometry = new THREE.CylinderBufferGeometry( 1, 1, 1, 8, 1, false, 0, Math.PI * 2 ); - var mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() ); - mesh.name = 'Cylinder ' + ( ++ meshCount ); - - editor.execute( new AddObjectCommand( mesh ) ); - - } ); - options.add( option ); - - // Sphere - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Sphere' ); - option.onClick( function () { - - var geometry = new THREE.SphereBufferGeometry( 1, 8, 6, 0, Math.PI * 2, 0, Math.PI ); - var mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() ); - mesh.name = 'Sphere ' + ( ++ meshCount ); - - editor.execute( new AddObjectCommand( mesh ) ); - - } ); - options.add( option ); - - // Icosahedron - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Icosahedron' ); - option.onClick( function () { - - var geometry = new THREE.IcosahedronGeometry( 1, 0 ); - var mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() ); - mesh.name = 'Icosahedron ' + ( ++ meshCount ); - - editor.execute( new AddObjectCommand( mesh ) ); - - } ); - options.add( option ); - - // Torus - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Torus' ); - option.onClick( function () { - - var geometry = new THREE.TorusBufferGeometry( 1, 0.4, 8, 6, Math.PI * 2 ); - var mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() ); - mesh.name = 'Torus ' + ( ++ meshCount ); - - editor.execute( new AddObjectCommand( mesh ) ); - - } ); - options.add( option ); - - // TorusKnot - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'TorusKnot' ); - option.onClick( function () { - - var geometry = new THREE.TorusKnotBufferGeometry( 1, 0.4, 64, 8, 2, 3 ); - var mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() ); - mesh.name = 'TorusKnot ' + ( ++ meshCount ); - - editor.execute( new AddObjectCommand( mesh ) ); - - } ); - options.add( option ); - - /* - // Teapot - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Teapot' ); - option.onClick( function () { - - var size = 50; - var segments = 10; - var bottom = true; - var lid = true; - var body = true; - var fitLid = false; - var blinnScale = true; - - var material = new THREE.MeshStandardMaterial(); - - var geometry = new THREE.TeapotBufferGeometry( size, segments, bottom, lid, body, fitLid, blinnScale ); - var mesh = new THREE.Mesh( geometry, material ); - mesh.name = 'Teapot ' + ( ++ meshCount ); - - editor.addObject( mesh ); - editor.select( mesh ); - - } ); - options.add( option ); - */ - - // Lathe - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Lathe' ); - option.onClick( function() { - - var points = [ - new THREE.Vector2( 0, 0 ), - new THREE.Vector2( 0.4, 0 ), - new THREE.Vector2( 0.35, 0.05 ), - new THREE.Vector2( 0.1, 0.075 ), - new THREE.Vector2( 0.08, 0.1 ), - new THREE.Vector2( 0.08, 0.4 ), - new THREE.Vector2( 0.1, 0.42 ), - new THREE.Vector2( 0.14, 0.48 ), - new THREE.Vector2( 0.2, 0.5 ), - new THREE.Vector2( 0.25, 0.54 ), - new THREE.Vector2( 0.3, 1.2 ) - ]; - - var geometry = new THREE.LatheBufferGeometry( points, 12, 0, Math.PI * 2 ); - var mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial( { side: THREE.DoubleSide } ) ); - mesh.name = 'Lathe ' + ( ++ meshCount ); - - editor.execute( new AddObjectCommand( mesh ) ); - - } ); - options.add( option ); - - // Sprite - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Sprite' ); - option.onClick( function () { - - var sprite = new THREE.Sprite( new THREE.SpriteMaterial() ); - sprite.name = 'Sprite ' + ( ++ meshCount ); - - editor.execute( new AddObjectCommand( sprite ) ); - - } ); - options.add( option ); - - // - - options.add( new UI.HorizontalRule() ); - - // PointLight - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'PointLight' ); - option.onClick( function () { - - var color = 0xffffff; - var intensity = 1; - var distance = 0; - - var light = new THREE.PointLight( color, intensity, distance ); - light.name = 'PointLight ' + ( ++ lightCount ); - - editor.execute( new AddObjectCommand( light ) ); - - } ); - options.add( option ); - - // SpotLight - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'SpotLight' ); - option.onClick( function () { - - var color = 0xffffff; - var intensity = 1; - var distance = 0; - var angle = Math.PI * 0.1; - var penumbra = 0; - - var light = new THREE.SpotLight( color, intensity, distance, angle, penumbra ); - light.name = 'SpotLight ' + ( ++ lightCount ); - light.target.name = 'SpotLight ' + ( lightCount ) + ' Target'; - - light.position.set( 5, 10, 7.5 ); - - editor.execute( new AddObjectCommand( light ) ); - - } ); - options.add( option ); - - // DirectionalLight - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'DirectionalLight' ); - option.onClick( function () { - - var color = 0xffffff; - var intensity = 1; - - var light = new THREE.DirectionalLight( color, intensity ); - light.name = 'DirectionalLight ' + ( ++ lightCount ); - light.target.name = 'DirectionalLight ' + ( lightCount ) + ' Target'; - - light.position.set( 5, 10, 7.5 ); - - editor.execute( new AddObjectCommand( light ) ); - - } ); - options.add( option ); - - // HemisphereLight - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'HemisphereLight' ); - option.onClick( function () { - - var skyColor = 0x00aaff; - var groundColor = 0xffaa00; - var intensity = 1; - - var light = new THREE.HemisphereLight( skyColor, groundColor, intensity ); - light.name = 'HemisphereLight ' + ( ++ lightCount ); - - light.position.set( 0, 10, 0 ); - - editor.execute( new AddObjectCommand( light ) ); - - } ); - options.add( option ); - - // AmbientLight - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'AmbientLight' ); - option.onClick( function() { - - var color = 0x222222; - - var light = new THREE.AmbientLight( color ); - light.name = 'AmbientLight ' + ( ++ lightCount ); - - editor.execute( new AddObjectCommand( light ) ); - - } ); - options.add( option ); - - // - - options.add( new UI.HorizontalRule() ); - - // PerspectiveCamera - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'PerspectiveCamera' ); - option.onClick( function() { - - var camera = new THREE.PerspectiveCamera( 50, 1, 1, 10000 ); - camera.name = 'PerspectiveCamera ' + ( ++ cameraCount ); - - editor.execute( new AddObjectCommand( camera ) ); - - } ); - options.add( option ); - - return container; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Menubar.Add', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Menubar.Edit = function ( editor ) { - - var container = new UI.Panel(); - container.setClass( 'menu' ); - - var title = new UI.Panel(); - title.setClass( 'title' ); - title.setTextContent( 'Edit' ); - container.add( title ); - - var options = new UI.Panel(); - options.setClass( 'options' ); - container.add( options ); - - // Undo - - var undo = new UI.Row(); - undo.setClass( 'option' ); - undo.setTextContent( 'Undo (Ctrl+Z)' ); - undo.onClick( function () { - - editor.undo(); - - } ); - options.add( undo ); - - // Redo - - var redo = new UI.Row(); - redo.setClass( 'option' ); - redo.setTextContent( 'Redo (Ctrl+Shift+Z)' ); - redo.onClick( function () { - - editor.redo(); - - } ); - options.add( redo ); - - // Clear History - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Clear History' ); - option.onClick( function () { - - if ( confirm( 'The Undo/Redo History will be cleared. Are you sure?' ) ) { - - editor.history.clear(); - - } - - } ); - options.add( option ); - - - editor.signals.historyChanged.add( function () { - - var history = editor.history; - - undo.setClass( 'option' ); - redo.setClass( 'option' ); - - if ( history.undos.length == 0 ) { - - undo.setClass( 'inactive' ); - - } - - if ( history.redos.length == 0 ) { - - redo.setClass( 'inactive' ); - - } - - } ); - - // --- - - options.add( new UI.HorizontalRule() ); - - // Clone - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Clone' ); - option.onClick( function () { - - var object = editor.selected; - - if ( object.parent === null ) return; // avoid cloning the camera or scene - - object = object.clone(); - - editor.execute( new AddObjectCommand( object ) ); - - } ); - options.add( option ); - - // Delete - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Delete (Del)' ); - option.onClick( function () { - - var object = editor.selected; - - if ( confirm( 'Delete ' + object.name + '?' ) === false ) return; - - var parent = object.parent; - if ( parent === undefined ) return; // avoid deleting the camera or scene - - editor.execute( new RemoveObjectCommand( object ) ); - - } ); - options.add( option ); - - // Minify shaders - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Minify Shaders' ); - option.onClick( function() { - - var root = editor.selected || editor.scene; - - var errors = []; - var nMaterialsChanged = 0; - - var path = []; - - function getPath ( object ) { - - path.length = 0; - - var parent = object.parent; - if ( parent !== undefined ) getPath( parent ); - - path.push( object.name || object.uuid ); - - return path; - - } - - var cmds = []; - root.traverse( function ( object ) { - - var material = object.material; - - if ( material instanceof THREE.ShaderMaterial ) { - - try { - - var shader = glslprep.minifyGlsl( [ - material.vertexShader, material.fragmentShader ] ); - - cmds.push( new SetMaterialValueCommand( object, 'vertexShader', shader[ 0 ] ) ); - cmds.push( new SetMaterialValueCommand( object, 'fragmentShader', shader[ 1 ] ) ); - - ++nMaterialsChanged; - - } catch ( e ) { - - var path = getPath( object ).join( "/" ); - - if ( e instanceof glslprep.SyntaxError ) - - errors.push( path + ":" + - e.line + ":" + e.column + ": " + e.message ); - - else { - - errors.push( path + - ": Unexpected error (see console for details)." ); - - console.error( e.stack || e ); - - } - - } - - } - - } ); - - if ( nMaterialsChanged > 0 ) { - - editor.execute( new MultiCmdsCommand( cmds ), 'Minify Shaders' ); - - } - - window.alert( nMaterialsChanged + - " material(s) were changed.\n" + errors.join( "\n" ) ); - - } ); - options.add( option ); - - - return container; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Menubar.Edit', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Menubar.Examples = function ( editor ) { - - var container = new UI.Panel(); - container.setClass( 'menu' ); - - var title = new UI.Panel(); - title.setClass( 'title' ); - title.setTextContent( 'Examples' ); - container.add( title ); - - var options = new UI.Panel(); - options.setClass( 'options' ); - container.add( options ); - - // Examples - - var items = [ - { title: 'Arkanoid', file: 'arkanoid.app.json' }, - { title: 'Camera', file: 'camera.app.json' }, - { title: 'Particles', file: 'particles.app.json' }, - { title: 'Pong', file: 'pong.app.json' }, - { title: 'Shaders', file: 'shaders.app.json' } - ]; - - var loader = new THREE.FileLoader(); - - for ( var i = 0; i < items.length; i ++ ) { - - ( function ( i ) { - - var item = items[ i ]; - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( item.title ); - option.onClick( function () { - - if ( confirm( 'Any unsaved data will be lost. Are you sure?' ) ) { - - loader.load( 'examples/' + item.file, function ( text ) { - - editor.clear(); - editor.fromJSON( JSON.parse( text ) ); - - } ); - - } - - } ); - options.add( option ); - - } )( i ); - - } - - return container; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Menubar.Examples', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Menubar.File = function ( editor ) { - - var NUMBER_PRECISION = 6; - - function parseNumber( key, value ) { - - return typeof value === 'number' ? parseFloat( value.toFixed( NUMBER_PRECISION ) ) : value; - - } - - // - - var container = new UI.Panel(); - container.setClass( 'menu' ); - - var title = new UI.Panel(); - title.setClass( 'title' ); - title.setTextContent( 'File' ); - container.add( title ); - - var options = new UI.Panel(); - options.setClass( 'options' ); - container.add( options ); - - // New - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'New' ); - option.onClick( function () { - - if ( confirm( 'Any unsaved data will be lost. Are you sure?' ) ) { - - editor.clear(); - - } - - } ); - options.add( option ); - - // - - options.add( new UI.HorizontalRule() ); - - // Import - - var form = document.createElement( 'form' ); - form.style.display = 'none'; - document.body.appendChild( form ); - - var fileInput = document.createElement( 'input' ); - fileInput.type = 'file'; - fileInput.addEventListener( 'change', function ( event ) { - - editor.loader.loadFile( fileInput.files[ 0 ] ); - form.reset(); - - } ); - form.appendChild( fileInput ); - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Import' ); - option.onClick( function () { - - fileInput.click(); - - } ); - options.add( option ); - - // - - options.add( new UI.HorizontalRule() ); - - // Export Geometry - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Export Geometry' ); - option.onClick( function () { - - var object = editor.selected; - - if ( object === null ) { - - alert( 'No object selected.' ); - return; - - } - - var geometry = object.geometry; - - if ( geometry === undefined ) { - - alert( 'The selected object doesn\'t have geometry.' ); - return; - - } - - var output = geometry.toJSON(); - - try { - - output = JSON.stringify( output, parseNumber, '\t' ); - output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' ); - - } catch ( e ) { - - output = JSON.stringify( output ); - - } - - saveString( output, 'geometry.json' ); - - } ); - options.add( option ); - - // Export Object - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Export Object' ); - option.onClick( function () { - - var object = editor.selected; - - if ( object === null ) { - - alert( 'No object selected' ); - return; - - } - - var output = object.toJSON(); - - try { - - output = JSON.stringify( output, parseNumber, '\t' ); - output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' ); - - } catch ( e ) { - - output = JSON.stringify( output ); - - } - - saveString( output, 'model.json' ); - - } ); - options.add( option ); - - // Export Scene - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Export Scene' ); - option.onClick( function () { - - var output = editor.scene.toJSON(); - - try { - - output = JSON.stringify( output, parseNumber, '\t' ); - output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' ); - - } catch ( e ) { - - output = JSON.stringify( output ); - - } - - saveString( output, 'scene.json' ); - - } ); - options.add( option ); - - // - - options.add( new UI.HorizontalRule() ); - - // Export GLTF - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Export GLTF' ); - option.onClick( function () { - - var exporter = new THREE.GLTFExporter(); - - exporter.parse( editor.scene, function ( result ) { - - saveString( JSON.stringify( result, null, 2 ), 'scene.gltf' ); - - } ); - - - } ); - options.add( option ); - - // Export OBJ - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Export OBJ' ); - option.onClick( function () { - - var object = editor.selected; - - if ( object === null ) { - - alert( 'No object selected.' ); - return; - - } - - var exporter = new THREE.OBJExporter(); - - saveString( exporter.parse( object ), 'model.obj' ); - - } ); - options.add( option ); - - // Export STL - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Export STL' ); - option.onClick( function () { - - var exporter = new THREE.STLExporter(); - - saveString( exporter.parse( editor.scene ), 'model.stl' ); - - } ); - options.add( option ); - - // - - options.add( new UI.HorizontalRule() ); - - // Publish - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Publish' ); - option.onClick( function () { - - var zip = new JSZip(); - - // - - var output = editor.toJSON(); - output.metadata.type = 'App'; - delete output.history; - - var vr = output.project.vr; - - output = JSON.stringify( output, parseNumber, '\t' ); - output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' ); - - zip.file( 'app.json', output ); - - // - - var manager = new THREE.LoadingManager( function () { - - save( zip.generate( { type: 'blob' } ), 'download.zip' ); - - } ); - - var loader = new THREE.FileLoader( manager ); - loader.load( 'js/libs/app/index.html', function ( content ) { - - var includes = []; - - if ( vr ) { - - includes.push( '' ); - - } - - content = content.replace( '', includes.join( '\n\t\t' ) ); - - var editButton = ''; - - if ( editor.config.getKey( 'project/editable' ) ) { - - editButton = ` - var button = document.createElement( 'a' ); - button.href = 'https://threejs.org/editor/#file=' + location.href.split( '/' ).slice( 0, - 1 ).join( '/' ) + '/app.json'; - button.style.cssText = 'position: absolute; bottom: 20px; right: 20px; padding: 7px 10px 6px 10px; color: #fff; border: 1px solid #fff; text-decoration: none;'; - button.target = '_blank'; - button.textContent = 'EDIT'; - document.body.appendChild( button ); - `; - - } - - content = content.replace( '/* edit button */', editButton ); - - zip.file( 'index.html', content ); - - } ); - loader.load( 'js/libs/app.js', function ( content ) { - - zip.file( 'js/app.js', content ); - - } ); - loader.load( '../build/three.min.js', function ( content ) { - - zip.file( 'js/three.min.js', content ); - - } ); - - if ( vr ) { - - loader.load( '../examples/js/vr/WebVR.js', function ( content ) { - - zip.file( 'js/WebVR.js', content ); - - } ); - - } - - } ); - options.add( option ); - - /* - // Publish (Dropbox) - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Publish (Dropbox)' ); - option.onClick( function () { - - var parameters = { - files: [ - { 'url': 'data:text/plain;base64,' + window.btoa( "Hello, World" ), 'filename': 'app/test.txt' } - ] - }; - - Dropbox.save( parameters ); - - } ); - options.add( option ); - */ - - - // - - var link = document.createElement( 'a' ); - link.style.display = 'none'; - document.body.appendChild( link ); // Firefox workaround, see #6594 - - function save( blob, filename ) { - - link.href = URL.createObjectURL( blob ); - link.download = filename || 'data.json'; - link.click(); - - // URL.revokeObjectURL( url ); breaks Firefox... - - } - - function saveString( text, filename ) { - - save( new Blob( [ text ], { type: 'text/plain' } ), filename ); - - } - - return container; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Menubar.File', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Menubar.Help = function ( editor ) { - - var container = new UI.Panel(); - container.setClass( 'menu' ); - - var title = new UI.Panel(); - title.setClass( 'title' ); - title.setTextContent( 'Help' ); - container.add( title ); - - var options = new UI.Panel(); - options.setClass( 'options' ); - container.add( options ); - - // Source code - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'Source code' ); - option.onClick( function () { - - window.open( 'https://github.com/mrdoob/three.js/tree/master/editor', '_blank' ); - - } ); - options.add( option ); - - // About - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'About' ); - option.onClick( function () { - - window.open( 'http://threejs.org', '_blank' ); - - } ); - options.add( option ); - - return container; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Menubar.Help', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Menubar.Play = function ( editor ) { - - var signals = editor.signals; - - var container = new UI.Panel(); - container.setClass( 'menu' ); - - var isPlaying = false; - - var title = new UI.Panel(); - title.setClass( 'title' ); - title.setTextContent( 'Play' ); - title.onClick( function () { - - if ( isPlaying === false ) { - - isPlaying = true; - title.setTextContent( 'Stop' ); - signals.startPlayer.dispatch(); - - } else { - - isPlaying = false; - title.setTextContent( 'Play' ); - signals.stopPlayer.dispatch(); - - } - - } ); - container.add( title ); - - return container; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Menubar.Play', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Menubar.Status = function ( editor ) { - - var container = new UI.Panel(); - container.setClass( 'menu right' ); - - var autosave = new UI.THREE.Boolean( editor.config.getKey( 'autosave' ), 'autosave' ); - autosave.text.setColor( '#888' ); - autosave.onChange( function () { - - var value = this.getValue(); - - editor.config.setKey( 'autosave', value ); - - if ( value === true ) { - - editor.signals.sceneGraphChanged.dispatch(); - - } - - } ); - container.add( autosave ); - - editor.signals.savingStarted.add( function () { - - autosave.text.setTextDecoration( 'underline' ); - - } ); - - editor.signals.savingFinished.add( function () { - - autosave.text.setTextDecoration( 'none' ); - - } ); - - var version = new UI.Text( 'r' + THREE.REVISION ); - version.setClass( 'title' ); - version.setOpacity( 0.5 ); - container.add( version ); - - return container; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Menubar.Status', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Menubar.View = function ( editor ) { - - var container = new UI.Panel(); - container.setClass( 'menu' ); - - var title = new UI.Panel(); - title.setClass( 'title' ); - title.setTextContent( 'View' ); - container.add( title ); - - var options = new UI.Panel(); - options.setClass( 'options' ); - container.add( options ); - - // VR mode - - var option = new UI.Row(); - option.setClass( 'option' ); - option.setTextContent( 'VR mode' ); - option.onClick( function () { - - if ( WEBVR.isAvailable() === true ) { - - editor.signals.enterVR.dispatch(); - - } else { - - alert( 'WebVR not available' ); - - } - - } ); - options.add( option ); - - return container; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Menubar.View', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Sidebar.Animation = function ( editor ) { - - var signals = editor.signals; - - var options = {}; - var possibleAnimations = {}; - - var container = new UI.Panel(); - container.setDisplay( 'none' ); - - container.add( new UI.Text( 'Animation' ).setTextTransform( 'uppercase' ) ); - container.add( new UI.Break() ); - container.add( new UI.Break() ); - - var animationsRow = new UI.Row(); - container.add( animationsRow ); - - return container; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar.Animation', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Sidebar.Geometry = function ( editor ) { - - var signals = editor.signals; - - var container = new UI.Panel(); - container.setBorderTop( '0' ); - container.setPaddingTop( '20px' ); - - // Actions - - /* - var objectActions = new UI.Select().setPosition( 'absolute' ).setRight( '8px' ).setFontSize( '11px' ); - objectActions.setOptions( { - - 'Actions': 'Actions', - 'Center': 'Center', - 'Convert': 'Convert', - 'Flatten': 'Flatten' - - } ); - objectActions.onClick( function ( event ) { - - event.stopPropagation(); // Avoid panel collapsing - - } ); - objectActions.onChange( function ( event ) { - - var action = this.getValue(); - - var object = editor.selected; - var geometry = object.geometry; - - if ( confirm( action + ' ' + object.name + '?' ) === false ) return; - - switch ( action ) { - - case 'Center': - - var offset = geometry.center(); - - var newPosition = object.position.clone(); - newPosition.sub( offset ); - editor.execute( new SetPositionCommand( object, newPosition ) ); - - editor.signals.geometryChanged.dispatch( object ); - - break; - - case 'Convert': - - if ( geometry instanceof THREE.Geometry ) { - - editor.execute( new SetGeometryCommand( object, new THREE.BufferGeometry().fromGeometry( geometry ) ) ); - - } - - break; - - case 'Flatten': - - var newGeometry = geometry.clone(); - newGeometry.uuid = geometry.uuid; - newGeometry.applyMatrix( object.matrix ); - - var cmds = [ new SetGeometryCommand( object, newGeometry ), - new SetPositionCommand( object, new THREE.Vector3( 0, 0, 0 ) ), - new SetRotationCommand( object, new THREE.Euler( 0, 0, 0 ) ), - new SetScaleCommand( object, new THREE.Vector3( 1, 1, 1 ) ) ]; - - editor.execute( new MultiCmdsCommand( cmds ), 'Flatten Geometry' ); - - break; - - } - - this.setValue( 'Actions' ); - - } ); - container.addStatic( objectActions ); - */ - - // type - - var geometryTypeRow = new UI.Row(); - var geometryType = new UI.Text(); - - geometryTypeRow.add( new UI.Text( 'Type' ).setWidth( '90px' ) ); - geometryTypeRow.add( geometryType ); - - container.add( geometryTypeRow ); - - // uuid - - var geometryUUIDRow = new UI.Row(); - var geometryUUID = new UI.Input().setWidth( '102px' ).setFontSize( '12px' ).setDisabled( true ); - var geometryUUIDRenew = new UI.Button( 'New' ).setMarginLeft( '7px' ).onClick( function () { - - geometryUUID.setValue( THREE.Math.generateUUID() ); - - editor.execute( new SetGeometryValueCommand( editor.selected, 'uuid', geometryUUID.getValue() ) ); - - } ); - - geometryUUIDRow.add( new UI.Text( 'UUID' ).setWidth( '90px' ) ); - geometryUUIDRow.add( geometryUUID ); - geometryUUIDRow.add( geometryUUIDRenew ); - - container.add( geometryUUIDRow ); - - // name - - var geometryNameRow = new UI.Row(); - var geometryName = new UI.Input().setWidth( '150px' ).setFontSize( '12px' ).onChange( function () { - - editor.execute( new SetGeometryValueCommand( editor.selected, 'name', geometryName.getValue() ) ); - - } ); - - geometryNameRow.add( new UI.Text( 'Name' ).setWidth( '90px' ) ); - geometryNameRow.add( geometryName ); - - container.add( geometryNameRow ); - - // geometry - - container.add( new Sidebar.Geometry.Geometry( editor ) ); - - // buffergeometry - - container.add( new Sidebar.Geometry.BufferGeometry( editor ) ); - - // parameters - - var parameters = new UI.Span(); - container.add( parameters ); - - - // - - function build() { - - var object = editor.selected; - - if ( object && object.geometry ) { - - var geometry = object.geometry; - - container.setDisplay( 'block' ); - - geometryType.setValue( geometry.type ); - - geometryUUID.setValue( geometry.uuid ); - geometryName.setValue( geometry.name ); - - // - - parameters.clear(); - - if ( geometry.type === 'BufferGeometry' || geometry.type === 'Geometry' ) { - - parameters.add( new Sidebar.Geometry.Modifiers( editor, object ) ); - - } else if ( Sidebar.Geometry[ geometry.type ] !== undefined ) { - - parameters.add( new Sidebar.Geometry[ geometry.type ]( editor, object ) ); - - } - - } else { - - container.setDisplay( 'none' ); - - } - - } - - signals.objectSelected.add( build ); - signals.geometryChanged.add( build ); - - return container; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar.Geometry', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Sidebar.Geometry.BoxGeometry = function ( editor, object ) { - - var signals = editor.signals; - - var container = new UI.Row(); - - var geometry = object.geometry; - var parameters = geometry.parameters; - - // width - - var widthRow = new UI.Row(); - var width = new UI.Number( parameters.width ).onChange( update ); - - widthRow.add( new UI.Text( 'Width' ).setWidth( '90px' ) ); - widthRow.add( width ); - - container.add( widthRow ); - - // height - - var heightRow = new UI.Row(); - var height = new UI.Number( parameters.height ).onChange( update ); - - heightRow.add( new UI.Text( 'Height' ).setWidth( '90px' ) ); - heightRow.add( height ); - - container.add( heightRow ); - - // depth - - var depthRow = new UI.Row(); - var depth = new UI.Number( parameters.depth ).onChange( update ); - - depthRow.add( new UI.Text( 'Depth' ).setWidth( '90px' ) ); - depthRow.add( depth ); - - container.add( depthRow ); - - // widthSegments - - var widthSegmentsRow = new UI.Row(); - var widthSegments = new UI.Integer( parameters.widthSegments ).setRange( 1, Infinity ).onChange( update ); - - widthSegmentsRow.add( new UI.Text( 'Width segments' ).setWidth( '90px' ) ); - widthSegmentsRow.add( widthSegments ); - - container.add( widthSegmentsRow ); - - // heightSegments - - var heightSegmentsRow = new UI.Row(); - var heightSegments = new UI.Integer( parameters.heightSegments ).setRange( 1, Infinity ).onChange( update ); - - heightSegmentsRow.add( new UI.Text( 'Height segments' ).setWidth( '90px' ) ); - heightSegmentsRow.add( heightSegments ); - - container.add( heightSegmentsRow ); - - // depthSegments - - var depthSegmentsRow = new UI.Row(); - var depthSegments = new UI.Integer( parameters.depthSegments ).setRange( 1, Infinity ).onChange( update ); - - depthSegmentsRow.add( new UI.Text( 'Depth segments' ).setWidth( '90px' ) ); - depthSegmentsRow.add( depthSegments ); - - container.add( depthSegmentsRow ); - - // - - function update() { - - editor.execute( new SetGeometryCommand( object, new THREE[ geometry.type ]( - width.getValue(), - height.getValue(), - depth.getValue(), - widthSegments.getValue(), - heightSegments.getValue(), - depthSegments.getValue() - ) ) ); - - } - - return container; - - }; - - Sidebar.Geometry.BoxBufferGeometry = Sidebar.Geometry.BoxGeometry; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar.Geometry.BoxGeometry', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Sidebar.Geometry.BufferGeometry = function ( editor ) { - - var signals = editor.signals; - - var container = new UI.Row(); - - function update( object ) { - - if ( object === null ) return; // objectSelected.dispatch( null ) - if ( object === undefined ) return; - - var geometry = object.geometry; - - if ( geometry instanceof THREE.BufferGeometry ) { - - container.clear(); - container.setDisplay( 'block' ); - - var index = geometry.index; - - if ( index !== null ) { - - var panel = new UI.Row(); - panel.add( new UI.Text( 'index' ).setWidth( '90px' ) ); - panel.add( new UI.Text( ( index.count ).format() ).setFontSize( '12px' ) ); - container.add( panel ); - - } - - var attributes = geometry.attributes; - - for ( var name in attributes ) { - - var attribute = attributes[ name ]; - - var panel = new UI.Row(); - panel.add( new UI.Text( name ).setWidth( '90px' ) ); - panel.add( new UI.Text( ( attribute.count ).format() + ' (' + attribute.itemSize + ')' ).setFontSize( '12px' ) ); - container.add( panel ); - - } - - } else { - - container.setDisplay( 'none' ); - - } - - } - - signals.objectSelected.add( update ); - signals.geometryChanged.add( update ); - - return container; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar.Geometry.BufferGeometry', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Sidebar.Geometry.CircleGeometry = function ( editor, object ) { - - var signals = editor.signals; - - var container = new UI.Row(); - - var geometry = object.geometry; - var parameters = geometry.parameters; - - // radius - - var radiusRow = new UI.Row(); - var radius = new UI.Number( parameters.radius ).onChange( update ); - - radiusRow.add( new UI.Text( 'Radius' ).setWidth( '90px' ) ); - radiusRow.add( radius ); - - container.add( radiusRow ); - - // segments - - var segmentsRow = new UI.Row(); - var segments = new UI.Integer( parameters.segments ).setRange( 3, Infinity ).onChange( update ); - - segmentsRow.add( new UI.Text( 'Segments' ).setWidth( '90px' ) ); - segmentsRow.add( segments ); - - container.add( segmentsRow ); - - // thetaStart - - var thetaStartRow = new UI.Row(); - var thetaStart = new UI.Number( parameters.thetaStart ).onChange( update ); - - thetaStartRow.add( new UI.Text( 'Theta start' ).setWidth( '90px' ) ); - thetaStartRow.add( thetaStart ); - - container.add( thetaStartRow ); - - // thetaLength - - var thetaLengthRow = new UI.Row(); - var thetaLength = new UI.Number( parameters.thetaLength ).onChange( update ); - - thetaLengthRow.add( new UI.Text( 'Theta length' ).setWidth( '90px' ) ); - thetaLengthRow.add( thetaLength ); - - container.add( thetaLengthRow ); - - // - - function update() { - - editor.execute( new SetGeometryCommand( object, new THREE[ geometry.type ]( - radius.getValue(), - segments.getValue(), - thetaStart.getValue(), - thetaLength.getValue() - ) ) ); - - } - - return container; - - }; - - Sidebar.Geometry.CircleBufferGeometry = Sidebar.Geometry.CircleGeometry; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar.Geometry.CircleGeometry', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Sidebar.Geometry.CylinderGeometry = function ( editor, object ) { - - var signals = editor.signals; - - var container = new UI.Row(); - - var geometry = object.geometry; - var parameters = geometry.parameters; - - // radiusTop - - var radiusTopRow = new UI.Row(); - var radiusTop = new UI.Number( parameters.radiusTop ).onChange( update ); - - radiusTopRow.add( new UI.Text( 'Radius top' ).setWidth( '90px' ) ); - radiusTopRow.add( radiusTop ); - - container.add( radiusTopRow ); - - // radiusBottom - - var radiusBottomRow = new UI.Row(); - var radiusBottom = new UI.Number( parameters.radiusBottom ).onChange( update ); - - radiusBottomRow.add( new UI.Text( 'Radius bottom' ).setWidth( '90px' ) ); - radiusBottomRow.add( radiusBottom ); - - container.add( radiusBottomRow ); - - // height - - var heightRow = new UI.Row(); - var height = new UI.Number( parameters.height ).onChange( update ); - - heightRow.add( new UI.Text( 'Height' ).setWidth( '90px' ) ); - heightRow.add( height ); - - container.add( heightRow ); - - // radialSegments - - var radialSegmentsRow = new UI.Row(); - var radialSegments = new UI.Integer( parameters.radialSegments ).setRange( 1, Infinity ).onChange( update ); - - radialSegmentsRow.add( new UI.Text( 'Radial segments' ).setWidth( '90px' ) ); - radialSegmentsRow.add( radialSegments ); - - container.add( radialSegmentsRow ); - - // heightSegments - - var heightSegmentsRow = new UI.Row(); - var heightSegments = new UI.Integer( parameters.heightSegments ).setRange( 1, Infinity ).onChange( update ); - - heightSegmentsRow.add( new UI.Text( 'Height segments' ).setWidth( '90px' ) ); - heightSegmentsRow.add( heightSegments ); - - container.add( heightSegmentsRow ); - - // openEnded - - var openEndedRow = new UI.Row(); - var openEnded = new UI.Checkbox( parameters.openEnded ).onChange( update ); - - openEndedRow.add( new UI.Text( 'Open ended' ).setWidth( '90px' ) ); - openEndedRow.add( openEnded ); - - container.add( openEndedRow ); - - // - - function update() { - - editor.execute( new SetGeometryCommand( object, new THREE[ geometry.type ]( - radiusTop.getValue(), - radiusBottom.getValue(), - height.getValue(), - radialSegments.getValue(), - heightSegments.getValue(), - openEnded.getValue() - ) ) ); - - } - - return container; - - }; - - Sidebar.Geometry.CylinderBufferGeometry = Sidebar.Geometry.CylinderGeometry; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar.Geometry.CylinderGeometry', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar.Geometry', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Sidebar.Geometry.IcosahedronGeometry = function ( editor, object ) { - - var signals = editor.signals; - - var container = new UI.Row(); - - var geometry = object.geometry; - var parameters = geometry.parameters; - - // radius - - var radiusRow = new UI.Row(); - var radius = new UI.Number( parameters.radius ).onChange( update ); - - radiusRow.add( new UI.Text( 'Radius' ).setWidth( '90px' ) ); - radiusRow.add( radius ); - - container.add( radiusRow ); - - // detail - - var detailRow = new UI.Row(); - var detail = new UI.Integer( parameters.detail ).setRange( 0, Infinity ).onChange( update ); - - detailRow.add( new UI.Text( 'Detail' ).setWidth( '90px' ) ); - detailRow.add( detail ); - - container.add( detailRow ); - - - // - - function update() { - - editor.execute( new SetGeometryCommand( object, new THREE[ geometry.type ]( - radius.getValue(), - detail.getValue() - ) ) ); - - signals.objectChanged.dispatch( object ); - - } - - return container; - - }; - - Sidebar.Geometry.IcosahedronBufferGeometry = Sidebar.Geometry.IcosahedronGeometry; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar.Geometry.IcosahedronGeometry', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author rfm1201 - */ - - Sidebar.Geometry.LatheGeometry = function( editor, object ) { - - var signals = editor.signals; - - var container = new UI.Row(); - - var geometry = object.geometry; - var parameters = geometry.parameters; - - // segments - - var segmentsRow = new UI.Row(); - var segments = new UI.Integer( parameters.segments ).onChange( update ); - - segmentsRow.add( new UI.Text( 'Segments' ).setWidth( '90px' ) ); - segmentsRow.add( segments ); - - container.add( segmentsRow ); - - // phiStart - - var phiStartRow = new UI.Row(); - var phiStart = new UI.Number( parameters.phiStart * 180 / Math.PI ).onChange( update ); - - phiStartRow.add( new UI.Text( 'Phi start (°)' ).setWidth( '90px' ) ); - phiStartRow.add( phiStart ); - - container.add( phiStartRow ); - - // phiLength - - var phiLengthRow = new UI.Row(); - var phiLength = new UI.Number( parameters.phiLength * 180 / Math.PI ).onChange( update ); - - phiLengthRow.add( new UI.Text( 'Phi length (°)' ).setWidth( '90px' ) ); - phiLengthRow.add( phiLength ); - - container.add( phiLengthRow ); - - // points - - var lastPointIdx = 0; - var pointsUI = []; - - var pointsRow = new UI.Row(); - pointsRow.add( new UI.Text( 'Points' ).setWidth( '90px' ) ); - - var points = new UI.Span().setDisplay( 'inline-block' ); - pointsRow.add( points ); - - var pointsList = new UI.Div(); - points.add( pointsList ); - - for ( var i = 0; i < parameters.points.length; i ++ ) { - - var point = parameters.points[ i ]; - pointsList.add( createPointRow( point.x, point.y ) ); - - } - - var addPointButton = new UI.Button( '+' ).onClick( function() { - - if( pointsUI.length === 0 ){ - - pointsList.add( createPointRow( 0, 0 ) ); - - } else { - - var point = pointsUI[ pointsUI.length - 1 ]; - - pointsList.add( createPointRow( point.x.getValue(), point.y.getValue() ) ); - - } - - update(); - - } ); - points.add( addPointButton ); - - container.add( pointsRow ); - - // - - function createPointRow( x, y ) { - - var pointRow = new UI.Div(); - var lbl = new UI.Text( lastPointIdx + 1 ).setWidth( '20px' ); - var txtX = new UI.Number( x ).setRange( 0, Infinity ).setWidth( '40px' ).onChange( update ); - var txtY = new UI.Number( y ).setWidth( '40px' ).onChange( update ); - var idx = lastPointIdx; - var btn = new UI.Button( '-' ).onClick( function() { - - deletePointRow( idx ); - - } ); - - pointsUI.push( { row: pointRow, lbl: lbl, x: txtX, y: txtY } ); - lastPointIdx ++; - pointRow.add( lbl, txtX, txtY, btn ); - - return pointRow; - - } - - function deletePointRow( idx ) { - - if ( ! pointsUI[ idx ] ) return; - - pointsList.remove( pointsUI[ idx ].row ); - pointsUI[ idx ] = null; - - update(); - - } - - function update() { - - var points = []; - var count = 0; - - for ( var i = 0; i < pointsUI.length; i ++ ) { - - var pointUI = pointsUI[ i ]; - - if ( ! pointUI ) continue; - - points.push( new THREE.Vector2( pointUI.x.getValue(), pointUI.y.getValue() ) ); - count ++; - pointUI.lbl.setValue( count ); - - } - - editor.execute( new SetGeometryCommand( object, new THREE[ geometry.type ]( - points, - segments.getValue(), - phiStart.getValue() / 180 * Math.PI, - phiLength.getValue() / 180 * Math.PI - ) ) ); - - } - - return container; - - }; - - Sidebar.Geometry.LatheBufferGeometry = Sidebar.Geometry.LatheGeometry; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar.Geometry.LatheGeometry', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Sidebar.Geometry.Modifiers = function ( editor, object ) { - - var signals = editor.signals; - - var container = new UI.Row().setPaddingLeft( '90px' ); - - var geometry = object.geometry; - - // Compute Vertex Normals - - var button = new UI.Button( 'Compute Vertex Normals' ); - button.onClick( function () { - - geometry.computeVertexNormals(); - - if ( geometry instanceof THREE.BufferGeometry ) { - - geometry.attributes.normal.needsUpdate = true; - - } else { - - geometry.normalsNeedUpdate = true; - - } - - signals.geometryChanged.dispatch( object ); - - } ); - - container.add( button ); - - // - - return container; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar.Geometry.Modifiers', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Sidebar.Geometry.PlaneGeometry = function ( editor, object ) { - - var signals = editor.signals; - - var container = new UI.Row(); - - var geometry = object.geometry; - var parameters = geometry.parameters; - - // width - - var widthRow = new UI.Row(); - var width = new UI.Number( parameters.width ).onChange( update ); - - widthRow.add( new UI.Text( 'Width' ).setWidth( '90px' ) ); - widthRow.add( width ); - - container.add( widthRow ); - - // height - - var heightRow = new UI.Row(); - var height = new UI.Number( parameters.height ).onChange( update ); - - heightRow.add( new UI.Text( 'Height' ).setWidth( '90px' ) ); - heightRow.add( height ); - - container.add( heightRow ); - - // widthSegments - - var widthSegmentsRow = new UI.Row(); - var widthSegments = new UI.Integer( parameters.widthSegments ).setRange( 1, Infinity ).onChange( update ); - - widthSegmentsRow.add( new UI.Text( 'Width segments' ).setWidth( '90px' ) ); - widthSegmentsRow.add( widthSegments ); - - container.add( widthSegmentsRow ); - - // heightSegments - - var heightSegmentsRow = new UI.Row(); - var heightSegments = new UI.Integer( parameters.heightSegments ).setRange( 1, Infinity ).onChange( update ); - - heightSegmentsRow.add( new UI.Text( 'Height segments' ).setWidth( '90px' ) ); - heightSegmentsRow.add( heightSegments ); - - container.add( heightSegmentsRow ); - - - // - - function update() { - - editor.execute( new SetGeometryCommand( object, new THREE[ geometry.type ]( - width.getValue(), - height.getValue(), - widthSegments.getValue(), - heightSegments.getValue() - ) ) ); - - } - - return container; - - }; - - Sidebar.Geometry.PlaneBufferGeometry = Sidebar.Geometry.PlaneGeometry; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar.Geometry.PlaneGeometry', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Sidebar.Geometry.SphereGeometry = function ( editor, object ) { - - var signals = editor.signals; - - var container = new UI.Row(); - - var geometry = object.geometry; - var parameters = geometry.parameters; - - // radius - - var radiusRow = new UI.Row(); - var radius = new UI.Number( parameters.radius ).onChange( update ); - - radiusRow.add( new UI.Text( 'Radius' ).setWidth( '90px' ) ); - radiusRow.add( radius ); - - container.add( radiusRow ); - - // widthSegments - - var widthSegmentsRow = new UI.Row(); - var widthSegments = new UI.Integer( parameters.widthSegments ).setRange( 1, Infinity ).onChange( update ); - - widthSegmentsRow.add( new UI.Text( 'Width segments' ).setWidth( '90px' ) ); - widthSegmentsRow.add( widthSegments ); - - container.add( widthSegmentsRow ); - - // heightSegments - - var heightSegmentsRow = new UI.Row(); - var heightSegments = new UI.Integer( parameters.heightSegments ).setRange( 1, Infinity ).onChange( update ); - - heightSegmentsRow.add( new UI.Text( 'Height segments' ).setWidth( '90px' ) ); - heightSegmentsRow.add( heightSegments ); - - container.add( heightSegmentsRow ); - - // phiStart - - var phiStartRow = new UI.Row(); - var phiStart = new UI.Number( parameters.phiStart ).onChange( update ); - - phiStartRow.add( new UI.Text( 'Phi start' ).setWidth( '90px' ) ); - phiStartRow.add( phiStart ); - - container.add( phiStartRow ); - - // phiLength - - var phiLengthRow = new UI.Row(); - var phiLength = new UI.Number( parameters.phiLength ).onChange( update ); - - phiLengthRow.add( new UI.Text( 'Phi length' ).setWidth( '90px' ) ); - phiLengthRow.add( phiLength ); - - container.add( phiLengthRow ); - - // thetaStart - - var thetaStartRow = new UI.Row(); - var thetaStart = new UI.Number( parameters.thetaStart ).onChange( update ); - - thetaStartRow.add( new UI.Text( 'Theta start' ).setWidth( '90px' ) ); - thetaStartRow.add( thetaStart ); - - container.add( thetaStartRow ); - - // thetaLength - - var thetaLengthRow = new UI.Row(); - var thetaLength = new UI.Number( parameters.thetaLength ).onChange( update ); - - thetaLengthRow.add( new UI.Text( 'Theta length' ).setWidth( '90px' ) ); - thetaLengthRow.add( thetaLength ); - - container.add( thetaLengthRow ); - - - // - - function update() { - - editor.execute( new SetGeometryCommand( object, new THREE[ geometry.type ]( - radius.getValue(), - widthSegments.getValue(), - heightSegments.getValue(), - phiStart.getValue(), - phiLength.getValue(), - thetaStart.getValue(), - thetaLength.getValue() - ) ) ); - - } - - return container; - - }; - - Sidebar.Geometry.SphereBufferGeometry = Sidebar.Geometry.SphereGeometry; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar.Geometry.SphereGeometry', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author tschw - */ - - Sidebar.Geometry.TeapotBufferGeometry = function ( signals, object ) { - - var container = new UI.Row(); - - var parameters = object.geometry.parameters; - - // size - - var sizeRow = new UI.Row(); - var size = new UI.Number( parameters.size ).onChange( update ); - - sizeRow.add( new UI.Text( 'Size' ).setWidth( '90px' ) ); - sizeRow.add( size ); - - container.add( sizeRow ); - - // segments - - var segmentsRow = new UI.Row(); - var segments = new UI.Integer( parameters.segments ).setRange( 1, Infinity ).onChange( update ); - - segmentsRow.add( new UI.Text( 'Segments' ).setWidth( '90px' ) ); - segmentsRow.add( segments ); - - container.add( segmentsRow ); - - // bottom - - var bottomRow = new UI.Row(); - var bottom = new UI.Checkbox( parameters.bottom ).onChange( update ); - - bottomRow.add( new UI.Text( 'Bottom' ).setWidth( '90px' ) ); - bottomRow.add( bottom ); - - container.add( bottomRow ); - - // lid - - var lidRow = new UI.Row(); - var lid = new UI.Checkbox( parameters.lid ).onChange( update ); - - lidRow.add( new UI.Text( 'Lid' ).setWidth( '90px' ) ); - lidRow.add( lid ); - - container.add( lidRow ); - - // body - - var bodyRow = new UI.Row(); - var body = new UI.Checkbox( parameters.body ).onChange( update ); - - bodyRow.add( new UI.Text( 'Body' ).setWidth( '90px' ) ); - bodyRow.add( body ); - - container.add( bodyRow ); - - // fitted lid - - var fitLidRow = new UI.Row(); - var fitLid = new UI.Checkbox( parameters.fitLid ).onChange( update ); - - fitLidRow.add( new UI.Text( 'Fitted Lid' ).setWidth( '90px' ) ); - fitLidRow.add( fitLid ); - - container.add( fitLidRow ); - - // blinn-sized - - var blinnRow = new UI.Row(); - var blinn = new UI.Checkbox( parameters.blinn ).onChange( update ); - - blinnRow.add( new UI.Text( 'Blinn-scaled' ).setWidth( '90px' ) ); - blinnRow.add( blinn ); - - container.add( blinnRow ); - - function update() { - - object.geometry.dispose(); - - object.geometry = new THREE.TeapotBufferGeometry( - size.getValue(), - segments.getValue(), - bottom.getValue(), - lid.getValue(), - body.getValue(), - fitLid.getValue(), - blinn.getValue() - ); - - object.geometry.computeBoundingSphere(); - - signals.geometryChanged.dispatch( object ); - - } - - return container; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar.Geometry.TeapotBufferGeometry', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Sidebar.Geometry.TorusGeometry = function ( editor, object ) { - - var signals = editor.signals; - - var container = new UI.Row(); - - var geometry = object.geometry; - var parameters = geometry.parameters; - - // radius - - var radiusRow = new UI.Row(); - var radius = new UI.Number( parameters.radius ).onChange( update ); - - radiusRow.add( new UI.Text( 'Radius' ).setWidth( '90px' ) ); - radiusRow.add( radius ); - - container.add( radiusRow ); - - // tube - - var tubeRow = new UI.Row(); - var tube = new UI.Number( parameters.tube ).onChange( update ); - - tubeRow.add( new UI.Text( 'Tube' ).setWidth( '90px' ) ); - tubeRow.add( tube ); - - container.add( tubeRow ); - - // radialSegments - - var radialSegmentsRow = new UI.Row(); - var radialSegments = new UI.Integer( parameters.radialSegments ).setRange( 1, Infinity ).onChange( update ); - - radialSegmentsRow.add( new UI.Text( 'Radial segments' ).setWidth( '90px' ) ); - radialSegmentsRow.add( radialSegments ); - - container.add( radialSegmentsRow ); - - // tubularSegments - - var tubularSegmentsRow = new UI.Row(); - var tubularSegments = new UI.Integer( parameters.tubularSegments ).setRange( 1, Infinity ).onChange( update ); - - tubularSegmentsRow.add( new UI.Text( 'Tubular segments' ).setWidth( '90px' ) ); - tubularSegmentsRow.add( tubularSegments ); - - container.add( tubularSegmentsRow ); - - // arc - - var arcRow = new UI.Row(); - var arc = new UI.Number( parameters.arc ).onChange( update ); - - arcRow.add( new UI.Text( 'Arc' ).setWidth( '90px' ) ); - arcRow.add( arc ); - - container.add( arcRow ); - - - // - - function update() { - - editor.execute( new SetGeometryCommand( object, new THREE[ geometry.type ]( - radius.getValue(), - tube.getValue(), - radialSegments.getValue(), - tubularSegments.getValue(), - arc.getValue() - ) ) ); - - } - - return container; - - }; - - Sidebar.Geometry.TorusBufferGeometry = Sidebar.Geometry.TorusGeometry; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar.Geometry.TorusGeometry', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Sidebar.Geometry.TorusKnotGeometry = function ( editor, object ) { - - var signals = editor.signals; - - var container = new UI.Row(); - - var geometry = object.geometry; - var parameters = geometry.parameters; - - // radius - - var radiusRow = new UI.Row(); - var radius = new UI.Number( parameters.radius ).onChange( update ); - - radiusRow.add( new UI.Text( 'Radius' ).setWidth( '90px' ) ); - radiusRow.add( radius ); - - container.add( radiusRow ); - - // tube - - var tubeRow = new UI.Row(); - var tube = new UI.Number( parameters.tube ).onChange( update ); - - tubeRow.add( new UI.Text( 'Tube' ).setWidth( '90px' ) ); - tubeRow.add( tube ); - - container.add( tubeRow ); - - // tubularSegments - - var tubularSegmentsRow = new UI.Row(); - var tubularSegments = new UI.Integer( parameters.tubularSegments ).setRange( 1, Infinity ).onChange( update ); - - tubularSegmentsRow.add( new UI.Text( 'Tubular segments' ).setWidth( '90px' ) ); - tubularSegmentsRow.add( tubularSegments ); - - container.add( tubularSegmentsRow ); - - // radialSegments - - var radialSegmentsRow = new UI.Row(); - var radialSegments = new UI.Integer( parameters.radialSegments ).setRange( 1, Infinity ).onChange( update ); - - radialSegmentsRow.add( new UI.Text( 'Radial segments' ).setWidth( '90px' ) ); - radialSegmentsRow.add( radialSegments ); - - container.add( radialSegmentsRow ); - - // p - - var pRow = new UI.Row(); - var p = new UI.Number( parameters.p ).onChange( update ); - - pRow.add( new UI.Text( 'P' ).setWidth( '90px' ) ); - pRow.add( p ); - - container.add( pRow ); - - // q - - var qRow = new UI.Row(); - var q = new UI.Number( parameters.q ).onChange( update ); - - pRow.add( new UI.Text( 'Q' ).setWidth( '90px' ) ); - pRow.add( q ); - - container.add( qRow ); - - - // - - function update() { - - editor.execute( new SetGeometryCommand( object, new THREE[ geometry.type ]( - radius.getValue(), - tube.getValue(), - tubularSegments.getValue(), - radialSegments.getValue(), - p.getValue(), - q.getValue() - ) ) ); - - } - - return container; - - }; - - Sidebar.Geometry.TorusKnotBufferGeometry = Sidebar.Geometry.TorusKnotGeometry; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar.Geometry.TorusKnotGeometry', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author dforrer / https://github.com/dforrer - * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch) - */ - - Sidebar.History = function ( editor ) { - - var signals = editor.signals; - - var config = editor.config; - - var history = editor.history; - - var container = new UI.Panel(); - - container.add( new UI.Text( 'HISTORY' ) ); - - // - - var persistent = new UI.THREE.Boolean( config.getKey( 'settings/history' ), 'persistent' ); - persistent.setPosition( 'absolute' ).setRight( '8px' ); - persistent.onChange( function () { - - var value = this.getValue(); - - config.setKey( 'settings/history', value ); - - if ( value ) { - - alert( 'The history will be preserved across sessions.\nThis can have an impact on performance when working with textures.' ); - - var lastUndoCmd = history.undos[ history.undos.length - 1 ]; - var lastUndoId = ( lastUndoCmd !== undefined ) ? lastUndoCmd.id : 0; - editor.history.enableSerialization( lastUndoId ); - - } else { - - signals.historyChanged.dispatch(); - - } - - } ); - container.add( persistent ); - - container.add( new UI.Break(), new UI.Break() ); - - var ignoreObjectSelectedSignal = false; - - var outliner = new UI.Outliner( editor ); - outliner.onChange( function () { - - ignoreObjectSelectedSignal = true; - - editor.history.goToState( parseInt( outliner.getValue() ) ); - - ignoreObjectSelectedSignal = false; - - } ); - container.add( outliner ); - - // - - var refreshUI = function () { - - var options = []; - var enumerator = 1; - - function buildOption( object ) { - - var option = document.createElement( 'div' ); - option.value = object.id; - - return option; - - } - - ( function addObjects( objects ) { - - for ( var i = 0, l = objects.length; i < l; i ++ ) { - - var object = objects[ i ]; - - var option = buildOption( object ); - option.innerHTML = ' ' + object.name; - - options.push( option ); - - } - - } )( history.undos ); - - - ( function addObjects( objects, pad ) { - - for ( var i = objects.length - 1; i >= 0; i -- ) { - - var object = objects[ i ]; - - var option = buildOption( object ); - option.innerHTML = ' ' + object.name; - option.style.opacity = 0.3; - - options.push( option ); - - } - - } )( history.redos, ' ' ); - - outliner.setOptions( options ); - - }; - - refreshUI(); - - // events - - signals.editorCleared.add( refreshUI ); - - signals.historyChanged.add( refreshUI ); - signals.historyChanged.add( function ( cmd ) { - - outliner.setValue( cmd !== undefined ? cmd.id : null ); - - } ); - - - return container; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar.History', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Sidebar.Material = function ( editor ) { - - var signals = editor.signals; - - var currentObject; - - var currentMaterialSlot = 0; - - var container = new UI.Panel(); - container.setBorderTop( '0' ); - container.setPaddingTop( '20px' ); - - // New / Copy / Paste - - var copiedMaterial; - - var managerRow = new UI.Row(); - - // Current material slot - - var materialSlotRow = new UI.Row(); - - materialSlotRow.add( new UI.Text( 'Slot' ).setWidth( '90px' ) ); - - var materialSlotSelect = new UI.Select().setWidth( '170px' ).setFontSize( '12px' ).onChange( update ); - materialSlotSelect.setOptions( { 0: '' } ).setValue( 0 ); - materialSlotRow.add( materialSlotSelect ); - - container.add( materialSlotRow ); - - managerRow.add( new UI.Text( '' ).setWidth( '90px' ) ); - - managerRow.add( new UI.Button( 'New' ).onClick( function () { - - var material = new THREE[ materialClass.getValue() ](); - editor.execute( new SetMaterialCommand( currentObject, material, currentMaterialSlot ), 'New Material: ' + materialClass.getValue() ); - update(); - - } ) ); - - managerRow.add( new UI.Button( 'Copy' ).setMarginLeft( '4px' ).onClick( function () { - - copiedMaterial = currentObject.material; - - if ( Array.isArray( copiedMaterial ) ) { - - if ( copiedMaterial.length === 0 ) return; - - copiedMaterial = copiedMaterial[ currentMaterialSlot ]; - - } - - } ) ); - - managerRow.add( new UI.Button( 'Paste' ).setMarginLeft( '4px' ).onClick( function () { - - if ( copiedMaterial === undefined ) return; - - editor.execute( new SetMaterialCommand( currentObject, copiedMaterial, currentMaterialSlot ), 'Pasted Material: ' + materialClass.getValue() ); - refreshUI(); - update(); - - } ) ); - - container.add( managerRow ); - - - // type - - var materialClassRow = new UI.Row(); - var materialClass = new UI.Select().setOptions( { - - 'LineBasicMaterial': 'LineBasicMaterial', - 'LineDashedMaterial': 'LineDashedMaterial', - 'MeshBasicMaterial': 'MeshBasicMaterial', - 'MeshDepthMaterial': 'MeshDepthMaterial', - 'MeshNormalMaterial': 'MeshNormalMaterial', - 'MeshLambertMaterial': 'MeshLambertMaterial', - 'MeshPhongMaterial': 'MeshPhongMaterial', - 'MeshStandardMaterial': 'MeshStandardMaterial', - 'MeshPhysicalMaterial': 'MeshPhysicalMaterial', - 'ShaderMaterial': 'ShaderMaterial', - 'SpriteMaterial': 'SpriteMaterial' - - } ).setWidth( '150px' ).setFontSize( '12px' ).onChange( update ); - - materialClassRow.add( new UI.Text( 'Type' ).setWidth( '90px' ) ); - materialClassRow.add( materialClass ); - - container.add( materialClassRow ); - - // uuid - - var materialUUIDRow = new UI.Row(); - var materialUUID = new UI.Input().setWidth( '102px' ).setFontSize( '12px' ).setDisabled( true ); - var materialUUIDRenew = new UI.Button( 'New' ).setMarginLeft( '7px' ).onClick( function () { - - materialUUID.setValue( THREE.Math.generateUUID() ); - update(); - - } ); - - materialUUIDRow.add( new UI.Text( 'UUID' ).setWidth( '90px' ) ); - materialUUIDRow.add( materialUUID ); - materialUUIDRow.add( materialUUIDRenew ); - - container.add( materialUUIDRow ); - - // name - - var materialNameRow = new UI.Row(); - var materialName = new UI.Input().setWidth( '150px' ).setFontSize( '12px' ).onChange( function () { - - editor.execute( new SetMaterialValueCommand( editor.selected, 'name', materialName.getValue(), currentMaterialSlot ) ); - - } ); - - materialNameRow.add( new UI.Text( 'Name' ).setWidth( '90px' ) ); - materialNameRow.add( materialName ); - - container.add( materialNameRow ); - - // program - - var materialProgramRow = new UI.Row(); - materialProgramRow.add( new UI.Text( 'Program' ).setWidth( '90px' ) ); - - var materialProgramInfo = new UI.Button( 'Info' ); - materialProgramInfo.setMarginLeft( '4px' ); - materialProgramInfo.onClick( function () { - - signals.editScript.dispatch( currentObject, 'programInfo' ); - - } ); - materialProgramRow.add( materialProgramInfo ); - - var materialProgramVertex = new UI.Button( 'Vertex' ); - materialProgramVertex.setMarginLeft( '4px' ); - materialProgramVertex.onClick( function () { - - signals.editScript.dispatch( currentObject, 'vertexShader' ); - - } ); - materialProgramRow.add( materialProgramVertex ); - - var materialProgramFragment = new UI.Button( 'Fragment' ); - materialProgramFragment.setMarginLeft( '4px' ); - materialProgramFragment.onClick( function () { - - signals.editScript.dispatch( currentObject, 'fragmentShader' ); - - } ); - materialProgramRow.add( materialProgramFragment ); - - container.add( materialProgramRow ); - - // color - - var materialColorRow = new UI.Row(); - var materialColor = new UI.Color().onChange( update ); - - materialColorRow.add( new UI.Text( 'Color' ).setWidth( '90px' ) ); - materialColorRow.add( materialColor ); - - container.add( materialColorRow ); - - // roughness - - var materialRoughnessRow = new UI.Row(); - var materialRoughness = new UI.Number( 0.5 ).setWidth( '60px' ).setRange( 0, 1 ).onChange( update ); - - materialRoughnessRow.add( new UI.Text( 'Roughness' ).setWidth( '90px' ) ); - materialRoughnessRow.add( materialRoughness ); - - container.add( materialRoughnessRow ); - - // metalness - - var materialMetalnessRow = new UI.Row(); - var materialMetalness = new UI.Number( 0.5 ).setWidth( '60px' ).setRange( 0, 1 ).onChange( update ); - - materialMetalnessRow.add( new UI.Text( 'Metalness' ).setWidth( '90px' ) ); - materialMetalnessRow.add( materialMetalness ); - - container.add( materialMetalnessRow ); - - // emissive - - var materialEmissiveRow = new UI.Row(); - var materialEmissive = new UI.Color().setHexValue( 0x000000 ).onChange( update ); - - materialEmissiveRow.add( new UI.Text( 'Emissive' ).setWidth( '90px' ) ); - materialEmissiveRow.add( materialEmissive ); - - container.add( materialEmissiveRow ); - - // specular - - var materialSpecularRow = new UI.Row(); - var materialSpecular = new UI.Color().setHexValue( 0x111111 ).onChange( update ); - - materialSpecularRow.add( new UI.Text( 'Specular' ).setWidth( '90px' ) ); - materialSpecularRow.add( materialSpecular ); - - container.add( materialSpecularRow ); - - // shininess - - var materialShininessRow = new UI.Row(); - var materialShininess = new UI.Number( 30 ).onChange( update ); - - materialShininessRow.add( new UI.Text( 'Shininess' ).setWidth( '90px' ) ); - materialShininessRow.add( materialShininess ); - - container.add( materialShininessRow ); - - // clearCoat - - var materialClearCoatRow = new UI.Row(); - var materialClearCoat = new UI.Number( 1 ).setWidth( '60px' ).setRange( 0, 1 ).onChange( update ); - - materialClearCoatRow.add( new UI.Text( 'ClearCoat' ).setWidth( '90px' ) ); - materialClearCoatRow.add( materialClearCoat ); - - container.add( materialClearCoatRow ); - - // clearCoatRoughness - - var materialClearCoatRoughnessRow = new UI.Row(); - var materialClearCoatRoughness = new UI.Number( 1 ).setWidth( '60px' ).setRange( 0, 1 ).onChange( update ); - - materialClearCoatRoughnessRow.add( new UI.Text( 'ClearCoat Roughness' ).setWidth( '90px' ) ); - materialClearCoatRoughnessRow.add( materialClearCoatRoughness ); - - container.add( materialClearCoatRoughnessRow ); - - // vertex colors - - var materialVertexColorsRow = new UI.Row(); - var materialVertexColors = new UI.Select().setOptions( { - - 0: 'No', - 1: 'Face', - 2: 'Vertex' - - } ).onChange( update ); - - materialVertexColorsRow.add( new UI.Text( 'Vertex Colors' ).setWidth( '90px' ) ); - materialVertexColorsRow.add( materialVertexColors ); - - container.add( materialVertexColorsRow ); - - // skinning - - var materialSkinningRow = new UI.Row(); - var materialSkinning = new UI.Checkbox( false ).onChange( update ); - - materialSkinningRow.add( new UI.Text( 'Skinning' ).setWidth( '90px' ) ); - materialSkinningRow.add( materialSkinning ); - - container.add( materialSkinningRow ); - - // map - - var materialMapRow = new UI.Row(); - var materialMapEnabled = new UI.Checkbox( false ).onChange( update ); - var materialMap = new UI.Texture().onChange( update ); - - materialMapRow.add( new UI.Text( 'Map' ).setWidth( '90px' ) ); - materialMapRow.add( materialMapEnabled ); - materialMapRow.add( materialMap ); - - container.add( materialMapRow ); - - // alpha map - - var materialAlphaMapRow = new UI.Row(); - var materialAlphaMapEnabled = new UI.Checkbox( false ).onChange( update ); - var materialAlphaMap = new UI.Texture().onChange( update ); - - materialAlphaMapRow.add( new UI.Text( 'Alpha Map' ).setWidth( '90px' ) ); - materialAlphaMapRow.add( materialAlphaMapEnabled ); - materialAlphaMapRow.add( materialAlphaMap ); - - container.add( materialAlphaMapRow ); - - // bump map - - var materialBumpMapRow = new UI.Row(); - var materialBumpMapEnabled = new UI.Checkbox( false ).onChange( update ); - var materialBumpMap = new UI.Texture().onChange( update ); - var materialBumpScale = new UI.Number( 1 ).setWidth( '30px' ).onChange( update ); - - materialBumpMapRow.add( new UI.Text( 'Bump Map' ).setWidth( '90px' ) ); - materialBumpMapRow.add( materialBumpMapEnabled ); - materialBumpMapRow.add( materialBumpMap ); - materialBumpMapRow.add( materialBumpScale ); - - container.add( materialBumpMapRow ); - - // normal map - - var materialNormalMapRow = new UI.Row(); - var materialNormalMapEnabled = new UI.Checkbox( false ).onChange( update ); - var materialNormalMap = new UI.Texture().onChange( update ); - - materialNormalMapRow.add( new UI.Text( 'Normal Map' ).setWidth( '90px' ) ); - materialNormalMapRow.add( materialNormalMapEnabled ); - materialNormalMapRow.add( materialNormalMap ); - - container.add( materialNormalMapRow ); - - // displacement map - - var materialDisplacementMapRow = new UI.Row(); - var materialDisplacementMapEnabled = new UI.Checkbox( false ).onChange( update ); - var materialDisplacementMap = new UI.Texture().onChange( update ); - var materialDisplacementScale = new UI.Number( 1 ).setWidth( '30px' ).onChange( update ); - - materialDisplacementMapRow.add( new UI.Text( 'Displace Map' ).setWidth( '90px' ) ); - materialDisplacementMapRow.add( materialDisplacementMapEnabled ); - materialDisplacementMapRow.add( materialDisplacementMap ); - materialDisplacementMapRow.add( materialDisplacementScale ); - - container.add( materialDisplacementMapRow ); - - // roughness map - - var materialRoughnessMapRow = new UI.Row(); - var materialRoughnessMapEnabled = new UI.Checkbox( false ).onChange( update ); - var materialRoughnessMap = new UI.Texture().onChange( update ); - - materialRoughnessMapRow.add( new UI.Text( 'Rough. Map' ).setWidth( '90px' ) ); - materialRoughnessMapRow.add( materialRoughnessMapEnabled ); - materialRoughnessMapRow.add( materialRoughnessMap ); - - container.add( materialRoughnessMapRow ); - - // metalness map - - var materialMetalnessMapRow = new UI.Row(); - var materialMetalnessMapEnabled = new UI.Checkbox( false ).onChange( update ); - var materialMetalnessMap = new UI.Texture().onChange( update ); - - materialMetalnessMapRow.add( new UI.Text( 'Metal. Map' ).setWidth( '90px' ) ); - materialMetalnessMapRow.add( materialMetalnessMapEnabled ); - materialMetalnessMapRow.add( materialMetalnessMap ); - - container.add( materialMetalnessMapRow ); - - // specular map - - var materialSpecularMapRow = new UI.Row(); - var materialSpecularMapEnabled = new UI.Checkbox( false ).onChange( update ); - var materialSpecularMap = new UI.Texture().onChange( update ); - - materialSpecularMapRow.add( new UI.Text( 'Specular Map' ).setWidth( '90px' ) ); - materialSpecularMapRow.add( materialSpecularMapEnabled ); - materialSpecularMapRow.add( materialSpecularMap ); - - container.add( materialSpecularMapRow ); - - // env map - - var materialEnvMapRow = new UI.Row(); - var materialEnvMapEnabled = new UI.Checkbox( false ).onChange( update ); - var materialEnvMap = new UI.Texture( THREE.SphericalReflectionMapping ).onChange( update ); - var materialReflectivity = new UI.Number( 1 ).setWidth( '30px' ).onChange( update ); - - materialEnvMapRow.add( new UI.Text( 'Env Map' ).setWidth( '90px' ) ); - materialEnvMapRow.add( materialEnvMapEnabled ); - materialEnvMapRow.add( materialEnvMap ); - materialEnvMapRow.add( materialReflectivity ); - - container.add( materialEnvMapRow ); - - // light map - - var materialLightMapRow = new UI.Row(); - var materialLightMapEnabled = new UI.Checkbox( false ).onChange( update ); - var materialLightMap = new UI.Texture().onChange( update ); - - materialLightMapRow.add( new UI.Text( 'Light Map' ).setWidth( '90px' ) ); - materialLightMapRow.add( materialLightMapEnabled ); - materialLightMapRow.add( materialLightMap ); - - container.add( materialLightMapRow ); - - // ambient occlusion map - - var materialAOMapRow = new UI.Row(); - var materialAOMapEnabled = new UI.Checkbox( false ).onChange( update ); - var materialAOMap = new UI.Texture().onChange( update ); - var materialAOScale = new UI.Number( 1 ).setRange( 0, 1 ).setWidth( '30px' ).onChange( update ); - - materialAOMapRow.add( new UI.Text( 'AO Map' ).setWidth( '90px' ) ); - materialAOMapRow.add( materialAOMapEnabled ); - materialAOMapRow.add( materialAOMap ); - materialAOMapRow.add( materialAOScale ); - - container.add( materialAOMapRow ); - - // emissive map - - var materialEmissiveMapRow = new UI.Row(); - var materialEmissiveMapEnabled = new UI.Checkbox( false ).onChange( update ); - var materialEmissiveMap = new UI.Texture().onChange( update ); - - materialEmissiveMapRow.add( new UI.Text( 'Emissive Map' ).setWidth( '90px' ) ); - materialEmissiveMapRow.add( materialEmissiveMapEnabled ); - materialEmissiveMapRow.add( materialEmissiveMap ); - - container.add( materialEmissiveMapRow ); - - // side - - var materialSideRow = new UI.Row(); - var materialSide = new UI.Select().setOptions( { - - 0: 'Front', - 1: 'Back', - 2: 'Double' - - } ).setWidth( '150px' ).setFontSize( '12px' ).onChange( update ); - - materialSideRow.add( new UI.Text( 'Side' ).setWidth( '90px' ) ); - materialSideRow.add( materialSide ); - - container.add( materialSideRow ); - - // shading - - var materialShadingRow = new UI.Row(); - var materialShading = new UI.Checkbox(false).setLeft( '100px' ).onChange( update ); - - materialShadingRow.add( new UI.Text( 'Flat Shaded' ).setWidth( '90px' ) ); - materialShadingRow.add( materialShading ); - - container.add( materialShadingRow ); - - // blending - - var materialBlendingRow = new UI.Row(); - var materialBlending = new UI.Select().setOptions( { - - 0: 'No', - 1: 'Normal', - 2: 'Additive', - 3: 'Subtractive', - 4: 'Multiply', - 5: 'Custom' - - } ).setWidth( '150px' ).setFontSize( '12px' ).onChange( update ); - - materialBlendingRow.add( new UI.Text( 'Blending' ).setWidth( '90px' ) ); - materialBlendingRow.add( materialBlending ); - - container.add( materialBlendingRow ); - - // opacity - - var materialOpacityRow = new UI.Row(); - var materialOpacity = new UI.Number( 1 ).setWidth( '60px' ).setRange( 0, 1 ).onChange( update ); - - materialOpacityRow.add( new UI.Text( 'Opacity' ).setWidth( '90px' ) ); - materialOpacityRow.add( materialOpacity ); - - container.add( materialOpacityRow ); - - // transparent - - var materialTransparentRow = new UI.Row(); - var materialTransparent = new UI.Checkbox().setLeft( '100px' ).onChange( update ); - - materialTransparentRow.add( new UI.Text( 'Transparent' ).setWidth( '90px' ) ); - materialTransparentRow.add( materialTransparent ); - - container.add( materialTransparentRow ); - - // alpha test - - var materialAlphaTestRow = new UI.Row(); - var materialAlphaTest = new UI.Number().setWidth( '60px' ).setRange( 0, 1 ).onChange( update ); - - materialAlphaTestRow.add( new UI.Text( 'Alpha Test' ).setWidth( '90px' ) ); - materialAlphaTestRow.add( materialAlphaTest ); - - container.add( materialAlphaTestRow ); - - // wireframe - - var materialWireframeRow = new UI.Row(); - var materialWireframe = new UI.Checkbox( false ).onChange( update ); - var materialWireframeLinewidth = new UI.Number( 1 ).setWidth( '60px' ).setRange( 0, 100 ).onChange( update ); - - materialWireframeRow.add( new UI.Text( 'Wireframe' ).setWidth( '90px' ) ); - materialWireframeRow.add( materialWireframe ); - materialWireframeRow.add( materialWireframeLinewidth ); - - container.add( materialWireframeRow ); - - // - - function update() { - - var object = currentObject; - - var geometry = object.geometry; - - var previousSelectedSlot = currentMaterialSlot; - - currentMaterialSlot = parseInt( materialSlotSelect.getValue() ); - - if ( currentMaterialSlot !== previousSelectedSlot ) refreshUI( true ); - - var material = editor.getObjectMaterial( currentObject, currentMaterialSlot ); - - var textureWarning = false; - var objectHasUvs = false; - - if ( object instanceof THREE.Sprite ) objectHasUvs = true; - if ( geometry instanceof THREE.Geometry && geometry.faceVertexUvs[ 0 ].length > 0 ) objectHasUvs = true; - if ( geometry instanceof THREE.BufferGeometry && geometry.attributes.uv !== undefined ) objectHasUvs = true; - - if ( material ) { - - if ( material.uuid !== undefined && material.uuid !== materialUUID.getValue() ) { - - editor.execute( new SetMaterialValueCommand( currentObject, 'uuid', materialUUID.getValue(), currentMaterialSlot ) ); - - } - - if ( material instanceof THREE[ materialClass.getValue() ] === false ) { - - material = new THREE[ materialClass.getValue() ](); - - editor.execute( new SetMaterialCommand( currentObject, material, currentMaterialSlot ), 'New Material: ' + materialClass.getValue() ); - // TODO Copy other references in the scene graph - // keeping name and UUID then. - // Also there should be means to create a unique - // copy for the current object explicitly and to - // attach the current material to other objects. - - } - - if ( material.color !== undefined && material.color.getHex() !== materialColor.getHexValue() ) { - - editor.execute( new SetMaterialColorCommand( currentObject, 'color', materialColor.getHexValue(), currentMaterialSlot ) ); - - } - - if ( material.roughness !== undefined && Math.abs( material.roughness - materialRoughness.getValue() ) >= 0.01 ) { - - editor.execute( new SetMaterialValueCommand( currentObject, 'roughness', materialRoughness.getValue(), currentMaterialSlot ) ); - - } - - if ( material.metalness !== undefined && Math.abs( material.metalness - materialMetalness.getValue() ) >= 0.01 ) { - - editor.execute( new SetMaterialValueCommand( currentObject, 'metalness', materialMetalness.getValue(), currentMaterialSlot ) ); - - } - - if ( material.emissive !== undefined && material.emissive.getHex() !== materialEmissive.getHexValue() ) { - - editor.execute( new SetMaterialColorCommand( currentObject, 'emissive', materialEmissive.getHexValue(), currentMaterialSlot ) ); - - } - - if ( material.specular !== undefined && material.specular.getHex() !== materialSpecular.getHexValue() ) { - - editor.execute( new SetMaterialColorCommand( currentObject, 'specular', materialSpecular.getHexValue(), currentMaterialSlot ) ); - - } - - if ( material.shininess !== undefined && Math.abs( material.shininess - materialShininess.getValue() ) >= 0.01 ) { - - editor.execute( new SetMaterialValueCommand( currentObject, 'shininess', materialShininess.getValue(), currentMaterialSlot ) ); - - } - - if ( material.clearCoat !== undefined && Math.abs( material.clearCoat - materialClearCoat.getValue() ) >= 0.01 ) { - - editor.execute( new SetMaterialValueCommand( currentObject, 'clearCoat', materialClearCoat.getValue(), currentMaterialSlot ) ); - - } - - if ( material.clearCoatRoughness !== undefined && Math.abs( material.clearCoatRoughness - materialClearCoatRoughness.getValue() ) >= 0.01 ) { - - editor.execute( new SetMaterialValueCommand( currentObject, 'clearCoatRoughness', materialClearCoatRoughness.getValue(), currentMaterialSlot ) ); - - } - - if ( material.vertexColors !== undefined ) { - - var vertexColors = parseInt( materialVertexColors.getValue() ); - - if ( material.vertexColors !== vertexColors ) { - - editor.execute( new SetMaterialValueCommand( currentObject, 'vertexColors', vertexColors, currentMaterialSlot ) ); - - } - - } - - if ( material.skinning !== undefined && material.skinning !== materialSkinning.getValue() ) { - - editor.execute( new SetMaterialValueCommand( currentObject, 'skinning', materialSkinning.getValue(), currentMaterialSlot ) ); - - } - - if ( material.map !== undefined ) { - - var mapEnabled = materialMapEnabled.getValue() === true; - - if ( objectHasUvs ) { - - var map = mapEnabled ? materialMap.getValue() : null; - if ( material.map !== map ) { - - editor.execute( new SetMaterialMapCommand( currentObject, 'map', map, currentMaterialSlot ) ); - - } - - } else { - - if ( mapEnabled ) textureWarning = true; - - } - - } - - if ( material.alphaMap !== undefined ) { - - var mapEnabled = materialAlphaMapEnabled.getValue() === true; - - if ( objectHasUvs ) { - - var alphaMap = mapEnabled ? materialAlphaMap.getValue() : null; - if ( material.alphaMap !== alphaMap ) { - - editor.execute( new SetMaterialMapCommand( currentObject, 'alphaMap', alphaMap, currentMaterialSlot ) ); - - } - - } else { - - if ( mapEnabled ) textureWarning = true; - - } - - } - - if ( material.bumpMap !== undefined ) { - - var bumpMapEnabled = materialBumpMapEnabled.getValue() === true; - - if ( objectHasUvs ) { - - var bumpMap = bumpMapEnabled ? materialBumpMap.getValue() : null; - if ( material.bumpMap !== bumpMap ) { - - editor.execute( new SetMaterialMapCommand( currentObject, 'bumpMap', bumpMap, currentMaterialSlot ) ); - - } - - if ( material.bumpScale !== materialBumpScale.getValue() ) { - - editor.execute( new SetMaterialValueCommand( currentObject, 'bumpScale', materialBumpScale.getValue(), currentMaterialSlot ) ); - - } - - } else { - - if ( bumpMapEnabled ) textureWarning = true; - - } - - } - - if ( material.normalMap !== undefined ) { - - var normalMapEnabled = materialNormalMapEnabled.getValue() === true; - - if ( objectHasUvs ) { - - var normalMap = normalMapEnabled ? materialNormalMap.getValue() : null; - if ( material.normalMap !== normalMap ) { - - editor.execute( new SetMaterialMapCommand( currentObject, 'normalMap', normalMap, currentMaterialSlot ) ); - - } - - } else { - - if ( normalMapEnabled ) textureWarning = true; - - } - - } - - if ( material.displacementMap !== undefined ) { - - var displacementMapEnabled = materialDisplacementMapEnabled.getValue() === true; - - if ( objectHasUvs ) { - - var displacementMap = displacementMapEnabled ? materialDisplacementMap.getValue() : null; - if ( material.displacementMap !== displacementMap ) { - - editor.execute( new SetMaterialMapCommand( currentObject, 'displacementMap', displacementMap, currentMaterialSlot ) ); - - } - - if ( material.displacementScale !== materialDisplacementScale.getValue() ) { - - editor.execute( new SetMaterialValueCommand( currentObject, 'displacementScale', materialDisplacementScale.getValue(), currentMaterialSlot ) ); - - } - - } else { - - if ( displacementMapEnabled ) textureWarning = true; - - } - - } - - if ( material.roughnessMap !== undefined ) { - - var roughnessMapEnabled = materialRoughnessMapEnabled.getValue() === true; - - if ( objectHasUvs ) { - - var roughnessMap = roughnessMapEnabled ? materialRoughnessMap.getValue() : null; - if ( material.roughnessMap !== roughnessMap ) { - - editor.execute( new SetMaterialMapCommand( currentObject, 'roughnessMap', roughnessMap, currentMaterialSlot ) ); - - } - - } else { - - if ( roughnessMapEnabled ) textureWarning = true; - - } - - } - - if ( material.metalnessMap !== undefined ) { - - var metalnessMapEnabled = materialMetalnessMapEnabled.getValue() === true; - - if ( objectHasUvs ) { - - var metalnessMap = metalnessMapEnabled ? materialMetalnessMap.getValue() : null; - if ( material.metalnessMap !== metalnessMap ) { - - editor.execute( new SetMaterialMapCommand( currentObject, 'metalnessMap', metalnessMap, currentMaterialSlot ) ); - - } - - } else { - - if ( metalnessMapEnabled ) textureWarning = true; - - } - - } - - if ( material.specularMap !== undefined ) { - - var specularMapEnabled = materialSpecularMapEnabled.getValue() === true; - - if ( objectHasUvs ) { - - var specularMap = specularMapEnabled ? materialSpecularMap.getValue() : null; - if ( material.specularMap !== specularMap ) { - - editor.execute( new SetMaterialMapCommand( currentObject, 'specularMap', specularMap, currentMaterialSlot ) ); - - } - - } else { - - if ( specularMapEnabled ) textureWarning = true; - - } - - } - - if ( material.envMap !== undefined ) { - - var envMapEnabled = materialEnvMapEnabled.getValue() === true; - - var envMap = envMapEnabled ? materialEnvMap.getValue() : null; - - if ( material.envMap !== envMap ) { - - editor.execute( new SetMaterialMapCommand( currentObject, 'envMap', envMap, currentMaterialSlot ) ); - - } - - } - - if ( material.reflectivity !== undefined ) { - - var reflectivity = materialReflectivity.getValue(); - - if ( material.reflectivity !== reflectivity ) { - - editor.execute( new SetMaterialValueCommand( currentObject, 'reflectivity', reflectivity, currentMaterialSlot ) ); - - } - - } - - if ( material.lightMap !== undefined ) { - - var lightMapEnabled = materialLightMapEnabled.getValue() === true; - - if ( objectHasUvs ) { - - var lightMap = lightMapEnabled ? materialLightMap.getValue() : null; - if ( material.lightMap !== lightMap ) { - - editor.execute( new SetMaterialMapCommand( currentObject, 'lightMap', lightMap, currentMaterialSlot ) ); - - } - - } else { - - if ( lightMapEnabled ) textureWarning = true; - - } - - } - - if ( material.aoMap !== undefined ) { - - var aoMapEnabled = materialAOMapEnabled.getValue() === true; - - if ( objectHasUvs ) { - - var aoMap = aoMapEnabled ? materialAOMap.getValue() : null; - if ( material.aoMap !== aoMap ) { - - editor.execute( new SetMaterialMapCommand( currentObject, 'aoMap', aoMap, currentMaterialSlot ) ); - - } - - if ( material.aoMapIntensity !== materialAOScale.getValue() ) { - - editor.execute( new SetMaterialValueCommand( currentObject, 'aoMapIntensity', materialAOScale.getValue(), currentMaterialSlot ) ); - - } - - } else { - - if ( aoMapEnabled ) textureWarning = true; - - } - - } - - if ( material.emissiveMap !== undefined ) { - - var emissiveMapEnabled = materialEmissiveMapEnabled.getValue() === true; - - if ( objectHasUvs ) { - - var emissiveMap = emissiveMapEnabled ? materialEmissiveMap.getValue() : null; - if ( material.emissiveMap !== emissiveMap ) { - - editor.execute( new SetMaterialMapCommand( currentObject, 'emissiveMap', emissiveMap, currentMaterialSlot ) ); - - } - - } else { - - if ( emissiveMapEnabled ) textureWarning = true; - - } - - } - - if ( material.side !== undefined ) { - - var side = parseInt( materialSide.getValue() ); - if ( material.side !== side ) { - - editor.execute( new SetMaterialValueCommand( currentObject, 'side', side, currentMaterialSlot ) ); - - } - - - } - - if ( material.flatShading !== undefined ) { - - var flatShading = materialShading.getValue(); - if ( material.flatShading != flatShading ) { - - editor.execute( new SetMaterialValueCommand( currentObject, 'flatShading', flatShading, currentMaterialSlot ) ); - - } - - } - - if ( material.blending !== undefined ) { - - var blending = parseInt( materialBlending.getValue() ); - if ( material.blending !== blending ) { - - editor.execute( new SetMaterialValueCommand( currentObject, 'blending', blending, currentMaterialSlot ) ); - - } - - } - - if ( material.opacity !== undefined && Math.abs( material.opacity - materialOpacity.getValue() ) >= 0.01 ) { - - editor.execute( new SetMaterialValueCommand( currentObject, 'opacity', materialOpacity.getValue(), currentMaterialSlot ) ); - - } - - if ( material.transparent !== undefined && material.transparent !== materialTransparent.getValue() ) { - - editor.execute( new SetMaterialValueCommand( currentObject, 'transparent', materialTransparent.getValue(), currentMaterialSlot ) ); - - } - - if ( material.alphaTest !== undefined && Math.abs( material.alphaTest - materialAlphaTest.getValue() ) >= 0.01 ) { - - editor.execute( new SetMaterialValueCommand( currentObject, 'alphaTest', materialAlphaTest.getValue(), currentMaterialSlot ) ); - - } - - if ( material.wireframe !== undefined && material.wireframe !== materialWireframe.getValue() ) { - - editor.execute( new SetMaterialValueCommand( currentObject, 'wireframe', materialWireframe.getValue(), currentMaterialSlot) ); - - } - - if ( material.wireframeLinewidth !== undefined && Math.abs( material.wireframeLinewidth - materialWireframeLinewidth.getValue() ) >= 0.01 ) { - - editor.execute( new SetMaterialValueCommand( currentObject, 'wireframeLinewidth', materialWireframeLinewidth.getValue(), currentMaterialSlot ) ); - - } - - refreshUI(); - - } - - if ( textureWarning ) { - - console.warn( "Can't set texture, model doesn't have texture coordinates" ); - - } - - } - - // - - function setRowVisibility() { - - var properties = { - 'name': materialNameRow, - 'color': materialColorRow, - 'roughness': materialRoughnessRow, - 'metalness': materialMetalnessRow, - 'emissive': materialEmissiveRow, - 'specular': materialSpecularRow, - 'shininess': materialShininessRow, - 'clearCoat': materialClearCoatRow, - 'clearCoatRoughness': materialClearCoatRoughnessRow, - 'vertexShader': materialProgramRow, - 'vertexColors': materialVertexColorsRow, - 'skinning': materialSkinningRow, - 'map': materialMapRow, - 'alphaMap': materialAlphaMapRow, - 'bumpMap': materialBumpMapRow, - 'normalMap': materialNormalMapRow, - 'displacementMap': materialDisplacementMapRow, - 'roughnessMap': materialRoughnessMapRow, - 'metalnessMap': materialMetalnessMapRow, - 'specularMap': materialSpecularMapRow, - 'envMap': materialEnvMapRow, - 'lightMap': materialLightMapRow, - 'aoMap': materialAOMapRow, - 'emissiveMap': materialEmissiveMapRow, - 'side': materialSideRow, - 'flatShading': materialShadingRow, - 'blending': materialBlendingRow, - 'opacity': materialOpacityRow, - 'transparent': materialTransparentRow, - 'alphaTest': materialAlphaTestRow, - 'wireframe': materialWireframeRow - }; - - var material = currentObject.material; - - if ( Array.isArray( material ) ) { - - materialSlotRow.setDisplay( '' ); - - if ( material.length === 0 ) return; - - material = material[ currentMaterialSlot ]; - - } else { - - materialSlotRow.setDisplay( 'none' ); - - } - - for ( var property in properties ) { - - properties[ property ].setDisplay( material[ property ] !== undefined ? '' : 'none' ); - - } - - } - - - function refreshUI( resetTextureSelectors ) { - - if ( ! currentObject ) return; - - var material = currentObject.material; - - if ( Array.isArray( material ) ) { - - var slotOptions = {}; - - currentMaterialSlot = Math.max( 0, Math.min( material.length, currentMaterialSlot ) ); - - for ( var i = 0; i < material.length; i ++ ) { - - slotOptions[ i ] = String( i + 1 ) + ': ' + material[ i ].name; - - } - - materialSlotSelect.setOptions( slotOptions ).setValue( currentMaterialSlot ); - - } - - material = editor.getObjectMaterial( currentObject, currentMaterialSlot ); - - if ( material.uuid !== undefined ) { - - materialUUID.setValue( material.uuid ); - - } - - if ( material.name !== undefined ) { - - materialName.setValue( material.name ); - - } - - materialClass.setValue( material.type ); - - if ( material.color !== undefined ) { - - materialColor.setHexValue( material.color.getHexString() ); - - } - - if ( material.roughness !== undefined ) { - - materialRoughness.setValue( material.roughness ); - - } - - if ( material.metalness !== undefined ) { - - materialMetalness.setValue( material.metalness ); - - } - - if ( material.emissive !== undefined ) { - - materialEmissive.setHexValue( material.emissive.getHexString() ); - - } - - if ( material.specular !== undefined ) { - - materialSpecular.setHexValue( material.specular.getHexString() ); - - } - - if ( material.shininess !== undefined ) { - - materialShininess.setValue( material.shininess ); - - } - - if ( material.clearCoat !== undefined ) { - - materialClearCoat.setValue( material.clearCoat ); - - } - - if ( material.clearCoatRoughness !== undefined ) { - - materialClearCoatRoughness.setValue( material.clearCoatRoughness ); - - } - - if ( material.vertexColors !== undefined ) { - - materialVertexColors.setValue( material.vertexColors ); - - } - - if ( material.skinning !== undefined ) { - - materialSkinning.setValue( material.skinning ); - - } - - if ( material.map !== undefined ) { - - materialMapEnabled.setValue( material.map !== null ); - - if ( material.map !== null || resetTextureSelectors ) { - - materialMap.setValue( material.map ); - - } - - } - - if ( material.alphaMap !== undefined ) { - - materialAlphaMapEnabled.setValue( material.alphaMap !== null ); - - if ( material.alphaMap !== null || resetTextureSelectors ) { - - materialAlphaMap.setValue( material.alphaMap ); - - } - - } - - if ( material.bumpMap !== undefined ) { - - materialBumpMapEnabled.setValue( material.bumpMap !== null ); - - if ( material.bumpMap !== null || resetTextureSelectors ) { - - materialBumpMap.setValue( material.bumpMap ); - - } - - materialBumpScale.setValue( material.bumpScale ); - - } - - if ( material.normalMap !== undefined ) { - - materialNormalMapEnabled.setValue( material.normalMap !== null ); - - if ( material.normalMap !== null || resetTextureSelectors ) { - - materialNormalMap.setValue( material.normalMap ); - - } - - } - - if ( material.displacementMap !== undefined ) { - - materialDisplacementMapEnabled.setValue( material.displacementMap !== null ); - - if ( material.displacementMap !== null || resetTextureSelectors ) { - - materialDisplacementMap.setValue( material.displacementMap ); - - } - - materialDisplacementScale.setValue( material.displacementScale ); - - } - - if ( material.roughnessMap !== undefined ) { - - materialRoughnessMapEnabled.setValue( material.roughnessMap !== null ); - - if ( material.roughnessMap !== null || resetTextureSelectors ) { - - materialRoughnessMap.setValue( material.roughnessMap ); - - } - - } - - if ( material.metalnessMap !== undefined ) { - - materialMetalnessMapEnabled.setValue( material.metalnessMap !== null ); - - if ( material.metalnessMap !== null || resetTextureSelectors ) { - - materialMetalnessMap.setValue( material.metalnessMap ); - - } - - } - - if ( material.specularMap !== undefined ) { - - materialSpecularMapEnabled.setValue( material.specularMap !== null ); - - if ( material.specularMap !== null || resetTextureSelectors ) { - - materialSpecularMap.setValue( material.specularMap ); - - } - - } - - if ( material.envMap !== undefined ) { - - materialEnvMapEnabled.setValue( material.envMap !== null ); - - if ( material.envMap !== null || resetTextureSelectors ) { - - materialEnvMap.setValue( material.envMap ); - - } - - } - - if ( material.reflectivity !== undefined ) { - - materialReflectivity.setValue( material.reflectivity ); - - } - - if ( material.lightMap !== undefined ) { - - materialLightMapEnabled.setValue( material.lightMap !== null ); - - if ( material.lightMap !== null || resetTextureSelectors ) { - - materialLightMap.setValue( material.lightMap ); - - } - - } - - if ( material.aoMap !== undefined ) { - - materialAOMapEnabled.setValue( material.aoMap !== null ); - - if ( material.aoMap !== null || resetTextureSelectors ) { - - materialAOMap.setValue( material.aoMap ); - - } - - materialAOScale.setValue( material.aoMapIntensity ); - - } - - if ( material.emissiveMap !== undefined ) { - - materialEmissiveMapEnabled.setValue( material.emissiveMap !== null ); - - if ( material.emissiveMap !== null || resetTextureSelectors ) { - - materialEmissiveMap.setValue( material.emissiveMap ); - - } - - } - - if ( material.side !== undefined ) { - - materialSide.setValue( material.side ); - - } - - if ( material.flatShading !== undefined ) { - - materialShading.setValue( material.flatShading ); - - } - - if ( material.blending !== undefined ) { - - materialBlending.setValue( material.blending ); - - } - - if ( material.opacity !== undefined ) { - - materialOpacity.setValue( material.opacity ); - - } - - if ( material.transparent !== undefined ) { - - materialTransparent.setValue( material.transparent ); - - } - - if ( material.alphaTest !== undefined ) { - - materialAlphaTest.setValue( material.alphaTest ); - - } - - if ( material.wireframe !== undefined ) { - - materialWireframe.setValue( material.wireframe ); - - } - - if ( material.wireframeLinewidth !== undefined ) { - - materialWireframeLinewidth.setValue( material.wireframeLinewidth ); - - } - - setRowVisibility(); - - } - - // events - - signals.objectSelected.add( function ( object ) { - - var hasMaterial = false; - - if ( object && object.material ) { - - hasMaterial = true; - - if ( Array.isArray( object.material ) && object.material.length === 0 ) { - - hasMaterial = false; - - } - - } - - if ( hasMaterial ) { - - var objectChanged = object !== currentObject; - - currentObject = object; - refreshUI( objectChanged ); - container.setDisplay( '' ); - - } else { - - currentObject = null; - container.setDisplay( 'none' ); - - } - - } ); - - signals.materialChanged.add( function () { - - refreshUI(); - - } ); - - return container; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar.Material', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Sidebar.Object = function ( editor ) { - - var signals = editor.signals; - - var container = new UI.Panel(); - container.setBorderTop( '0' ); - container.setPaddingTop( '20px' ); - container.setDisplay( 'none' ); - - // Actions - - var objectActions = new UI.Select().setPosition( 'absolute' ).setRight( '8px' ).setFontSize( '11px' ); - objectActions.setOptions( { - - 'Actions': 'Actions', - 'Reset Position': 'Reset Position', - 'Reset Rotation': 'Reset Rotation', - 'Reset Scale': 'Reset Scale' - - } ); - objectActions.onClick( function ( event ) { - - event.stopPropagation(); // Avoid panel collapsing - - } ); - objectActions.onChange( function ( event ) { - - var object = editor.selected; - - switch ( this.getValue() ) { - - case 'Reset Position': - editor.execute( new SetPositionCommand( object, new THREE.Vector3( 0, 0, 0 ) ) ); - break; - - case 'Reset Rotation': - editor.execute( new SetRotationCommand( object, new THREE.Euler( 0, 0, 0 ) ) ); - break; - - case 'Reset Scale': - editor.execute( new SetScaleCommand( object, new THREE.Vector3( 1, 1, 1 ) ) ); - break; - - } - - this.setValue( 'Actions' ); - - } ); - // container.addStatic( objectActions ); - - // type - - var objectTypeRow = new UI.Row(); - var objectType = new UI.Text(); - - objectTypeRow.add( new UI.Text( 'Type' ).setWidth( '90px' ) ); - objectTypeRow.add( objectType ); - - container.add( objectTypeRow ); - - // uuid - - var objectUUIDRow = new UI.Row(); - var objectUUID = new UI.Input().setWidth( '102px' ).setFontSize( '12px' ).setDisabled( true ); - var objectUUIDRenew = new UI.Button( 'New' ).setMarginLeft( '7px' ).onClick( function () { - - objectUUID.setValue( THREE.Math.generateUUID() ); - - editor.execute( new SetUuidCommand( editor.selected, objectUUID.getValue() ) ); - - } ); - - objectUUIDRow.add( new UI.Text( 'UUID' ).setWidth( '90px' ) ); - objectUUIDRow.add( objectUUID ); - objectUUIDRow.add( objectUUIDRenew ); - - container.add( objectUUIDRow ); - - // name - - var objectNameRow = new UI.Row(); - var objectName = new UI.Input().setWidth( '150px' ).setFontSize( '12px' ).onChange( function () { - - editor.execute( new SetValueCommand( editor.selected, 'name', objectName.getValue() ) ); - - } ); - - objectNameRow.add( new UI.Text( 'Name' ).setWidth( '90px' ) ); - objectNameRow.add( objectName ); - - container.add( objectNameRow ); - - // position - - var objectPositionRow = new UI.Row(); - var objectPositionX = new UI.Number().setWidth( '50px' ).onChange( update ); - var objectPositionY = new UI.Number().setWidth( '50px' ).onChange( update ); - var objectPositionZ = new UI.Number().setWidth( '50px' ).onChange( update ); - - objectPositionRow.add( new UI.Text( 'Position' ).setWidth( '90px' ) ); - objectPositionRow.add( objectPositionX, objectPositionY, objectPositionZ ); - - container.add( objectPositionRow ); - - // rotation - - var objectRotationRow = new UI.Row(); - var objectRotationX = new UI.Number().setStep( 10 ).setUnit( '°' ).setWidth( '50px' ).onChange( update ); - var objectRotationY = new UI.Number().setStep( 10 ).setUnit( '°' ).setWidth( '50px' ).onChange( update ); - var objectRotationZ = new UI.Number().setStep( 10 ).setUnit( '°' ).setWidth( '50px' ).onChange( update ); - - objectRotationRow.add( new UI.Text( 'Rotation' ).setWidth( '90px' ) ); - objectRotationRow.add( objectRotationX, objectRotationY, objectRotationZ ); - - container.add( objectRotationRow ); - - // scale - - var objectScaleRow = new UI.Row(); - var objectScaleLock = new UI.Checkbox( true ).setPosition( 'absolute' ).setLeft( '75px' ); - var objectScaleX = new UI.Number( 1 ).setRange( 0.01, Infinity ).setWidth( '50px' ).onChange( updateScaleX ); - var objectScaleY = new UI.Number( 1 ).setRange( 0.01, Infinity ).setWidth( '50px' ).onChange( updateScaleY ); - var objectScaleZ = new UI.Number( 1 ).setRange( 0.01, Infinity ).setWidth( '50px' ).onChange( updateScaleZ ); - - objectScaleRow.add( new UI.Text( 'Scale' ).setWidth( '90px' ) ); - objectScaleRow.add( objectScaleLock ); - objectScaleRow.add( objectScaleX, objectScaleY, objectScaleZ ); - - container.add( objectScaleRow ); - - // fov - - var objectFovRow = new UI.Row(); - var objectFov = new UI.Number().onChange( update ); - - objectFovRow.add( new UI.Text( 'Fov' ).setWidth( '90px' ) ); - objectFovRow.add( objectFov ); - - container.add( objectFovRow ); - - // near - - var objectNearRow = new UI.Row(); - var objectNear = new UI.Number().onChange( update ); - - objectNearRow.add( new UI.Text( 'Near' ).setWidth( '90px' ) ); - objectNearRow.add( objectNear ); - - container.add( objectNearRow ); - - // far - - var objectFarRow = new UI.Row(); - var objectFar = new UI.Number().onChange( update ); - - objectFarRow.add( new UI.Text( 'Far' ).setWidth( '90px' ) ); - objectFarRow.add( objectFar ); - - container.add( objectFarRow ); - - // intensity - - var objectIntensityRow = new UI.Row(); - var objectIntensity = new UI.Number().setRange( 0, Infinity ).onChange( update ); - - objectIntensityRow.add( new UI.Text( 'Intensity' ).setWidth( '90px' ) ); - objectIntensityRow.add( objectIntensity ); - - container.add( objectIntensityRow ); - - // color - - var objectColorRow = new UI.Row(); - var objectColor = new UI.Color().onChange( update ); - - objectColorRow.add( new UI.Text( 'Color' ).setWidth( '90px' ) ); - objectColorRow.add( objectColor ); - - container.add( objectColorRow ); - - // ground color - - var objectGroundColorRow = new UI.Row(); - var objectGroundColor = new UI.Color().onChange( update ); - - objectGroundColorRow.add( new UI.Text( 'Ground color' ).setWidth( '90px' ) ); - objectGroundColorRow.add( objectGroundColor ); - - container.add( objectGroundColorRow ); - - // distance - - var objectDistanceRow = new UI.Row(); - var objectDistance = new UI.Number().setRange( 0, Infinity ).onChange( update ); - - objectDistanceRow.add( new UI.Text( 'Distance' ).setWidth( '90px' ) ); - objectDistanceRow.add( objectDistance ); - - container.add( objectDistanceRow ); - - // angle - - var objectAngleRow = new UI.Row(); - var objectAngle = new UI.Number().setPrecision( 3 ).setRange( 0, Math.PI / 2 ).onChange( update ); - - objectAngleRow.add( new UI.Text( 'Angle' ).setWidth( '90px' ) ); - objectAngleRow.add( objectAngle ); - - container.add( objectAngleRow ); - - // penumbra - - var objectPenumbraRow = new UI.Row(); - var objectPenumbra = new UI.Number().setRange( 0, 1 ).onChange( update ); - - objectPenumbraRow.add( new UI.Text( 'Penumbra' ).setWidth( '90px' ) ); - objectPenumbraRow.add( objectPenumbra ); - - container.add( objectPenumbraRow ); - - // decay - - var objectDecayRow = new UI.Row(); - var objectDecay = new UI.Number().setRange( 0, Infinity ).onChange( update ); - - objectDecayRow.add( new UI.Text( 'Decay' ).setWidth( '90px' ) ); - objectDecayRow.add( objectDecay ); - - container.add( objectDecayRow ); - - // shadow - - var objectShadowRow = new UI.Row(); - - objectShadowRow.add( new UI.Text( 'Shadow' ).setWidth( '90px' ) ); - - var objectCastShadow = new UI.THREE.Boolean( false, 'cast' ).onChange( update ); - objectShadowRow.add( objectCastShadow ); - - var objectReceiveShadow = new UI.THREE.Boolean( false, 'receive' ).onChange( update ); - objectShadowRow.add( objectReceiveShadow ); - - var objectShadowRadius = new UI.Number( 1 ).onChange( update ); - objectShadowRow.add( objectShadowRadius ); - - container.add( objectShadowRow ); - - // visible - - var objectVisibleRow = new UI.Row(); - var objectVisible = new UI.Checkbox().onChange( update ); - - objectVisibleRow.add( new UI.Text( 'Visible' ).setWidth( '90px' ) ); - objectVisibleRow.add( objectVisible ); - - container.add( objectVisibleRow ); - - // user data - - var timeout; - - var objectUserDataRow = new UI.Row(); - var objectUserData = new UI.TextArea().setWidth( '150px' ).setHeight( '40px' ).setFontSize( '12px' ).onChange( update ); - objectUserData.onKeyUp( function () { - - try { - - JSON.parse( objectUserData.getValue() ); - - objectUserData.dom.classList.add( 'success' ); - objectUserData.dom.classList.remove( 'fail' ); - - } catch ( error ) { - - objectUserData.dom.classList.remove( 'success' ); - objectUserData.dom.classList.add( 'fail' ); - - } - - } ); - - objectUserDataRow.add( new UI.Text( 'User data' ).setWidth( '90px' ) ); - objectUserDataRow.add( objectUserData ); - - container.add( objectUserDataRow ); - - - // - - function updateScaleX() { - - var object = editor.selected; - - if ( objectScaleLock.getValue() === true ) { - - var scale = objectScaleX.getValue() / object.scale.x; - - objectScaleY.setValue( objectScaleY.getValue() * scale ); - objectScaleZ.setValue( objectScaleZ.getValue() * scale ); - - } - - update(); - - } - - function updateScaleY() { - - var object = editor.selected; - - if ( objectScaleLock.getValue() === true ) { - - var scale = objectScaleY.getValue() / object.scale.y; - - objectScaleX.setValue( objectScaleX.getValue() * scale ); - objectScaleZ.setValue( objectScaleZ.getValue() * scale ); - - } - - update(); - - } - - function updateScaleZ() { - - var object = editor.selected; - - if ( objectScaleLock.getValue() === true ) { - - var scale = objectScaleZ.getValue() / object.scale.z; - - objectScaleX.setValue( objectScaleX.getValue() * scale ); - objectScaleY.setValue( objectScaleY.getValue() * scale ); - - } - - update(); - - } - - function update() { - - var object = editor.selected; - - if ( object !== null ) { - - var newPosition = new THREE.Vector3( objectPositionX.getValue(), objectPositionY.getValue(), objectPositionZ.getValue() ); - if ( object.position.distanceTo( newPosition ) >= 0.01 ) { - - editor.execute( new SetPositionCommand( object, newPosition ) ); - - } - - var newRotation = new THREE.Euler( objectRotationX.getValue() * THREE.Math.DEG2RAD, objectRotationY.getValue() * THREE.Math.DEG2RAD, objectRotationZ.getValue() * THREE.Math.DEG2RAD ); - if ( object.rotation.toVector3().distanceTo( newRotation.toVector3() ) >= 0.01 ) { - - editor.execute( new SetRotationCommand( object, newRotation ) ); - - } - - var newScale = new THREE.Vector3( objectScaleX.getValue(), objectScaleY.getValue(), objectScaleZ.getValue() ); - if ( object.scale.distanceTo( newScale ) >= 0.01 ) { - - editor.execute( new SetScaleCommand( object, newScale ) ); - - } - - if ( object.fov !== undefined && Math.abs( object.fov - objectFov.getValue() ) >= 0.01 ) { - - editor.execute( new SetValueCommand( object, 'fov', objectFov.getValue() ) ); - object.updateProjectionMatrix(); - - } - - if ( object.near !== undefined && Math.abs( object.near - objectNear.getValue() ) >= 0.01 ) { - - editor.execute( new SetValueCommand( object, 'near', objectNear.getValue() ) ); - - } - - if ( object.far !== undefined && Math.abs( object.far - objectFar.getValue() ) >= 0.01 ) { - - editor.execute( new SetValueCommand( object, 'far', objectFar.getValue() ) ); - - } - - if ( object.intensity !== undefined && Math.abs( object.intensity - objectIntensity.getValue() ) >= 0.01 ) { - - editor.execute( new SetValueCommand( object, 'intensity', objectIntensity.getValue() ) ); - - } - - if ( object.color !== undefined && object.color.getHex() !== objectColor.getHexValue() ) { - - editor.execute( new SetColorCommand( object, 'color', objectColor.getHexValue() ) ); - - } - - if ( object.groundColor !== undefined && object.groundColor.getHex() !== objectGroundColor.getHexValue() ) { - - editor.execute( new SetColorCommand( object, 'groundColor', objectGroundColor.getHexValue() ) ); - - } - - if ( object.distance !== undefined && Math.abs( object.distance - objectDistance.getValue() ) >= 0.01 ) { - - editor.execute( new SetValueCommand( object, 'distance', objectDistance.getValue() ) ); - - } - - if ( object.angle !== undefined && Math.abs( object.angle - objectAngle.getValue() ) >= 0.01 ) { - - editor.execute( new SetValueCommand( object, 'angle', objectAngle.getValue() ) ); - - } - - if ( object.penumbra !== undefined && Math.abs( object.penumbra - objectPenumbra.getValue() ) >= 0.01 ) { - - editor.execute( new SetValueCommand( object, 'penumbra', objectPenumbra.getValue() ) ); - - } - - if ( object.decay !== undefined && Math.abs( object.decay - objectDecay.getValue() ) >= 0.01 ) { - - editor.execute( new SetValueCommand( object, 'decay', objectDecay.getValue() ) ); - - } - - if ( object.visible !== objectVisible.getValue() ) { - - editor.execute( new SetValueCommand( object, 'visible', objectVisible.getValue() ) ); - - } - - if ( object.castShadow !== undefined && object.castShadow !== objectCastShadow.getValue() ) { - - editor.execute( new SetValueCommand( object, 'castShadow', objectCastShadow.getValue() ) ); - - } - - if ( object.receiveShadow !== undefined && object.receiveShadow !== objectReceiveShadow.getValue() ) { - - editor.execute( new SetValueCommand( object, 'receiveShadow', objectReceiveShadow.getValue() ) ); - object.material.needsUpdate = true; - - } - - if ( object.shadow !== undefined ) { - - if ( object.shadow.radius !== objectShadowRadius.getValue() ) { - - editor.execute( new SetValueCommand( object.shadow, 'radius', objectShadowRadius.getValue() ) ); - - } - - } - - try { - - var userData = JSON.parse( objectUserData.getValue() ); - if ( JSON.stringify( object.userData ) != JSON.stringify( userData ) ) { - - editor.execute( new SetValueCommand( object, 'userData', userData ) ); - - } - - } catch ( exception ) { - - console.warn( exception ); - - } - - } - - } - - function updateRows( object ) { - - var properties = { - 'fov': objectFovRow, - 'near': objectNearRow, - 'far': objectFarRow, - 'intensity': objectIntensityRow, - 'color': objectColorRow, - 'groundColor': objectGroundColorRow, - 'distance' : objectDistanceRow, - 'angle' : objectAngleRow, - 'penumbra' : objectPenumbraRow, - 'decay' : objectDecayRow, - 'castShadow' : objectShadowRow, - 'receiveShadow' : objectReceiveShadow, - 'shadow': objectShadowRadius - }; - - for ( var property in properties ) { - - properties[ property ].setDisplay( object[ property ] !== undefined ? '' : 'none' ); - - } - - } - - function updateTransformRows( object ) { - - if ( object instanceof THREE.Light || - ( object instanceof THREE.Object3D && object.userData.targetInverse ) ) { - - objectRotationRow.setDisplay( 'none' ); - objectScaleRow.setDisplay( 'none' ); - - } else { - - objectRotationRow.setDisplay( '' ); - objectScaleRow.setDisplay( '' ); - - } - - } - - // events - - signals.objectSelected.add( function ( object ) { - - if ( object !== null ) { - - container.setDisplay( 'block' ); - - updateRows( object ); - updateUI( object ); - - } else { - - container.setDisplay( 'none' ); - - } - - } ); - - signals.objectChanged.add( function ( object ) { - - if ( object !== editor.selected ) return; - - updateUI( object ); - - } ); - - signals.refreshSidebarObject3D.add( function ( object ) { - - if ( object !== editor.selected ) return; - - updateUI( object ); - - } ); - - function updateUI( object ) { - - objectType.setValue( object.type ); - - objectUUID.setValue( object.uuid ); - objectName.setValue( object.name ); - - objectPositionX.setValue( object.position.x ); - objectPositionY.setValue( object.position.y ); - objectPositionZ.setValue( object.position.z ); - - objectRotationX.setValue( object.rotation.x * THREE.Math.RAD2DEG ); - objectRotationY.setValue( object.rotation.y * THREE.Math.RAD2DEG ); - objectRotationZ.setValue( object.rotation.z * THREE.Math.RAD2DEG ); - - objectScaleX.setValue( object.scale.x ); - objectScaleY.setValue( object.scale.y ); - objectScaleZ.setValue( object.scale.z ); - - if ( object.fov !== undefined ) { - - objectFov.setValue( object.fov ); - - } - - if ( object.near !== undefined ) { - - objectNear.setValue( object.near ); - - } - - if ( object.far !== undefined ) { - - objectFar.setValue( object.far ); - - } - - if ( object.intensity !== undefined ) { - - objectIntensity.setValue( object.intensity ); - - } - - if ( object.color !== undefined ) { - - objectColor.setHexValue( object.color.getHexString() ); - - } - - if ( object.groundColor !== undefined ) { - - objectGroundColor.setHexValue( object.groundColor.getHexString() ); - - } - - if ( object.distance !== undefined ) { - - objectDistance.setValue( object.distance ); - - } - - if ( object.angle !== undefined ) { - - objectAngle.setValue( object.angle ); - - } - - if ( object.penumbra !== undefined ) { - - objectPenumbra.setValue( object.penumbra ); - - } - - if ( object.decay !== undefined ) { - - objectDecay.setValue( object.decay ); - - } - - if ( object.castShadow !== undefined ) { - - objectCastShadow.setValue( object.castShadow ); - - } - - if ( object.receiveShadow !== undefined ) { - - objectReceiveShadow.setValue( object.receiveShadow ); - - } - - if ( object.shadow !== undefined ) { - - objectShadowRadius.setValue( object.shadow.radius ); - - } - - objectVisible.setValue( object.visible ); - - try { - - objectUserData.setValue( JSON.stringify( object.userData, null, ' ' ) ); - - } catch ( error ) { - - console.log( error ); - - } - - objectUserData.setBorderColor( 'transparent' ); - objectUserData.setBackgroundColor( '' ); - - updateTransformRows( object ); - - } - - return container; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar.Object', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Sidebar.Project = function ( editor ) { - - var config = editor.config; - var signals = editor.signals; - - var rendererTypes = { - - 'WebGLRenderer': THREE.WebGLRenderer, - 'CanvasRenderer': THREE.CanvasRenderer, - 'SVGRenderer': THREE.SVGRenderer, - 'SoftwareRenderer': THREE.SoftwareRenderer, - 'RaytracingRenderer': THREE.RaytracingRenderer - - }; - - var container = new UI.Panel(); - container.setBorderTop( '0' ); - container.setPaddingTop( '20px' ); - - // class - - var options = {}; - - for ( var key in rendererTypes ) { - - if ( key.indexOf( 'WebGL' ) >= 0 && System.support.webgl === false ) continue; - - options[ key ] = key; - - } - - var rendererTypeRow = new UI.Row(); - var rendererType = new UI.Select().setOptions( options ).setWidth( '150px' ).onChange( function () { - - var value = this.getValue(); - - config.setKey( 'project/renderer', value ); - - updateRenderer(); - - } ); - - rendererTypeRow.add( new UI.Text( 'Renderer' ).setWidth( '90px' ) ); - rendererTypeRow.add( rendererType ); - - container.add( rendererTypeRow ); - - if ( config.getKey( 'project/renderer' ) !== undefined ) { - - rendererType.setValue( config.getKey( 'project/renderer' ) ); - - } - - // antialiasing - - var rendererPropertiesRow = new UI.Row().setMarginLeft( '90px' ); - - var rendererAntialias = new UI.THREE.Boolean( config.getKey( 'project/renderer/antialias' ), 'antialias' ).onChange( function () { - - config.setKey( 'project/renderer/antialias', this.getValue() ); - updateRenderer(); - - } ); - rendererPropertiesRow.add( rendererAntialias ); - - // shadow - - var rendererShadows = new UI.THREE.Boolean( config.getKey( 'project/renderer/shadows' ), 'shadows' ).onChange( function () { - - config.setKey( 'project/renderer/shadows', this.getValue() ); - updateRenderer(); - - } ); - rendererPropertiesRow.add( rendererShadows ); - - rendererPropertiesRow.add( new UI.Break() ); - - // gamma input - - var rendererGammaInput = new UI.THREE.Boolean( config.getKey( 'project/renderer/gammaInput' ), 'γ input' ).onChange( function () { - - config.setKey( 'project/renderer/gammaInput', this.getValue() ); - updateRenderer(); - - } ); - rendererPropertiesRow.add( rendererGammaInput ); - - // gamma output - - var rendererGammaOutput = new UI.THREE.Boolean( config.getKey( 'project/renderer/gammaOutput' ), 'γ output' ).onChange( function () { - - config.setKey( 'project/renderer/gammaOutput', this.getValue() ); - updateRenderer(); - - } ); - rendererPropertiesRow.add( rendererGammaOutput ); - - container.add( rendererPropertiesRow ); - - // Editable - - var editableRow = new UI.Row(); - var editable = new UI.Checkbox( config.getKey( 'project/editable' ) ).setLeft( '100px' ).onChange( function () { - - config.setKey( 'project/editable', this.getValue() ); - - } ); - - editableRow.add( new UI.Text( 'Editable' ).setWidth( '90px' ) ); - editableRow.add( editable ); - - container.add( editableRow ); - - // VR - - var vrRow = new UI.Row(); - var vr = new UI.Checkbox( config.getKey( 'project/vr' ) ).setLeft( '100px' ).onChange( function () { - - config.setKey( 'project/vr', this.getValue() ); - - } ); - - vrRow.add( new UI.Text( 'VR' ).setWidth( '90px' ) ); - vrRow.add( vr ); - - container.add( vrRow ); - - // - - function updateRenderer() { - - createRenderer( rendererType.getValue(), rendererAntialias.getValue(), rendererShadows.getValue(), rendererGammaInput.getValue(), rendererGammaOutput.getValue() ); - - } - - function createRenderer( type, antialias, shadows, gammaIn, gammaOut ) { - - if ( type === 'WebGLRenderer' && System.support.webgl === false ) { - - type = 'CanvasRenderer'; - - } - - rendererPropertiesRow.setDisplay( type === 'WebGLRenderer' ? '' : 'none' ); - - var renderer = new rendererTypes[ type ]( { antialias: antialias} ); - renderer.gammaInput = gammaIn; - renderer.gammaOutput = gammaOut; - if ( shadows && renderer.shadowMap ) { - - renderer.shadowMap.enabled = true; - // renderer.shadowMap.type = THREE.PCFSoftShadowMap; - - } - - signals.rendererChanged.dispatch( renderer ); - - } - - createRenderer( config.getKey( 'project/renderer' ), config.getKey( 'project/renderer/antialias' ), config.getKey( 'project/renderer/shadows' ), config.getKey( 'project/renderer/gammaInput' ), config.getKey( 'project/renderer/gammaOutput' ) ); - - return container; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar.Project', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Sidebar.Properties = function ( editor ) { - - var signals = editor.signals; - - var container = new UI.Span(); - - var objectTab = new UI.Text( 'OBJECT' ).onClick( onClick ); - var geometryTab = new UI.Text( 'GEOMETRY' ).onClick( onClick ); - var materialTab = new UI.Text( 'MATERIAL' ).onClick( onClick ); - - var tabs = new UI.Div(); - tabs.setId( 'tabs' ); - tabs.add( objectTab, geometryTab, materialTab ); - container.add( tabs ); - - function onClick( event ) { - - select( event.target.textContent ); - - } - - // - - var object = new UI.Span().add( - new Sidebar.Object( editor ) - ); - container.add( object ); - - var geometry = new UI.Span().add( - new Sidebar.Geometry( editor ) - ); - container.add( geometry ); - - var material = new UI.Span().add( - new Sidebar.Material( editor ) - ); - container.add( material ); - - // - - function select( section ) { - - objectTab.setClass( '' ); - geometryTab.setClass( '' ); - materialTab.setClass( '' ); - - object.setDisplay( 'none' ); - geometry.setDisplay( 'none' ); - material.setDisplay( 'none' ); - - switch ( section ) { - case 'OBJECT': - objectTab.setClass( 'selected' ); - object.setDisplay( '' ); - break; - case 'GEOMETRY': - geometryTab.setClass( 'selected' ); - geometry.setDisplay( '' ); - break; - case 'MATERIAL': - materialTab.setClass( 'selected' ); - material.setDisplay( '' ); - break; - } - - } - - select( 'OBJECT' ); - - return container; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar.Properties', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Sidebar.Scene = function ( editor ) { - - var signals = editor.signals; - - var container = new UI.Panel(); - container.setBorderTop( '0' ); - container.setPaddingTop( '20px' ); - - // outliner - - function buildOption( object, draggable ) { - - var option = document.createElement( 'div' ); - option.draggable = draggable; - option.innerHTML = buildHTML( object ); - option.value = object.id; - - return option; - - } - - function getMaterialName( material ) { - - if ( Array.isArray( material ) ) { - - var array = []; - - for ( var i = 0; i < material.length; i ++ ) { - - array.push( material[ i ].name ); - - } - - return array.join( ',' ); - - } - - return material.name; - - } - - function buildHTML( object ) { - - var html = ' ' + object.name; - - if ( object instanceof THREE.Mesh ) { - - var geometry = object.geometry; - var material = object.material; - - html += ' ' + geometry.name; - html += ' ' + getMaterialName( material ); - - } - - html += getScript( object.uuid ); - - return html; - - } - - function getScript( uuid ) { - - if ( editor.scripts[ uuid ] !== undefined ) { - - return ' '; - - } - - return ''; - - } - - var ignoreObjectSelectedSignal = false; - - var outliner = new UI.Outliner( editor ); - outliner.setId( 'outliner' ); - outliner.onChange( function () { - - ignoreObjectSelectedSignal = true; - - editor.selectById( parseInt( outliner.getValue() ) ); - - ignoreObjectSelectedSignal = false; - - } ); - outliner.onDblClick( function () { - - editor.focusById( parseInt( outliner.getValue() ) ); - - } ); - container.add( outliner ); - container.add( new UI.Break() ); - - // background - - function onBackgroundChanged() { - - signals.sceneBackgroundChanged.dispatch( backgroundColor.getHexValue() ); - - } - - var backgroundRow = new UI.Row(); - - var backgroundColor = new UI.Color().setValue( '#aaaaaa' ).onChange( onBackgroundChanged ); - - backgroundRow.add( new UI.Text( 'Background' ).setWidth( '90px' ) ); - backgroundRow.add( backgroundColor ); - - container.add( backgroundRow ); - - // fog - - function onFogChanged() { - - signals.sceneFogChanged.dispatch( - fogType.getValue(), - fogColor.getHexValue(), - fogNear.getValue(), - fogFar.getValue(), - fogDensity.getValue() - ); - - } - - var fogTypeRow = new UI.Row(); - var fogType = new UI.Select().setOptions( { - - 'None': 'None', - 'Fog': 'Linear', - 'FogExp2': 'Exponential' - - } ).setWidth( '150px' ); - fogType.onChange( function () { - - onFogChanged(); - refreshFogUI(); - - } ); - - fogTypeRow.add( new UI.Text( 'Fog' ).setWidth( '90px' ) ); - fogTypeRow.add( fogType ); - - container.add( fogTypeRow ); - - // fog color - - var fogPropertiesRow = new UI.Row(); - fogPropertiesRow.setDisplay( 'none' ); - fogPropertiesRow.setMarginLeft( '90px' ); - container.add( fogPropertiesRow ); - - var fogColor = new UI.Color().setValue( '#aaaaaa' ); - fogColor.onChange( onFogChanged ); - fogPropertiesRow.add( fogColor ); - - // fog near - - var fogNear = new UI.Number( 0.1 ).setWidth( '40px' ).setRange( 0, Infinity ).onChange( onFogChanged ); - fogPropertiesRow.add( fogNear ); - - // fog far - - var fogFar = new UI.Number( 50 ).setWidth( '40px' ).setRange( 0, Infinity ).onChange( onFogChanged ); - fogPropertiesRow.add( fogFar ); - - // fog density - - var fogDensity = new UI.Number( 0.05 ).setWidth( '40px' ).setRange( 0, 0.1 ).setPrecision( 3 ).onChange( onFogChanged ); - fogPropertiesRow.add( fogDensity ); - - // - - function refreshUI() { - - var camera = editor.camera; - var scene = editor.scene; - - var options = []; - - options.push( buildOption( camera, false ) ); - options.push( buildOption( scene, false ) ); - - ( function addObjects( objects, pad ) { - - for ( var i = 0, l = objects.length; i < l; i ++ ) { - - var object = objects[ i ]; - - var option = buildOption( object, true ); - option.style.paddingLeft = ( pad * 10 ) + 'px'; - options.push( option ); - - addObjects( object.children, pad + 1 ); - - } - - } )( scene.children, 1 ); - - outliner.setOptions( options ); - - if ( editor.selected !== null ) { - - outliner.setValue( editor.selected.id ); - - } - - if ( scene.background ) { - - backgroundColor.setHexValue( scene.background.getHex() ); - - } - - if ( scene.fog ) { - - fogColor.setHexValue( scene.fog.color.getHex() ); - - if ( scene.fog instanceof THREE.Fog ) { - - fogType.setValue( "Fog" ); - fogNear.setValue( scene.fog.near ); - fogFar.setValue( scene.fog.far ); - - } else if ( scene.fog instanceof THREE.FogExp2 ) { - - fogType.setValue( "FogExp2" ); - fogDensity.setValue( scene.fog.density ); - - } - - } else { - - fogType.setValue( "None" ); - - } - - refreshFogUI(); - - } - - function refreshFogUI() { - - var type = fogType.getValue(); - - fogPropertiesRow.setDisplay( type === 'None' ? 'none' : '' ); - fogNear.setDisplay( type === 'Fog' ? '' : 'none' ); - fogFar.setDisplay( type === 'Fog' ? '' : 'none' ); - fogDensity.setDisplay( type === 'FogExp2' ? '' : 'none' ); - - } - - refreshUI(); - - // events - - signals.editorCleared.add( refreshUI ); - - signals.sceneGraphChanged.add( refreshUI ); - - signals.objectChanged.add( function ( object ) { - - var options = outliner.options; - - for ( var i = 0; i < options.length; i ++ ) { - - var option = options[ i ]; - - if ( option.value === object.id ) { - - option.innerHTML = buildHTML( object ); - return; - - } - - } - - } ); - - signals.objectSelected.add( function ( object ) { - - if ( ignoreObjectSelectedSignal === true ) return; - - outliner.setValue( object !== null ? object.id : null ); - - } ); - - return container; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar.Scene', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Sidebar.Script = function ( editor ) { - - var signals = editor.signals; - - var container = new UI.Panel(); - container.setDisplay( 'none' ); - - container.add( new UI.Text( 'Script' ).setTextTransform( 'uppercase' ) ); - container.add( new UI.Break() ); - container.add( new UI.Break() ); - - // - - var scriptsContainer = new UI.Row(); - container.add( scriptsContainer ); - - var newScript = new UI.Button( 'New' ); - newScript.onClick( function () { - - var script = { name: '', source: 'function update( event ) {}' }; - editor.execute( new AddScriptCommand( editor.selected, script ) ); - - } ); - container.add( newScript ); - - /* - var loadScript = new UI.Button( 'Load' ); - loadScript.setMarginLeft( '4px' ); - container.add( loadScript ); - */ - - // - - function update() { - - scriptsContainer.clear(); - scriptsContainer.setDisplay( 'none' ); - - var object = editor.selected; - - if ( object === null ) { - - return; - - } - - var scripts = editor.scripts[ object.uuid ]; - - if ( scripts !== undefined ) { - - scriptsContainer.setDisplay( 'block' ); - - for ( var i = 0; i < scripts.length; i ++ ) { - - ( function ( object, script ) { - - var name = new UI.Input( script.name ).setWidth( '130px' ).setFontSize( '12px' ); - name.onChange( function () { - - editor.execute( new SetScriptValueCommand( editor.selected, script, 'name', this.getValue() ) ); - - } ); - scriptsContainer.add( name ); - - var edit = new UI.Button( 'Edit' ); - edit.setMarginLeft( '4px' ); - edit.onClick( function () { - - signals.editScript.dispatch( object, script ); - - } ); - scriptsContainer.add( edit ); - - var remove = new UI.Button( 'Remove' ); - remove.setMarginLeft( '4px' ); - remove.onClick( function () { - - if ( confirm( 'Are you sure?' ) ) { - - editor.execute( new RemoveScriptCommand( editor.selected, script ) ); - - } - - } ); - scriptsContainer.add( remove ); - - scriptsContainer.add( new UI.Break() ); - - } )( object, scripts[ i ] ); - - } - - } - - } - - // signals - - signals.objectSelected.add( function ( object ) { - - if ( object !== null && editor.camera !== object ) { - - container.setDisplay( 'block' ); - - update(); - - } else { - - container.setDisplay( 'none' ); - - } - - } ); - - signals.scriptAdded.add( update ); - signals.scriptRemoved.add( update ); - signals.scriptChanged.add( update ); - - return container; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar.Script', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Sidebar.Settings = function ( editor ) { - - var config = editor.config; - var signals = editor.signals; - - var container = new UI.Panel(); - container.setBorderTop( '0' ); - container.setPaddingTop( '20px' ); - - // class - - var options = { - 'css/light.css': 'light', - 'css/dark.css': 'dark' - }; - - var themeRow = new UI.Row(); - var theme = new UI.Select().setWidth( '150px' ); - theme.setOptions( options ); - - if ( config.getKey( 'theme' ) !== undefined ) { - - theme.setValue( config.getKey( 'theme' ) ); - - } - - theme.onChange( function () { - - var value = this.getValue(); - - editor.setTheme( value ); - editor.config.setKey( 'theme', value ); - - } ); - - themeRow.add( new UI.Text( 'Theme' ).setWidth( '90px' ) ); - themeRow.add( theme ); - - container.add( themeRow ); - - return container; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Sidebar.Settings', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Storage', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Toolbar', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Viewport', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - Viewport.Info = function ( editor ) { - - var signals = editor.signals; - - var container = new UI.Panel(); - container.setId( 'info' ); - container.setPosition( 'absolute' ); - container.setLeft( '10px' ); - container.setBottom( '10px' ); - container.setFontSize( '12px' ); - container.setColor( '#fff' ); - - var objectsText = new UI.Text( '0' ).setMarginLeft( '6px' ); - var verticesText = new UI.Text( '0' ).setMarginLeft( '6px' ); - var trianglesText = new UI.Text( '0' ).setMarginLeft( '6px' ); - - container.add( new UI.Text( 'objects' ), objectsText, new UI.Break() ); - container.add( new UI.Text( 'vertices' ), verticesText, new UI.Break() ); - container.add( new UI.Text( 'triangles' ), trianglesText, new UI.Break() ); - - signals.objectAdded.add( update ); - signals.objectRemoved.add( update ); - signals.geometryChanged.add( update ); - - // - - function update() { - - var scene = editor.scene; - - var objects = 0, vertices = 0, triangles = 0; - - for ( var i = 0, l = scene.children.length; i < l; i ++ ) { - - var object = scene.children[ i ]; - - object.traverseVisible( function ( object ) { - - objects ++; - - if ( object instanceof THREE.Mesh ) { - - var geometry = object.geometry; - - if ( geometry instanceof THREE.Geometry ) { - - vertices += geometry.vertices.length; - triangles += geometry.faces.length; - - } else if ( geometry instanceof THREE.BufferGeometry ) { - - if ( geometry.index !== null ) { - - vertices += geometry.index.count * 3; - triangles += geometry.index.count; - - } else { - - vertices += geometry.attributes.position.count; - triangles += geometry.attributes.position.count / 3; - - } - - } - - } - - } ); - - } - - objectsText.setValue( objects.format() ); - verticesText.setValue( vertices.format() ); - trianglesText.setValue( triangles.format() ); - - } - - return container; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module.todo( 'Viewport.Info', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author dforrer / https://github.com/dforrer - * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch) - */ - - /** - * @param object THREE.Object3D - * @constructor - */ - - var AddObjectCommand$1 = function ( object ) { - - Command.call( this ); - - this.type = 'AddObjectCommand'; - - this.object = object; - if ( object !== undefined ) { - - this.name = 'Add Object: ' + object.name; - - } - - }; - - AddObjectCommand$1.prototype = { - - execute: function () { - - this.editor.addObject( this.object ); - this.editor.select( this.object ); - - }, - - undo: function () { - - this.editor.removeObject( this.object ); - this.editor.deselect(); - - }, - - toJSON: function () { - - var output = Command.prototype.toJSON.call( this ); - output.object = this.object.toJSON(); - - return output; - - }, - - fromJSON: function ( json ) { - - Command.prototype.fromJSON.call( this, json ); - - this.object = this.editor.objectByUuid( json.object.object.uuid ); - - if ( this.object === undefined ) { - - var loader = new THREE.ObjectLoader(); - this.object = loader.parse( json.object ); - - } - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module( 'Commands', () => { - - QUnit.module.todo( 'AddObjectCommand', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author dforrer / https://github.com/dforrer - * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch) - */ - - /** - * @param object THREE.Object3D - * @param script javascript object - * @constructor - */ - - var AddScriptCommand$1 = function ( object, script ) { - - Command.call( this ); - - this.type = 'AddScriptCommand'; - this.name = 'Add Script'; - - this.object = object; - this.script = script; - - }; - - AddScriptCommand$1.prototype = { - - execute: function () { - - if ( this.editor.scripts[ this.object.uuid ] === undefined ) { - - this.editor.scripts[ this.object.uuid ] = []; - - } - - this.editor.scripts[ this.object.uuid ].push( this.script ); - - this.editor.signals.scriptAdded.dispatch( this.script ); - - }, - - undo: function () { - - if ( this.editor.scripts[ this.object.uuid ] === undefined ) return; - - var index = this.editor.scripts[ this.object.uuid ].indexOf( this.script ); - - if ( index !== - 1 ) { - - this.editor.scripts[ this.object.uuid ].splice( index, 1 ); - - } - - this.editor.signals.scriptRemoved.dispatch( this.script ); - - }, - - toJSON: function () { - - var output = Command.prototype.toJSON.call( this ); - - output.objectUuid = this.object.uuid; - output.script = this.script; - - return output; - - }, - - fromJSON: function ( json ) { - - Command.prototype.fromJSON.call( this, json ); - - this.script = json.script; - this.object = this.editor.objectByUuid( json.objectUuid ); - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module( 'Commands', () => { - - QUnit.module.todo( 'AddScriptCommand', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author dforrer / https://github.com/dforrer - * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch) - */ - - /** - * @param object THREE.Object3D - * @param newParent THREE.Object3D - * @param newBefore THREE.Object3D - * @constructor - */ - - var MoveObjectCommand = function ( object, newParent, newBefore ) { - - Command.call( this ); - - this.type = 'MoveObjectCommand'; - this.name = 'Move Object'; - - this.object = object; - this.oldParent = ( object !== undefined ) ? object.parent : undefined; - this.oldIndex = ( this.oldParent !== undefined ) ? this.oldParent.children.indexOf( this.object ) : undefined; - this.newParent = newParent; - - if ( newBefore !== undefined ) { - - this.newIndex = ( newParent !== undefined ) ? newParent.children.indexOf( newBefore ) : undefined; - - } else { - - this.newIndex = ( newParent !== undefined ) ? newParent.children.length : undefined; - - } - - if ( this.oldParent === this.newParent && this.newIndex > this.oldIndex ) { - - this.newIndex --; - - } - - this.newBefore = newBefore; - - }; - - MoveObjectCommand.prototype = { - - execute: function () { - - this.oldParent.remove( this.object ); - - var children = this.newParent.children; - children.splice( this.newIndex, 0, this.object ); - this.object.parent = this.newParent; - - this.editor.signals.sceneGraphChanged.dispatch(); - - }, - - undo: function () { - - this.newParent.remove( this.object ); - - var children = this.oldParent.children; - children.splice( this.oldIndex, 0, this.object ); - this.object.parent = this.oldParent; - - this.editor.signals.sceneGraphChanged.dispatch(); - - }, - - toJSON: function () { - - var output = Command.prototype.toJSON.call( this ); - - output.objectUuid = this.object.uuid; - output.newParentUuid = this.newParent.uuid; - output.oldParentUuid = this.oldParent.uuid; - output.newIndex = this.newIndex; - output.oldIndex = this.oldIndex; - - return output; - - }, - - fromJSON: function ( json ) { - - Command.prototype.fromJSON.call( this, json ); - - this.object = this.editor.objectByUuid( json.objectUuid ); - this.oldParent = this.editor.objectByUuid( json.oldParentUuid ); - if ( this.oldParent === undefined ) { - - this.oldParent = this.editor.scene; - - } - this.newParent = this.editor.objectByUuid( json.newParentUuid ); - if ( this.newParent === undefined ) { - - this.newParent = this.editor.scene; - - } - this.newIndex = json.newIndex; - this.oldIndex = json.oldIndex; - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module( 'Commands', () => { - - QUnit.module.todo( 'MoveObjectCommand', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author dforrer / https://github.com/dforrer - * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch) - */ - - /** - * @param cmdArray array containing command objects - * @constructor - */ - - var MultiCmdsCommand$1 = function ( cmdArray ) { - - Command.call( this ); - - this.type = 'MultiCmdsCommand'; - this.name = 'Multiple Changes'; - - this.cmdArray = ( cmdArray !== undefined ) ? cmdArray : []; - - }; - - MultiCmdsCommand$1.prototype = { - - execute: function () { - - this.editor.signals.sceneGraphChanged.active = false; - - for ( var i = 0; i < this.cmdArray.length; i ++ ) { - - this.cmdArray[ i ].execute(); - - } - - this.editor.signals.sceneGraphChanged.active = true; - this.editor.signals.sceneGraphChanged.dispatch(); - - }, - - undo: function () { - - this.editor.signals.sceneGraphChanged.active = false; - - for ( var i = this.cmdArray.length - 1; i >= 0; i -- ) { - - this.cmdArray[ i ].undo(); - - } - - this.editor.signals.sceneGraphChanged.active = true; - this.editor.signals.sceneGraphChanged.dispatch(); - - }, - - toJSON: function () { - - var output = Command.prototype.toJSON.call( this ); - - var cmds = []; - for ( var i = 0; i < this.cmdArray.length; i ++ ) { - - cmds.push( this.cmdArray[ i ].toJSON() ); - - } - output.cmds = cmds; - - return output; - - }, - - fromJSON: function ( json ) { - - Command.prototype.fromJSON.call( this, json ); - - var cmds = json.cmds; - for ( var i = 0; i < cmds.length; i ++ ) { - - var cmd = new window[ cmds[ i ].type ](); // creates a new object of type "json.type" - cmd.fromJSON( cmds[ i ] ); - this.cmdArray.push( cmd ); - - } - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module( 'Commands', () => { - - QUnit.module.todo( 'MultiCmdsCommand', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author dforrer / https://github.com/dforrer - * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch) - */ - - /** - * @param object THREE.Object3D - * @constructor - */ - - var RemoveObjectCommand$1 = function ( object ) { - - Command.call( this ); - - this.type = 'RemoveObjectCommand'; - this.name = 'Remove Object'; - - this.object = object; - this.parent = ( object !== undefined ) ? object.parent : undefined; - if ( this.parent !== undefined ) { - - this.index = this.parent.children.indexOf( this.object ); - - } - - }; - - RemoveObjectCommand$1.prototype = { - - execute: function () { - - var scope = this.editor; - this.object.traverse( function ( child ) { - - scope.removeHelper( child ); - - } ); - - this.parent.remove( this.object ); - this.editor.select( this.parent ); - - this.editor.signals.objectRemoved.dispatch( this.object ); - this.editor.signals.sceneGraphChanged.dispatch(); - - }, - - undo: function () { - - var scope = this.editor; - - this.object.traverse( function ( child ) { - - if ( child.geometry !== undefined ) scope.addGeometry( child.geometry ); - if ( child.material !== undefined ) scope.addMaterial( child.material ); - - scope.addHelper( child ); - - } ); - - this.parent.children.splice( this.index, 0, this.object ); - this.object.parent = this.parent; - this.editor.select( this.object ); - - this.editor.signals.objectAdded.dispatch( this.object ); - this.editor.signals.sceneGraphChanged.dispatch(); - - }, - - toJSON: function () { - - var output = Command.prototype.toJSON.call( this ); - output.object = this.object.toJSON(); - output.index = this.index; - output.parentUuid = this.parent.uuid; - - return output; - - }, - - fromJSON: function ( json ) { - - Command.prototype.fromJSON.call( this, json ); - - this.parent = this.editor.objectByUuid( json.parentUuid ); - if ( this.parent === undefined ) { - - this.parent = this.editor.scene; - - } - - this.index = json.index; - - this.object = this.editor.objectByUuid( json.object.object.uuid ); - if ( this.object === undefined ) { - - var loader = new THREE.ObjectLoader(); - this.object = loader.parse( json.object ); - - } - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module( 'Commands', () => { - - QUnit.module.todo( 'RemoveObjectCommand', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author dforrer / https://github.com/dforrer - * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch) - */ - - /** - * @param object THREE.Object3D - * @param script javascript object - * @constructor - */ - - var RemoveScriptCommand$1 = function ( object, script ) { - - Command.call( this ); - - this.type = 'RemoveScriptCommand'; - this.name = 'Remove Script'; - - this.object = object; - this.script = script; - if ( this.object && this.script ) { - - this.index = this.editor.scripts[ this.object.uuid ].indexOf( this.script ); - - } - - }; - - RemoveScriptCommand$1.prototype = { - - execute: function () { - - if ( this.editor.scripts[ this.object.uuid ] === undefined ) return; - - if ( this.index !== - 1 ) { - - this.editor.scripts[ this.object.uuid ].splice( this.index, 1 ); - - } - - this.editor.signals.scriptRemoved.dispatch( this.script ); - - }, - - undo: function () { - - if ( this.editor.scripts[ this.object.uuid ] === undefined ) { - - this.editor.scripts[ this.object.uuid ] = []; - - } - - this.editor.scripts[ this.object.uuid ].splice( this.index, 0, this.script ); - - this.editor.signals.scriptAdded.dispatch( this.script ); - - }, - - toJSON: function () { - - var output = Command.prototype.toJSON.call( this ); - - output.objectUuid = this.object.uuid; - output.script = this.script; - output.index = this.index; - - return output; - - }, - - fromJSON: function ( json ) { - - Command.prototype.fromJSON.call( this, json ); - - this.script = json.script; - this.index = json.index; - this.object = this.editor.objectByUuid( json.objectUuid ); - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module( 'Commands', () => { - - QUnit.module.todo( 'RemoveScriptCommand', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author dforrer / https://github.com/dforrer - * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch) - */ - - /** - * @param object THREE.Object3D - * @param attributeName string - * @param newValue integer representing a hex color value - * @constructor - */ - - var SetColorCommand$1 = function ( object, attributeName, newValue ) { - - Command.call( this ); - - this.type = 'SetColorCommand'; - this.name = 'Set ' + attributeName; - this.updatable = true; - - this.object = object; - this.attributeName = attributeName; - this.oldValue = ( object !== undefined ) ? this.object[ this.attributeName ].getHex() : undefined; - this.newValue = newValue; - - }; - - SetColorCommand$1.prototype = { - - execute: function () { - - this.object[ this.attributeName ].setHex( this.newValue ); - this.editor.signals.objectChanged.dispatch( this.object ); - - }, - - undo: function () { - - this.object[ this.attributeName ].setHex( this.oldValue ); - this.editor.signals.objectChanged.dispatch( this.object ); - - }, - - update: function ( cmd ) { - - this.newValue = cmd.newValue; - - }, - - toJSON: function () { - - var output = Command.prototype.toJSON.call( this ); - - output.objectUuid = this.object.uuid; - output.attributeName = this.attributeName; - output.oldValue = this.oldValue; - output.newValue = this.newValue; - - return output; - - }, - - fromJSON: function ( json ) { - - Command.prototype.fromJSON.call( this, json ); - - this.object = this.editor.objectByUuid( json.objectUuid ); - this.attributeName = json.attributeName; - this.oldValue = json.oldValue; - this.newValue = json.newValue; - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module( 'Commands', () => { - - QUnit.module.todo( 'SetColorCommand', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author dforrer / https://github.com/dforrer - * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch) - */ - - /** - * @param object THREE.Object3D - * @param newGeometry THREE.Geometry - * @constructor - */ - - var SetGeometryCommand$1 = function ( object, newGeometry ) { - - Command.call( this ); - - this.type = 'SetGeometryCommand'; - this.name = 'Set Geometry'; - this.updatable = true; - - this.object = object; - this.oldGeometry = ( object !== undefined ) ? object.geometry : undefined; - this.newGeometry = newGeometry; - - }; - - SetGeometryCommand$1.prototype = { - - execute: function () { - - this.object.geometry.dispose(); - this.object.geometry = this.newGeometry; - this.object.geometry.computeBoundingSphere(); - - this.editor.signals.geometryChanged.dispatch( this.object ); - this.editor.signals.sceneGraphChanged.dispatch(); - - }, - - undo: function () { - - this.object.geometry.dispose(); - this.object.geometry = this.oldGeometry; - this.object.geometry.computeBoundingSphere(); - - this.editor.signals.geometryChanged.dispatch( this.object ); - this.editor.signals.sceneGraphChanged.dispatch(); - - }, - - update: function ( cmd ) { - - this.newGeometry = cmd.newGeometry; - - }, - - toJSON: function () { - - var output = Command.prototype.toJSON.call( this ); - - output.objectUuid = this.object.uuid; - output.oldGeometry = this.object.geometry.toJSON(); - output.newGeometry = this.newGeometry.toJSON(); - - return output; - - }, - - fromJSON: function ( json ) { - - Command.prototype.fromJSON.call( this, json ); - - this.object = this.editor.objectByUuid( json.objectUuid ); - - this.oldGeometry = parseGeometry( json.oldGeometry ); - this.newGeometry = parseGeometry( json.newGeometry ); - - function parseGeometry ( data ) { - - var loader = new THREE.ObjectLoader(); - return loader.parseGeometries( [ data ] )[ data.uuid ]; - - } - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module( 'Commands', () => { - - QUnit.module.todo( 'SetGeometryCommand', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author dforrer / https://github.com/dforrer - * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch) - */ - - /** - * @param object THREE.Object3D - * @param attributeName string - * @param newValue number, string, boolean or object - * @constructor - */ - - var SetGeometryValueCommand$1 = function ( object, attributeName, newValue ) { - - Command.call( this ); - - this.type = 'SetGeometryValueCommand'; - this.name = 'Set Geometry.' + attributeName; - - this.object = object; - this.attributeName = attributeName; - this.oldValue = ( object !== undefined ) ? object.geometry[ attributeName ] : undefined; - this.newValue = newValue; - - }; - - SetGeometryValueCommand$1.prototype = { - - execute: function () { - - this.object.geometry[ this.attributeName ] = this.newValue; - this.editor.signals.objectChanged.dispatch( this.object ); - this.editor.signals.geometryChanged.dispatch(); - this.editor.signals.sceneGraphChanged.dispatch(); - - }, - - undo: function () { - - this.object.geometry[ this.attributeName ] = this.oldValue; - this.editor.signals.objectChanged.dispatch( this.object ); - this.editor.signals.geometryChanged.dispatch(); - this.editor.signals.sceneGraphChanged.dispatch(); - - }, - - toJSON: function () { - - var output = Command.prototype.toJSON.call( this ); - - output.objectUuid = this.object.uuid; - output.attributeName = this.attributeName; - output.oldValue = this.oldValue; - output.newValue = this.newValue; - - return output; - - }, - - fromJSON: function ( json ) { - - Command.prototype.fromJSON.call( this, json ); - - this.object = this.editor.objectByUuid( json.objectUuid ); - this.attributeName = json.attributeName; - this.oldValue = json.oldValue; - this.newValue = json.newValue; - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module( 'Commands', () => { - - QUnit.module.todo( 'SetGeometryValueCommand', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author dforrer / https://github.com/dforrer - * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch) - */ - - /** - * @param object THREE.Object3D - * @param attributeName string - * @param newValue integer representing a hex color value - * @constructor - */ - - var SetMaterialColorCommand$1 = function ( object, attributeName, newValue, materialSlot ) { - - Command.call( this ); - - this.type = 'SetMaterialColorCommand'; - this.name = 'Set Material.' + attributeName; - this.updatable = true; - - this.object = object; - this.material = this.editor.getObjectMaterial( object, materialSlot ); - - this.oldValue = ( this.material !== undefined ) ? this.material[ attributeName ].getHex() : undefined; - this.newValue = newValue; - - this.attributeName = attributeName; - - }; - - SetMaterialColorCommand$1.prototype = { - - execute: function () { - - this.material[ this.attributeName ].setHex( this.newValue ); - - this.editor.signals.materialChanged.dispatch( this.material ); - - }, - - undo: function () { - - this.material[ this.attributeName ].setHex( this.oldValue ); - - this.editor.signals.materialChanged.dispatch( this.material ); - - }, - - update: function ( cmd ) { - - this.newValue = cmd.newValue; - - }, - - toJSON: function () { - - var output = Command.prototype.toJSON.call( this ); - - output.objectUuid = this.object.uuid; - output.attributeName = this.attributeName; - output.oldValue = this.oldValue; - output.newValue = this.newValue; - - return output; - - }, - - fromJSON: function ( json ) { - - Command.prototype.fromJSON.call( this, json ); - - this.object = this.editor.objectByUuid( json.objectUuid ); - this.attributeName = json.attributeName; - this.oldValue = json.oldValue; - this.newValue = json.newValue; - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module( 'Commands', () => { - - QUnit.module.todo( 'SetMaterialColorCommand', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author dforrer / https://github.com/dforrer - * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch) - */ - - /** - * @param object THREE.Object3D - * @param newMaterial THREE.Material - * @constructor - */ - - - var SetMaterialCommand$1 = function ( object, newMaterial, materialSlot ) { - - Command.call( this ); - - this.type = 'SetMaterialCommand'; - this.name = 'New Material'; - - this.object = object; - this.materialSlot = materialSlot; - - this.oldMaterial = this.editor.getObjectMaterial( object, materialSlot ); - this.newMaterial = newMaterial; - - }; - - SetMaterialCommand$1.prototype = { - - execute: function () { - - this.editor.setObjectMaterial( this.object, this.materialSlot, this.newMaterial ); - this.editor.signals.materialChanged.dispatch( this.newMaterial ); - - }, - - undo: function () { - - this.editor.setObjectMaterial( this.object, this.materialSlot, this.oldMaterial ); - this.editor.signals.materialChanged.dispatch( this.oldMaterial ); - - }, - - toJSON: function () { - - var output = Command.prototype.toJSON.call( this ); - - output.objectUuid = this.object.uuid; - output.oldMaterial = this.oldMaterial.toJSON(); - output.newMaterial = this.newMaterial.toJSON(); - - return output; - - }, - - fromJSON: function ( json ) { - - Command.prototype.fromJSON.call( this, json ); - - this.object = this.editor.objectByUuid( json.objectUuid ); - this.oldMaterial = parseMaterial( json.oldMaterial ); - this.newMaterial = parseMaterial( json.newMaterial ); - - function parseMaterial ( json ) { - - var loader = new THREE.ObjectLoader(); - var images = loader.parseImages( json.images ); - var textures = loader.parseTextures( json.textures, images ); - var materials = loader.parseMaterials( [ json ], textures ); - return materials[ json.uuid ]; - - } - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module( 'Commands', () => { - - QUnit.module.todo( 'SetMaterialCommand', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author dforrer / https://github.com/dforrer - * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch) - */ - - /** - * @param object THREE.Object3D - * @param mapName string - * @param newMap THREE.Texture - * @constructor - */ - - var SetMaterialMapCommand$1 = function ( object, mapName, newMap, materialSlot ) { - - Command.call( this ); - - this.type = 'SetMaterialMapCommand'; - this.name = 'Set Material.' + mapName; - - this.object = object; - this.material = this.editor.getObjectMaterial( object, materialSlot ); - - this.oldMap = ( object !== undefined ) ? this.material[ mapName ] : undefined; - this.newMap = newMap; - - this.mapName = mapName; - - }; - - SetMaterialMapCommand$1.prototype = { - - execute: function () { - - this.material[ this.mapName ] = this.newMap; - this.material.needsUpdate = true; - - this.editor.signals.materialChanged.dispatch( this.material ); - - }, - - undo: function () { - - this.material[ this.mapName ] = this.oldMap; - this.material.needsUpdate = true; - - this.editor.signals.materialChanged.dispatch( this.material ); - - }, - - toJSON: function () { - - var output = Command.prototype.toJSON.call( this ); - - output.objectUuid = this.object.uuid; - output.mapName = this.mapName; - output.newMap = serializeMap( this.newMap ); - output.oldMap = serializeMap( this.oldMap ); - - return output; - - // serializes a map (THREE.Texture) - - function serializeMap ( map ) { - - if ( map === null || map === undefined ) return null; - - var meta = { - geometries: {}, - materials: {}, - textures: {}, - images: {} - }; - - var json = map.toJSON( meta ); - var images = extractFromCache( meta.images ); - if ( images.length > 0 ) json.images = images; - json.sourceFile = map.sourceFile; - - return json; - - } - - // Note: The function 'extractFromCache' is copied from Object3D.toJSON() - - // extract data from the cache hash - // remove metadata on each item - // and return as array - function extractFromCache ( cache ) { - - var values = []; - for ( var key in cache ) { - - var data = cache[ key ]; - delete data.metadata; - values.push( data ); - - } - return values; - - } - - }, - - fromJSON: function ( json ) { - - Command.prototype.fromJSON.call( this, json ); - - this.object = this.editor.objectByUuid( json.objectUuid ); - this.mapName = json.mapName; - this.oldMap = parseTexture( json.oldMap ); - this.newMap = parseTexture( json.newMap ); - - function parseTexture ( json ) { - - var map = null; - if ( json !== null ) { - - var loader = new THREE.ObjectLoader(); - var images = loader.parseImages( json.images ); - var textures = loader.parseTextures( [ json ], images ); - map = textures[ json.uuid ]; - map.sourceFile = json.sourceFile; - - } - return map; - - } - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module( 'Commands', () => { - - QUnit.module.todo( 'SetMaterialMapCommand', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author dforrer / https://github.com/dforrer - * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch) - */ - - /** - * @param object THREE.Object3D - * @param attributeName string - * @param newValue number, string, boolean or object - * @constructor - */ - - var SetMaterialValueCommand$1 = function ( object, attributeName, newValue, materialSlot ) { - - Command.call( this ); - - this.type = 'SetMaterialValueCommand'; - this.name = 'Set Material.' + attributeName; - this.updatable = true; - - this.object = object; - this.material = this.editor.getObjectMaterial( object, materialSlot ); - - this.oldValue = ( this.material !== undefined ) ? this.material[ attributeName ] : undefined; - this.newValue = newValue; - - this.attributeName = attributeName; - - }; - - SetMaterialValueCommand$1.prototype = { - - execute: function () { - - this.material[ this.attributeName ] = this.newValue; - this.material.needsUpdate = true; - - this.editor.signals.objectChanged.dispatch( this.object ); - this.editor.signals.materialChanged.dispatch( this.material ); - - }, - - undo: function () { - - this.material[ this.attributeName ] = this.oldValue; - this.material.needsUpdate = true; - - this.editor.signals.objectChanged.dispatch( this.object ); - this.editor.signals.materialChanged.dispatch( this.material ); - - }, - - update: function ( cmd ) { - - this.newValue = cmd.newValue; - - }, - - toJSON: function () { - - var output = Command.prototype.toJSON.call( this ); - - output.objectUuid = this.object.uuid; - output.attributeName = this.attributeName; - output.oldValue = this.oldValue; - output.newValue = this.newValue; - - return output; - - }, - - fromJSON: function ( json ) { - - Command.prototype.fromJSON.call( this, json ); - - this.attributeName = json.attributeName; - this.oldValue = json.oldValue; - this.newValue = json.newValue; - this.object = this.editor.objectByUuid( json.objectUuid ); - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module( 'Commands', () => { - - QUnit.module.todo( 'SetMaterialValueCommand', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author dforrer / https://github.com/dforrer - * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch) - */ - - /** - * @param object THREE.Object3D - * @param newPosition THREE.Vector3 - * @param optionalOldPosition THREE.Vector3 - * @constructor - */ - - var SetPositionCommand$1 = function ( object, newPosition, optionalOldPosition ) { - - Command.call( this ); - - this.type = 'SetPositionCommand'; - this.name = 'Set Position'; - this.updatable = true; - - this.object = object; - - if ( object !== undefined && newPosition !== undefined ) { - - this.oldPosition = object.position.clone(); - this.newPosition = newPosition.clone(); - - } - - if ( optionalOldPosition !== undefined ) { - - this.oldPosition = optionalOldPosition.clone(); - - } - - }; - SetPositionCommand$1.prototype = { - - execute: function () { - - this.object.position.copy( this.newPosition ); - this.object.updateMatrixWorld( true ); - this.editor.signals.objectChanged.dispatch( this.object ); - - }, - - undo: function () { - - this.object.position.copy( this.oldPosition ); - this.object.updateMatrixWorld( true ); - this.editor.signals.objectChanged.dispatch( this.object ); - - }, - - update: function ( command ) { - - this.newPosition.copy( command.newPosition ); - - }, - - toJSON: function () { - - var output = Command.prototype.toJSON.call( this ); - - output.objectUuid = this.object.uuid; - output.oldPosition = this.oldPosition.toArray(); - output.newPosition = this.newPosition.toArray(); - - return output; - - }, - - fromJSON: function ( json ) { - - Command.prototype.fromJSON.call( this, json ); - - this.object = this.editor.objectByUuid( json.objectUuid ); - this.oldPosition = new THREE.Vector3().fromArray( json.oldPosition ); - this.newPosition = new THREE.Vector3().fromArray( json.newPosition ); - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module( 'Commands', () => { - - QUnit.module.todo( 'SetPositionCommand', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author dforrer / https://github.com/dforrer - * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch) - */ - - /** - * @param object THREE.Object3D - * @param newRotation THREE.Euler - * @param optionalOldRotation THREE.Euler - * @constructor - */ - - var SetRotationCommand$1 = function ( object, newRotation, optionalOldRotation ) { - - Command.call( this ); - - this.type = 'SetRotationCommand'; - this.name = 'Set Rotation'; - this.updatable = true; - - this.object = object; - - if ( object !== undefined && newRotation !== undefined ) { - - this.oldRotation = object.rotation.clone(); - this.newRotation = newRotation.clone(); - - } - - if ( optionalOldRotation !== undefined ) { - - this.oldRotation = optionalOldRotation.clone(); - - } - - }; - - SetRotationCommand$1.prototype = { - - execute: function () { - - this.object.rotation.copy( this.newRotation ); - this.object.updateMatrixWorld( true ); - this.editor.signals.objectChanged.dispatch( this.object ); - - }, - - undo: function () { - - this.object.rotation.copy( this.oldRotation ); - this.object.updateMatrixWorld( true ); - this.editor.signals.objectChanged.dispatch( this.object ); - - }, - - update: function ( command ) { - - this.newRotation.copy( command.newRotation ); - - }, - - toJSON: function () { - - var output = Command.prototype.toJSON.call( this ); - - output.objectUuid = this.object.uuid; - output.oldRotation = this.oldRotation.toArray(); - output.newRotation = this.newRotation.toArray(); - - return output; - - }, - - fromJSON: function ( json ) { - - Command.prototype.fromJSON.call( this, json ); - - this.object = this.editor.objectByUuid( json.objectUuid ); - this.oldRotation = new THREE.Euler().fromArray( json.oldRotation ); - this.newRotation = new THREE.Euler().fromArray( json.newRotation ); - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module( 'Commands', () => { - - QUnit.module.todo( 'SetRotationCommand', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author dforrer / https://github.com/dforrer - * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch) - */ - - /** - * @param object THREE.Object3D - * @param newScale THREE.Vector3 - * @param optionalOldScale THREE.Vector3 - * @constructor - */ - - var SetScaleCommand$1 = function ( object, newScale, optionalOldScale ) { - - Command.call( this ); - - this.type = 'SetScaleCommand'; - this.name = 'Set Scale'; - this.updatable = true; - - this.object = object; - - if ( object !== undefined && newScale !== undefined ) { - - this.oldScale = object.scale.clone(); - this.newScale = newScale.clone(); - - } - - if ( optionalOldScale !== undefined ) { - - this.oldScale = optionalOldScale.clone(); - - } - - }; - - SetScaleCommand$1.prototype = { - - execute: function () { - - this.object.scale.copy( this.newScale ); - this.object.updateMatrixWorld( true ); - this.editor.signals.objectChanged.dispatch( this.object ); - - }, - - undo: function () { - - this.object.scale.copy( this.oldScale ); - this.object.updateMatrixWorld( true ); - this.editor.signals.objectChanged.dispatch( this.object ); - - }, - - update: function ( command ) { - - this.newScale.copy( command.newScale ); - - }, - - toJSON: function () { - - var output = Command.prototype.toJSON.call( this ); - - output.objectUuid = this.object.uuid; - output.oldScale = this.oldScale.toArray(); - output.newScale = this.newScale.toArray(); - - return output; - - }, - - fromJSON: function ( json ) { - - Command.prototype.fromJSON.call( this, json ); - - this.object = this.editor.objectByUuid( json.objectUuid ); - this.oldScale = new THREE.Vector3().fromArray( json.oldScale ); - this.newScale = new THREE.Vector3().fromArray( json.newScale ); - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module( 'Commands', () => { - - QUnit.module.todo( 'SetScaleCommand', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author dforrer / https://github.com/dforrer - * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch) - */ - - /** - * @param scene containing children to import - * @constructor - */ - - var SetSceneCommand$1 = function ( scene ) { - - Command.call( this ); - - this.type = 'SetSceneCommand'; - this.name = 'Set Scene'; - - this.cmdArray = []; - - if ( scene !== undefined ) { - - this.cmdArray.push( new SetUuidCommand( this.editor.scene, scene.uuid ) ); - this.cmdArray.push( new SetValueCommand( this.editor.scene, 'name', scene.name ) ); - this.cmdArray.push( new SetValueCommand( this.editor.scene, 'userData', JSON.parse( JSON.stringify( scene.userData ) ) ) ); - - while ( scene.children.length > 0 ) { - - var child = scene.children.pop(); - this.cmdArray.push( new AddObjectCommand( child ) ); - - } - - } - - }; - - SetSceneCommand$1.prototype = { - - execute: function () { - - this.editor.signals.sceneGraphChanged.active = false; - - for ( var i = 0; i < this.cmdArray.length; i ++ ) { - - this.cmdArray[ i ].execute(); - - } - - this.editor.signals.sceneGraphChanged.active = true; - this.editor.signals.sceneGraphChanged.dispatch(); - - }, - - undo: function () { - - this.editor.signals.sceneGraphChanged.active = false; - - for ( var i = this.cmdArray.length - 1; i >= 0; i -- ) { - - this.cmdArray[ i ].undo(); - - } - - this.editor.signals.sceneGraphChanged.active = true; - this.editor.signals.sceneGraphChanged.dispatch(); - - }, - - toJSON: function () { - - var output = Command.prototype.toJSON.call( this ); - - var cmds = []; - for ( var i = 0; i < this.cmdArray.length; i ++ ) { - - cmds.push( this.cmdArray[ i ].toJSON() ); - - } - output.cmds = cmds; - - return output; - - }, - - fromJSON: function ( json ) { - - Command.prototype.fromJSON.call( this, json ); - - var cmds = json.cmds; - for ( var i = 0; i < cmds.length; i ++ ) { - - var cmd = new window[ cmds[ i ].type ](); // creates a new object of type "json.type" - cmd.fromJSON( cmds[ i ] ); - this.cmdArray.push( cmd ); - - } - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module( 'Commands', () => { - - QUnit.module.todo( 'SetSceneCommand', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author dforrer / https://github.com/dforrer - * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch) - */ - - /** - * @param object THREE.Object3D - * @param script javascript object - * @param attributeName string - * @param newValue string, object - * @constructor - */ - - var SetScriptValueCommand$1 = function ( object, script, attributeName, newValue ) { - - Command.call( this ); - - this.type = 'SetScriptValueCommand'; - this.name = 'Set Script.' + attributeName; - this.updatable = true; - - this.object = object; - this.script = script; - - this.attributeName = attributeName; - this.oldValue = ( script !== undefined ) ? script[ this.attributeName ] : undefined; - this.newValue = newValue; - - }; - - SetScriptValueCommand$1.prototype = { - - execute: function () { - - this.script[ this.attributeName ] = this.newValue; - - this.editor.signals.scriptChanged.dispatch(); - - }, - - undo: function () { - - this.script[ this.attributeName ] = this.oldValue; - - this.editor.signals.scriptChanged.dispatch(); - - }, - - update: function ( cmd ) { - - this.newValue = cmd.newValue; - - }, - - toJSON: function () { - - var output = Command.prototype.toJSON.call( this ); - - output.objectUuid = this.object.uuid; - output.index = this.editor.scripts[ this.object.uuid ].indexOf( this.script ); - output.attributeName = this.attributeName; - output.oldValue = this.oldValue; - output.newValue = this.newValue; - - return output; - - }, - - fromJSON: function ( json ) { - - Command.prototype.fromJSON.call( this, json ); - - this.oldValue = json.oldValue; - this.newValue = json.newValue; - this.attributeName = json.attributeName; - this.object = this.editor.objectByUuid( json.objectUuid ); - this.script = this.editor.scripts[ json.objectUuid ][ json.index ]; - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module( 'Commands', () => { - - QUnit.module.todo( 'SetScriptValueCommand', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author dforrer / https://github.com/dforrer - * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch) - */ - - /** - * @param object THREE.Object3D - * @param newUuid string - * @constructor - */ - - var SetUuidCommand$1 = function ( object, newUuid ) { - - Command.call( this ); - - this.type = 'SetUuidCommand'; - this.name = 'Update UUID'; - - this.object = object; - - this.oldUuid = ( object !== undefined ) ? object.uuid : undefined; - this.newUuid = newUuid; - - }; - - SetUuidCommand$1.prototype = { - - execute: function () { - - this.object.uuid = this.newUuid; - this.editor.signals.objectChanged.dispatch( this.object ); - this.editor.signals.sceneGraphChanged.dispatch(); - - }, - - undo: function () { - - this.object.uuid = this.oldUuid; - this.editor.signals.objectChanged.dispatch( this.object ); - this.editor.signals.sceneGraphChanged.dispatch(); - - }, - - toJSON: function () { - - var output = Command.prototype.toJSON.call( this ); - - output.oldUuid = this.oldUuid; - output.newUuid = this.newUuid; - - return output; - - }, - - fromJSON: function ( json ) { - - Command.prototype.fromJSON.call( this, json ); - - this.oldUuid = json.oldUuid; - this.newUuid = json.newUuid; - this.object = this.editor.objectByUuid( json.oldUuid ); - - if ( this.object === undefined ) { - - this.object = this.editor.objectByUuid( json.newUuid ); - - } - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module( 'Commands', () => { - - QUnit.module.todo( 'SetUuidCommand', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author dforrer / https://github.com/dforrer - * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch) - */ - - /** - * @param object THREE.Object3D - * @param attributeName string - * @param newValue number, string, boolean or object - * @constructor - */ - - var SetValueCommand$1 = function ( object, attributeName, newValue ) { - - Command.call( this ); - - this.type = 'SetValueCommand'; - this.name = 'Set ' + attributeName; - this.updatable = true; - - this.object = object; - this.attributeName = attributeName; - this.oldValue = ( object !== undefined ) ? object[ attributeName ] : undefined; - this.newValue = newValue; - - }; - - SetValueCommand$1.prototype = { - - execute: function () { - - this.object[ this.attributeName ] = this.newValue; - this.editor.signals.objectChanged.dispatch( this.object ); - // this.editor.signals.sceneGraphChanged.dispatch(); - - }, - - undo: function () { - - this.object[ this.attributeName ] = this.oldValue; - this.editor.signals.objectChanged.dispatch( this.object ); - // this.editor.signals.sceneGraphChanged.dispatch(); - - }, - - update: function ( cmd ) { - - this.newValue = cmd.newValue; - - }, - - toJSON: function () { - - var output = Command.prototype.toJSON.call( this ); - - output.objectUuid = this.object.uuid; - output.attributeName = this.attributeName; - output.oldValue = this.oldValue; - output.newValue = this.newValue; - - return output; - - }, - - fromJSON: function ( json ) { - - Command.prototype.fromJSON.call( this, json ); - - this.attributeName = json.attributeName; - this.oldValue = json.oldValue; - this.newValue = json.newValue; - this.object = this.editor.objectByUuid( json.objectUuid ); - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Editor', () => { - - QUnit.module( 'Commands', () => { - - QUnit.module.todo( 'SetValueCommand', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - - // TODO (Itee) Editor is not es6 module so care to include order !!! - // TODO: all views could not be testable, waiting modular code before implement units tests on them - - //editor - //editor/commands - - - //editor/others - - } ); - -}))); diff --git a/test/unit/three.example.unit.js b/test/unit/three.example.unit.js deleted file mode 100644 index f348849ee1..0000000000 --- a/test/unit/three.example.unit.js +++ /dev/null @@ -1,15 +0,0 @@ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory() : - typeof define === 'function' && define.amd ? define(factory) : - (factory()); -}(this, (function () { 'use strict'; - - QUnit.module( "Example", () => { - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - - } ); - -}))); diff --git a/test/unit/three.source.unit.js b/test/unit/three.source.unit.js deleted file mode 100644 index 213d0baa4d..0000000000 --- a/test/unit/three.source.unit.js +++ /dev/null @@ -1,66084 +0,0 @@ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory() : - typeof define === 'function' && define.amd ? define(factory) : - (factory()); -}(this, (function () { 'use strict'; - - QUnit.module( "Source", () => { - - var REVISION = '88dev'; - var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 }; - var CullFaceNone = 0; - var CullFaceBack = 1; - var CullFaceFront = 2; - var CullFaceFrontBack = 3; - var FrontFaceDirectionCW = 0; - var FrontFaceDirectionCCW = 1; - var BasicShadowMap = 0; - var PCFShadowMap = 1; - var PCFSoftShadowMap = 2; - var FrontSide = 0; - var BackSide = 1; - var DoubleSide = 2; - var FlatShading = 1; - var SmoothShading = 2; - var NoColors = 0; - var FaceColors = 1; - var VertexColors = 2; - var NoBlending = 0; - var NormalBlending = 1; - var AdditiveBlending = 2; - var SubtractiveBlending = 3; - var MultiplyBlending = 4; - var CustomBlending = 5; - var AddEquation = 100; - var SubtractEquation = 101; - var ReverseSubtractEquation = 102; - var MinEquation = 103; - var MaxEquation = 104; - var ZeroFactor = 200; - var OneFactor = 201; - var SrcColorFactor = 202; - var OneMinusSrcColorFactor = 203; - var SrcAlphaFactor = 204; - var OneMinusSrcAlphaFactor = 205; - var DstAlphaFactor = 206; - var OneMinusDstAlphaFactor = 207; - var DstColorFactor = 208; - var OneMinusDstColorFactor = 209; - var SrcAlphaSaturateFactor = 210; - var NeverDepth = 0; - var AlwaysDepth = 1; - var LessDepth = 2; - var LessEqualDepth = 3; - var EqualDepth = 4; - var GreaterEqualDepth = 5; - var GreaterDepth = 6; - var NotEqualDepth = 7; - var MultiplyOperation = 0; - var MixOperation = 1; - var AddOperation = 2; - var NoToneMapping = 0; - var LinearToneMapping = 1; - var ReinhardToneMapping = 2; - var Uncharted2ToneMapping = 3; - var CineonToneMapping = 4; - var UVMapping = 300; - var CubeReflectionMapping = 301; - var CubeRefractionMapping = 302; - var EquirectangularReflectionMapping = 303; - var EquirectangularRefractionMapping = 304; - var SphericalReflectionMapping = 305; - var CubeUVReflectionMapping = 306; - var CubeUVRefractionMapping = 307; - var RepeatWrapping = 1000; - var ClampToEdgeWrapping = 1001; - var MirroredRepeatWrapping = 1002; - var NearestFilter = 1003; - var NearestMipMapNearestFilter = 1004; - var NearestMipMapLinearFilter = 1005; - var LinearFilter = 1006; - var LinearMipMapNearestFilter = 1007; - var LinearMipMapLinearFilter = 1008; - var UnsignedByteType = 1009; - var ByteType = 1010; - var ShortType = 1011; - var UnsignedShortType = 1012; - var IntType = 1013; - var UnsignedIntType = 1014; - var FloatType = 1015; - var HalfFloatType = 1016; - var UnsignedShort4444Type = 1017; - var UnsignedShort5551Type = 1018; - var UnsignedShort565Type = 1019; - var UnsignedInt248Type = 1020; - var AlphaFormat = 1021; - var RGBFormat = 1022; - var RGBAFormat = 1023; - var LuminanceFormat = 1024; - var LuminanceAlphaFormat = 1025; - var RGBEFormat = RGBAFormat; - var DepthFormat = 1026; - var DepthStencilFormat = 1027; - var RGB_S3TC_DXT1_Format = 2001; - var RGBA_S3TC_DXT1_Format = 2002; - var RGBA_S3TC_DXT3_Format = 2003; - var RGBA_S3TC_DXT5_Format = 2004; - var RGB_PVRTC_4BPPV1_Format = 2100; - var RGB_PVRTC_2BPPV1_Format = 2101; - var RGBA_PVRTC_4BPPV1_Format = 2102; - var RGBA_PVRTC_2BPPV1_Format = 2103; - var RGB_ETC1_Format = 2151; - var LoopOnce = 2200; - var LoopRepeat = 2201; - var LoopPingPong = 2202; - var InterpolateDiscrete = 2300; - var InterpolateLinear = 2301; - var InterpolateSmooth = 2302; - var ZeroCurvatureEnding = 2400; - var ZeroSlopeEnding = 2401; - var WrapAroundEnding = 2402; - var TrianglesDrawMode = 0; - var TriangleStripDrawMode = 1; - var TriangleFanDrawMode = 2; - var LinearEncoding = 3000; - var sRGBEncoding = 3001; - var GammaEncoding = 3007; - var RGBEEncoding = 3002; - var LogLuvEncoding = 3003; - var RGBM7Encoding = 3004; - var RGBM16Encoding = 3005; - var RGBDEncoding = 3006; - var BasicDepthPacking = 3200; - var RGBADepthPacking = 3201; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Constants', () => { - - QUnit.test( "default values", ( assert ) => { - - assert.propEqual( MOUSE, { LEFT: 0, MIDDLE: 1, RIGHT: 2 }, 'MOUSE equal { LEFT: 0, MIDDLE: 1, RIGHT: 2 }' ); - assert.equal( CullFaceNone, 0, 'CullFaceNone equal 0' ); - assert.equal( CullFaceBack, 1, 'CullFaceBack equal 1' ); - assert.equal( CullFaceFront, 2, 'CullFaceFront is equal to 2' ); - assert.equal( CullFaceFrontBack, 3, 'CullFaceFrontBack is equal to 3' ); - assert.equal( FrontFaceDirectionCW, 0, 'FrontFaceDirectionCW is equal to 0' ); - assert.equal( FrontFaceDirectionCCW, 1, 'FrontFaceDirectionCCW is equal to 1' ); - assert.equal( BasicShadowMap, 0, 'BasicShadowMap is equal to 0' ); - assert.equal( PCFShadowMap, 1, 'PCFShadowMap is equal to 1' ); - assert.equal( PCFSoftShadowMap, 2, 'PCFSoftShadowMap is equal to 2' ); - assert.equal( FrontSide, 0, 'FrontSide is equal to 0' ); - assert.equal( BackSide, 1, 'BackSide is equal to 1' ); - assert.equal( DoubleSide, 2, 'DoubleSide is equal to 2' ); - assert.equal( FlatShading, 1, 'FlatShading is equal to 1' ); - assert.equal( SmoothShading, 2, 'SmoothShading is equal to 2' ); - assert.equal( NoColors, 0, 'NoColors is equal to 0' ); - assert.equal( FaceColors, 1, 'FaceColors is equal to 1' ); - assert.equal( VertexColors, 2, 'VertexColors is equal to 2' ); - assert.equal( NoBlending, 0, 'NoBlending is equal to 0' ); - assert.equal( NormalBlending, 1, 'NormalBlending is equal to 1' ); - assert.equal( AdditiveBlending, 2, 'AdditiveBlending is equal to 2' ); - assert.equal( SubtractiveBlending, 3, 'SubtractiveBlending is equal to 3' ); - assert.equal( MultiplyBlending, 4, 'MultiplyBlending is equal to 4' ); - assert.equal( CustomBlending, 5, 'CustomBlending is equal to 5' ); - assert.equal( AddEquation, 100, 'AddEquation is equal to 100' ); - assert.equal( SubtractEquation, 101, 'SubtractEquation is equal to 101' ); - assert.equal( ReverseSubtractEquation, 102, 'ReverseSubtractEquation is equal to 102' ); - assert.equal( MinEquation, 103, 'MinEquation is equal to 103' ); - assert.equal( MaxEquation, 104, 'MaxEquation is equal to 104' ); - assert.equal( ZeroFactor, 200, 'ZeroFactor is equal to 200' ); - assert.equal( OneFactor, 201, 'OneFactor is equal to 201' ); - assert.equal( SrcColorFactor, 202, 'SrcColorFactor is equal to 202' ); - assert.equal( OneMinusSrcColorFactor, 203, 'OneMinusSrcColorFactor is equal to 203' ); - assert.equal( SrcAlphaFactor, 204, 'SrcAlphaFactor is equal to 204' ); - assert.equal( OneMinusSrcAlphaFactor, 205, 'OneMinusSrcAlphaFactor is equal to 205' ); - assert.equal( DstAlphaFactor, 206, 'DstAlphaFactor is equal to 206' ); - assert.equal( OneMinusDstAlphaFactor, 207, 'OneMinusDstAlphaFactor is equal to 207' ); - assert.equal( DstColorFactor, 208, 'DstColorFactor is equal to 208' ); - assert.equal( OneMinusDstColorFactor, 209, 'OneMinusDstColorFactor is equal to 209' ); - assert.equal( SrcAlphaSaturateFactor, 210, 'SrcAlphaSaturateFactor is equal to 210' ); - assert.equal( NeverDepth, 0, 'NeverDepth is equal to 0' ); - assert.equal( AlwaysDepth, 1, 'AlwaysDepth is equal to 1' ); - assert.equal( LessDepth, 2, 'LessDepth is equal to 2' ); - assert.equal( LessEqualDepth, 3, 'LessEqualDepth is equal to 3' ); - assert.equal( EqualDepth, 4, 'EqualDepth is equal to 4' ); - assert.equal( GreaterEqualDepth, 5, 'GreaterEqualDepth is equal to 5' ); - assert.equal( GreaterDepth, 6, 'GreaterDepth is equal to 6' ); - assert.equal( NotEqualDepth, 7, 'NotEqualDepth is equal to 7' ); - assert.equal( MultiplyOperation, 0, 'MultiplyOperation is equal to 0' ); - assert.equal( MixOperation, 1, 'MixOperation is equal to 1' ); - assert.equal( AddOperation, 2, 'AddOperation is equal to 2' ); - assert.equal( NoToneMapping, 0, 'NoToneMapping is equal to 0' ); - assert.equal( LinearToneMapping, 1, 'LinearToneMapping is equal to 1' ); - assert.equal( ReinhardToneMapping, 2, 'ReinhardToneMapping is equal to 2' ); - assert.equal( Uncharted2ToneMapping, 3, 'Uncharted2ToneMapping is equal to 3' ); - assert.equal( CineonToneMapping, 4, 'CineonToneMapping is equal to 4' ); - assert.equal( UVMapping, 300, 'UVMapping is equal to 300' ); - assert.equal( CubeReflectionMapping, 301, 'CubeReflectionMapping is equal to 301' ); - assert.equal( CubeRefractionMapping, 302, 'CubeRefractionMapping is equal to 302' ); - assert.equal( EquirectangularReflectionMapping, 303, 'EquirectangularReflectionMapping is equal to 303' ); - assert.equal( EquirectangularRefractionMapping, 304, 'EquirectangularRefractionMapping is equal to 304' ); - assert.equal( SphericalReflectionMapping, 305, 'SphericalReflectionMapping is equal to 305' ); - assert.equal( CubeUVReflectionMapping, 306, 'CubeUVReflectionMapping is equal to 306' ); - assert.equal( CubeUVRefractionMapping, 307, 'CubeUVRefractionMapping is equal to 307' ); - assert.equal( RepeatWrapping, 1000, 'RepeatWrapping is equal to 1000' ); - assert.equal( ClampToEdgeWrapping, 1001, 'ClampToEdgeWrapping is equal to 1001' ); - assert.equal( MirroredRepeatWrapping, 1002, 'MirroredRepeatWrapping is equal to 1002' ); - assert.equal( NearestFilter, 1003, 'NearestFilter is equal to 1003' ); - assert.equal( NearestMipMapNearestFilter, 1004, 'NearestMipMapNearestFilter is equal to 1004' ); - assert.equal( NearestMipMapLinearFilter, 1005, 'NearestMipMapLinearFilter is equal to 1005' ); - assert.equal( LinearFilter, 1006, 'LinearFilter is equal to 1006' ); - assert.equal( LinearMipMapNearestFilter, 1007, 'LinearMipMapNearestFilter is equal to 1007' ); - assert.equal( LinearMipMapLinearFilter, 1008, 'LinearMipMapLinearFilter is equal to 1008' ); - assert.equal( UnsignedByteType, 1009, 'UnsignedByteType is equal to 1009' ); - assert.equal( ByteType, 1010, 'ByteType is equal to 1010' ); - assert.equal( ShortType, 1011, 'ShortType is equal to 1011' ); - assert.equal( UnsignedShortType, 1012, 'UnsignedShortType is equal to 1012' ); - assert.equal( IntType, 1013, 'IntType is equal to 1013' ); - assert.equal( UnsignedIntType, 1014, 'UnsignedIntType is equal to 1014' ); - assert.equal( FloatType, 1015, 'FloatType is equal to 1015' ); - assert.equal( HalfFloatType, 1016, 'HalfFloatType is equal to 1016' ); - assert.equal( UnsignedShort4444Type, 1017, 'UnsignedShort4444Type is equal to 1017' ); - assert.equal( UnsignedShort5551Type, 1018, 'UnsignedShort5551Type is equal to 1018' ); - assert.equal( UnsignedShort565Type, 1019, 'UnsignedShort565Type is equal to 1019' ); - assert.equal( UnsignedInt248Type, 1020, 'UnsignedInt248Type is equal to 1020' ); - assert.equal( AlphaFormat, 1021, 'AlphaFormat is equal to 1021' ); - assert.equal( RGBFormat, 1022, 'RGBFormat is equal to 1022' ); - assert.equal( RGBAFormat, 1023, 'RGBAFormat is equal to 1023' ); - assert.equal( LuminanceFormat, 1024, 'LuminanceFormat is equal to 1024' ); - assert.equal( LuminanceAlphaFormat, 1025, 'LuminanceAlphaFormat is equal to 1025' ); - assert.equal( RGBEFormat, RGBAFormat, 'RGBEFormat is equal to RGBAFormat' ); - assert.equal( DepthFormat, 1026, 'DepthFormat is equal to 1026' ); - assert.equal( DepthStencilFormat, 1027, 'DepthStencilFormat is equal to 1027' ); - assert.equal( RGB_S3TC_DXT1_Format, 2001, 'RGB_S3TC_DXT1_Format is equal to 2001' ); - assert.equal( RGBA_S3TC_DXT1_Format, 2002, 'RGBA_S3TC_DXT1_Format is equal to 2002' ); - assert.equal( RGBA_S3TC_DXT3_Format, 2003, 'RGBA_S3TC_DXT3_Format is equal to 2003' ); - assert.equal( RGBA_S3TC_DXT5_Format, 2004, 'RGBA_S3TC_DXT5_Format is equal to 2004' ); - assert.equal( RGB_PVRTC_4BPPV1_Format, 2100, 'RGB_PVRTC_4BPPV1_Format is equal to 2100' ); - assert.equal( RGB_PVRTC_2BPPV1_Format, 2101, 'RGB_PVRTC_2BPPV1_Format is equal to 2101' ); - assert.equal( RGBA_PVRTC_4BPPV1_Format, 2102, 'RGBA_PVRTC_4BPPV1_Format is equal to 2102' ); - assert.equal( RGBA_PVRTC_2BPPV1_Format, 2103, 'RGBA_PVRTC_2BPPV1_Format is equal to 2103' ); - assert.equal( RGB_ETC1_Format, 2151, 'RGB_ETC1_Format is equal to 2151' ); - assert.equal( LoopOnce, 2200, 'LoopOnce is equal to 2200' ); - assert.equal( LoopRepeat, 2201, 'LoopRepeat is equal to 2201' ); - assert.equal( LoopPingPong, 2202, 'LoopPingPong is equal to 2202' ); - assert.equal( InterpolateDiscrete, 2300, 'InterpolateDiscrete is equal to 2300' ); - assert.equal( InterpolateLinear, 2301, 'InterpolateLinear is equal to 2301' ); - assert.equal( InterpolateSmooth, 2302, 'InterpolateSmooth is equal to 2302' ); - assert.equal( ZeroCurvatureEnding, 2400, 'ZeroCurvatureEnding is equal to 2400' ); - assert.equal( ZeroSlopeEnding, 2401, 'ZeroSlopeEnding is equal to 2401' ); - assert.equal( WrapAroundEnding, 2402, 'WrapAroundEnding is equal to 2402' ); - assert.equal( TrianglesDrawMode, 0, 'TrianglesDrawMode is equal to 0' ); - assert.equal( TriangleStripDrawMode, 1, 'TriangleStripDrawMode is equal to 1' ); - assert.equal( TriangleFanDrawMode, 2, 'TriangleFanDrawMode is equal to 2' ); - assert.equal( LinearEncoding, 3000, 'LinearEncoding is equal to 3000' ); - assert.equal( sRGBEncoding, 3001, 'sRGBEncoding is equal to 3001' ); - assert.equal( GammaEncoding, 3007, 'GammaEncoding is equal to 3007' ); - assert.equal( RGBEEncoding, 3002, 'RGBEEncoding is equal to 3002' ); - assert.equal( LogLuvEncoding, 3003, 'LogLuvEncoding is equal to 3003' ); - assert.equal( RGBM7Encoding, 3004, 'RGBM7Encoding is equal to 3004' ); - assert.equal( RGBM16Encoding, 3005, 'RGBM16Encoding is equal to 3005' ); - assert.equal( RGBDEncoding, 3006, 'RGBDEncoding is equal to 3006' ); - assert.equal( BasicDepthPacking, 3200, 'BasicDepthPacking is equal to 3200' ); - assert.equal( RGBADepthPacking, 3201, 'RGBADepthPacking is equal to 3201' ); - - } ); - - } ); - - // Polyfills - - if ( Number.EPSILON === undefined ) { - - Number.EPSILON = Math.pow( 2, - 52 ); - - } - - if ( Number.isInteger === undefined ) { - - // Missing in IE - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger - - Number.isInteger = function ( value ) { - - return typeof value === 'number' && isFinite( value ) && Math.floor( value ) === value; - - }; - - } - - // - - if ( Math.sign === undefined ) { - - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign - - Math.sign = function ( x ) { - - return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : + x; - - }; - - } - - if ( 'name' in Function.prototype === false ) { - - // Missing in IE - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name - - Object.defineProperty( Function.prototype, 'name', { - - get: function () { - - return this.toString().match( /^\s*function\s*([^\(\s]*)/ )[ 1 ]; - - } - - } ); - - } - - if ( Object.assign === undefined ) { - - // Missing in IE - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign - - ( function () { - - Object.assign = function ( target ) { - - 'use strict'; - - if ( target === undefined || target === null ) { - - throw new TypeError( 'Cannot convert undefined or null to object' ); - - } - - var output = Object( target ); - - for ( var index = 1; index < arguments.length; index ++ ) { - - var source = arguments[ index ]; - - if ( source !== undefined && source !== null ) { - - for ( var nextKey in source ) { - - if ( Object.prototype.hasOwnProperty.call( source, nextKey ) ) { - - output[ nextKey ] = source[ nextKey ]; - - } - - } - - } - - } - - return output; - - }; - - } )(); - - } - - /** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - */ - - var _Math = { - - DEG2RAD: Math.PI / 180, - RAD2DEG: 180 / Math.PI, - - generateUUID: function () { - - // http://www.broofa.com/Tools/Math.uuid.htm - // Replaced .join with string concatenation (@takahirox) - - var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split( '' ); - var rnd = 0, r; - - return function generateUUID() { - - var uuid = ''; - - for ( var i = 0; i < 36; i ++ ) { - - if ( i === 8 || i === 13 || i === 18 || i === 23 ) { - - uuid += '-'; - - } else if ( i === 14 ) { - - uuid += '4'; - - } else { - - if ( rnd <= 0x02 ) rnd = 0x2000000 + ( Math.random() * 0x1000000 ) | 0; - r = rnd & 0xf; - rnd = rnd >> 4; - uuid += chars[ ( i === 19 ) ? ( r & 0x3 ) | 0x8 : r ]; - - } - - } - - return uuid; - - }; - - }(), - - clamp: function ( value, min, max ) { - - return Math.max( min, Math.min( max, value ) ); - - }, - - // compute euclidian modulo of m % n - // https://en.wikipedia.org/wiki/Modulo_operation - - euclideanModulo: function ( n, m ) { - - return ( ( n % m ) + m ) % m; - - }, - - // Linear mapping from range to range - - mapLinear: function ( x, a1, a2, b1, b2 ) { - - return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 ); - - }, - - // https://en.wikipedia.org/wiki/Linear_interpolation - - lerp: function ( x, y, t ) { - - return ( 1 - t ) * x + t * y; - - }, - - // http://en.wikipedia.org/wiki/Smoothstep - - smoothstep: function ( x, min, max ) { - - if ( x <= min ) return 0; - if ( x >= max ) return 1; - - x = ( x - min ) / ( max - min ); - - return x * x * ( 3 - 2 * x ); - - }, - - smootherstep: function ( x, min, max ) { - - if ( x <= min ) return 0; - if ( x >= max ) return 1; - - x = ( x - min ) / ( max - min ); - - return x * x * x * ( x * ( x * 6 - 15 ) + 10 ); - - }, - - // Random integer from interval - - randInt: function ( low, high ) { - - return low + Math.floor( Math.random() * ( high - low + 1 ) ); - - }, - - // Random float from interval - - randFloat: function ( low, high ) { - - return low + Math.random() * ( high - low ); - - }, - - // Random float from <-range/2, range/2> interval - - randFloatSpread: function ( range ) { - - return range * ( 0.5 - Math.random() ); - - }, - - degToRad: function ( degrees ) { - - return degrees * _Math.DEG2RAD; - - }, - - radToDeg: function ( radians ) { - - return radians * _Math.RAD2DEG; - - }, - - isPowerOfTwo: function ( value ) { - - return ( value & ( value - 1 ) ) === 0 && value !== 0; - - }, - - ceilPowerOfTwo: function ( value ) { - - return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) ); - - }, - - floorPowerOfTwo: function ( value ) { - - return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) ); - - } - - }; - - function Matrix4() { - - this.elements = [ - - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - - ]; - - if ( arguments.length > 0 ) { - - console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' ); - - } - - } - - Object.assign( Matrix4.prototype, { - - isMatrix4: true, - - set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { - - var te = this.elements; - - te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14; - te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24; - te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34; - te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44; - - return this; - - }, - - identity: function () { - - this.set( - - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - - ); - - return this; - - }, - - clone: function () { - - return new Matrix4().fromArray( this.elements ); - - }, - - copy: function ( m ) { - - var te = this.elements; - var me = m.elements; - - te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ]; - te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; - te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ]; - te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ]; - - return this; - - }, - - copyPosition: function ( m ) { - - var te = this.elements, me = m.elements; - - te[ 12 ] = me[ 12 ]; - te[ 13 ] = me[ 13 ]; - te[ 14 ] = me[ 14 ]; - - return this; - - }, - - extractBasis: function ( xAxis, yAxis, zAxis ) { - - xAxis.setFromMatrixColumn( this, 0 ); - yAxis.setFromMatrixColumn( this, 1 ); - zAxis.setFromMatrixColumn( this, 2 ); - - return this; - - }, - - makeBasis: function ( xAxis, yAxis, zAxis ) { - - this.set( - xAxis.x, yAxis.x, zAxis.x, 0, - xAxis.y, yAxis.y, zAxis.y, 0, - xAxis.z, yAxis.z, zAxis.z, 0, - 0, 0, 0, 1 - ); - - return this; - - }, - - extractRotation: function () { - - var v1 = new Vector3(); - - return function extractRotation( m ) { - - var te = this.elements; - var me = m.elements; - - var scaleX = 1 / v1.setFromMatrixColumn( m, 0 ).length(); - var scaleY = 1 / v1.setFromMatrixColumn( m, 1 ).length(); - var scaleZ = 1 / v1.setFromMatrixColumn( m, 2 ).length(); - - te[ 0 ] = me[ 0 ] * scaleX; - te[ 1 ] = me[ 1 ] * scaleX; - te[ 2 ] = me[ 2 ] * scaleX; - - te[ 4 ] = me[ 4 ] * scaleY; - te[ 5 ] = me[ 5 ] * scaleY; - te[ 6 ] = me[ 6 ] * scaleY; - - te[ 8 ] = me[ 8 ] * scaleZ; - te[ 9 ] = me[ 9 ] * scaleZ; - te[ 10 ] = me[ 10 ] * scaleZ; - - return this; - - }; - - }(), - - makeRotationFromEuler: function ( euler ) { - - if ( ! ( euler && euler.isEuler ) ) { - - console.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' ); - - } - - var te = this.elements; - - var x = euler.x, y = euler.y, z = euler.z; - var a = Math.cos( x ), b = Math.sin( x ); - var c = Math.cos( y ), d = Math.sin( y ); - var e = Math.cos( z ), f = Math.sin( z ); - - if ( euler.order === 'XYZ' ) { - - var ae = a * e, af = a * f, be = b * e, bf = b * f; - - te[ 0 ] = c * e; - te[ 4 ] = - c * f; - te[ 8 ] = d; - - te[ 1 ] = af + be * d; - te[ 5 ] = ae - bf * d; - te[ 9 ] = - b * c; - - te[ 2 ] = bf - ae * d; - te[ 6 ] = be + af * d; - te[ 10 ] = a * c; - - } else if ( euler.order === 'YXZ' ) { - - var ce = c * e, cf = c * f, de = d * e, df = d * f; - - te[ 0 ] = ce + df * b; - te[ 4 ] = de * b - cf; - te[ 8 ] = a * d; - - te[ 1 ] = a * f; - te[ 5 ] = a * e; - te[ 9 ] = - b; - - te[ 2 ] = cf * b - de; - te[ 6 ] = df + ce * b; - te[ 10 ] = a * c; - - } else if ( euler.order === 'ZXY' ) { - - var ce = c * e, cf = c * f, de = d * e, df = d * f; - - te[ 0 ] = ce - df * b; - te[ 4 ] = - a * f; - te[ 8 ] = de + cf * b; - - te[ 1 ] = cf + de * b; - te[ 5 ] = a * e; - te[ 9 ] = df - ce * b; - - te[ 2 ] = - a * d; - te[ 6 ] = b; - te[ 10 ] = a * c; - - } else if ( euler.order === 'ZYX' ) { - - var ae = a * e, af = a * f, be = b * e, bf = b * f; - - te[ 0 ] = c * e; - te[ 4 ] = be * d - af; - te[ 8 ] = ae * d + bf; - - te[ 1 ] = c * f; - te[ 5 ] = bf * d + ae; - te[ 9 ] = af * d - be; - - te[ 2 ] = - d; - te[ 6 ] = b * c; - te[ 10 ] = a * c; - - } else if ( euler.order === 'YZX' ) { - - var ac = a * c, ad = a * d, bc = b * c, bd = b * d; - - te[ 0 ] = c * e; - te[ 4 ] = bd - ac * f; - te[ 8 ] = bc * f + ad; - - te[ 1 ] = f; - te[ 5 ] = a * e; - te[ 9 ] = - b * e; - - te[ 2 ] = - d * e; - te[ 6 ] = ad * f + bc; - te[ 10 ] = ac - bd * f; - - } else if ( euler.order === 'XZY' ) { - - var ac = a * c, ad = a * d, bc = b * c, bd = b * d; - - te[ 0 ] = c * e; - te[ 4 ] = - f; - te[ 8 ] = d * e; - - te[ 1 ] = ac * f + bd; - te[ 5 ] = a * e; - te[ 9 ] = ad * f - bc; - - te[ 2 ] = bc * f - ad; - te[ 6 ] = b * e; - te[ 10 ] = bd * f + ac; - - } - - // last column - te[ 3 ] = 0; - te[ 7 ] = 0; - te[ 11 ] = 0; - - // bottom row - te[ 12 ] = 0; - te[ 13 ] = 0; - te[ 14 ] = 0; - te[ 15 ] = 1; - - return this; - - }, - - makeRotationFromQuaternion: function ( q ) { - - var te = this.elements; - - var x = q._x, y = q._y, z = q._z, w = q._w; - var x2 = x + x, y2 = y + y, z2 = z + z; - var xx = x * x2, xy = x * y2, xz = x * z2; - var yy = y * y2, yz = y * z2, zz = z * z2; - var wx = w * x2, wy = w * y2, wz = w * z2; - - te[ 0 ] = 1 - ( yy + zz ); - te[ 4 ] = xy - wz; - te[ 8 ] = xz + wy; - - te[ 1 ] = xy + wz; - te[ 5 ] = 1 - ( xx + zz ); - te[ 9 ] = yz - wx; - - te[ 2 ] = xz - wy; - te[ 6 ] = yz + wx; - te[ 10 ] = 1 - ( xx + yy ); - - // last column - te[ 3 ] = 0; - te[ 7 ] = 0; - te[ 11 ] = 0; - - // bottom row - te[ 12 ] = 0; - te[ 13 ] = 0; - te[ 14 ] = 0; - te[ 15 ] = 1; - - return this; - - }, - - lookAt: function () { - - var x = new Vector3(); - var y = new Vector3(); - var z = new Vector3(); - - return function lookAt( eye, target, up ) { - - var te = this.elements; - - z.subVectors( eye, target ); - - if ( z.lengthSq() === 0 ) { - - // eye and target are in the same position - - z.z = 1; - - } - - z.normalize(); - x.crossVectors( up, z ); - - if ( x.lengthSq() === 0 ) { - - // up and z are parallel - - if ( Math.abs( up.z ) === 1 ) { - - z.x += 0.0001; - - } else { - - z.z += 0.0001; - - } - - z.normalize(); - x.crossVectors( up, z ); - - } - - x.normalize(); - y.crossVectors( z, x ); - - te[ 0 ] = x.x; te[ 4 ] = y.x; te[ 8 ] = z.x; - te[ 1 ] = x.y; te[ 5 ] = y.y; te[ 9 ] = z.y; - te[ 2 ] = x.z; te[ 6 ] = y.z; te[ 10 ] = z.z; - - return this; - - }; - - }(), - - multiply: function ( m, n ) { - - if ( n !== undefined ) { - - console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' ); - return this.multiplyMatrices( m, n ); - - } - - return this.multiplyMatrices( this, m ); - - }, - - premultiply: function ( m ) { - - return this.multiplyMatrices( m, this ); - - }, - - multiplyMatrices: function ( a, b ) { - - var ae = a.elements; - var be = b.elements; - var te = this.elements; - - var a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ]; - var a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ]; - var a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ]; - var a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ]; - - var b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ]; - var b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ]; - var b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ]; - var b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ]; - - te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41; - te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42; - te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43; - te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44; - - te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41; - te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42; - te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43; - te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44; - - te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41; - te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42; - te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43; - te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44; - - te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41; - te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42; - te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43; - te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44; - - return this; - - }, - - multiplyScalar: function ( s ) { - - var te = this.elements; - - te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s; - te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s; - te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s; - te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s; - - return this; - - }, - - applyToBufferAttribute: function () { - - var v1 = new Vector3(); - - return function applyToBufferAttribute( attribute ) { - - for ( var i = 0, l = attribute.count; i < l; i ++ ) { - - v1.x = attribute.getX( i ); - v1.y = attribute.getY( i ); - v1.z = attribute.getZ( i ); - - v1.applyMatrix4( this ); - - attribute.setXYZ( i, v1.x, v1.y, v1.z ); - - } - - return attribute; - - }; - - }(), - - determinant: function () { - - var te = this.elements; - - var n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ]; - var n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ]; - var n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ]; - var n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ]; - - //TODO: make this more efficient - //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm ) - - return ( - n41 * ( - + n14 * n23 * n32 - - n13 * n24 * n32 - - n14 * n22 * n33 - + n12 * n24 * n33 - + n13 * n22 * n34 - - n12 * n23 * n34 - ) + - n42 * ( - + n11 * n23 * n34 - - n11 * n24 * n33 - + n14 * n21 * n33 - - n13 * n21 * n34 - + n13 * n24 * n31 - - n14 * n23 * n31 - ) + - n43 * ( - + n11 * n24 * n32 - - n11 * n22 * n34 - - n14 * n21 * n32 - + n12 * n21 * n34 - + n14 * n22 * n31 - - n12 * n24 * n31 - ) + - n44 * ( - - n13 * n22 * n31 - - n11 * n23 * n32 - + n11 * n22 * n33 - + n13 * n21 * n32 - - n12 * n21 * n33 - + n12 * n23 * n31 - ) - - ); - - }, - - transpose: function () { - - var te = this.elements; - var tmp; - - tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp; - tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp; - tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp; - - tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp; - tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp; - tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp; - - return this; - - }, - - setPosition: function ( v ) { - - var te = this.elements; - - te[ 12 ] = v.x; - te[ 13 ] = v.y; - te[ 14 ] = v.z; - - return this; - - }, - - getInverse: function ( m, throwOnDegenerate ) { - - // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm - var te = this.elements, - me = m.elements, - - n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], n41 = me[ 3 ], - n12 = me[ 4 ], n22 = me[ 5 ], n32 = me[ 6 ], n42 = me[ 7 ], - n13 = me[ 8 ], n23 = me[ 9 ], n33 = me[ 10 ], n43 = me[ 11 ], - n14 = me[ 12 ], n24 = me[ 13 ], n34 = me[ 14 ], n44 = me[ 15 ], - - t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44, - t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44, - t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44, - t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34; - - var det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14; - - if ( det === 0 ) { - - var msg = "THREE.Matrix4: .getInverse() can't invert matrix, determinant is 0"; - - if ( throwOnDegenerate === true ) { - - throw new Error( msg ); - - } else { - - console.warn( msg ); - - } - - return this.identity(); - - } - - var detInv = 1 / det; - - te[ 0 ] = t11 * detInv; - te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv; - te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv; - te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv; - - te[ 4 ] = t12 * detInv; - te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv; - te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv; - te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv; - - te[ 8 ] = t13 * detInv; - te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv; - te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv; - te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv; - - te[ 12 ] = t14 * detInv; - te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv; - te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv; - te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv; - - return this; - - }, - - scale: function ( v ) { - - var te = this.elements; - var x = v.x, y = v.y, z = v.z; - - te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z; - te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z; - te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z; - te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z; - - return this; - - }, - - getMaxScaleOnAxis: function () { - - var te = this.elements; - - var scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ]; - var scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ]; - var scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ]; - - return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) ); - - }, - - makeTranslation: function ( x, y, z ) { - - this.set( - - 1, 0, 0, x, - 0, 1, 0, y, - 0, 0, 1, z, - 0, 0, 0, 1 - - ); - - return this; - - }, - - makeRotationX: function ( theta ) { - - var c = Math.cos( theta ), s = Math.sin( theta ); - - this.set( - - 1, 0, 0, 0, - 0, c, - s, 0, - 0, s, c, 0, - 0, 0, 0, 1 - - ); - - return this; - - }, - - makeRotationY: function ( theta ) { - - var c = Math.cos( theta ), s = Math.sin( theta ); - - this.set( - - c, 0, s, 0, - 0, 1, 0, 0, - - s, 0, c, 0, - 0, 0, 0, 1 - - ); - - return this; - - }, - - makeRotationZ: function ( theta ) { - - var c = Math.cos( theta ), s = Math.sin( theta ); - - this.set( - - c, - s, 0, 0, - s, c, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - - ); - - return this; - - }, - - makeRotationAxis: function ( axis, angle ) { - - // Based on http://www.gamedev.net/reference/articles/article1199.asp - - var c = Math.cos( angle ); - var s = Math.sin( angle ); - var t = 1 - c; - var x = axis.x, y = axis.y, z = axis.z; - var tx = t * x, ty = t * y; - - this.set( - - tx * x + c, tx * y - s * z, tx * z + s * y, 0, - tx * y + s * z, ty * y + c, ty * z - s * x, 0, - tx * z - s * y, ty * z + s * x, t * z * z + c, 0, - 0, 0, 0, 1 - - ); - - return this; - - }, - - makeScale: function ( x, y, z ) { - - this.set( - - x, 0, 0, 0, - 0, y, 0, 0, - 0, 0, z, 0, - 0, 0, 0, 1 - - ); - - return this; - - }, - - makeShear: function ( x, y, z ) { - - this.set( - - 1, y, z, 0, - x, 1, z, 0, - x, y, 1, 0, - 0, 0, 0, 1 - - ); - - return this; - - }, - - compose: function ( position, quaternion, scale ) { - - this.makeRotationFromQuaternion( quaternion ); - this.scale( scale ); - this.setPosition( position ); - - return this; - - }, - - decompose: function () { - - var vector = new Vector3(); - var matrix = new Matrix4(); - - return function decompose( position, quaternion, scale ) { - - var te = this.elements; - - var sx = vector.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length(); - var sy = vector.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length(); - var sz = vector.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length(); - - // if determine is negative, we need to invert one scale - var det = this.determinant(); - if ( det < 0 ) sx = - sx; - - position.x = te[ 12 ]; - position.y = te[ 13 ]; - position.z = te[ 14 ]; - - // scale the rotation part - matrix.copy( this ); - - var invSX = 1 / sx; - var invSY = 1 / sy; - var invSZ = 1 / sz; - - matrix.elements[ 0 ] *= invSX; - matrix.elements[ 1 ] *= invSX; - matrix.elements[ 2 ] *= invSX; - - matrix.elements[ 4 ] *= invSY; - matrix.elements[ 5 ] *= invSY; - matrix.elements[ 6 ] *= invSY; - - matrix.elements[ 8 ] *= invSZ; - matrix.elements[ 9 ] *= invSZ; - matrix.elements[ 10 ] *= invSZ; - - quaternion.setFromRotationMatrix( matrix ); - - scale.x = sx; - scale.y = sy; - scale.z = sz; - - return this; - - }; - - }(), - - makePerspective: function ( left, right, top, bottom, near, far ) { - - if ( far === undefined ) { - - console.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' ); - - } - - var te = this.elements; - var x = 2 * near / ( right - left ); - var y = 2 * near / ( top - bottom ); - - var a = ( right + left ) / ( right - left ); - var b = ( top + bottom ) / ( top - bottom ); - var c = - ( far + near ) / ( far - near ); - var d = - 2 * far * near / ( far - near ); - - te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0; - te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0; - te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d; - te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0; - - return this; - - }, - - makeOrthographic: function ( left, right, top, bottom, near, far ) { - - var te = this.elements; - var w = 1.0 / ( right - left ); - var h = 1.0 / ( top - bottom ); - var p = 1.0 / ( far - near ); - - var x = ( right + left ) * w; - var y = ( top + bottom ) * h; - var z = ( far + near ) * p; - - te[ 0 ] = 2 * w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x; - te[ 1 ] = 0; te[ 5 ] = 2 * h; te[ 9 ] = 0; te[ 13 ] = - y; - te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = - 2 * p; te[ 14 ] = - z; - te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; te[ 15 ] = 1; - - return this; - - }, - - equals: function ( matrix ) { - - var te = this.elements; - var me = matrix.elements; - - for ( var i = 0; i < 16; i ++ ) { - - if ( te[ i ] !== me[ i ] ) return false; - - } - - return true; - - }, - - fromArray: function ( array, offset ) { - - if ( offset === undefined ) offset = 0; - - for ( var i = 0; i < 16; i ++ ) { - - this.elements[ i ] = array[ i + offset ]; - - } - - return this; - - }, - - toArray: function ( array, offset ) { - - if ( array === undefined ) array = []; - if ( offset === undefined ) offset = 0; - - var te = this.elements; - - array[ offset ] = te[ 0 ]; - array[ offset + 1 ] = te[ 1 ]; - array[ offset + 2 ] = te[ 2 ]; - array[ offset + 3 ] = te[ 3 ]; - - array[ offset + 4 ] = te[ 4 ]; - array[ offset + 5 ] = te[ 5 ]; - array[ offset + 6 ] = te[ 6 ]; - array[ offset + 7 ] = te[ 7 ]; - - array[ offset + 8 ] = te[ 8 ]; - array[ offset + 9 ] = te[ 9 ]; - array[ offset + 10 ] = te[ 10 ]; - array[ offset + 11 ] = te[ 11 ]; - - array[ offset + 12 ] = te[ 12 ]; - array[ offset + 13 ] = te[ 13 ]; - array[ offset + 14 ] = te[ 14 ]; - array[ offset + 15 ] = te[ 15 ]; - - return array; - - } - - } ); - - function Quaternion( x, y, z, w ) { - - this._x = x || 0; - this._y = y || 0; - this._z = z || 0; - this._w = ( w !== undefined ) ? w : 1; - - } - - Object.assign( Quaternion, { - - slerp: function ( qa, qb, qm, t ) { - - return qm.copy( qa ).slerp( qb, t ); - - }, - - slerpFlat: function ( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) { - - // fuzz-free, array-based Quaternion SLERP operation - - var x0 = src0[ srcOffset0 + 0 ], - y0 = src0[ srcOffset0 + 1 ], - z0 = src0[ srcOffset0 + 2 ], - w0 = src0[ srcOffset0 + 3 ], - - x1 = src1[ srcOffset1 + 0 ], - y1 = src1[ srcOffset1 + 1 ], - z1 = src1[ srcOffset1 + 2 ], - w1 = src1[ srcOffset1 + 3 ]; - - if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) { - - var s = 1 - t, - - cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, - - dir = ( cos >= 0 ? 1 : - 1 ), - sqrSin = 1 - cos * cos; - - // Skip the Slerp for tiny steps to avoid numeric problems: - if ( sqrSin > Number.EPSILON ) { - - var sin = Math.sqrt( sqrSin ), - len = Math.atan2( sin, cos * dir ); - - s = Math.sin( s * len ) / sin; - t = Math.sin( t * len ) / sin; - - } - - var tDir = t * dir; - - x0 = x0 * s + x1 * tDir; - y0 = y0 * s + y1 * tDir; - z0 = z0 * s + z1 * tDir; - w0 = w0 * s + w1 * tDir; - - // Normalize in case we just did a lerp: - if ( s === 1 - t ) { - - var f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 ); - - x0 *= f; - y0 *= f; - z0 *= f; - w0 *= f; - - } - - } - - dst[ dstOffset ] = x0; - dst[ dstOffset + 1 ] = y0; - dst[ dstOffset + 2 ] = z0; - dst[ dstOffset + 3 ] = w0; - - } - - } ); - - Object.defineProperties( Quaternion.prototype, { - - x: { - - get: function () { - - return this._x; - - }, - - set: function ( value ) { - - this._x = value; - this.onChangeCallback(); - - } - - }, - - y: { - - get: function () { - - return this._y; - - }, - - set: function ( value ) { - - this._y = value; - this.onChangeCallback(); - - } - - }, - - z: { - - get: function () { - - return this._z; - - }, - - set: function ( value ) { - - this._z = value; - this.onChangeCallback(); - - } - - }, - - w: { - - get: function () { - - return this._w; - - }, - - set: function ( value ) { - - this._w = value; - this.onChangeCallback(); - - } - - } - - } ); - - Object.assign( Quaternion.prototype, { - - set: function ( x, y, z, w ) { - - this._x = x; - this._y = y; - this._z = z; - this._w = w; - - this.onChangeCallback(); - - return this; - - }, - - clone: function () { - - return new this.constructor( this._x, this._y, this._z, this._w ); - - }, - - copy: function ( quaternion ) { - - this._x = quaternion.x; - this._y = quaternion.y; - this._z = quaternion.z; - this._w = quaternion.w; - - this.onChangeCallback(); - - return this; - - }, - - setFromEuler: function ( euler, update ) { - - if ( ! ( euler && euler.isEuler ) ) { - - throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' ); - - } - - var x = euler._x, y = euler._y, z = euler._z, order = euler.order; - - // http://www.mathworks.com/matlabcentral/fileexchange/ - // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/ - // content/SpinCalc.m - - var cos = Math.cos; - var sin = Math.sin; - - var c1 = cos( x / 2 ); - var c2 = cos( y / 2 ); - var c3 = cos( z / 2 ); - - var s1 = sin( x / 2 ); - var s2 = sin( y / 2 ); - var s3 = sin( z / 2 ); - - if ( order === 'XYZ' ) { - - this._x = s1 * c2 * c3 + c1 * s2 * s3; - this._y = c1 * s2 * c3 - s1 * c2 * s3; - this._z = c1 * c2 * s3 + s1 * s2 * c3; - this._w = c1 * c2 * c3 - s1 * s2 * s3; - - } else if ( order === 'YXZ' ) { - - this._x = s1 * c2 * c3 + c1 * s2 * s3; - this._y = c1 * s2 * c3 - s1 * c2 * s3; - this._z = c1 * c2 * s3 - s1 * s2 * c3; - this._w = c1 * c2 * c3 + s1 * s2 * s3; - - } else if ( order === 'ZXY' ) { - - this._x = s1 * c2 * c3 - c1 * s2 * s3; - this._y = c1 * s2 * c3 + s1 * c2 * s3; - this._z = c1 * c2 * s3 + s1 * s2 * c3; - this._w = c1 * c2 * c3 - s1 * s2 * s3; - - } else if ( order === 'ZYX' ) { - - this._x = s1 * c2 * c3 - c1 * s2 * s3; - this._y = c1 * s2 * c3 + s1 * c2 * s3; - this._z = c1 * c2 * s3 - s1 * s2 * c3; - this._w = c1 * c2 * c3 + s1 * s2 * s3; - - } else if ( order === 'YZX' ) { - - this._x = s1 * c2 * c3 + c1 * s2 * s3; - this._y = c1 * s2 * c3 + s1 * c2 * s3; - this._z = c1 * c2 * s3 - s1 * s2 * c3; - this._w = c1 * c2 * c3 - s1 * s2 * s3; - - } else if ( order === 'XZY' ) { - - this._x = s1 * c2 * c3 - c1 * s2 * s3; - this._y = c1 * s2 * c3 - s1 * c2 * s3; - this._z = c1 * c2 * s3 + s1 * s2 * c3; - this._w = c1 * c2 * c3 + s1 * s2 * s3; - - } - - if ( update !== false ) this.onChangeCallback(); - - return this; - - }, - - setFromAxisAngle: function ( axis, angle ) { - - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm - - // assumes axis is normalized - - var halfAngle = angle / 2, s = Math.sin( halfAngle ); - - this._x = axis.x * s; - this._y = axis.y * s; - this._z = axis.z * s; - this._w = Math.cos( halfAngle ); - - this.onChangeCallback(); - - return this; - - }, - - setFromRotationMatrix: function ( m ) { - - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm - - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - - var te = m.elements, - - m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], - m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], - m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ], - - trace = m11 + m22 + m33, - s; - - if ( trace > 0 ) { - - s = 0.5 / Math.sqrt( trace + 1.0 ); - - this._w = 0.25 / s; - this._x = ( m32 - m23 ) * s; - this._y = ( m13 - m31 ) * s; - this._z = ( m21 - m12 ) * s; - - } else if ( m11 > m22 && m11 > m33 ) { - - s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 ); - - this._w = ( m32 - m23 ) / s; - this._x = 0.25 * s; - this._y = ( m12 + m21 ) / s; - this._z = ( m13 + m31 ) / s; - - } else if ( m22 > m33 ) { - - s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 ); - - this._w = ( m13 - m31 ) / s; - this._x = ( m12 + m21 ) / s; - this._y = 0.25 * s; - this._z = ( m23 + m32 ) / s; - - } else { - - s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 ); - - this._w = ( m21 - m12 ) / s; - this._x = ( m13 + m31 ) / s; - this._y = ( m23 + m32 ) / s; - this._z = 0.25 * s; - - } - - this.onChangeCallback(); - - return this; - - }, - - setFromUnitVectors: function () { - - // assumes direction vectors vFrom and vTo are normalized - - var v1 = new Vector3(); - var r; - - var EPS = 0.000001; - - return function setFromUnitVectors( vFrom, vTo ) { - - if ( v1 === undefined ) v1 = new Vector3(); - - r = vFrom.dot( vTo ) + 1; - - if ( r < EPS ) { - - r = 0; - - if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { - - v1.set( - vFrom.y, vFrom.x, 0 ); - - } else { - - v1.set( 0, - vFrom.z, vFrom.y ); - - } - - } else { - - v1.crossVectors( vFrom, vTo ); - - } - - this._x = v1.x; - this._y = v1.y; - this._z = v1.z; - this._w = r; - - return this.normalize(); - - }; - - }(), - - inverse: function () { - - return this.conjugate().normalize(); - - }, - - conjugate: function () { - - this._x *= - 1; - this._y *= - 1; - this._z *= - 1; - - this.onChangeCallback(); - - return this; - - }, - - dot: function ( v ) { - - return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w; - - }, - - lengthSq: function () { - - return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; - - }, - - length: function () { - - return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w ); - - }, - - normalize: function () { - - var l = this.length(); - - if ( l === 0 ) { - - this._x = 0; - this._y = 0; - this._z = 0; - this._w = 1; - - } else { - - l = 1 / l; - - this._x = this._x * l; - this._y = this._y * l; - this._z = this._z * l; - this._w = this._w * l; - - } - - this.onChangeCallback(); - - return this; - - }, - - multiply: function ( q, p ) { - - if ( p !== undefined ) { - - console.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' ); - return this.multiplyQuaternions( q, p ); - - } - - return this.multiplyQuaternions( this, q ); - - }, - - premultiply: function ( q ) { - - return this.multiplyQuaternions( q, this ); - - }, - - multiplyQuaternions: function ( a, b ) { - - // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm - - var qax = a._x, qay = a._y, qaz = a._z, qaw = a._w; - var qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w; - - this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; - this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; - this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; - this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; - - this.onChangeCallback(); - - return this; - - }, - - slerp: function ( qb, t ) { - - if ( t === 0 ) return this; - if ( t === 1 ) return this.copy( qb ); - - var x = this._x, y = this._y, z = this._z, w = this._w; - - // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ - - var cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z; - - if ( cosHalfTheta < 0 ) { - - this._w = - qb._w; - this._x = - qb._x; - this._y = - qb._y; - this._z = - qb._z; - - cosHalfTheta = - cosHalfTheta; - - } else { - - this.copy( qb ); - - } - - if ( cosHalfTheta >= 1.0 ) { - - this._w = w; - this._x = x; - this._y = y; - this._z = z; - - return this; - - } - - var sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta ); - - if ( Math.abs( sinHalfTheta ) < 0.001 ) { - - this._w = 0.5 * ( w + this._w ); - this._x = 0.5 * ( x + this._x ); - this._y = 0.5 * ( y + this._y ); - this._z = 0.5 * ( z + this._z ); - - return this; - - } - - var halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta ); - var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta, - ratioB = Math.sin( t * halfTheta ) / sinHalfTheta; - - this._w = ( w * ratioA + this._w * ratioB ); - this._x = ( x * ratioA + this._x * ratioB ); - this._y = ( y * ratioA + this._y * ratioB ); - this._z = ( z * ratioA + this._z * ratioB ); - - this.onChangeCallback(); - - return this; - - }, - - equals: function ( quaternion ) { - - return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w ); - - }, - - fromArray: function ( array, offset ) { - - if ( offset === undefined ) offset = 0; - - this._x = array[ offset ]; - this._y = array[ offset + 1 ]; - this._z = array[ offset + 2 ]; - this._w = array[ offset + 3 ]; - - this.onChangeCallback(); - - return this; - - }, - - toArray: function ( array, offset ) { - - if ( array === undefined ) array = []; - if ( offset === undefined ) offset = 0; - - array[ offset ] = this._x; - array[ offset + 1 ] = this._y; - array[ offset + 2 ] = this._z; - array[ offset + 3 ] = this._w; - - return array; - - }, - - onChange: function ( callback ) { - - this.onChangeCallback = callback; - - return this; - - }, - - onChangeCallback: function () {} - - } ); - - function Vector3( x, y, z ) { - - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; - - } - - Object.assign( Vector3.prototype, { - - isVector3: true, - - set: function ( x, y, z ) { - - this.x = x; - this.y = y; - this.z = z; - - return this; - - }, - - setScalar: function ( scalar ) { - - this.x = scalar; - this.y = scalar; - this.z = scalar; - - return this; - - }, - - setX: function ( x ) { - - this.x = x; - - return this; - - }, - - setY: function ( y ) { - - this.y = y; - - return this; - - }, - - setZ: function ( z ) { - - this.z = z; - - return this; - - }, - - setComponent: function ( index, value ) { - - switch ( index ) { - - case 0: this.x = value; break; - case 1: this.y = value; break; - case 2: this.z = value; break; - default: throw new Error( 'index is out of range: ' + index ); - - } - - return this; - - }, - - getComponent: function ( index ) { - - switch ( index ) { - - case 0: return this.x; - case 1: return this.y; - case 2: return this.z; - default: throw new Error( 'index is out of range: ' + index ); - - } - - }, - - clone: function () { - - return new this.constructor( this.x, this.y, this.z ); - - }, - - copy: function ( v ) { - - this.x = v.x; - this.y = v.y; - this.z = v.z; - - return this; - - }, - - add: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); - return this.addVectors( v, w ); - - } - - this.x += v.x; - this.y += v.y; - this.z += v.z; - - return this; - - }, - - addScalar: function ( s ) { - - this.x += s; - this.y += s; - this.z += s; - - return this; - - }, - - addVectors: function ( a, b ) { - - this.x = a.x + b.x; - this.y = a.y + b.y; - this.z = a.z + b.z; - - return this; - - }, - - addScaledVector: function ( v, s ) { - - this.x += v.x * s; - this.y += v.y * s; - this.z += v.z * s; - - return this; - - }, - - sub: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); - return this.subVectors( v, w ); - - } - - this.x -= v.x; - this.y -= v.y; - this.z -= v.z; - - return this; - - }, - - subScalar: function ( s ) { - - this.x -= s; - this.y -= s; - this.z -= s; - - return this; - - }, - - subVectors: function ( a, b ) { - - this.x = a.x - b.x; - this.y = a.y - b.y; - this.z = a.z - b.z; - - return this; - - }, - - multiply: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' ); - return this.multiplyVectors( v, w ); - - } - - this.x *= v.x; - this.y *= v.y; - this.z *= v.z; - - return this; - - }, - - multiplyScalar: function ( scalar ) { - - this.x *= scalar; - this.y *= scalar; - this.z *= scalar; - - return this; - - }, - - multiplyVectors: function ( a, b ) { - - this.x = a.x * b.x; - this.y = a.y * b.y; - this.z = a.z * b.z; - - return this; - - }, - - applyEuler: function () { - - var quaternion = new Quaternion(); - - return function applyEuler( euler ) { - - if ( ! ( euler && euler.isEuler ) ) { - - console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' ); - - } - - return this.applyQuaternion( quaternion.setFromEuler( euler ) ); - - }; - - }(), - - applyAxisAngle: function () { - - var quaternion = new Quaternion(); - - return function applyAxisAngle( axis, angle ) { - - return this.applyQuaternion( quaternion.setFromAxisAngle( axis, angle ) ); - - }; - - }(), - - applyMatrix3: function ( m ) { - - var x = this.x, y = this.y, z = this.z; - var e = m.elements; - - this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z; - this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z; - this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z; - - return this; - - }, - - applyMatrix4: function ( m ) { - - var x = this.x, y = this.y, z = this.z; - var e = m.elements; - - var w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] ); - - this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w; - this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w; - this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w; - - return this; - - }, - - applyQuaternion: function ( q ) { - - var x = this.x, y = this.y, z = this.z; - var qx = q.x, qy = q.y, qz = q.z, qw = q.w; - - // calculate quat * vector - - var ix = qw * x + qy * z - qz * y; - var iy = qw * y + qz * x - qx * z; - var iz = qw * z + qx * y - qy * x; - var iw = - qx * x - qy * y - qz * z; - - // calculate result * inverse quat - - this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy; - this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz; - this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx; - - return this; - - }, - - project: function () { - - var matrix = new Matrix4(); - - return function project( camera ) { - - matrix.multiplyMatrices( camera.projectionMatrix, matrix.getInverse( camera.matrixWorld ) ); - return this.applyMatrix4( matrix ); - - }; - - }(), - - unproject: function () { - - var matrix = new Matrix4(); - - return function unproject( camera ) { - - matrix.multiplyMatrices( camera.matrixWorld, matrix.getInverse( camera.projectionMatrix ) ); - return this.applyMatrix4( matrix ); - - }; - - }(), - - transformDirection: function ( m ) { - - // input: THREE.Matrix4 affine matrix - // vector interpreted as a direction - - var x = this.x, y = this.y, z = this.z; - var e = m.elements; - - this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z; - this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z; - this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z; - - return this.normalize(); - - }, - - divide: function ( v ) { - - this.x /= v.x; - this.y /= v.y; - this.z /= v.z; - - return this; - - }, - - divideScalar: function ( scalar ) { - - return this.multiplyScalar( 1 / scalar ); - - }, - - min: function ( v ) { - - this.x = Math.min( this.x, v.x ); - this.y = Math.min( this.y, v.y ); - this.z = Math.min( this.z, v.z ); - - return this; - - }, - - max: function ( v ) { - - this.x = Math.max( this.x, v.x ); - this.y = Math.max( this.y, v.y ); - this.z = Math.max( this.z, v.z ); - - return this; - - }, - - clamp: function ( min, max ) { - - // assumes min < max, componentwise - - this.x = Math.max( min.x, Math.min( max.x, this.x ) ); - this.y = Math.max( min.y, Math.min( max.y, this.y ) ); - this.z = Math.max( min.z, Math.min( max.z, this.z ) ); - - return this; - - }, - - clampScalar: function () { - - var min = new Vector3(); - var max = new Vector3(); - - return function clampScalar( minVal, maxVal ) { - - min.set( minVal, minVal, minVal ); - max.set( maxVal, maxVal, maxVal ); - - return this.clamp( min, max ); - - }; - - }(), - - clampLength: function ( min, max ) { - - var length = this.length(); - - return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); - - }, - - floor: function () { - - this.x = Math.floor( this.x ); - this.y = Math.floor( this.y ); - this.z = Math.floor( this.z ); - - return this; - - }, - - ceil: function () { - - this.x = Math.ceil( this.x ); - this.y = Math.ceil( this.y ); - this.z = Math.ceil( this.z ); - - return this; - - }, - - round: function () { - - this.x = Math.round( this.x ); - this.y = Math.round( this.y ); - this.z = Math.round( this.z ); - - return this; - - }, - - roundToZero: function () { - - this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x ); - this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y ); - this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z ); - - return this; - - }, - - negate: function () { - - this.x = - this.x; - this.y = - this.y; - this.z = - this.z; - - return this; - - }, - - dot: function ( v ) { - - return this.x * v.x + this.y * v.y + this.z * v.z; - - }, - - // TODO lengthSquared? - - lengthSq: function () { - - return this.x * this.x + this.y * this.y + this.z * this.z; - - }, - - length: function () { - - return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); - - }, - - manhattanLength: function () { - - return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ); - - }, - - normalize: function () { - - return this.divideScalar( this.length() || 1 ); - - }, - - setLength: function ( length ) { - - return this.normalize().multiplyScalar( length ); - - }, - - lerp: function ( v, alpha ) { - - this.x += ( v.x - this.x ) * alpha; - this.y += ( v.y - this.y ) * alpha; - this.z += ( v.z - this.z ) * alpha; - - return this; - - }, - - lerpVectors: function ( v1, v2, alpha ) { - - return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 ); - - }, - - cross: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' ); - return this.crossVectors( v, w ); - - } - - return this.crossVectors( this, v ); - - }, - - crossVectors: function ( a, b ) { - - var ax = a.x, ay = a.y, az = a.z; - var bx = b.x, by = b.y, bz = b.z; - - this.x = ay * bz - az * by; - this.y = az * bx - ax * bz; - this.z = ax * by - ay * bx; - - return this; - - }, - - projectOnVector: function ( vector ) { - - var scalar = vector.dot( this ) / vector.lengthSq(); - - return this.copy( vector ).multiplyScalar( scalar ); - - }, - - projectOnPlane: function () { - - var v1 = new Vector3(); - - return function projectOnPlane( planeNormal ) { - - v1.copy( this ).projectOnVector( planeNormal ); - - return this.sub( v1 ); - - }; - - }(), - - reflect: function () { - - // reflect incident vector off plane orthogonal to normal - // normal is assumed to have unit length - - var v1 = new Vector3(); - - return function reflect( normal ) { - - return this.sub( v1.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) ); - - }; - - }(), - - angleTo: function ( v ) { - - var theta = this.dot( v ) / ( Math.sqrt( this.lengthSq() * v.lengthSq() ) ); - - // clamp, to handle numerical problems - - return Math.acos( _Math.clamp( theta, - 1, 1 ) ); - - }, - - distanceTo: function ( v ) { - - return Math.sqrt( this.distanceToSquared( v ) ); - - }, - - distanceToSquared: function ( v ) { - - var dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z; - - return dx * dx + dy * dy + dz * dz; - - }, - - manhattanDistanceTo: function ( v ) { - - return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z ); - - }, - - setFromSpherical: function ( s ) { - - var sinPhiRadius = Math.sin( s.phi ) * s.radius; - - this.x = sinPhiRadius * Math.sin( s.theta ); - this.y = Math.cos( s.phi ) * s.radius; - this.z = sinPhiRadius * Math.cos( s.theta ); - - return this; - - }, - - setFromCylindrical: function ( c ) { - - this.x = c.radius * Math.sin( c.theta ); - this.y = c.y; - this.z = c.radius * Math.cos( c.theta ); - - return this; - - }, - - setFromMatrixPosition: function ( m ) { - - var e = m.elements; - - this.x = e[ 12 ]; - this.y = e[ 13 ]; - this.z = e[ 14 ]; - - return this; - - }, - - setFromMatrixScale: function ( m ) { - - var sx = this.setFromMatrixColumn( m, 0 ).length(); - var sy = this.setFromMatrixColumn( m, 1 ).length(); - var sz = this.setFromMatrixColumn( m, 2 ).length(); - - this.x = sx; - this.y = sy; - this.z = sz; - - return this; - - }, - - setFromMatrixColumn: function ( m, index ) { - - return this.fromArray( m.elements, index * 4 ); - - }, - - equals: function ( v ) { - - return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) ); - - }, - - fromArray: function ( array, offset ) { - - if ( offset === undefined ) offset = 0; - - this.x = array[ offset ]; - this.y = array[ offset + 1 ]; - this.z = array[ offset + 2 ]; - - return this; - - }, - - toArray: function ( array, offset ) { - - if ( array === undefined ) array = []; - if ( offset === undefined ) offset = 0; - - array[ offset ] = this.x; - array[ offset + 1 ] = this.y; - array[ offset + 2 ] = this.z; - - return array; - - }, - - fromBufferAttribute: function ( attribute, index, offset ) { - - if ( offset !== undefined ) { - - console.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' ); - - } - - this.x = attribute.getX( index ); - this.y = attribute.getY( index ); - this.z = attribute.getZ( index ); - - return this; - - } - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module.todo( 'Polyfills', () => { - - // PUBLIC STUFF - QUnit.test( "Number.EPSILON", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "Number.isInteger", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign - //http://people.mozilla.org/~jorendorff/es6-draft.html#sec-math.sign - /* - 20.2.2.29 Math.sign(x) - - Returns the sign of the x, indicating whether x is positive, negative or zero. - - If x is NaN, the result is NaN. - If x is -0, the result is -0. - If x is +0, the result is +0. - If x is negative and not -0, the result is -1. - If x is positive and not +0, the result is +1. - */ - QUnit.test( "Math.sign", ( assert ) => { - - assert.ok( isNaN( Math.sign( NaN ) ), "If x is NaN, the result is NaN." ); - assert.ok( isNaN( Math.sign( new Vector3() ) ), "If x is NaN, the result is NaN." ); - assert.ok( isNaN( Math.sign() ), "If x is NaN, the result is NaN." ); - assert.ok( isNaN( Math.sign( '--3' ) ), "If x is NaN<'--3'>, the result is NaN." ); - assert.ok( isNegativeZero( Math.sign( - 0 ) ), "If x is -0, the result is -0." ); - assert.ok( Math.sign( + 0 ) === + 0, "If x is +0, the result is +0." ); - assert.ok( Math.sign( - Infinity ) === - 1, "If x is negative<-Infinity> and not -0, the result is -1." ); - assert.ok( Math.sign( '-3' ) === - 1, "If x is negative<'-3'> and not -0, the result is -1." ); - assert.ok( Math.sign( '-1e-10' ) === - 1, "If x is negative<'-1e-10'> and not -0, the result is -1." ); - assert.ok( Math.sign( + Infinity ) === + 1, "If x is positive<+Infinity> and not +0, the result is +1." ); - assert.ok( Math.sign( '+3' ) === + 1, "If x is positive<'+3'> and not +0, the result is +1." ); - - // Comparing with -0 is tricky because 0 === -0. But - // luckily 1 / -0 === -Infinity so we can use that. - - function isNegativeZero( value ) { - - return value === 0 && 1 / value < 0; - - } - - } ); - - QUnit.test( "'name' in Function.prototype", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "Object.assign", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function arrayMin( array ) { - - if ( array.length === 0 ) return Infinity; - - var min = array[ 0 ]; - - for ( var i = 1, l = array.length; i < l; ++ i ) { - - if ( array[ i ] < min ) min = array[ i ]; - - } - - return min; - - } - - function arrayMax( array ) { - - if ( array.length === 0 ) return - Infinity; - - var max = array[ 0 ]; - - for ( var i = 1, l = array.length; i < l; ++ i ) { - - if ( array[ i ] > max ) max = array[ i ]; - - } - - return max; - - } - - /** - * @author alemures / https://github.com/alemures - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'utils', () => { - - QUnit.test( 'arrayMin', ( assert ) => { - - assert.equal( arrayMin( [] ), Infinity, 'Empty array return positive infinit' ); - assert.equal( arrayMin( [ 5 ] ), 5, 'Single valued array should return the unique value as minimum' ); - assert.equal( arrayMin( [ 1, 5, 10 ] ), 1, 'The array [ 1, 5, 10 ] return 1' ); - assert.equal( arrayMin( [ 5, 1, 10 ] ), 1, 'The array [ 5, 1, 10 ] return 1' ); - assert.equal( arrayMin( [ 10, 5, 1 ] ), 1, 'The array [ 10, 5, 1 ] return 1' ); - assert.equal( arrayMax( [ - 0, 0 ] ), - 0, 'The array [ - 0, 0 ] return -0' ); - assert.equal( arrayMin( [ - Infinity, 0, Infinity ] ), - Infinity, 'The array [ - Infinity, 0, Infinity ] return -Infinity' ); - - } ); - - QUnit.test( 'arrayMax', ( assert ) => { - - assert.equal( arrayMax( [] ), - Infinity, 'Empty array return negative infinit' ); - assert.equal( arrayMax( [ 5 ] ), 5, 'Single valued array should return the unique value as maximum' ); - assert.equal( arrayMax( [ 10, 5, 1 ] ), 10, 'The array [ 10, 5, 1 ] return 10' ); - assert.equal( arrayMax( [ 1, 10, 5 ] ), 10, 'The array [ 1, 10, 5 ] return 10' ); - assert.equal( arrayMax( [ 1, 5, 10 ] ), 10, 'The array [ 1, 5, 10 ] return 10' ); - assert.equal( arrayMax( [ - 0, 0 ] ), 0, 'The array [ - 0, 0 ] return 0' ); - assert.equal( arrayMax( [ - Infinity, 0, Infinity ] ), Infinity, 'The array [ - Infinity, 0, Infinity ] return Infinity' ); - - } ); - - - } ); - - function AnimationAction( mixer, clip, localRoot ) { - - this._mixer = mixer; - this._clip = clip; - this._localRoot = localRoot || null; - - var tracks = clip.tracks, - nTracks = tracks.length, - interpolants = new Array( nTracks ); - - var interpolantSettings = { - endingStart: ZeroCurvatureEnding, - endingEnd: ZeroCurvatureEnding - }; - - for ( var i = 0; i !== nTracks; ++ i ) { - - var interpolant = tracks[ i ].createInterpolant( null ); - interpolants[ i ] = interpolant; - interpolant.settings = interpolantSettings; - - } - - this._interpolantSettings = interpolantSettings; - - this._interpolants = interpolants; // bound by the mixer - - // inside: PropertyMixer (managed by the mixer) - this._propertyBindings = new Array( nTracks ); - - this._cacheIndex = null; // for the memory manager - this._byClipCacheIndex = null; // for the memory manager - - this._timeScaleInterpolant = null; - this._weightInterpolant = null; - - this.loop = LoopRepeat; - this._loopCount = - 1; - - // global mixer time when the action is to be started - // it's set back to 'null' upon start of the action - this._startTime = null; - - // scaled local time of the action - // gets clamped or wrapped to 0..clip.duration according to loop - this.time = 0; - - this.timeScale = 1; - this._effectiveTimeScale = 1; - - this.weight = 1; - this._effectiveWeight = 1; - - this.repetitions = Infinity; // no. of repetitions when looping - - this.paused = false; // true -> zero effective time scale - this.enabled = true; // false -> zero effective weight - - this.clampWhenFinished = false; // keep feeding the last frame? - - this.zeroSlopeAtStart = true; // for smooth interpolation w/o separate - this.zeroSlopeAtEnd = true; // clips for start, loop and end - - } - - Object.assign( AnimationAction.prototype, { - - // State & Scheduling - - play: function () { - - this._mixer._activateAction( this ); - - return this; - - }, - - stop: function () { - - this._mixer._deactivateAction( this ); - - return this.reset(); - - }, - - reset: function () { - - this.paused = false; - this.enabled = true; - - this.time = 0; // restart clip - this._loopCount = - 1; // forget previous loops - this._startTime = null; // forget scheduling - - return this.stopFading().stopWarping(); - - }, - - isRunning: function () { - - return this.enabled && ! this.paused && this.timeScale !== 0 && - this._startTime === null && this._mixer._isActiveAction( this ); - - }, - - // return true when play has been called - isScheduled: function () { - - return this._mixer._isActiveAction( this ); - - }, - - startAt: function ( time ) { - - this._startTime = time; - - return this; - - }, - - setLoop: function ( mode, repetitions ) { - - this.loop = mode; - this.repetitions = repetitions; - - return this; - - }, - - // Weight - - // set the weight stopping any scheduled fading - // although .enabled = false yields an effective weight of zero, this - // method does *not* change .enabled, because it would be confusing - setEffectiveWeight: function ( weight ) { - - this.weight = weight; - - // note: same logic as when updated at runtime - this._effectiveWeight = this.enabled ? weight : 0; - - return this.stopFading(); - - }, - - // return the weight considering fading and .enabled - getEffectiveWeight: function () { - - return this._effectiveWeight; - - }, - - fadeIn: function ( duration ) { - - return this._scheduleFading( duration, 0, 1 ); - - }, - - fadeOut: function ( duration ) { - - return this._scheduleFading( duration, 1, 0 ); - - }, - - crossFadeFrom: function ( fadeOutAction, duration, warp ) { - - fadeOutAction.fadeOut( duration ); - this.fadeIn( duration ); - - if ( warp ) { - - var fadeInDuration = this._clip.duration, - fadeOutDuration = fadeOutAction._clip.duration, - - startEndRatio = fadeOutDuration / fadeInDuration, - endStartRatio = fadeInDuration / fadeOutDuration; - - fadeOutAction.warp( 1.0, startEndRatio, duration ); - this.warp( endStartRatio, 1.0, duration ); - - } - - return this; - - }, - - crossFadeTo: function ( fadeInAction, duration, warp ) { - - return fadeInAction.crossFadeFrom( this, duration, warp ); - - }, - - stopFading: function () { - - var weightInterpolant = this._weightInterpolant; - - if ( weightInterpolant !== null ) { - - this._weightInterpolant = null; - this._mixer._takeBackControlInterpolant( weightInterpolant ); - - } - - return this; - - }, - - // Time Scale Control - - // set the time scale stopping any scheduled warping - // although .paused = true yields an effective time scale of zero, this - // method does *not* change .paused, because it would be confusing - setEffectiveTimeScale: function ( timeScale ) { - - this.timeScale = timeScale; - this._effectiveTimeScale = this.paused ? 0 : timeScale; - - return this.stopWarping(); - - }, - - // return the time scale considering warping and .paused - getEffectiveTimeScale: function () { - - return this._effectiveTimeScale; - - }, - - setDuration: function ( duration ) { - - this.timeScale = this._clip.duration / duration; - - return this.stopWarping(); - - }, - - syncWith: function ( action ) { - - this.time = action.time; - this.timeScale = action.timeScale; - - return this.stopWarping(); - - }, - - halt: function ( duration ) { - - return this.warp( this._effectiveTimeScale, 0, duration ); - - }, - - warp: function ( startTimeScale, endTimeScale, duration ) { - - var mixer = this._mixer, now = mixer.time, - interpolant = this._timeScaleInterpolant, - - timeScale = this.timeScale; - - if ( interpolant === null ) { - - interpolant = mixer._lendControlInterpolant(); - this._timeScaleInterpolant = interpolant; - - } - - var times = interpolant.parameterPositions, - values = interpolant.sampleValues; - - times[ 0 ] = now; - times[ 1 ] = now + duration; - - values[ 0 ] = startTimeScale / timeScale; - values[ 1 ] = endTimeScale / timeScale; - - return this; - - }, - - stopWarping: function () { - - var timeScaleInterpolant = this._timeScaleInterpolant; - - if ( timeScaleInterpolant !== null ) { - - this._timeScaleInterpolant = null; - this._mixer._takeBackControlInterpolant( timeScaleInterpolant ); - - } - - return this; - - }, - - // Object Accessors - - getMixer: function () { - - return this._mixer; - - }, - - getClip: function () { - - return this._clip; - - }, - - getRoot: function () { - - return this._localRoot || this._mixer._root; - - }, - - // Interna - - _update: function ( time, deltaTime, timeDirection, accuIndex ) { - - // called by the mixer - - if ( ! this.enabled ) { - - // call ._updateWeight() to update ._effectiveWeight - - this._updateWeight( time ); - return; - - } - - var startTime = this._startTime; - - if ( startTime !== null ) { - - // check for scheduled start of action - - var timeRunning = ( time - startTime ) * timeDirection; - if ( timeRunning < 0 || timeDirection === 0 ) { - - return; // yet to come / don't decide when delta = 0 - - } - - // start - - this._startTime = null; // unschedule - deltaTime = timeDirection * timeRunning; - - } - - // apply time scale and advance time - - deltaTime *= this._updateTimeScale( time ); - var clipTime = this._updateTime( deltaTime ); - - // note: _updateTime may disable the action resulting in - // an effective weight of 0 - - var weight = this._updateWeight( time ); - - if ( weight > 0 ) { - - var interpolants = this._interpolants; - var propertyMixers = this._propertyBindings; - - for ( var j = 0, m = interpolants.length; j !== m; ++ j ) { - - interpolants[ j ].evaluate( clipTime ); - propertyMixers[ j ].accumulate( accuIndex, weight ); - - } - - } - - }, - - _updateWeight: function ( time ) { - - var weight = 0; - - if ( this.enabled ) { - - weight = this.weight; - var interpolant = this._weightInterpolant; - - if ( interpolant !== null ) { - - var interpolantValue = interpolant.evaluate( time )[ 0 ]; - - weight *= interpolantValue; - - if ( time > interpolant.parameterPositions[ 1 ] ) { - - this.stopFading(); - - if ( interpolantValue === 0 ) { - - // faded out, disable - this.enabled = false; - - } - - } - - } - - } - - this._effectiveWeight = weight; - return weight; - - }, - - _updateTimeScale: function ( time ) { - - var timeScale = 0; - - if ( ! this.paused ) { - - timeScale = this.timeScale; - - var interpolant = this._timeScaleInterpolant; - - if ( interpolant !== null ) { - - var interpolantValue = interpolant.evaluate( time )[ 0 ]; - - timeScale *= interpolantValue; - - if ( time > interpolant.parameterPositions[ 1 ] ) { - - this.stopWarping(); - - if ( timeScale === 0 ) { - - // motion has halted, pause - this.paused = true; - - } else { - - // warp done - apply final time scale - this.timeScale = timeScale; - - } - - } - - } - - } - - this._effectiveTimeScale = timeScale; - return timeScale; - - }, - - _updateTime: function ( deltaTime ) { - - var time = this.time + deltaTime; - - if ( deltaTime === 0 ) return time; - - var duration = this._clip.duration, - - loop = this.loop, - loopCount = this._loopCount; - - if ( loop === LoopOnce ) { - - if ( loopCount === - 1 ) { - - // just started - - this._loopCount = 0; - this._setEndings( true, true, false ); - - } - - handle_stop: { - - if ( time >= duration ) { - - time = duration; - - } else if ( time < 0 ) { - - time = 0; - - } else break handle_stop; - - if ( this.clampWhenFinished ) this.paused = true; - else this.enabled = false; - - this._mixer.dispatchEvent( { - type: 'finished', action: this, - direction: deltaTime < 0 ? - 1 : 1 - } ); - - } - - } else { // repetitive Repeat or PingPong - - var pingPong = ( loop === LoopPingPong ); - - if ( loopCount === - 1 ) { - - // just started - - if ( deltaTime >= 0 ) { - - loopCount = 0; - - this._setEndings( true, this.repetitions === 0, pingPong ); - - } else { - - // when looping in reverse direction, the initial - // transition through zero counts as a repetition, - // so leave loopCount at -1 - - this._setEndings( this.repetitions === 0, true, pingPong ); - - } - - } - - if ( time >= duration || time < 0 ) { - - // wrap around - - var loopDelta = Math.floor( time / duration ); // signed - time -= duration * loopDelta; - - loopCount += Math.abs( loopDelta ); - - var pending = this.repetitions - loopCount; - - if ( pending < 0 ) { - - // have to stop (switch state, clamp time, fire event) - - if ( this.clampWhenFinished ) this.paused = true; - else this.enabled = false; - - time = deltaTime > 0 ? duration : 0; - - this._mixer.dispatchEvent( { - type: 'finished', action: this, - direction: deltaTime > 0 ? 1 : - 1 - } ); - - } else { - - // keep running - - if ( pending === 0 ) { - - // entering the last round - - var atStart = deltaTime < 0; - this._setEndings( atStart, ! atStart, pingPong ); - - } else { - - this._setEndings( false, false, pingPong ); - - } - - this._loopCount = loopCount; - - this._mixer.dispatchEvent( { - type: 'loop', action: this, loopDelta: loopDelta - } ); - - } - - } - - if ( pingPong && ( loopCount & 1 ) === 1 ) { - - // invert time for the "pong round" - - this.time = time; - return duration - time; - - } - - } - - this.time = time; - return time; - - }, - - _setEndings: function ( atStart, atEnd, pingPong ) { - - var settings = this._interpolantSettings; - - if ( pingPong ) { - - settings.endingStart = ZeroSlopeEnding; - settings.endingEnd = ZeroSlopeEnding; - - } else { - - // assuming for LoopOnce atStart == atEnd == true - - if ( atStart ) { - - settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding; - - } else { - - settings.endingStart = WrapAroundEnding; - - } - - if ( atEnd ) { - - settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding; - - } else { - - settings.endingEnd = WrapAroundEnding; - - } - - } - - }, - - _scheduleFading: function ( duration, weightNow, weightThen ) { - - var mixer = this._mixer, now = mixer.time, - interpolant = this._weightInterpolant; - - if ( interpolant === null ) { - - interpolant = mixer._lendControlInterpolant(); - this._weightInterpolant = interpolant; - - } - - var times = interpolant.parameterPositions, - values = interpolant.sampleValues; - - times[ 0 ] = now; values[ 0 ] = weightNow; - times[ 1 ] = now + duration; values[ 1 ] = weightThen; - - return this; - - } - - } ); - - /** - * https://github.com/mrdoob/eventdispatcher.js/ - */ - - function EventDispatcher() {} - - Object.assign( EventDispatcher.prototype, { - - addEventListener: function ( type, listener ) { - - if ( this._listeners === undefined ) this._listeners = {}; - - var listeners = this._listeners; - - if ( listeners[ type ] === undefined ) { - - listeners[ type ] = []; - - } - - if ( listeners[ type ].indexOf( listener ) === - 1 ) { - - listeners[ type ].push( listener ); - - } - - }, - - hasEventListener: function ( type, listener ) { - - if ( this._listeners === undefined ) return false; - - var listeners = this._listeners; - - return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1; - - }, - - removeEventListener: function ( type, listener ) { - - if ( this._listeners === undefined ) return; - - var listeners = this._listeners; - var listenerArray = listeners[ type ]; - - if ( listenerArray !== undefined ) { - - var index = listenerArray.indexOf( listener ); - - if ( index !== - 1 ) { - - listenerArray.splice( index, 1 ); - - } - - } - - }, - - dispatchEvent: function ( event ) { - - if ( this._listeners === undefined ) return; - - var listeners = this._listeners; - var listenerArray = listeners[ event.type ]; - - if ( listenerArray !== undefined ) { - - event.target = this; - - var array = listenerArray.slice( 0 ); - - for ( var i = 0, l = array.length; i < l; i ++ ) { - - array[ i ].call( this, event ); - - } - - } - - } - - } ); - - /** - * Abstract base class of interpolants over parametric samples. - * - * The parameter domain is one dimensional, typically the time or a path - * along a curve defined by the data. - * - * The sample values can have any dimensionality and derived classes may - * apply special interpretations to the data. - * - * This class provides the interval seek in a Template Method, deferring - * the actual interpolation to derived classes. - * - * Time complexity is O(1) for linear access crossing at most two points - * and O(log N) for random access, where N is the number of positions. - * - * References: - * - * http://www.oodesign.com/template-method-pattern.html - * - * @author tschw - */ - - function Interpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - - this.parameterPositions = parameterPositions; - this._cachedIndex = 0; - - this.resultBuffer = resultBuffer !== undefined ? - resultBuffer : new sampleValues.constructor( sampleSize ); - this.sampleValues = sampleValues; - this.valueSize = sampleSize; - - } - - Object.assign( Interpolant.prototype, { - - evaluate: function ( t ) { - - var pp = this.parameterPositions, - i1 = this._cachedIndex, - - t1 = pp[ i1 ], - t0 = pp[ i1 - 1 ]; - - validate_interval: { - - seek: { - - var right; - - linear_scan: { - - //- See http://jsperf.com/comparison-to-undefined/3 - //- slower code: - //- - //- if ( t >= t1 || t1 === undefined ) { - forward_scan: if ( ! ( t < t1 ) ) { - - for ( var giveUpAt = i1 + 2; ; ) { - - if ( t1 === undefined ) { - - if ( t < t0 ) break forward_scan; - - // after end - - i1 = pp.length; - this._cachedIndex = i1; - return this.afterEnd_( i1 - 1, t, t0 ); - - } - - if ( i1 === giveUpAt ) break; // this loop - - t0 = t1; - t1 = pp[ ++ i1 ]; - - if ( t < t1 ) { - - // we have arrived at the sought interval - break seek; - - } - - } - - // prepare binary search on the right side of the index - right = pp.length; - break linear_scan; - - } - - //- slower code: - //- if ( t < t0 || t0 === undefined ) { - if ( ! ( t >= t0 ) ) { - - // looping? - - var t1global = pp[ 1 ]; - - if ( t < t1global ) { - - i1 = 2; // + 1, using the scan for the details - t0 = t1global; - - } - - // linear reverse scan - - for ( var giveUpAt = i1 - 2; ; ) { - - if ( t0 === undefined ) { - - // before start - - this._cachedIndex = 0; - return this.beforeStart_( 0, t, t1 ); - - } - - if ( i1 === giveUpAt ) break; // this loop - - t1 = t0; - t0 = pp[ -- i1 - 1 ]; - - if ( t >= t0 ) { - - // we have arrived at the sought interval - break seek; - - } - - } - - // prepare binary search on the left side of the index - right = i1; - i1 = 0; - break linear_scan; - - } - - // the interval is valid - - break validate_interval; - - } // linear scan - - // binary search - - while ( i1 < right ) { - - var mid = ( i1 + right ) >>> 1; - - if ( t < pp[ mid ] ) { - - right = mid; - - } else { - - i1 = mid + 1; - - } - - } - - t1 = pp[ i1 ]; - t0 = pp[ i1 - 1 ]; - - // check boundary cases, again - - if ( t0 === undefined ) { - - this._cachedIndex = 0; - return this.beforeStart_( 0, t, t1 ); - - } - - if ( t1 === undefined ) { - - i1 = pp.length; - this._cachedIndex = i1; - return this.afterEnd_( i1 - 1, t0, t ); - - } - - } // seek - - this._cachedIndex = i1; - - this.intervalChanged_( i1, t0, t1 ); - - } // validate_interval - - return this.interpolate_( i1, t0, t, t1 ); - - }, - - settings: null, // optional, subclass-specific settings structure - // Note: The indirection allows central control of many interpolants. - - // --- Protected interface - - DefaultSettings_: {}, - - getSettings_: function () { - - return this.settings || this.DefaultSettings_; - - }, - - copySampleValue_: function ( index ) { - - // copies a sample value to the result buffer - - var result = this.resultBuffer, - values = this.sampleValues, - stride = this.valueSize, - offset = index * stride; - - for ( var i = 0; i !== stride; ++ i ) { - - result[ i ] = values[ offset + i ]; - - } - - return result; - - }, - - // Template methods for derived classes: - - interpolate_: function ( /* i1, t0, t, t1 */ ) { - - throw new Error( 'call to abstract method' ); - // implementations shall return this.resultBuffer - - }, - - intervalChanged_: function ( /* i1, t0, t1 */ ) { - - // empty - - } - - } ); - - //!\ DECLARE ALIAS AFTER assign prototype ! - Object.assign( Interpolant.prototype, { - - //( 0, t, t0 ), returns this.resultBuffer - beforeStart_: Interpolant.prototype.copySampleValue_, - - //( N-1, tN-1, t ), returns this.resultBuffer - afterEnd_: Interpolant.prototype.copySampleValue_, - - } ); - - function LinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - - Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); - - } - - LinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { - - constructor: LinearInterpolant, - - interpolate_: function ( i1, t0, t, t1 ) { - - var result = this.resultBuffer, - values = this.sampleValues, - stride = this.valueSize, - - offset1 = i1 * stride, - offset0 = offset1 - stride, - - weight1 = ( t - t0 ) / ( t1 - t0 ), - weight0 = 1 - weight1; - - for ( var i = 0; i !== stride; ++ i ) { - - result[ i ] = - values[ offset0 + i ] * weight0 + - values[ offset1 + i ] * weight1; - - } - - return result; - - } - - } ); - - /** - * - * A reference to a real property in the scene graph. - * - * - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - * @author tschw - */ - - function Composite( targetGroup, path, optionalParsedPath ) { - - var parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path ); - - this._targetGroup = targetGroup; - this._bindings = targetGroup.subscribe_( path, parsedPath ); - - } - - Object.assign( Composite.prototype, { - - getValue: function ( array, offset ) { - - this.bind(); // bind all binding - - var firstValidIndex = this._targetGroup.nCachedObjects_, - binding = this._bindings[ firstValidIndex ]; - - // and only call .getValue on the first - if ( binding !== undefined ) binding.getValue( array, offset ); - - }, - - setValue: function ( array, offset ) { - - var bindings = this._bindings; - - for ( var i = this._targetGroup.nCachedObjects_, - n = bindings.length; i !== n; ++ i ) { - - bindings[ i ].setValue( array, offset ); - - } - - }, - - bind: function () { - - var bindings = this._bindings; - - for ( var i = this._targetGroup.nCachedObjects_, - n = bindings.length; i !== n; ++ i ) { - - bindings[ i ].bind(); - - } - - }, - - unbind: function () { - - var bindings = this._bindings; - - for ( var i = this._targetGroup.nCachedObjects_, - n = bindings.length; i !== n; ++ i ) { - - bindings[ i ].unbind(); - - } - - } - - } ); - - - function PropertyBinding( rootNode, path, parsedPath ) { - - this.path = path; - this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path ); - - this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ) || rootNode; - - this.rootNode = rootNode; - - } - - Object.assign( PropertyBinding, { - - Composite: Composite, - - create: function ( root, path, parsedPath ) { - - if ( ! ( root && root.isAnimationObjectGroup ) ) { - - return new PropertyBinding( root, path, parsedPath ); - - } else { - - return new PropertyBinding.Composite( root, path, parsedPath ); - - } - - }, - - /** - * Replaces spaces with underscores and removes unsupported characters from - * node names, to ensure compatibility with parseTrackName(). - * - * @param {string} name Node name to be sanitized. - * @return {string} - */ - sanitizeNodeName: function ( name ) { - - return name.replace( /\s/g, '_' ).replace( /[^\w-]/g, '' ); - - }, - - parseTrackName: function () { - - // Parent directories, delimited by '/' or ':'. Currently unused, but must - // be matched to parse the rest of the track name. - var directoryRe = /((?:[\w-]+[\/:])*)/; - - // Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'. - var nodeRe = /([\w-\.]+)?/; - - // Object on target node, and accessor. Name may contain only word - // characters. Accessor may contain any character except closing bracket. - var objectRe = /(?:\.([\w-]+)(?:\[(.+)\])?)?/; - - // Property and accessor. May contain only word characters. Accessor may - // contain any non-bracket characters. - var propertyRe = /\.([\w-]+)(?:\[(.+)\])?/; - - var trackRe = new RegExp( '' - + '^' - + directoryRe.source - + nodeRe.source - + objectRe.source - + propertyRe.source - + '$' - ); - - var supportedObjectNames = [ 'material', 'materials', 'bones' ]; - - return function ( trackName ) { - - var matches = trackRe.exec( trackName ); - - if ( ! matches ) { - - throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName ); - - } - - var results = { - // directoryName: matches[ 1 ], // (tschw) currently unused - nodeName: matches[ 2 ], - objectName: matches[ 3 ], - objectIndex: matches[ 4 ], - propertyName: matches[ 5 ], // required - propertyIndex: matches[ 6 ] - }; - - var lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' ); - - if ( lastDot !== undefined && lastDot !== - 1 ) { - - var objectName = results.nodeName.substring( lastDot + 1 ); - - // Object names must be checked against a whitelist. Otherwise, there - // is no way to parse 'foo.bar.baz': 'baz' must be a property, but - // 'bar' could be the objectName, or part of a nodeName (which can - // include '.' characters). - if ( supportedObjectNames.indexOf( objectName ) !== - 1 ) { - - results.nodeName = results.nodeName.substring( 0, lastDot ); - results.objectName = objectName; - - } - - } - - if ( results.propertyName === null || results.propertyName.length === 0 ) { - - throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName ); - - } - - return results; - - }; - - }(), - - findNode: function ( root, nodeName ) { - - if ( ! nodeName || nodeName === "" || nodeName === "root" || nodeName === "." || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) { - - return root; - - } - - // search into skeleton bones. - if ( root.skeleton ) { - - var searchSkeleton = function ( skeleton ) { - - for ( var i = 0; i < skeleton.bones.length; i ++ ) { - - var bone = skeleton.bones[ i ]; - - if ( bone.name === nodeName ) { - - return bone; - - } - - } - - return null; - - }; - - var bone = searchSkeleton( root.skeleton ); - - if ( bone ) { - - return bone; - - } - - } - - // search into node subtree. - if ( root.children ) { - - var searchNodeSubtree = function ( children ) { - - for ( var i = 0; i < children.length; i ++ ) { - - var childNode = children[ i ]; - - if ( childNode.name === nodeName || childNode.uuid === nodeName ) { - - return childNode; - - } - - var result = searchNodeSubtree( childNode.children ); - - if ( result ) return result; - - } - - return null; - - }; - - var subTreeNode = searchNodeSubtree( root.children ); - - if ( subTreeNode ) { - - return subTreeNode; - - } - - } - - return null; - - } - - } ); - - Object.assign( PropertyBinding.prototype, { // prototype, continued - - // these are used to "bind" a nonexistent property - _getValue_unavailable: function () {}, - _setValue_unavailable: function () {}, - - BindingType: { - Direct: 0, - EntireArray: 1, - ArrayElement: 2, - HasFromToArray: 3 - }, - - Versioning: { - None: 0, - NeedsUpdate: 1, - MatrixWorldNeedsUpdate: 2 - }, - - GetterByBindingType: [ - - function getValue_direct( buffer, offset ) { - - buffer[ offset ] = this.node[ this.propertyName ]; - - }, - - function getValue_array( buffer, offset ) { - - var source = this.resolvedProperty; - - for ( var i = 0, n = source.length; i !== n; ++ i ) { - - buffer[ offset ++ ] = source[ i ]; - - } - - }, - - function getValue_arrayElement( buffer, offset ) { - - buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ]; - - }, - - function getValue_toArray( buffer, offset ) { - - this.resolvedProperty.toArray( buffer, offset ); - - } - - ], - - SetterByBindingTypeAndVersioning: [ - - [ - // Direct - - function setValue_direct( buffer, offset ) { - - this.targetObject[ this.propertyName ] = buffer[ offset ]; - - }, - - function setValue_direct_setNeedsUpdate( buffer, offset ) { - - this.targetObject[ this.propertyName ] = buffer[ offset ]; - this.targetObject.needsUpdate = true; - - }, - - function setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) { - - this.targetObject[ this.propertyName ] = buffer[ offset ]; - this.targetObject.matrixWorldNeedsUpdate = true; - - } - - ], [ - - // EntireArray - - function setValue_array( buffer, offset ) { - - var dest = this.resolvedProperty; - - for ( var i = 0, n = dest.length; i !== n; ++ i ) { - - dest[ i ] = buffer[ offset ++ ]; - - } - - }, - - function setValue_array_setNeedsUpdate( buffer, offset ) { - - var dest = this.resolvedProperty; - - for ( var i = 0, n = dest.length; i !== n; ++ i ) { - - dest[ i ] = buffer[ offset ++ ]; - - } - - this.targetObject.needsUpdate = true; - - }, - - function setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) { - - var dest = this.resolvedProperty; - - for ( var i = 0, n = dest.length; i !== n; ++ i ) { - - dest[ i ] = buffer[ offset ++ ]; - - } - - this.targetObject.matrixWorldNeedsUpdate = true; - - } - - ], [ - - // ArrayElement - - function setValue_arrayElement( buffer, offset ) { - - this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; - - }, - - function setValue_arrayElement_setNeedsUpdate( buffer, offset ) { - - this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; - this.targetObject.needsUpdate = true; - - }, - - function setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) { - - this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; - this.targetObject.matrixWorldNeedsUpdate = true; - - } - - ], [ - - // HasToFromArray - - function setValue_fromArray( buffer, offset ) { - - this.resolvedProperty.fromArray( buffer, offset ); - - }, - - function setValue_fromArray_setNeedsUpdate( buffer, offset ) { - - this.resolvedProperty.fromArray( buffer, offset ); - this.targetObject.needsUpdate = true; - - }, - - function setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) { - - this.resolvedProperty.fromArray( buffer, offset ); - this.targetObject.matrixWorldNeedsUpdate = true; - - } - - ] - - ], - - getValue: function getValue_unbound( targetArray, offset ) { - - this.bind(); - this.getValue( targetArray, offset ); - - // Note: This class uses a State pattern on a per-method basis: - // 'bind' sets 'this.getValue' / 'setValue' and shadows the - // prototype version of these methods with one that represents - // the bound state. When the property is not found, the methods - // become no-ops. - - }, - - setValue: function getValue_unbound( sourceArray, offset ) { - - this.bind(); - this.setValue( sourceArray, offset ); - - }, - - // create getter / setter pair for a property in the scene graph - bind: function () { - - var targetObject = this.node, - parsedPath = this.parsedPath, - - objectName = parsedPath.objectName, - propertyName = parsedPath.propertyName, - propertyIndex = parsedPath.propertyIndex; - - if ( ! targetObject ) { - - targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ) || this.rootNode; - - this.node = targetObject; - - } - - // set fail state so we can just 'return' on error - this.getValue = this._getValue_unavailable; - this.setValue = this._setValue_unavailable; - - // ensure there is a value node - if ( ! targetObject ) { - - console.error( 'THREE.PropertyBinding: Trying to update node for track: ' + this.path + ' but it wasn\'t found.' ); - return; - - } - - if ( objectName ) { - - var objectIndex = parsedPath.objectIndex; - - // special cases were we need to reach deeper into the hierarchy to get the face materials.... - switch ( objectName ) { - - case 'materials': - - if ( ! targetObject.material ) { - - console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this ); - return; - - } - - if ( ! targetObject.material.materials ) { - - console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this ); - return; - - } - - targetObject = targetObject.material.materials; - - break; - - case 'bones': - - if ( ! targetObject.skeleton ) { - - console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this ); - return; - - } - - // potential future optimization: skip this if propertyIndex is already an integer - // and convert the integer string to a true integer. - - targetObject = targetObject.skeleton.bones; - - // support resolving morphTarget names into indices. - for ( var i = 0; i < targetObject.length; i ++ ) { - - if ( targetObject[ i ].name === objectIndex ) { - - objectIndex = i; - break; - - } - - } - - break; - - default: - - if ( targetObject[ objectName ] === undefined ) { - - console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this ); - return; - - } - - targetObject = targetObject[ objectName ]; - - } - - - if ( objectIndex !== undefined ) { - - if ( targetObject[ objectIndex ] === undefined ) { - - console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject ); - return; - - } - - targetObject = targetObject[ objectIndex ]; - - } - - } - - // resolve property - var nodeProperty = targetObject[ propertyName ]; - - if ( nodeProperty === undefined ) { - - var nodeName = parsedPath.nodeName; - - console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName + - '.' + propertyName + ' but it wasn\'t found.', targetObject ); - return; - - } - - // determine versioning scheme - var versioning = this.Versioning.None; - - if ( targetObject.needsUpdate !== undefined ) { // material - - versioning = this.Versioning.NeedsUpdate; - this.targetObject = targetObject; - - } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform - - versioning = this.Versioning.MatrixWorldNeedsUpdate; - this.targetObject = targetObject; - - } - - // determine how the property gets bound - var bindingType = this.BindingType.Direct; - - if ( propertyIndex !== undefined ) { - - // access a sub element of the property array (only primitives are supported right now) - - if ( propertyName === "morphTargetInfluences" ) { - - // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer. - - // support resolving morphTarget names into indices. - if ( ! targetObject.geometry ) { - - console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this ); - return; - - } - - if ( targetObject.geometry.isBufferGeometry ) { - - if ( ! targetObject.geometry.morphAttributes ) { - - console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this ); - return; - - } - - for ( var i = 0; i < this.node.geometry.morphAttributes.position.length; i ++ ) { - - if ( targetObject.geometry.morphAttributes.position[ i ].name === propertyIndex ) { - - propertyIndex = i; - break; - - } - - } - - - } else { - - if ( ! targetObject.geometry.morphTargets ) { - - console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphTargets.', this ); - return; - - } - - for ( var i = 0; i < this.node.geometry.morphTargets.length; i ++ ) { - - if ( targetObject.geometry.morphTargets[ i ].name === propertyIndex ) { - - propertyIndex = i; - break; - - } - - } - - } - - } - - bindingType = this.BindingType.ArrayElement; - - this.resolvedProperty = nodeProperty; - this.propertyIndex = propertyIndex; - - } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) { - - // must use copy for Object3D.Euler/Quaternion - - bindingType = this.BindingType.HasFromToArray; - - this.resolvedProperty = nodeProperty; - - } else if ( Array.isArray( nodeProperty ) ) { - - bindingType = this.BindingType.EntireArray; - - this.resolvedProperty = nodeProperty; - - } else { - - this.propertyName = propertyName; - - } - - // select getter / setter - this.getValue = this.GetterByBindingType[ bindingType ]; - this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ]; - - }, - - unbind: function () { - - this.node = null; - - // back to the prototype version of getValue / setValue - // note: avoiding to mutate the shape of 'this' via 'delete' - this.getValue = this._getValue_unbound; - this.setValue = this._setValue_unbound; - - } - - } ); - - //!\ DECLARE ALIAS AFTER assign prototype ! - Object.assign( PropertyBinding.prototype, { - - // initial state of these methods that calls 'bind' - _getValue_unbound: PropertyBinding.prototype.getValue, - _setValue_unbound: PropertyBinding.prototype.setValue, - - } ); - - function PropertyMixer( binding, typeName, valueSize ) { - - this.binding = binding; - this.valueSize = valueSize; - - var bufferType = Float64Array, - mixFunction; - - switch ( typeName ) { - - case 'quaternion': - mixFunction = this._slerp; - break; - - case 'string': - case 'bool': - bufferType = Array; - mixFunction = this._select; - break; - - default: - mixFunction = this._lerp; - - } - - this.buffer = new bufferType( valueSize * 4 ); - // layout: [ incoming | accu0 | accu1 | orig ] - // - // interpolators can use .buffer as their .result - // the data then goes to 'incoming' - // - // 'accu0' and 'accu1' are used frame-interleaved for - // the cumulative result and are compared to detect - // changes - // - // 'orig' stores the original state of the property - - this._mixBufferRegion = mixFunction; - - this.cumulativeWeight = 0; - - this.useCount = 0; - this.referenceCount = 0; - - } - - Object.assign( PropertyMixer.prototype, { - - // accumulate data in the 'incoming' region into 'accu' - accumulate: function ( accuIndex, weight ) { - - // note: happily accumulating nothing when weight = 0, the caller knows - // the weight and shouldn't have made the call in the first place - - var buffer = this.buffer, - stride = this.valueSize, - offset = accuIndex * stride + stride, - - currentWeight = this.cumulativeWeight; - - if ( currentWeight === 0 ) { - - // accuN := incoming * weight - - for ( var i = 0; i !== stride; ++ i ) { - - buffer[ offset + i ] = buffer[ i ]; - - } - - currentWeight = weight; - - } else { - - // accuN := accuN + incoming * weight - - currentWeight += weight; - var mix = weight / currentWeight; - this._mixBufferRegion( buffer, offset, 0, mix, stride ); - - } - - this.cumulativeWeight = currentWeight; - - }, - - // apply the state of 'accu' to the binding when accus differ - apply: function ( accuIndex ) { - - var stride = this.valueSize, - buffer = this.buffer, - offset = accuIndex * stride + stride, - - weight = this.cumulativeWeight, - - binding = this.binding; - - this.cumulativeWeight = 0; - - if ( weight < 1 ) { - - // accuN := accuN + original * ( 1 - cumulativeWeight ) - - var originalValueOffset = stride * 3; - - this._mixBufferRegion( - buffer, offset, originalValueOffset, 1 - weight, stride ); - - } - - for ( var i = stride, e = stride + stride; i !== e; ++ i ) { - - if ( buffer[ i ] !== buffer[ i + stride ] ) { - - // value has changed -> update scene graph - - binding.setValue( buffer, offset ); - break; - - } - - } - - }, - - // remember the state of the bound property and copy it to both accus - saveOriginalState: function () { - - var binding = this.binding; - - var buffer = this.buffer, - stride = this.valueSize, - - originalValueOffset = stride * 3; - - binding.getValue( buffer, originalValueOffset ); - - // accu[0..1] := orig -- initially detect changes against the original - for ( var i = stride, e = originalValueOffset; i !== e; ++ i ) { - - buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ]; - - } - - this.cumulativeWeight = 0; - - }, - - // apply the state previously taken via 'saveOriginalState' to the binding - restoreOriginalState: function () { - - var originalValueOffset = this.valueSize * 3; - this.binding.setValue( this.buffer, originalValueOffset ); - - }, - - - // mix functions - - _select: function ( buffer, dstOffset, srcOffset, t, stride ) { - - if ( t >= 0.5 ) { - - for ( var i = 0; i !== stride; ++ i ) { - - buffer[ dstOffset + i ] = buffer[ srcOffset + i ]; - - } - - } - - }, - - _slerp: function ( buffer, dstOffset, srcOffset, t ) { - - Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t ); - - }, - - _lerp: function ( buffer, dstOffset, srcOffset, t, stride ) { - - var s = 1 - t; - - for ( var i = 0; i !== stride; ++ i ) { - - var j = dstOffset + i; - - buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t; - - } - - } - - } ); - - /** - * @author tschw - * @author Ben Houston / http://clara.io/ - * @author David Sarno / http://lighthaus.us/ - */ - - var AnimationUtils = { - - // same as Array.prototype.slice, but also works on typed arrays - arraySlice: function ( array, from, to ) { - - if ( AnimationUtils.isTypedArray( array ) ) { - - // in ios9 array.subarray(from, undefined) will return empty array - // but array.subarray(from) or array.subarray(from, len) is correct - return new array.constructor( array.subarray( from, to !== undefined ? to : array.length ) ); - - } - - return array.slice( from, to ); - - }, - - // converts an array to a specific type - convertArray: function ( array, type, forceClone ) { - - if ( ! array || // let 'undefined' and 'null' pass - ! forceClone && array.constructor === type ) return array; - - if ( typeof type.BYTES_PER_ELEMENT === 'number' ) { - - return new type( array ); // create typed array - - } - - return Array.prototype.slice.call( array ); // create Array - - }, - - isTypedArray: function ( object ) { - - return ArrayBuffer.isView( object ) && - ! ( object instanceof DataView ); - - }, - - // returns an array by which times and values can be sorted - getKeyframeOrder: function ( times ) { - - function compareTime( i, j ) { - - return times[ i ] - times[ j ]; - - } - - var n = times.length; - var result = new Array( n ); - for ( var i = 0; i !== n; ++ i ) result[ i ] = i; - - result.sort( compareTime ); - - return result; - - }, - - // uses the array previously returned by 'getKeyframeOrder' to sort data - sortedArray: function ( values, stride, order ) { - - var nValues = values.length; - var result = new values.constructor( nValues ); - - for ( var i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) { - - var srcOffset = order[ i ] * stride; - - for ( var j = 0; j !== stride; ++ j ) { - - result[ dstOffset ++ ] = values[ srcOffset + j ]; - - } - - } - - return result; - - }, - - // function for parsing AOS keyframe formats - flattenJSON: function ( jsonKeys, times, values, valuePropertyName ) { - - var i = 1, key = jsonKeys[ 0 ]; - - while ( key !== undefined && key[ valuePropertyName ] === undefined ) { - - key = jsonKeys[ i ++ ]; - - } - - if ( key === undefined ) return; // no data - - var value = key[ valuePropertyName ]; - if ( value === undefined ) return; // no data - - if ( Array.isArray( value ) ) { - - do { - - value = key[ valuePropertyName ]; - - if ( value !== undefined ) { - - times.push( key.time ); - values.push.apply( values, value ); // push all elements - - } - - key = jsonKeys[ i ++ ]; - - } while ( key !== undefined ); - - } else if ( value.toArray !== undefined ) { - - // ...assume THREE.Math-ish - - do { - - value = key[ valuePropertyName ]; - - if ( value !== undefined ) { - - times.push( key.time ); - value.toArray( values, values.length ); - - } - - key = jsonKeys[ i ++ ]; - - } while ( key !== undefined ); - - } else { - - // otherwise push as-is - - do { - - value = key[ valuePropertyName ]; - - if ( value !== undefined ) { - - times.push( key.time ); - values.push( value ); - - } - - key = jsonKeys[ i ++ ]; - - } while ( key !== undefined ); - - } - - } - - }; - - function CubicInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - - Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); - - this._weightPrev = - 0; - this._offsetPrev = - 0; - this._weightNext = - 0; - this._offsetNext = - 0; - - } - - CubicInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { - - constructor: CubicInterpolant, - - DefaultSettings_: { - - endingStart: ZeroCurvatureEnding, - endingEnd: ZeroCurvatureEnding - - }, - - intervalChanged_: function ( i1, t0, t1 ) { - - var pp = this.parameterPositions, - iPrev = i1 - 2, - iNext = i1 + 1, - - tPrev = pp[ iPrev ], - tNext = pp[ iNext ]; - - if ( tPrev === undefined ) { - - switch ( this.getSettings_().endingStart ) { - - case ZeroSlopeEnding: - - // f'(t0) = 0 - iPrev = i1; - tPrev = 2 * t0 - t1; - - break; - - case WrapAroundEnding: - - // use the other end of the curve - iPrev = pp.length - 2; - tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ]; - - break; - - default: // ZeroCurvatureEnding - - // f''(t0) = 0 a.k.a. Natural Spline - iPrev = i1; - tPrev = t1; - - } - - } - - if ( tNext === undefined ) { - - switch ( this.getSettings_().endingEnd ) { - - case ZeroSlopeEnding: - - // f'(tN) = 0 - iNext = i1; - tNext = 2 * t1 - t0; - - break; - - case WrapAroundEnding: - - // use the other end of the curve - iNext = 1; - tNext = t1 + pp[ 1 ] - pp[ 0 ]; - - break; - - default: // ZeroCurvatureEnding - - // f''(tN) = 0, a.k.a. Natural Spline - iNext = i1 - 1; - tNext = t0; - - } - - } - - var halfDt = ( t1 - t0 ) * 0.5, - stride = this.valueSize; - - this._weightPrev = halfDt / ( t0 - tPrev ); - this._weightNext = halfDt / ( tNext - t1 ); - this._offsetPrev = iPrev * stride; - this._offsetNext = iNext * stride; - - }, - - interpolate_: function ( i1, t0, t, t1 ) { - - var result = this.resultBuffer, - values = this.sampleValues, - stride = this.valueSize, - - o1 = i1 * stride, o0 = o1 - stride, - oP = this._offsetPrev, oN = this._offsetNext, - wP = this._weightPrev, wN = this._weightNext, - - p = ( t - t0 ) / ( t1 - t0 ), - pp = p * p, - ppp = pp * p; - - // evaluate polynomials - - var sP = - wP * ppp + 2 * wP * pp - wP * p; - var s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1; - var s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p; - var sN = wN * ppp - wN * pp; - - // combine data linearly - - for ( var i = 0; i !== stride; ++ i ) { - - result[ i ] = - sP * values[ oP + i ] + - s0 * values[ o0 + i ] + - s1 * values[ o1 + i ] + - sN * values[ oN + i ]; - - } - - return result; - - } - - } ); - - function DiscreteInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - - Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); - - } - - DiscreteInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { - - constructor: DiscreteInterpolant, - - interpolate_: function ( i1 /*, t0, t, t1 */ ) { - - return this.copySampleValue_( i1 - 1 ); - - } - - } ); - - var KeyframeTrackPrototype; - - KeyframeTrackPrototype = { - - TimeBufferType: Float32Array, - ValueBufferType: Float32Array, - - DefaultInterpolation: InterpolateLinear, - - InterpolantFactoryMethodDiscrete: function ( result ) { - - return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result ); - - }, - - InterpolantFactoryMethodLinear: function ( result ) { - - return new LinearInterpolant( this.times, this.values, this.getValueSize(), result ); - - }, - - InterpolantFactoryMethodSmooth: function ( result ) { - - return new CubicInterpolant( this.times, this.values, this.getValueSize(), result ); - - }, - - setInterpolation: function ( interpolation ) { - - var factoryMethod; - - switch ( interpolation ) { - - case InterpolateDiscrete: - - factoryMethod = this.InterpolantFactoryMethodDiscrete; - - break; - - case InterpolateLinear: - - factoryMethod = this.InterpolantFactoryMethodLinear; - - break; - - case InterpolateSmooth: - - factoryMethod = this.InterpolantFactoryMethodSmooth; - - break; - - } - - if ( factoryMethod === undefined ) { - - var message = "unsupported interpolation for " + - this.ValueTypeName + " keyframe track named " + this.name; - - if ( this.createInterpolant === undefined ) { - - // fall back to default, unless the default itself is messed up - if ( interpolation !== this.DefaultInterpolation ) { - - this.setInterpolation( this.DefaultInterpolation ); - - } else { - - throw new Error( message ); // fatal, in this case - - } - - } - - console.warn( 'THREE.KeyframeTrackPrototype:', message ); - return; - - } - - this.createInterpolant = factoryMethod; - - }, - - getInterpolation: function () { - - switch ( this.createInterpolant ) { - - case this.InterpolantFactoryMethodDiscrete: - - return InterpolateDiscrete; - - case this.InterpolantFactoryMethodLinear: - - return InterpolateLinear; - - case this.InterpolantFactoryMethodSmooth: - - return InterpolateSmooth; - - } - - }, - - getValueSize: function () { - - return this.values.length / this.times.length; - - }, - - // move all keyframes either forwards or backwards in time - shift: function ( timeOffset ) { - - if ( timeOffset !== 0.0 ) { - - var times = this.times; - - for ( var i = 0, n = times.length; i !== n; ++ i ) { - - times[ i ] += timeOffset; - - } - - } - - return this; - - }, - - // scale all keyframe times by a factor (useful for frame <-> seconds conversions) - scale: function ( timeScale ) { - - if ( timeScale !== 1.0 ) { - - var times = this.times; - - for ( var i = 0, n = times.length; i !== n; ++ i ) { - - times[ i ] *= timeScale; - - } - - } - - return this; - - }, - - // removes keyframes before and after animation without changing any values within the range [startTime, endTime]. - // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values - trim: function ( startTime, endTime ) { - - var times = this.times, - nKeys = times.length, - from = 0, - to = nKeys - 1; - - while ( from !== nKeys && times[ from ] < startTime ) ++ from; - while ( to !== - 1 && times[ to ] > endTime ) -- to; - - ++ to; // inclusive -> exclusive bound - - if ( from !== 0 || to !== nKeys ) { - - // empty tracks are forbidden, so keep at least one keyframe - if ( from >= to ) to = Math.max( to, 1 ), from = to - 1; - - var stride = this.getValueSize(); - this.times = AnimationUtils.arraySlice( times, from, to ); - this.values = AnimationUtils.arraySlice( this.values, from * stride, to * stride ); - - } - - return this; - - }, - - // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable - validate: function () { - - var valid = true; - - var valueSize = this.getValueSize(); - if ( valueSize - Math.floor( valueSize ) !== 0 ) { - - console.error( 'THREE.KeyframeTrackPrototype: Invalid value size in track.', this ); - valid = false; - - } - - var times = this.times, - values = this.values, - - nKeys = times.length; - - if ( nKeys === 0 ) { - - console.error( 'THREE.KeyframeTrackPrototype: Track is empty.', this ); - valid = false; - - } - - var prevTime = null; - - for ( var i = 0; i !== nKeys; i ++ ) { - - var currTime = times[ i ]; - - if ( typeof currTime === 'number' && isNaN( currTime ) ) { - - console.error( 'THREE.KeyframeTrackPrototype: Time is not a valid number.', this, i, currTime ); - valid = false; - break; - - } - - if ( prevTime !== null && prevTime > currTime ) { - - console.error( 'THREE.KeyframeTrackPrototype: Out of order keys.', this, i, currTime, prevTime ); - valid = false; - break; - - } - - prevTime = currTime; - - } - - if ( values !== undefined ) { - - if ( AnimationUtils.isTypedArray( values ) ) { - - for ( var i = 0, n = values.length; i !== n; ++ i ) { - - var value = values[ i ]; - - if ( isNaN( value ) ) { - - console.error( 'THREE.KeyframeTrackPrototype: Value is not a valid number.', this, i, value ); - valid = false; - break; - - } - - } - - } - - } - - return valid; - - }, - - // removes equivalent sequential keys as common in morph target sequences - // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0) - optimize: function () { - - var times = this.times, - values = this.values, - stride = this.getValueSize(), - - smoothInterpolation = this.getInterpolation() === InterpolateSmooth, - - writeIndex = 1, - lastIndex = times.length - 1; - - for ( var i = 1; i < lastIndex; ++ i ) { - - var keep = false; - - var time = times[ i ]; - var timeNext = times[ i + 1 ]; - - // remove adjacent keyframes scheduled at the same time - - if ( time !== timeNext && ( i !== 1 || time !== time[ 0 ] ) ) { - - if ( ! smoothInterpolation ) { - - // remove unnecessary keyframes same as their neighbors - - var offset = i * stride, - offsetP = offset - stride, - offsetN = offset + stride; - - for ( var j = 0; j !== stride; ++ j ) { - - var value = values[ offset + j ]; - - if ( value !== values[ offsetP + j ] || - value !== values[ offsetN + j ] ) { - - keep = true; - break; - - } - - } - - } else keep = true; - - } - - // in-place compaction - - if ( keep ) { - - if ( i !== writeIndex ) { - - times[ writeIndex ] = times[ i ]; - - var readOffset = i * stride, - writeOffset = writeIndex * stride; - - for ( var j = 0; j !== stride; ++ j ) - - values[ writeOffset + j ] = values[ readOffset + j ]; - - } - - ++ writeIndex; - - } - - } - - // flush last keyframe (compaction looks ahead) - - if ( lastIndex > 0 ) { - - times[ writeIndex ] = times[ lastIndex ]; - - for ( var readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) - - values[ writeOffset + j ] = values[ readOffset + j ]; - - ++ writeIndex; - - } - - if ( writeIndex !== times.length ) { - - this.times = AnimationUtils.arraySlice( times, 0, writeIndex ); - this.values = AnimationUtils.arraySlice( values, 0, writeIndex * stride ); - - } - - return this; - - } - - }; - - function KeyframeTrackConstructor( name, times, values, interpolation ) { - - if ( name === undefined ) throw new Error( 'track name is undefined' ); - - if ( times === undefined || times.length === 0 ) { - - throw new Error( 'no keyframes in track named ' + name ); - - } - - this.name = name; - - this.times = AnimationUtils.convertArray( times, this.TimeBufferType ); - this.values = AnimationUtils.convertArray( values, this.ValueBufferType ); - - this.setInterpolation( interpolation || this.DefaultInterpolation ); - - this.validate(); - this.optimize(); - - } - - function VectorKeyframeTrack( name, times, values, interpolation ) { - - KeyframeTrackConstructor.call( this, name, times, values, interpolation ); - - } - - VectorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrackPrototype ), { - - constructor: VectorKeyframeTrack, - - ValueTypeName: 'vector' - - // ValueBufferType is inherited - - // DefaultInterpolation is inherited - - } ); - - function QuaternionLinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - - Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); - - } - - QuaternionLinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { - - constructor: QuaternionLinearInterpolant, - - interpolate_: function ( i1, t0, t, t1 ) { - - var result = this.resultBuffer, - values = this.sampleValues, - stride = this.valueSize, - - offset = i1 * stride, - - alpha = ( t - t0 ) / ( t1 - t0 ); - - for ( var end = offset + stride; offset !== end; offset += 4 ) { - - Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha ); - - } - - return result; - - } - - } ); - - function QuaternionKeyframeTrack( name, times, values, interpolation ) { - - KeyframeTrackConstructor.call( this, name, times, values, interpolation ); - - } - - QuaternionKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrackPrototype ), { - - constructor: QuaternionKeyframeTrack, - - ValueTypeName: 'quaternion', - - // ValueBufferType is inherited - - DefaultInterpolation: InterpolateLinear, - - InterpolantFactoryMethodLinear: function ( result ) { - - return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result ); - - }, - - InterpolantFactoryMethodSmooth: undefined // not yet implemented - - } ); - - function NumberKeyframeTrack( name, times, values, interpolation ) { - - KeyframeTrackConstructor.call( this, name, times, values, interpolation ); - - } - - NumberKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrackPrototype ), { - - constructor: NumberKeyframeTrack, - - ValueTypeName: 'number' - - // ValueBufferType is inherited - - // DefaultInterpolation is inherited - - } ); - - function StringKeyframeTrack( name, times, values, interpolation ) { - - KeyframeTrackConstructor.call( this, name, times, values, interpolation ); - - } - - StringKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrackPrototype ), { - - constructor: StringKeyframeTrack, - - ValueTypeName: 'string', - ValueBufferType: Array, - - DefaultInterpolation: InterpolateDiscrete, - - InterpolantFactoryMethodLinear: undefined, - - InterpolantFactoryMethodSmooth: undefined - - } ); - - function BooleanKeyframeTrack( name, times, values ) { - - KeyframeTrackConstructor.call( this, name, times, values ); - - } - - BooleanKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrackPrototype ), { - - constructor: BooleanKeyframeTrack, - - ValueTypeName: 'bool', - ValueBufferType: Array, - - DefaultInterpolation: InterpolateDiscrete, - - InterpolantFactoryMethodLinear: undefined, - InterpolantFactoryMethodSmooth: undefined - - // Note: Actually this track could have a optimized / compressed - // representation of a single value and a custom interpolant that - // computes "firstValue ^ isOdd( index )". - - } ); - - function ColorKeyframeTrack( name, times, values, interpolation ) { - - KeyframeTrackConstructor.call( this, name, times, values, interpolation ); - - } - - ColorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrackPrototype ), { - - constructor: ColorKeyframeTrack, - - ValueTypeName: 'color' - - // ValueBufferType is inherited - - // DefaultInterpolation is inherited - - - // Note: Very basic implementation and nothing special yet. - // However, this is the place for color space parameterization. - - } ); - - function KeyframeTrack( name, times, values, interpolation ) { - - KeyframeTrackConstructor.apply( this, name, times, values, interpolation ); - - } - - KeyframeTrack.prototype = KeyframeTrackPrototype; - KeyframeTrackPrototype.constructor = KeyframeTrack; - - // Static methods: - - Object.assign( KeyframeTrack, { - - // Serialization (in static context, because of constructor invocation - // and automatic invocation of .toJSON): - - parse: function ( json ) { - - if ( json.type === undefined ) { - - throw new Error( 'track type undefined, can not parse' ); - - } - - var trackType = KeyframeTrack._getTrackTypeForValueTypeName( json.type ); - - if ( json.times === undefined ) { - - var times = [], values = []; - - AnimationUtils.flattenJSON( json.keys, times, values, 'value' ); - - json.times = times; - json.values = values; - - } - - // derived classes can define a static parse method - if ( trackType.parse !== undefined ) { - - return trackType.parse( json ); - - } else { - - // by default, we assume a constructor compatible with the base - return new trackType( json.name, json.times, json.values, json.interpolation ); - - } - - }, - - toJSON: function ( track ) { - - var trackType = track.constructor; - - var json; - - // derived classes can define a static toJSON method - if ( trackType.toJSON !== undefined ) { - - json = trackType.toJSON( track ); - - } else { - - // by default, we assume the data can be serialized as-is - json = { - - 'name': track.name, - 'times': AnimationUtils.convertArray( track.times, Array ), - 'values': AnimationUtils.convertArray( track.values, Array ) - - }; - - var interpolation = track.getInterpolation(); - - if ( interpolation !== track.DefaultInterpolation ) { - - json.interpolation = interpolation; - - } - - } - - json.type = track.ValueTypeName; // mandatory - - return json; - - }, - - _getTrackTypeForValueTypeName: function ( typeName ) { - - switch ( typeName.toLowerCase() ) { - - case 'scalar': - case 'double': - case 'float': - case 'number': - case 'integer': - - return NumberKeyframeTrack; - - case 'vector': - case 'vector2': - case 'vector3': - case 'vector4': - - return VectorKeyframeTrack; - - case 'color': - - return ColorKeyframeTrack; - - case 'quaternion': - - return QuaternionKeyframeTrack; - - case 'bool': - case 'boolean': - - return BooleanKeyframeTrack; - - case 'string': - - return StringKeyframeTrack; - - } - - throw new Error( 'Unsupported typeName: ' + typeName ); - - } - - } ); - - function AnimationClip( name, duration, tracks ) { - - this.name = name; - this.tracks = tracks; - this.duration = ( duration !== undefined ) ? duration : - 1; - - this.uuid = _Math.generateUUID(); - - // this means it should figure out its duration by scanning the tracks - if ( this.duration < 0 ) { - - this.resetDuration(); - - } - - this.optimize(); - - } - - Object.assign( AnimationClip, { - - parse: function ( json ) { - - var tracks = [], - jsonTracks = json.tracks, - frameTime = 1.0 / ( json.fps || 1.0 ); - - for ( var i = 0, n = jsonTracks.length; i !== n; ++ i ) { - - tracks.push( KeyframeTrack.parse( jsonTracks[ i ] ).scale( frameTime ) ); - - } - - return new AnimationClip( json.name, json.duration, tracks ); - - }, - - toJSON: function ( clip ) { - - var tracks = [], - clipTracks = clip.tracks; - - var json = { - - 'name': clip.name, - 'duration': clip.duration, - 'tracks': tracks - - }; - - for ( var i = 0, n = clipTracks.length; i !== n; ++ i ) { - - tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) ); - - } - - return json; - - }, - - CreateFromMorphTargetSequence: function ( name, morphTargetSequence, fps, noLoop ) { - - var numMorphTargets = morphTargetSequence.length; - var tracks = []; - - for ( var i = 0; i < numMorphTargets; i ++ ) { - - var times = []; - var values = []; - - times.push( - ( i + numMorphTargets - 1 ) % numMorphTargets, - i, - ( i + 1 ) % numMorphTargets ); - - values.push( 0, 1, 0 ); - - var order = AnimationUtils.getKeyframeOrder( times ); - times = AnimationUtils.sortedArray( times, 1, order ); - values = AnimationUtils.sortedArray( values, 1, order ); - - // if there is a key at the first frame, duplicate it as the - // last frame as well for perfect loop. - if ( ! noLoop && times[ 0 ] === 0 ) { - - times.push( numMorphTargets ); - values.push( values[ 0 ] ); - - } - - tracks.push( - new NumberKeyframeTrack( - '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']', - times, values - ).scale( 1.0 / fps ) ); - - } - - return new AnimationClip( name, - 1, tracks ); - - }, - - findByName: function ( objectOrClipArray, name ) { - - var clipArray = objectOrClipArray; - - if ( ! Array.isArray( objectOrClipArray ) ) { - - var o = objectOrClipArray; - clipArray = o.geometry && o.geometry.animations || o.animations; - - } - - for ( var i = 0; i < clipArray.length; i ++ ) { - - if ( clipArray[ i ].name === name ) { - - return clipArray[ i ]; - - } - - } - - return null; - - }, - - CreateClipsFromMorphTargetSequences: function ( morphTargets, fps, noLoop ) { - - var animationToMorphTargets = {}; - - // tested with https://regex101.com/ on trick sequences - // such flamingo_flyA_003, flamingo_run1_003, crdeath0059 - var pattern = /^([\w-]*?)([\d]+)$/; - - // sort morph target names into animation groups based - // patterns like Walk_001, Walk_002, Run_001, Run_002 - for ( var i = 0, il = morphTargets.length; i < il; i ++ ) { - - var morphTarget = morphTargets[ i ]; - var parts = morphTarget.name.match( pattern ); - - if ( parts && parts.length > 1 ) { - - var name = parts[ 1 ]; - - var animationMorphTargets = animationToMorphTargets[ name ]; - if ( ! animationMorphTargets ) { - - animationToMorphTargets[ name ] = animationMorphTargets = []; - - } - - animationMorphTargets.push( morphTarget ); - - } - - } - - var clips = []; - - for ( var name in animationToMorphTargets ) { - - clips.push( AnimationClip.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) ); - - } - - return clips; - - }, - - // parse the animation.hierarchy format - parseAnimation: function ( animation, bones ) { - - if ( ! animation ) { - - console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' ); - return null; - - } - - var addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) { - - // only return track if there are actually keys. - if ( animationKeys.length !== 0 ) { - - var times = []; - var values = []; - - AnimationUtils.flattenJSON( animationKeys, times, values, propertyName ); - - // empty keys are filtered out, so check again - if ( times.length !== 0 ) { - - destTracks.push( new trackType( trackName, times, values ) ); - - } - - } - - }; - - var tracks = []; - - var clipName = animation.name || 'default'; - // automatic length determination in AnimationClip. - var duration = animation.length || - 1; - var fps = animation.fps || 30; - - var hierarchyTracks = animation.hierarchy || []; - - for ( var h = 0; h < hierarchyTracks.length; h ++ ) { - - var animationKeys = hierarchyTracks[ h ].keys; - - // skip empty tracks - if ( ! animationKeys || animationKeys.length === 0 ) continue; - - // process morph targets - if ( animationKeys[ 0 ].morphTargets ) { - - // figure out all morph targets used in this track - var morphTargetNames = {}; - - for ( var k = 0; k < animationKeys.length; k ++ ) { - - if ( animationKeys[ k ].morphTargets ) { - - for ( var m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) { - - morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1; - - } - - } - - } - - // create a track for each morph target with all zero - // morphTargetInfluences except for the keys in which - // the morphTarget is named. - for ( var morphTargetName in morphTargetNames ) { - - var times = []; - var values = []; - - for ( var m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) { - - var animationKey = animationKeys[ k ]; - - times.push( animationKey.time ); - values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 ); - - } - - tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) ); - - } - - duration = morphTargetNames.length * ( fps || 1.0 ); - - } else { - - // ...assume skeletal animation - - var boneName = '.bones[' + bones[ h ].name + ']'; - - addNonemptyTrack( - VectorKeyframeTrack, boneName + '.position', - animationKeys, 'pos', tracks ); - - addNonemptyTrack( - QuaternionKeyframeTrack, boneName + '.quaternion', - animationKeys, 'rot', tracks ); - - addNonemptyTrack( - VectorKeyframeTrack, boneName + '.scale', - animationKeys, 'scl', tracks ); - - } - - } - - if ( tracks.length === 0 ) { - - return null; - - } - - var clip = new AnimationClip( clipName, duration, tracks ); - - return clip; - - } - - } ); - - Object.assign( AnimationClip.prototype, { - - resetDuration: function () { - - var tracks = this.tracks, duration = 0; - - for ( var i = 0, n = tracks.length; i !== n; ++ i ) { - - var track = this.tracks[ i ]; - - duration = Math.max( duration, track.times[ track.times.length - 1 ] ); - - } - - this.duration = duration; - - }, - - trim: function () { - - for ( var i = 0; i < this.tracks.length; i ++ ) { - - this.tracks[ i ].trim( 0, this.duration ); - - } - - return this; - - }, - - optimize: function () { - - for ( var i = 0; i < this.tracks.length; i ++ ) { - - this.tracks[ i ].optimize(); - - } - - return this; - - } - - } ); - - function AnimationMixer( root ) { - - this._root = root; - this._initMemoryManager(); - this._accuIndex = 0; - - this.time = 0; - - this.timeScale = 1.0; - - } - - Object.assign( AnimationMixer.prototype, EventDispatcher.prototype, { - - _bindAction: function ( action, prototypeAction ) { - - var root = action._localRoot || this._root, - tracks = action._clip.tracks, - nTracks = tracks.length, - bindings = action._propertyBindings, - interpolants = action._interpolants, - rootUuid = root.uuid, - bindingsByRoot = this._bindingsByRootAndName, - bindingsByName = bindingsByRoot[ rootUuid ]; - - if ( bindingsByName === undefined ) { - - bindingsByName = {}; - bindingsByRoot[ rootUuid ] = bindingsByName; - - } - - for ( var i = 0; i !== nTracks; ++ i ) { - - var track = tracks[ i ], - trackName = track.name, - binding = bindingsByName[ trackName ]; - - if ( binding !== undefined ) { - - bindings[ i ] = binding; - - } else { - - binding = bindings[ i ]; - - if ( binding !== undefined ) { - - // existing binding, make sure the cache knows - - if ( binding._cacheIndex === null ) { - - ++ binding.referenceCount; - this._addInactiveBinding( binding, rootUuid, trackName ); - - } - - continue; - - } - - var path = prototypeAction && prototypeAction. - _propertyBindings[ i ].binding.parsedPath; - - binding = new PropertyMixer( - PropertyBinding.create( root, trackName, path ), - track.ValueTypeName, track.getValueSize() ); - - ++ binding.referenceCount; - this._addInactiveBinding( binding, rootUuid, trackName ); - - bindings[ i ] = binding; - - } - - interpolants[ i ].resultBuffer = binding.buffer; - - } - - }, - - _activateAction: function ( action ) { - - if ( ! this._isActiveAction( action ) ) { - - if ( action._cacheIndex === null ) { - - // this action has been forgotten by the cache, but the user - // appears to be still using it -> rebind - - var rootUuid = ( action._localRoot || this._root ).uuid, - clipUuid = action._clip.uuid, - actionsForClip = this._actionsByClip[ clipUuid ]; - - this._bindAction( action, - actionsForClip && actionsForClip.knownActions[ 0 ] ); - - this._addInactiveAction( action, clipUuid, rootUuid ); - - } - - var bindings = action._propertyBindings; - - // increment reference counts / sort out state - for ( var i = 0, n = bindings.length; i !== n; ++ i ) { - - var binding = bindings[ i ]; - - if ( binding.useCount ++ === 0 ) { - - this._lendBinding( binding ); - binding.saveOriginalState(); - - } - - } - - this._lendAction( action ); - - } - - }, - - _deactivateAction: function ( action ) { - - if ( this._isActiveAction( action ) ) { - - var bindings = action._propertyBindings; - - // decrement reference counts / sort out state - for ( var i = 0, n = bindings.length; i !== n; ++ i ) { - - var binding = bindings[ i ]; - - if ( -- binding.useCount === 0 ) { - - binding.restoreOriginalState(); - this._takeBackBinding( binding ); - - } - - } - - this._takeBackAction( action ); - - } - - }, - - // Memory manager - - _initMemoryManager: function () { - - this._actions = []; // 'nActiveActions' followed by inactive ones - this._nActiveActions = 0; - - this._actionsByClip = {}; - // inside: - // { - // knownActions: Array< AnimationAction > - used as prototypes - // actionByRoot: AnimationAction - lookup - // } - - - this._bindings = []; // 'nActiveBindings' followed by inactive ones - this._nActiveBindings = 0; - - this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer > - - - this._controlInterpolants = []; // same game as above - this._nActiveControlInterpolants = 0; - - var scope = this; - - this.stats = { - - actions: { - get total() { - - return scope._actions.length; - - }, - get inUse() { - - return scope._nActiveActions; - - } - }, - bindings: { - get total() { - - return scope._bindings.length; - - }, - get inUse() { - - return scope._nActiveBindings; - - } - }, - controlInterpolants: { - get total() { - - return scope._controlInterpolants.length; - - }, - get inUse() { - - return scope._nActiveControlInterpolants; - - } - } - - }; - - }, - - // Memory management for AnimationAction objects - - _isActiveAction: function ( action ) { - - var index = action._cacheIndex; - return index !== null && index < this._nActiveActions; - - }, - - _addInactiveAction: function ( action, clipUuid, rootUuid ) { - - var actions = this._actions, - actionsByClip = this._actionsByClip, - actionsForClip = actionsByClip[ clipUuid ]; - - if ( actionsForClip === undefined ) { - - actionsForClip = { - - knownActions: [ action ], - actionByRoot: {} - - }; - - action._byClipCacheIndex = 0; - - actionsByClip[ clipUuid ] = actionsForClip; - - } else { - - var knownActions = actionsForClip.knownActions; - - action._byClipCacheIndex = knownActions.length; - knownActions.push( action ); - - } - - action._cacheIndex = actions.length; - actions.push( action ); - - actionsForClip.actionByRoot[ rootUuid ] = action; - - }, - - _removeInactiveAction: function ( action ) { - - var actions = this._actions, - lastInactiveAction = actions[ actions.length - 1 ], - cacheIndex = action._cacheIndex; - - lastInactiveAction._cacheIndex = cacheIndex; - actions[ cacheIndex ] = lastInactiveAction; - actions.pop(); - - action._cacheIndex = null; - - - var clipUuid = action._clip.uuid, - actionsByClip = this._actionsByClip, - actionsForClip = actionsByClip[ clipUuid ], - knownActionsForClip = actionsForClip.knownActions, - - lastKnownAction = - knownActionsForClip[ knownActionsForClip.length - 1 ], - - byClipCacheIndex = action._byClipCacheIndex; - - lastKnownAction._byClipCacheIndex = byClipCacheIndex; - knownActionsForClip[ byClipCacheIndex ] = lastKnownAction; - knownActionsForClip.pop(); - - action._byClipCacheIndex = null; - - - var actionByRoot = actionsForClip.actionByRoot, - rootUuid = ( action._localRoot || this._root ).uuid; - - delete actionByRoot[ rootUuid ]; - - if ( knownActionsForClip.length === 0 ) { - - delete actionsByClip[ clipUuid ]; - - } - - this._removeInactiveBindingsForAction( action ); - - }, - - _removeInactiveBindingsForAction: function ( action ) { - - var bindings = action._propertyBindings; - for ( var i = 0, n = bindings.length; i !== n; ++ i ) { - - var binding = bindings[ i ]; - - if ( -- binding.referenceCount === 0 ) { - - this._removeInactiveBinding( binding ); - - } - - } - - }, - - _lendAction: function ( action ) { - - // [ active actions | inactive actions ] - // [ active actions >| inactive actions ] - // s a - // <-swap-> - // a s - - var actions = this._actions, - prevIndex = action._cacheIndex, - - lastActiveIndex = this._nActiveActions ++, - - firstInactiveAction = actions[ lastActiveIndex ]; - - action._cacheIndex = lastActiveIndex; - actions[ lastActiveIndex ] = action; - - firstInactiveAction._cacheIndex = prevIndex; - actions[ prevIndex ] = firstInactiveAction; - - }, - - _takeBackAction: function ( action ) { - - // [ active actions | inactive actions ] - // [ active actions |< inactive actions ] - // a s - // <-swap-> - // s a - - var actions = this._actions, - prevIndex = action._cacheIndex, - - firstInactiveIndex = -- this._nActiveActions, - - lastActiveAction = actions[ firstInactiveIndex ]; - - action._cacheIndex = firstInactiveIndex; - actions[ firstInactiveIndex ] = action; - - lastActiveAction._cacheIndex = prevIndex; - actions[ prevIndex ] = lastActiveAction; - - }, - - // Memory management for PropertyMixer objects - - _addInactiveBinding: function ( binding, rootUuid, trackName ) { - - var bindingsByRoot = this._bindingsByRootAndName, - bindingByName = bindingsByRoot[ rootUuid ], - - bindings = this._bindings; - - if ( bindingByName === undefined ) { - - bindingByName = {}; - bindingsByRoot[ rootUuid ] = bindingByName; - - } - - bindingByName[ trackName ] = binding; - - binding._cacheIndex = bindings.length; - bindings.push( binding ); - - }, - - _removeInactiveBinding: function ( binding ) { - - var bindings = this._bindings, - propBinding = binding.binding, - rootUuid = propBinding.rootNode.uuid, - trackName = propBinding.path, - bindingsByRoot = this._bindingsByRootAndName, - bindingByName = bindingsByRoot[ rootUuid ], - - lastInactiveBinding = bindings[ bindings.length - 1 ], - cacheIndex = binding._cacheIndex; - - lastInactiveBinding._cacheIndex = cacheIndex; - bindings[ cacheIndex ] = lastInactiveBinding; - bindings.pop(); - - delete bindingByName[ trackName ]; - - remove_empty_map: { - - for ( var _ in bindingByName ) break remove_empty_map; // eslint-disable-line no-unused-vars - - delete bindingsByRoot[ rootUuid ]; - - } - - }, - - _lendBinding: function ( binding ) { - - var bindings = this._bindings, - prevIndex = binding._cacheIndex, - - lastActiveIndex = this._nActiveBindings ++, - - firstInactiveBinding = bindings[ lastActiveIndex ]; - - binding._cacheIndex = lastActiveIndex; - bindings[ lastActiveIndex ] = binding; - - firstInactiveBinding._cacheIndex = prevIndex; - bindings[ prevIndex ] = firstInactiveBinding; - - }, - - _takeBackBinding: function ( binding ) { - - var bindings = this._bindings, - prevIndex = binding._cacheIndex, - - firstInactiveIndex = -- this._nActiveBindings, - - lastActiveBinding = bindings[ firstInactiveIndex ]; - - binding._cacheIndex = firstInactiveIndex; - bindings[ firstInactiveIndex ] = binding; - - lastActiveBinding._cacheIndex = prevIndex; - bindings[ prevIndex ] = lastActiveBinding; - - }, - - - // Memory management of Interpolants for weight and time scale - - _lendControlInterpolant: function () { - - var interpolants = this._controlInterpolants, - lastActiveIndex = this._nActiveControlInterpolants ++, - interpolant = interpolants[ lastActiveIndex ]; - - if ( interpolant === undefined ) { - - interpolant = new LinearInterpolant( - new Float32Array( 2 ), new Float32Array( 2 ), - 1, this._controlInterpolantsResultBuffer ); - - interpolant.__cacheIndex = lastActiveIndex; - interpolants[ lastActiveIndex ] = interpolant; - - } - - return interpolant; - - }, - - _takeBackControlInterpolant: function ( interpolant ) { - - var interpolants = this._controlInterpolants, - prevIndex = interpolant.__cacheIndex, - - firstInactiveIndex = -- this._nActiveControlInterpolants, - - lastActiveInterpolant = interpolants[ firstInactiveIndex ]; - - interpolant.__cacheIndex = firstInactiveIndex; - interpolants[ firstInactiveIndex ] = interpolant; - - lastActiveInterpolant.__cacheIndex = prevIndex; - interpolants[ prevIndex ] = lastActiveInterpolant; - - }, - - _controlInterpolantsResultBuffer: new Float32Array( 1 ), - - // return an action for a clip optionally using a custom root target - // object (this method allocates a lot of dynamic memory in case a - // previously unknown clip/root combination is specified) - clipAction: function ( clip, optionalRoot ) { - - var root = optionalRoot || this._root, - rootUuid = root.uuid, - - clipObject = typeof clip === 'string' ? - AnimationClip.findByName( root, clip ) : clip, - - clipUuid = clipObject !== null ? clipObject.uuid : clip, - - actionsForClip = this._actionsByClip[ clipUuid ], - prototypeAction = null; - - if ( actionsForClip !== undefined ) { - - var existingAction = - actionsForClip.actionByRoot[ rootUuid ]; - - if ( existingAction !== undefined ) { - - return existingAction; - - } - - // we know the clip, so we don't have to parse all - // the bindings again but can just copy - prototypeAction = actionsForClip.knownActions[ 0 ]; - - // also, take the clip from the prototype action - if ( clipObject === null ) - clipObject = prototypeAction._clip; - - } - - // clip must be known when specified via string - if ( clipObject === null ) return null; - - // allocate all resources required to run it - var newAction = new AnimationAction( this, clipObject, optionalRoot ); - - this._bindAction( newAction, prototypeAction ); - - // and make the action known to the memory manager - this._addInactiveAction( newAction, clipUuid, rootUuid ); - - return newAction; - - }, - - // get an existing action - existingAction: function ( clip, optionalRoot ) { - - var root = optionalRoot || this._root, - rootUuid = root.uuid, - - clipObject = typeof clip === 'string' ? - AnimationClip.findByName( root, clip ) : clip, - - clipUuid = clipObject ? clipObject.uuid : clip, - - actionsForClip = this._actionsByClip[ clipUuid ]; - - if ( actionsForClip !== undefined ) { - - return actionsForClip.actionByRoot[ rootUuid ] || null; - - } - - return null; - - }, - - // deactivates all previously scheduled actions - stopAllAction: function () { - - var actions = this._actions, - nActions = this._nActiveActions, - bindings = this._bindings, - nBindings = this._nActiveBindings; - - this._nActiveActions = 0; - this._nActiveBindings = 0; - - for ( var i = 0; i !== nActions; ++ i ) { - - actions[ i ].reset(); - - } - - for ( var i = 0; i !== nBindings; ++ i ) { - - bindings[ i ].useCount = 0; - - } - - return this; - - }, - - // advance the time and update apply the animation - update: function ( deltaTime ) { - - deltaTime *= this.timeScale; - - var actions = this._actions, - nActions = this._nActiveActions, - - time = this.time += deltaTime, - timeDirection = Math.sign( deltaTime ), - - accuIndex = this._accuIndex ^= 1; - - // run active actions - - for ( var i = 0; i !== nActions; ++ i ) { - - var action = actions[ i ]; - - action._update( time, deltaTime, timeDirection, accuIndex ); - - } - - // update scene graph - - var bindings = this._bindings, - nBindings = this._nActiveBindings; - - for ( var i = 0; i !== nBindings; ++ i ) { - - bindings[ i ].apply( accuIndex ); - - } - - return this; - - }, - - // return this mixer's root target object - getRoot: function () { - - return this._root; - - }, - - // free all resources specific to a particular clip - uncacheClip: function ( clip ) { - - var actions = this._actions, - clipUuid = clip.uuid, - actionsByClip = this._actionsByClip, - actionsForClip = actionsByClip[ clipUuid ]; - - if ( actionsForClip !== undefined ) { - - // note: just calling _removeInactiveAction would mess up the - // iteration state and also require updating the state we can - // just throw away - - var actionsToRemove = actionsForClip.knownActions; - - for ( var i = 0, n = actionsToRemove.length; i !== n; ++ i ) { - - var action = actionsToRemove[ i ]; - - this._deactivateAction( action ); - - var cacheIndex = action._cacheIndex, - lastInactiveAction = actions[ actions.length - 1 ]; - - action._cacheIndex = null; - action._byClipCacheIndex = null; - - lastInactiveAction._cacheIndex = cacheIndex; - actions[ cacheIndex ] = lastInactiveAction; - actions.pop(); - - this._removeInactiveBindingsForAction( action ); - - } - - delete actionsByClip[ clipUuid ]; - - } - - }, - - // free all resources specific to a particular root target object - uncacheRoot: function ( root ) { - - var rootUuid = root.uuid, - actionsByClip = this._actionsByClip; - - for ( var clipUuid in actionsByClip ) { - - var actionByRoot = actionsByClip[ clipUuid ].actionByRoot, - action = actionByRoot[ rootUuid ]; - - if ( action !== undefined ) { - - this._deactivateAction( action ); - this._removeInactiveAction( action ); - - } - - } - - var bindingsByRoot = this._bindingsByRootAndName, - bindingByName = bindingsByRoot[ rootUuid ]; - - if ( bindingByName !== undefined ) { - - for ( var trackName in bindingByName ) { - - var binding = bindingByName[ trackName ]; - binding.restoreOriginalState(); - this._removeInactiveBinding( binding ); - - } - - } - - }, - - // remove a targeted clip from the cache - uncacheAction: function ( clip, optionalRoot ) { - - var action = this.existingAction( clip, optionalRoot ); - - if ( action !== null ) { - - this._deactivateAction( action ); - this._removeInactiveAction( action ); - - } - - } - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Animation', () => { - - QUnit.module.todo( 'AnimationAction', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - var mixer = new AnimationMixer(); - var clip = new AnimationClip(); - - assert.throws( - function () { - - new AnimationAction(); - - }, - new Error( "Mixer can't be null or undefined !" ), - "raised error instance about undefined or null mixer" - ); - - assert.throws( - function () { - - new AnimationAction( mixer ); - - }, - new Error( "Clip can't be null or undefined !" ), - "raised error instance about undefined or null clip" - ); - - var animationAction = new AnimationAction( mixer, clip ); - assert.ok( animationAction, "animationAction instanciated" ); - - } ); - - // PRIVATE STUFF - QUnit.test( "_update", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_updateWeight", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_updateTimeScale", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_updateTime", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_setEndings", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_scheduleFading", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "play", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "stop", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "reset", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "isRunning", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "isScheduled", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "startAt", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setLoop", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setEffectiveWeight", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getEffectiveWeight", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "fadeIn", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "fadeOut", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "crossFadeFrom", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "crossFadeTo", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "stopFading", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setEffectiveTimeScale", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getEffectiveTimeScale", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setDuration", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "syncWith", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "halt", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "warp", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "stopWarping", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getMixer", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getClip", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getRoot", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Animation', () => { - - QUnit.module.todo( 'AnimationClip', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // STATIC STUFF - QUnit.test( "parse", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "toJSON", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "CreateFromMorphTargetSequence", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "findByName", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "CreateClipsFromMorphTargetSequences", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "parseAnimation", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "resetDuration", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "trim", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "optimize", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Animation', () => { - - QUnit.module.todo( 'AnimationMixer', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PRIVATE STUFF - QUnit.test( "_bindAction", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_activateAction", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_deactivateAction", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_initMemoryManager", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_isActiveAction", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_addInactiveAction", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_removeInactiveAction", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_removeInactiveBindingsForAction", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_lendAction", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_takeBackAction", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_addInactiveBinding", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_removeInactiveBinding", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_lendBinding", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_takeBackBinding", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_lendControlInterpolant", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_takeBackControlInterpolant", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_controlInterpolantsResultBuffer", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "clipAction", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "existingAction", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "stopAllAction", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "update", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getRoot", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "uncacheClip", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "uncacheRoot", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "uncacheAction", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - function AnimationObjectGroup() { - - this.uuid = _Math.generateUUID(); - - // cached objects followed by the active ones - this._objects = Array.prototype.slice.call( arguments ); - - this.nCachedObjects_ = 0; // threshold - // note: read by PropertyBinding.Composite - - var indices = {}; - this._indicesByUUID = indices; // for bookkeeping - - for ( var i = 0, n = arguments.length; i !== n; ++ i ) { - - indices[ arguments[ i ].uuid ] = i; - - } - - this._paths = []; // inside: string - this._parsedPaths = []; // inside: { we don't care, here } - this._bindings = []; // inside: Array< PropertyBinding > - this._bindingsIndicesByPath = {}; // inside: indices in these arrays - - var scope = this; - - this.stats = { - - objects: { - get total() { - - return scope._objects.length; - - }, - get inUse() { - - return this.total - scope.nCachedObjects_; - - } - }, - get bindingsPerObject() { - - return scope._bindings.length; - - } - - }; - - } - - Object.assign( AnimationObjectGroup.prototype, { - - isAnimationObjectGroup: true, - - add: function () { - - var objects = this._objects, - nObjects = objects.length, - nCachedObjects = this.nCachedObjects_, - indicesByUUID = this._indicesByUUID, - paths = this._paths, - parsedPaths = this._parsedPaths, - bindings = this._bindings, - nBindings = bindings.length; - - for ( var i = 0, n = arguments.length; i !== n; ++ i ) { - - var object = arguments[ i ], - uuid = object.uuid, - index = indicesByUUID[ uuid ], - knownObject = undefined; - - if ( index === undefined ) { - - // unknown object -> add it to the ACTIVE region - - index = nObjects ++; - indicesByUUID[ uuid ] = index; - objects.push( object ); - - // accounting is done, now do the same for all bindings - - for ( var j = 0, m = nBindings; j !== m; ++ j ) { - - bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) ); - - } - - } else if ( index < nCachedObjects ) { - - knownObject = objects[ index ]; - - // move existing object to the ACTIVE region - - var firstActiveIndex = -- nCachedObjects, - lastCachedObject = objects[ firstActiveIndex ]; - - indicesByUUID[ lastCachedObject.uuid ] = index; - objects[ index ] = lastCachedObject; - - indicesByUUID[ uuid ] = firstActiveIndex; - objects[ firstActiveIndex ] = object; - - // accounting is done, now do the same for all bindings - - for ( var j = 0, m = nBindings; j !== m; ++ j ) { - - var bindingsForPath = bindings[ j ], - lastCached = bindingsForPath[ firstActiveIndex ], - binding = bindingsForPath[ index ]; - - bindingsForPath[ index ] = lastCached; - - if ( binding === undefined ) { - - // since we do not bother to create new bindings - // for objects that are cached, the binding may - // or may not exist - - binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ); - - } - - bindingsForPath[ firstActiveIndex ] = binding; - - } - - } else if ( objects[ index ] !== knownObject ) { - - console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' + - 'detected. Clean the caches or recreate your infrastructure when reloading scenes.' ); - - } // else the object is already where we want it to be - - } // for arguments - - this.nCachedObjects_ = nCachedObjects; - - }, - - remove: function () { - - var objects = this._objects, - nCachedObjects = this.nCachedObjects_, - indicesByUUID = this._indicesByUUID, - bindings = this._bindings, - nBindings = bindings.length; - - for ( var i = 0, n = arguments.length; i !== n; ++ i ) { - - var object = arguments[ i ], - uuid = object.uuid, - index = indicesByUUID[ uuid ]; - - if ( index !== undefined && index >= nCachedObjects ) { - - // move existing object into the CACHED region - - var lastCachedIndex = nCachedObjects ++, - firstActiveObject = objects[ lastCachedIndex ]; - - indicesByUUID[ firstActiveObject.uuid ] = index; - objects[ index ] = firstActiveObject; - - indicesByUUID[ uuid ] = lastCachedIndex; - objects[ lastCachedIndex ] = object; - - // accounting is done, now do the same for all bindings - - for ( var j = 0, m = nBindings; j !== m; ++ j ) { - - var bindingsForPath = bindings[ j ], - firstActive = bindingsForPath[ lastCachedIndex ], - binding = bindingsForPath[ index ]; - - bindingsForPath[ index ] = firstActive; - bindingsForPath[ lastCachedIndex ] = binding; - - } - - } - - } // for arguments - - this.nCachedObjects_ = nCachedObjects; - - }, - - // remove & forget - uncache: function () { - - var objects = this._objects, - nObjects = objects.length, - nCachedObjects = this.nCachedObjects_, - indicesByUUID = this._indicesByUUID, - bindings = this._bindings, - nBindings = bindings.length; - - for ( var i = 0, n = arguments.length; i !== n; ++ i ) { - - var object = arguments[ i ], - uuid = object.uuid, - index = indicesByUUID[ uuid ]; - - if ( index !== undefined ) { - - delete indicesByUUID[ uuid ]; - - if ( index < nCachedObjects ) { - - // object is cached, shrink the CACHED region - - var firstActiveIndex = -- nCachedObjects, - lastCachedObject = objects[ firstActiveIndex ], - lastIndex = -- nObjects, - lastObject = objects[ lastIndex ]; - - // last cached object takes this object's place - indicesByUUID[ lastCachedObject.uuid ] = index; - objects[ index ] = lastCachedObject; - - // last object goes to the activated slot and pop - indicesByUUID[ lastObject.uuid ] = firstActiveIndex; - objects[ firstActiveIndex ] = lastObject; - objects.pop(); - - // accounting is done, now do the same for all bindings - - for ( var j = 0, m = nBindings; j !== m; ++ j ) { - - var bindingsForPath = bindings[ j ], - lastCached = bindingsForPath[ firstActiveIndex ], - last = bindingsForPath[ lastIndex ]; - - bindingsForPath[ index ] = lastCached; - bindingsForPath[ firstActiveIndex ] = last; - bindingsForPath.pop(); - - } - - } else { - - // object is active, just swap with the last and pop - - var lastIndex = -- nObjects, - lastObject = objects[ lastIndex ]; - - indicesByUUID[ lastObject.uuid ] = index; - objects[ index ] = lastObject; - objects.pop(); - - // accounting is done, now do the same for all bindings - - for ( var j = 0, m = nBindings; j !== m; ++ j ) { - - var bindingsForPath = bindings[ j ]; - - bindingsForPath[ index ] = bindingsForPath[ lastIndex ]; - bindingsForPath.pop(); - - } - - } // cached or active - - } // if object is known - - } // for arguments - - this.nCachedObjects_ = nCachedObjects; - - }, - - // Internal interface used by befriended PropertyBinding.Composite: - - subscribe_: function ( path, parsedPath ) { - - // returns an array of bindings for the given path that is changed - // according to the contained objects in the group - - var indicesByPath = this._bindingsIndicesByPath, - index = indicesByPath[ path ], - bindings = this._bindings; - - if ( index !== undefined ) return bindings[ index ]; - - var paths = this._paths, - parsedPaths = this._parsedPaths, - objects = this._objects, - nObjects = objects.length, - nCachedObjects = this.nCachedObjects_, - bindingsForPath = new Array( nObjects ); - - index = bindings.length; - - indicesByPath[ path ] = index; - - paths.push( path ); - parsedPaths.push( parsedPath ); - bindings.push( bindingsForPath ); - - for ( var i = nCachedObjects, n = objects.length; i !== n; ++ i ) { - - var object = objects[ i ]; - bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath ); - - } - - return bindingsForPath; - - }, - - unsubscribe_: function ( path ) { - - // tells the group to forget about a property path and no longer - // update the array previously obtained with 'subscribe_' - - var indicesByPath = this._bindingsIndicesByPath, - index = indicesByPath[ path ]; - - if ( index !== undefined ) { - - var paths = this._paths, - parsedPaths = this._parsedPaths, - bindings = this._bindings, - lastBindingsIndex = bindings.length - 1, - lastBindings = bindings[ lastBindingsIndex ], - lastBindingsPath = path[ lastBindingsIndex ]; - - indicesByPath[ lastBindingsPath ] = index; - - bindings[ index ] = lastBindings; - bindings.pop(); - - parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ]; - parsedPaths.pop(); - - paths[ index ] = paths[ lastBindingsIndex ]; - paths.pop(); - - } - - } - - } ); - - function Euler( x, y, z, order ) { - - this._x = x || 0; - this._y = y || 0; - this._z = z || 0; - this._order = order || Euler.DefaultOrder; - - } - - Euler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ]; - - Euler.DefaultOrder = 'XYZ'; - - Object.defineProperties( Euler.prototype, { - - x: { - - get: function () { - - return this._x; - - }, - - set: function ( value ) { - - this._x = value; - this.onChangeCallback(); - - } - - }, - - y: { - - get: function () { - - return this._y; - - }, - - set: function ( value ) { - - this._y = value; - this.onChangeCallback(); - - } - - }, - - z: { - - get: function () { - - return this._z; - - }, - - set: function ( value ) { - - this._z = value; - this.onChangeCallback(); - - } - - }, - - order: { - - get: function () { - - return this._order; - - }, - - set: function ( value ) { - - this._order = value; - this.onChangeCallback(); - - } - - } - - } ); - - Object.assign( Euler.prototype, { - - isEuler: true, - - set: function ( x, y, z, order ) { - - this._x = x; - this._y = y; - this._z = z; - this._order = order || this._order; - - this.onChangeCallback(); - - return this; - - }, - - clone: function () { - - return new this.constructor( this._x, this._y, this._z, this._order ); - - }, - - copy: function ( euler ) { - - this._x = euler._x; - this._y = euler._y; - this._z = euler._z; - this._order = euler._order; - - this.onChangeCallback(); - - return this; - - }, - - setFromRotationMatrix: function ( m, order, update ) { - - var clamp = _Math.clamp; - - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - - var te = m.elements; - var m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ]; - var m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ]; - var m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ]; - - order = order || this._order; - - if ( order === 'XYZ' ) { - - this._y = Math.asin( clamp( m13, - 1, 1 ) ); - - if ( Math.abs( m13 ) < 0.99999 ) { - - this._x = Math.atan2( - m23, m33 ); - this._z = Math.atan2( - m12, m11 ); - - } else { - - this._x = Math.atan2( m32, m22 ); - this._z = 0; - - } - - } else if ( order === 'YXZ' ) { - - this._x = Math.asin( - clamp( m23, - 1, 1 ) ); - - if ( Math.abs( m23 ) < 0.99999 ) { - - this._y = Math.atan2( m13, m33 ); - this._z = Math.atan2( m21, m22 ); - - } else { - - this._y = Math.atan2( - m31, m11 ); - this._z = 0; - - } - - } else if ( order === 'ZXY' ) { - - this._x = Math.asin( clamp( m32, - 1, 1 ) ); - - if ( Math.abs( m32 ) < 0.99999 ) { - - this._y = Math.atan2( - m31, m33 ); - this._z = Math.atan2( - m12, m22 ); - - } else { - - this._y = 0; - this._z = Math.atan2( m21, m11 ); - - } - - } else if ( order === 'ZYX' ) { - - this._y = Math.asin( - clamp( m31, - 1, 1 ) ); - - if ( Math.abs( m31 ) < 0.99999 ) { - - this._x = Math.atan2( m32, m33 ); - this._z = Math.atan2( m21, m11 ); - - } else { - - this._x = 0; - this._z = Math.atan2( - m12, m22 ); - - } - - } else if ( order === 'YZX' ) { - - this._z = Math.asin( clamp( m21, - 1, 1 ) ); - - if ( Math.abs( m21 ) < 0.99999 ) { - - this._x = Math.atan2( - m23, m22 ); - this._y = Math.atan2( - m31, m11 ); - - } else { - - this._x = 0; - this._y = Math.atan2( m13, m33 ); - - } - - } else if ( order === 'XZY' ) { - - this._z = Math.asin( - clamp( m12, - 1, 1 ) ); - - if ( Math.abs( m12 ) < 0.99999 ) { - - this._x = Math.atan2( m32, m22 ); - this._y = Math.atan2( m13, m11 ); - - } else { - - this._x = Math.atan2( - m23, m33 ); - this._y = 0; - - } - - } else { - - console.warn( 'THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order ); - - } - - this._order = order; - - if ( update !== false ) this.onChangeCallback(); - - return this; - - }, - - setFromQuaternion: function () { - - var matrix = new Matrix4(); - - return function setFromQuaternion( q, order, update ) { - - matrix.makeRotationFromQuaternion( q ); - - return this.setFromRotationMatrix( matrix, order, update ); - - }; - - }(), - - setFromVector3: function ( v, order ) { - - return this.set( v.x, v.y, v.z, order || this._order ); - - }, - - reorder: function () { - - // WARNING: this discards revolution information -bhouston - - var q = new Quaternion(); - - return function reorder( newOrder ) { - - q.setFromEuler( this ); - - return this.setFromQuaternion( q, newOrder ); - - }; - - }(), - - equals: function ( euler ) { - - return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order ); - - }, - - fromArray: function ( array ) { - - this._x = array[ 0 ]; - this._y = array[ 1 ]; - this._z = array[ 2 ]; - if ( array[ 3 ] !== undefined ) this._order = array[ 3 ]; - - this.onChangeCallback(); - - return this; - - }, - - toArray: function ( array, offset ) { - - if ( array === undefined ) array = []; - if ( offset === undefined ) offset = 0; - - array[ offset ] = this._x; - array[ offset + 1 ] = this._y; - array[ offset + 2 ] = this._z; - array[ offset + 3 ] = this._order; - - return array; - - }, - - toVector3: function ( optionalResult ) { - - if ( optionalResult ) { - - return optionalResult.set( this._x, this._y, this._z ); - - } else { - - return new Vector3( this._x, this._y, this._z ); - - } - - }, - - onChange: function ( callback ) { - - this.onChangeCallback = callback; - - return this; - - }, - - onChangeCallback: function () {} - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function Layers() { - - this.mask = 1 | 0; - - } - - Object.assign( Layers.prototype, { - - set: function ( channel ) { - - this.mask = 1 << channel | 0; - - }, - - enable: function ( channel ) { - - this.mask |= 1 << channel | 0; - - }, - - toggle: function ( channel ) { - - this.mask ^= 1 << channel | 0; - - }, - - disable: function ( channel ) { - - this.mask &= ~ ( 1 << channel | 0 ); - - }, - - test: function ( layers ) { - - return ( this.mask & layers.mask ) !== 0; - - } - - } ); - - function Matrix3() { - - this.elements = [ - - 1, 0, 0, - 0, 1, 0, - 0, 0, 1 - - ]; - - if ( arguments.length > 0 ) { - - console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' ); - - } - - } - - Object.assign( Matrix3.prototype, { - - isMatrix3: true, - - set: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { - - var te = this.elements; - - te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31; - te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32; - te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33; - - return this; - - }, - - identity: function () { - - this.set( - - 1, 0, 0, - 0, 1, 0, - 0, 0, 1 - - ); - - return this; - - }, - - clone: function () { - - return new this.constructor().fromArray( this.elements ); - - }, - - copy: function ( m ) { - - var te = this.elements; - var me = m.elements; - - te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; - te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; - te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ]; - - return this; - - }, - - setFromMatrix4: function ( m ) { - - var me = m.elements; - - this.set( - - me[ 0 ], me[ 4 ], me[ 8 ], - me[ 1 ], me[ 5 ], me[ 9 ], - me[ 2 ], me[ 6 ], me[ 10 ] - - ); - - return this; - - }, - - applyToBufferAttribute: function () { - - var v1 = new Vector3(); - - return function applyToBufferAttribute( attribute ) { - - for ( var i = 0, l = attribute.count; i < l; i ++ ) { - - v1.x = attribute.getX( i ); - v1.y = attribute.getY( i ); - v1.z = attribute.getZ( i ); - - v1.applyMatrix3( this ); - - attribute.setXYZ( i, v1.x, v1.y, v1.z ); - - } - - return attribute; - - }; - - }(), - - multiply: function ( m ) { - - return this.multiplyMatrices( this, m ); - - }, - - premultiply: function ( m ) { - - return this.multiplyMatrices( m, this ); - - }, - - multiplyMatrices: function ( a, b ) { - - var ae = a.elements; - var be = b.elements; - var te = this.elements; - - var a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ]; - var a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ]; - var a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ]; - - var b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ]; - var b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ]; - var b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ]; - - te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31; - te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32; - te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33; - - te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31; - te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32; - te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33; - - te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31; - te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32; - te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33; - - return this; - - }, - - multiplyScalar: function ( s ) { - - var te = this.elements; - - te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s; - te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s; - te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s; - - return this; - - }, - - determinant: function () { - - var te = this.elements; - - var a = te[ 0 ], b = te[ 1 ], c = te[ 2 ], - d = te[ 3 ], e = te[ 4 ], f = te[ 5 ], - g = te[ 6 ], h = te[ 7 ], i = te[ 8 ]; - - return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g; - - }, - - getInverse: function ( matrix, throwOnDegenerate ) { - - if ( matrix && matrix.isMatrix4 ) { - - console.error( "THREE.Matrix3: .getInverse() no longer takes a Matrix4 argument." ); - - } - - var me = matrix.elements, - te = this.elements, - - n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], - n12 = me[ 3 ], n22 = me[ 4 ], n32 = me[ 5 ], - n13 = me[ 6 ], n23 = me[ 7 ], n33 = me[ 8 ], - - t11 = n33 * n22 - n32 * n23, - t12 = n32 * n13 - n33 * n12, - t13 = n23 * n12 - n22 * n13, - - det = n11 * t11 + n21 * t12 + n31 * t13; - - if ( det === 0 ) { - - var msg = "THREE.Matrix3: .getInverse() can't invert matrix, determinant is 0"; - - if ( throwOnDegenerate === true ) { - - throw new Error( msg ); - - } else { - - console.warn( msg ); - - } - - return this.identity(); - - } - - var detInv = 1 / det; - - te[ 0 ] = t11 * detInv; - te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv; - te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv; - - te[ 3 ] = t12 * detInv; - te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv; - te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv; - - te[ 6 ] = t13 * detInv; - te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv; - te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv; - - return this; - - }, - - transpose: function () { - - var tmp, m = this.elements; - - tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp; - tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp; - tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp; - - return this; - - }, - - getNormalMatrix: function ( matrix4 ) { - - return this.setFromMatrix4( matrix4 ).getInverse( this ).transpose(); - - }, - - transposeIntoArray: function ( r ) { - - var m = this.elements; - - r[ 0 ] = m[ 0 ]; - r[ 1 ] = m[ 3 ]; - r[ 2 ] = m[ 6 ]; - r[ 3 ] = m[ 1 ]; - r[ 4 ] = m[ 4 ]; - r[ 5 ] = m[ 7 ]; - r[ 6 ] = m[ 2 ]; - r[ 7 ] = m[ 5 ]; - r[ 8 ] = m[ 8 ]; - - return this; - - }, - - setUvTransform: function ( tx, ty, sx, sy, rotation, cx, cy ) { - - var c = Math.cos( rotation ); - var s = Math.sin( rotation ); - - this.set( - sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx, - - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty, - 0, 0, 1 - ); - - }, - - scale: function ( sx, sy ) { - - var te = this.elements; - - te[ 0 ] *= sx; te[ 3 ] *= sx; te[ 6 ] *= sx; - te[ 1 ] *= sy; te[ 4 ] *= sy; te[ 7 ] *= sy; - - return this; - - }, - - rotate: function ( theta ) { - - var c = Math.cos( theta ); - var s = Math.sin( theta ); - - var te = this.elements; - - var a11 = te[ 0 ], a12 = te[ 3 ], a13 = te[ 6 ]; - var a21 = te[ 1 ], a22 = te[ 4 ], a23 = te[ 7 ]; - - te[ 0 ] = c * a11 + s * a21; - te[ 3 ] = c * a12 + s * a22; - te[ 6 ] = c * a13 + s * a23; - - te[ 1 ] = - s * a11 + c * a21; - te[ 4 ] = - s * a12 + c * a22; - te[ 7 ] = - s * a13 + c * a23; - - return this; - - }, - - translate: function ( tx, ty ) { - - var te = this.elements; - - te[ 0 ] += tx * te[ 2 ]; te[ 3 ] += tx * te[ 5 ]; te[ 6 ] += tx * te[ 8 ]; - te[ 1 ] += ty * te[ 2 ]; te[ 4 ] += ty * te[ 5 ]; te[ 7 ] += ty * te[ 8 ]; - - return this; - - }, - - equals: function ( matrix ) { - - var te = this.elements; - var me = matrix.elements; - - for ( var i = 0; i < 9; i ++ ) { - - if ( te[ i ] !== me[ i ] ) return false; - - } - - return true; - - }, - - fromArray: function ( array, offset ) { - - if ( offset === undefined ) offset = 0; - - for ( var i = 0; i < 9; i ++ ) { - - this.elements[ i ] = array[ i + offset ]; - - } - - return this; - - }, - - toArray: function ( array, offset ) { - - if ( array === undefined ) array = []; - if ( offset === undefined ) offset = 0; - - var te = this.elements; - - array[ offset ] = te[ 0 ]; - array[ offset + 1 ] = te[ 1 ]; - array[ offset + 2 ] = te[ 2 ]; - - array[ offset + 3 ] = te[ 3 ]; - array[ offset + 4 ] = te[ 4 ]; - array[ offset + 5 ] = te[ 5 ]; - - array[ offset + 6 ] = te[ 6 ]; - array[ offset + 7 ] = te[ 7 ]; - array[ offset + 8 ] = te[ 8 ]; - - return array; - - } - - } ); - - var object3DId = 0; - - function Object3D() { - - Object.defineProperty( this, 'id', { value: object3DId ++ } ); - - this.uuid = _Math.generateUUID(); - - this.name = ''; - this.type = 'Object3D'; - - this.parent = null; - this.children = []; - - this.up = Object3D.DefaultUp.clone(); - - var position = new Vector3(); - var rotation = new Euler(); - var quaternion = new Quaternion(); - var scale = new Vector3( 1, 1, 1 ); - - function onRotationChange() { - - quaternion.setFromEuler( rotation, false ); - - } - - function onQuaternionChange() { - - rotation.setFromQuaternion( quaternion, undefined, false ); - - } - - rotation.onChange( onRotationChange ); - quaternion.onChange( onQuaternionChange ); - - Object.defineProperties( this, { - position: { - enumerable: true, - value: position - }, - rotation: { - enumerable: true, - value: rotation - }, - quaternion: { - enumerable: true, - value: quaternion - }, - scale: { - enumerable: true, - value: scale - }, - modelViewMatrix: { - value: new Matrix4() - }, - normalMatrix: { - value: new Matrix3() - } - } ); - - this.matrix = new Matrix4(); - this.matrixWorld = new Matrix4(); - - this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate; - this.matrixWorldNeedsUpdate = false; - - this.layers = new Layers(); - this.visible = true; - - this.castShadow = false; - this.receiveShadow = false; - - this.frustumCulled = true; - this.renderOrder = 0; - - this.userData = {}; - - } - - Object3D.DefaultUp = new Vector3( 0, 1, 0 ); - Object3D.DefaultMatrixAutoUpdate = true; - - Object.assign( Object3D.prototype, EventDispatcher.prototype, { - - isObject3D: true, - - onBeforeRender: function () {}, - onAfterRender: function () {}, - - applyMatrix: function ( matrix ) { - - this.matrix.multiplyMatrices( matrix, this.matrix ); - - this.matrix.decompose( this.position, this.quaternion, this.scale ); - - }, - - applyQuaternion: function ( q ) { - - this.quaternion.premultiply( q ); - - return this; - - }, - - setRotationFromAxisAngle: function ( axis, angle ) { - - // assumes axis is normalized - - this.quaternion.setFromAxisAngle( axis, angle ); - - }, - - setRotationFromEuler: function ( euler ) { - - this.quaternion.setFromEuler( euler, true ); - - }, - - setRotationFromMatrix: function ( m ) { - - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - - this.quaternion.setFromRotationMatrix( m ); - - }, - - setRotationFromQuaternion: function ( q ) { - - // assumes q is normalized - - this.quaternion.copy( q ); - - }, - - rotateOnAxis: function () { - - // rotate object on axis in object space - // axis is assumed to be normalized - - var q1 = new Quaternion(); - - return function rotateOnAxis( axis, angle ) { - - q1.setFromAxisAngle( axis, angle ); - - this.quaternion.multiply( q1 ); - - return this; - - }; - - }(), - - rotateOnWorldAxis: function () { - - // rotate object on axis in world space - // axis is assumed to be normalized - // method assumes no rotated parent - - var q1 = new Quaternion(); - - return function rotateOnWorldAxis( axis, angle ) { - - q1.setFromAxisAngle( axis, angle ); - - this.quaternion.premultiply( q1 ); - - return this; - - }; - - }(), - - rotateX: function () { - - var v1 = new Vector3( 1, 0, 0 ); - - return function rotateX( angle ) { - - return this.rotateOnAxis( v1, angle ); - - }; - - }(), - - rotateY: function () { - - var v1 = new Vector3( 0, 1, 0 ); - - return function rotateY( angle ) { - - return this.rotateOnAxis( v1, angle ); - - }; - - }(), - - rotateZ: function () { - - var v1 = new Vector3( 0, 0, 1 ); - - return function rotateZ( angle ) { - - return this.rotateOnAxis( v1, angle ); - - }; - - }(), - - translateOnAxis: function () { - - // translate object by distance along axis in object space - // axis is assumed to be normalized - - var v1 = new Vector3(); - - return function translateOnAxis( axis, distance ) { - - v1.copy( axis ).applyQuaternion( this.quaternion ); - - this.position.add( v1.multiplyScalar( distance ) ); - - return this; - - }; - - }(), - - translateX: function () { - - var v1 = new Vector3( 1, 0, 0 ); - - return function translateX( distance ) { - - return this.translateOnAxis( v1, distance ); - - }; - - }(), - - translateY: function () { - - var v1 = new Vector3( 0, 1, 0 ); - - return function translateY( distance ) { - - return this.translateOnAxis( v1, distance ); - - }; - - }(), - - translateZ: function () { - - var v1 = new Vector3( 0, 0, 1 ); - - return function translateZ( distance ) { - - return this.translateOnAxis( v1, distance ); - - }; - - }(), - - localToWorld: function ( vector ) { - - return vector.applyMatrix4( this.matrixWorld ); - - }, - - worldToLocal: function () { - - var m1 = new Matrix4(); - - return function worldToLocal( vector ) { - - return vector.applyMatrix4( m1.getInverse( this.matrixWorld ) ); - - }; - - }(), - - lookAt: function () { - - // This method does not support objects with rotated and/or translated parent(s) - - var m1 = new Matrix4(); - var vector = new Vector3(); - - return function lookAt( x, y, z ) { - - if ( x.isVector3 ) { - - vector.copy( x ); - - } else { - - vector.set( x, y, z ); - - } - - if ( this.isCamera ) { - - m1.lookAt( this.position, vector, this.up ); - - } else { - - m1.lookAt( vector, this.position, this.up ); - - } - - this.quaternion.setFromRotationMatrix( m1 ); - - }; - - }(), - - add: function ( object ) { - - if ( arguments.length > 1 ) { - - for ( var i = 0; i < arguments.length; i ++ ) { - - this.add( arguments[ i ] ); - - } - - return this; - - } - - if ( object === this ) { - - console.error( "THREE.Object3D.add: object can't be added as a child of itself.", object ); - return this; - - } - - if ( ( object && object.isObject3D ) ) { - - if ( object.parent !== null ) { - - object.parent.remove( object ); - - } - - object.parent = this; - object.dispatchEvent( { type: 'added' } ); - - this.children.push( object ); - - } else { - - console.error( "THREE.Object3D.add: object not an instance of THREE.Object3D.", object ); - - } - - return this; - - }, - - remove: function ( object ) { - - if ( arguments.length > 1 ) { - - for ( var i = 0; i < arguments.length; i ++ ) { - - this.remove( arguments[ i ] ); - - } - - return this; - - } - - var index = this.children.indexOf( object ); - - if ( index !== - 1 ) { - - object.parent = null; - - object.dispatchEvent( { type: 'removed' } ); - - this.children.splice( index, 1 ); - - } - - return this; - - }, - - getObjectById: function ( id ) { - - return this.getObjectByProperty( 'id', id ); - - }, - - getObjectByName: function ( name ) { - - return this.getObjectByProperty( 'name', name ); - - }, - - getObjectByProperty: function ( name, value ) { - - if ( this[ name ] === value ) return this; - - for ( var i = 0, l = this.children.length; i < l; i ++ ) { - - var child = this.children[ i ]; - var object = child.getObjectByProperty( name, value ); - - if ( object !== undefined ) { - - return object; - - } - - } - - return undefined; - - }, - - getWorldPosition: function ( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - this.updateMatrixWorld( true ); - - return result.setFromMatrixPosition( this.matrixWorld ); - - }, - - getWorldQuaternion: function () { - - var position = new Vector3(); - var scale = new Vector3(); - - return function getWorldQuaternion( optionalTarget ) { - - var result = optionalTarget || new Quaternion(); - - this.updateMatrixWorld( true ); - - this.matrixWorld.decompose( position, result, scale ); - - return result; - - }; - - }(), - - getWorldRotation: function () { - - var quaternion = new Quaternion(); - - return function getWorldRotation( optionalTarget ) { - - var result = optionalTarget || new Euler(); - - this.getWorldQuaternion( quaternion ); - - return result.setFromQuaternion( quaternion, this.rotation.order, false ); - - }; - - }(), - - getWorldScale: function () { - - var position = new Vector3(); - var quaternion = new Quaternion(); - - return function getWorldScale( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - this.updateMatrixWorld( true ); - - this.matrixWorld.decompose( position, quaternion, result ); - - return result; - - }; - - }(), - - getWorldDirection: function () { - - var quaternion = new Quaternion(); - - return function getWorldDirection( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - this.getWorldQuaternion( quaternion ); - - return result.set( 0, 0, 1 ).applyQuaternion( quaternion ); - - }; - - }(), - - raycast: function () {}, - - traverse: function ( callback ) { - - callback( this ); - - var children = this.children; - - for ( var i = 0, l = children.length; i < l; i ++ ) { - - children[ i ].traverse( callback ); - - } - - }, - - traverseVisible: function ( callback ) { - - if ( this.visible === false ) return; - - callback( this ); - - var children = this.children; - - for ( var i = 0, l = children.length; i < l; i ++ ) { - - children[ i ].traverseVisible( callback ); - - } - - }, - - traverseAncestors: function ( callback ) { - - var parent = this.parent; - - if ( parent !== null ) { - - callback( parent ); - - parent.traverseAncestors( callback ); - - } - - }, - - updateMatrix: function () { - - this.matrix.compose( this.position, this.quaternion, this.scale ); - - this.matrixWorldNeedsUpdate = true; - - }, - - updateMatrixWorld: function ( force ) { - - if ( this.matrixAutoUpdate ) this.updateMatrix(); - - if ( this.matrixWorldNeedsUpdate || force ) { - - if ( this.parent === null ) { - - this.matrixWorld.copy( this.matrix ); - - } else { - - this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); - - } - - this.matrixWorldNeedsUpdate = false; - - force = true; - - } - - // update children - - var children = this.children; - - for ( var i = 0, l = children.length; i < l; i ++ ) { - - children[ i ].updateMatrixWorld( force ); - - } - - }, - - toJSON: function ( meta ) { - - // meta is a string when called from JSON.stringify - var isRootObject = ( meta === undefined || typeof meta === 'string' ); - - var output = {}; - - // meta is a hash used to collect geometries, materials. - // not providing it implies that this is the root object - // being serialized. - if ( isRootObject ) { - - // initialize meta obj - meta = { - geometries: {}, - materials: {}, - textures: {}, - images: {} - }; - - output.metadata = { - version: 4.5, - type: 'Object', - generator: 'Object3D.toJSON' - }; - - } - - // standard Object3D serialization - - var object = {}; - - object.uuid = this.uuid; - object.type = this.type; - - if ( this.name !== '' ) object.name = this.name; - if ( this.castShadow === true ) object.castShadow = true; - if ( this.receiveShadow === true ) object.receiveShadow = true; - if ( this.visible === false ) object.visible = false; - if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData; - - object.matrix = this.matrix.toArray(); - - // - - function serialize( library, element ) { - - if ( library[ element.uuid ] === undefined ) { - - library[ element.uuid ] = element.toJSON( meta ); - - } - - return element.uuid; - - } - - if ( this.geometry !== undefined ) { - - object.geometry = serialize( meta.geometries, this.geometry ); - - } - - if ( this.material !== undefined ) { - - if ( Array.isArray( this.material ) ) { - - var uuids = []; - - for ( var i = 0, l = this.material.length; i < l; i ++ ) { - - uuids.push( serialize( meta.materials, this.material[ i ] ) ); - - } - - object.material = uuids; - - } else { - - object.material = serialize( meta.materials, this.material ); - - } - - } - - // - - if ( this.children.length > 0 ) { - - object.children = []; - - for ( var i = 0; i < this.children.length; i ++ ) { - - object.children.push( this.children[ i ].toJSON( meta ).object ); - - } - - } - - if ( isRootObject ) { - - var geometries = extractFromCache( meta.geometries ); - var materials = extractFromCache( meta.materials ); - var textures = extractFromCache( meta.textures ); - var images = extractFromCache( meta.images ); - - if ( geometries.length > 0 ) output.geometries = geometries; - if ( materials.length > 0 ) output.materials = materials; - if ( textures.length > 0 ) output.textures = textures; - if ( images.length > 0 ) output.images = images; - - } - - output.object = object; - - return output; - - // extract data from the cache hash - // remove metadata on each item - // and return as array - function extractFromCache( cache ) { - - var values = []; - for ( var key in cache ) { - - var data = cache[ key ]; - delete data.metadata; - values.push( data ); - - } - return values; - - } - - }, - - clone: function ( recursive ) { - - return new this.constructor().copy( this, recursive ); - - }, - - copy: function ( source, recursive ) { - - if ( recursive === undefined ) recursive = true; - - this.name = source.name; - - this.up.copy( source.up ); - - this.position.copy( source.position ); - this.quaternion.copy( source.quaternion ); - this.scale.copy( source.scale ); - - this.matrix.copy( source.matrix ); - this.matrixWorld.copy( source.matrixWorld ); - - this.matrixAutoUpdate = source.matrixAutoUpdate; - this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate; - - this.layers.mask = source.layers.mask; - this.visible = source.visible; - - this.castShadow = source.castShadow; - this.receiveShadow = source.receiveShadow; - - this.frustumCulled = source.frustumCulled; - this.renderOrder = source.renderOrder; - - this.userData = JSON.parse( JSON.stringify( source.userData ) ); - - if ( recursive === true ) { - - for ( var i = 0; i < source.children.length; i ++ ) { - - var child = source.children[ i ]; - this.add( child.clone() ); - - } - - } - - return this; - - } - - } ); - - /** - * @author tschw - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( "Animation", () => { - - QUnit.module.todo( "AnimationObjectGroup", () => { - - var ObjectA = new Object3D(), - ObjectB = new Object3D(), - ObjectC = new Object3D(), - - PathA = 'object.position', - PathB = 'object.rotation', - PathC = 'object.scale', - - ParsedPathA = PropertyBinding.parseTrackName( PathA ), - ParsedPathB = PropertyBinding.parseTrackName( PathB ), - ParsedPathC = PropertyBinding.parseTrackName( PathC ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PRIVATE STUFF - QUnit.test( "subscribe_", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); // Todo: Naming guys -_-' - - QUnit.test( "unsubscribe_", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); // Todo: Naming guys -_-' - - // PUBLIC STUFF - QUnit.test( "isAnimationObjectGroup", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "add", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "remove", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "uncache", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( "smoke test", ( assert ) => { - - var expect = function expect( testIndex, group, bindings, path, cached, roots ) { - - var rootNodes = [], pathsOk = true, nodesOk = true; - - for ( var i = group.nCachedObjects_, n = bindings.length; i !== n; ++ i ) { - - if ( bindings[ i ].path !== path ) pathsOk = false; - rootNodes.push( bindings[ i ].rootNode ); - - } - - for ( var i = 0, n = roots.length; i !== n; ++ i ) { - - if ( rootNodes.indexOf( roots[ i ] ) === - 1 ) nodesOk = false; - - } - - assert.ok( pathsOk, QUnit.testIndex + " paths" ); - assert.ok( nodesOk, QUnit.testIndex + " nodes" ); - assert.ok( group.nCachedObjects_ === cached, QUnit.testIndex + " cache size" ); - assert.ok( bindings.length - group.nCachedObjects_ === roots.length, QUnit.testIndex + " object count" ); - - }; - - // initial state - - var groupA = new AnimationObjectGroup(); - assert.ok( groupA instanceof AnimationObjectGroup, "constructor (w/o args)" ); - - var bindingsAA = groupA.subscribe_( PathA, ParsedPathA ); - expect( 0, groupA, bindingsAA, PathA, 0, [] ); - - var groupB = new AnimationObjectGroup( ObjectA, ObjectB ); - assert.ok( groupB instanceof AnimationObjectGroup, "constructor (with args)" ); - - var bindingsBB = groupB.subscribe_( PathB, ParsedPathB ); - expect( 1, groupB, bindingsBB, PathB, 0, [ ObjectA, ObjectB ] ); - - // add - - groupA.add( ObjectA, ObjectB ); - expect( 2, groupA, bindingsAA, PathA, 0, [ ObjectA, ObjectB ] ); - - groupB.add( ObjectC ); - expect( 3, groupB, bindingsBB, PathB, 0, [ ObjectA, ObjectB, ObjectC ] ); - - // remove - - groupA.remove( ObjectA, ObjectC ); - expect( 4, groupA, bindingsAA, PathA, 1, [ ObjectB ] ); - - groupB.remove( ObjectA, ObjectB, ObjectC ); - expect( 5, groupB, bindingsBB, PathB, 3, [] ); - - // subscribe after re-add - - groupA.add( ObjectC ); - expect( 6, groupA, bindingsAA, PathA, 1, [ ObjectB, ObjectC ] ); - var bindingsAC = groupA.subscribe_( PathC, ParsedPathC ); - expect( 7, groupA, bindingsAC, PathC, 1, [ ObjectB, ObjectC ] ); - - // re-add after subscribe - - var bindingsBC = groupB.subscribe_( PathC, ParsedPathC ); - groupB.add( ObjectA, ObjectB ); - expect( 8, groupB, bindingsBB, PathB, 1, [ ObjectA, ObjectB ] ); - - // unsubscribe - - var copyOfBindingsBC = bindingsBC.slice(); - groupB.unsubscribe_( PathC ); - groupB.add( ObjectC ); - assert.deepEqual( bindingsBC, copyOfBindingsBC, "no more update after unsubscribe" ); - - // uncache active - - groupB.uncache( ObjectA ); - expect( 9, groupB, bindingsBB, PathB, 0, [ ObjectB, ObjectC ] ); - - // uncache cached - - groupA.uncache( ObjectA ); - expect( 10, groupA, bindingsAC, PathC, 0, [ ObjectB, ObjectC ] ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Animation', () => { - - QUnit.module.todo( 'AnimationUtils', () => { - - // PUBLIC STUFF - QUnit.test( "arraySlice", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "convertArray", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "isTypedArray", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getKeyframeOrder", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "sortedArray", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "flattenJSON", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Animation', () => { - - QUnit.module.todo( 'KeyframeTrack', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // STATIC STUFF - QUnit.test( "parse", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "toJSON", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_getTrackTypeForValueTypeName", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "TimeBufferType", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "ValueBufferType", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "DefaultInterpolation", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "InterpolantFactoryMethodDiscrete", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "InterpolantFactoryMethodLinear", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "InterpolantFactoryMethodSmooth", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setInterpolation", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getInterpolation", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getValueSize", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "shift", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "scale", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "trim", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "validate", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "optimize", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - var ColorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF, - 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2, - 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50, - 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B, - 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B, - 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F, - 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3, - 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222, - 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700, - 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4, - 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00, - 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3, - 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA, - 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32, - 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3, - 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC, - 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD, - 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6, - 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9, - 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F, - 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE, - 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA, - 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0, - 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 }; - - function Color( r, g, b ) { - - if ( g === undefined && b === undefined ) { - - // r is THREE.Color, hex or string - return this.set( r ); - - } - - return this.setRGB( r, g, b ); - - } - - Object.assign( Color.prototype, { - - isColor: true, - - r: 1, g: 1, b: 1, - - set: function ( value ) { - - if ( value && value.isColor ) { - - this.copy( value ); - - } else if ( typeof value === 'number' ) { - - this.setHex( value ); - - } else if ( typeof value === 'string' ) { - - this.setStyle( value ); - - } - - return this; - - }, - - setScalar: function ( scalar ) { - - this.r = scalar; - this.g = scalar; - this.b = scalar; - - return this; - - }, - - setHex: function ( hex ) { - - hex = Math.floor( hex ); - - this.r = ( hex >> 16 & 255 ) / 255; - this.g = ( hex >> 8 & 255 ) / 255; - this.b = ( hex & 255 ) / 255; - - return this; - - }, - - setRGB: function ( r, g, b ) { - - this.r = r; - this.g = g; - this.b = b; - - return this; - - }, - - setHSL: function () { - - function hue2rgb( p, q, t ) { - - if ( t < 0 ) t += 1; - if ( t > 1 ) t -= 1; - if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t; - if ( t < 1 / 2 ) return q; - if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t ); - return p; - - } - - return function setHSL( h, s, l ) { - - // h,s,l ranges are in 0.0 - 1.0 - h = _Math.euclideanModulo( h, 1 ); - s = _Math.clamp( s, 0, 1 ); - l = _Math.clamp( l, 0, 1 ); - - if ( s === 0 ) { - - this.r = this.g = this.b = l; - - } else { - - var p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s ); - var q = ( 2 * l ) - p; - - this.r = hue2rgb( q, p, h + 1 / 3 ); - this.g = hue2rgb( q, p, h ); - this.b = hue2rgb( q, p, h - 1 / 3 ); - - } - - return this; - - }; - - }(), - - setStyle: function ( style ) { - - function handleAlpha( string ) { - - if ( string === undefined ) return; - - if ( parseFloat( string ) < 1 ) { - - console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' ); - - } - - } - - - var m; - - if ( m = /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec( style ) ) { - - // rgb / hsl - - var color; - var name = m[ 1 ]; - var components = m[ 2 ]; - - switch ( name ) { - - case 'rgb': - case 'rgba': - - if ( color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) { - - // rgb(255,0,0) rgba(255,0,0,0.5) - this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255; - this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255; - this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255; - - handleAlpha( color[ 5 ] ); - - return this; - - } - - if ( color = /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) { - - // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5) - this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100; - this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100; - this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100; - - handleAlpha( color[ 5 ] ); - - return this; - - } - - break; - - case 'hsl': - case 'hsla': - - if ( color = /^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) { - - // hsl(120,50%,50%) hsla(120,50%,50%,0.5) - var h = parseFloat( color[ 1 ] ) / 360; - var s = parseInt( color[ 2 ], 10 ) / 100; - var l = parseInt( color[ 3 ], 10 ) / 100; - - handleAlpha( color[ 5 ] ); - - return this.setHSL( h, s, l ); - - } - - break; - - } - - } else if ( m = /^\#([A-Fa-f0-9]+)$/.exec( style ) ) { - - // hex color - - var hex = m[ 1 ]; - var size = hex.length; - - if ( size === 3 ) { - - // #ff0 - this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255; - this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255; - this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255; - - return this; - - } else if ( size === 6 ) { - - // #ff0000 - this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255; - this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255; - this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255; - - return this; - - } - - } - - if ( style && style.length > 0 ) { - - // color keywords - var hex = ColorKeywords[ style ]; - - if ( hex !== undefined ) { - - // red - this.setHex( hex ); - - } else { - - // unknown color - console.warn( 'THREE.Color: Unknown color ' + style ); - - } - - } - - return this; - - }, - - clone: function () { - - return new this.constructor( this.r, this.g, this.b ); - - }, - - copy: function ( color ) { - - this.r = color.r; - this.g = color.g; - this.b = color.b; - - return this; - - }, - - copyGammaToLinear: function ( color, gammaFactor ) { - - if ( gammaFactor === undefined ) gammaFactor = 2.0; - - this.r = Math.pow( color.r, gammaFactor ); - this.g = Math.pow( color.g, gammaFactor ); - this.b = Math.pow( color.b, gammaFactor ); - - return this; - - }, - - copyLinearToGamma: function ( color, gammaFactor ) { - - if ( gammaFactor === undefined ) gammaFactor = 2.0; - - var safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0; - - this.r = Math.pow( color.r, safeInverse ); - this.g = Math.pow( color.g, safeInverse ); - this.b = Math.pow( color.b, safeInverse ); - - return this; - - }, - - convertGammaToLinear: function () { - - var r = this.r, g = this.g, b = this.b; - - this.r = r * r; - this.g = g * g; - this.b = b * b; - - return this; - - }, - - convertLinearToGamma: function () { - - this.r = Math.sqrt( this.r ); - this.g = Math.sqrt( this.g ); - this.b = Math.sqrt( this.b ); - - return this; - - }, - - getHex: function () { - - return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0; - - }, - - getHexString: function () { - - return ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 ); - - }, - - getHSL: function ( optionalTarget ) { - - // h,s,l ranges are in 0.0 - 1.0 - - var hsl = optionalTarget || { h: 0, s: 0, l: 0 }; - - var r = this.r, g = this.g, b = this.b; - - var max = Math.max( r, g, b ); - var min = Math.min( r, g, b ); - - var hue, saturation; - var lightness = ( min + max ) / 2.0; - - if ( min === max ) { - - hue = 0; - saturation = 0; - - } else { - - var delta = max - min; - - saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min ); - - switch ( max ) { - - case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break; - case g: hue = ( b - r ) / delta + 2; break; - case b: hue = ( r - g ) / delta + 4; break; - - } - - hue /= 6; - - } - - hsl.h = hue; - hsl.s = saturation; - hsl.l = lightness; - - return hsl; - - }, - - getStyle: function () { - - return 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')'; - - }, - - offsetHSL: function ( h, s, l ) { - - var hsl = this.getHSL(); - - hsl.h += h; hsl.s += s; hsl.l += l; - - this.setHSL( hsl.h, hsl.s, hsl.l ); - - return this; - - }, - - add: function ( color ) { - - this.r += color.r; - this.g += color.g; - this.b += color.b; - - return this; - - }, - - addColors: function ( color1, color2 ) { - - this.r = color1.r + color2.r; - this.g = color1.g + color2.g; - this.b = color1.b + color2.b; - - return this; - - }, - - addScalar: function ( s ) { - - this.r += s; - this.g += s; - this.b += s; - - return this; - - }, - - sub: function ( color ) { - - this.r = Math.max( 0, this.r - color.r ); - this.g = Math.max( 0, this.g - color.g ); - this.b = Math.max( 0, this.b - color.b ); - - return this; - - }, - - multiply: function ( color ) { - - this.r *= color.r; - this.g *= color.g; - this.b *= color.b; - - return this; - - }, - - multiplyScalar: function ( s ) { - - this.r *= s; - this.g *= s; - this.b *= s; - - return this; - - }, - - lerp: function ( color, alpha ) { - - this.r += ( color.r - this.r ) * alpha; - this.g += ( color.g - this.g ) * alpha; - this.b += ( color.b - this.b ) * alpha; - - return this; - - }, - - equals: function ( c ) { - - return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b ); - - }, - - fromArray: function ( array, offset ) { - - if ( offset === undefined ) offset = 0; - - this.r = array[ offset ]; - this.g = array[ offset + 1 ]; - this.b = array[ offset + 2 ]; - - return this; - - }, - - toArray: function ( array, offset ) { - - if ( array === undefined ) array = []; - if ( offset === undefined ) offset = 0; - - array[ offset ] = this.r; - array[ offset + 1 ] = this.g; - array[ offset + 2 ] = this.b; - - return array; - - }, - - toJSON: function () { - - return this.getHex(); - - } - - } ); - - function Face3( a, b, c, normal, color, materialIndex ) { - - this.a = a; - this.b = b; - this.c = c; - - this.normal = ( normal && normal.isVector3 ) ? normal : new Vector3(); - this.vertexNormals = Array.isArray( normal ) ? normal : []; - - this.color = ( color && color.isColor ) ? color : new Color(); - this.vertexColors = Array.isArray( color ) ? color : []; - - this.materialIndex = materialIndex !== undefined ? materialIndex : 0; - - } - - Object.assign( Face3.prototype, { - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( source ) { - - this.a = source.a; - this.b = source.b; - this.c = source.c; - - this.normal.copy( source.normal ); - this.color.copy( source.color ); - - this.materialIndex = source.materialIndex; - - for ( var i = 0, il = source.vertexNormals.length; i < il; i ++ ) { - - this.vertexNormals[ i ] = source.vertexNormals[ i ].clone(); - - } - - for ( var i = 0, il = source.vertexColors.length; i < il; i ++ ) { - - this.vertexColors[ i ] = source.vertexColors[ i ].clone(); - - } - - return this; - - } - - } ); - - function Box3( min, max ) { - - this.min = ( min !== undefined ) ? min : new Vector3( + Infinity, + Infinity, + Infinity ); - this.max = ( max !== undefined ) ? max : new Vector3( - Infinity, - Infinity, - Infinity ); - - } - - Object.assign( Box3.prototype, { - - isBox3: true, - - set: function ( min, max ) { - - this.min.copy( min ); - this.max.copy( max ); - - return this; - - }, - - setFromArray: function ( array ) { - - var minX = + Infinity; - var minY = + Infinity; - var minZ = + Infinity; - - var maxX = - Infinity; - var maxY = - Infinity; - var maxZ = - Infinity; - - for ( var i = 0, l = array.length; i < l; i += 3 ) { - - var x = array[ i ]; - var y = array[ i + 1 ]; - var z = array[ i + 2 ]; - - if ( x < minX ) minX = x; - if ( y < minY ) minY = y; - if ( z < minZ ) minZ = z; - - if ( x > maxX ) maxX = x; - if ( y > maxY ) maxY = y; - if ( z > maxZ ) maxZ = z; - - } - - this.min.set( minX, minY, minZ ); - this.max.set( maxX, maxY, maxZ ); - - return this; - - }, - - setFromBufferAttribute: function ( attribute ) { - - var minX = + Infinity; - var minY = + Infinity; - var minZ = + Infinity; - - var maxX = - Infinity; - var maxY = - Infinity; - var maxZ = - Infinity; - - for ( var i = 0, l = attribute.count; i < l; i ++ ) { - - var x = attribute.getX( i ); - var y = attribute.getY( i ); - var z = attribute.getZ( i ); - - if ( x < minX ) minX = x; - if ( y < minY ) minY = y; - if ( z < minZ ) minZ = z; - - if ( x > maxX ) maxX = x; - if ( y > maxY ) maxY = y; - if ( z > maxZ ) maxZ = z; - - } - - this.min.set( minX, minY, minZ ); - this.max.set( maxX, maxY, maxZ ); - - return this; - - }, - - setFromPoints: function ( points ) { - - this.makeEmpty(); - - for ( var i = 0, il = points.length; i < il; i ++ ) { - - this.expandByPoint( points[ i ] ); - - } - - return this; - - }, - - setFromCenterAndSize: function () { - - var v1 = new Vector3(); - - return function setFromCenterAndSize( center, size ) { - - var halfSize = v1.copy( size ).multiplyScalar( 0.5 ); - - this.min.copy( center ).sub( halfSize ); - this.max.copy( center ).add( halfSize ); - - return this; - - }; - - }(), - - setFromObject: function ( object ) { - - this.makeEmpty(); - - return this.expandByObject( object ); - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( box ) { - - this.min.copy( box.min ); - this.max.copy( box.max ); - - return this; - - }, - - makeEmpty: function () { - - this.min.x = this.min.y = this.min.z = + Infinity; - this.max.x = this.max.y = this.max.z = - Infinity; - - return this; - - }, - - isEmpty: function () { - - // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes - - return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z ); - - }, - - getCenter: function ( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - return this.isEmpty() ? result.set( 0, 0, 0 ) : result.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); - - }, - - getSize: function ( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - return this.isEmpty() ? result.set( 0, 0, 0 ) : result.subVectors( this.max, this.min ); - - }, - - expandByPoint: function ( point ) { - - this.min.min( point ); - this.max.max( point ); - - return this; - - }, - - expandByVector: function ( vector ) { - - this.min.sub( vector ); - this.max.add( vector ); - - return this; - - }, - - expandByScalar: function ( scalar ) { - - this.min.addScalar( - scalar ); - this.max.addScalar( scalar ); - - return this; - - }, - - expandByObject: function () { - - // Computes the world-axis-aligned bounding box of an object (including its children), - // accounting for both the object's, and children's, world transforms - - var scope, i, l; - - var v1 = new Vector3(); - - function traverse( node ) { - - var geometry = node.geometry; - - if ( geometry !== undefined ) { - - if ( geometry.isGeometry ) { - - var vertices = geometry.vertices; - - for ( i = 0, l = vertices.length; i < l; i ++ ) { - - v1.copy( vertices[ i ] ); - v1.applyMatrix4( node.matrixWorld ); - - scope.expandByPoint( v1 ); - - } - - } else if ( geometry.isBufferGeometry ) { - - var attribute = geometry.attributes.position; - - if ( attribute !== undefined ) { - - for ( i = 0, l = attribute.count; i < l; i ++ ) { - - v1.fromBufferAttribute( attribute, i ).applyMatrix4( node.matrixWorld ); - - scope.expandByPoint( v1 ); - - } - - } - - } - - } - - } - - return function expandByObject( object ) { - - scope = this; - - object.updateMatrixWorld( true ); - - object.traverse( traverse ); - - return this; - - }; - - }(), - - containsPoint: function ( point ) { - - return point.x < this.min.x || point.x > this.max.x || - point.y < this.min.y || point.y > this.max.y || - point.z < this.min.z || point.z > this.max.z ? false : true; - - }, - - containsBox: function ( box ) { - - return this.min.x <= box.min.x && box.max.x <= this.max.x && - this.min.y <= box.min.y && box.max.y <= this.max.y && - this.min.z <= box.min.z && box.max.z <= this.max.z; - - }, - - getParameter: function ( point, optionalTarget ) { - - // This can potentially have a divide by zero if the box - // has a size dimension of 0. - - var result = optionalTarget || new Vector3(); - - return result.set( - ( point.x - this.min.x ) / ( this.max.x - this.min.x ), - ( point.y - this.min.y ) / ( this.max.y - this.min.y ), - ( point.z - this.min.z ) / ( this.max.z - this.min.z ) - ); - - }, - - intersectsBox: function ( box ) { - - // using 6 splitting planes to rule out intersections. - return box.max.x < this.min.x || box.min.x > this.max.x || - box.max.y < this.min.y || box.min.y > this.max.y || - box.max.z < this.min.z || box.min.z > this.max.z ? false : true; - - }, - - intersectsSphere: ( function () { - - var closestPoint = new Vector3(); - - return function intersectsSphere( sphere ) { - - // Find the point on the AABB closest to the sphere center. - this.clampPoint( sphere.center, closestPoint ); - - // If that point is inside the sphere, the AABB and sphere intersect. - return closestPoint.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius ); - - }; - - } )(), - - intersectsPlane: function ( plane ) { - - // We compute the minimum and maximum dot product values. If those values - // are on the same side (back or front) of the plane, then there is no intersection. - - var min, max; - - if ( plane.normal.x > 0 ) { - - min = plane.normal.x * this.min.x; - max = plane.normal.x * this.max.x; - - } else { - - min = plane.normal.x * this.max.x; - max = plane.normal.x * this.min.x; - - } - - if ( plane.normal.y > 0 ) { - - min += plane.normal.y * this.min.y; - max += plane.normal.y * this.max.y; - - } else { - - min += plane.normal.y * this.max.y; - max += plane.normal.y * this.min.y; - - } - - if ( plane.normal.z > 0 ) { - - min += plane.normal.z * this.min.z; - max += plane.normal.z * this.max.z; - - } else { - - min += plane.normal.z * this.max.z; - max += plane.normal.z * this.min.z; - - } - - return ( min <= plane.constant && max >= plane.constant ); - - }, - - clampPoint: function ( point, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - return result.copy( point ).clamp( this.min, this.max ); - - }, - - distanceToPoint: function () { - - var v1 = new Vector3(); - - return function distanceToPoint( point ) { - - var clampedPoint = v1.copy( point ).clamp( this.min, this.max ); - return clampedPoint.sub( point ).length(); - - }; - - }(), - - getBoundingSphere: function () { - - var v1 = new Vector3(); - - return function getBoundingSphere( optionalTarget ) { - - var result = optionalTarget || new Sphere(); - - this.getCenter( result.center ); - - result.radius = this.getSize( v1 ).length() * 0.5; - - return result; - - }; - - }(), - - intersect: function ( box ) { - - this.min.max( box.min ); - this.max.min( box.max ); - - // ensure that if there is no overlap, the result is fully empty, not slightly empty with non-inf/+inf values that will cause subsequence intersects to erroneously return valid values. - if ( this.isEmpty() ) this.makeEmpty(); - - return this; - - }, - - union: function ( box ) { - - this.min.min( box.min ); - this.max.max( box.max ); - - return this; - - }, - - applyMatrix4: function () { - - var points = [ - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3(), - new Vector3() - ]; - - return function applyMatrix4( matrix ) { - - // transform of empty box is an empty box. - if ( this.isEmpty() ) return this; - - // NOTE: I am using a binary pattern to specify all 2^3 combinations below - points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000 - points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001 - points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010 - points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011 - points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100 - points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101 - points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110 - points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111 - - this.setFromPoints( points ); - - return this; - - }; - - }(), - - translate: function ( offset ) { - - this.min.add( offset ); - this.max.add( offset ); - - return this; - - }, - - equals: function ( box ) { - - return box.min.equals( this.min ) && box.max.equals( this.max ); - - } - - } ); - - function Sphere( center, radius ) { - - this.center = ( center !== undefined ) ? center : new Vector3(); - this.radius = ( radius !== undefined ) ? radius : 0; - - } - - Object.assign( Sphere.prototype, { - - set: function ( center, radius ) { - - this.center.copy( center ); - this.radius = radius; - - return this; - - }, - - setFromPoints: function () { - - var box = new Box3(); - - return function setFromPoints( points, optionalCenter ) { - - var center = this.center; - - if ( optionalCenter !== undefined ) { - - center.copy( optionalCenter ); - - } else { - - box.setFromPoints( points ).getCenter( center ); - - } - - var maxRadiusSq = 0; - - for ( var i = 0, il = points.length; i < il; i ++ ) { - - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) ); - - } - - this.radius = Math.sqrt( maxRadiusSq ); - - return this; - - }; - - }(), - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( sphere ) { - - this.center.copy( sphere.center ); - this.radius = sphere.radius; - - return this; - - }, - - empty: function () { - - return ( this.radius <= 0 ); - - }, - - containsPoint: function ( point ) { - - return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) ); - - }, - - distanceToPoint: function ( point ) { - - return ( point.distanceTo( this.center ) - this.radius ); - - }, - - intersectsSphere: function ( sphere ) { - - var radiusSum = this.radius + sphere.radius; - - return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum ); - - }, - - intersectsBox: function ( box ) { - - return box.intersectsSphere( this ); - - }, - - intersectsPlane: function ( plane ) { - - return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius; - - }, - - clampPoint: function ( point, optionalTarget ) { - - var deltaLengthSq = this.center.distanceToSquared( point ); - - var result = optionalTarget || new Vector3(); - - result.copy( point ); - - if ( deltaLengthSq > ( this.radius * this.radius ) ) { - - result.sub( this.center ).normalize(); - result.multiplyScalar( this.radius ).add( this.center ); - - } - - return result; - - }, - - getBoundingBox: function ( optionalTarget ) { - - var box = optionalTarget || new Box3(); - - box.set( this.center, this.center ); - box.expandByScalar( this.radius ); - - return box; - - }, - - applyMatrix4: function ( matrix ) { - - this.center.applyMatrix4( matrix ); - this.radius = this.radius * matrix.getMaxScaleOnAxis(); - - return this; - - }, - - translate: function ( offset ) { - - this.center.add( offset ); - - return this; - - }, - - equals: function ( sphere ) { - - return sphere.center.equals( this.center ) && ( sphere.radius === this.radius ); - - } - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - * @author philogb / http://blog.thejit.org/ - * @author egraether / http://egraether.com/ - * @author zz85 / http://www.lab4games.net/zz85/blog - */ - - function Vector2( x, y ) { - - this.x = x || 0; - this.y = y || 0; - - } - - Object.defineProperties( Vector2.prototype, { - - "width": { - - get: function () { - - return this.x; - - }, - - set: function ( value ) { - - this.x = value; - - } - - }, - - "height": { - - get: function () { - - return this.y; - - }, - - set: function ( value ) { - - this.y = value; - - } - - } - - } ); - - Object.assign( Vector2.prototype, { - - isVector2: true, - - set: function ( x, y ) { - - this.x = x; - this.y = y; - - return this; - - }, - - setScalar: function ( scalar ) { - - this.x = scalar; - this.y = scalar; - - return this; - - }, - - setX: function ( x ) { - - this.x = x; - - return this; - - }, - - setY: function ( y ) { - - this.y = y; - - return this; - - }, - - setComponent: function ( index, value ) { - - switch ( index ) { - - case 0: this.x = value; break; - case 1: this.y = value; break; - default: throw new Error( 'index is out of range: ' + index ); - - } - - return this; - - }, - - getComponent: function ( index ) { - - switch ( index ) { - - case 0: return this.x; - case 1: return this.y; - default: throw new Error( 'index is out of range: ' + index ); - - } - - }, - - clone: function () { - - return new this.constructor( this.x, this.y ); - - }, - - copy: function ( v ) { - - this.x = v.x; - this.y = v.y; - - return this; - - }, - - add: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); - return this.addVectors( v, w ); - - } - - this.x += v.x; - this.y += v.y; - - return this; - - }, - - addScalar: function ( s ) { - - this.x += s; - this.y += s; - - return this; - - }, - - addVectors: function ( a, b ) { - - this.x = a.x + b.x; - this.y = a.y + b.y; - - return this; - - }, - - addScaledVector: function ( v, s ) { - - this.x += v.x * s; - this.y += v.y * s; - - return this; - - }, - - sub: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); - return this.subVectors( v, w ); - - } - - this.x -= v.x; - this.y -= v.y; - - return this; - - }, - - subScalar: function ( s ) { - - this.x -= s; - this.y -= s; - - return this; - - }, - - subVectors: function ( a, b ) { - - this.x = a.x - b.x; - this.y = a.y - b.y; - - return this; - - }, - - multiply: function ( v ) { - - this.x *= v.x; - this.y *= v.y; - - return this; - - }, - - multiplyScalar: function ( scalar ) { - - this.x *= scalar; - this.y *= scalar; - - return this; - - }, - - divide: function ( v ) { - - this.x /= v.x; - this.y /= v.y; - - return this; - - }, - - divideScalar: function ( scalar ) { - - return this.multiplyScalar( 1 / scalar ); - - }, - - applyMatrix3: function ( m ) { - - var x = this.x, y = this.y; - var e = m.elements; - - this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ]; - this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ]; - - return this; - - }, - - min: function ( v ) { - - this.x = Math.min( this.x, v.x ); - this.y = Math.min( this.y, v.y ); - - return this; - - }, - - max: function ( v ) { - - this.x = Math.max( this.x, v.x ); - this.y = Math.max( this.y, v.y ); - - return this; - - }, - - clamp: function ( min, max ) { - - // assumes min < max, componentwise - - this.x = Math.max( min.x, Math.min( max.x, this.x ) ); - this.y = Math.max( min.y, Math.min( max.y, this.y ) ); - - return this; - - }, - - clampScalar: function () { - - var min = new Vector2(); - var max = new Vector2(); - - return function clampScalar( minVal, maxVal ) { - - min.set( minVal, minVal ); - max.set( maxVal, maxVal ); - - return this.clamp( min, max ); - - }; - - }(), - - clampLength: function ( min, max ) { - - var length = this.length(); - - return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); - - }, - - floor: function () { - - this.x = Math.floor( this.x ); - this.y = Math.floor( this.y ); - - return this; - - }, - - ceil: function () { - - this.x = Math.ceil( this.x ); - this.y = Math.ceil( this.y ); - - return this; - - }, - - round: function () { - - this.x = Math.round( this.x ); - this.y = Math.round( this.y ); - - return this; - - }, - - roundToZero: function () { - - this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x ); - this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y ); - - return this; - - }, - - negate: function () { - - this.x = - this.x; - this.y = - this.y; - - return this; - - }, - - dot: function ( v ) { - - return this.x * v.x + this.y * v.y; - - }, - - lengthSq: function () { - - return this.x * this.x + this.y * this.y; - - }, - - length: function () { - - return Math.sqrt( this.x * this.x + this.y * this.y ); - - }, - - manhattanLength: function () { - - return Math.abs( this.x ) + Math.abs( this.y ); - - }, - - normalize: function () { - - return this.divideScalar( this.length() || 1 ); - - }, - - angle: function () { - - // computes the angle in radians with respect to the positive x-axis - - var angle = Math.atan2( this.y, this.x ); - - if ( angle < 0 ) angle += 2 * Math.PI; - - return angle; - - }, - - distanceTo: function ( v ) { - - return Math.sqrt( this.distanceToSquared( v ) ); - - }, - - distanceToSquared: function ( v ) { - - var dx = this.x - v.x, dy = this.y - v.y; - return dx * dx + dy * dy; - - }, - - manhattanDistanceTo: function ( v ) { - - return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ); - - }, - - setLength: function ( length ) { - - return this.normalize().multiplyScalar( length ); - - }, - - lerp: function ( v, alpha ) { - - this.x += ( v.x - this.x ) * alpha; - this.y += ( v.y - this.y ) * alpha; - - return this; - - }, - - lerpVectors: function ( v1, v2, alpha ) { - - return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 ); - - }, - - equals: function ( v ) { - - return ( ( v.x === this.x ) && ( v.y === this.y ) ); - - }, - - fromArray: function ( array, offset ) { - - if ( offset === undefined ) offset = 0; - - this.x = array[ offset ]; - this.y = array[ offset + 1 ]; - - return this; - - }, - - toArray: function ( array, offset ) { - - if ( array === undefined ) array = []; - if ( offset === undefined ) offset = 0; - - array[ offset ] = this.x; - array[ offset + 1 ] = this.y; - - return array; - - }, - - fromBufferAttribute: function ( attribute, index, offset ) { - - if ( offset !== undefined ) { - - console.warn( 'THREE.Vector2: offset has been removed from .fromBufferAttribute().' ); - - } - - this.x = attribute.getX( index ); - this.y = attribute.getY( index ); - - return this; - - }, - - rotateAround: function ( center, angle ) { - - var c = Math.cos( angle ), s = Math.sin( angle ); - - var x = this.x - center.x; - var y = this.y - center.y; - - this.x = x * c - y * s + center.x; - this.y = x * s + y * c + center.y; - - return this; - - } - - } ); - - var geometryId = 0; // Geometry uses even numbers as Id - - function Geometry() { - - Object.defineProperty( this, 'id', { value: geometryId += 2 } ); - - this.uuid = _Math.generateUUID(); - - this.name = ''; - this.type = 'Geometry'; - - this.vertices = []; - this.colors = []; - this.faces = []; - this.faceVertexUvs = [[]]; - - this.morphTargets = []; - this.morphNormals = []; - - this.skinWeights = []; - this.skinIndices = []; - - this.lineDistances = []; - - this.boundingBox = null; - this.boundingSphere = null; - - // update flags - - this.elementsNeedUpdate = false; - this.verticesNeedUpdate = false; - this.uvsNeedUpdate = false; - this.normalsNeedUpdate = false; - this.colorsNeedUpdate = false; - this.lineDistancesNeedUpdate = false; - this.groupsNeedUpdate = false; - - } - - Object.assign( Geometry.prototype, EventDispatcher.prototype, { - - isGeometry: true, - - applyMatrix: function ( matrix ) { - - var normalMatrix = new Matrix3().getNormalMatrix( matrix ); - - for ( var i = 0, il = this.vertices.length; i < il; i ++ ) { - - var vertex = this.vertices[ i ]; - vertex.applyMatrix4( matrix ); - - } - - for ( var i = 0, il = this.faces.length; i < il; i ++ ) { - - var face = this.faces[ i ]; - face.normal.applyMatrix3( normalMatrix ).normalize(); - - for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) { - - face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize(); - - } - - } - - if ( this.boundingBox !== null ) { - - this.computeBoundingBox(); - - } - - if ( this.boundingSphere !== null ) { - - this.computeBoundingSphere(); - - } - - this.verticesNeedUpdate = true; - this.normalsNeedUpdate = true; - - return this; - - }, - - rotateX: function () { - - // rotate geometry around world x-axis - - var m1 = new Matrix4(); - - return function rotateX( angle ) { - - m1.makeRotationX( angle ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - rotateY: function () { - - // rotate geometry around world y-axis - - var m1 = new Matrix4(); - - return function rotateY( angle ) { - - m1.makeRotationY( angle ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - rotateZ: function () { - - // rotate geometry around world z-axis - - var m1 = new Matrix4(); - - return function rotateZ( angle ) { - - m1.makeRotationZ( angle ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - translate: function () { - - // translate geometry - - var m1 = new Matrix4(); - - return function translate( x, y, z ) { - - m1.makeTranslation( x, y, z ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - scale: function () { - - // scale geometry - - var m1 = new Matrix4(); - - return function scale( x, y, z ) { - - m1.makeScale( x, y, z ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - lookAt: function () { - - var obj = new Object3D(); - - return function lookAt( vector ) { - - obj.lookAt( vector ); - - obj.updateMatrix(); - - this.applyMatrix( obj.matrix ); - - }; - - }(), - - fromBufferGeometry: function ( geometry ) { - - var scope = this; - - var indices = geometry.index !== null ? geometry.index.array : undefined; - var attributes = geometry.attributes; - - var positions = attributes.position.array; - var normals = attributes.normal !== undefined ? attributes.normal.array : undefined; - var colors = attributes.color !== undefined ? attributes.color.array : undefined; - var uvs = attributes.uv !== undefined ? attributes.uv.array : undefined; - var uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined; - - if ( uvs2 !== undefined ) this.faceVertexUvs[ 1 ] = []; - - var tempNormals = []; - var tempUVs = []; - var tempUVs2 = []; - - for ( var i = 0, j = 0; i < positions.length; i += 3, j += 2 ) { - - scope.vertices.push( new Vector3( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] ) ); - - if ( normals !== undefined ) { - - tempNormals.push( new Vector3( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] ) ); - - } - - if ( colors !== undefined ) { - - scope.colors.push( new Color( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ) ); - - } - - if ( uvs !== undefined ) { - - tempUVs.push( new Vector2( uvs[ j ], uvs[ j + 1 ] ) ); - - } - - if ( uvs2 !== undefined ) { - - tempUVs2.push( new Vector2( uvs2[ j ], uvs2[ j + 1 ] ) ); - - } - - } - - function addFace( a, b, c, materialIndex ) { - - var vertexNormals = normals !== undefined ? [ tempNormals[ a ].clone(), tempNormals[ b ].clone(), tempNormals[ c ].clone() ] : []; - var vertexColors = colors !== undefined ? [ scope.colors[ a ].clone(), scope.colors[ b ].clone(), scope.colors[ c ].clone() ] : []; - - var face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex ); - - scope.faces.push( face ); - - if ( uvs !== undefined ) { - - scope.faceVertexUvs[ 0 ].push( [ tempUVs[ a ].clone(), tempUVs[ b ].clone(), tempUVs[ c ].clone() ] ); - - } - - if ( uvs2 !== undefined ) { - - scope.faceVertexUvs[ 1 ].push( [ tempUVs2[ a ].clone(), tempUVs2[ b ].clone(), tempUVs2[ c ].clone() ] ); - - } - - } - - var groups = geometry.groups; - - if ( groups.length > 0 ) { - - for ( var i = 0; i < groups.length; i ++ ) { - - var group = groups[ i ]; - - var start = group.start; - var count = group.count; - - for ( var j = start, jl = start + count; j < jl; j += 3 ) { - - if ( indices !== undefined ) { - - addFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ], group.materialIndex ); - - } else { - - addFace( j, j + 1, j + 2, group.materialIndex ); - - } - - } - - } - - } else { - - if ( indices !== undefined ) { - - for ( var i = 0; i < indices.length; i += 3 ) { - - addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] ); - - } - - } else { - - for ( var i = 0; i < positions.length / 3; i += 3 ) { - - addFace( i, i + 1, i + 2 ); - - } - - } - - } - - this.computeFaceNormals(); - - if ( geometry.boundingBox !== null ) { - - this.boundingBox = geometry.boundingBox.clone(); - - } - - if ( geometry.boundingSphere !== null ) { - - this.boundingSphere = geometry.boundingSphere.clone(); - - } - - return this; - - }, - - center: function () { - - this.computeBoundingBox(); - - var offset = this.boundingBox.getCenter().negate(); - - this.translate( offset.x, offset.y, offset.z ); - - return offset; - - }, - - normalize: function () { - - this.computeBoundingSphere(); - - var center = this.boundingSphere.center; - var radius = this.boundingSphere.radius; - - var s = radius === 0 ? 1 : 1.0 / radius; - - var matrix = new Matrix4(); - matrix.set( - s, 0, 0, - s * center.x, - 0, s, 0, - s * center.y, - 0, 0, s, - s * center.z, - 0, 0, 0, 1 - ); - - this.applyMatrix( matrix ); - - return this; - - }, - - computeFaceNormals: function () { - - var cb = new Vector3(), ab = new Vector3(); - - for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) { - - var face = this.faces[ f ]; - - var vA = this.vertices[ face.a ]; - var vB = this.vertices[ face.b ]; - var vC = this.vertices[ face.c ]; - - cb.subVectors( vC, vB ); - ab.subVectors( vA, vB ); - cb.cross( ab ); - - cb.normalize(); - - face.normal.copy( cb ); - - } - - }, - - computeVertexNormals: function ( areaWeighted ) { - - if ( areaWeighted === undefined ) areaWeighted = true; - - var v, vl, f, fl, face, vertices; - - vertices = new Array( this.vertices.length ); - - for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { - - vertices[ v ] = new Vector3(); - - } - - if ( areaWeighted ) { - - // vertex normals weighted by triangle areas - // http://www.iquilezles.org/www/articles/normals/normals.htm - - var vA, vB, vC; - var cb = new Vector3(), ab = new Vector3(); - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - vA = this.vertices[ face.a ]; - vB = this.vertices[ face.b ]; - vC = this.vertices[ face.c ]; - - cb.subVectors( vC, vB ); - ab.subVectors( vA, vB ); - cb.cross( ab ); - - vertices[ face.a ].add( cb ); - vertices[ face.b ].add( cb ); - vertices[ face.c ].add( cb ); - - } - - } else { - - this.computeFaceNormals(); - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - vertices[ face.a ].add( face.normal ); - vertices[ face.b ].add( face.normal ); - vertices[ face.c ].add( face.normal ); - - } - - } - - for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { - - vertices[ v ].normalize(); - - } - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - var vertexNormals = face.vertexNormals; - - if ( vertexNormals.length === 3 ) { - - vertexNormals[ 0 ].copy( vertices[ face.a ] ); - vertexNormals[ 1 ].copy( vertices[ face.b ] ); - vertexNormals[ 2 ].copy( vertices[ face.c ] ); - - } else { - - vertexNormals[ 0 ] = vertices[ face.a ].clone(); - vertexNormals[ 1 ] = vertices[ face.b ].clone(); - vertexNormals[ 2 ] = vertices[ face.c ].clone(); - - } - - } - - if ( this.faces.length > 0 ) { - - this.normalsNeedUpdate = true; - - } - - }, - - computeFlatVertexNormals: function () { - - var f, fl, face; - - this.computeFaceNormals(); - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - var vertexNormals = face.vertexNormals; - - if ( vertexNormals.length === 3 ) { - - vertexNormals[ 0 ].copy( face.normal ); - vertexNormals[ 1 ].copy( face.normal ); - vertexNormals[ 2 ].copy( face.normal ); - - } else { - - vertexNormals[ 0 ] = face.normal.clone(); - vertexNormals[ 1 ] = face.normal.clone(); - vertexNormals[ 2 ] = face.normal.clone(); - - } - - } - - if ( this.faces.length > 0 ) { - - this.normalsNeedUpdate = true; - - } - - }, - - computeMorphNormals: function () { - - var i, il, f, fl, face; - - // save original normals - // - create temp variables on first access - // otherwise just copy (for faster repeated calls) - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - if ( ! face.__originalFaceNormal ) { - - face.__originalFaceNormal = face.normal.clone(); - - } else { - - face.__originalFaceNormal.copy( face.normal ); - - } - - if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = []; - - for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) { - - if ( ! face.__originalVertexNormals[ i ] ) { - - face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone(); - - } else { - - face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] ); - - } - - } - - } - - // use temp geometry to compute face and vertex normals for each morph - - var tmpGeo = new Geometry(); - tmpGeo.faces = this.faces; - - for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) { - - // create on first access - - if ( ! this.morphNormals[ i ] ) { - - this.morphNormals[ i ] = {}; - this.morphNormals[ i ].faceNormals = []; - this.morphNormals[ i ].vertexNormals = []; - - var dstNormalsFace = this.morphNormals[ i ].faceNormals; - var dstNormalsVertex = this.morphNormals[ i ].vertexNormals; - - var faceNormal, vertexNormals; - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - faceNormal = new Vector3(); - vertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() }; - - dstNormalsFace.push( faceNormal ); - dstNormalsVertex.push( vertexNormals ); - - } - - } - - var morphNormals = this.morphNormals[ i ]; - - // set vertices to morph target - - tmpGeo.vertices = this.morphTargets[ i ].vertices; - - // compute morph normals - - tmpGeo.computeFaceNormals(); - tmpGeo.computeVertexNormals(); - - // store morph normals - - var faceNormal, vertexNormals; - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - faceNormal = morphNormals.faceNormals[ f ]; - vertexNormals = morphNormals.vertexNormals[ f ]; - - faceNormal.copy( face.normal ); - - vertexNormals.a.copy( face.vertexNormals[ 0 ] ); - vertexNormals.b.copy( face.vertexNormals[ 1 ] ); - vertexNormals.c.copy( face.vertexNormals[ 2 ] ); - - } - - } - - // restore original normals - - for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { - - face = this.faces[ f ]; - - face.normal = face.__originalFaceNormal; - face.vertexNormals = face.__originalVertexNormals; - - } - - }, - - computeLineDistances: function () { - - var d = 0; - var vertices = this.vertices; - - for ( var i = 0, il = vertices.length; i < il; i ++ ) { - - if ( i > 0 ) { - - d += vertices[ i ].distanceTo( vertices[ i - 1 ] ); - - } - - this.lineDistances[ i ] = d; - - } - - }, - - computeBoundingBox: function () { - - if ( this.boundingBox === null ) { - - this.boundingBox = new Box3(); - - } - - this.boundingBox.setFromPoints( this.vertices ); - - }, - - computeBoundingSphere: function () { - - if ( this.boundingSphere === null ) { - - this.boundingSphere = new Sphere(); - - } - - this.boundingSphere.setFromPoints( this.vertices ); - - }, - - merge: function ( geometry, matrix, materialIndexOffset ) { - - if ( ! ( geometry && geometry.isGeometry ) ) { - - console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry ); - return; - - } - - var normalMatrix, - vertexOffset = this.vertices.length, - vertices1 = this.vertices, - vertices2 = geometry.vertices, - faces1 = this.faces, - faces2 = geometry.faces, - uvs1 = this.faceVertexUvs[ 0 ], - uvs2 = geometry.faceVertexUvs[ 0 ], - colors1 = this.colors, - colors2 = geometry.colors; - - if ( materialIndexOffset === undefined ) materialIndexOffset = 0; - - if ( matrix !== undefined ) { - - normalMatrix = new Matrix3().getNormalMatrix( matrix ); - - } - - // vertices - - for ( var i = 0, il = vertices2.length; i < il; i ++ ) { - - var vertex = vertices2[ i ]; - - var vertexCopy = vertex.clone(); - - if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix ); - - vertices1.push( vertexCopy ); - - } - - // colors - - for ( var i = 0, il = colors2.length; i < il; i ++ ) { - - colors1.push( colors2[ i ].clone() ); - - } - - // faces - - for ( i = 0, il = faces2.length; i < il; i ++ ) { - - var face = faces2[ i ], faceCopy, normal, color, - faceVertexNormals = face.vertexNormals, - faceVertexColors = face.vertexColors; - - faceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset ); - faceCopy.normal.copy( face.normal ); - - if ( normalMatrix !== undefined ) { - - faceCopy.normal.applyMatrix3( normalMatrix ).normalize(); - - } - - for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) { - - normal = faceVertexNormals[ j ].clone(); - - if ( normalMatrix !== undefined ) { - - normal.applyMatrix3( normalMatrix ).normalize(); - - } - - faceCopy.vertexNormals.push( normal ); - - } - - faceCopy.color.copy( face.color ); - - for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) { - - color = faceVertexColors[ j ]; - faceCopy.vertexColors.push( color.clone() ); - - } - - faceCopy.materialIndex = face.materialIndex + materialIndexOffset; - - faces1.push( faceCopy ); - - } - - // uvs - - for ( i = 0, il = uvs2.length; i < il; i ++ ) { - - var uv = uvs2[ i ], uvCopy = []; - - if ( uv === undefined ) { - - continue; - - } - - for ( var j = 0, jl = uv.length; j < jl; j ++ ) { - - uvCopy.push( uv[ j ].clone() ); - - } - - uvs1.push( uvCopy ); - - } - - }, - - mergeMesh: function ( mesh ) { - - if ( ! ( mesh && mesh.isMesh ) ) { - - console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh ); - return; - - } - - mesh.matrixAutoUpdate && mesh.updateMatrix(); - - this.merge( mesh.geometry, mesh.matrix ); - - }, - - /* - * Checks for duplicate vertices with hashmap. - * Duplicated vertices are removed - * and faces' vertices are updated. - */ - - mergeVertices: function () { - - var verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique) - var unique = [], changes = []; - - var v, key; - var precisionPoints = 4; // number of decimal points, e.g. 4 for epsilon of 0.0001 - var precision = Math.pow( 10, precisionPoints ); - var i, il, face; - var indices, j, jl; - - for ( i = 0, il = this.vertices.length; i < il; i ++ ) { - - v = this.vertices[ i ]; - key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision ); - - if ( verticesMap[ key ] === undefined ) { - - verticesMap[ key ] = i; - unique.push( this.vertices[ i ] ); - changes[ i ] = unique.length - 1; - - } else { - - //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]); - changes[ i ] = changes[ verticesMap[ key ] ]; - - } - - } - - - // if faces are completely degenerate after merging vertices, we - // have to remove them from the geometry. - var faceIndicesToRemove = []; - - for ( i = 0, il = this.faces.length; i < il; i ++ ) { - - face = this.faces[ i ]; - - face.a = changes[ face.a ]; - face.b = changes[ face.b ]; - face.c = changes[ face.c ]; - - indices = [ face.a, face.b, face.c ]; - - // if any duplicate vertices are found in a Face3 - // we have to remove the face as nothing can be saved - for ( var n = 0; n < 3; n ++ ) { - - if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) { - - faceIndicesToRemove.push( i ); - break; - - } - - } - - } - - for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) { - - var idx = faceIndicesToRemove[ i ]; - - this.faces.splice( idx, 1 ); - - for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) { - - this.faceVertexUvs[ j ].splice( idx, 1 ); - - } - - } - - // Use unique set of vertices - - var diff = this.vertices.length - unique.length; - this.vertices = unique; - return diff; - - }, - - setFromPoints: function ( points ) { - - this.vertices = []; - - for ( var i = 0, l = points.length; i < l; i ++ ) { - - var point = points[ i ]; - this.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) ); - - } - - return this; - - }, - - sortFacesByMaterialIndex: function () { - - var faces = this.faces; - var length = faces.length; - - // tag faces - - for ( var i = 0; i < length; i ++ ) { - - faces[ i ]._id = i; - - } - - // sort faces - - function materialIndexSort( a, b ) { - - return a.materialIndex - b.materialIndex; - - } - - faces.sort( materialIndexSort ); - - // sort uvs - - var uvs1 = this.faceVertexUvs[ 0 ]; - var uvs2 = this.faceVertexUvs[ 1 ]; - - var newUvs1, newUvs2; - - if ( uvs1 && uvs1.length === length ) newUvs1 = []; - if ( uvs2 && uvs2.length === length ) newUvs2 = []; - - for ( var i = 0; i < length; i ++ ) { - - var id = faces[ i ]._id; - - if ( newUvs1 ) newUvs1.push( uvs1[ id ] ); - if ( newUvs2 ) newUvs2.push( uvs2[ id ] ); - - } - - if ( newUvs1 ) this.faceVertexUvs[ 0 ] = newUvs1; - if ( newUvs2 ) this.faceVertexUvs[ 1 ] = newUvs2; - - }, - - toJSON: function () { - - var data = { - metadata: { - version: 4.5, - type: 'Geometry', - generator: 'Geometry.toJSON' - } - }; - - // standard Geometry serialization - - data.uuid = this.uuid; - data.type = this.type; - if ( this.name !== '' ) data.name = this.name; - - if ( this.parameters !== undefined ) { - - var parameters = this.parameters; - - for ( var key in parameters ) { - - if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; - - } - - return data; - - } - - var vertices = []; - - for ( var i = 0; i < this.vertices.length; i ++ ) { - - var vertex = this.vertices[ i ]; - vertices.push( vertex.x, vertex.y, vertex.z ); - - } - - var faces = []; - var normals = []; - var normalsHash = {}; - var colors = []; - var colorsHash = {}; - var uvs = []; - var uvsHash = {}; - - for ( var i = 0; i < this.faces.length; i ++ ) { - - var face = this.faces[ i ]; - - var hasMaterial = true; - var hasFaceUv = false; // deprecated - var hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== undefined; - var hasFaceNormal = face.normal.length() > 0; - var hasFaceVertexNormal = face.vertexNormals.length > 0; - var hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1; - var hasFaceVertexColor = face.vertexColors.length > 0; - - var faceType = 0; - - faceType = setBit( faceType, 0, 0 ); // isQuad - faceType = setBit( faceType, 1, hasMaterial ); - faceType = setBit( faceType, 2, hasFaceUv ); - faceType = setBit( faceType, 3, hasFaceVertexUv ); - faceType = setBit( faceType, 4, hasFaceNormal ); - faceType = setBit( faceType, 5, hasFaceVertexNormal ); - faceType = setBit( faceType, 6, hasFaceColor ); - faceType = setBit( faceType, 7, hasFaceVertexColor ); - - faces.push( faceType ); - faces.push( face.a, face.b, face.c ); - faces.push( face.materialIndex ); - - if ( hasFaceVertexUv ) { - - var faceVertexUvs = this.faceVertexUvs[ 0 ][ i ]; - - faces.push( - getUvIndex( faceVertexUvs[ 0 ] ), - getUvIndex( faceVertexUvs[ 1 ] ), - getUvIndex( faceVertexUvs[ 2 ] ) - ); - - } - - if ( hasFaceNormal ) { - - faces.push( getNormalIndex( face.normal ) ); - - } - - if ( hasFaceVertexNormal ) { - - var vertexNormals = face.vertexNormals; - - faces.push( - getNormalIndex( vertexNormals[ 0 ] ), - getNormalIndex( vertexNormals[ 1 ] ), - getNormalIndex( vertexNormals[ 2 ] ) - ); - - } - - if ( hasFaceColor ) { - - faces.push( getColorIndex( face.color ) ); - - } - - if ( hasFaceVertexColor ) { - - var vertexColors = face.vertexColors; - - faces.push( - getColorIndex( vertexColors[ 0 ] ), - getColorIndex( vertexColors[ 1 ] ), - getColorIndex( vertexColors[ 2 ] ) - ); - - } - - } - - function setBit( value, position, enabled ) { - - return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) ); - - } - - function getNormalIndex( normal ) { - - var hash = normal.x.toString() + normal.y.toString() + normal.z.toString(); - - if ( normalsHash[ hash ] !== undefined ) { - - return normalsHash[ hash ]; - - } - - normalsHash[ hash ] = normals.length / 3; - normals.push( normal.x, normal.y, normal.z ); - - return normalsHash[ hash ]; - - } - - function getColorIndex( color ) { - - var hash = color.r.toString() + color.g.toString() + color.b.toString(); - - if ( colorsHash[ hash ] !== undefined ) { - - return colorsHash[ hash ]; - - } - - colorsHash[ hash ] = colors.length; - colors.push( color.getHex() ); - - return colorsHash[ hash ]; - - } - - function getUvIndex( uv ) { - - var hash = uv.x.toString() + uv.y.toString(); - - if ( uvsHash[ hash ] !== undefined ) { - - return uvsHash[ hash ]; - - } - - uvsHash[ hash ] = uvs.length / 2; - uvs.push( uv.x, uv.y ); - - return uvsHash[ hash ]; - - } - - data.data = {}; - - data.data.vertices = vertices; - data.data.normals = normals; - if ( colors.length > 0 ) data.data.colors = colors; - if ( uvs.length > 0 ) data.data.uvs = [ uvs ]; // temporal backward compatibility - data.data.faces = faces; - - return data; - - }, - - clone: function () { - - /* - // Handle primitives - - var parameters = this.parameters; - - if ( parameters !== undefined ) { - - var values = []; - - for ( var key in parameters ) { - - values.push( parameters[ key ] ); - - } - - var geometry = Object.create( this.constructor.prototype ); - this.constructor.apply( geometry, values ); - return geometry; - - } - - return new this.constructor().copy( this ); - */ - - return new Geometry().copy( this ); - - }, - - copy: function ( source ) { - - var i, il, j, jl, k, kl; - - // reset - - this.vertices = []; - this.colors = []; - this.faces = []; - this.faceVertexUvs = [[]]; - this.morphTargets = []; - this.morphNormals = []; - this.skinWeights = []; - this.skinIndices = []; - this.lineDistances = []; - this.boundingBox = null; - this.boundingSphere = null; - - // name - - this.name = source.name; - - // vertices - - var vertices = source.vertices; - - for ( i = 0, il = vertices.length; i < il; i ++ ) { - - this.vertices.push( vertices[ i ].clone() ); - - } - - // colors - - var colors = source.colors; - - for ( i = 0, il = colors.length; i < il; i ++ ) { - - this.colors.push( colors[ i ].clone() ); - - } - - // faces - - var faces = source.faces; - - for ( i = 0, il = faces.length; i < il; i ++ ) { - - this.faces.push( faces[ i ].clone() ); - - } - - // face vertex uvs - - for ( i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) { - - var faceVertexUvs = source.faceVertexUvs[ i ]; - - if ( this.faceVertexUvs[ i ] === undefined ) { - - this.faceVertexUvs[ i ] = []; - - } - - for ( j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) { - - var uvs = faceVertexUvs[ j ], uvsCopy = []; - - for ( k = 0, kl = uvs.length; k < kl; k ++ ) { - - var uv = uvs[ k ]; - - uvsCopy.push( uv.clone() ); - - } - - this.faceVertexUvs[ i ].push( uvsCopy ); - - } - - } - - // morph targets - - var morphTargets = source.morphTargets; - - for ( i = 0, il = morphTargets.length; i < il; i ++ ) { - - var morphTarget = {}; - morphTarget.name = morphTargets[ i ].name; - - // vertices - - if ( morphTargets[ i ].vertices !== undefined ) { - - morphTarget.vertices = []; - - for ( j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) { - - morphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() ); - - } - - } - - // normals - - if ( morphTargets[ i ].normals !== undefined ) { - - morphTarget.normals = []; - - for ( j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) { - - morphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() ); - - } - - } - - this.morphTargets.push( morphTarget ); - - } - - // morph normals - - var morphNormals = source.morphNormals; - - for ( i = 0, il = morphNormals.length; i < il; i ++ ) { - - var morphNormal = {}; - - // vertex normals - - if ( morphNormals[ i ].vertexNormals !== undefined ) { - - morphNormal.vertexNormals = []; - - for ( j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) { - - var srcVertexNormal = morphNormals[ i ].vertexNormals[ j ]; - var destVertexNormal = {}; - - destVertexNormal.a = srcVertexNormal.a.clone(); - destVertexNormal.b = srcVertexNormal.b.clone(); - destVertexNormal.c = srcVertexNormal.c.clone(); - - morphNormal.vertexNormals.push( destVertexNormal ); - - } - - } - - // face normals - - if ( morphNormals[ i ].faceNormals !== undefined ) { - - morphNormal.faceNormals = []; - - for ( j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) { - - morphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() ); - - } - - } - - this.morphNormals.push( morphNormal ); - - } - - // skin weights - - var skinWeights = source.skinWeights; - - for ( i = 0, il = skinWeights.length; i < il; i ++ ) { - - this.skinWeights.push( skinWeights[ i ].clone() ); - - } - - // skin indices - - var skinIndices = source.skinIndices; - - for ( i = 0, il = skinIndices.length; i < il; i ++ ) { - - this.skinIndices.push( skinIndices[ i ].clone() ); - - } - - // line distances - - var lineDistances = source.lineDistances; - - for ( i = 0, il = lineDistances.length; i < il; i ++ ) { - - this.lineDistances.push( lineDistances[ i ] ); - - } - - // bounding box - - var boundingBox = source.boundingBox; - - if ( boundingBox !== null ) { - - this.boundingBox = boundingBox.clone(); - - } - - // bounding sphere - - var boundingSphere = source.boundingSphere; - - if ( boundingSphere !== null ) { - - this.boundingSphere = boundingSphere.clone(); - - } - - // update flags - - this.elementsNeedUpdate = source.elementsNeedUpdate; - this.verticesNeedUpdate = source.verticesNeedUpdate; - this.uvsNeedUpdate = source.uvsNeedUpdate; - this.normalsNeedUpdate = source.normalsNeedUpdate; - this.colorsNeedUpdate = source.colorsNeedUpdate; - this.lineDistancesNeedUpdate = source.lineDistancesNeedUpdate; - this.groupsNeedUpdate = source.groupsNeedUpdate; - - return this; - - }, - - dispose: function () { - - this.dispatchEvent( { type: 'dispose' } ); - - } - - } ); - - /** - * @author supereggbert / http://www.paulbrunt.co.uk/ - * @author philogb / http://blog.thejit.org/ - * @author mikael emtinger / http://gomo.se/ - * @author egraether / http://egraether.com/ - * @author WestLangley / http://github.com/WestLangley - */ - - function Vector4( x, y, z, w ) { - - this.x = x || 0; - this.y = y || 0; - this.z = z || 0; - this.w = ( w !== undefined ) ? w : 1; - - } - - Object.assign( Vector4.prototype, { - - isVector4: true, - - set: function ( x, y, z, w ) { - - this.x = x; - this.y = y; - this.z = z; - this.w = w; - - return this; - - }, - - setScalar: function ( scalar ) { - - this.x = scalar; - this.y = scalar; - this.z = scalar; - this.w = scalar; - - return this; - - }, - - setX: function ( x ) { - - this.x = x; - - return this; - - }, - - setY: function ( y ) { - - this.y = y; - - return this; - - }, - - setZ: function ( z ) { - - this.z = z; - - return this; - - }, - - setW: function ( w ) { - - this.w = w; - - return this; - - }, - - setComponent: function ( index, value ) { - - switch ( index ) { - - case 0: this.x = value; break; - case 1: this.y = value; break; - case 2: this.z = value; break; - case 3: this.w = value; break; - default: throw new Error( 'index is out of range: ' + index ); - - } - - return this; - - }, - - getComponent: function ( index ) { - - switch ( index ) { - - case 0: return this.x; - case 1: return this.y; - case 2: return this.z; - case 3: return this.w; - default: throw new Error( 'index is out of range: ' + index ); - - } - - }, - - clone: function () { - - return new this.constructor( this.x, this.y, this.z, this.w ); - - }, - - copy: function ( v ) { - - this.x = v.x; - this.y = v.y; - this.z = v.z; - this.w = ( v.w !== undefined ) ? v.w : 1; - - return this; - - }, - - add: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); - return this.addVectors( v, w ); - - } - - this.x += v.x; - this.y += v.y; - this.z += v.z; - this.w += v.w; - - return this; - - }, - - addScalar: function ( s ) { - - this.x += s; - this.y += s; - this.z += s; - this.w += s; - - return this; - - }, - - addVectors: function ( a, b ) { - - this.x = a.x + b.x; - this.y = a.y + b.y; - this.z = a.z + b.z; - this.w = a.w + b.w; - - return this; - - }, - - addScaledVector: function ( v, s ) { - - this.x += v.x * s; - this.y += v.y * s; - this.z += v.z * s; - this.w += v.w * s; - - return this; - - }, - - sub: function ( v, w ) { - - if ( w !== undefined ) { - - console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); - return this.subVectors( v, w ); - - } - - this.x -= v.x; - this.y -= v.y; - this.z -= v.z; - this.w -= v.w; - - return this; - - }, - - subScalar: function ( s ) { - - this.x -= s; - this.y -= s; - this.z -= s; - this.w -= s; - - return this; - - }, - - subVectors: function ( a, b ) { - - this.x = a.x - b.x; - this.y = a.y - b.y; - this.z = a.z - b.z; - this.w = a.w - b.w; - - return this; - - }, - - multiplyScalar: function ( scalar ) { - - this.x *= scalar; - this.y *= scalar; - this.z *= scalar; - this.w *= scalar; - - return this; - - }, - - applyMatrix4: function ( m ) { - - var x = this.x, y = this.y, z = this.z, w = this.w; - var e = m.elements; - - this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w; - this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w; - this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w; - this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w; - - return this; - - }, - - divideScalar: function ( scalar ) { - - return this.multiplyScalar( 1 / scalar ); - - }, - - setAxisAngleFromQuaternion: function ( q ) { - - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm - - // q is assumed to be normalized - - this.w = 2 * Math.acos( q.w ); - - var s = Math.sqrt( 1 - q.w * q.w ); - - if ( s < 0.0001 ) { - - this.x = 1; - this.y = 0; - this.z = 0; - - } else { - - this.x = q.x / s; - this.y = q.y / s; - this.z = q.z / s; - - } - - return this; - - }, - - setAxisAngleFromRotationMatrix: function ( m ) { - - // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm - - // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - - var angle, x, y, z, // variables for result - epsilon = 0.01, // margin to allow for rounding errors - epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees - - te = m.elements, - - m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], - m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], - m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ]; - - if ( ( Math.abs( m12 - m21 ) < epsilon ) && - ( Math.abs( m13 - m31 ) < epsilon ) && - ( Math.abs( m23 - m32 ) < epsilon ) ) { - - // singularity found - // first check for identity matrix which must have +1 for all terms - // in leading diagonal and zero in other terms - - if ( ( Math.abs( m12 + m21 ) < epsilon2 ) && - ( Math.abs( m13 + m31 ) < epsilon2 ) && - ( Math.abs( m23 + m32 ) < epsilon2 ) && - ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) { - - // this singularity is identity matrix so angle = 0 - - this.set( 1, 0, 0, 0 ); - - return this; // zero angle, arbitrary axis - - } - - // otherwise this singularity is angle = 180 - - angle = Math.PI; - - var xx = ( m11 + 1 ) / 2; - var yy = ( m22 + 1 ) / 2; - var zz = ( m33 + 1 ) / 2; - var xy = ( m12 + m21 ) / 4; - var xz = ( m13 + m31 ) / 4; - var yz = ( m23 + m32 ) / 4; - - if ( ( xx > yy ) && ( xx > zz ) ) { - - // m11 is the largest diagonal term - - if ( xx < epsilon ) { - - x = 0; - y = 0.707106781; - z = 0.707106781; - - } else { - - x = Math.sqrt( xx ); - y = xy / x; - z = xz / x; - - } - - } else if ( yy > zz ) { - - // m22 is the largest diagonal term - - if ( yy < epsilon ) { - - x = 0.707106781; - y = 0; - z = 0.707106781; - - } else { - - y = Math.sqrt( yy ); - x = xy / y; - z = yz / y; - - } - - } else { - - // m33 is the largest diagonal term so base result on this - - if ( zz < epsilon ) { - - x = 0.707106781; - y = 0.707106781; - z = 0; - - } else { - - z = Math.sqrt( zz ); - x = xz / z; - y = yz / z; - - } - - } - - this.set( x, y, z, angle ); - - return this; // return 180 deg rotation - - } - - // as we have reached here there are no singularities so we can handle normally - - var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) + - ( m13 - m31 ) * ( m13 - m31 ) + - ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize - - if ( Math.abs( s ) < 0.001 ) s = 1; - - // prevent divide by zero, should not happen if matrix is orthogonal and should be - // caught by singularity test above, but I've left it in just in case - - this.x = ( m32 - m23 ) / s; - this.y = ( m13 - m31 ) / s; - this.z = ( m21 - m12 ) / s; - this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 ); - - return this; - - }, - - min: function ( v ) { - - this.x = Math.min( this.x, v.x ); - this.y = Math.min( this.y, v.y ); - this.z = Math.min( this.z, v.z ); - this.w = Math.min( this.w, v.w ); - - return this; - - }, - - max: function ( v ) { - - this.x = Math.max( this.x, v.x ); - this.y = Math.max( this.y, v.y ); - this.z = Math.max( this.z, v.z ); - this.w = Math.max( this.w, v.w ); - - return this; - - }, - - clamp: function ( min, max ) { - - // assumes min < max, componentwise - - this.x = Math.max( min.x, Math.min( max.x, this.x ) ); - this.y = Math.max( min.y, Math.min( max.y, this.y ) ); - this.z = Math.max( min.z, Math.min( max.z, this.z ) ); - this.w = Math.max( min.w, Math.min( max.w, this.w ) ); - - return this; - - }, - - clampScalar: function () { - - var min, max; - - return function clampScalar( minVal, maxVal ) { - - if ( min === undefined ) { - - min = new Vector4(); - max = new Vector4(); - - } - - min.set( minVal, minVal, minVal, minVal ); - max.set( maxVal, maxVal, maxVal, maxVal ); - - return this.clamp( min, max ); - - }; - - }(), - - clampLength: function ( min, max ) { - - var length = this.length(); - - return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); - - }, - - floor: function () { - - this.x = Math.floor( this.x ); - this.y = Math.floor( this.y ); - this.z = Math.floor( this.z ); - this.w = Math.floor( this.w ); - - return this; - - }, - - ceil: function () { - - this.x = Math.ceil( this.x ); - this.y = Math.ceil( this.y ); - this.z = Math.ceil( this.z ); - this.w = Math.ceil( this.w ); - - return this; - - }, - - round: function () { - - this.x = Math.round( this.x ); - this.y = Math.round( this.y ); - this.z = Math.round( this.z ); - this.w = Math.round( this.w ); - - return this; - - }, - - roundToZero: function () { - - this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x ); - this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y ); - this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z ); - this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w ); - - return this; - - }, - - negate: function () { - - this.x = - this.x; - this.y = - this.y; - this.z = - this.z; - this.w = - this.w; - - return this; - - }, - - dot: function ( v ) { - - return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; - - }, - - lengthSq: function () { - - return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; - - }, - - length: function () { - - return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); - - }, - - manhattanLength: function () { - - return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); - - }, - - normalize: function () { - - return this.divideScalar( this.length() || 1 ); - - }, - - setLength: function ( length ) { - - return this.normalize().multiplyScalar( length ); - - }, - - lerp: function ( v, alpha ) { - - this.x += ( v.x - this.x ) * alpha; - this.y += ( v.y - this.y ) * alpha; - this.z += ( v.z - this.z ) * alpha; - this.w += ( v.w - this.w ) * alpha; - - return this; - - }, - - lerpVectors: function ( v1, v2, alpha ) { - - return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 ); - - }, - - equals: function ( v ) { - - return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); - - }, - - fromArray: function ( array, offset ) { - - if ( offset === undefined ) offset = 0; - - this.x = array[ offset ]; - this.y = array[ offset + 1 ]; - this.z = array[ offset + 2 ]; - this.w = array[ offset + 3 ]; - - return this; - - }, - - toArray: function ( array, offset ) { - - if ( array === undefined ) array = []; - if ( offset === undefined ) offset = 0; - - array[ offset ] = this.x; - array[ offset + 1 ] = this.y; - array[ offset + 2 ] = this.z; - array[ offset + 3 ] = this.w; - - return array; - - }, - - fromBufferAttribute: function ( attribute, index, offset ) { - - if ( offset !== undefined ) { - - console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' ); - - } - - this.x = attribute.getX( index ); - this.y = attribute.getY( index ); - this.z = attribute.getZ( index ); - this.w = attribute.getW( index ); - - return this; - - } - - } ); - - function BufferAttribute( array, itemSize, normalized ) { - - if ( Array.isArray( array ) ) { - - throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); - - } - - this.uuid = _Math.generateUUID(); - this.name = ''; - - this.array = array; - this.itemSize = itemSize; - this.count = array !== undefined ? array.length / itemSize : 0; - this.normalized = normalized === true; - - this.dynamic = false; - this.updateRange = { offset: 0, count: - 1 }; - - this.onUploadCallback = function () {}; - - this.version = 0; - - } - - Object.defineProperty( BufferAttribute.prototype, 'needsUpdate', { - - set: function ( value ) { - - if ( value === true ) this.version ++; - - } - - } ); - - Object.assign( BufferAttribute.prototype, { - - isBufferAttribute: true, - - setArray: function ( array ) { - - if ( Array.isArray( array ) ) { - - throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); - - } - - this.count = array !== undefined ? array.length / this.itemSize : 0; - this.array = array; - - }, - - setDynamic: function ( value ) { - - this.dynamic = value; - - return this; - - }, - - copy: function ( source ) { - - this.array = new source.array.constructor( source.array ); - this.itemSize = source.itemSize; - this.count = source.count; - this.normalized = source.normalized; - - this.dynamic = source.dynamic; - - return this; - - }, - - copyAt: function ( index1, attribute, index2 ) { - - index1 *= this.itemSize; - index2 *= attribute.itemSize; - - for ( var i = 0, l = this.itemSize; i < l; i ++ ) { - - this.array[ index1 + i ] = attribute.array[ index2 + i ]; - - } - - return this; - - }, - - copyArray: function ( array ) { - - this.array.set( array ); - - return this; - - }, - - copyColorsArray: function ( colors ) { - - var array = this.array, offset = 0; - - for ( var i = 0, l = colors.length; i < l; i ++ ) { - - var color = colors[ i ]; - - if ( color === undefined ) { - - console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i ); - color = new Color(); - - } - - array[ offset ++ ] = color.r; - array[ offset ++ ] = color.g; - array[ offset ++ ] = color.b; - - } - - return this; - - }, - - copyIndicesArray: function ( indices ) { - - var array = this.array, offset = 0; - - for ( var i = 0, l = indices.length; i < l; i ++ ) { - - var index = indices[ i ]; - - array[ offset ++ ] = index.a; - array[ offset ++ ] = index.b; - array[ offset ++ ] = index.c; - - } - - return this; - - }, - - copyVector2sArray: function ( vectors ) { - - var array = this.array, offset = 0; - - for ( var i = 0, l = vectors.length; i < l; i ++ ) { - - var vector = vectors[ i ]; - - if ( vector === undefined ) { - - console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i ); - vector = new Vector2(); - - } - - array[ offset ++ ] = vector.x; - array[ offset ++ ] = vector.y; - - } - - return this; - - }, - - copyVector3sArray: function ( vectors ) { - - var array = this.array, offset = 0; - - for ( var i = 0, l = vectors.length; i < l; i ++ ) { - - var vector = vectors[ i ]; - - if ( vector === undefined ) { - - console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i ); - vector = new Vector3(); - - } - - array[ offset ++ ] = vector.x; - array[ offset ++ ] = vector.y; - array[ offset ++ ] = vector.z; - - } - - return this; - - }, - - copyVector4sArray: function ( vectors ) { - - var array = this.array, offset = 0; - - for ( var i = 0, l = vectors.length; i < l; i ++ ) { - - var vector = vectors[ i ]; - - if ( vector === undefined ) { - - console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i ); - vector = new Vector4(); - - } - - array[ offset ++ ] = vector.x; - array[ offset ++ ] = vector.y; - array[ offset ++ ] = vector.z; - array[ offset ++ ] = vector.w; - - } - - return this; - - }, - - set: function ( value, offset ) { - - if ( offset === undefined ) offset = 0; - - this.array.set( value, offset ); - - return this; - - }, - - getX: function ( index ) { - - return this.array[ index * this.itemSize ]; - - }, - - setX: function ( index, x ) { - - this.array[ index * this.itemSize ] = x; - - return this; - - }, - - getY: function ( index ) { - - return this.array[ index * this.itemSize + 1 ]; - - }, - - setY: function ( index, y ) { - - this.array[ index * this.itemSize + 1 ] = y; - - return this; - - }, - - getZ: function ( index ) { - - return this.array[ index * this.itemSize + 2 ]; - - }, - - setZ: function ( index, z ) { - - this.array[ index * this.itemSize + 2 ] = z; - - return this; - - }, - - getW: function ( index ) { - - return this.array[ index * this.itemSize + 3 ]; - - }, - - setW: function ( index, w ) { - - this.array[ index * this.itemSize + 3 ] = w; - - return this; - - }, - - setXY: function ( index, x, y ) { - - index *= this.itemSize; - - this.array[ index + 0 ] = x; - this.array[ index + 1 ] = y; - - return this; - - }, - - setXYZ: function ( index, x, y, z ) { - - index *= this.itemSize; - - this.array[ index + 0 ] = x; - this.array[ index + 1 ] = y; - this.array[ index + 2 ] = z; - - return this; - - }, - - setXYZW: function ( index, x, y, z, w ) { - - index *= this.itemSize; - - this.array[ index + 0 ] = x; - this.array[ index + 1 ] = y; - this.array[ index + 2 ] = z; - this.array[ index + 3 ] = w; - - return this; - - }, - - onUpload: function ( callback ) { - - this.onUploadCallback = callback; - - return this; - - }, - - clone: function () { - - return new this.constructor( this.array, this.itemSize ).copy( this ); - - } - - } ); - - // - - function Uint16BufferAttribute( array, itemSize, normalized ) { - - BufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized ); - - } - - Uint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); - Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute; - - - function Uint32BufferAttribute( array, itemSize, normalized ) { - - BufferAttribute.call( this, new Uint32Array( array ), itemSize, normalized ); - - } - - Uint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); - Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute; - - - function Float32BufferAttribute( array, itemSize, normalized ) { - - BufferAttribute.call( this, new Float32Array( array ), itemSize, normalized ); - - } - - Float32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); - Float32BufferAttribute.prototype.constructor = Float32BufferAttribute; - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function DirectGeometry() { - - this.indices = []; - this.vertices = []; - this.normals = []; - this.colors = []; - this.uvs = []; - this.uvs2 = []; - - this.groups = []; - - this.morphTargets = {}; - - this.skinWeights = []; - this.skinIndices = []; - - // this.lineDistances = []; - - this.boundingBox = null; - this.boundingSphere = null; - - // update flags - - this.verticesNeedUpdate = false; - this.normalsNeedUpdate = false; - this.colorsNeedUpdate = false; - this.uvsNeedUpdate = false; - this.groupsNeedUpdate = false; - - } - - Object.assign( DirectGeometry.prototype, { - - computeGroups: function ( geometry ) { - - var group; - var groups = []; - var materialIndex = undefined; - - var faces = geometry.faces; - - for ( var i = 0; i < faces.length; i ++ ) { - - var face = faces[ i ]; - - // materials - - if ( face.materialIndex !== materialIndex ) { - - materialIndex = face.materialIndex; - - if ( group !== undefined ) { - - group.count = ( i * 3 ) - group.start; - groups.push( group ); - - } - - group = { - start: i * 3, - materialIndex: materialIndex - }; - - } - - } - - if ( group !== undefined ) { - - group.count = ( i * 3 ) - group.start; - groups.push( group ); - - } - - this.groups = groups; - - }, - - fromGeometry: function ( geometry ) { - - var faces = geometry.faces; - var vertices = geometry.vertices; - var faceVertexUvs = geometry.faceVertexUvs; - - var hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0; - var hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0; - - // morphs - - var morphTargets = geometry.morphTargets; - var morphTargetsLength = morphTargets.length; - - var morphTargetsPosition; - - if ( morphTargetsLength > 0 ) { - - morphTargetsPosition = []; - - for ( var i = 0; i < morphTargetsLength; i ++ ) { - - morphTargetsPosition[ i ] = []; - - } - - this.morphTargets.position = morphTargetsPosition; - - } - - var morphNormals = geometry.morphNormals; - var morphNormalsLength = morphNormals.length; - - var morphTargetsNormal; - - if ( morphNormalsLength > 0 ) { - - morphTargetsNormal = []; - - for ( var i = 0; i < morphNormalsLength; i ++ ) { - - morphTargetsNormal[ i ] = []; - - } - - this.morphTargets.normal = morphTargetsNormal; - - } - - // skins - - var skinIndices = geometry.skinIndices; - var skinWeights = geometry.skinWeights; - - var hasSkinIndices = skinIndices.length === vertices.length; - var hasSkinWeights = skinWeights.length === vertices.length; - - // - - for ( var i = 0; i < faces.length; i ++ ) { - - var face = faces[ i ]; - - this.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] ); - - var vertexNormals = face.vertexNormals; - - if ( vertexNormals.length === 3 ) { - - this.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] ); - - } else { - - var normal = face.normal; - - this.normals.push( normal, normal, normal ); - - } - - var vertexColors = face.vertexColors; - - if ( vertexColors.length === 3 ) { - - this.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] ); - - } else { - - var color = face.color; - - this.colors.push( color, color, color ); - - } - - if ( hasFaceVertexUv === true ) { - - var vertexUvs = faceVertexUvs[ 0 ][ i ]; - - if ( vertexUvs !== undefined ) { - - this.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] ); - - } else { - - console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i ); - - this.uvs.push( new Vector2(), new Vector2(), new Vector2() ); - - } - - } - - if ( hasFaceVertexUv2 === true ) { - - var vertexUvs = faceVertexUvs[ 1 ][ i ]; - - if ( vertexUvs !== undefined ) { - - this.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] ); - - } else { - - console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i ); - - this.uvs2.push( new Vector2(), new Vector2(), new Vector2() ); - - } - - } - - // morphs - - for ( var j = 0; j < morphTargetsLength; j ++ ) { - - var morphTarget = morphTargets[ j ].vertices; - - morphTargetsPosition[ j ].push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] ); - - } - - for ( var j = 0; j < morphNormalsLength; j ++ ) { - - var morphNormal = morphNormals[ j ].vertexNormals[ i ]; - - morphTargetsNormal[ j ].push( morphNormal.a, morphNormal.b, morphNormal.c ); - - } - - // skins - - if ( hasSkinIndices ) { - - this.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] ); - - } - - if ( hasSkinWeights ) { - - this.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] ); - - } - - } - - this.computeGroups( geometry ); - - this.verticesNeedUpdate = geometry.verticesNeedUpdate; - this.normalsNeedUpdate = geometry.normalsNeedUpdate; - this.colorsNeedUpdate = geometry.colorsNeedUpdate; - this.uvsNeedUpdate = geometry.uvsNeedUpdate; - this.groupsNeedUpdate = geometry.groupsNeedUpdate; - - return this; - - } - - } ); - - var bufferGeometryId = 1; // BufferGeometry uses odd numbers as Id - - function BufferGeometry() { - - Object.defineProperty( this, 'id', { value: bufferGeometryId += 2 } ); - - this.uuid = _Math.generateUUID(); - - this.name = ''; - this.type = 'BufferGeometry'; - - this.index = null; - this.attributes = {}; - - this.morphAttributes = {}; - - this.groups = []; - - this.boundingBox = null; - this.boundingSphere = null; - - this.drawRange = { start: 0, count: Infinity }; - - } - - Object.assign( BufferGeometry.prototype, EventDispatcher.prototype, { - - isBufferGeometry: true, - - getIndex: function () { - - return this.index; - - }, - - setIndex: function ( index ) { - - if ( Array.isArray( index ) ) { - - this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 ); - - } else { - - this.index = index; - - } - - }, - - addAttribute: function ( name, attribute ) { - - if ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) { - - console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' ); - - this.addAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) ); - - return; - - } - - if ( name === 'index' ) { - - console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' ); - this.setIndex( attribute ); - - return; - - } - - this.attributes[ name ] = attribute; - - return this; - - }, - - getAttribute: function ( name ) { - - return this.attributes[ name ]; - - }, - - removeAttribute: function ( name ) { - - delete this.attributes[ name ]; - - return this; - - }, - - addGroup: function ( start, count, materialIndex ) { - - this.groups.push( { - - start: start, - count: count, - materialIndex: materialIndex !== undefined ? materialIndex : 0 - - } ); - - }, - - clearGroups: function () { - - this.groups = []; - - }, - - setDrawRange: function ( start, count ) { - - this.drawRange.start = start; - this.drawRange.count = count; - - }, - - applyMatrix: function ( matrix ) { - - var position = this.attributes.position; - - if ( position !== undefined ) { - - matrix.applyToBufferAttribute( position ); - position.needsUpdate = true; - - } - - var normal = this.attributes.normal; - - if ( normal !== undefined ) { - - var normalMatrix = new Matrix3().getNormalMatrix( matrix ); - - normalMatrix.applyToBufferAttribute( normal ); - normal.needsUpdate = true; - - } - - if ( this.boundingBox !== null ) { - - this.computeBoundingBox(); - - } - - if ( this.boundingSphere !== null ) { - - this.computeBoundingSphere(); - - } - - return this; - - }, - - rotateX: function () { - - // rotate geometry around world x-axis - - var m1 = new Matrix4(); - - return function rotateX( angle ) { - - m1.makeRotationX( angle ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - rotateY: function () { - - // rotate geometry around world y-axis - - var m1 = new Matrix4(); - - return function rotateY( angle ) { - - m1.makeRotationY( angle ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - rotateZ: function () { - - // rotate geometry around world z-axis - - var m1 = new Matrix4(); - - return function rotateZ( angle ) { - - m1.makeRotationZ( angle ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - translate: function () { - - // translate geometry - - var m1 = new Matrix4(); - - return function translate( x, y, z ) { - - m1.makeTranslation( x, y, z ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - scale: function () { - - // scale geometry - - var m1 = new Matrix4(); - - return function scale( x, y, z ) { - - m1.makeScale( x, y, z ); - - this.applyMatrix( m1 ); - - return this; - - }; - - }(), - - lookAt: function () { - - var obj = new Object3D(); - - return function lookAt( vector ) { - - obj.lookAt( vector ); - - obj.updateMatrix(); - - this.applyMatrix( obj.matrix ); - - }; - - }(), - - center: function () { - - this.computeBoundingBox(); - - var offset = this.boundingBox.getCenter().negate(); - - this.translate( offset.x, offset.y, offset.z ); - - return offset; - - }, - - setFromObject: function ( object ) { - - // console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this ); - - var geometry = object.geometry; - - if ( object.isPoints || object.isLine ) { - - var positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 ); - var colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 ); - - this.addAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) ); - this.addAttribute( 'color', colors.copyColorsArray( geometry.colors ) ); - - if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) { - - var lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 ); - - this.addAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) ); - - } - - if ( geometry.boundingSphere !== null ) { - - this.boundingSphere = geometry.boundingSphere.clone(); - - } - - if ( geometry.boundingBox !== null ) { - - this.boundingBox = geometry.boundingBox.clone(); - - } - - } else if ( object.isMesh ) { - - if ( geometry && geometry.isGeometry ) { - - this.fromGeometry( geometry ); - - } - - } - - return this; - - }, - - setFromPoints: function ( points ) { - - var position = []; - - for ( var i = 0, l = points.length; i < l; i ++ ) { - - var point = points[ i ]; - position.push( point.x, point.y, point.z || 0 ); - - } - - this.addAttribute( 'position', new Float32BufferAttribute( position, 3 ) ); - - return this; - - }, - - updateFromObject: function ( object ) { - - var geometry = object.geometry; - - if ( object.isMesh ) { - - var direct = geometry.__directGeometry; - - if ( geometry.elementsNeedUpdate === true ) { - - direct = undefined; - geometry.elementsNeedUpdate = false; - - } - - if ( direct === undefined ) { - - return this.fromGeometry( geometry ); - - } - - direct.verticesNeedUpdate = geometry.verticesNeedUpdate; - direct.normalsNeedUpdate = geometry.normalsNeedUpdate; - direct.colorsNeedUpdate = geometry.colorsNeedUpdate; - direct.uvsNeedUpdate = geometry.uvsNeedUpdate; - direct.groupsNeedUpdate = geometry.groupsNeedUpdate; - - geometry.verticesNeedUpdate = false; - geometry.normalsNeedUpdate = false; - geometry.colorsNeedUpdate = false; - geometry.uvsNeedUpdate = false; - geometry.groupsNeedUpdate = false; - - geometry = direct; - - } - - var attribute; - - if ( geometry.verticesNeedUpdate === true ) { - - attribute = this.attributes.position; - - if ( attribute !== undefined ) { - - attribute.copyVector3sArray( geometry.vertices ); - attribute.needsUpdate = true; - - } - - geometry.verticesNeedUpdate = false; - - } - - if ( geometry.normalsNeedUpdate === true ) { - - attribute = this.attributes.normal; - - if ( attribute !== undefined ) { - - attribute.copyVector3sArray( geometry.normals ); - attribute.needsUpdate = true; - - } - - geometry.normalsNeedUpdate = false; - - } - - if ( geometry.colorsNeedUpdate === true ) { - - attribute = this.attributes.color; - - if ( attribute !== undefined ) { - - attribute.copyColorsArray( geometry.colors ); - attribute.needsUpdate = true; - - } - - geometry.colorsNeedUpdate = false; - - } - - if ( geometry.uvsNeedUpdate ) { - - attribute = this.attributes.uv; - - if ( attribute !== undefined ) { - - attribute.copyVector2sArray( geometry.uvs ); - attribute.needsUpdate = true; - - } - - geometry.uvsNeedUpdate = false; - - } - - if ( geometry.lineDistancesNeedUpdate ) { - - attribute = this.attributes.lineDistance; - - if ( attribute !== undefined ) { - - attribute.copyArray( geometry.lineDistances ); - attribute.needsUpdate = true; - - } - - geometry.lineDistancesNeedUpdate = false; - - } - - if ( geometry.groupsNeedUpdate ) { - - geometry.computeGroups( object.geometry ); - this.groups = geometry.groups; - - geometry.groupsNeedUpdate = false; - - } - - return this; - - }, - - fromGeometry: function ( geometry ) { - - geometry.__directGeometry = new DirectGeometry().fromGeometry( geometry ); - - return this.fromDirectGeometry( geometry.__directGeometry ); - - }, - - fromDirectGeometry: function ( geometry ) { - - var positions = new Float32Array( geometry.vertices.length * 3 ); - this.addAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) ); - - if ( geometry.normals.length > 0 ) { - - var normals = new Float32Array( geometry.normals.length * 3 ); - this.addAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) ); - - } - - if ( geometry.colors.length > 0 ) { - - var colors = new Float32Array( geometry.colors.length * 3 ); - this.addAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) ); - - } - - if ( geometry.uvs.length > 0 ) { - - var uvs = new Float32Array( geometry.uvs.length * 2 ); - this.addAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) ); - - } - - if ( geometry.uvs2.length > 0 ) { - - var uvs2 = new Float32Array( geometry.uvs2.length * 2 ); - this.addAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) ); - - } - - if ( geometry.indices.length > 0 ) { - - var TypeArray = arrayMax( geometry.indices ) > 65535 ? Uint32Array : Uint16Array; - var indices = new TypeArray( geometry.indices.length * 3 ); - this.setIndex( new BufferAttribute( indices, 1 ).copyIndicesArray( geometry.indices ) ); - - } - - // groups - - this.groups = geometry.groups; - - // morphs - - for ( var name in geometry.morphTargets ) { - - var array = []; - var morphTargets = geometry.morphTargets[ name ]; - - for ( var i = 0, l = morphTargets.length; i < l; i ++ ) { - - var morphTarget = morphTargets[ i ]; - - var attribute = new Float32BufferAttribute( morphTarget.length * 3, 3 ); - - array.push( attribute.copyVector3sArray( morphTarget ) ); - - } - - this.morphAttributes[ name ] = array; - - } - - // skinning - - if ( geometry.skinIndices.length > 0 ) { - - var skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 ); - this.addAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) ); - - } - - if ( geometry.skinWeights.length > 0 ) { - - var skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 ); - this.addAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) ); - - } - - // - - if ( geometry.boundingSphere !== null ) { - - this.boundingSphere = geometry.boundingSphere.clone(); - - } - - if ( geometry.boundingBox !== null ) { - - this.boundingBox = geometry.boundingBox.clone(); - - } - - return this; - - }, - - computeBoundingBox: function () { - - if ( this.boundingBox === null ) { - - this.boundingBox = new Box3(); - - } - - var position = this.attributes.position; - - if ( position !== undefined ) { - - this.boundingBox.setFromBufferAttribute( position ); - - } else { - - this.boundingBox.makeEmpty(); - - } - - if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) { - - console.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this ); - - } - - }, - - computeBoundingSphere: function () { - - var box = new Box3(); - var vector = new Vector3(); - - return function computeBoundingSphere() { - - if ( this.boundingSphere === null ) { - - this.boundingSphere = new Sphere(); - - } - - var position = this.attributes.position; - - if ( position ) { - - var center = this.boundingSphere.center; - - box.setFromBufferAttribute( position ); - box.getCenter( center ); - - // hoping to find a boundingSphere with a radius smaller than the - // boundingSphere of the boundingBox: sqrt(3) smaller in the best case - - var maxRadiusSq = 0; - - for ( var i = 0, il = position.count; i < il; i ++ ) { - - vector.x = position.getX( i ); - vector.y = position.getY( i ); - vector.z = position.getZ( i ); - maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) ); - - } - - this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); - - if ( isNaN( this.boundingSphere.radius ) ) { - - console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this ); - - } - - } - - }; - - }(), - - computeFaceNormals: function () { - - // backwards compatibility - - }, - - computeVertexNormals: function () { - - var index = this.index; - var attributes = this.attributes; - var groups = this.groups; - - if ( attributes.position ) { - - var positions = attributes.position.array; - - if ( attributes.normal === undefined ) { - - this.addAttribute( 'normal', new BufferAttribute( new Float32Array( positions.length ), 3 ) ); - - } else { - - // reset existing normals to zero - - var array = attributes.normal.array; - - for ( var i = 0, il = array.length; i < il; i ++ ) { - - array[ i ] = 0; - - } - - } - - var normals = attributes.normal.array; - - var vA, vB, vC; - var pA = new Vector3(), pB = new Vector3(), pC = new Vector3(); - var cb = new Vector3(), ab = new Vector3(); - - // indexed elements - - if ( index ) { - - var indices = index.array; - - if ( groups.length === 0 ) { - - this.addGroup( 0, indices.length ); - - } - - for ( var j = 0, jl = groups.length; j < jl; ++ j ) { - - var group = groups[ j ]; - - var start = group.start; - var count = group.count; - - for ( var i = start, il = start + count; i < il; i += 3 ) { - - vA = indices[ i + 0 ] * 3; - vB = indices[ i + 1 ] * 3; - vC = indices[ i + 2 ] * 3; - - pA.fromArray( positions, vA ); - pB.fromArray( positions, vB ); - pC.fromArray( positions, vC ); - - cb.subVectors( pC, pB ); - ab.subVectors( pA, pB ); - cb.cross( ab ); - - normals[ vA ] += cb.x; - normals[ vA + 1 ] += cb.y; - normals[ vA + 2 ] += cb.z; - - normals[ vB ] += cb.x; - normals[ vB + 1 ] += cb.y; - normals[ vB + 2 ] += cb.z; - - normals[ vC ] += cb.x; - normals[ vC + 1 ] += cb.y; - normals[ vC + 2 ] += cb.z; - - } - - } - - } else { - - // non-indexed elements (unconnected triangle soup) - - for ( var i = 0, il = positions.length; i < il; i += 9 ) { - - pA.fromArray( positions, i ); - pB.fromArray( positions, i + 3 ); - pC.fromArray( positions, i + 6 ); - - cb.subVectors( pC, pB ); - ab.subVectors( pA, pB ); - cb.cross( ab ); - - normals[ i ] = cb.x; - normals[ i + 1 ] = cb.y; - normals[ i + 2 ] = cb.z; - - normals[ i + 3 ] = cb.x; - normals[ i + 4 ] = cb.y; - normals[ i + 5 ] = cb.z; - - normals[ i + 6 ] = cb.x; - normals[ i + 7 ] = cb.y; - normals[ i + 8 ] = cb.z; - - } - - } - - this.normalizeNormals(); - - attributes.normal.needsUpdate = true; - - } - - }, - - merge: function ( geometry, offset ) { - - if ( ! ( geometry && geometry.isBufferGeometry ) ) { - - console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry ); - return; - - } - - if ( offset === undefined ) offset = 0; - - var attributes = this.attributes; - - for ( var key in attributes ) { - - if ( geometry.attributes[ key ] === undefined ) continue; - - var attribute1 = attributes[ key ]; - var attributeArray1 = attribute1.array; - - var attribute2 = geometry.attributes[ key ]; - var attributeArray2 = attribute2.array; - - var attributeSize = attribute2.itemSize; - - for ( var i = 0, j = attributeSize * offset; i < attributeArray2.length; i ++, j ++ ) { - - attributeArray1[ j ] = attributeArray2[ i ]; - - } - - } - - return this; - - }, - - normalizeNormals: function () { - - var vector = new Vector3(); - - return function normalizeNormals() { - - var normals = this.attributes.normal; - - for ( var i = 0, il = normals.count; i < il; i ++ ) { - - vector.x = normals.getX( i ); - vector.y = normals.getY( i ); - vector.z = normals.getZ( i ); - - vector.normalize(); - - normals.setXYZ( i, vector.x, vector.y, vector.z ); - - } - - }; - - }(), - - toNonIndexed: function () { - - if ( this.index === null ) { - - console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' ); - return this; - - } - - var geometry2 = new BufferGeometry(); - - var indices = this.index.array; - var attributes = this.attributes; - - for ( var name in attributes ) { - - var attribute = attributes[ name ]; - - var array = attribute.array; - var itemSize = attribute.itemSize; - - var array2 = new array.constructor( indices.length * itemSize ); - - var index = 0, index2 = 0; - - for ( var i = 0, l = indices.length; i < l; i ++ ) { - - index = indices[ i ] * itemSize; - - for ( var j = 0; j < itemSize; j ++ ) { - - array2[ index2 ++ ] = array[ index ++ ]; - - } - - } - - geometry2.addAttribute( name, new BufferAttribute( array2, itemSize ) ); - - } - - return geometry2; - - }, - - toJSON: function () { - - var data = { - metadata: { - version: 4.5, - type: 'BufferGeometry', - generator: 'BufferGeometry.toJSON' - } - }; - - // standard BufferGeometry serialization - - data.uuid = this.uuid; - data.type = this.type; - if ( this.name !== '' ) data.name = this.name; - - if ( this.parameters !== undefined ) { - - var parameters = this.parameters; - - for ( var key in parameters ) { - - if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; - - } - - return data; - - } - - data.data = { attributes: {} }; - - var index = this.index; - - if ( index !== null ) { - - var array = Array.prototype.slice.call( index.array ); - - data.data.index = { - type: index.array.constructor.name, - array: array - }; - - } - - var attributes = this.attributes; - - for ( var key in attributes ) { - - var attribute = attributes[ key ]; - - var array = Array.prototype.slice.call( attribute.array ); - - data.data.attributes[ key ] = { - itemSize: attribute.itemSize, - type: attribute.array.constructor.name, - array: array, - normalized: attribute.normalized - }; - - } - - var groups = this.groups; - - if ( groups.length > 0 ) { - - data.data.groups = JSON.parse( JSON.stringify( groups ) ); - - } - - var boundingSphere = this.boundingSphere; - - if ( boundingSphere !== null ) { - - data.data.boundingSphere = { - center: boundingSphere.center.toArray(), - radius: boundingSphere.radius - }; - - } - - return data; - - }, - - clone: function () { - - /* - // Handle primitives - - var parameters = this.parameters; - - if ( parameters !== undefined ) { - - var values = []; - - for ( var key in parameters ) { - - values.push( parameters[ key ] ); - - } - - var geometry = Object.create( this.constructor.prototype ); - this.constructor.apply( geometry, values ); - return geometry; - - } - - return new this.constructor().copy( this ); - */ - - return new BufferGeometry().copy( this ); - - }, - - copy: function ( source ) { - - var name, i, l; - - // reset - - this.index = null; - this.attributes = {}; - this.morphAttributes = {}; - this.groups = []; - this.boundingBox = null; - this.boundingSphere = null; - - // name - - this.name = source.name; - - // index - - var index = source.index; - - if ( index !== null ) { - - this.setIndex( index.clone() ); - - } - - // attributes - - var attributes = source.attributes; - - for ( name in attributes ) { - - var attribute = attributes[ name ]; - this.addAttribute( name, attribute.clone() ); - - } - - // morph attributes - - var morphAttributes = source.morphAttributes; - - for ( name in morphAttributes ) { - - var array = []; - var morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes - - for ( i = 0, l = morphAttribute.length; i < l; i ++ ) { - - array.push( morphAttribute[ i ].clone() ); - - } - - this.morphAttributes[ name ] = array; - - } - - // groups - - var groups = source.groups; - - for ( i = 0, l = groups.length; i < l; i ++ ) { - - var group = groups[ i ]; - this.addGroup( group.start, group.count, group.materialIndex ); - - } - - // bounding box - - var boundingBox = source.boundingBox; - - if ( boundingBox !== null ) { - - this.boundingBox = boundingBox.clone(); - - } - - // bounding sphere - - var boundingSphere = source.boundingSphere; - - if ( boundingSphere !== null ) { - - this.boundingSphere = boundingSphere.clone(); - - } - - // draw range - - this.drawRange.start = source.drawRange.start; - this.drawRange.count = source.drawRange.count; - - return this; - - }, - - dispose: function () { - - this.dispatchEvent( { type: 'dispose' } ); - - } - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ - - function BoxGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) { - - Geometry.call( this ); - - this.type = 'BoxGeometry'; - - this.parameters = { - width: width, - height: height, - depth: depth, - widthSegments: widthSegments, - heightSegments: heightSegments, - depthSegments: depthSegments - }; - - this.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) ); - this.mergeVertices(); - - } - - BoxGeometry.prototype = Object.create( Geometry.prototype ); - BoxGeometry.prototype.constructor = BoxGeometry; - - // BoxBufferGeometry - - function BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) { - - BufferGeometry.call( this ); - - this.type = 'BoxBufferGeometry'; - - this.parameters = { - width: width, - height: height, - depth: depth, - widthSegments: widthSegments, - heightSegments: heightSegments, - depthSegments: depthSegments - }; - - var scope = this; - - width = width || 1; - height = height || 1; - depth = depth || 1; - - // segments - - widthSegments = Math.floor( widthSegments ) || 1; - heightSegments = Math.floor( heightSegments ) || 1; - depthSegments = Math.floor( depthSegments ) || 1; - - // buffers - - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; - - // helper variables - - var numberOfVertices = 0; - var groupStart = 0; - - // build each side of the box geometry - - buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px - buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx - buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py - buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny - buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz - buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz - - // build geometry - - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - - function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) { - - var segmentWidth = width / gridX; - var segmentHeight = height / gridY; - - var widthHalf = width / 2; - var heightHalf = height / 2; - var depthHalf = depth / 2; - - var gridX1 = gridX + 1; - var gridY1 = gridY + 1; - - var vertexCounter = 0; - var groupCount = 0; - - var ix, iy; - - var vector = new Vector3(); - - // generate vertices, normals and uvs - - for ( iy = 0; iy < gridY1; iy ++ ) { - - var y = iy * segmentHeight - heightHalf; - - for ( ix = 0; ix < gridX1; ix ++ ) { - - var x = ix * segmentWidth - widthHalf; - - // set values to correct vector component - - vector[ u ] = x * udir; - vector[ v ] = y * vdir; - vector[ w ] = depthHalf; - - // now apply vector to vertex buffer - - vertices.push( vector.x, vector.y, vector.z ); - - // set values to correct vector component - - vector[ u ] = 0; - vector[ v ] = 0; - vector[ w ] = depth > 0 ? 1 : - 1; - - // now apply vector to normal buffer - - normals.push( vector.x, vector.y, vector.z ); - - // uvs - - uvs.push( ix / gridX ); - uvs.push( 1 - ( iy / gridY ) ); - - // counters - - vertexCounter += 1; - - } - - } - - // indices - - // 1. you need three indices to draw a single face - // 2. a single segment consists of two faces - // 3. so we need to generate six (2*3) indices per segment - - for ( iy = 0; iy < gridY; iy ++ ) { - - for ( ix = 0; ix < gridX; ix ++ ) { - - var a = numberOfVertices + ix + gridX1 * iy; - var b = numberOfVertices + ix + gridX1 * ( iy + 1 ); - var c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 ); - var d = numberOfVertices + ( ix + 1 ) + gridX1 * iy; - - // faces - - indices.push( a, b, d ); - indices.push( b, c, d ); - - // increase counter - - groupCount += 6; - - } - - } - - // add a group to the geometry. this will ensure multi material support - - scope.addGroup( groupStart, groupCount, materialIndex ); - - // calculate new start value for groups - - groupStart += groupCount; - - // update total number of vertices - - numberOfVertices += vertexCounter; - - } - - } - - BoxBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - BoxBufferGeometry.prototype.constructor = BoxBufferGeometry; - - function Ray( origin, direction ) { - - this.origin = ( origin !== undefined ) ? origin : new Vector3(); - this.direction = ( direction !== undefined ) ? direction : new Vector3(); - - } - - Object.assign( Ray.prototype, { - - set: function ( origin, direction ) { - - this.origin.copy( origin ); - this.direction.copy( direction ); - - return this; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( ray ) { - - this.origin.copy( ray.origin ); - this.direction.copy( ray.direction ); - - return this; - - }, - - at: function ( t, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - return result.copy( this.direction ).multiplyScalar( t ).add( this.origin ); - - }, - - lookAt: function ( v ) { - - this.direction.copy( v ).sub( this.origin ).normalize(); - - return this; - - }, - - recast: function () { - - var v1 = new Vector3(); - - return function recast( t ) { - - this.origin.copy( this.at( t, v1 ) ); - - return this; - - }; - - }(), - - closestPointToPoint: function ( point, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - result.subVectors( point, this.origin ); - var directionDistance = result.dot( this.direction ); - - if ( directionDistance < 0 ) { - - return result.copy( this.origin ); - - } - - return result.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); - - }, - - distanceToPoint: function ( point ) { - - return Math.sqrt( this.distanceSqToPoint( point ) ); - - }, - - distanceSqToPoint: function () { - - var v1 = new Vector3(); - - return function distanceSqToPoint( point ) { - - var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction ); - - // point behind the ray - - if ( directionDistance < 0 ) { - - return this.origin.distanceToSquared( point ); - - } - - v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); - - return v1.distanceToSquared( point ); - - }; - - }(), - - distanceSqToSegment: function () { - - var segCenter = new Vector3(); - var segDir = new Vector3(); - var diff = new Vector3(); - - return function distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) { - - // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h - // It returns the min distance between the ray and the segment - // defined by v0 and v1 - // It can also set two optional targets : - // - The closest point on the ray - // - The closest point on the segment - - segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 ); - segDir.copy( v1 ).sub( v0 ).normalize(); - diff.copy( this.origin ).sub( segCenter ); - - var segExtent = v0.distanceTo( v1 ) * 0.5; - var a01 = - this.direction.dot( segDir ); - var b0 = diff.dot( this.direction ); - var b1 = - diff.dot( segDir ); - var c = diff.lengthSq(); - var det = Math.abs( 1 - a01 * a01 ); - var s0, s1, sqrDist, extDet; - - if ( det > 0 ) { - - // The ray and segment are not parallel. - - s0 = a01 * b1 - b0; - s1 = a01 * b0 - b1; - extDet = segExtent * det; - - if ( s0 >= 0 ) { - - if ( s1 >= - extDet ) { - - if ( s1 <= extDet ) { - - // region 0 - // Minimum at interior points of ray and segment. - - var invDet = 1 / det; - s0 *= invDet; - s1 *= invDet; - sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c; - - } else { - - // region 1 - - s1 = segExtent; - s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - - } - - } else { - - // region 5 - - s1 = - segExtent; - s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - - } - - } else { - - if ( s1 <= - extDet ) { - - // region 4 - - s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) ); - s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - - } else if ( s1 <= extDet ) { - - // region 3 - - s0 = 0; - s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent ); - sqrDist = s1 * ( s1 + 2 * b1 ) + c; - - } else { - - // region 2 - - s0 = Math.max( 0, - ( a01 * segExtent + b0 ) ); - s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - - } - - } - - } else { - - // Ray and segment are parallel. - - s1 = ( a01 > 0 ) ? - segExtent : segExtent; - s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); - sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; - - } - - if ( optionalPointOnRay ) { - - optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin ); - - } - - if ( optionalPointOnSegment ) { - - optionalPointOnSegment.copy( segDir ).multiplyScalar( s1 ).add( segCenter ); - - } - - return sqrDist; - - }; - - }(), - - intersectSphere: function () { - - var v1 = new Vector3(); - - return function intersectSphere( sphere, optionalTarget ) { - - v1.subVectors( sphere.center, this.origin ); - var tca = v1.dot( this.direction ); - var d2 = v1.dot( v1 ) - tca * tca; - var radius2 = sphere.radius * sphere.radius; - - if ( d2 > radius2 ) return null; - - var thc = Math.sqrt( radius2 - d2 ); - - // t0 = first intersect point - entrance on front of sphere - var t0 = tca - thc; - - // t1 = second intersect point - exit point on back of sphere - var t1 = tca + thc; - - // test to see if both t0 and t1 are behind the ray - if so, return null - if ( t0 < 0 && t1 < 0 ) return null; - - // test to see if t0 is behind the ray: - // if it is, the ray is inside the sphere, so return the second exit point scaled by t1, - // in order to always return an intersect point that is in front of the ray. - if ( t0 < 0 ) return this.at( t1, optionalTarget ); - - // else t0 is in front of the ray, so return the first collision point scaled by t0 - return this.at( t0, optionalTarget ); - - }; - - }(), - - intersectsSphere: function ( sphere ) { - - return this.distanceToPoint( sphere.center ) <= sphere.radius; - - }, - - distanceToPlane: function ( plane ) { - - var denominator = plane.normal.dot( this.direction ); - - if ( denominator === 0 ) { - - // line is coplanar, return origin - if ( plane.distanceToPoint( this.origin ) === 0 ) { - - return 0; - - } - - // Null is preferable to undefined since undefined means.... it is undefined - - return null; - - } - - var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator; - - // Return if the ray never intersects the plane - - return t >= 0 ? t : null; - - }, - - intersectPlane: function ( plane, optionalTarget ) { - - var t = this.distanceToPlane( plane ); - - if ( t === null ) { - - return null; - - } - - return this.at( t, optionalTarget ); - - }, - - intersectsPlane: function ( plane ) { - - // check if the ray lies on the plane first - - var distToPoint = plane.distanceToPoint( this.origin ); - - if ( distToPoint === 0 ) { - - return true; - - } - - var denominator = plane.normal.dot( this.direction ); - - if ( denominator * distToPoint < 0 ) { - - return true; - - } - - // ray origin is behind the plane (and is pointing behind it) - - return false; - - }, - - intersectBox: function ( box, optionalTarget ) { - - var tmin, tmax, tymin, tymax, tzmin, tzmax; - - var invdirx = 1 / this.direction.x, - invdiry = 1 / this.direction.y, - invdirz = 1 / this.direction.z; - - var origin = this.origin; - - if ( invdirx >= 0 ) { - - tmin = ( box.min.x - origin.x ) * invdirx; - tmax = ( box.max.x - origin.x ) * invdirx; - - } else { - - tmin = ( box.max.x - origin.x ) * invdirx; - tmax = ( box.min.x - origin.x ) * invdirx; - - } - - if ( invdiry >= 0 ) { - - tymin = ( box.min.y - origin.y ) * invdiry; - tymax = ( box.max.y - origin.y ) * invdiry; - - } else { - - tymin = ( box.max.y - origin.y ) * invdiry; - tymax = ( box.min.y - origin.y ) * invdiry; - - } - - if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null; - - // These lines also handle the case where tmin or tmax is NaN - // (result of 0 * Infinity). x !== x returns true if x is NaN - - if ( tymin > tmin || tmin !== tmin ) tmin = tymin; - - if ( tymax < tmax || tmax !== tmax ) tmax = tymax; - - if ( invdirz >= 0 ) { - - tzmin = ( box.min.z - origin.z ) * invdirz; - tzmax = ( box.max.z - origin.z ) * invdirz; - - } else { - - tzmin = ( box.max.z - origin.z ) * invdirz; - tzmax = ( box.min.z - origin.z ) * invdirz; - - } - - if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null; - - if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin; - - if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax; - - //return point closest to the ray (positive side) - - if ( tmax < 0 ) return null; - - return this.at( tmin >= 0 ? tmin : tmax, optionalTarget ); - - }, - - intersectsBox: ( function () { - - var v = new Vector3(); - - return function intersectsBox( box ) { - - return this.intersectBox( box, v ) !== null; - - }; - - } )(), - - intersectTriangle: function () { - - // Compute the offset origin, edges, and normal. - var diff = new Vector3(); - var edge1 = new Vector3(); - var edge2 = new Vector3(); - var normal = new Vector3(); - - return function intersectTriangle( a, b, c, backfaceCulling, optionalTarget ) { - - // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h - - edge1.subVectors( b, a ); - edge2.subVectors( c, a ); - normal.crossVectors( edge1, edge2 ); - - // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction, - // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by - // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2)) - // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q)) - // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N) - var DdN = this.direction.dot( normal ); - var sign; - - if ( DdN > 0 ) { - - if ( backfaceCulling ) return null; - sign = 1; - - } else if ( DdN < 0 ) { - - sign = - 1; - DdN = - DdN; - - } else { - - return null; - - } - - diff.subVectors( this.origin, a ); - var DdQxE2 = sign * this.direction.dot( edge2.crossVectors( diff, edge2 ) ); - - // b1 < 0, no intersection - if ( DdQxE2 < 0 ) { - - return null; - - } - - var DdE1xQ = sign * this.direction.dot( edge1.cross( diff ) ); - - // b2 < 0, no intersection - if ( DdE1xQ < 0 ) { - - return null; - - } - - // b1+b2 > 1, no intersection - if ( DdQxE2 + DdE1xQ > DdN ) { - - return null; - - } - - // Line intersects triangle, check if ray does. - var QdN = - sign * diff.dot( normal ); - - // t < 0, no intersection - if ( QdN < 0 ) { - - return null; - - } - - // Ray intersects triangle. - return this.at( QdN / DdN, optionalTarget ); - - }; - - }(), - - applyMatrix4: function ( matrix4 ) { - - this.origin.applyMatrix4( matrix4 ); - this.direction.transformDirection( matrix4 ); - - return this; - - }, - - equals: function ( ray ) { - - return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction ); - - } - - } ); - - function Line3( start, end ) { - - this.start = ( start !== undefined ) ? start : new Vector3(); - this.end = ( end !== undefined ) ? end : new Vector3(); - - } - - Object.assign( Line3.prototype, { - - set: function ( start, end ) { - - this.start.copy( start ); - this.end.copy( end ); - - return this; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( line ) { - - this.start.copy( line.start ); - this.end.copy( line.end ); - - return this; - - }, - - getCenter: function ( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - return result.addVectors( this.start, this.end ).multiplyScalar( 0.5 ); - - }, - - delta: function ( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - return result.subVectors( this.end, this.start ); - - }, - - distanceSq: function () { - - return this.start.distanceToSquared( this.end ); - - }, - - distance: function () { - - return this.start.distanceTo( this.end ); - - }, - - at: function ( t, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - return this.delta( result ).multiplyScalar( t ).add( this.start ); - - }, - - closestPointToPointParameter: function () { - - var startP = new Vector3(); - var startEnd = new Vector3(); - - return function closestPointToPointParameter( point, clampToLine ) { - - startP.subVectors( point, this.start ); - startEnd.subVectors( this.end, this.start ); - - var startEnd2 = startEnd.dot( startEnd ); - var startEnd_startP = startEnd.dot( startP ); - - var t = startEnd_startP / startEnd2; - - if ( clampToLine ) { - - t = _Math.clamp( t, 0, 1 ); - - } - - return t; - - }; - - }(), - - closestPointToPoint: function ( point, clampToLine, optionalTarget ) { - - var t = this.closestPointToPointParameter( point, clampToLine ); - - var result = optionalTarget || new Vector3(); - - return this.delta( result ).multiplyScalar( t ).add( this.start ); - - }, - - applyMatrix4: function ( matrix ) { - - this.start.applyMatrix4( matrix ); - this.end.applyMatrix4( matrix ); - - return this; - - }, - - equals: function ( line ) { - - return line.start.equals( this.start ) && line.end.equals( this.end ); - - } - - } ); - - function Plane( normal, constant ) { - - // normal is assumed to be normalized - - this.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 ); - this.constant = ( constant !== undefined ) ? constant : 0; - - } - - Object.assign( Plane.prototype, { - - set: function ( normal, constant ) { - - this.normal.copy( normal ); - this.constant = constant; - - return this; - - }, - - setComponents: function ( x, y, z, w ) { - - this.normal.set( x, y, z ); - this.constant = w; - - return this; - - }, - - setFromNormalAndCoplanarPoint: function ( normal, point ) { - - this.normal.copy( normal ); - this.constant = - point.dot( this.normal ); - - return this; - - }, - - setFromCoplanarPoints: function () { - - var v1 = new Vector3(); - var v2 = new Vector3(); - - return function setFromCoplanarPoints( a, b, c ) { - - var normal = v1.subVectors( c, b ).cross( v2.subVectors( a, b ) ).normalize(); - - // Q: should an error be thrown if normal is zero (e.g. degenerate plane)? - - this.setFromNormalAndCoplanarPoint( normal, a ); - - return this; - - }; - - }(), - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( plane ) { - - this.normal.copy( plane.normal ); - this.constant = plane.constant; - - return this; - - }, - - normalize: function () { - - // Note: will lead to a divide by zero if the plane is invalid. - - var inverseNormalLength = 1.0 / this.normal.length(); - this.normal.multiplyScalar( inverseNormalLength ); - this.constant *= inverseNormalLength; - - return this; - - }, - - negate: function () { - - this.constant *= - 1; - this.normal.negate(); - - return this; - - }, - - distanceToPoint: function ( point ) { - - return this.normal.dot( point ) + this.constant; - - }, - - distanceToSphere: function ( sphere ) { - - return this.distanceToPoint( sphere.center ) - sphere.radius; - - }, - - projectPoint: function ( point, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - return result.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point ); - - }, - - intersectLine: function () { - - var v1 = new Vector3(); - - return function intersectLine( line, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - var direction = line.delta( v1 ); - - var denominator = this.normal.dot( direction ); - - if ( denominator === 0 ) { - - // line is coplanar, return origin - if ( this.distanceToPoint( line.start ) === 0 ) { - - return result.copy( line.start ); - - } - - // Unsure if this is the correct method to handle this case. - return undefined; - - } - - var t = - ( line.start.dot( this.normal ) + this.constant ) / denominator; - - if ( t < 0 || t > 1 ) { - - return undefined; - - } - - return result.copy( direction ).multiplyScalar( t ).add( line.start ); - - }; - - }(), - - intersectsLine: function ( line ) { - - // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it. - - var startSign = this.distanceToPoint( line.start ); - var endSign = this.distanceToPoint( line.end ); - - return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 ); - - }, - - intersectsBox: function ( box ) { - - return box.intersectsPlane( this ); - - }, - - intersectsSphere: function ( sphere ) { - - return sphere.intersectsPlane( this ); - - }, - - coplanarPoint: function ( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - return result.copy( this.normal ).multiplyScalar( - this.constant ); - - }, - - applyMatrix4: function () { - - var v1 = new Vector3(); - var m1 = new Matrix3(); - - return function applyMatrix4( matrix, optionalNormalMatrix ) { - - var normalMatrix = optionalNormalMatrix || m1.getNormalMatrix( matrix ); - - var referencePoint = this.coplanarPoint( v1 ).applyMatrix4( matrix ); - - var normal = this.normal.applyMatrix3( normalMatrix ).normalize(); - - this.constant = - referencePoint.dot( normal ); - - return this; - - }; - - }(), - - translate: function ( offset ) { - - this.constant -= offset.dot( this.normal ); - - return this; - - }, - - equals: function ( plane ) { - - return plane.normal.equals( this.normal ) && ( plane.constant === this.constant ); - - } - - } ); - - function Triangle( a, b, c ) { - - this.a = ( a !== undefined ) ? a : new Vector3(); - this.b = ( b !== undefined ) ? b : new Vector3(); - this.c = ( c !== undefined ) ? c : new Vector3(); - - } - - Object.assign( Triangle, { - - normal: function () { - - var v0 = new Vector3(); - - return function normal( a, b, c, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - result.subVectors( c, b ); - v0.subVectors( a, b ); - result.cross( v0 ); - - var resultLengthSq = result.lengthSq(); - if ( resultLengthSq > 0 ) { - - return result.multiplyScalar( 1 / Math.sqrt( resultLengthSq ) ); - - } - - return result.set( 0, 0, 0 ); - - }; - - }(), - - // static/instance method to calculate barycentric coordinates - // based on: http://www.blackpawn.com/texts/pointinpoly/default.html - barycoordFromPoint: function () { - - var v0 = new Vector3(); - var v1 = new Vector3(); - var v2 = new Vector3(); - - return function barycoordFromPoint( point, a, b, c, optionalTarget ) { - - v0.subVectors( c, a ); - v1.subVectors( b, a ); - v2.subVectors( point, a ); - - var dot00 = v0.dot( v0 ); - var dot01 = v0.dot( v1 ); - var dot02 = v0.dot( v2 ); - var dot11 = v1.dot( v1 ); - var dot12 = v1.dot( v2 ); - - var denom = ( dot00 * dot11 - dot01 * dot01 ); - - var result = optionalTarget || new Vector3(); - - // collinear or singular triangle - if ( denom === 0 ) { - - // arbitrary location outside of triangle? - // not sure if this is the best idea, maybe should be returning undefined - return result.set( - 2, - 1, - 1 ); - - } - - var invDenom = 1 / denom; - var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; - var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; - - // barycentric coordinates must always sum to 1 - return result.set( 1 - u - v, v, u ); - - }; - - }(), - - containsPoint: function () { - - var v1 = new Vector3(); - - return function containsPoint( point, a, b, c ) { - - var result = Triangle.barycoordFromPoint( point, a, b, c, v1 ); - - return ( result.x >= 0 ) && ( result.y >= 0 ) && ( ( result.x + result.y ) <= 1 ); - - }; - - }() - - } ); - - Object.assign( Triangle.prototype, { - - set: function ( a, b, c ) { - - this.a.copy( a ); - this.b.copy( b ); - this.c.copy( c ); - - return this; - - }, - - setFromPointsAndIndices: function ( points, i0, i1, i2 ) { - - this.a.copy( points[ i0 ] ); - this.b.copy( points[ i1 ] ); - this.c.copy( points[ i2 ] ); - - return this; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( triangle ) { - - this.a.copy( triangle.a ); - this.b.copy( triangle.b ); - this.c.copy( triangle.c ); - - return this; - - }, - - area: function () { - - var v0 = new Vector3(); - var v1 = new Vector3(); - - return function area() { - - v0.subVectors( this.c, this.b ); - v1.subVectors( this.a, this.b ); - - return v0.cross( v1 ).length() * 0.5; - - }; - - }(), - - midpoint: function ( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - return result.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 ); - - }, - - normal: function ( optionalTarget ) { - - return Triangle.normal( this.a, this.b, this.c, optionalTarget ); - - }, - - plane: function ( optionalTarget ) { - - var result = optionalTarget || new Plane(); - - return result.setFromCoplanarPoints( this.a, this.b, this.c ); - - }, - - barycoordFromPoint: function ( point, optionalTarget ) { - - return Triangle.barycoordFromPoint( point, this.a, this.b, this.c, optionalTarget ); - - }, - - containsPoint: function ( point ) { - - return Triangle.containsPoint( point, this.a, this.b, this.c ); - - }, - - closestPointToPoint: function () { - - var plane = new Plane(); - var edgeList = [ new Line3(), new Line3(), new Line3() ]; - var projectedPoint = new Vector3(); - var closestPoint = new Vector3(); - - return function closestPointToPoint( point, optionalTarget ) { - - var result = optionalTarget || new Vector3(); - var minDistance = Infinity; - - // project the point onto the plane of the triangle - - plane.setFromCoplanarPoints( this.a, this.b, this.c ); - plane.projectPoint( point, projectedPoint ); - - // check if the projection lies within the triangle - - if ( this.containsPoint( projectedPoint ) === true ) { - - // if so, this is the closest point - - result.copy( projectedPoint ); - - } else { - - // if not, the point falls outside the triangle. the result is the closest point to the triangle's edges or vertices - - edgeList[ 0 ].set( this.a, this.b ); - edgeList[ 1 ].set( this.b, this.c ); - edgeList[ 2 ].set( this.c, this.a ); - - for ( var i = 0; i < edgeList.length; i ++ ) { - - edgeList[ i ].closestPointToPoint( projectedPoint, true, closestPoint ); - - var distance = projectedPoint.distanceToSquared( closestPoint ); - - if ( distance < minDistance ) { - - minDistance = distance; - - result.copy( closestPoint ); - - } - - } - - } - - return result; - - }; - - }(), - - equals: function ( triangle ) { - - return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c ); - - } - - } ); - - var materialId = 0; - - function Material() { - - Object.defineProperty( this, 'id', { value: materialId ++ } ); - - this.uuid = _Math.generateUUID(); - - this.name = ''; - this.type = 'Material'; - - this.fog = true; - this.lights = true; - - this.blending = NormalBlending; - this.side = FrontSide; - this.flatShading = false; - this.vertexColors = NoColors; // THREE.NoColors, THREE.VertexColors, THREE.FaceColors - - this.opacity = 1; - this.transparent = false; - - this.blendSrc = SrcAlphaFactor; - this.blendDst = OneMinusSrcAlphaFactor; - this.blendEquation = AddEquation; - this.blendSrcAlpha = null; - this.blendDstAlpha = null; - this.blendEquationAlpha = null; - - this.depthFunc = LessEqualDepth; - this.depthTest = true; - this.depthWrite = true; - - this.clippingPlanes = null; - this.clipIntersection = false; - this.clipShadows = false; - - this.colorWrite = true; - - this.precision = null; // override the renderer's default precision for this material - - this.polygonOffset = false; - this.polygonOffsetFactor = 0; - this.polygonOffsetUnits = 0; - - this.dithering = false; - - this.alphaTest = 0; - this.premultipliedAlpha = false; - - this.overdraw = 0; // Overdrawn pixels (typically between 0 and 1) for fixing antialiasing gaps in CanvasRenderer - - this.visible = true; - - this.userData = {}; - - this.needsUpdate = true; - - } - - Object.assign( Material.prototype, EventDispatcher.prototype, { - - isMaterial: true, - - onBeforeCompile: function () {}, - - setValues: function ( values ) { - - if ( values === undefined ) return; - - for ( var key in values ) { - - var newValue = values[ key ]; - - if ( newValue === undefined ) { - - console.warn( "THREE.Material: '" + key + "' parameter is undefined." ); - continue; - - } - - // for backward compatability if shading is set in the constructor - if ( key === 'shading' ) { - - console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' ); - this.flatShading = ( newValue === FlatShading ) ? true : false; - continue; - - } - - var currentValue = this[ key ]; - - if ( currentValue === undefined ) { - - console.warn( "THREE." + this.type + ": '" + key + "' is not a property of this material." ); - continue; - - } - - if ( currentValue && currentValue.isColor ) { - - currentValue.set( newValue ); - - } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) { - - currentValue.copy( newValue ); - - } else if ( key === 'overdraw' ) { - - // ensure overdraw is backwards-compatible with legacy boolean type - this[ key ] = Number( newValue ); - - } else { - - this[ key ] = newValue; - - } - - } - - }, - - toJSON: function ( meta ) { - - var isRoot = ( meta === undefined || typeof meta === 'string' ); - - if ( isRoot ) { - - meta = { - textures: {}, - images: {} - }; - - } - - var data = { - metadata: { - version: 4.5, - type: 'Material', - generator: 'Material.toJSON' - } - }; - - // standard Material serialization - data.uuid = this.uuid; - data.type = this.type; - - if ( this.name !== '' ) data.name = this.name; - - if ( this.color && this.color.isColor ) data.color = this.color.getHex(); - - if ( this.roughness !== undefined ) data.roughness = this.roughness; - if ( this.metalness !== undefined ) data.metalness = this.metalness; - - if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex(); - if ( this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity; - - if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex(); - if ( this.shininess !== undefined ) data.shininess = this.shininess; - if ( this.clearCoat !== undefined ) data.clearCoat = this.clearCoat; - if ( this.clearCoatRoughness !== undefined ) data.clearCoatRoughness = this.clearCoatRoughness; - - if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid; - if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid; - if ( this.lightMap && this.lightMap.isTexture ) data.lightMap = this.lightMap.toJSON( meta ).uuid; - if ( this.bumpMap && this.bumpMap.isTexture ) { - - data.bumpMap = this.bumpMap.toJSON( meta ).uuid; - data.bumpScale = this.bumpScale; - - } - if ( this.normalMap && this.normalMap.isTexture ) { - - data.normalMap = this.normalMap.toJSON( meta ).uuid; - data.normalScale = this.normalScale.toArray(); - - } - if ( this.displacementMap && this.displacementMap.isTexture ) { - - data.displacementMap = this.displacementMap.toJSON( meta ).uuid; - data.displacementScale = this.displacementScale; - data.displacementBias = this.displacementBias; - - } - if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid; - if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid; - - if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid; - if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid; - - if ( this.envMap && this.envMap.isTexture ) { - - data.envMap = this.envMap.toJSON( meta ).uuid; - data.reflectivity = this.reflectivity; // Scale behind envMap - - } - - if ( this.gradientMap && this.gradientMap.isTexture ) { - - data.gradientMap = this.gradientMap.toJSON( meta ).uuid; - - } - - if ( this.size !== undefined ) data.size = this.size; - if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation; - - if ( this.blending !== NormalBlending ) data.blending = this.blending; - if ( this.flatShading === true ) data.flatShading = this.flatShading; - if ( this.side !== FrontSide ) data.side = this.side; - if ( this.vertexColors !== NoColors ) data.vertexColors = this.vertexColors; - - if ( this.opacity < 1 ) data.opacity = this.opacity; - if ( this.transparent === true ) data.transparent = this.transparent; - - data.depthFunc = this.depthFunc; - data.depthTest = this.depthTest; - data.depthWrite = this.depthWrite; - - // rotation (SpriteMaterial) - if ( this.rotation !== 0 ) data.rotation = this.rotation; - - if ( this.linewidth !== 1 ) data.linewidth = this.linewidth; - if ( this.dashSize !== undefined ) data.dashSize = this.dashSize; - if ( this.gapSize !== undefined ) data.gapSize = this.gapSize; - if ( this.scale !== undefined ) data.scale = this.scale; - - if ( this.dithering === true ) data.dithering = true; - - if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest; - if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha; - - if ( this.wireframe === true ) data.wireframe = this.wireframe; - if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth; - if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap; - if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin; - - if ( this.morphTargets === true ) data.morphTargets = true; - if ( this.skinning === true ) data.skinning = true; - - if ( this.visible === false ) data.visible = false; - if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData; - - // TODO: Copied from Object3D.toJSON - - function extractFromCache( cache ) { - - var values = []; - - for ( var key in cache ) { - - var data = cache[ key ]; - delete data.metadata; - values.push( data ); - - } - - return values; - - } - - if ( isRoot ) { - - var textures = extractFromCache( meta.textures ); - var images = extractFromCache( meta.images ); - - if ( textures.length > 0 ) data.textures = textures; - if ( images.length > 0 ) data.images = images; - - } - - return data; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( source ) { - - this.name = source.name; - - this.fog = source.fog; - this.lights = source.lights; - - this.blending = source.blending; - this.side = source.side; - this.flatShading = source.flatShading; - this.vertexColors = source.vertexColors; - - this.opacity = source.opacity; - this.transparent = source.transparent; - - this.blendSrc = source.blendSrc; - this.blendDst = source.blendDst; - this.blendEquation = source.blendEquation; - this.blendSrcAlpha = source.blendSrcAlpha; - this.blendDstAlpha = source.blendDstAlpha; - this.blendEquationAlpha = source.blendEquationAlpha; - - this.depthFunc = source.depthFunc; - this.depthTest = source.depthTest; - this.depthWrite = source.depthWrite; - - this.colorWrite = source.colorWrite; - - this.precision = source.precision; - - this.polygonOffset = source.polygonOffset; - this.polygonOffsetFactor = source.polygonOffsetFactor; - this.polygonOffsetUnits = source.polygonOffsetUnits; - - this.dithering = source.dithering; - - this.alphaTest = source.alphaTest; - this.premultipliedAlpha = source.premultipliedAlpha; - - this.overdraw = source.overdraw; - - this.visible = source.visible; - this.userData = JSON.parse( JSON.stringify( source.userData ) ); - - this.clipShadows = source.clipShadows; - this.clipIntersection = source.clipIntersection; - - var srcPlanes = source.clippingPlanes, - dstPlanes = null; - - if ( srcPlanes !== null ) { - - var n = srcPlanes.length; - dstPlanes = new Array( n ); - - for ( var i = 0; i !== n; ++ i ) - dstPlanes[ i ] = srcPlanes[ i ].clone(); - - } - - this.clippingPlanes = dstPlanes; - - return this; - - }, - - dispose: function () { - - this.dispatchEvent( { type: 'dispose' } ); - - } - - } ); - - function MeshBasicMaterial( parameters ) { - - Material.call( this ); - - this.type = 'MeshBasicMaterial'; - - this.color = new Color( 0xffffff ); // emissive - - this.map = null; - - this.lightMap = null; - this.lightMapIntensity = 1.0; - - this.aoMap = null; - this.aoMapIntensity = 1.0; - - this.specularMap = null; - - this.alphaMap = null; - - this.envMap = null; - this.combine = MultiplyOperation; - this.reflectivity = 1; - this.refractionRatio = 0.98; - - this.wireframe = false; - this.wireframeLinewidth = 1; - this.wireframeLinecap = 'round'; - this.wireframeLinejoin = 'round'; - - this.skinning = false; - this.morphTargets = false; - - this.lights = false; - - this.setValues( parameters ); - - } - - MeshBasicMaterial.prototype = Object.create( Material.prototype ); - MeshBasicMaterial.prototype.constructor = MeshBasicMaterial; - - MeshBasicMaterial.prototype.isMeshBasicMaterial = true; - - MeshBasicMaterial.prototype.copy = function ( source ) { - - Material.prototype.copy.call( this, source ); - - this.color.copy( source.color ); - - this.map = source.map; - - this.lightMap = source.lightMap; - this.lightMapIntensity = source.lightMapIntensity; - - this.aoMap = source.aoMap; - this.aoMapIntensity = source.aoMapIntensity; - - this.specularMap = source.specularMap; - - this.alphaMap = source.alphaMap; - - this.envMap = source.envMap; - this.combine = source.combine; - this.reflectivity = source.reflectivity; - this.refractionRatio = source.refractionRatio; - - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; - this.wireframeLinecap = source.wireframeLinecap; - this.wireframeLinejoin = source.wireframeLinejoin; - - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - - return this; - - }; - - function Mesh( geometry, material ) { - - Object3D.call( this ); - - this.type = 'Mesh'; - - this.geometry = geometry !== undefined ? geometry : new BufferGeometry(); - this.material = material !== undefined ? material : new MeshBasicMaterial( { color: Math.random() * 0xffffff } ); - - this.drawMode = TrianglesDrawMode; - - this.updateMorphTargets(); - - } - - Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), { - - constructor: Mesh, - - isMesh: true, - - setDrawMode: function ( value ) { - - this.drawMode = value; - - }, - - copy: function ( source ) { - - Object3D.prototype.copy.call( this, source ); - - this.drawMode = source.drawMode; - - if ( source.morphTargetInfluences !== undefined ) { - - this.morphTargetInfluences = source.morphTargetInfluences.slice(); - - } - - if ( source.morphTargetDictionary !== undefined ) { - - this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary ); - - } - - return this; - - }, - - updateMorphTargets: function () { - - var geometry = this.geometry; - var m, ml, name; - - if ( geometry.isBufferGeometry ) { - - var morphAttributes = geometry.morphAttributes; - var keys = Object.keys( morphAttributes ); - - if ( keys.length > 0 ) { - - var morphAttribute = morphAttributes[ keys[ 0 ] ]; - - if ( morphAttribute !== undefined ) { - - this.morphTargetInfluences = []; - this.morphTargetDictionary = {}; - - for ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) { - - name = morphAttribute[ m ].name || String( m ); - - this.morphTargetInfluences.push( 0 ); - this.morphTargetDictionary[ name ] = m; - - } - - } - - } - - } else { - - var morphTargets = geometry.morphTargets; - - if ( morphTargets !== undefined && morphTargets.length > 0 ) { - - this.morphTargetInfluences = []; - this.morphTargetDictionary = {}; - - for ( m = 0, ml = morphTargets.length; m < ml; m ++ ) { - - name = morphTargets[ m ].name || String( m ); - - this.morphTargetInfluences.push( 0 ); - this.morphTargetDictionary[ name ] = m; - - } - - } - - } - - }, - - raycast: ( function () { - - var inverseMatrix = new Matrix4(); - var ray = new Ray(); - var sphere = new Sphere(); - - var vA = new Vector3(); - var vB = new Vector3(); - var vC = new Vector3(); - - var tempA = new Vector3(); - var tempB = new Vector3(); - var tempC = new Vector3(); - - var uvA = new Vector2(); - var uvB = new Vector2(); - var uvC = new Vector2(); - - var barycoord = new Vector3(); - - var intersectionPoint = new Vector3(); - var intersectionPointWorld = new Vector3(); - - function uvIntersection( point, p1, p2, p3, uv1, uv2, uv3 ) { - - Triangle.barycoordFromPoint( point, p1, p2, p3, barycoord ); - - uv1.multiplyScalar( barycoord.x ); - uv2.multiplyScalar( barycoord.y ); - uv3.multiplyScalar( barycoord.z ); - - uv1.add( uv2 ).add( uv3 ); - - return uv1.clone(); - - } - - function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) { - - var intersect; - - if ( material.side === BackSide ) { - - intersect = ray.intersectTriangle( pC, pB, pA, true, point ); - - } else { - - intersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point ); - - } - - if ( intersect === null ) return null; - - intersectionPointWorld.copy( point ); - intersectionPointWorld.applyMatrix4( object.matrixWorld ); - - var distance = raycaster.ray.origin.distanceTo( intersectionPointWorld ); - - if ( distance < raycaster.near || distance > raycaster.far ) return null; - - return { - distance: distance, - point: intersectionPointWorld.clone(), - object: object - }; - - } - - function checkBufferGeometryIntersection( object, raycaster, ray, position, uv, a, b, c ) { - - vA.fromBufferAttribute( position, a ); - vB.fromBufferAttribute( position, b ); - vC.fromBufferAttribute( position, c ); - - var intersection = checkIntersection( object, object.material, raycaster, ray, vA, vB, vC, intersectionPoint ); - - if ( intersection ) { - - if ( uv ) { - - uvA.fromBufferAttribute( uv, a ); - uvB.fromBufferAttribute( uv, b ); - uvC.fromBufferAttribute( uv, c ); - - intersection.uv = uvIntersection( intersectionPoint, vA, vB, vC, uvA, uvB, uvC ); - - } - - intersection.face = new Face3( a, b, c, Triangle.normal( vA, vB, vC ) ); - intersection.faceIndex = a; - - } - - return intersection; - - } - - return function raycast( raycaster, intersects ) { - - var geometry = this.geometry; - var material = this.material; - var matrixWorld = this.matrixWorld; - - if ( material === undefined ) return; - - // Checking boundingSphere distance to ray - - if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); - - sphere.copy( geometry.boundingSphere ); - sphere.applyMatrix4( matrixWorld ); - - if ( raycaster.ray.intersectsSphere( sphere ) === false ) return; - - // - - inverseMatrix.getInverse( matrixWorld ); - ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix ); - - // Check boundingBox before continuing - - if ( geometry.boundingBox !== null ) { - - if ( ray.intersectsBox( geometry.boundingBox ) === false ) return; - - } - - var intersection; - - if ( geometry.isBufferGeometry ) { - - var a, b, c; - var index = geometry.index; - var position = geometry.attributes.position; - var uv = geometry.attributes.uv; - var i, l; - - if ( index !== null ) { - - // indexed buffer geometry - - for ( i = 0, l = index.count; i < l; i += 3 ) { - - a = index.getX( i ); - b = index.getX( i + 1 ); - c = index.getX( i + 2 ); - - intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c ); - - if ( intersection ) { - - intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indices buffer semantics - intersects.push( intersection ); - - } - - } - - } else if ( position !== undefined ) { - - // non-indexed buffer geometry - - for ( i = 0, l = position.count; i < l; i += 3 ) { - - a = i; - b = i + 1; - c = i + 2; - - intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c ); - - if ( intersection ) { - - intersection.index = a; // triangle number in positions buffer semantics - intersects.push( intersection ); - - } - - } - - } - - } else if ( geometry.isGeometry ) { - - var fvA, fvB, fvC; - var isMultiMaterial = Array.isArray( material ); - - var vertices = geometry.vertices; - var faces = geometry.faces; - var uvs; - - var faceVertexUvs = geometry.faceVertexUvs[ 0 ]; - if ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs; - - for ( var f = 0, fl = faces.length; f < fl; f ++ ) { - - var face = faces[ f ]; - var faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material; - - if ( faceMaterial === undefined ) continue; - - fvA = vertices[ face.a ]; - fvB = vertices[ face.b ]; - fvC = vertices[ face.c ]; - - if ( faceMaterial.morphTargets === true ) { - - var morphTargets = geometry.morphTargets; - var morphInfluences = this.morphTargetInfluences; - - vA.set( 0, 0, 0 ); - vB.set( 0, 0, 0 ); - vC.set( 0, 0, 0 ); - - for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) { - - var influence = morphInfluences[ t ]; - - if ( influence === 0 ) continue; - - var targets = morphTargets[ t ].vertices; - - vA.addScaledVector( tempA.subVectors( targets[ face.a ], fvA ), influence ); - vB.addScaledVector( tempB.subVectors( targets[ face.b ], fvB ), influence ); - vC.addScaledVector( tempC.subVectors( targets[ face.c ], fvC ), influence ); - - } - - vA.add( fvA ); - vB.add( fvB ); - vC.add( fvC ); - - fvA = vA; - fvB = vB; - fvC = vC; - - } - - intersection = checkIntersection( this, faceMaterial, raycaster, ray, fvA, fvB, fvC, intersectionPoint ); - - if ( intersection ) { - - if ( uvs && uvs[ f ] ) { - - var uvs_f = uvs[ f ]; - uvA.copy( uvs_f[ 0 ] ); - uvB.copy( uvs_f[ 1 ] ); - uvC.copy( uvs_f[ 2 ] ); - - intersection.uv = uvIntersection( intersectionPoint, fvA, fvB, fvC, uvA, uvB, uvC ); - - } - - intersection.face = face; - intersection.faceIndex = f; - intersects.push( intersection ); - - } - - } - - } - - }; - - }() ), - - clone: function () { - - return new this.constructor( this.geometry, this.material ).copy( this ); - - } - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author Anonymous - */ - /* global QUnit */ - - QUnit.module( 'Animation', () => { - - QUnit.module.todo( 'PropertyBinding', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // STATIC STUFF - QUnit.test( "Composite", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "create", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( 'sanitizeNodeName', ( assert ) => { - - assert.equal( - PropertyBinding.sanitizeNodeName( 'valid-name-123_' ), - 'valid-name-123_', - 'Leaves valid name intact.' - ); - - assert.equal( - PropertyBinding.sanitizeNodeName( 'space separated name 123_ -' ), - 'space_separated_name_123__-', - 'Replaces spaces with underscores.' - ); - - assert.equal( - PropertyBinding.sanitizeNodeName( '"invalid" name %123%_' ), - 'invalid_name_123_', - 'Strips invalid characters.' - ); - - } ); - - QUnit.test( 'parseTrackName', ( assert ) => { - - var paths = [ - - [ - '.property', - { - nodeName: undefined, - objectName: undefined, - objectIndex: undefined, - propertyName: 'property', - propertyIndex: undefined - } - ], - - [ - 'nodeName.property', - { - nodeName: 'nodeName', - objectName: undefined, - objectIndex: undefined, - propertyName: 'property', - propertyIndex: undefined - } - ], - - [ - 'a.property', - { - nodeName: 'a', - objectName: undefined, - objectIndex: undefined, - propertyName: 'property', - propertyIndex: undefined - } - ], - - [ - 'no.de.Name.property', - { - nodeName: 'no.de.Name', - objectName: undefined, - objectIndex: undefined, - propertyName: 'property', - propertyIndex: undefined - } - ], - - [ - 'no.d-e.Name.property', - { - nodeName: 'no.d-e.Name', - objectName: undefined, - objectIndex: undefined, - propertyName: 'property', - propertyIndex: undefined - } - ], - - [ - 'nodeName.property[accessor]', - { - nodeName: 'nodeName', - objectName: undefined, - objectIndex: undefined, - propertyName: 'property', - propertyIndex: 'accessor' - } - ], - - [ - 'nodeName.material.property[accessor]', - { - nodeName: 'nodeName', - objectName: 'material', - objectIndex: undefined, - propertyName: 'property', - propertyIndex: 'accessor' - } - ], - - [ - 'no.de.Name.material.property', - { - nodeName: 'no.de.Name', - objectName: 'material', - objectIndex: undefined, - propertyName: 'property', - propertyIndex: undefined - } - ], - - [ - 'no.de.Name.material[materialIndex].property', - { - nodeName: 'no.de.Name', - objectName: 'material', - objectIndex: 'materialIndex', - propertyName: 'property', - propertyIndex: undefined - } - ], - - [ - 'uuid.property[accessor]', - { - nodeName: 'uuid', - objectName: undefined, - objectIndex: undefined, - propertyName: 'property', - propertyIndex: 'accessor' - } - ], - - [ - 'uuid.objectName[objectIndex].propertyName[propertyIndex]', - { - nodeName: 'uuid', - objectName: 'objectName', - objectIndex: 'objectIndex', - propertyName: 'propertyName', - propertyIndex: 'propertyIndex' - } - ], - - [ - 'parentName/nodeName.property', - { - // directoryName is currently unused. - nodeName: 'nodeName', - objectName: undefined, - objectIndex: undefined, - propertyName: 'property', - propertyIndex: undefined - } - ], - - [ - 'parentName/no.de.Name.property', - { - // directoryName is currently unused. - nodeName: 'no.de.Name', - objectName: undefined, - objectIndex: undefined, - propertyName: 'property', - propertyIndex: undefined - } - ], - - [ - 'parentName/parentName/nodeName.property[index]', - { - // directoryName is currently unused. - nodeName: 'nodeName', - objectName: undefined, - objectIndex: undefined, - propertyName: 'property', - propertyIndex: 'index' - } - ], - - [ - '.bone[Armature.DEF_cog].position', - { - nodeName: undefined, - objectName: 'bone', - objectIndex: 'Armature.DEF_cog', - propertyName: 'position', - propertyIndex: undefined - } - ], - - [ - 'scene:helium_balloon_model:helium_balloon_model.position', - { - nodeName: 'helium_balloon_model', - objectName: undefined, - objectIndex: undefined, - propertyName: 'position', - propertyIndex: undefined - } - ] - ]; - - paths.forEach( function ( path ) { - - assert.smartEqual( - PropertyBinding.parseTrackName( path[ 0 ] ), - path[ 1 ], - 'Parses track name: ' + path[ 0 ] - ); - - } ); - - } ); - - QUnit.test( "findNode", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "BindingType", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "Versioning", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "GetterByBindingType", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "SetterByBindingTypeAndVersioning", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getValue", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( 'setValue', ( assert ) => { - - var paths = [ - '.material.opacity', - '.material[opacity]' - ]; - - paths.forEach( function ( path ) { - - var originalValue = 0; - var expectedValue = 1; - - var geometry = new BoxGeometry(); - var material = new MeshBasicMaterial(); - material.opacity = originalValue; - var mesh = new Mesh( geometry, material ); - - var binding = new PropertyBinding( mesh, path, null ); - binding.bind(); - - assert.equal( - material.opacity, - originalValue, - 'Sets property of material with "' + path + '" (pre-setValue)' - ); - - binding.setValue( [ expectedValue ], 0 ); - assert.equal( - material.opacity, - expectedValue, - 'Sets property of material with "' + path + '" (post-setValue)' - ); - - } ); - - } ); - - QUnit.test( "bind", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "unbind", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( "_getValue_unavailable", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_setValue_unavailable", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Animation', () => { - - QUnit.module.todo( 'PropertyMixer', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PRIVATE STUFF - QUnit.test( "_select", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_slerp", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "_lerp", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "accumulate", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "apply", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "saveOriginalState", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "restoreOriginalState", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Animation', () => { - - QUnit.module( 'Tracks', () => { - - QUnit.module.todo( 'BooleanKeyframeTrack', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Animation', () => { - - QUnit.module( 'Tracks', () => { - - QUnit.module.todo( 'ColorKeyframeTrack', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Animation', () => { - - QUnit.module( 'Tracks', () => { - - QUnit.module.todo( 'NumberKeyframeTrack', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Animation', () => { - - QUnit.module( 'Tracks', () => { - - QUnit.module.todo( 'QuaternionKeyframeTrack', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Animation', () => { - - QUnit.module( 'Tracks', () => { - - QUnit.module.todo( 'StringKeyframeTrack', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Animation', () => { - - QUnit.module( 'Tracks', () => { - - QUnit.module.todo( 'VectorKeyframeTrack', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - * @author Reece Aaron Lecrivain / http://reecenotes.com/ - */ - - function Audio( listener ) { - - Object3D.call( this ); - - this.type = 'Audio'; - - this.context = listener.context; - - this.gain = this.context.createGain(); - this.gain.connect( listener.getInput() ); - - this.autoplay = false; - - this.buffer = null; - this.loop = false; - this.startTime = 0; - this.offset = 0; - this.playbackRate = 1; - this.isPlaying = false; - this.hasPlaybackControl = true; - this.sourceType = 'empty'; - - this.filters = []; - - } - - Audio.prototype = Object.assign( Object.create( Object3D.prototype ), { - - constructor: Audio, - - getOutput: function () { - - return this.gain; - - }, - - setNodeSource: function ( audioNode ) { - - this.hasPlaybackControl = false; - this.sourceType = 'audioNode'; - this.source = audioNode; - this.connect(); - - return this; - - }, - - setBuffer: function ( audioBuffer ) { - - this.buffer = audioBuffer; - this.sourceType = 'buffer'; - - if ( this.autoplay ) this.play(); - - return this; - - }, - - play: function () { - - if ( this.isPlaying === true ) { - - console.warn( 'THREE.Audio: Audio is already playing.' ); - return; - - } - - if ( this.hasPlaybackControl === false ) { - - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return; - - } - - var source = this.context.createBufferSource(); - - source.buffer = this.buffer; - source.loop = this.loop; - source.onended = this.onEnded.bind( this ); - source.playbackRate.setValueAtTime( this.playbackRate, this.startTime ); - this.startTime = this.context.currentTime; - source.start( this.startTime, this.offset ); - - this.isPlaying = true; - - this.source = source; - - return this.connect(); - - }, - - pause: function () { - - if ( this.hasPlaybackControl === false ) { - - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return; - - } - - if ( this.isPlaying === true ) { - - this.source.stop(); - this.offset += ( this.context.currentTime - this.startTime ) * this.playbackRate; - this.isPlaying = false; - - } - - return this; - - }, - - stop: function () { - - if ( this.hasPlaybackControl === false ) { - - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return; - - } - - this.source.stop(); - this.offset = 0; - this.isPlaying = false; - - return this; - - }, - - connect: function () { - - if ( this.filters.length > 0 ) { - - this.source.connect( this.filters[ 0 ] ); - - for ( var i = 1, l = this.filters.length; i < l; i ++ ) { - - this.filters[ i - 1 ].connect( this.filters[ i ] ); - - } - - this.filters[ this.filters.length - 1 ].connect( this.getOutput() ); - - } else { - - this.source.connect( this.getOutput() ); - - } - - return this; - - }, - - disconnect: function () { - - if ( this.filters.length > 0 ) { - - this.source.disconnect( this.filters[ 0 ] ); - - for ( var i = 1, l = this.filters.length; i < l; i ++ ) { - - this.filters[ i - 1 ].disconnect( this.filters[ i ] ); - - } - - this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() ); - - } else { - - this.source.disconnect( this.getOutput() ); - - } - - return this; - - }, - - getFilters: function () { - - return this.filters; - - }, - - setFilters: function ( value ) { - - if ( ! value ) value = []; - - if ( this.isPlaying === true ) { - - this.disconnect(); - this.filters = value; - this.connect(); - - } else { - - this.filters = value; - - } - - return this; - - }, - - getFilter: function () { - - return this.getFilters()[ 0 ]; - - }, - - setFilter: function ( filter ) { - - return this.setFilters( filter ? [ filter ] : [] ); - - }, - - setPlaybackRate: function ( value ) { - - if ( this.hasPlaybackControl === false ) { - - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return; - - } - - this.playbackRate = value; - - if ( this.isPlaying === true ) { - - this.source.playbackRate.setValueAtTime( this.playbackRate, this.context.currentTime ); - - } - - return this; - - }, - - getPlaybackRate: function () { - - return this.playbackRate; - - }, - - onEnded: function () { - - this.isPlaying = false; - - }, - - getLoop: function () { - - if ( this.hasPlaybackControl === false ) { - - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return false; - - } - - return this.loop; - - }, - - setLoop: function ( value ) { - - if ( this.hasPlaybackControl === false ) { - - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return; - - } - - this.loop = value; - - if ( this.isPlaying === true ) { - - this.source.loop = this.loop; - - } - - return this; - - }, - - getVolume: function () { - - return this.gain.gain.value; - - }, - - setVolume: function ( value ) { - - this.gain.gain.value = value; - - return this; - - } - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Audios', () => { - - QUnit.module.todo( 'Audio', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "getOutput", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setNodeSource", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setBuffer", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "play", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "pause", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "stop", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "connect", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "disconnect", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getFilters", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setFilters", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getFilter", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setFilter", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setPlaybackRate", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getPlaybackRate", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "onEnded", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getLoop", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setLoop", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getVolume", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setVolume", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function AudioAnalyser( audio, fftSize ) { - - this.analyser = audio.context.createAnalyser(); - this.analyser.fftSize = fftSize !== undefined ? fftSize : 2048; - - this.data = new Uint8Array( this.analyser.frequencyBinCount ); - - audio.getOutput().connect( this.analyser ); - - } - - Object.assign( AudioAnalyser.prototype, { - - getFrequencyData: function () { - - this.analyser.getByteFrequencyData( this.data ); - - return this.data; - - }, - - getAverageFrequency: function () { - - var value = 0, data = this.getFrequencyData(); - - for ( var i = 0; i < data.length; i ++ ) { - - value += data[ i ]; - - } - - return value / data.length; - - } - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Audios', () => { - - QUnit.module.todo( 'AudioAnalyser', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "getFrequencyData", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getAverageFrequency", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - var context; - - var AudioContext = { - - getContext: function () { - - if ( context === undefined ) { - - context = new ( window.AudioContext || window.webkitAudioContext )(); - - } - - return context; - - }, - - setContext: function ( value ) { - - context = value; - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Audios', () => { - - QUnit.module.todo( 'AudioContext', () => { - - // PUBLIC STUFF - QUnit.test( "getContext", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setContext", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function AudioListener() { - - Object3D.call( this ); - - this.type = 'AudioListener'; - - this.context = AudioContext.getContext(); - - this.gain = this.context.createGain(); - this.gain.connect( this.context.destination ); - - this.filter = null; - - } - - AudioListener.prototype = Object.assign( Object.create( Object3D.prototype ), { - - constructor: AudioListener, - - getInput: function () { - - return this.gain; - - }, - - removeFilter: function ( ) { - - if ( this.filter !== null ) { - - this.gain.disconnect( this.filter ); - this.filter.disconnect( this.context.destination ); - this.gain.connect( this.context.destination ); - this.filter = null; - - } - - }, - - getFilter: function () { - - return this.filter; - - }, - - setFilter: function ( value ) { - - if ( this.filter !== null ) { - - this.gain.disconnect( this.filter ); - this.filter.disconnect( this.context.destination ); - - } else { - - this.gain.disconnect( this.context.destination ); - - } - - this.filter = value; - this.gain.connect( this.filter ); - this.filter.connect( this.context.destination ); - - }, - - getMasterVolume: function () { - - return this.gain.gain.value; - - }, - - setMasterVolume: function ( value ) { - - this.gain.gain.value = value; - - }, - - updateMatrixWorld: ( function () { - - var position = new Vector3(); - var quaternion = new Quaternion(); - var scale = new Vector3(); - - var orientation = new Vector3(); - - return function updateMatrixWorld( force ) { - - Object3D.prototype.updateMatrixWorld.call( this, force ); - - var listener = this.context.listener; - var up = this.up; - - this.matrixWorld.decompose( position, quaternion, scale ); - - orientation.set( 0, 0, - 1 ).applyQuaternion( quaternion ); - - if ( listener.positionX ) { - - listener.positionX.setValueAtTime( position.x, this.context.currentTime ); - listener.positionY.setValueAtTime( position.y, this.context.currentTime ); - listener.positionZ.setValueAtTime( position.z, this.context.currentTime ); - listener.forwardX.setValueAtTime( orientation.x, this.context.currentTime ); - listener.forwardY.setValueAtTime( orientation.y, this.context.currentTime ); - listener.forwardZ.setValueAtTime( orientation.z, this.context.currentTime ); - listener.upX.setValueAtTime( up.x, this.context.currentTime ); - listener.upY.setValueAtTime( up.y, this.context.currentTime ); - listener.upZ.setValueAtTime( up.z, this.context.currentTime ); - - } else { - - listener.setPosition( position.x, position.y, position.z ); - listener.setOrientation( orientation.x, orientation.y, orientation.z, up.x, up.y, up.z ); - - } - - }; - - } )() - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Audios', () => { - - QUnit.module.todo( 'AudioListener', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "getInput", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "removeFilter", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getFilter", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setFilter", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getMasterVolume", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setMasterVolume", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "updateMatrixWorld", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function PositionalAudio( listener ) { - - Audio.call( this, listener ); - - this.panner = this.context.createPanner(); - this.panner.connect( this.gain ); - - } - - PositionalAudio.prototype = Object.assign( Object.create( Audio.prototype ), { - - constructor: PositionalAudio, - - getOutput: function () { - - return this.panner; - - }, - - getRefDistance: function () { - - return this.panner.refDistance; - - }, - - setRefDistance: function ( value ) { - - this.panner.refDistance = value; - - }, - - getRolloffFactor: function () { - - return this.panner.rolloffFactor; - - }, - - setRolloffFactor: function ( value ) { - - this.panner.rolloffFactor = value; - - }, - - getDistanceModel: function () { - - return this.panner.distanceModel; - - }, - - setDistanceModel: function ( value ) { - - this.panner.distanceModel = value; - - }, - - getMaxDistance: function () { - - return this.panner.maxDistance; - - }, - - setMaxDistance: function ( value ) { - - this.panner.maxDistance = value; - - }, - - updateMatrixWorld: ( function () { - - var position = new Vector3(); - - return function updateMatrixWorld( force ) { - - Object3D.prototype.updateMatrixWorld.call( this, force ); - - position.setFromMatrixPosition( this.matrixWorld ); - - this.panner.setPosition( position.x, position.y, position.z ); - - }; - - } )() - - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Audios', () => { - - QUnit.module.todo( 'PositionalAudio', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "getOutput", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getRefDistance", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setRefDistance", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getRolloffFactor", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setRolloffFactor", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getDistanceModel", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setDistanceModel", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getMaxDistance", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setMaxDistance", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "updateMatrixWorld", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - * @author mikael emtinger / http://gomo.se/ - * @author WestLangley / http://github.com/WestLangley - */ - - function Camera() { - - Object3D.call( this ); - - this.type = 'Camera'; - - this.matrixWorldInverse = new Matrix4(); - this.projectionMatrix = new Matrix4(); - - } - - Camera.prototype = Object.assign( Object.create( Object3D.prototype ), { - - constructor: Camera, - - isCamera: true, - - copy: function ( source, recursive ) { - - Object3D.prototype.copy.call( this, source, recursive ); - - this.matrixWorldInverse.copy( source.matrixWorldInverse ); - this.projectionMatrix.copy( source.projectionMatrix ); - - return this; - - }, - - getWorldDirection: function () { - - var quaternion = new Quaternion(); - - return function getWorldDirection( optionalTarget ) { - - var result = optionalTarget || new Vector3(); - - this.getWorldQuaternion( quaternion ); - - return result.set( 0, 0, - 1 ).applyQuaternion( quaternion ); - - }; - - }(), - - updateMatrixWorld: function ( force ) { - - Object3D.prototype.updateMatrixWorld.call( this, force ); - - this.matrixWorldInverse.getInverse( this.matrixWorld ); - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - } - - } ); - - function PerspectiveCamera( fov, aspect, near, far ) { - - Camera.call( this ); - - this.type = 'PerspectiveCamera'; - - this.fov = fov !== undefined ? fov : 50; - this.zoom = 1; - - this.near = near !== undefined ? near : 0.1; - this.far = far !== undefined ? far : 2000; - this.focus = 10; - - this.aspect = aspect !== undefined ? aspect : 1; - this.view = null; - - this.filmGauge = 35; // width of the film (default in millimeters) - this.filmOffset = 0; // horizontal film offset (same unit as gauge) - - this.updateProjectionMatrix(); - - } - - PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), { - - constructor: PerspectiveCamera, - - isPerspectiveCamera: true, - - copy: function ( source, recursive ) { - - Camera.prototype.copy.call( this, source, recursive ); - - this.fov = source.fov; - this.zoom = source.zoom; - - this.near = source.near; - this.far = source.far; - this.focus = source.focus; - - this.aspect = source.aspect; - this.view = source.view === null ? null : Object.assign( {}, source.view ); - - this.filmGauge = source.filmGauge; - this.filmOffset = source.filmOffset; - - return this; - - }, - - /** - * Sets the FOV by focal length in respect to the current .filmGauge. - * - * The default film gauge is 35, so that the focal length can be specified for - * a 35mm (full frame) camera. - * - * Values for focal length and film gauge must have the same unit. - */ - setFocalLength: function ( focalLength ) { - - // see http://www.bobatkins.com/photography/technical/field_of_view.html - var vExtentSlope = 0.5 * this.getFilmHeight() / focalLength; - - this.fov = _Math.RAD2DEG * 2 * Math.atan( vExtentSlope ); - this.updateProjectionMatrix(); - - }, - - /** - * Calculates the focal length from the current .fov and .filmGauge. - */ - getFocalLength: function () { - - var vExtentSlope = Math.tan( _Math.DEG2RAD * 0.5 * this.fov ); - - return 0.5 * this.getFilmHeight() / vExtentSlope; - - }, - - getEffectiveFOV: function () { - - return _Math.RAD2DEG * 2 * Math.atan( - Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom ); - - }, - - getFilmWidth: function () { - - // film not completely covered in portrait format (aspect < 1) - return this.filmGauge * Math.min( this.aspect, 1 ); - - }, - - getFilmHeight: function () { - - // film not completely covered in landscape format (aspect > 1) - return this.filmGauge / Math.max( this.aspect, 1 ); - - }, - - /** - * Sets an offset in a larger frustum. This is useful for multi-window or - * multi-monitor/multi-machine setups. - * - * For example, if you have 3x2 monitors and each monitor is 1920x1080 and - * the monitors are in grid like this - * - * +---+---+---+ - * | A | B | C | - * +---+---+---+ - * | D | E | F | - * +---+---+---+ - * - * then for each monitor you would call it like this - * - * var w = 1920; - * var h = 1080; - * var fullWidth = w * 3; - * var fullHeight = h * 2; - * - * --A-- - * camera.setOffset( fullWidth, fullHeight, w * 0, h * 0, w, h ); - * --B-- - * camera.setOffset( fullWidth, fullHeight, w * 1, h * 0, w, h ); - * --C-- - * camera.setOffset( fullWidth, fullHeight, w * 2, h * 0, w, h ); - * --D-- - * camera.setOffset( fullWidth, fullHeight, w * 0, h * 1, w, h ); - * --E-- - * camera.setOffset( fullWidth, fullHeight, w * 1, h * 1, w, h ); - * --F-- - * camera.setOffset( fullWidth, fullHeight, w * 2, h * 1, w, h ); - * - * Note there is no reason monitors have to be the same size or in a grid. - */ - setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) { - - this.aspect = fullWidth / fullHeight; - - if ( this.view === null ) { - - this.view = { - enabled: true, - fullWidth: 1, - fullHeight: 1, - offsetX: 0, - offsetY: 0, - width: 1, - height: 1 - }; - - } - - this.view.enabled = true; - this.view.fullWidth = fullWidth; - this.view.fullHeight = fullHeight; - this.view.offsetX = x; - this.view.offsetY = y; - this.view.width = width; - this.view.height = height; - - this.updateProjectionMatrix(); - - }, - - clearViewOffset: function () { - - if ( this.view !== null ) { - - this.view.enabled = false; - - } - - this.updateProjectionMatrix(); - - }, - - updateProjectionMatrix: function () { - - var near = this.near, - top = near * Math.tan( - _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom, - height = 2 * top, - width = this.aspect * height, - left = - 0.5 * width, - view = this.view; - - if ( this.view !== null && this.view.enabled ) { - - var fullWidth = view.fullWidth, - fullHeight = view.fullHeight; - - left += view.offsetX * width / fullWidth; - top -= view.offsetY * height / fullHeight; - width *= view.width / fullWidth; - height *= view.height / fullHeight; - - } - - var skew = this.filmOffset; - if ( skew !== 0 ) left += near * skew / this.getFilmWidth(); - - this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far ); - - }, - - toJSON: function ( meta ) { - - var data = Object3D.prototype.toJSON.call( this, meta ); - - data.object.fov = this.fov; - data.object.zoom = this.zoom; - - data.object.near = this.near; - data.object.far = this.far; - data.object.focus = this.focus; - - data.object.aspect = this.aspect; - - if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); - - data.object.filmGauge = this.filmGauge; - data.object.filmOffset = this.filmOffset; - - return data; - - } - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function ArrayCamera( array ) { - - PerspectiveCamera.call( this ); - - this.cameras = array || []; - - } - - ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), { - - constructor: ArrayCamera, - - isArrayCamera: true - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Cameras', () => { - - QUnit.module.todo( 'ArrayCamera', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isArrayCamera", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author simonThiele / https://github.com/simonThiele - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Cameras', () => { - - QUnit.module.todo( 'Camera', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isCamera", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getWorldDirection", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "updateMatrixWorld", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - var cam = new Camera(); - - // fill the matrices with any nonsense values just to see if they get copied - cam.matrixWorldInverse.set( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); - cam.projectionMatrix.set( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); - - var clonedCam = cam.clone(); - - // TODO: Uuuummmhhh DO NOT relie equality on object methods ! - // TODO: What's append if matrix.equal is wrongly implemented ??? - // TODO: this MUST be check by assert - assert.ok( cam.matrixWorldInverse.equals( clonedCam.matrixWorldInverse ), "matrixWorldInverse is equal" ); - assert.ok( cam.projectionMatrix.equals( clonedCam.projectionMatrix ), "projectionMatrix is equal" ); - - } ); - - // OTHERS - // TODO: this should not be here !!! This is Object3D stuff !!! - QUnit.test( "lookAt", ( assert ) => { - - var cam = new Camera(); - cam.lookAt( new Vector3( 0, 1, - 1 ) ); - - assert.numEqual( cam.rotation.x * ( 180 / Math.PI ), 45, "x is equal" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - * @author alteredq / http://alteredqualia.com/ - * @author szimek / https://github.com/szimek/ - */ - - var textureId = 0; - - function Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) { - - Object.defineProperty( this, 'id', { value: textureId ++ } ); - - this.uuid = _Math.generateUUID(); - - this.name = ''; - - this.image = image !== undefined ? image : Texture.DEFAULT_IMAGE; - this.mipmaps = []; - - this.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING; - - this.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping; - this.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping; - - this.magFilter = magFilter !== undefined ? magFilter : LinearFilter; - this.minFilter = minFilter !== undefined ? minFilter : LinearMipMapLinearFilter; - - this.anisotropy = anisotropy !== undefined ? anisotropy : 1; - - this.format = format !== undefined ? format : RGBAFormat; - this.type = type !== undefined ? type : UnsignedByteType; - - this.offset = new Vector2( 0, 0 ); - this.repeat = new Vector2( 1, 1 ); - this.center = new Vector2( 0, 0 ); - this.rotation = 0; - - this.matrixAutoUpdate = true; - this.matrix = new Matrix3(); - - this.generateMipmaps = true; - this.premultiplyAlpha = false; - this.flipY = true; - this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) - - // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap. - // - // Also changing the encoding after already used by a Material will not automatically make the Material - // update. You need to explicitly call Material.needsUpdate to trigger it to recompile. - this.encoding = encoding !== undefined ? encoding : LinearEncoding; - - this.version = 0; - this.onUpdate = null; - - } - - Texture.DEFAULT_IMAGE = undefined; - Texture.DEFAULT_MAPPING = UVMapping; - - Object.defineProperty( Texture.prototype, "needsUpdate", { - - set: function ( value ) { - - if ( value === true ) this.version ++; - - } - - } ); - - Object.assign( Texture.prototype, EventDispatcher.prototype, { - - constructor: Texture, - - isTexture: true, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( source ) { - - this.name = source.name; - - this.image = source.image; - this.mipmaps = source.mipmaps.slice( 0 ); - - this.mapping = source.mapping; - - this.wrapS = source.wrapS; - this.wrapT = source.wrapT; - - this.magFilter = source.magFilter; - this.minFilter = source.minFilter; - - this.anisotropy = source.anisotropy; - - this.format = source.format; - this.type = source.type; - - this.offset.copy( source.offset ); - this.repeat.copy( source.repeat ); - this.center.copy( source.center ); - this.rotation = source.rotation; - - this.matrixAutoUpdate = source.matrixAutoUpdate; - this.matrix.copy( source.matrix ); - - this.generateMipmaps = source.generateMipmaps; - this.premultiplyAlpha = source.premultiplyAlpha; - this.flipY = source.flipY; - this.unpackAlignment = source.unpackAlignment; - this.encoding = source.encoding; - - return this; - - }, - - toJSON: function ( meta ) { - - var isRootObject = ( meta === undefined || typeof meta === 'string' ); - - if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) { - - return meta.textures[ this.uuid ]; - - } - - function getDataURL( image ) { - - var canvas; - - if ( image instanceof HTMLCanvasElement ) { - - canvas = image; - - } else { - - canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); - canvas.width = image.width; - canvas.height = image.height; - - var context = canvas.getContext( '2d' ); - - if ( image instanceof ImageData ) { - - context.putImageData( image, 0, 0 ); - - } else { - - context.drawImage( image, 0, 0, image.width, image.height ); - - } - - } - - if ( canvas.width > 2048 || canvas.height > 2048 ) { - - return canvas.toDataURL( 'image/jpeg', 0.6 ); - - } else { - - return canvas.toDataURL( 'image/png' ); - - } - - } - - var output = { - metadata: { - version: 4.5, - type: 'Texture', - generator: 'Texture.toJSON' - }, - - uuid: this.uuid, - name: this.name, - - mapping: this.mapping, - - repeat: [ this.repeat.x, this.repeat.y ], - offset: [ this.offset.x, this.offset.y ], - center: [ this.center.x, this.center.y ], - rotation: this.rotation, - - wrap: [ this.wrapS, this.wrapT ], - - minFilter: this.minFilter, - magFilter: this.magFilter, - anisotropy: this.anisotropy, - - flipY: this.flipY - }; - - if ( this.image !== undefined ) { - - // TODO: Move to THREE.Image - - var image = this.image; - - if ( image.uuid === undefined ) { - - image.uuid = _Math.generateUUID(); // UGH - - } - - if ( ! isRootObject && meta.images[ image.uuid ] === undefined ) { - - meta.images[ image.uuid ] = { - uuid: image.uuid, - url: getDataURL( image ) - }; - - } - - output.image = image.uuid; - - } - - if ( ! isRootObject ) { - - meta.textures[ this.uuid ] = output; - - } - - return output; - - }, - - dispose: function () { - - this.dispatchEvent( { type: 'dispose' } ); - - }, - - transformUv: function ( uv ) { - - if ( this.mapping !== UVMapping ) return; - - uv.applyMatrix3( this.matrix ); - - if ( uv.x < 0 || uv.x > 1 ) { - - switch ( this.wrapS ) { - - case RepeatWrapping: - - uv.x = uv.x - Math.floor( uv.x ); - break; - - case ClampToEdgeWrapping: - - uv.x = uv.x < 0 ? 0 : 1; - break; - - case MirroredRepeatWrapping: - - if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) { - - uv.x = Math.ceil( uv.x ) - uv.x; - - } else { - - uv.x = uv.x - Math.floor( uv.x ); - - } - break; - - } - - } - - if ( uv.y < 0 || uv.y > 1 ) { - - switch ( this.wrapT ) { - - case RepeatWrapping: - - uv.y = uv.y - Math.floor( uv.y ); - break; - - case ClampToEdgeWrapping: - - uv.y = uv.y < 0 ? 0 : 1; - break; - - case MirroredRepeatWrapping: - - if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { - - uv.y = Math.ceil( uv.y ) - uv.y; - - } else { - - uv.y = uv.y - Math.floor( uv.y ); - - } - break; - - } - - } - - if ( this.flipY ) { - - uv.y = 1 - uv.y; - - } - - } - - } ); - - function WebGLRenderTarget( width, height, options ) { - - this.uuid = _Math.generateUUID(); - - this.width = width; - this.height = height; - - this.scissor = new Vector4( 0, 0, width, height ); - this.scissorTest = false; - - this.viewport = new Vector4( 0, 0, width, height ); - - options = options || {}; - - if ( options.minFilter === undefined ) options.minFilter = LinearFilter; - - this.texture = new Texture( undefined, undefined, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding ); - - this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true; - this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true; - this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null; - - } - - Object.assign( WebGLRenderTarget.prototype, EventDispatcher.prototype, { - - isWebGLRenderTarget: true, - - setSize: function ( width, height ) { - - if ( this.width !== width || this.height !== height ) { - - this.width = width; - this.height = height; - - this.dispose(); - - } - - this.viewport.set( 0, 0, width, height ); - this.scissor.set( 0, 0, width, height ); - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( source ) { - - this.width = source.width; - this.height = source.height; - - this.viewport.copy( source.viewport ); - - this.texture = source.texture.clone(); - - this.depthBuffer = source.depthBuffer; - this.stencilBuffer = source.stencilBuffer; - this.depthTexture = source.depthTexture; - - return this; - - }, - - dispose: function () { - - this.dispatchEvent( { type: 'dispose' } ); - - } - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Cameras', () => { - - QUnit.module.todo( 'CubeCamera', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - function OrthographicCamera( left, right, top, bottom, near, far ) { - - Camera.call( this ); - - this.type = 'OrthographicCamera'; - - this.zoom = 1; - this.view = null; - - this.left = left; - this.right = right; - this.top = top; - this.bottom = bottom; - - this.near = ( near !== undefined ) ? near : 0.1; - this.far = ( far !== undefined ) ? far : 2000; - - this.updateProjectionMatrix(); - - } - - OrthographicCamera.prototype = Object.assign( Object.create( Camera.prototype ), { - - constructor: OrthographicCamera, - - isOrthographicCamera: true, - - copy: function ( source, recursive ) { - - Camera.prototype.copy.call( this, source, recursive ); - - this.left = source.left; - this.right = source.right; - this.top = source.top; - this.bottom = source.bottom; - this.near = source.near; - this.far = source.far; - - this.zoom = source.zoom; - this.view = source.view === null ? null : Object.assign( {}, source.view ); - - return this; - - }, - - setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) { - - if ( this.view === null ) { - - this.view = { - enabled: true, - fullWidth: 1, - fullHeight: 1, - offsetX: 0, - offsetY: 0, - width: 1, - height: 1 - }; - - } - - this.view.enabled = true; - this.view.fullWidth = fullWidth; - this.view.fullHeight = fullHeight; - this.view.offsetX = x; - this.view.offsetY = y; - this.view.width = width; - this.view.height = height; - - this.updateProjectionMatrix(); - - }, - - clearViewOffset: function () { - - if ( this.view !== null ) { - - this.view.enabled = false; - - } - - this.updateProjectionMatrix(); - - }, - - updateProjectionMatrix: function () { - - var dx = ( this.right - this.left ) / ( 2 * this.zoom ); - var dy = ( this.top - this.bottom ) / ( 2 * this.zoom ); - var cx = ( this.right + this.left ) / 2; - var cy = ( this.top + this.bottom ) / 2; - - var left = cx - dx; - var right = cx + dx; - var top = cy + dy; - var bottom = cy - dy; - - if ( this.view !== null && this.view.enabled ) { - - var zoomW = this.zoom / ( this.view.width / this.view.fullWidth ); - var zoomH = this.zoom / ( this.view.height / this.view.fullHeight ); - var scaleW = ( this.right - this.left ) / this.view.width; - var scaleH = ( this.top - this.bottom ) / this.view.height; - - left += scaleW * ( this.view.offsetX / zoomW ); - right = left + scaleW * ( this.view.width / zoomW ); - top -= scaleH * ( this.view.offsetY / zoomH ); - bottom = top - scaleH * ( this.view.height / zoomH ); - - } - - this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far ); - - }, - - toJSON: function ( meta ) { - - var data = Object3D.prototype.toJSON.call( this, meta ); - - data.object.zoom = this.zoom; - data.object.left = this.left; - data.object.right = this.right; - data.object.top = this.top; - data.object.bottom = this.bottom; - data.object.near = this.near; - data.object.far = this.far; - - if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); - - return data; - - } - - } ); - - /** - * @author simonThiele / https://github.com/simonThiele - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Cameras', () => { - - QUnit.module.todo( 'OrthographicCamera', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isOrthographicCamera", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setViewOffset", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clearViewOffset", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "updateProjectionMatrix", ( assert ) => { - - var left = - 1, right = 1, top = 1, bottom = - 1, near = 1, far = 3; - var cam = new OrthographicCamera( left, right, top, bottom, near, far ); - - // updateProjectionMatrix is called in contructor - var pMatrix = cam.projectionMatrix.elements; - - // orthographic projection is given my the 4x4 Matrix - // 2/r-l 0 0 -(l+r/r-l) - // 0 2/t-b 0 -(t+b/t-b) - // 0 0 -2/f-n -(f+n/f-n) - // 0 0 0 1 - - assert.ok( pMatrix[ 0 ] === 2 / ( right - left ), "m[0,0] === 2 / (r - l)" ); - assert.ok( pMatrix[ 5 ] === 2 / ( top - bottom ), "m[1,1] === 2 / (t - b)" ); - assert.ok( pMatrix[ 10 ] === - 2 / ( far - near ), "m[2,2] === -2 / (f - n)" ); - assert.ok( pMatrix[ 12 ] === - ( ( right + left ) / ( right - left ) ), "m[3,0] === -(r+l/r-l)" ); - assert.ok( pMatrix[ 13 ] === - ( ( top + bottom ) / ( top - bottom ) ), "m[3,1] === -(t+b/b-t)" ); - assert.ok( pMatrix[ 14 ] === - ( ( far + near ) / ( far - near ) ), "m[3,2] === -(f+n/f-n)" ); - - } ); - - QUnit.test( "toJSON", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - // TODO: no no no clone is a camera methods that relied to copy method - QUnit.test( "clone", ( assert ) => { - - var left = - 1.5, right = 1.5, top = 1, bottom = - 1, near = 0.1, far = 42; - var cam = new OrthographicCamera( left, right, top, bottom, near, far ); - - var clonedCam = cam.clone(); - - assert.ok( cam.left === clonedCam.left, "left is equal" ); - assert.ok( cam.right === clonedCam.right, "right is equal" ); - assert.ok( cam.top === clonedCam.top, "top is equal" ); - assert.ok( cam.bottom === clonedCam.bottom, "bottom is equal" ); - assert.ok( cam.near === clonedCam.near, "near is equal" ); - assert.ok( cam.far === clonedCam.far, "far is equal" ); - assert.ok( cam.zoom === clonedCam.zoom, "zoom is equal" ); - - } ); - - } ); - - } ); - - /** - * @author simonThiele / https://github.com/simonThiele - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Cameras', () => { - - QUnit.module.todo( 'PerspectiveCamera', () => { - - // see e.g. math/Matrix4.js - var matrixEquals4 = function ( a, b, tolerance ) { - - tolerance = tolerance || 0.0001; - if ( a.elements.length != b.elements.length ) { - - return false; - - } - for ( var i = 0, il = a.elements.length; i < il; i ++ ) { - - var delta = a.elements[ i ] - b.elements[ i ]; - if ( delta > tolerance ) { - - return false; - - } - - } - - return true; - - }; - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isPerspectiveCamera", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setFocalLength", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getFocalLength", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getEffectiveFOV", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getFilmWidth", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getFilmHeight", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setViewOffset", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clearViewOffset", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "updateProjectionMatrix", ( assert ) => { - - var cam = new PerspectiveCamera( 75, 16 / 9, 0.1, 300.0 ); - - // updateProjectionMatrix is called in contructor - var m = cam.projectionMatrix; - - // perspective projection is given my the 4x4 Matrix - // 2n/r-l 0 l+r/r-l 0 - // 0 2n/t-b t+b/t-b 0 - // 0 0 -(f+n/f-n) -(2fn/f-n) - // 0 0 -1 0 - - // this matrix was calculated by hand via glMatrix.perspective(75, 16 / 9, 0.1, 300.0, pMatrix) - // to get a reference matrix from plain WebGL - var reference = new Matrix4().set( - 0.7330642938613892, 0, 0, 0, - 0, 1.3032253980636597, 0, 0, - 0, 0, - 1.000666856765747, - 0.2000666856765747, - 0, 0, - 1, 0 - ); - - // assert.ok( reference.equals(m) ); - assert.ok( matrixEquals4( reference, m, 0.000001 ) ); - - } ); - - QUnit.test( "toJSON", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - // TODO: no no no clone is a camera methods that relied to copy method - QUnit.test( "clone", ( assert ) => { - - var near = 1, - far = 3, - aspect = 16 / 9, - fov = 90; - - var cam = new PerspectiveCamera( fov, aspect, near, far ); - - var clonedCam = cam.clone(); - - assert.ok( cam.fov === clonedCam.fov, "fov is equal" ); - assert.ok( cam.aspect === clonedCam.aspect, "aspect is equal" ); - assert.ok( cam.near === clonedCam.near, "near is equal" ); - assert.ok( cam.far === clonedCam.far, "far is equal" ); - assert.ok( cam.zoom === clonedCam.zoom, "zoom is equal" ); - assert.ok( cam.projectionMatrix.equals( clonedCam.projectionMatrix ), "projectionMatrix is equal" ); - - } ); - - } ); - - } ); - - function StereoCamera() { - - this.type = 'StereoCamera'; - - this.aspect = 1; - - this.eyeSep = 0.064; - - this.cameraL = new PerspectiveCamera(); - this.cameraL.layers.enable( 1 ); - this.cameraL.matrixAutoUpdate = false; - - this.cameraR = new PerspectiveCamera(); - this.cameraR.layers.enable( 2 ); - this.cameraR.matrixAutoUpdate = false; - - } - - Object.assign( StereoCamera.prototype, { - - update: ( function () { - - var instance, focus, fov, aspect, near, far, zoom, eyeSep; - - var eyeRight = new Matrix4(); - var eyeLeft = new Matrix4(); - - return function update( camera ) { - - var needsUpdate = instance !== this || focus !== camera.focus || fov !== camera.fov || - aspect !== camera.aspect * this.aspect || near !== camera.near || - far !== camera.far || zoom !== camera.zoom || eyeSep !== this.eyeSep; - - if ( needsUpdate ) { - - instance = this; - focus = camera.focus; - fov = camera.fov; - aspect = camera.aspect * this.aspect; - near = camera.near; - far = camera.far; - zoom = camera.zoom; - - // Off-axis stereoscopic effect based on - // http://paulbourke.net/stereographics/stereorender/ - - var projectionMatrix = camera.projectionMatrix.clone(); - eyeSep = this.eyeSep / 2; - var eyeSepOnProjection = eyeSep * near / focus; - var ymax = ( near * Math.tan( _Math.DEG2RAD * fov * 0.5 ) ) / zoom; - var xmin, xmax; - - // translate xOffset - - eyeLeft.elements[ 12 ] = - eyeSep; - eyeRight.elements[ 12 ] = eyeSep; - - // for left eye - - xmin = - ymax * aspect + eyeSepOnProjection; - xmax = ymax * aspect + eyeSepOnProjection; - - projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin ); - projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin ); - - this.cameraL.projectionMatrix.copy( projectionMatrix ); - - // for right eye - - xmin = - ymax * aspect - eyeSepOnProjection; - xmax = ymax * aspect - eyeSepOnProjection; - - projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin ); - projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin ); - - this.cameraR.projectionMatrix.copy( projectionMatrix ); - - } - - this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( eyeLeft ); - this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( eyeRight ); - - }; - - } )() - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Cameras', () => { - - QUnit.module.todo( 'StereoCamera', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "update", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author simonThiele / https://github.com/simonThiele - */ - /* global QUnit */ - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'BufferAttribute', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.throws( - function () { - - var a = new BufferAttribute( [ 1, 2, 3, 4 ], 2, false ); - - }, - /array should be a Typed Array/, - "Calling constructor with a simple array throws Error" - ); - - } ); - - // PROPERTIES - QUnit.test( "needsUpdate", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isBufferAttribute", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setArray", ( assert ) => { - - var f32a = new Float32Array( [ 1, 2, 3, 4 ] ); - var a = new BufferAttribute( f32a, 2, false ); - - a.setArray( f32a, 2 ); - - assert.strictEqual( a.count, 2, "Check item count" ); - assert.strictEqual( a.array, f32a, "Check array" ); - - assert.throws( - function () { - - a.setArray( [ 1, 2, 3, 4 ] ); - - }, - /array should be a Typed Array/, - "Calling setArray with a simple array throws Error" - ); - - } ); - - QUnit.test( "setDynamic", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - var attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ); - attr.setDynamic( true ); - attr.needsUpdate = true; - - var attrCopy = new BufferAttribute().copy( attr ); - - assert.ok( attr.count === attrCopy.count, 'count is equal' ); - assert.ok( attr.itemSize === attrCopy.itemSize, 'itemSize is equal' ); - assert.ok( attr.dynamic === attrCopy.dynamic, 'dynamic is equal' ); - assert.ok( attr.array.length === attrCopy.array.length, 'array length is equal' ); - assert.ok( attr.version === 1 && attrCopy.version === 0, 'version is not copied which is good' ); - - } ); - - QUnit.test( "copyAt", ( assert ) => { - - var attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] ), 3 ); - var attr2 = new BufferAttribute( new Float32Array( 9 ), 3 ); - - attr2.copyAt( 1, attr, 2 ); - attr2.copyAt( 0, attr, 1 ); - attr2.copyAt( 2, attr, 0 ); - - var i = attr.array; - var i2 = attr2.array; // should be [4, 5, 6, 7, 8, 9, 1, 2, 3] - - assert.ok( i2[ 0 ] === i[ 3 ] && i2[ 1 ] === i[ 4 ] && i2[ 2 ] === i[ 5 ], 'chunck copied to correct place' ); - assert.ok( i2[ 3 ] === i[ 6 ] && i2[ 4 ] === i[ 7 ] && i2[ 5 ] === i[ 8 ], 'chunck copied to correct place' ); - assert.ok( i2[ 6 ] === i[ 0 ] && i2[ 7 ] === i[ 1 ] && i2[ 8 ] === i[ 2 ], 'chunck copied to correct place' ); - - } ); - - QUnit.test( "copyArray", ( assert ) => { - - var f32a = new Float32Array( [ 5, 6, 7, 8 ] ); - var a = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4 ] ), 2, false ); - - a.copyArray( f32a ); - - assert.deepEqual( a.array, f32a, "Check array has new values" ); - - } ); - - QUnit.test( "copyColorsArray", ( assert ) => { - - var attr = new BufferAttribute( new Float32Array( 6 ), 3 ); - - attr.copyColorsArray( [ - new Color( 0, 0.5, 1 ), - new Color( 0.25, 1, 0 ) - ] ); - - var i = attr.array; - assert.ok( i[ 0 ] === 0 && i[ 1 ] === 0.5 && i[ 2 ] === 1, 'first color was copied correctly' ); - assert.ok( i[ 3 ] === 0.25 && i[ 4 ] === 1 && i[ 5 ] === 0, 'second color was copied correctly' ); - - } ); - - QUnit.test( "copyIndicesArray", ( assert ) => { - - var attr = new BufferAttribute( new Float32Array( 6 ), 3 ); - - attr.copyIndicesArray( [ - { - a: 1, - b: 2, - c: 3 - }, - { - a: 4, - b: 5, - c: 6 - } - ] ); - - var i = attr.array; - assert.ok( i[ 0 ] === 1 && i[ 1 ] === 2 && i[ 2 ] === 3, 'first indices were copied correctly' ); - assert.ok( i[ 3 ] === 4 && i[ 4 ] === 5 && i[ 5 ] === 6, 'second indices were copied correctly' ); - - } ); - - QUnit.test( "copyVector2sArray", ( assert ) => { - - var attr = new BufferAttribute( new Float32Array( 4 ), 2 ); - - attr.copyVector2sArray( [ - new Vector2( 1, 2 ), - new Vector2( 4, 5 ) - ] ); - - var i = attr.array; - assert.ok( i[ 0 ] === 1 && i[ 1 ] === 2, 'first vector was copied correctly' ); - assert.ok( i[ 2 ] === 4 && i[ 3 ] === 5, 'second vector was copied correctly' ); - - } ); - - QUnit.test( "copyVector3sArray", ( assert ) => { - - var attr = new BufferAttribute( new Float32Array( 6 ), 2 ); - - attr.copyVector3sArray( [ - new Vector3( 1, 2, 3 ), - new Vector3( 10, 20, 30 ) - ] ); - - var i = attr.array; - assert.ok( i[ 0 ] === 1 && i[ 1 ] === 2 && i[ 2 ] === 3, 'first vector was copied correctly' ); - assert.ok( i[ 3 ] === 10 && i[ 4 ] === 20 && i[ 5 ] === 30, 'second vector was copied correctly' ); - - } ); - - QUnit.test( "copyVector4sArray", ( assert ) => { - - var attr = new BufferAttribute( new Float32Array( 8 ), 2 ); - - attr.copyVector4sArray( [ - new Vector4( 1, 2, 3, 4 ), - new Vector4( 10, 20, 30, 40 ) - ] ); - - var i = attr.array; - assert.ok( i[ 0 ] === 1 && i[ 1 ] === 2 && i[ 2 ] === 3 && i[ 3 ] === 4, 'first vector was copied correctly' ); - assert.ok( i[ 4 ] === 10 && i[ 5 ] === 20 && i[ 6 ] === 30 && i[ 7 ] === 40, 'second vector was copied correctly' ); - - } ); - - QUnit.test( "set", ( assert ) => { - - var f32a = new Float32Array( [ 1, 2, 3, 4 ] ); - var a = new BufferAttribute( f32a, 2, false ); - var expected = new Float32Array( [ 9, 2, 8, 4 ] ); - - a.set( [ 9 ] ); - a.set( [ 8 ], 2 ); - - assert.deepEqual( a.array, expected, "Check array has expected values" ); - - } ); - - QUnit.test( "set[X, Y, Z, W, XYZ, XYZW]/get[X, Y, Z, W]", ( assert ) => { - - var f32a = new Float32Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); - var a = new BufferAttribute( f32a, 4, false ); - var expected = new Float32Array( [ 1, 2, - 3, - 4, - 5, - 6, 7, 8 ] ); - - a.setX( 1, a.getX( 1 ) * - 1 ); - a.setY( 1, a.getY( 1 ) * - 1 ); - a.setZ( 0, a.getZ( 0 ) * - 1 ); - a.setW( 0, a.getW( 0 ) * - 1 ); - - assert.deepEqual( a.array, expected, "Check all set* calls set the correct values" ); - - } ); - - QUnit.test( "setXY", ( assert ) => { - - var f32a = new Float32Array( [ 1, 2, 3, 4 ] ); - var a = new BufferAttribute( f32a, 2, false ); - var expected = new Float32Array( [ - 1, - 2, 3, 4 ] ); - - a.setXY( 0, - 1, - 2 ); - - assert.deepEqual( a.array, expected, "Check for the correct values" ); - - } ); - - QUnit.test( "setXYZ", ( assert ) => { - - var f32a = new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ); - var a = new BufferAttribute( f32a, 3, false ); - var expected = new Float32Array( [ 1, 2, 3, - 4, - 5, - 6 ] ); - - a.setXYZ( 1, - 4, - 5, - 6 ); - - assert.deepEqual( a.array, expected, "Check for the correct values" ); - - } ); - - QUnit.test( "setXYZW", ( assert ) => { - - var f32a = new Float32Array( [ 1, 2, 3, 4 ] ); - var a = new BufferAttribute( f32a, 4, false ); - var expected = new Float32Array( [ - 1, - 2, - 3, - 4 ] ); - - a.setXYZW( 0, - 1, - 2, - 3, - 4 ); - - assert.deepEqual( a.array, expected, "Check for the correct values" ); - - } ); - - QUnit.test( "onUpload", ( assert ) => { - - var a = new BufferAttribute(); - var func = function () { }; - - a.onUpload( func ); - - assert.strictEqual( a.onUploadCallback, func, "Check callback was set properly" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - var attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 0.12, - 12 ] ), 2 ); - var attrCopy = attr.clone(); - - assert.ok( attr.array.length === attrCopy.array.length, 'attribute was cloned' ); - for ( var i = 0; i < attr.array.length; i ++ ) { - - assert.ok( attr.array[ i ] === attrCopy.array[ i ], 'array item is equal' ); - - } - - } ); - - // OTHERS - QUnit.test( "count", ( assert ) => { - - assert.ok( - new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ).count === 2, - 'count is equal to the number of chunks' - ); - - } ); - - } ); - - QUnit.module.todo( 'Int8BufferAttribute', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - QUnit.module.todo( 'Uint8BufferAttribute', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - QUnit.module.todo( 'Uint8ClampedBufferAttribute', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - QUnit.module.todo( 'Int16BufferAttribute', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - QUnit.module.todo( 'Uint16BufferAttribute', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - QUnit.module.todo( 'Int32BufferAttribute', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - QUnit.module.todo( 'Uint32BufferAttribute', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - QUnit.module.todo( 'Float32BufferAttribute', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - QUnit.module.todo( 'Float64BufferAttribute', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - var Cache = { - - enabled: false, - - files: {}, - - add: function ( key, file ) { - - if ( this.enabled === false ) return; - - // console.log( 'THREE.Cache', 'Adding key:', key ); - - this.files[ key ] = file; - - }, - - get: function ( key ) { - - if ( this.enabled === false ) return; - - // console.log( 'THREE.Cache', 'Checking key:', key ); - - return this.files[ key ]; - - }, - - remove: function ( key ) { - - delete this.files[ key ]; - - }, - - clear: function () { - - this.files = {}; - - } - - }; - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function LoadingManager( onLoad, onProgress, onError ) { - - var scope = this; - - var isLoading = false; - var itemsLoaded = 0; - var itemsTotal = 0; - var urlModifier = undefined; - - this.onStart = undefined; - this.onLoad = onLoad; - this.onProgress = onProgress; - this.onError = onError; - - this.itemStart = function ( url ) { - - itemsTotal ++; - - if ( isLoading === false ) { - - if ( scope.onStart !== undefined ) { - - scope.onStart( url, itemsLoaded, itemsTotal ); - - } - - } - - isLoading = true; - - }; - - this.itemEnd = function ( url ) { - - itemsLoaded ++; - - if ( scope.onProgress !== undefined ) { - - scope.onProgress( url, itemsLoaded, itemsTotal ); - - } - - if ( itemsLoaded === itemsTotal ) { - - isLoading = false; - - if ( scope.onLoad !== undefined ) { - - scope.onLoad(); - - } - - } - - }; - - this.itemError = function ( url ) { - - if ( scope.onError !== undefined ) { - - scope.onError( url ); - - } - - }; - - this.resolveURL = function ( url ) { - - if ( urlModifier ) { - - return urlModifier( url ); - - } - - return url; - - }; - - this.setURLModifier = function ( transform ) { - - urlModifier = transform; - - }; - - } - - var DefaultLoadingManager = new LoadingManager(); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - var loading = {}; - - function FileLoader( manager ) { - - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - - } - - Object.assign( FileLoader.prototype, { - - load: function ( url, onLoad, onProgress, onError ) { - - if ( url === undefined ) url = ''; - - if ( this.path !== undefined ) url = this.path + url; - - url = this.manager.resolveURL( url ); - - var scope = this; - - var cached = Cache.get( url ); - - if ( cached !== undefined ) { - - scope.manager.itemStart( url ); - - setTimeout( function () { - - if ( onLoad ) onLoad( cached ); - - scope.manager.itemEnd( url ); - - }, 0 ); - - return cached; - - } - - // Check if request is duplicate - - if ( loading[ url ] !== undefined ) { - - loading[ url ].push( { - - onLoad: onLoad, - onProgress: onProgress, - onError: onError - - } ); - - return; - - } - - // Check for data: URI - var dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/; - var dataUriRegexResult = url.match( dataUriRegex ); - - // Safari can not handle Data URIs through XMLHttpRequest so process manually - if ( dataUriRegexResult ) { - - var mimeType = dataUriRegexResult[ 1 ]; - var isBase64 = !! dataUriRegexResult[ 2 ]; - var data = dataUriRegexResult[ 3 ]; - - data = window.decodeURIComponent( data ); - - if ( isBase64 ) data = window.atob( data ); - - try { - - var response; - var responseType = ( this.responseType || '' ).toLowerCase(); - - switch ( responseType ) { - - case 'arraybuffer': - case 'blob': - - var view = new Uint8Array( data.length ); - - for ( var i = 0; i < data.length; i ++ ) { - - view[ i ] = data.charCodeAt( i ); - - } - - if ( responseType === 'blob' ) { - - response = new Blob( [ view.buffer ], { type: mimeType } ); - - } else { - - response = view.buffer; - - } - - break; - - case 'document': - - var parser = new DOMParser(); - response = parser.parseFromString( data, mimeType ); - - break; - - case 'json': - - response = JSON.parse( data ); - - break; - - default: // 'text' or other - - response = data; - - break; - - } - - // Wait for next browser tick like standard XMLHttpRequest event dispatching does - window.setTimeout( function () { - - if ( onLoad ) onLoad( response ); - - scope.manager.itemEnd( url ); - - }, 0 ); - - } catch ( error ) { - - // Wait for next browser tick like standard XMLHttpRequest event dispatching does - window.setTimeout( function () { - - if ( onError ) onError( error ); - - scope.manager.itemEnd( url ); - scope.manager.itemError( url ); - - }, 0 ); - - } - - } else { - - // Initialise array for duplicate requests - - loading[ url ] = []; - - loading[ url ].push( { - - onLoad: onLoad, - onProgress: onProgress, - onError: onError - - } ); - - var request = new XMLHttpRequest(); - - request.open( 'GET', url, true ); - - request.addEventListener( 'load', function ( event ) { - - var response = event.target.response; - - Cache.add( url, response ); - - var callbacks = loading[ url ]; - - delete loading[ url ]; - - if ( this.status === 200 ) { - - for ( var i = 0, il = callbacks.length; i < il; i ++ ) { - - var callback = callbacks[ i ]; - if ( callback.onLoad ) callback.onLoad( response ); - - } - - scope.manager.itemEnd( url ); - - } else if ( this.status === 0 ) { - - // Some browsers return HTTP Status 0 when using non-http protocol - // e.g. 'file://' or 'data://'. Handle as success. - - console.warn( 'THREE.FileLoader: HTTP Status 0 received.' ); - - for ( var i = 0, il = callbacks.length; i < il; i ++ ) { - - var callback = callbacks[ i ]; - if ( callback.onLoad ) callback.onLoad( response ); - - } - - scope.manager.itemEnd( url ); - - } else { - - for ( var i = 0, il = callbacks.length; i < il; i ++ ) { - - var callback = callbacks[ i ]; - if ( callback.onError ) callback.onError( event ); - - } - - scope.manager.itemEnd( url ); - scope.manager.itemError( url ); - - } - - }, false ); - - request.addEventListener( 'progress', function ( event ) { - - var callbacks = loading[ url ]; - - for ( var i = 0, il = callbacks.length; i < il; i ++ ) { - - var callback = callbacks[ i ]; - if ( callback.onProgress ) callback.onProgress( event ); - - } - - }, false ); - - request.addEventListener( 'error', function ( event ) { - - var callbacks = loading[ url ]; - - delete loading[ url ]; - - for ( var i = 0, il = callbacks.length; i < il; i ++ ) { - - var callback = callbacks[ i ]; - if ( callback.onError ) callback.onError( event ); - - } - - scope.manager.itemEnd( url ); - scope.manager.itemError( url ); - - }, false ); - - if ( this.responseType !== undefined ) request.responseType = this.responseType; - if ( this.withCredentials !== undefined ) request.withCredentials = this.withCredentials; - - if ( request.overrideMimeType ) request.overrideMimeType( this.mimeType !== undefined ? this.mimeType : 'text/plain' ); - - for ( var header in this.requestHeader ) { - - request.setRequestHeader( header, this.requestHeader[ header ] ); - - } - - request.send( null ); - - } - - scope.manager.itemStart( url ); - - return request; - - }, - - setPath: function ( value ) { - - this.path = value; - return this; - - }, - - setResponseType: function ( value ) { - - this.responseType = value; - return this; - - }, - - setWithCredentials: function ( value ) { - - this.withCredentials = value; - return this; - - }, - - setMimeType: function ( value ) { - - this.mimeType = value; - return this; - - }, - - setRequestHeader: function ( value ) { - - this.requestHeader = value; - return this; - - } - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - * - * parameters = { - * color: , - * opacity: - * } - */ - - function ShadowMaterial( parameters ) { - - Material.call( this ); - - this.type = 'ShadowMaterial'; - - this.color = new Color( 0x000000 ); - this.opacity = 1.0; - - this.lights = true; - this.transparent = true; - - this.setValues( parameters ); - - } - - ShadowMaterial.prototype = Object.create( Material.prototype ); - ShadowMaterial.prototype.constructor = ShadowMaterial; - - ShadowMaterial.prototype.isShadowMaterial = true; - - function SpriteMaterial( parameters ) { - - Material.call( this ); - - this.type = 'SpriteMaterial'; - - this.color = new Color( 0xffffff ); - this.map = null; - - this.rotation = 0; - - this.fog = false; - this.lights = false; - - this.setValues( parameters ); - - } - - SpriteMaterial.prototype = Object.create( Material.prototype ); - SpriteMaterial.prototype.constructor = SpriteMaterial; - SpriteMaterial.prototype.isSpriteMaterial = true; - - SpriteMaterial.prototype.copy = function ( source ) { - - Material.prototype.copy.call( this, source ); - - this.color.copy( source.color ); - this.map = source.map; - - this.rotation = source.rotation; - - return this; - - }; - - /** - * Uniform Utilities - */ - - var UniformsUtils = { - - merge: function ( uniforms ) { - - var merged = {}; - - for ( var u = 0; u < uniforms.length; u ++ ) { - - var tmp = this.clone( uniforms[ u ] ); - - for ( var p in tmp ) { - - merged[ p ] = tmp[ p ]; - - } - - } - - return merged; - - }, - - clone: function ( uniforms_src ) { - - var uniforms_dst = {}; - - for ( var u in uniforms_src ) { - - uniforms_dst[ u ] = {}; - - for ( var p in uniforms_src[ u ] ) { - - var parameter_src = uniforms_src[ u ][ p ]; - - if ( parameter_src && ( parameter_src.isColor || - parameter_src.isMatrix3 || parameter_src.isMatrix4 || - parameter_src.isVector2 || parameter_src.isVector3 || parameter_src.isVector4 || - parameter_src.isTexture ) ) { - - uniforms_dst[ u ][ p ] = parameter_src.clone(); - - } else if ( Array.isArray( parameter_src ) ) { - - uniforms_dst[ u ][ p ] = parameter_src.slice(); - - } else { - - uniforms_dst[ u ][ p ] = parameter_src; - - } - - } - - } - - return uniforms_dst; - - } - - }; - - function ShaderMaterial( parameters ) { - - Material.call( this ); - - this.type = 'ShaderMaterial'; - - this.defines = {}; - this.uniforms = {}; - - this.vertexShader = 'void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}'; - this.fragmentShader = 'void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}'; - - this.linewidth = 1; - - this.wireframe = false; - this.wireframeLinewidth = 1; - - this.fog = false; // set to use scene fog - this.lights = false; // set to use scene lights - this.clipping = false; // set to use user-defined clipping planes - - this.skinning = false; // set to use skinning attribute streams - this.morphTargets = false; // set to use morph targets - this.morphNormals = false; // set to use morph normals - - this.extensions = { - derivatives: false, // set to use derivatives - fragDepth: false, // set to use fragment depth values - drawBuffers: false, // set to use draw buffers - shaderTextureLOD: false // set to use shader texture LOD - }; - - // When rendered geometry doesn't include these attributes but the material does, - // use these default values in WebGL. This avoids errors when buffer data is missing. - this.defaultAttributeValues = { - 'color': [ 1, 1, 1 ], - 'uv': [ 0, 0 ], - 'uv2': [ 0, 0 ] - }; - - this.index0AttributeName = undefined; - - if ( parameters !== undefined ) { - - if ( parameters.attributes !== undefined ) { - - console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' ); - - } - - this.setValues( parameters ); - - } - - } - - ShaderMaterial.prototype = Object.create( Material.prototype ); - ShaderMaterial.prototype.constructor = ShaderMaterial; - - ShaderMaterial.prototype.isShaderMaterial = true; - - ShaderMaterial.prototype.copy = function ( source ) { - - Material.prototype.copy.call( this, source ); - - this.fragmentShader = source.fragmentShader; - this.vertexShader = source.vertexShader; - - this.uniforms = UniformsUtils.clone( source.uniforms ); - - this.defines = source.defines; - - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; - - this.lights = source.lights; - this.clipping = source.clipping; - - this.skinning = source.skinning; - - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; - - this.extensions = source.extensions; - - return this; - - }; - - ShaderMaterial.prototype.toJSON = function ( meta ) { - - var data = Material.prototype.toJSON.call( this, meta ); - - data.uniforms = this.uniforms; - data.vertexShader = this.vertexShader; - data.fragmentShader = this.fragmentShader; - - return data; - - }; - - function RawShaderMaterial( parameters ) { - - ShaderMaterial.call( this, parameters ); - - this.type = 'RawShaderMaterial'; - - } - - RawShaderMaterial.prototype = Object.create( ShaderMaterial.prototype ); - RawShaderMaterial.prototype.constructor = RawShaderMaterial; - - RawShaderMaterial.prototype.isRawShaderMaterial = true; - - function PointsMaterial( parameters ) { - - Material.call( this ); - - this.type = 'PointsMaterial'; - - this.color = new Color( 0xffffff ); - - this.map = null; - - this.size = 1; - this.sizeAttenuation = true; - - this.lights = false; - - this.setValues( parameters ); - - } - - PointsMaterial.prototype = Object.create( Material.prototype ); - PointsMaterial.prototype.constructor = PointsMaterial; - - PointsMaterial.prototype.isPointsMaterial = true; - - PointsMaterial.prototype.copy = function ( source ) { - - Material.prototype.copy.call( this, source ); - - this.color.copy( source.color ); - - this.map = source.map; - - this.size = source.size; - this.sizeAttenuation = source.sizeAttenuation; - - return this; - - }; - - function MeshStandardMaterial( parameters ) { - - Material.call( this ); - - this.defines = { 'STANDARD': '' }; - - this.type = 'MeshStandardMaterial'; - - this.color = new Color( 0xffffff ); // diffuse - this.roughness = 0.5; - this.metalness = 0.5; - - this.map = null; - - this.lightMap = null; - this.lightMapIntensity = 1.0; - - this.aoMap = null; - this.aoMapIntensity = 1.0; - - this.emissive = new Color( 0x000000 ); - this.emissiveIntensity = 1.0; - this.emissiveMap = null; - - this.bumpMap = null; - this.bumpScale = 1; - - this.normalMap = null; - this.normalScale = new Vector2( 1, 1 ); - - this.displacementMap = null; - this.displacementScale = 1; - this.displacementBias = 0; - - this.roughnessMap = null; - - this.metalnessMap = null; - - this.alphaMap = null; - - this.envMap = null; - this.envMapIntensity = 1.0; - - this.refractionRatio = 0.98; - - this.wireframe = false; - this.wireframeLinewidth = 1; - this.wireframeLinecap = 'round'; - this.wireframeLinejoin = 'round'; - - this.skinning = false; - this.morphTargets = false; - this.morphNormals = false; - - this.setValues( parameters ); - - } - - MeshStandardMaterial.prototype = Object.create( Material.prototype ); - MeshStandardMaterial.prototype.constructor = MeshStandardMaterial; - - MeshStandardMaterial.prototype.isMeshStandardMaterial = true; - - MeshStandardMaterial.prototype.copy = function ( source ) { - - Material.prototype.copy.call( this, source ); - - this.defines = { 'STANDARD': '' }; - - this.color.copy( source.color ); - this.roughness = source.roughness; - this.metalness = source.metalness; - - this.map = source.map; - - this.lightMap = source.lightMap; - this.lightMapIntensity = source.lightMapIntensity; - - this.aoMap = source.aoMap; - this.aoMapIntensity = source.aoMapIntensity; - - this.emissive.copy( source.emissive ); - this.emissiveMap = source.emissiveMap; - this.emissiveIntensity = source.emissiveIntensity; - - this.bumpMap = source.bumpMap; - this.bumpScale = source.bumpScale; - - this.normalMap = source.normalMap; - this.normalScale.copy( source.normalScale ); - - this.displacementMap = source.displacementMap; - this.displacementScale = source.displacementScale; - this.displacementBias = source.displacementBias; - - this.roughnessMap = source.roughnessMap; - - this.metalnessMap = source.metalnessMap; - - this.alphaMap = source.alphaMap; - - this.envMap = source.envMap; - this.envMapIntensity = source.envMapIntensity; - - this.refractionRatio = source.refractionRatio; - - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; - this.wireframeLinecap = source.wireframeLinecap; - this.wireframeLinejoin = source.wireframeLinejoin; - - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; - - return this; - - }; - - function MeshPhysicalMaterial( parameters ) { - - MeshStandardMaterial.call( this ); - - this.defines = { 'PHYSICAL': '' }; - - this.type = 'MeshPhysicalMaterial'; - - this.reflectivity = 0.5; // maps to F0 = 0.04 - - this.clearCoat = 0.0; - this.clearCoatRoughness = 0.0; - - this.setValues( parameters ); - - } - - MeshPhysicalMaterial.prototype = Object.create( MeshStandardMaterial.prototype ); - MeshPhysicalMaterial.prototype.constructor = MeshPhysicalMaterial; - - MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true; - - MeshPhysicalMaterial.prototype.copy = function ( source ) { - - MeshStandardMaterial.prototype.copy.call( this, source ); - - this.defines = { 'PHYSICAL': '' }; - - this.reflectivity = source.reflectivity; - - this.clearCoat = source.clearCoat; - this.clearCoatRoughness = source.clearCoatRoughness; - - return this; - - }; - - function MeshPhongMaterial( parameters ) { - - Material.call( this ); - - this.type = 'MeshPhongMaterial'; - - this.color = new Color( 0xffffff ); // diffuse - this.specular = new Color( 0x111111 ); - this.shininess = 30; - - this.map = null; - - this.lightMap = null; - this.lightMapIntensity = 1.0; - - this.aoMap = null; - this.aoMapIntensity = 1.0; - - this.emissive = new Color( 0x000000 ); - this.emissiveIntensity = 1.0; - this.emissiveMap = null; - - this.bumpMap = null; - this.bumpScale = 1; - - this.normalMap = null; - this.normalScale = new Vector2( 1, 1 ); - - this.displacementMap = null; - this.displacementScale = 1; - this.displacementBias = 0; - - this.specularMap = null; - - this.alphaMap = null; - - this.envMap = null; - this.combine = MultiplyOperation; - this.reflectivity = 1; - this.refractionRatio = 0.98; - - this.wireframe = false; - this.wireframeLinewidth = 1; - this.wireframeLinecap = 'round'; - this.wireframeLinejoin = 'round'; - - this.skinning = false; - this.morphTargets = false; - this.morphNormals = false; - - this.setValues( parameters ); - - } - - MeshPhongMaterial.prototype = Object.create( Material.prototype ); - MeshPhongMaterial.prototype.constructor = MeshPhongMaterial; - - MeshPhongMaterial.prototype.isMeshPhongMaterial = true; - - MeshPhongMaterial.prototype.copy = function ( source ) { - - Material.prototype.copy.call( this, source ); - - this.color.copy( source.color ); - this.specular.copy( source.specular ); - this.shininess = source.shininess; - - this.map = source.map; - - this.lightMap = source.lightMap; - this.lightMapIntensity = source.lightMapIntensity; - - this.aoMap = source.aoMap; - this.aoMapIntensity = source.aoMapIntensity; - - this.emissive.copy( source.emissive ); - this.emissiveMap = source.emissiveMap; - this.emissiveIntensity = source.emissiveIntensity; - - this.bumpMap = source.bumpMap; - this.bumpScale = source.bumpScale; - - this.normalMap = source.normalMap; - this.normalScale.copy( source.normalScale ); - - this.displacementMap = source.displacementMap; - this.displacementScale = source.displacementScale; - this.displacementBias = source.displacementBias; - - this.specularMap = source.specularMap; - - this.alphaMap = source.alphaMap; - - this.envMap = source.envMap; - this.combine = source.combine; - this.reflectivity = source.reflectivity; - this.refractionRatio = source.refractionRatio; - - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; - this.wireframeLinecap = source.wireframeLinecap; - this.wireframeLinejoin = source.wireframeLinejoin; - - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; - - return this; - - }; - - function MeshToonMaterial( parameters ) { - - MeshPhongMaterial.call( this ); - - this.defines = { 'TOON': '' }; - - this.type = 'MeshToonMaterial'; - - this.gradientMap = null; - - this.setValues( parameters ); - - } - - MeshToonMaterial.prototype = Object.create( MeshPhongMaterial.prototype ); - MeshToonMaterial.prototype.constructor = MeshToonMaterial; - - MeshToonMaterial.prototype.isMeshToonMaterial = true; - - MeshToonMaterial.prototype.copy = function ( source ) { - - MeshPhongMaterial.prototype.copy.call( this, source ); - - this.gradientMap = source.gradientMap; - - return this; - - }; - - function MeshNormalMaterial( parameters ) { - - Material.call( this ); - - this.type = 'MeshNormalMaterial'; - - this.bumpMap = null; - this.bumpScale = 1; - - this.normalMap = null; - this.normalScale = new Vector2( 1, 1 ); - - this.displacementMap = null; - this.displacementScale = 1; - this.displacementBias = 0; - - this.wireframe = false; - this.wireframeLinewidth = 1; - - this.fog = false; - this.lights = false; - - this.skinning = false; - this.morphTargets = false; - this.morphNormals = false; - - this.setValues( parameters ); - - } - - MeshNormalMaterial.prototype = Object.create( Material.prototype ); - MeshNormalMaterial.prototype.constructor = MeshNormalMaterial; - - MeshNormalMaterial.prototype.isMeshNormalMaterial = true; - - MeshNormalMaterial.prototype.copy = function ( source ) { - - Material.prototype.copy.call( this, source ); - - this.bumpMap = source.bumpMap; - this.bumpScale = source.bumpScale; - - this.normalMap = source.normalMap; - this.normalScale.copy( source.normalScale ); - - this.displacementMap = source.displacementMap; - this.displacementScale = source.displacementScale; - this.displacementBias = source.displacementBias; - - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; - - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; - - return this; - - }; - - function MeshLambertMaterial( parameters ) { - - Material.call( this ); - - this.type = 'MeshLambertMaterial'; - - this.color = new Color( 0xffffff ); // diffuse - - this.map = null; - - this.lightMap = null; - this.lightMapIntensity = 1.0; - - this.aoMap = null; - this.aoMapIntensity = 1.0; - - this.emissive = new Color( 0x000000 ); - this.emissiveIntensity = 1.0; - this.emissiveMap = null; - - this.specularMap = null; - - this.alphaMap = null; - - this.envMap = null; - this.combine = MultiplyOperation; - this.reflectivity = 1; - this.refractionRatio = 0.98; - - this.wireframe = false; - this.wireframeLinewidth = 1; - this.wireframeLinecap = 'round'; - this.wireframeLinejoin = 'round'; - - this.skinning = false; - this.morphTargets = false; - this.morphNormals = false; - - this.setValues( parameters ); - - } - - MeshLambertMaterial.prototype = Object.create( Material.prototype ); - MeshLambertMaterial.prototype.constructor = MeshLambertMaterial; - - MeshLambertMaterial.prototype.isMeshLambertMaterial = true; - - MeshLambertMaterial.prototype.copy = function ( source ) { - - Material.prototype.copy.call( this, source ); - - this.color.copy( source.color ); - - this.map = source.map; - - this.lightMap = source.lightMap; - this.lightMapIntensity = source.lightMapIntensity; - - this.aoMap = source.aoMap; - this.aoMapIntensity = source.aoMapIntensity; - - this.emissive.copy( source.emissive ); - this.emissiveMap = source.emissiveMap; - this.emissiveIntensity = source.emissiveIntensity; - - this.specularMap = source.specularMap; - - this.alphaMap = source.alphaMap; - - this.envMap = source.envMap; - this.combine = source.combine; - this.reflectivity = source.reflectivity; - this.refractionRatio = source.refractionRatio; - - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; - this.wireframeLinecap = source.wireframeLinecap; - this.wireframeLinejoin = source.wireframeLinejoin; - - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - this.morphNormals = source.morphNormals; - - return this; - - }; - - function MeshDepthMaterial( parameters ) { - - Material.call( this ); - - this.type = 'MeshDepthMaterial'; - - this.depthPacking = BasicDepthPacking; - - this.skinning = false; - this.morphTargets = false; - - this.map = null; - - this.alphaMap = null; - - this.displacementMap = null; - this.displacementScale = 1; - this.displacementBias = 0; - - this.wireframe = false; - this.wireframeLinewidth = 1; - - this.fog = false; - this.lights = false; - - this.setValues( parameters ); - - } - - MeshDepthMaterial.prototype = Object.create( Material.prototype ); - MeshDepthMaterial.prototype.constructor = MeshDepthMaterial; - - MeshDepthMaterial.prototype.isMeshDepthMaterial = true; - - MeshDepthMaterial.prototype.copy = function ( source ) { - - Material.prototype.copy.call( this, source ); - - this.depthPacking = source.depthPacking; - - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - - this.map = source.map; - - this.alphaMap = source.alphaMap; - - this.displacementMap = source.displacementMap; - this.displacementScale = source.displacementScale; - this.displacementBias = source.displacementBias; - - this.wireframe = source.wireframe; - this.wireframeLinewidth = source.wireframeLinewidth; - - return this; - - }; - - function MeshDistanceMaterial( parameters ) { - - Material.call( this ); - - this.type = 'MeshDistanceMaterial'; - - this.referencePosition = new Vector3(); - this.nearDistance = 1; - this.farDistance = 1000; - - this.skinning = false; - this.morphTargets = false; - - this.map = null; - - this.alphaMap = null; - - this.displacementMap = null; - this.displacementScale = 1; - this.displacementBias = 0; - - this.fog = false; - this.lights = false; - - this.setValues( parameters ); - - } - - MeshDistanceMaterial.prototype = Object.create( Material.prototype ); - MeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial; - - MeshDistanceMaterial.prototype.isMeshDistanceMaterial = true; - - MeshDistanceMaterial.prototype.copy = function ( source ) { - - Material.prototype.copy.call( this, source ); - - this.referencePosition.copy( source.referencePosition ); - this.nearDistance = source.nearDistance; - this.farDistance = source.farDistance; - - this.skinning = source.skinning; - this.morphTargets = source.morphTargets; - - this.map = source.map; - - this.alphaMap = source.alphaMap; - - this.displacementMap = source.displacementMap; - this.displacementScale = source.displacementScale; - this.displacementBias = source.displacementBias; - - return this; - - }; - - function LineBasicMaterial( parameters ) { - - Material.call( this ); - - this.type = 'LineBasicMaterial'; - - this.color = new Color( 0xffffff ); - - this.linewidth = 1; - this.linecap = 'round'; - this.linejoin = 'round'; - - this.lights = false; - - this.setValues( parameters ); - - } - - LineBasicMaterial.prototype = Object.create( Material.prototype ); - LineBasicMaterial.prototype.constructor = LineBasicMaterial; - - LineBasicMaterial.prototype.isLineBasicMaterial = true; - - LineBasicMaterial.prototype.copy = function ( source ) { - - Material.prototype.copy.call( this, source ); - - this.color.copy( source.color ); - - this.linewidth = source.linewidth; - this.linecap = source.linecap; - this.linejoin = source.linejoin; - - return this; - - }; - - /** - * @author alteredq / http://alteredqualia.com/ - * - * parameters = { - * color: , - * opacity: , - * - * linewidth: , - * - * scale: , - * dashSize: , - * gapSize: - * } - */ - - function LineDashedMaterial( parameters ) { - - LineBasicMaterial.call( this ); - - this.type = 'LineDashedMaterial'; - - this.scale = 1; - this.dashSize = 3; - this.gapSize = 1; - - this.setValues( parameters ); - - } - - LineDashedMaterial.prototype = Object.create( LineBasicMaterial.prototype ); - LineDashedMaterial.prototype.constructor = LineDashedMaterial; - - LineDashedMaterial.prototype.isLineDashedMaterial = true; - - LineDashedMaterial.prototype.copy = function ( source ) { - - LineBasicMaterial.prototype.copy.call( this, source ); - - this.scale = source.scale; - this.dashSize = source.dashSize; - this.gapSize = source.gapSize; - - return this; - - }; - - - - var Materials = Object.freeze({ - ShadowMaterial: ShadowMaterial, - SpriteMaterial: SpriteMaterial, - RawShaderMaterial: RawShaderMaterial, - ShaderMaterial: ShaderMaterial, - PointsMaterial: PointsMaterial, - MeshPhysicalMaterial: MeshPhysicalMaterial, - MeshStandardMaterial: MeshStandardMaterial, - MeshPhongMaterial: MeshPhongMaterial, - MeshToonMaterial: MeshToonMaterial, - MeshNormalMaterial: MeshNormalMaterial, - MeshLambertMaterial: MeshLambertMaterial, - MeshDepthMaterial: MeshDepthMaterial, - MeshDistanceMaterial: MeshDistanceMaterial, - MeshBasicMaterial: MeshBasicMaterial, - LineDashedMaterial: LineDashedMaterial, - LineBasicMaterial: LineBasicMaterial, - Material: Material - }); - - function MaterialLoader( manager ) { - - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - this.textures = {}; - - } - - Object.assign( MaterialLoader.prototype, { - - load: function ( url, onLoad, onProgress, onError ) { - - var scope = this; - - var loader = new FileLoader( scope.manager ); - loader.load( url, function ( text ) { - - onLoad( scope.parse( JSON.parse( text ) ) ); - - }, onProgress, onError ); - - }, - - setTextures: function ( value ) { - - this.textures = value; - - }, - - parse: function ( json ) { - - var textures = this.textures; - - function getTexture( name ) { - - if ( textures[ name ] === undefined ) { - - console.warn( 'THREE.MaterialLoader: Undefined texture', name ); - - } - - return textures[ name ]; - - } - - var material = new Materials[ json.type ](); - - if ( json.uuid !== undefined ) material.uuid = json.uuid; - if ( json.name !== undefined ) material.name = json.name; - if ( json.color !== undefined ) material.color.setHex( json.color ); - if ( json.roughness !== undefined ) material.roughness = json.roughness; - if ( json.metalness !== undefined ) material.metalness = json.metalness; - if ( json.emissive !== undefined ) material.emissive.setHex( json.emissive ); - if ( json.specular !== undefined ) material.specular.setHex( json.specular ); - if ( json.shininess !== undefined ) material.shininess = json.shininess; - if ( json.clearCoat !== undefined ) material.clearCoat = json.clearCoat; - if ( json.clearCoatRoughness !== undefined ) material.clearCoatRoughness = json.clearCoatRoughness; - if ( json.uniforms !== undefined ) material.uniforms = json.uniforms; - if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader; - if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader; - if ( json.vertexColors !== undefined ) material.vertexColors = json.vertexColors; - if ( json.fog !== undefined ) material.fog = json.fog; - if ( json.flatShading !== undefined ) material.flatShading = json.flatShading; - if ( json.blending !== undefined ) material.blending = json.blending; - if ( json.side !== undefined ) material.side = json.side; - if ( json.opacity !== undefined ) material.opacity = json.opacity; - if ( json.transparent !== undefined ) material.transparent = json.transparent; - if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest; - if ( json.depthTest !== undefined ) material.depthTest = json.depthTest; - if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite; - if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite; - if ( json.wireframe !== undefined ) material.wireframe = json.wireframe; - if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth; - if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap; - if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin; - - if ( json.rotation !== undefined ) material.rotation = json.rotation; - - if ( json.linewidth !== 1 ) material.linewidth = json.linewidth; - if ( json.dashSize !== undefined ) material.dashSize = json.dashSize; - if ( json.gapSize !== undefined ) material.gapSize = json.gapSize; - if ( json.scale !== undefined ) material.scale = json.scale; - - if ( json.skinning !== undefined ) material.skinning = json.skinning; - if ( json.morphTargets !== undefined ) material.morphTargets = json.morphTargets; - if ( json.dithering !== undefined ) material.dithering = json.dithering; - - if ( json.visible !== undefined ) material.visible = json.visible; - if ( json.userData !== undefined ) material.userData = json.userData; - - // Deprecated - - if ( json.shading !== undefined ) material.flatShading = json.shading === 1; // THREE.FlatShading - - // for PointsMaterial - - if ( json.size !== undefined ) material.size = json.size; - if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation; - - // maps - - if ( json.map !== undefined ) material.map = getTexture( json.map ); - - if ( json.alphaMap !== undefined ) { - - material.alphaMap = getTexture( json.alphaMap ); - material.transparent = true; - - } - - if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap ); - if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale; - - if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap ); - if ( json.normalScale !== undefined ) { - - var normalScale = json.normalScale; - - if ( Array.isArray( normalScale ) === false ) { - - // Blender exporter used to export a scalar. See #7459 - - normalScale = [ normalScale, normalScale ]; - - } - - material.normalScale = new Vector2().fromArray( normalScale ); - - } - - if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap ); - if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale; - if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias; - - if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap ); - if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap ); - - if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap ); - if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity; - - if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap ); - - if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap ); - - if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity; - - if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap ); - if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity; - - if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap ); - if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity; - - if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap ); - - return material; - - } - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function ImageLoader( manager ) { - - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - - } - - Object.assign( ImageLoader.prototype, { - - crossOrigin: 'Anonymous', - - load: function ( url, onLoad, onProgress, onError ) { - - if ( url === undefined ) url = ''; - - if ( this.path !== undefined ) url = this.path + url; - - url = this.manager.resolveURL( url ); - - var scope = this; - - var cached = Cache.get( url ); - - if ( cached !== undefined ) { - - scope.manager.itemStart( url ); - - setTimeout( function () { - - if ( onLoad ) onLoad( cached ); - - scope.manager.itemEnd( url ); - - }, 0 ); - - return cached; - - } - - var image = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'img' ); - - image.addEventListener( 'load', function () { - - Cache.add( url, this ); - - if ( onLoad ) onLoad( this ); - - scope.manager.itemEnd( url ); - - }, false ); - - /* - image.addEventListener( 'progress', function ( event ) { - - if ( onProgress ) onProgress( event ); - - }, false ); - */ - - image.addEventListener( 'error', function ( event ) { - - if ( onError ) onError( event ); - - scope.manager.itemEnd( url ); - scope.manager.itemError( url ); - - }, false ); - - if ( url.substr( 0, 5 ) !== 'data:' ) { - - if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin; - - } - - scope.manager.itemStart( url ); - - image.src = url; - - return image; - - }, - - setCrossOrigin: function ( value ) { - - this.crossOrigin = value; - return this; - - }, - - setPath: function ( value ) { - - this.path = value; - return this; - - } - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function TextureLoader( manager ) { - - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - - } - - Object.assign( TextureLoader.prototype, { - - crossOrigin: 'Anonymous', - - load: function ( url, onLoad, onProgress, onError ) { - - var loader = new ImageLoader( this.manager ); - loader.setCrossOrigin( this.crossOrigin ); - loader.setPath( this.path ); - - var texture = new Texture(); - texture.image = loader.load( url, function () { - - // JPEGs can't have an alpha channel, so memory can be saved by storing them as RGB. - var isJPEG = url.search( /\.(jpg|jpeg)$/ ) > 0 || url.search( /^data\:image\/jpeg/ ) === 0; - - texture.format = isJPEG ? RGBFormat : RGBAFormat; - texture.needsUpdate = true; - - if ( onLoad !== undefined ) { - - onLoad( texture ); - - } - - }, onProgress, onError ); - - return texture; - - }, - - setCrossOrigin: function ( value ) { - - this.crossOrigin = value; - return this; - - }, - - setPath: function ( value ) { - - this.path = value; - return this; - - } - - } ); - - function Loader() { - - this.onLoadStart = function () {}; - this.onLoadProgress = function () {}; - this.onLoadComplete = function () {}; - - } - - Loader.Handlers = { - - handlers: [], - - add: function ( regex, loader ) { - - this.handlers.push( regex, loader ); - - }, - - get: function ( file ) { - - var handlers = this.handlers; - - for ( var i = 0, l = handlers.length; i < l; i += 2 ) { - - var regex = handlers[ i ]; - var loader = handlers[ i + 1 ]; - - if ( regex.test( file ) ) { - - return loader; - - } - - } - - return null; - - } - - }; - - Object.assign( Loader.prototype, { - - crossOrigin: undefined, - - extractUrlBase: function ( url ) { - - var parts = url.split( '/' ); - - if ( parts.length === 1 ) return './'; - - parts.pop(); - - return parts.join( '/' ) + '/'; - - }, - - initMaterials: function ( materials, texturePath, crossOrigin ) { - - var array = []; - - for ( var i = 0; i < materials.length; ++ i ) { - - array[ i ] = this.createMaterial( materials[ i ], texturePath, crossOrigin ); - - } - - return array; - - }, - - createMaterial: ( function () { - - var BlendingMode = { - NoBlending: NoBlending, - NormalBlending: NormalBlending, - AdditiveBlending: AdditiveBlending, - SubtractiveBlending: SubtractiveBlending, - MultiplyBlending: MultiplyBlending, - CustomBlending: CustomBlending - }; - - var color = new Color(); - var textureLoader = new TextureLoader(); - var materialLoader = new MaterialLoader(); - - return function createMaterial( m, texturePath, crossOrigin ) { - - // convert from old material format - - var textures = {}; - - function loadTexture( path, repeat, offset, wrap, anisotropy ) { - - var fullPath = texturePath + path; - var loader = Loader.Handlers.get( fullPath ); - - var texture; - - if ( loader !== null ) { - - texture = loader.load( fullPath ); - - } else { - - textureLoader.setCrossOrigin( crossOrigin ); - texture = textureLoader.load( fullPath ); - - } - - if ( repeat !== undefined ) { - - texture.repeat.fromArray( repeat ); - - if ( repeat[ 0 ] !== 1 ) texture.wrapS = RepeatWrapping; - if ( repeat[ 1 ] !== 1 ) texture.wrapT = RepeatWrapping; - - } - - if ( offset !== undefined ) { - - texture.offset.fromArray( offset ); - - } - - if ( wrap !== undefined ) { - - if ( wrap[ 0 ] === 'repeat' ) texture.wrapS = RepeatWrapping; - if ( wrap[ 0 ] === 'mirror' ) texture.wrapS = MirroredRepeatWrapping; - - if ( wrap[ 1 ] === 'repeat' ) texture.wrapT = RepeatWrapping; - if ( wrap[ 1 ] === 'mirror' ) texture.wrapT = MirroredRepeatWrapping; - - } - - if ( anisotropy !== undefined ) { - - texture.anisotropy = anisotropy; - - } - - var uuid = _Math.generateUUID(); - - textures[ uuid ] = texture; - - return uuid; - - } - - // - - var json = { - uuid: _Math.generateUUID(), - type: 'MeshLambertMaterial' - }; - - for ( var name in m ) { - - var value = m[ name ]; - - switch ( name ) { - - case 'DbgColor': - case 'DbgIndex': - case 'opticalDensity': - case 'illumination': - break; - case 'DbgName': - json.name = value; - break; - case 'blending': - json.blending = BlendingMode[ value ]; - break; - case 'colorAmbient': - case 'mapAmbient': - console.warn( 'THREE.Loader.createMaterial:', name, 'is no longer supported.' ); - break; - case 'colorDiffuse': - json.color = color.fromArray( value ).getHex(); - break; - case 'colorSpecular': - json.specular = color.fromArray( value ).getHex(); - break; - case 'colorEmissive': - json.emissive = color.fromArray( value ).getHex(); - break; - case 'specularCoef': - json.shininess = value; - break; - case 'shading': - if ( value.toLowerCase() === 'basic' ) json.type = 'MeshBasicMaterial'; - if ( value.toLowerCase() === 'phong' ) json.type = 'MeshPhongMaterial'; - if ( value.toLowerCase() === 'standard' ) json.type = 'MeshStandardMaterial'; - break; - case 'mapDiffuse': - json.map = loadTexture( value, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap, m.mapDiffuseAnisotropy ); - break; - case 'mapDiffuseRepeat': - case 'mapDiffuseOffset': - case 'mapDiffuseWrap': - case 'mapDiffuseAnisotropy': - break; - case 'mapEmissive': - json.emissiveMap = loadTexture( value, m.mapEmissiveRepeat, m.mapEmissiveOffset, m.mapEmissiveWrap, m.mapEmissiveAnisotropy ); - break; - case 'mapEmissiveRepeat': - case 'mapEmissiveOffset': - case 'mapEmissiveWrap': - case 'mapEmissiveAnisotropy': - break; - case 'mapLight': - json.lightMap = loadTexture( value, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap, m.mapLightAnisotropy ); - break; - case 'mapLightRepeat': - case 'mapLightOffset': - case 'mapLightWrap': - case 'mapLightAnisotropy': - break; - case 'mapAO': - json.aoMap = loadTexture( value, m.mapAORepeat, m.mapAOOffset, m.mapAOWrap, m.mapAOAnisotropy ); - break; - case 'mapAORepeat': - case 'mapAOOffset': - case 'mapAOWrap': - case 'mapAOAnisotropy': - break; - case 'mapBump': - json.bumpMap = loadTexture( value, m.mapBumpRepeat, m.mapBumpOffset, m.mapBumpWrap, m.mapBumpAnisotropy ); - break; - case 'mapBumpScale': - json.bumpScale = value; - break; - case 'mapBumpRepeat': - case 'mapBumpOffset': - case 'mapBumpWrap': - case 'mapBumpAnisotropy': - break; - case 'mapNormal': - json.normalMap = loadTexture( value, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap, m.mapNormalAnisotropy ); - break; - case 'mapNormalFactor': - json.normalScale = [ value, value ]; - break; - case 'mapNormalRepeat': - case 'mapNormalOffset': - case 'mapNormalWrap': - case 'mapNormalAnisotropy': - break; - case 'mapSpecular': - json.specularMap = loadTexture( value, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap, m.mapSpecularAnisotropy ); - break; - case 'mapSpecularRepeat': - case 'mapSpecularOffset': - case 'mapSpecularWrap': - case 'mapSpecularAnisotropy': - break; - case 'mapMetalness': - json.metalnessMap = loadTexture( value, m.mapMetalnessRepeat, m.mapMetalnessOffset, m.mapMetalnessWrap, m.mapMetalnessAnisotropy ); - break; - case 'mapMetalnessRepeat': - case 'mapMetalnessOffset': - case 'mapMetalnessWrap': - case 'mapMetalnessAnisotropy': - break; - case 'mapRoughness': - json.roughnessMap = loadTexture( value, m.mapRoughnessRepeat, m.mapRoughnessOffset, m.mapRoughnessWrap, m.mapRoughnessAnisotropy ); - break; - case 'mapRoughnessRepeat': - case 'mapRoughnessOffset': - case 'mapRoughnessWrap': - case 'mapRoughnessAnisotropy': - break; - case 'mapAlpha': - json.alphaMap = loadTexture( value, m.mapAlphaRepeat, m.mapAlphaOffset, m.mapAlphaWrap, m.mapAlphaAnisotropy ); - break; - case 'mapAlphaRepeat': - case 'mapAlphaOffset': - case 'mapAlphaWrap': - case 'mapAlphaAnisotropy': - break; - case 'flipSided': - json.side = BackSide; - break; - case 'doubleSided': - json.side = DoubleSide; - break; - case 'transparency': - console.warn( 'THREE.Loader.createMaterial: transparency has been renamed to opacity' ); - json.opacity = value; - break; - case 'depthTest': - case 'depthWrite': - case 'colorWrite': - case 'opacity': - case 'reflectivity': - case 'transparent': - case 'visible': - case 'wireframe': - json[ name ] = value; - break; - case 'vertexColors': - if ( value === true ) json.vertexColors = VertexColors; - if ( value === 'face' ) json.vertexColors = FaceColors; - break; - default: - console.error( 'THREE.Loader.createMaterial: Unsupported', name, value ); - break; - - } - - } - - if ( json.type === 'MeshBasicMaterial' ) delete json.emissive; - if ( json.type !== 'MeshPhongMaterial' ) delete json.specular; - - if ( json.opacity < 1 ) json.transparent = true; - - materialLoader.setTextures( textures ); - - return materialLoader.parse( json ); - - }; - - } )() - - } ); - - function JSONLoader( manager ) { - - if ( typeof manager === 'boolean' ) { - - console.warn( 'THREE.JSONLoader: showStatus parameter has been removed from constructor.' ); - manager = undefined; - - } - - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - - this.withCredentials = false; - - } - - Object.assign( JSONLoader.prototype, { - - load: function ( url, onLoad, onProgress, onError ) { - - var scope = this; - - var texturePath = this.texturePath && ( typeof this.texturePath === "string" ) ? this.texturePath : Loader.prototype.extractUrlBase( url ); - - var loader = new FileLoader( this.manager ); - loader.setWithCredentials( this.withCredentials ); - loader.load( url, function ( text ) { - - var json = JSON.parse( text ); - var metadata = json.metadata; - - if ( metadata !== undefined ) { - - var type = metadata.type; - - if ( type !== undefined ) { - - if ( type.toLowerCase() === 'object' ) { - - console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.ObjectLoader instead.' ); - return; - - } - - if ( type.toLowerCase() === 'scene' ) { - - console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.SceneLoader instead.' ); - return; - - } - - } - - } - - var object = scope.parse( json, texturePath ); - onLoad( object.geometry, object.materials ); - - }, onProgress, onError ); - - }, - - setTexturePath: function ( value ) { - - this.texturePath = value; - - }, - - parse: ( function () { - - function parseModel( json, geometry ) { - - function isBitSet( value, position ) { - - return value & ( 1 << position ); - - } - - var i, j, fi, - - offset, zLength, - - colorIndex, normalIndex, uvIndex, materialIndex, - - type, - isQuad, - hasMaterial, - hasFaceVertexUv, - hasFaceNormal, hasFaceVertexNormal, - hasFaceColor, hasFaceVertexColor, - - vertex, face, faceA, faceB, hex, normal, - - uvLayer, uv, u, v, - - faces = json.faces, - vertices = json.vertices, - normals = json.normals, - colors = json.colors, - - scale = json.scale, - - nUvLayers = 0; - - - if ( json.uvs !== undefined ) { - - // disregard empty arrays - - for ( i = 0; i < json.uvs.length; i ++ ) { - - if ( json.uvs[ i ].length ) nUvLayers ++; - - } - - for ( i = 0; i < nUvLayers; i ++ ) { - - geometry.faceVertexUvs[ i ] = []; - - } - - } - - offset = 0; - zLength = vertices.length; - - while ( offset < zLength ) { - - vertex = new Vector3(); - - vertex.x = vertices[ offset ++ ] * scale; - vertex.y = vertices[ offset ++ ] * scale; - vertex.z = vertices[ offset ++ ] * scale; - - geometry.vertices.push( vertex ); - - } - - offset = 0; - zLength = faces.length; - - while ( offset < zLength ) { - - type = faces[ offset ++ ]; - - isQuad = isBitSet( type, 0 ); - hasMaterial = isBitSet( type, 1 ); - hasFaceVertexUv = isBitSet( type, 3 ); - hasFaceNormal = isBitSet( type, 4 ); - hasFaceVertexNormal = isBitSet( type, 5 ); - hasFaceColor = isBitSet( type, 6 ); - hasFaceVertexColor = isBitSet( type, 7 ); - - // console.log("type", type, "bits", isQuad, hasMaterial, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor); - - if ( isQuad ) { - - faceA = new Face3(); - faceA.a = faces[ offset ]; - faceA.b = faces[ offset + 1 ]; - faceA.c = faces[ offset + 3 ]; - - faceB = new Face3(); - faceB.a = faces[ offset + 1 ]; - faceB.b = faces[ offset + 2 ]; - faceB.c = faces[ offset + 3 ]; - - offset += 4; - - if ( hasMaterial ) { - - materialIndex = faces[ offset ++ ]; - faceA.materialIndex = materialIndex; - faceB.materialIndex = materialIndex; - - } - - // to get face <=> uv index correspondence - - fi = geometry.faces.length; - - if ( hasFaceVertexUv ) { - - for ( i = 0; i < nUvLayers; i ++ ) { - - uvLayer = json.uvs[ i ]; - - geometry.faceVertexUvs[ i ][ fi ] = []; - geometry.faceVertexUvs[ i ][ fi + 1 ] = []; - - for ( j = 0; j < 4; j ++ ) { - - uvIndex = faces[ offset ++ ]; - - u = uvLayer[ uvIndex * 2 ]; - v = uvLayer[ uvIndex * 2 + 1 ]; - - uv = new Vector2( u, v ); - - if ( j !== 2 ) geometry.faceVertexUvs[ i ][ fi ].push( uv ); - if ( j !== 0 ) geometry.faceVertexUvs[ i ][ fi + 1 ].push( uv ); - - } - - } - - } - - if ( hasFaceNormal ) { - - normalIndex = faces[ offset ++ ] * 3; - - faceA.normal.set( - normals[ normalIndex ++ ], - normals[ normalIndex ++ ], - normals[ normalIndex ] - ); - - faceB.normal.copy( faceA.normal ); - - } - - if ( hasFaceVertexNormal ) { - - for ( i = 0; i < 4; i ++ ) { - - normalIndex = faces[ offset ++ ] * 3; - - normal = new Vector3( - normals[ normalIndex ++ ], - normals[ normalIndex ++ ], - normals[ normalIndex ] - ); - - - if ( i !== 2 ) faceA.vertexNormals.push( normal ); - if ( i !== 0 ) faceB.vertexNormals.push( normal ); - - } - - } - - - if ( hasFaceColor ) { - - colorIndex = faces[ offset ++ ]; - hex = colors[ colorIndex ]; - - faceA.color.setHex( hex ); - faceB.color.setHex( hex ); - - } - - - if ( hasFaceVertexColor ) { - - for ( i = 0; i < 4; i ++ ) { - - colorIndex = faces[ offset ++ ]; - hex = colors[ colorIndex ]; - - if ( i !== 2 ) faceA.vertexColors.push( new Color( hex ) ); - if ( i !== 0 ) faceB.vertexColors.push( new Color( hex ) ); - - } - - } - - geometry.faces.push( faceA ); - geometry.faces.push( faceB ); - - } else { - - face = new Face3(); - face.a = faces[ offset ++ ]; - face.b = faces[ offset ++ ]; - face.c = faces[ offset ++ ]; - - if ( hasMaterial ) { - - materialIndex = faces[ offset ++ ]; - face.materialIndex = materialIndex; - - } - - // to get face <=> uv index correspondence - - fi = geometry.faces.length; - - if ( hasFaceVertexUv ) { - - for ( i = 0; i < nUvLayers; i ++ ) { - - uvLayer = json.uvs[ i ]; - - geometry.faceVertexUvs[ i ][ fi ] = []; - - for ( j = 0; j < 3; j ++ ) { - - uvIndex = faces[ offset ++ ]; - - u = uvLayer[ uvIndex * 2 ]; - v = uvLayer[ uvIndex * 2 + 1 ]; - - uv = new Vector2( u, v ); - - geometry.faceVertexUvs[ i ][ fi ].push( uv ); - - } - - } - - } - - if ( hasFaceNormal ) { - - normalIndex = faces[ offset ++ ] * 3; - - face.normal.set( - normals[ normalIndex ++ ], - normals[ normalIndex ++ ], - normals[ normalIndex ] - ); - - } - - if ( hasFaceVertexNormal ) { - - for ( i = 0; i < 3; i ++ ) { - - normalIndex = faces[ offset ++ ] * 3; - - normal = new Vector3( - normals[ normalIndex ++ ], - normals[ normalIndex ++ ], - normals[ normalIndex ] - ); - - face.vertexNormals.push( normal ); - - } - - } - - - if ( hasFaceColor ) { - - colorIndex = faces[ offset ++ ]; - face.color.setHex( colors[ colorIndex ] ); - - } - - - if ( hasFaceVertexColor ) { - - for ( i = 0; i < 3; i ++ ) { - - colorIndex = faces[ offset ++ ]; - face.vertexColors.push( new Color( colors[ colorIndex ] ) ); - - } - - } - - geometry.faces.push( face ); - - } - - } - - } - - function parseSkin( json, geometry ) { - - var influencesPerVertex = ( json.influencesPerVertex !== undefined ) ? json.influencesPerVertex : 2; - - if ( json.skinWeights ) { - - for ( var i = 0, l = json.skinWeights.length; i < l; i += influencesPerVertex ) { - - var x = json.skinWeights[ i ]; - var y = ( influencesPerVertex > 1 ) ? json.skinWeights[ i + 1 ] : 0; - var z = ( influencesPerVertex > 2 ) ? json.skinWeights[ i + 2 ] : 0; - var w = ( influencesPerVertex > 3 ) ? json.skinWeights[ i + 3 ] : 0; - - geometry.skinWeights.push( new Vector4( x, y, z, w ) ); - - } - - } - - if ( json.skinIndices ) { - - for ( var i = 0, l = json.skinIndices.length; i < l; i += influencesPerVertex ) { - - var a = json.skinIndices[ i ]; - var b = ( influencesPerVertex > 1 ) ? json.skinIndices[ i + 1 ] : 0; - var c = ( influencesPerVertex > 2 ) ? json.skinIndices[ i + 2 ] : 0; - var d = ( influencesPerVertex > 3 ) ? json.skinIndices[ i + 3 ] : 0; - - geometry.skinIndices.push( new Vector4( a, b, c, d ) ); - - } - - } - - geometry.bones = json.bones; - - if ( geometry.bones && geometry.bones.length > 0 && ( geometry.skinWeights.length !== geometry.skinIndices.length || geometry.skinIndices.length !== geometry.vertices.length ) ) { - - console.warn( 'When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' + - geometry.skinIndices.length + '), and skinWeights (' + geometry.skinWeights.length + ') should match.' ); - - } - - } - - function parseMorphing( json, geometry ) { - - var scale = json.scale; - - if ( json.morphTargets !== undefined ) { - - for ( var i = 0, l = json.morphTargets.length; i < l; i ++ ) { - - geometry.morphTargets[ i ] = {}; - geometry.morphTargets[ i ].name = json.morphTargets[ i ].name; - geometry.morphTargets[ i ].vertices = []; - - var dstVertices = geometry.morphTargets[ i ].vertices; - var srcVertices = json.morphTargets[ i ].vertices; - - for ( var v = 0, vl = srcVertices.length; v < vl; v += 3 ) { - - var vertex = new Vector3(); - vertex.x = srcVertices[ v ] * scale; - vertex.y = srcVertices[ v + 1 ] * scale; - vertex.z = srcVertices[ v + 2 ] * scale; - - dstVertices.push( vertex ); - - } - - } - - } - - if ( json.morphColors !== undefined && json.morphColors.length > 0 ) { - - console.warn( 'THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.' ); - - var faces = geometry.faces; - var morphColors = json.morphColors[ 0 ].colors; - - for ( var i = 0, l = faces.length; i < l; i ++ ) { - - faces[ i ].color.fromArray( morphColors, i * 3 ); - - } - - } - - } - - function parseAnimations( json, geometry ) { - - var outputAnimations = []; - - // parse old style Bone/Hierarchy animations - var animations = []; - - if ( json.animation !== undefined ) { - - animations.push( json.animation ); - - } - - if ( json.animations !== undefined ) { - - if ( json.animations.length ) { - - animations = animations.concat( json.animations ); - - } else { - - animations.push( json.animations ); - - } - - } - - for ( var i = 0; i < animations.length; i ++ ) { - - var clip = AnimationClip.parseAnimation( animations[ i ], geometry.bones ); - if ( clip ) outputAnimations.push( clip ); - - } - - // parse implicit morph animations - if ( geometry.morphTargets ) { - - // TODO: Figure out what an appropraite FPS is for morph target animations -- defaulting to 10, but really it is completely arbitrary. - var morphAnimationClips = AnimationClip.CreateClipsFromMorphTargetSequences( geometry.morphTargets, 10 ); - outputAnimations = outputAnimations.concat( morphAnimationClips ); - - } - - if ( outputAnimations.length > 0 ) geometry.animations = outputAnimations; - - } - - return function ( json, texturePath ) { - - if ( json.data !== undefined ) { - - // Geometry 4.0 spec - json = json.data; - - } - - if ( json.scale !== undefined ) { - - json.scale = 1.0 / json.scale; - - } else { - - json.scale = 1.0; - - } - - var geometry = new Geometry(); - - parseModel( json, geometry ); - parseSkin( json, geometry ); - parseMorphing( json, geometry ); - parseAnimations( json, geometry ); - - geometry.computeFaceNormals(); - geometry.computeBoundingSphere(); - - if ( json.materials === undefined || json.materials.length === 0 ) { - - return { geometry: geometry }; - - } else { - - var materials = Loader.prototype.initMaterials( json.materials, texturePath, this.crossOrigin ); - - return { geometry: geometry, materials: materials }; - - } - - }; - - } )() - - } ); - - function Line( geometry, material, mode ) { - - if ( mode === 1 ) { - - console.warn( 'THREE.Line: parameter THREE.LinePieces no longer supported. Created THREE.LineSegments instead.' ); - return new LineSegments( geometry, material ); - - } - - Object3D.call( this ); - - this.type = 'Line'; - - this.geometry = geometry !== undefined ? geometry : new BufferGeometry(); - this.material = material !== undefined ? material : new LineBasicMaterial( { color: Math.random() * 0xffffff } ); - - } - - Line.prototype = Object.assign( Object.create( Object3D.prototype ), { - - constructor: Line, - - isLine: true, - - raycast: ( function () { - - var inverseMatrix = new Matrix4(); - var ray = new Ray(); - var sphere = new Sphere(); - - return function raycast( raycaster, intersects ) { - - var precision = raycaster.linePrecision; - var precisionSq = precision * precision; - - var geometry = this.geometry; - var matrixWorld = this.matrixWorld; - - // Checking boundingSphere distance to ray - - if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); - - sphere.copy( geometry.boundingSphere ); - sphere.applyMatrix4( matrixWorld ); - - if ( raycaster.ray.intersectsSphere( sphere ) === false ) return; - - // - - inverseMatrix.getInverse( matrixWorld ); - ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix ); - - var vStart = new Vector3(); - var vEnd = new Vector3(); - var interSegment = new Vector3(); - var interRay = new Vector3(); - var step = ( this && this.isLineSegments ) ? 2 : 1; - - if ( geometry.isBufferGeometry ) { - - var index = geometry.index; - var attributes = geometry.attributes; - var positions = attributes.position.array; - - if ( index !== null ) { - - var indices = index.array; - - for ( var i = 0, l = indices.length - 1; i < l; i += step ) { - - var a = indices[ i ]; - var b = indices[ i + 1 ]; - - vStart.fromArray( positions, a * 3 ); - vEnd.fromArray( positions, b * 3 ); - - var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment ); - - if ( distSq > precisionSq ) continue; - - interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation - - var distance = raycaster.ray.origin.distanceTo( interRay ); - - if ( distance < raycaster.near || distance > raycaster.far ) continue; - - intersects.push( { - - distance: distance, - // What do we want? intersection point on the ray or on the segment?? - // point: raycaster.ray.at( distance ), - point: interSegment.clone().applyMatrix4( this.matrixWorld ), - index: i, - face: null, - faceIndex: null, - object: this - - } ); - - } - - } else { - - for ( var i = 0, l = positions.length / 3 - 1; i < l; i += step ) { - - vStart.fromArray( positions, 3 * i ); - vEnd.fromArray( positions, 3 * i + 3 ); - - var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment ); - - if ( distSq > precisionSq ) continue; - - interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation - - var distance = raycaster.ray.origin.distanceTo( interRay ); - - if ( distance < raycaster.near || distance > raycaster.far ) continue; - - intersects.push( { - - distance: distance, - // What do we want? intersection point on the ray or on the segment?? - // point: raycaster.ray.at( distance ), - point: interSegment.clone().applyMatrix4( this.matrixWorld ), - index: i, - face: null, - faceIndex: null, - object: this - - } ); - - } - - } - - } else if ( geometry.isGeometry ) { - - var vertices = geometry.vertices; - var nbVertices = vertices.length; - - for ( var i = 0; i < nbVertices - 1; i += step ) { - - var distSq = ray.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment ); - - if ( distSq > precisionSq ) continue; - - interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation - - var distance = raycaster.ray.origin.distanceTo( interRay ); - - if ( distance < raycaster.near || distance > raycaster.far ) continue; - - intersects.push( { - - distance: distance, - // What do we want? intersection point on the ray or on the segment?? - // point: raycaster.ray.at( distance ), - point: interSegment.clone().applyMatrix4( this.matrixWorld ), - index: i, - face: null, - faceIndex: null, - object: this - - } ); - - } - - } - - }; - - }() ), - - clone: function () { - - return new this.constructor( this.geometry, this.material ).copy( this ); - - } - - } ); - - function LineSegments( geometry, material ) { - - Line.call( this, geometry, material ); - - this.type = 'LineSegments'; - - } - - LineSegments.prototype = Object.assign( Object.create( Line.prototype ), { - - constructor: LineSegments, - - isLineSegments: true - - } ); - - /** - * @author bhouston / http://exocortex.com - */ - - const x = 2; - const y = 3; - const z = 4; - const w = 5; - - const negInf2 = new Vector2( - Infinity, - Infinity ); - const posInf2 = new Vector2( Infinity, Infinity ); - - const zero2 = new Vector2(); - const one2 = new Vector2( 1, 1 ); - const two2 = new Vector2( 2, 2 ); - - const negInf3 = new Vector3( - Infinity, - Infinity, - Infinity ); - const posInf3 = new Vector3( Infinity, Infinity, Infinity ); - - const zero3 = new Vector3(); - const one3 = new Vector3( 1, 1, 1 ); - const two3 = new Vector3( 2, 2, 2 ); - - const eps = 0.0001; - - /** - * @author simonThiele / https://github.com/simonThiele - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - var DegToRad = Math.PI / 180; - - function bufferAttributeEquals( a, b, tolerance ) { - - tolerance = tolerance || 0.0001; - - if ( a.count !== b.count || a.itemSize !== b.itemSize ) { - - return false; - - } - - for ( var i = 0, il = a.count * a.itemSize; i < il; i ++ ) { - - var delta = a[ i ] - b[ i ]; - if ( delta > tolerance ) { - - return false; - - } - - } - - return true; - - } - - function getBBForVertices( vertices ) { - - var geometry = new BufferGeometry(); - - geometry.addAttribute( "position", new BufferAttribute( new Float32Array( vertices ), 3 ) ); - geometry.computeBoundingBox(); - - return geometry.boundingBox; - - } - - function getBSForVertices( vertices ) { - - var geometry = new BufferGeometry(); - - geometry.addAttribute( "position", new BufferAttribute( new Float32Array( vertices ), 3 ) ); - geometry.computeBoundingSphere(); - - return geometry.boundingSphere; - - } - - function getNormalsForVertices( vertices, assert ) { - - var geometry = new BufferGeometry(); - - geometry.addAttribute( "position", new BufferAttribute( new Float32Array( vertices ), 3 ) ); - - geometry.computeVertexNormals(); - - assert.ok( geometry.attributes.normal !== undefined, "normal attribute was created" ); - - return geometry.attributes.normal.array; - - } - - function comparePositions( pos, v ) { - - return ( - pos[ 0 ] === v[ 0 ].x && pos[ 1 ] === v[ 0 ].y && pos[ 2 ] === v[ 0 ].z && - pos[ 3 ] === v[ 1 ].x && pos[ 4 ] === v[ 1 ].y && pos[ 5 ] === v[ 1 ].z && - pos[ 6 ] === v[ 2 ].x && pos[ 7 ] === v[ 2 ].y && pos[ 8 ] === v[ 2 ].z - ); - - } - - function compareColors( col, c ) { - - return ( - col[ 0 ] === c[ 0 ].r && col[ 1 ] === c[ 0 ].g && col[ 2 ] === c[ 0 ].b && - col[ 3 ] === c[ 1 ].r && col[ 4 ] === c[ 1 ].g && col[ 5 ] === c[ 1 ].b && - col[ 6 ] === c[ 2 ].r && col[ 7 ] === c[ 2 ].g && col[ 8 ] === c[ 2 ].b - ); - - } - - function compareUvs( uvs, u ) { - - return ( - uvs[ 0 ] === u[ 0 ].x && uvs[ 1 ] === u[ 0 ].y && - uvs[ 2 ] === u[ 1 ].x && uvs[ 3 ] === u[ 1 ].y && - uvs[ 4 ] === u[ 2 ].x && uvs[ 5 ] === u[ 2 ].y - ); - - } - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'BufferGeometry', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isBufferGeometry", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setIndex/getIndex", ( assert ) => { - - var a = new BufferGeometry(); - var uint16 = [ 1, 2, 3 ]; - var uint32 = [ 65535, 65536, 65537 ]; - var str = "foo"; - - a.setIndex( uint16 ); - assert.ok( a.getIndex() instanceof Uint16BufferAttribute, "Index has the right type" ); - assert.deepEqual( a.getIndex().array, new Uint16Array( uint16 ), "Small index gets stored correctly" ); - - a.setIndex( uint32 ); - assert.ok( a.getIndex() instanceof Uint32BufferAttribute, "Index has the right type" ); - assert.deepEqual( a.getIndex().array, new Uint32Array( uint32 ), "Large index gets stored correctly" ); - - a.setIndex( str ); - assert.strictEqual( a.getIndex(), str, "Weird index gets stored correctly" ); - - } ); - - QUnit.test( "getAttribute", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "add / delete Attribute", ( assert ) => { - - var geometry = new BufferGeometry(); - var attributeName = "position"; - - assert.ok( geometry.attributes[ attributeName ] === undefined, 'no attribute defined' ); - - geometry.addAttribute( attributeName, new BufferAttribute( new Float32Array( [ 1, 2, 3 ], 1 ) ) ); - - assert.ok( geometry.attributes[ attributeName ] !== undefined, 'attribute is defined' ); - - geometry.removeAttribute( attributeName ); - - assert.ok( geometry.attributes[ attributeName ] === undefined, 'no attribute defined' ); - - } ); - - QUnit.test( "addGroup", ( assert ) => { - - var a = new BufferGeometry(); - var expected = [ - { - start: 0, - count: 1, - materialIndex: 0 - }, - { - start: 1, - count: 2, - materialIndex: 2 - } - ]; - - a.addGroup( 0, 1, 0 ); - a.addGroup( 1, 2, 2 ); - - assert.deepEqual( a.groups, expected, "Check groups were stored correctly and in order" ); - - a.clearGroups(); - assert.strictEqual( a.groups.length, 0, "Check groups were deleted correctly" ); - - } ); - QUnit.test( "clearGroups", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setDrawRange", ( assert ) => { - - var a = new BufferGeometry(); - - a.setDrawRange( 1.0, 7 ); - - assert.deepEqual( a.drawRange, { - start: 1, - count: 7 - }, "Check draw range was stored correctly" ); - - } ); - - QUnit.test( "applyMatrix", ( assert ) => { - - var geometry = new BufferGeometry(); - geometry.addAttribute( "position", new BufferAttribute( new Float32Array( 6 ), 3 ) ); - - var matrix = new Matrix4().set( - 1, 0, 0, 1.5, - 0, 1, 0, - 2, - 0, 0, 1, 3, - 0, 0, 0, 1 - ); - geometry.applyMatrix( matrix ); - - var position = geometry.attributes.position.array; - var m = matrix.elements; - assert.ok( position[ 0 ] === m[ 12 ] && position[ 1 ] === m[ 13 ] && position[ 2 ] === m[ 14 ], "position was extracted from matrix" ); - assert.ok( position[ 3 ] === m[ 12 ] && position[ 4 ] === m[ 13 ] && position[ 5 ] === m[ 14 ], "position was extracted from matrix twice" ); - assert.ok( geometry.attributes.position.version === 1, "version was increased during update" ); - - } ); - - QUnit.test( "rotateX/Y/Z", ( assert ) => { - - var geometry = new BufferGeometry(); - geometry.addAttribute( "position", new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ) ); - - var pos = geometry.attributes.position.array; - - geometry.rotateX( 180 * DegToRad ); - - // object was rotated around x so all items should be flipped but the x ones - assert.ok( pos[ 0 ] === 1 && pos[ 1 ] === - 2 && pos[ 2 ] === - 3 && - pos[ 3 ] === 4 && pos[ 4 ] === - 5 && pos[ 5 ] === - 6, "vertices were rotated around x by 180 degrees" ); - - geometry.rotateY( 180 * DegToRad ); - - // vertices were rotated around y so all items should be flipped again but the y ones - assert.ok( pos[ 0 ] === - 1 && pos[ 1 ] === - 2 && pos[ 2 ] === 3 && - pos[ 3 ] === - 4 && pos[ 4 ] === - 5 && pos[ 5 ] === 6, "vertices were rotated around y by 180 degrees" ); - - geometry.rotateZ( 180 * DegToRad ); - - // vertices were rotated around z so all items should be flipped again but the z ones - assert.ok( pos[ 0 ] === 1 && pos[ 1 ] === 2 && pos[ 2 ] === 3 && - pos[ 3 ] === 4 && pos[ 4 ] === 5 && pos[ 5 ] === 6, "vertices were rotated around z by 180 degrees" ); - - } ); - - QUnit.test( "translate", ( assert ) => { - - var geometry = new BufferGeometry(); - geometry.addAttribute( "position", new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ) ); - - var pos = geometry.attributes.position.array; - - geometry.translate( 10, 20, 30 ); - - assert.ok( pos[ 0 ] === 11 && pos[ 1 ] === 22 && pos[ 2 ] === 33 && - pos[ 3 ] === 14 && pos[ 4 ] === 25 && pos[ 5 ] === 36, "vertices were translated" ); - - } ); - - QUnit.test( "scale", ( assert ) => { - - var geometry = new BufferGeometry(); - geometry.addAttribute( "position", new BufferAttribute( new Float32Array( [ - 1, - 1, - 1, 2, 2, 2 ] ), 3 ) ); - - var pos = geometry.attributes.position.array; - - geometry.scale( 1, 2, 3 ); - - assert.ok( pos[ 0 ] === - 1 && pos[ 1 ] === - 2 && pos[ 2 ] === - 3 && - pos[ 3 ] === 2 && pos[ 4 ] === 4 && pos[ 5 ] === 6, "vertices were scaled" ); - - } ); - - QUnit.test( "lookAt", ( assert ) => { - - var a = new BufferGeometry(); - var vertices = new Float32Array( [ - - 1.0, - 1.0, 1.0, - 1.0, - 1.0, 1.0, - 1.0, 1.0, 1.0, - - 1.0, 1.0, 1.0, - - 1.0, 1.0, 1.0, - - 1.0, - 1.0, 1.0 - ] ); - a.addAttribute( 'position', new BufferAttribute( vertices, 3 ) ); - - var sqrt = Math.sqrt( 2 ); - var expected = new Float32Array( [ - 1, 0, - sqrt, - - 1, 0, - sqrt, - - 1, sqrt, 0, - - - 1, sqrt, 0, - 1, sqrt, 0, - 1, 0, - sqrt - ] ); - - a.lookAt( new Vector3( 0, 1, - 1 ) ); - - assert.ok( bufferAttributeEquals( a.attributes.position.array, expected ), "Rotation is correct" ); - - } ); - - QUnit.test( "center", ( assert ) => { - - var geometry = new BufferGeometry(); - geometry.addAttribute( "position", new BufferAttribute( new Float32Array( [ - - 1, - 1, - 1, - 1, 1, 1, - 4, 4, 4 - ] ), 3 ) ); - - geometry.center(); - - var pos = geometry.attributes.position.array; - - // the boundingBox should go from (-1, -1, -1) to (4, 4, 4) so it has a size of (5, 5, 5) - // after centering it the vertices should be placed between (-2.5, -2.5, -2.5) and (2.5, 2.5, 2.5) - assert.ok( pos[ 0 ] === - 2.5 && pos[ 1 ] === - 2.5 && pos[ 2 ] === - 2.5 && - pos[ 3 ] === - 0.5 && pos[ 4 ] === - 0.5 && pos[ 5 ] === - 0.5 && - pos[ 6 ] === 2.5 && pos[ 7 ] === 2.5 && pos[ 8 ] === 2.5, "vertices were replaced by boundingBox dimensions" ); - - } ); - - QUnit.test( "setFromObject", ( assert ) => { - - var lineGeo = new Geometry(); - lineGeo.vertices.push( - new Vector3( - 10, 0, 0 ), - new Vector3( 0, 10, 0 ), - new Vector3( 10, 0, 0 ) - ); - - lineGeo.colors.push( - new Color( 1, 0, 0 ), - new Color( 0, 1, 0 ), - new Color( 0, 0, 1 ) - ); - - var line = new LineSegments( lineGeo, null ); - var geometry = new BufferGeometry().setFromObject( line ); - - var pos = geometry.attributes.position.array; - var col = geometry.attributes.color.array; - var v = lineGeo.vertices; - var c = lineGeo.colors; - - assert.ok( - // position exists - pos !== undefined && - - // vertex arrays have the same size - v.length * 3 === pos.length && - - // there are three complete vertices (each vertex contains three values) - geometry.attributes.position.count === 3 && - - // check if both arrays contains the same data - pos[ 0 ] === v[ 0 ].x && pos[ 1 ] === v[ 0 ].y && pos[ 2 ] === v[ 0 ].z && - pos[ 3 ] === v[ 1 ].x && pos[ 4 ] === v[ 1 ].y && pos[ 5 ] === v[ 1 ].z && - pos[ 6 ] === v[ 2 ].x && pos[ 7 ] === v[ 2 ].y && pos[ 8 ] === v[ 2 ].z - , "positions are equal" ); - - assert.ok( - // color exists - col !== undefined && - - // color arrays have the same size - c.length * 3 === col.length && - - // there are three complete colors (each color contains three values) - geometry.attributes.color.count === 3 && - - // check if both arrays contains the same data - col[ 0 ] === c[ 0 ].r && col[ 1 ] === c[ 0 ].g && col[ 2 ] === c[ 0 ].b && - col[ 3 ] === c[ 1 ].r && col[ 4 ] === c[ 1 ].g && col[ 5 ] === c[ 1 ].b && - col[ 6 ] === c[ 2 ].r && col[ 7 ] === c[ 2 ].g && col[ 8 ] === c[ 2 ].b - , "colors are equal" ); - - } ); - QUnit.test( "setFromObject (more)", ( assert ) => { - - var lineGeo = new Geometry(); - lineGeo.vertices.push( - new Vector3( - 10, 0, 0 ), - new Vector3( 0, 10, 0 ), - new Vector3( 10, 0, 0 ) - ); - - lineGeo.colors.push( - new Color( 1, 0, 0 ), - new Color( 0, 1, 0 ), - new Color( 0, 0, 1 ) - ); - - lineGeo.computeBoundingBox(); - lineGeo.computeBoundingSphere(); - - var line = new LineSegments( lineGeo ); - var geometry = new BufferGeometry().setFromObject( line ); - - assert.ok( geometry.boundingBox.equals( lineGeo.boundingBox ), "BoundingBox was set correctly" ); - assert.ok( geometry.boundingSphere.equals( lineGeo.boundingSphere ), "BoundingSphere was set correctly" ); - - var pos = geometry.attributes.position.array; - var col = geometry.attributes.color.array; - var v = lineGeo.vertices; - var c = lineGeo.colors; - - // adapted from setFromObject QUnit.test (way up) - assert.notStrictEqual( pos, undefined, "Position attribute exists" ); - assert.strictEqual( v.length * 3, pos.length, "Vertex arrays have the same size" ); - assert.strictEqual( geometry.attributes.position.count, 3, "Correct number of vertices" ); - assert.ok( comparePositions( pos, v ), "Positions are identical" ); - - assert.notStrictEqual( col, undefined, "Color attribute exists" ); - assert.strictEqual( c.length * 3, col.length, "Color arrays have the same size" ); - assert.strictEqual( geometry.attributes.color.count, 3, "Correct number of colors" ); - assert.ok( compareColors( col, c ), "Colors are identical" ); - - // setFromObject with a Mesh as object - lineGeo.faces.push( new Face3( 0, 1, 2 ) ); - var lineMesh = new Mesh( lineGeo ); - var geometry = new BufferGeometry().setFromObject( lineMesh ); - - // no colors - var pos = geometry.attributes.position.array; - var v = lineGeo.vertices; - - assert.notStrictEqual( pos, undefined, "Mesh: position attribute exists" ); - assert.strictEqual( v.length * 3, pos.length, "Mesh: vertex arrays have the same size" ); - assert.strictEqual( geometry.attributes.position.count, 3, "Mesh: correct number of vertices" ); - assert.ok( comparePositions( pos, v ), "Mesh: positions are identical" ); - - } ); - - QUnit.test( "updateFromObject", ( assert ) => { - - var geo = new Geometry(); - - geo.vertices.push( - new Vector3( - 10, 0, 0 ), - new Vector3( 0, 10, 0 ), - new Vector3( 10, 0, 0 ) - ); - - geo.faces.push( new Face3( 0, 1, 2 ) ); - - geo.faces[ 0 ].vertexColors.push( - new Color( 1, 0, 0 ), - new Color( 0, 1, 0 ), - new Color( 0, 0, 1 ) - ); - - geo.faceVertexUvs[ 0 ] = [ - [ - new Vector2( 0, 0 ), - new Vector2( 1, 0 ), - new Vector2( 1, 1 ) - ] - ]; - - geo.computeFaceNormals(); - geo.computeVertexNormals(); - - geo.verticesNeedUpdate = true; - geo.normalsNeedUpdate = true; - geo.colorsNeedUpdate = true; - geo.uvsNeedUpdate = true; - geo.groupsNeedUpdate = true; - - var mesh = new Mesh( geo ); - var geometry = new BufferGeometry(); - - geometry.updateFromObject( mesh ); // first call to create the underlying structure (DirectGeometry) - geometry.updateFromObject( mesh ); // second time to actually go thru the motions and update - - var pos = geometry.attributes.position.array; - var col = geometry.attributes.color.array; - var norm = geometry.attributes.normal.array; - var uvs = geometry.attributes.uv.array; - var v = geo.vertices; - var c = geo.faces[ 0 ].vertexColors; - var n = geo.faces[ 0 ].vertexNormals; - var u = geo.faceVertexUvs[ 0 ][ 0 ]; - - assert.notStrictEqual( pos, undefined, "Position attribute exists" ); - assert.strictEqual( v.length * 3, pos.length, "Both arrays have the same size" ); - assert.strictEqual( geometry.attributes.position.count, v.length, "Correct number of vertices" ); - assert.ok( comparePositions( pos, v ), "Positions are identical" ); - - assert.notStrictEqual( col, undefined, "Color attribute exists" ); - assert.strictEqual( c.length * 3, col.length, "Both arrays have the same size" ); - assert.strictEqual( geometry.attributes.color.count, c.length, "Correct number of colors" ); - assert.ok( compareColors( col, c ), "Colors are identical" ); - - assert.notStrictEqual( norm, undefined, "Normal attribute exists" ); - assert.strictEqual( n.length * 3, norm.length, "Both arrays have the same size" ); - assert.strictEqual( geometry.attributes.normal.count, n.length, "Correct number of normals" ); - assert.ok( comparePositions( norm, n ), "Normals are identical" ); - - assert.notStrictEqual( uvs, undefined, "UV attribute exists" ); - assert.strictEqual( u.length * 2, uvs.length, "Both arrays have the same size" ); - assert.strictEqual( geometry.attributes.uv.count, u.length, "Correct number of UV coordinates" ); - assert.ok( compareUvs( uvs, u ), "UVs are identical" ); - - } ); - - QUnit.test( "fromGeometry/fromDirectGeometry", ( assert ) => { - - assert.timeout( 1000 ); - - var a = new BufferGeometry(); - // BoxGeometry is a bit too simple but works fine in a pinch - // var b = new BoxGeometry( 1, 1, 1 ); - // b.mergeVertices(); - // b.computeVertexNormals(); - // b.computeBoundingBox(); - // b.computeBoundingSphere(); - var asyncDone = assert.async(); // tell QUnit we're done with asserts - - var loader = new JSONLoader(); - loader.load( "../../examples/models/skinned/simple/simple.js", function ( modelGeometry ) { - - a.fromGeometry( modelGeometry ); - - var attr; - var geometry = new DirectGeometry().fromGeometry( modelGeometry ); - - var positions = new Float32Array( geometry.vertices.length * 3 ); - attr = new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ); - assert.ok( bufferAttributeEquals( a.attributes.position, attr ), "Vertices are identical" ); - - if ( geometry.normals.length > 0 ) { - - var normals = new Float32Array( geometry.normals.length * 3 ); - attr = new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ); - assert.ok( bufferAttributeEquals( a.attributes.normal, attr ), "Normals are identical" ); - - } - - if ( geometry.colors.length > 0 ) { - - var colors = new Float32Array( geometry.colors.length * 3 ); - attr = new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ); - assert.ok( bufferAttributeEquals( a.attributes.color, attr ), "Colors are identical" ); - - } - - if ( geometry.uvs.length > 0 ) { - - var uvs = new Float32Array( geometry.uvs.length * 2 ); - attr = new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ); - assert.ok( bufferAttributeEquals( a.attributes.uv, attr ), "UVs are identical" ); - - } - - if ( geometry.uvs2.length > 0 ) { - - var uvs2 = new Float32Array( geometry.uvs2.length * 2 ); - attr = new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ); - assert.ok( bufferAttributeEquals( a.attributes.uv2, attr ), "UV2s are identical" ); - - } - - if ( geometry.indices.length > 0 ) { - - var TypeArray = arrayMax( geometry.indices ) > 65535 ? Uint32Array : Uint16Array; - var indices = new TypeArray( geometry.indices.length * 3 ); - attr = new BufferAttribute( indices, 1 ).copyIndicesArray( geometry.indices ); - assert.ok( bufferAttributeEquals( a.indices, attr ), "Indices are identical" ); - - } - - // groups - assert.deepEqual( a.groups, geometry.groups, "Groups are identical" ); - - // morphs - if ( geometry.morphTargets !== undefined ) { - - for ( var name in geometry.morphTargets ) { - - var morphTargets = geometry.morphTargets[ name ]; - - for ( var i = 0, l = morphTargets.length; i < l; i ++ ) { - - var morphTarget = morphTargets[ i ]; - - attr = new Float32BufferAttribute( morphTarget.length * 3, 3 ); - attr.copyVector3sArray( morphTarget ); - - assert.ok( - bufferAttributeEquals( a.morphAttributes[ name ][ i ], attr ), - "MorphTargets #" + i + " are identical" - ); - - } - - } - - } - - // skinning - if ( geometry.skinIndices.length > 0 ) { - - attr = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 ); - attr.copyVector4sArray( geometry.skinIndices ); - assert.ok( bufferAttributeEquals( a.attributes.skinIndex, attr ), "SkinIndices are identical" ); - - } - - if ( geometry.skinWeights.length > 0 ) { - - attr = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 ); - attr.copyVector4sArray( geometry.skinWeights ); - assert.ok( bufferAttributeEquals( a.attributes.skinWeight, attr ), "SkinWeights are identical" ); - - } - - // TODO - // DirectGeometry doesn't actually copy boundingSphere and boundingBox yet, - // so they're always null - if ( geometry.boundingSphere !== null ) { - - assert.ok( a.boundingSphere.equals( geometry.boundingSphere ), "BoundingSphere is identical" ); - - } - - if ( geometry.boundingBox !== null ) { - - assert.ok( a.boundingBox.equals( geometry.boundingBox ), "BoundingBox is identical" ); - - } - - asyncDone(); - - } ); - - } ); - - QUnit.test( "computeBoundingBox", ( assert ) => { - - var bb = getBBForVertices( [ - 1, - 2, - 3, 13, - 2, - 3.5, - 1, - 20, 0, - 4, 5, 6 ] ); - - assert.ok( bb.min.x === - 4 && bb.min.y === - 20 && bb.min.z === - 3.5, "min values are set correctly" ); - assert.ok( bb.max.x === 13 && bb.max.y === 5 && bb.max.z === 6, "max values are set correctly" ); - - var bb = getBBForVertices( [ - 1, - 1, - 1 ] ); - - assert.ok( bb.min.x === bb.max.x && bb.min.y === bb.max.y && bb.min.z === bb.max.z, "since there is only one vertex, max and min are equal" ); - assert.ok( bb.min.x === - 1 && bb.min.y === - 1 && bb.min.z === - 1, "since there is only one vertex, min and max are this vertex" ); - - } ); - - QUnit.test( "computeBoundingSphere", ( assert ) => { - - var bs = getBSForVertices( [ - 10, 0, 0, 10, 0, 0 ] ); - - assert.ok( bs.radius === ( 10 + 10 ) / 2, "radius is equal to deltaMinMax / 2" ); - assert.ok( bs.center.x === 0 && bs.center.y === 0 && bs.center.y === 0, "bounding sphere is at ( 0, 0, 0 )" ); - - var bs = getBSForVertices( [ - 5, 11, - 3, 5, - 11, 3 ] ); - var radius = new Vector3( 5, 11, 3 ).length(); - - assert.ok( bs.radius === radius, "radius is equal to directionLength" ); - assert.ok( bs.center.x === 0 && bs.center.y === 0 && bs.center.y === 0, "bounding sphere is at ( 0, 0, 0 )" ); - - } ); - - QUnit.test( "computeFaceNormals", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "computeVertexNormals", ( assert ) => { - - // get normals for a counter clockwise created triangle - var normals = getNormalsForVertices( [ - 1, 0, 0, 1, 0, 0, 0, 1, 0 ], assert ); - - assert.ok( normals[ 0 ] === 0 && normals[ 1 ] === 0 && normals[ 2 ] === 1, - "first normal is pointing to screen since the the triangle was created counter clockwise" ); - - assert.ok( normals[ 3 ] === 0 && normals[ 4 ] === 0 && normals[ 5 ] === 1, - "second normal is pointing to screen since the the triangle was created counter clockwise" ); - - assert.ok( normals[ 6 ] === 0 && normals[ 7 ] === 0 && normals[ 8 ] === 1, - "third normal is pointing to screen since the the triangle was created counter clockwise" ); - - // get normals for a clockwise created triangle - var normals = getNormalsForVertices( [ 1, 0, 0, - 1, 0, 0, 0, 1, 0 ], assert ); - - assert.ok( normals[ 0 ] === 0 && normals[ 1 ] === 0 && normals[ 2 ] === - 1, - "first normal is pointing to screen since the the triangle was created clockwise" ); - - assert.ok( normals[ 3 ] === 0 && normals[ 4 ] === 0 && normals[ 5 ] === - 1, - "second normal is pointing to screen since the the triangle was created clockwise" ); - - assert.ok( normals[ 6 ] === 0 && normals[ 7 ] === 0 && normals[ 8 ] === - 1, - "third normal is pointing to screen since the the triangle was created clockwise" ); - - var normals = getNormalsForVertices( [ 0, 0, 1, 0, 0, - 1, 1, 1, 0 ], assert ); - - // the triangle is rotated by 45 degrees to the right so the normals of the three vertices - // should point to (1, -1, 0).normalized(). The simplest solution is to check against a normalized - // vector (1, -1, 0) but you will get calculation errors because of floating calculations so another - // valid technique is to create a vector which stands in 90 degrees to the normals and calculate the - // dot product which is the cos of the angle between them. This should be < floating calculation error - // which can be taken from Number.EPSILON - var direction = new Vector3( 1, 1, 0 ).normalize(); // a vector which should have 90 degrees difference to normals - var difference = direction.dot( new Vector3( normals[ 0 ], normals[ 1 ], normals[ 2 ] ) ); - assert.ok( difference < Number.EPSILON, "normal is equal to reference vector" ); - - // get normals for a line should be NAN because you need min a triangle to calculate normals - var normals = getNormalsForVertices( [ 1, 0, 0, - 1, 0, 0 ], assert ); - for ( var i = 0; i < normals.length; i ++ ) { - - assert.ok( ! normals[ i ], "normals can't be calculated which is good" ); - - } - - } ); - QUnit.test( "computeVertexNormals (indexed)", ( assert ) => { - - var sqrt = 0.5 * Math.sqrt( 2 ); - var normal = new BufferAttribute( new Float32Array( [ - - 1, 0, 0, - 1, 0, 0, - 1, 0, 0, - sqrt, sqrt, 0, sqrt, sqrt, 0, sqrt, sqrt, 0, - - 1, 0, 0 - ] ), 3 ); - var position = new BufferAttribute( new Float32Array( [ - 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, - 0.5, 0.5, - 0.5, - 0.5, - 0.5, - 0.5, 0.5, - 0.5, - 0.5, 0.5, 0.5, - - 0.5, - 0.5, - 0.5 - ] ), 3 ); - var index = new BufferAttribute( new Uint16Array( [ - 0, 2, 1, 2, 3, 1, 4, 6, 5, 6, 7, 5 - ] ), 1 ); - - var a = new BufferGeometry(); - a.addAttribute( "position", position ); - a.computeVertexNormals(); - assert.ok( - bufferAttributeEquals( normal, a.getAttribute( "normal" ) ), - "Regular geometry: first computed normals are correct" - ); - - // a second time to see if the existing normals get properly deleted - a.computeVertexNormals(); - assert.ok( - bufferAttributeEquals( normal, a.getAttribute( "normal" ) ), - "Regular geometry: second computed normals are correct" - ); - - // indexed geometry - var a = new BufferGeometry(); - a.addAttribute( "position", position ); - a.setIndex( index ); - a.computeVertexNormals(); - assert.ok( bufferAttributeEquals( normal, a.getAttribute( "normal" ) ), "Indexed geometry: computed normals are correct" ); - - } ); - - QUnit.test( "merge", ( assert ) => { - - var geometry1 = new BufferGeometry(); - geometry1.addAttribute( "attrName", new BufferAttribute( new Float32Array( [ 1, 2, 3, 0, 0, 0 ] ), 3 ) ); - - var geometry2 = new BufferGeometry(); - geometry2.addAttribute( "attrName", new BufferAttribute( new Float32Array( [ 4, 5, 6 ] ), 3 ) ); - - var attr = geometry1.attributes.attrName.array; - - geometry1.merge( geometry2, 1 ); - - // merged array should be 1, 2, 3, 4, 5, 6 - for ( var i = 0; i < attr.length; i ++ ) { - - assert.ok( attr[ i ] === i + 1, "" ); - - } - - geometry1.merge( geometry2 ); - assert.ok( attr[ 0 ] === 4 && attr[ 1 ] === 5 && attr[ 2 ] === 6, "copied the 3 attributes without offset" ); - - } ); - - QUnit.test( "normalizeNormals", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "toNonIndexed", ( assert ) => { - - var geometry = new BufferGeometry(); - var vertices = new Float32Array( [ - 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, - 0.5, 0.5, 0.5, - 0.5, - 0.5 - ] ); - var index = new BufferAttribute( new Uint16Array( [ 0, 2, 1, 2, 3, 1 ] ) ); - var expected = new Float32Array( [ - 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, - 0.5, - 0.5, - 0.5, 0.5, 0.5, - 0.5, - 0.5, 0.5, 0.5, - 0.5 - ] ); - - geometry.addAttribute( 'position', new BufferAttribute( vertices, 3 ) ); - geometry.setIndex( index ); - - var nonIndexed = geometry.toNonIndexed(); - - assert.deepEqual( nonIndexed.getAttribute( "position" ).array, expected, "Expected vertices" ); - - } ); - - QUnit.test( "toJSON", ( assert ) => { - - var index = new BufferAttribute( new Uint16Array( [ 0, 1, 2, 3 ] ), 1 ); - var attribute1 = new BufferAttribute( new Uint16Array( [ 1, 3, 5, 7 ] ), 1 ); - var a = new BufferGeometry(); - a.name = "JSONQUnit.test"; - // a.parameters = { "placeholder": 0 }; - a.addAttribute( "attribute1", attribute1 ); - a.setIndex( index ); - a.addGroup( 0, 1, 2 ); - a.boundingSphere = new Sphere( new Vector3( x, y, z ), 0.5 ); - var j = a.toJSON(); - - var gold = { - "metadata": { - "version": 4.5, - "type": "BufferGeometry", - "generator": "BufferGeometry.toJSON" - }, - "uuid": a.uuid, - "type": "BufferGeometry", - "name": "JSONQUnit.test", - "data": { - "attributes": { - "attribute1": { - "itemSize": 1, - "type": "Uint16Array", - "array": [ 1, 3, 5, 7 ], - "normalized": false - } - }, - "index": { - "type": "Uint16Array", - "array": [ 0, 1, 2, 3 ] - }, - "groups": [ - { - "start": 0, - "count": 1, - "materialIndex": 2 - } - ], - "boundingSphere": { - "center": [ 2, 3, 4 ], - "radius": 0.5 - } - } - }; - - assert.deepEqual( j, gold, "Generated JSON is as expected" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - var a = new BufferGeometry(); - a.addAttribute( "attribute1", new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ) ); - a.addAttribute( "attribute2", new BufferAttribute( new Float32Array( [ 0, 1, 3, 5, 6 ] ), 1 ) ); - a.addGroup( 0, 1, 2 ); - a.computeBoundingBox(); - a.computeBoundingSphere(); - a.setDrawRange( 0, 1 ); - var b = a.clone(); - - assert.notEqual( a, b, "A new object was created" ); - assert.notEqual( a.id, b.id, "New object has a different GUID" ); - - assert.strictEqual( - Object.keys( a.attributes ).count, Object.keys( b.attributes ).count, - "Both objects have the same amount of attributes" - ); - assert.ok( - bufferAttributeEquals( a.getAttribute( "attribute1" ), b.getAttribute( "attribute1" ) ), - "First attributes buffer is identical" - ); - assert.ok( - bufferAttributeEquals( a.getAttribute( "attribute2" ), b.getAttribute( "attribute2" ) ), - "Second attributes buffer is identical" - ); - - assert.deepEqual( a.groups, b.groups, "Groups are identical" ); - - assert.ok( a.boundingBox.equals( b.boundingBox ), "BoundingBoxes are equal" ); - assert.ok( a.boundingSphere.equals( b.boundingSphere ), "BoundingSpheres are equal" ); - - assert.strictEqual( a.drawRange.start, b.drawRange.start, "DrawRange start is identical" ); - assert.strictEqual( a.drawRange.count, b.drawRange.count, "DrawRange count is identical" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - var geometry = new BufferGeometry(); - geometry.addAttribute( "attrName", new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ) ); - geometry.addAttribute( "attrName2", new BufferAttribute( new Float32Array( [ 0, 1, 3, 5, 6 ] ), 1 ) ); - - var copy = new BufferGeometry().copy( geometry ); - - assert.ok( copy !== geometry && geometry.id !== copy.id, "new object was created" ); - - Object.keys( geometry.attributes ).forEach( function ( key ) { - - var attribute = geometry.attributes[ key ]; - assert.ok( attribute !== undefined, "all attributes where copied" ); - - for ( var i = 0; i < attribute.array.length; i ++ ) { - - assert.ok( attribute.array[ i ] === copy.attributes[ key ].array[ i ], "values of the attribute are equal" ); - - } - - } ); - - } ); - - QUnit.test( "dispose", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author alteredq / http://alteredqualia.com/ - */ - - function Clock( autoStart ) { - - this.autoStart = ( autoStart !== undefined ) ? autoStart : true; - - this.startTime = 0; - this.oldTime = 0; - this.elapsedTime = 0; - - this.running = false; - - } - - Object.assign( Clock.prototype, { - - start: function () { - - this.startTime = ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732 - - this.oldTime = this.startTime; - this.elapsedTime = 0; - this.running = true; - - }, - - stop: function () { - - this.getElapsedTime(); - this.running = false; - this.autoStart = false; - - }, - - getElapsedTime: function () { - - this.getDelta(); - return this.elapsedTime; - - }, - - getDelta: function () { - - var diff = 0; - - if ( this.autoStart && ! this.running ) { - - this.start(); - return 0; - - } - - if ( this.running ) { - - var newTime = ( typeof performance === 'undefined' ? Date : performance ).now(); - - diff = ( newTime - this.oldTime ) / 1000; - this.oldTime = newTime; - - this.elapsedTime += diff; - - } - - return diff; - - } - - } ); - - /** - * @author simonThiele / https://github.com/simonThiele - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'Clock', () => { - - function mockPerformance() { - - self.performance = { - deltaTime: 0, - - next: function ( delta ) { - - this.deltaTime += delta; - - }, - - now: function () { - - return this.deltaTime; - - } - - }; - - } - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "start", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "stop", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getElapsedTime", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getDelta", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( "clock with performance", ( assert ) => { - - mockPerformance(); - - var clock = new Clock( false ); - - clock.start(); - - self.performance.next( 123 ); - assert.numEqual( clock.getElapsedTime(), 0.123, "okay" ); - - self.performance.next( 100 ); - assert.numEqual( clock.getElapsedTime(), 0.223, "okay" ); - - clock.stop(); - - self.performance.next( 1000 ); - assert.numEqual( clock.getElapsedTime(), 0.223, "don't update time if the clock was stopped" ); - - } ); - - } ); - - } ); - - /** - * @author moraxy / https://github.com/moraxy - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'DirectGeometry', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "computeGroups", ( assert ) => { - - var a = new DirectGeometry(); - var b = new Geometry(); - var expected = [ - { start: 0, materialIndex: 0, count: 3 }, - { start: 3, materialIndex: 1, count: 3 }, - { start: 6, materialIndex: 2, count: 6 } - ]; - - // we only care for materialIndex - b.faces.push( - new Face3( 0, 0, 0, undefined, undefined, 0 ), - new Face3( 0, 0, 0, undefined, undefined, 1 ), - new Face3( 0, 0, 0, undefined, undefined, 2 ), - new Face3( 0, 0, 0, undefined, undefined, 2 ) - ); - - a.computeGroups( b ); - - assert.deepEqual( a.groups, expected, "Groups are as expected" ); - - } ); - - QUnit.test( "fromGeometry", ( assert ) => { - - assert.timeout( 1000 ); - - var a = new DirectGeometry(); - - var asyncDone = assert.async(); // tell QUnit when we're done with async stuff - - var loader = new JSONLoader(); - loader.load( "../../examples/models/skinned/simple/simple.js", function ( geometry ) { - - a.fromGeometry( geometry ); - - var tmp = new DirectGeometry(); - tmp.computeGroups( geometry ); - assert.deepEqual( a.groups, tmp.groups, "Check groups" ); - - var morphTargets = geometry.morphTargets; - var morphTargetsLength = morphTargets.length; - - var morphTargetsPosition; - - if ( morphTargetsLength > 0 ) { - - morphTargetsPosition = []; - - for ( var i = 0; i < morphTargetsLength; i ++ ) { - - morphTargetsPosition[ i ] = []; - - } - - morphTargets.position = morphTargetsPosition; - - } - - var morphNormals = geometry.morphNormals; - var morphNormalsLength = morphNormals.length; - - var morphTargetsNormal; - - if ( morphNormalsLength > 0 ) { - - morphTargetsNormal = []; - - for ( var i = 0; i < morphNormalsLength; i ++ ) { - - morphTargetsNormal[ i ] = []; - - } - - morphTargets.normal = morphTargetsNormal; - - } - - var vertices = []; - var normals = []; - var colors = []; - var uvs = []; - var uvs2 = []; - var skinIndices = []; - var skinWeights = []; - - var hasFaceVertexUv = geometry.faceVertexUvs[ 0 ] && geometry.faceVertexUvs[ 0 ].length > 0; - var hasFaceVertexUv2 = geometry.faceVertexUvs[ 1 ] && geometry.faceVertexUvs[ 1 ].length > 0; - - var hasSkinIndices = geometry.skinIndices.length === geometry.vertices.length; - var hasSkinWeights = geometry.skinWeights.length === geometry.vertices.length; - - for ( var i = 0; i < geometry.faces.length; i ++ ) { - - var face = geometry.faces[ i ]; - - vertices.push( - geometry.vertices[ face.a ], - geometry.vertices[ face.b ], - geometry.vertices[ face.c ] - ); - - var vertexNormals = face.vertexNormals; - - if ( vertexNormals.length === 3 ) { - - normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] ); - - } else { - - normals.push( face.normal, face.normal, face.normal ); - - } - - var vertexColors = face.vertexColors; - - if ( vertexColors.length === 3 ) { - - colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] ); - - } else { - - colors.push( face.color, face.color, face.color ); - - } - - if ( hasFaceVertexUv === true ) { - - var vertexUvs = geometry.faceVertexUvs[ 0 ][ i ]; - - if ( vertexUvs !== undefined ) { - - uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] ); - - } else { - - uvs.push( new Vector2(), new Vector2(), new Vector2() ); - - } - - } - - if ( hasFaceVertexUv2 === true ) { - - var vertexUvs = geometry.faceVertexUvs[ 1 ][ i ]; - - if ( vertexUvs !== undefined ) { - - uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] ); - - } else { - - uvs2.push( new Vector2(), new Vector2(), new Vector2() ); - - } - - } - - // morphs - - for ( var j = 0; j < morphTargetsLength; j ++ ) { - - var morphTarget = morphTargets[ j ].vertices; - - morphTargetsPosition[ j ].push( - morphTarget[ face.a ], - morphTarget[ face.b ], - morphTarget[ face.c ] - ); - - } - - for ( var j = 0; j < morphNormalsLength; j ++ ) { - - var morphNormal = morphNormals[ j ].vertexNormals[ i ]; - - morphTargetsNormal[ j ].push( morphNormal.a, morphNormal.b, morphNormal.c ); - - } - - // skins - - if ( hasSkinIndices ) { - - skinIndices.push( - geometry.skinIndices[ face.a ], - geometry.skinIndices[ face.b ], - geometry.skinIndices[ face.c ] - ); - - } - - if ( hasSkinWeights ) { - - skinWeights.push( - geometry.skinWeights[ face.a ], - geometry.skinWeights[ face.b ], - geometry.skinWeights[ face.c ] - ); - - } - - } - - assert.deepEqual( a.vertices, vertices, "Vertices are identical" ); - assert.deepEqual( a.normals, normals, "Normals are identical" ); - assert.deepEqual( a.colors, colors, "Colors are identical" ); - assert.deepEqual( a.uvs, uvs, "UV coordinates are identical" ); - assert.deepEqual( a.uvs2, uvs2, "UV(2) coordinates are identical" ); - assert.deepEqual( a.skinIndices, skinIndices, "SkinIndices are identical" ); - assert.deepEqual( a.skinWeights, skinWeights, "SkinWeights are identical" ); - assert.deepEqual( a.morphTargetsPosition, morphTargetsPosition, "MorphTargets (Position) are identical" ); - assert.deepEqual( a.morphTargetsNormal, morphTargetsNormal, "MorphTargets (Normals) are identical" ); - - asyncDone(); - - }, onProgress, onError ); - - function onProgress() {} - - function onError( error ) { - - console.error( error ); - asyncDone(); - - } - - } ); - - } ); - - } ); - - /** - * @author simonThiele / https://github.com/simonThiele - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'EventDispatcher', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "addEventListener", ( assert ) => { - - var eventDispatcher = new EventDispatcher(); - - var listener = {}; - eventDispatcher.addEventListener( 'anyType', listener ); - - assert.ok( eventDispatcher._listeners.anyType.length === 1, "listener with unknown type was added" ); - assert.ok( eventDispatcher._listeners.anyType[ 0 ] === listener, "listener with unknown type was added" ); - - eventDispatcher.addEventListener( 'anyType', listener ); - - assert.ok( eventDispatcher._listeners.anyType.length === 1, "can't add one listener twice to same type" ); - assert.ok( eventDispatcher._listeners.anyType[ 0 ] === listener, "listener is still there" ); - - } ); - - QUnit.test( "hasEventListener", ( assert ) => { - - var eventDispatcher = new EventDispatcher(); - - var listener = {}; - eventDispatcher.addEventListener( 'anyType', listener ); - - assert.ok( eventDispatcher.hasEventListener( 'anyType', listener ), "listener was found" ); - assert.ok( ! eventDispatcher.hasEventListener( 'anotherType', listener ), "listener was not found which is good" ); - - } ); - - QUnit.test( "removeEventListener", ( assert ) => { - - var eventDispatcher = new EventDispatcher(); - - var listener = {}; - - assert.ok( eventDispatcher._listeners === undefined, "there are no listeners by default" ); - - eventDispatcher.addEventListener( 'anyType', listener ); - assert.ok( Object.keys( eventDispatcher._listeners ).length === 1 && - eventDispatcher._listeners.anyType.length === 1, "if a listener was added, there is a new key" ); - - eventDispatcher.removeEventListener( 'anyType', listener ); - assert.ok( eventDispatcher._listeners.anyType.length === 0, "listener was deleted" ); - - eventDispatcher.removeEventListener( 'unknownType', listener ); - assert.ok( eventDispatcher._listeners.unknownType === undefined, "unknown types will be ignored" ); - - eventDispatcher.removeEventListener( 'anyType', undefined ); - assert.ok( eventDispatcher._listeners.anyType.length === 0, "undefined listeners are ignored" ); - - } ); - - QUnit.test( "dispatchEvent", ( assert ) => { - - var eventDispatcher = new EventDispatcher(); - - var callCount = 0; - var listener = function () { - - callCount ++; - - }; - - eventDispatcher.addEventListener( 'anyType', listener ); - assert.ok( callCount === 0, "no event, no call" ); - - eventDispatcher.dispatchEvent( { type: 'anyType' } ); - assert.ok( callCount === 1, "one event, one call" ); - - eventDispatcher.dispatchEvent( { type: 'anyType' } ); - assert.ok( callCount === 2, "two events, two calls" ); - - } ); - - } ); - - } ); - - /** - * @author simonThiele / https://github.com/simonThiele - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'Face3', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "copy", ( assert ) => { - - var instance = new Face3( 0, 1, 2, new Vector3( 0, 1, 0 ), new Color( 0.25, 0.5, 0.75 ), 2 ); - var copiedInstance = instance.copy( instance ); - - checkCopy( copiedInstance, assert ); - checkVertexAndColors( copiedInstance, assert ); - - } ); - - QUnit.test( "copy (more)", ( assert ) => { - - var instance = new Face3( 0, 1, 2, - [ new Vector3( 0, 1, 0 ), new Vector3( 1, 0, 1 ) ], - [ new Color( 0.25, 0.5, 0.75 ), new Color( 1, 0, 0.4 ) ], - 2 ); - var copiedInstance = instance.copy( instance ); - - checkCopy( copiedInstance, assert ); - checkVertexAndColorArrays( copiedInstance, assert ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - var instance = new Face3( 0, 1, 2, new Vector3( 0, 1, 0 ), new Color( 0.25, 0.5, 0.75 ), 2 ); - var copiedInstance = instance.clone(); - - checkCopy( copiedInstance, assert ); - checkVertexAndColors( copiedInstance, assert ); - - } ); - - function checkCopy( copiedInstance, assert ) { - - assert.ok( copiedInstance instanceof Face3, "copy created the correct type" ); - assert.ok( - copiedInstance.a === 0 && - copiedInstance.b === 1 && - copiedInstance.c === 2 && - copiedInstance.materialIndex === 2 - , "properties where copied" ); - - } - - function checkVertexAndColors( copiedInstance, assert ) { - - assert.ok( - copiedInstance.normal.x === 0 && copiedInstance.normal.y === 1 && copiedInstance.normal.z === 0 && - copiedInstance.color.r === 0.25 && copiedInstance.color.g === 0.5 && copiedInstance.color.b === 0.75 - , "properties where copied" ); - - } - - function checkVertexAndColorArrays( copiedInstance, assert ) { - - assert.ok( - copiedInstance.vertexNormals[ 0 ].x === 0 && copiedInstance.vertexNormals[ 0 ].y === 1 && copiedInstance.vertexNormals[ 0 ].z === 0 && - copiedInstance.vertexNormals[ 1 ].x === 1 && copiedInstance.vertexNormals[ 1 ].y === 0 && copiedInstance.vertexNormals[ 1 ].z === 1 && - copiedInstance.vertexColors[ 0 ].r === 0.25 && copiedInstance.vertexColors[ 0 ].g === 0.5 && copiedInstance.vertexColors[ 0 ].b === 0.75 && - copiedInstance.vertexColors[ 1 ].r === 1 && copiedInstance.vertexColors[ 1 ].g === 0 && copiedInstance.vertexColors[ 1 ].b === 0.4 - , "properties where copied" ); - - } - - } ); - - } ); - - /** - * @author clockworkgeek / https://github.com/clockworkgeek - * @author timothypratley / https://github.com/timothypratley - * @author WestLangley / http://github.com/WestLangley - * @author Mugen87 / https://github.com/Mugen87 - */ - - function PolyhedronGeometry( vertices, indices, radius, detail ) { - - Geometry.call( this ); - - this.type = 'PolyhedronGeometry'; - - this.parameters = { - vertices: vertices, - indices: indices, - radius: radius, - detail: detail - }; - - this.fromBufferGeometry( new PolyhedronBufferGeometry( vertices, indices, radius, detail ) ); - this.mergeVertices(); - - } - - PolyhedronGeometry.prototype = Object.create( Geometry.prototype ); - PolyhedronGeometry.prototype.constructor = PolyhedronGeometry; - - // PolyhedronBufferGeometry - - function PolyhedronBufferGeometry( vertices, indices, radius, detail ) { - - BufferGeometry.call( this ); - - this.type = 'PolyhedronBufferGeometry'; - - this.parameters = { - vertices: vertices, - indices: indices, - radius: radius, - detail: detail - }; - - radius = radius || 1; - detail = detail || 0; - - // default buffer data - - var vertexBuffer = []; - var uvBuffer = []; - - // the subdivision creates the vertex buffer data - - subdivide( detail ); - - // all vertices should lie on a conceptual sphere with a given radius - - appplyRadius( radius ); - - // finally, create the uv data - - generateUVs(); - - // build non-indexed geometry - - this.addAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) ); - - if ( detail === 0 ) { - - this.computeVertexNormals(); // flat normals - - } else { - - this.normalizeNormals(); // smooth normals - - } - - // helper functions - - function subdivide( detail ) { - - var a = new Vector3(); - var b = new Vector3(); - var c = new Vector3(); - - // iterate over all faces and apply a subdivison with the given detail value - - for ( var i = 0; i < indices.length; i += 3 ) { - - // get the vertices of the face - - getVertexByIndex( indices[ i + 0 ], a ); - getVertexByIndex( indices[ i + 1 ], b ); - getVertexByIndex( indices[ i + 2 ], c ); - - // perform subdivision - - subdivideFace( a, b, c, detail ); - - } - - } - - function subdivideFace( a, b, c, detail ) { - - var cols = Math.pow( 2, detail ); - - // we use this multidimensional array as a data structure for creating the subdivision - - var v = []; - - var i, j; - - // construct all of the vertices for this subdivision - - for ( i = 0; i <= cols; i ++ ) { - - v[ i ] = []; - - var aj = a.clone().lerp( c, i / cols ); - var bj = b.clone().lerp( c, i / cols ); - - var rows = cols - i; - - for ( j = 0; j <= rows; j ++ ) { - - if ( j === 0 && i === cols ) { - - v[ i ][ j ] = aj; - - } else { - - v[ i ][ j ] = aj.clone().lerp( bj, j / rows ); - - } - - } - - } - - // construct all of the faces - - for ( i = 0; i < cols; i ++ ) { - - for ( j = 0; j < 2 * ( cols - i ) - 1; j ++ ) { - - var k = Math.floor( j / 2 ); - - if ( j % 2 === 0 ) { - - pushVertex( v[ i ][ k + 1 ] ); - pushVertex( v[ i + 1 ][ k ] ); - pushVertex( v[ i ][ k ] ); - - } else { - - pushVertex( v[ i ][ k + 1 ] ); - pushVertex( v[ i + 1 ][ k + 1 ] ); - pushVertex( v[ i + 1 ][ k ] ); - - } - - } - - } - - } - - function appplyRadius( radius ) { - - var vertex = new Vector3(); - - // iterate over the entire buffer and apply the radius to each vertex - - for ( var i = 0; i < vertexBuffer.length; i += 3 ) { - - vertex.x = vertexBuffer[ i + 0 ]; - vertex.y = vertexBuffer[ i + 1 ]; - vertex.z = vertexBuffer[ i + 2 ]; - - vertex.normalize().multiplyScalar( radius ); - - vertexBuffer[ i + 0 ] = vertex.x; - vertexBuffer[ i + 1 ] = vertex.y; - vertexBuffer[ i + 2 ] = vertex.z; - - } - - } - - function generateUVs() { - - var vertex = new Vector3(); - - for ( var i = 0; i < vertexBuffer.length; i += 3 ) { - - vertex.x = vertexBuffer[ i + 0 ]; - vertex.y = vertexBuffer[ i + 1 ]; - vertex.z = vertexBuffer[ i + 2 ]; - - var u = azimuth( vertex ) / 2 / Math.PI + 0.5; - var v = inclination( vertex ) / Math.PI + 0.5; - uvBuffer.push( u, 1 - v ); - - } - - correctUVs(); - - correctSeam(); - - } - - function correctSeam() { - - // handle case when face straddles the seam, see #3269 - - for ( var i = 0; i < uvBuffer.length; i += 6 ) { - - // uv data of a single face - - var x0 = uvBuffer[ i + 0 ]; - var x1 = uvBuffer[ i + 2 ]; - var x2 = uvBuffer[ i + 4 ]; - - var max = Math.max( x0, x1, x2 ); - var min = Math.min( x0, x1, x2 ); - - // 0.9 is somewhat arbitrary - - if ( max > 0.9 && min < 0.1 ) { - - if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1; - if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1; - if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1; - - } - - } - - } - - function pushVertex( vertex ) { - - vertexBuffer.push( vertex.x, vertex.y, vertex.z ); - - } - - function getVertexByIndex( index, vertex ) { - - var stride = index * 3; - - vertex.x = vertices[ stride + 0 ]; - vertex.y = vertices[ stride + 1 ]; - vertex.z = vertices[ stride + 2 ]; - - } - - function correctUVs() { - - var a = new Vector3(); - var b = new Vector3(); - var c = new Vector3(); - - var centroid = new Vector3(); - - var uvA = new Vector2(); - var uvB = new Vector2(); - var uvC = new Vector2(); - - for ( var i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) { - - a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] ); - b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] ); - c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] ); - - uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] ); - uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] ); - uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] ); - - centroid.copy( a ).add( b ).add( c ).divideScalar( 3 ); - - var azi = azimuth( centroid ); - - correctUV( uvA, j + 0, a, azi ); - correctUV( uvB, j + 2, b, azi ); - correctUV( uvC, j + 4, c, azi ); - - } - - } - - function correctUV( uv, stride, vector, azimuth ) { - - if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) { - - uvBuffer[ stride ] = uv.x - 1; - - } - - if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) { - - uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5; - - } - - } - - // Angle around the Y axis, counter-clockwise when looking from above. - - function azimuth( vector ) { - - return Math.atan2( vector.z, - vector.x ); - - } - - - // Angle above the XZ plane. - - function inclination( vector ) { - - return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) ); - - } - - } - - PolyhedronBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - PolyhedronBufferGeometry.prototype.constructor = PolyhedronBufferGeometry; - - /** - * @author Abe Pazos / https://hamoid.com - * @author Mugen87 / https://github.com/Mugen87 - */ - - function DodecahedronGeometry( radius, detail ) { - - Geometry.call( this ); - - this.type = 'DodecahedronGeometry'; - - this.parameters = { - radius: radius, - detail: detail - }; - - this.fromBufferGeometry( new DodecahedronBufferGeometry( radius, detail ) ); - this.mergeVertices(); - - } - - DodecahedronGeometry.prototype = Object.create( Geometry.prototype ); - DodecahedronGeometry.prototype.constructor = DodecahedronGeometry; - - // DodecahedronBufferGeometry - - function DodecahedronBufferGeometry( radius, detail ) { - - var t = ( 1 + Math.sqrt( 5 ) ) / 2; - var r = 1 / t; - - var vertices = [ - - // (±1, ±1, ±1) - - 1, - 1, - 1, - 1, - 1, 1, - - 1, 1, - 1, - 1, 1, 1, - 1, - 1, - 1, 1, - 1, 1, - 1, 1, - 1, 1, 1, 1, - - // (0, ±1/φ, ±φ) - 0, - r, - t, 0, - r, t, - 0, r, - t, 0, r, t, - - // (±1/φ, ±φ, 0) - - r, - t, 0, - r, t, 0, - r, - t, 0, r, t, 0, - - // (±φ, 0, ±1/φ) - - t, 0, - r, t, 0, - r, - - t, 0, r, t, 0, r - ]; - - var indices = [ - 3, 11, 7, 3, 7, 15, 3, 15, 13, - 7, 19, 17, 7, 17, 6, 7, 6, 15, - 17, 4, 8, 17, 8, 10, 17, 10, 6, - 8, 0, 16, 8, 16, 2, 8, 2, 10, - 0, 12, 1, 0, 1, 18, 0, 18, 16, - 6, 10, 2, 6, 2, 13, 6, 13, 15, - 2, 16, 18, 2, 18, 3, 2, 3, 13, - 18, 1, 9, 18, 9, 11, 18, 11, 3, - 4, 14, 12, 4, 12, 0, 4, 0, 8, - 11, 9, 5, 11, 5, 19, 11, 19, 7, - 19, 5, 14, 19, 14, 4, 19, 4, 17, - 1, 12, 14, 1, 14, 5, 1, 5, 9 - ]; - - PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail ); - - this.type = 'DodecahedronBufferGeometry'; - - this.parameters = { - radius: radius, - detail: detail - }; - - } - - DodecahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype ); - DodecahedronBufferGeometry.prototype.constructor = DodecahedronBufferGeometry; - - /** - * @author simonThiele / https://github.com/simonThiele - */ - /* global QUnit */ - - function getGeometryByParams( x1, y1, z1, x2, y2, z2, x3, y3, z3 ) { - - var geometry = new Geometry(); - - // a triangle - geometry.vertices = [ - new Vector3( x1, y1, z1 ), - new Vector3( x2, y2, z2 ), - new Vector3( x3, y3, z3 ) - ]; - - return geometry; - - } - - function getGeometry() { - - return getGeometryByParams( - 0.5, 0, 0, 0.5, 0, 0, 0, 1, 0 ); - - } - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'Geometry', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isGeometry", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "applyMatrix", ( assert ) => { - - var geometry = getGeometry(); - geometry.faces.push( new Face3( 0, 1, 2 ) ); - var m = new Matrix4(); - var expectedVerts = [ - new Vector3( 1.5, 3, 4 ), - new Vector3( 2.5, 3, 4 ), - new Vector3( 2, 3, 5 ) - ]; - var v0, v1, v2; - - m.makeRotationX( Math.PI / 2 ); - m.setPosition( new Vector3( x, y, z ) ); - - geometry.applyMatrix( m ); - - v0 = geometry.vertices[ 0 ]; - v1 = geometry.vertices[ 1 ]; - v2 = geometry.vertices[ 2 ]; - assert.ok( - Math.abs( v0.x - expectedVerts[ 0 ].x ) <= eps && - Math.abs( v0.y - expectedVerts[ 0 ].y ) <= eps && - Math.abs( v0.z - expectedVerts[ 0 ].z ) <= eps, - "First vertex is as expected" - ); - assert.ok( - Math.abs( v1.x - expectedVerts[ 1 ].x ) <= eps && - Math.abs( v1.y - expectedVerts[ 1 ].y ) <= eps && - Math.abs( v1.z - expectedVerts[ 1 ].z ) <= eps, - "Second vertex is as expected" - ); - assert.ok( - Math.abs( v2.x - expectedVerts[ 2 ].x ) <= eps && - Math.abs( v2.y - expectedVerts[ 2 ].y ) <= eps && - Math.abs( v2.z - expectedVerts[ 2 ].z ) <= eps, - "Third vertex is as expected" - ); - - } ); - - QUnit.test( "rotateX", ( assert ) => { - - var geometry = getGeometry(); - - var matrix = new Matrix4(); - matrix.makeRotationX( Math.PI / 2 ); // 90 degree - - geometry.applyMatrix( matrix ); - - var v0 = geometry.vertices[ 0 ], v1 = geometry.vertices[ 1 ], v2 = geometry.vertices[ 2 ]; - assert.ok( v0.x === - 0.5 && v0.y === 0 && v0.z === 0, "first vertex was rotated" ); - assert.ok( v1.x === 0.5 && v1.y === 0 && v1.z === 0, "second vertex was rotated" ); - assert.ok( v2.x === 0 && v2.y < Number.EPSILON && v2.z === 1, "third vertex was rotated" ); - - } ); - - QUnit.test( "rotateY", ( assert ) => { - - var geometry = getGeometry(); - - var matrix = new Matrix4(); - matrix.makeRotationY( Math.PI ); // 180 degrees - - geometry.applyMatrix( matrix ); - - var v0 = geometry.vertices[ 0 ], v1 = geometry.vertices[ 1 ], v2 = geometry.vertices[ 2 ]; - assert.ok( v0.x === 0.5 && v0.y === 0 && v0.z < Number.EPSILON, "first vertex was rotated" ); - assert.ok( v1.x === - 0.5 && v1.y === 0 && v1.z < Number.EPSILON, "second vertex was rotated" ); - assert.ok( v2.x === 0 && v2.y === 1 && v2.z === 0, "third vertex was rotated" ); - - } ); - - QUnit.test( "rotateZ", ( assert ) => { - - var geometry = getGeometry(); - - var matrix = new Matrix4(); - matrix.makeRotationZ( Math.PI / 2 * 3 ); // 270 degrees - - geometry.applyMatrix( matrix ); - - var v0 = geometry.vertices[ 0 ], v1 = geometry.vertices[ 1 ], v2 = geometry.vertices[ 2 ]; - assert.ok( v0.x < Number.EPSILON && v0.y === 0.5 && v0.z === 0, "first vertex was rotated" ); - assert.ok( v1.x < Number.EPSILON && v1.y === - 0.5 && v1.z === 0, "second vertex was rotated" ); - assert.ok( v2.x === 1 && v2.y < Number.EPSILON && v2.z === 0, "third vertex was rotated" ); - - } ); - - QUnit.test( "translate", ( assert ) => { - - var a = getGeometry(); - var expected = [ - new Vector3( - 2.5, 3, - 4 ), - new Vector3( - 1.5, 3, - 4 ), - new Vector3( - 2, 4, - 4 ) - ]; - var v; - - a.translate( - x, y, - z ); - - for ( var i = 0; i < a.vertices.length; i ++ ) { - - v = a.vertices[ i ]; - assert.ok( - Math.abs( v.x - expected[ i ].x ) <= eps && - Math.abs( v.y - expected[ i ].y ) <= eps && - Math.abs( v.z - expected[ i ].z ) <= eps, - "Vertex #" + i + " was translated as expected" - ); - - } - - } ); - - QUnit.test( "scale", ( assert ) => { - - var a = getGeometry(); - var expected = [ - new Vector3( - 1, 0, 0 ), - new Vector3( 1, 0, 0 ), - new Vector3( 0, 3, 0 ) - ]; - var v; - - a.scale( 2, 3, 4 ); - - for ( var i = 0; i < a.vertices.length; i ++ ) { - - v = a.vertices[ i ]; - assert.ok( - Math.abs( v.x - expected[ i ].x ) <= eps && - Math.abs( v.y - expected[ i ].y ) <= eps && - Math.abs( v.z - expected[ i ].z ) <= eps, - "Vertex #" + i + " was scaled as expected" - ); - - } - - } ); - - QUnit.test( "lookAt", ( assert ) => { - - var a = getGeometry(); - var expected = [ - new Vector3( - 0.5, 0, 0 ), - new Vector3( 0.5, 0, 0 ), - new Vector3( 0, 0.5 * Math.sqrt( 2 ), 0.5 * Math.sqrt( 2 ) ) - ]; - - a.lookAt( new Vector3( 0, - 1, 1 ) ); - - for ( var i = 0; i < a.vertices.length; i ++ ) { - - var v = a.vertices[ i ]; - assert.ok( - Math.abs( v.x - expected[ i ].x ) <= eps && - Math.abs( v.y - expected[ i ].y ) <= eps && - Math.abs( v.z - expected[ i ].z ) <= eps, - "Vertex #" + i + " was adjusted as expected" - ); - - } - - } ); - - QUnit.test( "fromBufferGeometry", ( assert ) => { - - var bufferGeometry = new BufferGeometry(); - bufferGeometry.addAttribute( 'position', new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] ), 3 ) ); - bufferGeometry.addAttribute( 'color', new BufferAttribute( new Float32Array( [ 0, 0, 0, 0.5, 0.5, 0.5, 1, 1, 1 ] ), 3 ) ); - bufferGeometry.addAttribute( 'normal', new BufferAttribute( new Float32Array( [ 0, 1, 0, 1, 0, 1, 1, 1, 0 ] ), 3 ) ); - bufferGeometry.addAttribute( 'uv', new BufferAttribute( new Float32Array( [ 0, 0, 0, 1, 1, 1 ] ), 2 ) ); - bufferGeometry.addAttribute( 'uv2', new BufferAttribute( new Float32Array( [ 0, 0, 0, 1, 1, 1 ] ), 2 ) ); - - var geometry = new Geometry().fromBufferGeometry( bufferGeometry ); - - var colors = geometry.colors; - assert.ok( - colors[ 0 ].r === 0 && colors[ 0 ].g === 0 && colors[ 0 ].b === 0 && - colors[ 1 ].r === 0.5 && colors[ 1 ].g === 0.5 && colors[ 1 ].b === 0.5 && - colors[ 2 ].r === 1 && colors[ 2 ].g === 1 && colors[ 2 ].b === 1 - , "colors were created well" ); - - var vertices = geometry.vertices; - assert.ok( - vertices[ 0 ].x === 1 && vertices[ 0 ].y === 2 && vertices[ 0 ].z === 3 && - vertices[ 1 ].x === 4 && vertices[ 1 ].y === 5 && vertices[ 1 ].z === 6 && - vertices[ 2 ].x === 7 && vertices[ 2 ].y === 8 && vertices[ 2 ].z === 9 - , "vertices were created well" ); - - var vNormals = geometry.faces[ 0 ].vertexNormals; - assert.ok( - vNormals[ 0 ].x === 0 && vNormals[ 0 ].y === 1 && vNormals[ 0 ].z === 0 && - vNormals[ 1 ].x === 1 && vNormals[ 1 ].y === 0 && vNormals[ 1 ].z === 1 && - vNormals[ 2 ].x === 1 && vNormals[ 2 ].y === 1 && vNormals[ 2 ].z === 0 - , "vertex normals were created well" ); - - } ); - - QUnit.test( "center", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "normalize", ( assert ) => { - - var geometry = getGeometry(); - geometry.computeLineDistances(); - - var distances = geometry.lineDistances; - assert.ok( distances[ 0 ] === 0, "distance to the 1st point is 0" ); - assert.ok( distances[ 1 ] === 1 + distances[ 0 ], "distance from the 1st to the 2nd is sqrt(2nd - 1st) + distance - 1" ); - assert.ok( distances[ 2 ] === Math.sqrt( 0.5 * 0.5 + 1 ) + distances[ 1 ], "distance from the 1st to the 3nd is sqrt(3rd - 2nd) + distance - 1" ); - - } ); - - QUnit.test( "normalize (actual)", ( assert ) => { - - var a = getGeometry(); - var sqrt = 0.5 * Math.sqrt( 2 ); - var expected = [ - new Vector3( - sqrt, - sqrt, 0 ), - new Vector3( sqrt, - sqrt, 0 ), - new Vector3( 0, sqrt, 0 ) - ]; - var v; - - a.normalize(); - - for ( var i = 0; i < a.vertices.length; i ++ ) { - - v = a.vertices[ i ]; - assert.ok( - Math.abs( v.x - expected[ i ].x ) <= eps && - Math.abs( v.y - expected[ i ].y ) <= eps && - Math.abs( v.z - expected[ i ].z ) <= eps, - "Vertex #" + i + " was normalized as expected" - ); - - } - - } ); - - QUnit.test( "computeFaceNormals", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "computeVertexNormals", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "computeFlatVertexNormals", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "computeMorphNormals", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "computeLineDistances", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "computeBoundingBox", ( assert ) => { - - var a = new DodecahedronGeometry(); - - a.computeBoundingBox(); - assert.strictEqual( a.boundingBox.isEmpty(), false, "Bounding box isn't empty" ); - - var allIn = true; - for ( var i = 0; i < a.vertices.length; i ++ ) { - - if ( ! a.boundingBox.containsPoint( a.vertices[ i ] ) ) { - - allIn = false; - - } - - } - assert.strictEqual( allIn, true, "All vertices are inside the box" ); - - } ); - - QUnit.test( "computeBoundingSphere", ( assert ) => { - - var a = new DodecahedronGeometry(); - - a.computeBoundingSphere(); - - var allIn = true; - for ( var i = 0; i < a.vertices.length; i ++ ) { - - if ( ! a.boundingSphere.containsPoint( a.vertices[ i ] ) ) { - - allIn = false; - - } - - } - assert.strictEqual( allIn, true, "All vertices are inside the bounding sphere" ); - - } ); - - QUnit.test( "merge", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "mergeMesh", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "mergeVertices", ( assert ) => { - - var a = new Geometry(); - var b = new BoxBufferGeometry( 1, 1, 1 ); - var verts, faces, removed; - - a.fromBufferGeometry( b ); - - removed = a.mergeVertices(); - verts = a.vertices.length; - faces = a.faces.length; - - assert.strictEqual( removed, 16, "Removed the expected number of vertices" ); - assert.strictEqual( verts, 8, "Minimum number of vertices remaining" ); - assert.strictEqual( faces, 12, "Minimum number of faces remaining" ); - - } ); - - QUnit.test( "sortFacesByMaterialIndex", ( assert ) => { - - var box = new BoxBufferGeometry( 1, 1, 1 ); - var a = new Geometry().fromBufferGeometry( box ); - var expected = [ 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 ]; - - a.faces.reverse(); // a bit too simple probably, still missing stuff like checking new UVs - a.sortFacesByMaterialIndex(); - - var indices = []; - - for ( var i = 0; i < a.faces.length; i ++ ) { - - indices.push( a.faces[ i ].materialIndex ); - - } - - assert.deepEqual( indices, expected, "Faces in correct order" ); - - } ); - - QUnit.test( "toJSON", ( assert ) => { - - var a = getGeometry(); - var gold = { - "metadata": { - "version": 4.5, - "type": "Geometry", - "generator": "Geometry.toJSON" - }, - "uuid": null, - "type": "Geometry", - "data": { - "vertices": [ - 0.5, 0, 0, 0.5, 0, 0, 0, 1, 0 ], - "normals": [ 0, 0, 1 ], - "faces": [ 50, 0, 1, 2, 0, 0, 0, 0, 0 ] - } - }; - var json; - - a.faces.push( new Face3( 0, 1, 2 ) ); - a.computeFaceNormals(); - a.computeVertexNormals(); - - json = a.toJSON(); - json.uuid = null; - assert.deepEqual( json, gold, "Generated JSON is as expected" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "dispose", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - function InstancedBufferAttribute( array, itemSize, meshPerAttribute ) { - - BufferAttribute.call( this, array, itemSize ); - - this.meshPerAttribute = meshPerAttribute || 1; - - } - - InstancedBufferAttribute.prototype = Object.assign( Object.create( BufferAttribute.prototype ), { - - constructor: InstancedBufferAttribute, - - isInstancedBufferAttribute: true, - - copy: function ( source ) { - - BufferAttribute.prototype.copy.call( this, source ); - - this.meshPerAttribute = source.meshPerAttribute; - - return this; - - } - - } ); - - /** - * @author simonThiele / https://github.com/simonThiele - */ - /* global QUnit */ - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'InstancedBufferAttribute', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - var instance = new InstancedBufferAttribute( new Float32Array( 10 ), 2 ); - assert.ok( instance.meshPerAttribute === 1, "ok" ); - - var instance = new InstancedBufferAttribute( new Float32Array( 10 ), 2, 123 ); - assert.ok( instance.meshPerAttribute === 123, "ok" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "copy", ( assert ) => { - - var array = new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ); - var instance = new InstancedBufferAttribute( array, 2, 123 ); - var copiedInstance = instance.copy( instance ); - - assert.ok( copiedInstance instanceof InstancedBufferAttribute, "the clone has the correct type" ); - assert.ok( copiedInstance.itemSize === 2, "itemSize was copied" ); - assert.ok( copiedInstance.meshPerAttribute === 123, "meshPerAttribute was copied" ); - - for ( var i = 0; i < array.length; i ++ ) { - - assert.ok( copiedInstance.array[ i ] === array[ i ], "array was copied" ); - - } - - } ); - - } ); - - } ); - - function InstancedBufferGeometry() { - - BufferGeometry.call( this ); - - this.type = 'InstancedBufferGeometry'; - this.maxInstancedCount = undefined; - - } - - InstancedBufferGeometry.prototype = Object.assign( Object.create( BufferGeometry.prototype ), { - - constructor: InstancedBufferGeometry, - - isInstancedBufferGeometry: true, - - copy: function ( source ) { - - BufferGeometry.prototype.copy.call( this, source ); - - this.maxInstancedCount = source.maxInstancedCount; - - return this; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - } - - } ); - - /** - * @author simonThiele / https://github.com/simonThiele - */ - /* global QUnit */ - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'InstancedBufferGeometry', () => { - - function createClonableMock() { - - return { - callCount: 0, - clone: function () { - - this.callCount ++; - return this; - - } - }; - - } - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "copy", ( assert ) => { - - var instanceMock1 = {}; - var instanceMock2 = {}; - var indexMock = createClonableMock(); - var defaultAttribute1 = new BufferAttribute( new Float32Array( [ 1 ] ) ); - var defaultAttribute2 = new BufferAttribute( new Float32Array( [ 2 ] ) ); - - var instance = new InstancedBufferGeometry(); - - instance.addGroup( 0, 10, instanceMock1 ); - instance.addGroup( 10, 5, instanceMock2 ); - instance.setIndex( indexMock ); - instance.addAttribute( 'defaultAttribute1', defaultAttribute1 ); - instance.addAttribute( 'defaultAttribute2', defaultAttribute2 ); - - var copiedInstance = new InstancedBufferGeometry().copy( instance ); - - assert.ok( copiedInstance instanceof InstancedBufferGeometry, "the clone has the correct type" ); - - assert.equal( copiedInstance.index, indexMock, "index was copied" ); - assert.equal( copiedInstance.index.callCount, 1, "index.clone was called once" ); - - assert.ok( copiedInstance.attributes[ 'defaultAttribute1' ] instanceof BufferAttribute, "attribute was created" ); - assert.deepEqual( copiedInstance.attributes[ 'defaultAttribute1' ].array, defaultAttribute1.array, "attribute was copied" ); - assert.deepEqual( copiedInstance.attributes[ 'defaultAttribute2' ].array, defaultAttribute2.array, "attribute was copied" ); - - assert.equal( copiedInstance.groups[ 0 ].start, 0, "group was copied" ); - assert.equal( copiedInstance.groups[ 0 ].count, 10, "group was copied" ); - assert.equal( copiedInstance.groups[ 0 ].materialIndex, instanceMock1, "group was copied" ); - - assert.equal( copiedInstance.groups[ 1 ].start, 10, "group was copied" ); - assert.equal( copiedInstance.groups[ 1 ].count, 5, "group was copied" ); - assert.equal( copiedInstance.groups[ 1 ].materialIndex, instanceMock2, "group was copied" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - function InterleavedBuffer( array, stride ) { - - this.uuid = _Math.generateUUID(); - - this.array = array; - this.stride = stride; - this.count = array !== undefined ? array.length / stride : 0; - - this.dynamic = false; - this.updateRange = { offset: 0, count: - 1 }; - - this.onUploadCallback = function () {}; - - this.version = 0; - - } - - Object.defineProperty( InterleavedBuffer.prototype, 'needsUpdate', { - - set: function ( value ) { - - if ( value === true ) this.version ++; - - } - - } ); - - Object.assign( InterleavedBuffer.prototype, { - - isInterleavedBuffer: true, - - setArray: function ( array ) { - - if ( Array.isArray( array ) ) { - - throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); - - } - - this.count = array !== undefined ? array.length / this.stride : 0; - this.array = array; - - }, - - setDynamic: function ( value ) { - - this.dynamic = value; - - return this; - - }, - - copy: function ( source ) { - - this.array = new source.array.constructor( source.array ); - this.count = source.count; - this.stride = source.stride; - this.dynamic = source.dynamic; - - return this; - - }, - - copyAt: function ( index1, attribute, index2 ) { - - index1 *= this.stride; - index2 *= attribute.stride; - - for ( var i = 0, l = this.stride; i < l; i ++ ) { - - this.array[ index1 + i ] = attribute.array[ index2 + i ]; - - } - - return this; - - }, - - set: function ( value, offset ) { - - if ( offset === undefined ) offset = 0; - - this.array.set( value, offset ); - - return this; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - onUpload: function ( callback ) { - - this.onUploadCallback = callback; - - return this; - - } - - } ); - - function InstancedInterleavedBuffer( array, stride, meshPerAttribute ) { - - InterleavedBuffer.call( this, array, stride ); - - this.meshPerAttribute = meshPerAttribute || 1; - - } - - InstancedInterleavedBuffer.prototype = Object.assign( Object.create( InterleavedBuffer.prototype ), { - - constructor: InstancedInterleavedBuffer, - - isInstancedInterleavedBuffer: true, - - copy: function ( source ) { - - InterleavedBuffer.prototype.copy.call( this, source ); - - this.meshPerAttribute = source.meshPerAttribute; - - return this; - - } - - } ); - - /** - * @author simonThiele / https://github.com/simonThiele - */ - /* global QUnit */ - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'InstancedInterleavedBuffer', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - var array = new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ); - var instance = new InstancedInterleavedBuffer( array, 3 ); - - assert.ok( instance.meshPerAttribute === 1, "ok" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isInstancedInterleavedBuffer", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - var array = new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ); - var instance = new InstancedInterleavedBuffer( array, 3 ); - var copiedInstance = instance.copy( instance ); - - assert.ok( copiedInstance.meshPerAttribute === 1, "additional attribute was copied" ); - - } ); - - } ); - - } ); - - /** - * @author simonThiele / https://github.com/simonThiele - */ - /* global QUnit */ - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'InterleavedBuffer', () => { - - function checkInstanceAgainstCopy( instance, copiedInstance, assert ) { - - assert.ok( copiedInstance instanceof InterleavedBuffer, "the clone has the correct type" ); - - for ( var i = 0; i < instance.array.length; i ++ ) { - - assert.ok( copiedInstance.array[ i ] === instance.array[ i ], "array was copied" ); - - } - - assert.ok( copiedInstance.stride === instance.stride, "stride was copied" ); - assert.ok( copiedInstance.dynamic === true, "dynamic was copied" ); - - } - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PROPERTIES - QUnit.test( "needsUpdate", ( assert ) => { - - var a = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 4 ], 2 ) ); - - a.needsUpdate = true; - - assert.strictEqual( a.version, 1, "Check version increased" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isInterleavedBuffer", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setArray", ( assert ) => { - - var f32a = new Float32Array( [ 1, 2, 3, 4 ] ); - var f32b = new Float32Array( [] ); - var a = new InterleavedBuffer( f32a, 2, false ); - - a.setArray( f32a ); - - assert.strictEqual( a.count, 2, "Check item count for non-empty array" ); - assert.strictEqual( a.array, f32a, "Check array itself" ); - - a.setArray( f32b ); - - assert.strictEqual( a.count, 0, "Check item count for empty array" ); - assert.strictEqual( a.array, f32b, "Check array itself" ); - - assert.throws( - function () { - - a.setArray( [ 1, 2, 3, 4 ] ); - - }, - /array should be a Typed Array/, - "Calling setArray with a non-typed array throws Error" - ); - - } ); - - QUnit.test( "setDynamic", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - var array = new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ); - var instance = new InterleavedBuffer( array, 3 ); - instance.setDynamic( true ); - - checkInstanceAgainstCopy( instance, instance.copy( instance ), assert ); - - } ); - - QUnit.test( "copyAt", ( assert ) => { - - var a = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] ), 3 ); - var b = new InterleavedBuffer( new Float32Array( 9 ), 3 ); - var expected = new Float32Array( [ 4, 5, 6, 7, 8, 9, 1, 2, 3 ] ); - - b.copyAt( 1, a, 2 ); - b.copyAt( 0, a, 1 ); - b.copyAt( 2, a, 0 ); - - assert.deepEqual( b.array, expected, "Check the right values were replaced" ); - - } ); - - QUnit.test( "set", ( assert ) => { - - var instance = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ), 3 ); - - instance.set( [ 0, - 1 ] ); - assert.ok( instance.array[ 0 ] === 0 && instance.array[ 1 ] === - 1, "replace at first by default" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - var array = new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ); - var instance = new InterleavedBuffer( array, 3 ); - instance.setDynamic( true ); - - checkInstanceAgainstCopy( instance, instance.clone(), assert ); - - } ); - - QUnit.test( "onUpload", ( assert ) => { - - var a = new InterleavedBuffer(); - var func = function () { }; - - a.onUpload( func ); - - assert.strictEqual( a.onUploadCallback, func, "Check callback was set properly" ); - - } ); - - // OTHERS - QUnit.test( "count", ( assert ) => { - - var instance = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ), 3 ); - - assert.equal( instance.count, 2, "count is calculated via array length / stride" ); - - } ); - - } ); - - } ); - - function InterleavedBufferAttribute( interleavedBuffer, itemSize, offset, normalized ) { - - this.uuid = _Math.generateUUID(); - - this.data = interleavedBuffer; - this.itemSize = itemSize; - this.offset = offset; - - this.normalized = normalized === true; - - } - - Object.defineProperties( InterleavedBufferAttribute.prototype, { - - count: { - - get: function () { - - return this.data.count; - - } - - }, - - array: { - - get: function () { - - return this.data.array; - - } - - } - - } ); - - Object.assign( InterleavedBufferAttribute.prototype, { - - isInterleavedBufferAttribute: true, - - setX: function ( index, x ) { - - this.data.array[ index * this.data.stride + this.offset ] = x; - - return this; - - }, - - setY: function ( index, y ) { - - this.data.array[ index * this.data.stride + this.offset + 1 ] = y; - - return this; - - }, - - setZ: function ( index, z ) { - - this.data.array[ index * this.data.stride + this.offset + 2 ] = z; - - return this; - - }, - - setW: function ( index, w ) { - - this.data.array[ index * this.data.stride + this.offset + 3 ] = w; - - return this; - - }, - - getX: function ( index ) { - - return this.data.array[ index * this.data.stride + this.offset ]; - - }, - - getY: function ( index ) { - - return this.data.array[ index * this.data.stride + this.offset + 1 ]; - - }, - - getZ: function ( index ) { - - return this.data.array[ index * this.data.stride + this.offset + 2 ]; - - }, - - getW: function ( index ) { - - return this.data.array[ index * this.data.stride + this.offset + 3 ]; - - }, - - setXY: function ( index, x, y ) { - - index = index * this.data.stride + this.offset; - - this.data.array[ index + 0 ] = x; - this.data.array[ index + 1 ] = y; - - return this; - - }, - - setXYZ: function ( index, x, y, z ) { - - index = index * this.data.stride + this.offset; - - this.data.array[ index + 0 ] = x; - this.data.array[ index + 1 ] = y; - this.data.array[ index + 2 ] = z; - - return this; - - }, - - setXYZW: function ( index, x, y, z, w ) { - - index = index * this.data.stride + this.offset; - - this.data.array[ index + 0 ] = x; - this.data.array[ index + 1 ] = y; - this.data.array[ index + 2 ] = z; - this.data.array[ index + 3 ] = w; - - return this; - - } - - } ); - - /** - * @author simonThiele / https://github.com/simonThiele - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'InterleavedBufferAttribute', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PROPERTIES - QUnit.test( "count", ( assert ) => { - - var buffer = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ), 3 ); - var instance = new InterleavedBufferAttribute( buffer, 2, 0 ); - - assert.ok( instance.count === 2, "count is calculated via array length / stride" ); - - } ); - - QUnit.test( "array", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - // setY, setZ and setW are calculated in the same way so not QUnit.testing this - // TODO: ( you can't be sure that will be the case in future, or a mistake was introduce in one off them ! ) - QUnit.test( "setX", ( assert ) => { - - var buffer = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ), 3 ); - var instance = new InterleavedBufferAttribute( buffer, 2, 0 ); - - instance.setX( 0, 123 ); - instance.setX( 1, 321 ); - - assert.ok( instance.data.array[ 0 ] === 123 && - instance.data.array[ 3 ] === 321, "x was calculated correct based on index and default offset" ); - - var buffer = new InterleavedBuffer( new Float32Array( [ 1, 2, 3, 7, 8, 9 ] ), 3 ); - var instance = new InterleavedBufferAttribute( buffer, 2, 1 ); - - instance.setX( 0, 123 ); - instance.setX( 1, 321 ); - - // the offset was defined as 1, so go one step futher in the array - assert.ok( instance.data.array[ 1 ] === 123 && - instance.data.array[ 4 ] === 321, "x was calculated correct based on index and default offset" ); - - } ); - - QUnit.test( "setY", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setZ", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setW", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getX", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getY", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getZ", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getW", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setXY", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setXYZ", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setXYZW", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author moraxy / https://github.com/moraxy - */ - /* global QUnit */ - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'Layers', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "set", ( assert ) => { - - var a = new Layers(); - - a.set( 0 ); - assert.strictEqual( a.mask, 1, "Set channel 0" ); - - a.set( 1 ); - assert.strictEqual( a.mask, 2, "Set channel 1" ); - - a.set( 2 ); - assert.strictEqual( a.mask, 4, "Set channel 2" ); - - } ); - - QUnit.test( "enable", ( assert ) => { - - var a = new Layers(); - - a.set( 0 ); - a.enable( 0 ); - assert.strictEqual( a.mask, 1, "Enable channel 0 with mask 0" ); - - a.set( 0 ); - a.enable( 1 ); - assert.strictEqual( a.mask, 3, "Enable channel 1 with mask 0" ); - - a.set( 1 ); - a.enable( 0 ); - assert.strictEqual( a.mask, 3, "Enable channel 0 with mask 1" ); - - a.set( 1 ); - a.enable( 1 ); - assert.strictEqual( a.mask, 2, "Enable channel 1 with mask 1" ); - - } ); - - QUnit.test( "toggle", ( assert ) => { - - var a = new Layers(); - - a.set( 0 ); - a.toggle( 0 ); - assert.strictEqual( a.mask, 0, "Toggle channel 0 with mask 0" ); - - a.set( 0 ); - a.toggle( 1 ); - assert.strictEqual( a.mask, 3, "Toggle channel 1 with mask 0" ); - - a.set( 1 ); - a.toggle( 0 ); - assert.strictEqual( a.mask, 3, "Toggle channel 0 with mask 1" ); - - a.set( 1 ); - a.toggle( 1 ); - assert.strictEqual( a.mask, 0, "Toggle channel 1 with mask 1" ); - - } ); - - QUnit.test( "disable", ( assert ) => { - - var a = new Layers(); - - a.set( 0 ); - a.disable( 0 ); - assert.strictEqual( a.mask, 0, "Disable channel 0 with mask 0" ); - - a.set( 0 ); - a.disable( 1 ); - assert.strictEqual( a.mask, 1, "Disable channel 1 with mask 0" ); - - a.set( 1 ); - a.disable( 0 ); - assert.strictEqual( a.mask, 2, "Disable channel 0 with mask 1" ); - - a.set( 1 ); - a.disable( 1 ); - assert.strictEqual( a.mask, 0, "Disable channel 1 with mask 1" ); - - } ); - - QUnit.test( "test", ( assert ) => { - - var a = new Layers(); - var b = new Layers(); - - assert.ok( a.test( b ), "Start out true" ); - - a.set( 1 ); - assert.notOk( a.test( b ), "Set channel 1 in a and fail the QUnit.test" ); - - b.toggle( 1 ); - assert.ok( a.test( b ), "Toggle channel 1 in b and pass again" ); - - } ); - - } ); - - } ); - - /** - * @author simonThiele / https://github.com/simonThiele - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'Object3D', () => { - - var RadToDeg = 180 / Math.PI; - - var eulerEquals = function ( a, b, tolerance ) { - - tolerance = tolerance || 0.0001; - - if ( a.order != b.order ) { - - return false; - - } - - return ( - Math.abs( a.x - b.x ) <= tolerance && - Math.abs( a.y - b.y ) <= tolerance && - Math.abs( a.z - b.z ) <= tolerance - ); - - }; - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // STATIC STUFF - QUnit.test( "DefaultUp", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "DefaultMatrixAutoUpdate", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isObject3D", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "onBeforeRender", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "onAfterRender", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "applyMatrix", ( assert ) => { - - var a = new Object3D(); - var m = new Matrix4(); - var expectedPos = new Vector3( x, y, z ); - var expectedQuat = new Quaternion( 0.5 * Math.sqrt( 2 ), 0, 0, 0.5 * Math.sqrt( 2 ) ); - - m.makeRotationX( Math.PI / 2 ); - m.setPosition( new Vector3( x, y, z ) ); - - a.applyMatrix( m ); - - assert.deepEqual( a.position, expectedPos, "Position has the expected values" ); - assert.ok( - Math.abs( a.quaternion.x - expectedQuat.x ) <= eps && - Math.abs( a.quaternion.y - expectedQuat.y ) <= eps && - Math.abs( a.quaternion.z - expectedQuat.z ) <= eps, - "Quaternion has the expected values" - ); - - } ); - - QUnit.test( "applyQuaternion", ( assert ) => { - - var a = new Object3D(); - var sqrt = 0.5 * Math.sqrt( 2 ); - var quat = new Quaternion( 0, sqrt, 0, sqrt ); - var expected = new Quaternion( sqrt / 2, sqrt / 2, 0, 0 ); - - a.quaternion.set( 0.25, 0.25, 0.25, 0.25 ); - a.applyQuaternion( quat ); - - assert.ok( - Math.abs( a.quaternion.x - expected.x ) <= eps && - Math.abs( a.quaternion.y - expected.y ) <= eps && - Math.abs( a.quaternion.z - expected.z ) <= eps, - "Quaternion has the expected values" - ); - - } ); - - QUnit.test( "setRotationFromAxisAngle", ( assert ) => { - - var a = new Object3D(); - var axis = new Vector3( 0, 1, 0 ); - var angle = Math.PI; - var expected = new Euler( - Math.PI, 0, - Math.PI ); - - a.setRotationFromAxisAngle( axis, angle ); - assert.ok( eulerEquals( a.getWorldRotation(), expected ), "Correct values after rotation" ); - - axis.set( 1, 0, 0 ); - var angle = 0; - expected.set( 0, 0, 0 ); - - a.setRotationFromAxisAngle( axis, angle ); - assert.ok( eulerEquals( a.getWorldRotation(), expected ), "Correct values after zeroing" ); - - } ); - - QUnit.test( "setRotationFromEuler", ( assert ) => { - - var a = new Object3D(); - var rotation = new Euler( ( 45 / RadToDeg ), 0, Math.PI ); - var expected = rotation.clone(); // bit obvious - - a.setRotationFromEuler( rotation ); - assert.ok( eulerEquals( a.getWorldRotation(), expected ), "Correct values after rotation" ); - - } ); - - QUnit.test( "setRotationFromMatrix", ( assert ) => { - - var a = new Object3D(); - var m = new Matrix4(); - var eye = new Vector3( 0, 0, 0 ); - var target = new Vector3( 0, 1, - 1 ); - var up = new Vector3( 0, 1, 0 ); - - m.lookAt( eye, target, up ); - a.setRotationFromMatrix( m ); - assert.numEqual( a.getWorldRotation().x * RadToDeg, 45, "Correct rotation angle" ); - - } ); - - QUnit.test( "setRotationFromQuaternion", ( assert ) => { - - var a = new Object3D(); - var rotation = new Quaternion().setFromEuler( new Euler( Math.PI, 0, - Math.PI ) ); - var expected = new Euler( Math.PI, 0, - Math.PI ); - - a.setRotationFromQuaternion( rotation ); - assert.ok( eulerEquals( a.getWorldRotation(), expected ), "Correct values after rotation" ); - - } ); - - QUnit.test( "rotateOnAxis", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "rotateOnWorldAxis", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "rotateX", ( assert ) => { - - var obj = new Object3D(); - - var angleInRad = 1.562; - obj.rotateX( angleInRad ); - - assert.numEqual( obj.rotation.x, angleInRad, "x is equal" ); - - } ); - - QUnit.test( "rotateY", ( assert ) => { - - var obj = new Object3D(); - - var angleInRad = - 0.346; - obj.rotateY( angleInRad ); - - assert.numEqual( obj.rotation.y, angleInRad, "y is equal" ); - - } ); - - QUnit.test( "rotateZ", ( assert ) => { - - var obj = new Object3D(); - - var angleInRad = 1; - obj.rotateZ( angleInRad ); - - assert.numEqual( obj.rotation.z, angleInRad, "z is equal" ); - - } ); - - QUnit.test( "translateOnAxis", ( assert ) => { - - var obj = new Object3D(); - - obj.translateOnAxis( new Vector3( 1, 0, 0 ), 1 ); - obj.translateOnAxis( new Vector3( 0, 1, 0 ), 1.23 ); - obj.translateOnAxis( new Vector3( 0, 0, 1 ), - 4.56 ); - - assert.propEqual( obj.position, { - x: 1, - y: 1.23, - z: - 4.56 - } ); - - } ); - - QUnit.test( "translateX", ( assert ) => { - - var obj = new Object3D(); - obj.translateX( 1.234 ); - - assert.numEqual( obj.position.x, 1.234, "x is equal" ); - - } ); - - QUnit.test( "translateY", ( assert ) => { - - var obj = new Object3D(); - obj.translateY( 1.234 ); - - assert.numEqual( obj.position.y, 1.234, "y is equal" ); - - } ); - - QUnit.test( "translateZ", ( assert ) => { - - var obj = new Object3D(); - obj.translateZ( 1.234 ); - - assert.numEqual( obj.position.z, 1.234, "z is equal" ); - - } ); - - QUnit.test( "localToWorld", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "worldToLocal", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "lookAt", ( assert ) => { - - var obj = new Object3D(); - obj.lookAt( new Vector3( 0, - 1, 1 ) ); - - assert.numEqual( obj.rotation.x * RadToDeg, 45, "x is equal" ); - - } ); - - QUnit.test( "add/remove", ( assert ) => { - - var a = new Object3D(); - var child1 = new Object3D(); - var child2 = new Object3D(); - - assert.strictEqual( a.children.length, 0, "Starts with no children" ); - - a.add( child1 ); - assert.strictEqual( a.children.length, 1, "The first child was added" ); - assert.strictEqual( a.children[ 0 ], child1, "It's the right one" ); - - a.add( child2 ); - assert.strictEqual( a.children.length, 2, "The second child was added" ); - assert.strictEqual( a.children[ 1 ], child2, "It's the right one" ); - assert.strictEqual( a.children[ 0 ], child1, "The first one is still there" ); - - a.remove( child1 ); - assert.strictEqual( a.children.length, 1, "The first child was removed" ); - assert.strictEqual( a.children[ 0 ], child2, "The second one is still there" ); - - a.add( child1 ); - a.remove( child1, child2 ); - assert.strictEqual( a.children.length, 0, "Both children were removed at once" ); - - child1.add( child2 ); - assert.strictEqual( child1.children.length, 1, "The second child was added to the first one" ); - a.add( child2 ); - assert.strictEqual( a.children.length, 1, "The second one was added to the parent (no remove)" ); - assert.strictEqual( a.children[ 0 ], child2, "The second one is now the parent's child again" ); - assert.strictEqual( child1.children.length, 0, "The first one no longer has any children" ); - - } ); - - QUnit.test( "getObjectById/getObjectByName/getObjectByProperty", ( assert ) => { - - var parent = new Object3D(); - var childName = new Object3D(); - var childId = new Object3D(); // id = parent.id + 2 - var childNothing = new Object3D(); - - parent.prop = true; - childName.name = "foo"; - parent.add( childName, childId, childNothing ); - - assert.strictEqual( parent.getObjectByProperty( 'prop', true ), parent, "Get parent by its own property" ); - assert.strictEqual( parent.getObjectByName( "foo" ), childName, "Get child by name" ); - assert.strictEqual( parent.getObjectById( parent.id + 2 ), childId, "Get child by Id" ); - assert.strictEqual( - parent.getObjectByProperty( 'no-property', 'no-value' ), undefined, - "Unknown property results in undefined" - ); - - } ); - - QUnit.test( "getWorldPosition", ( assert ) => { - - var a = new Object3D(); - var b = new Object3D(); - var expectedSingle = new Vector3( x, y, z ); - var expectedParent = new Vector3( x, y, 0 ); - var expectedChild = new Vector3( x, y, 7 + ( z - z ) ); - - a.translateX( x ); - a.translateY( y ); - a.translateZ( z ); - - assert.deepEqual( - a.getWorldPosition(), expectedSingle, - "WorldPosition as expected for single object" - ); - - // translate child and then parent - b.translateZ( 7 ); - a.add( b ); - a.translateZ( - z ); - - assert.deepEqual( a.getWorldPosition(), expectedParent, "WorldPosition as expected for parent" ); - assert.deepEqual( b.getWorldPosition(), expectedChild, "WorldPosition as expected for child" ); - - } ); - - QUnit.test( "getWorldQuaternion", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getWorldRotation", ( assert ) => { - - var obj = new Object3D(); - - obj.lookAt( new Vector3( 0, - 1, 1 ) ); - assert.numEqual( obj.getWorldRotation().x * RadToDeg, 45, "x is equal" ); - - obj.lookAt( new Vector3( 1, 0, 0 ) ); - assert.numEqual( obj.getWorldRotation().y * RadToDeg, 90, "y is equal" ); - - } ); - - QUnit.test( "getWorldScale", ( assert ) => { - - var a = new Object3D(); - var m = new Matrix4().makeScale( x, y, z ); - var expected = new Vector3( x, y, z ); - - a.applyMatrix( m ); - - assert.deepEqual( a.getWorldScale(), expected, "WorldScale as expected" ); - - } ); - - QUnit.test( "getWorldDirection", ( assert ) => { - - var a = new Object3D(); - var expected = new Vector3( 0, - 0.5 * Math.sqrt( 2 ), 0.5 * Math.sqrt( 2 ) ); - var dir; - - a.lookAt( new Vector3( 0, - 1, 1 ) ); - dir = a.getWorldDirection(); - - assert.ok( - Math.abs( dir.x - expected.x ) <= eps && - Math.abs( dir.y - expected.y ) <= eps && - Math.abs( dir.z - expected.z ) <= eps, - "Direction has the expected values" - ); - - } ); - - QUnit.test( "raycast", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "traverse/traverseVisible/traverseAncestors", ( assert ) => { - - var a = new Object3D(); - var b = new Object3D(); - var c = new Object3D(); - var d = new Object3D(); - var names = []; - var expectedNormal = [ "parent", "child", "childchild 1", "childchild 2" ]; - var expectedVisible = [ "parent", "child", "childchild 2" ]; - var expectedAncestors = [ "child", "parent" ]; - - a.name = "parent"; - b.name = "child"; - c.name = "childchild 1"; - c.visible = false; - d.name = "childchild 2"; - - b.add( c ); - b.add( d ); - a.add( b ); - - a.traverse( function ( obj ) { - - names.push( obj.name ); - - } ); - assert.deepEqual( names, expectedNormal, "Traversed objects in expected order" ); - - var names = []; - a.traverseVisible( function ( obj ) { - - names.push( obj.name ); - - } ); - assert.deepEqual( names, expectedVisible, "Traversed visible objects in expected order" ); - - var names = []; - c.traverseAncestors( function ( obj ) { - - names.push( obj.name ); - - } ); - assert.deepEqual( names, expectedAncestors, "Traversed ancestors in expected order" ); - - } ); - - QUnit.test( "updateMatrix", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "updateMatrixWorld", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "toJSON", ( assert ) => { - - var a = new Object3D(); - var child = new Object3D(); - var childChild = new Object3D(); - - a.name = "a's name"; - a.matrix.set( 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ); - a.visible = false; - a.castShadow = true; - a.receiveShadow = true; - a.userData[ "foo" ] = "bar"; - - child.uuid = "5D4E9AE8-DA61-4912-A575-71A5BE3D72CD"; - childChild.uuid = "B43854B3-E970-4E85-BD41-AAF8D7BFA189"; - child.add( childChild ); - a.add( child ); - - var gold = { - "metadata": { - "version": 4.5, - "type": "Object", - "generator": "Object3D.toJSON" - }, - "object": { - "uuid": "0A1E4F43-CB5B-4097-8F82-DC2969C0B8C2", - "type": "Object3D", - "name": "a's name", - "castShadow": true, - "receiveShadow": true, - "visible": false, - "userData": { "foo": "bar" }, - "matrix": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ], - "children": [ - { - "uuid": "5D4E9AE8-DA61-4912-A575-71A5BE3D72CD", - "type": "Object3D", - "matrix": [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ], - "children": [ - { - "uuid": "B43854B3-E970-4E85-BD41-AAF8D7BFA189", - "type": "Object3D", - "matrix": [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ] - } - ] - } - ] - } - }; - - // hacks - var out = a.toJSON(); - out.object.uuid = "0A1E4F43-CB5B-4097-8F82-DC2969C0B8C2"; - - assert.deepEqual( out, gold, "JSON is as expected" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - var a; - var b = new Object3D(); - - assert.strictEqual( a, undefined, "Undefined pre-clone()" ); - - a = b.clone(); - assert.notStrictEqual( a, b, "Defined but seperate instances post-clone()" ); - - a.uuid = b.uuid; - assert.deepEqual( a, b, "But identical properties" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - var a = new Object3D(); - var b = new Object3D(); - var child = new Object3D(); - var childChild = new Object3D(); - - a.name = "original"; - b.name = "to-be-copied"; - - b.position.set( x, y, z ); - b.quaternion.set( x, y, z, w ); - b.scale.set( 2, 3, 4 ); - - // bogus QUnit.test values - b.matrix.set( 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ); - b.matrixWorld.set( 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ); - - b.matrixAutoUpdate = false; - b.matrixWorldNeedsUpdate = true; - - b.layers.mask = 2; - b.visible = false; - - b.castShadow = true; - b.receiveShadow = true; - - b.frustumCulled = false; - b.renderOrder = 1; - - b.userData[ "foo" ] = "bar"; - - child.add( childChild ); - b.add( child ); - - assert.notDeepEqual( a, b, "Objects are not equal pre-copy()" ); - a.copy( b, true ); - - // check they're all unique instances - assert.ok( - a.uuid !== b.uuid && - a.children[ 0 ].uuid !== b.children[ 0 ].uuid && - a.children[ 0 ].children[ 0 ].uuid !== b.children[ 0 ].children[ 0 ].uuid, - "UUIDs are all different" - ); - - // and now fix that - a.uuid = b.uuid; - a.children[ 0 ].uuid = b.children[ 0 ].uuid; - a.children[ 0 ].children[ 0 ].uuid = b.children[ 0 ].children[ 0 ].uuid; - - assert.deepEqual( a, b, "Objects are equal post-copy()" ); - - } ); - - } ); - - } ); - - function Raycaster( origin, direction, near, far ) { - - this.ray = new Ray( origin, direction ); - // direction is assumed to be normalized (for accurate distance calculations) - - this.near = near || 0; - this.far = far || Infinity; - - this.params = { - Mesh: {}, - Line: {}, - LOD: {}, - Points: { threshold: 1 }, - Sprite: {} - }; - - Object.defineProperties( this.params, { - PointCloud: { - get: function () { - - console.warn( 'THREE.Raycaster: params.PointCloud has been renamed to params.Points.' ); - return this.Points; - - } - } - } ); - - } - - function ascSort( a, b ) { - - return a.distance - b.distance; - - } - - function intersectObject( object, raycaster, intersects, recursive ) { - - if ( object.visible === false ) return; - - object.raycast( raycaster, intersects ); - - if ( recursive === true ) { - - var children = object.children; - - for ( var i = 0, l = children.length; i < l; i ++ ) { - - intersectObject( children[ i ], raycaster, intersects, true ); - - } - - } - - } - - Object.assign( Raycaster.prototype, { - - linePrecision: 1, - - set: function ( origin, direction ) { - - // direction is assumed to be normalized (for accurate distance calculations) - - this.ray.set( origin, direction ); - - }, - - setFromCamera: function ( coords, camera ) { - - if ( ( camera && camera.isPerspectiveCamera ) ) { - - this.ray.origin.setFromMatrixPosition( camera.matrixWorld ); - this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize(); - - } else if ( ( camera && camera.isOrthographicCamera ) ) { - - this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera - this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ); - - } else { - - console.error( 'THREE.Raycaster: Unsupported camera type.' ); - - } - - }, - - intersectObject: function ( object, recursive ) { - - var intersects = []; - - intersectObject( object, this, intersects, recursive ); - - intersects.sort( ascSort ); - - return intersects; - - }, - - intersectObjects: function ( objects, recursive ) { - - var intersects = []; - - if ( Array.isArray( objects ) === false ) { - - console.warn( 'THREE.Raycaster.intersectObjects: objects is not an Array.' ); - return intersects; - - } - - for ( var i = 0, l = objects.length; i < l; i ++ ) { - - intersectObject( objects[ i ], this, intersects, recursive ); - - } - - intersects.sort( ascSort ); - - return intersects; - - } - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - * @author benaadams / https://twitter.com/ben_a_adams - * @author Mugen87 / https://github.com/Mugen87 - */ - - function SphereGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) { - - Geometry.call( this ); - - this.type = 'SphereGeometry'; - - this.parameters = { - radius: radius, - widthSegments: widthSegments, - heightSegments: heightSegments, - phiStart: phiStart, - phiLength: phiLength, - thetaStart: thetaStart, - thetaLength: thetaLength - }; - - this.fromBufferGeometry( new SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) ); - this.mergeVertices(); - - } - - SphereGeometry.prototype = Object.create( Geometry.prototype ); - SphereGeometry.prototype.constructor = SphereGeometry; - - // SphereBufferGeometry - - function SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) { - - BufferGeometry.call( this ); - - this.type = 'SphereBufferGeometry'; - - this.parameters = { - radius: radius, - widthSegments: widthSegments, - heightSegments: heightSegments, - phiStart: phiStart, - phiLength: phiLength, - thetaStart: thetaStart, - thetaLength: thetaLength - }; - - radius = radius || 1; - - widthSegments = Math.max( 3, Math.floor( widthSegments ) || 8 ); - heightSegments = Math.max( 2, Math.floor( heightSegments ) || 6 ); - - phiStart = phiStart !== undefined ? phiStart : 0; - phiLength = phiLength !== undefined ? phiLength : Math.PI * 2; - - thetaStart = thetaStart !== undefined ? thetaStart : 0; - thetaLength = thetaLength !== undefined ? thetaLength : Math.PI; - - var thetaEnd = thetaStart + thetaLength; - - var ix, iy; - - var index = 0; - var grid = []; - - var vertex = new Vector3(); - var normal = new Vector3(); - - // buffers - - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; - - // generate vertices, normals and uvs - - for ( iy = 0; iy <= heightSegments; iy ++ ) { - - var verticesRow = []; - - var v = iy / heightSegments; - - for ( ix = 0; ix <= widthSegments; ix ++ ) { - - var u = ix / widthSegments; - - // vertex - - vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); - vertex.y = radius * Math.cos( thetaStart + v * thetaLength ); - vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); - - vertices.push( vertex.x, vertex.y, vertex.z ); - - // normal - - normal.set( vertex.x, vertex.y, vertex.z ).normalize(); - normals.push( normal.x, normal.y, normal.z ); - - // uv - - uvs.push( u, 1 - v ); - - verticesRow.push( index ++ ); - - } - - grid.push( verticesRow ); - - } - - // indices - - for ( iy = 0; iy < heightSegments; iy ++ ) { - - for ( ix = 0; ix < widthSegments; ix ++ ) { - - var a = grid[ iy ][ ix + 1 ]; - var b = grid[ iy ][ ix ]; - var c = grid[ iy + 1 ][ ix ]; - var d = grid[ iy + 1 ][ ix + 1 ]; - - if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d ); - if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d ); - - } - - } - - // build geometry - - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - - } - - SphereBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - SphereBufferGeometry.prototype.constructor = SphereBufferGeometry; - - /** - * @author simonThiele / https://github.com/simonThiele - */ - /* global QUnit */ - - function checkRayDirectionAgainstReferenceVector( rayDirection, refVector, assert ) { - - assert.ok( refVector.x - rayDirection.x <= Number.EPSILON && refVector.y - rayDirection.y <= Number.EPSILON && refVector.z - rayDirection.z <= Number.EPSILON, "camera is pointing to" + - " the same direction as expected" ); - - } - - function getRaycaster() { - - return new Raycaster( - new Vector3( 0, 0, 0 ), - new Vector3( 0, 0, - 1 ), - 1, - 100 - ); - - } - - function getObjectsToCheck() { - - var objects = []; - - var sphere1 = getSphere(); - sphere1.position.set( 0, 0, - 10 ); - sphere1.name = 1; - objects.push( sphere1 ); - - var sphere11 = getSphere(); - sphere11.position.set( 0, 0, 1 ); - sphere11.name = 11; - sphere1.add( sphere11 ); - - var sphere12 = getSphere(); - sphere12.position.set( 0, 0, - 1 ); - sphere12.name = 12; - sphere1.add( sphere12 ); - - var sphere2 = getSphere(); - sphere2.position.set( - 5, 0, - 5 ); - sphere2.name = 2; - objects.push( sphere2 ); - - for ( var i = 0; i < objects.length; i ++ ) { - - objects[ i ].updateMatrixWorld(); - - } - - return objects; - - } - - function getSphere() { - - return new Mesh( new SphereGeometry( 1, 100, 100 ) ); - - } - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'Raycaster', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "linePrecision", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "set", ( assert ) => { - - var origin = new Vector3( 0, 0, 0 ); - var direction = new Vector3( 0, 0, - 1 ); - var a = new Raycaster( origin.clone(), direction.clone() ); - - assert.deepEqual( a.ray.origin, origin, "Origin is correct" ); - assert.deepEqual( a.ray.direction, direction, "Direction is correct" ); - - origin.set( 1, 1, 1 ); - direction.set( - 1, 0, 0 ); - a.set( origin, direction ); - - assert.deepEqual( a.ray.origin, origin, "Origin was set correctly" ); - assert.deepEqual( a.ray.direction, direction, "Direction was set correctly" ); - - } ); - - QUnit.test( "setFromCamera (Perspective)", ( assert ) => { - - var raycaster = new Raycaster(); - var rayDirection = raycaster.ray.direction; - var camera = new PerspectiveCamera( 90, 1, 1, 1000 ); - - raycaster.setFromCamera( { - x: 0, - y: 0 - }, camera ); - assert.ok( rayDirection.x === 0, rayDirection.y === 0, rayDirection.z === - 1, - "camera is looking straight to -z and so does the ray in the middle of the screen" ); - - var step = 0.1; - - for ( var x = - 1; x <= 1; x += step ) { - - for ( var y = - 1; y <= 1; y += step ) { - - raycaster.setFromCamera( { - x, - y - }, camera ); - - var refVector = new Vector3( x, y, - 1 ).normalize(); - - checkRayDirectionAgainstReferenceVector( rayDirection, refVector, assert ); - - } - - } - - } ); - - QUnit.test( "setFromCamera (Orthographic)", ( assert ) => { - - var raycaster = new Raycaster(); - var rayOrigin = raycaster.ray.origin; - var rayDirection = raycaster.ray.direction; - var camera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1000 ); - var expectedOrigin = new Vector3( 0, 0, 0 ); - var expectedDirection = new Vector3( 0, 0, - 1 ); - - raycaster.setFromCamera( { - x: 0, - y: 0 - }, camera ); - assert.deepEqual( rayOrigin, expectedOrigin, "Ray origin has the right coordinates" ); - assert.deepEqual( rayDirection, expectedDirection, "Camera and Ray are pointing towards -z" ); - - } ); - - QUnit.test( "intersectObject", ( assert ) => { - - var raycaster = getRaycaster(); - var objectsToCheck = getObjectsToCheck(); - - assert.ok( raycaster.intersectObject( objectsToCheck[ 0 ] ).length === 1, - "no recursive search should lead to one hit" ); - - assert.ok( raycaster.intersectObject( objectsToCheck[ 0 ], true ).length === 3, - "recursive search should lead to three hits" ); - - var intersections = raycaster.intersectObject( objectsToCheck[ 0 ], true ); - for ( var i = 0; i < intersections.length - 1; i ++ ) { - - assert.ok( intersections[ i ].distance <= intersections[ i + 1 ].distance, "intersections are sorted" ); - - } - - } ); - - QUnit.test( "intersectObjects", ( assert ) => { - - var raycaster = getRaycaster(); - var objectsToCheck = getObjectsToCheck(); - - assert.ok( raycaster.intersectObjects( objectsToCheck ).length === 1, - "no recursive search should lead to one hit" ); - - assert.ok( raycaster.intersectObjects( objectsToCheck, true ).length === 3, - "recursive search should lead to three hits" ); - - var intersections = raycaster.intersectObjects( objectsToCheck, true ); - for ( var i = 0; i < intersections.length - 1; i ++ ) { - - assert.ok( intersections[ i ].distance <= intersections[ i + 1 ].distance, "intersections are sorted" ); - - } - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function Uniform( value ) { - - if ( typeof value === 'string' ) { - - console.warn( 'THREE.Uniform: Type parameter is no longer needed.' ); - value = arguments[ 1 ]; - - } - - this.value = value; - - } - - Uniform.prototype.clone = function () { - - return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() ); - - }; - - /** - * @author moraxy / https://github.com/moraxy - */ - /* global QUnit */ - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'Uniform', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - var a; - var b = new Vector3( x, y, z ); - - a = new Uniform( 5 ); - assert.strictEqual( a.value, 5, "New constructor works with simple values" ); - - a = new Uniform( b ); - assert.ok( a.value.equals( b ), "New constructor works with complex values" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "clone", ( assert ) => { - - var a = new Uniform( 23 ); - var b = a.clone(); - - assert.strictEqual( b.value, a.value, "clone() with simple values works" ); - - var a = new Uniform( new Vector3( 1, 2, 3 ) ); - var b = a.clone(); - - assert.ok( b.value.equals( a.value ), "clone() with complex values works" ); - - } ); - - } ); - - } ); - - function Group() { - - Object3D.call( this ); - - this.type = 'Group'; - - } - - Group.prototype = Object.assign( Object.create( Object3D.prototype ), { - - constructor: Group - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module.todo( 'Extras', () => { - - QUnit.module.todo( 'SceneUtils', () => { - - // PUBLIC STUFF - QUnit.test( "createMultiMaterialObject", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "detach", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "attach", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author zz85 / http://www.lab4games.net/zz85/blog - */ - - var ShapeUtils = { - - // calculate area of the contour polygon - - area: function ( contour ) { - - var n = contour.length; - var a = 0.0; - - for ( var p = n - 1, q = 0; q < n; p = q ++ ) { - - a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y; - - } - - return a * 0.5; - - }, - - triangulate: ( function () { - - /** - * This code is a quick port of code written in C++ which was submitted to - * flipcode.com by John W. Ratcliff // July 22, 2000 - * See original code and more information here: - * http://www.flipcode.com/archives/Efficient_Polygon_Triangulation.shtml - * - * ported to actionscript by Zevan Rosser - * www.actionsnippet.com - * - * ported to javascript by Joshua Koo - * http://www.lab4games.net/zz85/blog - * - */ - - function snip( contour, u, v, w, n, verts ) { - - var p; - var ax, ay, bx, by; - var cx, cy, px, py; - - ax = contour[ verts[ u ] ].x; - ay = contour[ verts[ u ] ].y; - - bx = contour[ verts[ v ] ].x; - by = contour[ verts[ v ] ].y; - - cx = contour[ verts[ w ] ].x; - cy = contour[ verts[ w ] ].y; - - if ( ( bx - ax ) * ( cy - ay ) - ( by - ay ) * ( cx - ax ) <= 0 ) return false; - - var aX, aY, bX, bY, cX, cY; - var apx, apy, bpx, bpy, cpx, cpy; - var cCROSSap, bCROSScp, aCROSSbp; - - aX = cx - bx; aY = cy - by; - bX = ax - cx; bY = ay - cy; - cX = bx - ax; cY = by - ay; - - for ( p = 0; p < n; p ++ ) { - - px = contour[ verts[ p ] ].x; - py = contour[ verts[ p ] ].y; - - if ( ( ( px === ax ) && ( py === ay ) ) || - ( ( px === bx ) && ( py === by ) ) || - ( ( px === cx ) && ( py === cy ) ) ) continue; - - apx = px - ax; apy = py - ay; - bpx = px - bx; bpy = py - by; - cpx = px - cx; cpy = py - cy; - - // see if p is inside triangle abc - - aCROSSbp = aX * bpy - aY * bpx; - cCROSSap = cX * apy - cY * apx; - bCROSScp = bX * cpy - bY * cpx; - - if ( ( aCROSSbp >= - Number.EPSILON ) && ( bCROSScp >= - Number.EPSILON ) && ( cCROSSap >= - Number.EPSILON ) ) return false; - - } - - return true; - - } - - // takes in an contour array and returns - - return function triangulate( contour, indices ) { - - var n = contour.length; - - if ( n < 3 ) return null; - - var result = [], - verts = [], - vertIndices = []; - - /* we want a counter-clockwise polygon in verts */ - - var u, v, w; - - if ( ShapeUtils.area( contour ) > 0.0 ) { - - for ( v = 0; v < n; v ++ ) verts[ v ] = v; - - } else { - - for ( v = 0; v < n; v ++ ) verts[ v ] = ( n - 1 ) - v; - - } - - var nv = n; - - /* remove nv - 2 vertices, creating 1 triangle every time */ - - var count = 2 * nv; /* error detection */ - - for ( v = nv - 1; nv > 2; ) { - - /* if we loop, it is probably a non-simple polygon */ - - if ( ( count -- ) <= 0 ) { - - //** Triangulate: ERROR - probable bad polygon! - - //throw ( "Warning, unable to triangulate polygon!" ); - //return null; - // Sometimes warning is fine, especially polygons are triangulated in reverse. - console.warn( 'THREE.ShapeUtils: Unable to triangulate polygon! in triangulate()' ); - - if ( indices ) return vertIndices; - return result; - - } - - /* three consecutive vertices in current polygon, */ - - u = v; if ( nv <= u ) u = 0; /* previous */ - v = u + 1; if ( nv <= v ) v = 0; /* new v */ - w = v + 1; if ( nv <= w ) w = 0; /* next */ - - if ( snip( contour, u, v, w, nv, verts ) ) { - - var a, b, c, s, t; - - /* true names of the vertices */ - - a = verts[ u ]; - b = verts[ v ]; - c = verts[ w ]; - - /* output Triangle */ - - result.push( [ contour[ a ], - contour[ b ], - contour[ c ] ] ); - - - vertIndices.push( [ verts[ u ], verts[ v ], verts[ w ] ] ); - - /* remove v from the remaining polygon */ - - for ( s = v, t = v + 1; t < nv; s ++, t ++ ) { - - verts[ s ] = verts[ t ]; - - } - - nv --; - - /* reset error detection counter */ - - count = 2 * nv; - - } - - } - - if ( indices ) return vertIndices; - return result; - - }; - - } )(), - - triangulateShape: function ( contour, holes ) { - - function removeDupEndPts( points ) { - - var l = points.length; - - if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) { - - points.pop(); - - } - - } - - removeDupEndPts( contour ); - holes.forEach( removeDupEndPts ); - - function point_in_segment_2D_colin( inSegPt1, inSegPt2, inOtherPt ) { - - // inOtherPt needs to be collinear to the inSegment - if ( inSegPt1.x !== inSegPt2.x ) { - - if ( inSegPt1.x < inSegPt2.x ) { - - return ( ( inSegPt1.x <= inOtherPt.x ) && ( inOtherPt.x <= inSegPt2.x ) ); - - } else { - - return ( ( inSegPt2.x <= inOtherPt.x ) && ( inOtherPt.x <= inSegPt1.x ) ); - - } - - } else { - - if ( inSegPt1.y < inSegPt2.y ) { - - return ( ( inSegPt1.y <= inOtherPt.y ) && ( inOtherPt.y <= inSegPt2.y ) ); - - } else { - - return ( ( inSegPt2.y <= inOtherPt.y ) && ( inOtherPt.y <= inSegPt1.y ) ); - - } - - } - - } - - function intersect_segments_2D( inSeg1Pt1, inSeg1Pt2, inSeg2Pt1, inSeg2Pt2, inExcludeAdjacentSegs ) { - - var seg1dx = inSeg1Pt2.x - inSeg1Pt1.x, seg1dy = inSeg1Pt2.y - inSeg1Pt1.y; - var seg2dx = inSeg2Pt2.x - inSeg2Pt1.x, seg2dy = inSeg2Pt2.y - inSeg2Pt1.y; - - var seg1seg2dx = inSeg1Pt1.x - inSeg2Pt1.x; - var seg1seg2dy = inSeg1Pt1.y - inSeg2Pt1.y; - - var limit = seg1dy * seg2dx - seg1dx * seg2dy; - var perpSeg1 = seg1dy * seg1seg2dx - seg1dx * seg1seg2dy; - - if ( Math.abs( limit ) > Number.EPSILON ) { - - // not parallel - - var perpSeg2; - if ( limit > 0 ) { - - if ( ( perpSeg1 < 0 ) || ( perpSeg1 > limit ) ) return []; - perpSeg2 = seg2dy * seg1seg2dx - seg2dx * seg1seg2dy; - if ( ( perpSeg2 < 0 ) || ( perpSeg2 > limit ) ) return []; - - } else { - - if ( ( perpSeg1 > 0 ) || ( perpSeg1 < limit ) ) return []; - perpSeg2 = seg2dy * seg1seg2dx - seg2dx * seg1seg2dy; - if ( ( perpSeg2 > 0 ) || ( perpSeg2 < limit ) ) return []; - - } - - // i.e. to reduce rounding errors - // intersection at endpoint of segment#1? - if ( perpSeg2 === 0 ) { - - if ( ( inExcludeAdjacentSegs ) && - ( ( perpSeg1 === 0 ) || ( perpSeg1 === limit ) ) ) return []; - return [ inSeg1Pt1 ]; - - } - if ( perpSeg2 === limit ) { - - if ( ( inExcludeAdjacentSegs ) && - ( ( perpSeg1 === 0 ) || ( perpSeg1 === limit ) ) ) return []; - return [ inSeg1Pt2 ]; - - } - // intersection at endpoint of segment#2? - if ( perpSeg1 === 0 ) return [ inSeg2Pt1 ]; - if ( perpSeg1 === limit ) return [ inSeg2Pt2 ]; - - // return real intersection point - var factorSeg1 = perpSeg2 / limit; - return [ { x: inSeg1Pt1.x + factorSeg1 * seg1dx, y: inSeg1Pt1.y + factorSeg1 * seg1dy } ]; - - } else { - - // parallel or collinear - if ( ( perpSeg1 !== 0 ) || - ( seg2dy * seg1seg2dx !== seg2dx * seg1seg2dy ) ) return []; - - // they are collinear or degenerate - var seg1Pt = ( ( seg1dx === 0 ) && ( seg1dy === 0 ) ); // segment1 is just a point? - var seg2Pt = ( ( seg2dx === 0 ) && ( seg2dy === 0 ) ); // segment2 is just a point? - // both segments are points - if ( seg1Pt && seg2Pt ) { - - if ( ( inSeg1Pt1.x !== inSeg2Pt1.x ) || - ( inSeg1Pt1.y !== inSeg2Pt1.y ) ) return []; // they are distinct points - return [ inSeg1Pt1 ]; // they are the same point - - } - // segment#1 is a single point - if ( seg1Pt ) { - - if ( ! point_in_segment_2D_colin( inSeg2Pt1, inSeg2Pt2, inSeg1Pt1 ) ) return []; // but not in segment#2 - return [ inSeg1Pt1 ]; - - } - // segment#2 is a single point - if ( seg2Pt ) { - - if ( ! point_in_segment_2D_colin( inSeg1Pt1, inSeg1Pt2, inSeg2Pt1 ) ) return []; // but not in segment#1 - return [ inSeg2Pt1 ]; - - } - - // they are collinear segments, which might overlap - var seg1min, seg1max, seg1minVal, seg1maxVal; - var seg2min, seg2max, seg2minVal, seg2maxVal; - if ( seg1dx !== 0 ) { - - // the segments are NOT on a vertical line - if ( inSeg1Pt1.x < inSeg1Pt2.x ) { - - seg1min = inSeg1Pt1; seg1minVal = inSeg1Pt1.x; - seg1max = inSeg1Pt2; seg1maxVal = inSeg1Pt2.x; - - } else { - - seg1min = inSeg1Pt2; seg1minVal = inSeg1Pt2.x; - seg1max = inSeg1Pt1; seg1maxVal = inSeg1Pt1.x; - - } - if ( inSeg2Pt1.x < inSeg2Pt2.x ) { - - seg2min = inSeg2Pt1; seg2minVal = inSeg2Pt1.x; - seg2max = inSeg2Pt2; seg2maxVal = inSeg2Pt2.x; - - } else { - - seg2min = inSeg2Pt2; seg2minVal = inSeg2Pt2.x; - seg2max = inSeg2Pt1; seg2maxVal = inSeg2Pt1.x; - - } - - } else { - - // the segments are on a vertical line - if ( inSeg1Pt1.y < inSeg1Pt2.y ) { - - seg1min = inSeg1Pt1; seg1minVal = inSeg1Pt1.y; - seg1max = inSeg1Pt2; seg1maxVal = inSeg1Pt2.y; - - } else { - - seg1min = inSeg1Pt2; seg1minVal = inSeg1Pt2.y; - seg1max = inSeg1Pt1; seg1maxVal = inSeg1Pt1.y; - - } - if ( inSeg2Pt1.y < inSeg2Pt2.y ) { - - seg2min = inSeg2Pt1; seg2minVal = inSeg2Pt1.y; - seg2max = inSeg2Pt2; seg2maxVal = inSeg2Pt2.y; - - } else { - - seg2min = inSeg2Pt2; seg2minVal = inSeg2Pt2.y; - seg2max = inSeg2Pt1; seg2maxVal = inSeg2Pt1.y; - - } - - } - if ( seg1minVal <= seg2minVal ) { - - if ( seg1maxVal < seg2minVal ) return []; - if ( seg1maxVal === seg2minVal ) { - - if ( inExcludeAdjacentSegs ) return []; - return [ seg2min ]; - - } - if ( seg1maxVal <= seg2maxVal ) return [ seg2min, seg1max ]; - return [ seg2min, seg2max ]; - - } else { - - if ( seg1minVal > seg2maxVal ) return []; - if ( seg1minVal === seg2maxVal ) { - - if ( inExcludeAdjacentSegs ) return []; - return [ seg1min ]; - - } - if ( seg1maxVal <= seg2maxVal ) return [ seg1min, seg1max ]; - return [ seg1min, seg2max ]; - - } - - } - - } - - function isPointInsideAngle( inVertex, inLegFromPt, inLegToPt, inOtherPt ) { - - // The order of legs is important - - // translation of all points, so that Vertex is at (0,0) - var legFromPtX = inLegFromPt.x - inVertex.x, legFromPtY = inLegFromPt.y - inVertex.y; - var legToPtX = inLegToPt.x - inVertex.x, legToPtY = inLegToPt.y - inVertex.y; - var otherPtX = inOtherPt.x - inVertex.x, otherPtY = inOtherPt.y - inVertex.y; - - // main angle >0: < 180 deg.; 0: 180 deg.; <0: > 180 deg. - var from2toAngle = legFromPtX * legToPtY - legFromPtY * legToPtX; - var from2otherAngle = legFromPtX * otherPtY - legFromPtY * otherPtX; - - if ( Math.abs( from2toAngle ) > Number.EPSILON ) { - - // angle != 180 deg. - - var other2toAngle = otherPtX * legToPtY - otherPtY * legToPtX; - // console.log( "from2to: " + from2toAngle + ", from2other: " + from2otherAngle + ", other2to: " + other2toAngle ); - - if ( from2toAngle > 0 ) { - - // main angle < 180 deg. - return ( ( from2otherAngle >= 0 ) && ( other2toAngle >= 0 ) ); - - } else { - - // main angle > 180 deg. - return ( ( from2otherAngle >= 0 ) || ( other2toAngle >= 0 ) ); - - } - - } else { - - // angle == 180 deg. - // console.log( "from2to: 180 deg., from2other: " + from2otherAngle ); - return ( from2otherAngle > 0 ); - - } - - } - - - function removeHoles( contour, holes ) { - - var shape = contour.concat(); // work on this shape - var hole; - - function isCutLineInsideAngles( inShapeIdx, inHoleIdx ) { - - // Check if hole point lies within angle around shape point - var lastShapeIdx = shape.length - 1; - - var prevShapeIdx = inShapeIdx - 1; - if ( prevShapeIdx < 0 ) prevShapeIdx = lastShapeIdx; - - var nextShapeIdx = inShapeIdx + 1; - if ( nextShapeIdx > lastShapeIdx ) nextShapeIdx = 0; - - var insideAngle = isPointInsideAngle( shape[ inShapeIdx ], shape[ prevShapeIdx ], shape[ nextShapeIdx ], hole[ inHoleIdx ] ); - if ( ! insideAngle ) { - - // console.log( "Vertex (Shape): " + inShapeIdx + ", Point: " + hole[inHoleIdx].x + "/" + hole[inHoleIdx].y ); - return false; - - } - - // Check if shape point lies within angle around hole point - var lastHoleIdx = hole.length - 1; - - var prevHoleIdx = inHoleIdx - 1; - if ( prevHoleIdx < 0 ) prevHoleIdx = lastHoleIdx; - - var nextHoleIdx = inHoleIdx + 1; - if ( nextHoleIdx > lastHoleIdx ) nextHoleIdx = 0; - - insideAngle = isPointInsideAngle( hole[ inHoleIdx ], hole[ prevHoleIdx ], hole[ nextHoleIdx ], shape[ inShapeIdx ] ); - if ( ! insideAngle ) { - - // console.log( "Vertex (Hole): " + inHoleIdx + ", Point: " + shape[inShapeIdx].x + "/" + shape[inShapeIdx].y ); - return false; - - } - - return true; - - } - - function intersectsShapeEdge( inShapePt, inHolePt ) { - - // checks for intersections with shape edges - var sIdx, nextIdx, intersection; - for ( sIdx = 0; sIdx < shape.length; sIdx ++ ) { - - nextIdx = sIdx + 1; nextIdx %= shape.length; - intersection = intersect_segments_2D( inShapePt, inHolePt, shape[ sIdx ], shape[ nextIdx ], true ); - if ( intersection.length > 0 ) return true; - - } - - return false; - - } - - var indepHoles = []; - - function intersectsHoleEdge( inShapePt, inHolePt ) { - - // checks for intersections with hole edges - var ihIdx, chkHole, - hIdx, nextIdx, intersection; - for ( ihIdx = 0; ihIdx < indepHoles.length; ihIdx ++ ) { - - chkHole = holes[ indepHoles[ ihIdx ] ]; - for ( hIdx = 0; hIdx < chkHole.length; hIdx ++ ) { - - nextIdx = hIdx + 1; nextIdx %= chkHole.length; - intersection = intersect_segments_2D( inShapePt, inHolePt, chkHole[ hIdx ], chkHole[ nextIdx ], true ); - if ( intersection.length > 0 ) return true; - - } - - } - return false; - - } - - var holeIndex, shapeIndex, - shapePt, holePt, - holeIdx, cutKey, failedCuts = [], - tmpShape1, tmpShape2, - tmpHole1, tmpHole2; - - for ( var h = 0, hl = holes.length; h < hl; h ++ ) { - - indepHoles.push( h ); - - } - - var minShapeIndex = 0; - var counter = indepHoles.length * 2; - while ( indepHoles.length > 0 ) { - - counter --; - if ( counter < 0 ) { - - console.log( 'THREE.ShapeUtils: Infinite Loop! Holes left:" + indepHoles.length + ", Probably Hole outside Shape!' ); - break; - - } - - // search for shape-vertex and hole-vertex, - // which can be connected without intersections - for ( shapeIndex = minShapeIndex; shapeIndex < shape.length; shapeIndex ++ ) { - - shapePt = shape[ shapeIndex ]; - holeIndex = - 1; - - // search for hole which can be reached without intersections - for ( var h = 0; h < indepHoles.length; h ++ ) { - - holeIdx = indepHoles[ h ]; - - // prevent multiple checks - cutKey = shapePt.x + ':' + shapePt.y + ':' + holeIdx; - if ( failedCuts[ cutKey ] !== undefined ) continue; - - hole = holes[ holeIdx ]; - for ( var h2 = 0; h2 < hole.length; h2 ++ ) { - - holePt = hole[ h2 ]; - if ( ! isCutLineInsideAngles( shapeIndex, h2 ) ) continue; - if ( intersectsShapeEdge( shapePt, holePt ) ) continue; - if ( intersectsHoleEdge( shapePt, holePt ) ) continue; - - holeIndex = h2; - indepHoles.splice( h, 1 ); - - tmpShape1 = shape.slice( 0, shapeIndex + 1 ); - tmpShape2 = shape.slice( shapeIndex ); - tmpHole1 = hole.slice( holeIndex ); - tmpHole2 = hole.slice( 0, holeIndex + 1 ); - - shape = tmpShape1.concat( tmpHole1 ).concat( tmpHole2 ).concat( tmpShape2 ); - - minShapeIndex = shapeIndex; - - // Debug only, to show the selected cuts - // glob_CutLines.push( [ shapePt, holePt ] ); - - break; - - } - if ( holeIndex >= 0 ) break; // hole-vertex found - - failedCuts[ cutKey ] = true; // remember failure - - } - if ( holeIndex >= 0 ) break; // hole-vertex found - - } - - } - - return shape; /* shape with no holes */ - - } - - - var i, il, f, face, - key, index, - allPointsMap = {}; - - // To maintain reference to old shape, one must match coordinates, or offset the indices from original arrays. It's probably easier to do the first. - - var allpoints = contour.concat(); - - for ( var h = 0, hl = holes.length; h < hl; h ++ ) { - - Array.prototype.push.apply( allpoints, holes[ h ] ); - - } - - //console.log( "allpoints",allpoints, allpoints.length ); - - // prepare all points map - - for ( i = 0, il = allpoints.length; i < il; i ++ ) { - - key = allpoints[ i ].x + ':' + allpoints[ i ].y; - - if ( allPointsMap[ key ] !== undefined ) { - - console.warn( 'THREE.ShapeUtils: Duplicate point', key, i ); - - } - - allPointsMap[ key ] = i; - - } - - // remove holes by cutting paths to holes and adding them to the shape - var shapeWithoutHoles = removeHoles( contour, holes ); - - var triangles = ShapeUtils.triangulate( shapeWithoutHoles, false ); // True returns indices for points of spooled shape - //console.log( "triangles",triangles, triangles.length ); - - // check all face vertices against all points map - - for ( i = 0, il = triangles.length; i < il; i ++ ) { - - face = triangles[ i ]; - - for ( f = 0; f < 3; f ++ ) { - - key = face[ f ].x + ':' + face[ f ].y; - - index = allPointsMap[ key ]; - - if ( index !== undefined ) { - - face[ f ] = index; - - } - - } - - } - - return triangles.concat(); - - }, - - isClockWise: function ( pts ) { - - return ShapeUtils.area( pts ) < 0; - - } - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Extras', () => { - - QUnit.module.todo( 'ShapeUtils', () => { - - // PUBLIC STUFF - QUnit.test( "area", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "triangulate", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "triangulateShape", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "isClockWise", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - function Curve() { - - this.type = 'Curve'; - - this.arcLengthDivisions = 200; - - } - - Object.assign( Curve.prototype, { - - // Virtual base class method to overwrite and implement in subclasses - // - t [0 .. 1] - - getPoint: function ( /* t, optionalTarget */ ) { - - console.warn( 'THREE.Curve: .getPoint() not implemented.' ); - return null; - - }, - - // Get point at relative position in curve according to arc length - // - u [0 .. 1] - - getPointAt: function ( u, optionalTarget ) { - - var t = this.getUtoTmapping( u ); - return this.getPoint( t, optionalTarget ); - - }, - - // Get sequence of points using getPoint( t ) - - getPoints: function ( divisions ) { - - if ( divisions === undefined ) divisions = 5; - - var points = []; - - for ( var d = 0; d <= divisions; d ++ ) { - - points.push( this.getPoint( d / divisions ) ); - - } - - return points; - - }, - - // Get sequence of points using getPointAt( u ) - - getSpacedPoints: function ( divisions ) { - - if ( divisions === undefined ) divisions = 5; - - var points = []; - - for ( var d = 0; d <= divisions; d ++ ) { - - points.push( this.getPointAt( d / divisions ) ); - - } - - return points; - - }, - - // Get total curve arc length - - getLength: function () { - - var lengths = this.getLengths(); - return lengths[ lengths.length - 1 ]; - - }, - - // Get list of cumulative segment lengths - - getLengths: function ( divisions ) { - - if ( divisions === undefined ) divisions = this.arcLengthDivisions; - - if ( this.cacheArcLengths && - ( this.cacheArcLengths.length === divisions + 1 ) && - ! this.needsUpdate ) { - - return this.cacheArcLengths; - - } - - this.needsUpdate = false; - - var cache = []; - var current, last = this.getPoint( 0 ); - var p, sum = 0; - - cache.push( 0 ); - - for ( p = 1; p <= divisions; p ++ ) { - - current = this.getPoint( p / divisions ); - sum += current.distanceTo( last ); - cache.push( sum ); - last = current; - - } - - this.cacheArcLengths = cache; - - return cache; // { sums: cache, sum: sum }; Sum is in the last element. - - }, - - updateArcLengths: function () { - - this.needsUpdate = true; - this.getLengths(); - - }, - - // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant - - getUtoTmapping: function ( u, distance ) { - - var arcLengths = this.getLengths(); - - var i = 0, il = arcLengths.length; - - var targetArcLength; // The targeted u distance value to get - - if ( distance ) { - - targetArcLength = distance; - - } else { - - targetArcLength = u * arcLengths[ il - 1 ]; - - } - - // binary search for the index with largest value smaller than target u distance - - var low = 0, high = il - 1, comparison; - - while ( low <= high ) { - - i = Math.floor( low + ( high - low ) / 2 ); // less likely to overflow, though probably not issue here, JS doesn't really have integers, all numbers are floats - - comparison = arcLengths[ i ] - targetArcLength; - - if ( comparison < 0 ) { - - low = i + 1; - - } else if ( comparison > 0 ) { - - high = i - 1; - - } else { - - high = i; - break; - - // DONE - - } - - } - - i = high; - - if ( arcLengths[ i ] === targetArcLength ) { - - return i / ( il - 1 ); - - } - - // we could get finer grain at lengths, or use simple interpolation between two points - - var lengthBefore = arcLengths[ i ]; - var lengthAfter = arcLengths[ i + 1 ]; - - var segmentLength = lengthAfter - lengthBefore; - - // determine where we are between the 'before' and 'after' points - - var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength; - - // add that fractional amount to t - - var t = ( i + segmentFraction ) / ( il - 1 ); - - return t; - - }, - - // Returns a unit vector tangent at t - // In case any sub curve does not implement its tangent derivation, - // 2 points a small delta apart will be used to find its gradient - // which seems to give a reasonable approximation - - getTangent: function ( t ) { - - var delta = 0.0001; - var t1 = t - delta; - var t2 = t + delta; - - // Capping in case of danger - - if ( t1 < 0 ) t1 = 0; - if ( t2 > 1 ) t2 = 1; - - var pt1 = this.getPoint( t1 ); - var pt2 = this.getPoint( t2 ); - - var vec = pt2.clone().sub( pt1 ); - return vec.normalize(); - - }, - - getTangentAt: function ( u ) { - - var t = this.getUtoTmapping( u ); - return this.getTangent( t ); - - }, - - computeFrenetFrames: function ( segments, closed ) { - - // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf - - var normal = new Vector3(); - - var tangents = []; - var normals = []; - var binormals = []; - - var vec = new Vector3(); - var mat = new Matrix4(); - - var i, u, theta; - - // compute the tangent vectors for each segment on the curve - - for ( i = 0; i <= segments; i ++ ) { - - u = i / segments; - - tangents[ i ] = this.getTangentAt( u ); - tangents[ i ].normalize(); - - } - - // select an initial normal vector perpendicular to the first tangent vector, - // and in the direction of the minimum tangent xyz component - - normals[ 0 ] = new Vector3(); - binormals[ 0 ] = new Vector3(); - var min = Number.MAX_VALUE; - var tx = Math.abs( tangents[ 0 ].x ); - var ty = Math.abs( tangents[ 0 ].y ); - var tz = Math.abs( tangents[ 0 ].z ); - - if ( tx <= min ) { - - min = tx; - normal.set( 1, 0, 0 ); - - } - - if ( ty <= min ) { - - min = ty; - normal.set( 0, 1, 0 ); - - } - - if ( tz <= min ) { - - normal.set( 0, 0, 1 ); - - } - - vec.crossVectors( tangents[ 0 ], normal ).normalize(); - - normals[ 0 ].crossVectors( tangents[ 0 ], vec ); - binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] ); - - - // compute the slowly-varying normal and binormal vectors for each segment on the curve - - for ( i = 1; i <= segments; i ++ ) { - - normals[ i ] = normals[ i - 1 ].clone(); - - binormals[ i ] = binormals[ i - 1 ].clone(); - - vec.crossVectors( tangents[ i - 1 ], tangents[ i ] ); - - if ( vec.length() > Number.EPSILON ) { - - vec.normalize(); - - theta = Math.acos( _Math.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors - - normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) ); - - } - - binormals[ i ].crossVectors( tangents[ i ], normals[ i ] ); - - } - - // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same - - if ( closed === true ) { - - theta = Math.acos( _Math.clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) ); - theta /= segments; - - if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) { - - theta = - theta; - - } - - for ( i = 1; i <= segments; i ++ ) { - - // twist a little... - normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) ); - binormals[ i ].crossVectors( tangents[ i ], normals[ i ] ); - - } - - } - - return { - tangents: tangents, - normals: normals, - binormals: binormals - }; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( source ) { - - this.arcLengthDivisions = source.arcLengthDivisions; - - return this; - - } - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Extras', () => { - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'Curve', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "getPoint", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getPointAt", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getPoints", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getSpacedPoints", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getLength", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getLengths", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "updateArcLengths", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getUtoTmapping", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getTangent", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getTangentAt", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "computeFrenetFrames", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - function LineCurve( v1, v2 ) { - - Curve.call( this ); - - this.type = 'LineCurve'; - - this.v1 = v1 || new Vector2(); - this.v2 = v2 || new Vector2(); - - } - - LineCurve.prototype = Object.create( Curve.prototype ); - LineCurve.prototype.constructor = LineCurve; - - LineCurve.prototype.isLineCurve = true; - - LineCurve.prototype.getPoint = function ( t, optionalTarget ) { - - var point = optionalTarget || new Vector2(); - - if ( t === 1 ) { - - point.copy( this.v2 ); - - } else { - - point.copy( this.v2 ).sub( this.v1 ); - point.multiplyScalar( t ).add( this.v1 ); - - } - - return point; - - }; - - // Line curve is linear, so we can overwrite default getPointAt - - LineCurve.prototype.getPointAt = function ( u, optionalTarget ) { - - return this.getPoint( u, optionalTarget ); - - }; - - LineCurve.prototype.getTangent = function ( /* t */ ) { - - var tangent = this.v2.clone().sub( this.v1 ); - - return tangent.normalize(); - - }; - - LineCurve.prototype.copy = function ( source ) { - - Curve.prototype.copy.call( this, source ); - - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); - - return this; - - }; - - function CurvePath() { - - Curve.call( this ); - - this.type = 'CurvePath'; - - this.curves = []; - this.autoClose = false; // Automatically closes the path - - } - - CurvePath.prototype = Object.assign( Object.create( Curve.prototype ), { - - constructor: CurvePath, - - add: function ( curve ) { - - this.curves.push( curve ); - - }, - - closePath: function () { - - // Add a line curve if start and end of lines are not connected - var startPoint = this.curves[ 0 ].getPoint( 0 ); - var endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 ); - - if ( ! startPoint.equals( endPoint ) ) { - - this.curves.push( new LineCurve( endPoint, startPoint ) ); - - } - - }, - - // To get accurate point with reference to - // entire path distance at time t, - // following has to be done: - - // 1. Length of each sub path have to be known - // 2. Locate and identify type of curve - // 3. Get t for the curve - // 4. Return curve.getPointAt(t') - - getPoint: function ( t ) { - - var d = t * this.getLength(); - var curveLengths = this.getCurveLengths(); - var i = 0; - - // To think about boundaries points. - - while ( i < curveLengths.length ) { - - if ( curveLengths[ i ] >= d ) { - - var diff = curveLengths[ i ] - d; - var curve = this.curves[ i ]; - - var segmentLength = curve.getLength(); - var u = segmentLength === 0 ? 0 : 1 - diff / segmentLength; - - return curve.getPointAt( u ); - - } - - i ++; - - } - - return null; - - // loop where sum != 0, sum > d , sum+1 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) { - - points.push( points[ 0 ] ); - - } - - return points; - - } - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Extras', () => { - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'CurvePath', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "add", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "closePath", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getPoint", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getLength", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "updateArcLengths", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getCurveLengths", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getSpacedPoints", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getPoints", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "createPointsGeometry", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "createSpacedPointsGeometry", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "createGeometry", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author zz85 / http://www.lab4games.net/zz85/blog - * - * Bezier Curves formulas obtained from - * http://en.wikipedia.org/wiki/Bézier_curve - */ - - function CatmullRom( t, p0, p1, p2, p3 ) { - - var v0 = ( p2 - p0 ) * 0.5; - var v1 = ( p3 - p1 ) * 0.5; - var t2 = t * t; - var t3 = t * t2; - return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1; - - } - - // - - function QuadraticBezierP0( t, p ) { - - var k = 1 - t; - return k * k * p; - - } - - function QuadraticBezierP1( t, p ) { - - return 2 * ( 1 - t ) * t * p; - - } - - function QuadraticBezierP2( t, p ) { - - return t * t * p; - - } - - function QuadraticBezier( t, p0, p1, p2 ) { - - return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) + - QuadraticBezierP2( t, p2 ); - - } - - // - - function CubicBezierP0( t, p ) { - - var k = 1 - t; - return k * k * k * p; - - } - - function CubicBezierP1( t, p ) { - - var k = 1 - t; - return 3 * k * k * t * p; - - } - - function CubicBezierP2( t, p ) { - - return 3 * ( 1 - t ) * t * t * p; - - } - - function CubicBezierP3( t, p ) { - - return t * t * t * p; - - } - - function CubicBezier( t, p0, p1, p2, p3 ) { - - return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) + - CubicBezierP3( t, p3 ); - - } - - function EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { - - Curve.call( this ); - - this.type = 'EllipseCurve'; - - this.aX = aX || 0; - this.aY = aY || 0; - - this.xRadius = xRadius || 1; - this.yRadius = yRadius || 1; - - this.aStartAngle = aStartAngle || 0; - this.aEndAngle = aEndAngle || 2 * Math.PI; - - this.aClockwise = aClockwise || false; - - this.aRotation = aRotation || 0; - - } - - EllipseCurve.prototype = Object.create( Curve.prototype ); - EllipseCurve.prototype.constructor = EllipseCurve; - - EllipseCurve.prototype.isEllipseCurve = true; - - EllipseCurve.prototype.getPoint = function ( t, optionalTarget ) { - - var point = optionalTarget || new Vector2(); - - var twoPi = Math.PI * 2; - var deltaAngle = this.aEndAngle - this.aStartAngle; - var samePoints = Math.abs( deltaAngle ) < Number.EPSILON; - - // ensures that deltaAngle is 0 .. 2 PI - while ( deltaAngle < 0 ) deltaAngle += twoPi; - while ( deltaAngle > twoPi ) deltaAngle -= twoPi; - - if ( deltaAngle < Number.EPSILON ) { - - if ( samePoints ) { - - deltaAngle = 0; - - } else { - - deltaAngle = twoPi; - - } - - } - - if ( this.aClockwise === true && ! samePoints ) { - - if ( deltaAngle === twoPi ) { - - deltaAngle = - twoPi; - - } else { - - deltaAngle = deltaAngle - twoPi; - - } - - } - - var angle = this.aStartAngle + t * deltaAngle; - var x = this.aX + this.xRadius * Math.cos( angle ); - var y = this.aY + this.yRadius * Math.sin( angle ); - - if ( this.aRotation !== 0 ) { - - var cos = Math.cos( this.aRotation ); - var sin = Math.sin( this.aRotation ); - - var tx = x - this.aX; - var ty = y - this.aY; - - // Rotate the point about the center of the ellipse. - x = tx * cos - ty * sin + this.aX; - y = tx * sin + ty * cos + this.aY; - - } - - return point.set( x, y ); - - }; - - EllipseCurve.prototype.copy = function ( source ) { - - Curve.prototype.copy.call( this, source ); - - this.aX = source.aX; - this.aY = source.aY; - - this.xRadius = source.xRadius; - this.yRadius = source.yRadius; - - this.aStartAngle = source.aStartAngle; - this.aEndAngle = source.aEndAngle; - - this.aClockwise = source.aClockwise; - - this.aRotation = source.aRotation; - - return this; - - }; - - function SplineCurve( points /* array of Vector2 */ ) { - - Curve.call( this ); - - this.type = 'SplineCurve'; - - this.points = points || []; - - } - - SplineCurve.prototype = Object.create( Curve.prototype ); - SplineCurve.prototype.constructor = SplineCurve; - - SplineCurve.prototype.isSplineCurve = true; - - SplineCurve.prototype.getPoint = function ( t, optionalTarget ) { - - var point = optionalTarget || new Vector2(); - - var points = this.points; - var p = ( points.length - 1 ) * t; - - var intPoint = Math.floor( p ); - var weight = p - intPoint; - - var p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ]; - var p1 = points[ intPoint ]; - var p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ]; - var p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ]; - - point.set( - CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ), - CatmullRom( weight, p0.y, p1.y, p2.y, p3.y ) - ); - - return point; - - }; - - SplineCurve.prototype.copy = function ( source ) { - - Curve.prototype.copy.call( this, source ); - - this.points = []; - - for ( var i = 0, l = source.points.length; i < l; i ++ ) { - - var point = source.points[ i ]; - - this.points.push( point.clone() ); - - } - - return this; - - }; - - function CubicBezierCurve( v0, v1, v2, v3 ) { - - Curve.call( this ); - - this.type = 'CubicBezierCurve'; - - this.v0 = v0 || new Vector2(); - this.v1 = v1 || new Vector2(); - this.v2 = v2 || new Vector2(); - this.v3 = v3 || new Vector2(); - - } - - CubicBezierCurve.prototype = Object.create( Curve.prototype ); - CubicBezierCurve.prototype.constructor = CubicBezierCurve; - - CubicBezierCurve.prototype.isCubicBezierCurve = true; - - CubicBezierCurve.prototype.getPoint = function ( t, optionalTarget ) { - - var point = optionalTarget || new Vector2(); - - var v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3; - - point.set( - CubicBezier( t, v0.x, v1.x, v2.x, v3.x ), - CubicBezier( t, v0.y, v1.y, v2.y, v3.y ) - ); - - return point; - - }; - - CubicBezierCurve.prototype.copy = function ( source ) { - - Curve.prototype.copy.call( this, source ); - - this.v0.copy( source.v0 ); - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); - this.v3.copy( source.v3 ); - - return this; - - }; - - function QuadraticBezierCurve( v0, v1, v2 ) { - - Curve.call( this ); - - this.type = 'QuadraticBezierCurve'; - - this.v0 = v0 || new Vector2(); - this.v1 = v1 || new Vector2(); - this.v2 = v2 || new Vector2(); - - } - - QuadraticBezierCurve.prototype = Object.create( Curve.prototype ); - QuadraticBezierCurve.prototype.constructor = QuadraticBezierCurve; - - QuadraticBezierCurve.prototype.isQuadraticBezierCurve = true; - - QuadraticBezierCurve.prototype.getPoint = function ( t, optionalTarget ) { - - var point = optionalTarget || new Vector2(); - - var v0 = this.v0, v1 = this.v1, v2 = this.v2; - - point.set( - QuadraticBezier( t, v0.x, v1.x, v2.x ), - QuadraticBezier( t, v0.y, v1.y, v2.y ) - ); - - return point; - - }; - - QuadraticBezierCurve.prototype.copy = function ( source ) { - - Curve.prototype.copy.call( this, source ); - - this.v0.copy( source.v0 ); - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); - - return this; - - }; - - var PathPrototype = Object.assign( Object.create( CurvePath.prototype ), { - - fromPoints: function ( vectors ) { - - this.moveTo( vectors[ 0 ].x, vectors[ 0 ].y ); - - for ( var i = 1, l = vectors.length; i < l; i ++ ) { - - this.lineTo( vectors[ i ].x, vectors[ i ].y ); - - } - - }, - - moveTo: function ( x, y ) { - - this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying? - - }, - - lineTo: function ( x, y ) { - - var curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) ); - this.curves.push( curve ); - - this.currentPoint.set( x, y ); - - }, - - quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) { - - var curve = new QuadraticBezierCurve( - this.currentPoint.clone(), - new Vector2( aCPx, aCPy ), - new Vector2( aX, aY ) - ); - - this.curves.push( curve ); - - this.currentPoint.set( aX, aY ); - - }, - - bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) { - - var curve = new CubicBezierCurve( - this.currentPoint.clone(), - new Vector2( aCP1x, aCP1y ), - new Vector2( aCP2x, aCP2y ), - new Vector2( aX, aY ) - ); - - this.curves.push( curve ); - - this.currentPoint.set( aX, aY ); - - }, - - splineThru: function ( pts /*Array of Vector*/ ) { - - var npts = [ this.currentPoint.clone() ].concat( pts ); - - var curve = new SplineCurve( npts ); - this.curves.push( curve ); - - this.currentPoint.copy( pts[ pts.length - 1 ] ); - - }, - - arc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { - - var x0 = this.currentPoint.x; - var y0 = this.currentPoint.y; - - this.absarc( aX + x0, aY + y0, aRadius, - aStartAngle, aEndAngle, aClockwise ); - - }, - - absarc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { - - this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise ); - - }, - - ellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { - - var x0 = this.currentPoint.x; - var y0 = this.currentPoint.y; - - this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ); - - }, - - absellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { - - var curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ); - - if ( this.curves.length > 0 ) { - - // if a previous curve is present, attempt to join - var firstPoint = curve.getPoint( 0 ); - - if ( ! firstPoint.equals( this.currentPoint ) ) { - - this.lineTo( firstPoint.x, firstPoint.y ); - - } - - } - - this.curves.push( curve ); - - var lastPoint = curve.getPoint( 1 ); - this.currentPoint.copy( lastPoint ); - - } - - } ); - - /** - * @author zz85 / http://www.lab4games.net/zz85/blog - * Creates free form 2d path using series of points, lines or curves. - **/ - - function Path( points ) { - - CurvePath.call( this ); - - this.type = 'Path'; - - this.currentPoint = new Vector2(); - - if ( points ) { - - this.fromPoints( points ); - - } - - } - - Path.prototype = PathPrototype; - PathPrototype.constructor = Path; - - function Shape() { - - Path.apply( this, arguments ); - - this.type = 'Shape'; - - this.holes = []; - - } - - Shape.prototype = Object.assign( Object.create( PathPrototype ), { - - constructor: Shape, - - getPointsHoles: function ( divisions ) { - - var holesPts = []; - - for ( var i = 0, l = this.holes.length; i < l; i ++ ) { - - holesPts[ i ] = this.holes[ i ].getPoints( divisions ); - - } - - return holesPts; - - }, - - // Get points of shape and holes (keypoints based on segments parameter) - - extractAllPoints: function ( divisions ) { - - return { - - shape: this.getPoints( divisions ), - holes: this.getPointsHoles( divisions ) - - }; - - }, - - extractPoints: function ( divisions ) { - - return this.extractAllPoints( divisions ); - - } - - } ); - - function ShapePath() { - - this.type = 'ShapePath'; - - this.subPaths = []; - this.currentPath = null; - - } - - Object.assign( ShapePath.prototype, { - - moveTo: function ( x, y ) { - - this.currentPath = new Path(); - this.subPaths.push( this.currentPath ); - this.currentPath.moveTo( x, y ); - - }, - - lineTo: function ( x, y ) { - - this.currentPath.lineTo( x, y ); - - }, - - quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) { - - this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY ); - - }, - - bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) { - - this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ); - - }, - - splineThru: function ( pts ) { - - this.currentPath.splineThru( pts ); - - }, - - toShapes: function ( isCCW, noHoles ) { - - function toShapesNoHoles( inSubpaths ) { - - var shapes = []; - - for ( var i = 0, l = inSubpaths.length; i < l; i ++ ) { - - var tmpPath = inSubpaths[ i ]; - - var tmpShape = new Shape(); - tmpShape.curves = tmpPath.curves; - - shapes.push( tmpShape ); - - } - - return shapes; - - } - - function isPointInsidePolygon( inPt, inPolygon ) { - - var polyLen = inPolygon.length; - - // inPt on polygon contour => immediate success or - // toggling of inside/outside at every single! intersection point of an edge - // with the horizontal line through inPt, left of inPt - // not counting lowerY endpoints of edges and whole edges on that line - var inside = false; - for ( var p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) { - - var edgeLowPt = inPolygon[ p ]; - var edgeHighPt = inPolygon[ q ]; - - var edgeDx = edgeHighPt.x - edgeLowPt.x; - var edgeDy = edgeHighPt.y - edgeLowPt.y; - - if ( Math.abs( edgeDy ) > Number.EPSILON ) { - - // not parallel - if ( edgeDy < 0 ) { - - edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx; - edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy; - - } - if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) continue; - - if ( inPt.y === edgeLowPt.y ) { - - if ( inPt.x === edgeLowPt.x ) return true; // inPt is on contour ? - // continue; // no intersection or edgeLowPt => doesn't count !!! - - } else { - - var perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y ); - if ( perpEdge === 0 ) return true; // inPt is on contour ? - if ( perpEdge < 0 ) continue; - inside = ! inside; // true intersection left of inPt - - } - - } else { - - // parallel or collinear - if ( inPt.y !== edgeLowPt.y ) continue; // parallel - // edge lies on the same horizontal line as inPt - if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) || - ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) return true; // inPt: Point on contour ! - // continue; - - } - - } - - return inside; - - } - - var isClockWise = ShapeUtils.isClockWise; - - var subPaths = this.subPaths; - if ( subPaths.length === 0 ) return []; - - if ( noHoles === true ) return toShapesNoHoles( subPaths ); - - - var solid, tmpPath, tmpShape, shapes = []; - - if ( subPaths.length === 1 ) { - - tmpPath = subPaths[ 0 ]; - tmpShape = new Shape(); - tmpShape.curves = tmpPath.curves; - shapes.push( tmpShape ); - return shapes; - - } - - var holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() ); - holesFirst = isCCW ? ! holesFirst : holesFirst; - - // console.log("Holes first", holesFirst); - - var betterShapeHoles = []; - var newShapes = []; - var newShapeHoles = []; - var mainIdx = 0; - var tmpPoints; - - newShapes[ mainIdx ] = undefined; - newShapeHoles[ mainIdx ] = []; - - for ( var i = 0, l = subPaths.length; i < l; i ++ ) { - - tmpPath = subPaths[ i ]; - tmpPoints = tmpPath.getPoints(); - solid = isClockWise( tmpPoints ); - solid = isCCW ? ! solid : solid; - - if ( solid ) { - - if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) ) mainIdx ++; - - newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints }; - newShapes[ mainIdx ].s.curves = tmpPath.curves; - - if ( holesFirst ) mainIdx ++; - newShapeHoles[ mainIdx ] = []; - - //console.log('cw', i); - - } else { - - newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } ); - - //console.log('ccw', i); - - } - - } - - // only Holes? -> probably all Shapes with wrong orientation - if ( ! newShapes[ 0 ] ) return toShapesNoHoles( subPaths ); - - - if ( newShapes.length > 1 ) { - - var ambiguous = false; - var toChange = []; - - for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { - - betterShapeHoles[ sIdx ] = []; - - } - - for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { - - var sho = newShapeHoles[ sIdx ]; - - for ( var hIdx = 0; hIdx < sho.length; hIdx ++ ) { - - var ho = sho[ hIdx ]; - var hole_unassigned = true; - - for ( var s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) { - - if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) { - - if ( sIdx !== s2Idx ) toChange.push( { froms: sIdx, tos: s2Idx, hole: hIdx } ); - if ( hole_unassigned ) { - - hole_unassigned = false; - betterShapeHoles[ s2Idx ].push( ho ); - - } else { - - ambiguous = true; - - } - - } - - } - if ( hole_unassigned ) { - - betterShapeHoles[ sIdx ].push( ho ); - - } - - } - - } - // console.log("ambiguous: ", ambiguous); - if ( toChange.length > 0 ) { - - // console.log("to change: ", toChange); - if ( ! ambiguous ) newShapeHoles = betterShapeHoles; - - } - - } - - var tmpHoles; - - for ( var i = 0, il = newShapes.length; i < il; i ++ ) { - - tmpShape = newShapes[ i ].s; - shapes.push( tmpShape ); - tmpHoles = newShapeHoles[ i ]; - - for ( var j = 0, jl = tmpHoles.length; j < jl; j ++ ) { - - tmpShape.holes.push( tmpHoles[ j ].h ); - - } - - } - - //console.log("shape", shapes); - - return shapes; - - } - - } ); - - /** - * @author zz85 / http://www.lab4games.net/zz85/blog - * @author mrdoob / http://mrdoob.com/ - */ - - function Font( data ) { - - this.type = 'Font'; - - this.data = data; - - } - - Object.assign( Font.prototype, { - - isFont: true, - - generateShapes: function ( text, size, divisions ) { - - function createPaths( text ) { - - var chars = String( text ).split( '' ); - var scale = size / data.resolution; - var line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale; - - var offsetX = 0, offsetY = 0; - - var paths = []; - - for ( var i = 0; i < chars.length; i ++ ) { - - var char = chars[ i ]; - - if ( char === '\n' ) { - - offsetX = 0; - offsetY -= line_height; - - } else { - - var ret = createPath( char, scale, offsetX, offsetY ); - offsetX += ret.offsetX; - paths.push( ret.path ); - - } - - } - - return paths; - - } - - function createPath( c, scale, offsetX, offsetY ) { - - var glyph = data.glyphs[ c ] || data.glyphs[ '?' ]; - - if ( ! glyph ) return; - - var path = new ShapePath(); - - var pts = []; - var x, y, cpx, cpy, cpx0, cpy0, cpx1, cpy1, cpx2, cpy2, laste; - - if ( glyph.o ) { - - var outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) ); - - for ( var i = 0, l = outline.length; i < l; ) { - - var action = outline[ i ++ ]; - - switch ( action ) { - - case 'm': // moveTo - - x = outline[ i ++ ] * scale + offsetX; - y = outline[ i ++ ] * scale + offsetY; - - path.moveTo( x, y ); - - break; - - case 'l': // lineTo - - x = outline[ i ++ ] * scale + offsetX; - y = outline[ i ++ ] * scale + offsetY; - - path.lineTo( x, y ); - - break; - - case 'q': // quadraticCurveTo - - cpx = outline[ i ++ ] * scale + offsetX; - cpy = outline[ i ++ ] * scale + offsetY; - cpx1 = outline[ i ++ ] * scale + offsetX; - cpy1 = outline[ i ++ ] * scale + offsetY; - - path.quadraticCurveTo( cpx1, cpy1, cpx, cpy ); - - laste = pts[ pts.length - 1 ]; - - if ( laste ) { - - cpx0 = laste.x; - cpy0 = laste.y; - - for ( var i2 = 1; i2 <= divisions; i2 ++ ) { - - var t = i2 / divisions; - QuadraticBezier( t, cpx0, cpx1, cpx ); - QuadraticBezier( t, cpy0, cpy1, cpy ); - - } - - } - - break; - - case 'b': // bezierCurveTo - - cpx = outline[ i ++ ] * scale + offsetX; - cpy = outline[ i ++ ] * scale + offsetY; - cpx1 = outline[ i ++ ] * scale + offsetX; - cpy1 = outline[ i ++ ] * scale + offsetY; - cpx2 = outline[ i ++ ] * scale + offsetX; - cpy2 = outline[ i ++ ] * scale + offsetY; - - path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy ); - - laste = pts[ pts.length - 1 ]; - - if ( laste ) { - - cpx0 = laste.x; - cpy0 = laste.y; - - for ( var i2 = 1; i2 <= divisions; i2 ++ ) { - - var t = i2 / divisions; - CubicBezier( t, cpx0, cpx1, cpx2, cpx ); - CubicBezier( t, cpy0, cpy1, cpy2, cpy ); - - } - - } - - break; - - } - - } - - } - - return { offsetX: glyph.ha * scale, path: path }; - - } - - // - - if ( size === undefined ) size = 100; - if ( divisions === undefined ) divisions = 4; - - var data = this.data; - - var paths = createPaths( text ); - var shapes = []; - - for ( var p = 0, pl = paths.length; p < pl; p ++ ) { - - Array.prototype.push.apply( shapes, paths[ p ].toShapes() ); - - } - - return shapes; - - } - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Extras', () => { - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'Font', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isFont", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "generateShapes", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Extras', () => { - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'Interpolations', () => { - - // PUBLIC STUFF - QUnit.test( "CatmullRom", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "QuadraticBezier", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "CubicBezier", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Extras', () => { - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'Path', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Extras', () => { - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'PathPrototype', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "fromPoints", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "moveTo", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "lineTo", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "quadraticCurveTo", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "bezierCurveTo", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "splineThru", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "arc", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "absarc", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "ellipse", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "absellipse", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Extras', () => { - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'Shape', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "getPointsHoles", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "extractAllPoints", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "extractPoints", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Extras', () => { - - QUnit.module( 'Core', () => { - - QUnit.module.todo( 'ShapePath', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "moveTo", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "lineTo", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "quadraticCurveTo", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "bezierCurveTo", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "splineThru", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "toShapes", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Extras', () => { - - QUnit.module( 'Curves', () => { - - QUnit.module.todo( 'ArcCurve', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isArcCurve", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - function CubicPoly() { - - var c0 = 0, c1 = 0, c2 = 0, c3 = 0; - - /* - * Compute coefficients for a cubic polynomial - * p(s) = c0 + c1*s + c2*s^2 + c3*s^3 - * such that - * p(0) = x0, p(1) = x1 - * and - * p'(0) = t0, p'(1) = t1. - */ - function init( x0, x1, t0, t1 ) { - - c0 = x0; - c1 = t0; - c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1; - c3 = 2 * x0 - 2 * x1 + t0 + t1; - - } - - return { - - initCatmullRom: function ( x0, x1, x2, x3, tension ) { - - init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) ); - - }, - - initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) { - - // compute tangents when parameterized in [t1,t2] - var t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1; - var t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2; - - // rescale tangents for parametrization in [0,1] - t1 *= dt1; - t2 *= dt1; - - init( x1, x2, t1, t2 ); - - }, - - calc: function ( t ) { - - var t2 = t * t; - var t3 = t2 * t; - return c0 + c1 * t + c2 * t2 + c3 * t3; - - } - - }; - - } - - // - - var tmp = new Vector3(); - var px = new CubicPoly(); - var py = new CubicPoly(); - var pz = new CubicPoly(); - - function CatmullRomCurve3( points, closed, curveType, tension ) { - - Curve.call( this ); - - this.type = 'CatmullRomCurve3'; - - this.points = points || []; - this.closed = closed || false; - this.curveType = curveType || 'centripetal'; - this.tension = tension || 0.5; - - } - - CatmullRomCurve3.prototype = Object.create( Curve.prototype ); - CatmullRomCurve3.prototype.constructor = CatmullRomCurve3; - - CatmullRomCurve3.prototype.isCatmullRomCurve3 = true; - - CatmullRomCurve3.prototype.getPoint = function ( t, optionalTarget ) { - - var point = optionalTarget || new Vector3(); - - var points = this.points; - var l = points.length; - - var p = ( l - ( this.closed ? 0 : 1 ) ) * t; - var intPoint = Math.floor( p ); - var weight = p - intPoint; - - if ( this.closed ) { - - intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / points.length ) + 1 ) * points.length; - - } else if ( weight === 0 && intPoint === l - 1 ) { - - intPoint = l - 2; - weight = 1; - - } - - var p0, p1, p2, p3; // 4 points - - if ( this.closed || intPoint > 0 ) { - - p0 = points[ ( intPoint - 1 ) % l ]; - - } else { - - // extrapolate first point - tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] ); - p0 = tmp; - - } - - p1 = points[ intPoint % l ]; - p2 = points[ ( intPoint + 1 ) % l ]; - - if ( this.closed || intPoint + 2 < l ) { - - p3 = points[ ( intPoint + 2 ) % l ]; - - } else { - - // extrapolate last point - tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] ); - p3 = tmp; - - } - - if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) { - - // init Centripetal / Chordal Catmull-Rom - var pow = this.curveType === 'chordal' ? 0.5 : 0.25; - var dt0 = Math.pow( p0.distanceToSquared( p1 ), pow ); - var dt1 = Math.pow( p1.distanceToSquared( p2 ), pow ); - var dt2 = Math.pow( p2.distanceToSquared( p3 ), pow ); - - // safety check for repeated points - if ( dt1 < 1e-4 ) dt1 = 1.0; - if ( dt0 < 1e-4 ) dt0 = dt1; - if ( dt2 < 1e-4 ) dt2 = dt1; - - px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 ); - py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 ); - pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 ); - - } else if ( this.curveType === 'catmullrom' ) { - - px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension ); - py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension ); - pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension ); - - } - - point.set( - px.calc( weight ), - py.calc( weight ), - pz.calc( weight ) - ); - - return point; - - }; - - CatmullRomCurve3.prototype.copy = function ( source ) { - - Curve.prototype.copy.call( this, source ); - - this.points = []; - - for ( var i = 0, l = source.points.length; i < l; i ++ ) { - - var point = source.points[ i ]; - - this.points.push( point.clone() ); - - } - - this.closed = source.closed; - this.curveType = source.curveType; - this.tension = source.tension; - - return this; - - }; - - /** - * @author zz85 / http://joshuakoo.com - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Extras', () => { - - QUnit.module( 'Curves', () => { - - QUnit.module.todo( 'CatmullRomCurve3', () => { - - /* eslint-disable */ - var positions = [ - new Vector3( - 60, - 100, 60 ), - new Vector3( - 60, 20, 60 ), - new Vector3( - 60, 120, 60 ), - new Vector3( 60, 20, - 60 ), - new Vector3( 60, - 100, - 60 ) - ]; - /* eslint-enable */ - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isCatmullRomCurve3", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getPoint", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( "catmullrom check", ( assert ) => { - - var curve = new CatmullRomCurve3( positions ); - curve.type = 'catmullrom'; - - var expectedPoints = [ - - new Vector3( - 60, - 100, 60 ), - new Vector3( - 60, - 51.04, 60 ), - new Vector3( - 60, - 2.7199999999999998, 60 ), - new Vector3( - 61.92, 44.48, 61.92 ), - new Vector3( - 68.64, 95.36000000000001, 68.64 ), - new Vector3( - 60, 120, 60 ), - new Vector3( - 14.880000000000017, 95.36000000000001, 14.880000000000017 ), - new Vector3( 41.75999999999997, 44.48000000000003, - 41.75999999999997 ), - new Vector3( 67.68, - 2.720000000000023, - 67.68 ), - new Vector3( 65.75999999999999, - 51.04000000000001, - 65.75999999999999 ), - new Vector3( 60, - 100, - 60 ) - - ]; - - var points = curve.getPoints( 10 ); - - assert.equal( points.length, expectedPoints.length, 'correct number of points.' ); - - points.forEach( function ( point, i ) { - - assert.numEqual( point.x, expectedPoints[ i ].x, 'points[' + i + '].x' ); - assert.numEqual( point.y, expectedPoints[ i ].y, 'points[' + i + '].y' ); - assert.numEqual( point.z, expectedPoints[ i ].z, 'points[' + i + '].z' ); - - } ); - - } ); - - QUnit.test( "chordal basic check", ( assert ) => { - - var curve = new CatmullRomCurve3( positions ); - - curve.type = 'chordal'; - - var expectedPoints = [ - new Vector3( - 60, - 100, 60 ), - new Vector3( - 60, - 52, 60 ), - new Vector3( - 60, - 4, 60 ), - new Vector3( - 60.656435889910924, 41.62455386421379, 60.656435889910924 ), - new Vector3( - 62.95396150459915, 87.31049238896205, 62.95396150459915 ), - new Vector3( - 60, 120, 60 ), - new Vector3( - 16.302568199486444, 114.1500463116312, 16.302568199486444 ), - new Vector3( 42.998098664956586, 54.017050116427455, - 42.998098664956586 ), - new Vector3( 63.542500175682434, - 1.137153397546383, - 63.542500175682434 ), - new Vector3( 62.65687513176183, - 49.85286504815978, - 62.65687513176183 ), - new Vector3( 60.00000000000001, - 100, - 60.00000000000001 ) - ]; - - var points = curve.getPoints( 10 ); - - assert.equal( points.length, expectedPoints.length, 'correct number of points.' ); - - points.forEach( function ( point, i ) { - - assert.numEqual( point.x, expectedPoints[ i ].x, 'points[' + i + '].x' ); - assert.numEqual( point.y, expectedPoints[ i ].y, 'points[' + i + '].y' ); - assert.numEqual( point.z, expectedPoints[ i ].z, 'points[' + i + '].z' ); - - } ); - - } ); - - QUnit.test( "centripetal basic check", ( assert ) => { - - var curve = new CatmullRomCurve3( positions ); - curve.type = 'centripetal'; - - var expectedPoints = [ - new Vector3( - 60, - 100, 60 ), - new Vector3( - 60, - 51.47527724919028, 60 ), - new Vector3( - 60, - 3.300369665587032, 60 ), - new Vector3( - 61.13836565863938, 42.86306307781241, 61.13836565863938 ), - new Vector3( - 65.1226454638772, 90.69743905511538, 65.1226454638772 ), - new Vector3( - 60, 120, 60 ), - new Vector3( - 15.620412575504497, 103.10790870179872, 15.620412575504497 ), - new Vector3( 42.384384731047874, 48.35477686933143, - 42.384384731047874 ), - new Vector3( 65.25545512241153, - 1.646250966068339, - 65.25545512241153 ), - new Vector3( 63.94159134180865, - 50.234688224551256, - 63.94159134180865 ), - new Vector3( 59.99999999999999, - 100, - 59.99999999999999 ), - ]; - - var points = curve.getPoints( 10 ); - - assert.equal( points.length, expectedPoints.length, 'correct number of points.' ); - - points.forEach( function ( point, i ) { - - assert.numEqual( point.x, expectedPoints[ i ].x, 'points[' + i + '].x' ); - assert.numEqual( point.y, expectedPoints[ i ].y, 'points[' + i + '].y' ); - assert.numEqual( point.z, expectedPoints[ i ].z, 'points[' + i + '].z' ); - - } ); - - } ); - - QUnit.test( "closed catmullrom basic check", ( assert ) => { - - var curve = new CatmullRomCurve3( positions ); - curve.type = 'catmullrom'; - curve.closed = true; - - var expectedPoints = [ - new Vector3( - 60, - 100, 60 ), - new Vector3( - 67.5, - 46.25, 67.5 ), - new Vector3( - 60, 20, 60 ), - new Vector3( - 67.5, 83.75, 67.5 ), - new Vector3( - 60, 120, 60 ), - new Vector3( 0, 83.75, 0 ), - new Vector3( 60, 20, - 60 ), - new Vector3( 75, - 46.25, - 75 ), - new Vector3( 60, - 100, - 60 ), - new Vector3( 0, - 115, 0 ), - new Vector3( - 60, - 100, 60 ), - ]; - - var points = curve.getPoints( 10 ); - - assert.equal( points.length, expectedPoints.length, 'correct number of points.' ); - - points.forEach( function ( point, i ) { - - assert.numEqual( point.x, expectedPoints[ i ].x, 'points[' + i + '].x' ); - assert.numEqual( point.y, expectedPoints[ i ].y, 'points[' + i + '].y' ); - assert.numEqual( point.z, expectedPoints[ i ].z, 'points[' + i + '].z' ); - - } ); - - } ); - - // - // curve.type = 'catmullrom'; only from here on - // - QUnit.test( "getLength/getLengths", ( assert ) => { - - var curve = new THREE.CatmullRomCurve3( positions ); - curve.type = 'catmullrom'; - - var length = curve.getLength(); - var expectedLength = 551.549686276872; - - assert.numEqual( length, expectedLength, "Correct length of curve" ); - - var expectedLengths = [ - 0, - 120, - 220, - 416.9771560359221, - 536.9771560359221 - ]; - var lengths = curve.getLengths( expectedLengths.length - 1 ); - - assert.strictEqual( lengths.length, expectedLengths.length, "Correct number of segments" ); - - lengths.forEach( function ( segment, i ) { - - assert.numEqual( segment, expectedLengths[ i ], "segment[" + i + "] correct" ); - - } ); - - } ); - - QUnit.test( "getPointAt", ( assert ) => { - - var curve = new THREE.CatmullRomCurve3( positions ); - curve.type = 'catmullrom'; - - var expectedPoints = [ - new THREE.Vector3( - 60, - 100, 60 ), - new THREE.Vector3( - 64.84177333183106, 64.86956465359813, 64.84177333183106 ), - new THREE.Vector3( - 28.288507045700854, 104.83101184518996, 28.288507045700854 ), - new THREE.Vector3( 60, - 100, - 60 ) - ]; - - var points = [ - curve.getPointAt( 0 ), - curve.getPointAt( 0.3 ), - curve.getPointAt( 0.5 ), - curve.getPointAt( 1 ) - ]; - - assert.deepEqual( points, expectedPoints, "Correct points" ); - - } ); - - QUnit.test( "getTangent/getTangentAt", ( assert ) => { - - var curve = new THREE.CatmullRomCurve3( positions ); - curve.type = 'catmullrom'; - - var expectedTangents = [ - new THREE.Vector3( 0, 1, 0 ), - new THREE.Vector3( - 0.0001090274561657922, 0.9999999881130137, 0.0001090274561657922 ), - new THREE.Vector3( 0.7071067811865475, - 2.0930381713877622e-13, - 0.7071067811865475 ), - new THREE.Vector3( 0.43189437062802816, - 0.7917919583070032, - 0.43189437062802816 ), - new THREE.Vector3( - 0.00019991333100812723, - 0.9999999600346592, 0.00019991333100812723 ) - ]; - - var tangents = [ - curve.getTangent( 0 ), - curve.getTangent( 0.25 ), - curve.getTangent( 0.5 ), - curve.getTangent( 0.75 ), - curve.getTangent( 1 ) - ]; - - expectedTangents.forEach( function ( exp, i ) { - - var tangent = tangents[ i ]; - - assert.numEqual( tangent.x, exp.x, "getTangent #" + i + ": x correct" ); - assert.numEqual( tangent.y, exp.y, "getTangent #" + i + ": y correct" ); - - } ); - - // - - var expectedTangents = [ - new THREE.Vector3( 0, 1, 0 ), - new THREE.Vector3( - 0.10709018822205997, 0.9884651653817284, 0.10709018822205997 ), - new THREE.Vector3( 0.6396363672964268, - 0.4262987629159402, - 0.6396363672964268 ), - new THREE.Vector3( 0.5077298411616501, - 0.6960034603275557, - 0.5077298411616501 ), - new THREE.Vector3( - 0.00019991333100812723, - 0.9999999600346592, 0.00019991333100812723 ) - ]; - - var tangents = [ - curve.getTangentAt( 0 ), - curve.getTangentAt( 0.25 ), - curve.getTangentAt( 0.5 ), - curve.getTangentAt( 0.75 ), - curve.getTangentAt( 1 ) - ]; - - expectedTangents.forEach( function ( exp, i ) { - - var tangent = tangents[ i ]; - - assert.numEqual( tangent.x, exp.x, "getTangentAt #" + i + ": x correct" ); - assert.numEqual( tangent.y, exp.y, "getTangentAt #" + i + ": y correct" ); - - } ); - - } ); - - QUnit.test( "computeFrenetFrames", ( assert ) => { - - var curve = new THREE.CatmullRomCurve3( positions ); - curve.type = 'catmullrom'; - - var expected = { - binormals: [ - new THREE.Vector3( - 1, 0, 0 ), - new THREE.Vector3( - 0.28685061854203, 0.6396363672964267, - 0.7131493814579701 ), - new THREE.Vector3( - 1.9982670528160395e-8, - 0.0001999133310081272, - 0.9999999800173295 ) - ], - normals: [ - new THREE.Vector3( 0, 0, - 1 ), - new THREE.Vector3( - 0.7131493814579699, - 0.6396363672964268, - 0.2868506185420297 ), - new THREE.Vector3( - 0.9999999800173294, 0.00019991333100810582, - 1.99826701852146e-8 ) - ], - tangents: [ - new THREE.Vector3( 0, 1, 0 ), - new THREE.Vector3( 0.6396363672964269, - 0.4262987629159403, - 0.6396363672964269 ), - new THREE.Vector3( - 0.0001999133310081273, - 0.9999999600346594, 0.0001999133310081273 ) - ] - }; - - var frames = curve.computeFrenetFrames( 2, false ); - - Object.keys( expected ).forEach( function ( group, i ) { - - expected[ group ].forEach( function ( vec, j ) { - - assert.numEqual( frames[ group ][ j ].x, vec.x, "Frenet frames [" + i + ", " + j + "].x correct" ); - assert.numEqual( frames[ group ][ j ].y, vec.y, "Frenet frames [" + i + ", " + j + "].y correct" ); - assert.numEqual( frames[ group ][ j ].z, vec.z, "Frenet frames [" + i + ", " + j + "].z correct" ); - - } ); - - } ); - - } ); - - QUnit.test( "getUtoTmapping", ( assert ) => { - - var curve = new THREE.CatmullRomCurve3( positions ); - curve.type = 'catmullrom'; - - var start = curve.getUtoTmapping( 0, 0 ); - var end = curve.getUtoTmapping( 0, curve.getLength() ); - var somewhere = curve.getUtoTmapping( 0.5, 500 ); - - var expectedSomewhere = 0.8964116382083199; - - assert.strictEqual( start, 0, "getUtoTmapping( 0, 0 ) is the starting point" ); - assert.strictEqual( end, 1, "getUtoTmapping( 0, length ) is the ending point" ); - assert.numEqual( somewhere, expectedSomewhere, "getUtoTmapping( 0.5, 500 ) is correct" ); - - } ); - - QUnit.test( "getSpacedPoints", ( assert ) => { - - var curve = new THREE.CatmullRomCurve3( positions ); - curve.type = 'catmullrom'; - - var expectedPoints = [ - new THREE.Vector3( - 60, - 100, 60 ), - new THREE.Vector3( - 60, 10.311489426555056, 60 ), - new THREE.Vector3( - 65.05889864636504, 117.99691802595966, 65.05889864636504 ), - new THREE.Vector3( 6.054276900088592, 78.7153118386369, - 6.054276900088592 ), - new THREE.Vector3( 64.9991491385602, 8.386980812799566, - 64.9991491385602 ), - new THREE.Vector3( 60, - 100, - 60 ) - ]; - - var points = curve.getSpacedPoints(); - - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - assert.deepEqual( points, expectedPoints, "Correct points calculated" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author moraxy / https://github.com/moraxy - */ - /* global QUnit */ - - QUnit.module( 'Extras', () => { - - QUnit.module( 'Curves', () => { - - QUnit.module.todo( 'CubicBezierCurve', ( hooks ) => { - - let curve = undefined; - hooks.before( function () { - - curve = new CubicBezierCurve( - new Vector2( - 10, 0 ), - new Vector2( - 5, 15 ), - new Vector2( 20, 15 ), - new Vector2( 10, 0 ) - ); - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isCubicBezierCurve", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getPoint", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( "Simple curve", ( assert ) => { - - var expectedPoints = [ - new Vector2( - 10, 0 ), - new Vector2( - 3.359375, 8.4375 ), - new Vector2( 5.625, 11.25 ), - new Vector2( 11.796875, 8.4375 ), - new Vector2( 10, 0 ) - ]; - - var points = curve.getPoints( expectedPoints.length - 1 ); - - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - assert.deepEqual( points, expectedPoints, "Correct points calculated" ); - - // symmetry - var curveRev = new CubicBezierCurve( - curve.v3, curve.v2, curve.v1, curve.v0 - ); - - var points = curveRev.getPoints( expectedPoints.length - 1 ); - - assert.strictEqual( points.length, expectedPoints.length, "Reversed: Correct number of points" ); - assert.deepEqual( points, expectedPoints.reverse(), "Reversed: Correct points curve" ); - - } ); - - QUnit.test( "getLength/getLengths", ( assert ) => { - - var length = curve.getLength(); - var expectedLength = 36.64630888504102; - - assert.numEqual( length, expectedLength, "Correct length of curve" ); - - var expectedLengths = [ - 0, - 10.737285813492393, - 20.15159143794633, - 26.93408340370825, - 35.56079575637337 - ]; - var lengths = curve.getLengths( expectedLengths.length - 1 ); - - assert.strictEqual( lengths.length, expectedLengths.length, "Correct number of segments" ); - - lengths.forEach( function ( segment, i ) { - - assert.numEqual( segment, expectedLengths[ i ], "segment[" + i + "] correct" ); - - } ); - - } ); - - QUnit.test( "getPointAt", ( assert ) => { - - var expectedPoints = [ - new Vector2( - 10, 0 ), - new Vector2( - 3.3188282598022596, 8.463722639089221 ), - new Vector2( 3.4718554735926617, 11.07899406116314 ), - new Vector2( 10, 0 ) - ]; - - var points = [ - curve.getPointAt( 0 ), - curve.getPointAt( 0.3 ), - curve.getPointAt( 0.5 ), - curve.getPointAt( 1 ) - ]; - - assert.deepEqual( points, expectedPoints, "Correct points" ); - - } ); - - QUnit.test( "getTangent/getTangentAt", ( assert ) => { - - var expectedTangents = [ - new Vector2( 0.316370061632252, 0.9486358543207215 ), - new Vector2( 0.838961283088303, 0.5441911111721949 ), - new Vector2( 1, 0 ), - new Vector2( 0.47628313192245453, - 0.8792919755383518 ), - new Vector2( - 0.5546041767829665, - 0.8321142992972107 ) - ]; - - var tangents = [ - curve.getTangent( 0 ), - curve.getTangent( 0.25 ), - curve.getTangent( 0.5 ), - curve.getTangent( 0.75 ), - curve.getTangent( 1 ) - ]; - - expectedTangents.forEach( function ( exp, i ) { - - var tangent = tangents[ i ]; - - assert.numEqual( tangent.x, exp.x, "getTangent #" + i + ": x correct" ); - assert.numEqual( tangent.y, exp.y, "getTangent #" + i + ": y correct" ); - - } ); - - // - - var expectedTangents = [ - new Vector2( 0.316370061632252, 0.9486358543207215 ), - new Vector2( 0.7794223085548987, 0.6264988945935596 ), - new Vector2( 0.988266153082452, 0.15274164681452052 ), - new Vector2( 0.5004110404199416, - 0.8657879593906534 ), - new Vector2( - 0.5546041767829665, - 0.8321142992972107 ) - ]; - - var tangents = [ - curve.getTangentAt( 0 ), - curve.getTangentAt( 0.25 ), - curve.getTangentAt( 0.5 ), - curve.getTangentAt( 0.75 ), - curve.getTangentAt( 1 ) - ]; - - expectedTangents.forEach( function ( exp, i ) { - - var tangent = tangents[ i ]; - - assert.numEqual( tangent.x, exp.x, "getTangentAt #" + i + ": x correct" ); - assert.numEqual( tangent.y, exp.y, "getTangentAt #" + i + ": y correct" ); - - } ); - - } ); - - QUnit.test( "getUtoTmapping", ( assert ) => { - - var start = curve.getUtoTmapping( 0, 0 ); - var end = curve.getUtoTmapping( 0, curve.getLength() ); - var somewhere = curve.getUtoTmapping( 0.5, 1 ); - - var expectedSomewhere = 0.02130029182257093; - - assert.strictEqual( start, 0, "getUtoTmapping( 0, 0 ) is the starting point" ); - assert.strictEqual( end, 1, "getUtoTmapping( 0, length ) is the ending point" ); - assert.numEqual( somewhere, expectedSomewhere, "getUtoTmapping( 0.5, 1 ) is correct" ); - - } ); - - QUnit.test( "getSpacedPoints", ( assert ) => { - - var expectedPoints = [ - new Vector2( - 10, 0 ), - new Vector2( - 6.16826457740703, 6.17025727295411 ), - new Vector2( - 0.058874033259857184, 10.1240558653185 ), - new Vector2( 7.123523032625162, 11.154913869041575 ), - new Vector2( 12.301846885754463, 6.808865855469985 ), - new Vector2( 10, 0 ) - ]; - - var points = curve.getSpacedPoints(); - - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - assert.deepEqual( points, expectedPoints, "Correct points calculated" ); - - } ); - - } ); - - } ); - - } ); - - function CubicBezierCurve3( v0, v1, v2, v3 ) { - - Curve.call( this ); - - this.type = 'CubicBezierCurve3'; - - this.v0 = v0 || new Vector3(); - this.v1 = v1 || new Vector3(); - this.v2 = v2 || new Vector3(); - this.v3 = v3 || new Vector3(); - - } - - CubicBezierCurve3.prototype = Object.create( Curve.prototype ); - CubicBezierCurve3.prototype.constructor = CubicBezierCurve3; - - CubicBezierCurve3.prototype.isCubicBezierCurve3 = true; - - CubicBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) { - - var point = optionalTarget || new Vector3(); - - var v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3; - - point.set( - CubicBezier( t, v0.x, v1.x, v2.x, v3.x ), - CubicBezier( t, v0.y, v1.y, v2.y, v3.y ), - CubicBezier( t, v0.z, v1.z, v2.z, v3.z ) - ); - - return point; - - }; - - CubicBezierCurve3.prototype.copy = function ( source ) { - - Curve.prototype.copy.call( this, source ); - - this.v0.copy( source.v0 ); - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); - this.v3.copy( source.v3 ); - - return this; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author moraxy / https://github.com/moraxy - */ - /* global QUnit */ - - QUnit.module( 'Extras', () => { - - QUnit.module( 'Curves', () => { - - QUnit.module.todo( 'CubicBezierCurve3', ( hooks ) => { - - let curve = undefined; - hooks.before( function () { - - curve = new CubicBezierCurve3( - new Vector3( - 10, 0, 2 ), - new Vector3( - 5, 15, 4 ), - new Vector3( 20, 15, - 5 ), - new Vector3( 10, 0, 10 ) - ); - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isCubicBezierCurve3", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getPoint", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( "Simple curve", ( assert ) => { - - var expectedPoints = [ - new Vector3( - 10, 0, 2 ), - new Vector3( - 3.359375, 8.4375, 1.984375 ), - new Vector3( 5.625, 11.25, 1.125 ), - new Vector3( 11.796875, 8.4375, 2.703125 ), - new Vector3( 10, 0, 10 ) - ]; - - var points = curve.getPoints( expectedPoints.length - 1 ); - - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - assert.deepEqual( points, expectedPoints, "Correct points calculated" ); - - // symmetry - var curveRev = new CubicBezierCurve3( - curve.v3, curve.v2, curve.v1, curve.v0 - ); - - points = curveRev.getPoints( expectedPoints.length - 1 ); - - assert.strictEqual( points.length, expectedPoints.length, "Reversed: Correct number of points" ); - assert.deepEqual( points, expectedPoints.reverse(), "Reversed: Correct points curve" ); - - } ); - - QUnit.test( "getLength/getLengths", ( assert ) => { - - var length = curve.getLength(); - var expectedLength = 39.58103024989427; - - assert.numEqual( length, expectedLength, "Correct length of curve" ); - - var expectedLengths = [ - 0, - 10.73729718231036, - 20.19074500737662, - 27.154413277853756, - 38.453287150114214 - ]; - var lengths = curve.getLengths( expectedLengths.length - 1 ); - - assert.strictEqual( lengths.length, expectedLengths.length, "Correct number of segments" ); - - lengths.forEach( function ( segment, i ) { - - assert.numEqual( segment, expectedLengths[ i ], "segment[" + i + "] correct" ); - - } ); - - } ); - - QUnit.test( "getPointAt", ( assert ) => { - - var expectedPoints = [ - new Vector3( - 10, 0, 2 ), - new Vector3( - 2.591880240484318, 8.908333501170798, 1.8953420625251136 ), - new Vector3( 4.866251460832755, 11.22787914038507, 1.150832855206874 ), - new Vector3( 10, 0, 10 ) - ]; - - var points = [ - curve.getPointAt( 0 ), - curve.getPointAt( 0.3 ), - curve.getPointAt( 0.5 ), - curve.getPointAt( 1 ) - ]; - - assert.deepEqual( points, expectedPoints, "Correct points" ); - - } ); - - QUnit.test( "getTangent/getTangentAt", ( assert ) => { - - var expectedTangents = [ - new Vector3( 0.3138715439944244, 0.9411440474105875, 0.12542940601858074 ), - new Vector3( 0.8351825262580098, 0.54174002562179, - 0.09480449605683638 ), - new Vector3( 0.9997531780538501, 0, - 0.02221672728433752 ), - new Vector3( 0.40693407933981185, - 0.7512629496079668, 0.5196235518317053 ), - new Vector3( - 0.42632467075185815, - 0.6396469221230213, 0.6396085444448543 ) - ]; - - var tangents = [ - curve.getTangent( 0 ), - curve.getTangent( 0.25 ), - curve.getTangent( 0.5 ), - curve.getTangent( 0.75 ), - curve.getTangent( 1 ) - ]; - - expectedTangents.forEach( function ( exp, i ) { - - var tangent = tangents[ i ]; - - assert.numEqual( tangent.x, exp.x, "getTangent #" + i + ": x correct" ); - assert.numEqual( tangent.y, exp.y, "getTangent #" + i + ": y correct" ); - - } ); - - // - - expectedTangents = [ - new Vector3( 0.3138715439944244, 0.9411440474105875, 0.12542940601858074 ), - new Vector3( 0.8016539573770751, 0.5918626760037707, - 0.08396133262002324 ), - new Vector3( 0.997337559412928, 0.05740742907719314, - 0.044968652092444425 ), - new Vector3( 0.1389373097746809, - 0.7882209938358005, 0.5995032016837588 ), - new Vector3( - 0.42632467075185815, - 0.6396469221230213, 0.6396085444448543 ) - ]; - - tangents = [ - curve.getTangentAt( 0 ), - curve.getTangentAt( 0.25 ), - curve.getTangentAt( 0.5 ), - curve.getTangentAt( 0.75 ), - curve.getTangentAt( 1 ) - ]; - - expectedTangents.forEach( function ( exp, i ) { - - var tangent = tangents[ i ]; - - assert.numEqual( tangent.x, exp.x, "getTangentAt #" + i + ": x correct" ); - assert.numEqual( tangent.y, exp.y, "getTangentAt #" + i + ": y correct" ); - - } ); - - } ); - - QUnit.test( "getUtoTmapping", ( assert ) => { - - var start = curve.getUtoTmapping( 0, 0 ); - var end = curve.getUtoTmapping( 0, curve.getLength() ); - var somewhere = curve.getUtoTmapping( 0.5, 1 ); - - var expectedSomewhere = 0.021163245321323316; - - assert.strictEqual( start, 0, "getUtoTmapping( 0, 0 ) is the starting point" ); - assert.strictEqual( end, 1, "getUtoTmapping( 0, length ) is the ending point" ); - assert.numEqual( somewhere, expectedSomewhere, "getUtoTmapping( 0.5, 1 ) is correct" ); - - } ); - - QUnit.test( "getSpacedPoints", ( assert ) => { - - var expectedPoints = [ - new Vector3( - 10, 0, 2 ), - new Vector3( - 5.756524515061918, 6.568020242700483, 2.22116711170301 ), - new Vector3( 1.0003511895116906, 10.49656064587831, 1.4727101010850698 ), - new Vector3( 8.767656412295171, 10.784286845278622, 1.2873599519775174 ), - new Vector3( 12.306772513558396, 5.545103788071547, 4.909948454535794 ), - new Vector3( 10, 0, 10 ) - ]; - - var points = curve.getSpacedPoints(); - - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - assert.deepEqual( points, expectedPoints, "Correct points calculated" ); - - } ); - - QUnit.test( "computeFrenetFrames", ( assert ) => { - - var expected = { - binormals: [ - new Vector3( - 0.9486358543207215, 0.316370061632252, - 6.938893903907228e-18 ), - new Vector3( - 0.05491430765311864, 0.9969838307670049, 0.054842137122173326 ), - new Vector3( 0.5944656510461876, 0.334836503700931, 0.7310917216844742 ) - ], - normals: [ - new Vector3( 0.03968210891259515, 0.11898683173537697, - 0.9921025471723304 ), - new Vector3( - 0.047981365124836806, 0.05222670079466692, - 0.9974819097732357 ), - new Vector3( 0.6818048583242511, - 0.6919077473246573, - 0.23749906180354932 ) - ], - tangents: [ - new Vector3( 0.3138715439944244, 0.9411440474105875, 0.12542940601858074 ), - new Vector3( 0.9973375594129282, 0.05740742907719315, - 0.04496865209244443 ), - new Vector3( - 0.42632467075185815, - 0.6396469221230213, 0.6396085444448543 ) - ] - }; - - var frames = curve.computeFrenetFrames( 2, false ); - - Object.keys( expected ).forEach( function ( group, i ) { - - expected[ group ].forEach( function ( vec, j ) { - - assert.numEqual( frames[ group ][ j ].x, vec.x, "Frenet frames [" + i + ", " + j + "].x correct" ); - assert.numEqual( frames[ group ][ j ].y, vec.y, "Frenet frames [" + i + ", " + j + "].y correct" ); - assert.numEqual( frames[ group ][ j ].z, vec.z, "Frenet frames [" + i + ", " + j + "].z correct" ); - - } ); - - } ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Extras', () => { - - QUnit.module( 'Curves', () => { - - QUnit.module.todo( 'EllipseCurve', ( hooks ) => { - - let curve = undefined; - hooks.before( function () { - - curve = new EllipseCurve( - 0, 0, // ax, aY - 10, 10, // xRadius, yRadius - 0, 2 * Math.PI, // aStartAngle, aEndAngle - false, // aClockwise - 0 // aRotation - ); - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isEllipseCurve", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getPoint", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( "Simple curve", ( assert ) => { - - var expectedPoints = [ - new Vector2( 10, 0 ), - new Vector2( 0, 10 ), - new Vector2( - 10, 0 ), - new Vector2( 0, - 10 ), - new Vector2( 10, 0 ) - ]; - - var points = curve.getPoints( expectedPoints.length - 1 ); - - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - - points.forEach( function ( point, i ) { - - assert.numEqual( point.x, expectedPoints[ i ].x, "point[" + i + "].x correct" ); - assert.numEqual( point.y, expectedPoints[ i ].y, "point[" + i + "].y correct" ); - - } ); - - } ); - - QUnit.test( "getLength/getLengths", ( assert ) => { - - var length = curve.getLength(); - var expectedLength = 62.829269247282795; - - assert.numEqual( length, expectedLength, "Correct length of curve" ); - - var lengths = curve.getLengths( 5 ); - var expectedLengths = [ - 0, - 11.755705045849462, - 23.51141009169892, - 35.26711513754839, - 47.02282018339785, - 58.77852522924731 - ]; - - assert.strictEqual( lengths.length, expectedLengths.length, "Correct number of segments" ); - - lengths.forEach( function ( segment, i ) { - - assert.numEqual( segment, expectedLengths[ i ], "segment[" + i + "] correct" ); - - } ); - - } ); - - QUnit.test( "getPoint/getPointAt", ( assert ) => { - - var testValues = [ 0, 0.3, 0.5, 0.7, 1 ]; - - testValues.forEach( function ( val, i ) { - - var expectedX = Math.cos( val * Math.PI * 2 ) * 10; - var expectedY = Math.sin( val * Math.PI * 2 ) * 10; - - var p = curve.getPoint( val ); - var a = curve.getPointAt( val ); - - assert.numEqual( p.x, expectedX, "getPoint(" + val + ").x correct" ); - assert.numEqual( p.y, expectedY, "getPoint(" + val + ").y correct" ); - - assert.numEqual( a.x, expectedX, "getPointAt(" + val + ").x correct" ); - assert.numEqual( a.y, expectedY, "getPointAt(" + val + ").y correct" ); - - } ); - - } ); - - QUnit.test( "getTangent", ( assert ) => { - - var expectedTangents = [ - new Vector2( - 0.000314159260186071, 0.9999999506519786 ), - new Vector2( - 1, 0 ), - new Vector2( 0, - 1 ), - new Vector2( 1, 0 ), - new Vector2( 0.00031415926018600165, 0.9999999506519784 ) - ]; - - var tangents = [ - curve.getTangent( 0 ), - curve.getTangent( 0.25 ), - curve.getTangent( 0.5 ), - curve.getTangent( 0.75 ), - curve.getTangent( 1 ) - ]; - - expectedTangents.forEach( function ( exp, i ) { - - var tangent = tangents[ i ]; - - assert.numEqual( tangent.x, exp.x, "getTangent #" + i + ": x correct" ); - assert.numEqual( tangent.y, exp.y, "getTangent #" + i + ": y correct" ); - - } ); - - } ); - - QUnit.test( "getUtoTmapping", ( assert ) => { - - var start = curve.getUtoTmapping( 0, 0 ); - var end = curve.getUtoTmapping( 0, curve.getLength() ); - var somewhere = curve.getUtoTmapping( 0.7, 1 ); - - var expectedSomewhere = 0.01591614882650014; - - assert.strictEqual( start, 0, "getUtoTmapping( 0, 0 ) is the starting point" ); - assert.strictEqual( end, 1, "getUtoTmapping( 0, length ) is the ending point" ); - assert.numEqual( somewhere, expectedSomewhere, "getUtoTmapping( 0.7, 1 ) is correct" ); - - } ); - - QUnit.test( "getSpacedPoints", ( assert ) => { - - var expectedPoints = [ - new Vector2( 10, 0 ), - new Vector2( 3.0901699437494603, 9.51056516295154 ), - new Vector2( - 8.090169943749492, 5.877852522924707 ), - new Vector2( - 8.090169943749459, - 5.877852522924751 ), - new Vector2( 3.0901699437494807, - 9.510565162951533 ), - new Vector2( 10, - 2.4492935982947065e-15 ) - ]; - - var points = curve.getSpacedPoints(); - - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - - expectedPoints.forEach( function ( exp, i ) { - - var point = points[ i ]; - - assert.numEqual( point.x, exp.x, "Point #" + i + ": x correct" ); - assert.numEqual( point.y, exp.y, "Point #" + i + ": y correct" ); - - } ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Extras', () => { - - QUnit.module( 'Curves', () => { - - QUnit.module.todo( 'LineCurve', ( hooks ) => { - - let _points = undefined; - let _curve = undefined; - hooks.before( function () { - - _points = [ - new Vector2( 0, 0 ), - new Vector2( 10, 10 ), - new Vector2( - 10, 10 ), - new Vector2( - 8, 5 ) - ]; - - _curve = new LineCurve( _points[ 0 ], _points[ 1 ] ); - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isLineCurve", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getPoint", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getPointAt", ( assert ) => { - - var curve = new LineCurve( _points[ 0 ], _points[ 3 ] ); - - var expectedPoints = [ - new Vector2( 0, 0 ), - new Vector2( - 2.4, 1.5 ), - new Vector2( - 4, 2.5 ), - new Vector2( - 8, 5 ) - ]; - - var points = [ - curve.getPointAt( 0 ), - curve.getPointAt( 0.3 ), - curve.getPointAt( 0.5 ), - curve.getPointAt( 1 ) - ]; - - assert.deepEqual( points, expectedPoints, "Correct points" ); - - } ); - - QUnit.test( "getTangent", ( assert ) => { - - var curve = _curve; - - var tangent = curve.getTangent( 0 ); - var expectedTangent = Math.sqrt( 0.5 ); - - assert.numEqual( tangent.x, expectedTangent, "tangent.x correct" ); - assert.numEqual( tangent.y, expectedTangent, "tangent.y correct" ); - - } ); - - // OTHERS - QUnit.test( "Simple curve", ( assert ) => { - - var curve = _curve; - - var expectedPoints = [ - new Vector2( 0, 0 ), - new Vector2( 2, 2 ), - new Vector2( 4, 4 ), - new Vector2( 6, 6 ), - new Vector2( 8, 8 ), - new Vector2( 10, 10 ) - ]; - - var points = curve.getPoints(); - - assert.deepEqual( points, expectedPoints, "Correct points for first curve" ); - - // - - curve = new LineCurve( _points[ 1 ], _points[ 2 ] ); - - expectedPoints = [ - new Vector2( 10, 10 ), - new Vector2( 6, 10 ), - new Vector2( 2, 10 ), - new Vector2( - 2, 10 ), - new Vector2( - 6, 10 ), - new Vector2( - 10, 10 ) - ]; - - points = curve.getPoints(); - - assert.deepEqual( points, expectedPoints, "Correct points for second curve" ); - - } ); - - QUnit.test( "getLength/getLengths", ( assert ) => { - - var curve = _curve; - - var length = curve.getLength(); - var expectedLength = Math.sqrt( 200 ); - - assert.numEqual( length, expectedLength, "Correct length of curve" ); - - var lengths = curve.getLengths( 5 ); - var expectedLengths = [ - 0.0, - Math.sqrt( 8 ), - Math.sqrt( 32 ), - Math.sqrt( 72 ), - Math.sqrt( 128 ), - Math.sqrt( 200 ) - ]; - - assert.strictEqual( lengths.length, expectedLengths.length, "Correct number of segments" ); - - lengths.forEach( function ( segment, i ) { - - assert.numEqual( segment, expectedLengths[ i ], "segment[" + i + "] correct" ); - - } ); - - } ); - - QUnit.test( "getUtoTmapping", ( assert ) => { - - var curve = _curve; - - var start = curve.getUtoTmapping( 0, 0 ); - var end = curve.getUtoTmapping( 0, curve.getLength() ); - var somewhere = curve.getUtoTmapping( 0.3, 0 ); - - assert.strictEqual( start, 0, "getUtoTmapping( 0, 0 ) is the starting point" ); - assert.strictEqual( end, 1, "getUtoTmapping( 0, length ) is the ending point" ); - assert.numEqual( somewhere, 0.3, "getUtoTmapping( 0.3, 0 ) is correct" ); - - } ); - - QUnit.test( "getSpacedPoints", ( assert ) => { - - var curve = _curve; - - var expectedPoints = [ - new Vector2( 0, 0 ), - new Vector2( 2.5, 2.5 ), - new Vector2( 5, 5 ), - new Vector2( 7.5, 7.5 ), - new Vector2( 10, 10 ) - ]; - - var points = curve.getSpacedPoints( 4 ); - - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - assert.deepEqual( points, expectedPoints, "Correct points calculated" ); - - } ); - - } ); - - } ); - - } ); - - function LineCurve3( v1, v2 ) { - - Curve.call( this ); - - this.type = 'LineCurve3'; - - this.v1 = v1 || new Vector3(); - this.v2 = v2 || new Vector3(); - - } - - LineCurve3.prototype = Object.create( Curve.prototype ); - LineCurve3.prototype.constructor = LineCurve3; - - LineCurve3.prototype.isLineCurve3 = true; - - LineCurve3.prototype.getPoint = function ( t, optionalTarget ) { - - var point = optionalTarget || new Vector3(); - - if ( t === 1 ) { - - point.copy( this.v2 ); - - } else { - - point.copy( this.v2 ).sub( this.v1 ); - point.multiplyScalar( t ).add( this.v1 ); - - } - - return point; - - }; - - // Line curve is linear, so we can overwrite default getPointAt - - LineCurve3.prototype.getPointAt = function ( u, optionalTarget ) { - - return this.getPoint( u, optionalTarget ); - - }; - - LineCurve3.prototype.copy = function ( source ) { - - Curve.prototype.copy.call( this, source ); - - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); - - return this; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Extras', () => { - - QUnit.module( 'Curves', () => { - - QUnit.module.todo( 'LineCurve3', ( hooks ) => { - - let _points = undefined; - let _curve = undefined; - hooks.before( function () { - - _points = [ - new Vector3( 0, 0, 0 ), - new Vector3( 10, 10, 10 ), - new Vector3( - 10, 10, - 10 ), - new Vector3( - 8, 5, - 7 ) - ]; - - _curve = new LineCurve3( _points[ 0 ], _points[ 1 ] ); - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isCatmullRomCurve3", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getPoint", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getPointAt", ( assert ) => { - - var curve = new LineCurve3( _points[ 0 ], _points[ 3 ] ); - - var expectedPoints = [ - new Vector3( 0, 0, 0 ), - new Vector3( - 2.4, 1.5, - 2.1 ), - new Vector3( - 4, 2.5, - 3.5 ), - new Vector3( - 8, 5, - 7 ) - ]; - - var points = [ - curve.getPointAt( 0 ), - curve.getPointAt( 0.3 ), - curve.getPointAt( 0.5 ), - curve.getPointAt( 1 ) - ]; - - assert.deepEqual( points, expectedPoints, "Correct getPointAt points" ); - - } ); - - // OTHERS - QUnit.test( "Simple curve", ( assert ) => { - - var curve = _curve; - - var expectedPoints = [ - new Vector3( 0, 0, 0 ), - new Vector3( 2, 2, 2 ), - new Vector3( 4, 4, 4 ), - new Vector3( 6, 6, 6 ), - new Vector3( 8, 8, 8 ), - new Vector3( 10, 10, 10 ) - ]; - - var points = curve.getPoints(); - - assert.deepEqual( points, expectedPoints, "Correct points for first curve" ); - - // - - curve = new LineCurve3( _points[ 1 ], _points[ 2 ] ); - - expectedPoints = [ - new Vector3( 10, 10, 10 ), - new Vector3( 6, 10, 6 ), - new Vector3( 2, 10, 2 ), - new Vector3( - 2, 10, - 2 ), - new Vector3( - 6, 10, - 6 ), - new Vector3( - 10, 10, - 10 ) - ]; - - points = curve.getPoints(); - - assert.deepEqual( points, expectedPoints, "Correct points for second curve" ); - - } ); - - QUnit.test( "getLength/getLengths", ( assert ) => { - - var curve = _curve; - - var length = curve.getLength(); - var expectedLength = Math.sqrt( 300 ); - - assert.numEqual( length, expectedLength, "Correct length of curve" ); - - var lengths = curve.getLengths( 5 ); - var expectedLengths = [ - 0.0, - Math.sqrt( 12 ), - Math.sqrt( 48 ), - Math.sqrt( 108 ), - Math.sqrt( 192 ), - Math.sqrt( 300 ) - ]; - - assert.strictEqual( lengths.length, expectedLengths.length, "Correct number of segments" ); - - lengths.forEach( function ( segment, i ) { - - assert.numEqual( segment, expectedLengths[ i ], "segment[" + i + "] correct" ); - - } ); - - } ); - - QUnit.test( "getTangent/getTangentAt", ( assert ) => { - - var curve = _curve; - - var tangent = curve.getTangent( 0.5 ); - var expectedTangent = Math.sqrt( 1 / 3 ); - - assert.numEqual( tangent.x, expectedTangent, "tangent.x correct" ); - assert.numEqual( tangent.y, expectedTangent, "tangent.y correct" ); - assert.numEqual( tangent.z, expectedTangent, "tangent.z correct" ); - - tangent = curve.getTangentAt( 0.5 ); - - assert.numEqual( tangent.x, expectedTangent, "tangentAt.x correct" ); - assert.numEqual( tangent.y, expectedTangent, "tangentAt.y correct" ); - assert.numEqual( tangent.z, expectedTangent, "tangentAt.z correct" ); - - } ); - - QUnit.test( "computeFrenetFrames", ( assert ) => { - - var curve = _curve; - - var expected = { - binormals: new Vector3( - 0.5 * Math.sqrt( 2 ), 0.5 * Math.sqrt( 2 ), 0 ), - normals: new Vector3( Math.sqrt( 1 / 6 ), Math.sqrt( 1 / 6 ), - Math.sqrt( 2 / 3 ) ), - tangents: new Vector3( Math.sqrt( 1 / 3 ), Math.sqrt( 1 / 3 ), Math.sqrt( 1 / 3 ) ) - }; - - var frames = curve.computeFrenetFrames( 1, false ); - - for ( var val in expected ) { - - assert.numEqual( frames[ val ][ 0 ].x, expected[ val ].x, "Frenet frames " + val + ".x correct" ); - assert.numEqual( frames[ val ][ 0 ].y, expected[ val ].y, "Frenet frames " + val + ".y correct" ); - assert.numEqual( frames[ val ][ 0 ].z, expected[ val ].z, "Frenet frames " + val + ".z correct" ); - - } - - } ); - - QUnit.test( "getUtoTmapping", ( assert ) => { - - var curve = _curve; - - var start = curve.getUtoTmapping( 0, 0 ); - var end = curve.getUtoTmapping( 0, curve.getLength() ); - var somewhere = curve.getUtoTmapping( 0.7, 0 ); - - assert.strictEqual( start, 0, "getUtoTmapping( 0, 0 ) is the starting point" ); - assert.strictEqual( end, 1, "getUtoTmapping( 0, length ) is the ending point" ); - assert.numEqual( somewhere, 0.7, "getUtoTmapping( 0.7, 0 ) is correct" ); - - } ); - - QUnit.test( "getSpacedPoints", ( assert ) => { - - var curve = _curve; - - var expectedPoints = [ - new Vector3( 0, 0, 0 ), - new Vector3( 2.5, 2.5, 2.5 ), - new Vector3( 5, 5, 5 ), - new Vector3( 7.5, 7.5, 7.5 ), - new Vector3( 10, 10, 10 ) - ]; - - var points = curve.getSpacedPoints( 4 ); - - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - assert.deepEqual( points, expectedPoints, "Correct points calculated" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Extras', () => { - - QUnit.module( 'Curves', () => { - - QUnit.module.todo( 'QuadraticBezierCurve', ( hooks ) => { - - let _curve = undefined; - hooks.before( function () { - - _curve = new QuadraticBezierCurve( - new Vector2( - 10, 0 ), - new Vector2( 20, 15 ), - new Vector2( 10, 0 ) - ); - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isQuadraticBezierCurve", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getPoint", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( "Simple curve", ( assert ) => { - - var curve = _curve; - - var expectedPoints = [ - new Vector2( - 10, 0 ), - new Vector2( 2.5, 5.625 ), - new Vector2( 10, 7.5 ), - new Vector2( 12.5, 5.625 ), - new Vector2( 10, 0 ) - ]; - - var points = curve.getPoints( expectedPoints.length - 1 ); - - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - assert.deepEqual( points, expectedPoints, "Correct points calculated" ); - - // symmetry - var curveRev = new QuadraticBezierCurve( - curve.v2, curve.v1, curve.v0 - ); - - points = curveRev.getPoints( expectedPoints.length - 1 ); - - assert.strictEqual( points.length, expectedPoints.length, "Reversed: Correct number of points" ); - assert.deepEqual( points, expectedPoints.reverse(), "Reversed: Correct points curve" ); - - } ); - - QUnit.test( "getLength/getLengths", ( assert ) => { - - var curve = _curve; - - var length = curve.getLength(); - var expectedLength = 31.269026549416683; - - assert.numEqual( length, expectedLength, "Correct length of curve" ); - - var expectedLengths = [ - 0, - 13.707320124663317, - 21.43814317269643, - 24.56314317269643, - 30.718679298818998 - ]; - var lengths = curve.getLengths( expectedLengths.length - 1 ); - - assert.strictEqual( lengths.length, expectedLengths.length, "Correct number of segments" ); - - lengths.forEach( function ( segment, i ) { - - assert.numEqual( segment, expectedLengths[ i ], "segment[" + i + "] correct" ); - - } ); - - } ); - - QUnit.test( "getPointAt", ( assert ) => { - - var curve = _curve; - - var expectedPoints = [ - new Vector2( - 10, 0 ), - new Vector2( - 1.5127849599387615, 3.993582003773624 ), - new Vector2( 4.310076165722796, 6.269921971403917 ), - new Vector2( 10, 0 ) - ]; - - var points = [ - curve.getPointAt( 0 ), - curve.getPointAt( 0.3 ), - curve.getPointAt( 0.5 ), - curve.getPointAt( 1 ) - ]; - - assert.deepEqual( points, expectedPoints, "Correct points" ); - - } ); - - QUnit.test( "getTangent/getTangentAt", ( assert ) => { - - var curve = _curve; - - var expectedTangents = [ - new Vector2( 0.89443315420562, 0.44720166888975904 ), - new Vector2( 0.936329177569021, 0.3511234415884543 ), - new Vector2( 1, 0 ), - new Vector2( - 5.921189464667277e-13, - 1 ), - new Vector2( - 0.5546617882904897, - 0.8320758983472577 ) - ]; - - var tangents = [ - curve.getTangent( 0 ), - curve.getTangent( 0.25 ), - curve.getTangent( 0.5 ), - curve.getTangent( 0.75 ), - curve.getTangent( 1 ) - ]; - - expectedTangents.forEach( function ( exp, i ) { - - var tangent = tangents[ i ]; - - assert.numEqual( tangent.x, exp.x, "getTangent #" + i + ": x correct" ); - assert.numEqual( tangent.y, exp.y, "getTangent #" + i + ": y correct" ); - - } ); - - // - - expectedTangents = [ - new Vector2( 0.89443315420562, 0.44720166888975904 ), - new Vector2( 0.9125211423360805, 0.40902954024086674 ), - new Vector2( 0.9480289098765387, 0.3181842014278863 ), - new Vector2( 0.7969127189169473, - 0.6040944615111106 ), - new Vector2( - 0.5546617882904897, - 0.8320758983472577 ) - ]; - - tangents = [ - curve.getTangentAt( 0 ), - curve.getTangentAt( 0.25 ), - curve.getTangentAt( 0.5 ), - curve.getTangentAt( 0.75 ), - curve.getTangentAt( 1 ) - ]; - - expectedTangents.forEach( function ( exp, i ) { - - var tangent = tangents[ i ]; - - assert.numEqual( tangent.x, exp.x, "getTangentAt #" + i + ": x correct" ); - assert.numEqual( tangent.y, exp.y, "getTangentAt #" + i + ": y correct" ); - - } ); - - } ); - - QUnit.test( "getUtoTmapping", ( assert ) => { - - var curve = _curve; - - var start = curve.getUtoTmapping( 0, 0 ); - var end = curve.getUtoTmapping( 0, curve.getLength() ); - var somewhere = curve.getUtoTmapping( 0.5, 1 ); - - var expectedSomewhere = 0.015073978276116116; - - assert.strictEqual( start, 0, "getUtoTmapping( 0, 0 ) is the starting point" ); - assert.strictEqual( end, 1, "getUtoTmapping( 0, length ) is the ending point" ); - assert.numEqual( somewhere, expectedSomewhere, "getUtoTmapping( 0.5, 1 ) is correct" ); - - } ); - - QUnit.test( "getSpacedPoints", ( assert ) => { - - var curve = _curve; - - var expectedPoints = [ - new Vector2( - 10, 0 ), - new Vector2( - 4.366603655406173, 2.715408933540383 ), - new Vector2( 1.3752241477827831, 5.191972084404416 ), - new Vector2( 7.312990279153634, 7.136310044848586 ), - new Vector2( 12.499856644824826, 5.653289188715387 ), - new Vector2( 10, 0 ) - ]; - - var points = curve.getSpacedPoints(); - - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - assert.deepEqual( points, expectedPoints, "Correct points calculated" ); - - } ); - - } ); - - } ); - - } ); - - function QuadraticBezierCurve3( v0, v1, v2 ) { - - Curve.call( this ); - - this.type = 'QuadraticBezierCurve3'; - - this.v0 = v0 || new Vector3(); - this.v1 = v1 || new Vector3(); - this.v2 = v2 || new Vector3(); - - } - - QuadraticBezierCurve3.prototype = Object.create( Curve.prototype ); - QuadraticBezierCurve3.prototype.constructor = QuadraticBezierCurve3; - - QuadraticBezierCurve3.prototype.isQuadraticBezierCurve3 = true; - - QuadraticBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) { - - var point = optionalTarget || new Vector3(); - - var v0 = this.v0, v1 = this.v1, v2 = this.v2; - - point.set( - QuadraticBezier( t, v0.x, v1.x, v2.x ), - QuadraticBezier( t, v0.y, v1.y, v2.y ), - QuadraticBezier( t, v0.z, v1.z, v2.z ) - ); - - return point; - - }; - - QuadraticBezierCurve3.prototype.copy = function ( source ) { - - Curve.prototype.copy.call( this, source ); - - this.v0.copy( source.v0 ); - this.v1.copy( source.v1 ); - this.v2.copy( source.v2 ); - - return this; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Extras', () => { - - QUnit.module( 'Curves', () => { - - QUnit.module.todo( 'QuadraticBezierCurve3', ( hooks ) => { - - let _curve = undefined; - hooks.before( function () { - - _curve = new QuadraticBezierCurve3( - new Vector3( - 10, 0, 2 ), - new Vector3( 20, 15, - 5 ), - new Vector3( 10, 0, 10 ) - ); - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isQuadraticBezierCurve3", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getPoint", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( "Simple curve", ( assert ) => { - - var curve = _curve; - - var expectedPoints = [ - new Vector3( - 10, 0, 2 ), - new Vector3( 2.5, 5.625, - 0.125 ), - new Vector3( 10, 7.5, 0.5 ), - new Vector3( 12.5, 5.625, 3.875 ), - new Vector3( 10, 0, 10 ) - ]; - - var points = curve.getPoints( expectedPoints.length - 1 ); - - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - assert.deepEqual( points, expectedPoints, "Correct points calculated" ); - - // symmetry - var curveRev = new QuadraticBezierCurve3( - curve.v2, curve.v1, curve.v0 - ); - - points = curveRev.getPoints( expectedPoints.length - 1 ); - - assert.strictEqual( points.length, expectedPoints.length, "Reversed: Correct number of points" ); - assert.deepEqual( points, expectedPoints.reverse(), "Reversed: Correct points curve" ); - - } ); - - QUnit.test( "getLength/getLengths", ( assert ) => { - - var curve = _curve; - - var length = curve.getLength(); - var expectedLength = 35.47294274967861; - - assert.numEqual( length, expectedLength, "Correct length of curve" ); - - var expectedLengths = [ - 0, - 13.871057998581074, - 21.62710402732536, - 26.226696400568883, - 34.91037361704809 - ]; - var lengths = curve.getLengths( expectedLengths.length - 1 ); - - assert.strictEqual( lengths.length, expectedLengths.length, "Correct number of segments" ); - - lengths.forEach( function ( segment, i ) { - - assert.numEqual( segment, expectedLengths[ i ], "segment[" + i + "] correct" ); - - } ); - - } ); - - QUnit.test( "getPointAt", ( assert ) => { - - var curve = _curve; - - var expectedPoints = [ - new Vector3( - 10, 0, 2 ), - new Vector3( - 0.4981634504454243, 4.427089043881476, 0.19308849757196012 ), - new Vector3( 6.149415812887238, 6.838853310980195, - 0.20278120208668637 ), - new Vector3( 10, 0, 10 ) - ]; - - var points = [ - curve.getPointAt( 0 ), - curve.getPointAt( 0.3 ), - curve.getPointAt( 0.5 ), - curve.getPointAt( 1 ) - ]; - - assert.deepEqual( points, expectedPoints, "Correct points" ); - - } ); - - QUnit.test( "getTangent/getTangentAt", ( assert ) => { - - var curve = _curve; - - var expectedTangents = [ - new Vector3( 0.8755715084258769, 0.4377711603816079, - 0.2042815331129452 ), - new Vector3( 0.9340289249885844, 0.3502608468707904, - 0.07005216937416067 ), - new Vector3( 0.9284766908853163, 0, 0.37139067635396156 ), - new Vector3( - 3.669031233375946e-13, - 0.6196442885791218, 0.7848827655333463 ), - new Vector3( - 0.4263618889888853, - 0.6396068005601663, 0.6396238584473043 ) - ]; - - var tangents = [ - curve.getTangent( 0 ), - curve.getTangent( 0.25 ), - curve.getTangent( 0.5 ), - curve.getTangent( 0.75 ), - curve.getTangent( 1 ) - ]; - - expectedTangents.forEach( function ( exp, i ) { - - var tangent = tangents[ i ]; - - assert.numEqual( tangent.x, exp.x, "getTangent #" + i + ": x correct" ); - assert.numEqual( tangent.y, exp.y, "getTangent #" + i + ": y correct" ); - - } ); - - // - - expectedTangents = [ - new Vector3( 0.8755715084258769, 0.4377711603816079, - 0.2042815331129452 ), - new Vector3( 0.9060725703490549, 0.3984742932857448, - 0.14230507668907377 ), - new Vector3( 0.9621604167456882, 0.2688562845452628, 0.044312872940942424 ), - new Vector3( 0.016586454041780826, - 0.6163270940470614, 0.7873155674098058 ), - new Vector3( - 0.4263618889888853, - 0.6396068005601663, 0.6396238584473043 ) - ]; - - tangents = [ - curve.getTangentAt( 0 ), - curve.getTangentAt( 0.25 ), - curve.getTangentAt( 0.5 ), - curve.getTangentAt( 0.75 ), - curve.getTangentAt( 1 ) - ]; - - expectedTangents.forEach( function ( exp, i ) { - - var tangent = tangents[ i ]; - - assert.numEqual( tangent.x, exp.x, "getTangentAt #" + i + ": x correct" ); - assert.numEqual( tangent.y, exp.y, "getTangentAt #" + i + ": y correct" ); - - } ); - - } ); - - QUnit.test( "getUtoTmapping", ( assert ) => { - - var curve = _curve; - - var start = curve.getUtoTmapping( 0, 0 ); - var end = curve.getUtoTmapping( 0, curve.getLength() ); - var somewhere = curve.getUtoTmapping( 0.5, 1 ); - - var expectedSomewhere = 0.014760890927167196; - - assert.strictEqual( start, 0, "getUtoTmapping( 0, 0 ) is the starting point" ); - assert.strictEqual( end, 1, "getUtoTmapping( 0, length ) is the ending point" ); - assert.numEqual( somewhere, expectedSomewhere, "getUtoTmapping( 0.5, 1 ) is correct" ); - - } ); - - QUnit.test( "getSpacedPoints", ( assert ) => { - - var curve = _curve; - - var expectedPoints = [ - new Vector3( - 10, 0, 2 ), - new Vector3( - 3.712652983516992, 3.015179001762753, 0.6957120710270492 ), - new Vector3( 2.7830973773262975, 5.730399338061483, - 0.1452668772806931 ), - new Vector3( 9.575825284074465, 7.48754187603603, 0.3461104039841496 ), - new Vector3( 12.345199937734154, 4.575759904730531, 5.142117429101656 ), - new Vector3( 10, 0, 10 ) - ]; - - var points = curve.getSpacedPoints(); - - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - assert.deepEqual( points, expectedPoints, "Correct points calculated" ); - - } ); - - QUnit.test( "computeFrenetFrames", ( assert ) => { - - var curve = _curve; - - var expected = { - binormals: [ - new Vector3( - 0.447201668889759, 0.8944331542056199, 0 ), - new Vector3( - 0.2684231751110917, 0.9631753839815436, - 0.01556209353802903 ), - new Vector3( 0.3459273556592433, 0.53807011680075, 0.7686447905324219 ) - ], - normals: [ - new Vector3( - 0.18271617600817133, - 0.09135504253146765, - 0.9789121795283909 ), - new Vector3( 0.046865035058597876, - 0.003078628350883253, - 0.9988964863970807 ), - new Vector3( 0.8357929194629689, - 0.5489842348221077, 0.008155102228190641 ) - ], - tangents: [ - new Vector3( 0.8755715084258767, 0.4377711603816078, - 0.20428153311294514 ), - new Vector3( 0.9621604167456884, 0.26885628454526284, 0.04431287294094243 ), - new Vector3( - 0.4263618889888853, - 0.6396068005601663, 0.6396238584473043 ) - ] - }; - - var frames = curve.computeFrenetFrames( 2, false ); - - Object.keys( expected ).forEach( function ( group, i ) { - - expected[ group ].forEach( function ( vec, j ) { - - assert.numEqual( frames[ group ][ j ].x, vec.x, "Frenet frames [" + i + ", " + j + "].x correct" ); - assert.numEqual( frames[ group ][ j ].y, vec.y, "Frenet frames [" + i + ", " + j + "].y correct" ); - assert.numEqual( frames[ group ][ j ].z, vec.z, "Frenet frames [" + i + ", " + j + "].z correct" ); - - } ); - - } ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Extras', () => { - - QUnit.module( 'Curves', () => { - - QUnit.module.todo( 'SplineCurve', ( hooks ) => { - - let _curve = undefined; - hooks.before( function () { - - _curve = new SplineCurve( [ - new Vector2( - 10, 0 ), - new Vector2( - 5, 5 ), - new Vector2( 0, 0 ), - new Vector2( 5, - 5 ), - new Vector2( 10, 0 ) - ] ); - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isSplineCurve", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getPoint", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( "Simple curve", ( assert ) => { - - var curve = _curve; - - var expectedPoints = [ - new Vector2( - 10, 0 ), - new Vector2( - 6.08, 4.56 ), - new Vector2( - 2, 2.48 ), - new Vector2( 2, - 2.48 ), - new Vector2( 6.08, - 4.56 ), - new Vector2( 10, 0 ) - ]; - - var points = curve.getPoints( 5 ); - - assert.strictEqual( points.length, expectedPoints.length, "1st: Correct number of points" ); - - points.forEach( function ( point, i ) { - - assert.numEqual( point.x, expectedPoints[ i ].x, "points[" + i + "].x" ); - assert.numEqual( point.y, expectedPoints[ i ].y, "points[" + i + "].y" ); - - } ); - - // - - points = curve.getPoints( 4 ); - - assert.deepEqual( points, curve.points, "2nd: Returned points are identical to control points" ); - - } ); - - QUnit.test( "getLength/getLengths", ( assert ) => { - - var curve = _curve; - - var length = curve.getLength(); - var expectedLength = 28.876950901868135; - - assert.numEqual( length, expectedLength, "Correct length of curve" ); - - var expectedLengths = [ - 0.0, - Math.sqrt( 50 ), - Math.sqrt( 200 ), - Math.sqrt( 450 ), - Math.sqrt( 800 ) - ]; - - var lengths = curve.getLengths( 4 ); - - assert.deepEqual( lengths, expectedLengths, "Correct segment lengths" ); - - } ); - - QUnit.test( "getPointAt", ( assert ) => { - - var curve = _curve; - - assert.ok( curve.getPointAt( 0 ).equals( curve.points[ 0 ] ), "PointAt 0.0 correct" ); - assert.ok( curve.getPointAt( 1 ).equals( curve.points[ 4 ] ), "PointAt 1.0 correct" ); - - var pointAt = curve.getPointAt( 0.5 ); - assert.numEqual( pointAt.x, 0.0, "PointAt 0.5 x correct" ); - assert.numEqual( pointAt.y, 0.0, "PointAt 0.5 y correct" ); - - } ); - - QUnit.test( "getTangent", ( assert ) => { - - var curve = _curve; - - var expectedTangent = [ - new Vector2( 0.7068243340243188, 0.7073891155729485 ), // 0 - new Vector2( 0.7069654305325396, - 0.7072481035902046 ), // 0.5 - new Vector2( 0.7068243340245123, 0.7073891155727552 ) // 1 - ]; - - var tangents = [ - curve.getTangent( 0 ), - curve.getTangent( 0.5 ), - curve.getTangent( 1 ) - ]; - - tangents.forEach( function ( tangent, i ) { - - assert.numEqual( tangent.x, expectedTangent[ i ].x, "tangent[" + i + "].x" ); - assert.numEqual( tangent.y, expectedTangent[ i ].y, "tangent[" + i + "].y" ); - - } ); - - } ); - - QUnit.test( "getUtoTmapping", ( assert ) => { - - var curve = _curve; - - var start = curve.getUtoTmapping( 0, 0 ); - var end = curve.getUtoTmapping( 0, curve.getLength() ); - var middle = curve.getUtoTmapping( 0.5, 0 ); - - assert.strictEqual( start, 0, "getUtoTmapping( 0, 0 ) is the starting point" ); - assert.strictEqual( end, 1, "getUtoTmapping( 0, length ) is the ending point" ); - assert.numEqual( middle, 0.5, "getUtoTmapping( 0.5, 0 ) is the middle" ); - - } ); - - QUnit.test( "getSpacedPoints", ( assert ) => { - - var curve = _curve; - - var expectedPoints = [ - new Vector2( - 10, 0 ), - new Vector2( - 4.996509634683014, 4.999995128640857 ), - new Vector2( 0, 0 ), - new Vector2( 4.996509634683006, - 4.999995128640857 ), - new Vector2( 10, 0 ) - ]; - - var points = curve.getSpacedPoints( 4 ); - - assert.strictEqual( points.length, expectedPoints.length, "Correct number of points" ); - - points.forEach( function ( point, i ) { - - assert.numEqual( point.x, expectedPoints[ i ].x, "points[" + i + "].x" ); - assert.numEqual( point.y, expectedPoints[ i ].y, "points[" + i + "].y" ); - - } ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Extras', () => { - - QUnit.module( 'Objects', () => { - - QUnit.module.todo( 'ImmediateRenderObject', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isImmediateRenderObject", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author Anonymous - */ - /* global QUnit */ - - QUnit.module( 'Geometries', () => { - - QUnit.module.todo( 'BoxGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - width: 10, - height: 20, - depth: 30, - widthSegments: 2, - heightSegments: 3, - depthSegments: 4 - }; - - geometries = [ - new BoxGeometry(), - new BoxGeometry( parameters.width, parameters.height, parameters.depth ), - new BoxGeometry( parameters.width, parameters.height, parameters.depth, parameters.widthSegments, parameters.heightSegments, parameters.depthSegments ) - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - QUnit.module.todo( 'BoxBufferGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - width: 10, - height: 20, - depth: 30, - widthSegments: 2, - heightSegments: 3, - depthSegments: 4 - }; - - geometries = [ - new BoxBufferGeometry(), - new BoxBufferGeometry( parameters.width, parameters.height, parameters.depth ), - new BoxBufferGeometry( parameters.width, parameters.height, parameters.depth, parameters.widthSegments, parameters.heightSegments, parameters.depthSegments ) - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - } ); - - /** - * @author benaadams / https://twitter.com/ben_a_adams - * @author Mugen87 / https://github.com/Mugen87 - * @author hughes - */ - - function CircleGeometry( radius, segments, thetaStart, thetaLength ) { - - Geometry.call( this ); - - this.type = 'CircleGeometry'; - - this.parameters = { - radius: radius, - segments: segments, - thetaStart: thetaStart, - thetaLength: thetaLength - }; - - this.fromBufferGeometry( new CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) ); - this.mergeVertices(); - - } - - CircleGeometry.prototype = Object.create( Geometry.prototype ); - CircleGeometry.prototype.constructor = CircleGeometry; - - // CircleBufferGeometry - - function CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) { - - BufferGeometry.call( this ); - - this.type = 'CircleBufferGeometry'; - - this.parameters = { - radius: radius, - segments: segments, - thetaStart: thetaStart, - thetaLength: thetaLength - }; - - radius = radius || 1; - segments = segments !== undefined ? Math.max( 3, segments ) : 8; - - thetaStart = thetaStart !== undefined ? thetaStart : 0; - thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2; - - // buffers - - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; - - // helper variables - - var i, s; - var vertex = new Vector3(); - var uv = new Vector2(); - - // center point - - vertices.push( 0, 0, 0 ); - normals.push( 0, 0, 1 ); - uvs.push( 0.5, 0.5 ); - - for ( s = 0, i = 3; s <= segments; s ++, i += 3 ) { - - var segment = thetaStart + s / segments * thetaLength; - - // vertex - - vertex.x = radius * Math.cos( segment ); - vertex.y = radius * Math.sin( segment ); - - vertices.push( vertex.x, vertex.y, vertex.z ); - - // normal - - normals.push( 0, 0, 1 ); - - // uvs - - uv.x = ( vertices[ i ] / radius + 1 ) / 2; - uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2; - - uvs.push( uv.x, uv.y ); - - } - - // indices - - for ( i = 1; i <= segments; i ++ ) { - - indices.push( i, i + 1, 0 ); - - } - - // build geometry - - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - - } - - CircleBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - CircleBufferGeometry.prototype.constructor = CircleBufferGeometry; - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author Anonymous - */ - /* global QUnit */ - - QUnit.module( 'Geometries', () => { - - QUnit.module.todo( 'CircleGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - radius: 10, - segments: 20, - thetaStart: 0.1, - thetaLength: 0.2 - }; - - geometries = [ - new CircleGeometry(), - new CircleGeometry( parameters.radius ), - new CircleGeometry( parameters.radius, parameters.segments ), - new CircleGeometry( parameters.radius, parameters.segments, parameters.thetaStart ), - new CircleGeometry( parameters.radius, parameters.segments, parameters.thetaStart, parameters.thetaLength ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - QUnit.module.todo( 'CircleBufferGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - radius: 10, - segments: 20, - thetaStart: 0.1, - thetaLength: 0.2 - }; - - geometries = [ - new CircleBufferGeometry(), - new CircleBufferGeometry( parameters.radius ), - new CircleBufferGeometry( parameters.radius, parameters.segments ), - new CircleBufferGeometry( parameters.radius, parameters.segments, parameters.thetaStart ), - new CircleBufferGeometry( parameters.radius, parameters.segments, parameters.thetaStart, parameters.thetaLength ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ - - function CylinderGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { - - Geometry.call( this ); - - this.type = 'CylinderGeometry'; - - this.parameters = { - radiusTop: radiusTop, - radiusBottom: radiusBottom, - height: height, - radialSegments: radialSegments, - heightSegments: heightSegments, - openEnded: openEnded, - thetaStart: thetaStart, - thetaLength: thetaLength - }; - - this.fromBufferGeometry( new CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) ); - this.mergeVertices(); - - } - - CylinderGeometry.prototype = Object.create( Geometry.prototype ); - CylinderGeometry.prototype.constructor = CylinderGeometry; - - // CylinderBufferGeometry - - function CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { - - BufferGeometry.call( this ); - - this.type = 'CylinderBufferGeometry'; - - this.parameters = { - radiusTop: radiusTop, - radiusBottom: radiusBottom, - height: height, - radialSegments: radialSegments, - heightSegments: heightSegments, - openEnded: openEnded, - thetaStart: thetaStart, - thetaLength: thetaLength - }; - - var scope = this; - - radiusTop = radiusTop !== undefined ? radiusTop : 1; - radiusBottom = radiusBottom !== undefined ? radiusBottom : 1; - height = height || 1; - - radialSegments = Math.floor( radialSegments ) || 8; - heightSegments = Math.floor( heightSegments ) || 1; - - openEnded = openEnded !== undefined ? openEnded : false; - thetaStart = thetaStart !== undefined ? thetaStart : 0.0; - thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2; - - // buffers - - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; - - // helper variables - - var index = 0; - var indexArray = []; - var halfHeight = height / 2; - var groupStart = 0; - - // generate geometry - - generateTorso(); - - if ( openEnded === false ) { - - if ( radiusTop > 0 ) generateCap( true ); - if ( radiusBottom > 0 ) generateCap( false ); - - } - - // build geometry - - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - - function generateTorso() { - - var x, y; - var normal = new Vector3(); - var vertex = new Vector3(); - - var groupCount = 0; - - // this will be used to calculate the normal - var slope = ( radiusBottom - radiusTop ) / height; - - // generate vertices, normals and uvs - - for ( y = 0; y <= heightSegments; y ++ ) { - - var indexRow = []; - - var v = y / heightSegments; - - // calculate the radius of the current row - - var radius = v * ( radiusBottom - radiusTop ) + radiusTop; - - for ( x = 0; x <= radialSegments; x ++ ) { - - var u = x / radialSegments; - - var theta = u * thetaLength + thetaStart; - - var sinTheta = Math.sin( theta ); - var cosTheta = Math.cos( theta ); - - // vertex - - vertex.x = radius * sinTheta; - vertex.y = - v * height + halfHeight; - vertex.z = radius * cosTheta; - vertices.push( vertex.x, vertex.y, vertex.z ); - - // normal - - normal.set( sinTheta, slope, cosTheta ).normalize(); - normals.push( normal.x, normal.y, normal.z ); - - // uv - - uvs.push( u, 1 - v ); - - // save index of vertex in respective row - - indexRow.push( index ++ ); - - } - - // now save vertices of the row in our index array - - indexArray.push( indexRow ); - - } - - // generate indices - - for ( x = 0; x < radialSegments; x ++ ) { - - for ( y = 0; y < heightSegments; y ++ ) { - - // we use the index array to access the correct indices - - var a = indexArray[ y ][ x ]; - var b = indexArray[ y + 1 ][ x ]; - var c = indexArray[ y + 1 ][ x + 1 ]; - var d = indexArray[ y ][ x + 1 ]; - - // faces - - indices.push( a, b, d ); - indices.push( b, c, d ); - - // update group counter - - groupCount += 6; - - } - - } - - // add a group to the geometry. this will ensure multi material support - - scope.addGroup( groupStart, groupCount, 0 ); - - // calculate new start value for groups - - groupStart += groupCount; - - } - - function generateCap( top ) { - - var x, centerIndexStart, centerIndexEnd; - - var uv = new Vector2(); - var vertex = new Vector3(); - - var groupCount = 0; - - var radius = ( top === true ) ? radiusTop : radiusBottom; - var sign = ( top === true ) ? 1 : - 1; - - // save the index of the first center vertex - centerIndexStart = index; - - // first we generate the center vertex data of the cap. - // because the geometry needs one set of uvs per face, - // we must generate a center vertex per face/segment - - for ( x = 1; x <= radialSegments; x ++ ) { - - // vertex - - vertices.push( 0, halfHeight * sign, 0 ); - - // normal - - normals.push( 0, sign, 0 ); - - // uv - - uvs.push( 0.5, 0.5 ); - - // increase index - - index ++; - - } - - // save the index of the last center vertex - - centerIndexEnd = index; - - // now we generate the surrounding vertices, normals and uvs - - for ( x = 0; x <= radialSegments; x ++ ) { - - var u = x / radialSegments; - var theta = u * thetaLength + thetaStart; - - var cosTheta = Math.cos( theta ); - var sinTheta = Math.sin( theta ); - - // vertex - - vertex.x = radius * sinTheta; - vertex.y = halfHeight * sign; - vertex.z = radius * cosTheta; - vertices.push( vertex.x, vertex.y, vertex.z ); - - // normal - - normals.push( 0, sign, 0 ); - - // uv - - uv.x = ( cosTheta * 0.5 ) + 0.5; - uv.y = ( sinTheta * 0.5 * sign ) + 0.5; - uvs.push( uv.x, uv.y ); - - // increase index - - index ++; - - } - - // generate indices - - for ( x = 0; x < radialSegments; x ++ ) { - - var c = centerIndexStart + x; - var i = centerIndexEnd + x; - - if ( top === true ) { - - // face top - - indices.push( i, i + 1, c ); - - } else { - - // face bottom - - indices.push( i + 1, i, c ); - - } - - groupCount += 3; - - } - - // add a group to the geometry. this will ensure multi material support - - scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 ); - - // calculate new start value for groups - - groupStart += groupCount; - - } - - } - - CylinderBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - CylinderBufferGeometry.prototype.constructor = CylinderBufferGeometry; - - /** - * @author abelnation / http://github.com/abelnation - */ - - function ConeGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { - - CylinderGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ); - - this.type = 'ConeGeometry'; - - this.parameters = { - radius: radius, - height: height, - radialSegments: radialSegments, - heightSegments: heightSegments, - openEnded: openEnded, - thetaStart: thetaStart, - thetaLength: thetaLength - }; - - } - - ConeGeometry.prototype = Object.create( CylinderGeometry.prototype ); - ConeGeometry.prototype.constructor = ConeGeometry; - - // ConeBufferGeometry - - function ConeBufferGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { - - CylinderBufferGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ); - - this.type = 'ConeBufferGeometry'; - - this.parameters = { - radius: radius, - height: height, - radialSegments: radialSegments, - heightSegments: heightSegments, - openEnded: openEnded, - thetaStart: thetaStart, - thetaLength: thetaLength - }; - - } - - ConeBufferGeometry.prototype = Object.create( CylinderBufferGeometry.prototype ); - ConeBufferGeometry.prototype.constructor = ConeBufferGeometry; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Geometries', () => { - - QUnit.module.todo( 'ConeGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = {}; - - geometries = [ - new ConeGeometry() - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - QUnit.module.todo( 'ConeBufferGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = {}; - - geometries = [ - new ConeBufferGeometry() - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author Anonymous - */ - /* global QUnit */ - - QUnit.module( 'Geometries', () => { - - QUnit.module.todo( 'CylinderGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - radiusTop: 10, - radiusBottom: 20, - height: 30, - radialSegments: 20, - heightSegments: 30, - openEnded: true, - thetaStart: 0.1, - thetaLength: 2.0, - }; - - geometries = [ - new CylinderGeometry(), - new CylinderGeometry( parameters.radiusTop ), - new CylinderGeometry( parameters.radiusTop, parameters.radiusBottom ), - new CylinderGeometry( parameters.radiusTop, parameters.radiusBottom, parameters.height ), - new CylinderGeometry( parameters.radiusTop, parameters.radiusBottom, parameters.height, parameters.radialSegments ), - new CylinderGeometry( parameters.radiusTop, parameters.radiusBottom, parameters.height, parameters.radialSegments, parameters.heightSegments ), - new CylinderGeometry( parameters.radiusTop, parameters.radiusBottom, parameters.height, parameters.radialSegments, parameters.heightSegments, parameters.openEnded ), - new CylinderGeometry( parameters.radiusTop, parameters.radiusBottom, parameters.height, parameters.radialSegments, parameters.heightSegments, parameters.openEnded, parameters.thetaStart ), - new CylinderGeometry( parameters.radiusTop, parameters.radiusBottom, parameters.height, parameters.radialSegments, parameters.heightSegments, parameters.openEnded, parameters.thetaStart, parameters.thetaLength ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - QUnit.module.todo( 'CylinderBufferGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - radiusTop: 10, - radiusBottom: 20, - height: 30, - radialSegments: 20, - heightSegments: 30, - openEnded: true, - thetaStart: 0.1, - thetaLength: 2.0, - }; - - geometries = [ - new CylinderBufferGeometry(), - new CylinderBufferGeometry( parameters.radiusTop ), - new CylinderBufferGeometry( parameters.radiusTop, parameters.radiusBottom ), - new CylinderBufferGeometry( parameters.radiusTop, parameters.radiusBottom, parameters.height ), - new CylinderBufferGeometry( parameters.radiusTop, parameters.radiusBottom, parameters.height, parameters.radialSegments ), - new CylinderBufferGeometry( parameters.radiusTop, parameters.radiusBottom, parameters.height, parameters.radialSegments, parameters.heightSegments ), - new CylinderBufferGeometry( parameters.radiusTop, parameters.radiusBottom, parameters.height, parameters.radialSegments, parameters.heightSegments, parameters.openEnded ), - new CylinderBufferGeometry( parameters.radiusTop, parameters.radiusBottom, parameters.height, parameters.radialSegments, parameters.heightSegments, parameters.openEnded, parameters.thetaStart ), - new CylinderBufferGeometry( parameters.radiusTop, parameters.radiusBottom, parameters.height, parameters.radialSegments, parameters.heightSegments, parameters.openEnded, parameters.thetaStart, parameters.thetaLength ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author Anonymous - */ - /* global QUnit */ - - QUnit.module( 'Geometries', () => { - - QUnit.module.todo( 'CircleGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - radius: 10, - detail: undefined - }; - - geometries = [ - new DodecahedronGeometry(), - new DodecahedronGeometry( parameters.radius ), - new DodecahedronGeometry( parameters.radius, parameters.detail ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - QUnit.module.todo( 'CircleBufferGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - radius: 10, - detail: undefined - }; - - geometries = [ - new DodecahedronBufferGeometry(), - new DodecahedronBufferGeometry( parameters.radius ), - new DodecahedronBufferGeometry( parameters.radius, parameters.detail ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - } ); - - /** - * @author WestLangley / http://github.com/WestLangley - * @author Mugen87 / https://github.com/Mugen87 - */ - - function EdgesGeometry( geometry, thresholdAngle ) { - - BufferGeometry.call( this ); - - this.type = 'EdgesGeometry'; - - this.parameters = { - thresholdAngle: thresholdAngle - }; - - thresholdAngle = ( thresholdAngle !== undefined ) ? thresholdAngle : 1; - - // buffer - - var vertices = []; - - // helper variables - - var thresholdDot = Math.cos( _Math.DEG2RAD * thresholdAngle ); - var edge = [ 0, 0 ], edges = {}, edge1, edge2; - var key, keys = [ 'a', 'b', 'c' ]; - - // prepare source geometry - - var geometry2; - - if ( geometry.isBufferGeometry ) { - - geometry2 = new Geometry(); - geometry2.fromBufferGeometry( geometry ); - - } else { - - geometry2 = geometry.clone(); - - } - - geometry2.mergeVertices(); - geometry2.computeFaceNormals(); - - var sourceVertices = geometry2.vertices; - var faces = geometry2.faces; - - // now create a data structure where each entry represents an edge with its adjoining faces - - for ( var i = 0, l = faces.length; i < l; i ++ ) { - - var face = faces[ i ]; - - for ( var j = 0; j < 3; j ++ ) { - - edge1 = face[ keys[ j ] ]; - edge2 = face[ keys[ ( j + 1 ) % 3 ] ]; - edge[ 0 ] = Math.min( edge1, edge2 ); - edge[ 1 ] = Math.max( edge1, edge2 ); - - key = edge[ 0 ] + ',' + edge[ 1 ]; - - if ( edges[ key ] === undefined ) { - - edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ], face1: i, face2: undefined }; - - } else { - - edges[ key ].face2 = i; - - } - - } - - } - - // generate vertices - - for ( key in edges ) { - - var e = edges[ key ]; - - // an edge is only rendered if the angle (in degrees) between the face normals of the adjoining faces exceeds this value. default = 1 degree. - - if ( e.face2 === undefined || faces[ e.face1 ].normal.dot( faces[ e.face2 ].normal ) <= thresholdDot ) { - - var vertex = sourceVertices[ e.index1 ]; - vertices.push( vertex.x, vertex.y, vertex.z ); - - vertex = sourceVertices[ e.index2 ]; - vertices.push( vertex.x, vertex.y, vertex.z ); - - } - - } - - // build geometry - - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - - } - - EdgesGeometry.prototype = Object.create( BufferGeometry.prototype ); - EdgesGeometry.prototype.constructor = EdgesGeometry; - - function Scene() { - - Object3D.call( this ); - - this.type = 'Scene'; - - this.background = null; - this.fog = null; - this.overrideMaterial = null; - - this.autoUpdate = true; // checked by the renderer - - } - - Scene.prototype = Object.assign( Object.create( Object3D.prototype ), { - - constructor: Scene, - - copy: function ( source, recursive ) { - - Object3D.prototype.copy.call( this, source, recursive ); - - if ( source.background !== null ) this.background = source.background.clone(); - if ( source.fog !== null ) this.fog = source.fog.clone(); - if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone(); - - this.autoUpdate = source.autoUpdate; - this.matrixAutoUpdate = source.matrixAutoUpdate; - - return this; - - }, - - toJSON: function ( meta ) { - - var data = Object3D.prototype.toJSON.call( this, meta ); - - if ( this.background !== null ) data.object.background = this.background.toJSON( meta ); - if ( this.fog !== null ) data.object.fog = this.fog.toJSON(); - - return data; - - } - - } ); - - /** - * @author alteredq / http://alteredqualia.com/ - */ - - function DataTexture( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) { - - Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); - - this.image = { data: data, width: width, height: height }; - - this.magFilter = magFilter !== undefined ? magFilter : NearestFilter; - this.minFilter = minFilter !== undefined ? minFilter : NearestFilter; - - this.generateMipmaps = false; - this.flipY = false; - this.unpackAlignment = 1; - - } - - DataTexture.prototype = Object.create( Texture.prototype ); - DataTexture.prototype.constructor = DataTexture; - - DataTexture.prototype.isDataTexture = true; - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function CubeTexture( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) { - - images = images !== undefined ? images : []; - mapping = mapping !== undefined ? mapping : CubeReflectionMapping; - - Texture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); - - this.flipY = false; - - } - - CubeTexture.prototype = Object.create( Texture.prototype ); - CubeTexture.prototype.constructor = CubeTexture; - - CubeTexture.prototype.isCubeTexture = true; - - Object.defineProperty( CubeTexture.prototype, 'images', { - - get: function () { - - return this.image; - - }, - - set: function ( value ) { - - this.image = value; - - } - - } ); - - /** - * @author tschw - * - * Uniforms of a program. - * Those form a tree structure with a special top-level container for the root, - * which you get by calling 'new WebGLUniforms( gl, program, renderer )'. - * - * - * Properties of inner nodes including the top-level container: - * - * .seq - array of nested uniforms - * .map - nested uniforms by name - * - * - * Methods of all nodes except the top-level container: - * - * .setValue( gl, value, [renderer] ) - * - * uploads a uniform value(s) - * the 'renderer' parameter is needed for sampler uniforms - * - * - * Static methods of the top-level container (renderer factorizations): - * - * .upload( gl, seq, values, renderer ) - * - * sets uniforms in 'seq' to 'values[id].value' - * - * .seqWithValue( seq, values ) : filteredSeq - * - * filters 'seq' entries with corresponding entry in values - * - * - * Methods of the top-level container (renderer factorizations): - * - * .setValue( gl, name, value ) - * - * sets uniform with name 'name' to 'value' - * - * .set( gl, obj, prop ) - * - * sets uniform from object and property with same name than uniform - * - * .setOptional( gl, obj, prop ) - * - * like .set for an optional property of the object - * - */ - - var emptyTexture = new Texture(); - var emptyCubeTexture = new CubeTexture(); - - // --- Base for inner nodes (including the root) --- - - function UniformContainer() { - - this.seq = []; - this.map = {}; - - } - - // --- Utilities --- - - // Array Caches (provide typed arrays for temporary by size) - - var arrayCacheF32 = []; - var arrayCacheI32 = []; - - // Float32Array caches used for uploading Matrix uniforms - - var mat4array = new Float32Array( 16 ); - var mat3array = new Float32Array( 9 ); - - // Flattening for arrays of vectors and matrices - - function flatten( array, nBlocks, blockSize ) { - - var firstElem = array[ 0 ]; - - if ( firstElem <= 0 || firstElem > 0 ) return array; - // unoptimized: ! isNaN( firstElem ) - // see http://jacksondunstan.com/articles/983 - - var n = nBlocks * blockSize, - r = arrayCacheF32[ n ]; - - if ( r === undefined ) { - - r = new Float32Array( n ); - arrayCacheF32[ n ] = r; - - } - - if ( nBlocks !== 0 ) { - - firstElem.toArray( r, 0 ); - - for ( var i = 1, offset = 0; i !== nBlocks; ++ i ) { - - offset += blockSize; - array[ i ].toArray( r, offset ); - - } - - } - - return r; - - } - - // Texture unit allocation - - function allocTexUnits( renderer, n ) { - - var r = arrayCacheI32[ n ]; - - if ( r === undefined ) { - - r = new Int32Array( n ); - arrayCacheI32[ n ] = r; - - } - - for ( var i = 0; i !== n; ++ i ) - r[ i ] = renderer.allocTextureUnit(); - - return r; - - } - - // --- Setters --- - - // Note: Defining these methods externally, because they come in a bunch - // and this way their names minify. - - // Single scalar - - function setValue1f( gl, v ) { - - gl.uniform1f( this.addr, v ); - - } - - function setValue1i( gl, v ) { - - gl.uniform1i( this.addr, v ); - - } - - // Single float vector (from flat array or THREE.VectorN) - - function setValue2fv( gl, v ) { - - if ( v.x === undefined ) { - - gl.uniform2fv( this.addr, v ); - - } else { - - gl.uniform2f( this.addr, v.x, v.y ); - - } - - } - - function setValue3fv( gl, v ) { - - if ( v.x !== undefined ) { - - gl.uniform3f( this.addr, v.x, v.y, v.z ); - - } else if ( v.r !== undefined ) { - - gl.uniform3f( this.addr, v.r, v.g, v.b ); - - } else { - - gl.uniform3fv( this.addr, v ); - - } - - } - - function setValue4fv( gl, v ) { - - if ( v.x === undefined ) { - - gl.uniform4fv( this.addr, v ); - - } else { - - gl.uniform4f( this.addr, v.x, v.y, v.z, v.w ); - - } - - } - - // Single matrix (from flat array or MatrixN) - - function setValue2fm( gl, v ) { - - gl.uniformMatrix2fv( this.addr, false, v.elements || v ); - - } - - function setValue3fm( gl, v ) { - - if ( v.elements === undefined ) { - - gl.uniformMatrix3fv( this.addr, false, v ); - - } else { - - mat3array.set( v.elements ); - gl.uniformMatrix3fv( this.addr, false, mat3array ); - - } - - } - - function setValue4fm( gl, v ) { - - if ( v.elements === undefined ) { - - gl.uniformMatrix4fv( this.addr, false, v ); - - } else { - - mat4array.set( v.elements ); - gl.uniformMatrix4fv( this.addr, false, mat4array ); - - } - - } - - // Single texture (2D / Cube) - - function setValueT1( gl, v, renderer ) { - - var unit = renderer.allocTextureUnit(); - gl.uniform1i( this.addr, unit ); - renderer.setTexture2D( v || emptyTexture, unit ); - - } - - function setValueT6( gl, v, renderer ) { - - var unit = renderer.allocTextureUnit(); - gl.uniform1i( this.addr, unit ); - renderer.setTextureCube( v || emptyCubeTexture, unit ); - - } - - // Integer / Boolean vectors or arrays thereof (always flat arrays) - - function setValue2iv( gl, v ) { - - gl.uniform2iv( this.addr, v ); - - } - - function setValue3iv( gl, v ) { - - gl.uniform3iv( this.addr, v ); - - } - - function setValue4iv( gl, v ) { - - gl.uniform4iv( this.addr, v ); - - } - - // Helper to pick the right setter for the singular case - - function getSingularSetter( type ) { - - switch ( type ) { - - case 0x1406: return setValue1f; // FLOAT - case 0x8b50: return setValue2fv; // _VEC2 - case 0x8b51: return setValue3fv; // _VEC3 - case 0x8b52: return setValue4fv; // _VEC4 - - case 0x8b5a: return setValue2fm; // _MAT2 - case 0x8b5b: return setValue3fm; // _MAT3 - case 0x8b5c: return setValue4fm; // _MAT4 - - case 0x8b5e: case 0x8d66: return setValueT1; // SAMPLER_2D, SAMPLER_EXTERNAL_OES - case 0x8b60: return setValueT6; // SAMPLER_CUBE - - case 0x1404: case 0x8b56: return setValue1i; // INT, BOOL - case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2 - case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3 - case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4 - - } - - } - - // Array of scalars - - function setValue1fv( gl, v ) { - - gl.uniform1fv( this.addr, v ); - - } - function setValue1iv( gl, v ) { - - gl.uniform1iv( this.addr, v ); - - } - - // Array of vectors (flat or from THREE classes) - - function setValueV2a( gl, v ) { - - gl.uniform2fv( this.addr, flatten( v, this.size, 2 ) ); - - } - - function setValueV3a( gl, v ) { - - gl.uniform3fv( this.addr, flatten( v, this.size, 3 ) ); - - } - - function setValueV4a( gl, v ) { - - gl.uniform4fv( this.addr, flatten( v, this.size, 4 ) ); - - } - - // Array of matrices (flat or from THREE clases) - - function setValueM2a( gl, v ) { - - gl.uniformMatrix2fv( this.addr, false, flatten( v, this.size, 4 ) ); - - } - - function setValueM3a( gl, v ) { - - gl.uniformMatrix3fv( this.addr, false, flatten( v, this.size, 9 ) ); - - } - - function setValueM4a( gl, v ) { - - gl.uniformMatrix4fv( this.addr, false, flatten( v, this.size, 16 ) ); - - } - - // Array of textures (2D / Cube) - - function setValueT1a( gl, v, renderer ) { - - var n = v.length, - units = allocTexUnits( renderer, n ); - - gl.uniform1iv( this.addr, units ); - - for ( var i = 0; i !== n; ++ i ) { - - renderer.setTexture2D( v[ i ] || emptyTexture, units[ i ] ); - - } - - } - - function setValueT6a( gl, v, renderer ) { - - var n = v.length, - units = allocTexUnits( renderer, n ); - - gl.uniform1iv( this.addr, units ); - - for ( var i = 0; i !== n; ++ i ) { - - renderer.setTextureCube( v[ i ] || emptyCubeTexture, units[ i ] ); - - } - - } - - // Helper to pick the right setter for a pure (bottom-level) array - - function getPureArraySetter( type ) { - - switch ( type ) { - - case 0x1406: return setValue1fv; // FLOAT - case 0x8b50: return setValueV2a; // _VEC2 - case 0x8b51: return setValueV3a; // _VEC3 - case 0x8b52: return setValueV4a; // _VEC4 - - case 0x8b5a: return setValueM2a; // _MAT2 - case 0x8b5b: return setValueM3a; // _MAT3 - case 0x8b5c: return setValueM4a; // _MAT4 - - case 0x8b5e: return setValueT1a; // SAMPLER_2D - case 0x8b60: return setValueT6a; // SAMPLER_CUBE - - case 0x1404: case 0x8b56: return setValue1iv; // INT, BOOL - case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2 - case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3 - case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4 - - } - - } - - // --- Uniform Classes --- - - function SingleUniform( id, activeInfo, addr ) { - - this.id = id; - this.addr = addr; - this.setValue = getSingularSetter( activeInfo.type ); - - // this.path = activeInfo.name; // DEBUG - - } - - function PureArrayUniform( id, activeInfo, addr ) { - - this.id = id; - this.addr = addr; - this.size = activeInfo.size; - this.setValue = getPureArraySetter( activeInfo.type ); - - // this.path = activeInfo.name; // DEBUG - - } - - function StructuredUniform( id ) { - - this.id = id; - - UniformContainer.call( this ); // mix-in - - } - - StructuredUniform.prototype.setValue = function ( gl, value ) { - - // Note: Don't need an extra 'renderer' parameter, since samplers - // are not allowed in structured uniforms. - - var seq = this.seq; - - for ( var i = 0, n = seq.length; i !== n; ++ i ) { - - var u = seq[ i ]; - u.setValue( gl, value[ u.id ] ); - - } - - }; - - // --- Top-level --- - - // Parser - builds up the property tree from the path strings - - var RePathPart = /([\w\d_]+)(\])?(\[|\.)?/g; - - // extracts - // - the identifier (member name or array index) - // - followed by an optional right bracket (found when array index) - // - followed by an optional left bracket or dot (type of subscript) - // - // Note: These portions can be read in a non-overlapping fashion and - // allow straightforward parsing of the hierarchy that WebGL encodes - // in the uniform names. - - function addUniform( container, uniformObject ) { - - container.seq.push( uniformObject ); - container.map[ uniformObject.id ] = uniformObject; - - } - - function parseUniform( activeInfo, addr, container ) { - - var path = activeInfo.name, - pathLength = path.length; - - // reset RegExp object, because of the early exit of a previous run - RePathPart.lastIndex = 0; - - for ( ; ; ) { - - var match = RePathPart.exec( path ), - matchEnd = RePathPart.lastIndex, - - id = match[ 1 ], - idIsIndex = match[ 2 ] === ']', - subscript = match[ 3 ]; - - if ( idIsIndex ) id = id | 0; // convert to integer - - if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) { - - // bare name or "pure" bottom-level array "[0]" suffix - - addUniform( container, subscript === undefined ? - new SingleUniform( id, activeInfo, addr ) : - new PureArrayUniform( id, activeInfo, addr ) ); - - break; - - } else { - - // step into inner node / create it in case it doesn't exist - - var map = container.map, next = map[ id ]; - - if ( next === undefined ) { - - next = new StructuredUniform( id ); - addUniform( container, next ); - - } - - container = next; - - } - - } - - } - - // Root Container - - function WebGLUniforms( gl, program, renderer ) { - - UniformContainer.call( this ); - - this.renderer = renderer; - - var n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS ); - - for ( var i = 0; i < n; ++ i ) { - - var info = gl.getActiveUniform( program, i ), - path = info.name, - addr = gl.getUniformLocation( program, path ); - - parseUniform( info, addr, this ); - - } - - } - - WebGLUniforms.prototype.setValue = function ( gl, name, value ) { - - var u = this.map[ name ]; - - if ( u !== undefined ) u.setValue( gl, value, this.renderer ); - - }; - - WebGLUniforms.prototype.setOptional = function ( gl, object, name ) { - - var v = object[ name ]; - - if ( v !== undefined ) this.setValue( gl, name, v ); - - }; - - - // Static interface - - WebGLUniforms.upload = function ( gl, seq, values, renderer ) { - - for ( var i = 0, n = seq.length; i !== n; ++ i ) { - - var u = seq[ i ], - v = values[ u.id ]; - - if ( v.needsUpdate !== false ) { - - // note: always updating when .needsUpdate is undefined - u.setValue( gl, v.value, renderer ); - - } - - } - - }; - - WebGLUniforms.seqWithValue = function ( seq, values ) { - - var r = []; - - for ( var i = 0, n = seq.length; i !== n; ++ i ) { - - var u = seq[ i ]; - if ( u.id in values ) r.push( u ); - - } - - return r; - - }; - - var UniformsLib = { - - common: { - - diffuse: { value: new Color( 0xeeeeee ) }, - opacity: { value: 1.0 }, - - map: { value: null }, - uvTransform: { value: new Matrix3() }, - - alphaMap: { value: null }, - - }, - - specularmap: { - - specularMap: { value: null }, - - }, - - envmap: { - - envMap: { value: null }, - flipEnvMap: { value: - 1 }, - reflectivity: { value: 1.0 }, - refractionRatio: { value: 0.98 } - - }, - - aomap: { - - aoMap: { value: null }, - aoMapIntensity: { value: 1 } - - }, - - lightmap: { - - lightMap: { value: null }, - lightMapIntensity: { value: 1 } - - }, - - emissivemap: { - - emissiveMap: { value: null } - - }, - - bumpmap: { - - bumpMap: { value: null }, - bumpScale: { value: 1 } - - }, - - normalmap: { - - normalMap: { value: null }, - normalScale: { value: new Vector2( 1, 1 ) } - - }, - - displacementmap: { - - displacementMap: { value: null }, - displacementScale: { value: 1 }, - displacementBias: { value: 0 } - - }, - - roughnessmap: { - - roughnessMap: { value: null } - - }, - - metalnessmap: { - - metalnessMap: { value: null } - - }, - - gradientmap: { - - gradientMap: { value: null } - - }, - - fog: { - - fogDensity: { value: 0.00025 }, - fogNear: { value: 1 }, - fogFar: { value: 2000 }, - fogColor: { value: new Color( 0xffffff ) } - - }, - - lights: { - - ambientLightColor: { value: [] }, - - directionalLights: { value: [], properties: { - direction: {}, - color: {}, - - shadow: {}, - shadowBias: {}, - shadowRadius: {}, - shadowMapSize: {} - } }, - - directionalShadowMap: { value: [] }, - directionalShadowMatrix: { value: [] }, - - spotLights: { value: [], properties: { - color: {}, - position: {}, - direction: {}, - distance: {}, - coneCos: {}, - penumbraCos: {}, - decay: {}, - - shadow: {}, - shadowBias: {}, - shadowRadius: {}, - shadowMapSize: {} - } }, - - spotShadowMap: { value: [] }, - spotShadowMatrix: { value: [] }, - - pointLights: { value: [], properties: { - color: {}, - position: {}, - decay: {}, - distance: {}, - - shadow: {}, - shadowBias: {}, - shadowRadius: {}, - shadowMapSize: {}, - shadowCameraNear: {}, - shadowCameraFar: {} - } }, - - pointShadowMap: { value: [] }, - pointShadowMatrix: { value: [] }, - - hemisphereLights: { value: [], properties: { - direction: {}, - skyColor: {}, - groundColor: {} - } }, - - // TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src - rectAreaLights: { value: [], properties: { - color: {}, - position: {}, - width: {}, - height: {} - } } - - }, - - points: { - - diffuse: { value: new Color( 0xeeeeee ) }, - opacity: { value: 1.0 }, - size: { value: 1.0 }, - scale: { value: 1.0 }, - map: { value: null }, - uvTransform: { value: new Matrix3() } - - } - - }; - - var alphamap_fragment = "#ifdef USE_ALPHAMAP\r\n\r\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\r\n\r\n#endif\r\n"; - - var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\r\n\r\n\tuniform sampler2D alphaMap;\r\n\r\n#endif\r\n"; - - var alphatest_fragment = "#ifdef ALPHATEST\r\n\r\n\tif ( diffuseColor.a < ALPHATEST ) discard;\r\n\r\n#endif\r\n"; - - var aomap_fragment = "#ifdef USE_AOMAP\r\n\r\n\t// reads channel R, compatible with a combined OcclusionRoughnessMetallic (RGB) texture\r\n\tfloat ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\r\n\r\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\r\n\r\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL )\r\n\r\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\r\n\r\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.specularRoughness );\r\n\r\n\t#endif\r\n\r\n#endif\r\n"; - - var aomap_pars_fragment = "#ifdef USE_AOMAP\r\n\r\n\tuniform sampler2D aoMap;\r\n\tuniform float aoMapIntensity;\r\n\r\n#endif"; - - var begin_vertex = "\r\nvec3 transformed = vec3( position );\r\n"; - - var beginnormal_vertex = "\r\nvec3 objectNormal = vec3( normal );\r\n"; - - var bsdfs = "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\r\n\r\n\tif( decayExponent > 0.0 ) {\r\n\r\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\r\n\r\n\t\t// based upon Frostbite 3 Moving to Physically-based Rendering\r\n\t\t// page 32, equation 26: E[window1]\r\n\t\t// https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf\r\n\t\t// this is intended to be used on spot and point lights who are represented as luminous intensity\r\n\t\t// but who must be converted to luminous irradiance for surface lighting calculation\r\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\r\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\r\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\r\n\r\n#else\r\n\r\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\r\n\r\n#endif\r\n\r\n\t}\r\n\r\n\treturn 1.0;\r\n\r\n}\r\n\r\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\r\n\r\n\treturn RECIPROCAL_PI * diffuseColor;\r\n\r\n} // validated\r\n\r\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\r\n\r\n\t// Original approximation by Christophe Schlick '94\r\n\t// float fresnel = pow( 1.0 - dotLH, 5.0 );\r\n\r\n\t// Optimized variant (presented by Epic at SIGGRAPH '13)\r\n\t// https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf\r\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\r\n\r\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\r\n\r\n} // validated\r\n\r\n// Microfacet Models for Refraction through Rough Surfaces - equation (34)\r\n// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html\r\n// alpha is \"roughness squared\" in Disney’s reparameterization\r\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\r\n\r\n\t// geometry term (normalized) = G(l)â‹…G(v) / 4(nâ‹…l)(nâ‹…v)\r\n\t// also see #12151\r\n\r\n\tfloat a2 = pow2( alpha );\r\n\r\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\r\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\r\n\r\n\treturn 1.0 / ( gl * gv );\r\n\r\n} // validated\r\n\r\n// Moving Frostbite to Physically Based Rendering 3.0 - page 12, listing 2\r\n// https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf\r\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\r\n\r\n\tfloat a2 = pow2( alpha );\r\n\r\n\t// dotNL and dotNV are explicitly swapped. This is not a mistake.\r\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\r\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\r\n\r\n\treturn 0.5 / max( gv + gl, EPSILON );\r\n\r\n}\r\n\r\n// Microfacet Models for Refraction through Rough Surfaces - equation (33)\r\n// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html\r\n// alpha is \"roughness squared\" in Disney’s reparameterization\r\nfloat D_GGX( const in float alpha, const in float dotNH ) {\r\n\r\n\tfloat a2 = pow2( alpha );\r\n\r\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0; // avoid alpha = 0 with dotNH = 1\r\n\r\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\r\n\r\n}\r\n\r\n// GGX Distribution, Schlick Fresnel, GGX-Smith Visibility\r\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\r\n\r\n\tfloat alpha = pow2( roughness ); // UE4's roughness\r\n\r\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\r\n\r\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\r\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\r\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\r\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\r\n\r\n\tvec3 F = F_Schlick( specularColor, dotLH );\r\n\r\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\r\n\r\n\tfloat D = D_GGX( alpha, dotNH );\r\n\r\n\treturn F * ( G * D );\r\n\r\n} // validated\r\n\r\n// Rect Area Light\r\n\r\n// Area light computation code adapted from:\r\n// Real-Time Polygonal-Light Shading with Linearly Transformed Cosines\r\n// By: Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt\r\n// https://drive.google.com/file/d/0BzvWIdpUpRx_d09ndGVjNVJzZjA/view\r\n// https://eheitzresearch.wordpress.com/415-2/\r\n// http://blog.selfshadow.com/sandbox/ltc.html\r\n\r\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\r\n\r\n\tconst float LUT_SIZE = 64.0;\r\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\r\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\r\n\r\n\tfloat theta = acos( dot( N, V ) );\r\n\r\n\t// Parameterization of texture:\r\n\t// sqrt(roughness) -> [0,1]\r\n\t// theta -> [0, PI/2]\r\n\tvec2 uv = vec2(\r\n\t\tsqrt( saturate( roughness ) ),\r\n\t\tsaturate( theta / ( 0.5 * PI ) ) );\r\n\r\n\t// Ensure we don't have nonlinearities at the look-up table's edges\r\n\t// see: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter24.html\r\n\t// \"Shader Analysis\" section\r\n\tuv = uv * LUT_SCALE + LUT_BIAS;\r\n\r\n\treturn uv;\r\n\r\n}\r\n\r\n// Real-Time Area Lighting: a Journey from Research to Production\r\n// By: Stephen Hill & Eric Heitz\r\n// http://advances.realtimerendering.com/s2016/s2016_ltc_rnd.pdf\r\n// An approximation for the form factor of a clipped rectangle.\r\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\r\n\r\n\tfloat l = length( f );\r\n\r\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\r\n\r\n}\r\n\r\n// Real-Time Polygonal-Light Shading with Linearly Transformed Cosines\r\n// also Real-Time Area Lighting: a Journey from Research to Production\r\n// http://advances.realtimerendering.com/s2016/s2016_ltc_rnd.pdf\r\n// Normalization by 2*PI is incorporated in this function itself.\r\n// theta/sin(theta) is approximated by rational polynomial\r\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\r\n\r\n\tfloat x = dot( v1, v2 );\r\n\r\n\tfloat y = abs( x );\r\n\tfloat a = 0.86267 + (0.49788 + 0.01436 * y ) * y;\r\n\tfloat b = 3.45068 + (4.18814 + y) * y;\r\n\tfloat v = a / b;\r\n\r\n\tfloat theta_sintheta = (x > 0.0) ? v : 0.5 * inversesqrt( 1.0 - x * x ) - v;\r\n\r\n\treturn cross( v1, v2 ) * theta_sintheta;\r\n\r\n}\r\n\r\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\r\n\r\n\t// bail if point is on back side of plane of light\r\n\t// assumes ccw winding order of light vertices\r\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\r\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\r\n\tvec3 lightNormal = cross( v1, v2 );\r\n\r\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\r\n\r\n\t// construct orthonormal basis around N\r\n\tvec3 T1, T2;\r\n\tT1 = normalize( V - N * dot( V, N ) );\r\n\tT2 = - cross( N, T1 ); // negated from paper; possibly due to a different assumed handedness of world coordinate system\r\n\r\n\t// compute transform\r\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\r\n\r\n\t// transform rect\r\n\tvec3 coords[ 4 ];\r\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\r\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\r\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\r\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\r\n\r\n\t// project rect onto sphere\r\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\r\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\r\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\r\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\r\n\r\n\t// calculate vector form factor\r\n\tvec3 vectorFormFactor = vec3( 0.0 );\r\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\r\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\r\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\r\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\r\n\r\n\t// adjust for horizon clipping\r\n\tvec3 result = vec3( LTC_ClippedSphereFormFactor( vectorFormFactor ) );\r\n\r\n\treturn result;\r\n\r\n}\r\n\r\n// End Rect Area Light\r\n\r\n// ref: https://www.unrealengine.com/blog/physically-based-shading-on-mobile - environmentBRDF for GGX on mobile\r\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\r\n\r\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\r\n\r\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\r\n\r\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\r\n\r\n\tvec4 r = roughness * c0 + c1;\r\n\r\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\r\n\r\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\r\n\r\n\treturn specularColor * AB.x + AB.y;\r\n\r\n} // validated\r\n\r\n\r\nfloat G_BlinnPhong_Implicit( ) {\r\n\r\n\t// geometry term is (n dot l)(n dot v) / 4(n dot l)(n dot v)\r\n\treturn 0.25;\r\n\r\n}\r\n\r\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\r\n\r\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\r\n\r\n}\r\n\r\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\r\n\r\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\r\n\r\n\t//float dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\r\n\t//float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\r\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\r\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\r\n\r\n\tvec3 F = F_Schlick( specularColor, dotLH );\r\n\r\n\tfloat G = G_BlinnPhong_Implicit( );\r\n\r\n\tfloat D = D_BlinnPhong( shininess, dotNH );\r\n\r\n\treturn F * ( G * D );\r\n\r\n} // validated\r\n\r\n// source: http://simonstechblog.blogspot.ca/2011/12/microfacet-brdf.html\r\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\r\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\r\n}\r\n\r\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\r\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\r\n}\r\n"; - - var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\r\n\r\n\tuniform sampler2D bumpMap;\r\n\tuniform float bumpScale;\r\n\r\n\t// Derivative maps - bump mapping unparametrized surfaces by Morten Mikkelsen\r\n\t// http://mmikkelsen3d.blogspot.sk/2011/07/derivative-maps.html\r\n\r\n\t// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)\r\n\r\n\tvec2 dHdxy_fwd() {\r\n\r\n\t\tvec2 dSTdx = dFdx( vUv );\r\n\t\tvec2 dSTdy = dFdy( vUv );\r\n\r\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\r\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\r\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\r\n\r\n\t\treturn vec2( dBx, dBy );\r\n\r\n\t}\r\n\r\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\r\n\r\n\t\t// Workaround for Adreno 3XX dFd*( vec3 ) bug. See #9988\r\n\r\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\r\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\r\n\t\tvec3 vN = surf_norm;\t\t// normalized\r\n\r\n\t\tvec3 R1 = cross( vSigmaY, vN );\r\n\t\tvec3 R2 = cross( vN, vSigmaX );\r\n\r\n\t\tfloat fDet = dot( vSigmaX, R1 );\r\n\r\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\r\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\r\n\r\n\t}\r\n\r\n#endif\r\n"; - - var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\r\n\r\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; ++ i ) {\r\n\r\n\t\tvec4 plane = clippingPlanes[ i ];\r\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\r\n\r\n\t}\r\n\t\t\r\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\r\n\r\n\t\tbool clipped = true;\r\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; ++ i ) {\r\n\t\t\tvec4 plane = clippingPlanes[ i ];\r\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\r\n\t\t}\r\n\r\n\t\tif ( clipped ) discard;\r\n\t\r\n\t#endif\r\n\r\n#endif\r\n"; - - var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\r\n\r\n\t#if ! defined( PHYSICAL ) && ! defined( PHONG )\r\n\t\tvarying vec3 vViewPosition;\r\n\t#endif\r\n\r\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\r\n\r\n#endif\r\n"; - - var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\r\n\tvarying vec3 vViewPosition;\r\n#endif\r\n"; - - var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\r\n\tvViewPosition = - mvPosition.xyz;\r\n#endif\r\n\r\n"; - - var color_fragment = "#ifdef USE_COLOR\r\n\r\n\tdiffuseColor.rgb *= vColor;\r\n\r\n#endif"; - - var color_pars_fragment = "#ifdef USE_COLOR\r\n\r\n\tvarying vec3 vColor;\r\n\r\n#endif\r\n"; - - var color_pars_vertex = "#ifdef USE_COLOR\r\n\r\n\tvarying vec3 vColor;\r\n\r\n#endif"; - - var color_vertex = "#ifdef USE_COLOR\r\n\r\n\tvColor.xyz = color.xyz;\r\n\r\n#endif"; - - var common = "#define PI 3.14159265359\r\n#define PI2 6.28318530718\r\n#define PI_HALF 1.5707963267949\r\n#define RECIPROCAL_PI 0.31830988618\r\n#define RECIPROCAL_PI2 0.15915494\r\n#define LOG2 1.442695\r\n#define EPSILON 1e-6\r\n\r\n#define saturate(a) clamp( a, 0.0, 1.0 )\r\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\r\n\r\nfloat pow2( const in float x ) { return x*x; }\r\nfloat pow3( const in float x ) { return x*x*x; }\r\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\r\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\r\n// expects values in the range of [0,1]x[0,1], returns values in the [0,1] range.\r\n// do not collapse into a single function per: http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/\r\nhighp float rand( const in vec2 uv ) {\r\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\r\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\r\n\treturn fract(sin(sn) * c);\r\n}\r\n\r\nstruct IncidentLight {\r\n\tvec3 color;\r\n\tvec3 direction;\r\n\tbool visible;\r\n};\r\n\r\nstruct ReflectedLight {\r\n\tvec3 directDiffuse;\r\n\tvec3 directSpecular;\r\n\tvec3 indirectDiffuse;\r\n\tvec3 indirectSpecular;\r\n};\r\n\r\nstruct GeometricContext {\r\n\tvec3 position;\r\n\tvec3 normal;\r\n\tvec3 viewDir;\r\n};\r\n\r\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\r\n\r\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\r\n\r\n}\r\n\r\n// http://en.wikibooks.org/wiki/GLSL_Programming/Applying_Matrix_Transformations\r\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\r\n\r\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\r\n\r\n}\r\n\r\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\r\n\r\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\r\n\r\n\treturn - distance * planeNormal + point;\r\n\r\n}\r\n\r\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\r\n\r\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\r\n\r\n}\r\n\r\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\r\n\r\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\r\n\r\n}\r\n\r\nmat3 transposeMat3( const in mat3 m ) {\r\n\r\n\tmat3 tmp;\r\n\r\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\r\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\r\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\r\n\r\n\treturn tmp;\r\n\r\n}\r\n\r\n// https://en.wikipedia.org/wiki/Relative_luminance\r\nfloat linearToRelativeLuminance( const in vec3 color ) {\r\n\r\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\r\n\r\n\treturn dot( weights, color.rgb );\r\n\r\n}\r\n"; - - var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\r\n\r\n#define cubeUV_textureSize (1024.0)\r\n\r\nint getFaceFromDirection(vec3 direction) {\r\n\tvec3 absDirection = abs(direction);\r\n\tint face = -1;\r\n\tif( absDirection.x > absDirection.z ) {\r\n\t\tif(absDirection.x > absDirection.y )\r\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\r\n\t\telse\r\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\r\n\t}\r\n\telse {\r\n\t\tif(absDirection.z > absDirection.y )\r\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\r\n\t\telse\r\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\r\n\t}\r\n\treturn face;\r\n}\r\n#define cubeUV_maxLods1 (log2(cubeUV_textureSize*0.25) - 1.0)\r\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\r\n\r\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\r\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\r\n\tfloat dxRoughness = dFdx(roughness);\r\n\tfloat dyRoughness = dFdy(roughness);\r\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\r\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\r\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\r\n\t// Clamp the value to the max mip level counts. hard coded to 6 mips\r\n\td = clamp(d, 1.0, cubeUV_rangeClamp);\r\n\tfloat mipLevel = 0.5 * log2(d);\r\n\treturn vec2(floor(mipLevel), fract(mipLevel));\r\n}\r\n\r\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\r\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\r\n\r\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\r\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\r\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\r\n\r\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\r\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\r\n\t// float powScale = exp2(roughnessLevel + mipLevel);\r\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\r\n\t// float scale = 1.0 / exp2(roughnessLevel + 2.0 + mipLevel);\r\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\r\n\t// float mipOffset = 0.75*(1.0 - 1.0/exp2(mipLevel))/exp2(roughnessLevel);\r\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\r\n\r\n\tbool bRes = mipLevel == 0.0;\r\n\tscale = bRes && (scale < a) ? a : scale;\r\n\r\n\tvec3 r;\r\n\tvec2 offset;\r\n\tint face = getFaceFromDirection(direction);\r\n\r\n\tfloat rcpPowScale = 1.0 / powScale;\r\n\r\n\tif( face == 0) {\r\n\t\tr = vec3(direction.x, -direction.z, direction.y);\r\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\r\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\r\n\t}\r\n\telse if( face == 1) {\r\n\t\tr = vec3(direction.y, direction.x, direction.z);\r\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\r\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\r\n\t}\r\n\telse if( face == 2) {\r\n\t\tr = vec3(direction.z, direction.x, direction.y);\r\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\r\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\r\n\t}\r\n\telse if( face == 3) {\r\n\t\tr = vec3(direction.x, direction.z, direction.y);\r\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\r\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\r\n\t}\r\n\telse if( face == 4) {\r\n\t\tr = vec3(direction.y, direction.x, -direction.z);\r\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\r\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\r\n\t}\r\n\telse {\r\n\t\tr = vec3(direction.z, -direction.x, direction.y);\r\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\r\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\r\n\t}\r\n\tr = normalize(r);\r\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\r\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\r\n\tvec2 base = offset + vec2( texelOffset );\r\n\treturn base + s * ( scale - 2.0 * texelOffset );\r\n}\r\n\r\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\r\n\r\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\r\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\r\n\tfloat r1 = floor(roughnessVal);\r\n\tfloat r2 = r1 + 1.0;\r\n\tfloat t = fract(roughnessVal);\r\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\r\n\tfloat s = mipInfo.y;\r\n\tfloat level0 = mipInfo.x;\r\n\tfloat level1 = level0 + 1.0;\r\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\r\n\r\n\t// round to nearest mipmap if we are not interpolating.\r\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\r\n\r\n\t// Tri linear interpolation.\r\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\r\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\r\n\r\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\r\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\r\n\r\n\tvec4 result = mix(color10, color20, t);\r\n\r\n\treturn vec4(result.rgb, 1.0);\r\n}\r\n\r\n#endif\r\n"; - - var defaultnormal_vertex = "vec3 transformedNormal = normalMatrix * objectNormal;\r\n\r\n#ifdef FLIP_SIDED\r\n\r\n\ttransformedNormal = - transformedNormal;\r\n\r\n#endif\r\n"; - - var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\r\n\r\n\tuniform sampler2D displacementMap;\r\n\tuniform float displacementScale;\r\n\tuniform float displacementBias;\r\n\r\n#endif\r\n"; - - var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\r\n\r\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\r\n\r\n#endif\r\n"; - - var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\r\n\r\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\r\n\r\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\r\n\r\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\r\n\r\n#endif\r\n"; - - var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\r\n\r\n\tuniform sampler2D emissiveMap;\r\n\r\n#endif\r\n"; - - var encodings_fragment = " gl_FragColor = linearToOutputTexel( gl_FragColor );\r\n"; - - var encodings_pars_fragment = "// For a discussion of what this is, please read this: http://lousodrome.net/blog/light/2013/05/26/gamma-correct-and-hdr-rendering-in-a-32-bits-buffer/\r\n\r\nvec4 LinearToLinear( in vec4 value ) {\r\n\treturn value;\r\n}\r\n\r\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\r\n\treturn vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );\r\n}\r\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\r\n\treturn vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\r\n}\r\n\r\nvec4 sRGBToLinear( in vec4 value ) {\r\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );\r\n}\r\nvec4 LinearTosRGB( in vec4 value ) {\r\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.w );\r\n}\r\n\r\nvec4 RGBEToLinear( in vec4 value ) {\r\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\r\n}\r\nvec4 LinearToRGBE( in vec4 value ) {\r\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\r\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\r\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\r\n// return vec4( value.brg, ( 3.0 + 128.0 ) / 256.0 );\r\n}\r\n\r\n// reference: http://iwasbeingirony.blogspot.ca/2010/06/difference-between-rgbm-and-rgbd.html\r\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\r\n\treturn vec4( value.xyz * value.w * maxRange, 1.0 );\r\n}\r\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\r\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\r\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\r\n\tM = ceil( M * 255.0 ) / 255.0;\r\n\treturn vec4( value.rgb / ( M * maxRange ), M );\r\n}\r\n\r\n// reference: http://iwasbeingirony.blogspot.ca/2010/06/difference-between-rgbm-and-rgbd.html\r\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\r\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\r\n}\r\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\r\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\r\n\tfloat D = max( maxRange / maxRGB, 1.0 );\r\n\tD = min( floor( D ) / 255.0, 1.0 );\r\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\r\n}\r\n\r\n// LogLuv reference: http://graphicrants.blogspot.ca/2009/04/rgbm-color-encoding.html\r\n\r\n// M matrix, for encoding\r\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\r\nvec4 LinearToLogLuv( in vec4 value ) {\r\n\tvec3 Xp_Y_XYZp = value.rgb * cLogLuvM;\r\n\tXp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));\r\n\tvec4 vResult;\r\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\r\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\r\n\tvResult.w = fract(Le);\r\n\tvResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;\r\n\treturn vResult;\r\n}\r\n\r\n// Inverse M matrix, for decoding\r\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\r\nvec4 LogLuvToLinear( in vec4 value ) {\r\n\tfloat Le = value.z * 255.0 + value.w;\r\n\tvec3 Xp_Y_XYZp;\r\n\tXp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);\r\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\r\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\r\n\tvec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;\r\n\treturn vec4( max(vRGB, 0.0), 1.0 );\r\n}\r\n"; - - var envmap_fragment = "#ifdef USE_ENVMAP\r\n\r\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\r\n\r\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\r\n\r\n\t\t// Transforming Normal Vectors with the Inverse Transformation\r\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\r\n\r\n\t\t#ifdef ENVMAP_MODE_REFLECTION\r\n\r\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\r\n\r\n\t\t#else\r\n\r\n\t\t\tvec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\r\n\r\n\t\t#endif\r\n\r\n\t#else\r\n\r\n\t\tvec3 reflectVec = vReflect;\r\n\r\n\t#endif\r\n\r\n\t#ifdef ENVMAP_TYPE_CUBE\r\n\r\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\r\n\r\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\r\n\r\n\t\tvec2 sampleUV;\r\n\r\n\t\treflectVec = normalize( reflectVec );\r\n\r\n\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\r\n\r\n\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\r\n\r\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\r\n\r\n\t#elif defined( ENVMAP_TYPE_SPHERE )\r\n\r\n\t\treflectVec = normalize( reflectVec );\r\n\r\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\r\n\r\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\r\n\r\n\t#else\r\n\r\n\t\tvec4 envColor = vec4( 0.0 );\r\n\r\n\t#endif\r\n\r\n\tenvColor = envMapTexelToLinear( envColor );\r\n\r\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\r\n\r\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\r\n\r\n\t#elif defined( ENVMAP_BLENDING_MIX )\r\n\r\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\r\n\r\n\t#elif defined( ENVMAP_BLENDING_ADD )\r\n\r\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\r\n\r\n\t#endif\r\n\r\n#endif\r\n"; - - var envmap_pars_fragment = "#if defined( USE_ENVMAP ) || defined( PHYSICAL )\r\n\tuniform float reflectivity;\r\n\tuniform float envMapIntensity;\r\n#endif\r\n\r\n#ifdef USE_ENVMAP\r\n\r\n\t#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\r\n\t\tvarying vec3 vWorldPosition;\r\n\t#endif\r\n\r\n\t#ifdef ENVMAP_TYPE_CUBE\r\n\t\tuniform samplerCube envMap;\r\n\t#else\r\n\t\tuniform sampler2D envMap;\r\n\t#endif\r\n\tuniform float flipEnvMap;\r\n\r\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\r\n\t\tuniform float refractionRatio;\r\n\t#else\r\n\t\tvarying vec3 vReflect;\r\n\t#endif\r\n\r\n#endif\r\n"; - - var envmap_pars_vertex = "#ifdef USE_ENVMAP\r\n\r\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\r\n\t\tvarying vec3 vWorldPosition;\r\n\r\n\t#else\r\n\r\n\t\tvarying vec3 vReflect;\r\n\t\tuniform float refractionRatio;\r\n\r\n\t#endif\r\n\r\n#endif\r\n"; - - var envmap_vertex = "#ifdef USE_ENVMAP\r\n\r\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\r\n\r\n\t\tvWorldPosition = worldPosition.xyz;\r\n\r\n\t#else\r\n\r\n\t\tvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\r\n\r\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\r\n\r\n\t\t#ifdef ENVMAP_MODE_REFLECTION\r\n\r\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\r\n\r\n\t\t#else\r\n\r\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\r\n\r\n\t\t#endif\r\n\r\n\t#endif\r\n\r\n#endif\r\n"; - - var fog_vertex = "\r\n#ifdef USE_FOG\r\nfogDepth = -mvPosition.z;\r\n#endif"; - - var fog_pars_vertex = "#ifdef USE_FOG\r\n\r\n varying float fogDepth;\r\n\r\n#endif\r\n"; - - var fog_fragment = "#ifdef USE_FOG\r\n\r\n\t#ifdef FOG_EXP2\r\n\r\n\t\tfloat fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );\r\n\r\n\t#else\r\n\r\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\r\n\r\n\t#endif\r\n\r\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\r\n\r\n#endif\r\n"; - - var fog_pars_fragment = "#ifdef USE_FOG\r\n\r\n\tuniform vec3 fogColor;\r\n\tvarying float fogDepth;\r\n\r\n\t#ifdef FOG_EXP2\r\n\r\n\t\tuniform float fogDensity;\r\n\r\n\t#else\r\n\r\n\t\tuniform float fogNear;\r\n\t\tuniform float fogFar;\r\n\r\n\t#endif\r\n\r\n#endif\r\n"; - - var gradientmap_pars_fragment = "#ifdef TOON\r\n\r\n\tuniform sampler2D gradientMap;\r\n\r\n\tvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\r\n\r\n\t\t// dotNL will be from -1.0 to 1.0\r\n\t\tfloat dotNL = dot( normal, lightDirection );\r\n\t\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\r\n\r\n\t\t#ifdef USE_GRADIENTMAP\r\n\r\n\t\t\treturn texture2D( gradientMap, coord ).rgb;\r\n\r\n\t\t#else\r\n\r\n\t\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\r\n\r\n\t\t#endif\r\n\r\n\r\n\t}\r\n\r\n#endif\r\n"; - - var lightmap_fragment = "#ifdef USE_LIGHTMAP\r\n\r\n\treflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity; // factor of PI should not be present; included here to prevent breakage\r\n\r\n#endif\r\n"; - - var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\r\n\r\n\tuniform sampler2D lightMap;\r\n\tuniform float lightMapIntensity;\r\n\r\n#endif"; - - var lights_lambert_vertex = "vec3 diffuse = vec3( 1.0 );\r\n\r\nGeometricContext geometry;\r\ngeometry.position = mvPosition.xyz;\r\ngeometry.normal = normalize( transformedNormal );\r\ngeometry.viewDir = normalize( -mvPosition.xyz );\r\n\r\nGeometricContext backGeometry;\r\nbackGeometry.position = geometry.position;\r\nbackGeometry.normal = -geometry.normal;\r\nbackGeometry.viewDir = geometry.viewDir;\r\n\r\nvLightFront = vec3( 0.0 );\r\n\r\n#ifdef DOUBLE_SIDED\r\n\tvLightBack = vec3( 0.0 );\r\n#endif\r\n\r\nIncidentLight directLight;\r\nfloat dotNL;\r\nvec3 directLightColor_Diffuse;\r\n\r\n#if NUM_POINT_LIGHTS > 0\r\n\r\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\r\n\r\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\r\n\r\n\t\tdotNL = dot( geometry.normal, directLight.direction );\r\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\r\n\r\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\r\n\r\n\t\t#ifdef DOUBLE_SIDED\r\n\r\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\r\n\r\n\t\t#endif\r\n\r\n\t}\r\n\r\n#endif\r\n\r\n#if NUM_SPOT_LIGHTS > 0\r\n\r\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\r\n\r\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\r\n\r\n\t\tdotNL = dot( geometry.normal, directLight.direction );\r\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\r\n\r\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\r\n\r\n\t\t#ifdef DOUBLE_SIDED\r\n\r\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\r\n\r\n\t\t#endif\r\n\t}\r\n\r\n#endif\r\n\r\n\r\n\r\n#if NUM_DIR_LIGHTS > 0\r\n\r\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\r\n\r\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\r\n\r\n\t\tdotNL = dot( geometry.normal, directLight.direction );\r\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\r\n\r\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\r\n\r\n\t\t#ifdef DOUBLE_SIDED\r\n\r\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\r\n\r\n\t\t#endif\r\n\r\n\t}\r\n\r\n#endif\r\n\r\n#if NUM_HEMI_LIGHTS > 0\r\n\r\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\r\n\r\n\t\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\r\n\r\n\t\t#ifdef DOUBLE_SIDED\r\n\r\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\r\n\r\n\t\t#endif\r\n\r\n\t}\r\n\r\n#endif\r\n"; - - var lights_pars = "uniform vec3 ambientLightColor;\r\n\r\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\r\n\r\n\tvec3 irradiance = ambientLightColor;\r\n\r\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\r\n\r\n\t\tirradiance *= PI;\r\n\r\n\t#endif\r\n\r\n\treturn irradiance;\r\n\r\n}\r\n\r\n#if NUM_DIR_LIGHTS > 0\r\n\r\n\tstruct DirectionalLight {\r\n\t\tvec3 direction;\r\n\t\tvec3 color;\r\n\r\n\t\tint shadow;\r\n\t\tfloat shadowBias;\r\n\t\tfloat shadowRadius;\r\n\t\tvec2 shadowMapSize;\r\n\t};\r\n\r\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\r\n\r\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\r\n\r\n\t\tdirectLight.color = directionalLight.color;\r\n\t\tdirectLight.direction = directionalLight.direction;\r\n\t\tdirectLight.visible = true;\r\n\r\n\t}\r\n\r\n#endif\r\n\r\n\r\n#if NUM_POINT_LIGHTS > 0\r\n\r\n\tstruct PointLight {\r\n\t\tvec3 position;\r\n\t\tvec3 color;\r\n\t\tfloat distance;\r\n\t\tfloat decay;\r\n\r\n\t\tint shadow;\r\n\t\tfloat shadowBias;\r\n\t\tfloat shadowRadius;\r\n\t\tvec2 shadowMapSize;\r\n\t\tfloat shadowCameraNear;\r\n\t\tfloat shadowCameraFar;\r\n\t};\r\n\r\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\r\n\r\n\t// directLight is an out parameter as having it as a return value caused compiler errors on some devices\r\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\r\n\r\n\t\tvec3 lVector = pointLight.position - geometry.position;\r\n\t\tdirectLight.direction = normalize( lVector );\r\n\r\n\t\tfloat lightDistance = length( lVector );\r\n\r\n\t\tdirectLight.color = pointLight.color;\r\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\r\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\r\n\r\n\t}\r\n\r\n#endif\r\n\r\n\r\n#if NUM_SPOT_LIGHTS > 0\r\n\r\n\tstruct SpotLight {\r\n\t\tvec3 position;\r\n\t\tvec3 direction;\r\n\t\tvec3 color;\r\n\t\tfloat distance;\r\n\t\tfloat decay;\r\n\t\tfloat coneCos;\r\n\t\tfloat penumbraCos;\r\n\r\n\t\tint shadow;\r\n\t\tfloat shadowBias;\r\n\t\tfloat shadowRadius;\r\n\t\tvec2 shadowMapSize;\r\n\t};\r\n\r\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\r\n\r\n\t// directLight is an out parameter as having it as a return value caused compiler errors on some devices\r\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\r\n\r\n\t\tvec3 lVector = spotLight.position - geometry.position;\r\n\t\tdirectLight.direction = normalize( lVector );\r\n\r\n\t\tfloat lightDistance = length( lVector );\r\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\r\n\r\n\t\tif ( angleCos > spotLight.coneCos ) {\r\n\r\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\r\n\r\n\t\t\tdirectLight.color = spotLight.color;\r\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\r\n\t\t\tdirectLight.visible = true;\r\n\r\n\t\t} else {\r\n\r\n\t\t\tdirectLight.color = vec3( 0.0 );\r\n\t\t\tdirectLight.visible = false;\r\n\r\n\t\t}\r\n\t}\r\n\r\n#endif\r\n\r\n\r\n#if NUM_RECT_AREA_LIGHTS > 0\r\n\r\n\tstruct RectAreaLight {\r\n\t\tvec3 color;\r\n\t\tvec3 position;\r\n\t\tvec3 halfWidth;\r\n\t\tvec3 halfHeight;\r\n\t};\r\n\r\n\t// Pre-computed values of LinearTransformedCosine approximation of BRDF\r\n\t// BRDF approximation Texture is 64x64\r\n\tuniform sampler2D ltcMat; // RGBA Float\r\n\tuniform sampler2D ltcMag; // Alpha Float (only has w component)\r\n\r\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\r\n\r\n#endif\r\n\r\n\r\n#if NUM_HEMI_LIGHTS > 0\r\n\r\n\tstruct HemisphereLight {\r\n\t\tvec3 direction;\r\n\t\tvec3 skyColor;\r\n\t\tvec3 groundColor;\r\n\t};\r\n\r\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\r\n\r\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\r\n\r\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\r\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\r\n\r\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\r\n\r\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\r\n\r\n\t\t\tirradiance *= PI;\r\n\r\n\t\t#endif\r\n\r\n\t\treturn irradiance;\r\n\r\n\t}\r\n\r\n#endif\r\n\r\n\r\n#if defined( USE_ENVMAP ) && defined( PHYSICAL )\r\n\r\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\r\n\r\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\r\n\r\n\t\t#ifdef ENVMAP_TYPE_CUBE\r\n\r\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\r\n\r\n\t\t\t// TODO: replace with properly filtered cubemaps and access the irradiance LOD level, be it the last LOD level\r\n\t\t\t// of a specular cubemap, or just the default level of a specially created irradiance cubemap.\r\n\r\n\t\t\t#ifdef TEXTURE_LOD_EXT\r\n\r\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\r\n\r\n\t\t\t#else\r\n\r\n\t\t\t\t// force the bias high to get the last LOD level as it is the most blurred.\r\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\r\n\r\n\t\t\t#endif\r\n\r\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\r\n\r\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\r\n\r\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\r\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 1.0 );\r\n\r\n\t\t#else\r\n\r\n\t\t\tvec4 envMapColor = vec4( 0.0 );\r\n\r\n\t\t#endif\r\n\r\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\r\n\r\n\t}\r\n\r\n\t// taken from here: http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html\r\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\r\n\r\n\t\t//float envMapWidth = pow( 2.0, maxMIPLevelScalar );\r\n\t\t//float desiredMIPLevel = log2( envMapWidth * sqrt( 3.0 ) ) - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\r\n\r\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\r\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\r\n\r\n\t\t// clamp to allowable LOD ranges.\r\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\r\n\r\n\t}\r\n\r\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\r\n\r\n\t\t#ifdef ENVMAP_MODE_REFLECTION\r\n\r\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\r\n\r\n\t\t#else\r\n\r\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\r\n\r\n\t\t#endif\r\n\r\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\r\n\r\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\r\n\r\n\t\t#ifdef ENVMAP_TYPE_CUBE\r\n\r\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\r\n\r\n\t\t\t#ifdef TEXTURE_LOD_EXT\r\n\r\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\r\n\r\n\t\t\t#else\r\n\r\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\r\n\r\n\t\t\t#endif\r\n\r\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\r\n\r\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\r\n\r\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\r\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\r\n\r\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\r\n\r\n\t\t\tvec2 sampleUV;\r\n\t\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\r\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\r\n\r\n\t\t\t#ifdef TEXTURE_LOD_EXT\r\n\r\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\r\n\r\n\t\t\t#else\r\n\r\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\r\n\r\n\t\t\t#endif\r\n\r\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\r\n\r\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\r\n\r\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\r\n\r\n\t\t\t#ifdef TEXTURE_LOD_EXT\r\n\r\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\r\n\r\n\t\t\t#else\r\n\r\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\r\n\r\n\t\t\t#endif\r\n\r\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\r\n\r\n\t\t#endif\r\n\r\n\t\treturn envMapColor.rgb * envMapIntensity;\r\n\r\n\t}\r\n\r\n#endif\r\n"; - - var lights_phong_fragment = "BlinnPhongMaterial material;\r\nmaterial.diffuseColor = diffuseColor.rgb;\r\nmaterial.specularColor = specular;\r\nmaterial.specularShininess = shininess;\r\nmaterial.specularStrength = specularStrength;\r\n"; - - var lights_phong_pars_fragment = "varying vec3 vViewPosition;\r\n\r\n#ifndef FLAT_SHADED\r\n\r\n\tvarying vec3 vNormal;\r\n\r\n#endif\r\n\r\n\r\nstruct BlinnPhongMaterial {\r\n\r\n\tvec3\tdiffuseColor;\r\n\tvec3\tspecularColor;\r\n\tfloat\tspecularShininess;\r\n\tfloat\tspecularStrength;\r\n\r\n};\r\n\r\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\r\n\r\n\t#ifdef TOON\r\n\r\n\t\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\r\n\r\n\t#else\r\n\r\n\t\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\r\n\t\tvec3 irradiance = dotNL * directLight.color;\r\n\r\n\t#endif\r\n\r\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\r\n\r\n\t\tirradiance *= PI; // punctual light\r\n\r\n\t#endif\r\n\r\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\r\n\r\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\r\n\r\n}\r\n\r\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\r\n\r\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\r\n\r\n}\r\n\r\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\r\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\r\n\r\n#define Material_LightProbeLOD( material )\t(0)\r\n"; - - var lights_physical_fragment = "PhysicalMaterial material;\r\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\r\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\r\n#ifdef STANDARD\r\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\r\n#else\r\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\r\n\tmaterial.clearCoat = saturate( clearCoat ); // Burley clearcoat model\r\n\tmaterial.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 );\r\n#endif\r\n"; - - var lights_physical_pars_fragment = "struct PhysicalMaterial {\r\n\r\n\tvec3\tdiffuseColor;\r\n\tfloat\tspecularRoughness;\r\n\tvec3\tspecularColor;\r\n\r\n\t#ifndef STANDARD\r\n\t\tfloat clearCoat;\r\n\t\tfloat clearCoatRoughness;\r\n\t#endif\r\n\r\n};\r\n\r\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\r\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\r\n\r\n// Clear coat directional hemishperical reflectance (this approximation should be improved)\r\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\r\n\r\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\r\n\r\n}\r\n\r\n#if NUM_RECT_AREA_LIGHTS > 0\r\n\r\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\r\n\r\n\t\tvec3 normal = geometry.normal;\r\n\t\tvec3 viewDir = geometry.viewDir;\r\n\t\tvec3 position = geometry.position;\r\n\t\tvec3 lightPos = rectAreaLight.position;\r\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\r\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\r\n\t\tvec3 lightColor = rectAreaLight.color;\r\n\t\tfloat roughness = material.specularRoughness;\r\n\r\n\t\tvec3 rectCoords[ 4 ];\r\n\t\trectCoords[ 0 ] = lightPos - halfWidth - halfHeight; // counterclockwise\r\n\t\trectCoords[ 1 ] = lightPos + halfWidth - halfHeight;\r\n\t\trectCoords[ 2 ] = lightPos + halfWidth + halfHeight;\r\n\t\trectCoords[ 3 ] = lightPos - halfWidth + halfHeight;\r\n\r\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\r\n\r\n\t\tfloat norm = texture2D( ltcMag, uv ).a;\r\n\r\n\t\tvec4 t = texture2D( ltcMat, uv );\r\n\r\n\t\tmat3 mInv = mat3(\r\n\t\t\tvec3( 1, 0, t.y ),\r\n\t\t\tvec3( 0, t.z, 0 ),\r\n\t\t\tvec3( t.w, 0, t.x )\r\n\t\t);\r\n\r\n\t\treflectedLight.directSpecular += lightColor * material.specularColor * norm * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords ); // no fresnel\r\n\r\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1 ), rectCoords );\r\n\r\n\t}\r\n\r\n#endif\r\n\r\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\r\n\r\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\r\n\r\n\tvec3 irradiance = dotNL * directLight.color;\r\n\r\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\r\n\r\n\t\tirradiance *= PI; // punctual light\r\n\r\n\t#endif\r\n\r\n\t#ifndef STANDARD\r\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\r\n\t#else\r\n\t\tfloat clearCoatDHR = 0.0;\r\n\t#endif\r\n\r\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\r\n\r\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\r\n\r\n\t#ifndef STANDARD\r\n\r\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\r\n\r\n\t#endif\r\n\r\n}\r\n\r\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\r\n\r\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\r\n\r\n}\r\n\r\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\r\n\r\n\t#ifndef STANDARD\r\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\r\n\t\tfloat dotNL = dotNV;\r\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\r\n\t#else\r\n\t\tfloat clearCoatDHR = 0.0;\r\n\t#endif\r\n\r\n\treflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\r\n\r\n\t#ifndef STANDARD\r\n\r\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\r\n\r\n\t#endif\r\n\r\n}\r\n\r\n#define RE_Direct\t\t\t\tRE_Direct_Physical\r\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\r\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\r\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\r\n\r\n#define Material_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.specularRoughness )\r\n#define Material_ClearCoat_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\r\n\r\n// ref: https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf\r\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\r\n\r\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\r\n\r\n}\r\n"; - - var lights_template = "\r\n\r\nGeometricContext geometry;\r\n\r\ngeometry.position = - vViewPosition;\r\ngeometry.normal = normal;\r\ngeometry.viewDir = normalize( vViewPosition );\r\n\r\nIncidentLight directLight;\r\n\r\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\r\n\r\n\tPointLight pointLight;\r\n\r\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\r\n\r\n\t\tpointLight = pointLights[ i ];\r\n\r\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\r\n\r\n\t\t#ifdef USE_SHADOWMAP\r\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\r\n\t\t#endif\r\n\r\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\r\n\r\n\t}\r\n\r\n#endif\r\n\r\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\r\n\r\n\tSpotLight spotLight;\r\n\r\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\r\n\r\n\t\tspotLight = spotLights[ i ];\r\n\r\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\r\n\r\n\t\t#ifdef USE_SHADOWMAP\r\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\r\n\t\t#endif\r\n\r\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\r\n\r\n\t}\r\n\r\n#endif\r\n\r\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\r\n\r\n\tDirectionalLight directionalLight;\r\n\r\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\r\n\r\n\t\tdirectionalLight = directionalLights[ i ];\r\n\r\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\r\n\r\n\t\t#ifdef USE_SHADOWMAP\r\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\r\n\t\t#endif\r\n\r\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\r\n\r\n\t}\r\n\r\n#endif\r\n\r\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\r\n\r\n\tRectAreaLight rectAreaLight;\r\n\r\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\r\n\r\n\t\trectAreaLight = rectAreaLights[ i ];\r\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\r\n\r\n\t}\r\n\r\n#endif\r\n\r\n#if defined( RE_IndirectDiffuse )\r\n\r\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\r\n\r\n\t#ifdef USE_LIGHTMAP\r\n\r\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\r\n\r\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\r\n\r\n\t\t\tlightMapIrradiance *= PI; // factor of PI should not be present; included here to prevent breakage\r\n\r\n\t\t#endif\r\n\r\n\t\tirradiance += lightMapIrradiance;\r\n\r\n\t#endif\r\n\r\n\t#if ( NUM_HEMI_LIGHTS > 0 )\r\n\r\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\r\n\r\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\r\n\r\n\t\t}\r\n\r\n\t#endif\r\n\r\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\r\n\r\n\t\t// TODO, replace 8 with the real maxMIPLevel\r\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, 8 );\r\n\r\n\t#endif\r\n\r\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\r\n\r\n#endif\r\n\r\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\r\n\r\n\t// TODO, replace 8 with the real maxMIPLevel\r\n\tvec3 radiance = getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), 8 );\r\n\r\n\t#ifndef STANDARD\r\n\t\tvec3 clearCoatRadiance = getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), 8 );\r\n\t#else\r\n\t\tvec3 clearCoatRadiance = vec3( 0.0 );\r\n\t#endif\r\n\r\n\tRE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\r\n\r\n#endif\r\n"; - - var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\r\n\r\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\r\n\r\n#endif"; - - var logdepthbuf_pars_fragment = "#ifdef USE_LOGDEPTHBUF\r\n\r\n\tuniform float logDepthBufFC;\r\n\r\n\t#ifdef USE_LOGDEPTHBUF_EXT\r\n\r\n\t\tvarying float vFragDepth;\r\n\r\n\t#endif\r\n\r\n#endif\r\n"; - - var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\r\n\r\n\t#ifdef USE_LOGDEPTHBUF_EXT\r\n\r\n\t\tvarying float vFragDepth;\r\n\r\n\t#endif\r\n\r\n\tuniform float logDepthBufFC;\r\n\r\n#endif"; - - var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\r\n\r\n\t#ifdef USE_LOGDEPTHBUF_EXT\r\n\r\n\t\tvFragDepth = 1.0 + gl_Position.w;\r\n\r\n\t#else\r\n\r\n\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\r\n\r\n\t\tgl_Position.z *= gl_Position.w;\r\n\r\n\t#endif\r\n\r\n#endif\r\n"; - - var map_fragment = "#ifdef USE_MAP\r\n\r\n\tvec4 texelColor = texture2D( map, vUv );\r\n\r\n\ttexelColor = mapTexelToLinear( texelColor );\r\n\tdiffuseColor *= texelColor;\r\n\r\n#endif\r\n"; - - var map_pars_fragment = "#ifdef USE_MAP\r\n\r\n\tuniform sampler2D map;\r\n\r\n#endif\r\n"; - - var map_particle_fragment = "#ifdef USE_MAP\r\n\r\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\r\n\tvec4 mapTexel = texture2D( map, uv );\r\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\r\n\r\n#endif\r\n"; - - var map_particle_pars_fragment = "#ifdef USE_MAP\r\n\r\n\tuniform mat3 uvTransform;\r\n\tuniform sampler2D map;\r\n\r\n#endif\r\n"; - - var metalnessmap_fragment = "float metalnessFactor = metalness;\r\n\r\n#ifdef USE_METALNESSMAP\r\n\r\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\r\n\r\n\t// reads channel B, compatible with a combined OcclusionRoughnessMetallic (RGB) texture\r\n\tmetalnessFactor *= texelMetalness.b;\r\n\r\n#endif\r\n"; - - var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\r\n\r\n\tuniform sampler2D metalnessMap;\r\n\r\n#endif"; - - var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\r\n\r\n\tobjectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\r\n\tobjectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\r\n\tobjectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\r\n\tobjectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\r\n\r\n#endif\r\n"; - - var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\r\n\r\n\t#ifndef USE_MORPHNORMALS\r\n\r\n\tuniform float morphTargetInfluences[ 8 ];\r\n\r\n\t#else\r\n\r\n\tuniform float morphTargetInfluences[ 4 ];\r\n\r\n\t#endif\r\n\r\n#endif"; - - var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\r\n\r\n\ttransformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\r\n\ttransformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\r\n\ttransformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\r\n\ttransformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\r\n\r\n\t#ifndef USE_MORPHNORMALS\r\n\r\n\ttransformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\r\n\ttransformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\r\n\ttransformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\r\n\ttransformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\r\n\r\n\t#endif\r\n\r\n#endif\r\n"; - - var normal_fragment = "#ifdef FLAT_SHADED\r\n\r\n\t// Workaround for Adreno/Nexus5 not able able to do dFdx( vViewPosition ) ...\r\n\r\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\r\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\r\n\tvec3 normal = normalize( cross( fdx, fdy ) );\r\n\r\n#else\r\n\r\n\tvec3 normal = normalize( vNormal );\r\n\r\n\t#ifdef DOUBLE_SIDED\r\n\r\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\r\n\r\n\t#endif\r\n\r\n#endif\r\n\r\n#ifdef USE_NORMALMAP\r\n\r\n\tnormal = perturbNormal2Arb( -vViewPosition, normal );\r\n\r\n#elif defined( USE_BUMPMAP )\r\n\r\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\r\n\r\n#endif\r\n"; - - var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\r\n\r\n\tuniform sampler2D normalMap;\r\n\tuniform vec2 normalScale;\r\n\r\n\t// Per-Pixel Tangent Space Normal Mapping\r\n\t// http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html\r\n\r\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\r\n\r\n\t\t// Workaround for Adreno 3XX dFd*( vec3 ) bug. See #9988\r\n\r\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\r\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\r\n\t\tvec2 st0 = dFdx( vUv.st );\r\n\t\tvec2 st1 = dFdy( vUv.st );\r\n\r\n\t\tvec3 S = normalize( q0 * st1.t - q1 * st0.t );\r\n\t\tvec3 T = normalize( -q0 * st1.s + q1 * st0.s );\r\n\t\tvec3 N = normalize( surf_norm );\r\n\r\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\r\n\t\tmapN.xy = normalScale * mapN.xy;\r\n\t\tmat3 tsn = mat3( S, T, N );\r\n\t\treturn normalize( tsn * mapN );\r\n\r\n\t}\r\n\r\n#endif\r\n"; - - var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\r\n\treturn normalize( normal ) * 0.5 + 0.5;\r\n}\r\n\r\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\r\n\treturn 2.0 * rgb.xyz - 1.0;\r\n}\r\n\r\nconst float PackUpscale = 256. / 255.; // fraction -> 0..1 (including 1)\r\nconst float UnpackDownscale = 255. / 256.; // 0..1 -> fraction (excluding 1)\r\n\r\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\r\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\r\n\r\nconst float ShiftRight8 = 1. / 256.;\r\n\r\nvec4 packDepthToRGBA( const in float v ) {\r\n\tvec4 r = vec4( fract( v * PackFactors ), v );\r\n\tr.yzw -= r.xyz * ShiftRight8; // tidy overflow\r\n\treturn r * PackUpscale;\r\n}\r\n\r\nfloat unpackRGBAToDepth( const in vec4 v ) {\r\n\treturn dot( v, UnpackFactors );\r\n}\r\n\r\n// NOTE: viewZ/eyeZ is < 0 when in front of the camera per OpenGL conventions\r\n\r\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\r\n\treturn ( viewZ + near ) / ( near - far );\r\n}\r\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\r\n\treturn linearClipZ * ( near - far ) - near;\r\n}\r\n\r\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\r\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\r\n}\r\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\r\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\r\n}\r\n"; - - var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\r\n\r\n\t// Get get normal blending with premultipled, use with CustomBlending, OneFactor, OneMinusSrcAlphaFactor, AddEquation.\r\n\tgl_FragColor.rgb *= gl_FragColor.a;\r\n\r\n#endif\r\n"; - - var project_vertex = "vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\r\n\r\ngl_Position = projectionMatrix * mvPosition;\r\n"; - - var dithering_fragment = "#if defined( DITHERING )\r\n\r\n gl_FragColor.rgb = dithering( gl_FragColor.rgb );\r\n\r\n#endif\r\n"; - - var dithering_pars_fragment = "#if defined( DITHERING )\r\n\r\n\t// based on https://www.shadertoy.com/view/MslGR8\r\n\tvec3 dithering( vec3 color ) {\r\n\t\t//Calculate grid position\r\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\r\n\r\n\t\t//Shift the individual colors differently, thus making it even harder to see the dithering pattern\r\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\r\n\r\n\t\t//modify shift acording to grid position.\r\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\r\n\r\n\t\t//shift the color by dither_shift\r\n\t\treturn color + dither_shift_RGB;\r\n\t}\r\n\r\n#endif\r\n"; - - var roughnessmap_fragment = "float roughnessFactor = roughness;\r\n\r\n#ifdef USE_ROUGHNESSMAP\r\n\r\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\r\n\r\n\t// reads channel G, compatible with a combined OcclusionRoughnessMetallic (RGB) texture\r\n\troughnessFactor *= texelRoughness.g;\r\n\r\n#endif\r\n"; - - var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\r\n\r\n\tuniform sampler2D roughnessMap;\r\n\r\n#endif"; - - var shadowmap_pars_fragment = "#ifdef USE_SHADOWMAP\r\n\r\n\t#if NUM_DIR_LIGHTS > 0\r\n\r\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\r\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\r\n\r\n\t#endif\r\n\r\n\t#if NUM_SPOT_LIGHTS > 0\r\n\r\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\r\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\r\n\r\n\t#endif\r\n\r\n\t#if NUM_POINT_LIGHTS > 0\r\n\r\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\r\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\r\n\r\n\t#endif\r\n\r\n\r\n\r\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\r\n\r\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\r\n\r\n\t}\r\n\r\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\r\n\r\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\r\n\r\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\r\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\r\n\r\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\r\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\r\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\r\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\r\n\r\n\t\tvec2 f = fract( uv * size + 0.5 );\r\n\r\n\t\tfloat a = mix( lb, lt, f.y );\r\n\t\tfloat b = mix( rb, rt, f.y );\r\n\t\tfloat c = mix( a, b, f.x );\r\n\r\n\t\treturn c;\r\n\r\n\t}\r\n\r\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\r\n\r\n\t\tfloat shadow = 1.0;\r\n\r\n\t\tshadowCoord.xyz /= shadowCoord.w;\r\n\t\tshadowCoord.z += shadowBias;\r\n\r\n\t\t// if ( something && something ) breaks ATI OpenGL shader compiler\r\n\t\t// if ( all( something, something ) ) using this instead\r\n\r\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\r\n\t\tbool inFrustum = all( inFrustumVec );\r\n\r\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\r\n\r\n\t\tbool frustumTest = all( frustumTestVec );\r\n\r\n\t\tif ( frustumTest ) {\r\n\r\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\r\n\r\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\r\n\r\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\r\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\r\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\r\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\r\n\r\n\t\t\tshadow = (\r\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\r\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\r\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\r\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\r\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\r\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\r\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\r\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\r\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\r\n\t\t\t) * ( 1.0 / 9.0 );\r\n\r\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\r\n\r\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\r\n\r\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\r\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\r\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\r\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\r\n\r\n\t\t\tshadow = (\r\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\r\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\r\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\r\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\r\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\r\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\r\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\r\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\r\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\r\n\t\t\t) * ( 1.0 / 9.0 );\r\n\r\n\t\t#else // no percentage-closer filtering:\r\n\r\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\r\n\r\n\t\t#endif\r\n\r\n\t\t}\r\n\r\n\t\treturn shadow;\r\n\r\n\t}\r\n\r\n\t// cubeToUV() maps a 3D direction vector suitable for cube texture mapping to a 2D\r\n\t// vector suitable for 2D texture mapping. This code uses the following layout for the\r\n\t// 2D texture:\r\n\t//\r\n\t// xzXZ\r\n\t// y Y\r\n\t//\r\n\t// Y - Positive y direction\r\n\t// y - Negative y direction\r\n\t// X - Positive x direction\r\n\t// x - Negative x direction\r\n\t// Z - Positive z direction\r\n\t// z - Negative z direction\r\n\t//\r\n\t// Source and test bed:\r\n\t// https://gist.github.com/tschw/da10c43c467ce8afd0c4\r\n\r\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\r\n\r\n\t\t// Number of texels to avoid at the edge of each square\r\n\r\n\t\tvec3 absV = abs( v );\r\n\r\n\t\t// Intersect unit cube\r\n\r\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\r\n\t\tabsV *= scaleToCube;\r\n\r\n\t\t// Apply scale to avoid seams\r\n\r\n\t\t// two texels less per square (one texel will do for NEAREST)\r\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\r\n\r\n\t\t// Unwrap\r\n\r\n\t\t// space: -1 ... 1 range for each square\r\n\t\t//\r\n\t\t// #X##\t\tdim := ( 4 , 2 )\r\n\t\t// # #\t\tcenter := ( 1 , 1 )\r\n\r\n\t\tvec2 planar = v.xy;\r\n\r\n\t\tfloat almostATexel = 1.5 * texelSizeY;\r\n\t\tfloat almostOne = 1.0 - almostATexel;\r\n\r\n\t\tif ( absV.z >= almostOne ) {\r\n\r\n\t\t\tif ( v.z > 0.0 )\r\n\t\t\t\tplanar.x = 4.0 - v.x;\r\n\r\n\t\t} else if ( absV.x >= almostOne ) {\r\n\r\n\t\t\tfloat signX = sign( v.x );\r\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\r\n\r\n\t\t} else if ( absV.y >= almostOne ) {\r\n\r\n\t\t\tfloat signY = sign( v.y );\r\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\r\n\t\t\tplanar.y = v.z * signY - 2.0;\r\n\r\n\t\t}\r\n\r\n\t\t// Transform to UV space\r\n\r\n\t\t// scale := 0.5 / dim\r\n\t\t// translate := ( center + 0.5 ) / dim\r\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\r\n\r\n\t}\r\n\r\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\r\n\r\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\r\n\r\n\t\t// for point lights, the uniform @vShadowCoord is re-purposed to hold\r\n\t\t// the vector from the light to the world-space position of the fragment.\r\n\t\tvec3 lightToPosition = shadowCoord.xyz;\r\n\r\n\t\t// dp = normalized distance from light to fragment position\r\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear ); // need to clamp?\r\n\t\tdp += shadowBias;\r\n\r\n\t\t// bd3D = base direction 3D\r\n\t\tvec3 bd3D = normalize( lightToPosition );\r\n\r\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\r\n\r\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\r\n\r\n\t\t\treturn (\r\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\r\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\r\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\r\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\r\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\r\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\r\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\r\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\r\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\r\n\t\t\t) * ( 1.0 / 9.0 );\r\n\r\n\t\t#else // no percentage-closer filtering\r\n\r\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\r\n\r\n\t\t#endif\r\n\r\n\t}\r\n\r\n#endif\r\n"; - - var shadowmap_pars_vertex = "#ifdef USE_SHADOWMAP\r\n\r\n\t#if NUM_DIR_LIGHTS > 0\r\n\r\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\r\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\r\n\r\n\t#endif\r\n\r\n\t#if NUM_SPOT_LIGHTS > 0\r\n\r\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\r\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\r\n\r\n\t#endif\r\n\r\n\t#if NUM_POINT_LIGHTS > 0\r\n\r\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\r\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\r\n\r\n\t#endif\r\n\r\n\r\n\r\n#endif\r\n"; - - var shadowmap_vertex = "#ifdef USE_SHADOWMAP\r\n\r\n\t#if NUM_DIR_LIGHTS > 0\r\n\r\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\r\n\r\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\r\n\r\n\t}\r\n\r\n\t#endif\r\n\r\n\t#if NUM_SPOT_LIGHTS > 0\r\n\r\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\r\n\r\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\r\n\r\n\t}\r\n\r\n\t#endif\r\n\r\n\t#if NUM_POINT_LIGHTS > 0\r\n\r\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\r\n\r\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\r\n\r\n\t}\r\n\r\n\t#endif\r\n\r\n\r\n\r\n#endif\r\n"; - - var shadowmask_pars_fragment = "float getShadowMask() {\r\n\r\n\tfloat shadow = 1.0;\r\n\r\n\t#ifdef USE_SHADOWMAP\r\n\r\n\t#if NUM_DIR_LIGHTS > 0\r\n\r\n\tDirectionalLight directionalLight;\r\n\r\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\r\n\r\n\t\tdirectionalLight = directionalLights[ i ];\r\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\r\n\r\n\t}\r\n\r\n\t#endif\r\n\r\n\t#if NUM_SPOT_LIGHTS > 0\r\n\r\n\tSpotLight spotLight;\r\n\r\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\r\n\r\n\t\tspotLight = spotLights[ i ];\r\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\r\n\r\n\t}\r\n\r\n\t#endif\r\n\r\n\t#if NUM_POINT_LIGHTS > 0\r\n\r\n\tPointLight pointLight;\r\n\r\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\r\n\r\n\t\tpointLight = pointLights[ i ];\r\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\r\n\r\n\t}\r\n\r\n\t#endif\r\n\r\n\r\n\r\n\t#endif\r\n\r\n\treturn shadow;\r\n\r\n}\r\n"; - - var skinbase_vertex = "#ifdef USE_SKINNING\r\n\r\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\r\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\r\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\r\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\r\n\r\n#endif"; - - var skinning_pars_vertex = "#ifdef USE_SKINNING\r\n\r\n\tuniform mat4 bindMatrix;\r\n\tuniform mat4 bindMatrixInverse;\r\n\r\n\t#ifdef BONE_TEXTURE\r\n\r\n\t\tuniform sampler2D boneTexture;\r\n\t\tuniform int boneTextureSize;\r\n\r\n\t\tmat4 getBoneMatrix( const in float i ) {\r\n\r\n\t\t\tfloat j = i * 4.0;\r\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\r\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\r\n\r\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\r\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\r\n\r\n\t\t\ty = dy * ( y + 0.5 );\r\n\r\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\r\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\r\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\r\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\r\n\r\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\r\n\r\n\t\t\treturn bone;\r\n\r\n\t\t}\r\n\r\n\t#else\r\n\r\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\r\n\r\n\t\tmat4 getBoneMatrix( const in float i ) {\r\n\r\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\r\n\t\t\treturn bone;\r\n\r\n\t\t}\r\n\r\n\t#endif\r\n\r\n#endif\r\n"; - - var skinning_vertex = "#ifdef USE_SKINNING\r\n\r\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\r\n\r\n\tvec4 skinned = vec4( 0.0 );\r\n\tskinned += boneMatX * skinVertex * skinWeight.x;\r\n\tskinned += boneMatY * skinVertex * skinWeight.y;\r\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\r\n\tskinned += boneMatW * skinVertex * skinWeight.w;\r\n\r\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\r\n\r\n#endif\r\n"; - - var skinnormal_vertex = "#ifdef USE_SKINNING\r\n\r\n\tmat4 skinMatrix = mat4( 0.0 );\r\n\tskinMatrix += skinWeight.x * boneMatX;\r\n\tskinMatrix += skinWeight.y * boneMatY;\r\n\tskinMatrix += skinWeight.z * boneMatZ;\r\n\tskinMatrix += skinWeight.w * boneMatW;\r\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\r\n\r\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\r\n\r\n#endif\r\n"; - - var specularmap_fragment = "float specularStrength;\r\n\r\n#ifdef USE_SPECULARMAP\r\n\r\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\r\n\tspecularStrength = texelSpecular.r;\r\n\r\n#else\r\n\r\n\tspecularStrength = 1.0;\r\n\r\n#endif"; - - var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\r\n\r\n\tuniform sampler2D specularMap;\r\n\r\n#endif"; - - var tonemapping_fragment = "#if defined( TONE_MAPPING )\r\n\r\n gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\r\n\r\n#endif\r\n"; - - var tonemapping_pars_fragment = "#ifndef saturate\r\n\t#define saturate(a) clamp( a, 0.0, 1.0 )\r\n#endif\r\n\r\nuniform float toneMappingExposure;\r\nuniform float toneMappingWhitePoint;\r\n\r\n// exposure only\r\nvec3 LinearToneMapping( vec3 color ) {\r\n\r\n\treturn toneMappingExposure * color;\r\n\r\n}\r\n\r\n// source: https://www.cs.utah.edu/~reinhard/cdrom/\r\nvec3 ReinhardToneMapping( vec3 color ) {\r\n\r\n\tcolor *= toneMappingExposure;\r\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\r\n\r\n}\r\n\r\n// source: http://filmicgames.com/archives/75\r\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\r\nvec3 Uncharted2ToneMapping( vec3 color ) {\r\n\r\n\t// John Hable's filmic operator from Uncharted 2 video game\r\n\tcolor *= toneMappingExposure;\r\n\treturn saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\r\n\r\n}\r\n\r\n// source: http://filmicgames.com/archives/75\r\nvec3 OptimizedCineonToneMapping( vec3 color ) {\r\n\r\n\t// optimized filmic operator by Jim Hejl and Richard Burgess-Dawson\r\n\tcolor *= toneMappingExposure;\r\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\r\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\r\n\r\n}\r\n"; - - var uv_pars_fragment = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\r\n\r\n\tvarying vec2 vUv;\r\n\r\n#endif"; - - var uv_pars_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\r\n\r\n\tvarying vec2 vUv;\r\n\tuniform mat3 uvTransform;\r\n\r\n#endif\r\n"; - - var uv_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\r\n\r\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\r\n\r\n#endif"; - - var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\r\n\r\n\tvarying vec2 vUv2;\r\n\r\n#endif"; - - var uv2_pars_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\r\n\r\n\tattribute vec2 uv2;\r\n\tvarying vec2 vUv2;\r\n\r\n#endif"; - - var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\r\n\r\n\tvUv2 = uv2;\r\n\r\n#endif"; - - var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\r\n\r\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\r\n\r\n#endif\r\n"; - - var cube_frag = "uniform samplerCube tCube;\r\nuniform float tFlip;\r\nuniform float opacity;\r\n\r\nvarying vec3 vWorldPosition;\r\n\r\nvoid main() {\r\n\r\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\r\n\tgl_FragColor.a *= opacity;\r\n\r\n}\r\n"; - - var cube_vert = "varying vec3 vWorldPosition;\r\n\r\n#include \r\n\r\nvoid main() {\r\n\r\n\tvWorldPosition = transformDirection( position, modelMatrix );\r\n\r\n\t#include \r\n\t#include \r\n\r\n\tgl_Position.z = gl_Position.w; // set z to camera.far\r\n\r\n}\r\n"; - - var depth_frag = "#if DEPTH_PACKING == 3200\r\n\r\n\tuniform float opacity;\r\n\r\n#endif\r\n\r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n\r\nvoid main() {\r\n\r\n\t#include \r\n\r\n\tvec4 diffuseColor = vec4( 1.0 );\r\n\r\n\t#if DEPTH_PACKING == 3200\r\n\r\n\t\tdiffuseColor.a = opacity;\r\n\r\n\t#endif\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n\t#include \r\n\r\n\t#if DEPTH_PACKING == 3200\r\n\r\n\t\tgl_FragColor = vec4( vec3( gl_FragCoord.z ), opacity );\r\n\r\n\t#elif DEPTH_PACKING == 3201\r\n\r\n\t\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\r\n\r\n\t#endif\r\n\r\n}\r\n"; - - var depth_vert = "#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n\r\nvoid main() {\r\n\r\n\t#include \r\n\r\n\t#include \r\n\r\n\t#ifdef USE_DISPLACEMENTMAP\r\n\r\n\t\t#include \r\n\t\t#include \r\n\t\t#include \r\n\r\n\t#endif\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n}\r\n"; - - var distanceRGBA_frag = "#define DISTANCE\r\n\r\nuniform vec3 referencePosition;\r\nuniform float nearDistance;\r\nuniform float farDistance;\r\nvarying vec3 vWorldPosition;\r\n\r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n\r\nvoid main () {\r\n\r\n\t#include \r\n\r\n\tvec4 diffuseColor = vec4( 1.0 );\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n\tfloat dist = length( vWorldPosition - referencePosition );\r\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\r\n\tdist = saturate( dist ); // clamp to [ 0, 1 ]\r\n\r\n\tgl_FragColor = packDepthToRGBA( dist );\r\n\r\n}\r\n"; - - var distanceRGBA_vert = "#define DISTANCE\r\n\r\nvarying vec3 vWorldPosition;\r\n\r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n\r\nvoid main() {\r\n\r\n\t#include \r\n\r\n\t#include \r\n\r\n\t#ifdef USE_DISPLACEMENTMAP\r\n\r\n\t\t#include \r\n\t\t#include \r\n\t\t#include \r\n\r\n\t#endif\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n\tvWorldPosition = worldPosition.xyz;\r\n\r\n}\r\n"; - - var equirect_frag = "uniform sampler2D tEquirect;\r\n\r\nvarying vec3 vWorldPosition;\r\n\r\n#include \r\n\r\nvoid main() {\r\n\r\n\tvec3 direction = normalize( vWorldPosition );\r\n\r\n\tvec2 sampleUV;\r\n\r\n\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\r\n\r\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\r\n\r\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\r\n\r\n}\r\n"; - - var equirect_vert = "varying vec3 vWorldPosition;\r\n\r\n#include \r\n\r\nvoid main() {\r\n\r\n\tvWorldPosition = transformDirection( position, modelMatrix );\r\n\r\n\t#include \r\n\t#include \r\n\r\n}\r\n"; - - var linedashed_frag = "uniform vec3 diffuse;\r\nuniform float opacity;\r\n\r\nuniform float dashSize;\r\nuniform float totalSize;\r\n\r\nvarying float vLineDistance;\r\n\r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n\r\nvoid main() {\r\n\r\n\t#include \r\n\r\n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\r\n\r\n\t\tdiscard;\r\n\r\n\t}\r\n\r\n\tvec3 outgoingLight = vec3( 0.0 );\r\n\tvec4 diffuseColor = vec4( diffuse, opacity );\r\n\r\n\t#include \r\n\t#include \r\n\r\n\toutgoingLight = diffuseColor.rgb; // simple shader\r\n\r\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n}\r\n"; - - var linedashed_vert = "uniform float scale;\r\nattribute float lineDistance;\r\n\r\nvarying float vLineDistance;\r\n\r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n\r\nvoid main() {\r\n\r\n\t#include \r\n\r\n\tvLineDistance = scale * lineDistance;\r\n\r\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\r\n\tgl_Position = projectionMatrix * mvPosition;\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n}\r\n"; - - var meshbasic_frag = "uniform vec3 diffuse;\r\nuniform float opacity;\r\n\r\n#ifndef FLAT_SHADED\r\n\r\n\tvarying vec3 vNormal;\r\n\r\n#endif\r\n\r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n\r\nvoid main() {\r\n\r\n\t#include \r\n\r\n\tvec4 diffuseColor = vec4( diffuse, opacity );\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\r\n\r\n\t// accumulation (baked indirect lighting only)\r\n\t#ifdef USE_LIGHTMAP\r\n\r\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\r\n\r\n\t#else\r\n\r\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\r\n\r\n\t#endif\r\n\r\n\t// modulation\r\n\t#include \r\n\r\n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\r\n\r\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\r\n\r\n\t#include \r\n\r\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n}\r\n"; - - var meshbasic_vert = "#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n\r\nvoid main() {\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n\t#ifdef USE_ENVMAP\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n\t#endif\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n}\r\n"; - - var meshlambert_frag = "uniform vec3 diffuse;\r\nuniform vec3 emissive;\r\nuniform float opacity;\r\n\r\nvarying vec3 vLightFront;\r\n\r\n#ifdef DOUBLE_SIDED\r\n\r\n\tvarying vec3 vLightBack;\r\n\r\n#endif\r\n\r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n\r\nvoid main() {\r\n\r\n\t#include \r\n\r\n\tvec4 diffuseColor = vec4( diffuse, opacity );\r\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\r\n\tvec3 totalEmissiveRadiance = emissive;\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n\t// accumulation\r\n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\r\n\r\n\t#include \r\n\r\n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\r\n\r\n\t#ifdef DOUBLE_SIDED\r\n\r\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\r\n\r\n\t#else\r\n\r\n\t\treflectedLight.directDiffuse = vLightFront;\r\n\r\n\t#endif\r\n\r\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\r\n\r\n\t// modulation\r\n\t#include \r\n\r\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\r\n\r\n\t#include \r\n\r\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n}\r\n"; - - var meshlambert_vert = "#define LAMBERT\r\n\r\nvarying vec3 vLightFront;\r\n\r\n#ifdef DOUBLE_SIDED\r\n\r\n\tvarying vec3 vLightBack;\r\n\r\n#endif\r\n\r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n\r\nvoid main() {\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n}\r\n"; - - var meshphong_frag = "#define PHONG\r\n\r\nuniform vec3 diffuse;\r\nuniform vec3 emissive;\r\nuniform vec3 specular;\r\nuniform float shininess;\r\nuniform float opacity;\r\n\r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n\r\nvoid main() {\r\n\r\n\t#include \r\n\r\n\tvec4 diffuseColor = vec4( diffuse, opacity );\r\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\r\n\tvec3 totalEmissiveRadiance = emissive;\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n\t// accumulation\r\n\t#include \r\n\t#include \r\n\r\n\t// modulation\r\n\t#include \r\n\r\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\r\n\r\n\t#include \r\n\r\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n}\r\n"; - - var meshphong_vert = "#define PHONG\r\n\r\nvarying vec3 vViewPosition;\r\n\r\n#ifndef FLAT_SHADED\r\n\r\n\tvarying vec3 vNormal;\r\n\r\n#endif\r\n\r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n\r\nvoid main() {\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n#ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED\r\n\r\n\tvNormal = normalize( transformedNormal );\r\n\r\n#endif\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n\tvViewPosition = - mvPosition.xyz;\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n}\r\n"; - - var meshphysical_frag = "#define PHYSICAL\r\n\r\nuniform vec3 diffuse;\r\nuniform vec3 emissive;\r\nuniform float roughness;\r\nuniform float metalness;\r\nuniform float opacity;\r\n\r\n#ifndef STANDARD\r\n\tuniform float clearCoat;\r\n\tuniform float clearCoatRoughness;\r\n#endif\r\n\r\nvarying vec3 vViewPosition;\r\n\r\n#ifndef FLAT_SHADED\r\n\r\n\tvarying vec3 vNormal;\r\n\r\n#endif\r\n\r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n\r\nvoid main() {\r\n\r\n\t#include \r\n\r\n\tvec4 diffuseColor = vec4( diffuse, opacity );\r\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\r\n\tvec3 totalEmissiveRadiance = emissive;\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n\t// accumulation\r\n\t#include \r\n\t#include \r\n\r\n\t// modulation\r\n\t#include \r\n\r\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\r\n\r\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n}\r\n"; - - var meshphysical_vert = "#define PHYSICAL\r\n\r\nvarying vec3 vViewPosition;\r\n\r\n#ifndef FLAT_SHADED\r\n\r\n\tvarying vec3 vNormal;\r\n\r\n#endif\r\n\r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n\r\nvoid main() {\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n#ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED\r\n\r\n\tvNormal = normalize( transformedNormal );\r\n\r\n#endif\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n\tvViewPosition = - mvPosition.xyz;\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n}\r\n"; - - var normal_frag = "#define NORMAL\r\n\r\nuniform float opacity;\r\n\r\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\r\n\r\n\tvarying vec3 vViewPosition;\r\n\r\n#endif\r\n\r\n#ifndef FLAT_SHADED\r\n\r\n\tvarying vec3 vNormal;\r\n\r\n#endif\r\n\r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n\r\nvoid main() {\r\n\r\n\t#include \r\n\t#include \r\n\r\n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\r\n\r\n}\r\n"; - - var normal_vert = "#define NORMAL\r\n\r\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\r\n\r\n\tvarying vec3 vViewPosition;\r\n\r\n#endif\r\n\r\n#ifndef FLAT_SHADED\r\n\r\n\tvarying vec3 vNormal;\r\n\r\n#endif\r\n\r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n\r\nvoid main() {\r\n\r\n\t#include \r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n#ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED\r\n\r\n\tvNormal = normalize( transformedNormal );\r\n\r\n#endif\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\r\n\r\n\tvViewPosition = - mvPosition.xyz;\r\n\r\n#endif\r\n\r\n}\r\n"; - - var points_frag = "uniform vec3 diffuse;\r\nuniform float opacity;\r\n\r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n\r\nvoid main() {\r\n\r\n\t#include \r\n\r\n\tvec3 outgoingLight = vec3( 0.0 );\r\n\tvec4 diffuseColor = vec4( diffuse, opacity );\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n\toutgoingLight = diffuseColor.rgb;\r\n\r\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n}\r\n"; - - var points_vert = "uniform float size;\r\nuniform float scale;\r\n\r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n\r\nvoid main() {\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n\t#ifdef USE_SIZEATTENUATION\r\n\t\tgl_PointSize = size * ( scale / - mvPosition.z );\r\n\t#else\r\n\t\tgl_PointSize = size;\r\n\t#endif\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n}\r\n"; - - var shadow_frag = "uniform vec3 color;\r\nuniform float opacity;\r\n\r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n#include \r\n\r\nvoid main() {\r\n\r\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\r\n\r\n\t#include \r\n\r\n}\r\n"; - - var shadow_vert = "#include \r\n#include \r\n\r\nvoid main() {\r\n\r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\t#include \r\n\r\n}\r\n"; - - var ShaderChunk = { - alphamap_fragment: alphamap_fragment, - alphamap_pars_fragment: alphamap_pars_fragment, - alphatest_fragment: alphatest_fragment, - aomap_fragment: aomap_fragment, - aomap_pars_fragment: aomap_pars_fragment, - begin_vertex: begin_vertex, - beginnormal_vertex: beginnormal_vertex, - bsdfs: bsdfs, - bumpmap_pars_fragment: bumpmap_pars_fragment, - clipping_planes_fragment: clipping_planes_fragment, - clipping_planes_pars_fragment: clipping_planes_pars_fragment, - clipping_planes_pars_vertex: clipping_planes_pars_vertex, - clipping_planes_vertex: clipping_planes_vertex, - color_fragment: color_fragment, - color_pars_fragment: color_pars_fragment, - color_pars_vertex: color_pars_vertex, - color_vertex: color_vertex, - common: common, - cube_uv_reflection_fragment: cube_uv_reflection_fragment, - defaultnormal_vertex: defaultnormal_vertex, - displacementmap_pars_vertex: displacementmap_pars_vertex, - displacementmap_vertex: displacementmap_vertex, - emissivemap_fragment: emissivemap_fragment, - emissivemap_pars_fragment: emissivemap_pars_fragment, - encodings_fragment: encodings_fragment, - encodings_pars_fragment: encodings_pars_fragment, - envmap_fragment: envmap_fragment, - envmap_pars_fragment: envmap_pars_fragment, - envmap_pars_vertex: envmap_pars_vertex, - envmap_vertex: envmap_vertex, - fog_vertex: fog_vertex, - fog_pars_vertex: fog_pars_vertex, - fog_fragment: fog_fragment, - fog_pars_fragment: fog_pars_fragment, - gradientmap_pars_fragment: gradientmap_pars_fragment, - lightmap_fragment: lightmap_fragment, - lightmap_pars_fragment: lightmap_pars_fragment, - lights_lambert_vertex: lights_lambert_vertex, - lights_pars: lights_pars, - lights_phong_fragment: lights_phong_fragment, - lights_phong_pars_fragment: lights_phong_pars_fragment, - lights_physical_fragment: lights_physical_fragment, - lights_physical_pars_fragment: lights_physical_pars_fragment, - lights_template: lights_template, - logdepthbuf_fragment: logdepthbuf_fragment, - logdepthbuf_pars_fragment: logdepthbuf_pars_fragment, - logdepthbuf_pars_vertex: logdepthbuf_pars_vertex, - logdepthbuf_vertex: logdepthbuf_vertex, - map_fragment: map_fragment, - map_pars_fragment: map_pars_fragment, - map_particle_fragment: map_particle_fragment, - map_particle_pars_fragment: map_particle_pars_fragment, - metalnessmap_fragment: metalnessmap_fragment, - metalnessmap_pars_fragment: metalnessmap_pars_fragment, - morphnormal_vertex: morphnormal_vertex, - morphtarget_pars_vertex: morphtarget_pars_vertex, - morphtarget_vertex: morphtarget_vertex, - normal_fragment: normal_fragment, - normalmap_pars_fragment: normalmap_pars_fragment, - packing: packing, - premultiplied_alpha_fragment: premultiplied_alpha_fragment, - project_vertex: project_vertex, - dithering_fragment: dithering_fragment, - dithering_pars_fragment: dithering_pars_fragment, - roughnessmap_fragment: roughnessmap_fragment, - roughnessmap_pars_fragment: roughnessmap_pars_fragment, - shadowmap_pars_fragment: shadowmap_pars_fragment, - shadowmap_pars_vertex: shadowmap_pars_vertex, - shadowmap_vertex: shadowmap_vertex, - shadowmask_pars_fragment: shadowmask_pars_fragment, - skinbase_vertex: skinbase_vertex, - skinning_pars_vertex: skinning_pars_vertex, - skinning_vertex: skinning_vertex, - skinnormal_vertex: skinnormal_vertex, - specularmap_fragment: specularmap_fragment, - specularmap_pars_fragment: specularmap_pars_fragment, - tonemapping_fragment: tonemapping_fragment, - tonemapping_pars_fragment: tonemapping_pars_fragment, - uv_pars_fragment: uv_pars_fragment, - uv_pars_vertex: uv_pars_vertex, - uv_vertex: uv_vertex, - uv2_pars_fragment: uv2_pars_fragment, - uv2_pars_vertex: uv2_pars_vertex, - uv2_vertex: uv2_vertex, - worldpos_vertex: worldpos_vertex, - - cube_frag: cube_frag, - cube_vert: cube_vert, - depth_frag: depth_frag, - depth_vert: depth_vert, - distanceRGBA_frag: distanceRGBA_frag, - distanceRGBA_vert: distanceRGBA_vert, - equirect_frag: equirect_frag, - equirect_vert: equirect_vert, - linedashed_frag: linedashed_frag, - linedashed_vert: linedashed_vert, - meshbasic_frag: meshbasic_frag, - meshbasic_vert: meshbasic_vert, - meshlambert_frag: meshlambert_frag, - meshlambert_vert: meshlambert_vert, - meshphong_frag: meshphong_frag, - meshphong_vert: meshphong_vert, - meshphysical_frag: meshphysical_frag, - meshphysical_vert: meshphysical_vert, - normal_frag: normal_frag, - normal_vert: normal_vert, - points_frag: points_frag, - points_vert: points_vert, - shadow_frag: shadow_frag, - shadow_vert: shadow_vert - }; - - var ShaderLib = { - - basic: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.specularmap, - UniformsLib.envmap, - UniformsLib.aomap, - UniformsLib.lightmap, - UniformsLib.fog - ] ), - - vertexShader: ShaderChunk.meshbasic_vert, - fragmentShader: ShaderChunk.meshbasic_frag - - }, - - lambert: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.specularmap, - UniformsLib.envmap, - UniformsLib.aomap, - UniformsLib.lightmap, - UniformsLib.emissivemap, - UniformsLib.fog, - UniformsLib.lights, - { - emissive: { value: new Color( 0x000000 ) } - } - ] ), - - vertexShader: ShaderChunk.meshlambert_vert, - fragmentShader: ShaderChunk.meshlambert_frag - - }, - - phong: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.specularmap, - UniformsLib.envmap, - UniformsLib.aomap, - UniformsLib.lightmap, - UniformsLib.emissivemap, - UniformsLib.bumpmap, - UniformsLib.normalmap, - UniformsLib.displacementmap, - UniformsLib.gradientmap, - UniformsLib.fog, - UniformsLib.lights, - { - emissive: { value: new Color( 0x000000 ) }, - specular: { value: new Color( 0x111111 ) }, - shininess: { value: 30 } - } - ] ), - - vertexShader: ShaderChunk.meshphong_vert, - fragmentShader: ShaderChunk.meshphong_frag - - }, - - standard: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.envmap, - UniformsLib.aomap, - UniformsLib.lightmap, - UniformsLib.emissivemap, - UniformsLib.bumpmap, - UniformsLib.normalmap, - UniformsLib.displacementmap, - UniformsLib.roughnessmap, - UniformsLib.metalnessmap, - UniformsLib.fog, - UniformsLib.lights, - { - emissive: { value: new Color( 0x000000 ) }, - roughness: { value: 0.5 }, - metalness: { value: 0.5 }, - envMapIntensity: { value: 1 } // temporary - } - ] ), - - vertexShader: ShaderChunk.meshphysical_vert, - fragmentShader: ShaderChunk.meshphysical_frag - - }, - - points: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.points, - UniformsLib.fog - ] ), - - vertexShader: ShaderChunk.points_vert, - fragmentShader: ShaderChunk.points_frag - - }, - - dashed: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.fog, - { - scale: { value: 1 }, - dashSize: { value: 1 }, - totalSize: { value: 2 } - } - ] ), - - vertexShader: ShaderChunk.linedashed_vert, - fragmentShader: ShaderChunk.linedashed_frag - - }, - - depth: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.displacementmap - ] ), - - vertexShader: ShaderChunk.depth_vert, - fragmentShader: ShaderChunk.depth_frag - - }, - - normal: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.bumpmap, - UniformsLib.normalmap, - UniformsLib.displacementmap, - { - opacity: { value: 1.0 } - } - ] ), - - vertexShader: ShaderChunk.normal_vert, - fragmentShader: ShaderChunk.normal_frag - - }, - - /* ------------------------------------------------------------------------- - // Cube map shader - ------------------------------------------------------------------------- */ - - cube: { - - uniforms: { - tCube: { value: null }, - tFlip: { value: - 1 }, - opacity: { value: 1.0 } - }, - - vertexShader: ShaderChunk.cube_vert, - fragmentShader: ShaderChunk.cube_frag - - }, - - equirect: { - - uniforms: { - tEquirect: { value: null }, - }, - - vertexShader: ShaderChunk.equirect_vert, - fragmentShader: ShaderChunk.equirect_frag - - }, - - distanceRGBA: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.common, - UniformsLib.displacementmap, - { - referencePosition: { value: new Vector3() }, - nearDistance: { value: 1 }, - farDistance: { value: 1000 } - } - ] ), - - vertexShader: ShaderChunk.distanceRGBA_vert, - fragmentShader: ShaderChunk.distanceRGBA_frag - - }, - - shadow: { - - uniforms: UniformsUtils.merge( [ - UniformsLib.lights, - UniformsLib.fog, - { - color: { value: new Color( 0x00000 ) }, - opacity: { value: 1.0 } - }, - ] ), - - vertexShader: ShaderChunk.shadow_vert, - fragmentShader: ShaderChunk.shadow_frag - - } - - }; - - ShaderLib.physical = { - - uniforms: UniformsUtils.merge( [ - ShaderLib.standard.uniforms, - { - clearCoat: { value: 0 }, - clearCoatRoughness: { value: 0 } - } - ] ), - - vertexShader: ShaderChunk.meshphysical_vert, - fragmentShader: ShaderChunk.meshphysical_frag - - }; - - function Box2( min, max ) { - - this.min = ( min !== undefined ) ? min : new Vector2( + Infinity, + Infinity ); - this.max = ( max !== undefined ) ? max : new Vector2( - Infinity, - Infinity ); - - } - - Object.assign( Box2.prototype, { - - set: function ( min, max ) { - - this.min.copy( min ); - this.max.copy( max ); - - return this; - - }, - - setFromPoints: function ( points ) { - - this.makeEmpty(); - - for ( var i = 0, il = points.length; i < il; i ++ ) { - - this.expandByPoint( points[ i ] ); - - } - - return this; - - }, - - setFromCenterAndSize: function () { - - var v1 = new Vector2(); - - return function setFromCenterAndSize( center, size ) { - - var halfSize = v1.copy( size ).multiplyScalar( 0.5 ); - this.min.copy( center ).sub( halfSize ); - this.max.copy( center ).add( halfSize ); - - return this; - - }; - - }(), - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( box ) { - - this.min.copy( box.min ); - this.max.copy( box.max ); - - return this; - - }, - - makeEmpty: function () { - - this.min.x = this.min.y = + Infinity; - this.max.x = this.max.y = - Infinity; - - return this; - - }, - - isEmpty: function () { - - // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes - - return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ); - - }, - - getCenter: function ( optionalTarget ) { - - var result = optionalTarget || new Vector2(); - return this.isEmpty() ? result.set( 0, 0 ) : result.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); - - }, - - getSize: function ( optionalTarget ) { - - var result = optionalTarget || new Vector2(); - return this.isEmpty() ? result.set( 0, 0 ) : result.subVectors( this.max, this.min ); - - }, - - expandByPoint: function ( point ) { - - this.min.min( point ); - this.max.max( point ); - - return this; - - }, - - expandByVector: function ( vector ) { - - this.min.sub( vector ); - this.max.add( vector ); - - return this; - - }, - - expandByScalar: function ( scalar ) { - - this.min.addScalar( - scalar ); - this.max.addScalar( scalar ); - - return this; - - }, - - containsPoint: function ( point ) { - - return point.x < this.min.x || point.x > this.max.x || - point.y < this.min.y || point.y > this.max.y ? false : true; - - }, - - containsBox: function ( box ) { - - return this.min.x <= box.min.x && box.max.x <= this.max.x && - this.min.y <= box.min.y && box.max.y <= this.max.y; - - }, - - getParameter: function ( point, optionalTarget ) { - - // This can potentially have a divide by zero if the box - // has a size dimension of 0. - - var result = optionalTarget || new Vector2(); - - return result.set( - ( point.x - this.min.x ) / ( this.max.x - this.min.x ), - ( point.y - this.min.y ) / ( this.max.y - this.min.y ) - ); - - }, - - intersectsBox: function ( box ) { - - // using 4 splitting planes to rule out intersections - - return box.max.x < this.min.x || box.min.x > this.max.x || - box.max.y < this.min.y || box.min.y > this.max.y ? false : true; - - }, - - clampPoint: function ( point, optionalTarget ) { - - var result = optionalTarget || new Vector2(); - return result.copy( point ).clamp( this.min, this.max ); - - }, - - distanceToPoint: function () { - - var v1 = new Vector2(); - - return function distanceToPoint( point ) { - - var clampedPoint = v1.copy( point ).clamp( this.min, this.max ); - return clampedPoint.sub( point ).length(); - - }; - - }(), - - intersect: function ( box ) { - - this.min.max( box.min ); - this.max.min( box.max ); - - return this; - - }, - - union: function ( box ) { - - this.min.min( box.min ); - this.max.max( box.max ); - - return this; - - }, - - translate: function ( offset ) { - - this.min.add( offset ); - this.max.add( offset ); - - return this; - - }, - - equals: function ( box ) { - - return box.min.equals( this.min ) && box.max.equals( this.max ); - - } - - } ); - - /** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - */ - - function WebGLFlareRenderer( renderer, gl, state, textures, capabilities ) { - - var vertexBuffer, elementBuffer; - var shader, program, attributes, uniforms; - - var tempTexture, occlusionTexture; - - function init() { - - var vertices = new Float32Array( [ - - 1, - 1, 0, 0, - 1, - 1, 1, 0, - 1, 1, 1, 1, - - 1, 1, 0, 1 - ] ); - - var faces = new Uint16Array( [ - 0, 1, 2, - 0, 2, 3 - ] ); - - // buffers - - vertexBuffer = gl.createBuffer(); - elementBuffer = gl.createBuffer(); - - gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer ); - gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW ); - - gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer ); - gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW ); - - // textures - - tempTexture = gl.createTexture(); - occlusionTexture = gl.createTexture(); - - state.bindTexture( gl.TEXTURE_2D, tempTexture ); - gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGB, 16, 16, 0, gl.RGB, gl.UNSIGNED_BYTE, null ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); - - state.bindTexture( gl.TEXTURE_2D, occlusionTexture ); - gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); - - shader = { - - vertexShader: [ - - 'uniform lowp int renderType;', - - 'uniform vec3 screenPosition;', - 'uniform vec2 scale;', - 'uniform float rotation;', - - 'uniform sampler2D occlusionMap;', - - 'attribute vec2 position;', - 'attribute vec2 uv;', - - 'varying vec2 vUV;', - 'varying float vVisibility;', - - 'void main() {', - - ' vUV = uv;', - - ' vec2 pos = position;', - - ' if ( renderType == 2 ) {', - - ' vec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );', - ' visibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );', - - ' vVisibility = visibility.r / 9.0;', - ' vVisibility *= 1.0 - visibility.g / 9.0;', - ' vVisibility *= visibility.b / 9.0;', - ' vVisibility *= 1.0 - visibility.a / 9.0;', - - ' pos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;', - ' pos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;', - - ' }', - - ' gl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );', - - '}' - - ].join( '\n' ), - - fragmentShader: [ - - 'uniform lowp int renderType;', - - 'uniform sampler2D map;', - 'uniform float opacity;', - 'uniform vec3 color;', - - 'varying vec2 vUV;', - 'varying float vVisibility;', - - 'void main() {', - - // pink square - - ' if ( renderType == 0 ) {', - - ' gl_FragColor = vec4( 1.0, 0.0, 1.0, 0.0 );', - - // restore - - ' } else if ( renderType == 1 ) {', - - ' gl_FragColor = texture2D( map, vUV );', - - // flare - - ' } else {', - - ' vec4 texture = texture2D( map, vUV );', - ' texture.a *= opacity * vVisibility;', - ' gl_FragColor = texture;', - ' gl_FragColor.rgb *= color;', - - ' }', - - '}' - - ].join( '\n' ) - - }; - - program = createProgram( shader ); - - attributes = { - vertex: gl.getAttribLocation( program, 'position' ), - uv: gl.getAttribLocation( program, 'uv' ) - }; - - uniforms = { - renderType: gl.getUniformLocation( program, 'renderType' ), - map: gl.getUniformLocation( program, 'map' ), - occlusionMap: gl.getUniformLocation( program, 'occlusionMap' ), - opacity: gl.getUniformLocation( program, 'opacity' ), - color: gl.getUniformLocation( program, 'color' ), - scale: gl.getUniformLocation( program, 'scale' ), - rotation: gl.getUniformLocation( program, 'rotation' ), - screenPosition: gl.getUniformLocation( program, 'screenPosition' ) - }; - - } - - /* - * Render lens flares - * Method: renders 16x16 0xff00ff-colored points scattered over the light source area, - * reads these back and calculates occlusion. - */ - - this.render = function ( flares, scene, camera, viewport ) { - - if ( flares.length === 0 ) return; - - var tempPosition = new Vector3(); - - var invAspect = viewport.w / viewport.z, - halfViewportWidth = viewport.z * 0.5, - halfViewportHeight = viewport.w * 0.5; - - var size = 16 / viewport.w, - scale = new Vector2( size * invAspect, size ); - - var screenPosition = new Vector3( 1, 1, 0 ), - screenPositionPixels = new Vector2( 1, 1 ); - - var validArea = new Box2(); - - validArea.min.set( viewport.x, viewport.y ); - validArea.max.set( viewport.x + ( viewport.z - 16 ), viewport.y + ( viewport.w - 16 ) ); - - if ( program === undefined ) { - - init(); - - } - - state.useProgram( program ); - - state.initAttributes(); - state.enableAttribute( attributes.vertex ); - state.enableAttribute( attributes.uv ); - state.disableUnusedAttributes(); - - // loop through all lens flares to update their occlusion and positions - // setup gl and common used attribs/uniforms - - gl.uniform1i( uniforms.occlusionMap, 0 ); - gl.uniform1i( uniforms.map, 1 ); - - gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer ); - gl.vertexAttribPointer( attributes.vertex, 2, gl.FLOAT, false, 2 * 8, 0 ); - gl.vertexAttribPointer( attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8 ); - - gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer ); - - state.disable( gl.CULL_FACE ); - state.buffers.depth.setMask( false ); - - for ( var i = 0, l = flares.length; i < l; i ++ ) { - - size = 16 / viewport.w; - scale.set( size * invAspect, size ); - - // calc object screen position - - var flare = flares[ i ]; - - tempPosition.set( flare.matrixWorld.elements[ 12 ], flare.matrixWorld.elements[ 13 ], flare.matrixWorld.elements[ 14 ] ); - - tempPosition.applyMatrix4( camera.matrixWorldInverse ); - tempPosition.applyMatrix4( camera.projectionMatrix ); - - // setup arrays for gl programs - - screenPosition.copy( tempPosition ); - - // horizontal and vertical coordinate of the lower left corner of the pixels to copy - - screenPositionPixels.x = viewport.x + ( screenPosition.x * halfViewportWidth ) + halfViewportWidth - 8; - screenPositionPixels.y = viewport.y + ( screenPosition.y * halfViewportHeight ) + halfViewportHeight - 8; - - // screen cull - - if ( validArea.containsPoint( screenPositionPixels ) === true ) { - - // save current RGB to temp texture - - state.activeTexture( gl.TEXTURE0 ); - state.bindTexture( gl.TEXTURE_2D, null ); - state.activeTexture( gl.TEXTURE1 ); - state.bindTexture( gl.TEXTURE_2D, tempTexture ); - gl.copyTexImage2D( gl.TEXTURE_2D, 0, gl.RGB, screenPositionPixels.x, screenPositionPixels.y, 16, 16, 0 ); - - - // render pink quad - - gl.uniform1i( uniforms.renderType, 0 ); - gl.uniform2f( uniforms.scale, scale.x, scale.y ); - gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z ); - - state.disable( gl.BLEND ); - state.enable( gl.DEPTH_TEST ); - - gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); - - - // copy result to occlusionMap - - state.activeTexture( gl.TEXTURE0 ); - state.bindTexture( gl.TEXTURE_2D, occlusionTexture ); - gl.copyTexImage2D( gl.TEXTURE_2D, 0, gl.RGBA, screenPositionPixels.x, screenPositionPixels.y, 16, 16, 0 ); - - - // restore graphics - - gl.uniform1i( uniforms.renderType, 1 ); - state.disable( gl.DEPTH_TEST ); - - state.activeTexture( gl.TEXTURE1 ); - state.bindTexture( gl.TEXTURE_2D, tempTexture ); - gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); - - - // update object positions - - flare.positionScreen.copy( screenPosition ); - - if ( flare.customUpdateCallback ) { - - flare.customUpdateCallback( flare ); - - } else { - - flare.updateLensFlares(); - - } - - // render flares - - gl.uniform1i( uniforms.renderType, 2 ); - state.enable( gl.BLEND ); - - for ( var j = 0, jl = flare.lensFlares.length; j < jl; j ++ ) { - - var sprite = flare.lensFlares[ j ]; - - if ( sprite.opacity > 0.001 && sprite.scale > 0.001 ) { - - screenPosition.x = sprite.x; - screenPosition.y = sprite.y; - screenPosition.z = sprite.z; - - size = sprite.size * sprite.scale / viewport.w; - - scale.x = size * invAspect; - scale.y = size; - - gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z ); - gl.uniform2f( uniforms.scale, scale.x, scale.y ); - gl.uniform1f( uniforms.rotation, sprite.rotation ); - - gl.uniform1f( uniforms.opacity, sprite.opacity ); - gl.uniform3f( uniforms.color, sprite.color.r, sprite.color.g, sprite.color.b ); - - state.setBlending( sprite.blending, sprite.blendEquation, sprite.blendSrc, sprite.blendDst ); - - textures.setTexture2D( sprite.texture, 1 ); - - gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); - - } - - } - - } - - } - - // restore gl - - state.enable( gl.CULL_FACE ); - state.enable( gl.DEPTH_TEST ); - state.buffers.depth.setMask( true ); - - state.reset(); - - }; - - function createProgram( shader ) { - - var program = gl.createProgram(); - - var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER ); - var vertexShader = gl.createShader( gl.VERTEX_SHADER ); - - var prefix = 'precision ' + capabilities.precision + ' float;\n'; - - gl.shaderSource( fragmentShader, prefix + shader.fragmentShader ); - gl.shaderSource( vertexShader, prefix + shader.vertexShader ); - - gl.compileShader( fragmentShader ); - gl.compileShader( vertexShader ); - - gl.attachShader( program, fragmentShader ); - gl.attachShader( program, vertexShader ); - - gl.linkProgram( program ); - - return program; - - } - - } - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { - - Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); - - this.needsUpdate = true; - - } - - CanvasTexture.prototype = Object.create( Texture.prototype ); - CanvasTexture.prototype.constructor = CanvasTexture; - - /** - * @author mikael emtinger / http://gomo.se/ - * @author alteredq / http://alteredqualia.com/ - */ - - function WebGLSpriteRenderer( renderer, gl, state, textures, capabilities ) { - - var vertexBuffer, elementBuffer; - var program, attributes, uniforms; - - var texture; - - // decompose matrixWorld - - var spritePosition = new Vector3(); - var spriteRotation = new Quaternion(); - var spriteScale = new Vector3(); - - function init() { - - var vertices = new Float32Array( [ - - 0.5, - 0.5, 0, 0, - 0.5, - 0.5, 1, 0, - 0.5, 0.5, 1, 1, - - 0.5, 0.5, 0, 1 - ] ); - - var faces = new Uint16Array( [ - 0, 1, 2, - 0, 2, 3 - ] ); - - vertexBuffer = gl.createBuffer(); - elementBuffer = gl.createBuffer(); - - gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer ); - gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW ); - - gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer ); - gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW ); - - program = createProgram(); - - attributes = { - position: gl.getAttribLocation( program, 'position' ), - uv: gl.getAttribLocation( program, 'uv' ) - }; - - uniforms = { - uvOffset: gl.getUniformLocation( program, 'uvOffset' ), - uvScale: gl.getUniformLocation( program, 'uvScale' ), - - rotation: gl.getUniformLocation( program, 'rotation' ), - scale: gl.getUniformLocation( program, 'scale' ), - - color: gl.getUniformLocation( program, 'color' ), - map: gl.getUniformLocation( program, 'map' ), - opacity: gl.getUniformLocation( program, 'opacity' ), - - modelViewMatrix: gl.getUniformLocation( program, 'modelViewMatrix' ), - projectionMatrix: gl.getUniformLocation( program, 'projectionMatrix' ), - - fogType: gl.getUniformLocation( program, 'fogType' ), - fogDensity: gl.getUniformLocation( program, 'fogDensity' ), - fogNear: gl.getUniformLocation( program, 'fogNear' ), - fogFar: gl.getUniformLocation( program, 'fogFar' ), - fogColor: gl.getUniformLocation( program, 'fogColor' ), - fogDepth: gl.getUniformLocation( program, 'fogDepth' ), - - alphaTest: gl.getUniformLocation( program, 'alphaTest' ) - }; - - var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); - canvas.width = 8; - canvas.height = 8; - - var context = canvas.getContext( '2d' ); - context.fillStyle = 'white'; - context.fillRect( 0, 0, 8, 8 ); - - texture = new CanvasTexture( canvas ); - - } - - this.render = function ( sprites, scene, camera ) { - - if ( sprites.length === 0 ) return; - - // setup gl - - if ( program === undefined ) { - - init(); - - } - - state.useProgram( program ); - - state.initAttributes(); - state.enableAttribute( attributes.position ); - state.enableAttribute( attributes.uv ); - state.disableUnusedAttributes(); - - state.disable( gl.CULL_FACE ); - state.enable( gl.BLEND ); - - gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer ); - gl.vertexAttribPointer( attributes.position, 2, gl.FLOAT, false, 2 * 8, 0 ); - gl.vertexAttribPointer( attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8 ); - - gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer ); - - gl.uniformMatrix4fv( uniforms.projectionMatrix, false, camera.projectionMatrix.elements ); - - state.activeTexture( gl.TEXTURE0 ); - gl.uniform1i( uniforms.map, 0 ); - - var oldFogType = 0; - var sceneFogType = 0; - var fog = scene.fog; - - if ( fog ) { - - gl.uniform3f( uniforms.fogColor, fog.color.r, fog.color.g, fog.color.b ); - - if ( fog.isFog ) { - - gl.uniform1f( uniforms.fogNear, fog.near ); - gl.uniform1f( uniforms.fogFar, fog.far ); - - gl.uniform1i( uniforms.fogType, 1 ); - oldFogType = 1; - sceneFogType = 1; - - } else if ( fog.isFogExp2 ) { - - gl.uniform1f( uniforms.fogDensity, fog.density ); - - gl.uniform1i( uniforms.fogType, 2 ); - oldFogType = 2; - sceneFogType = 2; - - } - - } else { - - gl.uniform1i( uniforms.fogType, 0 ); - oldFogType = 0; - sceneFogType = 0; - - } - - - // update positions and sort - - for ( var i = 0, l = sprites.length; i < l; i ++ ) { - - var sprite = sprites[ i ]; - - sprite.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, sprite.matrixWorld ); - sprite.z = - sprite.modelViewMatrix.elements[ 14 ]; - - } - - sprites.sort( painterSortStable ); - - // render all sprites - - var scale = []; - - for ( var i = 0, l = sprites.length; i < l; i ++ ) { - - var sprite = sprites[ i ]; - var material = sprite.material; - - if ( material.visible === false ) continue; - - sprite.onBeforeRender( renderer, scene, camera, undefined, material, undefined ); - - gl.uniform1f( uniforms.alphaTest, material.alphaTest ); - gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite.modelViewMatrix.elements ); - - sprite.matrixWorld.decompose( spritePosition, spriteRotation, spriteScale ); - - scale[ 0 ] = spriteScale.x; - scale[ 1 ] = spriteScale.y; - - var fogType = 0; - - if ( scene.fog && material.fog ) { - - fogType = sceneFogType; - - } - - if ( oldFogType !== fogType ) { - - gl.uniform1i( uniforms.fogType, fogType ); - oldFogType = fogType; - - } - - if ( material.map !== null ) { - - gl.uniform2f( uniforms.uvOffset, material.map.offset.x, material.map.offset.y ); - gl.uniform2f( uniforms.uvScale, material.map.repeat.x, material.map.repeat.y ); - - } else { - - gl.uniform2f( uniforms.uvOffset, 0, 0 ); - gl.uniform2f( uniforms.uvScale, 1, 1 ); - - } - - gl.uniform1f( uniforms.opacity, material.opacity ); - gl.uniform3f( uniforms.color, material.color.r, material.color.g, material.color.b ); - - gl.uniform1f( uniforms.rotation, material.rotation ); - gl.uniform2fv( uniforms.scale, scale ); - - state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha ); - state.buffers.depth.setTest( material.depthTest ); - state.buffers.depth.setMask( material.depthWrite ); - state.buffers.color.setMask( material.colorWrite ); - - textures.setTexture2D( material.map || texture, 0 ); - - gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); - - sprite.onAfterRender( renderer, scene, camera, undefined, material, undefined ); - - } - - // restore gl - - state.enable( gl.CULL_FACE ); - - state.reset(); - - }; - - function createProgram() { - - var program = gl.createProgram(); - - var vertexShader = gl.createShader( gl.VERTEX_SHADER ); - var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER ); - - gl.shaderSource( vertexShader, [ - - 'precision ' + capabilities.precision + ' float;', - - '#define SHADER_NAME ' + 'SpriteMaterial', - - 'uniform mat4 modelViewMatrix;', - 'uniform mat4 projectionMatrix;', - 'uniform float rotation;', - 'uniform vec2 scale;', - 'uniform vec2 uvOffset;', - 'uniform vec2 uvScale;', - - 'attribute vec2 position;', - 'attribute vec2 uv;', - - 'varying vec2 vUV;', - 'varying float fogDepth;', - - 'void main() {', - - ' vUV = uvOffset + uv * uvScale;', - - ' vec2 alignedPosition = position * scale;', - - ' vec2 rotatedPosition;', - ' rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;', - ' rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;', - - ' vec4 mvPosition;', - - ' mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );', - ' mvPosition.xy += rotatedPosition;', - - ' gl_Position = projectionMatrix * mvPosition;', - - ' fogDepth = - mvPosition.z;', - - '}' - - ].join( '\n' ) ); - - gl.shaderSource( fragmentShader, [ - - 'precision ' + capabilities.precision + ' float;', - - '#define SHADER_NAME ' + 'SpriteMaterial', - - 'uniform vec3 color;', - 'uniform sampler2D map;', - 'uniform float opacity;', - - 'uniform int fogType;', - 'uniform vec3 fogColor;', - 'uniform float fogDensity;', - 'uniform float fogNear;', - 'uniform float fogFar;', - 'uniform float alphaTest;', - - 'varying vec2 vUV;', - 'varying float fogDepth;', - - 'void main() {', - - ' vec4 texture = texture2D( map, vUV );', - - ' gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );', - - ' if ( gl_FragColor.a < alphaTest ) discard;', - - ' if ( fogType > 0 ) {', - - ' float fogFactor = 0.0;', - - ' if ( fogType == 1 ) {', - - ' fogFactor = smoothstep( fogNear, fogFar, fogDepth );', - - ' } else {', - - ' const float LOG2 = 1.442695;', - ' fogFactor = exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 );', - ' fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );', - - ' }', - - ' gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );', - - ' }', - - '}' - - ].join( '\n' ) ); - - gl.compileShader( vertexShader ); - gl.compileShader( fragmentShader ); - - gl.attachShader( program, vertexShader ); - gl.attachShader( program, fragmentShader ); - - gl.linkProgram( program ); - - return program; - - } - - function painterSortStable( a, b ) { - - if ( a.renderOrder !== b.renderOrder ) { - - return a.renderOrder - b.renderOrder; - - } else if ( a.z !== b.z ) { - - return b.z - a.z; - - } else { - - return b.id - a.id; - - } - - } - - } - - function Frustum( p0, p1, p2, p3, p4, p5 ) { - - this.planes = [ - - ( p0 !== undefined ) ? p0 : new Plane(), - ( p1 !== undefined ) ? p1 : new Plane(), - ( p2 !== undefined ) ? p2 : new Plane(), - ( p3 !== undefined ) ? p3 : new Plane(), - ( p4 !== undefined ) ? p4 : new Plane(), - ( p5 !== undefined ) ? p5 : new Plane() - - ]; - - } - - Object.assign( Frustum.prototype, { - - set: function ( p0, p1, p2, p3, p4, p5 ) { - - var planes = this.planes; - - planes[ 0 ].copy( p0 ); - planes[ 1 ].copy( p1 ); - planes[ 2 ].copy( p2 ); - planes[ 3 ].copy( p3 ); - planes[ 4 ].copy( p4 ); - planes[ 5 ].copy( p5 ); - - return this; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( frustum ) { - - var planes = this.planes; - - for ( var i = 0; i < 6; i ++ ) { - - planes[ i ].copy( frustum.planes[ i ] ); - - } - - return this; - - }, - - setFromMatrix: function ( m ) { - - var planes = this.planes; - var me = m.elements; - var me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ]; - var me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ]; - var me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ]; - var me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ]; - - planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize(); - planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize(); - planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize(); - planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize(); - planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize(); - planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize(); - - return this; - - }, - - intersectsObject: function () { - - var sphere = new Sphere(); - - return function intersectsObject( object ) { - - var geometry = object.geometry; - - if ( geometry.boundingSphere === null ) - geometry.computeBoundingSphere(); - - sphere.copy( geometry.boundingSphere ) - .applyMatrix4( object.matrixWorld ); - - return this.intersectsSphere( sphere ); - - }; - - }(), - - intersectsSprite: function () { - - var sphere = new Sphere(); - - return function intersectsSprite( sprite ) { - - sphere.center.set( 0, 0, 0 ); - sphere.radius = 0.7071067811865476; - sphere.applyMatrix4( sprite.matrixWorld ); - - return this.intersectsSphere( sphere ); - - }; - - }(), - - intersectsSphere: function ( sphere ) { - - var planes = this.planes; - var center = sphere.center; - var negRadius = - sphere.radius; - - for ( var i = 0; i < 6; i ++ ) { - - var distance = planes[ i ].distanceToPoint( center ); - - if ( distance < negRadius ) { - - return false; - - } - - } - - return true; - - }, - - intersectsBox: function () { - - var p1 = new Vector3(), - p2 = new Vector3(); - - return function intersectsBox( box ) { - - var planes = this.planes; - - for ( var i = 0; i < 6; i ++ ) { - - var plane = planes[ i ]; - - p1.x = plane.normal.x > 0 ? box.min.x : box.max.x; - p2.x = plane.normal.x > 0 ? box.max.x : box.min.x; - p1.y = plane.normal.y > 0 ? box.min.y : box.max.y; - p2.y = plane.normal.y > 0 ? box.max.y : box.min.y; - p1.z = plane.normal.z > 0 ? box.min.z : box.max.z; - p2.z = plane.normal.z > 0 ? box.max.z : box.min.z; - - var d1 = plane.distanceToPoint( p1 ); - var d2 = plane.distanceToPoint( p2 ); - - // if both outside plane, no intersection - - if ( d1 < 0 && d2 < 0 ) { - - return false; - - } - - } - - return true; - - }; - - }(), - - containsPoint: function ( point ) { - - var planes = this.planes; - - for ( var i = 0; i < 6; i ++ ) { - - if ( planes[ i ].distanceToPoint( point ) < 0 ) { - - return false; - - } - - } - - return true; - - } - - } ); - - /** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - */ - - function WebGLShadowMap( _renderer, _objects, maxTextureSize ) { - - var _frustum = new Frustum(), - _projScreenMatrix = new Matrix4(), - - _shadowMapSize = new Vector2(), - _maxShadowMapSize = new Vector2( maxTextureSize, maxTextureSize ), - - _lookTarget = new Vector3(), - _lightPositionWorld = new Vector3(), - - _MorphingFlag = 1, - _SkinningFlag = 2, - - _NumberOfMaterialVariants = ( _MorphingFlag | _SkinningFlag ) + 1, - - _depthMaterials = new Array( _NumberOfMaterialVariants ), - _distanceMaterials = new Array( _NumberOfMaterialVariants ), - - _materialCache = {}; - - var cubeDirections = [ - new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ), - new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 ) - ]; - - var cubeUps = [ - new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), - new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 ) - ]; - - var cube2DViewPorts = [ - new Vector4(), new Vector4(), new Vector4(), - new Vector4(), new Vector4(), new Vector4() - ]; - - // init - - for ( var i = 0; i !== _NumberOfMaterialVariants; ++ i ) { - - var useMorphing = ( i & _MorphingFlag ) !== 0; - var useSkinning = ( i & _SkinningFlag ) !== 0; - - var depthMaterial = new MeshDepthMaterial( { - - depthPacking: RGBADepthPacking, - - morphTargets: useMorphing, - skinning: useSkinning - - } ); - - _depthMaterials[ i ] = depthMaterial; - - // - - var distanceMaterial = new MeshDistanceMaterial( { - - morphTargets: useMorphing, - skinning: useSkinning - - } ); - - _distanceMaterials[ i ] = distanceMaterial; - - } - - // - - var scope = this; - - this.enabled = false; - - this.autoUpdate = true; - this.needsUpdate = false; - - this.type = PCFShadowMap; - - this.renderReverseSided = true; - this.renderSingleSided = true; - - this.render = function ( lights, scene, camera ) { - - if ( scope.enabled === false ) return; - if ( scope.autoUpdate === false && scope.needsUpdate === false ) return; - - if ( lights.length === 0 ) return; - - // TODO Clean up (needed in case of contextlost) - var _gl = _renderer.context; - var _state = _renderer.state; - - // Set GL state for depth map. - _state.disable( _gl.BLEND ); - _state.buffers.color.setClear( 1, 1, 1, 1 ); - _state.buffers.depth.setTest( true ); - _state.setScissorTest( false ); - - // render depth map - - var faceCount; - - for ( var i = 0, il = lights.length; i < il; i ++ ) { - - var light = lights[ i ]; - var shadow = light.shadow; - var isPointLight = light && light.isPointLight; - - if ( shadow === undefined ) { - - console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' ); - continue; - - } - - var shadowCamera = shadow.camera; - - _shadowMapSize.copy( shadow.mapSize ); - _shadowMapSize.min( _maxShadowMapSize ); - - if ( isPointLight ) { - - var vpWidth = _shadowMapSize.x; - var vpHeight = _shadowMapSize.y; - - // These viewports map a cube-map onto a 2D texture with the - // following orientation: - // - // xzXZ - // y Y - // - // X - Positive x direction - // x - Negative x direction - // Y - Positive y direction - // y - Negative y direction - // Z - Positive z direction - // z - Negative z direction - - // positive X - cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight ); - // negative X - cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight ); - // positive Z - cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight ); - // negative Z - cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight ); - // positive Y - cube2DViewPorts[ 4 ].set( vpWidth * 3, 0, vpWidth, vpHeight ); - // negative Y - cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight ); - - _shadowMapSize.x *= 4.0; - _shadowMapSize.y *= 2.0; - - } - - if ( shadow.map === null ) { - - var pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat }; - - shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars ); - shadow.map.texture.name = light.name + ".shadowMap"; - - shadowCamera.updateProjectionMatrix(); - - } - - if ( shadow.isSpotLightShadow ) { - - shadow.update( light ); - - } - - var shadowMap = shadow.map; - var shadowMatrix = shadow.matrix; - - _lightPositionWorld.setFromMatrixPosition( light.matrixWorld ); - shadowCamera.position.copy( _lightPositionWorld ); - - if ( isPointLight ) { - - faceCount = 6; - - // for point lights we set the shadow matrix to be a translation-only matrix - // equal to inverse of the light's position - - shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z ); - - } else { - - faceCount = 1; - - _lookTarget.setFromMatrixPosition( light.target.matrixWorld ); - shadowCamera.lookAt( _lookTarget ); - shadowCamera.updateMatrixWorld(); - - // compute shadow matrix - - shadowMatrix.set( - 0.5, 0.0, 0.0, 0.5, - 0.0, 0.5, 0.0, 0.5, - 0.0, 0.0, 0.5, 0.5, - 0.0, 0.0, 0.0, 1.0 - ); - - shadowMatrix.multiply( shadowCamera.projectionMatrix ); - shadowMatrix.multiply( shadowCamera.matrixWorldInverse ); - - } - - _renderer.setRenderTarget( shadowMap ); - _renderer.clear(); - - // render shadow map for each cube face (if omni-directional) or - // run a single pass if not - - for ( var face = 0; face < faceCount; face ++ ) { - - if ( isPointLight ) { - - _lookTarget.copy( shadowCamera.position ); - _lookTarget.add( cubeDirections[ face ] ); - shadowCamera.up.copy( cubeUps[ face ] ); - shadowCamera.lookAt( _lookTarget ); - shadowCamera.updateMatrixWorld(); - - var vpDimensions = cube2DViewPorts[ face ]; - _state.viewport( vpDimensions ); - - } - - // update camera matrices and frustum - - _projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse ); - _frustum.setFromMatrix( _projScreenMatrix ); - - // set object matrices & frustum culling - - renderObject( scene, camera, shadowCamera, isPointLight ); - - } - - } - - scope.needsUpdate = false; - - }; - - function getDepthMaterial( object, material, isPointLight, lightPositionWorld, shadowCameraNear, shadowCameraFar ) { - - var geometry = object.geometry; - - var result = null; - - var materialVariants = _depthMaterials; - var customMaterial = object.customDepthMaterial; - - if ( isPointLight ) { - - materialVariants = _distanceMaterials; - customMaterial = object.customDistanceMaterial; - - } - - if ( ! customMaterial ) { - - var useMorphing = false; - - if ( material.morphTargets ) { - - if ( geometry && geometry.isBufferGeometry ) { - - useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0; - - } else if ( geometry && geometry.isGeometry ) { - - useMorphing = geometry.morphTargets && geometry.morphTargets.length > 0; - - } - - } - - if ( object.isSkinnedMesh && material.skinning === false ) { - - console.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object ); - - } - - var useSkinning = object.isSkinnedMesh && material.skinning; - - var variantIndex = 0; - - if ( useMorphing ) variantIndex |= _MorphingFlag; - if ( useSkinning ) variantIndex |= _SkinningFlag; - - result = materialVariants[ variantIndex ]; - - } else { - - result = customMaterial; - - } - - if ( _renderer.localClippingEnabled && - material.clipShadows === true && - material.clippingPlanes.length !== 0 ) { - - // in this case we need a unique material instance reflecting the - // appropriate state - - var keyA = result.uuid, keyB = material.uuid; - - var materialsForVariant = _materialCache[ keyA ]; - - if ( materialsForVariant === undefined ) { - - materialsForVariant = {}; - _materialCache[ keyA ] = materialsForVariant; - - } - - var cachedMaterial = materialsForVariant[ keyB ]; - - if ( cachedMaterial === undefined ) { - - cachedMaterial = result.clone(); - materialsForVariant[ keyB ] = cachedMaterial; - - } - - result = cachedMaterial; - - } - - result.visible = material.visible; - result.wireframe = material.wireframe; - - var side = material.side; - - if ( scope.renderSingleSided && side == DoubleSide ) { - - side = FrontSide; - - } - - if ( scope.renderReverseSided ) { - - if ( side === FrontSide ) side = BackSide; - else if ( side === BackSide ) side = FrontSide; - - } - - result.side = side; - - result.clipShadows = material.clipShadows; - result.clippingPlanes = material.clippingPlanes; - result.clipIntersection = material.clipIntersection; - - result.wireframeLinewidth = material.wireframeLinewidth; - result.linewidth = material.linewidth; - - if ( isPointLight && result.isMeshDistanceMaterial ) { - - result.referencePosition.copy( lightPositionWorld ); - result.nearDistance = shadowCameraNear; - result.farDistance = shadowCameraFar; - - } - - return result; - - } - - function renderObject( object, camera, shadowCamera, isPointLight ) { - - if ( object.visible === false ) return; - - var visible = object.layers.test( camera.layers ); - - if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) { - - if ( object.castShadow && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) { - - object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld ); - - var geometry = _objects.update( object ); - var material = object.material; - - if ( Array.isArray( material ) ) { - - var groups = geometry.groups; - - for ( var k = 0, kl = groups.length; k < kl; k ++ ) { - - var group = groups[ k ]; - var groupMaterial = material[ group.materialIndex ]; - - if ( groupMaterial && groupMaterial.visible ) { - - var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far ); - _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group ); - - } - - } - - } else if ( material.visible ) { - - var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far ); - _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null ); - - } - - } - - } - - var children = object.children; - - for ( var i = 0, l = children.length; i < l; i ++ ) { - - renderObject( children[ i ], camera, shadowCamera, isPointLight ); - - } - - } - - } - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function WebGLAttributes( gl ) { - - var buffers = {}; - - function createBuffer( attribute, bufferType ) { - - var array = attribute.array; - var usage = attribute.dynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW; - - var buffer = gl.createBuffer(); - - gl.bindBuffer( bufferType, buffer ); - gl.bufferData( bufferType, array, usage ); - - attribute.onUploadCallback(); - - var type = gl.FLOAT; - - if ( array instanceof Float32Array ) { - - type = gl.FLOAT; - - } else if ( array instanceof Float64Array ) { - - console.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' ); - - } else if ( array instanceof Uint16Array ) { - - type = gl.UNSIGNED_SHORT; - - } else if ( array instanceof Int16Array ) { - - type = gl.SHORT; - - } else if ( array instanceof Uint32Array ) { - - type = gl.UNSIGNED_INT; - - } else if ( array instanceof Int32Array ) { - - type = gl.INT; - - } else if ( array instanceof Int8Array ) { - - type = gl.BYTE; - - } else if ( array instanceof Uint8Array ) { - - type = gl.UNSIGNED_BYTE; - - } - - return { - buffer: buffer, - type: type, - bytesPerElement: array.BYTES_PER_ELEMENT, - version: attribute.version - }; - - } - - function updateBuffer( buffer, attribute, bufferType ) { - - var array = attribute.array; - var updateRange = attribute.updateRange; - - gl.bindBuffer( bufferType, buffer ); - - if ( attribute.dynamic === false ) { - - gl.bufferData( bufferType, array, gl.STATIC_DRAW ); - - } else if ( updateRange.count === - 1 ) { - - // Not using update ranges - - gl.bufferSubData( bufferType, 0, array ); - - } else if ( updateRange.count === 0 ) { - - console.error( 'THREE.WebGLObjects.updateBuffer: dynamic THREE.BufferAttribute marked as needsUpdate but updateRange.count is 0, ensure you are using set methods or updating manually.' ); - - } else { - - gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, - array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) ); - - updateRange.count = - 1; // reset range - - } - - } - - // - - function get( attribute ) { - - if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; - - return buffers[ attribute.uuid ]; - - } - - function remove( attribute ) { - - if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; - - var data = buffers[ attribute.uuid ]; - - if ( data ) { - - gl.deleteBuffer( data.buffer ); - - delete buffers[ attribute.uuid ]; - - } - - } - - function update( attribute, bufferType ) { - - if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; - - var data = buffers[ attribute.uuid ]; - - if ( data === undefined ) { - - buffers[ attribute.uuid ] = createBuffer( attribute, bufferType ); - - } else if ( data.version < attribute.version ) { - - updateBuffer( data.buffer, attribute, bufferType ); - - data.version = attribute.version; - - } - - } - - return { - - get: get, - remove: remove, - update: update - - }; - - } - - /** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ - - function PlaneGeometry( width, height, widthSegments, heightSegments ) { - - Geometry.call( this ); - - this.type = 'PlaneGeometry'; - - this.parameters = { - width: width, - height: height, - widthSegments: widthSegments, - heightSegments: heightSegments - }; - - this.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) ); - this.mergeVertices(); - - } - - PlaneGeometry.prototype = Object.create( Geometry.prototype ); - PlaneGeometry.prototype.constructor = PlaneGeometry; - - // PlaneBufferGeometry - - function PlaneBufferGeometry( width, height, widthSegments, heightSegments ) { - - BufferGeometry.call( this ); - - this.type = 'PlaneBufferGeometry'; - - this.parameters = { - width: width, - height: height, - widthSegments: widthSegments, - heightSegments: heightSegments - }; - - width = width || 1; - height = height || 1; - - var width_half = width / 2; - var height_half = height / 2; - - var gridX = Math.floor( widthSegments ) || 1; - var gridY = Math.floor( heightSegments ) || 1; - - var gridX1 = gridX + 1; - var gridY1 = gridY + 1; - - var segment_width = width / gridX; - var segment_height = height / gridY; - - var ix, iy; - - // buffers - - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; - - // generate vertices, normals and uvs - - for ( iy = 0; iy < gridY1; iy ++ ) { - - var y = iy * segment_height - height_half; - - for ( ix = 0; ix < gridX1; ix ++ ) { - - var x = ix * segment_width - width_half; - - vertices.push( x, - y, 0 ); - - normals.push( 0, 0, 1 ); - - uvs.push( ix / gridX ); - uvs.push( 1 - ( iy / gridY ) ); - - } - - } - - // indices - - for ( iy = 0; iy < gridY; iy ++ ) { - - for ( ix = 0; ix < gridX; ix ++ ) { - - var a = ix + gridX1 * iy; - var b = ix + gridX1 * ( iy + 1 ); - var c = ( ix + 1 ) + gridX1 * ( iy + 1 ); - var d = ( ix + 1 ) + gridX1 * iy; - - // faces - - indices.push( a, b, d ); - indices.push( b, c, d ); - - } - - } - - // build geometry - - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - - } - - PlaneBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - PlaneBufferGeometry.prototype.constructor = PlaneBufferGeometry; - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function WebGLBackground( renderer, state, geometries, premultipliedAlpha ) { - - var clearColor = new Color( 0x000000 ); - var clearAlpha = 0; - - var planeCamera, planeMesh; - var boxMesh; - - function render( renderList, scene, camera, forceClear ) { - - var background = scene.background; - - if ( background === null ) { - - setClear( clearColor, clearAlpha ); - - } else if ( background && background.isColor ) { - - setClear( background, 1 ); - forceClear = true; - - } - - if ( renderer.autoClear || forceClear ) { - - renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil ); - - } - - if ( background && background.isCubeTexture ) { - - if ( boxMesh === undefined ) { - - boxMesh = new Mesh( - new BoxBufferGeometry( 1, 1, 1 ), - new ShaderMaterial( { - uniforms: ShaderLib.cube.uniforms, - vertexShader: ShaderLib.cube.vertexShader, - fragmentShader: ShaderLib.cube.fragmentShader, - side: BackSide, - depthTest: true, - depthWrite: false, - fog: false - } ) - ); - - boxMesh.geometry.removeAttribute( 'normal' ); - boxMesh.geometry.removeAttribute( 'uv' ); - - boxMesh.onBeforeRender = function ( renderer, scene, camera ) { - - this.matrixWorld.copyPosition( camera.matrixWorld ); - - }; - - geometries.update( boxMesh.geometry ); - - } - - boxMesh.material.uniforms.tCube.value = background; - - renderList.push( boxMesh, boxMesh.geometry, boxMesh.material, 0, null ); - - } else if ( background && background.isTexture ) { - - if ( planeCamera === undefined ) { - - planeCamera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); - - planeMesh = new Mesh( - new PlaneBufferGeometry( 2, 2 ), - new MeshBasicMaterial( { depthTest: false, depthWrite: false, fog: false } ) - ); - - geometries.update( planeMesh.geometry ); - - } - - planeMesh.material.map = background; - - // TODO Push this to renderList - - renderer.renderBufferDirect( planeCamera, null, planeMesh.geometry, planeMesh.material, planeMesh, null ); - - } - - } - - function setClear( color, alpha ) { - - state.buffers.color.setClear( color.r, color.g, color.b, alpha, premultipliedAlpha ); - - } - - return { - - getClearColor: function () { - - return clearColor; - - }, - setClearColor: function ( color, alpha ) { - - clearColor.set( color ); - clearAlpha = alpha !== undefined ? alpha : 1; - setClear( clearColor, clearAlpha ); - - }, - getClearAlpha: function () { - - return clearAlpha; - - }, - setClearAlpha: function ( alpha ) { - - clearAlpha = alpha; - setClear( clearColor, clearAlpha ); - - }, - render: render - - }; - - } - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function painterSortStable( a, b ) { - - if ( a.renderOrder !== b.renderOrder ) { - - return a.renderOrder - b.renderOrder; - - } else if ( a.program && b.program && a.program !== b.program ) { - - return a.program.id - b.program.id; - - } else if ( a.material.id !== b.material.id ) { - - return a.material.id - b.material.id; - - } else if ( a.z !== b.z ) { - - return a.z - b.z; - - } else { - - return a.id - b.id; - - } - - } - - function reversePainterSortStable( a, b ) { - - if ( a.renderOrder !== b.renderOrder ) { - - return a.renderOrder - b.renderOrder; - - } if ( a.z !== b.z ) { - - return b.z - a.z; - - } else { - - return a.id - b.id; - - } - - } - - function WebGLRenderList() { - - var renderItems = []; - var renderItemsIndex = 0; - - var opaque = []; - var transparent = []; - - function init() { - - renderItemsIndex = 0; - - opaque.length = 0; - transparent.length = 0; - - } - - function push( object, geometry, material, z, group ) { - - var renderItem = renderItems[ renderItemsIndex ]; - - if ( renderItem === undefined ) { - - renderItem = { - id: object.id, - object: object, - geometry: geometry, - material: material, - program: material.program, - renderOrder: object.renderOrder, - z: z, - group: group - }; - - renderItems[ renderItemsIndex ] = renderItem; - - } else { - - renderItem.id = object.id; - renderItem.object = object; - renderItem.geometry = geometry; - renderItem.material = material; - renderItem.program = material.program; - renderItem.renderOrder = object.renderOrder; - renderItem.z = z; - renderItem.group = group; - - } - - ( material.transparent === true ? transparent : opaque ).push( renderItem ); - - renderItemsIndex ++; - - } - - function sort() { - - if ( opaque.length > 1 ) opaque.sort( painterSortStable ); - if ( transparent.length > 1 ) transparent.sort( reversePainterSortStable ); - - } - - return { - opaque: opaque, - transparent: transparent, - - init: init, - push: push, - - sort: sort - }; - - } - - function WebGLRenderLists() { - - var lists = {}; - - function get( scene, camera ) { - - var hash = scene.id + ',' + camera.id; - var list = lists[ hash ]; - - if ( list === undefined ) { - - // console.log( 'THREE.WebGLRenderLists:', hash ); - - list = new WebGLRenderList(); - lists[ hash ] = list; - - } - - return list; - - } - - function dispose() { - - lists = {}; - - } - - return { - get: get, - dispose: dispose - }; - - } - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function absNumericalSort( a, b ) { - - return Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] ); - - } - - function WebGLMorphtargets( gl ) { - - var influencesList = {}; - var morphInfluences = new Float32Array( 8 ); - - function update( object, geometry, material, program ) { - - var objectInfluences = object.morphTargetInfluences; - - var length = objectInfluences.length; - - var influences = influencesList[ geometry.id ]; - - if ( influences === undefined ) { - - // initialise list - - influences = []; - - for ( var i = 0; i < length; i ++ ) { - - influences[ i ] = [ i, 0 ]; - - } - - influencesList[ geometry.id ] = influences; - - } - - var morphTargets = material.morphTargets && geometry.morphAttributes.position; - var morphNormals = material.morphNormals && geometry.morphAttributes.normal; - - // Remove current morphAttributes - - for ( var i = 0; i < length; i ++ ) { - - var influence = influences[ i ]; - - if ( influence[ 1 ] !== 0 ) { - - if ( morphTargets ) geometry.removeAttribute( 'morphTarget' + i ); - if ( morphNormals ) geometry.removeAttribute( 'morphNormal' + i ); - - } - - } - - // Collect influences - - for ( var i = 0; i < length; i ++ ) { - - var influence = influences[ i ]; - - influence[ 0 ] = i; - influence[ 1 ] = objectInfluences[ i ]; - - } - - influences.sort( absNumericalSort ); - - // Add morphAttributes - - for ( var i = 0; i < 8; i ++ ) { - - var influence = influences[ i ]; - - if ( influence ) { - - var index = influence[ 0 ]; - var value = influence[ 1 ]; - - if ( value ) { - - if ( morphTargets ) geometry.addAttribute( 'morphTarget' + i, morphTargets[ index ] ); - if ( morphNormals ) geometry.addAttribute( 'morphNormal' + i, morphNormals[ index ] ); - - morphInfluences[ i ] = value; - continue; - - } - - } - - morphInfluences[ i ] = 0; - - } - - program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences ); - - } - - return { - - update: update - - }; - - } - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function WebGLIndexedBufferRenderer( gl, extensions, infoRender ) { - - var mode; - - function setMode( value ) { - - mode = value; - - } - - var type, bytesPerElement; - - function setIndex( value ) { - - type = value.type; - bytesPerElement = value.bytesPerElement; - - } - - function render( start, count ) { - - gl.drawElements( mode, count, type, start * bytesPerElement ); - - infoRender.calls ++; - infoRender.vertices += count; - - if ( mode === gl.TRIANGLES ) infoRender.faces += count / 3; - else if ( mode === gl.POINTS ) infoRender.points += count; - - } - - function renderInstances( geometry, start, count ) { - - var extension = extensions.get( 'ANGLE_instanced_arrays' ); - - if ( extension === null ) { - - console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' ); - return; - - } - - extension.drawElementsInstancedANGLE( mode, count, type, start * bytesPerElement, geometry.maxInstancedCount ); - - infoRender.calls ++; - infoRender.vertices += count * geometry.maxInstancedCount; - - if ( mode === gl.TRIANGLES ) infoRender.faces += geometry.maxInstancedCount * count / 3; - else if ( mode === gl.POINTS ) infoRender.points += geometry.maxInstancedCount * count; - - } - - // - - this.setMode = setMode; - this.setIndex = setIndex; - this.render = render; - this.renderInstances = renderInstances; - - } - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function WebGLBufferRenderer( gl, extensions, infoRender ) { - - var mode; - - function setMode( value ) { - - mode = value; - - } - - function render( start, count ) { - - gl.drawArrays( mode, start, count ); - - infoRender.calls ++; - infoRender.vertices += count; - - if ( mode === gl.TRIANGLES ) infoRender.faces += count / 3; - else if ( mode === gl.POINTS ) infoRender.points += count; - - } - - function renderInstances( geometry, start, count ) { - - var extension = extensions.get( 'ANGLE_instanced_arrays' ); - - if ( extension === null ) { - - console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' ); - return; - - } - - var position = geometry.attributes.position; - - if ( position.isInterleavedBufferAttribute ) { - - count = position.data.count; - - extension.drawArraysInstancedANGLE( mode, 0, count, geometry.maxInstancedCount ); - - } else { - - extension.drawArraysInstancedANGLE( mode, start, count, geometry.maxInstancedCount ); - - } - - infoRender.calls ++; - infoRender.vertices += count * geometry.maxInstancedCount; - - if ( mode === gl.TRIANGLES ) infoRender.faces += geometry.maxInstancedCount * count / 3; - else if ( mode === gl.POINTS ) infoRender.points += geometry.maxInstancedCount * count; - - } - - // - - this.setMode = setMode; - this.render = render; - this.renderInstances = renderInstances; - - } - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function WebGLGeometries( gl, attributes, infoMemory ) { - - var geometries = {}; - var wireframeAttributes = {}; - - function onGeometryDispose( event ) { - - var geometry = event.target; - var buffergeometry = geometries[ geometry.id ]; - - if ( buffergeometry.index !== null ) { - - attributes.remove( buffergeometry.index ); - - } - - for ( var name in buffergeometry.attributes ) { - - attributes.remove( buffergeometry.attributes[ name ] ); - - } - - geometry.removeEventListener( 'dispose', onGeometryDispose ); - - delete geometries[ geometry.id ]; - - // TODO Remove duplicate code - - var attribute = wireframeAttributes[ geometry.id ]; - - if ( attribute ) { - - attributes.remove( attribute ); - delete wireframeAttributes[ geometry.id ]; - - } - - attribute = wireframeAttributes[ buffergeometry.id ]; - - if ( attribute ) { - - attributes.remove( attribute ); - delete wireframeAttributes[ buffergeometry.id ]; - - } - - // - - infoMemory.geometries --; - - } - - function get( object, geometry ) { - - var buffergeometry = geometries[ geometry.id ]; - - if ( buffergeometry ) return buffergeometry; - - geometry.addEventListener( 'dispose', onGeometryDispose ); - - if ( geometry.isBufferGeometry ) { - - buffergeometry = geometry; - - } else if ( geometry.isGeometry ) { - - if ( geometry._bufferGeometry === undefined ) { - - geometry._bufferGeometry = new BufferGeometry().setFromObject( object ); - - } - - buffergeometry = geometry._bufferGeometry; - - } - - geometries[ geometry.id ] = buffergeometry; - - infoMemory.geometries ++; - - return buffergeometry; - - } - - function update( geometry ) { - - var index = geometry.index; - var geometryAttributes = geometry.attributes; - - if ( index !== null ) { - - attributes.update( index, gl.ELEMENT_ARRAY_BUFFER ); - - } - - for ( var name in geometryAttributes ) { - - attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER ); - - } - - // morph targets - - var morphAttributes = geometry.morphAttributes; - - for ( var name in morphAttributes ) { - - var array = morphAttributes[ name ]; - - for ( var i = 0, l = array.length; i < l; i ++ ) { - - attributes.update( array[ i ], gl.ARRAY_BUFFER ); - - } - - } - - } - - function getWireframeAttribute( geometry ) { - - var attribute = wireframeAttributes[ geometry.id ]; - - if ( attribute ) return attribute; - - var indices = []; - - var geometryIndex = geometry.index; - var geometryAttributes = geometry.attributes; - - // console.time( 'wireframe' ); - - if ( geometryIndex !== null ) { - - var array = geometryIndex.array; - - for ( var i = 0, l = array.length; i < l; i += 3 ) { - - var a = array[ i + 0 ]; - var b = array[ i + 1 ]; - var c = array[ i + 2 ]; - - indices.push( a, b, b, c, c, a ); - - } - - } else { - - var array = geometryAttributes.position.array; - - for ( var i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) { - - var a = i + 0; - var b = i + 1; - var c = i + 2; - - indices.push( a, b, b, c, c, a ); - - } - - } - - // console.timeEnd( 'wireframe' ); - - attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 ); - - attributes.update( attribute, gl.ELEMENT_ARRAY_BUFFER ); - - wireframeAttributes[ geometry.id ] = attribute; - - return attribute; - - } - - return { - - get: get, - update: update, - - getWireframeAttribute: getWireframeAttribute - - }; - - } - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function UniformsCache() { - - var lights = {}; - - return { - - get: function ( light ) { - - if ( lights[ light.id ] !== undefined ) { - - return lights[ light.id ]; - - } - - var uniforms; - - switch ( light.type ) { - - case 'DirectionalLight': - uniforms = { - direction: new Vector3(), - color: new Color(), - - shadow: false, - shadowBias: 0, - shadowRadius: 1, - shadowMapSize: new Vector2() - }; - break; - - case 'SpotLight': - uniforms = { - position: new Vector3(), - direction: new Vector3(), - color: new Color(), - distance: 0, - coneCos: 0, - penumbraCos: 0, - decay: 0, - - shadow: false, - shadowBias: 0, - shadowRadius: 1, - shadowMapSize: new Vector2() - }; - break; - - case 'PointLight': - uniforms = { - position: new Vector3(), - color: new Color(), - distance: 0, - decay: 0, - - shadow: false, - shadowBias: 0, - shadowRadius: 1, - shadowMapSize: new Vector2(), - shadowCameraNear: 1, - shadowCameraFar: 1000 - }; - break; - - case 'HemisphereLight': - uniforms = { - direction: new Vector3(), - skyColor: new Color(), - groundColor: new Color() - }; - break; - - case 'RectAreaLight': - uniforms = { - color: new Color(), - position: new Vector3(), - halfWidth: new Vector3(), - halfHeight: new Vector3() - // TODO (abelnation): set RectAreaLight shadow uniforms - }; - break; - - } - - lights[ light.id ] = uniforms; - - return uniforms; - - } - - }; - - } - - function WebGLLights() { - - var cache = new UniformsCache(); - - var state = { - - hash: '', - - ambient: [ 0, 0, 0 ], - directional: [], - directionalShadowMap: [], - directionalShadowMatrix: [], - spot: [], - spotShadowMap: [], - spotShadowMatrix: [], - rectArea: [], - point: [], - pointShadowMap: [], - pointShadowMatrix: [], - hemi: [] - - }; - - var vector3 = new Vector3(); - var matrix4 = new Matrix4(); - var matrix42 = new Matrix4(); - - function setup( lights, shadows, camera ) { - - var r = 0, g = 0, b = 0; - - var directionalLength = 0; - var pointLength = 0; - var spotLength = 0; - var rectAreaLength = 0; - var hemiLength = 0; - - var viewMatrix = camera.matrixWorldInverse; - - for ( var i = 0, l = lights.length; i < l; i ++ ) { - - var light = lights[ i ]; - - var color = light.color; - var intensity = light.intensity; - var distance = light.distance; - - var shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null; - - if ( light.isAmbientLight ) { - - r += color.r * intensity; - g += color.g * intensity; - b += color.b * intensity; - - } else if ( light.isDirectionalLight ) { - - var uniforms = cache.get( light ); - - uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); - uniforms.direction.setFromMatrixPosition( light.matrixWorld ); - vector3.setFromMatrixPosition( light.target.matrixWorld ); - uniforms.direction.sub( vector3 ); - uniforms.direction.transformDirection( viewMatrix ); - - uniforms.shadow = light.castShadow; - - if ( light.castShadow ) { - - var shadow = light.shadow; - - uniforms.shadowBias = shadow.bias; - uniforms.shadowRadius = shadow.radius; - uniforms.shadowMapSize = shadow.mapSize; - - } - - state.directionalShadowMap[ directionalLength ] = shadowMap; - state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix; - state.directional[ directionalLength ] = uniforms; - - directionalLength ++; - - } else if ( light.isSpotLight ) { - - var uniforms = cache.get( light ); - - uniforms.position.setFromMatrixPosition( light.matrixWorld ); - uniforms.position.applyMatrix4( viewMatrix ); - - uniforms.color.copy( color ).multiplyScalar( intensity ); - uniforms.distance = distance; - - uniforms.direction.setFromMatrixPosition( light.matrixWorld ); - vector3.setFromMatrixPosition( light.target.matrixWorld ); - uniforms.direction.sub( vector3 ); - uniforms.direction.transformDirection( viewMatrix ); - - uniforms.coneCos = Math.cos( light.angle ); - uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) ); - uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay; - - uniforms.shadow = light.castShadow; - - if ( light.castShadow ) { - - var shadow = light.shadow; - - uniforms.shadowBias = shadow.bias; - uniforms.shadowRadius = shadow.radius; - uniforms.shadowMapSize = shadow.mapSize; - - } - - state.spotShadowMap[ spotLength ] = shadowMap; - state.spotShadowMatrix[ spotLength ] = light.shadow.matrix; - state.spot[ spotLength ] = uniforms; - - spotLength ++; - - } else if ( light.isRectAreaLight ) { - - var uniforms = cache.get( light ); - - // (a) intensity controls irradiance of entire light - uniforms.color - .copy( color ) - .multiplyScalar( intensity / ( light.width * light.height ) ); - - // (b) intensity controls the radiance per light area - // uniforms.color.copy( color ).multiplyScalar( intensity ); - - uniforms.position.setFromMatrixPosition( light.matrixWorld ); - uniforms.position.applyMatrix4( viewMatrix ); - - // extract local rotation of light to derive width/height half vectors - matrix42.identity(); - matrix4.copy( light.matrixWorld ); - matrix4.premultiply( viewMatrix ); - matrix42.extractRotation( matrix4 ); - - uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 ); - uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 ); - - uniforms.halfWidth.applyMatrix4( matrix42 ); - uniforms.halfHeight.applyMatrix4( matrix42 ); - - // TODO (abelnation): RectAreaLight distance? - // uniforms.distance = distance; - - state.rectArea[ rectAreaLength ] = uniforms; - - rectAreaLength ++; - - } else if ( light.isPointLight ) { - - var uniforms = cache.get( light ); - - uniforms.position.setFromMatrixPosition( light.matrixWorld ); - uniforms.position.applyMatrix4( viewMatrix ); - - uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); - uniforms.distance = light.distance; - uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay; - - uniforms.shadow = light.castShadow; - - if ( light.castShadow ) { - - var shadow = light.shadow; - - uniforms.shadowBias = shadow.bias; - uniforms.shadowRadius = shadow.radius; - uniforms.shadowMapSize = shadow.mapSize; - uniforms.shadowCameraNear = shadow.camera.near; - uniforms.shadowCameraFar = shadow.camera.far; - - } - - state.pointShadowMap[ pointLength ] = shadowMap; - state.pointShadowMatrix[ pointLength ] = light.shadow.matrix; - state.point[ pointLength ] = uniforms; - - pointLength ++; - - } else if ( light.isHemisphereLight ) { - - var uniforms = cache.get( light ); - - uniforms.direction.setFromMatrixPosition( light.matrixWorld ); - uniforms.direction.transformDirection( viewMatrix ); - uniforms.direction.normalize(); - - uniforms.skyColor.copy( light.color ).multiplyScalar( intensity ); - uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity ); - - state.hemi[ hemiLength ] = uniforms; - - hemiLength ++; - - } - - } - - state.ambient[ 0 ] = r; - state.ambient[ 1 ] = g; - state.ambient[ 2 ] = b; - - state.directional.length = directionalLength; - state.spot.length = spotLength; - state.rectArea.length = rectAreaLength; - state.point.length = pointLength; - state.hemi.length = hemiLength; - - // TODO (sam-g-steel) why aren't we using join - state.hash = directionalLength + ',' + pointLength + ',' + spotLength + ',' + rectAreaLength + ',' + hemiLength + ',' + shadows.length; - - } - - return { - setup: setup, - state: state - }; - - } - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function WebGLObjects( geometries, infoRender ) { - - var updateList = {}; - - function update( object ) { - - var frame = infoRender.frame; - - var geometry = object.geometry; - var buffergeometry = geometries.get( object, geometry ); - - // Update once per frame - - if ( updateList[ buffergeometry.id ] !== frame ) { - - if ( geometry.isGeometry ) { - - buffergeometry.updateFromObject( object ); - - } - - geometries.update( buffergeometry ); - - updateList[ buffergeometry.id ] = frame; - - } - - return buffergeometry; - - } - - function clear() { - - updateList = {}; - - } - - return { - - update: update, - clear: clear - - }; - - } - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function addLineNumbers( string ) { - - var lines = string.split( '\n' ); - - for ( var i = 0; i < lines.length; i ++ ) { - - lines[ i ] = ( i + 1 ) + ': ' + lines[ i ]; - - } - - return lines.join( '\n' ); - - } - - function WebGLShader( gl, type, string ) { - - var shader = gl.createShader( type ); - - gl.shaderSource( shader, string ); - gl.compileShader( shader ); - - if ( gl.getShaderParameter( shader, gl.COMPILE_STATUS ) === false ) { - - console.error( 'THREE.WebGLShader: Shader couldn\'t compile.' ); - - } - - if ( gl.getShaderInfoLog( shader ) !== '' ) { - - console.warn( 'THREE.WebGLShader: gl.getShaderInfoLog()', type === gl.VERTEX_SHADER ? 'vertex' : 'fragment', gl.getShaderInfoLog( shader ), addLineNumbers( string ) ); - - } - - // --enable-privileged-webgl-extension - // console.log( type, gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) ); - - return shader; - - } - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - var programIdCount = 0; - - function getEncodingComponents( encoding ) { - - switch ( encoding ) { - - case LinearEncoding: - return [ 'Linear', '( value )' ]; - case sRGBEncoding: - return [ 'sRGB', '( value )' ]; - case RGBEEncoding: - return [ 'RGBE', '( value )' ]; - case RGBM7Encoding: - return [ 'RGBM', '( value, 7.0 )' ]; - case RGBM16Encoding: - return [ 'RGBM', '( value, 16.0 )' ]; - case RGBDEncoding: - return [ 'RGBD', '( value, 256.0 )' ]; - case GammaEncoding: - return [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ]; - default: - throw new Error( 'unsupported encoding: ' + encoding ); - - } - - } - - function getTexelDecodingFunction( functionName, encoding ) { - - var components = getEncodingComponents( encoding ); - return "vec4 " + functionName + "( vec4 value ) { return " + components[ 0 ] + "ToLinear" + components[ 1 ] + "; }"; - - } - - function getTexelEncodingFunction( functionName, encoding ) { - - var components = getEncodingComponents( encoding ); - return "vec4 " + functionName + "( vec4 value ) { return LinearTo" + components[ 0 ] + components[ 1 ] + "; }"; - - } - - function getToneMappingFunction( functionName, toneMapping ) { - - var toneMappingName; - - switch ( toneMapping ) { - - case LinearToneMapping: - toneMappingName = "Linear"; - break; - - case ReinhardToneMapping: - toneMappingName = "Reinhard"; - break; - - case Uncharted2ToneMapping: - toneMappingName = "Uncharted2"; - break; - - case CineonToneMapping: - toneMappingName = "OptimizedCineon"; - break; - - default: - throw new Error( 'unsupported toneMapping: ' + toneMapping ); - - } - - return "vec3 " + functionName + "( vec3 color ) { return " + toneMappingName + "ToneMapping( color ); }"; - - } - - function generateExtensions( extensions, parameters, rendererExtensions ) { - - extensions = extensions || {}; - - var chunks = [ - ( extensions.derivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.normalMap || parameters.flatShading ) ? '#extension GL_OES_standard_derivatives : enable' : '', - ( extensions.fragDepth || parameters.logarithmicDepthBuffer ) && rendererExtensions.get( 'EXT_frag_depth' ) ? '#extension GL_EXT_frag_depth : enable' : '', - ( extensions.drawBuffers ) && rendererExtensions.get( 'WEBGL_draw_buffers' ) ? '#extension GL_EXT_draw_buffers : require' : '', - ( extensions.shaderTextureLOD || parameters.envMap ) && rendererExtensions.get( 'EXT_shader_texture_lod' ) ? '#extension GL_EXT_shader_texture_lod : enable' : '' - ]; - - return chunks.filter( filterEmptyLine ).join( '\n' ); - - } - - function generateDefines( defines ) { - - var chunks = []; - - for ( var name in defines ) { - - var value = defines[ name ]; - - if ( value === false ) continue; - - chunks.push( '#define ' + name + ' ' + value ); - - } - - return chunks.join( '\n' ); - - } - - function fetchAttributeLocations( gl, program ) { - - var attributes = {}; - - var n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES ); - - for ( var i = 0; i < n; i ++ ) { - - var info = gl.getActiveAttrib( program, i ); - var name = info.name; - - // console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i ); - - attributes[ name ] = gl.getAttribLocation( program, name ); - - } - - return attributes; - - } - - function filterEmptyLine( string ) { - - return string !== ''; - - } - - function replaceLightNums( string, parameters ) { - - return string - .replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights ) - .replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights ) - .replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights ) - .replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights ) - .replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights ); - - } - - function parseIncludes( string ) { - - var pattern = /^[ \t]*#include +<([\w\d.]+)>/gm; - - function replace( match, include ) { - - var replace = ShaderChunk[ include ]; - - if ( replace === undefined ) { - - throw new Error( 'Can not resolve #include <' + include + '>' ); - - } - - return parseIncludes( replace ); - - } - - return string.replace( pattern, replace ); - - } - - function unrollLoops( string ) { - - var pattern = /for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g; - - function replace( match, start, end, snippet ) { - - var unroll = ''; - - for ( var i = parseInt( start ); i < parseInt( end ); i ++ ) { - - unroll += snippet.replace( /\[ i \]/g, '[ ' + i + ' ]' ); - - } - - return unroll; - - } - - return string.replace( pattern, replace ); - - } - - function WebGLProgram( renderer, extensions, code, material, shader, parameters ) { - - var gl = renderer.context; - - var defines = material.defines; - - var vertexShader = shader.vertexShader; - var fragmentShader = shader.fragmentShader; - - var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC'; - - if ( parameters.shadowMapType === PCFShadowMap ) { - - shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF'; - - } else if ( parameters.shadowMapType === PCFSoftShadowMap ) { - - shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT'; - - } - - var envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; - var envMapModeDefine = 'ENVMAP_MODE_REFLECTION'; - var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY'; - - if ( parameters.envMap ) { - - switch ( material.envMap.mapping ) { - - case CubeReflectionMapping: - case CubeRefractionMapping: - envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; - break; - - case CubeUVReflectionMapping: - case CubeUVRefractionMapping: - envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV'; - break; - - case EquirectangularReflectionMapping: - case EquirectangularRefractionMapping: - envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC'; - break; - - case SphericalReflectionMapping: - envMapTypeDefine = 'ENVMAP_TYPE_SPHERE'; - break; - - } - - switch ( material.envMap.mapping ) { - - case CubeRefractionMapping: - case EquirectangularRefractionMapping: - envMapModeDefine = 'ENVMAP_MODE_REFRACTION'; - break; - - } - - switch ( material.combine ) { - - case MultiplyOperation: - envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY'; - break; - - case MixOperation: - envMapBlendingDefine = 'ENVMAP_BLENDING_MIX'; - break; - - case AddOperation: - envMapBlendingDefine = 'ENVMAP_BLENDING_ADD'; - break; - - } - - } - - var gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0; - - // console.log( 'building new program ' ); - - // - - var customExtensions = generateExtensions( material.extensions, parameters, extensions ); - - var customDefines = generateDefines( defines ); - - // - - var program = gl.createProgram(); - - var prefixVertex, prefixFragment; - - if ( material.isRawShaderMaterial ) { - - prefixVertex = [ - - customDefines - - ].filter( filterEmptyLine ).join( '\n' ); - - if ( prefixVertex.length > 0 ) { - - prefixVertex += '\n'; - - } - - prefixFragment = [ - - customExtensions, - customDefines - - ].filter( filterEmptyLine ).join( '\n' ); - - if ( prefixFragment.length > 0 ) { - - prefixFragment += '\n'; - - } - - } else { - - prefixVertex = [ - - 'precision ' + parameters.precision + ' float;', - 'precision ' + parameters.precision + ' int;', - - '#define SHADER_NAME ' + shader.name, - - customDefines, - - parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '', - - '#define GAMMA_FACTOR ' + gammaFactorDefine, - - '#define MAX_BONES ' + parameters.maxBones, - ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', - ( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '', - - parameters.map ? '#define USE_MAP' : '', - parameters.envMap ? '#define USE_ENVMAP' : '', - parameters.envMap ? '#define ' + envMapModeDefine : '', - parameters.lightMap ? '#define USE_LIGHTMAP' : '', - parameters.aoMap ? '#define USE_AOMAP' : '', - parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', - parameters.bumpMap ? '#define USE_BUMPMAP' : '', - parameters.normalMap ? '#define USE_NORMALMAP' : '', - parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '', - parameters.specularMap ? '#define USE_SPECULARMAP' : '', - parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', - parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', - parameters.alphaMap ? '#define USE_ALPHAMAP' : '', - parameters.vertexColors ? '#define USE_COLOR' : '', - - parameters.flatShading ? '#define FLAT_SHADED' : '', - - parameters.skinning ? '#define USE_SKINNING' : '', - parameters.useVertexTexture ? '#define BONE_TEXTURE' : '', - - parameters.morphTargets ? '#define USE_MORPHTARGETS' : '', - parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '', - parameters.doubleSided ? '#define DOUBLE_SIDED' : '', - parameters.flipSided ? '#define FLIP_SIDED' : '', - - '#define NUM_CLIPPING_PLANES ' + parameters.numClippingPlanes, - - parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', - parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', - - parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', - - parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', - parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '', - - 'uniform mat4 modelMatrix;', - 'uniform mat4 modelViewMatrix;', - 'uniform mat4 projectionMatrix;', - 'uniform mat4 viewMatrix;', - 'uniform mat3 normalMatrix;', - 'uniform vec3 cameraPosition;', - - 'attribute vec3 position;', - 'attribute vec3 normal;', - 'attribute vec2 uv;', - - '#ifdef USE_COLOR', - - ' attribute vec3 color;', - - '#endif', - - '#ifdef USE_MORPHTARGETS', - - ' attribute vec3 morphTarget0;', - ' attribute vec3 morphTarget1;', - ' attribute vec3 morphTarget2;', - ' attribute vec3 morphTarget3;', - - ' #ifdef USE_MORPHNORMALS', - - ' attribute vec3 morphNormal0;', - ' attribute vec3 morphNormal1;', - ' attribute vec3 morphNormal2;', - ' attribute vec3 morphNormal3;', - - ' #else', - - ' attribute vec3 morphTarget4;', - ' attribute vec3 morphTarget5;', - ' attribute vec3 morphTarget6;', - ' attribute vec3 morphTarget7;', - - ' #endif', - - '#endif', - - '#ifdef USE_SKINNING', - - ' attribute vec4 skinIndex;', - ' attribute vec4 skinWeight;', - - '#endif', - - '\n' - - ].filter( filterEmptyLine ).join( '\n' ); - - prefixFragment = [ - - customExtensions, - - 'precision ' + parameters.precision + ' float;', - 'precision ' + parameters.precision + ' int;', - - '#define SHADER_NAME ' + shader.name, - - customDefines, - - parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest : '', - - '#define GAMMA_FACTOR ' + gammaFactorDefine, - - ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', - ( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '', - - parameters.map ? '#define USE_MAP' : '', - parameters.envMap ? '#define USE_ENVMAP' : '', - parameters.envMap ? '#define ' + envMapTypeDefine : '', - parameters.envMap ? '#define ' + envMapModeDefine : '', - parameters.envMap ? '#define ' + envMapBlendingDefine : '', - parameters.lightMap ? '#define USE_LIGHTMAP' : '', - parameters.aoMap ? '#define USE_AOMAP' : '', - parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', - parameters.bumpMap ? '#define USE_BUMPMAP' : '', - parameters.normalMap ? '#define USE_NORMALMAP' : '', - parameters.specularMap ? '#define USE_SPECULARMAP' : '', - parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', - parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', - parameters.alphaMap ? '#define USE_ALPHAMAP' : '', - parameters.vertexColors ? '#define USE_COLOR' : '', - - parameters.gradientMap ? '#define USE_GRADIENTMAP' : '', - - parameters.flatShading ? '#define FLAT_SHADED' : '', - - parameters.doubleSided ? '#define DOUBLE_SIDED' : '', - parameters.flipSided ? '#define FLIP_SIDED' : '', - - '#define NUM_CLIPPING_PLANES ' + parameters.numClippingPlanes, - '#define UNION_CLIPPING_PLANES ' + ( parameters.numClippingPlanes - parameters.numClipIntersection ), - - parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', - parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', - - parameters.premultipliedAlpha ? "#define PREMULTIPLIED_ALPHA" : '', - - parameters.physicallyCorrectLights ? "#define PHYSICALLY_CORRECT_LIGHTS" : '', - - parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', - parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '', - - parameters.envMap && extensions.get( 'EXT_shader_texture_lod' ) ? '#define TEXTURE_LOD_EXT' : '', - - 'uniform mat4 viewMatrix;', - 'uniform vec3 cameraPosition;', - - ( parameters.toneMapping !== NoToneMapping ) ? "#define TONE_MAPPING" : '', - ( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below - ( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( "toneMapping", parameters.toneMapping ) : '', - - parameters.dithering ? '#define DITHERING' : '', - - ( parameters.outputEncoding || parameters.mapEncoding || parameters.envMapEncoding || parameters.emissiveMapEncoding ) ? ShaderChunk[ 'encodings_pars_fragment' ] : '', // this code is required here because it is used by the various encoding/decoding function defined below - parameters.mapEncoding ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '', - parameters.envMapEncoding ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '', - parameters.emissiveMapEncoding ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '', - parameters.outputEncoding ? getTexelEncodingFunction( "linearToOutputTexel", parameters.outputEncoding ) : '', - - parameters.depthPacking ? "#define DEPTH_PACKING " + material.depthPacking : '', - - '\n' - - ].filter( filterEmptyLine ).join( '\n' ); - - } - - vertexShader = parseIncludes( vertexShader ); - vertexShader = replaceLightNums( vertexShader, parameters ); - - fragmentShader = parseIncludes( fragmentShader ); - fragmentShader = replaceLightNums( fragmentShader, parameters ); - - if ( ! material.isShaderMaterial ) { - - vertexShader = unrollLoops( vertexShader ); - fragmentShader = unrollLoops( fragmentShader ); - - } - - var vertexGlsl = prefixVertex + vertexShader; - var fragmentGlsl = prefixFragment + fragmentShader; - - // console.log( '*VERTEX*', vertexGlsl ); - // console.log( '*FRAGMENT*', fragmentGlsl ); - - var glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl ); - var glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl ); - - gl.attachShader( program, glVertexShader ); - gl.attachShader( program, glFragmentShader ); - - // Force a particular attribute to index 0. - - if ( material.index0AttributeName !== undefined ) { - - gl.bindAttribLocation( program, 0, material.index0AttributeName ); - - } else if ( parameters.morphTargets === true ) { - - // programs with morphTargets displace position out of attribute 0 - gl.bindAttribLocation( program, 0, 'position' ); - - } - - gl.linkProgram( program ); - - var programLog = gl.getProgramInfoLog( program ); - var vertexLog = gl.getShaderInfoLog( glVertexShader ); - var fragmentLog = gl.getShaderInfoLog( glFragmentShader ); - - var runnable = true; - var haveDiagnostics = true; - - // console.log( '**VERTEX**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glVertexShader ) ); - // console.log( '**FRAGMENT**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glFragmentShader ) ); - - if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) { - - runnable = false; - - console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), 'gl.VALIDATE_STATUS', gl.getProgramParameter( program, gl.VALIDATE_STATUS ), 'gl.getProgramInfoLog', programLog, vertexLog, fragmentLog ); - - } else if ( programLog !== '' ) { - - console.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog ); - - } else if ( vertexLog === '' || fragmentLog === '' ) { - - haveDiagnostics = false; - - } - - if ( haveDiagnostics ) { - - this.diagnostics = { - - runnable: runnable, - material: material, - - programLog: programLog, - - vertexShader: { - - log: vertexLog, - prefix: prefixVertex - - }, - - fragmentShader: { - - log: fragmentLog, - prefix: prefixFragment - - } - - }; - - } - - // clean up - - gl.deleteShader( glVertexShader ); - gl.deleteShader( glFragmentShader ); - - // set up caching for uniform locations - - var cachedUniforms; - - this.getUniforms = function () { - - if ( cachedUniforms === undefined ) { - - cachedUniforms = new WebGLUniforms( gl, program, renderer ); - - } - - return cachedUniforms; - - }; - - // set up caching for attribute locations - - var cachedAttributes; - - this.getAttributes = function () { - - if ( cachedAttributes === undefined ) { - - cachedAttributes = fetchAttributeLocations( gl, program ); - - } - - return cachedAttributes; - - }; - - // free resource - - this.destroy = function () { - - gl.deleteProgram( program ); - this.program = undefined; - - }; - - // DEPRECATED - - Object.defineProperties( this, { - - uniforms: { - get: function () { - - console.warn( 'THREE.WebGLProgram: .uniforms is now .getUniforms().' ); - return this.getUniforms(); - - } - }, - - attributes: { - get: function () { - - console.warn( 'THREE.WebGLProgram: .attributes is now .getAttributes().' ); - return this.getAttributes(); - - } - } - - } ); - - - // - - this.id = programIdCount ++; - this.code = code; - this.usedTimes = 1; - this.program = program; - this.vertexShader = glVertexShader; - this.fragmentShader = glFragmentShader; - - return this; - - } - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function WebGLPrograms( renderer, extensions, capabilities ) { - - var programs = []; - - var shaderIDs = { - MeshDepthMaterial: 'depth', - MeshDistanceMaterial: 'distanceRGBA', - MeshNormalMaterial: 'normal', - MeshBasicMaterial: 'basic', - MeshLambertMaterial: 'lambert', - MeshPhongMaterial: 'phong', - MeshToonMaterial: 'phong', - MeshStandardMaterial: 'physical', - MeshPhysicalMaterial: 'physical', - LineBasicMaterial: 'basic', - LineDashedMaterial: 'dashed', - PointsMaterial: 'points', - ShadowMaterial: 'shadow' - }; - - var parameterNames = [ - "precision", "supportsVertexTextures", "map", "mapEncoding", "envMap", "envMapMode", "envMapEncoding", - "lightMap", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "displacementMap", "specularMap", - "roughnessMap", "metalnessMap", "gradientMap", - "alphaMap", "combine", "vertexColors", "fog", "useFog", "fogExp", - "flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning", - "maxBones", "useVertexTexture", "morphTargets", "morphNormals", - "maxMorphTargets", "maxMorphNormals", "premultipliedAlpha", - "numDirLights", "numPointLights", "numSpotLights", "numHemiLights", "numRectAreaLights", - "shadowMapEnabled", "shadowMapType", "toneMapping", 'physicallyCorrectLights', - "alphaTest", "doubleSided", "flipSided", "numClippingPlanes", "numClipIntersection", "depthPacking", "dithering" - ]; - - - function allocateBones( object ) { - - var skeleton = object.skeleton; - var bones = skeleton.bones; - - if ( capabilities.floatVertexTextures ) { - - return 1024; - - } else { - - // default for when object is not specified - // ( for example when prebuilding shader to be used with multiple objects ) - // - // - leave some extra space for other uniforms - // - limit here is ANGLE's 254 max uniform vectors - // (up to 54 should be safe) - - var nVertexUniforms = capabilities.maxVertexUniforms; - var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 ); - - var maxBones = Math.min( nVertexMatrices, bones.length ); - - if ( maxBones < bones.length ) { - - console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' ); - return 0; - - } - - return maxBones; - - } - - } - - function getTextureEncodingFromMap( map, gammaOverrideLinear ) { - - var encoding; - - if ( ! map ) { - - encoding = LinearEncoding; - - } else if ( map.isTexture ) { - - encoding = map.encoding; - - } else if ( map.isWebGLRenderTarget ) { - - console.warn( "THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead." ); - encoding = map.texture.encoding; - - } - - // add backwards compatibility for WebGLRenderer.gammaInput/gammaOutput parameter, should probably be removed at some point. - if ( encoding === LinearEncoding && gammaOverrideLinear ) { - - encoding = GammaEncoding; - - } - - return encoding; - - } - - this.getParameters = function ( material, lights, shadows, fog, nClipPlanes, nClipIntersection, object ) { - - var shaderID = shaderIDs[ material.type ]; - - // heuristics to create shader parameters according to lights in the scene - // (not to blow over maxLights budget) - - var maxBones = object.isSkinnedMesh ? allocateBones( object ) : 0; - var precision = capabilities.precision; - - if ( material.precision !== null ) { - - precision = capabilities.getMaxPrecision( material.precision ); - - if ( precision !== material.precision ) { - - console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' ); - - } - - } - - var currentRenderTarget = renderer.getRenderTarget(); - - var parameters = { - - shaderID: shaderID, - - precision: precision, - supportsVertexTextures: capabilities.vertexTextures, - outputEncoding: getTextureEncodingFromMap( ( ! currentRenderTarget ) ? null : currentRenderTarget.texture, renderer.gammaOutput ), - map: !! material.map, - mapEncoding: getTextureEncodingFromMap( material.map, renderer.gammaInput ), - envMap: !! material.envMap, - envMapMode: material.envMap && material.envMap.mapping, - envMapEncoding: getTextureEncodingFromMap( material.envMap, renderer.gammaInput ), - envMapCubeUV: ( !! material.envMap ) && ( ( material.envMap.mapping === CubeUVReflectionMapping ) || ( material.envMap.mapping === CubeUVRefractionMapping ) ), - lightMap: !! material.lightMap, - aoMap: !! material.aoMap, - emissiveMap: !! material.emissiveMap, - emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap, renderer.gammaInput ), - bumpMap: !! material.bumpMap, - normalMap: !! material.normalMap, - displacementMap: !! material.displacementMap, - roughnessMap: !! material.roughnessMap, - metalnessMap: !! material.metalnessMap, - specularMap: !! material.specularMap, - alphaMap: !! material.alphaMap, - - gradientMap: !! material.gradientMap, - - combine: material.combine, - - vertexColors: material.vertexColors, - - fog: !! fog, - useFog: material.fog, - fogExp: ( fog && fog.isFogExp2 ), - - flatShading: material.flatShading, - - sizeAttenuation: material.sizeAttenuation, - logarithmicDepthBuffer: capabilities.logarithmicDepthBuffer, - - skinning: material.skinning && maxBones > 0, - maxBones: maxBones, - useVertexTexture: capabilities.floatVertexTextures, - - morphTargets: material.morphTargets, - morphNormals: material.morphNormals, - maxMorphTargets: renderer.maxMorphTargets, - maxMorphNormals: renderer.maxMorphNormals, - - numDirLights: lights.directional.length, - numPointLights: lights.point.length, - numSpotLights: lights.spot.length, - numRectAreaLights: lights.rectArea.length, - numHemiLights: lights.hemi.length, - - numClippingPlanes: nClipPlanes, - numClipIntersection: nClipIntersection, - - dithering: material.dithering, - - shadowMapEnabled: renderer.shadowMap.enabled && object.receiveShadow && shadows.length > 0, - shadowMapType: renderer.shadowMap.type, - - toneMapping: renderer.toneMapping, - physicallyCorrectLights: renderer.physicallyCorrectLights, - - premultipliedAlpha: material.premultipliedAlpha, - - alphaTest: material.alphaTest, - doubleSided: material.side === DoubleSide, - flipSided: material.side === BackSide, - - depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false - - }; - - return parameters; - - }; - - this.getProgramCode = function ( material, parameters ) { - - var array = []; - - if ( parameters.shaderID ) { - - array.push( parameters.shaderID ); - - } else { - - array.push( material.fragmentShader ); - array.push( material.vertexShader ); - - } - - if ( material.defines !== undefined ) { - - for ( var name in material.defines ) { - - array.push( name ); - array.push( material.defines[ name ] ); - - } - - } - - for ( var i = 0; i < parameterNames.length; i ++ ) { - - array.push( parameters[ parameterNames[ i ] ] ); - - } - - array.push( material.onBeforeCompile.toString() ); - - array.push( renderer.gammaOutput ); - - return array.join(); - - }; - - this.acquireProgram = function ( material, shader, parameters, code ) { - - var program; - - // Check if code has been already compiled - for ( var p = 0, pl = programs.length; p < pl; p ++ ) { - - var programInfo = programs[ p ]; - - if ( programInfo.code === code ) { - - program = programInfo; - ++ program.usedTimes; - - break; - - } - - } - - if ( program === undefined ) { - - program = new WebGLProgram( renderer, extensions, code, material, shader, parameters ); - programs.push( program ); - - } - - return program; - - }; - - this.releaseProgram = function ( program ) { - - if ( -- program.usedTimes === 0 ) { - - // Remove from unordered set - var i = programs.indexOf( program ); - programs[ i ] = programs[ programs.length - 1 ]; - programs.pop(); - - // Free WebGL resources - program.destroy(); - - } - - }; - - // Exposed for resource monitoring & error feedback via renderer.info: - this.programs = programs; - - } - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, infoMemory ) { - - var _isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && _gl instanceof window.WebGL2RenderingContext ); - - // - - function clampToMaxSize( image, maxSize ) { - - if ( image.width > maxSize || image.height > maxSize ) { - - // Warning: Scaling through the canvas will only work with images that use - // premultiplied alpha. - - var scale = maxSize / Math.max( image.width, image.height ); - - var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); - canvas.width = Math.floor( image.width * scale ); - canvas.height = Math.floor( image.height * scale ); - - var context = canvas.getContext( '2d' ); - context.drawImage( image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height ); - - console.warn( 'THREE.WebGLRenderer: image is too big (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image ); - - return canvas; - - } - - return image; - - } - - function isPowerOfTwo( image ) { - - return _Math.isPowerOfTwo( image.width ) && _Math.isPowerOfTwo( image.height ); - - } - - function makePowerOfTwo( image ) { - - if ( image instanceof HTMLImageElement || image instanceof HTMLCanvasElement || image instanceof ImageBitmap ) { - - var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); - canvas.width = _Math.floorPowerOfTwo( image.width ); - canvas.height = _Math.floorPowerOfTwo( image.height ); - - var context = canvas.getContext( '2d' ); - context.drawImage( image, 0, 0, canvas.width, canvas.height ); - - console.warn( 'THREE.WebGLRenderer: image is not power of two (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image ); - - return canvas; - - } - - return image; - - } - - function textureNeedsPowerOfTwo( texture ) { - - return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) || - ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ); - - } - - function textureNeedsGenerateMipmaps( texture, isPowerOfTwo ) { - - return texture.generateMipmaps && isPowerOfTwo && - texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter; - - } - - // Fallback filters for non-power-of-2 textures - - function filterFallback( f ) { - - if ( f === NearestFilter || f === NearestMipMapNearestFilter || f === NearestMipMapLinearFilter ) { - - return _gl.NEAREST; - - } - - return _gl.LINEAR; - - } - - // - - function onTextureDispose( event ) { - - var texture = event.target; - - texture.removeEventListener( 'dispose', onTextureDispose ); - - deallocateTexture( texture ); - - infoMemory.textures --; - - - } - - function onRenderTargetDispose( event ) { - - var renderTarget = event.target; - - renderTarget.removeEventListener( 'dispose', onRenderTargetDispose ); - - deallocateRenderTarget( renderTarget ); - - infoMemory.textures --; - - } - - // - - function deallocateTexture( texture ) { - - var textureProperties = properties.get( texture ); - - if ( texture.image && textureProperties.__image__webglTextureCube ) { - - // cube texture - - _gl.deleteTexture( textureProperties.__image__webglTextureCube ); - - } else { - - // 2D texture - - if ( textureProperties.__webglInit === undefined ) return; - - _gl.deleteTexture( textureProperties.__webglTexture ); - - } - - // remove all webgl properties - properties.remove( texture ); - - } - - function deallocateRenderTarget( renderTarget ) { - - var renderTargetProperties = properties.get( renderTarget ); - var textureProperties = properties.get( renderTarget.texture ); - - if ( ! renderTarget ) return; - - if ( textureProperties.__webglTexture !== undefined ) { - - _gl.deleteTexture( textureProperties.__webglTexture ); - - } - - if ( renderTarget.depthTexture ) { - - renderTarget.depthTexture.dispose(); - - } - - if ( renderTarget.isWebGLRenderTargetCube ) { - - for ( var i = 0; i < 6; i ++ ) { - - _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] ); - if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] ); - - } - - } else { - - _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer ); - if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer ); - - } - - properties.remove( renderTarget.texture ); - properties.remove( renderTarget ); - - } - - // - - - - function setTexture2D( texture, slot ) { - - var textureProperties = properties.get( texture ); - - if ( texture.version > 0 && textureProperties.__version !== texture.version ) { - - var image = texture.image; - - if ( image === undefined ) { - - console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined', texture ); - - } else if ( image.complete === false ) { - - console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete', texture ); - - } else { - - uploadTexture( textureProperties, texture, slot ); - return; - - } - - } - - state.activeTexture( _gl.TEXTURE0 + slot ); - state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture ); - - } - - function setTextureCube( texture, slot ) { - - var textureProperties = properties.get( texture ); - - if ( texture.image.length === 6 ) { - - if ( texture.version > 0 && textureProperties.__version !== texture.version ) { - - if ( ! textureProperties.__image__webglTextureCube ) { - - texture.addEventListener( 'dispose', onTextureDispose ); - - textureProperties.__image__webglTextureCube = _gl.createTexture(); - - infoMemory.textures ++; - - } - - state.activeTexture( _gl.TEXTURE0 + slot ); - state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube ); - - _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ); - - var isCompressed = ( texture && texture.isCompressedTexture ); - var isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture ); - - var cubeImage = []; - - for ( var i = 0; i < 6; i ++ ) { - - if ( ! isCompressed && ! isDataTexture ) { - - cubeImage[ i ] = clampToMaxSize( texture.image[ i ], capabilities.maxCubemapSize ); - - } else { - - cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ]; - - } - - } - - var image = cubeImage[ 0 ], - isPowerOfTwoImage = isPowerOfTwo( image ), - glFormat = utils.convert( texture.format ), - glType = utils.convert( texture.type ); - - setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isPowerOfTwoImage ); - - for ( var i = 0; i < 6; i ++ ) { - - if ( ! isCompressed ) { - - if ( isDataTexture ) { - - state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data ); - - } else { - - state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] ); - - } - - } else { - - var mipmap, mipmaps = cubeImage[ i ].mipmaps; - - for ( var j = 0, jl = mipmaps.length; j < jl; j ++ ) { - - mipmap = mipmaps[ j ]; - - if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) { - - if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) { - - state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data ); - - } else { - - console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' ); - - } - - } else { - - state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); - - } - - } - - } - - } - - if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) { - - _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP ); - - } - - textureProperties.__version = texture.version; - - if ( texture.onUpdate ) texture.onUpdate( texture ); - - } else { - - state.activeTexture( _gl.TEXTURE0 + slot ); - state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube ); - - } - - } - - } - - function setTextureCubeDynamic( texture, slot ) { - - state.activeTexture( _gl.TEXTURE0 + slot ); - state.bindTexture( _gl.TEXTURE_CUBE_MAP, properties.get( texture ).__webglTexture ); - - } - - function setTextureParameters( textureType, texture, isPowerOfTwoImage ) { - - var extension; - - if ( isPowerOfTwoImage ) { - - _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, utils.convert( texture.wrapS ) ); - _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, utils.convert( texture.wrapT ) ); - - _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, utils.convert( texture.magFilter ) ); - _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, utils.convert( texture.minFilter ) ); - - } else { - - _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE ); - _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE ); - - if ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) { - - console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.', texture ); - - } - - _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) ); - _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) ); - - if ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) { - - console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.', texture ); - - } - - } - - extension = extensions.get( 'EXT_texture_filter_anisotropic' ); - - if ( extension ) { - - if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return; - if ( texture.type === HalfFloatType && extensions.get( 'OES_texture_half_float_linear' ) === null ) return; - - if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) { - - _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) ); - properties.get( texture ).__currentAnisotropy = texture.anisotropy; - - } - - } - - } - - function uploadTexture( textureProperties, texture, slot ) { - - if ( textureProperties.__webglInit === undefined ) { - - textureProperties.__webglInit = true; - - texture.addEventListener( 'dispose', onTextureDispose ); - - textureProperties.__webglTexture = _gl.createTexture(); - - infoMemory.textures ++; - - } - - state.activeTexture( _gl.TEXTURE0 + slot ); - state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture ); - - _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ); - _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha ); - _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment ); - - var image = clampToMaxSize( texture.image, capabilities.maxTextureSize ); - - if ( textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( image ) === false ) { - - image = makePowerOfTwo( image ); - - } - - var isPowerOfTwoImage = isPowerOfTwo( image ), - glFormat = utils.convert( texture.format ), - glType = utils.convert( texture.type ); - - setTextureParameters( _gl.TEXTURE_2D, texture, isPowerOfTwoImage ); - - var mipmap, mipmaps = texture.mipmaps; - - if ( texture.isDepthTexture ) { - - // populate depth texture with dummy data - - var internalFormat = _gl.DEPTH_COMPONENT; - - if ( texture.type === FloatType ) { - - if ( ! _isWebGL2 ) throw new Error( 'Float Depth Texture only supported in WebGL2.0' ); - internalFormat = _gl.DEPTH_COMPONENT32F; - - } else if ( _isWebGL2 ) { - - // WebGL 2.0 requires signed internalformat for glTexImage2D - internalFormat = _gl.DEPTH_COMPONENT16; - - } - - if ( texture.format === DepthFormat && internalFormat === _gl.DEPTH_COMPONENT ) { - - // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are - // DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT - // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) - if ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) { - - console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' ); - - texture.type = UnsignedShortType; - glType = utils.convert( texture.type ); - - } - - } - - // Depth stencil textures need the DEPTH_STENCIL internal format - // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) - if ( texture.format === DepthStencilFormat ) { - - internalFormat = _gl.DEPTH_STENCIL; - - // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are - // DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL. - // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) - if ( texture.type !== UnsignedInt248Type ) { - - console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' ); - - texture.type = UnsignedInt248Type; - glType = utils.convert( texture.type ); - - } - - } - - state.texImage2D( _gl.TEXTURE_2D, 0, internalFormat, image.width, image.height, 0, glFormat, glType, null ); - - } else if ( texture.isDataTexture ) { - - // use manually created mipmaps if available - // if there are no manual mipmaps - // set 0 level mipmap and then use GL to generate other mipmap levels - - if ( mipmaps.length > 0 && isPowerOfTwoImage ) { - - for ( var i = 0, il = mipmaps.length; i < il; i ++ ) { - - mipmap = mipmaps[ i ]; - state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); - - } - - texture.generateMipmaps = false; - - } else { - - state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data ); - - } - - } else if ( texture.isCompressedTexture ) { - - for ( var i = 0, il = mipmaps.length; i < il; i ++ ) { - - mipmap = mipmaps[ i ]; - - if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) { - - if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) { - - state.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data ); - - } else { - - console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); - - } - - } else { - - state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); - - } - - } - - } else { - - // regular Texture (image, video, canvas) - - // use manually created mipmaps if available - // if there are no manual mipmaps - // set 0 level mipmap and then use GL to generate other mipmap levels - - if ( mipmaps.length > 0 && isPowerOfTwoImage ) { - - for ( var i = 0, il = mipmaps.length; i < il; i ++ ) { - - mipmap = mipmaps[ i ]; - state.texImage2D( _gl.TEXTURE_2D, i, glFormat, glFormat, glType, mipmap ); - - } - - texture.generateMipmaps = false; - - } else { - - state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, image ); - - } - - } - - if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) _gl.generateMipmap( _gl.TEXTURE_2D ); - - textureProperties.__version = texture.version; - - if ( texture.onUpdate ) texture.onUpdate( texture ); - - } - - // Render targets - - // Setup storage for target texture and bind it to correct framebuffer - function setupFrameBufferTexture( framebuffer, renderTarget, attachment, textureTarget ) { - - var glFormat = utils.convert( renderTarget.texture.format ); - var glType = utils.convert( renderTarget.texture.type ); - state.texImage2D( textureTarget, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null ); - _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 ); - _gl.bindFramebuffer( _gl.FRAMEBUFFER, null ); - - } - - // Setup storage for internal depth/stencil buffers and bind to correct framebuffer - function setupRenderBufferStorage( renderbuffer, renderTarget ) { - - _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer ); - - if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) { - - _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTarget.width, renderTarget.height ); - _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer ); - - } else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) { - - _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height ); - _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer ); - - } else { - - // FIXME: We don't support !depth !stencil - _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height ); - - } - - _gl.bindRenderbuffer( _gl.RENDERBUFFER, null ); - - } - - // Setup resources for a Depth Texture for a FBO (needs an extension) - function setupDepthTexture( framebuffer, renderTarget ) { - - var isCube = ( renderTarget && renderTarget.isWebGLRenderTargetCube ); - if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' ); - - _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - - if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) { - - throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' ); - - } - - // upload an empty depth texture with framebuffer size - if ( ! properties.get( renderTarget.depthTexture ).__webglTexture || - renderTarget.depthTexture.image.width !== renderTarget.width || - renderTarget.depthTexture.image.height !== renderTarget.height ) { - - renderTarget.depthTexture.image.width = renderTarget.width; - renderTarget.depthTexture.image.height = renderTarget.height; - renderTarget.depthTexture.needsUpdate = true; - - } - - setTexture2D( renderTarget.depthTexture, 0 ); - - var webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture; - - if ( renderTarget.depthTexture.format === DepthFormat ) { - - _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); - - } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) { - - _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); - - } else { - - throw new Error( 'Unknown depthTexture format' ); - - } - - } - - // Setup GL resources for a non-texture depth buffer - function setupDepthRenderbuffer( renderTarget ) { - - var renderTargetProperties = properties.get( renderTarget ); - - var isCube = ( renderTarget.isWebGLRenderTargetCube === true ); - - if ( renderTarget.depthTexture ) { - - if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' ); - - setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget ); - - } else { - - if ( isCube ) { - - renderTargetProperties.__webglDepthbuffer = []; - - for ( var i = 0; i < 6; i ++ ) { - - _gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] ); - renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer(); - setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget ); - - } - - } else { - - _gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); - renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer(); - setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget ); - - } - - } - - _gl.bindFramebuffer( _gl.FRAMEBUFFER, null ); - - } - - // Set up GL resources for the render target - function setupRenderTarget( renderTarget ) { - - var renderTargetProperties = properties.get( renderTarget ); - var textureProperties = properties.get( renderTarget.texture ); - - renderTarget.addEventListener( 'dispose', onRenderTargetDispose ); - - textureProperties.__webglTexture = _gl.createTexture(); - - infoMemory.textures ++; - - var isCube = ( renderTarget.isWebGLRenderTargetCube === true ); - var isTargetPowerOfTwo = isPowerOfTwo( renderTarget ); - - // Setup framebuffer - - if ( isCube ) { - - renderTargetProperties.__webglFramebuffer = []; - - for ( var i = 0; i < 6; i ++ ) { - - renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer(); - - } - - } else { - - renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer(); - - } - - // Setup color buffer - - if ( isCube ) { - - state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture ); - setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, isTargetPowerOfTwo ); - - for ( var i = 0; i < 6; i ++ ) { - - setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i ); - - } - - if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP ); - state.bindTexture( _gl.TEXTURE_CUBE_MAP, null ); - - } else { - - state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture ); - setTextureParameters( _gl.TEXTURE_2D, renderTarget.texture, isTargetPowerOfTwo ); - setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D ); - - if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) _gl.generateMipmap( _gl.TEXTURE_2D ); - state.bindTexture( _gl.TEXTURE_2D, null ); - - } - - // Setup depth and stencil buffers - - if ( renderTarget.depthBuffer ) { - - setupDepthRenderbuffer( renderTarget ); - - } - - } - - function updateRenderTargetMipmap( renderTarget ) { - - var texture = renderTarget.texture; - var isTargetPowerOfTwo = isPowerOfTwo( renderTarget ); - - if ( textureNeedsGenerateMipmaps( texture, isTargetPowerOfTwo ) ) { - - var target = renderTarget.isWebGLRenderTargetCube ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D; - var webglTexture = properties.get( texture ).__webglTexture; - - state.bindTexture( target, webglTexture ); - _gl.generateMipmap( target ); - state.bindTexture( target, null ); - - } - - } - - this.setTexture2D = setTexture2D; - this.setTextureCube = setTextureCube; - this.setTextureCubeDynamic = setTextureCubeDynamic; - this.setupRenderTarget = setupRenderTarget; - this.updateRenderTargetMipmap = updateRenderTargetMipmap; - - } - - /** - * @author fordacious / fordacious.github.io - */ - - function WebGLProperties() { - - var properties = {}; - - function get( object ) { - - var uuid = object.uuid; - var map = properties[ uuid ]; - - if ( map === undefined ) { - - map = {}; - properties[ uuid ] = map; - - } - - return map; - - } - - function remove( object ) { - - delete properties[ object.uuid ]; - - } - - function clear() { - - properties = {}; - - } - - return { - get: get, - remove: remove, - clear: clear - }; - - } - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function WebGLState( gl, extensions, utils ) { - - function ColorBuffer() { - - var locked = false; - - var color = new Vector4(); - var currentColorMask = null; - var currentColorClear = new Vector4( 0, 0, 0, 0 ); - - return { - - setMask: function ( colorMask ) { - - if ( currentColorMask !== colorMask && ! locked ) { - - gl.colorMask( colorMask, colorMask, colorMask, colorMask ); - currentColorMask = colorMask; - - } - - }, - - setLocked: function ( lock ) { - - locked = lock; - - }, - - setClear: function ( r, g, b, a, premultipliedAlpha ) { - - if ( premultipliedAlpha === true ) { - - r *= a; g *= a; b *= a; - - } - - color.set( r, g, b, a ); - - if ( currentColorClear.equals( color ) === false ) { - - gl.clearColor( r, g, b, a ); - currentColorClear.copy( color ); - - } - - }, - - reset: function () { - - locked = false; - - currentColorMask = null; - currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state - - } - - }; - - } - - function DepthBuffer() { - - var locked = false; - - var currentDepthMask = null; - var currentDepthFunc = null; - var currentDepthClear = null; - - return { - - setTest: function ( depthTest ) { - - if ( depthTest ) { - - enable( gl.DEPTH_TEST ); - - } else { - - disable( gl.DEPTH_TEST ); - - } - - }, - - setMask: function ( depthMask ) { - - if ( currentDepthMask !== depthMask && ! locked ) { - - gl.depthMask( depthMask ); - currentDepthMask = depthMask; - - } - - }, - - setFunc: function ( depthFunc ) { - - if ( currentDepthFunc !== depthFunc ) { - - if ( depthFunc ) { - - switch ( depthFunc ) { - - case NeverDepth: - - gl.depthFunc( gl.NEVER ); - break; - - case AlwaysDepth: - - gl.depthFunc( gl.ALWAYS ); - break; - - case LessDepth: - - gl.depthFunc( gl.LESS ); - break; - - case LessEqualDepth: - - gl.depthFunc( gl.LEQUAL ); - break; - - case EqualDepth: - - gl.depthFunc( gl.EQUAL ); - break; - - case GreaterEqualDepth: - - gl.depthFunc( gl.GEQUAL ); - break; - - case GreaterDepth: - - gl.depthFunc( gl.GREATER ); - break; - - case NotEqualDepth: - - gl.depthFunc( gl.NOTEQUAL ); - break; - - default: - - gl.depthFunc( gl.LEQUAL ); - - } - - } else { - - gl.depthFunc( gl.LEQUAL ); - - } - - currentDepthFunc = depthFunc; - - } - - }, - - setLocked: function ( lock ) { - - locked = lock; - - }, - - setClear: function ( depth ) { - - if ( currentDepthClear !== depth ) { - - gl.clearDepth( depth ); - currentDepthClear = depth; - - } - - }, - - reset: function () { - - locked = false; - - currentDepthMask = null; - currentDepthFunc = null; - currentDepthClear = null; - - } - - }; - - } - - function StencilBuffer() { - - var locked = false; - - var currentStencilMask = null; - var currentStencilFunc = null; - var currentStencilRef = null; - var currentStencilFuncMask = null; - var currentStencilFail = null; - var currentStencilZFail = null; - var currentStencilZPass = null; - var currentStencilClear = null; - - return { - - setTest: function ( stencilTest ) { - - if ( stencilTest ) { - - enable( gl.STENCIL_TEST ); - - } else { - - disable( gl.STENCIL_TEST ); - - } - - }, - - setMask: function ( stencilMask ) { - - if ( currentStencilMask !== stencilMask && ! locked ) { - - gl.stencilMask( stencilMask ); - currentStencilMask = stencilMask; - - } - - }, - - setFunc: function ( stencilFunc, stencilRef, stencilMask ) { - - if ( currentStencilFunc !== stencilFunc || - currentStencilRef !== stencilRef || - currentStencilFuncMask !== stencilMask ) { - - gl.stencilFunc( stencilFunc, stencilRef, stencilMask ); - - currentStencilFunc = stencilFunc; - currentStencilRef = stencilRef; - currentStencilFuncMask = stencilMask; - - } - - }, - - setOp: function ( stencilFail, stencilZFail, stencilZPass ) { - - if ( currentStencilFail !== stencilFail || - currentStencilZFail !== stencilZFail || - currentStencilZPass !== stencilZPass ) { - - gl.stencilOp( stencilFail, stencilZFail, stencilZPass ); - - currentStencilFail = stencilFail; - currentStencilZFail = stencilZFail; - currentStencilZPass = stencilZPass; - - } - - }, - - setLocked: function ( lock ) { - - locked = lock; - - }, - - setClear: function ( stencil ) { - - if ( currentStencilClear !== stencil ) { - - gl.clearStencil( stencil ); - currentStencilClear = stencil; - - } - - }, - - reset: function () { - - locked = false; - - currentStencilMask = null; - currentStencilFunc = null; - currentStencilRef = null; - currentStencilFuncMask = null; - currentStencilFail = null; - currentStencilZFail = null; - currentStencilZPass = null; - currentStencilClear = null; - - } - - }; - - } - - // - - var colorBuffer = new ColorBuffer(); - var depthBuffer = new DepthBuffer(); - var stencilBuffer = new StencilBuffer(); - - var maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS ); - var newAttributes = new Uint8Array( maxVertexAttributes ); - var enabledAttributes = new Uint8Array( maxVertexAttributes ); - var attributeDivisors = new Uint8Array( maxVertexAttributes ); - - var capabilities = {}; - - var compressedTextureFormats = null; - - var currentProgram = null; - - var currentBlending = null; - var currentBlendEquation = null; - var currentBlendSrc = null; - var currentBlendDst = null; - var currentBlendEquationAlpha = null; - var currentBlendSrcAlpha = null; - var currentBlendDstAlpha = null; - var currentPremultipledAlpha = false; - - var currentFlipSided = null; - var currentCullFace = null; - - var currentLineWidth = null; - - var currentPolygonOffsetFactor = null; - var currentPolygonOffsetUnits = null; - - var maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS ); - - var version = parseFloat( /^WebGL\ ([0-9])/.exec( gl.getParameter( gl.VERSION ) )[ 1 ] ); - var lineWidthAvailable = parseFloat( version ) >= 1.0; - - var currentTextureSlot = null; - var currentBoundTextures = {}; - - var currentScissor = new Vector4(); - var currentViewport = new Vector4(); - - function createTexture( type, target, count ) { - - var data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4. - var texture = gl.createTexture(); - - gl.bindTexture( type, texture ); - gl.texParameteri( type, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); - gl.texParameteri( type, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); - - for ( var i = 0; i < count; i ++ ) { - - gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); - - } - - return texture; - - } - - var emptyTextures = {}; - emptyTextures[ gl.TEXTURE_2D ] = createTexture( gl.TEXTURE_2D, gl.TEXTURE_2D, 1 ); - emptyTextures[ gl.TEXTURE_CUBE_MAP ] = createTexture( gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6 ); - - // init - - colorBuffer.setClear( 0, 0, 0, 1 ); - depthBuffer.setClear( 1 ); - stencilBuffer.setClear( 0 ); - - enable( gl.DEPTH_TEST ); - depthBuffer.setFunc( LessEqualDepth ); - - setFlipSided( false ); - setCullFace( CullFaceBack ); - enable( gl.CULL_FACE ); - - enable( gl.BLEND ); - setBlending( NormalBlending ); - - // - - function initAttributes() { - - for ( var i = 0, l = newAttributes.length; i < l; i ++ ) { - - newAttributes[ i ] = 0; - - } - - } - - function enableAttribute( attribute ) { - - newAttributes[ attribute ] = 1; - - if ( enabledAttributes[ attribute ] === 0 ) { - - gl.enableVertexAttribArray( attribute ); - enabledAttributes[ attribute ] = 1; - - } - - if ( attributeDivisors[ attribute ] !== 0 ) { - - var extension = extensions.get( 'ANGLE_instanced_arrays' ); - - extension.vertexAttribDivisorANGLE( attribute, 0 ); - attributeDivisors[ attribute ] = 0; - - } - - } - - function enableAttributeAndDivisor( attribute, meshPerAttribute ) { - - newAttributes[ attribute ] = 1; - - if ( enabledAttributes[ attribute ] === 0 ) { - - gl.enableVertexAttribArray( attribute ); - enabledAttributes[ attribute ] = 1; - - } - - if ( attributeDivisors[ attribute ] !== meshPerAttribute ) { - - var extension = extensions.get( 'ANGLE_instanced_arrays' ); - - extension.vertexAttribDivisorANGLE( attribute, meshPerAttribute ); - attributeDivisors[ attribute ] = meshPerAttribute; - - } - - } - - function disableUnusedAttributes() { - - for ( var i = 0, l = enabledAttributes.length; i !== l; ++ i ) { - - if ( enabledAttributes[ i ] !== newAttributes[ i ] ) { - - gl.disableVertexAttribArray( i ); - enabledAttributes[ i ] = 0; - - } - - } - - } - - function enable( id ) { - - if ( capabilities[ id ] !== true ) { - - gl.enable( id ); - capabilities[ id ] = true; - - } - - } - - function disable( id ) { - - if ( capabilities[ id ] !== false ) { - - gl.disable( id ); - capabilities[ id ] = false; - - } - - } - - function getCompressedTextureFormats() { - - if ( compressedTextureFormats === null ) { - - compressedTextureFormats = []; - - if ( extensions.get( 'WEBGL_compressed_texture_pvrtc' ) || - extensions.get( 'WEBGL_compressed_texture_s3tc' ) || - extensions.get( 'WEBGL_compressed_texture_etc1' ) ) { - - var formats = gl.getParameter( gl.COMPRESSED_TEXTURE_FORMATS ); - - for ( var i = 0; i < formats.length; i ++ ) { - - compressedTextureFormats.push( formats[ i ] ); - - } - - } - - } - - return compressedTextureFormats; - - } - - function useProgram( program ) { - - if ( currentProgram !== program ) { - - gl.useProgram( program ); - - currentProgram = program; - - return true; - - } - - return false; - - } - - function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) { - - if ( blending !== NoBlending ) { - - enable( gl.BLEND ); - - } else { - - disable( gl.BLEND ); - - } - - if ( blending !== CustomBlending ) { - - if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) { - - switch ( blending ) { - - case AdditiveBlending: - - if ( premultipliedAlpha ) { - - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ONE, gl.ONE, gl.ONE, gl.ONE ); - - } else { - - gl.blendEquation( gl.FUNC_ADD ); - gl.blendFunc( gl.SRC_ALPHA, gl.ONE ); - - } - break; - - case SubtractiveBlending: - - if ( premultipliedAlpha ) { - - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ZERO, gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ONE_MINUS_SRC_ALPHA ); - - } else { - - gl.blendEquation( gl.FUNC_ADD ); - gl.blendFunc( gl.ZERO, gl.ONE_MINUS_SRC_COLOR ); - - } - break; - - case MultiplyBlending: - - if ( premultipliedAlpha ) { - - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA ); - - } else { - - gl.blendEquation( gl.FUNC_ADD ); - gl.blendFunc( gl.ZERO, gl.SRC_COLOR ); - - } - break; - - default: - - if ( premultipliedAlpha ) { - - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); - - } else { - - gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); - gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); - - } - - } - - } - - currentBlendEquation = null; - currentBlendSrc = null; - currentBlendDst = null; - currentBlendEquationAlpha = null; - currentBlendSrcAlpha = null; - currentBlendDstAlpha = null; - - } else { - - blendEquationAlpha = blendEquationAlpha || blendEquation; - blendSrcAlpha = blendSrcAlpha || blendSrc; - blendDstAlpha = blendDstAlpha || blendDst; - - if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) { - - gl.blendEquationSeparate( utils.convert( blendEquation ), utils.convert( blendEquationAlpha ) ); - - currentBlendEquation = blendEquation; - currentBlendEquationAlpha = blendEquationAlpha; - - } - - if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) { - - gl.blendFuncSeparate( utils.convert( blendSrc ), utils.convert( blendDst ), utils.convert( blendSrcAlpha ), utils.convert( blendDstAlpha ) ); - - currentBlendSrc = blendSrc; - currentBlendDst = blendDst; - currentBlendSrcAlpha = blendSrcAlpha; - currentBlendDstAlpha = blendDstAlpha; - - } - - } - - currentBlending = blending; - currentPremultipledAlpha = premultipliedAlpha; - - } - - function setMaterial( material ) { - - material.side === DoubleSide - ? disable( gl.CULL_FACE ) - : enable( gl.CULL_FACE ); - - setFlipSided( material.side === BackSide ); - - material.transparent === true - ? setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha ) - : setBlending( NoBlending ); - - depthBuffer.setFunc( material.depthFunc ); - depthBuffer.setTest( material.depthTest ); - depthBuffer.setMask( material.depthWrite ); - colorBuffer.setMask( material.colorWrite ); - - setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); - - } - - // - - function setFlipSided( flipSided ) { - - if ( currentFlipSided !== flipSided ) { - - if ( flipSided ) { - - gl.frontFace( gl.CW ); - - } else { - - gl.frontFace( gl.CCW ); - - } - - currentFlipSided = flipSided; - - } - - } - - function setCullFace( cullFace ) { - - if ( cullFace !== CullFaceNone ) { - - enable( gl.CULL_FACE ); - - if ( cullFace !== currentCullFace ) { - - if ( cullFace === CullFaceBack ) { - - gl.cullFace( gl.BACK ); - - } else if ( cullFace === CullFaceFront ) { - - gl.cullFace( gl.FRONT ); - - } else { - - gl.cullFace( gl.FRONT_AND_BACK ); - - } - - } - - } else { - - disable( gl.CULL_FACE ); - - } - - currentCullFace = cullFace; - - } - - function setLineWidth( width ) { - - if ( width !== currentLineWidth ) { - - if ( lineWidthAvailable ) gl.lineWidth( width ); - - currentLineWidth = width; - - } - - } - - function setPolygonOffset( polygonOffset, factor, units ) { - - if ( polygonOffset ) { - - enable( gl.POLYGON_OFFSET_FILL ); - - if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) { - - gl.polygonOffset( factor, units ); - - currentPolygonOffsetFactor = factor; - currentPolygonOffsetUnits = units; - - } - - } else { - - disable( gl.POLYGON_OFFSET_FILL ); - - } - - } - - function setScissorTest( scissorTest ) { - - if ( scissorTest ) { - - enable( gl.SCISSOR_TEST ); - - } else { - - disable( gl.SCISSOR_TEST ); - - } - - } - - // texture - - function activeTexture( webglSlot ) { - - if ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1; - - if ( currentTextureSlot !== webglSlot ) { - - gl.activeTexture( webglSlot ); - currentTextureSlot = webglSlot; - - } - - } - - function bindTexture( webglType, webglTexture ) { - - if ( currentTextureSlot === null ) { - - activeTexture(); - - } - - var boundTexture = currentBoundTextures[ currentTextureSlot ]; - - if ( boundTexture === undefined ) { - - boundTexture = { type: undefined, texture: undefined }; - currentBoundTextures[ currentTextureSlot ] = boundTexture; - - } - - if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) { - - gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] ); - - boundTexture.type = webglType; - boundTexture.texture = webglTexture; - - } - - } - - function compressedTexImage2D() { - - try { - - gl.compressedTexImage2D.apply( gl, arguments ); - - } catch ( error ) { - - console.error( 'THREE.WebGLState:', error ); - - } - - } - - function texImage2D() { - - try { - - gl.texImage2D.apply( gl, arguments ); - - } catch ( error ) { - - console.error( 'THREE.WebGLState:', error ); - - } - - } - - // - - function scissor( scissor ) { - - if ( currentScissor.equals( scissor ) === false ) { - - gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w ); - currentScissor.copy( scissor ); - - } - - } - - function viewport( viewport ) { - - if ( currentViewport.equals( viewport ) === false ) { - - gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w ); - currentViewport.copy( viewport ); - - } - - } - - // - - function reset() { - - for ( var i = 0; i < enabledAttributes.length; i ++ ) { - - if ( enabledAttributes[ i ] === 1 ) { - - gl.disableVertexAttribArray( i ); - enabledAttributes[ i ] = 0; - - } - - } - - capabilities = {}; - - compressedTextureFormats = null; - - currentTextureSlot = null; - currentBoundTextures = {}; - - currentProgram = null; - - currentBlending = null; - - currentFlipSided = null; - currentCullFace = null; - - colorBuffer.reset(); - depthBuffer.reset(); - stencilBuffer.reset(); - - } - - return { - - buffers: { - color: colorBuffer, - depth: depthBuffer, - stencil: stencilBuffer - }, - - initAttributes: initAttributes, - enableAttribute: enableAttribute, - enableAttributeAndDivisor: enableAttributeAndDivisor, - disableUnusedAttributes: disableUnusedAttributes, - enable: enable, - disable: disable, - getCompressedTextureFormats: getCompressedTextureFormats, - - useProgram: useProgram, - - setBlending: setBlending, - setMaterial: setMaterial, - - setFlipSided: setFlipSided, - setCullFace: setCullFace, - - setLineWidth: setLineWidth, - setPolygonOffset: setPolygonOffset, - - setScissorTest: setScissorTest, - - activeTexture: activeTexture, - bindTexture: bindTexture, - compressedTexImage2D: compressedTexImage2D, - texImage2D: texImage2D, - - scissor: scissor, - viewport: viewport, - - reset: reset - - }; - - } - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function WebGLCapabilities( gl, extensions, parameters ) { - - var maxAnisotropy; - - function getMaxAnisotropy() { - - if ( maxAnisotropy !== undefined ) return maxAnisotropy; - - var extension = extensions.get( 'EXT_texture_filter_anisotropic' ); - - if ( extension !== null ) { - - maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT ); - - } else { - - maxAnisotropy = 0; - - } - - return maxAnisotropy; - - } - - function getMaxPrecision( precision ) { - - if ( precision === 'highp' ) { - - if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 && - gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) { - - return 'highp'; - - } - - precision = 'mediump'; - - } - - if ( precision === 'mediump' ) { - - if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 && - gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) { - - return 'mediump'; - - } - - } - - return 'lowp'; - - } - - var precision = parameters.precision !== undefined ? parameters.precision : 'highp'; - var maxPrecision = getMaxPrecision( precision ); - - if ( maxPrecision !== precision ) { - - console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' ); - precision = maxPrecision; - - } - - var logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true; - - var maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS ); - var maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ); - var maxTextureSize = gl.getParameter( gl.MAX_TEXTURE_SIZE ); - var maxCubemapSize = gl.getParameter( gl.MAX_CUBE_MAP_TEXTURE_SIZE ); - - var maxAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS ); - var maxVertexUniforms = gl.getParameter( gl.MAX_VERTEX_UNIFORM_VECTORS ); - var maxVaryings = gl.getParameter( gl.MAX_VARYING_VECTORS ); - var maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS ); - - var vertexTextures = maxVertexTextures > 0; - var floatFragmentTextures = !! extensions.get( 'OES_texture_float' ); - var floatVertexTextures = vertexTextures && floatFragmentTextures; - - return { - - getMaxAnisotropy: getMaxAnisotropy, - getMaxPrecision: getMaxPrecision, - - precision: precision, - logarithmicDepthBuffer: logarithmicDepthBuffer, - - maxTextures: maxTextures, - maxVertexTextures: maxVertexTextures, - maxTextureSize: maxTextureSize, - maxCubemapSize: maxCubemapSize, - - maxAttributes: maxAttributes, - maxVertexUniforms: maxVertexUniforms, - maxVaryings: maxVaryings, - maxFragmentUniforms: maxFragmentUniforms, - - vertexTextures: vertexTextures, - floatFragmentTextures: floatFragmentTextures, - floatVertexTextures: floatVertexTextures - - }; - - } - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function WebVRManager( renderer ) { - - var scope = this; - - var device = null; - var frameData = null; - - if ( typeof window !== 'undefined' && 'VRFrameData' in window ) { - - frameData = new window.VRFrameData(); - - } - - var matrixWorldInverse = new Matrix4(); - - var standingMatrix = new Matrix4(); - var standingMatrixInverse = new Matrix4(); - - var cameraL = new PerspectiveCamera(); - cameraL.bounds = new Vector4( 0.0, 0.0, 0.5, 1.0 ); - cameraL.layers.enable( 1 ); - - var cameraR = new PerspectiveCamera(); - cameraR.bounds = new Vector4( 0.5, 0.0, 0.5, 1.0 ); - cameraR.layers.enable( 2 ); - - var cameraVR = new ArrayCamera( [ cameraL, cameraR ] ); - cameraVR.layers.enable( 1 ); - cameraVR.layers.enable( 2 ); - - // - - var currentSize, currentPixelRatio; - - function onVRDisplayPresentChange() { - - if ( device !== null && device.isPresenting ) { - - var eyeParameters = device.getEyeParameters( 'left' ); - var renderWidth = eyeParameters.renderWidth; - var renderHeight = eyeParameters.renderHeight; - - currentPixelRatio = renderer.getPixelRatio(); - currentSize = renderer.getSize(); - - renderer.setDrawingBufferSize( renderWidth * 2, renderHeight, 1 ); - - } else if ( scope.enabled ) { - - renderer.setDrawingBufferSize( currentSize.width, currentSize.height, currentPixelRatio ); - - } - - } - - if ( typeof window !== 'undefined' ) { - - window.addEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange, false ); - - } - - // - - this.enabled = false; - this.standing = false; - - this.getDevice = function () { - - return device; - - }; - - this.setDevice = function ( value ) { - - if ( value !== undefined ) device = value; - - }; - - this.getCamera = function ( camera ) { - - if ( device === null ) return camera; - - device.depthNear = camera.near; - device.depthFar = camera.far; - - device.getFrameData( frameData ); - - // - - var pose = frameData.pose; - - if ( pose.position !== null ) { - - camera.position.fromArray( pose.position ); - - } else { - - camera.position.set( 0, 0, 0 ); - - } - - if ( pose.orientation !== null ) { - - camera.quaternion.fromArray( pose.orientation ); - - } - - camera.updateMatrixWorld(); - - var stageParameters = device.stageParameters; - - if ( this.standing && stageParameters ) { - - standingMatrix.fromArray( stageParameters.sittingToStandingTransform ); - standingMatrixInverse.getInverse( standingMatrix ); - - camera.matrixWorld.multiply( standingMatrix ); - camera.matrixWorldInverse.multiply( standingMatrixInverse ); - - } - - if ( device.isPresenting === false ) return camera; - - // - - cameraL.near = camera.near; - cameraR.near = camera.near; - - cameraL.far = camera.far; - cameraR.far = camera.far; - - cameraVR.matrixWorld.copy( camera.matrixWorld ); - cameraVR.matrixWorldInverse.copy( camera.matrixWorldInverse ); - - cameraL.matrixWorldInverse.fromArray( frameData.leftViewMatrix ); - cameraR.matrixWorldInverse.fromArray( frameData.rightViewMatrix ); - - if ( this.standing && stageParameters ) { - - cameraL.matrixWorldInverse.multiply( standingMatrixInverse ); - cameraR.matrixWorldInverse.multiply( standingMatrixInverse ); - - } - - var parent = camera.parent; - - if ( parent !== null ) { - - matrixWorldInverse.getInverse( parent.matrixWorld ); - - cameraL.matrixWorldInverse.multiply( matrixWorldInverse ); - cameraR.matrixWorldInverse.multiply( matrixWorldInverse ); - - } - - // envMap and Mirror needs camera.matrixWorld - - cameraL.matrixWorld.getInverse( cameraL.matrixWorldInverse ); - cameraR.matrixWorld.getInverse( cameraR.matrixWorldInverse ); - - cameraL.projectionMatrix.fromArray( frameData.leftProjectionMatrix ); - cameraR.projectionMatrix.fromArray( frameData.rightProjectionMatrix ); - - // HACK @mrdoob - // https://github.com/w3c/webvr/issues/203 - - cameraVR.projectionMatrix.copy( cameraL.projectionMatrix ); - - // - - var layers = device.getLayers(); - - if ( layers.length ) { - - var layer = layers[ 0 ]; - - if ( layer.leftBounds !== null && layer.leftBounds.length === 4 ) { - - cameraL.bounds.fromArray( layer.leftBounds ); - - } - - if ( layer.rightBounds !== null && layer.rightBounds.length === 4 ) { - - cameraR.bounds.fromArray( layer.rightBounds ); - - } - - } - - return cameraVR; - - }; - - this.getStandingMatrix = function () { - - return standingMatrix; - - }; - - this.submitFrame = function () { - - if ( device && device.isPresenting ) device.submitFrame(); - - }; - - this.dispose = function () { - - window.removeEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange ); - - }; - - } - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - function WebGLExtensions( gl ) { - - var extensions = {}; - - return { - - get: function ( name ) { - - if ( extensions[ name ] !== undefined ) { - - return extensions[ name ]; - - } - - var extension; - - switch ( name ) { - - case 'WEBGL_depth_texture': - extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' ); - break; - - case 'EXT_texture_filter_anisotropic': - extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' ); - break; - - case 'WEBGL_compressed_texture_s3tc': - extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' ); - break; - - case 'WEBGL_compressed_texture_pvrtc': - extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' ); - break; - - case 'WEBGL_compressed_texture_etc1': - extension = gl.getExtension( 'WEBGL_compressed_texture_etc1' ); - break; - - default: - extension = gl.getExtension( name ); - - } - - if ( extension === null ) { - - console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' ); - - } - - extensions[ name ] = extension; - - return extension; - - } - - }; - - } - - /** - * @author tschw - */ - - function WebGLClipping() { - - var scope = this, - - globalState = null, - numGlobalPlanes = 0, - localClippingEnabled = false, - renderingShadows = false, - - plane = new Plane(), - viewNormalMatrix = new Matrix3(), - - uniform = { value: null, needsUpdate: false }; - - this.uniform = uniform; - this.numPlanes = 0; - this.numIntersection = 0; - - this.init = function ( planes, enableLocalClipping, camera ) { - - var enabled = - planes.length !== 0 || - enableLocalClipping || - // enable state of previous frame - the clipping code has to - // run another frame in order to reset the state: - numGlobalPlanes !== 0 || - localClippingEnabled; - - localClippingEnabled = enableLocalClipping; - - globalState = projectPlanes( planes, camera, 0 ); - numGlobalPlanes = planes.length; - - return enabled; - - }; - - this.beginShadows = function () { - - renderingShadows = true; - projectPlanes( null ); - - }; - - this.endShadows = function () { - - renderingShadows = false; - resetGlobalState(); - - }; - - this.setState = function ( planes, clipIntersection, clipShadows, camera, cache, fromCache ) { - - if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) { - - // there's no local clipping - - if ( renderingShadows ) { - - // there's no global clipping - - projectPlanes( null ); - - } else { - - resetGlobalState(); - - } - - } else { - - var nGlobal = renderingShadows ? 0 : numGlobalPlanes, - lGlobal = nGlobal * 4, - - dstArray = cache.clippingState || null; - - uniform.value = dstArray; // ensure unique state - - dstArray = projectPlanes( planes, camera, lGlobal, fromCache ); - - for ( var i = 0; i !== lGlobal; ++ i ) { - - dstArray[ i ] = globalState[ i ]; - - } - - cache.clippingState = dstArray; - this.numIntersection = clipIntersection ? this.numPlanes : 0; - this.numPlanes += nGlobal; - - } - - - }; - - function resetGlobalState() { - - if ( uniform.value !== globalState ) { - - uniform.value = globalState; - uniform.needsUpdate = numGlobalPlanes > 0; - - } - - scope.numPlanes = numGlobalPlanes; - scope.numIntersection = 0; - - } - - function projectPlanes( planes, camera, dstOffset, skipTransform ) { - - var nPlanes = planes !== null ? planes.length : 0, - dstArray = null; - - if ( nPlanes !== 0 ) { - - dstArray = uniform.value; - - if ( skipTransform !== true || dstArray === null ) { - - var flatSize = dstOffset + nPlanes * 4, - viewMatrix = camera.matrixWorldInverse; - - viewNormalMatrix.getNormalMatrix( viewMatrix ); - - if ( dstArray === null || dstArray.length < flatSize ) { - - dstArray = new Float32Array( flatSize ); - - } - - for ( var i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) { - - plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix ); - - plane.normal.toArray( dstArray, i4 ); - dstArray[ i4 + 3 ] = plane.constant; - - } - - } - - uniform.value = dstArray; - uniform.needsUpdate = true; - - } - - scope.numPlanes = nPlanes; - - return dstArray; - - } - - } - - /** - * @author thespite / http://www.twitter.com/thespite - */ - - function WebGLUtils( gl, extensions ) { - - function convert( p ) { - - var extension; - - if ( p === RepeatWrapping ) return gl.REPEAT; - if ( p === ClampToEdgeWrapping ) return gl.CLAMP_TO_EDGE; - if ( p === MirroredRepeatWrapping ) return gl.MIRRORED_REPEAT; - - if ( p === NearestFilter ) return gl.NEAREST; - if ( p === NearestMipMapNearestFilter ) return gl.NEAREST_MIPMAP_NEAREST; - if ( p === NearestMipMapLinearFilter ) return gl.NEAREST_MIPMAP_LINEAR; - - if ( p === LinearFilter ) return gl.LINEAR; - if ( p === LinearMipMapNearestFilter ) return gl.LINEAR_MIPMAP_NEAREST; - if ( p === LinearMipMapLinearFilter ) return gl.LINEAR_MIPMAP_LINEAR; - - if ( p === UnsignedByteType ) return gl.UNSIGNED_BYTE; - if ( p === UnsignedShort4444Type ) return gl.UNSIGNED_SHORT_4_4_4_4; - if ( p === UnsignedShort5551Type ) return gl.UNSIGNED_SHORT_5_5_5_1; - if ( p === UnsignedShort565Type ) return gl.UNSIGNED_SHORT_5_6_5; - - if ( p === ByteType ) return gl.BYTE; - if ( p === ShortType ) return gl.SHORT; - if ( p === UnsignedShortType ) return gl.UNSIGNED_SHORT; - if ( p === IntType ) return gl.INT; - if ( p === UnsignedIntType ) return gl.UNSIGNED_INT; - if ( p === FloatType ) return gl.FLOAT; - - if ( p === HalfFloatType ) { - - extension = extensions.get( 'OES_texture_half_float' ); - - if ( extension !== null ) return extension.HALF_FLOAT_OES; - - } - - if ( p === AlphaFormat ) return gl.ALPHA; - if ( p === RGBFormat ) return gl.RGB; - if ( p === RGBAFormat ) return gl.RGBA; - if ( p === LuminanceFormat ) return gl.LUMINANCE; - if ( p === LuminanceAlphaFormat ) return gl.LUMINANCE_ALPHA; - if ( p === DepthFormat ) return gl.DEPTH_COMPONENT; - if ( p === DepthStencilFormat ) return gl.DEPTH_STENCIL; - - if ( p === AddEquation ) return gl.FUNC_ADD; - if ( p === SubtractEquation ) return gl.FUNC_SUBTRACT; - if ( p === ReverseSubtractEquation ) return gl.FUNC_REVERSE_SUBTRACT; - - if ( p === ZeroFactor ) return gl.ZERO; - if ( p === OneFactor ) return gl.ONE; - if ( p === SrcColorFactor ) return gl.SRC_COLOR; - if ( p === OneMinusSrcColorFactor ) return gl.ONE_MINUS_SRC_COLOR; - if ( p === SrcAlphaFactor ) return gl.SRC_ALPHA; - if ( p === OneMinusSrcAlphaFactor ) return gl.ONE_MINUS_SRC_ALPHA; - if ( p === DstAlphaFactor ) return gl.DST_ALPHA; - if ( p === OneMinusDstAlphaFactor ) return gl.ONE_MINUS_DST_ALPHA; - - if ( p === DstColorFactor ) return gl.DST_COLOR; - if ( p === OneMinusDstColorFactor ) return gl.ONE_MINUS_DST_COLOR; - if ( p === SrcAlphaSaturateFactor ) return gl.SRC_ALPHA_SATURATE; - - if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || - p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { - - extension = extensions.get( 'WEBGL_compressed_texture_s3tc' ); - - if ( extension !== null ) { - - if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT; - if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT; - if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT; - if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT; - - } - - } - - if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || - p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) { - - extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' ); - - if ( extension !== null ) { - - if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG; - if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG; - if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; - if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; - - } - - } - - if ( p === RGB_ETC1_Format ) { - - extension = extensions.get( 'WEBGL_compressed_texture_etc1' ); - - if ( extension !== null ) return extension.COMPRESSED_RGB_ETC1_WEBGL; - - } - - if ( p === MinEquation || p === MaxEquation ) { - - extension = extensions.get( 'EXT_blend_minmax' ); - - if ( extension !== null ) { - - if ( p === MinEquation ) return extension.MIN_EXT; - if ( p === MaxEquation ) return extension.MAX_EXT; - - } - - } - - if ( p === UnsignedInt248Type ) { - - extension = extensions.get( 'WEBGL_depth_texture' ); - - if ( extension !== null ) return extension.UNSIGNED_INT_24_8_WEBGL; - - } - - return 0; - - } - - return { convert: convert }; - - } - - function WebGLRenderer( parameters ) { - - console.log( 'THREE.WebGLRenderer', REVISION ); - - parameters = parameters || {}; - - var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ), - _context = parameters.context !== undefined ? parameters.context : null, - - _alpha = parameters.alpha !== undefined ? parameters.alpha : false, - _depth = parameters.depth !== undefined ? parameters.depth : true, - _stencil = parameters.stencil !== undefined ? parameters.stencil : true, - _antialias = parameters.antialias !== undefined ? parameters.antialias : false, - _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true, - _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false; - - var lightsArray = []; - var shadowsArray = []; - - var currentRenderList = null; - - var spritesArray = []; - var flaresArray = []; - - // public properties - - this.domElement = _canvas; - this.context = null; - - // clearing - - this.autoClear = true; - this.autoClearColor = true; - this.autoClearDepth = true; - this.autoClearStencil = true; - - // scene graph - - this.sortObjects = true; - - // user-defined clipping - - this.clippingPlanes = []; - this.localClippingEnabled = false; - - // physically based shading - - this.gammaFactor = 2.0; // for backwards compatibility - this.gammaInput = false; - this.gammaOutput = false; - - // physical lights - - this.physicallyCorrectLights = false; - - // tone mapping - - this.toneMapping = LinearToneMapping; - this.toneMappingExposure = 1.0; - this.toneMappingWhitePoint = 1.0; - - // morphs - - this.maxMorphTargets = 8; - this.maxMorphNormals = 4; - - // internal properties - - var _this = this, - - _isContextLost = false, - - // internal state cache - - _currentRenderTarget = null, - _currentFramebuffer = null, - _currentMaterialId = - 1, - _currentGeometryProgram = '', - - _currentCamera = null, - _currentArrayCamera = null, - - _currentViewport = new Vector4(), - _currentScissor = new Vector4(), - _currentScissorTest = null, - - // - - _usedTextureUnits = 0, - - // - - _width = _canvas.width, - _height = _canvas.height, - - _pixelRatio = 1, - - _viewport = new Vector4( 0, 0, _width, _height ), - _scissor = new Vector4( 0, 0, _width, _height ), - _scissorTest = false, - - // frustum - - _frustum = new Frustum(), - - // clipping - - _clipping = new WebGLClipping(), - _clippingEnabled = false, - _localClippingEnabled = false, - - // camera matrices cache - - _projScreenMatrix = new Matrix4(), - - _vector3 = new Vector3(), - - // info - - _infoMemory = { - geometries: 0, - textures: 0 - }, - - _infoRender = { - - frame: 0, - calls: 0, - vertices: 0, - faces: 0, - points: 0 - - }; - - this.info = { - - render: _infoRender, - memory: _infoMemory, - programs: null - - }; - - function getTargetPixelRatio() { - - return _currentRenderTarget === null ? _pixelRatio : 1; - - } - - // initialize - - var _gl; - - try { - - var contextAttributes = { - alpha: _alpha, - depth: _depth, - stencil: _stencil, - antialias: _antialias, - premultipliedAlpha: _premultipliedAlpha, - preserveDrawingBuffer: _preserveDrawingBuffer - }; - - _gl = _context || _canvas.getContext( 'webgl', contextAttributes ) || _canvas.getContext( 'experimental-webgl', contextAttributes ); - - if ( _gl === null ) { - - if ( _canvas.getContext( 'webgl' ) !== null ) { - - throw 'Error creating WebGL context with your selected attributes.'; - - } else { - - throw 'Error creating WebGL context.'; - - } - - } - - // Some experimental-webgl implementations do not have getShaderPrecisionFormat - - if ( _gl.getShaderPrecisionFormat === undefined ) { - - _gl.getShaderPrecisionFormat = function () { - - return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 }; - - }; - - } - - _canvas.addEventListener( 'webglcontextlost', onContextLost, false ); - _canvas.addEventListener( 'webglcontextrestored', onContextRestore, false ); - - } catch ( error ) { - - console.error( 'THREE.WebGLRenderer: ' + error ); - - } - - var extensions, capabilities, state; - var properties, textures, attributes, geometries, objects, lights; - var programCache, renderLists; - - var background, morphtargets, bufferRenderer, indexedBufferRenderer; - var flareRenderer, spriteRenderer; - - var utils; - - function initGLContext() { - - extensions = new WebGLExtensions( _gl ); - extensions.get( 'WEBGL_depth_texture' ); - extensions.get( 'OES_texture_float' ); - extensions.get( 'OES_texture_float_linear' ); - extensions.get( 'OES_texture_half_float' ); - extensions.get( 'OES_texture_half_float_linear' ); - extensions.get( 'OES_standard_derivatives' ); - extensions.get( 'OES_element_index_uint' ); - extensions.get( 'ANGLE_instanced_arrays' ); - - utils = new WebGLUtils( _gl, extensions ); - - capabilities = new WebGLCapabilities( _gl, extensions, parameters ); - - state = new WebGLState( _gl, extensions, utils ); - state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) ); - state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) ); - - properties = new WebGLProperties(); - textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, _infoMemory ); - attributes = new WebGLAttributes( _gl ); - geometries = new WebGLGeometries( _gl, attributes, _infoMemory ); - objects = new WebGLObjects( geometries, _infoRender ); - morphtargets = new WebGLMorphtargets( _gl ); - programCache = new WebGLPrograms( _this, extensions, capabilities ); - lights = new WebGLLights(); - renderLists = new WebGLRenderLists(); - - background = new WebGLBackground( _this, state, geometries, _premultipliedAlpha ); - - bufferRenderer = new WebGLBufferRenderer( _gl, extensions, _infoRender ); - indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, _infoRender ); - - flareRenderer = new WebGLFlareRenderer( _this, _gl, state, textures, capabilities ); - spriteRenderer = new WebGLSpriteRenderer( _this, _gl, state, textures, capabilities ); - - _this.info.programs = programCache.programs; - - _this.context = _gl; - _this.capabilities = capabilities; - _this.extensions = extensions; - _this.properties = properties; - _this.renderLists = renderLists; - _this.state = state; - - } - - initGLContext(); - - // vr - - var vr = new WebVRManager( _this ); - - this.vr = vr; - - // shadow map - - var shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize ); - - this.shadowMap = shadowMap; - - // API - - this.getContext = function () { - - return _gl; - - }; - - this.getContextAttributes = function () { - - return _gl.getContextAttributes(); - - }; - - this.forceContextLoss = function () { - - var extension = extensions.get( 'WEBGL_lose_context' ); - if ( extension ) extension.loseContext(); - - }; - - this.forceContextRestore = function () { - - var extension = extensions.get( 'WEBGL_lose_context' ); - if ( extension ) extension.restoreContext(); - - }; - - this.getPixelRatio = function () { - - return _pixelRatio; - - }; - - this.setPixelRatio = function ( value ) { - - if ( value === undefined ) return; - - _pixelRatio = value; - - this.setSize( _width, _height, false ); - - }; - - this.getSize = function () { - - return { - width: _width, - height: _height - }; - - }; - - this.setSize = function ( width, height, updateStyle ) { - - var device = vr.getDevice(); - - if ( device && device.isPresenting ) { - - console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); - return; - - } - - _width = width; - _height = height; - - _canvas.width = width * _pixelRatio; - _canvas.height = height * _pixelRatio; - - if ( updateStyle !== false ) { - - _canvas.style.width = width + 'px'; - _canvas.style.height = height + 'px'; - - } - - this.setViewport( 0, 0, width, height ); - - }; - - this.getDrawingBufferSize = function () { - - return { - width: _width * _pixelRatio, - height: _height * _pixelRatio - }; - - }; - - this.setDrawingBufferSize = function ( width, height, pixelRatio ) { - - _width = width; - _height = height; - - _pixelRatio = pixelRatio; - - _canvas.width = width * pixelRatio; - _canvas.height = height * pixelRatio; - - this.setViewport( 0, 0, width, height ); - - }; - - this.setViewport = function ( x, y, width, height ) { - - _viewport.set( x, _height - y - height, width, height ); - state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) ); - - }; - - this.setScissor = function ( x, y, width, height ) { - - _scissor.set( x, _height - y - height, width, height ); - state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) ); - - }; - - this.setScissorTest = function ( boolean ) { - - state.setScissorTest( _scissorTest = boolean ); - - }; - - // Clearing - - this.getClearColor = function () { - - return background.getClearColor(); - - }; - - this.setClearColor = function () { - - background.setClearColor.apply( background, arguments ); - - }; - - this.getClearAlpha = function () { - - return background.getClearAlpha(); - - }; - - this.setClearAlpha = function () { - - background.setClearAlpha.apply( background, arguments ); - - }; - - this.clear = function ( color, depth, stencil ) { - - var bits = 0; - - if ( color === undefined || color ) bits |= _gl.COLOR_BUFFER_BIT; - if ( depth === undefined || depth ) bits |= _gl.DEPTH_BUFFER_BIT; - if ( stencil === undefined || stencil ) bits |= _gl.STENCIL_BUFFER_BIT; - - _gl.clear( bits ); - - }; - - this.clearColor = function () { - - this.clear( true, false, false ); - - }; - - this.clearDepth = function () { - - this.clear( false, true, false ); - - }; - - this.clearStencil = function () { - - this.clear( false, false, true ); - - }; - - this.clearTarget = function ( renderTarget, color, depth, stencil ) { - - this.setRenderTarget( renderTarget ); - this.clear( color, depth, stencil ); - - }; - - // - - this.dispose = function () { - - _canvas.removeEventListener( 'webglcontextlost', onContextLost, false ); - _canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false ); - - renderLists.dispose(); - - vr.dispose(); - - }; - - // Events - - function onContextLost( event ) { - - event.preventDefault(); - - console.log( 'THREE.WebGLRenderer: Context Lost.' ); - - _isContextLost = true; - - } - - function onContextRestore( /* event */ ) { - - console.log( 'THREE.WebGLRenderer: Context Restored.' ); - - _isContextLost = false; - - initGLContext(); - - } - - function onMaterialDispose( event ) { - - var material = event.target; - - material.removeEventListener( 'dispose', onMaterialDispose ); - - deallocateMaterial( material ); - - } - - // Buffer deallocation - - function deallocateMaterial( material ) { - - releaseMaterialProgramReference( material ); - - properties.remove( material ); - - } - - - function releaseMaterialProgramReference( material ) { - - var programInfo = properties.get( material ).program; - - material.program = undefined; - - if ( programInfo !== undefined ) { - - programCache.releaseProgram( programInfo ); - - } - - } - - // Buffer rendering - - function renderObjectImmediate( object, program, material ) { - - object.render( function ( object ) { - - _this.renderBufferImmediate( object, program, material ); - - } ); - - } - - this.renderBufferImmediate = function ( object, program, material ) { - - state.initAttributes(); - - var buffers = properties.get( object ); - - if ( object.hasPositions && ! buffers.position ) buffers.position = _gl.createBuffer(); - if ( object.hasNormals && ! buffers.normal ) buffers.normal = _gl.createBuffer(); - if ( object.hasUvs && ! buffers.uv ) buffers.uv = _gl.createBuffer(); - if ( object.hasColors && ! buffers.color ) buffers.color = _gl.createBuffer(); - - var programAttributes = program.getAttributes(); - - if ( object.hasPositions ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.position ); - _gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW ); - - state.enableAttribute( programAttributes.position ); - _gl.vertexAttribPointer( programAttributes.position, 3, _gl.FLOAT, false, 0, 0 ); - - } - - if ( object.hasNormals ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.normal ); - - if ( ! material.isMeshPhongMaterial && - ! material.isMeshStandardMaterial && - ! material.isMeshNormalMaterial && - material.flatShading === true ) { - - for ( var i = 0, l = object.count * 3; i < l; i += 9 ) { - - var array = object.normalArray; - - var nx = ( array[ i + 0 ] + array[ i + 3 ] + array[ i + 6 ] ) / 3; - var ny = ( array[ i + 1 ] + array[ i + 4 ] + array[ i + 7 ] ) / 3; - var nz = ( array[ i + 2 ] + array[ i + 5 ] + array[ i + 8 ] ) / 3; - - array[ i + 0 ] = nx; - array[ i + 1 ] = ny; - array[ i + 2 ] = nz; - - array[ i + 3 ] = nx; - array[ i + 4 ] = ny; - array[ i + 5 ] = nz; - - array[ i + 6 ] = nx; - array[ i + 7 ] = ny; - array[ i + 8 ] = nz; - - } - - } - - _gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW ); - - state.enableAttribute( programAttributes.normal ); - - _gl.vertexAttribPointer( programAttributes.normal, 3, _gl.FLOAT, false, 0, 0 ); - - } - - if ( object.hasUvs && material.map ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.uv ); - _gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW ); - - state.enableAttribute( programAttributes.uv ); - - _gl.vertexAttribPointer( programAttributes.uv, 2, _gl.FLOAT, false, 0, 0 ); - - } - - if ( object.hasColors && material.vertexColors !== NoColors ) { - - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.color ); - _gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW ); - - state.enableAttribute( programAttributes.color ); - - _gl.vertexAttribPointer( programAttributes.color, 3, _gl.FLOAT, false, 0, 0 ); - - } - - state.disableUnusedAttributes(); - - _gl.drawArrays( _gl.TRIANGLES, 0, object.count ); - - object.count = 0; - - }; - - this.renderBufferDirect = function ( camera, fog, geometry, material, object, group ) { - - state.setMaterial( material ); - - var program = setProgram( camera, fog, material, object ); - var geometryProgram = geometry.id + '_' + program.id + '_' + ( material.wireframe === true ); - - var updateBuffers = false; - - if ( geometryProgram !== _currentGeometryProgram ) { - - _currentGeometryProgram = geometryProgram; - updateBuffers = true; - - } - - if ( object.morphTargetInfluences ) { - - morphtargets.update( object, geometry, material, program ); - - updateBuffers = true; - - } - - // - - var index = geometry.index; - var position = geometry.attributes.position; - var rangeFactor = 1; - - if ( material.wireframe === true ) { - - index = geometries.getWireframeAttribute( geometry ); - rangeFactor = 2; - - } - - var attribute; - var renderer = bufferRenderer; - - if ( index !== null ) { - - attribute = attributes.get( index ); - - renderer = indexedBufferRenderer; - renderer.setIndex( attribute ); - - } - - if ( updateBuffers ) { - - setupVertexAttributes( material, program, geometry ); - - if ( index !== null ) { - - _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, attribute.buffer ); - - } - - } - - // - - var dataCount = 0; - - if ( index !== null ) { - - dataCount = index.count; - - } else if ( position !== undefined ) { - - dataCount = position.count; - - } - - var rangeStart = geometry.drawRange.start * rangeFactor; - var rangeCount = geometry.drawRange.count * rangeFactor; - - var groupStart = group !== null ? group.start * rangeFactor : 0; - var groupCount = group !== null ? group.count * rangeFactor : Infinity; - - var drawStart = Math.max( rangeStart, groupStart ); - var drawEnd = Math.min( dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1; - - var drawCount = Math.max( 0, drawEnd - drawStart + 1 ); - - if ( drawCount === 0 ) return; - - // - - if ( object.isMesh ) { - - if ( material.wireframe === true ) { - - state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() ); - renderer.setMode( _gl.LINES ); - - } else { - - switch ( object.drawMode ) { - - case TrianglesDrawMode: - renderer.setMode( _gl.TRIANGLES ); - break; - - case TriangleStripDrawMode: - renderer.setMode( _gl.TRIANGLE_STRIP ); - break; - - case TriangleFanDrawMode: - renderer.setMode( _gl.TRIANGLE_FAN ); - break; - - } - - } - - - } else if ( object.isLine ) { - - var lineWidth = material.linewidth; - - if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material - - state.setLineWidth( lineWidth * getTargetPixelRatio() ); - - if ( object.isLineSegments ) { - - renderer.setMode( _gl.LINES ); - - } else if ( object.isLineLoop ) { - - renderer.setMode( _gl.LINE_LOOP ); - - } else { - - renderer.setMode( _gl.LINE_STRIP ); - - } - - } else if ( object.isPoints ) { - - renderer.setMode( _gl.POINTS ); - - } - - if ( geometry && geometry.isInstancedBufferGeometry ) { - - if ( geometry.maxInstancedCount > 0 ) { - - renderer.renderInstances( geometry, drawStart, drawCount ); - - } - - } else { - - renderer.render( drawStart, drawCount ); - - } - - }; - - function setupVertexAttributes( material, program, geometry, startIndex ) { - - if ( geometry && geometry.isInstancedBufferGeometry ) { - - if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) { - - console.error( 'THREE.WebGLRenderer.setupVertexAttributes: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' ); - return; - - } - - } - - if ( startIndex === undefined ) startIndex = 0; - - state.initAttributes(); - - var geometryAttributes = geometry.attributes; - - var programAttributes = program.getAttributes(); - - var materialDefaultAttributeValues = material.defaultAttributeValues; - - for ( var name in programAttributes ) { - - var programAttribute = programAttributes[ name ]; - - if ( programAttribute >= 0 ) { - - var geometryAttribute = geometryAttributes[ name ]; - - if ( geometryAttribute !== undefined ) { - - var normalized = geometryAttribute.normalized; - var size = geometryAttribute.itemSize; - - var attribute = attributes.get( geometryAttribute ); - - // TODO Attribute may not be available on context restore - - if ( attribute === undefined ) continue; - - var buffer = attribute.buffer; - var type = attribute.type; - var bytesPerElement = attribute.bytesPerElement; - - if ( geometryAttribute.isInterleavedBufferAttribute ) { - - var data = geometryAttribute.data; - var stride = data.stride; - var offset = geometryAttribute.offset; - - if ( data && data.isInstancedInterleavedBuffer ) { - - state.enableAttributeAndDivisor( programAttribute, data.meshPerAttribute ); - - if ( geometry.maxInstancedCount === undefined ) { - - geometry.maxInstancedCount = data.meshPerAttribute * data.count; - - } - - } else { - - state.enableAttribute( programAttribute ); - - } - - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffer ); - _gl.vertexAttribPointer( programAttribute, size, type, normalized, stride * bytesPerElement, ( startIndex * stride + offset ) * bytesPerElement ); - - } else { - - if ( geometryAttribute.isInstancedBufferAttribute ) { - - state.enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute ); - - if ( geometry.maxInstancedCount === undefined ) { - - geometry.maxInstancedCount = geometryAttribute.meshPerAttribute * geometryAttribute.count; - - } - - } else { - - state.enableAttribute( programAttribute ); - - } - - _gl.bindBuffer( _gl.ARRAY_BUFFER, buffer ); - _gl.vertexAttribPointer( programAttribute, size, type, normalized, 0, startIndex * size * bytesPerElement ); - - } - - } else if ( materialDefaultAttributeValues !== undefined ) { - - var value = materialDefaultAttributeValues[ name ]; - - if ( value !== undefined ) { - - switch ( value.length ) { - - case 2: - _gl.vertexAttrib2fv( programAttribute, value ); - break; - - case 3: - _gl.vertexAttrib3fv( programAttribute, value ); - break; - - case 4: - _gl.vertexAttrib4fv( programAttribute, value ); - break; - - default: - _gl.vertexAttrib1fv( programAttribute, value ); - - } - - } - - } - - } - - } - - state.disableUnusedAttributes(); - - } - - // Compile - - this.compile = function ( scene, camera ) { - - lightsArray.length = 0; - shadowsArray.length = 0; - - scene.traverse( function ( object ) { - - if ( object.isLight ) { - - lightsArray.push( object ); - - if ( object.castShadow ) { - - shadowsArray.push( object ); - - } - - } - - } ); - - lights.setup( lightsArray, shadowsArray, camera ); - - scene.traverse( function ( object ) { - - if ( object.material ) { - - if ( Array.isArray( object.material ) ) { - - for ( var i = 0; i < object.material.length; i ++ ) { - - initMaterial( object.material[ i ], scene.fog, object ); - - } - - } else { - - initMaterial( object.material, scene.fog, object ); - - } - - } - - } ); - - }; - - // Animation Loop - - var isAnimating = false; - var onAnimationFrame = null; - - function start() { - - if ( isAnimating ) return; - - var device = vr.getDevice(); - - if ( device && device.isPresenting ) { - - device.requestAnimationFrame( loop ); - - } else { - - window.requestAnimationFrame( loop ); - - } - - isAnimating = true; - - } - - function loop( time ) { - - if ( onAnimationFrame !== null ) onAnimationFrame( time ); - - var device = vr.getDevice(); - - if ( device && device.isPresenting ) { - - device.requestAnimationFrame( loop ); - - } else { - - window.requestAnimationFrame( loop ); - - } - - } - - this.animate = function ( callback ) { - - onAnimationFrame = callback; - start(); - - }; - - // Rendering - - this.render = function ( scene, camera, renderTarget, forceClear ) { - - if ( ! ( camera && camera.isCamera ) ) { - - console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); - return; - - } - - if ( _isContextLost ) return; - - // reset caching for this frame - - _currentGeometryProgram = ''; - _currentMaterialId = - 1; - _currentCamera = null; - - // update scene graph - - if ( scene.autoUpdate === true ) scene.updateMatrixWorld(); - - // update camera matrices and frustum - - if ( camera.parent === null ) camera.updateMatrixWorld(); - - if ( vr.enabled ) { - - camera = vr.getCamera( camera ); - - } - - _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); - _frustum.setFromMatrix( _projScreenMatrix ); - - lightsArray.length = 0; - shadowsArray.length = 0; - - spritesArray.length = 0; - flaresArray.length = 0; - - _localClippingEnabled = this.localClippingEnabled; - _clippingEnabled = _clipping.init( this.clippingPlanes, _localClippingEnabled, camera ); - - currentRenderList = renderLists.get( scene, camera ); - currentRenderList.init(); - - projectObject( scene, camera, _this.sortObjects ); - - if ( _this.sortObjects === true ) { - - currentRenderList.sort(); - - } - - // - - if ( _clippingEnabled ) _clipping.beginShadows(); - - shadowMap.render( shadowsArray, scene, camera ); - - lights.setup( lightsArray, shadowsArray, camera ); - - if ( _clippingEnabled ) _clipping.endShadows(); - - // - - _infoRender.frame ++; - _infoRender.calls = 0; - _infoRender.vertices = 0; - _infoRender.faces = 0; - _infoRender.points = 0; - - if ( renderTarget === undefined ) { - - renderTarget = null; - - } - - this.setRenderTarget( renderTarget ); - - // - - background.render( currentRenderList, scene, camera, forceClear ); - - // render scene - - var opaqueObjects = currentRenderList.opaque; - var transparentObjects = currentRenderList.transparent; - - if ( scene.overrideMaterial ) { - - var overrideMaterial = scene.overrideMaterial; - - if ( opaqueObjects.length ) renderObjects( opaqueObjects, scene, camera, overrideMaterial ); - if ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera, overrideMaterial ); - - } else { - - // opaque pass (front-to-back order) - - if ( opaqueObjects.length ) renderObjects( opaqueObjects, scene, camera ); - - // transparent pass (back-to-front order) - - if ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera ); - - } - - // custom renderers - - spriteRenderer.render( spritesArray, scene, camera ); - flareRenderer.render( flaresArray, scene, camera, _currentViewport ); - - // Generate mipmap if we're using any kind of mipmap filtering - - if ( renderTarget ) { - - textures.updateRenderTargetMipmap( renderTarget ); - - } - - // Ensure depth buffer writing is enabled so it can be cleared on next render - - state.buffers.depth.setTest( true ); - state.buffers.depth.setMask( true ); - state.buffers.color.setMask( true ); - - state.setPolygonOffset( false ); - - if ( vr.enabled ) { - - vr.submitFrame(); - - } - - // _gl.finish(); - - }; - - /* - // TODO Duplicated code (Frustum) - - var _sphere = new Sphere(); - - function isObjectViewable( object ) { - - var geometry = object.geometry; - - if ( geometry.boundingSphere === null ) - geometry.computeBoundingSphere(); - - _sphere.copy( geometry.boundingSphere ). - applyMatrix4( object.matrixWorld ); - - return isSphereViewable( _sphere ); - - } - - function isSpriteViewable( sprite ) { - - _sphere.center.set( 0, 0, 0 ); - _sphere.radius = 0.7071067811865476; - _sphere.applyMatrix4( sprite.matrixWorld ); - - return isSphereViewable( _sphere ); - - } - - function isSphereViewable( sphere ) { - - if ( ! _frustum.intersectsSphere( sphere ) ) return false; - - var numPlanes = _clipping.numPlanes; - - if ( numPlanes === 0 ) return true; - - var planes = _this.clippingPlanes, - - center = sphere.center, - negRad = - sphere.radius, - i = 0; - - do { - - // out when deeper than radius in the negative halfspace - if ( planes[ i ].distanceToPoint( center ) < negRad ) return false; - - } while ( ++ i !== numPlanes ); - - return true; - - } - */ - - function projectObject( object, camera, sortObjects ) { - - if ( object.visible === false ) return; - - var visible = object.layers.test( camera.layers ); - - if ( visible ) { - - if ( object.isLight ) { - - lightsArray.push( object ); - - if ( object.castShadow ) { - - shadowsArray.push( object ); - - } - - } else if ( object.isSprite ) { - - if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) { - - spritesArray.push( object ); - - } - - } else if ( object.isLensFlare ) { - - flaresArray.push( object ); - - } else if ( object.isImmediateRenderObject ) { - - if ( sortObjects ) { - - _vector3.setFromMatrixPosition( object.matrixWorld ) - .applyMatrix4( _projScreenMatrix ); - - } - - currentRenderList.push( object, null, object.material, _vector3.z, null ); - - } else if ( object.isMesh || object.isLine || object.isPoints ) { - - if ( object.isSkinnedMesh ) { - - object.skeleton.update(); - - } - - if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) { - - if ( sortObjects ) { - - _vector3.setFromMatrixPosition( object.matrixWorld ) - .applyMatrix4( _projScreenMatrix ); - - } - - var geometry = objects.update( object ); - var material = object.material; - - if ( Array.isArray( material ) ) { - - var groups = geometry.groups; - - for ( var i = 0, l = groups.length; i < l; i ++ ) { - - var group = groups[ i ]; - var groupMaterial = material[ group.materialIndex ]; - - if ( groupMaterial && groupMaterial.visible ) { - - currentRenderList.push( object, geometry, groupMaterial, _vector3.z, group ); - - } - - } - - } else if ( material.visible ) { - - currentRenderList.push( object, geometry, material, _vector3.z, null ); - - } - - } - - } - - } - - var children = object.children; - - for ( var i = 0, l = children.length; i < l; i ++ ) { - - projectObject( children[ i ], camera, sortObjects ); - - } - - } - - function renderObjects( renderList, scene, camera, overrideMaterial ) { - - for ( var i = 0, l = renderList.length; i < l; i ++ ) { - - var renderItem = renderList[ i ]; - - var object = renderItem.object; - var geometry = renderItem.geometry; - var material = overrideMaterial === undefined ? renderItem.material : overrideMaterial; - var group = renderItem.group; - - if ( camera.isArrayCamera ) { - - _currentArrayCamera = camera; - - var cameras = camera.cameras; - - for ( var j = 0, jl = cameras.length; j < jl; j ++ ) { - - var camera2 = cameras[ j ]; - - if ( object.layers.test( camera2.layers ) ) { - - var bounds = camera2.bounds; - - var x = bounds.x * _width; - var y = bounds.y * _height; - var width = bounds.z * _width; - var height = bounds.w * _height; - - state.viewport( _currentViewport.set( x, y, width, height ).multiplyScalar( _pixelRatio ) ); - - renderObject( object, scene, camera2, geometry, material, group ); - - } - - } - - } else { - - _currentArrayCamera = null; - - renderObject( object, scene, camera, geometry, material, group ); - - } - - } - - } - - function renderObject( object, scene, camera, geometry, material, group ) { - - object.onBeforeRender( _this, scene, camera, geometry, material, group ); - - object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); - object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); - - if ( object.isImmediateRenderObject ) { - - state.setMaterial( material ); - - var program = setProgram( camera, scene.fog, material, object ); - - _currentGeometryProgram = ''; - - renderObjectImmediate( object, program, material ); - - } else { - - _this.renderBufferDirect( camera, scene.fog, geometry, material, object, group ); - - } - - object.onAfterRender( _this, scene, camera, geometry, material, group ); - - } - - function initMaterial( material, fog, object ) { - - var materialProperties = properties.get( material ); - - var parameters = programCache.getParameters( - material, lights.state, shadowsArray, fog, _clipping.numPlanes, _clipping.numIntersection, object ); - - var code = programCache.getProgramCode( material, parameters ); - - var program = materialProperties.program; - var programChange = true; - - if ( program === undefined ) { - - // new material - material.addEventListener( 'dispose', onMaterialDispose ); - - } else if ( program.code !== code ) { - - // changed glsl or parameters - releaseMaterialProgramReference( material ); - - } else if ( parameters.shaderID !== undefined ) { - - // same glsl and uniform list - return; - - } else { - - // only rebuild uniform list - programChange = false; - - } - - if ( programChange ) { - - if ( parameters.shaderID ) { - - var shader = ShaderLib[ parameters.shaderID ]; - - materialProperties.shader = { - name: material.type, - uniforms: UniformsUtils.clone( shader.uniforms ), - vertexShader: shader.vertexShader, - fragmentShader: shader.fragmentShader - }; - - } else { - - materialProperties.shader = { - name: material.type, - uniforms: material.uniforms, - vertexShader: material.vertexShader, - fragmentShader: material.fragmentShader - }; - - } - - material.onBeforeCompile( materialProperties.shader ); - - program = programCache.acquireProgram( material, materialProperties.shader, parameters, code ); - - materialProperties.program = program; - material.program = program; - - } - - var programAttributes = program.getAttributes(); - - if ( material.morphTargets ) { - - material.numSupportedMorphTargets = 0; - - for ( var i = 0; i < _this.maxMorphTargets; i ++ ) { - - if ( programAttributes[ 'morphTarget' + i ] >= 0 ) { - - material.numSupportedMorphTargets ++; - - } - - } - - } - - if ( material.morphNormals ) { - - material.numSupportedMorphNormals = 0; - - for ( var i = 0; i < _this.maxMorphNormals; i ++ ) { - - if ( programAttributes[ 'morphNormal' + i ] >= 0 ) { - - material.numSupportedMorphNormals ++; - - } - - } - - } - - var uniforms = materialProperties.shader.uniforms; - - if ( ! material.isShaderMaterial && - ! material.isRawShaderMaterial || - material.clipping === true ) { - - materialProperties.numClippingPlanes = _clipping.numPlanes; - materialProperties.numIntersection = _clipping.numIntersection; - uniforms.clippingPlanes = _clipping.uniform; - - } - - materialProperties.fog = fog; - - // store the light setup it was created for - - materialProperties.lightsHash = lights.state.hash; - - if ( material.lights ) { - - // wire up the material to this renderer's lighting state - - uniforms.ambientLightColor.value = lights.state.ambient; - uniforms.directionalLights.value = lights.state.directional; - uniforms.spotLights.value = lights.state.spot; - uniforms.rectAreaLights.value = lights.state.rectArea; - uniforms.pointLights.value = lights.state.point; - uniforms.hemisphereLights.value = lights.state.hemi; - - uniforms.directionalShadowMap.value = lights.state.directionalShadowMap; - uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix; - uniforms.spotShadowMap.value = lights.state.spotShadowMap; - uniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix; - uniforms.pointShadowMap.value = lights.state.pointShadowMap; - uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; - // TODO (abelnation): add area lights shadow info to uniforms - - } - - var progUniforms = materialProperties.program.getUniforms(), - uniformsList = - WebGLUniforms.seqWithValue( progUniforms.seq, uniforms ); - - materialProperties.uniformsList = uniformsList; - - } - - function setProgram( camera, fog, material, object ) { - - _usedTextureUnits = 0; - - var materialProperties = properties.get( material ); - - if ( _clippingEnabled ) { - - if ( _localClippingEnabled || camera !== _currentCamera ) { - - var useCache = - camera === _currentCamera && - material.id === _currentMaterialId; - - // we might want to call this function with some ClippingGroup - // object instead of the material, once it becomes feasible - // (#8465, #8379) - _clipping.setState( - material.clippingPlanes, material.clipIntersection, material.clipShadows, - camera, materialProperties, useCache ); - - } - - } - - if ( material.needsUpdate === false ) { - - if ( materialProperties.program === undefined ) { - - material.needsUpdate = true; - - } else if ( material.fog && materialProperties.fog !== fog ) { - - material.needsUpdate = true; - - } else if ( material.lights && materialProperties.lightsHash !== lights.state.hash ) { - - material.needsUpdate = true; - - } else if ( materialProperties.numClippingPlanes !== undefined && - ( materialProperties.numClippingPlanes !== _clipping.numPlanes || - materialProperties.numIntersection !== _clipping.numIntersection ) ) { - - material.needsUpdate = true; - - } - - } - - if ( material.needsUpdate ) { - - initMaterial( material, fog, object ); - material.needsUpdate = false; - - } - - var refreshProgram = false; - var refreshMaterial = false; - var refreshLights = false; - - var program = materialProperties.program, - p_uniforms = program.getUniforms(), - m_uniforms = materialProperties.shader.uniforms; - - if ( state.useProgram( program.program ) ) { - - refreshProgram = true; - refreshMaterial = true; - refreshLights = true; - - } - - if ( material.id !== _currentMaterialId ) { - - _currentMaterialId = material.id; - - refreshMaterial = true; - - } - - if ( refreshProgram || camera !== _currentCamera ) { - - p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); - - if ( capabilities.logarithmicDepthBuffer ) { - - p_uniforms.setValue( _gl, 'logDepthBufFC', - 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) ); - - } - - // Avoid unneeded uniform updates per ArrayCamera's sub-camera - - if ( _currentCamera !== ( _currentArrayCamera || camera ) ) { - - _currentCamera = ( _currentArrayCamera || camera ); - - // lighting uniforms depend on the camera so enforce an update - // now, in case this material supports lights - or later, when - // the next material that does gets activated: - - refreshMaterial = true; // set to true on material change - refreshLights = true; // remains set until update done - - } - - // load material specific uniforms - // (shader material also gets them for the sake of genericity) - - if ( material.isShaderMaterial || - material.isMeshPhongMaterial || - material.isMeshStandardMaterial || - material.envMap ) { - - var uCamPos = p_uniforms.map.cameraPosition; - - if ( uCamPos !== undefined ) { - - uCamPos.setValue( _gl, - _vector3.setFromMatrixPosition( camera.matrixWorld ) ); - - } - - } - - if ( material.isMeshPhongMaterial || - material.isMeshLambertMaterial || - material.isMeshBasicMaterial || - material.isMeshStandardMaterial || - material.isShaderMaterial || - material.skinning ) { - - p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); - - } - - } - - // skinning uniforms must be set even if material didn't change - // auto-setting of texture unit for bone texture must go before other textures - // not sure why, but otherwise weird things happen - - if ( material.skinning ) { - - p_uniforms.setOptional( _gl, object, 'bindMatrix' ); - p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' ); - - var skeleton = object.skeleton; - - if ( skeleton ) { - - var bones = skeleton.bones; - - if ( capabilities.floatVertexTextures ) { - - if ( skeleton.boneTexture === undefined ) { - - // layout (1 matrix = 4 pixels) - // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4) - // with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8) - // 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16) - // 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32) - // 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64) - - - var size = Math.sqrt( bones.length * 4 ); // 4 pixels needed for 1 matrix - size = _Math.ceilPowerOfTwo( size ); - size = Math.max( size, 4 ); - - var boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel - boneMatrices.set( skeleton.boneMatrices ); // copy current values - - var boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType ); - - skeleton.boneMatrices = boneMatrices; - skeleton.boneTexture = boneTexture; - skeleton.boneTextureSize = size; - - } - - p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture ); - p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize ); - - } else { - - p_uniforms.setOptional( _gl, skeleton, 'boneMatrices' ); - - } - - } - - } - - if ( refreshMaterial ) { - - p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); - p_uniforms.setValue( _gl, 'toneMappingWhitePoint', _this.toneMappingWhitePoint ); - - if ( material.lights ) { - - // the current material requires lighting info - - // note: all lighting uniforms are always set correctly - // they simply reference the renderer's state for their - // values - // - // use the current material's .needsUpdate flags to set - // the GL state when required - - markUniformsLightsNeedsUpdate( m_uniforms, refreshLights ); - - } - - // refresh uniforms common to several materials - - if ( fog && material.fog ) { - - refreshUniformsFog( m_uniforms, fog ); - - } - - if ( material.isMeshBasicMaterial ) { - - refreshUniformsCommon( m_uniforms, material ); - - } else if ( material.isMeshLambertMaterial ) { - - refreshUniformsCommon( m_uniforms, material ); - refreshUniformsLambert( m_uniforms, material ); - - } else if ( material.isMeshPhongMaterial ) { - - refreshUniformsCommon( m_uniforms, material ); - - if ( material.isMeshToonMaterial ) { - - refreshUniformsToon( m_uniforms, material ); - - } else { - - refreshUniformsPhong( m_uniforms, material ); - - } - - } else if ( material.isMeshStandardMaterial ) { - - refreshUniformsCommon( m_uniforms, material ); - - if ( material.isMeshPhysicalMaterial ) { - - refreshUniformsPhysical( m_uniforms, material ); - - } else { - - refreshUniformsStandard( m_uniforms, material ); - - } - - } else if ( material.isMeshDepthMaterial ) { - - refreshUniformsCommon( m_uniforms, material ); - refreshUniformsDepth( m_uniforms, material ); - - } else if ( material.isMeshDistanceMaterial ) { - - refreshUniformsCommon( m_uniforms, material ); - refreshUniformsDistance( m_uniforms, material ); - - } else if ( material.isMeshNormalMaterial ) { - - refreshUniformsCommon( m_uniforms, material ); - refreshUniformsNormal( m_uniforms, material ); - - } else if ( material.isLineBasicMaterial ) { - - refreshUniformsLine( m_uniforms, material ); - - if ( material.isLineDashedMaterial ) { - - refreshUniformsDash( m_uniforms, material ); - - } - - } else if ( material.isPointsMaterial ) { - - refreshUniformsPoints( m_uniforms, material ); - - } else if ( material.isShadowMaterial ) { - - m_uniforms.color.value = material.color; - m_uniforms.opacity.value = material.opacity; - - } - - // RectAreaLight Texture - // TODO (mrdoob): Find a nicer implementation - - if ( m_uniforms.ltcMat !== undefined ) m_uniforms.ltcMat.value = UniformsLib.LTC_MAT_TEXTURE; - if ( m_uniforms.ltcMag !== undefined ) m_uniforms.ltcMag.value = UniformsLib.LTC_MAG_TEXTURE; - - WebGLUniforms.upload( - _gl, materialProperties.uniformsList, m_uniforms, _this ); - - } - - - // common matrices - - p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix ); - p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix ); - p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld ); - - return program; - - } - - // Uniforms (refresh uniforms objects) - - function refreshUniformsCommon( uniforms, material ) { - - uniforms.opacity.value = material.opacity; - - if ( material.color ) { - - uniforms.diffuse.value = material.color; - - } - - if ( material.emissive ) { - - uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity ); - - } - - if ( material.map ) { - - uniforms.map.value = material.map; - - } - - if ( material.alphaMap ) { - - uniforms.alphaMap.value = material.alphaMap; - - } - - if ( material.specularMap ) { - - uniforms.specularMap.value = material.specularMap; - - } - - if ( material.envMap ) { - - uniforms.envMap.value = material.envMap; - - // don't flip CubeTexture envMaps, flip everything else: - // WebGLRenderTargetCube will be flipped for backwards compatibility - // WebGLRenderTargetCube.texture will be flipped because it's a Texture and NOT a CubeTexture - // this check must be handled differently, or removed entirely, if WebGLRenderTargetCube uses a CubeTexture in the future - uniforms.flipEnvMap.value = ( ! ( material.envMap && material.envMap.isCubeTexture ) ) ? 1 : - 1; - - uniforms.reflectivity.value = material.reflectivity; - uniforms.refractionRatio.value = material.refractionRatio; - - } - - if ( material.lightMap ) { - - uniforms.lightMap.value = material.lightMap; - uniforms.lightMapIntensity.value = material.lightMapIntensity; - - } - - if ( material.aoMap ) { - - uniforms.aoMap.value = material.aoMap; - uniforms.aoMapIntensity.value = material.aoMapIntensity; - - } - - // uv repeat and offset setting priorities - // 1. color map - // 2. specular map - // 3. normal map - // 4. bump map - // 5. alpha map - // 6. emissive map - - var uvScaleMap; - - if ( material.map ) { - - uvScaleMap = material.map; - - } else if ( material.specularMap ) { - - uvScaleMap = material.specularMap; - - } else if ( material.displacementMap ) { - - uvScaleMap = material.displacementMap; - - } else if ( material.normalMap ) { - - uvScaleMap = material.normalMap; - - } else if ( material.bumpMap ) { - - uvScaleMap = material.bumpMap; - - } else if ( material.roughnessMap ) { - - uvScaleMap = material.roughnessMap; - - } else if ( material.metalnessMap ) { - - uvScaleMap = material.metalnessMap; - - } else if ( material.alphaMap ) { - - uvScaleMap = material.alphaMap; - - } else if ( material.emissiveMap ) { - - uvScaleMap = material.emissiveMap; - - } - - if ( uvScaleMap !== undefined ) { - - // backwards compatibility - if ( uvScaleMap.isWebGLRenderTarget ) { - - uvScaleMap = uvScaleMap.texture; - - } - - if ( uvScaleMap.matrixAutoUpdate === true ) { - - var offset = uvScaleMap.offset; - var repeat = uvScaleMap.repeat; - var rotation = uvScaleMap.rotation; - var center = uvScaleMap.center; - - uvScaleMap.matrix.setUvTransform( offset.x, offset.y, repeat.x, repeat.y, rotation, center.x, center.y ); - - } - - uniforms.uvTransform.value.copy( uvScaleMap.matrix ); - - } - - } - - function refreshUniformsLine( uniforms, material ) { - - uniforms.diffuse.value = material.color; - uniforms.opacity.value = material.opacity; - - } - - function refreshUniformsDash( uniforms, material ) { - - uniforms.dashSize.value = material.dashSize; - uniforms.totalSize.value = material.dashSize + material.gapSize; - uniforms.scale.value = material.scale; - - } - - function refreshUniformsPoints( uniforms, material ) { - - uniforms.diffuse.value = material.color; - uniforms.opacity.value = material.opacity; - uniforms.size.value = material.size * _pixelRatio; - uniforms.scale.value = _height * 0.5; - - uniforms.map.value = material.map; - - if ( material.map !== null ) { - - if ( material.map.matrixAutoUpdate === true ) { - - var offset = material.map.offset; - var repeat = material.map.repeat; - var rotation = material.map.rotation; - var center = material.map.center; - - material.map.matrix.setUvTransform( offset.x, offset.y, repeat.x, repeat.y, rotation, center.x, center.y ); - - } - - uniforms.uvTransform.value.copy( material.map.matrix ); - - } - - } - - function refreshUniformsFog( uniforms, fog ) { - - uniforms.fogColor.value = fog.color; - - if ( fog.isFog ) { - - uniforms.fogNear.value = fog.near; - uniforms.fogFar.value = fog.far; - - } else if ( fog.isFogExp2 ) { - - uniforms.fogDensity.value = fog.density; - - } - - } - - function refreshUniformsLambert( uniforms, material ) { - - if ( material.emissiveMap ) { - - uniforms.emissiveMap.value = material.emissiveMap; - - } - - } - - function refreshUniformsPhong( uniforms, material ) { - - uniforms.specular.value = material.specular; - uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 ) - - if ( material.emissiveMap ) { - - uniforms.emissiveMap.value = material.emissiveMap; - - } - - if ( material.bumpMap ) { - - uniforms.bumpMap.value = material.bumpMap; - uniforms.bumpScale.value = material.bumpScale; - - } - - if ( material.normalMap ) { - - uniforms.normalMap.value = material.normalMap; - uniforms.normalScale.value.copy( material.normalScale ); - - } - - if ( material.displacementMap ) { - - uniforms.displacementMap.value = material.displacementMap; - uniforms.displacementScale.value = material.displacementScale; - uniforms.displacementBias.value = material.displacementBias; - - } - - } - - function refreshUniformsToon( uniforms, material ) { - - refreshUniformsPhong( uniforms, material ); - - if ( material.gradientMap ) { - - uniforms.gradientMap.value = material.gradientMap; - - } - - } - - function refreshUniformsStandard( uniforms, material ) { - - uniforms.roughness.value = material.roughness; - uniforms.metalness.value = material.metalness; - - if ( material.roughnessMap ) { - - uniforms.roughnessMap.value = material.roughnessMap; - - } - - if ( material.metalnessMap ) { - - uniforms.metalnessMap.value = material.metalnessMap; - - } - - if ( material.emissiveMap ) { - - uniforms.emissiveMap.value = material.emissiveMap; - - } - - if ( material.bumpMap ) { - - uniforms.bumpMap.value = material.bumpMap; - uniforms.bumpScale.value = material.bumpScale; - - } - - if ( material.normalMap ) { - - uniforms.normalMap.value = material.normalMap; - uniforms.normalScale.value.copy( material.normalScale ); - - } - - if ( material.displacementMap ) { - - uniforms.displacementMap.value = material.displacementMap; - uniforms.displacementScale.value = material.displacementScale; - uniforms.displacementBias.value = material.displacementBias; - - } - - if ( material.envMap ) { - - //uniforms.envMap.value = material.envMap; // part of uniforms common - uniforms.envMapIntensity.value = material.envMapIntensity; - - } - - } - - function refreshUniformsPhysical( uniforms, material ) { - - uniforms.clearCoat.value = material.clearCoat; - uniforms.clearCoatRoughness.value = material.clearCoatRoughness; - - refreshUniformsStandard( uniforms, material ); - - } - - function refreshUniformsDepth( uniforms, material ) { - - if ( material.displacementMap ) { - - uniforms.displacementMap.value = material.displacementMap; - uniforms.displacementScale.value = material.displacementScale; - uniforms.displacementBias.value = material.displacementBias; - - } - - } - - function refreshUniformsDistance( uniforms, material ) { - - if ( material.displacementMap ) { - - uniforms.displacementMap.value = material.displacementMap; - uniforms.displacementScale.value = material.displacementScale; - uniforms.displacementBias.value = material.displacementBias; - - } - - uniforms.referencePosition.value.copy( material.referencePosition ); - uniforms.nearDistance.value = material.nearDistance; - uniforms.farDistance.value = material.farDistance; - - } - - function refreshUniformsNormal( uniforms, material ) { - - if ( material.bumpMap ) { - - uniforms.bumpMap.value = material.bumpMap; - uniforms.bumpScale.value = material.bumpScale; - - } - - if ( material.normalMap ) { - - uniforms.normalMap.value = material.normalMap; - uniforms.normalScale.value.copy( material.normalScale ); - - } - - if ( material.displacementMap ) { - - uniforms.displacementMap.value = material.displacementMap; - uniforms.displacementScale.value = material.displacementScale; - uniforms.displacementBias.value = material.displacementBias; - - } - - } - - // If uniforms are marked as clean, they don't need to be loaded to the GPU. - - function markUniformsLightsNeedsUpdate( uniforms, value ) { - - uniforms.ambientLightColor.needsUpdate = value; - - uniforms.directionalLights.needsUpdate = value; - uniforms.pointLights.needsUpdate = value; - uniforms.spotLights.needsUpdate = value; - uniforms.rectAreaLights.needsUpdate = value; - uniforms.hemisphereLights.needsUpdate = value; - - } - - // GL state setting - - this.setFaceCulling = function ( cullFace, frontFaceDirection ) { - - state.setCullFace( cullFace ); - state.setFlipSided( frontFaceDirection === FrontFaceDirectionCW ); - - }; - - // Textures - - function allocTextureUnit() { - - var textureUnit = _usedTextureUnits; - - if ( textureUnit >= capabilities.maxTextures ) { - - console.warn( 'THREE.WebGLRenderer: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures ); - - } - - _usedTextureUnits += 1; - - return textureUnit; - - } - - this.allocTextureUnit = allocTextureUnit; - - // this.setTexture2D = setTexture2D; - this.setTexture2D = ( function () { - - var warned = false; - - // backwards compatibility: peel texture.texture - return function setTexture2D( texture, slot ) { - - if ( texture && texture.isWebGLRenderTarget ) { - - if ( ! warned ) { - - console.warn( "THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead." ); - warned = true; - - } - - texture = texture.texture; - - } - - textures.setTexture2D( texture, slot ); - - }; - - }() ); - - this.setTexture = ( function () { - - var warned = false; - - return function setTexture( texture, slot ) { - - if ( ! warned ) { - - console.warn( "THREE.WebGLRenderer: .setTexture is deprecated, use setTexture2D instead." ); - warned = true; - - } - - textures.setTexture2D( texture, slot ); - - }; - - }() ); - - this.setTextureCube = ( function () { - - var warned = false; - - return function setTextureCube( texture, slot ) { - - // backwards compatibility: peel texture.texture - if ( texture && texture.isWebGLRenderTargetCube ) { - - if ( ! warned ) { - - console.warn( "THREE.WebGLRenderer.setTextureCube: don't use cube render targets as textures. Use their .texture property instead." ); - warned = true; - - } - - texture = texture.texture; - - } - - // currently relying on the fact that WebGLRenderTargetCube.texture is a Texture and NOT a CubeTexture - // TODO: unify these code paths - if ( ( texture && texture.isCubeTexture ) || - ( Array.isArray( texture.image ) && texture.image.length === 6 ) ) { - - // CompressedTexture can have Array in image :/ - - // this function alone should take care of cube textures - textures.setTextureCube( texture, slot ); - - } else { - - // assumed: texture property of THREE.WebGLRenderTargetCube - - textures.setTextureCubeDynamic( texture, slot ); - - } - - }; - - }() ); - - this.getRenderTarget = function () { - - return _currentRenderTarget; - - }; - - this.setRenderTarget = function ( renderTarget ) { - - _currentRenderTarget = renderTarget; - - if ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) { - - textures.setupRenderTarget( renderTarget ); - - } - - var framebuffer = null; - var isCube = false; - - if ( renderTarget ) { - - var __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer; - - if ( renderTarget.isWebGLRenderTargetCube ) { - - framebuffer = __webglFramebuffer[ renderTarget.activeCubeFace ]; - isCube = true; - - } else { - - framebuffer = __webglFramebuffer; - - } - - _currentViewport.copy( renderTarget.viewport ); - _currentScissor.copy( renderTarget.scissor ); - _currentScissorTest = renderTarget.scissorTest; - - } else { - - _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ); - _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ); - _currentScissorTest = _scissorTest; - - } - - if ( _currentFramebuffer !== framebuffer ) { - - _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - _currentFramebuffer = framebuffer; - - } - - state.viewport( _currentViewport ); - state.scissor( _currentScissor ); - state.setScissorTest( _currentScissorTest ); - - if ( isCube ) { - - var textureProperties = properties.get( renderTarget.texture ); - _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + renderTarget.activeCubeFace, textureProperties.__webglTexture, renderTarget.activeMipMapLevel ); - - } - - }; - - this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer ) { - - if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { - - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); - return; - - } - - var framebuffer = properties.get( renderTarget ).__webglFramebuffer; - - if ( framebuffer ) { - - var restore = false; - - if ( framebuffer !== _currentFramebuffer ) { - - _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - - restore = true; - - } - - try { - - var texture = renderTarget.texture; - var textureFormat = texture.format; - var textureType = texture.type; - - if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) { - - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); - return; - - } - - if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // IE11, Edge and Chrome Mac < 52 (#9513) - ! ( textureType === FloatType && ( extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox - ! ( textureType === HalfFloatType && extensions.get( 'EXT_color_buffer_half_float' ) ) ) { - - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' ); - return; - - } - - if ( _gl.checkFramebufferStatus( _gl.FRAMEBUFFER ) === _gl.FRAMEBUFFER_COMPLETE ) { - - // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) - - if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { - - _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer ); - - } - - } else { - - console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' ); - - } - - } finally { - - if ( restore ) { - - _gl.bindFramebuffer( _gl.FRAMEBUFFER, _currentFramebuffer ); - - } - - } - - } - - }; - - } - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author Anonymous - */ - /* global QUnit */ - - function testEdges( vertList, idxList, numAfter, assert ) { - - var geoms = createGeometries( vertList, idxList ); - - for ( var i = 0; i < geoms.length; i ++ ) { - - var geom = geoms[ i ]; - - var numBefore = idxList.length; - assert.equal( countEdges( geom ), numBefore, "Edges before!" ); - - var egeom = new EdgesGeometry( geom ); - - assert.equal( countEdges( egeom ), numAfter, "Edges after!" ); - output( geom, egeom ); - - } - - } - - function createGeometries( vertList, idxList ) { - - var geomIB = createIndexedBufferGeometry( vertList, idxList ); - var geom = new Geometry().fromBufferGeometry( geomIB ); - var geomB = new BufferGeometry().fromGeometry( geom ); - var geomDC = addDrawCalls( geomIB.clone() ); - return [ geom, geomB, geomIB, geomDC ]; - - } - - function createIndexedBufferGeometry( vertList, idxList ) { - - var geom = new BufferGeometry(); - - var indexTable = []; - var numTris = idxList.length / 3; - var numVerts = 0; - - var indices = new Uint32Array( numTris * 3 ); - var vertices = new Float32Array( vertList.length * 3 ); - - for ( var i = 0; i < numTris; i ++ ) { - - for ( var j = 0; j < 3; j ++ ) { - - var idx = idxList[ 3 * i + j ]; - if ( indexTable[ idx ] === undefined ) { - - var v = vertList[ idx ]; - vertices[ 3 * numVerts ] = v.x; - vertices[ 3 * numVerts + 1 ] = v.y; - vertices[ 3 * numVerts + 2 ] = v.z; - - indexTable[ idx ] = numVerts; - - numVerts ++; - - } - - indices[ 3 * i + j ] = indexTable[ idx ]; - - } - - } - - vertices = vertices.subarray( 0, 3 * numVerts ); - - geom.setIndex( new BufferAttribute( indices, 1 ) ); - geom.addAttribute( 'position', new BufferAttribute( vertices, 3 ) ); - - geom.computeFaceNormals(); - - return geom; - - } - - function addDrawCalls( geometry ) { - - var numTris = geometry.index.count / 3; - - for ( var i = 0; i < numTris; i ++ ) { - - var start = i * 3; - var count = 3; - - geometry.addGroup( start, count ); - - } - - return geometry; - - } - - function countEdges( geom ) { - - if ( geom instanceof EdgesGeometry ) { - - return geom.getAttribute( 'position' ).count / 2; - - } - - if ( geom.faces !== undefined ) { - - return geom.faces.length * 3; - - } - - var indices = geom.index; - if ( indices ) { - - return indices.count; - - } - - return geom.getAttribute( 'position' ).count; - - } - - // - // DEBUGGING - // - var DEBUG = false; - var renderer; - var camera; - var scene = new Scene(); - var xoffset = 0; - - function output( geom, egeom ) { - - if ( DEBUG !== true ) return; - - if ( ! renderer ) initDebug(); - - var mesh = new Mesh( geom, undefined ); - var edges = new LineSegments( egeom, new LineBasicMaterial( { color: 'black' } ) ); - - mesh.position.setX( xoffset ); - edges.position.setX( xoffset ++ ); - scene.add( mesh ); - scene.add( edges ); - - if ( scene.children.length % 8 === 0 ) { - - xoffset += 2; - - } - - } - - function initDebug() { - - renderer = new WebGLRenderer( { - - antialias: true - - } ); - - var width = 600; - var height = 480; - - renderer.setSize( width, height ); - renderer.setClearColor( 0xCCCCCC ); - - camera = new PerspectiveCamera( 45, width / height, 1, 100 ); - camera.position.x = 30; - camera.position.z = 40; - camera.lookAt( new Vector3( 30, 0, 0 ) ); - - document.body.appendChild( renderer.domElement ); - - var controls = new THREE.OrbitControls( camera, renderer.domElement ); // TODO: please do somethings for that -_-' - controls.target = new Vector3( 30, 0, 0 ); - - animate(); - - function animate() { - - requestAnimationFrame( animate ); - - controls.update(); - - renderer.render( scene, camera ); - - } - - } - - QUnit.module( 'Geometries', () => { - - QUnit.module.todo( 'EdgesGeometry', () => { - - var vertList = [ - new Vector3( 0, 0, 0 ), - new Vector3( 1, 0, 0 ), - new Vector3( 1, 1, 0 ), - new Vector3( 0, 1, 0 ), - new Vector3( 1, 1, 1 ), - ]; - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( "singularity", ( assert ) => { - - testEdges( vertList, [ 1, 1, 1 ], 0, assert ); - - } ); - - QUnit.test( "needle", ( assert ) => { - - testEdges( vertList, [ 0, 0, 1 ], 0, assert ); - - } ); - - QUnit.test( "single triangle", ( assert ) => { - - testEdges( vertList, [ 0, 1, 2 ], 3, assert ); - - } ); - - QUnit.test( "two isolated triangles", ( assert ) => { - - var vertList = [ - new Vector3( 0, 0, 0 ), - new Vector3( 1, 0, 0 ), - new Vector3( 1, 1, 0 ), - new Vector3( 0, 0, 1 ), - new Vector3( 1, 0, 1 ), - new Vector3( 1, 1, 1 ), - ]; - - testEdges( vertList, [ 0, 1, 2, 3, 4, 5 ], 6, assert ); - - } ); - - QUnit.test( "two flat triangles", ( assert ) => { - - testEdges( vertList, [ 0, 1, 2, 0, 2, 3 ], 4, assert ); - - } ); - - QUnit.test( "two flat triangles, inverted", ( assert ) => { - - testEdges( vertList, [ 0, 1, 2, 0, 3, 2 ], 5, assert ); - - } ); - - QUnit.test( "two non-coplanar triangles", ( assert ) => { - - testEdges( vertList, [ 0, 1, 2, 0, 4, 2 ], 5, assert ); - - } ); - - QUnit.test( "three triangles, coplanar first", ( assert ) => { - - testEdges( vertList, [ 0, 1, 2, 0, 2, 3, 0, 4, 2 ], 7, assert ); - - } ); - - QUnit.test( "three triangles, coplanar last", ( assert ) => { - - testEdges( vertList, [ 0, 1, 2, 0, 4, 2, 0, 2, 3 ], 6, assert ); // Should be 7 - - } ); - - QUnit.test( "tetrahedron", ( assert ) => { - - testEdges( vertList, [ 0, 1, 2, 0, 1, 4, 0, 4, 2, 1, 2, 4 ], 6, assert ); - - } ); - - } ); - - } ); - - /** - * @author zz85 / http://www.lab4games.net/zz85/blog - * - * Creates extruded geometry from a path shape. - * - * parameters = { - * - * curveSegments: , // number of points on the curves - * steps: , // number of points for z-side extrusions / used for subdividing segments of extrude spline too - * amount: , // Depth to extrude the shape - * - * bevelEnabled: , // turn on bevel - * bevelThickness: , // how deep into the original shape bevel goes - * bevelSize: , // how far from shape outline is bevel - * bevelSegments: , // number of bevel layers - * - * extrudePath: // curve to extrude shape along - * frames: // containing arrays of tangents, normals, binormals - * - * UVGenerator: // object that provides UV generator functions - * - * } - */ - - function ExtrudeGeometry( shapes, options ) { - - Geometry.call( this ); - - this.type = 'ExtrudeGeometry'; - - this.parameters = { - shapes: shapes, - options: options - }; - - this.fromBufferGeometry( new ExtrudeBufferGeometry( shapes, options ) ); - this.mergeVertices(); - - } - - ExtrudeGeometry.prototype = Object.create( Geometry.prototype ); - ExtrudeGeometry.prototype.constructor = ExtrudeGeometry; - - // ExtrudeBufferGeometry - - function ExtrudeBufferGeometry( shapes, options ) { - - if ( typeof ( shapes ) === "undefined" ) { - - return; - - } - - BufferGeometry.call( this ); - - this.type = 'ExtrudeBufferGeometry'; - - shapes = Array.isArray( shapes ) ? shapes : [ shapes ]; - - this.addShapeList( shapes, options ); - - this.computeVertexNormals(); - - // can't really use automatic vertex normals - // as then front and back sides get smoothed too - // should do separate smoothing just for sides - - //this.computeVertexNormals(); - - //console.log( "took", ( Date.now() - startTime ) ); - - } - - ExtrudeBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - ExtrudeBufferGeometry.prototype.constructor = ExtrudeBufferGeometry; - - ExtrudeBufferGeometry.prototype.getArrays = function () { - - var positionAttribute = this.getAttribute( "position" ); - var verticesArray = positionAttribute ? Array.prototype.slice.call( positionAttribute.array ) : []; - - var uvAttribute = this.getAttribute( "uv" ); - var uvArray = uvAttribute ? Array.prototype.slice.call( uvAttribute.array ) : []; - - var IndexAttribute = this.index; - var indicesArray = IndexAttribute ? Array.prototype.slice.call( IndexAttribute.array ) : []; - - return { - position: verticesArray, - uv: uvArray, - index: indicesArray - }; - - }; - - ExtrudeBufferGeometry.prototype.addShapeList = function ( shapes, options ) { - - var sl = shapes.length; - options.arrays = this.getArrays(); - - for ( var s = 0; s < sl; s ++ ) { - - var shape = shapes[ s ]; - this.addShape( shape, options ); - - } - - this.setIndex( options.arrays.index ); - this.addAttribute( 'position', new Float32BufferAttribute( options.arrays.position, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( options.arrays.uv, 2 ) ); - - }; - - ExtrudeBufferGeometry.prototype.addShape = function ( shape, options ) { - - var arrays = options.arrays ? options.arrays : this.getArrays(); - var verticesArray = arrays.position; - var indicesArray = arrays.index; - var uvArray = arrays.uv; - - var placeholder = []; - - - var amount = options.amount !== undefined ? options.amount : 100; - - var bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6; // 10 - var bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2; // 8 - var bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3; - - var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true; // false - - var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12; - - var steps = options.steps !== undefined ? options.steps : 1; - - var extrudePath = options.extrudePath; - var extrudePts, extrudeByPath = false; - - // Use default WorldUVGenerator if no UV generators are specified. - var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : ExtrudeGeometry.WorldUVGenerator; - - var splineTube, binormal, normal, position2; - if ( extrudePath ) { - - extrudePts = extrudePath.getSpacedPoints( steps ); - - extrudeByPath = true; - bevelEnabled = false; // bevels not supported for path extrusion - - // SETUP TNB variables - - // TODO1 - have a .isClosed in spline? - - splineTube = options.frames !== undefined ? options.frames : extrudePath.computeFrenetFrames( steps, false ); - - // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length); - - binormal = new Vector3(); - normal = new Vector3(); - position2 = new Vector3(); - - } - - // Safeguards if bevels are not enabled - - if ( ! bevelEnabled ) { - - bevelSegments = 0; - bevelThickness = 0; - bevelSize = 0; - - } - - // Variables initialization - - var ahole, h, hl; // looping of holes - var scope = this; - - var shapePoints = shape.extractPoints( curveSegments ); - - var vertices = shapePoints.shape; - var holes = shapePoints.holes; - - var reverse = ! ShapeUtils.isClockWise( vertices ); - - if ( reverse ) { - - vertices = vertices.reverse(); - - // Maybe we should also check if holes are in the opposite direction, just to be safe ... - - for ( h = 0, hl = holes.length; h < hl; h ++ ) { - - ahole = holes[ h ]; - - if ( ShapeUtils.isClockWise( ahole ) ) { - - holes[ h ] = ahole.reverse(); - - } - - } - - } - - - var faces = ShapeUtils.triangulateShape( vertices, holes ); - - /* Vertices */ - - var contour = vertices; // vertices has all points but contour has only points of circumference - - for ( h = 0, hl = holes.length; h < hl; h ++ ) { - - ahole = holes[ h ]; - - vertices = vertices.concat( ahole ); - - } - - - function scalePt2( pt, vec, size ) { - - if ( ! vec ) console.error( "THREE.ExtrudeGeometry: vec does not exist" ); - - return vec.clone().multiplyScalar( size ).add( pt ); - - } - - var b, bs, t, z, - vert, vlen = vertices.length, - face, flen = faces.length; - - - // Find directions for point movement - - - function getBevelVec( inPt, inPrev, inNext ) { - - // computes for inPt the corresponding point inPt' on a new contour - // shifted by 1 unit (length of normalized vector) to the left - // if we walk along contour clockwise, this new contour is outside the old one - // - // inPt' is the intersection of the two lines parallel to the two - // adjacent edges of inPt at a distance of 1 unit on the left side. - - var v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt - - // good reading for geometry algorithms (here: line-line intersection) - // http://geomalgorithms.com/a05-_intersect-1.html - - var v_prev_x = inPt.x - inPrev.x, - v_prev_y = inPt.y - inPrev.y; - var v_next_x = inNext.x - inPt.x, - v_next_y = inNext.y - inPt.y; - - var v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y ); - - // check for collinear edges - var collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x ); - - if ( Math.abs( collinear0 ) > Number.EPSILON ) { - - // not collinear - - // length of vectors for normalizing - - var v_prev_len = Math.sqrt( v_prev_lensq ); - var v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y ); - - // shift adjacent points by unit vectors to the left - - var ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len ); - var ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len ); - - var ptNextShift_x = ( inNext.x - v_next_y / v_next_len ); - var ptNextShift_y = ( inNext.y + v_next_x / v_next_len ); - - // scaling factor for v_prev to intersection point - - var sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y - - ( ptNextShift_y - ptPrevShift_y ) * v_next_x ) / - ( v_prev_x * v_next_y - v_prev_y * v_next_x ); - - // vector from inPt to intersection point - - v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x ); - v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y ); - - // Don't normalize!, otherwise sharp corners become ugly - // but prevent crazy spikes - var v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y ); - if ( v_trans_lensq <= 2 ) { - - return new Vector2( v_trans_x, v_trans_y ); - - } else { - - shrink_by = Math.sqrt( v_trans_lensq / 2 ); - - } - - } else { - - // handle special case of collinear edges - - var direction_eq = false; // assumes: opposite - if ( v_prev_x > Number.EPSILON ) { - - if ( v_next_x > Number.EPSILON ) { - - direction_eq = true; - - } - - } else { - - if ( v_prev_x < - Number.EPSILON ) { - - if ( v_next_x < - Number.EPSILON ) { - - direction_eq = true; - - } - - } else { - - if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) { - - direction_eq = true; - - } - - } - - } - - if ( direction_eq ) { - - // console.log("Warning: lines are a straight sequence"); - v_trans_x = - v_prev_y; - v_trans_y = v_prev_x; - shrink_by = Math.sqrt( v_prev_lensq ); - - } else { - - // console.log("Warning: lines are a straight spike"); - v_trans_x = v_prev_x; - v_trans_y = v_prev_y; - shrink_by = Math.sqrt( v_prev_lensq / 2 ); - - } - - } - - return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by ); - - } - - - var contourMovements = []; - - for ( var i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) { - - if ( j === il ) j = 0; - if ( k === il ) k = 0; - - // (j)---(i)---(k) - // console.log('i,j,k', i, j , k) - - contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] ); - - } - - var holesMovements = [], - oneHoleMovements, verticesMovements = contourMovements.concat(); - - for ( h = 0, hl = holes.length; h < hl; h ++ ) { - - ahole = holes[ h ]; - - oneHoleMovements = []; - - for ( i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) { - - if ( j === il ) j = 0; - if ( k === il ) k = 0; - - // (j)---(i)---(k) - oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] ); - - } - - holesMovements.push( oneHoleMovements ); - verticesMovements = verticesMovements.concat( oneHoleMovements ); - - } - - - // Loop bevelSegments, 1 for the front, 1 for the back - - for ( b = 0; b < bevelSegments; b ++ ) { - - //for ( b = bevelSegments; b > 0; b -- ) { - - t = b / bevelSegments; - z = bevelThickness * Math.cos( t * Math.PI / 2 ); - bs = bevelSize * Math.sin( t * Math.PI / 2 ); - - // contract shape - - for ( i = 0, il = contour.length; i < il; i ++ ) { - - vert = scalePt2( contour[ i ], contourMovements[ i ], bs ); - - v( vert.x, vert.y, - z ); - - } - - // expand holes - - for ( h = 0, hl = holes.length; h < hl; h ++ ) { - - ahole = holes[ h ]; - oneHoleMovements = holesMovements[ h ]; - - for ( i = 0, il = ahole.length; i < il; i ++ ) { - - vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs ); - - v( vert.x, vert.y, - z ); - - } - - } - - } - - bs = bevelSize; - - // Back facing vertices - - for ( i = 0; i < vlen; i ++ ) { - - vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ]; - - if ( ! extrudeByPath ) { - - v( vert.x, vert.y, 0 ); - - } else { - - // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x ); - - normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x ); - binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y ); - - position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal ); - - v( position2.x, position2.y, position2.z ); - - } - - } - - // Add stepped vertices... - // Including front facing vertices - - var s; - - for ( s = 1; s <= steps; s ++ ) { - - for ( i = 0; i < vlen; i ++ ) { - - vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ]; - - if ( ! extrudeByPath ) { - - v( vert.x, vert.y, amount / steps * s ); - - } else { - - // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x ); - - normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x ); - binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y ); - - position2.copy( extrudePts[ s ] ).add( normal ).add( binormal ); - - v( position2.x, position2.y, position2.z ); - - } - - } - - } - - - // Add bevel segments planes - - //for ( b = 1; b <= bevelSegments; b ++ ) { - for ( b = bevelSegments - 1; b >= 0; b -- ) { - - t = b / bevelSegments; - z = bevelThickness * Math.cos( t * Math.PI / 2 ); - bs = bevelSize * Math.sin( t * Math.PI / 2 ); - - // contract shape - - for ( i = 0, il = contour.length; i < il; i ++ ) { - - vert = scalePt2( contour[ i ], contourMovements[ i ], bs ); - v( vert.x, vert.y, amount + z ); - - } - - // expand holes - - for ( h = 0, hl = holes.length; h < hl; h ++ ) { - - ahole = holes[ h ]; - oneHoleMovements = holesMovements[ h ]; - - for ( i = 0, il = ahole.length; i < il; i ++ ) { - - vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs ); - - if ( ! extrudeByPath ) { - - v( vert.x, vert.y, amount + z ); - - } else { - - v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z ); - - } - - } - - } - - } - - /* Faces */ - - // Top and bottom faces - - buildLidFaces(); - - // Sides faces - - buildSideFaces(); - - - ///// Internal functions - - function buildLidFaces() { - - var start = verticesArray.length / 3; - - if ( bevelEnabled ) { - - var layer = 0; // steps + 1 - var offset = vlen * layer; - - // Bottom faces - - for ( i = 0; i < flen; i ++ ) { - - face = faces[ i ]; - f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset ); - - } - - layer = steps + bevelSegments * 2; - offset = vlen * layer; - - // Top faces - - for ( i = 0; i < flen; i ++ ) { - - face = faces[ i ]; - f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset ); - - } - - } else { - - // Bottom faces - - for ( i = 0; i < flen; i ++ ) { - - face = faces[ i ]; - f3( face[ 2 ], face[ 1 ], face[ 0 ] ); - - } - - // Top faces - - for ( i = 0; i < flen; i ++ ) { - - face = faces[ i ]; - f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps ); - - } - - } - - scope.addGroup( start, verticesArray.length / 3 - start, options.material !== undefined ? options.material : 0 ); - - } - - // Create faces for the z-sides of the shape - - function buildSideFaces() { - - var start = verticesArray.length / 3; - var layeroffset = 0; - sidewalls( contour, layeroffset ); - layeroffset += contour.length; - - for ( h = 0, hl = holes.length; h < hl; h ++ ) { - - ahole = holes[ h ]; - sidewalls( ahole, layeroffset ); - - //, true - layeroffset += ahole.length; - - } - - - scope.addGroup( start, verticesArray.length / 3 - start, options.extrudeMaterial !== undefined ? options.extrudeMaterial : 1 ); - - - } - - function sidewalls( contour, layeroffset ) { - - var j, k; - i = contour.length; - - while ( -- i >= 0 ) { - - j = i; - k = i - 1; - if ( k < 0 ) k = contour.length - 1; - - //console.log('b', i,j, i-1, k,vertices.length); - - var s = 0, - sl = steps + bevelSegments * 2; - - for ( s = 0; s < sl; s ++ ) { - - var slen1 = vlen * s; - var slen2 = vlen * ( s + 1 ); - - var a = layeroffset + j + slen1, - b = layeroffset + k + slen1, - c = layeroffset + k + slen2, - d = layeroffset + j + slen2; - - f4( a, b, c, d ); - - } - - } - - } - - function v( x, y, z ) { - - placeholder.push( x ); - placeholder.push( y ); - placeholder.push( z ); - - } - - - function f3( a, b, c ) { - - addVertex( a ); - addVertex( b ); - addVertex( c ); - - var nextIndex = verticesArray.length / 3; - var uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 ); - - addUV( uvs[ 0 ] ); - addUV( uvs[ 1 ] ); - addUV( uvs[ 2 ] ); - - } - - function f4( a, b, c, d ) { - - addVertex( a ); - addVertex( b ); - addVertex( d ); - - addVertex( b ); - addVertex( c ); - addVertex( d ); - - - var nextIndex = verticesArray.length / 3; - var uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 ); - - addUV( uvs[ 0 ] ); - addUV( uvs[ 1 ] ); - addUV( uvs[ 3 ] ); - - addUV( uvs[ 1 ] ); - addUV( uvs[ 2 ] ); - addUV( uvs[ 3 ] ); - - } - - function addVertex( index ) { - - indicesArray.push( verticesArray.length / 3 ); - verticesArray.push( placeholder[ index * 3 + 0 ] ); - verticesArray.push( placeholder[ index * 3 + 1 ] ); - verticesArray.push( placeholder[ index * 3 + 2 ] ); - - } - - - function addUV( vector2 ) { - - uvArray.push( vector2.x ); - uvArray.push( vector2.y ); - - } - - if ( ! options.arrays ) { - - this.setIndex( indicesArray ); - this.addAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( options.arrays.uv, 2 ) ); - - } - - }; - - ExtrudeGeometry.WorldUVGenerator = { - - generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) { - - var a_x = vertices[ indexA * 3 ]; - var a_y = vertices[ indexA * 3 + 1 ]; - var b_x = vertices[ indexB * 3 ]; - var b_y = vertices[ indexB * 3 + 1 ]; - var c_x = vertices[ indexC * 3 ]; - var c_y = vertices[ indexC * 3 + 1 ]; - - return [ - new Vector2( a_x, a_y ), - new Vector2( b_x, b_y ), - new Vector2( c_x, c_y ) - ]; - - }, - - generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) { - - var a_x = vertices[ indexA * 3 ]; - var a_y = vertices[ indexA * 3 + 1 ]; - var a_z = vertices[ indexA * 3 + 2 ]; - var b_x = vertices[ indexB * 3 ]; - var b_y = vertices[ indexB * 3 + 1 ]; - var b_z = vertices[ indexB * 3 + 2 ]; - var c_x = vertices[ indexC * 3 ]; - var c_y = vertices[ indexC * 3 + 1 ]; - var c_z = vertices[ indexC * 3 + 2 ]; - var d_x = vertices[ indexD * 3 ]; - var d_y = vertices[ indexD * 3 + 1 ]; - var d_z = vertices[ indexD * 3 + 2 ]; - - if ( Math.abs( a_y - b_y ) < 0.01 ) { - - return [ - new Vector2( a_x, 1 - a_z ), - new Vector2( b_x, 1 - b_z ), - new Vector2( c_x, 1 - c_z ), - new Vector2( d_x, 1 - d_z ) - ]; - - } else { - - return [ - new Vector2( a_y, 1 - a_z ), - new Vector2( b_y, 1 - b_z ), - new Vector2( c_y, 1 - c_z ), - new Vector2( d_y, 1 - d_z ) - ]; - - } - - } - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Geometries', () => { - - QUnit.module.todo( 'ExtrudeGeometry', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - QUnit.module.todo( 'ExtrudeBufferGeometry', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // STATIC STUFF - QUnit.test( "WorldUVGenerator.generateTopUV", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "WorldUVGenerator.generateSideWallUV", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( "getArrays", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "addShapeList", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "addShape", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - - } ); - - } ); - - /** - * @author timothypratley / https://github.com/timothypratley - * @author Mugen87 / https://github.com/Mugen87 - */ - - function IcosahedronGeometry( radius, detail ) { - - Geometry.call( this ); - - this.type = 'IcosahedronGeometry'; - - this.parameters = { - radius: radius, - detail: detail - }; - - this.fromBufferGeometry( new IcosahedronBufferGeometry( radius, detail ) ); - this.mergeVertices(); - - } - - IcosahedronGeometry.prototype = Object.create( Geometry.prototype ); - IcosahedronGeometry.prototype.constructor = IcosahedronGeometry; - - // IcosahedronBufferGeometry - - function IcosahedronBufferGeometry( radius, detail ) { - - var t = ( 1 + Math.sqrt( 5 ) ) / 2; - - var vertices = [ - - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t, 0, - 0, - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t, - t, 0, - 1, t, 0, 1, - t, 0, - 1, - t, 0, 1 - ]; - - var indices = [ - 0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11, - 1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8, - 3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9, - 4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1 - ]; - - PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail ); - - this.type = 'IcosahedronBufferGeometry'; - - this.parameters = { - radius: radius, - detail: detail - }; - - } - - IcosahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype ); - IcosahedronBufferGeometry.prototype.constructor = IcosahedronBufferGeometry; - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author Anonymous - */ - /* global QUnit */ - - QUnit.module( 'Geometries', () => { - - QUnit.module.todo( 'IcosahedronGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - radius: 10, - detail: undefined - }; - - geometries = [ - new IcosahedronGeometry(), - new IcosahedronGeometry( parameters.radius ), - new IcosahedronGeometry( parameters.radius, parameters.detail ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - QUnit.module.todo( 'IcosahedronBufferGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - radius: 10, - detail: undefined - }; - - geometries = [ - new IcosahedronBufferGeometry(), - new IcosahedronBufferGeometry( parameters.radius ), - new IcosahedronBufferGeometry( parameters.radius, parameters.detail ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - } ); - - /** - * @author astrodud / http://astrodud.isgreat.org/ - * @author zz85 / https://github.com/zz85 - * @author bhouston / http://clara.io - * @author Mugen87 / https://github.com/Mugen87 - */ - - function LatheGeometry( points, segments, phiStart, phiLength ) { - - Geometry.call( this ); - - this.type = 'LatheGeometry'; - - this.parameters = { - points: points, - segments: segments, - phiStart: phiStart, - phiLength: phiLength - }; - - this.fromBufferGeometry( new LatheBufferGeometry( points, segments, phiStart, phiLength ) ); - this.mergeVertices(); - - } - - LatheGeometry.prototype = Object.create( Geometry.prototype ); - LatheGeometry.prototype.constructor = LatheGeometry; - - // LatheBufferGeometry - - function LatheBufferGeometry( points, segments, phiStart, phiLength ) { - - BufferGeometry.call( this ); - - this.type = 'LatheBufferGeometry'; - - this.parameters = { - points: points, - segments: segments, - phiStart: phiStart, - phiLength: phiLength - }; - - segments = Math.floor( segments ) || 12; - phiStart = phiStart || 0; - phiLength = phiLength || Math.PI * 2; - - // clamp phiLength so it's in range of [ 0, 2PI ] - - phiLength = _Math.clamp( phiLength, 0, Math.PI * 2 ); - - - // buffers - - var indices = []; - var vertices = []; - var uvs = []; - - // helper variables - - var base; - var inverseSegments = 1.0 / segments; - var vertex = new Vector3(); - var uv = new Vector2(); - var i, j; - - // generate vertices and uvs - - for ( i = 0; i <= segments; i ++ ) { - - var phi = phiStart + i * inverseSegments * phiLength; - - var sin = Math.sin( phi ); - var cos = Math.cos( phi ); - - for ( j = 0; j <= ( points.length - 1 ); j ++ ) { - - // vertex - - vertex.x = points[ j ].x * sin; - vertex.y = points[ j ].y; - vertex.z = points[ j ].x * cos; - - vertices.push( vertex.x, vertex.y, vertex.z ); - - // uv - - uv.x = i / segments; - uv.y = j / ( points.length - 1 ); - - uvs.push( uv.x, uv.y ); - - - } - - } - - // indices - - for ( i = 0; i < segments; i ++ ) { - - for ( j = 0; j < ( points.length - 1 ); j ++ ) { - - base = j + i * points.length; - - var a = base; - var b = base + points.length; - var c = base + points.length + 1; - var d = base + 1; - - // faces - - indices.push( a, b, d ); - indices.push( b, c, d ); - - } - - } - - // build geometry - - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - - // generate normals - - this.computeVertexNormals(); - - // if the geometry is closed, we need to average the normals along the seam. - // because the corresponding vertices are identical (but still have different UVs). - - if ( phiLength === Math.PI * 2 ) { - - var normals = this.attributes.normal.array; - var n1 = new Vector3(); - var n2 = new Vector3(); - var n = new Vector3(); - - // this is the buffer offset for the last line of vertices - - base = segments * points.length * 3; - - for ( i = 0, j = 0; i < points.length; i ++, j += 3 ) { - - // select the normal of the vertex in the first line - - n1.x = normals[ j + 0 ]; - n1.y = normals[ j + 1 ]; - n1.z = normals[ j + 2 ]; - - // select the normal of the vertex in the last line - - n2.x = normals[ base + j + 0 ]; - n2.y = normals[ base + j + 1 ]; - n2.z = normals[ base + j + 2 ]; - - // average normals - - n.addVectors( n1, n2 ).normalize(); - - // assign the new values to both normals - - normals[ j + 0 ] = normals[ base + j + 0 ] = n.x; - normals[ j + 1 ] = normals[ base + j + 1 ] = n.y; - normals[ j + 2 ] = normals[ base + j + 2 ] = n.z; - - } - - } - - } - - LatheBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - LatheBufferGeometry.prototype.constructor = LatheBufferGeometry; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Geometries', () => { - - QUnit.module.todo( 'LatheGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - points: [], - segments: 0, - phiStart: 0, - phiLength: 0 - }; - - geometries = [ - // new LatheGeometry(), // Todo: error for undefined point - new LatheGeometry( parameters.points ) - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - QUnit.module.todo( 'LatheBufferGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - points: [], - segments: 0, - phiStart: 0, - phiLength: 0 - }; - - geometries = [ - // new LatheBufferGeometry(), // Todo: error for undefined point - new LatheBufferGeometry( parameters.points ) - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - } ); - - /** - * @author timothypratley / https://github.com/timothypratley - * @author Mugen87 / https://github.com/Mugen87 - */ - - function OctahedronGeometry( radius, detail ) { - - Geometry.call( this ); - - this.type = 'OctahedronGeometry'; - - this.parameters = { - radius: radius, - detail: detail - }; - - this.fromBufferGeometry( new OctahedronBufferGeometry( radius, detail ) ); - this.mergeVertices(); - - } - - OctahedronGeometry.prototype = Object.create( Geometry.prototype ); - OctahedronGeometry.prototype.constructor = OctahedronGeometry; - - // OctahedronBufferGeometry - - function OctahedronBufferGeometry( radius, detail ) { - - var vertices = [ - 1, 0, 0, - 1, 0, 0, 0, 1, 0, - 0, - 1, 0, 0, 0, 1, 0, 0, - 1 - ]; - - var indices = [ - 0, 2, 4, 0, 4, 3, 0, 3, 5, - 0, 5, 2, 1, 2, 5, 1, 5, 3, - 1, 3, 4, 1, 4, 2 - ]; - - PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail ); - - this.type = 'OctahedronBufferGeometry'; - - this.parameters = { - radius: radius, - detail: detail - }; - - } - - OctahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype ); - OctahedronBufferGeometry.prototype.constructor = OctahedronBufferGeometry; - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author Anonymous - */ - /* global QUnit */ - - QUnit.module( 'Geometries', () => { - - QUnit.module.todo( 'OctahedronGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - radius: 10, - detail: undefined - }; - - geometries = [ - new OctahedronGeometry(), - new OctahedronGeometry( parameters.radius ), - new OctahedronGeometry( parameters.radius, parameters.detail ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - QUnit.module.todo( 'OctahedronBufferGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - radius: 10, - detail: undefined - }; - - geometries = [ - new OctahedronBufferGeometry(), - new OctahedronBufferGeometry( parameters.radius ), - new OctahedronBufferGeometry( parameters.radius, parameters.detail ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - } ); - - /** - * @author zz85 / https://github.com/zz85 - * @author Mugen87 / https://github.com/Mugen87 - * - * Parametric Surfaces Geometry - * based on the brilliant article by @prideout http://prideout.net/blog/?p=44 - */ - - function ParametricGeometry( func, slices, stacks ) { - - Geometry.call( this ); - - this.type = 'ParametricGeometry'; - - this.parameters = { - func: func, - slices: slices, - stacks: stacks - }; - - this.fromBufferGeometry( new ParametricBufferGeometry( func, slices, stacks ) ); - this.mergeVertices(); - - } - - ParametricGeometry.prototype = Object.create( Geometry.prototype ); - ParametricGeometry.prototype.constructor = ParametricGeometry; - - // ParametricBufferGeometry - - function ParametricBufferGeometry( func, slices, stacks ) { - - BufferGeometry.call( this ); - - this.type = 'ParametricBufferGeometry'; - - this.parameters = { - func: func, - slices: slices, - stacks: stacks - }; - - // buffers - - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; - - var EPS = 0.00001; - - var normal = new Vector3(); - - var p0 = new Vector3(), p1 = new Vector3(); - var pu = new Vector3(), pv = new Vector3(); - - var i, j; - - // generate vertices, normals and uvs - - var sliceCount = slices + 1; - - for ( i = 0; i <= stacks; i ++ ) { - - var v = i / stacks; - - for ( j = 0; j <= slices; j ++ ) { - - var u = j / slices; - - // vertex - - p0 = func( u, v, p0 ); - vertices.push( p0.x, p0.y, p0.z ); - - // normal - - // approximate tangent vectors via finite differences - - if ( u - EPS >= 0 ) { - - p1 = func( u - EPS, v, p1 ); - pu.subVectors( p0, p1 ); - - } else { - - p1 = func( u + EPS, v, p1 ); - pu.subVectors( p1, p0 ); - - } - - if ( v - EPS >= 0 ) { - - p1 = func( u, v - EPS, p1 ); - pv.subVectors( p0, p1 ); - - } else { - - p1 = func( u, v + EPS, p1 ); - pv.subVectors( p1, p0 ); - - } - - // cross product of tangent vectors returns surface normal - - normal.crossVectors( pu, pv ).normalize(); - normals.push( normal.x, normal.y, normal.z ); - - // uv - - uvs.push( u, v ); - - } - - } - - // generate indices - - for ( i = 0; i < stacks; i ++ ) { - - for ( j = 0; j < slices; j ++ ) { - - var a = i * sliceCount + j; - var b = i * sliceCount + j + 1; - var c = ( i + 1 ) * sliceCount + j + 1; - var d = ( i + 1 ) * sliceCount + j; - - // faces one and two - - indices.push( a, b, d ); - indices.push( b, c, d ); - - } - - } - - // build geometry - - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - - } - - ParametricBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - ParametricBufferGeometry.prototype.constructor = ParametricBufferGeometry; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Geometries', () => { - - QUnit.module.todo( 'ParametricGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = {}; - - geometries = [ - new ParametricGeometry() - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - QUnit.module.todo( 'ParametricBufferGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = {}; - - geometries = [ - new ParametricBufferGeometry() - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author Anonymous - */ - /* global QUnit */ - - QUnit.module( 'Geometries', () => { - - QUnit.module.todo( 'PlaneGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - width: 10, - height: 30, - widthSegments: 3, - heightSegments: 5 - }; - - geometries = [ - new PlaneGeometry(), - new PlaneGeometry( parameters.width ), - new PlaneGeometry( parameters.width, parameters.height ), - new PlaneGeometry( parameters.width, parameters.height, parameters.widthSegments ), - new PlaneGeometry( parameters.width, parameters.height, parameters.widthSegments, parameters.heightSegments ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - QUnit.module.todo( 'PlaneBufferGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - width: 10, - height: 30, - widthSegments: 3, - heightSegments: 5 - }; - - geometries = [ - new PlaneBufferGeometry(), - new PlaneBufferGeometry( parameters.width ), - new PlaneBufferGeometry( parameters.width, parameters.height ), - new PlaneBufferGeometry( parameters.width, parameters.height, parameters.widthSegments ), - new PlaneBufferGeometry( parameters.width, parameters.height, parameters.widthSegments, parameters.heightSegments ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Geometries', () => { - - QUnit.module.todo( 'PolyhedronGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = {}; - - geometries = [ - new PolyhedronGeometry() - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - QUnit.module.todo( 'PolyhedronBufferGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = {}; - - geometries = [ - new PolyhedronBufferGeometry() - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - } ); - - /** - * @author Kaleb Murphy - * @author Mugen87 / https://github.com/Mugen87 - */ - - function RingGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) { - - Geometry.call( this ); - - this.type = 'RingGeometry'; - - this.parameters = { - innerRadius: innerRadius, - outerRadius: outerRadius, - thetaSegments: thetaSegments, - phiSegments: phiSegments, - thetaStart: thetaStart, - thetaLength: thetaLength - }; - - this.fromBufferGeometry( new RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) ); - this.mergeVertices(); - - } - - RingGeometry.prototype = Object.create( Geometry.prototype ); - RingGeometry.prototype.constructor = RingGeometry; - - // RingBufferGeometry - - function RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) { - - BufferGeometry.call( this ); - - this.type = 'RingBufferGeometry'; - - this.parameters = { - innerRadius: innerRadius, - outerRadius: outerRadius, - thetaSegments: thetaSegments, - phiSegments: phiSegments, - thetaStart: thetaStart, - thetaLength: thetaLength - }; - - innerRadius = innerRadius || 0.5; - outerRadius = outerRadius || 1; - - thetaStart = thetaStart !== undefined ? thetaStart : 0; - thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2; - - thetaSegments = thetaSegments !== undefined ? Math.max( 3, thetaSegments ) : 8; - phiSegments = phiSegments !== undefined ? Math.max( 1, phiSegments ) : 1; - - // buffers - - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; - - // some helper variables - - var segment; - var radius = innerRadius; - var radiusStep = ( ( outerRadius - innerRadius ) / phiSegments ); - var vertex = new Vector3(); - var uv = new Vector2(); - var j, i; - - // generate vertices, normals and uvs - - for ( j = 0; j <= phiSegments; j ++ ) { - - for ( i = 0; i <= thetaSegments; i ++ ) { - - // values are generate from the inside of the ring to the outside - - segment = thetaStart + i / thetaSegments * thetaLength; - - // vertex - - vertex.x = radius * Math.cos( segment ); - vertex.y = radius * Math.sin( segment ); - - vertices.push( vertex.x, vertex.y, vertex.z ); - - // normal - - normals.push( 0, 0, 1 ); - - // uv - - uv.x = ( vertex.x / outerRadius + 1 ) / 2; - uv.y = ( vertex.y / outerRadius + 1 ) / 2; - - uvs.push( uv.x, uv.y ); - - } - - // increase the radius for next row of vertices - - radius += radiusStep; - - } - - // indices - - for ( j = 0; j < phiSegments; j ++ ) { - - var thetaSegmentLevel = j * ( thetaSegments + 1 ); - - for ( i = 0; i < thetaSegments; i ++ ) { - - segment = i + thetaSegmentLevel; - - var a = segment; - var b = segment + thetaSegments + 1; - var c = segment + thetaSegments + 2; - var d = segment + 1; - - // faces - - indices.push( a, b, d ); - indices.push( b, c, d ); - - } - - } - - // build geometry - - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - - } - - RingBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - RingBufferGeometry.prototype.constructor = RingBufferGeometry; - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author Anonymous - */ - /* global QUnit */ - - QUnit.module( 'Geometries', () => { - - QUnit.module.todo( 'RingGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - innerRadius: 10, - outerRadius: 60, - thetaSegments: 12, - phiSegments: 14, - thetaStart: 0.1, - thetaLength: 2.0 - }; - - geometries = [ - new RingGeometry(), - new RingGeometry( parameters.innerRadius ), - new RingGeometry( parameters.innerRadius, parameters.outerRadius ), - new RingGeometry( parameters.innerRadius, parameters.outerRadius, parameters.thetaSegments ), - new RingGeometry( parameters.innerRadius, parameters.outerRadius, parameters.thetaSegments, parameters.phiSegments ), - new RingGeometry( parameters.innerRadius, parameters.outerRadius, parameters.thetaSegments, parameters.phiSegments, parameters.thetaStart ), - new RingGeometry( parameters.innerRadius, parameters.outerRadius, parameters.thetaSegments, parameters.phiSegments, parameters.thetaStart, parameters.thetaLength ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - QUnit.module.todo( 'RingBufferGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - innerRadius: 10, - outerRadius: 60, - thetaSegments: 12, - phiSegments: 14, - thetaStart: 0.1, - thetaLength: 2.0 - }; - - geometries = [ - new RingBufferGeometry(), - new RingBufferGeometry( parameters.innerRadius ), - new RingBufferGeometry( parameters.innerRadius, parameters.outerRadius ), - new RingBufferGeometry( parameters.innerRadius, parameters.outerRadius, parameters.thetaSegments ), - new RingBufferGeometry( parameters.innerRadius, parameters.outerRadius, parameters.thetaSegments, parameters.phiSegments ), - new RingBufferGeometry( parameters.innerRadius, parameters.outerRadius, parameters.thetaSegments, parameters.phiSegments, parameters.thetaStart ), - new RingBufferGeometry( parameters.innerRadius, parameters.outerRadius, parameters.thetaSegments, parameters.phiSegments, parameters.thetaStart, parameters.thetaLength ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - } ); - - /** - * @author jonobr1 / http://jonobr1.com - * @author Mugen87 / https://github.com/Mugen87 - */ - - function ShapeGeometry( shapes, curveSegments ) { - - Geometry.call( this ); - - this.type = 'ShapeGeometry'; - - if ( typeof curveSegments === 'object' ) { - - console.warn( 'THREE.ShapeGeometry: Options parameter has been removed.' ); - - curveSegments = curveSegments.curveSegments; - - } - - this.parameters = { - shapes: shapes, - curveSegments: curveSegments - }; - - this.fromBufferGeometry( new ShapeBufferGeometry( shapes, curveSegments ) ); - this.mergeVertices(); - - } - - ShapeGeometry.prototype = Object.create( Geometry.prototype ); - ShapeGeometry.prototype.constructor = ShapeGeometry; - - // ShapeBufferGeometry - - function ShapeBufferGeometry( shapes, curveSegments ) { - - BufferGeometry.call( this ); - - this.type = 'ShapeBufferGeometry'; - - this.parameters = { - shapes: shapes, - curveSegments: curveSegments - }; - - curveSegments = curveSegments || 12; - - // buffers - - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; - - // helper variables - - var groupStart = 0; - var groupCount = 0; - - // allow single and array values for "shapes" parameter - - if ( Array.isArray( shapes ) === false ) { - - addShape( shapes ); - - } else { - - for ( var i = 0; i < shapes.length; i ++ ) { - - addShape( shapes[ i ] ); - - this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support - - groupStart += groupCount; - groupCount = 0; - - } - - } - - // build geometry - - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - - - // helper functions - - function addShape( shape ) { - - var i, l, shapeHole; - - var indexOffset = vertices.length / 3; - var points = shape.extractPoints( curveSegments ); - - var shapeVertices = points.shape; - var shapeHoles = points.holes; - - // check direction of vertices - - if ( ShapeUtils.isClockWise( shapeVertices ) === false ) { - - shapeVertices = shapeVertices.reverse(); - - // also check if holes are in the opposite direction - - for ( i = 0, l = shapeHoles.length; i < l; i ++ ) { - - shapeHole = shapeHoles[ i ]; - - if ( ShapeUtils.isClockWise( shapeHole ) === true ) { - - shapeHoles[ i ] = shapeHole.reverse(); - - } - - } - - } - - var faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles ); - - // join vertices of inner and outer paths to a single array - - for ( i = 0, l = shapeHoles.length; i < l; i ++ ) { - - shapeHole = shapeHoles[ i ]; - shapeVertices = shapeVertices.concat( shapeHole ); - - } - - // vertices, normals, uvs - - for ( i = 0, l = shapeVertices.length; i < l; i ++ ) { - - var vertex = shapeVertices[ i ]; - - vertices.push( vertex.x, vertex.y, 0 ); - normals.push( 0, 0, 1 ); - uvs.push( vertex.x, vertex.y ); // world uvs - - } - - // incides - - for ( i = 0, l = faces.length; i < l; i ++ ) { - - var face = faces[ i ]; - - var a = face[ 0 ] + indexOffset; - var b = face[ 1 ] + indexOffset; - var c = face[ 2 ] + indexOffset; - - indices.push( a, b, c ); - groupCount += 3; - - } - - } - - } - - ShapeBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - ShapeBufferGeometry.prototype.constructor = ShapeBufferGeometry; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Geometries', () => { - - QUnit.module.todo( 'ShapeGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = {}; - - geometries = [ - new ShapeGeometry() - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - QUnit.module.todo( 'ShapeBufferGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = {}; - - geometries = [ - new ShapeBufferGeometry() - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author Anonymous - */ - /* global QUnit */ - - QUnit.module( 'Geometries', () => { - - QUnit.module.todo( 'SphereGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - radius: 10, - widthSegments: 20, - heightSegments: 30, - phiStart: 0.5, - phiLength: 1.0, - thetaStart: 0.4, - thetaLength: 2.0, - }; - - geometries = [ - new SphereGeometry(), - new SphereGeometry( parameters.radius ), - new SphereGeometry( parameters.radius, parameters.widthSegments ), - new SphereGeometry( parameters.radius, parameters.widthSegments, parameters.heightSegments ), - new SphereGeometry( parameters.radius, parameters.widthSegments, parameters.heightSegments, parameters.phiStart ), - new SphereGeometry( parameters.radius, parameters.widthSegments, parameters.heightSegments, parameters.phiStart, parameters.phiLength ), - new SphereGeometry( parameters.radius, parameters.widthSegments, parameters.heightSegments, parameters.phiStart, parameters.phiLength, parameters.thetaStart ), - new SphereGeometry( parameters.radius, parameters.widthSegments, parameters.heightSegments, parameters.phiStart, parameters.phiLength, parameters.thetaStart, parameters.thetaLength ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - QUnit.module.todo( 'SphereBufferGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - radius: 10, - widthSegments: 20, - heightSegments: 30, - phiStart: 0.5, - phiLength: 1.0, - thetaStart: 0.4, - thetaLength: 2.0, - }; - - geometries = [ - new SphereBufferGeometry(), - new SphereBufferGeometry( parameters.radius ), - new SphereBufferGeometry( parameters.radius, parameters.widthSegments ), - new SphereBufferGeometry( parameters.radius, parameters.widthSegments, parameters.heightSegments ), - new SphereBufferGeometry( parameters.radius, parameters.widthSegments, parameters.heightSegments, parameters.phiStart ), - new SphereBufferGeometry( parameters.radius, parameters.widthSegments, parameters.heightSegments, parameters.phiStart, parameters.phiLength ), - new SphereBufferGeometry( parameters.radius, parameters.widthSegments, parameters.heightSegments, parameters.phiStart, parameters.phiLength, parameters.thetaStart ), - new SphereBufferGeometry( parameters.radius, parameters.widthSegments, parameters.heightSegments, parameters.phiStart, parameters.phiLength, parameters.thetaStart, parameters.thetaLength ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - } ); - - /** - * @author timothypratley / https://github.com/timothypratley - * @author Mugen87 / https://github.com/Mugen87 - */ - - function TetrahedronGeometry( radius, detail ) { - - Geometry.call( this ); - - this.type = 'TetrahedronGeometry'; - - this.parameters = { - radius: radius, - detail: detail - }; - - this.fromBufferGeometry( new TetrahedronBufferGeometry( radius, detail ) ); - this.mergeVertices(); - - } - - TetrahedronGeometry.prototype = Object.create( Geometry.prototype ); - TetrahedronGeometry.prototype.constructor = TetrahedronGeometry; - - // TetrahedronBufferGeometry - - function TetrahedronBufferGeometry( radius, detail ) { - - var vertices = [ - 1, 1, 1, - 1, - 1, 1, - 1, 1, - 1, 1, - 1, - 1 - ]; - - var indices = [ - 2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1 - ]; - - PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail ); - - this.type = 'TetrahedronBufferGeometry'; - - this.parameters = { - radius: radius, - detail: detail - }; - - } - - TetrahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype ); - TetrahedronBufferGeometry.prototype.constructor = TetrahedronBufferGeometry; - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author Anonymous - */ - /* global QUnit */ - - QUnit.module( 'Geometries', () => { - - QUnit.module.todo( 'TetrahedronGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - radius: 10, - detail: undefined - }; - - geometries = [ - new TetrahedronGeometry(), - new TetrahedronGeometry( parameters.radius ), - new TetrahedronGeometry( parameters.radius, parameters.widthSegments ), - new TetrahedronGeometry( parameters.radius, parameters.widthSegments, parameters.heightSegments ), - new TetrahedronGeometry( parameters.radius, parameters.widthSegments, parameters.heightSegments, parameters.phiStart ), - new TetrahedronGeometry( parameters.radius, parameters.widthSegments, parameters.heightSegments, parameters.phiStart, parameters.phiLength ), - new TetrahedronGeometry( parameters.radius, parameters.widthSegments, parameters.heightSegments, parameters.phiStart, parameters.phiLength, parameters.thetaStart ), - new TetrahedronGeometry( parameters.radius, parameters.widthSegments, parameters.heightSegments, parameters.phiStart, parameters.phiLength, parameters.thetaStart, parameters.thetaLength ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - QUnit.module.todo( 'SphereBufferGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - radius: 10, - detail: undefined - }; - - geometries = [ - new TetrahedronBufferGeometry(), - new TetrahedronBufferGeometry( parameters.radius ), - new TetrahedronBufferGeometry( parameters.radius, parameters.widthSegments ), - new TetrahedronBufferGeometry( parameters.radius, parameters.widthSegments, parameters.heightSegments ), - new TetrahedronBufferGeometry( parameters.radius, parameters.widthSegments, parameters.heightSegments, parameters.phiStart ), - new TetrahedronBufferGeometry( parameters.radius, parameters.widthSegments, parameters.heightSegments, parameters.phiStart, parameters.phiLength ), - new TetrahedronBufferGeometry( parameters.radius, parameters.widthSegments, parameters.heightSegments, parameters.phiStart, parameters.phiLength, parameters.thetaStart ), - new TetrahedronBufferGeometry( parameters.radius, parameters.widthSegments, parameters.heightSegments, parameters.phiStart, parameters.phiLength, parameters.thetaStart, parameters.thetaLength ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - } ); - - /** - * @author zz85 / http://www.lab4games.net/zz85/blog - * @author alteredq / http://alteredqualia.com/ - * - * Text = 3D Text - * - * parameters = { - * font: , // font - * - * size: , // size of the text - * height: , // thickness to extrude text - * curveSegments: , // number of points on the curves - * - * bevelEnabled: , // turn on bevel - * bevelThickness: , // how deep into text bevel goes - * bevelSize: // how far from text outline is bevel - * } - */ - - function TextGeometry( text, parameters ) { - - Geometry.call( this ); - - this.type = 'TextGeometry'; - - this.parameters = { - text: text, - parameters: parameters - }; - - this.fromBufferGeometry( new TextBufferGeometry( text, parameters ) ); - this.mergeVertices(); - - } - - TextGeometry.prototype = Object.create( Geometry.prototype ); - TextGeometry.prototype.constructor = TextGeometry; - - // TextBufferGeometry - - function TextBufferGeometry( text, parameters ) { - - parameters = parameters || {}; - - var font = parameters.font; - - if ( ! ( font && font.isFont ) ) { - - console.error( 'THREE.TextGeometry: font parameter is not an instance of THREE.Font.' ); - return new Geometry(); - - } - - var shapes = font.generateShapes( text, parameters.size, parameters.curveSegments ); - - // translate parameters to ExtrudeGeometry API - - parameters.amount = parameters.height !== undefined ? parameters.height : 50; - - // defaults - - if ( parameters.bevelThickness === undefined ) parameters.bevelThickness = 10; - if ( parameters.bevelSize === undefined ) parameters.bevelSize = 8; - if ( parameters.bevelEnabled === undefined ) parameters.bevelEnabled = false; - - ExtrudeBufferGeometry.call( this, shapes, parameters ); - - this.type = 'TextBufferGeometry'; - - } - - TextBufferGeometry.prototype = Object.create( ExtrudeBufferGeometry.prototype ); - TextBufferGeometry.prototype.constructor = TextBufferGeometry; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Geometries', () => { - - QUnit.module.todo( 'TextGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - // TODO: we cannot load any font from Threejs package :S - const parameters = { - font: undefined - }; - - geometries = [ - new TextGeometry() - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - QUnit.module.todo( 'TextBufferGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = {}; - - geometries = [ - new TextBufferGeometry() - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - } ); - - /** - * @author oosmoxiecode - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ - - function TorusGeometry( radius, tube, radialSegments, tubularSegments, arc ) { - - Geometry.call( this ); - - this.type = 'TorusGeometry'; - - this.parameters = { - radius: radius, - tube: tube, - radialSegments: radialSegments, - tubularSegments: tubularSegments, - arc: arc - }; - - this.fromBufferGeometry( new TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) ); - this.mergeVertices(); - - } - - TorusGeometry.prototype = Object.create( Geometry.prototype ); - TorusGeometry.prototype.constructor = TorusGeometry; - - // TorusBufferGeometry - - function TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) { - - BufferGeometry.call( this ); - - this.type = 'TorusBufferGeometry'; - - this.parameters = { - radius: radius, - tube: tube, - radialSegments: radialSegments, - tubularSegments: tubularSegments, - arc: arc - }; - - radius = radius || 1; - tube = tube || 0.4; - radialSegments = Math.floor( radialSegments ) || 8; - tubularSegments = Math.floor( tubularSegments ) || 6; - arc = arc || Math.PI * 2; - - // buffers - - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; - - // helper variables - - var center = new Vector3(); - var vertex = new Vector3(); - var normal = new Vector3(); - - var j, i; - - // generate vertices, normals and uvs - - for ( j = 0; j <= radialSegments; j ++ ) { - - for ( i = 0; i <= tubularSegments; i ++ ) { - - var u = i / tubularSegments * arc; - var v = j / radialSegments * Math.PI * 2; - - // vertex - - vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u ); - vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u ); - vertex.z = tube * Math.sin( v ); - - vertices.push( vertex.x, vertex.y, vertex.z ); - - // normal - - center.x = radius * Math.cos( u ); - center.y = radius * Math.sin( u ); - normal.subVectors( vertex, center ).normalize(); - - normals.push( normal.x, normal.y, normal.z ); - - // uv - - uvs.push( i / tubularSegments ); - uvs.push( j / radialSegments ); - - } - - } - - // generate indices - - for ( j = 1; j <= radialSegments; j ++ ) { - - for ( i = 1; i <= tubularSegments; i ++ ) { - - // indices - - var a = ( tubularSegments + 1 ) * j + i - 1; - var b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1; - var c = ( tubularSegments + 1 ) * ( j - 1 ) + i; - var d = ( tubularSegments + 1 ) * j + i; - - // faces - - indices.push( a, b, d ); - indices.push( b, c, d ); - - } - - } - - // build geometry - - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - - } - - TorusBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - TorusBufferGeometry.prototype.constructor = TorusBufferGeometry; - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author Anonymous - */ - /* global QUnit */ - - QUnit.module( 'Geometries', () => { - - QUnit.module.todo( 'TorusGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - radius: 10, - tube: 20, - radialSegments: 30, - tubularSegments: 10, - arc: 2.0, - }; - - geometries = [ - new TorusGeometry(), - new TorusGeometry( parameters.radius ), - new TorusGeometry( parameters.radius, parameters.tube ), - new TorusGeometry( parameters.radius, parameters.tube, parameters.radialSegments ), - new TorusGeometry( parameters.radius, parameters.tube, parameters.radialSegments, parameters.tubularSegments ), - new TorusGeometry( parameters.radius, parameters.tube, parameters.radialSegments, parameters.tubularSegments, parameters.arc ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - QUnit.module.todo( 'TorusBufferGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - radius: 10, - tube: 20, - radialSegments: 30, - tubularSegments: 10, - arc: 2.0, - }; - - geometries = [ - new TorusBufferGeometry(), - new TorusBufferGeometry( parameters.radius ), - new TorusBufferGeometry( parameters.radius, parameters.tube ), - new TorusBufferGeometry( parameters.radius, parameters.tube, parameters.radialSegments ), - new TorusBufferGeometry( parameters.radius, parameters.tube, parameters.radialSegments, parameters.tubularSegments ), - new TorusBufferGeometry( parameters.radius, parameters.tube, parameters.radialSegments, parameters.tubularSegments, parameters.arc ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - } ); - - /** - * @author oosmoxiecode - * @author Mugen87 / https://github.com/Mugen87 - * - * based on http://www.blackpawn.com/texts/pqtorus/ - */ - - function TorusKnotGeometry( radius, tube, tubularSegments, radialSegments, p, q, heightScale ) { - - Geometry.call( this ); - - this.type = 'TorusKnotGeometry'; - - this.parameters = { - radius: radius, - tube: tube, - tubularSegments: tubularSegments, - radialSegments: radialSegments, - p: p, - q: q - }; - - if ( heightScale !== undefined ) console.warn( 'THREE.TorusKnotGeometry: heightScale has been deprecated. Use .scale( x, y, z ) instead.' ); - - this.fromBufferGeometry( new TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) ); - this.mergeVertices(); - - } - - TorusKnotGeometry.prototype = Object.create( Geometry.prototype ); - TorusKnotGeometry.prototype.constructor = TorusKnotGeometry; - - // TorusKnotBufferGeometry - - function TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) { - - BufferGeometry.call( this ); - - this.type = 'TorusKnotBufferGeometry'; - - this.parameters = { - radius: radius, - tube: tube, - tubularSegments: tubularSegments, - radialSegments: radialSegments, - p: p, - q: q - }; - - radius = radius || 1; - tube = tube || 0.4; - tubularSegments = Math.floor( tubularSegments ) || 64; - radialSegments = Math.floor( radialSegments ) || 8; - p = p || 2; - q = q || 3; - - // buffers - - var indices = []; - var vertices = []; - var normals = []; - var uvs = []; - - // helper variables - - var i, j; - - var vertex = new Vector3(); - var normal = new Vector3(); - - var P1 = new Vector3(); - var P2 = new Vector3(); - - var B = new Vector3(); - var T = new Vector3(); - var N = new Vector3(); - - // generate vertices, normals and uvs - - for ( i = 0; i <= tubularSegments; ++ i ) { - - // the radian "u" is used to calculate the position on the torus curve of the current tubular segement - - var u = i / tubularSegments * p * Math.PI * 2; - - // now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead. - // these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions - - calculatePositionOnCurve( u, p, q, radius, P1 ); - calculatePositionOnCurve( u + 0.01, p, q, radius, P2 ); - - // calculate orthonormal basis - - T.subVectors( P2, P1 ); - N.addVectors( P2, P1 ); - B.crossVectors( T, N ); - N.crossVectors( B, T ); - - // normalize B, N. T can be ignored, we don't use it - - B.normalize(); - N.normalize(); - - for ( j = 0; j <= radialSegments; ++ j ) { - - // now calculate the vertices. they are nothing more than an extrusion of the torus curve. - // because we extrude a shape in the xy-plane, there is no need to calculate a z-value. - - var v = j / radialSegments * Math.PI * 2; - var cx = - tube * Math.cos( v ); - var cy = tube * Math.sin( v ); - - // now calculate the final vertex position. - // first we orient the extrusion with our basis vectos, then we add it to the current position on the curve - - vertex.x = P1.x + ( cx * N.x + cy * B.x ); - vertex.y = P1.y + ( cx * N.y + cy * B.y ); - vertex.z = P1.z + ( cx * N.z + cy * B.z ); - - vertices.push( vertex.x, vertex.y, vertex.z ); - - // normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal) - - normal.subVectors( vertex, P1 ).normalize(); - - normals.push( normal.x, normal.y, normal.z ); - - // uv - - uvs.push( i / tubularSegments ); - uvs.push( j / radialSegments ); - - } - - } - - // generate indices - - for ( j = 1; j <= tubularSegments; j ++ ) { - - for ( i = 1; i <= radialSegments; i ++ ) { - - // indices - - var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 ); - var b = ( radialSegments + 1 ) * j + ( i - 1 ); - var c = ( radialSegments + 1 ) * j + i; - var d = ( radialSegments + 1 ) * ( j - 1 ) + i; - - // faces - - indices.push( a, b, d ); - indices.push( b, c, d ); - - } - - } - - // build geometry - - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - - // this function calculates the current position on the torus curve - - function calculatePositionOnCurve( u, p, q, radius, position ) { - - var cu = Math.cos( u ); - var su = Math.sin( u ); - var quOverP = q / p * u; - var cs = Math.cos( quOverP ); - - position.x = radius * ( 2 + cs ) * 0.5 * cu; - position.y = radius * ( 2 + cs ) * su * 0.5; - position.z = radius * Math.sin( quOverP ) * 0.5; - - } - - } - - TorusKnotBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - TorusKnotBufferGeometry.prototype.constructor = TorusKnotBufferGeometry; - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author Anonymous - */ - /* global QUnit */ - - QUnit.module( 'Geometries', () => { - - QUnit.module.todo( 'SphereGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - radius: 10, - tube: 20, - tubularSegments: 30, - radialSegments: 10, - p: 3, - q: 2 - }; - - geometries = [ - new TorusKnotGeometry(), - new TorusKnotGeometry( parameters.radius ), - new TorusKnotGeometry( parameters.radius, parameters.tube ), - new TorusKnotGeometry( parameters.radius, parameters.tube, parameters.tubularSegments ), - new TorusKnotGeometry( parameters.radius, parameters.tube, parameters.tubularSegments, parameters.radialSegments ), - new TorusKnotGeometry( parameters.radius, parameters.tube, parameters.tubularSegments, parameters.radialSegments, parameters.p, parameters.q ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - QUnit.module.todo( 'TorusKnotBufferGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - radius: 10, - tube: 20, - tubularSegments: 30, - radialSegments: 10, - p: 3, - q: 2 - }; - - geometries = [ - new TorusKnotBufferGeometry(), - new TorusKnotBufferGeometry( parameters.radius ), - new TorusKnotBufferGeometry( parameters.radius, parameters.tube ), - new TorusKnotBufferGeometry( parameters.radius, parameters.tube, parameters.tubularSegments ), - new TorusKnotBufferGeometry( parameters.radius, parameters.tube, parameters.tubularSegments, parameters.radialSegments ), - new TorusKnotBufferGeometry( parameters.radius, parameters.tube, parameters.tubularSegments, parameters.radialSegments, parameters.p, parameters.q ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - } ); - - /** - * @author oosmoxiecode / https://github.com/oosmoxiecode - * @author WestLangley / https://github.com/WestLangley - * @author zz85 / https://github.com/zz85 - * @author miningold / https://github.com/miningold - * @author jonobr1 / https://github.com/jonobr1 - * @author Mugen87 / https://github.com/Mugen87 - * - */ - - function TubeGeometry( path, tubularSegments, radius, radialSegments, closed, taper ) { - - Geometry.call( this ); - - this.type = 'TubeGeometry'; - - this.parameters = { - path: path, - tubularSegments: tubularSegments, - radius: radius, - radialSegments: radialSegments, - closed: closed - }; - - if ( taper !== undefined ) console.warn( 'THREE.TubeGeometry: taper has been removed.' ); - - var bufferGeometry = new TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed ); - - // expose internals - - this.tangents = bufferGeometry.tangents; - this.normals = bufferGeometry.normals; - this.binormals = bufferGeometry.binormals; - - // create geometry - - this.fromBufferGeometry( bufferGeometry ); - this.mergeVertices(); - - } - - TubeGeometry.prototype = Object.create( Geometry.prototype ); - TubeGeometry.prototype.constructor = TubeGeometry; - - // TubeBufferGeometry - - function TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed ) { - - BufferGeometry.call( this ); - - this.type = 'TubeBufferGeometry'; - - this.parameters = { - path: path, - tubularSegments: tubularSegments, - radius: radius, - radialSegments: radialSegments, - closed: closed - }; - - tubularSegments = tubularSegments || 64; - radius = radius || 1; - radialSegments = radialSegments || 8; - closed = closed || false; - - var frames = path.computeFrenetFrames( tubularSegments, closed ); - - // expose internals - - this.tangents = frames.tangents; - this.normals = frames.normals; - this.binormals = frames.binormals; - - // helper variables - - var vertex = new Vector3(); - var normal = new Vector3(); - var uv = new Vector2(); - var P = new Vector3(); - - var i, j; - - // buffer - - var vertices = []; - var normals = []; - var uvs = []; - var indices = []; - - // create buffer data - - generateBufferData(); - - // build geometry - - this.setIndex( indices ); - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); - this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); - - // functions - - function generateBufferData() { - - for ( i = 0; i < tubularSegments; i ++ ) { - - generateSegment( i ); - - } - - // if the geometry is not closed, generate the last row of vertices and normals - // at the regular position on the given path - // - // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ) - - generateSegment( ( closed === false ) ? tubularSegments : 0 ); - - // uvs are generated in a separate function. - // this makes it easy compute correct values for closed geometries - - generateUVs(); - - // finally create faces - - generateIndices(); - - } - - function generateSegment( i ) { - - // we use getPointAt to sample evenly distributed points from the given path - - P = path.getPointAt( i / tubularSegments, P ); - - // retrieve corresponding normal and binormal - - var N = frames.normals[ i ]; - var B = frames.binormals[ i ]; - - // generate normals and vertices for the current segment - - for ( j = 0; j <= radialSegments; j ++ ) { - - var v = j / radialSegments * Math.PI * 2; - - var sin = Math.sin( v ); - var cos = - Math.cos( v ); - - // normal - - normal.x = ( cos * N.x + sin * B.x ); - normal.y = ( cos * N.y + sin * B.y ); - normal.z = ( cos * N.z + sin * B.z ); - normal.normalize(); - - normals.push( normal.x, normal.y, normal.z ); - - // vertex - - vertex.x = P.x + radius * normal.x; - vertex.y = P.y + radius * normal.y; - vertex.z = P.z + radius * normal.z; - - vertices.push( vertex.x, vertex.y, vertex.z ); - - } - - } - - function generateIndices() { - - for ( j = 1; j <= tubularSegments; j ++ ) { - - for ( i = 1; i <= radialSegments; i ++ ) { - - var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 ); - var b = ( radialSegments + 1 ) * j + ( i - 1 ); - var c = ( radialSegments + 1 ) * j + i; - var d = ( radialSegments + 1 ) * ( j - 1 ) + i; - - // faces - - indices.push( a, b, d ); - indices.push( b, c, d ); - - } - - } - - } - - function generateUVs() { - - for ( i = 0; i <= tubularSegments; i ++ ) { - - for ( j = 0; j <= radialSegments; j ++ ) { - - uv.x = i / tubularSegments; - uv.y = j / radialSegments; - - uvs.push( uv.x, uv.y ); - - } - - } - - } - - } - - TubeBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); - TubeBufferGeometry.prototype.constructor = TubeBufferGeometry; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Geometries', () => { - - QUnit.module.todo( 'TubeGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = {}; - - geometries = [ - new TubeGeometry() - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - QUnit.module.todo( 'TubeBufferGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = {}; - - geometries = [ - new TubeBufferGeometry() - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ - - function WireframeGeometry( geometry ) { - - BufferGeometry.call( this ); - - this.type = 'WireframeGeometry'; - - // buffer - - var vertices = []; - - // helper variables - - var i, j, l, o, ol; - var edge = [ 0, 0 ], edges = {}, e, edge1, edge2; - var key, keys = [ 'a', 'b', 'c' ]; - var vertex; - - // different logic for Geometry and BufferGeometry - - if ( geometry && geometry.isGeometry ) { - - // create a data structure that contains all edges without duplicates - - var faces = geometry.faces; - - for ( i = 0, l = faces.length; i < l; i ++ ) { - - var face = faces[ i ]; - - for ( j = 0; j < 3; j ++ ) { - - edge1 = face[ keys[ j ] ]; - edge2 = face[ keys[ ( j + 1 ) % 3 ] ]; - edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates - edge[ 1 ] = Math.max( edge1, edge2 ); - - key = edge[ 0 ] + ',' + edge[ 1 ]; - - if ( edges[ key ] === undefined ) { - - edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] }; - - } - - } - - } - - // generate vertices - - for ( key in edges ) { - - e = edges[ key ]; - - vertex = geometry.vertices[ e.index1 ]; - vertices.push( vertex.x, vertex.y, vertex.z ); - - vertex = geometry.vertices[ e.index2 ]; - vertices.push( vertex.x, vertex.y, vertex.z ); - - } - - } else if ( geometry && geometry.isBufferGeometry ) { - - var position, indices, groups; - var group, start, count; - var index1, index2; - - vertex = new Vector3(); - - if ( geometry.index !== null ) { - - // indexed BufferGeometry - - position = geometry.attributes.position; - indices = geometry.index; - groups = geometry.groups; - - if ( groups.length === 0 ) { - - groups = [ { start: 0, count: indices.count, materialIndex: 0 } ]; - - } - - // create a data structure that contains all eges without duplicates - - for ( o = 0, ol = groups.length; o < ol; ++ o ) { - - group = groups[ o ]; - - start = group.start; - count = group.count; - - for ( i = start, l = ( start + count ); i < l; i += 3 ) { - - for ( j = 0; j < 3; j ++ ) { - - edge1 = indices.getX( i + j ); - edge2 = indices.getX( i + ( j + 1 ) % 3 ); - edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates - edge[ 1 ] = Math.max( edge1, edge2 ); - - key = edge[ 0 ] + ',' + edge[ 1 ]; - - if ( edges[ key ] === undefined ) { - - edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] }; - - } - - } - - } - - } - - // generate vertices - - for ( key in edges ) { - - e = edges[ key ]; - - vertex.fromBufferAttribute( position, e.index1 ); - vertices.push( vertex.x, vertex.y, vertex.z ); - - vertex.fromBufferAttribute( position, e.index2 ); - vertices.push( vertex.x, vertex.y, vertex.z ); - - } - - } else { - - // non-indexed BufferGeometry - - position = geometry.attributes.position; - - for ( i = 0, l = ( position.count / 3 ); i < l; i ++ ) { - - for ( j = 0; j < 3; j ++ ) { - - // three edges per triangle, an edge is represented as (index1, index2) - // e.g. the first triangle has the following edges: (0,1),(1,2),(2,0) - - index1 = 3 * i + j; - vertex.fromBufferAttribute( position, index1 ); - vertices.push( vertex.x, vertex.y, vertex.z ); - - index2 = 3 * i + ( ( j + 1 ) % 3 ); - vertex.fromBufferAttribute( position, index2 ); - vertices.push( vertex.x, vertex.y, vertex.z ); - - } - - } - - } - - } - - // build geometry - - this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - - } - - WireframeGeometry.prototype = Object.create( BufferGeometry.prototype ); - WireframeGeometry.prototype.constructor = WireframeGeometry; - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Geometries', () => { - - QUnit.module.todo( 'WireframeGeometry', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = {}; - - geometries = [ - new WireframeGeometry() - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - } ); - - /** - * @author WestLangley / http://github.com/WestLangley - * @author zz85 / http://github.com/zz85 - * @author bhouston / http://clara.io - * - * Creates an arrow for visualizing directions - * - * Parameters: - * dir - Vector3 - * origin - Vector3 - * length - Number - * color - color in hex value - * headLength - Number - * headWidth - Number - */ - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Helpers', () => { - - QUnit.module.todo( 'ArrowHelper', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "setDirection", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setLength", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setColor", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author sroucheray / http://sroucheray.org/ - * @author mrdoob / http://mrdoob.com/ - */ - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Helpers', () => { - - QUnit.module.todo( 'AxesHelper', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author WestLangley / http://github.com/WestLangley - */ - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Helpers', () => { - - QUnit.module.todo( 'Box3Helper', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "updateMatrixWorld", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / http://github.com/Mugen87 - */ - - function BoxHelper( object, color ) { - - this.object = object; - - if ( color === undefined ) color = 0xffff00; - - var indices = new Uint16Array( [ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ] ); - var positions = new Float32Array( 8 * 3 ); - - var geometry = new BufferGeometry(); - geometry.setIndex( new BufferAttribute( indices, 1 ) ); - geometry.addAttribute( 'position', new BufferAttribute( positions, 3 ) ); - - LineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) ); - - this.matrixAutoUpdate = false; - - this.update(); - - } - - BoxHelper.prototype = Object.create( LineSegments.prototype ); - BoxHelper.prototype.constructor = BoxHelper; - - BoxHelper.prototype.update = ( function () { - - var box = new Box3(); - - return function update( object ) { - - if ( object !== undefined ) { - - console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' ); - - } - - if ( this.object !== undefined ) { - - box.setFromObject( this.object ); - - } - - if ( box.isEmpty() ) return; - - var min = box.min; - var max = box.max; - - /* - 5____4 - 1/___0/| - | 6__|_7 - 2/___3/ - - 0: max.x, max.y, max.z - 1: min.x, max.y, max.z - 2: min.x, min.y, max.z - 3: max.x, min.y, max.z - 4: max.x, max.y, min.z - 5: min.x, max.y, min.z - 6: min.x, min.y, min.z - 7: max.x, min.y, min.z - */ - - var position = this.geometry.attributes.position; - var array = position.array; - - array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z; - array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z; - array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z; - array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z; - array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z; - array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z; - array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z; - array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z; - - position.needsUpdate = true; - - this.geometry.computeBoundingSphere(); - - }; - - } )(); - - BoxHelper.prototype.setFromObject = function ( object ) { - - this.object = object; - this.update(); - - return this; - - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author Anonymous - */ - /* global QUnit */ - - QUnit.module( 'Helpers', () => { - - QUnit.module.todo( 'BoxHelper', ( hooks ) => { - - var geometries = undefined; - hooks.beforeEach( function () { - - const parameters = { - radius: 10, - widthSegments: 20, - heightSegments: 30, - phiStart: 0.5, - phiLength: 1.0, - thetaStart: 0.4, - thetaLength: 2.0, - }; - - // Test with a normal cube and a box helper - var boxGeometry = new BoxGeometry( parameters.diameter ); - var box = new Mesh( boxGeometry ); - var boxHelper = new BoxHelper( box ); - - // The same should happen with a comparable sphere - var sphereGeometry = new SphereGeometry( parameters.diameter / 2 ); - var sphere = new Mesh( sphereGeometry ); - var sphereBoxHelper = new BoxHelper( sphere ); - - // Note that unlike what I'd like to, these doesn't check the equivalency of the two generated geometries - geometries = [ boxHelper.geometry, sphereBoxHelper.geometry ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "update", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setFromObject", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard geometry tests', ( assert ) => { - - runStdGeometryTests( assert, geometries ); - - } ); - - } ); - - } ); - - /** - * @author alteredq / http://alteredqualia.com/ - * @author Mugen87 / https://github.com/Mugen87 - * - * - shows frustum, line of sight and up of the camera - * - suitable for fast updates - * - based on frustum visualization in lightgl.js shadowmap example - * http://evanw.github.com/lightgl.js/tests/shadowmap.html - */ - - function CameraHelper( camera ) { - - var geometry = new BufferGeometry(); - var material = new LineBasicMaterial( { color: 0xffffff, vertexColors: FaceColors } ); - - var vertices = []; - var colors = []; - - var pointMap = {}; - - // colors - - var colorFrustum = new Color( 0xffaa00 ); - var colorCone = new Color( 0xff0000 ); - var colorUp = new Color( 0x00aaff ); - var colorTarget = new Color( 0xffffff ); - var colorCross = new Color( 0x333333 ); - - // near - - addLine( 'n1', 'n2', colorFrustum ); - addLine( 'n2', 'n4', colorFrustum ); - addLine( 'n4', 'n3', colorFrustum ); - addLine( 'n3', 'n1', colorFrustum ); - - // far - - addLine( 'f1', 'f2', colorFrustum ); - addLine( 'f2', 'f4', colorFrustum ); - addLine( 'f4', 'f3', colorFrustum ); - addLine( 'f3', 'f1', colorFrustum ); - - // sides - - addLine( 'n1', 'f1', colorFrustum ); - addLine( 'n2', 'f2', colorFrustum ); - addLine( 'n3', 'f3', colorFrustum ); - addLine( 'n4', 'f4', colorFrustum ); - - // cone - - addLine( 'p', 'n1', colorCone ); - addLine( 'p', 'n2', colorCone ); - addLine( 'p', 'n3', colorCone ); - addLine( 'p', 'n4', colorCone ); - - // up - - addLine( 'u1', 'u2', colorUp ); - addLine( 'u2', 'u3', colorUp ); - addLine( 'u3', 'u1', colorUp ); - - // target - - addLine( 'c', 't', colorTarget ); - addLine( 'p', 'c', colorCross ); - - // cross - - addLine( 'cn1', 'cn2', colorCross ); - addLine( 'cn3', 'cn4', colorCross ); - - addLine( 'cf1', 'cf2', colorCross ); - addLine( 'cf3', 'cf4', colorCross ); - - function addLine( a, b, color ) { - - addPoint( a, color ); - addPoint( b, color ); - - } - - function addPoint( id, color ) { - - vertices.push( 0, 0, 0 ); - colors.push( color.r, color.g, color.b ); - - if ( pointMap[ id ] === undefined ) { - - pointMap[ id ] = []; - - } - - pointMap[ id ].push( ( vertices.length / 3 ) - 1 ); - - } - - geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); - - LineSegments.call( this, geometry, material ); - - this.camera = camera; - if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix(); - - this.matrix = camera.matrixWorld; - this.matrixAutoUpdate = false; - - this.pointMap = pointMap; - - this.update(); - - } - - CameraHelper.prototype = Object.create( LineSegments.prototype ); - CameraHelper.prototype.constructor = CameraHelper; - - CameraHelper.prototype.update = function () { - - var geometry, pointMap; - - var vector = new Vector3(); - var camera = new Camera(); - - function setPoint( point, x, y, z ) { - - vector.set( x, y, z ).unproject( camera ); - - var points = pointMap[ point ]; - - if ( points !== undefined ) { - - var position = geometry.getAttribute( 'position' ); - - for ( var i = 0, l = points.length; i < l; i ++ ) { - - position.setXYZ( points[ i ], vector.x, vector.y, vector.z ); - - } - - } - - } - - return function update() { - - geometry = this.geometry; - pointMap = this.pointMap; - - var w = 1, h = 1; - - // we need just camera projection matrix - // world matrix must be identity - - camera.projectionMatrix.copy( this.camera.projectionMatrix ); - - // center / target - - setPoint( 'c', 0, 0, - 1 ); - setPoint( 't', 0, 0, 1 ); - - // near - - setPoint( 'n1', - w, - h, - 1 ); - setPoint( 'n2', w, - h, - 1 ); - setPoint( 'n3', - w, h, - 1 ); - setPoint( 'n4', w, h, - 1 ); - - // far - - setPoint( 'f1', - w, - h, 1 ); - setPoint( 'f2', w, - h, 1 ); - setPoint( 'f3', - w, h, 1 ); - setPoint( 'f4', w, h, 1 ); - - // up - - setPoint( 'u1', w * 0.7, h * 1.1, - 1 ); - setPoint( 'u2', - w * 0.7, h * 1.1, - 1 ); - setPoint( 'u3', 0, h * 2, - 1 ); - - // cross - - setPoint( 'cf1', - w, 0, 1 ); - setPoint( 'cf2', w, 0, 1 ); - setPoint( 'cf3', 0, - h, 1 ); - setPoint( 'cf4', 0, h, 1 ); - - setPoint( 'cn1', - w, 0, - 1 ); - setPoint( 'cn2', w, 0, - 1 ); - setPoint( 'cn3', 0, - h, - 1 ); - setPoint( 'cn4', 0, h, - 1 ); - - geometry.getAttribute( 'position' ).needsUpdate = true; - - }; - - }(); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Helpers', () => { - - QUnit.module.todo( 'CameraHelper', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "update", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - - } ); - - } ); - - /** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - * @author WestLangley / http://github.com/WestLangley - */ - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Helpers', () => { - - QUnit.module.todo( 'DirectionalLightHelper', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "dispose", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "update", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - * @author WestLangley / http://github.com/WestLangley - */ - - function FaceNormalsHelper( object, size, hex, linewidth ) { - - // FaceNormalsHelper only supports THREE.Geometry - - this.object = object; - - this.size = ( size !== undefined ) ? size : 1; - - var color = ( hex !== undefined ) ? hex : 0xffff00; - - var width = ( linewidth !== undefined ) ? linewidth : 1; - - // - - var nNormals = 0; - - var objGeometry = this.object.geometry; - - if ( objGeometry && objGeometry.isGeometry ) { - - nNormals = objGeometry.faces.length; - - } else { - - console.warn( 'THREE.FaceNormalsHelper: only THREE.Geometry is supported. Use THREE.VertexNormalsHelper, instead.' ); - - } - - // - - var geometry = new BufferGeometry(); - - var positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 ); - - geometry.addAttribute( 'position', positions ); - - LineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) ); - - // - - this.matrixAutoUpdate = false; - this.update(); - - } - - FaceNormalsHelper.prototype = Object.create( LineSegments.prototype ); - FaceNormalsHelper.prototype.constructor = FaceNormalsHelper; - - FaceNormalsHelper.prototype.update = ( function () { - - var v1 = new Vector3(); - var v2 = new Vector3(); - var normalMatrix = new Matrix3(); - - return function update() { - - this.object.updateMatrixWorld( true ); - - normalMatrix.getNormalMatrix( this.object.matrixWorld ); - - var matrixWorld = this.object.matrixWorld; - - var position = this.geometry.attributes.position; - - // - - var objGeometry = this.object.geometry; - - var vertices = objGeometry.vertices; - - var faces = objGeometry.faces; - - var idx = 0; - - for ( var i = 0, l = faces.length; i < l; i ++ ) { - - var face = faces[ i ]; - - var normal = face.normal; - - v1.copy( vertices[ face.a ] ) - .add( vertices[ face.b ] ) - .add( vertices[ face.c ] ) - .divideScalar( 3 ) - .applyMatrix4( matrixWorld ); - - v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 ); - - position.setXYZ( idx, v1.x, v1.y, v1.z ); - - idx = idx + 1; - - position.setXYZ( idx, v2.x, v2.y, v2.z ); - - idx = idx + 1; - - } - - position.needsUpdate = true; - - }; - - }() ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Helpers', () => { - - QUnit.module.todo( 'FaceNormalsHelper', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "update", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Helpers', () => { - - QUnit.module.todo( 'GridHelper', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / https://github.com/Mugen87 - */ - - function HemisphereLightHelper( light, size, color ) { - - Object3D.call( this ); - - this.light = light; - this.light.updateMatrixWorld(); - - this.matrix = light.matrixWorld; - this.matrixAutoUpdate = false; - - this.color = color; - - var geometry = new OctahedronBufferGeometry( size ); - geometry.rotateY( Math.PI * 0.5 ); - - this.material = new MeshBasicMaterial( { wireframe: true, fog: false } ); - if ( this.color === undefined ) this.material.vertexColors = VertexColors; - - var position = geometry.getAttribute( 'position' ); - var colors = new Float32Array( position.count * 3 ); - - geometry.addAttribute( 'color', new BufferAttribute( colors, 3 ) ); - - this.add( new Mesh( geometry, this.material ) ); - - this.update(); - - } - - HemisphereLightHelper.prototype = Object.create( Object3D.prototype ); - HemisphereLightHelper.prototype.constructor = HemisphereLightHelper; - - HemisphereLightHelper.prototype.dispose = function () { - - this.children[ 0 ].geometry.dispose(); - this.children[ 0 ].material.dispose(); - - }; - - HemisphereLightHelper.prototype.update = function () { - - var vector = new Vector3(); - - var color1 = new Color(); - var color2 = new Color(); - - return function update() { - - var mesh = this.children[ 0 ]; - - if ( this.color !== undefined ) { - - this.material.color.set( this.color ); - - } else { - - var colors = mesh.geometry.getAttribute( 'color' ); - - color1.copy( this.light.color ); - color2.copy( this.light.groundColor ); - - for ( var i = 0, l = colors.count; i < l; i ++ ) { - - var color = ( i < ( l / 2 ) ) ? color1 : color2; - - colors.setXYZ( i, color.r, color.g, color.b ); - - } - - colors.needsUpdate = true; - - } - - mesh.lookAt( vector.setFromMatrixPosition( this.light.matrixWorld ).negate() ); - - }; - - }(); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Helpers', () => { - - QUnit.module.todo( 'HemisphereLightHelper', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "dispose", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "update", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author WestLangley / http://github.com/WestLangley - */ - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Helpers', () => { - - QUnit.module.todo( 'PlaneHelper', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "updateMatrixWorld", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - - } ); - - } ); - - /** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - */ - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Helpers', () => { - - QUnit.module.todo( 'PointLightHelper', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "dispose", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "update", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - * @author Mugen87 / http://github.com/Mugen87 - * @author Hectate / http://www.github.com/Hectate - */ - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Helpers', () => { - - QUnit.module.todo( 'PolarGridHelper', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author abelnation / http://github.com/abelnation - * @author Mugen87 / http://github.com/Mugen87 - * @author WestLangley / http://github.com/WestLangley - */ - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Helpers', () => { - - QUnit.module.todo( 'RectAreaLightHelper', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "dispose", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "update", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author Sean Griffin / http://twitter.com/sgrif - * @author Michael Guerrero / http://realitymeltdown.com - * @author mrdoob / http://mrdoob.com/ - * @author ikerr / http://verold.com - * @author Mugen87 / https://github.com/Mugen87 - */ - - function getBoneList( object ) { - - var boneList = []; - - if ( object && object.isBone ) { - - boneList.push( object ); - - } - - for ( var i = 0; i < object.children.length; i ++ ) { - - boneList.push.apply( boneList, getBoneList( object.children[ i ] ) ); - - } - - return boneList; - - } - - function SkeletonHelper( object ) { - - var bones = getBoneList( object ); - - var geometry = new BufferGeometry(); - - var vertices = []; - var colors = []; - - var color1 = new Color( 0, 0, 1 ); - var color2 = new Color( 0, 1, 0 ); - - for ( var i = 0; i < bones.length; i ++ ) { - - var bone = bones[ i ]; - - if ( bone.parent && bone.parent.isBone ) { - - vertices.push( 0, 0, 0 ); - vertices.push( 0, 0, 0 ); - colors.push( color1.r, color1.g, color1.b ); - colors.push( color2.r, color2.g, color2.b ); - - } - - } - - geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); - - var material = new LineBasicMaterial( { vertexColors: VertexColors, depthTest: false, depthWrite: false, transparent: true } ); - - LineSegments.call( this, geometry, material ); - - this.root = object; - this.bones = bones; - - this.matrix = object.matrixWorld; - this.matrixAutoUpdate = false; - - } - - SkeletonHelper.prototype = Object.create( LineSegments.prototype ); - SkeletonHelper.prototype.constructor = SkeletonHelper; - - SkeletonHelper.prototype.updateMatrixWorld = function () { - - var vector = new Vector3(); - - var boneMatrix = new Matrix4(); - var matrixWorldInv = new Matrix4(); - - return function updateMatrixWorld( force ) { - - var bones = this.bones; - - var geometry = this.geometry; - var position = geometry.getAttribute( 'position' ); - - matrixWorldInv.getInverse( this.root.matrixWorld ); - - for ( var i = 0, j = 0; i < bones.length; i ++ ) { - - var bone = bones[ i ]; - - if ( bone.parent && bone.parent.isBone ) { - - boneMatrix.multiplyMatrices( matrixWorldInv, bone.matrixWorld ); - vector.setFromMatrixPosition( boneMatrix ); - position.setXYZ( j, vector.x, vector.y, vector.z ); - - boneMatrix.multiplyMatrices( matrixWorldInv, bone.parent.matrixWorld ); - vector.setFromMatrixPosition( boneMatrix ); - position.setXYZ( j + 1, vector.x, vector.y, vector.z ); - - j += 2; - - } - - } - - geometry.getAttribute( 'position' ).needsUpdate = true; - - Object3D.prototype.updateMatrixWorld.call( this, force ); - - }; - - }(); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Helpers', () => { - - QUnit.module.todo( 'SkeletonHelper', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "updateMatrixWorld", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - - } ); - - } ); - - /** - * @author alteredq / http://alteredqualia.com/ - * @author mrdoob / http://mrdoob.com/ - * @author WestLangley / http://github.com/WestLangley - */ - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Helpers', () => { - - QUnit.module.todo( 'SpotLightHelper', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "dispose", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "update", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - * @author WestLangley / http://github.com/WestLangley - */ - - function VertexNormalsHelper( object, size, hex, linewidth ) { - - this.object = object; - - this.size = ( size !== undefined ) ? size : 1; - - var color = ( hex !== undefined ) ? hex : 0xff0000; - - var width = ( linewidth !== undefined ) ? linewidth : 1; - - // - - var nNormals = 0; - - var objGeometry = this.object.geometry; - - if ( objGeometry && objGeometry.isGeometry ) { - - nNormals = objGeometry.faces.length * 3; - - } else if ( objGeometry && objGeometry.isBufferGeometry ) { - - nNormals = objGeometry.attributes.normal.count; - - } - - // - - var geometry = new BufferGeometry(); - - var positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 ); - - geometry.addAttribute( 'position', positions ); - - LineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) ); - - // - - this.matrixAutoUpdate = false; - - this.update(); - - } - - VertexNormalsHelper.prototype = Object.create( LineSegments.prototype ); - VertexNormalsHelper.prototype.constructor = VertexNormalsHelper; - - VertexNormalsHelper.prototype.update = ( function () { - - var v1 = new Vector3(); - var v2 = new Vector3(); - var normalMatrix = new Matrix3(); - - return function update() { - - var keys = [ 'a', 'b', 'c' ]; - - this.object.updateMatrixWorld( true ); - - normalMatrix.getNormalMatrix( this.object.matrixWorld ); - - var matrixWorld = this.object.matrixWorld; - - var position = this.geometry.attributes.position; - - // - - var objGeometry = this.object.geometry; - - if ( objGeometry && objGeometry.isGeometry ) { - - var vertices = objGeometry.vertices; - - var faces = objGeometry.faces; - - var idx = 0; - - for ( var i = 0, l = faces.length; i < l; i ++ ) { - - var face = faces[ i ]; - - for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) { - - var vertex = vertices[ face[ keys[ j ] ] ]; - - var normal = face.vertexNormals[ j ]; - - v1.copy( vertex ).applyMatrix4( matrixWorld ); - - v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 ); - - position.setXYZ( idx, v1.x, v1.y, v1.z ); - - idx = idx + 1; - - position.setXYZ( idx, v2.x, v2.y, v2.z ); - - idx = idx + 1; - - } - - } - - } else if ( objGeometry && objGeometry.isBufferGeometry ) { - - var objPos = objGeometry.attributes.position; - - var objNorm = objGeometry.attributes.normal; - - var idx = 0; - - // for simplicity, ignore index and drawcalls, and render every normal - - for ( var j = 0, jl = objPos.count; j < jl; j ++ ) { - - v1.set( objPos.getX( j ), objPos.getY( j ), objPos.getZ( j ) ).applyMatrix4( matrixWorld ); - - v2.set( objNorm.getX( j ), objNorm.getY( j ), objNorm.getZ( j ) ); - - v2.applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 ); - - position.setXYZ( idx, v1.x, v1.y, v1.z ); - - idx = idx + 1; - - position.setXYZ( idx, v2.x, v2.y, v2.z ); - - idx = idx + 1; - - } - - } - - position.needsUpdate = true; - - }; - - }() ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Helpers', () => { - - QUnit.module.todo( 'VertexNormalsHelper', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "update", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - function Light( color, intensity ) { - - Object3D.call( this ); - - this.type = 'Light'; - - this.color = new Color( color ); - this.intensity = intensity !== undefined ? intensity : 1; - - this.receiveShadow = undefined; - - } - - Light.prototype = Object.assign( Object.create( Object3D.prototype ), { - - constructor: Light, - - isLight: true, - - copy: function ( source ) { - - Object3D.prototype.copy.call( this, source ); - - this.color.copy( source.color ); - this.intensity = source.intensity; - - return this; - - }, - - toJSON: function ( meta ) { - - var data = Object3D.prototype.toJSON.call( this, meta ); - - data.object.color = this.color.getHex(); - data.object.intensity = this.intensity; - - if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex(); - - if ( this.distance !== undefined ) data.object.distance = this.distance; - if ( this.angle !== undefined ) data.object.angle = this.angle; - if ( this.decay !== undefined ) data.object.decay = this.decay; - if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra; - - if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON(); - - return data; - - } - - } ); - - function AmbientLight( color, intensity ) { - - Light.call( this, color, intensity ); - - this.type = 'AmbientLight'; - - this.castShadow = undefined; - - } - - AmbientLight.prototype = Object.assign( Object.create( Light.prototype ), { - - constructor: AmbientLight, - - isAmbientLight: true - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author moraxy / https://github.com/moraxy - */ - /* global QUnit */ - - QUnit.module( 'Lights', () => { - - QUnit.module.todo( 'ArrowHelper', ( hooks ) => { - - var lights = undefined; - hooks.beforeEach( function () { - - const parameters = { - color: 0xaaaaaa, - intensity: 0.5 - }; - - lights = [ - new AmbientLight(), - new AmbientLight( parameters.color ), - new AmbientLight( parameters.color, parameters.intensity ) - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isAmbiantLight", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard light tests', ( assert ) => { - - runStdLightTests( assert, lights ); - - } ); - - } ); - - } ); - - function LightShadow( camera ) { - - this.camera = camera; - - this.bias = 0; - this.radius = 1; - - this.mapSize = new Vector2( 512, 512 ); - - this.map = null; - this.matrix = new Matrix4(); - - } - - Object.assign( LightShadow.prototype, { - - copy: function ( source ) { - - this.camera = source.camera.clone(); - - this.bias = source.bias; - this.radius = source.radius; - - this.mapSize.copy( source.mapSize ); - - return this; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - toJSON: function () { - - var object = {}; - - if ( this.bias !== 0 ) object.bias = this.bias; - if ( this.radius !== 1 ) object.radius = this.radius; - if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray(); - - object.camera = this.camera.toJSON( false ).object; - delete object.camera.matrix; - - return object; - - } - - } ); - - function DirectionalLightShadow( ) { - - LightShadow.call( this, new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) ); - - } - - DirectionalLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), { - - constructor: DirectionalLightShadow - - } ); - - function DirectionalLight$1( color, intensity ) { - - Light.call( this, color, intensity ); - - this.type = 'DirectionalLight'; - - this.position.copy( Object3D.DefaultUp ); - this.updateMatrix(); - - this.target = new Object3D(); - - this.shadow = new DirectionalLightShadow(); - - } - - DirectionalLight$1.prototype = Object.assign( Object.create( Light.prototype ), { - - constructor: DirectionalLight$1, - - isDirectionalLight: true, - - copy: function ( source ) { - - Light.prototype.copy.call( this, source ); - - this.target = source.target.clone(); - - this.shadow = source.shadow.clone(); - - return this; - - } - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author moraxy / https://github.com/moraxy - */ - /* global QUnit */ - - QUnit.module( 'Lights', () => { - - QUnit.module.todo( 'DirectionalLight', ( hooks ) => { - - var lights = undefined; - hooks.beforeEach( function () { - - const parameters = { - color: 0xaaaaaa, - intensity: 0.8 - }; - - lights = [ - new DirectionalLight$1(), - new DirectionalLight$1( parameters.color ), - new DirectionalLight$1( parameters.color, parameters.intensity ) - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isDirectionalLight", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard light tests', ( assert ) => { - - runStdLightTests( assert, lights ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author moraxy / https://github.com/moraxy - */ - /* global QUnit */ - - QUnit.module( 'Lights', () => { - - QUnit.module.todo( 'DirectionalLightShadow', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( "clone/copy", ( assert ) => { - - var a = new DirectionalLightShadow(); - var b = new DirectionalLightShadow(); - var c; - - assert.notDeepEqual( a, b, "Newly instanced shadows are not equal" ); - - c = a.clone(); - assert.smartEqual( a, c, "Shadows are identical after clone()" ); - - c.mapSize.set( 1024, 1024 ); - assert.notDeepEqual( a, c, "Shadows are different again after change" ); - - b.copy( a ); - assert.smartEqual( a, b, "Shadows are identical after copy()" ); - - b.mapSize.set( 512, 512 ); - assert.notDeepEqual( a, b, "Shadows are different again after change" ); - - } ); - - QUnit.test( "toJSON", ( assert ) => { - - var light = new DirectionalLight(); - var shadow = new DirectionalLightShadow(); - - shadow.bias = 10; - shadow.radius = 5; - shadow.mapSize.set( 1024, 1024 ); - light.shadow = shadow; - - var json = light.toJSON(); - var newLight = new ObjectLoader().parse( json ); - - assert.smartEqual( newLight.shadow, light.shadow, "Reloaded shadow is identical to the original one" ); - - } ); - - } ); - - } ); - - function HemisphereLight( skyColor, groundColor, intensity ) { - - Light.call( this, skyColor, intensity ); - - this.type = 'HemisphereLight'; - - this.castShadow = undefined; - - this.position.copy( Object3D.DefaultUp ); - this.updateMatrix(); - - this.groundColor = new Color( groundColor ); - - } - - HemisphereLight.prototype = Object.assign( Object.create( Light.prototype ), { - - constructor: HemisphereLight, - - isHemisphereLight: true, - - copy: function ( source ) { - - Light.prototype.copy.call( this, source ); - - this.groundColor.copy( source.groundColor ); - - return this; - - } - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author moraxy / https://github.com/moraxy - */ - /* global QUnit */ - - QUnit.module( 'Lights', () => { - - QUnit.module.todo( 'HemisphereLight', ( hooks ) => { - - var lights = undefined; - hooks.beforeEach( function () { - - const parameters = { - skyColor: 0x123456, - groundColor: 0xabc012, - intensity: 0.6 - }; - - lights = [ - new HemisphereLight(), - new HemisphereLight( parameters.skyColor ), - new HemisphereLight( parameters.skyColor, parameters.groundColor ), - new HemisphereLight( parameters.skyColor, parameters.groundColor, parameters.intensity ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isHemisphereLight", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard light tests', ( assert ) => { - - runStdLightTests( assert, lights ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Lights', () => { - - QUnit.module.todo( 'Light', ( hooks ) => { - - var lights = undefined; - hooks.beforeEach( function () { - - const parameters = { - color: 0xaaaaaa, - intensity: 0.5 - }; - - lights = [ - new Light(), - new Light( parameters.color ), - new Light( parameters.color, parameters.intensity ) - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isLight", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "toJSON", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard light tests', ( assert ) => { - - runStdLightTests( assert, lights ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author moraxy / https://github.com/moraxy - */ - /* global QUnit */ - - QUnit.module( 'Lights', () => { - - QUnit.module.todo( 'LightShadow', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "clone/copy", ( assert ) => { - - var a = new LightShadow( new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) ); - var b = new LightShadow( new OrthographicCamera( - 3, 3, 3, - 3, 0.3, 300 ) ); - var c; - - assert.notDeepEqual( a, b, "Newly instanced shadows are not equal" ); - - c = a.clone(); - assert.smartEqual( a, c, "Shadows are identical after clone()" ); - - c.mapSize.set( 256, 256 ); - assert.notDeepEqual( a, c, "Shadows are different again after change" ); - - b.copy( a ); - assert.smartEqual( a, b, "Shadows are identical after copy()" ); - - b.mapSize.set( 512, 512 ); - assert.notDeepEqual( a, b, "Shadows are different again after change" ); - - } ); - - QUnit.test( "toJSON", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - function PointLight( color, intensity, distance, decay ) { - - Light.call( this, color, intensity ); - - this.type = 'PointLight'; - - Object.defineProperty( this, 'power', { - get: function () { - - // intensity = power per solid angle. - // ref: equation (15) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf - return this.intensity * 4 * Math.PI; - - }, - set: function ( power ) { - - // intensity = power per solid angle. - // ref: equation (15) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf - this.intensity = power / ( 4 * Math.PI ); - - } - } ); - - this.distance = ( distance !== undefined ) ? distance : 0; - this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2. - - this.shadow = new LightShadow( new PerspectiveCamera( 90, 1, 0.5, 500 ) ); - - } - - PointLight.prototype = Object.assign( Object.create( Light.prototype ), { - - constructor: PointLight, - - isPointLight: true, - - copy: function ( source ) { - - Light.prototype.copy.call( this, source ); - - this.distance = source.distance; - this.decay = source.decay; - - this.shadow = source.shadow.clone(); - - return this; - - } - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author moraxy / https://github.com/moraxy - */ - /* global QUnit */ - - QUnit.module( 'Lights', () => { - - QUnit.module.todo( 'PointLight', ( hooks ) => { - - var lights = undefined; - hooks.beforeEach( function () { - - const parameters = { - color: 0xaaaaaa, - intensity: 0.5, - distance: 100, - decay: 2 - }; - - lights = [ - new PointLight(), - new PointLight( parameters.color ), - new PointLight( parameters.color, parameters.intensity ), - new PointLight( parameters.color, parameters.intensity, parameters.distance ), - new PointLight( parameters.color, parameters.intensity, parameters.distance, parameters.decay ) - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PROPERTIES - QUnit.test( "power", ( assert ) => { - - var a = new PointLight( 0xaaaaaa ); - - a.intensity = 100; - assert.numEqual( a.power, 100 * Math.PI * 4, "Correct power for an intensity of 100" ); - - a.intensity = 40; - assert.numEqual( a.power, 40 * Math.PI * 4, "Correct power for an intensity of 40" ); - - a.power = 100; - assert.numEqual( a.intensity, 100 / ( 4 * Math.PI ), "Correct intensity for a power of 100" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isPointLight", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard light tests', ( assert ) => { - - runStdLightTests( assert, lights ); - - } ); - - - } ); - - } ); - - function RectAreaLight( color, intensity, width, height ) { - - Light.call( this, color, intensity ); - - this.type = 'RectAreaLight'; - - this.position.set( 0, 1, 0 ); - this.updateMatrix(); - - this.width = ( width !== undefined ) ? width : 10; - this.height = ( height !== undefined ) ? height : 10; - - // TODO (abelnation): distance/decay - - // TODO (abelnation): update method for RectAreaLight to update transform to lookat target - - // TODO (abelnation): shadows - - } - - // TODO (abelnation): RectAreaLight update when light shape is changed - RectAreaLight.prototype = Object.assign( Object.create( Light.prototype ), { - - constructor: RectAreaLight, - - isRectAreaLight: true, - - copy: function ( source ) { - - Light.prototype.copy.call( this, source ); - - this.width = source.width; - this.height = source.height; - - return this; - - }, - - toJSON: function ( meta ) { - - var data = Light.prototype.toJSON.call( this, meta ); - - data.object.width = this.width; - data.object.height = this.height; - - return data; - - } - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author moraxy / https://github.com/moraxy - */ - /* global QUnit */ - - QUnit.module( 'Lights', () => { - - QUnit.module.todo( 'RectAreaLight', ( hooks ) => { - - var lights = undefined; - hooks.beforeEach( function () { - - const parameters = { - color: 0xaaaaaa, - intensity: 0.5, - width: 100, - height: 50 - }; - - lights = [ - new RectAreaLight( parameters.color ), - new RectAreaLight( parameters.color, parameters.intensity ), - new RectAreaLight( parameters.color, parameters.intensity, parameters.width ), - new RectAreaLight( parameters.color, parameters.intensity, parameters.width, parameters.height ) - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isRectAreaLight", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "toJSON", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard light tests', ( assert ) => { - - runStdLightTests( assert, lights ); - - } ); - - } ); - - } ); - - function SpotLightShadow() { - - LightShadow.call( this, new PerspectiveCamera( 50, 1, 0.5, 500 ) ); - - } - - SpotLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), { - - constructor: SpotLightShadow, - - isSpotLightShadow: true, - - update: function ( light ) { - - var camera = this.camera; - - var fov = _Math.RAD2DEG * 2 * light.angle; - var aspect = this.mapSize.width / this.mapSize.height; - var far = light.distance || camera.far; - - if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) { - - camera.fov = fov; - camera.aspect = aspect; - camera.far = far; - camera.updateProjectionMatrix(); - - } - - } - - } ); - - function SpotLight( color, intensity, distance, angle, penumbra, decay ) { - - Light.call( this, color, intensity ); - - this.type = 'SpotLight'; - - this.position.copy( Object3D.DefaultUp ); - this.updateMatrix(); - - this.target = new Object3D(); - - Object.defineProperty( this, 'power', { - get: function () { - - // intensity = power per solid angle. - // ref: equation (17) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf - return this.intensity * Math.PI; - - }, - set: function ( power ) { - - // intensity = power per solid angle. - // ref: equation (17) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf - this.intensity = power / Math.PI; - - } - } ); - - this.distance = ( distance !== undefined ) ? distance : 0; - this.angle = ( angle !== undefined ) ? angle : Math.PI / 3; - this.penumbra = ( penumbra !== undefined ) ? penumbra : 0; - this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2. - - this.shadow = new SpotLightShadow(); - - } - - SpotLight.prototype = Object.assign( Object.create( Light.prototype ), { - - constructor: SpotLight, - - isSpotLight: true, - - copy: function ( source ) { - - Light.prototype.copy.call( this, source ); - - this.distance = source.distance; - this.angle = source.angle; - this.penumbra = source.penumbra; - this.decay = source.decay; - - this.target = source.target.clone(); - - this.shadow = source.shadow.clone(); - - return this; - - } - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author moraxy / https://github.com/moraxy - */ - /* global QUnit */ - - QUnit.module( 'Lights', () => { - - QUnit.module.todo( 'SpotLight', ( hooks ) => { - - var lights = undefined; - hooks.beforeEach( function () { - - const parameters = { - color: 0xaaaaaa, - intensity: 0.5, - distance: 100, - angle: 0.8, - penumbra: 8, - decay: 2 - }; - - lights = [ - new SpotLight( parameters.color ), - new SpotLight( parameters.color, parameters.intensity ), - new SpotLight( parameters.color, parameters.intensity, parameters.distance ), - new SpotLight( parameters.color, parameters.intensity, parameters.distance, parameters.angle ), - new SpotLight( parameters.color, parameters.intensity, parameters.distance, parameters.angle, parameters.penumbra ), - new SpotLight( parameters.color, parameters.intensity, parameters.distance, parameters.angle, parameters.penumbra, parameters.decay ), - ]; - - } ); - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PROPERTIES - QUnit.test( "power", ( assert ) => { - - var a = new SpotLight( 0xaaaaaa ); - - a.intensity = 100; - assert.numEqual( a.power, 100 * Math.PI, "Correct power for an intensity of 100" ); - - a.intensity = 40; - assert.numEqual( a.power, 40 * Math.PI, "Correct power for an intensity of 40" ); - - a.power = 100; - assert.numEqual( a.intensity, 100 / Math.PI, "Correct intensity for a power of 100" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isSpotLight", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( 'Standard light tests', ( assert ) => { - - runStdLightTests( assert, lights ); - - } ); - - - - } ); - - } ); - - function Sprite( material ) { - - Object3D.call( this ); - - this.type = 'Sprite'; - - this.material = ( material !== undefined ) ? material : new SpriteMaterial(); - - } - - Sprite.prototype = Object.assign( Object.create( Object3D.prototype ), { - - constructor: Sprite, - - isSprite: true, - - raycast: ( function () { - - var intersectPoint = new Vector3(); - var worldPosition = new Vector3(); - var worldScale = new Vector3(); - - return function raycast( raycaster, intersects ) { - - worldPosition.setFromMatrixPosition( this.matrixWorld ); - raycaster.ray.closestPointToPoint( worldPosition, intersectPoint ); - - worldScale.setFromMatrixScale( this.matrixWorld ); - var guessSizeSq = worldScale.x * worldScale.y / 4; - - if ( worldPosition.distanceToSquared( intersectPoint ) > guessSizeSq ) return; - - var distance = raycaster.ray.origin.distanceTo( intersectPoint ); - - if ( distance < raycaster.near || distance > raycaster.far ) return; - - intersects.push( { - - distance: distance, - point: intersectPoint.clone(), - face: null, - object: this - - } ); - - }; - - }() ), - - clone: function () { - - return new this.constructor( this.material ).copy( this ); - - } - - } ); - - function Points( geometry, material ) { - - Object3D.call( this ); - - this.type = 'Points'; - - this.geometry = geometry !== undefined ? geometry : new BufferGeometry(); - this.material = material !== undefined ? material : new PointsMaterial( { color: Math.random() * 0xffffff } ); - - } - - Points.prototype = Object.assign( Object.create( Object3D.prototype ), { - - constructor: Points, - - isPoints: true, - - raycast: ( function () { - - var inverseMatrix = new Matrix4(); - var ray = new Ray(); - var sphere = new Sphere(); - - return function raycast( raycaster, intersects ) { - - var object = this; - var geometry = this.geometry; - var matrixWorld = this.matrixWorld; - var threshold = raycaster.params.Points.threshold; - - // Checking boundingSphere distance to ray - - if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); - - sphere.copy( geometry.boundingSphere ); - sphere.applyMatrix4( matrixWorld ); - sphere.radius += threshold; - - if ( raycaster.ray.intersectsSphere( sphere ) === false ) return; - - // - - inverseMatrix.getInverse( matrixWorld ); - ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix ); - - var localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 ); - var localThresholdSq = localThreshold * localThreshold; - var position = new Vector3(); - - function testPoint( point, index ) { - - var rayPointDistanceSq = ray.distanceSqToPoint( point ); - - if ( rayPointDistanceSq < localThresholdSq ) { - - var intersectPoint = ray.closestPointToPoint( point ); - intersectPoint.applyMatrix4( matrixWorld ); - - var distance = raycaster.ray.origin.distanceTo( intersectPoint ); - - if ( distance < raycaster.near || distance > raycaster.far ) return; - - intersects.push( { - - distance: distance, - distanceToRay: Math.sqrt( rayPointDistanceSq ), - point: intersectPoint.clone(), - index: index, - face: null, - object: object - - } ); - - } - - } - - if ( geometry.isBufferGeometry ) { - - var index = geometry.index; - var attributes = geometry.attributes; - var positions = attributes.position.array; - - if ( index !== null ) { - - var indices = index.array; - - for ( var i = 0, il = indices.length; i < il; i ++ ) { - - var a = indices[ i ]; - - position.fromArray( positions, a * 3 ); - - testPoint( position, a ); - - } - - } else { - - for ( var i = 0, l = positions.length / 3; i < l; i ++ ) { - - position.fromArray( positions, i * 3 ); - - testPoint( position, i ); - - } - - } - - } else { - - var vertices = geometry.vertices; - - for ( var i = 0, l = vertices.length; i < l; i ++ ) { - - testPoint( vertices[ i ], i ); - - } - - } - - }; - - }() ), - - clone: function () { - - return new this.constructor( this.geometry, this.material ).copy( this ); - - } - - } ); - - function LineLoop( geometry, material ) { - - Line.call( this, geometry, material ); - - this.type = 'LineLoop'; - - } - - LineLoop.prototype = Object.assign( Object.create( Line.prototype ), { - - constructor: LineLoop, - - isLineLoop: true, - - } ); - - function LOD() { - - Object3D.call( this ); - - this.type = 'LOD'; - - Object.defineProperties( this, { - levels: { - enumerable: true, - value: [] - } - } ); - - } - - LOD.prototype = Object.assign( Object.create( Object3D.prototype ), { - - constructor: LOD, - - copy: function ( source ) { - - Object3D.prototype.copy.call( this, source, false ); - - var levels = source.levels; - - for ( var i = 0, l = levels.length; i < l; i ++ ) { - - var level = levels[ i ]; - - this.addLevel( level.object.clone(), level.distance ); - - } - - return this; - - }, - - addLevel: function ( object, distance ) { - - if ( distance === undefined ) distance = 0; - - distance = Math.abs( distance ); - - var levels = this.levels; - - for ( var l = 0; l < levels.length; l ++ ) { - - if ( distance < levels[ l ].distance ) { - - break; - - } - - } - - levels.splice( l, 0, { distance: distance, object: object } ); - - this.add( object ); - - }, - - getObjectForDistance: function ( distance ) { - - var levels = this.levels; - - for ( var i = 1, l = levels.length; i < l; i ++ ) { - - if ( distance < levels[ i ].distance ) { - - break; - - } - - } - - return levels[ i - 1 ].object; - - }, - - raycast: ( function () { - - var matrixPosition = new Vector3(); - - return function raycast( raycaster, intersects ) { - - matrixPosition.setFromMatrixPosition( this.matrixWorld ); - - var distance = raycaster.ray.origin.distanceTo( matrixPosition ); - - this.getObjectForDistance( distance ).raycast( raycaster, intersects ); - - }; - - }() ), - - update: function () { - - var v1 = new Vector3(); - var v2 = new Vector3(); - - return function update( camera ) { - - var levels = this.levels; - - if ( levels.length > 1 ) { - - v1.setFromMatrixPosition( camera.matrixWorld ); - v2.setFromMatrixPosition( this.matrixWorld ); - - var distance = v1.distanceTo( v2 ); - - levels[ 0 ].object.visible = true; - - for ( var i = 1, l = levels.length; i < l; i ++ ) { - - if ( distance >= levels[ i ].distance ) { - - levels[ i - 1 ].object.visible = false; - levels[ i ].object.visible = true; - - } else { - - break; - - } - - } - - for ( ; i < l; i ++ ) { - - levels[ i ].object.visible = false; - - } - - } - - }; - - }(), - - toJSON: function ( meta ) { - - var data = Object3D.prototype.toJSON.call( this, meta ); - - data.object.levels = []; - - var levels = this.levels; - - for ( var i = 0, l = levels.length; i < l; i ++ ) { - - var level = levels[ i ]; - - data.object.levels.push( { - object: level.object.uuid, - distance: level.distance - } ); - - } - - return data; - - } - - } ); - - function Skeleton( bones, boneInverses ) { - - // copy the bone array - - bones = bones || []; - - this.bones = bones.slice( 0 ); - this.boneMatrices = new Float32Array( this.bones.length * 16 ); - - // use the supplied bone inverses or calculate the inverses - - if ( boneInverses === undefined ) { - - this.calculateInverses(); - - } else { - - if ( this.bones.length === boneInverses.length ) { - - this.boneInverses = boneInverses.slice( 0 ); - - } else { - - console.warn( 'THREE.Skeleton boneInverses is the wrong length.' ); - - this.boneInverses = []; - - for ( var i = 0, il = this.bones.length; i < il; i ++ ) { - - this.boneInverses.push( new Matrix4() ); - - } - - } - - } - - } - - Object.assign( Skeleton.prototype, { - - calculateInverses: function () { - - this.boneInverses = []; - - for ( var i = 0, il = this.bones.length; i < il; i ++ ) { - - var inverse = new Matrix4(); - - if ( this.bones[ i ] ) { - - inverse.getInverse( this.bones[ i ].matrixWorld ); - - } - - this.boneInverses.push( inverse ); - - } - - }, - - pose: function () { - - var bone, i, il; - - // recover the bind-time world matrices - - for ( i = 0, il = this.bones.length; i < il; i ++ ) { - - bone = this.bones[ i ]; - - if ( bone ) { - - bone.matrixWorld.getInverse( this.boneInverses[ i ] ); - - } - - } - - // compute the local matrices, positions, rotations and scales - - for ( i = 0, il = this.bones.length; i < il; i ++ ) { - - bone = this.bones[ i ]; - - if ( bone ) { - - if ( bone.parent && bone.parent.isBone ) { - - bone.matrix.getInverse( bone.parent.matrixWorld ); - bone.matrix.multiply( bone.matrixWorld ); - - } else { - - bone.matrix.copy( bone.matrixWorld ); - - } - - bone.matrix.decompose( bone.position, bone.quaternion, bone.scale ); - - } - - } - - }, - - update: ( function () { - - var offsetMatrix = new Matrix4(); - var identityMatrix = new Matrix4(); - - return function update() { - - var bones = this.bones; - var boneInverses = this.boneInverses; - var boneMatrices = this.boneMatrices; - var boneTexture = this.boneTexture; - - // flatten bone matrices to array - - for ( var i = 0, il = bones.length; i < il; i ++ ) { - - // compute the offset between the current and the original transform - - var matrix = bones[ i ] ? bones[ i ].matrixWorld : identityMatrix; - - offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] ); - offsetMatrix.toArray( boneMatrices, i * 16 ); - - } - - if ( boneTexture !== undefined ) { - - boneTexture.needsUpdate = true; - - } - - }; - - } )(), - - clone: function () { - - return new Skeleton( this.bones, this.boneInverses ); - - } - - } ); - - function Bone() { - - Object3D.call( this ); - - this.type = 'Bone'; - - } - - Bone.prototype = Object.assign( Object.create( Object3D.prototype ), { - - constructor: Bone, - - isBone: true - - } ); - - function SkinnedMesh( geometry, material ) { - - Mesh.call( this, geometry, material ); - - this.type = 'SkinnedMesh'; - - this.bindMode = 'attached'; - this.bindMatrix = new Matrix4(); - this.bindMatrixInverse = new Matrix4(); - - var bones = this.initBones(); - var skeleton = new Skeleton( bones ); - - this.bind( skeleton, this.matrixWorld ); - - this.normalizeSkinWeights(); - - } - - SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { - - constructor: SkinnedMesh, - - isSkinnedMesh: true, - - initBones: function () { - - var bones = [], bone, gbone; - var i, il; - - if ( this.geometry && this.geometry.bones !== undefined ) { - - // first, create array of 'Bone' objects from geometry data - - for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) { - - gbone = this.geometry.bones[ i ]; - - // create new 'Bone' object - - bone = new Bone(); - bones.push( bone ); - - // apply values - - bone.name = gbone.name; - bone.position.fromArray( gbone.pos ); - bone.quaternion.fromArray( gbone.rotq ); - if ( gbone.scl !== undefined ) bone.scale.fromArray( gbone.scl ); - - } - - // second, create bone hierarchy - - for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) { - - gbone = this.geometry.bones[ i ]; - - if ( ( gbone.parent !== - 1 ) && ( gbone.parent !== null ) && ( bones[ gbone.parent ] !== undefined ) ) { - - // subsequent bones in the hierarchy - - bones[ gbone.parent ].add( bones[ i ] ); - - } else { - - // topmost bone, immediate child of the skinned mesh - - this.add( bones[ i ] ); - - } - - } - - } - - // now the bones are part of the scene graph and children of the skinned mesh. - // let's update the corresponding matrices - - this.updateMatrixWorld( true ); - - return bones; - - }, - - bind: function ( skeleton, bindMatrix ) { - - this.skeleton = skeleton; - - if ( bindMatrix === undefined ) { - - this.updateMatrixWorld( true ); - - this.skeleton.calculateInverses(); - - bindMatrix = this.matrixWorld; - - } - - this.bindMatrix.copy( bindMatrix ); - this.bindMatrixInverse.getInverse( bindMatrix ); - - }, - - pose: function () { - - this.skeleton.pose(); - - }, - - normalizeSkinWeights: function () { - - var scale, i; - - if ( this.geometry && this.geometry.isGeometry ) { - - for ( i = 0; i < this.geometry.skinWeights.length; i ++ ) { - - var sw = this.geometry.skinWeights[ i ]; - - scale = 1.0 / sw.manhattanLength(); - - if ( scale !== Infinity ) { - - sw.multiplyScalar( scale ); - - } else { - - sw.set( 1, 0, 0, 0 ); // do something reasonable - - } - - } - - } else if ( this.geometry && this.geometry.isBufferGeometry ) { - - var vec = new Vector4(); - - var skinWeight = this.geometry.attributes.skinWeight; - - for ( i = 0; i < skinWeight.count; i ++ ) { - - vec.x = skinWeight.getX( i ); - vec.y = skinWeight.getY( i ); - vec.z = skinWeight.getZ( i ); - vec.w = skinWeight.getW( i ); - - scale = 1.0 / vec.manhattanLength(); - - if ( scale !== Infinity ) { - - vec.multiplyScalar( scale ); - - } else { - - vec.set( 1, 0, 0, 0 ); // do something reasonable - - } - - skinWeight.setXYZW( i, vec.x, vec.y, vec.z, vec.w ); - - } - - } - - }, - - updateMatrixWorld: function ( force ) { - - Mesh.prototype.updateMatrixWorld.call( this, force ); - - if ( this.bindMode === 'attached' ) { - - this.bindMatrixInverse.getInverse( this.matrixWorld ); - - } else if ( this.bindMode === 'detached' ) { - - this.bindMatrixInverse.getInverse( this.bindMatrix ); - - } else { - - console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode ); - - } - - }, - - clone: function () { - - return new this.constructor( this.geometry, this.material ).copy( this ); - - } - - } ); - - function Fog( color, near, far ) { - - this.name = ''; - - this.color = new Color( color ); - - this.near = ( near !== undefined ) ? near : 1; - this.far = ( far !== undefined ) ? far : 1000; - - } - - Fog.prototype.isFog = true; - - Fog.prototype.clone = function () { - - return new Fog( this.color.getHex(), this.near, this.far ); - - }; - - Fog.prototype.toJSON = function ( /* meta */ ) { - - return { - type: 'Fog', - color: this.color.getHex(), - near: this.near, - far: this.far - }; - - }; - - function FogExp2( color, density ) { - - this.name = ''; - - this.color = new Color( color ); - this.density = ( density !== undefined ) ? density : 0.00025; - - } - - FogExp2.prototype.isFogExp2 = true; - - FogExp2.prototype.clone = function () { - - return new FogExp2( this.color.getHex(), this.density ); - - }; - - FogExp2.prototype.toJSON = function ( /* meta */ ) { - - return { - type: 'FogExp2', - color: this.color.getHex(), - density: this.density - }; - - }; - - function BufferGeometryLoader( manager ) { - - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - - } - - Object.assign( BufferGeometryLoader.prototype, { - - load: function ( url, onLoad, onProgress, onError ) { - - var scope = this; - - var loader = new FileLoader( scope.manager ); - loader.load( url, function ( text ) { - - onLoad( scope.parse( JSON.parse( text ) ) ); - - }, onProgress, onError ); - - }, - - parse: function ( json ) { - - var geometry = new BufferGeometry(); - - var index = json.data.index; - - if ( index !== undefined ) { - - var typedArray = new TYPED_ARRAYS[ index.type ]( index.array ); - geometry.setIndex( new BufferAttribute( typedArray, 1 ) ); - - } - - var attributes = json.data.attributes; - - for ( var key in attributes ) { - - var attribute = attributes[ key ]; - var typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array ); - - geometry.addAttribute( key, new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized ) ); - - } - - var groups = json.data.groups || json.data.drawcalls || json.data.offsets; - - if ( groups !== undefined ) { - - for ( var i = 0, n = groups.length; i !== n; ++ i ) { - - var group = groups[ i ]; - - geometry.addGroup( group.start, group.count, group.materialIndex ); - - } - - } - - var boundingSphere = json.data.boundingSphere; - - if ( boundingSphere !== undefined ) { - - var center = new Vector3(); - - if ( boundingSphere.center !== undefined ) { - - center.fromArray( boundingSphere.center ); - - } - - geometry.boundingSphere = new Sphere( center, boundingSphere.radius ); - - } - - return geometry; - - } - - } ); - - var TYPED_ARRAYS = { - Int8Array: Int8Array, - Uint8Array: Uint8Array, - // Workaround for IE11 pre KB2929437. See #11440 - Uint8ClampedArray: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : Uint8Array, - Int16Array: Int16Array, - Uint16Array: Uint16Array, - Int32Array: Int32Array, - Uint32Array: Uint32Array, - Float32Array: Float32Array, - Float64Array: Float64Array - }; - - - - var Geometries = Object.freeze({ - WireframeGeometry: WireframeGeometry, - ParametricGeometry: ParametricGeometry, - ParametricBufferGeometry: ParametricBufferGeometry, - TetrahedronGeometry: TetrahedronGeometry, - TetrahedronBufferGeometry: TetrahedronBufferGeometry, - OctahedronGeometry: OctahedronGeometry, - OctahedronBufferGeometry: OctahedronBufferGeometry, - IcosahedronGeometry: IcosahedronGeometry, - IcosahedronBufferGeometry: IcosahedronBufferGeometry, - DodecahedronGeometry: DodecahedronGeometry, - DodecahedronBufferGeometry: DodecahedronBufferGeometry, - PolyhedronGeometry: PolyhedronGeometry, - PolyhedronBufferGeometry: PolyhedronBufferGeometry, - TubeGeometry: TubeGeometry, - TubeBufferGeometry: TubeBufferGeometry, - TorusKnotGeometry: TorusKnotGeometry, - TorusKnotBufferGeometry: TorusKnotBufferGeometry, - TorusGeometry: TorusGeometry, - TorusBufferGeometry: TorusBufferGeometry, - TextGeometry: TextGeometry, - TextBufferGeometry: TextBufferGeometry, - SphereGeometry: SphereGeometry, - SphereBufferGeometry: SphereBufferGeometry, - RingGeometry: RingGeometry, - RingBufferGeometry: RingBufferGeometry, - PlaneGeometry: PlaneGeometry, - PlaneBufferGeometry: PlaneBufferGeometry, - LatheGeometry: LatheGeometry, - LatheBufferGeometry: LatheBufferGeometry, - ShapeGeometry: ShapeGeometry, - ShapeBufferGeometry: ShapeBufferGeometry, - ExtrudeGeometry: ExtrudeGeometry, - ExtrudeBufferGeometry: ExtrudeBufferGeometry, - EdgesGeometry: EdgesGeometry, - ConeGeometry: ConeGeometry, - ConeBufferGeometry: ConeBufferGeometry, - CylinderGeometry: CylinderGeometry, - CylinderBufferGeometry: CylinderBufferGeometry, - CircleGeometry: CircleGeometry, - CircleBufferGeometry: CircleBufferGeometry, - BoxGeometry: BoxGeometry, - BoxBufferGeometry: BoxBufferGeometry - }); - - function ObjectLoader$1( manager ) { - - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - this.texturePath = ''; - - } - - Object.assign( ObjectLoader$1.prototype, { - - load: function ( url, onLoad, onProgress, onError ) { - - if ( this.texturePath === '' ) { - - this.texturePath = url.substring( 0, url.lastIndexOf( '/' ) + 1 ); - - } - - var scope = this; - - var loader = new FileLoader( scope.manager ); - loader.load( url, function ( text ) { - - var json = null; - - try { - - json = JSON.parse( text ); - - } catch ( error ) { - - if ( onError !== undefined ) onError( error ); - - console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message ); - - return; - - } - - var metadata = json.metadata; - - if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) { - - console.error( 'THREE.ObjectLoader: Can\'t load ' + url + '. Use THREE.JSONLoader instead.' ); - return; - - } - - scope.parse( json, onLoad ); - - }, onProgress, onError ); - - }, - - setTexturePath: function ( value ) { - - this.texturePath = value; - - }, - - setCrossOrigin: function ( value ) { - - this.crossOrigin = value; - - }, - - parse: function ( json, onLoad ) { - - var geometries = this.parseGeometries( json.geometries ); - - var images = this.parseImages( json.images, function () { - - if ( onLoad !== undefined ) onLoad( object ); - - } ); - - var textures = this.parseTextures( json.textures, images ); - var materials = this.parseMaterials( json.materials, textures ); - - var object = this.parseObject( json.object, geometries, materials ); - - if ( json.animations ) { - - object.animations = this.parseAnimations( json.animations ); - - } - - if ( json.images === undefined || json.images.length === 0 ) { - - if ( onLoad !== undefined ) onLoad( object ); - - } - - return object; - - }, - - parseGeometries: function ( json ) { - - var geometries = {}; - - if ( json !== undefined ) { - - var geometryLoader = new JSONLoader(); - var bufferGeometryLoader = new BufferGeometryLoader(); - - for ( var i = 0, l = json.length; i < l; i ++ ) { - - var geometry; - var data = json[ i ]; - - switch ( data.type ) { - - case 'PlaneGeometry': - case 'PlaneBufferGeometry': - - geometry = new Geometries[ data.type ]( - data.width, - data.height, - data.widthSegments, - data.heightSegments - ); - - break; - - case 'BoxGeometry': - case 'BoxBufferGeometry': - case 'CubeGeometry': // backwards compatible - - geometry = new Geometries[ data.type ]( - data.width, - data.height, - data.depth, - data.widthSegments, - data.heightSegments, - data.depthSegments - ); - - break; - - case 'CircleGeometry': - case 'CircleBufferGeometry': - - geometry = new Geometries[ data.type ]( - data.radius, - data.segments, - data.thetaStart, - data.thetaLength - ); - - break; - - case 'CylinderGeometry': - case 'CylinderBufferGeometry': - - geometry = new Geometries[ data.type ]( - data.radiusTop, - data.radiusBottom, - data.height, - data.radialSegments, - data.heightSegments, - data.openEnded, - data.thetaStart, - data.thetaLength - ); - - break; - - case 'ConeGeometry': - case 'ConeBufferGeometry': - - geometry = new Geometries[ data.type ]( - data.radius, - data.height, - data.radialSegments, - data.heightSegments, - data.openEnded, - data.thetaStart, - data.thetaLength - ); - - break; - - case 'SphereGeometry': - case 'SphereBufferGeometry': - - geometry = new Geometries[ data.type ]( - data.radius, - data.widthSegments, - data.heightSegments, - data.phiStart, - data.phiLength, - data.thetaStart, - data.thetaLength - ); - - break; - - case 'DodecahedronGeometry': - case 'DodecahedronBufferGeometry': - case 'IcosahedronGeometry': - case 'IcosahedronBufferGeometry': - case 'OctahedronGeometry': - case 'OctahedronBufferGeometry': - case 'TetrahedronGeometry': - case 'TetrahedronBufferGeometry': - - geometry = new Geometries[ data.type ]( - data.radius, - data.detail - ); - - break; - - case 'RingGeometry': - case 'RingBufferGeometry': - - geometry = new Geometries[ data.type ]( - data.innerRadius, - data.outerRadius, - data.thetaSegments, - data.phiSegments, - data.thetaStart, - data.thetaLength - ); - - break; - - case 'TorusGeometry': - case 'TorusBufferGeometry': - - geometry = new Geometries[ data.type ]( - data.radius, - data.tube, - data.radialSegments, - data.tubularSegments, - data.arc - ); - - break; - - case 'TorusKnotGeometry': - case 'TorusKnotBufferGeometry': - - geometry = new Geometries[ data.type ]( - data.radius, - data.tube, - data.tubularSegments, - data.radialSegments, - data.p, - data.q - ); - - break; - - case 'LatheGeometry': - case 'LatheBufferGeometry': - - geometry = new Geometries[ data.type ]( - data.points, - data.segments, - data.phiStart, - data.phiLength - ); - - break; - - case 'PolyhedronGeometry': - case 'PolyhedronBufferGeometry': - - geometry = new Geometries[ data.type ]( - data.vertices, - data.indices, - data.radius, - data.details - ); - - break; - - case 'BufferGeometry': - - geometry = bufferGeometryLoader.parse( data ); - - break; - - case 'Geometry': - - geometry = geometryLoader.parse( data, this.texturePath ).geometry; - - break; - - default: - - console.warn( 'THREE.ObjectLoader: Unsupported geometry type "' + data.type + '"' ); - - continue; - - } - - geometry.uuid = data.uuid; - - if ( data.name !== undefined ) geometry.name = data.name; - - geometries[ data.uuid ] = geometry; - - } - - } - - return geometries; - - }, - - parseMaterials: function ( json, textures ) { - - var materials = {}; - - if ( json !== undefined ) { - - var loader = new MaterialLoader(); - loader.setTextures( textures ); - - for ( var i = 0, l = json.length; i < l; i ++ ) { - - var data = json[ i ]; - - if ( data.type === 'MultiMaterial' ) { - - // Deprecated - - var array = []; - - for ( var j = 0; j < data.materials.length; j ++ ) { - - array.push( loader.parse( data.materials[ j ] ) ); - - } - - materials[ data.uuid ] = array; - - } else { - - materials[ data.uuid ] = loader.parse( data ); - - } - - } - - } - - return materials; - - }, - - parseAnimations: function ( json ) { - - var animations = []; - - for ( var i = 0; i < json.length; i ++ ) { - - var clip = AnimationClip.parse( json[ i ] ); - - animations.push( clip ); - - } - - return animations; - - }, - - parseImages: function ( json, onLoad ) { - - var scope = this; - var images = {}; - - function loadImage( url ) { - - scope.manager.itemStart( url ); - - return loader.load( url, function () { - - scope.manager.itemEnd( url ); - - }, undefined, function () { - - scope.manager.itemEnd( url ); - scope.manager.itemError( url ); - - } ); - - } - - if ( json !== undefined && json.length > 0 ) { - - var manager = new LoadingManager( onLoad ); - - var loader = new ImageLoader( manager ); - loader.setCrossOrigin( this.crossOrigin ); - - for ( var i = 0, l = json.length; i < l; i ++ ) { - - var image = json[ i ]; - var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.texturePath + image.url; - - images[ image.uuid ] = loadImage( path ); - - } - - } - - return images; - - }, - - parseTextures: function ( json, images ) { - - function parseConstant( value, type ) { - - if ( typeof value === 'number' ) return value; - - console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value ); - - return type[ value ]; - - } - - var textures = {}; - - if ( json !== undefined ) { - - for ( var i = 0, l = json.length; i < l; i ++ ) { - - var data = json[ i ]; - - if ( data.image === undefined ) { - - console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid ); - - } - - if ( images[ data.image ] === undefined ) { - - console.warn( 'THREE.ObjectLoader: Undefined image', data.image ); - - } - - var texture = new Texture( images[ data.image ] ); - texture.needsUpdate = true; - - texture.uuid = data.uuid; - - if ( data.name !== undefined ) texture.name = data.name; - - if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING ); - - if ( data.offset !== undefined ) texture.offset.fromArray( data.offset ); - if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat ); - if ( data.center !== undefined ) texture.center.fromArray( data.center ); - if ( data.rotation !== undefined ) texture.rotation = data.rotation; - - if ( data.wrap !== undefined ) { - - texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING ); - texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING ); - - } - - if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER ); - if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER ); - if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy; - - if ( data.flipY !== undefined ) texture.flipY = data.flipY; - - textures[ data.uuid ] = texture; - - } - - } - - return textures; - - }, - - parseObject: function () { - - var matrix = new Matrix4(); - - return function parseObject( data, geometries, materials ) { - - var object; - - function getGeometry( name ) { - - if ( geometries[ name ] === undefined ) { - - console.warn( 'THREE.ObjectLoader: Undefined geometry', name ); - - } - - return geometries[ name ]; - - } - - function getMaterial( name ) { - - if ( name === undefined ) return undefined; - - if ( Array.isArray( name ) ) { - - var array = []; - - for ( var i = 0, l = name.length; i < l; i ++ ) { - - var uuid = name[ i ]; - - if ( materials[ uuid ] === undefined ) { - - console.warn( 'THREE.ObjectLoader: Undefined material', uuid ); - - } - - array.push( materials[ uuid ] ); - - } - - return array; - - } - - if ( materials[ name ] === undefined ) { - - console.warn( 'THREE.ObjectLoader: Undefined material', name ); - - } - - return materials[ name ]; - - } - - switch ( data.type ) { - - case 'Scene': - - object = new Scene(); - - if ( data.background !== undefined ) { - - if ( Number.isInteger( data.background ) ) { - - object.background = new Color( data.background ); - - } - - } - - if ( data.fog !== undefined ) { - - if ( data.fog.type === 'Fog' ) { - - object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far ); - - } else if ( data.fog.type === 'FogExp2' ) { - - object.fog = new FogExp2( data.fog.color, data.fog.density ); - - } - - } - - break; - - case 'PerspectiveCamera': - - object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far ); - - if ( data.focus !== undefined ) object.focus = data.focus; - if ( data.zoom !== undefined ) object.zoom = data.zoom; - if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge; - if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset; - if ( data.view !== undefined ) object.view = Object.assign( {}, data.view ); - - break; - - case 'OrthographicCamera': - - object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far ); - - break; - - case 'AmbientLight': - - object = new AmbientLight( data.color, data.intensity ); - - break; - - case 'DirectionalLight': - - object = new DirectionalLight$1( data.color, data.intensity ); - - break; - - case 'PointLight': - - object = new PointLight( data.color, data.intensity, data.distance, data.decay ); - - break; - - case 'RectAreaLight': - - object = new RectAreaLight( data.color, data.intensity, data.width, data.height ); - - break; - - case 'SpotLight': - - object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay ); - - break; - - case 'HemisphereLight': - - object = new HemisphereLight( data.color, data.groundColor, data.intensity ); - - break; - - case 'SkinnedMesh': - - console.warn( 'THREE.ObjectLoader.parseObject() does not support SkinnedMesh yet.' ); - - case 'Mesh': - - var geometry = getGeometry( data.geometry ); - var material = getMaterial( data.material ); - - if ( geometry.bones && geometry.bones.length > 0 ) { - - object = new SkinnedMesh( geometry, material ); - - } else { - - object = new Mesh( geometry, material ); - - } - - break; - - case 'LOD': - - object = new LOD(); - - break; - - case 'Line': - - object = new Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode ); - - break; - - case 'LineLoop': - - object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) ); - - break; - - case 'LineSegments': - - object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) ); - - break; - - case 'PointCloud': - case 'Points': - - object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) ); - - break; - - case 'Sprite': - - object = new Sprite( getMaterial( data.material ) ); - - break; - - case 'Group': - - object = new Group(); - - break; - - default: - - object = new Object3D(); - - } - - object.uuid = data.uuid; - - if ( data.name !== undefined ) object.name = data.name; - if ( data.matrix !== undefined ) { - - matrix.fromArray( data.matrix ); - matrix.decompose( object.position, object.quaternion, object.scale ); - - } else { - - if ( data.position !== undefined ) object.position.fromArray( data.position ); - if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation ); - if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion ); - if ( data.scale !== undefined ) object.scale.fromArray( data.scale ); - - } - - if ( data.castShadow !== undefined ) object.castShadow = data.castShadow; - if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow; - - if ( data.shadow ) { - - if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias; - if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius; - if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize ); - if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera ); - - } - - if ( data.visible !== undefined ) object.visible = data.visible; - if ( data.userData !== undefined ) object.userData = data.userData; - - if ( data.children !== undefined ) { - - var children = data.children; - - for ( var i = 0; i < children.length; i ++ ) { - - object.add( this.parseObject( children[ i ], geometries, materials ) ); - - } - - } - - if ( data.type === 'LOD' ) { - - var levels = data.levels; - - for ( var l = 0; l < levels.length; l ++ ) { - - var level = levels[ l ]; - var child = object.getObjectByProperty( 'uuid', level.object ); - - if ( child !== undefined ) { - - object.addLevel( child, level.distance ); - - } - - } - - } - - return object; - - }; - - }() - - } ); - - var TEXTURE_MAPPING = { - UVMapping: UVMapping, - CubeReflectionMapping: CubeReflectionMapping, - CubeRefractionMapping: CubeRefractionMapping, - EquirectangularReflectionMapping: EquirectangularReflectionMapping, - EquirectangularRefractionMapping: EquirectangularRefractionMapping, - SphericalReflectionMapping: SphericalReflectionMapping, - CubeUVReflectionMapping: CubeUVReflectionMapping, - CubeUVRefractionMapping: CubeUVRefractionMapping - }; - - var TEXTURE_WRAPPING = { - RepeatWrapping: RepeatWrapping, - ClampToEdgeWrapping: ClampToEdgeWrapping, - MirroredRepeatWrapping: MirroredRepeatWrapping - }; - - var TEXTURE_FILTER = { - NearestFilter: NearestFilter, - NearestMipMapNearestFilter: NearestMipMapNearestFilter, - NearestMipMapLinearFilter: NearestMipMapLinearFilter, - LinearFilter: LinearFilter, - LinearMipMapNearestFilter: LinearMipMapNearestFilter, - LinearMipMapLinearFilter: LinearMipMapLinearFilter - }; - - /** - * @author TristanVALCKE / https://github.com/Itee - * @author moraxy / https://github.com/moraxy - */ - /* global QUnit */ - - QUnit.module( 'Lights', () => { - - QUnit.module.todo( 'SpotLightShadow', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isSpotLightShadow", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "update", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( "clone/copy", ( assert ) => { - - var a = new SpotLightShadow(); - var b = new SpotLightShadow(); - var c; - - assert.notDeepEqual( a, b, "Newly instanced shadows are not equal" ); - - c = a.clone(); - assert.smartEqual( a, c, "Shadows are identical after clone()" ); - - c.mapSize.set( 256, 256 ); - assert.notDeepEqual( a, c, "Shadows are different again after change" ); - - b.copy( a ); - assert.smartEqual( a, b, "Shadows are identical after copy()" ); - - b.mapSize.set( 512, 512 ); - assert.notDeepEqual( a, b, "Shadows are different again after change" ); - - } ); - - QUnit.test( "toJSON", ( assert ) => { - - var light = new SpotLight(); - var shadow = new SpotLightShadow(); - - shadow.bias = 10; - shadow.radius = 5; - shadow.mapSize.set( 128, 128 ); - light.shadow = shadow; - - var json = light.toJSON(); - var newLight = new ObjectLoader$1().parse( json ); - - assert.smartEqual( newLight.shadow, light.shadow, "Reloaded shadow is equal to the original one" ); - - } ); - - } ); - - } ); - - function AnimationLoader( manager ) { - - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - - } - - Object.assign( AnimationLoader.prototype, { - - load: function ( url, onLoad, onProgress, onError ) { - - var scope = this; - - var loader = new FileLoader( scope.manager ); - loader.load( url, function ( text ) { - - onLoad( scope.parse( JSON.parse( text ) ) ); - - }, onProgress, onError ); - - }, - - parse: function ( json, onLoad ) { - - var animations = []; - - for ( var i = 0; i < json.length; i ++ ) { - - var clip = AnimationClip.parse( json[ i ] ); - - animations.push( clip ); - - } - - onLoad( animations ); - - } - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Loaders', () => { - - QUnit.module.todo( 'AnimationLoader', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "load", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "parse", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - function AudioLoader( manager ) { - - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - - } - - Object.assign( AudioLoader.prototype, { - - load: function ( url, onLoad, onProgress, onError ) { - - var loader = new FileLoader( this.manager ); - loader.setResponseType( 'arraybuffer' ); - loader.load( url, function ( buffer ) { - - var context = AudioContext.getContext(); - - context.decodeAudioData( buffer, function ( audioBuffer ) { - - onLoad( audioBuffer ); - - } ); - - }, onProgress, onError ); - - } - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Loaders', () => { - - QUnit.module.todo( 'AudioLoader', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "load", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Loaders', () => { - - QUnit.module.todo( 'BufferGeometryLoader', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "load", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "parse", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Loaders', () => { - - QUnit.module.todo( 'Cache', () => { - - // PUBLIC STUFF - QUnit.test( "add", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "get", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "remove", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clear", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author alteredq / http://alteredqualia.com/ - */ - - function CompressedTexture( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) { - - Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); - - this.image = { width: width, height: height }; - this.mipmaps = mipmaps; - - // no flipping for cube textures - // (also flipping doesn't work for compressed textures ) - - this.flipY = false; - - // can't generate mipmaps for compressed textures - // mips must be embedded in DDS files - - this.generateMipmaps = false; - - } - - CompressedTexture.prototype = Object.create( Texture.prototype ); - CompressedTexture.prototype.constructor = CompressedTexture; - - CompressedTexture.prototype.isCompressedTexture = true; - - function CompressedTextureLoader( manager ) { - - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - - // override in sub classes - this._parser = null; - - } - - Object.assign( CompressedTextureLoader.prototype, { - - load: function ( url, onLoad, onProgress, onError ) { - - var scope = this; - - var images = []; - - var texture = new CompressedTexture(); - texture.image = images; - - var loader = new FileLoader( this.manager ); - loader.setPath( this.path ); - loader.setResponseType( 'arraybuffer' ); - - function loadTexture( i ) { - - loader.load( url[ i ], function ( buffer ) { - - var texDatas = scope._parser( buffer, true ); - - images[ i ] = { - width: texDatas.width, - height: texDatas.height, - format: texDatas.format, - mipmaps: texDatas.mipmaps - }; - - loaded += 1; - - if ( loaded === 6 ) { - - if ( texDatas.mipmapCount === 1 ) - texture.minFilter = LinearFilter; - - texture.format = texDatas.format; - texture.needsUpdate = true; - - if ( onLoad ) onLoad( texture ); - - } - - }, onProgress, onError ); - - } - - if ( Array.isArray( url ) ) { - - var loaded = 0; - - for ( var i = 0, il = url.length; i < il; ++ i ) { - - loadTexture( i ); - - } - - } else { - - // compressed cubemap texture stored in a single DDS file - - loader.load( url, function ( buffer ) { - - var texDatas = scope._parser( buffer, true ); - - if ( texDatas.isCubemap ) { - - var faces = texDatas.mipmaps.length / texDatas.mipmapCount; - - for ( var f = 0; f < faces; f ++ ) { - - images[ f ] = { mipmaps: [] }; - - for ( var i = 0; i < texDatas.mipmapCount; i ++ ) { - - images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] ); - images[ f ].format = texDatas.format; - images[ f ].width = texDatas.width; - images[ f ].height = texDatas.height; - - } - - } - - } else { - - texture.image.width = texDatas.width; - texture.image.height = texDatas.height; - texture.mipmaps = texDatas.mipmaps; - - } - - if ( texDatas.mipmapCount === 1 ) { - - texture.minFilter = LinearFilter; - - } - - texture.format = texDatas.format; - texture.needsUpdate = true; - - if ( onLoad ) onLoad( texture ); - - }, onProgress, onError ); - - } - - return texture; - - }, - - setPath: function ( value ) { - - this.path = value; - return this; - - } - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Loaders', () => { - - QUnit.module.todo( 'CompressedTextureLoader', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "load", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setPath", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - function CubeTextureLoader( manager ) { - - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - - } - - Object.assign( CubeTextureLoader.prototype, { - - crossOrigin: 'Anonymous', - - load: function ( urls, onLoad, onProgress, onError ) { - - var texture = new CubeTexture(); - - var loader = new ImageLoader( this.manager ); - loader.setCrossOrigin( this.crossOrigin ); - loader.setPath( this.path ); - - var loaded = 0; - - function loadTexture( i ) { - - loader.load( urls[ i ], function ( image ) { - - texture.images[ i ] = image; - - loaded ++; - - if ( loaded === 6 ) { - - texture.needsUpdate = true; - - if ( onLoad ) onLoad( texture ); - - } - - }, undefined, onError ); - - } - - for ( var i = 0; i < urls.length; ++ i ) { - - loadTexture( i ); - - } - - return texture; - - }, - - setCrossOrigin: function ( value ) { - - this.crossOrigin = value; - return this; - - }, - - setPath: function ( value ) { - - this.path = value; - return this; - - } - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Loaders', () => { - - QUnit.module.todo( 'CubeTextureLoader', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "load", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setCrossOrigin", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setPath", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - function DataTextureLoader( manager ) { - - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - - // override in sub classes - this._parser = null; - - } - - Object.assign( DataTextureLoader.prototype, { - - load: function ( url, onLoad, onProgress, onError ) { - - var scope = this; - - var texture = new DataTexture(); - - var loader = new FileLoader( this.manager ); - loader.setResponseType( 'arraybuffer' ); - - loader.load( url, function ( buffer ) { - - var texData = scope._parser( buffer ); - - if ( ! texData ) return; - - if ( undefined !== texData.image ) { - - texture.image = texData.image; - - } else if ( undefined !== texData.data ) { - - texture.image.width = texData.width; - texture.image.height = texData.height; - texture.image.data = texData.data; - - } - - texture.wrapS = undefined !== texData.wrapS ? texData.wrapS : ClampToEdgeWrapping; - texture.wrapT = undefined !== texData.wrapT ? texData.wrapT : ClampToEdgeWrapping; - - texture.magFilter = undefined !== texData.magFilter ? texData.magFilter : LinearFilter; - texture.minFilter = undefined !== texData.minFilter ? texData.minFilter : LinearMipMapLinearFilter; - - texture.anisotropy = undefined !== texData.anisotropy ? texData.anisotropy : 1; - - if ( undefined !== texData.format ) { - - texture.format = texData.format; - - } - if ( undefined !== texData.type ) { - - texture.type = texData.type; - - } - - if ( undefined !== texData.mipmaps ) { - - texture.mipmaps = texData.mipmaps; - - } - - if ( 1 === texData.mipmapCount ) { - - texture.minFilter = LinearFilter; - - } - - texture.needsUpdate = true; - - if ( onLoad ) onLoad( texture, texData ); - - }, onProgress, onError ); - - - return texture; - - } - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Loaders', () => { - - QUnit.module.todo( 'DataTextureLoader', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "load", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Loaders', () => { - - QUnit.module.todo( 'FileLoader', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "load", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setPath", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setResponseType", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setWithCredentials", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setMimeType", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setRequestHeader", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - function FontLoader( manager ) { - - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; - - } - - Object.assign( FontLoader.prototype, { - - load: function ( url, onLoad, onProgress, onError ) { - - var scope = this; - - var loader = new FileLoader( this.manager ); - loader.setPath( this.path ); - loader.load( url, function ( text ) { - - var json; - - try { - - json = JSON.parse( text ); - - } catch ( e ) { - - console.warn( 'THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.' ); - json = JSON.parse( text.substring( 65, text.length - 2 ) ); - - } - - var font = scope.parse( json ); - - if ( onLoad ) onLoad( font ); - - }, onProgress, onError ); - - }, - - parse: function ( json ) { - - return new Font( json ); - - }, - - setPath: function ( value ) { - - this.path = value; - return this; - - } - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Loaders', () => { - - QUnit.module.todo( 'FontLoader', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "load", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "parse", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setPath", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Loaders', () => { - - QUnit.module.todo( 'ImageLoader', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "load", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setCrossOrigin", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setPath", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Loaders', () => { - - QUnit.module.todo( 'JSONLoader', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "load", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setTexturePath", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "parse", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Loaders', () => { - - QUnit.module.todo( 'Loader', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // STATIC STUFF - QUnit.test( "Handlers.add", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "Handlers.get", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "extractUrlBase", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "initMaterials", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "createMaterial", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Loaders', () => { - - QUnit.module.todo( 'LoadingManager', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "onStart", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "onLoad", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "onProgress", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "onError", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "itemStart", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "itemEnd", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "itemError", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Loaders', () => { - - QUnit.module.todo( 'MaterialLoader', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "load", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setTextures", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "parse", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Loaders', () => { - - QUnit.module.todo( 'ObjectLoader', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "load", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setTexturePath", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setCrossOrigin", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "parse", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "parseGeometries", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "parseMaterials", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "parseAnimations", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "parseImages", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "parseTextures", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "parseObject", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Loaders', () => { - - QUnit.module.todo( 'TextureLoader', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "load", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setCrossOrigin", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setPath", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Materials', () => { - - QUnit.module.todo( 'LineBasicMaterial', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isLineBasicMaterial", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Materials', () => { - - QUnit.module.todo( 'LineDashedMaterial', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isLineDashedMaterial", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Materials', () => { - - QUnit.module.todo( 'Material', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isMaterial", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "onBeforeCompile", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setValues", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "toJSON", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "dispose", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Materials', () => { - - QUnit.module.todo( 'MeshBasicMaterial', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isMeshBasicMaterial", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Materials', () => { - - QUnit.module.todo( 'MeshDepthMaterial', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isMeshDepthMaterial", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Materials', () => { - - QUnit.module.todo( 'MeshDistanceMaterial', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isMeshDistanceMaterial", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Materials', () => { - - QUnit.module.todo( 'MeshLambertMaterial', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isMeshLambertMaterial", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Materials', () => { - - QUnit.module.todo( 'MeshNormalMaterial', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isMeshNormalMaterial", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Materials', () => { - - QUnit.module.todo( 'MeshPhongMaterial', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isMeshPhongMaterial", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Materials', () => { - - QUnit.module.todo( 'MeshPhysicalMaterial', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isMeshPhysicalMaterial", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Materials', () => { - - QUnit.module.todo( 'MeshStandardMaterial', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isMeshStandardMaterial", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Materials', () => { - - QUnit.module.todo( 'MeshToonMaterial', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isMeshToonMaterial", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Materials', () => { - - QUnit.module.todo( 'PointsMaterial', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isPointsMaterial", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Materials', () => { - - QUnit.module.todo( 'RawShaderMaterial', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isRawShaderMaterial", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Materials', () => { - - QUnit.module.todo( 'ShaderMaterial', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isShaderwMaterial", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "toJSON", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Materials', () => { - - QUnit.module.todo( 'LineBasicMaterial', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isShadowMaterial", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Materials', () => { - - QUnit.module.todo( 'SpriteMaterial', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isSpriteMaterial", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author bhouston / http://exocortex.com - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Maths', () => { - - QUnit.module.todo( 'Box2', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - var a = new Box2(); - assert.ok( a.min.equals( posInf2 ), "Passed!" ); - assert.ok( a.max.equals( negInf2 ), "Passed!" ); - - var a = new Box2( zero2.clone(), zero2.clone() ); - assert.ok( a.min.equals( zero2 ), "Passed!" ); - assert.ok( a.max.equals( zero2 ), "Passed!" ); - - var a = new Box2( zero2.clone(), one2.clone() ); - assert.ok( a.min.equals( zero2 ), "Passed!" ); - assert.ok( a.max.equals( one2 ), "Passed!" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "set", ( assert ) => { - - var a = new Box2(); - - a.set( zero2, one2 ); - assert.ok( a.min.equals( zero2 ), "Passed!" ); - assert.ok( a.max.equals( one2 ), "Passed!" ); - - } ); - - QUnit.test( "setFromPoints", ( assert ) => { - - var a = new Box2(); - - a.setFromPoints( [ zero2, one2, two2 ] ); - assert.ok( a.min.equals( zero2 ), "Passed!" ); - assert.ok( a.max.equals( two2 ), "Passed!" ); - - a.setFromPoints( [ one2 ] ); - assert.ok( a.min.equals( one2 ), "Passed!" ); - assert.ok( a.max.equals( one2 ), "Passed!" ); - - a.setFromPoints( [] ); - assert.ok( a.isEmpty(), "Passed!" ); - - } ); - - QUnit.test( "setFromCenterAndSize", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - var a = new Box2( zero2.clone(), one2.clone() ); - var b = new Box2().copy( a ); - assert.ok( b.min.equals( zero2 ), "Passed!" ); - assert.ok( b.max.equals( one2 ), "Passed!" ); - - // ensure that it is a true copy - a.min = zero2; - a.max = one2; - assert.ok( b.min.equals( zero2 ), "Passed!" ); - assert.ok( b.max.equals( one2 ), "Passed!" ); - - } ); - - QUnit.test( "empty/makeEmpty", ( assert ) => { - - var a = new Box2(); - - assert.ok( a.isEmpty(), "Passed!" ); - - var a = new Box2( zero2.clone(), one2.clone() ); - assert.ok( ! a.isEmpty(), "Passed!" ); - - a.makeEmpty(); - assert.ok( a.isEmpty(), "Passed!" ); - - } ); - - QUnit.test( "isEmpty", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getCenter", ( assert ) => { - - var a = new Box2( zero2.clone(), zero2.clone() ); - - assert.ok( a.getCenter().equals( zero2 ), "Passed!" ); - - var a = new Box2( zero2, one2 ); - var midpoint = one2.clone().multiplyScalar( 0.5 ); - assert.ok( a.getCenter().equals( midpoint ), "Passed!" ); - - } ); - - QUnit.test( "getSize", ( assert ) => { - - var a = new Box2( zero2.clone(), zero2.clone() ); - - assert.ok( a.getSize().equals( zero2 ), "Passed!" ); - - var a = new Box2( zero2.clone(), one2.clone() ); - assert.ok( a.getSize().equals( one2 ), "Passed!" ); - - } ); - - QUnit.test( "expandByPoint", ( assert ) => { - - var a = new Box2( zero2.clone(), zero2.clone() ); - - a.expandByPoint( zero2 ); - assert.ok( a.getSize().equals( zero2 ), "Passed!" ); - - a.expandByPoint( one2 ); - assert.ok( a.getSize().equals( one2 ), "Passed!" ); - - a.expandByPoint( one2.clone().negate() ); - assert.ok( a.getSize().equals( one2.clone().multiplyScalar( 2 ) ), "Passed!" ); - assert.ok( a.getCenter().equals( zero2 ), "Passed!" ); - - } ); - - QUnit.test( "expandByVector", ( assert ) => { - - var a = new Box2( zero2.clone(), zero2.clone() ); - - a.expandByVector( zero2 ); - assert.ok( a.getSize().equals( zero2 ), "Passed!" ); - - a.expandByVector( one2 ); - assert.ok( a.getSize().equals( one2.clone().multiplyScalar( 2 ) ), "Passed!" ); - assert.ok( a.getCenter().equals( zero2 ), "Passed!" ); - - } ); - - QUnit.test( "expandByScalar", ( assert ) => { - - var a = new Box2( zero2.clone(), zero2.clone() ); - - a.expandByScalar( 0 ); - assert.ok( a.getSize().equals( zero2 ), "Passed!" ); - - a.expandByScalar( 1 ); - assert.ok( a.getSize().equals( one2.clone().multiplyScalar( 2 ) ), "Passed!" ); - assert.ok( a.getCenter().equals( zero2 ), "Passed!" ); - - } ); - - QUnit.test( "containsPoint", ( assert ) => { - - var a = new Box2( zero2.clone(), zero2.clone() ); - - assert.ok( a.containsPoint( zero2 ), "Passed!" ); - assert.ok( ! a.containsPoint( one2 ), "Passed!" ); - - a.expandByScalar( 1 ); - assert.ok( a.containsPoint( zero2 ), "Passed!" ); - assert.ok( a.containsPoint( one2 ), "Passed!" ); - assert.ok( a.containsPoint( one2.clone().negate() ), "Passed!" ); - - } ); - - QUnit.test( "containsBox", ( assert ) => { - - var a = new Box2( zero2.clone(), zero2.clone() ); - var b = new Box2( zero2.clone(), one2.clone() ); - var c = new Box2( one2.clone().negate(), one2.clone() ); - - assert.ok( a.containsBox( a ), "Passed!" ); - assert.ok( ! a.containsBox( b ), "Passed!" ); - assert.ok( ! a.containsBox( c ), "Passed!" ); - - assert.ok( b.containsBox( a ), "Passed!" ); - assert.ok( c.containsBox( a ), "Passed!" ); - assert.ok( ! b.containsBox( c ), "Passed!" ); - - } ); - - QUnit.test( "getParameter", ( assert ) => { - - var a = new Box2( zero2.clone(), one2.clone() ); - var b = new Box2( one2.clone().negate(), one2.clone() ); - - assert.ok( a.getParameter( new Vector2( 0, 0 ) ).equals( new Vector2( 0, 0 ) ), "Passed!" ); - assert.ok( a.getParameter( new Vector2( 1, 1 ) ).equals( new Vector2( 1, 1 ) ), "Passed!" ); - - assert.ok( b.getParameter( new Vector2( - 1, - 1 ) ).equals( new Vector2( 0, 0 ) ), "Passed!" ); - assert.ok( b.getParameter( new Vector2( 0, 0 ) ).equals( new Vector2( 0.5, 0.5 ) ), "Passed!" ); - assert.ok( b.getParameter( new Vector2( 1, 1 ) ).equals( new Vector2( 1, 1 ) ), "Passed!" ); - - } ); - - QUnit.test( "intersectsBox", ( assert ) => { - - var a = new Box2( zero2.clone(), zero2.clone() ); - var b = new Box2( zero2.clone(), one2.clone() ); - var c = new Box2( one2.clone().negate(), one2.clone() ); - - assert.ok( a.intersectsBox( a ), "Passed!" ); - assert.ok( a.intersectsBox( b ), "Passed!" ); - assert.ok( a.intersectsBox( c ), "Passed!" ); - - assert.ok( b.intersectsBox( a ), "Passed!" ); - assert.ok( c.intersectsBox( a ), "Passed!" ); - assert.ok( b.intersectsBox( c ), "Passed!" ); - - b.translate( new Vector2( 2, 2 ) ); - assert.ok( ! a.intersectsBox( b ), "Passed!" ); - assert.ok( ! b.intersectsBox( a ), "Passed!" ); - assert.ok( ! b.intersectsBox( c ), "Passed!" ); - - } ); - - QUnit.test( "clampPoint", ( assert ) => { - - var a = new Box2( zero2.clone(), zero2.clone() ); - var b = new Box2( one2.clone().negate(), one2.clone() ); - - assert.ok( a.clampPoint( new Vector2( 0, 0 ) ).equals( new Vector2( 0, 0 ) ), "Passed!" ); - assert.ok( a.clampPoint( new Vector2( 1, 1 ) ).equals( new Vector2( 0, 0 ) ), "Passed!" ); - assert.ok( a.clampPoint( new Vector2( - 1, - 1 ) ).equals( new Vector2( 0, 0 ) ), "Passed!" ); - - assert.ok( b.clampPoint( new Vector2( 2, 2 ) ).equals( new Vector2( 1, 1 ) ), "Passed!" ); - assert.ok( b.clampPoint( new Vector2( 1, 1 ) ).equals( new Vector2( 1, 1 ) ), "Passed!" ); - assert.ok( b.clampPoint( new Vector2( 0, 0 ) ).equals( new Vector2( 0, 0 ) ), "Passed!" ); - assert.ok( b.clampPoint( new Vector2( - 1, - 1 ) ).equals( new Vector2( - 1, - 1 ) ), "Passed!" ); - assert.ok( b.clampPoint( new Vector2( - 2, - 2 ) ).equals( new Vector2( - 1, - 1 ) ), "Passed!" ); - - } ); - - QUnit.test( "distanceToPoint", ( assert ) => { - - var a = new Box2( zero2.clone(), zero2.clone() ); - var b = new Box2( one2.clone().negate(), one2.clone() ); - - assert.ok( a.distanceToPoint( new Vector2( 0, 0 ) ) == 0, "Passed!" ); - assert.ok( a.distanceToPoint( new Vector2( 1, 1 ) ) == Math.sqrt( 2 ), "Passed!" ); - assert.ok( a.distanceToPoint( new Vector2( - 1, - 1 ) ) == Math.sqrt( 2 ), "Passed!" ); - - assert.ok( b.distanceToPoint( new Vector2( 2, 2 ) ) == Math.sqrt( 2 ), "Passed!" ); - assert.ok( b.distanceToPoint( new Vector2( 1, 1 ) ) == 0, "Passed!" ); - assert.ok( b.distanceToPoint( new Vector2( 0, 0 ) ) == 0, "Passed!" ); - assert.ok( b.distanceToPoint( new Vector2( - 1, - 1 ) ) == 0, "Passed!" ); - assert.ok( b.distanceToPoint( new Vector2( - 2, - 2 ) ) == Math.sqrt( 2 ), "Passed!" ); - - } ); - - QUnit.test( "intersect", ( assert ) => { - - var a = new Box2( zero2.clone(), zero2.clone() ); - var b = new Box2( zero2.clone(), one2.clone() ); - var c = new Box2( one2.clone().negate(), one2.clone() ); - - assert.ok( a.clone().intersect( a ).equals( a ), "Passed!" ); - assert.ok( a.clone().intersect( b ).equals( a ), "Passed!" ); - assert.ok( b.clone().intersect( b ).equals( b ), "Passed!" ); - assert.ok( a.clone().intersect( c ).equals( a ), "Passed!" ); - assert.ok( b.clone().intersect( c ).equals( b ), "Passed!" ); - assert.ok( c.clone().intersect( c ).equals( c ), "Passed!" ); - - } ); - - QUnit.test( "union", ( assert ) => { - - var a = new Box2( zero2.clone(), zero2.clone() ); - var b = new Box2( zero2.clone(), one2.clone() ); - var c = new Box2( one2.clone().negate(), one2.clone() ); - - assert.ok( a.clone().union( a ).equals( a ), "Passed!" ); - assert.ok( a.clone().union( b ).equals( b ), "Passed!" ); - assert.ok( a.clone().union( c ).equals( c ), "Passed!" ); - assert.ok( b.clone().union( c ).equals( c ), "Passed!" ); - - } ); - - QUnit.test( "translate", ( assert ) => { - - var a = new Box2( zero2.clone(), zero2.clone() ); - var b = new Box2( zero2.clone(), one2.clone() ); - var c = new Box2( one2.clone().negate(), one2.clone() ); - var d = new Box2( one2.clone().negate(), zero2.clone() ); - - assert.ok( a.clone().translate( one2 ).equals( new Box2( one2, one2 ) ), "Passed!" ); - assert.ok( a.clone().translate( one2 ).translate( one2.clone().negate() ).equals( a ), "Passed!" ); - assert.ok( d.clone().translate( one2 ).equals( b ), "Passed!" ); - assert.ok( b.clone().translate( one2.clone().negate() ).equals( d ), "Passed!" ); - - } ); - - QUnit.test( "equals", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author bhouston / http://exocortex.com - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - function compareBox( a, b, threshold ) { - - threshold = threshold || 0.0001; - return ( a.min.distanceTo( b.min ) < threshold && - a.max.distanceTo( b.max ) < threshold ); - - } - - QUnit.module( 'Maths', () => { - - QUnit.module.todo( 'Box3', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - var a = new Box3(); - assert.ok( a.min.equals( posInf3 ), "Passed!" ); - assert.ok( a.max.equals( negInf3 ), "Passed!" ); - - var a = new Box3( zero3.clone(), zero3.clone() ); - assert.ok( a.min.equals( zero3 ), "Passed!" ); - assert.ok( a.max.equals( zero3 ), "Passed!" ); - - var a = new Box3( zero3.clone(), one3.clone() ); - assert.ok( a.min.equals( zero3 ), "Passed!" ); - assert.ok( a.max.equals( one3 ), "Passed!" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isBox3", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "set", ( assert ) => { - - var a = new Box3(); - - a.set( zero3, one3 ); - assert.ok( a.min.equals( zero3 ), "Passed!" ); - assert.ok( a.max.equals( one3 ), "Passed!" ); - - } ); - - QUnit.test( "setFromArray", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setFromBufferAttribute", ( assert ) => { - - var a = new Box3( zero3.clone(), one3.clone() ); - var bigger = new BufferAttribute( new Float32Array( [ - - 2, - 2, - 2, 2, 2, 2, 1.5, 1.5, 1.5, 0, 0, 0 - ] ), 3 ); - var smaller = new BufferAttribute( new Float32Array( [ - - 0.5, - 0.5, - 0.5, 0.5, 0.5, 0.5, 0, 0, 0 - ] ), 3 ); - var newMin = new Vector3( - 2, - 2, - 2 ); - var newMax = new Vector3( 2, 2, 2 ); - - a.setFromBufferAttribute( bigger ); - assert.ok( a.min.equals( newMin ), "Bigger box: correct new minimum" ); - assert.ok( a.max.equals( newMax ), "Bigger box: correct new maximum" ); - - newMin.set( - 0.5, - 0.5, - 0.5 ); - newMax.set( 0.5, 0.5, 0.5 ); - - a.setFromBufferAttribute( smaller ); - assert.ok( a.min.equals( newMin ), "Smaller box: correct new minimum" ); - assert.ok( a.max.equals( newMax ), "Smaller box: correct new maximum" ); - - } ); - - QUnit.test( "setFromPoints", ( assert ) => { - - var a = new Box3(); - - a.setFromPoints( [ zero3, one3, two3 ] ); - assert.ok( a.min.equals( zero3 ), "Passed!" ); - assert.ok( a.max.equals( two3 ), "Passed!" ); - - a.setFromPoints( [ one3 ] ); - assert.ok( a.min.equals( one3 ), "Passed!" ); - assert.ok( a.max.equals( one3 ), "Passed!" ); - - a.setFromPoints( [] ); - assert.ok( a.isEmpty(), "Passed!" ); - - } ); - - QUnit.test( "setFromCenterAndSize", ( assert ) => { - - var a = new Box3( zero3.clone(), one3.clone() ); - var b = a.clone(); - var newCenter = one3; - var newSize = two3; - - a.setFromCenterAndSize( a.getCenter(), a.getSize() ); - assert.ok( a.equals( b ), "Same values: no changes" ); - - a.setFromCenterAndSize( newCenter, a.getSize() ); - assert.ok( a.getCenter().equals( newCenter ), "Move center: correct new center" ); - assert.ok( a.getSize().equals( b.getSize() ), "Move center: no change in size" ); - assert.notOk( a.equals( b ), "Move center: no longer equal to old values" ); - - a.setFromCenterAndSize( a.getCenter(), newSize ); - assert.ok( a.getCenter().equals( newCenter ), "Resize: no change to center" ); - assert.ok( a.getSize().equals( newSize ), "Resize: correct new size" ); - assert.notOk( a.equals( b ), "Resize: no longer equal to old values" ); - - } ); - - QUnit.test( "setFromObject/BufferGeometry", ( assert ) => { - - var a = new Box3( zero3.clone(), one3.clone() ); - var object = new Mesh( new BoxBufferGeometry( 2, 2, 2 ) ); - var child = new Mesh( new BoxBufferGeometry( 1, 1, 1 ) ); - object.add( child ); - - a.setFromObject( object ); - assert.ok( a.min.equals( new Vector3( - 1, - 1, - 1 ) ), "Correct new minimum" ); - assert.ok( a.max.equals( new Vector3( 1, 1, 1 ) ), "Correct new maximum" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - var a = new Box3( zero3.clone(), one3.clone() ); - var b = new Box3().copy( a ); - assert.ok( b.min.equals( zero3 ), "Passed!" ); - assert.ok( b.max.equals( one3 ), "Passed!" ); - - // ensure that it is a true copy - a.min = zero3; - a.max = one3; - assert.ok( b.min.equals( zero3 ), "Passed!" ); - assert.ok( b.max.equals( one3 ), "Passed!" ); - - } ); - - QUnit.test( "empty/makeEmpty", ( assert ) => { - - var a = new Box3(); - - assert.ok( a.isEmpty(), "Passed!" ); - - var a = new Box3( zero3.clone(), one3.clone() ); - assert.ok( ! a.isEmpty(), "Passed!" ); - - a.makeEmpty(); - assert.ok( a.isEmpty(), "Passed!" ); - - } ); - - QUnit.test( "isEmpty", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getCenter", ( assert ) => { - - var a = new Box3( zero3.clone(), zero3.clone() ); - - assert.ok( a.getCenter().equals( zero3 ), "Passed!" ); - - var a = new Box3( zero3.clone(), one3.clone() ); - var midpoint = one3.clone().multiplyScalar( 0.5 ); - assert.ok( a.getCenter().equals( midpoint ), "Passed!" ); - - } ); - - QUnit.test( "getSize", ( assert ) => { - - var a = new Box3( zero3.clone(), zero3.clone() ); - - assert.ok( a.getSize().equals( zero3 ), "Passed!" ); - - var a = new Box3( zero3.clone(), one3.clone() ); - assert.ok( a.getSize().equals( one3 ), "Passed!" ); - - } ); - - QUnit.test( "expandByPoint", ( assert ) => { - - var a = new Box3( zero3.clone(), zero3.clone() ); - - a.expandByPoint( zero3 ); - assert.ok( a.getSize().equals( zero3 ), "Passed!" ); - - a.expandByPoint( one3 ); - assert.ok( a.getSize().equals( one3 ), "Passed!" ); - - a.expandByPoint( one3.clone().negate() ); - assert.ok( a.getSize().equals( one3.clone().multiplyScalar( 2 ) ), "Passed!" ); - assert.ok( a.getCenter().equals( zero3 ), "Passed!" ); - - } ); - - QUnit.test( "expandByVector", ( assert ) => { - - var a = new Box3( zero3.clone(), zero3.clone() ); - - a.expandByVector( zero3 ); - assert.ok( a.getSize().equals( zero3 ), "Passed!" ); - - a.expandByVector( one3 ); - assert.ok( a.getSize().equals( one3.clone().multiplyScalar( 2 ) ), "Passed!" ); - assert.ok( a.getCenter().equals( zero3 ), "Passed!" ); - - } ); - - QUnit.test( "expandByScalar", ( assert ) => { - - var a = new Box3( zero3.clone(), zero3.clone() ); - - a.expandByScalar( 0 ); - assert.ok( a.getSize().equals( zero3 ), "Passed!" ); - - a.expandByScalar( 1 ); - assert.ok( a.getSize().equals( one3.clone().multiplyScalar( 2 ) ), "Passed!" ); - assert.ok( a.getCenter().equals( zero3 ), "Passed!" ); - - } ); - - QUnit.test( "expandByObject", ( assert ) => { - - var a = new Box3( zero3.clone(), one3.clone() ); - var b = a.clone(); - var bigger = new Mesh( new BoxGeometry( 2, 2, 2 ) ); - var smaller = new Mesh( new BoxGeometry( 0.5, 0.5, 0.5 ) ); - var child = new Mesh( new BoxGeometry( 1, 1, 1 ) ); - - // just a bigger box to begin with - a.expandByObject( bigger ); - assert.ok( a.min.equals( new Vector3( - 1, - 1, - 1 ) ), "Bigger box: correct new minimum" ); - assert.ok( a.max.equals( new Vector3( 1, 1, 1 ) ), "Bigger box: correct new maximum" ); - - // a translated, bigger box - a.copy( b ); - bigger.translateX( 2 ); - a.expandByObject( bigger ); - assert.ok( a.min.equals( new Vector3( 0, - 1, - 1 ) ), "Translated, bigger box: correct new minimum" ); - assert.ok( a.max.equals( new Vector3( 3, 1, 1 ) ), "Translated, bigger box: correct new maximum" ); - - // a translated, bigger box with child - a.copy( b ); - bigger.add( child ); - a.expandByObject( bigger ); - assert.ok( a.min.equals( new Vector3( 0, - 1, - 1 ) ), "Translated, bigger box with child: correct new minimum" ); - assert.ok( a.max.equals( new Vector3( 3, 1, 1 ) ), "Translated, bigger box with child: correct new maximum" ); - - // a translated, bigger box with a translated child - a.copy( b ); - child.translateX( 2 ); - a.expandByObject( bigger ); - assert.ok( a.min.equals( new Vector3( 0, - 1, - 1 ) ), "Translated, bigger box with translated child: correct new minimum" ); - assert.ok( a.max.equals( new Vector3( 4.5, 1, 1 ) ), "Translated, bigger box with translated child: correct new maximum" ); - - // a smaller box - a.copy( b ); - a.expandByObject( smaller ); - assert.ok( a.min.equals( new Vector3( - 0.25, - 0.25, - 0.25 ) ), "Smaller box: correct new minimum" ); - assert.ok( a.max.equals( new Vector3( 1, 1, 1 ) ), "Smaller box: correct new maximum" ); - - } ); - - QUnit.test( "containsPoint", ( assert ) => { - - var a = new Box3( zero3.clone(), zero3.clone() ); - - assert.ok( a.containsPoint( zero3 ), "Passed!" ); - assert.ok( ! a.containsPoint( one3 ), "Passed!" ); - - a.expandByScalar( 1 ); - assert.ok( a.containsPoint( zero3 ), "Passed!" ); - assert.ok( a.containsPoint( one3 ), "Passed!" ); - assert.ok( a.containsPoint( one3.clone().negate() ), "Passed!" ); - - } ); - - QUnit.test( "containsBox", ( assert ) => { - - var a = new Box3( zero3.clone(), zero3.clone() ); - var b = new Box3( zero3.clone(), one3.clone() ); - var c = new Box3( one3.clone().negate(), one3.clone() ); - - assert.ok( a.containsBox( a ), "Passed!" ); - assert.ok( ! a.containsBox( b ), "Passed!" ); - assert.ok( ! a.containsBox( c ), "Passed!" ); - - assert.ok( b.containsBox( a ), "Passed!" ); - assert.ok( c.containsBox( a ), "Passed!" ); - assert.ok( ! b.containsBox( c ), "Passed!" ); - - } ); - - QUnit.test( "getParameter", ( assert ) => { - - var a = new Box3( zero3.clone(), one3.clone() ); - var b = new Box3( one3.clone().negate(), one3.clone() ); - - assert.ok( a.getParameter( new Vector3( 0, 0, 0 ) ).equals( new Vector3( 0, 0, 0 ) ), "Passed!" ); - assert.ok( a.getParameter( new Vector3( 1, 1, 1 ) ).equals( new Vector3( 1, 1, 1 ) ), "Passed!" ); - - assert.ok( b.getParameter( new Vector3( - 1, - 1, - 1 ) ).equals( new Vector3( 0, 0, 0 ) ), "Passed!" ); - assert.ok( b.getParameter( new Vector3( 0, 0, 0 ) ).equals( new Vector3( 0.5, 0.5, 0.5 ) ), "Passed!" ); - assert.ok( b.getParameter( new Vector3( 1, 1, 1 ) ).equals( new Vector3( 1, 1, 1 ) ), "Passed!" ); - - } ); - - QUnit.test( "intersectsBox", ( assert ) => { - - var a = new Box3( zero3.clone(), zero3.clone() ); - var b = new Box3( zero3.clone(), one3.clone() ); - var c = new Box3( one3.clone().negate(), one3.clone() ); - - assert.ok( a.intersectsBox( a ), "Passed!" ); - assert.ok( a.intersectsBox( b ), "Passed!" ); - assert.ok( a.intersectsBox( c ), "Passed!" ); - - assert.ok( b.intersectsBox( a ), "Passed!" ); - assert.ok( c.intersectsBox( a ), "Passed!" ); - assert.ok( b.intersectsBox( c ), "Passed!" ); - - b.translate( new Vector3( 2, 2, 2 ) ); - assert.ok( ! a.intersectsBox( b ), "Passed!" ); - assert.ok( ! b.intersectsBox( a ), "Passed!" ); - assert.ok( ! b.intersectsBox( c ), "Passed!" ); - - } ); - - QUnit.test( "intersectsSphere", ( assert ) => { - - var a = new Box3( zero3.clone(), one3.clone() ); - var b = new Sphere( zero3.clone(), 1 ); - - assert.ok( a.intersectsSphere( b ), "Passed!" ); - - b.translate( new Vector3( 2, 2, 2 ) ); - assert.ok( ! a.intersectsSphere( b ), "Passed!" ); - - } ); - - QUnit.test( "intersectsPlane", ( assert ) => { - - var a = new Box3( zero3.clone(), one3.clone() ); - var b = new Plane( new Vector3( 0, 1, 0 ), 1 ); - var c = new Plane( new Vector3( 0, 1, 0 ), 1.25 ); - var d = new Plane( new Vector3( 0, - 1, 0 ), 1.25 ); - - assert.ok( a.intersectsPlane( b ), "Passed!" ); - assert.ok( ! a.intersectsPlane( c ), "Passed!" ); - assert.ok( ! a.intersectsPlane( d ), "Passed!" ); - - } ); - - QUnit.test( "clampPoint", ( assert ) => { - - var a = new Box3( zero3.clone(), zero3.clone() ); - var b = new Box3( one3.clone().negate(), one3.clone() ); - - assert.ok( a.clampPoint( new Vector3( 0, 0, 0 ) ).equals( new Vector3( 0, 0, 0 ) ), "Passed!" ); - assert.ok( a.clampPoint( new Vector3( 1, 1, 1 ) ).equals( new Vector3( 0, 0, 0 ) ), "Passed!" ); - assert.ok( a.clampPoint( new Vector3( - 1, - 1, - 1 ) ).equals( new Vector3( 0, 0, 0 ) ), "Passed!" ); - - assert.ok( b.clampPoint( new Vector3( 2, 2, 2 ) ).equals( new Vector3( 1, 1, 1 ) ), "Passed!" ); - assert.ok( b.clampPoint( new Vector3( 1, 1, 1 ) ).equals( new Vector3( 1, 1, 1 ) ), "Passed!" ); - assert.ok( b.clampPoint( new Vector3( 0, 0, 0 ) ).equals( new Vector3( 0, 0, 0 ) ), "Passed!" ); - assert.ok( b.clampPoint( new Vector3( - 1, - 1, - 1 ) ).equals( new Vector3( - 1, - 1, - 1 ) ), "Passed!" ); - assert.ok( b.clampPoint( new Vector3( - 2, - 2, - 2 ) ).equals( new Vector3( - 1, - 1, - 1 ) ), "Passed!" ); - - } ); - - QUnit.test( "distanceToPoint", ( assert ) => { - - var a = new Box3( zero3.clone(), zero3.clone() ); - var b = new Box3( one3.clone().negate(), one3.clone() ); - - assert.ok( a.distanceToPoint( new Vector3( 0, 0, 0 ) ) == 0, "Passed!" ); - assert.ok( a.distanceToPoint( new Vector3( 1, 1, 1 ) ) == Math.sqrt( 3 ), "Passed!" ); - assert.ok( a.distanceToPoint( new Vector3( - 1, - 1, - 1 ) ) == Math.sqrt( 3 ), "Passed!" ); - - assert.ok( b.distanceToPoint( new Vector3( 2, 2, 2 ) ) == Math.sqrt( 3 ), "Passed!" ); - assert.ok( b.distanceToPoint( new Vector3( 1, 1, 1 ) ) == 0, "Passed!" ); - assert.ok( b.distanceToPoint( new Vector3( 0, 0, 0 ) ) == 0, "Passed!" ); - assert.ok( b.distanceToPoint( new Vector3( - 1, - 1, - 1 ) ) == 0, "Passed!" ); - assert.ok( b.distanceToPoint( new Vector3( - 2, - 2, - 2 ) ) == Math.sqrt( 3 ), "Passed!" ); - - } ); - - QUnit.test( "getBoundingSphere", ( assert ) => { - - var a = new Box3( zero3.clone(), zero3.clone() ); - var b = new Box3( zero3.clone(), one3.clone() ); - var c = new Box3( one3.clone().negate(), one3.clone() ); - - assert.ok( a.getBoundingSphere().equals( new Sphere( zero3, 0 ) ), "Passed!" ); - assert.ok( b.getBoundingSphere().equals( new Sphere( one3.clone().multiplyScalar( 0.5 ), Math.sqrt( 3 ) * 0.5 ) ), "Passed!" ); - assert.ok( c.getBoundingSphere().equals( new Sphere( zero3, Math.sqrt( 12 ) * 0.5 ) ), "Passed!" ); - - } ); - - QUnit.test( "intersect", ( assert ) => { - - var a = new Box3( zero3.clone(), zero3.clone() ); - var b = new Box3( zero3.clone(), one3.clone() ); - var c = new Box3( one3.clone().negate(), one3.clone() ); - - assert.ok( a.clone().intersect( a ).equals( a ), "Passed!" ); - assert.ok( a.clone().intersect( b ).equals( a ), "Passed!" ); - assert.ok( b.clone().intersect( b ).equals( b ), "Passed!" ); - assert.ok( a.clone().intersect( c ).equals( a ), "Passed!" ); - assert.ok( b.clone().intersect( c ).equals( b ), "Passed!" ); - assert.ok( c.clone().intersect( c ).equals( c ), "Passed!" ); - - } ); - - QUnit.test( "union", ( assert ) => { - - var a = new Box3( zero3.clone(), zero3.clone() ); - var b = new Box3( zero3.clone(), one3.clone() ); - var c = new Box3( one3.clone().negate(), one3.clone() ); - - assert.ok( a.clone().union( a ).equals( a ), "Passed!" ); - assert.ok( a.clone().union( b ).equals( b ), "Passed!" ); - assert.ok( a.clone().union( c ).equals( c ), "Passed!" ); - assert.ok( b.clone().union( c ).equals( c ), "Passed!" ); - - } ); - - QUnit.test( "applyMatrix4", ( assert ) => { - - var a = new Box3( zero3.clone(), zero3.clone() ); - var b = new Box3( zero3.clone(), one3.clone() ); - var c = new Box3( one3.clone().negate(), one3.clone() ); - var d = new Box3( one3.clone().negate(), zero3.clone() ); - - var m = new Matrix4().makeTranslation( 1, - 2, 1 ); - var t1 = new Vector3( 1, - 2, 1 ); - - assert.ok( compareBox( a.clone().applyMatrix4( m ), a.clone().translate( t1 ) ), "Passed!" ); - assert.ok( compareBox( b.clone().applyMatrix4( m ), b.clone().translate( t1 ) ), "Passed!" ); - assert.ok( compareBox( c.clone().applyMatrix4( m ), c.clone().translate( t1 ) ), "Passed!" ); - assert.ok( compareBox( d.clone().applyMatrix4( m ), d.clone().translate( t1 ) ), "Passed!" ); - - } ); - - QUnit.test( "translate", ( assert ) => { - - var a = new Box3( zero3.clone(), zero3.clone() ); - var b = new Box3( zero3.clone(), one3.clone() ); - var c = new Box3( one3.clone().negate(), one3.clone() ); - var d = new Box3( one3.clone().negate(), zero3.clone() ); - - assert.ok( a.clone().translate( one3 ).equals( new Box3( one3, one3 ) ), "Passed!" ); - assert.ok( a.clone().translate( one3 ).translate( one3.clone().negate() ).equals( a ), "Passed!" ); - assert.ok( d.clone().translate( one3 ).equals( b ), "Passed!" ); - assert.ok( b.clone().translate( one3.clone().negate() ).equals( d ), "Passed!" ); - - } ); - - QUnit.test( "equals", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author bhouston / http://exocortex.com - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Maths', () => { - - QUnit.module.todo( 'Color', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - // default ctor - var c = new Color(); - assert.ok( c.r, "Red: " + c.r ); - assert.ok( c.g, "Green: " + c.g ); - assert.ok( c.b, "Blue: " + c.b ); - - // rgb ctor - var c = new Color( 1, 1, 1 ); - assert.ok( c.r == 1, "Passed" ); - assert.ok( c.g == 1, "Passed" ); - assert.ok( c.b == 1, "Passed" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isColor", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "set", ( assert ) => { - - var a = new Color(); - var b = new Color( 0.5, 0, 0 ); - var c = new Color( 0xFF0000 ); - var d = new Color( 0, 1.0, 0 ); - - a.set( b ); - assert.ok( a.equals( b ), "Set with Color instance" ); - - a.set( 0xFF0000 ); - assert.ok( a.equals( c ), "Set with number" ); - - a.set( "rgb(0,255,0)" ); - assert.ok( a.equals( d ), "Set with style" ); - - } ); - - QUnit.test( "setScalar", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setHex", ( assert ) => { - - var c = new Color(); - c.setHex( 0xFA8072 ); - assert.ok( c.getHex() == 0xFA8072, "Hex: " + c.getHex() ); - - } ); - - QUnit.test( "setRGB", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setHSL", ( assert ) => { - - var c = new Color(); - c.setHSL( 0.75, 1.0, 0.25 ); - var hsl = c.getHSL(); - - assert.ok( hsl.h == 0.75, "hue: " + hsl.h ); - assert.ok( hsl.s == 1.00, "saturation: " + hsl.s ); - assert.ok( hsl.l == 0.25, "lightness: " + hsl.l ); - - } ); - - QUnit.test( "setStyle", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - var c = new Color( 'teal' ); - var c2 = c.clone(); - assert.ok( c2.getHex() == 0x008080, "Hex c2: " + c2.getHex() ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copyGammaToLinear", ( assert ) => { - - var c = new Color(); - var c2 = new Color(); - c2.setRGB( 0.3, 0.5, 0.9 ); - c.copyGammaToLinear( c2 ); - assert.ok( c.r == 0.09, "Red c: " + c.r + " Red c2: " + c2.r ); - assert.ok( c.g == 0.25, "Green c: " + c.g + " Green c2: " + c2.g ); - assert.ok( c.b == 0.81, "Blue c: " + c.b + " Blue c2: " + c2.b ); - - } ); - - QUnit.test( "copyLinearToGamma", ( assert ) => { - - var c = new Color(); - var c2 = new Color(); - c2.setRGB( 0.09, 0.25, 0.81 ); - c.copyLinearToGamma( c2 ); - assert.ok( c.r == 0.3, "Red c: " + c.r + " Red c2: " + c2.r ); - assert.ok( c.g == 0.5, "Green c: " + c.g + " Green c2: " + c2.g ); - assert.ok( c.b == 0.9, "Blue c: " + c.b + " Blue c2: " + c2.b ); - - } ); - - QUnit.test( "convertGammaToLinear", ( assert ) => { - - var c = new Color(); - c.setRGB( 0.3, 0.5, 0.9 ); - c.convertGammaToLinear(); - assert.ok( c.r == 0.09, "Red: " + c.r ); - assert.ok( c.g == 0.25, "Green: " + c.g ); - assert.ok( c.b == 0.81, "Blue: " + c.b ); - - } ); - - QUnit.test( "convertLinearToGamma", ( assert ) => { - - var c = new Color(); - c.setRGB( 4, 9, 16 ); - c.convertLinearToGamma(); - assert.ok( c.r == 2, "Red: " + c.r ); - assert.ok( c.g == 3, "Green: " + c.g ); - assert.ok( c.b == 4, "Blue: " + c.b ); - - } ); - - QUnit.test( "getHex", ( assert ) => { - - var c = new Color( 'red' ); - var res = c.getHex(); - assert.ok( res == 0xFF0000, "Hex: " + res ); - - } ); - - QUnit.test( "getHexString", ( assert ) => { - - var c = new Color( 'tomato' ); - var res = c.getHexString(); - assert.ok( res == 'ff6347', "Hex: " + res ); - - } ); - - QUnit.test( "getHSL", ( assert ) => { - - var c = new Color( 0x80ffff ); - var hsl = c.getHSL(); - - assert.ok( hsl.h == 0.5, "hue: " + hsl.h ); - assert.ok( hsl.s == 1.0, "saturation: " + hsl.s ); - assert.ok( ( Math.round( parseFloat( hsl.l ) * 100 ) / 100 ) == 0.75, "lightness: " + hsl.l ); - - } ); - - QUnit.test( "getStyle", ( assert ) => { - - var c = new Color( 'plum' ); - var res = c.getStyle(); - assert.ok( res == 'rgb(221,160,221)', "style: " + res ); - - } ); - - QUnit.test( "offsetHSL", ( assert ) => { - - var a = new Color( "hsl(120,50%,50%)" ); - var b = new Color( 0.36, 0.84, 0.648 ); - - a.offsetHSL( 0.1, 0.1, 0.1 ); - - assert.ok( Math.abs( a.r - b.r ) <= eps, "Check r" ); - assert.ok( Math.abs( a.g - b.g ) <= eps, "Check g" ); - assert.ok( Math.abs( a.b - b.b ) <= eps, "Check b" ); - - } ); - - QUnit.test( "add", ( assert ) => { - - var a = new Color( 0x0000FF ); - var b = new Color( 0xFF0000 ); - var c = new Color( 0xFF00FF ); - - a.add( b ); - - assert.ok( a.equals( c ), "Check new value" ); - - } ); - - QUnit.test( "addColors", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "addScalar", ( assert ) => { - - var a = new Color( 0.1, 0.0, 0.0 ); - var b = new Color( 0.6, 0.5, 0.5 ); - - a.addScalar( 0.5 ); - - assert.ok( a.equals( b ), "Check new value" ); - - } ); - - QUnit.test( "sub", ( assert ) => { - - var a = new Color( 0x0000CC ); - var b = new Color( 0xFF0000 ); - var c = new Color( 0x0000AA ); - - a.sub( b ); - assert.strictEqual( a.getHex(), 0xCC, "Difference too large" ); - - a.sub( c ); - assert.strictEqual( a.getHex(), 0x22, "Difference fine" ); - - } ); - - QUnit.test( "multiply", ( assert ) => { - - var a = new Color( 1, 0, 0.5 ); - var b = new Color( 0.5, 1, 0.5 ); - var c = new Color( 0.5, 0, 0.25 ); - - a.multiply( b ); - assert.ok( a.equals( c ), "Check new value" ); - - } ); - - QUnit.test( "multiplyScalar", ( assert ) => { - - var a = new Color( 0.25, 0, 0.5 ); - var b = new Color( 0.5, 0, 1 ); - - a.multiplyScalar( 2 ); - assert.ok( a.equals( b ), "Check new value" ); - - } ); - - QUnit.test( "copyHex", ( assert ) => { - - var c = new Color(); - var c2 = new Color( 0xF5FFFA ); - c.copy( c2 ); - assert.ok( c.getHex() == c2.getHex(), "Hex c: " + c.getHex() + " Hex c2: " + c2.getHex() ); - - } ); - - QUnit.test( "copyColorString", ( assert ) => { - - var c = new Color(); - var c2 = new Color( 'ivory' ); - c.copy( c2 ); - assert.ok( c.getHex() == c2.getHex(), "Hex c: " + c.getHex() + " Hex c2: " + c2.getHex() ); - - } ); - - QUnit.test( "setRGB", ( assert ) => { - - var c = new Color(); - c.setRGB( 1, 0.2, 0.1 ); - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g == 0.2, "Green: " + c.g ); - assert.ok( c.b == 0.1, "Blue: " + c.b ); - - } ); - - QUnit.test( "lerp", ( assert ) => { - - var c = new Color(); - var c2 = new Color(); - c.setRGB( 0, 0, 0 ); - c.lerp( c2, 0.2 ); - assert.ok( c.r == 0.2, "Red: " + c.r ); - assert.ok( c.g == 0.2, "Green: " + c.g ); - assert.ok( c.b == 0.2, "Blue: " + c.b ); - - } ); - - QUnit.test( "equals", ( assert ) => { - - var a = new Color( 0.5, 0.0, 1.0 ); - var b = new Color( 0.5, 1.0, 0.0 ); - - assert.strictEqual( a.r, b.r, "Components: r is equal" ); - assert.notStrictEqual( a.g, b.g, "Components: g is not equal" ); - assert.notStrictEqual( a.b, b.b, "Components: b is not equal" ); - - assert.notOk( a.equals( b ), "equals(): a not equal b" ); - assert.notOk( b.equals( a ), "equals(): b not equal a" ); - - a.copy( b ); - assert.strictEqual( a.r, b.r, "Components after copy(): r is equal" ); - assert.strictEqual( a.g, b.g, "Components after copy(): g is equal" ); - assert.strictEqual( a.b, b.b, "Components after copy(): b is equal" ); - - assert.ok( a.equals( b ), "equals() after copy(): a equals b" ); - assert.ok( b.equals( a ), "equals() after copy(): b equals a" ); - - } ); - - QUnit.test( "fromArray", ( assert ) => { - - var a = new Color(); - var array = [ 0.5, 0.6, 0.7, 0, 1, 0 ]; - - a.fromArray( array ); - assert.strictEqual( a.r, 0.5, "No offset: check r" ); - assert.strictEqual( a.g, 0.6, "No offset: check g" ); - assert.strictEqual( a.b, 0.7, "No offset: check b" ); - - a.fromArray( array, 3 ); - assert.strictEqual( a.r, 0, "With offset: check r" ); - assert.strictEqual( a.g, 1, "With offset: check g" ); - assert.strictEqual( a.b, 0, "With offset: check b" ); - - } ); - - QUnit.test( "toArray", ( assert ) => { - - var r = 0.5, g = 1.0, b = 0.0; - var a = new Color( r, g, b ); - - var array = a.toArray(); - assert.strictEqual( array[ 0 ], r, "No array, no offset: check r" ); - assert.strictEqual( array[ 1 ], g, "No array, no offset: check g" ); - assert.strictEqual( array[ 2 ], b, "No array, no offset: check b" ); - - var array = []; - a.toArray( array ); - assert.strictEqual( array[ 0 ], r, "With array, no offset: check r" ); - assert.strictEqual( array[ 1 ], g, "With array, no offset: check g" ); - assert.strictEqual( array[ 2 ], b, "With array, no offset: check b" ); - - var array = []; - a.toArray( array, 1 ); - assert.strictEqual( array[ 0 ], undefined, "With array and offset: check [0]" ); - assert.strictEqual( array[ 1 ], r, "With array and offset: check r" ); - assert.strictEqual( array[ 2 ], g, "With array and offset: check g" ); - assert.strictEqual( array[ 3 ], b, "With array and offset: check b" ); - - } ); - - QUnit.test( "toJSON", ( assert ) => { - - var a = new Color( 0.0, 0.0, 0.0 ); - var b = new Color( 0.0, 0.5, 0.0 ); - var c = new Color( 1.0, 0.0, 0.0 ); - var d = new Color( 1.0, 1.0, 1.0 ); - - assert.strictEqual( a.toJSON(), 0x000000, "Check black" ); - assert.strictEqual( b.toJSON(), 0x007F00, "Check half-blue" ); - assert.strictEqual( c.toJSON(), 0xFF0000, "Check red" ); - assert.strictEqual( d.toJSON(), 0xFFFFFF, "Check white" ); - - } ); - - // OTHERS - QUnit.test( "setWithNum", ( assert ) => { - - var c = new Color(); - c.set( 0xFF0000 ); - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g === 0, "Green: " + c.g ); - assert.ok( c.b === 0, "Blue: " + c.b ); - - } ); - - QUnit.test( "setWithString", ( assert ) => { - - var c = new Color(); - c.set( 'silver' ); - assert.ok( c.getHex() == 0xC0C0C0, "Hex c: " + c.getHex() ); - - } ); - - QUnit.test( "setStyleRGBRed", ( assert ) => { - - var c = new Color(); - c.setStyle( 'rgb(255,0,0)' ); - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g === 0, "Green: " + c.g ); - assert.ok( c.b === 0, "Blue: " + c.b ); - - } ); - - QUnit.test( "setStyleRGBARed", ( assert ) => { - - var c = new Color(); - c.setStyle( 'rgba(255,0,0,0.5)' ); - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g === 0, "Green: " + c.g ); - assert.ok( c.b === 0, "Blue: " + c.b ); - - } ); - - QUnit.test( "setStyleRGBRedWithSpaces", ( assert ) => { - - var c = new Color(); - c.setStyle( 'rgb( 255 , 0, 0 )' ); - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g === 0, "Green: " + c.g ); - assert.ok( c.b === 0, "Blue: " + c.b ); - - } ); - - QUnit.test( "setStyleRGBARedWithSpaces", ( assert ) => { - - var c = new Color(); - c.setStyle( 'rgba( 255, 0, 0 , 1 )' ); - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g === 0, "Green: " + c.g ); - assert.ok( c.b === 0, "Blue: " + c.b ); - - } ); - - QUnit.test( "setStyleRGBPercent", ( assert ) => { - - var c = new Color(); - c.setStyle( 'rgb(100%,50%,10%)' ); - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g == 0.5, "Green: " + c.g ); - assert.ok( c.b == 0.1, "Blue: " + c.b ); - - } ); - - QUnit.test( "setStyleRGBAPercent", ( assert ) => { - - var c = new Color(); - c.setStyle( 'rgba(100%,50%,10%, 0.5)' ); - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g == 0.5, "Green: " + c.g ); - assert.ok( c.b == 0.1, "Blue: " + c.b ); - - } ); - - QUnit.test( "setStyleRGBPercentWithSpaces", ( assert ) => { - - var c = new Color(); - c.setStyle( 'rgb( 100% ,50% , 10% )' ); - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g == 0.5, "Green: " + c.g ); - assert.ok( c.b == 0.1, "Blue: " + c.b ); - - } ); - - QUnit.test( "setStyleRGBAPercentWithSpaces", ( assert ) => { - - var c = new Color(); - c.setStyle( 'rgba( 100% ,50% , 10%, 0.5 )' ); - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g == 0.5, "Green: " + c.g ); - assert.ok( c.b == 0.1, "Blue: " + c.b ); - - } ); - - QUnit.test( "setStyleHSLRed", ( assert ) => { - - var c = new Color(); - c.setStyle( 'hsl(360,100%,50%)' ); - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g === 0, "Green: " + c.g ); - assert.ok( c.b === 0, "Blue: " + c.b ); - - } ); - - QUnit.test( "setStyleHSLARed", ( assert ) => { - - var c = new Color(); - c.setStyle( 'hsla(360,100%,50%,0.5)' ); - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g === 0, "Green: " + c.g ); - assert.ok( c.b === 0, "Blue: " + c.b ); - - } ); - - QUnit.test( "setStyleHSLRedWithSpaces", ( assert ) => { - - var c = new Color(); - c.setStyle( 'hsl(360, 100% , 50% )' ); - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g === 0, "Green: " + c.g ); - assert.ok( c.b === 0, "Blue: " + c.b ); - - } ); - - QUnit.test( "setStyleHSLARedWithSpaces", ( assert ) => { - - var c = new Color(); - c.setStyle( 'hsla( 360, 100% , 50%, 0.5 )' ); - assert.ok( c.r == 1, "Red: " + c.r ); - assert.ok( c.g === 0, "Green: " + c.g ); - assert.ok( c.b === 0, "Blue: " + c.b ); - - } ); - - QUnit.test( "setStyleHexSkyBlue", ( assert ) => { - - var c = new Color(); - c.setStyle( '#87CEEB' ); - assert.ok( c.getHex() == 0x87CEEB, "Hex c: " + c.getHex() ); - - } ); - - QUnit.test( "setStyleHexSkyBlueMixed", ( assert ) => { - - var c = new Color(); - c.setStyle( '#87cEeB' ); - assert.ok( c.getHex() == 0x87CEEB, "Hex c: " + c.getHex() ); - - } ); - - QUnit.test( "setStyleHex2Olive", ( assert ) => { - - var c = new Color(); - c.setStyle( '#F00' ); - assert.ok( c.getHex() == 0xFF0000, "Hex c: " + c.getHex() ); - - } ); - - QUnit.test( "setStyleHex2OliveMixed", ( assert ) => { - - var c = new Color(); - c.setStyle( '#f00' ); - assert.ok( c.getHex() == 0xFF0000, "Hex c: " + c.getHex() ); - - } ); - - QUnit.test( "setStyleColorName", ( assert ) => { - - var c = new Color(); - c.setStyle( 'powderblue' ); - assert.ok( c.getHex() == 0xB0E0E6, "Hex c: " + c.getHex() ); - - } ); - - - } ); - - } ); - - /** - * @author Mugen87 / https://github.com/Mugen87 - * - * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system - * - */ - - function Cylindrical( radius, theta, y ) { - - this.radius = ( radius !== undefined ) ? radius : 1.0; // distance from the origin to a point in the x-z plane - this.theta = ( theta !== undefined ) ? theta : 0; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis - this.y = ( y !== undefined ) ? y : 0; // height above the x-z plane - - return this; - - } - - Object.assign( Cylindrical.prototype, { - - set: function ( radius, theta, y ) { - - this.radius = radius; - this.theta = theta; - this.y = y; - - return this; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( other ) { - - this.radius = other.radius; - this.theta = other.theta; - this.y = other.y; - - return this; - - }, - - setFromVector3: function ( vec3 ) { - - this.radius = Math.sqrt( vec3.x * vec3.x + vec3.z * vec3.z ); - this.theta = Math.atan2( vec3.x, vec3.z ); - this.y = vec3.y; - - return this; - - } - - } ); - - /** - * @author moraxy / https://github.com/moraxy - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Maths', () => { - - QUnit.module.todo( 'Cylindrical', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - var a = new Cylindrical(); - var radius = 10.0; - var theta = Math.PI; - var y$$1 = 5; - - assert.strictEqual( a.radius, 1.0, "Default values: check radius" ); - assert.strictEqual( a.theta, 0, "Default values: check theta" ); - assert.strictEqual( a.y, 0, "Default values: check y" ); - - var a = new Cylindrical( radius, theta, y$$1 ); - assert.strictEqual( a.radius, radius, "Custom values: check radius" ); - assert.strictEqual( a.theta, theta, "Custom values: check theta" ); - assert.strictEqual( a.y, y$$1, "Custom values: check y" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "set", ( assert ) => { - - var a = new Cylindrical(); - var radius = 10.0; - var theta = Math.PI; - var y$$1 = 5; - - a.set( radius, theta, y$$1 ); - assert.strictEqual( a.radius, radius, "Check radius" ); - assert.strictEqual( a.theta, theta, "Check theta" ); - assert.strictEqual( a.y, y$$1, "Check y" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - var radius = 10.0; - var theta = Math.PI; - var y$$1 = 5; - var a = new Cylindrical( radius, theta, y$$1 ); - var b = a.clone(); - - assert.propEqual( a, b, "Check a and b are equal after clone()" ); - - a.radius = 1; - assert.notPropEqual( a, b, "Check a and b are not equal after modification" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - var radius = 10.0; - var theta = Math.PI; - var y$$1 = 5; - var a = new Cylindrical( radius, theta, y$$1 ); - var b = new Cylindrical().copy( a ); - - assert.propEqual( a, b, "Check a and b are equal after copy()" ); - - a.radius = 1; - assert.notPropEqual( a, b, "Check a and b are not equal after modification" ); - - } ); - - QUnit.test( "setFromVector3", ( assert ) => { - - var a = new Cylindrical( 1, 1, 1 ); - var b = new Vector3( 0, 0, 0 ); - var c = new Vector3( 3, - 1, - 3 ); - var expected = new Cylindrical( Math.sqrt( 9 + 9 ), Math.atan2( 3, - 3 ), - 1 ); - - a.setFromVector3( b ); - assert.strictEqual( a.radius, 0, "Zero-length vector: check radius" ); - assert.strictEqual( a.theta, 0, "Zero-length vector: check theta" ); - assert.strictEqual( a.y, 0, "Zero-length vector: check y" ); - - a.setFromVector3( c ); - assert.ok( Math.abs( a.radius - expected.radius ) <= eps, "Normal vector: check radius" ); - assert.ok( Math.abs( a.theta - expected.theta ) <= eps, "Normal vector: check theta" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Normal vector: check y" ); - - } ); - - } ); - - } ); - - /** - * @author bhouston / http://exocortex.com - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - const eulerZero = new Euler( 0, 0, 0, "XYZ" ); - const eulerAxyz = new Euler( 1, 0, 0, "XYZ" ); - const eulerAzyx = new Euler( 0, 1, 0, "ZYX" ); - - function matrixEquals4( a, b, tolerance ) { - - tolerance = tolerance || 0.0001; - if ( a.elements.length != b.elements.length ) { - - return false; - - } - - for ( var i = 0, il = a.elements.length; i < il; i ++ ) { - - var delta = a.elements[ i ] - b.elements[ i ]; - if ( delta > tolerance ) { - - return false; - - } - - } - - return true; - - } - - function eulerEquals( a, b, tolerance ) { - - tolerance = tolerance || 0.0001; - var diff = Math.abs( a.x - b.x ) + Math.abs( a.y - b.y ) + Math.abs( a.z - b.z ); - - return ( diff < tolerance ); - - } - - function quatEquals( a, b, tolerance ) { - - tolerance = tolerance || 0.0001; - var diff = Math.abs( a.x - b.x ) + Math.abs( a.y - b.y ) + Math.abs( a.z - b.z ) + Math.abs( a.w - b.w ); - - return ( diff < tolerance ); - - } - - QUnit.module( 'Maths', () => { - - QUnit.module.todo( 'Euler', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - var a = new Euler(); - assert.ok( a.equals( eulerZero ), "Passed!" ); - assert.ok( ! a.equals( eulerAxyz ), "Passed!" ); - assert.ok( ! a.equals( eulerAzyx ), "Passed!" ); - - } ); - - // STATIC STUFF - QUnit.test( "RotationOrders", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "DefaultOrder", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PROPERTIES STUFF - QUnit.test( "x", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "y", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "z", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "order", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isEuler", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "set/setFromVector3/toVector3", ( assert ) => { - - var a = new Euler(); - - a.set( 0, 1, 0, "ZYX" ); - assert.ok( a.equals( eulerAzyx ), "Passed!" ); - assert.ok( ! a.equals( eulerAxyz ), "Passed!" ); - assert.ok( ! a.equals( eulerZero ), "Passed!" ); - - var vec = new Vector3( 0, 1, 0 ); - - var b = new Euler().setFromVector3( vec, "ZYX" ); - assert.ok( a.equals( b ), "Passed!" ); - - var c = b.toVector3(); - assert.ok( c.equals( vec ), "Passed!" ); - - } ); - - QUnit.test( "clone/copy/equals", ( assert ) => { - - var a = eulerAxyz.clone(); - assert.ok( a.equals( eulerAxyz ), "Passed!" ); - assert.ok( ! a.equals( eulerZero ), "Passed!" ); - assert.ok( ! a.equals( eulerAzyx ), "Passed!" ); - - a.copy( eulerAzyx ); - assert.ok( a.equals( eulerAzyx ), "Passed!" ); - assert.ok( ! a.equals( eulerAxyz ), "Passed!" ); - assert.ok( ! a.equals( eulerZero ), "Passed!" ); - - } ); - - QUnit.test( "Quaternion.setFromEuler/Euler.fromQuaternion", ( assert ) => { - - var testValues = [ eulerZero, eulerAxyz, eulerAzyx ]; - for ( var i = 0; i < testValues.length; i ++ ) { - - var v = testValues[ i ]; - var q = new Quaternion().setFromEuler( v ); - - var v2 = new Euler().setFromQuaternion( q, v.order ); - var q2 = new Quaternion().setFromEuler( v2 ); - assert.ok( quatEquals( q, q2 ), "Passed!" ); - - } - - } ); - - QUnit.test( "Matrix4.setFromEuler/Euler.fromRotationMatrix", ( assert ) => { - - var testValues = [ eulerZero, eulerAxyz, eulerAzyx ]; - for ( var i = 0; i < testValues.length; i ++ ) { - - var v = testValues[ i ]; - var m = new Matrix4().makeRotationFromEuler( v ); - - var v2 = new Euler().setFromRotationMatrix( m, v.order ); - var m2 = new Matrix4().makeRotationFromEuler( v2 ); - assert.ok( matrixEquals4( m, m2, 0.0001 ), "Passed!" ); - - } - - } ); - - QUnit.test( "reorder", ( assert ) => { - - var testValues = [ eulerZero, eulerAxyz, eulerAzyx ]; - for ( var i = 0; i < testValues.length; i ++ ) { - - var v = testValues[ i ]; - var q = new Quaternion().setFromEuler( v ); - - v.reorder( 'YZX' ); - var q2 = new Quaternion().setFromEuler( v ); - assert.ok( quatEquals( q, q2 ), "Passed!" ); - - v.reorder( 'ZXY' ); - var q3 = new Quaternion().setFromEuler( v ); - assert.ok( quatEquals( q, q3 ), "Passed!" ); - - } - - } ); - - QUnit.test( "set/get properties, check callbacks", ( assert ) => { - - var a = new Euler(); - a.onChange( function () { - - assert.step( "set: onChange called" ); - - } ); - - assert.expect( 8 ); - - // should be 4 calls to onChangeCallback - a.x = 1; - a.y = 2; - a.z = 3; - a.order = "ZYX"; - - assert.strictEqual( a.x, 1, "get: check x" ); - assert.strictEqual( a.y, 2, "get: check y" ); - assert.strictEqual( a.z, 3, "get: check z" ); - assert.strictEqual( a.order, "ZYX", "get: check order" ); - - } ); - - QUnit.test( "clone/copy, check callbacks", ( assert ) => { - - assert.expect( 3 ); - - var a = new Euler( 1, 2, 3, "ZXY" ); - var b = new Euler( 4, 5, 6, "XZY" ); - var cb = function () { - - assert.step( "onChange called" ); - - }; - a.onChange( cb ); - b.onChange( cb ); - - // clone doesn't trigger onChange - var a = b.clone(); - assert.ok( a.equals( b ), "clone: check if a equals b" ); - - // copy triggers onChange once - var a = new Euler( 1, 2, 3, "ZXY" ); - a.onChange( cb ); - a.copy( b ); - assert.ok( a.equals( b ), "copy: check if a equals b" ); - - } ); - - QUnit.test( "toArray", ( assert ) => { - - var order = "YXZ"; - var a = new Euler( x, y, z, order ); - - var array = a.toArray(); - assert.strictEqual( array[ 0 ], x, "No array, no offset: check x" ); - assert.strictEqual( array[ 1 ], y, "No array, no offset: check y" ); - assert.strictEqual( array[ 2 ], z, "No array, no offset: check z" ); - assert.strictEqual( array[ 3 ], order, "No array, no offset: check order" ); - - var array = []; - a.toArray( array ); - assert.strictEqual( array[ 0 ], x, "With array, no offset: check x" ); - assert.strictEqual( array[ 1 ], y, "With array, no offset: check y" ); - assert.strictEqual( array[ 2 ], z, "With array, no offset: check z" ); - assert.strictEqual( array[ 3 ], order, "With array, no offset: check order" ); - - var array = []; - a.toArray( array, 1 ); - assert.strictEqual( array[ 0 ], undefined, "With array and offset: check [0]" ); - assert.strictEqual( array[ 1 ], x, "With array and offset: check x" ); - assert.strictEqual( array[ 2 ], y, "With array and offset: check y" ); - assert.strictEqual( array[ 3 ], z, "With array and offset: check z" ); - assert.strictEqual( array[ 4 ], order, "With array and offset: check order" ); - - } ); - - QUnit.test( "fromArray", ( assert ) => { - - assert.expect( 10 ); - - var a = new Euler(); - var array = [ x, y, z ]; - var cb = function () { - - assert.step( "onChange called" ); - - }; - a.onChange( cb ); - - a.fromArray( array ); - assert.strictEqual( a.x, x, "No order: check x" ); - assert.strictEqual( a.y, y, "No order: check y" ); - assert.strictEqual( a.z, z, "No order: check z" ); - assert.strictEqual( a.order, "XYZ", "No order: check order" ); - - var a = new Euler(); - var array = [ x, y, z, "ZXY" ]; - a.onChange( cb ); - a.fromArray( array ); - assert.strictEqual( a.x, x, "With order: check x" ); - assert.strictEqual( a.y, y, "With order: check y" ); - assert.strictEqual( a.z, z, "With order: check z" ); - assert.strictEqual( a.order, "ZXY", "With order: check order" ); - - } ); - - QUnit.test( "onChange", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "onChangeCallback", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( "gimbalLocalQuat", ( assert ) => { - - // known problematic quaternions - var q1 = new Quaternion( 0.5207769385244341, - 0.4783214164122354, 0.520776938524434, 0.47832141641223547 ); - var q2 = new Quaternion( 0.11284905712620674, 0.6980437630368944, - 0.11284905712620674, 0.6980437630368944 ); - - var eulerOrder = "ZYX"; - - // create Euler directly from a Quaternion - var eViaQ1 = new Euler().setFromQuaternion( q1, eulerOrder ); // there is likely a bug here - - // create Euler from Quaternion via an intermediate Matrix4 - var mViaQ1 = new Matrix4().makeRotationFromQuaternion( q1 ); - var eViaMViaQ1 = new Euler().setFromRotationMatrix( mViaQ1, eulerOrder ); - - // the results here are different - assert.ok( eulerEquals( eViaQ1, eViaMViaQ1 ), "Passed!" ); // this result is correct - - } ); - - } ); - - } ); - - /** - * @author bhouston / http://exocortex.com - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - const unit3 = new Vector3( 1, 0, 0 ); - - QUnit.module( 'Maths', () => { - - QUnit.module.todo( 'Frustum', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - var a = new Frustum(); - - assert.ok( a.planes !== undefined, "Passed!" ); - assert.ok( a.planes.length === 6, "Passed!" ); - - var pDefault = new Plane(); - for ( var i = 0; i < 6; i ++ ) { - - assert.ok( a.planes[ i ].equals( pDefault ), "Passed!" ); - - } - - var p0 = new Plane( unit3, - 1 ); - var p1 = new Plane( unit3, 1 ); - var p2 = new Plane( unit3, 2 ); - var p3 = new Plane( unit3, 3 ); - var p4 = new Plane( unit3, 4 ); - var p5 = new Plane( unit3, 5 ); - - var a = new Frustum( p0, p1, p2, p3, p4, p5 ); - assert.ok( a.planes[ 0 ].equals( p0 ), "Passed!" ); - assert.ok( a.planes[ 1 ].equals( p1 ), "Passed!" ); - assert.ok( a.planes[ 2 ].equals( p2 ), "Passed!" ); - assert.ok( a.planes[ 3 ].equals( p3 ), "Passed!" ); - assert.ok( a.planes[ 4 ].equals( p4 ), "Passed!" ); - assert.ok( a.planes[ 5 ].equals( p5 ), "Passed!" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "set", ( assert ) => { - - var a = new Frustum(); - var p0 = new Plane( unit3, - 1 ); - var p1 = new Plane( unit3, 1 ); - var p2 = new Plane( unit3, 2 ); - var p3 = new Plane( unit3, 3 ); - var p4 = new Plane( unit3, 4 ); - var p5 = new Plane( unit3, 5 ); - - a.set( p0, p1, p2, p3, p4, p5 ); - - assert.ok( a.planes[ 0 ].equals( p0 ), "Check plane #0" ); - assert.ok( a.planes[ 1 ].equals( p1 ), "Check plane #1" ); - assert.ok( a.planes[ 2 ].equals( p2 ), "Check plane #2" ); - assert.ok( a.planes[ 3 ].equals( p3 ), "Check plane #3" ); - assert.ok( a.planes[ 4 ].equals( p4 ), "Check plane #4" ); - assert.ok( a.planes[ 5 ].equals( p5 ), "Check plane #5" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - var p0 = new Plane( unit3, - 1 ); - var p1 = new Plane( unit3, 1 ); - var p2 = new Plane( unit3, 2 ); - var p3 = new Plane( unit3, 3 ); - var p4 = new Plane( unit3, 4 ); - var p5 = new Plane( unit3, 5 ); - - var b = new Frustum( p0, p1, p2, p3, p4, p5 ); - var a = b.clone(); - assert.ok( a.planes[ 0 ].equals( p0 ), "Passed!" ); - assert.ok( a.planes[ 1 ].equals( p1 ), "Passed!" ); - assert.ok( a.planes[ 2 ].equals( p2 ), "Passed!" ); - assert.ok( a.planes[ 3 ].equals( p3 ), "Passed!" ); - assert.ok( a.planes[ 4 ].equals( p4 ), "Passed!" ); - assert.ok( a.planes[ 5 ].equals( p5 ), "Passed!" ); - - // ensure it is a true copy by modifying source - a.planes[ 0 ].copy( p1 ); - assert.ok( b.planes[ 0 ].equals( p0 ), "Passed!" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - var p0 = new Plane( unit3, - 1 ); - var p1 = new Plane( unit3, 1 ); - var p2 = new Plane( unit3, 2 ); - var p3 = new Plane( unit3, 3 ); - var p4 = new Plane( unit3, 4 ); - var p5 = new Plane( unit3, 5 ); - - var b = new Frustum( p0, p1, p2, p3, p4, p5 ); - var a = new Frustum().copy( b ); - assert.ok( a.planes[ 0 ].equals( p0 ), "Passed!" ); - assert.ok( a.planes[ 1 ].equals( p1 ), "Passed!" ); - assert.ok( a.planes[ 2 ].equals( p2 ), "Passed!" ); - assert.ok( a.planes[ 3 ].equals( p3 ), "Passed!" ); - assert.ok( a.planes[ 4 ].equals( p4 ), "Passed!" ); - assert.ok( a.planes[ 5 ].equals( p5 ), "Passed!" ); - - // ensure it is a true copy by modifying source - b.planes[ 0 ] = p1; - assert.ok( a.planes[ 0 ].equals( p0 ), "Passed!" ); - - } ); - - QUnit.test( "setFromMatrix/makeOrthographic/containsPoint", ( assert ) => { - - var m = new Matrix4().makeOrthographic( - 1, 1, - 1, 1, 1, 100 ); - var a = new Frustum().setFromMatrix( m ); - - assert.ok( ! a.containsPoint( new Vector3( 0, 0, 0 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( 0, 0, - 50 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( 0, 0, - 1.001 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( - 1, - 1, - 1.001 ) ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( - 1.1, - 1.1, - 1.001 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( 1, 1, - 1.001 ) ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( 1.1, 1.1, - 1.001 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( 0, 0, - 100 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( - 1, - 1, - 100 ) ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( - 1.1, - 1.1, - 100.1 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( 1, 1, - 100 ) ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( 1.1, 1.1, - 100.1 ) ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( 0, 0, - 101 ) ), "Passed!" ); - - } ); - - QUnit.test( "setFromMatrix/makePerspective/containsPoint", ( assert ) => { - - var m = new Matrix4().makePerspective( - 1, 1, 1, - 1, 1, 100 ); - var a = new Frustum().setFromMatrix( m ); - - assert.ok( ! a.containsPoint( new Vector3( 0, 0, 0 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( 0, 0, - 50 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( 0, 0, - 1.001 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( - 1, - 1, - 1.001 ) ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( - 1.1, - 1.1, - 1.001 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( 1, 1, - 1.001 ) ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( 1.1, 1.1, - 1.001 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( 0, 0, - 99.999 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( - 99.999, - 99.999, - 99.999 ) ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( - 100.1, - 100.1, - 100.1 ) ), "Passed!" ); - assert.ok( a.containsPoint( new Vector3( 99.999, 99.999, - 99.999 ) ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( 100.1, 100.1, - 100.1 ) ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( 0, 0, - 101 ) ), "Passed!" ); - - } ); - - QUnit.test( "setFromMatrix/makePerspective/intersectsSphere", ( assert ) => { - - var m = new Matrix4().makePerspective( - 1, 1, 1, - 1, 1, 100 ); - var a = new Frustum().setFromMatrix( m ); - - assert.ok( ! a.intersectsSphere( new Sphere( new Vector3( 0, 0, 0 ), 0 ) ), "Passed!" ); - assert.ok( ! a.intersectsSphere( new Sphere( new Vector3( 0, 0, 0 ), 0.9 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( 0, 0, 0 ), 1.1 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( 0, 0, - 50 ), 0 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( 0, 0, - 1.001 ), 0 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( - 1, - 1, - 1.001 ), 0 ) ), "Passed!" ); - assert.ok( ! a.intersectsSphere( new Sphere( new Vector3( - 1.1, - 1.1, - 1.001 ), 0 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( - 1.1, - 1.1, - 1.001 ), 0.5 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( 1, 1, - 1.001 ), 0 ) ), "Passed!" ); - assert.ok( ! a.intersectsSphere( new Sphere( new Vector3( 1.1, 1.1, - 1.001 ), 0 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( 1.1, 1.1, - 1.001 ), 0.5 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( 0, 0, - 99.999 ), 0 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( - 99.999, - 99.999, - 99.999 ), 0 ) ), "Passed!" ); - assert.ok( ! a.intersectsSphere( new Sphere( new Vector3( - 100.1, - 100.1, - 100.1 ), 0 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( - 100.1, - 100.1, - 100.1 ), 0.5 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( 99.999, 99.999, - 99.999 ), 0 ) ), "Passed!" ); - assert.ok( ! a.intersectsSphere( new Sphere( new Vector3( 100.1, 100.1, - 100.1 ), 0 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( 100.1, 100.1, - 100.1 ), 0.2 ) ), "Passed!" ); - assert.ok( ! a.intersectsSphere( new Sphere( new Vector3( 0, 0, - 101 ), 0 ) ), "Passed!" ); - assert.ok( a.intersectsSphere( new Sphere( new Vector3( 0, 0, - 101 ), 1.1 ) ), "Passed!" ); - - } ); - - QUnit.test( "intersectsObject", ( assert ) => { - - var m = new Matrix4().makePerspective( - 1, 1, 1, - 1, 1, 100 ); - var a = new Frustum().setFromMatrix( m ); - var object = new Mesh( new BoxGeometry( 1, 1, 1 ) ); - var intersects; - - intersects = a.intersectsObject( object ); - assert.notOk( intersects, "No intersection" ); - - object.position.set( - 1, - 1, - 1 ); - object.updateMatrixWorld(); - - intersects = a.intersectsObject( object ); - assert.ok( intersects, "Successful intersection" ); - - object.position.set( 1, 1, 1 ); - object.updateMatrixWorld(); - - intersects = a.intersectsObject( object ); - assert.notOk( intersects, "No intersection" ); - - } ); - - QUnit.test( "intersectsSprite", ( assert ) => { - - var m = new Matrix4().makePerspective( - 1, 1, 1, - 1, 1, 100 ); - var a = new Frustum().setFromMatrix( m ); - var sprite = new Sprite(); - var intersects; - - intersects = a.intersectsSprite( sprite ); - assert.notOk( intersects, "No intersection" ); - - sprite.position.set( - 1, - 1, - 1 ); - sprite.updateMatrixWorld(); - - intersects = a.intersectsSprite( sprite ); - assert.ok( intersects, "Successful intersection" ); - - } ); - - QUnit.test( "intersectsSphere", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "intersectsBox", ( assert ) => { - - var m = new Matrix4().makePerspective( - 1, 1, 1, - 1, 1, 100 ); - var a = new Frustum().setFromMatrix( m ); - var box = new Box3( zero3.clone(), one3.clone() ); - var intersects; - - intersects = a.intersectsBox( box ); - assert.notOk( intersects, "No intersection" ); - - box.translate( - 1, - 1, - 1 ); - - intersects = a.intersectsBox( box ); - assert.ok( intersects, "Successful intersection" ); - - } ); - - QUnit.test( "containsPoint", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author tschw - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Maths', () => { - - QUnit.module.todo( 'Interpolant', () => { - - // Since this is an abstract base class, we have to make it concrete in order - // to QUnit.test its functionality... - - function Mock( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - - Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); - - } - - Mock.prototype = Object.create( Interpolant.prototype ); - - Mock.prototype.intervalChanged_ = function intervalChanged( i1, t0, t1 ) { - - Mock.captureCall( arguments ); - - }; - - Mock.prototype.interpolate_ = function interpolate( i1, t0, t, t1 ) { - - Mock.captureCall( arguments ); - return this.copySampleValue_( i1 - 1 ); - - }; - - Mock.prototype.beforeStart_ = function beforeStart( i, t, t0 ) { - - Mock.captureCall( arguments ); - return this.copySampleValue_( i ); - - }; - - Mock.prototype.afterEnd_ = function afterEnd( i, tN, t ) { - - Mock.captureCall( arguments ); - return this.copySampleValue_( i ); - - }; - - // Call capturing facility - - Mock.calls = null; - - Mock.captureCall = function ( args ) { - - if ( Mock.calls !== null ) { - - Mock.calls.push( { - func: Mock.captureCall.caller.name, - args: Array.prototype.slice.call( args ) - } ); - - } - - }; - - // Tests - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "evaluate", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PRIVATE STUFF - QUnit.test( "DefaultSettings_", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getSettings_", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copySampleValue_", ( assert ) => { - - var interpolant = new Mock( null, [ 1, 11, 2, 22, 3, 33 ], 2, [] ); - - assert.deepEqual( interpolant.copySampleValue_( 0 ), [ 1, 11 ], "sample fetch (0)" ); - assert.deepEqual( interpolant.copySampleValue_( 1 ), [ 2, 22 ], "sample fetch (1)" ); - assert.deepEqual( interpolant.copySampleValue_( 2 ), [ 3, 33 ], "first sample (2)" ); - - } ); - - QUnit.test( "evaluate -> intervalChanged_ / interpolate_", ( assert ) => { - - var actual, expect; - - var interpolant = new Mock( [ 11, 22, 33, 44, 55, 66, 77, 88, 99 ], null, 0, null ); - - Mock.calls = []; - interpolant.evaluate( 11 ); - - actual = Mock.calls[ 0 ]; - expect = { - func: 'intervalChanged', - args: [ 1, 11, 22 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - actual = Mock.calls[ 1 ]; - expect = { - func: 'interpolate', - args: [ 1, 11, 11, 22 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 2, "no further calls" ); - - Mock.calls = []; - interpolant.evaluate( 12 ); // same interval - - actual = Mock.calls[ 0 ]; - expect = { - func: 'interpolate', - args: [ 1, 11, 12, 22 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 1, "no further calls" ); - - Mock.calls = []; - interpolant.evaluate( 22 ); // step forward - - actual = Mock.calls[ 0 ]; - expect = { - func: 'intervalChanged', - args: [ 2, 22, 33 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - actual = Mock.calls[ 1 ]; - expect = { - func: 'interpolate', - args: [ 2, 22, 22, 33 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 2 ); - - Mock.calls = []; - interpolant.evaluate( 21 ); // step back - - actual = Mock.calls[ 0 ]; - expect = { - func: 'intervalChanged', - args: [ 1, 11, 22 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - actual = Mock.calls[ 1 ]; - expect = { - func: 'interpolate', - args: [ 1, 11, 21, 22 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 2, "no further calls" ); - - Mock.calls = []; - interpolant.evaluate( 20 ); // same interval - - actual = Mock.calls[ 0 ]; - expect = { - func: 'interpolate', - args: [ 1, 11, 20, 22 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 1, "no further calls" ); - - Mock.calls = []; - interpolant.evaluate( 43 ); // two steps forward - - actual = Mock.calls[ 0 ]; - expect = { - func: 'intervalChanged', - args: [ 3, 33, 44 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - actual = Mock.calls[ 1 ]; - expect = { - func: 'interpolate', - args: [ 3, 33, 43, 44 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 2, "no further calls" ); - - Mock.calls = []; - interpolant.evaluate( 12 ); // two steps back - - actual = Mock.calls[ 0 ]; - expect = { - func: 'intervalChanged', - args: [ 1, 11, 22 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - actual = Mock.calls[ 1 ]; - expect = { - func: 'interpolate', - args: [ 1, 11, 12, 22 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 2, "no further calls" ); - - Mock.calls = []; - interpolant.evaluate( 77 ); // random access - - actual = Mock.calls[ 0 ]; - expect = { - func: 'intervalChanged', - args: [ 7, 77, 88 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - actual = Mock.calls[ 1 ]; - expect = { - func: 'interpolate', - args: [ 7, 77, 77, 88 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 2, "no further calls" ); - - Mock.calls = []; - interpolant.evaluate( 80 ); // same interval - - actual = Mock.calls[ 0 ]; - expect = { - func: 'interpolate', - args: [ 7, 77, 80, 88 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 1, "no further calls" ); - - Mock.calls = []; - interpolant.evaluate( 36 ); // random access - - actual = Mock.calls[ 0 ]; - expect = { - func: 'intervalChanged', - args: [ 3, 33, 44 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - actual = Mock.calls[ 1 ]; - expect = { - func: 'interpolate', - args: [ 3, 33, 36, 44 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 2, "no further calls" ); - - Mock.calls = []; - interpolant.evaluate( 24 ); // fast reset / loop (2nd) - - actual = Mock.calls[ 0 ]; - expect = { - func: 'intervalChanged', - args: [ 2, 22, 33 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - actual = Mock.calls[ 1 ]; - expect = { - func: 'interpolate', - args: [ 2, 22, 24, 33 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 2, "no further calls" ); - - Mock.calls = []; - interpolant.evaluate( 16 ); // fast reset / loop (2nd) - - actual = Mock.calls[ 0 ]; - expect = { - func: 'intervalChanged', - args: [ 1, 11, 22 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - actual = Mock.calls[ 1 ]; - expect = { - func: 'interpolate', - args: [ 1, 11, 16, 22 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 2, "no further calls" ); - - } ); - - QUnit.test( "evaulate -> beforeStart_ [once]", ( assert ) => { - - var actual, expect; - - var interpolant = new Mock( [ 11, 22, 33 ], null, 0, null ); - - Mock.calls = []; - interpolant.evaluate( 10 ); - - actual = Mock.calls[ 0 ]; - expect = { - func: 'beforeStart', - args: [ 0, 10, 11 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 1, "no further calls" ); - - // Check operation resumes normally and intervalChanged gets called - Mock.calls = []; - interpolant.evaluate( 11 ); - - actual = Mock.calls[ 0 ]; - expect = { - func: 'intervalChanged', - args: [ 1, 11, 22 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - actual = Mock.calls[ 1 ]; - expect = { - func: 'interpolate', - args: [ 1, 11, 11, 22 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 2, "no further calls" ); - - // Back off-bounds - Mock.calls = []; - interpolant.evaluate( 10 ); - - actual = Mock.calls[ 0 ]; - expect = { - func: 'beforeStart', - args: [ 0, 10, 11 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 1, "no further calls" ); - - } ); - - QUnit.test( "evaluate -> beforeStart_ [twice]", ( assert ) => { - - var actual, expect; - - var interpolant = new Mock( [ 11, 22, 33 ], null, 0, null ); - - Mock.calls = []; - interpolant.evaluate( 10 ); - - actual = Mock.calls[ 0 ]; - expect = { - func: 'beforeStart', - args: [ 0, 10, 11 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 1, "no further calls" ); - - Mock.calls = []; // again - consider changed state - interpolant.evaluate( 10 ); - - actual = Mock.calls[ 0 ]; - expect = { - func: 'beforeStart', - args: [ 0, 10, 11 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 1, "no further calls" ); - - // Check operation resumes normally and intervalChanged gets called - Mock.calls = []; - interpolant.evaluate( 11 ); - - actual = Mock.calls[ 0 ]; - expect = { - func: 'intervalChanged', - args: [ 1, 11, 22 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - actual = Mock.calls[ 1 ]; - expect = { - func: 'interpolate', - args: [ 1, 11, 11, 22 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 2, "no further calls" ); - - } ); - - QUnit.test( "evaluate -> afterEnd_ [once]", ( assert ) => { - - var actual, expect; - - var interpolant = new Mock( [ 11, 22, 33 ], null, 0, null ); - - Mock.calls = []; - interpolant.evaluate( 33 ); - - actual = Mock.calls[ 0 ]; - expect = { - func: 'afterEnd', - args: [ 2, 33, 33 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 1, "no further calls" ); - - // Check operation resumes normally and intervalChanged gets called - Mock.calls = []; - interpolant.evaluate( 32 ); - - actual = Mock.calls[ 0 ]; - expect = { - func: 'intervalChanged', - args: [ 2, 22, 33 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - actual = Mock.calls[ 1 ]; - expect = { - func: 'interpolate', - args: [ 2, 22, 32, 33 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 2, "no further calls" ); - - // Back off-bounds - Mock.calls = []; - interpolant.evaluate( 33 ); - - actual = Mock.calls[ 0 ]; - expect = { - func: 'afterEnd', - args: [ 2, 33, 33 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 1, "no further calls" ); - - } ); - - QUnit.test( "evaluate -> afterEnd_ [twice]", ( assert ) => { - - var actual, expect; - - var interpolant = new Mock( [ 11, 22, 33 ], null, 0, null ); - - Mock.calls = []; - interpolant.evaluate( 33 ); - - actual = Mock.calls[ 0 ]; - expect = { - func: 'afterEnd', - args: [ 2, 33, 33 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 1, "no further calls" ); - - Mock.calls = []; // again - consider changed state - interpolant.evaluate( 33 ); - - actual = Mock.calls[ 0 ]; - expect = { - func: 'afterEnd', - args: [ 2, 33, 33 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 1, "no further calls" ); - - // Check operation resumes normally and intervalChanged gets called - Mock.calls = []; - interpolant.evaluate( 32 ); - - actual = Mock.calls[ 0 ]; - expect = { - func: 'intervalChanged', - args: [ 2, 22, 33 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - actual = Mock.calls[ 1 ]; - expect = { - func: 'interpolate', - args: [ 2, 22, 32, 33 ] - }; - assert.deepEqual( actual, expect, JSON.stringify( expect ) ); - - assert.ok( Mock.calls.length === 2, "no further calls" ); - - } ); - - } ); - - } ); - - /** - * @author bhouston / http://exocortex.com - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Maths', () => { - - QUnit.module.todo( 'Line3', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - var a = new Line3(); - assert.ok( a.start.equals( zero3 ), "Passed!" ); - assert.ok( a.end.equals( zero3 ), "Passed!" ); - - var a = new Line3( two3.clone(), one3.clone() ); - assert.ok( a.start.equals( two3 ), "Passed!" ); - assert.ok( a.end.equals( one3 ), "Passed!" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "set", ( assert ) => { - - var a = new Line3(); - - a.set( one3, one3 ); - assert.ok( a.start.equals( one3 ), "Passed!" ); - assert.ok( a.end.equals( one3 ), "Passed!" ); - - } ); - - QUnit.test( "copy/equals", ( assert ) => { - - var a = new Line3( zero3.clone(), one3.clone() ); - var b = new Line3().copy( a ); - assert.ok( b.start.equals( zero3 ), "Passed!" ); - assert.ok( b.end.equals( one3 ), "Passed!" ); - - // ensure that it is a true copy - a.start = zero3; - a.end = one3; - assert.ok( b.start.equals( zero3 ), "Passed!" ); - assert.ok( b.end.equals( one3 ), "Passed!" ); - - } ); - - QUnit.test( "clone/equal", ( assert ) => { - - var a = new Line3(); - var b = new Line3( zero3, new Vector3( 1, 1, 1 ) ); - var c = new Line3( zero3, new Vector3( 1, 1, 0 ) ); - - assert.notOk( a.equals( b ), "Check a and b aren't equal" ); - assert.notOk( a.equals( c ), "Check a and c aren't equal" ); - assert.notOk( b.equals( c ), "Check b and c aren't equal" ); - - var a = b.clone(); - assert.ok( a.equals( b ), "Check a and b are equal after clone()" ); - assert.notOk( a.equals( c ), "Check a and c aren't equal after clone()" ); - - a.set( zero3, zero3 ); - assert.notOk( a.equals( b ), "Check a and b are not equal after modification" ); - - } ); - - QUnit.test( "getCenter", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "delta", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "distanceSq", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "distance", ( assert ) => { - - var a = new Line3( zero3, zero3 ); - var b = new Line3( zero3, one3 ); - var c = new Line3( one3.clone().negate(), one3 ); - var d = new Line3( two3.clone().multiplyScalar( - 2 ), two3.clone().negate() ); - - assert.numEqual( a.distance(), 0, "Check distance for zero-length line" ); - assert.numEqual( b.distance(), Math.sqrt( 3 ), "Check distance for simple line" ); - assert.numEqual( c.distance(), Math.sqrt( 12 ), "Check distance for negative to positive endpoints" ); - assert.numEqual( d.distance(), Math.sqrt( 12 ), "Check distance for negative to negative endpoints" ); - - } ); - - QUnit.test( "at", ( assert ) => { - - var a = new Line3( one3.clone(), new Vector3( 1, 1, 2 ) ); - - assert.ok( a.at( - 1 ).distanceTo( new Vector3( 1, 1, 0 ) ) < 0.0001, "Passed!" ); - assert.ok( a.at( 0 ).distanceTo( one3.clone() ) < 0.0001, "Passed!" ); - assert.ok( a.at( 1 ).distanceTo( new Vector3( 1, 1, 2 ) ) < 0.0001, "Passed!" ); - assert.ok( a.at( 2 ).distanceTo( new Vector3( 1, 1, 3 ) ) < 0.0001, "Passed!" ); - - } ); - - QUnit.test( "closestPointToPoint/closestPointToPointParameter", ( assert ) => { - - var a = new Line3( one3.clone(), new Vector3( 1, 1, 2 ) ); - - // nearby the ray - assert.ok( a.closestPointToPointParameter( zero3.clone(), true ) == 0, "Passed!" ); - var b1 = a.closestPointToPoint( zero3.clone(), true ); - assert.ok( b1.distanceTo( new Vector3( 1, 1, 1 ) ) < 0.0001, "Passed!" ); - - // nearby the ray - assert.ok( a.closestPointToPointParameter( zero3.clone(), false ) == - 1, "Passed!" ); - var b2 = a.closestPointToPoint( zero3.clone(), false ); - assert.ok( b2.distanceTo( new Vector3( 1, 1, 0 ) ) < 0.0001, "Passed!" ); - - // nearby the ray - assert.ok( a.closestPointToPointParameter( new Vector3( 1, 1, 5 ), true ) == 1, "Passed!" ); - var b = a.closestPointToPoint( new Vector3( 1, 1, 5 ), true ); - assert.ok( b.distanceTo( new Vector3( 1, 1, 2 ) ) < 0.0001, "Passed!" ); - - // exactly on the ray - assert.ok( a.closestPointToPointParameter( one3.clone(), true ) == 0, "Passed!" ); - var c = a.closestPointToPoint( one3.clone(), true ); - assert.ok( c.distanceTo( one3.clone() ) < 0.0001, "Passed!" ); - - } ); - - QUnit.test( "applyMatrix4", ( assert ) => { - - var a = new Line3( zero3.clone(), two3.clone() ); - var b = new Vector4( two3.x, two3.y, two3.z, 1 ); - var m = new Matrix4().makeTranslation( x, y, z ); - var v = new Vector3( x, y, z ); - - a.applyMatrix4( m ); - assert.ok( a.start.equals( v ), "Translation: check start" ); - assert.ok( a.end.equals( new Vector3( 2 + x, 2 + y, 2 + z ) ), "Translation: check start" ); - - // reset starting conditions - a.set( zero3.clone(), two3.clone() ); - m.makeRotationX( Math.PI ); - - a.applyMatrix4( m ); - b.applyMatrix4( m ); - - assert.ok( a.start.equals( zero3 ), "Rotation: check start" ); - assert.numEqual( a.end.x, b.x / b.w, "Rotation: check end.x" ); - assert.numEqual( a.end.y, b.y / b.w, "Rotation: check end.y" ); - assert.numEqual( a.end.z, b.z / b.w, "Rotation: check end.z" ); - - // reset starting conditions - a.set( zero3.clone(), two3.clone() ); - b.set( two3.x, two3.y, two3.z, 1 ); - m.setPosition( v ); - - a.applyMatrix4( m ); - b.applyMatrix4( m ); - - assert.ok( a.start.equals( v ), "Both: check start" ); - assert.numEqual( a.end.x, b.x / b.w, "Both: check end.x" ); - assert.numEqual( a.end.y, b.y / b.w, "Both: check end.y" ); - assert.numEqual( a.end.z, b.z / b.w, "Both: check end.z" ); - - } ); - - QUnit.test( "equals", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author humbletim / https://github.com/humbletim - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Maths', () => { - - QUnit.module.todo( 'Math', () => { - - // PUBLIC STUFF - QUnit.test( "generateUUID", ( assert ) => { - - var a = _Math.generateUUID(); - var regex = /[A-Z0-9]{8}-[A-Z0-9]{4}-4[A-Z0-9]{3}-[A-Z0-9]{4}-[A-Z0-9]{12}/i; - // note the fixed '4' here ----------^ - - assert.ok( regex.test( a ), "Generated UUID matches the expected pattern" ); - - } ); - - QUnit.test( "clamp", ( assert ) => { - - assert.strictEqual( _Math.clamp( 0.5, 0, 1 ), 0.5, "Value already within limits" ); - assert.strictEqual( _Math.clamp( 0, 0, 1 ), 0, "Value equal to one limit" ); - assert.strictEqual( _Math.clamp( - 0.1, 0, 1 ), 0, "Value too low" ); - assert.strictEqual( _Math.clamp( 1.1, 0, 1 ), 1, "Value too high" ); - - } ); - - QUnit.test( "euclideanModulo", ( assert ) => { - - assert.ok( isNaN( _Math.euclideanModulo( 6, 0 ) ), "Division by zero returns NaN" ); - assert.strictEqual( _Math.euclideanModulo( 6, 1 ), 0, "Divison by trivial divisor" ); - assert.strictEqual( _Math.euclideanModulo( 6, 2 ), 0, "Divison by non-trivial divisor" ); - assert.strictEqual( _Math.euclideanModulo( 6, 5 ), 1, "Divison by itself - 1" ); - assert.strictEqual( _Math.euclideanModulo( 6, 6 ), 0, "Divison by itself" ); - assert.strictEqual( _Math.euclideanModulo( 6, 7 ), 6, "Divison by itself + 1" ); - - } ); - - QUnit.test( "mapLinear", ( assert ) => { - - assert.strictEqual( _Math.mapLinear( 0.5, 0, 1, 0, 10 ), 5, "Value within range" ); - assert.strictEqual( _Math.mapLinear( 0.0, 0, 1, 0, 10 ), 0, "Value equal to lower boundary" ); - assert.strictEqual( _Math.mapLinear( 1.0, 0, 1, 0, 10 ), 10, "Value equal to upper boundary" ); - - } ); - - QUnit.test( "lerp", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "smoothstep", ( assert ) => { - - assert.strictEqual( _Math.smoothstep( - 1, 0, 2 ), 0, "Value lower than minimum" ); - assert.strictEqual( _Math.smoothstep( 0, 0, 2 ), 0, "Value equal to minimum" ); - assert.strictEqual( _Math.smoothstep( 0.5, 0, 2 ), 0.15625, "Value within limits" ); - assert.strictEqual( _Math.smoothstep( 1, 0, 2 ), 0.5, "Value within limits" ); - assert.strictEqual( _Math.smoothstep( 1.5, 0, 2 ), 0.84375, "Value within limits" ); - assert.strictEqual( _Math.smoothstep( 2, 0, 2 ), 1, "Value equal to maximum" ); - assert.strictEqual( _Math.smoothstep( 3, 0, 2 ), 1, "Value highter than maximum" ); - - } ); - - QUnit.test( "smootherstep", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "randInt", ( assert ) => { - - var low = 1, high = 3; - var a = _Math.randInt( low, high ); - - assert.ok( a >= low, "Value equal to or higher than lower limit" ); - assert.ok( a <= high, "Value equal to or lower than upper limit" ); - - } ); - - QUnit.test( "randFloat", ( assert ) => { - - var low = 1, high = 3; - var a = _Math.randFloat( low, high ); - - assert.ok( a >= low, "Value equal to or higher than lower limit" ); - assert.ok( a <= high, "Value equal to or lower than upper limit" ); - - } ); - - QUnit.test( "randFloatSpread", ( assert ) => { - - var a = _Math.randFloatSpread( 3 ); - - assert.ok( a > - 3 / 2, "Value higher than lower limit" ); - assert.ok( a < 3 / 2, "Value lower than upper limit" ); - - } ); - - QUnit.test( "degToRad", ( assert ) => { - - assert.strictEqual( _Math.degToRad( 0 ), 0, "0 degrees" ); - assert.strictEqual( _Math.degToRad( 90 ), Math.PI / 2, "90 degrees" ); - assert.strictEqual( _Math.degToRad( 180 ), Math.PI, "180 degrees" ); - assert.strictEqual( _Math.degToRad( 360 ), Math.PI * 2, "360 degrees" ); - - } ); - - QUnit.test( "radToDeg", ( assert ) => { - - assert.strictEqual( _Math.radToDeg( 0 ), 0, "0 radians" ); - assert.strictEqual( _Math.radToDeg( Math.PI / 2 ), 90, "Math.PI / 2 radians" ); - assert.strictEqual( _Math.radToDeg( Math.PI ), 180, "Math.PI radians" ); - assert.strictEqual( _Math.radToDeg( Math.PI * 2 ), 360, "Math.PI * 2 radians" ); - - } ); - - QUnit.test( "isPowerOfTwo", ( assert ) => { - - assert.strictEqual( _Math.isPowerOfTwo( 0 ), false, "0 is not a PoT" ); - assert.strictEqual( _Math.isPowerOfTwo( 1 ), true, "1 is a PoT" ); - assert.strictEqual( _Math.isPowerOfTwo( 2 ), true, "2 is a PoT" ); - assert.strictEqual( _Math.isPowerOfTwo( 3 ), false, "3 is not a PoT" ); - assert.strictEqual( _Math.isPowerOfTwo( 4 ), true, "4 is a PoT" ); - - } ); - - QUnit.test( "ceilPowerOfTwo", ( assert ) => { - - assert.strictEqual( _Math.ceilPowerOfTwo( 1 ), 1, "Closest higher PoT to 1 is 1" ); - assert.strictEqual( _Math.ceilPowerOfTwo( 3 ), 4, "Closest higher PoT to 3 is 4" ); - assert.strictEqual( _Math.ceilPowerOfTwo( 4 ), 4, "Closest higher PoT to 4 is 4" ); - - } ); - - QUnit.test( "floorPowerOfTwo", ( assert ) => { - - assert.strictEqual( _Math.floorPowerOfTwo( 1 ), 1, "Closest lower PoT to 1 is 1" ); - assert.strictEqual( _Math.floorPowerOfTwo( 3 ), 2, "Closest lower PoT to 3 is 2" ); - assert.strictEqual( _Math.floorPowerOfTwo( 4 ), 4, "Closest lower PoT to 4 is 4" ); - - } ); - - } ); - - } ); - - /** - * @author bhouston / http://exocortex.com - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - function matrixEquals3( a, b, tolerance ) { - - tolerance = tolerance || 0.0001; - if ( a.elements.length != b.elements.length ) { - - return false; - - } - - for ( var i = 0, il = a.elements.length; i < il; i ++ ) { - - var delta = a.elements[ i ] - b.elements[ i ]; - if ( delta > tolerance ) { - - return false; - - } - - } - - return true; - - } - - function toMatrix4( m3 ) { - - var result = new Matrix4(); - var re = result.elements; - var me = m3.elements; - re[ 0 ] = me[ 0 ]; - re[ 1 ] = me[ 1 ]; - re[ 2 ] = me[ 2 ]; - re[ 4 ] = me[ 3 ]; - re[ 5 ] = me[ 4 ]; - re[ 6 ] = me[ 5 ]; - re[ 8 ] = me[ 6 ]; - re[ 9 ] = me[ 7 ]; - re[ 10 ] = me[ 8 ]; - - return result; - - } - - QUnit.module( 'Maths', () => { - - QUnit.module.todo( 'Matrix3', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - var a = new Matrix3(); - assert.ok( a.determinant() == 1, "Passed!" ); - - var b = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); - assert.ok( b.elements[ 0 ] == 0 ); - assert.ok( b.elements[ 1 ] == 3 ); - assert.ok( b.elements[ 2 ] == 6 ); - assert.ok( b.elements[ 3 ] == 1 ); - assert.ok( b.elements[ 4 ] == 4 ); - assert.ok( b.elements[ 5 ] == 7 ); - assert.ok( b.elements[ 6 ] == 2 ); - assert.ok( b.elements[ 7 ] == 5 ); - assert.ok( b.elements[ 8 ] == 8 ); - - assert.ok( ! matrixEquals3( a, b ), "Passed!" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isMatrix3", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "set", ( assert ) => { - - var b = new Matrix3(); - assert.ok( b.determinant() == 1, "Passed!" ); - - b.set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); - assert.ok( b.elements[ 0 ] == 0 ); - assert.ok( b.elements[ 1 ] == 3 ); - assert.ok( b.elements[ 2 ] == 6 ); - assert.ok( b.elements[ 3 ] == 1 ); - assert.ok( b.elements[ 4 ] == 4 ); - assert.ok( b.elements[ 5 ] == 7 ); - assert.ok( b.elements[ 6 ] == 2 ); - assert.ok( b.elements[ 7 ] == 5 ); - assert.ok( b.elements[ 8 ] == 8 ); - - } ); - - QUnit.test( "identity", ( assert ) => { - - var b = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); - assert.ok( b.elements[ 0 ] == 0 ); - assert.ok( b.elements[ 1 ] == 3 ); - assert.ok( b.elements[ 2 ] == 6 ); - assert.ok( b.elements[ 3 ] == 1 ); - assert.ok( b.elements[ 4 ] == 4 ); - assert.ok( b.elements[ 5 ] == 7 ); - assert.ok( b.elements[ 6 ] == 2 ); - assert.ok( b.elements[ 7 ] == 5 ); - assert.ok( b.elements[ 8 ] == 8 ); - - var a = new Matrix3(); - assert.ok( ! matrixEquals3( a, b ), "Passed!" ); - - b.identity(); - assert.ok( matrixEquals3( a, b ), "Passed!" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - var a = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); - var b = a.clone(); - - assert.ok( matrixEquals3( a, b ), "Passed!" ); - - // ensure that it is a true copy - a.elements[ 0 ] = 2; - assert.ok( ! matrixEquals3( a, b ), "Passed!" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - var a = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); - var b = new Matrix3().copy( a ); - - assert.ok( matrixEquals3( a, b ), "Passed!" ); - - // ensure that it is a true copy - a.elements[ 0 ] = 2; - assert.ok( ! matrixEquals3( a, b ), "Passed!" ); - - } ); - - QUnit.test( "setFromMatrix4", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "applyToBufferAttribute", ( assert ) => { - - var a = new Matrix3().set( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); - var attr = new Float32BufferAttribute( [ 1, 2, 1, 3, 0, 3 ], 3 ); - var expected = new Float32Array( [ 8, 20, 32, 12, 30, 48 ] ); - - var applied = a.applyToBufferAttribute( attr ); - - assert.deepEqual( applied.array, expected, "Check resulting buffer" ); - - } ); - - QUnit.test( "multiply/premultiply", ( assert ) => { - - // both simply just wrap multiplyMatrices - var a = new Matrix3().set( 2, 3, 5, 7, 11, 13, 17, 19, 23 ); - var b = new Matrix3().set( 29, 31, 37, 41, 43, 47, 53, 59, 61 ); - var expectedMultiply = [ 446, 1343, 2491, 486, 1457, 2701, 520, 1569, 2925 ]; - var expectedPremultiply = [ 904, 1182, 1556, 1131, 1489, 1967, 1399, 1845, 2435 ]; - - a.multiply( b ); - assert.deepEqual( a.elements, expectedMultiply, "multiply: check result" ); - - a.set( 2, 3, 5, 7, 11, 13, 17, 19, 23 ); - a.premultiply( b ); - assert.deepEqual( a.elements, expectedPremultiply, "premultiply: check result" ); - - } ); - - QUnit.test( "multiplyMatrices", ( assert ) => { - - // Reference: - // - // #!/usr/bin/env python - // from __future__ import print_function - // import numpy as np - // print( - // np.dot( - // np.reshape([2, 3, 5, 7, 11, 13, 17, 19, 23], (3, 3)), - // np.reshape([29, 31, 37, 41, 43, 47, 53, 59, 61], (3, 3)) - // ) - // ) - // - // [[ 446 486 520] - // [1343 1457 1569] - // [2491 2701 2925]] - var lhs = new Matrix3().set( 2, 3, 5, 7, 11, 13, 17, 19, 23 ); - var rhs = new Matrix3().set( 29, 31, 37, 41, 43, 47, 53, 59, 61 ); - var ans = new Matrix3(); - - ans.multiplyMatrices( lhs, rhs ); - - assert.ok( ans.elements[ 0 ] == 446 ); - assert.ok( ans.elements[ 1 ] == 1343 ); - assert.ok( ans.elements[ 2 ] == 2491 ); - assert.ok( ans.elements[ 3 ] == 486 ); - assert.ok( ans.elements[ 4 ] == 1457 ); - assert.ok( ans.elements[ 5 ] == 2701 ); - assert.ok( ans.elements[ 6 ] == 520 ); - assert.ok( ans.elements[ 7 ] == 1569 ); - assert.ok( ans.elements[ 8 ] == 2925 ); - - } ); - - QUnit.test( "multiplyScalar", ( assert ) => { - - var b = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); - assert.ok( b.elements[ 0 ] == 0 ); - assert.ok( b.elements[ 1 ] == 3 ); - assert.ok( b.elements[ 2 ] == 6 ); - assert.ok( b.elements[ 3 ] == 1 ); - assert.ok( b.elements[ 4 ] == 4 ); - assert.ok( b.elements[ 5 ] == 7 ); - assert.ok( b.elements[ 6 ] == 2 ); - assert.ok( b.elements[ 7 ] == 5 ); - assert.ok( b.elements[ 8 ] == 8 ); - - b.multiplyScalar( 2 ); - assert.ok( b.elements[ 0 ] == 0 * 2 ); - assert.ok( b.elements[ 1 ] == 3 * 2 ); - assert.ok( b.elements[ 2 ] == 6 * 2 ); - assert.ok( b.elements[ 3 ] == 1 * 2 ); - assert.ok( b.elements[ 4 ] == 4 * 2 ); - assert.ok( b.elements[ 5 ] == 7 * 2 ); - assert.ok( b.elements[ 6 ] == 2 * 2 ); - assert.ok( b.elements[ 7 ] == 5 * 2 ); - assert.ok( b.elements[ 8 ] == 8 * 2 ); - - } ); - - QUnit.test( "determinant", ( assert ) => { - - var a = new Matrix3(); - assert.ok( a.determinant() == 1, "Passed!" ); - - a.elements[ 0 ] = 2; - assert.ok( a.determinant() == 2, "Passed!" ); - - a.elements[ 0 ] = 0; - assert.ok( a.determinant() == 0, "Passed!" ); - - // calculated via http://www.euclideanspace.com/maths/algebra/matrix/functions/determinant/threeD/index.htm - a.set( 2, 3, 4, 5, 13, 7, 8, 9, 11 ); - assert.ok( a.determinant() == - 73, "Passed!" ); - - } ); - - QUnit.test( "getInverse", ( assert ) => { - - var identity = new Matrix3(); - var identity4 = new Matrix4(); - var a = new Matrix3(); - var b = new Matrix3().set( 0, 0, 0, 0, 0, 0, 0, 0, 0 ); - var c = new Matrix3().set( 0, 0, 0, 0, 0, 0, 0, 0, 0 ); - - b.getInverse( a, false ); - assert.ok( matrixEquals3( a, identity ), "Matrix a is identity matrix" ); - - try { - - b.getInverse( c, true ); - assert.ok( false, "Should never get here !" ); // should never get here. - - } catch ( err ) { - - assert.ok( true, "Passed: " + err ); - - } - - var testMatrices = [ - new Matrix4().makeRotationX( 0.3 ), - new Matrix4().makeRotationX( - 0.3 ), - new Matrix4().makeRotationY( 0.3 ), - new Matrix4().makeRotationY( - 0.3 ), - new Matrix4().makeRotationZ( 0.3 ), - new Matrix4().makeRotationZ( - 0.3 ), - new Matrix4().makeScale( 1, 2, 3 ), - new Matrix4().makeScale( 1 / 8, 1 / 2, 1 / 3 ) - ]; - - for ( var i = 0, il = testMatrices.length; i < il; i ++ ) { - - var m = testMatrices[ i ]; - - a.setFromMatrix4( m ); - var mInverse3 = b.getInverse( a ); - - var mInverse = toMatrix4( mInverse3 ); - - // the determinant of the inverse should be the reciprocal - assert.ok( Math.abs( a.determinant() * mInverse3.determinant() - 1 ) < 0.0001, "Passed!" ); - assert.ok( Math.abs( m.determinant() * mInverse.determinant() - 1 ) < 0.0001, "Passed!" ); - - var mProduct = new Matrix4().multiplyMatrices( m, mInverse ); - assert.ok( Math.abs( mProduct.determinant() - 1 ) < 0.0001, "Passed!" ); - assert.ok( matrixEquals3( mProduct, identity4 ), "Passed!" ); - - } - - } ); - - QUnit.test( "transpose", ( assert ) => { - - var a = new Matrix3(); - var b = a.clone().transpose(); - assert.ok( matrixEquals3( a, b ), "Passed!" ); - - var b = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); - var c = b.clone().transpose(); - assert.ok( ! matrixEquals3( b, c ), "Passed!" ); - c.transpose(); - assert.ok( matrixEquals3( b, c ), "Passed!" ); - - } ); - - QUnit.test( "getNormalMatrix", ( assert ) => { - - var a = new Matrix3(); - var b = new Matrix4().set( - 2, 3, 5, 7, - 11, 13, 17, 19, - 23, 29, 31, 37, - 41, 43, 47, 57 - ); - var expected = new Matrix3().set( - - 1.2857142857142856, 0.7142857142857143, 0.2857142857142857, - 0.7428571428571429, - 0.7571428571428571, 0.15714285714285714, - - 0.19999999999999998, 0.3, - 0.09999999999999999 - ); - - a.getNormalMatrix( b ); - assert.ok( matrixEquals3( a, expected ), "Check resulting Matrix3" ); - - } ); - - QUnit.test( "transposeIntoArray", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setUvTransform", ( assert ) => { - - var a = new Matrix3().set( - 0.1767766952966369, 0.17677669529663687, 0.32322330470336313, - - 0.17677669529663687, 0.1767766952966369, 0.5, - 0, 0, 1 - ); - var b = new Matrix3(); - var params = { - centerX: 0.5, - centerY: 0.5, - offsetX: 0, - offsetY: 0, - repeatX: 0.25, - repeatY: 0.25, - rotation: 0.7753981633974483 - }; - var expected = new Matrix3().set( - 0.1785355940258599, 0.17500011904519763, 0.32323214346447127, - - 0.17500011904519763, 0.1785355940258599, 0.4982322625096689, - 0, 0, 1 - ); - - a.setUvTransform( - params.offsetX, params.offsetY, - params.repeatX, params.repeatY, - params.rotation, - params.centerX, params.centerY - ); - - b.identity() - .translate( - params.centerX, - params.centerY ) - .rotate( params.rotation ) - .scale( params.repeatX, params.repeatY ) - .translate( params.centerX, params.centerY ) - .translate( params.offsetX, params.offsetY ); - - assert.ok( matrixEquals3( a, expected ), "Check direct method" ); - assert.ok( matrixEquals3( b, expected ), "Check indirect method" ); - - } ); - - QUnit.test( "scale", ( assert ) => { - - var a = new Matrix3().set( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); - var expected = new Matrix3().set( - 0.25, 0.5, 0.75, - 1, 1.25, 1.5, - 7, 8, 9 - ); - - a.scale( 0.25, 0.25 ); - assert.ok( matrixEquals3( a, expected ), "Check scaling result" ); - - } ); - - QUnit.test( "rotate", ( assert ) => { - - var a = new Matrix3().set( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); - var expected = new Matrix3().set( - 3.5355339059327373, 4.949747468305833, 6.363961030678928, - 2.121320343559643, 2.121320343559643, 2.1213203435596433, - 7, 8, 9 - ); - - a.rotate( Math.PI / 4 ); - assert.ok( matrixEquals3( a, expected ), "Check rotated result" ); - - } ); - - QUnit.test( "translate", ( assert ) => { - - var a = new Matrix3().set( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); - var expected = new Matrix3().set( 22, 26, 30, 53, 61, 69, 7, 8, 9 ); - - a.translate( 3, 7 ); - assert.ok( matrixEquals3( a, expected ), "Check translation result" ); - - } ); - - QUnit.test( "equals", ( assert ) => { - - var a = new Matrix3().set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); - var b = new Matrix3().set( 0, - 1, 2, 3, 4, 5, 6, 7, 8 ); - - assert.notOk( a.equals( b ), "Check that a does not equal b" ); - assert.notOk( b.equals( a ), "Check that b does not equal a" ); - - a.copy( b ); - assert.ok( a.equals( b ), "Check that a equals b after copy()" ); - assert.ok( b.equals( a ), "Check that b equals a after copy()" ); - - } ); - - QUnit.test( "fromArray", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "toArray", ( assert ) => { - - var a = new Matrix3().set( 1, 2, 3, 4, 5, 6, 7, 8, 9 ); - var noOffset = [ 1, 4, 7, 2, 5, 8, 3, 6, 9 ]; - var withOffset = [ undefined, 1, 4, 7, 2, 5, 8, 3, 6, 9 ]; - - var array = a.toArray(); - assert.deepEqual( array, noOffset, "No array, no offset" ); - - var array = []; - a.toArray( array ); - assert.deepEqual( array, noOffset, "With array, no offset" ); - - var array = []; - a.toArray( array, 1 ); - assert.deepEqual( array, withOffset, "With array, with offset" ); - - } ); - - } ); - - } ); - - /** - * @author bhouston / http://exocortex.com - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - function matrixEquals4$1( a, b, tolerance ) { - - tolerance = tolerance || 0.0001; - if ( a.elements.length != b.elements.length ) { - - return false; - - } - - for ( var i = 0, il = a.elements.length; i < il; i ++ ) { - - var delta = a.elements[ i ] - b.elements[ i ]; - if ( delta > tolerance ) { - - return false; - - } - - } - - return true; - - } - - // from Euler.js - function eulerEquals$1( a, b, tolerance ) { - - tolerance = tolerance || 0.0001; - var diff = Math.abs( a.x - b.x ) + Math.abs( a.y - b.y ) + Math.abs( a.z - b.z ); - return ( diff < tolerance ); - - } - - QUnit.module( 'Maths', () => { - - QUnit.module.todo( 'Matrix4', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - var a = new Matrix4(); - assert.ok( a.determinant() == 1, "Passed!" ); - - var b = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); - assert.ok( b.elements[ 0 ] == 0 ); - assert.ok( b.elements[ 1 ] == 4 ); - assert.ok( b.elements[ 2 ] == 8 ); - assert.ok( b.elements[ 3 ] == 12 ); - assert.ok( b.elements[ 4 ] == 1 ); - assert.ok( b.elements[ 5 ] == 5 ); - assert.ok( b.elements[ 6 ] == 9 ); - assert.ok( b.elements[ 7 ] == 13 ); - assert.ok( b.elements[ 8 ] == 2 ); - assert.ok( b.elements[ 9 ] == 6 ); - assert.ok( b.elements[ 10 ] == 10 ); - assert.ok( b.elements[ 11 ] == 14 ); - assert.ok( b.elements[ 12 ] == 3 ); - assert.ok( b.elements[ 13 ] == 7 ); - assert.ok( b.elements[ 14 ] == 11 ); - assert.ok( b.elements[ 15 ] == 15 ); - - assert.ok( ! matrixEquals4$1( a, b ), "Passed!" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isMatrix4", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "set", ( assert ) => { - - var b = new Matrix4(); - assert.ok( b.determinant() == 1, "Passed!" ); - - b.set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); - assert.ok( b.elements[ 0 ] == 0 ); - assert.ok( b.elements[ 1 ] == 4 ); - assert.ok( b.elements[ 2 ] == 8 ); - assert.ok( b.elements[ 3 ] == 12 ); - assert.ok( b.elements[ 4 ] == 1 ); - assert.ok( b.elements[ 5 ] == 5 ); - assert.ok( b.elements[ 6 ] == 9 ); - assert.ok( b.elements[ 7 ] == 13 ); - assert.ok( b.elements[ 8 ] == 2 ); - assert.ok( b.elements[ 9 ] == 6 ); - assert.ok( b.elements[ 10 ] == 10 ); - assert.ok( b.elements[ 11 ] == 14 ); - assert.ok( b.elements[ 12 ] == 3 ); - assert.ok( b.elements[ 13 ] == 7 ); - assert.ok( b.elements[ 14 ] == 11 ); - assert.ok( b.elements[ 15 ] == 15 ); - - } ); - - QUnit.test( "identity", ( assert ) => { - - var b = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); - assert.ok( b.elements[ 0 ] == 0 ); - assert.ok( b.elements[ 1 ] == 4 ); - assert.ok( b.elements[ 2 ] == 8 ); - assert.ok( b.elements[ 3 ] == 12 ); - assert.ok( b.elements[ 4 ] == 1 ); - assert.ok( b.elements[ 5 ] == 5 ); - assert.ok( b.elements[ 6 ] == 9 ); - assert.ok( b.elements[ 7 ] == 13 ); - assert.ok( b.elements[ 8 ] == 2 ); - assert.ok( b.elements[ 9 ] == 6 ); - assert.ok( b.elements[ 10 ] == 10 ); - assert.ok( b.elements[ 11 ] == 14 ); - assert.ok( b.elements[ 12 ] == 3 ); - assert.ok( b.elements[ 13 ] == 7 ); - assert.ok( b.elements[ 14 ] == 11 ); - assert.ok( b.elements[ 15 ] == 15 ); - - var a = new Matrix4(); - assert.ok( ! matrixEquals4$1( a, b ), "Passed!" ); - - b.identity(); - assert.ok( matrixEquals4$1( a, b ), "Passed!" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - var a = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); - var b = a.clone(); - - assert.ok( matrixEquals4$1( a, b ), "Passed!" ); - - // ensure that it is a true copy - a.elements[ 0 ] = 2; - assert.ok( ! matrixEquals4$1( a, b ), "Passed!" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - var a = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); - var b = new Matrix4().copy( a ); - - assert.ok( matrixEquals4$1( a, b ), "Passed!" ); - - // ensure that it is a true copy - a.elements[ 0 ] = 2; - assert.ok( ! matrixEquals4$1( a, b ), "Passed!" ); - - } ); - - QUnit.test( "copyPosition", ( assert ) => { - - var a = new Matrix4().set( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); - var b = new Matrix4().set( 1, 2, 3, 0, 5, 6, 7, 0, 9, 10, 11, 0, 13, 14, 15, 16 ); - - assert.notOk( matrixEquals4$1( a, b ), "a and b initially not equal" ); - - b.copyPosition( a ); - assert.ok( matrixEquals4$1( a, b ), "a and b equal after copyPosition()" ); - - } ); - - QUnit.test( "makeBasis/extractBasis", ( assert ) => { - - var identityBasis = [ new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ) ]; - var a = new Matrix4().makeBasis( identityBasis[ 0 ], identityBasis[ 1 ], identityBasis[ 2 ] ); - var identity = new Matrix4(); - assert.ok( matrixEquals4$1( a, identity ), "Passed!" ); - - var testBases = [[ new Vector3( 0, 1, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ) ]]; - for ( var i = 0; i < testBases.length; i ++ ) { - - var testBasis = testBases[ i ]; - var b = new Matrix4().makeBasis( testBasis[ 0 ], testBasis[ 1 ], testBasis[ 2 ] ); - var outBasis = [ new Vector3(), new Vector3(), new Vector3() ]; - b.extractBasis( outBasis[ 0 ], outBasis[ 1 ], outBasis[ 2 ] ); - // check what goes in, is what comes out. - for ( var j = 0; j < outBasis.length; j ++ ) { - - assert.ok( outBasis[ j ].equals( testBasis[ j ] ), "Passed!" ); - - } - - // get the basis out the hard war - for ( var j = 0; j < identityBasis.length; j ++ ) { - - outBasis[ j ].copy( identityBasis[ j ] ); - outBasis[ j ].applyMatrix4( b ); - - } - // did the multiply method of basis extraction work? - for ( var j = 0; j < outBasis.length; j ++ ) { - - assert.ok( outBasis[ j ].equals( testBasis[ j ] ), "Passed!" ); - - } - - } - - } ); - - QUnit.test( "extractRotation", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "makeRotationFromEuler/extractRotation", ( assert ) => { - - var testValues = [ - new Euler( 0, 0, 0, "XYZ" ), - new Euler( 1, 0, 0, "XYZ" ), - new Euler( 0, 1, 0, "ZYX" ), - new Euler( 0, 0, 0.5, "YZX" ), - new Euler( 0, 0, - 0.5, "YZX" ) - ]; - - for ( var i = 0; i < testValues.length; i ++ ) { - - var v = testValues[ i ]; - - var m = new Matrix4().makeRotationFromEuler( v ); - - var v2 = new Euler().setFromRotationMatrix( m, v.order ); - var m2 = new Matrix4().makeRotationFromEuler( v2 ); - - assert.ok( matrixEquals4$1( m, m2, eps ), "makeRotationFromEuler #" + i + ": original and Euler-derived matrices are equal" ); - assert.ok( eulerEquals$1( v, v2, eps ), "makeRotationFromEuler #" + i + ": original and matrix-derived Eulers are equal" ); - - var m3 = new Matrix4().extractRotation( m2 ); - var v3 = new Euler().setFromRotationMatrix( m3, v.order ); - - assert.ok( matrixEquals4$1( m, m3, eps ), "extractRotation #" + i + ": original and extracted matrices are equal" ); - assert.ok( eulerEquals$1( v, v3, eps ), "extractRotation #" + i + ": original and extracted Eulers are equal" ); - - } - - } ); - - QUnit.test( "lookAt", ( assert ) => { - - var a = new Matrix4(); - var expected = new Matrix4().identity(); - var eye = new Vector3( 0, 0, 0 ); - var target = new Vector3( 0, 1, - 1 ); - var up = new Vector3( 0, 1, 0 ); - - a.lookAt( eye, target, up ); - var rotation = new Euler().setFromRotationMatrix( a ); - assert.numEqual( rotation.x * ( 180 / Math.PI ), 45, "Check the rotation" ); - - // eye and target are in the same position - eye.copy( target ); - a.lookAt( eye, target, up ); - assert.ok( matrixEquals4$1( a, expected ), "Check the result for eye == target" ); - - // up and z are parallel - eye.set( 0, 1, 0 ); - target.set( 0, 0, 0 ); - a.lookAt( eye, target, up ); - expected.set( - 1, 0, 0, 0, - 0, 0.0001, 1, 0, - 0, - 1, 0.0001, 0, - 0, 0, 0, 1 - ); - assert.ok( matrixEquals4$1( a, expected ), "Check the result for when up and z are parallel" ); - - } ); - - QUnit.test( "multiply", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "premultiply", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "multiplyMatrices", ( assert ) => { - - // Reference: - // - // #!/usr/bin/env python - // from __future__ import print_function - // import numpy as np - // print( - // np.dot( - // np.reshape([2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53], (4, 4)), - // np.reshape([59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131], (4, 4)) - // ) - // ) - // - // [[ 1585 1655 1787 1861] - // [ 5318 5562 5980 6246] - // [10514 11006 11840 12378] - // [15894 16634 17888 18710]] - var lhs = new Matrix4().set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 ); - var rhs = new Matrix4().set( 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131 ); - var ans = new Matrix4(); - - ans.multiplyMatrices( lhs, rhs ); - - assert.ok( ans.elements[ 0 ] == 1585 ); - assert.ok( ans.elements[ 1 ] == 5318 ); - assert.ok( ans.elements[ 2 ] == 10514 ); - assert.ok( ans.elements[ 3 ] == 15894 ); - assert.ok( ans.elements[ 4 ] == 1655 ); - assert.ok( ans.elements[ 5 ] == 5562 ); - assert.ok( ans.elements[ 6 ] == 11006 ); - assert.ok( ans.elements[ 7 ] == 16634 ); - assert.ok( ans.elements[ 8 ] == 1787 ); - assert.ok( ans.elements[ 9 ] == 5980 ); - assert.ok( ans.elements[ 10 ] == 11840 ); - assert.ok( ans.elements[ 11 ] == 17888 ); - assert.ok( ans.elements[ 12 ] == 1861 ); - assert.ok( ans.elements[ 13 ] == 6246 ); - assert.ok( ans.elements[ 14 ] == 12378 ); - assert.ok( ans.elements[ 15 ] == 18710 ); - - } ); - - QUnit.test( "multiplyScalar", ( assert ) => { - - var b = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); - assert.ok( b.elements[ 0 ] == 0 ); - assert.ok( b.elements[ 1 ] == 4 ); - assert.ok( b.elements[ 2 ] == 8 ); - assert.ok( b.elements[ 3 ] == 12 ); - assert.ok( b.elements[ 4 ] == 1 ); - assert.ok( b.elements[ 5 ] == 5 ); - assert.ok( b.elements[ 6 ] == 9 ); - assert.ok( b.elements[ 7 ] == 13 ); - assert.ok( b.elements[ 8 ] == 2 ); - assert.ok( b.elements[ 9 ] == 6 ); - assert.ok( b.elements[ 10 ] == 10 ); - assert.ok( b.elements[ 11 ] == 14 ); - assert.ok( b.elements[ 12 ] == 3 ); - assert.ok( b.elements[ 13 ] == 7 ); - assert.ok( b.elements[ 14 ] == 11 ); - assert.ok( b.elements[ 15 ] == 15 ); - - b.multiplyScalar( 2 ); - assert.ok( b.elements[ 0 ] == 0 * 2 ); - assert.ok( b.elements[ 1 ] == 4 * 2 ); - assert.ok( b.elements[ 2 ] == 8 * 2 ); - assert.ok( b.elements[ 3 ] == 12 * 2 ); - assert.ok( b.elements[ 4 ] == 1 * 2 ); - assert.ok( b.elements[ 5 ] == 5 * 2 ); - assert.ok( b.elements[ 6 ] == 9 * 2 ); - assert.ok( b.elements[ 7 ] == 13 * 2 ); - assert.ok( b.elements[ 8 ] == 2 * 2 ); - assert.ok( b.elements[ 9 ] == 6 * 2 ); - assert.ok( b.elements[ 10 ] == 10 * 2 ); - assert.ok( b.elements[ 11 ] == 14 * 2 ); - assert.ok( b.elements[ 12 ] == 3 * 2 ); - assert.ok( b.elements[ 13 ] == 7 * 2 ); - assert.ok( b.elements[ 14 ] == 11 * 2 ); - assert.ok( b.elements[ 15 ] == 15 * 2 ); - - } ); - - QUnit.test( "applyToBufferAttribute", ( assert ) => { - - var a = new Matrix4().set( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); - var attr = new Float32BufferAttribute( [ 1, 2, 1, 3, 0, 3 ], 3 ); - var expected = new Float32BufferAttribute( [ - 0.1666666716337204, 0.4444444477558136, 0.7222222089767456, - 0.1599999964237213, 0.4399999976158142, 0.7200000286102295 - ], 3 ); - - var applied = a.applyToBufferAttribute( attr ); - - assert.strictEqual( expected.count, applied.count, "Applied buffer and expected buffer have the same number of entries" ); - - for ( var i = 0, l = expected.count; i < l; i ++ ) { - - assert.ok( Math.abs( applied.getX( i ) - expected.getX( i ) ) <= eps, "Check x" ); - assert.ok( Math.abs( applied.getY( i ) - expected.getY( i ) ) <= eps, "Check y" ); - assert.ok( Math.abs( applied.getZ( i ) - expected.getZ( i ) ) <= eps, "Check z" ); - - } - - } ); - - QUnit.test( "determinant", ( assert ) => { - - var a = new Matrix4(); - assert.ok( a.determinant() == 1, "Passed!" ); - - a.elements[ 0 ] = 2; - assert.ok( a.determinant() == 2, "Passed!" ); - - a.elements[ 0 ] = 0; - assert.ok( a.determinant() == 0, "Passed!" ); - - // calculated via http://www.euclideanspace.com/maths/algebra/matrix/functions/determinant/fourD/index.htm - a.set( 2, 3, 4, 5, - 1, - 21, - 3, - 4, 6, 7, 8, 10, - 8, - 9, - 10, - 12 ); - assert.ok( a.determinant() == 76, "Passed!" ); - - } ); - - QUnit.test( "transpose", ( assert ) => { - - var a = new Matrix4(); - var b = a.clone().transpose(); - assert.ok( matrixEquals4$1( a, b ), "Passed!" ); - - var b = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); - var c = b.clone().transpose(); - assert.ok( ! matrixEquals4$1( b, c ), "Passed!" ); - c.transpose(); - assert.ok( matrixEquals4$1( b, c ), "Passed!" ); - - } ); - - QUnit.test( "setPosition", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getInverse", ( assert ) => { - - var identity = new Matrix4(); - - var a = new Matrix4(); - var b = new Matrix4().set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); - var c = new Matrix4().set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); - - assert.ok( ! matrixEquals4$1( a, b ), "Passed!" ); - b.getInverse( a, false ); - assert.ok( matrixEquals4$1( b, new Matrix4() ), "Passed!" ); - - try { - - b.getInverse( c, true ); - assert.ok( false, "Passed!" ); // should never get here. - - } catch ( err ) { - - assert.ok( true, "Passed!" ); - - } - - var testMatrices = [ - new Matrix4().makeRotationX( 0.3 ), - new Matrix4().makeRotationX( - 0.3 ), - new Matrix4().makeRotationY( 0.3 ), - new Matrix4().makeRotationY( - 0.3 ), - new Matrix4().makeRotationZ( 0.3 ), - new Matrix4().makeRotationZ( - 0.3 ), - new Matrix4().makeScale( 1, 2, 3 ), - new Matrix4().makeScale( 1 / 8, 1 / 2, 1 / 3 ), - new Matrix4().makePerspective( - 1, 1, 1, - 1, 1, 1000 ), - new Matrix4().makePerspective( - 16, 16, 9, - 9, 0.1, 10000 ), - new Matrix4().makeTranslation( 1, 2, 3 ) - ]; - - for ( var i = 0, il = testMatrices.length; i < il; i ++ ) { - - var m = testMatrices[ i ]; - - var mInverse = new Matrix4().getInverse( m ); - var mSelfInverse = m.clone(); - mSelfInverse.getInverse( mSelfInverse ); - - // self-inverse should the same as inverse - assert.ok( matrixEquals4$1( mSelfInverse, mInverse ), "Passed!" ); - - // the determinant of the inverse should be the reciprocal - assert.ok( Math.abs( m.determinant() * mInverse.determinant() - 1 ) < 0.0001, "Passed!" ); - - var mProduct = new Matrix4().multiplyMatrices( m, mInverse ); - - // the determinant of the identity matrix is 1 - assert.ok( Math.abs( mProduct.determinant() - 1 ) < 0.0001, "Passed!" ); - assert.ok( matrixEquals4$1( mProduct, identity ), "Passed!" ); - - } - - } ); - - QUnit.test( "scale", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getMaxScaleOnAxis", ( assert ) => { - - var a = new Matrix4().set( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); - var expected = Math.sqrt( 3 * 3 + 7 * 7 + 11 * 11 ); - - assert.ok( Math.abs( a.getMaxScaleOnAxis() - expected ) <= eps, "Check result" ); - - } ); - - QUnit.test( "makeTranslation", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "makeRotationX", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "makeRotationY", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "makeRotationZ", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "makeRotationAxis", ( assert ) => { - - var axis = new Vector3( 1.5, 0.0, 1.0 ).normalize(); - var radians = _Math.degToRad( 45 ); - var a = new Matrix4().makeRotationAxis( axis, radians ); - - var expected = new Matrix4().set( - 0.9098790095958609, - 0.39223227027636803, 0.13518148560620882, 0, - 0.39223227027636803, 0.7071067811865476, - 0.588348405414552, 0, - 0.13518148560620882, 0.588348405414552, 0.7972277715906868, 0, - 0, 0, 0, 1 - ); - - assert.ok( matrixEquals4$1( a, expected ), "Check numeric result" ); - - } ); - - QUnit.test( "makeScale", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "makeShear", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "compose/decompose", ( assert ) => { - - var tValues = [ - new Vector3(), - new Vector3( 3, 0, 0 ), - new Vector3( 0, 4, 0 ), - new Vector3( 0, 0, 5 ), - new Vector3( - 6, 0, 0 ), - new Vector3( 0, - 7, 0 ), - new Vector3( 0, 0, - 8 ), - new Vector3( - 2, 5, - 9 ), - new Vector3( - 2, - 5, - 9 ) - ]; - - var sValues = [ - new Vector3( 1, 1, 1 ), - new Vector3( 2, 2, 2 ), - new Vector3( 1, - 1, 1 ), - new Vector3( - 1, 1, 1 ), - new Vector3( 1, 1, - 1 ), - new Vector3( 2, - 2, 1 ), - new Vector3( - 1, 2, - 2 ), - new Vector3( - 1, - 1, - 1 ), - new Vector3( - 2, - 2, - 2 ) - ]; - - var rValues = [ - new Quaternion(), - new Quaternion().setFromEuler( new Euler( 1, 1, 0 ) ), - new Quaternion().setFromEuler( new Euler( 1, - 1, 1 ) ), - new Quaternion( 0, 0.9238795292366128, 0, 0.38268342717215614 ) - ]; - - for ( var ti = 0; ti < tValues.length; ti ++ ) { - - for ( var si = 0; si < sValues.length; si ++ ) { - - for ( var ri = 0; ri < rValues.length; ri ++ ) { - - var t = tValues[ ti ]; - var s = sValues[ si ]; - var r = rValues[ ri ]; - - var m = new Matrix4().compose( t, r, s ); - var t2 = new Vector3(); - var r2 = new Quaternion(); - var s2 = new Vector3(); - - m.decompose( t2, r2, s2 ); - - var m2 = new Matrix4().compose( t2, r2, s2 ); - - /* - // debug code - var matrixIsSame = matrixEquals4( m, m2 ); - if ( ! matrixIsSame ) { - - console.log( t, s, r ); - console.log( t2, s2, r2 ); - console.log( m, m2 ); - - } - */ - - assert.ok( matrixEquals4$1( m, m2 ), "Passed!" ); - - } - - } - - } - - } ); - - QUnit.test( "makePerspective", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "makeOrthographic", ( assert ) => { - - var a = new Matrix4().makeOrthographic( - 1, 1, - 1, 1, 1, 100 ); - var expected = new Matrix4().set( - 1, 0, 0, 0, - 0, - 1, 0, 0, - 0, 0, - 2 / 99, - 101 / 99, - 0, 0, 0, 1 - ); - - assert.ok( matrixEquals4$1( a, expected ), "Check result" ); - - } ); - - QUnit.test( "equals", ( assert ) => { - - var a = new Matrix4().set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); - var b = new Matrix4().set( 0, - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); - - assert.notOk( a.equals( b ), "Check that a does not equal b" ); - assert.notOk( b.equals( a ), "Check that b does not equal a" ); - - a.copy( b ); - assert.ok( a.equals( b ), "Check that a equals b after copy()" ); - assert.ok( b.equals( a ), "Check that b equals a after copy()" ); - - } ); - - QUnit.test( "fromArray", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "toArray", ( assert ) => { - - var a = new Matrix4().set( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ); - var noOffset = [ 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16 ]; - var withOffset = [ undefined, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16 ]; - - var array = a.toArray(); - assert.deepEqual( array, noOffset, "No array, no offset" ); - - var array = []; - a.toArray( array ); - assert.deepEqual( array, noOffset, "With array, no offset" ); - - var array = []; - a.toArray( array, 1 ); - assert.deepEqual( array, withOffset, "With array, with offset" ); - - } ); - - } ); - - } ); - - /** - * @author bhouston / http://exocortex.com - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - function comparePlane( a, b, threshold ) { - - threshold = threshold || 0.0001; - return ( a.normal.distanceTo( b.normal ) < threshold && - Math.abs( a.constant - b.constant ) < threshold ); - - } - - QUnit.module( 'Maths', () => { - - QUnit.module.todo( 'Plane', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - var a = new Plane(); - assert.ok( a.normal.x == 1, "Passed!" ); - assert.ok( a.normal.y == 0, "Passed!" ); - assert.ok( a.normal.z == 0, "Passed!" ); - assert.ok( a.constant == 0, "Passed!" ); - - var a = new Plane( one3.clone(), 0 ); - assert.ok( a.normal.x == 1, "Passed!" ); - assert.ok( a.normal.y == 1, "Passed!" ); - assert.ok( a.normal.z == 1, "Passed!" ); - assert.ok( a.constant == 0, "Passed!" ); - - var a = new Plane( one3.clone(), 1 ); - assert.ok( a.normal.x == 1, "Passed!" ); - assert.ok( a.normal.y == 1, "Passed!" ); - assert.ok( a.normal.z == 1, "Passed!" ); - assert.ok( a.constant == 1, "Passed!" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isPlane", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "set", ( assert ) => { - - var a = new Plane(); - assert.ok( a.normal.x == 1, "Passed!" ); - assert.ok( a.normal.y == 0, "Passed!" ); - assert.ok( a.normal.z == 0, "Passed!" ); - assert.ok( a.constant == 0, "Passed!" ); - - var b = a.clone().set( new Vector3( x, y, z ), w ); - assert.ok( b.normal.x == x, "Passed!" ); - assert.ok( b.normal.y == y, "Passed!" ); - assert.ok( b.normal.z == z, "Passed!" ); - assert.ok( b.constant == w, "Passed!" ); - - } ); - - QUnit.test( "setComponents", ( assert ) => { - - var a = new Plane(); - assert.ok( a.normal.x == 1, "Passed!" ); - assert.ok( a.normal.y == 0, "Passed!" ); - assert.ok( a.normal.z == 0, "Passed!" ); - assert.ok( a.constant == 0, "Passed!" ); - - var b = a.clone().setComponents( x, y, z, w ); - assert.ok( b.normal.x == x, "Passed!" ); - assert.ok( b.normal.y == y, "Passed!" ); - assert.ok( b.normal.z == z, "Passed!" ); - assert.ok( b.constant == w, "Passed!" ); - - } ); - - QUnit.test( "setFromNormalAndCoplanarPoint", ( assert ) => { - - var normal = one3.clone().normalize(); - var a = new Plane().setFromNormalAndCoplanarPoint( normal, zero3 ); - - assert.ok( a.normal.equals( normal ), "Passed!" ); - assert.ok( a.constant == 0, "Passed!" ); - - } ); - - QUnit.test( "setFromCoplanarPoints", ( assert ) => { - - var a = new Plane(); - var v1 = new Vector3( 2.0, 0.5, 0.25 ); - var v2 = new Vector3( 2.0, - 0.5, 1.25 ); - var v3 = new Vector3( 2.0, - 3.5, 2.2 ); - var normal = new Vector3( 1, 0, 0 ); - var constant = - 2; - - a.setFromCoplanarPoints( v1, v2, v3 ); - - assert.ok( a.normal.equals( normal ), "Check normal" ); - assert.strictEqual( a.constant, constant, "Check constant" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - var a = new Plane( new Vector3( x, y, z ), w ); - var b = new Plane().copy( a ); - assert.ok( b.normal.x == x, "Passed!" ); - assert.ok( b.normal.y == y, "Passed!" ); - assert.ok( b.normal.z == z, "Passed!" ); - assert.ok( b.constant == w, "Passed!" ); - - // ensure that it is a true copy - a.normal.x = 0; - a.normal.y = - 1; - a.normal.z = - 2; - a.constant = - 3; - assert.ok( b.normal.x == x, "Passed!" ); - assert.ok( b.normal.y == y, "Passed!" ); - assert.ok( b.normal.z == z, "Passed!" ); - assert.ok( b.constant == w, "Passed!" ); - - } ); - - QUnit.test( "normalize", ( assert ) => { - - var a = new Plane( new Vector3( 2, 0, 0 ), 2 ); - - a.normalize(); - assert.ok( a.normal.length() == 1, "Passed!" ); - assert.ok( a.normal.equals( new Vector3( 1, 0, 0 ) ), "Passed!" ); - assert.ok( a.constant == 1, "Passed!" ); - - } ); - - QUnit.test( "negate/distanceToPoint", ( assert ) => { - - var a = new Plane( new Vector3( 2, 0, 0 ), - 2 ); - - a.normalize(); - assert.ok( a.distanceToPoint( new Vector3( 4, 0, 0 ) ) === 3, "Passed!" ); - assert.ok( a.distanceToPoint( new Vector3( 1, 0, 0 ) ) === 0, "Passed!" ); - - a.negate(); - assert.ok( a.distanceToPoint( new Vector3( 4, 0, 0 ) ) === - 3, "Passed!" ); - assert.ok( a.distanceToPoint( new Vector3( 1, 0, 0 ) ) === 0, "Passed!" ); - - } ); - - QUnit.test( "distanceToPoint", ( assert ) => { - - var a = new Plane( new Vector3( 2, 0, 0 ), - 2 ); - - a.normalize(); - assert.ok( a.distanceToPoint( a.projectPoint( zero3.clone() ) ) === 0, "Passed!" ); - assert.ok( a.distanceToPoint( new Vector3( 4, 0, 0 ) ) === 3, "Passed!" ); - - } ); - - QUnit.test( "distanceToSphere", ( assert ) => { - - var a = new Plane( new Vector3( 1, 0, 0 ), 0 ); - - var b = new Sphere( new Vector3( 2, 0, 0 ), 1 ); - - assert.ok( a.distanceToSphere( b ) === 1, "Passed!" ); - - a.set( new Vector3( 1, 0, 0 ), 2 ); - assert.ok( a.distanceToSphere( b ) === 3, "Passed!" ); - a.set( new Vector3( 1, 0, 0 ), - 2 ); - assert.ok( a.distanceToSphere( b ) === - 1, "Passed!" ); - - } ); - - QUnit.test( "projectPoint", ( assert ) => { - - var a = new Plane( new Vector3( 1, 0, 0 ), 0 ); - - assert.ok( a.projectPoint( new Vector3( 10, 0, 0 ) ).equals( zero3 ), "Passed!" ); - assert.ok( a.projectPoint( new Vector3( - 10, 0, 0 ) ).equals( zero3 ), "Passed!" ); - - var a = new Plane( new Vector3( 0, 1, 0 ), - 1 ); - assert.ok( a.projectPoint( new Vector3( 0, 0, 0 ) ).equals( new Vector3( 0, 1, 0 ) ), "Passed!" ); - assert.ok( a.projectPoint( new Vector3( 0, 1, 0 ) ).equals( new Vector3( 0, 1, 0 ) ), "Passed!" ); - - } ); - - QUnit.test( "isInterestionLine/intersectLine", ( assert ) => { - - var a = new Plane( new Vector3( 1, 0, 0 ), 0 ); - - var l1 = new Line3( new Vector3( - 10, 0, 0 ), new Vector3( 10, 0, 0 ) ); - assert.ok( a.intersectsLine( l1 ), "Passed!" ); - assert.ok( a.intersectLine( l1 ).equals( new Vector3( 0, 0, 0 ) ), "Passed!" ); - - var a = new Plane( new Vector3( 1, 0, 0 ), - 3 ); - - assert.ok( a.intersectsLine( l1 ), "Passed!" ); - assert.ok( a.intersectLine( l1 ).equals( new Vector3( 3, 0, 0 ) ), "Passed!" ); - - var a = new Plane( new Vector3( 1, 0, 0 ), - 11 ); - - assert.ok( ! a.intersectsLine( l1 ), "Passed!" ); - assert.ok( a.intersectLine( l1 ) === undefined, "Passed!" ); - - var a = new Plane( new Vector3( 1, 0, 0 ), 11 ); - - assert.ok( ! a.intersectsLine( l1 ), "Passed!" ); - assert.ok( a.intersectLine( l1 ) === undefined, "Passed!" ); - - } ); - - QUnit.test( "intersectsBox", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "intersectsSphere", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "coplanarPoint", ( assert ) => { - - var a = new Plane( new Vector3( 1, 0, 0 ), 0 ); - assert.ok( a.distanceToPoint( a.coplanarPoint() ) === 0, "Passed!" ); - - var a = new Plane( new Vector3( 0, 1, 0 ), - 1 ); - assert.ok( a.distanceToPoint( a.coplanarPoint() ) === 0, "Passed!" ); - - } ); - - QUnit.test( "applyMatrix4/translate", ( assert ) => { - - var a = new Plane( new Vector3( 1, 0, 0 ), 0 ); - - var m = new Matrix4(); - m.makeRotationZ( Math.PI * 0.5 ); - - assert.ok( comparePlane( a.clone().applyMatrix4( m ), new Plane( new Vector3( 0, 1, 0 ), 0 ) ), "Passed!" ); - - var a = new Plane( new Vector3( 0, 1, 0 ), - 1 ); - assert.ok( comparePlane( a.clone().applyMatrix4( m ), new Plane( new Vector3( - 1, 0, 0 ), - 1 ) ), "Passed!" ); - - m.makeTranslation( 1, 1, 1 ); - assert.ok( comparePlane( a.clone().applyMatrix4( m ), a.clone().translate( new Vector3( 1, 1, 1 ) ) ), "Passed!" ); - - } ); - - QUnit.test( "equals", ( assert ) => { - - var a = new Plane( new Vector3( 1, 0, 0 ), 0 ); - var b = new Plane( new Vector3( 1, 0, 0 ), 1 ); - var c = new Plane( new Vector3( 0, 1, 0 ), 0 ); - - assert.ok( a.normal.equals( b.normal ), "Normals: equal" ); - assert.notOk( a.normal.equals( c.normal ), "Normals: not equal" ); - - assert.notStrictEqual( a.constant, b.constant, "Constants: not equal" ); - assert.strictEqual( a.constant, c.constant, "Constants: equal" ); - - assert.notOk( a.equals( b ), "Planes: not equal" ); - assert.notOk( a.equals( c ), "Planes: not equal" ); - - a.copy( b ); - assert.ok( a.normal.equals( b.normal ), "Normals after copy(): equal" ); - assert.strictEqual( a.constant, b.constant, "Constants after copy(): equal" ); - assert.ok( a.equals( b ), "Planes after copy(): equal" ); - - } ); - - } ); - - } ); - - QUnit.module( "Plane" ); - - /** - * @author bhouston / http://exocortex.com - * @author tschw - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - const orders = [ 'XYZ', 'YXZ', 'ZXY', 'ZYX', 'YZX', 'XZY' ]; - const eulerAngles = new Euler( 0.1, - 0.3, 0.25 ); - - function qSub( a, b ) { - - var result = new Quaternion(); - result.copy( a ); - - result.x -= b.x; - result.y -= b.y; - result.z -= b.z; - result.w -= b.w; - - return result; - - } - - function doSlerpObject( aArr, bArr, t ) { - - var a = new Quaternion().fromArray( aArr ), - b = new Quaternion().fromArray( bArr ), - c = new Quaternion().fromArray( aArr ); - - c.slerp( b, t ); - - return { - - equals: function ( x$$1, y$$1, z$$1, w$$1, maxError ) { - - if ( maxError === undefined ) maxError = Number.EPSILON; - - return Math.abs( x$$1 - c.x ) <= maxError && - Math.abs( y$$1 - c.y ) <= maxError && - Math.abs( z$$1 - c.z ) <= maxError && - Math.abs( w$$1 - c.w ) <= maxError; - - }, - - length: c.length(), - - dotA: c.dot( a ), - dotB: c.dot( b ) - - }; - - } - - function doSlerpArray( a, b, t ) { - - var result = [ 0, 0, 0, 0 ]; - - Quaternion.slerpFlat( result, 0, a, 0, b, 0, t ); - - function arrDot( a, b ) { - - return a[ 0 ] * b[ 0 ] + a[ 1 ] * b[ 1 ] + - a[ 2 ] * b[ 2 ] + a[ 3 ] * b[ 3 ]; - - } - - return { - - equals: function ( x$$1, y$$1, z$$1, w$$1, maxError ) { - - if ( maxError === undefined ) maxError = Number.EPSILON; - - return Math.abs( x$$1 - result[ 0 ] ) <= maxError && - Math.abs( y$$1 - result[ 1 ] ) <= maxError && - Math.abs( z$$1 - result[ 2 ] ) <= maxError && - Math.abs( w$$1 - result[ 3 ] ) <= maxError; - - }, - - length: Math.sqrt( arrDot( result, result ) ), - - dotA: arrDot( result, a ), - dotB: arrDot( result, b ) - - }; - - } - - function slerpTestSkeleton( doSlerp, maxError, assert ) { - - var a, b, result; - - a = [ - 0.6753410084407496, - 0.4087830051091744, - 0.32856700410659473, - 0.5185120064806223 - ]; - - b = [ - 0.6602792107657797, - 0.43647413932562285, - 0.35119011210236006, - 0.5001871596632682 - ]; - - var maxNormError = 0; - - function isNormal( result ) { - - var normError = Math.abs( 1 - result.length ); - maxNormError = Math.max( maxNormError, normError ); - return normError <= maxError; - - } - - result = doSlerp( a, b, 0 ); - assert.ok( result.equals( - a[ 0 ], a[ 1 ], a[ 2 ], a[ 3 ], 0 ), "Exactly A @ t = 0" ); - - result = doSlerp( a, b, 1 ); - assert.ok( result.equals( - b[ 0 ], b[ 1 ], b[ 2 ], b[ 3 ], 0 ), "Exactly B @ t = 1" ); - - result = doSlerp( a, b, 0.5 ); - assert.ok( Math.abs( result.dotA - result.dotB ) <= Number.EPSILON, "Symmetry at 0.5" ); - assert.ok( isNormal( result ), "Approximately normal (at 0.5)" ); - - result = doSlerp( a, b, 0.25 ); - assert.ok( result.dotA > result.dotB, "Interpolating at 0.25" ); - assert.ok( isNormal( result ), "Approximately normal (at 0.25)" ); - - result = doSlerp( a, b, 0.75 ); - assert.ok( result.dotA < result.dotB, "Interpolating at 0.75" ); - assert.ok( isNormal( result ), "Approximately normal (at 0.75)" ); - - var D = Math.SQRT1_2; - - result = doSlerp( [ 1, 0, 0, 0 ], [ 0, 0, 1, 0 ], 0.5 ); - assert.ok( result.equals( D, 0, D, 0 ), "X/Z diagonal from axes" ); - assert.ok( isNormal( result ), "Approximately normal (X/Z diagonal)" ); - - result = doSlerp( [ 0, D, 0, D ], [ 0, - D, 0, D ], 0.5 ); - assert.ok( result.equals( 0, 0, 0, 1 ), "W-Unit from diagonals" ); - assert.ok( isNormal( result ), "Approximately normal (W-Unit)" ); - - } - - QUnit.module( 'Maths', () => { - - QUnit.module.todo( 'Quaternion', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - var a = new Quaternion(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); - assert.ok( a.w == 1, "Passed!" ); - - var a = new Quaternion( x, y, z, w ); - assert.ok( a.x === x, "Passed!" ); - assert.ok( a.y === y, "Passed!" ); - assert.ok( a.z === z, "Passed!" ); - assert.ok( a.w === w, "Passed!" ); - - } ); - - // STATIC STUFF - QUnit.test( "slerp", ( assert ) => { - - slerpTestSkeleton( doSlerpObject, Number.EPSILON, assert ); - - } ); - - QUnit.test( "slerpFlat", ( assert ) => { - - slerpTestSkeleton( doSlerpArray, Number.EPSILON, assert ); - - } ); - - // PROPERTIES - QUnit.test( "properties", ( assert ) => { - - assert.expect( 8 ); - - var a = new Quaternion(); - a.onChange( function () { - - assert.ok( true, "onChange called" ); - - } ); - - a.x = x; - a.y = y; - a.z = z; - a.w = w; - - assert.strictEqual( a.x, x, "Check x" ); - assert.strictEqual( a.y, y, "Check y" ); - assert.strictEqual( a.z, z, "Check z" ); - assert.strictEqual( a.w, w, "Check w" ); - - } ); - - QUnit.test( "x", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "y", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "z", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "w", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "set", ( assert ) => { - - var a = new Quaternion(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); - assert.ok( a.w == 1, "Passed!" ); - - a.set( x, y, z, w ); - assert.ok( a.x == x, "Passed!" ); - assert.ok( a.y == y, "Passed!" ); - assert.ok( a.z === z, "Passed!" ); - assert.ok( a.w === w, "Passed!" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - var a = new Quaternion( x, y, z, w ); - var b = new Quaternion().copy( a ); - assert.ok( b.x == x, "Passed!" ); - assert.ok( b.y == y, "Passed!" ); - assert.ok( b.z == z, "Passed!" ); - assert.ok( b.w == w, "Passed!" ); - - // ensure that it is a true copy - a.x = 0; - a.y = - 1; - a.z = 0; - a.w = - 1; - assert.ok( b.x == x, "Passed!" ); - assert.ok( b.y == y, "Passed!" ); - - } ); - - QUnit.test( "setFromEuler/setFromQuaternion", ( assert ) => { - - var angles = [ new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ) ]; - - // ensure euler conversion to/from Quaternion matches. - for ( var i = 0; i < orders.length; i ++ ) { - - for ( var j = 0; j < angles.length; j ++ ) { - - var eulers2 = new Euler().setFromQuaternion( new Quaternion().setFromEuler( new Euler( angles[ j ].x, angles[ j ].y, angles[ j ].z, orders[ i ] ) ), orders[ i ] ); - var newAngle = new Vector3( eulers2.x, eulers2.y, eulers2.z ); - assert.ok( newAngle.distanceTo( angles[ j ] ) < 0.001, "Passed!" ); - - } - - } - - } ); - - QUnit.test( "setFromAxisAngle", ( assert ) => { - - // TODO: find cases to validate. - // assert.ok( true, "Passed!" ); - - var zero = new Quaternion(); - - var a = new Quaternion().setFromAxisAngle( new Vector3( 1, 0, 0 ), 0 ); - assert.ok( a.equals( zero ), "Passed!" ); - a = new Quaternion().setFromAxisAngle( new Vector3( 0, 1, 0 ), 0 ); - assert.ok( a.equals( zero ), "Passed!" ); - a = new Quaternion().setFromAxisAngle( new Vector3( 0, 0, 1 ), 0 ); - assert.ok( a.equals( zero ), "Passed!" ); - - var b1 = new Quaternion().setFromAxisAngle( new Vector3( 1, 0, 0 ), Math.PI ); - assert.ok( ! a.equals( b1 ), "Passed!" ); - var b2 = new Quaternion().setFromAxisAngle( new Vector3( 1, 0, 0 ), - Math.PI ); - assert.ok( ! a.equals( b2 ), "Passed!" ); - - b1.multiply( b2 ); - assert.ok( a.equals( b1 ), "Passed!" ); - - } ); - - QUnit.test( "setFromEuler/setFromRotationMatrix", ( assert ) => { - - // ensure euler conversion for Quaternion matches that of Matrix4 - for ( var i = 0; i < orders.length; i ++ ) { - - var q = new Quaternion().setFromEuler( eulerAngles, orders[ i ] ); - var m = new Matrix4().makeRotationFromEuler( eulerAngles, orders[ i ] ); - var q2 = new Quaternion().setFromRotationMatrix( m ); - - assert.ok( qSub( q, q2 ).length() < 0.001, "Passed!" ); - - } - - } ); - - QUnit.test( "setFromRotationMatrix", ( assert ) => { - - // contrived examples purely to please the god of code coverage... - // match conditions in various 'else [if]' blocks - - var a = new Quaternion(); - var q = new Quaternion( - 9, - 2, 3, - 4 ).normalize(); - var m = new Matrix4().makeRotationFromQuaternion( q ); - var expected = new Vector4( 0.8581163303210332, 0.19069251784911848, - 0.2860387767736777, 0.38138503569823695 ); - - a.setFromRotationMatrix( m ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "m11 > m22 && m11 > m33: check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "m11 > m22 && m11 > m33: check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "m11 > m22 && m11 > m33: check z" ); - assert.ok( Math.abs( a.w - expected.w ) <= eps, "m11 > m22 && m11 > m33: check w" ); - - var q = new Quaternion( - 1, - 2, 1, - 1 ).normalize(); - m.makeRotationFromQuaternion( q ); - var expected = new Vector4( 0.37796447300922714, 0.7559289460184544, - 0.37796447300922714, 0.37796447300922714 ); - - a.setFromRotationMatrix( m ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "m22 > m33: check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "m22 > m33: check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "m22 > m33: check z" ); - assert.ok( Math.abs( a.w - expected.w ) <= eps, "m22 > m33: check w" ); - - } ); - - QUnit.test( "setFromUnitVectors", ( assert ) => { - - var a = new Quaternion(); - var b = new Vector3( 1, 0, 0 ); - var c = new Vector3( 0, 1, 0 ); - var expected = new Quaternion( 0, 0, Math.sqrt( 2 ) / 2, Math.sqrt( 2 ) / 2 ); - - a.setFromUnitVectors( b, c ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "Check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "Check z" ); - assert.ok( Math.abs( a.w - expected.w ) <= eps, "Check w" ); - - } ); - - QUnit.test( "inverse/conjugate", ( assert ) => { - - var a = new Quaternion( x, y, z, w ); - - // TODO: add better validation here. - - var b = a.clone().conjugate(); - - assert.ok( a.x == - b.x, "Passed!" ); - assert.ok( a.y == - b.y, "Passed!" ); - assert.ok( a.z == - b.z, "Passed!" ); - assert.ok( a.w == b.w, "Passed!" ); - - } ); - - QUnit.test( "inverse", ( assert ) => { - - assert.expect( 6 ); - - var a = new Quaternion( x, y, z, w ); - var inverted = new Quaternion( - 0.2721655269759087, - 0.408248290463863, - 0.5443310539518174, 0.6804138174397717 ); - a.onChange( function () { - - assert.ok( true, "onChange called" ); - - } ); - - a.inverse(); - assert.ok( Math.abs( a.x - inverted.x ) <= eps, "Check x" ); - assert.ok( Math.abs( a.y - inverted.y ) <= eps, "Check y" ); - assert.ok( Math.abs( a.z - inverted.z ) <= eps, "Check z" ); - assert.ok( Math.abs( a.w - inverted.w ) <= eps, "Check w" ); - - } ); - - QUnit.test( "dot", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "normalize/length/lengthSq", ( assert ) => { - - var a = new Quaternion( x, y, z, w ); - var b = new Quaternion( - x, - y, - z, - w ); - - assert.ok( a.length() != 1, "Passed!" ); - assert.ok( a.lengthSq() != 1, "Passed!" ); - a.normalize(); - assert.ok( a.length() == 1, "Passed!" ); - assert.ok( a.lengthSq() == 1, "Passed!" ); - - a.set( 0, 0, 0, 0 ); - assert.ok( a.lengthSq() == 0, "Passed!" ); - assert.ok( a.length() == 0, "Passed!" ); - a.normalize(); - assert.ok( a.lengthSq() == 1, "Passed!" ); - assert.ok( a.length() == 1, "Passed!" ); - - } ); - - QUnit.test( "multiplyQuaternions/multiply", ( assert ) => { - - var angles = [ new Euler( 1, 0, 0 ), new Euler( 0, 1, 0 ), new Euler( 0, 0, 1 ) ]; - - var q1 = new Quaternion().setFromEuler( angles[ 0 ], "XYZ" ); - var q2 = new Quaternion().setFromEuler( angles[ 1 ], "XYZ" ); - var q3 = new Quaternion().setFromEuler( angles[ 2 ], "XYZ" ); - - var q = new Quaternion().multiplyQuaternions( q1, q2 ).multiply( q3 ); - - var m1 = new Matrix4().makeRotationFromEuler( angles[ 0 ], "XYZ" ); - var m2 = new Matrix4().makeRotationFromEuler( angles[ 1 ], "XYZ" ); - var m3 = new Matrix4().makeRotationFromEuler( angles[ 2 ], "XYZ" ); - - var m = new Matrix4().multiplyMatrices( m1, m2 ).multiply( m3 ); - - var qFromM = new Quaternion().setFromRotationMatrix( m ); - - assert.ok( qSub( q, qFromM ).length() < 0.001, "Passed!" ); - - } ); - - QUnit.test( "premultiply", ( assert ) => { - - var a = new Quaternion( x, y, z, w ); - var b = new Quaternion( 2 * x, - y, - 2 * z, w ); - var expected = new Quaternion( 42, - 32, - 2, 58 ); - - a.premultiply( b ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "Check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "Check z" ); - assert.ok( Math.abs( a.w - expected.w ) <= eps, "Check w" ); - - } ); - - QUnit.test( "slerp", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "equals", ( assert ) => { - - var a = new Quaternion( x, y, z, w ); - var b = new Quaternion( - x, - y, - z, - w ); - - assert.ok( a.x != b.x, "Passed!" ); - assert.ok( a.y != b.y, "Passed!" ); - - assert.ok( ! a.equals( b ), "Passed!" ); - assert.ok( ! b.equals( a ), "Passed!" ); - - a.copy( b ); - assert.ok( a.x == b.x, "Passed!" ); - assert.ok( a.y == b.y, "Passed!" ); - - assert.ok( a.equals( b ), "Passed!" ); - assert.ok( b.equals( a ), "Passed!" ); - - } ); - - QUnit.test( "fromArray", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "toArray", ( assert ) => { - - var a = new Quaternion( x, y, z, w ); - - var array = a.toArray(); - assert.strictEqual( array[ 0 ], x, "No array, no offset: check x" ); - assert.strictEqual( array[ 1 ], y, "No array, no offset: check y" ); - assert.strictEqual( array[ 2 ], z, "No array, no offset: check z" ); - assert.strictEqual( array[ 3 ], w, "No array, no offset: check w" ); - - var array = []; - a.toArray( array ); - assert.strictEqual( array[ 0 ], x, "With array, no offset: check x" ); - assert.strictEqual( array[ 1 ], y, "With array, no offset: check y" ); - assert.strictEqual( array[ 2 ], z, "With array, no offset: check z" ); - assert.strictEqual( array[ 3 ], w, "With array, no offset: check w" ); - - var array = []; - a.toArray( array, 1 ); - assert.strictEqual( array[ 0 ], undefined, "With array and offset: check [0]" ); - assert.strictEqual( array[ 1 ], x, "With array and offset: check x" ); - assert.strictEqual( array[ 2 ], y, "With array and offset: check y" ); - assert.strictEqual( array[ 3 ], z, "With array and offset: check z" ); - assert.strictEqual( array[ 4 ], w, "With array and offset: check w" ); - - } ); - - QUnit.test( "onChange", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "onChangeCallback", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // OTHERS - QUnit.test( "multiplyVector3", ( assert ) => { - - var angles = [ new Euler( 1, 0, 0 ), new Euler( 0, 1, 0 ), new Euler( 0, 0, 1 ) ]; - - // ensure euler conversion for Quaternion matches that of Matrix4 - for ( var i = 0; i < orders.length; i ++ ) { - - for ( var j = 0; j < angles.length; j ++ ) { - - var q = new Quaternion().setFromEuler( angles[ j ], orders[ i ] ); - var m = new Matrix4().makeRotationFromEuler( angles[ j ], orders[ i ] ); - - var v0 = new Vector3( 1, 0, 0 ); - var qv = v0.clone().applyQuaternion( q ); - var mv = v0.clone().applyMatrix4( m ); - - assert.ok( qv.distanceTo( mv ) < 0.001, "Passed!" ); - - } - - } - - } ); - - } ); - - } ); - - QUnit.module( "Quaternion" ); - - /** - * @author bhouston / http://exocortex.com - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Maths', () => { - - QUnit.module.todo( 'Ray', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - var a = new Ray(); - assert.ok( a.origin.equals( zero3 ), "Passed!" ); - assert.ok( a.direction.equals( zero3 ), "Passed!" ); - - var a = new Ray( two3.clone(), one3.clone() ); - assert.ok( a.origin.equals( two3 ), "Passed!" ); - assert.ok( a.direction.equals( one3 ), "Passed!" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isRay", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "set", ( assert ) => { - - var a = new Ray(); - - a.set( one3, one3 ); - assert.ok( a.origin.equals( one3 ), "Passed!" ); - assert.ok( a.direction.equals( one3 ), "Passed!" ); - - } ); - - QUnit.test( "recast/clone", ( assert ) => { - - var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); - - assert.ok( a.recast( 0 ).equals( a ), "Passed!" ); - - var b = a.clone(); - assert.ok( b.recast( - 1 ).equals( new Ray( new Vector3( 1, 1, 0 ), new Vector3( 0, 0, 1 ) ) ), "Passed!" ); - - var c = a.clone(); - assert.ok( c.recast( 1 ).equals( new Ray( new Vector3( 1, 1, 2 ), new Vector3( 0, 0, 1 ) ) ), "Passed!" ); - - var d = a.clone(); - var e = d.clone().recast( 1 ); - assert.ok( d.equals( a ), "Passed!" ); - assert.ok( ! e.equals( d ), "Passed!" ); - assert.ok( e.equals( c ), "Passed!" ); - - } ); - - QUnit.test( "copy/equals", ( assert ) => { - - var a = new Ray( zero3.clone(), one3.clone() ); - var b = new Ray().copy( a ); - assert.ok( b.origin.equals( zero3 ), "Passed!" ); - assert.ok( b.direction.equals( one3 ), "Passed!" ); - - // ensure that it is a true copy - a.origin = zero3; - a.direction = one3; - assert.ok( b.origin.equals( zero3 ), "Passed!" ); - assert.ok( b.direction.equals( one3 ), "Passed!" ); - - } ); - - QUnit.test( "at", ( assert ) => { - - var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); - - assert.ok( a.at( 0 ).equals( one3 ), "Passed!" ); - assert.ok( a.at( - 1 ).equals( new Vector3( 1, 1, 0 ) ), "Passed!" ); - assert.ok( a.at( 1 ).equals( new Vector3( 1, 1, 2 ) ), "Passed!" ); - - } ); - - QUnit.test( "lookAt", ( assert ) => { - - var a = new Ray( two3.clone(), one3.clone() ); - var target = one3.clone(); - var expected = target.sub( two3 ).normalize(); - - a.lookAt( target ); - assert.ok( a.direction.equals( expected ), "Check if we're looking in the right direction" ); - - } ); - - QUnit.test( "closestPointToPoint", ( assert ) => { - - var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); - - // behind the ray - var b = a.closestPointToPoint( zero3 ); - assert.ok( b.equals( one3 ), "Passed!" ); - - // front of the ray - var c = a.closestPointToPoint( new Vector3( 0, 0, 50 ) ); - assert.ok( c.equals( new Vector3( 1, 1, 50 ) ), "Passed!" ); - - // exactly on the ray - var d = a.closestPointToPoint( one3 ); - assert.ok( d.equals( one3 ), "Passed!" ); - - } ); - - QUnit.test( "distanceToPoint", ( assert ) => { - - var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); - - // behind the ray - var b = a.distanceToPoint( zero3 ); - assert.ok( b === Math.sqrt( 3 ), "Passed!" ); - - // front of the ray - var c = a.distanceToPoint( new Vector3( 0, 0, 50 ) ); - assert.ok( c === Math.sqrt( 2 ), "Passed!" ); - - // exactly on the ray - var d = a.distanceToPoint( one3 ); - assert.ok( d === 0, "Passed!" ); - - } ); - - QUnit.test( "distanceSqToPoint", ( assert ) => { - - var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); - - // behind the ray - var b = a.distanceSqToPoint( zero3 ); - assert.ok( b === 3, "Passed!" ); - - // front of the ray - var c = a.distanceSqToPoint( new Vector3( 0, 0, 50 ) ); - assert.ok( c === 2, "Passed!" ); - - // exactly on the ray - var d = a.distanceSqToPoint( one3 ); - assert.ok( d === 0, "Passed!" ); - - } ); - - QUnit.test( "distanceSqToSegment", ( assert ) => { - - var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); - var ptOnLine = new Vector3(); - var ptOnSegment = new Vector3(); - - //segment in front of the ray - var v0 = new Vector3( 3, 5, 50 ); - var v1 = new Vector3( 50, 50, 50 ); // just a far away point - var distSqr = a.distanceSqToSegment( v0, v1, ptOnLine, ptOnSegment ); - - assert.ok( ptOnSegment.distanceTo( v0 ) < 0.0001, "Passed!" ); - assert.ok( ptOnLine.distanceTo( new Vector3( 1, 1, 50 ) ) < 0.0001, "Passed!" ); - // ((3-1) * (3-1) + (5-1) * (5-1) = 4 + 16 = 20 - assert.ok( Math.abs( distSqr - 20 ) < 0.0001, "Passed!" ); - - //segment behind the ray - var v0 = new Vector3( - 50, - 50, - 50 ); // just a far away point - var v1 = new Vector3( - 3, - 5, - 4 ); - var distSqr = a.distanceSqToSegment( v0, v1, ptOnLine, ptOnSegment ); - - assert.ok( ptOnSegment.distanceTo( v1 ) < 0.0001, "Passed!" ); - assert.ok( ptOnLine.distanceTo( one3 ) < 0.0001, "Passed!" ); - // ((-3-1) * (-3-1) + (-5-1) * (-5-1) + (-4-1) + (-4-1) = 16 + 36 + 25 = 77 - assert.ok( Math.abs( distSqr - 77 ) < 0.0001, "Passed!" ); - - //exact intersection between the ray and the segment - var v0 = new Vector3( - 50, - 50, - 50 ); - var v1 = new Vector3( 50, 50, 50 ); - var distSqr = a.distanceSqToSegment( v0, v1, ptOnLine, ptOnSegment ); - - assert.ok( ptOnSegment.distanceTo( one3 ) < 0.0001, "Passed!" ); - assert.ok( ptOnLine.distanceTo( one3 ) < 0.0001, "Passed!" ); - assert.ok( distSqr < 0.0001, "Passed!" ); - - } ); - - QUnit.test( "intersectSphere", ( assert ) => { - - var TOL = 0.0001; - - // ray a0 origin located at ( 0, 0, 0 ) and points outward in negative-z direction - var a0 = new Ray( zero3.clone(), new Vector3( 0, 0, - 1 ) ); - // ray a1 origin located at ( 1, 1, 1 ) and points left in negative-x direction - var a1 = new Ray( one3.clone(), new Vector3( - 1, 0, 0 ) ); - - // sphere (radius of 2) located behind ray a0, should result in null - var b = new Sphere( new Vector3( 0, 0, 3 ), 2 ); - assert.ok( a0.intersectSphere( b ) === null, "Passed!" ); - - // sphere (radius of 2) located in front of, but too far right of ray a0, should result in null - var b = new Sphere( new Vector3( 3, 0, - 1 ), 2 ); - assert.ok( a0.intersectSphere( b ) === null, "Passed!" ); - - // sphere (radius of 2) located below ray a1, should result in null - var b = new Sphere( new Vector3( 1, - 2, 1 ), 2 ); - assert.ok( a1.intersectSphere( b ) === null, "Passed!" ); - - // sphere (radius of 1) located to the left of ray a1, should result in intersection at 0, 1, 1 - var b = new Sphere( new Vector3( - 1, 1, 1 ), 1 ); - assert.ok( a1.intersectSphere( b ).distanceTo( new Vector3( 0, 1, 1 ) ) < TOL, "Passed!" ); - - // sphere (radius of 1) located in front of ray a0, should result in intersection at 0, 0, -1 - var b = new Sphere( new Vector3( 0, 0, - 2 ), 1 ); - assert.ok( a0.intersectSphere( b ).distanceTo( new Vector3( 0, 0, - 1 ) ) < TOL, "Passed!" ); - - // sphere (radius of 2) located in front & right of ray a0, should result in intersection at 0, 0, -1, or left-most edge of sphere - var b = new Sphere( new Vector3( 2, 0, - 1 ), 2 ); - assert.ok( a0.intersectSphere( b ).distanceTo( new Vector3( 0, 0, - 1 ) ) < TOL, "Passed!" ); - - // same situation as above, but move the sphere a fraction more to the right, and ray a0 should now just miss - var b = new Sphere( new Vector3( 2.01, 0, - 1 ), 2 ); - assert.ok( a0.intersectSphere( b ) === null, "Passed!" ); - - // following QUnit.tests are for situations where the ray origin is inside the sphere - - // sphere (radius of 1) center located at ray a0 origin / sphere surrounds the ray origin, so the first intersect point 0, 0, 1, - // is behind ray a0. Therefore, second exit point on back of sphere will be returned: 0, 0, -1 - // thus keeping the intersection point always in front of the ray. - var b = new Sphere( zero3.clone(), 1 ); - assert.ok( a0.intersectSphere( b ).distanceTo( new Vector3( 0, 0, - 1 ) ) < TOL, "Passed!" ); - - // sphere (radius of 4) center located behind ray a0 origin / sphere surrounds the ray origin, so the first intersect point 0, 0, 5, - // is behind ray a0. Therefore, second exit point on back of sphere will be returned: 0, 0, -3 - // thus keeping the intersection point always in front of the ray. - var b = new Sphere( new Vector3( 0, 0, 1 ), 4 ); - assert.ok( a0.intersectSphere( b ).distanceTo( new Vector3( 0, 0, - 3 ) ) < TOL, "Passed!" ); - - // sphere (radius of 4) center located in front of ray a0 origin / sphere surrounds the ray origin, so the first intersect point 0, 0, 3, - // is behind ray a0. Therefore, second exit point on back of sphere will be returned: 0, 0, -5 - // thus keeping the intersection point always in front of the ray. - var b = new Sphere( new Vector3( 0, 0, - 1 ), 4 ); - assert.ok( a0.intersectSphere( b ).distanceTo( new Vector3( 0, 0, - 5 ) ) < TOL, "Passed!" ); - - } ); - - QUnit.test( "intersectsSphere", ( assert ) => { - - var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); - var b = new Sphere( zero3, 0.5 ); - var c = new Sphere( zero3, 1.5 ); - var d = new Sphere( one3, 0.1 ); - var e = new Sphere( two3, 0.1 ); - var f = new Sphere( two3, 1 ); - - assert.ok( ! a.intersectsSphere( b ), "Passed!" ); - assert.ok( ! a.intersectsSphere( c ), "Passed!" ); - assert.ok( a.intersectsSphere( d ), "Passed!" ); - assert.ok( ! a.intersectsSphere( e ), "Passed!" ); - assert.ok( ! a.intersectsSphere( f ), "Passed!" ); - - } ); - - QUnit.test( "distanceToPlane", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "intersectPlane", ( assert ) => { - - var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); - - // parallel plane behind - var b = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), new Vector3( 1, 1, - 1 ) ); - assert.ok( a.intersectPlane( b ) === null, "Passed!" ); - - // parallel plane coincident with origin - var c = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), new Vector3( 1, 1, 0 ) ); - assert.ok( a.intersectPlane( c ) === null, "Passed!" ); - - // parallel plane infront - var d = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), new Vector3( 1, 1, 1 ) ); - assert.ok( a.intersectPlane( d ).equals( a.origin ), "Passed!" ); - - // perpendical ray that overlaps exactly - var e = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 1, 0, 0 ), one3 ); - assert.ok( a.intersectPlane( e ).equals( a.origin ), "Passed!" ); - - // perpendical ray that doesn't overlap - var f = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 1, 0, 0 ), zero3 ); - assert.ok( a.intersectPlane( f ) === null, "Passed!" ); - - } ); - - QUnit.test( "intersectsPlane", ( assert ) => { - - var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); - - // parallel plane in front of the ray - var b = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), one3.clone().sub( new Vector3( 0, 0, - 1 ) ) ); - assert.ok( a.intersectsPlane( b ), "Passed!" ); - - // parallel plane coincident with origin - var c = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), one3.clone().sub( new Vector3( 0, 0, 0 ) ) ); - assert.ok( a.intersectsPlane( c ), "Passed!" ); - - // parallel plane behind the ray - var d = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 0, 0, 1 ), one3.clone().sub( new Vector3( 0, 0, 1 ) ) ); - assert.ok( ! a.intersectsPlane( d ), "Passed!" ); - - // perpendical ray that overlaps exactly - var e = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 1, 0, 0 ), one3 ); - assert.ok( a.intersectsPlane( e ), "Passed!" ); - - // perpendical ray that doesn't overlap - var f = new Plane().setFromNormalAndCoplanarPoint( new Vector3( 1, 0, 0 ), zero3 ); - assert.ok( ! a.intersectsPlane( f ), "Passed!" ); - - } ); - - QUnit.test( "intersectBox", ( assert ) => { - - var TOL = 0.0001; - - var box = new Box3( new Vector3( - 1, - 1, - 1 ), new Vector3( 1, 1, 1 ) ); - - var a = new Ray( new Vector3( - 2, 0, 0 ), new Vector3( 1, 0, 0 ) ); - //ray should intersect box at -1,0,0 - assert.ok( a.intersectsBox( box ) === true, "Passed!" ); - assert.ok( a.intersectBox( box ).distanceTo( new Vector3( - 1, 0, 0 ) ) < TOL, "Passed!" ); - - var b = new Ray( new Vector3( - 2, 0, 0 ), new Vector3( - 1, 0, 0 ) ); - //ray is point away from box, it should not intersect - assert.ok( b.intersectsBox( box ) === false, "Passed!" ); - assert.ok( b.intersectBox( box ) === null, "Passed!" ); - - var c = new Ray( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ) ); - // ray is inside box, should return exit point - assert.ok( c.intersectsBox( box ) === true, "Passed!" ); - assert.ok( c.intersectBox( box ).distanceTo( new Vector3( 1, 0, 0 ) ) < TOL, "Passed!" ); - - var d = new Ray( new Vector3( 0, 2, 1 ), new Vector3( 0, - 1, - 1 ).normalize() ); - //tilted ray should intersect box at 0,1,0 - assert.ok( d.intersectsBox( box ) === true, "Passed!" ); - assert.ok( d.intersectBox( box ).distanceTo( new Vector3( 0, 1, 0 ) ) < TOL, "Passed!" ); - - var e = new Ray( new Vector3( 1, - 2, 1 ), new Vector3( 0, 1, 0 ).normalize() ); - //handle case where ray is coplanar with one of the boxes side - box in front of ray - assert.ok( e.intersectsBox( box ) === true, "Passed!" ); - assert.ok( e.intersectBox( box ).distanceTo( new Vector3( 1, - 1, 1 ) ) < TOL, "Passed!" ); - - var f = new Ray( new Vector3( 1, - 2, 0 ), new Vector3( 0, - 1, 0 ).normalize() ); - //handle case where ray is coplanar with one of the boxes side - box behind ray - assert.ok( f.intersectsBox( box ) === false, "Passed!" ); - assert.ok( f.intersectBox( box ) == null, "Passed!" ); - - } ); - - QUnit.test( "intersectsBox", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "intersectTriangle", ( assert ) => { - - var ray = new Ray(); - var a = new Vector3( 1, 1, 0 ); - var b = new Vector3( 0, 1, 1 ); - var c = new Vector3( 1, 0, 1 ); - var intersect; - - // DdN == 0 - ray.set( ray.origin, zero3.clone() ); - intersect = ray.intersectTriangle( a, b, c, false ); - assert.strictEqual( intersect, null, "No intersection if direction == zero" ); - - // DdN > 0, backfaceCulling = true - ray.set( ray.origin, one3.clone() ); - intersect = ray.intersectTriangle( a, b, c, true ); - assert.strictEqual( intersect, null, "No intersection with backside faces if backfaceCulling is true" ); - - // DdN > 0 - ray.set( ray.origin, one3.clone() ); - intersect = ray.intersectTriangle( a, b, c, false ); - assert.ok( Math.abs( intersect.x - 2 / 3 ) <= eps, "Successful intersection: check x" ); - assert.ok( Math.abs( intersect.y - 2 / 3 ) <= eps, "Successful intersection: check y" ); - assert.ok( Math.abs( intersect.z - 2 / 3 ) <= eps, "Successful intersection: check z" ); - - // DdN > 0, DdQxE2 < 0 - b.multiplyScalar( - 1 ); - intersect = ray.intersectTriangle( a, b, c, false ); - assert.strictEqual( intersect, null, "No intersection" ); - - // DdN > 0, DdE1xQ < 0 - a.multiplyScalar( - 1 ); - intersect = ray.intersectTriangle( a, b, c, false ); - assert.strictEqual( intersect, null, "No intersection" ); - - // DdN > 0, DdQxE2 + DdE1xQ > DdN - b.multiplyScalar( - 1 ); - intersect = ray.intersectTriangle( a, b, c, false ); - assert.strictEqual( intersect, null, "No intersection" ); - - // DdN < 0, QdN < 0 - a.multiplyScalar( - 1 ); - b.multiplyScalar( - 1 ); - ray.direction.multiplyScalar( - 1 ); - intersect = ray.intersectTriangle( a, b, c, false ); - assert.strictEqual( intersect, null, "No intersection when looking in the wrong direction" ); - - } ); - - QUnit.test( "applyMatrix4", ( assert ) => { - - var a = new Ray( one3.clone(), new Vector3( 0, 0, 1 ) ); - var m = new Matrix4(); - - assert.ok( a.clone().applyMatrix4( m ).equals( a ), "Passed!" ); - - var a = new Ray( zero3.clone(), new Vector3( 0, 0, 1 ) ); - m.makeRotationZ( Math.PI ); - assert.ok( a.clone().applyMatrix4( m ).equals( a ), "Passed!" ); - - m.makeRotationX( Math.PI ); - var b = a.clone(); - b.direction.negate(); - var a2 = a.clone().applyMatrix4( m ); - assert.ok( a2.origin.distanceTo( b.origin ) < 0.0001, "Passed!" ); - assert.ok( a2.direction.distanceTo( b.direction ) < 0.0001, "Passed!" ); - - a.origin = new Vector3( 0, 0, 1 ); - b.origin = new Vector3( 0, 0, - 1 ); - var a2 = a.clone().applyMatrix4( m ); - assert.ok( a2.origin.distanceTo( b.origin ) < 0.0001, "Passed!" ); - assert.ok( a2.direction.distanceTo( b.direction ) < 0.0001, "Passed!" ); - - } ); - - QUnit.test( "equals", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author bhouston / http://exocortex.com - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Maths', () => { - - QUnit.module.todo( 'Sphere', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - var a = new Sphere(); - assert.ok( a.center.equals( zero3 ), "Passed!" ); - assert.ok( a.radius == 0, "Passed!" ); - - var a = new Sphere( one3.clone(), 1 ); - assert.ok( a.center.equals( one3 ), "Passed!" ); - assert.ok( a.radius == 1, "Passed!" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isSphere", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "set", ( assert ) => { - - var a = new Sphere(); - assert.ok( a.center.equals( zero3 ), "Passed!" ); - assert.ok( a.radius == 0, "Passed!" ); - - a.set( one3, 1 ); - assert.ok( a.center.equals( one3 ), "Passed!" ); - assert.ok( a.radius == 1, "Passed!" ); - - } ); - - QUnit.test( "setFromPoints", ( assert ) => { - - var a = new Sphere(); - var expectedCenter = new Vector3( 0.9330126941204071, 0, 0 ); - var expectedRadius = 1.3676668773461689; - var optionalCenter = new Vector3( 1, 1, 1 ); - var points = [ - new Vector3( 1, 1, 0 ), new Vector3( 1, 1, 0 ), - new Vector3( 1, 1, 0 ), new Vector3( 1, 1, 0 ), - new Vector3( 1, 1, 0 ), new Vector3( 0.8660253882408142, 0.5, 0 ), - new Vector3( - 0, 0.5, 0.8660253882408142 ), new Vector3( 1.8660253882408142, 0.5, 0 ), - new Vector3( 0, 0.5, - 0.8660253882408142 ), new Vector3( 0.8660253882408142, 0.5, - 0 ), - new Vector3( 0.8660253882408142, - 0.5, 0 ), new Vector3( - 0, - 0.5, 0.8660253882408142 ), - new Vector3( 1.8660253882408142, - 0.5, 0 ), new Vector3( 0, - 0.5, - 0.8660253882408142 ), - new Vector3( 0.8660253882408142, - 0.5, - 0 ), new Vector3( - 0, - 1, 0 ), - new Vector3( - 0, - 1, 0 ), new Vector3( 0, - 1, 0 ), - new Vector3( 0, - 1, - 0 ), new Vector3( - 0, - 1, - 0 ), - ]; - - a.setFromPoints( points ); - assert.ok( Math.abs( a.center.x - expectedCenter.x ) <= eps, "Default center: check center.x" ); - assert.ok( Math.abs( a.center.y - expectedCenter.y ) <= eps, "Default center: check center.y" ); - assert.ok( Math.abs( a.center.z - expectedCenter.z ) <= eps, "Default center: check center.z" ); - assert.ok( Math.abs( a.radius - expectedRadius ) <= eps, "Default center: check radius" ); - - var expectedRadius = 2.5946195770400102; - a.setFromPoints( points, optionalCenter ); - assert.ok( Math.abs( a.center.x - optionalCenter.x ) <= eps, "Optional center: check center.x" ); - assert.ok( Math.abs( a.center.y - optionalCenter.y ) <= eps, "Optional center: check center.y" ); - assert.ok( Math.abs( a.center.z - optionalCenter.z ) <= eps, "Optional center: check center.z" ); - assert.ok( Math.abs( a.radius - expectedRadius ) <= eps, "Optional center: check radius" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - var a = new Sphere( one3.clone(), 1 ); - var b = new Sphere().copy( a ); - - assert.ok( b.center.equals( one3 ), "Passed!" ); - assert.ok( b.radius == 1, "Passed!" ); - - // ensure that it is a true copy - a.center = zero3; - a.radius = 0; - assert.ok( b.center.equals( one3 ), "Passed!" ); - assert.ok( b.radius == 1, "Passed!" ); - - } ); - - QUnit.test( "empty", ( assert ) => { - - var a = new Sphere(); - assert.ok( a.empty(), "Passed!" ); - - a.set( one3, 1 ); - assert.ok( ! a.empty(), "Passed!" ); - - } ); - - QUnit.test( "containsPoint", ( assert ) => { - - var a = new Sphere( one3.clone(), 1 ); - - assert.ok( ! a.containsPoint( zero3 ), "Passed!" ); - assert.ok( a.containsPoint( one3 ), "Passed!" ); - - } ); - - QUnit.test( "distanceToPoint", ( assert ) => { - - var a = new Sphere( one3.clone(), 1 ); - - assert.ok( ( a.distanceToPoint( zero3 ) - 0.7320 ) < 0.001, "Passed!" ); - assert.ok( a.distanceToPoint( one3 ) === - 1, "Passed!" ); - - } ); - - QUnit.test( "intersectsSphere", ( assert ) => { - - var a = new Sphere( one3.clone(), 1 ); - var b = new Sphere( zero3.clone(), 1 ); - var c = new Sphere( zero3.clone(), 0.25 ); - - assert.ok( a.intersectsSphere( b ), "Passed!" ); - assert.ok( ! a.intersectsSphere( c ), "Passed!" ); - - } ); - - QUnit.test( "intersectsBox", ( assert ) => { - - var a = new Sphere(); - var b = new Sphere( new Vector3( - 5, - 5, - 5 ) ); - var box = new Box3( zero3, one3 ); - - assert.strictEqual( a.intersectsBox( box ), true, "Check default sphere" ); - assert.strictEqual( b.intersectsBox( box ), false, "Check shifted sphere" ); - - } ); - - QUnit.test( "intersectsPlane", ( assert ) => { - - var a = new Sphere( zero3.clone(), 1 ); - var b = new Plane( new Vector3( 0, 1, 0 ), 1 ); - var c = new Plane( new Vector3( 0, 1, 0 ), 1.25 ); - var d = new Plane( new Vector3( 0, - 1, 0 ), 1.25 ); - - assert.ok( a.intersectsPlane( b ), "Passed!" ); - assert.ok( ! a.intersectsPlane( c ), "Passed!" ); - assert.ok( ! a.intersectsPlane( d ), "Passed!" ); - - } ); - - QUnit.test( "clampPoint", ( assert ) => { - - var a = new Sphere( one3.clone(), 1 ); - - assert.ok( a.clampPoint( new Vector3( 1, 1, 3 ) ).equals( new Vector3( 1, 1, 2 ) ), "Passed!" ); - assert.ok( a.clampPoint( new Vector3( 1, 1, - 3 ) ).equals( new Vector3( 1, 1, 0 ) ), "Passed!" ); - - } ); - - QUnit.test( "getBoundingBox", ( assert ) => { - - var a = new Sphere( one3.clone(), 1 ); - - assert.ok( a.getBoundingBox().equals( new Box3( zero3, two3 ) ), "Passed!" ); - - a.set( zero3, 0 ); - assert.ok( a.getBoundingBox().equals( new Box3( zero3, zero3 ) ), "Passed!" ); - - } ); - - QUnit.test( "applyMatrix4", ( assert ) => { - - var a = new Sphere( one3.clone(), 1 ); - var m = new Matrix4().makeTranslation( 1, - 2, 1 ); - - assert.ok( a.clone().applyMatrix4( m ).getBoundingBox().equals( a.getBoundingBox().applyMatrix4( m ) ), "Passed!" ); - - } ); - - QUnit.test( "translate", ( assert ) => { - - var a = new Sphere( one3.clone(), 1 ); - - a.translate( one3.clone().negate() ); - assert.ok( a.center.equals( zero3 ), "Passed!" ); - - } ); - - QUnit.test( "equals", ( assert ) => { - - var a = new Sphere(); - var b = new Sphere( new Vector3( 1, 0, 0 ) ); - var c = new Sphere( new Vector3( 1, 0, 0 ), 1.0 ); - - assert.strictEqual( a.equals( b ), false, "a does not equal b" ); - assert.strictEqual( a.equals( c ), false, "a does not equal c" ); - assert.strictEqual( b.equals( c ), false, "b does not equal c" ); - - a.copy( b ); - assert.strictEqual( a.equals( b ), true, "a equals b after copy()" ); - - } ); - - } ); - - } ); - - function Spherical( radius, phi, theta ) { - - this.radius = ( radius !== undefined ) ? radius : 1.0; - this.phi = ( phi !== undefined ) ? phi : 0; // up / down towards top and bottom pole - this.theta = ( theta !== undefined ) ? theta : 0; // around the equator of the sphere - - return this; - - } - - Object.assign( Spherical.prototype, { - - set: function ( radius, phi, theta ) { - - this.radius = radius; - this.phi = phi; - this.theta = theta; - - return this; - - }, - - clone: function () { - - return new this.constructor().copy( this ); - - }, - - copy: function ( other ) { - - this.radius = other.radius; - this.phi = other.phi; - this.theta = other.theta; - - return this; - - }, - - // restrict phi to be betwee EPS and PI-EPS - makeSafe: function () { - - var EPS = 0.000001; - this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) ); - - return this; - - }, - - setFromVector3: function ( vec3 ) { - - this.radius = vec3.length(); - - if ( this.radius === 0 ) { - - this.theta = 0; - this.phi = 0; - - } else { - - this.theta = Math.atan2( vec3.x, vec3.z ); // equator angle around y-up axis - this.phi = Math.acos( _Math.clamp( vec3.y / this.radius, - 1, 1 ) ); // polar angle - - } - - return this; - - } - - } ); - - /** - * @author moraxy / https://github.com/moraxy - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Maths', () => { - - QUnit.module.todo( 'Spherical', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - var a = new Spherical(); - var radius = 10.0; - var phi = Math.acos( - 0.5 ); - var theta = Math.sqrt( Math.PI ) * phi; - - assert.strictEqual( a.radius, 1.0, "Default values: check radius" ); - assert.strictEqual( a.phi, 0, "Default values: check phi" ); - assert.strictEqual( a.theta, 0, "Default values: check theta" ); - - var a = new Spherical( radius, phi, theta ); - assert.strictEqual( a.radius, radius, "Custom values: check radius" ); - assert.strictEqual( a.phi, phi, "Custom values: check phi" ); - assert.strictEqual( a.theta, theta, "Custom values: check theta" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isSpherical", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "set", ( assert ) => { - - var a = new Spherical(); - var radius = 10.0; - var phi = Math.acos( - 0.5 ); - var theta = Math.sqrt( Math.PI ) * phi; - - a.set( radius, phi, theta ); - assert.strictEqual( a.radius, radius, "Check radius" ); - assert.strictEqual( a.phi, phi, "Check phi" ); - assert.strictEqual( a.theta, theta, "Check theta" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - var radius = 10.0; - var phi = Math.acos( - 0.5 ); - var theta = Math.sqrt( Math.PI ) * phi; - var a = new Spherical( radius, phi, theta ); - var b = a.clone(); - - assert.propEqual( a, b, "Check a and b are equal after clone()" ); - - a.radius = 2.0; - assert.notPropEqual( a, b, "Check a and b are not equal after modification" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - var radius = 10.0; - var phi = Math.acos( - 0.5 ); - var theta = Math.sqrt( Math.PI ) * phi; - var a = new Spherical( radius, phi, theta ); - var b = new Spherical().copy( a ); - - assert.propEqual( a, b, "Check a and b are equal after copy()" ); - - a.radius = 2.0; - assert.notPropEqual( a, b, "Check a and b are not equal after modification" ); - - } ); - - QUnit.test( "makeSafe", ( assert ) => { - - var EPS = 0.000001; // from source - var tooLow = 0.0; - var tooHigh = Math.PI; - var justRight = 1.5; - var a = new Spherical( 1, tooLow, 0 ); - - a.makeSafe(); - assert.strictEqual( a.phi, EPS, "Check if small values are set to EPS" ); - - a.set( 1, tooHigh, 0 ); - a.makeSafe(); - assert.strictEqual( a.phi, Math.PI - EPS, "Check if high values are set to (Math.PI - EPS)" ); - - a.set( 1, justRight, 0 ); - a.makeSafe(); - assert.strictEqual( a.phi, justRight, "Check that valid values don't get changed" ); - - } ); - - QUnit.test( "setFromVector3", ( assert ) => { - - var a = new Spherical( 1, 1, 1 ); - var b = new Vector3( 0, 0, 0 ); - var c = new Vector3( Math.PI, 1, - Math.PI ); - var expected = new Spherical( 4.554032147688322, 1.3494066171539107, 2.356194490192345 ); - - a.setFromVector3( b ); - assert.strictEqual( a.radius, 0, "Zero-length vector: check radius" ); - assert.strictEqual( a.phi, 0, "Zero-length vector: check phi" ); - assert.strictEqual( a.theta, 0, "Zero-length vector: check theta" ); - - a.setFromVector3( c ); - assert.ok( Math.abs( a.radius - expected.radius ) <= eps, "Normal vector: check radius" ); - assert.ok( Math.abs( a.phi - expected.phi ) <= eps, "Normal vector: check phi" ); - assert.ok( Math.abs( a.theta - expected.theta ) <= eps, "Normal vector: check theta" ); - - } ); - - } ); - - } ); - - /** - * @author bhouston / http://exocortex.com - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Maths', () => { - - QUnit.module.todo( 'Triangle', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - var a = new Triangle(); - assert.ok( a.a.equals( zero3 ), "Passed!" ); - assert.ok( a.b.equals( zero3 ), "Passed!" ); - assert.ok( a.c.equals( zero3 ), "Passed!" ); - - var a = new Triangle( one3.clone().negate(), one3.clone(), two3.clone() ); - assert.ok( a.a.equals( one3.clone().negate() ), "Passed!" ); - assert.ok( a.b.equals( one3 ), "Passed!" ); - assert.ok( a.c.equals( two3 ), "Passed!" ); - - } ); - - // STATIC STUFF - QUnit.test( "normal", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "barycoordFromPoint", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "containsPoint", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "set", ( assert ) => { - - var a = new Triangle(); - - a.set( one3.clone().negate(), one3, two3 ); - assert.ok( a.a.equals( one3.clone().negate() ), "Passed!" ); - assert.ok( a.b.equals( one3 ), "Passed!" ); - assert.ok( a.c.equals( two3 ), "Passed!" ); - - } ); - - QUnit.test( "setFromPointsAndIndices", ( assert ) => { - - var a = new Triangle(); - - var points = [ one3, one3.clone().negate(), two3 ]; - a.setFromPointsAndIndices( points, 1, 0, 2 ); - assert.ok( a.a.equals( one3.clone().negate() ), "Passed!" ); - assert.ok( a.b.equals( one3 ), "Passed!" ); - assert.ok( a.c.equals( two3 ), "Passed!" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - var a = new Triangle( one3.clone().negate(), one3.clone(), two3.clone() ); - var b = new Triangle().copy( a ); - assert.ok( b.a.equals( one3.clone().negate() ), "Passed!" ); - assert.ok( b.b.equals( one3 ), "Passed!" ); - assert.ok( b.c.equals( two3 ), "Passed!" ); - - // ensure that it is a true copy - a.a = one3; - a.b = zero3; - a.c = zero3; - assert.ok( b.a.equals( one3.clone().negate() ), "Passed!" ); - assert.ok( b.b.equals( one3 ), "Passed!" ); - assert.ok( b.c.equals( two3 ), "Passed!" ); - - } ); - - QUnit.test( "area", ( assert ) => { - - var a = new Triangle(); - - assert.ok( a.area() == 0, "Passed!" ); - - var a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); - assert.ok( a.area() == 0.5, "Passed!" ); - - var a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); - assert.ok( a.area() == 2, "Passed!" ); - - // colinear triangle. - var a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 3, 0, 0 ) ); - assert.ok( a.area() == 0, "Passed!" ); - - } ); - - QUnit.test( "midpoint", ( assert ) => { - - var a = new Triangle(); - - assert.ok( a.midpoint().equals( new Vector3( 0, 0, 0 ) ), "Passed!" ); - - var a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); - assert.ok( a.midpoint().equals( new Vector3( 1 / 3, 1 / 3, 0 ) ), "Passed!" ); - - var a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); - assert.ok( a.midpoint().equals( new Vector3( 2 / 3, 0, 2 / 3 ) ), "Passed!" ); - - } ); - - QUnit.test( "normal", ( assert ) => { - - var a = new Triangle(); - - assert.ok( a.normal().equals( new Vector3( 0, 0, 0 ) ), "Passed!" ); - - var a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); - assert.ok( a.normal().equals( new Vector3( 0, 0, 1 ) ), "Passed!" ); - - var a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); - assert.ok( a.normal().equals( new Vector3( 0, 1, 0 ) ), "Passed!" ); - - } ); - - QUnit.test( "plane", ( assert ) => { - - var a = new Triangle(); - - assert.notOk( isNaN( a.plane().distanceToPoint( a.a ) ), "Passed!" ); - assert.notOk( isNaN( a.plane().distanceToPoint( a.b ) ), "Passed!" ); - assert.notOk( isNaN( a.plane().distanceToPoint( a.c ) ), "Passed!" ); - assert.notPropEqual( a.plane().normal, { - x: NaN, - y: NaN, - z: NaN - }, "Passed!" ); - - var a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); - assert.ok( a.plane().distanceToPoint( a.a ) == 0, "Passed!" ); - assert.ok( a.plane().distanceToPoint( a.b ) == 0, "Passed!" ); - assert.ok( a.plane().distanceToPoint( a.c ) == 0, "Passed!" ); - assert.ok( a.plane().normal.equals( a.normal() ), "Passed!" ); - - var a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); - assert.ok( a.plane().distanceToPoint( a.a ) == 0, "Passed!" ); - assert.ok( a.plane().distanceToPoint( a.b ) == 0, "Passed!" ); - assert.ok( a.plane().distanceToPoint( a.c ) == 0, "Passed!" ); - assert.ok( a.plane().normal.clone().normalize().equals( a.normal() ), "Passed!" ); - - } ); - - QUnit.test( "barycoordFromPoint", ( assert ) => { - - var a = new Triangle(); - - var bad = new Vector3( - 2, - 1, - 1 ); - - assert.ok( a.barycoordFromPoint( a.a ).equals( bad ), "Passed!" ); - assert.ok( a.barycoordFromPoint( a.b ).equals( bad ), "Passed!" ); - assert.ok( a.barycoordFromPoint( a.c ).equals( bad ), "Passed!" ); - - var a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); - assert.ok( a.barycoordFromPoint( a.a ).equals( new Vector3( 1, 0, 0 ) ), "Passed!" ); - assert.ok( a.barycoordFromPoint( a.b ).equals( new Vector3( 0, 1, 0 ) ), "Passed!" ); - assert.ok( a.barycoordFromPoint( a.c ).equals( new Vector3( 0, 0, 1 ) ), "Passed!" ); - assert.ok( a.barycoordFromPoint( a.midpoint() ).distanceTo( new Vector3( 1 / 3, 1 / 3, 1 / 3 ) ) < 0.0001, "Passed!" ); - - var a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); - assert.ok( a.barycoordFromPoint( a.a ).equals( new Vector3( 1, 0, 0 ) ), "Passed!" ); - assert.ok( a.barycoordFromPoint( a.b ).equals( new Vector3( 0, 1, 0 ) ), "Passed!" ); - assert.ok( a.barycoordFromPoint( a.c ).equals( new Vector3( 0, 0, 1 ) ), "Passed!" ); - assert.ok( a.barycoordFromPoint( a.midpoint() ).distanceTo( new Vector3( 1 / 3, 1 / 3, 1 / 3 ) ) < 0.0001, "Passed!" ); - - } ); - - QUnit.test( "containsPoint", ( assert ) => { - - var a = new Triangle(); - - assert.ok( ! a.containsPoint( a.a ), "Passed!" ); - assert.ok( ! a.containsPoint( a.b ), "Passed!" ); - assert.ok( ! a.containsPoint( a.c ), "Passed!" ); - - var a = new Triangle( new Vector3( 0, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); - assert.ok( a.containsPoint( a.a ), "Passed!" ); - assert.ok( a.containsPoint( a.b ), "Passed!" ); - assert.ok( a.containsPoint( a.c ), "Passed!" ); - assert.ok( a.containsPoint( a.midpoint() ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( - 1, - 1, - 1 ) ), "Passed!" ); - - var a = new Triangle( new Vector3( 2, 0, 0 ), new Vector3( 0, 0, 0 ), new Vector3( 0, 0, 2 ) ); - assert.ok( a.containsPoint( a.a ), "Passed!" ); - assert.ok( a.containsPoint( a.b ), "Passed!" ); - assert.ok( a.containsPoint( a.c ), "Passed!" ); - assert.ok( a.containsPoint( a.midpoint() ), "Passed!" ); - assert.ok( ! a.containsPoint( new Vector3( - 1, - 1, - 1 ) ), "Passed!" ); - - } ); - - QUnit.test( "closestPointToPoint", ( assert ) => { - - var a = new Triangle( new Vector3( - 1, 0, 0 ), new Vector3( 1, 0, 0 ), new Vector3( 0, 1, 0 ) ); - - // point lies inside the triangle - var b0 = a.closestPointToPoint( new Vector3( 0, 0.5, 0 ) ); - assert.ok( b0.equals( new Vector3( 0, 0.5, 0 ) ), "Passed!" ); - - // point lies on a vertex - var b0 = a.closestPointToPoint( a.a ); - assert.ok( b0.equals( a.a ), "Passed!" ); - - var b0 = a.closestPointToPoint( a.b ); - assert.ok( b0.equals( a.b ), "Passed!" ); - - var b0 = a.closestPointToPoint( a.c ); - assert.ok( b0.equals( a.c ), "Passed!" ); - - // point lies on an edge - var b0 = a.closestPointToPoint( zero3.clone() ); - assert.ok( b0.equals( zero3.clone() ), "Passed!" ); - - // point lies outside the triangle - var b0 = a.closestPointToPoint( new Vector3( - 2, 0, 0 ) ); - assert.ok( b0.equals( new Vector3( - 1, 0, 0 ) ), "Passed!" ); - - var b0 = a.closestPointToPoint( new Vector3( 2, 0, 0 ) ); - assert.ok( b0.equals( new Vector3( 1, 0, 0 ) ), "Passed!" ); - - var b0 = a.closestPointToPoint( new Vector3( 0, 2, 0 ) ); - assert.ok( b0.equals( new Vector3( 0, 1, 0 ) ), "Passed!" ); - - var b0 = a.closestPointToPoint( new Vector3( 0, - 2, 0 ) ); - assert.ok( b0.equals( new Vector3( 0, 0, 0 ) ), "Passed!" ); - - } ); - - QUnit.test( "equals", ( assert ) => { - - var a = new Triangle( - new Vector3( 1, 0, 0 ), - new Vector3( 0, 1, 0 ), - new Vector3( 0, 0, 1 ) - ); - var b = new Triangle( - new Vector3( 0, 0, 1 ), - new Vector3( 0, 1, 0 ), - new Vector3( 1, 0, 0 ) - ); - var c = new Triangle( - new Vector3( - 1, 0, 0 ), - new Vector3( 0, 1, 0 ), - new Vector3( 0, 0, 1 ) - ); - - assert.ok( a.equals( a ), "a equals a" ); - assert.notOk( a.equals( b ), "a does not equal b" ); - assert.notOk( a.equals( c ), "a does not equal c" ); - assert.notOk( b.equals( c ), "b does not equal c" ); - - a.copy( b ); - assert.ok( a.equals( a ), "a equals b after copy()" ); - - } ); - - } ); - - } ); - - /** - * @author bhouston / http://exocortex.com - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Maths', () => { - - QUnit.module.todo( 'Vector2', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - var a = new Vector2(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - - var a = new Vector2( x, y ); - assert.ok( a.x === x, "Passed!" ); - assert.ok( a.y === y, "Passed!" ); - - } ); - - // PROPERTIES // ( [Itee] WHAT ??? o_O ) - QUnit.test( "properties", ( assert ) => { - - var a = new Vector2( 0, 0 ); - var width = 100; - var height = 200; - - assert.ok( a.width = width, "Set width" ); - assert.ok( a.height = height, "Set height" ); - - a.set( width, height ); - assert.strictEqual( a.width, width, "Get width" ); - assert.strictEqual( a.height, height, "Get height" ); - - } ); - - QUnit.test( "width", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "height", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isVector2", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "set", ( assert ) => { - - var a = new Vector2(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - - a.set( x, y ); - assert.ok( a.x == x, "Passed!" ); - assert.ok( a.y == y, "Passed!" ); - - } ); - - QUnit.test( "setScalar", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setX", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setY", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setComponent", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getComponent", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - var a = new Vector2( x, y ); - var b = new Vector2().copy( a ); - assert.ok( b.x == x, "Passed!" ); - assert.ok( b.y == y, "Passed!" ); - - // ensure that it is a true copy - a.x = 0; - a.y = - 1; - assert.ok( b.x == x, "Passed!" ); - assert.ok( b.y == y, "Passed!" ); - - } ); - - QUnit.test( "add", ( assert ) => { - - var a = new Vector2( x, y ); - var b = new Vector2( - x, - y ); - - a.add( b ); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - - var c = new Vector2().addVectors( b, b ); - assert.ok( c.x == - 2 * x, "Passed!" ); - assert.ok( c.y == - 2 * y, "Passed!" ); - - } ); - - QUnit.test( "addScalar", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "addVectors", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "addScaledVector", ( assert ) => { - - var a = new Vector2( x, y ); - var b = new Vector2( 2, 3 ); - var s = 3; - - a.addScaledVector( b, s ); - assert.strictEqual( a.x, x + b.x * s, "Check x" ); - assert.strictEqual( a.y, y + b.y * s, "Check y" ); - - } ); - - QUnit.test( "sub", ( assert ) => { - - var a = new Vector2( x, y ); - var b = new Vector2( - x, - y ); - - a.sub( b ); - assert.ok( a.x == 2 * x, "Passed!" ); - assert.ok( a.y == 2 * y, "Passed!" ); - - var c = new Vector2().subVectors( a, a ); - assert.ok( c.x == 0, "Passed!" ); - assert.ok( c.y == 0, "Passed!" ); - - } ); - - QUnit.test( "subScalar", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "subVectors", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "multiply", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "multiplyScalar", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "divide", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "divideScalar", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "applyMatrix3", ( assert ) => { - - var a = new Vector2( x, y ); - var m = new Matrix3().set( 2, 3, 5, 7, 11, 13, 17, 19, 23 ); - - a.applyMatrix3( m ); - assert.strictEqual( a.x, 18, "Check x" ); - assert.strictEqual( a.y, 60, "Check y" ); - - } ); - - QUnit.test( "min", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "max", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clamp", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clampScalar", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clampLength", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "floor", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "ceil", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "round", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "roundToZero", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "negate", ( assert ) => { - - var a = new Vector2( x, y ); - - a.negate(); - assert.ok( a.x == - x, "Passed!" ); - assert.ok( a.y == - y, "Passed!" ); - - } ); - - QUnit.test( "dot", ( assert ) => { - - var a = new Vector2( x, y ); - var b = new Vector2( - x, - y ); - var c = new Vector2(); - - var result = a.dot( b ); - assert.ok( result == ( - x * x - y * y ), "Passed!" ); - - var result = a.dot( c ); - assert.ok( result == 0, "Passed!" ); - - } ); - - QUnit.test( "lengthSq", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "length", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "manhattanLength", ( assert ) => { - - var a = new Vector2( x, 0 ); - var b = new Vector2( 0, - y ); - var c = new Vector2(); - - assert.strictEqual( a.manhattanLength(), x, "Positive component" ); - assert.strictEqual( b.manhattanLength(), y, "Negative component" ); - assert.strictEqual( c.manhattanLength(), 0, "Empty component" ); - - a.set( x, y ); - assert.strictEqual( a.manhattanLength(), Math.abs( x ) + Math.abs( y ), "Two components" ); - - } ); - - QUnit.test( "normalize", ( assert ) => { - - var a = new Vector2( x, 0 ); - var b = new Vector2( 0, - y ); - var c = new Vector2(); - - a.normalize(); - assert.ok( a.length() == 1, "Passed!" ); - assert.ok( a.x == 1, "Passed!" ); - - b.normalize(); - assert.ok( b.length() == 1, "Passed!" ); - assert.ok( b.y == - 1, "Passed!" ); - - } ); - - QUnit.test( "angle", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "distanceTo", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "distanceToSquared", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "manhattanDistanceTo", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setLength", ( assert ) => { - - var a = new Vector2( x, 0 ); - - assert.ok( a.length() == x, "Passed!" ); - a.setLength( y ); - assert.ok( a.length() == y, "Passed!" ); - - var a = new Vector2( 0, 0 ); - assert.ok( a.length() == 0, "Passed!" ); - a.setLength( y ); - assert.ok( a.length() == 0, "Passed!" ); - a.setLength(); - assert.ok( isNaN( a.length() ), "Passed!" ); - - } ); - - QUnit.test( "lerp", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "lerpVectors", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "equals", ( assert ) => { - - var a = new Vector2( x, 0 ); - var b = new Vector2( 0, - y ); - - assert.ok( a.x != b.x, "Passed!" ); - assert.ok( a.y != b.y, "Passed!" ); - - assert.ok( ! a.equals( b ), "Passed!" ); - assert.ok( ! b.equals( a ), "Passed!" ); - - a.copy( b ); - assert.ok( a.x == b.x, "Passed!" ); - assert.ok( a.y == b.y, "Passed!" ); - - assert.ok( a.equals( b ), "Passed!" ); - assert.ok( b.equals( a ), "Passed!" ); - - } ); - - QUnit.test( "fromArray", ( assert ) => { - - var a = new Vector2(); - var array = [ 1, 2, 3, 4 ]; - - a.fromArray( array ); - assert.strictEqual( a.x, 1, "No offset: check x" ); - assert.strictEqual( a.y, 2, "No offset: check y" ); - - a.fromArray( array, 2 ); - assert.strictEqual( a.x, 3, "With offset: check x" ); - assert.strictEqual( a.y, 4, "With offset: check y" ); - - } ); - - QUnit.test( "toArray", ( assert ) => { - - var a = new Vector2( x, y ); - - var array = a.toArray(); - assert.strictEqual( array[ 0 ], x, "No array, no offset: check x" ); - assert.strictEqual( array[ 1 ], y, "No array, no offset: check y" ); - - var array = []; - a.toArray( array ); - assert.strictEqual( array[ 0 ], x, "With array, no offset: check x" ); - assert.strictEqual( array[ 1 ], y, "With array, no offset: check y" ); - - var array = []; - a.toArray( array, 1 ); - assert.strictEqual( array[ 0 ], undefined, "With array and offset: check [0]" ); - assert.strictEqual( array[ 1 ], x, "With array and offset: check x" ); - assert.strictEqual( array[ 2 ], y, "With array and offset: check y" ); - - } ); - - QUnit.test( "fromBufferAttribute", ( assert ) => { - - var a = new Vector2(); - var attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4 ] ), 2 ); - - a.fromBufferAttribute( attr, 0 ); - assert.strictEqual( a.x, 1, "Offset 0: check x" ); - assert.strictEqual( a.y, 2, "Offset 0: check y" ); - - a.fromBufferAttribute( attr, 1 ); - assert.strictEqual( a.x, 3, "Offset 1: check x" ); - assert.strictEqual( a.y, 4, "Offset 1: check y" ); - - } ); - - QUnit.test( "rotateAround", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - - // TODO (Itee) refactor/split - QUnit.test( "setX,setY", ( assert ) => { - - var a = new Vector2(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - - a.setX( x ); - a.setY( y ); - assert.ok( a.x == x, "Passed!" ); - assert.ok( a.y == y, "Passed!" ); - - } ); - QUnit.test( "setComponent,getComponent", ( assert ) => { - - var a = new Vector2(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - - a.setComponent( 0, 1 ); - a.setComponent( 1, 2 ); - assert.ok( a.getComponent( 0 ) == 1, "Passed!" ); - assert.ok( a.getComponent( 1 ) == 2, "Passed!" ); - - } ); - QUnit.test( "multiply/divide", ( assert ) => { - - var a = new Vector2( x, y ); - var b = new Vector2( - x, - y ); - - a.multiplyScalar( - 2 ); - assert.ok( a.x == x * - 2, "Passed!" ); - assert.ok( a.y == y * - 2, "Passed!" ); - - b.multiplyScalar( - 2 ); - assert.ok( b.x == 2 * x, "Passed!" ); - assert.ok( b.y == 2 * y, "Passed!" ); - - a.divideScalar( - 2 ); - assert.ok( a.x == x, "Passed!" ); - assert.ok( a.y == y, "Passed!" ); - - b.divideScalar( - 2 ); - assert.ok( b.x == - x, "Passed!" ); - assert.ok( b.y == - y, "Passed!" ); - - } ); - QUnit.test( "min/max/clamp", ( assert ) => { - - var a = new Vector2( x, y ); - var b = new Vector2( - x, - y ); - var c = new Vector2(); - - c.copy( a ).min( b ); - assert.ok( c.x == - x, "Passed!" ); - assert.ok( c.y == - y, "Passed!" ); - - c.copy( a ).max( b ); - assert.ok( c.x == x, "Passed!" ); - assert.ok( c.y == y, "Passed!" ); - - c.set( - 2 * x, 2 * y ); - c.clamp( b, a ); - assert.ok( c.x == - x, "Passed!" ); - assert.ok( c.y == y, "Passed!" ); - - c.set( - 2 * x, 2 * x ); - c.clampScalar( - x, x ); - assert.equal( c.x, - x, "scalar clamp x" ); - assert.equal( c.y, x, "scalar clamp y" ); - - } ); - QUnit.test( "rounding", ( assert ) => { - - assert.deepEqual( new Vector2( - 0.1, 0.1 ).floor(), new Vector2( - 1, 0 ), "floor .1" ); - assert.deepEqual( new Vector2( - 0.5, 0.5 ).floor(), new Vector2( - 1, 0 ), "floor .5" ); - assert.deepEqual( new Vector2( - 0.9, 0.9 ).floor(), new Vector2( - 1, 0 ), "floor .9" ); - - assert.deepEqual( new Vector2( - 0.1, 0.1 ).ceil(), new Vector2( 0, 1 ), "ceil .1" ); - assert.deepEqual( new Vector2( - 0.5, 0.5 ).ceil(), new Vector2( 0, 1 ), "ceil .5" ); - assert.deepEqual( new Vector2( - 0.9, 0.9 ).ceil(), new Vector2( 0, 1 ), "ceil .9" ); - - assert.deepEqual( new Vector2( - 0.1, 0.1 ).round(), new Vector2( 0, 0 ), "round .1" ); - assert.deepEqual( new Vector2( - 0.5, 0.5 ).round(), new Vector2( 0, 1 ), "round .5" ); - assert.deepEqual( new Vector2( - 0.9, 0.9 ).round(), new Vector2( - 1, 1 ), "round .9" ); - - assert.deepEqual( new Vector2( - 0.1, 0.1 ).roundToZero(), new Vector2( 0, 0 ), "roundToZero .1" ); - assert.deepEqual( new Vector2( - 0.5, 0.5 ).roundToZero(), new Vector2( 0, 0 ), "roundToZero .5" ); - assert.deepEqual( new Vector2( - 0.9, 0.9 ).roundToZero(), new Vector2( 0, 0 ), "roundToZero .9" ); - assert.deepEqual( new Vector2( - 1.1, 1.1 ).roundToZero(), new Vector2( - 1, 1 ), "roundToZero 1.1" ); - assert.deepEqual( new Vector2( - 1.5, 1.5 ).roundToZero(), new Vector2( - 1, 1 ), "roundToZero 1.5" ); - assert.deepEqual( new Vector2( - 1.9, 1.9 ).roundToZero(), new Vector2( - 1, 1 ), "roundToZero 1.9" ); - - } ); - QUnit.test( "length/lengthSq", ( assert ) => { - - var a = new Vector2( x, 0 ); - var b = new Vector2( 0, - y ); - var c = new Vector2(); - - assert.ok( a.length() == x, "Passed!" ); - assert.ok( a.lengthSq() == x * x, "Passed!" ); - assert.ok( b.length() == y, "Passed!" ); - assert.ok( b.lengthSq() == y * y, "Passed!" ); - assert.ok( c.length() == 0, "Passed!" ); - assert.ok( c.lengthSq() == 0, "Passed!" ); - - a.set( x, y ); - assert.ok( a.length() == Math.sqrt( x * x + y * y ), "Passed!" ); - assert.ok( a.lengthSq() == ( x * x + y * y ), "Passed!" ); - - } ); - QUnit.test( "distanceTo/distanceToSquared", ( assert ) => { - - var a = new Vector2( x, 0 ); - var b = new Vector2( 0, - y ); - var c = new Vector2(); - - assert.ok( a.distanceTo( c ) == x, "Passed!" ); - assert.ok( a.distanceToSquared( c ) == x * x, "Passed!" ); - - assert.ok( b.distanceTo( c ) == y, "Passed!" ); - assert.ok( b.distanceToSquared( c ) == y * y, "Passed!" ); - - } ); - QUnit.test( "lerp/clone", ( assert ) => { - - var a = new Vector2( x, 0 ); - var b = new Vector2( 0, - y ); - - assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 0.5 ) ), "Passed!" ); - assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 1 ) ), "Passed!" ); - - assert.ok( a.clone().lerp( b, 0 ).equals( a ), "Passed!" ); - - assert.ok( a.clone().lerp( b, 0.5 ).x == x * 0.5, "Passed!" ); - assert.ok( a.clone().lerp( b, 0.5 ).y == - y * 0.5, "Passed!" ); - - assert.ok( a.clone().lerp( b, 1 ).equals( b ), "Passed!" ); - - } ); - QUnit.test( "setComponent/getComponent exceptions", ( assert ) => { - - var a = new Vector2( 0, 0 ); - - assert.throws( - function () { - - a.setComponent( 2, 0 ); - - }, - /index is out of range/, - "setComponent with an out of range index throws Error" - ); - assert.throws( - function () { - - a.getComponent( 2 ); - - }, - /index is out of range/, - "getComponent with an out of range index throws Error" - ); - - } ); - QUnit.test( "setScalar/addScalar/subScalar", ( assert ) => { - - var a = new Vector2( 1, 1 ); - var s = 3; - - a.setScalar( s ); - assert.strictEqual( a.x, s, "setScalar: check x" ); - assert.strictEqual( a.y, s, "setScalar: check y" ); - - a.addScalar( s ); - assert.strictEqual( a.x, 2 * s, "addScalar: check x" ); - assert.strictEqual( a.y, 2 * s, "addScalar: check y" ); - - a.subScalar( 2 * s ); - assert.strictEqual( a.x, 0, "subScalar: check x" ); - assert.strictEqual( a.y, 0, "subScalar: check y" ); - - } ); - QUnit.test( "multiply/divide", ( assert ) => { - - var a = new Vector2( x, y ); - var b = new Vector2( 2 * x, 2 * y ); - var c = new Vector2( 4 * x, 4 * y ); - - a.multiply( b ); - assert.strictEqual( a.x, x * b.x, "multiply: check x" ); - assert.strictEqual( a.y, y * b.y, "multiply: check y" ); - - b.divide( c ); - assert.strictEqual( b.x, 0.5, "divide: check x" ); - assert.strictEqual( b.y, 0.5, "divide: check y" ); - - } ); - - } ); - - } ); - - /** - * @author bhouston / http://exocortex.com - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Maths', () => { - - QUnit.module.todo( 'Vector3', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - var a = new Vector3(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); - - var a = new Vector3( x, y, z ); - assert.ok( a.x === x, "Passed!" ); - assert.ok( a.y === y, "Passed!" ); - assert.ok( a.z === z, "Passed!" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isVector3", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "set", ( assert ) => { - - var a = new Vector3(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); - - a.set( x, y, z ); - assert.ok( a.x == x, "Passed!" ); - assert.ok( a.y == y, "Passed!" ); - assert.ok( a.z == z, "Passed!" ); - - } ); - - QUnit.test( "setScalar", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setX", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setY", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setZ", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setComponent", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getComponent", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - var a = new Vector3( x, y, z ); - var b = new Vector3().copy( a ); - assert.ok( b.x == x, "Passed!" ); - assert.ok( b.y == y, "Passed!" ); - assert.ok( b.z == z, "Passed!" ); - - // ensure that it is a true copy - a.x = 0; - a.y = - 1; - a.z = - 2; - assert.ok( b.x == x, "Passed!" ); - assert.ok( b.y == y, "Passed!" ); - assert.ok( b.z == z, "Passed!" ); - - } ); - - QUnit.test( "add", ( assert ) => { - - var a = new Vector3( x, y, z ); - var b = new Vector3( - x, - y, - z ); - - a.add( b ); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); - - var c = new Vector3().addVectors( b, b ); - assert.ok( c.x == - 2 * x, "Passed!" ); - assert.ok( c.y == - 2 * y, "Passed!" ); - assert.ok( c.z == - 2 * z, "Passed!" ); - - } ); - - QUnit.test( "addScalar", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "addVectors", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "addScaledVector", ( assert ) => { - - var a = new Vector3( x, y, z ); - var b = new Vector3( 2, 3, 4 ); - var s = 3; - - a.addScaledVector( b, s ); - assert.strictEqual( a.x, x + b.x * s, "Check x" ); - assert.strictEqual( a.y, y + b.y * s, "Check y" ); - assert.strictEqual( a.z, z + b.z * s, "Check z" ); - - } ); - - QUnit.test( "sub", ( assert ) => { - - var a = new Vector3( x, y, z ); - var b = new Vector3( - x, - y, - z ); - - a.sub( b ); - assert.ok( a.x == 2 * x, "Passed!" ); - assert.ok( a.y == 2 * y, "Passed!" ); - assert.ok( a.z == 2 * z, "Passed!" ); - - var c = new Vector3().subVectors( a, a ); - assert.ok( c.x == 0, "Passed!" ); - assert.ok( c.y == 0, "Passed!" ); - assert.ok( c.z == 0, "Passed!" ); - - } ); - - QUnit.test( "subScalar", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "subVectors", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "multiply", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "multiplyScalar", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "multiplyVectors", ( assert ) => { - - var a = new Vector3( x, y, z ); - var b = new Vector3( 2, 3, - 5 ); - - var c = new Vector3().multiplyVectors( a, b ); - assert.strictEqual( c.x, x * 2, "Check x" ); - assert.strictEqual( c.y, y * 3, "Check y" ); - assert.strictEqual( c.z, z * - 5, "Check z" ); - - } ); - - QUnit.test( "applyEuler", ( assert ) => { - - var a = new Vector3( x, y, z ); - var euler = new Euler( 90, - 45, 0 ); - var expected = new Vector3( - 2.352970120501014, - 4.7441750936226645, 0.9779234597246458 ); - - a.applyEuler( euler ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "Check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "Check z" ); - - } ); - - QUnit.test( "applyAxisAngle", ( assert ) => { - - var a = new Vector3( x, y, z ); - var axis = new Vector3( 0, 1, 0 ); - var angle = Math.PI / 4.0; - var expected = new Vector3( 3 * Math.sqrt( 2 ), 3, Math.sqrt( 2 ) ); - - a.applyAxisAngle( axis, angle ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "Check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "Check z" ); - - } ); - - QUnit.test( "applyMatrix3", ( assert ) => { - - var a = new Vector3( x, y, z ); - var m = new Matrix3().set( 2, 3, 5, 7, 11, 13, 17, 19, 23 ); - - a.applyMatrix3( m ); - assert.strictEqual( a.x, 33, "Check x" ); - assert.strictEqual( a.y, 99, "Check y" ); - assert.strictEqual( a.z, 183, "Check z" ); - - } ); - - QUnit.test( "applyMatrix4", ( assert ) => { - - - var a = new Vector3( x, y, z ); - var b = new Vector4( x, y, z, 1 ); - - var m = new Matrix4().makeRotationX( Math.PI ); - a.applyMatrix4( m ); - b.applyMatrix4( m ); - assert.ok( a.x == b.x / b.w, "Passed!" ); - assert.ok( a.y == b.y / b.w, "Passed!" ); - assert.ok( a.z == b.z / b.w, "Passed!" ); - - var m = new Matrix4().makeTranslation( 3, 2, 1 ); - a.applyMatrix4( m ); - b.applyMatrix4( m ); - assert.ok( a.x == b.x / b.w, "Passed!" ); - assert.ok( a.y == b.y / b.w, "Passed!" ); - assert.ok( a.z == b.z / b.w, "Passed!" ); - - var m = new Matrix4().set( - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 1, 0 - ); - a.applyMatrix4( m ); - b.applyMatrix4( m ); - assert.ok( a.x == b.x / b.w, "Passed!" ); - assert.ok( a.y == b.y / b.w, "Passed!" ); - assert.ok( a.z == b.z / b.w, "Passed!" ); - - } ); - - QUnit.test( "applyQuaternion", ( assert ) => { - - var a = new Vector3( x, y, z ); - - a.applyQuaternion( new Quaternion() ); - assert.strictEqual( a.x, x, "Identity rotation: check x" ); - assert.strictEqual( a.y, y, "Identity rotation: check y" ); - assert.strictEqual( a.z, z, "Identity rotation: check z" ); - - a.applyQuaternion( new Quaternion( x, y, z, w ) ); - assert.strictEqual( a.x, 108, "Normal rotation: check x" ); - assert.strictEqual( a.y, 162, "Normal rotation: check y" ); - assert.strictEqual( a.z, 216, "Normal rotation: check z" ); - - } ); - - QUnit.test( "project", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "unproject", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "transformDirection", ( assert ) => { - - var a = new Vector3( x, y, z ); - var m = new Matrix4(); - var transformed = new Vector3( 0.3713906763541037, 0.5570860145311556, 0.7427813527082074 ); - - a.transformDirection( m ); - assert.ok( Math.abs( a.x - transformed.x ) <= eps, "Check x" ); - assert.ok( Math.abs( a.y - transformed.y ) <= eps, "Check y" ); - assert.ok( Math.abs( a.z - transformed.z ) <= eps, "Check z" ); - - } ); - - QUnit.test( "divide", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "divideScalar", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "min", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "max", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clamp", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clampScalar", ( assert ) => { - - var a = new Vector3( - 0.01, 0.5, 1.5 ); - var clamped = new Vector3( 0.1, 0.5, 1.0 ); - - a.clampScalar( 0.1, 1.0 ); - assert.ok( Math.abs( a.x - clamped.x ) <= 0.001, "Check x" ); - assert.ok( Math.abs( a.y - clamped.y ) <= 0.001, "Check y" ); - assert.ok( Math.abs( a.z - clamped.z ) <= 0.001, "Check z" ); - - } ); - - QUnit.test( "clampLength", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "floor", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "ceil", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "round", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "roundToZero", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "negate", ( assert ) => { - - var a = new Vector3( x, y, z ); - - a.negate(); - assert.ok( a.x == - x, "Passed!" ); - assert.ok( a.y == - y, "Passed!" ); - assert.ok( a.z == - z, "Passed!" ); - - } ); - - QUnit.test( "dot", ( assert ) => { - - var a = new Vector3( x, y, z ); - var b = new Vector3( - x, - y, - z ); - var c = new Vector3(); - - var result = a.dot( b ); - assert.ok( result == ( - x * x - y * y - z * z ), "Passed!" ); - - var result = a.dot( c ); - assert.ok( result == 0, "Passed!" ); - - } ); - - QUnit.test( "lengthSq", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "length", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "manhattanLength", ( assert ) => { - - var a = new Vector3( x, 0, 0 ); - var b = new Vector3( 0, - y, 0 ); - var c = new Vector3( 0, 0, z ); - var d = new Vector3(); - - assert.ok( a.manhattanLength() == x, "Positive x" ); - assert.ok( b.manhattanLength() == y, "Negative y" ); - assert.ok( c.manhattanLength() == z, "Positive z" ); - assert.ok( d.manhattanLength() == 0, "Empty initialization" ); - - a.set( x, y, z ); - assert.ok( a.manhattanLength() == Math.abs( x ) + Math.abs( y ) + Math.abs( z ), "All components" ); - - } ); - - QUnit.test( "normalize", ( assert ) => { - - var a = new Vector3( x, 0, 0 ); - var b = new Vector3( 0, - y, 0 ); - var c = new Vector3( 0, 0, z ); - - a.normalize(); - assert.ok( a.length() == 1, "Passed!" ); - assert.ok( a.x == 1, "Passed!" ); - - b.normalize(); - assert.ok( b.length() == 1, "Passed!" ); - assert.ok( b.y == - 1, "Passed!" ); - - c.normalize(); - assert.ok( c.length() == 1, "Passed!" ); - assert.ok( c.z == 1, "Passed!" ); - - } ); - - QUnit.test( "setLength", ( assert ) => { - - var a = new Vector3( x, 0, 0 ); - - assert.ok( a.length() == x, "Passed!" ); - a.setLength( y ); - assert.ok( a.length() == y, "Passed!" ); - - var a = new Vector3( 0, 0, 0 ); - assert.ok( a.length() == 0, "Passed!" ); - a.setLength( y ); - assert.ok( a.length() == 0, "Passed!" ); - a.setLength(); - assert.ok( isNaN( a.length() ), "Passed!" ); - - } ); - - QUnit.test( "lerp", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "lerpVectors", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "cross", ( assert ) => { - - var a = new Vector3( x, y, z ); - var b = new Vector3( 2 * x, - y, 0.5 * z ); - var crossed = new Vector3( 18, 12, - 18 ); - - a.cross( b ); - assert.ok( Math.abs( a.x - crossed.x ) <= eps, "Check x" ); - assert.ok( Math.abs( a.y - crossed.y ) <= eps, "Check y" ); - assert.ok( Math.abs( a.z - crossed.z ) <= eps, "Check z" ); - - } ); - - QUnit.test( "crossVectors", ( assert ) => { - - var a = new Vector3( x, y, z ); - var b = new Vector3( x, - y, z ); - var c = new Vector3(); - var crossed = new Vector3( 24, 0, - 12 ); - - c.crossVectors( a, b ); - assert.ok( Math.abs( c.x - crossed.x ) <= eps, "Check x" ); - assert.ok( Math.abs( c.y - crossed.y ) <= eps, "Check y" ); - assert.ok( Math.abs( c.z - crossed.z ) <= eps, "Check z" ); - - } ); - - QUnit.test( "projectOnVector", ( assert ) => { - - var a = new Vector3( 1, 0, 0 ); - var b = new Vector3(); - var normal = new Vector3( 10, 0, 0 ); - - assert.ok( b.copy( a ).projectOnVector( normal ).equals( new Vector3( 1, 0, 0 ) ), "Passed!" ); - - a.set( 0, 1, 0 ); - assert.ok( b.copy( a ).projectOnVector( normal ).equals( new Vector3( 0, 0, 0 ) ), "Passed!" ); - - a.set( 0, 0, - 1 ); - assert.ok( b.copy( a ).projectOnVector( normal ).equals( new Vector3( 0, 0, 0 ) ), "Passed!" ); - - a.set( - 1, 0, 0 ); - assert.ok( b.copy( a ).projectOnVector( normal ).equals( new Vector3( - 1, 0, 0 ) ), "Passed!" ); - - } ); - - QUnit.test( "projectOnPlane", ( assert ) => { - - var a = new Vector3( 1, 0, 0 ); - var b = new Vector3(); - var normal = new Vector3( 1, 0, 0 ); - - assert.ok( b.copy( a ).projectOnPlane( normal ).equals( new Vector3( 0, 0, 0 ) ), "Passed!" ); - - a.set( 0, 1, 0 ); - assert.ok( b.copy( a ).projectOnPlane( normal ).equals( new Vector3( 0, 1, 0 ) ), "Passed!" ); - - a.set( 0, 0, - 1 ); - assert.ok( b.copy( a ).projectOnPlane( normal ).equals( new Vector3( 0, 0, - 1 ) ), "Passed!" ); - - a.set( - 1, 0, 0 ); - assert.ok( b.copy( a ).projectOnPlane( normal ).equals( new Vector3( 0, 0, 0 ) ), "Passed!" ); - - } ); - - QUnit.test( "reflect", ( assert ) => { - - var a = new Vector3(); - var normal = new Vector3( 0, 1, 0 ); - var b = new Vector3(); - - a.set( 0, - 1, 0 ); - assert.ok( b.copy( a ).reflect( normal ).equals( new Vector3( 0, 1, 0 ) ), "Passed!" ); - - a.set( 1, - 1, 0 ); - assert.ok( b.copy( a ).reflect( normal ).equals( new Vector3( 1, 1, 0 ) ), "Passed!" ); - - a.set( 1, - 1, 0 ); - normal.set( 0, - 1, 0 ); - assert.ok( b.copy( a ).reflect( normal ).equals( new Vector3( 1, 1, 0 ) ), "Passed!" ); - - } ); - - QUnit.test( "angleTo", ( assert ) => { - - var a = new Vector3( 0, - 0.18851655680720186, 0.9820700116639124 ); - var b = new Vector3( 0, 0.18851655680720186, - 0.9820700116639124 ); - - assert.equal( a.angleTo( a ), 0 ); - assert.equal( a.angleTo( b ), Math.PI ); - - var x$$1 = new Vector3( 1, 0, 0 ); - var y$$1 = new Vector3( 0, 1, 0 ); - var z$$1 = new Vector3( 0, 0, 1 ); - - assert.equal( x$$1.angleTo( y$$1 ), Math.PI / 2 ); - assert.equal( x$$1.angleTo( z$$1 ), Math.PI / 2 ); - assert.equal( z$$1.angleTo( x$$1 ), Math.PI / 2 ); - - assert.ok( Math.abs( x$$1.angleTo( new Vector3( 1, 1, 0 ) ) - ( Math.PI / 4 ) ) < 0.0000001 ); - - } ); - - QUnit.test( "distanceTo", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "distanceToSquared", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "manhattanDistanceTo", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setFromSpherical", ( assert ) => { - - var a = new Vector3(); - var phi = Math.acos( - 0.5 ); - var theta = Math.sqrt( Math.PI ) * phi; - var sph = new Spherical( 10, phi, theta ); - var expected = new Vector3( - 4.677914006701843, - 5, - 7.288149322420796 ); - - a.setFromSpherical( sph ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "Check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "Check z" ); - - } ); - - QUnit.test( "setFromCylindrical", ( assert ) => { - - var a = new Vector3(); - var cyl = new Cylindrical( 10, Math.PI * 0.125, 20 ); - var expected = new Vector3( 3.826834323650898, 20, 9.238795325112868 ); - - a.setFromCylindrical( cyl ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "Check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "Check z" ); - - } ); - - QUnit.test( "setFromMatrixPosition", ( assert ) => { - - var a = new Vector3(); - var m = new Matrix4().set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 ); - - a.setFromMatrixPosition( m ); - assert.strictEqual( a.x, 7, "Check x" ); - assert.strictEqual( a.y, 19, "Check y" ); - assert.strictEqual( a.z, 37, "Check z" ); - - } ); - - QUnit.test( "setFromMatrixScale", ( assert ) => { - - var a = new Vector3(); - var m = new Matrix4().set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 ); - var expected = new Vector3( 25.573423705088842, 31.921779399024736, 35.70714214271425 ); - - a.setFromMatrixScale( m ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "Check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "Check z" ); - - } ); - - QUnit.test( "setFromMatrixColumn", ( assert ) => { - - var a = new Vector3(); - var m = new Matrix4().set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 ); - - a.setFromMatrixColumn( m, 0 ); - assert.strictEqual( a.x, 2, "Index 0: check x" ); - assert.strictEqual( a.y, 11, "Index 0: check y" ); - assert.strictEqual( a.z, 23, "Index 0: check z" ); - - a.setFromMatrixColumn( m, 2 ); - assert.strictEqual( a.x, 5, "Index 2: check x" ); - assert.strictEqual( a.y, 17, "Index 2: check y" ); - assert.strictEqual( a.z, 31, "Index 2: check z" ); - - } ); - - QUnit.test( "equals", ( assert ) => { - - var a = new Vector3( x, 0, z ); - var b = new Vector3( 0, - y, 0 ); - - assert.ok( a.x != b.x, "Passed!" ); - assert.ok( a.y != b.y, "Passed!" ); - assert.ok( a.z != b.z, "Passed!" ); - - assert.ok( ! a.equals( b ), "Passed!" ); - assert.ok( ! b.equals( a ), "Passed!" ); - - a.copy( b ); - assert.ok( a.x == b.x, "Passed!" ); - assert.ok( a.y == b.y, "Passed!" ); - assert.ok( a.z == b.z, "Passed!" ); - - assert.ok( a.equals( b ), "Passed!" ); - assert.ok( b.equals( a ), "Passed!" ); - - } ); - - QUnit.test( "fromArray", ( assert ) => { - - var a = new Vector3(); - var array = [ 1, 2, 3, 4, 5, 6 ]; - - a.fromArray( array ); - assert.strictEqual( a.x, 1, "No offset: check x" ); - assert.strictEqual( a.y, 2, "No offset: check y" ); - assert.strictEqual( a.z, 3, "No offset: check z" ); - - a.fromArray( array, 3 ); - assert.strictEqual( a.x, 4, "With offset: check x" ); - assert.strictEqual( a.y, 5, "With offset: check y" ); - assert.strictEqual( a.z, 6, "With offset: check z" ); - - } ); - - QUnit.test( "toArray", ( assert ) => { - - var a = new Vector3( x, y, z ); - - var array = a.toArray(); - assert.strictEqual( array[ 0 ], x, "No array, no offset: check x" ); - assert.strictEqual( array[ 1 ], y, "No array, no offset: check y" ); - assert.strictEqual( array[ 2 ], z, "No array, no offset: check z" ); - - var array = []; - a.toArray( array ); - assert.strictEqual( array[ 0 ], x, "With array, no offset: check x" ); - assert.strictEqual( array[ 1 ], y, "With array, no offset: check y" ); - assert.strictEqual( array[ 2 ], z, "With array, no offset: check z" ); - - var array = []; - a.toArray( array, 1 ); - assert.strictEqual( array[ 0 ], undefined, "With array and offset: check [0]" ); - assert.strictEqual( array[ 1 ], x, "With array and offset: check x" ); - assert.strictEqual( array[ 2 ], y, "With array and offset: check y" ); - assert.strictEqual( array[ 3 ], z, "With array and offset: check z" ); - - } ); - - QUnit.test( "fromBufferAttribute", ( assert ) => { - - var a = new Vector3(); - var attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6 ] ), 3 ); - - a.fromBufferAttribute( attr, 0 ); - assert.strictEqual( a.x, 1, "Offset 0: check x" ); - assert.strictEqual( a.y, 2, "Offset 0: check y" ); - assert.strictEqual( a.z, 3, "Offset 0: check z" ); - - a.fromBufferAttribute( attr, 1 ); - assert.strictEqual( a.x, 4, "Offset 1: check x" ); - assert.strictEqual( a.y, 5, "Offset 1: check y" ); - assert.strictEqual( a.z, 6, "Offset 1: check z" ); - - } ); - - // TODO (Itee) refactor/split - QUnit.test( "setX,setY,setZ", ( assert ) => { - - var a = new Vector3(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); - - a.setX( x ); - a.setY( y ); - a.setZ( z ); - - assert.ok( a.x == x, "Passed!" ); - assert.ok( a.y == y, "Passed!" ); - assert.ok( a.z == z, "Passed!" ); - - } ); - QUnit.test( "setComponent,getComponent", ( assert ) => { - - var a = new Vector3(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); - - a.setComponent( 0, 1 ); - a.setComponent( 1, 2 ); - a.setComponent( 2, 3 ); - assert.ok( a.getComponent( 0 ) == 1, "Passed!" ); - assert.ok( a.getComponent( 1 ) == 2, "Passed!" ); - assert.ok( a.getComponent( 2 ) == 3, "Passed!" ); - - } ); - QUnit.test( "setComponent/getComponent exceptions", ( assert ) => { - - var a = new Vector3(); - - assert.throws( - function () { - - a.setComponent( 3, 0 ); - - }, - /index is out of range/, - "setComponent with an out of range index throws Error" - ); - assert.throws( - function () { - - a.getComponent( 3 ); - - }, - /index is out of range/, - "getComponent with an out of range index throws Error" - ); - - } ); - QUnit.test( "min/max/clamp", ( assert ) => { - - var a = new Vector3( x, y, z ); - var b = new Vector3( - x, - y, - z ); - var c = new Vector3(); - - c.copy( a ).min( b ); - assert.ok( c.x == - x, "Passed!" ); - assert.ok( c.y == - y, "Passed!" ); - assert.ok( c.z == - z, "Passed!" ); - - c.copy( a ).max( b ); - assert.ok( c.x == x, "Passed!" ); - assert.ok( c.y == y, "Passed!" ); - assert.ok( c.z == z, "Passed!" ); - - c.set( - 2 * x, 2 * y, - 2 * z ); - c.clamp( b, a ); - assert.ok( c.x == - x, "Passed!" ); - assert.ok( c.y == y, "Passed!" ); - assert.ok( c.z == - z, "Passed!" ); - - } ); - QUnit.test( "distanceTo/distanceToSquared", ( assert ) => { - - var a = new Vector3( x, 0, 0 ); - var b = new Vector3( 0, - y, 0 ); - var c = new Vector3( 0, 0, z ); - var d = new Vector3(); - - assert.ok( a.distanceTo( d ) == x, "Passed!" ); - assert.ok( a.distanceToSquared( d ) == x * x, "Passed!" ); - - assert.ok( b.distanceTo( d ) == y, "Passed!" ); - assert.ok( b.distanceToSquared( d ) == y * y, "Passed!" ); - - assert.ok( c.distanceTo( d ) == z, "Passed!" ); - assert.ok( c.distanceToSquared( d ) == z * z, "Passed!" ); - - } ); - QUnit.test( "setScalar/addScalar/subScalar", ( assert ) => { - - var a = new Vector3(); - var s = 3; - - a.setScalar( s ); - assert.strictEqual( a.x, s, "setScalar: check x" ); - assert.strictEqual( a.y, s, "setScalar: check y" ); - assert.strictEqual( a.z, s, "setScalar: check z" ); - - a.addScalar( s ); - assert.strictEqual( a.x, 2 * s, "addScalar: check x" ); - assert.strictEqual( a.y, 2 * s, "addScalar: check y" ); - assert.strictEqual( a.z, 2 * s, "addScalar: check z" ); - - a.subScalar( 2 * s ); - assert.strictEqual( a.x, 0, "subScalar: check x" ); - assert.strictEqual( a.y, 0, "subScalar: check y" ); - assert.strictEqual( a.z, 0, "subScalar: check z" ); - - } ); - QUnit.test( "multiply/divide", ( assert ) => { - - var a = new Vector3( x, y, z ); - var b = new Vector3( 2 * x, 2 * y, 2 * z ); - var c = new Vector3( 4 * x, 4 * y, 4 * z ); - - a.multiply( b ); - assert.strictEqual( a.x, x * b.x, "multiply: check x" ); - assert.strictEqual( a.y, y * b.y, "multiply: check y" ); - assert.strictEqual( a.z, z * b.z, "multiply: check z" ); - - b.divide( c ); - assert.ok( Math.abs( b.x - 0.5 ) <= eps, "divide: check z" ); - assert.ok( Math.abs( b.y - 0.5 ) <= eps, "divide: check z" ); - assert.ok( Math.abs( b.z - 0.5 ) <= eps, "divide: check z" ); - - } ); - QUnit.test( "multiply/divide", ( assert ) => { - - var a = new Vector3( x, y, z ); - var b = new Vector3( - x, - y, - z ); - - a.multiplyScalar( - 2 ); - assert.ok( a.x == x * - 2, "Passed!" ); - assert.ok( a.y == y * - 2, "Passed!" ); - assert.ok( a.z == z * - 2, "Passed!" ); - - b.multiplyScalar( - 2 ); - assert.ok( b.x == 2 * x, "Passed!" ); - assert.ok( b.y == 2 * y, "Passed!" ); - assert.ok( b.z == 2 * z, "Passed!" ); - - a.divideScalar( - 2 ); - assert.ok( a.x == x, "Passed!" ); - assert.ok( a.y == y, "Passed!" ); - assert.ok( a.z == z, "Passed!" ); - - b.divideScalar( - 2 ); - assert.ok( b.x == - x, "Passed!" ); - assert.ok( b.y == - y, "Passed!" ); - assert.ok( b.z == - z, "Passed!" ); - - } ); - QUnit.test( "project/unproject", ( assert ) => { - - var a = new Vector3( x, y, z ); - var camera = new PerspectiveCamera( 75, 16 / 9, 0.1, 300.0 ); - var projected = new Vector3( - 0.36653213611158914, - 0.9774190296309043, 1.0506835611870624 ); - - a.project( camera ); - assert.ok( Math.abs( a.x - projected.x ) <= eps, "project: check x" ); - assert.ok( Math.abs( a.y - projected.y ) <= eps, "project: check y" ); - assert.ok( Math.abs( a.z - projected.z ) <= eps, "project: check z" ); - - a.unproject( camera ); - assert.ok( Math.abs( a.x - x ) <= eps, "unproject: check x" ); - assert.ok( Math.abs( a.y - y ) <= eps, "unproject: check y" ); - assert.ok( Math.abs( a.z - z ) <= eps, "unproject: check z" ); - - } ); - QUnit.test( "length/lengthSq", ( assert ) => { - - var a = new Vector3( x, 0, 0 ); - var b = new Vector3( 0, - y, 0 ); - var c = new Vector3( 0, 0, z ); - var d = new Vector3(); - - assert.ok( a.length() == x, "Passed!" ); - assert.ok( a.lengthSq() == x * x, "Passed!" ); - assert.ok( b.length() == y, "Passed!" ); - assert.ok( b.lengthSq() == y * y, "Passed!" ); - assert.ok( c.length() == z, "Passed!" ); - assert.ok( c.lengthSq() == z * z, "Passed!" ); - assert.ok( d.length() == 0, "Passed!" ); - assert.ok( d.lengthSq() == 0, "Passed!" ); - - a.set( x, y, z ); - assert.ok( a.length() == Math.sqrt( x * x + y * y + z * z ), "Passed!" ); - assert.ok( a.lengthSq() == ( x * x + y * y + z * z ), "Passed!" ); - - } ); - QUnit.test( "lerp/clone", ( assert ) => { - - var a = new Vector3( x, 0, z ); - var b = new Vector3( 0, - y, 0 ); - - assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 0.5 ) ), "Passed!" ); - assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 1 ) ), "Passed!" ); - - assert.ok( a.clone().lerp( b, 0 ).equals( a ), "Passed!" ); - - assert.ok( a.clone().lerp( b, 0.5 ).x == x * 0.5, "Passed!" ); - assert.ok( a.clone().lerp( b, 0.5 ).y == - y * 0.5, "Passed!" ); - assert.ok( a.clone().lerp( b, 0.5 ).z == z * 0.5, "Passed!" ); - - assert.ok( a.clone().lerp( b, 1 ).equals( b ), "Passed!" ); - - } ); - - } ); - - } ); - - /** - * @author bhouston / http://exocortex.com - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Maths', () => { - - QUnit.module.todo( 'Vector4', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - var a = new Vector4(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); - assert.ok( a.w == 1, "Passed!" ); - - var a = new Vector4( x, y, z, w ); - assert.ok( a.x === x, "Passed!" ); - assert.ok( a.y === y, "Passed!" ); - assert.ok( a.z === z, "Passed!" ); - assert.ok( a.w === w, "Passed!" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isVector4", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "set", ( assert ) => { - - var a = new Vector4(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); - assert.ok( a.w == 1, "Passed!" ); - - a.set( x, y, z, w ); - assert.ok( a.x == x, "Passed!" ); - assert.ok( a.y == y, "Passed!" ); - assert.ok( a.z == z, "Passed!" ); - assert.ok( a.w == w, "Passed!" ); - - } ); - - QUnit.test( "setScalar", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setX", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setY", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setZ", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setW", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setComponent", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getComponent", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - var a = new Vector4( x, y, z, w ); - var b = new Vector4().copy( a ); - assert.ok( b.x == x, "Passed!" ); - assert.ok( b.y == y, "Passed!" ); - assert.ok( b.z == z, "Passed!" ); - assert.ok( b.w == w, "Passed!" ); - - // ensure that it is a true copy - a.x = 0; - a.y = - 1; - a.z = - 2; - a.w = - 3; - assert.ok( b.x == x, "Passed!" ); - assert.ok( b.y == y, "Passed!" ); - assert.ok( b.z == z, "Passed!" ); - assert.ok( b.w == w, "Passed!" ); - - } ); - - QUnit.test( "add", ( assert ) => { - - var a = new Vector4( x, y, z, w ); - var b = new Vector4( - x, - y, - z, - w ); - - a.add( b ); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); - assert.ok( a.w == 0, "Passed!" ); - - var c = new Vector4().addVectors( b, b ); - assert.ok( c.x == - 2 * x, "Passed!" ); - assert.ok( c.y == - 2 * y, "Passed!" ); - assert.ok( c.z == - 2 * z, "Passed!" ); - assert.ok( c.w == - 2 * w, "Passed!" ); - - } ); - - QUnit.test( "addScalar", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "addVectors", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "addScaledVector", ( assert ) => { - - var a = new Vector4( x, y, z, w ); - var b = new Vector4( 6, 7, 8, 9 ); - var s = 3; - - a.addScaledVector( b, s ); - assert.strictEqual( a.x, x + b.x * s, "Check x" ); - assert.strictEqual( a.y, y + b.y * s, "Check y" ); - assert.strictEqual( a.z, z + b.z * s, "Check z" ); - assert.strictEqual( a.w, w + b.w * s, "Check w" ); - - } ); - - QUnit.test( "sub", ( assert ) => { - - var a = new Vector4( x, y, z, w ); - var b = new Vector4( - x, - y, - z, - w ); - - a.sub( b ); - assert.ok( a.x == 2 * x, "Passed!" ); - assert.ok( a.y == 2 * y, "Passed!" ); - assert.ok( a.z == 2 * z, "Passed!" ); - assert.ok( a.w == 2 * w, "Passed!" ); - - var c = new Vector4().subVectors( a, a ); - assert.ok( c.x == 0, "Passed!" ); - assert.ok( c.y == 0, "Passed!" ); - assert.ok( c.z == 0, "Passed!" ); - assert.ok( c.w == 0, "Passed!" ); - - } ); - - QUnit.test( "subScalar", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "subVectors", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "multiplyScalar", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "applyMatrix4", ( assert ) => { - - var a = new Vector4( x, y, z, w ); - var m = new Matrix4().makeRotationX( Math.PI ); - var expected = new Vector4( 2, - 3, - 4, 5 ); - - a.applyMatrix4( m ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "Rotation matrix: check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Rotation matrix: check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "Rotation matrix: check z" ); - assert.ok( Math.abs( a.w - expected.w ) <= eps, "Rotation matrix: check w" ); - - a.set( x, y, z, w ); - m.makeTranslation( 5, 7, 11 ); - expected.set( 27, 38, 59, 5 ); - - a.applyMatrix4( m ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "Translation matrix: check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Translation matrix: check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "Translation matrix: check z" ); - assert.ok( Math.abs( a.w - expected.w ) <= eps, "Translation matrix: check w" ); - - a.set( x, y, z, w ); - m.set( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0 ); - expected.set( 2, 3, 4, 4 ); - - a.applyMatrix4( m ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "Custom matrix: check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Custom matrix: check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "Custom matrix: check z" ); - assert.ok( Math.abs( a.w - expected.w ) <= eps, "Custom matrix: check w" ); - - a.set( x, y, z, w ); - m.set( 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 ); - expected.set( 68, 224, 442, 664 ); - - a.applyMatrix4( m ); - assert.ok( Math.abs( a.x - expected.x ) <= eps, "Bogus matrix: check x" ); - assert.ok( Math.abs( a.y - expected.y ) <= eps, "Bogus matrix: check y" ); - assert.ok( Math.abs( a.z - expected.z ) <= eps, "Bogus matrix: check z" ); - assert.ok( Math.abs( a.w - expected.w ) <= eps, "Bogus matrix: check w" ); - - } ); - - QUnit.test( "divideScalar", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setAxisAngleFromQuaternion", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setAxisAngleFromRotationMatrix", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "min", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "max", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clamp", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clampScalar", ( assert ) => { - - var a = new Vector4( - 0.1, 0.01, 0.5, 1.5 ); - var clamped = new Vector4( 0.1, 0.1, 0.5, 1.0 ); - - a.clampScalar( 0.1, 1.0 ); - assert.ok( Math.abs( a.x - clamped.x ) <= eps, "Check x" ); - assert.ok( Math.abs( a.y - clamped.y ) <= eps, "Check y" ); - assert.ok( Math.abs( a.z - clamped.z ) <= eps, "Check z" ); - assert.ok( Math.abs( a.w - clamped.w ) <= eps, "Check w" ); - - } ); - - QUnit.test( "clampLength", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "floor", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "ceil", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "round", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "roundToZero", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "negate", ( assert ) => { - - var a = new Vector4( x, y, z, w ); - - a.negate(); - assert.ok( a.x == - x, "Passed!" ); - assert.ok( a.y == - y, "Passed!" ); - assert.ok( a.z == - z, "Passed!" ); - assert.ok( a.w == - w, "Passed!" ); - - } ); - - QUnit.test( "dot", ( assert ) => { - - var a = new Vector4( x, y, z, w ); - var b = new Vector4( - x, - y, - z, - w ); - var c = new Vector4( 0, 0, 0, 0 ); - - var result = a.dot( b ); - assert.ok( result == ( - x * x - y * y - z * z - w * w ), "Passed!" ); - - var result = a.dot( c ); - assert.ok( result == 0, "Passed!" ); - - } ); - - QUnit.test( "lengthSq", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "length", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "manhattanLength", ( assert ) => { - - var a = new Vector4( x, 0, 0, 0 ); - var b = new Vector4( 0, - y, 0, 0 ); - var c = new Vector4( 0, 0, z, 0 ); - var d = new Vector4( 0, 0, 0, w ); - var e = new Vector4( 0, 0, 0, 0 ); - - assert.ok( a.manhattanLength() == x, "Positive x" ); - assert.ok( b.manhattanLength() == y, "Negative y" ); - assert.ok( c.manhattanLength() == z, "Positive z" ); - assert.ok( d.manhattanLength() == w, "Positive w" ); - assert.ok( e.manhattanLength() == 0, "Empty initialization" ); - - a.set( x, y, z, w ); - assert.ok( - a.manhattanLength() == Math.abs( x ) + Math.abs( y ) + Math.abs( z ) + Math.abs( w ), - "All components" - ); - - } ); - - QUnit.test( "normalize", ( assert ) => { - - var a = new Vector4( x, 0, 0, 0 ); - var b = new Vector4( 0, - y, 0, 0 ); - var c = new Vector4( 0, 0, z, 0 ); - var d = new Vector4( 0, 0, 0, - w ); - - a.normalize(); - assert.ok( a.length() == 1, "Passed!" ); - assert.ok( a.x == 1, "Passed!" ); - - b.normalize(); - assert.ok( b.length() == 1, "Passed!" ); - assert.ok( b.y == - 1, "Passed!" ); - - c.normalize(); - assert.ok( c.length() == 1, "Passed!" ); - assert.ok( c.z == 1, "Passed!" ); - - d.normalize(); - assert.ok( d.length() == 1, "Passed!" ); - assert.ok( d.w == - 1, "Passed!" ); - - } ); - - QUnit.test( "setLength", ( assert ) => { - - var a = new Vector4( x, 0, 0, 0 ); - - assert.ok( a.length() == x, "Passed!" ); - a.setLength( y ); - assert.ok( a.length() == y, "Passed!" ); - - var a = new Vector4( 0, 0, 0, 0 ); - assert.ok( a.length() == 0, "Passed!" ); - a.setLength( y ); - assert.ok( a.length() == 0, "Passed!" ); - a.setLength(); - assert.ok( isNaN( a.length() ), "Passed!" ); - - } ); - - QUnit.test( "lerp", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "lerpVectors", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "equals", ( assert ) => { - - var a = new Vector4( x, 0, z, 0 ); - var b = new Vector4( 0, - y, 0, - w ); - - assert.ok( a.x != b.x, "Passed!" ); - assert.ok( a.y != b.y, "Passed!" ); - assert.ok( a.z != b.z, "Passed!" ); - assert.ok( a.w != b.w, "Passed!" ); - - assert.ok( ! a.equals( b ), "Passed!" ); - assert.ok( ! b.equals( a ), "Passed!" ); - - a.copy( b ); - assert.ok( a.x == b.x, "Passed!" ); - assert.ok( a.y == b.y, "Passed!" ); - assert.ok( a.z == b.z, "Passed!" ); - assert.ok( a.w == b.w, "Passed!" ); - - assert.ok( a.equals( b ), "Passed!" ); - assert.ok( b.equals( a ), "Passed!" ); - - } ); - - QUnit.test( "fromArray", ( assert ) => { - - var a = new Vector4(); - var array = [ 1, 2, 3, 4, 5, 6, 7, 8 ]; - - a.fromArray( array ); - assert.strictEqual( a.x, 1, "No offset: check x" ); - assert.strictEqual( a.y, 2, "No offset: check y" ); - assert.strictEqual( a.z, 3, "No offset: check z" ); - assert.strictEqual( a.w, 4, "No offset: check w" ); - - a.fromArray( array, 4 ); - assert.strictEqual( a.x, 5, "With offset: check x" ); - assert.strictEqual( a.y, 6, "With offset: check y" ); - assert.strictEqual( a.z, 7, "With offset: check z" ); - assert.strictEqual( a.w, 8, "With offset: check w" ); - - } ); - - QUnit.test( "toArray", ( assert ) => { - - var a = new Vector4( x, y, z, w ); - - var array = a.toArray(); - assert.strictEqual( array[ 0 ], x, "No array, no offset: check x" ); - assert.strictEqual( array[ 1 ], y, "No array, no offset: check y" ); - assert.strictEqual( array[ 2 ], z, "No array, no offset: check z" ); - assert.strictEqual( array[ 3 ], w, "No array, no offset: check w" ); - - var array = []; - a.toArray( array ); - assert.strictEqual( array[ 0 ], x, "With array, no offset: check x" ); - assert.strictEqual( array[ 1 ], y, "With array, no offset: check y" ); - assert.strictEqual( array[ 2 ], z, "With array, no offset: check z" ); - assert.strictEqual( array[ 3 ], w, "With array, no offset: check w" ); - - var array = []; - a.toArray( array, 1 ); - assert.strictEqual( array[ 0 ], undefined, "With array and offset: check [0]" ); - assert.strictEqual( array[ 1 ], x, "With array and offset: check x" ); - assert.strictEqual( array[ 2 ], y, "With array and offset: check y" ); - assert.strictEqual( array[ 3 ], z, "With array and offset: check z" ); - assert.strictEqual( array[ 4 ], w, "With array and offset: check w" ); - - } ); - - QUnit.test( "fromBufferAttribute", ( assert ) => { - - var a = new Vector4(); - var attr = new BufferAttribute( new Float32Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ), 4 ); - - a.fromBufferAttribute( attr, 0 ); - assert.strictEqual( a.x, 1, "Offset 0: check x" ); - assert.strictEqual( a.y, 2, "Offset 0: check y" ); - assert.strictEqual( a.z, 3, "Offset 0: check z" ); - assert.strictEqual( a.w, 4, "Offset 0: check w" ); - - a.fromBufferAttribute( attr, 1 ); - assert.strictEqual( a.x, 5, "Offset 1: check x" ); - assert.strictEqual( a.y, 6, "Offset 1: check y" ); - assert.strictEqual( a.z, 7, "Offset 1: check z" ); - assert.strictEqual( a.w, 8, "Offset 1: check w" ); - - } ); - - // TODO (Itee) refactor/split - QUnit.test( "setX,setY,setZ,setW", ( assert ) => { - - var a = new Vector4(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); - assert.ok( a.w == 1, "Passed!" ); - - a.setX( x ); - a.setY( y ); - a.setZ( z ); - a.setW( w ); - - assert.ok( a.x == x, "Passed!" ); - assert.ok( a.y == y, "Passed!" ); - assert.ok( a.z == z, "Passed!" ); - assert.ok( a.w == w, "Passed!" ); - - } ); - QUnit.test( "setComponent,getComponent", ( assert ) => { - - var a = new Vector4(); - assert.ok( a.x == 0, "Passed!" ); - assert.ok( a.y == 0, "Passed!" ); - assert.ok( a.z == 0, "Passed!" ); - assert.ok( a.w == 1, "Passed!" ); - - a.setComponent( 0, 1 ); - a.setComponent( 1, 2 ); - a.setComponent( 2, 3 ); - a.setComponent( 3, 4 ); - assert.ok( a.getComponent( 0 ) == 1, "Passed!" ); - assert.ok( a.getComponent( 1 ) == 2, "Passed!" ); - assert.ok( a.getComponent( 2 ) == 3, "Passed!" ); - assert.ok( a.getComponent( 3 ) == 4, "Passed!" ); - - } ); - QUnit.test( "setComponent/getComponent exceptions", ( assert ) => { - - var a = new Vector4(); - - assert.throws( - function () { - - a.setComponent( 4, 0 ); - - }, - /index is out of range/, - "setComponent with an out of range index throws Error" - ); - assert.throws( - function () { - - a.getComponent( 4 ); - - }, - /index is out of range/, - "getComponent with an out of range index throws Error" - ); - - } ); - QUnit.test( "setScalar/addScalar/subScalar", ( assert ) => { - - var a = new Vector4(); - var s = 3; - - a.setScalar( s ); - assert.strictEqual( a.x, s, "setScalar: check x" ); - assert.strictEqual( a.y, s, "setScalar: check y" ); - assert.strictEqual( a.z, s, "setScalar: check z" ); - assert.strictEqual( a.w, s, "setScalar: check w" ); - - a.addScalar( s ); - assert.strictEqual( a.x, 2 * s, "addScalar: check x" ); - assert.strictEqual( a.y, 2 * s, "addScalar: check y" ); - assert.strictEqual( a.z, 2 * s, "addScalar: check z" ); - assert.strictEqual( a.w, 2 * s, "addScalar: check w" ); - - a.subScalar( 2 * s ); - assert.strictEqual( a.x, 0, "subScalar: check x" ); - assert.strictEqual( a.y, 0, "subScalar: check y" ); - assert.strictEqual( a.z, 0, "subScalar: check z" ); - assert.strictEqual( a.w, 0, "subScalar: check w" ); - - } ); - QUnit.test( "multiply/divide", ( assert ) => { - - var a = new Vector4( x, y, z, w ); - var b = new Vector4( - x, - y, - z, - w ); - - a.multiplyScalar( - 2 ); - assert.ok( a.x == x * - 2, "Passed!" ); - assert.ok( a.y == y * - 2, "Passed!" ); - assert.ok( a.z == z * - 2, "Passed!" ); - assert.ok( a.w == w * - 2, "Passed!" ); - - b.multiplyScalar( - 2 ); - assert.ok( b.x == 2 * x, "Passed!" ); - assert.ok( b.y == 2 * y, "Passed!" ); - assert.ok( b.z == 2 * z, "Passed!" ); - assert.ok( b.w == 2 * w, "Passed!" ); - - a.divideScalar( - 2 ); - assert.ok( a.x == x, "Passed!" ); - assert.ok( a.y == y, "Passed!" ); - assert.ok( a.z == z, "Passed!" ); - assert.ok( a.w == w, "Passed!" ); - - b.divideScalar( - 2 ); - assert.ok( b.x == - x, "Passed!" ); - assert.ok( b.y == - y, "Passed!" ); - assert.ok( b.z == - z, "Passed!" ); - assert.ok( b.w == - w, "Passed!" ); - - } ); - QUnit.test( "min/max/clamp", ( assert ) => { - - var a = new Vector4( x, y, z, w ); - var b = new Vector4( - x, - y, - z, - w ); - var c = new Vector4(); - - c.copy( a ).min( b ); - assert.ok( c.x == - x, "Passed!" ); - assert.ok( c.y == - y, "Passed!" ); - assert.ok( c.z == - z, "Passed!" ); - assert.ok( c.w == - w, "Passed!" ); - - c.copy( a ).max( b ); - assert.ok( c.x == x, "Passed!" ); - assert.ok( c.y == y, "Passed!" ); - assert.ok( c.z == z, "Passed!" ); - assert.ok( c.w == w, "Passed!" ); - - c.set( - 2 * x, 2 * y, - 2 * z, 2 * w ); - c.clamp( b, a ); - assert.ok( c.x == - x, "Passed!" ); - assert.ok( c.y == y, "Passed!" ); - assert.ok( c.z == - z, "Passed!" ); - assert.ok( c.w == w, "Passed!" ); - - } ); - QUnit.test( "length/lengthSq", ( assert ) => { - - var a = new Vector4( x, 0, 0, 0 ); - var b = new Vector4( 0, - y, 0, 0 ); - var c = new Vector4( 0, 0, z, 0 ); - var d = new Vector4( 0, 0, 0, w ); - var e = new Vector4( 0, 0, 0, 0 ); - - assert.ok( a.length() == x, "Passed!" ); - assert.ok( a.lengthSq() == x * x, "Passed!" ); - assert.ok( b.length() == y, "Passed!" ); - assert.ok( b.lengthSq() == y * y, "Passed!" ); - assert.ok( c.length() == z, "Passed!" ); - assert.ok( c.lengthSq() == z * z, "Passed!" ); - assert.ok( d.length() == w, "Passed!" ); - assert.ok( d.lengthSq() == w * w, "Passed!" ); - assert.ok( e.length() == 0, "Passed!" ); - assert.ok( e.lengthSq() == 0, "Passed!" ); - - a.set( x, y, z, w ); - assert.ok( a.length() == Math.sqrt( x * x + y * y + z * z + w * w ), "Passed!" ); - assert.ok( a.lengthSq() == ( x * x + y * y + z * z + w * w ), "Passed!" ); - - } ); - QUnit.test( "lerp/clone", ( assert ) => { - - var a = new Vector4( x, 0, z, 0 ); - var b = new Vector4( 0, - y, 0, - w ); - - assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 0.5 ) ), "Passed!" ); - assert.ok( a.lerp( a, 0 ).equals( a.lerp( a, 1 ) ), "Passed!" ); - - assert.ok( a.clone().lerp( b, 0 ).equals( a ), "Passed!" ); - - assert.ok( a.clone().lerp( b, 0.5 ).x == x * 0.5, "Passed!" ); - assert.ok( a.clone().lerp( b, 0.5 ).y == - y * 0.5, "Passed!" ); - assert.ok( a.clone().lerp( b, 0.5 ).z == z * 0.5, "Passed!" ); - assert.ok( a.clone().lerp( b, 0.5 ).w == - w * 0.5, "Passed!" ); - - assert.ok( a.clone().lerp( b, 1 ).equals( b ), "Passed!" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Maths', () => { - - QUnit.module( 'Interpolants', () => { - - QUnit.module.todo( 'CubicInterpolant', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PRIVATE STUFF - QUnit.test( "DefaultSettings_", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "intervalChanged_", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "interpolate_", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Maths', () => { - - QUnit.module( 'Interpolants', () => { - - QUnit.module.todo( 'DiscreteInterpolant', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PRIVATE STUFF - QUnit.test( "interpolate_", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Maths', () => { - - QUnit.module( 'Interpolants', () => { - - QUnit.module.todo( 'LinearInterpolant', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PRIVATE STUFF - QUnit.test( "interpolate_", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Maths', () => { - - QUnit.module( 'Interpolants', () => { - - QUnit.module.todo( 'QuaternionLinearInterpolant', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PRIVATE STUFF - QUnit.test( "interpolate_", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Objects', () => { - - QUnit.module.todo( 'Bone', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isBone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Objects', () => { - - QUnit.module.todo( 'Group', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - function LensFlare( texture, size, distance, blending, color ) { - - Object3D.call( this ); - - this.lensFlares = []; - - this.positionScreen = new Vector3(); - this.customUpdateCallback = undefined; - - if ( texture !== undefined ) { - - this.add( texture, size, distance, blending, color ); - - } - - } - - LensFlare.prototype = Object.assign( Object.create( Object3D.prototype ), { - - constructor: LensFlare, - - isLensFlare: true, - - copy: function ( source ) { - - Object3D.prototype.copy.call( this, source ); - - this.positionScreen.copy( source.positionScreen ); - this.customUpdateCallback = source.customUpdateCallback; - - for ( var i = 0, l = source.lensFlares.length; i < l; i ++ ) { - - this.lensFlares.push( source.lensFlares[ i ] ); - - } - - return this; - - }, - - add: function ( texture, size, distance, blending, color, opacity ) { - - if ( size === undefined ) size = - 1; - if ( distance === undefined ) distance = 0; - if ( opacity === undefined ) opacity = 1; - if ( color === undefined ) color = new Color( 0xffffff ); - if ( blending === undefined ) blending = NormalBlending; - - distance = Math.min( distance, Math.max( 0, distance ) ); - - this.lensFlares.push( { - texture: texture, // THREE.Texture - size: size, // size in pixels (-1 = use texture.width) - distance: distance, // distance (0-1) from light source (0=at light source) - x: 0, y: 0, z: 0, // screen position (-1 => 1) z = 0 is in front z = 1 is back - scale: 1, // scale - rotation: 0, // rotation - opacity: opacity, // opacity - color: color, // color - blending: blending // blending - } ); - - }, - - /* - * Update lens flares update positions on all flares based on the screen position - * Set myLensFlare.customUpdateCallback to alter the flares in your project specific way. - */ - - updateLensFlares: function () { - - var f, fl = this.lensFlares.length; - var flare; - var vecX = - this.positionScreen.x * 2; - var vecY = - this.positionScreen.y * 2; - - for ( f = 0; f < fl; f ++ ) { - - flare = this.lensFlares[ f ]; - - flare.x = this.positionScreen.x + vecX * flare.distance; - flare.y = this.positionScreen.y + vecY * flare.distance; - - flare.wantedRotation = flare.x * Math.PI * 0.25; - flare.rotation += ( flare.wantedRotation - flare.rotation ) * 0.25; - - } - - } - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Objects', () => { - - QUnit.module.todo( 'LensFlare', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isLensFlare", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "add", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "updateLensFlares", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Objects', () => { - - QUnit.module.todo( 'Line', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isLine", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "raycast", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Objects', () => { - - QUnit.module.todo( 'LineLoop', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isLineLoop", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Objects', () => { - - QUnit.module.todo( 'LineSegments', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isLineSegments", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Objects', () => { - - QUnit.module.todo( 'LOD', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PROPERTIES - QUnit.test( "levels", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isLOD", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "addLevel", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "getObjectForDistance", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "raycast", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "update", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "toJSON", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Objects', () => { - - QUnit.module.todo( 'Mesh', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isMesh", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "setDrawMode", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "updateMorphTargets", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "raycast", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "clone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Objects', () => { - - QUnit.module.todo( 'Points', () => { - - // INHERITANCE - QUnit.test( "isPoints", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "raycast", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "clone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Objects', () => { - - QUnit.module.todo( 'Skeleton', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "calculateInverses", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "pose", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "update", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Objects', () => { - - QUnit.module.todo( 'SkinnedMesh', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isSkinnedMesh", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "initBones", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "bind", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "pose", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "normalizeSkinWeights", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "updateMatrixWorld", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "clone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Objects', () => { - - QUnit.module.todo( 'Sprite', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isSprite", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "raycast", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module.todo( 'WebGL2Renderer', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "domElement", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clear", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setPixelRatio", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setSize", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "render", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module.todo( 'WebGLRenderer', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "PrayForUs", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module.todo( 'WebGLRenderTarget', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isWebGLRenderTarget", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setSize", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "dispose", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module.todo( 'WebGLRenderTargetCube', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isWebGLRenderTargetCube", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'Shaders', () => { - - QUnit.module.todo( 'ShaderChunk', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'Shaders', () => { - - QUnit.module.todo( 'ShaderLib', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'Shaders', () => { - - QUnit.module.todo( 'UniformsLib', () => { - - // PUBLIC STUFF - QUnit.test( "merge", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'Shaders', () => { - - QUnit.module.todo( 'UniformsUtils', () => { - - QUnit.test( 'write me !', ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebGLAttributes', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "get", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "remove", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "update", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebGLBackground', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "getClearColor", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setClearColor", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getClearAlpha", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setClearAlpha", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "render", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebGLBufferRenderer', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "setMode", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "render", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "renderInstances", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebGLCapabilities', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "getMaxAnisotropy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getMaxPrecision", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "precision", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "logarithmicDepthBuffer", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "maxTextures", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "maxVertexTextures", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "maxTextureSize", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "maxCubemapSize", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "maxAttributes", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "maxVertexUniforms", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "maxVaryings", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "maxFragmentUniforms", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "vertexTextures", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "floatFragmentTextures", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "floatVertexTextures", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebGLClipping', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "init", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "beginShadows", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "endShadows", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setState", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebGLExtensions', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "get", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebGLFlareRenderer', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "render", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebGLGeometries', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "get", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "update", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getWireframeAttribute", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebGLIndexedBufferRenderer', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "setMode", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setIndex", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "render", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "renderInstances", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebGLLights', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "setup", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "state", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebGLMorphtargets', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "update", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebGLObjects', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "update", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clear", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebGLProgram', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PROPERTIES - QUnit.test( "uniforms", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "attributes", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "getUniforms", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getAttributes", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "destroy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebGLPrograms', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "getParameters", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getProgramCode", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "acquireProgram", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "releaseProgram", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "programs", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebGLProperties', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "get", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "remove", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clear", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebGLRenderLists', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "get", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "dispose", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebGLShader', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebGLShadowMap', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "render", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebGLSpriteRenderer', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "render", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebGLState', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "buffers", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "initAttributes", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "enableAttribute", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "enableAttributeAndDivisor", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "disableUnusedAttributes", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "enable", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "disable", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getCompressedTextureFormats", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "useProgram", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setBlending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setMaterial", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setFlipSided", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setCullFace", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setLineWidth", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setPolygonOffset", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setScissorTest", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "activeTexture", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "bindTexture", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "compressedTexImage2D", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "texImage2D", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "scissor", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "viewport", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "reset", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebGLTextures', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "setTexture2D", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "setTextureCube", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "setTextureCubeDynamic", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "setupRenderTarget", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - QUnit.test( "updateRenderTargetMipmap", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebGLUniforms', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "setValue", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setOptional", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "upload", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "seqWithValue", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebGLUtils', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "convert", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Renderers', () => { - - QUnit.module( 'WebGL', () => { - - QUnit.module.todo( 'WebVRManager', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "getDevice", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "setDevice", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getCamera", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "getStandingMatrix", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "submitFrame", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "dispose", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Fog', () => { - - QUnit.module.todo( 'Scene', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isFog", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "toJSON", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'FoxExp2', () => { - - QUnit.module.todo( 'Scene', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isFogExp2", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "toJSON", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Scenes', () => { - - QUnit.module.todo( 'Scene', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isScene", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "toJSON", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Textures', () => { - - QUnit.module.todo( 'CanvasTexture', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isCanvasTexture", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Textures', () => { - - QUnit.module.todo( 'CompressedTexture', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isCompressedTexture", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Textures', () => { - - QUnit.module.todo( 'CubeTexture', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PROPERTIES - QUnit.test( "images", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isCubeTexture", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Textures', () => { - - QUnit.module.todo( 'DataTexture', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isDataTexture", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author Matt DesLauriers / @mattdesl - * @author atix / arthursilber.de - */ - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Textures', () => { - - QUnit.module.todo( 'DepthTexture', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isDepthTexture", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Textures', () => { - - QUnit.module.todo( 'Texture', () => { - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PROPERTIES - QUnit.test( "needsUpdate", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isTexture", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "clone", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "copy", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "toJSON", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "dispose", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - QUnit.test( "transformUv", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author mrdoob / http://mrdoob.com/ - */ - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - /* global QUnit */ - - QUnit.module( 'Textures', () => { - - QUnit.module.todo( 'VideoTexture', () => { - - // INHERITANCE - QUnit.test( "Extending", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // INSTANCING - QUnit.test( "Instancing", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - // PUBLIC STUFF - QUnit.test( "isVideoTexture", ( assert ) => { - - assert.ok( false, "everything's gonna be alright" ); - - } ); - - } ); - - } ); - - /** - * @author TristanVALCKE / https://github.com/Itee - */ - - //src - - } ); - -}))); -- GitLab