partial support for geometry instancing

metadata
Wenzel Jakob 2010-11-12 03:15:32 +01:00
parent 4c5b2a6942
commit 57d13dfe7b
7 changed files with 282 additions and 1 deletions

View File

@ -530,7 +530,8 @@ plugins += env.SharedLibrary('plugins/serialized', ['src/shapes/serialized.cpp']
plugins += env.SharedLibrary('plugins/sphere', ['src/shapes/sphere.cpp'])
plugins += env.SharedLibrary('plugins/cylinder', ['src/shapes/cylinder.cpp'])
plugins += env.SharedLibrary('plugins/hair', ['src/shapes/hair.cpp'])
#plugins += env.SharedLibrary('plugins/group', ['src/shapes/group.cpp'])
plugins += env.SharedLibrary('plugins/shapegroup', ['src/shapes/shapegroup.cpp'])
plugins += env.SharedLibrary('plugins/instance', ['src/shapes/instance.cpp'])
# Samplers
plugins += env.SharedLibrary('plugins/independent', ['src/samplers/independent.cpp'])

View File

@ -34,6 +34,7 @@ class GatherPhotonProcess;
class HemisphereSampler;
class HWResource;
class ImageBlock;
class Instanced;
class Integrator;
struct Intersection;
class IrradianceCache;

View File

@ -63,6 +63,7 @@ MTS_NAMESPACE_BEGIN
*/
class MTS_EXPORT_RENDER KDTree : public GenericKDTree<AABB, KDTree> {
friend class GenericKDTree<AABB, KDTree>;
friend class Instance;
public:
/// Create an empty kd-tree
KDTree();

View File

@ -101,6 +101,7 @@
<xsd:element name="subsurface" type="object"/>
<xsd:element name="ref" type="reference"/>
<xsd:element name="luminaire" type="luminaire"/>
<xsd:element name="shape" type="shape"/>
</xsd:choice>
</xsd:extension>
</xsd:complexContent>

124
src/shapes/instance.cpp Normal file
View File

@ -0,0 +1,124 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include "shapegroup.h"
MTS_NAMESPACE_BEGIN
class Instance : public Shape {
public:
Instance(const Properties &props) : Shape(props) {
m_objectToWorld = props.getTransform("toWorld", Transform());
m_worldToObject = m_objectToWorld.inverse();
}
Instance(Stream *stream, InstanceManager *manager)
: Shape(stream, manager) {
m_shapeGroup = static_cast<ShapeGroup *>(manager->getInstance(stream));
m_objectToWorld = Transform(stream);
m_worldToObject = m_objectToWorld.inverse();
}
void serialize(Stream *stream, InstanceManager *manager) const {
Shape::serialize(stream, manager);
m_objectToWorld.serialize(stream);
manager->serialize(stream, m_shapeGroup.get());
}
void configure() {
if (!m_shapeGroup)
Log(EError, "A reference to a 'shapegroup' must be specified!");
}
AABB getAABB() const {
const KDTree *kdtree = m_shapeGroup->getKDTree();
const AABB &aabb = kdtree->getAABB();
AABB result;
for (int i=0; i<8; ++i)
result.expandBy(m_objectToWorld(aabb.getCorner(i)));
return result;
}
Float getSurfaceArea() const {
Log(EError, "Instance::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<ShapeGroup *>(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;
m_worldToObject(_ray, ray);
Float mint, maxt, tempT = std::numeric_limits<Float>::infinity();
if (kdtree->m_aabb.rayIntersect(ray, mint, maxt)) {
if (_mint > mint) mint = _mint;
if (_maxt < maxt) maxt = _maxt;
if (EXPECT_TAKEN(maxt > mint)) {
if (kdtree->rayIntersectHavran<false>(ray, mint, maxt, tempT, temp)) {
t = tempT;
return true;
}
}
}
return false;
}
bool rayIntersect(const Ray &_ray, Float _mint, Float _maxt) const {
const KDTree *kdtree = m_shapeGroup->getKDTree();
Ray ray;
m_worldToObject(_ray, ray);
Float mint, maxt, tempT = std::numeric_limits<Float>::infinity();
if (kdtree->m_aabb.rayIntersect(ray, mint, maxt)) {
if (_mint > mint) mint = _mint;
if (_maxt < maxt) maxt = _maxt;
if (EXPECT_TAKEN(maxt > mint)) {
if (kdtree->rayIntersectHavran<true>(ray, mint, maxt, tempT, NULL))
return true;
}
}
return false;
}
void fillIntersectionRecord(const Ray &ray, Float t,
const void *temp, Intersection &its) const {
const KDTree *kdtree = m_shapeGroup->getKDTree();
Log(EError, "fillIntersectionRecord(): Unsupported!");
}
MTS_DECLARE_CLASS()
private:
ref<ShapeGroup> m_shapeGroup;
Transform m_objectToWorld, m_worldToObject;
};
MTS_IMPLEMENT_CLASS_S(Instance, false, Shape)
MTS_EXPORT_PLUGIN(Instance, "Instanced geometry");
MTS_NAMESPACE_END

86
src/shapes/shapegroup.cpp Normal file
View File

@ -0,0 +1,86 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include "shapegroup.h"
MTS_NAMESPACE_BEGIN
ShapeGroup::ShapeGroup(const Properties &props) : Shape(props) {
m_kdtree = new KDTree();
}
ShapeGroup::ShapeGroup(Stream *stream, InstanceManager *manager)
: Shape(stream, manager) {
m_kdtree = new KDTree();
size_t shapeCount = stream->readUInt();
for (size_t i=0; i<shapeCount; ++i)
m_kdtree->addShape(static_cast<Shape *>(manager->getInstance(stream)));
configure();
}
void ShapeGroup::serialize(Stream *stream, InstanceManager *manager) const {
Shape::serialize(stream, manager);
const std::vector<const Shape *> &shapes = m_kdtree->getShapes();
stream->writeUInt((uint32_t) shapes.size());
for (size_t i=0; i<shapes.size(); ++i)
manager->serialize(stream, shapes[i]);
}
void ShapeGroup::configure() {
if (!m_kdtree->isBuilt())
m_kdtree->build();
}
AABB ShapeGroup::getAABB() const {
return AABB();
}
Float ShapeGroup::getSurfaceArea() const {
return 0.0f;
}
void ShapeGroup::addChild(const std::string &name, ConfigurableObject *child) {
const Class *cClass = child->getClass();
if (cClass->derivesFrom(ShapeGroup::m_theClass) || cClass->getName() == "ShapeInstance") {
Log(EError, "Nested instancing is not supported!");
} else if (cClass->derivesFrom(Shape::m_theClass)) {
Shape *shape = static_cast<Shape *>(child);
if (shape->isCompound()) {
int index = 0;
do {
ref<Shape> element = shape->getElement(index++);
if (element == NULL)
break;
addChild("", element);
} while (true);
} else {
m_kdtree->addShape(shape);
}
} else {
Shape::addChild(name, child);
}
}
bool ShapeGroup::isCompound() const {
// this shape reduces to nothing (compound, no children)
return true;
}
MTS_IMPLEMENT_CLASS_S(ShapeGroup, false, Shape)
MTS_EXPORT_PLUGIN(ShapeGroup, "Grouped geometry for instancing");
MTS_NAMESPACE_END

67
src/shapes/shapegroup.h Normal file
View File

@ -0,0 +1,67 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include <mitsuba/render/kdtree.h>
#include <mitsuba/render/bsdf.h>
#include <mitsuba/render/subsurface.h>
#include <mitsuba/render/luminaire.h>
MTS_NAMESPACE_BEGIN
/**
* \brief "Fake" shape that groups sub-shapes into a
* separate KD-tree. When this shape is used by itself,
* it doesn't actually generate any intersectable geometry.
* Instead, the "instance" plugin must be used to create
* references to the geometry stored inside it.
*/
class ShapeGroup : public Shape {
public:
/// Create a new shape group
ShapeGroup(const Properties &props);
/// Unserialize from a binary data stream
ShapeGroup(Stream *stream, InstanceManager *manager);
/// Serialize to a binary data stream
void serialize(Stream *stream, InstanceManager *manager) const;
/// Build the internal KD-tree
void configure();
/// Add a child object
void addChild(const std::string &name, ConfigurableObject *child);
/// Return whether or not the shape is a compound object
bool isCompound() const;
/// Returns an invalid AABB
AABB getAABB() const;
/// Returns the surface area
Float getSurfaceArea() const;
/// Return a pointer to the internal KD-tree
inline const KDTree *getKDTree() const { return m_kdtree.get(); }
MTS_DECLARE_CLASS()
private:
ref<KDTree> m_kdtree;
};
MTS_NAMESPACE_END