@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
156 lines (119 loc) • 3.75 kB
JavaScript
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 0;
}
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
);
}