import { TextureBase } from './TextureBase.js';
import { Vector2 } from '../math/Vector2.js';
import { Matrix3 } from '../math/Matrix3.js';
import { WEBGL_TEXTURE_TYPE, WEBGL_PIXEL_FORMAT } from '../const.js';
import { ImageLoader } from '../loader/ImageLoader.js';
import { TGALoader } from '../loader/TGALoader.js';
import { RGBELoader } from '../loader/RGBELoader.js';
/**
* Creates a cube texture made up of single image.
* @constructor
* @memberof zen3d
* @extends zen3d.TextureBase
*/
function Texture2D() {
TextureBase.call(this);
this.textureType = WEBGL_TEXTURE_TYPE.TEXTURE_2D;
/**
* Image data for this texture.
* @member {null|HTMLImageElement|Object}
* @default null
*/
this.image = null;
/**
* How much a single repetition of the texture is offset from the beginning, in each direction U and V.
* Typical range is 0.0 to 1.0.
* _Note:_ The offset property is a convenience modifier and only affects the Texture's application to the first set of UVs on a model.
* If the Texture is used as a map requiring additional UV sets (e.g. the aoMap or lightMap of most stock materials), those UVs must be manually assigned to achieve the desired offset..
* @member {zen3d.Vector2}
* @default zen3d.Vector2(0, 0)
*/
this.offset = new Vector2();
/**
* How many times the texture is repeated across the surface, in each direction U and V.
* If repeat is set greater than 1 in either direction, the corresponding Wrap parameter should also be set to {@link zen3d.WEBGL_TEXTURE_WRAP.REPEAT} or {@link zen3d.WEBGL_TEXTURE_WRAP.MIRRORED_REPEAT} to achieve the desired tiling effect.
* _Note:_ The repeat property is a convenience modifier and only affects the Texture's application to the first set of UVs on a model.
* If the Texture is used as a map requiring additional UV sets (e.g. the aoMap or lightMap of most stock materials), those UVs must be manually assigned to achieve the desired repetiton.
* @member {zen3d.Vector2}
* @default zen3d.Vector2(1, 1)
*/
this.repeat = new Vector2(1, 1);
/**
* The point around which rotation occurs.
* A value of (0.5, 0.5) corresponds to the center of the texture.
* Default is (0, 0), the lower left.
* @member {zen3d.Vector2}
* @default zen3d.Vector2(0, 0)
*/
this.center = new Vector2();
/**
* How much the texture is rotated around the center point, in radians.
* Postive values are counter-clockwise.
* @member {number}
* @default 0
*/
this.rotation = 0;
/**
* The uv-transform matrix for the texture. Updated by the renderer from the texture properties {@link zen3d.Texture2D#offset}, {@link zen3d.Texture2D#repeat}, {@link zen3d.Texture2D#rotation}, and {@link zen3d.Texture2D#center} when the texture's {@link zen3d.Texture2D#matrixAutoUpdate} property is true.
* When {@link zen3d.Texture2D#matrixAutoUpdate} property is false, this matrix may be set manually.
* Default is the identity matrix.
* @member {zen3d.Matrix3}
* @default Matrix3()
*/
this.matrix = new Matrix3();
/**
* Whether to update the texture's uv-transform {@link zen3d.Texture2D#matrix} from the texture properties {@link zen3d.Texture2D#offset}, {@link zen3d.Texture2D#repeat}, {@link zen3d.Texture2D#rotation}, and {@link zen3d.Texture2D#center}.
* Set this to false if you are specifying the uv-transform matrix directly.
* @member {boolean}
* @default true
*/
this.matrixAutoUpdate = true;
/**
* Whether to use the texture's uv-transform {@link zen3d.Texture2D#matrix} from the texture properties {@link zen3d.Texture2D#offset}, {@link zen3d.Texture2D#repeat}, {@link zen3d.Texture2D#rotation}, and {@link zen3d.Texture2D#center}.
* This is only useful when the texture is an alphaMap for Now.
* Other material map will use a same uv-transform by default.
* @member {boolean}
* @default true
*/
this.useUVTransform = true;
}
Texture2D.prototype = Object.assign(Object.create(TextureBase.prototype), /** @lends zen3d.Texture2D.prototype */{
constructor: Texture2D,
copy: function(source) {
TextureBase.prototype.copy.call(this, source);
this.image = source.image;
this.mipmaps = source.mipmaps.slice(0);
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);
return this;
},
/**
* Update the texture's uv-transform {@link zen3d.Texture2D#matrix} from the texture properties {@link zen3d.Texture2D#offset}, {@link zen3d.Texture2D#repeat}, {@link zen3d.Texture2D#rotation}, and {@link zen3d.Texture2D#center}.
*/
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);
}
});
/**
* Create Texture2D from image.
* @param {HTMLImageElement} image
* @return {TextureCube} - The result Texture.
*/
Texture2D.fromImage = function(image) {
var texture = new Texture2D();
texture.image = image;
texture.version++;
return texture;
}
/**
* Create Texture2D from src.
* @param {string} src
* @return {TextureCube} - The result Texture.
*/
Texture2D.fromSrc = function(src) {
var texture = new Texture2D();
// JPEGs can't have an alpha channel, so memory can be saved by storing them as RGB.
var isJPEG = src.search(/\.(jpg|jpeg)$/) > 0 || src.search(/^data\:image\/jpeg/) === 0;
var isTGA = src.search(/\.(tga)$/) > 0 || src.search(/^data\:image\/tga/) === 0;
var isHDR = src.search(/\.(hdr)$/) > 0;
if (isHDR) {
var loader = new RGBELoader();
loader.load(src, function(textureData) {
texture.image = { data: textureData.data, width: textureData.width, height: textureData.height };
texture.encoding = zen3d.TEXEL_ENCODING_TYPE.RGBE;
texture.type = textureData.type;
texture.format = textureData.format;
texture.version++;
texture.dispatchEvent({ type: 'onload' });
});
} else {
var loader = isTGA ? new TGALoader() : new ImageLoader();
loader.load(src, function(image) {
texture.format = isJPEG ? WEBGL_PIXEL_FORMAT.RGB : WEBGL_PIXEL_FORMAT.RGBA;
texture.image = image;
texture.version++;
texture.dispatchEvent({ type: 'onload' });
});
}
return texture;
}
export { Texture2D };