UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

222 lines (177 loc) 5.59 kB
import { fastArrayEquals } from "../../../../core/collection/array/fastArrayEquals.js"; import { isArrayLike } from "../../../../core/collection/array/isArrayLike.js"; import { computeImageCanvasEquality } from "../../../graphics/canvas/computeImageCanvasEquality.js"; import { isImageBitmap } from "../../../graphics/texture/isImageBitmap.js"; import { computeImageBitmapEquality } from "./computeImageBitmapEquality.js"; /** * Compare two three.js textures for equality * @param {THREE.Texture} a * @param {THREE.Texture} b * @returns {boolean} */ export function computeTextureEquality(a, b) { if (a === b) { return true; } if ( a === null || b === null || a === undefined || b === undefined ) { return false; } // special methods if (typeof a.equals === "function" && typeof b.equals === "function") { // can check for equality using custom methods return a.equals(b); } // revert to generic check if ( a.mapping !== b.mapping || a.wrapS !== b.wrapS || a.wrapT !== b.wrapT || a.magFilter !== b.magFilter || a.minFilter !== b.minFilter || a.anisotropy !== b.anisotropy || a.format !== b.format || a.type !== b.type || !a.offset.equals(b.offset) || !a.repeat.equals(b.repeat) || !a.center.equals(b.center) || a.rotation !== b.rotation || a.generateMipmaps !== b.generateMipmaps || a.premultiplyAlpha !== b.premultiplyAlpha || a.flipY !== b.flipY || a.unpackAlignment !== b.unpackAlignment || a.encoding !== b.encoding || !textureImagesEqual(a.image, b.image) ) { return false; } if (a.isCompressedTexture && b.isCompressedTexture) { const aMipmaps = a.mipmaps; const bMipmaps = b.mipmaps; if (!textureMipChainEqual(aMipmaps, bMipmaps)) { return false; } } //TODO implement support for other texture types // checks up until now were for rejection, so if we got until this point - textures must be equal return true; } /** * * @param {Image|ImageBitmap|HTMLCanvasElement|[]|{width:number, height:number}} a * @param {Image|ImageBitmap|HTMLCanvasElement|[]|{width:number, height:number}} b * @returns {boolean} */ export function textureImagesEqual(a, b) { if (a === b) { return true; } if (a instanceof Image && b instanceof Image) { //both are images if (a.src === b.src) { //same source return true; } else { // different source, assume images are different too return false; } } if ( (typeof a.width === "number" && a.width !== b.width) || (typeof a.height === "number" && a.height !== b.height) ) { // dimensions are present, but are inconsistent return false; } if (isImageBitmap(a) && isImageBitmap(b)) { return computeImageBitmapEquality(a, b); } if (a instanceof HTMLCanvasElement && b instanceof HTMLCanvasElement) { return computeImageCanvasEquality(a, b); } if (Array.isArray(a) && Array.isArray(b)) { if (a.length !== b.length) { return false; } for (let i = 0; i < a.length; i++) { const ai = a[i]; const bi = b[i]; if (ai.format !== bi.format) { return false; } const aMipmaps = ai.mipmaps; const bMipmaps = bi.mipmaps; //TODO should we ignore mipmaps if they are absent? if (!textureMipChainEqual(aMipmaps, bMipmaps)) { return false; } } return true; } const a_data = a.data; const b_data = b.data; if (a_data === null && b_data === null) { // special case, empty texture return true; } if (isArrayLike(a_data) && isArrayLike(b_data)) { return textureMipmapEqual(a, b); } // assume different return false; } /** * * @param {Array} a * @param {Array} b * @returns {boolean} */ function textureMipChainEqual(a, b) { if (a === undefined) { if (b === undefined) { return true; } else { return false; } } else if (b === undefined) { return false; } const a_length = a.length; if (a_length !== b.length) { // different mip chain length return false; } for (let j = a_length - 1; j >= 0; j--) { //traverse chain top to bottom, starting from smallest mip for faster rejection const aMipmap = a[j]; const bMipmap = b[j]; if (!textureMipmapEqual(aMipmap, bMipmap)) { return false; } } return true; } /** * * @param {{data:Uint8Array, width:number, height:number}} a * @param {{data:Uint8Array, width:number, height:number}} b * @returns {boolean} */ function textureMipmapEqual(a, b) { if (a.width !== b.width) { return false; } if (a.height !== b.width) { return false; } const aData = a.data; const bData = b.data; if (aData === bData) { // special case return true; } return fastArrayEquals(aData, bData); }