00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <archon/util/window.H>
00021 #include <archon/util/time.H>
00022 #include <archon/util/thread.H>
00023 #include <archon/util/kdtree.H>
00024 #include <archon/util/adaptive_skip.H>
00025 #include <archon/util/color.H>
00026 #include <archon/util/image.H>
00027 #include <archon/util/progress_meter.H>
00028
00029 #include "options.H"
00030 #include "world.H"
00031 #include "engine.H"
00032
00033 #if ! defined M_PI
00034 #define M_E 2.7182818284590452353602874713526625
00035 #define M_LOG2E 1.4426950408889634073599246810018922
00036 #define M_LOG10E 0.4342944819032518276511289189166051
00037 #define M_LN2 0.6931471805599453094172321214581766
00038 #define M_LN10 2.3025850929940456840179914546843642
00039 #define M_PI 3.1415926535897932384626433832795029
00040 #define M_PI_2 1.5707963267948966192313216916397514
00041 #define M_PI_4 0.7853981633974483096156608458198757
00042 #define M_1_PI 0.3183098861837906715377675267450287
00043 #define M_2_PI 0.6366197723675813430755350534900574
00044 #define M_2_SQRTPI 1.1283791670955125738961589031215452
00045 #define M_SQRT2 1.4142135623730950488016887242096981
00046 #define M_SQRT1_2 0.7071067811865475244008443621048490
00047 #endif
00048
00049 using namespace std;
00050
00051 namespace Archon
00052 {
00053 using namespace Utilities;
00054 using namespace Math;
00055
00056 namespace Raytracer
00057 {
00058 void flush(Window *window, vector<Vector4> &pixels,
00059 unsigned &frameX, unsigned &frameY)
00060 {
00061 Window::Update update(window);
00062 for(unsigned i=0; i<pixels.size(); ++i)
00063 {
00064 unsigned red = unsigned(pixels[i][0] * 256); if(red >= 256) red = 255;
00065 unsigned green = unsigned(pixels[i][1] * 256); if(green >= 256) green = 255;
00066 unsigned blue = unsigned(pixels[i][2] * 256); if(blue >= 256) blue = 255;
00067 update.drawPoint(frameX, frameY, Window::set, red, green, blue);
00068 ++frameX;
00069 if(frameX == window->getWidth())
00070 {
00071 frameX = 0;
00072 --frameY;
00073 }
00074 }
00075
00076 pixels.clear();
00077 }
00078
00079 class WindowQuitHandler: public Window::WindowHandler
00080 {
00081 bool &quitFlag;
00082
00083 public:
00084 WindowQuitHandler(bool &quitFlag): quitFlag(quitFlag) {}
00085
00086 void quit()
00087 {
00088 quitFlag = true;
00089 cout << "\n";
00090 }
00091 };
00092
00093 void Engine::render(World *world, View view)
00094 {
00095 if(opt_generatePhotonMap)
00096 world->photonTrace(opt_causticPhotons);
00097
00098 const double aspect = double(opt_resolution.y) / opt_resolution.x;
00099
00100 Vector2 viewPlane;
00101
00102 if(aspect < 1)
00103 {
00104 viewPlane[1] = 2*tan(view.fieldOfView/2);
00105 viewPlane[0] = viewPlane[1] / aspect;
00106 }
00107 else
00108 {
00109 viewPlane[0] = 2*tan(view.fieldOfView/2);
00110 viewPlane[1] = viewPlane[0] * aspect;
00111 }
00112
00113 Vector3 viewPlaneLowerLeft = view.coordSystem.origin;
00114 viewPlaneLowerLeft -= view.coordSystem.basis.x * viewPlane[0] / 2;
00115 viewPlaneLowerLeft -= view.coordSystem.basis.y * viewPlane[1] / 2;
00116 viewPlaneLowerLeft -= view.coordSystem.basis.z;
00117
00118 Vector3 viewPlaneHorizontalSpan = view.coordSystem.basis.x;
00119 viewPlaneHorizontalSpan *= viewPlane[0];
00120
00121 Vector3 viewPlaneVerticalSpan = view.coordSystem.basis.y;
00122 viewPlaneVerticalSpan *= viewPlane[1];
00123
00124 Window *window = 0;
00125 AdaptiveSkip skip(100);
00126 vector<Vector4> pixels;
00127 unsigned frameX = 0;
00128 unsigned frameY = opt_resolution.y - 1;
00129
00130 bool quit = false;
00131
00132 WindowQuitHandler windowQuitHandler(quit);
00133
00134 if(opt_displayRendering)
00135 window = new Window(opt_resolution.x, opt_resolution.y,
00136 32, false, false, 0, 0, &windowQuitHandler);
00137
00138 Image image(opt_resolution.x, opt_resolution.y);
00139
00140 ProgressStatus progress(opt_resolution.x * opt_resolution.y);
00141
00142 unsigned extraSkip = 0;
00143
00144 for(int y = 0; y<opt_resolution.y; ++y)
00145 {
00146 Vector3 vy(viewPlaneVerticalSpan);
00147 vy *= double(y) / opt_resolution.y;
00148
00149 for(int x = 0; x<opt_resolution.x; ++x)
00150 {
00151 Vector3 v(viewPlaneHorizontalSpan);
00152 v *= double(x) / opt_resolution.x;
00153 v += vy;
00154 v += viewPlaneLowerLeft;
00155 v -= view.coordSystem.origin;
00156 v.normalize();
00157
00158 Vector4 c = world->trace(Line3(view.coordSystem.origin, v));
00159 image.setPixel(x, y, c[0], c[1], c[2], c[3]);
00160
00161 if(c[0] >= 1) c[0] = 1;
00162 if(c[1] >= 1) c[1] = 1;
00163 if(c[2] >= 1) c[2] = 1;
00164 if(c[3] >= 1) c[3] = 1;
00165
00166
00167 double tile = ((x/16+y/16)%2 ? 0.5 : 0.7) * (1-c[3]);
00168 c[0] = c[3] * c[0] + tile;
00169 c[1] = c[3] * c[1] + tile;
00170 c[2] = c[3] * c[2] + tile;
00171 c[3] = 1;
00172
00173 pixels.push_back(c);
00174
00175 progress.tick();
00176
00177 if(opt_displayRendering && skip.tick())
00178 {
00179 window->executeEventQueue(Time::now().getMilliSeconds());
00180 if(++extraSkip == 10)
00181 {
00182 flush(window, pixels, frameX, frameY);
00183 extraSkip = 0;
00184 }
00185 }
00186
00187 if(quit) break;
00188 }
00189 if(quit) break;
00190 }
00191
00192 if(opt_displayRendering) flush(window, pixels, frameX, frameY);
00193
00194 image.save(opt_outputFileName, "", 0, logger);
00195
00196 if(opt_displayRendering) while(!quit)
00197 {
00198 window->executeEventQueue(Time::now().getMilliSeconds());
00199 Thread::sleep(Time(0, 100000000));
00200 }
00201 }
00202 }
00203 }