three#AdditiveBlending JavaScript Examples

The following examples show how to use three#AdditiveBlending. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: vr.js    From 3DTilesRendererJS with Apache License 2.0 6 votes vote down vote up
function buildController( data ) {

	let geometry, material;

	switch ( data.targetRayMode ) {

		case 'tracked-pointer':

			geometry = new BufferGeometry();
			geometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, - 1 ], 3 ) );
			geometry.setAttribute( 'color', new Float32BufferAttribute( [ 0.5, 0.5, 0.5, 0, 0, 0 ], 3 ) );

			material = new LineBasicMaterial( {
				vertexColors: true,
				blending: AdditiveBlending,
				depthWrite: false,
				transparent: true,
			} );

			return new Line( geometry, material );

		case 'gaze':

			geometry = new RingBufferGeometry( 0.02, 0.04, 32 ).translate( 0, 0, - 1 );
			material = new MeshBasicMaterial( { opacity: 0.5, transparent: true } );
			return new Mesh( geometry, material );

	}

}
Example #2
Source File: item.js    From architect3d with MIT License 6 votes vote down vote up
/** */
	createGlow(color, opacity, ignoreDepth)
	{
		ignoreDepth = ignoreDepth || false;
		opacity = opacity || 0.2;
		var glowMaterial = new MeshBasicMaterial({color: color, blending: AdditiveBlending, opacity: 0.2, transparent: true, depthTest: !ignoreDepth});
		var glow = new Mesh(this.geometry.clone(), glowMaterial);
		glow.position.copy(this.position);
		glow.rotation.copy(this.rotation);
		glow.scale.copy(this.scale);
		return glow;
	}
Example #3
Source File: SSAARenderPass.js    From Computer-Graphics with MIT License 6 votes vote down vote up
constructor( scene, camera, clearColor, clearAlpha ) {

		super();

		this.scene = scene;
		this.camera = camera;

		this.sampleLevel = 4; // specified as n, where the number of samples is 2^n, so sampleLevel = 4, is 2^4 samples, 16.
		this.unbiased = true;

		// as we need to clear the buffer in this pass, clearColor must be set to something, defaults to black.
		this.clearColor = ( clearColor !== undefined ) ? clearColor : 0x000000;
		this.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 0;
		this._oldClearColor = new Color();

		if ( CopyShader === undefined ) console.error( 'THREE.SSAARenderPass relies on CopyShader' );

		const copyShader = CopyShader;
		this.copyUniforms = UniformsUtils.clone( copyShader.uniforms );

		this.copyMaterial = new ShaderMaterial(	{
			uniforms: this.copyUniforms,
			vertexShader: copyShader.vertexShader,
			fragmentShader: copyShader.fragmentShader,
			premultipliedAlpha: true,
			transparent: true,
			blending: AdditiveBlending,
			depthTest: false,
			depthWrite: false
		} );

		this.fsQuad = new FullScreenQuad( this.copyMaterial );

	}
Example #4
Source File: Face.js    From sketch-webcam with MIT License 6 votes vote down vote up
constructor() {
    // Define Geometry
    const geometry = new BufferGeometry();
    const baPositions = new BufferAttribute(new Float32Array(468 * 3), 3);
    const baIndices = new BufferAttribute(TRIANGULATION, 1);
    geometry.setAttribute('position', baPositions);
    geometry.setIndex(baIndices);

    // Define Material
    const material = new RawShaderMaterial({
      uniforms: {
        time: {
          value: 0
        },
        texture: {
          value: null
        }
      },
      vertexShader: vs,
      fragmentShader: fs,
      side: BackSide,
      transparent: true,
      blending: AdditiveBlending
    });

    super(geometry, material);
    this.size = new Vector2();
    this.imgRatio = new Vector2();
  }
Example #5
Source File: FireBallFlare.js    From sketch-webcam with MIT License 6 votes vote down vote up
constructor() {
    const geometry = new IcosahedronBufferGeometry(2.2, 5);

    const material = new RawShaderMaterial({
      uniforms: {
        time: {
          value: 0
        },
        texture: {
          value: null
        },
        alphaShow: {
          value: 0
        },
        alphaHide: {
          value: 0
        }
      },
      vertexShader: vs,
      fragmentShader: fs,
      transparent: true,
      blending: AdditiveBlending,
      side: DoubleSide,
      depthWrite: false
    });

    super(geometry, material);
  }
