import { arrayFill } from "../../Source/Cesium.js";
import { Cartesian2 } from "../../Source/Cesium.js";
import { Cartesian3 } from "../../Source/Cesium.js";
import { Ellipsoid } from "../../Source/Cesium.js";
import { GeographicProjection } from "../../Source/Cesium.js";
import { GeometryOffsetAttribute } from "../../Source/Cesium.js";
import { Math as CesiumMath } from "../../Source/Cesium.js";
import { Matrix2 } from "../../Source/Cesium.js";
import { Rectangle } from "../../Source/Cesium.js";
import { RectangleGeometry } from "../../Source/Cesium.js";
import { VertexFormat } from "../../Source/Cesium.js";
import createPackableSpecs from "../createPackableSpecs.js";

describe("Core/RectangleGeometry", function () {
  it("computes positions", function () {
    var rectangle = new Rectangle(-2.0, -1.0, 0.0, 1.0);
    var m = RectangleGeometry.createGeometry(
      new RectangleGeometry({
        vertexFormat: VertexFormat.POSITION_ONLY,
        rectangle: rectangle,
        granularity: 1.0,
      })
    );
    var positions = m.attributes.position.values;
    var length = positions.length;

    expect(positions.length).toEqual(9 * 3);
    expect(m.indices.length).toEqual(8 * 3);

    var expectedNWCorner = Ellipsoid.WGS84.cartographicToCartesian(
      Rectangle.northwest(rectangle)
    );
    var expectedSECorner = Ellipsoid.WGS84.cartographicToCartesian(
      Rectangle.southeast(rectangle)
    );
    expect(
      new Cartesian3(positions[0], positions[1], positions[2])
    ).toEqualEpsilon(expectedNWCorner, CesiumMath.EPSILON9);
    expect(
      new Cartesian3(
        positions[length - 3],
        positions[length - 2],
        positions[length - 1]
      )
    ).toEqualEpsilon(expectedSECorner, CesiumMath.EPSILON9);
  });

  it("computes positions across IDL", function () {
    var rectangle = Rectangle.fromDegrees(179.0, -1.0, -179.0, 1.0);
    var m = RectangleGeometry.createGeometry(
      new RectangleGeometry({
        vertexFormat: VertexFormat.POSITION_ONLY,
        rectangle: rectangle,
      })
    );
    var positions = m.attributes.position.values;
    var length = positions.length;

    expect(positions.length).toEqual(9 * 3);
    expect(m.indices.length).toEqual(8 * 3);

    var expectedNWCorner = Ellipsoid.WGS84.cartographicToCartesian(
      Rectangle.northwest(rectangle)
    );
    var expectedSECorner = Ellipsoid.WGS84.cartographicToCartesian(
      Rectangle.southeast(rectangle)
    );
    expect(
      new Cartesian3(positions[0], positions[1], positions[2])
    ).toEqualEpsilon(expectedNWCorner, CesiumMath.EPSILON8);
    expect(
      new Cartesian3(
        positions[length - 3],
        positions[length - 2],
        positions[length - 1]
      )
    ).toEqualEpsilon(expectedSECorner, CesiumMath.EPSILON8);
  });

  it("computes positions at north pole", function () {
    var rectangle = Rectangle.fromDegrees(-180.0, 89.0, -179.0, 90.0);
    var m = RectangleGeometry.createGeometry(
      new RectangleGeometry({
        vertexFormat: VertexFormat.POSITION_ONLY,
        rectangle: rectangle,
      })
    );
    var positions = m.attributes.position.values;
    expect(positions.length).toEqual(5 * 3);
    expect(m.indices.length).toEqual(3 * 3);
  });

  it("computes positions at south pole", function () {
    var rectangle = Rectangle.fromDegrees(-180.0, -90.0, -179.0, -89.0);
    var m = RectangleGeometry.createGeometry(
      new RectangleGeometry({
        vertexFormat: VertexFormat.POSITION_ONLY,
        rectangle: rectangle,
      })
    );
    var positions = m.attributes.position.values;
    expect(positions.length).toEqual(5 * 3);
    expect(m.indices.length).toEqual(3 * 3);
  });

  it("computes all attributes", function () {
    var m = RectangleGeometry.createGeometry(
      new RectangleGeometry({
        vertexFormat: VertexFormat.ALL,
        rectangle: new Rectangle(-2.0, -1.0, 0.0, 1.0),
        granularity: 1.0,
      })
    );
    var numVertices = 9; // 8 around edge + 1 in middle
    var numTriangles = 8; // 4 squares * 2 triangles per square
    expect(m.attributes.position.values.length).toEqual(numVertices * 3);
    expect(m.attributes.st.values.length).toEqual(numVertices * 2);
    expect(m.attributes.normal.values.length).toEqual(numVertices * 3);
    expect(m.attributes.tangent.values.length).toEqual(numVertices * 3);
    expect(m.attributes.bitangent.values.length).toEqual(numVertices * 3);
    expect(m.indices.length).toEqual(numTriangles * 3);
  });

  it("compute positions with rotation", function () {
    var rectangle = new Rectangle(-1, -1, 1, 1);
    var angle = CesiumMath.PI_OVER_TWO;
    var m = RectangleGeometry.createGeometry(
      new RectangleGeometry({
        vertexFormat: VertexFormat.POSITIONS_ONLY,
        rectangle: rectangle,
        rotation: angle,
        granularity: 1.0,
      })
    );
    var positions = m.attributes.position.values;
    var length = positions.length;

    expect(length).toEqual(9 * 3);
    expect(m.indices.length).toEqual(8 * 3);

    var unrotatedSECorner = Rectangle.southeast(rectangle);
    var projection = new GeographicProjection();
    var projectedSECorner = projection.project(unrotatedSECorner);
    var rotation = Matrix2.fromRotation(angle);
    var rotatedSECornerCartographic = projection.unproject(
      Matrix2.multiplyByVector(rotation, projectedSECorner, new Cartesian2())
    );
    var rotatedSECorner = Ellipsoid.WGS84.cartographicToCartesian(
      rotatedSECornerCartographic
    );
    var actual = new Cartesian3(
      positions[length - 3],
      positions[length - 2],
      positions[length - 1]
    );
    expect(actual).toEqualEpsilon(rotatedSECorner, CesiumMath.EPSILON6);
  });

  it("compute vertices with PI rotation", function () {
    var rectangle = new Rectangle(-1, -1, 1, 1);
    var m = RectangleGeometry.createGeometry(
      new RectangleGeometry({
        rectangle: rectangle,
        rotation: CesiumMath.PI,
        granularity: 1.0,
      })
    );
    var positions = m.attributes.position.values;
    var length = positions.length;

    expect(length).toEqual(9 * 3);
    expect(m.indices.length).toEqual(8 * 3);

    var unrotatedNWCorner = Ellipsoid.WGS84.cartographicToCartesian(
      Rectangle.northwest(rectangle)
    );
    var unrotatedSECorner = Ellipsoid.WGS84.cartographicToCartesian(
      Rectangle.southeast(rectangle)
    );

    var actual = new Cartesian3(positions[0], positions[1], positions[2]);
    expect(actual).toEqualEpsilon(unrotatedSECorner, CesiumMath.EPSILON8);

    actual = new Cartesian3(
      positions[length - 3],
      positions[length - 2],
      positions[length - 1]
    );
    expect(actual).toEqualEpsilon(unrotatedNWCorner, CesiumMath.EPSILON8);
  });

  it("compute texture coordinates with rotation", function () {
    var rectangle = new Rectangle(-1, -1, 1, 1);
    var angle = CesiumMath.PI_OVER_TWO;
    var m = RectangleGeometry.createGeometry(
      new RectangleGeometry({
        vertexFormat: VertexFormat.POSITION_AND_ST,
        rectangle: rectangle,
        stRotation: angle,
        granularity: 1.0,
      })
    );
    var positions = m.attributes.position.values;
    var st = m.attributes.st.values;
    var length = st.length;

    expect(positions.length).toEqual(9 * 3);
    expect(length).toEqual(9 * 2);
    expect(m.indices.length).toEqual(8 * 3);

    expect(st[length - 2]).toEqualEpsilon(0.0, CesiumMath.EPSILON14);
    expect(st[length - 1]).toEqualEpsilon(0.0, CesiumMath.EPSILON14);
  });

  it("compute texture coordinate rotation with rectangle rotation", function () {
    var rectangle = new Rectangle(-1, -1, 1, 1);
    var angle = CesiumMath.toRadians(30);
    var m = RectangleGeometry.createGeometry(
      new RectangleGeometry({
        vertexFormat: VertexFormat.POSITION_AND_ST,
        rectangle: rectangle,
        rotation: angle,
        stRotation: angle,
        granularity: 1.0,
      })
    );
    var st = m.attributes.st.values;

    expect(st[0]).toEqual(0.0); //top left corner
    expect(st[1]).toEqual(1.0);
    expect(st[4]).toEqual(1.0); //top right corner
    expect(st[5]).toEqual(1.0);
    expect(st[12]).toEqual(0.0); //bottom left corner
    expect(st[13]).toEqual(0.0);
    expect(st[16]).toEqual(1.0); //bottom right corner
    expect(st[17]).toEqual(0.0);
  });

  it("throws without rectangle", function () {
    expect(function () {
      return new RectangleGeometry({});
    }).toThrowDeveloperError();
  });

  it("throws if rotated rectangle is invalid", function () {
    expect(function () {
      return RectangleGeometry.createGeometry(
        new RectangleGeometry({
          rectangle: new Rectangle(
            -CesiumMath.PI_OVER_TWO,
            1,
            CesiumMath.PI_OVER_TWO,
            CesiumMath.PI_OVER_TWO
          ),
          rotation: CesiumMath.PI_OVER_TWO,
        })
      );
    }).toThrowDeveloperError();
  });

  it("throws if north is less than south", function () {
    expect(function () {
      return new RectangleGeometry({
        rectangle: new Rectangle(
          -CesiumMath.PI_OVER_TWO,
          CesiumMath.PI_OVER_TWO,
          CesiumMath.PI_OVER_TWO,
          -CesiumMath.PI_OVER_TWO
        ),
      });
    }).toThrowDeveloperError();
  });

  it("computes positions extruded", function () {
    var rectangle = new Rectangle(-2.0, -1.0, 0.0, 1.0);
    var m = RectangleGeometry.createGeometry(
      new RectangleGeometry({
        vertexFormat: VertexFormat.POSITION_ONLY,
        rectangle: rectangle,
        granularity: 1.0,
        extrudedHeight: 2,
      })
    );
    var positions = m.attributes.position.values;

    expect(positions.length).toEqual(42 * 3); // (9 fill + 8 edge + 4 corners) * 2 to duplicate for bottom
    expect(m.indices.length).toEqual(32 * 3); // 8 * 2 for fill top and bottom + 4 triangles * 4 walls
  });

  it("computes positions extruded at the north pole", function () {
    var rectangle = Rectangle.fromDegrees(-180.0, 89.0, -179.0, 90.0);
    var m = RectangleGeometry.createGeometry(
      new RectangleGeometry({
        vertexFormat: VertexFormat.POSITION_ONLY,
        rectangle: rectangle,
        extrudedHeight: 2,
      })
    );
    var positions = m.attributes.position.values;

    expect(positions.length).toEqual(26 * 3); // (5 fill + 5 edge + 3 corners) * 2 to duplicate for bottom
    expect(m.indices.length).toEqual(16 * 3); // 3 * 2 for fill top and bottom + 2 triangles * 5 walls
  });

  it("computes positions extruded at the south pole", function () {
    var rectangle = Rectangle.fromDegrees(-180.0, -90.0, -179.0, -89.0);
    var m = RectangleGeometry.createGeometry(
      new RectangleGeometry({
        vertexFormat: VertexFormat.POSITION_ONLY,
        rectangle: rectangle,
        extrudedHeight: 2,
      })
    );
    var positions = m.attributes.position.values;

    expect(positions.length).toEqual(26 * 3); // (5 fill + 5 edge + 3 corners) * 2 to duplicate for bottom
    expect(m.indices.length).toEqual(16 * 3); // 3 * 2 for fill top and bottom + 2 triangles * 5 walls
  });

  it("computes all attributes extruded", function () {
    var m = RectangleGeometry.createGeometry(
      new RectangleGeometry({
        vertexFormat: VertexFormat.ALL,
        rectangle: new Rectangle(-2.0, -1.0, 0.0, 1.0),
        granularity: 1.0,
        extrudedHeight: 2,
      })
    );
    var numVertices = 42;
    var numTriangles = 32;
    expect(m.attributes.position.values.length).toEqual(numVertices * 3);
    expect(m.attributes.st.values.length).toEqual(numVertices * 2);
    expect(m.attributes.normal.values.length).toEqual(numVertices * 3);
    expect(m.attributes.tangent.values.length).toEqual(numVertices * 3);
    expect(m.attributes.bitangent.values.length).toEqual(numVertices * 3);
    expect(m.indices.length).toEqual(numTriangles * 3);
  });

  it("compute positions with rotation extruded", function () {
    var rectangle = new Rectangle(-1, -1, 1, 1);
    var angle = CesiumMath.PI_OVER_TWO;
    var m = RectangleGeometry.createGeometry(
      new RectangleGeometry({
        vertexFormat: VertexFormat.POSITIONS_ONLY,
        rectangle: rectangle,
        rotation: angle,
        granularity: 1.0,
        extrudedHeight: 2,
      })
    );
    var positions = m.attributes.position.values;
    var length = positions.length;

    expect(length).toEqual(42 * 3);
    expect(m.indices.length).toEqual(32 * 3);

    var unrotatedSECorner = Rectangle.southeast(rectangle);
    var projection = new GeographicProjection();
    var projectedSECorner = projection.project(unrotatedSECorner);
    var rotation = Matrix2.fromRotation(angle);
    var rotatedSECornerCartographic = projection.unproject(
      Matrix2.multiplyByVector(rotation, projectedSECorner, new Cartesian2())
    );
    var rotatedSECorner = Ellipsoid.WGS84.cartographicToCartesian(
      rotatedSECornerCartographic
    );
    var actual = new Cartesian3(positions[51], positions[52], positions[53]);
    expect(actual).toEqualEpsilon(rotatedSECorner, CesiumMath.EPSILON6);
  });

  it("computes non-extruded rectangle if height is small", function () {
    var rectangle = new Rectangle(-2.0, -1.0, 0.0, 1.0);
    var m = RectangleGeometry.createGeometry(
      new RectangleGeometry({
        vertexFormat: VertexFormat.POSITION_ONLY,
        rectangle: rectangle,
        granularity: 1.0,
        extrudedHeight: CesiumMath.EPSILON14,
      })
    );
    var positions = m.attributes.position.values;

    var numVertices = 9;
    var numTriangles = 8;
    expect(positions.length).toEqual(numVertices * 3);
    expect(m.indices.length).toEqual(numTriangles * 3);
  });

  it("computes offset attribute", function () {
    var rectangle = new Rectangle(-2.0, -1.0, 0.0, 1.0);
    var m = RectangleGeometry.createGeometry(
      new RectangleGeometry({
        vertexFormat: VertexFormat.POSITION_ONLY,
        rectangle: rectangle,
        granularity: 1.0,
        offsetAttribute: GeometryOffsetAttribute.TOP,
      })
    );
    var positions = m.attributes.position.values;

    var numVertices = 9;
    expect(positions.length).toEqual(numVertices * 3);

    var offset = m.attributes.applyOffset.values;
    expect(offset.length).toEqual(numVertices);
    var expected = new Array(offset.length);
    expected = arrayFill(expected, 1);
    expect(offset).toEqual(expected);
  });

  it("computes offset attribute extruded for top vertices", function () {
    var rectangle = new Rectangle(-2.0, -1.0, 0.0, 1.0);
    var m = RectangleGeometry.createGeometry(
      new RectangleGeometry({
        vertexFormat: VertexFormat.POSITION_ONLY,
        rectangle: rectangle,
        granularity: 1.0,
        extrudedHeight: 2,
        offsetAttribute: GeometryOffsetAttribute.TOP,
      })
    );
    var positions = m.attributes.position.values;

    var numVertices = 42; // (9 fill + 8 edge + 4 corners) * 2 to duplicate for bottom
    expect(positions.length).toEqual(numVertices * 3);

    var offset = m.attributes.applyOffset.values;
    expect(offset.length).toEqual(numVertices);
    var expected = new Array(offset.length);
    expected = arrayFill(expected, 0);
    expected = arrayFill(expected, 1, 0, 9);
    for (var i = 18; i < offset.length; i += 2) {
      expected[i] = 1;
    }
    expect(offset).toEqual(expected);
  });

  it("computes offset attribute extruded for all vertices", function () {
    var rectangle = new Rectangle(-2.0, -1.0, 0.0, 1.0);
    var m = RectangleGeometry.createGeometry(
      new RectangleGeometry({
        vertexFormat: VertexFormat.POSITION_ONLY,
        rectangle: rectangle,
        granularity: 1.0,
        extrudedHeight: 2,
        offsetAttribute: GeometryOffsetAttribute.ALL,
      })
    );
    var positions = m.attributes.position.values;

    var numVertices = 42; // (9 fill + 8 edge + 4 corners) * 2 to duplicate for bottom
    expect(positions.length).toEqual(numVertices * 3);

    var offset = m.attributes.applyOffset.values;
    expect(offset.length).toEqual(numVertices);
    var expected = new Array(offset.length);
    expected = arrayFill(expected, 1);
    for (var i = 18; i < offset.length; i += 2) {
      expected[i] = 1;
    }
    expect(offset).toEqual(expected);
  });

  it("undefined is returned if any side are of length zero", function () {
    var rectangle0 = new RectangleGeometry({
      rectangle: Rectangle.fromDegrees(-80.0, 39.0, -80.0, 42.0),
    });
    var rectangle1 = new RectangleGeometry({
      rectangle: Rectangle.fromDegrees(-81.0, 42.0, -80.0, 42.0),
    });
    var rectangle2 = new RectangleGeometry({
      rectangle: Rectangle.fromDegrees(-80.0, 39.0, -80.0, 39.0),
    });

    var geometry0 = RectangleGeometry.createGeometry(rectangle0);
    var geometry1 = RectangleGeometry.createGeometry(rectangle1);
    var geometry2 = RectangleGeometry.createGeometry(rectangle2);

    expect(geometry0).toBeUndefined();
    expect(geometry1).toBeUndefined();
    expect(geometry2).toBeUndefined();
  });

  it("computing rectangle property", function () {
    var rectangle = new Rectangle.fromDegrees(-1.0, -1.0, 1.0, 1.0);
    var geometry = new RectangleGeometry({
      vertexFormat: VertexFormat.POSITION_ONLY,
      rectangle: rectangle,
      granularity: 1.0,
    });

    var r = geometry.rectangle;
    expect(CesiumMath.toDegrees(r.north)).toEqual(1.0);
    expect(CesiumMath.toDegrees(r.south)).toEqual(-1.0);
    expect(CesiumMath.toDegrees(r.east)).toEqual(1.0);
    expect(CesiumMath.toDegrees(r.west)).toEqual(-1.0);
  });

  it("computing rectangle property with rotation", function () {
    var rectangle = new Rectangle.fromDegrees(-1.0, -1.0, 1.0, 1.0);
    var geometry = new RectangleGeometry({
      vertexFormat: VertexFormat.POSITION_ONLY,
      rectangle: rectangle,
      granularity: 1.0,
      rotation: CesiumMath.toRadians(45.0),
    });

    var r = geometry.rectangle;
    expect(CesiumMath.toDegrees(r.north)).toEqualEpsilon(
      1.414213562373095,
      CesiumMath.EPSILON15
    );
    expect(CesiumMath.toDegrees(r.south)).toEqualEpsilon(
      -1.414213562373095,
      CesiumMath.EPSILON15
    );
    expect(CesiumMath.toDegrees(r.east)).toEqualEpsilon(
      1.414213562373095,
      CesiumMath.EPSILON15
    );
    expect(CesiumMath.toDegrees(r.west)).toEqualEpsilon(
      -1.4142135623730951,
      CesiumMath.EPSILON15
    );
  });

  it("computing textureCoordinateRotationPoints property", function () {
    var rectangle = new Rectangle.fromDegrees(-1.0, -1.0, 1.0, 1.0);
    var geometry = new RectangleGeometry({
      vertexFormat: VertexFormat.POSITION_ONLY,
      rectangle: rectangle,
      granularity: 1.0,
      rotation: CesiumMath.toRadians(90.0),
    });

    // 90 degree rotation means (0, 1) should be the new min and (1, 1) (0, 0) are extents
    var textureCoordinateRotationPoints =
      geometry.textureCoordinateRotationPoints;
    expect(textureCoordinateRotationPoints.length).toEqual(6);
    expect(textureCoordinateRotationPoints[0]).toEqualEpsilon(
      0,
      CesiumMath.EPSILON7
    );
    expect(textureCoordinateRotationPoints[1]).toEqualEpsilon(
      0,
      CesiumMath.EPSILON7
    );
    expect(textureCoordinateRotationPoints[2]).toEqualEpsilon(
      0,
      CesiumMath.EPSILON7
    );
    expect(textureCoordinateRotationPoints[3]).toEqualEpsilon(
      1,
      CesiumMath.EPSILON7
    );
    expect(textureCoordinateRotationPoints[4]).toEqualEpsilon(
      1,
      CesiumMath.EPSILON7
    );
    expect(textureCoordinateRotationPoints[5]).toEqualEpsilon(
      0,
      CesiumMath.EPSILON7
    );

    geometry = new RectangleGeometry({
      vertexFormat: VertexFormat.POSITION_ONLY,
      rectangle: rectangle,
      granularity: 1.0,
      rotation: CesiumMath.toRadians(90.0),
    });

    textureCoordinateRotationPoints = geometry.textureCoordinateRotationPoints;
    expect(textureCoordinateRotationPoints.length).toEqual(6);
    expect(textureCoordinateRotationPoints[0]).toEqualEpsilon(
      0,
      CesiumMath.EPSILON7
    );
    expect(textureCoordinateRotationPoints[1]).toEqualEpsilon(
      0,
      CesiumMath.EPSILON7
    );
    expect(textureCoordinateRotationPoints[2]).toEqualEpsilon(
      0,
      CesiumMath.EPSILON7
    );
    expect(textureCoordinateRotationPoints[3]).toEqualEpsilon(
      1,
      CesiumMath.EPSILON7
    );
    expect(textureCoordinateRotationPoints[4]).toEqualEpsilon(
      1,
      CesiumMath.EPSILON7
    );
    expect(textureCoordinateRotationPoints[5]).toEqualEpsilon(
      0,
      CesiumMath.EPSILON7
    );
  });

  it("computeRectangle", function () {
    var options = {
      vertexFormat: VertexFormat.POSITION_ONLY,
      rectangle: new Rectangle.fromDegrees(-1.0, -1.0, 1.0, 1.0),
      granularity: 1.0,
      ellipsoid: Ellipsoid.UNIT_SPHERE,
      rotation: CesiumMath.PI,
    };
    var geometry = new RectangleGeometry(options);

    var expected = geometry.rectangle;
    var result = RectangleGeometry.computeRectangle(options);

    expect(result).toEqual(expected);
  });

  it("computeRectangle with result parameter", function () {
    var options = {
      vertexFormat: VertexFormat.POSITION_ONLY,
      rectangle: new Rectangle.fromDegrees(-1.0, -1.0, 1.0, 1.0),
    };
    var geometry = new RectangleGeometry(options);

    var result = new Rectangle();
    var expected = geometry.rectangle;
    var returned = RectangleGeometry.computeRectangle(options, result);

    expect(returned).toEqual(expected);
    expect(returned).toBe(result);
  });

  it("computing rectangle property with zero rotation", function () {
    expect(function () {
      return RectangleGeometry.createGeometry(
        new RectangleGeometry({
          vertexFormat: VertexFormat.POSITION_ONLY,
          rectangle: Rectangle.MAX_VALUE,
          granularity: 1.0,
          rotation: 0,
        })
      );
    }).not.toThrowDeveloperError();
  });

  it("can create rectangle geometry where the nw corner and the center are on opposite sides of the IDL", function () {
    var rectangle = new Rectangle(
      Math.PI - 0.005,
      CesiumMath.PI_OVER_SIX + 0.02,
      0.01 - Math.PI,
      CesiumMath.PI_OVER_SIX + 0.04
    );

    var geometry = new RectangleGeometry({
      rectangle: rectangle,
      rotation: 0.5,
    });

    expect(function () {
      RectangleGeometry.createGeometry(geometry);
    }).not.toThrowDeveloperError();
  });

  var rectangle = new RectangleGeometry({
    vertexFormat: VertexFormat.POSITION_ONLY,
    rectangle: new Rectangle(-2.0, -1.0, 0.0, 1.0),
    granularity: 1.0,
    ellipsoid: Ellipsoid.UNIT_SPHERE,
  });
  var packedInstance = [
    -2.0,
    -1.0,
    0.0,
    1.0,
    1.0,
    1.0,
    1.0,
    1.0,
    0.0,
    0.0,
    0.0,
    0.0,
    0.0,
    1.0,
    0.0,
    0.0,
    0.0,
    0.0,
    0.0,
    -1,
  ];
  createPackableSpecs(RectangleGeometry, rectangle, packedInstance);
});
