191 lines
6.0 KiB
C++
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
|