Example #6
Source File: BloomPass.js    From Computer-Graphics with MIT License 5 votes vote down vote up
constructor( strength = 1, kernelSize = 25, sigma = 4, resolution = 256 ) {

		super();

		// render targets

		const pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat };

		this.renderTargetX = new WebGLRenderTarget( resolution, resolution, pars );
		this.renderTargetX.texture.name = 'BloomPass.x';
		this.renderTargetY = new WebGLRenderTarget( resolution, resolution, pars );
		this.renderTargetY.texture.name = 'BloomPass.y';

		// copy material

		if ( CopyShader === undefined ) console.error( 'THREE.BloomPass relies on CopyShader' );

		const copyShader = CopyShader;

		this.copyUniforms = UniformsUtils.clone( copyShader.uniforms );

		this.copyUniforms[ 'opacity' ].value = strength;

		this.materialCopy = new ShaderMaterial( {

			uniforms: this.copyUniforms,
			vertexShader: copyShader.vertexShader,
			fragmentShader: copyShader.fragmentShader,
			blending: AdditiveBlending,
			transparent: true

		} );

		// convolution material

		if ( ConvolutionShader === undefined ) console.error( 'THREE.BloomPass relies on ConvolutionShader' );

		const convolutionShader = ConvolutionShader;

		this.convolutionUniforms = UniformsUtils.clone( convolutionShader.uniforms );

		this.convolutionUniforms[ 'uImageIncrement' ].value = BloomPass.blurX;
		this.convolutionUniforms[ 'cKernel' ].value = ConvolutionShader.buildKernel( sigma );

		this.materialConvolution = new ShaderMaterial( {

			uniforms: this.convolutionUniforms,
			vertexShader: convolutionShader.vertexShader,
			fragmentShader: convolutionShader.fragmentShader,
			defines: {
				'KERNEL_SIZE_FLOAT': kernelSize.toFixed( 1 ),
				'KERNEL_SIZE_INT': kernelSize.toFixed( 0 )
			}

		} );

		this.needsSwap = false;

		this.fsQuad = new FullScreenQuad( null );

	}
Example #7
Source File: OutlinePass.js    From Computer-Graphics with MIT License 5 votes vote down vote up
getOverlayMaterial() {

		return new ShaderMaterial( {

			uniforms: {
				'maskTexture': { value: null },
				'edgeTexture1': { value: null },
				'edgeTexture2': { value: null },
				'patternTexture': { value: null },
				'edgeStrength': { value: 1.0 },
				'edgeGlow': { value: 1.0 },
				'usePatternTexture': { value: 0.0 }
			},

			vertexShader:
				`varying vec2 vUv;

				void main() {
					vUv = uv;
					gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
				}`,

			fragmentShader:
				`varying vec2 vUv;

				uniform sampler2D maskTexture;
				uniform sampler2D edgeTexture1;
				uniform sampler2D edgeTexture2;
				uniform sampler2D patternTexture;
				uniform float edgeStrength;
				uniform float edgeGlow;
				uniform bool usePatternTexture;

				void main() {
					vec4 edgeValue1 = texture2D(edgeTexture1, vUv);
					vec4 edgeValue2 = texture2D(edgeTexture2, vUv);
					vec4 maskColor = texture2D(maskTexture, vUv);
					vec4 patternColor = texture2D(patternTexture, 6.0 * vUv);
					float visibilityFactor = 1.0 - maskColor.g > 0.0 ? 1.0 : 0.5;
					vec4 edgeValue = edgeValue1 + edgeValue2 * edgeGlow;
					vec4 finalColor = edgeStrength * maskColor.r * edgeValue;
					if(usePatternTexture)
						finalColor += + visibilityFactor * (1.0 - maskColor.r) * (1.0 - patternColor.r);
					gl_FragColor = finalColor;
				}`,
			blending: AdditiveBlending,
			depthTest: false,
			depthWrite: false,
			transparent: true
		} );

	}
