mitsuba/src/librender/camera.cpp

193 lines
6.2 KiB
C++

#include <mitsuba/render/camera.h>
#include <mitsuba/core/plugin.h>
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<Film *>(manager->getInstance(stream));
m_sampler = static_cast<Sampler *>(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<Sampler *>(child);
} else if (child->getClass()->derivesFrom(Film::m_theClass)) {
Assert(m_film == NULL);
m_film = static_cast<Film *>(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<Film*> (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<Sampler *> (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 <tt>fov</tt> 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