diff --git a/SConstruct b/SConstruct index c5687241..47a92b2b 100644 --- a/SConstruct +++ b/SConstruct @@ -277,6 +277,12 @@ env.Append(LIBPATH=['src/libcore']) # Rendering-specific library renderEnv = env.Clone() renderEnv.Append(CPPDEFINES = {'MTS_BUILD_MODULE' : 'MTS_MODULE_RENDER'} ) +if renderEnv.has_key('XERCESINCLUDE'): + renderEnv.Append(CPPPATH=renderEnv['XERCESINCLUDE']) +if renderEnv.has_key('XERCESLIBDIR'): + renderEnv.Append(LIBPATH=renderEnv['XERCESLIBDIR']) +if renderEnv.has_key('XERCESLIB'): + renderEnv.Append(LIBS=renderEnv['XERCESLIB']) librender = renderEnv.SharedLibrary('src/librender/mitsuba-render', [ 'src/librender/bsdf.cpp', 'src/librender/camera.cpp', 'src/librender/film.cpp', 'src/librender/integrator.cpp', @@ -295,7 +301,8 @@ librender = renderEnv.SharedLibrary('src/librender/mitsuba-render', [ 'src/librender/preview.cpp', 'src/librender/photonmap.cpp', 'src/librender/gatherproc.cpp', 'src/librender/mipmap3d.cpp', 'src/librender/volume.cpp', 'src/librender/vpl.cpp', - 'src/librender/shader.cpp' + 'src/librender/shader.cpp', 'src/librender/shandler.cpp', + 'src/librender/util.cpp' ]) if sys.platform == "darwin": @@ -353,12 +360,6 @@ env['SHLIBPREFIX']='' # Environment with Xerces + wxWidgets mainEnv = env.Clone() -if mainEnv.has_key('XERCESINCLUDE'): - mainEnv.Append(CPPPATH=mainEnv['XERCESINCLUDE']) -if mainEnv.has_key('XERCESLIBDIR'): - mainEnv.Append(LIBPATH=mainEnv['XERCESLIBDIR']) -if mainEnv.has_key('XERCESLIB'): - mainEnv.Append(LIBS=mainEnv['XERCESLIB']) if mainEnv.has_key('GLLIB'): mainEnv.Append(LIBS=mainEnv['GLLIB']) if mainEnv.has_key('GLLIBDIR'): @@ -374,12 +375,11 @@ darwinStub = [] if sys.platform == 'win32': resources += [env.RES('tools/windows/mitsuba_res.rc'), env.StaticObject('src/mitsuba/getopt.c')] -shandler = mainEnv.StaticObject('src/mitsuba/shandler.cpp') # Build the command-line+GUI interface mainEnv.Program('mtssrv', resources + ['src/mitsuba/mtssrv.cpp']) -mainEnv.Program('mitsuba', resources + ['src/mitsuba/mitsuba.cpp', shandler]) -mainEnv.Program('mtsutil', resources + ['src/mitsuba/mtsutil.cpp', shandler]) +mainEnv.Program('mitsuba', resources + ['src/mitsuba/mitsuba.cpp']) +mainEnv.Program('mtsutil', resources + ['src/mitsuba/mtsutil.cpp']) if sys.platform == 'darwin': mainEnv_osx = mainEnv.Clone(); @@ -388,10 +388,7 @@ if sys.platform == 'darwin': mainEnv_osx['CXXFLAGS'].append('-fno-strict-aliasing'); darwinStub += [mainEnv_osx.StaticObject('src/mitsuba/darwin_stub.mm')] -env.Program('src/utils/utils_test', ['src/utils/utils_test.cpp']) env.Program('src/utils/joinrgb', ['src/utils/joinrgb.cpp']) -env.Program('src/utils/ssalbedo', ['src/utils/ssalbedo.cpp']) -env.Program('src/utils/dumpimage', ['src/utils/dumpimage.cpp']) env.Program('src/utils/ttest', ['src/utils/ttest.cpp']) env.Program('src/utils/createvol', ['src/utils/createvol.cpp']) @@ -435,7 +432,7 @@ if hasQt: qtInterfaces = [qtEnv.Uic4(uic) for uic in scanFiles('src/qtgui', ['*.ui'])] qtResources = [qtEnv.Qrc(qrc) for qrc in scanFiles('src/qtgui', ['*.qrc'])] - qtgui_files = scanFiles('src/qtgui', ['*.cpp']) + qtResources + shandler + resources + qtgui_files = scanFiles('src/qtgui', ['*.cpp']) + qtResources + resources if hasCollada: qtgui_files += converter_objects @@ -601,6 +598,11 @@ plugins += env.SharedLibrary('plugins/vpl', ['src/integrators/vpl/vpl.cpp']) # pathvertex_mlt, path_mlt #]) +# Testcases +for plugin in glob.glob('src/tests/test_*.cpp'): + name = os.path.basename(plugin) + plugins += env.SharedLibrary('plugins/' + name[0:len(name)-4], plugin) + installTargets = [] # Windows build? diff --git a/doc/parallelization.tex b/doc/parallelization.tex index 3d6e3a7c..1e83ea35 100644 --- a/doc/parallelization.tex +++ b/doc/parallelization.tex @@ -36,17 +36,14 @@ MTS_NAMESPACE_BEGIN class ROT13Encoder : public Utility { public: - ROT13Encoder(UtilityServices *us) : Utility(us) { } - int run(int argc, char **argv) { cout << "Hello world!" << endl; return 0; } - MTS_DECLARE_CLASS() + MTS_DECLARE_UTILITY() }; -MTS_IMPLEMENT_CLASS(ROT13Encoder, false, Utility) MTS_EXPORT_UTILITY(ROT13Encoder, "Perform a ROT13 encryption of a string") MTS_NAMESPACE_END \end{cpp} diff --git a/include/mitsuba/core/plugin.h b/include/mitsuba/core/plugin.h index a8b68c05..480348e4 100644 --- a/include/mitsuba/core/plugin.h +++ b/include/mitsuba/core/plugin.h @@ -6,7 +6,6 @@ MTS_NAMESPACE_BEGIN class Utility; -class UtilityServices; /** * Abstract plugin class -- can represent loadable configurable objects @@ -15,7 +14,7 @@ class UtilityServices; */ class MTS_EXPORT_CORE Plugin { typedef void *(*CreateInstanceFunc)(const Properties &props); - typedef void *(*CreateUtilityFunc)(UtilityServices *us); + typedef void *(*CreateUtilityFunc)(); typedef char *(*GetDescriptionFunc)(); public: /// Load a plugin from the supplied path @@ -31,7 +30,7 @@ public: ConfigurableObject *createInstance(const Properties &props) const; /// Return an utility instance (if this is an utility plugin) - Utility *createUtility(UtilityServices *us) const; + Utility *createUtility() const; /// Return a description of this plugin std::string getDescription() const; diff --git a/include/mitsuba/core/shvector.h b/include/mitsuba/core/shvector.h index 18e4c23d..8d722e5a 100644 --- a/include/mitsuba/core/shvector.h +++ b/include/mitsuba/core/shvector.h @@ -234,7 +234,7 @@ public: Float value = f(sphericalDirection(theta, phi))*std::sin(theta) * weightExt*weightInt; - + for (int l=0; lrayIntersect(ray); diff --git a/src/mitsuba/shandler.h b/include/mitsuba/render/shandler.h similarity index 98% rename from src/mitsuba/shandler.h rename to include/mitsuba/render/shandler.h index 29988f95..fe71a379 100644 --- a/src/mitsuba/shandler.h +++ b/include/mitsuba/render/shandler.h @@ -11,7 +11,7 @@ #include XERCES_CPP_NAMESPACE_USE -using namespace mitsuba; +MTS_NAMESPACE_BEGIN /** * XML parser for mitsuba scene files. Uses Xerces-C and SAX @@ -72,4 +72,6 @@ private: bool m_isIncludedFile; }; +MTS_NAMESPACE_END + #endif /* __SHANDLER_H */ diff --git a/include/mitsuba/render/testcase.h b/include/mitsuba/render/testcase.h index 011c1b47..546d70ca 100644 --- a/include/mitsuba/render/testcase.h +++ b/include/mitsuba/render/testcase.h @@ -1,10 +1,45 @@ #if !defined(__TESTCASE_H) #define __TESTCASE_H -#include +#include MTS_NAMESPACE_BEGIN +/** \brief Base class of all testcases. Implementations of this + * interface can be executed using the 'mtsutil' command. The execution + * order is as follows: after initializaiton using init(), any tests + * declared using the MTS_DECLARE_TEST() macro are executed. Finally, + * the shutdown() method is called. See the files in 'mitsuba/src/tests' + * for examples. + */ +class MTS_EXPORT_RENDER TestCase : public Utility { +public: + /** + * Perform any required initializations. The default + * implementation simply returns + */ + virtual void init(); + + /** + * Execute any required shutdown code. The default + * implementation simply returns + */ + virtual void shutdown(); + + /// Return the number of executed testcases + inline int getExecuted() const { return m_executed; } + + /// Return the number of successfully executed testcases + inline int getSucceeded() const { return m_succeeded; } + + MTS_DECLARE_CLASS() +protected: + /// Virtual destructor + virtual ~TestCase() { } +protected: + int m_executed, m_succeeded; +}; + /** * The test supervisor is used when rendering a collection of testcases in the * form of scenes with analytic solutions. Reference output is compared against @@ -40,4 +75,40 @@ private: MTS_NAMESPACE_END +#define EXECUTE_GUARDED(name) \ + try { \ + Log(EInfo, "Executing test \"%s\" ..", #name); \ + m_executed++;\ + name();\ + m_succeeded++;\ + } catch (std::exception &e) {\ + Log(EInfo, "Testcase failed with error: %s", e.what());\ + } + +#define MTS_BEGIN_TESTCASE() \ + MTS_DECLARE_CLASS() \ + int run(int argc, char **argv) {\ + init(); \ + Log(EInfo, "Executing testcase \"%s\" ..", getClass()->getName().c_str()); \ + m_executed = m_succeeded = 0; + +#define MTS_DECLARE_TEST(name) \ + EXECUTE_GUARDED(name) + +#define MTS_END_TESTCASE()\ + shutdown();\ + return 0;\ + } + +#define MTS_EXPORT_TESTCASE(name, descr) \ + MTS_IMPLEMENT_CLASS(name, false, TestCase) \ + extern "C" { \ + void MTS_EXPORT *CreateUtility() { \ + return new name(); \ + } \ + const char MTS_EXPORT *GetDescription() { \ + return descr; \ + } \ + } + #endif /* __TESTCASE_H */ diff --git a/include/mitsuba/render/util.h b/include/mitsuba/render/util.h index 9cf76c4f..0e4bfa2f 100644 --- a/include/mitsuba/render/util.h +++ b/include/mitsuba/render/util.h @@ -5,24 +5,12 @@ MTS_NAMESPACE_BEGIN -/** - * Contains functionality provided to utility plugins, - * such as loading a scene from an XML file. - */ -class MTS_EXPORT_RENDER UtilityServices { -public: - virtual ref loadScene(const std::string &filename) = 0; -}; - /** \brief Abstract utility class -- can be used to implement * loadable utility plugins that perform various actions. They * can be started using the 'mtsutil' launcher. */ class MTS_EXPORT_RENDER Utility : public Object { public: - inline Utility(UtilityServices *services) - : m_utilityServices(services) { } - /** * Run the utility. The supplied argc * and argv parameters contain any @@ -38,17 +26,17 @@ protected: virtual ~Utility() { } /// Load a scene - inline ref loadScene(const std::string &fname) { - return m_utilityServices->loadScene(fname); - } -private: - UtilityServices *m_utilityServices; + ref loadScene(const std::string &fname); }; +#define MTS_DECLARE_UTILITY() \ + MTS_DECLARE_CLASS() + #define MTS_EXPORT_UTILITY(name, descr) \ + MTS_IMPLEMENT_CLASS(name, false, Utility) \ extern "C" { \ - void MTS_EXPORT *CreateUtility(UtilityServices *us) { \ - return new name(us); \ + void MTS_EXPORT *CreateUtility() { \ + return new name(); \ } \ const char MTS_EXPORT *GetDescription() { \ return descr; \ diff --git a/src/libcore/plugin.cpp b/src/libcore/plugin.cpp index 4a2b3083..290a045c 100644 --- a/src/libcore/plugin.cpp +++ b/src/libcore/plugin.cpp @@ -76,8 +76,8 @@ ConfigurableObject *Plugin::createInstance(const Properties &props) const { return (ConfigurableObject *) m_createInstance(props); } -Utility *Plugin::createUtility(UtilityServices *us) const { - return (Utility *) m_createUtility(us); +Utility *Plugin::createUtility() const { + return (Utility *) m_createUtility(); } std::string Plugin::getDescription() const { diff --git a/src/libcore/util.cpp b/src/libcore/util.cpp index ae133409..76630128 100644 --- a/src/libcore/util.cpp +++ b/src/libcore/util.cpp @@ -177,6 +177,10 @@ bool endsWith(const std::string& str, const std::string& end) { return (pos == str.size() - end.size()) && str.length() >= end.length(); } +bool startsWith(const std::string& str, const std::string& start) { + return str.find(start) == 0; +} + void * __restrict allocAligned(size_t size) { #if defined(WIN32) return _aligned_malloc(size, L1_CACHE_LINE_SIZE); @@ -370,6 +374,46 @@ bool solveQuadratic(Float a, Float b, Float c, Float &x0, Float &x1) { return true; } +bool solveQuadraticDouble(double a, double b, double c, double &x0, double &x1) { + /* Linear case */ + if (a == 0) { + if (b != 0) { + x0 = x1 = -c / b; + return true; + } + return false; + } + + double discrim = b*b - 4.0f*a*c; + + /* Leave if there is no solution */ + if (discrim < 0) + return false; + + double temp, sqrtDiscrim = std::sqrt(discrim); + + /* Numerically stable version of (-b (+/-) sqrtDiscrim) / (2 * a) + * + * Based on the observation that one solution is always + * accurate while the other is not. Finds the solution of + * greater magnitude which does not suffer from loss of + * precision and then uses the identity x1 * x2 = c / a + */ + if (b < 0) + temp = -0.5f * (b - sqrtDiscrim); + else + temp = -0.5f * (b + sqrtDiscrim); + + x0 = temp / a; + x1 = c / temp; + + /* Return the results so that x0 < x1 */ + if (x0 > x1) + std::swap(x0, x1); + + return true; +} + bool solveLinearSystem2x2(const Float a[2][2], const Float b[2], Float x[2]) { Float det = a[0][0] * a[1][1] - a[0][1] * a[1][0]; diff --git a/src/librender/kdtree_traversal.cpp b/src/librender/kdtree_traversal.cpp index 94331422..1fa7fd55 100644 --- a/src/librender/kdtree_traversal.cpp +++ b/src/librender/kdtree_traversal.cpp @@ -211,8 +211,15 @@ bool KDTree::rayIntersect(const Ray &ray, Intersection &its) const { ++raysTraced; if (m_rootBounds.rayIntersect(ray, mint, maxt)) { its.t = std::numeric_limits::infinity(); - if (ray.mint > mint) - mint = ray.mint; + + /* Adaptive ray epsilon */ + Float rayMinT = ray.mint; + if (rayMinT == Epsilon) + rayMinT *= std::max(std::max(std::abs(ray.o.x), + std::abs(ray.o.y)), std::abs(ray.o.z)); + + if (rayMinT > mint) + mint = rayMinT; if (ray.maxt < maxt) maxt = ray.maxt; if (maxt <= mint) @@ -245,20 +252,6 @@ bool KDTree::rayIntersect(const Ray &ray, Intersection &its) const { } #endif -#if 0 - /* Slightly offset along the normal to avoid surface acne. - The offset is dependent on the magnitude of each component */ - if (dot(faceNormal, ray.d) < 0) { - its.p.x += faceNormal.x * std::abs(its.p.x) * 1e-6f; - its.p.y += faceNormal.y * std::abs(its.p.y) * 1e-6f; - its.p.z += faceNormal.z * std::abs(its.p.z) * 1e-6f; - } else { - its.p.x -= faceNormal.x * std::abs(its.p.x) * 1e-6f; - its.p.y -= faceNormal.y * std::abs(its.p.y) * 1e-6f; - its.p.z -= faceNormal.z * std::abs(its.p.z) * 1e-6f; - } -#endif - const Vector b(1 - its.uv.x - its.uv.y, its.uv.x, its.uv.y); diff --git a/src/librender/scene.cpp b/src/librender/scene.cpp index d4c9cb80..d5b0869b 100644 --- a/src/librender/scene.cpp +++ b/src/librender/scene.cpp @@ -635,5 +635,4 @@ std::string Scene::toString() const { } MTS_IMPLEMENT_CLASS_S(Scene, false, ConfigurableObject) -MTS_IMPLEMENT_CLASS(Utility, true, Object) MTS_NAMESPACE_END diff --git a/src/mitsuba/shandler.cpp b/src/librender/shandler.cpp similarity index 99% rename from src/mitsuba/shandler.cpp rename to src/librender/shandler.cpp index a6c9e5ec..37e63ab3 100644 --- a/src/mitsuba/shandler.cpp +++ b/src/librender/shandler.cpp @@ -1,6 +1,8 @@ #include #include -#include "shandler.h" +#include + +MTS_NAMESPACE_BEGIN SceneHandler::SceneHandler() : m_isIncludedFile(false) { m_pluginManager = PluginManager::getInstance(); @@ -399,3 +401,4 @@ void SceneHandler::fatalError(const SAXParseException& e) { transcode(e.getMessage()).c_str()); } +MTS_NAMESPACE_END diff --git a/src/librender/testcase.cpp b/src/librender/testcase.cpp index 7718c22e..f8654af6 100644 --- a/src/librender/testcase.cpp +++ b/src/librender/testcase.cpp @@ -5,6 +5,9 @@ MTS_NAMESPACE_BEGIN +void TestCase::init() { } +void TestCase::shutdown() { } + struct Sample { Float value; Float variance; @@ -169,4 +172,5 @@ void TestSupervisor::printSummary() const { } MTS_IMPLEMENT_CLASS(TestSupervisor, false, Object) +MTS_IMPLEMENT_CLASS(TestCase, false, Utility) MTS_NAMESPACE_END diff --git a/src/librender/util.cpp b/src/librender/util.cpp new file mode 100644 index 00000000..c34c6508 --- /dev/null +++ b/src/librender/util.cpp @@ -0,0 +1,36 @@ +#include +#include +#include +#include + +MTS_NAMESPACE_BEGIN + +ref Utility::loadScene(const std::string &filename) { + /* Prepare for parsing scene descriptions */ + FileResolver *resolver = FileResolver::getInstance(); + SAXParser* parser = new SAXParser(); + std::string schemaPath = resolver->resolveAbsolute("schema/scene.xsd"); + + /* Check against the 'scene.xsd' XML Schema */ + parser->setDoSchema(true); + parser->setValidationSchemaFullChecking(true); + parser->setValidationScheme(SAXParser::Val_Always); + parser->setExternalNoNamespaceSchemaLocation(schemaPath.c_str()); + + std::map parameters; + SceneHandler *handler = new SceneHandler(parameters); + parser->setDoNamespaces(true); + parser->setDocumentHandler(handler); + parser->setErrorHandler(handler); + + parser->parse(filename.c_str()); + ref scene = handler->getScene(); + + delete parser; + delete handler; + + return scene; +} + +MTS_IMPLEMENT_CLASS(Utility, true, Object) +MTS_NAMESPACE_END diff --git a/src/mitsuba/mitsuba.cpp b/src/mitsuba/mitsuba.cpp index e383e462..e0038da8 100644 --- a/src/mitsuba/mitsuba.cpp +++ b/src/mitsuba/mitsuba.cpp @@ -5,9 +5,9 @@ #include #include #include +#include #include #include -#include "shandler.h" #if defined(WIN32) #include "getopt.h" diff --git a/src/mitsuba/mtsutil.cpp b/src/mitsuba/mtsutil.cpp index 1e8e334c..a03fe922 100644 --- a/src/mitsuba/mtsutil.cpp +++ b/src/mitsuba/mtsutil.cpp @@ -6,10 +6,10 @@ #include #include #include +#include #include #include #include -#include "shandler.h" #if !defined(WIN32) #include @@ -24,36 +24,6 @@ using namespace mitsuba; -class UtilityServicesImpl : public UtilityServices { -public: - ref loadScene(const std::string &filename) { - /* Prepare for parsing scene descriptions */ - FileResolver *resolver = FileResolver::getInstance(); - SAXParser* parser = new SAXParser(); - std::string schemaPath = resolver->resolveAbsolute("schema/scene.xsd"); - - /* Check against the 'scene.xsd' XML Schema */ - parser->setDoSchema(true); - parser->setValidationSchemaFullChecking(true); - parser->setValidationScheme(SAXParser::Val_Always); - parser->setExternalNoNamespaceSchemaLocation(schemaPath.c_str()); - - std::map parameters; - SceneHandler *handler = new SceneHandler(parameters); - parser->setDoNamespaces(true); - parser->setDocumentHandler(handler); - parser->setErrorHandler(handler); - - parser->parse(filename.c_str()); - ref scene = handler->getScene(); - - delete parser; - delete handler; - - return scene; - } -}; - void help() { cout << "Mitsuba version " MTS_VERSION ", Copyright (c) " MTS_YEAR " Wenzel Jakob" << endl; cout << "Usage: mtsutil [mtsutil options] [arguments]" << endl; @@ -74,10 +44,14 @@ void help() { cout << " -s file Connect to additional Mitsuba servers specified in a file" << endl; cout << " with one name per line (same format as in -c)" << endl<< endl; cout << " -n name Assign a node name to this instance (Default: host name)" << endl << endl; + cout << " -t Execute all testcases" << endl << endl; cout << " -v Be more verbose" << endl << endl; FileResolver *resolver = FileResolver::getInstance(); - cout << "The following utilities are available:" << endl << endl; + std::ostringstream utilities, testcases; + + testcases << "The following testcases are available:" << endl << endl; + utilities << endl << "The following utilities are available:" << endl << endl; std::vector dirPaths = resolver->resolveAllAbsolute("plugins"); std::set seen; @@ -115,10 +89,17 @@ void help() { Plugin utility(shortName, fullName); if (!utility.isUtility()) continue; - cout << "\t" << shortName; - for (int i=0; i<22-(int) shortName.length(); ++i) - cout << ' '; - cout << utility.getDescription() << endl; + if (startsWith(shortName, "test_")) { + testcases << "\t" << shortName; + for (int i=0; i<22-(int) shortName.length(); ++i) + testcases << ' '; + testcases << utility.getDescription() << endl; + } else { + utilities << "\t" << shortName; + for (int i=0; i<22-(int) shortName.length(); ++i) + utilities << ' '; + utilities << utility.getDescription() << endl; + } #if !defined(WIN32) } #else @@ -126,6 +107,8 @@ void help() { FindClose(hFind); #endif } + + cout << testcases.str() << utilities.str(); } @@ -140,6 +123,7 @@ int ubi_main(int argc, char **argv) { bool quietMode = false; ELogLevel logLevel = EInfo; FileResolver *resolver = FileResolver::getInstance(); + bool testCaseMode = false; if (argc < 2) { help(); @@ -148,7 +132,7 @@ int ubi_main(int argc, char **argv) { optind = 1; /* Parse command-line arguments */ - while ((optchar = getopt(argc, argv, "a:c:s:n:p:qhv")) != -1) { + while ((optchar = getopt(argc, argv, "a:c:s:n:p:qhvt")) != -1) { switch (optchar) { case 'a': { std::vector paths = tokenize(optarg, ";"); @@ -159,6 +143,9 @@ int ubi_main(int argc, char **argv) { case 'c': networkHosts = networkHosts + std::string(";") + std::string(optarg); break; + case 't': + testCaseMode = true; + break; case 's': { std::ifstream is(optarg); if (is.fail()) @@ -261,36 +248,96 @@ int ubi_main(int argc, char **argv) { scheduler->start(); - if (argc <= optind) { - std::cerr << "A utility name must be supplied!" << endl; - return -1; - } + if (testCaseMode) { + std::vector dirPaths = resolver->resolveAllAbsolute("plugins"); + std::set seen; + int executed = 0, succeeded = 0; - /* Build the full plugin file name */ -#if defined(WIN32) - std::string shortName = std::string("plugins/") + argv[optind] + std::string(".dll"); -#elif defined(__OSX__) - std::string shortName = std::string("plugins/") + argv[optind] + std::string(".dylib"); + for (size_t i=0; id_name); + if (!endsWith(fname, ".dylib") && !endsWith(fname, ".so")) + continue; + std::string fullName = dirPath + "/" + fname; #else - std::string shortName = std::string("plugins/") + argv[optind] + std::string(".so"); + HANDLE hFind; + WIN32_FIND_DATA findFileData; + + if ((hFind = FindFirstFile((dirPath + "\\*.dll").c_str(), &findFileData)) == INVALID_HANDLE_VALUE) + SLog(EInfo, "Could not open plugin directory"); + + do { + std::string fname = findFileData.cFileName; + std::string fullName = dirPath + "\\" + fname; #endif - std::string fullName = resolver->resolve(shortName); + std::string shortName = fname.substr(0, strrchr(fname.c_str(), '.') - fname.c_str()); + if (!startsWith(shortName, "test_") || seen.find(shortName) != seen.end()) + continue; + seen.insert(shortName); + Plugin plugin(shortName, fullName); + if (!plugin.isUtility()) + continue; - if (!FileStream::exists(fullName)) { - /* Plugin not found! */ - SLog(EError, "Utility \"%s\" not found (run \"mtsutil\" without arguments to " - "see a list of available utilities)", fullName.c_str()); + ref utility = plugin.createUtility(); + + TestCase *testCase = static_cast(utility.get()); + if (!utility->getClass()->derivesFrom(TestCase::m_theClass)) + SLog(EError, "This is not a test case!"); + + if (testCase->run(argc-optind, argv+optind) != 0) + SLog(EError, "Testcase unexpectedly returned with a nonzero value."); + + executed += testCase->getExecuted(); + succeeded += testCase->getSucceeded(); +#if !defined(WIN32) + } +#else + } while (FindNextFile(hFind, &findFileData)); + FindClose(hFind); +#endif + } + + SLog(EInfo, "Ran %i tests, %i succeeded, %i failed.", executed, succeeded, executed-succeeded); + } else { + if (argc <= optind) { + std::cerr << "A utility name must be supplied!" << endl; + return -1; + } + + /* Build the full plugin file name */ +#if defined(WIN32) + std::string shortName = std::string("plugins/") + argv[optind] + std::string(".dll"); +#elif defined(__OSX__) + std::string shortName = std::string("plugins/") + argv[optind] + std::string(".dylib"); +#else + std::string shortName = std::string("plugins/") + argv[optind] + std::string(".so"); +#endif + std::string fullName = resolver->resolve(shortName); + + if (!FileStream::exists(fullName)) { + /* Plugin not found! */ + SLog(EError, "Utility \"%s\" not found (run \"mtsutil\" without arguments to " + "see a list of available utilities)", fullName.c_str()); + } + SLog(EInfo, "Loading utility \"%s\" ..", argv[optind]); + Plugin *plugin = new Plugin(argv[optind], fullName); + if (!plugin->isUtility()) + SLog(EError, "This plugin does not implement the 'Utility' interface!"); + Statistics::getInstance()->logPlugin(argv[optind], plugin->getDescription()); + + ref utility = plugin->createUtility(); + + return utility->run(argc-optind, argv+optind); } - SLog(EInfo, "Loading utility \"%s\" ..", argv[optind]); - Plugin *plugin = new Plugin(argv[optind], fullName); - if (!plugin->isUtility()) - SLog(EError, "This plugin does not implement the 'Utility' interface!"); - Statistics::getInstance()->logPlugin(argv[optind], plugin->getDescription()); - - UtilityServices *utilityServices = new UtilityServicesImpl(); - Utility *utility = plugin->createUtility(utilityServices); - - return utility->run(argc-optind, argv+optind); } catch (const std::exception &e) { std::cerr << "Caught a critical exeption: " << e.what() << std::endl; } catch (...) { diff --git a/src/qtgui/common.h b/src/qtgui/common.h index 2869ce9b..400c838b 100644 --- a/src/qtgui/common.h +++ b/src/qtgui/common.h @@ -10,10 +10,15 @@ using namespace mitsuba; enum EConnectionType { - ESSHConnection, + ESSHConnection = 0, EDirectConnection }; +enum ENavigationMode { + EFlythroughFixedYaw = 0, + EFlythrough +}; + namespace mitsuba { class RemoteWorker; }; @@ -123,7 +128,7 @@ struct SceneContext { float progress; QString eta, progressName; ref framebuffer; - EMode mode; + EMode mode, cancelMode; Float gamma, exposure, clamping; bool srgb; int pathLength, shadowMapResolution; diff --git a/src/qtgui/glwidget.cpp b/src/qtgui/glwidget.cpp index 09b5c9b9..d1050316 100644 --- a/src/qtgui/glwidget.cpp +++ b/src/qtgui/glwidget.cpp @@ -29,6 +29,7 @@ GLWidget::GLWidget(QWidget *parent) : connect(m_preview, SIGNAL(statusMessage(const QString &)), this, SIGNAL(statusMessage(const QString &)), Qt::QueuedConnection); m_invertMouse = false; + m_navigationMode = EFlythroughFixedYaw; m_ignoreMouseEvent = QPoint(0, 0); m_didSetCursor = false; m_softwareFallback = false; @@ -456,9 +457,12 @@ void GLWidget::timerImpulse() { if (m_context->renderJob) { m_context->renderJob->cancel(); m_context->cancelled = true; + m_context->cancelMode = EPreview; return; - } else { + } else if (m_context->mode != EPreview) { m_context->mode = EPreview; + // causes updateUI to be called in the main window + emit stopRendering(); } resetPreview(); @@ -468,7 +472,7 @@ void GLWidget::resetPreview() { if (!m_context || !m_context->scene || !m_preview->isRunning()) return; bool motion = m_leftKeyDown || m_rightKeyDown || - m_upKeyDown || m_downKeyDown || m_mouseButtonDown; + m_upKeyDown || m_downKeyDown || m_mouseButtonDown; m_preview->setSceneContext(m_context, false, motion); updateGL(); } @@ -555,6 +559,14 @@ void GLWidget::mouseMoveEvent(QMouseEvent *event) { PinholeCamera *camera = static_cast(m_context->scene->getCamera()); Point p = camera->getInverseViewTransform()(Point(0,0,0)); Vector direction = camera->getInverseViewTransform()(Vector(0,0,1)); + Vector up; + + if (m_navigationMode == EFlythrough) + up = camera->getInverseViewTransform()(Vector(0,1,0)); + else if (m_navigationMode == EFlythroughFixedYaw) + up = m_context->up; + else + SLog(EError, "Unknown navigation mode encountered!"); bool didMove = false; @@ -570,10 +582,10 @@ void GLWidget::mouseMoveEvent(QMouseEvent *event) { direction = trafo.inverse()(Vector(0,0,1)); if (camera->getViewTransform().det3x3() < 0) { - camera->setInverseViewTransform(Transform::lookAt(p, p+direction, m_context->up)); + camera->setInverseViewTransform(Transform::lookAt(p, p+direction, up)); } else { camera->setInverseViewTransform( - Transform::lookAt(p, p+direction, m_context->up) * + Transform::lookAt(p, p+direction, up) * Transform::scale(Vector(-1,1,1)) ); } @@ -585,10 +597,10 @@ void GLWidget::mouseMoveEvent(QMouseEvent *event) { Float fovChange = rel.y() * m_mouseSensitivity * .03f; if (camera->getViewTransform().det3x3() < 0) { - m_context->up = Transform::rotate(direction, roll)(m_context->up); + m_context->up = Transform::rotate(direction, roll)(up); camera->setInverseViewTransform(Transform::lookAt(p, p+direction, m_context->up)); } else { - m_context->up = Transform::rotate(direction, -roll)(m_context->up); + m_context->up = Transform::rotate(direction, -roll)(up); camera->setInverseViewTransform( Transform::lookAt(p, p+direction, m_context->up) * Transform::scale(Vector(-1,1,1)) @@ -630,7 +642,7 @@ void GLWidget::wheelEvent(QWheelEvent *event) { if (!bar->isVisible() || !m_preview->isRunning()) return; - + int oldStep = bar->singleStep(); bar->setSingleStep(event->delta()/4); #if defined(__OSX__) @@ -658,8 +670,8 @@ void GLWidget::mouseReleaseEvent(QMouseEvent *event) { if (!m_preview->isRunning()) return; if (event->buttons() == 0) { + m_mouseButtonDown = false; if (m_didSetCursor) { - m_mouseButtonDown = false; resetPreview(); QApplication::restoreOverrideCursor(); QCursor::setPos(m_initialMousePos); diff --git a/src/qtgui/glwidget.h b/src/qtgui/glwidget.h index 04efb968..0b8cc639 100644 --- a/src/qtgui/glwidget.h +++ b/src/qtgui/glwidget.h @@ -32,6 +32,8 @@ public: inline bool getInvertMouse() const { return m_invertMouse; } void setInvertMouse(bool invert) { m_invertMouse = invert; } + inline ENavigationMode getNavigationMode() const { return m_navigationMode; } + void setNavigationMode(ENavigationMode mode) { m_navigationMode = mode; } inline int getMouseSensitivity() const { return m_mouseSensitivity; } void setMouseSensitivity(int sensitivity) { m_mouseSensitivity = sensitivity; } void setScrollBars(QScrollBar *hScroll, QScrollBar *vScroll); @@ -119,6 +121,7 @@ private: QTimer *m_movementTimer, *m_redrawTimer; QScrollBar *m_hScroll, *m_vScroll; ref m_clock; + ENavigationMode m_navigationMode; bool m_invertMouse, m_didSetCursor; bool m_ignoreScrollEvents, m_ignoreResizeEvents; int m_mouseSensitivity, m_softwareFallback; diff --git a/src/qtgui/mainwindow.cpp b/src/qtgui/mainwindow.cpp index 15098fd0..13bcdca8 100644 --- a/src/qtgui/mainwindow.cpp +++ b/src/qtgui/mainwindow.cpp @@ -146,6 +146,8 @@ MainWindow::MainWindow(QWidget *parent) : /* Load defaults from app settings file */ ui->glView->setInvertMouse(settings.value("invertMouse", false).toBool()); ui->glView->setMouseSensitivity(settings.value("mouseSensitivity", 3).toInt()); + ui->glView->setNavigationMode((ENavigationMode) settings.value("navigationMode", + EFlythroughFixedYaw).toInt()); m_searchPaths = settings.value("searchPaths", QStringList()).toStringList(); m_blockSize = settings.value("blockSize", 32).toInt(); m_listenPort = settings.value("listenPort", MTS_DEFAULT_PORT).toInt(); @@ -181,7 +183,7 @@ MainWindow::MainWindow(QWidget *parent) : ui->toolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); QToolButton *previewButton = static_cast(ui->toolBar->widgetForAction(ui->actionPreviewSettings)); previewButton->setStyleSheet("margin-left: -5px; margin-right:-5px"); - + /* Weird Qt/OSX bug -- moving while a window while it is invisible causes it to appear move up by 65 pixels (this is related to the unified toolbar) */ move(windowPos + QPoint(0, 65)); @@ -499,6 +501,7 @@ void MainWindow::onProgressMessage(const RenderJob *job, const QString &name, context->progressName = name + ": "; updateUI(); } + void MainWindow::on_actionOpen_triggered() { QFileDialog *dialog = new QFileDialog(this, Qt::Sheet); dialog->setNameFilter(tr("Mitsuba scenes (*.xml);;EXR images (*.exr)")); @@ -662,23 +665,10 @@ void MainWindow::updateUI() { bool fallback = ui->glView->isUsingSoftwareFallback(); ui->actionStop->setEnabled(isShowingRendering); - if (isShowingRendering && !isRendering) { - if (ui->actionStop->text() != tr("Preview")) { - QIcon icon; - ui->actionStop->setText(tr("Preview")); - ui->actionStop->setToolTip(tr("Return to the realtime preview")); - icon.addFile(QString::fromUtf8(":/resources/fpreview.png"), QSize(), QIcon::Normal, QIcon::Off); - ui->actionStop->setIcon(icon); - } - } else { - if (ui->actionStop->text() != tr("Stop")) { - QIcon icon; - ui->actionStop->setText(tr("Stop")); - ui->actionStop->setToolTip(tr("Stop rendering")); - icon.addFile(QString::fromUtf8(":/resources/stop.png"), QSize(), QIcon::Normal, QIcon::Off); - ui->actionStop->setIcon(icon); - } - } + if (isShowingRendering && !isRendering) + ui->actionStop->setToolTip(tr("Return to the realtime preview")); + else + ui->actionStop->setToolTip(tr("Stop rendering")); ui->actionRender->setEnabled(isInactiveScene); ui->actionRefresh->setEnabled(isInactiveScene); @@ -972,6 +962,8 @@ void MainWindow::on_actionPreviewSettings_triggered() { connect(m_previewSettings, SIGNAL(previewMethodChanged(EPreviewMethod)), ui->glView, SLOT(setPreviewMethod(EPreviewMethod))); connect(m_previewSettings, SIGNAL(toneMappingMethodChanged(EToneMappingMethod)), ui->glView, SLOT(setToneMappingMethod(EToneMappingMethod))); connect(m_previewSettings, SIGNAL(close()), this, SLOT(onPreviewSettingsClose())); + connect(m_previewSettings, SIGNAL(diffuseReceiversChanged(bool)), ui->glView, SLOT(setDiffuseReceivers(bool))); + connect(m_previewSettings, SIGNAL(diffuseSourcesChanged(bool)), ui->glView, SLOT(setDiffuseSources(bool))); } SceneContext *ctx = NULL; if (ui->tabBar->currentIndex() != -1) @@ -1026,6 +1018,7 @@ void MainWindow::on_actionSettings_triggered() { d.setWindowModality(Qt::ApplicationModal); d.setLogLevel(logger->getLogLevel()); d.setInvertMouse(ui->glView->getInvertMouse()); + d.setNavigationMode(ui->glView->getNavigationMode()); d.setMouseSensitivity(ui->glView->getMouseSensitivity()); d.setBlockSize(m_blockSize); d.setSearchPaths(m_searchPaths); @@ -1052,10 +1045,12 @@ void MainWindow::on_actionSettings_triggered() { settings.setValue("mouseSensitivity", d.getMouseSensitivity()); settings.setValue("listenPort", d.getListenPort()); settings.setValue("nodeName", d.getNodeName()); + settings.setValue("navigationMode", (int) d.getNavigationMode()); logger->setLogLevel(d.getLogLevel()); ui->glView->setInvertMouse(d.getInvertMouse()); ui->glView->setMouseSensitivity(d.getMouseSensitivity()); + ui->glView->setNavigationMode(d.getNavigationMode()); m_blockSize = d.getBlockSize(); m_searchPaths = d.getSearchPaths(); m_checkForUpdates = d.getCheckForUpdates(); @@ -1131,6 +1126,7 @@ void MainWindow::on_actionRender_triggered() { scene->setBlockSize(m_blockSize); context->renderJob = new RenderJob("rend", scene, m_renderQueue, NULL, context->sceneResID, -1, -1, false); + context->cancelMode = ERender; if (context->mode != ERender) ui->glView->downloadFramebuffer(); context->cancelled = false; @@ -1356,6 +1352,7 @@ void MainWindow::onJobFinished(const RenderJob *job, bool cancelled) { tr("The rendering job did not complete successfully. Please check the log."), QMessageBox::Ok); } else { + context->mode = context->cancelMode; if (ui->tabBar->currentIndex() != -1 && m_context[ui->tabBar->currentIndex()] == context) ui->glView->resumePreview(); diff --git a/src/qtgui/previewsettingsdlg_cocoa.h b/src/qtgui/previewsettingsdlg_cocoa.h index e0adc866..a61036b4 100644 --- a/src/qtgui/previewsettingsdlg_cocoa.h +++ b/src/qtgui/previewsettingsdlg_cocoa.h @@ -19,6 +19,8 @@ class PreviewSettingsDlg; IBOutlet BWTransparentSlider *exposure; IBOutlet BWTransparentSlider *gamma; IBOutlet BWTransparentCheckbox *sRGB; + IBOutlet BWTransparentCheckbox *diffuseSourcesBox; + IBOutlet BWTransparentCheckbox *diffuseReceiversBox; IBOutlet NSTextField *shadowMapLabel; IBOutlet NSTextField *reinhardKeyLabel; IBOutlet NSTextField *gammaLabel; @@ -40,6 +42,8 @@ class PreviewSettingsDlg; - (IBAction) exposureChanged: (id) sender; - (IBAction) gammaChanged: (id) sender; - (IBAction) sRGBChanged: (id) sender; +- (IBAction) diffuseSourcesChanged: (id) sender; +- (IBAction) diffuseReceiversChanged: (id) sender; - (IBAction) reset: (id) sender; - (void) updateUI; - (void) showAt: (NSPoint) point; @@ -87,6 +91,12 @@ public: void triggerReinhardBurnChanged(float burn) { emit reinhardBurnChanged(burn); } + void triggerDiffuseReceiversChanged(bool value) { + emit diffuseReceiversChanged(value); + } + void triggerDiffuseSourcesChanged(bool value) { + emit diffuseSourcesChanged(value); + } void triggerClose() { emit close(); } @@ -101,6 +111,8 @@ signals: void reinhardKeyChanged(Float key); void reinhardBurnChanged(Float burn); void close(); + void diffuseReceiversChanged(bool); + void diffuseSourcesChanged(bool); private: CocoaRenderSettingsDlg *m_dlg; }; diff --git a/src/qtgui/previewsettingsdlg_cocoa_impl.mm b/src/qtgui/previewsettingsdlg_cocoa_impl.mm index 757dee0e..f0f0118b 100644 --- a/src/qtgui/previewsettingsdlg_cocoa_impl.mm +++ b/src/qtgui/previewsettingsdlg_cocoa_impl.mm @@ -54,6 +54,7 @@ bool hasShadowMaps = (sel_previewMethod == EOpenGL || sel_previewMethod == EOpenGLSinglePass); bool hasKey = (sel_toneMappingMethod == EReinhard); bool hasGamma = [sRGB state] == NSOffState; + bool hasDiffuseSources = [diffuseSourcesBox state] == NSOnState; std::string gammaStr = formatString("%.1f", [gamma floatValue]); std::string exposureStr = formatString("%.1f", [exposure floatValue]); @@ -69,6 +70,8 @@ [[gamma animator] setAlphaValue: hasGamma ? 1.0f : 0.5f]; [gammaValueLabel setStringValue: [NSString stringWithCString: gammaStr.c_str() encoding: NSASCIIStringEncoding]]; [exposureValueLabel setStringValue: [NSString stringWithCString: exposureStr.c_str() encoding: NSASCIIStringEncoding]]; + [diffuseReceiversBox setEnabled: (BOOL) hasDiffuseSources]; + [[diffuseReceiversBox animator] setAlphaValue: hasDiffuseSources ? 1.0f : 0.5f]; } - (IBAction) previewMethodChanged: (id) sender { @@ -110,6 +113,15 @@ [self updateUI]; } +- (IBAction) diffuseSourcesChanged: (id) sender { + delegate->triggerDiffuseSourcesChanged([diffuseSourcesBox state] == NSOnState); + [self updateUI]; +} + +- (IBAction) diffuseReceiversChanged: (id) sender { + delegate->triggerDiffuseReceiversChanged([diffuseReceiversBox state] == NSOnState); +} + - (IBAction) shadowMapResolutionChanged: (id) sender { int res, index = [shadowMapResolution indexOfSelectedItem]; switch (index) { @@ -144,6 +156,8 @@ [exposure setFloatValue: 0.0]; [reinhardKey setFloatValue: 0.18]; [sRGB setState: NSOnState]; + [diffuseSourcesBox setState: NSOnState]; + [diffuseReceiversBox setState: NSOffState]; [self previewMethodChanged: self]; [self toneMappingMethodChanged: self]; [self shadowMapResolutionChanged: self]; @@ -151,6 +165,8 @@ [self exposureChanged: self]; [self clampingChanged: self]; [self gammaChanged: self]; + [self diffuseSourcesChanged: self]; + [self diffuseReceiversChanged: self]; } - (void) setContext: (SceneContext *) ctx { @@ -161,6 +177,8 @@ [clamping setFloatValue: (float) ctx->clamping]; [gamma setFloatValue: (float) ctx->gamma]; [sRGB setState: ctx->srgb ? NSOnState : NSOffState]; + [diffuseSourcesBox setState: ctx->diffuseSources ? NSOnState : NSOffState]; + [diffuseReceiversBox setState: ctx->diffuseReceivers ? NSOnState : NSOffState]; if (ctx->toneMappingMethod == EGamma) [exposure setFloatValue: (float) ctx->exposure]; diff --git a/src/qtgui/programsettingsdlg.h b/src/qtgui/programsettingsdlg.h index a7527dc9..380df740 100644 --- a/src/qtgui/programsettingsdlg.h +++ b/src/qtgui/programsettingsdlg.h @@ -37,6 +37,14 @@ public: return ui->invertMouseBox->checkState() == Qt::Checked; } + inline ENavigationMode getNavigationMode() const { + return (ENavigationMode) ui->navigationModeBox->currentIndex(); + } + + inline void setNavigationMode(ENavigationMode mode) const { + ui->navigationModeBox->setCurrentIndex(mode); + } + inline void setInvertMouse(bool value) { ui->invertMouseBox->setCheckState(value ? Qt::Checked : Qt::Unchecked); } diff --git a/src/qtgui/programsettingsdlg.ui b/src/qtgui/programsettingsdlg.ui index 237ab0b9..2ac991f0 100644 --- a/src/qtgui/programsettingsdlg.ui +++ b/src/qtgui/programsettingsdlg.ui @@ -6,8 +6,8 @@ 0 0 - 354 - 485 + 377 + 500 @@ -51,7 +51,7 @@ General - + 15 @@ -186,7 +186,7 @@ system load, especially when much of the work is done over the network. - + @@ -199,7 +199,7 @@ system load, especially when much of the work is done over the network. - + 6 @@ -286,50 +286,6 @@ system load, especially when much of the work is done over the network. - - - - Specifies the threshold for displaying log messages. -For instance, setting this to "Info" means that everything -above and including "Info" is written to the console. - - - Log verbosity : - - - logVerbosityBox - - - - - - - Specifies the threshold for displaying log messages. -For instance, setting this to "Info" means that everything -above and including "Info" is written to the console. - - - - Trace - - - - - Debug - - - - - Info - - - - - Warn - - - - @@ -343,7 +299,7 @@ above and including "Info" is written to the console. - + true @@ -415,7 +371,7 @@ release via Internet every time it is started. - + Specifies how sensitive the mouse should react to @@ -450,7 +406,7 @@ movements while navigating in the realt-time preview. - + Specifies how sensitive the mouse should react to @@ -461,7 +417,7 @@ movements while navigating in the realt-time preview. - + Should the preview navigation flip the Y axis of the mouse? @@ -474,7 +430,7 @@ movements while navigating in the realt-time preview. - + Should the preview navigation flip the Y axis of the mouse? @@ -493,6 +449,96 @@ movements while navigating in the realt-time preview. + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This option specifies the camera behavior when navigating within the realtime preview.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Fly-through (Fix yaw)</span>: Always yaw around a fixed &quot;up&quot; axis, which is determined when a scene is loaded. This is intuitive and similar to a person walking through a scene, but assumes that the camera has already been set up correctly.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Fly-through</span>: Always yaw around the current camera &quot;up&quot; axis.</p></body></html> + + + Navigation : + + + navigationModeBox + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This option specifies the camera behavior when navigating within the realtime preview.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Fly-through (Fix yaw)</span>: Always yaw around a fixed &quot;up&quot; axis, which is determined when a scene is loaded. This is intuitive and similar to a person walking through a scene, but assumes that the camera has already been set up correctly.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Fly-through</span>: Always yaw around the current camera &quot;up&quot; axis.</p></body></html> + + + + Fly-through (Fix yaw) + + + + + Fly-through + + + + + + + + Specifies the threshold for displaying log messages. +For instance, setting this to "Info" means that everything +above and including "Info" is written to the console. + + + + Trace + + + + + Debug + + + + + Info + + + + + Warn + + + + + + + + Specifies the threshold for displaying log messages. +For instance, setting this to "Info" means that everything +above and including "Info" is written to the console. + + + Log verbosity : + + + logVerbosityBox + + + @@ -757,9 +803,10 @@ connections. The default setting is 7554. blockSizeBox localWorkerBox checkForUpdatesBox + logVerbosityBox + navigationModeBox invertMouseBox sensitivitySlider - logVerbosityBox searchPathList removePathButton addPathButton @@ -782,8 +829,8 @@ connections. The default setting is 7554. reject() - 280 - 412 + 286 + 475 141 @@ -798,8 +845,8 @@ connections. The default setting is 7554. accept() - 309 - 412 + 315 + 475 318 @@ -831,7 +878,7 @@ connections. The default setting is 7554. 175 - 100 + 90 26 @@ -846,8 +893,8 @@ connections. The default setting is 7554. refresh() - 224 - 74 + 175 + 62 291 diff --git a/src/qtgui/sceneloader.cpp b/src/qtgui/sceneloader.cpp index 12e78eca..4a993fab 100644 --- a/src/qtgui/sceneloader.cpp +++ b/src/qtgui/sceneloader.cpp @@ -1,7 +1,7 @@ #include #include "glwidget.h" #include "sceneloader.h" -#include "../mitsuba/shandler.h" +#include SceneLoader::SceneLoader(FileResolver *resolver, const std::string &filename) : Thread("load"), m_resolver(resolver), m_filename(filename) { diff --git a/src/shapes/cylinder.cpp b/src/shapes/cylinder.cpp index 91d19846..1072e8b2 100644 --- a/src/shapes/cylinder.cpp +++ b/src/shapes/cylinder.cpp @@ -69,29 +69,35 @@ public: } bool rayIntersect(const Ray &_ray, Float start, Float end, Float &t) const { - Float nearT, farT; Ray ray; + double nearT, farT; Ray ray; /* Transform into the local coordinate system and normalize */ m_worldToObject(_ray, ray); + + const double + ox = ray.o.x, + oy = ray.o.y, + dx = ray.d.x, + dy = ray.d.y; - const Float A = ray.d.x*ray.d.x + ray.d.y*ray.d.y; - const Float B = 2 * (ray.d.x*ray.o.x + ray.d.y*ray.o.y); - const Float C = ray.o.x*ray.o.x + ray.o.y*ray.o.y - m_radius*m_radius; + const double A = dx*dx + dy*dy; + const double B = 2 * (dx*ox + dy*oy); + const double C = ox*ox + oy*oy - m_radius*m_radius; - if (!solveQuadratic(A, B, C, nearT, farT)) + if (!solveQuadraticDouble(A, B, C, nearT, farT)) return false; if (nearT > end || farT < start) return false; - const Float zPosNear = ray.o.z + ray.d.z * nearT; - const Float zPosFar = ray.o.z + ray.d.z * farT; + const double zPosNear = ray.o.z + ray.d.z * nearT; + const double zPosFar = ray.o.z + ray.d.z * farT; if (zPosNear >= 0 && zPosNear <= m_length && nearT >= start) { - t = nearT; + t = (Float) nearT; } else if (zPosFar >= 0 && zPosFar <= m_length) { if (farT > end) return false; - t = farT; + t = (Float) farT; } else { return false; } @@ -124,20 +130,6 @@ public: its.hasUVPartials = false; its.shape = this; - /* Intersection refinement step */ - Vector2 localDir(normalize(Vector2(local.x, local.y))); - Vector rel = its.p - m_objectToWorld(Point(m_radius * localDir.x, - m_radius * localDir.y, local.z)); - Float correction = -dot(rel, its.geoFrame.n)/dot(ray.d, its.geoFrame.n); - - its.t += correction; - if (its.t < ray.mint || its.t > ray.maxt) { - its.t = std::numeric_limits::infinity(); - return false; - } - - its.p += ray.d * correction; - return true; } diff --git a/src/shapes/sphere.cpp b/src/shapes/sphere.cpp index a06c0ff5..636abad9 100644 --- a/src/shapes/sphere.cpp +++ b/src/shapes/sphere.cpp @@ -38,14 +38,16 @@ public: bool rayIntersect(const Ray &ray, Float start, Float end, Float &t) const { /* Transform into the local coordinate system and normalize */ - Float nearT, farT; - const Float ox = ray.o.x - m_center.x, oy = ray.o.y - m_center.y, - oz = ray.o.z - m_center.z; - const Float A = ray.d.x*ray.d.x + ray.d.y*ray.d.y + ray.d.z*ray.d.z; - const Float B = 2 * (ray.d.x*ox + ray.d.y*oy + ray.d.z*oz); - const Float C = ox*ox + oy*oy + oz*oz - m_radius * m_radius; + double nearT, farT; + const double ox = (double) ray.o.x - (double) m_center.x, + oy = (double) ray.o.y - (double) m_center.y, + oz = (double) ray.o.z - (double) m_center.z; + const double dx = ray.d.x, dy = ray.d.y, dz = ray.d.z; + const double A = dx*dx + dy*dy + dz*dz; + const double B = 2 * (dx*ox + dy*oy + dz*oz); + const double C = ox*ox + oy*oy + oz*oz - m_radius * m_radius; - if (!solveQuadratic(A, B, C, nearT, farT)) + if (!solveQuadraticDouble(A, B, C, nearT, farT)) return false; if (nearT > end || farT < start) @@ -53,9 +55,9 @@ public: if (nearT < start) { if (farT > end) return false; - t = farT; + t = (Float) farT; } else { - t = nearT; + t = (Float) nearT; } return true; } @@ -99,19 +101,6 @@ public: coordinateSystem(its.geoFrame.n, its.geoFrame.s, its.geoFrame.t); } - /* Intersection refinement step */ - Vector rel = its.p - (m_center + its.geoFrame.n * m_radius); - Float correction = -dot(rel, its.geoFrame.n)/dot(ray.d, its.geoFrame.n); - - /* Move outside of the object */ - its.t += correction; - - if (its.t < ray.mint || its.t > ray.maxt) { - its.t = std::numeric_limits::infinity(); - return false; - } - - its.p += ray.d * correction; its.shFrame = its.geoFrame; its.wi = its.toLocal(-ray.d); its.hasUVPartials = false; diff --git a/src/tests/test_samplers.cpp b/src/tests/test_samplers.cpp new file mode 100644 index 00000000..65489a3d --- /dev/null +++ b/src/tests/test_samplers.cpp @@ -0,0 +1,72 @@ +#include +#include + +MTS_NAMESPACE_BEGIN + +class TestSamplers : public TestCase { +public: + MTS_BEGIN_TESTCASE() + MTS_DECLARE_TEST(test01_Halton) + MTS_DECLARE_TEST(test02_Hammersley) + MTS_DECLARE_TEST(test03_radicalInverseIncr) + MTS_END_TESTCASE() + + void test01_Halton() { + ref sampler = static_cast (PluginManager::getInstance()-> + createObject(Sampler::m_theClass, Properties("halton"))); + + /* MATLAB: p = haltonset(5); net(p,5) */ + Float comparison[] = { + 0, 0, 0, 0, 0, + 0.500000000000000, 0.333333333333333, 0.200000000000000, 0.142857142857143, 0.090909090909091, + 0.250000000000000, 0.666666666666667, 0.400000000000000, 0.285714285714286, 0.181818181818182, + 0.750000000000000, 0.111111111111111, 0.600000000000000, 0.428571428571429, 0.272727272727273, + 0.125000000000000, 0.444444444444444, 0.800000000000000, 0.571428571428571, 0.363636363636364 + }; + + int pos = 0; + sampler->generate(); + for (int i=0; i<5; ++i) { + for (int j=0; j<5; ++j) + Assert(std::abs(sampler->next1D() - comparison[pos++]) < 1e-7); + sampler->advance(); + } + } + + void test02_Hammersley() { + Properties props("hammersley"); + props.setInteger("sampleCount", 5); + + ref sampler = static_cast (PluginManager::getInstance()-> + createObject(Sampler::m_theClass, props)); + + Float comparison[] = { + 0.0, 0, 0, 0, 0, 0, + 1.0/5.0, 0.500000000000000, 0.333333333333333, 0.200000000000000, 0.142857142857143, 0.090909090909091, + 2.0/5.0, 0.250000000000000, 0.666666666666667, 0.400000000000000, 0.285714285714286, 0.181818181818182, + 3.0/5.0, 0.750000000000000, 0.111111111111111, 0.600000000000000, 0.428571428571429, 0.272727272727273, + 4.0/5.0, 0.125000000000000, 0.444444444444444, 0.800000000000000, 0.571428571428571, 0.363636363636364 + }; + + int pos = 0; + sampler->generate(); + for (int i=0; i<5; ++i) { + for (int j=0; j<6; ++j) + Assert(std::abs(sampler->next1D() - comparison[pos++]) < 1e-7); + sampler->advance(); + } + } + + void test03_radicalInverseIncr() { + Float x = 0.0f; + + for (int i=0; i<20; ++i) { + Assert(x == radicalInverse(2, i)); + x = radicalInverseIncremental(2, x); + } + } +}; + +MTS_EXPORT_TESTCASE(TestSamplers, "Testcase for Sampler implementations") + +MTS_NAMESPACE_END diff --git a/src/tests/test_sh.cpp b/src/tests/test_sh.cpp new file mode 100644 index 00000000..aed347a1 --- /dev/null +++ b/src/tests/test_sh.cpp @@ -0,0 +1,84 @@ +#include +#include + +MTS_NAMESPACE_BEGIN + +class TestSphericalHarmonics : public TestCase { +public: + MTS_BEGIN_TESTCASE() + MTS_DECLARE_TEST(test01_shRotation) + MTS_DECLARE_TEST(test02_shSampler) + MTS_END_TESTCASE() + + void test01_shRotation() { + /* Generate a random SH expansion, rotate it and + spot-check 100 times against the original */ + + ref random = new Random(); + int bands = 8; + + SHVector vec1(bands); + for (int l=0; lnextFloat(); + + Vector axis(squareToSphere(Point2(random->nextFloat(), random->nextFloat()))); + Transform trafo = Transform::rotate(axis, random->nextFloat()*360); + Transform inv = trafo.inverse(); + SHRotation rot(vec1.getBands()); + + SHVector::rotation(trafo, rot); + SHVector vec2(bands); + + rot(vec1, vec2); + + for (int i=0; i<100; ++i) { + Vector dir1(squareToSphere(Point2(random->nextFloat(), random->nextFloat()))), dir2; + trafo(dir1, dir2); + + Float value1 = vec1.eval(dir2); + Float value2 = vec2.eval(dir1); + Assert(std::abs(value1-value2) < Epsilon); + } + } + + struct ClampedCos { + Vector axis; + ClampedCos(Vector axis) : axis(axis) { } + Float operator()(const Vector &w) const { return std::max((Float) 0, dot(w, axis)); } + }; + + void test02_shSampler() { + /* Draw 100 samples from a SH expansion of a clamped cosine-shaped + distribution and verify the returned probabilities */ + int bands = 13, numSamples = 100, depth = 12; + + Vector v = normalize(Vector(1, 2, 3)); + ref random = new Random(); + SHVector clampedCos = SHVector(bands); + clampedCos.project(ClampedCos(v), numSamples); + //Float clampedCosError = clampedCos.l2Error(ClampedCos(v), numSamples); + clampedCos.normalize(); + + //cout << "Projection error = " << clampedCosError << endl; + //cout << "Precomputing mip-maps" << endl; + ref sampler = new SHSampler(bands, depth); + //cout << "Done: "<< sampler->toString() << endl; + Float accum = 0; + int nsamples = 100, nInAvg = 0; + for (int i=0; i<=nsamples; ++i) { + Point2 sample(random->nextFloat(), random->nextFloat()); + Float pdf1 = sampler->warp(clampedCos, sample); + Float pdf2 = dot(v, sphericalDirection(sample.x, sample.y))/M_PI; + Float relerr = std::abs(pdf1-pdf2)/pdf2; + if (pdf2 > 0.01) { + accum += relerr; ++nInAvg; + Assert(relerr < 0.08); + } + } + Assert(accum / nInAvg < 0.01); + } +}; + +MTS_EXPORT_TESTCASE(TestSphericalHarmonics, "Testcase for Spherical Harmonics code") +MTS_NAMESPACE_END diff --git a/src/utils/addimages.cpp b/src/utils/addimages.cpp index 65ba6f56..675d77a5 100644 --- a/src/utils/addimages.cpp +++ b/src/utils/addimages.cpp @@ -5,8 +5,6 @@ MTS_NAMESPACE_BEGIN class AddImages : public Utility { public: - AddImages(UtilityServices *us) : Utility(us) { } - int run(int argc, char **argv) { if (argc != 6) { cout << "Add the weighted pixel values of two EXR images to produce a new one" << endl; @@ -53,9 +51,8 @@ public: return 0; } - MTS_DECLARE_CLASS() + MTS_DECLARE_UTILITY() }; -MTS_IMPLEMENT_CLASS(AddImages, false, Utility) MTS_EXPORT_UTILITY(AddImages, "Generate linear combinations of EXR images") MTS_NAMESPACE_END diff --git a/src/utils/dumpimage.cpp b/src/utils/dumpimage.cpp deleted file mode 100644 index 0701274b..00000000 --- a/src/utils/dumpimage.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include -#include -#include - -using namespace mitsuba; - -Bitmap *downsample(const Bitmap *in) { - Bitmap *result = new Bitmap(in->getWidth()/2, in->getHeight()/2, 128); - const float *data = in->getFloatData(); - float *out = result->getFloatData(); - result->clear(); - for (int y=0; ygetWidth()/2; ++y) { - for (int x=0; xgetWidth()/2; ++x) { - Float value1 = data[(2*x + 2*y * in->getWidth()) * 4]; - Float value2 = data[(2*x + (2*y+1) * in->getWidth()) * 4]; - Float value3 = data[(2*x+1 + 2*y * in->getWidth()) * 4]; - Float value4 = data[(2*x+1 + (2*y+1) * in->getWidth()) * 4]; - Float avg = (value1+value2+value3+value4)/4; - out[(x + y * result->getWidth()) * 4 + 0] = avg; - out[(x + y * result->getWidth()) * 4 + 1] = avg; - out[(x + y * result->getWidth()) * 4 + 2] = avg; - out[(x + y * result->getWidth()) * 4 + 3] = 1; - } - } - return result; -} - -void dumpImage(const std::string &s1) { - ref stream = new FileStream(s1, FileStream::EReadOnly); - ref bitmap = new Bitmap(Bitmap::EEXR, stream); -// bitmap = downsample(bitmap); -// bitmap = downsample(bitmap); - stream = new FileStream("downsampled.exr", FileStream::ETruncReadWrite); - bitmap->save(Bitmap::EEXR, stream); - - float *data = bitmap->getFloatData(); - - cout << "A={" << endl; - cout << std::fixed << endl; - cout << std::setprecision(12)<< endl; - for (int y=0; ygetWidth(); ++y) { - cout << "\t{"; - for (int x=0; xgetWidth(); ++x) { - cout << data[(x + y * bitmap->getWidth()) * 4]; - if (x+1 < bitmap->getWidth()) - cout << ", "; - - } - cout << "}"; - if (y+1 < bitmap->getHeight()) - cout << ","; - cout << endl; - } - cout << "};"; -} - -int main(int argc, char **argv) { - Class::staticInitialization(); - Thread::staticInitialization(); - Logger::staticInitialization(); - Spectrum::staticInitialization(); - try { - if (argc < 2) { - cout << "dumpimage " << endl; - } else { - dumpImage(argv[1]); - } - } catch (const std::exception &e) { - std::cerr << "Caught a critical exeption: " << e.what() << std::endl; - exit(-1); - } catch (...) { - std::cerr << "Caught a critical exeption of unknown type! " << std::endl; - exit(-1); - } - Spectrum::staticShutdown(); - Logger::staticShutdown(); - Thread::staticShutdown(); - Class::staticShutdown(); - return 0; -} diff --git a/src/utils/ssalbedo.cpp b/src/utils/ssalbedo.cpp deleted file mode 100644 index 310aa4df..00000000 --- a/src/utils/ssalbedo.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include - -using namespace mitsuba; - -Float solveSSAlbedo(Float diffAlbedo) { - if (diffAlbedo == 1 || diffAlbedo == 0) - return diffAlbedo; - - if (diffAlbedo < 0 || diffAlbedo > 1) { - cout << "Overflow: "<< diffAlbedo << "!" << endl; - diffAlbedo = std::max((Float) 0, std::min((Float) 1, diffAlbedo)); - } - - Float l = 0, r = 1; - while (true) { - Float m = (l+r)/2, - fm = m/2*(1+std::exp(-4.0/3.0*std::sqrt(3*(1-m))))*std::exp(-std::sqrt(3*(1-m))); - if (fm < diffAlbedo) - l = m; - else - r = m; - if (std::abs(fm-diffAlbedo) < 1e-3) - return m; - } -} - -void computeSSAlbedo(const std::string &filename, const std::string target) { - ref stream = new FileStream(filename, FileStream::EReadOnly); - stream->setByteOrder(Stream::ELittleEndian); - - int xres = stream->readInt(), yres=stream->readInt(), zres=stream->readInt(); - Vector3i res = Vector3i(xres, yres, zres); - int channels = stream->readInt(); - - size_t nEntries = res.x*res.y*res.z*channels; - Float xmin = stream->readSingle(), ymin = stream->readSingle(), zmin = stream->readSingle(); - Float xmax = stream->readSingle(), ymax = stream->readSingle(), zmax = stream->readSingle(); - AABB aabb(Point(xmin, ymin, zmin), Point(xmax, ymax, zmax)); - - SLog(EInfo, "Loading \"%s\": %ix%ix%i (%i channels), %i KiB, %s", filename.c_str(), - res.x, res.y, res.z, channels, nEntries*sizeof(float)/1024, - aabb.toString().c_str()); - float *data = new float[nEntries]; - stream->read(data, nEntries*sizeof(float)); - stream->close(); - - SLog(EInfo, "Computing single scattering albedo .."); - for (size_t i=0; i targetStream = new FileStream(target, FileStream::ETruncReadWrite); - targetStream->setByteOrder(Stream::ELittleEndian); - res.serialize(targetStream); - targetStream->writeInt(channels); - targetStream->writeSingle(xmin); targetStream->writeSingle(ymin); targetStream->writeSingle(zmin); - targetStream->writeSingle(xmax); targetStream->writeSingle(ymax); targetStream->writeSingle(zmax); - targetStream->write(data, nEntries*sizeof(float)); - targetStream->close(); -} - -int main(int argc, char **argv) { - Class::staticInitialization(); - Thread::staticInitialization(); - Logger::staticInitialization(); - Spectrum::staticInitialization(); - - try { - if (argc != 3) { - cout << "Converts a volume of diffuse color values to " << endl; - cout << "a single scattering albedo volume by numerically" << endl; - cout << "inverting (2.4) in the Jensen et al. BSSRDF paper" << endl; - cout << "Syntax: ssalbedo " << endl; - } else { - computeSSAlbedo(argv[1], argv[2]); - } - } catch (const std::exception &e) { - std::cerr << "Caught a critical exeption: " << e.what() << std::endl; - exit(-1); - } catch (...) { - std::cerr << "Caught a critical exeption of unknown type! " << std::endl; - exit(-1); - } - - Spectrum::staticShutdown(); - Logger::staticShutdown(); - Thread::staticShutdown(); - Class::staticShutdown(); - return 0; -} diff --git a/src/utils/utils_test.cpp b/src/utils/utils_test.cpp deleted file mode 100644 index 993de520..00000000 --- a/src/utils/utils_test.cpp +++ /dev/null @@ -1,611 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "../medium/maxexp.h" -#include - -using namespace mitsuba; - -void testHalton() { - ref sampler = static_cast (PluginManager::getInstance()-> - createObject(Sampler::m_theClass, Properties("halton"))); - - /* MATLAB: p = haltonset(5); net(p,5) */ - Float comparison[] = { - 0, 0, 0, 0, 0, - 0.500000000000000, 0.333333333333333, 0.200000000000000, 0.142857142857143, 0.090909090909091, - 0.250000000000000, 0.666666666666667, 0.400000000000000, 0.285714285714286, 0.181818181818182, - 0.750000000000000, 0.111111111111111, 0.600000000000000, 0.428571428571429, 0.272727272727273, - 0.125000000000000, 0.444444444444444, 0.800000000000000, 0.571428571428571, 0.363636363636364 - }; - - int pos = 0; - sampler->generate(); - for (int i=0; i<5; ++i) { - for (int j=0; j<5; ++j) - SAssert(std::abs(sampler->next1D() - comparison[pos++]) < 1e-7); - sampler->advance(); - } -} - -void testHammersley() { - Properties props("hammersley"); - props.setInteger("sampleCount", 5); - - ref sampler = static_cast (PluginManager::getInstance()-> - createObject(Sampler::m_theClass, props)); - - Float comparison[] = { - 0.0, 0, 0, 0, 0, 0, - 1.0/5.0, 0.500000000000000, 0.333333333333333, 0.200000000000000, 0.142857142857143, 0.090909090909091, - 2.0/5.0, 0.250000000000000, 0.666666666666667, 0.400000000000000, 0.285714285714286, 0.181818181818182, - 3.0/5.0, 0.750000000000000, 0.111111111111111, 0.600000000000000, 0.428571428571429, 0.272727272727273, - 4.0/5.0, 0.125000000000000, 0.444444444444444, 0.800000000000000, 0.571428571428571, 0.363636363636364 - }; - - int pos = 0; - sampler->generate(); - for (int i=0; i<5; ++i) { - for (int j=0; j<6; ++j) - SAssert(std::abs(sampler->next1D() - comparison[pos++]) < 1e-7); - sampler->advance(); - } -} - -void testRadicalInverseIncr() { - Float x = 0.0f; - - for (int i=0; i<20; ++i) { - SAssert(x == radicalInverse(2, i)); - x = radicalInverseIncremental(2, x); - } -} - -void testSpotLuminaire() { - Properties props("spot"); - props.setFloat("beamWidth", 20); - props.setFloat("cutoffAngle", 25); - ref spot = static_cast (PluginManager::getInstance()-> - createObject(Luminaire::m_theClass, props)); - ref random = new Random(); - - Spectrum power; - EmissionRecord eRec; - const int nSamples = 1000000; - for (int i=0; inextFloat(), random->nextFloat()); - Point2 dirSample(random->nextFloat(), random->nextFloat()); - spot->sampleEmission(eRec, areaSample, dirSample); - power += eRec.P / (eRec.pdfArea*eRec.pdfDir); - } - power /= (Float) nSamples; - cout << "Estimated power: " << power.toString() << endl; - cout << "Actual power: " << spot->getPower().toString() << endl; -} - -void testHG1() { - Properties props("hg"); - props.setFloat("g", .8); - - ref hg = static_cast (PluginManager::getInstance()-> - createObject(PhaseFunction::m_theClass, props)); - ref random = new Random(); - - Float sum = 0; - Vector dir1(0, 0, 1); - const int nSamples = 100000; - MediumSamplingRecord mRec; - for (int i=0; inextFloat(), random->nextFloat()))); - sum += hg->f(mRec, dir2, dir2)[0]; - } - sum *= (4 * M_PI) / nSamples; - - cout << sum << endl; -} - -void testHG2() { - const int res = 8; - Float buf[res][res]; - Properties props("hg"); - props.setFloat("g", -.2); - MediumSamplingRecord mRec; - - ref hg = static_cast (PluginManager::getInstance()-> - createObject(PhaseFunction::m_theClass, props)); - ref random = new Random(); - - const Vector dir1(0, 0, 1); - memset(buf, 0, sizeof(Float)*res*res); - Vector dir2; - PhaseFunction::ESampledType sampledType; - - const int nSamples = 10000000; - for (int i=0; inextFloat(), random->nextFloat()); - hg->sample(mRec, dir1, dir2, sampledType, sample); - Float pdf = hg->f(mRec, dir1, dir2)[0]; - Float dir2Phi = (std::atan2(dir2.y, dir2.x) + (Float) M_PI) / (2 * (Float) M_PI); - Float dir2CosTheta = (dir2.z + 1) / (Float) 2; - - int pos1 = std::max(0, std::min((int) (dir2Phi * res), res-1)); - int pos2 = std::max(0, std::min((int) (dir2CosTheta* res), res-1)); - buf[pos1][pos2] += 1/pdf; - - } - cout << "A=["; - for (int y=0; y= 2); - Float cdf[4], intervalStart[3]; - cdf[0] = 0; - - /* Requires the coefficients to be sorted in descending order */ - for (int i=0; i= 0 && index < n); - - /* Sample according to f_i */ - Float t = -std::log(std::exp(-intervalStart[index] * sigma[index]) - - normFactor * (u - cdf[index])) / sigma[index]; - - /* Compute the probability of this sample */ - prob = sigma[index] * std::exp(-sigma[index] * t) / normFactor; - - /* CDF computation - Float *lowerBound = std::lower_bound(&intervalStart[0], &intervalStart[n], t); - int index = std::max(0, (int) (lowerBound - &intervalStart[0]) - 1); - Float lower = (index==0) ? -1 : -std::pow((sigma[index]/sigma[index-1]), - -sigma[index] / (sigma[index]-sigma[index-1])); - Float upper = -std::exp(-sigma[index] * t); - Float integral = cdf[index] + (upper - lower) / normFactor; - */ - - return t; -} - -void testVariance() { - ref random = new Random(); - Spectrum mean, meanSqr, variance; - Spectrum sigmaT; - sigmaT[0] = 0.7014; - sigmaT[1] = 1.2225; - sigmaT[2] = 1.9142; - int nSamples = 100000; - - for (int chan=0; chan<3; ++chan) { - cout << "Sampling with respect to channel " << chan << endl; - mean = Spectrum(0.0f); meanSqr = Spectrum(0.0f); - for (int i=0; inextFloat(); - - Float t = -std::log(desiredAttenuation)/sigmaT[chan]; - Float prob = sigmaT[chan] * std::exp(-sigmaT[chan] * t); - Spectrum value = (sigmaT * (-t)).exp() / prob; - - Spectrum delta = value - mean; - mean += delta / (Float) (i+1); - meanSqr += delta * (value - mean); - variance = meanSqr / (Float) i; - } - cout << "Expectation : " << (Spectrum(1)/sigmaT).toString() << endl; - cout << "Mean : " << mean.toString() << endl; - cout << "Sample variance : " << variance.toString() << endl << endl; - } - - cout << "Random sampling test" << endl; - mean = Spectrum(0.0f); meanSqr = Spectrum(0.0f); - for (int i=0; inextFloat(); - int chan = random->nextInteger(3); - - Float t = -std::log(desiredAttenuation)/sigmaT[chan]; - Spectrum prob = sigmaT * (-sigmaT * t).exp(); - Spectrum value = (sigmaT * (-t)).exp() / (prob[chan]); - - Spectrum delta = value - mean; - mean += delta / (Float) (i+1); - meanSqr += delta * (value - mean); - variance = meanSqr / (Float) i; - } - cout << "Expectation : " << (Spectrum(1)/sigmaT).toString() << endl; - cout << "Mean : " << mean.toString() << endl; - cout << "Sample variance : " << variance.toString() << endl << endl; - - cout << "Single sample test" << endl; - mean = Spectrum(0.0f); meanSqr = Spectrum(0.0f); - for (int i=0; inextFloat(); - int chan = random->nextInteger(3); - - Float t = -std::log(desiredAttenuation)/sigmaT[chan]; - Spectrum prob = sigmaT * (-sigmaT * t).exp(); - Float weight = prob[chan] / (prob[0] + prob[1] + prob[2]); - Spectrum value = (sigmaT * (-t)).exp() / (prob[chan] * 1/(Float) 3) * weight; - - Spectrum delta = value - mean; - mean += delta / (Float) (i+1); - meanSqr += delta * (value - mean); - variance = meanSqr / (Float) i; - } - cout << "Expectation : " << (Spectrum(1)/sigmaT).toString() << endl; - cout << "Mean : " << mean.toString() << endl; - cout << "Sample variance : " << variance.toString() << endl << endl; - - - cout << "New distribution test" << endl; - mean = Spectrum(0.0f); meanSqr = Spectrum(0.0f); - Float extinction[] = {1.9142, 1.2225, 0.7014}; - for (int i=0; inextFloat(), prob); - - Spectrum value = (sigmaT * (-t)).exp() / prob; - - Spectrum delta = value - mean; - mean += delta / (Float) (i+1); - meanSqr += delta * (value - mean); - variance = meanSqr / (Float) i; - } - - cout << "Expectation : " << (Spectrum(1)/sigmaT).toString() << endl; - cout << "Mean : " << mean.toString() << endl; - cout << "Sample variance : " << variance.toString() << endl << endl; -} - -void testPhotonMap() { - int nPhotons = 3000000; - ref map = new PhotonMap(nPhotons); - Spectrum power; - ref random = new Random(); - power.fromLinearRGB(1, 2, 3); - power *= M_PI; - - bool storePhoton(const Point &pos, const Vector &dir, const Spectrum &power); - for (int i=0; inextFloat(), random->nextFloat())); - map->storePhoton(Point(disk.x,disk.y,0), Normal(0,0,1), Vector(0, 0, -1), power, 1); - } - - map->setScale(1/(Float) nPhotons); - map->balance(); - - for (int i=1; i<10; ++i) { - Point2 disk = squareToDisk(Point2(random->nextFloat(), random->nextFloat())) * .2; - - cout << map->estimateIrradiance(Point(disk.x, disk.y, 0), Normal(0, 0, 1), .3, 10000).toString() << endl; - cout << map->estimateIrradianceFiltered(Point(disk.x, disk.y, 0), Normal(0, 0, 1), .3, 10000).toString() << endl; - } -} - -void testMaxExp() { - std::vector sigmaT; - sigmaT.push_back(0.7014); - sigmaT.push_back(1.2225); - sigmaT.push_back(1.9142); - - MaxExpDist dist(sigmaT); - - for (int i=0; i<9; ++i) { - Float U=.01f + i/10.0f, t, pdf, cdf; - t = dist.sample(U, pdf); - cdf = dist.cdf(t); - - cout << "Sampled U=" << U << " => t = " << t << ", pdf=" << pdf << ", cdf=" << cdf << endl; - } -} - -void testHeterogeneous() { - ref sampler = static_cast (PluginManager::getInstance()-> - createObject(Sampler::m_theClass, Properties("independent"))); - - Properties props("heterogeneous"); - props.setString("filename", "scenes/cornell/smoke-density.65.vol"); - props.setSpectrum("sigmaS", Spectrum(2.62)); - props.setSpectrum("sigmaA", Spectrum(.05f)); - props.setString("strategy", "standard"); - props.setFloat("sizeMultiplier", 10); - ref standardMedium = static_cast (PluginManager::getInstance()-> - createObject(Medium::m_theClass, props)); - standardMedium->configure(); - - props = Properties("heterogeneous"); - props.setString("filename", "scenes/cornell/smoke-density.65.vol"); - props.setString("strategy", "coleman"); - props.setSpectrum("sigmaS", Spectrum(2.62)); - props.setSpectrum("sigmaA", Spectrum(.05f)); - props.setFloat("sizeMultiplier", 10); - ref colemanMedium = static_cast (PluginManager::getInstance()-> - createObject(Medium::m_theClass, props)); - colemanMedium->configure(); - - Ray ray(Point(0, 1, .4), Vector(1, 0, 0)); - - MediumSamplingRecord mRec; - - std::ofstream distr("distr.m"); - int res = 300000, failures = 0; - - distr << "samplesStandard=[" << endl; - for (int i=0; isampleDistance(ray, std::numeric_limits::infinity(), mRec, sampler)) { -// distr << mRec.t << " "; - distr << mRec.sigmaS[0] * mRec.attenuation[0] / mRec.pdf << " " << endl; - } else { - ++failures; - } - } - distr << "];" << endl; - cout << failures/(Float)res << endl; - failures = 0; - cout << failures/(Float)res << endl; - distr << "samplesColeman=[" << endl; - for (int i=0; isampleDistance(ray, std::numeric_limits::infinity(), mRec, sampler)) { -// distr << mRec.t << " "; - distr << mRec.sigmaS[0] * mRec.attenuation[0] / mRec.pdf << " " << endl; - } else { - ++failures; - } - } - distr << "];" << endl; - distr << "hist(samplesStandard, 300);" << endl; - distr << "title('Standard');" << endl; - distr << "figure;" << endl; - distr << "hist(samplesColeman, 300);" << endl; - distr.close(); - cout << failures/(Float)res << endl; -} - -void testWavelet() { - ref stream = new FileStream("cat.png", FileStream::EReadOnly); - ref bitmap = new Bitmap(Bitmap::EPNG, stream); - - ref wavelet = new Wavelet2D(bitmap); - cout << "2D compression ratio: " << wavelet->compress(.015) << endl; - ref sw = wavelet->toSparseWavelet(); - ref stream3 = new FileStream("cat2.raw", FileStream::ETruncReadWrite); - sw->serialize(stream3, NULL); - stream3->close(); - ref stream4 = new FileStream("cat2.raw", FileStream::EReadOnly); - ref sw2 = new SparseWavelet2D(stream4, NULL); - ref wavelet2 = new Wavelet2D(sw2); - ref bitmap2 = new Bitmap(bitmap->getWidth(), bitmap->getHeight(), 8); - - wavelet2->decode(bitmap2); - - size_t nEntries = 512*512; - Float mean = 0, sqrError = 0; - for (size_t i=0; igetData()[i] / (255.0f * nEntries); - sqrError += std::pow(bitmap->getData()[i]/(255.0f)-bitmap2->getData()[i]/(255.0f), 2)/nEntries; - } - - cout << "Mean: " << mean << ", error:" << std::sqrt(sqrError)/mean<< endl; - - ref stream2 = new FileStream("cat2.png", FileStream::ETruncReadWrite); - bitmap2->save(Bitmap::EPNG, stream2); -} - -void testLineIntegral() { - ref stream = new FileStream("cat.png", FileStream::EReadOnly); - ref bitmap = new Bitmap(Bitmap::EPNG, stream); - - Point2 start(0.121, 0.566); - Point2 end(0.815, 0.318); - - Vector2 dir = Vector2(end-start); - - for (int i=3; i<18; ++i) { - size_t nsteps = (int) std::ldexp((Float) 1, i); - uint8_t *data = bitmap->getData(); - double accum = 0; - for (size_t i=0; i stream = new FileStream("cat.png", FileStream::EReadOnly); - ref bitmap = new Bitmap(Bitmap::EPNG, stream); - ref wavelet = new Wavelet2D(bitmap); - ref sparse = wavelet->toSparseWavelet(); - - Point2 start(0.121, 0.566); - Point2 end(0.815, 0.318); - start*=512; end *= 512; - - cout << sparse->lineIntegral(start, end) << endl; -} - -void testSHRotation() { - ref random = new Random(); - int bands = 8; - - SHVector vec1(bands); - for (int l=0; lnextFloat(); - - Vector axis(squareToSphere(Point2(random->nextFloat(), random->nextFloat()))); - Transform trafo = Transform::rotate(axis, random->nextFloat()*360); - Transform inv = trafo.inverse(); - SHRotation rot(vec1.getBands()); - - SHVector::rotation(trafo, rot); - SHVector vec2(bands); - - rot(vec1, vec2); - - for (int i=0; i<100; ++i) { - Vector dir1(squareToSphere(Point2(random->nextFloat(), random->nextFloat()))), dir2; - trafo(dir1, dir2); - - Float value1 = vec1.eval(dir2); - Float value2 = vec2.eval(dir1); - SAssert(std::abs(value1-value2) < Epsilon); - } - cout << "Passed." << endl; -} - -struct ClampedCos { - Vector axis; - ClampedCos(Vector axis) : axis(axis) { } - Float operator()(const Vector &w) const { return std::max((Float) 0, dot(w, axis)); } -}; - -void testSHSampler() { - int bands = 25, numSamples = 100, depth = 12; - - Vector v = normalize(Vector(1, 2, 3)); - ref random = new Random(); - SHVector clampedCos = SHVector(bands); - clampedCos.project(ClampedCos(v), numSamples); - Float clampedCosError = clampedCos.l2Error(ClampedCos(v), numSamples); - clampedCos.normalize(); - - cout << "Projection error = " << clampedCosError << endl; - cout << "Precomputing mip-maps" << endl; - ref sampler = new SHSampler(bands, depth); - cout << "Done: "<< sampler->toString() << endl; - Float accum = 0; - int nsamples = 100; - for (int i=0; i<=nsamples; ++i) { - Point2 sample(random->nextFloat(), random->nextFloat()); - Float pdf1 = sampler->warp(clampedCos, sample); - Float pdf2 = dot(v, sphericalDirection(sample.x, sample.y))/M_PI; - Float relerr = std::abs(pdf1-pdf2)/pdf2; - accum += relerr; - SAssert(relerr < 0.04); - } - SAssert(accum / nsamples < 1); -} - -struct GridFunctor { - Float operator()(Float value, Float length) const { - cout << "functor(value=" << value << ", length=" << length << ")" << endl; - return 0; - } -}; - -void testGrid() { - Grid grid(Vector3i(3, 3, 1), AABB(Point(10, 0, 0), Point(11,1,1))); - Ray ray(Point(10 + 1.0f/6.0f, .5, .5), Vector(1, 0, 0), 0, 2.0f/3.0f); - - grid(0, 1, 0) = 1; - grid(1, 1, 0) = 2; - grid(2, 1, 0) = 3; - - SAssert(std::abs(grid.lookup(Point(10 + 1.0/3.0f, .5, .5))-1.5) < 1e-6); - - GridFunctor functor; - grid.rasterize(ray, functor); - - cout << "Expected: functor(value=1, length=" << 1.0f/6.0f << ")" << endl; - cout << "Expected: functor(value=2, length=" << 1.0f/3.0f << ")" << endl; - cout << "Expected: functor(value=3, length=" << 1.0f/6.0f << ")" << endl; - - SAssert(grid(0,1,0) == 0); - SAssert(grid(1,1,0) == 0); - SAssert(grid(2,1,0) == 0); -} - -int main(int argc, char **argv) { - Class::staticInitialization(); - Thread::staticInitialization(); - Logger::staticInitialization(); - Spectrum::staticInitialization(); - SHVector::staticInitialization(); - try { - /* - testHalton(); - testHammersley(); - testRadicalInverseIncr(); - testSpotLuminaire(); - testHG1(); - testHG2(); - testVariance(); - testPhotonMap(); - testMaxExp(); - testHeterogeneous(); - testLineIntegral(); - testLineIntegralWavelet(); - testWaveletBasic(); - testWavelet(); - testWavelet3D(); - testGrid(); - testSHRotation(); - testSHSampler(); - */ - } catch (const std::exception &e) { - std::cerr << "Caught a critical exeption: " << e.what() << std::endl; - exit(-1); - } catch (...) { - std::cerr << "Caught a critical exeption of unknown type! " << std::endl; - exit(-1); - } - SHVector::staticShutdown(); - Spectrum::staticShutdown(); - Logger::staticShutdown(); - Thread::staticShutdown(); - Class::staticShutdown(); - return 0; -} diff --git a/src/volume/gridvolume.cpp b/src/volume/gridvolume.cpp index 1e7f988c..a56a7281 100644 --- a/src/volume/gridvolume.cpp +++ b/src/volume/gridvolume.cpp @@ -124,6 +124,18 @@ public: m_filename = filename; m_fromStream = false; + char header[3]; + stream->read(header, 3); + if (header[0] != 'V' || header[1] != 'O' || header[2] != 'L') + Log(EError, "Encountered an invalid volume data file (incorrect header identifier)"); + uint8_t version; + stream->read(&version, 1); + if (version != 3) + Log(EError, "Encountered an invalid volume data file (incorrect file version)"); + int type = stream->readInt(); + if (type != 1) + Log(EError, "Encountered an invalid volume data file (incorrect data type)"); + int xres = stream->readInt(), yres=stream->readInt(), zres=stream->readInt(); m_res = Vector3i(xres, yres, zres); m_channels = stream->readInt(); @@ -142,11 +154,11 @@ public: int fd = open(resolved.c_str(), O_RDONLY); if (fd == -1) Log(EError, "Could not open \"%s\"!", m_filename.c_str()); - m_mmapSize = (nEntries+10)*sizeof(float); + m_mmapSize = (nEntries+12)*sizeof(float); m_mmapPtr = mmap(NULL, m_mmapSize, PROT_READ, MAP_SHARED, fd, 0); if (m_mmapPtr == NULL) Log(EError, "Could not map \"%s\" to memory!", m_filename.c_str()); - m_data = ((float *) m_mmapPtr) + 10; + m_data = ((float *) m_mmapPtr) + 12; if (close(fd) != 0) Log(EError, "close(): unable to close file!"); #elif defined(WIN32) diff --git a/tools/darwin/PreviewSettings.nib/designable.nib b/tools/darwin/PreviewSettings.nib/designable.nib index 08e7b3e8..97dd5ae0 100644 --- a/tools/darwin/PreviewSettings.nib/designable.nib +++ b/tools/darwin/PreviewSettings.nib/designable.nib @@ -3,7 +3,7 @@ 1060 10F569 - 762 + 788 1038.29 461.00 @@ -15,7 +15,7 @@ YES - 762 + 788 1.2.5 @@ -51,7 +51,7 @@ 8211 2 - {{157, 148}, {303, 313}} + {{157, 123}, {303, 338}} -461896704 Preview settings NSPanel @@ -65,7 +65,7 @@ 268 - {{17, 291}, {124, 14}} + {{17, 316}, {124, 14}} 2 YES @@ -103,7 +103,7 @@ 268 - {{40, 267}, {52, 14}} + {{40, 292}, {52, 14}} 2 YES @@ -124,7 +124,7 @@ 268 - {{137, 261}, {147, 22}} + {{137, 286}, {147, 22}} 2 YES @@ -212,7 +212,7 @@ 268 - {{128, 6}, {74, 28}} + {{128, 5}, {74, 28}} 2 YES @@ -233,7 +233,7 @@ 268 - {{210, 6}, {74, 28}} + {{210, 5}, {74, 28}} 2 YES @@ -254,7 +254,7 @@ 268 - {{136, 238}, {149, 17}} + {{136, 263}, {149, 17}} 2 YES @@ -277,7 +277,7 @@ 268 - {{40, 240}, {72, 14}} + {{40, 265}, {72, 14}} 2 YES @@ -294,7 +294,7 @@ 268 - {{40, 213}, {72, 14}} + {{40, 238}, {72, 14}} 2 YES @@ -311,7 +311,7 @@ 268 - {{136, 212}, {150, 15}} + {{136, 237}, {150, 15}} 2 YES @@ -334,7 +334,7 @@ 268 - {{40, 186}, {85, 14}} + {{40, 185}, {85, 14}} YES 2 @@ -355,7 +355,7 @@ 268 - {{137, 180}, {147, 22}} + {{137, 179}, {147, 22}} YES 2 @@ -456,7 +456,7 @@ 268 - {{17, 157}, {124, 14}} + {{17, 156}, {124, 14}} 2 YES @@ -474,7 +474,7 @@ 268 - {{40, 133}, {52, 14}} + {{40, 132}, {52, 14}} 2 YES @@ -491,7 +491,7 @@ 268 - {{137, 127}, {147, 22}} + {{137, 126}, {147, 22}} 2 YES @@ -548,7 +548,7 @@ 268 - {{40, 106}, {72, 14}} + {{40, 105}, {72, 14}} YES 2 @@ -566,7 +566,7 @@ 268 - {{40, 79}, {96, 14}} + {{40, 78}, {96, 14}} 2 YES @@ -583,7 +583,7 @@ 268 - {{136, 79}, {118, 15}} + {{136, 78}, {118, 15}} 2 YES @@ -606,7 +606,7 @@ 268 - {{40, 52}, {85, 14}} + {{40, 51}, {85, 14}} YES 2 @@ -624,7 +624,7 @@ 268 - {{201, 52}, {50, 14}} + {{201, 51}, {33, 14}} 2 YES @@ -643,7 +643,7 @@ 268 - {{232, 50}, {95, 18}} + {{232, 49}, {95, 18}} 2 YES @@ -655,11 +655,11 @@ 1211912703 130 - + NSImage NSSwitch - + NSSwitch @@ -671,7 +671,7 @@ 268 - {{136, 105}, {150, 15}} + {{136, 104}, {150, 15}} YES 2 @@ -695,7 +695,7 @@ 268 - {{256, 79}, {50, 14}} + {{256, 78}, {50, 14}} 2 YES @@ -714,7 +714,7 @@ 268 - {{136, 52}, {59, 15}} + {{136, 51}, {59, 15}} YES 2 @@ -735,8 +735,71 @@ NO + + + 268 + {{136, 210}, {66, 18}} + + 2 + YES + + -2080244224 + 131072 + Sources + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{209, 210}, {76, 18}} + + 2 + YES + + -2080244224 + 131072 + Receivers + + + 1211912703 + 130 + + + + + 200 + 25 + + + + + 268 + {{40, 212}, {80, 14}} + + 2 + YES + + 68288064 + 272761856 + Force diffuse : + + + + + + - {303, 313} + {303, 338} YES 2 @@ -964,6 +1027,38 @@ 311 + + + diffuseSourcesBox + + + + 320 + + + + diffuseReceiversBox + + + + 321 + + + + diffuseReceiversChanged: + + + + 322 + + + + diffuseSourcesChanged: + + + + 323 + @@ -1011,7 +1106,6 @@ - @@ -1029,6 +1123,10 @@ + + + + @@ -1462,6 +1560,48 @@ + + 312 + + + YES + + + + + + 313 + + + + + 314 + + + YES + + + + + + 315 + + + + + 316 + + + YES + + + + + + 317 + + + @@ -1478,12 +1618,14 @@ 12.IBPluginDependency 13.IBPluginDependency 14.IBPluginDependency + 142.IBAttributePlaceholdersKey 142.IBPluginDependency 142.IBViewIntegration.shadowBlurRadius 142.IBViewIntegration.shadowColor 142.IBViewIntegration.shadowOffsetHeight 142.IBViewIntegration.shadowOffsetWidth 143.IBPluginDependency + 144.IBAttributePlaceholdersKey 144.IBPluginDependency 144.IBViewIntegration.shadowBlurRadius 144.IBViewIntegration.shadowColor @@ -1503,7 +1645,9 @@ 17.IBPluginDependency 18.IBPluginDependency 213.IBPluginDependency + 214.IBAttributePlaceholdersKey 214.IBPluginDependency + 215.IBAttributePlaceholdersKey 215.IBPluginDependency 215.IBViewIntegration.shadowBlurRadius 215.IBViewIntegration.shadowColor @@ -1513,6 +1657,7 @@ 218.IBPluginDependency 219.IBPluginDependency 220.IBPluginDependency + 23.IBAttributePlaceholdersKey 23.IBPluginDependency 230.IBPluginDependency 231.IBPluginDependency @@ -1528,30 +1673,49 @@ 242.IBPluginDependency 245.IBPluginDependency 246.IBPluginDependency + 247.IBAttributePlaceholdersKey 247.IBPluginDependency 248.IBPluginDependency 260.IBPluginDependency 261.IBPluginDependency 262.IBPluginDependency 263.IBPluginDependency + 290.IBAttributePlaceholdersKey 290.IBPluginDependency 291.IBPluginDependency 3.IBEditorWindowLastContentRect 3.IBPluginDependency 3.IBWindowTemplateEditedContentRect 3.NSWindowTemplate.visibleAtLaunch + 31.IBAttributePlaceholdersKey 31.IBPluginDependency + 312.IBAttributePlaceholdersKey + 312.IBPluginDependency + 313.IBPluginDependency + 314.IBAttributePlaceholdersKey + 314.IBPluginDependency + 315.IBPluginDependency + 316.IBAttributePlaceholdersKey + 316.IBPluginDependency + 317.IBPluginDependency 32.IBPluginDependency + 35.IBAttributePlaceholdersKey 35.IBPluginDependency 36.IBPluginDependency + 37.IBAttributePlaceholdersKey 37.IBPluginDependency + 38.IBAttributePlaceholdersKey 38.IBPluginDependency + 4.IBAttributePlaceholdersKey 4.IBPluginDependency + 4.IBUserGuides 43.IBPluginDependency 5.IBPluginDependency 6.IBPluginDependency + 7.IBAttributePlaceholdersKey 7.IBPluginDependency 8.IBPluginDependency + 9.IBAttributePlaceholdersKey 9.IBPluginDependency 9.IBViewIntegration.shadowBlurRadius 9.IBViewIntegration.shadowColor @@ -1576,12 +1740,28 @@ com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit + + ToolTip + + ToolTip + + The two OpenGL preview techniques use shadow mapping to compute the light transport in a scene. This parameter allows choosing the resolution of the associated shadow maps, which is useful when the shadow quality is too low (for example when jagged edges are visible in the image). The higher this value, the slower the preview will converge. A value of 256 or 512 is usually a good start. + + com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit + + ToolTip + + ToolTip + + The two OpenGL preview techniques use shadow mapping to compute the light transport in a scene. This parameter allows choosing the resolution of the associated shadow maps, which is useful when the shadow quality is too low (for example when jagged edges are visible in the image). The higher this value, the slower the preview will converge. A value of 256 or 512 is usually a good start. + + com.brandonwalkin.BWToolkit @@ -1601,7 +1781,43 @@ com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit + + ToolTip + + ToolTip + + QSB0b25lbWFwcGluZyBtZXRob2QgaXMgbmVjZXNzYXJ5IHRvIHRyYW5zbGF0ZSBwaHlzaWNhbCByYWRp +YW5jZSB2YWx1ZXMgaW50byBwaXhlbCBpbnRlbnNpdGllcy4gVGhlIHRlY2huaXF1ZSBjaG9zZW4gaGVy +ZSBpcyB1c2VkIGJvdGggZm9yIHRoZSBwcmV2aWV3IGFuZCByZW5kZXJlZCBpbWFnZXMuCgpHYW1tYSBj +b3JyZWN0aW9uIGlzIHRoZSBkZWZhdWx0IGFuZCB3ZWxsLXN1aXRlZCBpZiB0aGUgZHluYW1pYyByYW5n +ZSBvZiB5b3VyIHNjZW5lIGlzIG5vdCB0b28gZ3JlYXQuCgpbUmVpbmhhcmQuIGV0IGFsIDIwMDJdIHdv +cmtzIHdlbGwgZm9yIHNjZW5lcyB3aXRoIGEgaGlnaCBkeW5hbWljIHJhbmdlLiBOb3RlIHRoYXQgdGhp +cyB0ZWNobmlxdWUgY29udGludWFsbHkgYWRhcHRzIHRvIHRoZSBvdmVyYWxsIGltYWdlIGJyaWdodG5l +c3MsIHdoaWNoIG1heSBwcm9kdWNlIHVuZXhwZWN0ZWQgYmVoYXZpb3IgdG9nZXRoZXIgd2l0aCB0aGUg +cmVhbHRpbWUgcHJldmlldzogd2hlbiB0dXJuaW5nIHRvIGZhY2UgYSBkYXJrIHJlZ2lvbiBvZiB0aGUg +c2NlbmUsIHRoZSB0b25lbWFwcGVyIHdpbGwgY2hhbmdlIHRoZSBleHBvc3VyZSB0byBtYWludGFpbiB0 +aGUgc2FtZSBvdmVyYWxsIGJyaWdodG5lc3MuA + + com.brandonwalkin.BWToolkit + + ToolTip + + ToolTip + + QSB0b25lbWFwcGluZyBtZXRob2QgaXMgbmVjZXNzYXJ5IHRvIHRyYW5zbGF0ZSBwaHlzaWNhbCByYWRp +YW5jZSB2YWx1ZXMgaW50byBwaXhlbCBpbnRlbnNpdGllcy4gVGhlIHRlY2huaXF1ZSBjaG9zZW4gaGVy +ZSBpcyB1c2VkIGJvdGggZm9yIHRoZSBwcmV2aWV3IGFuZCByZW5kZXJlZCBpbWFnZXMuCgpHYW1tYSBj +b3JyZWN0aW9uIGlzIHRoZSBkZWZhdWx0IGFuZCB3ZWxsLXN1aXRlZCBpZiB0aGUgZHluYW1pYyByYW5n +ZSBvZiB5b3VyIHNjZW5lIGlzIG5vdCB0b28gZ3JlYXQuCgpbUmVpbmhhcmQuIGV0IGFsIDIwMDJdIHdv +cmtzIHdlbGwgZm9yIHNjZW5lcyB3aXRoIGEgaGlnaCBkeW5hbWljIHJhbmdlLiBOb3RlIHRoYXQgdGhp +cyB0ZWNobmlxdWUgY29udGludWFsbHkgYWRhcHRzIHRvIHRoZSBvdmVyYWxsIGltYWdlIGJyaWdodG5l +c3MsIHdoaWNoIG1heSBwcm9kdWNlIHVuZXhwZWN0ZWQgYmVoYXZpb3IgdG9nZXRoZXIgd2l0aCB0aGUg +cmVhbHRpbWUgcHJldmlldzogd2hlbiB0dXJuaW5nIHRvIGZhY2UgYSBkYXJrIHJlZ2lvbiBvZiB0aGUg +c2NlbmUsIHRoZSB0b25lbWFwcGVyIHdpbGwgY2hhbmdlIHRoZSBleHBvc3VyZSB0byBtYWludGFpbiB0 +aGUgc2FtZSBvdmVyYWxsIGJyaWdodG5lc3MuA + + com.brandonwalkin.BWToolkit @@ -1611,6 +1827,14 @@ com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit + + ToolTip + + ToolTip + + Highest path length to visualize in the preview. The lowest value corresponds to direct illumination and the highest one is 4-bounce global illumination. + + com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit @@ -1626,30 +1850,206 @@ com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit + + ToolTip + + ToolTip + + Does the viewing device have an sRGB response curve? For most monitors and LCD screens on the market, this is the case. + + com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit + + ToolTip + + ToolTip + + Gamma of the viewing device (usually 2.2). When sRGB is selected, this value is ignored. + + com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit - {{204, 75}, {303, 313}} + {{703, 287}, {303, 338}} com.apple.InterfaceBuilder.CocoaPlugin - {{204, 75}, {303, 313}} + {{703, 287}, {303, 338}} + + ToolTip + + ToolTip + + Highest path length to visualize in the preview. The lowest value corresponds to direct illumination and the highest one is 4-bounce global illumination. + + + com.brandonwalkin.BWToolkit + + ToolTip + + ToolTip + + V2hlbiBhIHNjZW5lIGNvbnRhaW5zIG1hbnkgZ2xvc3N5IHN1cmZhY2VzLCB0aGUgcmVhbC10aW1lIHZp +c3VhbGl6YXRpb24gY2FuIHNvbWV0aW1lcyBwcm9kdWNlIGRpc3R1cmJpbmcgaW1hZ2UgYXJ0aWZhY3Rz +IChicmlnaHQgYmxvdGNoZXMpLiBUaGVzZSBldmVudHVhbGx5IGRpc2FwcGVhciBhcyB0aGUgcHJldmll +dyBjb252ZXJnZXMsIGJ1dCB3YWl0aW5nIGZvciBhIGxvbmcgdGltZSBtYXkgYmUgdW5kZXNpcmFibGUu +IFRoZSBmb2xsb3dpbmcgb3B0aW9ucyBhcmUgbWVhbnQgdG8gcmVkdWNlIHN1Y2ggaXNzdWVzOgoKRGlm +ZnVzZSBzb3VyY2VzOiB0cmVhdCBnbG9zc3kgc3VyZmFjZXMgYXQgdGhlIHNlY29uZCBib3VuY2UgYXMg +aWYgdGhleSB3ZXJlIGRpZmZ1c2UuIFRoaXMgaXMgdXN1YWxseSBwZXJmZWN0bHkgZmluZSBmb3IgcHJl +dmlld2luZyBwdXJwb3NlcyBhbmQgaXMgdGh1cyB0dXJuZWQgb24gYnkgZGVmYXVsdC4KCkRpZmZ1c2Ug +cmVjZWl2ZXJzOiB0cmVhdCBkaXJlY3RseSB2aXNpYmxlIHN1cmZhY2VzIGFzIGlmIHRoZXkgd2VyZSBk +aWZmdXNlLiBUaGlzIGlzIGxlYWRzIHRvIGEgbXVjaCBtb3JlIGFwcHJveGltYXRlIHJlc3VsdCDigJQg +ZXNzZW50aWFsbHksIGEgY2xheSB2ZXJzaW9uIG9mIHRoZSBzY2VuZSBpcyBiZWluZyByZW5kZXJlZC4 + + + com.brandonwalkin.BWToolkit + com.brandonwalkin.BWToolkit + + ToolTip + + ToolTip + + V2hlbiBhIHNjZW5lIGNvbnRhaW5zIG1hbnkgZ2xvc3N5IHN1cmZhY2VzLCB0aGUgcmVhbC10aW1lIHZp +c3VhbGl6YXRpb24gY2FuIHNvbWV0aW1lcyBwcm9kdWNlIGRpc3R1cmJpbmcgaW1hZ2UgYXJ0aWZhY3Rz +IChicmlnaHQgYmxvdGNoZXMpLiBUaGVzZSBldmVudHVhbGx5IGRpc2FwcGVhciBhcyB0aGUgcHJldmll +dyBjb252ZXJnZXMsIGJ1dCB3YWl0aW5nIGZvciBhIGxvbmcgdGltZSBtYXkgYmUgdW5kZXNpcmFibGUu +IFRoZSBmb2xsb3dpbmcgb3B0aW9ucyBhcmUgbWVhbnQgdG8gcmVkdWNlIHN1Y2ggaXNzdWVzOgoKRGlm +ZnVzZSBzb3VyY2VzOiB0cmVhdCBnbG9zc3kgc3VyZmFjZXMgYXQgdGhlIHNlY29uZCBib3VuY2UgYXMg +aWYgdGhleSB3ZXJlIGRpZmZ1c2UuIFRoaXMgaXMgdXN1YWxseSBwZXJmZWN0bHkgZmluZSBmb3IgcHJl +dmlld2luZyBwdXJwb3NlcyBhbmQgaXMgdGh1cyB0dXJuZWQgb24gYnkgZGVmYXVsdC4KCkRpZmZ1c2Ug +cmVjZWl2ZXJzOiB0cmVhdCBkaXJlY3RseSB2aXNpYmxlIHN1cmZhY2VzIGFzIGlmIHRoZXkgd2VyZSBk +aWZmdXNlLiBUaGlzIGlzIGxlYWRzIHRvIGEgbXVjaCBtb3JlIGFwcHJveGltYXRlIHJlc3VsdCAtLSBl +c3NlbnRpYWxseSwgYSBjbGF5IHZlcnNpb24gb2YgdGhlIHNjZW5lIGlzIGJlaW5nIHJlbmRlcmVkLg + + + com.brandonwalkin.BWToolkit + com.brandonwalkin.BWToolkit + + ToolTip + + ToolTip + + V2hlbiBhIHNjZW5lIGNvbnRhaW5zIG1hbnkgZ2xvc3N5IHN1cmZhY2VzLCB0aGUgcmVhbC10aW1lIHZp +c3VhbGl6YXRpb24gY2FuIHNvbWV0aW1lcyBwcm9kdWNlIGRpc3R1cmJpbmcgaW1hZ2UgYXJ0aWZhY3Rz +IChicmlnaHQgYmxvdGNoZXMpLiBUaGVzZSBldmVudHVhbGx5IGRpc2FwcGVhciBhcyB0aGUgcHJldmll +dyBjb252ZXJnZXMsIGJ1dCB3YWl0aW5nIGZvciBhIGxvbmcgdGltZSBtYXkgYmUgdW5kZXNpcmFibGUu +IFRoZSBmb2xsb3dpbmcgb3B0aW9ucyBhcmUgbWVhbnQgdG8gcmVkdWNlIHN1Y2ggaXNzdWVzOgoKRGlm +ZnVzZSBzb3VyY2VzOiB0cmVhdCBnbG9zc3kgc3VyZmFjZXMgYXQgdGhlIHNlY29uZCBib3VuY2UgYXMg +aWYgdGhleSB3ZXJlIGRpZmZ1c2UuIFRoaXMgaXMgdXN1YWxseSBwZXJmZWN0bHkgZmluZSBmb3IgcHJl +dmlld2luZyBwdXJwb3NlcyBhbmQgaXMgdGh1cyB0dXJuZWQgb24gYnkgZGVmYXVsdC4KCkRpZmZ1c2Ug +cmVjZWl2ZXJzOiB0cmVhdCBkaXJlY3RseSB2aXNpYmxlIHN1cmZhY2VzIGFzIGlmIHRoZXkgd2VyZSBk +aWZmdXNlLiBUaGlzIGlzIGxlYWRzIHRvIGEgbXVjaCBtb3JlIGFwcHJveGltYXRlIHJlc3VsdCDigJQg +ZXNzZW50aWFsbHksIGEgY2xheSB2ZXJzaW9uIG9mIHRoZSBzY2VuZSBpcyBiZWluZyByZW5kZXJlZC4 + + com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit + + ToolTip + + ToolTip + + Q2xhbXBpbmcgY2hhbmdlcyB0aGUgaW5mbHVlbmNlIHJhZGl1cyBvZiBwaG90b25zIHVzZWQgdG8gcmVu +ZGVyIHRoZSBwcmV2aWV3LiBBIHRvbyBzbWFsbCB2YWx1ZSB3aWxsIGNhdXNlIGJyaWdodCBibG90Y2hl +cyB0byBhcHBlYXIgaW4gdGhlIHByZXZpZXcsIHdoZXJlYXMgYSB0b28gbGFyZ2UgdmFsdWUgd2lsbCBh +cnRpZmljaWFsbHkgZGFya2VuIHRoZSBpbWFnZS4KCkEgZ29vZCBhcHByb2FjaCBpcyB0byBzZXQgdGhp +cyBzbGlkZXIgYXMgbG93IGFzIHBvc3NpYmxlIHdpdGhvdXQgc2VlaW5nIGRpc3R1cmJpbmcgYmxvdGNo +ZXMgaW4gdGhlIGltYWdlLg + + com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit + + ToolTip + + ToolTip + + Q2xhbXBpbmcgY2hhbmdlcyB0aGUgaW5mbHVlbmNlIHJhZGl1cyBvZiBwaG90b25zIHVzZWQgdG8gcmVu +ZGVyIHRoZSBwcmV2aWV3LiBBIHRvbyBzbWFsbCB2YWx1ZSB3aWxsIGNhdXNlIGJyaWdodCBibG90Y2hl +cyB0byBhcHBlYXIgaW4gdGhlIHByZXZpZXcsIHdoZXJlYXMgYSB0b28gbGFyZ2UgdmFsdWUgd2lsbCBh +cnRpZmljaWFsbHkgZGFya2VuIHRoZSBpbWFnZS4KCkEgZ29vZCBhcHByb2FjaCBpcyB0byBzZXQgdGhp +cyBzbGlkZXIgYXMgbG93IGFzIHBvc3NpYmxlIHdpdGhvdXQgc2VlaW5nIGRpc3R1cmJpbmcgYmxvdGNo +ZXMgaW4gdGhlIGltYWdlLg + + com.brandonwalkin.BWToolkit + + ToolTip + + ToolTip + + Q2xhbXBpbmcgY2hhbmdlcyB0aGUgaW5mbHVlbmNlIHJhZGl1cyBvZiBwaG90b25zIHVzZWQgdG8gcmVu +ZGVyIHRoZSBwcmV2aWV3LiBBIHRvbyBzbWFsbCB2YWx1ZSB3aWxsIGNhdXNlIGJyaWdodCBibG90Y2hl +cyB0byBhcHBlYXIgaW4gdGhlIHByZXZpZXcsIHdoZXJlYXMgYSB0b28gbGFyZ2UgdmFsdWUgd2lsbCBh +cnRpZmljaWFsbHkgZGFya2VuIHRoZSBpbWFnZS4KCkEgZ29vZCBhcHByb2FjaCBpcyB0byBzZXQgdGhp +cyBzbGlkZXIgYXMgbG93IGFzIHBvc3NpYmxlIHdpdGhvdXQgc2VlaW5nIGRpc3R1cmJpbmcgYmxvdGNo +ZXMgaW4gdGhlIGltYWdlLg + + + com.brandonwalkin.BWToolkit + + ToolTip + + ToolTip + + V2hlbiBhIHNjZW5lIGNvbnRhaW5zIG1hbnkgZ2xvc3N5IHN1cmZhY2VzLCB0aGUgcmVhbC10aW1lIHZp +c3VhbGl6YXRpb24gY2FuIHNvbWV0aW1lcyBwcm9kdWNlIGRpc3R1cmJpbmcgaW1hZ2UgYXJ0aWZhY3Rz +IChicmlnaHQgYmxvdGNoZXMpLiBUaGVzZSBldmVudHVhbGx5IGRpc2FwcGVhciBhcyB0aGUgcHJldmll +dyBjb252ZXJnZXMsIGJ1dCB3YWl0aW5nIGZvciBhIGxvbmcgdGltZSBtYXkgYmUgdW5kZXNpcmFibGUu +IFRoZSBmb2xsb3dpbmcgb3B0aW9ucyBhcmUgbWVhbnQgdG8gcmVkdWNlIHN1Y2ggaXNzdWVzOgoKRGlm +ZnVzZSBzb3VyY2VzOiB0cmVhdCBnbG9zc3kgc3VyZmFjZXMgYXQgdGhlIHNlY29uZCBib3VuY2UgYXMg +aWYgdGhleSB3ZXJlIGRpZmZ1c2UuIFRoaXMgaXMgdXN1YWxseSBwZXJmZWN0bHkgZmluZSBmb3IgcHJl +dmlld2luZyBwdXJwb3NlcyBhbmQgaXMgdGh1cyB0dXJuZWQgb24gYnkgZGVmYXVsdC4KCkRpZmZ1c2Ug +cmVjZWl2ZXJzOiB0cmVhdCBkaXJlY3RseSB2aXNpYmxlIHN1cmZhY2VzIGFzIGlmIHRoZXkgd2VyZSBk +aWZmdXNlLiBUaGlzIGlzIGxlYWRzIHRvIGEgbXVjaCBtb3JlIGFwcHJveGltYXRlIHJlc3VsdCDigJQg +ZXNzZW50aWFsbHksIGEgY2xheSB2ZXJzaW9uIG9mIHRoZSBzY2VuZSBpcyBiZWluZyByZW5kZXJlZC4 + + com.apple.InterfaceBuilder.CocoaPlugin + com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit + + ToolTip + + ToolTip + + T3BlbkdMIGFuZCBPcGVuR0wgKHNpbmdsZSBwYXNzKSB1c2UgdGhlIGdyYXBoaWNzIGNhcmQgdG8gZHJh +dyBhbiBhcHByb3hpbWF0ZSBwcmV2aWV3IG9mIHRoZSBzY2VuZSwgd2hpY2ggaXMgdXN1YWxseSBwcmVm +ZXJhYmxlIGZvciBwZXJmb3JtYW5jZSByZWFzb25zLiBUaGUgc2luZ2xlIHBhc3MgdmFyaWFudCBtYWtl +cyBoZWF2eSB1c2Ugb24gZ2VvbWV0cnkgc2hhZGVycyB0byBmdXJ0aGVyIGFjY2VsZXJhdGUgcmVuZGVy +aW5nLCBidXQgZm9yIHRoaXMgdG8gYmUgYWN0dWFsbHkgZmFzdGVyLCB0aGUgY2FyZCBtdXN0IGJlIHZl +cnkgcmVjZW50IChlLmcuIEZlcm1pIGFuZCBhYm92ZSkuCgpUaGUgUmF5IFRyYWNpbmcgc3RyYXRlZ2ll +cyBhcmUgcHJlZmVyYWJsZSB3aGVuIHRoZSBzY2VuZSBjb250YWlucyBub24tdHJpYW5ndWxhciBzaGFw +ZXMsIHdoaWNoIGNhbm5vdCBlYXNpbHkgYmUgcmVuZGVyZWQgYnkgZ3JhcGhpY3MgaGFyZHdhcmUsIHN1 +Y2ggYXMgcXVhZHJpY3MuIFRoZSBDb2hlcmVudCBSYXkgVHJhY2luZyB0ZWNobmlxdWUgdHJhY2VzIGZv +dXIgcmF5cyBhdCBhIHRpbWUgdXNpbmcgU1NFMi4 + + com.brandonwalkin.BWToolkit com.brandonwalkin.BWToolkit + + ToolTip + + ToolTip + + T3BlbkdMIGFuZCBPcGVuR0wgKHNpbmdsZSBwYXNzKSB1c2UgdGhlIGdyYXBoaWNzIGNhcmQgdG8gZHJh +dyBhbiBhcHByb3hpbWF0ZSBwcmV2aWV3IG9mIHRoZSBzY2VuZSwgd2hpY2ggaXMgdXN1YWxseSBwcmVm +ZXJhYmxlIGZvciBwZXJmb3JtYW5jZSByZWFzb25zLiBUaGUgc2luZ2xlIHBhc3MgdmFyaWFudCBtYWtl +cyBoZWF2eSB1c2Ugb24gZ2VvbWV0cnkgc2hhZGVycyB0byBmdXJ0aGVyIGFjY2VsZXJhdGUgcmVuZGVy +aW5nLCBidXQgZm9yIHRoaXMgdG8gYmUgYWN0dWFsbHkgZmFzdGVyLCB0aGUgY2FyZCBtdXN0IGJlIHZl +cnkgcmVjZW50IChlLmcuIEZlcm1pIGFuZCBhYm92ZSkuCgpUaGUgUmF5IFRyYWNpbmcgc3RyYXRlZ2ll +cyBhcmUgcHJlZmVyYWJsZSB3aGVuIHRoZSBzY2VuZSBjb250YWlucyBub24tdHJpYW5ndWxhciBzaGFw +ZXMsIHdoaWNoIGNhbm5vdCBlYXNpbHkgYmUgcmVuZGVyZWQgYnkgZ3JhcGhpY3MgaGFyZHdhcmUsIHN1 +Y2ggYXMgcXVhZHJpY3MuIFRoZSBDb2hlcmVudCBSYXkgVHJhY2luZyB0ZWNobmlxdWUgdHJhY2VzIGZv +dXIgcmF5cyBhdCBhIHRpbWUgdXNpbmcgU1NFMi4 + + com.brandonwalkin.BWToolkit @@ -1673,7 +2073,7 @@ - 311 + 323 @@ -1686,9 +2086,10 @@ YES clampingChanged: + diffuseReceiversChanged: + diffuseSourcesChanged: exposureChanged: gammaChanged: - myAction1: pathLengthChanged: previewMethodChanged: reinhardKeyChanged: @@ -1710,6 +2111,76 @@ id id id + id + + + + YES + + YES + clampingChanged: + diffuseReceiversChanged: + diffuseSourcesChanged: + exposureChanged: + gammaChanged: + pathLengthChanged: + previewMethodChanged: + reinhardKeyChanged: + reset: + sRGBChanged: + shadowMapResolutionChanged: + toneMappingMethodChanged: + + + YES + + clampingChanged: + id + + + diffuseReceiversChanged: + id + + + diffuseSourcesChanged: + id + + + exposureChanged: + id + + + gammaChanged: + id + + + pathLengthChanged: + id + + + previewMethodChanged: + id + + + reinhardKeyChanged: + id + + + reset: + id + + + sRGBChanged: + id + + + shadowMapResolutionChanged: + id + + + toneMappingMethodChanged: + id + @@ -1717,6 +2188,8 @@ YES clamping + diffuseReceiversBox + diffuseSourcesBox exposure exposureLabel exposureValueLabel @@ -1736,6 +2209,8 @@ YES BWTransparentSlider + BWTransparentCheckbox + BWTransparentCheckbox BWTransparentSlider NSTextField NSTextField @@ -1753,6 +2228,105 @@ BWTransparentPopUpButton + + YES + + YES + clamping + diffuseReceiversBox + diffuseSourcesBox + exposure + exposureLabel + exposureValueLabel + gamma + gammaLabel + gammaValueLabel + panel + pathLength + previewMethod + reinhardKey + reinhardKeyLabel + sRGB + shadowMapLabel + shadowMapResolution + toneMappingMethod + + + YES + + clamping + BWTransparentSlider + + + diffuseReceiversBox + BWTransparentCheckbox + + + diffuseSourcesBox + BWTransparentCheckbox + + + exposure + BWTransparentSlider + + + exposureLabel + NSTextField + + + exposureValueLabel + NSTextField + + + gamma + BWTransparentSlider + + + gammaLabel + NSTextField + + + gammaValueLabel + NSTextField + + + panel + NSPanel + + + pathLength + BWTransparentSlider + + + previewMethod + BWTransparentPopUpButton + + + reinhardKey + BWTransparentSlider + + + reinhardKeyLabel + NSTextField + + + sRGB + BWTransparentCheckbox + + + shadowMapLabel + NSTextField + + + shadowMapResolution + BWTransparentPopUpButton + + + toneMappingMethod + BWTransparentPopUpButton + + + IBUserSource diff --git a/tools/darwin/PreviewSettings.nib/keyedobjects.nib b/tools/darwin/PreviewSettings.nib/keyedobjects.nib index 80b1e3ce..4da713d1 100644 Binary files a/tools/darwin/PreviewSettings.nib/keyedobjects.nib and b/tools/darwin/PreviewSettings.nib/keyedobjects.nib differ diff --git a/tools/qt4.py b/tools/qt4.py index 5d700736..7aba35f3 100644 --- a/tools/qt4.py +++ b/tools/qt4.py @@ -203,9 +203,9 @@ def _detect(env): moc = env.WhereIs('moc-qt4') or env.WhereIs('moc4') or env.WhereIs('moc') if moc: QTDIR = os.path.dirname(os.path.dirname(moc)) - SCons.Warnings.warn( - QtdirNotFound, - "QTDIR variable is not defined, using moc executable as a hint (QTDIR=%s)" % QTDIR) + #SCons.Warnings.warn( + # QtdirNotFound, + # "QTDIR variable is not defined, using moc executable as a hint (QTDIR=%s)" % QTDIR) return QTDIR raise SCons.Errors.StopError(