Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

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

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Students also viewed these Databases questions