/* This file is part of Mitsuba, a physically based rendering system. Copyright (c) 2007-2010 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 "shapegroup.h" MTS_NAMESPACE_BEGIN #define TIME 0 class AnimatedInstance : public Shape { public: AnimatedInstance(const Properties &props) : Shape(props) { FileResolver *fResolver = Thread::getThread()->getFileResolver(); fs::path path = fResolver->resolve(props.getString("filename")); m_name = path.filename(); Log(EInfo, "Loading animation track from \"%s\"", m_name.c_str()); ref fs = new FileStream(path, FileStream::EReadOnly); m_transform = new AnimatedTransform(fs); } AnimatedInstance(Stream *stream, InstanceManager *manager) : Shape(stream, manager) { m_shapeGroup = static_cast(manager->getInstance(stream)); m_transform = new AnimatedTransform(stream); } void serialize(Stream *stream, InstanceManager *manager) const { Shape::serialize(stream, manager); manager->serialize(stream, m_shapeGroup.get()); m_transform->serialize(stream); } void configure() { if (!m_shapeGroup) Log(EError, "A reference to a 'shapegroup' must be specified!"); const KDTree *kdtree = m_shapeGroup->getKDTree(); const AABB &aabb = kdtree->getAABB(); Float minT, maxT; m_transform->computeTimeBounds(minT, maxT); /* Compute approximate bounds */ int nSteps = 100; Float step = (maxT-minT) / (nSteps-1); Transform objectToWorld; for (int i=0; ieval(minT + step * i, objectToWorld); for (int j=0; j<8; ++j) m_aabb.expandBy(objectToWorld(aabb.getCorner(j))); } } AABB getAABB() const { return m_aabb; } std::string getName() const { return m_name; } Float getSurfaceArea() const { Log(EError, "AnimatedInstance::getSurfaceArea(): not supported!"); return 0.0f; } void addChild(const std::string &name, ConfigurableObject *child) { const Class *cClass = child->getClass(); if (cClass->getName() == "ShapeGroup") { m_shapeGroup = static_cast(child); } else { Shape::addChild(name, child); } } bool rayIntersect(const Ray &_ray, Float mint, Float maxt, Float &t, void *temp) const { const KDTree *kdtree = m_shapeGroup->getKDTree(); Ray ray; Transform objectToWorld, worldToObject; m_transform->eval(TIME, objectToWorld); worldToObject = objectToWorld.inverse(); worldToObject(_ray, ray); return kdtree->rayIntersect(ray, mint, maxt, t, temp); } bool rayIntersect(const Ray &_ray, Float mint, Float maxt) const { const KDTree *kdtree = m_shapeGroup->getKDTree(); Ray ray; Transform objectToWorld, worldToObject; m_transform->eval(TIME, objectToWorld); worldToObject = objectToWorld.inverse(); worldToObject(_ray, ray); return kdtree->rayIntersect(ray, mint, maxt); } void fillIntersectionRecord(const Ray &ray, const void *temp, Intersection &its) const { const KDTree *kdtree = m_shapeGroup->getKDTree(); Transform objectToWorld; m_transform->eval(TIME, objectToWorld); kdtree->fillIntersectionRecord(ray, temp, its); its.shFrame.n = normalize(objectToWorld(its.shFrame.n)); its.shFrame.s = normalize(objectToWorld(its.shFrame.s)); its.shFrame.t = normalize(objectToWorld(its.shFrame.t)); its.geoFrame = Frame(normalize(objectToWorld(its.geoFrame.n))); its.wi = its.shFrame.toLocal(-ray.d); its.dpdu = objectToWorld(its.dpdu); its.dpdv = objectToWorld(its.dpdv); } MTS_DECLARE_CLASS() private: ref m_shapeGroup; ref m_transform; AABB m_aabb; std::string m_name; }; MTS_IMPLEMENT_CLASS_S(AnimatedInstance, false, Shape) MTS_EXPORT_PLUGIN(AnimatedInstance, "AnimatedInstanced geometry"); MTS_NAMESPACE_END