Light classes, gathering materials

This commit is contained in:
2023-08-03 20:05:28 +02:00
parent 7fef3c90d8
commit 94ad52397c
8 changed files with 385 additions and 57 deletions

View File

@@ -6,9 +6,9 @@
import { Node } from ".";
export type Camera = CameraOrthographic | CameraPerspective;
export type Camera = OrthographicCamera | PerspectiveCamera;
export interface CameraOrthographicProps {
export interface OrthographicCameraProps {
readonly name?: string;
readonly verticalSize: number;
@@ -16,7 +16,7 @@ export interface CameraOrthographicProps {
readonly farPlane: number;
}
export interface CameraPerspectiveProps {
export interface PerspectiveCameraProps {
readonly name?: string;
readonly verticalFovRad: number;
@@ -24,9 +24,9 @@ export interface CameraPerspectiveProps {
readonly farPlane: number;
}
export class CameraOrthographic {
export class OrthographicCamera {
readonly type!: "CameraOrthographic";
readonly type!: "OrthographicCamera";
_name: string;
@@ -42,7 +42,7 @@ export class CameraOrthographic {
verticalSize,
nearPlane,
farPlane,
}: CameraOrthographicProps) {
}: OrthographicCameraProps) {
this._name = name;
this._verticalSize = verticalSize;
@@ -64,7 +64,7 @@ export class CameraOrthographic {
set farPlane(value: number) { this._farPlane = value; }
get farPlane(): number { return this._farPlane; }
attach(node: Node): CameraOrthographic {
attach(node: Node): OrthographicCamera {
if (this._node !== null) {
this._node._camera = null;
}
@@ -78,7 +78,7 @@ export class CameraOrthographic {
return this;
}
detach(): CameraOrthographic {
detach(): OrthographicCamera {
if (this._node === null) {
return this;
}
@@ -89,11 +89,9 @@ export class CameraOrthographic {
}
}
Object.defineProperty(CameraOrthographic.prototype, "type", { value: "CameraOrthographic" });
export class PerspectiveCamera {
export class CameraPerspective {
readonly type!: "CameraPerspective";
readonly type!: "PerspectiveCamera";
_name: string;
@@ -109,7 +107,7 @@ export class CameraPerspective {
verticalFovRad,
nearPlane,
farPlane,
}: CameraPerspectiveProps) {
}: PerspectiveCameraProps) {
this._name = name;
this._verticalFovRad = verticalFovRad;
@@ -128,7 +126,7 @@ export class CameraPerspective {
set farPlane(value: number) { this._farPlane = value; }
get farPlane(): number { return this._farPlane; }
attach(node: Node): CameraPerspective {
attach(node: Node): PerspectiveCamera {
if (this._node !== null) {
this._node._camera = null;
}
@@ -142,7 +140,7 @@ export class CameraPerspective {
return this;
}
detach(): CameraPerspective {
detach(): PerspectiveCamera {
if (this._node === null) {
return this;
}
@@ -153,12 +151,14 @@ export class CameraPerspective {
}
}
Object.defineProperty(CameraPerspective.prototype, "type", { value: "CameraPerspective" });
Object.defineProperty(OrthographicCamera.prototype, "type", { value: "OrthographicCamera" });
export function isCameraOrthographic(value: unknown): value is CameraOrthographic {
return Boolean(value) && (value as CameraOrthographic).type === "CameraOrthographic";
Object.defineProperty(PerspectiveCamera.prototype, "type", { value: "PerspectiveCamera" });
export function isOrthographicCamera(value: unknown): value is OrthographicCamera {
return Boolean(value) && (value as OrthographicCamera).type === "OrthographicCamera";
}
export function isCameraPerspective(value: unknown): value is CameraPerspective {
return Boolean(value) && (value as CameraPerspective).type === "CameraPerspective";
export function isPerspectiveCamera(value: unknown): value is PerspectiveCamera {
return Boolean(value) && (value as PerspectiveCamera).type === "PerspectiveCamera";
}

151
src/data/Light.ts Normal file
View File

@@ -0,0 +1,151 @@
/*!
* 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, Node } from ".";
export type Light = DirectionalLight | PointLight;
export interface DirectionalLightProps {
readonly name?: string;
readonly color: ColorObject;
}
export interface PointLightProps {
readonly name?: string;
readonly color: ColorObject;
}
export class DirectionalLight {
readonly type!: "DirectionalLight";
_name: string;
_color: Color;
/** backreference */
_node: Node | null;
constructor({
name = "",
color,
}: DirectionalLightProps) {
this._name = name;
this._color = Color.fromObject(color);
this._node = null;
}
set name(value: string) { this._name = value; }
get name(): string { return this._name; }
setColor(value: ColorObject): DirectionalLight {
this._color.setObject(value);
return this;
}
getColor(res: Color): Color {
return res.setObject(this._color);
}
attach(node: Node): DirectionalLight {
if (this._node !== null) {
this._node._light = null;
}
if (node._light !== null) {
node._light._node = null;
}
node._light = this;
this._node = node;
return this;
}
detach(): DirectionalLight {
if (this._node === null) {
return this;
}
this._node._light = null;
this._node = null;
return this;
}
}
export class PointLight {
readonly type!: "PointLight";
_name: string;
_color: Color;
/** backreference */
_node: Node | null;
constructor({
name = "",
color,
}: PointLightProps) {
this._name = name;
this._color = Color.fromObject(color);
this._node = null;
}
set name(value: string) { this._name = value; }
get name(): string { return this._name; }
setColor(value: ColorObject): PointLight {
this._color.setObject(value);
return this;
}
getColor(res: Color): Color {
return res.setObject(this._color);
}
attach(node: Node): PointLight {
if (this._node !== null) {
this._node._light = null;
}
if (node._light !== null) {
node._light._node = null;
}
node._light = this;
this._node = node;
return this;
}
detach(): PointLight {
if (this._node === null) {
return this;
}
this._node._light = null;
this._node = null;
return this;
}
}
Object.defineProperty(DirectionalLight.prototype, "type", { value: "DirectionalLight" });
Object.defineProperty(PointLight.prototype, "type", { value: "PointLight" });
export function isDirectionalLight(value: unknown): value is DirectionalLight {
return Boolean(value) && (value as DirectionalLight).type === "DirectionalLight";
}
export function isPointLight(value: unknown): value is PointLight {
return Boolean(value) && (value as PointLight).type === "PointLight";
}

114
src/data/Material.ts Normal file
View File

@@ -0,0 +1,114 @@
/*!
* 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 ".";
import { Texture2D } from "../resources";
export const UNIFORM_BUFFER_SIZE = 64;
export interface MaterialProps {
name?: string;
baseColor?: ColorObject;
partialCoverage?: number;
transmission?: ColorObject;
collimation?: number;
occlusionTextureStrength?: number;
roughness?: number;
metallic?: number;
normalScale?: number;
emissive?: ColorObject;
ior?: number;
baseColorPartialCoverageTexture?: Texture2D | null;
occlusionTexture?: Texture2D | null;
roughnessMetallicTexture?: Texture2D | null;
normalTexture?: Texture2D | null;
emissiveTexture?: Texture2D | null;
transmissionCollimationTexture?: Texture2D | null;
transparent?: boolean;
doubleSided?: boolean;
}
export class Material {
readonly type!: "Material";
_name: string;
_baseColor: Color;
_partialCoverage: number;
_occlusionTextureStrength: number;
_metallic: number;
_roughness: number;
_normalScale: number;
_emissive: Color;
_transmission: Color;
_collimation: number;
_ior: number;
_baseColorPartialCoverageTexture: Texture2D | null;
_occlusionTexture: Texture2D | null;
_roughnessMetallicTexture: Texture2D | null;
_normalTexture: Texture2D | null;
_emissiveTexture: Texture2D | null;
_transmissionCollimationTexture: Texture2D | null;
_transparent: boolean;
_doubleSided: boolean;
constructor({
name = "",
baseColor,
partialCoverage = 1,
occlusionTextureStrength = 1,
metallic = 1,
roughness = 1,
normalScale = 1,
emissive,
transmission,
collimation = 1,
ior = 1.45,
baseColorPartialCoverageTexture = null,
occlusionTexture = null,
roughnessMetallicTexture = null,
normalTexture = null,
emissiveTexture = null,
transmissionCollimationTexture = null,
transparent = false,
doubleSided = false,
}: MaterialProps) {
this._name = name;
this._baseColor = baseColor !== undefined ? Color.fromObject(baseColor) : Color.white();
this._partialCoverage = partialCoverage;
this._occlusionTextureStrength = occlusionTextureStrength;
this._metallic = metallic;
this._roughness = roughness;
this._normalScale = normalScale;
this._emissive = emissive !== undefined ? Color.fromObject(emissive) : Color.black();
this._transmission = transmission !== undefined ? Color.fromObject(transmission) : Color.black();
this._collimation = collimation;
this._ior = ior;
this._baseColorPartialCoverageTexture = baseColorPartialCoverageTexture;
this._occlusionTexture = occlusionTexture;
this._roughnessMetallicTexture = roughnessMetallicTexture;
this._normalTexture = normalTexture;
this._emissiveTexture = emissiveTexture;
this._transmissionCollimationTexture = transmissionCollimationTexture;
this._transparent = transparent;
this._doubleSided = doubleSided;
}
}
Object.defineProperty(Material.prototype, "type", { value: "Material" });
export function isMaterial(value: unknown): value is Material {
return Boolean(value) && (value as Material).type === "Material";
}

View File

@@ -4,8 +4,7 @@
* obtain one at http://mozilla.org/MPL/2.0/.
*/
import { Camera, Matrix4x4, Mesh, Quaternion, QuaternionObject, Vector3, Vector3Object } from ".";
import { Material } from "../resources";
import { Camera, Light, Material, Matrix4x4, Mesh, Quaternion, QuaternionObject, Vector3, Vector3Object } from ".";
export interface NodeProps {
readonly name?: string;
@@ -15,6 +14,7 @@ export interface NodeProps {
readonly scale?: Vector3Object;
readonly camera?: Camera | null;
readonly light?: Light | null;
readonly mesh?: Mesh | null;
readonly materials?: Material[];
@@ -33,6 +33,8 @@ export class Node {
/** unique */
_camera: Camera | null;
/** unique */
_light: Light | null;
/** shared */
_mesh: Mesh | null;
/** shared */
@@ -56,6 +58,7 @@ export class Node {
rotation,
scale,
camera = null,
light = null,
mesh = null,
materials = [],
children = [],
@@ -67,6 +70,7 @@ export class Node {
this._scale = scale !== undefined ? Vector3.fromObject(scale) : Vector3.one();
this._camera = camera;
this._light = light;
this._mesh = mesh;
this._materials = materials;
@@ -94,6 +98,10 @@ export class Node {
this._camera._node = this;
}
if (this._light !== null) {
this._light._node = this;
}
if (this._children !== null) {
for (const child of this._children) {
child._parent = this;
@@ -101,6 +109,9 @@ export class Node {
}
}
set name(value: string) { this._name = value; }
get name(): string { return this._name; }
setTranslation(value: Vector3Object): Node {
this._translation.setObject(value);
this._localMatrixNeedsUpdate = true;
@@ -109,8 +120,7 @@ export class Node {
}
getTranslation(res: Vector3): Vector3 {
res.setObject(this._translation);
return res;
return res.setObject(this._translation);
}
setRotation(value: QuaternionObject): Node {
@@ -121,8 +131,7 @@ export class Node {
}
getRotation(res: Quaternion): Quaternion {
res.setObject(this._rotation);
return res;
return res.setObject(this._rotation);
}
setScale(value: Vector3Object): Node {
@@ -133,8 +142,7 @@ export class Node {
}
getScale(res: Vector3): Vector3 {
res.setObject(this._scale);
return res;
return res.setObject(this._scale);
}
set camera(value: Camera | null) {
@@ -172,6 +180,41 @@ export class Node {
return this;
}
set light(value: Light | null) {
if (value !== null) {
this.attachLight(value);
} else {
this.detachLight();
}
}
get light(): Light | null { return this._light; }
attachLight(light: Light): Node {
if (this._light !== null) {
this._light._node = null;
}
this._light = light;
if (light._node !== null) {
light._node._light = null;
}
light._node = this;
this._light = light;
return this;
}
detachLight(): Node {
if (this._light === null) {
return this;
}
this._light._node = null;
this._light = null;
return this;
}
set mesh(value: Mesh | null) { this._mesh = value; }
get mesh(): Mesh | null { return this._mesh; }
@@ -269,3 +312,10 @@ Object.defineProperty(Node.prototype, "type", { value: "Node" });
export function isNode(value: unknown): value is Node {
return Boolean(value) && (value as Node).type === "Node";
}
export function* preOrder(nodes: Iterable<Node>): Generator<Node, void, undefined> {
for (const node of nodes) {
yield node;
yield* node._children;
}
}

View File

@@ -6,6 +6,8 @@
export * from "./Camera";
export * from "./Color";
export * from "./Light";
export * from "./Material";
export * from "./Matrix4x4";
export * from "./Mesh";
export * from "./Node";