Define basic data structure
This commit is contained in:
		@@ -2,7 +2,11 @@
 | 
			
		||||
	"name": "oktaeder",
 | 
			
		||||
	"version": "0.1.0",
 | 
			
		||||
	"description": "3D rendering library for WebGPU",
 | 
			
		||||
	"keywords": ["3d", "gltf", "wegbpu"],
 | 
			
		||||
	"keywords": [
 | 
			
		||||
		"3d",
 | 
			
		||||
		"gltf",
 | 
			
		||||
		"wegbpu"
 | 
			
		||||
	],
 | 
			
		||||
	"homepage": "https://github.com/iszn11/oktaeder",
 | 
			
		||||
	"bugs": {
 | 
			
		||||
		"url": "https://github.com/iszn11/oktaeder/issues"
 | 
			
		||||
@@ -20,6 +24,7 @@
 | 
			
		||||
		"tslib": "^2.6.1"
 | 
			
		||||
	},
 | 
			
		||||
	"devDependencies": {
 | 
			
		||||
		"@webgpu/types": "^0.1.34",
 | 
			
		||||
		"typescript": "5.1.6"
 | 
			
		||||
	},
 | 
			
		||||
	"exports": {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										7
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							@@ -10,12 +10,19 @@ dependencies:
 | 
			
		||||
    version: 2.6.1
 | 
			
		||||
 | 
			
		||||
devDependencies:
 | 
			
		||||
  '@webgpu/types':
 | 
			
		||||
    specifier: ^0.1.34
 | 
			
		||||
    version: 0.1.34
 | 
			
		||||
  typescript:
 | 
			
		||||
    specifier: 5.1.6
 | 
			
		||||
    version: 5.1.6
 | 
			
		||||
 | 
			
		||||
packages:
 | 
			
		||||
 | 
			
		||||
  /@webgpu/types@0.1.34:
 | 
			
		||||
    resolution: {integrity: sha512-9mXtH+CC8q+Ku7Z+1XazNIte81FvfdXwR2lLRO7Ykzjd/hh1J1krJa0gtnkF1kvP11psUmKEPKo7iMTeEcUpNA==}
 | 
			
		||||
    dev: true
 | 
			
		||||
 | 
			
		||||
  /tslib@2.6.1:
 | 
			
		||||
    resolution: {integrity: sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==}
 | 
			
		||||
    dev: false
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										115
									
								
								src/Camera.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								src/Camera.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,115 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * This Source Code Form is subject to the terms of the Mozilla Public License,
 | 
			
		||||
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
 | 
			
		||||
 * obtain one at http://mozilla.org/MPL/2.0/.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { Node } from "./Node";
 | 
			
		||||
 | 
			
		||||
export type Camera = CameraOrthographic | CameraPerspective;
 | 
			
		||||
 | 
			
		||||
export interface CameraOrthographicProps {
 | 
			
		||||
	readonly name?: string;
 | 
			
		||||
 | 
			
		||||
	readonly verticalSize: number;
 | 
			
		||||
	readonly nearPlane: number;
 | 
			
		||||
	readonly farPlane: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface CameraPerspectiveProps {
 | 
			
		||||
	readonly name?: string;
 | 
			
		||||
 | 
			
		||||
	readonly verticalFovRad: number;
 | 
			
		||||
	readonly nearPlane: number;
 | 
			
		||||
	readonly farPlane: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class CameraOrthographic {
 | 
			
		||||
 | 
			
		||||
	readonly type!: "CameraOrthographic";
 | 
			
		||||
 | 
			
		||||
	_name: string;
 | 
			
		||||
 | 
			
		||||
	_verticalSize: number;
 | 
			
		||||
	_nearPlane: number;
 | 
			
		||||
	_farPlane: number;
 | 
			
		||||
 | 
			
		||||
	/** backreference */
 | 
			
		||||
	_node: Node | undefined;
 | 
			
		||||
 | 
			
		||||
	constructor({
 | 
			
		||||
		name = "",
 | 
			
		||||
		verticalSize,
 | 
			
		||||
		nearPlane,
 | 
			
		||||
		farPlane,
 | 
			
		||||
	}: CameraOrthographicProps) {
 | 
			
		||||
		Object.defineProperty(this, "type", { value: "CameraOrthographic" });
 | 
			
		||||
 | 
			
		||||
		this._name = name;
 | 
			
		||||
 | 
			
		||||
		this._verticalSize = verticalSize;
 | 
			
		||||
		this._nearPlane = nearPlane;
 | 
			
		||||
		this._farPlane = farPlane;
 | 
			
		||||
 | 
			
		||||
		this._node = undefined;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	detach(): Camera {
 | 
			
		||||
		if (this._node === undefined) {
 | 
			
		||||
			return this;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		this._node._camera = undefined;
 | 
			
		||||
		this._node = undefined;
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class CameraPerspective {
 | 
			
		||||
 | 
			
		||||
	readonly type!: "CameraPerspective";
 | 
			
		||||
 | 
			
		||||
	_name: string;
 | 
			
		||||
 | 
			
		||||
	_verticalFovRad: number;
 | 
			
		||||
	_nearPlane: number;
 | 
			
		||||
	_farPlane: number;
 | 
			
		||||
 | 
			
		||||
	/** backreference */
 | 
			
		||||
	_node: Node | undefined;
 | 
			
		||||
 | 
			
		||||
	constructor({
 | 
			
		||||
		name = "",
 | 
			
		||||
		verticalFovRad,
 | 
			
		||||
		nearPlane,
 | 
			
		||||
		farPlane,
 | 
			
		||||
	}: CameraPerspectiveProps) {
 | 
			
		||||
		Object.defineProperty(this, "type", { value: "CameraPerspective" });
 | 
			
		||||
 | 
			
		||||
		this._name = name;
 | 
			
		||||
 | 
			
		||||
		this._verticalFovRad = verticalFovRad;
 | 
			
		||||
		this._nearPlane = nearPlane;
 | 
			
		||||
		this._farPlane = farPlane;
 | 
			
		||||
 | 
			
		||||
		this._node = undefined;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	detach(): Camera {
 | 
			
		||||
		if (this._node === undefined) {
 | 
			
		||||
			return this;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		this._node._camera = undefined;
 | 
			
		||||
		this._node = undefined;
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function isCameraOrthographic(value: unknown): value is CameraOrthographic {
 | 
			
		||||
	return Boolean(value) && (value as CameraOrthographic).type === "CameraOrthographic";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function isCameraPerspective(value: unknown): value is CameraPerspective {
 | 
			
		||||
	return Boolean(value) && (value as CameraPerspective).type === "CameraPerspective";
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										266
									
								
								src/Color.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										266
									
								
								src/Color.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,266 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * This Source Code Form is subject to the terms of the Mozilla Public License,
 | 
			
		||||
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
 | 
			
		||||
 * obtain one at http://mozilla.org/MPL/2.0/.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { Vector3Object } from "./Vector3";
 | 
			
		||||
 | 
			
		||||
/* Named colors
 | 
			
		||||
 * black       #000000   (0, 0, 0, 1)
 | 
			
		||||
 * silver      #C0C0C0   (192 / 255, 192 / 255, 192 / 255, 1)
 | 
			
		||||
 * gray        #808080   (128 / 255, 128 / 255, 128 / 255, 1)
 | 
			
		||||
 * white       #FFFFFF   (1, 1, 1, 1)
 | 
			
		||||
 * maroon      #800000   (128 / 255, 0, 0, 1)
 | 
			
		||||
 * red         #FF0000   (1, 0, 0, 1)
 | 
			
		||||
 * purple      #800080   (128 / 255, 0, 128 / 255, 1)
 | 
			
		||||
 * fuchsia     #FF00FF   (1, 0, 1, 1)
 | 
			
		||||
 * green       #008000   (0, 128 / 255, 0, 1)
 | 
			
		||||
 * lime        #00FF00   (0, 255, 0, 1)
 | 
			
		||||
 * olive       #808000   (128 / 255, 128 / 255, 0, 1)
 | 
			
		||||
 * yellow      #FFFF00   (1, 1, 0, 1)
 | 
			
		||||
 * navy        #000080   (0, 0, 128 / 255, 1)
 | 
			
		||||
 * blue        #0000FF   (0, 0, 1, 1)
 | 
			
		||||
 * teal        #008080   (0, 128 / 255, 128 / 255, 1)
 | 
			
		||||
 * aqua        #00FFFF   (0, 1, 1, 1)
 | 
			
		||||
 * orange      #FFA500   (1, 165 / 255, 0, 1)
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
export type ColorName =
 | 
			
		||||
	| "black"
 | 
			
		||||
	| "silver"
 | 
			
		||||
	| "gray"
 | 
			
		||||
	| "white"
 | 
			
		||||
	| "maroon"
 | 
			
		||||
	| "red"
 | 
			
		||||
	| "purple"
 | 
			
		||||
	| "fuchsia"
 | 
			
		||||
	| "green"
 | 
			
		||||
	| "lime"
 | 
			
		||||
	| "olive"
 | 
			
		||||
	| "yellow"
 | 
			
		||||
	| "navy"
 | 
			
		||||
	| "blue"
 | 
			
		||||
	| "teal"
 | 
			
		||||
	| "aqua"
 | 
			
		||||
	| "orange"
 | 
			
		||||
	;
 | 
			
		||||
 | 
			
		||||
export interface ColorObject {
 | 
			
		||||
	readonly r: number;
 | 
			
		||||
	readonly g: number;
 | 
			
		||||
	readonly b: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type ColorTuple = readonly [r: number, g: number, b: number];
 | 
			
		||||
 | 
			
		||||
export class Color {
 | 
			
		||||
 | 
			
		||||
	readonly type!: "Color";
 | 
			
		||||
 | 
			
		||||
	r: number;
 | 
			
		||||
	g: number;
 | 
			
		||||
	b: number;
 | 
			
		||||
 | 
			
		||||
	constructor(r: number, g: number, b: number) {
 | 
			
		||||
		Object.defineProperty(this, "type", { value: "Color" });
 | 
			
		||||
 | 
			
		||||
		this.r = r;
 | 
			
		||||
		this.g = g;
 | 
			
		||||
		this.b = b;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static fromObject(object: ColorObject): Color {
 | 
			
		||||
		return new Color(object.r, object.g, object.b);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static fromTuple(tuple: ColorTuple): Color {
 | 
			
		||||
		return new Color(...tuple);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static fromName(name: ColorName): Color {
 | 
			
		||||
		switch (name) {
 | 
			
		||||
			case "black": return new Color(0, 0, 0);
 | 
			
		||||
			case "silver": return new Color(192 / 255, 192 / 255, 192 / 255);
 | 
			
		||||
			case "gray": return new Color(128 / 255, 128 / 255, 128 / 255);
 | 
			
		||||
			case "white": return new Color(1, 1, 1);
 | 
			
		||||
			case "maroon": return new Color(128 / 255, 0, 0);
 | 
			
		||||
			case "red": return new Color(1, 0, 0);
 | 
			
		||||
			case "purple": return new Color(128 / 255, 0, 128 / 255);
 | 
			
		||||
			case "fuchsia": return new Color(1, 0, 1);
 | 
			
		||||
			case "green": return new Color(0, 128 / 255, 0);
 | 
			
		||||
			case "lime": return new Color(0, 255, 0);
 | 
			
		||||
			case "olive": return new Color(128 / 255, 128 / 255, 0);
 | 
			
		||||
			case "yellow": return new Color(1, 1, 0);
 | 
			
		||||
			case "navy": return new Color(0, 0, 128 / 255);
 | 
			
		||||
			case "blue": return new Color(0, 0, 1);
 | 
			
		||||
			case "teal": return new Color(0, 128 / 255, 128 / 255);
 | 
			
		||||
			case "aqua": return new Color(0, 1, 1);
 | 
			
		||||
			case "orange": return new Color(1, 165 / 255, 0);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static fromVector3(vector: Vector3Object): Color {
 | 
			
		||||
		return new Color(vector.x, vector.y, vector.z);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static white(): Color {
 | 
			
		||||
		return new Color(1, 1, 1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static black(): Color {
 | 
			
		||||
		return new Color(0, 0, 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	set(r: number, g: number, b: number): Color {
 | 
			
		||||
		this.r = r;
 | 
			
		||||
		this.g = g;
 | 
			
		||||
		this.b = b;
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setObject(object: ColorObject): Color {
 | 
			
		||||
		this.r = object.r;
 | 
			
		||||
		this.g = object.g;
 | 
			
		||||
		this.b = object.b;
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setTuple(tuple: ColorTuple): Color {
 | 
			
		||||
		this.r = tuple[0];
 | 
			
		||||
		this.g = tuple[1];
 | 
			
		||||
		this.b = tuple[2];
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setName(name: ColorName): Color {
 | 
			
		||||
		switch (name) {
 | 
			
		||||
			case "black":
 | 
			
		||||
				this.r = 0;
 | 
			
		||||
				this.g = 0;
 | 
			
		||||
				this.b = 0;
 | 
			
		||||
				break;
 | 
			
		||||
			case "silver":
 | 
			
		||||
				this.r = 192 / 255;
 | 
			
		||||
				this.g = 192 / 255;
 | 
			
		||||
				this.b = 192 / 255;
 | 
			
		||||
				break;
 | 
			
		||||
			case "gray":
 | 
			
		||||
				this.r = 128 / 255;
 | 
			
		||||
				this.g = 128 / 255;
 | 
			
		||||
				this.b = 128 / 255;
 | 
			
		||||
				break;
 | 
			
		||||
			case "white":
 | 
			
		||||
				this.r = 1;
 | 
			
		||||
				this.g = 1;
 | 
			
		||||
				this.b = 1;
 | 
			
		||||
				break;
 | 
			
		||||
			case "maroon":
 | 
			
		||||
				this.r = 128 / 255;
 | 
			
		||||
				this.g = 0;
 | 
			
		||||
				this.b = 0;
 | 
			
		||||
				break;
 | 
			
		||||
			case "red":
 | 
			
		||||
				this.r = 1;
 | 
			
		||||
				this.g = 0;
 | 
			
		||||
				this.b = 0;
 | 
			
		||||
				break;
 | 
			
		||||
			case "purple":
 | 
			
		||||
				this.r = 128 / 255;
 | 
			
		||||
				this.g = 0;
 | 
			
		||||
				this.b = 128 / 255;
 | 
			
		||||
				break;
 | 
			
		||||
			case "fuchsia":
 | 
			
		||||
				this.r = 1;
 | 
			
		||||
				this.g = 0;
 | 
			
		||||
				this.b = 1;
 | 
			
		||||
				break;
 | 
			
		||||
			case "green":
 | 
			
		||||
				this.r = 0;
 | 
			
		||||
				this.g = 128 / 255;
 | 
			
		||||
				this.b = 0;
 | 
			
		||||
				break;
 | 
			
		||||
			case "lime":
 | 
			
		||||
				this.r = 0;
 | 
			
		||||
				this.g = 255;
 | 
			
		||||
				this.b = 0;
 | 
			
		||||
				break;
 | 
			
		||||
			case "olive":
 | 
			
		||||
				this.r = 128 / 255;
 | 
			
		||||
				this.g = 128 / 255;
 | 
			
		||||
				this.b = 0;
 | 
			
		||||
				break;
 | 
			
		||||
			case "yellow":
 | 
			
		||||
				this.r = 1;
 | 
			
		||||
				this.g = 1;
 | 
			
		||||
				this.b = 0;
 | 
			
		||||
				break;
 | 
			
		||||
			case "navy":
 | 
			
		||||
				this.r = 0;
 | 
			
		||||
				this.g = 0;
 | 
			
		||||
				this.b = 128 / 255;
 | 
			
		||||
				break;
 | 
			
		||||
			case "blue":
 | 
			
		||||
				this.r = 0;
 | 
			
		||||
				this.g = 0;
 | 
			
		||||
				this.b = 1;
 | 
			
		||||
				break;
 | 
			
		||||
			case "teal":
 | 
			
		||||
				this.r = 0;
 | 
			
		||||
				this.g = 128 / 255;
 | 
			
		||||
				this.b = 128 / 255;
 | 
			
		||||
				break;
 | 
			
		||||
			case "aqua":
 | 
			
		||||
				this.r = 0;
 | 
			
		||||
				this.g = 1;
 | 
			
		||||
				this.b = 1;
 | 
			
		||||
				break;
 | 
			
		||||
			case "orange":
 | 
			
		||||
				this.r = 1;
 | 
			
		||||
				this.g = 165 / 255;
 | 
			
		||||
				this.b = 0;
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setVector3(vector: Vector3Object): Color {
 | 
			
		||||
		this.r = vector.x;
 | 
			
		||||
		this.g = vector.y;
 | 
			
		||||
		this.b = vector.z;
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setWhite(): Color {
 | 
			
		||||
		this.r = 1;
 | 
			
		||||
		this.g = 1;
 | 
			
		||||
		this.b = 1;
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setBlack(): Color {
 | 
			
		||||
		this.r = 0;
 | 
			
		||||
		this.g = 0;
 | 
			
		||||
		this.b = 0;
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setR(r: number): Color {
 | 
			
		||||
		this.r = r;
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setG(g: number): Color {
 | 
			
		||||
		this.g = g;
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setB(b: number): Color {
 | 
			
		||||
		this.b = b;
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function isColor(value: unknown): value is Color {
 | 
			
		||||
	return Boolean(value) && (value as Color).type === "Color";
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										49
									
								
								src/IndexBuffer.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/IndexBuffer.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * This Source Code Form is subject to the terms of the Mozilla Public License,
 | 
			
		||||
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
 | 
			
		||||
 * obtain one at http://mozilla.org/MPL/2.0/.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
export const INDEX_SIZE = 2;
 | 
			
		||||
 | 
			
		||||
export class IndexBuffer {
 | 
			
		||||
 | 
			
		||||
	readonly type!: "IndexBuffer";
 | 
			
		||||
 | 
			
		||||
	_device: GPUDevice;
 | 
			
		||||
	_buffer: GPUBuffer;
 | 
			
		||||
 | 
			
		||||
	constructor(device: GPUDevice, indexCount: number) {
 | 
			
		||||
		Object.defineProperty(this, "type", { value: "IndexBuffer" });
 | 
			
		||||
 | 
			
		||||
		this._device = device;
 | 
			
		||||
		this._buffer = device.createBuffer({
 | 
			
		||||
			usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.INDEX,
 | 
			
		||||
			size: indexCount * INDEX_SIZE,
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dispose(): IndexBuffer {
 | 
			
		||||
		this._buffer.destroy();
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	get vertexCount(): number {
 | 
			
		||||
		return this._buffer.size / INDEX_SIZE | 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	writeArray(offset: number, indices: readonly number[]): IndexBuffer {
 | 
			
		||||
		const array = new Uint16Array(indices);
 | 
			
		||||
		this._device.queue.writeBuffer(this._buffer, offset * INDEX_SIZE | 0, array);
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	writeTypedArray(offset: number, indices: Uint16Array): IndexBuffer {
 | 
			
		||||
		this._device.queue.writeBuffer(this._buffer, offset * INDEX_SIZE | 0, indices);
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function isIndexBuffer(value: unknown): value is IndexBuffer {
 | 
			
		||||
	return Boolean(value) && (value as IndexBuffer).type === "IndexBuffer";
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										76
									
								
								src/Material.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								src/Material.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * This Source Code Form is subject to the terms of the Mozilla Public License,
 | 
			
		||||
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
 | 
			
		||||
 * obtain one at http://mozilla.org/MPL/2.0/.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { Color, ColorObject } from "./Color";
 | 
			
		||||
 | 
			
		||||
export interface MaterialProps {
 | 
			
		||||
	name?: string;
 | 
			
		||||
 | 
			
		||||
	baseColor?: ColorObject;
 | 
			
		||||
	metallic?: number;
 | 
			
		||||
	roughness?: number;
 | 
			
		||||
	emissive?: ColorObject;
 | 
			
		||||
	partialCoverage?: number;
 | 
			
		||||
	transmission?: ColorObject;
 | 
			
		||||
	collimation?: number;
 | 
			
		||||
	ior?: number;
 | 
			
		||||
 | 
			
		||||
	doubleSided?: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class Material {
 | 
			
		||||
 | 
			
		||||
	readonly type!: "Material";
 | 
			
		||||
 | 
			
		||||
	_name: string;
 | 
			
		||||
 | 
			
		||||
	_baseColor: Color;
 | 
			
		||||
	_metallic: number;
 | 
			
		||||
	_roughness: number;
 | 
			
		||||
	_emissive: Color;
 | 
			
		||||
	_partialCoverage: number;
 | 
			
		||||
	_transmission: Color;
 | 
			
		||||
	_collimation: number;
 | 
			
		||||
	_ior: number;
 | 
			
		||||
 | 
			
		||||
	_doubleSided: boolean;
 | 
			
		||||
 | 
			
		||||
	constructor({
 | 
			
		||||
		name = "",
 | 
			
		||||
		baseColor,
 | 
			
		||||
		metallic = 1,
 | 
			
		||||
		roughness = 1,
 | 
			
		||||
		emissive,
 | 
			
		||||
		partialCoverage = 1,
 | 
			
		||||
		transmission,
 | 
			
		||||
		collimation = 1,
 | 
			
		||||
		ior = 1.45,
 | 
			
		||||
		doubleSided = false,
 | 
			
		||||
	}: MaterialProps) {
 | 
			
		||||
		Object.defineProperty(this, "type", { value: "Material" });
 | 
			
		||||
 | 
			
		||||
		this._name = name;
 | 
			
		||||
 | 
			
		||||
		this._baseColor = baseColor !== undefined ? Color.fromObject(baseColor) : Color.white();
 | 
			
		||||
		this._metallic = metallic;
 | 
			
		||||
		this._roughness = roughness;
 | 
			
		||||
		this._emissive = emissive !== undefined ? Color.fromObject(emissive) : Color.black();
 | 
			
		||||
		this._partialCoverage = partialCoverage;
 | 
			
		||||
		this._transmission = transmission !== undefined ? Color.fromObject(transmission) : Color.black();
 | 
			
		||||
		this._collimation = collimation;
 | 
			
		||||
		this._ior = ior;
 | 
			
		||||
 | 
			
		||||
		this._doubleSided = doubleSided;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	get isTransparent(): boolean {
 | 
			
		||||
		return this._partialCoverage < 1 || this._transmission.r > 0 || this._transmission.g > 0 || this._transmission.b > 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function isMaterial(value: unknown): value is Material {
 | 
			
		||||
	return Boolean(value) && (value as Material).type === "Material";
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										246
									
								
								src/Matrix4x4.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										246
									
								
								src/Matrix4x4.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,246 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * This Source Code Form is subject to the terms of the Mozilla Public License,
 | 
			
		||||
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
 | 
			
		||||
 * obtain one at http://mozilla.org/MPL/2.0/.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { QuaternionObject } from "./Quaternion";
 | 
			
		||||
import { Vector3Object } from "./Vector3";
 | 
			
		||||
 | 
			
		||||
export interface Matrix4x4Object {
 | 
			
		||||
	readonly ix: number;
 | 
			
		||||
	readonly iy: number;
 | 
			
		||||
	readonly iz: number;
 | 
			
		||||
	readonly iw: number;
 | 
			
		||||
	readonly jx: number;
 | 
			
		||||
	readonly jy: number;
 | 
			
		||||
	readonly jz: number;
 | 
			
		||||
	readonly jw: number;
 | 
			
		||||
	readonly kx: number;
 | 
			
		||||
	readonly ky: number;
 | 
			
		||||
	readonly kz: number;
 | 
			
		||||
	readonly kw: number;
 | 
			
		||||
	readonly tx: number;
 | 
			
		||||
	readonly ty: number;
 | 
			
		||||
	readonly tz: number;
 | 
			
		||||
	readonly tw: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type Matrix4x4Tuple = readonly [
 | 
			
		||||
	ix: number, iy: number, iz: number, iw: number,
 | 
			
		||||
	jx: number, jy: number, jz: number, jw: number,
 | 
			
		||||
	kx: number, ky: number, kz: number, kw: number,
 | 
			
		||||
	tx: number, ty: number, tz: number, tw: number,
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
export class Matrix4x4 {
 | 
			
		||||
 | 
			
		||||
	readonly type!: "Matrix4x4";
 | 
			
		||||
 | 
			
		||||
	ix: number;
 | 
			
		||||
	iy: number;
 | 
			
		||||
	iz: number;
 | 
			
		||||
	iw: number;
 | 
			
		||||
	jx: number;
 | 
			
		||||
	jy: number;
 | 
			
		||||
	jz: number;
 | 
			
		||||
	jw: number;
 | 
			
		||||
	kx: number;
 | 
			
		||||
	ky: number;
 | 
			
		||||
	kz: number;
 | 
			
		||||
	kw: number;
 | 
			
		||||
	tx: number;
 | 
			
		||||
	ty: number;
 | 
			
		||||
	tz: number;
 | 
			
		||||
	tw: number;
 | 
			
		||||
 | 
			
		||||
	constructor(
 | 
			
		||||
		ix: number, iy: number, iz: number, iw: number,
 | 
			
		||||
		jx: number, jy: number, jz: number, jw: number,
 | 
			
		||||
		kx: number, ky: number, kz: number, kw: number,
 | 
			
		||||
		tx: number, ty: number, tz: number, tw: number
 | 
			
		||||
	) {
 | 
			
		||||
		Object.defineProperty(this, "type", { value: "Matrix4x4" });
 | 
			
		||||
 | 
			
		||||
		this.ix = ix;
 | 
			
		||||
		this.iy = iy;
 | 
			
		||||
		this.iz = iz;
 | 
			
		||||
		this.iw = iw;
 | 
			
		||||
		this.jx = jx;
 | 
			
		||||
		this.jy = jy;
 | 
			
		||||
		this.jz = jz;
 | 
			
		||||
		this.jw = jw;
 | 
			
		||||
		this.kx = kx;
 | 
			
		||||
		this.ky = ky;
 | 
			
		||||
		this.kz = kz;
 | 
			
		||||
		this.kw = kw;
 | 
			
		||||
		this.tx = tx;
 | 
			
		||||
		this.ty = ty;
 | 
			
		||||
		this.tz = tz;
 | 
			
		||||
		this.tw = tw;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static fromObject(object: Matrix4x4Object): Matrix4x4 {
 | 
			
		||||
		return new Matrix4x4(
 | 
			
		||||
			object.ix, object.iy, object.iz, object.iw,
 | 
			
		||||
			object.jx, object.jy, object.jz, object.jw,
 | 
			
		||||
			object.kx, object.ky, object.kz, object.kw,
 | 
			
		||||
			object.tx, object.ty, object.tz, object.tw,
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static fromTuple(tuple: Matrix4x4Tuple): Matrix4x4 {
 | 
			
		||||
		return new Matrix4x4(...tuple);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static fromTranslation(translation: Vector3Object): Matrix4x4 {
 | 
			
		||||
		return new Matrix4x4(
 | 
			
		||||
			1, 0, 0, 0,
 | 
			
		||||
			0, 1, 0, 0,
 | 
			
		||||
			0, 0, 1, 0,
 | 
			
		||||
			translation.x, translation.y, translation.z, 1,
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static fromQuaternion(quaternion: QuaternionObject): Matrix4x4 {
 | 
			
		||||
		const xx = quaternion.x * quaternion.x;
 | 
			
		||||
		const xy = quaternion.x * quaternion.y;
 | 
			
		||||
		const xz = quaternion.x * quaternion.z;
 | 
			
		||||
		const xw = quaternion.x * quaternion.w;
 | 
			
		||||
		const yy = quaternion.y * quaternion.y;
 | 
			
		||||
		const yz = quaternion.y * quaternion.z;
 | 
			
		||||
		const yw = quaternion.y * quaternion.w;
 | 
			
		||||
		const zz = quaternion.z * quaternion.z;
 | 
			
		||||
		const zw = quaternion.z * quaternion.w;
 | 
			
		||||
 | 
			
		||||
		return new Matrix4x4(
 | 
			
		||||
			1 - 2 * (yy + zz), 2 * (xy + zw), 2 * (xz - yw), 0,
 | 
			
		||||
			2 * (xy - zw), 1 - 2 * (xx + zz), 2 * (yz + xw), 0,
 | 
			
		||||
			2 * (xz + yw), 2 * (yz - xw), 1 - 2 * (xx + yy), 0,
 | 
			
		||||
			0, 0, 0, 1,
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static fromScale(scale: Vector3Object): Matrix4x4 {
 | 
			
		||||
		return new Matrix4x4(
 | 
			
		||||
			scale.x, 0, 0, 0,
 | 
			
		||||
			0, scale.y, 0, 0,
 | 
			
		||||
			0, 0, scale.z, 0,
 | 
			
		||||
			0, 0, 0, 1
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setObject(object: Matrix4x4Object): Matrix4x4 {
 | 
			
		||||
		this.ix = object.ix;
 | 
			
		||||
		this.iy = object.iy;
 | 
			
		||||
		this.iz = object.iz;
 | 
			
		||||
		this.iw = object.iw;
 | 
			
		||||
		this.jx = object.jx;
 | 
			
		||||
		this.jy = object.jy;
 | 
			
		||||
		this.jz = object.jz;
 | 
			
		||||
		this.jw = object.jw;
 | 
			
		||||
		this.kx = object.kx;
 | 
			
		||||
		this.ky = object.ky;
 | 
			
		||||
		this.kz = object.kz;
 | 
			
		||||
		this.kw = object.kw;
 | 
			
		||||
		this.tx = object.tx;
 | 
			
		||||
		this.ty = object.ty;
 | 
			
		||||
		this.tz = object.tz;
 | 
			
		||||
		this.tw = object.tw;
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setTuple(tuple: Matrix4x4Tuple): Matrix4x4 {
 | 
			
		||||
		this.ix = tuple[0];
 | 
			
		||||
		this.iy = tuple[1];
 | 
			
		||||
		this.iz = tuple[2];
 | 
			
		||||
		this.iw = tuple[3];
 | 
			
		||||
		this.jx = tuple[4];
 | 
			
		||||
		this.jy = tuple[5];
 | 
			
		||||
		this.jz = tuple[6];
 | 
			
		||||
		this.jw = tuple[7];
 | 
			
		||||
		this.kx = tuple[8];
 | 
			
		||||
		this.ky = tuple[9];
 | 
			
		||||
		this.kz = tuple[10];
 | 
			
		||||
		this.kw = tuple[11];
 | 
			
		||||
		this.tx = tuple[12];
 | 
			
		||||
		this.ty = tuple[13];
 | 
			
		||||
		this.tz = tuple[14];
 | 
			
		||||
		this.tw = tuple[15];
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setTranslation(translation: Vector3Object): Matrix4x4 {
 | 
			
		||||
		this.ix = 1;
 | 
			
		||||
		this.iy = 0;
 | 
			
		||||
		this.iz = 0;
 | 
			
		||||
		this.iw = 0;
 | 
			
		||||
		this.jx = 0;
 | 
			
		||||
		this.jy = 1;
 | 
			
		||||
		this.jz = 0;
 | 
			
		||||
		this.jw = 0;
 | 
			
		||||
		this.kx = 0;
 | 
			
		||||
		this.ky = 0;
 | 
			
		||||
		this.kz = 1;
 | 
			
		||||
		this.kw = 0;
 | 
			
		||||
		this.tx = translation.x;
 | 
			
		||||
		this.ty = translation.y;
 | 
			
		||||
		this.tz = translation.z;
 | 
			
		||||
		this.tw = 1;
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setQuaternion(quaternion: QuaternionObject): Matrix4x4 {
 | 
			
		||||
		const xx = quaternion.x * quaternion.x;
 | 
			
		||||
		const xy = quaternion.x * quaternion.y;
 | 
			
		||||
		const xz = quaternion.x * quaternion.z;
 | 
			
		||||
		const xw = quaternion.x * quaternion.w;
 | 
			
		||||
		const yy = quaternion.y * quaternion.y;
 | 
			
		||||
		const yz = quaternion.y * quaternion.z;
 | 
			
		||||
		const yw = quaternion.y * quaternion.w;
 | 
			
		||||
		const zz = quaternion.z * quaternion.z;
 | 
			
		||||
		const zw = quaternion.z * quaternion.w;
 | 
			
		||||
 | 
			
		||||
		this.ix = 1 - 2 * (yy + zz);
 | 
			
		||||
		this.iy = 2 * (xy + zw);
 | 
			
		||||
		this.iz = 2 * (xz - yw);
 | 
			
		||||
		this.iw = 0;
 | 
			
		||||
		this.jx = 2 * (xy - zw);
 | 
			
		||||
		this.jy = 1 - 2 * (xx + zz);
 | 
			
		||||
		this.jz = 2 * (yz + xw);
 | 
			
		||||
		this.jw = 0;
 | 
			
		||||
		this.kx = 2 * (xz + yw);
 | 
			
		||||
		this.ky = 2 * (yz - xw);
 | 
			
		||||
		this.kz = 1 - 2 * (xx + yy);
 | 
			
		||||
		this.kw = 0;
 | 
			
		||||
		this.tx = 0;
 | 
			
		||||
		this.ty = 0;
 | 
			
		||||
		this.tz = 0;
 | 
			
		||||
		this.tw = 1;
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setScale(scale: Vector3Object): Matrix4x4 {
 | 
			
		||||
		this.ix = scale.x;
 | 
			
		||||
		this.iy = 0;
 | 
			
		||||
		this.iz = 0;
 | 
			
		||||
		this.iw = 0;
 | 
			
		||||
		this.jx = 0;
 | 
			
		||||
		this.jy = scale.y;
 | 
			
		||||
		this.jz = 0;
 | 
			
		||||
		this.jw = 0;
 | 
			
		||||
		this.kx = 0;
 | 
			
		||||
		this.ky = 0;
 | 
			
		||||
		this.kz = scale.z;
 | 
			
		||||
		this.kw = 0;
 | 
			
		||||
		this.tx = 0;
 | 
			
		||||
		this.ty = 0;
 | 
			
		||||
		this.tz = 0;
 | 
			
		||||
		this.tw = 1;
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function isMatrix4x4(value: unknown): value is Matrix4x4 {
 | 
			
		||||
	return Boolean(value) && (value as Matrix4x4).type === "Matrix4x4";
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								src/Mesh.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/Mesh.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * This Source Code Form is subject to the terms of the Mozilla Public License,
 | 
			
		||||
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
 | 
			
		||||
 * obtain one at http://mozilla.org/MPL/2.0/.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { IndexBuffer } from "./IndexBuffer";
 | 
			
		||||
import { VertexBuffer } from "./VertexBuffer";
 | 
			
		||||
 | 
			
		||||
export interface MeshProps {
 | 
			
		||||
	readonly name?: string;
 | 
			
		||||
 | 
			
		||||
	readonly vertexBuffer: VertexBuffer;
 | 
			
		||||
	readonly indexBuffer: IndexBuffer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class Mesh {
 | 
			
		||||
 | 
			
		||||
	readonly type!: "Mesh"
 | 
			
		||||
 | 
			
		||||
	_name: string;
 | 
			
		||||
 | 
			
		||||
	_vertexBuffer: VertexBuffer;
 | 
			
		||||
	_indexBuffer: IndexBuffer;
 | 
			
		||||
 | 
			
		||||
	constructor({
 | 
			
		||||
		name = "",
 | 
			
		||||
		vertexBuffer,
 | 
			
		||||
		indexBuffer,
 | 
			
		||||
	}: MeshProps) {
 | 
			
		||||
		Object.defineProperty(this, "type", { value: "Mesh" });
 | 
			
		||||
 | 
			
		||||
		this._name = name;
 | 
			
		||||
 | 
			
		||||
		this._vertexBuffer = vertexBuffer;
 | 
			
		||||
		this._indexBuffer = indexBuffer
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function isMesh(value: unknown): value is Mesh {
 | 
			
		||||
	return Boolean(value) && (value as Mesh).type === "Mesh";
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										84
									
								
								src/Node.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								src/Node.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * This Source Code Form is subject to the terms of the Mozilla Public License,
 | 
			
		||||
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
 | 
			
		||||
 * obtain one at http://mozilla.org/MPL/2.0/.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { Camera } from "./Camera";
 | 
			
		||||
import { Mesh } from "./Mesh";
 | 
			
		||||
import { Quaternion, QuaternionObject } from "./Quaternion";
 | 
			
		||||
import { Vector3, Vector3Object } from "./Vector3";
 | 
			
		||||
 | 
			
		||||
export interface NodeProps {
 | 
			
		||||
	readonly name?: string;
 | 
			
		||||
 | 
			
		||||
	readonly translation?: Vector3Object;
 | 
			
		||||
	readonly rotation?: QuaternionObject;
 | 
			
		||||
	readonly scale?: Vector3Object;
 | 
			
		||||
 | 
			
		||||
	readonly camera?: Camera;
 | 
			
		||||
	readonly mesh?: Mesh;
 | 
			
		||||
 | 
			
		||||
	readonly children?: Node[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class Node {
 | 
			
		||||
 | 
			
		||||
	readonly type!: "Node";
 | 
			
		||||
 | 
			
		||||
	_name: string;
 | 
			
		||||
 | 
			
		||||
	_translation: Vector3;
 | 
			
		||||
	_rotation: Quaternion;
 | 
			
		||||
	_scale: Vector3;
 | 
			
		||||
 | 
			
		||||
	/** unique */
 | 
			
		||||
	_camera: Camera | undefined;
 | 
			
		||||
	/** shared */
 | 
			
		||||
	_mesh: Mesh | undefined;
 | 
			
		||||
 | 
			
		||||
	/** unique */
 | 
			
		||||
	_children: Node[];
 | 
			
		||||
 | 
			
		||||
	/** backreference */
 | 
			
		||||
	_parent: Node | undefined;
 | 
			
		||||
 | 
			
		||||
	constructor({
 | 
			
		||||
		name = "",
 | 
			
		||||
		translation,
 | 
			
		||||
		rotation,
 | 
			
		||||
		scale,
 | 
			
		||||
		camera,
 | 
			
		||||
		mesh,
 | 
			
		||||
		children = [],
 | 
			
		||||
	}: NodeProps) {
 | 
			
		||||
		Object.defineProperty(this, "type", { value: "Node" });
 | 
			
		||||
 | 
			
		||||
		this._name = name;
 | 
			
		||||
 | 
			
		||||
		this._translation = translation !== undefined ? Vector3.fromObject(translation) : Vector3.zero();
 | 
			
		||||
		this._rotation = rotation !== undefined ? Quaternion.fromObject(rotation) : Quaternion.identity();
 | 
			
		||||
		this._scale = scale !== undefined ? Vector3.fromObject(scale) : Vector3.one();
 | 
			
		||||
 | 
			
		||||
		this._camera = camera;
 | 
			
		||||
		this._mesh = mesh;
 | 
			
		||||
 | 
			
		||||
		this._children = children;
 | 
			
		||||
 | 
			
		||||
		this._parent = undefined;
 | 
			
		||||
 | 
			
		||||
		if (this._camera !== undefined) {
 | 
			
		||||
			this._camera._node = this;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (this._children !== undefined) {
 | 
			
		||||
			for (const child of this._children) {
 | 
			
		||||
				child._parent = this;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function isNode(value: unknown): value is Node {
 | 
			
		||||
	return Boolean(value) && (value as Node).type === "Node";
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										73
									
								
								src/Quaternion.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								src/Quaternion.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * This Source Code Form is subject to the terms of the Mozilla Public License,
 | 
			
		||||
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
 | 
			
		||||
 * obtain one at http://mozilla.org/MPL/2.0/.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
export interface QuaternionObject {
 | 
			
		||||
	readonly x: number;
 | 
			
		||||
	readonly y: number;
 | 
			
		||||
	readonly z: number;
 | 
			
		||||
	readonly w: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type QuaternionTuple = readonly [x: number, y: number, z: number, w: number];
 | 
			
		||||
 | 
			
		||||
export class Quaternion {
 | 
			
		||||
 | 
			
		||||
	readonly type!: "Quaternion";
 | 
			
		||||
 | 
			
		||||
	x: number;
 | 
			
		||||
	y: number;
 | 
			
		||||
	z: number;
 | 
			
		||||
	w: number;
 | 
			
		||||
 | 
			
		||||
	constructor(x: number, y: number, z: number, w: number) {
 | 
			
		||||
		Object.defineProperty(this, "type", { value: "Quaternion" });
 | 
			
		||||
 | 
			
		||||
		this.x = x;
 | 
			
		||||
		this.y = y;
 | 
			
		||||
		this.z = z;
 | 
			
		||||
		this.w = w;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static fromObject(object: QuaternionObject): Quaternion {
 | 
			
		||||
		return new Quaternion(object.x, object.y, object.z, object.w);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static fromTuple(tuple: QuaternionTuple): Quaternion {
 | 
			
		||||
		return new Quaternion(...tuple);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static identity(): Quaternion {
 | 
			
		||||
		return new Quaternion(0, 0, 0, 1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setObject(object: QuaternionObject): Quaternion {
 | 
			
		||||
		this.x = object.x;
 | 
			
		||||
		this.y = object.y;
 | 
			
		||||
		this.z = object.z;
 | 
			
		||||
		this.w = object.w;
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setTuple(tuple: QuaternionTuple): Quaternion {
 | 
			
		||||
		this.x = tuple[0];
 | 
			
		||||
		this.y = tuple[1];
 | 
			
		||||
		this.z = tuple[2];
 | 
			
		||||
		this.w = tuple[3];
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setIdentity(): Quaternion {
 | 
			
		||||
		this.x = 0;
 | 
			
		||||
		this.y = 0;
 | 
			
		||||
		this.z = 0;
 | 
			
		||||
		this.w = 1;
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function isQuaternion(value: unknown): value is Quaternion {
 | 
			
		||||
	return Boolean(value) && (value as Quaternion).type === "Quaternion";
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										37
									
								
								src/Scene.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/Scene.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * This Source Code Form is subject to the terms of the Mozilla Public License,
 | 
			
		||||
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
 | 
			
		||||
 * obtain one at http://mozilla.org/MPL/2.0/.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { Node } from "./Node";
 | 
			
		||||
 | 
			
		||||
export interface SceneProps {
 | 
			
		||||
	readonly name?: string;
 | 
			
		||||
 | 
			
		||||
	readonly nodes?: Node[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class Scene {
 | 
			
		||||
 | 
			
		||||
	readonly type!: "Scene";
 | 
			
		||||
 | 
			
		||||
	_name: string | undefined;
 | 
			
		||||
 | 
			
		||||
	_nodes: Node[];
 | 
			
		||||
 | 
			
		||||
	constructor({
 | 
			
		||||
		name = "",
 | 
			
		||||
		nodes = [],
 | 
			
		||||
	}: SceneProps) {
 | 
			
		||||
		Object.defineProperty(this, "type", { value: "Scene" });
 | 
			
		||||
 | 
			
		||||
		this._name = name;
 | 
			
		||||
 | 
			
		||||
		this._nodes = nodes;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function isScene(value: unknown): value is Scene {
 | 
			
		||||
	return Boolean(value) && (value as Scene).type === "Scene";
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										72
									
								
								src/Texture2D.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								src/Texture2D.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,72 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * This Source Code Form is subject to the terms of the Mozilla Public License,
 | 
			
		||||
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
 | 
			
		||||
 * obtain one at http://mozilla.org/MPL/2.0/.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
export interface Texture2DProps {
 | 
			
		||||
	name?: string;
 | 
			
		||||
	device: GPUDevice;
 | 
			
		||||
	width: number;
 | 
			
		||||
	height: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class Texture2D {
 | 
			
		||||
 | 
			
		||||
	readonly type!: "Texture2D";
 | 
			
		||||
 | 
			
		||||
	_name: string;
 | 
			
		||||
 | 
			
		||||
	_device: GPUDevice;
 | 
			
		||||
	_texture: GPUTexture;
 | 
			
		||||
	_textureView: GPUTextureView;
 | 
			
		||||
 | 
			
		||||
	constructor({
 | 
			
		||||
		name = "",
 | 
			
		||||
		device,
 | 
			
		||||
		width,
 | 
			
		||||
		height,
 | 
			
		||||
	}: Texture2DProps) {
 | 
			
		||||
		Object.defineProperty(this, "type", { value: "Texture2D" });
 | 
			
		||||
 | 
			
		||||
		this._name = name;
 | 
			
		||||
 | 
			
		||||
		this._device = device;
 | 
			
		||||
		this._texture = device.createTexture({
 | 
			
		||||
			usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,
 | 
			
		||||
			size: { width, height },
 | 
			
		||||
			format: "rgba8unorm",
 | 
			
		||||
		});
 | 
			
		||||
		this._textureView = this._texture.createView({
 | 
			
		||||
			format: "rgba8unorm",
 | 
			
		||||
			dimension: "2d",
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dispose(): Texture2D {
 | 
			
		||||
		this._texture.destroy();
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	get width(): number {
 | 
			
		||||
		return this._texture.width;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	get height(): number {
 | 
			
		||||
		return this._texture.height;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	writeTypedArray(data: Uint8Array): Texture2D {
 | 
			
		||||
		this._device.queue.writeTexture(
 | 
			
		||||
			{ texture: this._texture },
 | 
			
		||||
			data,
 | 
			
		||||
			{ bytesPerRow: 4 * this._texture.width },
 | 
			
		||||
			{ width: this._texture.width, height: this._texture.height },
 | 
			
		||||
		);
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function isTexture2D(value: unknown): value is Texture2D {
 | 
			
		||||
	return Boolean(value) && (value as Texture2D).type === "Texture2D";
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										100
									
								
								src/Vector3.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								src/Vector3.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * This Source Code Form is subject to the terms of the Mozilla Public License,
 | 
			
		||||
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
 | 
			
		||||
 * obtain one at http://mozilla.org/MPL/2.0/.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
export interface Vector3Object {
 | 
			
		||||
	readonly x: number;
 | 
			
		||||
	readonly y: number;
 | 
			
		||||
	readonly z: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type Vector3Tuple = readonly [x: number, y: number, z: number];
 | 
			
		||||
 | 
			
		||||
export class Vector3 {
 | 
			
		||||
 | 
			
		||||
	readonly type!: "Vector3";
 | 
			
		||||
 | 
			
		||||
	x: number;
 | 
			
		||||
	y: number;
 | 
			
		||||
	z: number;
 | 
			
		||||
 | 
			
		||||
	constructor(x: number, y: number, z: number) {
 | 
			
		||||
		Object.defineProperty(this, "type", { value: "Vector3" });
 | 
			
		||||
 | 
			
		||||
		this.x = x;
 | 
			
		||||
		this.y = y;
 | 
			
		||||
		this.z = z;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static fromObject(object: Vector3Object): Vector3 {
 | 
			
		||||
		return new Vector3(object.x, object.y, object.z);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static fromTuple(tuple: Vector3Tuple): Vector3 {
 | 
			
		||||
		return new Vector3(...tuple);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static zero(): Vector3 {
 | 
			
		||||
		return new Vector3(0, 0, 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static one(): Vector3 {
 | 
			
		||||
		return new Vector3(1, 1, 1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	set(x: number, y: number, z: number): Vector3 {
 | 
			
		||||
		this.x = x;
 | 
			
		||||
		this.y = y;
 | 
			
		||||
		this.z = z;
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setObject(object: Vector3Object): Vector3 {
 | 
			
		||||
		this.x = object.x;
 | 
			
		||||
		this.y = object.y;
 | 
			
		||||
		this.z = object.z;
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setTuple(tuple: Vector3Tuple): Vector3 {
 | 
			
		||||
		this.x = tuple[0];
 | 
			
		||||
		this.y = tuple[1];
 | 
			
		||||
		this.z = tuple[2];
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setZero(): Vector3 {
 | 
			
		||||
		this.x = 0;
 | 
			
		||||
		this.y = 0;
 | 
			
		||||
		this.z = 0;
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setOne(): Vector3 {
 | 
			
		||||
		this.x = 1;
 | 
			
		||||
		this.y = 1;
 | 
			
		||||
		this.z = 1;
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setX(x: number): Vector3 {
 | 
			
		||||
		this.x = x;
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setY(y: number): Vector3 {
 | 
			
		||||
		this.y = y;
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setZ(z: number): Vector3 {
 | 
			
		||||
		this.z = z;
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function isVector3(value: unknown): value is Vector3 {
 | 
			
		||||
	return Boolean(value) && (value as Vector3).type === "Vector3";
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										57
									
								
								src/VertexBuffer.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/VertexBuffer.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * This Source Code Form is subject to the terms of the Mozilla Public License,
 | 
			
		||||
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
 | 
			
		||||
 * obtain one at http://mozilla.org/MPL/2.0/.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { Vector3Object } from "./Vector3";
 | 
			
		||||
 | 
			
		||||
export const VERTEX_SIZE = 12;
 | 
			
		||||
 | 
			
		||||
export class VertexBuffer {
 | 
			
		||||
 | 
			
		||||
	readonly type!: "VertexBuffer";
 | 
			
		||||
 | 
			
		||||
	_device: GPUDevice;
 | 
			
		||||
	_buffer: GPUBuffer;
 | 
			
		||||
 | 
			
		||||
	constructor(device: GPUDevice, vertexCount: number) {
 | 
			
		||||
		Object.defineProperty(this, "type", { value: "VertexBuffer" });
 | 
			
		||||
 | 
			
		||||
		this._device = device;
 | 
			
		||||
		this._buffer = device.createBuffer({
 | 
			
		||||
			usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.VERTEX,
 | 
			
		||||
			size: vertexCount * VERTEX_SIZE,
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dispose(): VertexBuffer {
 | 
			
		||||
		this._buffer.destroy();
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	get vertexCount(): number {
 | 
			
		||||
		return this._buffer.size / VERTEX_SIZE | 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	writeArray(offset: number, vertices: readonly Vector3Object[]): VertexBuffer {
 | 
			
		||||
		const array = new Float32Array(vertices.length * 3);
 | 
			
		||||
		for (let vi = 0, ptr = 0; vi < vertices.length; ++vi) {
 | 
			
		||||
			const vertex = vertices[vi]!;
 | 
			
		||||
			array[ptr++] = vertex.x;
 | 
			
		||||
			array[ptr++] = vertex.y;
 | 
			
		||||
			array[ptr++] = vertex.z;
 | 
			
		||||
		}
 | 
			
		||||
		this._device.queue.writeBuffer(this._buffer, offset * VERTEX_SIZE | 0, array);
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	writeTypedArray(offset: number, vertices: Float32Array): VertexBuffer {
 | 
			
		||||
		this._device.queue.writeBuffer(this._buffer, offset * VERTEX_SIZE | 0, vertices);
 | 
			
		||||
		return this;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function isVertexBuffer(value: unknown): value is VertexBuffer {
 | 
			
		||||
	return Boolean(value) && (value as VertexBuffer).type === "VertexBuffer";
 | 
			
		||||
}
 | 
			
		||||
@@ -1 +1,18 @@
 | 
			
		||||
export {};
 | 
			
		||||
/*!
 | 
			
		||||
 * This Source Code Form is subject to the terms of the Mozilla Public License,
 | 
			
		||||
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
 | 
			
		||||
 * obtain one at http://mozilla.org/MPL/2.0/.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
export * from "./Camera";
 | 
			
		||||
export * from "./Color";
 | 
			
		||||
export * from "./IndexBuffer";
 | 
			
		||||
export * from "./Material";
 | 
			
		||||
export * from "./Matrix4x4";
 | 
			
		||||
export * from "./Mesh";
 | 
			
		||||
export * from "./Node";
 | 
			
		||||
export * from "./Quaternion";
 | 
			
		||||
export * from "./Scene";
 | 
			
		||||
export * from "./Texture2D";
 | 
			
		||||
export * from "./Vector3";
 | 
			
		||||
export * from "./VertexBuffer";
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,7 @@
 | 
			
		||||
 | 
			
		||||
		"target": "ES2022",
 | 
			
		||||
		"lib": ["ES2022", "DOM"],
 | 
			
		||||
		"typeRoots": ["./node_modules/@webgpu/types"],
 | 
			
		||||
 | 
			
		||||
		"sourceMap": true,
 | 
			
		||||
		"declaration": true,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user