minerender 2.1.0-alpha.65 → 2.1.0-alpha.67

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.
@@ -3006,16 +3006,17 @@ var init_UVMapper = __esm({
3006
3006
  positions[textureKey] = [x, y];
3007
3007
  const [width, height] = sizes[textureKey];
3008
3008
  const sequence = frames[textureKey];
3009
- const drawFrame = (index) => {
3009
+ const getFrameData = (index) => {
3010
3010
  const columns = texture.width / width;
3011
- image.putData(texture.getSectionData(
3011
+ return texture.getSectionData(
3012
3012
  index % columns * width,
3013
3013
  Math.floor(index / columns) * height,
3014
3014
  width,
3015
3015
  height
3016
- ), x, y);
3016
+ );
3017
3017
  };
3018
- drawFrame(sequence?.[0].index ?? 0);
3018
+ const firstFrame = getFrameData(sequence?.[0].index ?? 0);
3019
+ image.putData(firstFrame, x, y);
3019
3020
  if (texture.hasTransparency) {
3020
3021
  hasTransparency = true;
3021
3022
  }
@@ -3023,13 +3024,28 @@ var init_UVMapper = __esm({
3023
3024
  hasAnimation = true;
3024
3025
  let t = 0;
3025
3026
  let f = 0;
3027
+ const interpolated = metaMap[textureKey]?.animation?.interpolate ? image.context.createImageData(width, height) : void 0;
3028
+ let currentFrame = firstFrame;
3029
+ let nextFrame = interpolated ? getFrameData(sequence[1].index) : firstFrame;
3026
3030
  animatorFunctions[textureKey] = () => {
3027
- if (++t < sequence[f].time) return false;
3028
- t = 0;
3029
- const previous = sequence[f].index;
3030
- f = (f + 1) % sequence.length;
3031
- if (sequence[f].index === previous) return false;
3032
- drawFrame(sequence[f].index);
3031
+ if (++t >= sequence[f].time) {
3032
+ t = 0;
3033
+ const previous = sequence[f].index;
3034
+ f = (f + 1) % sequence.length;
3035
+ if (interpolated) {
3036
+ currentFrame = nextFrame;
3037
+ nextFrame = getFrameData(sequence[(f + 1) % sequence.length].index);
3038
+ }
3039
+ if (sequence[f].index === previous) return false;
3040
+ image.putData(interpolated ? currentFrame : getFrameData(sequence[f].index), x, y);
3041
+ return true;
3042
+ }
3043
+ if (!interpolated || sequence[f].index === sequence[(f + 1) % sequence.length].index) return false;
3044
+ const progress = Math.floor(Math.fround(Math.fround(t / sequence[f].time) * 1e3)) / 1e3;
3045
+ for (let i = 0; i < interpolated.data.length; i++) {
3046
+ interpolated.data[i] = currentFrame.data[i] + (nextFrame.data[i] - currentFrame.data[i]) * progress;
3047
+ }
3048
+ image.putData(interpolated, x, y);
3033
3049
  return true;
3034
3050
  };
3035
3051
  }
@@ -3582,7 +3598,7 @@ var init_InstanceReference = __esm({
3582
3598
  });
3583
3599
 
3584
3600
  // src/renderer/SceneObject.ts
3585
- import { Color as Color2, Euler as Euler4, InstancedBufferAttribute, InstancedMesh, MathUtils, Matrix4 as Matrix44, Mesh as Mesh3, Object3D as Object3D2, Quaternion as Quaternion3, Vector3 as Vector36 } from "three";
3601
+ import { Color as Color2, Euler as Euler4, InstancedBufferAttribute, InstancedMesh, Matrix4 as Matrix44, Mesh as Mesh3, Object3D as Object3D2, Quaternion as Quaternion3, Vector3 as Vector36 } from "three";
3586
3602
  function isSceneObject(obj) {
3587
3603
  return obj.isSceneObject;
3588
3604
  }
@@ -4018,6 +4034,7 @@ var init_SceneObject = __esm({
4018
4034
  dispose() {
4019
4035
  this.disposeAndRemoveAllChildren();
4020
4036
  this.notifyDirty();
4037
+ super.dispose();
4021
4038
  }
4022
4039
  disposeAndRemoveAllChildren() {
4023
4040
  if (this.instanceMesh) {
@@ -4231,6 +4248,7 @@ var init_EntityObject = __esm({
4231
4248
  else matrix.makeRotationFromEuler(new Euler5(...op.rotate, "ZYX"));
4232
4249
  modelRoot.matrix.multiply(matrix);
4233
4250
  }
4251
+ modelRoot.matrixWorldNeedsUpdate = true;
4234
4252
  modelRoot.matrixAutoUpdate = false;
4235
4253
  } else if (this.options.flip ?? true) {
4236
4254
  modelRoot.scale.set(-1, -1, 1);
@@ -5147,6 +5165,7 @@ var init_ModelObject = __esm({
5147
5165
  for (const part of parts) {
5148
5166
  const object = new EntityObject(part.model, { flip: false, wireframe: this.options.wireframe });
5149
5167
  object.matrix.copy(transform).multiply(part.transform);
5168
+ object.matrixWorldNeedsUpdate = true;
5150
5169
  object.matrixAutoUpdate = false;
5151
5170
  this.add(object);
5152
5171
  await object.init();
@@ -5818,16 +5837,26 @@ init_EntityObject();
5818
5837
  init_MineRenderError();
5819
5838
 
5820
5839
  // src/export/SceneExporter.ts
5821
- import { ClampToEdgeWrapping as ClampToEdgeWrapping2, Color as Color7, Float32BufferAttribute as Float32BufferAttribute3, Matrix4 as Matrix47, Mesh as Mesh5, MeshBasicMaterial as MeshBasicMaterial2, NearestFilter as NearestFilter3, RGBAFormat as RGBAFormat3, Scene as Scene4, Source as Source2, Texture as Texture4, UnsignedByteType } from "three";
5840
+ import { ClampToEdgeWrapping as ClampToEdgeWrapping2, Color as Color7, Float32BufferAttribute as Float32BufferAttribute3, Matrix4 as Matrix47, Mesh as Mesh4, MeshBasicMaterial as MeshBasicMaterial2, NearestFilter as NearestFilter3, RGBAFormat as RGBAFormat3, Scene as Scene3, TextureSource as TextureSource2, Texture as Texture3, UnsignedByteType } from "three";
5822
5841
 
5823
5842
  // ../../node_modules/three/examples/jsm/exporters/OBJExporter.js
5824
5843
  import {
5825
5844
  Color as Color4,
5845
+ ColorManagement,
5826
5846
  Matrix3,
5847
+ SRGBColorSpace as SRGBColorSpace3,
5827
5848
  Vector2 as Vector22,
5828
5849
  Vector3 as Vector37
5829
5850
  } from "three";
5830
5851
  var OBJExporter = class {
5852
+ /**
5853
+ * Parses the given 3D object and generates the OBJ output.
5854
+ *
5855
+ * If the 3D object is composed of multiple children and geometry, they are merged into a single mesh in the file.
5856
+ *
5857
+ * @param {Object3D} object - The 3D object to export.
5858
+ * @return {string} The exported OBJ.
5859
+ */
5831
5860
  parse(object) {
5832
5861
  let output = "";
5833
5862
  let indexVertex = 0;
@@ -5933,7 +5962,8 @@ var OBJExporter = class {
5933
5962
  vertex.applyMatrix4(points.matrixWorld);
5934
5963
  output += "v " + vertex.x + " " + vertex.y + " " + vertex.z;
5935
5964
  if (colors !== void 0) {
5936
- color.fromBufferAttribute(colors, i).convertLinearToSRGB();
5965
+ color.fromBufferAttribute(colors, i);
5966
+ ColorManagement.workingToColorSpace(color, SRGBColorSpace3);
5937
5967
  output += " " + color.r + " " + color.g + " " + color.b;
5938
5968
  }
5939
5969
  output += "\n";
@@ -5965,9 +5995,21 @@ var OBJExporter = class {
5965
5995
  import {
5966
5996
  Matrix3 as Matrix32,
5967
5997
  Vector3 as Vector38,
5968
- Color as Color5
5998
+ Color as Color5,
5999
+ ColorManagement as ColorManagement2,
6000
+ SRGBColorSpace as SRGBColorSpace4
5969
6001
  } from "three";
5970
6002
  var PLYExporter = class {
6003
+ /**
6004
+ * Parses the given 3D object and generates the PLY output.
6005
+ *
6006
+ * If the 3D object is composed of multiple children and geometry, they are merged into a single mesh in the file.
6007
+ *
6008
+ * @param {Object3D} object - The 3D object to export.
6009
+ * @param {PLYExporter~OnDone} onDone - A callback function that is executed when the export has finished.
6010
+ * @param {PLYExporter~Options} options - The export options.
6011
+ * @return {?(string|ArrayBuffer)} The exported PLY.
6012
+ */
5971
6013
  parse(object, onDone, options = {}) {
5972
6014
  function traverseMeshes(cb) {
5973
6015
  object.traverse(function(child) {
@@ -5984,14 +6026,23 @@ var PLYExporter = class {
5984
6026
  binary: false,
5985
6027
  excludeAttributes: [],
5986
6028
  // normal, uv, color, index
5987
- littleEndian: false
6029
+ littleEndian: false,
6030
+ customPropertyMapping: {}
5988
6031
  };
5989
6032
  options = Object.assign(defaultOptions, options);
5990
6033
  const excludeAttributes = options.excludeAttributes;
6034
+ const customPropertyMapping = options.customPropertyMapping;
6035
+ const customAttributeNames = Object.keys(customPropertyMapping);
5991
6036
  let includeIndices = true;
5992
6037
  let includeNormals = false;
5993
6038
  let includeColors = false;
5994
6039
  let includeUVs = false;
6040
+ let positionType = "float";
6041
+ let normalType = "float";
6042
+ let uvType = "float";
6043
+ let colorType = "uchar";
6044
+ const customTypes = {};
6045
+ for (const name of customAttributeNames) customTypes[name] = "float";
5995
6046
  let vertexCount = 0;
5996
6047
  let faceCount = 0;
5997
6048
  object.traverse(function(child) {
@@ -6008,9 +6059,23 @@ var PLYExporter = class {
6008
6059
  }
6009
6060
  vertexCount += vertices.count;
6010
6061
  faceCount += indices ? indices.count / 3 : vertices.count / 3;
6011
- if (normals !== void 0) includeNormals = true;
6012
- if (uvs !== void 0) includeUVs = true;
6013
- if (colors !== void 0) includeColors = true;
6062
+ positionType = getPlyType(vertices.array);
6063
+ if (normals !== void 0) {
6064
+ includeNormals = true;
6065
+ normalType = getPlyType(normals.array);
6066
+ }
6067
+ if (uvs !== void 0) {
6068
+ includeUVs = true;
6069
+ uvType = getPlyType(uvs.array);
6070
+ }
6071
+ if (colors !== void 0) {
6072
+ includeColors = true;
6073
+ colorType = getPlyType(colors.array);
6074
+ }
6075
+ for (const name of customAttributeNames) {
6076
+ const attr = geometry.getAttribute(name);
6077
+ if (attr !== void 0) customTypes[name] = getPlyType(attr.array);
6078
+ }
6014
6079
  } else if (child.isPoints) {
6015
6080
  const mesh = child;
6016
6081
  const geometry = mesh.geometry;
@@ -6018,8 +6083,19 @@ var PLYExporter = class {
6018
6083
  const normals = geometry.getAttribute("normal");
6019
6084
  const colors = geometry.getAttribute("color");
6020
6085
  vertexCount += vertices.count;
6021
- if (normals !== void 0) includeNormals = true;
6022
- if (colors !== void 0) includeColors = true;
6086
+ positionType = getPlyType(vertices.array);
6087
+ if (normals !== void 0) {
6088
+ includeNormals = true;
6089
+ normalType = getPlyType(normals.array);
6090
+ }
6091
+ if (colors !== void 0) {
6092
+ includeColors = true;
6093
+ colorType = getPlyType(colors.array);
6094
+ }
6095
+ for (const name of customAttributeNames) {
6096
+ const attr = geometry.getAttribute(name);
6097
+ if (attr !== void 0) customTypes[name] = getPlyType(attr.array);
6098
+ }
6023
6099
  includeIndices = false;
6024
6100
  }
6025
6101
  });
@@ -6038,18 +6114,33 @@ var PLYExporter = class {
6038
6114
  let header = `ply
6039
6115
  format ${options.binary ? options.littleEndian ? "binary_little_endian" : "binary_big_endian" : "ascii"} 1.0
6040
6116
  element vertex ${vertexCount}
6041
- property float x
6042
- property float y
6043
- property float z
6117
+ property ${positionType} x
6118
+ property ${positionType} y
6119
+ property ${positionType} z
6044
6120
  `;
6045
6121
  if (includeNormals === true) {
6046
- header += "property float nx\nproperty float ny\nproperty float nz\n";
6122
+ header += `property ${normalType} nx
6123
+ property ${normalType} ny
6124
+ property ${normalType} nz
6125
+ `;
6047
6126
  }
6048
6127
  if (includeUVs === true) {
6049
- header += "property float s\nproperty float t\n";
6128
+ header += `property ${uvType} s
6129
+ property ${uvType} t
6130
+ `;
6050
6131
  }
6051
6132
  if (includeColors === true) {
6052
- header += "property uchar red\nproperty uchar green\nproperty uchar blue\n";
6133
+ header += `property ${colorType} red
6134
+ property ${colorType} green
6135
+ property ${colorType} blue
6136
+ `;
6137
+ }
6138
+ for (const name of customAttributeNames) {
6139
+ const type = customTypes[name];
6140
+ for (const propName of customPropertyMapping[name]) {
6141
+ header += `property ${type} ${propName}
6142
+ `;
6143
+ }
6053
6144
  }
6054
6145
  if (includeIndices === true) {
6055
6146
  header += `element face ${faceCount}
@@ -6062,7 +6153,23 @@ property list uchar int vertex_index
6062
6153
  let result = null;
6063
6154
  if (options.binary === true) {
6064
6155
  const headerBin = new TextEncoder().encode(header);
6065
- const vertexListLength = vertexCount * (4 * 3 + (includeNormals ? 4 * 3 : 0) + (includeColors ? 3 : 0) + (includeUVs ? 4 * 2 : 0));
6156
+ const posWriter = getBinaryWriter(positionType);
6157
+ const normalWriter = includeNormals ? getBinaryWriter(normalType) : null;
6158
+ const uvWriter = includeUVs ? getBinaryWriter(uvType) : null;
6159
+ const colorWriter = includeColors ? getBinaryWriter(colorType) : null;
6160
+ const colorIsFloat = isFloatType(colorType);
6161
+ const colorScale = getColorScale(colorType);
6162
+ const customWriters = {};
6163
+ const customIsFloat = {};
6164
+ let customStride = 0;
6165
+ for (const name of customAttributeNames) {
6166
+ const type = customTypes[name];
6167
+ const writer = getBinaryWriter(type);
6168
+ customWriters[name] = writer;
6169
+ customIsFloat[name] = isFloatType(type);
6170
+ customStride += customPropertyMapping[name].length * writer.size;
6171
+ }
6172
+ const vertexListLength = vertexCount * (3 * posWriter.size + (includeNormals ? 3 * normalWriter.size : 0) + (includeUVs ? 2 * uvWriter.size : 0) + (includeColors ? 3 * colorWriter.size : 0) + customStride);
6066
6173
  const faceListLength = includeIndices ? faceCount * (indexByteCount * 3 + 1) : 0;
6067
6174
  const output = new DataView(new ArrayBuffer(headerBin.length + vertexListLength + faceListLength));
6068
6175
  new Uint8Array(output.buffer).set(headerBin, 0);
@@ -6079,60 +6186,76 @@ property list uchar int vertex_index
6079
6186
  for (let i = 0, l = vertices.count; i < l; i++) {
6080
6187
  vertex.fromBufferAttribute(vertices, i);
6081
6188
  vertex.applyMatrix4(mesh.matrixWorld);
6082
- output.setFloat32(vOffset, vertex.x, options.littleEndian);
6083
- vOffset += 4;
6084
- output.setFloat32(vOffset, vertex.y, options.littleEndian);
6085
- vOffset += 4;
6086
- output.setFloat32(vOffset, vertex.z, options.littleEndian);
6087
- vOffset += 4;
6189
+ posWriter.write(output, vOffset, vertex.x, options.littleEndian);
6190
+ vOffset += posWriter.size;
6191
+ posWriter.write(output, vOffset, vertex.y, options.littleEndian);
6192
+ vOffset += posWriter.size;
6193
+ posWriter.write(output, vOffset, vertex.z, options.littleEndian);
6194
+ vOffset += posWriter.size;
6088
6195
  if (includeNormals === true) {
6089
6196
  if (normals != null) {
6090
6197
  vertex.fromBufferAttribute(normals, i);
6091
6198
  vertex.applyMatrix3(normalMatrixWorld).normalize();
6092
- output.setFloat32(vOffset, vertex.x, options.littleEndian);
6093
- vOffset += 4;
6094
- output.setFloat32(vOffset, vertex.y, options.littleEndian);
6095
- vOffset += 4;
6096
- output.setFloat32(vOffset, vertex.z, options.littleEndian);
6097
- vOffset += 4;
6199
+ normalWriter.write(output, vOffset, vertex.x, options.littleEndian);
6200
+ vOffset += normalWriter.size;
6201
+ normalWriter.write(output, vOffset, vertex.y, options.littleEndian);
6202
+ vOffset += normalWriter.size;
6203
+ normalWriter.write(output, vOffset, vertex.z, options.littleEndian);
6204
+ vOffset += normalWriter.size;
6098
6205
  } else {
6099
- output.setFloat32(vOffset, 0, options.littleEndian);
6100
- vOffset += 4;
6101
- output.setFloat32(vOffset, 0, options.littleEndian);
6102
- vOffset += 4;
6103
- output.setFloat32(vOffset, 0, options.littleEndian);
6104
- vOffset += 4;
6206
+ normalWriter.write(output, vOffset, 0, options.littleEndian);
6207
+ vOffset += normalWriter.size;
6208
+ normalWriter.write(output, vOffset, 0, options.littleEndian);
6209
+ vOffset += normalWriter.size;
6210
+ normalWriter.write(output, vOffset, 0, options.littleEndian);
6211
+ vOffset += normalWriter.size;
6105
6212
  }
6106
6213
  }
6107
6214
  if (includeUVs === true) {
6108
6215
  if (uvs != null) {
6109
- output.setFloat32(vOffset, uvs.getX(i), options.littleEndian);
6110
- vOffset += 4;
6111
- output.setFloat32(vOffset, uvs.getY(i), options.littleEndian);
6112
- vOffset += 4;
6216
+ uvWriter.write(output, vOffset, uvs.getX(i), options.littleEndian);
6217
+ vOffset += uvWriter.size;
6218
+ uvWriter.write(output, vOffset, uvs.getY(i), options.littleEndian);
6219
+ vOffset += uvWriter.size;
6113
6220
  } else {
6114
- output.setFloat32(vOffset, 0, options.littleEndian);
6115
- vOffset += 4;
6116
- output.setFloat32(vOffset, 0, options.littleEndian);
6117
- vOffset += 4;
6221
+ uvWriter.write(output, vOffset, 0, options.littleEndian);
6222
+ vOffset += uvWriter.size;
6223
+ uvWriter.write(output, vOffset, 0, options.littleEndian);
6224
+ vOffset += uvWriter.size;
6118
6225
  }
6119
6226
  }
6120
6227
  if (includeColors === true) {
6121
6228
  if (colors != null) {
6122
- tempColor.fromBufferAttribute(colors, i).convertLinearToSRGB();
6123
- output.setUint8(vOffset, Math.floor(tempColor.r * 255));
6124
- vOffset += 1;
6125
- output.setUint8(vOffset, Math.floor(tempColor.g * 255));
6126
- vOffset += 1;
6127
- output.setUint8(vOffset, Math.floor(tempColor.b * 255));
6128
- vOffset += 1;
6229
+ tempColor.fromBufferAttribute(colors, i);
6230
+ ColorManagement2.workingToColorSpace(tempColor, SRGBColorSpace4);
6231
+ const r = colorIsFloat ? tempColor.r : Math.round(tempColor.r * colorScale);
6232
+ const g = colorIsFloat ? tempColor.g : Math.round(tempColor.g * colorScale);
6233
+ const b = colorIsFloat ? tempColor.b : Math.round(tempColor.b * colorScale);
6234
+ colorWriter.write(output, vOffset, r, options.littleEndian);
6235
+ vOffset += colorWriter.size;
6236
+ colorWriter.write(output, vOffset, g, options.littleEndian);
6237
+ vOffset += colorWriter.size;
6238
+ colorWriter.write(output, vOffset, b, options.littleEndian);
6239
+ vOffset += colorWriter.size;
6129
6240
  } else {
6130
- output.setUint8(vOffset, 255);
6131
- vOffset += 1;
6132
- output.setUint8(vOffset, 255);
6133
- vOffset += 1;
6134
- output.setUint8(vOffset, 255);
6135
- vOffset += 1;
6241
+ const white = colorIsFloat ? 1 : colorScale;
6242
+ colorWriter.write(output, vOffset, white, options.littleEndian);
6243
+ vOffset += colorWriter.size;
6244
+ colorWriter.write(output, vOffset, white, options.littleEndian);
6245
+ vOffset += colorWriter.size;
6246
+ colorWriter.write(output, vOffset, white, options.littleEndian);
6247
+ vOffset += colorWriter.size;
6248
+ }
6249
+ }
6250
+ for (const name of customAttributeNames) {
6251
+ const writer = customWriters[name];
6252
+ const propCount = customPropertyMapping[name].length;
6253
+ const attr = geometry.getAttribute(name);
6254
+ const isFloat = customIsFloat[name];
6255
+ for (let c = 0; c < propCount; c++) {
6256
+ const raw = attr != null ? getAttributeComponent(attr, i, c) : 0;
6257
+ writer.write(output, vOffset, isFloat ? raw : Math.round(raw), options.littleEndian);
6258
+ vOffset += writer.size;
6136
6259
  }
6137
6260
  }
6138
6261
  }
@@ -6168,6 +6291,14 @@ property list uchar int vertex_index
6168
6291
  let writtenVertices = 0;
6169
6292
  let vertexList = "";
6170
6293
  let faceList = "";
6294
+ const positionIsFloat = isFloatType(positionType);
6295
+ const normalIsFloat = isFloatType(normalType);
6296
+ const uvIsFloat = isFloatType(uvType);
6297
+ const colorIsFloat = isFloatType(colorType);
6298
+ const colorScale = getColorScale(colorType);
6299
+ const customIsFloat = {};
6300
+ for (const name of customAttributeNames) customIsFloat[name] = isFloatType(customTypes[name]);
6301
+ const encode = (v, isFloat) => isFloat ? v : Math.round(v);
6171
6302
  traverseMeshes(function(mesh, geometry) {
6172
6303
  const vertices = geometry.getAttribute("position");
6173
6304
  const normals = geometry.getAttribute("normal");
@@ -6178,29 +6309,43 @@ property list uchar int vertex_index
6178
6309
  for (let i = 0, l = vertices.count; i < l; i++) {
6179
6310
  vertex.fromBufferAttribute(vertices, i);
6180
6311
  vertex.applyMatrix4(mesh.matrixWorld);
6181
- let line = vertex.x + " " + vertex.y + " " + vertex.z;
6312
+ let line = encode(vertex.x, positionIsFloat) + " " + encode(vertex.y, positionIsFloat) + " " + encode(vertex.z, positionIsFloat);
6182
6313
  if (includeNormals === true) {
6183
6314
  if (normals != null) {
6184
6315
  vertex.fromBufferAttribute(normals, i);
6185
6316
  vertex.applyMatrix3(normalMatrixWorld).normalize();
6186
- line += " " + vertex.x + " " + vertex.y + " " + vertex.z;
6317
+ line += " " + encode(vertex.x, normalIsFloat) + " " + encode(vertex.y, normalIsFloat) + " " + encode(vertex.z, normalIsFloat);
6187
6318
  } else {
6188
6319
  line += " 0 0 0";
6189
6320
  }
6190
6321
  }
6191
6322
  if (includeUVs === true) {
6192
6323
  if (uvs != null) {
6193
- line += " " + uvs.getX(i) + " " + uvs.getY(i);
6324
+ line += " " + encode(uvs.getX(i), uvIsFloat) + " " + encode(uvs.getY(i), uvIsFloat);
6194
6325
  } else {
6195
6326
  line += " 0 0";
6196
6327
  }
6197
6328
  }
6198
6329
  if (includeColors === true) {
6199
6330
  if (colors != null) {
6200
- tempColor.fromBufferAttribute(colors, i).convertLinearToSRGB();
6201
- line += " " + Math.floor(tempColor.r * 255) + " " + Math.floor(tempColor.g * 255) + " " + Math.floor(tempColor.b * 255);
6331
+ tempColor.fromBufferAttribute(colors, i);
6332
+ ColorManagement2.workingToColorSpace(tempColor, SRGBColorSpace4);
6333
+ const r = colorIsFloat ? tempColor.r : Math.round(tempColor.r * colorScale);
6334
+ const g = colorIsFloat ? tempColor.g : Math.round(tempColor.g * colorScale);
6335
+ const b = colorIsFloat ? tempColor.b : Math.round(tempColor.b * colorScale);
6336
+ line += ` ${r} ${g} ${b}`;
6202
6337
  } else {
6203
- line += " 255 255 255";
6338
+ const white = colorIsFloat ? 1 : colorScale;
6339
+ line += ` ${white} ${white} ${white}`;
6340
+ }
6341
+ }
6342
+ for (const name of customAttributeNames) {
6343
+ const propCount = customPropertyMapping[name].length;
6344
+ const attr = geometry.getAttribute(name);
6345
+ const isFloat = customIsFloat[name];
6346
+ for (let c = 0; c < propCount; c++) {
6347
+ const raw = attr != null ? getAttributeComponent(attr, i, c) : 0;
6348
+ line += " " + encode(raw, isFloat);
6204
6349
  }
6205
6350
  }
6206
6351
  vertexList += line + "\n";
@@ -6230,6 +6375,62 @@ property list uchar int vertex_index
6230
6375
  return result;
6231
6376
  }
6232
6377
  };
6378
+ function getPlyType(array) {
6379
+ if (array instanceof Int8Array) return "char";
6380
+ if (array instanceof Uint8Array || array instanceof Uint8ClampedArray) return "uchar";
6381
+ if (array instanceof Int16Array) return "short";
6382
+ if (array instanceof Uint16Array) return "ushort";
6383
+ if (array instanceof Int32Array) return "int";
6384
+ if (array instanceof Uint32Array) return "uint";
6385
+ if (array instanceof Float32Array) return "float";
6386
+ if (array instanceof Float64Array) return "double";
6387
+ return "float";
6388
+ }
6389
+ function getBinaryWriter(type) {
6390
+ switch (type) {
6391
+ case "char":
6392
+ return { write: (dv, at, v) => dv.setInt8(at, v), size: 1 };
6393
+ case "uchar":
6394
+ return { write: (dv, at, v) => dv.setUint8(at, v), size: 1 };
6395
+ case "short":
6396
+ return { write: (dv, at, v, le) => dv.setInt16(at, v, le), size: 2 };
6397
+ case "ushort":
6398
+ return { write: (dv, at, v, le) => dv.setUint16(at, v, le), size: 2 };
6399
+ case "int":
6400
+ return { write: (dv, at, v, le) => dv.setInt32(at, v, le), size: 4 };
6401
+ case "uint":
6402
+ return { write: (dv, at, v, le) => dv.setUint32(at, v, le), size: 4 };
6403
+ case "float":
6404
+ return { write: (dv, at, v, le) => dv.setFloat32(at, v, le), size: 4 };
6405
+ case "double":
6406
+ return { write: (dv, at, v, le) => dv.setFloat64(at, v, le), size: 8 };
6407
+ }
6408
+ }
6409
+ function isFloatType(type) {
6410
+ return type === "float" || type === "double";
6411
+ }
6412
+ function getAttributeComponent(attr, i, c) {
6413
+ switch (c) {
6414
+ case 0:
6415
+ return attr.getX(i);
6416
+ case 1:
6417
+ return attr.getY(i);
6418
+ case 2:
6419
+ return attr.getZ(i);
6420
+ case 3:
6421
+ return attr.getW(i);
6422
+ }
6423
+ }
6424
+ function getColorScale(type) {
6425
+ switch (type) {
6426
+ case "uchar":
6427
+ return 255;
6428
+ case "ushort":
6429
+ return 65535;
6430
+ default:
6431
+ return 1;
6432
+ }
6433
+ }
6233
6434
 
6234
6435
  // ../../node_modules/three/examples/jsm/exporters/GLTFExporter.js
6235
6436
  import {
@@ -6243,7 +6444,7 @@ import {
6243
6444
  LinearFilter,
6244
6445
  LinearMipmapLinearFilter,
6245
6446
  LinearMipmapNearestFilter,
6246
- MathUtils as MathUtils2,
6447
+ MathUtils,
6247
6448
  Matrix4 as Matrix46,
6248
6449
  MirroredRepeatWrapping,
6249
6450
  NearestFilter as NearestFilter2,
@@ -6252,84 +6453,15 @@ import {
6252
6453
  PropertyBinding,
6253
6454
  RGBAFormat as RGBAFormat2,
6254
6455
  RepeatWrapping as RepeatWrapping2,
6255
- Scene as Scene3,
6256
- Source,
6257
- SRGBColorSpace as SRGBColorSpace4,
6456
+ Scene as Scene2,
6457
+ SRGBColorSpace as SRGBColorSpace5,
6458
+ TextureSource,
6258
6459
  CompressedTexture,
6259
6460
  Vector3 as Vector39,
6260
- Quaternion as Quaternion4
6461
+ Quaternion as Quaternion4,
6462
+ REVISION,
6463
+ ImageUtils
6261
6464
  } from "three";
6262
-
6263
- // ../../node_modules/three/examples/jsm/utils/TextureUtils.js
6264
- import {
6265
- PlaneGeometry,
6266
- ShaderMaterial as ShaderMaterial2,
6267
- Uniform,
6268
- Mesh as Mesh4,
6269
- PerspectiveCamera,
6270
- Scene as Scene2,
6271
- WebGLRenderer,
6272
- Texture as Texture3,
6273
- SRGBColorSpace as SRGBColorSpace3
6274
- } from "three";
6275
- var _renderer;
6276
- var fullscreenQuadGeometry;
6277
- var fullscreenQuadMaterial;
6278
- var fullscreenQuad;
6279
- function decompress(texture, maxTextureSize = Infinity, renderer = null) {
6280
- if (!fullscreenQuadGeometry) fullscreenQuadGeometry = new PlaneGeometry(2, 2, 1, 1);
6281
- if (!fullscreenQuadMaterial) fullscreenQuadMaterial = new ShaderMaterial2({
6282
- uniforms: { blitTexture: new Uniform(texture) },
6283
- vertexShader: `
6284
- varying vec2 vUv;
6285
- void main(){
6286
- vUv = uv;
6287
- gl_Position = vec4(position.xy * 1.0,0.,.999999);
6288
- }`,
6289
- fragmentShader: `
6290
- uniform sampler2D blitTexture;
6291
- varying vec2 vUv;
6292
-
6293
- void main(){
6294
- gl_FragColor = vec4(vUv.xy, 0, 1);
6295
-
6296
- #ifdef IS_SRGB
6297
- gl_FragColor = LinearTosRGB( texture2D( blitTexture, vUv) );
6298
- #else
6299
- gl_FragColor = texture2D( blitTexture, vUv);
6300
- #endif
6301
- }`
6302
- });
6303
- fullscreenQuadMaterial.uniforms.blitTexture.value = texture;
6304
- fullscreenQuadMaterial.defines.IS_SRGB = texture.colorSpace == SRGBColorSpace3;
6305
- fullscreenQuadMaterial.needsUpdate = true;
6306
- if (!fullscreenQuad) {
6307
- fullscreenQuad = new Mesh4(fullscreenQuadGeometry, fullscreenQuadMaterial);
6308
- fullscreenQuad.frustrumCulled = false;
6309
- }
6310
- const _camera = new PerspectiveCamera();
6311
- const _scene = new Scene2();
6312
- _scene.add(fullscreenQuad);
6313
- if (!renderer) {
6314
- renderer = _renderer = new WebGLRenderer({ antialias: false });
6315
- }
6316
- renderer.setSize(Math.min(texture.image.width, maxTextureSize), Math.min(texture.image.height, maxTextureSize));
6317
- renderer.clear();
6318
- renderer.render(_scene, _camera);
6319
- const readableTexture = new Texture3(renderer.domElement);
6320
- readableTexture.minFilter = texture.minFilter;
6321
- readableTexture.magFilter = texture.magFilter;
6322
- readableTexture.wrapS = texture.wrapS;
6323
- readableTexture.wrapT = texture.wrapT;
6324
- readableTexture.name = texture.name;
6325
- if (_renderer) {
6326
- _renderer.dispose();
6327
- _renderer = null;
6328
- }
6329
- return readableTexture;
6330
- }
6331
-
6332
- // ../../node_modules/three/examples/jsm/exporters/GLTFExporter.js
6333
6465
  var KHR_mesh_quantization_ExtraAttrTypes = {
6334
6466
  POSITION: [
6335
6467
  "byte",
@@ -6359,7 +6491,11 @@ var KHR_mesh_quantization_ExtraAttrTypes = {
6359
6491
  ]
6360
6492
  };
6361
6493
  var GLTFExporter = class {
6494
+ /**
6495
+ * Constructs a new glTF exporter.
6496
+ */
6362
6497
  constructor() {
6498
+ this.textureUtils = null;
6363
6499
  this.pluginCallbacks = [];
6364
6500
  this.register(function(writer) {
6365
6501
  return new GLTFLightExtension(writer);
@@ -6382,6 +6518,9 @@ var GLTFExporter = class {
6382
6518
  this.register(function(writer) {
6383
6519
  return new GLTFMaterialsClearcoatExtension(writer);
6384
6520
  });
6521
+ this.register(function(writer) {
6522
+ return new GLTFMaterialsDispersionExtension(writer);
6523
+ });
6385
6524
  this.register(function(writer) {
6386
6525
  return new GLTFMaterialsIridescenceExtension(writer);
6387
6526
  });
@@ -6394,16 +6533,33 @@ var GLTFExporter = class {
6394
6533
  this.register(function(writer) {
6395
6534
  return new GLTFMaterialsEmissiveStrengthExtension(writer);
6396
6535
  });
6536
+ this.register(function(writer) {
6537
+ return new GLTFMaterialsBumpExtension(writer);
6538
+ });
6397
6539
  this.register(function(writer) {
6398
6540
  return new GLTFMeshGpuInstancing(writer);
6399
6541
  });
6400
6542
  }
6543
+ /**
6544
+ * Registers a plugin callback. This API is internally used to implement the various
6545
+ * glTF extensions but can also used by third-party code to add additional logic
6546
+ * to the exporter.
6547
+ *
6548
+ * @param {function(writer:GLTFWriter)} callback - The callback function to register.
6549
+ * @return {GLTFExporter} A reference to this exporter.
6550
+ */
6401
6551
  register(callback) {
6402
6552
  if (this.pluginCallbacks.indexOf(callback) === -1) {
6403
6553
  this.pluginCallbacks.push(callback);
6404
6554
  }
6405
6555
  return this;
6406
6556
  }
6557
+ /**
6558
+ * Unregisters a plugin callback.
6559
+ *
6560
+ * @param {Function} callback - The callback function to unregister.
6561
+ * @return {GLTFExporter} A reference to this exporter.
6562
+ */
6407
6563
  unregister(callback) {
6408
6564
  if (this.pluginCallbacks.indexOf(callback) !== -1) {
6409
6565
  this.pluginCallbacks.splice(this.pluginCallbacks.indexOf(callback), 1);
@@ -6411,11 +6567,25 @@ var GLTFExporter = class {
6411
6567
  return this;
6412
6568
  }
6413
6569
  /**
6414
- * Parse scenes and generate GLTF output
6415
- * @param {Scene or [THREE.Scenes]} input Scene or Array of THREE.Scenes
6416
- * @param {Function} onDone Callback on completed
6417
- * @param {Function} onError Callback on errors
6418
- * @param {Object} options options
6570
+ * Sets the texture utils for this exporter. Only relevant when compressed textures have to be exported.
6571
+ *
6572
+ * Depending on whether you use {@link WebGLRenderer} or {@link WebGPURenderer}, you must inject the
6573
+ * corresponding texture utils {@link module:WebGLTextureUtils} or {@link module:WebGPUTextureUtils}.
6574
+ *
6575
+ * @param {WebGLTextureUtils|WebGPUTextureUtils} utils - The texture utils.
6576
+ * @return {GLTFExporter} A reference to this exporter.
6577
+ */
6578
+ setTextureUtils(utils) {
6579
+ this.textureUtils = utils;
6580
+ return this;
6581
+ }
6582
+ /**
6583
+ * Parses the given scenes and generates the glTF output.
6584
+ *
6585
+ * @param {Scene|Array<Scene>} input - A scene or an array of scenes.
6586
+ * @param {GLTFExporter~OnDone} onDone - A callback function that is executed when the export has finished.
6587
+ * @param {GLTFExporter~OnError} onError - A callback function that is executed when an error happens.
6588
+ * @param {GLTFExporter~Options} options - options
6419
6589
  */
6420
6590
  parse(input, onDone, onError, options) {
6421
6591
  const writer = new GLTFWriter();
@@ -6424,8 +6594,16 @@ var GLTFExporter = class {
6424
6594
  plugins.push(this.pluginCallbacks[i](writer));
6425
6595
  }
6426
6596
  writer.setPlugins(plugins);
6427
- writer.write(input, onDone, options).catch(onError);
6597
+ writer.setTextureUtils(this.textureUtils);
6598
+ writer.writeAsync(input, onDone, options).catch(onError);
6428
6599
  }
6600
+ /**
6601
+ * Async version of {@link GLTFExporter#parse}.
6602
+ *
6603
+ * @param {Scene|Array<Scene>} input - A scene or an array of scenes.
6604
+ * @param {GLTFExporter~Options} options - options.
6605
+ * @return {Promise<ArrayBuffer|string>} A Promise that resolved with the exported glTF data.
6606
+ */
6429
6607
  parseAsync(input, options) {
6430
6608
  const scope = this;
6431
6609
  return new Promise(function(resolve, reject) {
@@ -6511,7 +6689,7 @@ function getMinMax(attribute, start, count) {
6511
6689
  else if (a === 2) value = attribute.getZ(i);
6512
6690
  else if (a === 3) value = attribute.getW(i);
6513
6691
  if (attribute.normalized === true) {
6514
- value = MathUtils2.normalize(value, attribute.array);
6692
+ value = MathUtils.normalize(value, attribute.array);
6515
6693
  }
6516
6694
  }
6517
6695
  output.min[a] = Math.min(output.min[a], value);
@@ -6544,19 +6722,20 @@ function getCanvas() {
6544
6722
  return document.createElement("canvas");
6545
6723
  }
6546
6724
  function getToBlobPromise(canvas, mimeType) {
6547
- if (canvas.toBlob !== void 0) {
6725
+ if (typeof OffscreenCanvas !== "undefined" && canvas instanceof OffscreenCanvas) {
6726
+ let quality;
6727
+ if (mimeType === "image/jpeg") {
6728
+ quality = 0.92;
6729
+ } else if (mimeType === "image/webp") {
6730
+ quality = 0.8;
6731
+ }
6732
+ return canvas.convertToBlob({
6733
+ type: mimeType,
6734
+ quality
6735
+ });
6736
+ } else {
6548
6737
  return new Promise((resolve) => canvas.toBlob(resolve, mimeType));
6549
6738
  }
6550
- let quality;
6551
- if (mimeType === "image/jpeg") {
6552
- quality = 0.92;
6553
- } else if (mimeType === "image/webp") {
6554
- quality = 0.8;
6555
- }
6556
- return canvas.convertToBlob({
6557
- type: mimeType,
6558
- quality
6559
- });
6560
6739
  }
6561
6740
  var GLTFWriter = class {
6562
6741
  constructor() {
@@ -6575,7 +6754,7 @@ var GLTFWriter = class {
6575
6754
  this.json = {
6576
6755
  asset: {
6577
6756
  version: "2.0",
6578
- generator: "THREE.GLTFExporter"
6757
+ generator: "THREE.GLTFExporter r" + REVISION
6579
6758
  }
6580
6759
  };
6581
6760
  this.cache = {
@@ -6584,19 +6763,25 @@ var GLTFWriter = class {
6584
6763
  attributesNormalized: /* @__PURE__ */ new Map(),
6585
6764
  materials: /* @__PURE__ */ new Map(),
6586
6765
  textures: /* @__PURE__ */ new Map(),
6587
- images: /* @__PURE__ */ new Map()
6766
+ images: /* @__PURE__ */ new Map(),
6767
+ normalMaps: /* @__PURE__ */ new Map()
6588
6768
  };
6769
+ this.textureUtils = null;
6589
6770
  }
6590
6771
  setPlugins(plugins) {
6591
6772
  this.plugins = plugins;
6592
6773
  }
6774
+ setTextureUtils(utils) {
6775
+ this.textureUtils = utils;
6776
+ }
6593
6777
  /**
6594
6778
  * Parse scenes and generate GLTF output
6595
- * @param {Scene or [THREE.Scenes]} input Scene or Array of THREE.Scenes
6596
- * @param {Function} onDone Callback on completed
6597
- * @param {Object} options options
6779
+ *
6780
+ * @param {Scene|Array<Scene>} input Scene or Array of THREE.Scenes
6781
+ * @param {Function} onDone Callback on completed
6782
+ * @param {Object} options options
6598
6783
  */
6599
- async write(input, onDone, options = {}) {
6784
+ async writeAsync(input, onDone, options = {}) {
6600
6785
  this.options = Object.assign({
6601
6786
  // default options
6602
6787
  binary: false,
@@ -6604,12 +6789,13 @@ var GLTFWriter = class {
6604
6789
  onlyVisible: true,
6605
6790
  maxTextureSize: Infinity,
6606
6791
  animations: [],
6607
- includeCustomExtensions: false
6792
+ includeCustomExtensions: false,
6793
+ copyright: null
6608
6794
  }, options);
6609
6795
  if (this.options.animations.length > 0) {
6610
6796
  this.options.trs = true;
6611
6797
  }
6612
- this.processInput(input);
6798
+ await this.processInputAsync(input);
6613
6799
  await Promise.all(this.pending);
6614
6800
  const writer = this;
6615
6801
  const buffers = writer.buffers;
@@ -6623,6 +6809,7 @@ var GLTFWriter = class {
6623
6809
  if (extensionsUsedList.length > 0) json.extensionsUsed = extensionsUsedList;
6624
6810
  if (extensionsRequiredList.length > 0) json.extensionsRequired = extensionsRequiredList;
6625
6811
  if (json.buffers && json.buffers.length > 0) json.buffers[0].byteLength = blob.size;
6812
+ if (options.copyright) json.asset.copyright = options.copyright;
6626
6813
  if (options.binary === true) {
6627
6814
  const reader = new FileReader();
6628
6815
  reader.readAsArrayBuffer(blob);
@@ -6671,7 +6858,7 @@ var GLTFWriter = class {
6671
6858
  /**
6672
6859
  * Serializes a userData.
6673
6860
  *
6674
- * @param {THREE.Object3D|THREE.Material} object
6861
+ * @param {THREE.Object3D|THREE.Material|THREE.BufferGeometry|THREE.AnimationClip} object
6675
6862
  * @param {Object} objectDef
6676
6863
  */
6677
6864
  serializeUserData(object, objectDef) {
@@ -6695,8 +6882,10 @@ var GLTFWriter = class {
6695
6882
  }
6696
6883
  /**
6697
6884
  * Returns ids for buffer attributes.
6698
- * @param {Object} object
6699
- * @return {Integer}
6885
+ *
6886
+ * @param {Object} attribute
6887
+ * @param {boolean} [isRelativeCopy=false]
6888
+ * @return {number} An integer
6700
6889
  */
6701
6890
  getUID(attribute, isRelativeCopy = false) {
6702
6891
  if (this.uids.has(attribute) === false) {
@@ -6712,7 +6901,7 @@ var GLTFWriter = class {
6712
6901
  * Checks if normal attribute values are normalized.
6713
6902
  *
6714
6903
  * @param {BufferAttribute} normal
6715
- * @returns {Boolean}
6904
+ * @returns {boolean}
6716
6905
  */
6717
6906
  isNormalizedNormalAttribute(normal) {
6718
6907
  const cache = this.cache;
@@ -6775,10 +6964,10 @@ var GLTFWriter = class {
6775
6964
  this.extensionsUsed["KHR_texture_transform"] = true;
6776
6965
  }
6777
6966
  }
6778
- buildMetalRoughTexture(metalnessMap, roughnessMap) {
6967
+ async buildMetalRoughTextureAsync(metalnessMap, roughnessMap) {
6779
6968
  if (metalnessMap === roughnessMap) return metalnessMap;
6780
6969
  function getEncodingConversion(map) {
6781
- if (map.colorSpace === SRGBColorSpace4) {
6970
+ if (map.colorSpace === SRGBColorSpace5) {
6782
6971
  return function SRGBToLinear(c) {
6783
6972
  return c < 0.04045 ? c * 0.0773993808 : Math.pow(c * 0.9478672986 + 0.0521327014, 2.4);
6784
6973
  };
@@ -6787,12 +6976,11 @@ var GLTFWriter = class {
6787
6976
  return c;
6788
6977
  };
6789
6978
  }
6790
- console.warn("THREE.GLTFExporter: Merged metalnessMap and roughnessMap textures.");
6791
6979
  if (metalnessMap instanceof CompressedTexture) {
6792
- metalnessMap = decompress(metalnessMap);
6980
+ metalnessMap = await this.decompressTextureAsync(metalnessMap);
6793
6981
  }
6794
6982
  if (roughnessMap instanceof CompressedTexture) {
6795
- roughnessMap = decompress(roughnessMap);
6983
+ roughnessMap = await this.decompressTextureAsync(roughnessMap);
6796
6984
  }
6797
6985
  const metalness = metalnessMap ? metalnessMap.image : null;
6798
6986
  const roughness = roughnessMap ? roughnessMap.image : null;
@@ -6801,7 +6989,9 @@ var GLTFWriter = class {
6801
6989
  const canvas = getCanvas();
6802
6990
  canvas.width = width;
6803
6991
  canvas.height = height;
6804
- const context = canvas.getContext("2d");
6992
+ const context = canvas.getContext("2d", {
6993
+ willReadFrequently: true
6994
+ });
6805
6995
  context.fillStyle = "#00ffff";
6806
6996
  context.fillRect(0, 0, width, height);
6807
6997
  const composite = context.getImageData(0, 0, width, height);
@@ -6824,18 +7014,60 @@ var GLTFWriter = class {
6824
7014
  context.putImageData(composite, 0, 0);
6825
7015
  const reference = metalnessMap || roughnessMap;
6826
7016
  const texture = reference.clone();
6827
- texture.source = new Source(canvas);
7017
+ texture.source = new TextureSource(canvas);
6828
7018
  texture.colorSpace = NoColorSpace;
6829
7019
  texture.channel = (metalnessMap || roughnessMap).channel;
6830
7020
  if (metalnessMap && roughnessMap && metalnessMap.channel !== roughnessMap.channel) {
6831
7021
  console.warn("THREE.GLTFExporter: UV channels for metalnessMap and roughnessMap textures must match.");
6832
7022
  }
7023
+ console.warn("THREE.GLTFExporter: Merged metalnessMap and roughnessMap textures.");
6833
7024
  return texture;
6834
7025
  }
7026
+ /**
7027
+ * Builds a copy of the given normal map with the red and/or green channels
7028
+ * inverted (`color = 255 - color`). This is used to bake the sign of
7029
+ * `material.normalScale` and the tangent-space convention into the texture,
7030
+ * since glTF only supports OpenGL-style normal maps with a univariate,
7031
+ * positive scale.
7032
+ *
7033
+ * @param {THREE.Texture} normalMap The source normal map.
7034
+ * @param {boolean} flipX Whether to invert the red channel (normal X).
7035
+ * @param {boolean} flipY Whether to invert the green channel (normal Y).
7036
+ * @return {Promise<THREE.Texture>} The derived normal map texture.
7037
+ */
7038
+ async buildNormalMapTextureAsync(normalMap, flipX, flipY) {
7039
+ if (normalMap instanceof CompressedTexture) {
7040
+ normalMap = await this.decompressTextureAsync(normalMap);
7041
+ }
7042
+ const image = normalMap.image;
7043
+ const canvas = getCanvas();
7044
+ canvas.width = image.width;
7045
+ canvas.height = image.height;
7046
+ const context = canvas.getContext("2d", {
7047
+ willReadFrequently: true
7048
+ });
7049
+ context.drawImage(image, 0, 0, canvas.width, canvas.height);
7050
+ const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
7051
+ const data = imageData.data;
7052
+ for (let i = 0; i < data.length; i += 4) {
7053
+ if (flipX) data[i + 0] = 255 - data[i + 0];
7054
+ if (flipY) data[i + 1] = 255 - data[i + 1];
7055
+ }
7056
+ context.putImageData(imageData, 0, 0);
7057
+ const texture = normalMap.clone();
7058
+ texture.source = new TextureSource(canvas);
7059
+ return texture;
7060
+ }
7061
+ async decompressTextureAsync(texture, maxTextureSize = Infinity) {
7062
+ if (this.textureUtils === null) {
7063
+ throw new Error("THREE.GLTFExporter: setTextureUtils() must be called to process compressed textures.");
7064
+ }
7065
+ return await this.textureUtils.decompress(texture, maxTextureSize);
7066
+ }
6835
7067
  /**
6836
7068
  * Process a buffer to append to the default one.
6837
- * @param {ArrayBuffer} buffer
6838
- * @return {Integer}
7069
+ * @param {ArrayBuffer} buffer
7070
+ * @return {0}
6839
7071
  */
6840
7072
  processBuffer(buffer) {
6841
7073
  const json = this.json;
@@ -6846,11 +7078,11 @@ var GLTFWriter = class {
6846
7078
  }
6847
7079
  /**
6848
7080
  * Process and generate a BufferView
6849
- * @param {BufferAttribute} attribute
6850
- * @param {number} componentType
6851
- * @param {number} start
6852
- * @param {number} count
6853
- * @param {number} target (Optional) Target usage of the BufferView
7081
+ * @param {BufferAttribute} attribute
7082
+ * @param {number} componentType
7083
+ * @param {number} start
7084
+ * @param {number} count
7085
+ * @param {number} [target] Target usage of the BufferView
6854
7086
  * @return {Object}
6855
7087
  */
6856
7088
  processBufferView(attribute, componentType, start, count, target) {
@@ -6869,7 +7101,11 @@ var GLTFWriter = class {
6869
7101
  default:
6870
7102
  componentSize = 4;
6871
7103
  }
6872
- const byteLength = getPaddedBufferSize(count * attribute.itemSize * componentSize);
7104
+ let byteStride = attribute.itemSize * componentSize;
7105
+ if (target === WEBGL_CONSTANTS.ARRAY_BUFFER) {
7106
+ byteStride = Math.ceil(byteStride / 4) * 4;
7107
+ }
7108
+ const byteLength = getPaddedBufferSize(count * byteStride);
6873
7109
  const dataView = new DataView(new ArrayBuffer(byteLength));
6874
7110
  let offset = 0;
6875
7111
  for (let i = start; i < start + count; i++) {
@@ -6883,7 +7119,7 @@ var GLTFWriter = class {
6883
7119
  else if (a === 2) value = attribute.getZ(i);
6884
7120
  else if (a === 3) value = attribute.getW(i);
6885
7121
  if (attribute.normalized === true) {
6886
- value = MathUtils2.normalize(value, attribute.array);
7122
+ value = MathUtils.normalize(value, attribute.array);
6887
7123
  }
6888
7124
  }
6889
7125
  if (componentType === WEBGL_CONSTANTS.FLOAT) {
@@ -6903,6 +7139,9 @@ var GLTFWriter = class {
6903
7139
  }
6904
7140
  offset += componentSize;
6905
7141
  }
7142
+ if (offset % byteStride !== 0) {
7143
+ offset += byteStride - offset % byteStride;
7144
+ }
6906
7145
  }
6907
7146
  const bufferViewDef = {
6908
7147
  buffer: this.processBuffer(dataView.buffer),
@@ -6911,7 +7150,7 @@ var GLTFWriter = class {
6911
7150
  };
6912
7151
  if (target !== void 0) bufferViewDef.target = target;
6913
7152
  if (target === WEBGL_CONSTANTS.ARRAY_BUFFER) {
6914
- bufferViewDef.byteStride = attribute.itemSize * componentSize;
7153
+ bufferViewDef.byteStride = byteStride;
6915
7154
  }
6916
7155
  this.byteOffset += byteLength;
6917
7156
  json.bufferViews.push(bufferViewDef);
@@ -6924,7 +7163,7 @@ var GLTFWriter = class {
6924
7163
  /**
6925
7164
  * Process and generate a BufferView from an image Blob.
6926
7165
  * @param {Blob} blob
6927
- * @return {Promise<Integer>}
7166
+ * @return {Promise<number>} An integer
6928
7167
  */
6929
7168
  processBufferViewImage(blob) {
6930
7169
  const writer = this;
@@ -6947,11 +7186,11 @@ var GLTFWriter = class {
6947
7186
  }
6948
7187
  /**
6949
7188
  * Process attribute to generate an accessor
6950
- * @param {BufferAttribute} attribute Attribute to process
6951
- * @param {THREE.BufferGeometry} geometry (Optional) Geometry used for truncated draw range
6952
- * @param {Integer} start (Optional)
6953
- * @param {Integer} count (Optional)
6954
- * @return {Integer|null} Index of the processed accessor on the "accessors" array
7189
+ * @param {BufferAttribute} attribute Attribute to process
7190
+ * @param {?BufferGeometry} [geometry] Geometry used for truncated draw range
7191
+ * @param {number} [start=0]
7192
+ * @param {number} [count=Infinity]
7193
+ * @return {?number} Index of the processed accessor on the "accessors" array
6955
7194
  */
6956
7195
  processAccessor(attribute, geometry, start, count) {
6957
7196
  const json = this.json;
@@ -7005,11 +7244,11 @@ var GLTFWriter = class {
7005
7244
  }
7006
7245
  /**
7007
7246
  * Process image
7008
- * @param {Image} image to process
7009
- * @param {Integer} format of the image (RGBAFormat)
7010
- * @param {Boolean} flipY before writing out the image
7011
- * @param {String} mimeType export format
7012
- * @return {Integer} Index of the processed texture in the "images" array
7247
+ * @param {Image} image to process
7248
+ * @param {number} format Identifier of the format (RGBAFormat)
7249
+ * @param {boolean} flipY before writing out the image
7250
+ * @param {string} mimeType export format
7251
+ * @return {number} Index of the processed texture in the "images" array
7013
7252
  */
7014
7253
  processImage(image, format, flipY, mimeType = "image/png") {
7015
7254
  if (image !== null) {
@@ -7027,7 +7266,9 @@ var GLTFWriter = class {
7027
7266
  const canvas = getCanvas();
7028
7267
  canvas.width = Math.min(image.width, options.maxTextureSize);
7029
7268
  canvas.height = Math.min(image.height, options.maxTextureSize);
7030
- const ctx = canvas.getContext("2d");
7269
+ const ctx = canvas.getContext("2d", {
7270
+ willReadFrequently: true
7271
+ });
7031
7272
  if (flipY === true) {
7032
7273
  ctx.translate(0, canvas.height);
7033
7274
  ctx.scale(1, -1);
@@ -7048,7 +7289,11 @@ var GLTFWriter = class {
7048
7289
  }
7049
7290
  ctx.putImageData(new ImageData(data, image.width, image.height), 0, 0);
7050
7291
  } else {
7051
- ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
7292
+ if (typeof HTMLImageElement !== "undefined" && image instanceof HTMLImageElement || typeof HTMLCanvasElement !== "undefined" && image instanceof HTMLCanvasElement || typeof ImageBitmap !== "undefined" && image instanceof ImageBitmap || typeof OffscreenCanvas !== "undefined" && image instanceof OffscreenCanvas) {
7293
+ ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
7294
+ } else {
7295
+ throw new Error("THREE.GLTFExporter: Invalid image type. Use HTMLImageElement, HTMLCanvasElement, ImageBitmap or OffscreenCanvas.");
7296
+ }
7052
7297
  }
7053
7298
  if (options.binary === true) {
7054
7299
  pending.push(
@@ -7057,15 +7302,7 @@ var GLTFWriter = class {
7057
7302
  })
7058
7303
  );
7059
7304
  } else {
7060
- if (canvas.toDataURL !== void 0) {
7061
- imageDef.uri = canvas.toDataURL(mimeType);
7062
- } else {
7063
- pending.push(
7064
- getToBlobPromise(canvas, mimeType).then((blob) => new FileReader().readAsDataURL(blob)).then((dataURL) => {
7065
- imageDef.uri = dataURL;
7066
- })
7067
- );
7068
- }
7305
+ imageDef.uri = ImageUtils.getDataURL(canvas, mimeType);
7069
7306
  }
7070
7307
  const index = json.images.push(imageDef) - 1;
7071
7308
  cachedImages[key] = index;
@@ -7076,8 +7313,8 @@ var GLTFWriter = class {
7076
7313
  }
7077
7314
  /**
7078
7315
  * Process sampler
7079
- * @param {Texture} map Texture to process
7080
- * @return {Integer} Index of the processed texture in the "samplers" array
7316
+ * @param {Texture} map Texture to process
7317
+ * @return {number} Index of the processed texture in the "samplers" array
7081
7318
  */
7082
7319
  processSampler(map) {
7083
7320
  const json = this.json;
@@ -7092,10 +7329,10 @@ var GLTFWriter = class {
7092
7329
  }
7093
7330
  /**
7094
7331
  * Process texture
7095
- * @param {Texture} map Map to process
7096
- * @return {Integer} Index of the processed texture in the "textures" array
7332
+ * @param {Texture} map Map to process
7333
+ * @return {Promise<number>} Index of the processed texture in the "textures" array
7097
7334
  */
7098
- processTexture(map) {
7335
+ async processTextureAsync(map) {
7099
7336
  const writer = this;
7100
7337
  const options = writer.options;
7101
7338
  const cache = this.cache;
@@ -7103,17 +7340,26 @@ var GLTFWriter = class {
7103
7340
  if (cache.textures.has(map)) return cache.textures.get(map);
7104
7341
  if (!json.textures) json.textures = [];
7105
7342
  if (map instanceof CompressedTexture) {
7106
- map = decompress(map, options.maxTextureSize);
7343
+ map = await this.decompressTextureAsync(map, options.maxTextureSize);
7107
7344
  }
7108
- let mimeType = map.userData.mimeType;
7109
- if (mimeType === "image/webp") mimeType = "image/png";
7345
+ const mimeType = map.userData.mimeType;
7346
+ const imageIndex = this.processImage(map.image, map.format, map.flipY, mimeType);
7110
7347
  const textureDef = {
7111
- sampler: this.processSampler(map),
7112
- source: this.processImage(map.image, map.format, map.flipY, mimeType)
7348
+ sampler: this.processSampler(map)
7113
7349
  };
7350
+ if (mimeType === "image/webp") {
7351
+ textureDef.extensions = textureDef.extensions || {};
7352
+ textureDef.extensions["EXT_texture_webp"] = {
7353
+ source: imageIndex
7354
+ };
7355
+ this.extensionsUsed["EXT_texture_webp"] = true;
7356
+ this.extensionsRequired["EXT_texture_webp"] = true;
7357
+ } else {
7358
+ textureDef.source = imageIndex;
7359
+ }
7114
7360
  if (map.name) textureDef.name = map.name;
7115
- this._invokeAll(function(ext) {
7116
- ext.writeTexture && ext.writeTexture(map, textureDef);
7361
+ await this._invokeAllAsync(async function(ext) {
7362
+ ext.writeTexture && await ext.writeTexture(map, textureDef);
7117
7363
  });
7118
7364
  const index = json.textures.push(textureDef) - 1;
7119
7365
  cache.textures.set(map, index);
@@ -7121,13 +7367,16 @@ var GLTFWriter = class {
7121
7367
  }
7122
7368
  /**
7123
7369
  * Process material
7124
- * @param {THREE.Material} material Material to process
7125
- * @return {Integer|null} Index of the processed material in the "materials" array
7370
+ * @param {THREE.Material} material Material to process
7371
+ * @param {THREE.BufferGeometry} [geometry] Geometry the material is used with.
7372
+ * @return {Promise<?number>} Index of the processed material in the "materials" array
7126
7373
  */
7127
- processMaterial(material) {
7374
+ async processMaterialAsync(material, geometry) {
7128
7375
  const cache = this.cache;
7129
7376
  const json = this.json;
7130
- if (cache.materials.has(material)) return cache.materials.get(material);
7377
+ const hasTangent = geometry !== void 0 && geometry.hasAttribute("tangent");
7378
+ const cacheKey = material.normalMap ? material.uuid + ":" + hasTangent : material.uuid;
7379
+ if (cache.materials.has(cacheKey)) return cache.materials.get(cacheKey);
7131
7380
  if (material.isShaderMaterial) {
7132
7381
  console.warn("GLTFExporter: THREE.ShaderMaterial not supported.");
7133
7382
  return null;
@@ -7145,21 +7394,21 @@ var GLTFWriter = class {
7145
7394
  materialDef.pbrMetallicRoughness.metallicFactor = material.metalness;
7146
7395
  materialDef.pbrMetallicRoughness.roughnessFactor = material.roughness;
7147
7396
  } else {
7148
- materialDef.pbrMetallicRoughness.metallicFactor = 0.5;
7149
- materialDef.pbrMetallicRoughness.roughnessFactor = 0.5;
7397
+ materialDef.pbrMetallicRoughness.metallicFactor = 0;
7398
+ materialDef.pbrMetallicRoughness.roughnessFactor = 1;
7150
7399
  }
7151
7400
  if (material.metalnessMap || material.roughnessMap) {
7152
- const metalRoughTexture = this.buildMetalRoughTexture(material.metalnessMap, material.roughnessMap);
7401
+ const metalRoughTexture = await this.buildMetalRoughTextureAsync(material.metalnessMap, material.roughnessMap);
7153
7402
  const metalRoughMapDef = {
7154
- index: this.processTexture(metalRoughTexture),
7155
- channel: metalRoughTexture.channel
7403
+ index: await this.processTextureAsync(metalRoughTexture),
7404
+ texCoord: metalRoughTexture.channel
7156
7405
  };
7157
7406
  this.applyTextureTransform(metalRoughMapDef, metalRoughTexture);
7158
7407
  materialDef.pbrMetallicRoughness.metallicRoughnessTexture = metalRoughMapDef;
7159
7408
  }
7160
7409
  if (material.map) {
7161
7410
  const baseColorMapDef = {
7162
- index: this.processTexture(material.map),
7411
+ index: await this.processTextureAsync(material.map),
7163
7412
  texCoord: material.map.channel
7164
7413
  };
7165
7414
  this.applyTextureTransform(baseColorMapDef, material.map);
@@ -7173,7 +7422,7 @@ var GLTFWriter = class {
7173
7422
  }
7174
7423
  if (material.emissiveMap) {
7175
7424
  const emissiveMapDef = {
7176
- index: this.processTexture(material.emissiveMap),
7425
+ index: await this.processTextureAsync(material.emissiveMap),
7177
7426
  texCoord: material.emissiveMap.channel
7178
7427
  };
7179
7428
  this.applyTextureTransform(emissiveMapDef, material.emissiveMap);
@@ -7181,19 +7430,32 @@ var GLTFWriter = class {
7181
7430
  }
7182
7431
  }
7183
7432
  if (material.normalMap) {
7433
+ const normalScale = material.normalScale;
7434
+ const flipX = normalScale.x < 0;
7435
+ const flipY = hasTangent ? normalScale.y < 0 : normalScale.y > 0;
7436
+ let normalMap = material.normalMap;
7437
+ if (flipX || flipY) {
7438
+ if (cache.normalMaps.has(material.normalMap) === false) cache.normalMaps.set(material.normalMap, {});
7439
+ const cachedVariants = cache.normalMaps.get(material.normalMap);
7440
+ const cacheKey2 = `${flipX}:${flipY}`;
7441
+ if (cachedVariants[cacheKey2] === void 0) {
7442
+ cachedVariants[cacheKey2] = await this.buildNormalMapTextureAsync(material.normalMap, flipX, flipY);
7443
+ }
7444
+ normalMap = cachedVariants[cacheKey2];
7445
+ }
7184
7446
  const normalMapDef = {
7185
- index: this.processTexture(material.normalMap),
7447
+ index: await this.processTextureAsync(normalMap),
7186
7448
  texCoord: material.normalMap.channel
7187
7449
  };
7188
- if (material.normalScale && material.normalScale.x !== 1) {
7189
- normalMapDef.scale = material.normalScale.x;
7450
+ if (Math.abs(normalScale.x) !== 1) {
7451
+ normalMapDef.scale = Math.abs(normalScale.x);
7190
7452
  }
7191
7453
  this.applyTextureTransform(normalMapDef, material.normalMap);
7192
7454
  materialDef.normalTexture = normalMapDef;
7193
7455
  }
7194
7456
  if (material.aoMap) {
7195
7457
  const occlusionMapDef = {
7196
- index: this.processTexture(material.aoMap),
7458
+ index: await this.processTextureAsync(material.aoMap),
7197
7459
  texCoord: material.aoMap.channel
7198
7460
  };
7199
7461
  if (material.aoMapIntensity !== 1) {
@@ -7213,19 +7475,19 @@ var GLTFWriter = class {
7213
7475
  if (material.side === DoubleSide2) materialDef.doubleSided = true;
7214
7476
  if (material.name !== "") materialDef.name = material.name;
7215
7477
  this.serializeUserData(material, materialDef);
7216
- this._invokeAll(function(ext) {
7217
- ext.writeMaterial && ext.writeMaterial(material, materialDef);
7478
+ await this._invokeAllAsync(async function(ext) {
7479
+ ext.writeMaterialAsync && await ext.writeMaterialAsync(material, materialDef);
7218
7480
  });
7219
7481
  const index = json.materials.push(materialDef) - 1;
7220
- cache.materials.set(material, index);
7482
+ cache.materials.set(cacheKey, index);
7221
7483
  return index;
7222
7484
  }
7223
7485
  /**
7224
7486
  * Process mesh
7225
- * @param {THREE.Mesh} mesh Mesh to process
7226
- * @return {Integer|null} Index of the processed mesh in the "meshes" array
7487
+ * @param {THREE.Mesh} mesh Mesh to process
7488
+ * @return {Promise<?number>} Index of the processed mesh in the "meshes" array
7227
7489
  */
7228
- processMesh(mesh) {
7490
+ async processMeshAsync(mesh) {
7229
7491
  const cache = this.cache;
7230
7492
  const json = this.json;
7231
7493
  const meshCacheKeyParts = [mesh.geometry.uuid];
@@ -7275,7 +7537,7 @@ var GLTFWriter = class {
7275
7537
  const attribute = geometry.attributes[attributeName];
7276
7538
  attributeName = nameConversion[attributeName] || attributeName.toUpperCase();
7277
7539
  const validVertexAttributes = /^(POSITION|NORMAL|TANGENT|TEXCOORD_\d+|COLOR_\d+|JOINTS_\d+|WEIGHTS_\d+)$/;
7278
- if (!validVertexAttributes.test(attributeName)) attributeName = "_" + attributeName;
7540
+ if (!validVertexAttributes.test(attributeName) && !attributeName.startsWith("_")) attributeName = "_" + attributeName;
7279
7541
  if (cache.attributes.has(this.getUID(attribute))) {
7280
7542
  attributes[attributeName] = cache.attributes.get(this.getUID(attribute));
7281
7543
  continue;
@@ -7284,7 +7546,10 @@ var GLTFWriter = class {
7284
7546
  const array = attribute.array;
7285
7547
  if (attributeName === "JOINTS_0" && !(array instanceof Uint16Array) && !(array instanceof Uint8Array)) {
7286
7548
  console.warn('GLTFExporter: Attribute "skinIndex" converted to type UNSIGNED_SHORT.');
7287
- modifiedAttribute = new BufferAttribute3(new Uint16Array(array), attribute.itemSize, attribute.normalized);
7549
+ modifiedAttribute = GLTFExporter.Utils.toTypedBufferAttribute(attribute, Uint16Array);
7550
+ } else if ((array instanceof Uint32Array || array instanceof Int32Array) && !attributeName.startsWith("_")) {
7551
+ console.warn(`GLTFExporter: Attribute "${attributeName}" converted to type FLOAT.`);
7552
+ modifiedAttribute = GLTFExporter.Utils.toTypedBufferAttribute(attribute, Float32Array);
7288
7553
  }
7289
7554
  const accessor = this.processAccessor(modifiedAttribute || attribute, geometry);
7290
7555
  if (accessor !== null) {
@@ -7350,6 +7615,15 @@ var GLTFWriter = class {
7350
7615
  }
7351
7616
  const isMultiMaterial = Array.isArray(mesh.material);
7352
7617
  if (isMultiMaterial && geometry.groups.length === 0) return null;
7618
+ let didForceIndices = false;
7619
+ if (isMultiMaterial && geometry.index === null) {
7620
+ const indices = [];
7621
+ for (let i = 0, il = geometry.attributes.position.count; i < il; i++) {
7622
+ indices[i] = i;
7623
+ }
7624
+ geometry.setIndex(indices);
7625
+ didForceIndices = true;
7626
+ }
7353
7627
  const materials = isMultiMaterial ? mesh.material : [mesh.material];
7354
7628
  const groups = isMultiMaterial ? geometry.groups : [{ materialIndex: 0, start: void 0, count: void 0 }];
7355
7629
  for (let i = 0, il = groups.length; i < il; i++) {
@@ -7372,13 +7646,16 @@ var GLTFWriter = class {
7372
7646
  }
7373
7647
  if (primitive.indices === null) delete primitive.indices;
7374
7648
  }
7375
- const material = this.processMaterial(materials[groups[i].materialIndex]);
7649
+ const material = await this.processMaterialAsync(materials[groups[i].materialIndex], geometry);
7376
7650
  if (material !== null) primitive.material = material;
7377
7651
  primitives.push(primitive);
7378
7652
  }
7653
+ if (didForceIndices === true) {
7654
+ geometry.setIndex(null);
7655
+ }
7379
7656
  meshDef.primitives = primitives;
7380
7657
  if (!json.meshes) json.meshes = [];
7381
- this._invokeAll(function(ext) {
7658
+ await this._invokeAllAsync(function(ext) {
7382
7659
  ext.writeMesh && ext.writeMesh(mesh, meshDef);
7383
7660
  });
7384
7661
  const index = json.meshes.push(meshDef) - 1;
@@ -7424,8 +7701,8 @@ var GLTFWriter = class {
7424
7701
  }
7425
7702
  /**
7426
7703
  * Process camera
7427
- * @param {THREE.Camera} camera Camera to process
7428
- * @return {Integer} Index of the processed mesh in the "camera" array
7704
+ * @param {THREE.Camera} camera Camera to process
7705
+ * @return {number} Index of the processed mesh in the "camera" array
7429
7706
  */
7430
7707
  processCamera(camera) {
7431
7708
  const json = this.json;
@@ -7444,7 +7721,7 @@ var GLTFWriter = class {
7444
7721
  } else {
7445
7722
  cameraDef.perspective = {
7446
7723
  aspectRatio: camera.aspect,
7447
- yfov: MathUtils2.degToRad(camera.fov),
7724
+ yfov: MathUtils.degToRad(camera.fov),
7448
7725
  zfar: camera.far <= 0 ? 1e-3 : camera.far,
7449
7726
  znear: camera.near < 0 ? 0 : camera.near
7450
7727
  };
@@ -7460,7 +7737,7 @@ var GLTFWriter = class {
7460
7737
  *
7461
7738
  * @param {THREE.AnimationClip} clip
7462
7739
  * @param {THREE.Object3D} root
7463
- * @return {number|null}
7740
+ * @return {?number}
7464
7741
  */
7465
7742
  processAnimation(clip, root) {
7466
7743
  const json = this.json;
@@ -7484,7 +7761,7 @@ var GLTFWriter = class {
7484
7761
  }
7485
7762
  if (!trackNode || !trackProperty) {
7486
7763
  console.warn('THREE.GLTFExporter: Could not export animation track "%s".', track.name);
7487
- return null;
7764
+ continue;
7488
7765
  }
7489
7766
  const inputItemSize = 1;
7490
7767
  let outputItemSize = track.values.length / track.times.length;
@@ -7513,16 +7790,18 @@ var GLTFWriter = class {
7513
7790
  }
7514
7791
  });
7515
7792
  }
7516
- json.animations.push({
7793
+ const animationDef = {
7517
7794
  name: clip.name || "clip_" + json.animations.length,
7518
7795
  samplers,
7519
7796
  channels
7520
- });
7797
+ };
7798
+ this.serializeUserData(clip, animationDef);
7799
+ json.animations.push(animationDef);
7521
7800
  return json.animations.length - 1;
7522
7801
  }
7523
7802
  /**
7524
7803
  * @param {THREE.Object3D} object
7525
- * @return {number|null}
7804
+ * @return {?number}
7526
7805
  */
7527
7806
  processSkin(object) {
7528
7807
  const json = this.json;
@@ -7551,14 +7830,17 @@ var GLTFWriter = class {
7551
7830
  }
7552
7831
  /**
7553
7832
  * Process Object3D node
7554
- * @param {THREE.Object3D} node Object3D to processNode
7555
- * @return {Integer} Index of the node in the nodes list
7833
+ * @param {THREE.Object3D} object Object3D to processNodeAsync
7834
+ * @return {Promise<number>} Index of the node in the nodes list
7556
7835
  */
7557
- processNode(object) {
7836
+ async processNodeAsync(object) {
7558
7837
  const json = this.json;
7559
7838
  const options = this.options;
7560
7839
  const nodeMap = this.nodeMap;
7561
7840
  if (!json.nodes) json.nodes = [];
7841
+ if (object.pivot !== null) {
7842
+ return await this._processNodeWithPivotAsync(object);
7843
+ }
7562
7844
  const nodeDef = {};
7563
7845
  if (options.trs) {
7564
7846
  const rotation = object.quaternion.toArray();
@@ -7584,35 +7866,98 @@ var GLTFWriter = class {
7584
7866
  if (object.name !== "") nodeDef.name = String(object.name);
7585
7867
  this.serializeUserData(object, nodeDef);
7586
7868
  if (object.isMesh || object.isLine || object.isPoints) {
7587
- const meshIndex = this.processMesh(object);
7869
+ const meshIndex = await this.processMeshAsync(object);
7588
7870
  if (meshIndex !== null) nodeDef.mesh = meshIndex;
7589
7871
  } else if (object.isCamera) {
7590
7872
  nodeDef.camera = this.processCamera(object);
7591
7873
  }
7592
7874
  if (object.isSkinnedMesh) this.skins.push(object);
7875
+ const nodeIndex = json.nodes.push(nodeDef) - 1;
7876
+ nodeMap.set(object, nodeIndex);
7593
7877
  if (object.children.length > 0) {
7594
7878
  const children = [];
7595
7879
  for (let i = 0, l = object.children.length; i < l; i++) {
7596
7880
  const child = object.children[i];
7597
7881
  if (child.visible || options.onlyVisible === false) {
7598
- const nodeIndex2 = this.processNode(child);
7599
- if (nodeIndex2 !== null) children.push(nodeIndex2);
7882
+ const childNodeIndex = await this.processNodeAsync(child);
7883
+ if (childNodeIndex !== null) children.push(childNodeIndex);
7600
7884
  }
7601
7885
  }
7602
7886
  if (children.length > 0) nodeDef.children = children;
7603
7887
  }
7604
- this._invokeAll(function(ext) {
7888
+ await this._invokeAllAsync(function(ext) {
7605
7889
  ext.writeNode && ext.writeNode(object, nodeDef);
7606
7890
  });
7607
- const nodeIndex = json.nodes.push(nodeDef) - 1;
7608
- nodeMap.set(object, nodeIndex);
7609
7891
  return nodeIndex;
7610
7892
  }
7893
+ /**
7894
+ * Process Object3D node with pivot using container approach
7895
+ * @param {THREE.Object3D} object Object3D with pivot
7896
+ * @return {Promise<number>} Index of the container node
7897
+ */
7898
+ async _processNodeWithPivotAsync(object) {
7899
+ const json = this.json;
7900
+ const options = this.options;
7901
+ const nodeMap = this.nodeMap;
7902
+ const pivot = object.pivot;
7903
+ const containerDef = {};
7904
+ const rotation = object.quaternion.toArray();
7905
+ const position = [
7906
+ object.position.x + pivot.x,
7907
+ object.position.y + pivot.y,
7908
+ object.position.z + pivot.z
7909
+ ];
7910
+ const scale = object.scale.toArray();
7911
+ if (!equalArray(rotation, [0, 0, 0, 1])) {
7912
+ containerDef.rotation = rotation;
7913
+ }
7914
+ if (!equalArray(position, [0, 0, 0])) {
7915
+ containerDef.translation = position;
7916
+ }
7917
+ if (!equalArray(scale, [1, 1, 1])) {
7918
+ containerDef.scale = scale;
7919
+ }
7920
+ containerDef.extras = { pivot: pivot.toArray() };
7921
+ if (object.name !== "") containerDef.name = String(object.name);
7922
+ this.serializeUserData(object, containerDef);
7923
+ const containerIndex = json.nodes.push(containerDef) - 1;
7924
+ nodeMap.set(object, containerIndex);
7925
+ const childDef = {};
7926
+ const childPosition = [-pivot.x, -pivot.y, -pivot.z];
7927
+ if (!equalArray(childPosition, [0, 0, 0])) {
7928
+ childDef.translation = childPosition;
7929
+ }
7930
+ if (object.isMesh || object.isLine || object.isPoints) {
7931
+ const meshIndex = await this.processMeshAsync(object);
7932
+ if (meshIndex !== null) childDef.mesh = meshIndex;
7933
+ } else if (object.isCamera) {
7934
+ childDef.camera = this.processCamera(object);
7935
+ }
7936
+ if (object.isSkinnedMesh) this.skins.push(object);
7937
+ const childIndex = json.nodes.push(childDef) - 1;
7938
+ const containerChildren = [childIndex];
7939
+ if (object.children.length > 0) {
7940
+ const grandchildren = [];
7941
+ for (let i = 0, l = object.children.length; i < l; i++) {
7942
+ const child = object.children[i];
7943
+ if (child.visible || options.onlyVisible === false) {
7944
+ const childNodeIndex = await this.processNodeAsync(child);
7945
+ if (childNodeIndex !== null) grandchildren.push(childNodeIndex);
7946
+ }
7947
+ }
7948
+ if (grandchildren.length > 0) childDef.children = grandchildren;
7949
+ }
7950
+ containerDef.children = containerChildren;
7951
+ await this._invokeAllAsync(function(ext) {
7952
+ ext.writeNode && ext.writeNode(object, containerDef);
7953
+ });
7954
+ return containerIndex;
7955
+ }
7611
7956
  /**
7612
7957
  * Process Scene
7613
- * @param {Scene} node Scene to process
7958
+ * @param {Scene} scene Scene to process
7614
7959
  */
7615
- processScene(scene) {
7960
+ async processSceneAsync(scene) {
7616
7961
  const json = this.json;
7617
7962
  const options = this.options;
7618
7963
  if (!json.scenes) {
@@ -7626,7 +7971,7 @@ var GLTFWriter = class {
7626
7971
  for (let i = 0, l = scene.children.length; i < l; i++) {
7627
7972
  const child = scene.children[i];
7628
7973
  if (child.visible || options.onlyVisible === false) {
7629
- const nodeIndex = this.processNode(child);
7974
+ const nodeIndex = await this.processNodeAsync(child);
7630
7975
  if (nodeIndex !== null) nodes.push(nodeIndex);
7631
7976
  }
7632
7977
  }
@@ -7635,47 +7980,58 @@ var GLTFWriter = class {
7635
7980
  }
7636
7981
  /**
7637
7982
  * Creates a Scene to hold a list of objects and parse it
7638
- * @param {Array} objects List of objects to process
7983
+ * @param {Array<THREE.Object3D>} objects List of objects to process
7639
7984
  */
7640
- processObjects(objects) {
7641
- const scene = new Scene3();
7985
+ async processObjectsAsync(objects) {
7986
+ const scene = new Scene2();
7642
7987
  scene.name = "AuxScene";
7643
7988
  for (let i = 0; i < objects.length; i++) {
7644
7989
  scene.children.push(objects[i]);
7645
7990
  }
7646
- this.processScene(scene);
7991
+ await this.processSceneAsync(scene);
7647
7992
  }
7648
7993
  /**
7649
7994
  * @param {THREE.Object3D|Array<THREE.Object3D>} input
7650
7995
  */
7651
- processInput(input) {
7996
+ async processInputAsync(input) {
7652
7997
  const options = this.options;
7653
7998
  input = input instanceof Array ? input : [input];
7654
- this._invokeAll(function(ext) {
7999
+ await this._invokeAllAsync(function(ext) {
7655
8000
  ext.beforeParse && ext.beforeParse(input);
7656
8001
  });
7657
8002
  const objectsWithoutScene = [];
7658
8003
  for (let i = 0; i < input.length; i++) {
7659
- if (input[i] instanceof Scene3) {
7660
- this.processScene(input[i]);
8004
+ if (input[i] instanceof Scene2) {
8005
+ await this.processSceneAsync(input[i]);
7661
8006
  } else {
7662
8007
  objectsWithoutScene.push(input[i]);
7663
8008
  }
7664
8009
  }
7665
- if (objectsWithoutScene.length > 0) this.processObjects(objectsWithoutScene);
8010
+ if (objectsWithoutScene.length > 0) {
8011
+ await this.processObjectsAsync(objectsWithoutScene);
8012
+ }
7666
8013
  for (let i = 0; i < this.skins.length; ++i) {
7667
8014
  this.processSkin(this.skins[i]);
7668
8015
  }
7669
- for (let i = 0; i < options.animations.length; ++i) {
7670
- this.processAnimation(options.animations[i], input[0]);
8016
+ if (input.length === 1) {
8017
+ for (let i = 0; i < options.animations.length; ++i) {
8018
+ this.processAnimation(options.animations[i], input[0]);
8019
+ }
8020
+ } else {
8021
+ for (let i = 0; i < input.length; i++) {
8022
+ const animations = options.animations[i] || [];
8023
+ for (let j = 0; j < animations.length; ++j) {
8024
+ this.processAnimation(animations[j], input[i]);
8025
+ }
8026
+ }
7671
8027
  }
7672
- this._invokeAll(function(ext) {
8028
+ await this._invokeAllAsync(function(ext) {
7673
8029
  ext.afterParse && ext.afterParse(input);
7674
8030
  });
7675
8031
  }
7676
- _invokeAll(func) {
8032
+ async _invokeAllAsync(func) {
7677
8033
  for (let i = 0, il = this.plugins.length; i < il; i++) {
7678
- func(this.plugins[i]);
8034
+ await func(this.plugins[i]);
7679
8035
  }
7680
8036
  }
7681
8037
  };
@@ -7731,7 +8087,7 @@ var GLTFMaterialsUnlitExtension = class {
7731
8087
  this.writer = writer;
7732
8088
  this.name = "KHR_materials_unlit";
7733
8089
  }
7734
- writeMaterial(material, materialDef) {
8090
+ async writeMaterialAsync(material, materialDef) {
7735
8091
  if (!material.isMeshBasicMaterial) return;
7736
8092
  const writer = this.writer;
7737
8093
  const extensionsUsed = writer.extensionsUsed;
@@ -7747,7 +8103,7 @@ var GLTFMaterialsClearcoatExtension = class {
7747
8103
  this.writer = writer;
7748
8104
  this.name = "KHR_materials_clearcoat";
7749
8105
  }
7750
- writeMaterial(material, materialDef) {
8106
+ async writeMaterialAsync(material, materialDef) {
7751
8107
  if (!material.isMeshPhysicalMaterial || material.clearcoat === 0) return;
7752
8108
  const writer = this.writer;
7753
8109
  const extensionsUsed = writer.extensionsUsed;
@@ -7755,7 +8111,7 @@ var GLTFMaterialsClearcoatExtension = class {
7755
8111
  extensionDef.clearcoatFactor = material.clearcoat;
7756
8112
  if (material.clearcoatMap) {
7757
8113
  const clearcoatMapDef = {
7758
- index: writer.processTexture(material.clearcoatMap),
8114
+ index: await writer.processTextureAsync(material.clearcoatMap),
7759
8115
  texCoord: material.clearcoatMap.channel
7760
8116
  };
7761
8117
  writer.applyTextureTransform(clearcoatMapDef, material.clearcoatMap);
@@ -7764,7 +8120,7 @@ var GLTFMaterialsClearcoatExtension = class {
7764
8120
  extensionDef.clearcoatRoughnessFactor = material.clearcoatRoughness;
7765
8121
  if (material.clearcoatRoughnessMap) {
7766
8122
  const clearcoatRoughnessMapDef = {
7767
- index: writer.processTexture(material.clearcoatRoughnessMap),
8123
+ index: await writer.processTextureAsync(material.clearcoatRoughnessMap),
7768
8124
  texCoord: material.clearcoatRoughnessMap.channel
7769
8125
  };
7770
8126
  writer.applyTextureTransform(clearcoatRoughnessMapDef, material.clearcoatRoughnessMap);
@@ -7772,9 +8128,10 @@ var GLTFMaterialsClearcoatExtension = class {
7772
8128
  }
7773
8129
  if (material.clearcoatNormalMap) {
7774
8130
  const clearcoatNormalMapDef = {
7775
- index: writer.processTexture(material.clearcoatNormalMap),
8131
+ index: await writer.processTextureAsync(material.clearcoatNormalMap),
7776
8132
  texCoord: material.clearcoatNormalMap.channel
7777
8133
  };
8134
+ if (material.clearcoatNormalScale.x !== 1) clearcoatNormalMapDef.scale = material.clearcoatNormalScale.x;
7778
8135
  writer.applyTextureTransform(clearcoatNormalMapDef, material.clearcoatNormalMap);
7779
8136
  extensionDef.clearcoatNormalTexture = clearcoatNormalMapDef;
7780
8137
  }
@@ -7783,12 +8140,28 @@ var GLTFMaterialsClearcoatExtension = class {
7783
8140
  extensionsUsed[this.name] = true;
7784
8141
  }
7785
8142
  };
8143
+ var GLTFMaterialsDispersionExtension = class {
8144
+ constructor(writer) {
8145
+ this.writer = writer;
8146
+ this.name = "KHR_materials_dispersion";
8147
+ }
8148
+ async writeMaterialAsync(material, materialDef) {
8149
+ if (!material.isMeshPhysicalMaterial || material.dispersion === 0) return;
8150
+ const writer = this.writer;
8151
+ const extensionsUsed = writer.extensionsUsed;
8152
+ const extensionDef = {};
8153
+ extensionDef.dispersion = material.dispersion;
8154
+ materialDef.extensions = materialDef.extensions || {};
8155
+ materialDef.extensions[this.name] = extensionDef;
8156
+ extensionsUsed[this.name] = true;
8157
+ }
8158
+ };
7786
8159
  var GLTFMaterialsIridescenceExtension = class {
7787
8160
  constructor(writer) {
7788
8161
  this.writer = writer;
7789
8162
  this.name = "KHR_materials_iridescence";
7790
8163
  }
7791
- writeMaterial(material, materialDef) {
8164
+ async writeMaterialAsync(material, materialDef) {
7792
8165
  if (!material.isMeshPhysicalMaterial || material.iridescence === 0) return;
7793
8166
  const writer = this.writer;
7794
8167
  const extensionsUsed = writer.extensionsUsed;
@@ -7796,7 +8169,7 @@ var GLTFMaterialsIridescenceExtension = class {
7796
8169
  extensionDef.iridescenceFactor = material.iridescence;
7797
8170
  if (material.iridescenceMap) {
7798
8171
  const iridescenceMapDef = {
7799
- index: writer.processTexture(material.iridescenceMap),
8172
+ index: await writer.processTextureAsync(material.iridescenceMap),
7800
8173
  texCoord: material.iridescenceMap.channel
7801
8174
  };
7802
8175
  writer.applyTextureTransform(iridescenceMapDef, material.iridescenceMap);
@@ -7807,7 +8180,7 @@ var GLTFMaterialsIridescenceExtension = class {
7807
8180
  extensionDef.iridescenceThicknessMaximum = material.iridescenceThicknessRange[1];
7808
8181
  if (material.iridescenceThicknessMap) {
7809
8182
  const iridescenceThicknessMapDef = {
7810
- index: writer.processTexture(material.iridescenceThicknessMap),
8183
+ index: await writer.processTextureAsync(material.iridescenceThicknessMap),
7811
8184
  texCoord: material.iridescenceThicknessMap.channel
7812
8185
  };
7813
8186
  writer.applyTextureTransform(iridescenceThicknessMapDef, material.iridescenceThicknessMap);
@@ -7823,7 +8196,7 @@ var GLTFMaterialsTransmissionExtension = class {
7823
8196
  this.writer = writer;
7824
8197
  this.name = "KHR_materials_transmission";
7825
8198
  }
7826
- writeMaterial(material, materialDef) {
8199
+ async writeMaterialAsync(material, materialDef) {
7827
8200
  if (!material.isMeshPhysicalMaterial || material.transmission === 0) return;
7828
8201
  const writer = this.writer;
7829
8202
  const extensionsUsed = writer.extensionsUsed;
@@ -7831,7 +8204,7 @@ var GLTFMaterialsTransmissionExtension = class {
7831
8204
  extensionDef.transmissionFactor = material.transmission;
7832
8205
  if (material.transmissionMap) {
7833
8206
  const transmissionMapDef = {
7834
- index: writer.processTexture(material.transmissionMap),
8207
+ index: await writer.processTextureAsync(material.transmissionMap),
7835
8208
  texCoord: material.transmissionMap.channel
7836
8209
  };
7837
8210
  writer.applyTextureTransform(transmissionMapDef, material.transmissionMap);
@@ -7847,7 +8220,7 @@ var GLTFMaterialsVolumeExtension = class {
7847
8220
  this.writer = writer;
7848
8221
  this.name = "KHR_materials_volume";
7849
8222
  }
7850
- writeMaterial(material, materialDef) {
8223
+ async writeMaterialAsync(material, materialDef) {
7851
8224
  if (!material.isMeshPhysicalMaterial || material.transmission === 0) return;
7852
8225
  const writer = this.writer;
7853
8226
  const extensionsUsed = writer.extensionsUsed;
@@ -7855,13 +8228,15 @@ var GLTFMaterialsVolumeExtension = class {
7855
8228
  extensionDef.thicknessFactor = material.thickness;
7856
8229
  if (material.thicknessMap) {
7857
8230
  const thicknessMapDef = {
7858
- index: writer.processTexture(material.thicknessMap),
8231
+ index: await writer.processTextureAsync(material.thicknessMap),
7859
8232
  texCoord: material.thicknessMap.channel
7860
8233
  };
7861
8234
  writer.applyTextureTransform(thicknessMapDef, material.thicknessMap);
7862
8235
  extensionDef.thicknessTexture = thicknessMapDef;
7863
8236
  }
7864
- extensionDef.attenuationDistance = material.attenuationDistance;
8237
+ if (material.attenuationDistance !== Infinity) {
8238
+ extensionDef.attenuationDistance = material.attenuationDistance;
8239
+ }
7865
8240
  extensionDef.attenuationColor = material.attenuationColor.toArray();
7866
8241
  materialDef.extensions = materialDef.extensions || {};
7867
8242
  materialDef.extensions[this.name] = extensionDef;
@@ -7873,7 +8248,7 @@ var GLTFMaterialsIorExtension = class {
7873
8248
  this.writer = writer;
7874
8249
  this.name = "KHR_materials_ior";
7875
8250
  }
7876
- writeMaterial(material, materialDef) {
8251
+ async writeMaterialAsync(material, materialDef) {
7877
8252
  if (!material.isMeshPhysicalMaterial || material.ior === 1.5) return;
7878
8253
  const writer = this.writer;
7879
8254
  const extensionsUsed = writer.extensionsUsed;
@@ -7889,14 +8264,14 @@ var GLTFMaterialsSpecularExtension = class {
7889
8264
  this.writer = writer;
7890
8265
  this.name = "KHR_materials_specular";
7891
8266
  }
7892
- writeMaterial(material, materialDef) {
7893
- if (!material.isMeshPhysicalMaterial || material.specularIntensity === 1 && material.specularColor.equals(DEFAULT_SPECULAR_COLOR) && !material.specularIntensityMap && !material.specularColorTexture) return;
8267
+ async writeMaterialAsync(material, materialDef) {
8268
+ if (!material.isMeshPhysicalMaterial || material.specularIntensity === 1 && material.specularColor.equals(DEFAULT_SPECULAR_COLOR) && !material.specularIntensityMap && !material.specularColorMap) return;
7894
8269
  const writer = this.writer;
7895
8270
  const extensionsUsed = writer.extensionsUsed;
7896
8271
  const extensionDef = {};
7897
8272
  if (material.specularIntensityMap) {
7898
8273
  const specularIntensityMapDef = {
7899
- index: writer.processTexture(material.specularIntensityMap),
8274
+ index: await writer.processTextureAsync(material.specularIntensityMap),
7900
8275
  texCoord: material.specularIntensityMap.channel
7901
8276
  };
7902
8277
  writer.applyTextureTransform(specularIntensityMapDef, material.specularIntensityMap);
@@ -7904,7 +8279,7 @@ var GLTFMaterialsSpecularExtension = class {
7904
8279
  }
7905
8280
  if (material.specularColorMap) {
7906
8281
  const specularColorMapDef = {
7907
- index: writer.processTexture(material.specularColorMap),
8282
+ index: await writer.processTextureAsync(material.specularColorMap),
7908
8283
  texCoord: material.specularColorMap.channel
7909
8284
  };
7910
8285
  writer.applyTextureTransform(specularColorMapDef, material.specularColorMap);
@@ -7922,14 +8297,14 @@ var GLTFMaterialsSheenExtension = class {
7922
8297
  this.writer = writer;
7923
8298
  this.name = "KHR_materials_sheen";
7924
8299
  }
7925
- writeMaterial(material, materialDef) {
8300
+ async writeMaterialAsync(material, materialDef) {
7926
8301
  if (!material.isMeshPhysicalMaterial || material.sheen == 0) return;
7927
8302
  const writer = this.writer;
7928
8303
  const extensionsUsed = writer.extensionsUsed;
7929
8304
  const extensionDef = {};
7930
8305
  if (material.sheenRoughnessMap) {
7931
8306
  const sheenRoughnessMapDef = {
7932
- index: writer.processTexture(material.sheenRoughnessMap),
8307
+ index: await writer.processTextureAsync(material.sheenRoughnessMap),
7933
8308
  texCoord: material.sheenRoughnessMap.channel
7934
8309
  };
7935
8310
  writer.applyTextureTransform(sheenRoughnessMapDef, material.sheenRoughnessMap);
@@ -7937,7 +8312,7 @@ var GLTFMaterialsSheenExtension = class {
7937
8312
  }
7938
8313
  if (material.sheenColorMap) {
7939
8314
  const sheenColorMapDef = {
7940
- index: writer.processTexture(material.sheenColorMap),
8315
+ index: await writer.processTextureAsync(material.sheenColorMap),
7941
8316
  texCoord: material.sheenColorMap.channel
7942
8317
  };
7943
8318
  writer.applyTextureTransform(sheenColorMapDef, material.sheenColorMap);
@@ -7955,13 +8330,13 @@ var GLTFMaterialsAnisotropyExtension = class {
7955
8330
  this.writer = writer;
7956
8331
  this.name = "KHR_materials_anisotropy";
7957
8332
  }
7958
- writeMaterial(material, materialDef) {
8333
+ async writeMaterialAsync(material, materialDef) {
7959
8334
  if (!material.isMeshPhysicalMaterial || material.anisotropy == 0) return;
7960
8335
  const writer = this.writer;
7961
8336
  const extensionsUsed = writer.extensionsUsed;
7962
8337
  const extensionDef = {};
7963
8338
  if (material.anisotropyMap) {
7964
- const anisotropyMapDef = { index: writer.processTexture(material.anisotropyMap) };
8339
+ const anisotropyMapDef = { index: await writer.processTextureAsync(material.anisotropyMap) };
7965
8340
  writer.applyTextureTransform(anisotropyMapDef, material.anisotropyMap);
7966
8341
  extensionDef.anisotropyTexture = anisotropyMapDef;
7967
8342
  }
@@ -7977,7 +8352,7 @@ var GLTFMaterialsEmissiveStrengthExtension = class {
7977
8352
  this.writer = writer;
7978
8353
  this.name = "KHR_materials_emissive_strength";
7979
8354
  }
7980
- writeMaterial(material, materialDef) {
8355
+ async writeMaterialAsync(material, materialDef) {
7981
8356
  if (!material.isMeshStandardMaterial || material.emissiveIntensity === 1) return;
7982
8357
  const writer = this.writer;
7983
8358
  const extensionsUsed = writer.extensionsUsed;
@@ -7988,6 +8363,30 @@ var GLTFMaterialsEmissiveStrengthExtension = class {
7988
8363
  extensionsUsed[this.name] = true;
7989
8364
  }
7990
8365
  };
8366
+ var GLTFMaterialsBumpExtension = class {
8367
+ constructor(writer) {
8368
+ this.writer = writer;
8369
+ this.name = "EXT_materials_bump";
8370
+ }
8371
+ async writeMaterialAsync(material, materialDef) {
8372
+ if (!material.isMeshStandardMaterial || material.bumpScale === 1 && !material.bumpMap) return;
8373
+ const writer = this.writer;
8374
+ const extensionsUsed = writer.extensionsUsed;
8375
+ const extensionDef = {};
8376
+ if (material.bumpMap) {
8377
+ const bumpMapDef = {
8378
+ index: await writer.processTextureAsync(material.bumpMap),
8379
+ texCoord: material.bumpMap.channel
8380
+ };
8381
+ writer.applyTextureTransform(bumpMapDef, material.bumpMap);
8382
+ extensionDef.bumpTexture = bumpMapDef;
8383
+ }
8384
+ extensionDef.bumpFactor = material.bumpScale;
8385
+ materialDef.extensions = materialDef.extensions || {};
8386
+ materialDef.extensions[this.name] = extensionDef;
8387
+ extensionsUsed[this.name] = true;
8388
+ }
8389
+ };
7991
8390
  var GLTFMeshGpuInstancing = class {
7992
8391
  constructor(writer) {
7993
8392
  this.writer = writer;
@@ -8123,6 +8522,19 @@ GLTFExporter.Utils = {
8123
8522
  }
8124
8523
  clip.tracks = tracks;
8125
8524
  return clip;
8525
+ },
8526
+ toTypedBufferAttribute: function(srcAttribute, TypedArray) {
8527
+ const dstAttribute = new BufferAttribute3(new TypedArray(srcAttribute.count * srcAttribute.itemSize), srcAttribute.itemSize, false);
8528
+ if (!srcAttribute.normalized && !srcAttribute.isInterleavedBufferAttribute) {
8529
+ dstAttribute.array.set(srcAttribute.array);
8530
+ return dstAttribute;
8531
+ }
8532
+ for (let i = 0, il = srcAttribute.count; i < il; i++) {
8533
+ for (let j = 0; j < srcAttribute.itemSize; j++) {
8534
+ dstAttribute.setComponent(i, j, srcAttribute.getComponent(i, j));
8535
+ }
8536
+ }
8537
+ return dstAttribute;
8126
8538
  }
8127
8539
  };
8128
8540
 
@@ -8177,7 +8589,7 @@ function localMatrix(object) {
8177
8589
  return object.matrixAutoUpdate ? new Matrix47().compose(object.position, object.quaternion, object.scale) : object.matrix.clone();
8178
8590
  }
8179
8591
  function createSnapshot(root, gltf, bakeColors = false) {
8180
- const scene = new Scene4();
8592
+ const scene = new Scene3();
8181
8593
  const geometries = [];
8182
8594
  const materials = [];
8183
8595
  const textures = [];
@@ -8272,7 +8684,7 @@ function createSnapshot(root, gltf, bakeColors = false) {
8272
8684
  material.color.copy(tint);
8273
8685
  }
8274
8686
  }
8275
- const copy = new Mesh5(geometry, material);
8687
+ const copy = new Mesh4(geometry, material);
8276
8688
  copy.name = mesh.name;
8277
8689
  copy.renderOrder = mesh.renderOrder;
8278
8690
  scene.add(copy);
@@ -8351,7 +8763,7 @@ function selectAlphaMode(material, geometry) {
8351
8763
  }
8352
8764
  function copyDataTexture(source) {
8353
8765
  const image = source.image;
8354
- if (source.format !== RGBAFormat3 || source.type !== UnsignedByteType) {
8766
+ if (!image.data || source.format !== RGBAFormat3 || source.type !== UnsignedByteType) {
8355
8767
  throw new MineRenderError("glTF export requires RGBA unsigned-byte data textures");
8356
8768
  }
8357
8769
  const canvas = createCanvas2(image.width, image.height);
@@ -8362,8 +8774,8 @@ function copyDataTexture(source) {
8362
8774
  context.putImageData(pixels, 0, 0);
8363
8775
  const copySource = Object.create(source);
8364
8776
  copySource.userData = {};
8365
- copySource.source = new Source2(canvas);
8366
- return new Texture4().copy(copySource);
8777
+ copySource.source = new TextureSource2(canvas);
8778
+ return new Texture3().copy(copySource);
8367
8779
  }
8368
8780
 
8369
8781
  // src/gui/GuiHelper.ts
@@ -8442,7 +8854,7 @@ init_Materials();
8442
8854
  init_ModelObject();
8443
8855
  init_DisplayPosition();
8444
8856
  init_GuiLight();
8445
- import { Box2, Box3 as Box32, Matrix4 as Matrix410, Mesh as Mesh7, PlaneGeometry as PlaneGeometry2, Vector2 as Vector23 } from "three";
8857
+ import { Box2, Box3 as Box32, Matrix4 as Matrix410, Mesh as Mesh6, PlaneGeometry, Vector2 as Vector23 } from "three";
8446
8858
  var GuiObject = class extends SceneObject {
8447
8859
  constructor(textureLayers, options) {
8448
8860
  super({ ...options, instanceMeshes: false, mergeMeshes: false });
@@ -8485,7 +8897,7 @@ var GuiObject = class extends SceneObject {
8485
8897
  const image = material.map.image;
8486
8898
  const [cropX, cropY, cropWidth, cropHeight] = layer.crop ?? [0, 0, image.width, image.height];
8487
8899
  const [width, height] = layer.size ?? [cropWidth, cropHeight];
8488
- const geometry = new PlaneGeometry2(width, height);
8900
+ const geometry = new PlaneGeometry(width, height);
8489
8901
  this.geometries.add(geometry);
8490
8902
  const uv = geometry.getAttribute("uv");
8491
8903
  for (let i = 0; i < uv.count; i++) {
@@ -8495,7 +8907,7 @@ var GuiObject = class extends SceneObject {
8495
8907
  1 - (cropY + (1 - uv.getY(i)) * cropHeight) / image.height
8496
8908
  );
8497
8909
  }
8498
- const mesh = new Mesh7(geometry, material);
8910
+ const mesh = new Mesh6(geometry, material);
8499
8911
  mesh.name = `mesh:${layer.name ?? index}`;
8500
8912
  mesh.position.set(x + width / 2, -y - height / 2, depth);
8501
8913
  mesh.renderOrder = index;
@@ -9337,6 +9749,7 @@ var BlockObject = class _BlockObject extends SceneObject {
9337
9749
  replacement.setMatrix(matrix);
9338
9750
  } else {
9339
9751
  replacement.matrix.copy(matrix);
9752
+ replacement.matrixWorldNeedsUpdate = true;
9340
9753
  matrix.decompose(replacement.position, replacement.quaternion, replacement.scale);
9341
9754
  replacement.matrixAutoUpdate = object.matrixAutoUpdate;
9342
9755
  replacement.visible = object.visible;
@@ -11395,7 +11808,7 @@ init_nbt();
11395
11808
  init_SceneObject();
11396
11809
  var import_ts_deepmerge8 = __toESM(require_dist());
11397
11810
  init_ModelObject();
11398
- import { Scene as Scene5 } from "three";
11811
+ import { Scene as Scene4 } from "three";
11399
11812
 
11400
11813
  // src/skin/scene/SkinObject.ts
11401
11814
  init_SceneObject();
@@ -12128,7 +12541,7 @@ init_util();
12128
12541
  init_Caching();
12129
12542
  init_CacheKey();
12130
12543
  init_MineRenderError();
12131
- import { DataTexture as DataTexture2, DoubleSide as DoubleSide4, FrontSide as FrontSide2, MeshBasicMaterial as MeshBasicMaterial6, SRGBColorSpace as SRGBColorSpace5 } from "three";
12544
+ import { DataTexture as DataTexture2, DoubleSide as DoubleSide4, FrontSide as FrontSide2, MeshBasicMaterial as MeshBasicMaterial6, SRGBColorSpace as SRGBColorSpace6 } from "three";
12132
12545
 
12133
12546
  // src/skin/SkinImage.ts
12134
12547
  init_Caching();
@@ -12210,7 +12623,7 @@ var SkinTextures = class {
12210
12623
  }
12211
12624
  static createMaterial(pixels, width, height, transparent = true) {
12212
12625
  const texture = Textures.initTextureProps(new DataTexture2(pixels, width, height));
12213
- texture.colorSpace = SRGBColorSpace5;
12626
+ texture.colorSpace = SRGBColorSpace6;
12214
12627
  texture.flipY = true;
12215
12628
  texture.needsUpdate = true;
12216
12629
  return new MeshBasicMaterial6({ map: texture, transparent, side: transparent ? DoubleSide4 : FrontSide2, alphaTest: transparent ? 0.1 : 0 });
@@ -12443,7 +12856,7 @@ var SkinObject = class extends SceneObject {
12443
12856
  // src/renderer/MineRenderScene.ts
12444
12857
  init_EntityObject();
12445
12858
  init_ItemTints();
12446
- var MineRenderScene = class _MineRenderScene extends Scene5 {
12859
+ var MineRenderScene = class _MineRenderScene extends Scene4 {
12447
12860
  constructor(options) {
12448
12861
  super();
12449
12862
  this.isMineRenderScene = true;
@@ -12489,12 +12902,13 @@ var MineRenderScene = class _MineRenderScene extends Scene5 {
12489
12902
  }
12490
12903
  updateObjectRegistration(object, attached) {
12491
12904
  if (this.observedObjects.has(object) === attached) return;
12905
+ const observable = object;
12492
12906
  if (attached) {
12493
12907
  this.observedObjects.add(object);
12494
- object.addEventListener("change", this.onObjectChange);
12908
+ observable.addEventListener("change", this.onObjectChange);
12495
12909
  } else {
12496
12910
  this.observedObjects.delete(object);
12497
- object.removeEventListener("change", this.onObjectChange);
12911
+ observable.removeEventListener("change", this.onObjectChange);
12498
12912
  }
12499
12913
  const change = attached ? 1 : -1;
12500
12914
  this.stats.objectCount += change;
@@ -12572,7 +12986,7 @@ function isMineRenderScene(obj) {
12572
12986
  }
12573
12987
 
12574
12988
  // src/renderer/Renderer.ts
12575
- import { AxesHelper as AxesHelper2, GridHelper, OrthographicCamera, PCFSoftShadowMap, PerspectiveCamera as PerspectiveCamera2, SRGBColorSpace as SRGBColorSpace6, Vector3 as Vector314, WebGLRenderer as WebGLRenderer2 } from "three";
12989
+ import { AxesHelper as AxesHelper2, GridHelper, OrthographicCamera, PCFShadowMap, PerspectiveCamera, SRGBColorSpace as SRGBColorSpace7, Vector3 as Vector314, WebGLRenderer } from "three";
12576
12990
  var import_ts_deepmerge9 = __toESM(require_dist());
12577
12991
  init_util();
12578
12992
  init_Model();
@@ -13317,7 +13731,7 @@ var Renderer = class _Renderer {
13317
13731
  switch (this.options.camera.type) {
13318
13732
  case "perspective":
13319
13733
  default:
13320
- return new PerspectiveCamera2(
13734
+ return new PerspectiveCamera(
13321
13735
  this.options.camera.perspective.fov,
13322
13736
  this.options.camera.perspective.aspect ?? this.viewWidth / this.viewHeight,
13323
13737
  this.options.camera.near,
@@ -13335,7 +13749,7 @@ var Renderer = class _Renderer {
13335
13749
  }
13336
13750
  }
13337
13751
  createRenderer() {
13338
- const renderer = new WebGLRenderer2({
13752
+ const renderer = new WebGLRenderer({
13339
13753
  antialias: this.options.render.antialias,
13340
13754
  alpha: true,
13341
13755
  powerPreference: "high-performance",
@@ -13343,8 +13757,8 @@ var Renderer = class _Renderer {
13343
13757
  });
13344
13758
  renderer.setClearColor(0, 0);
13345
13759
  renderer.shadowMap.enabled = true;
13346
- renderer.shadowMap.type = PCFSoftShadowMap;
13347
- renderer.outputColorSpace = SRGBColorSpace6;
13760
+ renderer.shadowMap.type = PCFShadowMap;
13761
+ renderer.outputColorSpace = SRGBColorSpace7;
13348
13762
  renderer.setPixelRatio(this.options.render.pixelRatio ?? 1);
13349
13763
  renderer.setSize(this.viewWidth, this.viewHeight);
13350
13764
  return renderer;
@@ -14422,7 +14836,7 @@ init_Model();
14422
14836
  // src/world/SectionMesh.ts
14423
14837
  init_CanvasCompat();
14424
14838
  init_Materials();
14425
- import { BufferGeometry as BufferGeometry6, Float32BufferAttribute as Float32BufferAttribute6, Group, Mesh as Mesh10 } from "three";
14839
+ import { BufferGeometry as BufferGeometry6, Float32BufferAttribute as Float32BufferAttribute6, Group, Mesh as Mesh9 } from "three";
14426
14840
  var SectionMesh = class _SectionMesh extends Group {
14427
14841
  constructor() {
14428
14842
  super(...arguments);
@@ -14507,7 +14921,7 @@ var SectionMesh = class _SectionMesh extends Group {
14507
14921
  const material = Materials.createShadedCanvasMaterial(canvas, false);
14508
14922
  material.vertexColors = true;
14509
14923
  const texture = material.uniforms?.map?.value ?? material.map;
14510
- const mesh = new Mesh10(geometry, material);
14924
+ const mesh = new Mesh9(geometry, material);
14511
14925
  section.add(mesh);
14512
14926
  section.ownedMeshes.push({ mesh, texture });
14513
14927
  }
@@ -14521,6 +14935,7 @@ var SectionMesh = class _SectionMesh extends Group {
14521
14935
  texture?.dispose();
14522
14936
  }
14523
14937
  this.removeFromParent();
14938
+ super.dispose();
14524
14939
  }
14525
14940
  };
14526
14941