mitsuba/src/librender/shape.cpp

191 lines
6.0 KiB
C++

/*
This file is part of Mitsuba, a physically based rendering system.
Copyright (c) 2007-2011 by Wenzel Jakob and others.
Mitsuba is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License Version 3
as published by the Free Software Foundation.
Mitsuba is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <mitsuba/core/plugin.h>
#include <mitsuba/core/properties.h>
#include <mitsuba/render/shape.h>
#include <mitsuba/render/bsdf.h>
#include <mitsuba/render/subsurface.h>
#include <mitsuba/render/luminaire.h>
#include <mitsuba/render/medium.h>
MTS_NAMESPACE_BEGIN
Shape::Shape(const Properties &props)
: ConfigurableObject(props), m_occluder(false) { }
Shape::Shape(Stream *stream, InstanceManager *manager)
: ConfigurableObject(stream, manager) {
m_bsdf = static_cast<BSDF *>(manager->getInstance(stream));
m_subsurface = static_cast<Subsurface *>(manager->getInstance(stream));
m_luminaire = static_cast<Luminaire *>(manager->getInstance(stream));
m_interiorMedium = static_cast<Medium *>(manager->getInstance(stream));
m_exteriorMedium = static_cast<Medium *>(manager->getInstance(stream));
m_occluder = stream->readBool();
}
Shape::~Shape() { }
void Shape::configure() { }
bool Shape::isCompound() const {
return false;
}
std::string Shape::getName() const {
return "Unnamed";
}
Shape *Shape::getElement(int i) {
return NULL;
}
AABB Shape::getClippedAABB(const AABB &box) const {
AABB result = getAABB();
result.clip(box);
return result;
}
Float Shape::sampleSolidAngle(ShapeSamplingRecord &sRec,
const Point &from, const Point2 &sample) const {
/* Turns the area sampling routine into one that samples wrt. solid angles */
Float pdfArea = sampleArea(sRec, sample);
Vector lumToPoint = from - sRec.p;
Float distSquared = lumToPoint.lengthSquared(), dp = dot(lumToPoint, sRec.n);
if (dp > 0)
return pdfArea * distSquared * std::sqrt(distSquared) / dp;
else
return 0.0f;
}
Float Shape::pdfSolidAngle(const ShapeSamplingRecord &sRec, const Point &from) const {
/* Turns the area sampling routine into one that samples wrt. solid angles */
Vector lumToPoint = from - sRec.p;
Float distSquared = lumToPoint.lengthSquared();
Float invDP = std::max((Float) 0, std::sqrt(distSquared) / dot(lumToPoint, sRec.n));
return pdfArea(sRec) * distSquared * invDP;
}
void Shape::addChild(const std::string &name, ConfigurableObject *child) {
const Class *cClass = child->getClass();
if (cClass->derivesFrom(MTS_CLASS(BSDF))) {
m_bsdf = static_cast<BSDF *>(child);
m_occluder = true;
} else if (cClass->derivesFrom(MTS_CLASS(Luminaire))) {
Assert(m_luminaire == NULL);
m_luminaire = static_cast<Luminaire *>(child);
if (m_luminaire && m_exteriorMedium)
m_luminaire->setMedium(m_exteriorMedium);
} else if (cClass->derivesFrom(MTS_CLASS(Subsurface))) {
Assert(m_subsurface == NULL);
if (m_interiorMedium != NULL)
Log(EError, "Shape \"%s\" has both an interior medium "
"and a subsurface integrator -- please choose one or the other!", getName().c_str());
m_subsurface = static_cast<Subsurface *>(child);
} else if (cClass->derivesFrom(MTS_CLASS(Medium))) {
if (name == "interior") {
Assert(m_interiorMedium == NULL);
if (m_subsurface != NULL)
Log(EError, "Shape \"%s\" has both an interior medium "
"and a subsurface integrator -- please choose one or the other!", getName().c_str());
m_interiorMedium = static_cast<Medium *>(child);
} else if (name == "exterior") {
Assert(m_exteriorMedium == NULL);
m_exteriorMedium = static_cast<Medium *>(child);
if (m_luminaire)
m_luminaire->setMedium(m_exteriorMedium);
} else {
Log(EError, "Shape: Invalid medium child (must be named "
"'interior' or 'exterior')!");
}
} else {
ConfigurableObject::addChild(name, child);
}
}
const KDTreeBase<AABB> *Shape::getKDTree() const {
return NULL;
}
void Shape::serialize(Stream *stream, InstanceManager *manager) const {
ConfigurableObject::serialize(stream, manager);
manager->serialize(stream, m_bsdf.get());
manager->serialize(stream, m_subsurface.get());
manager->serialize(stream, m_luminaire.get());
manager->serialize(stream, m_interiorMedium.get());
manager->serialize(stream, m_exteriorMedium.get());
stream->writeBool(m_occluder);
}
Float Shape::getSurfaceArea() const {
Log(EError, "%s::getSurfaceArea(): Not implemented!",
getClass()->getName().c_str());
return 0.0f;
}
bool Shape::rayIntersect(const Ray &ray, Float mint,
Float maxt, Float &t, void *temp) const {
Log(EError, "%s::rayIntersect(): Not implemented!",
getClass()->getName().c_str());
return false;
}
bool Shape::rayIntersect(const Ray &ray, Float mint,
Float maxt) const {
Log(EError, "%s::rayIntersect(): Not implemented!",
getClass()->getName().c_str());
return false;
}
void Shape::fillIntersectionRecord(const Ray &ray,
const void *temp, Intersection &its) const {
Log(EError, "%s::fillIntersectionRecord(): Not implemented!",
getClass()->getName().c_str());
}
Float Shape::sampleArea(ShapeSamplingRecord &sRec,
const Point2 &sample) const {
Log(EError, "%s::sampleArea(): Not implemented!",
getClass()->getName().c_str());
return 0.0f;
}
Float Shape::pdfArea(const ShapeSamplingRecord &sRec) const {
Log(EError, "%s::pdfArea(): Not implemented!",
getClass()->getName().c_str());
return 0.0f;
}
ref<TriMesh> Shape::createTriMesh() {
return NULL;
}
std::string ShapeSamplingRecord::toString() const {
std::ostringstream oss;
oss << "ShapeSamplingRecord[" << std::endl
<< " p = " << p.toString() << "," << std::endl
<< " n = " << n.toString() << std::endl
<< "]";
return oss.str();
}
MTS_IMPLEMENT_CLASS(Shape, true, ConfigurableObject)
MTS_NAMESPACE_END