00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "orthographic.h"
00025 #include "sampling.h"
00026 #include "mc.h"
00027 #include "scene.h"
00028 #include "film.h"
00029 #include "specularreflection.h"
00030 #include "fresnelnoop.h"
00031 #include "paramset.h"
00032 #include "dynload.h"
00033
00034 using namespace lux;
00035
00036
00037 OrthoCamera::OrthoCamera(const Transform &world2camStart,
00038 const Transform &world2camEnd,
00039 const float Screen[4], float hither, float yon,
00040 float sopen, float sclose, int sdist, float lensr,
00041 float focald, bool autofocus, Film *f)
00042 : ProjectiveCamera(world2camStart, world2camEnd, Orthographic(hither, yon),
00043 Screen, hither, yon, sopen, sclose, sdist,
00044 lensr, focald, f), autoFocus(autofocus) {
00045 screenDx = Screen[1] - Screen[0];
00046 screenDy = Screen[3] - Screen[2];
00047 posPdf = (film->xResolution * film->yResolution) / (screenDx * screenDy);
00048 normal = CameraToWorld(Normal(0, 0, 1));
00049 RasterToCameraBidir = Orthographic(0.f, 1e30f).GetInverse() * RasterToScreen;
00050 WorldToRasterBidir = RasterToCameraBidir.GetInverse() * WorldToCamera;
00051 }
00052
00053 void OrthoCamera::AutoFocus(Scene* scene)
00054 {
00055 if (autoFocus) {
00056 std::stringstream ss;
00057
00058
00059
00060 int xstart, xend, ystart, yend;
00061 film->GetSampleExtent(&xstart, &xend, &ystart, ¥d);
00062 Point Pras((xend - xstart) / 2, (yend - ystart) / 2, 0);
00063
00064
00065
00066
00067
00068
00069 Point Pcamera;
00070 RasterToCamera(Pras, &Pcamera);
00071 Ray ray;
00072 ray.o = Pcamera;
00073 ray.d = Vector(0,0,1);
00074
00075
00076 ray.time = 0.0f;
00077
00078 ray.mint = 0.f;
00079 ray.maxt = ClipYon - ClipHither;
00080 CameraToWorld(ray, &ray);
00081
00082
00083
00084
00085
00086
00087 Intersection isect;
00088 if (scene->Intersect(ray, &isect))
00089 FocalDistance = ray.maxt;
00090 else
00091 luxError(LUX_NOERROR, LUX_WARNING, "Unable to define the Autofocus focal distance");
00092
00093 ss.str("");
00094 ss << "Autofocus focal distance: " << FocalDistance;
00095 luxError(LUX_NOERROR, LUX_INFO, ss.str().c_str());
00096 }
00097 }
00098
00099 float OrthoCamera::GenerateRay(const Sample &sample, Ray *ray) const
00100 {
00101
00102 Point Pras(sample.imageX, sample.imageY, 0);
00103 Point Pcamera;
00104 RasterToCamera(Pras, &Pcamera);
00105 ray->o = Pcamera;
00106 ray->d = Vector(0,0,1);
00107
00108 ray->time = GetTime(sample.time);
00109
00110
00111 if (LensRadius > 0.) {
00112
00113 float lensU, lensV;
00114 ConcentricSampleDisk(sample.lensU, sample.lensV,
00115 &lensU, &lensV);
00116 lensU *= LensRadius;
00117 lensV *= LensRadius;
00118
00119 float ft = (FocalDistance - ClipHither) / ray->d.z;
00120 Point Pfocus = (*ray)(ft);
00121
00122 ray->o.x += lensU * (FocalDistance - ClipHither) / FocalDistance;
00123 ray->o.y += lensV * (FocalDistance - ClipHither) / FocalDistance;
00124 ray->d = Pfocus - ray->o;
00125 }
00126
00127 ray->mint = 0.;
00128 ray->maxt = ClipYon - ClipHither;
00129 ray->d = Normalize(ray->d);
00130 CameraToWorld(*ray, ray);
00131 return 1.f;
00132 }
00133
00134 bool OrthoCamera::Sample_W(const TsPack *tspack, const Scene *scene, float u1, float u2, float u3, BSDF **bsdf, float *pdf, SWCSpectrum *We) const
00135 {
00136 Point psC(RasterToCameraBidir(Point(u1, u2, 0.f)));
00137 Point ps = CameraToWorld(psC);
00138 DifferentialGeometry dg(ps, normal, CameraToWorld(Vector(1, 0, 0)), CameraToWorld(Vector(0, 1, 0)), Normal(0, 0, 0), Normal(0, 0, 0), 0, 0, NULL);
00139 *bsdf = BSDF_ALLOC(tspack, SingleBSDF)(dg, normal,
00140 BSDF_ALLOC(tspack, SpecularReflection)(SWCSpectrum(1.f),
00141 BSDF_ALLOC(tspack, FresnelNoOp)(), 0.f, 0.f));
00142 *pdf = posPdf;
00143 *We = SWCSpectrum(posPdf);
00144 return true;
00145 }
00146 bool OrthoCamera::Sample_W(const TsPack *tspack, const Scene *scene, const Point &p, const Normal &n, float u1, float u2, float u3, BSDF **bsdf, float *pdf, float *pdfDirect, VisibilityTester *visibility, SWCSpectrum *We) const
00147 {
00148 return false;
00149 }
00150 bool OrthoCamera::GetSamplePosition(const Point &p, const Vector &wi, float distance, float *x, float *y) const
00151 {
00152 if (Dot(wi, normal) < 1.f - MachineEpsilon::E(1.f) || distance < ClipHither || distance > ClipYon)
00153 return false;
00154 Point ps(WorldToRasterBidir(p));
00155 *x = ps.x;
00156 *y = ps.y;
00157 return true;
00158 }
00159
00160 void OrthoCamera::ClampRay(Ray &ray) const
00161 {
00162 ray.mint = ClipHither;
00163 ray.maxt = ClipYon;
00164 }
00165
00166 BBox OrthoCamera::Bounds() const
00167 {
00168 BBox bound(Point(0, 0, 0), Point(1, 1, 0));
00169 bound = WorldToScreen.GetInverse()(bound);
00170 bound.Expand(MachineEpsilon::E(bound));
00171 return bound;
00172 }
00173
00174 Camera* OrthoCamera::CreateCamera(const Transform &world2camStart, const Transform &world2camEnd,
00175 const ParamSet ¶ms, Film *film)
00176 {
00177
00178 float hither = max(1e-4f, params.FindOneFloat("hither", 1e-3f));
00179 float yon = min(params.FindOneFloat("yon", 1e30f), 1e30f);
00180
00181 float shutteropen = params.FindOneFloat("shutteropen", 0.f);
00182 float shutterclose = params.FindOneFloat("shutterclose", 1.f);
00183 int shutterdist = 0;
00184 string shutterdistribution = params.FindOneString("shutterdistribution", "uniform");
00185 if (shutterdistribution == "uniform") shutterdist = 0;
00186 else if (shutterdistribution == "gaussian") shutterdist = 1;
00187 else {
00188 std::stringstream ss;
00189 ss<<"Distribution '"<<shutterdistribution<<"' for perspective camera shutter sampling unknown. Using \"uniform\".";
00190 luxError(LUX_BADTOKEN,LUX_WARNING,ss.str().c_str());
00191 shutterdist = 0;
00192 }
00193
00194 float lensradius = params.FindOneFloat("lensradius", 0.f);
00195 float focaldistance = params.FindOneFloat("focaldistance", 1e30f);
00196 bool autofocus = params.FindOneBool("autofocus", false);
00197 float frame = params.FindOneFloat("frameaspectratio",
00198 float(film->xResolution)/float(film->yResolution));
00199 float screen[4];
00200 if (frame > 1.f) {
00201 screen[0] = -frame;
00202 screen[1] = frame;
00203 screen[2] = -1.f;
00204 screen[3] = 1.f;
00205 }
00206 else {
00207 screen[0] = -1.f;
00208 screen[1] = 1.f;
00209 screen[2] = -1.f / frame;
00210 screen[3] = 1.f / frame;
00211 }
00212 int swi;
00213 const float *sw = params.FindFloat("screenwindow", &swi);
00214 if (sw && swi == 4)
00215 memcpy(screen, sw, 4*sizeof(float));
00216 return new OrthoCamera(world2camStart, world2camEnd, screen, hither, yon,
00217 shutteropen, shutterclose, shutterdist, lensradius, focaldistance, autofocus,
00218 film);
00219 }
00220
00221 static DynamicLoader::RegisterCamera<OrthoCamera> r("orthographic");