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.
@@ -2832,7 +2832,7 @@ var Entities = class {
2832
2832
  };
2833
2833
 
2834
2834
  // src/renderer/SceneObject.ts
2835
- import { Euler as Euler3, InstancedMesh, MathUtils, Matrix4 as Matrix43, Mesh as Mesh3, Object3D as Object3D2, Quaternion as Quaternion3, Vector3 as Vector35 } from "three";
2835
+ import { Color as Color2, Euler as Euler3, InstancedBufferAttribute, InstancedMesh, MathUtils, Matrix4 as Matrix43, Mesh as Mesh3, Object3D as Object3D2, Quaternion as Quaternion3, Vector3 as Vector35 } from "three";
2836
2836
 
2837
2837
  // src/instance/InstanceReference.ts
2838
2838
  var InstanceReference = class {
@@ -2844,32 +2844,42 @@ var InstanceReference = class {
2844
2844
  nextInstance() {
2845
2845
  return this.instanceable.nextInstance();
2846
2846
  }
2847
+ get activeInstanceable() {
2848
+ if (!this.instanceable.isInstanceActive(this.index, this)) throw new MineRenderError("Instance has been removed");
2849
+ return this.instanceable;
2850
+ }
2851
+ removeFromScene() {
2852
+ if (this.instanceable.isInstanceActive(this.index, this)) this.instanceable.removeInstanceAt(this.index);
2853
+ }
2854
+ dispose() {
2855
+ this.removeFromScene();
2856
+ }
2847
2857
  getMatrix(matrix) {
2848
- return this.instanceable.getMatrixAt(this.index, matrix);
2858
+ return this.activeInstanceable.getMatrixAt(this.index, matrix);
2849
2859
  }
2850
2860
  setMatrix(matrix) {
2851
- this.instanceable.setMatrixAt(this.index, matrix);
2861
+ this.activeInstanceable.setMatrixAt(this.index, matrix);
2852
2862
  }
2853
2863
  setPositionRotationScale(position, rotation, scale) {
2854
- this.instanceable.setPositionRotationScaleAt(this.index, position, rotation, scale);
2864
+ this.activeInstanceable.setPositionRotationScaleAt(this.index, position, rotation, scale);
2855
2865
  }
2856
2866
  setPosition(position) {
2857
- this.instanceable.setPositionAt(this.index, position);
2867
+ this.activeInstanceable.setPositionAt(this.index, position);
2858
2868
  }
2859
2869
  getPosition() {
2860
- return this.instanceable.getPositionAt(this.index);
2870
+ return this.activeInstanceable.getPositionAt(this.index);
2861
2871
  }
2862
2872
  setRotation(rotation) {
2863
- this.instanceable.setRotationAt(this.index, rotation);
2873
+ this.activeInstanceable.setRotationAt(this.index, rotation);
2864
2874
  }
2865
2875
  getRotation() {
2866
- return this.instanceable.getRotationAt(this.index);
2876
+ return this.activeInstanceable.getRotationAt(this.index);
2867
2877
  }
2868
2878
  setScale(scale) {
2869
- this.instanceable.setScaleAt(this.index, scale);
2879
+ this.activeInstanceable.setScaleAt(this.index, scale);
2870
2880
  }
2871
2881
  getScale() {
2872
- return this.instanceable.getScaleAt(this.index);
2882
+ return this.activeInstanceable.getScaleAt(this.index);
2873
2883
  }
2874
2884
  //TODO: support for custom methods e.g. setting block variants
2875
2885
  };
@@ -2887,6 +2897,8 @@ var SceneObject = class _SceneObject extends Object3D2 {
2887
2897
  this.materialCallbacks = {};
2888
2898
  this._isInstanced = false;
2889
2899
  this._instanceCounter = 0;
2900
+ this.instanceReferences = /* @__PURE__ */ new Map();
2901
+ this.freeInstanceIndices = [];
2890
2902
  this.options = (0, import_ts_deepmerge3.default)({}, _SceneObject.DEFAULT_OPTIONS, options ?? {});
2891
2903
  console.log("SceneObject options", this.options);
2892
2904
  }
@@ -2990,6 +3002,8 @@ var SceneObject = class _SceneObject extends Object3D2 {
2990
3002
  createInstancedMesh(name, geometry, material, count) {
2991
3003
  const mesh = new InstancedMesh(geometry, material, count);
2992
3004
  mesh.count = 0;
3005
+ this.instanceMesh = mesh;
3006
+ this._isInstanced = true;
2993
3007
  if (name) {
2994
3008
  mesh.name = `mesh:${name}`;
2995
3009
  }
@@ -3057,40 +3071,70 @@ var SceneObject = class _SceneObject extends Object3D2 {
3057
3071
  return new InstanceReference(this, i);
3058
3072
  }
3059
3073
  nextInstance() {
3060
- if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3061
- const i = this._instanceCounter++;
3062
- this.setMatrixAt(i, new Matrix43());
3063
- const mesh = this.children[0];
3064
- if (mesh && isInstancedMesh(mesh)) {
3065
- mesh.count = Math.min(this._instanceCounter, mesh.instanceMatrix.count);
3066
- }
3067
- console.debug(p6, "nextInstance " + i);
3068
- if (i === this.options.maxInstanceCount) {
3069
- console.warn(p6, "Max instance count reached for " + this);
3070
- }
3071
- if (this.scene) {
3072
- this.scene.stats.instanceCount++;
3074
+ const mesh = this.instanceMesh;
3075
+ if (!mesh) throw new MineRenderError("Object is not instanced");
3076
+ const index = this.freeInstanceIndices.pop() ?? mesh.count;
3077
+ if (index >= mesh.instanceMatrix.count) this.growInstances(index + 1);
3078
+ const reference = this.constructInstanceReference(index);
3079
+ this.instanceReferences.set(index, reference);
3080
+ this._instanceCounter = this.instanceReferences.size;
3081
+ mesh.count = Math.max(mesh.count, index + 1);
3082
+ if (mesh.instanceColor) {
3083
+ mesh.setColorAt(index, new Color2(16777215));
3084
+ mesh.instanceColor.needsUpdate = true;
3085
+ }
3086
+ if (this._scene) this._scene.stats.instanceCount++;
3087
+ this.setMatrixAt(index, new Matrix43());
3088
+ return reference;
3089
+ }
3090
+ isInstanceActive(index, reference) {
3091
+ return this.instanceReferences.get(index) === reference;
3092
+ }
3093
+ removeInstanceAt(index) {
3094
+ if (!this.instanceReferences.has(index)) return;
3095
+ const mesh = this.instanceMesh;
3096
+ this.setMatrixAt(index, new Matrix43().makeScale(0, 0, 0));
3097
+ this.instanceReferences.delete(index);
3098
+ this.freeInstanceIndices.push(index);
3099
+ this._instanceCounter = this.instanceReferences.size;
3100
+ while (mesh.count > 0 && !this.instanceReferences.has(mesh.count - 1)) mesh.count--;
3101
+ if (this._scene) this._scene.stats.instanceCount--;
3102
+ }
3103
+ growInstances(required) {
3104
+ const mesh = this.instanceMesh;
3105
+ const capacity = Math.max(required, mesh.instanceMatrix.count * 2);
3106
+ const grow = (attribute, fill) => {
3107
+ const array = new Float32Array(capacity * attribute.itemSize).fill(fill);
3108
+ array.set(attribute.array);
3109
+ return new InstancedBufferAttribute(array, attribute.itemSize, attribute.normalized, attribute.meshPerAttribute).setUsage(attribute.usage);
3110
+ };
3111
+ const matrix = grow(mesh.instanceMatrix, 0);
3112
+ const color = mesh.instanceColor ? grow(mesh.instanceColor, 1) : null;
3113
+ mesh.dispose();
3114
+ mesh.instanceMatrix = matrix;
3115
+ mesh.instanceColor = color;
3116
+ }
3117
+ *activeInstanceIndices() {
3118
+ if (this.instanceMesh) {
3119
+ yield* this.instanceReferences.keys();
3120
+ } else {
3121
+ for (let i = 0; i < this.instanceCounter; i++) yield i;
3073
3122
  }
3074
- this.notifyDirty();
3075
- return this.constructInstanceReference(i);
3076
3123
  }
3077
3124
  //</editor-fold>
3078
3125
  //<editor-fold desc="TRANSFORMATION">
3079
3126
  getMatrixAt(index, matrix = new Matrix43()) {
3080
- if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3081
- const child = this.children[0];
3082
- if (child && isInstancedMesh(child)) {
3083
- child.getMatrixAt(index, matrix);
3084
- }
3127
+ if (!this.instanceReferences.has(index)) throw new MineRenderError("Instance is not active");
3128
+ this.instanceMesh.getMatrixAt(index, matrix);
3085
3129
  return matrix;
3086
3130
  }
3087
3131
  setMatrixAt(index, matrix) {
3088
- if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3089
- const child = this.children[0];
3090
- if (child && isInstancedMesh(child)) {
3091
- child.setMatrixAt(index, matrix);
3092
- child.instanceMatrix.needsUpdate = true;
3093
- }
3132
+ if (!this.instanceReferences.has(index)) throw new MineRenderError("Instance is not active");
3133
+ const mesh = this.instanceMesh;
3134
+ mesh.setMatrixAt(index, matrix);
3135
+ mesh.instanceMatrix.needsUpdate = true;
3136
+ mesh.boundingBox = null;
3137
+ mesh.boundingSphere = null;
3094
3138
  this.notifyDirty();
3095
3139
  }
3096
3140
  setPositionRotationScaleAt(index, position, rotation, scale) {
@@ -3141,7 +3185,7 @@ var SceneObject = class _SceneObject extends Object3D2 {
3141
3185
  }
3142
3186
  setPositionRotationScale(position, rotation, scale) {
3143
3187
  if (this.isInstanced) {
3144
- for (let i = 0; i < this.instanceCounter; i++) {
3188
+ for (const i of this.activeInstanceIndices()) {
3145
3189
  this.setPositionRotationScaleAt(i, position, rotation, scale);
3146
3190
  }
3147
3191
  } else {
@@ -3159,7 +3203,7 @@ var SceneObject = class _SceneObject extends Object3D2 {
3159
3203
  }
3160
3204
  setPosition(position) {
3161
3205
  if (this.isInstanced) {
3162
- for (let i = 0; i < this.instanceCounter; i++) {
3206
+ for (const i of this.activeInstanceIndices()) {
3163
3207
  this.setPositionRotationScaleAt(i, position);
3164
3208
  }
3165
3209
  } else {
@@ -3169,14 +3213,14 @@ var SceneObject = class _SceneObject extends Object3D2 {
3169
3213
  }
3170
3214
  getPosition() {
3171
3215
  if (this.isInstanced) {
3172
- return this.getPositionAt(0);
3216
+ return this.getPositionAt(this.instanceReferences.keys().next().value ?? 0);
3173
3217
  } else {
3174
3218
  return this.position;
3175
3219
  }
3176
3220
  }
3177
3221
  setRotation(rotation) {
3178
3222
  if (this.isInstanced) {
3179
- for (let i = 0; i < this.instanceCounter; i++) {
3223
+ for (const i of this.activeInstanceIndices()) {
3180
3224
  this.setPositionRotationScaleAt(i, void 0, rotation);
3181
3225
  }
3182
3226
  } else {
@@ -3186,14 +3230,14 @@ var SceneObject = class _SceneObject extends Object3D2 {
3186
3230
  }
3187
3231
  getRotation() {
3188
3232
  if (this.isInstanced) {
3189
- return this.getRotationAt(0);
3233
+ return this.getRotationAt(this.instanceReferences.keys().next().value ?? 0);
3190
3234
  } else {
3191
3235
  return this.rotation;
3192
3236
  }
3193
3237
  }
3194
3238
  setScale(scale) {
3195
3239
  if (this.isInstanced) {
3196
- for (let i = 0; i < this.instanceCounter; i++) {
3240
+ for (const i of this.activeInstanceIndices()) {
3197
3241
  this.setPositionRotationScaleAt(i, void 0, void 0, scale);
3198
3242
  }
3199
3243
  } else {
@@ -3203,7 +3247,7 @@ var SceneObject = class _SceneObject extends Object3D2 {
3203
3247
  }
3204
3248
  getScale() {
3205
3249
  if (this.isInstanced) {
3206
- return this.getScaleAt(0);
3250
+ return this.getScaleAt(this.instanceReferences.keys().next().value ?? 0);
3207
3251
  } else {
3208
3252
  return this.scale;
3209
3253
  }
@@ -3227,6 +3271,17 @@ var SceneObject = class _SceneObject extends Object3D2 {
3227
3271
  this.notifyDirty();
3228
3272
  }
3229
3273
  disposeAndRemoveAllChildren() {
3274
+ if (this.instanceMesh) {
3275
+ if (this._scene) this._scene.stats.instanceCount -= this.instanceReferences.size;
3276
+ this.instanceReferences.clear();
3277
+ this.freeInstanceIndices.length = 0;
3278
+ this._instanceCounter = 0;
3279
+ this.instanceMesh.count = 0;
3280
+ this.instanceMesh.dispose();
3281
+ this.instanceMesh.removeFromParent();
3282
+ this.instanceMesh = void 0;
3283
+ this._isInstanced = false;
3284
+ }
3230
3285
  while (this.children.length > 0) {
3231
3286
  let c = this.children[0];
3232
3287
  if (isDisposable(c)) {
@@ -4449,10 +4504,6 @@ var ModelObject = class _ModelObject extends SceneObject {
4449
4504
  this.createMeshes();
4450
4505
  this.applyTextures();
4451
4506
  }
4452
- dispose() {
4453
- super.dispose();
4454
- this.atlas?.dispose();
4455
- }
4456
4507
  get textureAtlas() {
4457
4508
  return this.atlas;
4458
4509
  }
@@ -4566,7 +4617,7 @@ function isModelObject(obj) {
4566
4617
 
4567
4618
  // src/model/block/scene/BlockObject.ts
4568
4619
  var import_ts_deepmerge6 = __toESM(require_dist());
4569
- import { Euler as Euler5, Matrix4 as Matrix45, Vector3 as Vector37 } from "three";
4620
+ import { Euler as Euler5, Matrix4 as Matrix45 } from "three";
4570
4621
  var p10 = prefix("BlockObject");
4571
4622
  function matchesCondition(condition, state) {
4572
4623
  return Object.entries(condition).every(([key, value]) => {
@@ -4621,18 +4672,21 @@ var BlockObject = class _BlockObject extends SceneObject {
4621
4672
  }
4622
4673
  }
4623
4674
  dispose() {
4675
+ this.clearModels();
4624
4676
  super.dispose();
4625
4677
  }
4626
4678
  removeFromScene() {
4627
- for (let model of this._models) {
4628
- if (isModelObject(model)) {
4629
- model.removeFromScene();
4630
- } else if (isInstanceReference(model)) {
4631
- model.setScale(new Vector37(0, 0, 0));
4632
- }
4633
- }
4679
+ this.clearModels();
4634
4680
  super.removeFromScene();
4635
4681
  }
4682
+ clearModels() {
4683
+ for (const model of this._models.splice(0)) {
4684
+ model.removeFromScene();
4685
+ if (!isInstanceReference(model)) model.dispose();
4686
+ }
4687
+ this._isInstanced = false;
4688
+ this._instanceCounter = 0;
4689
+ }
4636
4690
  get state() {
4637
4691
  return this._state;
4638
4692
  }
@@ -4681,22 +4735,7 @@ var BlockObject = class _BlockObject extends SceneObject {
4681
4735
  return out;
4682
4736
  }
4683
4737
  async recreateModels() {
4684
- const instanceInfo = [];
4685
- if (this.isInstanced) {
4686
- for (let i = 0; i < this.instanceCounter; i++) {
4687
- instanceInfo[i] = this.getMatrixAt(i);
4688
- }
4689
- }
4690
- for (let model of this._models) {
4691
- if (isInstanceReference(model)) {
4692
- model.setScale(new Vector37(0, 0, 0));
4693
- } else {
4694
- model.dispose();
4695
- }
4696
- }
4697
- while (this._models.length > 0) {
4698
- this._models.shift();
4699
- }
4738
+ this.clearModels();
4700
4739
  const variantsToCreate = await this.mapStateToVariant(this.state);
4701
4740
  this._variants = variantsToCreate;
4702
4741
  for (let blockStateVariant of variantsToCreate) {
@@ -4747,6 +4786,7 @@ var BlockObject = class _BlockObject extends SceneObject {
4747
4786
  this._instanceCounter = 1;
4748
4787
  }
4749
4788
  obj.setRotation(rotation);
4789
+ obj.setPosition(this.position);
4750
4790
  return obj;
4751
4791
  }
4752
4792
  async resetState() {