UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

168 lines (127 loc) 4.05 kB
import { assert } from "../../../../core/assert.js"; import { combine_hash } from "../../../../core/collection/array/combine_hash.js"; import { murmur3_32 } from "../../../../core/math/hash/murmur3_32.js"; import { computeHashFloat } from "../../../../core/primitives/numbers/computeHashFloat.js"; import { computeStringHash } from "../../../../core/primitives/strings/computeStringHash.js"; import { computeHtmlCanvasElementHash } from "../../../graphics/canvas/computeHtmlCanvasElementHash.js"; import { isImageBitmap } from "../../../graphics/texture/isImageBitmap.js"; import { computeImageBitmapHash } from "./computeImageBitmapHash.js"; /** * * @param {Vector2} v * @return {number} */ function vector2Hash(v) { const x = computeHashFloat(v.x); const y = computeHashFloat(v.y); return ((x << 5) - x) + y; } /** * * @type {WeakMap<object, number>} */ const data_cache = new WeakMap(); /** * * @param {ImageBitmap|HTMLImageElement|{data,width:number,height:number}} image * @return {number} */ export function computeImageDataHash(image) { const cached_value = data_cache.get(image); if (cached_value !== undefined) { return cached_value; } let result = 0; if (isImageBitmap(image)) { result = computeImageBitmapHash(image); } else if (image instanceof HTMLImageElement) { result = computeStringHash(image.src); } else if (image instanceof HTMLCanvasElement) { result = computeHtmlCanvasElementHash(image); } let width = 0; let height = 0; if (typeof image.width === "number") { width = image.width; } if (typeof image.height === "number") { height = image.height; } result = result ^ (((width & 0xFFFF) << 16) | (height & 0xFFFF)); // cache value data_cache.set(image, result); return result; } /** * * @param {Texture} texture * @return {number} */ function computeSpecificHash(texture) { let dataHash = 0; let i; if (texture.image !== null && texture.image !== undefined) { const image = texture.image; dataHash = computeImageDataHash(image); } const mipmaps = texture.mipmaps; if (Array.isArray(mipmaps)) { const nMipmaps = mipmaps.length; for (i = 0; i < nMipmaps; i++) { const mipmap = mipmaps[i]; const data = mipmap.data; const dataSize = data.length; if (dataSize > 1024) { continue; } dataHash = ((dataHash << 5) - dataHash) + murmur3_32(data, 1337); break; } } return dataHash; } /** * * @param {Texture|THREE.Texture} t * @returns {number} */ export function computeTextureHash(t) { if (t === null) { return 0; } if (t === undefined) { return 1; } // special methods if (typeof t.hash === "function") { const hash = t.hash(); // must produce an integer value assert.isInteger(hash, 'hash'); return hash; } // revert to generic check const specificHash = computeSpecificHash(t); return combine_hash( t.mapping, t.wrapS, t.wrapT, t.magFilter, t.minFilter, t.anisotropy, t.format, t.type, vector2Hash(t.offset), vector2Hash(t.repeat), vector2Hash(t.center), computeHashFloat(t.rotation), t.generateMipmaps ? 1 : 0, t.premultiplyAlpha ? 1 : 0, t.flipY ? 1 : 0, t.unpackAlignment, /* we are excluding encoding from hash, as this property has disappeared in later version of three.js This property is rarely going to have the deciding role for the hash anyway. This notice is left for historical purposes only */ // t.encoding, specificHash ); }