001/*
002
003*/
004
005package renderer.pipeline;
006import  renderer.scene.*;
007import  renderer.framebuffer.*;
008
009import java.util.List;
010import java.util.ArrayList;
011
012/**
013   This renderer takes as its input a {@link Scene} data structure
014   and a {@link FrameBuffer} data structure. This renderer mutates
015   the {@link FrameBuffer}'s current viewport so that it is filled
016   in with the rendered image of the scene represented by the
017   {@link Scene} object.
018<p>
019   This implements our fifth rendering pipeline. This pipeline can
020   process the colors stored in each {@link Vertex}. This renderer
021   has the same four pipeline stages but {@link Vertex} color is
022   interpolated by the {@link Clip} stage and {@link Vertex} color
023   is also interpolated to pixels by the {@link Rasterize} stage.
024*/
025public class Pipeline
026{
027   public static boolean doAntialiasing = false;
028   public static boolean debug = false;
029
030   /**
031      Mutate the {@link FrameBuffer}'s current viewport so that
032      it holds the rendered image of the {@link Scene} object.
033
034      @param scene  {@link Scene} object to render
035      @param fb     {@link FrameBuffer} to hold rendered image of the {@link Scene}
036   */
037   public static void render(Scene scene, FrameBuffer fb)
038   {
039      if ( debug )
040         render_debug(scene, fb);
041      else
042         render_(scene, fb);
043   }
044
045
046   /**
047      Renderer the {@link Scene} without any debugging information.
048
049      @param scene  {@link Scene} object to render
050      @param fb     {@link FrameBuffer} to hold rendered image of the {@link Scene}
051   */
052   private static void render_(Scene scene, FrameBuffer fb)
053   {
054      // Render every Model in the Scene.
055      for (Model model : scene.modelList)
056      {
057         if ( model.visible )
058         {
059            // 0. Make a deep copy of the model.
060            Model model2 = new Model(model);
061
062            // 1. Apply the projection transformation.
063            Projection.project(model2.vertexList, scene.camera);
064
065            // 2. Clip each line segment to the standard view rectangle.
066            List<LineSegment> lineSegmentList2 = new ArrayList<>();
067            for (LineSegment ls : model2.lineSegmentList)
068            {
069               if ( Clip.clip(ls) )
070               {
071                  // Keep the line segments that are visible.
072                  lineSegmentList2.add(ls);
073               }
074            }
075            model2.lineSegmentList = lineSegmentList2;
076
077            // 3. Apply viewport transformation to each visible line segment.
078            // (Alternatively, we could apply viewport transformation to every vertex?)
079            boolean[] transformed = new boolean[model2.vertexList.size()];
080            for (LineSegment ls : model2.lineSegmentList)
081            {
082               Viewport.viewport(ls, transformed, fb);
083            }
084
085            // 4. Rasterize each visible line segment into pixels.
086            for (LineSegment ls : model2.lineSegmentList)
087            {
088               if ( doAntialiasing )
089               {
090                  RasterizeAntialias.rasterize(ls, fb);
091               }
092               else
093               {
094                  Rasterize.rasterize(ls, fb);
095               }
096            }
097         }
098      }
099   }
100
101
102
103   /**
104      Render the {@link Scene} with quite a bit of debugging information.
105
106      @param scene  {@link Scene} object to render
107      @param fb     {@link FrameBuffer} to hold rendered image of the {@link Scene}
108   */
109   private static void render_debug(Scene scene, FrameBuffer fb)
110   {
111      System.out.println("=== Render Scene ===================================");
112
113      // Render every Model in the Scene.
114      for (Model model : scene.modelList)
115      {
116         System.out.println("=== Render Model ===================================");
117
118         if ( model.visible )
119         {
120            // 0. Make a deep copy of the model.
121            Model model2 = new Model(model);
122
123            // log interesting information to standard output
124            logVertexList("0. Input    ", model2.vertexList);
125
126            // 1. Apply the projection transformation.
127            Projection.project(model2.vertexList, scene.camera);
128
129            // log interesting information to standard output
130            logVertexList("1. Projected", model2.vertexList);
131
132            // 2. Clip each line segment to the standard view rectangle.
133            List<LineSegment> lineSegmentList2 = new ArrayList<>();
134            for (LineSegment ls : model2.lineSegmentList)
135            {
136               // log interesting information to standard output
137               logLineSegment("2. Clipping", ls);
138
139               if ( Clip.clip(ls) )
140               {
141                  // log interesting information to standard output
142                  logLineSegment("2. Clipped (accept)", ls);
143
144                  // Keep the line segments that are visible.
145                  lineSegmentList2.add(ls);
146               }
147               else
148               {
149                  // log interesting information to standard output
150                  logLineSegment("2. Clipped (reject)", ls);
151               }
152            }
153            model2.lineSegmentList = lineSegmentList2;
154
155            // log interesting information to standard output
156            logVertexList("2. Clipped  ", model2.vertexList);
157
158            // 3. Apply viewport transformation to each visible line segment.
159            boolean[] transformed = new boolean[model2.vertexList.size()];
160            for (LineSegment ls : model2.lineSegmentList)
161            {
162               Viewport.viewport(ls, transformed, fb);
163
164               // log interesting information to standard output
165               logLineSegment("3. Viewport ", ls);
166            }
167
168            // 4. Rasterize each visible line segment into pixels.
169            for (LineSegment ls : model2.lineSegmentList)
170            {
171               // log interesting information to standard output
172               logLineSegment("4. Rasterize", ls);
173
174               if ( doAntialiasing )
175               {
176                  RasterizeAntialias.rasterize(ls, fb);
177               }
178               else
179               {
180                  Rasterize.rasterize(ls, fb);
181               }
182            }
183            System.out.println();
184         }
185         else
186         {
187            System.out.println("   Hidden model.");
188         }
189         System.out.println("=== End Model ===================================");
190      }
191      System.out.println("=== End Scene ===================================");
192   }
193
194
195   /**
196      This method prints a {@link String} representation of the given vertex list.
197
198      @param stage       name for the pipeline stage
199      @param vertexList  vertex list whose string representation is to be printed
200   */
201   private static void logVertexList(String stage, List<Vertex> vertexList)
202   {
203      int i = 0;
204      for (Vertex v : vertexList)
205      {
206         System.out.printf( stage + ": index = %3d, " + v.toString(), i );
207         i++;
208      }
209   }
210
211
212   /**
213      This method prints a {@link String} representation of the given {@link LineSegment}.
214
215      @param stage  name for the pipeline stage
216      @param ls     {@link LineSegment} whose string representation is to be printed
217   */
218   private static void logLineSegment(String stage, LineSegment ls)
219   {
220      System.out.print( stage + ": " + ls.toString() );
221      int index0 = ls.index[0];
222      int index1 = ls.index[1];
223      Vertex v0 = ls.model.vertexList.get(index0);
224      Vertex v1 = ls.model.vertexList.get(index1);
225      System.out.printf("    index = %3d, " + v0.toString(), index0);
226      System.out.printf("                 " + v0.toStringColor());
227      System.out.printf("    index = %3d, " + v1.toString(), index1);
228      System.out.printf("                 " + v1.toStringColor(), index1);
229   }
230}