import type Extent from "./Extent.js";
import type BaseGeometry from "./Geometry.js";
import type Point from "./Point.js";
import type Polygon from "./Polygon.js";
import type MeshComponent from "./support/MeshComponent.js";
import type MeshTransform from "./support/MeshTransform.js";
import type MeshVertexAttributes from "./support/MeshVertexAttributes.js";
import type { ClonableMixin } from "../core/Clonable.js";
import type { LoadableMixin, LoadableMixinProperties } from "../core/Loadable.js";
import type { EsriPromiseMixin } from "../core/Promise.js";
import type { MeshVertexSpaceUnion } from "./types.js";
import type { MeshComponentProperties } from "./support/MeshComponent.js";
import type { MeshMaterialProperties } from "./support/MeshMaterial.js";
import type { CreateBoxParameters, CreateCylinderParameters, CreateSphereParameters, CreatePlaneParameters, RotateParameters, CenterAtParameters, ScaleParameters, CreateFromGLTFParameters, ExportGLTFOptions } from "./support/meshUtils/types.js";
import type { MeshLocalVertexSpaceProperties } from "./support/MeshLocalVertexSpace.js";
import type { MeshGeoreferencedVertexSpaceProperties } from "./support/MeshGeoreferencedVertexSpace.js";
import type { MeshTransformProperties } from "./support/MeshTransform.js";
import type { MeshVertexAttributesProperties } from "./support/MeshVertexAttributes.js";
import type { GeometryProperties as BaseGeometryProperties } from "./Geometry.js";

export interface MeshProperties extends BaseGeometryProperties, LoadableMixinProperties {
  /**
   * An array of mesh components that can be used to apply materials
   * to different regions of the same mesh. There are three common
   * usage patterns for components.
   *
   * 1. **Specify a material for the whole mesh.** In this case, use a single
   *    component with only a material (leaving faces as `null`).
   * 2. **Reuse vertex attributes.** When modeling continuous surfaces,
   *    it can be convenient to only specify vertices once and then
   *    simply refer to them. In this case, use a single component
   *    with faces set to index the vertex attributes that form
   *    triangles.
   * 3. **Specify multiple materials for the same mesh.** In this case,
   *    use multiple components with faces that determine to which region
   *    of the mesh the material of the component applies.
   */
  components?: MeshComponentProperties[] | null;
  /**
   * Additional local transformation of the mesh vertices. The transform is ignored if the
   * [vertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#vertexSpace)
   * is of type [georeferenced](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshGeoreferencedVertexSpace/) and does not specify
   * an [MeshGeoreferencedVertexSpace.origin](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshGeoreferencedVertexSpace/#origin).
   */
  transform?: MeshTransformProperties | null;
  /**
   * Object describing the attributes of each vertex of the mesh. Vertex attributes
   * are flat numerical arrays that describe the position (mandatory), normal (used for
   * lighting calculations and shading) and UV (used for mapping material images to the
   * mesh surface) for each vertex.
   *
   * Vertex attributes can be addressed by indices specified in the components
   * [MeshComponent.faces](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshComponent/#faces) property. If the
   * mesh does not contain any components, or if a component does not specify any faces,
   * then the vertex attributes are interpreted as if each consecutive vertex triple
   * makes up a triangle.
   *
   * @example
   * let mesh = new Mesh({ spatialReference: SpatialReference.WebMercator });
   *
   * // Specify vertices for two triangles that make up a square
   * // around a provided point. UV coordinates are set up to cover the square
   * // from (0, 0) to (1, 1) from corner to corner.
   * mesh.vertexAttributes = {
   *   position: [
   *     pt.x - 10, pt.y - 10, 100,
   *     pt.x + 10, pt.y - 10, 100,
   *     pt.x + 10, pt.y + 10, 100,
   *
   *     pt.x - 10, pt.y - 10, 100,
   *     pt.x + 10, pt.y + 10, 100,
   *     pt.x - 10, pt.y + 10, 100
   *   ],
   *   uv: [
   *     0, 0,
   *     1, 0,
   *     1, 1,
   *
   *     0, 0,
   *     1, 1,
   *     0, 1
   *   ]
   * };
   */
  vertexAttributes?: MeshVertexAttributesProperties;
  /**
   * Defines how the SDK interprets the x, y, z position values stored in
   * [Mesh.vertexAttributes.position](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshVertexAttributes/#position).
   *
   * A source 3D model or custom vertex buffer usually stores positions as numbers, but those numbers do not indicate by
   * themselves whether they are local model coordinates, offsets from a placement point, or absolute map coordinates.
   * This property makes that interpretation explicit for the Mesh geometry.
   *
   * Use [MeshLocalVertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshLocalVertexSpace/) when the position values are meter-based local model coordinates
   * and should be placed in a global [SceneView](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/). Use
   * [MeshGeoreferencedVertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshGeoreferencedVertexSpace/) when the position values should be interpreted as offsets or
   * absolute coordinates in the coordinate system identified by
   * [Mesh.spatialReference](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#spatialReference), which is the usual choice for local scenes with a
   * projected coordinate system.
   *
   * This property is construct-only because changing it changes the meaning of every vertex position in the mesh.
   * To change the vertex space of an existing mesh, use [convertVertexSpace()](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/meshUtils/#convertVertexSpace).
   */
  vertexSpace?: ((MeshGeoreferencedVertexSpaceProperties & { type: "georeferenced" }) | (MeshLocalVertexSpaceProperties & { type: "local" }));
}

