From 5fa7111078b683cb15951d1dbb27691e81a8b304 Mon Sep 17 00:00:00 2001 From: Peter Date: Fri, 25 Aug 2023 23:48:45 +0200 Subject: [PATCH 1/2] feat(RandUtils): add RandUtils --- src/index.ts | 1 + src/utils/RandUtils.ts | 120 +++++++++++++++++++++++++++++++++++++++++ src/utils/index.ts | 3 ++ 3 files changed, 124 insertions(+) create mode 100644 src/utils/RandUtils.ts diff --git a/src/index.ts b/src/index.ts index 46d458ad..65ee564f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1 +1,2 @@ export * from './core' +export * from './utils' diff --git a/src/utils/RandUtils.ts b/src/utils/RandUtils.ts new file mode 100644 index 00000000..399a1948 --- /dev/null +++ b/src/utils/RandUtils.ts @@ -0,0 +1,120 @@ +import { MathUtils } from 'THREE' +const clamp = MathUtils.clamp + +/** + * Seedable pseudorandom number tools + */ +export default class RandUtils { + private _getNext: () => number + private _getGenerator: (seed: number) => () => number + + /** + * Create a new seeded pseudorandom number generator. + * @param [seed=0] - the seed for the generator + * @param [getSeededRandomGenerator=getMulberry32] - a function that returns a pseudorandom number generator + * @constructor + */ + constructor(seed = 0, getSeededRandomGenerator?: (seed: number) => () => number) { + this._getGenerator = getSeededRandomGenerator ?? this.getMulberry32 + this._getNext = this._getGenerator(seed) + } + + /** + * Reseed the pseudorandom number generator + */ + seed(s: number) { + this._getNext = this._getGenerator(s) + } + + /** + * Return the next pseudorandom number in the interval [0, 1] + */ + rand(): number { + return this._getNext() + } + + /** + * Random float from interval + * @param low - Low value of the interval + * @param high - High value of the interval + */ + float(low: number, high: number): number { + return low + this._getNext() * (high - low) + } + + /** + * Random float from <-range/2, range/2> interval + * @param range - Interval range + */ + floatSpread(range: number): number { + return this.float(-0.5 * range, 0.5 * range) + } + + /** + * Random integer from interval + * @param low Low value of the interval + * @param high High value of the interval + */ + int(low: number, high: number): number { + return low + Math.floor(this._getNext() * (high - low + 1)) + } + + /** + * Choose an element from an array. + * @param array The array to choose from + * @returns An element from the array or null if the array is empty + */ + choice(array: T[]): T | null { + if (!array.length) { + return null + } + return array[Math.floor(this._getNext() * array.length)] + } + + /** + * Return n elements from an array. + * @param array The array to sample + * @param sampleSizeMin The minimum sample size + * @param sampleSizeMax The maximum sample size + */ + sample(array: T[], sampleSizeMin: number, sampleSizeMax?: number): T[] { + const len = array.length + sampleSizeMin = clamp(sampleSizeMin, 0, len - 1) + sampleSizeMax = clamp(sampleSizeMax ?? len - 1, 0, len - 1) + const sampleSize = this.int(sampleSizeMin, sampleSizeMax) + const indicies = this.shuffle(array.map((_, i) => i)) + const n = Math.min(array.length, sampleSize) + return indicies + .slice(0, n) + .sort() + .map(i => array[i]) + } + + /** + * Shuffle an array. Not in-place. + * @param array The array to shuffle + */ + shuffle(array: T[]): T[] { + return array + .map(value => ({ value, sort: this._getNext() })) + .sort((a, b) => a.sort - b.sort) + .map(({ value }) => value) + } + + /** + * The default pseudorandom generator. + */ + private getMulberry32(seed = 0): () => number { + if (0 < seed && seed < 1) { + seed = Math.floor(seed * 2 ** 16) + } + return () => { + // NOTE: Mulberry32 generator + seed += 0x6d2b79f5 + let t = seed + t = Math.imul(t ^ (t >>> 15), t | 1) + t ^= t + Math.imul(t ^ (t >>> 7), t | 61) + return ((t ^ (t >>> 14)) >>> 0) / 4294967296 + } + } +} diff --git a/src/utils/index.ts b/src/utils/index.ts index 53bfbbfc..07b43b48 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -30,3 +30,6 @@ export function hasSetter(obj: any, prop: string): boolean { const setterName = `set${prop[0].toUpperCase()}${prop.slice(1)}` return obj[setterName] !== undefined } + +import RandUtils from './RandUtils' +export { RandUtils } From fb1f52d72838d9e9a18cf841e38335232cf9abd7 Mon Sep 17 00:00:00 2001 From: Peter Date: Fri, 18 Aug 2023 01:30:51 +0200 Subject: [PATCH 2/2] feat(Lensflare): add Lensflare --- playground/src/pages/LensflareDemo.vue | 82 +++++++ playground/src/router.ts | 5 + src/core/abstractions/Lensflare.vue | 305 +++++++++++++++++++++++++ src/core/abstractions/index.ts | 2 + 4 files changed, 394 insertions(+) create mode 100644 playground/src/pages/LensflareDemo.vue create mode 100644 src/core/abstractions/Lensflare.vue diff --git a/playground/src/pages/LensflareDemo.vue b/playground/src/pages/LensflareDemo.vue new file mode 100644 index 00000000..cf04d6a7 --- /dev/null +++ b/playground/src/pages/LensflareDemo.vue @@ -0,0 +1,82 @@ + + + diff --git a/playground/src/router.ts b/playground/src/router.ts index 748261dc..354791e2 100644 --- a/playground/src/router.ts +++ b/playground/src/router.ts @@ -76,6 +76,11 @@ const routes = [ name: 'MouseParallax', component: () => import('./pages/MouseParallaxDemo.vue'), }, + { + path: '/abstractions/lensflare', + name: 'MouseParallax', + component: () => import('./pages/LensflareDemo.vue'), + }, ] export const router = createRouter({ diff --git a/src/core/abstractions/Lensflare.vue b/src/core/abstractions/Lensflare.vue new file mode 100644 index 00000000..a0d2aa7c --- /dev/null +++ b/src/core/abstractions/Lensflare.vue @@ -0,0 +1,305 @@ + + + diff --git a/src/core/abstractions/index.ts b/src/core/abstractions/index.ts index f43b4696..26c836f1 100644 --- a/src/core/abstractions/index.ts +++ b/src/core/abstractions/index.ts @@ -4,6 +4,7 @@ import { Environment } from './useEnvironment/component' import Stars from './Stars.vue' import Precipitation from './Precipitation.vue' import Smoke from './Smoke.vue' +import Lensflare from './Lensflare.vue' import Levioso from './Levioso.vue' import ContactShadows from './ContactShadows.vue' import MouseParallax from './MouseParallax.vue' @@ -15,6 +16,7 @@ export { MouseParallax, Stars, Smoke, + Lensflare, Levioso, ContactShadows, Precipitation,