001/*
002 * Renderer 7. The MIT License.
003 * Copyright (c) 2022 rlkraft@pnw.edu
004 * See LICENSE for details.
005*/
006
007package renderer.pipeline;
008
009import renderer.scene.*;
010import renderer.scene.primitives.Point;
011import renderer.framebuffer.*;
012import static renderer.pipeline.PipelineLogger.*;
013
014import java.awt.Color;
015
016/**
017   Rasterize a clipped {@link Point} into shaded pixels
018   in a {@link FrameBuffer.Viewport}, but do not rasterize
019   any part of the {@link Point} that is not contained in
020   the {@link Camera}'s view rectangle.
021*/
022public class Rasterize_Clip_Point
023{
024   /**
025      Rasterize a {@link Point} into shaded pixels
026      in a {@link FrameBuffer.Viewport}.
027
028      @param model  {@link Model} that the {@link Point} {@code pt} comes from
029      @param pt     {@code Point} to rasterize into the {@code FrameBuffer.Viewport}
030      @param vp     {@link FrameBuffer.Viewport} to hold rasterized, shaded pixels
031   */
032   public static void rasterize(final Model model,
033                                final Point pt,
034                                final FrameBuffer.Viewport vp)
035   {
036      final String     CLIPPED = " : Clipped";
037      final String NOT_CLIPPED = "";
038
039      // Get the viewport's background color.
040      final Color bg = vp.bgColorVP;
041
042      // Make local copies of several values.
043      final int w = vp.getWidthVP();
044      final int h = vp.getHeightVP();
045
046      final int vIndex = pt.vIndexList.get(0);
047      final Vertex v = model.vertexList.get(vIndex);
048
049      final int cIndex = pt.cIndexList.get(0);
050      final float[] c = model.colorList.get(cIndex).getRGBComponents(null);
051      float r = c[0], g = c[1], b = c[2];
052
053      if (Rasterize.doGamma)
054      {
055         // Apply gamma-encoding (gamma-compression) to the two colors.
056         // https://www.scratchapixel.com/lessons/digital-imaging/digital-images
057         // http://blog.johnnovak.net/2016/09/21/what-every-coder-should-know-about-gamma/
058         final double gammaInv = 1.0 / Rasterize.GAMMA;
059         r = (float)Math.pow(r, gammaInv);
060         g = (float)Math.pow(g, gammaInv);
061         b = (float)Math.pow(b, gammaInv);
062      }
063
064      // Transform the vertex to the pixel-plane coordinate system.
065      double x = 0.5 + w/2.001 * (v.x + 1); // x_pp = 0.5 + w/2 * (x_p+1)
066      double y = 0.5 + h/2.001 * (v.y + 1); // y_pp = 0.5 + h/2 * (y_p+1)
067      // NOTE: Notice the 2.001 fudge factor in the last two equations.
068      // This is explained on page 142 of
069      //    "Jim Blinn's Corner: A Trip Down The Graphics Pipeline"
070      //     by Jim Blinn, 1996, Morgan Kaufmann Publishers.
071
072      if (Rasterize.debug)
073      {
074         logMessage(String.format("(x_pp, y_pp) = (%9.4f, %9.4f)", x, y));
075      }
076
077      // Round the point's coordinates to the nearest logical pixel.
078      x = Math.round( x );
079      y = Math.round( y );
080
081      final int radius = pt.radius;
082
083      for (int y_ = (int)y - radius; y_ <= (int)y + radius; ++y_)
084      {
085         for (int x_ = (int)x - radius; x_ <= (int)x + radius; ++x_)
086         {
087            if (Rasterize.debug)
088            {
089               final String clippedMessage;
090               if (x_ > 0 && x_ <= w && y_ > 0 && y_ <= h) // clipping test
091               {
092                  clippedMessage = NOT_CLIPPED;
093               }
094               else
095               {
096                  clippedMessage = CLIPPED;
097               }
098               logPixel(clippedMessage, x, y, x_ - 1, h - y_, r, g, b, vp);
099            }
100            // Log the pixel before setting it so that an array out-
101            // of-bounds error will be right after the pixel's address.
102
103            if (x_ > 0 && x_ <= w && y_ > 0 && y_ <= h) // clipping test
104            {
105               vp.setPixelVP(x_ - 1, h - y_, new Color(r, g, b));
106            }
107         }
108      }
109   }
110
111
112
113   // Private default constructor to enforce noninstantiable class.
114   // See Item 4 in "Effective Java", 3rd Ed, Joshua Bloch.
115   private Rasterize_Clip_Point() {
116      throw new AssertionError();
117   }
118}