Example #8
Source File: FireBallPoints.js    From sketch-webcam with MIT License 5 votes vote down vote up
constructor() {
    // Define Geometry
    const geometry = new BufferGeometry();

    // Define attributes of the geometry
    const baPositions = new BufferAttribute(new Float32Array(NUM * 3), 3);
    const baDelays = new BufferAttribute(new Float32Array(NUM), 1);
    const baStartY = new BufferAttribute(new Float32Array(NUM), 1);
    for (var i = 0, ul = NUM; i < ul; i++) {
      const radian = MathEx.radians(Math.random() * 360);
      const radius = Math.random() * 2 + 1;
      baPositions.setXYZ(
        i,
        Math.cos(radian) * radius,
        0,
        Math.sin(radian) * radius
      );
      baDelays.setX(i, Math.random() * DURATION);
      baStartY.setX(i, Math.random() * 1);
    }
    geometry.setAttribute('position', baPositions);
    geometry.setAttribute('delay', baDelays);
    geometry.setAttribute('startY', baStartY);

    // Define Material
    const material = new RawShaderMaterial({
      uniforms: {
        time: {
          value: 0
        },
        duration: {
          value: DURATION
        },
        noiseTex: {
          value: null
        },
        alphaShow: {
          value: 0
        },
        alphaHide: {
          value: 0
        }
      },
      vertexShader: vs,
      fragmentShader: fs,
      transparent: true,
      blending: AdditiveBlending,
      depthWrite: false
    });

    // Create Object3D
    super(geometry, material);
    this.name = 'FireBallPoints';
  }
