00001
00005 #include "Scene.h"
00006 #include "Background.h"
00007 #include "Camera.h"
00008 #include "HitRecord.h"
00009 #include "Image.h"
00010 #include "Light.h"
00011 #include "Material.h"
00012 #include "Object.h"
00013 #include "Ray.h"
00014 #include "RenderContext.h"
00015 #include <float.h>
00016 #include <iostream>
00017 #include <stdlib.h>
00018 using namespace std;
00019
00020 Scene::Scene()
00021 {
00022 object = 0;
00023 background = 0;
00024 camera = 0;
00025 ambient = Color(0, 0, 0);
00026 image = 0;
00027 minAttenuation = 0;
00028 }
00029
00030 Scene::~Scene()
00031 {
00032 delete object;
00033 delete background;
00034 delete camera;
00035 delete image;
00036 for(int i=0;i<static_cast<int>(lights.size());i++){
00037 Light* light = lights[i];
00038 delete light;
00039 }
00040 }
00041
00042 void Scene::preprocess()
00043 {
00044 background->preprocess();
00045 for(int i=0;i<static_cast<int>(lights.size());i++){
00046 Light* light = lights[i];
00047 light->preprocess();
00048 }
00049 double aspect_ratio = image->aspect_ratio();
00050 camera->preprocess(aspect_ratio);
00051 object->preprocess();
00052 }
00053
00054 void Scene::render()
00055 {
00056 extern bool one_only;
00057 extern int xpixel;
00058 extern int ypixel;
00059
00060
00061 if(!object || !background || !camera || !image){
00062 cerr << "Incomplete scene, cannot render!\n";
00063 exit(1);
00064 }
00065 int xres = image->getXresolution();
00066 int yres = image->getYresolution();
00067 RenderContext context(this);
00068 double dx = 2./xres;
00069 double xmin = -1. + dx/2.;
00070 double dy = 2./yres;
00071 double ymin = -1. + dy/2.;
00072 Color atten(1,1,1);
00073 if (one_only) {
00074
00075 double y = ymin + ypixel*dy;
00076 double x = xmin + xpixel*dx;
00077
00078 Ray ray;
00079 camera->makeRay(ray, context, x, y);
00080 HitRecord hit(DBL_MAX);
00081 object->intersect(hit, context, ray);
00082 Color result;
00083 if(hit.getPrimitive()){
00084
00085 const Material* matl = hit.getMaterial();
00086 matl->shade(result, context, ray, hit, atten, 0);
00087 } else {
00088 background->getBackgroundColor(result, context, ray);
00089 }
00090 image->set(xpixel, ypixel, result);
00091 } else {
00092 for(int i=0 ; i<yres ; i++){
00093
00094 double y = ymin + i*dy;
00095 for(int j=0;j<xres;j++){
00096 double x = xmin + j*dx;
00097
00098 Ray ray;
00099 camera->makeRay(ray, context, x, y);
00100 HitRecord hit(DBL_MAX);
00101 object->intersect(hit, context, ray);
00102 Color result;
00103 if(hit.getPrimitive()){
00104
00105 const Material* matl = hit.getMaterial();
00106 matl->shade(result, context, ray, hit, atten, 0);
00107 } else {
00108 background->getBackgroundColor(result, context, ray);
00109 }
00110 image->set(j, i, result);
00111 }
00112 }
00113 }
00114 }
00115 double Scene::traceRay(Color& result, const RenderContext& context, const Ray& ray, const Color& atten, int depth) const
00116 {
00117 if(depth >= maxRayDepth || atten.maxComponent() < minAttenuation){
00118 result = Color(0, 0, 0);
00119 return 0;
00120 } else {
00121 HitRecord hit(DBL_MAX);
00122 object->intersect(hit, context, ray);
00123 if(hit.getPrimitive()){
00124
00125 const Material* matl = hit.getMaterial();
00126 matl->shade(result, context, ray, hit, atten, depth);
00127 return hit.minT();
00128 } else {
00129 background->getBackgroundColor(result, context, ray);
00130 return DBL_MAX;
00131 }
00132 }
00133 }
00134
00135 double Scene::traceRay(Color& result, const RenderContext& context, const Object* obj, const Ray& ray, const Color& atten, int depth) const
00136 {
00137 if(depth >= maxRayDepth || atten.maxComponent() < minAttenuation){
00138 result = Color(0, 0, 0);
00139 return 0;
00140 } else {
00141 HitRecord hit(DBL_MAX);
00142 obj->intersect(hit, context, ray);
00143 if(hit.getPrimitive()){
00144
00145 const Material* matl = hit.getMaterial();
00146 matl->shade(result, context, ray, hit, atten, depth);
00147 return hit.minT();
00148 } else {
00149 background->getBackgroundColor(result, context, ray);
00150 return DBL_MAX;
00151 }
00152 }
00153 }