@fonsecabarreto/genesis-gl-core 0.1.3 → 0.1.33
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/dist/Core/classes/Material.d.ts +1 -1
- package/dist/Core/classes/Material.js +1 -1
- package/dist/Core/classes/Model.d.ts +2 -2
- package/dist/Core/classes/Renderer.d.ts +4 -2
- package/dist/Core/classes/Renderer.js +4 -4
- package/dist/Core/classes/Scene.d.ts +3 -3
- package/dist/Core/classes/Scene.js +1 -1
- package/dist/Core/classes/Viewport.d.ts +4 -1
- package/dist/Core/classes/Viewport.js +1 -1
- package/dist/Core/index.d.ts +73 -3
- package/dist/Core/index.js +13 -7
- package/dist/Core/utils/load-glb.d.ts +2 -2
- package/dist/Core/utils/load-glb.js +4 -4
- package/dist/Core/utils/parse-obj.d.ts +2 -2
- package/dist/Core/utils/parse-obj.js +4 -4
- package/dist/Game/controls/KeyboardInput.d.ts +3 -3
- package/dist/Game/index.d.ts +4 -4
- package/dist/Game/index.js +5 -5
- package/dist/{KeyboardInput-1xOAabI0.d.ts → KeyboardInput-RJ0mbuWM.d.ts} +1 -1
- package/dist/{Material-DhwSRbP2.d.ts → Material-A-7kKes_.d.ts} +2 -0
- package/dist/{Model-BBZHnUp1.d.ts → Model-efZcQkOK.d.ts} +2 -2
- package/dist/{chunk-ZCJ3MJZD.js → chunk-4M3XFPH3.js} +17 -3
- package/dist/chunk-4M3XFPH3.js.map +1 -0
- package/dist/chunk-IOAANJZG.js +159 -0
- package/dist/chunk-IOAANJZG.js.map +1 -0
- package/dist/{chunk-XMW2MS66.js → chunk-WHOIVV44.js} +19 -12
- package/dist/chunk-WHOIVV44.js.map +1 -0
- package/dist/{chunk-3ULETMWF.js → chunk-WKSDPPXS.js} +4 -3
- package/dist/{chunk-3ULETMWF.js.map → chunk-WKSDPPXS.js.map} +1 -1
- package/dist/{chunk-L66K4AZU.js → chunk-XCYJCLHB.js} +3 -1
- package/dist/chunk-XCYJCLHB.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-L66K4AZU.js.map +0 -1
- package/dist/chunk-SUNYSY45.js +0 -81
- package/dist/chunk-SUNYSY45.js.map +0 -1
- package/dist/chunk-XMW2MS66.js.map +0 -1
- package/dist/chunk-ZCJ3MJZD.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/Core/classes/Camera.ts","../src/Core/controls/Mouse/MouseWheelControl.ts","../src/Core/controls/Mouse/MouseDragControl.ts","../src/Core/controls/Mouse/MousePointerLockControl.ts","../src/Core/classes/Viewport.ts"],"sourcesContent":["import { mat4, vec3, vec4 } from 'gl-matrix';\nimport { Vector3 } from '../domain/interfaces/Vectors';\n\n/**\n * Perspective camera with orbit (yaw/pitch), zoom, and viewport controls.\n */\nexport class Camera {\n public target: Vector3 = [0, 0, 0]; // camera looks at this\n\n /* Translation */\n public position: Vector3 = [0, 0, 0]; // 3D position\n\n /* Zoom */\n public zoom: number = 0.89;\n public minZoom: number = 0.5;\n public maxZoom: number = 1;\n public zoomSpeed: number = 0.06;\n\n /* Rotation */\n public yaw: number = 0; // horizontal rotation\n public pitch: number = 0.5; // vertical rotation\n\n public near = 0.01;\n public far = 1000.0;\n\n /* Render Utils */\n public lastViewMatrix?: Float32Array;\n public lastProjectionMatrix?: Float32Array;\n\n // ── Cached matrices (rebuilt only when camera state changes) ──\n private readonly _view: mat4 = mat4.create();\n private readonly _proj: mat4 = mat4.create();\n private readonly _mvp: mat4 = mat4.create();\n private _viewDirty = true;\n private _projDirty = true;\n\n constructor(\n public viewportWidth: number,\n public viewportHeight: number,\n ) {}\n\n /** Translate the camera by a delta. */\n move(dx: number, dy: number, dz: number = 0) {\n this.position[0] += dx;\n this.position[1] += dy;\n this.position[2] += dz;\n this._viewDirty = true;\n }\n\n /** Clamp-set the zoom level. */\n setZoom(zoom: number) {\n this.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, zoom));\n this._viewDirty = true;\n this._projDirty = true;\n }\n\n /**\n * Mark the view matrix as dirty so it is rebuilt on the next\n * {@link getViewMatrix} call. Call this after directly mutating\n * {@link target} or {@link position} (e.g. from a follow-camera update).\n */\n invalidate(): void {\n this._viewDirty = true;\n }\n\n /** Zoom by a signed delta (positive = zoom in). */\n zoomBy(delta: number) {\n const factor = Math.exp(delta * this.zoomSpeed);\n this.setZoom(this.zoom * factor);\n }\n\n worldToNDC(x: number, y: number): [number, number] {\n const ndcX = ((x - this.position[0]) / this.viewportWidth) * 2 * this.zoom;\n const ndcY = ((y - this.position[1]) / this.viewportHeight) * 2 * this.zoom;\n return [ndcX, ndcY];\n }\n\n worldScale(scale: [number, number]): [number, number] {\n return [\n (scale[0] / this.viewportWidth) * 2 * this.zoom,\n (scale[1] / this.viewportHeight) * 2 * this.zoom,\n ];\n }\n\n setViewport(width: number, height: number) {\n this.viewportWidth = width;\n this.viewportHeight = height;\n this._projDirty = true;\n }\n\n /** Compute the eye position from yaw/pitch/distance to target. */\n getComputedPosition(): vec3 {\n const radius = vec3.distance(this.position, this.target);\n\n const camX =\n this.target[0] + radius * Math.cos(this.pitch) * Math.sin(this.yaw);\n const camY = this.target[1] + radius * Math.sin(this.pitch);\n const camZ =\n this.target[2] + radius * Math.cos(this.pitch) * Math.cos(this.yaw);\n\n return vec3.fromValues(camX, camY, camZ);\n }\n\n /** Build the view matrix (lookAt). Returns a cached matrix rebuilt only when the camera moves. */\n getViewMatrix(): mat4 {\n if (this._viewDirty) {\n const eye = this.getComputedPosition();\n mat4.lookAt(this._view, eye, this.target, vec3.fromValues(0, 1, 0));\n this._viewDirty = false;\n this.lastViewMatrix = this._view as unknown as Float32Array;\n }\n return this._view;\n }\n\n /** Build the perspective projection matrix. Returns a cached matrix rebuilt only when viewport/zoom changes. */\n getProjectionMatrix(): mat4 {\n if (this._projDirty) {\n const aspect = this.viewportWidth / this.viewportHeight;\n const fov = Math.PI / 4 / this.zoom;\n mat4.perspective(this._proj, fov, aspect, this.near, this.far);\n this._projDirty = false;\n this.lastProjectionMatrix = this._proj as unknown as Float32Array;\n }\n return this._proj;\n }\n\n worldToNDC3D(x: number, y: number, z: number = 0): [number, number, number] {\n const world = vec4.fromValues(x, y, z, 1.0);\n mat4.multiply(this._mvp, this.getProjectionMatrix(), this.getViewMatrix());\n vec4.transformMat4(world, world, this._mvp);\n return [world[0] / world[3], world[1] / world[3], world[2] / world[3]];\n }\n\n worldScale3D(scale: [number, number, number]): [number, number, number] {\n return [\n (scale[0] / this.viewportWidth) * 2 * this.zoom,\n (scale[1] / this.viewportHeight) * 2 * this.zoom,\n (scale[2] / ((this.viewportWidth + this.viewportHeight) / 2)) *\n 2 *\n this.zoom,\n ];\n }\n\n public minPitch: number = -Math.PI / 2 + 1.49;\n public maxPitch: number = Math.PI / 2 - 0.01;\n\n rotate(deltaYaw: number, deltaPitch: number) {\n this.yaw += deltaYaw;\n\n this.pitch -= deltaPitch; // ← add deltaPitch here\n this.pitch = Math.max(this.minPitch, Math.min(this.maxPitch, this.pitch));\n this._viewDirty = true;\n }\n}\n","import { IMouseControl } from './IMouseControl';\n\nexport type WheelDirection = 'up' | 'down';\nexport type WheelListener = (direction: WheelDirection, delta: number) => void;\n\nexport class MouseWheelControl implements IMouseControl {\n private listeners: WheelListener[] = [];\n private wheelHandler?: (e: WheelEvent) => void;\n\n public enable() {\n if (this.wheelHandler) return;\n\n this.wheelHandler = (e: WheelEvent) => {\n const direction: WheelDirection = e.deltaY < 0 ? 'up' : 'down';\n this.notify(direction, e.deltaY);\n };\n\n window.addEventListener('wheel', this.wheelHandler, { passive: true });\n }\n\n public disable() {\n if (this.wheelHandler) {\n window.removeEventListener('wheel', this.wheelHandler);\n this.wheelHandler = undefined;\n }\n }\n\n public onChange(listener: WheelListener) {\n this.listeners.push(listener);\n }\n\n /** Remove a previously registered listener. */\n public removeListener(listener: WheelListener) {\n this.listeners = this.listeners.filter((l) => l !== listener);\n }\n\n private notify(direction: WheelDirection, delta: number) {\n for (const listener of this.listeners) listener(direction, delta);\n }\n}\n","import { IMouseControl } from './IMouseControl';\n\nexport type DragListener = (dx: number, dy: number, button: number) => void;\n\nexport class MouseDragControl implements IMouseControl {\n private listeners: DragListener[] = [];\n public isDragging = false;\n\n private dragButton: number = 0; // 0 = left, 2 = right\n private lastX = 0;\n private lastY = 0;\n\n constructor(private element: HTMLElement) {}\n\n enable() {\n this.element.addEventListener('mousedown', this.onMouseDown);\n window.addEventListener('mouseup', this.onMouseUp);\n window.addEventListener('mousemove', this.onMouseMove);\n }\n\n disable() {\n this.element.removeEventListener('mousedown', this.onMouseDown);\n window.removeEventListener('mouseup', this.onMouseUp);\n window.removeEventListener('mousemove', this.onMouseMove);\n }\n\n onChange(listener: DragListener) {\n this.listeners.push(listener);\n }\n\n /** Remove a previously registered listener. */\n removeListener(listener: DragListener) {\n this.listeners = this.listeners.filter((l) => l !== listener);\n }\n\n private onMouseDown = (e: MouseEvent) => {\n this.isDragging = true;\n this.dragButton = e.button;\n\n this.lastX = e.clientX;\n this.lastY = e.clientY;\n };\n\n private onMouseUp = () => {\n this.isDragging = false;\n };\n\n private onMouseMove = (e: MouseEvent) => {\n if (!this.isDragging) return;\n\n const dx = e.clientX - this.lastX;\n const dy = e.clientY - this.lastY;\n\n this.lastX = e.clientX;\n this.lastY = e.clientY;\n\n for (const listener of this.listeners) listener(dx, dy, this.dragButton);\n };\n}\n","import { IMouseControl } from './IMouseControl';\n\nexport type MoveListener = (dx: number, dy: number) => void;\n\n/**\n * Captures mouse movement using the Pointer Lock API.\n * Ideal for camera-like controls where the cursor should not hit screen edges.\n */\nexport class MousePointerLockControl implements IMouseControl {\n private listeners: MoveListener[] = [];\n private isEnabled = false;\n private isPointerLocked = false;\n\n constructor(\n private element: HTMLElement,\n private sensitivity = 1,\n ) {}\n\n enable() {\n if (this.isEnabled) return;\n this.isEnabled = true;\n\n // Must be initiated by user click\n this.element.addEventListener('click', this.requestPointerLock);\n document.addEventListener('pointerlockchange', this.onPointerLockChange);\n document.addEventListener('mousemove', this.onMouseMove);\n }\n\n disable() {\n if (!this.isEnabled) return;\n this.isEnabled = false;\n\n this.element.removeEventListener('click', this.requestPointerLock);\n document.removeEventListener('pointerlockchange', this.onPointerLockChange);\n document.removeEventListener('mousemove', this.onMouseMove);\n\n if (this.isPointerLocked) document.exitPointerLock();\n }\n\n onChange(listener: MoveListener) {\n this.listeners.push(listener);\n }\n\n /** Remove a previously registered listener. */\n removeListener(listener: MoveListener) {\n this.listeners = this.listeners.filter((l) => l !== listener);\n }\n\n setSensitivity(value: number) {\n this.sensitivity = value;\n }\n\n private requestPointerLock = () => {\n this.element.requestPointerLock();\n };\n\n private onPointerLockChange = () => {\n this.isPointerLocked = document.pointerLockElement === this.element;\n };\n\n private onMouseMove = (e: MouseEvent) => {\n if (!this.isPointerLocked) return;\n\n const dx = e.movementX * this.sensitivity;\n const dy = e.movementY * this.sensitivity;\n\n for (const listener of this.listeners) listener(dx, dy);\n };\n}\n","import { Camera } from './Camera';\nimport {\n MouseWheelControl,\n WheelDirection,\n} from '../controls/Mouse/MouseWheelControl';\nimport { MouseDragControl } from '../controls/Mouse/MouseDragControl';\nimport { MousePointerLockControl } from '../controls/Mouse/MousePointerLockControl';\nimport WebGLCore from './WebGLCore';\n\nexport class Viewport {\n private static zoomInterval = 25;\n\n private wheelControl = new MouseWheelControl();\n private dragControl: MouseDragControl;\n private moveControl: MousePointerLockControl;\n\n private lastZoomTime: number = 0;\n private canvas: HTMLCanvasElement;\n private scale: number = 1;\n private webglCore: WebGLCore | null = null;\n private resizeHandler = () => this.resizeCanvas();\n public camera: Camera;\n\n /**\n * @param canvasOrId - An HTMLCanvasElement or the `id` attribute of one.\n * @param width - Logical viewport width.\n * @param height - Logical viewport height.\n * @param webglCore - Optional WebGLCore instance. When provided, the existing\n * GL context is reused for viewport resize instead of\n * requesting a new one.\n */\n constructor(\n canvasOrId: string | HTMLCanvasElement,\n public width: number,\n public height: number,\n webglCore?: WebGLCore,\n ) {\n this.canvas =\n typeof canvasOrId === 'string'\n ? (document.getElementById(canvasOrId) as HTMLCanvasElement)\n : canvasOrId;\n if (!this.canvas) throw new Error('Canvas not found');\n\n this.webglCore = webglCore ?? null;\n this.camera = new Camera(width, height);\n this.dragControl = new MouseDragControl(this.canvas);\n this.moveControl = new MousePointerLockControl(this.canvas, 0.25);\n\n this.resizeCanvas();\n this.setupControls();\n\n window.addEventListener('resize', this.resizeHandler);\n }\n\n private setupControls() {\n const zoomInterval = Viewport.zoomInterval;\n\n // Camera Zoom\n this.wheelControl.onChange((direction: WheelDirection) => {\n const now = performance.now();\n if (now - this.lastZoomTime < zoomInterval) return;\n\n const zoomDelta = direction === 'up' ? 1 : -1;\n this.camera.zoomBy(zoomDelta);\n\n this.lastZoomTime = now;\n });\n this.wheelControl.enable();\n\n // Drag / pan / rotate\n /* this.dragControl.onChange((dx, dy, button) => {\n const factor = 0.01 * this.camera.zoom;\n\n if (button === 2) {\n // Right click = orbit\n this.camera.rotate(-dx * factor, -dy * factor);\n } else if (button === 0) {\n this.camera.target[0] -= (dx * factor) / this.scale;\n this.camera.target[1] += (dy * factor) / this.scale;\n }\n\n });\n this.dragControl.enable(); */\n\n this.moveControl.onChange((dx, dy) => {\n const factor = 0.01 * this.camera.zoom;\n this.camera.rotate(-dx * factor, -dy * factor);\n });\n this.moveControl.enable();\n\n this.canvas.addEventListener('contextmenu', (e) => e.preventDefault());\n }\n\n public isDraggingCamera(): boolean {\n return this.dragControl.isDragging;\n }\n\n private resizeCanvas() {\n const screenWidth = window.innerWidth;\n const screenHeight = window.innerHeight;\n\n const aspectViewport = this.width / this.height;\n const aspectScreen = screenWidth / screenHeight;\n\n let canvasWidth: number, canvasHeight: number;\n\n if (aspectScreen > aspectViewport) {\n canvasHeight = screenHeight;\n canvasWidth = canvasHeight * aspectViewport;\n } else {\n canvasWidth = screenWidth;\n canvasHeight = canvasWidth / aspectViewport;\n }\n\n this.canvas.width = canvasWidth;\n this.canvas.height = canvasHeight;\n\n this.scale = canvasWidth / this.width;\n\n // Reuse the existing GL context when available, otherwise fall back.\n const gl = this.webglCore\n ? this.webglCore.getRenderingContext()\n : (this.canvas.getContext('webgl2') ?? this.canvas.getContext('webgl'));\n\n if (!gl) throw new Error('WebGL not supported');\n gl.viewport(0, 0, canvasWidth, canvasHeight);\n\n this.camera.setViewport(canvasWidth, canvasHeight);\n }\n\n getCanvas(): HTMLCanvasElement {\n return this.canvas;\n }\n\n getScale(): number {\n return this.scale;\n }\n\n /** Release event listeners. Call when the viewport is no longer needed. */\n dispose() {\n window.removeEventListener('resize', this.resizeHandler);\n this.wheelControl.disable();\n this.dragControl.disable();\n this.moveControl.disable();\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/Core/classes/Renderer.ts","../src/Core/utils/compute-bounds.ts","../src/Core/classes/Mesh.ts","../src/Core/shaders/index.ts","../src/Core/classes/WebGLCore.ts","../src/Core/classes/Skeleton.ts","../src/Core/classes/AnimationClip.ts","../src/Core/utils/create-wire-box.ts"],"sourcesContent":["import { mat4, vec3 } from 'gl-matrix';\nimport { Material, Mesh, Scene, WebGLCore } from '.';\nimport { Viewport } from './Viewport';\nimport { Light } from './Light';\nimport { Vector3 } from '../domain/interfaces/Vectors';\nimport { Model } from './Model';\nimport { Skeleton } from './Skeleton';\nimport { createWireBox } from '../utils/create-wire-box';\n\nexport class Renderer {\n /** Set to `true` to render wireframe bounding boxes for debugging. */\n public debug = false;\n\n // Cached debug materials to avoid per-frame GPU allocations\n private _modelHitboxMaterial: Material | null = null;\n private _meshHitboxMaterial: Material | null = null;\n\n // Cache wire-box debug meshes: recreated only when the bounding box changes.\n private readonly _modelWireBoxCache = new WeakMap<Model, { mesh: Mesh; key: string }>();\n private readonly _meshWireBoxCache = new WeakMap<Mesh, { mesh: Mesh; key: string }>();\n\n /** Pre-allocated identity matrix for world-space hitbox draws. */\n private readonly _identity: mat4 = mat4.create();\n\n /** Cached `gl instanceof WebGL2RenderingContext` — computed once at construction. */\n private readonly _isWebGL2: boolean;\n\n constructor(\n private webglCore: WebGLCore,\n public viewport: Viewport,\n ) {\n const gl = webglCore.getRenderingContext();\n this._isWebGL2 = gl instanceof WebGL2RenderingContext;\n if (gl) gl.enable(gl.DEPTH_TEST);\n }\n\n /** Lazily-created material for model-level hitboxes (red). */\n private get modelHitboxMaterial(): Material {\n if (!this._modelHitboxMaterial) {\n this._modelHitboxMaterial = new Material(this.webglCore);\n this._modelHitboxMaterial.setColorHex('#ff0404ff');\n this._modelHitboxMaterial.unlit = true;\n }\n return this._modelHitboxMaterial;\n }\n\n /** Lazily-created material for mesh-level hitboxes (green). */\n private get meshHitboxMaterial(): Material {\n if (!this._meshHitboxMaterial) {\n this._meshHitboxMaterial = new Material(this.webglCore);\n this._meshHitboxMaterial.setColorHex('#04ff0cff');\n this._meshHitboxMaterial.unlit = true;\n }\n return this._meshHitboxMaterial;\n }\n\n public clearFrame(\n color: [number, number, number, number] = [0.2, 0.5, 0.95, 1],\n ) {\n const gl = this.webglCore.getRenderingContext();\n if (!gl) return;\n\n gl.clearColor(...color);\n gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);\n }\n\n public render(scene: Scene) {\n const gl = this.webglCore.getRenderingContext();\n if (!gl) return;\n\n const models = scene.getModels();\n const lights = scene.getLights();\n const camera = this.viewport.camera;\n\n const viewPosition: vec3 = camera.getComputedPosition();\n this.clearFrame();\n\n const viewMatrix = camera.getViewMatrix() as Float32Array;\n const projMatrix = camera.getProjectionMatrix() as Float32Array;\n\n let activeProgram: WebGLProgram | null = null;\n\n for (const model of models) {\n activeProgram = this.drawModel(\n gl,\n model,\n lights,\n viewPosition,\n viewMatrix,\n projMatrix,\n activeProgram,\n );\n }\n }\n\n private drawModel(\n gl: WebGLRenderingContext,\n model: Model,\n lights: Light[],\n viewPosition: vec3,\n viewMatrix: Float32Array,\n projMatrix: Float32Array,\n activeProgram: WebGLProgram | null,\n ): WebGLProgram | null {\n const modelMatrix = model.getModelMatrix();\n const hasSkeleton = model.skeleton !== null;\n\n for (const mesh of model.meshes) {\n activeProgram = this.drawMesh(\n mesh,\n lights,\n viewPosition,\n modelMatrix,\n viewMatrix,\n projMatrix,\n activeProgram,\n hasSkeleton && mesh.isSkinned ? model : null,\n );\n\n if (this.debug) {\n this.drawHitBoxForMesh(\n mesh,\n modelMatrix,\n viewMatrix,\n projMatrix,\n activeProgram,\n );\n }\n }\n\n // Debug wireframe\n if (this.debug) {\n this.drawHitBox(model, activeProgram);\n }\n\n return activeProgram;\n }\n\n private drawMesh(\n mesh: Mesh,\n lights: Light[],\n viewPosition: vec3,\n modelMatrix: mat4,\n viewMatrix: Float32Array,\n projMatrix: Float32Array,\n activeProgram: WebGLProgram | null,\n skinnedModel: Model | null = null,\n ): WebGLProgram | null {\n const gl = this.webglCore.getRenderingContext();\n if (!gl) return activeProgram;\n if (!mesh.material) return activeProgram;\n\n mesh.initBuffer(this.webglCore);\n\n const { program, uniformLocations } = mesh.material;\n\n if (program !== activeProgram) {\n gl.useProgram(program);\n activeProgram = program;\n\n if (uniformLocations['uView'])\n gl.uniformMatrix4fv(uniformLocations['uView'], false, viewMatrix);\n if (uniformLocations['uProjection'])\n gl.uniformMatrix4fv(uniformLocations['uProjection'], false, projMatrix);\n }\n\n // Use cached WebGL2 check\n const isWebGL2 = this._isWebGL2;\n\n // --- Bind VAO if available ---\n if (isWebGL2 && mesh.buffers?.vao) {\n (gl as unknown as WebGL2RenderingContext).bindVertexArray(\n mesh.buffers.vao,\n );\n } else {\n // --- WebGL1 Fallback ---\n const aPosition = mesh.material.attribLocations['aPosition'];\n if (aPosition !== -1 && mesh.buffers?.vertexBuffer) {\n gl.bindBuffer(gl.ARRAY_BUFFER, mesh.buffers.vertexBuffer);\n gl.enableVertexAttribArray(aPosition);\n gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 0, 0);\n }\n\n const aNormal = mesh.material.attribLocations['aNormal'];\n if (aNormal !== -1 && mesh.buffers?.normalBuffer) {\n gl.bindBuffer(gl.ARRAY_BUFFER, mesh.buffers.normalBuffer);\n gl.enableVertexAttribArray(aNormal);\n gl.vertexAttribPointer(aNormal, 3, gl.FLOAT, false, 0, 0);\n }\n\n const aTexCoord = mesh.material.attribLocations['aTexCoord'];\n if (aTexCoord !== -1 && mesh.buffers?.texCoordBuffer) {\n gl.bindBuffer(gl.ARRAY_BUFFER, mesh.buffers.texCoordBuffer);\n gl.enableVertexAttribArray(aTexCoord);\n gl.vertexAttribPointer(aTexCoord, 2, gl.FLOAT, false, 0, 0);\n }\n\n // Skinning attributes (joint indices + weights)\n const aJointIndices = mesh.material.attribLocations['aJointIndices'];\n if (aJointIndices !== -1 && mesh.buffers?.jointIndexBuffer) {\n gl.bindBuffer(gl.ARRAY_BUFFER, mesh.buffers.jointIndexBuffer);\n gl.enableVertexAttribArray(aJointIndices);\n gl.vertexAttribPointer(aJointIndices, 4, gl.FLOAT, false, 0, 0);\n }\n\n const aJointWeights = mesh.material.attribLocations['aJointWeights'];\n if (aJointWeights !== -1 && mesh.buffers?.jointWeightBuffer) {\n gl.bindBuffer(gl.ARRAY_BUFFER, mesh.buffers.jointWeightBuffer);\n gl.enableVertexAttribArray(aJointWeights);\n gl.vertexAttribPointer(aJointWeights, 4, gl.FLOAT, false, 0, 0);\n }\n }\n\n // Material uniforms\n mesh.material.apply(gl, lights, viewPosition as Vector3);\n\n // ── Skinning uniforms ─────────────────────────────────────\n const uUseSkinning = uniformLocations['uUseSkinning'];\n const skeleton: Skeleton | null =\n (skinnedModel?.skeleton as Skeleton | undefined) ?? null;\n if (skeleton && mesh.isSkinned) {\n if (uUseSkinning) gl.uniform1i(uUseSkinning, 1);\n const uJointMatrices = uniformLocations['uJointMatrices[0]'];\n if (uJointMatrices) {\n gl.uniformMatrix4fv(uJointMatrices, false, skeleton.jointMatrices);\n }\n } else {\n if (uUseSkinning) gl.uniform1i(uUseSkinning, 0);\n }\n\n // Model transform\n const uModel = mesh.material.uniformLocations['uModel'];\n if (uModel) gl.uniformMatrix4fv(uModel, false, modelMatrix as Float32Array);\n\n // Draw\n if (mesh.buffers?.indexBuffer && mesh.indices) {\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh.buffers.indexBuffer);\n const type =\n mesh.indices instanceof Uint32Array\n ? gl.UNSIGNED_INT\n : gl.UNSIGNED_SHORT;\n gl.drawElements(mesh.mode, mesh.indices.length, type, 0);\n } else {\n gl.drawArrays(mesh.mode, 0, mesh.vertices.length / 3);\n }\n\n // Cleanup\n if (isWebGL2 && mesh.buffers?.vao) {\n (gl as unknown as WebGL2RenderingContext).bindVertexArray(null);\n } else {\n gl.bindBuffer(gl.ARRAY_BUFFER, null);\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n }\n\n return activeProgram;\n }\n\n public drawHitBox(\n model: Model,\n activeProgram: WebGLProgram | null,\n ) {\n const bbox = model.boundingBox;\n const key = `${bbox.min[0]},${bbox.min[1]},${bbox.min[2]},${bbox.max[0]},${bbox.max[1]},${bbox.max[2]}`;\n const cached = this._modelWireBoxCache.get(model);\n let hitboxMesh: Mesh;\n if (!cached || cached.key !== key) {\n hitboxMesh = createWireBox(bbox.min, bbox.max, this.modelHitboxMaterial);\n hitboxMesh.isCollidable = false;\n this._modelWireBoxCache.set(model, { mesh: hitboxMesh, key });\n } else {\n hitboxMesh = cached.mesh;\n }\n\n const camera = this.viewport.camera;\n const viewMatrix = camera.getViewMatrix() as Float32Array;\n const projMatrix = camera.getProjectionMatrix() as Float32Array;\n\n this.drawMesh(\n hitboxMesh,\n [],\n camera.position,\n this._identity,\n viewMatrix,\n projMatrix,\n activeProgram,\n );\n }\n\n private drawHitBoxForMesh(\n mesh: Mesh,\n modelMatrix: mat4,\n viewMatrix: Float32Array,\n projMatrix: Float32Array,\n activeProgram: WebGLProgram | null,\n ) {\n if (!mesh.boundingBox) return;\n\n const { min, max } = mesh.boundingBox;\n const key = `${min[0]},${min[1]},${min[2]},${max[0]},${max[1]},${max[2]}`;\n const cached = this._meshWireBoxCache.get(mesh);\n let wireBox: Mesh;\n if (!cached || cached.key !== key) {\n wireBox = createWireBox(min, max, this.meshHitboxMaterial);\n wireBox.isCollidable = false;\n this._meshWireBoxCache.set(mesh, { mesh: wireBox, key });\n } else {\n wireBox = cached.mesh;\n }\n\n const camera = this.viewport.camera;\n this.drawMesh(\n wireBox,\n [],\n camera.position,\n modelMatrix,\n viewMatrix,\n projMatrix,\n activeProgram,\n );\n }\n}\n","import { AABB } from '../domain/value-objects/Collider';\n\n/**\n * Compute the axis-aligned bounding box (AABB) from a flat Float32Array of vertices.\n * Each vertex is expected to be 3 consecutive floats: [x, y, z, ...].\n */\nexport function computeVertexBounds(vertices: Float32Array): AABB {\n if (!vertices || vertices.length === 0) {\n return { min: [0, 0, 0], max: [0, 0, 0] };\n }\n\n let minX = Infinity,\n minY = Infinity,\n minZ = Infinity;\n let maxX = -Infinity,\n maxY = -Infinity,\n maxZ = -Infinity;\n\n for (let i = 0; i < vertices.length; i += 3) {\n const x = vertices[i];\n const y = vertices[i + 1];\n const z = vertices[i + 2];\n\n if (x < minX) minX = x;\n if (y < minY) minY = y;\n if (z < minZ) minZ = z;\n\n if (x > maxX) maxX = x;\n if (y > maxY) maxY = y;\n if (z > maxZ) maxZ = z;\n }\n\n return {\n min: [minX, minY, minZ],\n max: [maxX, maxY, maxZ],\n };\n}\n","import WebGLCore from './WebGLCore';\nimport { Material } from './Material';\nimport { AABB } from '../domain/value-objects/Collider';\nimport { computeVertexBounds } from '../utils/compute-bounds';\n\n/** WebGL draw-mode constants. */\nexport const GL_LINES = 0x0001;\nexport const GL_TRIANGLES = 0x0004;\n\nexport const INITIAL_BOUNDING_BOX: AABB = { min: [0, 0, 0], max: [0, 0, 0] };\n\n/**\n * A single renderable mesh: vertex data, normals, indices, a material, and an\n * optional bounding box used for collision detection.\n *\n * For skinned meshes, set {@link jointIndices} and {@link jointWeights} to\n * enable GPU skeletal animation.\n */\nexport class Mesh {\n name: string;\n\n vertices: Float32Array;\n\n normals: Float32Array;\n\n texCoords: Float32Array;\n\n indices: Uint16Array | Uint32Array | null;\n\n mode: number;\n\n material: Material;\n\n // ── Skinning data (optional) ─────────────────────────────────\n /** Per-vertex joint indices (vec4 per vertex, 4 influences). */\n jointIndices: Float32Array | null = null;\n\n /** Per-vertex joint weights (vec4 per vertex, 4 influences). */\n jointWeights: Float32Array | null = null;\n\n // WebGL buffers aggregate\n buffers: MeshBuffers | null = null;\n\n boundingBox: AABB = INITIAL_BOUNDING_BOX;\n\n isCollidable = true;\n\n isInitialized = false;\n\n constructor(\n name: string,\n vertices: Float32Array,\n normals: Float32Array,\n material: Material,\n texCoords: Float32Array = new Float32Array(),\n indices: Uint16Array | Uint32Array | null = null,\n ) {\n this.mode = GL_TRIANGLES;\n this.name = name;\n this.normals = normals;\n this.indices = indices;\n this.vertices = vertices;\n this.texCoords = texCoords;\n this.material = material;\n\n this.computeBounds();\n }\n\n setMode(newMode: number) {\n this.mode = newMode;\n }\n\n /** Whether this mesh has skinning data for skeletal animation. */\n get isSkinned(): boolean {\n return this.jointIndices !== null && this.jointWeights !== null;\n }\n\n computeBounds() {\n this.boundingBox = computeVertexBounds(this.vertices);\n }\n\n clone(): Mesh {\n const clonedMesh = new Mesh(\n this.name,\n new Float32Array(this.vertices),\n new Float32Array(this.normals),\n this.material, // shallow ref — call Material.clone() if independent material is needed\n new Float32Array(this.texCoords),\n this.indices\n ? this.indices instanceof Uint16Array\n ? new Uint16Array(this.indices)\n : new Uint32Array(this.indices)\n : null,\n );\n clonedMesh.setMode(this.mode);\n clonedMesh.isCollidable = this.isCollidable;\n if (this.jointIndices)\n clonedMesh.jointIndices = new Float32Array(this.jointIndices);\n if (this.jointWeights)\n clonedMesh.jointWeights = new Float32Array(this.jointWeights);\n return clonedMesh;\n }\n\n /** Initialize GPU buffers safely */\n public initBuffer(webglCore: WebGLCore) {\n const gl = webglCore.getRenderingContext();\n\n if (!gl) {\n console.warn(\n `[Mesh:${this.name}] GL context not available, skipping buffer init.`,\n );\n return;\n }\n if (this.isInitialized) return;\n\n this.buffers = new MeshBuffers();\n this.buffers.init(gl as WebGL2RenderingContext, this);\n this.isInitialized = true;\n }\n\n /** Dispose of GPU buffers safely */\n public dispose(webglCore: WebGLCore) {\n const gl = webglCore.getRenderingContext();\n if (!gl || !this.buffers) return;\n\n this.buffers.dispose(gl as WebGL2RenderingContext);\n this.buffers = null;\n this.isInitialized = false;\n }\n}\n\nexport class MeshBuffers {\n vao: WebGLVertexArrayObject | null = null;\n vertexBuffer: WebGLBuffer | null = null;\n normalBuffer: WebGLBuffer | null = null;\n texCoordBuffer: WebGLBuffer | null = null;\n indexBuffer: WebGLBuffer | null = null;\n jointIndexBuffer: WebGLBuffer | null = null;\n jointWeightBuffer: WebGLBuffer | null = null;\n\n public init(gl: WebGLRenderingContext, mesh: Mesh) {\n if (!gl) throw new Error('Cannot init MeshBuffers: invalid GL context');\n\n const isWebGL2 = gl instanceof WebGL2RenderingContext;\n const gl2 = isWebGL2 ? (gl as unknown as WebGL2RenderingContext) : null;\n\n if (gl2) {\n this.vao = gl2.createVertexArray();\n gl2.bindVertexArray(this.vao);\n }\n\n // --- Attribute layout ---\n // Attribute locations must match the shader (aPosition=0, aNormal=1, aTexCoord=2).\n // Look them up from the mesh's material program so the VAO captures the bindings.\n const program = mesh.material?.program;\n const aPosition = program ? gl.getAttribLocation(program, 'aPosition') : 0;\n const aNormal = program ? gl.getAttribLocation(program, 'aNormal') : 1;\n const aTexCoord = program ? gl.getAttribLocation(program, 'aTexCoord') : 2;\n\n // Vertex buffer\n this.vertexBuffer = gl.createBuffer();\n if (!this.vertexBuffer) throw new Error('Failed to create vertex buffer');\n gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.STATIC_DRAW);\n if (aPosition !== -1) {\n gl.enableVertexAttribArray(aPosition);\n gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 0, 0);\n }\n\n // Normal buffer\n this.normalBuffer = gl.createBuffer();\n if (!this.normalBuffer) throw new Error('Failed to create normal buffer');\n gl.bindBuffer(gl.ARRAY_BUFFER, this.normalBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, mesh.normals, gl.STATIC_DRAW);\n if (aNormal !== -1) {\n gl.enableVertexAttribArray(aNormal);\n gl.vertexAttribPointer(aNormal, 3, gl.FLOAT, false, 0, 0);\n }\n\n // TexCoord buffer\n if (mesh.texCoords.length > 0) {\n this.texCoordBuffer = gl.createBuffer();\n if (!this.texCoordBuffer)\n throw new Error('Failed to create texCoord buffer');\n gl.bindBuffer(gl.ARRAY_BUFFER, this.texCoordBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, mesh.texCoords, gl.STATIC_DRAW);\n if (aTexCoord !== -1) {\n gl.enableVertexAttribArray(aTexCoord);\n gl.vertexAttribPointer(aTexCoord, 2, gl.FLOAT, false, 0, 0);\n }\n }\n\n // Index buffer\n if (mesh.indices && mesh.indices.length > 0) {\n this.indexBuffer = gl.createBuffer();\n if (!this.indexBuffer) throw new Error('Failed to create index buffer');\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);\n gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW);\n }\n\n // Joint indices buffer (skinning)\n const aJointIndices = program\n ? gl.getAttribLocation(program, 'aJointIndices')\n : -1;\n if (\n mesh.jointIndices &&\n mesh.jointIndices.length > 0 &&\n aJointIndices !== -1\n ) {\n this.jointIndexBuffer = gl.createBuffer();\n if (!this.jointIndexBuffer)\n throw new Error('Failed to create joint index buffer');\n gl.bindBuffer(gl.ARRAY_BUFFER, this.jointIndexBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, mesh.jointIndices, gl.STATIC_DRAW);\n gl.enableVertexAttribArray(aJointIndices);\n gl.vertexAttribPointer(aJointIndices, 4, gl.FLOAT, false, 0, 0);\n }\n\n // Joint weights buffer (skinning)\n const aJointWeights = program\n ? gl.getAttribLocation(program, 'aJointWeights')\n : -1;\n if (\n mesh.jointWeights &&\n mesh.jointWeights.length > 0 &&\n aJointWeights !== -1\n ) {\n this.jointWeightBuffer = gl.createBuffer();\n if (!this.jointWeightBuffer)\n throw new Error('Failed to create joint weight buffer');\n gl.bindBuffer(gl.ARRAY_BUFFER, this.jointWeightBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, mesh.jointWeights, gl.STATIC_DRAW);\n gl.enableVertexAttribArray(aJointWeights);\n gl.vertexAttribPointer(aJointWeights, 4, gl.FLOAT, false, 0, 0);\n }\n\n if (gl2) {\n gl2.bindVertexArray(null);\n }\n }\n\n public dispose(gl: WebGL2RenderingContext) {\n if (!gl) {\n console.warn('Cannot dispose MeshBuffers: invalid GL context');\n return;\n }\n\n const isWebGL2 = gl instanceof WebGL2RenderingContext;\n\n if (this.vertexBuffer) gl.deleteBuffer(this.vertexBuffer);\n if (this.normalBuffer) gl.deleteBuffer(this.normalBuffer);\n if (this.texCoordBuffer) gl.deleteBuffer(this.texCoordBuffer);\n if (this.indexBuffer) gl.deleteBuffer(this.indexBuffer);\n if (this.jointIndexBuffer) gl.deleteBuffer(this.jointIndexBuffer);\n if (this.jointWeightBuffer) gl.deleteBuffer(this.jointWeightBuffer);\n\n if (isWebGL2 && this.vao) {\n (gl as unknown as WebGL2RenderingContext).deleteVertexArray(this.vao);\n }\n\n this.vertexBuffer =\n this.normalBuffer =\n this.texCoordBuffer =\n this.indexBuffer =\n this.jointIndexBuffer =\n this.jointWeightBuffer =\n this.vao =\n null;\n }\n}\n","// GLSL shader sources inlined as TypeScript strings so the package can\n// be built with tsup without requiring Vite's ?raw loader.\n\nexport const vsSource = /* glsl */ `\n#define MAX_JOINTS 128\n\nattribute vec3 aPosition;\nattribute vec3 aNormal;\nattribute vec2 aTexCoord;\n\n// ── Skinning attributes (vec4: up to 4 joint influences per vertex) ──\nattribute vec4 aJointIndices;\nattribute vec4 aJointWeights;\n\nuniform mat4 uModel;\nuniform mat4 uView;\nuniform mat4 uProjection;\n\n// ── Skinning uniforms ──\nuniform bool uUseSkinning;\nuniform mat4 uJointMatrices[MAX_JOINTS];\n\nvarying vec3 vNormal;\nvarying vec3 vPosition;\nvarying vec2 vTexCoord;\n\nvoid main() {\n vTexCoord = aTexCoord;\n\n vec4 pos = vec4(aPosition, 1.0);\n vec3 norm = aNormal;\n\n if (uUseSkinning) {\n mat4 skinMat =\n aJointWeights.x * uJointMatrices[int(aJointIndices.x)] +\n aJointWeights.y * uJointMatrices[int(aJointIndices.y)] +\n aJointWeights.z * uJointMatrices[int(aJointIndices.z)] +\n aJointWeights.w * uJointMatrices[int(aJointIndices.w)];\n pos = skinMat * pos;\n norm = mat3(skinMat) * norm;\n }\n\n vNormal = mat3(uModel) * norm;\n\n vec4 worldPosition = uModel * pos;\n vPosition = worldPosition.xyz;\n gl_Position = uProjection * uView * worldPosition;\n}\n`;\n\nexport const fsSource = /* glsl */ `\nprecision mediump float;\n\n#define MAX_LIGHTS 5\n\nvarying vec3 vNormal;\nvarying vec3 vPosition;\nvarying vec2 vTexCoord;\n\nuniform vec3 uLightDirection[MAX_LIGHTS];\nuniform vec3 uLightColor[MAX_LIGHTS];\nuniform float uLightIntensity[MAX_LIGHTS];\nuniform int uLightType[MAX_LIGHTS]; // 0=directional, 1=point, 2=ambient\nuniform int uLightCount;\nuniform vec3 uLightPosition[MAX_LIGHTS];\nuniform float uLightConstant[MAX_LIGHTS];\nuniform float uLightLinear[MAX_LIGHTS];\nuniform float uLightQuadratic[MAX_LIGHTS];\n\nuniform vec4 uColor;\nuniform bool uUnlit;\nuniform bool uUseTexture;\nuniform sampler2D uTexture;\n\nuniform vec3 uViewPosition;\nuniform float uShininess;\nuniform vec3 uSpecularColor;\n\nvoid main() {\n vec4 baseColor = uColor;\n if (uUseTexture) {\n baseColor *= texture2D(uTexture, vTexCoord);\n }\n\n if (uUnlit) {\n gl_FragColor = baseColor;\n return;\n }\n\n vec3 norm = normalize(vNormal);\n vec3 totalDiffuse = vec3(0.0);\n vec3 totalAmbient = vec3(0.0);\n vec3 totalSpecular = vec3(0.0);\n\n vec3 viewDir = normalize(uViewPosition - vPosition);\n\n for (int i = 0; i < MAX_LIGHTS; i++) {\n if (i >= uLightCount) break;\n\n if (uLightType[i] == 2) {\n totalAmbient += uLightColor[i] * uLightIntensity[i];\n } else {\n vec3 lightDir;\n float attenuation = 1.0;\n\n if (uLightType[i] == 0) {\n // Directional light\n lightDir = normalize(-uLightDirection[i]);\n } else {\n // Point light\n vec3 lightVec = uLightPosition[i] - vPosition;\n float distance = length(lightVec);\n lightDir = normalize(lightVec);\n attenuation = 1.0 / (\n uLightConstant[i] +\n uLightLinear[i] * distance +\n uLightQuadratic[i] * distance * distance\n );\n }\n\n // Diffuse\n float diff = max(dot(norm, lightDir), 0.0);\n totalDiffuse += diff * uLightColor[i] * uLightIntensity[i] * attenuation;\n\n // Specular (Blinn-Phong) — softer, more natural highlights\n vec3 halfDir = normalize(lightDir + viewDir);\n float spec = pow(max(dot(norm, halfDir), 0.0), uShininess);\n totalSpecular += spec * uSpecularColor * uLightIntensity[i] * attenuation;\n }\n }\n\n vec3 lightingResult =\n totalAmbient * baseColor.rgb +\n totalDiffuse * baseColor.rgb +\n totalSpecular;\n\n gl_FragColor = vec4(lightingResult, baseColor.a);\n}\n`;\n","/* eslint-disable @typescript-eslint/no-unsafe-argument */\nimport { vsSource, fsSource } from '../shaders/index';\n\nexport type RenderCallback = (\n gl: WebGLRenderingContext,\n program: WebGLProgram,\n) => void;\n\nexport class WebGLCore {\n public gl: WebGL2RenderingContext | WebGLRenderingContext;\n public program: WebGLProgram;\n public canvas: HTMLCanvasElement;\n public isWebGL2: boolean;\n\n /**\n * Initialise the WebGL rendering core.\n *\n * @param canvasOrId - An `HTMLCanvasElement` or the DOM `id` of one.\n * Defaults to `'glcanvas'`.\n */\n constructor(canvasOrId: string | HTMLCanvasElement = 'glcanvas') {\n const canvas =\n typeof canvasOrId === 'string'\n ? (document.getElementById(canvasOrId) as HTMLCanvasElement | null)\n : canvasOrId;\n if (!canvas) throw new Error('Canvas not found');\n this.canvas = canvas;\n\n canvas.width = window.innerWidth;\n canvas.height = window.innerHeight;\n\n this.gl = (canvas.getContext('webgl2') ?? canvas.getContext('webgl')) as\n | WebGL2RenderingContext\n | WebGLRenderingContext;\n\n if (!this.gl) throw new Error('WebGL not supported in this browser!');\n\n this.isWebGL2 = this.gl instanceof WebGL2RenderingContext;\n this.gl.viewport(0, 0, canvas.width, canvas.height);\n\n const program = this.createProgram(this.gl);\n if (!program) throw new Error('Failed to create program');\n this.program = program as unknown as WebGLProgram;\n }\n\n public getProgram(): WebGLProgram {\n return this.program;\n }\n\n public getRenderingContext(): WebGLRenderingContext {\n return this.gl;\n }\n\n private createProgram(gl: WebGLRenderingContext): WebGLProgram | null {\n const vertexShader = this.compileShader(gl, gl.VERTEX_SHADER, vsSource);\n const fragmentShader = this.compileShader(gl, gl.FRAGMENT_SHADER, fsSource);\n\n if (!vertexShader || !fragmentShader)\n throw new Error('Failed to create shaders');\n\n const program = gl.createProgram();\n if (!program) return null;\n\n gl.attachShader(program, vertexShader);\n gl.attachShader(program, fragmentShader);\n gl.linkProgram(program);\n\n // Clean up shader objects\n gl.deleteShader(vertexShader);\n gl.deleteShader(fragmentShader);\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n console.error(gl.getProgramInfoLog(program));\n throw new Error(gl.getProgramInfoLog(program) || 'Program link error');\n }\n\n return program;\n }\n\n private compileShader(\n gl: WebGLRenderingContext,\n type: number,\n source: string,\n ): WebGLShader | null {\n const shader = gl.createShader(type);\n if (!shader) return null;\n\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n console.error(gl.getShaderInfoLog(shader));\n gl.deleteShader(shader);\n throw new Error(gl.getShaderInfoLog(shader) || 'Shader compile error');\n }\n return shader;\n }\n\n public resize(width: number, height: number) {\n this.canvas.width = width;\n this.canvas.height = height;\n this.gl.viewport(0, 0, width, height);\n }\n\n dispose() {\n const { gl, program } = this;\n if (program) gl.deleteProgram(program);\n }\n}\n\nexport default WebGLCore;\n","import { mat4, quat, vec3 } from 'gl-matrix';\n\n/** Maximum number of joints supported per skeleton (must match shader). */\nexport const MAX_JOINTS = 128;\n\n/**\n * Describes a single joint (bone) inside a {@link Skeleton}.\n *\n * Each joint stores its default bind-pose transform (translation, rotation,\n * scale) and the inverse bind matrix used to transform vertices from model\n * space into joint-local space.\n */\nexport interface Joint {\n /** Human-readable name (e.g. \"Hips\", \"LeftArm\"). */\n name: string;\n /** Original glTF node index this joint references. */\n nodeIndex: number;\n /** Index of the parent joint in the skeleton's joint array (-1 = root). */\n parentIndex: number;\n /** Bind-pose translation. */\n localTranslation: vec3;\n /** Bind-pose rotation (quaternion). */\n localRotation: quat;\n /** Bind-pose scale. */\n localScale: vec3;\n /** Inverse bind matrix from the glTF skin. */\n inverseBindMatrix: mat4;\n}\n\n/**\n * Per-joint local transform produced by animation sampling.\n * Any undefined component falls back to the bind-pose value.\n */\nexport interface JointPose {\n t?: vec3;\n r?: quat;\n s?: vec3;\n}\n\n/**\n * A skeleton representing a hierarchy of {@link Joint}s.\n *\n * Call {@link computeJointMatrices} each frame with the current animation pose\n * to produce a flat `Float32Array` of `mat4`s ready for upload as a shader\n * uniform.\n */\nexport class Skeleton {\n /** Ordered joint list (parent always precedes child). */\n public readonly joints: Joint[];\n\n /**\n * Flat `Float32Array` of `joints.length` column-major `mat4` values.\n * Updated by {@link computeJointMatrices} — upload directly to\n * `uJointMatrices[0]`.\n */\n public readonly jointMatrices: Float32Array;\n\n /**\n * Global transform of the non-joint ancestor nodes above the skeleton\n * root. In many exported models the armature sits under a scene-root\n * node that carries scale / rotation (e.g. cm → m conversion). This\n * transform is pre-multiplied into root-joint globals so that\n * `global * inverseBindMatrix` evaluates to identity in the bind pose.\n */\n public readonly rootTransform: mat4;\n\n // ── Pre-allocated scratch buffers ──\n /** Per-joint global transform matrices, reused each frame (allocated once in constructor). */\n private readonly _globals: mat4[];\n private readonly _local: mat4 = mat4.create();\n private readonly _final: mat4 = mat4.create();\n\n constructor(joints: Joint[], rootTransform?: mat4) {\n if (joints.length > MAX_JOINTS) {\n console.warn(\n `[Skeleton] ${joints.length} joints exceeds MAX_JOINTS (${MAX_JOINTS}). ` +\n 'Extra joints will be ignored by the shader.',\n );\n }\n this.joints = joints;\n this.jointMatrices = new Float32Array(joints.length * 16);\n this.rootTransform = rootTransform ?? mat4.create();\n // Pre-allocate per-joint globals and scratch matrices — reused every frame.\n this._globals = Array.from({ length: joints.length }, () => mat4.create());\n }\n\n /** Number of joints in the skeleton. */\n get jointCount(): number {\n return this.joints.length;\n }\n\n /**\n * Walk the joint hierarchy, composing global transforms, then multiply by\n * each joint's inverse-bind matrix. The result is stored in\n * {@link jointMatrices} ready for shader upload.\n *\n * @param animatedPoses - Optional per-joint local transforms from an\n * {@link AnimationClip}. Map keys are **joint array indices** (not glTF\n * node indices).\n */\n computeJointMatrices(animatedPoses?: Map<number, JointPose>): void {\n const local = this._local;\n const final = this._final;\n const globals = this._globals;\n\n for (let i = 0; i < this.joints.length; i++) {\n const joint = this.joints[i];\n const pose = animatedPoses?.get(i);\n\n const t = pose?.t ?? joint.localTranslation;\n const r = pose?.r ?? joint.localRotation;\n const s = pose?.s ?? joint.localScale;\n\n mat4.fromRotationTranslationScale(local, r, t, s);\n\n if (joint.parentIndex >= 0) {\n mat4.multiply(globals[i], globals[joint.parentIndex], local);\n } else {\n // Root joint — include the non-joint ancestor transform\n mat4.multiply(globals[i], this.rootTransform, local);\n }\n\n // final = global * inverseBindMatrix\n mat4.multiply(final, globals[i], joint.inverseBindMatrix);\n this.jointMatrices.set(final as unknown as Float32Array, i * 16);\n }\n }\n\n /**\n * Create a deep clone of this skeleton (useful when instancing models).\n */\n clone(): Skeleton {\n const clonedJoints: Joint[] = this.joints.map((j) => ({\n name: j.name,\n nodeIndex: j.nodeIndex,\n parentIndex: j.parentIndex,\n localTranslation: vec3.clone(j.localTranslation),\n localRotation: quat.clone(j.localRotation),\n localScale: vec3.clone(j.localScale),\n inverseBindMatrix: mat4.clone(j.inverseBindMatrix),\n }));\n return new Skeleton(clonedJoints, mat4.clone(this.rootTransform));\n }\n}\n","import { quat, vec3 } from 'gl-matrix';\nimport type { JointPose } from './Skeleton';\n\n// ── Module-level scratch buffers ──\n// Reused across all AnimationClip.sample() calls. Safe because sample() is\n// synchronous and scratch values are copied into pose storage before reuse.\nconst _sv0Vec3 = vec3.create();\nconst _sv1Vec3 = vec3.create();\nconst _sOutVec3 = vec3.create();\nconst _sv0Quat = quat.create();\nconst _sv1Quat = quat.create();\nconst _sOutQuat = quat.create();\n\n// ─── Types ──────────────────────────────────────────────────────\n\n/** Interpolation mode as defined by glTF 2.0. */\nexport type InterpolationMode = 'STEP' | 'LINEAR' | 'CUBICSPLINE';\n\n/** Which transform component the channel drives. */\nexport type AnimationPath = 'translation' | 'rotation' | 'scale';\n\n/**\n * Stores the raw keyframe data for one animated property and performs\n * interpolation between keyframes.\n */\nexport interface AnimationSampler {\n /** Keyframe timestamps (seconds). */\n times: Float32Array;\n /** Flattened keyframe output values (3 or 4 components per key). */\n values: Float32Array;\n /** Interpolation mode (default `LINEAR`). */\n interpolation: InterpolationMode;\n}\n\n/**\n * Links a {@link AnimationSampler} to a specific joint property.\n */\nexport interface AnimationChannel {\n /** Index into the owning {@link Skeleton}'s joint array. */\n jointIndex: number;\n /** Transform component this channel drives. */\n path: AnimationPath;\n /** The sampler that holds keyframe data. */\n sampler: AnimationSampler;\n}\n\n// ─── AnimationClip ──────────────────────────────────────────────\n\n/**\n * A named animation clip containing one or more {@link AnimationChannel}s.\n *\n * Call {@link update} each frame to advance the playhead, then {@link sample}\n * to obtain per-joint local transforms that feed into\n * `Skeleton.computeJointMatrices()`.\n *\n * ```ts\n * clip.play();\n * // game loop:\n * clip.update(deltaTime);\n * const poses = clip.sample();\n * skeleton.computeJointMatrices(poses);\n * ```\n */\nexport class AnimationClip {\n /** Human-readable name (e.g. \"Walk\", \"Idle\"). */\n public readonly name: string;\n\n /** All channels in this clip. */\n public readonly channels: AnimationChannel[];\n\n /** Total duration in seconds (derived from the maximum keyframe time). */\n public readonly duration: number;\n\n /** Current playback time in seconds. */\n public currentTime = 0;\n\n /** Whether the clip loops when it reaches the end. */\n public loop = true;\n\n /** Playback speed multiplier (1 = normal, 2 = double, −1 = reverse). */\n public speed = 1;\n\n /** Whether the clip is currently advancing. */\n public playing = false;\n\n /**\n * Per-joint pose objects reused across frames to avoid per-frame allocations.\n * The vec3/quat inside each entry are also pre-allocated on first use.\n */\n private readonly _posePool = new Map<number, JointPose>();\n\n constructor(name: string, channels: AnimationChannel[], duration: number) {\n this.name = name;\n this.channels = channels;\n this.duration = duration;\n }\n\n /** Start / resume playback. */\n play(): void {\n this.playing = true;\n }\n\n /** Pause playback (keeps current time). */\n pause(): void {\n this.playing = false;\n }\n\n /** Stop and rewind to the beginning. */\n stop(): void {\n this.playing = false;\n this.currentTime = 0;\n }\n\n /** Rewind to the beginning without changing play state. */\n reset(): void {\n this.currentTime = 0;\n }\n\n /**\n * Advance the playhead by `deltaTime` seconds (respects {@link speed}).\n * Automatically loops or clamps depending on {@link loop}.\n */\n update(deltaTime: number): void {\n if (!this.playing || this.duration <= 0) return;\n\n this.currentTime += deltaTime * this.speed;\n\n if (this.loop) {\n this.currentTime =\n ((this.currentTime % this.duration) + this.duration) % this.duration;\n } else {\n if (this.currentTime >= this.duration) {\n this.currentTime = this.duration;\n this.playing = false;\n } else if (this.currentTime < 0) {\n this.currentTime = 0;\n this.playing = false;\n }\n }\n }\n\n /**\n * Sample every channel at the current playhead and write per-joint local\n * transforms into `out` (or a newly created map if none is provided).\n *\n * Pass a persistent `Map` to avoid allocating a new one every frame.\n */\n sample(out?: Map<number, JointPose>): Map<number, JointPose> {\n const result = out ?? new Map<number, JointPose>();\n if (out) out.clear();\n\n for (const channel of this.channels) {\n // Reuse the JointPose object for this joint from the pool.\n let entry = this._posePool.get(channel.jointIndex);\n if (!entry) {\n entry = {};\n this._posePool.set(channel.jointIndex, entry);\n }\n result.set(channel.jointIndex, entry);\n\n // sampleChannel writes into a module-level scratch buffer.\n // Copy the result into the pre-allocated fields of the pose entry.\n const value = sampleChannel(channel, this.currentTime);\n switch (channel.path) {\n case 'translation':\n if (!entry.t) entry.t = vec3.create();\n vec3.copy(entry.t, value as vec3);\n break;\n case 'rotation':\n if (!entry.r) entry.r = quat.create();\n quat.copy(entry.r, value as quat);\n break;\n case 'scale':\n if (!entry.s) entry.s = vec3.create();\n vec3.copy(entry.s, value as vec3);\n break;\n }\n }\n\n return result;\n }\n\n /**\n * Create an independent copy of this clip (shares the underlying sampler\n * data but has its own playback state).\n */\n clone(): AnimationClip {\n const copy = new AnimationClip(this.name, this.channels, this.duration);\n copy.loop = this.loop;\n copy.speed = this.speed;\n return copy;\n }\n}\n\n// ── Sampling helpers ───────────────────────────────────────────────\n\n/** Write `numComponents` floats from `values` at `index * numComponents` into `out`. */\nfunction readValueInto(\n values: Float32Array,\n index: number,\n numComponents: number,\n out: vec3 | quat,\n): void {\n const off = index * numComponents;\n out[0] = values[off];\n out[1] = values[off + 1];\n out[2] = values[off + 2];\n if (numComponents === 4) out[3] = values[off + 3];\n}\n\n/**\n * Sample a single channel at the given time. Writes the result into a\n * module-level scratch buffer and returns a reference to it.\n * The caller must copy the value before the next sampleChannel invocation.\n */\nfunction sampleChannel(channel: AnimationChannel, time: number): vec3 | quat {\n const { sampler, path } = channel;\n const { times, values, interpolation } = sampler;\n const numComponents = path === 'rotation' ? 4 : 3;\n const outScratch: vec3 | quat = numComponents === 4 ? _sOutQuat : _sOutVec3;\n\n // Edge cases — clamp to first / last keyframe\n if (times.length === 0) {\n if (numComponents === 4) quat.identity(outScratch as quat);\n else vec3.set(outScratch as vec3, 0, 0, 0);\n return outScratch;\n }\n if (time <= times[0]) {\n readValueInto(values, 0, numComponents, outScratch);\n return outScratch;\n }\n if (time >= times[times.length - 1]) {\n readValueInto(values, times.length - 1, numComponents, outScratch);\n return outScratch;\n }\n\n // Binary search for the surrounding keyframe pair\n let lo = 0;\n let hi = times.length - 1;\n while (lo < hi - 1) {\n const mid = (lo + hi) >>> 1;\n if (times[mid] <= time) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n\n const t0 = times[lo];\n const t1 = times[hi];\n const factor = (time - t0) / (t1 - t0);\n\n const v0Scratch: vec3 | quat = numComponents === 4 ? _sv0Quat : _sv0Vec3;\n const v1Scratch: vec3 | quat = numComponents === 4 ? _sv1Quat : _sv1Vec3;\n readValueInto(values, lo, numComponents, v0Scratch);\n readValueInto(values, hi, numComponents, v1Scratch);\n\n if (interpolation === 'STEP') {\n // STEP: return v0 unchanged\n readValueInto(values, lo, numComponents, outScratch);\n return outScratch;\n }\n\n // LINEAR (or fallback for CUBICSPLINE — true cubic not yet implemented)\n if (path === 'rotation') {\n quat.slerp(outScratch as quat, v0Scratch as quat, v1Scratch as quat, factor);\n return outScratch;\n }\n\n vec3.lerp(outScratch as vec3, v0Scratch as vec3, v1Scratch as vec3, factor);\n return outScratch;\n}\n","import { Material, Mesh } from '../classes';\nimport { GL_LINES } from '../classes/Mesh';\nimport { Vector3 } from '../domain/interfaces/Vectors';\n\nexport function createWireBox(\n min: Vector3,\n max: Vector3,\n material: Material,\n): Mesh {\n const [minX, minY, minZ] = min;\n const [maxX, maxY, maxZ] = max;\n\n // 8 corners of the box\n const vertices: number[] = [\n minX,\n minY,\n minZ,\n maxX,\n minY,\n minZ,\n maxX,\n maxY,\n minZ,\n minX,\n maxY,\n minZ,\n minX,\n minY,\n maxZ,\n maxX,\n minY,\n maxZ,\n maxX,\n maxY,\n maxZ,\n minX,\n maxY,\n maxZ,\n ];\n\n // edges as lines (pairs of indices)\n const indices: number[] = [\n 0,\n 1,\n 1,\n 2,\n 2,\n 3,\n 3,\n 0, // bottom face\n 4,\n 5,\n 5,\n 6,\n 6,\n 7,\n 7,\n 4, // top face\n 0,\n 4,\n 1,\n 5,\n 2,\n 6,\n 3,\n 7, // vertical edges\n ];\n\n // expand indices to vertices array (since WebGL uses gl.LINES)\n const lineVertices: number[] = [];\n for (let i = 0; i < indices.length; i++) {\n const idx = indices[i];\n lineVertices.push(\n vertices[idx * 3],\n vertices[idx * 3 + 1],\n vertices[idx * 3 + 2],\n );\n }\n\n // Normals can just be zero for wireframe\n const normals = new Float32Array(lineVertices.length);\n\n const mesh = new Mesh(\n 'hitbox',\n new Float32Array(lineVertices),\n normals,\n material,\n new Float32Array(),\n null,\n );\n mesh.setMode(GL_LINES);\n return mesh;\n}\n"],"mappings":"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","names":["mat4","quat","vec3","mat4"]}
|