| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610 | import defaultValue from "../Core/defaultValue.js";import defined from "../Core/defined.js";import PrimitiveType from "../Core/PrimitiveType.js";const Flags = {  CULL: 1,  OCCLUDE: 2,  EXECUTE_IN_CLOSEST_FRUSTUM: 4,  DEBUG_SHOW_BOUNDING_VOLUME: 8,  CAST_SHADOWS: 16,  RECEIVE_SHADOWS: 32,  PICK_ONLY: 64,  DEPTH_FOR_TRANSLUCENT_CLASSIFICATION: 128,};/** * Represents a command to the renderer for drawing. * * @private */function DrawCommand(options) {  options = defaultValue(options, defaultValue.EMPTY_OBJECT);  this._boundingVolume = options.boundingVolume;  this._orientedBoundingBox = options.orientedBoundingBox;  this._modelMatrix = options.modelMatrix;  this._primitiveType = defaultValue(    options.primitiveType,    PrimitiveType.TRIANGLES  );  this._vertexArray = options.vertexArray;  this._count = options.count;  this._offset = defaultValue(options.offset, 0);  this._instanceCount = defaultValue(options.instanceCount, 0);  this._shaderProgram = options.shaderProgram;  this._uniformMap = options.uniformMap;  this._renderState = options.renderState;  this._framebuffer = options.framebuffer;  this._pass = options.pass;  this._owner = options.owner;  this._debugOverlappingFrustums = 0;  this._pickId = options.pickId;  // Set initial flags.  this._flags = 0;  this.cull = defaultValue(options.cull, true);  this.occlude = defaultValue(options.occlude, true);  this.executeInClosestFrustum = defaultValue(    options.executeInClosestFrustum,    false  );  this.debugShowBoundingVolume = defaultValue(    options.debugShowBoundingVolume,    false  );  this.castShadows = defaultValue(options.castShadows, false);  this.receiveShadows = defaultValue(options.receiveShadows, false);  this.pickOnly = defaultValue(options.pickOnly, false);  this.depthForTranslucentClassification = defaultValue(    options.depthForTranslucentClassification,    false  );  this.dirty = true;  this.lastDirtyTime = 0;  /**   * @private   */  this.derivedCommands = {};}function hasFlag(command, flag) {  return (command._flags & flag) === flag;}function setFlag(command, flag, value) {  if (value) {    command._flags |= flag;  } else {    command._flags &= ~flag;  }}Object.defineProperties(DrawCommand.prototype, {  /**   * The bounding volume of the geometry in world space.  This is used for culling and frustum selection.   * <p>   * For best rendering performance, use the tightest possible bounding volume.  Although   * <code>undefined</code> is allowed, always try to provide a bounding volume to   * allow the tightest possible near and far planes to be computed for the scene, and   * minimize the number of frustums needed.   * </p>   *   * @memberof DrawCommand.prototype   * @type {Object}   * @default undefined   *   * @see DrawCommand#debugShowBoundingVolume   */  boundingVolume: {    get: function () {      return this._boundingVolume;    },    set: function (value) {      if (this._boundingVolume !== value) {        this._boundingVolume = value;        this.dirty = true;      }    },  },  /**   * The oriented bounding box of the geometry in world space. If this is defined, it is used instead of   * {@link DrawCommand#boundingVolume} for plane intersection testing.   *   * @memberof DrawCommand.prototype   * @type {OrientedBoundingBox}   * @default undefined   *   * @see DrawCommand#debugShowBoundingVolume   */  orientedBoundingBox: {    get: function () {      return this._orientedBoundingBox;    },    set: function (value) {      if (this._orientedBoundingBox !== value) {        this._orientedBoundingBox = value;        this.dirty = true;      }    },  },  /**   * When <code>true</code>, the renderer frustum and horizon culls the command based on its {@link DrawCommand#boundingVolume}.   * If the command was already culled, set this to <code>false</code> for a performance improvement.   *   * @memberof DrawCommand.prototype   * @type {Boolean}   * @default true   */  cull: {    get: function () {      return hasFlag(this, Flags.CULL);    },    set: function (value) {      if (hasFlag(this, Flags.CULL) !== value) {        setFlag(this, Flags.CULL, value);        this.dirty = true;      }    },  },  /**   * When <code>true</code>, the horizon culls the command based on its {@link DrawCommand#boundingVolume}.   * {@link DrawCommand#cull} must also be <code>true</code> in order for the command to be culled.   *   * @memberof DrawCommand.prototype   * @type {Boolean}   * @default true   */  occlude: {    get: function () {      return hasFlag(this, Flags.OCCLUDE);    },    set: function (value) {      if (hasFlag(this, Flags.OCCLUDE) !== value) {        setFlag(this, Flags.OCCLUDE, value);        this.dirty = true;      }    },  },  /**   * The transformation from the geometry in model space to world space.   * <p>   * When <code>undefined</code>, the geometry is assumed to be defined in world space.   * </p>   *   * @memberof DrawCommand.prototype   * @type {Matrix4}   * @default undefined   */  modelMatrix: {    get: function () {      return this._modelMatrix;    },    set: function (value) {      if (this._modelMatrix !== value) {        this._modelMatrix = value;        this.dirty = true;      }    },  },  /**   * The type of geometry in the vertex array.   *   * @memberof DrawCommand.prototype   * @type {PrimitiveType}   * @default PrimitiveType.TRIANGLES   */  primitiveType: {    get: function () {      return this._primitiveType;    },    set: function (value) {      if (this._primitiveType !== value) {        this._primitiveType = value;        this.dirty = true;      }    },  },  /**   * The vertex array.   *   * @memberof DrawCommand.prototype   * @type {VertexArray}   * @default undefined   */  vertexArray: {    get: function () {      return this._vertexArray;    },    set: function (value) {      if (this._vertexArray !== value) {        this._vertexArray = value;        this.dirty = true;      }    },  },  /**   * The number of vertices to draw in the vertex array.   *   * @memberof DrawCommand.prototype   * @type {Number}   * @default undefined   */  count: {    get: function () {      return this._count;    },    set: function (value) {      if (this._count !== value) {        this._count = value;        this.dirty = true;      }    },  },  /**   * The offset to start drawing in the vertex array.   *   * @memberof DrawCommand.prototype   * @type {Number}   * @default 0   */  offset: {    get: function () {      return this._offset;    },    set: function (value) {      if (this._offset !== value) {        this._offset = value;        this.dirty = true;      }    },  },  /**   * The number of instances to draw.   *   * @memberof DrawCommand.prototype   * @type {Number}   * @default 0   */  instanceCount: {    get: function () {      return this._instanceCount;    },    set: function (value) {      if (this._instanceCount !== value) {        this._instanceCount = value;        this.dirty = true;      }    },  },  /**   * The shader program to apply.   *   * @memberof DrawCommand.prototype   * @type {ShaderProgram}   * @default undefined   */  shaderProgram: {    get: function () {      return this._shaderProgram;    },    set: function (value) {      if (this._shaderProgram !== value) {        this._shaderProgram = value;        this.dirty = true;      }    },  },  /**   * Whether this command should cast shadows when shadowing is enabled.   *   * @memberof DrawCommand.prototype   * @type {Boolean}   * @default false   */  castShadows: {    get: function () {      return hasFlag(this, Flags.CAST_SHADOWS);    },    set: function (value) {      if (hasFlag(this, Flags.CAST_SHADOWS) !== value) {        setFlag(this, Flags.CAST_SHADOWS, value);        this.dirty = true;      }    },  },  /**   * Whether this command should receive shadows when shadowing is enabled.   *   * @memberof DrawCommand.prototype   * @type {Boolean}   * @default false   */  receiveShadows: {    get: function () {      return hasFlag(this, Flags.RECEIVE_SHADOWS);    },    set: function (value) {      if (hasFlag(this, Flags.RECEIVE_SHADOWS) !== value) {        setFlag(this, Flags.RECEIVE_SHADOWS, value);        this.dirty = true;      }    },  },  /**   * An object with functions whose names match the uniforms in the shader program   * and return values to set those uniforms.   *   * @memberof DrawCommand.prototype   * @type {Object}   * @default undefined   */  uniformMap: {    get: function () {      return this._uniformMap;    },    set: function (value) {      if (this._uniformMap !== value) {        this._uniformMap = value;        this.dirty = true;      }    },  },  /**   * The render state.   *   * @memberof DrawCommand.prototype   * @type {RenderState}   * @default undefined   */  renderState: {    get: function () {      return this._renderState;    },    set: function (value) {      if (this._renderState !== value) {        this._renderState = value;        this.dirty = true;      }    },  },  /**   * The framebuffer to draw to.   *   * @memberof DrawCommand.prototype   * @type {Framebuffer}   * @default undefined   */  framebuffer: {    get: function () {      return this._framebuffer;    },    set: function (value) {      if (this._framebuffer !== value) {        this._framebuffer = value;        this.dirty = true;      }    },  },  /**   * The pass when to render.   *   * @memberof DrawCommand.prototype   * @type {Pass}   * @default undefined   */  pass: {    get: function () {      return this._pass;    },    set: function (value) {      if (this._pass !== value) {        this._pass = value;        this.dirty = true;      }    },  },  /**   * Specifies if this command is only to be executed in the frustum closest   * to the eye containing the bounding volume. Defaults to <code>false</code>.   *   * @memberof DrawCommand.prototype   * @type {Boolean}   * @default false   */  executeInClosestFrustum: {    get: function () {      return hasFlag(this, Flags.EXECUTE_IN_CLOSEST_FRUSTUM);    },    set: function (value) {      if (hasFlag(this, Flags.EXECUTE_IN_CLOSEST_FRUSTUM) !== value) {        setFlag(this, Flags.EXECUTE_IN_CLOSEST_FRUSTUM, value);        this.dirty = true;      }    },  },  /**   * The object who created this command.  This is useful for debugging command   * execution; it allows us to see who created a command when we only have a   * reference to the command, and can be used to selectively execute commands   * with {@link Scene#debugCommandFilter}.   *   * @memberof DrawCommand.prototype   * @type {Object}   * @default undefined   *   * @see Scene#debugCommandFilter   */  owner: {    get: function () {      return this._owner;    },    set: function (value) {      if (this._owner !== value) {        this._owner = value;        this.dirty = true;      }    },  },  /**   * This property is for debugging only; it is not for production use nor is it optimized.   * <p>   * Draws the {@link DrawCommand#boundingVolume} for this command, assuming it is a sphere, when the command executes.   * </p>   *   * @memberof DrawCommand.prototype   * @type {Boolean}   * @default false   *   * @see DrawCommand#boundingVolume   */  debugShowBoundingVolume: {    get: function () {      return hasFlag(this, Flags.DEBUG_SHOW_BOUNDING_VOLUME);    },    set: function (value) {      if (hasFlag(this, Flags.DEBUG_SHOW_BOUNDING_VOLUME) !== value) {        setFlag(this, Flags.DEBUG_SHOW_BOUNDING_VOLUME, value);        this.dirty = true;      }    },  },  /**   * Used to implement Scene.debugShowFrustums.   * @private   */  debugOverlappingFrustums: {    get: function () {      return this._debugOverlappingFrustums;    },    set: function (value) {      if (this._debugOverlappingFrustums !== value) {        this._debugOverlappingFrustums = value;        this.dirty = true;      }    },  },  /**   * A GLSL string that will evaluate to a pick id. When <code>undefined</code>, the command will only draw depth   * during the pick pass.   *   * @memberof DrawCommand.prototype   * @type {String}   * @default undefined   */  pickId: {    get: function () {      return this._pickId;    },    set: function (value) {      if (this._pickId !== value) {        this._pickId = value;        this.dirty = true;      }    },  },  /**   * Whether this command should be executed in the pick pass only.   *   * @memberof DrawCommand.prototype   * @type {Boolean}   * @default false   */  pickOnly: {    get: function () {      return hasFlag(this, Flags.PICK_ONLY);    },    set: function (value) {      if (hasFlag(this, Flags.PICK_ONLY) !== value) {        setFlag(this, Flags.PICK_ONLY, value);        this.dirty = true;      }    },  },  /**   * Whether this command should be derived to draw depth for classification of translucent primitives.   *   * @memberof DrawCommand.prototype   * @type {Boolean}   * @default false   */  depthForTranslucentClassification: {    get: function () {      return hasFlag(this, Flags.DEPTH_FOR_TRANSLUCENT_CLASSIFICATION);    },    set: function (value) {      if (hasFlag(this, Flags.DEPTH_FOR_TRANSLUCENT_CLASSIFICATION) !== value) {        setFlag(this, Flags.DEPTH_FOR_TRANSLUCENT_CLASSIFICATION, value);        this.dirty = true;      }    },  },});/** * @private */DrawCommand.shallowClone = function (command, result) {  if (!defined(command)) {    return undefined;  }  if (!defined(result)) {    result = new DrawCommand();  }  result._boundingVolume = command._boundingVolume;  result._orientedBoundingBox = command._orientedBoundingBox;  result._modelMatrix = command._modelMatrix;  result._primitiveType = command._primitiveType;  result._vertexArray = command._vertexArray;  result._count = command._count;  result._offset = command._offset;  result._instanceCount = command._instanceCount;  result._shaderProgram = command._shaderProgram;  result._uniformMap = command._uniformMap;  result._renderState = command._renderState;  result._framebuffer = command._framebuffer;  result._pass = command._pass;  result._owner = command._owner;  result._debugOverlappingFrustums = command._debugOverlappingFrustums;  result._pickId = command._pickId;  result._flags = command._flags;  result.dirty = true;  result.lastDirtyTime = 0;  return result;};/** * Executes the draw command. * * @param {Context} context The renderer context in which to draw. * @param {PassState} [passState] The state for the current render pass. */DrawCommand.prototype.execute = function (context, passState) {  context.draw(this, passState);};export default DrawCommand;
 |