├── .gitignore
├── .npmignore
├── README.md
├── examples
├── anisotropic.html
├── assets
│ ├── acorn.jpg
│ ├── acorn.json
│ ├── airplane.jpg
│ ├── airplane.json
│ ├── anim-format.json
│ ├── compressed
│ │ ├── astc-m-y.ktx
│ │ ├── etc-m-y.ktx
│ │ ├── etc1-m-y.ktx
│ │ ├── pvrtc-m-y.ktx
│ │ ├── s3tc-m-y.ktx
│ │ └── uv.jpg
│ ├── croissant.jpg
│ ├── croissant.json
│ ├── cube
│ │ ├── negx.jpg
│ │ ├── negy.jpg
│ │ ├── negz.jpg
│ │ ├── posx.jpg
│ │ ├── posy.jpg
│ │ └── posz.jpg
│ ├── earth.jpg
│ ├── earth_cloud.jpg
│ ├── earth_specular.jpg
│ ├── favicon.png
│ ├── fonts
│ │ ├── FiraSans-Bold.json
│ │ ├── FiraSans-Bold.png
│ │ ├── FiraSans-Bold.ttf
│ │ ├── raleway-bold-webfont.woff
│ │ ├── raleway-bold-webfont.woff2
│ │ ├── raleway-regular-webfont.woff
│ │ └── raleway-regular-webfont.woff2
│ ├── forest.jpg
│ ├── forest.json
│ ├── fox.jpg
│ ├── fox.json
│ ├── gltf
│ │ ├── cottage-basis-draco.glb
│ │ ├── cottage-basis.glb
│ │ ├── hershel-optimized.glb
│ │ └── hershel.glb
│ ├── goat.jpg
│ ├── goat.json
│ ├── granite-diffuse.jpg
│ ├── granite-normal.jpg
│ ├── grid.jpg
│ ├── laputa.mp4
│ ├── leaf.jpg
│ ├── libs
│ │ ├── basis
│ │ │ ├── BasisWorker.js
│ │ │ ├── basis_transcoder.js
│ │ │ └── basis_transcoder.wasm
│ │ └── draco
│ │ │ ├── DracoWorker.js
│ │ │ ├── draco_decoder.js
│ │ │ ├── draco_decoder.wasm
│ │ │ ├── draco_encoder.js
│ │ │ ├── draco_wasm_wrapper.js
│ │ │ └── gltf
│ │ │ ├── draco_decoder.js
│ │ │ ├── draco_decoder.wasm
│ │ │ ├── draco_encoder.js
│ │ │ └── draco_wasm_wrapper.js
│ ├── macaw.jpg
│ ├── macaw.json
│ ├── main.css
│ ├── matcap.jpg
│ ├── octopus.jpg
│ ├── octopus.json
│ ├── ogl.png
│ ├── pbr
│ │ ├── black.jpg
│ │ ├── car-ext-color.jpg
│ │ ├── car-ext-emissive.jpg
│ │ ├── car-ext-inner.json
│ │ ├── car-ext-normal.jpg
│ │ ├── car-ext-opacity.jpg
│ │ ├── car-ext-rmo.jpg
│ │ ├── car-ext.json
│ │ ├── car-int-color.jpg
│ │ ├── car-int-normal.jpg
│ │ ├── car-int-rmo.jpg
│ │ ├── car-int.json
│ │ ├── car-shadow.jpg
│ │ ├── car-shadow.png
│ │ ├── lut.png
│ │ ├── waterfall-diffuse-RGBM.png
│ │ ├── waterfall-specular-RGBM.png
│ │ └── white.jpg
│ ├── plane.json
│ ├── rounded-cube.json
│ ├── saddle.jpg
│ ├── saddle.json
│ ├── sky.jpg
│ ├── snout-anim.json
│ ├── snout-rig.json
│ ├── snout-shadow.jpg
│ ├── snout.jpg
│ ├── sunset-diffuse-RGBM.png
│ ├── sunset-specular-RGBM.png
│ ├── sunset.exr
│ ├── uv.jpg
│ ├── water.jpg
│ ├── windmill.jpg
│ └── windmill.json
├── base-primitives.html
├── compressed-textures.html
├── cube-map.html
├── curves.html
├── draw-modes.html
├── flat-shading-matcap.html
├── fog.html
├── fresnel.html
├── frustum-culling.html
├── gltf-draco-webp.html
├── gltf-ktx2-basis-draco.html
├── gltf-ktx2-basis.html
├── gpgpu-particles.html
├── helpers.html
├── high-mesh-count.html
├── index.html
├── indexed-vs-non-indexed.html
├── instancing-gpu-picking.html
├── instancing.html
├── load-gltf.html
├── load-json.html
├── mouse-flowmap.html
├── mrt.html
├── msdf-text.html
├── normal-maps.html
├── orbit-controls.html
├── particles.html
├── paths.html
├── pbr.html
├── point-lighting.html
├── polylines.html
├── post-bloom.html
├── post-fluid-distortion.html
├── post-fxaa.html
├── raycasting.html
├── render-to-texture.html
├── scene-graph.html
├── shadow-maps.html
├── skinning.html
├── skydome.html
├── sort-transparency.html
├── textures.html
├── torus.html
├── triangle-screen-shader.html
├── tube.html
├── wire-mesh.html
├── wireframe-shader.html
└── wireframe.html
├── package.json
├── src
├── core
│ ├── Camera.js
│ ├── Geometry.js
│ ├── Mesh.js
│ ├── Program.js
│ ├── RenderTarget.js
│ ├── Renderer.js
│ ├── Texture.js
│ └── Transform.js
├── extras
│ ├── Animation.js
│ ├── BasisManager.js
│ ├── Box.js
│ ├── Curve.js
│ ├── Cylinder.js
│ ├── DracoManager.js
│ ├── Flowmap.js
│ ├── GLTFAnimation.js
│ ├── GLTFLoader.js
│ ├── GLTFSkin.js
│ ├── GPGPU.js
│ ├── InstancedMesh.js
│ ├── KTXTexture.js
│ ├── NormalProgram.js
│ ├── Orbit.js
│ ├── Plane.js
│ ├── Polyline.js
│ ├── Post.js
│ ├── Raycast.js
│ ├── Shadow.js
│ ├── Skin.js
│ ├── Sphere.js
│ ├── Text.js
│ ├── Texture3D.js
│ ├── TextureLoader.js
│ ├── Torus.js
│ ├── Triangle.js
│ ├── Tube.js
│ ├── WireMesh.js
│ ├── helpers
│ │ ├── AxesHelper.js
│ │ ├── FaceNormalsHelper.js
│ │ ├── GridHelper.js
│ │ └── VertexNormalsHelper.js
│ └── path
│ │ ├── BaseSegment.js
│ │ ├── CubicBezierSegment.js
│ │ ├── LineSegment.js
│ │ ├── Path.js
│ │ ├── QuadraticBezierSegment.js
│ │ └── utils.js
├── index.js
└── math
│ ├── Color.js
│ ├── Euler.js
│ ├── Mat3.js
│ ├── Mat4.js
│ ├── Quat.js
│ ├── Vec2.js
│ ├── Vec3.js
│ ├── Vec4.js
│ └── functions
│ ├── ColorFunc.js
│ ├── EulerFunc.js
│ ├── Mat3Func.js
│ ├── Mat4Func.js
│ ├── QuatFunc.js
│ ├── Vec2Func.js
│ ├── Vec3Func.js
│ └── Vec4Func.js
└── types
├── core
├── Camera.d.ts
├── Geometry.d.ts
├── Mesh.d.ts
├── Program.d.ts
├── RenderTarget.d.ts
├── Renderer.d.ts
├── Texture.d.ts
└── Transform.d.ts
├── extras
├── Animation.d.ts
├── BasisManager.d.ts
├── Box.d.ts
├── Curve.d.ts
├── Cylinder.d.ts
├── DracoManager.d.ts
├── Flowmap.d.ts
├── GLTFAnimation.d.ts
├── GLTFLoader.d.ts
├── GLTFSkin.d.ts
├── GPGPU.d.ts
├── InstancedMesh.d.ts
├── KTXTexture.d.ts
├── NormalProgram.d.ts
├── Orbit.d.ts
├── Plane.d.ts
├── Polyline.d.ts
├── Post.d.ts
├── Raycast.d.ts
├── Shadow.d.ts
├── Skin.d.ts
├── Sphere.d.ts
├── Text.d.ts
├── Texture3D.d.ts
├── TextureLoader.d.ts
├── Torus.d.ts
├── Triangle.d.ts
├── Tube.d.ts
├── WireMesh.d.ts
├── helpers
│ ├── AxesHelper.d.ts
│ ├── FaceNormalsHelper.d.ts
│ ├── GridHelper.d.ts
│ └── VertexNormalsHelper.d.ts
└── path
│ ├── BaseSegment.d.ts
│ ├── CubicBezierSegment.d.ts
│ ├── LineSegment.d.ts
│ ├── Path.d.ts
│ └── QuadraticBezierSegment.d.ts
├── index.d.ts
└── math
├── Color.d.ts
├── Euler.d.ts
├── Mat3.d.ts
├── Mat4.d.ts
├── Quat.d.ts
├── Vec2.d.ts
├── Vec3.d.ts
└── Vec4.d.ts
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | dist/
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | examples
--------------------------------------------------------------------------------
/examples/assets/acorn.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/acorn.jpg
--------------------------------------------------------------------------------
/examples/assets/airplane.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/airplane.jpg
--------------------------------------------------------------------------------
/examples/assets/anim-format.json:
--------------------------------------------------------------------------------
1 | {
2 | frames: [
3 | {
4 | position: [bone1X, bone1Y, bone1Z, bone2X, bone2Y, bone2Z],
5 | quaternion: [2, 3, 1, 5, 6, 2],
6 | scale: [2, 3, 1, 5, 6, 2],
7 | },
8 | {
9 | position: [2, 3, 1, 5, 6, 2],
10 | quaternion: [2, 3, 1, 5, 6, 2],
11 | scale: [2, 3, 1, 5, 6, 2],
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/examples/assets/compressed/astc-m-y.ktx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/compressed/astc-m-y.ktx
--------------------------------------------------------------------------------
/examples/assets/compressed/etc-m-y.ktx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/compressed/etc-m-y.ktx
--------------------------------------------------------------------------------
/examples/assets/compressed/etc1-m-y.ktx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/compressed/etc1-m-y.ktx
--------------------------------------------------------------------------------
/examples/assets/compressed/pvrtc-m-y.ktx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/compressed/pvrtc-m-y.ktx
--------------------------------------------------------------------------------
/examples/assets/compressed/s3tc-m-y.ktx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/compressed/s3tc-m-y.ktx
--------------------------------------------------------------------------------
/examples/assets/compressed/uv.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/compressed/uv.jpg
--------------------------------------------------------------------------------
/examples/assets/croissant.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/croissant.jpg
--------------------------------------------------------------------------------
/examples/assets/cube/negx.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/cube/negx.jpg
--------------------------------------------------------------------------------
/examples/assets/cube/negy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/cube/negy.jpg
--------------------------------------------------------------------------------
/examples/assets/cube/negz.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/cube/negz.jpg
--------------------------------------------------------------------------------
/examples/assets/cube/posx.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/cube/posx.jpg
--------------------------------------------------------------------------------
/examples/assets/cube/posy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/cube/posy.jpg
--------------------------------------------------------------------------------
/examples/assets/cube/posz.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/cube/posz.jpg
--------------------------------------------------------------------------------
/examples/assets/earth.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/earth.jpg
--------------------------------------------------------------------------------
/examples/assets/earth_cloud.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/earth_cloud.jpg
--------------------------------------------------------------------------------
/examples/assets/earth_specular.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/earth_specular.jpg
--------------------------------------------------------------------------------
/examples/assets/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/favicon.png
--------------------------------------------------------------------------------
/examples/assets/fonts/FiraSans-Bold.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/fonts/FiraSans-Bold.png
--------------------------------------------------------------------------------
/examples/assets/fonts/FiraSans-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/fonts/FiraSans-Bold.ttf
--------------------------------------------------------------------------------
/examples/assets/fonts/raleway-bold-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/fonts/raleway-bold-webfont.woff
--------------------------------------------------------------------------------
/examples/assets/fonts/raleway-bold-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/fonts/raleway-bold-webfont.woff2
--------------------------------------------------------------------------------
/examples/assets/fonts/raleway-regular-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/fonts/raleway-regular-webfont.woff
--------------------------------------------------------------------------------
/examples/assets/fonts/raleway-regular-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/fonts/raleway-regular-webfont.woff2
--------------------------------------------------------------------------------
/examples/assets/forest.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/forest.jpg
--------------------------------------------------------------------------------
/examples/assets/fox.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/fox.jpg
--------------------------------------------------------------------------------
/examples/assets/gltf/cottage-basis-draco.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/gltf/cottage-basis-draco.glb
--------------------------------------------------------------------------------
/examples/assets/gltf/cottage-basis.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/gltf/cottage-basis.glb
--------------------------------------------------------------------------------
/examples/assets/gltf/hershel-optimized.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/gltf/hershel-optimized.glb
--------------------------------------------------------------------------------
/examples/assets/gltf/hershel.glb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/gltf/hershel.glb
--------------------------------------------------------------------------------
/examples/assets/goat.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/goat.jpg
--------------------------------------------------------------------------------
/examples/assets/granite-diffuse.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/granite-diffuse.jpg
--------------------------------------------------------------------------------
/examples/assets/granite-normal.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/granite-normal.jpg
--------------------------------------------------------------------------------
/examples/assets/grid.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/grid.jpg
--------------------------------------------------------------------------------
/examples/assets/laputa.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/laputa.mp4
--------------------------------------------------------------------------------
/examples/assets/leaf.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/leaf.jpg
--------------------------------------------------------------------------------
/examples/assets/libs/basis/basis_transcoder.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/libs/basis/basis_transcoder.wasm
--------------------------------------------------------------------------------
/examples/assets/libs/draco/DracoWorker.js:
--------------------------------------------------------------------------------
1 | // TODO
2 | // [ ] Cleanup decoder
3 | // [ ] Point clouds
4 | // [ ] WASM support
5 |
6 | // https://github.com/mrdoob/three.js/tree/master/examples/jsm/libs/draco
7 | importScripts('gltf/draco_decoder.js');
8 |
9 | let draco;
10 | let decoder;
11 |
12 | let moduleReadyResolve;
13 | const moduleReady = new Promise((res) => (moduleReadyResolve = res));
14 |
15 | // Create the Draco decoder
16 | // const initStartTime = performance.now();
17 | DracoDecoderModule().then((module) => {
18 | draco = module;
19 | decoder = new draco.Decoder();
20 | // const elapsed = performance.now() - initStartTime;
21 | // console.log('worker init time', `${elapsed.toFixed(2)}ms`);
22 | moduleReadyResolve();
23 | });
24 |
25 | addEventListener('message', ({ data }) => {
26 | decodeGeometry(data);
27 | });
28 |
29 | async function decodeGeometry({ id, buffer, config }) {
30 | await moduleReady;
31 |
32 | // const startTime = performance.now();
33 | const array = new Int8Array(buffer);
34 | const { attributeIds, attributeTypes } = config;
35 |
36 | const dracoGeometry = new draco.Mesh();
37 | const decodingStatus = decoder.DecodeArrayToMesh(array, array.byteLength, dracoGeometry);
38 |
39 | if (!decodingStatus.ok() || dracoGeometry.ptr === 0)
40 | postMessage({ id, error: `Decoding failed: ${decodingStatus.error_msg()}` });
41 |
42 | const geometry = { index: null, attributes: [] };
43 |
44 | // Gather all vertex attributes
45 | for (const attributeName in attributeIds) {
46 | const attributeType = self[attributeTypes[attributeName]];
47 | const attribute = decoder.GetAttributeByUniqueId(dracoGeometry, attributeIds[attributeName]);
48 | const attributeResult = decodeAttribute(dracoGeometry, attributeName, attributeType, attribute);
49 |
50 | geometry.attributes.push(attributeResult);
51 | }
52 |
53 | // Add index
54 | geometry.index = decodeIndex(dracoGeometry);
55 |
56 | draco.destroy(dracoGeometry);
57 | // draco.destroy(decoder);
58 |
59 | // const elapsed = performance.now() - startTime;
60 | // console.log('decodeGeometry time', `${elapsed.toFixed(2)}ms`);
61 |
62 | // Transfer buffers
63 | const buffers = geometry.attributes.map((attr) => attr.array.buffer);
64 | if (geometry.index) buffers.push(geometry.index.array.buffer);
65 |
66 | postMessage(
67 | {
68 | id,
69 | geometry,
70 | },
71 | buffers
72 | );
73 | }
74 |
75 | // https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/DRACOLoader.js
76 |
77 | function decodeIndex(dracoGeometry) {
78 | const numFaces = dracoGeometry.num_faces();
79 | const numIndices = numFaces * 3;
80 | const byteLength = numIndices * 4;
81 |
82 | const ptr = draco._malloc(byteLength);
83 | decoder.GetTrianglesUInt32Array(dracoGeometry, byteLength, ptr);
84 | const index = new Uint32Array(draco.HEAPF32.buffer, ptr, numIndices).slice();
85 | draco._free(ptr);
86 |
87 | return { array: index, itemSize: 1 };
88 | }
89 |
90 | function decodeAttribute(dracoGeometry, attributeName, attributeType, attribute) {
91 | const numComponents = attribute.num_components();
92 | const numPoints = dracoGeometry.num_points();
93 | const numValues = numPoints * numComponents;
94 | const byteLength = numValues * attributeType.BYTES_PER_ELEMENT;
95 | const dataType = getDracoDataType(attributeType);
96 |
97 | const ptr = draco._malloc(byteLength);
98 | decoder.GetAttributeDataArrayForAllPoints(dracoGeometry, attribute, dataType, byteLength, ptr);
99 | const array = new attributeType(draco.HEAPF32.buffer, ptr, numValues).slice();
100 | draco._free(ptr);
101 |
102 | return {
103 | name: attributeName,
104 | array,
105 | itemSize: numComponents,
106 | };
107 | }
108 |
109 | function getDracoDataType(attributeType) {
110 | switch (attributeType) {
111 | case Float32Array:
112 | return draco.DT_FLOAT32;
113 | case Int8Array:
114 | return draco.DT_INT8;
115 | case Int16Array:
116 | return draco.DT_INT16;
117 | case Int32Array:
118 | return draco.DT_INT32;
119 | case Uint8Array:
120 | return draco.DT_UINT8;
121 | case Uint16Array:
122 | return draco.DT_UINT16;
123 | case Uint32Array:
124 | return draco.DT_UINT32;
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/examples/assets/libs/draco/draco_decoder.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/libs/draco/draco_decoder.wasm
--------------------------------------------------------------------------------
/examples/assets/libs/draco/gltf/draco_decoder.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/libs/draco/gltf/draco_decoder.wasm
--------------------------------------------------------------------------------
/examples/assets/macaw.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/macaw.jpg
--------------------------------------------------------------------------------
/examples/assets/main.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 |
5 | body,
6 | html {
7 | -webkit-font-smoothing: antialiased;
8 | -moz-osx-font-smoothing: grayscale;
9 | overflow-x: hidden;
10 | height: 100%;
11 | overscroll-behavior-y: contain;
12 | }
13 |
14 | body,
15 | button,
16 | p,
17 | ul {
18 | margin: 0;
19 | padding: 0;
20 | }
21 |
22 | button,
23 | select {
24 | border: none;
25 | outline: none;
26 | background: none;
27 | font-family: inherit;
28 | }
29 |
30 | a,
31 | button,
32 | input,
33 | select,
34 | textarea {
35 | -webkit-tap-highlight-color: transparent;
36 | }
37 |
38 | a {
39 | color: inherit; /* blue colors for links too */
40 | text-decoration: inherit; /* no underline */
41 | }
42 |
43 | :root {
44 | overflow-x: hidden;
45 | height: 100%;
46 | }
47 |
48 | @font-face {
49 | font-family: 'Raleway';
50 | src: url('fonts/raleway-regular-webfont.woff2') format('woff2'),
51 | url('fonts/raleway-regular-webfont.woff') format('woff');
52 | font-weight: 400;
53 | font-style: normal;
54 | }
55 |
56 | @font-face {
57 | font-family: 'Raleway';
58 | src: url('fonts/raleway-bold-webfont.woff2') format('woff2'),
59 | url('fonts/raleway-bold-webfont.woff') format('woff');
60 | font-weight: 700;
61 | font-style: normal;
62 | }
63 |
64 | body {
65 | font-family: 'Raleway', sans-serif;
66 | font-weight: 700;
67 | font-size: 14px;
68 | }
69 |
70 | .Side {
71 | position: relative;
72 | width: 300px;
73 | height: 100%;
74 | overflow: auto;
75 | padding-bottom: 100px;
76 | padding-left: 20px;
77 | padding-right: 40px;
78 | background: #fff;
79 | }
80 | .Iframe {
81 | position: absolute;
82 | left: 300px;
83 | right: 0;
84 | top: 0;
85 | bottom: 0;
86 | height: 100%;
87 | width: calc(100% - 300px);
88 | border: none;
89 | margin: 0;
90 | }
91 | .Title {
92 | font-size: 18px;
93 | margin: 20px 0;
94 | display: block;
95 | }
96 | .SubTitle {
97 | font-weight: 400;
98 | font-size: 17px;
99 | margin: 20px 0 50px;
100 | }
101 | .Section {
102 | font-weight: 400;
103 | margin: 40px 0 20px;
104 | padding-left: 15px;
105 | }
106 | .Example {
107 | margin: 10px 0;
108 | padding-left: 30px;
109 | display: block;
110 | }
111 | .Example.active {
112 | background-color: #3dd6ff;
113 | margin: 0px -40px 0px -20px;
114 | padding: 5px 0px 5px 50px;
115 | font-weight: bold;
116 | color: white;
117 | }
118 | div.Example {
119 | opacity: 0.2;
120 | }
121 |
122 | .SideIcon,
123 | .CodeIcon {
124 | position: absolute;
125 | display: block;
126 | z-index: 1;
127 | margin: 30px;
128 | width: 50px;
129 | height: 50px;
130 | line-height: 50px;
131 | text-align: center;
132 | background: #fff;
133 | border-radius: 100%;
134 | font-size: 19px;
135 | letter-spacing: -0.1em;
136 | box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.1);
137 | }
138 | .CodeIcon {
139 | bottom: 0;
140 | right: 0;
141 | }
142 | .SideIcon {
143 | top: 20px;
144 | left: 245px;
145 | display: none;
146 | }
147 |
148 | @media (max-width: 600px) {
149 | .Side {
150 | z-index: 1;
151 | }
152 | .Iframe {
153 | left: 0;
154 | width: 100%;
155 | }
156 | .SideIcon {
157 | display: block;
158 | }
159 | [data-hideSidebar] .Side {
160 | transform: translateX(-100%);
161 | }
162 |
163 | [data-hideSidebar] .SideIcon {
164 | left: 0;
165 | transform: rotate(180deg);
166 | }
167 | }
168 |
169 | .Info {
170 | padding: 20px;
171 | position: relative;
172 | z-index: 1;
173 | }
174 | .Info a {
175 | color: rgb(39, 124, 235);
176 | }
177 | canvas {
178 | position: absolute;
179 | width: 100%;
180 | height: 100%;
181 | top: 0;
182 | left: 0;
183 | }
184 |
185 | #dropdown {
186 | margin: 1em 0em;
187 | }
188 |
--------------------------------------------------------------------------------
/examples/assets/matcap.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/matcap.jpg
--------------------------------------------------------------------------------
/examples/assets/octopus.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/octopus.jpg
--------------------------------------------------------------------------------
/examples/assets/ogl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/ogl.png
--------------------------------------------------------------------------------
/examples/assets/pbr/black.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/pbr/black.jpg
--------------------------------------------------------------------------------
/examples/assets/pbr/car-ext-color.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/pbr/car-ext-color.jpg
--------------------------------------------------------------------------------
/examples/assets/pbr/car-ext-emissive.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/pbr/car-ext-emissive.jpg
--------------------------------------------------------------------------------
/examples/assets/pbr/car-ext-normal.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/pbr/car-ext-normal.jpg
--------------------------------------------------------------------------------
/examples/assets/pbr/car-ext-opacity.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/pbr/car-ext-opacity.jpg
--------------------------------------------------------------------------------
/examples/assets/pbr/car-ext-rmo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/pbr/car-ext-rmo.jpg
--------------------------------------------------------------------------------
/examples/assets/pbr/car-int-color.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/pbr/car-int-color.jpg
--------------------------------------------------------------------------------
/examples/assets/pbr/car-int-normal.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/pbr/car-int-normal.jpg
--------------------------------------------------------------------------------
/examples/assets/pbr/car-int-rmo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/pbr/car-int-rmo.jpg
--------------------------------------------------------------------------------
/examples/assets/pbr/car-shadow.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/pbr/car-shadow.jpg
--------------------------------------------------------------------------------
/examples/assets/pbr/car-shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/pbr/car-shadow.png
--------------------------------------------------------------------------------
/examples/assets/pbr/lut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/pbr/lut.png
--------------------------------------------------------------------------------
/examples/assets/pbr/waterfall-diffuse-RGBM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/pbr/waterfall-diffuse-RGBM.png
--------------------------------------------------------------------------------
/examples/assets/pbr/waterfall-specular-RGBM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/pbr/waterfall-specular-RGBM.png
--------------------------------------------------------------------------------
/examples/assets/pbr/white.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/pbr/white.jpg
--------------------------------------------------------------------------------
/examples/assets/plane.json:
--------------------------------------------------------------------------------
1 | {
2 | "position": [0.0, -0.149, -1.543, -0.002, -0.288, 0.649, 0.242, 0.149, 0.589, 0.242, 0.149, 0.589, 0.681, -0.055, 0.618, 0.0, -0.149, -1.543, -0.221, 0.149, 0.589, -0.002, -0.288, 0.649, 0.0, -0.149, -1.543, -0.681, -0.055, 0.618, -0.221, 0.149, 0.589, 0.0, -0.149, -1.543],
3 | "normal": [-0.87, 0.491, 0.03, -0.87, 0.491, 0.03, -0.87, 0.491, 0.03, 0.425, 0.889, -0.172, 0.425, 0.889, -0.172, 0.425, 0.889, -0.172, 0.892, 0.451, 0.03, 0.892, 0.451, 0.03, 0.892, 0.451, 0.03, -0.409, 0.897, -0.168, -0.409, 0.897, -0.168, -0.409, 0.897, -0.168],
4 | "uv": [0.5, 1.0, 0.5, 0.0, 0.698, 0.0, 0.698, 0.0, 1.0, 0.0, 0.5, 1.0, 0.312, 0.0, 0.5, 0.0, 0.5, 1.0, 0.0, 0.0, 0.312, 0.0, 0.5, 1.0]
5 | }
--------------------------------------------------------------------------------
/examples/assets/saddle.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/saddle.jpg
--------------------------------------------------------------------------------
/examples/assets/sky.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/sky.jpg
--------------------------------------------------------------------------------
/examples/assets/snout-shadow.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/snout-shadow.jpg
--------------------------------------------------------------------------------
/examples/assets/snout.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/snout.jpg
--------------------------------------------------------------------------------
/examples/assets/sunset-diffuse-RGBM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/sunset-diffuse-RGBM.png
--------------------------------------------------------------------------------
/examples/assets/sunset-specular-RGBM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/sunset-specular-RGBM.png
--------------------------------------------------------------------------------
/examples/assets/sunset.exr:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/sunset.exr
--------------------------------------------------------------------------------
/examples/assets/uv.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/uv.jpg
--------------------------------------------------------------------------------
/examples/assets/water.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/water.jpg
--------------------------------------------------------------------------------
/examples/assets/windmill.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oframe/ogl/385ce65c352c70734a36dc98c787fdd1d30ddb3b/examples/assets/windmill.jpg
--------------------------------------------------------------------------------
/examples/load-json.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | OGL • Load JSON
10 |
11 |
12 |
13 | Load JSON (Javascript Object Notation). Model by Google Poly
14 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/examples/skydome.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | OGL • Skydome
10 |
11 |
12 |
13 |
14 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/examples/torus.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | OGL • Torus
10 |
11 |
12 |
13 | Torus
14 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/examples/triangle-screen-shader.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | OGL • Triangle Screen Shader
10 |
11 |
12 |
13 | Triangle Screen Shader
14 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/examples/wire-mesh.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | OGL • WireMesh
10 |
11 |
12 |
13 | WireMesh (wireframe). Model by Google Poly
14 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ogl",
3 | "version": "1.0.11",
4 | "description": "WebGL Library",
5 | "type": "module",
6 | "main": "./src/index.js",
7 | "exports": {
8 | ".": {
9 | "types": "./types/index.d.ts",
10 | "default": "./src/index.js"
11 | },
12 | "./src/*": "./src/*"
13 | },
14 | "sideEffects": false,
15 | "types": "./types/index.d.ts",
16 | "directories": {
17 | "example": "examples"
18 | },
19 | "repository": {
20 | "type": "git",
21 | "url": "git+https://gordonnl@github.com/oframe/ogl.git"
22 | },
23 | "author": {
24 | "name": "Nathan Gordon",
25 | "email": "gordonnl@gmail.com",
26 | "url": "https://twitter.com/gordonnl"
27 | },
28 | "license": "Unlicense",
29 | "bugs": {
30 | "url": "https://github.com/oframe/ogl/issues"
31 | },
32 | "homepage": "https://github.com/oframe/ogl#readme",
33 | "prettier": {
34 | "arrowParens": "always",
35 | "bracketSpacing": true,
36 | "endOfLine": "lf",
37 | "htmlWhitespaceSensitivity": "css",
38 | "printWidth": 200,
39 | "quoteProps": "as-needed",
40 | "semi": true,
41 | "singleQuote": true,
42 | "tabWidth": 4,
43 | "trailingComma": "es5",
44 | "useTabs": false
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/core/Mesh.js:
--------------------------------------------------------------------------------
1 | import { Transform } from './Transform.js';
2 | import { Mat3 } from '../math/Mat3.js';
3 | import { Mat4 } from '../math/Mat4.js';
4 |
5 | let ID = 0;
6 |
7 | export class Mesh extends Transform {
8 | constructor(gl, { geometry, program, mode = gl.TRIANGLES, frustumCulled = true, renderOrder = 0 } = {}) {
9 | super();
10 | if (!gl.canvas) console.error('gl not passed as first argument to Mesh');
11 | this.gl = gl;
12 | this.id = ID++;
13 | this.geometry = geometry;
14 | this.program = program;
15 | this.mode = mode;
16 |
17 | // Used to skip frustum culling
18 | this.frustumCulled = frustumCulled;
19 |
20 | // Override sorting to force an order
21 | this.renderOrder = renderOrder;
22 | this.modelViewMatrix = new Mat4();
23 | this.normalMatrix = new Mat3();
24 | this.beforeRenderCallbacks = [];
25 | this.afterRenderCallbacks = [];
26 | }
27 |
28 | onBeforeRender(f) {
29 | this.beforeRenderCallbacks.push(f);
30 | return this;
31 | }
32 |
33 | onAfterRender(f) {
34 | this.afterRenderCallbacks.push(f);
35 | return this;
36 | }
37 |
38 | draw({ camera } = {}) {
39 | if (camera) {
40 | // Add empty matrix uniforms to program if unset
41 | if (!this.program.uniforms.modelMatrix) {
42 | Object.assign(this.program.uniforms, {
43 | modelMatrix: { value: null },
44 | viewMatrix: { value: null },
45 | modelViewMatrix: { value: null },
46 | normalMatrix: { value: null },
47 | projectionMatrix: { value: null },
48 | cameraPosition: { value: null },
49 | });
50 | }
51 |
52 | // Set the matrix uniforms
53 | this.program.uniforms.projectionMatrix.value = camera.projectionMatrix;
54 | this.program.uniforms.cameraPosition.value = camera.worldPosition;
55 | this.program.uniforms.viewMatrix.value = camera.viewMatrix;
56 | this.modelViewMatrix.multiply(camera.viewMatrix, this.worldMatrix);
57 | this.normalMatrix.getNormalMatrix(this.modelViewMatrix);
58 | this.program.uniforms.modelMatrix.value = this.worldMatrix;
59 | this.program.uniforms.modelViewMatrix.value = this.modelViewMatrix;
60 | this.program.uniforms.normalMatrix.value = this.normalMatrix;
61 | }
62 | this.beforeRenderCallbacks.forEach((f) => f && f({ mesh: this, camera }));
63 |
64 | // determine if faces need to be flipped - when mesh scaled negatively
65 | let flipFaces = this.program.cullFace && this.worldMatrix.determinant() < 0;
66 | this.program.use({ flipFaces });
67 | this.geometry.draw({ mode: this.mode, program: this.program });
68 | this.afterRenderCallbacks.forEach((f) => f && f({ mesh: this, camera }));
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/core/Transform.js:
--------------------------------------------------------------------------------
1 | import { Vec3 } from '../math/Vec3.js';
2 | import { Quat } from '../math/Quat.js';
3 | import { Mat4 } from '../math/Mat4.js';
4 | import { Euler } from '../math/Euler.js';
5 |
6 | export class Transform {
7 | constructor() {
8 | this.parent = null;
9 | this.children = [];
10 | this.visible = true;
11 |
12 | this.matrix = new Mat4();
13 | this.worldMatrix = new Mat4();
14 | this.matrixAutoUpdate = true;
15 | this.worldMatrixNeedsUpdate = false;
16 |
17 | this.position = new Vec3();
18 | this.quaternion = new Quat();
19 | this.scale = new Vec3(1);
20 | this.rotation = new Euler();
21 | this.up = new Vec3(0, 1, 0);
22 |
23 | this.rotation._target.onChange = () => this.quaternion.fromEuler(this.rotation, true);
24 | this.quaternion._target.onChange = () => this.rotation.fromQuaternion(this.quaternion, undefined, true);
25 | }
26 |
27 | setParent(parent, notifyParent = true) {
28 | if (this.parent && parent !== this.parent) this.parent.removeChild(this, false);
29 | this.parent = parent;
30 | if (notifyParent && parent) parent.addChild(this, false);
31 | }
32 |
33 | addChild(child, notifyChild = true) {
34 | if (!~this.children.indexOf(child)) this.children.push(child);
35 | if (notifyChild) child.setParent(this, false);
36 | }
37 |
38 | removeChild(child, notifyChild = true) {
39 | if (!!~this.children.indexOf(child)) this.children.splice(this.children.indexOf(child), 1);
40 | if (notifyChild) child.setParent(null, false);
41 | }
42 |
43 | updateMatrixWorld(force) {
44 | if (this.matrixAutoUpdate) this.updateMatrix();
45 | if (this.worldMatrixNeedsUpdate || force) {
46 | if (this.parent === null) this.worldMatrix.copy(this.matrix);
47 | else this.worldMatrix.multiply(this.parent.worldMatrix, this.matrix);
48 | this.worldMatrixNeedsUpdate = false;
49 | force = true;
50 | }
51 |
52 | for (let i = 0, l = this.children.length; i < l; i++) {
53 | this.children[i].updateMatrixWorld(force);
54 | }
55 | }
56 |
57 | updateMatrix() {
58 | this.matrix.compose(this.quaternion, this.position, this.scale);
59 | this.worldMatrixNeedsUpdate = true;
60 | }
61 |
62 | traverse(callback) {
63 | // Return true in callback to stop traversing children
64 | if (callback(this)) return;
65 | for (let i = 0, l = this.children.length; i < l; i++) {
66 | this.children[i].traverse(callback);
67 | }
68 | }
69 |
70 | decompose() {
71 | this.matrix.decompose(this.quaternion._target, this.position, this.scale);
72 | this.rotation.fromQuaternion(this.quaternion);
73 | }
74 |
75 | lookAt(target, invert = false) {
76 | if (invert) this.matrix.lookAt(this.position, target, this.up);
77 | else this.matrix.lookAt(target, this.position, this.up);
78 | this.matrix.getRotation(this.quaternion._target);
79 | this.rotation.fromQuaternion(this.quaternion);
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/extras/Animation.js:
--------------------------------------------------------------------------------
1 | import { Vec3 } from '../math/Vec3.js';
2 | import { Quat } from '../math/Quat.js';
3 |
4 | const prevPos = /* @__PURE__ */ new Vec3();
5 | const prevRot = /* @__PURE__ */ new Quat();
6 | const prevScl = /* @__PURE__ */ new Vec3();
7 |
8 | const nextPos = /* @__PURE__ */ new Vec3();
9 | const nextRot = /* @__PURE__ */ new Quat();
10 | const nextScl = /* @__PURE__ */ new Vec3();
11 |
12 | export class Animation {
13 | constructor({ objects, data }) {
14 | this.objects = objects;
15 | this.data = data;
16 | this.elapsed = 0;
17 | this.weight = 1;
18 | this.duration = data.frames.length - 1;
19 | }
20 |
21 | update(totalWeight = 1, isSet) {
22 | const weight = isSet ? 1 : this.weight / totalWeight;
23 | const elapsed = this.elapsed % this.duration;
24 |
25 | const floorFrame = Math.floor(elapsed);
26 | const blend = elapsed - floorFrame;
27 | const prevKey = this.data.frames[floorFrame];
28 | const nextKey = this.data.frames[(floorFrame + 1) % this.duration];
29 |
30 | this.objects.forEach((object, i) => {
31 | prevPos.fromArray(prevKey.position, i * 3);
32 | prevRot.fromArray(prevKey.quaternion, i * 4);
33 | prevScl.fromArray(prevKey.scale, i * 3);
34 |
35 | nextPos.fromArray(nextKey.position, i * 3);
36 | nextRot.fromArray(nextKey.quaternion, i * 4);
37 | nextScl.fromArray(nextKey.scale, i * 3);
38 |
39 | prevPos.lerp(nextPos, blend);
40 | prevRot.slerp(nextRot, blend);
41 | prevScl.lerp(nextScl, blend);
42 |
43 | object.position.lerp(prevPos, weight);
44 | object.quaternion.slerp(prevRot, weight);
45 | object.scale.lerp(prevScl, weight);
46 | });
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/extras/BasisManager.js:
--------------------------------------------------------------------------------
1 | let supportedFormat;
2 | let id = 0;
3 |
4 | export class BasisManager {
5 | constructor(workerSrc, gl) {
6 | if (!supportedFormat) supportedFormat = this.getSupportedFormat(gl);
7 | this.onMessage = this.onMessage.bind(this);
8 | this.queue = new Map();
9 | this.initWorker(workerSrc);
10 | }
11 |
12 | getSupportedFormat(gl = document.createElement('canvas').getContext('webgl')) {
13 | /* if (!!gl.getExtension('WEBGL_compressed_texture_etc')) {
14 | return 'etc2';
15 | } else */
16 | if (!!gl.getExtension('WEBGL_compressed_texture_astc')) {
17 | return 'astc';
18 | } else if (!!gl.getExtension('EXT_texture_compression_bptc')) {
19 | return 'bptc';
20 | } else if (!!gl.getExtension('WEBGL_compressed_texture_s3tc')) {
21 | return 's3tc';
22 | } else if (!!gl.getExtension('WEBGL_compressed_texture_etc1')) {
23 | return 'etc1';
24 | } else if (!!gl.getExtension('WEBGL_compressed_texture_pvrtc') || !!gl.getExtension('WEBKIT_WEBGL_compressed_texture_pvrtc')) {
25 | return 'pvrtc';
26 | // } else if (!!gl.getExtension('WEBGL_compressed_texture_atc')) {
27 | // return 'atc';
28 | }
29 | return 'none';
30 | }
31 |
32 | initWorker(workerSrc) {
33 | this.worker = new Worker(workerSrc);
34 | this.worker.onmessage = this.onMessage;
35 | }
36 |
37 | onMessage({ data }) {
38 | const { id, error, image } = data;
39 | if (error) {
40 | console.log(error, id);
41 | return;
42 | }
43 | const textureResolve = this.queue.get(id);
44 | this.queue.delete(id);
45 | image.isBasis = true;
46 | textureResolve(image);
47 | }
48 |
49 | parseTexture(buffer) {
50 | id++;
51 | this.worker.postMessage({
52 | id,
53 | buffer,
54 | supportedFormat,
55 | });
56 | let textureResolve;
57 | const promise = new Promise((res) => (textureResolve = res));
58 | this.queue.set(id, textureResolve);
59 | return promise;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/extras/Box.js:
--------------------------------------------------------------------------------
1 | import { Geometry } from '../core/Geometry.js';
2 | import { Plane } from './Plane.js';
3 |
4 | export class Box extends Geometry {
5 | constructor(gl, { width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1, attributes = {} } = {}) {
6 | const wSegs = widthSegments;
7 | const hSegs = heightSegments;
8 | const dSegs = depthSegments;
9 |
10 | const num = (wSegs + 1) * (hSegs + 1) * 2 + (wSegs + 1) * (dSegs + 1) * 2 + (hSegs + 1) * (dSegs + 1) * 2;
11 | const numIndices = (wSegs * hSegs * 2 + wSegs * dSegs * 2 + hSegs * dSegs * 2) * 6;
12 |
13 | const position = new Float32Array(num * 3);
14 | const normal = new Float32Array(num * 3);
15 | const uv = new Float32Array(num * 2);
16 | const index = num > 65536 ? new Uint32Array(numIndices) : new Uint16Array(numIndices);
17 |
18 | let i = 0;
19 | let ii = 0;
20 |
21 | // left, right
22 | Plane.buildPlane(position, normal, uv, index, depth, height, width, dSegs, hSegs, 2, 1, 0, -1, -1, i, ii);
23 | i += (dSegs + 1) * (hSegs + 1);
24 | ii += dSegs * hSegs;
25 |
26 | Plane.buildPlane(position, normal, uv, index, depth, height, -width, dSegs, hSegs, 2, 1, 0, 1, -1, i, ii);
27 | i += (dSegs + 1) * (hSegs + 1);
28 | ii += dSegs * hSegs;
29 |
30 | // top, bottom
31 | Plane.buildPlane(position, normal, uv, index, width, depth, height, dSegs, wSegs, 0, 2, 1, 1, 1, i, ii);
32 | i += (wSegs + 1) * (dSegs + 1);
33 | ii += wSegs * dSegs;
34 |
35 | Plane.buildPlane(position, normal, uv, index, width, depth, -height, dSegs, wSegs, 0, 2, 1, 1, -1, i, ii);
36 | i += (wSegs + 1) * (dSegs + 1);
37 | ii += wSegs * dSegs;
38 |
39 | // front, back
40 | Plane.buildPlane(position, normal, uv, index, width, height, -depth, wSegs, hSegs, 0, 1, 2, -1, -1, i, ii);
41 | i += (wSegs + 1) * (hSegs + 1);
42 | ii += wSegs * hSegs;
43 |
44 | Plane.buildPlane(position, normal, uv, index, width, height, depth, wSegs, hSegs, 0, 1, 2, 1, -1, i, ii);
45 |
46 | Object.assign(attributes, {
47 | position: { size: 3, data: position },
48 | normal: { size: 3, data: normal },
49 | uv: { size: 2, data: uv },
50 | index: { data: index },
51 | });
52 |
53 | super(gl, attributes);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/extras/DracoManager.js:
--------------------------------------------------------------------------------
1 | let id = 0;
2 |
3 | export class DracoManager {
4 | constructor(workerSrc) {
5 | this.onMessage = this.onMessage.bind(this);
6 | this.queue = new Map();
7 | this.initWorker(workerSrc);
8 | }
9 |
10 | initWorker(workerSrc) {
11 | this.worker = new Worker(workerSrc);
12 | this.worker.onmessage = this.onMessage;
13 | }
14 |
15 | onMessage({ data }) {
16 | const { id, error, geometry } = data;
17 | if (error) {
18 | console.log(error, id);
19 | return;
20 | }
21 | const geometryResolve = this.queue.get(id);
22 | this.queue.delete(id);
23 | geometryResolve(geometry);
24 | }
25 |
26 | decodeGeometry(buffer, config) {
27 | id++;
28 | this.worker.postMessage({
29 | id,
30 | buffer,
31 | config,
32 | });
33 | let geometryResolve;
34 | const promise = new Promise((res) => (geometryResolve = res));
35 | this.queue.set(id, geometryResolve);
36 | return promise;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/extras/GLTFSkin.js:
--------------------------------------------------------------------------------
1 | import { Mesh } from '../core/Mesh.js';
2 | import { Mat4 } from '../math/Mat4.js';
3 | import { Texture } from '../core/Texture.js';
4 |
5 | const tempMat4 = /* @__PURE__ */ new Mat4();
6 | const identity = /* @__PURE__ */ new Mat4();
7 |
8 | export class GLTFSkin extends Mesh {
9 | constructor(gl, { skeleton, geometry, program, mode = gl.TRIANGLES } = {}) {
10 | super(gl, { geometry, program, mode });
11 | this.skeleton = skeleton;
12 | this.program = program;
13 | this.createBoneTexture();
14 | }
15 |
16 | createBoneTexture() {
17 | if (!this.skeleton.joints.length) return;
18 | const size = Math.max(4, Math.pow(2, Math.ceil(Math.log(Math.sqrt(this.skeleton.joints.length * 4)) / Math.LN2)));
19 | this.boneMatrices = new Float32Array(size * size * 4);
20 | this.boneTextureSize = size;
21 | this.boneTexture = new Texture(this.gl, {
22 | image: this.boneMatrices,
23 | generateMipmaps: false,
24 | type: this.gl.FLOAT,
25 | internalFormat: this.gl.renderer.isWebgl2 ? this.gl.RGBA32F : this.gl.RGBA,
26 | minFilter: this.gl.NEAREST,
27 | magFilter: this.gl.NEAREST,
28 | flipY: false,
29 | width: size,
30 | });
31 | }
32 |
33 | updateUniforms() {
34 | // Update bone texture
35 | this.skeleton.joints.forEach((bone, i) => {
36 | // Find difference between current and bind pose
37 | tempMat4.multiply(bone.worldMatrix, bone.bindInverse);
38 | this.boneMatrices.set(tempMat4, i * 16);
39 | });
40 | this.boneTexture.needsUpdate = true;
41 | // Reset for programs shared between multiple skins
42 | this.program.uniforms.boneTexture.value = this.boneTexture;
43 | this.program.uniforms.boneTextureSize.value = this.boneTextureSize;
44 | }
45 |
46 | draw({ camera } = {}) {
47 | if (!this.program.uniforms.boneTexture) {
48 | Object.assign(this.program.uniforms, {
49 | boneTexture: { value: this.boneTexture },
50 | boneTextureSize: { value: this.boneTextureSize },
51 | });
52 | }
53 |
54 | this.updateUniforms();
55 |
56 | // Switch the world matrix with identity to ignore any transforms
57 | // on the mesh itself - only use skeleton's transforms
58 | const _worldMatrix = this.worldMatrix;
59 | this.worldMatrix = identity;
60 |
61 | super.draw({ camera });
62 |
63 | // Switch back to leave identity untouched
64 | this.worldMatrix = _worldMatrix;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/extras/InstancedMesh.js:
--------------------------------------------------------------------------------
1 | import { Transform } from '../core/Transform.js';
2 | import { Mesh } from '../core/Mesh.js';
3 | import { Vec4 } from '../math/Vec4.js';
4 |
5 | export class InstancedMesh extends Mesh {
6 | constructor(...args) {
7 | super(...args);
8 |
9 | // Skip renderer frustum culling
10 | this.frustumCulled = false;
11 | this.isInstancedMesh = true;
12 | }
13 |
14 | addFrustumCull() {
15 | this.instanceTransforms = null;
16 | this.instanceLightmapScaleOffset = null;
17 | this.totalInstanceCount = 0;
18 | this.frustumCullFunction = null;
19 | this.instanceRenderList = null;
20 |
21 | // Get instanced mesh
22 | if (!this.geometry.attributes.instanceMatrix)
23 | console.error(`mesh ${this.name ? `"${this.name}" ` : ``}missing instanceMatrix attribute; unable to frustum cull`);
24 |
25 | // Make list of transforms from instanceMatrix
26 | const matrixData = this.geometry.attributes.instanceMatrix.data;
27 | this.instanceTransforms = [];
28 | for (let i = 0, j = 0; i < matrixData.length; i += 16, j++) {
29 | const transform = new Transform();
30 | transform.index = j;
31 | transform.matrix.fromArray(matrixData, i);
32 | transform.decompose();
33 | this.instanceTransforms.push(transform);
34 | // Add transforms to parent to update world matrices
35 | transform.setParent(this.parent);
36 | }
37 | this.totalInstanceCount = this.instanceTransforms.length;
38 |
39 | // Check for lightmap attributes - attach to transform
40 | if (!!this.geometry.attributes.lightmapScaleOffset) {
41 | const lightmapData = this.geometry.attributes.lightmapScaleOffset.data;
42 | for (let i = 0, j = 0; i < lightmapData.length; i += 4, j++) {
43 | this.instanceTransforms[j].lightmapData = new Vec4().fromArray(lightmapData, i);
44 | }
45 | }
46 |
47 | this.frustumCullFunction = ({ camera }) => {
48 | // frustum cull transforms each frame - pass world matrix
49 | this.instanceRenderList = [];
50 | this.instanceTransforms.forEach((transform) => {
51 | if (!camera.frustumIntersectsMesh(this, transform.worldMatrix)) return;
52 | this.instanceRenderList.push(transform);
53 | });
54 |
55 | // update instanceMatrix and instancedCount with visible
56 | this.instanceRenderList.forEach((transform, i) => {
57 | transform.matrix.toArray(this.geometry.attributes.instanceMatrix.data, i * 16);
58 |
59 | // Update lightmap attr
60 | if (transform.lightmapData) {
61 | transform.lightmapData.toArray(this.geometry.attributes.lightmapScaleOffset.data, i * 4);
62 | this.geometry.attributes.lightmapScaleOffset.needsUpdate = true;
63 | }
64 | });
65 | this.geometry.instancedCount = this.instanceRenderList.length;
66 | this.geometry.attributes.instanceMatrix.needsUpdate = true;
67 | };
68 |
69 | this.onBeforeRender(this.frustumCullFunction);
70 | }
71 |
72 | removeFrustumCull() {
73 | this.offBeforeRender(this.frustumCullFunction);
74 | this.geometry.instancedCount = this.totalInstanceCount;
75 | this.instanceTransforms.forEach((transform, i) => {
76 | transform.matrix.toArray(this.geometry.attributes.instanceMatrix.data, i * 16);
77 |
78 | // Update lightmap attr
79 | if (transform.lightmapData) {
80 | transform.lightmapData.toArray(this.geometry.attributes.lightmapScaleOffset.data, i * 4);
81 | this.geometry.attributes.lightmapScaleOffset.needsUpdate = true;
82 | }
83 | });
84 | this.geometry.attributes.instanceMatrix.needsUpdate = true;
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/extras/KTXTexture.js:
--------------------------------------------------------------------------------
1 | import { Texture } from '../core/Texture.js';
2 |
3 | // TODO: Support cubemaps
4 | // Generate textures using https://github.com/TimvanScherpenzeel/texture-compressor
5 |
6 | export class KTXTexture extends Texture {
7 | constructor(gl, { buffer, wrapS = gl.CLAMP_TO_EDGE, wrapT = gl.CLAMP_TO_EDGE, anisotropy = 0, minFilter, magFilter } = {}) {
8 | super(gl, {
9 | generateMipmaps: false,
10 | wrapS,
11 | wrapT,
12 | anisotropy,
13 | minFilter,
14 | magFilter,
15 | });
16 |
17 | if (buffer) return this.parseBuffer(buffer);
18 | }
19 |
20 | parseBuffer(buffer) {
21 | const ktx = new KhronosTextureContainer(buffer);
22 | ktx.mipmaps.isCompressedTexture = true;
23 |
24 | // Update texture
25 | this.image = ktx.mipmaps;
26 | this.internalFormat = ktx.glInternalFormat;
27 | if (ktx.numberOfMipmapLevels > 1) {
28 | if (this.minFilter === this.gl.LINEAR) this.minFilter = this.gl.NEAREST_MIPMAP_LINEAR;
29 | } else {
30 | if (this.minFilter === this.gl.NEAREST_MIPMAP_LINEAR) this.minFilter = this.gl.LINEAR;
31 | }
32 |
33 | // TODO: support cube maps
34 | // ktx.numberOfFaces
35 | }
36 | }
37 |
38 | function KhronosTextureContainer(buffer) {
39 | const idCheck = [0xab, 0x4b, 0x54, 0x58, 0x20, 0x31, 0x31, 0xbb, 0x0d, 0x0a, 0x1a, 0x0a];
40 | const id = new Uint8Array(buffer, 0, 12);
41 | for (let i = 0; i < id.length; i++) if (id[i] !== idCheck[i]) return console.error('File missing KTX identifier');
42 |
43 | // TODO: Is this always 4? Tested: [android, macos]
44 | const size = Uint32Array.BYTES_PER_ELEMENT;
45 | const head = new DataView(buffer, 12, 13 * size);
46 | const littleEndian = head.getUint32(0, true) === 0x04030201;
47 | const glType = head.getUint32(1 * size, littleEndian);
48 | if (glType !== 0) return console.warn('only compressed formats currently supported');
49 | this.glInternalFormat = head.getUint32(4 * size, littleEndian);
50 | let width = head.getUint32(6 * size, littleEndian);
51 | let height = head.getUint32(7 * size, littleEndian);
52 | this.numberOfFaces = head.getUint32(10 * size, littleEndian);
53 | this.numberOfMipmapLevels = Math.max(1, head.getUint32(11 * size, littleEndian));
54 | const bytesOfKeyValueData = head.getUint32(12 * size, littleEndian);
55 |
56 | this.mipmaps = [];
57 | let offset = 12 + 13 * 4 + bytesOfKeyValueData;
58 | for (let level = 0; level < this.numberOfMipmapLevels; level++) {
59 | const levelSize = new Int32Array(buffer, offset, 1)[0]; // size per face, since not supporting array cubemaps
60 | offset += 4; // levelSize field
61 | for (let face = 0; face < this.numberOfFaces; face++) {
62 | const data = new Uint8Array(buffer, offset, levelSize);
63 | this.mipmaps.push({ data, width, height });
64 | offset += levelSize;
65 | offset += 3 - ((levelSize + 3) % 4); // add padding for odd sized image
66 | }
67 | width = width >> 1;
68 | height = height >> 1;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/extras/NormalProgram.js:
--------------------------------------------------------------------------------
1 | import { Program } from '../core/Program.js';
2 |
3 | const vertex = /* glsl */ `
4 | precision highp float;
5 | precision highp int;
6 |
7 | attribute vec3 position;
8 | attribute vec3 normal;
9 |
10 | uniform mat3 normalMatrix;
11 | uniform mat4 modelViewMatrix;
12 | uniform mat4 projectionMatrix;
13 |
14 | varying vec3 vNormal;
15 |
16 | void main() {
17 | vNormal = normalize(normalMatrix * normal);
18 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
19 | }
20 | `;
21 |
22 | const fragment = /* glsl */ `
23 | precision highp float;
24 | precision highp int;
25 |
26 | varying vec3 vNormal;
27 |
28 | void main() {
29 | gl_FragColor.rgb = normalize(vNormal);
30 | gl_FragColor.a = 1.0;
31 | }
32 | `;
33 |
34 | export function NormalProgram(gl) {
35 | return new Program(gl, {
36 | vertex: vertex,
37 | fragment: fragment,
38 | cullFace: false,
39 | });
40 | }
41 |
--------------------------------------------------------------------------------
/src/extras/Plane.js:
--------------------------------------------------------------------------------
1 | import { Geometry } from '../core/Geometry.js';
2 |
3 | export class Plane extends Geometry {
4 | constructor(gl, { width = 1, height = 1, widthSegments = 1, heightSegments = 1, attributes = {} } = {}) {
5 | const wSegs = widthSegments;
6 | const hSegs = heightSegments;
7 |
8 | // Determine length of arrays
9 | const num = (wSegs + 1) * (hSegs + 1);
10 | const numIndices = wSegs * hSegs * 6;
11 |
12 | // Generate empty arrays once
13 | const position = new Float32Array(num * 3);
14 | const normal = new Float32Array(num * 3);
15 | const uv = new Float32Array(num * 2);
16 | const index = numIndices > 65536 ? new Uint32Array(numIndices) : new Uint16Array(numIndices);
17 |
18 | Plane.buildPlane(position, normal, uv, index, width, height, 0, wSegs, hSegs);
19 |
20 | Object.assign(attributes, {
21 | position: { size: 3, data: position },
22 | normal: { size: 3, data: normal },
23 | uv: { size: 2, data: uv },
24 | index: { data: index },
25 | });
26 |
27 | super(gl, attributes);
28 | }
29 |
30 | static buildPlane(position, normal, uv, index, width, height, depth, wSegs, hSegs, u = 0, v = 1, w = 2, uDir = 1, vDir = -1, i = 0, ii = 0) {
31 | const io = i;
32 | const segW = width / wSegs;
33 | const segH = height / hSegs;
34 |
35 | for (let iy = 0; iy <= hSegs; iy++) {
36 | let y = iy * segH - height / 2;
37 | for (let ix = 0; ix <= wSegs; ix++, i++) {
38 | let x = ix * segW - width / 2;
39 |
40 | position[i * 3 + u] = x * uDir;
41 | position[i * 3 + v] = y * vDir;
42 | position[i * 3 + w] = depth / 2;
43 |
44 | normal[i * 3 + u] = 0;
45 | normal[i * 3 + v] = 0;
46 | normal[i * 3 + w] = depth >= 0 ? 1 : -1;
47 |
48 | uv[i * 2] = ix / wSegs;
49 | uv[i * 2 + 1] = 1 - iy / hSegs;
50 |
51 | if (iy === hSegs || ix === wSegs) continue;
52 | let a = io + ix + iy * (wSegs + 1);
53 | let b = io + ix + (iy + 1) * (wSegs + 1);
54 | let c = io + ix + (iy + 1) * (wSegs + 1) + 1;
55 | let d = io + ix + iy * (wSegs + 1) + 1;
56 |
57 | index[ii * 6] = a;
58 | index[ii * 6 + 1] = b;
59 | index[ii * 6 + 2] = d;
60 | index[ii * 6 + 3] = b;
61 | index[ii * 6 + 4] = c;
62 | index[ii * 6 + 5] = d;
63 | ii++;
64 | }
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/extras/Shadow.js:
--------------------------------------------------------------------------------
1 | import { Camera } from '../core/Camera.js';
2 | import { Program } from '../core/Program.js';
3 | import { RenderTarget } from '../core/RenderTarget.js';
4 |
5 | export class Shadow {
6 | constructor(gl, { light = new Camera(gl), width = 1024, height = width }) {
7 | this.gl = gl;
8 |
9 | this.light = light;
10 |
11 | this.target = new RenderTarget(gl, { width, height });
12 | this.targetUniform = { value: this.target.texture };
13 |
14 | this.depthProgram = new Program(gl, {
15 | vertex: defaultVertex,
16 | fragment: defaultFragment,
17 | cullFace: false,
18 | });
19 |
20 | this.castMeshes = [];
21 | }
22 |
23 | add({
24 | mesh,
25 | receive = true,
26 | cast = true,
27 | vertex = defaultVertex,
28 | fragment = defaultFragment,
29 | uniformProjection = 'shadowProjectionMatrix',
30 | uniformView = 'shadowViewMatrix',
31 | uniformTexture = 'tShadow',
32 | }) {
33 | // Add uniforms to existing program
34 | if (receive && !mesh.program.uniforms[uniformProjection]) {
35 | mesh.program.uniforms[uniformProjection] = { value: this.light.projectionMatrix };
36 | mesh.program.uniforms[uniformView] = { value: this.light.viewMatrix };
37 | mesh.program.uniforms[uniformTexture] = this.targetUniform;
38 | }
39 |
40 | if (!cast) return;
41 | this.castMeshes.push(mesh);
42 |
43 | // Store program for when switching between depth override
44 | mesh.colorProgram = mesh.program;
45 |
46 | // Check if depth program already attached
47 | if (mesh.depthProgram) return;
48 |
49 | // Use global depth override if nothing custom passed in
50 | if (vertex === defaultVertex && fragment === defaultFragment) {
51 | mesh.depthProgram = this.depthProgram;
52 | return;
53 | }
54 |
55 | // Create custom override program
56 | mesh.depthProgram = new Program(this.gl, {
57 | vertex,
58 | fragment,
59 | cullFace: false,
60 | });
61 | }
62 |
63 | setSize({ width = 1024, height = width }) {
64 | this.target = new RenderTarget(this.gl, { width, height });
65 | this.targetUniform.value = this.target.texture;
66 | }
67 |
68 | render({ scene }) {
69 | // For depth render, replace program with depth override.
70 | // Hide meshes not casting shadows.
71 | scene.traverse((node) => {
72 | if (!node.draw) return;
73 | if (!!~this.castMeshes.indexOf(node)) {
74 | node.program = node.depthProgram;
75 | } else {
76 | node.isForceVisibility = node.visible;
77 | node.visible = false;
78 | }
79 | });
80 |
81 | // Render the depth shadow map using the light as the camera
82 | this.gl.renderer.render({
83 | scene,
84 | camera: this.light,
85 | target: this.target,
86 | });
87 |
88 | // Then switch the program back to the normal one
89 | scene.traverse((node) => {
90 | if (!node.draw) return;
91 | if (!!~this.castMeshes.indexOf(node)) {
92 | node.program = node.colorProgram;
93 | } else {
94 | node.visible = node.isForceVisibility;
95 | }
96 | });
97 | }
98 | }
99 |
100 | const defaultVertex = /* glsl */ `
101 | attribute vec3 position;
102 | attribute vec2 uv;
103 |
104 | uniform mat4 modelViewMatrix;
105 | uniform mat4 projectionMatrix;
106 |
107 | void main() {
108 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
109 | }
110 | `;
111 |
112 | const defaultFragment = /* glsl */ `
113 | precision highp float;
114 |
115 | vec4 packRGBA (float v) {
116 | vec4 pack = fract(vec4(1.0, 255.0, 65025.0, 16581375.0) * v);
117 | pack -= pack.yzww * vec2(1.0 / 255.0, 0.0).xxxy;
118 | return pack;
119 | }
120 |
121 | void main() {
122 | gl_FragColor = packRGBA(gl_FragCoord.z);
123 | }
124 | `;
125 |
--------------------------------------------------------------------------------
/src/extras/Skin.js:
--------------------------------------------------------------------------------
1 | import { Mesh } from '../core/Mesh.js';
2 | import { Transform } from '../core/Transform.js';
3 | import { Mat4 } from '../math/Mat4.js';
4 | import { Texture } from '../core/Texture.js';
5 | import { Animation } from './Animation.js';
6 |
7 | const tempMat4 = /* @__PURE__ */ new Mat4();
8 |
9 | export class Skin extends Mesh {
10 | constructor(gl, { rig, geometry, program, mode = gl.TRIANGLES } = {}) {
11 | super(gl, { geometry, program, mode });
12 |
13 | this.createBones(rig);
14 | this.createBoneTexture();
15 | this.animations = [];
16 |
17 | Object.assign(this.program.uniforms, {
18 | boneTexture: { value: this.boneTexture },
19 | boneTextureSize: { value: this.boneTextureSize },
20 | });
21 | }
22 |
23 | createBones(rig) {
24 | // Create root so that can simply update world matrix of whole skeleton
25 | this.root = new Transform();
26 |
27 | // Create bones
28 | this.bones = [];
29 | if (!rig.bones || !rig.bones.length) return;
30 | for (let i = 0; i < rig.bones.length; i++) {
31 | const bone = new Transform();
32 |
33 | // Set initial values (bind pose)
34 | bone.position.fromArray(rig.bindPose.position, i * 3);
35 | bone.quaternion.fromArray(rig.bindPose.quaternion, i * 4);
36 | bone.scale.fromArray(rig.bindPose.scale, i * 3);
37 |
38 | this.bones.push(bone);
39 | }
40 |
41 | // Once created, set the hierarchy
42 | rig.bones.forEach((data, i) => {
43 | this.bones[i].name = data.name;
44 | if (data.parent === -1) return this.bones[i].setParent(this.root);
45 | this.bones[i].setParent(this.bones[data.parent]);
46 | });
47 |
48 | // Then update to calculate world matrices
49 | this.root.updateMatrixWorld(true);
50 |
51 | // Store inverse of bind pose to calculate differences
52 | this.bones.forEach((bone) => {
53 | bone.bindInverse = new Mat4(...bone.worldMatrix).inverse();
54 | });
55 | }
56 |
57 | createBoneTexture() {
58 | if (!this.bones.length) return;
59 | const size = Math.max(4, Math.pow(2, Math.ceil(Math.log(Math.sqrt(this.bones.length * 4)) / Math.LN2)));
60 | this.boneMatrices = new Float32Array(size * size * 4);
61 | this.boneTextureSize = size;
62 | this.boneTexture = new Texture(this.gl, {
63 | image: this.boneMatrices,
64 | generateMipmaps: false,
65 | type: this.gl.FLOAT,
66 | internalFormat: this.gl.renderer.isWebgl2 ? this.gl.RGBA32F : this.gl.RGBA,
67 | minFilter: this.gl.NEAREST,
68 | magFilter: this.gl.NEAREST,
69 | flipY: false,
70 | width: size,
71 | });
72 | }
73 |
74 | addAnimation(data) {
75 | const animation = new Animation({ objects: this.bones, data });
76 | this.animations.push(animation);
77 | return animation;
78 | }
79 |
80 | update() {
81 | // Calculate combined animation weight
82 | let total = 0;
83 | this.animations.forEach((animation) => (total += animation.weight));
84 |
85 | this.animations.forEach((animation, i) => {
86 | // force first animation to set in order to reset frame
87 | animation.update(total, i === 0);
88 | });
89 | }
90 |
91 | draw({ camera } = {}) {
92 | // Update world matrices manually, as not part of scene graph
93 | this.root.updateMatrixWorld(true);
94 |
95 | // Update bone texture
96 | this.bones.forEach((bone, i) => {
97 | // Find difference between current and bind pose
98 | tempMat4.multiply(bone.worldMatrix, bone.bindInverse);
99 | this.boneMatrices.set(tempMat4, i * 16);
100 | });
101 | if (this.boneTexture) this.boneTexture.needsUpdate = true;
102 |
103 | super.draw({ camera });
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/extras/Sphere.js:
--------------------------------------------------------------------------------
1 | import { Geometry } from '../core/Geometry.js';
2 | import { Vec3 } from '../math/Vec3.js';
3 |
4 | export class Sphere extends Geometry {
5 | constructor(
6 | gl,
7 | {
8 | radius = 0.5,
9 | widthSegments = 16,
10 | heightSegments = Math.ceil(widthSegments * 0.5),
11 | phiStart = 0,
12 | phiLength = Math.PI * 2,
13 | thetaStart = 0,
14 | thetaLength = Math.PI,
15 | attributes = {},
16 | } = {}
17 | ) {
18 | const wSegs = widthSegments;
19 | const hSegs = heightSegments;
20 | const pStart = phiStart;
21 | const pLength = phiLength;
22 | const tStart = thetaStart;
23 | const tLength = thetaLength;
24 |
25 | const num = (wSegs + 1) * (hSegs + 1);
26 | const numIndices = wSegs * hSegs * 6;
27 |
28 | const position = new Float32Array(num * 3);
29 | const normal = new Float32Array(num * 3);
30 | const uv = new Float32Array(num * 2);
31 | const index = num > 65536 ? new Uint32Array(numIndices) : new Uint16Array(numIndices);
32 |
33 | let i = 0;
34 | let iv = 0;
35 | let ii = 0;
36 | let te = tStart + tLength;
37 | const grid = [];
38 |
39 | let n = new Vec3();
40 |
41 | for (let iy = 0; iy <= hSegs; iy++) {
42 | let vRow = [];
43 | let v = iy / hSegs;
44 | for (let ix = 0; ix <= wSegs; ix++, i++) {
45 | let u = ix / wSegs;
46 | let x = -radius * Math.cos(pStart + u * pLength) * Math.sin(tStart + v * tLength);
47 | let y = radius * Math.cos(tStart + v * tLength);
48 | let z = radius * Math.sin(pStart + u * pLength) * Math.sin(tStart + v * tLength);
49 |
50 | position[i * 3] = x;
51 | position[i * 3 + 1] = y;
52 | position[i * 3 + 2] = z;
53 |
54 | n.set(x, y, z).normalize();
55 | normal[i * 3] = n.x;
56 | normal[i * 3 + 1] = n.y;
57 | normal[i * 3 + 2] = n.z;
58 |
59 | uv[i * 2] = u;
60 | uv[i * 2 + 1] = 1 - v;
61 |
62 | vRow.push(iv++);
63 | }
64 |
65 | grid.push(vRow);
66 | }
67 |
68 | for (let iy = 0; iy < hSegs; iy++) {
69 | for (let ix = 0; ix < wSegs; ix++) {
70 | let a = grid[iy][ix + 1];
71 | let b = grid[iy][ix];
72 | let c = grid[iy + 1][ix];
73 | let d = grid[iy + 1][ix + 1];
74 |
75 | if (iy !== 0 || tStart > 0) {
76 | index[ii * 3] = a;
77 | index[ii * 3 + 1] = b;
78 | index[ii * 3 + 2] = d;
79 | ii++;
80 | }
81 | if (iy !== hSegs - 1 || te < Math.PI) {
82 | index[ii * 3] = b;
83 | index[ii * 3 + 1] = c;
84 | index[ii * 3 + 2] = d;
85 | ii++;
86 | }
87 | }
88 | }
89 |
90 | Object.assign(attributes, {
91 | position: { size: 3, data: position },
92 | normal: { size: 3, data: normal },
93 | uv: { size: 2, data: uv },
94 | index: { data: index },
95 | });
96 |
97 | super(gl, attributes);
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/extras/Texture3D.js:
--------------------------------------------------------------------------------
1 | import { Texture } from '../core/Texture.js';
2 |
3 | export class Texture3D extends Texture {
4 | constructor(gl, args) {
5 | super(gl, {
6 | ...args,
7 | target: gl.TEXTURE_3D,
8 | width: args.width ? args.width : 2,
9 | height: args.height ? args.height : 2,
10 | });
11 |
12 | const image = new Image();
13 | image.crossOrigin = '*';
14 | image.src = args.src;
15 |
16 | image.onload = () => {
17 | let canvas = document.createElement('canvas');
18 | canvas.width = image.width;
19 | canvas.height = image.height;
20 |
21 | let ctx = canvas.getContext('2d');
22 | ctx.scale(1, -1);
23 | ctx.translate(0, -image.height);
24 | ctx.drawImage(image, 0, 0);
25 | const imageData = ctx.getImageData(0, 0, image.width, image.height).data;
26 |
27 | canvas = null;
28 | ctx = null;
29 | let elementCount;
30 |
31 | switch (this.format) {
32 | case gl.RED:
33 | elementCount = 1;
34 | break;
35 | case gl.RG:
36 | elementCount = 2;
37 | break;
38 | case gl.RGB:
39 | elementCount = 3;
40 | break;
41 | default:
42 | elementCount = 4;
43 | break;
44 | }
45 |
46 | const dataCount = this.width * this.height * this.length * elementCount;
47 | const data = this.type === gl.UNSIGNED_BYTE ? new Uint8Array(dataCount) : new Float32Array(dataCount);
48 |
49 | let dataIterator = 0;
50 |
51 | for (let z = 0; z < this.length; z++) {
52 | for (let y = 0; y < this.height; y++) {
53 | for (let x = 0; x < this.width; x++) {
54 | let zOffsetX = (z % args.tileCountX) * this.width;
55 | let zOffsetY = Math.floor(z / args.tileCountX) * (this.width * this.height * args.tileCountX);
56 | let index = x + zOffsetX + (y * image.width + zOffsetY);
57 |
58 | const r = imageData[index * 4];
59 | const g = imageData[index * 4 + 1];
60 | const b = imageData[index * 4 + 2];
61 | const a = imageData[index * 4 + 3];
62 |
63 | let texel = [r, g, b, a];
64 |
65 | for (let i = 0; i < elementCount; i++) {
66 | if (this.type === this.gl.UNSIGNED_BYTE) {
67 | data[dataIterator++] = texel[i];
68 | } else {
69 | data[dataIterator++] = texel[i] / 255;
70 | }
71 | }
72 | }
73 | }
74 | }
75 |
76 | this.image = data;
77 | this.needsUpdate = true;
78 | };
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/extras/Torus.js:
--------------------------------------------------------------------------------
1 | // https://github.com/mrdoob/three.js/blob/master/src/geometries/TorusGeometry.js
2 |
3 | import { Geometry } from '../core/Geometry.js';
4 | import { Vec3 } from '../math/Vec3.js';
5 |
6 | export class Torus extends Geometry {
7 | constructor(gl, { radius = 0.5, tube = 0.2, radialSegments = 8, tubularSegments = 6, arc = Math.PI * 2, attributes = {} } = {}) {
8 | const num = (radialSegments + 1) * (tubularSegments + 1);
9 | const numIndices = radialSegments * tubularSegments * 6;
10 |
11 | const vertices = new Float32Array(num * 3);
12 | const normals = new Float32Array(num * 3);
13 | const uvs = new Float32Array(num * 2);
14 | const indices = num > 65536 ? new Uint32Array(numIndices) : new Uint16Array(numIndices);
15 |
16 | const center = new Vec3();
17 | const vertex = new Vec3();
18 | const normal = new Vec3();
19 |
20 | // generate vertices, normals and uvs
21 | let idx = 0;
22 | for (let j = 0; j <= radialSegments; j++) {
23 | for (let i = 0; i <= tubularSegments; i++, idx++) {
24 | const u = (i / tubularSegments) * arc;
25 | const v = (j / radialSegments) * Math.PI * 2;
26 |
27 | // vertex
28 | vertex.x = (radius + tube * Math.cos(v)) * Math.cos(u);
29 | vertex.y = (radius + tube * Math.cos(v)) * Math.sin(u);
30 | vertex.z = tube * Math.sin(v);
31 |
32 | vertices.set([vertex.x, vertex.y, vertex.z], idx * 3);
33 |
34 | // normal
35 | center.x = radius * Math.cos(u);
36 | center.y = radius * Math.sin(u);
37 | normal.sub(vertex, center).normalize();
38 |
39 | normals.set([normal.x, normal.y, normal.z], idx * 3);
40 |
41 | // uv
42 | uvs.set([i / tubularSegments, j / radialSegments], idx * 2);
43 | }
44 | }
45 |
46 | // generate indices
47 | idx = 0;
48 | for (let j = 1; j <= radialSegments; j++) {
49 | for (let i = 1; i <= tubularSegments; i++, idx++) {
50 | // indices
51 | const a = (tubularSegments + 1) * j + i - 1;
52 | const b = (tubularSegments + 1) * (j - 1) + i - 1;
53 | const c = (tubularSegments + 1) * (j - 1) + i;
54 | const d = (tubularSegments + 1) * j + i;
55 |
56 | // faces
57 | indices.set([a, b, d, b, c, d], idx * 6);
58 | }
59 | }
60 |
61 | Object.assign(attributes, {
62 | position: { size: 3, data: vertices },
63 | normal: { size: 3, data: normals },
64 | uv: { size: 2, data: uvs },
65 | index: { data: indices },
66 | });
67 |
68 | super(gl, attributes);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/extras/Triangle.js:
--------------------------------------------------------------------------------
1 | import { Geometry } from '../core/Geometry.js';
2 |
3 | export class Triangle extends Geometry {
4 | constructor(gl, { attributes = {} } = {}) {
5 | Object.assign(attributes, {
6 | position: { size: 2, data: new Float32Array([-1, -1, 3, -1, -1, 3]) },
7 | uv: { size: 2, data: new Float32Array([0, 0, 2, 0, 0, 2]) },
8 | });
9 |
10 | super(gl, attributes);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/extras/Tube.js:
--------------------------------------------------------------------------------
1 | import { Geometry } from '../core/Geometry.js';
2 | import { Vec3 } from '../math/Vec3.js';
3 | import { Vec2 } from '../math/Vec2.js';
4 |
5 | // helper variables
6 | const vertex = /* @__PURE__ */ new Vec3();
7 | const normal = /* @__PURE__ */ new Vec3();
8 | const uv = /* @__PURE__ */ new Vec2();
9 | const point = /* @__PURE__ */ new Vec3();
10 |
11 | export class Tube extends Geometry {
12 | constructor(gl, { path, radius = 1, tubularSegments = 64, radialSegments = 8, closed = false, attributes = {} } = {}) {
13 | super(gl, attributes);
14 |
15 | this.path = path;
16 | this.radius = radius;
17 | this.tubularSegments = tubularSegments;
18 | this.radialSegments = radialSegments;
19 | this.closed = closed;
20 |
21 | this.frenetFrames = path.computeFrenetFrames(tubularSegments, closed);
22 |
23 | const numVertices = (tubularSegments + 1) * (radialSegments + 1);
24 | const numIndices = tubularSegments * radialSegments * 6;
25 | this.positions = new Float32Array(numVertices * 3);
26 | this.normals = new Float32Array(numVertices * 3);
27 | this.uvs = new Float32Array(numVertices * 2);
28 | this.indices = numVertices > 65536 ? new Uint32Array(numIndices) : new Uint16Array(numIndices);
29 |
30 | // create buffer data
31 | this._generateAttributes();
32 | this._generateIndices();
33 |
34 | this.addAttribute('position', { size: 3, data: this.positions });
35 | this.addAttribute('normal', { size: 3, data: this.normals });
36 | this.addAttribute('uv', { size: 2, data: this.uvs });
37 | this.setIndex({ data: this.indices });
38 | }
39 |
40 | _generateAttributes() {
41 | for (let i = 0; i <= this.tubularSegments; i++) {
42 | let ci = i;
43 | if (i === this.tubularSegments) {
44 | // if the geometry is not closed, generate the last row of vertices and normals
45 | // at the regular position on the given path
46 | // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
47 | ci = this.closed ? 0 : this.tubularSegments;
48 | }
49 |
50 | this.path.getPointAt(ci / this.tubularSegments, point);
51 | // retrieve corresponding normal and binormal
52 | const N = this.frenetFrames.normals[ci];
53 | const B = this.frenetFrames.binormals[ci];
54 |
55 | // generate normals and vertices for the current segment
56 | for (let j = 0; j <= this.radialSegments; j++) {
57 | const v = (j / this.radialSegments) * Math.PI * 2;
58 | const sin = Math.sin(v);
59 | const cos = -Math.cos(v);
60 |
61 | const idx = i * (this.radialSegments + 1) + j;
62 |
63 | // normal
64 | normal.x = cos * N.x + sin * B.x;
65 | normal.y = cos * N.y + sin * B.y;
66 | normal.z = cos * N.z + sin * B.z;
67 | // normal.normalize(); // ???
68 | this.normals.set(normal, idx * 3);
69 |
70 | // vertex
71 | vertex.x = point.x + this.radius * normal.x;
72 | vertex.y = point.y + this.radius * normal.y;
73 | vertex.z = point.z + this.radius * normal.z;
74 | this.positions.set(vertex, idx * 3);
75 |
76 | // uv
77 | uv.x = i / this.tubularSegments;
78 | uv.y = j / this.radialSegments;
79 | this.uvs.set(uv, idx * 2);
80 | }
81 | }
82 | }
83 |
84 | _generateIndices() {
85 | for (let j = 1; j <= this.tubularSegments; j++) {
86 | for (let i = 1; i <= this.radialSegments; i++) {
87 | const a = (this.radialSegments + 1) * (j - 1) + (i - 1);
88 | const b = (this.radialSegments + 1) * j + (i - 1);
89 | const c = (this.radialSegments + 1) * j + i;
90 | const d = (this.radialSegments + 1) * (j - 1) + i;
91 |
92 | const idx = (j - 1) * this.radialSegments + (i - 1);
93 | this.indices.set([a, b, d, b, c, d], idx * 6);
94 | }
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/extras/WireMesh.js:
--------------------------------------------------------------------------------
1 | import { Mesh } from '../core/Mesh.js';
2 | import { Program } from '../core/Program.js';
3 | import { Geometry } from '../core/Geometry.js';
4 | import { Color } from '../math/Color.js';
5 |
6 | export class WireMesh extends Mesh {
7 | constructor(gl, { geometry, wireColor = new Color(0, 0.75, 0.5), ...meshProps } = {}) {
8 | const wireProgram = new Program(gl, {
9 | vertex,
10 | fragment,
11 | uniforms: { wireColor: { value: wireColor } },
12 | });
13 |
14 | const positionArray = geometry.attributes.position.data;
15 | const indices = [];
16 | const hashSet = new Set();
17 |
18 | function addUniqueIndices(idx) {
19 | for (let i = 0; i < idx.length; i += 2) {
20 | if (isUniqueEdgePosition(idx[i] * 3, idx[i + 1] * 3, positionArray, hashSet)) {
21 | indices.push(idx[i], idx[i + 1]);
22 | }
23 | }
24 | }
25 |
26 | if (geometry.attributes.index) {
27 | const idata = geometry.attributes.index.data;
28 |
29 | for (let i = 0; i < idata.length; i += 3) {
30 | // For every triangle, make three line pairs (start, end)
31 | // prettier-ignore
32 | addUniqueIndices([
33 | idata[i], idata[i + 1],
34 | idata[i + 1], idata[i + 2],
35 | idata[i + 2], idata[i]
36 | ]);
37 | }
38 | } else {
39 | const numVertices = Math.floor(positionArray.length / 3);
40 |
41 | for (let i = 0; i < numVertices; i += 3) {
42 | addUniqueIndices([i, i + 1, i + 1, i + 2, i + 2, i]);
43 | }
44 | }
45 |
46 | const indicesTyped = indices.length > 65536 ? new Uint32Array(indices) : new Uint16Array(indices);
47 | const wireGeometry = new Geometry(gl, {
48 | position: { ...geometry.attributes.position },
49 | index: { data: indicesTyped },
50 | });
51 |
52 | super(gl, { ...meshProps, mode: gl.LINES, geometry: wireGeometry, program: wireProgram });
53 | }
54 | }
55 |
56 | // from https://github.com/mrdoob/three.js/blob/0c26bb4bb8220126447c8373154ac045588441de/src/geometries/WireframeGeometry.js#L116
57 | function isUniqueEdgePosition(start, end, pos, hashSet) {
58 | // prettier-ignore
59 | const hash1 = [
60 | pos[start], pos[start + 1], pos[start + 2],
61 | pos[end], pos[end + 1], pos[end + 2]
62 | ].join('#');
63 |
64 | // coincident edge
65 | // prettier-ignore
66 | const hash2 = [
67 | pos[end], pos[end + 1], pos[end + 2],
68 | pos[start], pos[start + 1], pos[start + 2]
69 | ].join('#');
70 |
71 | const oldSize = hashSet.size;
72 | hashSet.add(hash1);
73 | hashSet.add(hash2);
74 | return hashSet.size - oldSize === 2;
75 | }
76 |
77 | const vertex = /* glsl */ `
78 | attribute vec3 position;
79 | uniform mat4 modelViewMatrix;
80 | uniform mat4 projectionMatrix;
81 |
82 | void main() {
83 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
84 | }
85 | `;
86 |
87 | const fragment = /* glsl */ `
88 | precision highp float;
89 | uniform vec3 wireColor;
90 |
91 | void main() {
92 | gl_FragColor = vec4(wireColor, 1.0);
93 | }
94 | `;
95 |
--------------------------------------------------------------------------------
/src/extras/helpers/AxesHelper.js:
--------------------------------------------------------------------------------
1 | import { Mesh } from '../../core/Mesh.js';
2 | import { Program } from '../../core/Program.js';
3 | import { Geometry } from '../../core/Geometry.js';
4 | import { Vec3 } from '../../math/Vec3.js';
5 |
6 | export class AxesHelper extends Mesh {
7 | constructor(
8 | gl,
9 | {
10 | size = 1,
11 | symmetric = false,
12 | xColor = new Vec3(0.96, 0.21, 0.32),
13 | yColor = new Vec3(0.44, 0.64, 0.11),
14 | zColor = new Vec3(0.18, 0.52, 0.89),
15 | ...meshProps
16 | } = {}
17 | ) {
18 | const a = symmetric ? -size : 0;
19 | const b = size;
20 |
21 | // prettier-ignore
22 | const vertices = new Float32Array([
23 | a, 0, 0, b, 0, 0,
24 | 0, a, 0, 0, b, 0,
25 | 0, 0, a, 0, 0, b
26 | ]);
27 |
28 | // prettier-ignore
29 | const colors = new Float32Array([
30 | ...xColor, ...xColor,
31 | ...yColor, ...yColor,
32 | ...zColor, ...zColor
33 | ]);
34 |
35 | const geometry = new Geometry(gl, {
36 | position: { size: 3, data: vertices },
37 | color: { size: 3, data: colors },
38 | });
39 |
40 | const program = new Program(gl, { vertex, fragment });
41 |
42 | super(gl, { ...meshProps, mode: gl.LINES, geometry, program });
43 | }
44 | }
45 |
46 | const vertex = /* glsl */ `
47 | attribute vec3 position;
48 | attribute vec3 color;
49 | uniform mat4 modelViewMatrix;
50 | uniform mat4 projectionMatrix;
51 |
52 | varying vec3 vColor;
53 |
54 | void main() {
55 | vColor = color;
56 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
57 | }
58 | `;
59 |
60 | const fragment = /* glsl */ `
61 | precision highp float;
62 | varying vec3 vColor;
63 |
64 | void main() {
65 | gl_FragColor = vec4(vColor, 1.0);
66 | }
67 | `;
68 |
--------------------------------------------------------------------------------
/src/extras/helpers/FaceNormalsHelper.js:
--------------------------------------------------------------------------------
1 | import { Mesh } from '../../core/Mesh.js';
2 | import { Program } from '../../core/Program.js';
3 | import { Geometry } from '../../core/Geometry.js';
4 | import { Vec3 } from '../../math/Vec3.js';
5 | import { Mat3 } from '../../math/Mat3.js';
6 |
7 | const vA = /* @__PURE__ */ new Vec3();
8 | const vB = /* @__PURE__ */ new Vec3();
9 | const vC = /* @__PURE__ */ new Vec3();
10 | const vCenter = /* @__PURE__ */ new Vec3();
11 | const vNormal = /* @__PURE__ */ new Vec3();
12 |
13 | export class FaceNormalsHelper extends Mesh {
14 | constructor(object, { size = 0.1, color = new Vec3(0.15, 0.86, 0.86), ...meshProps } = {}) {
15 | const gl = object.gl;
16 |
17 | const positionData = object.geometry.attributes.position.data;
18 | const sizeData = new Float32Array([0, size]);
19 |
20 | const indexAttr = object.geometry.attributes.index;
21 | const getIndex = indexAttr ? (i) => indexAttr.data[i] : (i) => i;
22 | const numVertices = indexAttr ? indexAttr.data.length : Math.floor(positionData.length / 3);
23 |
24 | const nNormals = Math.floor(numVertices / 3);
25 | const positionsArray = new Float32Array(nNormals * 2 * 3);
26 | const normalsArray = new Float32Array(nNormals * 2 * 3);
27 | const sizeArray = new Float32Array(nNormals * 2);
28 |
29 | for (let i = 0; i < numVertices; i += 3) {
30 | vA.fromArray(positionData, getIndex(i + 0) * 3);
31 | vB.fromArray(positionData, getIndex(i + 1) * 3);
32 | vC.fromArray(positionData, getIndex(i + 2) * 3);
33 |
34 | vCenter
35 | .add(vA, vB)
36 | .add(vC)
37 | .multiply(1 / 3);
38 |
39 | vA.sub(vA, vB);
40 | vC.sub(vC, vB);
41 | vNormal.cross(vC, vA).normalize();
42 |
43 | // duplicate position and normal for line start and end point
44 | const i2 = i * 2;
45 | positionsArray.set(vCenter, i2);
46 | positionsArray.set(vCenter, i2 + 3);
47 |
48 | normalsArray.set(vNormal, i2);
49 | normalsArray.set(vNormal, i2 + 3);
50 | sizeArray.set(sizeData, (i / 3) * 2);
51 | }
52 |
53 | const geometry = new Geometry(gl, {
54 | position: { size: 3, data: positionsArray },
55 | normal: { size: 3, data: normalsArray },
56 | size: { size: 1, data: sizeArray },
57 | });
58 |
59 | const program = new Program(gl, {
60 | vertex,
61 | fragment,
62 | uniforms: {
63 | color: { value: color },
64 | worldNormalMatrix: { value: new Mat3() },
65 | objectWorldMatrix: { value: object.worldMatrix },
66 | },
67 | });
68 |
69 | super(gl, { ...meshProps, mode: gl.LINES, geometry, program });
70 |
71 | this.object = object;
72 | }
73 |
74 | draw(arg) {
75 | this.program.uniforms.worldNormalMatrix.value.getNormalMatrix(this.object.worldMatrix);
76 | super.draw(arg);
77 | }
78 | }
79 |
80 | const vertex = /* glsl */ `
81 | attribute vec3 position;
82 | attribute vec3 normal;
83 | attribute float size;
84 |
85 | uniform mat4 viewMatrix;
86 | uniform mat4 projectionMatrix;
87 | uniform mat4 objectWorldMatrix;
88 | uniform mat3 worldNormalMatrix;
89 |
90 | void main() {
91 | vec3 n = normalize(worldNormalMatrix * normal) * size;
92 | vec3 p = (objectWorldMatrix * vec4(position, 1.0)).xyz;
93 | gl_Position = projectionMatrix * viewMatrix * vec4(p + n, 1.0);
94 | }
95 | `;
96 |
97 | const fragment = /* glsl */ `
98 | precision highp float;
99 | uniform vec3 color;
100 |
101 | void main() {
102 | gl_FragColor = vec4(color, 1.0);
103 | }
104 | `;
105 |
--------------------------------------------------------------------------------
/src/extras/helpers/GridHelper.js:
--------------------------------------------------------------------------------
1 | import { Mesh } from '../../core/Mesh.js';
2 | import { Program } from '../../core/Program.js';
3 | import { Geometry } from '../../core/Geometry.js';
4 | import { Vec3 } from '../../math/Vec3.js';
5 |
6 | export class GridHelper extends Mesh {
7 | constructor(gl, { size = 10, divisions = 10, color = new Vec3(0.75, 0.75, 0.75), ...meshProps } = {}) {
8 | const numVertices = (size + 1) * 2 * 2;
9 | const vertices = new Float32Array(numVertices * 3);
10 |
11 | const hs = size / 2;
12 | for (let i = 0; i <= divisions; i++) {
13 | const t = i / divisions;
14 | const o = t * size - hs;
15 |
16 | vertices.set([o, 0, -hs, o, 0, hs], i * 12);
17 | vertices.set([-hs, 0, o, hs, 0, o], i * 12 + 6);
18 | }
19 |
20 | const geometry = new Geometry(gl, {
21 | position: { size: 3, data: vertices },
22 | });
23 |
24 | const program = new Program(gl, {
25 | vertex,
26 | fragment,
27 | uniforms: {
28 | color: { value: color },
29 | },
30 | });
31 | super(gl, { ...meshProps, mode: gl.LINES, geometry, program });
32 | }
33 | }
34 |
35 | const vertex = /* glsl */ `
36 | attribute vec3 position;
37 | uniform mat4 modelViewMatrix;
38 | uniform mat4 projectionMatrix;
39 |
40 | void main() {
41 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
42 | }
43 | `;
44 |
45 | const fragment = /* glsl */ `
46 | precision highp float;
47 | uniform vec3 color;
48 |
49 | void main() {
50 | gl_FragColor = vec4(color, 1.0);
51 | }
52 | `;
53 |
--------------------------------------------------------------------------------
/src/extras/helpers/VertexNormalsHelper.js:
--------------------------------------------------------------------------------
1 | import { Mesh } from '../../core/Mesh.js';
2 | import { Program } from '../../core/Program.js';
3 | import { Geometry } from '../../core/Geometry.js';
4 | import { Vec3 } from '../../math/Vec3.js';
5 | import { Mat3 } from '../../math/Mat3.js';
6 |
7 | export class VertexNormalsHelper extends Mesh {
8 | constructor(object, { size = 0.1, color = new Vec3(0.86, 0.16, 0.86), ...meshProps } = {}) {
9 | const gl = object.gl;
10 | const nNormals = object.geometry.attributes.normal.count;
11 | const positionsArray = new Float32Array(nNormals * 2 * 3);
12 | const normalsArray = new Float32Array(nNormals * 2 * 3);
13 | const sizeArray = new Float32Array(nNormals * 2);
14 |
15 | const normalData = object.geometry.attributes.normal.data;
16 | const positionData = object.geometry.attributes.position.data;
17 | const sizeData = new Float32Array([0, size]);
18 |
19 | for (let i = 0; i < nNormals; i++) {
20 | const i6 = i * 6;
21 | const i3 = i * 3;
22 |
23 | // duplicate position and normal for line start and end point
24 | const pSub = positionData.subarray(i3, i3 + 3);
25 | positionsArray.set(pSub, i6);
26 | positionsArray.set(pSub, i6 + 3);
27 |
28 | const nSub = normalData.subarray(i3, i3 + 3);
29 | normalsArray.set(nSub, i6);
30 | normalsArray.set(nSub, i6 + 3);
31 |
32 | sizeArray.set(sizeData, i * 2);
33 | }
34 |
35 | const geometry = new Geometry(gl, {
36 | position: { size: 3, data: positionsArray },
37 | normal: { size: 3, data: normalsArray },
38 | size: { size: 1, data: sizeArray },
39 | });
40 |
41 | const program = new Program(gl, {
42 | vertex,
43 | fragment,
44 | uniforms: {
45 | color: { value: color },
46 | worldNormalMatrix: { value: new Mat3() },
47 | objectWorldMatrix: { value: object.worldMatrix },
48 | },
49 | });
50 |
51 | super(gl, { ...meshProps, mode: gl.LINES, geometry, program });
52 |
53 | this.object = object;
54 | }
55 |
56 | draw(arg) {
57 | this.program.uniforms.worldNormalMatrix.value.getNormalMatrix(this.object.worldMatrix);
58 | super.draw(arg);
59 | }
60 | }
61 |
62 | const vertex = /* glsl */ `
63 | attribute vec3 position;
64 | attribute vec3 normal;
65 | attribute float size;
66 |
67 | uniform mat4 viewMatrix;
68 | uniform mat4 projectionMatrix;
69 | uniform mat4 objectWorldMatrix;
70 | uniform mat3 worldNormalMatrix;
71 |
72 | void main() {
73 | vec3 n = normalize(worldNormalMatrix * normal) * size;
74 | vec3 p = (objectWorldMatrix * vec4(position, 1.0)).xyz;
75 | gl_Position = projectionMatrix * viewMatrix * vec4(p + n, 1.0);
76 | }
77 | `;
78 |
79 | const fragment = /* glsl */ `
80 | precision highp float;
81 | uniform vec3 color;
82 |
83 | void main() {
84 | gl_FragColor = vec4(color, 1.0);
85 | }
86 | `;
87 |
--------------------------------------------------------------------------------
/src/extras/path/BaseSegment.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Abstract base class for path segments.
3 | * This class contains common methods for all segments types.
4 | */
5 | export default class BaseSegment {
6 | constructor() {
7 | this._len = -1;
8 | this.tiltStart = 0;
9 | this.tiltEnd = 0;
10 | }
11 |
12 | /**
13 | * Get segment length.
14 | * @returns {number} segment length
15 | */
16 | getLength() {
17 | if (this._len < 0) {
18 | this.updateLength();
19 | }
20 |
21 | return this._len;
22 | }
23 |
24 | /**
25 | * Get tilt angle at t
26 | * @param {number} t Distance at time t in range [0 .. 1]
27 | * @returns {number} Tilt angle at t
28 | */
29 | getTiltAt(t) {
30 | return this.tiltStart * (1 - t) * this.tiltEnd * t;
31 | }
32 |
33 | /**
34 | * Creates a clone of this instance
35 | * @returns {BaseSegment} cloned instance
36 | */
37 | clone() {
38 | return new this.constructor().copy(this);
39 | }
40 |
41 | /**
42 | * Copies another segment object to this instance.
43 | * @param {BaseSegment} source reference object
44 | * @returns {BaseSegment} copy of source object
45 | */
46 | copy(source) {
47 | this._len = source._len;
48 | this.tiltStart = source.tiltStart;
49 | this.tiltEnd = source.tiltEnd;
50 | return this;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/extras/path/CubicBezierSegment.js:
--------------------------------------------------------------------------------
1 | import BaseSegment from './BaseSegment.js';
2 | import { Vec3 } from '../../math/Vec3.js';
3 | import { T_VALUES, C_VALUES } from './utils.js';
4 |
5 | const tempVec3 = /* @__PURE__ */ new Vec3();
6 |
7 | function cubicBezier(t, p0, p1, p2, p3) {
8 | const k = 1 - t;
9 | // prettier-ignore
10 | return (
11 | (k * k * k * p0) +
12 | (3 * k * k * t * p1) +
13 | (3 * k * t * t * p2) +
14 | (t * t * t * p3)
15 | );
16 | }
17 |
18 | function cubicBezierDeriv(t, p0, p1, p2, p3) {
19 | const k = 1 - t;
20 | // prettier-ignore
21 | return (
22 | (3 * k * k * (p1 - p0)) +
23 | (6 * k * t * (p2 - p1)) +
24 | (3 * t * t * (p3 - p2))
25 | );
26 | }
27 |
28 | export default class CubicBezierSegment extends BaseSegment {
29 | constructor(p0, p1, p2, p3, tiltStart = 0, tiltEnd = 0) {
30 | super();
31 | this.p0 = p0;
32 | this.p1 = p1;
33 | this.p2 = p2;
34 | this.p3 = p3;
35 |
36 | this.tiltStart = tiltStart;
37 | this.tiltEnd = tiltEnd;
38 |
39 | this._len = -1;
40 | }
41 |
42 | /**
43 | * Updates the segment length. You must call this method every time you change the curve's control points.
44 | */
45 | updateLength() {
46 | // from https://github.com/Pomax/bezierjs/blob/d19695f3cc3ce383cf38ce4643f467deca7edb92/src/utils.js#L265
47 | const z = 0.5;
48 | const len = T_VALUES.length;
49 |
50 | let sum = 0;
51 | for (let i = 0, t; i < len; i++) {
52 | t = z * T_VALUES[i] + z;
53 | sum += C_VALUES[i] * this.getDerivativeAt(t, tempVec3).len();
54 | }
55 |
56 | this._len = z * sum;
57 | }
58 |
59 | /**
60 | * Get point at relative position in curve according to segment length.
61 | * @param {number} t Distance at time t in range [0 .. 1]
62 | * @param {Vec3} out Optional Vec3 to output
63 | * @returns {Vec3} Point at relative position
64 | */
65 | getPointAt(t, out = new Vec3()) {
66 | out.x = cubicBezier(t, this.p0.x, this.p1.x, this.p2.x, this.p3.x);
67 | out.y = cubicBezier(t, this.p0.y, this.p1.y, this.p2.y, this.p3.y);
68 | out.z = cubicBezier(t, this.p0.z, this.p1.z, this.p2.z, this.p3.z);
69 | return out;
70 | }
71 |
72 | getDerivativeAt(t, out = new Vec3()) {
73 | out.x = cubicBezierDeriv(t, this.p0.x, this.p1.x, this.p2.x, this.p3.x);
74 | out.y = cubicBezierDeriv(t, this.p0.y, this.p1.y, this.p2.y, this.p3.y);
75 | out.z = cubicBezierDeriv(t, this.p0.z, this.p1.z, this.p2.z, this.p3.z);
76 | return out;
77 | }
78 |
79 | /**
80 | * Returns a unit vector tangent at t
81 | * @param {number} t Distance at time t in range [0 .. 1]
82 | * @param {Vec3} out Optional Vec3 to output
83 | * @returns {Vec3} A unit vector
84 | */
85 | getTangentAt(t, out = new Vec3()) {
86 | return this.getDerivativeAt(t, out).normalize();
87 | }
88 |
89 | lastPoint() {
90 | return this.p3;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/extras/path/LineSegment.js:
--------------------------------------------------------------------------------
1 | import BaseSegment from './BaseSegment.js';
2 | import { Vec3 } from '../../math/Vec3.js';
3 | import { lerp as lerp3 } from '../../math/functions/Vec3Func.js';
4 |
5 | const tempVec3 = /* @__PURE__ */ new Vec3();
6 |
7 | export default class LineSegment extends BaseSegment {
8 | constructor(p0, p1, tiltStart = 0, tiltEnd = 0) {
9 | super();
10 | this.p0 = p0;
11 | this.p1 = p1;
12 |
13 | this.tiltStart = tiltStart;
14 | this.tiltEnd = tiltEnd;
15 |
16 | this._len = -1;
17 | }
18 |
19 | /**
20 | * Updates the segment length. You must call this method every time you change the curve's control points.
21 | */
22 | updateLength() {
23 | this._len = tempVec3.sub(this.p1, this.p0).len();
24 | }
25 |
26 | /**
27 | * Get point at relative position in curve according to segment length.
28 | * @param {number} t Distance at time t in range [0 .. 1]
29 | * @param {Vec3} out Optional Vec3 to output
30 | * @returns {Vec3} Point at relative position
31 | */
32 | getPointAt(t, out = new Vec3()) {
33 | lerp3(out, this.p0, this.p1, t);
34 | return out;
35 | }
36 |
37 | /**
38 | * Returns a unit vector tangent at t
39 | * @param {number} t Distance at time t in range [0 .. 1]
40 | * @param {Vec3} out Optional Vec3 to output
41 | * @returns {Vec3} A unit vector
42 | */
43 | getTangentAt(t, out = new Vec3()) {
44 | return out.sub(this.p1, this.p0).normalize();
45 | }
46 |
47 | lastPoint() {
48 | return this.p1;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/extras/path/QuadraticBezierSegment.js:
--------------------------------------------------------------------------------
1 | import BaseSegment from './BaseSegment.js';
2 | import { Vec3 } from '../../math/Vec3.js';
3 | import { T_VALUES, C_VALUES } from './utils.js';
4 |
5 | const tempVec3 = /* @__PURE__ */ new Vec3();
6 |
7 | function quadraticBezier(t, p0, p1, p2) {
8 | const k = 1 - t;
9 | return k * k * p0 + 2 * k * t * p1 + t * t * p2;
10 | }
11 |
12 | function quadraticBezierDeriv(t, p0, p1, p2) {
13 | const k = 1 - t;
14 | return 2 * k * (p1 - p0) + 2 * t * (p2 - p1);
15 | }
16 |
17 | export default class QuadraticBezierSegment extends BaseSegment {
18 | constructor(p0, p1, p2, tiltStart = 0, tiltEnd = 0) {
19 | super();
20 | this.p0 = p0;
21 | this.p1 = p1;
22 | this.p2 = p2;
23 |
24 | this.tiltStart = tiltStart;
25 | this.tiltEnd = tiltEnd;
26 |
27 | this._len = -1;
28 | }
29 |
30 | /**
31 | * Updates the segment length. You must call this method every time you change the curve's control points.
32 | */
33 | updateLength() {
34 | // from https://github.com/Pomax/bezierjs/blob/d19695f3cc3ce383cf38ce4643f467deca7edb92/src/utils.js#L265
35 | const z = 0.5;
36 | const len = T_VALUES.length;
37 |
38 | let sum = 0;
39 | for (let i = 0, t; i < len; i++) {
40 | t = z * T_VALUES[i] + z;
41 | sum += C_VALUES[i] * this.getDerivativeAt(t, tempVec3).len();
42 | }
43 |
44 | this._len = z * sum;
45 | }
46 |
47 | /**
48 | * Get point at relative position in curve according to segment length.
49 | * @param {number} t Distance at time t in range [0 .. 1]
50 | * @param {Vec3} out Optional Vec3 to output
51 | * @returns {Vec3} Point at relative position
52 | */
53 | getPointAt(t, out = new Vec3()) {
54 | out.x = quadraticBezier(t, this.p0.x, this.p1.x, this.p2.x);
55 | out.y = quadraticBezier(t, this.p0.y, this.p1.y, this.p2.y);
56 | out.z = quadraticBezier(t, this.p0.z, this.p1.z, this.p2.z);
57 | return out;
58 | }
59 |
60 | getDerivativeAt(t, out = new Vec3()) {
61 | out.x = quadraticBezierDeriv(t, this.p0.x, this.p1.x, this.p2.x);
62 | out.y = quadraticBezierDeriv(t, this.p0.y, this.p1.y, this.p2.y);
63 | out.z = quadraticBezierDeriv(t, this.p0.z, this.p1.z, this.p2.z);
64 | return out;
65 | }
66 |
67 | /**
68 | * Returns a unit vector tangent at t
69 | * @param {number} t Distance at time t in range [0 .. 1]
70 | * @param {Vec3} out Optional Vec3 to output
71 | * @returns {Vec3} A unit vector
72 | */
73 | getTangentAt(t, out = new Vec3()) {
74 | return this.getDerivativeAt(t, out).normalize();
75 | }
76 |
77 | lastPoint() {
78 | return this.p2;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | // Core
2 | export { Geometry } from './core/Geometry.js';
3 | export { Program } from './core/Program.js';
4 | export { Renderer } from './core/Renderer.js';
5 | export { Camera } from './core/Camera.js';
6 | export { Transform } from './core/Transform.js';
7 | export { Mesh } from './core/Mesh.js';
8 | export { Texture } from './core/Texture.js';
9 | export { RenderTarget } from './core/RenderTarget.js';
10 |
11 | // Maths
12 | export { Color } from './math/Color.js';
13 | export { Euler } from './math/Euler.js';
14 | export { Mat3 } from './math/Mat3.js';
15 | export { Mat4 } from './math/Mat4.js';
16 | export { Quat } from './math/Quat.js';
17 | export { Vec2 } from './math/Vec2.js';
18 | export { Vec3 } from './math/Vec3.js';
19 | export { Vec4 } from './math/Vec4.js';
20 |
21 | // Extras
22 | export { Plane } from './extras/Plane.js';
23 | export { Box } from './extras/Box.js';
24 | export { Sphere } from './extras/Sphere.js';
25 | export { Cylinder } from './extras/Cylinder.js';
26 | export { Triangle } from './extras/Triangle.js';
27 | export { Torus } from './extras/Torus.js';
28 | export { Orbit } from './extras/Orbit.js';
29 | export { Raycast } from './extras/Raycast.js';
30 | export { Curve } from './extras/Curve.js';
31 | export { Path } from './extras/path/Path.js';
32 | export { Tube } from './extras/Tube.js';
33 | export { Post } from './extras/Post.js';
34 | export { Skin } from './extras/Skin.js';
35 | export { Animation } from './extras/Animation.js';
36 | export { Text } from './extras/Text.js';
37 | export { NormalProgram } from './extras/NormalProgram.js';
38 | export { Flowmap } from './extras/Flowmap.js';
39 | export { GPGPU } from './extras/GPGPU.js';
40 | export { Polyline } from './extras/Polyline.js';
41 | export { Shadow } from './extras/Shadow.js';
42 | export { KTXTexture } from './extras/KTXTexture.js';
43 | export { TextureLoader } from './extras/TextureLoader.js';
44 | export { GLTFLoader } from './extras/GLTFLoader.js';
45 | export { GLTFSkin } from './extras/GLTFSkin.js';
46 | export { GLTFAnimation } from './extras/GLTFAnimation.js';
47 | export { DracoManager } from './extras/DracoManager.js';
48 | export { BasisManager } from './extras/BasisManager.js';
49 | export { WireMesh } from './extras/WireMesh.js';
50 | export { AxesHelper } from './extras/helpers/AxesHelper.js';
51 | export { GridHelper } from './extras/helpers/GridHelper.js';
52 | export { VertexNormalsHelper } from './extras/helpers/VertexNormalsHelper.js';
53 | export { FaceNormalsHelper } from './extras/helpers/FaceNormalsHelper.js';
54 | export { InstancedMesh } from './extras/InstancedMesh.js';
55 | export { Texture3D } from './extras/Texture3D.js';
56 |
--------------------------------------------------------------------------------
/src/math/Color.js:
--------------------------------------------------------------------------------
1 | import * as ColorFunc from './functions/ColorFunc.js';
2 |
3 | // Color stored as an array of RGB decimal values (between 0 > 1)
4 | // Constructor and set method accept following formats:
5 | // new Color() - Empty (defaults to black)
6 | // new Color([0.2, 0.4, 1.0]) - Decimal Array (or another Color instance)
7 | // new Color(0.7, 0.0, 0.1) - Decimal RGB values
8 | // new Color('#ff0000') - Hex string
9 | // new Color('#ccc') - Short-hand Hex string
10 | // new Color(0x4f27e8) - Number
11 | // new Color('red') - Color name string (short list in ColorFunc.js)
12 |
13 | export class Color extends Array {
14 | constructor(color) {
15 | if (Array.isArray(color)) return super(...color);
16 | return super(...ColorFunc.parseColor(...arguments));
17 | }
18 |
19 | get r() {
20 | return this[0];
21 | }
22 |
23 | get g() {
24 | return this[1];
25 | }
26 |
27 | get b() {
28 | return this[2];
29 | }
30 |
31 | set r(v) {
32 | this[0] = v;
33 | }
34 |
35 | set g(v) {
36 | this[1] = v;
37 | }
38 |
39 | set b(v) {
40 | this[2] = v;
41 | }
42 |
43 | set(color) {
44 | if (Array.isArray(color)) return this.copy(color);
45 | return this.copy(ColorFunc.parseColor(...arguments));
46 | }
47 |
48 | copy(v) {
49 | this[0] = v[0];
50 | this[1] = v[1];
51 | this[2] = v[2];
52 | return this;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/math/Euler.js:
--------------------------------------------------------------------------------
1 | import * as EulerFunc from './functions/EulerFunc.js';
2 | import { Mat4 } from './Mat4.js';
3 |
4 | const tmpMat4 = /* @__PURE__ */ new Mat4();
5 |
6 | export class Euler extends Array {
7 | constructor(x = 0, y = x, z = x, order = 'YXZ') {
8 | super(x, y, z);
9 | this.order = order;
10 | this.onChange = () => {};
11 |
12 | // Keep reference to proxy target to avoid triggering onChange internally
13 | this._target = this;
14 |
15 | // Return a proxy to trigger onChange when array elements are edited directly
16 | const triggerProps = ['0', '1', '2'];
17 | return new Proxy(this, {
18 | set(target, property) {
19 | const success = Reflect.set(...arguments);
20 | if (success && triggerProps.includes(property)) target.onChange();
21 | return success;
22 | },
23 | });
24 | }
25 |
26 | get x() {
27 | return this[0];
28 | }
29 |
30 | get y() {
31 | return this[1];
32 | }
33 |
34 | get z() {
35 | return this[2];
36 | }
37 |
38 | set x(v) {
39 | this._target[0] = v;
40 | this.onChange();
41 | }
42 |
43 | set y(v) {
44 | this._target[1] = v;
45 | this.onChange();
46 | }
47 |
48 | set z(v) {
49 | this._target[2] = v;
50 | this.onChange();
51 | }
52 |
53 | set(x, y = x, z = x) {
54 | if (x.length) return this.copy(x);
55 | this._target[0] = x;
56 | this._target[1] = y;
57 | this._target[2] = z;
58 | this.onChange();
59 | return this;
60 | }
61 |
62 | copy(v) {
63 | this._target[0] = v[0];
64 | this._target[1] = v[1];
65 | this._target[2] = v[2];
66 | this.onChange();
67 | return this;
68 | }
69 |
70 | reorder(order) {
71 | this._target.order = order;
72 | this.onChange();
73 | return this;
74 | }
75 |
76 | fromRotationMatrix(m, order = this.order) {
77 | EulerFunc.fromRotationMatrix(this._target, m, order);
78 | this.onChange();
79 | return this;
80 | }
81 |
82 | fromQuaternion(q, order = this.order, isInternal) {
83 | tmpMat4.fromQuaternion(q);
84 | this._target.fromRotationMatrix(tmpMat4, order);
85 | // Avoid infinite recursion
86 | if (!isInternal) this.onChange();
87 | return this;
88 | }
89 |
90 | fromArray(a, o = 0) {
91 | this._target[0] = a[o];
92 | this._target[1] = a[o + 1];
93 | this._target[2] = a[o + 2];
94 | return this;
95 | }
96 |
97 | toArray(a = [], o = 0) {
98 | a[o] = this[0];
99 | a[o + 1] = this[1];
100 | a[o + 2] = this[2];
101 | return a;
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/math/Mat3.js:
--------------------------------------------------------------------------------
1 | import * as Mat3Func from './functions/Mat3Func.js';
2 |
3 | export class Mat3 extends Array {
4 | constructor(m00 = 1, m01 = 0, m02 = 0, m10 = 0, m11 = 1, m12 = 0, m20 = 0, m21 = 0, m22 = 1) {
5 | super(m00, m01, m02, m10, m11, m12, m20, m21, m22);
6 | return this;
7 | }
8 |
9 | set(m00, m01, m02, m10, m11, m12, m20, m21, m22) {
10 | if (m00.length) return this.copy(m00);
11 | Mat3Func.set(this, m00, m01, m02, m10, m11, m12, m20, m21, m22);
12 | return this;
13 | }
14 |
15 | translate(v, m = this) {
16 | Mat3Func.translate(this, m, v);
17 | return this;
18 | }
19 |
20 | rotate(v, m = this) {
21 | Mat3Func.rotate(this, m, v);
22 | return this;
23 | }
24 |
25 | scale(v, m = this) {
26 | Mat3Func.scale(this, m, v);
27 | return this;
28 | }
29 |
30 | multiply(ma, mb) {
31 | if (mb) {
32 | Mat3Func.multiply(this, ma, mb);
33 | } else {
34 | Mat3Func.multiply(this, this, ma);
35 | }
36 | return this;
37 | }
38 |
39 | identity() {
40 | Mat3Func.identity(this);
41 | return this;
42 | }
43 |
44 | copy(m) {
45 | Mat3Func.copy(this, m);
46 | return this;
47 | }
48 |
49 | fromMatrix4(m) {
50 | Mat3Func.fromMat4(this, m);
51 | return this;
52 | }
53 |
54 | fromQuaternion(q) {
55 | Mat3Func.fromQuat(this, q);
56 | return this;
57 | }
58 |
59 | fromBasis(vec3a, vec3b, vec3c) {
60 | this.set(vec3a[0], vec3a[1], vec3a[2], vec3b[0], vec3b[1], vec3b[2], vec3c[0], vec3c[1], vec3c[2]);
61 | return this;
62 | }
63 |
64 | inverse(m = this) {
65 | Mat3Func.invert(this, m);
66 | return this;
67 | }
68 |
69 | getNormalMatrix(m) {
70 | Mat3Func.normalFromMat4(this, m);
71 | return this;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/math/Quat.js:
--------------------------------------------------------------------------------
1 | import * as QuatFunc from './functions/QuatFunc.js';
2 |
3 | export class Quat extends Array {
4 | constructor(x = 0, y = 0, z = 0, w = 1) {
5 | super(x, y, z, w);
6 | this.onChange = () => {};
7 |
8 | // Keep reference to proxy target to avoid triggering onChange internally
9 | this._target = this;
10 |
11 | // Return a proxy to trigger onChange when array elements are edited directly
12 | const triggerProps = ['0', '1', '2', '3'];
13 | return new Proxy(this, {
14 | set(target, property) {
15 | const success = Reflect.set(...arguments);
16 | if (success && triggerProps.includes(property)) target.onChange();
17 | return success;
18 | },
19 | });
20 | }
21 |
22 | get x() {
23 | return this[0];
24 | }
25 |
26 | get y() {
27 | return this[1];
28 | }
29 |
30 | get z() {
31 | return this[2];
32 | }
33 |
34 | get w() {
35 | return this[3];
36 | }
37 |
38 | set x(v) {
39 | this._target[0] = v;
40 | this.onChange();
41 | }
42 |
43 | set y(v) {
44 | this._target[1] = v;
45 | this.onChange();
46 | }
47 |
48 | set z(v) {
49 | this._target[2] = v;
50 | this.onChange();
51 | }
52 |
53 | set w(v) {
54 | this._target[3] = v;
55 | this.onChange();
56 | }
57 |
58 | identity() {
59 | QuatFunc.identity(this._target);
60 | this.onChange();
61 | return this;
62 | }
63 |
64 | set(x, y, z, w) {
65 | if (x.length) return this.copy(x);
66 | QuatFunc.set(this._target, x, y, z, w);
67 | this.onChange();
68 | return this;
69 | }
70 |
71 | rotateX(a) {
72 | QuatFunc.rotateX(this._target, this._target, a);
73 | this.onChange();
74 | return this;
75 | }
76 |
77 | rotateY(a) {
78 | QuatFunc.rotateY(this._target, this._target, a);
79 | this.onChange();
80 | return this;
81 | }
82 |
83 | rotateZ(a) {
84 | QuatFunc.rotateZ(this._target, this._target, a);
85 | this.onChange();
86 | return this;
87 | }
88 |
89 | inverse(q = this._target) {
90 | QuatFunc.invert(this._target, q);
91 | this.onChange();
92 | return this;
93 | }
94 |
95 | conjugate(q = this._target) {
96 | QuatFunc.conjugate(this._target, q);
97 | this.onChange();
98 | return this;
99 | }
100 |
101 | copy(q) {
102 | QuatFunc.copy(this._target, q);
103 | this.onChange();
104 | return this;
105 | }
106 |
107 | normalize(q = this._target) {
108 | QuatFunc.normalize(this._target, q);
109 | this.onChange();
110 | return this;
111 | }
112 |
113 | multiply(qA, qB) {
114 | if (qB) {
115 | QuatFunc.multiply(this._target, qA, qB);
116 | } else {
117 | QuatFunc.multiply(this._target, this._target, qA);
118 | }
119 | this.onChange();
120 | return this;
121 | }
122 |
123 | dot(v) {
124 | return QuatFunc.dot(this._target, v);
125 | }
126 |
127 | fromMatrix3(matrix3) {
128 | QuatFunc.fromMat3(this._target, matrix3);
129 | this.onChange();
130 | return this;
131 | }
132 |
133 | fromEuler(euler, isInternal) {
134 | QuatFunc.fromEuler(this._target, euler, euler.order);
135 | // Avoid infinite recursion
136 | if (!isInternal) this.onChange();
137 | return this;
138 | }
139 |
140 | fromAxisAngle(axis, a) {
141 | QuatFunc.setAxisAngle(this._target, axis, a);
142 | this.onChange();
143 | return this;
144 | }
145 |
146 | slerp(q, t) {
147 | QuatFunc.slerp(this._target, this._target, q, t);
148 | this.onChange();
149 | return this;
150 | }
151 |
152 | fromArray(a, o = 0) {
153 | this._target[0] = a[o];
154 | this._target[1] = a[o + 1];
155 | this._target[2] = a[o + 2];
156 | this._target[3] = a[o + 3];
157 | this.onChange();
158 | return this;
159 | }
160 |
161 | toArray(a = [], o = 0) {
162 | a[o] = this[0];
163 | a[o + 1] = this[1];
164 | a[o + 2] = this[2];
165 | a[o + 3] = this[3];
166 | return a;
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/src/math/Vec2.js:
--------------------------------------------------------------------------------
1 | import * as Vec2Func from './functions/Vec2Func.js';
2 |
3 | export class Vec2 extends Array {
4 | constructor(x = 0, y = x) {
5 | super(x, y);
6 | return this;
7 | }
8 |
9 | get x() {
10 | return this[0];
11 | }
12 |
13 | get y() {
14 | return this[1];
15 | }
16 |
17 | set x(v) {
18 | this[0] = v;
19 | }
20 |
21 | set y(v) {
22 | this[1] = v;
23 | }
24 |
25 | set(x, y = x) {
26 | if (x.length) return this.copy(x);
27 | Vec2Func.set(this, x, y);
28 | return this;
29 | }
30 |
31 | copy(v) {
32 | Vec2Func.copy(this, v);
33 | return this;
34 | }
35 |
36 | add(va, vb) {
37 | if (vb) Vec2Func.add(this, va, vb);
38 | else Vec2Func.add(this, this, va);
39 | return this;
40 | }
41 |
42 | sub(va, vb) {
43 | if (vb) Vec2Func.subtract(this, va, vb);
44 | else Vec2Func.subtract(this, this, va);
45 | return this;
46 | }
47 |
48 | multiply(v) {
49 | if (v.length) Vec2Func.multiply(this, this, v);
50 | else Vec2Func.scale(this, this, v);
51 | return this;
52 | }
53 |
54 | divide(v) {
55 | if (v.length) Vec2Func.divide(this, this, v);
56 | else Vec2Func.scale(this, this, 1 / v);
57 | return this;
58 | }
59 |
60 | inverse(v = this) {
61 | Vec2Func.inverse(this, v);
62 | return this;
63 | }
64 |
65 | // Can't use 'length' as Array.prototype uses it
66 | len() {
67 | return Vec2Func.length(this);
68 | }
69 |
70 | distance(v) {
71 | if (v) return Vec2Func.distance(this, v);
72 | else return Vec2Func.length(this);
73 | }
74 |
75 | squaredLen() {
76 | return this.squaredDistance();
77 | }
78 |
79 | squaredDistance(v) {
80 | if (v) return Vec2Func.squaredDistance(this, v);
81 | else return Vec2Func.squaredLength(this);
82 | }
83 |
84 | negate(v = this) {
85 | Vec2Func.negate(this, v);
86 | return this;
87 | }
88 |
89 | cross(va, vb) {
90 | if (vb) return Vec2Func.cross(va, vb);
91 | return Vec2Func.cross(this, va);
92 | }
93 |
94 | scale(v) {
95 | Vec2Func.scale(this, this, v);
96 | return this;
97 | }
98 |
99 | normalize() {
100 | Vec2Func.normalize(this, this);
101 | return this;
102 | }
103 |
104 | dot(v) {
105 | return Vec2Func.dot(this, v);
106 | }
107 |
108 | equals(v) {
109 | return Vec2Func.exactEquals(this, v);
110 | }
111 |
112 | applyMatrix3(mat3) {
113 | Vec2Func.transformMat3(this, this, mat3);
114 | return this;
115 | }
116 |
117 | applyMatrix4(mat4) {
118 | Vec2Func.transformMat4(this, this, mat4);
119 | return this;
120 | }
121 |
122 | lerp(v, a) {
123 | Vec2Func.lerp(this, this, v, a);
124 | return this;
125 | }
126 |
127 | smoothLerp(v, decay, dt) {
128 | Vec2Func.smoothLerp(this, this, v, decay, dt);
129 | return this;
130 | }
131 |
132 | clone() {
133 | return new Vec2(this[0], this[1]);
134 | }
135 |
136 | fromArray(a, o = 0) {
137 | this[0] = a[o];
138 | this[1] = a[o + 1];
139 | return this;
140 | }
141 |
142 | toArray(a = [], o = 0) {
143 | a[o] = this[0];
144 | a[o + 1] = this[1];
145 | return a;
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/src/math/Vec3.js:
--------------------------------------------------------------------------------
1 | import * as Vec3Func from './functions/Vec3Func.js';
2 |
3 | export class Vec3 extends Array {
4 | constructor(x = 0, y = x, z = x) {
5 | super(x, y, z);
6 | return this;
7 | }
8 |
9 | get x() {
10 | return this[0];
11 | }
12 |
13 | get y() {
14 | return this[1];
15 | }
16 |
17 | get z() {
18 | return this[2];
19 | }
20 |
21 | set x(v) {
22 | this[0] = v;
23 | }
24 |
25 | set y(v) {
26 | this[1] = v;
27 | }
28 |
29 | set z(v) {
30 | this[2] = v;
31 | }
32 |
33 | set(x, y = x, z = x) {
34 | if (x.length) return this.copy(x);
35 | Vec3Func.set(this, x, y, z);
36 | return this;
37 | }
38 |
39 | copy(v) {
40 | Vec3Func.copy(this, v);
41 | return this;
42 | }
43 |
44 | add(va, vb) {
45 | if (vb) Vec3Func.add(this, va, vb);
46 | else Vec3Func.add(this, this, va);
47 | return this;
48 | }
49 |
50 | sub(va, vb) {
51 | if (vb) Vec3Func.subtract(this, va, vb);
52 | else Vec3Func.subtract(this, this, va);
53 | return this;
54 | }
55 |
56 | multiply(v) {
57 | if (v.length) Vec3Func.multiply(this, this, v);
58 | else Vec3Func.scale(this, this, v);
59 | return this;
60 | }
61 |
62 | divide(v) {
63 | if (v.length) Vec3Func.divide(this, this, v);
64 | else Vec3Func.scale(this, this, 1 / v);
65 | return this;
66 | }
67 |
68 | inverse(v = this) {
69 | Vec3Func.inverse(this, v);
70 | return this;
71 | }
72 |
73 | // Can't use 'length' as Array.prototype uses it
74 | len() {
75 | return Vec3Func.length(this);
76 | }
77 |
78 | distance(v) {
79 | if (v) return Vec3Func.distance(this, v);
80 | else return Vec3Func.length(this);
81 | }
82 |
83 | squaredLen() {
84 | return Vec3Func.squaredLength(this);
85 | }
86 |
87 | squaredDistance(v) {
88 | if (v) return Vec3Func.squaredDistance(this, v);
89 | else return Vec3Func.squaredLength(this);
90 | }
91 |
92 | negate(v = this) {
93 | Vec3Func.negate(this, v);
94 | return this;
95 | }
96 |
97 | cross(va, vb) {
98 | if (vb) Vec3Func.cross(this, va, vb);
99 | else Vec3Func.cross(this, this, va);
100 | return this;
101 | }
102 |
103 | scale(v) {
104 | Vec3Func.scale(this, this, v);
105 | return this;
106 | }
107 |
108 | normalize() {
109 | Vec3Func.normalize(this, this);
110 | return this;
111 | }
112 |
113 | dot(v) {
114 | return Vec3Func.dot(this, v);
115 | }
116 |
117 | equals(v) {
118 | return Vec3Func.exactEquals(this, v);
119 | }
120 |
121 | applyMatrix3(mat3) {
122 | Vec3Func.transformMat3(this, this, mat3);
123 | return this;
124 | }
125 |
126 | applyMatrix4(mat4) {
127 | Vec3Func.transformMat4(this, this, mat4);
128 | return this;
129 | }
130 |
131 | scaleRotateMatrix4(mat4) {
132 | Vec3Func.scaleRotateMat4(this, this, mat4);
133 | return this;
134 | }
135 |
136 | applyQuaternion(q) {
137 | Vec3Func.transformQuat(this, this, q);
138 | return this;
139 | }
140 |
141 | angle(v) {
142 | return Vec3Func.angle(this, v);
143 | }
144 |
145 | lerp(v, t) {
146 | Vec3Func.lerp(this, this, v, t);
147 | return this;
148 | }
149 |
150 | smoothLerp(v, decay, dt) {
151 | Vec3Func.smoothLerp(this, this, v, decay, dt);
152 | return this;
153 | }
154 |
155 | clone() {
156 | return new Vec3(this[0], this[1], this[2]);
157 | }
158 |
159 | fromArray(a, o = 0) {
160 | this[0] = a[o];
161 | this[1] = a[o + 1];
162 | this[2] = a[o + 2];
163 | return this;
164 | }
165 |
166 | toArray(a = [], o = 0) {
167 | a[o] = this[0];
168 | a[o + 1] = this[1];
169 | a[o + 2] = this[2];
170 | return a;
171 | }
172 |
173 | transformDirection(mat4) {
174 | const x = this[0];
175 | const y = this[1];
176 | const z = this[2];
177 |
178 | this[0] = mat4[0] * x + mat4[4] * y + mat4[8] * z;
179 | this[1] = mat4[1] * x + mat4[5] * y + mat4[9] * z;
180 | this[2] = mat4[2] * x + mat4[6] * y + mat4[10] * z;
181 |
182 | return this.normalize();
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/src/math/Vec4.js:
--------------------------------------------------------------------------------
1 | import * as Vec4Func from './functions/Vec4Func.js';
2 |
3 | export class Vec4 extends Array {
4 | constructor(x = 0, y = x, z = x, w = x) {
5 | super(x, y, z, w);
6 | return this;
7 | }
8 |
9 | get x() {
10 | return this[0];
11 | }
12 |
13 | get y() {
14 | return this[1];
15 | }
16 |
17 | get z() {
18 | return this[2];
19 | }
20 |
21 | get w() {
22 | return this[3];
23 | }
24 |
25 | set x(v) {
26 | this[0] = v;
27 | }
28 |
29 | set y(v) {
30 | this[1] = v;
31 | }
32 |
33 | set z(v) {
34 | this[2] = v;
35 | }
36 |
37 | set w(v) {
38 | this[3] = v;
39 | }
40 |
41 | set(x, y = x, z = x, w = x) {
42 | if (x.length) return this.copy(x);
43 | Vec4Func.set(this, x, y, z, w);
44 | return this;
45 | }
46 |
47 | copy(v) {
48 | Vec4Func.copy(this, v);
49 | return this;
50 | }
51 |
52 | normalize() {
53 | Vec4Func.normalize(this, this);
54 | return this;
55 | }
56 |
57 | multiply(v) {
58 | Vec4Func.scale(this, this, v);
59 | return this;
60 | }
61 |
62 | dot(v) {
63 | return Vec4Func.dot(this, v);
64 | }
65 |
66 | fromArray(a, o = 0) {
67 | this[0] = a[o];
68 | this[1] = a[o + 1];
69 | this[2] = a[o + 2];
70 | this[3] = a[o + 3];
71 | return this;
72 | }
73 |
74 | toArray(a = [], o = 0) {
75 | a[o] = this[0];
76 | a[o + 1] = this[1];
77 | a[o + 2] = this[2];
78 | a[o + 3] = this[3];
79 | return a;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/math/functions/ColorFunc.js:
--------------------------------------------------------------------------------
1 | const NAMES = {
2 | black: '#000000',
3 | white: '#ffffff',
4 | red: '#ff0000',
5 | green: '#00ff00',
6 | blue: '#0000ff',
7 | fuchsia: '#ff00ff',
8 | cyan: '#00ffff',
9 | yellow: '#ffff00',
10 | orange: '#ff8000',
11 | };
12 |
13 | export function hexToRGB(hex) {
14 | if (hex.length === 4) hex = hex[0] + hex[1] + hex[1] + hex[2] + hex[2] + hex[3] + hex[3];
15 | const rgb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
16 | if (!rgb) console.warn(`Unable to convert hex string ${hex} to rgb values`);
17 | return [parseInt(rgb[1], 16) / 255, parseInt(rgb[2], 16) / 255, parseInt(rgb[3], 16) / 255];
18 | }
19 |
20 | export function numberToRGB(num) {
21 | num = parseInt(num);
22 | return [((num >> 16) & 255) / 255, ((num >> 8) & 255) / 255, (num & 255) / 255];
23 | }
24 |
25 | export function parseColor(color) {
26 | // Empty
27 | if (color === undefined) return [0, 0, 0];
28 |
29 | // Decimal
30 | if (arguments.length === 3) return arguments;
31 |
32 | // Number
33 | if (!isNaN(color)) return numberToRGB(color);
34 |
35 | // Hex
36 | if (color[0] === '#') return hexToRGB(color);
37 |
38 | // Names
39 | if (NAMES[color.toLowerCase()]) return hexToRGB(NAMES[color.toLowerCase()]);
40 |
41 | console.warn('Color format not recognised');
42 | return [0, 0, 0];
43 | }
44 |
--------------------------------------------------------------------------------
/src/math/functions/EulerFunc.js:
--------------------------------------------------------------------------------
1 | // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
2 | export function fromRotationMatrix(out, m, order = 'YXZ') {
3 | if (order === 'XYZ') {
4 | out[1] = Math.asin(Math.min(Math.max(m[8], -1), 1));
5 | if (Math.abs(m[8]) < 0.99999) {
6 | out[0] = Math.atan2(-m[9], m[10]);
7 | out[2] = Math.atan2(-m[4], m[0]);
8 | } else {
9 | out[0] = Math.atan2(m[6], m[5]);
10 | out[2] = 0;
11 | }
12 | } else if (order === 'YXZ') {
13 | out[0] = Math.asin(-Math.min(Math.max(m[9], -1), 1));
14 | if (Math.abs(m[9]) < 0.99999) {
15 | out[1] = Math.atan2(m[8], m[10]);
16 | out[2] = Math.atan2(m[1], m[5]);
17 | } else {
18 | out[1] = Math.atan2(-m[2], m[0]);
19 | out[2] = 0;
20 | }
21 | } else if (order === 'ZXY') {
22 | out[0] = Math.asin(Math.min(Math.max(m[6], -1), 1));
23 | if (Math.abs(m[6]) < 0.99999) {
24 | out[1] = Math.atan2(-m[2], m[10]);
25 | out[2] = Math.atan2(-m[4], m[5]);
26 | } else {
27 | out[1] = 0;
28 | out[2] = Math.atan2(m[1], m[0]);
29 | }
30 | } else if (order === 'ZYX') {
31 | out[1] = Math.asin(-Math.min(Math.max(m[2], -1), 1));
32 | if (Math.abs(m[2]) < 0.99999) {
33 | out[0] = Math.atan2(m[6], m[10]);
34 | out[2] = Math.atan2(m[1], m[0]);
35 | } else {
36 | out[0] = 0;
37 | out[2] = Math.atan2(-m[4], m[5]);
38 | }
39 | } else if (order === 'YZX') {
40 | out[2] = Math.asin(Math.min(Math.max(m[1], -1), 1));
41 | if (Math.abs(m[1]) < 0.99999) {
42 | out[0] = Math.atan2(-m[9], m[5]);
43 | out[1] = Math.atan2(-m[2], m[0]);
44 | } else {
45 | out[0] = 0;
46 | out[1] = Math.atan2(m[8], m[10]);
47 | }
48 | } else if (order === 'XZY') {
49 | out[2] = Math.asin(-Math.min(Math.max(m[4], -1), 1));
50 | if (Math.abs(m[4]) < 0.99999) {
51 | out[0] = Math.atan2(m[6], m[5]);
52 | out[1] = Math.atan2(m[8], m[0]);
53 | } else {
54 | out[0] = Math.atan2(-m[9], m[10]);
55 | out[1] = 0;
56 | }
57 | }
58 |
59 | return out;
60 | }
61 |
--------------------------------------------------------------------------------
/src/math/functions/Vec4Func.js:
--------------------------------------------------------------------------------
1 | const EPSILON = 0.000001;
2 |
3 | /**
4 | * Copy the values from one vec4 to another
5 | *
6 | * @param {vec4} out the receiving vector
7 | * @param {vec4} a the source vector
8 | * @returns {vec4} out
9 | */
10 | export function copy(out, a) {
11 | out[0] = a[0];
12 | out[1] = a[1];
13 | out[2] = a[2];
14 | out[3] = a[3];
15 | return out;
16 | }
17 |
18 | /**
19 | * Set the components of a vec4 to the given values
20 | *
21 | * @param {vec4} out the receiving vector
22 | * @param {Number} x X component
23 | * @param {Number} y Y component
24 | * @param {Number} z Z component
25 | * @param {Number} w W component
26 | * @returns {vec4} out
27 | */
28 | export function set(out, x, y, z, w) {
29 | out[0] = x;
30 | out[1] = y;
31 | out[2] = z;
32 | out[3] = w;
33 | return out;
34 | }
35 |
36 | /**
37 | * Adds two vec4's
38 | *
39 | * @param {vec4} out the receiving vector
40 | * @param {vec4} a the first operand
41 | * @param {vec4} b the second operand
42 | * @returns {vec4} out
43 | */
44 | export function add(out, a, b) {
45 | out[0] = a[0] + b[0];
46 | out[1] = a[1] + b[1];
47 | out[2] = a[2] + b[2];
48 | out[3] = a[3] + b[3];
49 | return out;
50 | }
51 |
52 | /**
53 | * Scales a vec4 by a scalar number
54 | *
55 | * @param {vec4} out the receiving vector
56 | * @param {vec4} a the vector to scale
57 | * @param {Number} b amount to scale the vector by
58 | * @returns {vec4} out
59 | */
60 | export function scale(out, a, b) {
61 | out[0] = a[0] * b;
62 | out[1] = a[1] * b;
63 | out[2] = a[2] * b;
64 | out[3] = a[3] * b;
65 | return out;
66 | }
67 |
68 | /**
69 | * Calculates the length of a vec4
70 | *
71 | * @param {vec4} a vector to calculate length of
72 | * @returns {Number} length of a
73 | */
74 | export function length(a) {
75 | let x = a[0];
76 | let y = a[1];
77 | let z = a[2];
78 | let w = a[3];
79 | return Math.sqrt(x * x + y * y + z * z + w * w);
80 | }
81 |
82 | /**
83 | * Normalize a vec4
84 | *
85 | * @param {vec4} out the receiving vector
86 | * @param {vec4} a vector to normalize
87 | * @returns {vec4} out
88 | */
89 | export function normalize(out, a) {
90 | let x = a[0];
91 | let y = a[1];
92 | let z = a[2];
93 | let w = a[3];
94 | let len = x * x + y * y + z * z + w * w;
95 | if (len > 0) {
96 | len = 1 / Math.sqrt(len);
97 | }
98 | out[0] = x * len;
99 | out[1] = y * len;
100 | out[2] = z * len;
101 | out[3] = w * len;
102 | return out;
103 | }
104 |
105 | /**
106 | * Calculates the dot product of two vec4's
107 | *
108 | * @param {vec4} a the first operand
109 | * @param {vec4} b the second operand
110 | * @returns {Number} dot product of a and b
111 | */
112 | export function dot(a, b) {
113 | return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
114 | }
115 |
116 | /**
117 | * Performs a linear interpolation between two vec4's
118 | *
119 | * @param {vec4} out the receiving vector
120 | * @param {vec4} a the first operand
121 | * @param {vec4} b the second operand
122 | * @param {Number} t interpolation amount between the two inputs
123 | * @returns {vec4} out
124 | */
125 | export function lerp(out, a, b, t) {
126 | let ax = a[0];
127 | let ay = a[1];
128 | let az = a[2];
129 | let aw = a[3];
130 | out[0] = ax + t * (b[0] - ax);
131 | out[1] = ay + t * (b[1] - ay);
132 | out[2] = az + t * (b[2] - az);
133 | out[3] = aw + t * (b[3] - aw);
134 | return out;
135 | }
136 |
--------------------------------------------------------------------------------
/types/core/Camera.d.ts:
--------------------------------------------------------------------------------
1 | import { Transform } from './Transform.js';
2 | import { Mat4 } from '../math/Mat4.js';
3 | import { Vec3 } from '../math/Vec3.js';
4 |
5 | import type { OGLRenderingContext } from './Renderer.js';
6 | import type { Vec3Tuple } from '../math/Vec3.js';
7 | import type { Mesh } from './Mesh.js';
8 |
9 | export interface CameraOptions {
10 | near: number;
11 | far: number;
12 | fov: number;
13 | aspect: number;
14 | left: number;
15 | right: number;
16 | bottom: number;
17 | top: number;
18 | zoom: number;
19 | }
20 |
21 | export interface PerspectiveOptions extends Pick {}
22 |
23 | export interface OrthographicOptions extends Pick {}
24 |
25 | export type CameraType = 'perspective' | 'orthographic';
26 |
27 | /**
28 | * A perspective or orthographic camera.
29 | * @see {@link https://github.com/oframe/ogl/blob/master/src/core/Camera.js | Source}
30 | */
31 | export class Camera extends Transform {
32 | projectionMatrix: Mat4;
33 | viewMatrix: Mat4;
34 | projectionViewMatrix: Mat4;
35 | worldPosition: Vec3;
36 |
37 | type: CameraType;
38 |
39 | near: number;
40 | far: number;
41 | fov: number;
42 | aspect: number;
43 | left: number;
44 | right: number;
45 | bottom: number;
46 | top: number;
47 | zoom: number;
48 |
49 | frustum: (Vec3 & {
50 | constant: number;
51 | })[];
52 |
53 | constructor(gl: OGLRenderingContext, options?: Partial);
54 |
55 | perspective(options?: Partial): this;
56 |
57 | orthographic(options?: Partial): this;
58 |
59 | updateMatrixWorld(): this;
60 |
61 | updateProjectionMatrix(): this;
62 |
63 | lookAt(target: Vec3 | Vec3Tuple): this;
64 |
65 | project(v: Vec3): this;
66 |
67 | unproject(v: Vec3): this;
68 |
69 | updateFrustum(): void;
70 |
71 | frustumIntersectsMesh(node: Mesh, worldMatrix?: Mat4): boolean;
72 |
73 | frustumIntersectsSphere(center: Vec3, radius: number): boolean;
74 | }
75 |
--------------------------------------------------------------------------------
/types/core/Geometry.d.ts:
--------------------------------------------------------------------------------
1 | import { Vec3 } from '../math/Vec3.js';
2 |
3 | import type { OGLRenderingContext, RenderState } from './Renderer.js';
4 | import type { Program } from './Program.js';
5 |
6 | export type AttributeMap = Record>;
7 |
8 | export type AttributeData =
9 | | Float32Array
10 | | Uint32Array
11 | | Uint16Array
12 | | Int16Array
13 | | Uint8Array
14 | | Int8Array;
15 |
16 | export interface Attribute {
17 | data: AttributeData;
18 | size: number;
19 | instanced: null | number | boolean;
20 | type: GLenum;
21 | normalized: boolean;
22 |
23 | buffer: WebGLBuffer;
24 | stride: number;
25 | offset: number;
26 | count: number;
27 | target: number;
28 | id: number;
29 | divisor: number;
30 | needsUpdate: boolean;
31 | usage: number;
32 | }
33 |
34 | export interface Bounds {
35 | min: Vec3;
36 | max: Vec3;
37 | center: Vec3;
38 | scale: Vec3;
39 | radius: number;
40 | }
41 |
42 | export type GeometryRaycast = 'sphere' | 'box';
43 |
44 | /**
45 | * A mesh, line, or point geometry.
46 | * @see {@link https://github.com/oframe/ogl/blob/master/src/core/Geometry.js | Source}
47 | */
48 | export class Geometry {
49 | gl: OGLRenderingContext;
50 | attributes: AttributeMap;
51 | id: number;
52 |
53 | VAOs: {
54 | [programKey: string]: WebGLVertexArrayObject;
55 | };
56 |
57 | drawRange: {
58 | start: number;
59 | count: number;
60 | };
61 | instancedCount: number;
62 |
63 | glState: RenderState;
64 |
65 | isInstanced: boolean;
66 | bounds: Bounds;
67 |
68 | // Set from gltf loader
69 | extras?: Record;
70 | extensions?: Record;
71 |
72 | raycast?: GeometryRaycast; // User defined
73 |
74 | constructor(gl: OGLRenderingContext, attributes?: AttributeMap);
75 |
76 | addAttribute(key: string, attr: Partial): number | undefined;
77 |
78 | updateAttribute(attr: Partial): void;
79 |
80 | setIndex(attr: Partial): void;
81 |
82 | setDrawRange(start: number, count: number): void;
83 |
84 | setInstancedCount(value: number): void;
85 |
86 | createVAO(program: Program): void;
87 |
88 | bindAttributes(program: Program): void;
89 |
90 | draw(options: { program: Program; mode?: number }): void;
91 |
92 | getPosition(): Partial;
93 |
94 | computeBoundingBox(attr?: Partial): void;
95 |
96 | computeBoundingSphere(attr?: Partial): void;
97 |
98 | remove(): void;
99 | }
100 |
--------------------------------------------------------------------------------
/types/core/Mesh.d.ts:
--------------------------------------------------------------------------------
1 | import { Transform } from './Transform.js';
2 | import { Mat3 } from '../math/Mat3.js';
3 | import { Mat4 } from '../math/Mat4.js';
4 |
5 | import type { OGLRenderingContext } from './Renderer.js';
6 | import type { Vec2 } from '../math/Vec2.js';
7 | import type { Vec3 } from '../math/Vec3.js';
8 | import type { Geometry } from './Geometry.js';
9 | import type { Program } from './Program.js';
10 | import type { Camera } from './Camera.js';
11 |
12 | export interface MeshOptions<
13 | TGeometry extends Geometry = Geometry,
14 | TProgram extends Program = Program,
15 | > {
16 | geometry: TGeometry;
17 | program: TProgram;
18 | mode: GLenum;
19 | frustumCulled: boolean;
20 | renderOrder: number;
21 | }
22 |
23 | export type MeshRenderCallback = (renderInfo: { mesh: Mesh; camera?: Camera }) => any;
24 |
25 | export interface RaycastHit {
26 | localPoint: Vec3;
27 | distance: number;
28 | point: Vec3;
29 | faceNormal: Vec3;
30 | localFaceNormal: Vec3;
31 | uv: Vec2;
32 | localNormal: Vec3;
33 | normal: Vec3;
34 | }
35 |
36 | /**
37 | * Represents a {@link https://en.wikipedia.org/wiki/Polygon_mesh | polygon mesh}.
38 | * @see {@link https://github.com/oframe/ogl/blob/master/src/core/Mesh.js | Source}
39 | */
40 | export class Mesh<
41 | TGeometry extends Geometry = Geometry,
42 | TProgram extends Program = Program,
43 | > extends Transform {
44 | gl: OGLRenderingContext;
45 | id: number;
46 | geometry: TGeometry;
47 | program: TProgram;
48 | mode: GLenum;
49 |
50 | frustumCulled: boolean;
51 |
52 | renderOrder: number;
53 | modelViewMatrix: Mat4;
54 | normalMatrix: Mat3;
55 | beforeRenderCallbacks: MeshRenderCallback[];
56 | afterRenderCallbacks: MeshRenderCallback[];
57 |
58 | hit?: Partial; // Set from raycaster
59 |
60 | constructor(gl: OGLRenderingContext, options?: Partial);
61 |
62 | onBeforeRender(f: MeshRenderCallback): this;
63 |
64 | onAfterRender(f: MeshRenderCallback): this;
65 |
66 | draw(options?: { camera?: Camera }): void;
67 | }
68 |
--------------------------------------------------------------------------------
/types/core/Program.d.ts:
--------------------------------------------------------------------------------
1 | import type { OGLRenderingContext, BlendFunc, BlendEquation, StencilFunc, StencilOp } from './Renderer';
2 |
3 | export interface ProgramOptions {
4 | vertex: string;
5 | fragment: string;
6 | uniforms: Record;
7 |
8 | transparent: boolean;
9 | cullFace: GLenum | false | null;
10 | frontFace: GLenum;
11 | depthTest: boolean;
12 | depthWrite: boolean;
13 | depthFunc: GLenum;
14 | }
15 |
16 | export interface UniformInfo extends WebGLActiveInfo {
17 | uniformName: string;
18 | nameComponents: string[];
19 | isStruct: boolean;
20 | isStructArray: boolean;
21 | structIndex: number;
22 | structProperty: string;
23 | }
24 |
25 | /**
26 | * A WebGL program.
27 | * @see {@link https://github.com/oframe/ogl/blob/master/src/core/Program.js | Source}
28 | */
29 | export class Program {
30 | gl: OGLRenderingContext;
31 | uniforms: Record;
32 | id: number;
33 |
34 | transparent: boolean;
35 | cullFace: GLenum | false | null;
36 | frontFace: GLenum;
37 | depthTest: boolean;
38 | depthWrite: boolean;
39 | depthFunc: GLenum;
40 | blendFunc: BlendFunc;
41 | blendEquation: BlendEquation;
42 | stencilRef: GLint;
43 | stencilFunc: StencilFunc;
44 | stencilOp: StencilOp;
45 |
46 | vertexShader: WebGLShader;
47 | fragmentShader: WebGLShader;
48 | program: WebGLProgram;
49 | uniformLocations: Map;
50 | attributeLocations: Map;
51 | attributeOrder: string;
52 |
53 | constructor(gl: OGLRenderingContext, options?: Partial);
54 |
55 | setShaders(options: { vertex: string; fragment: string }): void;
56 |
57 | setBlendFunc(src: GLenum, dst: GLenum, srcAlpha?: GLenum, dstAlpha?: GLenum): void;
58 |
59 | setBlendEquation(modeRGB: GLenum, modeAlpha: GLenum): void;
60 |
61 | setStencilFunc(func: GLenum, ref: GLint, mask: GLuint): void;
62 |
63 | setStencilOp(stencilFail: GLenum, depthFail: GLenum, depthPass: GLenum): void;
64 |
65 | applyState(): void;
66 |
67 | use(options?: { flipFaces?: boolean }): void;
68 |
69 | remove(): void;
70 | }
71 |
--------------------------------------------------------------------------------
/types/core/RenderTarget.d.ts:
--------------------------------------------------------------------------------
1 | import { Texture } from './Texture.js';
2 |
3 | import type { OGLRenderingContext } from './Renderer.js';
4 |
5 | export interface RenderTargetOptions {
6 | width: number;
7 | height: number;
8 | target: GLenum;
9 | color: number;
10 | depth: boolean;
11 | stencil: boolean;
12 | depthTexture: boolean;
13 | wrapS: GLenum;
14 | wrapT: GLenum;
15 | wrapR: GLenum;
16 | minFilter: GLenum;
17 | magFilter: GLenum;
18 | type: GLenum;
19 | format: GLenum;
20 | internalFormat: GLenum;
21 | unpackAlignment: number;
22 | premultiplyAlpha: boolean;
23 | }
24 |
25 | /**
26 | * A render target.
27 | * @see {@link https://github.com/oframe/ogl/blob/master/src/core/RenderTarget.js | Source}
28 | */
29 | export class RenderTarget {
30 | gl: OGLRenderingContext;
31 | width: number;
32 | height: number;
33 | depth: boolean;
34 | stencil: boolean;
35 | buffer: WebGLFramebuffer;
36 | target: number;
37 |
38 | textures: Texture[];
39 | texture: Texture;
40 | depthTexture: Texture;
41 | depthBuffer: WebGLRenderbuffer;
42 | stencilBuffer: WebGLRenderbuffer;
43 | depthStencilBuffer: WebGLRenderbuffer;
44 |
45 | constructor(gl: OGLRenderingContext, options?: Partial);
46 |
47 | setSize(width: number, height: number): void;
48 | }
49 |
--------------------------------------------------------------------------------
/types/core/Texture.d.ts:
--------------------------------------------------------------------------------
1 | import type { OGLRenderingContext, RenderState } from './Renderer';
2 |
3 | export type CompressedImage = {
4 | isCompressedTexture?: boolean;
5 | data: Uint8Array;
6 | width: number;
7 | height: number;
8 | }[];
9 |
10 | export type ImageRepresentation =
11 | | HTMLImageElement
12 | | HTMLCanvasElement
13 | | HTMLVideoElement
14 | | HTMLImageElement[]
15 | | HTMLCanvasElement[]
16 | | ArrayBufferView
17 | | CompressedImage;
18 |
19 | export interface TextureOptions {
20 | image: ImageRepresentation;
21 | target: number;
22 | type: number;
23 | format: number;
24 | internalFormat: number;
25 | wrapS: number;
26 | wrapT: number;
27 | wrapR: number;
28 | generateMipmaps: boolean;
29 | minFilter: number;
30 | magFilter: number;
31 | premultiplyAlpha: boolean;
32 | unpackAlignment: number;
33 | flipY: boolean;
34 | anisotropy: number;
35 | level: number;
36 | width: number;
37 | height: number;
38 | length: number;
39 | }
40 |
41 | /**
42 | * A surface, reflection, or refraction map.
43 | * @see {@link https://github.com/oframe/ogl/blob/master/src/core/Texture.js | Source}
44 | */
45 | export class Texture {
46 | gl: OGLRenderingContext;
47 | id: number;
48 |
49 | image?: ImageRepresentation;
50 | target: number;
51 | type: number;
52 | format: number;
53 | internalFormat: number;
54 | minFilter: number;
55 | magFilter: number;
56 | wrapS: number;
57 | wrapT: number;
58 | wrapR: number;
59 | generateMipmaps: boolean;
60 | premultiplyAlpha: boolean;
61 | unpackAlignment: number;
62 | flipY: boolean;
63 | anisotropy: number;
64 | level: number;
65 | width: number;
66 | height: number;
67 | length: number;
68 | texture: WebGLTexture;
69 |
70 | store: {
71 | image?: ImageRepresentation | null;
72 | };
73 |
74 | glState: RenderState;
75 |
76 | state: {
77 | minFilter: number;
78 | magFilter: number;
79 | wrapS: number;
80 | wrapT: number;
81 | anisotropy: number;
82 | };
83 |
84 | needsUpdate: boolean;
85 |
86 | // Set from texture loader
87 | onUpdate?: () => void | null;
88 | ext?: string;
89 | name?: string;
90 | loaded?: Promise;
91 |
92 | constructor(gl: OGLRenderingContext, options?: Partial);
93 |
94 | bind(): void;
95 |
96 | update(textureUnit?: number): void;
97 | }
98 |
--------------------------------------------------------------------------------
/types/core/Transform.d.ts:
--------------------------------------------------------------------------------
1 | import type { Euler } from '../math/Euler.js';
2 | import type { Mat4 } from '../math/Mat4.js';
3 | import type { Quat } from '../math/Quat.js';
4 | import type { Vec3, Vec3Tuple } from '../math/Vec3.js';
5 | import type { GLTFLoader } from '../extras/GLTFLoader.d.js';
6 |
7 | /**
8 | * The base class for most objects and provides a set of properties and methods for manipulating
9 | * objects in 3D space.
10 | * @see {@link https://github.com/oframe/ogl/blob/master/src/core/Transform.js | Source}
11 | */
12 | export class Transform {
13 | /**
14 | * The parent.
15 | * @see {@link https://en.wikipedia.org/wiki/Scene_graph | scene graph}.
16 | */
17 | parent: Transform | null;
18 |
19 | /**
20 | * An array with the children.
21 | */
22 | children: Transform[];
23 |
24 | /**
25 | * The visibility.
26 | */
27 | visible: boolean;
28 |
29 | /**
30 | * The local transform matrix.
31 | */
32 | matrix: Mat4;
33 |
34 | /**
35 | * The world transform matrix.
36 | */
37 | worldMatrix: Mat4;
38 |
39 | /**
40 | * When set, it updates the local transform matrix every frame and also updates the worldMatrix
41 | * property.
42 | * @defaultValue `true`
43 | */
44 | matrixAutoUpdate: boolean;
45 |
46 | /**
47 | * When set, it updates the world transform matrix in that frame and resets this property to
48 | * false.
49 | * @defaultValue `false`
50 | */
51 | worldMatrixNeedsUpdate: boolean;
52 |
53 | /**
54 | * The local position.
55 | */
56 | position: Vec3;
57 |
58 | /**
59 | * The local rotation as a {@link Quat | Quaternion}.
60 | */
61 | quaternion: Quat;
62 |
63 | /**
64 | * The local scale.
65 | * @defaultValue `new Vec3(1)`
66 | */
67 | scale: Vec3;
68 |
69 | /**
70 | * The local rotation as {@link Euler | Euler angles}.
71 | */
72 | rotation: Euler;
73 |
74 | /**
75 | * Up vector used by the {@link lookAt | lookAt} method.
76 | * @defaultValue `new Vec3(0, 1, 0)`
77 | */
78 | up: Vec3;
79 |
80 | /**
81 | * Set from {@link GLTFLoader | GLTF Loader}.
82 | */
83 | name?: string;
84 | extras?: Record;
85 | extensions?: Record;
86 |
87 | /**
88 | * Creates a new transform object.
89 | */
90 | constructor();
91 |
92 | /**
93 | * Sets the parent.
94 | * @param {Transform | null} parent The parent.
95 | * @param {boolean} [notifyParent=true] Adds this as a child of the parent.
96 | */
97 | setParent(parent: Transform | null, notifyParent?: boolean): void;
98 |
99 | /**
100 | * Adds a child.
101 | * @param {Transform} child The child.
102 | * @param {boolean} [notifyChild=true] Sets the parent of the child to this.
103 | */
104 | addChild(child: Transform, notifyChild?: boolean): void;
105 |
106 | /**
107 | * Removes a child.
108 | * @param {Transform} child The child.
109 | * @param {boolean} [notifyChild=true] Sets the parent of the child to null.
110 | */
111 | removeChild(child: Transform, notifyChild?: boolean): void;
112 |
113 | /**
114 | * Updates the world transform matrix.
115 | */
116 | updateMatrixWorld(force?: boolean): void;
117 |
118 | /**
119 | * Updates the local transform matrix.
120 | */
121 | updateMatrix(): void;
122 |
123 | /**
124 | * Executes the callback on this transform object and all descendants.
125 | * @param {Function} callback The callback.
126 | */
127 | traverse(callback: (node: Transform) => boolean | void): void;
128 |
129 | /**
130 | * Decomposes this transform object into it's position, quaternion and scale components.
131 | */
132 | decompose(): void;
133 |
134 | /**
135 | * Rotates this transform object to face a target vector.
136 | * @param {Vec3 | Vec3Tuple} target A target vector to look at.
137 | * @param {boolean} [invert=false] Invert the local position and target vector.
138 | */
139 | lookAt(target: Vec3 | Vec3Tuple, invert?: boolean): void;
140 | }
141 |
--------------------------------------------------------------------------------
/types/extras/Animation.d.ts:
--------------------------------------------------------------------------------
1 | import { Vec3 } from '../math/Vec3.js';
2 | import { Quat } from '../math/Quat.js';
3 |
4 | import type { OGLRenderingContext } from '../core/Renderer.js';
5 | import type { BoneTransform } from './Skin.js';
6 |
7 | export interface AnimationFrame {
8 | position: Vec3;
9 | quaternion: Quat;
10 | scale: Vec3;
11 | }
12 |
13 | export interface AnimationData {
14 | frames: AnimationFrame[];
15 | }
16 |
17 | export interface AnimationOptions {
18 | objects: BoneTransform[];
19 | data: AnimationData;
20 | }
21 |
22 | /**
23 | * A class for animation.
24 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/Animation.js | Source}
25 | */
26 | export class Animation {
27 | objects: BoneTransform[];
28 | data: AnimationData;
29 | elapsed: number;
30 | weight: number;
31 | duration: number;
32 |
33 | constructor(gl: OGLRenderingContext, options?: Partial);
34 |
35 | update(totalWeight?: number, isSet?: boolean): void;
36 | }
37 |
--------------------------------------------------------------------------------
/types/extras/BasisManager.d.ts:
--------------------------------------------------------------------------------
1 | import type { OGLRenderingContext } from '../core/Renderer.js';
2 |
3 | export type BasisManagerFormat = 'astc' | 'bptc' | 's3tc' | 'etc1' | 'pvrtc' | 'none';
4 |
5 | export type BasisImage = (Uint8Array | Uint16Array) & {
6 | width: number;
7 | height: number;
8 | isCompressedTexture: boolean;
9 | internalFormat: number;
10 | isBasis: boolean;
11 | };
12 |
13 | /**
14 | * A {@link https://github.com/BinomialLLC/basis_universal | Basis Universal GPU Texture} loader.
15 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/BasisManager.js | Source}
16 | */
17 | export class BasisManager {
18 | constructor(workerSrc: string | URL, gl?: OGLRenderingContext);
19 |
20 | getSupportedFormat(gl?: OGLRenderingContext): BasisManagerFormat;
21 |
22 | initWorker(workerSrc: string | URL): void;
23 |
24 | onMessage(event: { data: { id: number; error: string; image: BasisImage } }): void;
25 |
26 | parseTexture(buffer: ArrayBuffer): Promise;
27 | }
28 |
--------------------------------------------------------------------------------
/types/extras/Box.d.ts:
--------------------------------------------------------------------------------
1 | import { Geometry } from '../core/Geometry.js';
2 |
3 | import type { OGLRenderingContext } from '../core/Renderer.js';
4 | import type { AttributeMap } from '../core/Geometry.js';
5 |
6 | export interface BoxOptions {
7 | width: number;
8 | height: number;
9 | depth: number;
10 | widthSegments: number;
11 | heightSegments: number;
12 | depthSegments: number;
13 | attributes: AttributeMap;
14 | }
15 |
16 | /**
17 | * A box geometry.
18 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/Box.js | Source}
19 | */
20 | export class Box extends Geometry {
21 | constructor(gl: OGLRenderingContext, options?: Partial);
22 | }
23 |
--------------------------------------------------------------------------------
/types/extras/Curve.d.ts:
--------------------------------------------------------------------------------
1 | import { Vec3 } from '../math/Vec3.js';
2 |
3 | export type CurveType = 'catmullrom' | 'cubicbezier' | 'quadraticbezier';
4 |
5 | export interface CurveOptions {
6 | points: Vec3[];
7 | divisions: number;
8 | type: CurveType;
9 | }
10 |
11 | /**
12 | * A class for creating curves.
13 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/Curve.js | Source}
14 | */
15 | export class Curve {
16 | static CATMULLROM: 'catmullrom';
17 | static CUBICBEZIER: 'cubicbezier';
18 | static QUADRATICBEZIER: 'quadraticbezier';
19 |
20 | points: Vec3[];
21 | divisions: number;
22 | type: CurveType;
23 |
24 | constructor(options?: Partial);
25 |
26 | getPoints(divisions?: number, a?: number, b?: number): Vec3[];
27 | }
28 |
--------------------------------------------------------------------------------
/types/extras/Cylinder.d.ts:
--------------------------------------------------------------------------------
1 | import { Geometry } from '../core/Geometry.js';
2 |
3 | import type { OGLRenderingContext } from '../core/Renderer.js';
4 | import type { AttributeMap } from '../core/Geometry.js';
5 |
6 | export interface CylinderOptions {
7 | radiusTop: number;
8 | radiusBottom: number;
9 | height: number;
10 | radialSegments: number;
11 | heightSegments: number;
12 | openEnded: boolean;
13 | thetaStart: number;
14 | thetaLength: number;
15 | attributes: AttributeMap;
16 | }
17 |
18 | /**
19 | * A cylinder geometry.
20 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/Cylinder.js | Source}
21 | */
22 | export class Cylinder extends Geometry {
23 | constructor(gl: OGLRenderingContext, options?: Partial);
24 | }
25 |
--------------------------------------------------------------------------------
/types/extras/DracoManager.d.ts:
--------------------------------------------------------------------------------
1 | import type { AttributeData } from '../core/Geometry.js';
2 |
3 | export type AttributeIds = Record;
4 |
5 | export type AttributeTypes = Record;
13 |
14 | export interface DecodeGeometryConfig {
15 | attributeIds: AttributeIds;
16 | attributeTypes: AttributeTypes;
17 | }
18 |
19 | export interface IndexResult {
20 | array: Uint32Array;
21 | itemSize: number;
22 | }
23 |
24 | export interface AttributeResult {
25 | name: string;
26 | array: AttributeData;
27 | itemSize: number;
28 | normalized?: boolean;
29 | }
30 |
31 | export interface GeometryData {
32 | index: IndexResult;
33 | attributes: AttributeResult[];
34 | }
35 |
36 | /**
37 | * A {@link https://github.com/google/draco | Draco 3D Data Compression} loader.
38 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/DracoManager.js | Source}
39 | */
40 | export class DracoManager {
41 | constructor(workerSrc: string | URL);
42 |
43 | initWorker(workerSrc: string | URL): void;
44 |
45 | onMessage(event: { data: { id: number; error: string; geometry: GeometryData } }): void;
46 |
47 | decodeGeometry(buffer: ArrayBuffer, config: DecodeGeometryConfig): Promise;
48 | }
49 |
--------------------------------------------------------------------------------
/types/extras/Flowmap.d.ts:
--------------------------------------------------------------------------------
1 | import { RenderTarget } from '../core/RenderTarget.js';
2 | import { Mesh } from '../core/Mesh.js';
3 | import { Vec2 } from '../math/Vec2.js';
4 |
5 | import type { OGLRenderingContext } from '../core/Renderer.js';
6 |
7 | export interface FlowmapOptions {
8 | size: number;
9 | falloff: number;
10 | alpha: number;
11 | dissipation: number;
12 | type: number;
13 | }
14 |
15 | /**
16 | * Mouse flowmap.
17 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/Flowmap.js | Source}
18 | */
19 | export class Flowmap {
20 | gl: OGLRenderingContext;
21 |
22 | uniform: { value: RenderTarget['texture'] | null };
23 |
24 | mask: {
25 | read: RenderTarget;
26 | write: RenderTarget;
27 | swap: () => void;
28 | };
29 |
30 | aspect: number;
31 | mouse: Vec2;
32 | velocity: Vec2;
33 |
34 | mesh: Mesh;
35 |
36 | constructor(gl: OGLRenderingContext, options?: Partial);
37 |
38 | update(): void;
39 | }
40 |
--------------------------------------------------------------------------------
/types/extras/GLTFAnimation.d.ts:
--------------------------------------------------------------------------------
1 | export interface GLTFAnimationData {
2 | node: any;
3 | transform: any;
4 | interpolation: any;
5 | times: any;
6 | values: any;
7 | }
8 |
9 | /**
10 | * A class for animation.
11 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/GLTFAnimation.js | Source}
12 | */
13 | export class GLTFAnimation {
14 | data: GLTFAnimationData[];
15 | elapsed: number;
16 | weight: number;
17 | loop: boolean;
18 | startTime: number;
19 | endTime: number;
20 | duration: number;
21 |
22 | constructor(data: GLTFAnimationData[], weight?: number);
23 |
24 | update(totalWeight?: number, isSet?: boolean): void;
25 |
26 | cubicSplineInterpolate(t: number, prevVal: any, prevTan: any, nextTan: any, nextVal: any): any;
27 | }
28 |
--------------------------------------------------------------------------------
/types/extras/GLTFSkin.d.ts:
--------------------------------------------------------------------------------
1 | import { Mesh } from '../core/Mesh.js';
2 | import { Mat4 } from '../math/Mat4.js';
3 | import { Texture } from '../core/Texture.js';
4 |
5 | import type { OGLRenderingContext } from '../core/Renderer.js';
6 | import type { Geometry } from '../core/Geometry.js';
7 | import type { Program } from '../core/Program.js';
8 | import type { Camera } from '../core/Camera.js';
9 |
10 | export interface GLTFSkinSkeleton {
11 | joints: { worldMatrix: Mat4; bindInverse: Mat4 }[];
12 | }
13 |
14 | export interface GLTFSkinOptions {
15 | skeleton: GLTFSkinSkeleton;
16 | geometry: Geometry;
17 | program: Program;
18 | mode: GLenum;
19 | }
20 |
21 | /**
22 | * A mesh with a skeleton and bones for animation.
23 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/GLTFSkin.js | Source}
24 | */
25 | export class GLTFSkin extends Mesh {
26 | skeleton: GLTFSkinSkeleton;
27 | program: TProgram;
28 |
29 | boneMatrices: Float32Array;
30 | boneTextureSize: number;
31 | boneTexture: Texture;
32 |
33 | constructor(gl: OGLRenderingContext, options?: Partial);
34 |
35 | createBoneTexture(): void;
36 |
37 | updateUniforms(): void;
38 |
39 | override draw(options?: { camera?: Camera }): void;
40 | }
41 |
--------------------------------------------------------------------------------
/types/extras/GPGPU.d.ts:
--------------------------------------------------------------------------------
1 | import { Program } from '../core/Program.js';
2 | import { Mesh } from '../core/Mesh.js';
3 | import { Texture } from '../core/Texture.js';
4 | import { RenderTarget } from '../core/RenderTarget.js';
5 | import { Triangle } from './Triangle.js';
6 |
7 | import type { OGLRenderingContext } from '../core/Renderer.js';
8 |
9 | export interface GPGPUOptions {
10 | data: Float32Array;
11 | geometry: Triangle;
12 | type: Texture['type'];
13 | }
14 |
15 | export interface GPGPUPass {
16 | mesh: Mesh;
17 | program: Program;
18 | uniforms: Record;
19 | enabled: boolean;
20 | textureUniform: string;
21 | vertex: string;
22 | fragment: string;
23 | }
24 |
25 | /**
26 | * A class for {@link https://en.wikipedia.org/wiki/General-purpose_computing_on_graphics_processing_units | GPGPU (General Purpose GPU)} calculations.
27 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/GPGPU.js | Source}
28 | */
29 | export class GPGPU {
30 | gl: OGLRenderingContext;
31 | passes: GPGPUPass[];
32 | geometry: Triangle;
33 | dataLength: number;
34 | size: number;
35 | coords: Float32Array;
36 | uniform: { value: any };
37 |
38 | fbo: {
39 | read: RenderTarget;
40 | write: RenderTarget;
41 | swap: () => void;
42 | };
43 |
44 | constructor(gl: OGLRenderingContext, options?: Partial);
45 |
46 | addPass(options?: Partial): GPGPUPass;
47 |
48 | render(): void;
49 | }
50 |
--------------------------------------------------------------------------------
/types/extras/InstancedMesh.d.ts:
--------------------------------------------------------------------------------
1 | import { Mesh } from '../core/Mesh.js';
2 |
3 | /**
4 | * A special version of {@link Mesh | Mesh} with instanced frustum culling.
5 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/InstancedMesh.js | Source}
6 | */
7 | export class InstancedMesh extends Mesh {
8 | readonly isInstancedMesh: true;
9 |
10 | addFrustumCull(): void;
11 |
12 | removeFrustumCull(): void;
13 | }
14 |
--------------------------------------------------------------------------------
/types/extras/KTXTexture.d.ts:
--------------------------------------------------------------------------------
1 | import { Texture } from '../core/Texture.js';
2 |
3 | import type { OGLRenderingContext } from '../core/Renderer.js';
4 |
5 | export interface KTXTextureOptions {
6 | buffer: ArrayBuffer;
7 | src: string;
8 | wrapS: number;
9 | wrapT: number;
10 | anisotropy: number;
11 | minFilter: number;
12 | magFilter: number;
13 | }
14 |
15 | /**
16 | * A {@link https://github.com/KhronosGroup/KTX-Specification | KTX 2.0 GPU Texture} container.
17 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/KTXTexture.js | Source}
18 | */
19 | export class KTXTexture extends Texture {
20 | constructor(gl: OGLRenderingContext, options?: Partial);
21 |
22 | parseBuffer(buffer: ArrayBuffer): void;
23 | }
24 |
--------------------------------------------------------------------------------
/types/extras/NormalProgram.d.ts:
--------------------------------------------------------------------------------
1 | import { Program } from '../core/Program.js';
2 |
3 | import type { OGLRenderingContext } from '../core/Renderer.js';
4 | import type { ProgramOptions } from '../core/Program.js';
5 |
6 | /**
7 | * A normal program.
8 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/NormalProgram.js | Source}
9 | */
10 | export class NormalProgram extends Program {
11 | constructor(gl: OGLRenderingContext, options?: Partial);
12 | }
13 |
--------------------------------------------------------------------------------
/types/extras/Orbit.d.ts:
--------------------------------------------------------------------------------
1 | import { Vec3 } from '../math/Vec3.js';
2 |
3 | import type { Camera } from '../core/Camera.js';
4 |
5 | export type ZoomStyle = 'dolly' | 'fov';
6 |
7 | export interface OrbitOptions {
8 | element: HTMLElement;
9 | enabled: boolean;
10 | target: Vec3;
11 | ease: number;
12 | inertia: number;
13 | enableRotate: boolean;
14 | rotateSpeed: number;
15 | autoRotate: boolean;
16 | autoRotateSpeed: number;
17 | enableZoom: boolean;
18 | zoomSpeed: number;
19 | zoomStyle: ZoomStyle;
20 | enablePan: boolean;
21 | panSpeed: number;
22 | minPolarAngle: number;
23 | maxPolarAngle: number;
24 | minAzimuthAngle: number;
25 | maxAzimuthAngle: number;
26 | minDistance: number;
27 | maxDistance: number;
28 | }
29 |
30 | /**
31 | * Orbit controls based on the three.js `OrbitControls` class, rewritten using ES6 with some
32 | * additions and subtractions.
33 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/Orbit.js | Source}
34 | * @see {@link https://github.com/mrdoob/three.js/blob/master/examples/jsm/controls/OrbitControls.js | `OrbitControls` Source}
35 | */
36 | export class Orbit {
37 | enabled: boolean;
38 | target: Vec3;
39 | zoomStyle: ZoomStyle;
40 |
41 | minDistance: number;
42 | maxDistance: number;
43 |
44 | offset: Vec3;
45 |
46 | constructor(object: Camera, options?: Partial);
47 |
48 | update(): void;
49 |
50 | forcePosition(): void;
51 |
52 | remove(): void;
53 | }
54 |
--------------------------------------------------------------------------------
/types/extras/Plane.d.ts:
--------------------------------------------------------------------------------
1 | import { Geometry } from '../core/Geometry.js';
2 |
3 | import type { OGLRenderingContext } from '../core/Renderer.js';
4 | import type { AttributeMap } from '../core/Geometry.js';
5 |
6 | export interface PlaneOptions {
7 | width: number;
8 | height: number;
9 | widthSegments: number;
10 | heightSegments: number;
11 | attributes: AttributeMap;
12 | }
13 |
14 | /**
15 | * A plane geometry.
16 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/Plane.js | Source}
17 | */
18 | export class Plane extends Geometry {
19 | constructor(gl: OGLRenderingContext, options?: Partial);
20 |
21 | static buildPlane(
22 | position: Float32Array,
23 | normal: Float32Array,
24 | uv: Float32Array,
25 | index: Uint32Array | Uint16Array,
26 | width: number,
27 | height: number,
28 | depth: number,
29 | wSegs: number,
30 | hSegs: number,
31 | u: number,
32 | v: number,
33 | w: number,
34 | uDir: number,
35 | vDir: number,
36 | i: number,
37 | ii: number,
38 | ): void;
39 | }
40 |
--------------------------------------------------------------------------------
/types/extras/Polyline.d.ts:
--------------------------------------------------------------------------------
1 | import { Geometry } from '../core/Geometry.js';
2 | import { Program } from '../core/Program.js';
3 | import { Mesh } from '../core/Mesh.js';
4 | import { Vec2 } from '../math/Vec2.js';
5 | import { Vec3 } from '../math/Vec3.js';
6 | import { Color } from '../math/Color.js';
7 |
8 | import type { OGLRenderingContext } from '../core/Renderer.js';
9 | import type { AttributeMap } from '../core/Geometry.js';
10 |
11 | export interface PolylineOptions {
12 | points: Vec3[];
13 | vertex: string;
14 | fragment: string;
15 | uniforms: Record;
16 | attributes: AttributeMap;
17 | }
18 |
19 | /**
20 | * A polyline mesh.
21 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/Polyline.js | Source}
22 | */
23 | export class Polyline {
24 | gl: OGLRenderingContext;
25 | points: Vec3[];
26 | count: number;
27 |
28 | position: Float32Array;
29 | prev: Float32Array;
30 | next: Float32Array;
31 |
32 | geometry: Geometry;
33 |
34 | resolution: { value: Vec2 };
35 | dpr: { value: number };
36 | thickness: { value: number };
37 | color: { value: Color };
38 | miter: { value: number };
39 |
40 | program: Program;
41 |
42 | mesh: Mesh;
43 |
44 | constructor(gl: OGLRenderingContext, options?: Partial);
45 |
46 | updateGeometry(): void;
47 |
48 | resize(): void;
49 | }
50 |
--------------------------------------------------------------------------------
/types/extras/Post.d.ts:
--------------------------------------------------------------------------------
1 | import { Program } from '../core/Program.js';
2 | import { Mesh } from '../core/Mesh.js';
3 | import { RenderTarget } from '../core/RenderTarget.js';
4 | import { Triangle } from './Triangle.js';
5 |
6 | import type { OGLRenderingContext } from '../core/Renderer.js';
7 | import type { Camera } from '../core/Camera.js';
8 | import type { Transform } from '../core/Transform.js';
9 | import type { Texture } from '../core/Texture.js';
10 |
11 | export interface PostOptions {
12 | width: number;
13 | height: number;
14 | dpr: number;
15 | wrapS: GLenum;
16 | wrapT: GLenum;
17 | minFilter: GLenum;
18 | magFilter: GLenum;
19 | geometry: Triangle;
20 | targetOnly: boolean;
21 | depth: boolean;
22 | }
23 |
24 | export interface Pass {
25 | mesh: Mesh;
26 | program: Program;
27 | uniforms: Record;
28 | enabled: boolean;
29 | textureUniform: string;
30 | vertex: string;
31 | fragment: string;
32 | }
33 |
34 | /**
35 | * A class for managing post-processing shader passes.
36 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/Post.js | Source}
37 | */
38 | export class Post {
39 | gl: OGLRenderingContext;
40 |
41 | passes: Pass[];
42 |
43 | geometry: Triangle;
44 |
45 | uniform: { value: any };
46 | targetOnly: boolean;
47 |
48 | dpr: number;
49 | width: number;
50 | height: number;
51 |
52 | resolutionWidth: number;
53 | resolutionHeight: number;
54 |
55 | fbo: {
56 | read: RenderTarget;
57 | write: RenderTarget;
58 | swap: () => void;
59 | };
60 |
61 | constructor(gl: OGLRenderingContext, options?: Partial);
62 |
63 | addPass(options?: Partial): Pass;
64 |
65 | resize(
66 | options?: Partial<{
67 | width: number;
68 | height: number;
69 | dpr: number;
70 | }>,
71 | ): void;
72 |
73 | render(
74 | options: Partial<{
75 | scene: Transform;
76 | camera: Camera;
77 | texture: Texture;
78 | target: RenderTarget;
79 | update: boolean;
80 | sort: boolean;
81 | frustumCull: boolean;
82 | beforePostCallbacks: Function[];
83 | }>,
84 | ): void;
85 | }
86 |
--------------------------------------------------------------------------------
/types/extras/Raycast.d.ts:
--------------------------------------------------------------------------------
1 | import { Vec2 } from '../math/Vec2.js';
2 | import { Vec3 } from '../math/Vec3.js';
3 |
4 | import type { Vec2Tuple } from '../math/Vec2.js';
5 | import type { Bounds } from '../core/Geometry.js';
6 | import type { Camera } from '../core/Camera.js';
7 | import type { Mesh } from '../core/Mesh.js';
8 |
9 | /**
10 | * A class to assist with {@link https://en.wikipedia.org/wiki/Ray_casting | raycasting}.
11 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/Raycast.js | Source}
12 | */
13 | export class Raycast {
14 | origin: Vec3;
15 | direction: Vec3;
16 |
17 | constructor();
18 |
19 | castMouse(camera: Camera, mouse?: Vec2 | Vec2Tuple): void;
20 |
21 | intersectBounds(meshes: Mesh | Mesh[], options?: { maxDistance?: number; output?: Mesh[] }): Mesh[];
22 |
23 | intersectMeshes(
24 | meshes: Mesh[],
25 | options?: {
26 | cullFace?: boolean;
27 | maxDistance?: number;
28 | includeUV?: boolean;
29 | includeNormal?: boolean;
30 | output?: Mesh[];
31 | },
32 | ): Mesh[];
33 |
34 | intersectPlane(plane: { origin: Vec3; normal: Vec3 }, origin?: Vec3, direction?: Vec3): Vec3;
35 |
36 | intersectSphere(sphere: Bounds, origin?: Vec3, direction?: Vec3): number;
37 |
38 | intersectBox(box: Bounds, origin?: Vec3, direction?: Vec3): number;
39 |
40 | intersectTriangle(a: Vec3, b: Vec3, c: Vec3, backfaceCulling?: boolean, origin?: Vec3, direction?: Vec3, normal?: Vec3): number;
41 |
42 | getBarycoord(point: Vec3, a: Vec3, b: Vec3, c: Vec3, target?: Vec3): Vec3;
43 | }
44 |
--------------------------------------------------------------------------------
/types/extras/Shadow.d.ts:
--------------------------------------------------------------------------------
1 | import { Camera } from '../core/Camera.js';
2 | import { Program } from '../core/Program.js';
3 | import { RenderTarget } from '../core/RenderTarget.js';
4 |
5 | import type { OGLRenderingContext } from '../core/Renderer.js';
6 | import type { Transform } from '../core/Transform.js';
7 | import type { Mesh } from '../core/Mesh.js';
8 |
9 | export interface ShadowOptions {
10 | light: Camera;
11 | width: number;
12 | height: number;
13 | }
14 |
15 | /**
16 | * Shadow map.
17 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/Shadow.js | Source}
18 | */
19 | export class Shadow {
20 | gl: OGLRenderingContext;
21 |
22 | light: Camera;
23 |
24 | target: RenderTarget;
25 | targetUniform: { value: RenderTarget['texture'] | null };
26 |
27 | depthProgram: Program;
28 |
29 | castMeshes: Mesh[];
30 |
31 | constructor(gl: OGLRenderingContext, options?: Partial);
32 |
33 | add(options: {
34 | mesh: Mesh;
35 | receive?: boolean;
36 | cast?: boolean;
37 | vertex?: string;
38 | fragment?: string;
39 | uniformProjection?: string;
40 | uniformView?: string;
41 | uniformTexture?: string;
42 | }): void;
43 |
44 | setSize(options: { width?: number; height?: number }): void;
45 |
46 | render(options: { scene: Transform }): void;
47 | }
48 |
--------------------------------------------------------------------------------
/types/extras/Skin.d.ts:
--------------------------------------------------------------------------------
1 | import { Mesh } from '../core/Mesh.js';
2 | import { Transform } from '../core/Transform.js';
3 | import { Mat4 } from '../math/Mat4.js';
4 | import { Texture } from '../core/Texture.js';
5 | import { Animation } from './Animation.js';
6 |
7 | import type { OGLRenderingContext } from '../core/Renderer.js';
8 | import type { Quat } from '../math/Quat.js';
9 | import type { Vec3 } from '../math/Vec3.js';
10 | import type { Geometry } from '../core/Geometry.js';
11 | import type { Program } from '../core/Program.js';
12 | import type { Camera } from '../core/Camera.js';
13 |
14 | export interface SkinRig {
15 | bindPose: { position: Vec3; quaternion: Quat; scale: Vec3 };
16 | bones: { name: string; parent: Transform }[];
17 | }
18 |
19 | export interface SkinOptions {
20 | rig: SkinRig;
21 | geometry: Geometry;
22 | program: Program;
23 | mode: GLenum;
24 | }
25 |
26 | export interface BoneTransform extends Transform {
27 | name: string;
28 | bindInverse: Mat4;
29 | }
30 |
31 | /**
32 | * A mesh with a skeleton and bones for animation.
33 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/Skin.js | Source}
34 | */
35 | export class Skin extends Mesh {
36 | root: Transform;
37 |
38 | bones: Transform[];
39 |
40 | boneMatrices: Float32Array;
41 | boneTextureSize: number;
42 | boneTexture: Texture;
43 | animations: Animation[];
44 |
45 | constructor(gl: OGLRenderingContext, options?: Partial);
46 |
47 | createBones(rig: SkinRig): void;
48 |
49 | createBoneTexture(): void;
50 |
51 | addAnimation(data: Animation['data']): Animation;
52 |
53 | update(): void;
54 |
55 | override draw(options?: { camera?: Camera }): void;
56 | }
57 |
--------------------------------------------------------------------------------
/types/extras/Sphere.d.ts:
--------------------------------------------------------------------------------
1 | import { Geometry } from '../core/Geometry.js';
2 |
3 | import type { OGLRenderingContext } from '../core/Renderer.js';
4 | import type { AttributeMap } from '../core/Geometry.js';
5 |
6 | export interface SphereOptions {
7 | radius: number;
8 | widthSegments: number;
9 | heightSegments: number;
10 | phiStart: number;
11 | phiLength: number;
12 | thetaStart: number;
13 | thetaLength: number;
14 | attributes: AttributeMap;
15 | }
16 |
17 | /**
18 | * A sphere geometry.
19 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/Sphere.js | Source}
20 | */
21 | export class Sphere extends Geometry {
22 | constructor(gl: OGLRenderingContext, options?: Partial);
23 | }
24 |
--------------------------------------------------------------------------------
/types/extras/Text.d.ts:
--------------------------------------------------------------------------------
1 | export type TextAlign = 'left' | 'right' | 'center';
2 |
3 | export interface TextOptions {
4 | font: object;
5 | text: string;
6 | width: number;
7 | align: TextAlign;
8 | size: number;
9 | letterSpacing: number;
10 | lineHeight: number;
11 | wordSpacing: number;
12 | wordBreak: boolean;
13 | }
14 |
15 | /**
16 | * A text geometry.
17 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/Text.js | Source}
18 | */
19 | export class Text {
20 | buffers: {
21 | position: Float32Array;
22 | uv: Float32Array;
23 | id: Float32Array;
24 | index: Uint32Array | Uint16Array;
25 | };
26 | numLines: number;
27 | height: number;
28 | width: number;
29 |
30 | constructor(options?: Partial);
31 |
32 | resize(options: { width: number }): void;
33 |
34 | update(options: { text: string }): void;
35 | }
36 |
--------------------------------------------------------------------------------
/types/extras/Texture3D.d.ts:
--------------------------------------------------------------------------------
1 | import { Texture } from '../core/Texture.js';
2 |
3 | import type { OGLRenderingContext } from '../core/Renderer.js';
4 | import type { TextureOptions } from '../core/Texture.js';
5 |
6 | export interface Texture3DOptions extends TextureOptions {
7 | src: string;
8 | tileCountX: number;
9 | }
10 |
11 | /**
12 | * A class for rearranging a flat 3D texture from software like Houdini.
13 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/Texture3D.js | Source}
14 | */
15 | export class Texture3D extends Texture {
16 | constructor(gl: OGLRenderingContext, options?: Partial);
17 | }
18 |
--------------------------------------------------------------------------------
/types/extras/TextureLoader.d.ts:
--------------------------------------------------------------------------------
1 | import { Texture } from '../core/Texture.js';
2 |
3 | import type { OGLRenderingContext } from '../core/Renderer.js';
4 |
5 | /**
6 | * The texture loader.
7 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/TextureLoader.js | Source}
8 | */
9 | export class TextureLoader {
10 | static load(gl: OGLRenderingContext, options?: object): Texture;
11 |
12 | static getSupportedExtensions(gl: OGLRenderingContext): string[];
13 |
14 | static loadKTX(src: string, texture: Texture): Promise;
15 |
16 | static loadImage(gl: OGLRenderingContext, src: string, texture: Texture, flipY: boolean): Promise;
17 |
18 | static clearCache(): void;
19 | }
20 |
--------------------------------------------------------------------------------
/types/extras/Torus.d.ts:
--------------------------------------------------------------------------------
1 | import { Geometry } from '../core/Geometry.js';
2 |
3 | import type { OGLRenderingContext } from '../core/Renderer.js';
4 | import type { AttributeMap } from '../core/Geometry.js';
5 |
6 | export interface TorusOptions {
7 | radius: number;
8 | tube: number;
9 | radialSegments: number;
10 | tubularSegments: number;
11 | arc: number;
12 | attributes: AttributeMap;
13 | }
14 |
15 | /**
16 | * A torus geometry.
17 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/Torus.js | Source}
18 | */
19 | export class Torus extends Geometry {
20 | constructor(gl: OGLRenderingContext, options?: Partial);
21 | }
22 |
--------------------------------------------------------------------------------
/types/extras/Triangle.d.ts:
--------------------------------------------------------------------------------
1 | import { Geometry } from '../core/Geometry.js';
2 |
3 | /**
4 | * A triangle geometry.
5 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/Triangle.js | Source}
6 | */
7 | export class Triangle extends Geometry {}
8 |
--------------------------------------------------------------------------------
/types/extras/Tube.d.ts:
--------------------------------------------------------------------------------
1 | import { Geometry } from '../core/Geometry.js';
2 |
3 | import type { OGLRenderingContext } from '../core/Renderer.js';
4 | import type { AttributeMap } from '../core/Geometry.js';
5 | import type { Path } from './path/Path.js';
6 |
7 | export interface TubeOptions {
8 | path: Path;
9 | radius: number;
10 | tubularSegments: number;
11 | radialSegments: number;
12 | closed: boolean;
13 | attributes: AttributeMap;
14 | }
15 |
16 | /**
17 | * A tube geometry.
18 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/Tube.js | Source}
19 | */
20 | export class Tube extends Geometry {
21 | path: Path;
22 | radius: number;
23 | tubularSegments: number;
24 | radialSegments: number;
25 | closed: boolean;
26 |
27 | frenetFrames: object;
28 |
29 | positions: Float32Array;
30 | normals: Float32Array;
31 | uvs: Float32Array;
32 | indices: Uint32Array | Uint16Array;
33 |
34 | constructor(gl: OGLRenderingContext, options?: Partial);
35 | }
36 |
--------------------------------------------------------------------------------
/types/extras/WireMesh.d.ts:
--------------------------------------------------------------------------------
1 | import { Mesh } from '../core/Mesh.js';
2 |
3 | import type { OGLRenderingContext } from '../core/Renderer.js';
4 | import type { Color } from '../math/Color.js';
5 | import type { MeshOptions } from '../core/Mesh.js';
6 |
7 | export interface WireMeshOptions extends MeshOptions {
8 | wireColor: Color;
9 | }
10 |
11 | /**
12 | * A wireframe mesh.
13 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/WireMesh.js | Source}
14 | */
15 | export class WireMesh extends Mesh {
16 | constructor(gl: OGLRenderingContext, options?: Partial);
17 | }
18 |
--------------------------------------------------------------------------------
/types/extras/helpers/AxesHelper.d.ts:
--------------------------------------------------------------------------------
1 | import { Mesh } from '../../core/Mesh.js';
2 |
3 | import type { OGLRenderingContext } from '../../core/Renderer.js';
4 | import type { Color } from '../../math/Color.js';
5 |
6 | export interface AxesHelperOptions {
7 | size: number;
8 | symmetric: boolean;
9 | xColor: Color;
10 | yColor: Color;
11 | zColor: Color;
12 | }
13 |
14 | /**
15 | * Axes helper.
16 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/helpers/AxesHelper.js | Source}
17 | */
18 | export class AxesHelper extends Mesh {
19 | constructor(gl: OGLRenderingContext, options?: Partial);
20 | }
21 |
--------------------------------------------------------------------------------
/types/extras/helpers/FaceNormalsHelper.d.ts:
--------------------------------------------------------------------------------
1 | import { Mesh } from '../../core/Mesh.js';
2 |
3 | import type { Color } from '../../math/Color.js';
4 |
5 | export interface FaceNormalsHelperOptions {
6 | size: number;
7 | color: Color;
8 | }
9 |
10 | /**
11 | * Face normals helper.
12 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/helpers/FaceNormalsHelper.js | Source}
13 | */
14 | export class FaceNormalsHelper extends Mesh {
15 | constructor(object: Mesh, options?: Partial);
16 | }
17 |
--------------------------------------------------------------------------------
/types/extras/helpers/GridHelper.d.ts:
--------------------------------------------------------------------------------
1 | import { Mesh } from '../../core/Mesh.js';
2 |
3 | import type { OGLRenderingContext } from '../../core/Renderer.js';
4 | import type { Color } from '../../math/Color.js';
5 |
6 | export interface GridHelperOptions {
7 | size: number;
8 | divisions: number;
9 | color: Color;
10 | }
11 |
12 | /**
13 | * Grid helper.
14 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/helpers/GridHelper.js | Source}
15 | */
16 | export class GridHelper extends Mesh {
17 | constructor(gl: OGLRenderingContext, options?: Partial);
18 | }
19 |
--------------------------------------------------------------------------------
/types/extras/helpers/VertexNormalsHelper.d.ts:
--------------------------------------------------------------------------------
1 | import { Mesh } from '../../core/Mesh.js';
2 |
3 | import type { Color } from '../../math/Color.js';
4 |
5 | export interface VertexNormalsHelperOptions {
6 | size: number;
7 | color: Color;
8 | }
9 |
10 | /**
11 | * Vertex normals helper.
12 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/helpers/VertexNormalsHelper.js | Source}
13 | */
14 | export class VertexNormalsHelper extends Mesh {
15 | constructor(object: Mesh, options?: Partial);
16 | }
17 |
--------------------------------------------------------------------------------
/types/extras/path/BaseSegment.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Abstract base class for path segments.
3 | * This class contains common methods for all segments types.
4 | */
5 | export default class BaseSegment {}
6 |
--------------------------------------------------------------------------------
/types/extras/path/CubicBezierSegment.d.ts:
--------------------------------------------------------------------------------
1 | import BaseSegment from './BaseSegment.js';
2 |
3 | export default class CubicBezierSegment extends BaseSegment {}
4 |
--------------------------------------------------------------------------------
/types/extras/path/LineSegment.d.ts:
--------------------------------------------------------------------------------
1 | import BaseSegment from './BaseSegment.js';
2 |
3 | export default class LineSegment extends BaseSegment {}
4 |
--------------------------------------------------------------------------------
/types/extras/path/Path.d.ts:
--------------------------------------------------------------------------------
1 | import { Vec3 } from '../../math/Vec3.js';
2 |
3 | /**
4 | * Path builder.
5 | * @see {@link https://github.com/oframe/ogl/blob/master/src/extras/path/Path.js | Source}
6 | */
7 | export class Path {
8 | tiltFunction: Function | null;
9 |
10 | constructor();
11 |
12 | moveTo(p: Vec3, tilt?: number): void;
13 |
14 | bezierCurveTo(cp1: Vec3, cp2: Vec3, p: Vec3, tilt?: number): this;
15 |
16 | quadraticCurveTo(cp: Vec3, p: Vec3, tilt?: number): this;
17 |
18 | lineTo(p: Vec3, tilt?: number): this;
19 |
20 | addSegment(segment: object): this;
21 |
22 | getSegments(): object[];
23 |
24 | updateLength(): void;
25 |
26 | getLength(): number;
27 |
28 | findSegmentIndexAtLength(len: number): [number, number];
29 |
30 | getPointAtLength(len: number, out?: Vec3): Vec3;
31 |
32 | getPointAt(t: number, out?: Vec3): Vec3;
33 |
34 | getTangentAtLength(len: number, out?: Vec3): number;
35 |
36 | getTangentAt(t: number, out?: Vec3): number;
37 |
38 | getTiltAtLength(len: number): number;
39 |
40 | getTiltAt(t: number): number;
41 |
42 | getPoints(divisions?: number): Vec3[];
43 |
44 | computeFrenetFrames(divisions?: number, closed?: boolean): { tangents: Vec3[]; normals: Vec3[]; binormals: Vec3[] };
45 | }
46 |
--------------------------------------------------------------------------------
/types/extras/path/QuadraticBezierSegment.d.ts:
--------------------------------------------------------------------------------
1 | import BaseSegment from './BaseSegment.js';
2 |
3 | export default class QuadraticBezierSegment extends BaseSegment {}
4 |
--------------------------------------------------------------------------------
/types/index.d.ts:
--------------------------------------------------------------------------------
1 | // Type definitions for ogl 1.0.0
2 | // Project: https://github.com/oframe/ogl
3 | // Definitions by: Xin Chen
4 | // Cody Bennett
5 | // Patrick Schroen
6 | // Definitions: https://github.com/oframe/ogl
7 |
8 | // Core
9 | export * from './core/Geometry';
10 | export * from './core/Program';
11 | export * from './core/Renderer';
12 | export * from './core/Camera';
13 | export * from './core/Transform';
14 | export * from './core/Mesh';
15 | export * from './core/Texture';
16 | export * from './core/RenderTarget';
17 |
18 | // Maths
19 | export * from './math/Color';
20 | export * from './math/Euler';
21 | export * from './math/Mat3';
22 | export * from './math/Mat4';
23 | export * from './math/Quat';
24 | export * from './math/Vec2';
25 | export * from './math/Vec3';
26 | export * from './math/Vec4';
27 |
28 | // Extras
29 | export * from './extras/Plane';
30 | export * from './extras/Box';
31 | export * from './extras/Sphere';
32 | export * from './extras/Cylinder';
33 | export * from './extras/Triangle';
34 | export * from './extras/Torus';
35 | export * from './extras/Orbit';
36 | export * from './extras/Raycast';
37 | export * from './extras/Curve';
38 | export * from './extras/path/Path';
39 | export * from './extras/Tube';
40 | export * from './extras/Post';
41 | export * from './extras/Skin';
42 | export * from './extras/Animation';
43 | export * from './extras/Text';
44 | export * from './extras/NormalProgram';
45 | export * from './extras/Flowmap';
46 | export * from './extras/GPGPU';
47 | export * from './extras/Polyline';
48 | export * from './extras/Shadow';
49 | export * from './extras/KTXTexture';
50 | export * from './extras/TextureLoader';
51 | export * from './extras/GLTFLoader';
52 | export * from './extras/GLTFSkin';
53 | export * from './extras/GLTFAnimation';
54 | export * from './extras/DracoManager';
55 | export * from './extras/BasisManager';
56 | export * from './extras/WireMesh';
57 | export * from './extras/helpers/AxesHelper';
58 | export * from './extras/helpers/GridHelper';
59 | export * from './extras/helpers/VertexNormalsHelper';
60 | export * from './extras/helpers/FaceNormalsHelper';
61 | export * from './extras/InstancedMesh';
62 | export * from './extras/Texture3D.js';
63 |
--------------------------------------------------------------------------------
/types/math/Color.d.ts:
--------------------------------------------------------------------------------
1 | export type ColorTuple = [r: number, g: number, b: number];
2 |
3 | export type ColorRepresentation =
4 | | ColorTuple
5 | | Color
6 | | 'black'
7 | | 'white'
8 | | 'red'
9 | | 'green'
10 | | 'blue'
11 | | 'fuchsia'
12 | | 'cyan'
13 | | 'yellow'
14 | | 'orange'
15 | | string
16 | | number;
17 |
18 | /**
19 | * Represents a color.
20 | * @see {@link https://github.com/oframe/ogl/blob/master/src/math/Color.js | Source}
21 | */
22 | export class Color extends Array {
23 | constructor(color?: ColorRepresentation, g?: number, b?: number);
24 |
25 | get r(): number;
26 |
27 | get g(): number;
28 |
29 | get b(): number;
30 |
31 | set r(v: number);
32 |
33 | set g(v: number);
34 |
35 | set b(v: number);
36 |
37 | set(color?: ColorRepresentation, g?: number, b?: number): this;
38 |
39 | copy(v: Color): this;
40 | }
41 |
--------------------------------------------------------------------------------
/types/math/Euler.d.ts:
--------------------------------------------------------------------------------
1 | import { Mat4 } from './Mat4.js';
2 |
3 | import type { Quat } from './Quat.js';
4 | import type { AttributeData } from '../core/Geometry.js';
5 |
6 | export type EulerTuple = [x: number, y: number, z: number];
7 |
8 | export type EulerOrder = 'XYZ' | 'XZY' | 'YXZ' | 'YZX' | 'ZXY' | 'ZYX';
9 |
10 | /**
11 | * Implementation of {@link https://en.wikipedia.org/wiki/Euler_angles | Euler angles}.
12 | * @see {@link https://github.com/oframe/ogl/blob/master/src/math/Euler.js | Source}
13 | */
14 | export class Euler extends Array {
15 | order: EulerOrder;
16 | onChange: () => void;
17 |
18 | constructor(x?: number, y?: number, z?: number, order?: EulerOrder);
19 |
20 | get x(): number;
21 |
22 | get y(): number;
23 |
24 | get z(): number;
25 |
26 | set x(v: number);
27 |
28 | set y(v: number);
29 |
30 | set z(v: number);
31 |
32 | set(x: number | Euler | EulerTuple, y?: number, z?: number): this;
33 |
34 | copy(v: Euler): this;
35 |
36 | reorder(order: EulerOrder): this;
37 |
38 | fromRotationMatrix(m: Mat4, order?: EulerOrder): this;
39 |
40 | fromQuaternion(q: Quat, order?: EulerOrder): this;
41 |
42 | fromArray(a: number[] | AttributeData, o?: number): this;
43 |
44 | toArray(a?: T, o?: number): T;
45 | }
46 |
--------------------------------------------------------------------------------
/types/math/Mat3.d.ts:
--------------------------------------------------------------------------------
1 | import type { Mat4 } from './Mat4.js';
2 | import type { Quat } from './Quat.js';
3 | import type { Vec2 } from './Vec2.js';
4 | import type { Vec3 } from './Vec3.js';
5 |
6 | export type Mat3Tuple = [
7 | m00: number,
8 | m01: number,
9 | m02: number,
10 | m10: number,
11 | m11: number,
12 | m12: number,
13 | m20: number,
14 | m21: number,
15 | m22: number,
16 | ];
17 |
18 | /**
19 | * 3x3 matrix.
20 | * @see {@link https://github.com/oframe/ogl/blob/master/src/math/Mat3.js | Source}
21 | */
22 | export class Mat3 extends Array {
23 | constructor(
24 | m00?: number,
25 | m01?: number,
26 | m02?: number,
27 | m10?: number,
28 | m11?: number,
29 | m12?: number,
30 | m20?: number,
31 | m21?: number,
32 | m22?: number,
33 | );
34 |
35 | set(
36 | m00: number | Mat3 | Mat3Tuple,
37 | m01: number,
38 | m02: number,
39 | m10: number,
40 | m11: number,
41 | m12: number,
42 | m20: number,
43 | m21: number,
44 | m22: number,
45 | ): this;
46 |
47 | translate(v: Vec2, m?: Mat3): this;
48 |
49 | rotate(v: number, m?: Mat3): this;
50 |
51 | scale(v: Vec2, m?: Mat3): this;
52 |
53 | multiply(ma: Mat3, mb?: Mat3): this;
54 |
55 | identity(): this;
56 |
57 | copy(m: Mat3): this;
58 |
59 | fromMatrix4(m: Mat4): this;
60 |
61 | fromQuaternion(q: Quat): this;
62 |
63 | fromBasis(vec3a: Vec3, vec3b: Vec3, vec3c: Vec3): this;
64 |
65 | inverse(m?: Mat3): this;
66 |
67 | getNormalMatrix(m: Mat4): this;
68 | }
69 |
--------------------------------------------------------------------------------
/types/math/Mat4.d.ts:
--------------------------------------------------------------------------------
1 | import type { Quat } from './Quat.js';
2 | import type { Vec3 } from './Vec3.js';
3 | import type { AttributeData } from '../core/Geometry.js';
4 |
5 | export type Mat4Tuple = [
6 | m00: number,
7 | m01: number,
8 | m02: number,
9 | m03: number,
10 | m10: number,
11 | m11: number,
12 | m12: number,
13 | m13: number,
14 | m20: number,
15 | m21: number,
16 | m22: number,
17 | m23: number,
18 | m30: number,
19 | m31: number,
20 | m32: number,
21 | m33: number,
22 | ];
23 |
24 | /**
25 | * 4x4 matrix.
26 | * @see {@link https://github.com/oframe/ogl/blob/master/src/math/Mat4.js | Source}
27 | */
28 | export class Mat4 extends Array {
29 | constructor(
30 | m00?: number,
31 | m01?: number,
32 | m02?: number,
33 | m03?: number,
34 | m10?: number,
35 | m11?: number,
36 | m12?: number,
37 | m13?: number,
38 | m20?: number,
39 | m21?: number,
40 | m22?: number,
41 | m23?: number,
42 | m30?: number,
43 | m31?: number,
44 | m32?: number,
45 | m33?: number,
46 | );
47 |
48 | get x(): number;
49 |
50 | get y(): number;
51 |
52 | get z(): number;
53 |
54 | get w(): number;
55 |
56 | set x(v: number);
57 |
58 | set y(v: number);
59 |
60 | set z(v: number);
61 |
62 | set w(v: number);
63 |
64 | set(
65 | m00: number | Mat4 | Mat4Tuple,
66 | m01: number,
67 | m02: number,
68 | m03: number,
69 | m10: number,
70 | m11: number,
71 | m12: number,
72 | m13: number,
73 | m20: number,
74 | m21: number,
75 | m22: number,
76 | m23: number,
77 | m30: number,
78 | m31: number,
79 | m32: number,
80 | m33: number,
81 | ): this;
82 |
83 | translate(v: Vec3, m?: Mat4): this;
84 |
85 | rotate(v: number, axis: Vec3, m?: Mat4): this;
86 |
87 | scale(v: Vec3 | number, m?: Mat4): this;
88 |
89 | add(ma: Mat4, mb?: Mat4): this;
90 |
91 | sub(ma: Mat4, mb?: Mat4): this;
92 |
93 | multiply(ma: Mat4 | number, mb?: Mat4): this;
94 |
95 | identity(): this;
96 |
97 | copy(m: Mat4): this;
98 |
99 | fromPerspective(options: { fov: number; aspect: number; near: number; far: number }): this;
100 |
101 | fromOrthogonal(options: { left: number; right: number; bottom: number; top: number; near: number; far: number }): this;
102 |
103 | fromQuaternion(q: Quat): this;
104 |
105 | setPosition(v: Vec3): this;
106 |
107 | inverse(m?: Mat4): this;
108 |
109 | compose(q: Quat, pos: Vec3, scale: Vec3): this;
110 |
111 | getRotation(q: Quat): this;
112 |
113 | getTranslation(pos: Vec3): this;
114 |
115 | getScaling(scale: Vec3): this;
116 |
117 | getMaxScaleOnAxis(): number;
118 |
119 | lookAt(eye: Vec3, target: Vec3, up: Vec3): this;
120 |
121 | determinant(): number;
122 |
123 | fromArray(a: number[] | AttributeData, o?: number): this;
124 |
125 | toArray(a?: T, o?: number): T;
126 | }
127 |
--------------------------------------------------------------------------------
/types/math/Quat.d.ts:
--------------------------------------------------------------------------------
1 | import type { Euler } from './Euler.js';
2 | import type { Mat3 } from './Mat3.js';
3 | import type { Vec3 } from './Vec3.js';
4 | import type { AttributeData } from '../core/Geometry.js';
5 |
6 | export type QuatTuple = [x: number, y: number, z: number, w: number];
7 |
8 | /**
9 | * Implementation of a quaternion.
10 | * @see {@link https://github.com/oframe/ogl/blob/master/src/math/Quat.js | Source}
11 | */
12 | export class Quat extends Array {
13 | onChange: () => void;
14 |
15 | constructor(x?: number, y?: number, z?: number, w?: number);
16 |
17 | get x(): number;
18 |
19 | get y(): number;
20 |
21 | get z(): number;
22 |
23 | get w(): number;
24 |
25 | set x(v: number);
26 |
27 | set y(v: number);
28 |
29 | set z(v: number);
30 |
31 | set w(v: number);
32 |
33 | identity(): this;
34 |
35 | set(x: number | Quat | QuatTuple, y: number, z: number, w: number): this;
36 |
37 | rotateX(a: number): this;
38 |
39 | rotateY(a: number): this;
40 |
41 | rotateZ(a: number): this;
42 |
43 | inverse(q?: Quat): this;
44 |
45 | conjugate(q?: Quat): this;
46 |
47 | copy(q: Quat): this;
48 |
49 | normalize(q?: Quat): this;
50 |
51 | multiply(qA: Quat, qB?: Quat): this;
52 |
53 | dot(v: Quat): number;
54 |
55 | fromMatrix3(matrix3: Mat3): this;
56 |
57 | fromEuler(euler: Euler): this;
58 |
59 | fromAxisAngle(axis: Vec3, a: number): this;
60 |
61 | slerp(q: Quat, t: number): this;
62 |
63 | fromArray(a: number[] | AttributeData, o?: number): this;
64 |
65 | toArray(a?: T, o?: number): T;
66 | }
67 |
--------------------------------------------------------------------------------
/types/math/Vec2.d.ts:
--------------------------------------------------------------------------------
1 | import type { Mat3 } from './Mat3.js';
2 | import type { Mat4 } from './Mat4.js';
3 | import type { AttributeData } from '../core/Geometry.js';
4 |
5 | export type Vec2Tuple = [x: number, y: number];
6 |
7 | /**
8 | * 2D vector.
9 | * @see {@link https://github.com/oframe/ogl/blob/master/src/math/Vec2.js | Source}
10 | */
11 | export class Vec2 extends Array {
12 | constructor(x?: number, y?: number);
13 |
14 | get x(): number;
15 |
16 | get y(): number;
17 |
18 | set x(v: number);
19 |
20 | set y(v: number);
21 |
22 | set(x: number | Vec2 | Vec2Tuple, y?: number): this;
23 |
24 | copy(v: Vec2): this;
25 |
26 | add(va: Vec2, vb?: Vec2): this;
27 |
28 | sub(va: Vec2, vb?: Vec2): this;
29 |
30 | multiply(v: Vec2 | number): this;
31 |
32 | divide(v: Vec2 | number): this;
33 |
34 | inverse(v?: Vec2): this;
35 |
36 | len(): number;
37 |
38 | distance(v?: Vec2): number;
39 |
40 | squaredLen(): number;
41 |
42 | squaredDistance(v?: Vec2): number;
43 |
44 | negate(v?: Vec2): this;
45 |
46 | cross(va: Vec2, vb?: Vec2): number;
47 |
48 | scale(v: number): this;
49 |
50 | normalize(): this;
51 |
52 | dot(v: Vec2): number;
53 |
54 | equals(v: Vec2): boolean;
55 |
56 | applyMatrix3(mat3: Mat3): this;
57 |
58 | applyMatrix4(mat4: Mat4): this;
59 |
60 | lerp(v: Vec2, a: number): this;
61 |
62 | smoothLerp(v: Vec2, decay: number, dt: number): this;
63 |
64 | clone(): Vec2;
65 |
66 | fromArray(a: number[] | AttributeData, o?: number): this;
67 |
68 | toArray(a?: T, o?: number): T;
69 | }
70 |
--------------------------------------------------------------------------------
/types/math/Vec3.d.ts:
--------------------------------------------------------------------------------
1 | import type { Mat3 } from './Mat3.js';
2 | import type { Mat4 } from './Mat4.js';
3 | import type { Quat } from './Quat.js';
4 | import type { AttributeData } from '../core/Geometry.js';
5 |
6 | export type Vec3Tuple = [x: number, y: number, z: number];
7 |
8 | /**
9 | * 3D vector.
10 | * @see {@link https://github.com/oframe/ogl/blob/master/src/math/Vec3.js | Source}
11 | */
12 | export class Vec3 extends Array {
13 | constructor(x?: number, y?: number, z?: number);
14 |
15 | get x(): number;
16 |
17 | get y(): number;
18 |
19 | get z(): number;
20 |
21 | set x(v: number);
22 |
23 | set y(v: number);
24 |
25 | set z(v: number);
26 |
27 | set(x: number | Vec3 | Vec3Tuple, y?: number, z?: number): this;
28 |
29 | copy(v: Vec3): this;
30 |
31 | add(va: Vec3, vb?: Vec3): this;
32 |
33 | sub(va: Vec3, vb?: Vec3): this;
34 |
35 | multiply(v: Vec3 | number): this;
36 |
37 | divide(v: Vec3 | number): this;
38 |
39 | inverse(v?: Vec3): this;
40 |
41 | len(): number;
42 |
43 | distance(v?: Vec3): number;
44 |
45 | squaredLen(): number;
46 |
47 | squaredDistance(v?: Vec3): number;
48 |
49 | negate(v?: Vec3): this;
50 |
51 | cross(va: Vec3, vb?: Vec3): this;
52 |
53 | scale(v: number): this;
54 |
55 | normalize(): this;
56 |
57 | dot(v: Vec3): number;
58 |
59 | equals(v: Vec3): boolean;
60 |
61 | applyMatrix3(mat3: Mat3): this;
62 |
63 | applyMatrix4(mat4: Mat4): this;
64 |
65 | scaleRotateMatrix4(mat4: Mat4): this;
66 |
67 | applyQuaternion(q: Quat): this;
68 |
69 | angle(v: Vec3): number;
70 |
71 | lerp(v: Vec3, t: number): this;
72 |
73 | smoothLerp(v: Vec3, decay: number, dt: number): this;
74 |
75 | clone(): Vec3;
76 |
77 | fromArray(a: number[] | AttributeData, o?: number): this;
78 |
79 | toArray(a?: T, o?: number): T;
80 |
81 | transformDirection(mat4: Mat4): this;
82 | }
83 |
--------------------------------------------------------------------------------
/types/math/Vec4.d.ts:
--------------------------------------------------------------------------------
1 | import type { AttributeData } from '../core/Geometry';
2 |
3 | export type Vec4Tuple = [x: number, y: number, z: number, w: number];
4 |
5 | /**
6 | * 4D vector.
7 | * @see {@link https://github.com/oframe/ogl/blob/master/src/math/Vec4.js | Source}
8 | */
9 | export class Vec4 extends Array {
10 | constructor(x?: number, y?: number, z?: number, w?: number);
11 |
12 | get x(): number;
13 |
14 | get y(): number;
15 |
16 | get z(): number;
17 |
18 | get w(): number;
19 |
20 | set x(v: number);
21 |
22 | set y(v: number);
23 |
24 | set z(v: number);
25 |
26 | set w(v: number);
27 |
28 | set(x: number | Vec4 | Vec4Tuple, y?: number, z?: number, w?: number): this;
29 |
30 | copy(v: Vec4): this;
31 |
32 | normalize(): this;
33 |
34 | multiply(v: number): this;
35 |
36 | dot(v: Vec4): number;
37 |
38 | fromArray(a: number[] | AttributeData, o?: number): this;
39 |
40 | toArray(a?: T, o?: number): T;
41 | }
42 |
--------------------------------------------------------------------------------