/**
 * ## Overview
 *
 * In general 3D terminology, a mesh is a set of vertices connected into faces that define the shape and surface of a
 * 3D object. In the Maps SDK, a Mesh instance is a [Geometry](https://developers.arcgis.com/javascript/latest/references/core/geometry/Geometry/) that stores those vertices in
 * [vertexAttributes](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#vertexAttributes).
 *
 * The [position](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshVertexAttributes/#position) values define the shape of the 3D object,
 * [normals](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshVertexAttributes/#normal) affect lighting and shading, and
 * [UV coordinates](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshVertexAttributes/#uv) can be used to map images to the surface.
 * [Mesh components](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshComponent/) define triangle faces and can assign materials to different
 * regions of the Mesh geometry. Because faces index into the vertex attributes, components can reuse the same vertices
 * instead of duplicating them for every triangle.
 *
 * Mesh geometries can define intrinsic materials. Similar to 3D objects in scene layers, they are symbolized with a
 * [MeshSymbol3D](https://developers.arcgis.com/javascript/latest/references/core/symbols/MeshSymbol3D/) symbol containing a [FillSymbol3DLayer](https://developers.arcgis.com/javascript/latest/references/core/symbols/FillSymbol3DLayer/). The fill symbol layer renders
 * the mesh surface and can define visual overrides such as material, color, and edges.
 *
 * Meshes returned from remote services, such as through [SceneLayer.queryFeatures()](https://developers.arcgis.com/javascript/latest/references/core/layers/SceneLayer/#queryFeatures), may need to load
 * their content asynchronously. When a Mesh is added to a view through a [Graphic](https://developers.arcgis.com/javascript/latest/references/core/Graphic/), the API loads it as needed
 * for display. Call [load()](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#load) before accessing properties such as
 * [vertexAttributes](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#vertexAttributes), [extent](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#extent), and [components](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#components) directly
 * when the mesh is not yet loaded.
 *
 * ## Mesh georeferencing
 *
 * A source 3D model file, imported model, or custom vertex buffer often stores vertex positions as plain x, y, z
 * numbers. Those numbers do not, by themselves, say whether [10, 0, 0] means ten meters east of the source model's
 * own [0, 0, 0], ten map units east of a provided placement point in a projected coordinate system (PCS), or an absolute
 * coordinate on a map. Some formats (e.g., IFC4) and workflows include georeferencing metadata, but a Mesh instance still needs
 * an explicit interpretation of the position values stored in [MeshVertexAttributes.position](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshVertexAttributes/#position).
 *
 * The [vertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#vertexSpace) property provides this interpretation. It specifies whether
 * the position values are coordinates relative to the model's own origin, offsets from an specific origin you provide,
 * or absolute map coordinates.
 *
 * To georeference a Mesh geometry:
 *
 * 1. Note the [SceneView.viewingMode](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/#viewingMode) you are using. A "global" scene and a
 *    "local" scene require different Mesh configurations to work correctly and efficiently.
 * 2. Set [Mesh.spatialReference](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#spatialReference) to a coordinate system compatible with that
 *    [viewingMode](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/#viewingMode).
 * 3. Choose [Mesh.vertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#vertexSpace) based on both the
 *    [viewingMode](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/#viewingMode) and what the source x, y, z values mean.
 * 4. Provide an origin only when the source x, y, z values are offsets from a placement point, such as the source model's
 *    own [0, 0, 0] or an insertion point. The origin is stored on the selected vertex space:
 *    [local](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshLocalVertexSpace/#origin) or
 *    [georeferenced](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshGeoreferencedVertexSpace/#origin).
 *
 * ### Common georeferencing workflows
 *
 * The common workflows below show how to choose a vertex space for source values that are measured from [0, 0, 0],
 * offsets from a placement point, or absolute map coordinates.
 *
 * - In a [global](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/#viewingMode) view, use [MeshLocalVertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshLocalVertexSpace/).
 *   This is common for models whose x, y, z positions describe the object relative to the model's own [0, 0, 0],
 *   such as models from 3D modeling or CAD tools. Set [Mesh.spatialReference](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#spatialReference)
 *   to a geographic coordinate system, such as WGS84 or CGCS2000, or to Web Mercator, and set
 *   [MeshLocalVertexSpace.origin](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshLocalVertexSpace/#origin) to the coordinate where the model's [0, 0, 0] should land.
 * - In a [local](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/#viewingMode) view, use [MeshGeoreferencedVertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshGeoreferencedVertexSpace/) with
 *   an [MeshGeoreferencedVertexSpace.origin](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshGeoreferencedVertexSpace/#origin). This works for both source data whose x, y, z
 *   values are offsets from a placement point, and for models whose x, y, z positions describe the object relative to
 *   the model's own [0, 0, 0]. Set [Mesh.spatialReference](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#spatialReference) to the same projected
 *   coordinate system as [SceneView.spatialReference](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/#spatialReference). The SDK then treats each x, y, z position as an
 *   offset from the origin in the projected coordinate system used by the view.
 * - To use source data whose x, y, z positions were already exported as coordinates in a projected coordinate system,
 *   use [MeshGeoreferencedVertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshGeoreferencedVertexSpace/) without an origin. Set
 *   [Mesh.spatialReference](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#spatialReference) to that projected coordinate system. Each x, y, z
 *   position is then interpreted as an absolute coordinate in that coordinate system.
 * - When you create primitives or import glTF with [meshUtils](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/meshUtils/) create functions and do not
 *   provide a vertex space, the SDK chooses one from the provided location. It chooses
 *   [MeshLocalVertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshLocalVertexSpace/) when the location's spatial reference is geographic, such as WGS84
 *   or CGCS2000, or when it is Web Mercator. It chooses [MeshGeoreferencedVertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshGeoreferencedVertexSpace/) for
 *   other projected coordinate systems. This is a helpful default; choose the vertex space explicitly when your view
 *   setup or data workflow requires a different interpretation.
 *
 * <details>
 * <summary>Read More</summary>
 *
 * <span id="mesh-api"></span>
 *
 * ### Local vertex space
 *
 * In a [local vertex space](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshLocalVertexSpace/), the
 * [MeshVertexAttributes.position](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshVertexAttributes/#position) values are model coordinates in meters, measured from the
 * source model's local [0, 0, 0]. The [MeshLocalVertexSpace.origin](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshLocalVertexSpace/#origin) places that local origin
 * at an [x, y, z] coordinate in the coordinate system identified by
 * [Mesh.spatialReference](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#spatialReference).
 *
 * <img src="https://developers.arcgis.com/javascript/latest/assets/references/core/geometry/mesh-local-vertex-space.avif" style="width:300px;"/>
 *
 * *local vertex space*
 *
 * When a Mesh geometry with [MeshLocalVertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshLocalVertexSpace/) is displayed in a global scene and
 * [Mesh.spatialReference](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#spatialReference) is WGS84, CGCS2000, or Web Mercator, the SDK places the
 * local coordinate frame on the globe at [MeshLocalVertexSpace.origin](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshLocalVertexSpace/#origin). The frame is aligned to
 * the [local tangent plane](https://en.wikipedia.org/wiki/Local_tangent_plane_coordinates): X points east, Y points
 * north, and Z points up. This is commonly called an east, north, up (ENU) frame.
 *
 * <img src="https://developers.arcgis.com/javascript/latest/assets/references/core/geometry/mesh-local-vertex-space-on-GCS-or-WM.avif" style="width:300px;"/>
 *
 * *local vertex space aligned to the sphere's tangent plane at the origin point*
 *
 * This reference-frame approach is an approximation: it uses a spherical tangent plane matching how global scenes
 * are rendered. The farther a vertex is from
 * [MeshLocalVertexSpace.origin](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshLocalVertexSpace/#origin), the more the local tangent plane diverges from the curved
 * surface. This is usually acceptable for buildings and other models that occupy a limited area, but it is not
 * appropriate for long objects that must follow the earth's curvature.
 *
 * The word "local" in [MeshLocalVertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshLocalVertexSpace/) refers to coordinates from the source model
 * measured from that model's own [0, 0, 0]. It does not mean that this vertex space is the right choice for a
 * [local](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/#viewingMode) view. For mesh graphics in a local view, use
 * [MeshGeoreferencedVertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshGeoreferencedVertexSpace/) in the view's projected coordinate system.
 *
 * ### Georeferenced vertex space
 *
 * [Mesh.vertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#vertexSpace) gives meaning to the source x, y, z values stored in
 * [MeshVertexAttributes.position](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshVertexAttributes/#position). A
 * [georeferenced vertex space](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshGeoreferencedVertexSpace/) interprets those numbers in relation
 * to [Mesh.spatialReference](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#spatialReference), either as offsets from a placement point or as
 * absolute map coordinates.
 *
 * - When the [origin](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshGeoreferencedVertexSpace/#origin) is set, the mesh's vertex coordinates
 *   are interpreted as offsets from that origin. This works well for 3D models created by CAD software whose x, y and z
 *   values are measured from the source model's own [0, 0, 0], and for those measured from a specific insertion point.
 *   The origin is the [x, y, z] coordinate, in the Mesh's
 *   [spatialReference](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#spatialReference), where that local [0, 0, 0] or insertion point lands.
 *   The offset directions and units come from [Mesh.spatialReference](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#spatialReference). In a
 *   projected coordinate system, these are usually map units such as meters.
 * - Without an [origin](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshGeoreferencedVertexSpace/#origin), use this vertex space
 *   when the source x, y, z values are already absolute map coordinates, for example a mesh produced from a LiDAR scan,
 *   photogrammetry reconstruction, or surveyed surface and exported in a projected coordinate system. Each source
 *   position is used directly in [Mesh.spatialReference](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#spatialReference).
 *
 * <img src="https://developers.arcgis.com/javascript/latest/assets/references/core/geometry/mesh-georeferenced-vertex-space-on-PCS.avif" style="width:300px;"/>
 *
 * *georeferenced vertex space on a projected coordinate system*
 *
 * A georeferenced vertex space is the usual choice for mesh graphics in local scenes. Use it when the
 * [view spatial reference](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/#spatialReference) is a projected coordinate system and
 * [Mesh.spatialReference](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#spatialReference) uses the same projected coordinate system. In that
 * configuration, the position values and the view use the same projected coordinate space, so display and editing can
 * be efficient and predictable.
 *
 * > [!WARNING]
 * > Do not use a georeferenced vertex space with a
 * > [vertex space origin](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshGeoreferencedVertexSpace/#origin) in WGS84 or CGCS2000 for source
 * > models whose x, y, z values are measured in meters. In those geographic coordinate systems, longitude and latitude
 * > are angular coordinates, so an offset such as [10, 0, 0] means ten degrees of longitude, not ten meters east.
 * > A building model can appear at the wrong size or far from the intended location. If the source model is measured in
 * > meters and should be placed on the globe, use [MeshLocalVertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshLocalVertexSpace/) instead.
 *
 * ### Web Mercator
 *
 * Web Mercator is a projected coordinate system, but it is treated specially in global scenes because of its central
 * role in web mapping. A Mesh geometry whose [Mesh.spatialReference](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#spatialReference) is Web
 * Mercator can use
 * [MeshLocalVertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshLocalVertexSpace/) in a global [SceneView](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/). Other projected coordinate
 * systems should use a local [SceneView](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/) and [MeshGeoreferencedVertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshGeoreferencedVertexSpace/).
 *
 * Web Mercator is not recommended as the spatial reference for local scenes or for publishing 3D object layers that
 * require accurate local dimensions. Web Mercator map units are distorted: one Web Mercator meter equals one ground
 * meter only near the equator, and the scale variation increases with latitude. For local scenes and 3D object layer
 * workflows, prefer a projected coordinate system designed for the area of interest.
 *
 * ### Troubleshooting mesh georeferencing
 *
 * If a mesh graphic is not displayed, or is displayed in the wrong place or at the wrong size, first check the browser
 * console for warnings. Then narrow the problem in this order:
 *
 * 1. Start with [SceneView.viewingMode](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/#viewingMode). In a global SceneView, the usual choice for model files whose
 *    positions are measured from the model's own [0, 0, 0] is [MeshLocalVertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshLocalVertexSpace/). In a
 *    local SceneView, the usual choice is [MeshGeoreferencedVertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshGeoreferencedVertexSpace/) with a projected
 *    [Mesh.spatialReference](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#spatialReference) that matches
 *    [SceneView.spatialReference](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/#spatialReference).
 * 2. Identify what the source model's x, y, z values mean. They may be local model coordinates measured from
 *    [0, 0, 0], offsets from an insertion point, or absolute coordinates exported by a georeferenced workflow.
 * 3. Check the vertex space's origin when it has one. The origin should be the [x, y, z] coordinate where the source
 *    model's [0, 0, 0] or insertion point should land, using the coordinate system identified by
 *    [Mesh.spatialReference](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#spatialReference).
 * 4. Check units. [MeshLocalVertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshLocalVertexSpace/) interprets position values as meters.
 *    [MeshGeoreferencedVertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshGeoreferencedVertexSpace/) with a vertex space origin interprets offsets in the units
 *    of [Mesh.spatialReference](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#spatialReference).
 *
 * <span id="limitations"></span>
 * ### Limitations
 *
 * - [MeshLocalVertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshLocalVertexSpace/) is not supported for mesh graphics displayed in a local
 *   [SceneView](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/).
 * - Displaying or editing a Mesh geometry can be unsupported when
 *   [Mesh.spatialReference](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#spatialReference),
 *   [SceneView.spatialReference](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/#spatialReference), and
 *   [Mesh.vertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#vertexSpace) would require costly or unavailable per-vertex projection.
 * - For 3D object feature editing workflows that use Mesh geometry, see the
 *   [SceneLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/SceneLayer/) editing documentation and
 *   [3D object workflows in the SDK](https://developers.arcgis.com/javascript/latest/3d-object-workflows/#essential-aspects-of-the-editing-workflow).
 *
 * </details>
 *
 * ---
 *
 * ## Create simple mesh geometry primitives
 *
 * There are a couple of convenience functions in [meshUtils](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/meshUtils/) to create simple
 * primitive shapes. These shapes can help you get started with understanding
 * mesh geometries.
 *
 * ```js
 * // Create a box mesh geometry
 * let mesh = meshUtils.createBox(location, {
 *   size: {
 *     width: 100,
 *     height: 50,
 *     depth: 50
 *   },
 *   material: {
 *     color: "red"
 *   }
 * });
 *
 * // Create a graphic and add it to the view
 * let graphic = new Graphic({
 *   geometry: mesh,
 *   symbol: {
 *     type: "mesh-3d",
 *     symbolLayers: [ { type: "fill" } ]
 *   }
 * });
 *
 * view.graphics.add(graphic);
 * ```
 *
 * ---
 *
 * ## Create mesh geometries manually
 *
 * Mesh geometries can be manually created by specifying [vertexAttributes](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#vertexAttributes) and
 * [components](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#components) like in the following example:
 *
 * ```js
 * // Create a mesh geometry representing a pyramid
 * let pyramidMesh = new Mesh({
 *   vertexAttributes: {
 *     // vertex positions for the Louvre pyramid, Paris
 *     position: [
 *       // vertex 0 - base of the pyramid, south
 *       2.336006, 48.860818, 0,
 *
 *       // vertex 1 - base of the pyramid, east
 *       2.336172, 48.861114, 0,
 *
 *       // vertex 2 - base of the pyramid, north
 *       2.335724, 48.861229, 0,
 *
 *       // vertex 3 - base of the pyramid, west
 *       2.335563, 48.860922, 0,
 *
 *       // vertex 4 - top of the pyramid
 *       2.335896, 48.861024, 21
 *     ]
 *   },
 *   // Add a single component with faces that index the vertices
 *   // so we only need to define them once
 *   components: [
 *     {
 *       faces: [
 *         0, 4, 3,
 *         0, 1, 4,
 *         1, 2, 4,
 *         2, 3, 4
 *       ]
 *     }
 *   ],
 *   // specify a spatial reference if the position of the vertices is not in WGS84
 * });
 *
 * // add the mesh geometry to a graphic
 * let graphic = new Graphic({
 *   geometry: pyramidMesh,
 *   symbol: {
 *     type: "mesh-3d",
 *     symbolLayers: [ { type: "fill" } ]
 *   }
 * });
 *
 * view.graphics.add(graphic);
 * ```
 *
 * **Note:** Starting with version 4.11 autocasting is no longer supported for Mesh geometry.
 *
 * @since 4.7
 * @see [MeshComponent](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshComponent/)
 * @see [meshUtils](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/meshUtils/)
 * @see [Sample - Working with 3d mesh primitives](https://developers.arcgis.com/javascript/latest/sample-code/geometry-mesh-primitives/)
 * @see [Sample - Low poly terrain using mesh geometry](https://developers.arcgis.com/javascript/latest/sample-code/geometry-mesh-elevation/)
 */
