#include #include MTS_NAMESPACE_BEGIN Camera::Camera(const Properties &props) : ConfigurableObject(props), m_properties(props) { m_cameraToWorld = props.getTransform("toWorld", Transform()); m_worldToCamera = m_cameraToWorld.inverse(); m_position = m_cameraToWorld(Point(0,0,0)); } Camera::Camera(Stream *stream, InstanceManager *manager) : ConfigurableObject(stream, manager) { m_film = static_cast(manager->getInstance(stream)); m_sampler = static_cast(manager->getInstance(stream)); m_worldToCamera = Transform(stream); m_cameraToWorld = Transform(stream); m_position = m_cameraToWorld(Point(0,0,0)); } Camera::~Camera() { } void Camera::setParent(ConfigurableObject *parent) { // Do not store the parent - this is useful in case // the camera subtree needs to be serialized by itself. } Point Camera::getPosition(const Point2 &sample) const { return m_position; // default impl. } void Camera::setFilm(Film *film) { m_film = film; configure(); } void Camera::serialize(Stream *stream, InstanceManager *manager) const { ConfigurableObject::serialize(stream, manager); manager->serialize(stream, m_film.get()); manager->serialize(stream, m_sampler.get()); m_worldToCamera.serialize(stream); m_cameraToWorld.serialize(stream); } void Camera::generateRayDifferential(const Point2 &sample, const Point2 &lensSample, RayDifferential &ray) const { generateRay(sample, lensSample, ray); Point2 temp = sample; temp.x += 1; generateRay(temp, lensSample, ray.rx); temp = sample; temp.y += 1; generateRay(temp, lensSample, ray.ry); ray.hasDifferentials = true; } void Camera::addChild(const std::string &name, ConfigurableObject *child) { if (child->getClass()->derivesFrom(Sampler::m_theClass)) { Assert(m_sampler == NULL); m_sampler = static_cast(child); } else if (child->getClass()->derivesFrom(Film::m_theClass)) { Assert(m_film == NULL); m_film = static_cast(child); } else { Log(EError, "Camera: Invalid child node!"); } } ProjectiveCamera::ProjectiveCamera(Stream *stream, InstanceManager *manager) : Camera(stream, manager) { m_cameraToScreen = Transform(stream); m_cameraToScreenGL = Transform(stream); m_aspect = stream->readFloat(); } void ProjectiveCamera::configure() { if (m_film == NULL) { /* Instantiate an EXR film by default */ m_film = static_cast (PluginManager::getInstance()-> createObject(Film::m_theClass, Properties("exrfilm"))); m_film->configure(); } if (m_sampler == NULL) { /* No sampler has been selected - load an independent filter with 4 samples/pixel by default */ Properties props("independent"); props.setInteger("sampleCount", 4); m_sampler = static_cast (PluginManager::getInstance()-> createObject(Sampler::m_theClass, props)); m_sampler->configure(); } m_aspect = (Float) m_film->getSize().x / (Float) m_film->getSize().y; } void ProjectiveCamera::serialize(Stream *stream, InstanceManager *manager) const { Camera::serialize(stream, manager); m_cameraToScreen.serialize(stream); m_cameraToScreenGL.serialize(stream); stream->writeFloat(m_aspect); } PinholeCamera::PinholeCamera(const Properties &props) : ProjectiveCamera(props) { /* Field of view of the camera (in degrees) */ m_fov = props.getFloat("fov", 90); /* Specifies which side of the image plane should cover the field of view specified in the fov parameter */ m_mapSmallerSide = props.getBoolean("mapSmallerSide", true); } PinholeCamera::PinholeCamera(Stream *stream, InstanceManager *manager) : ProjectiveCamera(stream, manager) { m_fov = stream->readFloat(); m_mapSmallerSide = stream->readBool(); } void PinholeCamera::serialize(Stream *stream, InstanceManager *manager) const { ProjectiveCamera::serialize(stream, manager); stream->writeFloat(m_fov); stream->writeBool(m_mapSmallerSide); } void PinholeCamera::configure() { ProjectiveCamera::configure(); bool mapYToNDC01 = (m_aspect >= 1.0f); if (!m_mapSmallerSide) mapYToNDC01 = !mapYToNDC01; if (mapYToNDC01) { m_yfov = m_fov; m_xfov = radToDeg(2 * std::atan(std::tan(degToRad(m_fov)/2) * m_aspect)); } else { m_xfov = m_fov; m_yfov = radToDeg(2 * std::atan(std::tan(degToRad(m_fov)/2) / m_aspect)); } m_imagePlaneSize.x = 2 * std::tan(degToRad(m_xfov)/2); m_imagePlaneSize.y = 2 * std::tan(degToRad(m_yfov)/2); m_imagePlanePixelSize.x = m_imagePlaneSize.x / getFilm()->getSize().x; m_imagePlanePixelSize.y = m_imagePlaneSize.y / getFilm()->getSize().y; m_imagePlaneInvArea = 1 / (m_imagePlaneSize.x * m_imagePlaneSize.y); } Float PinholeCamera::importance(const Point2 &p) const { Float x = (p.x * m_imagePlanePixelSize.x) - .5f * m_imagePlaneSize.x; Float y = (p.y * m_imagePlanePixelSize.y) - .5f * m_imagePlaneSize.y; return std::pow(1 + x*x+y*y, (Float) (3.0/2.0)) * m_imagePlaneInvArea; } Float PinholeCamera::solidAngle(Float xs, Float xe, Float ys, Float ye) const { xs = (xs * m_imagePlanePixelSize.x) - .5f * m_imagePlaneSize.x; ys = (ys * m_imagePlanePixelSize.y) - .5f * m_imagePlaneSize.y; xe = (xe * m_imagePlanePixelSize.x) - .5f * m_imagePlaneSize.x; ye = (ye * m_imagePlanePixelSize.y) - .5f * m_imagePlaneSize.y; /* cos(theta) / d^2 with respect to the image plane integrated over the specified footprint */ Float xs2 = xs*xs, xe2 = xe*xe, ys2 = ys*ys, ye2 = ye*ye; Float atan1 = std::atan((xe*ye)/std::sqrt(1 + xe2 + ye2)); Float atan2 = std::atan((xs*ye)/std::sqrt(1 + xs2 + ye2)); Float atan3 = std::atan((xe*ys)/std::sqrt(1 + xe2 + ys2)); Float atan4 = std::atan((xs*ys)/std::sqrt(1 + xs2 + ys2)); return atan1 - atan2 - atan3 + atan4; } Float PinholeCamera::importance(const Vector &v) const { Vector localV; m_worldToCamera(v, localV); if (localV.z <= 0.0f) return 0.0f; Float invZ = 1.0f / localV.z; localV.x *= invZ; localV.y *= invZ; if (2*std::abs(localV.x)>m_imagePlaneSize.x || 2*std::abs(localV.y)>m_imagePlaneSize.y) return 0.0f; return std::pow(1 + localV.x*localV.x+localV.y*localV.y, (Float) (3.0/2.0)) * m_imagePlaneInvArea; } Vector2 PinholeCamera::getImagePlaneSize(Float dist) const { return m_imagePlaneSize * dist; } MTS_IMPLEMENT_CLASS(Camera, true, ConfigurableObject) MTS_IMPLEMENT_CLASS(ProjectiveCamera, true, Camera) MTS_IMPLEMENT_CLASS(PinholeCamera, true, ProjectiveCamera) MTS_NAMESPACE_END