Example #9
Source File: TDSLoader.js    From canvas with Apache License 2.0 4 votes vote down vote up
TDSLoader.prototype = Object.assign( Object.create( Loader.prototype ), {

	constructor: TDSLoader,

	/**
	 * Load 3ds file from url.
	 *
	 * @method load
	 * @param {[type]} url URL for the file.
	 * @param {Function} onLoad onLoad callback, receives group Object3D as argument.
	 * @param {Function} onProgress onProgress callback.
	 * @param {Function} onError onError callback.
	 */
	load: function ( url, onLoad, onProgress, onError ) {

		var scope = this;

		var path = ( scope.path === '' ) ? LoaderUtils.extractUrlBase( url ) : scope.path;

		var loader = new FileLoader( this.manager );
		loader.setPath( this.path );
		loader.setResponseType( 'arraybuffer' );

		loader.load( url, function ( data ) {

			try {

				onLoad( scope.parse( data, path ) );

			} catch ( e ) {

				if ( onError ) {

					onError( e );

				} else {

					console.error( e );

				}

				scope.manager.itemError( url );

			}

		}, onProgress, onError );

	},

	/**
	 * Parse arraybuffer data and load 3ds file.
	 *
	 * @method parse
	 * @param {ArrayBuffer} arraybuffer Arraybuffer data to be loaded.
	 * @param {String} path Path for external resources.
	 * @return {Group} Group loaded from 3ds file.
	 */
	parse: function ( arraybuffer, path ) {

		this.group = new Group();
		this.position = 0;
		this.materials = [];
		this.meshes = [];

		this.readFile( arraybuffer, path );

		for ( var i = 0; i < this.meshes.length; i ++ ) {

			this.group.add( this.meshes[ i ] );

		}

		return this.group;

	},

	/**
	 * Decode file content to read 3ds data.
	 *
	 * @method readFile
	 * @param {ArrayBuffer} arraybuffer Arraybuffer data to be loaded.
	 * @param {String} path Path for external resources.
	 */
	readFile: function ( arraybuffer, path ) {

		var data = new DataView( arraybuffer );
		var chunk = this.readChunk( data );

		if ( chunk.id === MLIBMAGIC || chunk.id === CMAGIC || chunk.id === M3DMAGIC ) {

			var next = this.nextChunk( data, chunk );

			while ( next !== 0 ) {

				if ( next === M3D_VERSION ) {

					var version = this.readDWord( data );
					this.debugMessage( '3DS file version: ' + version );

				} else if ( next === MDATA ) {

					this.resetPosition( data );
					this.readMeshData( data, path );

				} else {

					this.debugMessage( 'Unknown main chunk: ' + next.toString( 16 ) );

				}

				next = this.nextChunk( data, chunk );

			}

		}

		this.debugMessage( 'Parsed ' + this.meshes.length + ' meshes' );

	},

	/**
	 * Read mesh data chunk.
	 *
	 * @method readMeshData
	 * @param {Dataview} data Dataview in use.
	 * @param {String} path Path for external resources.
	 */
	readMeshData: function ( data, path ) {

		var chunk = this.readChunk( data );
		var next = this.nextChunk( data, chunk );

		while ( next !== 0 ) {

			if ( next === MESH_VERSION ) {

				var version = + this.readDWord( data );
				this.debugMessage( 'Mesh Version: ' + version );

			} else if ( next === MASTER_SCALE ) {

				var scale = this.readFloat( data );
				this.debugMessage( 'Master scale: ' + scale );
				this.group.scale.set( scale, scale, scale );

			} else if ( next === NAMED_OBJECT ) {

				this.debugMessage( 'Named Object' );
				this.resetPosition( data );
				this.readNamedObject( data );

			} else if ( next === MAT_ENTRY ) {

				this.debugMessage( 'Material' );
				this.resetPosition( data );
				this.readMaterialEntry( data, path );

			} else {

				this.debugMessage( 'Unknown MDATA chunk: ' + next.toString( 16 ) );

			}

			next = this.nextChunk( data, chunk );

		}

	},

	/**
	 * Read named object chunk.
	 *
	 * @method readNamedObject
	 * @param {Dataview} data Dataview in use.
	 */
	readNamedObject: function ( data ) {

		var chunk = this.readChunk( data );
		var name = this.readString( data, 64 );
		chunk.cur = this.position;

		var next = this.nextChunk( data, chunk );
		while ( next !== 0 ) {

			if ( next === N_TRI_OBJECT ) {

				this.resetPosition( data );
				var mesh = this.readMesh( data );
				mesh.name = name;
				this.meshes.push( mesh );

			} else {

				this.debugMessage( 'Unknown named object chunk: ' + next.toString( 16 ) );

			}

			next = this.nextChunk( data, chunk );

		}

		this.endChunk( chunk );

	},

	/**
	 * Read material data chunk and add it to the material list.
	 *
	 * @method readMaterialEntry
	 * @param {Dataview} data Dataview in use.
	 * @param {String} path Path for external resources.
	 */
	readMaterialEntry: function ( data, path ) {

		var chunk = this.readChunk( data );
		var next = this.nextChunk( data, chunk );
		var material = new MeshPhongMaterial();

		while ( next !== 0 ) {

			if ( next === MAT_NAME ) {

				material.name = this.readString( data, 64 );
				this.debugMessage( '   Name: ' + material.name );

			} else if ( next === MAT_WIRE ) {

				this.debugMessage( '   Wireframe' );
				material.wireframe = true;

			} else if ( next === MAT_WIRE_SIZE ) {

				var value = this.readByte( data );
				material.wireframeLinewidth = value;
				this.debugMessage( '   Wireframe Thickness: ' + value );

			} else if ( next === MAT_TWO_SIDE ) {

				material.side = DoubleSide;
				this.debugMessage( '   DoubleSided' );

			} else if ( next === MAT_ADDITIVE ) {

				this.debugMessage( '   Additive Blending' );
				material.blending = AdditiveBlending;

			} else if ( next === MAT_DIFFUSE ) {

				this.debugMessage( '   Diffuse Color' );
				material.color = this.readColor( data );

			} else if ( next === MAT_SPECULAR ) {

				this.debugMessage( '   Specular Color' );
				material.specular = this.readColor( data );

			} else if ( next === MAT_AMBIENT ) {

				this.debugMessage( '   Ambient color' );
				material.color = this.readColor( data );

			} else if ( next === MAT_SHININESS ) {

				var shininess = this.readWord( data );
				material.shininess = shininess;
				this.debugMessage( '   Shininess : ' + shininess );

			} else if ( next === MAT_TRANSPARENCY ) {

				var opacity = this.readWord( data );
				material.opacity = opacity * 0.01;
				this.debugMessage( '  Opacity : ' + opacity );
				material.transparent = opacity < 100 ? true : false;

			} else if ( next === MAT_TEXMAP ) {

				this.debugMessage( '   ColorMap' );
				this.resetPosition( data );
				material.map = this.readMap( data, path );

			} else if ( next === MAT_BUMPMAP ) {

				this.debugMessage( '   BumpMap' );
				this.resetPosition( data );
				material.bumpMap = this.readMap( data, path );

			} else if ( next === MAT_OPACMAP ) {

				this.debugMessage( '   OpacityMap' );
				this.resetPosition( data );
				material.alphaMap = this.readMap( data, path );

			} else if ( next === MAT_SPECMAP ) {

				this.debugMessage( '   SpecularMap' );
				this.resetPosition( data );
				material.specularMap = this.readMap( data, path );

			} else {

				this.debugMessage( '   Unknown material chunk: ' + next.toString( 16 ) );

			}

			next = this.nextChunk( data, chunk );

		}

		this.endChunk( chunk );

		this.materials[ material.name ] = material;

	},

	/**
	 * Read mesh data chunk.
	 *
	 * @method readMesh
	 * @param {Dataview} data Dataview in use.
	 * @return {Mesh} The parsed mesh.
	 */
	readMesh: function ( data ) {

		var chunk = this.readChunk( data );
		var next = this.nextChunk( data, chunk );

		var geometry = new BufferGeometry();
		var uvs = [];

		var material = new MeshPhongMaterial();
		var mesh = new Mesh( geometry, material );
		mesh.name = 'mesh';

		while ( next !== 0 ) {

			if ( next === POINT_ARRAY ) {

				var points = this.readWord( data );

				this.debugMessage( '   Vertex: ' + points );

				//BufferGeometry

				var vertices = [];

				for ( var i = 0; i < points; i ++ )		{

					vertices.push( this.readFloat( data ) );
					vertices.push( this.readFloat( data ) );
					vertices.push( this.readFloat( data ) );

				}

				geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );

			} else if ( next === FACE_ARRAY ) {

				this.resetPosition( data );
				this.readFaceArray( data, mesh );

			} else if ( next === TEX_VERTS ) {

				var texels = this.readWord( data );

				this.debugMessage( '   UV: ' + texels );

				//BufferGeometry

				var uvs = [];

				for ( var i = 0; i < texels; i ++ )		{

					uvs.push( this.readFloat( data ) );
					uvs.push( this.readFloat( data ) );

				}

				geometry.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );


			} else if ( next === MESH_MATRIX ) {

				this.debugMessage( '   Tranformation Matrix (TODO)' );

				var values = [];
				for ( var i = 0; i < 12; i ++ ) {

					values[ i ] = this.readFloat( data );

				}

				var matrix = new Matrix4();

				//X Line
				matrix.elements[ 0 ] = values[ 0 ];
				matrix.elements[ 1 ] = values[ 6 ];
				matrix.elements[ 2 ] = values[ 3 ];
				matrix.elements[ 3 ] = values[ 9 ];

				//Y Line
				matrix.elements[ 4 ] = values[ 2 ];
				matrix.elements[ 5 ] = values[ 8 ];
				matrix.elements[ 6 ] = values[ 5 ];
				matrix.elements[ 7 ] = values[ 11 ];

				//Z Line
				matrix.elements[ 8 ] = values[ 1 ];
				matrix.elements[ 9 ] = values[ 7 ];
				matrix.elements[ 10 ] = values[ 4 ];
				matrix.elements[ 11 ] = values[ 10 ];

				//W Line
				matrix.elements[ 12 ] = 0;
				matrix.elements[ 13 ] = 0;
				matrix.elements[ 14 ] = 0;
				matrix.elements[ 15 ] = 1;

				matrix.transpose();

				var inverse = new Matrix4();
				inverse.getInverse( matrix );
				geometry.applyMatrix4( inverse );

				matrix.decompose( mesh.position, mesh.quaternion, mesh.scale );

			} else {

				this.debugMessage( '   Unknown mesh chunk: ' + next.toString( 16 ) );

			}

			next = this.nextChunk( data, chunk );

		}

		this.endChunk( chunk );

		geometry.computeVertexNormals();

		return mesh;

	},

	/**
	 * Read face array data chunk.
	 *
	 * @method readFaceArray
	 * @param {Dataview} data Dataview in use.
	 * @param {Mesh} mesh Mesh to be filled with the data read.
	 */
	readFaceArray: function ( data, mesh ) {

		var chunk = this.readChunk( data );
		var faces = this.readWord( data );

		this.debugMessage( '   Faces: ' + faces );

		var index = [];

		for ( var i = 0; i < faces; ++ i ) {

			index.push( this.readWord( data ), this.readWord( data ), this.readWord( data ) );

			this.readWord( data ); // visibility

		}

		mesh.geometry.setIndex( index );

		//The rest of the FACE_ARRAY chunk is subchunks

		while ( this.position < chunk.end ) {

			var chunk = this.readChunk( data );

			if ( chunk.id === MSH_MAT_GROUP ) {

				this.debugMessage( '      Material Group' );

				this.resetPosition( data );

				var group = this.readMaterialGroup( data );

				var material = this.materials[ group.name ];

				if ( material !== undefined )	{

					mesh.material = material;

					if ( material.name === '' )		{

						material.name = mesh.name;

					}

				}

			} else {

				this.debugMessage( '      Unknown face array chunk: ' + chunk.toString( 16 ) );

			}

			this.endChunk( chunk );

		}

		this.endChunk( chunk );

	},

	/**
	 * Read texture map data chunk.
	 *
	 * @method readMap
	 * @param {Dataview} data Dataview in use.
	 * @param {String} path Path for external resources.
	 * @return {Texture} Texture read from this data chunk.
	 */
	readMap: function ( data, path ) {

		var chunk = this.readChunk( data );
		var next = this.nextChunk( data, chunk );
		var texture = {};

		var loader = new TextureLoader( this.manager );
		loader.setPath( this.resourcePath || path ).setCrossOrigin( this.crossOrigin );

		while ( next !== 0 ) {

			if ( next === MAT_MAPNAME ) {

				var name = this.readString( data, 128 );
				texture = loader.load( name );

				this.debugMessage( '      File: ' + path + name );

			} else if ( next === MAT_MAP_UOFFSET ) {

				texture.offset.x = this.readFloat( data );
				this.debugMessage( '      OffsetX: ' + texture.offset.x );

			} else if ( next === MAT_MAP_VOFFSET ) {

				texture.offset.y = this.readFloat( data );
				this.debugMessage( '      OffsetY: ' + texture.offset.y );

			} else if ( next === MAT_MAP_USCALE ) {

				texture.repeat.x = this.readFloat( data );
				this.debugMessage( '      RepeatX: ' + texture.repeat.x );

			} else if ( next === MAT_MAP_VSCALE ) {

				texture.repeat.y = this.readFloat( data );
				this.debugMessage( '      RepeatY: ' + texture.repeat.y );

			} else {

				this.debugMessage( '      Unknown map chunk: ' + next.toString( 16 ) );

			}

			next = this.nextChunk( data, chunk );

		}

		this.endChunk( chunk );

		return texture;

	},

	/**
	 * Read material group data chunk.
	 *
	 * @method readMaterialGroup
	 * @param {Dataview} data Dataview in use.
	 * @return {Object} Object with name and index of the object.
	 */
	readMaterialGroup: function ( data ) {

		this.readChunk( data );
		var name = this.readString( data, 64 );
		var numFaces = this.readWord( data );

		this.debugMessage( '         Name: ' + name );
		this.debugMessage( '         Faces: ' + numFaces );

		var index = [];
		for ( var i = 0; i < numFaces; ++ i ) {

			index.push( this.readWord( data ) );

		}

		return { name: name, index: index };

	},

	/**
	 * Read a color value.
	 *
	 * @method readColor
	 * @param {DataView} data Dataview.
	 * @return {Color} Color value read..
	 */
	readColor: function ( data ) {

		var chunk = this.readChunk( data );
		var color = new Color();

		if ( chunk.id === COLOR_24 || chunk.id === LIN_COLOR_24 ) {

			var r = this.readByte( data );
			var g = this.readByte( data );
			var b = this.readByte( data );

			color.setRGB( r / 255, g / 255, b / 255 );

			this.debugMessage( '      Color: ' + color.r + ', ' + color.g + ', ' + color.b );

		}	else if ( chunk.id === COLOR_F || chunk.id === LIN_COLOR_F ) {

			var r = this.readFloat( data );
			var g = this.readFloat( data );
			var b = this.readFloat( data );

			color.setRGB( r, g, b );

			this.debugMessage( '      Color: ' + color.r + ', ' + color.g + ', ' + color.b );

		}	else {

			this.debugMessage( '      Unknown color chunk: ' + chunk.toString( 16 ) );

		}

		this.endChunk( chunk );
		return color;

	},

	/**
	 * Read next chunk of data.
	 *
	 * @method readChunk
	 * @param {DataView} data Dataview.
	 * @return {Object} Chunk of data read.
	 */
	readChunk: function ( data ) {

		var chunk = {};

		chunk.cur = this.position;
		chunk.id = this.readWord( data );
		chunk.size = this.readDWord( data );
		chunk.end = chunk.cur + chunk.size;
		chunk.cur += 6;

		return chunk;

	},

	/**
	 * Set position to the end of the current chunk of data.
	 *
	 * @method endChunk
	 * @param {Object} chunk Data chunk.
	 */
	endChunk: function ( chunk ) {

		this.position = chunk.end;

	},

	/**
	 * Move to the next data chunk.
	 *
	 * @method nextChunk
	 * @param {DataView} data Dataview.
	 * @param {Object} chunk Data chunk.
	 */
	nextChunk: function ( data, chunk ) {

		if ( chunk.cur >= chunk.end ) {

			return 0;

		}

		this.position = chunk.cur;

		try {

			var next = this.readChunk( data );
			chunk.cur += next.size;
			return next.id;

		}	catch ( e ) {

			this.debugMessage( 'Unable to read chunk at ' + this.position );
			return 0;

		}

	},

	/**
	 * Reset dataview position.
	 *
	 * @method resetPosition
	 */
	resetPosition: function () {

		this.position -= 6;

	},

	/**
	 * Read byte value.
	 *
	 * @method readByte
	 * @param {DataView} data Dataview to read data from.
	 * @return {Number} Data read from the dataview.
	 */
	readByte: function ( data ) {

		var v = data.getUint8( this.position, true );
		this.position += 1;
		return v;

	},

	/**
	 * Read 32 bit float value.
	 *
	 * @method readFloat
	 * @param {DataView} data Dataview to read data from.
	 * @return {Number} Data read from the dataview.
	 */
	readFloat: function ( data ) {

		try {

			var v = data.getFloat32( this.position, true );
			this.position += 4;
			return v;

		}	catch ( e ) {

			this.debugMessage( e + ' ' + this.position + ' ' + data.byteLength );

		}

	},

	/**
	 * Read 32 bit signed integer value.
	 *
	 * @method readInt
	 * @param {DataView} data Dataview to read data from.
	 * @return {Number} Data read from the dataview.
	 */
	readInt: function ( data ) {

		var v = data.getInt32( this.position, true );
		this.position += 4;
		return v;

	},

	/**
	 * Read 16 bit signed integer value.
	 *
	 * @method readShort
	 * @param {DataView} data Dataview to read data from.
	 * @return {Number} Data read from the dataview.
	 */
	readShort: function ( data ) {

		var v = data.getInt16( this.position, true );
		this.position += 2;
		return v;

	},

	/**
	 * Read 64 bit unsigned integer value.
	 *
	 * @method readDWord
	 * @param {DataView} data Dataview to read data from.
	 * @return {Number} Data read from the dataview.
	 */
	readDWord: function ( data ) {

		var v = data.getUint32( this.position, true );
		this.position += 4;
		return v;

	},

	/**
	 * Read 32 bit unsigned integer value.
	 *
	 * @method readWord
	 * @param {DataView} data Dataview to read data from.
	 * @return {Number} Data read from the dataview.
	 */
	readWord: function ( data ) {

		var v = data.getUint16( this.position, true );
		this.position += 2;
		return v;

	},

	/**
	 * Read string value.
	 *
	 * @method readString
	 * @param {DataView} data Dataview to read data from.
	 * @param {Number} maxLength Max size of the string to be read.
	 * @return {String} Data read from the dataview.
	 */
	readString: function ( data, maxLength ) {

		var s = '';

		for ( var i = 0; i < maxLength; i ++ ) {

			var c = this.readByte( data );
			if ( ! c ) {

				break;

			}

			s += String.fromCharCode( c );

		}

		return s;

	},

	/**
	 * Print debug message to the console.
	 *
	 * Is controlled by a flag to show or hide debug messages.
	 *
	 * @method debugMessage
	 * @param {Object} message Debug message to print to the console.
	 */
	debugMessage: function ( message ) {

		if ( this.debug ) {

			console.log( message );

		}

	}

} );