@luma.gl/gltf 9.1.0-alpha.2 → 9.1.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/dist.dev.js CHANGED
@@ -51,6 +51,13 @@ var __exports__ = (() => {
51
51
  }
52
52
  });
53
53
 
54
+ // external-global-plugin:@luma.gl/shadertools
55
+ var require_shadertools = __commonJS({
56
+ "external-global-plugin:@luma.gl/shadertools"(exports, module) {
57
+ module.exports = globalThis.luma;
58
+ }
59
+ });
60
+
54
61
  // bundle.ts
55
62
  var bundle_exports = {};
56
63
  __export(bundle_exports, {
@@ -73,9 +80,9 @@ var __exports__ = (() => {
73
80
  bindings: {},
74
81
  uniforms: {
75
82
  // TODO: find better values?
76
- u_Camera: [0, 0, 0],
83
+ camera: [0, 0, 0],
77
84
  // Model should override
78
- u_MetallicRoughnessValues: [1, 1]
85
+ metallicRoughnessValues: [1, 1]
79
86
  // Default is 1 and 1
80
87
  },
81
88
  parameters: {},
@@ -85,15 +92,15 @@ var __exports__ = (() => {
85
92
  parsedMaterial.defines.USE_TEX_LOD = 1;
86
93
  const { imageBasedLightingEnvironment } = options;
87
94
  if (imageBasedLightingEnvironment) {
88
- parsedMaterial.bindings.u_DiffuseEnvSampler = imageBasedLightingEnvironment.diffuseEnvSampler.texture;
89
- parsedMaterial.bindings.u_SpecularEnvSampler = imageBasedLightingEnvironment.specularEnvSampler.texture;
90
- parsedMaterial.bindings.u_brdfLUT = imageBasedLightingEnvironment.brdfLutTexture.texture;
91
- parsedMaterial.uniforms.u_ScaleIBLAmbient = [1, 1];
95
+ parsedMaterial.bindings.pbr_diffuseEnvSampler = imageBasedLightingEnvironment.diffuseEnvSampler.texture;
96
+ parsedMaterial.bindings.pbr_specularEnvSampler = imageBasedLightingEnvironment.specularEnvSampler.texture;
97
+ parsedMaterial.bindings.pbr_BrdfLUT = imageBasedLightingEnvironment.brdfLutTexture.texture;
98
+ parsedMaterial.uniforms.scaleIBLAmbient = [1, 1];
92
99
  }
93
100
  if (options?.pbrDebug) {
94
101
  parsedMaterial.defines.PBR_DEBUG = 1;
95
- parsedMaterial.uniforms.u_ScaleDiffBaseMR = [0, 0, 0, 0];
96
- parsedMaterial.uniforms.u_ScaleFGDSpec = [0, 0, 0, 0];
102
+ parsedMaterial.uniforms.scaleDiffBaseMR = [0, 0, 0, 0];
103
+ parsedMaterial.uniforms.scaleFGDSpec = [0, 0, 0, 0];
97
104
  }
98
105
  if (attributes.NORMAL)
99
106
  parsedMaterial.defines.HAS_NORMALS = 1;
@@ -111,41 +118,47 @@ var __exports__ = (() => {
111
118
  return parsedMaterial;
112
119
  }
113
120
  function parseMaterial(device, material, parsedMaterial) {
114
- parsedMaterial.uniforms.pbr_uUnlit = Boolean(material.unlit);
121
+ parsedMaterial.uniforms.unlit = Boolean(material.unlit);
115
122
  if (material.pbrMetallicRoughness) {
116
123
  parsePbrMetallicRoughness(device, material.pbrMetallicRoughness, parsedMaterial);
117
124
  }
118
125
  if (material.normalTexture) {
119
- addTexture(device, material.normalTexture, "u_NormalSampler", "HAS_NORMALMAP", parsedMaterial);
126
+ addTexture(
127
+ device,
128
+ material.normalTexture,
129
+ "pbr_normalSampler",
130
+ "HAS_NORMALMAP",
131
+ parsedMaterial
132
+ );
120
133
  const { scale: scale4 = 1 } = material.normalTexture;
121
- parsedMaterial.uniforms.u_NormalScale = scale4;
134
+ parsedMaterial.uniforms.normalScale = scale4;
122
135
  }
123
136
  if (material.occlusionTexture) {
124
137
  addTexture(
125
138
  device,
126
139
  material.occlusionTexture,
127
- "u_OcclusionSampler",
140
+ "pbr_occlusionSampler",
128
141
  "HAS_OCCLUSIONMAP",
129
142
  parsedMaterial
130
143
  );
131
144
  const { strength = 1 } = material.occlusionTexture;
132
- parsedMaterial.uniforms.u_OcclusionStrength = strength;
145
+ parsedMaterial.uniforms.occlusionStrength = strength;
133
146
  }
134
147
  if (material.emissiveTexture) {
135
148
  addTexture(
136
149
  device,
137
150
  material.emissiveTexture,
138
- "u_EmissiveSampler",
151
+ "pbr_emissiveSampler",
139
152
  "HAS_EMISSIVEMAP",
140
153
  parsedMaterial
141
154
  );
142
- parsedMaterial.uniforms.u_EmissiveFactor = material.emissiveFactor || [0, 0, 0];
155
+ parsedMaterial.uniforms.emissiveFactor = material.emissiveFactor || [0, 0, 0];
143
156
  }
144
157
  switch (material.alphaMode) {
145
158
  case "MASK":
146
159
  const { alphaCutoff = 0.5 } = material;
147
160
  parsedMaterial.defines.ALPHA_CUTOFF = 1;
148
- parsedMaterial.uniforms.u_AlphaCutoff = alphaCutoff;
161
+ parsedMaterial.uniforms.alphaCutoff = alphaCutoff;
149
162
  break;
150
163
  case "BLEND":
151
164
  import_core.log.warn("glTF BLEND alphaMode might not work well because it requires mesh sorting")();
@@ -171,23 +184,23 @@ var __exports__ = (() => {
171
184
  addTexture(
172
185
  device,
173
186
  pbrMetallicRoughness.baseColorTexture,
174
- "u_BaseColorSampler",
187
+ "pbr_baseColorSampler",
175
188
  "HAS_BASECOLORMAP",
176
189
  parsedMaterial
177
190
  );
178
191
  }
179
- parsedMaterial.uniforms.u_BaseColorFactor = pbrMetallicRoughness.baseColorFactor || [1, 1, 1, 1];
192
+ parsedMaterial.uniforms.baseColorFactor = pbrMetallicRoughness.baseColorFactor || [1, 1, 1, 1];
180
193
  if (pbrMetallicRoughness.metallicRoughnessTexture) {
181
194
  addTexture(
182
195
  device,
183
196
  pbrMetallicRoughness.metallicRoughnessTexture,
184
- "u_MetallicRoughnessSampler",
197
+ "pbr_metallicRoughnessSampler",
185
198
  "HAS_METALROUGHNESSMAP",
186
199
  parsedMaterial
187
200
  );
188
201
  }
189
202
  const { metallicFactor = 1, roughnessFactor = 1 } = pbrMetallicRoughness;
190
- parsedMaterial.uniforms.u_MetallicRoughnessValues = [metallicFactor, roughnessFactor];
203
+ parsedMaterial.uniforms.metallicRoughnessValues = [metallicFactor, roughnessFactor];
191
204
  }
192
205
  function addTexture(device, gltfTexture, uniformName, define = null, parsedMaterial) {
193
206
  const parameters = gltfTexture?.texture?.sampler?.parameters || {};
@@ -264,7 +277,7 @@ var __exports__ = (() => {
264
277
  }
265
278
 
266
279
  // ../../node_modules/@loaders.gl/images/dist/lib/utils/version.js
267
- var VERSION = true ? "4.2.0-beta.2" : "latest";
280
+ var VERSION = true ? "4.2.1" : "latest";
268
281
 
269
282
  // ../../node_modules/@loaders.gl/images/dist/lib/category-api/image-type.js
270
283
  var parseImageNode = globalThis.loaders?.parseImageNode;
@@ -837,17 +850,11 @@ var __exports__ = (() => {
837
850
  printRowMajor: true,
838
851
  _cartographicRadians: false
839
852
  };
840
- globalThis.mathgl = globalThis.mathgl || {
841
- config: {
842
- ...DEFAULT_CONFIG
843
- }
844
- };
853
+ globalThis.mathgl = globalThis.mathgl || { config: { ...DEFAULT_CONFIG } };
845
854
  var config = globalThis.mathgl.config;
846
- function formatValue(value, {
847
- precision = config.precision
848
- } = {}) {
855
+ function formatValue(value, { precision = config.precision } = {}) {
849
856
  value = round(value);
850
- return "".concat(parseFloat(value.toPrecision(precision)));
857
+ return `${parseFloat(value.toPrecision(precision))}`;
851
858
  }
852
859
  function isArray(value) {
853
860
  return Array.isArray(value) || ArrayBuffer.isView(value) && !(value instanceof DataView);
@@ -891,28 +898,12 @@ var __exports__ = (() => {
891
898
  }
892
899
 
893
900
  // ../../node_modules/@math.gl/core/dist/classes/base/math-array.js
894
- function _extendableBuiltin(cls) {
895
- function ExtendableBuiltin() {
896
- var instance = Reflect.construct(cls, Array.from(arguments));
897
- Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
898
- return instance;
899
- }
900
- ExtendableBuiltin.prototype = Object.create(cls.prototype, {
901
- constructor: {
902
- value: cls,
903
- enumerable: false,
904
- writable: true,
905
- configurable: true
906
- }
907
- });
908
- if (Object.setPrototypeOf) {
909
- Object.setPrototypeOf(ExtendableBuiltin, cls);
910
- } else {
911
- ExtendableBuiltin.__proto__ = cls;
912
- }
913
- return ExtendableBuiltin;
914
- }
915
- var MathArray = class extends _extendableBuiltin(Array) {
901
+ var MathArray = class extends Array {
902
+ // Common methods
903
+ /**
904
+ * Clone the current object
905
+ * @returns a new copy of this object
906
+ */
916
907
  clone() {
917
908
  return new this.constructor().copy(this);
918
909
  }
@@ -932,7 +923,10 @@ var __exports__ = (() => {
932
923
  return targetObject;
933
924
  }
934
925
  from(arrayOrObject) {
935
- return Array.isArray(arrayOrObject) ? this.copy(arrayOrObject) : this.fromObject(arrayOrObject);
926
+ return Array.isArray(arrayOrObject) ? this.copy(arrayOrObject) : (
927
+ // @ts-ignore
928
+ this.fromObject(arrayOrObject)
929
+ );
936
930
  }
937
931
  to(arrayOrObject) {
938
932
  if (arrayOrObject === this) {
@@ -943,18 +937,20 @@ var __exports__ = (() => {
943
937
  toTarget(target) {
944
938
  return target ? this.to(target) : this;
945
939
  }
940
+ /** @deprecated */
946
941
  toFloat32Array() {
947
942
  return new Float32Array(this);
948
943
  }
949
944
  toString() {
950
945
  return this.formatString(config);
951
946
  }
947
+ /** Formats string according to options */
952
948
  formatString(opts) {
953
949
  let string = "";
954
950
  for (let i = 0; i < this.ELEMENTS; ++i) {
955
951
  string += (i > 0 ? ", " : "") + formatValue(this[i], opts);
956
952
  }
957
- return "".concat(opts.printTypes ? this.constructor.name : "", "[").concat(string, "]");
953
+ return `${opts.printTypes ? this.constructor.name : ""}[${string}]`;
958
954
  }
959
955
  equals(array) {
960
956
  if (!array || this.length !== array.length) {
@@ -978,6 +974,8 @@ var __exports__ = (() => {
978
974
  }
979
975
  return true;
980
976
  }
977
+ // Modifiers
978
+ /** Negates all values in this object */
981
979
  negate() {
982
980
  for (let i = 0; i < this.ELEMENTS; ++i) {
983
981
  this[i] = -this[i];
@@ -995,12 +993,14 @@ var __exports__ = (() => {
995
993
  }
996
994
  return this.check();
997
995
  }
996
+ /** Minimal */
998
997
  min(vector) {
999
998
  for (let i = 0; i < this.ELEMENTS; ++i) {
1000
999
  this[i] = Math.min(vector[i], this[i]);
1001
1000
  }
1002
1001
  return this.check();
1003
1002
  }
1003
+ /** Maximal */
1004
1004
  max(vector) {
1005
1005
  for (let i = 0; i < this.ELEMENTS; ++i) {
1006
1006
  this[i] = Math.max(vector[i], this[i]);
@@ -1041,18 +1041,25 @@ var __exports__ = (() => {
1041
1041
  }
1042
1042
  return this.check();
1043
1043
  }
1044
+ /**
1045
+ * Multiplies all elements by `scale`
1046
+ * Note: `Matrix4.multiplyByScalar` only scales its 3x3 "minor"
1047
+ */
1044
1048
  multiplyByScalar(scalar) {
1045
1049
  for (let i = 0; i < this.ELEMENTS; ++i) {
1046
1050
  this[i] *= scalar;
1047
1051
  }
1048
1052
  return this.check();
1049
1053
  }
1054
+ // Debug checks
1055
+ /** Throws an error if array length is incorrect or contains illegal values */
1050
1056
  check() {
1051
1057
  if (config.debug && !this.validate()) {
1052
- throw new Error("math.gl: ".concat(this.constructor.name, " some fields set to invalid numbers'"));
1058
+ throw new Error(`math.gl: ${this.constructor.name} some fields set to invalid numbers'`);
1053
1059
  }
1054
1060
  return this;
1055
1061
  }
1062
+ /** Returns false if the array length is incorrect or contains illegal values */
1056
1063
  validate() {
1057
1064
  let valid = this.length === this.ELEMENTS;
1058
1065
  for (let i = 0; i < this.ELEMENTS; ++i) {
@@ -1060,39 +1067,48 @@ var __exports__ = (() => {
1060
1067
  }
1061
1068
  return valid;
1062
1069
  }
1070
+ // three.js compatibility
1071
+ /** @deprecated */
1063
1072
  sub(a) {
1064
1073
  return this.subtract(a);
1065
1074
  }
1075
+ /** @deprecated */
1066
1076
  setScalar(a) {
1067
1077
  for (let i = 0; i < this.ELEMENTS; ++i) {
1068
1078
  this[i] = a;
1069
1079
  }
1070
1080
  return this.check();
1071
1081
  }
1082
+ /** @deprecated */
1072
1083
  addScalar(a) {
1073
1084
  for (let i = 0; i < this.ELEMENTS; ++i) {
1074
1085
  this[i] += a;
1075
1086
  }
1076
1087
  return this.check();
1077
1088
  }
1089
+ /** @deprecated */
1078
1090
  subScalar(a) {
1079
1091
  return this.addScalar(-a);
1080
1092
  }
1093
+ /** @deprecated */
1081
1094
  multiplyScalar(scalar) {
1082
1095
  for (let i = 0; i < this.ELEMENTS; ++i) {
1083
1096
  this[i] *= scalar;
1084
1097
  }
1085
1098
  return this.check();
1086
1099
  }
1100
+ /** @deprecated */
1087
1101
  divideScalar(a) {
1088
1102
  return this.multiplyByScalar(1 / a);
1089
1103
  }
1104
+ /** @deprecated */
1090
1105
  clampScalar(min, max) {
1091
1106
  for (let i = 0; i < this.ELEMENTS; ++i) {
1092
1107
  this[i] = Math.min(Math.max(this[i], min), max);
1093
1108
  }
1094
1109
  return this.check();
1095
1110
  }
1111
+ /** @deprecated */
1096
1112
  get elements() {
1097
1113
  return this;
1098
1114
  }
@@ -1112,13 +1128,13 @@ var __exports__ = (() => {
1112
1128
  }
1113
1129
  function checkNumber(value) {
1114
1130
  if (!Number.isFinite(value)) {
1115
- throw new Error("Invalid number ".concat(JSON.stringify(value)));
1131
+ throw new Error(`Invalid number ${JSON.stringify(value)}`);
1116
1132
  }
1117
1133
  return value;
1118
1134
  }
1119
1135
  function checkVector(v, length4, callerName = "") {
1120
1136
  if (config.debug && !validateVector(v, length4)) {
1121
- throw new Error("math.gl: ".concat(callerName, " some fields set to invalid numbers'"));
1137
+ throw new Error(`math.gl: ${callerName} some fields set to invalid numbers'`);
1122
1138
  }
1123
1139
  return v;
1124
1140
  }
@@ -1126,12 +1142,13 @@ var __exports__ = (() => {
1126
1142
  // ../../node_modules/@math.gl/core/dist/lib/assert.js
1127
1143
  function assert2(condition, message) {
1128
1144
  if (!condition) {
1129
- throw new Error("math.gl assertion ".concat(message));
1145
+ throw new Error(`math.gl assertion ${message}`);
1130
1146
  }
1131
1147
  }
1132
1148
 
1133
1149
  // ../../node_modules/@math.gl/core/dist/classes/base/vector.js
1134
1150
  var Vector = class extends MathArray {
1151
+ // ACCESSORS
1135
1152
  get x() {
1136
1153
  return this[0];
1137
1154
  }
@@ -1144,12 +1161,24 @@ var __exports__ = (() => {
1144
1161
  set y(value) {
1145
1162
  this[1] = checkNumber(value);
1146
1163
  }
1164
+ /**
1165
+ * Returns the length of the vector from the origin to the point described by this vector
1166
+ *
1167
+ * @note `length` is a reserved word for Arrays, so `v.length()` will return number of elements
1168
+ * Instead we provide `len` and `magnitude`
1169
+ */
1147
1170
  len() {
1148
1171
  return Math.sqrt(this.lengthSquared());
1149
1172
  }
1173
+ /**
1174
+ * Returns the length of the vector from the origin to the point described by this vector
1175
+ */
1150
1176
  magnitude() {
1151
1177
  return this.len();
1152
1178
  }
1179
+ /**
1180
+ * Returns the squared length of the vector from the origin to the point described by this vector
1181
+ */
1153
1182
  lengthSquared() {
1154
1183
  let length4 = 0;
1155
1184
  for (let i = 0; i < this.ELEMENTS; ++i) {
@@ -1157,6 +1186,9 @@ var __exports__ = (() => {
1157
1186
  }
1158
1187
  return length4;
1159
1188
  }
1189
+ /**
1190
+ * Returns the squared length of the vector from the origin to the point described by this vector
1191
+ */
1160
1192
  magnitudeSquared() {
1161
1193
  return this.lengthSquared();
1162
1194
  }
@@ -1178,6 +1210,7 @@ var __exports__ = (() => {
1178
1210
  }
1179
1211
  return checkNumber(product);
1180
1212
  }
1213
+ // MODIFIERS
1181
1214
  normalize() {
1182
1215
  const length4 = this.magnitude();
1183
1216
  if (length4 !== 0) {
@@ -1203,6 +1236,7 @@ var __exports__ = (() => {
1203
1236
  }
1204
1237
  return this.check();
1205
1238
  }
1239
+ // THREE.js compatibility
1206
1240
  lengthSq() {
1207
1241
  return this.lengthSquared();
1208
1242
  }
@@ -1501,6 +1535,8 @@ var __exports__ = (() => {
1501
1535
  object.w = this[3];
1502
1536
  return object;
1503
1537
  }
1538
+ // Getters/setters
1539
+ /* eslint-disable no-multi-spaces, brace-style, no-return-assign */
1504
1540
  get ELEMENTS() {
1505
1541
  return 4;
1506
1542
  }
@@ -1532,6 +1568,7 @@ var __exports__ = (() => {
1532
1568
  transformQuat(this, this, quaternion2);
1533
1569
  return this.check();
1534
1570
  }
1571
+ // three.js compatibility
1535
1572
  applyMatrix4(m) {
1536
1573
  m.transform(this, this);
1537
1574
  return this;
@@ -1540,19 +1577,29 @@ var __exports__ = (() => {
1540
1577
 
1541
1578
  // ../../node_modules/@math.gl/core/dist/classes/base/matrix.js
1542
1579
  var Matrix = class extends MathArray {
1580
+ // fromObject(object) {
1581
+ // const array = object.elements;
1582
+ // return this.fromRowMajor(array);
1583
+ // }
1584
+ // toObject(object) {
1585
+ // const array = object.elements;
1586
+ // this.toRowMajor(array);
1587
+ // return object;
1588
+ // }
1589
+ // TODO better override formatString?
1543
1590
  toString() {
1544
1591
  let string = "[";
1545
1592
  if (config.printRowMajor) {
1546
1593
  string += "row-major:";
1547
1594
  for (let row = 0; row < this.RANK; ++row) {
1548
1595
  for (let col = 0; col < this.RANK; ++col) {
1549
- string += " ".concat(this[col * this.RANK + row]);
1596
+ string += ` ${this[col * this.RANK + row]}`;
1550
1597
  }
1551
1598
  }
1552
1599
  } else {
1553
1600
  string += "column-major:";
1554
1601
  for (let i = 0; i < this.ELEMENTS; ++i) {
1555
- string += " ".concat(this[i]);
1602
+ string += ` ${this[i]}`;
1556
1603
  }
1557
1604
  }
1558
1605
  string += "]";
@@ -1561,9 +1608,11 @@ var __exports__ = (() => {
1561
1608
  getElementIndex(row, col) {
1562
1609
  return col * this.RANK + row;
1563
1610
  }
1611
+ // By default assumes row major indices
1564
1612
  getElement(row, col) {
1565
1613
  return this[col * this.RANK + row];
1566
1614
  }
1615
+ // By default assumes row major indices
1567
1616
  setElement(row, col, value) {
1568
1617
  this[col * this.RANK + row] = checkNumber(value);
1569
1618
  return this;
@@ -2421,6 +2470,7 @@ var __exports__ = (() => {
2421
2470
  this[15] = array[15];
2422
2471
  return this.check();
2423
2472
  }
2473
+ // eslint-disable-next-line max-params
2424
2474
  set(m00, m10, m20, m30, m01, m11, m21, m31, m02, m12, m22, m32, m03, m13, m23, m33) {
2425
2475
  this[0] = m00;
2426
2476
  this[1] = m10;
@@ -2440,6 +2490,8 @@ var __exports__ = (() => {
2440
2490
  this[15] = m33;
2441
2491
  return this.check();
2442
2492
  }
2493
+ // accepts row major order, stores as column major
2494
+ // eslint-disable-next-line max-params
2443
2495
  setRowMajor(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {
2444
2496
  this[0] = m00;
2445
2497
  this[1] = m10;
@@ -2478,25 +2530,41 @@ var __exports__ = (() => {
2478
2530
  result[15] = this[15];
2479
2531
  return result;
2480
2532
  }
2533
+ // Constructors
2534
+ /** Set to identity matrix */
2481
2535
  identity() {
2482
2536
  return this.copy(IDENTITY_MATRIX);
2483
2537
  }
2538
+ /**
2539
+ *
2540
+ * @param object
2541
+ * @returns self
2542
+ */
2543
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2484
2544
  fromObject(object) {
2485
2545
  return this.check();
2486
2546
  }
2547
+ /**
2548
+ * Calculates a 4x4 matrix from the given quaternion
2549
+ * @param quaternion Quaternion to create matrix from
2550
+ * @returns self
2551
+ */
2487
2552
  fromQuaternion(quaternion2) {
2488
2553
  fromQuat(this, quaternion2);
2489
2554
  return this.check();
2490
2555
  }
2556
+ /**
2557
+ * Generates a frustum matrix with the given bounds
2558
+ * @param view.left - Left bound of the frustum
2559
+ * @param view.right - Right bound of the frustum
2560
+ * @param view.bottom - Bottom bound of the frustum
2561
+ * @param view.top - Top bound of the frustum
2562
+ * @param view.near - Near bound of the frustum
2563
+ * @param view.far - Far bound of the frustum. Can be set to Infinity.
2564
+ * @returns self
2565
+ */
2491
2566
  frustum(view) {
2492
- const {
2493
- left,
2494
- right,
2495
- bottom,
2496
- top,
2497
- near = DEFAULT_NEAR,
2498
- far = DEFAULT_FAR
2499
- } = view;
2567
+ const { left, right, bottom, top, near = DEFAULT_NEAR, far = DEFAULT_FAR } = view;
2500
2568
  if (far === Infinity) {
2501
2569
  computeInfinitePerspectiveOffCenter(this, left, right, bottom, top, near);
2502
2570
  } else {
@@ -2504,35 +2572,47 @@ var __exports__ = (() => {
2504
2572
  }
2505
2573
  return this.check();
2506
2574
  }
2575
+ /**
2576
+ * Generates a look-at matrix with the given eye position, focal point,
2577
+ * and up axis
2578
+ * @param view.eye - (vector) Position of the viewer
2579
+ * @param view.center - (vector) Point the viewer is looking at
2580
+ * @param view.up - (vector) Up axis
2581
+ * @returns self
2582
+ */
2507
2583
  lookAt(view) {
2508
- const {
2509
- eye,
2510
- center = [0, 0, 0],
2511
- up = [0, 1, 0]
2512
- } = view;
2584
+ const { eye, center = [0, 0, 0], up = [0, 1, 0] } = view;
2513
2585
  lookAt(this, eye, center, up);
2514
2586
  return this.check();
2515
2587
  }
2588
+ /**
2589
+ * Generates a orthogonal projection matrix with the given bounds
2590
+ * from "traditional" view space parameters
2591
+ * @param view.left - Left bound of the frustum
2592
+ * @param view.right number Right bound of the frustum
2593
+ * @param view.bottom - Bottom bound of the frustum
2594
+ * @param view.top number Top bound of the frustum
2595
+ * @param view.near - Near bound of the frustum
2596
+ * @param view.far number Far bound of the frustum
2597
+ * @returns self
2598
+ */
2516
2599
  ortho(view) {
2517
- const {
2518
- left,
2519
- right,
2520
- bottom,
2521
- top,
2522
- near = DEFAULT_NEAR,
2523
- far = DEFAULT_FAR
2524
- } = view;
2600
+ const { left, right, bottom, top, near = DEFAULT_NEAR, far = DEFAULT_FAR } = view;
2525
2601
  ortho(this, left, right, bottom, top, near, far);
2526
2602
  return this.check();
2527
2603
  }
2604
+ /**
2605
+ * Generates an orthogonal projection matrix with the same parameters
2606
+ * as a perspective matrix (plus focalDistance)
2607
+ * @param view.fovy Vertical field of view in radians
2608
+ * @param view.aspect Aspect ratio. Typically viewport width / viewport height
2609
+ * @param view.focalDistance Distance in the view frustum used for extent calculations
2610
+ * @param view.near Near bound of the frustum
2611
+ * @param view.far Far bound of the frustum
2612
+ * @returns self
2613
+ */
2528
2614
  orthographic(view) {
2529
- const {
2530
- fovy = DEFAULT_FOVY,
2531
- aspect = DEFAULT_ASPECT,
2532
- focalDistance = 1,
2533
- near = DEFAULT_NEAR,
2534
- far = DEFAULT_FAR
2535
- } = view;
2615
+ const { fovy = DEFAULT_FOVY, aspect = DEFAULT_ASPECT, focalDistance = 1, near = DEFAULT_NEAR, far = DEFAULT_FAR } = view;
2536
2616
  checkRadians(fovy);
2537
2617
  const halfY = fovy / 2;
2538
2618
  const top = focalDistance * Math.tan(halfY);
@@ -2546,32 +2626,53 @@ var __exports__ = (() => {
2546
2626
  far
2547
2627
  });
2548
2628
  }
2629
+ /**
2630
+ * Generates a perspective projection matrix with the given bounds
2631
+ * @param view.fovy Vertical field of view in radians
2632
+ * @param view.aspect Aspect ratio. typically viewport width/height
2633
+ * @param view.near Near bound of the frustum
2634
+ * @param view.far Far bound of the frustum
2635
+ * @returns self
2636
+ */
2549
2637
  perspective(view) {
2550
- const {
2551
- fovy = 45 * Math.PI / 180,
2552
- aspect = 1,
2553
- near = 0.1,
2554
- far = 500
2555
- } = view;
2638
+ const { fovy = 45 * Math.PI / 180, aspect = 1, near = 0.1, far = 500 } = view;
2556
2639
  checkRadians(fovy);
2557
2640
  perspective(this, fovy, aspect, near, far);
2558
2641
  return this.check();
2559
2642
  }
2643
+ // Accessors
2560
2644
  determinant() {
2561
2645
  return determinant(this);
2562
2646
  }
2647
+ /**
2648
+ * Extracts the non-uniform scale assuming the matrix is an affine transformation.
2649
+ * The scales are the "lengths" of the column vectors in the upper-left 3x3 matrix.
2650
+ * @param result
2651
+ * @returns self
2652
+ */
2563
2653
  getScale(result = [-0, -0, -0]) {
2564
2654
  result[0] = Math.sqrt(this[0] * this[0] + this[1] * this[1] + this[2] * this[2]);
2565
2655
  result[1] = Math.sqrt(this[4] * this[4] + this[5] * this[5] + this[6] * this[6]);
2566
2656
  result[2] = Math.sqrt(this[8] * this[8] + this[9] * this[9] + this[10] * this[10]);
2567
2657
  return result;
2568
2658
  }
2659
+ /**
2660
+ * Gets the translation portion, assuming the matrix is a affine transformation matrix.
2661
+ * @param result
2662
+ * @returns self
2663
+ */
2569
2664
  getTranslation(result = [-0, -0, -0]) {
2570
2665
  result[0] = this[12];
2571
2666
  result[1] = this[13];
2572
2667
  result[2] = this[14];
2573
2668
  return result;
2574
2669
  }
2670
+ /**
2671
+ * Gets upper left 3x3 pure rotation matrix (non-scaling), assume affine transformation matrix
2672
+ * @param result
2673
+ * @param scaleResult
2674
+ * @returns self
2675
+ */
2575
2676
  getRotation(result, scaleResult) {
2576
2677
  result = result || [-0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0];
2577
2678
  scaleResult = scaleResult || [-0, -0, -0];
@@ -2597,6 +2698,12 @@ var __exports__ = (() => {
2597
2698
  result[15] = 1;
2598
2699
  return result;
2599
2700
  }
2701
+ /**
2702
+ *
2703
+ * @param result
2704
+ * @param scaleResult
2705
+ * @returns self
2706
+ */
2600
2707
  getRotationMatrix3(result, scaleResult) {
2601
2708
  result = result || [-0, -0, -0, -0, -0, -0, -0, -0, -0];
2602
2709
  scaleResult = scaleResult || [-0, -0, -0];
@@ -2615,6 +2722,7 @@ var __exports__ = (() => {
2615
2722
  result[8] = this[10] * inverseScale2;
2616
2723
  return result;
2617
2724
  }
2725
+ // Modifiers
2618
2726
  transpose() {
2619
2727
  transpose(this, this);
2620
2728
  return this.check();
@@ -2623,6 +2731,7 @@ var __exports__ = (() => {
2623
2731
  invert(this, this);
2624
2732
  return this.check();
2625
2733
  }
2734
+ // Operations
2626
2735
  multiplyLeft(a) {
2627
2736
  multiply(this, a, this);
2628
2737
  return this.check();
@@ -2631,33 +2740,68 @@ var __exports__ = (() => {
2631
2740
  multiply(this, this, a);
2632
2741
  return this.check();
2633
2742
  }
2743
+ // Rotates a matrix by the given angle around the X axis
2634
2744
  rotateX(radians) {
2635
2745
  rotateX(this, this, radians);
2636
2746
  return this.check();
2637
2747
  }
2748
+ // Rotates a matrix by the given angle around the Y axis.
2638
2749
  rotateY(radians) {
2639
2750
  rotateY(this, this, radians);
2640
2751
  return this.check();
2641
2752
  }
2753
+ /**
2754
+ * Rotates a matrix by the given angle around the Z axis.
2755
+ * @param radians
2756
+ * @returns self
2757
+ */
2642
2758
  rotateZ(radians) {
2643
2759
  rotateZ(this, this, radians);
2644
2760
  return this.check();
2645
2761
  }
2762
+ /**
2763
+ *
2764
+ * @param param0
2765
+ * @returns self
2766
+ */
2646
2767
  rotateXYZ(angleXYZ) {
2647
2768
  return this.rotateX(angleXYZ[0]).rotateY(angleXYZ[1]).rotateZ(angleXYZ[2]);
2648
2769
  }
2770
+ /**
2771
+ *
2772
+ * @param radians
2773
+ * @param axis
2774
+ * @returns self
2775
+ */
2649
2776
  rotateAxis(radians, axis) {
2650
2777
  rotate(this, this, radians, axis);
2651
2778
  return this.check();
2652
2779
  }
2780
+ /**
2781
+ *
2782
+ * @param factor
2783
+ * @returns self
2784
+ */
2653
2785
  scale(factor) {
2654
2786
  scale(this, this, Array.isArray(factor) ? factor : [factor, factor, factor]);
2655
2787
  return this.check();
2656
2788
  }
2789
+ /**
2790
+ *
2791
+ * @param vec
2792
+ * @returns self
2793
+ */
2657
2794
  translate(vector) {
2658
2795
  translate(this, this, vector);
2659
2796
  return this.check();
2660
2797
  }
2798
+ // Transforms
2799
+ /**
2800
+ * Transforms any 2, 3 or 4 element vector. 2 and 3 elements are treated as points
2801
+ * @param vector
2802
+ * @param result
2803
+ * @returns self
2804
+ */
2661
2805
  transform(vector, result) {
2662
2806
  if (vector.length === 4) {
2663
2807
  result = transformMat43(result || [-0, -0, -0, -0], vector, this);
@@ -2666,10 +2810,14 @@ var __exports__ = (() => {
2666
2810
  }
2667
2811
  return this.transformAsPoint(vector, result);
2668
2812
  }
2813
+ /**
2814
+ * Transforms any 2 or 3 element array as point (w implicitly 1)
2815
+ * @param vector
2816
+ * @param result
2817
+ * @returns self
2818
+ */
2669
2819
  transformAsPoint(vector, result) {
2670
- const {
2671
- length: length4
2672
- } = vector;
2820
+ const { length: length4 } = vector;
2673
2821
  let out;
2674
2822
  switch (length4) {
2675
2823
  case 2:
@@ -2684,6 +2832,12 @@ var __exports__ = (() => {
2684
2832
  checkVector(out, vector.length);
2685
2833
  return out;
2686
2834
  }
2835
+ /**
2836
+ * Transforms any 2 or 3 element array as vector (w implicitly 0)
2837
+ * @param vector
2838
+ * @param result
2839
+ * @returns self
2840
+ */
2687
2841
  transformAsVector(vector, result) {
2688
2842
  let out;
2689
2843
  switch (vector.length) {
@@ -2699,15 +2853,19 @@ var __exports__ = (() => {
2699
2853
  checkVector(out, vector.length);
2700
2854
  return out;
2701
2855
  }
2856
+ /** @deprecated */
2702
2857
  transformPoint(vector, result) {
2703
2858
  return this.transformAsPoint(vector, result);
2704
2859
  }
2860
+ /** @deprecated */
2705
2861
  transformVector(vector, result) {
2706
2862
  return this.transformAsPoint(vector, result);
2707
2863
  }
2864
+ /** @deprecated */
2708
2865
  transformDirection(vector, result) {
2709
2866
  return this.transformAsVector(vector, result);
2710
2867
  }
2868
+ // three.js math API compatibility
2711
2869
  makeRotationX(radians) {
2712
2870
  return this.identity().rotateX(radians);
2713
2871
  }
@@ -3034,6 +3192,13 @@ var __exports__ = (() => {
3034
3192
  this[3] = object.w;
3035
3193
  return this.check();
3036
3194
  }
3195
+ /**
3196
+ * Creates a quaternion from the given 3x3 rotation matrix.
3197
+ * NOTE: The resultant quaternion is not normalized, so you should
3198
+ * be sure to renormalize the quaternion yourself where necessary.
3199
+ * @param m
3200
+ * @returns
3201
+ */
3037
3202
  fromMatrix3(m) {
3038
3203
  fromMat3(this, m);
3039
3204
  return this.check();
@@ -3042,13 +3207,21 @@ var __exports__ = (() => {
3042
3207
  setAxisAngle(this, axis, rad);
3043
3208
  return this.check();
3044
3209
  }
3210
+ /** Set a quat to the identity quaternion */
3045
3211
  identity() {
3046
3212
  identity2(this);
3047
3213
  return this.check();
3048
3214
  }
3215
+ // Set the components of a quat to the given values
3216
+ // set(i, j, k, l) {
3217
+ // quat_set(this, i, j, k, l);
3218
+ // return this.check();
3219
+ // }
3220
+ // Sets a quat from the given angle and rotation axis, then returns it.
3049
3221
  setAxisAngle(axis, rad) {
3050
3222
  return this.fromAxisRotation(axis, rad);
3051
3223
  }
3224
+ // Getters/setters
3052
3225
  get ELEMENTS() {
3053
3226
  return 4;
3054
3227
  }
@@ -3076,35 +3249,72 @@ var __exports__ = (() => {
3076
3249
  set w(value) {
3077
3250
  this[3] = checkNumber(value);
3078
3251
  }
3252
+ // Calculates the length of a quat
3079
3253
  len() {
3080
3254
  return length3(this);
3081
3255
  }
3256
+ // Calculates the squared length of a quat
3082
3257
  lengthSquared() {
3083
3258
  return squaredLength2(this);
3084
3259
  }
3260
+ // Calculates the dot product of two quat's
3261
+ // @return {Number}
3085
3262
  dot(a) {
3086
3263
  return dot3(this, a);
3087
3264
  }
3265
+ // Gets the rotation axis and angle for a given quaternion.
3266
+ // If a quaternion is created with setAxisAngle, this method will
3267
+ // return the same values as providied in the original parameter
3268
+ // list OR functionally equivalent values.
3269
+ // Example: The quaternion formed by axis [0, 0, 1] and angle -90
3270
+ // is the same as the quaternion formed by [0, 0, 1] and 270.
3271
+ // This method favors the latter.
3272
+ // @return {{[x,y,z], Number}}
3273
+ // getAxisAngle() {
3274
+ // const axis = [];
3275
+ // // const angle = quat_getAxisAngle(axis, this);
3276
+ // return {axis, angle};
3277
+ // }
3278
+ // MODIFIERS
3279
+ // Sets a quaternion to represent the shortest rotation from one vector
3280
+ // to another. Both vectors are assumed to be unit length.
3088
3281
  rotationTo(vectorA, vectorB) {
3089
3282
  rotationTo(this, vectorA, vectorB);
3090
3283
  return this.check();
3091
3284
  }
3285
+ // Sets the specified quaternion with values corresponding to the given axes.
3286
+ // Each axis is a vec3 and is expected to be unit length and perpendicular
3287
+ // to all other specified axes.
3288
+ // setAxes() {
3289
+ // Number
3290
+ // }
3291
+ // Performs a spherical linear interpolation with two control points
3292
+ // sqlerp() {
3293
+ // Number;
3294
+ // }
3295
+ // Adds two quat's
3092
3296
  add(a) {
3093
3297
  add2(this, this, a);
3094
3298
  return this.check();
3095
3299
  }
3300
+ // Calculates the W component of a quat from the X, Y, and Z components.
3301
+ // Any existing W component will be ignored.
3096
3302
  calculateW() {
3097
3303
  calculateW(this, this);
3098
3304
  return this.check();
3099
3305
  }
3306
+ // Calculates the conjugate of a quat If the quaternion is normalized,
3307
+ // this function is faster than quat_invert and produces the same result.
3100
3308
  conjugate() {
3101
3309
  conjugate(this, this);
3102
3310
  return this.check();
3103
3311
  }
3312
+ // Calculates the inverse of a quat
3104
3313
  invert() {
3105
3314
  invert2(this, this);
3106
3315
  return this.check();
3107
3316
  }
3317
+ // Performs a linear interpolation between two quat's
3108
3318
  lerp(a, b, t) {
3109
3319
  if (t === void 0) {
3110
3320
  return this.lerp(this, a, b);
@@ -3112,6 +3322,7 @@ var __exports__ = (() => {
3112
3322
  lerp2(this, a, b, t);
3113
3323
  return this.check();
3114
3324
  }
3325
+ // Multiplies two quat's
3115
3326
  multiplyRight(a) {
3116
3327
  multiply2(this, this, a);
3117
3328
  return this.check();
@@ -3120,6 +3331,7 @@ var __exports__ = (() => {
3120
3331
  multiply2(this, a, this);
3121
3332
  return this.check();
3122
3333
  }
3334
+ // Normalize a quat
3123
3335
  normalize() {
3124
3336
  const length4 = this.len();
3125
3337
  const l = length4 > 0 ? 1 / length4 : 0;
@@ -3132,22 +3344,27 @@ var __exports__ = (() => {
3132
3344
  }
3133
3345
  return this.check();
3134
3346
  }
3347
+ // Rotates a quaternion by the given angle about the X axis
3135
3348
  rotateX(rad) {
3136
3349
  rotateX2(this, this, rad);
3137
3350
  return this.check();
3138
3351
  }
3352
+ // Rotates a quaternion by the given angle about the Y axis
3139
3353
  rotateY(rad) {
3140
3354
  rotateY2(this, this, rad);
3141
3355
  return this.check();
3142
3356
  }
3357
+ // Rotates a quaternion by the given angle about the Z axis
3143
3358
  rotateZ(rad) {
3144
3359
  rotateZ2(this, this, rad);
3145
3360
  return this.check();
3146
3361
  }
3362
+ // Scales a quat by a scalar number
3147
3363
  scale(b) {
3148
3364
  scale3(this, this, b);
3149
3365
  return this.check();
3150
3366
  }
3367
+ // Performs a spherical linear interpolation between two quat
3151
3368
  slerp(arg0, arg1, arg2) {
3152
3369
  let start;
3153
3370
  let target;
@@ -3177,6 +3394,7 @@ var __exports__ = (() => {
3177
3394
  transformQuat2(result, vector, this);
3178
3395
  return checkVector(result, 4);
3179
3396
  }
3397
+ // THREE.js Math API compatibility
3180
3398
  lengthSq() {
3181
3399
  return this.lengthSquared();
3182
3400
  }
@@ -3369,568 +3587,7 @@ var __exports__ = (() => {
3369
3587
 
3370
3588
  // src/gltf/create-gltf-model.ts
3371
3589
  var import_core4 = __toESM(require_core(), 1);
3372
-
3373
- // ../shadertools/src/lib/glsl-utils/highlight.ts
3374
- var glsl = (x) => `${x}`;
3375
-
3376
- // ../shadertools/src/modules-webgl1/lighting/lights/lights-glsl.ts
3377
- var lightingShader = glsl`\
3378
- #if (defined(SHADER_TYPE_FRAGMENT) && defined(LIGHTING_FRAGMENT)) || (defined(SHADER_TYPE_VERTEX) && defined(LIGHTING_VERTEX))
3379
-
3380
- struct AmbientLight {
3381
- vec3 color;
3382
- };
3383
-
3384
- struct PointLight {
3385
- vec3 color;
3386
- vec3 position;
3387
-
3388
- // Constant-Linear-Exponential
3389
- vec3 attenuation;
3390
- };
3391
-
3392
- struct DirectionalLight {
3393
- vec3 color;
3394
- vec3 direction;
3395
- };
3396
-
3397
- uniform AmbientLight lighting_uAmbientLight;
3398
- uniform PointLight lighting_uPointLight[MAX_LIGHTS];
3399
- uniform DirectionalLight lighting_uDirectionalLight[MAX_LIGHTS];
3400
- uniform int lighting_uPointLightCount;
3401
- uniform int lighting_uDirectionalLightCount;
3402
-
3403
- uniform bool lighting_uEnabled;
3404
-
3405
- float getPointLightAttenuation(PointLight pointLight, float distance) {
3406
- return pointLight.attenuation.x
3407
- + pointLight.attenuation.y * distance
3408
- + pointLight.attenuation.z * distance * distance;
3409
- }
3410
-
3411
- #endif
3412
- `;
3413
-
3414
- // ../shadertools/src/modules-webgl1/lighting/lights/lights.ts
3415
- var INITIAL_MODULE_OPTIONS = {
3416
- lightSources: {}
3417
- };
3418
- function convertColor(colorDef = {}) {
3419
- const { color = [0, 0, 0], intensity = 1 } = colorDef;
3420
- return color.map((component) => component * intensity / 255);
3421
- }
3422
- function getLightSourceUniforms({
3423
- ambientLight,
3424
- pointLights = [],
3425
- directionalLights = []
3426
- }) {
3427
- const lightSourceUniforms = {};
3428
- if (ambientLight) {
3429
- lightSourceUniforms["lighting_uAmbientLight.color"] = convertColor(ambientLight);
3430
- } else {
3431
- lightSourceUniforms["lighting_uAmbientLight.color"] = [0, 0, 0];
3432
- }
3433
- pointLights.forEach((pointLight, index) => {
3434
- lightSourceUniforms[`lighting_uPointLight[${index}].color`] = convertColor(pointLight);
3435
- lightSourceUniforms[`lighting_uPointLight[${index}].position`] = pointLight.position;
3436
- lightSourceUniforms[`lighting_uPointLight[${index}].attenuation`] = pointLight.attenuation || [
3437
- 1,
3438
- 0,
3439
- 0
3440
- ];
3441
- });
3442
- lightSourceUniforms.lighting_uPointLightCount = pointLights.length;
3443
- directionalLights.forEach((directionalLight, index) => {
3444
- lightSourceUniforms[`lighting_uDirectionalLight[${index}].color`] = convertColor(directionalLight);
3445
- lightSourceUniforms[`lighting_uDirectionalLight[${index}].direction`] = directionalLight.direction;
3446
- });
3447
- lightSourceUniforms.lighting_uDirectionalLightCount = directionalLights.length;
3448
- return lightSourceUniforms;
3449
- }
3450
- function getUniforms(opts = INITIAL_MODULE_OPTIONS) {
3451
- if ("lightSources" in opts) {
3452
- const { ambientLight, pointLights, directionalLights } = opts.lightSources || {};
3453
- const hasLights = ambientLight || pointLights && pointLights.length > 0 || directionalLights && directionalLights.length > 0;
3454
- if (!hasLights) {
3455
- return { lighting_uEnabled: false };
3456
- }
3457
- return Object.assign(
3458
- {},
3459
- getLightSourceUniforms({ ambientLight, pointLights, directionalLights }),
3460
- {
3461
- lighting_uEnabled: true
3462
- }
3463
- );
3464
- }
3465
- if ("lights" in opts) {
3466
- const lightSources = { pointLights: [], directionalLights: [] };
3467
- for (const light of opts.lights || []) {
3468
- switch (light.type) {
3469
- case "ambient":
3470
- lightSources.ambientLight = light;
3471
- break;
3472
- case "directional":
3473
- lightSources.directionalLights?.push(light);
3474
- break;
3475
- case "point":
3476
- lightSources.pointLights?.push(light);
3477
- break;
3478
- default:
3479
- }
3480
- }
3481
- return getUniforms({ lightSources });
3482
- }
3483
- return {};
3484
- }
3485
- var lights = {
3486
- name: "lights",
3487
- vs: lightingShader,
3488
- fs: lightingShader,
3489
- getUniforms,
3490
- defines: {
3491
- MAX_LIGHTS: 3
3492
- }
3493
- };
3494
-
3495
- // ../shadertools/src/modules-webgl1/lighting/pbr/pbr-vertex-glsl.ts
3496
- var vs = glsl`\
3497
- uniform mat4 u_MVPMatrix;
3498
- uniform mat4 u_ModelMatrix;
3499
- uniform mat4 u_NormalMatrix;
3500
-
3501
- out vec3 pbr_vPosition;
3502
- out vec2 pbr_vUV;
3503
-
3504
- #ifdef HAS_NORMALS
3505
- # ifdef HAS_TANGENTS
3506
- out mat3 pbr_vTBN;
3507
- # else
3508
- out vec3 pbr_vNormal;
3509
- # endif
3510
- #endif
3511
-
3512
- void pbr_setPositionNormalTangentUV(vec4 position, vec4 normal, vec4 tangent, vec2 uv)
3513
- {
3514
- vec4 pos = u_ModelMatrix * position;
3515
- pbr_vPosition = vec3(pos.xyz) / pos.w;
3516
-
3517
- #ifdef HAS_NORMALS
3518
- #ifdef HAS_TANGENTS
3519
- vec3 normalW = normalize(vec3(u_NormalMatrix * vec4(normal.xyz, 0.0)));
3520
- vec3 tangentW = normalize(vec3(u_ModelMatrix * vec4(tangent.xyz, 0.0)));
3521
- vec3 bitangentW = cross(normalW, tangentW) * tangent.w;
3522
- pbr_vTBN = mat3(tangentW, bitangentW, normalW);
3523
- #else // HAS_TANGENTS != 1
3524
- pbr_vNormal = normalize(vec3(u_ModelMatrix * vec4(normal.xyz, 0.0)));
3525
- #endif
3526
- #endif
3527
-
3528
- #ifdef HAS_UV
3529
- pbr_vUV = uv;
3530
- #else
3531
- pbr_vUV = vec2(0.,0.);
3532
- #endif
3533
- }
3534
- `;
3535
-
3536
- // ../shadertools/src/modules-webgl1/lighting/pbr/pbr-fragment-glsl.ts
3537
- var fs = glsl`\
3538
- precision highp float;
3539
-
3540
- uniform bool pbr_uUnlit;
3541
-
3542
- #ifdef USE_IBL
3543
- uniform samplerCube u_DiffuseEnvSampler;
3544
- uniform samplerCube u_SpecularEnvSampler;
3545
- uniform sampler2D u_brdfLUT;
3546
- uniform vec2 u_ScaleIBLAmbient;
3547
- #endif
3548
-
3549
- #ifdef HAS_BASECOLORMAP
3550
- uniform sampler2D u_BaseColorSampler;
3551
- #endif
3552
- #ifdef HAS_NORMALMAP
3553
- uniform sampler2D u_NormalSampler;
3554
- uniform float u_NormalScale;
3555
- #endif
3556
- #ifdef HAS_EMISSIVEMAP
3557
- uniform sampler2D u_EmissiveSampler;
3558
- uniform vec3 u_EmissiveFactor;
3559
- #endif
3560
- #ifdef HAS_METALROUGHNESSMAP
3561
- uniform sampler2D u_MetallicRoughnessSampler;
3562
- #endif
3563
- #ifdef HAS_OCCLUSIONMAP
3564
- uniform sampler2D u_OcclusionSampler;
3565
- uniform float u_OcclusionStrength;
3566
- #endif
3567
-
3568
- #ifdef ALPHA_CUTOFF
3569
- uniform float u_AlphaCutoff;
3570
- #endif
3571
-
3572
- uniform vec2 u_MetallicRoughnessValues;
3573
- uniform vec4 u_BaseColorFactor;
3574
-
3575
- uniform vec3 u_Camera;
3576
-
3577
- // debugging flags used for shader output of intermediate PBR variables
3578
- #ifdef PBR_DEBUG
3579
- uniform vec4 u_ScaleDiffBaseMR;
3580
- uniform vec4 u_ScaleFGDSpec;
3581
- #endif
3582
-
3583
- in vec3 pbr_vPosition;
3584
-
3585
- in vec2 pbr_vUV;
3586
-
3587
- #ifdef HAS_NORMALS
3588
- #ifdef HAS_TANGENTS
3589
- in mat3 pbr_vTBN;
3590
- #else
3591
- in vec3 pbr_vNormal;
3592
- #endif
3593
- #endif
3594
-
3595
- // Encapsulate the various inputs used by the various functions in the shading equation
3596
- // We store values in this struct to simplify the integration of alternative implementations
3597
- // of the shading terms, outlined in the Readme.MD Appendix.
3598
- struct PBRInfo
3599
- {
3600
- float NdotL; // cos angle between normal and light direction
3601
- float NdotV; // cos angle between normal and view direction
3602
- float NdotH; // cos angle between normal and half vector
3603
- float LdotH; // cos angle between light direction and half vector
3604
- float VdotH; // cos angle between view direction and half vector
3605
- float perceptualRoughness; // roughness value, as authored by the model creator (input to shader)
3606
- float metalness; // metallic value at the surface
3607
- vec3 reflectance0; // full reflectance color (normal incidence angle)
3608
- vec3 reflectance90; // reflectance color at grazing angle
3609
- float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2])
3610
- vec3 diffuseColor; // color contribution from diffuse lighting
3611
- vec3 specularColor; // color contribution from specular lighting
3612
- vec3 n; // normal at surface point
3613
- vec3 v; // vector from surface point to camera
3614
- };
3615
-
3616
- const float M_PI = 3.141592653589793;
3617
- const float c_MinRoughness = 0.04;
3618
-
3619
- vec4 SRGBtoLINEAR(vec4 srgbIn)
3620
- {
3621
- #ifdef MANUAL_SRGB
3622
- #ifdef SRGB_FAST_APPROXIMATION
3623
- vec3 linOut = pow(srgbIn.xyz,vec3(2.2));
3624
- #else //SRGB_FAST_APPROXIMATION
3625
- vec3 bLess = step(vec3(0.04045),srgbIn.xyz);
3626
- vec3 linOut = mix( srgbIn.xyz/vec3(12.92), pow((srgbIn.xyz+vec3(0.055))/vec3(1.055),vec3(2.4)), bLess );
3627
- #endif //SRGB_FAST_APPROXIMATION
3628
- return vec4(linOut,srgbIn.w);;
3629
- #else //MANUAL_SRGB
3630
- return srgbIn;
3631
- #endif //MANUAL_SRGB
3632
- }
3633
-
3634
- // Find the normal for this fragment, pulling either from a predefined normal map
3635
- // or from the interpolated mesh normal and tangent attributes.
3636
- vec3 getNormal()
3637
- {
3638
- // Retrieve the tangent space matrix
3639
- #ifndef HAS_TANGENTS
3640
- vec3 pos_dx = dFdx(pbr_vPosition);
3641
- vec3 pos_dy = dFdy(pbr_vPosition);
3642
- vec3 tex_dx = dFdx(vec3(pbr_vUV, 0.0));
3643
- vec3 tex_dy = dFdy(vec3(pbr_vUV, 0.0));
3644
- vec3 t = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t);
3645
-
3646
- #ifdef HAS_NORMALS
3647
- vec3 ng = normalize(pbr_vNormal);
3648
- #else
3649
- vec3 ng = cross(pos_dx, pos_dy);
3650
- #endif
3651
-
3652
- t = normalize(t - ng * dot(ng, t));
3653
- vec3 b = normalize(cross(ng, t));
3654
- mat3 tbn = mat3(t, b, ng);
3655
- #else // HAS_TANGENTS
3656
- mat3 tbn = pbr_vTBN;
3657
- #endif
3658
-
3659
- #ifdef HAS_NORMALMAP
3660
- vec3 n = texture(u_NormalSampler, pbr_vUV).rgb;
3661
- n = normalize(tbn * ((2.0 * n - 1.0) * vec3(u_NormalScale, u_NormalScale, 1.0)));
3662
- #else
3663
- // The tbn matrix is linearly interpolated, so we need to re-normalize
3664
- vec3 n = normalize(tbn[2].xyz);
3665
- #endif
3666
-
3667
- return n;
3668
- }
3669
-
3670
- // Calculation of the lighting contribution from an optional Image Based Light source.
3671
- // Precomputed Environment Maps are required uniform inputs and are computed as outlined in [1].
3672
- // See our README.md on Environment Maps [3] for additional discussion.
3673
- #ifdef USE_IBL
3674
- vec3 getIBLContribution(PBRInfo pbrInputs, vec3 n, vec3 reflection)
3675
- {
3676
- float mipCount = 9.0; // resolution of 512x512
3677
- float lod = (pbrInputs.perceptualRoughness * mipCount);
3678
- // retrieve a scale and bias to F0. See [1], Figure 3
3679
- vec3 brdf = SRGBtoLINEAR(texture(u_brdfLUT,
3680
- vec2(pbrInputs.NdotV, 1.0 - pbrInputs.perceptualRoughness))).rgb;
3681
- vec3 diffuseLight = SRGBtoLINEAR(textureCube(u_DiffuseEnvSampler, n)).rgb;
3682
-
3683
- #ifdef USE_TEX_LOD
3684
- vec3 specularLight = SRGBtoLINEAR(textureCubeLod(u_SpecularEnvSampler, reflection, lod)).rgb;
3685
- #else
3686
- vec3 specularLight = SRGBtoLINEAR(textureCube(u_SpecularEnvSampler, reflection)).rgb;
3687
- #endif
3688
-
3689
- vec3 diffuse = diffuseLight * pbrInputs.diffuseColor;
3690
- vec3 specular = specularLight * (pbrInputs.specularColor * brdf.x + brdf.y);
3691
-
3692
- // For presentation, this allows us to disable IBL terms
3693
- diffuse *= u_ScaleIBLAmbient.x;
3694
- specular *= u_ScaleIBLAmbient.y;
3695
-
3696
- return diffuse + specular;
3697
- }
3698
- #endif
3699
-
3700
- // Basic Lambertian diffuse
3701
- // Implementation from Lambert's Photometria https://archive.org/details/lambertsphotome00lambgoog
3702
- // See also [1], Equation 1
3703
- vec3 diffuse(PBRInfo pbrInputs)
3704
- {
3705
- return pbrInputs.diffuseColor / M_PI;
3706
- }
3707
-
3708
- // The following equation models the Fresnel reflectance term of the spec equation (aka F())
3709
- // Implementation of fresnel from [4], Equation 15
3710
- vec3 specularReflection(PBRInfo pbrInputs)
3711
- {
3712
- return pbrInputs.reflectance0 +
3713
- (pbrInputs.reflectance90 - pbrInputs.reflectance0) *
3714
- pow(clamp(1.0 - pbrInputs.VdotH, 0.0, 1.0), 5.0);
3715
- }
3716
-
3717
- // This calculates the specular geometric attenuation (aka G()),
3718
- // where rougher material will reflect less light back to the viewer.
3719
- // This implementation is based on [1] Equation 4, and we adopt their modifications to
3720
- // alphaRoughness as input as originally proposed in [2].
3721
- float geometricOcclusion(PBRInfo pbrInputs)
3722
- {
3723
- float NdotL = pbrInputs.NdotL;
3724
- float NdotV = pbrInputs.NdotV;
3725
- float r = pbrInputs.alphaRoughness;
3726
-
3727
- float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL)));
3728
- float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV)));
3729
- return attenuationL * attenuationV;
3730
- }
3731
-
3732
- // The following equation(s) model the distribution of microfacet normals across
3733
- // the area being drawn (aka D())
3734
- // Implementation from "Average Irregularity Representation of a Roughened Surface
3735
- // for Ray Reflection" by T. S. Trowbridge, and K. P. Reitz
3736
- // Follows the distribution function recommended in the SIGGRAPH 2013 course notes
3737
- // from EPIC Games [1], Equation 3.
3738
- float microfacetDistribution(PBRInfo pbrInputs)
3739
- {
3740
- float roughnessSq = pbrInputs.alphaRoughness * pbrInputs.alphaRoughness;
3741
- float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0;
3742
- return roughnessSq / (M_PI * f * f);
3743
- }
3744
-
3745
- void PBRInfo_setAmbientLight(inout PBRInfo pbrInputs) {
3746
- pbrInputs.NdotL = 1.0;
3747
- pbrInputs.NdotH = 0.0;
3748
- pbrInputs.LdotH = 0.0;
3749
- pbrInputs.VdotH = 1.0;
3750
- }
3751
-
3752
- void PBRInfo_setDirectionalLight(inout PBRInfo pbrInputs, vec3 lightDirection) {
3753
- vec3 n = pbrInputs.n;
3754
- vec3 v = pbrInputs.v;
3755
- vec3 l = normalize(lightDirection); // Vector from surface point to light
3756
- vec3 h = normalize(l+v); // Half vector between both l and v
3757
-
3758
- pbrInputs.NdotL = clamp(dot(n, l), 0.001, 1.0);
3759
- pbrInputs.NdotH = clamp(dot(n, h), 0.0, 1.0);
3760
- pbrInputs.LdotH = clamp(dot(l, h), 0.0, 1.0);
3761
- pbrInputs.VdotH = clamp(dot(v, h), 0.0, 1.0);
3762
- }
3763
-
3764
- void PBRInfo_setPointLight(inout PBRInfo pbrInputs, PointLight pointLight) {
3765
- vec3 light_direction = normalize(pointLight.position - pbr_vPosition);
3766
- PBRInfo_setDirectionalLight(pbrInputs, light_direction);
3767
- }
3768
-
3769
- vec3 calculateFinalColor(PBRInfo pbrInputs, vec3 lightColor) {
3770
- // Calculate the shading terms for the microfacet specular shading model
3771
- vec3 F = specularReflection(pbrInputs);
3772
- float G = geometricOcclusion(pbrInputs);
3773
- float D = microfacetDistribution(pbrInputs);
3774
-
3775
- // Calculation of analytical lighting contribution
3776
- vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInputs);
3777
- vec3 specContrib = F * G * D / (4.0 * pbrInputs.NdotL * pbrInputs.NdotV);
3778
- // Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law)
3779
- return pbrInputs.NdotL * lightColor * (diffuseContrib + specContrib);
3780
- }
3781
-
3782
- vec4 pbr_filterColor(vec4 colorUnused)
3783
- {
3784
- // The albedo may be defined from a base texture or a flat color
3785
- #ifdef HAS_BASECOLORMAP
3786
- vec4 baseColor = SRGBtoLINEAR(texture(u_BaseColorSampler, pbr_vUV)) * u_BaseColorFactor;
3787
- #else
3788
- vec4 baseColor = u_BaseColorFactor;
3789
- #endif
3790
-
3791
- #ifdef ALPHA_CUTOFF
3792
- if (baseColor.a < u_AlphaCutoff) {
3793
- discard;
3794
- }
3795
- #endif
3796
-
3797
- vec3 color = vec3(0, 0, 0);
3798
-
3799
- if(pbr_uUnlit){
3800
- color.rgb = baseColor.rgb;
3801
- }
3802
- else{
3803
- // Metallic and Roughness material properties are packed together
3804
- // In glTF, these factors can be specified by fixed scalar values
3805
- // or from a metallic-roughness map
3806
- float perceptualRoughness = u_MetallicRoughnessValues.y;
3807
- float metallic = u_MetallicRoughnessValues.x;
3808
- #ifdef HAS_METALROUGHNESSMAP
3809
- // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.
3810
- // This layout intentionally reserves the 'r' channel for (optional) occlusion map data
3811
- vec4 mrSample = texture(u_MetallicRoughnessSampler, pbr_vUV);
3812
- perceptualRoughness = mrSample.g * perceptualRoughness;
3813
- metallic = mrSample.b * metallic;
3814
- #endif
3815
- perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
3816
- metallic = clamp(metallic, 0.0, 1.0);
3817
- // Roughness is authored as perceptual roughness; as is convention,
3818
- // convert to material roughness by squaring the perceptual roughness [2].
3819
- float alphaRoughness = perceptualRoughness * perceptualRoughness;
3820
-
3821
- vec3 f0 = vec3(0.04);
3822
- vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0);
3823
- diffuseColor *= 1.0 - metallic;
3824
- vec3 specularColor = mix(f0, baseColor.rgb, metallic);
3825
-
3826
- // Compute reflectance.
3827
- float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
3828
-
3829
- // For typical incident reflectance range (between 4% to 100%) set the grazing
3830
- // reflectance to 100% for typical fresnel effect.
3831
- // For very low reflectance range on highly diffuse objects (below 4%),
3832
- // incrementally reduce grazing reflecance to 0%.
3833
- float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
3834
- vec3 specularEnvironmentR0 = specularColor.rgb;
3835
- vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;
3836
-
3837
- vec3 n = getNormal(); // normal at surface point
3838
- vec3 v = normalize(u_Camera - pbr_vPosition); // Vector from surface point to camera
3839
-
3840
- float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
3841
- vec3 reflection = -normalize(reflect(v, n));
3842
-
3843
- PBRInfo pbrInputs = PBRInfo(
3844
- 0.0, // NdotL
3845
- NdotV,
3846
- 0.0, // NdotH
3847
- 0.0, // LdotH
3848
- 0.0, // VdotH
3849
- perceptualRoughness,
3850
- metallic,
3851
- specularEnvironmentR0,
3852
- specularEnvironmentR90,
3853
- alphaRoughness,
3854
- diffuseColor,
3855
- specularColor,
3856
- n,
3857
- v
3858
- );
3859
-
3860
- #ifdef USE_LIGHTS
3861
- // Apply ambient light
3862
- PBRInfo_setAmbientLight(pbrInputs);
3863
- color += calculateFinalColor(pbrInputs, lighting_uAmbientLight.color);
3864
-
3865
- // Apply directional light
3866
- for(int i = 0; i < lighting_uDirectionalLightCount; i++) {
3867
- if (i < lighting_uDirectionalLightCount) {
3868
- PBRInfo_setDirectionalLight(pbrInputs, lighting_uDirectionalLight[i].direction);
3869
- color += calculateFinalColor(pbrInputs, lighting_uDirectionalLight[i].color);
3870
- }
3871
- }
3872
-
3873
- // Apply point light
3874
- for(int i = 0; i < lighting_uPointLightCount; i++) {
3875
- if (i < lighting_uPointLightCount) {
3876
- PBRInfo_setPointLight(pbrInputs, lighting_uPointLight[i]);
3877
- float attenuation = getPointLightAttenuation(lighting_uPointLight[i], distance(lighting_uPointLight[i].position, pbr_vPosition));
3878
- color += calculateFinalColor(pbrInputs, lighting_uPointLight[i].color / attenuation);
3879
- }
3880
- }
3881
- #endif
3882
-
3883
- // Calculate lighting contribution from image based lighting source (IBL)
3884
- #ifdef USE_IBL
3885
- color += getIBLContribution(pbrInputs, n, reflection);
3886
- #endif
3887
-
3888
- // Apply optional PBR terms for additional (optional) shading
3889
- #ifdef HAS_OCCLUSIONMAP
3890
- float ao = texture(u_OcclusionSampler, pbr_vUV).r;
3891
- color = mix(color, color * ao, u_OcclusionStrength);
3892
- #endif
3893
-
3894
- #ifdef HAS_EMISSIVEMAP
3895
- vec3 emissive = SRGBtoLINEAR(texture(u_EmissiveSampler, pbr_vUV)).rgb * u_EmissiveFactor;
3896
- color += emissive;
3897
- #endif
3898
-
3899
- // This section uses mix to override final color for reference app visualization
3900
- // of various parameters in the lighting equation.
3901
- #ifdef PBR_DEBUG
3902
- // TODO: Figure out how to debug multiple lights
3903
-
3904
- // color = mix(color, F, u_ScaleFGDSpec.x);
3905
- // color = mix(color, vec3(G), u_ScaleFGDSpec.y);
3906
- // color = mix(color, vec3(D), u_ScaleFGDSpec.z);
3907
- // color = mix(color, specContrib, u_ScaleFGDSpec.w);
3908
-
3909
- // color = mix(color, diffuseContrib, u_ScaleDiffBaseMR.x);
3910
- color = mix(color, baseColor.rgb, u_ScaleDiffBaseMR.y);
3911
- color = mix(color, vec3(metallic), u_ScaleDiffBaseMR.z);
3912
- color = mix(color, vec3(perceptualRoughness), u_ScaleDiffBaseMR.w);
3913
- #endif
3914
-
3915
- }
3916
-
3917
- return vec4(pow(color,vec3(1.0/2.2)), baseColor.a);
3918
- }
3919
- `;
3920
-
3921
- // ../shadertools/src/modules-webgl1/lighting/pbr/pbr.ts
3922
- var pbr = {
3923
- name: "pbr",
3924
- vs,
3925
- fs,
3926
- defines: {
3927
- LIGHTING_FRAGMENT: 1
3928
- },
3929
- dependencies: [lights],
3930
- getUniforms: (props) => props
3931
- };
3932
-
3933
- // src/gltf/create-gltf-model.ts
3590
+ var import_shadertools = __toESM(require_shadertools(), 1);
3934
3591
  var import_engine2 = __toESM(require_engine(), 1);
3935
3592
  var SHADER = (
3936
3593
  /* WGSL */
@@ -3981,8 +3638,9 @@ layout(0) positions: vec4; // in vec4 POSITION;
3981
3638
  }
3982
3639
  `
3983
3640
  );
3984
- var vs2 = import_core4.glsl`\
3985
- #version 300 es
3641
+ var vs = (
3642
+ /* glsl */
3643
+ `#version 300 es
3986
3644
 
3987
3645
  // in vec4 POSITION;
3988
3646
  in vec4 positions;
@@ -4019,18 +3677,21 @@ layout(0) positions: vec4; // in vec4 POSITION;
4019
3677
  #endif
4020
3678
 
4021
3679
  pbr_setPositionNormalTangentUV(positions, _NORMAL, _TANGENT, _TEXCOORD_0);
4022
- gl_Position = u_MVPMatrix * positions;
3680
+ gl_Position = pbrProjection.modelViewProjectionMatrix * positions;
4023
3681
  }
4024
- `;
4025
- var fs2 = import_core4.glsl`\
4026
- #version 300 es
3682
+ `
3683
+ );
3684
+ var fs = (
3685
+ /* glsl */
3686
+ `#version 300 es
4027
3687
  out vec4 fragmentColor;
4028
3688
 
4029
3689
  void main(void) {
4030
3690
  vec3 pos = pbr_vPosition;
4031
3691
  fragmentColor = pbr_filterColor(vec4(1.0));
4032
3692
  }
4033
- `;
3693
+ `
3694
+ );
4034
3695
  function createGLTFModel(device, options) {
4035
3696
  const { id, geometry, material, vertexCount, materialOptions, modelOptions } = options;
4036
3697
  const parsedMaterial = parsePBRMaterial(device, material, geometry.attributes, materialOptions);
@@ -4045,19 +3706,24 @@ layout(0) positions: vec4; // in vec4 POSITION;
4045
3706
  const modelProps = {
4046
3707
  id,
4047
3708
  source: SHADER,
4048
- vs: vs2,
4049
- fs: fs2,
3709
+ vs,
3710
+ fs,
4050
3711
  geometry,
4051
3712
  topology: geometry.topology,
4052
3713
  vertexCount,
4053
- modules: [pbr],
3714
+ modules: [import_shadertools.pbrMaterial],
4054
3715
  ...modelOptions,
4055
- bindings: { ...parsedMaterial.bindings, ...modelOptions.bindings },
4056
3716
  defines: { ...parsedMaterial.defines, ...modelOptions.defines },
4057
- parameters: { ...parameters, ...parsedMaterial.parameters, ...modelOptions.parameters },
4058
- uniforms: { ...parsedMaterial.uniforms, ...modelOptions.uniforms }
3717
+ parameters: { ...parameters, ...parsedMaterial.parameters, ...modelOptions.parameters }
4059
3718
  };
4060
3719
  const model = new import_engine2.Model(device, modelProps);
3720
+ const { camera, ...pbrMaterialProps } = {
3721
+ ...parsedMaterial.uniforms,
3722
+ ...modelOptions.uniforms,
3723
+ ...parsedMaterial.bindings,
3724
+ ...modelOptions.bindings
3725
+ };
3726
+ model.shaderInputs.setProps({ pbrMaterial: pbrMaterialProps, pbrProjection: { camera } });
4061
3727
  return new import_engine2.ModelNode({ managedResources, model });
4062
3728
  }
4063
3729
 
@@ -4096,8 +3762,8 @@ layout(0) positions: vec4; // in vec4 POSITION;
4096
3762
  this.options = { ...DEFAULT_OPTIONS, ...options };
4097
3763
  }
4098
3764
  instantiate(gltf) {
4099
- this.gltf = gltf;
4100
- const scenes = (gltf.scenes || []).map((scene) => this.createScene(scene));
3765
+ this.gltf = deepCopy(gltf);
3766
+ const scenes = (this.gltf.scenes || []).map((scene) => this.createScene(scene));
4101
3767
  return scenes;
4102
3768
  }
4103
3769
  createAnimator() {
@@ -4143,6 +3809,8 @@ layout(0) positions: vec4; // in vec4 POSITION;
4143
3809
  }
4144
3810
  gltfNode._node = node;
4145
3811
  }
3812
+ const topLevelNode = this.gltf.nodes.find((node) => node.id === gltfNode.id);
3813
+ topLevelNode._node = gltfNode._node;
4146
3814
  return gltfNode._node;
4147
3815
  }
4148
3816
  createMesh(gltfMesh) {
@@ -4219,6 +3887,22 @@ layout(0) positions: vec4; // in vec4 POSITION;
4219
3887
  return false;
4220
3888
  }
4221
3889
  };
3890
+ function deepCopy(object) {
3891
+ if (ArrayBuffer.isView(object) || object instanceof ArrayBuffer) {
3892
+ return object;
3893
+ }
3894
+ if (Array.isArray(object)) {
3895
+ return object.map(deepCopy);
3896
+ }
3897
+ if (object && typeof object === "object") {
3898
+ const result = {};
3899
+ for (const key in object) {
3900
+ result[key] = deepCopy(object[key]);
3901
+ }
3902
+ return result;
3903
+ }
3904
+ return object;
3905
+ }
4222
3906
 
4223
3907
  // src/gltf/create-gltf-objects.ts
4224
3908
  function createScenegraphsFromGLTF(device, gltf, options) {