minerender 2.1.0-alpha.33 → 2.1.0-alpha.34

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.
@@ -830,6 +830,8 @@ declare class BlockTints {
830
830
 
831
831
  interface Instanceable {
832
832
  nextInstance(): InstanceReference<SceneObject>;
833
+ removeInstanceAt(index: number): void;
834
+ isInstanceActive(index: number, reference: InstanceReference<Instanceable>): boolean;
833
835
  getMatrixAt(index: number, matrix?: Matrix4): Matrix4;
834
836
  setMatrixAt(index: number, matrix: Matrix4): void;
835
837
  setPositionRotationScaleAt(index: number, position?: Vector3, rotation?: Euler, scale?: Vector3): void;
@@ -842,12 +844,15 @@ interface Instanceable {
842
844
  }
843
845
  declare function isInstanceable(obj: any): obj is Instanceable;
844
846
 
845
- declare class InstanceReference<T extends Instanceable> implements Transformable {
847
+ declare class InstanceReference<T extends Instanceable> implements Transformable, Disposable {
846
848
  readonly instanceable: T;
847
849
  readonly index: number;
848
850
  readonly isInstanceReference: true;
849
851
  constructor(instanceable: T, index: number);
850
852
  nextInstance(): InstanceReference<SceneObject>;
853
+ private get activeInstanceable();
854
+ removeFromScene(): void;
855
+ dispose(): void;
851
856
  getMatrix(matrix?: Matrix4): Matrix4;
852
857
  setMatrix(matrix: Matrix4): void;
853
858
  setPositionRotationScale(position?: Vector3, rotation?: Euler, scale?: Vector3): void;
@@ -877,7 +882,6 @@ declare class ModelObject extends SceneObject {
877
882
  private meshesCreated;
878
883
  constructor(originalModel: Model, options?: Partial<ModelObjectOptions>);
879
884
  init(): Promise<void>;
880
- dispose(): void;
881
885
  get textureAtlas(): Maybe<TextureAtlas>;
882
886
  protected loadTextures(): Promise<void>;
883
887
  protected createMeshes(force?: boolean): void;
@@ -1011,6 +1015,9 @@ declare class SceneObject extends Object3D<Object3DEventMap & {
1011
1015
  private materialCallbacks;
1012
1016
  protected _isInstanced: boolean;
1013
1017
  _instanceCounter: number;
1018
+ protected instanceMesh?: InstancedMesh;
1019
+ private readonly instanceReferences;
1020
+ private readonly freeInstanceIndices;
1014
1021
  constructor(options?: Partial<SceneObjectOptions>);
1015
1022
  set scene(scene: MineRenderScene);
1016
1023
  get scene(): MineRenderScene;
@@ -1050,6 +1057,10 @@ declare class SceneObject extends Object3D<Object3DEventMap & {
1050
1057
  get instanceCounter(): number;
1051
1058
  protected constructInstanceReference(i: number): InstanceReference<SceneObject>;
1052
1059
  nextInstance(): InstanceReference<SceneObject>;
1060
+ isInstanceActive(index: number, reference: InstanceReference<Instanceable>): boolean;
1061
+ removeInstanceAt(index: number): void;
1062
+ private growInstances;
1063
+ protected activeInstanceIndices(): Iterable<number>;
1053
1064
  getMatrixAt(index: number, matrix?: Matrix4): Matrix4;
1054
1065
  setMatrixAt(index: number, matrix: Matrix4): void;
1055
1066
  setPositionRotationScaleAt(index: number, position?: Vector3, rotation?: Euler, scale?: Vector3): void;
@@ -1090,6 +1101,7 @@ declare class BlockObject extends SceneObject {
1090
1101
  init(): Promise<void>;
1091
1102
  dispose(): void;
1092
1103
  removeFromScene(): void;
1104
+ private clearModels;
1093
1105
  get state(): {
1094
1106
  [key: string]: string;
1095
1107
  };
@@ -830,6 +830,8 @@ declare class BlockTints {
830
830
 
831
831
  interface Instanceable {
832
832
  nextInstance(): InstanceReference<SceneObject>;
833
+ removeInstanceAt(index: number): void;
834
+ isInstanceActive(index: number, reference: InstanceReference<Instanceable>): boolean;
833
835
  getMatrixAt(index: number, matrix?: Matrix4): Matrix4;
834
836
  setMatrixAt(index: number, matrix: Matrix4): void;
835
837
  setPositionRotationScaleAt(index: number, position?: Vector3, rotation?: Euler, scale?: Vector3): void;
@@ -842,12 +844,15 @@ interface Instanceable {
842
844
  }
843
845
  declare function isInstanceable(obj: any): obj is Instanceable;
844
846
 
845
- declare class InstanceReference<T extends Instanceable> implements Transformable {
847
+ declare class InstanceReference<T extends Instanceable> implements Transformable, Disposable {
846
848
  readonly instanceable: T;
847
849
  readonly index: number;
848
850
  readonly isInstanceReference: true;
849
851
  constructor(instanceable: T, index: number);
850
852
  nextInstance(): InstanceReference<SceneObject>;
853
+ private get activeInstanceable();
854
+ removeFromScene(): void;
855
+ dispose(): void;
851
856
  getMatrix(matrix?: Matrix4): Matrix4;
852
857
  setMatrix(matrix: Matrix4): void;
853
858
  setPositionRotationScale(position?: Vector3, rotation?: Euler, scale?: Vector3): void;
@@ -877,7 +882,6 @@ declare class ModelObject extends SceneObject {
877
882
  private meshesCreated;
878
883
  constructor(originalModel: Model, options?: Partial<ModelObjectOptions>);
879
884
  init(): Promise<void>;
880
- dispose(): void;
881
885
  get textureAtlas(): Maybe<TextureAtlas>;
882
886
  protected loadTextures(): Promise<void>;
883
887
  protected createMeshes(force?: boolean): void;
@@ -1011,6 +1015,9 @@ declare class SceneObject extends Object3D<Object3DEventMap & {
1011
1015
  private materialCallbacks;
1012
1016
  protected _isInstanced: boolean;
1013
1017
  _instanceCounter: number;
1018
+ protected instanceMesh?: InstancedMesh;
1019
+ private readonly instanceReferences;
1020
+ private readonly freeInstanceIndices;
1014
1021
  constructor(options?: Partial<SceneObjectOptions>);
1015
1022
  set scene(scene: MineRenderScene);
1016
1023
  get scene(): MineRenderScene;
@@ -1050,6 +1057,10 @@ declare class SceneObject extends Object3D<Object3DEventMap & {
1050
1057
  get instanceCounter(): number;
1051
1058
  protected constructInstanceReference(i: number): InstanceReference<SceneObject>;
1052
1059
  nextInstance(): InstanceReference<SceneObject>;
1060
+ isInstanceActive(index: number, reference: InstanceReference<Instanceable>): boolean;
1061
+ removeInstanceAt(index: number): void;
1062
+ private growInstances;
1063
+ protected activeInstanceIndices(): Iterable<number>;
1053
1064
  getMatrixAt(index: number, matrix?: Matrix4): Matrix4;
1054
1065
  setMatrixAt(index: number, matrix: Matrix4): void;
1055
1066
  setPositionRotationScaleAt(index: number, position?: Vector3, rotation?: Euler, scale?: Vector3): void;
@@ -1090,6 +1101,7 @@ declare class BlockObject extends SceneObject {
1090
1101
  init(): Promise<void>;
1091
1102
  dispose(): void;
1092
1103
  removeFromScene(): void;
1104
+ private clearModels;
1093
1105
  get state(): {
1094
1106
  [key: string]: string;
1095
1107
  };
@@ -2958,32 +2958,42 @@ var InstanceReference = class {
2958
2958
  nextInstance() {
2959
2959
  return this.instanceable.nextInstance();
2960
2960
  }
2961
+ get activeInstanceable() {
2962
+ if (!this.instanceable.isInstanceActive(this.index, this)) throw new MineRenderError("Instance has been removed");
2963
+ return this.instanceable;
2964
+ }
2965
+ removeFromScene() {
2966
+ if (this.instanceable.isInstanceActive(this.index, this)) this.instanceable.removeInstanceAt(this.index);
2967
+ }
2968
+ dispose() {
2969
+ this.removeFromScene();
2970
+ }
2961
2971
  getMatrix(matrix) {
2962
- return this.instanceable.getMatrixAt(this.index, matrix);
2972
+ return this.activeInstanceable.getMatrixAt(this.index, matrix);
2963
2973
  }
2964
2974
  setMatrix(matrix) {
2965
- this.instanceable.setMatrixAt(this.index, matrix);
2975
+ this.activeInstanceable.setMatrixAt(this.index, matrix);
2966
2976
  }
2967
2977
  setPositionRotationScale(position, rotation, scale) {
2968
- this.instanceable.setPositionRotationScaleAt(this.index, position, rotation, scale);
2978
+ this.activeInstanceable.setPositionRotationScaleAt(this.index, position, rotation, scale);
2969
2979
  }
2970
2980
  setPosition(position) {
2971
- this.instanceable.setPositionAt(this.index, position);
2981
+ this.activeInstanceable.setPositionAt(this.index, position);
2972
2982
  }
2973
2983
  getPosition() {
2974
- return this.instanceable.getPositionAt(this.index);
2984
+ return this.activeInstanceable.getPositionAt(this.index);
2975
2985
  }
2976
2986
  setRotation(rotation) {
2977
- this.instanceable.setRotationAt(this.index, rotation);
2987
+ this.activeInstanceable.setRotationAt(this.index, rotation);
2978
2988
  }
2979
2989
  getRotation() {
2980
- return this.instanceable.getRotationAt(this.index);
2990
+ return this.activeInstanceable.getRotationAt(this.index);
2981
2991
  }
2982
2992
  setScale(scale) {
2983
- this.instanceable.setScaleAt(this.index, scale);
2993
+ this.activeInstanceable.setScaleAt(this.index, scale);
2984
2994
  }
2985
2995
  getScale() {
2986
- return this.instanceable.getScaleAt(this.index);
2996
+ return this.activeInstanceable.getScaleAt(this.index);
2987
2997
  }
2988
2998
  //TODO: support for custom methods e.g. setting block variants
2989
2999
  };
@@ -3001,6 +3011,8 @@ var _SceneObject = class _SceneObject extends import_three10.Object3D {
3001
3011
  this.materialCallbacks = {};
3002
3012
  this._isInstanced = false;
3003
3013
  this._instanceCounter = 0;
3014
+ this.instanceReferences = /* @__PURE__ */ new Map();
3015
+ this.freeInstanceIndices = [];
3004
3016
  this.options = (0, import_ts_deepmerge3.default)({}, _SceneObject.DEFAULT_OPTIONS, options ?? {});
3005
3017
  console.log("SceneObject options", this.options);
3006
3018
  }
@@ -3096,6 +3108,8 @@ var _SceneObject = class _SceneObject extends import_three10.Object3D {
3096
3108
  createInstancedMesh(name, geometry, material, count) {
3097
3109
  const mesh = new import_three10.InstancedMesh(geometry, material, count);
3098
3110
  mesh.count = 0;
3111
+ this.instanceMesh = mesh;
3112
+ this._isInstanced = true;
3099
3113
  if (name) {
3100
3114
  mesh.name = `mesh:${name}`;
3101
3115
  }
@@ -3163,40 +3177,70 @@ var _SceneObject = class _SceneObject extends import_three10.Object3D {
3163
3177
  return new InstanceReference(this, i);
3164
3178
  }
3165
3179
  nextInstance() {
3166
- if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3167
- const i = this._instanceCounter++;
3168
- this.setMatrixAt(i, new import_three10.Matrix4());
3169
- const mesh = this.children[0];
3170
- if (mesh && isInstancedMesh(mesh)) {
3171
- mesh.count = Math.min(this._instanceCounter, mesh.instanceMatrix.count);
3172
- }
3173
- console.debug(p6, "nextInstance " + i);
3174
- if (i === this.options.maxInstanceCount) {
3175
- console.warn(p6, "Max instance count reached for " + this);
3176
- }
3177
- if (this.scene) {
3178
- this.scene.stats.instanceCount++;
3180
+ const mesh = this.instanceMesh;
3181
+ if (!mesh) throw new MineRenderError("Object is not instanced");
3182
+ const index = this.freeInstanceIndices.pop() ?? mesh.count;
3183
+ if (index >= mesh.instanceMatrix.count) this.growInstances(index + 1);
3184
+ const reference = this.constructInstanceReference(index);
3185
+ this.instanceReferences.set(index, reference);
3186
+ this._instanceCounter = this.instanceReferences.size;
3187
+ mesh.count = Math.max(mesh.count, index + 1);
3188
+ if (mesh.instanceColor) {
3189
+ mesh.setColorAt(index, new import_three10.Color(16777215));
3190
+ mesh.instanceColor.needsUpdate = true;
3191
+ }
3192
+ if (this._scene) this._scene.stats.instanceCount++;
3193
+ this.setMatrixAt(index, new import_three10.Matrix4());
3194
+ return reference;
3195
+ }
3196
+ isInstanceActive(index, reference) {
3197
+ return this.instanceReferences.get(index) === reference;
3198
+ }
3199
+ removeInstanceAt(index) {
3200
+ if (!this.instanceReferences.has(index)) return;
3201
+ const mesh = this.instanceMesh;
3202
+ this.setMatrixAt(index, new import_three10.Matrix4().makeScale(0, 0, 0));
3203
+ this.instanceReferences.delete(index);
3204
+ this.freeInstanceIndices.push(index);
3205
+ this._instanceCounter = this.instanceReferences.size;
3206
+ while (mesh.count > 0 && !this.instanceReferences.has(mesh.count - 1)) mesh.count--;
3207
+ if (this._scene) this._scene.stats.instanceCount--;
3208
+ }
3209
+ growInstances(required) {
3210
+ const mesh = this.instanceMesh;
3211
+ const capacity = Math.max(required, mesh.instanceMatrix.count * 2);
3212
+ const grow = (attribute, fill) => {
3213
+ const array = new Float32Array(capacity * attribute.itemSize).fill(fill);
3214
+ array.set(attribute.array);
3215
+ return new import_three10.InstancedBufferAttribute(array, attribute.itemSize, attribute.normalized, attribute.meshPerAttribute).setUsage(attribute.usage);
3216
+ };
3217
+ const matrix = grow(mesh.instanceMatrix, 0);
3218
+ const color = mesh.instanceColor ? grow(mesh.instanceColor, 1) : null;
3219
+ mesh.dispose();
3220
+ mesh.instanceMatrix = matrix;
3221
+ mesh.instanceColor = color;
3222
+ }
3223
+ *activeInstanceIndices() {
3224
+ if (this.instanceMesh) {
3225
+ yield* this.instanceReferences.keys();
3226
+ } else {
3227
+ for (let i = 0; i < this.instanceCounter; i++) yield i;
3179
3228
  }
3180
- this.notifyDirty();
3181
- return this.constructInstanceReference(i);
3182
3229
  }
3183
3230
  //</editor-fold>
3184
3231
  //<editor-fold desc="TRANSFORMATION">
3185
3232
  getMatrixAt(index, matrix = new import_three10.Matrix4()) {
3186
- if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3187
- const child = this.children[0];
3188
- if (child && isInstancedMesh(child)) {
3189
- child.getMatrixAt(index, matrix);
3190
- }
3233
+ if (!this.instanceReferences.has(index)) throw new MineRenderError("Instance is not active");
3234
+ this.instanceMesh.getMatrixAt(index, matrix);
3191
3235
  return matrix;
3192
3236
  }
3193
3237
  setMatrixAt(index, matrix) {
3194
- if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3195
- const child = this.children[0];
3196
- if (child && isInstancedMesh(child)) {
3197
- child.setMatrixAt(index, matrix);
3198
- child.instanceMatrix.needsUpdate = true;
3199
- }
3238
+ if (!this.instanceReferences.has(index)) throw new MineRenderError("Instance is not active");
3239
+ const mesh = this.instanceMesh;
3240
+ mesh.setMatrixAt(index, matrix);
3241
+ mesh.instanceMatrix.needsUpdate = true;
3242
+ mesh.boundingBox = null;
3243
+ mesh.boundingSphere = null;
3200
3244
  this.notifyDirty();
3201
3245
  }
3202
3246
  setPositionRotationScaleAt(index, position, rotation, scale) {
@@ -3247,7 +3291,7 @@ var _SceneObject = class _SceneObject extends import_three10.Object3D {
3247
3291
  }
3248
3292
  setPositionRotationScale(position, rotation, scale) {
3249
3293
  if (this.isInstanced) {
3250
- for (let i = 0; i < this.instanceCounter; i++) {
3294
+ for (const i of this.activeInstanceIndices()) {
3251
3295
  this.setPositionRotationScaleAt(i, position, rotation, scale);
3252
3296
  }
3253
3297
  } else {
@@ -3265,7 +3309,7 @@ var _SceneObject = class _SceneObject extends import_three10.Object3D {
3265
3309
  }
3266
3310
  setPosition(position) {
3267
3311
  if (this.isInstanced) {
3268
- for (let i = 0; i < this.instanceCounter; i++) {
3312
+ for (const i of this.activeInstanceIndices()) {
3269
3313
  this.setPositionRotationScaleAt(i, position);
3270
3314
  }
3271
3315
  } else {
@@ -3275,14 +3319,14 @@ var _SceneObject = class _SceneObject extends import_three10.Object3D {
3275
3319
  }
3276
3320
  getPosition() {
3277
3321
  if (this.isInstanced) {
3278
- return this.getPositionAt(0);
3322
+ return this.getPositionAt(this.instanceReferences.keys().next().value ?? 0);
3279
3323
  } else {
3280
3324
  return this.position;
3281
3325
  }
3282
3326
  }
3283
3327
  setRotation(rotation) {
3284
3328
  if (this.isInstanced) {
3285
- for (let i = 0; i < this.instanceCounter; i++) {
3329
+ for (const i of this.activeInstanceIndices()) {
3286
3330
  this.setPositionRotationScaleAt(i, void 0, rotation);
3287
3331
  }
3288
3332
  } else {
@@ -3292,14 +3336,14 @@ var _SceneObject = class _SceneObject extends import_three10.Object3D {
3292
3336
  }
3293
3337
  getRotation() {
3294
3338
  if (this.isInstanced) {
3295
- return this.getRotationAt(0);
3339
+ return this.getRotationAt(this.instanceReferences.keys().next().value ?? 0);
3296
3340
  } else {
3297
3341
  return this.rotation;
3298
3342
  }
3299
3343
  }
3300
3344
  setScale(scale) {
3301
3345
  if (this.isInstanced) {
3302
- for (let i = 0; i < this.instanceCounter; i++) {
3346
+ for (const i of this.activeInstanceIndices()) {
3303
3347
  this.setPositionRotationScaleAt(i, void 0, void 0, scale);
3304
3348
  }
3305
3349
  } else {
@@ -3309,7 +3353,7 @@ var _SceneObject = class _SceneObject extends import_three10.Object3D {
3309
3353
  }
3310
3354
  getScale() {
3311
3355
  if (this.isInstanced) {
3312
- return this.getScaleAt(0);
3356
+ return this.getScaleAt(this.instanceReferences.keys().next().value ?? 0);
3313
3357
  } else {
3314
3358
  return this.scale;
3315
3359
  }
@@ -3333,6 +3377,17 @@ var _SceneObject = class _SceneObject extends import_three10.Object3D {
3333
3377
  this.notifyDirty();
3334
3378
  }
3335
3379
  disposeAndRemoveAllChildren() {
3380
+ if (this.instanceMesh) {
3381
+ if (this._scene) this._scene.stats.instanceCount -= this.instanceReferences.size;
3382
+ this.instanceReferences.clear();
3383
+ this.freeInstanceIndices.length = 0;
3384
+ this._instanceCounter = 0;
3385
+ this.instanceMesh.count = 0;
3386
+ this.instanceMesh.dispose();
3387
+ this.instanceMesh.removeFromParent();
3388
+ this.instanceMesh = void 0;
3389
+ this._isInstanced = false;
3390
+ }
3336
3391
  while (this.children.length > 0) {
3337
3392
  let c = this.children[0];
3338
3393
  if (isDisposable(c)) {
@@ -4548,10 +4603,6 @@ var _ModelObject = class _ModelObject extends SceneObject {
4548
4603
  this.createMeshes();
4549
4604
  this.applyTextures();
4550
4605
  }
4551
- dispose() {
4552
- super.dispose();
4553
- this.atlas?.dispose();
4554
- }
4555
4606
  get textureAtlas() {
4556
4607
  return this.atlas;
4557
4608
  }
@@ -4717,18 +4768,21 @@ var _BlockObject = class _BlockObject extends SceneObject {
4717
4768
  }
4718
4769
  }
4719
4770
  dispose() {
4771
+ this.clearModels();
4720
4772
  super.dispose();
4721
4773
  }
4722
4774
  removeFromScene() {
4723
- for (let model of this._models) {
4724
- if (isModelObject(model)) {
4725
- model.removeFromScene();
4726
- } else if (isInstanceReference(model)) {
4727
- model.setScale(new import_three18.Vector3(0, 0, 0));
4728
- }
4729
- }
4775
+ this.clearModels();
4730
4776
  super.removeFromScene();
4731
4777
  }
4778
+ clearModels() {
4779
+ for (const model of this._models.splice(0)) {
4780
+ model.removeFromScene();
4781
+ if (!isInstanceReference(model)) model.dispose();
4782
+ }
4783
+ this._isInstanced = false;
4784
+ this._instanceCounter = 0;
4785
+ }
4732
4786
  get state() {
4733
4787
  return this._state;
4734
4788
  }
@@ -4777,22 +4831,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
4777
4831
  return out;
4778
4832
  }
4779
4833
  async recreateModels() {
4780
- const instanceInfo = [];
4781
- if (this.isInstanced) {
4782
- for (let i = 0; i < this.instanceCounter; i++) {
4783
- instanceInfo[i] = this.getMatrixAt(i);
4784
- }
4785
- }
4786
- for (let model of this._models) {
4787
- if (isInstanceReference(model)) {
4788
- model.setScale(new import_three18.Vector3(0, 0, 0));
4789
- } else {
4790
- model.dispose();
4791
- }
4792
- }
4793
- while (this._models.length > 0) {
4794
- this._models.shift();
4795
- }
4834
+ this.clearModels();
4796
4835
  const variantsToCreate = await this.mapStateToVariant(this.state);
4797
4836
  this._variants = variantsToCreate;
4798
4837
  for (let blockStateVariant of variantsToCreate) {
@@ -4843,6 +4882,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
4843
4882
  this._instanceCounter = 1;
4844
4883
  }
4845
4884
  obj.setRotation(rotation);
4885
+ obj.setPosition(this.position);
4846
4886
  return obj;
4847
4887
  }
4848
4888
  async resetState() {