@kitware/vtk.js 32.6.1 → 32.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Common/Core/Math/index.js +1 -1
- package/Common/Core/Math.js +1 -1
- package/IO/Geometry/GLTFImporter/Animations.js +239 -0
- package/IO/Geometry/GLTFImporter/Constants.js +87 -0
- package/IO/Geometry/GLTFImporter/Decoder.js +69 -0
- package/IO/Geometry/GLTFImporter/Extensions.js +110 -0
- package/IO/Geometry/GLTFImporter/ORMTexture.worker.js +42 -0
- package/IO/Geometry/GLTFImporter/Parser.js +359 -0
- package/IO/Geometry/GLTFImporter/Reader.js +507 -0
- package/IO/Geometry/GLTFImporter/Utils.js +165 -0
- package/IO/Geometry/GLTFImporter.d.ts +266 -0
- package/IO/Geometry/GLTFImporter.js +245 -0
- package/IO/Geometry.js +3 -1
- package/IO/Image/HDRReader/Utils.js +1 -1
- package/IO/Image/HDRReader.js +1 -1
- package/Interaction/Manipulators/MouseCameraTrackballRollManipulator.js +1 -1
- package/Interaction/Style/InteractorStyleTrackballCamera.js +1 -1
- package/Rendering/Core/ImageProperty.d.ts +22 -0
- package/Rendering/Core/Prop3D.js +1 -1
- package/Rendering/Core/RenderWindowInteractor.js +1 -1
- package/_virtual/rollup-plugin-worker-loader__module_Sources/IO/Geometry/GLTFImporter/ORMTexture.worker.js +296 -0
- package/index.d.ts +1 -0
- package/package.json +1 -1
|
@@ -2256,4 +2256,4 @@ var vtkMath$1 = /*#__PURE__*/Object.freeze({
|
|
|
2256
2256
|
'default': vtkMath
|
|
2257
2257
|
});
|
|
2258
2258
|
|
|
2259
|
-
export { min as $,
|
|
2259
|
+
export { min as $, degreesFromRadians as A, ldexp as B, xyz2rgb as C, areEquals as D, clampValue as E, arrayRange as F, getMajorAxisIndex as G, createUninitializedBounds as H, identity as I, multiplyMatrix as J, floor as K, isInf as L, rgb2hsv as M, rgb2lab as N, lab2rgb as O, round as P, normalize2D as Q, nearestPowerOfTwo as R, multiply3x3_vect3 as S, getSparseOrthogonalMatrix as T, areBoundsInitialized as U, isPowerOfTwo as V, angleBetweenVectors as W, signedAngleBetweenVectors as X, createArray as Y, Pi as Z, ceil as _, areMatricesEqual as a, floatRGB2HexCode as a$, max as a0, arrayMin as a1, arrayMax as a2, ceilLog2 as a3, factorial as a4, binomial as a5, beginCombination as a6, nextCombination as a7, randomSeed as a8, getSeed as a9, multiplyQuaternion as aA, orthogonalize3x3 as aB, diagonalize3x3 as aC, singularValueDecomposition3x3 as aD, luFactorLinearSystem as aE, luSolveLinearSystem as aF, invertMatrix as aG, estimateMatrixCondition as aH, solveHomogeneousLeastSquares as aI, solveLeastSquares as aJ, hex2float as aK, lab2xyz as aL, xyz2lab as aM, rgb2xyz as aN, computeBoundsFromPoints as aO, clampAndNormalizeValue as aP, getScalarTypeFittingRange as aQ, getAdjustedScalarRange as aR, extentIsWithinOtherExtent as aS, boundsIsWithinOtherBounds as aT, pointIsWithinBounds as aU, solve3PointCircle as aV, inf as aW, negInf as aX, isFinite as aY, isNaN as aZ, floatToHex2 as a_, gaussian as aa, multiplyScalar2D as ab, multiplyAccumulate2D as ac, outer as ad, projectVector as ae, dot2D as af, projectVector2D as ag, gaussianAmplitude as ah, gaussianWeight as ai, outer2D as aj, norm2D as ak, rowsToMat4 as al, columnsToMat4 as am, columnsToMat3 as an, LUFactor3x3 as ao, LUSolve3x3 as ap, linearSolve3x3 as aq, multiply3x3_mat3 as ar, transpose3x3 as as, invert3x3 as at, identity3x3 as au, isIdentity as av, isIdentity3x3 as aw, quaternionToMatrix3x3 as ax, roundNumber as ay, matrix3x3ToQuaternion as az, roundVector as b, float2CssRGBA as b0, clampVector as c, dot as d, distance2BetweenPoints as e, vtkMath as f, solveLinearSystem as g, hsv2rgb as h, isNan as i, cross as j, add as k, normalize as l, multiplyAccumulate as m, norm as n, determinant2x2 as o, jacobiN as p, perpendiculars as q, radiansFromDegrees as r, subtract as s, jacobi as t, uninitializeBounds as u, vtkMath$1 as v, multiplyScalar as w, random as x, determinant3x3 as y, rowsToMat3 as z };
|
package/Common/Core/Math.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import 'seedrandom';
|
|
2
2
|
import '../../macros2.js';
|
|
3
3
|
import './Math/Constants.js';
|
|
4
|
-
export { ao as LUFactor3x3, ap as LUSolve3x3, Z as Pi, k as add, W as angleBetweenVectors, U as areBoundsInitialized, D as areEquals, a as areMatricesEqual, a2 as arrayMax, a1 as arrayMin, F as arrayRange, a6 as beginCombination, a5 as binomial, aT as boundsIsWithinOtherBounds, _ as ceil, a3 as ceilLog2, aP as clampAndNormalizeValue, E as clampValue, c as clampVector, an as columnsToMat3, am as columnsToMat4, aO as computeBoundsFromPoints, Y as createArray, H as createUninitializedBounds, j as cross, f as default,
|
|
4
|
+
export { ao as LUFactor3x3, ap as LUSolve3x3, Z as Pi, k as add, W as angleBetweenVectors, U as areBoundsInitialized, D as areEquals, a as areMatricesEqual, a2 as arrayMax, a1 as arrayMin, F as arrayRange, a6 as beginCombination, a5 as binomial, aT as boundsIsWithinOtherBounds, _ as ceil, a3 as ceilLog2, aP as clampAndNormalizeValue, E as clampValue, c as clampVector, an as columnsToMat3, am as columnsToMat4, aO as computeBoundsFromPoints, Y as createArray, H as createUninitializedBounds, j as cross, f as default, A as degreesFromRadians, o as determinant2x2, y as determinant3x3, aC as diagonalize3x3, e as distance2BetweenPoints, d as dot, af as dot2D, aH as estimateMatrixCondition, aS as extentIsWithinOtherExtent, a4 as factorial, b0 as float2CssRGBA, a$ as floatRGB2HexCode, a_ as floatToHex2, K as floor, aa as gaussian, ah as gaussianAmplitude, ai as gaussianWeight, aR as getAdjustedScalarRange, G as getMajorAxisIndex, aQ as getScalarTypeFittingRange, a9 as getSeed, T as getSparseOrthogonalMatrix, aK as hex2float, h as hsv2rgb, I as identity, au as identity3x3, aW as inf, at as invert3x3, aG as invertMatrix, aY as isFinite, av as isIdentity, aw as isIdentity3x3, L as isInf, aZ as isNaN, i as isNan, V as isPowerOfTwo, t as jacobi, p as jacobiN, O as lab2rgb, aL as lab2xyz, B as ldexp, aq as linearSolve3x3, aE as luFactorLinearSystem, aF as luSolveLinearSystem, az as matrix3x3ToQuaternion, a0 as max, $ as min, ar as multiply3x3_mat3, S as multiply3x3_vect3, m as multiplyAccumulate, ac as multiplyAccumulate2D, J as multiplyMatrix, aA as multiplyQuaternion, w as multiplyScalar, ab as multiplyScalar2D, R as nearestPowerOfTwo, aX as negInf, a7 as nextCombination, n as norm, ak as norm2D, l as normalize, Q as normalize2D, aB as orthogonalize3x3, ad as outer, aj as outer2D, q as perpendiculars, aU as pointIsWithinBounds, ae as projectVector, ag as projectVector2D, ax as quaternionToMatrix3x3, r as radiansFromDegrees, x as random, a8 as randomSeed, M as rgb2hsv, N as rgb2lab, aN as rgb2xyz, P as round, ay as roundNumber, b as roundVector, z as rowsToMat3, al as rowsToMat4, X as signedAngleBetweenVectors, aD as singularValueDecomposition3x3, aV as solve3PointCircle, aI as solveHomogeneousLeastSquares, aJ as solveLeastSquares, g as solveLinearSystem, s as subtract, as as transpose3x3, u as uninitializeBounds, aM as xyz2lab, C as xyz2rgb } from './Math/index.js';
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { m as macro } from '../../../macros2.js';
|
|
2
|
+
import { A as degreesFromRadians } from '../../../Common/Core/Math/index.js';
|
|
3
|
+
import { quat, vec3 } from 'gl-matrix';
|
|
4
|
+
|
|
5
|
+
const {
|
|
6
|
+
vtkDebugMacro,
|
|
7
|
+
vtkWarningMacro
|
|
8
|
+
} = macro;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Create an animation channel
|
|
12
|
+
* @param {glTFChannel} glTFChannel
|
|
13
|
+
* @param {glTFChannel[]} glTFSamplers
|
|
14
|
+
* @returns
|
|
15
|
+
*/
|
|
16
|
+
function createAnimationChannel(glTFChannel, glTFSamplers) {
|
|
17
|
+
const path = glTFChannel.target.path;
|
|
18
|
+
const node = glTFChannel.target.node;
|
|
19
|
+
function applyAnimation(value) {
|
|
20
|
+
let axisAngle;
|
|
21
|
+
let w;
|
|
22
|
+
let nq;
|
|
23
|
+
switch (path) {
|
|
24
|
+
case 'translation':
|
|
25
|
+
node.setPosition(value[0], value[1], value[2]);
|
|
26
|
+
break;
|
|
27
|
+
case 'rotation':
|
|
28
|
+
// Convert quaternion to axis-angle representation
|
|
29
|
+
nq = quat.normalize(quat.create(), value);
|
|
30
|
+
axisAngle = new Float64Array(3);
|
|
31
|
+
w = quat.getAxisAngle(axisAngle, nq);
|
|
32
|
+
// Apply rotation using rotateWXYZ
|
|
33
|
+
node.rotateWXYZ(degreesFromRadians(w), axisAngle[0], axisAngle[1], axisAngle[2]);
|
|
34
|
+
break;
|
|
35
|
+
case 'scale':
|
|
36
|
+
node.setScale(value[0], value[1], value[2]);
|
|
37
|
+
break;
|
|
38
|
+
default:
|
|
39
|
+
vtkWarningMacro(`Unsupported animation path: ${path}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function animate(currentTime) {
|
|
43
|
+
const sampler = glTFSamplers[glTFChannel.sampler];
|
|
44
|
+
const value = sampler.evaluate(currentTime, path);
|
|
45
|
+
applyAnimation(value);
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
...glTFChannel,
|
|
49
|
+
animate
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Create an animation sampler
|
|
55
|
+
* @param {glTFSampler} glTFSampler
|
|
56
|
+
* @returns
|
|
57
|
+
*/
|
|
58
|
+
function createAnimationSampler(glTFSampler) {
|
|
59
|
+
let lastKeyframeIndex = 0;
|
|
60
|
+
function findKeyframes(time) {
|
|
61
|
+
let i1 = lastKeyframeIndex;
|
|
62
|
+
while (i1 < glTFSampler.input.length - 1 && glTFSampler.input[i1] <= time) {
|
|
63
|
+
i1++;
|
|
64
|
+
}
|
|
65
|
+
const i0 = Math.max(0, i1 - 1);
|
|
66
|
+
lastKeyframeIndex = i0;
|
|
67
|
+
return [glTFSampler.input[i0], glTFSampler.input[i1], i0, i1];
|
|
68
|
+
}
|
|
69
|
+
function stepInterpolate(path, i0) {
|
|
70
|
+
const startIndex = i0 * 3;
|
|
71
|
+
const v0 = new Array(3);
|
|
72
|
+
for (let i = 0; i < 3; ++i) {
|
|
73
|
+
v0[i] = glTFSampler.output[startIndex + i];
|
|
74
|
+
}
|
|
75
|
+
return v0;
|
|
76
|
+
}
|
|
77
|
+
function linearInterpolate(path, t0, t1, i0, i1, t) {
|
|
78
|
+
const ratio = (t - t0) / (t1 - t0);
|
|
79
|
+
const startIndex = i0 * 4;
|
|
80
|
+
const endIndex = i1 * 4;
|
|
81
|
+
const v0 = new Array(4);
|
|
82
|
+
const v1 = new Array(4);
|
|
83
|
+
for (let i = 0; i < 4; ++i) {
|
|
84
|
+
v0[i] = glTFSampler.output[startIndex + i];
|
|
85
|
+
v1[i] = glTFSampler.output[endIndex + i];
|
|
86
|
+
}
|
|
87
|
+
switch (path) {
|
|
88
|
+
case 'translation':
|
|
89
|
+
case 'scale':
|
|
90
|
+
return vec3.lerp(vec3.create(), v0, v1, ratio);
|
|
91
|
+
case 'rotation':
|
|
92
|
+
return quat.slerp(quat.create(), v0, v1, ratio);
|
|
93
|
+
default:
|
|
94
|
+
vtkWarningMacro(`Unsupported animation path: ${path}`);
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function cubicSplineInterpolate(path, t0, t1, i0, i1, time) {
|
|
99
|
+
const dt = t1 - t0;
|
|
100
|
+
const t = (time - t0) / dt;
|
|
101
|
+
const t2 = t * t;
|
|
102
|
+
const t3 = t2 * t;
|
|
103
|
+
const p0 = glTFSampler.output[i0 * 3 + 1];
|
|
104
|
+
const m0 = dt * glTFSampler.output[i0 * 3 + 2];
|
|
105
|
+
const p1 = glTFSampler.output[i1 * 3 + 1];
|
|
106
|
+
const m1 = dt * glTFSampler.output[i1 * 3];
|
|
107
|
+
if (Array.isArray(p0)) {
|
|
108
|
+
return p0.map((v, j) => {
|
|
109
|
+
const a = 2 * t3 - 3 * t2 + 1;
|
|
110
|
+
const b = t3 - 2 * t2 + t;
|
|
111
|
+
const c = -2 * t3 + 3 * t2;
|
|
112
|
+
const d = t3 - t2;
|
|
113
|
+
return a * v + b * m0[j] + c * p1[j] + d * m1[j];
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
const a = 2 * t3 - 3 * t2 + 1;
|
|
117
|
+
const b = t3 - 2 * t2 + t;
|
|
118
|
+
const c = -2 * t3 + 3 * t2;
|
|
119
|
+
const d = t3 - t2;
|
|
120
|
+
return a * p0 + b * m0 + c * p1 + d * m1;
|
|
121
|
+
}
|
|
122
|
+
function evaluate(time, path) {
|
|
123
|
+
const [t0, t1, i0, i1] = findKeyframes(time);
|
|
124
|
+
let result;
|
|
125
|
+
switch (glTFSampler.interpolation) {
|
|
126
|
+
case 'STEP':
|
|
127
|
+
result = stepInterpolate(path, i0);
|
|
128
|
+
break;
|
|
129
|
+
case 'LINEAR':
|
|
130
|
+
result = linearInterpolate(path, t0, t1, i0, i1, time);
|
|
131
|
+
break;
|
|
132
|
+
case 'CUBICSPLINE':
|
|
133
|
+
result = cubicSplineInterpolate(path, t0, t1, i0, i1, time);
|
|
134
|
+
break;
|
|
135
|
+
default:
|
|
136
|
+
throw new Error(`Unknown interpolation method: ${glTFSampler.interpolation}`);
|
|
137
|
+
}
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
...glTFSampler,
|
|
142
|
+
evaluate
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Create an animation
|
|
148
|
+
* @param {glTFAnimation} glTFAnimation
|
|
149
|
+
* @param {Map} nodes
|
|
150
|
+
* @returns
|
|
151
|
+
*/
|
|
152
|
+
function createAnimation(glTFAnimation, nodes) {
|
|
153
|
+
glTFAnimation.samplers = glTFAnimation.samplers.map(sampler => createAnimationSampler(sampler));
|
|
154
|
+
glTFAnimation.channels = glTFAnimation.channels.map(channel => {
|
|
155
|
+
channel.target.node = nodes.get(`node-${channel.target.node}`);
|
|
156
|
+
return createAnimationChannel(channel, glTFAnimation.samplers);
|
|
157
|
+
});
|
|
158
|
+
function update(currentTime) {
|
|
159
|
+
glTFAnimation.channels.forEach(channel => channel.animate(currentTime));
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
...glTFAnimation,
|
|
163
|
+
update
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Create an animation mixer
|
|
169
|
+
* @param {Map} nodes
|
|
170
|
+
* @param {*} accessors
|
|
171
|
+
* @returns
|
|
172
|
+
*/
|
|
173
|
+
function createAnimationMixer(nodes, accessors) {
|
|
174
|
+
const animations = new Map();
|
|
175
|
+
const activeAnimations = new Map();
|
|
176
|
+
function addAnimation(glTFAnimation) {
|
|
177
|
+
const annimation = createAnimation(glTFAnimation, nodes);
|
|
178
|
+
animations.set(glTFAnimation.id, annimation);
|
|
179
|
+
vtkDebugMacro(`Animation "${glTFAnimation.id}" added to mixer`);
|
|
180
|
+
}
|
|
181
|
+
function play(name) {
|
|
182
|
+
let weight = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
|
|
183
|
+
if (!animations.has(name)) {
|
|
184
|
+
vtkWarningMacro(`Animation "${name}" not found in mixer`);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
activeAnimations.set(name, {
|
|
188
|
+
animation: animations.get(name),
|
|
189
|
+
weight,
|
|
190
|
+
time: 0
|
|
191
|
+
});
|
|
192
|
+
vtkDebugMacro(`Playing animation "${name}" with weight ${weight}`);
|
|
193
|
+
}
|
|
194
|
+
function stop(name) {
|
|
195
|
+
if (activeAnimations.delete(name)) {
|
|
196
|
+
vtkWarningMacro(`Stopped animation "${name}"`);
|
|
197
|
+
} else {
|
|
198
|
+
vtkWarningMacro(`Animation "${name}" was not playing`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
function stopAll() {
|
|
202
|
+
activeAnimations.clear();
|
|
203
|
+
vtkWarningMacro('Stopped all animations');
|
|
204
|
+
}
|
|
205
|
+
function update(deltaTime) {
|
|
206
|
+
// Normalize weights
|
|
207
|
+
const totalWeight = Array.from(activeAnimations.values()).reduce((sum, _ref) => {
|
|
208
|
+
let {
|
|
209
|
+
weight
|
|
210
|
+
} = _ref;
|
|
211
|
+
return sum + weight;
|
|
212
|
+
}, 0);
|
|
213
|
+
activeAnimations.forEach((_ref2, name) => {
|
|
214
|
+
let {
|
|
215
|
+
animation,
|
|
216
|
+
weight,
|
|
217
|
+
time
|
|
218
|
+
} = _ref2;
|
|
219
|
+
const normalizedWeight = totalWeight > 0 ? weight / totalWeight : 0;
|
|
220
|
+
const newTime = time + deltaTime;
|
|
221
|
+
activeAnimations.set(name, {
|
|
222
|
+
animation,
|
|
223
|
+
weight,
|
|
224
|
+
time: newTime
|
|
225
|
+
});
|
|
226
|
+
vtkDebugMacro(`Updating animation "${name}" at time ${newTime.toFixed(3)} with normalized weight ${normalizedWeight.toFixed(3)}`);
|
|
227
|
+
animation.update(newTime, normalizedWeight);
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
return {
|
|
231
|
+
addAnimation,
|
|
232
|
+
play,
|
|
233
|
+
stop,
|
|
234
|
+
stopAll,
|
|
235
|
+
update
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export { createAnimation, createAnimationChannel, createAnimationMixer, createAnimationSampler };
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
const BINARY_HEADER_MAGIC = 'glTF';
|
|
2
|
+
const BINARY_HEADER_LENGTH = 12;
|
|
3
|
+
const BINARY_CHUNK_TYPES = {
|
|
4
|
+
JSON: 0x4e4f534a,
|
|
5
|
+
BIN: 0x004e4942
|
|
6
|
+
};
|
|
7
|
+
const BINARY_HEADER_INTS = 3;
|
|
8
|
+
const BINARY_CHUNK_HEADER_INTS = 2;
|
|
9
|
+
const MIN_LIGHT_ATTENUATION = 0.01;
|
|
10
|
+
const COMPONENTS = {
|
|
11
|
+
SCALAR: 1,
|
|
12
|
+
VEC2: 2,
|
|
13
|
+
VEC3: 3,
|
|
14
|
+
VEC4: 4,
|
|
15
|
+
MAT2: 4,
|
|
16
|
+
MAT3: 9,
|
|
17
|
+
MAT4: 16
|
|
18
|
+
};
|
|
19
|
+
const BYTES = {
|
|
20
|
+
5120: 1,
|
|
21
|
+
// BYTE
|
|
22
|
+
5121: 1,
|
|
23
|
+
// UNSIGNED_BYTE
|
|
24
|
+
5122: 2,
|
|
25
|
+
// SHORT
|
|
26
|
+
5123: 2,
|
|
27
|
+
// UNSIGNED_SHORT
|
|
28
|
+
5125: 4,
|
|
29
|
+
// UNSIGNED_INT
|
|
30
|
+
5126: 4 // FLOAT
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const MODES = {
|
|
34
|
+
GL_POINTS: 0,
|
|
35
|
+
GL_LINES: 1,
|
|
36
|
+
GL_LINE_LOOP: 2,
|
|
37
|
+
GL_LINE_STRIP: 3,
|
|
38
|
+
GL_TRIANGLES: 4,
|
|
39
|
+
GL_TRIANGLE_STRIP: 5,
|
|
40
|
+
GL_TRIANGLE_FAN: 6
|
|
41
|
+
};
|
|
42
|
+
const ARRAY_TYPES = {
|
|
43
|
+
5120: Int8Array,
|
|
44
|
+
5121: Uint8Array,
|
|
45
|
+
5122: Int16Array,
|
|
46
|
+
5123: Uint16Array,
|
|
47
|
+
5125: Uint32Array,
|
|
48
|
+
5126: Float32Array
|
|
49
|
+
};
|
|
50
|
+
const GL_SAMPLER = {
|
|
51
|
+
NEAREST: 9728,
|
|
52
|
+
LINEAR: 9729,
|
|
53
|
+
NEAREST_MIPMAP_NEAREST: 9984,
|
|
54
|
+
LINEAR_MIPMAP_NEAREST: 9985,
|
|
55
|
+
NEAREST_MIPMAP_LINEAR: 9986,
|
|
56
|
+
LINEAR_MIPMAP_LINEAR: 9987,
|
|
57
|
+
REPEAT: 10497,
|
|
58
|
+
CLAMP_TO_EDGE: 33071,
|
|
59
|
+
MIRRORED_REPEAT: 33648,
|
|
60
|
+
TEXTURE_MAG_FILTER: 10240,
|
|
61
|
+
TEXTURE_MIN_FILTER: 10241,
|
|
62
|
+
TEXTURE_WRAP_S: 10242,
|
|
63
|
+
TEXTURE_WRAP_T: 10243
|
|
64
|
+
};
|
|
65
|
+
const DEFAULT_SAMPLER = {
|
|
66
|
+
magFilter: GL_SAMPLER.NEAREST,
|
|
67
|
+
minFilter: GL_SAMPLER.LINEAR_MIPMAP_LINEAR,
|
|
68
|
+
wrapS: GL_SAMPLER.REPEAT,
|
|
69
|
+
wrapT: GL_SAMPLER.REPEAT
|
|
70
|
+
};
|
|
71
|
+
const SEMANTIC_ATTRIBUTE_MAP = {
|
|
72
|
+
NORMAL: 'normal',
|
|
73
|
+
POSITION: 'position',
|
|
74
|
+
TEXCOORD_0: 'texcoord0',
|
|
75
|
+
TEXCOORD_1: 'texcoord1',
|
|
76
|
+
WEIGHTS_0: 'weight',
|
|
77
|
+
JOINTS_0: 'joint',
|
|
78
|
+
COLOR_0: 'color',
|
|
79
|
+
TANGENT: 'tangent'
|
|
80
|
+
};
|
|
81
|
+
const ALPHA_MODE = {
|
|
82
|
+
OPAQUE: 'OPAQUE',
|
|
83
|
+
MASK: 'MASK',
|
|
84
|
+
BLEND: 'BLEND'
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export { ALPHA_MODE, ARRAY_TYPES, BINARY_CHUNK_HEADER_INTS, BINARY_CHUNK_TYPES, BINARY_HEADER_INTS, BINARY_HEADER_LENGTH, BINARY_HEADER_MAGIC, BYTES, COMPONENTS, DEFAULT_SAMPLER, GL_SAMPLER, MIN_LIGHT_ATTENUATION, MODES, SEMANTIC_ATTRIBUTE_MAP };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import BinaryHelper from '../../Core/BinaryHelper.js';
|
|
2
|
+
import { BINARY_HEADER_MAGIC, BINARY_CHUNK_TYPES, BINARY_CHUNK_HEADER_INTS, BINARY_HEADER_LENGTH, BINARY_HEADER_INTS } from './Constants.js';
|
|
3
|
+
|
|
4
|
+
function getChunkInfo(headerStart, data) {
|
|
5
|
+
const header = new Uint32Array(data, headerStart, BINARY_CHUNK_HEADER_INTS);
|
|
6
|
+
const chunkStart = headerStart + BINARY_CHUNK_HEADER_INTS * 4;
|
|
7
|
+
const chunkLength = header[0];
|
|
8
|
+
const chunkType = header[1];
|
|
9
|
+
return {
|
|
10
|
+
start: chunkStart,
|
|
11
|
+
length: chunkLength,
|
|
12
|
+
type: chunkType
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function getAllChunkInfos(data) {
|
|
16
|
+
const infos = [];
|
|
17
|
+
let chunkStart = BINARY_HEADER_INTS * 4;
|
|
18
|
+
while (chunkStart < data.byteLength) {
|
|
19
|
+
const chunkInfo = getChunkInfo(chunkStart, data);
|
|
20
|
+
infos.push(chunkInfo);
|
|
21
|
+
chunkStart += chunkInfo.length + BINARY_CHUNK_HEADER_INTS * 4;
|
|
22
|
+
}
|
|
23
|
+
return infos;
|
|
24
|
+
}
|
|
25
|
+
function getJsonFromChunk(chunkInfo, data) {
|
|
26
|
+
const chunkLength = chunkInfo.length;
|
|
27
|
+
const jsonStart = (BINARY_HEADER_INTS + BINARY_CHUNK_HEADER_INTS) * 4;
|
|
28
|
+
const jsonSlice = new Uint8Array(data, jsonStart, chunkLength);
|
|
29
|
+
const stringBuffer = BinaryHelper.arrayBufferToString(jsonSlice);
|
|
30
|
+
return JSON.parse(stringBuffer);
|
|
31
|
+
}
|
|
32
|
+
function getBufferFromChunk(chunkInfo, data) {
|
|
33
|
+
return data.slice(chunkInfo.start, chunkInfo.start + chunkInfo.length);
|
|
34
|
+
}
|
|
35
|
+
function parseGLB(data) {
|
|
36
|
+
let json;
|
|
37
|
+
const buffers = [];
|
|
38
|
+
const headerView = new DataView(data, 0, BINARY_HEADER_LENGTH);
|
|
39
|
+
const header = {
|
|
40
|
+
magic: BinaryHelper.arrayBufferToString(new Uint8Array(data, 0, 4)),
|
|
41
|
+
version: headerView.getUint32(4, true),
|
|
42
|
+
length: headerView.getUint32(8, true)
|
|
43
|
+
};
|
|
44
|
+
if (header.magic !== BINARY_HEADER_MAGIC) {
|
|
45
|
+
throw new Error('Unsupported glTF-Binary header.');
|
|
46
|
+
} else if (header.version < 2.0) {
|
|
47
|
+
throw new Error('Unsupported legacy binary file detected.');
|
|
48
|
+
}
|
|
49
|
+
const chunkInfos = getAllChunkInfos(data);
|
|
50
|
+
chunkInfos.forEach(chunkInfo => {
|
|
51
|
+
if (chunkInfo.type === BINARY_CHUNK_TYPES.JSON && !json) {
|
|
52
|
+
json = getJsonFromChunk(chunkInfo, data);
|
|
53
|
+
} else if (chunkInfo.type === BINARY_CHUNK_TYPES.BIN) {
|
|
54
|
+
buffers.push(getBufferFromChunk(chunkInfo, data));
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
if (!json) {
|
|
58
|
+
throw new Error('glTF-Binary: JSON content not found.');
|
|
59
|
+
}
|
|
60
|
+
if (!buffers) {
|
|
61
|
+
throw new Error('glTF-Binary: Binary chunk not found.');
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
json,
|
|
65
|
+
buffers
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export { parseGLB as default };
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { m as macro } from '../../../macros2.js';
|
|
2
|
+
import { r as radiansFromDegrees } from '../../../Common/Core/Math/index.js';
|
|
3
|
+
import vtkDracoReader from '../DracoReader.js';
|
|
4
|
+
import vtkLight from '../../../Rendering/Core/Light.js';
|
|
5
|
+
import { MIN_LIGHT_ATTENUATION } from './Constants.js';
|
|
6
|
+
|
|
7
|
+
const {
|
|
8
|
+
vtkWarningMacro
|
|
9
|
+
} = macro;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Handles the KHR_materials_unlit extension.
|
|
13
|
+
*
|
|
14
|
+
* @param {object} extension - The KHR_materials_unlit extension object.
|
|
15
|
+
* @param {vtkProperty} property - The vtkProperty instance to update.
|
|
16
|
+
*/
|
|
17
|
+
function handleKHRMaterialsUnlit(extension, property) {
|
|
18
|
+
property.setLighting(true);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Handles the KHR_materials_ior extension.
|
|
23
|
+
*
|
|
24
|
+
* @param {object} extension - The KHR_materials_unlit extension object.
|
|
25
|
+
* @param {vtkProperty} property - The vtkProperty instance to update.
|
|
26
|
+
*/
|
|
27
|
+
function handleKHRMaterialsIor(extension, property) {
|
|
28
|
+
property.setBaseIOR(extension.ior);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Handles the KHR_materials_specular extension.
|
|
33
|
+
* @param {object} extension - The KHR_materials_specular extension object.
|
|
34
|
+
* @param {vtkProperty} property - The vtkProperty instance to update.
|
|
35
|
+
*/
|
|
36
|
+
function handleKHRMaterialsSpecular(extension, property) {
|
|
37
|
+
property.setSpecular(extension.specularFactor);
|
|
38
|
+
property.setSpecularColor(extension.specularColorFactor);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Handles the KHR_lights_punctual extension.
|
|
43
|
+
*
|
|
44
|
+
* @param {object} extension - The KHR_lights_punctual extension object.
|
|
45
|
+
* @param {vtkRenderer} renderer - The vtkRenderer instance to add the light to.
|
|
46
|
+
*/
|
|
47
|
+
function handleKHRLightsPunctual(extension, transformMatrix, model) {
|
|
48
|
+
const {
|
|
49
|
+
light
|
|
50
|
+
} = extension;
|
|
51
|
+
const {
|
|
52
|
+
color,
|
|
53
|
+
intensity,
|
|
54
|
+
range,
|
|
55
|
+
spot,
|
|
56
|
+
type
|
|
57
|
+
} = light;
|
|
58
|
+
const l = vtkLight.newInstance({
|
|
59
|
+
color: color || [1, 1, 1],
|
|
60
|
+
intensity: intensity || 1.0
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Apply the global transform to the light
|
|
64
|
+
l.setTransformMatrix(transformMatrix);
|
|
65
|
+
|
|
66
|
+
// Handle range
|
|
67
|
+
if (range > 0) {
|
|
68
|
+
// Set quadratic values to get attenuation(range) ~= MIN_LIGHT_ATTENUATION
|
|
69
|
+
l.setAttenuationValues(1, 0, 1.0 / (range * range * MIN_LIGHT_ATTENUATION));
|
|
70
|
+
}
|
|
71
|
+
switch (type) {
|
|
72
|
+
case 'directional':
|
|
73
|
+
l.setPositional(false);
|
|
74
|
+
break;
|
|
75
|
+
case 'point':
|
|
76
|
+
l.setPositional(true);
|
|
77
|
+
l.setConeAngle(90);
|
|
78
|
+
break;
|
|
79
|
+
case 'spot':
|
|
80
|
+
l.setPositional(true);
|
|
81
|
+
l.setConeAngle(radiansFromDegrees(spot.outerConeAngle));
|
|
82
|
+
break;
|
|
83
|
+
default:
|
|
84
|
+
vtkWarningMacro(`Unsupported light type: ${type}`);
|
|
85
|
+
}
|
|
86
|
+
model.lights.set(light.name, l);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Handles the KHR_draco_mesh_compression extension.
|
|
91
|
+
*
|
|
92
|
+
* @param {object} extension - The KHR_draco_mesh_compression extension object.
|
|
93
|
+
*/
|
|
94
|
+
async function handleKHRDracoMeshCompression(extension) {
|
|
95
|
+
const reader = vtkDracoReader.newInstance();
|
|
96
|
+
reader.parse(extension.bufferView);
|
|
97
|
+
return reader.getOutputData();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Handles the KHR_materials_variants extension.
|
|
102
|
+
*
|
|
103
|
+
* @param {object} extension - The KHR_materials_variants extension object.
|
|
104
|
+
* @param {object} model - The model object to update with variant information.
|
|
105
|
+
*/
|
|
106
|
+
function handleKHRMaterialsVariants(extension, model) {
|
|
107
|
+
model.variants = extension.variants.map(v => v.name);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export { handleKHRDracoMeshCompression, handleKHRLightsPunctual, handleKHRMaterialsIor, handleKHRMaterialsSpecular, handleKHRMaterialsUnlit, handleKHRMaterialsVariants };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import registerWebworker from 'webworker-promise/lib/register';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param {ArrayBuffer} imageBuffer
|
|
6
|
+
* @param {string} mimeType
|
|
7
|
+
* @param {string} channel
|
|
8
|
+
* @returns {Promise<ImageData>}
|
|
9
|
+
*/
|
|
10
|
+
registerWebworker(async _ref => {
|
|
11
|
+
let {
|
|
12
|
+
imageBuffer,
|
|
13
|
+
mimeType,
|
|
14
|
+
channel
|
|
15
|
+
} = _ref;
|
|
16
|
+
const channelsMap = {
|
|
17
|
+
r: 0,
|
|
18
|
+
g: 1,
|
|
19
|
+
b: 2
|
|
20
|
+
};
|
|
21
|
+
const blob = new Blob([imageBuffer], {
|
|
22
|
+
type: mimeType
|
|
23
|
+
});
|
|
24
|
+
const img = await createImageBitmap(blob);
|
|
25
|
+
const canvas = new OffscreenCanvas(img.width, img.height);
|
|
26
|
+
const ctx = canvas.getContext('2d');
|
|
27
|
+
ctx.drawImage(img, 0, 0, img.width, img.height);
|
|
28
|
+
const bitmap = ctx.getImageData(0, 0, img.width, img.height);
|
|
29
|
+
if (channel) {
|
|
30
|
+
const idx = channelsMap[channel];
|
|
31
|
+
for (let i = 0; i < bitmap.data.length; i += 4) {
|
|
32
|
+
const channelValue = bitmap.data[i + idx];
|
|
33
|
+
bitmap.data[i] = channelValue; // red channel
|
|
34
|
+
bitmap.data[i + 1] = channelValue; // green channel
|
|
35
|
+
bitmap.data[i + 2] = channelValue; // blue channel
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
bitmap
|
|
41
|
+
};
|
|
42
|
+
});
|