export default class Mesh extends MeshSuperclass {
  /**
   * Creates a mesh representing a box. The spatial reference of the resulting mesh is the same
   * as the location where it is placed.
   *
   * #### Box UV coordinate space
   *
   * The box geometry will have UV coordinates generated according to the following scheme:
   *
   * <img src="https://developers.arcgis.com/javascript/latest/assets/references/core/geometry/mesh-box-uv.avif" width="300" height="300"/>
   *
   * @deprecated since version 5.1. Use [createBox()](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/meshUtils/#createBox) instead.
   * @param location - The location bottom center of the box.
   * @param parameters - Parameters to configure the box creation.
   * @returns The resulting mesh.
   * @example
   * let mesh = Mesh.createBox(point, {
   *   size: {
   *     width: 10,
   *     height: 100,
   *     depth: 20
   *   },
   *   material: {
   *     color: "green"
   *   }
   * });
   * @example
   * let mesh = Mesh.createBox(point, {
   *   imageFace: "top",
   *   material: {
   *     colorTexture: new MeshTexture({ url: "./url-to-image.png" })
   *   }
   * });
   */
  static createBox(location: Point, parameters?: CreateBoxParameters): Mesh;
  /**
   * Creates a mesh representing a cylinder. The spatial reference of the resulting mesh is the same
   * as the location where it is placed.
   *
   * #### Cylinder UV coordinate space
   *
   * The cylinder geometry will have UV coordinates generated according to the following scheme
   * (example is shown for 8 vertices cylinder):
   *
   * <img src="https://developers.arcgis.com/javascript/latest/assets/references/core/geometry/mesh-cylinder-uv.avif" width="300" height="300"/>
   *
   * @deprecated since version 5.1. Use [createCylinder()](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/meshUtils/#createCylinder) instead.
   * @param location - The location of the bottom center of the cylinder.
   * @param parameters - Parameters to configure the cylinder creation.
   * @returns The resulting mesh.
   */
  static createCylinder(location: Point, parameters?: CreateCylinderParameters): Mesh;
  /**
   * Creates a new mesh geometry from a glTF model referenced by the `url` parameter.
   *
   * The spatial reference of the resulting mesh is the same as the spatial reference of the `location` parameter. For
   * more information on the supported glTF features you can read the
   * [Visualizing points with 3D symbols](https://developers.arcgis.com/javascript/latest/visualizing-points-3d/) guide topic. Animations are currently unsupported.
   *
   * @deprecated since version 5.1. Use [createFromGLTF()](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/meshUtils/#createFromGLTF) instead.
   * @param location - The location of the origin of the model. If the location does not
   *  contain a z-value, z is assumed to be `0`.
   * @param url - The URL of the glTF model. The URL should point to a glTF file (.gltf or .glb) which can
   *  reference additional binary (.bin) and image files (.jpg, .png).
   * @param parameters - Parameters to configure the mesh from glTF creation.
   * @returns A promise that resolves to a mesh geometry representing the loaded
   *  glTF model.
   * @since 4.11
   */
  static createFromGLTF(location: Point, url: string, parameters?: CreateFromGLTFParameters): Promise<Mesh>;
  /**
   * Creates a new mesh geometry from a polygon geometry. The resulting mesh contains only
   * a position vertex attribute and a single component with faces. The default shading will be
   * set to `flat`. The spatial reference of the resulting mesh is the same
   * as the input polygon. The resulting mesh will not contain any UV nor normal vertex attributes.
   *
   * @deprecated since version 5.1. Use [createFromPolygon()](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/meshUtils/#createFromPolygon) instead.
   * @param polygon - The input polygon.
   * @param parameters - Optional parameters.
   * @returns A new mesh representing the triangulated polygon.
   */
  static createFromPolygon(polygon: Polygon, parameters?: CreateFromPolygonParameters): Mesh;
  /**
   * Creates a mesh representing a plane. The spatial reference of the resulting mesh is the same
   * as the location where it is placed. A plane consists of two triangles and may be conveniently
   * oriented at creation time.
   *
   * #### Plane UV coordinate space
   *
   * The plane geometry will have UV coordinates generated according to the following scheme:
   *
   * <img src="https://developers.arcgis.com/javascript/latest/assets/references/core/geometry/mesh-plane-uv.avif" width="300" height="300"/>
   *
   * @deprecated since version 5.1. Use [createPlane()](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/meshUtils/#createPlane) instead.
   * @param location - The location of the bottom center of the plane.
   * @param parameters - Parameters to configure the plane creation.
   * @returns The resulting mesh.
   */
  static createPlane(location: Point, parameters?: CreatePlaneParameters): Mesh;
  /**
   * Creates a mesh representing a sphere. The spatial reference of the resulting mesh is the same
   * as the location where it is placed.
   *
   * #### Sphere UV coordinate space
   *
   * The sphere geometry will have UV coordinates generated according to the following scheme
   * (example is shown for 8x8 vertices sphere):
   *
   * <img src="https://developers.arcgis.com/javascript/latest/assets/references/core/geometry/mesh-sphere-uv.avif" width="300" height="300"/>
   *
   * @deprecated since version 5.1. Use [createSphere()](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/meshUtils/#createSphere) instead.
   * @param location - The location of the bottom center of the sphere.
   * @param parameters - Parameters to configure the sphere creation.
   * @returns The resulting mesh.
   */
  static createSphere(location: Point, parameters?: CreateSphereParameters): Mesh;
  constructor(properties?: MeshProperties);
  /**
   * An array of mesh components that can be used to apply materials
   * to different regions of the same mesh. There are three common
   * usage patterns for components.
   *
   * 1. **Specify a material for the whole mesh.** In this case, use a single
   *    component with only a material (leaving faces as `null`).
   * 2. **Reuse vertex attributes.** When modeling continuous surfaces,
   *    it can be convenient to only specify vertices once and then
   *    simply refer to them. In this case, use a single component
   *    with faces set to index the vertex attributes that form
   *    triangles.
   * 3. **Specify multiple materials for the same mesh.** In this case,
   *    use multiple components with faces that determine to which region
   *    of the mesh the material of the component applies.
   */
  get components(): MeshComponent[] | null | undefined;
  set components(value: MeshComponentProperties[] | null | undefined);
  /**
   * The 3D extent of the mesh geometry. The extent is computed from the
   * vertex positions stored in the [vertexAttributes](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#vertexAttributes).
   * The 3D extent is computed on-demand and cached. If you modify the
   * vertexAttributes manually, then you must call
   * [vertexAttributesChanged()](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#vertexAttributesChanged) to make sure the
   * extent will be recomputed.
   */
  get extent(): Extent;
  /**
   * The origin of the mesh. This corresponds to the vertex space origin for relative vertex spaces.
   * For absolute vertex spaces, the origin is at the bottom of the mesh.
   *
   * @since 4.30
   */
  get origin(): Point;
  /**
   * Additional local transformation of the mesh vertices. The transform is ignored if the
   * [vertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#vertexSpace)
   * is of type [georeferenced](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshGeoreferencedVertexSpace/) and does not specify
   * an [MeshGeoreferencedVertexSpace.origin](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshGeoreferencedVertexSpace/#origin).
   */
  get transform(): MeshTransform | null | undefined;
  set transform(value: MeshTransformProperties | null | undefined);
  /** The string value representing the type of geometry. */
  get type(): "mesh";
  /**
   * Object describing the attributes of each vertex of the mesh. Vertex attributes
   * are flat numerical arrays that describe the position (mandatory), normal (used for
   * lighting calculations and shading) and UV (used for mapping material images to the
   * mesh surface) for each vertex.
   *
   * Vertex attributes can be addressed by indices specified in the components
   * [MeshComponent.faces](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshComponent/#faces) property. If the
   * mesh does not contain any components, or if a component does not specify any faces,
   * then the vertex attributes are interpreted as if each consecutive vertex triple
   * makes up a triangle.
   *
   * @example
   * let mesh = new Mesh({ spatialReference: SpatialReference.WebMercator });
   *
   * // Specify vertices for two triangles that make up a square
   * // around a provided point. UV coordinates are set up to cover the square
   * // from (0, 0) to (1, 1) from corner to corner.
   * mesh.vertexAttributes = {
   *   position: [
   *     pt.x - 10, pt.y - 10, 100,
   *     pt.x + 10, pt.y - 10, 100,
   *     pt.x + 10, pt.y + 10, 100,
   *
   *     pt.x - 10, pt.y - 10, 100,
   *     pt.x + 10, pt.y + 10, 100,
   *     pt.x - 10, pt.y + 10, 100
   *   ],
   *   uv: [
   *     0, 0,
   *     1, 0,
   *     1, 1,
   *
   *     0, 0,
   *     1, 1,
   *     0, 1
   *   ]
   * };
   */
  get vertexAttributes(): MeshVertexAttributes;
  set vertexAttributes(value: MeshVertexAttributesProperties);
  /**
   * Defines how the SDK interprets the x, y, z position values stored in
   * [Mesh.vertexAttributes.position](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshVertexAttributes/#position).
   *
   * A source 3D model or custom vertex buffer usually stores positions as numbers, but those numbers do not indicate by
   * themselves whether they are local model coordinates, offsets from a placement point, or absolute map coordinates.
   * This property makes that interpretation explicit for the Mesh geometry.
   *
   * Use [MeshLocalVertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshLocalVertexSpace/) when the position values are meter-based local model coordinates
   * and should be placed in a global [SceneView](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/). Use
   * [MeshGeoreferencedVertexSpace](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/MeshGeoreferencedVertexSpace/) when the position values should be interpreted as offsets or
   * absolute coordinates in the coordinate system identified by
   * [Mesh.spatialReference](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#spatialReference), which is the usual choice for local scenes with a
   * projected coordinate system.
   *
   * This property is construct-only because changing it changes the meaning of every vertex position in the mesh.
   * To change the vertex space of an existing mesh, use [convertVertexSpace()](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/meshUtils/#convertVertexSpace).
   */
  get vertexSpace(): MeshVertexSpaceUnion;
  /**
   * Adds a component to the mesh.
   *
   * @param component - The component to add.
   */
  addComponent(component: MeshComponentProperties): void;
  /**
   * Centers the mesh at the specified location without changing its scale. This effectively adjusts the mesh
   * origin and mesh vertices such that vertices are given relative to the new location and the new location
   * is the new origin. The effective georeferenced vertex positions will not change.
   *
   * The mesh will be modified in place. To modify a copy of the mesh instead, use [clone()](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#clone)
   * before calling [centerAt()](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#centerAt).
   *
   * @param location - The location at which to center the mesh.
   * @param parameters - Additional parameters.
   * @returns The modified mesh.
   */
  centerAt(location: Point, parameters?: CenterAtParameters): this;
  /**
   * Creates a deep clone of the Mesh object.
   *
   * @returns A new instance of a Mesh object equal to the object used to call `.clone()`.
   */
  clone(): this;
  /**
   * Offsets the mesh geometry by the specified distance in x, y, and z. The units of x, y, and z are the
   * units of the spatial reference. When the vertex space is local or georeferenced with an origin,
   * the offset is applied to the origin of the vertex space. When the vertex space is georeferenced
   * without origin, the offset is applied to the vertex positions directly.
   *
   * The mesh will be modified in place. To modify a copy of the mesh instead, use [clone()](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#clone)
   * before calling [offset()](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#offset).
   *
   * @param dx - The amount to offset the geometry in the x direction.
   * @param dy - The amount to offset the geometry in the y direction.
   * @param dz - The amount to offset the geometry in the z direction.
   * @returns The modified mesh (this instance).
   */
  offset(dx: number, dy: number, dz: number): this;
  /**
   * Removes a component from the mesh.
   *
   * @param component - The component to remove.
   */
  removeComponent(component: MeshComponent): void;
  /**
   * Rotates the mesh geometry around its x, y and z axis (in that order). For each rotation angle,
   * the rotation direction is clockwise when looking in the direction of the respective axis.
   * The mesh will be modified in place. To modify a copy of the mesh instead, use [clone()](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#clone)
   * before calling [rotate()](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#rotate).
   *
   * @param angleX - The angle by which to rotate around the x-axis (in degrees).
   * @param angleY - The angle by which to rotate around the y-axis (in degrees).
   * @param angleZ - The angle by which to rotate around the z-axis (in degrees).
   * @param parameters - Additional parameters.
   * @returns The modified mesh (this instance).
   * @example
   * // rotate the mesh in the horizontal plane (around the z axis) by 90 degrees and tilt it in the lateral
   * // vertical plane (around the y axis) by 20 degrees.
   * mesh.rotate(0, 20, 90);
   */
  rotate(angleX: number, angleY: number, angleZ: number, parameters?: RotateParameters): this;
  /**
   * Scales the mesh geometry by the specified factor. The mesh will be modified in place.
   * To modify a copy of the mesh instead, use [clone()](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#clone) before calling [scale()](https://developers.arcgis.com/javascript/latest/references/core/geometry/Mesh/#scale).
   *
   * @param factor - The amount to scale the geometry.
   * @param parameters - Additional parameters.
   * @returns The modified mesh (this instance).
   */
  scale(factor: number, parameters?: ScaleParameters): this;
  /**
   * Export a mesh to a binary glTF (glb) representation. The resulting ArrayBuffer could be uploaded
   * to a service or give an application the option to download a representation of the mesh.
   *
   * @param options - Additional options.
   * @returns The binary glTF data.
   * @since 4.30
   * @example
   * function downloadBufferAsFile(filename, buffer, type) {
   *   const objectUrl = URL.createObjectURL(new Blob([buffer], { type }));
   *
   *   const a = document.createElement("a");
   *   a.download = filename;
   *   a.href = objectUrl;
   *   a.style.display = "none";
   *
   *   document.body.appendChild(a);
   *   a.click();
   *
   *   document.body.removeChild(a);
   *   URL.revokeObjectURL(objectUrl);
   * }
   *
   * const buffer = await mesh.toBinaryGLTF();
   * downloadBufferAsFile("model.glb", buffer, "model/gltf-binary");
   */
  toBinaryGLTF(options?: ExportGLTFOptions): Promise<ArrayBuffer>;
  /**
   * Notifies that any cached values that depend on vertex attributes need to be recalculated. Use this
   * method after modifying the vertex attributes in place so that values that depend on them (such as
   * the calculation of the extent) are recalculated accordingly.
   */
  vertexAttributesChanged(): void;
}
declare const MeshSuperclass: typeof BaseGeometry & typeof EsriPromiseMixin & typeof LoadableMixin & typeof ClonableMixin

/** @deprecated since version 5.1. Use [CreateFromPolygonParameters](https://developers.arcgis.com/javascript/latest/references/core/geometry/support/meshUtils/#CreateFromPolygonParameters) in `meshUtils` instead. */
export interface CreateFromPolygonParameters {
  /** The material to be used for the mesh. */
  material?: MeshMaterialProperties;
}