diff --git a/packages/typegpu/scripts/generateSwizzleFunctions.ts b/packages/typegpu/scripts/generateSwizzleFunctions.ts new file mode 100644 index 00000000..72c8c63f --- /dev/null +++ b/packages/typegpu/scripts/generateSwizzleFunctions.ts @@ -0,0 +1,40 @@ +/** + * Prints the swizzling getters to be manually added to the VecBase abstract class. + */ +printSwizzlingFor('xyzw'); + +/** + * Yields combinations of letters from `components` of given `length`. + * + * @example + * vectorComponentCombinations('xyz', 2) // xx, xy, xz, yx, yy ... + */ +function* vectorComponentCombinations( + components: string, + length: number, +): Generator { + if (length > 1) { + for (const str of vectorComponentCombinations(components, length - 1)) { + for (const component of components) { + yield str + component; + } + } + } else { + yield* components; + } +} + +function printSwizzlingFor(components: string) { + const componentIndex: Record = { x: 0, y: 1, z: 2, w: 3 }; + for (const count of [2, 3, 4] as const) { + const vecClassName = `_Vec${count}`; + for (const swizzle of vectorComponentCombinations(components, count)) { + const implementation = ` get ${swizzle}() { return new this.${vecClassName}(${[ + ...swizzle, + ] + .map((s) => `this[${componentIndex[s]}]`) + .join(', ')}); }`; + console.log(implementation); + } + } +} diff --git a/packages/typegpu/src/data/matrix.ts b/packages/typegpu/src/data/matrix.ts index cfac034d..e60e5b8d 100644 --- a/packages/typegpu/src/data/matrix.ts +++ b/packages/typegpu/src/data/matrix.ts @@ -1,10 +1,11 @@ import { inGPUMode } from '../gpuMode'; import type { SelfResolvable } from '../types'; -import { type VecKind, vec2f, vec3f, vec4f } from './vector'; +import { vec2f, vec3f, vec4f } from './vector'; import type { Mat2x2f, Mat3x3f, Mat4x4f, + VecKind, m2x2f, m3x3f, m4x4f, diff --git a/packages/typegpu/src/data/vector.ts b/packages/typegpu/src/data/vector.ts index 9e5e1316..28607294 100644 --- a/packages/typegpu/src/data/vector.ts +++ b/packages/typegpu/src/data/vector.ts @@ -1,5 +1,19 @@ import { inGPUMode } from '../gpuMode'; -import type { SelfResolvable } from '../types'; +import { + Vec2fImpl, + Vec2hImpl, + Vec2iImpl, + Vec2uImpl, + Vec3fImpl, + Vec3hImpl, + Vec3iImpl, + Vec3uImpl, + Vec4fImpl, + Vec4hImpl, + Vec4iImpl, + Vec4uImpl, + type VecBase, +} from './vectorImpl'; import type { Vec2f, Vec2h, @@ -31,478 +45,39 @@ import type { // Implementation // -------------- -interface VecSchemaOptions { - type: TType; - length: number; - make: (...args: number[]) => TValue; - makeFromScalar: (value: number) => TValue; -} - type VecSchemaBase = { readonly type: string; readonly '~repr': TValue; }; -function makeVecSchema( - options: VecSchemaOptions, +function makeVecSchema( + VecImpl: new (...args: number[]) => VecBase, ): VecSchemaBase & ((...args: number[]) => TValue) { - const VecSchema: VecSchemaBase = { - /** Type-token, not available at runtime */ - '~repr': undefined as unknown as TValue, - type: options.type, - }; + const { kind: type, length: componentCount } = new VecImpl(); const construct = (...args: number[]): TValue => { const values = args; // TODO: Allow users to pass in vectors that fill part of the values. if (inGPUMode()) { - return `${VecSchema.type}(${values.join(', ')})` as unknown as TValue; + return `${type}(${values.join(', ')})` as unknown as TValue; } - if (values.length <= 1) { - return options.makeFromScalar(values[0] ?? 0); - } - - if (values.length === options.length) { - return options.make(...values); + if (values.length <= 1 || values.length === componentCount) { + return new VecImpl(...values) as TValue; } throw new Error( - `'${options.type}' constructor called with invalid number of arguments.`, + `'${type}' constructor called with invalid number of arguments.`, ); }; - return Object.assign(construct, VecSchema); -} - -abstract class vec2Impl implements SelfResolvable { - public readonly length = 2; - abstract readonly kind: `vec2${'f' | 'u' | 'i' | 'h'}`; - - [n: number]: number; - - constructor( - public x: number, - public y: number, - ) {} - - *[Symbol.iterator]() { - yield this.x; - yield this.y; - } - - get [0]() { - return this.x; - } - - get [1]() { - return this.y; - } - - set [0](value: number) { - this.x = value; - } - - set [1](value: number) { - this.y = value; - } - - '~resolve'(): string { - return `${this.kind}(${this.x}, ${this.y})`; - } - - toString() { - return this['~resolve'](); - } -} - -class vec2fImpl extends vec2Impl { - readonly kind = 'vec2f'; - - make2(x: number, y: number): v2f { - return new vec2fImpl(x, y) as unknown as v2f; - } - - make3(x: number, y: number, z: number): v3f { - return new vec3fImpl(x, y, z) as unknown as v3f; - } - - make4(x: number, y: number, z: number, w: number): v4f { - return new vec4fImpl(x, y, z, w) as unknown as v4f; - } -} - -class vec2hImpl extends vec2Impl { - readonly kind = 'vec2h'; - - make2(x: number, y: number): v2h { - return new vec2hImpl(x, y) as unknown as v2h; - } - - make3(x: number, y: number, z: number): v3h { - return new vec3hImpl(x, y, z) as unknown as v3h; - } - - make4(x: number, y: number, z: number, w: number): v4h { - return new vec4hImpl(x, y, z, w) as unknown as v4h; - } -} - -class vec2iImpl extends vec2Impl { - readonly kind = 'vec2i'; - - make2(x: number, y: number): v2i { - return new vec2iImpl(x, y) as unknown as v2i; - } - - make3(x: number, y: number, z: number): v3i { - return new vec3iImpl(x, y, z) as unknown as v3i; - } - - make4(x: number, y: number, z: number, w: number): v4i { - return new vec4iImpl(x, y, z, w) as unknown as v4i; - } -} - -class vec2uImpl extends vec2Impl { - readonly kind = 'vec2u'; - - make2(x: number, y: number): v2u { - return new vec2uImpl(x, y) as unknown as v2u; - } - - make3(x: number, y: number, z: number): v3u { - return new vec3uImpl(x, y, z) as unknown as v3u; - } - - make4(x: number, y: number, z: number, w: number): v4u { - return new vec4uImpl(x, y, z, w) as unknown as v4u; - } -} - -abstract class vec3Impl implements SelfResolvable { - public readonly length = 3; - abstract readonly kind: `vec3${'f' | 'u' | 'i' | 'h'}`; - [n: number]: number; - - constructor( - public x: number, - public y: number, - public z: number, - ) {} - - *[Symbol.iterator]() { - yield this.x; - yield this.y; - yield this.z; - } - - get [0]() { - return this.x; - } - - get [1]() { - return this.y; - } - - get [2]() { - return this.z; - } - - set [0](value: number) { - this.x = value; - } - - set [1](value: number) { - this.y = value; - } - - set [2](value: number) { - this.z = value; - } - - '~resolve'(): string { - return `${this.kind}(${this.x}, ${this.y}, ${this.z})`; - } - - toString() { - return this['~resolve'](); - } -} - -class vec3fImpl extends vec3Impl { - readonly kind = 'vec3f'; - - make2(x: number, y: number): v2f { - return new vec2fImpl(x, y) as unknown as v2f; - } - - make3(x: number, y: number, z: number): v3f { - return new vec3fImpl(x, y, z) as unknown as v3f; - } - - make4(x: number, y: number, z: number, w: number): v4f { - return new vec4fImpl(x, y, z, w) as unknown as v4f; - } -} - -class vec3hImpl extends vec3Impl { - readonly kind = 'vec3h'; - - make2(x: number, y: number): v2h { - return new vec2hImpl(x, y) as unknown as v2h; - } - - make3(x: number, y: number, z: number): v3h { - return new vec3hImpl(x, y, z) as unknown as v3h; - } - - make4(x: number, y: number, z: number, w: number): v4h { - return new vec4hImpl(x, y, z, w) as unknown as v4h; - } + return Object.assign(construct, { type, '~repr': undefined as TValue }); } -class vec3iImpl extends vec3Impl { - readonly kind = 'vec3i'; - - make2(x: number, y: number): v2i { - return new vec2iImpl(x, y) as unknown as v2i; - } - - make3(x: number, y: number, z: number): v3i { - return new vec3iImpl(x, y, z) as unknown as v3i; - } - - make4(x: number, y: number, z: number, w: number): v4i { - return new vec4iImpl(x, y, z, w) as unknown as v4i; - } -} - -class vec3uImpl extends vec3Impl { - readonly kind = 'vec3u'; - - make2(x: number, y: number): v2u { - return new vec2uImpl(x, y) as unknown as v2u; - } - - make3(x: number, y: number, z: number): v3u { - return new vec3uImpl(x, y, z) as unknown as v3u; - } - - make4(x: number, y: number, z: number, w: number): v4u { - return new vec4uImpl(x, y, z, w) as unknown as v4u; - } -} - -abstract class vec4Impl implements SelfResolvable { - public readonly length = 4; - abstract readonly kind: `vec4${'f' | 'u' | 'i' | 'h'}`; - [n: number]: number; - - constructor( - public x: number, - public y: number, - public z: number, - public w: number, - ) {} - - *[Symbol.iterator]() { - yield this.x; - yield this.y; - yield this.z; - yield this.w; - } - - get [0]() { - return this.x; - } - - get [1]() { - return this.y; - } - - get [2]() { - return this.z; - } - - get [3]() { - return this.w; - } - - set [0](value: number) { - this.x = value; - } - - set [1](value: number) { - this.y = value; - } - - set [2](value: number) { - this.z = value; - } - - set [3](value: number) { - this.w = value; - } - - '~resolve'(): string { - return `${this.kind}(${this.x}, ${this.y}, ${this.z}, ${this.w})`; - } - - toString() { - return this['~resolve'](); - } -} - -class vec4fImpl extends vec4Impl { - readonly kind = 'vec4f'; - - make2(x: number, y: number): v2f { - return new vec2fImpl(x, y) as unknown as v2f; - } - - make3(x: number, y: number, z: number): v3f { - return new vec3fImpl(x, y, z) as unknown as v3f; - } - - make4(x: number, y: number, z: number, w: number): v4f { - return new vec4fImpl(x, y, z, w) as unknown as v4f; - } -} - -class vec4hImpl extends vec4Impl { - readonly kind = 'vec4h'; - - make2(x: number, y: number): v2h { - return new vec2hImpl(x, y) as unknown as v2h; - } - - make3(x: number, y: number, z: number): v3h { - return new vec3hImpl(x, y, z) as unknown as v3h; - } - - make4(x: number, y: number, z: number, w: number): v4h { - return new vec4hImpl(x, y, z, w) as unknown as v4h; - } -} - -class vec4iImpl extends vec4Impl { - readonly kind = 'vec4i'; - - make2(x: number, y: number): v2i { - return new vec2iImpl(x, y) as unknown as v2i; - } - - make3(x: number, y: number, z: number): v3i { - return new vec3iImpl(x, y, z) as unknown as v3i; - } - - make4(x: number, y: number, z: number, w: number): v4i { - return new vec4iImpl(x, y, z, w) as unknown as v4i; - } -} - -class vec4uImpl extends vec4Impl { - readonly kind = 'vec4u'; - - make2(x: number, y: number): v2u { - return new vec2uImpl(x, y) as unknown as v2u; - } - - make3(x: number, y: number, z: number): v3u { - return new vec3uImpl(x, y, z) as unknown as v3u; - } - - make4(x: number, y: number, z: number, w: number): v4u { - return new vec4uImpl(x, y, z, w) as unknown as v4u; - } -} - -const vecProxyHandler: ProxyHandler<{ kind: VecKind }> = { - get: (target, prop) => { - if (typeof prop === 'symbol' || !Number.isNaN(Number.parseInt(prop))) { - return Reflect.get(target, prop); - } - - const targetAsVec4 = target as unknown as vec4uImpl; - const values = new Array(prop.length) as number[]; - - let idx = 0; - for (const char of prop as string) { - switch (char) { - case 'x': - values[idx] = targetAsVec4.x; - break; - case 'y': - values[idx] = targetAsVec4.y; - break; - case 'z': - values[idx] = targetAsVec4.z; - break; - case 'w': - values[idx] = targetAsVec4.w; - break; - default: - return Reflect.get(targetAsVec4, prop); - } - idx++; - } - - if (prop.length === 4) { - return new Proxy( - targetAsVec4.make4( - values[0] as number, - values[1] as number, - values[2] as number, - values[3] as number, - ), - vecProxyHandler, - ); - } - - if (prop.length === 3) { - return new Proxy( - targetAsVec4.make3( - values[0] as number, - values[1] as number, - values[2] as number, - ), - vecProxyHandler, - ); - } - - if (prop.length === 2) { - return new Proxy( - targetAsVec4.make2(values[0] as number, values[1] as number), - vecProxyHandler, - ); - } - - return Reflect.get(target, prop); - }, -}; - // ---------- // Public API // ---------- -/** - * Type encompassing all available kinds of vector. - */ -export type VecKind = - | 'vec2f' - | 'vec2i' - | 'vec2u' - | 'vec2h' - | 'vec3f' - | 'vec3i' - | 'vec3u' - | 'vec3h' - | 'vec4f' - | 'vec4i' - | 'vec4u' - | 'vec4h'; - /** * Type of the `d.vec2f` object/function: vector data type schema/constructor */ @@ -526,13 +101,7 @@ export type NativeVec2f = Vec2f & { '~exotic': Vec2f } & (( * @example * const buffer = root.createBuffer(d.vec2f, d.vec2f(0, 1)); // buffer holding a d.vec2f value, with an initial value of vec2f(0, 1); */ -export const vec2f = makeVecSchema({ - type: 'vec2f', - length: 2, - make: (x: number, y: number) => - new Proxy(new vec2fImpl(x, y), vecProxyHandler) as v2f, - makeFromScalar: (x) => new Proxy(new vec2fImpl(x, x), vecProxyHandler) as v2f, -}) as NativeVec2f; +export const vec2f = makeVecSchema(Vec2fImpl) as NativeVec2f; /** * Type of the `d.vec2h` object/function: vector data type schema/constructor @@ -557,13 +126,7 @@ export type NativeVec2h = Vec2h & { '~exotic': Vec2h } & (( * @example * const buffer = root.createBuffer(d.vec2h, d.vec2h(0, 1)); // buffer holding a d.vec2h value, with an initial value of vec2h(0, 1); */ -export const vec2h = makeVecSchema({ - type: 'vec2h', - length: 2, - make: (x: number, y: number) => - new Proxy(new vec2hImpl(x, y), vecProxyHandler) as v2h, - makeFromScalar: (x) => new Proxy(new vec2hImpl(x, x), vecProxyHandler) as v2h, -}) as NativeVec2h; +export const vec2h = makeVecSchema(Vec2hImpl) as NativeVec2h; /** * Type of the `d.vec2i` object/function: vector data type schema/constructor @@ -588,13 +151,7 @@ export type NativeVec2i = Vec2i & { '~exotic': Vec2i } & (( * @example * const buffer = root.createBuffer(d.vec2i, d.vec2i(0, 1)); // buffer holding a d.vec2i value, with an initial value of vec2i(0, 1); */ -export const vec2i = makeVecSchema({ - type: 'vec2i', - length: 2, - make: (x: number, y: number) => - new Proxy(new vec2iImpl(x, y), vecProxyHandler) as v2i, - makeFromScalar: (x) => new Proxy(new vec2iImpl(x, x), vecProxyHandler) as v2i, -}) as NativeVec2i; +export const vec2i = makeVecSchema(Vec2iImpl) as NativeVec2i; /** * Type of the `d.vec2u` object/function: vector data type schema/constructor @@ -619,13 +176,7 @@ export type NativeVec2u = Vec2u & { '~exotic': Vec2u } & (( * @example * const buffer = root.createBuffer(d.vec2u, d.vec2u(0, 1)); // buffer holding a d.vec2u value, with an initial value of vec2u(0, 1); */ -export const vec2u = makeVecSchema({ - type: 'vec2u', - length: 2, - make: (x: number, y: number) => - new Proxy(new vec2uImpl(x, y), vecProxyHandler) as v2u, - makeFromScalar: (x) => new Proxy(new vec2uImpl(x, x), vecProxyHandler) as v2u, -}) as NativeVec2u; +export const vec2u = makeVecSchema(Vec2uImpl) as NativeVec2u; /** * Type of the `d.vec3f` object/function: vector data type schema/constructor @@ -651,13 +202,7 @@ export type NativeVec3f = Vec3f & { '~exotic': Vec3f } & (( * @example * const buffer = root.createBuffer(d.vec3f, d.vec3f(0, 1, 2)); // buffer holding a d.vec3f value, with an initial value of vec3f(0, 1, 2); */ -export const vec3f = makeVecSchema({ - type: 'vec3f', - length: 3, - make: (x, y, z) => new Proxy(new vec3fImpl(x, y, z), vecProxyHandler) as v3f, - makeFromScalar: (x) => - new Proxy(new vec3fImpl(x, x, x), vecProxyHandler) as v3f, -}) as NativeVec3f; +export const vec3f = makeVecSchema(Vec3fImpl) as NativeVec3f; /** * Type of the `d.vec3h` object/function: vector data type schema/constructor @@ -683,13 +228,7 @@ export type NativeVec3h = Vec3h & { '~exotic': Vec3h } & (( * @example * const buffer = root.createBuffer(d.vec3h, d.vec3h(0, 1, 2)); // buffer holding a d.vec3h value, with an initial value of vec3h(0, 1, 2); */ -export const vec3h = makeVecSchema({ - type: 'vec3h', - length: 3, - make: (x, y, z) => new Proxy(new vec3hImpl(x, y, z), vecProxyHandler) as v3h, - makeFromScalar: (x) => - new Proxy(new vec3hImpl(x, x, x), vecProxyHandler) as v3h, -}) as NativeVec3h; +export const vec3h = makeVecSchema(Vec3hImpl) as NativeVec3h; /** * Type of the `d.vec3i` object/function: vector data type schema/constructor @@ -715,13 +254,7 @@ export type NativeVec3i = Vec3i & { '~exotic': Vec3i } & (( * @example * const buffer = root.createBuffer(d.vec3i, d.vec3i(0, 1, 2)); // buffer holding a d.vec3i value, with an initial value of vec3i(0, 1, 2); */ -export const vec3i = makeVecSchema({ - type: 'vec3i', - length: 3, - make: (x, y, z) => new Proxy(new vec3iImpl(x, y, z), vecProxyHandler) as v3i, - makeFromScalar: (x) => - new Proxy(new vec3iImpl(x, x, x), vecProxyHandler) as v3i, -}) as NativeVec3i; +export const vec3i = makeVecSchema(Vec3iImpl) as NativeVec3i; /** * Type of the `d.vec3u` object/function: vector data type schema/constructor @@ -747,13 +280,7 @@ export type NativeVec3u = Vec3u & { '~exotic': Vec3u } & (( * @example * const buffer = root.createBuffer(d.vec3u, d.vec3u(0, 1, 2)); // buffer holding a d.vec3u value, with an initial value of vec3u(0, 1, 2); */ -export const vec3u = makeVecSchema({ - type: 'vec3u', - length: 3, - make: (x, y, z) => new Proxy(new vec3uImpl(x, y, z), vecProxyHandler) as v3u, - makeFromScalar: (x) => - new Proxy(new vec3uImpl(x, x, x), vecProxyHandler) as v3u, -}) as NativeVec3u; +export const vec3u = makeVecSchema(Vec3uImpl) as NativeVec3u; /** * Type of the `d.vec4f` object/function: vector data type schema/constructor @@ -780,14 +307,7 @@ export type NativeVec4f = Vec4f & { '~exotic': Vec4f } & (( * @example * const buffer = root.createBuffer(d.vec4f, d.vec4f(0, 1, 2, 3)); // buffer holding a d.vec4f value, with an initial value of vec4f(0, 1, 2, 3); */ -export const vec4f = makeVecSchema({ - type: 'vec4f', - length: 4, - make: (x, y, z, w) => - new Proxy(new vec4fImpl(x, y, z, w), vecProxyHandler) as v4f, - makeFromScalar: (x) => - new Proxy(new vec4fImpl(x, x, x, x), vecProxyHandler) as v4f, -}) as NativeVec4f; +export const vec4f = makeVecSchema(Vec4fImpl) as NativeVec4f; /** * Type of the `d.vec4h` object/function: vector data type schema/constructor @@ -814,14 +334,7 @@ export type NativeVec4h = Vec4h & { '~exotic': Vec4h } & (( * @example * const buffer = root.createBuffer(d.vec4h, d.vec4h(0, 1, 2, 3)); // buffer holding a d.vec4h value, with an initial value of vec4h(0, 1, 2, 3); */ -export const vec4h = makeVecSchema({ - type: 'vec4h', - length: 4, - make: (x, y, z, w) => - new Proxy(new vec4hImpl(x, y, z, w), vecProxyHandler) as v4h, - makeFromScalar: (x) => - new Proxy(new vec4hImpl(x, x, x, x), vecProxyHandler) as v4h, -}) as NativeVec4h; +export const vec4h = makeVecSchema(Vec4hImpl) as NativeVec4h; /** * Type of the `d.vec4i` object/function: vector data type schema/constructor @@ -848,14 +361,7 @@ export type NativeVec4i = Vec4i & { '~exotic': Vec4i } & (( * @example * const buffer = root.createBuffer(d.vec4i, d.vec4i(0, 1, 2, 3)); // buffer holding a d.vec4i value, with an initial value of vec4i(0, 1, 2, 3); */ -export const vec4i = makeVecSchema({ - type: 'vec4i', - length: 4, - make: (x, y, z, w) => - new Proxy(new vec4iImpl(x, y, z, w), vecProxyHandler) as v4i, - makeFromScalar: (x) => - new Proxy(new vec4iImpl(x, x, x, x), vecProxyHandler) as v4i, -}) as NativeVec4i; +export const vec4i = makeVecSchema(Vec4iImpl) as NativeVec4i; /** * Type of the `d.vec4u` object/function: vector data type schema/constructor @@ -882,11 +388,4 @@ export type NativeVec4u = Vec4u & { '~exotic': Vec4u } & (( * @example * const buffer = root.createBuffer(d.vec4u, d.vec4u(0, 1, 2, 3)); // buffer holding a d.vec4u value, with an initial value of vec4u(0, 1, 2, 3); */ -export const vec4u = makeVecSchema({ - length: 4, - type: 'vec4u', - make: (x, y, z, w) => - new Proxy(new vec4uImpl(x, y, z, w), vecProxyHandler) as v4u, - makeFromScalar: (x) => - new Proxy(new vec4uImpl(x, x, x, x), vecProxyHandler) as v4u, -}) as NativeVec4u; +export const vec4u = makeVecSchema(Vec4uImpl) as NativeVec4u; diff --git a/packages/typegpu/src/data/vectorImpl.ts b/packages/typegpu/src/data/vectorImpl.ts new file mode 100644 index 00000000..93b974bb --- /dev/null +++ b/packages/typegpu/src/data/vectorImpl.ts @@ -0,0 +1,683 @@ +import type { SelfResolvable } from '../types'; +import type { VecKind } from './wgslTypes'; + +// biome-ignore format: swizzles should not expand +export abstract class VecBase extends Array implements SelfResolvable { + abstract get kind(): VecKind; + + abstract get _Vec2(): new ( + x: number, + y: number, + ) => Vec2; + abstract get _Vec3(): new ( + x: number, + y: number, + z: number, + ) => Vec3; + abstract get _Vec4(): new ( + x: number, + y: number, + z: number, + w: number, + ) => Vec4; + + '~resolve'(): string { + return `${this.kind}(${this.join(', ')})`; + } + + toString() { + return this['~resolve'](); + } + + get xx() { return new this._Vec2(this[0], this[0]); } + get xy() { return new this._Vec2(this[0], this[1]); } + get xz() { return new this._Vec2(this[0], this[2]); } + get xw() { return new this._Vec2(this[0], this[3]); } + get yx() { return new this._Vec2(this[1], this[0]); } + get yy() { return new this._Vec2(this[1], this[1]); } + get yz() { return new this._Vec2(this[1], this[2]); } + get yw() { return new this._Vec2(this[1], this[3]); } + get zx() { return new this._Vec2(this[2], this[0]); } + get zy() { return new this._Vec2(this[2], this[1]); } + get zz() { return new this._Vec2(this[2], this[2]); } + get zw() { return new this._Vec2(this[2], this[3]); } + get wx() { return new this._Vec2(this[3], this[0]); } + get wy() { return new this._Vec2(this[3], this[1]); } + get wz() { return new this._Vec2(this[3], this[2]); } + get ww() { return new this._Vec2(this[3], this[3]); } + get xxx() { return new this._Vec3(this[0], this[0], this[0]); } + get xxy() { return new this._Vec3(this[0], this[0], this[1]); } + get xxz() { return new this._Vec3(this[0], this[0], this[2]); } + get xxw() { return new this._Vec3(this[0], this[0], this[3]); } + get xyx() { return new this._Vec3(this[0], this[1], this[0]); } + get xyy() { return new this._Vec3(this[0], this[1], this[1]); } + get xyz() { return new this._Vec3(this[0], this[1], this[2]); } + get xyw() { return new this._Vec3(this[0], this[1], this[3]); } + get xzx() { return new this._Vec3(this[0], this[2], this[0]); } + get xzy() { return new this._Vec3(this[0], this[2], this[1]); } + get xzz() { return new this._Vec3(this[0], this[2], this[2]); } + get xzw() { return new this._Vec3(this[0], this[2], this[3]); } + get xwx() { return new this._Vec3(this[0], this[3], this[0]); } + get xwy() { return new this._Vec3(this[0], this[3], this[1]); } + get xwz() { return new this._Vec3(this[0], this[3], this[2]); } + get xww() { return new this._Vec3(this[0], this[3], this[3]); } + get yxx() { return new this._Vec3(this[1], this[0], this[0]); } + get yxy() { return new this._Vec3(this[1], this[0], this[1]); } + get yxz() { return new this._Vec3(this[1], this[0], this[2]); } + get yxw() { return new this._Vec3(this[1], this[0], this[3]); } + get yyx() { return new this._Vec3(this[1], this[1], this[0]); } + get yyy() { return new this._Vec3(this[1], this[1], this[1]); } + get yyz() { return new this._Vec3(this[1], this[1], this[2]); } + get yyw() { return new this._Vec3(this[1], this[1], this[3]); } + get yzx() { return new this._Vec3(this[1], this[2], this[0]); } + get yzy() { return new this._Vec3(this[1], this[2], this[1]); } + get yzz() { return new this._Vec3(this[1], this[2], this[2]); } + get yzw() { return new this._Vec3(this[1], this[2], this[3]); } + get ywx() { return new this._Vec3(this[1], this[3], this[0]); } + get ywy() { return new this._Vec3(this[1], this[3], this[1]); } + get ywz() { return new this._Vec3(this[1], this[3], this[2]); } + get yww() { return new this._Vec3(this[1], this[3], this[3]); } + get zxx() { return new this._Vec3(this[2], this[0], this[0]); } + get zxy() { return new this._Vec3(this[2], this[0], this[1]); } + get zxz() { return new this._Vec3(this[2], this[0], this[2]); } + get zxw() { return new this._Vec3(this[2], this[0], this[3]); } + get zyx() { return new this._Vec3(this[2], this[1], this[0]); } + get zyy() { return new this._Vec3(this[2], this[1], this[1]); } + get zyz() { return new this._Vec3(this[2], this[1], this[2]); } + get zyw() { return new this._Vec3(this[2], this[1], this[3]); } + get zzx() { return new this._Vec3(this[2], this[2], this[0]); } + get zzy() { return new this._Vec3(this[2], this[2], this[1]); } + get zzz() { return new this._Vec3(this[2], this[2], this[2]); } + get zzw() { return new this._Vec3(this[2], this[2], this[3]); } + get zwx() { return new this._Vec3(this[2], this[3], this[0]); } + get zwy() { return new this._Vec3(this[2], this[3], this[1]); } + get zwz() { return new this._Vec3(this[2], this[3], this[2]); } + get zww() { return new this._Vec3(this[2], this[3], this[3]); } + get wxx() { return new this._Vec3(this[3], this[0], this[0]); } + get wxy() { return new this._Vec3(this[3], this[0], this[1]); } + get wxz() { return new this._Vec3(this[3], this[0], this[2]); } + get wxw() { return new this._Vec3(this[3], this[0], this[3]); } + get wyx() { return new this._Vec3(this[3], this[1], this[0]); } + get wyy() { return new this._Vec3(this[3], this[1], this[1]); } + get wyz() { return new this._Vec3(this[3], this[1], this[2]); } + get wyw() { return new this._Vec3(this[3], this[1], this[3]); } + get wzx() { return new this._Vec3(this[3], this[2], this[0]); } + get wzy() { return new this._Vec3(this[3], this[2], this[1]); } + get wzz() { return new this._Vec3(this[3], this[2], this[2]); } + get wzw() { return new this._Vec3(this[3], this[2], this[3]); } + get wwx() { return new this._Vec3(this[3], this[3], this[0]); } + get wwy() { return new this._Vec3(this[3], this[3], this[1]); } + get wwz() { return new this._Vec3(this[3], this[3], this[2]); } + get www() { return new this._Vec3(this[3], this[3], this[3]); } + get xxxx() { return new this._Vec4(this[0], this[0], this[0], this[0]); } + get xxxy() { return new this._Vec4(this[0], this[0], this[0], this[1]); } + get xxxz() { return new this._Vec4(this[0], this[0], this[0], this[2]); } + get xxxw() { return new this._Vec4(this[0], this[0], this[0], this[3]); } + get xxyx() { return new this._Vec4(this[0], this[0], this[1], this[0]); } + get xxyy() { return new this._Vec4(this[0], this[0], this[1], this[1]); } + get xxyz() { return new this._Vec4(this[0], this[0], this[1], this[2]); } + get xxyw() { return new this._Vec4(this[0], this[0], this[1], this[3]); } + get xxzx() { return new this._Vec4(this[0], this[0], this[2], this[0]); } + get xxzy() { return new this._Vec4(this[0], this[0], this[2], this[1]); } + get xxzz() { return new this._Vec4(this[0], this[0], this[2], this[2]); } + get xxzw() { return new this._Vec4(this[0], this[0], this[2], this[3]); } + get xxwx() { return new this._Vec4(this[0], this[0], this[3], this[0]); } + get xxwy() { return new this._Vec4(this[0], this[0], this[3], this[1]); } + get xxwz() { return new this._Vec4(this[0], this[0], this[3], this[2]); } + get xxww() { return new this._Vec4(this[0], this[0], this[3], this[3]); } + get xyxx() { return new this._Vec4(this[0], this[1], this[0], this[0]); } + get xyxy() { return new this._Vec4(this[0], this[1], this[0], this[1]); } + get xyxz() { return new this._Vec4(this[0], this[1], this[0], this[2]); } + get xyxw() { return new this._Vec4(this[0], this[1], this[0], this[3]); } + get xyyx() { return new this._Vec4(this[0], this[1], this[1], this[0]); } + get xyyy() { return new this._Vec4(this[0], this[1], this[1], this[1]); } + get xyyz() { return new this._Vec4(this[0], this[1], this[1], this[2]); } + get xyyw() { return new this._Vec4(this[0], this[1], this[1], this[3]); } + get xyzx() { return new this._Vec4(this[0], this[1], this[2], this[0]); } + get xyzy() { return new this._Vec4(this[0], this[1], this[2], this[1]); } + get xyzz() { return new this._Vec4(this[0], this[1], this[2], this[2]); } + get xyzw() { return new this._Vec4(this[0], this[1], this[2], this[3]); } + get xywx() { return new this._Vec4(this[0], this[1], this[3], this[0]); } + get xywy() { return new this._Vec4(this[0], this[1], this[3], this[1]); } + get xywz() { return new this._Vec4(this[0], this[1], this[3], this[2]); } + get xyww() { return new this._Vec4(this[0], this[1], this[3], this[3]); } + get xzxx() { return new this._Vec4(this[0], this[2], this[0], this[0]); } + get xzxy() { return new this._Vec4(this[0], this[2], this[0], this[1]); } + get xzxz() { return new this._Vec4(this[0], this[2], this[0], this[2]); } + get xzxw() { return new this._Vec4(this[0], this[2], this[0], this[3]); } + get xzyx() { return new this._Vec4(this[0], this[2], this[1], this[0]); } + get xzyy() { return new this._Vec4(this[0], this[2], this[1], this[1]); } + get xzyz() { return new this._Vec4(this[0], this[2], this[1], this[2]); } + get xzyw() { return new this._Vec4(this[0], this[2], this[1], this[3]); } + get xzzx() { return new this._Vec4(this[0], this[2], this[2], this[0]); } + get xzzy() { return new this._Vec4(this[0], this[2], this[2], this[1]); } + get xzzz() { return new this._Vec4(this[0], this[2], this[2], this[2]); } + get xzzw() { return new this._Vec4(this[0], this[2], this[2], this[3]); } + get xzwx() { return new this._Vec4(this[0], this[2], this[3], this[0]); } + get xzwy() { return new this._Vec4(this[0], this[2], this[3], this[1]); } + get xzwz() { return new this._Vec4(this[0], this[2], this[3], this[2]); } + get xzww() { return new this._Vec4(this[0], this[2], this[3], this[3]); } + get xwxx() { return new this._Vec4(this[0], this[3], this[0], this[0]); } + get xwxy() { return new this._Vec4(this[0], this[3], this[0], this[1]); } + get xwxz() { return new this._Vec4(this[0], this[3], this[0], this[2]); } + get xwxw() { return new this._Vec4(this[0], this[3], this[0], this[3]); } + get xwyx() { return new this._Vec4(this[0], this[3], this[1], this[0]); } + get xwyy() { return new this._Vec4(this[0], this[3], this[1], this[1]); } + get xwyz() { return new this._Vec4(this[0], this[3], this[1], this[2]); } + get xwyw() { return new this._Vec4(this[0], this[3], this[1], this[3]); } + get xwzx() { return new this._Vec4(this[0], this[3], this[2], this[0]); } + get xwzy() { return new this._Vec4(this[0], this[3], this[2], this[1]); } + get xwzz() { return new this._Vec4(this[0], this[3], this[2], this[2]); } + get xwzw() { return new this._Vec4(this[0], this[3], this[2], this[3]); } + get xwwx() { return new this._Vec4(this[0], this[3], this[3], this[0]); } + get xwwy() { return new this._Vec4(this[0], this[3], this[3], this[1]); } + get xwwz() { return new this._Vec4(this[0], this[3], this[3], this[2]); } + get xwww() { return new this._Vec4(this[0], this[3], this[3], this[3]); } + get yxxx() { return new this._Vec4(this[1], this[0], this[0], this[0]); } + get yxxy() { return new this._Vec4(this[1], this[0], this[0], this[1]); } + get yxxz() { return new this._Vec4(this[1], this[0], this[0], this[2]); } + get yxxw() { return new this._Vec4(this[1], this[0], this[0], this[3]); } + get yxyx() { return new this._Vec4(this[1], this[0], this[1], this[0]); } + get yxyy() { return new this._Vec4(this[1], this[0], this[1], this[1]); } + get yxyz() { return new this._Vec4(this[1], this[0], this[1], this[2]); } + get yxyw() { return new this._Vec4(this[1], this[0], this[1], this[3]); } + get yxzx() { return new this._Vec4(this[1], this[0], this[2], this[0]); } + get yxzy() { return new this._Vec4(this[1], this[0], this[2], this[1]); } + get yxzz() { return new this._Vec4(this[1], this[0], this[2], this[2]); } + get yxzw() { return new this._Vec4(this[1], this[0], this[2], this[3]); } + get yxwx() { return new this._Vec4(this[1], this[0], this[3], this[0]); } + get yxwy() { return new this._Vec4(this[1], this[0], this[3], this[1]); } + get yxwz() { return new this._Vec4(this[1], this[0], this[3], this[2]); } + get yxww() { return new this._Vec4(this[1], this[0], this[3], this[3]); } + get yyxx() { return new this._Vec4(this[1], this[1], this[0], this[0]); } + get yyxy() { return new this._Vec4(this[1], this[1], this[0], this[1]); } + get yyxz() { return new this._Vec4(this[1], this[1], this[0], this[2]); } + get yyxw() { return new this._Vec4(this[1], this[1], this[0], this[3]); } + get yyyx() { return new this._Vec4(this[1], this[1], this[1], this[0]); } + get yyyy() { return new this._Vec4(this[1], this[1], this[1], this[1]); } + get yyyz() { return new this._Vec4(this[1], this[1], this[1], this[2]); } + get yyyw() { return new this._Vec4(this[1], this[1], this[1], this[3]); } + get yyzx() { return new this._Vec4(this[1], this[1], this[2], this[0]); } + get yyzy() { return new this._Vec4(this[1], this[1], this[2], this[1]); } + get yyzz() { return new this._Vec4(this[1], this[1], this[2], this[2]); } + get yyzw() { return new this._Vec4(this[1], this[1], this[2], this[3]); } + get yywx() { return new this._Vec4(this[1], this[1], this[3], this[0]); } + get yywy() { return new this._Vec4(this[1], this[1], this[3], this[1]); } + get yywz() { return new this._Vec4(this[1], this[1], this[3], this[2]); } + get yyww() { return new this._Vec4(this[1], this[1], this[3], this[3]); } + get yzxx() { return new this._Vec4(this[1], this[2], this[0], this[0]); } + get yzxy() { return new this._Vec4(this[1], this[2], this[0], this[1]); } + get yzxz() { return new this._Vec4(this[1], this[2], this[0], this[2]); } + get yzxw() { return new this._Vec4(this[1], this[2], this[0], this[3]); } + get yzyx() { return new this._Vec4(this[1], this[2], this[1], this[0]); } + get yzyy() { return new this._Vec4(this[1], this[2], this[1], this[1]); } + get yzyz() { return new this._Vec4(this[1], this[2], this[1], this[2]); } + get yzyw() { return new this._Vec4(this[1], this[2], this[1], this[3]); } + get yzzx() { return new this._Vec4(this[1], this[2], this[2], this[0]); } + get yzzy() { return new this._Vec4(this[1], this[2], this[2], this[1]); } + get yzzz() { return new this._Vec4(this[1], this[2], this[2], this[2]); } + get yzzw() { return new this._Vec4(this[1], this[2], this[2], this[3]); } + get yzwx() { return new this._Vec4(this[1], this[2], this[3], this[0]); } + get yzwy() { return new this._Vec4(this[1], this[2], this[3], this[1]); } + get yzwz() { return new this._Vec4(this[1], this[2], this[3], this[2]); } + get yzww() { return new this._Vec4(this[1], this[2], this[3], this[3]); } + get ywxx() { return new this._Vec4(this[1], this[3], this[0], this[0]); } + get ywxy() { return new this._Vec4(this[1], this[3], this[0], this[1]); } + get ywxz() { return new this._Vec4(this[1], this[3], this[0], this[2]); } + get ywxw() { return new this._Vec4(this[1], this[3], this[0], this[3]); } + get ywyx() { return new this._Vec4(this[1], this[3], this[1], this[0]); } + get ywyy() { return new this._Vec4(this[1], this[3], this[1], this[1]); } + get ywyz() { return new this._Vec4(this[1], this[3], this[1], this[2]); } + get ywyw() { return new this._Vec4(this[1], this[3], this[1], this[3]); } + get ywzx() { return new this._Vec4(this[1], this[3], this[2], this[0]); } + get ywzy() { return new this._Vec4(this[1], this[3], this[2], this[1]); } + get ywzz() { return new this._Vec4(this[1], this[3], this[2], this[2]); } + get ywzw() { return new this._Vec4(this[1], this[3], this[2], this[3]); } + get ywwx() { return new this._Vec4(this[1], this[3], this[3], this[0]); } + get ywwy() { return new this._Vec4(this[1], this[3], this[3], this[1]); } + get ywwz() { return new this._Vec4(this[1], this[3], this[3], this[2]); } + get ywww() { return new this._Vec4(this[1], this[3], this[3], this[3]); } + get zxxx() { return new this._Vec4(this[2], this[0], this[0], this[0]); } + get zxxy() { return new this._Vec4(this[2], this[0], this[0], this[1]); } + get zxxz() { return new this._Vec4(this[2], this[0], this[0], this[2]); } + get zxxw() { return new this._Vec4(this[2], this[0], this[0], this[3]); } + get zxyx() { return new this._Vec4(this[2], this[0], this[1], this[0]); } + get zxyy() { return new this._Vec4(this[2], this[0], this[1], this[1]); } + get zxyz() { return new this._Vec4(this[2], this[0], this[1], this[2]); } + get zxyw() { return new this._Vec4(this[2], this[0], this[1], this[3]); } + get zxzx() { return new this._Vec4(this[2], this[0], this[2], this[0]); } + get zxzy() { return new this._Vec4(this[2], this[0], this[2], this[1]); } + get zxzz() { return new this._Vec4(this[2], this[0], this[2], this[2]); } + get zxzw() { return new this._Vec4(this[2], this[0], this[2], this[3]); } + get zxwx() { return new this._Vec4(this[2], this[0], this[3], this[0]); } + get zxwy() { return new this._Vec4(this[2], this[0], this[3], this[1]); } + get zxwz() { return new this._Vec4(this[2], this[0], this[3], this[2]); } + get zxww() { return new this._Vec4(this[2], this[0], this[3], this[3]); } + get zyxx() { return new this._Vec4(this[2], this[1], this[0], this[0]); } + get zyxy() { return new this._Vec4(this[2], this[1], this[0], this[1]); } + get zyxz() { return new this._Vec4(this[2], this[1], this[0], this[2]); } + get zyxw() { return new this._Vec4(this[2], this[1], this[0], this[3]); } + get zyyx() { return new this._Vec4(this[2], this[1], this[1], this[0]); } + get zyyy() { return new this._Vec4(this[2], this[1], this[1], this[1]); } + get zyyz() { return new this._Vec4(this[2], this[1], this[1], this[2]); } + get zyyw() { return new this._Vec4(this[2], this[1], this[1], this[3]); } + get zyzx() { return new this._Vec4(this[2], this[1], this[2], this[0]); } + get zyzy() { return new this._Vec4(this[2], this[1], this[2], this[1]); } + get zyzz() { return new this._Vec4(this[2], this[1], this[2], this[2]); } + get zyzw() { return new this._Vec4(this[2], this[1], this[2], this[3]); } + get zywx() { return new this._Vec4(this[2], this[1], this[3], this[0]); } + get zywy() { return new this._Vec4(this[2], this[1], this[3], this[1]); } + get zywz() { return new this._Vec4(this[2], this[1], this[3], this[2]); } + get zyww() { return new this._Vec4(this[2], this[1], this[3], this[3]); } + get zzxx() { return new this._Vec4(this[2], this[2], this[0], this[0]); } + get zzxy() { return new this._Vec4(this[2], this[2], this[0], this[1]); } + get zzxz() { return new this._Vec4(this[2], this[2], this[0], this[2]); } + get zzxw() { return new this._Vec4(this[2], this[2], this[0], this[3]); } + get zzyx() { return new this._Vec4(this[2], this[2], this[1], this[0]); } + get zzyy() { return new this._Vec4(this[2], this[2], this[1], this[1]); } + get zzyz() { return new this._Vec4(this[2], this[2], this[1], this[2]); } + get zzyw() { return new this._Vec4(this[2], this[2], this[1], this[3]); } + get zzzx() { return new this._Vec4(this[2], this[2], this[2], this[0]); } + get zzzy() { return new this._Vec4(this[2], this[2], this[2], this[1]); } + get zzzz() { return new this._Vec4(this[2], this[2], this[2], this[2]); } + get zzzw() { return new this._Vec4(this[2], this[2], this[2], this[3]); } + get zzwx() { return new this._Vec4(this[2], this[2], this[3], this[0]); } + get zzwy() { return new this._Vec4(this[2], this[2], this[3], this[1]); } + get zzwz() { return new this._Vec4(this[2], this[2], this[3], this[2]); } + get zzww() { return new this._Vec4(this[2], this[2], this[3], this[3]); } + get zwxx() { return new this._Vec4(this[2], this[3], this[0], this[0]); } + get zwxy() { return new this._Vec4(this[2], this[3], this[0], this[1]); } + get zwxz() { return new this._Vec4(this[2], this[3], this[0], this[2]); } + get zwxw() { return new this._Vec4(this[2], this[3], this[0], this[3]); } + get zwyx() { return new this._Vec4(this[2], this[3], this[1], this[0]); } + get zwyy() { return new this._Vec4(this[2], this[3], this[1], this[1]); } + get zwyz() { return new this._Vec4(this[2], this[3], this[1], this[2]); } + get zwyw() { return new this._Vec4(this[2], this[3], this[1], this[3]); } + get zwzx() { return new this._Vec4(this[2], this[3], this[2], this[0]); } + get zwzy() { return new this._Vec4(this[2], this[3], this[2], this[1]); } + get zwzz() { return new this._Vec4(this[2], this[3], this[2], this[2]); } + get zwzw() { return new this._Vec4(this[2], this[3], this[2], this[3]); } + get zwwx() { return new this._Vec4(this[2], this[3], this[3], this[0]); } + get zwwy() { return new this._Vec4(this[2], this[3], this[3], this[1]); } + get zwwz() { return new this._Vec4(this[2], this[3], this[3], this[2]); } + get zwww() { return new this._Vec4(this[2], this[3], this[3], this[3]); } + get wxxx() { return new this._Vec4(this[3], this[0], this[0], this[0]); } + get wxxy() { return new this._Vec4(this[3], this[0], this[0], this[1]); } + get wxxz() { return new this._Vec4(this[3], this[0], this[0], this[2]); } + get wxxw() { return new this._Vec4(this[3], this[0], this[0], this[3]); } + get wxyx() { return new this._Vec4(this[3], this[0], this[1], this[0]); } + get wxyy() { return new this._Vec4(this[3], this[0], this[1], this[1]); } + get wxyz() { return new this._Vec4(this[3], this[0], this[1], this[2]); } + get wxyw() { return new this._Vec4(this[3], this[0], this[1], this[3]); } + get wxzx() { return new this._Vec4(this[3], this[0], this[2], this[0]); } + get wxzy() { return new this._Vec4(this[3], this[0], this[2], this[1]); } + get wxzz() { return new this._Vec4(this[3], this[0], this[2], this[2]); } + get wxzw() { return new this._Vec4(this[3], this[0], this[2], this[3]); } + get wxwx() { return new this._Vec4(this[3], this[0], this[3], this[0]); } + get wxwy() { return new this._Vec4(this[3], this[0], this[3], this[1]); } + get wxwz() { return new this._Vec4(this[3], this[0], this[3], this[2]); } + get wxww() { return new this._Vec4(this[3], this[0], this[3], this[3]); } + get wyxx() { return new this._Vec4(this[3], this[1], this[0], this[0]); } + get wyxy() { return new this._Vec4(this[3], this[1], this[0], this[1]); } + get wyxz() { return new this._Vec4(this[3], this[1], this[0], this[2]); } + get wyxw() { return new this._Vec4(this[3], this[1], this[0], this[3]); } + get wyyx() { return new this._Vec4(this[3], this[1], this[1], this[0]); } + get wyyy() { return new this._Vec4(this[3], this[1], this[1], this[1]); } + get wyyz() { return new this._Vec4(this[3], this[1], this[1], this[2]); } + get wyyw() { return new this._Vec4(this[3], this[1], this[1], this[3]); } + get wyzx() { return new this._Vec4(this[3], this[1], this[2], this[0]); } + get wyzy() { return new this._Vec4(this[3], this[1], this[2], this[1]); } + get wyzz() { return new this._Vec4(this[3], this[1], this[2], this[2]); } + get wyzw() { return new this._Vec4(this[3], this[1], this[2], this[3]); } + get wywx() { return new this._Vec4(this[3], this[1], this[3], this[0]); } + get wywy() { return new this._Vec4(this[3], this[1], this[3], this[1]); } + get wywz() { return new this._Vec4(this[3], this[1], this[3], this[2]); } + get wyww() { return new this._Vec4(this[3], this[1], this[3], this[3]); } + get wzxx() { return new this._Vec4(this[3], this[2], this[0], this[0]); } + get wzxy() { return new this._Vec4(this[3], this[2], this[0], this[1]); } + get wzxz() { return new this._Vec4(this[3], this[2], this[0], this[2]); } + get wzxw() { return new this._Vec4(this[3], this[2], this[0], this[3]); } + get wzyx() { return new this._Vec4(this[3], this[2], this[1], this[0]); } + get wzyy() { return new this._Vec4(this[3], this[2], this[1], this[1]); } + get wzyz() { return new this._Vec4(this[3], this[2], this[1], this[2]); } + get wzyw() { return new this._Vec4(this[3], this[2], this[1], this[3]); } + get wzzx() { return new this._Vec4(this[3], this[2], this[2], this[0]); } + get wzzy() { return new this._Vec4(this[3], this[2], this[2], this[1]); } + get wzzz() { return new this._Vec4(this[3], this[2], this[2], this[2]); } + get wzzw() { return new this._Vec4(this[3], this[2], this[2], this[3]); } + get wzwx() { return new this._Vec4(this[3], this[2], this[3], this[0]); } + get wzwy() { return new this._Vec4(this[3], this[2], this[3], this[1]); } + get wzwz() { return new this._Vec4(this[3], this[2], this[3], this[2]); } + get wzww() { return new this._Vec4(this[3], this[2], this[3], this[3]); } + get wwxx() { return new this._Vec4(this[3], this[3], this[0], this[0]); } + get wwxy() { return new this._Vec4(this[3], this[3], this[0], this[1]); } + get wwxz() { return new this._Vec4(this[3], this[3], this[0], this[2]); } + get wwxw() { return new this._Vec4(this[3], this[3], this[0], this[3]); } + get wwyx() { return new this._Vec4(this[3], this[3], this[1], this[0]); } + get wwyy() { return new this._Vec4(this[3], this[3], this[1], this[1]); } + get wwyz() { return new this._Vec4(this[3], this[3], this[1], this[2]); } + get wwyw() { return new this._Vec4(this[3], this[3], this[1], this[3]); } + get wwzx() { return new this._Vec4(this[3], this[3], this[2], this[0]); } + get wwzy() { return new this._Vec4(this[3], this[3], this[2], this[1]); } + get wwzz() { return new this._Vec4(this[3], this[3], this[2], this[2]); } + get wwzw() { return new this._Vec4(this[3], this[3], this[2], this[3]); } + get wwwx() { return new this._Vec4(this[3], this[3], this[3], this[0]); } + get wwwy() { return new this._Vec4(this[3], this[3], this[3], this[1]); } + get wwwz() { return new this._Vec4(this[3], this[3], this[3], this[2]); } + get wwww() { return new this._Vec4(this[3], this[3], this[3], this[3]); } +} + +type Tuple2 = [number, number]; +type Tuple3 = [number, number, number]; +type Tuple4 = [number, number, number, number]; + +abstract class Vec2 extends VecBase implements Tuple2 { + declare readonly length = 2; + + 0: number; + 1: number; + + constructor(x?: number, y?: number) { + super(2); + this[0] = x ?? 0; + this[1] = y ?? x ?? 0; + } + + get x() { + return this[0]; + } + + get y() { + return this[1]; + } + + set x(value: number) { + this[0] = value; + } + + set y(value: number) { + this[1] = value; + } +} + +// biome-ignore format: swizzles should not expand +abstract class Vec3 extends VecBase implements Tuple3 { + declare readonly length = 3; + + 0: number; + 1: number; + 2: number; + + constructor(x?: number, y?: number, z?: number) { + super(3); + this[0] = x ?? 0; + this[1] = y ?? x ?? 0; + this[2] = z ?? x ?? 0; + } + + get x() { + return this[0]; + } + + get y() { + return this[1]; + } + + get z() { + return this[2]; + } + + set x(value: number) { + this[0] = value; + } + + set y(value: number) { + this[1] = value; + } + + set z(value: number) { + this[2] = value; + } +} + +// biome-ignore format: swizzles should not expand +abstract class Vec4 extends VecBase implements Tuple4 { + declare readonly length = 4; + + 0: number; + 1: number; + 2: number; + 3: number; + + constructor(x?: number, y?: number, z?: number, w?: number) { + super(4); + this[0] = x ?? 0; + this[1] = y ?? x ?? 0; + this[2] = z ?? x ?? 0; + this[3] = w ?? x ?? 0; + } + + get x() { + return this[0]; + } + + get y() { + return this[1]; + } + + get z() { + return this[2]; + } + + get w() { + return this[3]; + } + + set x(value: number) { + this[0] = value; + } + + set y(value: number) { + this[1] = value; + } + + set z(value: number) { + this[2] = value; + } + + set w(value: number) { + this[3] = value; + } +} + +export class Vec2fImpl extends Vec2 { + get kind() { + return 'vec2f' as const; + } + + get _Vec2() { + return Vec2fImpl; + } + get _Vec3() { + return Vec3fImpl; + } + get _Vec4() { + return Vec4fImpl; + } +} + +export class Vec2hImpl extends Vec2 { + get kind() { + return 'vec2h' as const; + } + + get _Vec2() { + return Vec2hImpl; + } + get _Vec3() { + return Vec3hImpl; + } + get _Vec4() { + return Vec4hImpl; + } +} + +export class Vec2iImpl extends Vec2 { + get kind() { + return 'vec2i' as const; + } + + get _Vec2() { + return Vec2iImpl; + } + get _Vec3() { + return Vec3iImpl; + } + get _Vec4() { + return Vec4iImpl; + } +} + +export class Vec2uImpl extends Vec2 { + get kind() { + return 'vec2u' as const; + } + + get _Vec2() { + return Vec2uImpl; + } + get _Vec3() { + return Vec3uImpl; + } + get _Vec4() { + return Vec4uImpl; + } +} + +export class Vec3fImpl extends Vec3 { + get kind() { + return 'vec3f' as const; + } + + get _Vec2() { + return Vec2fImpl; + } + get _Vec3() { + return Vec3fImpl; + } + get _Vec4() { + return Vec4fImpl; + } +} + +export class Vec3hImpl extends Vec3 { + get kind() { + return 'vec3h' as const; + } + + get _Vec2() { + return Vec2hImpl; + } + get _Vec3() { + return Vec3hImpl; + } + get _Vec4() { + return Vec4hImpl; + } +} + +export class Vec3iImpl extends Vec3 { + get kind() { + return 'vec3i' as const; + } + + get _Vec2() { + return Vec2iImpl; + } + get _Vec3() { + return Vec3iImpl; + } + get _Vec4() { + return Vec4iImpl; + } +} + +export class Vec3uImpl extends Vec3 { + get kind() { + return 'vec3u' as const; + } + + get _Vec2() { + return Vec2uImpl; + } + get _Vec3() { + return Vec3uImpl; + } + get _Vec4() { + return Vec4uImpl; + } +} + +export class Vec4fImpl extends Vec4 { + get kind() { + return 'vec4f' as const; + } + + get _Vec2() { + return Vec2fImpl; + } + get _Vec3() { + return Vec3fImpl; + } + get _Vec4() { + return Vec4fImpl; + } +} + +export class Vec4hImpl extends Vec4 { + get kind() { + return 'vec4h' as const; + } + + get _Vec2() { + return Vec2hImpl; + } + get _Vec3() { + return Vec3hImpl; + } + get _Vec4() { + return Vec4hImpl; + } +} + +export class Vec4iImpl extends Vec4 { + get kind() { + return 'vec4i' as const; + } + + get _Vec2() { + return Vec2iImpl; + } + get _Vec3() { + return Vec3iImpl; + } + get _Vec4() { + return Vec4iImpl; + } +} + +export class Vec4uImpl extends Vec4 { + get kind() { + return 'vec4u' as const; + } + + get _Vec2() { + return Vec2uImpl; + } + get _Vec3() { + return Vec3uImpl; + } + get _Vec4() { + return Vec4uImpl; + } +} diff --git a/packages/typegpu/src/data/vectorOps.ts b/packages/typegpu/src/data/vectorOps.ts index c362c30c..aeeafa22 100644 --- a/packages/typegpu/src/data/vectorOps.ts +++ b/packages/typegpu/src/data/vectorOps.ts @@ -1,5 +1,4 @@ import { - type VecKind, vec2f, vec2h, vec2i, @@ -15,7 +14,7 @@ import { } from './vector'; import type * as wgsl from './wgslTypes'; -type vBase = { kind: VecKind }; +type vBase = { kind: wgsl.VecKind }; type v2 = wgsl.v2f | wgsl.v2h | wgsl.v2i | wgsl.v2u; type v3 = wgsl.v3f | wgsl.v3h | wgsl.v3i | wgsl.v3u; type v4 = wgsl.v4f | wgsl.v4h | wgsl.v4i | wgsl.v4u; @@ -54,7 +53,7 @@ export const VectorOps = { vec4i(Math.abs(v.x), Math.abs(v.y), Math.abs(v.z), Math.abs(v.w)), vec4u: (v: wgsl.v4u) => vec4u(Math.abs(v.x), Math.abs(v.y), Math.abs(v.z), Math.abs(v.w)), - } as Record(v: T) => T>, + } as Record(v: T) => T>, ceil: { vec2f: (v: wgsl.v2f) => vec2f(Math.ceil(v.x), Math.ceil(v.y)), @@ -79,7 +78,7 @@ export const VectorOps = { vec4i(Math.ceil(v.x), Math.ceil(v.y), Math.ceil(v.z), Math.ceil(v.w)), vec4u: (v: wgsl.v4u) => vec4u(Math.ceil(v.x), Math.ceil(v.y), Math.ceil(v.z), Math.ceil(v.w)), - } as Record(v: T) => T>, + } as Record(v: T) => T>, clamp: { vec2f: (v: wgsl.v2f, low: wgsl.v2f, high: wgsl.v2f) => @@ -144,7 +143,7 @@ export const VectorOps = { clamp(v.z, low.z, high.z), clamp(v.w, low.w, high.w), ), - } as Record(v: T, low: T, high: T) => T>, + } as Record(v: T, low: T, high: T) => T>, length: { vec2f: lengthVec2, @@ -159,7 +158,7 @@ export const VectorOps = { vec4h: lengthVec4, vec4i: lengthVec4, vec4u: lengthVec4, - } as Record number>, + } as Record number>, add: { vec2f: (a: wgsl.v2f, b: wgsl.v2f) => vec2f(a.x + b.x, a.y + b.y), @@ -180,7 +179,7 @@ export const VectorOps = { vec4i(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w), vec4u: (a: wgsl.v4u, b: wgsl.v4u) => vec4u(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w), - } as Record(lhs: T, rhs: T) => T>, + } as Record(lhs: T, rhs: T) => T>, sub: { vec2f: (a: wgsl.v2f, b: wgsl.v2f) => vec2f(a.x - b.x, a.y - b.y), @@ -201,7 +200,7 @@ export const VectorOps = { vec4i(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w), vec4u: (a: wgsl.v4u, b: wgsl.v4u) => vec4u(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w), - } as Record(lhs: T, rhs: T) => T>, + } as Record(lhs: T, rhs: T) => T>, mulSxV: { vec2f: (s: number, v: wgsl.v2f) => vec2f(s * v.x, s * v.y), @@ -222,7 +221,7 @@ export const VectorOps = { vec4i(s * v.x, s * v.y, s * v.z, s * v.w), vec4u: (s: number, v: wgsl.v4u) => vec4u(s * v.x, s * v.y, s * v.z, s * v.w), - } as Record(s: number, v: T) => T>, + } as Record(s: number, v: T) => T>, mulVxV: { vec2f: (a: wgsl.v2f, b: wgsl.v2f) => vec2f(a.x * b.x, a.y * b.y), @@ -243,7 +242,7 @@ export const VectorOps = { vec4i(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w), vec4u: (a: wgsl.v4u, b: wgsl.v4u) => vec4u(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w), - } as Record(lhs: T, rhs: T) => T>, + } as Record(lhs: T, rhs: T) => T>, dot: { vec2f: dotVec2, @@ -258,7 +257,7 @@ export const VectorOps = { vec4h: dotVec4, vec4i: dotVec4, vec4u: dotVec4, - } as Record(lhs: T, rhs: T) => number>, + } as Record(lhs: T, rhs: T) => number>, normalize: { vec2f: (v: wgsl.v2f) => { @@ -311,7 +310,7 @@ export const VectorOps = { const len = lengthVec4(v); return vec4u(v.x / len, v.y / len, v.z / len, v.w / len); }, - } as Record(v: T) => T>, + } as Record(v: T) => T>, cross: { vec3f: (a: wgsl.v3f, b: wgsl.v3f) => { @@ -370,7 +369,7 @@ export const VectorOps = { vec4i(Math.floor(v.x), Math.floor(v.y), Math.floor(v.z), Math.floor(v.w)), vec4u: (v: wgsl.v4u) => vec4u(Math.floor(v.x), Math.floor(v.y), Math.floor(v.z), Math.floor(v.w)), - } as Record(v: T) => T>, + } as Record(v: T) => T>, max: { vec2f: (a: wgsl.v2f, b: wgsl.v2f) => @@ -419,7 +418,7 @@ export const VectorOps = { Math.max(a.z, b.z), Math.max(a.w, b.w), ), - } as Record(a: T, b: T) => T>, + } as Record(a: T, b: T) => T>, min: { vec2f: (a: wgsl.v2f, b: wgsl.v2f) => @@ -468,5 +467,5 @@ export const VectorOps = { Math.min(a.z, b.z), Math.min(a.w, b.w), ), - } as Record(a: T, b: T) => T>, + } as Record(a: T, b: T) => T>, }; diff --git a/packages/typegpu/src/data/wgslTypes.ts b/packages/typegpu/src/data/wgslTypes.ts index 8a78c3e2..6cc8c1de 100644 --- a/packages/typegpu/src/data/wgslTypes.ts +++ b/packages/typegpu/src/data/wgslTypes.ts @@ -495,6 +495,8 @@ export type AnyVecInstance = | v4i | v4u; +export type VecKind = AnyVecInstance['kind']; + export interface matBase extends NumberArrayView { readonly columns: readonly TColumn[]; } diff --git a/packages/typegpu/src/std/numeric.ts b/packages/typegpu/src/std/numeric.ts index 4b003756..d7c6f657 100644 --- a/packages/typegpu/src/std/numeric.ts +++ b/packages/typegpu/src/std/numeric.ts @@ -1,6 +1,5 @@ -import type { VecKind } from '../data/vector'; import { VectorOps } from '../data/vectorOps'; -import type { v3f, v3i, v3u } from '../data/wgslTypes'; +import type { VecKind, v3f, v3i, v3u } from '../data/wgslTypes'; import { inGPUMode } from '../gpuMode'; type vBase = { kind: VecKind };