/* 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 . */ #include #include #include #include #include #include #include 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(manager->getInstance(stream)); m_subsurface = static_cast(manager->getInstance(stream)); m_luminaire = static_cast(manager->getInstance(stream)); m_interiorMedium = static_cast(manager->getInstance(stream)); m_exteriorMedium = static_cast(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(child); m_occluder = true; } else if (cClass->derivesFrom(MTS_CLASS(Luminaire))) { Assert(m_luminaire == NULL); m_luminaire = static_cast(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(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(child); } else if (name == "exterior") { Assert(m_exteriorMedium == NULL); m_exteriorMedium = static_cast(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 *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 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