package terra.primitive;

import java.util.*;
import terra.math.*;
import terra.math.Vector;

public class Sphere extends Quadric {
    private final float radius;

    public Sphere(Attributes attributes, float radius, float startU, float endU, float startV, float endV)
    {
        super(attributes, startU, endU, startV, endV);

        this.radius = radius;
    }

    @Override
    public void split(LinkedList<Primitive> prims)
    {
        int width = 4;
        int height = 2;

        for (int i = 0; i < height; ++i) {
            for (int j = 0; j < width; ++j) {
                float su = startU + (endU - startU) * j / width;
                float sv = startV + (endV - startV) * i / height;

                float eu = startU + (endU - startU) * (j + 1) / width;
                float ev = startV + (endV - startV) * (i + 1) / height;

                prims.addFirst(new Sphere(attributes, radius, su, eu, sv, ev));
            }
        }
    }

    @Override
    Point evaluatePosition(float u, float v)
    {
        float theta = (float)Math.PI * 2.0f * u;
        float phi = (float)Math.PI * v;

        return new Point(
            radius * (float)Math.cos(theta) * (float)Math.sin(phi),
            radius * (float)Math.cos(phi),
            radius * (float)Math.sin(theta) * (float)Math.sin(phi));
    }

    @Override
    Vector evaluateNormal(float u, float v)
    {
        float theta = (float)Math.PI * 2.0f * u;
        float phi = (float)Math.PI * v;

        return new Vector(
            (float)Math.cos(theta) * (float)Math.sin(phi),
            (float)Math.cos(phi),
            (float)Math.sin(theta) * (float)Math.sin(phi));
    }
}
