001/* 002 * Renderer 9. 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.util.CheckModel; 011import renderer.framebuffer.*; 012import static renderer.pipeline.PipelineLogger.*; 013 014import java.awt.Color; 015 016/** 017 This renderer takes as its input a {@link Scene} data structure 018 and a {@link FrameBuffer.Viewport} within a {@link FrameBuffer} 019 data structure. This renderer mutates the {@link FrameBuffer.Viewport} 020 so that it is filled in with the rendered image of the geometric 021 scene represented by the {@link Scene} object. 022<p> 023 This implements our seventh rendering pipeline. It converts the 024 transformation stage {@link Model2World} to use {@link Matrix} 025 transformations instead of just using {@link Vector} translations. 026 There are still seven pipeline stages. 027*/ 028public final class Pipeline2 029{ 030 // Mostly for compatibility with renderers 1 through 3. 031 public static Color DEFAULT_COLOR = Color.white; 032 033 // Make all the intermediate Scene objects 034 // available for special effects processing. 035 public static Scene scene1 = null; 036 public static Scene scene2 = null; 037 public static Scene scene3 = null; 038 public static Scene scene4 = null; 039 public static Scene scene5 = null; 040 public static Scene scene6 = null; 041 042 /** 043 Mutate the {@link FrameBuffer}'s default {@link FrameBuffer.Viewport} 044 so that it holds the rendered image of the {@link Scene} object. 045 046 @param scene {@link Scene} object to render 047 @param fb {@link FrameBuffer} to hold rendered image of the {@link Scene} 048 */ 049 public static void render(final Scene scene, final FrameBuffer fb) 050 { 051 render(scene, fb.vp); // render into the default viewport 052 } 053 054 055 /** 056 Mutate the {@link FrameBuffer}'s given {@link FrameBuffer.Viewport} 057 so that it holds the rendered image of the {@link Scene} object. 058 059 @param scene {@link Scene} object to render 060 @param vp {@link FrameBuffer.Viewport} to hold rendered image of the {@link Scene} 061 */ 062 public static void render(final Scene scene, final FrameBuffer.Viewport vp) 063 { 064 PipelineLogger.debugScene = scene.debug; 065 066 logMessage("\n= Begin Rendering of Scene (Pipeline 2): " + scene.name + " ="); 067 068 logMessage("- Current Camera:\n" + scene.camera); 069 070 scene1 = new Scene(scene.name, scene.camera); 071 072 logMessage("== 1. Begin model-to-world transformation of Scene ===="); 073 for (final Position position : scene.positionList) 074 { 075 PipelineLogger.debugPosition = position.debug; 076 077 if ( position.visible ) 078 { 079 logMessage("==== 1. Render position: " 080 + position.name + " ===="); 081 082 logMessage("---- Transformation matrix:\n" + position.getMatrix()); 083 084 if ( position.getModel().visible ) 085 { 086 logMessage("==== 1. Model-to-world transform of: " 087 + position.getModel().name + " ===="); 088 089 CheckModel.check(position.getModel()); 090 091 // Mostly for compatibility with renderers 1 through 3. 092 if ( position.getModel().colorList.isEmpty() 093 && !position.getModel().vertexList.isEmpty()) 094 { 095 for (int i = 0; i < position.getModel().vertexList.size(); ++i) 096 { 097 position.getModel().addColor( DEFAULT_COLOR ); 098 } 099 System.err.println("***WARNING: Added default color to model: " 100 + position.getModel().name + "."); 101 } 102 103 logVertexList("0. Model ", position.getModel()); 104 105 final Model tempModel = Model2World.model2world(position); 106 107 logVertexList("1. World ", tempModel); 108 109 scene1.addPosition( new Position(tempModel) ); 110 111 logMessage("==== 1. End Model: " 112 + tempModel.name + " ===="); 113 } 114 else 115 { 116 logMessage("==== 1. Hidden model: " 117 + position.getModel().name + " ===="); 118 } 119 120 logMessage("==== 1. End position: " 121 + position.name + " ===="); 122 } 123 else 124 { 125 logMessage("==== 1. Hidden position: " 126 + position.name + " ===="); 127 } 128 } 129 logMessage("== 1. End model-to-world transformation of Scene ===="); 130 131 scene2 = new Scene(scene.name, scene.camera); 132 133 logMessage("== 2. Begin world-to-view transformation of Scene ===="); 134 for (final Position position : scene1.positionList) 135 { 136 logMessage("==== 2. Transform model: " 137 + position.getModel().name + " ===="); 138 139 final Model tempModel = World2View.world2view(position.getModel(), 140 scene.camera); 141 142 logVertexList("2. View ", tempModel); 143 144 scene2.addPosition( new Position(tempModel) ); 145 146 logMessage("==== 2. End Model: " + tempModel.name + " ===="); 147 } 148 logMessage("== 2. End view-to-camera transformation of Scene ===="); 149 150 scene3 = new Scene(scene.name, scene.camera); 151 152 logMessage("== 3. Begin view-to-camera transformation of Scene ===="); 153 for (final Position position : scene2.positionList) 154 { 155 logMessage("==== 3. Transform model: " 156 + position.getModel().name + " ===="); 157 158 final Model tempModel = View2Camera.view2camera(position.getModel(), 159 scene.camera); 160 161 logVertexList("3. Camera ", tempModel); 162 logColorList("3. Camera ", tempModel); 163 logPrimitiveList("3. Camera ", tempModel); 164 165 scene3.addPosition( new Position(tempModel) ); 166 167 logMessage("==== 3. End Model: " + tempModel.name + " ===="); 168 } 169 logMessage("== 3. End view-to-camera transformation of Scene ===="); 170 171 scene4 = new Scene(scene.name, scene.camera); 172 173 logMessage("== 4. Begin near-plane clipping of Scene ===="); 174 for (final Position position : scene3.positionList) 175 { 176 logMessage("==== 4. Near_Clip model: " 177 + position.getModel().name + " ===="); 178 179 final Model tempModel = NearClip.clip(position.getModel(), 180 scene.camera); 181 182 logVertexList("4. Near_Clipped ", tempModel); 183 logColorList("4. Near_Clipped ", tempModel); 184 logPrimitiveList("4. Near_Clipped ", tempModel); 185 186 scene4.addPosition( new Position(tempModel) ); 187 188 logMessage("==== 4. End Model: " + tempModel.name + " ===="); 189 } 190 logMessage("== 4. End near-plane clipping of Scene ===="); 191 192 scene5 = new Scene(scene.name, scene.camera); 193 194 logMessage("== 5. Begin projection transformation of Scene ===="); 195 for (final Position position : scene4.positionList) 196 { 197 logMessage("==== 5. Project model: " 198 + position.getModel().name + " ===="); 199 200 final Model tempModel = Projection.project(position.getModel(), 201 scene.camera); 202 203 logVertexList("5. Projected", tempModel); 204 //logPrimitiveList("5. Projected ", tempModel); 205 206 scene5.addPosition( new Position(tempModel) ); 207 208 logMessage("==== 5. End Model: " + tempModel.name + " ===="); 209 } 210 logMessage("== 5. End projection transformation of Scene ===="); 211 212 scene6 = new Scene(scene.name, scene.camera); 213 214 logMessage("== 6. Begin clipping of Scene ===="); 215 for (final Position position : scene5.positionList) 216 { 217 logMessage("==== 6. Clip model: " 218 + position.getModel().name + " ===="); 219 220 final Model tempModel = Clip.clip(position.getModel()); 221 222 logVertexList("6. Clipped ", tempModel); 223 logColorList("6. Clipped ", tempModel); 224 logPrimitiveList("6. Clipped ", tempModel); 225 226 scene6.addPosition( new Position(tempModel) ); 227 228 logMessage("==== 6. End Model: " + tempModel.name + " ===="); 229 } 230 logMessage("== 6. End clipping of Scene ===="); 231 232 logMessage("== 7. Begin rasterization of Scene ===="); 233 for (final Position position : scene6.positionList) 234 { 235 logMessage("==== 7. Rasterize model: " 236 + position.getModel().name + " ===="); 237 238 Rasterize.rasterize(position.getModel(), vp); 239 240 logMessage("==== 7. End Model: " 241 + position.getModel().name + " ===="); 242 } 243 logMessage("== 7. End rasterization of Scene ===="); 244 245 logMessage("= End Rendering of Scene (Pipeline 2) ="); 246 } 247 248 249 250 // Private default constructor to enforce noninstantiable class. 251 // See Item 4 in "Effective Java", 3rd Ed, Joshua Bloch. 252 private Pipeline2() { 253 throw new AssertionError(); 254 } 255}