@fonsecabarreto/genesis-gl-core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +33 -0
- package/dist/Camera-DY_8gx3C.d.ts +45 -0
- package/dist/Core/classes/Material.d.ts +3 -0
- package/dist/Core/classes/Material.js +9 -0
- package/dist/Core/classes/Material.js.map +1 -0
- package/dist/Core/classes/Model.d.ts +5 -0
- package/dist/Core/classes/Model.js +7 -0
- package/dist/Core/classes/Model.js.map +1 -0
- package/dist/Core/classes/Renderer.d.ts +30 -0
- package/dist/Core/classes/Renderer.js +11 -0
- package/dist/Core/classes/Renderer.js.map +1 -0
- package/dist/Core/classes/Scene.d.ts +37 -0
- package/dist/Core/classes/Scene.js +7 -0
- package/dist/Core/classes/Scene.js.map +1 -0
- package/dist/Core/classes/Viewport.d.ts +37 -0
- package/dist/Core/classes/Viewport.js +7 -0
- package/dist/Core/classes/Viewport.js.map +1 -0
- package/dist/Core/domain/interfaces/Vectors.d.ts +4 -0
- package/dist/Core/domain/interfaces/Vectors.js +1 -0
- package/dist/Core/domain/interfaces/Vectors.js.map +1 -0
- package/dist/Core/index.d.ts +10 -0
- package/dist/Core/index.js +51 -0
- package/dist/Core/index.js.map +1 -0
- package/dist/Core/utils/get-overlap.d.ts +3 -0
- package/dist/Core/utils/get-overlap.js +11 -0
- package/dist/Core/utils/get-overlap.js.map +1 -0
- package/dist/Core/utils/load-glb.d.ts +101 -0
- package/dist/Core/utils/load-glb.js +697 -0
- package/dist/Core/utils/load-glb.js.map +1 -0
- package/dist/Core/utils/parse-obj.d.ts +10 -0
- package/dist/Core/utils/parse-obj.js +183 -0
- package/dist/Core/utils/parse-obj.js.map +1 -0
- package/dist/Editor/index.d.ts +364 -0
- package/dist/Editor/index.js +1737 -0
- package/dist/Editor/index.js.map +1 -0
- package/dist/Game/controls/KeyboardInput.d.ts +8 -0
- package/dist/Game/controls/KeyboardInput.js +7 -0
- package/dist/Game/controls/KeyboardInput.js.map +1 -0
- package/dist/Game/index.d.ts +45 -0
- package/dist/Game/index.js +353 -0
- package/dist/Game/index.js.map +1 -0
- package/dist/KeyboardControl-5w7Vm0J0.d.ts +18 -0
- package/dist/KeyboardInput-DTsfj3tE.d.ts +166 -0
- package/dist/Material-BGLkldxv.d.ts +74 -0
- package/dist/Model-CQvDXd-b.d.ts +302 -0
- package/dist/WebGLCore-DR7ZHJB0.d.ts +22 -0
- package/dist/chunk-3ULETMWF.js +144 -0
- package/dist/chunk-3ULETMWF.js.map +1 -0
- package/dist/chunk-5TAAXI6S.js +330 -0
- package/dist/chunk-5TAAXI6S.js.map +1 -0
- package/dist/chunk-6LS6AO5H.js +296 -0
- package/dist/chunk-6LS6AO5H.js.map +1 -0
- package/dist/chunk-JK2HEZAT.js +317 -0
- package/dist/chunk-JK2HEZAT.js.map +1 -0
- package/dist/chunk-P7QOKDLY.js +57 -0
- package/dist/chunk-P7QOKDLY.js.map +1 -0
- package/dist/chunk-QCQVJCSR.js +968 -0
- package/dist/chunk-QCQVJCSR.js.map +1 -0
- package/dist/chunk-SUNYSY45.js +81 -0
- package/dist/chunk-SUNYSY45.js.map +1 -0
- package/package.json +83 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import { Vector3 } from './Core/domain/interfaces/Vectors.js';
|
|
2
|
+
import { W as WebGLCore } from './WebGLCore-DR7ZHJB0.js';
|
|
3
|
+
import { b as Material } from './Material-BGLkldxv.js';
|
|
4
|
+
import { vec3, quat, mat4 } from 'gl-matrix';
|
|
5
|
+
|
|
6
|
+
interface AABB {
|
|
7
|
+
min: Vector3;
|
|
8
|
+
max: Vector3;
|
|
9
|
+
}
|
|
10
|
+
type ColliderType = 'box' | 'sphere' | 'capsule';
|
|
11
|
+
declare class Collider {
|
|
12
|
+
type: ColliderType;
|
|
13
|
+
offset: Vector3;
|
|
14
|
+
size: Vector3;
|
|
15
|
+
constructor(type: ColliderType, offset?: Vector3, size?: Vector3);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** WebGL draw-mode constants. */
|
|
19
|
+
declare const GL_LINES = 1;
|
|
20
|
+
declare const GL_TRIANGLES = 4;
|
|
21
|
+
declare const INITIAL_BOUNDING_BOX: AABB;
|
|
22
|
+
/**
|
|
23
|
+
* A single renderable mesh: vertex data, normals, indices, a material, and an
|
|
24
|
+
* optional bounding box used for collision detection.
|
|
25
|
+
*
|
|
26
|
+
* For skinned meshes, set {@link jointIndices} and {@link jointWeights} to
|
|
27
|
+
* enable GPU skeletal animation.
|
|
28
|
+
*/
|
|
29
|
+
declare class Mesh {
|
|
30
|
+
name: string;
|
|
31
|
+
vertices: Float32Array;
|
|
32
|
+
normals: Float32Array;
|
|
33
|
+
texCoords: Float32Array;
|
|
34
|
+
indices: Uint16Array | Uint32Array | null;
|
|
35
|
+
mode: number;
|
|
36
|
+
material: Material;
|
|
37
|
+
/** Per-vertex joint indices (vec4 per vertex, 4 influences). */
|
|
38
|
+
jointIndices: Float32Array | null;
|
|
39
|
+
/** Per-vertex joint weights (vec4 per vertex, 4 influences). */
|
|
40
|
+
jointWeights: Float32Array | null;
|
|
41
|
+
buffers: MeshBuffers | null;
|
|
42
|
+
boundingBox: AABB;
|
|
43
|
+
isCollidable: boolean;
|
|
44
|
+
isInitialized: boolean;
|
|
45
|
+
constructor(name: string, vertices: Float32Array, normals: Float32Array, material: Material, texCoords?: Float32Array, indices?: Uint16Array | Uint32Array | null);
|
|
46
|
+
setMode(newMode: number): void;
|
|
47
|
+
/** Whether this mesh has skinning data for skeletal animation. */
|
|
48
|
+
get isSkinned(): boolean;
|
|
49
|
+
computeBounds(): void;
|
|
50
|
+
clone(): Mesh;
|
|
51
|
+
/** Initialize GPU buffers safely */
|
|
52
|
+
initBuffer(webglCore: WebGLCore): void;
|
|
53
|
+
/** Dispose of GPU buffers safely */
|
|
54
|
+
dispose(webglCore: WebGLCore): void;
|
|
55
|
+
}
|
|
56
|
+
declare class MeshBuffers {
|
|
57
|
+
vao: WebGLVertexArrayObject | null;
|
|
58
|
+
vertexBuffer: WebGLBuffer | null;
|
|
59
|
+
normalBuffer: WebGLBuffer | null;
|
|
60
|
+
texCoordBuffer: WebGLBuffer | null;
|
|
61
|
+
indexBuffer: WebGLBuffer | null;
|
|
62
|
+
jointIndexBuffer: WebGLBuffer | null;
|
|
63
|
+
jointWeightBuffer: WebGLBuffer | null;
|
|
64
|
+
init(gl: WebGLRenderingContext, mesh: Mesh): void;
|
|
65
|
+
dispose(gl: WebGL2RenderingContext): void;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Maximum number of joints supported per skeleton (must match shader). */
|
|
69
|
+
declare const MAX_JOINTS = 128;
|
|
70
|
+
/**
|
|
71
|
+
* Describes a single joint (bone) inside a {@link Skeleton}.
|
|
72
|
+
*
|
|
73
|
+
* Each joint stores its default bind-pose transform (translation, rotation,
|
|
74
|
+
* scale) and the inverse bind matrix used to transform vertices from model
|
|
75
|
+
* space into joint-local space.
|
|
76
|
+
*/
|
|
77
|
+
interface Joint {
|
|
78
|
+
/** Human-readable name (e.g. "Hips", "LeftArm"). */
|
|
79
|
+
name: string;
|
|
80
|
+
/** Original glTF node index this joint references. */
|
|
81
|
+
nodeIndex: number;
|
|
82
|
+
/** Index of the parent joint in the skeleton's joint array (-1 = root). */
|
|
83
|
+
parentIndex: number;
|
|
84
|
+
/** Bind-pose translation. */
|
|
85
|
+
localTranslation: vec3;
|
|
86
|
+
/** Bind-pose rotation (quaternion). */
|
|
87
|
+
localRotation: quat;
|
|
88
|
+
/** Bind-pose scale. */
|
|
89
|
+
localScale: vec3;
|
|
90
|
+
/** Inverse bind matrix from the glTF skin. */
|
|
91
|
+
inverseBindMatrix: mat4;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Per-joint local transform produced by animation sampling.
|
|
95
|
+
* Any undefined component falls back to the bind-pose value.
|
|
96
|
+
*/
|
|
97
|
+
interface JointPose {
|
|
98
|
+
t?: vec3;
|
|
99
|
+
r?: quat;
|
|
100
|
+
s?: vec3;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* A skeleton representing a hierarchy of {@link Joint}s.
|
|
104
|
+
*
|
|
105
|
+
* Call {@link computeJointMatrices} each frame with the current animation pose
|
|
106
|
+
* to produce a flat `Float32Array` of `mat4`s ready for upload as a shader
|
|
107
|
+
* uniform.
|
|
108
|
+
*/
|
|
109
|
+
declare class Skeleton {
|
|
110
|
+
/** Ordered joint list (parent always precedes child). */
|
|
111
|
+
readonly joints: Joint[];
|
|
112
|
+
/**
|
|
113
|
+
* Flat `Float32Array` of `joints.length` column-major `mat4` values.
|
|
114
|
+
* Updated by {@link computeJointMatrices} — upload directly to
|
|
115
|
+
* `uJointMatrices[0]`.
|
|
116
|
+
*/
|
|
117
|
+
readonly jointMatrices: Float32Array;
|
|
118
|
+
/**
|
|
119
|
+
* Global transform of the non-joint ancestor nodes above the skeleton
|
|
120
|
+
* root. In many exported models the armature sits under a scene-root
|
|
121
|
+
* node that carries scale / rotation (e.g. cm → m conversion). This
|
|
122
|
+
* transform is pre-multiplied into root-joint globals so that
|
|
123
|
+
* `global * inverseBindMatrix` evaluates to identity in the bind pose.
|
|
124
|
+
*/
|
|
125
|
+
readonly rootTransform: mat4;
|
|
126
|
+
constructor(joints: Joint[], rootTransform?: mat4);
|
|
127
|
+
/** Number of joints in the skeleton. */
|
|
128
|
+
get jointCount(): number;
|
|
129
|
+
/**
|
|
130
|
+
* Walk the joint hierarchy, composing global transforms, then multiply by
|
|
131
|
+
* each joint's inverse-bind matrix. The result is stored in
|
|
132
|
+
* {@link jointMatrices} ready for shader upload.
|
|
133
|
+
*
|
|
134
|
+
* @param animatedPoses - Optional per-joint local transforms from an
|
|
135
|
+
* {@link AnimationClip}. Map keys are **joint array indices** (not glTF
|
|
136
|
+
* node indices).
|
|
137
|
+
*/
|
|
138
|
+
computeJointMatrices(animatedPoses?: Map<number, JointPose>): void;
|
|
139
|
+
/**
|
|
140
|
+
* Create a deep clone of this skeleton (useful when instancing models).
|
|
141
|
+
*/
|
|
142
|
+
clone(): Skeleton;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Interpolation mode as defined by glTF 2.0. */
|
|
146
|
+
type InterpolationMode = 'STEP' | 'LINEAR' | 'CUBICSPLINE';
|
|
147
|
+
/** Which transform component the channel drives. */
|
|
148
|
+
type AnimationPath = 'translation' | 'rotation' | 'scale';
|
|
149
|
+
/**
|
|
150
|
+
* Stores the raw keyframe data for one animated property and performs
|
|
151
|
+
* interpolation between keyframes.
|
|
152
|
+
*/
|
|
153
|
+
interface AnimationSampler {
|
|
154
|
+
/** Keyframe timestamps (seconds). */
|
|
155
|
+
times: Float32Array;
|
|
156
|
+
/** Flattened keyframe output values (3 or 4 components per key). */
|
|
157
|
+
values: Float32Array;
|
|
158
|
+
/** Interpolation mode (default `LINEAR`). */
|
|
159
|
+
interpolation: InterpolationMode;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Links a {@link AnimationSampler} to a specific joint property.
|
|
163
|
+
*/
|
|
164
|
+
interface AnimationChannel {
|
|
165
|
+
/** Index into the owning {@link Skeleton}'s joint array. */
|
|
166
|
+
jointIndex: number;
|
|
167
|
+
/** Transform component this channel drives. */
|
|
168
|
+
path: AnimationPath;
|
|
169
|
+
/** The sampler that holds keyframe data. */
|
|
170
|
+
sampler: AnimationSampler;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* A named animation clip containing one or more {@link AnimationChannel}s.
|
|
174
|
+
*
|
|
175
|
+
* Call {@link update} each frame to advance the playhead, then {@link sample}
|
|
176
|
+
* to obtain per-joint local transforms that feed into
|
|
177
|
+
* `Skeleton.computeJointMatrices()`.
|
|
178
|
+
*
|
|
179
|
+
* ```ts
|
|
180
|
+
* clip.play();
|
|
181
|
+
* // game loop:
|
|
182
|
+
* clip.update(deltaTime);
|
|
183
|
+
* const poses = clip.sample();
|
|
184
|
+
* skeleton.computeJointMatrices(poses);
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
declare class AnimationClip {
|
|
188
|
+
/** Human-readable name (e.g. "Walk", "Idle"). */
|
|
189
|
+
readonly name: string;
|
|
190
|
+
/** All channels in this clip. */
|
|
191
|
+
readonly channels: AnimationChannel[];
|
|
192
|
+
/** Total duration in seconds (derived from the maximum keyframe time). */
|
|
193
|
+
readonly duration: number;
|
|
194
|
+
/** Current playback time in seconds. */
|
|
195
|
+
currentTime: number;
|
|
196
|
+
/** Whether the clip loops when it reaches the end. */
|
|
197
|
+
loop: boolean;
|
|
198
|
+
/** Playback speed multiplier (1 = normal, 2 = double, −1 = reverse). */
|
|
199
|
+
speed: number;
|
|
200
|
+
/** Whether the clip is currently advancing. */
|
|
201
|
+
playing: boolean;
|
|
202
|
+
constructor(name: string, channels: AnimationChannel[], duration: number);
|
|
203
|
+
/** Start / resume playback. */
|
|
204
|
+
play(): void;
|
|
205
|
+
/** Pause playback (keeps current time). */
|
|
206
|
+
pause(): void;
|
|
207
|
+
/** Stop and rewind to the beginning. */
|
|
208
|
+
stop(): void;
|
|
209
|
+
/** Rewind to the beginning without changing play state. */
|
|
210
|
+
reset(): void;
|
|
211
|
+
/**
|
|
212
|
+
* Advance the playhead by `deltaTime` seconds (respects {@link speed}).
|
|
213
|
+
* Automatically loops or clamps depending on {@link loop}.
|
|
214
|
+
*/
|
|
215
|
+
update(deltaTime: number): void;
|
|
216
|
+
/**
|
|
217
|
+
* Sample every channel at the current playhead and return a map of
|
|
218
|
+
* joint-index → local pose.
|
|
219
|
+
*/
|
|
220
|
+
sample(): Map<number, JointPose>;
|
|
221
|
+
/**
|
|
222
|
+
* Create an independent copy of this clip (shares the underlying sampler
|
|
223
|
+
* data but has its own playback state).
|
|
224
|
+
*/
|
|
225
|
+
clone(): AnimationClip;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* A high-level renderable object composed of one or more {@link Mesh}es.
|
|
230
|
+
* Provides transform, bounding-box, AABB collision, and optional skeletal
|
|
231
|
+
* animation utilities.
|
|
232
|
+
*/
|
|
233
|
+
declare class Model {
|
|
234
|
+
name: string;
|
|
235
|
+
meshes: Mesh[];
|
|
236
|
+
collider: Collider;
|
|
237
|
+
translation: Vector3;
|
|
238
|
+
rotation: Vector3;
|
|
239
|
+
scale: Vector3;
|
|
240
|
+
boundingBox: AABB;
|
|
241
|
+
/** The skeleton driving skinned meshes (set after GLB load if present). */
|
|
242
|
+
skeleton: Skeleton | null;
|
|
243
|
+
/** Named animation clips available on this model. */
|
|
244
|
+
animations: Map<string, AnimationClip>;
|
|
245
|
+
/** The currently playing animation clip (if any). */
|
|
246
|
+
activeAnimation: AnimationClip | null;
|
|
247
|
+
private _boundsDefinedManually;
|
|
248
|
+
private _modelMatrix;
|
|
249
|
+
private _matrixDirty;
|
|
250
|
+
/** When `false` the model is excluded from collision detection. */
|
|
251
|
+
collidable: boolean;
|
|
252
|
+
constructor(meshes: Mesh[], translation?: Vector3, scale?: Vector3, _name?: string, skeleton?: Skeleton | null);
|
|
253
|
+
/** Set absolute position. Marks matrix dirty and updates bounding box. */
|
|
254
|
+
setTranslation(x: number, y: number, z: number): void;
|
|
255
|
+
/** Set absolute rotation (radians per axis). */
|
|
256
|
+
setRotation(x: number, y: number, z: number): void;
|
|
257
|
+
/** Set absolute scale. */
|
|
258
|
+
setScale(x: number, y: number, z: number): void;
|
|
259
|
+
/** Translate the model by a delta. */
|
|
260
|
+
move(dx: number, dy: number, dz?: number): void;
|
|
261
|
+
private getModelMatrix;
|
|
262
|
+
/**
|
|
263
|
+
* Manually define the collision bounding box relative to the model's
|
|
264
|
+
* current translation.
|
|
265
|
+
*/
|
|
266
|
+
setBounds(xOffset: number, yOffset: number, zOffset: number, width: number, height: number, depth: number): void;
|
|
267
|
+
private computeBoundingBox;
|
|
268
|
+
/** Recompute the world-space AABB from mesh data (unless manually set). */
|
|
269
|
+
updateBoundingBox(): void;
|
|
270
|
+
/** World-space centre of the bounding box. */
|
|
271
|
+
getCenter(): Vector3;
|
|
272
|
+
/** Extents of the bounding box in each axis. */
|
|
273
|
+
getSize(): Vector3;
|
|
274
|
+
/** Test for intersection with another model using their colliders. */
|
|
275
|
+
intersects(other: Model): boolean;
|
|
276
|
+
private intersectAABB;
|
|
277
|
+
/** Release all GPU resources held by this model's meshes. */
|
|
278
|
+
dispose(glCore: WebGLCore): void;
|
|
279
|
+
/** Deep-clone the model including all meshes. Materials are shared. */
|
|
280
|
+
clone(): Model;
|
|
281
|
+
/**
|
|
282
|
+
* Start playing a named animation clip.
|
|
283
|
+
* @param name - Must match a key in {@link animations}.
|
|
284
|
+
* @param loop - Whether the clip should loop (default `true`).
|
|
285
|
+
*/
|
|
286
|
+
playAnimation(name: string, loop?: boolean): void;
|
|
287
|
+
/** Pause the active animation without rewinding. */
|
|
288
|
+
pauseAnimation(): void;
|
|
289
|
+
/** Stop the active animation and rewind. */
|
|
290
|
+
stopAnimation(): void;
|
|
291
|
+
/** List the names of all available animations. */
|
|
292
|
+
getAnimationNames(): string[];
|
|
293
|
+
/**
|
|
294
|
+
* Advance animation and recompute joint matrices.
|
|
295
|
+
* Call this every frame from your game loop.
|
|
296
|
+
*
|
|
297
|
+
* @param deltaTime - Elapsed time in seconds since the last frame.
|
|
298
|
+
*/
|
|
299
|
+
update(deltaTime: number): void;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export { type AnimationChannel as A, GL_LINES as G, INITIAL_BOUNDING_BOX as I, type Joint as J, MAX_JOINTS as M, Skeleton as S, AnimationClip as a, type AnimationPath as b, type AnimationSampler as c, GL_TRIANGLES as d, type InterpolationMode as e, type JointPose as f, Mesh as g, MeshBuffers as h, Model as i };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
type RenderCallback = (gl: WebGLRenderingContext, program: WebGLProgram) => void;
|
|
2
|
+
declare class WebGLCore {
|
|
3
|
+
gl: WebGL2RenderingContext | WebGLRenderingContext;
|
|
4
|
+
program: WebGLProgram;
|
|
5
|
+
canvas: HTMLCanvasElement;
|
|
6
|
+
isWebGL2: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Initialise the WebGL rendering core.
|
|
9
|
+
*
|
|
10
|
+
* @param canvasOrId - An `HTMLCanvasElement` or the DOM `id` of one.
|
|
11
|
+
* Defaults to `'glcanvas'`.
|
|
12
|
+
*/
|
|
13
|
+
constructor(canvasOrId?: string | HTMLCanvasElement);
|
|
14
|
+
getProgram(): WebGLProgram;
|
|
15
|
+
getRenderingContext(): WebGLRenderingContext;
|
|
16
|
+
private createProgram;
|
|
17
|
+
private compileShader;
|
|
18
|
+
resize(width: number, height: number): void;
|
|
19
|
+
dispose(): void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export { type RenderCallback as R, WebGLCore as W };
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// src/Core/classes/Light.ts
|
|
2
|
+
var Light = class {
|
|
3
|
+
constructor(type = "directional", position = [0, 10, 0], direction = [0, -1, -1], color = [1, 1, 1], intensity = 1, constant = 1, linear = 0, quadratic = 0) {
|
|
4
|
+
this.type = type;
|
|
5
|
+
this.position = position;
|
|
6
|
+
this.direction = direction;
|
|
7
|
+
this.color = color;
|
|
8
|
+
this.intensity = intensity;
|
|
9
|
+
this.constant = constant;
|
|
10
|
+
this.linear = linear;
|
|
11
|
+
this.quadratic = quadratic;
|
|
12
|
+
}
|
|
13
|
+
type;
|
|
14
|
+
position;
|
|
15
|
+
direction;
|
|
16
|
+
color;
|
|
17
|
+
intensity;
|
|
18
|
+
// Attenuation factors are initialized to standard values (no falloff)
|
|
19
|
+
constant = 1;
|
|
20
|
+
linear = 0;
|
|
21
|
+
quadratic = 0;
|
|
22
|
+
move(dx, dy, dz) {
|
|
23
|
+
this.position[0] += dx;
|
|
24
|
+
this.position[1] += dy;
|
|
25
|
+
this.position[2] += dz;
|
|
26
|
+
}
|
|
27
|
+
rotateY(delta) {
|
|
28
|
+
if (this.type === "directional") {
|
|
29
|
+
const cos = Math.cos(delta);
|
|
30
|
+
const sin = Math.sin(delta);
|
|
31
|
+
const [x, y, z] = this.direction;
|
|
32
|
+
this.direction[0] = x * cos - z * sin;
|
|
33
|
+
this.direction[2] = x * sin + z * cos;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// src/Core/classes/Scene.ts
|
|
39
|
+
var Scene = class _Scene {
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
41
|
+
constructor(webglCore) {
|
|
42
|
+
this.webglCore = webglCore;
|
|
43
|
+
}
|
|
44
|
+
webglCore;
|
|
45
|
+
models = [];
|
|
46
|
+
modelsMap = /* @__PURE__ */ new Map();
|
|
47
|
+
lights = [];
|
|
48
|
+
// ─────────────────────────────────────────────
|
|
49
|
+
// ░░░ Factory: pre-configured 3-point lighting ░░░
|
|
50
|
+
// ─────────────────────────────────────────────
|
|
51
|
+
/**
|
|
52
|
+
* Create a Scene pre-loaded with a classic **3-point lighting** rig
|
|
53
|
+
* (ambient + key + fill + back).
|
|
54
|
+
*
|
|
55
|
+
* Use this for quick prototyping; for production, create a plain Scene and
|
|
56
|
+
* add your own lights.
|
|
57
|
+
*/
|
|
58
|
+
static withDefaultLights(webglCore) {
|
|
59
|
+
const scene = new _Scene(webglCore);
|
|
60
|
+
scene.addLight(
|
|
61
|
+
"ambient_base",
|
|
62
|
+
new Light("ambient", [0, 0, 0], [0, 0, 0], [0.3, 0.3, 0.35], 0.5)
|
|
63
|
+
);
|
|
64
|
+
scene.addLight(
|
|
65
|
+
"directional_key",
|
|
66
|
+
new Light(
|
|
67
|
+
"directional",
|
|
68
|
+
[5, 10, 5],
|
|
69
|
+
[-0.5, -1, -0.5],
|
|
70
|
+
[1, 0.95, 0.9],
|
|
71
|
+
1.2
|
|
72
|
+
)
|
|
73
|
+
);
|
|
74
|
+
scene.addLight(
|
|
75
|
+
"directional_fill",
|
|
76
|
+
new Light(
|
|
77
|
+
"directional",
|
|
78
|
+
[-10, 5, 10],
|
|
79
|
+
[0.5, -0.2, -0.7],
|
|
80
|
+
[0.8, 0.8, 1],
|
|
81
|
+
0.5
|
|
82
|
+
)
|
|
83
|
+
);
|
|
84
|
+
scene.addLight(
|
|
85
|
+
"directional_back",
|
|
86
|
+
new Light(
|
|
87
|
+
"directional",
|
|
88
|
+
[0, 15, -10],
|
|
89
|
+
[0, -0.8, 1],
|
|
90
|
+
[1, 1, 1],
|
|
91
|
+
0.7
|
|
92
|
+
)
|
|
93
|
+
);
|
|
94
|
+
return scene;
|
|
95
|
+
}
|
|
96
|
+
/** Register a light source in the scene. */
|
|
97
|
+
addLight(id, light) {
|
|
98
|
+
this.lights.push(light);
|
|
99
|
+
}
|
|
100
|
+
/** Add a model to the scene with a unique key. */
|
|
101
|
+
add(id, model) {
|
|
102
|
+
this.models.push(model);
|
|
103
|
+
this.modelsMap.set(id, model);
|
|
104
|
+
}
|
|
105
|
+
/** Remove a model from the scene by key. */
|
|
106
|
+
remove(key) {
|
|
107
|
+
const mesh = this.modelsMap.get(key);
|
|
108
|
+
if (!mesh) return;
|
|
109
|
+
this.models = this.models.filter((m) => m !== mesh);
|
|
110
|
+
this.modelsMap.delete(key);
|
|
111
|
+
}
|
|
112
|
+
getModels() {
|
|
113
|
+
return this.models;
|
|
114
|
+
}
|
|
115
|
+
getLights() {
|
|
116
|
+
return this.lights;
|
|
117
|
+
}
|
|
118
|
+
/** Retrieve a model by its key. */
|
|
119
|
+
getModel(key) {
|
|
120
|
+
const mesh = this.modelsMap.get(key);
|
|
121
|
+
return mesh;
|
|
122
|
+
}
|
|
123
|
+
hasMesh(key) {
|
|
124
|
+
return this.modelsMap.has(key);
|
|
125
|
+
}
|
|
126
|
+
/** Returns all [id, model] pairs — useful for debug/inspector tools. */
|
|
127
|
+
getEntries() {
|
|
128
|
+
return [...this.modelsMap.entries()];
|
|
129
|
+
}
|
|
130
|
+
dispose(webglCore) {
|
|
131
|
+
for (const model of this.models) {
|
|
132
|
+
model.dispose(webglCore);
|
|
133
|
+
}
|
|
134
|
+
this.models.length = 0;
|
|
135
|
+
this.modelsMap.clear();
|
|
136
|
+
this.lights.length = 0;
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export {
|
|
141
|
+
Light,
|
|
142
|
+
Scene
|
|
143
|
+
};
|
|
144
|
+
//# sourceMappingURL=chunk-3ULETMWF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/Core/classes/Light.ts","../src/Core/classes/Scene.ts"],"sourcesContent":["import { Vector3 } from '../domain/interfaces/Vectors';\n\n/**\n * Supported light types.\n * - `directional` – parallel rays (sun-like).\n * - `point` – omnidirectional with distance attenuation.\n * - `ambient` – constant contribution everywhere.\n */\nexport type LightType = 'directional' | 'point' | 'ambient';\n\n/**\n * A scene light with type, position, direction, colour, intensity,\n * and attenuation factors (for point lights).\n */\nexport class Light {\n // Attenuation factors are initialized to standard values (no falloff)\n public constant: number = 1.0;\n public linear: number = 0.0;\n public quadratic: number = 0.0;\n\n constructor(\n public type: LightType = 'directional',\n public position: Vector3 = [0, 10, 0], // for point lights\n public direction: Vector3 = [0, -1, -1], // for directional lights\n public color: Vector3 = [1, 1, 1],\n public intensity: number = 1,\n constant: number = 1.0,\n linear: number = 0.0,\n quadratic: number = 0.0,\n ) {\n this.constant = constant;\n this.linear = linear;\n this.quadratic = quadratic;\n }\n\n move(dx: number, dy: number, dz: number) {\n this.position[0] += dx;\n this.position[1] += dy;\n this.position[2] += dz;\n }\n\n rotateY(delta: number) {\n if (this.type === 'directional') {\n const cos = Math.cos(delta);\n const sin = Math.sin(delta);\n const [x, y, z] = this.direction;\n this.direction[0] = x * cos - z * sin;\n this.direction[2] = x * sin + z * cos;\n }\n }\n}\n","import { Light } from './Light';\nimport { Model } from './Model';\nimport WebGLCore from './WebGLCore';\n\nexport class Scene {\n private models: Model[] = [];\n private modelsMap = new Map<string, Model>();\n public lights: Light[] = [];\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n constructor(private webglCore: WebGLCore) {}\n\n // ─────────────────────────────────────────────\n // ░░░ Factory: pre-configured 3-point lighting ░░░\n // ─────────────────────────────────────────────\n\n /**\n * Create a Scene pre-loaded with a classic **3-point lighting** rig\n * (ambient + key + fill + back).\n *\n * Use this for quick prototyping; for production, create a plain Scene and\n * add your own lights.\n */\n static withDefaultLights(webglCore: WebGLCore): Scene {\n const scene = new Scene(webglCore);\n\n // 🌈 AMBIENT LIGHT (Global Base Illumination)\n scene.addLight(\n 'ambient_base',\n new Light('ambient', [0, 0, 0], [0, 0, 0], [0.3, 0.3, 0.35], 0.5),\n );\n\n // 🔑 KEY LIGHT (Main Sun/Primary Source)\n scene.addLight(\n 'directional_key',\n new Light(\n 'directional',\n [5, 10, 5],\n [-0.5, -1.0, -0.5],\n [1.0, 0.95, 0.9],\n 1.2,\n ),\n );\n\n // ☁️ FILL LIGHT (Softens Shadows)\n scene.addLight(\n 'directional_fill',\n new Light(\n 'directional',\n [-10, 5, 10],\n [0.5, -0.2, -0.7],\n [0.8, 0.8, 1.0],\n 0.5,\n ),\n );\n\n // 💫 BACK LIGHT (Rim/Separation Light)\n scene.addLight(\n 'directional_back',\n new Light(\n 'directional',\n [0, 15, -10],\n [0.0, -0.8, 1.0],\n [1.0, 1.0, 1.0],\n 0.7,\n ),\n );\n\n return scene;\n }\n\n /** Register a light source in the scene. */\n public addLight(id: string, light: Light) {\n this.lights.push(light);\n\n /* Debug only */\n /* \n const lightSphere = createSphereMesh(\n this.webglCore,\n 0.25,\n 12,\n 12,\n [1, 1, 0.8],\n );\n\n lightSphere.isCollidable = false;\n lightSphere.translation = light.position;\n this.add(id + '_sphere', lightSphere);\n\n // Debug direction for directional lights\n if (light.type === 'point' || light.type === 'directional') {\n const dirMesh = createLightDirectionMesh(\n this.webglCore,\n light.position,\n light.direction,\n 5, // length of the arrow\n [1, 0, 0], // red arrow\n );\n this.add(id + '_dir', dirMesh);\n } \n */\n }\n\n /** Add a model to the scene with a unique key. */\n add(id: string, model: Model) {\n this.models.push(model);\n this.modelsMap.set(id, model);\n }\n\n /** Remove a model from the scene by key. */\n remove(key: string) {\n const mesh = this.modelsMap.get(key);\n if (!mesh) return;\n this.models = this.models.filter((m) => m !== mesh);\n this.modelsMap.delete(key);\n }\n\n getModels() {\n return this.models;\n }\n\n getLights() {\n return this.lights;\n }\n\n /** Retrieve a model by its key. */\n public getModel(key: string) {\n const mesh = this.modelsMap.get(key);\n return mesh;\n }\n\n public hasMesh(key: string) {\n return this.modelsMap.has(key);\n }\n\n /** Returns all [id, model] pairs — useful for debug/inspector tools. */\n public getEntries(): [string, Model][] {\n return [...this.modelsMap.entries()];\n }\n\n dispose(webglCore: WebGLCore) {\n for (const model of this.models) {\n model.dispose(webglCore);\n }\n this.models.length = 0;\n this.modelsMap.clear();\n this.lights.length = 0;\n }\n}\n"],"mappings":"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","names":[]}
|