123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377 |
- import { EventDispatcher } from '../core/EventDispatcher.js';
- import {
- MirroredRepeatWrapping,
- ClampToEdgeWrapping,
- RepeatWrapping,
- LinearEncoding,
- UnsignedByteType,
- RGBAFormat,
- LinearMipmapLinearFilter,
- LinearFilter,
- UVMapping
- } from '../constants.js';
- import * as MathUtils from '../math/MathUtils.js';
- import { Vector2 } from '../math/Vector2.js';
- import { Matrix3 } from '../math/Matrix3.js';
- import { ImageUtils } from '../extras/ImageUtils.js';
- let textureId = 0;
- class Texture extends EventDispatcher {
- constructor( image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = 1, encoding = LinearEncoding ) {
- super();
- Object.defineProperty( this, 'id', { value: textureId ++ } );
- this.uuid = MathUtils.generateUUID();
- this.name = '';
- this.image = image;
- this.mipmaps = [];
- this.mapping = mapping;
- this.wrapS = wrapS;
- this.wrapT = wrapT;
- this.magFilter = magFilter;
- this.minFilter = minFilter;
- this.anisotropy = anisotropy;
- this.format = format;
- this.internalFormat = null;
- this.type = type;
- 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;
- this.userData = {};
- this.version = 0;
- this.onUpdate = null;
- this.isRenderTargetTexture = false;
- }
- updateMatrix() {
- this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y );
- }
- clone() {
- return new this.constructor().copy( this );
- }
- copy( 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.internalFormat = source.internalFormat;
- 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;
- this.userData = JSON.parse( JSON.stringify( source.userData ) );
- return this;
- }
- toJSON( meta ) {
- const isRootObject = ( meta === undefined || typeof meta === 'string' );
- if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {
- return meta.textures[ this.uuid ];
- }
- const 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 ],
- format: this.format,
- type: this.type,
- encoding: this.encoding,
- minFilter: this.minFilter,
- magFilter: this.magFilter,
- anisotropy: this.anisotropy,
- flipY: this.flipY,
- premultiplyAlpha: this.premultiplyAlpha,
- unpackAlignment: this.unpackAlignment
- };
- if ( this.image !== undefined ) {
- // TODO: Move to THREE.Image
- const image = this.image;
- if ( image.uuid === undefined ) {
- image.uuid = MathUtils.generateUUID(); // UGH
- }
- if ( ! isRootObject && meta.images[ image.uuid ] === undefined ) {
- let url;
- if ( Array.isArray( image ) ) {
- // process array of images e.g. CubeTexture
- url = [];
- for ( let i = 0, l = image.length; i < l; i ++ ) {
- // check cube texture with data textures
- if ( image[ i ].isDataTexture ) {
- url.push( serializeImage( image[ i ].image ) );
- } else {
- url.push( serializeImage( image[ i ] ) );
- }
- }
- } else {
- // process single image
- url = serializeImage( image );
- }
- meta.images[ image.uuid ] = {
- uuid: image.uuid,
- url: url
- };
- }
- output.image = image.uuid;
- }
- if ( JSON.stringify( this.userData ) !== '{}' ) output.userData = this.userData;
- if ( ! isRootObject ) {
- meta.textures[ this.uuid ] = output;
- }
- return output;
- }
- dispose() {
- this.dispatchEvent( { type: 'dispose' } );
- }
- transformUv( uv ) {
- if ( this.mapping !== UVMapping ) return uv;
- 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;
- }
- return uv;
- }
- set needsUpdate( value ) {
- if ( value === true ) this.version ++;
- }
- }
- Texture.DEFAULT_IMAGE = undefined;
- Texture.DEFAULT_MAPPING = UVMapping;
- Texture.prototype.isTexture = true;
- function serializeImage( image ) {
- if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
- ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
- ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
- // default images
- return ImageUtils.getDataURL( image );
- } else {
- if ( image.data ) {
- // images of DataTexture
- return {
- data: Array.prototype.slice.call( image.data ),
- width: image.width,
- height: image.height,
- type: image.data.constructor.name
- };
- } else {
- console.warn( 'THREE.Texture: Unable to serialize Texture.' );
- return {};
- }
- }
- }
- export { Texture };
|