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.
@@ -2788,7 +2788,7 @@ var Entities = class {
2788
2788
  };
2789
2789
 
2790
2790
  // src/renderer/SceneObject.ts
2791
- import { Euler as Euler3, InstancedMesh, MathUtils, Matrix4 as Matrix43, Mesh as Mesh3, Object3D as Object3D2, Quaternion as Quaternion3, Vector3 as Vector35 } from "three";
2791
+ 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";
2792
2792
 
2793
2793
  // src/instance/InstanceReference.ts
2794
2794
  var InstanceReference = class {
@@ -2800,32 +2800,42 @@ var InstanceReference = class {
2800
2800
  nextInstance() {
2801
2801
  return this.instanceable.nextInstance();
2802
2802
  }
2803
+ get activeInstanceable() {
2804
+ if (!this.instanceable.isInstanceActive(this.index, this)) throw new MineRenderError("Instance has been removed");
2805
+ return this.instanceable;
2806
+ }
2807
+ removeFromScene() {
2808
+ if (this.instanceable.isInstanceActive(this.index, this)) this.instanceable.removeInstanceAt(this.index);
2809
+ }
2810
+ dispose() {
2811
+ this.removeFromScene();
2812
+ }
2803
2813
  getMatrix(matrix) {
2804
- return this.instanceable.getMatrixAt(this.index, matrix);
2814
+ return this.activeInstanceable.getMatrixAt(this.index, matrix);
2805
2815
  }
2806
2816
  setMatrix(matrix) {
2807
- this.instanceable.setMatrixAt(this.index, matrix);
2817
+ this.activeInstanceable.setMatrixAt(this.index, matrix);
2808
2818
  }
2809
2819
  setPositionRotationScale(position, rotation, scale) {
2810
- this.instanceable.setPositionRotationScaleAt(this.index, position, rotation, scale);
2820
+ this.activeInstanceable.setPositionRotationScaleAt(this.index, position, rotation, scale);
2811
2821
  }
2812
2822
  setPosition(position) {
2813
- this.instanceable.setPositionAt(this.index, position);
2823
+ this.activeInstanceable.setPositionAt(this.index, position);
2814
2824
  }
2815
2825
  getPosition() {
2816
- return this.instanceable.getPositionAt(this.index);
2826
+ return this.activeInstanceable.getPositionAt(this.index);
2817
2827
  }
2818
2828
  setRotation(rotation) {
2819
- this.instanceable.setRotationAt(this.index, rotation);
2829
+ this.activeInstanceable.setRotationAt(this.index, rotation);
2820
2830
  }
2821
2831
  getRotation() {
2822
- return this.instanceable.getRotationAt(this.index);
2832
+ return this.activeInstanceable.getRotationAt(this.index);
2823
2833
  }
2824
2834
  setScale(scale) {
2825
- this.instanceable.setScaleAt(this.index, scale);
2835
+ this.activeInstanceable.setScaleAt(this.index, scale);
2826
2836
  }
2827
2837
  getScale() {
2828
- return this.instanceable.getScaleAt(this.index);
2838
+ return this.activeInstanceable.getScaleAt(this.index);
2829
2839
  }
2830
2840
  //TODO: support for custom methods e.g. setting block variants
2831
2841
  };
@@ -2843,6 +2853,8 @@ var _SceneObject = class _SceneObject extends Object3D2 {
2843
2853
  this.materialCallbacks = {};
2844
2854
  this._isInstanced = false;
2845
2855
  this._instanceCounter = 0;
2856
+ this.instanceReferences = /* @__PURE__ */ new Map();
2857
+ this.freeInstanceIndices = [];
2846
2858
  this.options = (0, import_ts_deepmerge3.default)({}, _SceneObject.DEFAULT_OPTIONS, options ?? {});
2847
2859
  console.log("SceneObject options", this.options);
2848
2860
  }
@@ -2938,6 +2950,8 @@ var _SceneObject = class _SceneObject extends Object3D2 {
2938
2950
  createInstancedMesh(name, geometry, material, count) {
2939
2951
  const mesh = new InstancedMesh(geometry, material, count);
2940
2952
  mesh.count = 0;
2953
+ this.instanceMesh = mesh;
2954
+ this._isInstanced = true;
2941
2955
  if (name) {
2942
2956
  mesh.name = `mesh:${name}`;
2943
2957
  }
@@ -3005,40 +3019,70 @@ var _SceneObject = class _SceneObject extends Object3D2 {
3005
3019
  return new InstanceReference(this, i);
3006
3020
  }
3007
3021
  nextInstance() {
3008
- if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3009
- const i = this._instanceCounter++;
3010
- this.setMatrixAt(i, new Matrix43());
3011
- const mesh = this.children[0];
3012
- if (mesh && isInstancedMesh(mesh)) {
3013
- mesh.count = Math.min(this._instanceCounter, mesh.instanceMatrix.count);
3014
- }
3015
- console.debug(p6, "nextInstance " + i);
3016
- if (i === this.options.maxInstanceCount) {
3017
- console.warn(p6, "Max instance count reached for " + this);
3018
- }
3019
- if (this.scene) {
3020
- this.scene.stats.instanceCount++;
3022
+ const mesh = this.instanceMesh;
3023
+ if (!mesh) throw new MineRenderError("Object is not instanced");
3024
+ const index = this.freeInstanceIndices.pop() ?? mesh.count;
3025
+ if (index >= mesh.instanceMatrix.count) this.growInstances(index + 1);
3026
+ const reference = this.constructInstanceReference(index);
3027
+ this.instanceReferences.set(index, reference);
3028
+ this._instanceCounter = this.instanceReferences.size;
3029
+ mesh.count = Math.max(mesh.count, index + 1);
3030
+ if (mesh.instanceColor) {
3031
+ mesh.setColorAt(index, new Color2(16777215));
3032
+ mesh.instanceColor.needsUpdate = true;
3033
+ }
3034
+ if (this._scene) this._scene.stats.instanceCount++;
3035
+ this.setMatrixAt(index, new Matrix43());
3036
+ return reference;
3037
+ }
3038
+ isInstanceActive(index, reference) {
3039
+ return this.instanceReferences.get(index) === reference;
3040
+ }
3041
+ removeInstanceAt(index) {
3042
+ if (!this.instanceReferences.has(index)) return;
3043
+ const mesh = this.instanceMesh;
3044
+ this.setMatrixAt(index, new Matrix43().makeScale(0, 0, 0));
3045
+ this.instanceReferences.delete(index);
3046
+ this.freeInstanceIndices.push(index);
3047
+ this._instanceCounter = this.instanceReferences.size;
3048
+ while (mesh.count > 0 && !this.instanceReferences.has(mesh.count - 1)) mesh.count--;
3049
+ if (this._scene) this._scene.stats.instanceCount--;
3050
+ }
3051
+ growInstances(required) {
3052
+ const mesh = this.instanceMesh;
3053
+ const capacity = Math.max(required, mesh.instanceMatrix.count * 2);
3054
+ const grow = (attribute, fill) => {
3055
+ const array = new Float32Array(capacity * attribute.itemSize).fill(fill);
3056
+ array.set(attribute.array);
3057
+ return new InstancedBufferAttribute(array, attribute.itemSize, attribute.normalized, attribute.meshPerAttribute).setUsage(attribute.usage);
3058
+ };
3059
+ const matrix = grow(mesh.instanceMatrix, 0);
3060
+ const color = mesh.instanceColor ? grow(mesh.instanceColor, 1) : null;
3061
+ mesh.dispose();
3062
+ mesh.instanceMatrix = matrix;
3063
+ mesh.instanceColor = color;
3064
+ }
3065
+ *activeInstanceIndices() {
3066
+ if (this.instanceMesh) {
3067
+ yield* this.instanceReferences.keys();
3068
+ } else {
3069
+ for (let i = 0; i < this.instanceCounter; i++) yield i;
3021
3070
  }
3022
- this.notifyDirty();
3023
- return this.constructInstanceReference(i);
3024
3071
  }
3025
3072
  //</editor-fold>
3026
3073
  //<editor-fold desc="TRANSFORMATION">
3027
3074
  getMatrixAt(index, matrix = new Matrix43()) {
3028
- if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3029
- const child = this.children[0];
3030
- if (child && isInstancedMesh(child)) {
3031
- child.getMatrixAt(index, matrix);
3032
- }
3075
+ if (!this.instanceReferences.has(index)) throw new MineRenderError("Instance is not active");
3076
+ this.instanceMesh.getMatrixAt(index, matrix);
3033
3077
  return matrix;
3034
3078
  }
3035
3079
  setMatrixAt(index, matrix) {
3036
- if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3037
- const child = this.children[0];
3038
- if (child && isInstancedMesh(child)) {
3039
- child.setMatrixAt(index, matrix);
3040
- child.instanceMatrix.needsUpdate = true;
3041
- }
3080
+ if (!this.instanceReferences.has(index)) throw new MineRenderError("Instance is not active");
3081
+ const mesh = this.instanceMesh;
3082
+ mesh.setMatrixAt(index, matrix);
3083
+ mesh.instanceMatrix.needsUpdate = true;
3084
+ mesh.boundingBox = null;
3085
+ mesh.boundingSphere = null;
3042
3086
  this.notifyDirty();
3043
3087
  }
3044
3088
  setPositionRotationScaleAt(index, position, rotation, scale) {
@@ -3089,7 +3133,7 @@ var _SceneObject = class _SceneObject extends Object3D2 {
3089
3133
  }
3090
3134
  setPositionRotationScale(position, rotation, scale) {
3091
3135
  if (this.isInstanced) {
3092
- for (let i = 0; i < this.instanceCounter; i++) {
3136
+ for (const i of this.activeInstanceIndices()) {
3093
3137
  this.setPositionRotationScaleAt(i, position, rotation, scale);
3094
3138
  }
3095
3139
  } else {
@@ -3107,7 +3151,7 @@ var _SceneObject = class _SceneObject extends Object3D2 {
3107
3151
  }
3108
3152
  setPosition(position) {
3109
3153
  if (this.isInstanced) {
3110
- for (let i = 0; i < this.instanceCounter; i++) {
3154
+ for (const i of this.activeInstanceIndices()) {
3111
3155
  this.setPositionRotationScaleAt(i, position);
3112
3156
  }
3113
3157
  } else {
@@ -3117,14 +3161,14 @@ var _SceneObject = class _SceneObject extends Object3D2 {
3117
3161
  }
3118
3162
  getPosition() {
3119
3163
  if (this.isInstanced) {
3120
- return this.getPositionAt(0);
3164
+ return this.getPositionAt(this.instanceReferences.keys().next().value ?? 0);
3121
3165
  } else {
3122
3166
  return this.position;
3123
3167
  }
3124
3168
  }
3125
3169
  setRotation(rotation) {
3126
3170
  if (this.isInstanced) {
3127
- for (let i = 0; i < this.instanceCounter; i++) {
3171
+ for (const i of this.activeInstanceIndices()) {
3128
3172
  this.setPositionRotationScaleAt(i, void 0, rotation);
3129
3173
  }
3130
3174
  } else {
@@ -3134,14 +3178,14 @@ var _SceneObject = class _SceneObject extends Object3D2 {
3134
3178
  }
3135
3179
  getRotation() {
3136
3180
  if (this.isInstanced) {
3137
- return this.getRotationAt(0);
3181
+ return this.getRotationAt(this.instanceReferences.keys().next().value ?? 0);
3138
3182
  } else {
3139
3183
  return this.rotation;
3140
3184
  }
3141
3185
  }
3142
3186
  setScale(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, void 0, void 0, scale);
3146
3190
  }
3147
3191
  } else {
@@ -3151,7 +3195,7 @@ var _SceneObject = class _SceneObject extends Object3D2 {
3151
3195
  }
3152
3196
  getScale() {
3153
3197
  if (this.isInstanced) {
3154
- return this.getScaleAt(0);
3198
+ return this.getScaleAt(this.instanceReferences.keys().next().value ?? 0);
3155
3199
  } else {
3156
3200
  return this.scale;
3157
3201
  }
@@ -3175,6 +3219,17 @@ var _SceneObject = class _SceneObject extends Object3D2 {
3175
3219
  this.notifyDirty();
3176
3220
  }
3177
3221
  disposeAndRemoveAllChildren() {
3222
+ if (this.instanceMesh) {
3223
+ if (this._scene) this._scene.stats.instanceCount -= this.instanceReferences.size;
3224
+ this.instanceReferences.clear();
3225
+ this.freeInstanceIndices.length = 0;
3226
+ this._instanceCounter = 0;
3227
+ this.instanceMesh.count = 0;
3228
+ this.instanceMesh.dispose();
3229
+ this.instanceMesh.removeFromParent();
3230
+ this.instanceMesh = void 0;
3231
+ this._isInstanced = false;
3232
+ }
3178
3233
  while (this.children.length > 0) {
3179
3234
  let c = this.children[0];
3180
3235
  if (isDisposable(c)) {
@@ -4400,10 +4455,6 @@ var _ModelObject = class _ModelObject extends SceneObject {
4400
4455
  this.createMeshes();
4401
4456
  this.applyTextures();
4402
4457
  }
4403
- dispose() {
4404
- super.dispose();
4405
- this.atlas?.dispose();
4406
- }
4407
4458
  get textureAtlas() {
4408
4459
  return this.atlas;
4409
4460
  }
@@ -4519,7 +4570,7 @@ function isModelObject(obj) {
4519
4570
 
4520
4571
  // src/model/block/scene/BlockObject.ts
4521
4572
  var import_ts_deepmerge6 = __toESM(require_dist());
4522
- import { Euler as Euler5, Matrix4 as Matrix45, Vector3 as Vector37 } from "three";
4573
+ import { Euler as Euler5, Matrix4 as Matrix45 } from "three";
4523
4574
  var p10 = prefix("BlockObject");
4524
4575
  function matchesCondition(condition, state) {
4525
4576
  return Object.entries(condition).every(([key, value]) => {
@@ -4569,18 +4620,21 @@ var _BlockObject = class _BlockObject extends SceneObject {
4569
4620
  }
4570
4621
  }
4571
4622
  dispose() {
4623
+ this.clearModels();
4572
4624
  super.dispose();
4573
4625
  }
4574
4626
  removeFromScene() {
4575
- for (let model of this._models) {
4576
- if (isModelObject(model)) {
4577
- model.removeFromScene();
4578
- } else if (isInstanceReference(model)) {
4579
- model.setScale(new Vector37(0, 0, 0));
4580
- }
4581
- }
4627
+ this.clearModels();
4582
4628
  super.removeFromScene();
4583
4629
  }
4630
+ clearModels() {
4631
+ for (const model of this._models.splice(0)) {
4632
+ model.removeFromScene();
4633
+ if (!isInstanceReference(model)) model.dispose();
4634
+ }
4635
+ this._isInstanced = false;
4636
+ this._instanceCounter = 0;
4637
+ }
4584
4638
  get state() {
4585
4639
  return this._state;
4586
4640
  }
@@ -4629,22 +4683,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
4629
4683
  return out;
4630
4684
  }
4631
4685
  async recreateModels() {
4632
- const instanceInfo = [];
4633
- if (this.isInstanced) {
4634
- for (let i = 0; i < this.instanceCounter; i++) {
4635
- instanceInfo[i] = this.getMatrixAt(i);
4636
- }
4637
- }
4638
- for (let model of this._models) {
4639
- if (isInstanceReference(model)) {
4640
- model.setScale(new Vector37(0, 0, 0));
4641
- } else {
4642
- model.dispose();
4643
- }
4644
- }
4645
- while (this._models.length > 0) {
4646
- this._models.shift();
4647
- }
4686
+ this.clearModels();
4648
4687
  const variantsToCreate = await this.mapStateToVariant(this.state);
4649
4688
  this._variants = variantsToCreate;
4650
4689
  for (let blockStateVariant of variantsToCreate) {
@@ -4695,6 +4734,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
4695
4734
  this._instanceCounter = 1;
4696
4735
  }
4697
4736
  obj.setRotation(rotation);
4737
+ obj.setPosition(this.position);
4698
4738
  return obj;
4699
4739
  }
4700
4740
  async resetState() {