/*
 * Renderer 5. The MIT License.
 * Copyright (c) 2022 rlkraft@pnw.edu
 * See LICENSE for details.
*/

package renderer.pipeline;

import renderer.scene.*;
import renderer.scene.primitives.*;
import static renderer.pipeline.PipelineLogger.*;

import java.util.List;
import java.util.ArrayList;
import java.util.Optional;

/**
   Clip in camera space any {@link Point} that crosses the
   camera's near clipping plane {@code z = -near}.
*/
public class NearClip_Point
{
   /**
      If the {@link Vertex} used by the {@link Point} is on the camera
      side of the near plane, then return an empty {@link Optional}
      object to indicate that the {@link Point} should be discarded
      from the model's {@link Primitive} list.
      <p>
      If the {@link Vertex} used by the {@link Point} is on the far
      side of the near plane, then return the {@link Point} wrapped
      in an {@link Optional} object.

      @param model   {@link Model} that the {@link Point} {@code pt} comes from
      @param pt      {@link Point} to be clipped
      @param camera  {@link Camera} that determines the near clipping plane
      @return the clipped version of {@code pt} wrapped in an {@link Optional} object
   */
   public static Optional<Primitive> clip(final Model model,
                                          final Point pt,
                                          final Camera camera)
   {
      final Optional<Primitive> result;

      // Make local copies of several values.
      final int vIndex = pt.vIndexList.get(0);
      final Vertex v = model.vertexList.get(vIndex);

      final double z = v.z;

      // 1. Check for trivial accept.
      if ( z <= camera.n )
      {
         result = Optional.of(pt); // better than "return pt"
      }
      // 2. Trivial delete.
      else
      {
         result = Optional.empty(); // better than "return null"
      }

      return result;
   }



   // Private default constructor to enforce noninstantiable class.
   // See Item 4 in "Effective Java", 3rd Ed, Joshua Bloch.
   private NearClip_Point() {
      throw new AssertionError();
   }
}
