Question
Using Three.js create a unique 3D animated scene. The scene has the following specifications: a. Size: minimum of 640x480 b. Includes at least 6 different
Using Three.js create a unique 3D animated scene. The scene has the following specifications: a. Size: minimum of 640x480 b. Includes at least 6 different shapes c. Uses multiple lighting effects d. Includes radio buttons, slider bars or other widgets to turn on or off certain components of the animation. 2. Use Three.js 3. All JavaScript source code should be written using Google JavaScript style guide.( http://google.github.io/styleguide/jsguide.html) 4. Prepare, conduct and document a test plan verifying your application is working as expected. This plan should include a test matrix listing each method you tested, how you tested it, and the results of testing Deliverables: 1. All JavaScript source code used for this project. Code should adhere to the Google Javascript file:///C:/Users/SP/AppData/Local/Temp/Rar$EXa0.697/threejs/anaglyph.html THREE.AnaglyphEffect = function ( renderer, width, height ) { var eyeRight = new THREE.Matrix4(); var eyeLeft = new THREE.Matrix4(); var focalLength = 125; var _aspect, _near, _far, _fov; var _cameraL = new THREE.PerspectiveCamera(); _cameraL.matrixAutoUpdate = false; var _cameraR = new THREE.PerspectiveCamera(); _cameraR.matrixAutoUpdate = false; var _camera = new THREE.OrthographicCamera( -1, 1, 1, - 1, 0, 1 ); var _scene = new THREE.Scene(); var _params = { minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter, format: THREE.RGBAFormat }; if ( width === undefined ) width = 512; if ( height === undefined ) height = 512; var _renderTargetL = new THREE.WebGLRenderTarget( width, height, _params ); var _renderTargetR = new THREE.WebGLRenderTarget( width, height, _params ); var _material = new THREE.ShaderMaterial( { uniforms: { "mapLeft": { type: "t", value: _renderTargetL }, "mapRight": { type: "t", value: _renderTargetR } }, vertexShader: [ "varying vec2 vUv;", "void main() {", " vUv = vec2( uv.x, uv.y );", " gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join(" "), fragmentShader: [ "uniform sampler2D mapLeft;", "uniform sampler2D mapRight;", "varying vec2 vUv;", "void main() {", " vec4 colorL, colorR;", " vec2 uv = vUv;", " colorL = texture2D( mapLeft, uv );", " colorR = texture2D( mapRight, uv );", // http://3dtv.at/Knowhow/AnaglyphComparison_en.aspx " gl_FragColor = vec4( colorL.g * 0.7 + colorL.b * 0.3, colorR.g, colorR.b, colorL.a + colorR.a ) * 1.1;", "}" ].join(" ") } ); var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), _material ); _scene.add( mesh ); this.setSize = function ( width, height ) { if ( _renderTargetL ) _renderTargetL.dispose(); if ( _renderTargetR ) _renderTargetR.dispose(); _renderTargetL = new THREE.WebGLRenderTarget( width, height, _params ); _renderTargetR = new THREE.WebGLRenderTarget( width, height, _params ); _material.uniforms[ "mapLeft" ].value = _renderTargetL; _material.uniforms[ "mapRight" ].value = _renderTargetR; renderer.setSize( width, height ); }; /* * Renderer now uses an asymmetric perspective projection * (http://paulbourke.net/miscellaneous/stereographics/stereorender/). * * Each camera is offset by the eye seperation and its projection matrix is * also skewed asymetrically back to converge on the same projection plane. * Added a focal length parameter to, this is where the parallax is equal to 0. */ this.render = function ( scene, camera ) { scene.updateMatrixWorld(); if ( camera.parent === undefined ) camera.updateMatrixWorld(); var hasCameraChanged = ( _aspect !== camera.aspect ) || ( _near !== camera.near ) || ( _far !== camera.far ) || ( _fov !== camera.fov ); if ( hasCameraChanged ) { _aspect = camera.aspect; _near = camera.near; _far = camera.far; _fov = camera.fov; var projectionMatrix = camera.projectionMatrix.clone(); var eyeSep = focalLength / 30 * 0.5; var eyeSepOnProjection = eyeSep * _near / focalLength; var ymax = _near * Math.tan( THREE.Math.degToRad( _fov * 0.5 ) ); var xmin, xmax; // translate xOffset eyeRight.elements[12] = eyeSep; eyeLeft.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 ); _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 ); _cameraR.projectionMatrix.copy( projectionMatrix ); } _cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( eyeLeft ); _cameraL.position.copy( camera.position ); _cameraL.near = camera.near; _cameraL.far = camera.far; renderer.render( scene, _cameraL, _renderTargetL, true ); _cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( eyeRight ); _cameraR.position.copy( camera.position ); _cameraR.near = camera.near; _cameraR.far = camera.far; renderer.render( scene, _cameraR, _renderTargetR, true ); renderer.render( _scene, _camera ); }; this.dispose = function() { if ( _renderTargetL ) _renderTargetL.dispose(); if ( _renderTargetR ) _renderTargetR.dispose(); } }; THREE.TrackballControls = function ( object, domElement ) { var _this = this; var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 }; this.object = object; this.domElement = ( domElement !== undefined ) ? domElement : document; // API this.enabled = true; this.screen = { left: 0, top: 0, width: 0, height: 0 }; this.rotateSpeed = 1.0; this.zoomSpeed = 1.2; this.panSpeed = 0.3; this.noRotate = false; this.noZoom = false; this.noPan = false; this.staticMoving = false; this.dynamicDampingFactor = 0.2; this.minDistance = 0; this.maxDistance = Infinity; this.keys = [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ]; // internals this.target = new THREE.Vector3(); var EPS = 0.000001; var lastPosition = new THREE.Vector3(); var _state = STATE.NONE, _prevState = STATE.NONE, _eye = new THREE.Vector3(), _movePrev = new THREE.Vector2(), _moveCurr = new THREE.Vector2(), _lastAxis = new THREE.Vector3(), _lastAngle = 0, _zoomStart = new THREE.Vector2(), _zoomEnd = new THREE.Vector2(), _touchZoomDistanceStart = 0, _touchZoomDistanceEnd = 0, _panStart = new THREE.Vector2(), _panEnd = new THREE.Vector2(); // for reset this.target0 = this.target.clone(); this.position0 = this.object.position.clone(); this.up0 = this.object.up.clone(); // events var changeEvent = { type: 'change' }; var startEvent = { type: 'start' }; var endEvent = { type: 'end' }; // methods this.handleResize = function () { if ( this.domElement === document ) { this.screen.left = 0; this.screen.top = 0; this.screen.width = window.innerWidth; this.screen.height = window.innerHeight; } else { var box = this.domElement.getBoundingClientRect(); // adjustments come from similar code in the jquery offset() function var d = this.domElement.ownerDocument.documentElement; this.screen.left = box.left - d.clientLeft; this.screen.top = box.top - d.clientTop; this.screen.width = box.width; this.screen.height = box.height; } }; this.handleEvent = function ( event ) { if ( typeof this[ event.type ] == 'function' ) { this[ event.type ]( event ); } }; var getMouseOnScreen = ( function () { var vector = new THREE.Vector2(); return function ( pageX, pageY ) { vector.set( ( pageX - _this.screen.left ) / _this.screen.width, ( pageY - _this.screen.top ) / _this.screen.height ); return vector; }; }() ); var getMouseOnCircle = ( function () { var vector = new THREE.Vector2(); return function ( pageX, pageY ) { vector.set( ( ( pageX - _this.screen.width * 0.5 - _this.screen.left ) / ( _this.screen.width * 0.5 ) ), ( ( _this.screen.height + 2 * ( _this.screen.top - pageY ) ) / _this.screen.width ) // screen.width intentional ); return vector; }; }() ); this.rotateCamera = (function() { var axis = new THREE.Vector3(), quaternion = new THREE.Quaternion(), eyeDirection = new THREE.Vector3(), objectUpDirection = new THREE.Vector3(), objectSidewaysDirection = new THREE.Vector3(), moveDirection = new THREE.Vector3(), angle; return function () { moveDirection.set( _moveCurr.x - _movePrev.x, _moveCurr.y - _movePrev.y, 0 ); angle = moveDirection.length(); if ( angle ) { _eye.copy( _this.object.position ).sub( _this.target ); eyeDirection.copy( _eye ).normalize(); objectUpDirection.copy( _this.object.up ).normalize(); objectSidewaysDirection.crossVectors( objectUpDirection, eyeDirection ).normalize(); objectUpDirection.setLength( _moveCurr.y - _movePrev.y ); objectSidewaysDirection.setLength( _moveCurr.x - _movePrev.x ); moveDirection.copy( objectUpDirection.add( objectSidewaysDirection ) ); axis.crossVectors( moveDirection, _eye ).normalize(); angle *= _this.rotateSpeed; quaternion.setFromAxisAngle( axis, angle ); _eye.applyQuaternion( quaternion ); _this.object.up.applyQuaternion( quaternion ); _lastAxis.copy( axis ); _lastAngle = angle; } else if ( !_this.staticMoving && _lastAngle ) { _lastAngle *= Math.sqrt( 1.0 - _this.dynamicDampingFactor ); _eye.copy( _this.object.position ).sub( _this.target ); quaternion.setFromAxisAngle( _lastAxis, _lastAngle ); _eye.applyQuaternion( quaternion ); _this.object.up.applyQuaternion( quaternion ); } _movePrev.copy( _moveCurr ); }; }()); this.zoomCamera = function () { var factor; if ( _state === STATE.TOUCH_ZOOM_PAN ) { factor = _touchZoomDistanceStart / _touchZoomDistanceEnd; _touchZoomDistanceStart = _touchZoomDistanceEnd; _eye.multiplyScalar( factor ); } else { factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed; if ( factor !== 1.0 && factor > 0.0 ) { _eye.multiplyScalar( factor ); if ( _this.staticMoving ) { _zoomStart.copy( _zoomEnd ); } else { _zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor; } } } }; this.panCamera = (function() { var mouseChange = new THREE.Vector2(), objectUp = new THREE.Vector3(), pan = new THREE.Vector3(); return function () { mouseChange.copy( _panEnd ).sub( _panStart ); if ( mouseChange.lengthSq() ) { mouseChange.multiplyScalar( _eye.length() * _this.panSpeed ); pan.copy( _eye ).cross( _this.object.up ).setLength( mouseChange.x ); pan.add( objectUp.copy( _this.object.up ).setLength( mouseChange.y ) ); _this.object.position.add( pan ); _this.target.add( pan ); if ( _this.staticMoving ) { _panStart.copy( _panEnd ); } else { _panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) ); } } }; }()); this.checkDistances = function () { if ( !_this.noZoom || !_this.noPan ) { if ( _eye.lengthSq() > _this.maxDistance * _this.maxDistance ) { _this.object.position.addVectors( _this.target, _eye.setLength( _this.maxDistance ) ); } if ( _eye.lengthSq() < _this.minDistance * _this.minDistance ) { _this.object.position.addVectors( _this.target, _eye.setLength( _this.minDistance ) ); } } }; this.update = function () { _eye.subVectors( _this.object.position, _this.target ); if ( !_this.noRotate ) { _this.rotateCamera(); } if ( !_this.noZoom ) { _this.zoomCamera(); } if ( !_this.noPan ) { _this.panCamera(); } _this.object.position.addVectors( _this.target, _eye ); _this.checkDistances(); _this.object.lookAt( _this.target ); if ( lastPosition.distanceToSquared( _this.object.position ) > EPS ) { _this.dispatchEvent( changeEvent ); lastPosition.copy( _this.object.position ); } }; this.reset = function () { _state = STATE.NONE; _prevState = STATE.NONE; _this.target.copy( _this.target0 ); _this.object.position.copy( _this.position0 ); _this.object.up.copy( _this.up0 ); _eye.subVectors( _this.object.position, _this.target ); _this.object.lookAt( _this.target ); _this.dispatchEvent( changeEvent ); lastPosition.copy( _this.object.position ); }; // listeners function keydown( event ) { if ( _this.enabled === false ) return; window.removeEventListener( 'keydown', keydown ); _prevState = _state; if ( _state !== STATE.NONE ) { return; } else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && !_this.noRotate ) { _state = STATE.ROTATE; } else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && !_this.noZoom ) { _state = STATE.ZOOM; } else if ( event.keyCode === _this.keys[ STATE.PAN ] && !_this.noPan ) { _state = STATE.PAN; } } function keyup( event ) { if ( _this.enabled === false ) return; _state = _prevState; window.addEventListener( 'keydown', keydown, false ); } function mousedown( event ) { if ( _this.enabled === false ) return; event.preventDefault(); event.stopPropagation(); if ( _state === STATE.NONE ) { _state = event.button; } if ( _state === STATE.ROTATE && !_this.noRotate ) { _moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) ); _movePrev.copy(_moveCurr); } else if ( _state === STATE.ZOOM && !_this.noZoom ) { _zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) ); _zoomEnd.copy(_zoomStart); } else if ( _state === STATE.PAN && !_this.noPan ) { _panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) ); _panEnd.copy(_panStart); } document.addEventListener( 'mousemove', mousemove, false ); document.addEventListener( 'mouseup', mouseup, false ); _this.dispatchEvent( startEvent ); } function mousemove( event ) { if ( _this.enabled === false ) return; event.preventDefault(); event.stopPropagation(); if ( _state === STATE.ROTATE && !_this.noRotate ) { _movePrev.copy(_moveCurr); _moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) ); } else if ( _state === STATE.ZOOM && !_this.noZoom ) { _zoomEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) ); } else if ( _state === STATE.PAN && !_this.noPan ) { _panEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) ); } } function mouseup( event ) { if ( _this.enabled === false ) return; event.preventDefault(); event.stopPropagation(); _state = STATE.NONE; document.removeEventListener( 'mousemove', mousemove ); document.removeEventListener( 'mouseup', mouseup ); _this.dispatchEvent( endEvent ); } function mousewheel( event ) { if ( _this.enabled === false ) return; event.preventDefault(); event.stopPropagation(); var delta = 0; if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9 delta = event.wheelDelta / 40; } else if ( event.detail ) { // Firefox delta = - event.detail / 3; } _zoomStart.y += delta * 0.01; _this.dispatchEvent( startEvent ); _this.dispatchEvent( endEvent ); } function touchstart( event ) { if ( _this.enabled === false ) return; switch ( event.touches.length ) { case 1: _state = STATE.TOUCH_ROTATE; _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); _movePrev.copy(_moveCurr); break; case 2: _state = STATE.TOUCH_ZOOM_PAN; var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; _touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy ); var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2; var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2; _panStart.copy( getMouseOnScreen( x, y ) ); _panEnd.copy( _panStart ); break; default: _state = STATE.NONE; } _this.dispatchEvent( startEvent ); } function touchmove( event ) { if ( _this.enabled === false ) return; event.preventDefault(); event.stopPropagation(); switch ( event.touches.length ) { case 1: _movePrev.copy(_moveCurr); _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); break; case 2: var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; _touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy ); var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2; var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2; _panEnd.copy( getMouseOnScreen( x, y ) ); break; default: _state = STATE.NONE; } } function touchend( event ) { if ( _this.enabled === false ) return; switch ( event.touches.length ) { case 1: _movePrev.copy(_moveCurr); _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); break; case 2: _touchZoomDistanceStart = _touchZoomDistanceEnd = 0; var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2; var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2; _panEnd.copy( getMouseOnScreen( x, y ) ); _panStart.copy( _panEnd ); break; } _state = STATE.NONE; _this.dispatchEvent( endEvent ); } this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false ); this.domElement.addEventListener( 'mousedown', mousedown, false ); this.domElement.addEventListener( 'mousewheel', mousewheel, false ); this.domElement.addEventListener( 'DOMMouseScroll', mousewheel, false ); // firefox this.domElement.addEventListener( 'touchstart', touchstart, false ); this.domElement.addEventListener( 'touchend', touchend, false ); this.domElement.addEventListener( 'touchmove', touchmove, false ); window.addEventListener( 'keydown', keydown, false ); window.addEventListener( 'keyup', keyup, false ); this.handleResize(); // force an update at start this.update(); }; THREE.TrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype ); THREE.TrackballControls.prototype.constructor = THREE.TrackballControls;
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started