Nori
|
00001 /* 00002 This file is part of Nori, a simple educational ray tracer 00003 00004 Copyright (c) 2012 by Wenzel Jakob and Steve Marschner. 00005 00006 Nori is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License Version 3 00008 as published by the Free Software Foundation. 00009 00010 Nori is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with this program. If not, see <http://www.gnu.org/licenses/>. 00017 */ 00018 00019 #if !defined(__OBJECT_H) 00020 #define __OBJECT_H 00021 00022 #include <nori/proplist.h> 00023 #include <boost/function.hpp> 00024 00025 NORI_NAMESPACE_BEGIN 00026 00027 /** 00028 * \brief Base class of all objects 00029 * 00030 * A Nori object represents an instance that is part of 00031 * a scene description, e.g. a scattering model or luminaire. 00032 */ 00033 class NoriObject { 00034 public: 00035 enum EClassType { 00036 EScene = 0, 00037 EMesh, 00038 EBSDF, 00039 ELuminaire, 00040 ECamera, 00041 EIntegrator, 00042 ESampler, 00043 ETest, 00044 EReconstructionFilter, 00045 EClassTypeCount 00046 }; 00047 00048 /// Virtual destructor 00049 virtual ~NoriObject() { } 00050 00051 /** 00052 * \brief Return the type of object (i.e. Mesh/BSDF/etc.) 00053 * provided by this instance 00054 * */ 00055 virtual EClassType getClassType() const = 0; 00056 00057 /** 00058 * \brief Add a child object to the current instance 00059 * 00060 * The default implementation does not support children and 00061 * simply throws an exception 00062 */ 00063 virtual void addChild(NoriObject *child); 00064 00065 /** 00066 * \brief Set the parent object 00067 * 00068 * Subclasses may choose to override this method to be 00069 * notified when they are added to a parent object. The 00070 * default implementation does nothing. 00071 */ 00072 virtual void setParent(NoriObject *parent); 00073 00074 /** 00075 * \brief Perform some action associated with the object 00076 * 00077 * The default implementation throws an exception. Certain objects 00078 * may choose to override it, e.g. to implement initialization, 00079 * testing, or rendering functionality. 00080 * 00081 * This function is called by the XML parser once it has 00082 * constructed an object and added all of its children 00083 * using \ref addChild(). 00084 */ 00085 virtual void activate(); 00086 00087 /// Return a brief string summary of the instance (for debugging purposes) 00088 virtual QString toString() const = 0; 00089 00090 /// Turn a class type into a human-readable string 00091 inline static QString classTypeName(EClassType type) { 00092 switch (type) { 00093 case EScene: return "scene"; 00094 case EMesh: return "mesh"; 00095 case EBSDF: return "bsdf"; 00096 case ELuminaire: return "luminaire"; 00097 case ECamera: return "camera"; 00098 case EIntegrator: return "integrator"; 00099 case ESampler: return "sampler"; 00100 case ETest: return "test"; 00101 default: return "<unknown>"; 00102 } 00103 } 00104 }; 00105 00106 /** 00107 * \brief Factory for Nori objects 00108 * 00109 * This utility class is part of a mini-RTTI framework and can 00110 * instantiate arbitrary Nori objects by their name. 00111 */ 00112 class NoriObjectFactory { 00113 public: 00114 typedef boost::function<NoriObject *(const PropertyList &)> Constructor; 00115 00116 /** 00117 * \brief Register an object constructor with the object factory 00118 * 00119 * This function is called by the macro \ref NORI_REGISTER_CLASS 00120 * 00121 * \param name 00122 * An internal name that is associated with this class. This is the 00123 * 'type' field found in the scene description XML files 00124 * 00125 * \param constr 00126 * A Boost function pointer to an anonymous function that is 00127 * able to call the constructor of the class. 00128 */ 00129 static void registerClass(const QString &name, const Constructor &constr); 00130 00131 /** 00132 * \brief Construct an instance from the class of the given name 00133 * 00134 * \param name 00135 * An internal name that is associated with this class. This is the 00136 * 'type' field found in the scene description XML files 00137 * 00138 * \param propList 00139 * A list of properties that will be passed to the constructor 00140 * of the class. 00141 */ 00142 inline static NoriObject *createInstance(const QString &name, 00143 const PropertyList &propList) { 00144 if (m_constructors->find(name) == m_constructors->end()) 00145 throw NoriException(QString("A constructor for class '%1' " 00146 "could not be found!").arg(name)); 00147 return (*m_constructors)[name](propList); 00148 } 00149 private: 00150 static std::map<QString, Constructor> *m_constructors; 00151 }; 00152 00153 /// Macro for registering an object constructor with the \ref NoriObjectFactory 00154 #define NORI_REGISTER_CLASS(cls, name) \ 00155 cls *cls ##_create(const PropertyList &list) { \ 00156 return new cls(list); \ 00157 } \ 00158 static struct cls ##_{ \ 00159 cls ##_() { \ 00160 NoriObjectFactory::registerClass(name, cls ##_create); \ 00161 } \ 00162 } cls ##__; 00163 00164 NORI_NAMESPACE_END 00165 00166 #endif /* __OBJECT_H */