function HeightmapTerrainData(options) {
  //>>includeStart('debug', pragmas.debug);
  if (!defined(options) || !defined(options.buffer)) {
    throw new DeveloperError("options.buffer is required.");
  }
  if (!defined(options.width)) {
    throw new DeveloperError("options.width is required.");
  }
  if (!defined(options.height)) {
    throw new DeveloperError("options.height is required.");
  }
  //>>includeEnd('debug');

  this._buffer = options.buffer;
  this._width = options.width;
  this._height = options.height;
  this._childTileMask = options.childTileMask ?? 15;
  this._encoding = options.encoding ?? HeightmapEncoding.NONE;

  const defaultStructure = HeightmapTessellator.DEFAULT_STRUCTURE;
  let structure = options.structure;
  if (!defined(structure)) {
    structure = defaultStructure;
  } else if (structure !== defaultStructure) {
    structure.heightScale =
      structure.heightScale ?? defaultStructure.heightScale;
    structure.heightOffset =
      structure.heightOffset ?? defaultStructure.heightOffset;
    structure.elementsPerHeight =
      structure.elementsPerHeight ?? defaultStructure.elementsPerHeight;
    structure.stride = structure.stride ?? defaultStructure.stride;
    structure.elementMultiplier =
      structure.elementMultiplier ?? defaultStructure.elementMultiplier;
    structure.isBigEndian =
      structure.isBigEndian ?? defaultStructure.isBigEndian;
  }

  this._structure = structure;
  this._createdByUpsampling = options.createdByUpsampling ?? false;
  this._waterMask = options.waterMask;

  this._skirtHeight = undefined;
  this._bufferType =
    this._encoding === HeightmapEncoding.LERC
      ? Float32Array
      : this._buffer.constructor;
  this._mesh = undefined;
}
Terrain data for a single tile where the terrain data is represented as a heightmap.  A heightmap
is a rectangular array of heights in row-major order from north to south and west to east.

@alias HeightmapTerrainData
@constructor

@param {object} options Object with the following properties:
@param {Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array|Float64Array} options.buffer The buffer containing height data.
@param {number} options.width The width (longitude direction) of the heightmap, in samples.
@param {number} options.height The height (latitude direction) of the heightmap, in samples.
@param {number} [options.childTileMask=15] A bit mask indicating which of this tile's four children exist.
                If a child's bit is set, geometry will be requested for that tile as well when it
                is needed.  If the bit is cleared, the child tile is not requested and geometry is
                instead upsampled from the parent.  The bit values are as follows:
                <table>
                 <tr><th>Bit Position</th><th>Bit Value</th><th>Child Tile</th></tr>
                 <tr><td>0</td><td>1</td><td>Southwest</td></tr>
                 <tr><td>1</td><td>2</td><td>Southeast</td></tr>
                 <tr><td>2</td><td>4</td><td>Northwest</td></tr>
                 <tr><td>3</td><td>8</td><td>Northeast</td></tr>
                </table>
@param {Uint8Array} [options.waterMask] The water mask included in this terrain data, if any.  A water mask is a square
                    Uint8Array or image where a value of 255 indicates water and a value of 0 indicates land.
                    Values in between 0 and 255 are allowed as well to smoothly blend between land and water.
@param {object} [options.structure] An object describing the structure of the height data.
@param {number} [options.structure.heightScale=1.0] The factor by which to multiply height samples in order to obtain
                the height above the heightOffset, in meters.  The heightOffset is added to the resulting
                height after multiplying by the scale.
@param {number} [options.structure.heightOffset=0.0] The offset to add to the scaled height to obtain the final
                height in meters.  The offset is added after the height sample is multiplied by the
                heightScale.
@param {number} [options.structure.elementsPerHeight=1] The number of elements in the buffer that make up a single height
                sample.  This is usually 1, indicating that each element is a separate height sample.  If
                it is greater than 1, that number of elements together form the height sample, which is
                computed according to the structure.elementMultiplier and structure.isBigEndian properties.
@param {number} [options.structure.stride=1] The number of elements to skip to get from the first element of
                one height to the first element of the next height.
@param {number} [options.structure.elementMultiplier=256.0] The multiplier used to compute the height value when the
                stride property is greater than 1.  For example, if the stride is 4 and the strideMultiplier
                is 256, the height is computed as follows:
                `height = buffer[index] + buffer[index + 1] * 256 + buffer[index + 2] * 256 * 256 + buffer[index + 3] * 256 * 256 * 256`
                This is assuming that the isBigEndian property is false.  If it is true, the order of the
                elements is reversed.
@param {boolean} [options.structure.isBigEndian=false] Indicates endianness of the elements in the buffer when the
                 stride property is greater than 1.  If this property is false, the first element is the
                 low-order element.  If it is true, the first element is the high-order element.
@param {number} [options.structure.lowestEncodedHeight] The lowest value that can be stored in the height buffer.  Any heights that are lower
                than this value after encoding with the `heightScale` and `heightOffset` are clamped to this value.  For example, if the height
                buffer is a `Uint16Array`, this value should be 0 because a `Uint16Array` cannot store negative numbers.  If this parameter is
                not specified, no minimum value is enforced.
@param {number} [options.structure.highestEncodedHeight] The highest value that can be stored in the height buffer.  Any heights that are higher
                than this value after encoding with the `heightScale` and `heightOffset` are clamped to this value.  For example, if the height
                buffer is a `Uint16Array`, this value should be `256 * 256 - 1` or 65535 because a `Uint16Array` cannot store numbers larger
                than 65535.  If this parameter is not specified, no maximum value is enforced.
@param {HeightmapEncoding} [options.encoding=HeightmapEncoding.NONE] The encoding that is used on the buffer.
@param {boolean} [options.createdByUpsampling=false] True if this instance was created by upsampling another instance;
                 otherwise, false.


@example
const buffer = ...
const heightBuffer = new Uint16Array(buffer, 0, that._heightmapWidth * that._heightmapWidth);
const childTileMask = new Uint8Array(buffer, heightBuffer.byteLength, 1)[0];
const waterMask = new Uint8Array(buffer, heightBuffer.byteLength + 1, buffer.byteLength - heightBuffer.byteLength - 1);
const terrainData = new Cesium.HeightmapTerrainData({
  buffer : heightBuffer,
  width : 65,
  height : 65,
  childTileMask : childTileMask,
  waterMask : waterMask
});

@see TerrainData
@see QuantizedMeshTerrainData
@see GoogleEarthEnterpriseTerrainData