00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "realistic.h"
00030 #include "sampling.h"
00031 #include "shape.h"
00032 #include "mc.h"
00033 #include "film.h"
00034 #include "dynload.h"
00035 #include "paramset.h"
00036
00037 #include <fstream>
00038 using std::ifstream;
00039
00040 using namespace lux;
00041
00042 RealisticCamera::RealisticCamera(const Transform &world2cam,
00043 const float Screen[4],
00044 float hither, float yon,
00045 float sopen, float sclose,
00046 float filmdistance, float aperture_diameter, string specfile,
00047 float filmdiag, Film *f)
00048 : Camera(world2cam, hither, yon, sopen, sclose, f)
00049 {
00050 filmDistance = filmdistance;
00051 filmDist2 = filmDistance * filmDistance;
00052 apertureDiameter = aperture_diameter;
00053 filmDiag = filmdiag;
00054
00055 distToBack = ParseLensData(specfile);
00056
00057
00058 float diag2 = sqrt(float(film->xResolution * film->xResolution +
00059 film->yResolution * film->yResolution));
00060 float scale = diag2 / filmDiag;
00061 float w = film->xResolution / scale;
00062 float h = film->yResolution / scale;
00063 Transform FilmToRaster =
00064 Scale(-scale, scale, 1.f) *
00065 Translate(Vector(-w/2.0f, h/2.0f, 0.f));
00066 RasterToFilm = FilmToRaster.GetInverse();
00067 FilmToCamera = Translate(Vector(0.f, 0.f, -filmDistance - distToBack));
00068 RasterToCamera = FilmToCamera * RasterToFilm;
00069 }
00070 RealisticCamera::~RealisticCamera(void) {
00071 }
00072 float RealisticCamera::GenerateRay(const Sample &sample, Ray *ray) const {
00073
00074 Point Pras(sample.imageX, sample.imageY, 0.f);
00075 Point PCamera;
00076 RasterToCamera(Pras, &PCamera);
00077 float lensU, lensV;
00078 ConcentricSampleDisk(sample.lensU, sample.lensV, &lensU, &lensV);
00079 lensU *= backAperture;
00080 lensV *= backAperture;
00081 Point PBack(lensU, lensV, -distToBack);
00082
00083 ray->o = PCamera;
00084 ray->d = Normalize(PBack - PCamera);
00085 ray->time = Lerp(sample.time, ShutterOpen, ShutterClose);
00086 ray->mint = 0.;
00087 ray->maxt = INFINITY;
00088
00089 float cos4 = ray->d.z;
00090 cos4 *= cos4;
00091 cos4 *= cos4;
00092
00093
00094 DifferentialGeometry dg;
00095 float thit;
00096 for (int i = (int)lenses.size() -1 ; i >= 0; --i) {
00097 if (lenses[i]->shape->Intersect(*ray, &thit, &dg)) {
00098
00099 Normal n = (lenses[i]->entering == true) ? dg.nn : -dg.nn;
00100 float eta = lenses[i]->eta;
00101 float cos_i = Dot(-ray->d, n);
00102 float sint2 = (eta * eta * (1 - cos_i*cos_i));
00103 if (sint2 > 1.) {
00104 ray->mint = 1.f;
00105 ray->maxt = 0.f;
00106 return 1.f;
00107 }
00108
00109 float cost = sqrtf(max(0.f, 1.f - sint2));
00110 float nscale = eta * cos_i - cost;
00111 Vector d(n.x * nscale + eta * ray->d.x,
00112 n.y * nscale + eta * ray->d.y,
00113 n.z * nscale + eta * ray->d.z);
00114
00115 ray->o = (*ray)(thit);
00116 ray->d = Normalize(d);
00117 ray->mint = 0.f;
00118 ray->maxt = INFINITY;
00119 }
00120 else {
00121 ray->mint = 1.f;
00122 ray->maxt = 0.f;
00123 return 1.f;
00124 }
00125 }
00126 ray->maxt = (ClipYon - ClipHither) / ray->d.z;
00127 CameraToWorld(*ray, ray);
00128 return cos4 / filmDist2;
00129 }
00130
00131 float RealisticCamera::ParseLensData(const string& specfile) {
00132
00133 ifstream file;
00134 file.open(specfile.c_str());
00135 if (!file)
00136 printf("Couldn't open camera specfile...");
00137 string lineread;
00138 float r, sep, nt, aperture, ni = 1.f;
00139 float accumdist = 0.;
00140 bool entering;
00141 lenses.clear();
00142
00143 while (std::getline(file, lineread))
00144 {
00145 if (sscanf(lineread.c_str(), "%f\t%f\t%f\t%f\n",
00146 &r, &sep, &nt, &aperture) == 4)
00147 {
00148
00149 if (r == 0.0) {
00150 ParamSet paramSet;
00151 float height = -accumdist;
00152 float radius = apertureDiameter / 2.0f;
00153 float innerradius = 0.f;
00154 paramSet.AddFloat("height", &height);
00155 paramSet.AddFloat("radius", &radius);
00156 paramSet.AddFloat("innerradius", &innerradius);
00157 boost::shared_ptr<Shape> shape =
00158 MakeShape("disk", Transform(), false, paramSet);
00159 boost::shared_ptr<Lens> o (new Lens(false, 1.f, aperture, shape));
00160 lenses.push_back(o);
00161 ni = 1.f;
00162 }
00163 else {
00164
00165 float radius = fabsf(r);
00166 Transform lensToCam;
00167 if (r > 0) {
00168 lensToCam = Translate(Vector(0., 0., -accumdist - radius));
00169 entering = false;
00170 }
00171 else {
00172 lensToCam = Translate(Vector(0., 0., -accumdist + radius));
00173 entering = true;
00174 }
00175 ParamSet paramSet;
00176 paramSet.AddFloat("radius", &radius);
00177 paramSet.AddFloat("aperture", &aperture);
00178 boost::shared_ptr<Shape> shape =
00179 MakeShape("lenscomponent", lensToCam, false,
00180 paramSet);
00181 boost::shared_ptr<Lens> o (new Lens(entering, nt/ni, aperture, shape));
00182 lenses.push_back(o);
00183 ni = nt;
00184 }
00185 accumdist += sep;
00186 }
00187 }
00188 backAperture = aperture;
00189 return accumdist;
00190 }
00191
00192 Camera* RealisticCamera::CreateCamera(const ParamSet ¶ms,
00193 const Transform &world2cam, Film *film) {
00194
00195 float hither = params.FindOneFloat("hither", 1e-3f);
00196 float yon = params.FindOneFloat("yon", 1e30f);
00197 float shutteropen = params.FindOneFloat("shutteropen", 0.f);
00198 float shutterclose = params.FindOneFloat("shutterclose", 1.f);
00199
00200
00201 string specfile = params.FindOneString("specfile", "");
00202 float filmdistance = params.FindOneFloat("filmdistance", 70.0);
00203 float fstop = params.FindOneFloat("aperture_diameter", 1.0);
00204 float filmdiag = params.FindOneFloat("filmdiag", 35.0);
00205
00206 if (specfile == "") {
00207 printf( "No lens spec file supplied!\n" );
00208 }
00209
00210 float frame = float(film->xResolution)/float(film->yResolution);
00211 float screen[4];
00212 if (frame > 1.f) {
00213 screen[0] = -frame;
00214 screen[1] = frame;
00215 screen[2] = -1.f;
00216 screen[3] = 1.f;
00217 }
00218 else {
00219 screen[0] = -1.f;
00220 screen[1] = 1.f;
00221 screen[2] = -1.f / frame;
00222 screen[3] = 1.f / frame;
00223 }
00224 return new RealisticCamera(world2cam, screen, hither, yon,
00225 shutteropen, shutterclose, filmdistance, fstop,
00226 specfile, filmdiag, film);
00227 }