From 3881f295d8bcd17c6d44e7e18091d9cc5f96e1a1 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Sat, 3 Nov 2012 02:46:32 -0400 Subject: [PATCH] added a convenience wrapper to permit direct animation of every type of shape without having to declare instances etc --- src/emitters/sky.cpp | 7 ++-- src/emitters/sun.cpp | 3 +- src/emitters/sunsky.cpp | 2 +- src/libcore/properties.cpp | 11 ++++--- src/librender/scenehandler.cpp | 58 ++++++++++++++++++++++++++++++---- src/shapes/cylinder.cpp | 2 +- src/shapes/disk.cpp | 2 +- src/shapes/obj.cpp | 2 +- src/shapes/ply.cpp | 2 +- src/shapes/rectangle.cpp | 2 +- src/shapes/serialized.cpp | 2 +- src/shapes/sphere.cpp | 2 +- 12 files changed, 73 insertions(+), 22 deletions(-) diff --git a/src/emitters/sky.cpp b/src/emitters/sky.cpp index fe3a559b..2daf4284 100644 --- a/src/emitters/sky.cpp +++ b/src/emitters/sky.cpp @@ -71,6 +71,10 @@ MTS_NAMESPACE_BEGIN * Specifies the relative amount of samples * allocated to this emitter. \default{1} * } + * \parameter{toWorld}{\Transform\Or\ATransform}{ + * Specifies an optional sensor-to-world transformation. + * \default{none (i.e. sensor space $=$ world space)} + * } * } * * \renderings{ @@ -376,8 +380,7 @@ public: bitmapData.ptr = (uint8_t *) bitmap.get(); bitmapData.size = sizeof(Bitmap); props.setData("bitmap", bitmapData); - const Transform &trafo = m_worldTransform->eval(0); - props.setTransform("toWorld", trafo); + props.setAnimatedTransform("toWorld", m_worldTransform); props.setFloat("samplingWeight", m_samplingWeight); Emitter *emitter = static_cast( PluginManager::getInstance()->createObject( diff --git a/src/emitters/sun.cpp b/src/emitters/sun.cpp index 88655d5c..fc1378b1 100644 --- a/src/emitters/sun.cpp +++ b/src/emitters/sun.cpp @@ -221,8 +221,7 @@ public: bitmapData.ptr = (uint8_t *) bitmap.get(); bitmapData.size = sizeof(Bitmap); props.setData("bitmap", bitmapData); - const Transform &trafo = m_worldTransform->eval(0); - props.setTransform("toWorld", trafo); + props.setAnimatedTransform("toWorld", m_worldTransform); props.setFloat("samplingWeight", m_samplingWeight); Emitter *emitter = static_cast( PluginManager::getInstance()->createObject( diff --git a/src/emitters/sunsky.cpp b/src/emitters/sunsky.cpp index 779e84c5..e2b29ed0 100644 --- a/src/emitters/sunsky.cpp +++ b/src/emitters/sunsky.cpp @@ -223,7 +223,7 @@ public: bitmapData.ptr = (uint8_t *) bitmap.get(); bitmapData.size = sizeof(Bitmap); envProps.setData("bitmap", bitmapData); - envProps.setTransform("toWorld", trafo); + envProps.setAnimatedTransform("toWorld", m_worldTransform); envProps.setFloat("samplingWeight", m_samplingWeight); m_envEmitter = static_cast( PluginManager::getInstance()->createObject( diff --git a/src/libcore/properties.cpp b/src/libcore/properties.cpp index f9b0dc58..9ef3d159 100644 --- a/src/libcore/properties.cpp +++ b/src/libcore/properties.cpp @@ -198,9 +198,9 @@ Properties::~Properties() { void Properties::operator=(const Properties &props) { for (std::map::iterator it = m_elements->begin(); it != m_elements->end(); ++it) { - AnimatedTransform *trafo = boost::get((*it).second.data); + AnimatedTransform **trafo = boost::get(&(*it).second.data); if (trafo) - trafo->decRef(); + (*trafo)->decRef(); } m_pluginName = props.m_pluginName; @@ -209,9 +209,9 @@ void Properties::operator=(const Properties &props) { for (std::map::iterator it = m_elements->begin(); it != m_elements->end(); ++it) { - AnimatedTransform *trafo = boost::get((*it).second.data); + AnimatedTransform **trafo = boost::get(&(*it).second.data); if (trafo) - trafo->incRef(); + (*trafo)->incRef(); } } @@ -223,6 +223,9 @@ bool Properties::removeProperty(const std::string &name) { std::map::iterator it = m_elements->find(name); if (it == m_elements->end()) return false; + AnimatedTransform **trafo = boost::get(&(*it).second.data); + if (trafo) + (*trafo)->decRef(); m_elements->erase(it); return true; } diff --git a/src/librender/scenehandler.cpp b/src/librender/scenehandler.cpp index 556f0bb1..79589d2d 100644 --- a/src/librender/scenehandler.cpp +++ b/src/librender/scenehandler.cpp @@ -271,7 +271,7 @@ void SceneHandler::endElement(const XMLCh* const xmlName) { if (context.attributes.find("id") != context.attributes.end()) context.properties.setID(context.attributes["id"]); - ref object = NULL; + ref object; TagMap::const_iterator it = m_tags.find(name); if (it == m_tags.end()) @@ -686,11 +686,57 @@ void SceneHandler::endElement(const XMLCh* const xmlName) { } break; - default: - if (tag.second == NULL) - XMLLog(EError, "Internal error: could not instantiate an object " - "corresponding to the tag '%s'", name.c_str()); - object = m_pluginManager->createObject(tag.second, context.properties); + default: { + if (tag.second == NULL) + XMLLog(EError, "Internal error: could not instantiate an object " + "corresponding to the tag '%s'", name.c_str()); + + Properties &props = context.properties; + + /* Convenience hack: allow passing animated transforms to arbitrary shapes + and then internally rewrite this into a shape group + animated instance */ + if (tag.second == MTS_CLASS(Shape) && props.getPluginName() != "instance" && + props.hasProperty("toWorld") && props.getType("toWorld") == Properties::EAnimatedTransform) { + + ref trafo = props.getAnimatedTransform("toWorld"); + props.removeProperty("toWorld"); + + if (trafo->isStatic()) + props.setTransform("toWorld", trafo->eval(0)); + + object = m_pluginManager->createObject(tag.second, props); + + if (!trafo->isStatic()) { + object = m_pluginManager->createObject(tag.second, props); + /* If the object has children, append them */ + for (std::vector > + ::iterator it = context.children.begin(); + it != context.children.end(); ++it) { + if (it->second != NULL) { + object->addChild(it->first, it->second); + it->second->setParent(object); + it->second->decRef(); + } + } + context.children.clear(); + + object->configure(); + + ref shapeGroup = static_cast ( + m_pluginManager->createObject(MTS_CLASS(Shape), Properties("shapegroup"))); + shapeGroup->addChild(object); + shapeGroup->configure(); + + Properties instanceProps("instance"); + instanceProps.setAnimatedTransform("toWorld", trafo); + object = m_pluginManager->createObject(instanceProps); + object->addChild(shapeGroup); + + } + } else { + object = m_pluginManager->createObject(tag.second, props); + } + } break; } diff --git a/src/shapes/cylinder.cpp b/src/shapes/cylinder.cpp index 83af281a..c438ae06 100644 --- a/src/shapes/cylinder.cpp +++ b/src/shapes/cylinder.cpp @@ -43,7 +43,7 @@ MTS_NAMESPACE_BEGIN * Is the cylinder inverted, i.e. should the normal vectors * be flipped? \default{\code{false}, i.e. the normals point outside} * } - * \parameter{toWorld}{\Transform}{ + * \parameter{toWorld}{\Transform\Or\ATransform}{ * Specifies an optional linear object-to-world transformation. * Note that non-uniform scales are not permitted! * \default{none (i.e. object space $=$ world space)} diff --git a/src/shapes/disk.cpp b/src/shapes/disk.cpp index e4b2d429..40f3f25b 100644 --- a/src/shapes/disk.cpp +++ b/src/shapes/disk.cpp @@ -31,7 +31,7 @@ MTS_NAMESPACE_BEGIN /*!\plugin{disk}{Disk intersection primitive} * \order{4} * \parameters{ - * \parameter{toWorld}{\Transform}{ + * \parameter{toWorld}{\Transform\Or\ATransform}{ * Specifies a linear object-to-world transformation. * Note that non-uniform scales are not permitted! * \default{none (i.e. object space $=$ world space)} diff --git a/src/shapes/obj.cpp b/src/shapes/obj.cpp index 14834ed0..015384e4 100644 --- a/src/shapes/obj.cpp +++ b/src/shapes/obj.cpp @@ -55,7 +55,7 @@ MTS_NAMESPACE_BEGIN * this convention. \default{\code{true}, i.e. flip them to get the * correct coordinates}. * } - * \parameter{toWorld}{\Transform}{ + * \parameter{toWorld}{\Transform\Or\ATransform}{ * Specifies an optional linear object-to-world transformation. * Note that non-uniform scales are not permitted! * \default{none (i.e. object space $=$ world space)} diff --git a/src/shapes/ply.cpp b/src/shapes/ply.cpp index 4faa7f25..634055e8 100644 --- a/src/shapes/ply.cpp +++ b/src/shapes/ply.cpp @@ -62,7 +62,7 @@ MTS_NAMESPACE_BEGIN * Optional flag to flip all normals. \default{\code{false}, i.e. * the normals are left unchanged}. * } - * \parameter{toWorld}{\Transform}{ + * \parameter{toWorld}{\Transform\Or\ATransform}{ * Specifies an optional linear object-to-world transformation. * Note that non-uniform scales are not permitted! * \default{none (i.e. object space $=$ world space)} diff --git a/src/shapes/rectangle.cpp b/src/shapes/rectangle.cpp index e5056a9e..d620b714 100644 --- a/src/shapes/rectangle.cpp +++ b/src/shapes/rectangle.cpp @@ -30,7 +30,7 @@ MTS_NAMESPACE_BEGIN /*!\plugin{rectangle}{Rectangle intersection primitive} * \order{3} * \parameters{ - * \parameter{toWorld}{\Transform}{ + * \parameter{toWorld}{\Transform\Or\ATransform}{ * Specifies a linear object-to-world transformation. * It is allowed to use non-uniform scaling, but no shear. * \default{none (i.e. object space $=$ world space)} diff --git a/src/shapes/serialized.cpp b/src/shapes/serialized.cpp index 279283fa..6d198707 100644 --- a/src/shapes/serialized.cpp +++ b/src/shapes/serialized.cpp @@ -48,7 +48,7 @@ MTS_NAMESPACE_BEGIN * Optional flag to flip all normals. \default{\code{false}, i.e. * the normals are left unchanged}. * } - * \parameter{toWorld}{\Transform}{ + * \parameter{toWorld}{\Transform\Or\ATransform}{ * Specifies an optional linear object-to-world transformation. * Note that non-uniform scales are not permitted! * \default{none (i.e. object space $=$ world space)} diff --git a/src/shapes/sphere.cpp b/src/shapes/sphere.cpp index 0b644d19..bfd77026 100644 --- a/src/shapes/sphere.cpp +++ b/src/shapes/sphere.cpp @@ -37,7 +37,7 @@ MTS_NAMESPACE_BEGIN * \parameter{radius}{\Float}{ * Radius of the sphere in object-space units \default{1} * } - * \parameter{toWorld}{\Transform}{ + * \parameter{toWorld}{\Transform\Or\ATransform}{ * Specifies an optional linear object-to-world transformation. * Note that non-uniform scales are not permitted! * \default{none (i.e. object space $=$ world space)}