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