318 lines
6.3 KiB
JavaScript
318 lines
6.3 KiB
JavaScript
|
/**
|
||
|
* @author mrdoob / http://mrdoob.com/
|
||
|
* @author alteredq / http://alteredqualia.com/
|
||
|
* @author szimek / https://github.com/szimek/
|
||
|
*/
|
||
|
|
||
|
import { EventDispatcher } from '../core/EventDispatcher.js';
|
||
|
import { UVMapping } from '../constants.js';
|
||
|
import { MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, LinearEncoding, UnsignedByteType, RGBAFormat, LinearMipMapLinearFilter, LinearFilter } from '../constants.js';
|
||
|
import { _Math } from '../math/Math.js';
|
||
|
import { Vector2 } from '../math/Vector2.js';
|
||
|
import { Matrix3 } from '../math/Matrix3.js';
|
||
|
import { ImageUtils } from '../extras/ImageUtils.js';
|
||
|
|
||
|
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;
|
||
|
|
||
|
Texture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
|
||
|
|
||
|
constructor: Texture,
|
||
|
|
||
|
isTexture: true,
|
||
|
|
||
|
updateMatrix: function () {
|
||
|
|
||
|
this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y );
|
||
|
|
||
|
},
|
||
|
|
||
|
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 ];
|
||
|
|
||
|
}
|
||
|
|
||
|
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 ],
|
||
|
|
||
|
format: this.format,
|
||
|
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 ) {
|
||
|
|
||
|
var url;
|
||
|
|
||
|
if ( Array.isArray( image ) ) {
|
||
|
|
||
|
// process array of images e.g. CubeTexture
|
||
|
|
||
|
url = [];
|
||
|
|
||
|
for ( var i = 0, l = image.length; i < l; i ++ ) {
|
||
|
|
||
|
url.push( ImageUtils.getDataURL( image[ i ] ) );
|
||
|
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
|
||
|
// process single image
|
||
|
|
||
|
url = ImageUtils.getDataURL( image );
|
||
|
|
||
|
}
|
||
|
|
||
|
meta.images[ image.uuid ] = {
|
||
|
uuid: image.uuid,
|
||
|
url: url
|
||
|
};
|
||
|
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
|
||
|
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;
|
||
|
|
||
|
}
|
||
|
|
||
|
} );
|
||
|
|
||
|
Object.defineProperty( Texture.prototype, "needsUpdate", {
|
||
|
|
||
|
set: function ( value ) {
|
||
|
|
||
|
if ( value === true ) this.version ++;
|
||
|
|
||
|
}
|
||
|
|
||
|
} );
|
||
|
|
||
|
|
||
|
export { Texture };
|