/*
 * RingGeometry.ts
 * Created by 还有醋v on 2021/4/15.
 * Copyright © 2021 haiyoucuv. All rights reserved.
 */

import { Geometry } from "../Geometry";
import { Vector2 } from "../math/Vector2";
import { Vector3 } from "../math/Vector3";

export class RingGeometry extends Geometry {
    constructor(
        innerRadius = 0.5,
        outerRadius = 1,
        thetaSegments = 8,
        phiSegments = 1,
        thetaStart = 0,
        thetaLength = Math.PI * 2
    ) {

        thetaSegments = Math.max(3, thetaSegments);
        phiSegments = Math.max(1, phiSegments)

        // buffers
        const indices = [];
        const vertices = [];
        const normals = [];
        const uvs = [];

        // some helper variables
        let segment;
        let radius = innerRadius;
        const radiusStep = ((outerRadius - innerRadius) / phiSegments);
        const vertex = new Vector3();
        const uv = new Vector2();
        let j, i;

        // generate vertices, normals and uvs
        for (j = 0; j <= phiSegments; j++) {

            for (i = 0; i <= thetaSegments; i++) {

                // values are generate from the inside of the ring to the outside
                segment = thetaStart + i / thetaSegments * thetaLength;

                // vertex
                vertex.x = radius * Math.cos(segment);
                vertex.y = radius * Math.sin(segment);

                vertices.push(vertex.x, vertex.y, vertex.z);

                // normal
                normals.push(0, 0, 1);

                // uv
                uv.x = (vertex.x / outerRadius + 1) / 2;
                uv.y = 1 - (vertex.y / outerRadius + 1) / 2;

                uvs.push(uv.x, uv.y);

            }

            // increase the radius for next row of vertices
            radius += radiusStep;

        }

        // indices
        for (j = 0; j < phiSegments; j++) {

            const thetaSegmentLevel = j * (thetaSegments + 1);

            for (i = 0; i < thetaSegments; i++) {

                segment = i + thetaSegmentLevel;

                const a = segment;
                const b = segment + thetaSegments + 1;
                const c = segment + thetaSegments + 2;
                const d = segment + 1;

                // faces
                indices.push(a, b, d);
                indices.push(b, c, d);

            }

        }

        super(vertices, indices, normals, null, uvs);
    }

}
