CesiumInstancedMesh 实例

发布于:2025-05-31 ⋅ 阅读:(21) ⋅ 点赞:(0)

CesiumInstancedMesh 实例

import * as Cesium from 'cesium';

// Three.js 风格的 InstancedMesh 类, https://threejs.org/docs/#api/en/objects/InstancedMesh
export class CesiumInstancedMesh {
  /**
   * Creates an instance of InstancedMesh.
   *
   * @param {Cesium.Geometry} geometry - Cesium geometry instance
   * @param {Cesium.MaterialAppearance} material - Cesium material appearance
   * @param {number} count - Number of instances
   */
  constructor(geometry, material, count) {
    this._instances = Array.from({ length: count }, () => ({
      modelMatrix: null,
      geometry: null
    }));
    this._geometry = geometry;
    this._material = material;
    this._primitive = null;
  }

  /**
   * Gets the Cesium Primitive for rendering.
   * @returns {Cesium.Primitive}
   */
  get primitive() {
    if (this._primitive) return this._primitive;

    // 验证所有实例是否有效
    for (let i = 0; i < this._instances.length; i++) {
      if (!this._instances[i].modelMatrix || !this._instances[i].geometry) {
        throw new Error(`Instance at index ${i} is not fully initialized`);
      }
    }

    this._primitive = new Cesium.Primitive({
      geometryInstances: this._instances.map(instance => new Cesium.GeometryInstance({
        geometry: instance.geometry,
        modelMatrix: instance.modelMatrix
      })),
      appearance: this._material,
      asynchronous: false
    });
    return this._primitive;
  }

  /**
   * Sets the model matrix for an instance at the specified index.
   * @param {number} index - Instance index
   * @param {Cesium.Matrix4} matrix - Model matrix
   */
  setMatrixAt(index, matrix) {
    if (index < 0 || index >= this._instances.length) {
      throw new Error(`Index ${index} is out of bounds (0 to ${this._instances.length - 1})`);
    }
    this._instances[index].modelMatrix = Cesium.Matrix4.clone(matrix, new Cesium.Matrix4());
    this._instances[index].geometry = this._geometry;
    if (this._primitive) {
      this._primitive.geometryInstances = this._instances.map(instance => new Cesium.GeometryInstance({
        geometry: instance.geometry,
        modelMatrix: instance.modelMatrix
      }));
    }
  }

  /**
   * Destroys the instance and releases resources.
   */
  destroy() {
    this._primitive = null;
    this._instances = null;
    this._geometry = null;
    this._material = null;
  }
}