diff options
Diffstat (limited to 'intern')
436 files changed, 9295 insertions, 12891 deletions
diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt index 46571831efc..576c048288e 100644 --- a/intern/CMakeLists.txt +++ b/intern/CMakeLists.txt @@ -49,11 +49,6 @@ if(WITH_MOD_SMOKE) add_subdirectory(smoke) endif() -if(WITH_MOD_DECIMATE) - add_subdirectory(container) - add_subdirectory(decimation) -endif() - if(WITH_MOD_BOOLEAN) add_subdirectory(bsp) endif() diff --git a/intern/SConscript b/intern/SConscript index 3e40ef38705..59e412333b0 100644 --- a/intern/SConscript +++ b/intern/SConscript @@ -6,9 +6,7 @@ SConscript(['audaspace/SConscript', 'ghost/SConscript', 'guardedalloc/SConscript', 'moto/SConscript', - 'container/SConscript', 'memutil/SConscript/', - 'decimation/SConscript', 'iksolver/SConscript', 'itasc/SConscript', 'opencolorio/SConscript', @@ -17,6 +15,9 @@ SConscript(['audaspace/SConscript', 'smoke/SConscript', 'raskter/SConscript']) +# currently only contains headers +# SConscript('container/SConscript') + if env ['WITH_BF_REMESH']: SConscript(['dualcon/SConscript']) diff --git a/intern/audaspace/CMakeLists.txt b/intern/audaspace/CMakeLists.txt index dc4ca7903cd..1617e520ac7 100644 --- a/intern/audaspace/CMakeLists.txt +++ b/intern/audaspace/CMakeLists.txt @@ -28,6 +28,7 @@ set(INC set(INC_SYS ${PTHREADS_INCLUDE_DIRS} + ${BOOST_INCLUDE_DIR} ) set(SRC @@ -94,6 +95,7 @@ set(SRC intern/AUD_IDevice.h intern/AUD_IFactory.h intern/AUD_IHandle.h + intern/AUD_ILockable.h intern/AUD_IReader.h intern/AUD_IWriter.h intern/AUD_JOSResampleFactory.cpp @@ -108,16 +110,17 @@ set(SRC intern/AUD_Mixer.h intern/AUD_MixerFactory.cpp intern/AUD_MixerFactory.h + intern/AUD_MutexLock.h intern/AUD_NULLDevice.cpp intern/AUD_NULLDevice.h intern/AUD_PyInit.h intern/AUD_ReadDevice.cpp intern/AUD_ReadDevice.h - intern/AUD_Reference.h - intern/AUD_ReferenceHandler.cpp intern/AUD_ResampleFactory.h intern/AUD_ResampleReader.cpp intern/AUD_ResampleReader.h + intern/AUD_Sequencer.cpp + intern/AUD_Sequencer.h intern/AUD_SequencerEntry.cpp intern/AUD_SequencerEntry.h intern/AUD_SequencerFactory.cpp @@ -148,6 +151,7 @@ set(SRC FX/AUD_DelayReader.h FX/AUD_DoubleFactory.h FX/AUD_DoubleReader.h + FX/AUD_IDynamicIIRFilterCalculator.h FX/AUD_DynamicIIRFilterFactory.h FX/AUD_DynamicIIRFilterReader.h FX/AUD_EffectFactory.h diff --git a/intern/audaspace/FX/AUD_AccumulatorFactory.cpp b/intern/audaspace/FX/AUD_AccumulatorFactory.cpp index 1862b9ab79d..00d3a9f2395 100644 --- a/intern/audaspace/FX/AUD_AccumulatorFactory.cpp +++ b/intern/audaspace/FX/AUD_AccumulatorFactory.cpp @@ -50,15 +50,15 @@ sample_t AUD_AccumulatorFactory::accumulatorFilter(AUD_CallbackIIRFilterReader* return out; } -AUD_AccumulatorFactory::AUD_AccumulatorFactory(AUD_Reference<AUD_IFactory> factory, +AUD_AccumulatorFactory::AUD_AccumulatorFactory(boost::shared_ptr<AUD_IFactory> factory, bool additive) : AUD_EffectFactory(factory), m_additive(additive) { } -AUD_Reference<AUD_IReader> AUD_AccumulatorFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_AccumulatorFactory::createReader() { - return new AUD_CallbackIIRFilterReader(getReader(), 2, 2, - m_additive ? accumulatorFilterAdditive : accumulatorFilter); + return boost::shared_ptr<AUD_IReader>(new AUD_CallbackIIRFilterReader(getReader(), 2, 2, + m_additive ? accumulatorFilterAdditive : accumulatorFilter)); } diff --git a/intern/audaspace/FX/AUD_AccumulatorFactory.h b/intern/audaspace/FX/AUD_AccumulatorFactory.h index ac73c5aa6ae..9087218a5f9 100644 --- a/intern/audaspace/FX/AUD_AccumulatorFactory.h +++ b/intern/audaspace/FX/AUD_AccumulatorFactory.h @@ -58,9 +58,9 @@ public: * \param factory The input factory. * \param additive Whether the accumulator is additive. */ - AUD_AccumulatorFactory(AUD_Reference<AUD_IFactory> factory, bool additive = false); + AUD_AccumulatorFactory(boost::shared_ptr<AUD_IFactory> factory, bool additive = false); - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); static sample_t accumulatorFilterAdditive(AUD_CallbackIIRFilterReader* reader, void* useless); static sample_t accumulatorFilter(AUD_CallbackIIRFilterReader* reader, void* useless); diff --git a/intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp b/intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp index fa9e8746b2b..eadfc525f96 100644 --- a/intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp +++ b/intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp @@ -33,7 +33,7 @@ #define CC m_specs.channels + m_channel -AUD_BaseIIRFilterReader::AUD_BaseIIRFilterReader(AUD_Reference<AUD_IReader> reader, int in, +AUD_BaseIIRFilterReader::AUD_BaseIIRFilterReader(boost::shared_ptr<AUD_IReader> reader, int in, int out) : AUD_EffectReader(reader), m_specs(reader->getSpecs()), diff --git a/intern/audaspace/FX/AUD_BaseIIRFilterReader.h b/intern/audaspace/FX/AUD_BaseIIRFilterReader.h index 43970c96a42..fe0a8efce64 100644 --- a/intern/audaspace/FX/AUD_BaseIIRFilterReader.h +++ b/intern/audaspace/FX/AUD_BaseIIRFilterReader.h @@ -90,7 +90,7 @@ protected: * \param in The count of past input samples needed. * \param out The count of past output samples needed. */ - AUD_BaseIIRFilterReader(AUD_Reference<AUD_IReader> reader, int in, int out); + AUD_BaseIIRFilterReader(boost::shared_ptr<AUD_IReader> reader, int in, int out); void setLengths(int in, int out); diff --git a/intern/audaspace/FX/AUD_ButterworthFactory.cpp b/intern/audaspace/FX/AUD_ButterworthFactory.cpp index 5edca302ece..97d85c8122f 100644 --- a/intern/audaspace/FX/AUD_ButterworthFactory.cpp +++ b/intern/audaspace/FX/AUD_ButterworthFactory.cpp @@ -39,7 +39,7 @@ #define BWPB41 0.76536686473 #define BWPB42 1.84775906502 -AUD_ButterworthFactory::AUD_ButterworthFactory(AUD_Reference<AUD_IFactory> factory, +AUD_ButterworthFactory::AUD_ButterworthFactory(boost::shared_ptr<AUD_IFactory> factory, float frequency) : AUD_DynamicIIRFilterFactory(factory), m_frequency(frequency) @@ -53,11 +53,11 @@ void AUD_ButterworthFactory::recalculateCoefficients(AUD_SampleRate rate, float omega = 2 * tan(m_frequency * M_PI / rate); float o2 = omega * omega; float o4 = o2 * o2; - float x1 = o2 + 2 * BWPB41 * omega + 4; - float x2 = o2 + 2 * BWPB42 * omega + 4; - float y1 = o2 - 2 * BWPB41 * omega + 4; - float y2 = o2 - 2 * BWPB42 * omega + 4; - float o228 = 2 * o2 - 8; + float x1 = o2 + 2.0f * (float)BWPB41 * omega + 4.0f; + float x2 = o2 + 2.0f * (float)BWPB42 * omega + 4.0f; + float y1 = o2 - 2.0f * (float)BWPB41 * omega + 4.0f; + float y2 = o2 - 2.0f * (float)BWPB42 * omega + 4.0f; + float o228 = 2.0f * o2 - 8.0f; float norm = x1 * x2; a.push_back(1); a.push_back((x1 + x2) * o228 / norm); diff --git a/intern/audaspace/FX/AUD_ButterworthFactory.h b/intern/audaspace/FX/AUD_ButterworthFactory.h index dc8b4d92775..e796f76aa29 100644 --- a/intern/audaspace/FX/AUD_ButterworthFactory.h +++ b/intern/audaspace/FX/AUD_ButterworthFactory.h @@ -53,7 +53,7 @@ public: * \param factory The input factory. * \param frequency The cutoff frequency. */ - AUD_ButterworthFactory(AUD_Reference<AUD_IFactory> factory, float frequency); + AUD_ButterworthFactory(boost::shared_ptr<AUD_IFactory> factory, float frequency); virtual void recalculateCoefficients(AUD_SampleRate rate, std::vector<float>& b, diff --git a/intern/audaspace/FX/AUD_CallbackIIRFilterReader.cpp b/intern/audaspace/FX/AUD_CallbackIIRFilterReader.cpp index 1a5c99adfb9..b5157d47666 100644 --- a/intern/audaspace/FX/AUD_CallbackIIRFilterReader.cpp +++ b/intern/audaspace/FX/AUD_CallbackIIRFilterReader.cpp @@ -29,7 +29,7 @@ #include "AUD_CallbackIIRFilterReader.h" -AUD_CallbackIIRFilterReader::AUD_CallbackIIRFilterReader(AUD_Reference<AUD_IReader> reader, +AUD_CallbackIIRFilterReader::AUD_CallbackIIRFilterReader(boost::shared_ptr<AUD_IReader> reader, int in, int out, doFilterIIR doFilter, endFilterIIR endFilter, diff --git a/intern/audaspace/FX/AUD_CallbackIIRFilterReader.h b/intern/audaspace/FX/AUD_CallbackIIRFilterReader.h index 7ced73844c9..d9df65f03eb 100644 --- a/intern/audaspace/FX/AUD_CallbackIIRFilterReader.h +++ b/intern/audaspace/FX/AUD_CallbackIIRFilterReader.h @@ -74,7 +74,7 @@ public: * \param endFilter The finishing callback. * \param data Data pointer for the callbacks. */ - AUD_CallbackIIRFilterReader(AUD_Reference<AUD_IReader> reader, int in, int out, + AUD_CallbackIIRFilterReader(boost::shared_ptr<AUD_IReader> reader, int in, int out, doFilterIIR doFilter, endFilterIIR endFilter = 0, void* data = 0); diff --git a/intern/audaspace/FX/AUD_DelayFactory.cpp b/intern/audaspace/FX/AUD_DelayFactory.cpp index a4606597933..3e5a7cfd2f8 100644 --- a/intern/audaspace/FX/AUD_DelayFactory.cpp +++ b/intern/audaspace/FX/AUD_DelayFactory.cpp @@ -31,7 +31,7 @@ #include "AUD_DelayReader.h" #include "AUD_Space.h" -AUD_DelayFactory::AUD_DelayFactory(AUD_Reference<AUD_IFactory> factory, float delay) : +AUD_DelayFactory::AUD_DelayFactory(boost::shared_ptr<AUD_IFactory> factory, float delay) : AUD_EffectFactory(factory), m_delay(delay) { @@ -42,7 +42,7 @@ float AUD_DelayFactory::getDelay() const return m_delay; } -AUD_Reference<AUD_IReader> AUD_DelayFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_DelayFactory::createReader() { - return new AUD_DelayReader(getReader(), m_delay); + return boost::shared_ptr<AUD_IReader>(new AUD_DelayReader(getReader(), m_delay)); } diff --git a/intern/audaspace/FX/AUD_DelayFactory.h b/intern/audaspace/FX/AUD_DelayFactory.h index 26855a05d70..8cfb2be9ac8 100644 --- a/intern/audaspace/FX/AUD_DelayFactory.h +++ b/intern/audaspace/FX/AUD_DelayFactory.h @@ -53,14 +53,14 @@ public: * \param factory The input factory. * \param delay The desired delay in seconds. */ - AUD_DelayFactory(AUD_Reference<AUD_IFactory> factory, float delay = 0); + AUD_DelayFactory(boost::shared_ptr<AUD_IFactory> factory, float delay = 0); /** * Returns the delay in seconds. */ float getDelay() const; - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif //__AUD_DELAYFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_DelayReader.cpp b/intern/audaspace/FX/AUD_DelayReader.cpp index 903e043af01..050508f28da 100644 --- a/intern/audaspace/FX/AUD_DelayReader.cpp +++ b/intern/audaspace/FX/AUD_DelayReader.cpp @@ -31,10 +31,10 @@ #include <cstring> -AUD_DelayReader::AUD_DelayReader(AUD_Reference<AUD_IReader> reader, float delay) : +AUD_DelayReader::AUD_DelayReader(boost::shared_ptr<AUD_IReader> reader, float delay) : AUD_EffectReader(reader), - m_delay(int(delay * reader->getSpecs().rate)), - m_remdelay(int(delay * reader->getSpecs().rate)) + m_delay(int((AUD_SampleRate)delay * reader->getSpecs().rate)), + m_remdelay(int((AUD_SampleRate)delay * reader->getSpecs().rate)) { } diff --git a/intern/audaspace/FX/AUD_DelayReader.h b/intern/audaspace/FX/AUD_DelayReader.h index 9d9b6619470..d4388e3befc 100644 --- a/intern/audaspace/FX/AUD_DelayReader.h +++ b/intern/audaspace/FX/AUD_DelayReader.h @@ -59,7 +59,7 @@ public: * \param reader The reader to read from. * \param delay The delay in seconds. */ - AUD_DelayReader(AUD_Reference<AUD_IReader> reader, float delay); + AUD_DelayReader(boost::shared_ptr<AUD_IReader> reader, float delay); virtual void seek(int position); virtual int getLength() const; diff --git a/intern/audaspace/FX/AUD_DoubleFactory.cpp b/intern/audaspace/FX/AUD_DoubleFactory.cpp index ab0111f8955..21bcbc2f649 100644 --- a/intern/audaspace/FX/AUD_DoubleFactory.cpp +++ b/intern/audaspace/FX/AUD_DoubleFactory.cpp @@ -30,15 +30,15 @@ #include "AUD_DoubleFactory.h" #include "AUD_DoubleReader.h" -AUD_DoubleFactory::AUD_DoubleFactory(AUD_Reference<AUD_IFactory> factory1, AUD_Reference<AUD_IFactory> factory2) : +AUD_DoubleFactory::AUD_DoubleFactory(boost::shared_ptr<AUD_IFactory> factory1, boost::shared_ptr<AUD_IFactory> factory2) : m_factory1(factory1), m_factory2(factory2) { } -AUD_Reference<AUD_IReader> AUD_DoubleFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_DoubleFactory::createReader() { - AUD_Reference<AUD_IReader> reader1 = m_factory1->createReader(); - AUD_Reference<AUD_IReader> reader2 = m_factory2->createReader(); + boost::shared_ptr<AUD_IReader> reader1 = m_factory1->createReader(); + boost::shared_ptr<AUD_IReader> reader2 = m_factory2->createReader(); - return new AUD_DoubleReader(reader1, reader2); + return boost::shared_ptr<AUD_IReader>(new AUD_DoubleReader(reader1, reader2)); } diff --git a/intern/audaspace/FX/AUD_DoubleFactory.h b/intern/audaspace/FX/AUD_DoubleFactory.h index e4d8fbfde8f..4a02cc7bcdb 100644 --- a/intern/audaspace/FX/AUD_DoubleFactory.h +++ b/intern/audaspace/FX/AUD_DoubleFactory.h @@ -41,12 +41,12 @@ private: /** * First played factory. */ - AUD_Reference<AUD_IFactory> m_factory1; + boost::shared_ptr<AUD_IFactory> m_factory1; /** * Second played factory. */ - AUD_Reference<AUD_IFactory> m_factory2; + boost::shared_ptr<AUD_IFactory> m_factory2; // hide copy constructor and operator= AUD_DoubleFactory(const AUD_DoubleFactory&); @@ -58,9 +58,9 @@ public: * \param factory1 The first input factory. * \param factory2 The second input factory. */ - AUD_DoubleFactory(AUD_Reference<AUD_IFactory> factory1, AUD_Reference<AUD_IFactory> factory2); + AUD_DoubleFactory(boost::shared_ptr<AUD_IFactory> factory1, boost::shared_ptr<AUD_IFactory> factory2); - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif //__AUD_DOUBLEFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_DoubleReader.cpp b/intern/audaspace/FX/AUD_DoubleReader.cpp index 2b28bc7d679..ee18914e93f 100644 --- a/intern/audaspace/FX/AUD_DoubleReader.cpp +++ b/intern/audaspace/FX/AUD_DoubleReader.cpp @@ -31,8 +31,8 @@ #include <cstring> -AUD_DoubleReader::AUD_DoubleReader(AUD_Reference<AUD_IReader> reader1, - AUD_Reference<AUD_IReader> reader2) : +AUD_DoubleReader::AUD_DoubleReader(boost::shared_ptr<AUD_IReader> reader1, + boost::shared_ptr<AUD_IReader> reader2) : m_reader1(reader1), m_reader2(reader2), m_finished1(false) { AUD_Specs s1, s2; diff --git a/intern/audaspace/FX/AUD_DoubleReader.h b/intern/audaspace/FX/AUD_DoubleReader.h index 1489f4eb184..5d2f65f1a90 100644 --- a/intern/audaspace/FX/AUD_DoubleReader.h +++ b/intern/audaspace/FX/AUD_DoubleReader.h @@ -32,7 +32,8 @@ #include "AUD_IReader.h" #include "AUD_Buffer.h" -#include "AUD_Reference.h" + +#include <boost/shared_ptr.hpp> /** * This reader plays two readers sequently. @@ -43,12 +44,12 @@ private: /** * The first reader. */ - AUD_Reference<AUD_IReader> m_reader1; + boost::shared_ptr<AUD_IReader> m_reader1; /** * The second reader. */ - AUD_Reference<AUD_IReader> m_reader2; + boost::shared_ptr<AUD_IReader> m_reader2; /** * Whether we've reached the end of the first reader. @@ -65,7 +66,7 @@ public: * \param reader1 The first reader to read from. * \param reader2 The second reader to read from. */ - AUD_DoubleReader(AUD_Reference<AUD_IReader> reader1, AUD_Reference<AUD_IReader> reader2); + AUD_DoubleReader(boost::shared_ptr<AUD_IReader> reader1, boost::shared_ptr<AUD_IReader> reader2); /** * Destroys the reader. diff --git a/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.cpp b/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.cpp index 3d6beb6c554..e8ea4323b2e 100644 --- a/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.cpp +++ b/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.cpp @@ -29,12 +29,14 @@ #include "AUD_DynamicIIRFilterFactory.h" #include "AUD_DynamicIIRFilterReader.h" -AUD_DynamicIIRFilterFactory::AUD_DynamicIIRFilterFactory(AUD_Reference<AUD_IFactory> factory) : + +AUD_DynamicIIRFilterFactory::AUD_DynamicIIRFilterFactory(boost::shared_ptr<AUD_IFactory> factory) : AUD_EffectFactory(factory) { } -AUD_Reference<AUD_IReader> AUD_DynamicIIRFilterFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_DynamicIIRFilterFactory::createReader() { - return new AUD_DynamicIIRFilterReader(getReader(), this); + return boost::shared_ptr<AUD_IReader>(new AUD_DynamicIIRFilterReader(getReader(), m_calculator)); } + diff --git a/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.h b/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.h index 5b297db2d56..f36a37f44b4 100644 --- a/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.h +++ b/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.h @@ -30,6 +30,7 @@ #define __AUD_DYNAMICIIRFILTERFACTORY_H__ #include "AUD_EffectFactory.h" +#include "AUD_IDynamicIIRFilterCalculator.h" #include <vector> /** @@ -40,24 +41,17 @@ */ class AUD_DynamicIIRFilterFactory : public AUD_EffectFactory { +protected: + boost::shared_ptr<AUD_IDynamicIIRFilterCalculator> m_calculator; + public: /** * Creates a new Dynmic IIR filter factory. * \param factory The input factory. */ - AUD_DynamicIIRFilterFactory(AUD_Reference<AUD_IFactory> factory); - - virtual AUD_Reference<AUD_IReader> createReader(); + AUD_DynamicIIRFilterFactory(boost::shared_ptr<AUD_IFactory> factory); - /** - * Recalculates the filter coefficients. - * \param rate The sample rate of the audio data. - * \param[out] b The input filter coefficients. - * \param[out] a The output filter coefficients. - */ - virtual void recalculateCoefficients(AUD_SampleRate rate, - std::vector<float>& b, - std::vector<float>& a)=0; + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif // __AUD_DYNAMICIIRFILTERFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_DynamicIIRFilterReader.cpp b/intern/audaspace/FX/AUD_DynamicIIRFilterReader.cpp index 24332ebfc1a..52aaf2311c0 100644 --- a/intern/audaspace/FX/AUD_DynamicIIRFilterReader.cpp +++ b/intern/audaspace/FX/AUD_DynamicIIRFilterReader.cpp @@ -28,10 +28,10 @@ #include "AUD_DynamicIIRFilterReader.h" -AUD_DynamicIIRFilterReader::AUD_DynamicIIRFilterReader(AUD_Reference<AUD_IReader> reader, - AUD_Reference<AUD_DynamicIIRFilterFactory> factory) : +AUD_DynamicIIRFilterReader::AUD_DynamicIIRFilterReader(boost::shared_ptr<AUD_IReader> reader, + boost::shared_ptr<AUD_IDynamicIIRFilterCalculator> calculator) : AUD_IIRFilterReader(reader, std::vector<float>(), std::vector<float>()), - m_factory(factory) + m_calculator(calculator) { sampleRateChanged(reader->getSpecs().rate); } @@ -39,6 +39,6 @@ AUD_DynamicIIRFilterReader::AUD_DynamicIIRFilterReader(AUD_Reference<AUD_IReader void AUD_DynamicIIRFilterReader::sampleRateChanged(AUD_SampleRate rate) { std::vector<float> a, b; - m_factory->recalculateCoefficients(rate, b, a); + m_calculator->recalculateCoefficients(rate, b, a); setCoefficients(b, a); } diff --git a/intern/audaspace/FX/AUD_DynamicIIRFilterReader.h b/intern/audaspace/FX/AUD_DynamicIIRFilterReader.h index 8a53c15b18f..0b68578bc53 100644 --- a/intern/audaspace/FX/AUD_DynamicIIRFilterReader.h +++ b/intern/audaspace/FX/AUD_DynamicIIRFilterReader.h @@ -30,7 +30,7 @@ #define __AUD_DYNAMICIIRFILTERREADER_H__ #include "AUD_IIRFilterReader.h" -#include "AUD_DynamicIIRFilterFactory.h" +#include "AUD_IDynamicIIRFilterCalculator.h" /** * This class is for dynamic infinite impulse response filters with simple @@ -42,11 +42,11 @@ private: /** * The factory for dynamically recalculating filter coefficients. */ - AUD_Reference<AUD_DynamicIIRFilterFactory> m_factory; + boost::shared_ptr<AUD_IDynamicIIRFilterCalculator> m_calculator; public: - AUD_DynamicIIRFilterReader(AUD_Reference<AUD_IReader> reader, - AUD_Reference<AUD_DynamicIIRFilterFactory> factory); + AUD_DynamicIIRFilterReader(boost::shared_ptr<AUD_IReader> reader, + boost::shared_ptr<AUD_IDynamicIIRFilterCalculator> calculator); virtual void sampleRateChanged(AUD_SampleRate rate); }; diff --git a/intern/audaspace/FX/AUD_EffectFactory.cpp b/intern/audaspace/FX/AUD_EffectFactory.cpp index d35f8affec8..6018ed561ca 100644 --- a/intern/audaspace/FX/AUD_EffectFactory.cpp +++ b/intern/audaspace/FX/AUD_EffectFactory.cpp @@ -30,7 +30,7 @@ #include "AUD_EffectFactory.h" #include "AUD_IReader.h" -AUD_EffectFactory::AUD_EffectFactory(AUD_Reference<AUD_IFactory> factory) +AUD_EffectFactory::AUD_EffectFactory(boost::shared_ptr<AUD_IFactory> factory) { m_factory = factory; } @@ -39,7 +39,7 @@ AUD_EffectFactory::~AUD_EffectFactory() { } -AUD_Reference<AUD_IFactory> AUD_EffectFactory::getFactory() const +boost::shared_ptr<AUD_IFactory> AUD_EffectFactory::getFactory() const { return m_factory; } diff --git a/intern/audaspace/FX/AUD_EffectFactory.h b/intern/audaspace/FX/AUD_EffectFactory.h index c8d26a1daa7..d09872638be 100644 --- a/intern/audaspace/FX/AUD_EffectFactory.h +++ b/intern/audaspace/FX/AUD_EffectFactory.h @@ -47,7 +47,7 @@ protected: /** * If there is no reader it is created out of this factory. */ - AUD_Reference<AUD_IFactory> m_factory; + boost::shared_ptr<AUD_IFactory> m_factory; /** * Returns the reader created out of the factory. @@ -55,7 +55,7 @@ protected: * classes. * \return The reader created out of the factory. */ - inline AUD_Reference<AUD_IReader> getReader() const + inline boost::shared_ptr<AUD_IReader> getReader() const { return m_factory->createReader(); } @@ -65,7 +65,7 @@ public: * Creates a new factory. * \param factory The input factory. */ - AUD_EffectFactory(AUD_Reference<AUD_IFactory> factory); + AUD_EffectFactory(boost::shared_ptr<AUD_IFactory> factory); /** * Destroys the factory. @@ -76,7 +76,7 @@ public: * Returns the saved factory. * \return The factory or NULL if there has no factory been saved. */ - AUD_Reference<AUD_IFactory> getFactory() const; + boost::shared_ptr<AUD_IFactory> getFactory() const; }; #endif //__AUD_EFFECTFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_EffectReader.cpp b/intern/audaspace/FX/AUD_EffectReader.cpp index 6c08549e744..b3e80bef03b 100644 --- a/intern/audaspace/FX/AUD_EffectReader.cpp +++ b/intern/audaspace/FX/AUD_EffectReader.cpp @@ -29,7 +29,7 @@ #include "AUD_EffectReader.h" -AUD_EffectReader::AUD_EffectReader(AUD_Reference<AUD_IReader> reader) +AUD_EffectReader::AUD_EffectReader(boost::shared_ptr<AUD_IReader> reader) { m_reader = reader; } diff --git a/intern/audaspace/FX/AUD_EffectReader.h b/intern/audaspace/FX/AUD_EffectReader.h index b089ec9a318..2745c12afaf 100644 --- a/intern/audaspace/FX/AUD_EffectReader.h +++ b/intern/audaspace/FX/AUD_EffectReader.h @@ -31,7 +31,8 @@ #define __AUD_EFFECTREADER_H__ #include "AUD_IReader.h" -#include "AUD_Reference.h" + +#include <boost/shared_ptr.hpp> /** * This reader is a base class for all effect readers that take one other reader @@ -48,14 +49,14 @@ protected: /** * The reader to read from. */ - AUD_Reference<AUD_IReader> m_reader; + boost::shared_ptr<AUD_IReader> m_reader; public: /** * Creates a new effect reader. * \param reader The reader to read from. */ - AUD_EffectReader(AUD_Reference<AUD_IReader> reader); + AUD_EffectReader(boost::shared_ptr<AUD_IReader> reader); /** * Destroys the reader. diff --git a/intern/audaspace/FX/AUD_EnvelopeFactory.cpp b/intern/audaspace/FX/AUD_EnvelopeFactory.cpp index c7176662659..1e5737557c1 100644 --- a/intern/audaspace/FX/AUD_EnvelopeFactory.cpp +++ b/intern/audaspace/FX/AUD_EnvelopeFactory.cpp @@ -54,7 +54,7 @@ void AUD_EnvelopeFactory::endEnvelopeFilter(EnvelopeParameters* param) delete param; } -AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_Reference<AUD_IFactory> factory, float attack, +AUD_EnvelopeFactory::AUD_EnvelopeFactory(boost::shared_ptr<AUD_IFactory> factory, float attack, float release, float threshold, float arthreshold) : AUD_EffectFactory(factory), @@ -65,9 +65,9 @@ AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_Reference<AUD_IFactory> factory, fl { } -AUD_Reference<AUD_IReader> AUD_EnvelopeFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_EnvelopeFactory::createReader() { - AUD_Reference<AUD_IReader> reader = getReader(); + boost::shared_ptr<AUD_IReader> reader = getReader(); EnvelopeParameters* param = new EnvelopeParameters(); param->arthreshold = m_arthreshold; @@ -75,8 +75,8 @@ AUD_Reference<AUD_IReader> AUD_EnvelopeFactory::createReader() param->release = pow(m_arthreshold, 1.0f/(static_cast<float>(reader->getSpecs().rate) * m_release)); param->threshold = m_threshold; - return new AUD_CallbackIIRFilterReader(reader, 1, 2, + return boost::shared_ptr<AUD_IReader>(new AUD_CallbackIIRFilterReader(reader, 1, 2, (doFilterIIR) envelopeFilter, (endFilterIIR) endEnvelopeFilter, - param); + param)); } diff --git a/intern/audaspace/FX/AUD_EnvelopeFactory.h b/intern/audaspace/FX/AUD_EnvelopeFactory.h index c8f3dc37cd2..656212c8cac 100644 --- a/intern/audaspace/FX/AUD_EnvelopeFactory.h +++ b/intern/audaspace/FX/AUD_EnvelopeFactory.h @@ -73,10 +73,10 @@ public: * \param threshold The threshold value. * \param arthreshold The attack/release threshold value. */ - AUD_EnvelopeFactory(AUD_Reference<AUD_IFactory> factory, float attack, float release, + AUD_EnvelopeFactory(boost::shared_ptr<AUD_IFactory> factory, float attack, float release, float threshold, float arthreshold); - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); static sample_t envelopeFilter(AUD_CallbackIIRFilterReader* reader, EnvelopeParameters* param); static void endEnvelopeFilter(EnvelopeParameters* param); diff --git a/intern/audaspace/FX/AUD_FaderFactory.cpp b/intern/audaspace/FX/AUD_FaderFactory.cpp index ec119ef9388..b34d2134385 100644 --- a/intern/audaspace/FX/AUD_FaderFactory.cpp +++ b/intern/audaspace/FX/AUD_FaderFactory.cpp @@ -30,7 +30,7 @@ #include "AUD_FaderFactory.h" #include "AUD_FaderReader.h" -AUD_FaderFactory::AUD_FaderFactory(AUD_Reference<AUD_IFactory> factory, AUD_FadeType type, +AUD_FaderFactory::AUD_FaderFactory(boost::shared_ptr<AUD_IFactory> factory, AUD_FadeType type, float start, float length) : AUD_EffectFactory(factory), m_type(type), @@ -54,7 +54,7 @@ float AUD_FaderFactory::getLength() const return m_length; } -AUD_Reference<AUD_IReader> AUD_FaderFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_FaderFactory::createReader() { - return new AUD_FaderReader(getReader(), m_type, m_start, m_length); + return boost::shared_ptr<AUD_IReader>(new AUD_FaderReader(getReader(), m_type, m_start, m_length)); } diff --git a/intern/audaspace/FX/AUD_FaderFactory.h b/intern/audaspace/FX/AUD_FaderFactory.h index 82eaf2fae9f..f9ad88a751d 100644 --- a/intern/audaspace/FX/AUD_FaderFactory.h +++ b/intern/audaspace/FX/AUD_FaderFactory.h @@ -67,7 +67,7 @@ public: * \param start The time where fading should start in seconds. * \param length How long fading should last in seconds. */ - AUD_FaderFactory(AUD_Reference<AUD_IFactory> factory, + AUD_FaderFactory(boost::shared_ptr<AUD_IFactory> factory, AUD_FadeType type = AUD_FADE_IN, float start = 0.0f, float length = 1.0f); @@ -86,7 +86,7 @@ public: */ float getLength() const; - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif //__AUD_FADERFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_FaderReader.cpp b/intern/audaspace/FX/AUD_FaderReader.cpp index 4ece91ca899..e09072054cb 100644 --- a/intern/audaspace/FX/AUD_FaderReader.cpp +++ b/intern/audaspace/FX/AUD_FaderReader.cpp @@ -31,7 +31,7 @@ #include <cstring> -AUD_FaderReader::AUD_FaderReader(AUD_Reference<AUD_IReader> reader, AUD_FadeType type, +AUD_FaderReader::AUD_FaderReader(boost::shared_ptr<AUD_IReader> reader, AUD_FadeType type, float start,float length) : AUD_EffectReader(reader), m_type(type), diff --git a/intern/audaspace/FX/AUD_FaderReader.h b/intern/audaspace/FX/AUD_FaderReader.h index 788e8539228..a49960b30fb 100644 --- a/intern/audaspace/FX/AUD_FaderReader.h +++ b/intern/audaspace/FX/AUD_FaderReader.h @@ -67,7 +67,7 @@ public: * \param start The time where fading should start in seconds. * \param length How long fading should last in seconds. */ - AUD_FaderReader(AUD_Reference<AUD_IReader> reader, AUD_FadeType type, + AUD_FaderReader(boost::shared_ptr<AUD_IReader> reader, AUD_FadeType type, float start,float length); virtual void read(int& length, bool& eos, sample_t* buffer); diff --git a/intern/audaspace/FX/AUD_HighpassFactory.cpp b/intern/audaspace/FX/AUD_HighpassFactory.cpp index 41070842596..ba5297d21ed 100644 --- a/intern/audaspace/FX/AUD_HighpassFactory.cpp +++ b/intern/audaspace/FX/AUD_HighpassFactory.cpp @@ -36,7 +36,7 @@ #define M_PI 3.14159265358979323846 #endif -AUD_HighpassFactory::AUD_HighpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency, +AUD_HighpassFactory::AUD_HighpassFactory(boost::shared_ptr<AUD_IFactory> factory, float frequency, float Q) : AUD_DynamicIIRFilterFactory(factory), m_frequency(frequency), @@ -48,8 +48,8 @@ void AUD_HighpassFactory::recalculateCoefficients(AUD_SampleRate rate, std::vector<float> &b, std::vector<float> &a) { - float w0 = 2 * M_PI * m_frequency / rate; - float alpha = sin(w0) / (2 * m_Q); + float w0 = 2.0 * M_PI * (AUD_SampleRate)m_frequency / rate; + float alpha = (float)(sin(w0) / (2.0 * (double)m_Q)); float norm = 1 + alpha; float c = cos(w0); a.push_back(1); diff --git a/intern/audaspace/FX/AUD_HighpassFactory.h b/intern/audaspace/FX/AUD_HighpassFactory.h index 66aa8091234..ed7e9db44a4 100644 --- a/intern/audaspace/FX/AUD_HighpassFactory.h +++ b/intern/audaspace/FX/AUD_HighpassFactory.h @@ -59,7 +59,7 @@ public: * \param frequency The cutoff frequency. * \param Q The Q factor. */ - AUD_HighpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency, float Q = 1.0f); + AUD_HighpassFactory(boost::shared_ptr<AUD_IFactory> factory, float frequency, float Q = 1.0f); virtual void recalculateCoefficients(AUD_SampleRate rate, std::vector<float> &b, std::vector<float> &a); }; diff --git a/intern/audaspace/intern/AUD_ReferenceHandler.cpp b/intern/audaspace/FX/AUD_IDynamicIIRFilterCalculator.h index 6aa4f87ea96..77d83360255 100644 --- a/intern/audaspace/intern/AUD_ReferenceHandler.cpp +++ b/intern/audaspace/FX/AUD_IDynamicIIRFilterCalculator.h @@ -22,31 +22,31 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file audaspace/intern/AUD_ReferenceHandler.cpp - * \ingroup audaspaceintern +/** \file audaspace/FX/AUD_IDynamicIIRFilterCalculator.h + * \ingroup audfx */ -#include "AUD_Reference.h" +#ifndef AUD_IDYNAMICIIRFILTERCALCULATOR_H +#define AUD_IDYNAMICIIRFILTERCALCULATOR_H -std::map<void*, unsigned int> AUD_ReferenceHandler::m_references; -pthread_mutex_t AUD_ReferenceHandler::m_mutex; -bool AUD_ReferenceHandler::m_mutex_initialised = false; +#include <vector> -pthread_mutex_t *AUD_ReferenceHandler::getMutex() +/** + * This interface calculates dynamic filter coefficients which depend on the + * sampling rate for AUD_DynamicIIRFilterReaders. + */ +class AUD_IDynamicIIRFilterCalculator { - if(!m_mutex_initialised) - { - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - - pthread_mutex_init(&m_mutex, &attr); - - pthread_mutexattr_destroy(&attr); - - m_mutex_initialised = true; - } - - return &m_mutex; -} - +public: + /** + * Recalculates the filter coefficients. + * \param rate The sample rate of the audio data. + * \param[out] b The input filter coefficients. + * \param[out] a The output filter coefficients. + */ + virtual void recalculateCoefficients(AUD_SampleRate rate, + std::vector<float>& b, + std::vector<float>& a)=0; +}; + +#endif // AUD_IDYNAMICIIRFILTERCALCULATOR_H diff --git a/intern/audaspace/FX/AUD_IIRFilterFactory.cpp b/intern/audaspace/FX/AUD_IIRFilterFactory.cpp index 807b0ef4899..c4f94a2dc27 100644 --- a/intern/audaspace/FX/AUD_IIRFilterFactory.cpp +++ b/intern/audaspace/FX/AUD_IIRFilterFactory.cpp @@ -30,14 +30,14 @@ #include "AUD_IIRFilterFactory.h" #include "AUD_IIRFilterReader.h" -AUD_IIRFilterFactory::AUD_IIRFilterFactory(AUD_Reference<AUD_IFactory> factory, +AUD_IIRFilterFactory::AUD_IIRFilterFactory(boost::shared_ptr<AUD_IFactory> factory, std::vector<float> b, std::vector<float> a) : AUD_EffectFactory(factory), m_a(a), m_b(b) { } -AUD_Reference<AUD_IReader> AUD_IIRFilterFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_IIRFilterFactory::createReader() { - return new AUD_IIRFilterReader(getReader(), m_b, m_a); + return boost::shared_ptr<AUD_IReader>(new AUD_IIRFilterReader(getReader(), m_b, m_a)); } diff --git a/intern/audaspace/FX/AUD_IIRFilterFactory.h b/intern/audaspace/FX/AUD_IIRFilterFactory.h index 43256a166aa..0b55c120384 100644 --- a/intern/audaspace/FX/AUD_IIRFilterFactory.h +++ b/intern/audaspace/FX/AUD_IIRFilterFactory.h @@ -31,6 +31,7 @@ #define __AUD_IIRFILTERFACTORY_H__ #include "AUD_EffectFactory.h" +#include "AUD_IDynamicIIRFilterCalculator.h" #include <vector> @@ -61,10 +62,10 @@ public: * \param b The input filter coefficients. * \param a The output filter coefficients. */ - AUD_IIRFilterFactory(AUD_Reference<AUD_IFactory> factory, std::vector<float> b, + AUD_IIRFilterFactory(boost::shared_ptr<AUD_IFactory> factory, std::vector<float> b, std::vector<float> a); - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif //__AUD_IIRFILTERFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_IIRFilterReader.cpp b/intern/audaspace/FX/AUD_IIRFilterReader.cpp index 8f78c110d1f..6716e6b9ddc 100644 --- a/intern/audaspace/FX/AUD_IIRFilterReader.cpp +++ b/intern/audaspace/FX/AUD_IIRFilterReader.cpp @@ -29,7 +29,7 @@ #include "AUD_IIRFilterReader.h" -AUD_IIRFilterReader::AUD_IIRFilterReader(AUD_Reference<AUD_IReader> reader, +AUD_IIRFilterReader::AUD_IIRFilterReader(boost::shared_ptr<AUD_IReader> reader, const std::vector<float>& b, const std::vector<float>& a) : AUD_BaseIIRFilterReader(reader, b.size(), a.size()), m_a(a), m_b(b) diff --git a/intern/audaspace/FX/AUD_IIRFilterReader.h b/intern/audaspace/FX/AUD_IIRFilterReader.h index d9be52f2919..d663805b50f 100644 --- a/intern/audaspace/FX/AUD_IIRFilterReader.h +++ b/intern/audaspace/FX/AUD_IIRFilterReader.h @@ -61,7 +61,7 @@ public: * \param b The input filter coefficients. * \param a The output filter coefficients. */ - AUD_IIRFilterReader(AUD_Reference<AUD_IReader> reader, const std::vector<float>& b, + AUD_IIRFilterReader(boost::shared_ptr<AUD_IReader> reader, const std::vector<float>& b, const std::vector<float>& a); virtual sample_t filter(); diff --git a/intern/audaspace/FX/AUD_LimiterFactory.cpp b/intern/audaspace/FX/AUD_LimiterFactory.cpp index e58657d8d70..679ed3a6b8b 100644 --- a/intern/audaspace/FX/AUD_LimiterFactory.cpp +++ b/intern/audaspace/FX/AUD_LimiterFactory.cpp @@ -31,7 +31,7 @@ #include "AUD_LimiterReader.h" #include "AUD_Space.h" -AUD_LimiterFactory::AUD_LimiterFactory(AUD_Reference<AUD_IFactory> factory, +AUD_LimiterFactory::AUD_LimiterFactory(boost::shared_ptr<AUD_IFactory> factory, float start, float end) : AUD_EffectFactory(factory), m_start(start), @@ -49,7 +49,7 @@ float AUD_LimiterFactory::getEnd() const return m_end; } -AUD_Reference<AUD_IReader> AUD_LimiterFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_LimiterFactory::createReader() { - return new AUD_LimiterReader(getReader(), m_start, m_end); + return boost::shared_ptr<AUD_IReader>(new AUD_LimiterReader(getReader(), m_start, m_end)); } diff --git a/intern/audaspace/FX/AUD_LimiterFactory.h b/intern/audaspace/FX/AUD_LimiterFactory.h index ddc8183ce7a..0376952b4bd 100644 --- a/intern/audaspace/FX/AUD_LimiterFactory.h +++ b/intern/audaspace/FX/AUD_LimiterFactory.h @@ -60,7 +60,7 @@ public: * \param end The desired end time, a negative value signals that it should * play to the end. */ - AUD_LimiterFactory(AUD_Reference<AUD_IFactory> factory, + AUD_LimiterFactory(boost::shared_ptr<AUD_IFactory> factory, float start = 0, float end = -1); /** @@ -73,7 +73,7 @@ public: */ float getEnd() const; - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif //__AUD_LIMITERFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_LimiterReader.cpp b/intern/audaspace/FX/AUD_LimiterReader.cpp index 0abf496c7f9..9c1d4443b06 100644 --- a/intern/audaspace/FX/AUD_LimiterReader.cpp +++ b/intern/audaspace/FX/AUD_LimiterReader.cpp @@ -30,7 +30,7 @@ #include "AUD_LimiterReader.h" #include "AUD_Buffer.h" -AUD_LimiterReader::AUD_LimiterReader(AUD_Reference<AUD_IReader> reader, +AUD_LimiterReader::AUD_LimiterReader(boost::shared_ptr<AUD_IReader> reader, float start, float end) : AUD_EffectReader(reader), m_start(start), diff --git a/intern/audaspace/FX/AUD_LimiterReader.h b/intern/audaspace/FX/AUD_LimiterReader.h index 34c4ea7c20e..607eb9e5bec 100644 --- a/intern/audaspace/FX/AUD_LimiterReader.h +++ b/intern/audaspace/FX/AUD_LimiterReader.h @@ -60,7 +60,7 @@ public: * \param end The desired end time (sample exklusive), a negative value * signals that it should play to the end. */ - AUD_LimiterReader(AUD_Reference<AUD_IReader> reader, float start = 0, float end = -1); + AUD_LimiterReader(boost::shared_ptr<AUD_IReader> reader, float start = 0, float end = -1); virtual void seek(int position); virtual int getLength() const; diff --git a/intern/audaspace/FX/AUD_LoopFactory.cpp b/intern/audaspace/FX/AUD_LoopFactory.cpp index 32c9e6bad7f..a9e83e349a0 100644 --- a/intern/audaspace/FX/AUD_LoopFactory.cpp +++ b/intern/audaspace/FX/AUD_LoopFactory.cpp @@ -30,7 +30,7 @@ #include "AUD_LoopFactory.h" #include "AUD_LoopReader.h" -AUD_LoopFactory::AUD_LoopFactory(AUD_Reference<AUD_IFactory> factory, int loop) : +AUD_LoopFactory::AUD_LoopFactory(boost::shared_ptr<AUD_IFactory> factory, int loop) : AUD_EffectFactory(factory), m_loop(loop) { @@ -41,7 +41,7 @@ int AUD_LoopFactory::getLoop() const return m_loop; } -AUD_Reference<AUD_IReader> AUD_LoopFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_LoopFactory::createReader() { - return new AUD_LoopReader(getReader(), m_loop); + return boost::shared_ptr<AUD_IReader>(new AUD_LoopReader(getReader(), m_loop)); } diff --git a/intern/audaspace/FX/AUD_LoopFactory.h b/intern/audaspace/FX/AUD_LoopFactory.h index 754b780bd99..570536bee9a 100644 --- a/intern/audaspace/FX/AUD_LoopFactory.h +++ b/intern/audaspace/FX/AUD_LoopFactory.h @@ -55,14 +55,14 @@ public: * \param loop The desired loop count, negative values result in endless * looping. */ - AUD_LoopFactory(AUD_Reference<AUD_IFactory> factory, int loop = -1); + AUD_LoopFactory(boost::shared_ptr<AUD_IFactory> factory, int loop = -1); /** * Returns the loop count. */ int getLoop() const; - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif //__AUD_LOOPFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_LoopReader.cpp b/intern/audaspace/FX/AUD_LoopReader.cpp index 863f66f9f46..6fbcaa5af37 100644 --- a/intern/audaspace/FX/AUD_LoopReader.cpp +++ b/intern/audaspace/FX/AUD_LoopReader.cpp @@ -32,7 +32,7 @@ #include <cstring> -AUD_LoopReader::AUD_LoopReader(AUD_Reference<AUD_IReader> reader, int loop) : +AUD_LoopReader::AUD_LoopReader(boost::shared_ptr<AUD_IReader> reader, int loop) : AUD_EffectReader(reader), m_count(loop), m_left(loop) { } diff --git a/intern/audaspace/FX/AUD_LoopReader.h b/intern/audaspace/FX/AUD_LoopReader.h index fd2dd71d78f..12b8078b12d 100644 --- a/intern/audaspace/FX/AUD_LoopReader.h +++ b/intern/audaspace/FX/AUD_LoopReader.h @@ -61,7 +61,7 @@ public: * \param loop The desired loop count, negative values result in endless * looping. */ - AUD_LoopReader(AUD_Reference<AUD_IReader> reader, int loop); + AUD_LoopReader(boost::shared_ptr<AUD_IReader> reader, int loop); virtual void seek(int position); virtual int getLength() const; diff --git a/intern/audaspace/FX/AUD_LowpassFactory.cpp b/intern/audaspace/FX/AUD_LowpassFactory.cpp index 14dbc951c7f..e2faa241ac9 100644 --- a/intern/audaspace/FX/AUD_LowpassFactory.cpp +++ b/intern/audaspace/FX/AUD_LowpassFactory.cpp @@ -36,7 +36,7 @@ #define M_PI 3.14159265358979323846 #endif -AUD_LowpassFactory::AUD_LowpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency, +AUD_LowpassFactory::AUD_LowpassFactory(boost::shared_ptr<AUD_IFactory> factory, float frequency, float Q) : AUD_DynamicIIRFilterFactory(factory), m_frequency(frequency), diff --git a/intern/audaspace/FX/AUD_LowpassFactory.h b/intern/audaspace/FX/AUD_LowpassFactory.h index 7e98720a2db..fdbc6e5d91d 100644 --- a/intern/audaspace/FX/AUD_LowpassFactory.h +++ b/intern/audaspace/FX/AUD_LowpassFactory.h @@ -59,7 +59,7 @@ public: * \param frequency The cutoff frequency. * \param Q The Q factor. */ - AUD_LowpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency, float Q = 1.0f); + AUD_LowpassFactory(boost::shared_ptr<AUD_IFactory> factory, float frequency, float Q = 1.0f); virtual void recalculateCoefficients(AUD_SampleRate rate, std::vector<float> &b, std::vector<float> &a); }; diff --git a/intern/audaspace/FX/AUD_PingPongFactory.cpp b/intern/audaspace/FX/AUD_PingPongFactory.cpp index 3d5011cf47b..84e4b29415e 100644 --- a/intern/audaspace/FX/AUD_PingPongFactory.cpp +++ b/intern/audaspace/FX/AUD_PingPongFactory.cpp @@ -31,16 +31,16 @@ #include "AUD_DoubleReader.h" #include "AUD_ReverseFactory.h" -AUD_PingPongFactory::AUD_PingPongFactory(AUD_Reference<AUD_IFactory> factory) : +AUD_PingPongFactory::AUD_PingPongFactory(boost::shared_ptr<AUD_IFactory> factory) : AUD_EffectFactory(factory) { } -AUD_Reference<AUD_IReader> AUD_PingPongFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_PingPongFactory::createReader() { - AUD_Reference<AUD_IReader> reader = getReader(); + boost::shared_ptr<AUD_IReader> reader = getReader(); AUD_ReverseFactory factory(m_factory); - AUD_Reference<AUD_IReader> reader2 = factory.createReader(); + boost::shared_ptr<AUD_IReader> reader2 = factory.createReader(); - return new AUD_DoubleReader(reader, reader2); + return boost::shared_ptr<AUD_IReader>(new AUD_DoubleReader(reader, reader2)); } diff --git a/intern/audaspace/FX/AUD_PingPongFactory.h b/intern/audaspace/FX/AUD_PingPongFactory.h index f25624a7c5e..e8ee5c9e389 100644 --- a/intern/audaspace/FX/AUD_PingPongFactory.h +++ b/intern/audaspace/FX/AUD_PingPongFactory.h @@ -48,9 +48,9 @@ public: * Creates a new ping pong factory. * \param factory The input factory. */ - AUD_PingPongFactory(AUD_Reference<AUD_IFactory> factory); + AUD_PingPongFactory(boost::shared_ptr<AUD_IFactory> factory); - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif //__AUD_PINGPONGFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_PitchFactory.cpp b/intern/audaspace/FX/AUD_PitchFactory.cpp index c6e9ae0b457..9dc27a58162 100644 --- a/intern/audaspace/FX/AUD_PitchFactory.cpp +++ b/intern/audaspace/FX/AUD_PitchFactory.cpp @@ -31,13 +31,13 @@ #include "AUD_PitchReader.h" #include "AUD_Space.h" -AUD_PitchFactory::AUD_PitchFactory(AUD_Reference<AUD_IFactory> factory, float pitch) : +AUD_PitchFactory::AUD_PitchFactory(boost::shared_ptr<AUD_IFactory> factory, float pitch) : AUD_EffectFactory(factory), m_pitch(pitch) { } -AUD_Reference<AUD_IReader> AUD_PitchFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_PitchFactory::createReader() { - return new AUD_PitchReader(getReader(), m_pitch); + return boost::shared_ptr<AUD_IReader>(new AUD_PitchReader(getReader(), m_pitch)); } diff --git a/intern/audaspace/FX/AUD_PitchFactory.h b/intern/audaspace/FX/AUD_PitchFactory.h index 5ad37ad1a6c..159388b28dd 100644 --- a/intern/audaspace/FX/AUD_PitchFactory.h +++ b/intern/audaspace/FX/AUD_PitchFactory.h @@ -53,9 +53,9 @@ public: * \param factory The input factory. * \param pitch The desired pitch. */ - AUD_PitchFactory(AUD_Reference<AUD_IFactory> factory, float pitch); + AUD_PitchFactory(boost::shared_ptr<AUD_IFactory> factory, float pitch); - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif //__AUD_PITCHFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_PitchReader.cpp b/intern/audaspace/FX/AUD_PitchReader.cpp index 0d1ff012e73..218af4fc090 100644 --- a/intern/audaspace/FX/AUD_PitchReader.cpp +++ b/intern/audaspace/FX/AUD_PitchReader.cpp @@ -29,7 +29,7 @@ #include "AUD_PitchReader.h" -AUD_PitchReader::AUD_PitchReader(AUD_Reference<AUD_IReader> reader, float pitch) : +AUD_PitchReader::AUD_PitchReader(boost::shared_ptr<AUD_IReader> reader, float pitch) : AUD_EffectReader(reader), m_pitch(pitch) { } diff --git a/intern/audaspace/FX/AUD_PitchReader.h b/intern/audaspace/FX/AUD_PitchReader.h index 3185bfdf30b..d22e589b05d 100644 --- a/intern/audaspace/FX/AUD_PitchReader.h +++ b/intern/audaspace/FX/AUD_PitchReader.h @@ -53,7 +53,7 @@ public: * \param reader The reader to read from. * \param pitch The pitch value. */ - AUD_PitchReader(AUD_Reference<AUD_IReader> reader, float pitch); + AUD_PitchReader(boost::shared_ptr<AUD_IReader> reader, float pitch); virtual AUD_Specs getSpecs() const; diff --git a/intern/audaspace/FX/AUD_RectifyFactory.cpp b/intern/audaspace/FX/AUD_RectifyFactory.cpp index ad01f404698..26bb5615dad 100644 --- a/intern/audaspace/FX/AUD_RectifyFactory.cpp +++ b/intern/audaspace/FX/AUD_RectifyFactory.cpp @@ -37,12 +37,12 @@ sample_t AUD_RectifyFactory::rectifyFilter(AUD_CallbackIIRFilterReader* reader, return fabs(reader->x(0)); } -AUD_RectifyFactory::AUD_RectifyFactory(AUD_Reference<AUD_IFactory> factory) : +AUD_RectifyFactory::AUD_RectifyFactory(boost::shared_ptr<AUD_IFactory> factory) : AUD_EffectFactory(factory) { } -AUD_Reference<AUD_IReader> AUD_RectifyFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_RectifyFactory::createReader() { - return new AUD_CallbackIIRFilterReader(getReader(), 1, 1, rectifyFilter); + return boost::shared_ptr<AUD_IReader>(new AUD_CallbackIIRFilterReader(getReader(), 1, 1, rectifyFilter)); } diff --git a/intern/audaspace/FX/AUD_RectifyFactory.h b/intern/audaspace/FX/AUD_RectifyFactory.h index 5ad41d424d9..eb595e43e4f 100644 --- a/intern/audaspace/FX/AUD_RectifyFactory.h +++ b/intern/audaspace/FX/AUD_RectifyFactory.h @@ -48,9 +48,9 @@ public: * Creates a new rectify factory. * \param factory The input factory. */ - AUD_RectifyFactory(AUD_Reference<AUD_IFactory> factory); + AUD_RectifyFactory(boost::shared_ptr<AUD_IFactory> factory); - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); static sample_t rectifyFilter(AUD_CallbackIIRFilterReader* reader, void* useless); }; diff --git a/intern/audaspace/FX/AUD_ReverseFactory.cpp b/intern/audaspace/FX/AUD_ReverseFactory.cpp index 063cbc88180..afb4ad2bec9 100644 --- a/intern/audaspace/FX/AUD_ReverseFactory.cpp +++ b/intern/audaspace/FX/AUD_ReverseFactory.cpp @@ -31,12 +31,12 @@ #include "AUD_ReverseReader.h" #include "AUD_Space.h" -AUD_ReverseFactory::AUD_ReverseFactory(AUD_Reference<AUD_IFactory> factory) : +AUD_ReverseFactory::AUD_ReverseFactory(boost::shared_ptr<AUD_IFactory> factory) : AUD_EffectFactory(factory) { } -AUD_Reference<AUD_IReader> AUD_ReverseFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_ReverseFactory::createReader() { - return new AUD_ReverseReader(getReader()); + return boost::shared_ptr<AUD_IReader>(new AUD_ReverseReader(getReader())); } diff --git a/intern/audaspace/FX/AUD_ReverseFactory.h b/intern/audaspace/FX/AUD_ReverseFactory.h index e2d75dc560a..5b0c9e3c29a 100644 --- a/intern/audaspace/FX/AUD_ReverseFactory.h +++ b/intern/audaspace/FX/AUD_ReverseFactory.h @@ -48,9 +48,9 @@ public: * Creates a new reverse factory. * \param factory The input factory. */ - AUD_ReverseFactory(AUD_Reference<AUD_IFactory> factory); + AUD_ReverseFactory(boost::shared_ptr<AUD_IFactory> factory); - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif //__AUD_REVERSEFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_ReverseReader.cpp b/intern/audaspace/FX/AUD_ReverseReader.cpp index 6b454c66d25..c0a5962a299 100644 --- a/intern/audaspace/FX/AUD_ReverseReader.cpp +++ b/intern/audaspace/FX/AUD_ReverseReader.cpp @@ -34,7 +34,7 @@ static const char* props_error = "AUD_ReverseReader: The reader has to be " "seekable and a finite length."; -AUD_ReverseReader::AUD_ReverseReader(AUD_Reference<AUD_IReader> reader) : +AUD_ReverseReader::AUD_ReverseReader(boost::shared_ptr<AUD_IReader> reader) : AUD_EffectReader(reader), m_length(reader->getLength()), m_position(0) diff --git a/intern/audaspace/FX/AUD_ReverseReader.h b/intern/audaspace/FX/AUD_ReverseReader.h index d1e5179b8ec..219047915bd 100644 --- a/intern/audaspace/FX/AUD_ReverseReader.h +++ b/intern/audaspace/FX/AUD_ReverseReader.h @@ -61,7 +61,7 @@ public: * \exception AUD_Exception Thrown if the reader specified has an * undeterminable/infinite length or is not seekable. */ - AUD_ReverseReader(AUD_Reference<AUD_IReader> reader); + AUD_ReverseReader(boost::shared_ptr<AUD_IReader> reader); virtual void seek(int position); virtual int getLength() const; diff --git a/intern/audaspace/FX/AUD_SquareFactory.cpp b/intern/audaspace/FX/AUD_SquareFactory.cpp index 7aabdb775f6..4b4dccb6e6b 100644 --- a/intern/audaspace/FX/AUD_SquareFactory.cpp +++ b/intern/audaspace/FX/AUD_SquareFactory.cpp @@ -46,7 +46,7 @@ void AUD_SquareFactory::endSquareFilter(float* threshold) delete threshold; } -AUD_SquareFactory::AUD_SquareFactory(AUD_Reference<AUD_IFactory> factory, float threshold) : +AUD_SquareFactory::AUD_SquareFactory(boost::shared_ptr<AUD_IFactory> factory, float threshold) : AUD_EffectFactory(factory), m_threshold(threshold) { @@ -57,10 +57,10 @@ float AUD_SquareFactory::getThreshold() const return m_threshold; } -AUD_Reference<AUD_IReader> AUD_SquareFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_SquareFactory::createReader() { - return new AUD_CallbackIIRFilterReader(getReader(), 1, 1, + return boost::shared_ptr<AUD_IReader>(new AUD_CallbackIIRFilterReader(getReader(), 1, 1, (doFilterIIR) squareFilter, (endFilterIIR) endSquareFilter, - new float(m_threshold)); + new float(m_threshold))); } diff --git a/intern/audaspace/FX/AUD_SquareFactory.h b/intern/audaspace/FX/AUD_SquareFactory.h index 9c0dea25d2b..27e62b6f4cc 100644 --- a/intern/audaspace/FX/AUD_SquareFactory.h +++ b/intern/audaspace/FX/AUD_SquareFactory.h @@ -54,14 +54,14 @@ public: * \param factory The input factory. * \param threshold The threshold. */ - AUD_SquareFactory(AUD_Reference<AUD_IFactory> factory, float threshold = 0.0f); + AUD_SquareFactory(boost::shared_ptr<AUD_IFactory> factory, float threshold = 0.0f); /** * Returns the threshold. */ float getThreshold() const; - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); static sample_t squareFilter(AUD_CallbackIIRFilterReader* reader, float* threshold); static void endSquareFilter(float* threshold); diff --git a/intern/audaspace/FX/AUD_SumFactory.cpp b/intern/audaspace/FX/AUD_SumFactory.cpp index b58c44b0171..7f82233a0b7 100644 --- a/intern/audaspace/FX/AUD_SumFactory.cpp +++ b/intern/audaspace/FX/AUD_SumFactory.cpp @@ -30,16 +30,16 @@ #include "AUD_SumFactory.h" #include "AUD_IIRFilterReader.h" -AUD_SumFactory::AUD_SumFactory(AUD_Reference<AUD_IFactory> factory) : +AUD_SumFactory::AUD_SumFactory(boost::shared_ptr<AUD_IFactory> factory) : AUD_EffectFactory(factory) { } -AUD_Reference<AUD_IReader> AUD_SumFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_SumFactory::createReader() { std::vector<float> a, b; a.push_back(1); a.push_back(-1); b.push_back(1); - return new AUD_IIRFilterReader(getReader(), b, a); + return boost::shared_ptr<AUD_IReader>(new AUD_IIRFilterReader(getReader(), b, a)); } diff --git a/intern/audaspace/FX/AUD_SumFactory.h b/intern/audaspace/FX/AUD_SumFactory.h index ec17faf3fb2..a916f3509cb 100644 --- a/intern/audaspace/FX/AUD_SumFactory.h +++ b/intern/audaspace/FX/AUD_SumFactory.h @@ -47,9 +47,9 @@ public: * Creates a new sum factory. * \param factory The input factory. */ - AUD_SumFactory(AUD_Reference<AUD_IFactory> factory); + AUD_SumFactory(boost::shared_ptr<AUD_IFactory> factory); - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif //__AUD_SUMFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_SuperposeFactory.cpp b/intern/audaspace/FX/AUD_SuperposeFactory.cpp index 30c57198c73..3efad37a5b3 100644 --- a/intern/audaspace/FX/AUD_SuperposeFactory.cpp +++ b/intern/audaspace/FX/AUD_SuperposeFactory.cpp @@ -30,15 +30,15 @@ #include "AUD_SuperposeFactory.h" #include "AUD_SuperposeReader.h" -AUD_SuperposeFactory::AUD_SuperposeFactory(AUD_Reference<AUD_IFactory> factory1, AUD_Reference<AUD_IFactory> factory2) : +AUD_SuperposeFactory::AUD_SuperposeFactory(boost::shared_ptr<AUD_IFactory> factory1, boost::shared_ptr<AUD_IFactory> factory2) : m_factory1(factory1), m_factory2(factory2) { } -AUD_Reference<AUD_IReader> AUD_SuperposeFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_SuperposeFactory::createReader() { - AUD_Reference<AUD_IReader> reader1 = m_factory1->createReader(); - AUD_Reference<AUD_IReader> reader2 = m_factory2->createReader(); + boost::shared_ptr<AUD_IReader> reader1 = m_factory1->createReader(); + boost::shared_ptr<AUD_IReader> reader2 = m_factory2->createReader(); - return new AUD_SuperposeReader(reader1, reader2); + return boost::shared_ptr<AUD_IReader>(new AUD_SuperposeReader(reader1, reader2)); } diff --git a/intern/audaspace/FX/AUD_SuperposeFactory.h b/intern/audaspace/FX/AUD_SuperposeFactory.h index 2da8e34496d..caa0dfb752f 100644 --- a/intern/audaspace/FX/AUD_SuperposeFactory.h +++ b/intern/audaspace/FX/AUD_SuperposeFactory.h @@ -43,12 +43,12 @@ private: /** * First played factory. */ - AUD_Reference<AUD_IFactory> m_factory1; + boost::shared_ptr<AUD_IFactory> m_factory1; /** * Second played factory. */ - AUD_Reference<AUD_IFactory> m_factory2; + boost::shared_ptr<AUD_IFactory> m_factory2; // hide copy constructor and operator= AUD_SuperposeFactory(const AUD_SuperposeFactory&); @@ -60,9 +60,9 @@ public: * \param factory1 The first input factory. * \param factory2 The second input factory. */ - AUD_SuperposeFactory(AUD_Reference<AUD_IFactory> factory1, AUD_Reference<AUD_IFactory> factory2); + AUD_SuperposeFactory(boost::shared_ptr<AUD_IFactory> factory1, boost::shared_ptr<AUD_IFactory> factory2); - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif //__AUD_SUPERPOSEFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_SuperposeReader.cpp b/intern/audaspace/FX/AUD_SuperposeReader.cpp index 535d3590a8f..294a48b3e7a 100644 --- a/intern/audaspace/FX/AUD_SuperposeReader.cpp +++ b/intern/audaspace/FX/AUD_SuperposeReader.cpp @@ -34,7 +34,7 @@ static const char* specs_error = "AUD_SuperposeReader: Both readers have to " "have the same specs."; -AUD_SuperposeReader::AUD_SuperposeReader(AUD_Reference<AUD_IReader> reader1, AUD_Reference<AUD_IReader> reader2) : +AUD_SuperposeReader::AUD_SuperposeReader(boost::shared_ptr<AUD_IReader> reader1, boost::shared_ptr<AUD_IReader> reader2) : m_reader1(reader1), m_reader2(reader2) { } diff --git a/intern/audaspace/FX/AUD_SuperposeReader.h b/intern/audaspace/FX/AUD_SuperposeReader.h index d0fde13a267..a04ab90fe43 100644 --- a/intern/audaspace/FX/AUD_SuperposeReader.h +++ b/intern/audaspace/FX/AUD_SuperposeReader.h @@ -32,7 +32,8 @@ #include "AUD_IReader.h" #include "AUD_Buffer.h" -#include "AUD_Reference.h" + +#include <boost/shared_ptr.hpp> /** * This reader plays two readers with the same specs in parallel. @@ -43,12 +44,12 @@ private: /** * The first reader. */ - AUD_Reference<AUD_IReader> m_reader1; + boost::shared_ptr<AUD_IReader> m_reader1; /** * The second reader. */ - AUD_Reference<AUD_IReader> m_reader2; + boost::shared_ptr<AUD_IReader> m_reader2; /** * Buffer used for mixing. @@ -66,7 +67,7 @@ public: * \param reader2 The second reader to read from. * \exception AUD_Exception Thrown if the specs from the readers differ. */ - AUD_SuperposeReader(AUD_Reference<AUD_IReader> reader1, AUD_Reference<AUD_IReader> reader2); + AUD_SuperposeReader(boost::shared_ptr<AUD_IReader> reader1, boost::shared_ptr<AUD_IReader> reader2); /** * Destroys the reader. diff --git a/intern/audaspace/FX/AUD_VolumeFactory.cpp b/intern/audaspace/FX/AUD_VolumeFactory.cpp index f5e635eec2d..4f0e1e425e6 100644 --- a/intern/audaspace/FX/AUD_VolumeFactory.cpp +++ b/intern/audaspace/FX/AUD_VolumeFactory.cpp @@ -30,7 +30,7 @@ #include "AUD_VolumeFactory.h" #include "AUD_IIRFilterReader.h" -AUD_VolumeFactory::AUD_VolumeFactory(AUD_Reference<AUD_IFactory> factory, float volume) : +AUD_VolumeFactory::AUD_VolumeFactory(boost::shared_ptr<AUD_IFactory> factory, float volume) : AUD_EffectFactory(factory), m_volume(volume) { @@ -41,10 +41,10 @@ float AUD_VolumeFactory::getVolume() const return m_volume; } -AUD_Reference<AUD_IReader> AUD_VolumeFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_VolumeFactory::createReader() { std::vector<float> a, b; a.push_back(1); b.push_back(m_volume); - return new AUD_IIRFilterReader(getReader(), b, a); + return boost::shared_ptr<AUD_IReader>(new AUD_IIRFilterReader(getReader(), b, a)); } diff --git a/intern/audaspace/FX/AUD_VolumeFactory.h b/intern/audaspace/FX/AUD_VolumeFactory.h index b12838373b3..6fe779ffb88 100644 --- a/intern/audaspace/FX/AUD_VolumeFactory.h +++ b/intern/audaspace/FX/AUD_VolumeFactory.h @@ -55,7 +55,7 @@ public: * \param factory The input factory. * \param volume The desired volume. */ - AUD_VolumeFactory(AUD_Reference<AUD_IFactory> factory, float volume); + AUD_VolumeFactory(boost::shared_ptr<AUD_IFactory> factory, float volume); /** * Returns the volume. @@ -63,7 +63,7 @@ public: */ float getVolume() const; - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif //__AUD_VOLUMEFACTORY_H__ diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp index f68d41f6a1c..371e0007bd3 100644 --- a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp +++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp @@ -31,6 +31,7 @@ #include "AUD_IFactory.h" #include "AUD_IReader.h" #include "AUD_ConverterReader.h" +#include "AUD_MutexLock.h" #include <cstring> #include <limits> @@ -66,7 +67,7 @@ static const char* queue_error = "AUD_OpenALDevice: Buffer couldn't be " static const char* bufferdata_error = "AUD_OpenALDevice: Buffer couldn't be " "filled with data."; -AUD_OpenALDevice::AUD_OpenALHandle::AUD_OpenALHandle(AUD_OpenALDevice* device, ALenum format, AUD_Reference<AUD_IReader> reader, bool keep) : +AUD_OpenALDevice::AUD_OpenALHandle::AUD_OpenALHandle(AUD_OpenALDevice* device, ALenum format, boost::shared_ptr<AUD_IReader> reader, bool keep) : m_isBuffered(false), m_reader(reader), m_keep(keep), m_format(format), m_current(0), m_eos(false), m_loopcount(0), m_stop(NULL), m_stop_data(NULL), m_status(AUD_STATUS_PLAYING), m_device(device) @@ -125,22 +126,27 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::pause() { if(m_status) { - m_device->lock(); + AUD_MutexLock lock(*m_device); if(m_status == AUD_STATUS_PLAYING) { - m_device->m_playingSounds.remove(this); - m_device->m_pausedSounds.push_back(this); + for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++) + { + if(it->get() == this) + { + boost::shared_ptr<AUD_OpenALHandle> This = *it; - alSourcePause(m_source); + m_device->m_playingSounds.erase(it); + m_device->m_pausedSounds.push_back(This); - m_status = AUD_STATUS_PAUSED; - m_device->unlock(); + alSourcePause(m_source); - return true; - } + m_status = AUD_STATUS_PAUSED; - m_device->unlock(); + return true; + } + } + } } return false; @@ -150,20 +156,26 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::resume() { if(m_status) { - m_device->lock(); + AUD_MutexLock lock(*m_device); if(m_status == AUD_STATUS_PAUSED) { - m_device->m_pausedSounds.remove(this); - m_device->m_playingSounds.push_back(this); + for(AUD_HandleIterator it = m_device->m_pausedSounds.begin(); it != m_device->m_pausedSounds.end(); it++) + { + if(it->get() == this) + { + boost::shared_ptr<AUD_OpenALHandle> This = *it; - m_device->start(); - m_status = AUD_STATUS_PLAYING; - m_device->unlock(); - return true; - } + m_device->m_pausedSounds.erase(it); + m_device->m_playingSounds.push_back(This); + + m_device->start(); + m_status = AUD_STATUS_PLAYING; - m_device->unlock(); + return true; + } + } + } } return false; @@ -174,25 +186,39 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::stop() if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - // AUD_XXX Create a reference of our own object so that it doesn't get - // deleted before the end of this function - AUD_Reference<AUD_OpenALHandle> This = this; - - if(m_status == AUD_STATUS_PLAYING) - m_device->m_playingSounds.remove(This); - else - m_device->m_pausedSounds.remove(This); + if(!m_status) + return false; - m_device->unlock(); + m_status = AUD_STATUS_INVALID; alDeleteSources(1, &m_source); if(!m_isBuffered) alDeleteBuffers(CYCLE_BUFFERS, m_buffers); - m_status = AUD_STATUS_INVALID; - return true; + for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++) + { + if(it->get() == this) + { + boost::shared_ptr<AUD_OpenALHandle> This = *it; + + m_device->m_playingSounds.erase(it); + + return true; + } + } + + for(AUD_HandleIterator it = m_device->m_pausedSounds.begin(); it != m_device->m_pausedSounds.end(); it++) + { + if(it->get() == this) + { + m_device->m_pausedSounds.erase(it); + return true; + } + } + + return false; } bool AUD_OpenALDevice::AUD_OpenALHandle::getKeep() @@ -208,11 +234,12 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setKeep(bool keep) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - m_keep = keep; + if(!m_status) + return false; - m_device->unlock(); + m_keep = keep; return true; } @@ -222,7 +249,10 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::seek(float position) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; if(m_isBuffered) alSourcef(m_source, AL_SEC_OFFSET, position); @@ -272,17 +302,18 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::seek(float position) } } - m_device->unlock(); - return true; } float AUD_OpenALDevice::AUD_OpenALHandle::getPosition() { if(!m_status) - return 0.0f; + return false; + + AUD_MutexLock lock(*m_device); - m_device->lock(); + if(!m_status) + return 0.0f; float position = 0.0f; @@ -295,8 +326,6 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getPosition() CYCLE_BUFFERS) / (float)specs.rate; } - m_device->unlock(); - return position; } @@ -310,13 +339,14 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getVolume() float result = std::numeric_limits<float>::quiet_NaN(); if(!m_status) - return result; + return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alGetSourcef(m_source, AL_GAIN, &result); + if(!m_status) + return result; - m_device->unlock(); + alGetSourcef(m_source, AL_GAIN, &result); return result; } @@ -326,11 +356,12 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setVolume(float volume) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alSourcef(m_source, AL_GAIN, volume); + if(!m_status) + return false; - m_device->unlock(); + alSourcef(m_source, AL_GAIN, volume); return true; } @@ -340,13 +371,14 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getPitch() float result = std::numeric_limits<float>::quiet_NaN(); if(!m_status) - return result; + return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alGetSourcef(m_source, AL_PITCH, &result); + if(!m_status) + return result; - m_device->unlock(); + alGetSourcef(m_source, AL_PITCH, &result); return result; } @@ -356,11 +388,12 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setPitch(float pitch) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alSourcef(m_source, AL_PITCH, pitch); + if(!m_status) + return false; - m_device->unlock(); + alSourcef(m_source, AL_PITCH, pitch); return true; } @@ -385,13 +418,14 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setStopCallback(stopCallback callback, if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; m_stop = callback; m_stop_data = data; - m_device->unlock(); - return true; } @@ -404,15 +438,16 @@ AUD_Vector3 AUD_OpenALDevice::AUD_OpenALHandle::getSourceLocation() AUD_Vector3 result = AUD_Vector3(0, 0, 0); if(!m_status) - return result; + return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return result; ALfloat p[3]; alGetSourcefv(m_source, AL_POSITION, p); - m_device->unlock(); - result = AUD_Vector3(p[0], p[1], p[2]); return result; @@ -423,11 +458,12 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceLocation(const AUD_Vector3& lo if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alSourcefv(m_source, AL_POSITION, (ALfloat*)location.get()); + if(!m_status) + return false; - m_device->unlock(); + alSourcefv(m_source, AL_POSITION, (ALfloat*)location.get()); return true; } @@ -437,15 +473,16 @@ AUD_Vector3 AUD_OpenALDevice::AUD_OpenALHandle::getSourceVelocity() AUD_Vector3 result = AUD_Vector3(0, 0, 0); if(!m_status) - return result; + return false; + + AUD_MutexLock lock(*m_device); - m_device->lock(); + if(!m_status) + return result; ALfloat v[3]; alGetSourcefv(m_source, AL_VELOCITY, v); - m_device->unlock(); - result = AUD_Vector3(v[0], v[1], v[2]); return result; @@ -456,11 +493,12 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceVelocity(const AUD_Vector3& ve if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alSourcefv(m_source, AL_VELOCITY, (ALfloat*)velocity.get()); + if(!m_status) + return false; - m_device->unlock(); + alSourcefv(m_source, AL_VELOCITY, (ALfloat*)velocity.get()); return true; } @@ -472,9 +510,6 @@ AUD_Quaternion AUD_OpenALDevice::AUD_OpenALHandle::getSourceOrientation() bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceOrientation(const AUD_Quaternion& orientation) { - if(!m_status) - return false; - ALfloat direction[3]; direction[0] = -2 * (orientation.w() * orientation.y() + orientation.x() * orientation.z()); @@ -482,11 +517,16 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceOrientation(const AUD_Quaterni orientation.z() * orientation.y()); direction[2] = 2 * (orientation.x() * orientation.x() + orientation.y() * orientation.y()) - 1; - m_device->lock(); - alSourcefv(m_source, AL_DIRECTION, direction); + if(!m_status) + return false; + + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; - m_device->unlock(); + alSourcefv(m_source, AL_DIRECTION, direction); m_orientation = orientation; @@ -500,11 +540,12 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::isRelative() if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alGetSourcei(m_source, AL_SOURCE_RELATIVE, &result); + if(!m_status) + return false; - m_device->unlock(); + alGetSourcei(m_source, AL_SOURCE_RELATIVE, &result); return result; } @@ -514,11 +555,12 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setRelative(bool relative) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alSourcei(m_source, AL_SOURCE_RELATIVE, relative); + if(!m_status) + return false; - m_device->unlock(); + alSourcei(m_source, AL_SOURCE_RELATIVE, relative); return true; } @@ -528,13 +570,14 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getVolumeMaximum() float result = std::numeric_limits<float>::quiet_NaN(); if(!m_status) - return result; + return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alGetSourcef(m_source, AL_MAX_GAIN, &result); + if(!m_status) + return result; - m_device->unlock(); + alGetSourcef(m_source, AL_MAX_GAIN, &result); return result; } @@ -544,11 +587,12 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setVolumeMaximum(float volume) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alSourcef(m_source, AL_MAX_GAIN, volume); + if(!m_status) + return false; - m_device->unlock(); + alSourcef(m_source, AL_MAX_GAIN, volume); return true; } @@ -558,13 +602,14 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getVolumeMinimum() float result = std::numeric_limits<float>::quiet_NaN(); if(!m_status) - return result; + return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alGetSourcef(m_source, AL_MIN_GAIN, &result); + if(!m_status) + return result; - m_device->unlock(); + alGetSourcef(m_source, AL_MIN_GAIN, &result); return result; } @@ -574,11 +619,12 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setVolumeMinimum(float volume) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alSourcef(m_source, AL_MIN_GAIN, volume); + if(!m_status) + return false; - m_device->unlock(); + alSourcef(m_source, AL_MIN_GAIN, volume); return true; } @@ -588,13 +634,14 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getDistanceMaximum() float result = std::numeric_limits<float>::quiet_NaN(); if(!m_status) - return result; + return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alGetSourcef(m_source, AL_MAX_DISTANCE, &result); + if(!m_status) + return result; - m_device->unlock(); + alGetSourcef(m_source, AL_MAX_DISTANCE, &result); return result; } @@ -604,11 +651,12 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setDistanceMaximum(float distance) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alSourcef(m_source, AL_MAX_DISTANCE, distance); + if(!m_status) + return false; - m_device->unlock(); + alSourcef(m_source, AL_MAX_DISTANCE, distance); return true; } @@ -618,13 +666,14 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getDistanceReference() float result = std::numeric_limits<float>::quiet_NaN(); if(!m_status) - return result; + return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &result); + if(!m_status) + return result; - m_device->unlock(); + alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &result); return result; } @@ -634,11 +683,12 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setDistanceReference(float distance) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alSourcef(m_source, AL_REFERENCE_DISTANCE, distance); + if(!m_status) + return false; - m_device->unlock(); + alSourcef(m_source, AL_REFERENCE_DISTANCE, distance); return true; } @@ -648,13 +698,14 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getAttenuation() float result = std::numeric_limits<float>::quiet_NaN(); if(!m_status) - return result; + return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &result); + if(!m_status) + return result; - m_device->unlock(); + alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &result); return result; } @@ -664,11 +715,12 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setAttenuation(float factor) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alSourcef(m_source, AL_ROLLOFF_FACTOR, factor); + if(!m_status) + return false; - m_device->unlock(); + alSourcef(m_source, AL_ROLLOFF_FACTOR, factor); return true; } @@ -678,13 +730,14 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getConeAngleOuter() float result = std::numeric_limits<float>::quiet_NaN(); if(!m_status) - return result; + return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alGetSourcef(m_source, AL_CONE_OUTER_ANGLE, &result); + if(!m_status) + return result; - m_device->unlock(); + alGetSourcef(m_source, AL_CONE_OUTER_ANGLE, &result); return result; } @@ -694,11 +747,12 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setConeAngleOuter(float angle) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alSourcef(m_source, AL_CONE_OUTER_ANGLE, angle); + if(!m_status) + return false; - m_device->unlock(); + alSourcef(m_source, AL_CONE_OUTER_ANGLE, angle); return true; } @@ -708,13 +762,14 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getConeAngleInner() float result = std::numeric_limits<float>::quiet_NaN(); if(!m_status) - return result; + return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alGetSourcef(m_source, AL_CONE_INNER_ANGLE, &result); + if(!m_status) + return result; - m_device->unlock(); + alGetSourcef(m_source, AL_CONE_INNER_ANGLE, &result); return result; } @@ -724,11 +779,12 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setConeAngleInner(float angle) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alSourcef(m_source, AL_CONE_INNER_ANGLE, angle); + if(!m_status) + return false; - m_device->unlock(); + alSourcef(m_source, AL_CONE_INNER_ANGLE, angle); return true; } @@ -738,13 +794,14 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getConeVolumeOuter() float result = std::numeric_limits<float>::quiet_NaN(); if(!m_status) - return result; + return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alGetSourcef(m_source, AL_CONE_OUTER_GAIN, &result); + if(!m_status) + return result; - m_device->unlock(); + alGetSourcef(m_source, AL_CONE_OUTER_GAIN, &result); return result; } @@ -754,11 +811,12 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setConeVolumeOuter(float volume) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - alSourcef(m_source, AL_CONE_OUTER_GAIN, volume); + if(!m_status) + return false; - m_device->unlock(); + alSourcef(m_source, AL_CONE_OUTER_GAIN, volume); return true; } @@ -776,7 +834,7 @@ static void *AUD_openalRunThread(void *device) void AUD_OpenALDevice::start(bool join) { - lock(); + AUD_MutexLock lock(*this); if(!m_playing) { @@ -793,21 +851,19 @@ void AUD_OpenALDevice::start(bool join) m_playing = true; } - - unlock(); } void AUD_OpenALDevice::updateStreams() { - AUD_Reference<AUD_OpenALHandle> sound; + boost::shared_ptr<AUD_OpenALHandle> sound; int length; ALint info; AUD_DeviceSpecs specs = m_specs; ALCenum cerr; - std::list<AUD_Reference<AUD_OpenALHandle> > stopSounds; - std::list<AUD_Reference<AUD_OpenALHandle> > pauseSounds; + std::list<boost::shared_ptr<AUD_OpenALHandle> > stopSounds; + std::list<boost::shared_ptr<AUD_OpenALHandle> > pauseSounds; AUD_HandleIterator it; while(1) @@ -970,7 +1026,6 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) { // cannot determine how many channels or which format OpenAL uses, but // it at least is able to play 16 bit stereo audio - specs.channels = AUD_CHANNELS_STEREO; specs.format = AUD_FORMAT_S16; #if 0 @@ -1009,6 +1064,11 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) m_useMC = alIsExtensionPresent("AL_EXT_MCFORMATS") == AL_TRUE; + if((!m_useMC && specs.channels > AUD_CHANNELS_STEREO) || + specs.channels == AUD_CHANNELS_STEREO_LFE || + specs.channels == AUD_CHANNELS_SURROUND5) + specs.channels = AUD_CHANNELS_STEREO; + alGetError(); alcGetError(m_device); @@ -1161,36 +1221,36 @@ bool AUD_OpenALDevice::getFormat(ALenum &format, AUD_Specs specs) return valid; } -AUD_Reference<AUD_IHandle> AUD_OpenALDevice::play(AUD_Reference<AUD_IReader> reader, bool keep) +boost::shared_ptr<AUD_IHandle> AUD_OpenALDevice::play(boost::shared_ptr<AUD_IReader> reader, bool keep) { AUD_Specs specs = reader->getSpecs(); // check format if(specs.channels == AUD_CHANNELS_INVALID) - return AUD_Reference<AUD_IHandle>(); + return boost::shared_ptr<AUD_IHandle>(); if(m_specs.format != AUD_FORMAT_FLOAT32) - reader = new AUD_ConverterReader(reader, m_specs); + reader = boost::shared_ptr<AUD_IReader>(new AUD_ConverterReader(reader, m_specs)); ALenum format; if(!getFormat(format, specs)) - return AUD_Reference<AUD_IHandle>(); + return boost::shared_ptr<AUD_IHandle>(); + + AUD_MutexLock lock(*this); - lock(); alcSuspendContext(m_context); - AUD_Reference<AUD_OpenALDevice::AUD_OpenALHandle> sound; + boost::shared_ptr<AUD_OpenALDevice::AUD_OpenALHandle> sound; try { // create the handle - sound = new AUD_OpenALDevice::AUD_OpenALHandle(this, format, reader, keep); + sound = boost::shared_ptr<AUD_OpenALDevice::AUD_OpenALHandle>(new AUD_OpenALDevice::AUD_OpenALHandle(this, format, reader, keep)); } catch(AUD_Exception&) { alcProcessContext(m_context); - unlock(); throw; } @@ -1201,12 +1261,10 @@ AUD_Reference<AUD_IHandle> AUD_OpenALDevice::play(AUD_Reference<AUD_IReader> rea start(); - unlock(); - - return AUD_Reference<AUD_IHandle>(sound); + return boost::shared_ptr<AUD_IHandle>(sound); } -AUD_Reference<AUD_IHandle> AUD_OpenALDevice::play(AUD_Reference<AUD_IFactory> factory, bool keep) +boost::shared_ptr<AUD_IHandle> AUD_OpenALDevice::play(boost::shared_ptr<AUD_IFactory> factory, bool keep) { /* AUD_XXX disabled AUD_OpenALHandle* sound = NULL; @@ -1285,7 +1343,8 @@ AUD_Reference<AUD_IHandle> AUD_OpenALDevice::play(AUD_Reference<AUD_IFactory> fa void AUD_OpenALDevice::stopAll() { - lock(); + AUD_MutexLock lock(*this); + alcSuspendContext(m_context); while(!m_playingSounds.empty()) @@ -1295,7 +1354,6 @@ void AUD_OpenALDevice::stopAll() m_pausedSounds.front()->stop(); alcProcessContext(m_context); - unlock(); } void AUD_OpenALDevice::lock() diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.h b/intern/audaspace/OpenAL/AUD_OpenALDevice.h index 0a409b42462..d2a4be227ba 100644 --- a/intern/audaspace/OpenAL/AUD_OpenALDevice.h +++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.h @@ -58,7 +58,7 @@ private: bool m_isBuffered; /// The reader source. - AUD_Reference<AUD_IReader> m_reader; + boost::shared_ptr<AUD_IReader> m_reader; /// Whether to keep the source if end of it is reached. bool m_keep; @@ -105,7 +105,7 @@ private: * \param reader The reader this handle plays. * \param keep Whether to keep the handle alive when the reader ends. */ - AUD_OpenALHandle(AUD_OpenALDevice* device, ALenum format, AUD_Reference<AUD_IReader> reader, bool keep); + AUD_OpenALHandle(AUD_OpenALDevice* device, ALenum format, boost::shared_ptr<AUD_IReader> reader, bool keep); virtual ~AUD_OpenALHandle() {} virtual bool pause(); @@ -150,7 +150,7 @@ private: virtual bool setConeVolumeOuter(float volume); }; - typedef std::list<AUD_Reference<AUD_OpenALHandle> >::iterator AUD_HandleIterator; + typedef std::list<boost::shared_ptr<AUD_OpenALHandle> >::iterator AUD_HandleIterator; /** * The OpenAL device handle. @@ -175,12 +175,12 @@ private: /** * The list of sounds that are currently playing. */ - std::list<AUD_Reference<AUD_OpenALHandle> > m_playingSounds; + std::list<boost::shared_ptr<AUD_OpenALHandle> > m_playingSounds; /** * The list of sounds that are currently paused. */ - std::list<AUD_Reference<AUD_OpenALHandle> > m_pausedSounds; + std::list<boost::shared_ptr<AUD_OpenALHandle> > m_pausedSounds; /** * The list of buffered factories. @@ -255,8 +255,8 @@ public: virtual ~AUD_OpenALDevice(); virtual AUD_DeviceSpecs getSpecs() const; - virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IReader> reader, bool keep = false); - virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IFactory> factory, bool keep = false); + virtual boost::shared_ptr<AUD_IHandle> play(boost::shared_ptr<AUD_IReader> reader, bool keep = false); + virtual boost::shared_ptr<AUD_IHandle> play(boost::shared_ptr<AUD_IFactory> factory, bool keep = false); virtual void stopAll(); virtual void lock(); virtual void unlock(); diff --git a/intern/audaspace/Python/AUD_PyAPI.cpp b/intern/audaspace/Python/AUD_PyAPI.cpp index dd58e5a7398..9beba2eb0a0 100644 --- a/intern/audaspace/Python/AUD_PyAPI.cpp +++ b/intern/audaspace/Python/AUD_PyAPI.cpp @@ -90,7 +90,7 @@ static void Factory_dealloc(Factory* self) { if(self->factory) - delete reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory); + delete reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(self->factory); Py_XDECREF(self->child_list); Py_TYPE(self)->tp_free((PyObject *)self); } @@ -114,7 +114,7 @@ Factory_new(PyTypeObject *type, PyObject *args, PyObject *kwds) try { - self->factory = new AUD_Reference<AUD_IFactory>(new AUD_FileFactory(filename)); + self->factory = new boost::shared_ptr<AUD_IFactory>(new AUD_FileFactory(filename)); } catch(AUD_Exception& e) { @@ -154,7 +154,7 @@ Factory_sine(PyTypeObject* type, PyObject *args) { try { - self->factory = new AUD_Reference<AUD_IFactory>(new AUD_SinusFactory(frequency, (AUD_SampleRate)rate)); + self->factory = new boost::shared_ptr<AUD_IFactory>(new AUD_SinusFactory(frequency, (AUD_SampleRate)rate)); } catch(AUD_Exception& e) { @@ -193,7 +193,7 @@ Factory_file(PyTypeObject* type, PyObject *args) { try { - self->factory = new AUD_Reference<AUD_IFactory>(new AUD_FileFactory(filename)); + self->factory = new boost::shared_ptr<AUD_IFactory>(new AUD_FileFactory(filename)); } catch(AUD_Exception& e) { @@ -236,7 +236,7 @@ Factory_lowpass(Factory* self, PyObject *args) try { - parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_LowpassFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), frequency, Q)); + parent->factory = new boost::shared_ptr<AUD_IFactory>(new AUD_LowpassFactory(*reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(self->factory), frequency, Q)); } catch(AUD_Exception& e) { @@ -277,7 +277,7 @@ Factory_delay(Factory* self, PyObject *args) try { - parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_DelayFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), delay)); + parent->factory = new boost::shared_ptr<AUD_IFactory>(new AUD_DelayFactory(*reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(self->factory), delay)); } catch(AUD_Exception& e) { @@ -321,7 +321,7 @@ Factory_join(Factory* self, PyObject *object) try { - parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_DoubleFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), *reinterpret_cast<AUD_Reference<AUD_IFactory>*>(child->factory))); + parent->factory = new boost::shared_ptr<AUD_IFactory>(new AUD_DoubleFactory(*reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(self->factory), *reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(child->factory))); } catch(AUD_Exception& e) { @@ -364,7 +364,7 @@ Factory_highpass(Factory* self, PyObject *args) try { - parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_HighpassFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), frequency, Q)); + parent->factory = new boost::shared_ptr<AUD_IFactory>(new AUD_HighpassFactory(*reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(self->factory), frequency, Q)); } catch(AUD_Exception& e) { @@ -405,7 +405,7 @@ Factory_limit(Factory* self, PyObject *args) try { - parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_LimiterFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), start, end)); + parent->factory = new boost::shared_ptr<AUD_IFactory>(new AUD_LimiterFactory(*reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(self->factory), start, end)); } catch(AUD_Exception& e) { @@ -449,7 +449,7 @@ Factory_pitch(Factory* self, PyObject *args) try { - parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_PitchFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), factor)); + parent->factory = new boost::shared_ptr<AUD_IFactory>(new AUD_PitchFactory(*reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(self->factory), factor)); } catch(AUD_Exception& e) { @@ -491,7 +491,7 @@ Factory_volume(Factory* self, PyObject *args) try { - parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_VolumeFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), volume)); + parent->factory = new boost::shared_ptr<AUD_IFactory>(new AUD_VolumeFactory(*reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(self->factory), volume)); } catch(AUD_Exception& e) { @@ -534,7 +534,7 @@ Factory_fadein(Factory* self, PyObject *args) try { - parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_FaderFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), AUD_FADE_IN, start, length)); + parent->factory = new boost::shared_ptr<AUD_IFactory>(new AUD_FaderFactory(*reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(self->factory), AUD_FADE_IN, start, length)); } catch(AUD_Exception& e) { @@ -578,7 +578,7 @@ Factory_fadeout(Factory* self, PyObject *args) try { - parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_FaderFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), AUD_FADE_OUT, start, length)); + parent->factory = new boost::shared_ptr<AUD_IFactory>(new AUD_FaderFactory(*reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(self->factory), AUD_FADE_OUT, start, length)); } catch(AUD_Exception& e) { @@ -620,7 +620,7 @@ Factory_loop(Factory* self, PyObject *args) try { - parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_LoopFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), loop)); + parent->factory = new boost::shared_ptr<AUD_IFactory>(new AUD_LoopFactory(*reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(self->factory), loop)); } catch(AUD_Exception& e) { @@ -663,7 +663,7 @@ Factory_mix(Factory* self, PyObject *object) try { - parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_SuperposeFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), *reinterpret_cast<AUD_Reference<AUD_IFactory>*>(child->factory))); + parent->factory = new boost::shared_ptr<AUD_IFactory>(new AUD_SuperposeFactory(*reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(self->factory), *reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(child->factory))); } catch(AUD_Exception& e) { @@ -696,7 +696,7 @@ Factory_pingpong(Factory* self) try { - parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_PingPongFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory))); + parent->factory = new boost::shared_ptr<AUD_IFactory>(new AUD_PingPongFactory(*reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(self->factory))); } catch(AUD_Exception& e) { @@ -735,7 +735,7 @@ Factory_reverse(Factory* self) try { - parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_ReverseFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory))); + parent->factory = new boost::shared_ptr<AUD_IFactory>(new AUD_ReverseFactory(*reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(self->factory))); } catch(AUD_Exception& e) { @@ -770,7 +770,7 @@ Factory_buffer(Factory* self) { try { - parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_StreamBufferFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory))); + parent->factory = new boost::shared_ptr<AUD_IFactory>(new AUD_StreamBufferFactory(*reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(self->factory))); } catch(AUD_Exception& e) { @@ -812,7 +812,7 @@ Factory_square(Factory* self, PyObject *args) try { - parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_SquareFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), threshold)); + parent->factory = new boost::shared_ptr<AUD_IFactory>(new AUD_SquareFactory(*reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(self->factory), threshold)); } catch(AUD_Exception& e) { @@ -915,7 +915,7 @@ Factory_filter(Factory* self, PyObject *args) try { - parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_IIRFilterFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), b, a)); + parent->factory = new boost::shared_ptr<AUD_IFactory>(new AUD_IIRFilterFactory(*reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(self->factory), b, a)); } catch(AUD_Exception& e) { @@ -1039,7 +1039,7 @@ static void Handle_dealloc(Handle* self) { if(self->handle) - delete reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle); + delete reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle); Py_TYPE(self)->tp_free((PyObject *)self); } @@ -1054,7 +1054,7 @@ Handle_pause(Handle *self) { try { - return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->pause()); + return PyBool_FromLong((long)(*reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle))->pause()); } catch(AUD_Exception& e) { @@ -1074,7 +1074,7 @@ Handle_resume(Handle *self) { try { - return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->resume()); + return PyBool_FromLong((long)(*reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle))->resume()); } catch(AUD_Exception& e) { @@ -1095,7 +1095,7 @@ Handle_stop(Handle *self) { try { - return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->stop()); + return PyBool_FromLong((long)(*reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle))->stop()); } catch(AUD_Exception& e) { @@ -1125,7 +1125,7 @@ Handle_get_position(Handle *self, void* nothing) { try { - return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getPosition()); + return Py_BuildValue("f", (*reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle))->getPosition()); } catch(AUD_Exception& e) { @@ -1144,7 +1144,7 @@ Handle_set_position(Handle *self, PyObject *args, void* nothing) try { - if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->seek(position)) + if((*reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle))->seek(position)) return 0; PyErr_SetString(AUDError, "Couldn't seek the sound!"); } @@ -1170,7 +1170,7 @@ Handle_get_keep(Handle *self, void* nothing) { try { - return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getKeep()); + return PyBool_FromLong((long)(*reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle))->getKeep()); } catch(AUD_Exception& e) { @@ -1192,7 +1192,7 @@ Handle_set_keep(Handle *self, PyObject *args, void* nothing) try { - if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->setKeep(keep)) + if((*reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle))->setKeep(keep)) return 0; PyErr_SetString(AUDError, "Couldn't set keep of the sound!"); } @@ -1212,7 +1212,7 @@ Handle_get_status(Handle *self, void* nothing) { try { - return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getStatus()); + return PyBool_FromLong((long)(*reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle))->getStatus()); } catch(AUD_Exception& e) { @@ -1229,7 +1229,7 @@ Handle_get_volume(Handle *self, void* nothing) { try { - return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getVolume()); + return Py_BuildValue("f", (*reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle))->getVolume()); } catch(AUD_Exception& e) { @@ -1248,7 +1248,7 @@ Handle_set_volume(Handle *self, PyObject *args, void* nothing) try { - if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->setVolume(volume)) + if((*reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle))->setVolume(volume)) return 0; PyErr_SetString(AUDError, "Couldn't set the sound volume!"); } @@ -1268,7 +1268,7 @@ Handle_get_pitch(Handle *self, void* nothing) { try { - return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getPitch()); + return Py_BuildValue("f", (*reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle))->getPitch()); } catch(AUD_Exception& e) { @@ -1287,7 +1287,7 @@ Handle_set_pitch(Handle *self, PyObject *args, void* nothing) try { - if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->setPitch(pitch)) + if((*reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle))->setPitch(pitch)) return 0; PyErr_SetString(AUDError, "Couldn't set the sound pitch!"); } @@ -1307,7 +1307,7 @@ Handle_get_loop_count(Handle *self, void* nothing) { try { - return Py_BuildValue("i", (*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getLoopCount()); + return Py_BuildValue("i", (*reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle))->getLoopCount()); } catch(AUD_Exception& e) { @@ -1326,7 +1326,7 @@ Handle_set_loop_count(Handle *self, PyObject *args, void* nothing) try { - if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->setLoopCount(loops)) + if((*reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle))->setLoopCount(loops)) return 0; PyErr_SetString(AUDError, "Couldn't set the loop count!"); } @@ -1346,7 +1346,7 @@ Handle_get_location(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { AUD_Vector3 v = handle->getSourceLocation(); @@ -1375,7 +1375,7 @@ Handle_set_location(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { AUD_Vector3 location(x, y, z); @@ -1402,7 +1402,7 @@ Handle_get_velocity(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { AUD_Vector3 v = handle->getSourceVelocity(); @@ -1431,7 +1431,7 @@ Handle_set_velocity(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { AUD_Vector3 velocity(x, y, z); @@ -1458,7 +1458,7 @@ Handle_get_orientation(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { AUD_Quaternion o = handle->getSourceOrientation(); @@ -1487,7 +1487,7 @@ Handle_set_orientation(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { AUD_Quaternion orientation(w, x, y, z); @@ -1514,7 +1514,7 @@ Handle_get_relative(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { return PyBool_FromLong((long)handle->isRelative()); @@ -1545,7 +1545,7 @@ Handle_set_relative(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { if(handle->setRelative(relative)) @@ -1572,7 +1572,7 @@ Handle_get_volume_minimum(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getVolumeMinimum()); @@ -1600,7 +1600,7 @@ Handle_set_volume_minimum(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { if(handle->setVolumeMinimum(volume)) @@ -1627,7 +1627,7 @@ Handle_get_volume_maximum(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getVolumeMaximum()); @@ -1655,7 +1655,7 @@ Handle_set_volume_maximum(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { if(handle->setVolumeMaximum(volume)) @@ -1683,7 +1683,7 @@ Handle_get_distance_reference(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getDistanceReference()); @@ -1711,7 +1711,7 @@ Handle_set_distance_reference(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { if(handle->setDistanceReference(distance)) @@ -1739,7 +1739,7 @@ Handle_get_distance_maximum(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getDistanceMaximum()); @@ -1767,7 +1767,7 @@ Handle_set_distance_maximum(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { if(handle->setDistanceMaximum(distance)) @@ -1795,7 +1795,7 @@ Handle_get_attenuation(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getAttenuation()); @@ -1823,7 +1823,7 @@ Handle_set_attenuation(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { if(handle->setAttenuation(factor)) @@ -1856,7 +1856,7 @@ Handle_get_cone_angle_inner(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getConeAngleInner()); @@ -1884,7 +1884,7 @@ Handle_set_cone_angle_inner(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { if(handle->setConeAngleInner(angle)) @@ -1911,7 +1911,7 @@ Handle_get_cone_angle_outer(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getConeAngleOuter()); @@ -1939,7 +1939,7 @@ Handle_set_cone_angle_outer(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { if(handle->setConeAngleOuter(angle)) @@ -1966,7 +1966,7 @@ Handle_get_cone_volume_outer(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getConeVolumeOuter()); @@ -1994,7 +1994,7 @@ Handle_set_cone_volume_outer(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<boost::shared_ptr<AUD_IHandle>*>(self->handle)->get()); if(handle) { if(handle->setConeVolumeOuter(volume)) @@ -2104,7 +2104,7 @@ static void Device_dealloc(Device* self) { if(self->device) - delete reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device); + delete reinterpret_cast<boost::shared_ptr<AUD_IDevice>*>(self->device); Py_TYPE(self)->tp_free((PyObject *)self); } @@ -2147,21 +2147,21 @@ Device_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { case AUD_DEVICE_NULL: (void)specs; /* quiet warning when others disabled */ - self->device = new AUD_Reference<AUD_IDevice>(new AUD_NULLDevice()); + self->device = new boost::shared_ptr<AUD_IDevice>(new AUD_NULLDevice()); break; case AUD_DEVICE_OPENAL: #ifdef WITH_OPENAL - self->device = new AUD_Reference<AUD_IDevice>(new AUD_OpenALDevice(specs, buffersize)); + self->device = new boost::shared_ptr<AUD_IDevice>(new AUD_OpenALDevice(specs, buffersize)); #endif break; case AUD_DEVICE_SDL: #ifdef WITH_SDL - self->device = new AUD_Reference<AUD_IDevice>(new AUD_SDLDevice(specs, buffersize)); + self->device = new boost::shared_ptr<AUD_IDevice>(new AUD_SDLDevice(specs, buffersize)); #endif break; case AUD_DEVICE_JACK: #ifdef WITH_JACK - self->device = new AUD_Reference<AUD_IDevice>(new AUD_JackDevice(name, specs, buffersize)); + self->device = new boost::shared_ptr<AUD_IDevice>(new AUD_JackDevice(name, specs, buffersize)); #endif break; case AUD_DEVICE_READ: @@ -2236,7 +2236,7 @@ Device_play(Device *self, PyObject *args, PyObject *kwds) { try { - handle->handle = new AUD_Reference<AUD_IHandle>((*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->play(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(sound->factory), keep)); + handle->handle = new boost::shared_ptr<AUD_IHandle>((*reinterpret_cast<boost::shared_ptr<AUD_IDevice>*>(self->device))->play(*reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(sound->factory), keep)); } catch(AUD_Exception& e) { @@ -2258,7 +2258,7 @@ Device_stopAll(Device *self) { try { - (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->stopAll(); + (*reinterpret_cast<boost::shared_ptr<AUD_IDevice>*>(self->device))->stopAll(); Py_RETURN_NONE; } catch(AUD_Exception& e) @@ -2284,7 +2284,7 @@ Device_lock(Device *self) { try { - (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->lock(); + (*reinterpret_cast<boost::shared_ptr<AUD_IDevice>*>(self->device))->lock(); Py_RETURN_NONE; } catch(AUD_Exception& e) @@ -2304,7 +2304,7 @@ Device_unlock(Device *self) { try { - (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->unlock(); + (*reinterpret_cast<boost::shared_ptr<AUD_IDevice>*>(self->device))->unlock(); Py_RETURN_NONE; } catch(AUD_Exception& e) @@ -2338,7 +2338,7 @@ Device_get_rate(Device *self, void* nothing) { try { - AUD_DeviceSpecs specs = (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->getSpecs(); + AUD_DeviceSpecs specs = (*reinterpret_cast<boost::shared_ptr<AUD_IDevice>*>(self->device))->getSpecs(); return Py_BuildValue("d", specs.rate); } catch(AUD_Exception& e) @@ -2356,7 +2356,7 @@ Device_get_format(Device *self, void* nothing) { try { - AUD_DeviceSpecs specs = (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->getSpecs(); + AUD_DeviceSpecs specs = (*reinterpret_cast<boost::shared_ptr<AUD_IDevice>*>(self->device))->getSpecs(); return Py_BuildValue("i", specs.format); } catch(AUD_Exception& e) @@ -2374,7 +2374,7 @@ Device_get_channels(Device *self, void* nothing) { try { - AUD_DeviceSpecs specs = (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->getSpecs(); + AUD_DeviceSpecs specs = (*reinterpret_cast<boost::shared_ptr<AUD_IDevice>*>(self->device))->getSpecs(); return Py_BuildValue("i", specs.channels); } catch(AUD_Exception& e) @@ -2392,7 +2392,7 @@ Device_get_volume(Device *self, void* nothing) { try { - return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->getVolume()); + return Py_BuildValue("f", (*reinterpret_cast<boost::shared_ptr<AUD_IDevice>*>(self->device))->getVolume()); } catch(AUD_Exception& e) { @@ -2411,7 +2411,7 @@ Device_set_volume(Device *self, PyObject *args, void* nothing) try { - (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->setVolume(volume); + (*reinterpret_cast<boost::shared_ptr<AUD_IDevice>*>(self->device))->setVolume(volume); return 0; } catch(AUD_Exception& e) @@ -2429,7 +2429,7 @@ Device_get_listener_location(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<boost::shared_ptr<AUD_IDevice>*>(self->device)->get()); if(device) { AUD_Vector3 v = device->getListenerLocation(); @@ -2458,7 +2458,7 @@ Device_set_listener_location(Device *self, PyObject *args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<boost::shared_ptr<AUD_IDevice>*>(self->device)->get()); if(device) { AUD_Vector3 location(x, y, z); @@ -2484,7 +2484,7 @@ Device_get_listener_velocity(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<boost::shared_ptr<AUD_IDevice>*>(self->device)->get()); if(device) { AUD_Vector3 v = device->getListenerVelocity(); @@ -2513,7 +2513,7 @@ Device_set_listener_velocity(Device *self, PyObject *args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<boost::shared_ptr<AUD_IDevice>*>(self->device)->get()); if(device) { AUD_Vector3 velocity(x, y, z); @@ -2539,7 +2539,7 @@ Device_get_listener_orientation(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<boost::shared_ptr<AUD_IDevice>*>(self->device)->get()); if(device) { AUD_Quaternion o = device->getListenerOrientation(); @@ -2568,7 +2568,7 @@ Device_set_listener_orientation(Device *self, PyObject *args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<boost::shared_ptr<AUD_IDevice>*>(self->device)->get()); if(device) { AUD_Quaternion orientation(w, x, y, z); @@ -2595,7 +2595,7 @@ Device_get_speed_of_sound(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<boost::shared_ptr<AUD_IDevice>*>(self->device)->get()); if(device) { return Py_BuildValue("f", device->getSpeedOfSound()); @@ -2623,7 +2623,7 @@ Device_set_speed_of_sound(Device *self, PyObject *args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<boost::shared_ptr<AUD_IDevice>*>(self->device)->get()); if(device) { device->setSpeedOfSound(speed); @@ -2651,7 +2651,7 @@ Device_get_doppler_factor(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<boost::shared_ptr<AUD_IDevice>*>(self->device)->get()); if(device) { return Py_BuildValue("f", device->getDopplerFactor()); @@ -2679,7 +2679,7 @@ Device_set_doppler_factor(Device *self, PyObject *args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<boost::shared_ptr<AUD_IDevice>*>(self->device)->get()); if(device) { device->setDopplerFactor(factor); @@ -2705,7 +2705,7 @@ Device_get_distance_model(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<boost::shared_ptr<AUD_IDevice>*>(self->device)->get()); if(device) { return Py_BuildValue("i", int(device->getDistanceModel())); @@ -2733,7 +2733,7 @@ Device_set_distance_model(Device *self, PyObject *args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<boost::shared_ptr<AUD_IDevice>*>(self->device)->get()); if(device) { device->setDistanceModel(AUD_DistanceModel(model)); diff --git a/intern/audaspace/SConscript b/intern/audaspace/SConscript index 50c81db46dd..e2b6efacc96 100644 --- a/intern/audaspace/SConscript +++ b/intern/audaspace/SConscript @@ -3,7 +3,7 @@ Import ('env') sources = env.Glob('intern/*.cpp') + env.Glob('FX/*.cpp') -incs = '. intern FX ' + env['BF_PTHREADS_INC'] +incs = '. intern FX ' + env['BF_PTHREADS_INC'] + ' ' + env['BF_BOOST_INC'] defs = [] if env['WITH_BF_FFMPEG']: diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp index c4c384f054c..403c367fccc 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp @@ -46,10 +46,10 @@ AUD_FFMPEGFactory::AUD_FFMPEGFactory(const data_t* buffer, int size) : memcpy(m_buffer->getBuffer(), buffer, size); } -AUD_Reference<AUD_IReader> AUD_FFMPEGFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_FFMPEGFactory::createReader() { - if(m_buffer.isNull()) - return new AUD_FFMPEGReader(m_filename); + if(m_buffer.get()) + return boost::shared_ptr<AUD_IReader>(new AUD_FFMPEGReader(m_buffer)); else - return new AUD_FFMPEGReader(m_buffer); + return boost::shared_ptr<AUD_IReader>(new AUD_FFMPEGReader(m_filename)); } diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h index 349f55dd7db..23d0f07ed0b 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h @@ -31,10 +31,10 @@ #define __AUD_FFMPEGFACTORY_H__ #include "AUD_IFactory.h" -#include "AUD_Reference.h" #include "AUD_Buffer.h" #include <string> +#include <boost/shared_ptr.hpp> /** * This factory reads a sound file via ffmpeg. @@ -52,7 +52,7 @@ private: /** * The buffer to read from. */ - AUD_Reference<AUD_Buffer> m_buffer; + boost::shared_ptr<AUD_Buffer> m_buffer; // hide copy constructor and operator= AUD_FFMPEGFactory(const AUD_FFMPEGFactory&); @@ -72,7 +72,7 @@ public: */ AUD_FFMPEGFactory(const data_t* buffer, int size); - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif //__AUD_FFMPEGFACTORY_H__ diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp index 28a14a9cfc7..0a3d0f8e85a 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp @@ -197,7 +197,7 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(std::string filename) : static const char* streamopen_error = "AUD_FFMPEGReader: Stream couldn't be " "opened."; -AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer) : +AUD_FFMPEGReader::AUD_FFMPEGReader(boost::shared_ptr<AUD_Buffer> buffer) : m_pkgbuf(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1), m_membuffer(buffer), m_membufferpos(0) diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h index 2b354b0b2a1..d5d9fb300ff 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h @@ -32,10 +32,10 @@ #include "AUD_ConverterFunctions.h" #include "AUD_IReader.h" -#include "AUD_Reference.h" #include "AUD_Buffer.h" #include <string> +#include <boost/shared_ptr.hpp> struct AVCodecContext; extern "C" { @@ -99,7 +99,7 @@ private: /** * The memory file to read from. */ - AUD_Reference<AUD_Buffer> m_membuffer; + boost::shared_ptr<AUD_Buffer> m_membuffer; /** * The buffer to read with. @@ -143,7 +143,7 @@ public: * \exception AUD_Exception Thrown if the buffer specified cannot be read * with ffmpeg. */ - AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer); + AUD_FFMPEGReader(boost::shared_ptr<AUD_Buffer> buffer); /** * Destroys the reader and closes the file. diff --git a/intern/audaspace/intern/AUD_AnimateableProperty.cpp b/intern/audaspace/intern/AUD_AnimateableProperty.cpp index 8a5c538c094..0b333e687ff 100644 --- a/intern/audaspace/intern/AUD_AnimateableProperty.cpp +++ b/intern/audaspace/intern/AUD_AnimateableProperty.cpp @@ -28,6 +28,7 @@ #include "AUD_AnimateableProperty.h" +#include "AUD_MutexLock.h" #include <cstring> #include <cmath> @@ -63,17 +64,15 @@ void AUD_AnimateableProperty::unlock() void AUD_AnimateableProperty::write(const float* data) { - lock(); + AUD_MutexLock lock(*this); m_isAnimated = false; memcpy(getBuffer(), data, m_count * sizeof(float)); - - unlock(); } void AUD_AnimateableProperty::write(const float* data, int position, int count) { - lock(); + AUD_MutexLock lock(*this); m_isAnimated = true; @@ -87,18 +86,15 @@ void AUD_AnimateableProperty::write(const float* data, int position, int count) for(int i = pos; i < position; i++) memcpy(buf + i * m_count, buf + (pos - 1) * m_count, m_count * sizeof(float)); - - unlock(); } void AUD_AnimateableProperty::read(float position, float* out) { - lock(); + AUD_MutexLock lock(*this); if(!m_isAnimated) { memcpy(out, getBuffer(), m_count * sizeof(float)); - unlock(); return; } @@ -147,8 +143,6 @@ void AUD_AnimateableProperty::read(float position, float* out) (t3 - 2 * t2 + t) * m0 + (t3 - t2) * m1; } } - - unlock(); } bool AUD_AnimateableProperty::isAnimated() const diff --git a/intern/audaspace/intern/AUD_AnimateableProperty.h b/intern/audaspace/intern/AUD_AnimateableProperty.h index 2f25e330ebd..322748ad571 100644 --- a/intern/audaspace/intern/AUD_AnimateableProperty.h +++ b/intern/audaspace/intern/AUD_AnimateableProperty.h @@ -31,13 +31,14 @@ #define __AUD_ANIMATEABLEPROPERTY_H__ #include "AUD_Buffer.h" +#include "AUD_ILockable.h" #include <pthread.h> /** * This class saves animation data for float properties. */ -class AUD_AnimateableProperty : private AUD_Buffer +class AUD_AnimateableProperty : private AUD_Buffer, public AUD_ILockable { private: /// The count of floats for a single property. @@ -68,12 +69,12 @@ public: /** * Locks the property. */ - void lock(); + virtual void lock(); /** * Unlocks the previously locked property. */ - void unlock(); + virtual void unlock(); /** * Writes the properties value and marks it non-animated. diff --git a/intern/audaspace/intern/AUD_BufferReader.cpp b/intern/audaspace/intern/AUD_BufferReader.cpp index dbff70095ad..b9d819ff774 100644 --- a/intern/audaspace/intern/AUD_BufferReader.cpp +++ b/intern/audaspace/intern/AUD_BufferReader.cpp @@ -33,7 +33,7 @@ #include <cstring> -AUD_BufferReader::AUD_BufferReader(AUD_Reference<AUD_Buffer> buffer, +AUD_BufferReader::AUD_BufferReader(boost::shared_ptr<AUD_Buffer> buffer, AUD_Specs specs) : m_position(0), m_buffer(buffer), m_specs(specs) { diff --git a/intern/audaspace/intern/AUD_BufferReader.h b/intern/audaspace/intern/AUD_BufferReader.h index 0e8c5de9a9d..d0c90ce7e61 100644 --- a/intern/audaspace/intern/AUD_BufferReader.h +++ b/intern/audaspace/intern/AUD_BufferReader.h @@ -31,9 +31,10 @@ #define __AUD_BUFFERREADER_H__ #include "AUD_IReader.h" -#include "AUD_Reference.h" class AUD_Buffer; +#include <boost/shared_ptr.hpp> + /** * This class represents a simple reader from a buffer that exists in memory. * \warning Notice that the buffer used for creating the reader must exist as @@ -50,7 +51,7 @@ private: /** * The buffer that is read. */ - AUD_Reference<AUD_Buffer> m_buffer; + boost::shared_ptr<AUD_Buffer> m_buffer; /** * The specification of the sample data in the buffer. @@ -67,7 +68,7 @@ public: * \param buffer The buffer to read from. * \param specs The specification of the sample data in the buffer. */ - AUD_BufferReader(AUD_Reference<AUD_Buffer> buffer, AUD_Specs specs); + AUD_BufferReader(boost::shared_ptr<AUD_Buffer> buffer, AUD_Specs specs); virtual bool isSeekable() const; virtual void seek(int position); diff --git a/intern/audaspace/intern/AUD_C-API.cpp b/intern/audaspace/intern/AUD_C-API.cpp index 46bba237cff..3150c1af011 100644 --- a/intern/audaspace/intern/AUD_C-API.cpp +++ b/intern/audaspace/intern/AUD_C-API.cpp @@ -68,6 +68,7 @@ #include "AUD_SequencerFactory.h" #include "AUD_SequencerEntry.h" #include "AUD_SilenceFactory.h" +#include "AUD_MutexLock.h" #ifdef WITH_SDL #include "AUD_SDLDevice.h" @@ -90,10 +91,10 @@ extern "C" { #include <cassert> -typedef AUD_Reference<AUD_IFactory> AUD_Sound; -typedef AUD_Reference<AUD_ReadDevice> AUD_Device; -typedef AUD_Reference<AUD_IHandle> AUD_Handle; -typedef AUD_Reference<AUD_SequencerEntry> AUD_SEntry; +typedef boost::shared_ptr<AUD_IFactory> AUD_Sound; +typedef boost::shared_ptr<AUD_ReadDevice> AUD_Device; +typedef boost::shared_ptr<AUD_IHandle> AUD_Handle; +typedef boost::shared_ptr<AUD_SequencerEntry> AUD_SEntry; #define AUD_CAPI_IMPLEMENTATION #include "AUD_C-API.h" @@ -102,7 +103,7 @@ typedef AUD_Reference<AUD_SequencerEntry> AUD_SEntry; # define NULL (void *)0 #endif -static AUD_Reference<AUD_IDevice> AUD_device; +static boost::shared_ptr<AUD_IDevice> AUD_device; static AUD_I3DDevice *AUD_3ddevice; void AUD_initOnce() @@ -114,25 +115,25 @@ void AUD_initOnce() int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize) { - AUD_Reference<AUD_IDevice> dev; + boost::shared_ptr<AUD_IDevice> dev; - if (!AUD_device.isNull()) { + if (AUD_device.get()) { AUD_exit(); } try { switch(device) { case AUD_NULL_DEVICE: - dev = new AUD_NULLDevice(); + dev = boost::shared_ptr<AUD_IDevice>(new AUD_NULLDevice()); break; #ifdef WITH_SDL case AUD_SDL_DEVICE: - dev = new AUD_SDLDevice(specs, buffersize); + dev = boost::shared_ptr<AUD_IDevice>(new AUD_SDLDevice(specs, buffersize)); break; #endif #ifdef WITH_OPENAL case AUD_OPENAL_DEVICE: - dev = new AUD_OpenALDevice(specs, buffersize); + dev = boost::shared_ptr<AUD_IDevice>(new AUD_OpenALDevice(specs, buffersize)); break; #endif #ifdef WITH_JACK @@ -146,7 +147,7 @@ int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize) else { #endif - dev = new AUD_JackDevice("Blender", specs, buffersize); + dev = boost::shared_ptr<AUD_IDevice>(new AUD_JackDevice("Blender", specs, buffersize)); break; #ifdef __APPLE__ } @@ -169,17 +170,17 @@ int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize) void AUD_exit() { - AUD_device = AUD_Reference<AUD_IDevice>(); + AUD_device = boost::shared_ptr<AUD_IDevice>(); AUD_3ddevice = NULL; } #ifdef WITH_PYTHON static PyObject *AUD_getCDevice(PyObject *self) { - if (!AUD_device.isNull()) { + if (AUD_device.get()) { Device *device = (Device *)Device_empty(); if (device != NULL) { - device->device = new AUD_Reference<AUD_IDevice>(AUD_device); + device->device = new boost::shared_ptr<AUD_IDevice>(AUD_device); return (PyObject *)device; } } @@ -205,12 +206,12 @@ static PyObject *AUD_getSoundFromPointer(PyObject *self, PyObject *args) if (PyArg_Parse(args, "l:_sound_from_pointer", &lptr)) { if (lptr) { - AUD_Reference<AUD_IFactory>* factory = (AUD_Reference<AUD_IFactory>*) sound_get_factory((void *) lptr); + boost::shared_ptr<AUD_IFactory>* factory = (boost::shared_ptr<AUD_IFactory>*) sound_get_factory((void *) lptr); if (factory) { Factory *obj = (Factory *)Factory_empty(); if (obj) { - obj->factory = new AUD_Reference<AUD_IFactory>(*factory); + obj->factory = new boost::shared_ptr<AUD_IFactory>(*factory); return (PyObject *) obj; } } @@ -245,7 +246,7 @@ void *AUD_getPythonFactory(AUD_Sound *sound) if (sound) { Factory *obj = (Factory *) Factory_empty(); if (obj) { - obj->factory = new AUD_Reference<AUD_IFactory>(*sound); + obj->factory = new boost::shared_ptr<AUD_IFactory>(*sound); return (PyObject *) obj; } } @@ -260,7 +261,7 @@ AUD_Sound *AUD_getPythonSound(void *sound) if (!factory) return NULL; - return new AUD_Reference<AUD_IFactory>(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(factory->factory)); + return new boost::shared_ptr<AUD_IFactory>(*reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(factory->factory)); } #endif @@ -285,9 +286,9 @@ AUD_SoundInfo AUD_getInfo(AUD_Sound *sound) info.length = 0.0f; try { - AUD_Reference<AUD_IReader> reader = (*sound)->createReader(); + boost::shared_ptr<AUD_IReader> reader = (*sound)->createReader(); - if (!reader.isNull()) { + if (reader.get()) { info.specs = reader->getSpecs(); info.length = reader->getLength() / (float) info.specs.rate; } @@ -431,7 +432,7 @@ AUD_Handle *AUD_play(AUD_Sound *sound, int keep) assert(sound); try { AUD_Handle handle = AUD_device->play(*sound, keep); - if (!handle.isNull()) { + if (handle.get()) { return new AUD_Handle(handle); } } @@ -551,9 +552,9 @@ int AUD_setDistanceModel(AUD_DistanceModel model) int AUD_setSourceLocation(AUD_Handle *handle, const float location[3]) { assert(handle); - AUD_Reference<AUD_I3DHandle> h(*handle); + boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle); - if (!h.isNull()) { + if (h.get()) { AUD_Vector3 v(location[0], location[1], location[2]); return h->setSourceLocation(v); } @@ -564,9 +565,9 @@ int AUD_setSourceLocation(AUD_Handle *handle, const float location[3]) int AUD_setSourceVelocity(AUD_Handle *handle, const float velocity[3]) { assert(handle); - AUD_Reference<AUD_I3DHandle> h(*handle); + boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle); - if (!h.isNull()) { + if (h.get()) { AUD_Vector3 v(velocity[0], velocity[1], velocity[2]); return h->setSourceVelocity(v); } @@ -577,9 +578,9 @@ int AUD_setSourceVelocity(AUD_Handle *handle, const float velocity[3]) int AUD_setSourceOrientation(AUD_Handle *handle, const float orientation[4]) { assert(handle); - AUD_Reference<AUD_I3DHandle> h(*handle); + boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle); - if (!h.isNull()) { + if (h.get()) { AUD_Quaternion q(orientation[3], orientation[0], orientation[1], orientation[2]); return h->setSourceOrientation(q); } @@ -590,9 +591,9 @@ int AUD_setSourceOrientation(AUD_Handle *handle, const float orientation[4]) int AUD_setRelative(AUD_Handle *handle, int relative) { assert(handle); - AUD_Reference<AUD_I3DHandle> h(*handle); + boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle); - if (!h.isNull()) { + if (h.get()) { return h->setRelative(relative); } @@ -602,9 +603,9 @@ int AUD_setRelative(AUD_Handle *handle, int relative) int AUD_setVolumeMaximum(AUD_Handle *handle, float volume) { assert(handle); - AUD_Reference<AUD_I3DHandle> h(*handle); + boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle); - if (!h.isNull()) { + if (h.get()) { return h->setVolumeMaximum(volume); } @@ -614,9 +615,9 @@ int AUD_setVolumeMaximum(AUD_Handle *handle, float volume) int AUD_setVolumeMinimum(AUD_Handle *handle, float volume) { assert(handle); - AUD_Reference<AUD_I3DHandle> h(*handle); + boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle); - if (!h.isNull()) { + if (h.get()) { return h->setVolumeMinimum(volume); } @@ -626,9 +627,9 @@ int AUD_setVolumeMinimum(AUD_Handle *handle, float volume) int AUD_setDistanceMaximum(AUD_Handle *handle, float distance) { assert(handle); - AUD_Reference<AUD_I3DHandle> h(*handle); + boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle); - if (!h.isNull()) { + if (h.get()) { return h->setDistanceMaximum(distance); } @@ -638,9 +639,9 @@ int AUD_setDistanceMaximum(AUD_Handle *handle, float distance) int AUD_setDistanceReference(AUD_Handle *handle, float distance) { assert(handle); - AUD_Reference<AUD_I3DHandle> h(*handle); + boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle); - if (!h.isNull()) { + if (h.get()) { return h->setDistanceReference(distance); } @@ -650,9 +651,9 @@ int AUD_setDistanceReference(AUD_Handle *handle, float distance) int AUD_setAttenuation(AUD_Handle *handle, float factor) { assert(handle); - AUD_Reference<AUD_I3DHandle> h(*handle); + boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle); - if (!h.isNull()) { + if (h.get()) { return h->setAttenuation(factor); } @@ -662,9 +663,9 @@ int AUD_setAttenuation(AUD_Handle *handle, float factor) int AUD_setConeAngleOuter(AUD_Handle *handle, float angle) { assert(handle); - AUD_Reference<AUD_I3DHandle> h(*handle); + boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle); - if (!h.isNull()) { + if (h.get()) { return h->setConeAngleOuter(angle); } @@ -674,9 +675,9 @@ int AUD_setConeAngleOuter(AUD_Handle *handle, float angle) int AUD_setConeAngleInner(AUD_Handle *handle, float angle) { assert(handle); - AUD_Reference<AUD_I3DHandle> h(*handle); + boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle); - if (!h.isNull()) { + if (h.get()) { return h->setConeAngleInner(angle); } @@ -686,9 +687,9 @@ int AUD_setConeAngleInner(AUD_Handle *handle, float angle) int AUD_setConeVolumeOuter(AUD_Handle *handle, float volume) { assert(handle); - AUD_Reference<AUD_I3DHandle> h(*handle); + boost::shared_ptr<AUD_I3DHandle> h = boost::dynamic_pointer_cast<AUD_I3DHandle>(*handle); - if (!h.isNull()) { + if (h.get()) { return h->setConeVolumeOuter(volume); } @@ -733,7 +734,7 @@ AUD_Handle *AUD_playDevice(AUD_Device *device, AUD_Sound *sound, float seek) try { AUD_Handle handle = (*device)->play(*sound); - if (!handle.isNull()) { + if (handle.get()) { handle->seek(seek); return new AUD_Handle(handle); } @@ -792,38 +793,38 @@ float *AUD_readSoundBuffer(const char *filename, float low, float high, AUD_DeviceSpecs specs; specs.channels = AUD_CHANNELS_MONO; specs.rate = (AUD_SampleRate)samplerate; - AUD_Reference<AUD_IFactory> sound; + boost::shared_ptr<AUD_IFactory> sound; - AUD_Reference<AUD_IFactory> file = new AUD_FileFactory(filename); + boost::shared_ptr<AUD_IFactory> file = boost::shared_ptr<AUD_IFactory>(new AUD_FileFactory(filename)); int position = 0; try { - AUD_Reference<AUD_IReader> reader = file->createReader(); + boost::shared_ptr<AUD_IReader> reader = file->createReader(); AUD_SampleRate rate = reader->getSpecs().rate; - sound = new AUD_ChannelMapperFactory(file, specs); + sound = boost::shared_ptr<AUD_IFactory>(new AUD_ChannelMapperFactory(file, specs)); if (high < rate) - sound = new AUD_LowpassFactory(sound, high); + sound = boost::shared_ptr<AUD_IFactory>(new AUD_LowpassFactory(sound, high)); if (low > 0) - sound = new AUD_HighpassFactory(sound, low); + sound = boost::shared_ptr<AUD_IFactory>(new AUD_HighpassFactory(sound, low)); - sound = new AUD_EnvelopeFactory(sound, attack, release, threshold, 0.1f); - sound = new AUD_LinearResampleFactory(sound, specs); + sound = boost::shared_ptr<AUD_IFactory>(new AUD_EnvelopeFactory(sound, attack, release, threshold, 0.1f)); + sound = boost::shared_ptr<AUD_IFactory>(new AUD_LinearResampleFactory(sound, specs)); if (square) - sound = new AUD_SquareFactory(sound, sthreshold); + sound = boost::shared_ptr<AUD_IFactory>(new AUD_SquareFactory(sound, sthreshold)); if (accumulate) - sound = new AUD_AccumulatorFactory(sound, additive); + sound = boost::shared_ptr<AUD_IFactory>(new AUD_AccumulatorFactory(sound, additive)); else if (additive) - sound = new AUD_SumFactory(sound); + sound = boost::shared_ptr<AUD_IFactory>(new AUD_SumFactory(sound)); reader = sound->createReader(); - if (reader.isNull()) + if (!reader.get()) return NULL; int len; @@ -855,16 +856,15 @@ static void pauseSound(AUD_Handle *handle) AUD_Handle *AUD_pauseAfter(AUD_Handle *handle, float seconds) { - AUD_Reference<AUD_IFactory> silence = new AUD_SilenceFactory; - AUD_Reference<AUD_IFactory> limiter = new AUD_LimiterFactory(silence, 0, seconds); + boost::shared_ptr<AUD_IFactory> silence = boost::shared_ptr<AUD_IFactory>(new AUD_SilenceFactory); + boost::shared_ptr<AUD_IFactory> limiter = boost::shared_ptr<AUD_IFactory>(new AUD_LimiterFactory(silence, 0, seconds)); - AUD_device->lock(); + AUD_MutexLock lock(*AUD_device); try { AUD_Handle handle2 = AUD_device->play(limiter); - if (!handle2.isNull()) { + if (handle2.get()) { handle2->setStopCallback((stopCallback)pauseSound, handle); - AUD_device->unlock(); return new AUD_Handle(handle2); } } @@ -872,8 +872,6 @@ AUD_Handle *AUD_pauseAfter(AUD_Handle *handle, float seconds) { } - AUD_device->unlock(); - return NULL; } @@ -883,7 +881,7 @@ AUD_Sound *AUD_createSequencer(float fps, int muted) AUD_Specs specs; specs.channels = AUD_CHANNELS_STEREO; specs.rate = AUD_RATE_44100; - AUD_Sound *sequencer = new AUD_Sound(AUD_Reference<AUD_SequencerFactory>(new AUD_SequencerFactory(specs, fps, muted))); + AUD_Sound *sequencer = new AUD_Sound(boost::shared_ptr<AUD_SequencerFactory>(new AUD_SequencerFactory(specs, fps, muted))); return sequencer; } @@ -1072,7 +1070,7 @@ int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_pe specs.channels = AUD_CHANNELS_MONO; specs.format = AUD_FORMAT_INVALID; - AUD_Reference<AUD_IReader> reader = AUD_ChannelMapperFactory(*sound, specs).createReader(); + boost::shared_ptr<AUD_IReader> reader = AUD_ChannelMapperFactory(*sound, specs).createReader(); specs.specs = reader->getSpecs(); int len; @@ -1126,7 +1124,7 @@ int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_pe AUD_Sound *AUD_copy(AUD_Sound *sound) { - return new AUD_Reference<AUD_IFactory>(*sound); + return new boost::shared_ptr<AUD_IFactory>(*sound); } void AUD_freeHandle(AUD_Handle *handle) @@ -1178,9 +1176,9 @@ const char *AUD_mixdown(AUD_Sound *sound, unsigned int start, unsigned int lengt AUD_SequencerFactory *f = dynamic_cast<AUD_SequencerFactory *>(sound->get()); f->setSpecs(specs.specs); - AUD_Reference<AUD_IReader> reader = f->createQualityReader(); + boost::shared_ptr<AUD_IReader> reader = f->createQualityReader(); reader->seek(start); - AUD_Reference<AUD_IWriter> writer = AUD_FileWriter::createWriter(filename, specs, format, codec, bitrate); + boost::shared_ptr<AUD_IWriter> writer = AUD_FileWriter::createWriter(filename, specs, format, codec, bitrate); AUD_FileWriter::writeReader(reader, writer, length, buffersize); return NULL; @@ -1198,7 +1196,7 @@ const char *AUD_mixdown_per_channel(AUD_Sound *sound, unsigned int start, unsign f->setSpecs(specs.specs); - std::vector<AUD_Reference<AUD_IWriter> > writers; + std::vector<boost::shared_ptr<AUD_IWriter> > writers; int channels = specs.channels; specs.channels = AUD_CHANNELS_MONO; @@ -1222,7 +1220,7 @@ const char *AUD_mixdown_per_channel(AUD_Sound *sound, unsigned int start, unsign writers.push_back(AUD_FileWriter::createWriter(stream.str(), specs, format, codec, bitrate)); } - AUD_Reference<AUD_IReader> reader = f->createQualityReader(); + boost::shared_ptr<AUD_IReader> reader = f->createQualityReader(); reader->seek(start); AUD_FileWriter::writeReader(reader, writers, length, buffersize); @@ -1244,7 +1242,7 @@ AUD_Device *AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound *sequencer, f dynamic_cast<AUD_SequencerFactory *>(sequencer->get())->setSpecs(specs.specs); AUD_Handle handle = device->play(*sequencer); - if (!handle.isNull()) { + if (handle.get()) { handle->seek(start); } @@ -1256,7 +1254,7 @@ AUD_Device *AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound *sequencer, f } } -AUD_Reference<AUD_IDevice> AUD_getDevice() +boost::shared_ptr<AUD_IDevice> AUD_getDevice() { return AUD_device; } diff --git a/intern/audaspace/intern/AUD_C-API.h b/intern/audaspace/intern/AUD_C-API.h index 75e3456de9a..9c6611fe04a 100644 --- a/intern/audaspace/intern/AUD_C-API.h +++ b/intern/audaspace/intern/AUD_C-API.h @@ -755,7 +755,7 @@ extern AUD_Sound *AUD_getPythonSound(void *sound); #ifdef __cplusplus } -#include "AUD_Reference.h" +#include <boost/shared_ptr.hpp> class AUD_IDevice; class AUD_I3DDevice; @@ -763,7 +763,7 @@ class AUD_I3DDevice; * Returns the current playback device. * \return The playback device. */ -AUD_Reference<AUD_IDevice> AUD_getDevice(); +boost::shared_ptr<AUD_IDevice> AUD_getDevice(); /** * Returns the current playback 3D device. diff --git a/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp b/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp index 7743ccf46da..f4ba5d05ff0 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp +++ b/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp @@ -32,14 +32,14 @@ #include <cstring> -AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_Reference<AUD_IFactory> factory, +AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(boost::shared_ptr<AUD_IFactory> factory, AUD_DeviceSpecs specs) : AUD_MixerFactory(factory, specs) { } -AUD_Reference<AUD_IReader> AUD_ChannelMapperFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_ChannelMapperFactory::createReader() { - AUD_Reference<AUD_IReader> reader = getReader(); - return new AUD_ChannelMapperReader(reader, m_specs.channels); + boost::shared_ptr<AUD_IReader> reader = getReader(); + return boost::shared_ptr<AUD_IReader>(new AUD_ChannelMapperReader(reader, m_specs.channels)); } diff --git a/intern/audaspace/intern/AUD_ChannelMapperFactory.h b/intern/audaspace/intern/AUD_ChannelMapperFactory.h index b60a32d5510..611b5041c39 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperFactory.h +++ b/intern/audaspace/intern/AUD_ChannelMapperFactory.h @@ -49,9 +49,9 @@ public: * \param factory The input factory. * \param specs The target specifications. */ - AUD_ChannelMapperFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs); + AUD_ChannelMapperFactory(boost::shared_ptr<AUD_IFactory> factory, AUD_DeviceSpecs specs); - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif //__AUD_CHANNELMAPPERFACTORY_H__ diff --git a/intern/audaspace/intern/AUD_ChannelMapperReader.cpp b/intern/audaspace/intern/AUD_ChannelMapperReader.cpp index 61796098bf7..8b983d5c43d 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperReader.cpp +++ b/intern/audaspace/intern/AUD_ChannelMapperReader.cpp @@ -38,7 +38,7 @@ #include "AUD_ChannelMapperReader.h" -AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_Reference<AUD_IReader> reader, +AUD_ChannelMapperReader::AUD_ChannelMapperReader(boost::shared_ptr<AUD_IReader> reader, AUD_Channels channels) : AUD_EffectReader(reader), m_target_channels(channels), m_source_channels(AUD_CHANNELS_INVALID), m_mapping(0), m_map_size(0), m_mono_angle(0) @@ -67,10 +67,12 @@ void AUD_ChannelMapperReader::setMonoAngle(float angle) float AUD_ChannelMapperReader::angleDistance(float alpha, float beta) { - alpha = fabs(alpha - beta); + alpha = beta - alpha; if(alpha > M_PI) - alpha = fabs(alpha - 2 * M_PI); + alpha -= 2 * M_PI; + if(alpha < -M_PI) + alpha += 2 * M_PI; return alpha; } @@ -107,8 +109,8 @@ void AUD_ChannelMapperReader::calculateMapping() if(m_source_channels == AUD_CHANNELS_MONO) source_angles = &m_mono_angle; - int channel_min1, channel_min2; - float angle_min1, angle_min2, angle; + int channel_left, channel_right; + float angle_left, angle_right, angle; for(int i = 0; i < m_source_channels; i++) { @@ -120,38 +122,46 @@ void AUD_ChannelMapperReader::calculateMapping() continue; } - channel_min1 = channel_min2 = -1; - angle_min1 = angle_min2 = 2 * M_PI; + channel_left = channel_right = -1; + angle_left = -2 * M_PI; + angle_right = 2 * M_PI; for(int j = 0; j < m_target_channels; j++) { if(j == lfe) continue; angle = angleDistance(source_angles[i], target_angles[j]); - if(angle < angle_min1) + if(angle < 0) { - channel_min2 = channel_min1; - angle_min2 = angle_min1; - - channel_min1 = j; - angle_min1 = angle; + if(angle > angle_left) + { + angle_left = angle; + channel_left = j; + } } - else if(angle < angle_min2) + else { - channel_min2 = j; - angle_min2 = angle; + if(angle < angle_right) + { + angle_right = angle; + channel_right = j; + } } } - angle = angle_min1 + angle_min2; - if(channel_min2 == -1 || angle == 0) + angle = angle_right - angle_left; + if(channel_right == -1 || angle == 0) + { + m_mapping[channel_left * m_source_channels + i] = 1; + } + else if(channel_left == -1) { - m_mapping[channel_min1 * m_source_channels + i] = 1; + m_mapping[channel_right * m_source_channels + i] = 1; } else { - m_mapping[channel_min1 * m_source_channels + i] = cos(M_PI_2 * angle_min1 / angle); - m_mapping[channel_min2 * m_source_channels + i] = cos(M_PI_2 * angle_min2 / angle); + m_mapping[channel_left * m_source_channels + i] = cos(M_PI_2 * angle_left / angle); + m_mapping[channel_right * m_source_channels + i] = cos(M_PI_2 * angle_right / angle); } } diff --git a/intern/audaspace/intern/AUD_ChannelMapperReader.h b/intern/audaspace/intern/AUD_ChannelMapperReader.h index 32adb058115..b122b070d29 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperReader.h +++ b/intern/audaspace/intern/AUD_ChannelMapperReader.h @@ -110,7 +110,7 @@ public: * \param reader The reader to map. * \param mapping The mapping specification as two dimensional float array. */ - AUD_ChannelMapperReader(AUD_Reference<AUD_IReader> reader, AUD_Channels channels); + AUD_ChannelMapperReader(boost::shared_ptr<AUD_IReader> reader, AUD_Channels channels); /** * Destroys the reader. diff --git a/intern/audaspace/intern/AUD_ConverterFactory.cpp b/intern/audaspace/intern/AUD_ConverterFactory.cpp index b61f9bc194c..7cbf64f1697 100644 --- a/intern/audaspace/intern/AUD_ConverterFactory.cpp +++ b/intern/audaspace/intern/AUD_ConverterFactory.cpp @@ -30,18 +30,18 @@ #include "AUD_ConverterFactory.h" #include "AUD_ConverterReader.h" -AUD_ConverterFactory::AUD_ConverterFactory(AUD_Reference<AUD_IFactory> factory, +AUD_ConverterFactory::AUD_ConverterFactory(boost::shared_ptr<AUD_IFactory> factory, AUD_DeviceSpecs specs) : AUD_MixerFactory(factory, specs) { } -AUD_Reference<AUD_IReader> AUD_ConverterFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_ConverterFactory::createReader() { - AUD_Reference<AUD_IReader> reader = getReader(); + boost::shared_ptr<AUD_IReader> reader = getReader(); if(m_specs.format != AUD_FORMAT_FLOAT32) - reader = new AUD_ConverterReader(reader, m_specs); + reader = boost::shared_ptr<AUD_IReader>(new AUD_ConverterReader(reader, m_specs)); return reader; } diff --git a/intern/audaspace/intern/AUD_ConverterFactory.h b/intern/audaspace/intern/AUD_ConverterFactory.h index 3211b607517..2c9c82d235b 100644 --- a/intern/audaspace/intern/AUD_ConverterFactory.h +++ b/intern/audaspace/intern/AUD_ConverterFactory.h @@ -49,9 +49,9 @@ public: * \param factory The input factory. * \param specs The target specifications. */ - AUD_ConverterFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs); + AUD_ConverterFactory(boost::shared_ptr<AUD_IFactory> factory, AUD_DeviceSpecs specs); - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif //__AUD_CONVERTERFACTORY_H__ diff --git a/intern/audaspace/intern/AUD_ConverterReader.cpp b/intern/audaspace/intern/AUD_ConverterReader.cpp index 63178f316b2..a90a54670e8 100644 --- a/intern/audaspace/intern/AUD_ConverterReader.cpp +++ b/intern/audaspace/intern/AUD_ConverterReader.cpp @@ -29,7 +29,7 @@ #include "AUD_ConverterReader.h" -AUD_ConverterReader::AUD_ConverterReader(AUD_Reference<AUD_IReader> reader, +AUD_ConverterReader::AUD_ConverterReader(boost::shared_ptr<AUD_IReader> reader, AUD_DeviceSpecs specs) : AUD_EffectReader(reader), m_format(specs.format) diff --git a/intern/audaspace/intern/AUD_ConverterReader.h b/intern/audaspace/intern/AUD_ConverterReader.h index 2dedbd89180..987b7c70279 100644 --- a/intern/audaspace/intern/AUD_ConverterReader.h +++ b/intern/audaspace/intern/AUD_ConverterReader.h @@ -65,7 +65,7 @@ public: * \param reader The reader to convert. * \param specs The target specification. */ - AUD_ConverterReader(AUD_Reference<AUD_IReader> reader, AUD_DeviceSpecs specs); + AUD_ConverterReader(boost::shared_ptr<AUD_IReader> reader, AUD_DeviceSpecs specs); virtual void read(int& length, bool& eos, sample_t* buffer); }; diff --git a/intern/audaspace/intern/AUD_FileFactory.cpp b/intern/audaspace/intern/AUD_FileFactory.cpp index a27acff19cf..f9353db6677 100644 --- a/intern/audaspace/intern/AUD_FileFactory.cpp +++ b/intern/audaspace/intern/AUD_FileFactory.cpp @@ -56,15 +56,15 @@ AUD_FileFactory::AUD_FileFactory(const data_t* buffer, int size) : static const char* read_error = "AUD_FileFactory: File couldn't be read."; -AUD_Reference<AUD_IReader> AUD_FileFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_FileFactory::createReader() { #ifdef WITH_SNDFILE try { - if(m_buffer.isNull()) - return new AUD_SndFileReader(m_filename); + if(m_buffer.get()) + return boost::shared_ptr<AUD_IReader>(new AUD_SndFileReader(m_buffer)); else - return new AUD_SndFileReader(m_buffer); + return boost::shared_ptr<AUD_IReader>(new AUD_SndFileReader(m_filename)); } catch(AUD_Exception&) {} #endif @@ -72,10 +72,10 @@ AUD_Reference<AUD_IReader> AUD_FileFactory::createReader() #ifdef WITH_FFMPEG try { - if(m_buffer.isNull()) - return new AUD_FFMPEGReader(m_filename); + if(m_buffer.get()) + return boost::shared_ptr<AUD_IReader>(new AUD_FFMPEGReader(m_buffer)); else - return new AUD_FFMPEGReader(m_buffer); + return boost::shared_ptr<AUD_IReader>(new AUD_FFMPEGReader(m_filename)); } catch(AUD_Exception&) {} #endif diff --git a/intern/audaspace/intern/AUD_FileFactory.h b/intern/audaspace/intern/AUD_FileFactory.h index 4ea4a9392e9..35c8db731b4 100644 --- a/intern/audaspace/intern/AUD_FileFactory.h +++ b/intern/audaspace/intern/AUD_FileFactory.h @@ -31,10 +31,10 @@ #define __AUD_FILEFACTORY_H__ #include "AUD_IFactory.h" -#include "AUD_Reference.h" #include "AUD_Buffer.h" #include <string> +#include <boost/shared_ptr.hpp> /** * This factory tries to read a sound file via all available file readers. @@ -50,7 +50,7 @@ private: /** * The buffer to read from. */ - AUD_Reference<AUD_Buffer> m_buffer; + boost::shared_ptr<AUD_Buffer> m_buffer; // hide copy constructor and operator= AUD_FileFactory(const AUD_FileFactory&); @@ -70,7 +70,7 @@ public: */ AUD_FileFactory(const data_t* buffer, int size); - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif //__AUD_FILEFACTORY_H__ diff --git a/intern/audaspace/intern/AUD_FileWriter.cpp b/intern/audaspace/intern/AUD_FileWriter.cpp index f74021acad1..e3072fa82e0 100644 --- a/intern/audaspace/intern/AUD_FileWriter.cpp +++ b/intern/audaspace/intern/AUD_FileWriter.cpp @@ -43,13 +43,13 @@ static const char* write_error = "AUD_FileWriter: File couldn't be written."; -AUD_Reference<AUD_IWriter> AUD_FileWriter::createWriter(std::string filename,AUD_DeviceSpecs specs, +boost::shared_ptr<AUD_IWriter> AUD_FileWriter::createWriter(std::string filename,AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate) { #ifdef WITH_SNDFILE try { - return new AUD_SndFileWriter(filename, specs, format, codec, bitrate); + return boost::shared_ptr<AUD_IWriter>(new AUD_SndFileWriter(filename, specs, format, codec, bitrate)); } catch(AUD_Exception&) {} #endif @@ -57,7 +57,7 @@ AUD_Reference<AUD_IWriter> AUD_FileWriter::createWriter(std::string filename,AUD #ifdef WITH_FFMPEG try { - return new AUD_FFMPEGWriter(filename, specs, format, codec, bitrate); + return boost::shared_ptr<AUD_IWriter>(new AUD_FFMPEGWriter(filename, specs, format, codec, bitrate)); } catch(AUD_Exception&) {} #endif @@ -65,7 +65,7 @@ AUD_Reference<AUD_IWriter> AUD_FileWriter::createWriter(std::string filename,AUD AUD_THROW(AUD_ERROR_SPECS, write_error); } -void AUD_FileWriter::writeReader(AUD_Reference<AUD_IReader> reader, AUD_Reference<AUD_IWriter> writer, unsigned int length, unsigned int buffersize) +void AUD_FileWriter::writeReader(boost::shared_ptr<AUD_IReader> reader, boost::shared_ptr<AUD_IWriter> writer, unsigned int length, unsigned int buffersize) { AUD_Buffer buffer(buffersize * AUD_SAMPLE_SIZE(writer->getSpecs())); sample_t* buf = buffer.getBuffer(); @@ -94,7 +94,7 @@ void AUD_FileWriter::writeReader(AUD_Reference<AUD_IReader> reader, AUD_Referenc } } -void AUD_FileWriter::writeReader(AUD_Reference<AUD_IReader> reader, std::vector<AUD_Reference<AUD_IWriter> >& writers, unsigned int length, unsigned int buffersize) +void AUD_FileWriter::writeReader(boost::shared_ptr<AUD_IReader> reader, std::vector<boost::shared_ptr<AUD_IWriter> >& writers, unsigned int length, unsigned int buffersize) { AUD_Buffer buffer(buffersize * AUD_SAMPLE_SIZE(reader->getSpecs())); AUD_Buffer buffer2(buffersize * sizeof(sample_t)); diff --git a/intern/audaspace/intern/AUD_FileWriter.h b/intern/audaspace/intern/AUD_FileWriter.h index 385aba5ef45..da52c7e0fb2 100644 --- a/intern/audaspace/intern/AUD_FileWriter.h +++ b/intern/audaspace/intern/AUD_FileWriter.h @@ -32,8 +32,7 @@ #include <string> #include <vector> - -#include "AUD_Reference.h" +#include <boost/shared_ptr.hpp> #include "AUD_IWriter.h" #include "AUD_IReader.h" @@ -59,7 +58,7 @@ public: * \param bitrate The bitrate for encoding. * \return The writer to write data to. */ - static AUD_Reference<AUD_IWriter> createWriter(std::string filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate); + static boost::shared_ptr<AUD_IWriter> createWriter(std::string filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate); /** * Writes a reader to a writer. @@ -68,7 +67,7 @@ public: * \param length How many samples should be transfered. * \param buffersize How many samples should be transfered at once. */ - static void writeReader(AUD_Reference<AUD_IReader> reader, AUD_Reference<AUD_IWriter> writer, unsigned int length, unsigned int buffersize); + static void writeReader(boost::shared_ptr<AUD_IReader> reader, boost::shared_ptr<AUD_IWriter> writer, unsigned int length, unsigned int buffersize); /** * Writes a reader to several writers. @@ -77,7 +76,7 @@ public: * \param length How many samples should be transfered. * \param buffersize How many samples should be transfered at once. */ - static void writeReader(AUD_Reference<AUD_IReader> reader, std::vector<AUD_Reference<AUD_IWriter> >& writers, unsigned int length, unsigned int buffersize); + static void writeReader(boost::shared_ptr<AUD_IReader> reader, std::vector<boost::shared_ptr<AUD_IWriter> >& writers, unsigned int length, unsigned int buffersize); }; #endif //__AUD_FILEWRITER_H__ diff --git a/intern/audaspace/intern/AUD_IDevice.h b/intern/audaspace/intern/AUD_IDevice.h index 1d6f8ca6efb..a7f9a985ce4 100644 --- a/intern/audaspace/intern/AUD_IDevice.h +++ b/intern/audaspace/intern/AUD_IDevice.h @@ -31,10 +31,12 @@ #define __AUD_IDEVICE_H__ #include "AUD_Space.h" -#include "AUD_Reference.h" #include "AUD_IFactory.h" #include "AUD_IReader.h" #include "AUD_IHandle.h" +#include "AUD_ILockable.h" + +#include <boost/shared_ptr.hpp> /** * This class represents an output device for sound sources. @@ -44,7 +46,7 @@ * \warning Thread safety must be insured so that no reader is beeing called * twice at the same time. */ -class AUD_IDevice +class AUD_IDevice : public AUD_ILockable { public: /** @@ -67,7 +69,7 @@ public: * \exception AUD_Exception Thrown if there's an unexpected (from the * device side) error during creation of the reader. */ - virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IReader> reader, bool keep = false)=0; + virtual boost::shared_ptr<AUD_IHandle> play(boost::shared_ptr<AUD_IReader> reader, bool keep = false)=0; /** * Plays a sound source. @@ -79,7 +81,7 @@ public: * \exception AUD_Exception Thrown if there's an unexpected (from the * device side) error during creation of the reader. */ - virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IFactory> factory, bool keep = false)=0; + virtual boost::shared_ptr<AUD_IHandle> play(boost::shared_ptr<AUD_IFactory> factory, bool keep = false)=0; /** * Stops all playing sounds. diff --git a/intern/audaspace/intern/AUD_IFactory.h b/intern/audaspace/intern/AUD_IFactory.h index 95b4643072e..75103963c68 100644 --- a/intern/audaspace/intern/AUD_IFactory.h +++ b/intern/audaspace/intern/AUD_IFactory.h @@ -31,9 +31,10 @@ #define __AUD_IFACTORY_H__ #include "AUD_Space.h" -#include "AUD_Reference.h" #include "AUD_IReader.h" +#include <boost/shared_ptr.hpp> + /** * This class represents a type of sound source and saves the necessary values * for it. It is able to create a reader that is actually usable for playback @@ -54,7 +55,7 @@ public: * \exception AUD_Exception An exception may be thrown if there has been * a more unexpected error during reader creation. */ - virtual AUD_Reference<AUD_IReader> createReader()=0; + virtual boost::shared_ptr<AUD_IReader> createReader()=0; }; #endif //__AUD_IFACTORY_H__ diff --git a/intern/audaspace/intern/AUD_ILockable.h b/intern/audaspace/intern/AUD_ILockable.h new file mode 100644 index 00000000000..9bc417504fe --- /dev/null +++ b/intern/audaspace/intern/AUD_ILockable.h @@ -0,0 +1,21 @@ +#ifndef AUD_ILOCKABLE_H +#define AUD_ILOCKABLE_H + +/** + * This class provides an interface for lockable objects. + * The main reason for this interface is to be used with AUD_MutexLock. + */ +class AUD_ILockable +{ +public: + /** + * Locks the object. + */ + virtual void lock()=0; + /** + * Unlocks the previously locked object. + */ + virtual void unlock()=0; +}; + +#endif // AUD_ILOCKABLE_H diff --git a/intern/audaspace/intern/AUD_JOSResampleFactory.cpp b/intern/audaspace/intern/AUD_JOSResampleFactory.cpp index 21aae6b0547..188960f986f 100644 --- a/intern/audaspace/intern/AUD_JOSResampleFactory.cpp +++ b/intern/audaspace/intern/AUD_JOSResampleFactory.cpp @@ -30,13 +30,13 @@ #include "AUD_JOSResampleFactory.h" #include "AUD_JOSResampleReader.h" -AUD_JOSResampleFactory::AUD_JOSResampleFactory(AUD_Reference<AUD_IFactory> factory, +AUD_JOSResampleFactory::AUD_JOSResampleFactory(boost::shared_ptr<AUD_IFactory> factory, AUD_DeviceSpecs specs) : AUD_MixerFactory(factory, specs) { } -AUD_Reference<AUD_IReader> AUD_JOSResampleFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_JOSResampleFactory::createReader() { - return new AUD_JOSResampleReader(getReader(), m_specs.specs); + return boost::shared_ptr<AUD_IReader>(new AUD_JOSResampleReader(getReader(), m_specs.specs)); } diff --git a/intern/audaspace/intern/AUD_JOSResampleFactory.h b/intern/audaspace/intern/AUD_JOSResampleFactory.h index 6d18150d852..b6c2961c88a 100644 --- a/intern/audaspace/intern/AUD_JOSResampleFactory.h +++ b/intern/audaspace/intern/AUD_JOSResampleFactory.h @@ -48,9 +48,9 @@ public: * \param factory The input factory. * \param specs The target specifications. */ - AUD_JOSResampleFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs); + AUD_JOSResampleFactory(boost::shared_ptr<AUD_IFactory> factory, AUD_DeviceSpecs specs); - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif //__AUD_JOSRESAMPLEFACTORY_H__ diff --git a/intern/audaspace/intern/AUD_JOSResampleReader.cpp b/intern/audaspace/intern/AUD_JOSResampleReader.cpp index 0f7a038c88e..62fab48272b 100644 --- a/intern/audaspace/intern/AUD_JOSResampleReader.cpp +++ b/intern/audaspace/intern/AUD_JOSResampleReader.cpp @@ -68,7 +68,7 @@ static inline int lrint(double d) #define fp_rest(x) (x & ((1 << SHIFT_BITS) - 1)) #define fp_rest_to_double(x) fp_to_double(fp_rest(x)) -AUD_JOSResampleReader::AUD_JOSResampleReader(AUD_Reference<AUD_IReader> reader, AUD_Specs specs) : +AUD_JOSResampleReader::AUD_JOSResampleReader(boost::shared_ptr<AUD_IReader> reader, AUD_Specs specs) : AUD_ResampleReader(reader, specs.rate), m_channels(AUD_CHANNELS_INVALID), m_n(0), diff --git a/intern/audaspace/intern/AUD_JOSResampleReader.h b/intern/audaspace/intern/AUD_JOSResampleReader.h index 94524c1db3e..fb68e4dc9f5 100644 --- a/intern/audaspace/intern/AUD_JOSResampleReader.h +++ b/intern/audaspace/intern/AUD_JOSResampleReader.h @@ -123,7 +123,7 @@ public: * \param reader The reader to mix. * \param specs The target specification. */ - AUD_JOSResampleReader(AUD_Reference<AUD_IReader> reader, AUD_Specs specs); + AUD_JOSResampleReader(boost::shared_ptr<AUD_IReader> reader, AUD_Specs specs); virtual void seek(int position); virtual int getLength() const; diff --git a/intern/audaspace/intern/AUD_LinearResampleFactory.cpp b/intern/audaspace/intern/AUD_LinearResampleFactory.cpp index 7f602599b7a..cd573f1047c 100644 --- a/intern/audaspace/intern/AUD_LinearResampleFactory.cpp +++ b/intern/audaspace/intern/AUD_LinearResampleFactory.cpp @@ -30,13 +30,13 @@ #include "AUD_LinearResampleFactory.h" #include "AUD_LinearResampleReader.h" -AUD_LinearResampleFactory::AUD_LinearResampleFactory(AUD_Reference<AUD_IFactory> factory, +AUD_LinearResampleFactory::AUD_LinearResampleFactory(boost::shared_ptr<AUD_IFactory> factory, AUD_DeviceSpecs specs) : AUD_MixerFactory(factory, specs) { } -AUD_Reference<AUD_IReader> AUD_LinearResampleFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_LinearResampleFactory::createReader() { - return new AUD_LinearResampleReader(getReader(), m_specs.specs); + return boost::shared_ptr<AUD_IReader>(new AUD_LinearResampleReader(getReader(), m_specs.specs)); } diff --git a/intern/audaspace/intern/AUD_LinearResampleFactory.h b/intern/audaspace/intern/AUD_LinearResampleFactory.h index 7d9efa01d2d..ceb29ef2edd 100644 --- a/intern/audaspace/intern/AUD_LinearResampleFactory.h +++ b/intern/audaspace/intern/AUD_LinearResampleFactory.h @@ -48,9 +48,9 @@ public: * \param factory The input factory. * \param specs The target specifications. */ - AUD_LinearResampleFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs); + AUD_LinearResampleFactory(boost::shared_ptr<AUD_IFactory> factory, AUD_DeviceSpecs specs); - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif //__AUD_LINEARRESAMPLEFACTORY_H__ diff --git a/intern/audaspace/intern/AUD_LinearResampleReader.cpp b/intern/audaspace/intern/AUD_LinearResampleReader.cpp index aff62d7c3aa..6aa0faed863 100644 --- a/intern/audaspace/intern/AUD_LinearResampleReader.cpp +++ b/intern/audaspace/intern/AUD_LinearResampleReader.cpp @@ -34,7 +34,7 @@ #define CC m_channels + channel -AUD_LinearResampleReader::AUD_LinearResampleReader(AUD_Reference<AUD_IReader> reader, +AUD_LinearResampleReader::AUD_LinearResampleReader(boost::shared_ptr<AUD_IReader> reader, AUD_Specs specs) : AUD_ResampleReader(reader, specs.rate), m_channels(reader->getSpecs().channels), diff --git a/intern/audaspace/intern/AUD_LinearResampleReader.h b/intern/audaspace/intern/AUD_LinearResampleReader.h index 4f6d422f772..9beea251c07 100644 --- a/intern/audaspace/intern/AUD_LinearResampleReader.h +++ b/intern/audaspace/intern/AUD_LinearResampleReader.h @@ -74,7 +74,7 @@ public: * \param reader The reader to mix. * \param specs The target specification. */ - AUD_LinearResampleReader(AUD_Reference<AUD_IReader> reader, AUD_Specs specs); + AUD_LinearResampleReader(boost::shared_ptr<AUD_IReader> reader, AUD_Specs specs); virtual void seek(int position); virtual int getLength() const; diff --git a/intern/audaspace/intern/AUD_Mixer.h b/intern/audaspace/intern/AUD_Mixer.h index 0de9b7fc7dc..3dd03b0a3fe 100644 --- a/intern/audaspace/intern/AUD_Mixer.h +++ b/intern/audaspace/intern/AUD_Mixer.h @@ -32,9 +32,10 @@ #include "AUD_ConverterFunctions.h" #include "AUD_Buffer.h" -#include "AUD_Reference.h" class AUD_IReader; +#include <boost/shared_ptr.hpp> + /** * This abstract class is able to mix audiosignals with same channel count * and sample rate and convert it to a specific output format. diff --git a/intern/audaspace/intern/AUD_MixerFactory.cpp b/intern/audaspace/intern/AUD_MixerFactory.cpp index 95a7291d3eb..f3f00ea2cb6 100644 --- a/intern/audaspace/intern/AUD_MixerFactory.cpp +++ b/intern/audaspace/intern/AUD_MixerFactory.cpp @@ -30,12 +30,12 @@ #include "AUD_MixerFactory.h" #include "AUD_IReader.h" -AUD_Reference<AUD_IReader> AUD_MixerFactory::getReader() const +boost::shared_ptr<AUD_IReader> AUD_MixerFactory::getReader() const { return m_factory->createReader(); } -AUD_MixerFactory::AUD_MixerFactory(AUD_Reference<AUD_IFactory> factory, +AUD_MixerFactory::AUD_MixerFactory(boost::shared_ptr<AUD_IFactory> factory, AUD_DeviceSpecs specs) : m_specs(specs), m_factory(factory) { @@ -46,7 +46,7 @@ AUD_DeviceSpecs AUD_MixerFactory::getSpecs() const return m_specs; } -AUD_Reference<AUD_IFactory> AUD_MixerFactory::getFactory() const +boost::shared_ptr<AUD_IFactory> AUD_MixerFactory::getFactory() const { return m_factory; } diff --git a/intern/audaspace/intern/AUD_MixerFactory.h b/intern/audaspace/intern/AUD_MixerFactory.h index d65eb8ef6ae..1d2b6a4cc91 100644 --- a/intern/audaspace/intern/AUD_MixerFactory.h +++ b/intern/audaspace/intern/AUD_MixerFactory.h @@ -46,7 +46,7 @@ protected: /** * If there is no reader it is created out of this factory. */ - AUD_Reference<AUD_IFactory> m_factory; + boost::shared_ptr<AUD_IFactory> m_factory; /** * Returns the reader created out of the factory. @@ -54,7 +54,7 @@ protected: * classes. * \return The reader to mix. */ - AUD_Reference<AUD_IReader> getReader() const; + boost::shared_ptr<AUD_IReader> getReader() const; public: /** @@ -62,7 +62,7 @@ public: * \param factory The factory to create the readers to mix out of. * \param specs The target specification. */ - AUD_MixerFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs); + AUD_MixerFactory(boost::shared_ptr<AUD_IFactory> factory, AUD_DeviceSpecs specs); /** * Returns the target specification for resampling. @@ -73,7 +73,7 @@ public: * Returns the saved factory. * \return The factory. */ - AUD_Reference<AUD_IFactory> getFactory() const; + boost::shared_ptr<AUD_IFactory> getFactory() const; }; #endif //__AUD_MIXERFACTORY_H__ diff --git a/intern/audaspace/intern/AUD_MutexLock.h b/intern/audaspace/intern/AUD_MutexLock.h new file mode 100644 index 00000000000..b6f6d2b4334 --- /dev/null +++ b/intern/audaspace/intern/AUD_MutexLock.h @@ -0,0 +1,24 @@ +#ifndef AUD_MUTEXLOCK_H +#define AUD_MUTEXLOCK_H + +#include "AUD_ILockable.h" + +class AUD_MutexLock +{ +public: + inline AUD_MutexLock(AUD_ILockable& lockable) : + lockable(lockable) + { + lockable.lock(); + } + + inline ~AUD_MutexLock() + { + lockable.unlock(); + } + +private: + AUD_ILockable& lockable; +}; + +#endif // AUD_MUTEXLOCK_H diff --git a/intern/audaspace/intern/AUD_NULLDevice.cpp b/intern/audaspace/intern/AUD_NULLDevice.cpp index f390971c686..98a0d324c61 100644 --- a/intern/audaspace/intern/AUD_NULLDevice.cpp +++ b/intern/audaspace/intern/AUD_NULLDevice.cpp @@ -127,14 +127,14 @@ AUD_DeviceSpecs AUD_NULLDevice::getSpecs() const return specs; } -AUD_Reference<AUD_IHandle> AUD_NULLDevice::play(AUD_Reference<AUD_IReader> reader, bool keep) +boost::shared_ptr<AUD_IHandle> AUD_NULLDevice::play(boost::shared_ptr<AUD_IReader> reader, bool keep) { - return new AUD_NULLHandle(); + return boost::shared_ptr<AUD_IHandle>(new AUD_NULLHandle()); } -AUD_Reference<AUD_IHandle> AUD_NULLDevice::play(AUD_Reference<AUD_IFactory> factory, bool keep) +boost::shared_ptr<AUD_IHandle> AUD_NULLDevice::play(boost::shared_ptr<AUD_IFactory> factory, bool keep) { - return new AUD_NULLHandle(); + return boost::shared_ptr<AUD_IHandle>(new AUD_NULLHandle()); } void AUD_NULLDevice::stopAll() diff --git a/intern/audaspace/intern/AUD_NULLDevice.h b/intern/audaspace/intern/AUD_NULLDevice.h index ee97b151ebe..ae1435bbeea 100644 --- a/intern/audaspace/intern/AUD_NULLDevice.h +++ b/intern/audaspace/intern/AUD_NULLDevice.h @@ -72,8 +72,8 @@ public: virtual ~AUD_NULLDevice(); virtual AUD_DeviceSpecs getSpecs() const; - virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IReader> reader, bool keep = false); - virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IFactory> factory, bool keep = false); + virtual boost::shared_ptr<AUD_IHandle> play(boost::shared_ptr<AUD_IReader> reader, bool keep = false); + virtual boost::shared_ptr<AUD_IHandle> play(boost::shared_ptr<AUD_IFactory> factory, bool keep = false); virtual void stopAll(); virtual void lock(); virtual void unlock(); diff --git a/intern/audaspace/intern/AUD_Reference.h b/intern/audaspace/intern/AUD_Reference.h deleted file mode 100644 index 5a1aa947148..00000000000 --- a/intern/audaspace/intern/AUD_Reference.h +++ /dev/null @@ -1,275 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * Copyright 2009-2011 Jörg Hermann Müller - * - * This file is part of AudaSpace. - * - * Audaspace is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * AudaSpace is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Audaspace; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file audaspace/intern/AUD_Reference.h - * \ingroup audaspaceintern - */ - -#ifndef __AUD_REFERENCE_H__ -#define __AUD_REFERENCE_H__ - -#include <map> -#include <cstddef> -#include <pthread.h> - -// #define MEM_DEBUG - -#ifdef MEM_DEBUG -#include <iostream> -#include <typeinfo> -#endif - -/** - * This class handles the reference counting. - */ -class AUD_ReferenceHandler -{ -private: - /** - * Saves the reference counts. - */ - static std::map<void*, unsigned int> m_references; - static pthread_mutex_t m_mutex; - static bool m_mutex_initialised; - -public: - - static pthread_mutex_t* getMutex(); - - /** - * Reference increment. - * \param reference The reference. - */ - static inline void incref(void* reference) - { - if(!reference) - return; - - std::map<void*, unsigned int>::iterator result = m_references.find(reference); - if(result != m_references.end()) - { - m_references[reference]++; - } - else - { - m_references[reference] = 1; - } - } - - /** - * Reference decrement. - * \param reference The reference. - * \return Whether the reference has to be deleted. - */ - static inline bool decref(void* reference) - { - if(!reference) - return false; - - if(!--m_references[reference]) - { - m_references.erase(reference); - return true; - } - return false; - } -}; - -template <class T> -/** - * This class provides reference counting functionality. - */ -class AUD_Reference -{ -private: - /// The reference. - T* m_reference; - void* m_original; -public: - /** - * Creates a new reference counter. - * \param reference The reference. - */ - template <class U> - AUD_Reference(U* reference) - { - pthread_mutex_lock(AUD_ReferenceHandler::getMutex()); - m_original = reference; - m_reference = dynamic_cast<T*>(reference); - AUD_ReferenceHandler::incref(m_original); -#ifdef MEM_DEBUG - if(m_reference != NULL) - std::cerr << "+" << typeid(*m_reference).name() << std::endl; -#endif - pthread_mutex_unlock(AUD_ReferenceHandler::getMutex()); - } - - AUD_Reference() - { - m_original = NULL; - m_reference = NULL; - } - - /** - * Copies an AUD_Reference object. - * \param ref The AUD_Reference object to copy. - */ - AUD_Reference(const AUD_Reference& ref) - { - pthread_mutex_lock(AUD_ReferenceHandler::getMutex()); - m_original = ref.m_original; - m_reference = ref.m_reference; - AUD_ReferenceHandler::incref(m_original); -#ifdef MEM_DEBUG - if(m_reference != NULL) - std::cerr << "+" << typeid(*m_reference).name() << std::endl; -#endif - pthread_mutex_unlock(AUD_ReferenceHandler::getMutex()); - } - - template <class U> - explicit AUD_Reference(const AUD_Reference<U>& ref) - { - pthread_mutex_lock(AUD_ReferenceHandler::getMutex()); - m_original = ref.get(); - m_reference = dynamic_cast<T*>(ref.get()); - AUD_ReferenceHandler::incref(m_original); -#ifdef MEM_DEBUG - if(m_reference != NULL) - std::cerr << "+" << typeid(*m_reference).name() << std::endl; -#endif - pthread_mutex_unlock(AUD_ReferenceHandler::getMutex()); - } - - /** - * Destroys a AUD_Reference object, if there's no furthere reference on the - * reference, it is destroyed as well. - */ - ~AUD_Reference() - { - pthread_mutex_lock(AUD_ReferenceHandler::getMutex()); -#ifdef MEM_DEBUG - if(m_reference != NULL) - std::cerr << "-" << typeid(*m_reference).name() << std::endl; -#endif - if(AUD_ReferenceHandler::decref(m_original)) - { - pthread_mutex_unlock(AUD_ReferenceHandler::getMutex()); - delete m_reference; - } - else - { - pthread_mutex_unlock(AUD_ReferenceHandler::getMutex()); - } - } - - /** - * Assigns an AUD_Reference to this object. - * \param ref The AUD_Reference object to assign. - */ - AUD_Reference& operator=(const AUD_Reference& ref) - { - if(&ref == this) - return *this; - - pthread_mutex_lock(AUD_ReferenceHandler::getMutex()); - -#ifdef MEM_DEBUG - if(m_reference != NULL) - std::cerr << "-" << typeid(*m_reference).name() << std::endl; -#endif - if(AUD_ReferenceHandler::decref(m_original)) - { - pthread_mutex_unlock(AUD_ReferenceHandler::getMutex()); - delete m_reference; - pthread_mutex_lock(AUD_ReferenceHandler::getMutex()); - } - - m_original = ref.m_original; - m_reference = ref.m_reference; - AUD_ReferenceHandler::incref(m_original); -#ifdef MEM_DEBUG - if(m_reference != NULL) - std::cerr << "+" << typeid(*m_reference).name() << std::endl; -#endif - - pthread_mutex_unlock(AUD_ReferenceHandler::getMutex()); - - return *this; - } - - /** - * Returns whether the reference is NULL. - */ - inline bool isNull() const - { - return m_reference == NULL; - } - - /** - * Returns the reference. - */ - inline T* get() const - { - return m_reference; - } - - /** - * Returns the original pointer. - */ - inline void* getOriginal() const - { - return m_original; - } - - /** - * Returns the reference. - */ - inline T& operator*() const - { - return *m_reference; - } - - /** - * Returns the reference. - */ - inline T* operator->() const - { - return m_reference; - } -}; - -template<class T, class U> -inline bool operator==(const AUD_Reference<T>& a, const AUD_Reference<U>& b) -{ - return a.getOriginal() == b.getOriginal(); -} - -template<class T, class U> -inline bool operator!=(const AUD_Reference<T>& a, const AUD_Reference<U>& b) -{ - return a.getOriginal() != b.getOriginal(); -} - -#endif // __AUD_REFERENCE_H__ diff --git a/intern/audaspace/intern/AUD_ResampleReader.cpp b/intern/audaspace/intern/AUD_ResampleReader.cpp index 514d790be09..4b247ffd862 100644 --- a/intern/audaspace/intern/AUD_ResampleReader.cpp +++ b/intern/audaspace/intern/AUD_ResampleReader.cpp @@ -29,7 +29,7 @@ #include "AUD_ResampleReader.h" -AUD_ResampleReader::AUD_ResampleReader(AUD_Reference<AUD_IReader> reader, AUD_SampleRate rate) : +AUD_ResampleReader::AUD_ResampleReader(boost::shared_ptr<AUD_IReader> reader, AUD_SampleRate rate) : AUD_EffectReader(reader), m_rate(rate) { } diff --git a/intern/audaspace/intern/AUD_ResampleReader.h b/intern/audaspace/intern/AUD_ResampleReader.h index c423326489d..7e21989bfa8 100644 --- a/intern/audaspace/intern/AUD_ResampleReader.h +++ b/intern/audaspace/intern/AUD_ResampleReader.h @@ -47,7 +47,7 @@ protected: * \param reader The reader to mix. * \param rate The target sampling rate. */ - AUD_ResampleReader(AUD_Reference<AUD_IReader> reader, AUD_SampleRate rate); + AUD_ResampleReader(boost::shared_ptr<AUD_IReader> reader, AUD_SampleRate rate); public: /** diff --git a/intern/audaspace/intern/AUD_Sequencer.cpp b/intern/audaspace/intern/AUD_Sequencer.cpp new file mode 100644 index 00000000000..58e8f682714 --- /dev/null +++ b/intern/audaspace/intern/AUD_Sequencer.cpp @@ -0,0 +1,176 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * Copyright 2009-2011 Jörg Hermann Müller + * + * This file is part of AudaSpace. + * + * Audaspace is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * AudaSpace is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Audaspace; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file audaspace/intern/AUD_Sequencer.cpp + * \ingroup audaspaceintern + */ + + +#include "AUD_Sequencer.h" +#include "AUD_SequencerReader.h" +#include "AUD_3DMath.h" +#include "AUD_MutexLock.h" + +AUD_Sequencer::AUD_Sequencer(AUD_Specs specs, float fps, bool muted) : + m_specs(specs), + m_status(0), + m_entry_status(0), + m_id(0), + m_muted(muted), + m_fps(fps), + m_speed_of_sound(434), + m_doppler_factor(1), + m_distance_model(AUD_DISTANCE_MODEL_INVERSE_CLAMPED), + m_location(3), + m_orientation(4) +{ + AUD_Quaternion q; + m_orientation.write(q.get()); + float f = 1; + m_volume.write(&f); + + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + + pthread_mutex_init(&m_mutex, &attr); + + pthread_mutexattr_destroy(&attr); +} + +AUD_Sequencer::~AUD_Sequencer() +{ + pthread_mutex_destroy(&m_mutex); +} + +void AUD_Sequencer::lock() +{ + pthread_mutex_lock(&m_mutex); +} + +void AUD_Sequencer::unlock() +{ + pthread_mutex_unlock(&m_mutex); +} + +void AUD_Sequencer::setSpecs(AUD_Specs specs) +{ + AUD_MutexLock lock(*this); + + m_specs = specs; + m_status++; +} + +void AUD_Sequencer::setFPS(float fps) +{ + AUD_MutexLock lock(*this); + + m_fps = fps; +} + +void AUD_Sequencer::mute(bool muted) +{ + AUD_MutexLock lock(*this); + + m_muted = muted; +} + +bool AUD_Sequencer::getMute() const +{ + return m_muted; +} + +float AUD_Sequencer::getSpeedOfSound() const +{ + return m_speed_of_sound; +} + +void AUD_Sequencer::setSpeedOfSound(float speed) +{ + AUD_MutexLock lock(*this); + + m_speed_of_sound = speed; + m_status++; +} + +float AUD_Sequencer::getDopplerFactor() const +{ + return m_doppler_factor; +} + +void AUD_Sequencer::setDopplerFactor(float factor) +{ + AUD_MutexLock lock(*this); + + m_doppler_factor = factor; + m_status++; +} + +AUD_DistanceModel AUD_Sequencer::getDistanceModel() const +{ + return m_distance_model; +} + +void AUD_Sequencer::setDistanceModel(AUD_DistanceModel model) +{ + AUD_MutexLock lock(*this); + + m_distance_model = model; + m_status++; +} + +AUD_AnimateableProperty* AUD_Sequencer::getAnimProperty(AUD_AnimateablePropertyType type) +{ + switch(type) + { + case AUD_AP_VOLUME: + return &m_volume; + case AUD_AP_LOCATION: + return &m_location; + case AUD_AP_ORIENTATION: + return &m_orientation; + default: + return NULL; + } +} + +boost::shared_ptr<AUD_SequencerEntry> AUD_Sequencer::add(boost::shared_ptr<AUD_IFactory> sound, float begin, float end, float skip) +{ + AUD_MutexLock lock(*this); + + boost::shared_ptr<AUD_SequencerEntry> entry = boost::shared_ptr<AUD_SequencerEntry>(new AUD_SequencerEntry(sound, begin, end, skip, m_id++)); + + m_entries.push_front(entry); + m_entry_status++; + + return entry; +} + +void AUD_Sequencer::remove(boost::shared_ptr<AUD_SequencerEntry> entry) +{ + AUD_MutexLock lock(*this); + + m_entries.remove(entry); + m_entry_status++; +} diff --git a/intern/audaspace/intern/AUD_Sequencer.h b/intern/audaspace/intern/AUD_Sequencer.h new file mode 100644 index 00000000000..9fdf537ff97 --- /dev/null +++ b/intern/audaspace/intern/AUD_Sequencer.h @@ -0,0 +1,206 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * Copyright 2009-2011 Jörg Hermann Müller + * + * This file is part of AudaSpace. + * + * Audaspace is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * AudaSpace is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Audaspace; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file audaspace/intern/AUD_Sequencer.h + * \ingroup audaspaceintern + */ + + +#ifndef __AUD_SEQUENCER_H__ +#define __AUD_SEQUENCER_H__ + +#include "AUD_AnimateableProperty.h" +#include "AUD_IFactory.h" +#include "AUD_ILockable.h" + +#include <list> +#include <pthread.h> + +class AUD_SequencerEntry; + +/** + * This class represents sequenced entries to play a sound scene. + */ +class AUD_Sequencer : public AUD_ILockable +{ + friend class AUD_SequencerReader; +private: + /// The target specification. + AUD_Specs m_specs; + + /// The status of the sequence. Changes every time a non-animated parameter changes. + int m_status; + + /// The entry status. Changes every time an entry is removed or added. + int m_entry_status; + + /// The next unused ID for the entries. + int m_id; + + /// The sequenced entries. + std::list<boost::shared_ptr<AUD_SequencerEntry> > m_entries; + + /// Whether the whole scene is muted. + bool m_muted; + + /// The FPS of the scene. + float m_fps; + + /// Speed of Sound. + float m_speed_of_sound; + + /// Doppler factor. + float m_doppler_factor; + + /// Distance model. + AUD_DistanceModel m_distance_model; + + /// The animated volume. + AUD_AnimateableProperty m_volume; + + /// The animated listener location. + AUD_AnimateableProperty m_location; + + /// The animated listener orientation. + AUD_AnimateableProperty m_orientation; + + /// The mutex for locking. + pthread_mutex_t m_mutex; + + // hide copy constructor and operator= + AUD_Sequencer(const AUD_Sequencer&); + AUD_Sequencer& operator=(const AUD_Sequencer&); + +public: + /** + * Creates a new sound scene. + * \param specs The output audio data specification. + * \param fps The FPS of the scene. + * \param muted Whether the whole scene is muted. + */ + AUD_Sequencer(AUD_Specs specs, float fps, bool muted); + ~AUD_Sequencer(); + + /** + * Locks the sequence. + */ + virtual void lock(); + + /** + * Unlocks the previously locked sequence. + */ + virtual void unlock(); + + /** + * Sets the audio output specification. + * \param specs The new specification. + */ + void setSpecs(AUD_Specs specs); + + /** + * Sets the scene's FPS. + * \param fps The new FPS. + */ + void setFPS(float fps); + + /** + * Sets the muting state of the scene. + * \param muted Whether the scene is muted. + */ + void mute(bool muted); + + /** + * Retrieves the muting state of the scene. + * \return Whether the scene is muted. + */ + bool getMute() const; + + /** + * Retrieves the speed of sound. + * This value is needed for doppler effect calculation. + * \return The speed of sound. + */ + float getSpeedOfSound() const; + + /** + * Sets the speed of sound. + * This value is needed for doppler effect calculation. + * \param speed The new speed of sound. + */ + void setSpeedOfSound(float speed); + + /** + * Retrieves the doppler factor. + * This value is a scaling factor for the velocity vectors of sources and + * listener which is used while calculating the doppler effect. + * \return The doppler factor. + */ + float getDopplerFactor() const; + + /** + * Sets the doppler factor. + * This value is a scaling factor for the velocity vectors of sources and + * listener which is used while calculating the doppler effect. + * \param factor The new doppler factor. + */ + void setDopplerFactor(float factor); + + /** + * Retrieves the distance model. + * \return The distance model. + */ + AUD_DistanceModel getDistanceModel() const; + + /** + * Sets the distance model. + * \param model distance model. + */ + void setDistanceModel(AUD_DistanceModel model); + + /** + * Retrieves one of the animated properties of the sequence. + * \param type Which animated property to retrieve. + * \return A pointer to the animated property, valid as long as the + * sequence is. + */ + AUD_AnimateableProperty* getAnimProperty(AUD_AnimateablePropertyType type); + + /** + * Adds a new entry to the scene. + * \param sound The sound this entry should play. + * \param begin The start time. + * \param end The end time or a negative value if determined by the sound. + * \param skip How much seconds should be skipped at the beginning. + * \return The entry added. + */ + boost::shared_ptr<AUD_SequencerEntry> add(boost::shared_ptr<AUD_IFactory> sound, float begin, float end, float skip); + + /** + * Removes an entry from the scene. + * \param entry The entry to remove. + */ + void remove(boost::shared_ptr<AUD_SequencerEntry> entry); +}; + +#endif //__AUD_SEQUENCER_H__ diff --git a/intern/audaspace/intern/AUD_SequencerEntry.cpp b/intern/audaspace/intern/AUD_SequencerEntry.cpp index 6e6e2397626..005557bbed1 100644 --- a/intern/audaspace/intern/AUD_SequencerEntry.cpp +++ b/intern/audaspace/intern/AUD_SequencerEntry.cpp @@ -29,11 +29,12 @@ #include "AUD_SequencerEntry.h" #include "AUD_SequencerReader.h" +#include "AUD_MutexLock.h" #include <cmath> #include <limits> -AUD_SequencerEntry::AUD_SequencerEntry(AUD_Reference<AUD_IFactory> sound, float begin, float end, float skip, int id) : +AUD_SequencerEntry::AUD_SequencerEntry(boost::shared_ptr<AUD_IFactory> sound, float begin, float end, float skip, int id) : m_status(0), m_pos_status(1), m_sound_status(0), @@ -85,22 +86,20 @@ void AUD_SequencerEntry::unlock() pthread_mutex_unlock(&m_mutex); } -void AUD_SequencerEntry::setSound(AUD_Reference<AUD_IFactory> sound) +void AUD_SequencerEntry::setSound(boost::shared_ptr<AUD_IFactory> sound) { - lock(); + AUD_MutexLock lock(*this); if(m_sound.get() != sound.get()) { m_sound = sound; m_sound_status++; } - - unlock(); } void AUD_SequencerEntry::move(float begin, float end, float skip) { - lock(); + AUD_MutexLock lock(*this); if(m_begin != begin || m_skip != skip || m_end != end) { @@ -109,17 +108,13 @@ void AUD_SequencerEntry::move(float begin, float end, float skip) m_end = end; m_pos_status++; } - - unlock(); } void AUD_SequencerEntry::mute(bool mute) { - lock(); + AUD_MutexLock lock(*this); m_muted = mute; - - unlock(); } int AUD_SequencerEntry::getID() const @@ -150,7 +145,7 @@ void AUD_SequencerEntry::updateAll(float volume_max, float volume_min, float dis float distance_reference, float attenuation, float cone_angle_outer, float cone_angle_inner, float cone_volume_outer) { - lock(); + AUD_MutexLock lock(*this); if(volume_max != m_volume_max) { @@ -199,8 +194,6 @@ void AUD_SequencerEntry::updateAll(float volume_max, float volume_min, float dis m_cone_volume_outer = cone_volume_outer; m_status++; } - - unlock(); } bool AUD_SequencerEntry::isRelative() @@ -210,15 +203,13 @@ bool AUD_SequencerEntry::isRelative() void AUD_SequencerEntry::setRelative(bool relative) { - lock(); + AUD_MutexLock lock(*this); if(m_relative != relative) { m_relative = relative; m_status++; } - - unlock(); } float AUD_SequencerEntry::getVolumeMaximum() @@ -228,12 +219,10 @@ float AUD_SequencerEntry::getVolumeMaximum() void AUD_SequencerEntry::setVolumeMaximum(float volume) { - lock(); + AUD_MutexLock lock(*this); m_volume_max = volume; m_status++; - - unlock(); } float AUD_SequencerEntry::getVolumeMinimum() @@ -243,12 +232,10 @@ float AUD_SequencerEntry::getVolumeMinimum() void AUD_SequencerEntry::setVolumeMinimum(float volume) { - lock(); + AUD_MutexLock lock(*this); m_volume_min = volume; m_status++; - - unlock(); } float AUD_SequencerEntry::getDistanceMaximum() @@ -258,12 +245,10 @@ float AUD_SequencerEntry::getDistanceMaximum() void AUD_SequencerEntry::setDistanceMaximum(float distance) { - lock(); + AUD_MutexLock lock(*this); m_distance_max = distance; m_status++; - - unlock(); } float AUD_SequencerEntry::getDistanceReference() @@ -273,12 +258,10 @@ float AUD_SequencerEntry::getDistanceReference() void AUD_SequencerEntry::setDistanceReference(float distance) { - lock(); + AUD_MutexLock lock(*this); m_distance_reference = distance; m_status++; - - unlock(); } float AUD_SequencerEntry::getAttenuation() @@ -288,12 +271,10 @@ float AUD_SequencerEntry::getAttenuation() void AUD_SequencerEntry::setAttenuation(float factor) { - lock(); + AUD_MutexLock lock(*this); m_attenuation = factor; m_status++; - - unlock(); } float AUD_SequencerEntry::getConeAngleOuter() @@ -303,12 +284,10 @@ float AUD_SequencerEntry::getConeAngleOuter() void AUD_SequencerEntry::setConeAngleOuter(float angle) { - lock(); + AUD_MutexLock lock(*this); m_cone_angle_outer = angle; m_status++; - - unlock(); } float AUD_SequencerEntry::getConeAngleInner() @@ -318,12 +297,10 @@ float AUD_SequencerEntry::getConeAngleInner() void AUD_SequencerEntry::setConeAngleInner(float angle) { - lock(); + AUD_MutexLock lock(*this); m_cone_angle_inner = angle; m_status++; - - unlock(); } float AUD_SequencerEntry::getConeVolumeOuter() @@ -333,10 +310,8 @@ float AUD_SequencerEntry::getConeVolumeOuter() void AUD_SequencerEntry::setConeVolumeOuter(float volume) { - lock(); + AUD_MutexLock lock(*this); m_cone_volume_outer = volume; m_status++; - - unlock(); } diff --git a/intern/audaspace/intern/AUD_SequencerEntry.h b/intern/audaspace/intern/AUD_SequencerEntry.h index 7ff6fffea11..aa1edebfc2f 100644 --- a/intern/audaspace/intern/AUD_SequencerEntry.h +++ b/intern/audaspace/intern/AUD_SequencerEntry.h @@ -30,16 +30,17 @@ #ifndef __AUD_SEQUENCERENTRY_H__ #define __AUD_SEQUENCERENTRY_H__ -#include "AUD_Reference.h" #include "AUD_AnimateableProperty.h" #include "AUD_IFactory.h" +#include "AUD_ILockable.h" #include <pthread.h> +#include <boost/shared_ptr.hpp> /** * This class represents a sequenced entry in a sequencer factory. */ -class AUD_SequencerEntry +class AUD_SequencerEntry : public AUD_ILockable { friend class AUD_SequencerHandle; private: @@ -56,7 +57,7 @@ private: int m_id; /// The sound this entry plays. - AUD_Reference<AUD_IFactory> m_sound; + boost::shared_ptr<AUD_IFactory> m_sound; /// The begin time. float m_begin; @@ -124,24 +125,24 @@ public: * \param skip How much seconds should be skipped at the beginning. * \param id The ID of the entry. */ - AUD_SequencerEntry(AUD_Reference<AUD_IFactory> sound, float begin, float end, float skip, int id); + AUD_SequencerEntry(boost::shared_ptr<AUD_IFactory> sound, float begin, float end, float skip, int id); virtual ~AUD_SequencerEntry(); /** * Locks the entry. */ - void lock(); + virtual void lock(); /** * Unlocks the previously locked entry. */ - void unlock(); + virtual void unlock(); /** * Sets the sound of the entry. * \param sound The new sound. */ - void setSound(AUD_Reference<AUD_IFactory> sound); + void setSound(boost::shared_ptr<AUD_IFactory> sound); /** * Moves the entry. diff --git a/intern/audaspace/intern/AUD_SequencerFactory.cpp b/intern/audaspace/intern/AUD_SequencerFactory.cpp index fd495f467cf..f6076603c2b 100644 --- a/intern/audaspace/intern/AUD_SequencerFactory.cpp +++ b/intern/audaspace/intern/AUD_SequencerFactory.cpp @@ -30,40 +30,14 @@ #include "AUD_SequencerFactory.h" #include "AUD_SequencerReader.h" #include "AUD_3DMath.h" +#include "AUD_MutexLock.h" -AUD_SequencerFactory::AUD_SequencerFactory(AUD_Specs specs, float fps, bool muted) : - m_specs(specs), - m_status(0), - m_entry_status(0), - m_id(0), - m_muted(muted), - m_fps(fps), - m_speed_of_sound(434), - m_doppler_factor(1), - m_distance_model(AUD_DISTANCE_MODEL_INVERSE_CLAMPED), - m_location(3), - m_orientation(4) +AUD_SequencerFactory::AUD_SequencerFactory(AUD_Specs specs, float fps, bool muted) { - AUD_Quaternion q; - m_orientation.write(q.get()); - float f = 1; - m_volume.write(&f); - - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - - pthread_mutex_init(&m_mutex, &attr); - - pthread_mutexattr_destroy(&attr); + m_sequence = boost::shared_ptr<AUD_Sequencer>(new AUD_Sequencer(specs, fps, muted)); } -AUD_SequencerFactory::~AUD_SequencerFactory() -{ - pthread_mutex_destroy(&m_mutex); -} - -void AUD_SequencerFactory::lock() +/*void AUD_SequencerFactory::lock() { pthread_mutex_lock(&m_mutex); } @@ -71,131 +45,79 @@ void AUD_SequencerFactory::lock() void AUD_SequencerFactory::unlock() { pthread_mutex_unlock(&m_mutex); -} +}*/ void AUD_SequencerFactory::setSpecs(AUD_Specs specs) { - lock(); - - m_specs = specs; - m_status++; - - unlock(); + m_sequence->setSpecs(specs); } void AUD_SequencerFactory::setFPS(float fps) { - lock(); - - m_fps = fps; - - unlock(); + m_sequence->setFPS(fps); } void AUD_SequencerFactory::mute(bool muted) { - lock(); - - m_muted = muted; - - unlock(); + m_sequence->mute(muted); } bool AUD_SequencerFactory::getMute() const { - return m_muted; + return m_sequence->getMute(); } float AUD_SequencerFactory::getSpeedOfSound() const { - return m_speed_of_sound; + return m_sequence->getSpeedOfSound(); } void AUD_SequencerFactory::setSpeedOfSound(float speed) { - lock(); - - m_speed_of_sound = speed; - m_status++; - - unlock(); + m_sequence->setSpeedOfSound(speed); } float AUD_SequencerFactory::getDopplerFactor() const { - return m_doppler_factor; + return m_sequence->getDopplerFactor(); } void AUD_SequencerFactory::setDopplerFactor(float factor) { - lock(); - - m_doppler_factor = factor; - m_status++; - - unlock(); + m_sequence->setDopplerFactor(factor); } AUD_DistanceModel AUD_SequencerFactory::getDistanceModel() const { - return m_distance_model; + return m_sequence->getDistanceModel(); } void AUD_SequencerFactory::setDistanceModel(AUD_DistanceModel model) { - lock(); - - m_distance_model = model; - m_status++; - - unlock(); + m_sequence->setDistanceModel(model); } AUD_AnimateableProperty* AUD_SequencerFactory::getAnimProperty(AUD_AnimateablePropertyType type) { - switch(type) - { - case AUD_AP_VOLUME: - return &m_volume; - case AUD_AP_LOCATION: - return &m_location; - case AUD_AP_ORIENTATION: - return &m_orientation; - default: - return NULL; - } + return m_sequence->getAnimProperty(type); } -AUD_Reference<AUD_SequencerEntry> AUD_SequencerFactory::add(AUD_Reference<AUD_IFactory> sound, float begin, float end, float skip) +boost::shared_ptr<AUD_SequencerEntry> AUD_SequencerFactory::add(boost::shared_ptr<AUD_IFactory> sound, float begin, float end, float skip) { - lock(); - - AUD_Reference<AUD_SequencerEntry> entry = new AUD_SequencerEntry(sound, begin, end, skip, m_id++); - - m_entries.push_front(entry); - m_entry_status++; - - unlock(); - - return entry; + return m_sequence->add(sound, begin, end, skip); } -void AUD_SequencerFactory::remove(AUD_Reference<AUD_SequencerEntry> entry) +void AUD_SequencerFactory::remove(boost::shared_ptr<AUD_SequencerEntry> entry) { - lock(); - - m_entries.remove(entry); - m_entry_status++; - - unlock(); + m_sequence->remove(entry); } -AUD_Reference<AUD_IReader> AUD_SequencerFactory::createQualityReader() +boost::shared_ptr<AUD_IReader> AUD_SequencerFactory::createQualityReader() { - return new AUD_SequencerReader(this, true); + return boost::shared_ptr<AUD_IReader>(new AUD_SequencerReader(m_sequence, true)); } -AUD_Reference<AUD_IReader> AUD_SequencerFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_SequencerFactory::createReader() { - return new AUD_SequencerReader(this); + return boost::shared_ptr<AUD_IReader>(new AUD_SequencerReader(m_sequence)); } diff --git a/intern/audaspace/intern/AUD_SequencerFactory.h b/intern/audaspace/intern/AUD_SequencerFactory.h index 38241112020..3ef847d4b34 100644 --- a/intern/audaspace/intern/AUD_SequencerFactory.h +++ b/intern/audaspace/intern/AUD_SequencerFactory.h @@ -32,6 +32,8 @@ #include "AUD_IFactory.h" #include "AUD_AnimateableProperty.h" +//#include "AUD_ILockable.h" +#include "AUD_Sequencer.h" #include <list> #include <pthread.h> @@ -41,51 +43,12 @@ class AUD_SequencerEntry; /** * This factory represents sequenced entries to play a sound scene. */ -class AUD_SequencerFactory : public AUD_IFactory +class AUD_SequencerFactory : public AUD_IFactory//, public AUD_ILockable { friend class AUD_SequencerReader; private: - /// The target specification. - AUD_Specs m_specs; - - /// The status of the factory. Changes every time a non-animated parameter changes. - int m_status; - - /// The entry status. Changes every time an entry is removed or added. - int m_entry_status; - - /// The next unused ID for the entries. - int m_id; - - /// The sequenced entries. - std::list<AUD_Reference<AUD_SequencerEntry> > m_entries; - - /// Whether the whole scene is muted. - bool m_muted; - - /// The FPS of the scene. - float m_fps; - - /// Speed of Sound. - float m_speed_of_sound; - - /// Doppler factor. - float m_doppler_factor; - - /// Distance model. - AUD_DistanceModel m_distance_model; - - /// The animated volume. - AUD_AnimateableProperty m_volume; - - /// The animated listener location. - AUD_AnimateableProperty m_location; - - /// The animated listener orientation. - AUD_AnimateableProperty m_orientation; - - /// The mutex for locking. - pthread_mutex_t m_mutex; + /// The sequence. + boost::shared_ptr<AUD_Sequencer> m_sequence; // hide copy constructor and operator= AUD_SequencerFactory(const AUD_SequencerFactory&); @@ -99,17 +62,18 @@ public: * \param muted Whether the whole scene is muted. */ AUD_SequencerFactory(AUD_Specs specs, float fps, bool muted); - ~AUD_SequencerFactory(); +#if 0 /** * Locks the factory. */ - void lock(); + virtual void lock(); /** * Unlocks the previously locked factory. */ - void unlock(); + virtual void unlock(); +#endif /** * Sets the audio output specification. @@ -193,21 +157,21 @@ public: * \param skip How much seconds should be skipped at the beginning. * \return The entry added. */ - AUD_Reference<AUD_SequencerEntry> add(AUD_Reference<AUD_IFactory> sound, float begin, float end, float skip); + boost::shared_ptr<AUD_SequencerEntry> add(boost::shared_ptr<AUD_IFactory> sound, float begin, float end, float skip); /** * Removes an entry from the scene. * \param entry The entry to remove. */ - void remove(AUD_Reference<AUD_SequencerEntry> entry); + void remove(boost::shared_ptr<AUD_SequencerEntry> entry); /** * Creates a new reader with high quality resampling. * \return The new reader. */ - AUD_Reference<AUD_IReader> createQualityReader(); + boost::shared_ptr<AUD_IReader> createQualityReader(); - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif //__AUD_SEQUENCERFACTORY_H__ diff --git a/intern/audaspace/intern/AUD_SequencerHandle.cpp b/intern/audaspace/intern/AUD_SequencerHandle.cpp index f4bfae6cee7..c9473cf274e 100644 --- a/intern/audaspace/intern/AUD_SequencerHandle.cpp +++ b/intern/audaspace/intern/AUD_SequencerHandle.cpp @@ -29,18 +29,19 @@ #include "AUD_SequencerHandle.h" #include "AUD_ReadDevice.h" +#include "AUD_MutexLock.h" -AUD_SequencerHandle::AUD_SequencerHandle(AUD_Reference<AUD_SequencerEntry> entry, AUD_ReadDevice& device) : +AUD_SequencerHandle::AUD_SequencerHandle(boost::shared_ptr<AUD_SequencerEntry> entry, AUD_ReadDevice& device) : m_entry(entry), m_status(0), m_pos_status(0), m_sound_status(0), m_device(device) { - if(!entry->m_sound.isNull()) + if(entry->m_sound.get()) { m_handle = device.play(entry->m_sound, true); - m_3dhandle = AUD_Reference<AUD_I3DHandle>(m_handle); + m_3dhandle = boost::dynamic_pointer_cast<AUD_I3DHandle>(m_handle); } } @@ -49,7 +50,7 @@ AUD_SequencerHandle::~AUD_SequencerHandle() stop(); } -int AUD_SequencerHandle::compare(AUD_Reference<AUD_SequencerEntry> entry) const +int AUD_SequencerHandle::compare(boost::shared_ptr<AUD_SequencerEntry> entry) const { if(m_entry->getID() < entry->getID()) return -1; @@ -60,15 +61,15 @@ int AUD_SequencerHandle::compare(AUD_Reference<AUD_SequencerEntry> entry) const void AUD_SequencerHandle::stop() { - if(!m_handle.isNull()) + if(m_handle.get()) m_handle->stop(); } void AUD_SequencerHandle::update(float position, float frame, float fps) { - if(!m_handle.isNull()) + if(m_handle.get()) { - m_entry->lock(); + AUD_MutexLock lock(*m_entry); if(position >= m_entry->m_end && m_entry->m_end >= 0) m_handle->pause(); else if(position >= m_entry->m_begin) @@ -76,13 +77,13 @@ void AUD_SequencerHandle::update(float position, float frame, float fps) if(m_sound_status != m_entry->m_sound_status) { - if(!m_handle.isNull()) + if(m_handle.get()) m_handle->stop(); - if(!m_entry->m_sound.isNull()) + if(m_entry->m_sound.get()) { m_handle = m_device.play(m_entry->m_sound, true); - m_3dhandle = AUD_Reference<AUD_I3DHandle>(m_handle); + m_3dhandle = boost::dynamic_pointer_cast<AUD_I3DHandle>(m_handle); } m_sound_status = m_entry->m_sound_status; @@ -134,19 +135,17 @@ void AUD_SequencerHandle::update(float position, float frame, float fps) if(m_entry->m_muted) m_handle->setVolume(0); - m_entry->unlock(); } } void AUD_SequencerHandle::seek(float position) { - if(!m_handle.isNull()) + if(m_handle.get()) { - m_entry->lock(); + AUD_MutexLock lock(*m_entry); if(position >= m_entry->m_end && m_entry->m_end >= 0) { m_handle->pause(); - m_entry->unlock(); return; } @@ -160,6 +159,5 @@ void AUD_SequencerHandle::seek(float position) m_handle->pause(); else m_handle->resume(); - m_entry->unlock(); } } diff --git a/intern/audaspace/intern/AUD_SequencerHandle.h b/intern/audaspace/intern/AUD_SequencerHandle.h index 72d3240a103..881bbdd43dc 100644 --- a/intern/audaspace/intern/AUD_SequencerHandle.h +++ b/intern/audaspace/intern/AUD_SequencerHandle.h @@ -43,13 +43,13 @@ class AUD_SequencerHandle { private: /// The entry this handle belongs to. - AUD_Reference<AUD_SequencerEntry> m_entry; + boost::shared_ptr<AUD_SequencerEntry> m_entry; /// The handle in the read device. - AUD_Reference<AUD_IHandle> m_handle; + boost::shared_ptr<AUD_IHandle> m_handle; /// The 3D handle in the read device. - AUD_Reference<AUD_I3DHandle> m_3dhandle; + boost::shared_ptr<AUD_I3DHandle> m_3dhandle; /// The last read status from the entry. int m_status; @@ -69,7 +69,7 @@ public: * \param entry The entry this handle plays. * \param device The read device to play on. */ - AUD_SequencerHandle(AUD_Reference<AUD_SequencerEntry> entry, AUD_ReadDevice& device); + AUD_SequencerHandle(boost::shared_ptr<AUD_SequencerEntry> entry, AUD_ReadDevice& device); /** * Destroys the handle. @@ -81,7 +81,7 @@ public: * \param entry The entry to compare to. * \return Whether the entries ID is smaller, equal or bigger. */ - int compare(AUD_Reference<AUD_SequencerEntry> entry) const; + int compare(boost::shared_ptr<AUD_SequencerEntry> entry) const; /** * Stops playing back the handle. diff --git a/intern/audaspace/intern/AUD_SequencerReader.cpp b/intern/audaspace/intern/AUD_SequencerReader.cpp index 2e41a99d3db..d5e14590df5 100644 --- a/intern/audaspace/intern/AUD_SequencerReader.cpp +++ b/intern/audaspace/intern/AUD_SequencerReader.cpp @@ -28,12 +28,13 @@ #include "AUD_SequencerReader.h" +#include "AUD_MutexLock.h" -typedef std::list<AUD_Reference<AUD_SequencerHandle> >::iterator AUD_HandleIterator; -typedef std::list<AUD_Reference<AUD_SequencerEntry> >::iterator AUD_EntryIterator; +typedef std::list<boost::shared_ptr<AUD_SequencerHandle> >::iterator AUD_HandleIterator; +typedef std::list<boost::shared_ptr<AUD_SequencerEntry> >::iterator AUD_EntryIterator; -AUD_SequencerReader::AUD_SequencerReader(AUD_Reference<AUD_SequencerFactory> factory, bool quality) : - m_position(0), m_device(factory->m_specs), m_factory(factory), m_status(0), m_entry_status(0) +AUD_SequencerReader::AUD_SequencerReader(boost::shared_ptr<AUD_Sequencer> sequence, bool quality) : + m_position(0), m_device(sequence->m_specs), m_sequence(sequence), m_status(0), m_entry_status(0) { m_device.setQuality(quality); } @@ -56,7 +57,7 @@ void AUD_SequencerReader::seek(int position) for(AUD_HandleIterator it = m_handles.begin(); it != m_handles.end(); it++) { - (*it)->seek(position / m_factory->m_specs.rate); + (*it)->seek(position / m_sequence->m_specs.rate); } } @@ -72,37 +73,37 @@ int AUD_SequencerReader::getPosition() const AUD_Specs AUD_SequencerReader::getSpecs() const { - return m_factory->m_specs; + return m_sequence->m_specs; } void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer) { - m_factory->lock(); + AUD_MutexLock lock(*m_sequence); - if(m_factory->m_status != m_status) + if(m_sequence->m_status != m_status) { - m_device.changeSpecs(m_factory->m_specs); - m_device.setSpeedOfSound(m_factory->m_speed_of_sound); - m_device.setDistanceModel(m_factory->m_distance_model); - m_device.setDopplerFactor(m_factory->m_doppler_factor); + m_device.changeSpecs(m_sequence->m_specs); + m_device.setSpeedOfSound(m_sequence->m_speed_of_sound); + m_device.setDistanceModel(m_sequence->m_distance_model); + m_device.setDopplerFactor(m_sequence->m_doppler_factor); - m_status = m_factory->m_status; + m_status = m_sequence->m_status; } - if(m_factory->m_entry_status != m_entry_status) + if(m_sequence->m_entry_status != m_entry_status) { - std::list<AUD_Reference<AUD_SequencerHandle> > handles; + std::list<boost::shared_ptr<AUD_SequencerHandle> > handles; AUD_HandleIterator hit = m_handles.begin(); - AUD_EntryIterator eit = m_factory->m_entries.begin(); + AUD_EntryIterator eit = m_sequence->m_entries.begin(); int result; - AUD_Reference<AUD_SequencerHandle> handle; + boost::shared_ptr<AUD_SequencerHandle> handle; - while(hit != m_handles.end() && eit != m_factory->m_entries.end()) + while(hit != m_handles.end() && eit != m_sequence->m_entries.end()) { handle = *hit; - AUD_Reference<AUD_SequencerEntry> entry = *eit; + boost::shared_ptr<AUD_SequencerEntry> entry = *eit; result = handle->compare(entry); @@ -110,7 +111,7 @@ void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer) { try { - handle = new AUD_SequencerHandle(entry, m_device); + handle = boost::shared_ptr<AUD_SequencerHandle>(new AUD_SequencerHandle(entry, m_device)); handles.push_front(handle); } catch(AUD_Exception&) @@ -137,11 +138,11 @@ void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer) hit++; } - while(eit != m_factory->m_entries.end()) + while(eit != m_sequence->m_entries.end()) { try { - handle = new AUD_SequencerHandle(*eit, m_device); + handle = boost::shared_ptr<AUD_SequencerHandle>(new AUD_SequencerHandle(*eit, m_device)); handles.push_front(handle); } catch(AUD_Exception&) @@ -152,10 +153,10 @@ void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer) m_handles = handles; - m_entry_status = m_factory->m_entry_status; + m_entry_status = m_sequence->m_entry_status; } - AUD_Specs specs = m_factory->m_specs; + AUD_Specs specs = m_sequence->m_specs; int pos = 0; float time = float(m_position) / float(specs.rate); float volume, frame; @@ -166,30 +167,30 @@ void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer) while(pos < length) { - frame = time * m_factory->m_fps; + frame = time * m_sequence->m_fps; cfra = int(floor(frame)); - len = int(ceil((cfra + 1) / m_factory->m_fps * specs.rate)) - m_position; + len = int(ceil((cfra + 1) / m_sequence->m_fps * specs.rate)) - m_position; len = AUD_MIN(length - pos, len); len = AUD_MAX(len, 1); for(AUD_HandleIterator it = m_handles.begin(); it != m_handles.end(); it++) { - (*it)->update(time, frame, m_factory->m_fps); + (*it)->update(time, frame, m_sequence->m_fps); } - m_factory->m_volume.read(frame, &volume); - if(m_factory->m_muted) + m_sequence->m_volume.read(frame, &volume); + if(m_sequence->m_muted) volume = 0.0f; m_device.setVolume(volume); - m_factory->m_orientation.read(frame, q.get()); + m_sequence->m_orientation.read(frame, q.get()); m_device.setListenerOrientation(q); - m_factory->m_location.read(frame, v.get()); + m_sequence->m_location.read(frame, v.get()); m_device.setListenerLocation(v); - m_factory->m_location.read(frame + 1, v2.get()); + m_sequence->m_location.read(frame + 1, v2.get()); v2 -= v; - m_device.setListenerVelocity(v2 * m_factory->m_fps); + m_device.setListenerVelocity(v2 * m_sequence->m_fps); m_device.read(reinterpret_cast<data_t*>(buffer + specs.channels * pos), len); @@ -197,8 +198,6 @@ void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer) time += float(len) / float(specs.rate); } - m_factory->unlock(); - m_position += length; eos = false; diff --git a/intern/audaspace/intern/AUD_SequencerReader.h b/intern/audaspace/intern/AUD_SequencerReader.h index b3c3a3ea7a6..6b3dbc9313e 100644 --- a/intern/audaspace/intern/AUD_SequencerReader.h +++ b/intern/audaspace/intern/AUD_SequencerReader.h @@ -32,7 +32,7 @@ #include "AUD_IReader.h" #include "AUD_ReadDevice.h" -#include "AUD_SequencerFactory.h" +#include "AUD_Sequencer.h" #include "AUD_SequencerHandle.h" /** @@ -52,22 +52,22 @@ private: AUD_ReadDevice m_device; /** - * Saves the SequencerFactory the reader belongs to. + * Saves the sequence the reader belongs to. */ - AUD_Reference<AUD_SequencerFactory> m_factory; + boost::shared_ptr<AUD_Sequencer> m_sequence; /** * The list of playback handles for the entries. */ - std::list<AUD_Reference<AUD_SequencerHandle> > m_handles; + std::list<boost::shared_ptr<AUD_SequencerHandle> > m_handles; /** - * Last status read from the factory. + * Last status read from the sequence. */ int m_status; /** - * Last entry status read from the factory. + * Last entry status read from the sequence. */ int m_entry_status; @@ -81,7 +81,7 @@ public: * \param reader The reader to mix. * \param specs The target specification. */ - AUD_SequencerReader(AUD_Reference<AUD_SequencerFactory> factory, bool quality = false); + AUD_SequencerReader(boost::shared_ptr<AUD_Sequencer> sequence, bool quality = false); /** * Destroys the reader. diff --git a/intern/audaspace/intern/AUD_SilenceFactory.cpp b/intern/audaspace/intern/AUD_SilenceFactory.cpp index 0ba553f1c02..85034b316ca 100644 --- a/intern/audaspace/intern/AUD_SilenceFactory.cpp +++ b/intern/audaspace/intern/AUD_SilenceFactory.cpp @@ -35,7 +35,7 @@ AUD_SilenceFactory::AUD_SilenceFactory() { } -AUD_Reference<AUD_IReader> AUD_SilenceFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_SilenceFactory::createReader() { - return new AUD_SilenceReader(); + return boost::shared_ptr<AUD_IReader>(new AUD_SilenceReader()); } diff --git a/intern/audaspace/intern/AUD_SilenceFactory.h b/intern/audaspace/intern/AUD_SilenceFactory.h index 3bc7fc067ed..de62a2f94fc 100644 --- a/intern/audaspace/intern/AUD_SilenceFactory.h +++ b/intern/audaspace/intern/AUD_SilenceFactory.h @@ -48,7 +48,7 @@ public: */ AUD_SilenceFactory(); - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif //__AUD_SILENCEFACTORY_H__ diff --git a/intern/audaspace/intern/AUD_SinusFactory.cpp b/intern/audaspace/intern/AUD_SinusFactory.cpp index 3ef6a11de5b..2b9742cc90c 100644 --- a/intern/audaspace/intern/AUD_SinusFactory.cpp +++ b/intern/audaspace/intern/AUD_SinusFactory.cpp @@ -42,7 +42,7 @@ float AUD_SinusFactory::getFrequency() const return m_frequency; } -AUD_Reference<AUD_IReader> AUD_SinusFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_SinusFactory::createReader() { - return new AUD_SinusReader(m_frequency, m_sampleRate); + return boost::shared_ptr<AUD_IReader>(new AUD_SinusReader(m_frequency, m_sampleRate)); } diff --git a/intern/audaspace/intern/AUD_SinusFactory.h b/intern/audaspace/intern/AUD_SinusFactory.h index d83323c6635..d1909dedb66 100644 --- a/intern/audaspace/intern/AUD_SinusFactory.h +++ b/intern/audaspace/intern/AUD_SinusFactory.h @@ -66,7 +66,7 @@ public: */ float getFrequency() const; - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif //__AUD_SINUSFACTORY_H__ diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.cpp b/intern/audaspace/intern/AUD_SoftwareDevice.cpp index 1d993abab73..a7e5b25664b 100644 --- a/intern/audaspace/intern/AUD_SoftwareDevice.cpp +++ b/intern/audaspace/intern/AUD_SoftwareDevice.cpp @@ -33,6 +33,7 @@ #include "AUD_IFactory.h" #include "AUD_JOSResampleReader.h" #include "AUD_LinearResampleReader.h" +#include "AUD_MutexLock.h" #include <cstring> #include <cmath> @@ -56,7 +57,7 @@ typedef enum /********************** AUD_SoftwareHandle Handle Code ************************/ /******************************************************************************/ -AUD_SoftwareDevice::AUD_SoftwareHandle::AUD_SoftwareHandle(AUD_SoftwareDevice* device, AUD_Reference<AUD_IReader> reader, AUD_Reference<AUD_PitchReader> pitch, AUD_Reference<AUD_ResampleReader> resampler, AUD_Reference<AUD_ChannelMapperReader> mapper, bool keep) : +AUD_SoftwareDevice::AUD_SoftwareHandle::AUD_SoftwareHandle(AUD_SoftwareDevice* device, boost::shared_ptr<AUD_IReader> reader, boost::shared_ptr<AUD_PitchReader> pitch, boost::shared_ptr<AUD_ResampleReader> resampler, boost::shared_ptr<AUD_ChannelMapperReader> mapper, bool keep) : m_reader(reader), m_pitch(pitch), m_resampler(resampler), m_mapper(mapper), m_keep(keep), m_user_pitch(1.0f), m_user_volume(1.0f), m_user_pan(0.0f), m_volume(1.0f), m_loopcount(0), m_relative(true), m_volume_max(1.0f), m_volume_min(0), m_distance_max(std::numeric_limits<float>::max()), m_distance_reference(1.0f), m_attenuation(1.0f), m_cone_angle_outer(M_PI), m_cone_angle_inner(M_PI), m_cone_volume_outer(0), @@ -226,22 +227,28 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::pause() { if(m_status) { - m_device->lock(); + AUD_MutexLock lock(*m_device); if(m_status == AUD_STATUS_PLAYING) { - m_device->m_playingSounds.remove(this); - m_device->m_pausedSounds.push_back(this); + for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++) + { + if(it->get() == this) + { + boost::shared_ptr<AUD_SoftwareHandle> This = *it; - if(m_device->m_playingSounds.empty()) - m_device->playing(m_device->m_playback = false); - m_status = AUD_STATUS_PAUSED; - m_device->unlock(); + m_device->m_playingSounds.erase(it); + m_device->m_pausedSounds.push_back(This); - return true; - } + if(m_device->m_playingSounds.empty()) + m_device->playing(m_device->m_playback = false); - m_device->unlock(); + m_status = AUD_STATUS_PAUSED; + + return true; + } + } + } } return false; @@ -251,21 +258,29 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::resume() { if(m_status) { - m_device->lock(); + AUD_MutexLock lock(*m_device); if(m_status == AUD_STATUS_PAUSED) { - m_device->m_pausedSounds.remove(this); - m_device->m_playingSounds.push_back(this); + for(AUD_HandleIterator it = m_device->m_pausedSounds.begin(); it != m_device->m_pausedSounds.end(); it++) + { + if(it->get() == this) + { + boost::shared_ptr<AUD_SoftwareHandle> This = *it; - if(!m_device->m_playback) - m_device->playing(m_device->m_playback = true); - m_status = AUD_STATUS_PLAYING; - m_device->unlock(); - return true; + m_device->m_pausedSounds.erase(it); + + m_device->m_playingSounds.push_back(This); + + if(!m_device->m_playback) + m_device->playing(m_device->m_playback = true); + m_status = AUD_STATUS_PLAYING; + + return true; + } + } } - m_device->unlock(); } return false; @@ -276,25 +291,38 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::stop() if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; - // AUD_XXX Create a reference of our own object so that it doesn't get - // deleted before the end of this function - AUD_Reference<AUD_SoftwareHandle> This = this; + m_status = AUD_STATUS_INVALID; - if(m_status == AUD_STATUS_PLAYING) + for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++) { - m_device->m_playingSounds.remove(This); + if(it->get() == this) + { + boost::shared_ptr<AUD_SoftwareHandle> This = *it; - if(m_device->m_playingSounds.empty()) - m_device->playing(m_device->m_playback = false); + m_device->m_playingSounds.erase(it); + + if(m_device->m_playingSounds.empty()) + m_device->playing(m_device->m_playback = false); + + return true; + } } - else - m_device->m_pausedSounds.remove(This); - m_device->unlock(); - m_status = AUD_STATUS_INVALID; - return true; + for(AUD_HandleIterator it = m_device->m_pausedSounds.begin(); it != m_device->m_pausedSounds.end(); it++) + { + if(it->get() == this) + { + m_device->m_pausedSounds.erase(it); + return true; + } + } + + return false; } bool AUD_SoftwareDevice::AUD_SoftwareHandle::getKeep() @@ -310,11 +338,12 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::setKeep(bool keep) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - m_keep = keep; + if(!m_status) + return false; - m_device->unlock(); + m_keep = keep; return true; } @@ -324,11 +353,12 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::seek(float position) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - m_reader->seek((int)(position * m_reader->getSpecs().rate)); + if(!m_status) + return false; - m_device->unlock(); + m_reader->seek((int)(position * m_reader->getSpecs().rate)); return true; } @@ -336,13 +366,14 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::seek(float position) float AUD_SoftwareDevice::AUD_SoftwareHandle::getPosition() { if(!m_status) - return 0.0f; + return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - float position = m_reader->getPosition() / (float)m_device->m_specs.rate; + if(!m_status) + return 0.0f; - m_device->unlock(); + float position = m_reader->getPosition() / (float)m_device->m_specs.rate; return position; } @@ -407,13 +438,14 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::setStopCallback(stopCallback callba if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; m_stop = callback; m_stop_data = data; - m_device->unlock(); - return true; } @@ -657,7 +689,7 @@ void AUD_SoftwareDevice::create() { m_playback = false; m_volume = 1.0f; - m_mixer = new AUD_Mixer(m_specs); + m_mixer = boost::shared_ptr<AUD_Mixer>(new AUD_Mixer(m_specs)); m_speed_of_sound = 343.0f; m_doppler_factor = 1.0f; m_distance_model = AUD_DISTANCE_MODEL_INVERSE_CLAMPED; @@ -691,15 +723,15 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length) { m_buffer.assureSize(length * AUD_SAMPLE_SIZE(m_specs)); - lock(); + AUD_MutexLock lock(*this); { - AUD_Reference<AUD_SoftwareDevice::AUD_SoftwareHandle> sound; + boost::shared_ptr<AUD_SoftwareDevice::AUD_SoftwareHandle> sound; int len; int pos; bool eos; - std::list<AUD_Reference<AUD_SoftwareDevice::AUD_SoftwareHandle> > stopSounds; - std::list<AUD_Reference<AUD_SoftwareDevice::AUD_SoftwareHandle> > pauseSounds; + std::list<boost::shared_ptr<AUD_SoftwareDevice::AUD_SoftwareHandle> > stopSounds; + std::list<boost::shared_ptr<AUD_SoftwareDevice::AUD_SoftwareHandle> > pauseSounds; sample_t* buf = m_buffer.getBuffer(); m_mixer->clear(length); @@ -775,8 +807,6 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length) sound->pause(); } } - - unlock(); } void AUD_SoftwareDevice::setPanning(AUD_IHandle* handle, float pan) @@ -806,59 +836,57 @@ AUD_DeviceSpecs AUD_SoftwareDevice::getSpecs() const return m_specs; } -AUD_Reference<AUD_IHandle> AUD_SoftwareDevice::play(AUD_Reference<AUD_IReader> reader, bool keep) +boost::shared_ptr<AUD_IHandle> AUD_SoftwareDevice::play(boost::shared_ptr<AUD_IReader> reader, bool keep) { // prepare the reader // pitch - AUD_Reference<AUD_PitchReader> pitch = new AUD_PitchReader(reader, 1); - reader = AUD_Reference<AUD_IReader>(pitch); + boost::shared_ptr<AUD_PitchReader> pitch = boost::shared_ptr<AUD_PitchReader>(new AUD_PitchReader(reader, 1)); + reader = boost::shared_ptr<AUD_IReader>(pitch); - AUD_Reference<AUD_ResampleReader> resampler; + boost::shared_ptr<AUD_ResampleReader> resampler; // resample if(m_quality) - resampler = new AUD_JOSResampleReader(reader, m_specs.specs); + resampler = boost::shared_ptr<AUD_ResampleReader>(new AUD_JOSResampleReader(reader, m_specs.specs)); else - resampler = new AUD_LinearResampleReader(reader, m_specs.specs); - reader = AUD_Reference<AUD_IReader>(resampler); + resampler = boost::shared_ptr<AUD_ResampleReader>(new AUD_LinearResampleReader(reader, m_specs.specs)); + reader = boost::shared_ptr<AUD_IReader>(resampler); // rechannel - AUD_Reference<AUD_ChannelMapperReader> mapper = new AUD_ChannelMapperReader(reader, m_specs.channels); - reader = AUD_Reference<AUD_IReader>(mapper); + boost::shared_ptr<AUD_ChannelMapperReader> mapper = boost::shared_ptr<AUD_ChannelMapperReader>(new AUD_ChannelMapperReader(reader, m_specs.channels)); + reader = boost::shared_ptr<AUD_IReader>(mapper); - if(reader.isNull()) - return AUD_Reference<AUD_IHandle>(); + if(!reader.get()) + return boost::shared_ptr<AUD_IHandle>(); // play sound - AUD_Reference<AUD_SoftwareDevice::AUD_SoftwareHandle> sound = new AUD_SoftwareDevice::AUD_SoftwareHandle(this, reader, pitch, resampler, mapper, keep); + boost::shared_ptr<AUD_SoftwareDevice::AUD_SoftwareHandle> sound = boost::shared_ptr<AUD_SoftwareDevice::AUD_SoftwareHandle>(new AUD_SoftwareDevice::AUD_SoftwareHandle(this, reader, pitch, resampler, mapper, keep)); + + AUD_MutexLock lock(*this); - lock(); m_playingSounds.push_back(sound); if(!m_playback) playing(m_playback = true); - unlock(); - return AUD_Reference<AUD_IHandle>(sound); + return boost::shared_ptr<AUD_IHandle>(sound); } -AUD_Reference<AUD_IHandle> AUD_SoftwareDevice::play(AUD_Reference<AUD_IFactory> factory, bool keep) +boost::shared_ptr<AUD_IHandle> AUD_SoftwareDevice::play(boost::shared_ptr<AUD_IFactory> factory, bool keep) { return play(factory->createReader(), keep); } void AUD_SoftwareDevice::stopAll() { - lock(); + AUD_MutexLock lock(*this); while(!m_playingSounds.empty()) m_playingSounds.front()->stop(); while(!m_pausedSounds.empty()) m_pausedSounds.front()->stop(); - - unlock(); } void AUD_SoftwareDevice::lock() diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.h b/intern/audaspace/intern/AUD_SoftwareDevice.h index c429508b622..8675a5ce2b8 100644 --- a/intern/audaspace/intern/AUD_SoftwareDevice.h +++ b/intern/audaspace/intern/AUD_SoftwareDevice.h @@ -59,16 +59,16 @@ protected: { public: /// The reader source. - AUD_Reference<AUD_IReader> m_reader; + boost::shared_ptr<AUD_IReader> m_reader; /// The pitch reader in between. - AUD_Reference<AUD_PitchReader> m_pitch; + boost::shared_ptr<AUD_PitchReader> m_pitch; /// The resample reader in between. - AUD_Reference<AUD_ResampleReader> m_resampler; + boost::shared_ptr<AUD_ResampleReader> m_resampler; /// The channel mapper reader in between. - AUD_Reference<AUD_ChannelMapperReader> m_mapper; + boost::shared_ptr<AUD_ChannelMapperReader> m_mapper; /// Whether to keep the source if end of it is reached. bool m_keep; @@ -150,7 +150,7 @@ protected: * \param mapper The channel mapping reader. * \param keep Whether to keep the handle when the sound ends. */ - AUD_SoftwareHandle(AUD_SoftwareDevice* device, AUD_Reference<AUD_IReader> reader, AUD_Reference<AUD_PitchReader> pitch, AUD_Reference<AUD_ResampleReader> resampler, AUD_Reference<AUD_ChannelMapperReader> mapper, bool keep); + AUD_SoftwareHandle(AUD_SoftwareDevice* device, boost::shared_ptr<AUD_IReader> reader, boost::shared_ptr<AUD_PitchReader> pitch, boost::shared_ptr<AUD_ResampleReader> resampler, boost::shared_ptr<AUD_ChannelMapperReader> mapper, bool keep); /** * Updates the handle's playback parameters. @@ -206,7 +206,7 @@ protected: virtual bool setConeVolumeOuter(float volume); }; - typedef std::list<AUD_Reference<AUD_SoftwareHandle> >::iterator AUD_HandleIterator; + typedef std::list<boost::shared_ptr<AUD_SoftwareHandle> >::iterator AUD_HandleIterator; /** * The specification of the device. @@ -216,7 +216,7 @@ protected: /** * The mixer. */ - AUD_Reference<AUD_Mixer> m_mixer; + boost::shared_ptr<AUD_Mixer> m_mixer; /** * Whether to do high or low quality resampling. @@ -261,12 +261,12 @@ private: /** * The list of sounds that are currently playing. */ - std::list<AUD_Reference<AUD_SoftwareHandle> > m_playingSounds; + std::list<boost::shared_ptr<AUD_SoftwareHandle> > m_playingSounds; /** * The list of sounds that are currently paused. */ - std::list<AUD_Reference<AUD_SoftwareHandle> > m_pausedSounds; + std::list<boost::shared_ptr<AUD_SoftwareHandle> > m_pausedSounds; /** * Whether there is currently playback. @@ -320,8 +320,8 @@ public: void setQuality(bool quality); virtual AUD_DeviceSpecs getSpecs() const; - virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IReader> reader, bool keep = false); - virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IFactory> factory, bool keep = false); + virtual boost::shared_ptr<AUD_IHandle> play(boost::shared_ptr<AUD_IReader> reader, bool keep = false); + virtual boost::shared_ptr<AUD_IHandle> play(boost::shared_ptr<AUD_IFactory> factory, bool keep = false); virtual void stopAll(); virtual void lock(); virtual void unlock(); diff --git a/intern/audaspace/intern/AUD_StreamBufferFactory.cpp b/intern/audaspace/intern/AUD_StreamBufferFactory.cpp index 1c8d2a99351..daa714aeec3 100644 --- a/intern/audaspace/intern/AUD_StreamBufferFactory.cpp +++ b/intern/audaspace/intern/AUD_StreamBufferFactory.cpp @@ -33,10 +33,10 @@ #include <cstring> -AUD_StreamBufferFactory::AUD_StreamBufferFactory(AUD_Reference<AUD_IFactory> factory) : +AUD_StreamBufferFactory::AUD_StreamBufferFactory(boost::shared_ptr<AUD_IFactory> factory) : m_buffer(new AUD_Buffer()) { - AUD_Reference<AUD_IReader> reader = factory->createReader(); + boost::shared_ptr<AUD_IReader> reader = factory->createReader(); m_specs = reader->getSpecs(); @@ -70,7 +70,7 @@ AUD_StreamBufferFactory::AUD_StreamBufferFactory(AUD_Reference<AUD_IFactory> fac m_buffer->resize(index * sample_size, true); } -AUD_Reference<AUD_IReader> AUD_StreamBufferFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_StreamBufferFactory::createReader() { - return new AUD_BufferReader(m_buffer, m_specs); + return boost::shared_ptr<AUD_IReader>(new AUD_BufferReader(m_buffer, m_specs)); } diff --git a/intern/audaspace/intern/AUD_StreamBufferFactory.h b/intern/audaspace/intern/AUD_StreamBufferFactory.h index 99795d95d33..1bcd73d59b6 100644 --- a/intern/audaspace/intern/AUD_StreamBufferFactory.h +++ b/intern/audaspace/intern/AUD_StreamBufferFactory.h @@ -31,9 +31,10 @@ #define __AUD_STREAMBUFFERFACTORY_H__ #include "AUD_IFactory.h" -#include "AUD_Reference.h" #include "AUD_Buffer.h" +#include <boost/shared_ptr.hpp> + /** * This factory creates a buffer out of a reader. This way normally streamed * sound sources can be loaded into memory for buffered playback. @@ -44,7 +45,7 @@ private: /** * The buffer that holds the audio data. */ - AUD_Reference<AUD_Buffer> m_buffer; + boost::shared_ptr<AUD_Buffer> m_buffer; /** * The specification of the samples. @@ -62,9 +63,9 @@ public: * \param factory The factory that creates the reader for buffering. * \exception AUD_Exception Thrown if the reader cannot be created. */ - AUD_StreamBufferFactory(AUD_Reference<AUD_IFactory> factory); + AUD_StreamBufferFactory(boost::shared_ptr<AUD_IFactory> factory); - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif //__AUD_STREAMBUFFERFACTORY_H__ diff --git a/intern/audaspace/sndfile/AUD_SndFileFactory.cpp b/intern/audaspace/sndfile/AUD_SndFileFactory.cpp index 1fc77fbde66..106b2937a06 100644 --- a/intern/audaspace/sndfile/AUD_SndFileFactory.cpp +++ b/intern/audaspace/sndfile/AUD_SndFileFactory.cpp @@ -43,10 +43,10 @@ AUD_SndFileFactory::AUD_SndFileFactory(const data_t* buffer, int size) : memcpy(m_buffer->getBuffer(), buffer, size); } -AUD_Reference<AUD_IReader> AUD_SndFileFactory::createReader() +boost::shared_ptr<AUD_IReader> AUD_SndFileFactory::createReader() { - if(m_buffer.isNull()) - return new AUD_SndFileReader(m_filename); + if(m_buffer.get()) + return boost::shared_ptr<AUD_IReader>(new AUD_SndFileReader(m_buffer)); else - return new AUD_SndFileReader(m_buffer); + return boost::shared_ptr<AUD_IReader>(new AUD_SndFileReader(m_filename)); } diff --git a/intern/audaspace/sndfile/AUD_SndFileFactory.h b/intern/audaspace/sndfile/AUD_SndFileFactory.h index 7039c7a2615..bc96325d6eb 100644 --- a/intern/audaspace/sndfile/AUD_SndFileFactory.h +++ b/intern/audaspace/sndfile/AUD_SndFileFactory.h @@ -31,10 +31,10 @@ #define __AUD_SNDFILEFACTORY_H__ #include "AUD_IFactory.h" -#include "AUD_Reference.h" #include "AUD_Buffer.h" #include <string> +#include <boost/shared_ptr.hpp> /** * This factory reads a sound file via libsndfile. @@ -50,7 +50,7 @@ private: /** * The buffer to read from. */ - AUD_Reference<AUD_Buffer> m_buffer; + boost::shared_ptr<AUD_Buffer> m_buffer; // hide copy constructor and operator= AUD_SndFileFactory(const AUD_SndFileFactory&); @@ -70,7 +70,7 @@ public: */ AUD_SndFileFactory(const data_t* buffer, int size); - virtual AUD_Reference<AUD_IReader> createReader(); + virtual boost::shared_ptr<AUD_IReader> createReader(); }; #endif //__AUD_SNDFILEFACTORY_H__ diff --git a/intern/audaspace/sndfile/AUD_SndFileReader.cpp b/intern/audaspace/sndfile/AUD_SndFileReader.cpp index 8dbb43cb17e..aaee814f56b 100644 --- a/intern/audaspace/sndfile/AUD_SndFileReader.cpp +++ b/intern/audaspace/sndfile/AUD_SndFileReader.cpp @@ -100,7 +100,7 @@ AUD_SndFileReader::AUD_SndFileReader(std::string filename) : m_seekable = sfinfo.seekable; } -AUD_SndFileReader::AUD_SndFileReader(AUD_Reference<AUD_Buffer> buffer) : +AUD_SndFileReader::AUD_SndFileReader(boost::shared_ptr<AUD_Buffer> buffer) : m_position(0), m_membuffer(buffer), m_memoffset(0) diff --git a/intern/audaspace/sndfile/AUD_SndFileReader.h b/intern/audaspace/sndfile/AUD_SndFileReader.h index 81d8b45120c..5cac5051ee2 100644 --- a/intern/audaspace/sndfile/AUD_SndFileReader.h +++ b/intern/audaspace/sndfile/AUD_SndFileReader.h @@ -31,11 +31,11 @@ #define __AUD_SNDFILEREADER_H__ #include "AUD_IReader.h" -#include "AUD_Reference.h" #include "AUD_Buffer.h" #include <string> #include <sndfile.h> +#include <boost/shared_ptr.hpp> typedef sf_count_t (*sf_read_f)(SNDFILE *sndfile, void *ptr, sf_count_t frames); @@ -78,7 +78,7 @@ private: /** * The pointer to the memory file. */ - AUD_Reference<AUD_Buffer> m_membuffer; + boost::shared_ptr<AUD_Buffer> m_membuffer; /** * The current reading pointer of the memory file. @@ -110,7 +110,7 @@ public: * \exception AUD_Exception Thrown if the buffer specified cannot be read * with libsndfile. */ - AUD_SndFileReader(AUD_Reference<AUD_Buffer> buffer); + AUD_SndFileReader(boost::shared_ptr<AUD_Buffer> buffer); /** * Destroys the reader and closes the file. diff --git a/intern/bsp/CMakeLists.txt b/intern/bsp/CMakeLists.txt index 136c168bdb8..e3907c5273d 100644 --- a/intern/bsp/CMakeLists.txt +++ b/intern/bsp/CMakeLists.txt @@ -29,11 +29,10 @@ set(INC ../guardedalloc ../memutil ../moto/include - ../../extern/carve/include ) set(INC_SYS - + ../../extern/carve/include ) set(SRC diff --git a/intern/bsp/extern/CSG_BooleanOps.h b/intern/bsp/extern/CSG_BooleanOps.h index 94a74c30536..5ba6e0d76a1 100644 --- a/intern/bsp/extern/CSG_BooleanOps.h +++ b/intern/bsp/extern/CSG_BooleanOps.h @@ -61,9 +61,9 @@ extern "C" { #endif typedef struct { - int vertex_index[4]; - int vertex_number; - int orig_face; + int vertex_index[4]; + int vertex_number; + int orig_face; } CSG_IFace; /** @@ -72,7 +72,7 @@ typedef struct { */ typedef struct { - float position[3]; + float position[3]; } CSG_IVertex; /** diff --git a/intern/bsp/intern/BOP_CarveInterface.cpp b/intern/bsp/intern/BOP_CarveInterface.cpp index 1f9c989cbc8..bb3a783548c 100644 --- a/intern/bsp/intern/BOP_CarveInterface.cpp +++ b/intern/bsp/intern/BOP_CarveInterface.cpp @@ -60,7 +60,7 @@ static bool isQuadPlanar(carve::geom3d::Vector &v1, carve::geom3d::Vector &v2, float production = carve::geom::dot(cross, vec3); float magnitude = 1e-5 * cross.length(); - return fabs(production) < magnitude; + return fabsf(production) < magnitude; } static bool isFacePlanar(CSG_IFace &face, std::vector<carve::geom3d::Vector> &vertices) @@ -135,10 +135,10 @@ static bool Carve_checkEdgeFaceIntersections(carve::csg::Intersections &intersec static inline bool Carve_facesAreCoplanar(const MeshSet<3>::face_t *a, const MeshSet<3>::face_t *b) { - carve::geom3d::Ray temp; - // XXX: Find a better definition. This may be a source of problems - // if floating point inaccuracies cause an incorrect answer. - return !carve::geom3d::planeIntersection(a->plane, b->plane, temp); + carve::geom3d::Ray temp; + // XXX: Find a better definition. This may be a source of problems + // if floating point inaccuracies cause an incorrect answer. + return !carve::geom3d::planeIntersection(a->plane, b->plane, temp); } static bool Carve_checkMeshSetInterseciton_do(carve::csg::Intersections &intersections, @@ -205,7 +205,7 @@ static void Carve_getIntersectedOperandMeshes(std::vector<MeshSet<3>::mesh_t*> & std::vector<MeshSet<3>::mesh_t*>::iterator it = meshes.begin(); std::vector< RTreeNode<3, Face<3> *> *> meshRTree; - while(it != meshes.end()) { + while (it != meshes.end()) { MeshSet<3>::mesh_t *mesh = *it; bool isAdded = false; @@ -279,7 +279,7 @@ static MeshSet<3> *Carve_unionIntersectingMeshes(MeshSet<3> *poly, return poly; } - while(orig_meshes.size()) { + while (orig_meshes.size()) { MeshSet<3> *right = Carve_getIntersectedOperand(orig_meshes, otherAABB); if (!right) { @@ -559,8 +559,6 @@ static bool Carve_checkDegeneratedFace(std::map<MeshSet<3>::vertex_t*, uint> *ve if (v1 == v2 || v2 == v3 || v1 == v3) return true; - - return triangleArea(face->edge->prev->vert->v, face->edge->vert->v, face->edge->next->vert->v) < DBL_EPSILON; } else if (face->n_edges == 4) { uint v1, v2, v3, v4; @@ -572,9 +570,6 @@ static bool Carve_checkDegeneratedFace(std::map<MeshSet<3>::vertex_t*, uint> *ve if (v1 == v2 || v1 == v3 || v1 == v4 || v2 == v3 || v2 == v4 || v3 == v4) return true; - - return triangleArea(face->edge->vert->v, face->edge->next->vert->v, face->edge->next->next->vert->v) + - triangleArea(face->edge->prev->vert->v, face->edge->vert->v, face->edge->next->next->vert->v) < DBL_EPSILON; } return false; diff --git a/intern/container/CMakeLists.txt b/intern/container/CMakeLists.txt index b29eea37bc7..8adc46a59de 100644 --- a/intern/container/CMakeLists.txt +++ b/intern/container/CMakeLists.txt @@ -33,14 +33,11 @@ set(INC_SYS ) set(SRC - intern/CTR_List.cpp - CTR_HashedPtr.h - CTR_List.h CTR_Map.h CTR_TaggedIndex.h CTR_TaggedSetOps.h - CTR_UHeap.h ) +# infact nothing to compile! blender_add_lib(bf_intern_ctr "${SRC}" "${INC}" "${INC_SYS}") diff --git a/intern/container/CTR_HashedPtr.h b/intern/container/CTR_HashedPtr.h index 11dc37b3625..ee832eee153 100644 --- a/intern/container/CTR_HashedPtr.h +++ b/intern/container/CTR_HashedPtr.h @@ -30,8 +30,8 @@ * \ingroup ctr */ -#ifndef CTR_HASHEDPTR_H -#define CTR_HASHEDPTR_H +#ifndef __CTR_HASHEDPTR_H__ +#define __CTR_HASHEDPTR_H__ #include <stdlib.h> @@ -43,13 +43,20 @@ inline unsigned int CTR_Hash(void *inDWord) class CTR_HashedPtr { - void* m_valptr; + void *m_valptr; public: - CTR_HashedPtr(void* val) : m_valptr(val) {}; - unsigned int hash() const { return CTR_Hash(m_valptr);}; - inline friend bool operator ==(const CTR_HashedPtr & rhs, const CTR_HashedPtr & lhs) { return rhs.m_valptr == lhs.m_valptr;}; - void *getValue() const { return m_valptr; } + CTR_HashedPtr(void *val) : m_valptr(val) { + } + unsigned int hash() const { + return CTR_Hash(m_valptr); + } + inline friend bool operator ==(const CTR_HashedPtr & rhs, const CTR_HashedPtr & lhs) { + return rhs.m_valptr == lhs.m_valptr; + } + void *getValue() const { + return m_valptr; + } }; -#endif //CTR_HASHEDPTR_H +#endif /* __CTR_HASHEDPTR_H__ */ diff --git a/intern/container/CTR_List.h b/intern/container/CTR_List.h deleted file mode 100644 index 404a08fddf2..00000000000 --- a/intern/container/CTR_List.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file container/CTR_List.h - * \ingroup ctr - */ - - - -#ifndef CTR_LIST_H -#define CTR_LIST_H - -class CTR_Link { -public: - CTR_Link( - ); - - CTR_Link( - CTR_Link *next, - CTR_Link *prev - ); - - CTR_Link * - getNext( - ) const; - - CTR_Link * - getPrev( - ) const; - - bool - isHead( - ) const; - - bool - isTail( - ) const; - - void - insertBefore( - CTR_Link *link - ); - - void - insertAfter( - CTR_Link *link - ); - - void - remove( - ); - -private: - CTR_Link *m_next; - CTR_Link *m_prev; -}; - -class CTR_List { -public: - - CTR_List( - ); - - CTR_Link * - getHead( - ) const; - - CTR_Link * - getTail( - ) const; - - void - addHead( - CTR_Link *link - ); - - void - addTail( - CTR_Link *link - ); - -private: - CTR_Link m_head; - CTR_Link m_tail; -}; - -#endif - diff --git a/intern/container/CTR_Map.h b/intern/container/CTR_Map.h index 9557821d642..c278fe5330c 100644 --- a/intern/container/CTR_Map.h +++ b/intern/container/CTR_Map.h @@ -29,22 +29,22 @@ * \ingroup ctr */ - -#ifndef CTR_MAP_H -#define CTR_MAP_H +#ifndef __CTR_MAP_H__ +#define __CTR_MAP_H__ template <class Key, class Value> class CTR_Map { private: struct Entry { Entry (Entry *next, Key key, Value value) : - m_next(next), - m_key(key), - m_value(value) {} + m_next(next), + m_key(key), + m_value(value) { + } Entry *m_next; - Key m_key; - Value m_value; + Key m_key; + Value m_value; }; public: @@ -63,18 +63,18 @@ public: for (int i = 0; i < m_num_buckets; ++i) { m_buckets[i] = 0; - for (Entry *entry = map.m_buckets[i]; entry; entry=entry->m_next) + for (Entry *entry = map.m_buckets[i]; entry; entry = entry->m_next) { insert(entry->m_key, entry->m_value); + } } } - int size() { - int count=0; - for (int i=0;i<m_num_buckets;i++) - { - Entry* bucket = m_buckets[i]; - while(bucket) - { + int size() + { + int count = 0; + for (int i = 0; i < m_num_buckets; i++) { + Entry *bucket = m_buckets[i]; + while (bucket) { bucket = bucket->m_next; count++; } @@ -82,15 +82,13 @@ public: return count; } - Value* at(int index) { - int count=0; - for (int i=0;i<m_num_buckets;i++) - { - Entry* bucket = m_buckets[i]; - while(bucket) - { - if (count==index) - { + Value *at(int index) + { + int count = 0; + for (int i = 0; i < m_num_buckets; i++) { + Entry *bucket = m_buckets[i]; + while (bucket) { + if (count == index) { return &bucket->m_value; } bucket = bucket->m_next; @@ -100,15 +98,13 @@ public: return 0; } - Key* getKey(int index) { - int count=0; - for (int i=0;i<m_num_buckets;i++) - { - Entry* bucket = m_buckets[i]; - while(bucket) - { - if (count==index) - { + Key *getKey(int index) + { + int count = 0; + for (int i = 0; i < m_num_buckets; i++) { + Entry *bucket = m_buckets[i]; + while (bucket) { + if (count == index) { return &bucket->m_key; } bucket = bucket->m_next; @@ -118,7 +114,8 @@ public: return 0; } - void clear() { + void clear() + { for (int i = 0; i < m_num_buckets; ++i) { Entry *entry_ptr = m_buckets[i]; @@ -131,12 +128,14 @@ public: } } - ~CTR_Map() { + ~CTR_Map() + { clear(); - delete [] m_buckets; + delete[] m_buckets; } - void insert(const Key& key, const Value& value) { + void insert(const Key& key, const Value& value) + { Entry *entry_ptr = m_buckets[key.hash() % m_num_buckets]; while ((entry_ptr != 0) && !(key == entry_ptr->m_key)) { entry_ptr = entry_ptr->m_next; @@ -151,7 +150,8 @@ public: } } - void remove(const Key& key) { + void remove(const Key& key) + { Entry **entry_ptr = &m_buckets[key.hash() % m_num_buckets]; while ((*entry_ptr != 0) && !(key == (*entry_ptr)->m_key)) { entry_ptr = &(*entry_ptr)->m_next; @@ -164,7 +164,8 @@ public: } } - Value *operator[](Key key) { + Value *operator[](Key key) + { Entry *bucket = m_buckets[key.hash() % m_num_buckets]; while ((bucket != 0) && !(key == bucket->m_key)) { bucket = bucket->m_next; @@ -177,5 +178,4 @@ private: Entry **m_buckets; }; -#endif - +#endif /* __CTR_MAP_H__ */ diff --git a/intern/container/CTR_TaggedIndex.h b/intern/container/CTR_TaggedIndex.h index 8420414d6c7..0eb4e02e84f 100644 --- a/intern/container/CTR_TaggedIndex.h +++ b/intern/container/CTR_TaggedIndex.h @@ -29,13 +29,6 @@ * \ingroup ctr */ - -/** - - * Copyright (C) 2001 NaN Technologies B.V. - * Simple tagged index class. - */ - #ifndef __CTR_TAGGEDINDEX_H__ #define __CTR_TAGGEDINDEX_H__ @@ -53,7 +46,6 @@ #include "MEM_sys_types.h" enum { - empty_tag = 0x0, empty_index = 0xffffffff }; @@ -191,7 +183,7 @@ public: return (Tag() == Empty().Tag()); } - // functionals + /* functionals */ struct greater : std::binary_function<CTR_TaggedIndex, CTR_TaggedIndex, bool> { @@ -213,7 +205,6 @@ private : unsigned int m_val; -}; - -#endif +}; +#endif /* __CTR_TAGGEDINDEX_H__ */ diff --git a/intern/container/CTR_TaggedSetOps.h b/intern/container/CTR_TaggedSetOps.h index d30081d2d60..6ebf20b77bf 100644 --- a/intern/container/CTR_TaggedSetOps.h +++ b/intern/container/CTR_TaggedSetOps.h @@ -50,16 +50,16 @@ * type ObjectType must have the following public methods to be used by * this template class: * - * int + * int * OpenTag(void) --- return a persistent tag value for the primitive * - * void + * void * SetOpenTag(int bla) --- set the persistent tag value for this primitive to bla. * - * bool + * bool * SelectTag() --- return a persistent boolean tag for this primitive * - * void + * void * SetSelectTag(bool bla) --- set the persistent boolean tag for this primitive to bla. * * Here persistent means that the tag should be associated with the object for the @@ -86,16 +86,16 @@ public : unsigned int shift ) { - // iterate through vectors in index_list - // iterate through individual members of each vector - // mark each obejct that the index points to + /* iterate through vectors in index_list + * iterate through individual members of each vector + * mark each obejct that the index points to */ typename std::vector< std::vector<IndexType> >::const_iterator last_vector = index_list.end(); typename std::vector< std::vector<IndexType> >::const_iterator start_vector = index_list.begin(); - // FIXME some temporary space + /* FIXME some temporary space */ std::vector<IndexType> temp_union; temp_union.reserve(64); @@ -114,7 +114,7 @@ public : ObjectType & prim = primitives[*start_index]; if (!prim.OpenTag()) { - // compute the union + /* compute the union */ temp_union.push_back(*start_index); } int tag = prim.OpenTag(); @@ -126,7 +126,7 @@ public : ++tag_num; } - // now iterate through the union and pull out all those with the right tag + /* now iterate through the union and pull out all those with the right tag */ typename std::vector<IndexType>::const_iterator last_index = temp_union.end(); @@ -138,20 +138,20 @@ public : ObjectType & prim = primitives[*start_index]; if (prim.OpenTag() == tag_num) { - //it's part of the intersection! + /* it's part of the intersection! */ output.push_back(*start_index); - // because we're iterating through the union - // it's safe to remove the tag at this point + /* because we're iterating through the union + * it's safe to remove the tag at this point */ prim.SetOpenTag(prim.OpenTag() & ~mask); } } }; - // note not a strict set intersection! - // if x appears twice in b and is part of the intersection - // it will appear twice in the intersection + /* note not a strict set intersection! + * if x appears twice in b and is part of the intersection + * it will appear twice in the intersection */ static void @@ -180,7 +180,7 @@ public : output.push_back(*start_index); } } - // deselect + /* deselect */ last_index = a.end(); start_index = a.begin(); @@ -199,9 +199,9 @@ public : std::vector<IndexType> &output ) { - // iterate through vectors in index_list - // iterate through individual members of each vector - // mark each obejct that the index points to + /* iterate through vectors in index_list + * iterate through individual members of each vector + * mark each obejct that the index points to */ typename std::vector< std::vector<IndexType> >::const_iterator last_vector = index_list.end(); @@ -220,15 +220,15 @@ public : ObjectType & prim = primitives[*start_index]; if (!prim.SelectTag()) { - // compute the union + /* compute the union */ output.push_back(*start_index); prim.SetSelectTag(true); } } } - // now iterate through the union and reset the tags - + /* now iterate through the union and reset the tags */ + typename std::vector<IndexType>::const_iterator last_index = output.end(); typename std::vector<IndexType>::iterator start_index = @@ -238,7 +238,7 @@ public : ObjectType & prim = primitives[*start_index]; prim.SetSelectTag(false); - } + } } @@ -251,8 +251,8 @@ public : std::vector< IndexType> &output ) { - // iterate through b mark all - // iterate through a and add to output all unmarked + /* iterate through b mark all + * iterate through a and add to output all unmarked */ typename std::vector<IndexType>::const_iterator last_index = b.end(); @@ -276,7 +276,7 @@ public : } } - // clean up the tags + /* clean up the tags */ last_index = b.end(); start_index = b.begin(); @@ -290,12 +290,11 @@ public : private : - // private constructor - this class is not meant for - // instantiation + /* private constructor - this class is not meant for + * instantiation */ CTR_TaggedSetOps(); }; -#endif - +#endif /* __CTR_TAGGEDSETOPS_H__ */ diff --git a/intern/container/CTR_UHeap.h b/intern/container/CTR_UHeap.h deleted file mode 100644 index 8330faa2f54..00000000000 --- a/intern/container/CTR_UHeap.h +++ /dev/null @@ -1,307 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file container/CTR_UHeap.h - * \ingroup ctr - */ - - -/** - - * Copyright (C) 2001 NaN Technologies B.V. - * - * @author Laurence - * @mainpage CTR_UHeap an updatable heap template class (also - * known as an updatable priority queue) - * - * Todo: Make CTR_UHeapable a template class with m_key the - * template parameter, so that arbitrary value types with - * operators (=,>) defined can be used. - * - */ - -#ifndef __CTR_UHEAP_H__ -#define __CTR_UHEAP_H__ - -#include <vector> - -#include "MEM_NonCopyable.h" - -class CTR_UHeapable { - -public: - int & - HeapPos( - ) { - return m_ind; - }; - float & - HeapKey( - ) { - return m_key; - }; - - const - float & - HeapKey( - ) const { - return m_key; - }; - - const - int & - HeapPos( - ) const { - return m_ind; - }; - -private: - - float m_key; - int m_ind; - -protected: - - CTR_UHeapable( - ) : m_key(0), - m_ind(0) - { - }; - - ~CTR_UHeapable( - ) { - }; -}; - -template <class HeapType> -class CTR_UHeap : public MEM_NonCopyable -{ - -public: - - static - CTR_UHeap * - New( - ) { - return new CTR_UHeap(); - } - - void - MakeHeap( - HeapType *base - ) { - int i; - int start = Parent(m_vector.size() - 1); - for (i = start; i >= 0; --i) { - DownHeap(base, i); - } - }; - - void - Insert( - HeapType *base, - int elem - ) { - // add element to vector - m_vector.push_back(elem); - base[elem].HeapPos() = m_vector.size() - 1; - - // push the element up the heap - UpHeap(base, m_vector.size() - 1); - } - - // access to the vector for initial loading of elements - - std::vector<int> & - HeapVector( - ) { - return m_vector; - }; - - - void - Remove( - HeapType *base, - int i - ) { - - // exchange with last element - pop last - // element and move up or down the heap as appropriate - if (m_vector.empty()) { - assert(false); - } - - if (i != int(m_vector.size()) - 1) { - - Swap(base, i, m_vector.size() - 1); - m_vector.pop_back(); - - if (!m_vector.empty()) { - UpHeap(base, i); - DownHeap(base, i); - } - } - else { - m_vector.pop_back(); - } - } - - int - Top( - ) const { - if (m_vector.empty()) return -1; - return m_vector[0]; - } - - - void - SC_Heap( - HeapType *base - ) { - int i; - for (i = 1; i < int(m_vector.size()); i++) { - - CTR_UHeapable *elem = base + m_vector[i]; - CTR_UHeapable *p_elem = base + m_vector[Parent(i)]; - - assert(p_elem->HeapKey() >= elem->HeapKey()); - assert(elem->HeapPos() == i); - } - - }; - - - ~CTR_UHeap( - ) { - }; - - -private: - - CTR_UHeap( - ) { - }; - - - std::vector<int> m_vector; - -private: - void - Swap( - HeapType *base, - int i, - int j - ) { - std::swap(m_vector[i], m_vector[j]); - - CTR_UHeapable *heap_i = base + m_vector[i]; - CTR_UHeapable *heap_j = base + m_vector[j]; - - // Exchange heap positions - heap_i->HeapPos() = i; - heap_j->HeapPos() = j; - } - - int - Parent( - unsigned int i - ) { - return (i - 1) >> 1; - } - int - Left( - int i - ) { - return (i << 1) + 1; - } - - int - Right( - int i - ) { - return (i << 1) + 2; - } - - float - HeapVal( - HeapType *base, - int i - ) { - return base[m_vector[i]].HeapKey(); - } - - void - DownHeap( - HeapType *base, - int i - ) { - int heap_size = m_vector.size(); - - int l = Left(i); - int r = Right(i); - - int largest; - if (l < heap_size && HeapVal(base, l) > HeapVal(base, i)) { - largest = l; - } - else { - largest = i; - } - - if (r < heap_size && HeapVal(base, r) > HeapVal(base, largest)) { - largest = r; - } - - if (largest != i) { - // exchange i and largest - Swap(base, i, largest); - DownHeap(base, largest); - } - } - - void - UpHeap( - HeapType *base, - int i - ) { - - // swap parents untill it's found a place in the heap < it's parent or - // top of heap - - while (i > 0) { - int p = Parent(i); - if (HeapVal(base, i) < HeapVal(base, p)) { - break; - } - Swap(base, p, i); - i = p; - } - } -}; - -#endif - diff --git a/intern/container/intern/CTR_List.cpp b/intern/container/intern/CTR_List.cpp deleted file mode 100644 index c72d3ccf0d8..00000000000 --- a/intern/container/intern/CTR_List.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file container/intern/CTR_List.cpp - * \ingroup ctr - */ - - -#include "CTR_List.h" - - -CTR_Link::CTR_Link() : - m_next(0), - m_prev(0) -{ -} - -CTR_Link::CTR_Link(CTR_Link *next, CTR_Link *prev) : - m_next(next), - m_prev(prev) -{ -} - -CTR_Link * -CTR_Link::getNext() const -{ - return m_next; -} - -CTR_Link * -CTR_Link::getPrev() const -{ - return m_prev; -} - -bool -CTR_Link::isHead() const -{ - return m_prev == 0; -} - -bool -CTR_Link::isTail() const -{ - return m_next == 0; -} - -void -CTR_Link::insertBefore(CTR_Link *link) -{ - m_next = link; - m_prev = link->m_prev; - m_next->m_prev = this; - m_prev->m_next = this; -} - -void -CTR_Link::insertAfter(CTR_Link *link) -{ - m_next = link->m_next; - m_prev = link; - m_next->m_prev = this; - m_prev->m_next = this; -} - -void -CTR_Link::remove() -{ - m_next->m_prev = m_prev; - m_prev->m_next = m_next; -} - - -CTR_List::CTR_List() : - m_head(&m_tail, 0), - m_tail(0, &m_head) -{ -} - -CTR_Link * -CTR_List:: getHead() const -{ - return m_head.getNext(); -} - -CTR_Link * -CTR_List::getTail() const -{ - return m_tail.getPrev(); -} - -void -CTR_List::addHead(CTR_Link *link) -{ - link->insertAfter(&m_head); -} - -void -CTR_List::addTail(CTR_Link *link) -{ - link->insertBefore(&m_tail); -} - diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index 38daf790955..7495a98aed1 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -41,10 +41,7 @@ endif() if(WITH_CYCLES_OSL) add_definitions(-DWITH_OSL) -endif() - -if(WITH_CYCLES_PARTIO) - add_definitions(-DWITH_PARTIO) + include_directories(${OSL_INCLUDES}) endif() if(WITH_CYCLES_CUDA_BINARIES) @@ -68,7 +65,10 @@ if(WITH_CYCLES_BLENDER) add_subdirectory(blender) endif() -add_subdirectory(app) +if(WITH_CYCLES_TEST) + add_subdirectory(app) +endif() + add_subdirectory(bvh) add_subdirectory(device) add_subdirectory(doc) diff --git a/intern/cycles/SConscript b/intern/cycles/SConscript index a7b8637e3ad..c0e0353d37d 100644 --- a/intern/cycles/SConscript +++ b/intern/cycles/SConscript @@ -29,7 +29,7 @@ if env['WITH_BF_CYCLES_CUDA_BINARIES']: incs.extend('. bvh render device kernel kernel/osl kernel/svm util subd'.split()) incs.extend('#intern/guardedalloc #source/blender/makesrna #source/blender/makesdna'.split()) incs.extend('#source/blender/blenloader ../../source/blender/makesrna/intern'.split()) -incs.extend('#extern/glew/include'.split()) +incs.extend('#extern/glew/include #intern/mikktspace'.split()) incs.append(cycles['BF_OIIO_INC']) incs.append(cycles['BF_BOOST_INC']) incs.append(cycles['BF_PYTHON_INC']) diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt index 83b3f731ffe..3fb8aaf934f 100644 --- a/intern/cycles/app/CMakeLists.txt +++ b/intern/cycles/app/CMakeLists.txt @@ -35,10 +35,6 @@ if(WITH_CYCLES_OSL) list(APPEND LIBRARIES cycles_kernel_osl ${OSL_LIBRARIES}) endif() -if(WITH_CYCLES_PARTIO) - list(APPEND LIBRARIES ${PARTIO_LIBRARIES}) -endif() - include_directories(${INC}) include_directories(SYSTEM ${INC_SYS}) diff --git a/intern/cycles/app/cycles_test.cpp b/intern/cycles/app/cycles_test.cpp index e921cc46fe4..625e8cc1706 100644 --- a/intern/cycles/app/cycles_test.cpp +++ b/intern/cycles/app/cycles_test.cpp @@ -326,7 +326,7 @@ using namespace ccl; int main(int argc, const char **argv) { - path_init("../build/bin/2.59/scripts/addons/cycles/"); + path_init(); options_parse(argc, argv); diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index 87a238e508c..5de9d71b8cc 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -591,6 +591,7 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug if(string_iequals(in->name, attr.name())) { switch(in->type) { case SHADER_SOCKET_FLOAT: + case SHADER_SOCKET_INT: xml_read_float(&in->value.x, node, attr.name()); break; case SHADER_SOCKET_COLOR: diff --git a/intern/cycles/blender/CCL_api.h b/intern/cycles/blender/CCL_api.h index 469d63d1530..b8a30b71717 100644 --- a/intern/cycles/blender/CCL_api.h +++ b/intern/cycles/blender/CCL_api.h @@ -23,12 +23,12 @@ extern "C" { #endif -/* returns a list of devices for selection, array is name NULL pointer +/* returns a list of devices for selection, array is empty identifier * terminated and must not be freed */ typedef struct CCLDeviceInfo { - const char *identifier; - const char *name; + char identifier[128]; + char name[512]; int value; } CCLDeviceInfo; diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt index a8c7eef89fa..292c37d6b61 100644 --- a/intern/cycles/blender/CMakeLists.txt +++ b/intern/cycles/blender/CMakeLists.txt @@ -7,6 +7,7 @@ set(INC ../util ../subd ../../guardedalloc + ../../mikktspace ../../../source/blender/makesdna ../../../source/blender/makesrna ../../../source/blender/blenloader @@ -38,6 +39,7 @@ set(ADDON_FILES addon/__init__.py addon/engine.py addon/enums.py + addon/osl.py addon/presets.py addon/properties.py addon/ui.py diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py index 6292c09fbb1..0fad2ac5618 100644 --- a/intern/cycles/blender/addon/__init__.py +++ b/intern/cycles/blender/addon/__init__.py @@ -48,7 +48,11 @@ class CyclesRender(bpy.types.RenderEngine): # final render def update(self, data, scene): - engine.create(self, data, scene) + if not self.session: + engine.create(self, data, scene) + else: + engine.reset(self, data, scene) + engine.update(self, data, scene) def render(self, scene): @@ -71,6 +75,13 @@ class CyclesRender(bpy.types.RenderEngine): def view_draw(self, context): engine.draw(self, context.region, context.space_data, context.region_data) + def update_script_node(self, node): + if engine.with_osl(): + from . import osl + osl.update_script_node(node, self.report) + else: + self.report({'ERROR'}, "OSL support disabled in this build.") + def register(): properties.register() @@ -84,3 +95,4 @@ def unregister(): properties.unregister() presets.unregister() bpy.utils.unregister_module(__name__) + diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index 05b1f883594..ca5cbee9325 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -61,6 +61,13 @@ def render(engine): _cycles.render(engine.session) +def reset(engine, data, scene): + import _cycles + data = data.as_pointer() + scene = scene.as_pointer() + _cycles.reset(engine.session, data, scene) + + def update(engine, data, scene): import _cycles _cycles.sync(engine.session) @@ -83,3 +90,4 @@ def available_devices(): def with_osl(): import _cycles return _cycles.with_osl + diff --git a/intern/cycles/blender/addon/enums.py b/intern/cycles/blender/addon/enums.py index 6cc3010eb0e..82b48973ca1 100644 --- a/intern/cycles/blender/addon/enums.py +++ b/intern/cycles/blender/addon/enums.py @@ -58,5 +58,6 @@ aperture_types = ( panorama_types = ( ('EQUIRECTANGULAR', "Equirectangular", "Render the scene with a spherical camera, also known as Lat Long panorama"), ('FISHEYE_EQUIDISTANT', "Fisheye Equidistant", "Ideal for fulldomes, ignore the sensor dimensions"), - ('FISHEYE_EQUISOLID', "Fisheye Equisolid", "Similar to most fisheye modern lens, take sensor dimensions into consideration"), + ('FISHEYE_EQUISOLID', "Fisheye Equisolid", + "Similar to most fisheye modern lens, takes sensor dimensions into consideration"), ) diff --git a/intern/cycles/blender/addon/osl.py b/intern/cycles/blender/addon/osl.py new file mode 100644 index 00000000000..aac1e2422b9 --- /dev/null +++ b/intern/cycles/blender/addon/osl.py @@ -0,0 +1,127 @@ +# +# Copyright 2011, Blender Foundation. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# + +# <pep8 compliant> + +import bpy, _cycles, os, tempfile + +# compile .osl file with given filepath to temporary .oso file +def osl_compile(input_path, report): + output_file = tempfile.NamedTemporaryFile(mode='w', suffix=".oso", delete=False) + output_path = output_file.name + output_file.close() + + ok = _cycles.osl_compile(input_path, output_path) + + if ok: + report({'INFO'}, "OSL shader compilation succeeded") + + return ok, output_path + +# compile and update shader script node +def update_script_node(node, report): + import os, shutil + + if node.mode == 'EXTERNAL': + # compile external script file + script_path = bpy.path.abspath(node.filepath, library=node.id_data.library) + script_path_noext, script_ext = os.path.splitext(script_path) + + if script_ext == ".oso": + # it's a .oso file, no need to compile + ok, oso_path = True, script_path + oso_file_remove = False + elif script_ext == ".osl": + # compile .osl file + ok, oso_path = osl_compile(script_path, report) + oso_file_remove = True + + if ok: + # copy .oso from temporary path to .osl directory + dst_path = script_path_noext + ".oso" + try: + shutil.copy2(oso_path, dst_path) + except: + report({'ERROR'}, "Failed to write .oso file next to external .osl file at " + dst_path) + elif os.path.dirname(node.filepath) == "": + # module in search path + oso_path = node.filepath + oso_file_remove = False + ok = True + else: + # unknown + report({'ERROR'}, "External shader script must have .osl or .oso extension, or be a module name") + ok = False + + if ok: + node.bytecode = "" + node.bytecode_hash = "" + + elif node.mode == 'INTERNAL' and node.script: + # internal script, we will store bytecode in the node + script = node.script + osl_path = bpy.path.abspath(script.filepath, library=script.library) + + if script.is_in_memory or script.is_dirty or script.is_modified or not os.path.exists(osl_path): + # write text datablock contents to temporary file + osl_file = tempfile.NamedTemporaryFile(mode='w', suffix=".osl", delete=True) + osl_file.write(script.as_string()) + osl_file.flush() + ok, oso_path = osl_compile(osl_file.name, report) + oso_file_remove = False + osl_file.close() + else: + # compile text datablock from disk directly + ok, oso_path = osl_compile(osl_path, report) + oso_file_remove = False + + if ok: + # read bytecode + try: + oso = open(oso_path, 'r') + node.bytecode = oso.read() + oso.close() + except: + import traceback + traceback.print_exc() + + report({'ERROR'}, "Can't read OSO bytecode to store in node at %r" % oso_path) + ok = False + + else: + report({'WARNING'}, "No text or file specified in node, nothing to compile") + return + + if ok: + # now update node with new sockets + ok = _cycles.osl_update_node(node.id_data.as_pointer(), node.as_pointer(), oso_path) + + if not ok: + report({'ERROR'}, "OSL query failed to open " + oso_path) + else: + report({'ERROR'}, "OSL script compilation failed, see console for errors") + + # remove temporary oso file + if oso_file_remove: + try: + os.remove(oso_path) + except: + pass + + return ok + diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 0fadfa0afc8..0b8ca6e0fbe 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -136,7 +136,8 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): ) cls.blur_glossy = FloatProperty( name="Filter Glossy", - description="Adaptively blur glossy shaders after blurry bounces, to reduce noise at the cost of accuracy", + description="Adaptively blur glossy shaders after blurry bounces, " + "to reduce noise at the cost of accuracy", min=0.0, max=10.0, default=0.0, ) @@ -230,7 +231,9 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): cls.sample_clamp = FloatProperty( name="Clamp", - description="If non-zero, the maximum value for a sample, higher values will be scaled down to avoid too much noise and slow convergence at the cost of accuracy", + description="If non-zero, the maximum value for a sample, " + "higher values will be scaled down to avoid too " + "much noise and slow convergence at the cost of accuracy", min=0.0, max=1e8, default=0.0, ) @@ -244,7 +247,8 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): cls.preview_start_resolution = IntProperty( name="Start Resolution", - description="Resolution to start rendering preview at, progressively increasing it to the full viewport size", + description="Resolution to start rendering preview at, " + "progressively increasing it to the full viewport size", min=8, max=16384, default=64, ) @@ -284,6 +288,14 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): description="Cache last built BVH to disk for faster re-render if no geometry changed", default=False, ) + cls.use_progressive_refine = BoolProperty( + name="Progressive Refine", + description="Instead of rendering each tile until it is finished, " + "refine the whole image progressively " + "(this renders somewhat slower, " + "but time can be saved by manually stopping the render when the noise is low enough)", + default=False, + ) @classmethod def unregister(cls): @@ -369,12 +381,15 @@ class CyclesMaterialSettings(bpy.types.PropertyGroup): ) cls.sample_as_light = BoolProperty( name="Sample as Lamp", - description="Use direct light sampling for this material, disabling may reduce overall noise for large objects that emit little light compared to other light sources", + description="Use direct light sampling for this material, " + "disabling may reduce overall noise for large " + "objects that emit little light compared to other light sources", default=True, ) cls.homogeneous_volume = BoolProperty( name="Homogeneous Volume", - description="When using volume rendering, assume volume has the same density everywhere, for faster rendering", + description="When using volume rendering, assume volume has the same density everywhere, " + "for faster rendering", default=False, ) @@ -418,12 +433,14 @@ class CyclesWorldSettings(bpy.types.PropertyGroup): ) cls.sample_as_light = BoolProperty( name="Sample as Lamp", - description="Use direct light sampling for the environment, enabling for non-solid colors is recommended", + description="Use direct light sampling for the environment, " + "enabling for non-solid colors is recommended", default=False, ) cls.sample_map_resolution = IntProperty( name="Map Resolution", - description="Importance map size is resolution x resolution; higher values potentially produce less noise, at the cost of memory and speed", + description="Importance map size is resolution x resolution; " + "higher values potentially produce less noise, at the cost of memory and speed", min=4, max=8096, default=256, ) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 4f4b0371839..4a651eb5aab 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -134,10 +134,6 @@ class CyclesRender_PT_motion_blur(CyclesButtonsPanel, Panel): bl_label = "Motion Blur" bl_options = {'DEFAULT_CLOSED'} - @classmethod - def poll(cls, context): - return False - def draw_header(self, context): rd = context.scene.render @@ -197,10 +193,12 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel): sub.prop(rd, "threads") sub = col.column(align=True) - sub.label(text="Tiles:") + sub.label(text="Tile Size:") - sub.prop(rd, "parts_x", text="X") - sub.prop(rd, "parts_y", text="Y") + sub.prop(rd, "tile_x", text="X") + sub.prop(rd, "tile_y", text="Y") + + sub.prop(cscene, "use_progressive_refine") subsub = sub.column() subsub.enabled = not rd.use_border @@ -218,6 +216,10 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel): sub.label(text="Viewport:") sub.prop(cscene, "preview_start_resolution") + sub = col.column(align=True) + sub.label(text="Final Render:") + sub.prop(rd, "use_persistent_data", text="Persistent Images") + class CyclesRender_PT_layers(CyclesButtonsPanel, Panel): bl_label = "Layers" @@ -955,7 +957,7 @@ def draw_device(self, context): elif device_type == 'OPENCL' and cscene.feature_set == 'EXPERIMENTAL': layout.prop(cscene, "device") - if engine.with_osl() and (cscene.device == 'CPU' or device_type == 'None'): + if engine.with_osl() and (cscene.device == 'CPU' or device_type == 'NONE'): layout.prop(cscene, "shading_system") @@ -990,6 +992,7 @@ def get_panels(): bpy.types.DATA_PT_context_mesh, bpy.types.DATA_PT_context_camera, bpy.types.DATA_PT_context_lamp, + bpy.types.DATA_PT_context_speaker, bpy.types.DATA_PT_texture_space, bpy.types.DATA_PT_curve_texture_space, bpy.types.DATA_PT_mball_texture_space, @@ -1000,10 +1003,14 @@ def get_panels(): bpy.types.DATA_PT_camera, bpy.types.DATA_PT_camera_display, bpy.types.DATA_PT_lens, + bpy.types.DATA_PT_speaker, + bpy.types.DATA_PT_distance, + bpy.types.DATA_PT_cone, bpy.types.DATA_PT_customdata, bpy.types.DATA_PT_custom_props_mesh, bpy.types.DATA_PT_custom_props_camera, bpy.types.DATA_PT_custom_props_lamp, + bpy.types.DATA_PT_custom_props_speaker, bpy.types.TEXTURE_PT_clouds, bpy.types.TEXTURE_PT_wood, bpy.types.TEXTURE_PT_marble, diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index e16677336d5..61fe7cf254d 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -56,10 +56,8 @@ struct BlenderCamera { float sensor_width; float sensor_height; - float border_left; - float border_right; - float border_bottom; - float border_top; + BoundBox2D border; + BoundBox2D pano_viewplane; Transform matrix; }; @@ -75,8 +73,10 @@ static void blender_camera_init(BlenderCamera *bcam) bcam->sensor_height = 18.0f; bcam->sensor_fit = BlenderCamera::AUTO; bcam->shuttertime = 1.0f; - bcam->border_right = 1.0f; - bcam->border_top = 1.0f; + bcam->border.right = 1.0f; + bcam->border.top = 1.0f; + bcam->pano_viewplane.right = 1.0f; + bcam->pano_viewplane.top = 1.0f; } static float blender_camera_focal_distance(BL::Object b_ob, BL::Camera b_camera) @@ -199,7 +199,7 @@ static Transform blender_camera_matrix(const Transform& tfm, CameraType type) } static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height, - float *left, float *right, float *bottom, float *top, float *aspectratio, float *sensor_size) + BoundBox2D *viewplane, float *aspectratio, float *sensor_size) { /* dimensions */ float xratio = width*bcam->pixelaspect.x; @@ -244,32 +244,26 @@ static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height, if(bcam->type == CAMERA_PANORAMA) { /* set viewplane */ - *left = 0.0f; - *right = 1.0f; - *bottom = 0.0f; - *top = 1.0f; + *viewplane = bcam->pano_viewplane; } else { /* set viewplane */ - *left = -xaspect; - *right = xaspect; - *bottom = -yaspect; - *top = yaspect; + viewplane->left = -xaspect; + viewplane->right = xaspect; + viewplane->bottom = -yaspect; + viewplane->top = yaspect; /* zoom for 3d camera view */ - *left *= bcam->zoom; - *right *= bcam->zoom; - *bottom *= bcam->zoom; - *top *= bcam->zoom; + *viewplane = (*viewplane) * bcam->zoom; /* modify viewplane with camera shift and 3d camera view offset */ float dx = 2.0f*(*aspectratio*bcam->shift.x + bcam->offset.x*xaspect*2.0f); float dy = 2.0f*(*aspectratio*bcam->shift.y + bcam->offset.y*yaspect*2.0f); - *left += dx; - *right += dx; - *bottom += dy; - *top += dy; + viewplane->left += dx; + viewplane->right += dx; + viewplane->bottom += dy; + viewplane->top += dy; } } @@ -281,7 +275,7 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int /* viewplane */ blender_camera_viewplane(bcam, width, height, - &cam->left, &cam->right, &cam->bottom, &cam->top, &aspectratio, &sensor_size); + &cam->viewplane, &aspectratio, &sensor_size); /* sensor */ cam->sensorwidth = bcam->sensor_width; @@ -314,10 +308,7 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int cam->shuttertime = bcam->shuttertime; /* border */ - cam->border_left = bcam->border_left; - cam->border_right = bcam->border_right; - cam->border_bottom = bcam->border_bottom; - cam->border_top = bcam->border_top; + cam->border = bcam->border; /* set update flag */ if(cam->modified(prevcam)) @@ -340,10 +331,10 @@ void BlenderSync::sync_camera(BL::Object b_override, int width, int height) /* border */ if(r.use_border()) { - bcam.border_left = r.border_min_x(); - bcam.border_right = r.border_max_x(); - bcam.border_bottom = r.border_min_y(); - bcam.border_top = r.border_max_y(); + bcam.border.left = r.border_min_x(); + bcam.border.right = r.border_max_x(); + bcam.border.bottom = r.border_min_y(); + bcam.border.top = r.border_max_y(); } /* camera object */ @@ -381,6 +372,9 @@ void BlenderSync::sync_camera_motion(BL::Object b_ob, int motion) /* Sync 3D View Camera */ +static void blender_camera_view_subset(BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d, + BL::RegionView3D b_rv3d, int width, int height, BoundBox2D *view_box, BoundBox2D *cam_box); + static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height, bool skip_panorama = false) { /* 3d view parameters */ @@ -396,14 +390,25 @@ static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL: if(b_ob) { blender_camera_from_object(bcam, b_ob, skip_panorama); - /* magic zoom formula */ - bcam->zoom = (float)b_rv3d.view_camera_zoom(); - bcam->zoom = (1.41421f + bcam->zoom/50.0f); - bcam->zoom *= bcam->zoom; - bcam->zoom = 2.0f/bcam->zoom; - - /* offset */ - bcam->offset = get_float2(b_rv3d.view_camera_offset()); + if(!skip_panorama && bcam->type == CAMERA_PANORAMA) { + /* in panorama camera view, we map viewplane to camera border */ + BoundBox2D view_box, cam_box; + + blender_camera_view_subset(b_scene, b_ob, b_v3d, b_rv3d, width, height, + &view_box, &cam_box); + + bcam->pano_viewplane = view_box.make_relative_to(cam_box); + } + else { + /* magic zoom formula */ + bcam->zoom = (float)b_rv3d.view_camera_zoom(); + bcam->zoom = (1.41421f + bcam->zoom/50.0f); + bcam->zoom *= bcam->zoom; + bcam->zoom = 2.0f/bcam->zoom; + + /* offset */ + bcam->offset = get_float2(b_rv3d.view_camera_offset()); + } } } else if(b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_ORTHO) { @@ -411,8 +416,14 @@ static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL: bcam->farclip *= 0.5f; bcam->nearclip = -bcam->farclip; + float sensor_size; + if(bcam->sensor_fit == BlenderCamera::VERTICAL) + sensor_size = bcam->sensor_height; + else + sensor_size = bcam->sensor_width; + bcam->type = CAMERA_ORTHOGRAPHIC; - bcam->ortho_scale = b_rv3d.view_distance(); + bcam->ortho_scale = b_rv3d.view_distance() * sensor_size / b_v3d.lens(); } bcam->zoom *= 2.0f; @@ -421,30 +432,11 @@ static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL: bcam->matrix = transform_inverse(get_transform(b_rv3d.view_matrix())); } -static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::SpaceView3D b_v3d, - BL::RegionView3D b_rv3d, int width, int height) +static void blender_camera_view_subset(BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d, + BL::RegionView3D b_rv3d, int width, int height, BoundBox2D *view_box, BoundBox2D *cam_box) { BL::RenderSettings r = b_scene.render(); - - if(!r.use_border()) - return; - - /* camera view? */ - if(!(b_rv3d && b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_CAMERA)) - return; - - BL::Object b_ob = (b_v3d.lock_camera_and_layers())? b_scene.camera(): b_v3d.camera(); - - if(!b_ob) - return; - - bcam->border_left = r.border_min_x(); - bcam->border_right = r.border_max_x(); - bcam->border_bottom = r.border_min_y(); - bcam->border_top = r.border_max_y(); - - float cam_left, cam_right, cam_bottom, cam_top; - float view_left, view_right, view_bottom, view_top; + BoundBox2D cam, view; float view_aspect, cam_aspect, sensor_size; /* get viewport viewplane */ @@ -453,12 +445,7 @@ static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::Sp blender_camera_from_view(&view_bcam, b_scene, b_v3d, b_rv3d, width, height, true); blender_camera_viewplane(&view_bcam, width, height, - &view_left, &view_right, &view_bottom, &view_top, &view_aspect, &sensor_size); - - view_left /= view_aspect; - view_right /= view_aspect; - view_bottom /= view_aspect; - view_top /= view_aspect; + &view, &view_aspect, &sensor_size); /* get camera viewplane */ BlenderCamera cam_bcam; @@ -469,29 +456,58 @@ static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::Sp height = (int)(r.resolution_y()*r.resolution_percentage()/100); blender_camera_viewplane(&cam_bcam, width, height, - &cam_left, &cam_right, &cam_bottom, &cam_top, &cam_aspect, &sensor_size); + &cam, &cam_aspect, &sensor_size); + + /* return */ + *view_box = view * (1.0f/view_aspect); + *cam_box = cam * (1.0f/cam_aspect); +} + +static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::SpaceView3D b_v3d, + BL::RegionView3D b_rv3d, int width, int height) +{ + BL::RenderSettings r = b_scene.render(); + bool is_camera_view; - cam_left /= cam_aspect; - cam_right /= cam_aspect; - cam_bottom /= cam_aspect; - cam_top /= cam_aspect; + /* camera view? */ + is_camera_view = b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_CAMERA; + + if(!is_camera_view) { + /* for non-camera view check whether render border is enabled for viewport + * and if so use border from 3d viewport + * assume viewport has got correctly clamped border already + */ + if(b_v3d.use_render_border()) { + bcam->border.left = b_v3d.render_border_min_x(); + bcam->border.right = b_v3d.render_border_max_x(); + bcam->border.bottom = b_v3d.render_border_min_y(); + bcam->border.top = b_v3d.render_border_max_y(); + + return; + } + } + else if(!r.use_border()) + return; + + BL::Object b_ob = (b_v3d.lock_camera_and_layers())? b_scene.camera(): b_v3d.camera(); + + if(!b_ob) + return; + + bcam->border.left = r.border_min_x(); + bcam->border.right = r.border_max_x(); + bcam->border.bottom = r.border_min_y(); + bcam->border.top = r.border_max_y(); + + /* determine camera viewport subset */ + BoundBox2D view_box, cam_box; + + blender_camera_view_subset(b_scene, b_ob, b_v3d, b_rv3d, width, height, + &view_box, &cam_box); /* determine viewport subset matching camera border */ - float tmp_left = ((cam_left - view_left) / (view_right - view_left)); - float tmp_right = ((cam_right - view_left) / (view_right - view_left)); - float tmp_bottom = ((cam_bottom - view_bottom) / (view_top - view_bottom)); - float tmp_top = ((cam_top - view_bottom) / (view_top - view_bottom)); - - bcam->border_left = tmp_left + bcam->border_left*(tmp_right - tmp_left); - bcam->border_right = tmp_left + bcam->border_right*(tmp_right - tmp_left); - bcam->border_bottom = tmp_bottom + bcam->border_bottom*(tmp_top - tmp_bottom); - bcam->border_top = tmp_bottom + bcam->border_top*(tmp_top - tmp_bottom); - - /* clamp */ - bcam->border_left = clamp(bcam->border_left, 0.0f, 1.0f); - bcam->border_right = clamp(bcam->border_right, 0.0f, 1.0f); - bcam->border_bottom = clamp(bcam->border_bottom, 0.0f, 1.0f); - bcam->border_top = clamp(bcam->border_top, 0.0f, 1.0f); + cam_box = cam_box.make_relative_to(view_box); + bcam->border = cam_box.subset(bcam->border).clamp(); } void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height) @@ -504,19 +520,25 @@ void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int blender_camera_sync(scene->camera, &bcam, width, height); } -BufferParams BlenderSync::get_buffer_params(BL::Scene b_scene, Camera *cam, int width, int height) +BufferParams BlenderSync::get_buffer_params(BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, Camera *cam, int width, int height) { BufferParams params; + bool use_border = false; params.full_width = width; params.full_height = height; - if(b_scene.render().use_border()) { + if(b_v3d && b_rv3d && b_rv3d.view_perspective() != BL::RegionView3D::view_perspective_CAMERA) + use_border = b_v3d.use_render_border(); + else + use_border = b_scene.render().use_border(); + + if(use_border) { /* border render */ - params.full_x = cam->border_left*width; - params.full_y = cam->border_bottom*height; - params.width = (int)(cam->border_right*width) - params.full_x; - params.height = (int)(cam->border_top*height) - params.full_y; + params.full_x = cam->border.left*width; + params.full_y = cam->border.bottom*height; + params.width = (int)(cam->border.right*width) - params.full_x; + params.height = (int)(cam->border.top*height) - params.full_y; /* survive in case border goes out of view or becomes too small */ params.width = max(params.width, 1); diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 9764f24a893..c9748756d43 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -16,6 +16,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + #include "mesh.h" #include "object.h" #include "scene.h" @@ -29,9 +30,172 @@ #include "util_foreach.h" +#include "mikktspace.h" + CCL_NAMESPACE_BEGIN -/* Find/Add */ +/* Tangent Space */ + +struct MikkUserData { + MikkUserData(const BL::Mesh mesh_, const BL::MeshTextureFaceLayer layer_, int num_faces_) + : mesh(mesh_), layer(layer_), num_faces(num_faces_) + { + tangent.resize(num_faces*4); + } + + BL::Mesh mesh; + BL::MeshTextureFaceLayer layer; + int num_faces; + vector<float4> tangent; +}; + +static int mikk_get_num_faces(const SMikkTSpaceContext *context) +{ + MikkUserData *userdata = (MikkUserData*)context->m_pUserData; + return userdata->num_faces; +} + +static int mikk_get_num_verts_of_face(const SMikkTSpaceContext *context, const int face_num) +{ + MikkUserData *userdata = (MikkUserData*)context->m_pUserData; + BL::MeshTessFace f = userdata->mesh.tessfaces[face_num]; + int4 vi = get_int4(f.vertices_raw()); + + return (vi[3] == 0)? 3: 4; +} + +static void mikk_get_position(const SMikkTSpaceContext *context, float P[3], const int face_num, const int vert_num) +{ + MikkUserData *userdata = (MikkUserData*)context->m_pUserData; + BL::MeshTessFace f = userdata->mesh.tessfaces[face_num]; + int4 vi = get_int4(f.vertices_raw()); + BL::MeshVertex v = userdata->mesh.vertices[vi[vert_num]]; + float3 vP = get_float3(v.co()); + + P[0] = vP.x; + P[1] = vP.y; + P[2] = vP.z; +} + +static void mikk_get_texture_coordinate(const SMikkTSpaceContext *context, float uv[2], const int face_num, const int vert_num) +{ + MikkUserData *userdata = (MikkUserData*)context->m_pUserData; + BL::MeshTextureFace tf = userdata->layer.data[face_num]; + float3 tfuv; + + if(vert_num == 0) + tfuv = get_float3(tf.uv1()); + else if(vert_num == 1) + tfuv = get_float3(tf.uv2()); + else if(vert_num == 2) + tfuv = get_float3(tf.uv3()); + else + tfuv = get_float3(tf.uv4()); + + uv[0] = tfuv.x; + uv[1] = tfuv.y; +} + +static void mikk_get_normal(const SMikkTSpaceContext *context, float N[3], const int face_num, const int vert_num) +{ + MikkUserData *userdata = (MikkUserData*)context->m_pUserData; + BL::MeshTessFace f = userdata->mesh.tessfaces[face_num]; + int4 vi = get_int4(f.vertices_raw()); + BL::MeshVertex v = userdata->mesh.vertices[vi[vert_num]]; + float3 vN = get_float3(v.normal()); + + N[0] = vN.x; + N[1] = vN.y; + N[2] = vN.z; +} + +static void mikk_set_tangent_space(const SMikkTSpaceContext *context, const float T[], const float sign, const int face, const int vert) +{ + MikkUserData *userdata = (MikkUserData*)context->m_pUserData; + + userdata->tangent[face*4 + vert] = make_float4(T[0], T[1], T[2], sign); +} + +static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_layer, Mesh *mesh, vector<int>& nverts, bool need_sign, bool active_render) +{ + /* setup userdata */ + MikkUserData userdata(b_mesh, b_layer, nverts.size()); + + /* setup interface */ + SMikkTSpaceInterface sm_interface; + memset(&sm_interface, 0, sizeof(sm_interface)); + sm_interface.m_getNumFaces = mikk_get_num_faces; + sm_interface.m_getNumVerticesOfFace = mikk_get_num_verts_of_face; + sm_interface.m_getPosition = mikk_get_position; + sm_interface.m_getTexCoord = mikk_get_texture_coordinate; + sm_interface.m_getNormal = mikk_get_normal; + sm_interface.m_setTSpaceBasic = mikk_set_tangent_space; + + /* setup context */ + SMikkTSpaceContext context; + memset(&context, 0, sizeof(context)); + context.m_pUserData = &userdata; + context.m_pInterface = &sm_interface; + + /* compute tangents */ + genTangSpaceDefault(&context); + + /* create tangent attributes */ + Attribute *attr; + ustring name = ustring((string(b_layer.name().c_str()) + ".tangent").c_str()); + + if(active_render) + attr = mesh->attributes.add(ATTR_STD_UV_TANGENT, name); + else + attr = mesh->attributes.add(name, TypeDesc::TypeVector, Attribute::CORNER); + + float3 *tangent = attr->data_float3(); + + /* create bitangent sign attribute */ + float *tangent_sign = NULL; + + if(need_sign) { + Attribute *attr_sign; + ustring name_sign = ustring((string(b_layer.name().c_str()) + ".tangent_sign").c_str()); + + if(active_render) + attr_sign = mesh->attributes.add(ATTR_STD_UV_TANGENT_SIGN, name_sign); + else + attr_sign = mesh->attributes.add(name_sign, TypeDesc::TypeFloat, Attribute::CORNER); + + tangent_sign = attr_sign->data_float(); + } + + for(int i = 0; i < nverts.size(); i++) { + tangent[0] = float4_to_float3(userdata.tangent[i*4 + 0]); + tangent[1] = float4_to_float3(userdata.tangent[i*4 + 1]); + tangent[2] = float4_to_float3(userdata.tangent[i*4 + 2]); + tangent += 3; + + if(tangent_sign) { + tangent_sign[0] = userdata.tangent[i*4 + 0].w; + tangent_sign[1] = userdata.tangent[i*4 + 1].w; + tangent_sign[2] = userdata.tangent[i*4 + 2].w; + tangent_sign += 3; + } + + if(nverts[i] == 4) { + tangent[0] = float4_to_float3(userdata.tangent[i*4 + 0]); + tangent[1] = float4_to_float3(userdata.tangent[i*4 + 2]); + tangent[2] = float4_to_float3(userdata.tangent[i*4 + 3]); + tangent += 3; + + if(tangent_sign) { + tangent_sign[0] = userdata.tangent[i*4 + 0].w; + tangent_sign[1] = userdata.tangent[i*4 + 2].w; + tangent_sign[2] = userdata.tangent[i*4 + 3].w; + tangent_sign += 3; + } + } + } +} + +/* Create Mesh */ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<uint>& used_shaders) { @@ -67,27 +231,6 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< nverts.push_back(n); } - /* create generated coordinates. todo: we should actually get the orco - * coordinates from modifiers, for now we use texspace loc/size which - * is available in the api. */ - if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) { - Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED); - float3 loc = get_float3(b_mesh.texspace_location()); - float3 size = get_float3(b_mesh.texspace_size()); - - if(size.x != 0.0f) size.x = 0.5f/size.x; - if(size.y != 0.0f) size.y = 0.5f/size.y; - if(size.z != 0.0f) size.z = 0.5f/size.z; - - loc = loc*size - make_float3(0.5f, 0.5f, 0.5f); - - float3 *fdata = attr->data_float3(); - size_t i = 0; - - for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v) - fdata[i++] = get_float3(v->co())*size - loc; - } - /* create vertex color attributes */ { BL::Mesh::tessface_vertex_colors_iterator l; @@ -125,38 +268,72 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< BL::Mesh::tessface_uv_textures_iterator l; for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) { - AttributeStandard std = (l->active_render())? ATTR_STD_UV: ATTR_STD_NONE; + bool active_render = l->active_render(); + AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE; ustring name = ustring(l->name().c_str()); - if(!(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std))) - continue; - - Attribute *attr; - - if(l->active_render()) - attr = mesh->attributes.add(std, name); - else - attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER); + /* UV map */ + if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) { + Attribute *attr; - BL::MeshTextureFaceLayer::data_iterator t; - float3 *fdata = attr->data_float3(); - size_t i = 0; + if(active_render) + attr = mesh->attributes.add(std, name); + else + attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER); - for(l->data.begin(t); t != l->data.end(); ++t, ++i) { - fdata[0] = get_float3(t->uv1()); - fdata[1] = get_float3(t->uv2()); - fdata[2] = get_float3(t->uv3()); - fdata += 3; + BL::MeshTextureFaceLayer::data_iterator t; + float3 *fdata = attr->data_float3(); + size_t i = 0; - if(nverts[i] == 4) { + for(l->data.begin(t); t != l->data.end(); ++t, ++i) { fdata[0] = get_float3(t->uv1()); - fdata[1] = get_float3(t->uv3()); - fdata[2] = get_float3(t->uv4()); + fdata[1] = get_float3(t->uv2()); + fdata[2] = get_float3(t->uv3()); fdata += 3; + + if(nverts[i] == 4) { + fdata[0] = get_float3(t->uv1()); + fdata[1] = get_float3(t->uv3()); + fdata[2] = get_float3(t->uv4()); + fdata += 3; + } } } + + /* UV tangent */ + std = (active_render)? ATTR_STD_UV_TANGENT: ATTR_STD_NONE; + name = ustring((string(l->name().c_str()) + ".tangent").c_str()); + + if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) { + std = (active_render)? ATTR_STD_UV_TANGENT_SIGN: ATTR_STD_NONE; + name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str()); + bool need_sign = (mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)); + + mikk_compute_tangents(b_mesh, *l, mesh, nverts, need_sign, active_render); + } } } + + /* create generated coordinates. todo: we should actually get the orco + * coordinates from modifiers, for now we use texspace loc/size which + * is available in the api. */ + if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) { + Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED); + float3 loc = get_float3(b_mesh.texspace_location()); + float3 size = get_float3(b_mesh.texspace_size()); + + if(size.x != 0.0f) size.x = 0.5f/size.x; + if(size.y != 0.0f) size.y = 0.5f/size.y; + if(size.z != 0.0f) size.z = 0.5f/size.z; + + loc = loc*size - make_float3(0.5f, 0.5f, 0.5f); + + float3 *generated = attr->data_float3(); + size_t i = 0; + + for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v) + generated[i++] = get_float3(v->co())*size - loc; + } } static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, const vector<uint>& used_shaders) @@ -270,7 +447,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated) create_mesh(scene, mesh, b_mesh, used_shaders); /* free derived mesh */ - object_remove_mesh(b_data, b_mesh); + b_data.meshes.remove(b_mesh); } /* displacement method */ @@ -328,7 +505,7 @@ void BlenderSync::sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion) mesh->attributes.remove(std); /* free derived mesh */ - object_remove_mesh(b_data, b_mesh); + b_data.meshes.remove(b_mesh); } } diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 27301026d35..e8fa5c0ff3d 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -17,12 +17,14 @@ */ #include "camera.h" +#include "integrator.h" #include "graph.h" #include "light.h" #include "mesh.h" #include "object.h" #include "scene.h" #include "nodes.h" +#include "particles.h" #include "shader.h" #include "blender_sync.h" @@ -84,11 +86,11 @@ static uint object_ray_visibility(BL::Object b_ob) /* Light */ -void BlenderSync::sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm) +void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm) { /* test if we need to sync */ Light *light; - ObjectKey key(b_parent, b_index, b_ob); + ObjectKey key(b_parent, persistent_id, b_ob); if(!light_map.sync(&light, b_ob, b_parent, key)) return; @@ -194,23 +196,24 @@ void BlenderSync::sync_background_light() /* Object */ -void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject b_dupli_ob, Transform& tfm, uint layer_flag, int motion, int particle_id) +Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_ob, Transform& tfm, uint layer_flag, int motion) { BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent); /* light is handled separately */ if(object_is_light(b_ob)) { if(!motion) - sync_light(b_parent, b_index, b_ob, tfm); - return; + sync_light(b_parent, persistent_id, b_ob, tfm); + + return NULL; } /* only interested in object that we can create meshes from */ if(!object_is_mesh(b_ob)) - return; + return NULL; /* key to lookup object */ - ObjectKey key(b_parent, b_index, b_ob); + ObjectKey key(b_parent, persistent_id, b_ob); Object *object; /* motion vector case */ @@ -227,10 +230,12 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject object->use_motion = true; } - sync_mesh_motion(b_ob, object->mesh, motion); + /* mesh deformation blur not supported yet */ + if(!scene->integrator->motion_blur) + sync_mesh_motion(b_ob, object->mesh, motion); } - return; + return object; } /* test if we need to sync */ @@ -244,13 +249,15 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject /* mesh sync */ object->mesh = sync_mesh(b_ob, object_updated); + /* sspecial case not tracked by object update flags */ if(use_holdout != object->use_holdout) { object->use_holdout = use_holdout; scene->object_manager->tag_update(scene); + object_updated = true; } - /* object sync */ - /* transform comparison should not be needed, but duplis don't work perfect + /* object sync + * transform comparison should not be needed, but duplis don't work perfect * in the depsgraph and may not signal changes, so this is a workaround */ if(object_updated || (object->mesh && object->mesh->need_update) || tfm != object->tfm) { object->name = b_ob.name().c_str(); @@ -260,7 +267,15 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject object->motion.post = tfm; object->use_motion = false; - object->random_id = hash_int_2d(hash_string(object->name.c_str()), b_index); + /* random number */ + object->random_id = hash_string(object->name.c_str()); + + if(persistent_id) { + for(int i = 0; i < OBJECT_PERSISTENT_ID_SIZE; i++) + object->random_id = hash_int_2d(object->random_id, persistent_id[i]); + } + else + object->random_id = hash_int_2d(object->random_id, 0); /* visibility flags for both parent */ object->visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL; @@ -269,6 +284,10 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject object->random_id ^= hash_int(hash_string(b_parent.name().c_str())); } + /* make holdout objects on excluded layer invisible for non-camera rays */ + if(use_holdout && (layer_flag & render_layer.exclude_layer)) + object->visibility &= ~(PATH_RAY_ALL - PATH_RAY_CAMERA); + /* camera flag is not actually used, instead is tested * against render layer flags */ if(object->visibility & PATH_RAY_CAMERA) { @@ -285,10 +304,10 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject object->dupli_uv = make_float2(0.0f, 0.0f); } - object->particle_id = particle_id; - object->tag_update(scene); } + + return object; } /* Object Loop */ @@ -304,12 +323,15 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) mesh_map.pre_sync(); object_map.pre_sync(); mesh_synced.clear(); + particle_system_map.pre_sync(); } /* object loop */ BL::Scene::objects_iterator b_ob; BL::Scene b_sce = b_scene; - int particle_offset = 1; /* first particle is dummy for regular, non-instanced objects */ + + /* global particle index counter */ + int particle_id = 1; bool cancel = false; @@ -322,45 +344,70 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) if(!hide) { progress.set_sync_status("Synchronizing object", (*b_ob).name()); - int num_particles = object_count_particles(*b_ob); - if(b_ob->is_duplicator()) { - hide = true; /* duplicators hidden by default */ + /* duplicators hidden by default */ + hide = true; /* dupli objects */ - object_create_duplilist(*b_ob, b_scene); + b_ob->dupli_list_create(b_scene, 2); BL::Object::dupli_list_iterator b_dup; - int b_index = 0; for(b_ob->dupli_list.begin(b_dup); b_dup != b_ob->dupli_list.end(); ++b_dup) { Transform tfm = get_transform(b_dup->matrix()); BL::Object b_dup_ob = b_dup->object(); bool dup_hide = (b_v3d)? b_dup_ob.hide(): b_dup_ob.hide_render(); + bool emitter_hide = false; + + if(b_dup_ob.is_duplicator()) { + /* duplicators hidden by default */ + emitter_hide = true; + + /* check if we should render or hide particle emitter */ + BL::Object::particle_systems_iterator b_psys; + for(b_dup_ob.particle_systems.begin(b_psys); b_psys != b_dup_ob.particle_systems.end(); ++b_psys) + if(b_psys->settings().use_render_emitter()) + emitter_hide = false; + } + + if(!(b_dup->hide() || dup_hide || emitter_hide)) { + /* the persistent_id allows us to match dupli objects + * between frames and updates */ + BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id = b_dup->persistent_id(); + + /* sync object and mesh or light data */ + Object *object = sync_object(*b_ob, persistent_id.data, *b_dup, tfm, ob_layer, motion); + + /* sync possible particle data, note particle_id + * starts counting at 1, first is dummy particle */ + if(!motion && object && sync_dupli_particle(*b_ob, *b_dup, object)) { + if(particle_id != object->particle_id) { + object->particle_id = particle_id; + scene->object_manager->tag_update(scene); + } + + particle_id++; + } - if(!(b_dup->hide() || dup_hide)) { - sync_object(*b_ob, b_index, *b_dup, tfm, ob_layer, motion, b_dup->particle_index() + particle_offset); } - - ++b_index; } - object_free_duplilist(*b_ob); + b_ob->dupli_list_clear(); } /* check if we should render or hide particle emitter */ BL::Object::particle_systems_iterator b_psys; - for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) + + for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) { if(b_psys->settings().use_render_emitter()) hide = false; + } if(!hide) { /* object itself */ Transform tfm = get_transform(b_ob->matrix_world()); - sync_object(*b_ob, 0, PointerRNA_NULL, tfm, ob_layer, motion, 0); + sync_object(*b_ob, NULL, PointerRNA_NULL, tfm, ob_layer, motion); } - - particle_offset += num_particles; } cancel = progress.get_cancel(); @@ -379,6 +426,8 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) scene->mesh_manager->tag_update(scene); if(object_map.post_sync()) scene->object_manager->tag_update(scene); + if(particle_system_map.post_sync()) + scene->particle_system_manager->tag_update(scene); mesh_synced.clear(); } } @@ -393,11 +442,13 @@ void BlenderSync::sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override) if(b_override) b_cam = b_override; + Camera prevcam = *(scene->camera); + /* go back and forth one frame */ int frame = b_scene.frame_current(); for(int motion = -1; motion <= 1; motion += 2) { - scene_frame_set(b_scene, frame + motion); + b_scene.frame_set(frame + motion, 0.0f); /* camera object */ if(b_cam) @@ -407,7 +458,11 @@ void BlenderSync::sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override) sync_objects(b_v3d, motion); } - scene_frame_set(b_scene, frame); + b_scene.frame_set(frame, 0.0f); + + /* tag camera for motion update */ + if(scene->camera->motion_modified(prevcam)) + scene->camera->tag_update(); } CCL_NAMESPACE_END diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp index f309960fc55..769cd9f532d 100644 --- a/intern/cycles/blender/blender_particles.cpp +++ b/intern/cycles/blender/blender_particles.cpp @@ -17,6 +17,7 @@ */ #include "mesh.h" +#include "object.h" #include "particles.h" #include "blender_sync.h" @@ -28,191 +29,57 @@ CCL_NAMESPACE_BEGIN /* Utilities */ +bool BlenderSync::sync_dupli_particle(BL::Object b_ob, BL::DupliObject b_dup, Object *object) +{ + /* test if this dupli was generated from a particle sytem */ + BL::ParticleSystem b_psys = b_dup.particle_system(); + if(!b_psys) + return false; -/* Particles Sync */ + /* test if we need particle data */ + if(!object->mesh->need_attribute(scene, ATTR_STD_PARTICLE)) + return false; -bool BlenderSync::psys_need_update(BL::ParticleSystem b_psys) -{ - /* Particle data is only needed for - * a) Billboard render mode if object's own material uses particle info - * b) object/group render mode if any dupli object's material uses particle info - * - * Note: Meshes have to be synced at this point! - */ - bool need_update = false; - - switch (b_psys.settings().render_type()) { - /* XXX not implemented yet! - * billboards/strands would become part of the mesh data (?), - * so the mesh attributes would store whether particle info is required. - */ - #if 0 - case BL::ParticleSettings::render_type_BILLBOARD: - case BL::ParticleSettings::render_type_PATH: { /* for strand rendering */ - BL::ID key = (BKE_object_is_modified(b_ob))? b_ob: b_ob.data(); - Mesh *mesh = mesh_map.find(key); - if (mesh) { - need_update |= mesh->need_attribute(scene, ATTR_STD_PARTICLE) && mesh->need_update; - } - break; - } - #endif - - case BL::ParticleSettings::render_type_OBJECT: { - BL::Object b_dupli_ob = b_psys.settings().dupli_object(); - if (b_dupli_ob) { - BL::ID key = (BKE_object_is_modified(b_dupli_ob))? b_dupli_ob: b_dupli_ob.data(); - Mesh *mesh = mesh_map.find(key); - if (mesh) { - need_update |= mesh->need_attribute(scene, ATTR_STD_PARTICLE) && mesh->need_update; - } - } - break; - } - - case BL::ParticleSettings::render_type_GROUP: { - BL::Group b_dupli_group = b_psys.settings().dupli_group(); - if (b_dupli_group) { - BL::Group::objects_iterator b_gob; - for (b_dupli_group.objects.begin(b_gob); b_gob != b_dupli_group.objects.end(); ++b_gob) { - BL::ID key = (BKE_object_is_modified(*b_gob))? *b_gob: b_gob->data(); - Mesh *mesh = mesh_map.find(key); - if (mesh) { - need_update |= mesh->need_attribute(scene, ATTR_STD_PARTICLE) && mesh->need_update; - } - } - } - break; - } - - default: - /* avoid compiler warning */ - break; - } - - return need_update; -} + /* don't handle child particles yet */ + BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id = b_dup.persistent_id(); -static bool use_particle_system(BL::ParticleSystem b_psys) -{ - /* only use duplicator particles? disabled particle info for - * halo and billboard to reduce particle count. - * Probably not necessary since particles don't contain a huge amount - * of data compared to other textures. - */ - #if 0 - int render_type = b_psys->settings().render_type(); - return (render_type == BL::ParticleSettings::render_type_OBJECT - || render_type == BL::ParticleSettings::render_type_GROUP); - #endif - - return true; -} + if(persistent_id[0] >= b_psys.particles.length()) + return false; -static bool use_particle(BL::Particle b_pa) -{ - return b_pa.is_exist() && b_pa.is_visible() && - (b_pa.alive_state()==BL::Particle::alive_state_ALIVE || b_pa.alive_state()==BL::Particle::alive_state_DYING); -} + /* find particle system */ + ParticleSystemKey key(b_ob, persistent_id); + ParticleSystem *psys; -static int psys_count_particles(BL::ParticleSystem b_psys) -{ - int tot = 0; - BL::ParticleSystem::particles_iterator b_pa; - for(b_psys.particles.begin(b_pa); b_pa != b_psys.particles.end(); ++b_pa) { - if(use_particle(*b_pa)) - ++tot; - } - return tot; -} + bool first_use = !particle_system_map.is_used(key); + bool need_update = particle_system_map.sync(&psys, b_ob, b_dup.object(), key); -int BlenderSync::object_count_particles(BL::Object b_ob) -{ - int tot = 0; - BL::Object::particle_systems_iterator b_psys; - for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) { - if (use_particle_system(*b_psys)) - tot += psys_count_particles(*b_psys); - } - return tot; -} + /* no update needed? */ + if(!need_update && !object->mesh->need_update && !scene->object_manager->need_update) + return true; -void BlenderSync::sync_particles(BL::Object b_ob, BL::ParticleSystem b_psys) -{ - /* depending on settings the psys may not even be rendered */ - if (!use_particle_system(b_psys)) - return; - - /* key to lookup particle system */ - ParticleSystemKey key(b_ob, b_psys); - ParticleSystem *psys; - - /* test if we need to sync */ - bool object_updated = false; - - if(particle_system_map.sync(&psys, b_ob, b_ob, key)) - object_updated = true; - - bool need_update = psys_need_update(b_psys); - - if (object_updated || need_update) { - int tot = psys_count_particles(b_psys); + /* first time used in this sync loop? clear and tag update */ + if(first_use) { psys->particles.clear(); - psys->particles.reserve(tot); - - int index = 0; - BL::ParticleSystem::particles_iterator b_pa; - for(b_psys.particles.begin(b_pa); b_pa != b_psys.particles.end(); ++b_pa) { - if(use_particle(*b_pa)) { - Particle pa; - - pa.index = index; - pa.age = b_scene.frame_current() - b_pa->birth_time(); - pa.lifetime = b_pa->lifetime(); - pa.location = get_float3(b_pa->location()); - pa.rotation = get_float4(b_pa->rotation()); - pa.size = b_pa->size(); - pa.velocity = get_float3(b_pa->velocity()); - pa.angular_velocity = get_float3(b_pa->angular_velocity()); - - psys->particles.push_back(pa); - } - - ++index; - } - psys->tag_update(scene); } -} -void BlenderSync::sync_particle_systems() -{ - /* layer data */ - uint scene_layer = render_layer.scene_layer; + /* add particle */ + BL::Particle b_pa = b_psys.particles[persistent_id[0]]; + Particle pa; - particle_system_map.pre_sync(); - - /* object loop */ - BL::Scene::objects_iterator b_ob; - BL::Scene b_sce = b_scene; - - for(; b_sce; b_sce = b_sce.background_set()) { - for(b_sce.objects.begin(b_ob); b_ob != b_sce.objects.end(); ++b_ob) { - bool hide = (render_layer.use_viewport_visibility)? b_ob->hide(): b_ob->hide_render(); - uint ob_layer = get_layer(b_ob->layers(), b_ob->layers_local_view(), render_layer.use_localview, object_is_light(*b_ob)); - hide = hide || !(ob_layer & scene_layer); - - if(!hide) { - BL::Object::particle_systems_iterator b_psys; - for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) - sync_particles(*b_ob, *b_psys); - } - } - } - - /* handle removed data and modified pointers */ - if(particle_system_map.post_sync()) - scene->particle_system_manager->tag_update(scene); + pa.index = persistent_id[0]; + pa.age = b_scene.frame_current() - b_pa.birth_time(); + pa.lifetime = b_pa.lifetime(); + pa.location = get_float3(b_pa.location()); + pa.rotation = get_float4(b_pa.rotation()); + pa.size = b_pa.size(); + pa.velocity = get_float3(b_pa.velocity()); + pa.angular_velocity = get_float3(b_pa.angular_velocity()); + + psys->particles.push_back(pa); + + /* return that this object has particle data */ + return true; } CCL_NAMESPACE_END diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index d9220b76835..d164920ceff 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -24,9 +24,17 @@ #include "blender_session.h" #include "util_foreach.h" +#include "util_md5.h" #include "util_opengl.h" #include "util_path.h" +#ifdef WITH_OSL +#include "osl.h" + +#include <OSL/oslquery.h> +#include <OSL/oslconfig.h> +#endif + CCL_NAMESPACE_BEGIN static PyObject *init_func(PyObject *self, PyObject *args) @@ -138,6 +146,32 @@ static PyObject *draw_func(PyObject *self, PyObject *args) Py_RETURN_NONE; } +static PyObject *reset_func(PyObject *self, PyObject *args) +{ + PyObject *pysession, *pydata, *pyscene; + + if(!PyArg_ParseTuple(args, "OOO", &pysession, &pydata, &pyscene)) + return NULL; + + BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession); + + PointerRNA dataptr; + RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pydata), &dataptr); + BL::BlendData b_data(dataptr); + + PointerRNA sceneptr; + RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pyscene), &sceneptr); + BL::Scene b_scene(sceneptr); + + Py_BEGIN_ALLOW_THREADS + + session->reset_session(b_data, b_scene); + + Py_END_ALLOW_THREADS + + Py_RETURN_NONE; +} + static PyObject *sync_func(PyObject *self, PyObject *value) { Py_BEGIN_ALLOW_THREADS @@ -163,6 +197,182 @@ static PyObject *available_devices_func(PyObject *self, PyObject *args) return ret; } +#ifdef WITH_OSL +static PyObject *osl_update_node_func(PyObject *self, PyObject *args) +{ + PyObject *pynodegroup, *pynode; + const char *filepath = NULL; + + if(!PyArg_ParseTuple(args, "OOs", &pynodegroup, &pynode, &filepath)) + return NULL; + + /* RNA */ + PointerRNA nodeptr; + RNA_pointer_create((ID*)PyLong_AsVoidPtr(pynodegroup), &RNA_ShaderNodeScript, (void*)PyLong_AsVoidPtr(pynode), &nodeptr); + BL::ShaderNodeScript b_node(nodeptr); + + /* update bytecode hash */ + string bytecode = b_node.bytecode(); + + if(!bytecode.empty()) { + MD5Hash md5; + md5.append((const uint8_t*)bytecode.c_str(), bytecode.size()); + b_node.bytecode_hash(md5.get_hex().c_str()); + } + else + b_node.bytecode_hash(""); + + /* query from file path */ + OSL::OSLQuery query; + + if(!OSLShaderManager::osl_query(query, filepath)) + Py_RETURN_FALSE; + + /* add new sockets from parameters */ + set<void*> used_sockets; + + for(int i = 0; i < query.nparams(); i++) { + const OSL::OSLQuery::Parameter *param = query.getparam(i); + + /* skip unsupported types */ + if(param->varlenarray || param->isstruct || param->type.arraylen > 1) + continue; + + /* determine socket type */ + BL::NodeSocket::type_enum socket_type; + float default_float4[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + float default_float = 0.0f; + int default_int = 0; + std::string default_string = ""; + + if(param->isclosure) { + socket_type = BL::NodeSocket::type_SHADER; + } + else if(param->type.vecsemantics == TypeDesc::COLOR) { + socket_type = BL::NodeSocket::type_RGBA; + + if(param->validdefault) { + default_float4[0] = param->fdefault[0]; + default_float4[1] = param->fdefault[1]; + default_float4[2] = param->fdefault[2]; + } + } + else if(param->type.vecsemantics == TypeDesc::POINT || + param->type.vecsemantics == TypeDesc::VECTOR || + param->type.vecsemantics == TypeDesc::NORMAL) { + socket_type = BL::NodeSocket::type_VECTOR; + + if(param->validdefault) { + default_float4[0] = param->fdefault[0]; + default_float4[1] = param->fdefault[1]; + default_float4[2] = param->fdefault[2]; + } + } + else if(param->type.aggregate == TypeDesc::SCALAR) { + if(param->type.basetype == TypeDesc::INT) { + socket_type = BL::NodeSocket::type_INT; + if(param->validdefault) + default_int = param->idefault[0]; + } + else if(param->type.basetype == TypeDesc::FLOAT) { + socket_type = BL::NodeSocket::type_VALUE; + if(param->validdefault) + default_float = param->fdefault[0]; + } + else if(param->type.basetype == TypeDesc::STRING) { + socket_type = BL::NodeSocket::type_STRING; + if(param->validdefault) + default_string = param->sdefault[0]; + } + else + continue; + } + else + continue; + + /* find socket socket */ + BL::NodeSocket b_sock = b_node.find_socket(param->name.c_str(), param->isoutput); + + /* remove if type no longer matches */ + if(b_sock && b_sock.type() != socket_type) { + b_node.remove_socket(b_sock); + b_sock = BL::NodeSocket(PointerRNA_NULL); + } + + /* create new socket */ + if(!b_sock) { + b_sock = b_node.add_socket(param->name.c_str(), socket_type, param->isoutput); + + /* set default value */ + if(socket_type == BL::NodeSocket::type_VALUE) { + BL::NodeSocketFloatNone b_float_sock(b_sock.ptr); + b_float_sock.default_value(default_float); + } + else if(socket_type == BL::NodeSocket::type_INT) { + BL::NodeSocketIntNone b_int_sock(b_sock.ptr); + b_int_sock.default_value(default_int); + } + else if(socket_type == BL::NodeSocket::type_RGBA) { + BL::NodeSocketRGBA b_rgba_sock(b_sock.ptr); + b_rgba_sock.default_value(default_float4); + } + else if(socket_type == BL::NodeSocket::type_VECTOR) { + BL::NodeSocketVectorNone b_vector_sock(b_sock.ptr); + b_vector_sock.default_value(default_float4); + } + else if(socket_type == BL::NodeSocket::type_STRING) { + BL::NodeSocketStringNone b_string_sock(b_sock.ptr); + b_string_sock.default_value(default_string); + } + } + + used_sockets.insert(b_sock.ptr.data); + } + + /* remove unused parameters */ + bool removed; + + do { + BL::Node::inputs_iterator b_input; + BL::Node::outputs_iterator b_output; + + removed = false; + + for (b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) { + if(used_sockets.find(b_input->ptr.data) == used_sockets.end()) { + b_node.remove_socket(*b_input); + removed = true; + break; + } + } + + for (b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) { + if(used_sockets.find(b_output->ptr.data) == used_sockets.end()) { + b_node.remove_socket(*b_output); + removed = true; + break; + } + } + } while(removed); + + Py_RETURN_TRUE; +} + +static PyObject *osl_compile_func(PyObject *self, PyObject *args) +{ + const char *inputfile = NULL, *outputfile = NULL; + + if(!PyArg_ParseTuple(args, "ss", &inputfile, &outputfile)) + return NULL; + + /* return */ + if(!OSLShaderManager::osl_compile(inputfile, outputfile)) + Py_RETURN_FALSE; + + Py_RETURN_TRUE; +} +#endif + static PyMethodDef methods[] = { {"init", init_func, METH_VARARGS, ""}, {"create", create_func, METH_VARARGS, ""}, @@ -170,6 +380,11 @@ static PyMethodDef methods[] = { {"render", render_func, METH_O, ""}, {"draw", draw_func, METH_VARARGS, ""}, {"sync", sync_func, METH_O, ""}, + {"reset", reset_func, METH_VARARGS, ""}, +#ifdef WITH_OSL + {"osl_update_node", osl_update_node_func, METH_VARARGS, ""}, + {"osl_compile", osl_compile_func, METH_VARARGS, ""}, +#endif {"available_devices", available_devices_func, METH_NOARGS, ""}, {NULL, NULL, 0, NULL}, }; @@ -203,14 +418,23 @@ static CCLDeviceInfo *compute_device_list(DeviceType type) if(info.type == type || (info.type == DEVICE_MULTI && info.multi_devices[0].type == type)) { - CCLDeviceInfo cinfo = {info.id.c_str(), info.description.c_str(), i++}; + CCLDeviceInfo cinfo; + + strncpy(cinfo.identifier, info.id.c_str(), sizeof(cinfo.identifier)); + cinfo.identifier[info.id.length()] = '\0'; + + strncpy(cinfo.name, info.description.c_str(), sizeof(cinfo.name)); + cinfo.name[info.description.length()] = '\0'; + + cinfo.value = i++; + device_list.push_back(cinfo); } } /* null terminate */ if(!device_list.empty()) { - CCLDeviceInfo cinfo = {NULL, NULL, 0}; + CCLDeviceInfo cinfo = {"", "", 0}; device_list.push_back(cinfo); } } diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 7b80c520e72..ad43c39469c 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -105,13 +105,57 @@ void BlenderSession::create_session() sync->sync_camera(b_engine.camera_override(), width, height); /* set buffer parameters */ - BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, width, height); + BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_v3d, b_rv3d, scene->camera, width, height); + session->reset(buffer_params, session_params.samples); +} + +void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_) +{ + b_data = b_data_; + b_scene = b_scene_; + + SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background); + SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background); + + width = b_engine.resolution_x(); + height = b_engine.resolution_y(); + + if(scene->params.modified(scene_params) || + session->params.modified(session_params)) + { + /* if scene or session parameters changed, it's easier to simply re-create + * them rather than trying to distinguish which settings need to be updated + */ + + delete session; + + create_session(); + + return; + } + + session->progress.reset(); + scene->reset(); + + /* peak memory usage should show current render peak, not peak for all renders + * made by this render session + */ + session->stats.mem_peak = session->stats.mem_used; + + /* sync object should be re-created */ + sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress); + sync->sync_data(b_v3d, b_engine.camera_override()); + sync->sync_camera(b_engine.camera_override(), width, height); + + BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, PointerRNA_NULL, PointerRNA_NULL, scene->camera, width, height); session->reset(buffer_params, session_params.samples); } void BlenderSession::free_session() { - delete sync; + if(sync) + delete sync; + delete session; } @@ -178,15 +222,12 @@ static PassType get_pass_type(BL::RenderPass b_pass) static BL::RenderResult begin_render_result(BL::RenderEngine b_engine, int x, int y, int w, int h, const char *layername) { - RenderResult *rrp = RE_engine_begin_result((RenderEngine*)b_engine.ptr.data, x, y, w, h, layername); - PointerRNA rrptr; - RNA_pointer_create(NULL, &RNA_RenderResult, rrp, &rrptr); - return BL::RenderResult(rrptr); + return b_engine.begin_result(x, y, w, h, layername); } static void end_render_result(BL::RenderEngine b_engine, BL::RenderResult b_rr, bool cancel = false) { - RE_engine_end_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data, (int)cancel); + b_engine.end_result(b_rr, (int)cancel); } void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_update_only) @@ -239,7 +280,7 @@ void BlenderSession::render() /* get buffer parameters */ SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background); - BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, width, height); + BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_v3d, b_rv3d, scene->camera, width, height); /* render each layer */ BL::RenderSettings r = b_scene.render(); @@ -307,6 +348,15 @@ void BlenderSession::render() /* clear callback */ session->write_render_tile_cb = NULL; session->update_render_tile_cb = NULL; + + /* free all memory used (host and device), so we wouldn't leave render + * engine with extra memory allocated + */ + + session->device_free(); + + delete sync; + sync = NULL; } void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile, bool do_update_only) @@ -335,16 +385,16 @@ void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::Re /* copy pixels */ if(buffers->get_pass_rect(pass_type, exposure, rtile.sample, components, &pixels[0])) - rna_RenderPass_rect_set(&b_pass.ptr, &pixels[0]); + b_pass.rect(&pixels[0]); } } /* copy combined pass */ if(buffers->get_pass_rect(PASS_COMBINED, exposure, rtile.sample, 4, &pixels[0])) - rna_RenderLayer_rect_set(&b_rlay.ptr, &pixels[0]); + b_rlay.rect(&pixels[0]); /* tag result as updated */ - RE_engine_update_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data); + b_engine.update_result(b_rr); } void BlenderSession::write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile) @@ -399,7 +449,7 @@ void BlenderSession::synchronize() /* reset if needed */ if(scene->need_reset()) { - BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, width, height); + BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_v3d, b_rv3d, scene->camera, width, height); session->reset(buffer_params, session_params.samples); } } @@ -437,7 +487,7 @@ bool BlenderSession::draw(int w, int h) /* reset if requested */ if(reset) { SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background); - BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, w, h); + BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_v3d, b_rv3d, scene->camera, w, h); session->reset(buffer_params, session_params.samples); } @@ -447,7 +497,7 @@ bool BlenderSession::draw(int w, int h) update_status_progress(); /* draw */ - BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, width, height); + BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_v3d, b_rv3d, scene->camera, width, height); return !session->draw(buffer_params); } @@ -466,9 +516,12 @@ void BlenderSession::get_progress(float& progress, double& total_time) session->progress.get_tile(tile, total_time, tile_time); sample = session->progress.get_sample(); - samples_per_tile = session->tile_manager.state.num_samples; + samples_per_tile = session->params.samples; - progress = ((float)sample/(float)(tile_total * samples_per_tile)); + if(samples_per_tile) + progress = ((float)sample/(float)(tile_total * samples_per_tile)); + else + progress = 0.0; } void BlenderSession::update_status_progress() @@ -477,11 +530,15 @@ void BlenderSession::update_status_progress() float progress; double total_time; char time_str[128]; + float mem_used = (float)session->stats.mem_used / 1024.0f / 1024.0f; + float mem_peak = (float)session->stats.mem_peak / 1024.0f / 1024.0f; get_status(status, substatus); get_progress(progress, total_time); - timestatus = b_scene.name(); + timestatus = string_printf("Mem: %.2fM, Peak: %.2fM | ", mem_used, mem_peak); + + timestatus += b_scene.name(); if(b_rlay_name != "") timestatus += ", " + b_rlay_name; timestatus += " | "; @@ -493,11 +550,12 @@ void BlenderSession::update_status_progress() status += " | " + substatus; if(status != last_status) { - RE_engine_update_stats((RenderEngine*)b_engine.ptr.data, "", (timestatus + status).c_str()); + b_engine.update_stats("", (timestatus + status).c_str()); + b_engine.update_memory_stats(mem_used, mem_peak); last_status = status; } if(progress != last_progress) { - RE_engine_update_progress((RenderEngine*)b_engine.ptr.data, progress); + b_engine.update_progress(progress); last_progress = progress; } } @@ -505,7 +563,7 @@ void BlenderSession::update_status_progress() void BlenderSession::tag_update() { /* tell blender that we want to get another update callback */ - engine_tag_update((RenderEngine*)b_engine.ptr.data); + b_engine.tag_update(); } void BlenderSession::tag_redraw() @@ -517,13 +575,13 @@ void BlenderSession::tag_redraw() /* offline render, redraw if timeout passed */ if(time_dt() - last_redraw_time > 1.0) { - engine_tag_redraw((RenderEngine*)b_engine.ptr.data); + b_engine.tag_redraw(); last_redraw_time = time_dt(); } } else { /* tell blender that we want to redraw */ - engine_tag_redraw((RenderEngine*)b_engine.ptr.data); + b_engine.tag_redraw(); } } @@ -531,7 +589,7 @@ void BlenderSession::test_cancel() { /* test if we need to cancel rendering */ if(background) - if(RE_engine_test_break((RenderEngine*)b_engine.ptr.data)) + if(b_engine.test_break()) session->progress.set_cancel("Cancelled"); } diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index d52e0103bbf..7f3973ae873 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -46,6 +46,8 @@ public: void create_session(); void free_session(); + void reset_session(BL::BlendData b_data, BL::Scene b_scene); + /* offline render */ void render(); diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index b6d5cc623bb..63cf719d010 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -20,6 +20,7 @@ #include "graph.h" #include "light.h" #include "nodes.h" +#include "osl.h" #include "scene.h" #include "shader.h" @@ -43,6 +44,7 @@ void BlenderSync::find_shader(BL::ID id, vector<uint>& used_shaders, int default for(size_t i = 0; i < scene->shaders.size(); i++) { if(scene->shaders[i] == shader) { used_shaders.push_back(i); + scene->shaders[i]->tag_used(scene); break; } } @@ -80,22 +82,25 @@ static ShaderSocketType convert_socket_type(BL::NodeSocket::type_enum b_type) switch (b_type) { case BL::NodeSocket::type_VALUE: return SHADER_SOCKET_FLOAT; + case BL::NodeSocket::type_INT: + return SHADER_SOCKET_INT; case BL::NodeSocket::type_VECTOR: return SHADER_SOCKET_VECTOR; case BL::NodeSocket::type_RGBA: return SHADER_SOCKET_COLOR; case BL::NodeSocket::type_SHADER: return SHADER_SOCKET_CLOSURE; + case BL::NodeSocket::type_STRING: + return SHADER_SOCKET_STRING; case BL::NodeSocket::type_BOOLEAN: case BL::NodeSocket::type_MESH: - case BL::NodeSocket::type_INT: default: return SHADER_SOCKET_FLOAT; } } -static void set_default_value(ShaderInput *input, BL::NodeSocket sock) +static void set_default_value(ShaderInput *input, BL::NodeSocket sock, BL::BlendData b_data, BL::ID b_id) { /* copy values for non linked inputs */ switch(input->type) { @@ -104,6 +109,11 @@ static void set_default_value(ShaderInput *input, BL::NodeSocket sock) input->set(value_sock.default_value()); break; } + case SHADER_SOCKET_INT: { + BL::NodeSocketIntNone value_sock(sock); + input->set((float)value_sock.default_value()); + break; + } case SHADER_SOCKET_COLOR: { BL::NodeSocketRGBA rgba_sock(sock); input->set(get_float3(rgba_sock.default_value())); @@ -116,6 +126,11 @@ static void set_default_value(ShaderInput *input, BL::NodeSocket sock) input->set(get_float3(vec_sock.default_value())); break; } + case SHADER_SOCKET_STRING: { + BL::NodeSocketStringNone string_sock(sock); + input->set((ustring)blender_absolute_path(b_data, b_id, string_sock.default_value())); + break; + } case SHADER_SOCKET_CLOSURE: break; } @@ -152,7 +167,7 @@ static void get_tex_mapping(TextureMapping *mapping, BL::ShaderNodeMapping b_map mapping->max = get_float3(b_mapping.max()); } -static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNode b_node) +static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, BL::ShaderNode b_node) { ShaderNode *node = NULL; @@ -165,6 +180,7 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph case BL::ShaderNode::type_OUTPUT: break; case BL::ShaderNode::type_SQUEEZE: break; case BL::ShaderNode::type_TEXTURE: break; + case BL::ShaderNode::type_FRAME: break; /* handled outside this function */ case BL::ShaderNode::type_GROUP: break; /* existing blender nodes */ @@ -315,6 +331,10 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph node = new HoldoutNode(); break; } + case BL::ShaderNode::type_BSDF_ANISOTROPIC: { + node = new WardBsdfNode(); + break; + } case BL::ShaderNode::type_BSDF_DIFFUSE: { node = new DiffuseBsdfNode(); break; @@ -354,6 +374,23 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph node = glass; break; } + case BL::ShaderNode::type_BSDF_REFRACTION: { + BL::ShaderNodeBsdfRefraction b_refraction_node(b_node); + RefractionBsdfNode *refraction = new RefractionBsdfNode(); + switch(b_refraction_node.distribution()) { + case BL::ShaderNodeBsdfRefraction::distribution_SHARP: + refraction->distribution = ustring("Sharp"); + break; + case BL::ShaderNodeBsdfRefraction::distribution_BECKMANN: + refraction->distribution = ustring("Beckmann"); + break; + case BL::ShaderNodeBsdfRefraction::distribution_GGX: + refraction->distribution = ustring("GGX"); + break; + } + node = refraction; + break; + } case BL::ShaderNode::type_BSDF_TRANSLUCENT: { node = new TranslucentBsdfNode(); break; @@ -370,6 +407,10 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph node = new EmissionNode(); break; } + case BL::ShaderNode::type_AMBIENT_OCCLUSION: { + node = new AmbientOcclusionNode(); + break; + } case BL::ShaderNode::type_VOLUME_ISOTROPIC: { node = new IsotropicVolumeNode(); break; @@ -398,6 +439,62 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph node = new ParticleInfoNode(); break; } + case BL::ShaderNode::type_BUMP: { + node = new BumpNode(); + break; + } + case BL::ShaderNode::type_SCRIPT: { +#ifdef WITH_OSL + if(scene->params.shadingsystem != SceneParams::OSL) + break; + + /* create script node */ + BL::ShaderNodeScript b_script_node(b_node); + OSLScriptNode *script_node = new OSLScriptNode(); + + /* Generate inputs/outputs from node sockets + * + * Note: the node sockets are generated from OSL parameters, + * so the names match those of the corresponding parameters exactly. + * + * Note 2: ShaderInput/ShaderOutput store shallow string copies only! + * Socket names must be stored in the extra lists instead. */ + BL::Node::inputs_iterator b_input; + + for (b_script_node.inputs.begin(b_input); b_input != b_script_node.inputs.end(); ++b_input) { + script_node->input_names.push_back(ustring(b_input->name())); + ShaderInput *input = script_node->add_input(script_node->input_names.back().c_str(), convert_socket_type(b_input->type())); + set_default_value(input, *b_input, b_data, b_ntree); + } + + BL::Node::outputs_iterator b_output; + + for (b_script_node.outputs.begin(b_output); b_output != b_script_node.outputs.end(); ++b_output) { + script_node->output_names.push_back(ustring(b_output->name())); + script_node->add_output(script_node->output_names.back().c_str(), convert_socket_type(b_output->type())); + } + + /* load bytecode or filepath */ + OSLShaderManager *manager = (OSLShaderManager*)scene->shader_manager; + string bytecode_hash = b_script_node.bytecode_hash(); + + if(!bytecode_hash.empty()) { + /* loaded bytecode if not already done */ + if(!manager->shader_test_loaded(bytecode_hash)) + manager->shader_load_bytecode(bytecode_hash, b_script_node.bytecode()); + + script_node->bytecode_hash = bytecode_hash; + } + else { + /* set filepath */ + script_node->filepath = blender_absolute_path(b_data, b_ntree, b_script_node.filepath()); + } + + node = script_node; +#endif + + break; + } case BL::ShaderNode::type_TEX_IMAGE: { BL::ShaderNodeTexImage b_image_node(b_node); BL::Image b_image(b_image_node.image()); @@ -505,6 +602,23 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph node = sky; break; } + case BL::ShaderNode::type_NORMAL_MAP: { + BL::ShaderNodeNormalMap b_normal_map_node(b_node); + NormalMapNode *nmap = new NormalMapNode(); + nmap->space = NormalMapNode::space_enum[(int)b_normal_map_node.space()]; + nmap->attribute = b_normal_map_node.uv_map(); + node = nmap; + break; + } + case BL::ShaderNode::type_TANGENT: { + BL::ShaderNodeTangent b_tangent_node(b_node); + TangentNode *tangent = new TangentNode(); + tangent->direction_type = TangentNode::direction_type_enum[(int)b_tangent_node.direction_type()]; + tangent->axis = TangentNode::axis_enum[(int)b_tangent_node.axis()]; + tangent->attribute = b_tangent_node.uv_map(); + node = tangent; + break; + } } if(node && node != graph->output()) @@ -561,7 +675,7 @@ static SocketPair node_socket_map_pair(PtrNodeMap& node_map, BL::Node b_node, BL return SocketPair(node_map[b_node.ptr.data], name); } -static void add_nodes(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, PtrSockMap& sockets_map) +static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, PtrSockMap& sockets_map) { /* add nodes */ BL::ShaderNodeTree::nodes_iterator b_node; @@ -569,7 +683,34 @@ static void add_nodes(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *grap PtrSockMap proxy_map; for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) { - if(b_node->is_a(&RNA_NodeGroup)) { + if(b_node->mute()) { + BL::Node::inputs_iterator b_input; + BL::Node::outputs_iterator b_output; + bool found_match = false; + + /* this is slightly different than blender logic, we just connect a + * single pair for of input/output, but works ok for the node we have */ + for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) { + if(b_input->is_linked()) { + for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { + if(b_output->is_linked() && b_input->type() == b_output->type()) { + ProxyNode *proxy = new ProxyNode(convert_socket_type(b_input->type()), convert_socket_type(b_output->type())); + graph->add(proxy); + + proxy_map[b_input->ptr.data] = SocketPair(proxy, proxy->inputs[0]->name); + proxy_map[b_output->ptr.data] = SocketPair(proxy, proxy->outputs[0]->name); + found_match = true; + + break; + } + } + } + + if(found_match) + break; + } + } + else if(b_node->is_a(&RNA_NodeGroup)) { /* add proxy converter nodes for inputs and outputs */ BL::NodeGroup b_gnode(*b_node); BL::ShaderNodeTree b_group_ntree(b_gnode.node_tree()); @@ -592,7 +733,7 @@ static void add_nodes(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *grap group_sockmap[b_input->group_socket().ptr.data] = SocketPair(proxy, proxy->outputs[0]->name); /* default input values of the group node */ - set_default_value(proxy->inputs[0], *b_input); + set_default_value(proxy->inputs[0], *b_input, b_data, b_group_ntree); } for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { @@ -606,13 +747,13 @@ static void add_nodes(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *grap group_sockmap[b_output->group_socket().ptr.data] = SocketPair(proxy, proxy->inputs[0]->name); /* default input values of internal, unlinked group outputs */ - set_default_value(proxy->inputs[0], b_output->group_socket()); + set_default_value(proxy->inputs[0], b_output->group_socket(), b_data, b_group_ntree); } - add_nodes(b_data, b_scene, graph, b_group_ntree, group_sockmap); + add_nodes(scene, b_data, b_scene, graph, b_group_ntree, group_sockmap); } else { - ShaderNode *node = add_node(b_data, b_scene, graph, BL::ShaderNode(*b_node)); + ShaderNode *node = add_node(scene, b_data, b_scene, graph, b_ntree, BL::ShaderNode(*b_node)); if(node) { BL::Node::inputs_iterator b_input; @@ -626,7 +767,7 @@ static void add_nodes(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *grap assert(input); /* copy values for non linked inputs */ - set_default_value(input, *b_input); + set_default_value(input, *b_input, b_data, b_ntree); } } } @@ -649,7 +790,7 @@ static void add_nodes(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *grap /* from sock */ if(b_from_node) { - if (b_from_node.is_a(&RNA_NodeGroup)) + if (b_from_node.mute() || b_from_node.is_a(&RNA_NodeGroup)) from_pair = proxy_map[b_from_sock.ptr.data]; else from_pair = node_socket_map_pair(node_map, b_from_node, b_from_sock); @@ -659,7 +800,7 @@ static void add_nodes(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *grap /* to sock */ if(b_to_node) { - if (b_to_node.is_a(&RNA_NodeGroup)) + if (b_to_node.mute() || b_to_node.is_a(&RNA_NodeGroup)) to_pair = proxy_map[b_to_sock.ptr.data]; else to_pair = node_socket_map_pair(node_map, b_to_node, b_to_sock); @@ -702,7 +843,7 @@ void BlenderSync::sync_materials() PtrSockMap sock_to_node; BL::ShaderNodeTree b_ntree(b_mat->node_tree()); - add_nodes(b_data, b_scene, graph, b_ntree, sock_to_node); + add_nodes(scene, b_data, b_scene, graph, b_ntree, sock_to_node); } else { ShaderNode *closure, *out; @@ -743,7 +884,7 @@ void BlenderSync::sync_world() PtrSockMap sock_to_node; BL::ShaderNodeTree b_ntree(b_world.node_tree()); - add_nodes(b_data, b_scene, graph, b_ntree, sock_to_node); + add_nodes(scene, b_data, b_scene, graph, b_ntree, sock_to_node); } else if(b_world) { ShaderNode *closure, *out; @@ -802,7 +943,7 @@ void BlenderSync::sync_lamps() PtrSockMap sock_to_node; BL::ShaderNodeTree b_ntree(b_lamp->node_tree()); - add_nodes(b_data, b_scene, graph, b_ntree, sock_to_node); + add_nodes(scene, b_data, b_scene, graph, b_ntree, sock_to_node); } else { ShaderNode *closure, *out; diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index b4990eb815a..9ebdcfd04bd 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -17,6 +17,7 @@ */ #include "background.h" +#include "camera.h" #include "film.h" #include "../render/filter.h" #include "graph.h" @@ -141,7 +142,6 @@ void BlenderSync::sync_data(BL::SpaceView3D b_v3d, BL::Object b_override, const sync_film(); sync_shaders(); sync_objects(b_v3d); - sync_particle_systems(); sync_motion(b_v3d, b_override); } @@ -149,6 +149,9 @@ void BlenderSync::sync_data(BL::SpaceView3D b_v3d, BL::Object b_override, const void BlenderSync::sync_integrator() { +#ifdef __CAMERA_MOTION__ + BL::RenderSettings r = b_scene.render(); +#endif PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); experimental = (RNA_enum_get(&cscene, "feature_set") != 0); @@ -175,7 +178,12 @@ void BlenderSync::sync_integrator() integrator->layer_flag = render_layer.layer; integrator->sample_clamp = get_float(cscene, "sample_clamp"); -#ifdef __MOTION__ +#ifdef __CAMERA_MOTION__ + if(integrator->motion_blur != r.use_motion_blur()) { + scene->object_manager->tag_update(scene); + scene->camera->tag_update(); + } + integrator->motion_blur = (!preview && r.use_motion_blur()); #endif @@ -233,6 +241,7 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer) render_layer.use_localview = (b_v3d.local_view() ? true : false); render_layer.scene_layer = get_layer(b_v3d.layers(), b_v3d.layers_local_view(), render_layer.use_localview); render_layer.layer = render_layer.scene_layer; + render_layer.exclude_layer = 0; render_layer.holdout_layer = 0; render_layer.material_override = PointerRNA_NULL; render_layer.use_background = true; @@ -250,10 +259,16 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer) for(r.layers.begin(b_rlay); b_rlay != r.layers.end(); ++b_rlay) { if((!layer && first_layer) || (layer && b_rlay->name() == layer)) { render_layer.name = b_rlay->name(); - render_layer.scene_layer = get_layer(b_scene.layers()) & ~get_layer(b_rlay->layers_exclude()); - render_layer.layer = get_layer(b_rlay->layers()); + render_layer.holdout_layer = get_layer(b_rlay->layers_zmask()); + render_layer.exclude_layer = get_layer(b_rlay->layers_exclude()); + + render_layer.scene_layer = get_layer(b_scene.layers()) & ~render_layer.exclude_layer; + render_layer.scene_layer |= render_layer.exclude_layer & render_layer.holdout_layer; + + render_layer.layer = get_layer(b_rlay->layers()); render_layer.layer |= render_layer.holdout_layer; + render_layer.material_override = b_rlay->material_override(); render_layer.use_background = b_rlay->use_sky(); render_layer.use_viewport_visibility = false; @@ -269,6 +284,7 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer) SceneParams BlenderSync::get_scene_params(BL::Scene b_scene, bool background) { + BL::RenderSettings r = b_scene.render(); SceneParams params; PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); int shadingsystem = RNA_enum_get(&cscene, "shading_system"); @@ -286,6 +302,8 @@ SceneParams BlenderSync::get_scene_params(BL::Scene b_scene, bool background) params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits"); params.use_bvh_cache = (background)? RNA_boolean_get(&cscene, "use_cache"): false; + params.persistent_images = (background)? r.use_persistent_data(): false; + return params; } @@ -371,19 +389,36 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use params.start_resolution = get_int(cscene, "preview_start_resolution"); /* other parameters */ - params.threads = b_scene.render().threads(); + if(b_scene.render().threads_mode() == BL::RenderSettings::threads_mode_FIXED) + params.threads = b_scene.render().threads(); + else + params.threads = 0; params.cancel_timeout = get_float(cscene, "debug_cancel_timeout"); params.reset_timeout = get_float(cscene, "debug_reset_timeout"); params.text_timeout = get_float(cscene, "debug_text_timeout"); + params.progressive_refine = get_boolean(cscene, "use_progressive_refine"); + if(background) { - params.progressive = false; + if(params.progressive_refine) + params.progressive = true; + else + params.progressive = false; + params.start_resolution = INT_MAX; } else params.progressive = true; - + + /* shading system - scene level needs full refresh */ + int shadingsystem = RNA_enum_get(&cscene, "shading_system"); + + if(shadingsystem == 0) + params.shadingsystem = SessionParams::SVM; + else if(shadingsystem == 1) + params.shadingsystem = SessionParams::OSL; + return params; } diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index ce563087b4a..71781bc5459 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -42,6 +42,7 @@ class Film; class Light; class Mesh; class Object; +class ParticleSystem; class Scene; class Shader; class ShaderGraph; @@ -63,7 +64,7 @@ public: static SceneParams get_scene_params(BL::Scene b_scene, bool background); static SessionParams get_session_params(BL::RenderEngine b_engine, BL::UserPreferences b_userpref, BL::Scene b_scene, bool background); static bool get_session_pause(BL::Scene b_scene, bool background); - static BufferParams get_buffer_params(BL::Scene b_scene, Camera *cam, int width, int height); + static BufferParams get_buffer_params(BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, Camera *cam, int width, int height); private: /* sync */ @@ -77,24 +78,23 @@ private: void sync_world(); void sync_render_layers(BL::SpaceView3D b_v3d, const char *layer); void sync_shaders(); - void sync_particle_systems(); void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree); Mesh *sync_mesh(BL::Object b_ob, bool object_updated); - void sync_object(BL::Object b_parent, int b_index, BL::DupliObject b_dupli_object, Transform& tfm, uint layer_flag, int motion, int particle_id); - void sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm); + Object *sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_object, Transform& tfm, uint layer_flag, int motion); + void sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm); void sync_background_light(); void sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion); void sync_camera_motion(BL::Object b_ob, int motion); - void sync_particles(BL::Object b_ob, BL::ParticleSystem b_psys); + + /* particles */ + bool sync_dupli_particle(BL::Object b_ob, BL::DupliObject b_dup, Object *object); /* util */ void find_shader(BL::ID id, vector<uint>& used_shaders, int default_shader); bool BKE_object_is_modified(BL::Object b_ob); bool object_is_mesh(BL::Object b_ob); bool object_is_light(BL::Object b_ob); - bool psys_need_update(BL::ParticleSystem b_psys); - int object_count_particles(BL::Object b_ob); /* variables */ BL::RenderEngine b_engine; @@ -116,7 +116,8 @@ private: struct RenderLayerInfo { RenderLayerInfo() - : scene_layer(0), layer(0), holdout_layer(0), + : scene_layer(0), layer(0), + holdout_layer(0), exclude_layer(0), material_override(PointerRNA_NULL), use_background(true), use_viewport_visibility(false), @@ -127,6 +128,7 @@ private: uint scene_layer; uint layer; uint holdout_layer; + uint exclude_layer; BL::Material material_override; bool use_background; bool use_viewport_visibility; diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index da8f30ea169..4feb8b556d5 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -30,29 +30,7 @@ * todo: clean this up ... */ extern "C" { - -struct RenderEngine; -struct RenderResult; - -ID *rna_Object_to_mesh(void *_self, void *reports, void *scene, int apply_modifiers, int settings); -void rna_Main_meshes_remove(void *bmain, void *reports, void *mesh); -void rna_Object_create_duplilist(void *ob, void *reports, void *sce, int settings); -void rna_Object_free_duplilist(void *ob); -void rna_RenderLayer_rect_set(PointerRNA *ptr, const float *values); -void rna_RenderPass_rect_set(PointerRNA *ptr, const float *values); -struct RenderResult *RE_engine_begin_result(struct RenderEngine *engine, int x, int y, int w, int h, const char *layername); -void RE_engine_update_result(struct RenderEngine *engine, struct RenderResult *result); -void RE_engine_end_result(struct RenderEngine *engine, struct RenderResult *result, int cancel); -int RE_engine_test_break(struct RenderEngine *engine); -void RE_engine_update_stats(struct RenderEngine *engine, const char *stats, const char *info); -void RE_engine_update_progress(struct RenderEngine *engine, float progress); -void engine_tag_redraw(void *engine); -void engine_tag_update(void *engine); -int rna_Object_is_modified(void *ob, void *scene, int settings); -int rna_Object_is_deform_modified(void *ob, void *scene, int settings); void BLI_timestr(double _time, char *str); -void rna_ColorRamp_eval(void *coba, float position, float color[4]); -void rna_Scene_frame_set(void *scene, int frame, float subframe); void BKE_image_user_frame_calc(void *iuser, int cfra, int fieldnr); void BKE_image_user_file_path(void *iuser, void *ima, char *path); } @@ -61,10 +39,7 @@ CCL_NAMESPACE_BEGIN static inline BL::Mesh object_to_mesh(BL::Object self, BL::Scene scene, bool apply_modifiers, bool render) { - ID *data = rna_Object_to_mesh(self.ptr.data, NULL, scene.ptr.data, apply_modifiers, (render)? 2: 1); - PointerRNA ptr; - RNA_id_pointer_create(data, &ptr); - return BL::Mesh(ptr); + return self.to_mesh(scene, apply_modifiers, (render)? 2: 1); } static inline void colorramp_to_array(BL::ColorRamp ramp, float4 *data, int size) @@ -72,34 +47,19 @@ static inline void colorramp_to_array(BL::ColorRamp ramp, float4 *data, int size for(int i = 0; i < size; i++) { float color[4]; - rna_ColorRamp_eval(ramp.ptr.data, i/(float)(size-1), color); + ramp.evaluate(i/(float)(size-1), color); data[i] = make_float4(color[0], color[1], color[2], color[3]); } } -static inline void object_remove_mesh(BL::BlendData data, BL::Mesh mesh) -{ - rna_Main_meshes_remove(data.ptr.data, NULL, mesh.ptr.data); -} - -static inline void object_create_duplilist(BL::Object self, BL::Scene scene) -{ - rna_Object_create_duplilist(self.ptr.data, NULL, scene.ptr.data, 2); -} - -static inline void object_free_duplilist(BL::Object self) -{ - rna_Object_free_duplilist(self.ptr.data); -} - static inline bool BKE_object_is_modified(BL::Object self, BL::Scene scene, bool preview) { - return rna_Object_is_modified(self.ptr.data, scene.ptr.data, (preview)? (1<<0): (1<<1))? true: false; + return self.is_modified(scene, (preview)? (1<<0): (1<<1))? true: false; } static inline bool BKE_object_is_deform_modified(BL::Object self, BL::Scene scene, bool preview) { - return rna_Object_is_deform_modified(self.ptr.data, scene.ptr.data, (preview)? (1<<0): (1<<1))? true: false; + return self.is_deform_modified(scene, (preview)? (1<<0): (1<<1))? true: false; } static inline string image_user_file_path(BL::ImageUser iuser, BL::Image ima, int cfra) @@ -110,11 +70,6 @@ static inline string image_user_file_path(BL::ImageUser iuser, BL::Image ima, in return string(filepath); } -static inline void scene_frame_set(BL::Scene scene, int frame) -{ - rna_Scene_frame_set(scene.ptr.data, frame, 0.0f); -} - /* Utilities */ static inline Transform get_transform(BL::Array<float, 16> array) @@ -329,6 +284,12 @@ public: return recalc; } + bool is_used(const K& key) + { + T *data = find(key); + return (data) ? used_set.find(data) != used_set.end() : false; + } + void used(T *data) { /* tag data as still in use */ @@ -388,27 +349,49 @@ protected: /* Object Key */ +enum { OBJECT_PERSISTENT_ID_SIZE = 8 }; + struct ObjectKey { void *parent; - int index; + int id[OBJECT_PERSISTENT_ID_SIZE]; void *ob; - ObjectKey(void *parent_, int index_, void *ob_) - : parent(parent_), index(index_), ob(ob_) {} + ObjectKey(void *parent_, int id_[OBJECT_PERSISTENT_ID_SIZE], void *ob_) + : parent(parent_), ob(ob_) + { + if(id_) + memcpy(id, id_, sizeof(id)); + else + memset(id, 0, sizeof(id)); + } bool operator<(const ObjectKey& k) const - { return (parent < k.parent || (parent == k.parent && (index < k.index || (index == k.index && ob < k.ob)))); } + { + return (parent < k.parent) || + (parent == k.parent && (memcmp(id, k.id, sizeof(id)) < 0)) || + (memcmp(id, k.id, sizeof(id)) == 0 && ob < k.ob); + } }; struct ParticleSystemKey { void *ob; - void *psys; + int id[OBJECT_PERSISTENT_ID_SIZE]; - ParticleSystemKey(void *ob_, void *psys_) - : ob(ob_), psys(psys_) {} + ParticleSystemKey(void *ob_, int id_[OBJECT_PERSISTENT_ID_SIZE]) + : ob(ob_) + { + if(id_) + memcpy(id, id_, sizeof(id)); + else + memset(id, 0, sizeof(id)); + } bool operator<(const ParticleSystemKey& k) const - { return (ob < k.ob && psys < k.psys); } + { + /* first id is particle index, we don't compare that */ + return (ob < k.ob) || + (ob == k.ob && (memcmp(id+1, k.id+1, sizeof(int)*(OBJECT_PERSISTENT_ID_SIZE-1)) < 0)); + } }; CCL_NAMESPACE_END diff --git a/intern/cycles/bvh/CMakeLists.txt b/intern/cycles/bvh/CMakeLists.txt index ba5c3785eac..cbbd23fcff8 100644 --- a/intern/cycles/bvh/CMakeLists.txt +++ b/intern/cycles/bvh/CMakeLists.txt @@ -7,6 +7,7 @@ set(INC ../util ../device ) + set(INC_SYS ) diff --git a/intern/cycles/bvh/bvh_node.h b/intern/cycles/bvh/bvh_node.h index 5c00f7b7a38..a0d10a46bfc 100644 --- a/intern/cycles/bvh/bvh_node.h +++ b/intern/cycles/bvh/bvh_node.h @@ -54,7 +54,7 @@ public: // Subtree functions int getSubtreeSize(BVH_STAT stat=BVH_STAT_NODE_COUNT) const; - float computeSubtreeSAHCost(const BVHParams& p, float probability = 1.0f) const; + float computeSubtreeSAHCost(const BVHParams& p, float probability = 1.0f) const; void deleteSubtree(); uint update_visibility(); diff --git a/intern/cycles/cmake/external_libs.cmake b/intern/cycles/cmake/external_libs.cmake index 332d3d74715..790049898ff 100644 --- a/intern/cycles/cmake/external_libs.cmake +++ b/intern/cycles/cmake/external_libs.cmake @@ -18,33 +18,6 @@ else() endif() ########################################################################### -# Partio - -if(WITH_CYCLES_PARTIO) - - set(CYCLES_PARTIO "" CACHE PATH "Path to Partio installation") - - message(STATUS "CYCLES_PARTIO = ${CYCLES_PARTIO}") - - find_library(PARTIO_LIBRARIES NAMES partio PATHS ${CYCLES_PARTIO}/lib) - find_path(PARTIO_INCLUDES Partio.h ${CYCLES_PARTIO}/include) - - find_package(ZLIB) - - if(PARTIO_INCLUDES AND PARTIO_LIBRARIES AND ZLIB_LIBRARIES) - list(APPEND PARTIO_LIBRARIES ${ZLIB_LIBRARIES}) - set(PARTIO_FOUND TRUE) - message(STATUS "PARTIO includes = ${PARTIO_INCLUDES}") - message(STATUS "PARTIO library = ${PARTIO_LIBRARIES}") - else() - message(STATUS "PARTIO not found") - endif() - - include_directories(${PARTIO_INCLUDES}) - -endif() - -########################################################################### # CUDA if(WITH_CYCLES_CUDA_BINARIES) diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt index 0f692aa3051..fe2368b7ea8 100644 --- a/intern/cycles/device/CMakeLists.txt +++ b/intern/cycles/device/CMakeLists.txt @@ -7,6 +7,7 @@ set(INC ../util ../render ) + set(INC_SYS ${OPENGL_INCLUDE_DIR} ${GLEW_INCLUDE_PATH} diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index 2db2b11c1cb..721c262f094 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -28,6 +28,7 @@ #include "util_math.h" #include "util_opencl.h" #include "util_opengl.h" +#include "util_time.h" #include "util_types.h" #include "util_vector.h" @@ -79,36 +80,36 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int w } } -Device *Device::create(DeviceInfo& info, bool background, int threads) +Device *Device::create(DeviceInfo& info, Stats &stats, bool background) { Device *device; switch(info.type) { case DEVICE_CPU: - device = device_cpu_create(info, threads); + device = device_cpu_create(info, stats); break; #ifdef WITH_CUDA case DEVICE_CUDA: if(cuLibraryInit()) - device = device_cuda_create(info, background); + device = device_cuda_create(info, stats, background); else device = NULL; break; #endif #ifdef WITH_MULTI case DEVICE_MULTI: - device = device_multi_create(info, background); + device = device_multi_create(info, stats, background); break; #endif #ifdef WITH_NETWORK case DEVICE_NETWORK: - device = device_network_create(info, "127.0.0.1"); + device = device_network_create(info, stats, "127.0.0.1"); break; #endif #ifdef WITH_OPENCL case DEVICE_OPENCL: if(clLibraryInit()) - device = device_opencl_create(info, background); + device = device_opencl_create(info, stats, background); else device = NULL; break; @@ -190,6 +191,18 @@ vector<DeviceInfo>& Device::available_devices() { static vector<DeviceInfo> devices; static bool devices_init = false; + static double device_update_time = 0.0; + + /* only update device list if we're not actively rendering already, things + * could go very wrong if a device suddenly becomes (un)available. also do + * it only every 5 seconds. it not super cpu intensive but don't want to do + * it on every redraw. */ + if(devices_init) { + if(!TaskScheduler::active() && (time_dt() > device_update_time + 5.0)) { + devices.clear(); + devices_init = false; + } + } if(!devices_init) { #ifdef WITH_CUDA @@ -213,6 +226,7 @@ vector<DeviceInfo>& Device::available_devices() #endif devices_init = true; + device_update_time = time_dt(); } return devices; diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index 2ee2e044618..9840687b76a 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -25,6 +25,7 @@ #include "device_task.h" #include "util_list.h" +#include "util_stats.h" #include "util_string.h" #include "util_thread.h" #include "util_types.h" @@ -72,7 +73,7 @@ public: class Device { protected: - Device() {} + Device(Stats &stats_) : stats(stats_) {} bool background; string error_msg; @@ -84,6 +85,9 @@ public: DeviceInfo info; virtual const string& error_message() { return error_msg; } + /* statistics */ + Stats &stats; + /* regular memory */ virtual void mem_alloc(device_memory& mem, MemoryType type) = 0; virtual void mem_copy_to(device_memory& mem) = 0; @@ -130,7 +134,7 @@ public: virtual int device_number(Device *sub_device) { return 0; } /* static */ - static Device *create(DeviceInfo& info, bool background = true, int threads = 0); + static Device *create(DeviceInfo& info, Stats &stats, bool background = true); static DeviceType type_from_string(const char *name); static string string_from_type(DeviceType type); diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index 4c54671b0d0..bc280616615 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -45,7 +45,7 @@ public: TaskPool task_pool; KernelGlobals *kg; - CPUDevice(int threads_num) + CPUDevice(Stats &stats) : Device(stats) { kg = kernel_globals_create(); @@ -67,6 +67,8 @@ public: void mem_alloc(device_memory& mem, MemoryType type) { mem.device_pointer = mem.data_pointer; + + stats.mem_alloc(mem.memory_size()); } void mem_copy_to(device_memory& mem) @@ -87,6 +89,8 @@ public: void mem_free(device_memory& mem) { mem.device_pointer = 0; + + stats.mem_free(mem.memory_size()); } void const_copy_to(const char *name, void *host, size_t size) @@ -98,11 +102,15 @@ public: { kernel_tex_copy(kg, name, mem.data_pointer, mem.data_width, mem.data_height); mem.device_pointer = mem.data_pointer; + + stats.mem_alloc(mem.memory_size()); } void tex_free(device_memory& mem) { mem.device_pointer = 0; + + stats.mem_free(mem.memory_size()); } void *osl_memory() @@ -135,8 +143,10 @@ public: void thread_path_trace(DeviceTask& task) { - if(task_pool.cancelled()) - return; + if(task_pool.cancelled()) { + if(task.need_finish_queue == false) + return; + } #ifdef WITH_OSL if(kernel_osl_use(kg)) @@ -154,8 +164,10 @@ public: #ifdef WITH_OPTIMIZED_KERNEL if(system_cpu_support_optimized()) { for(int sample = start_sample; sample < end_sample; sample++) { - if (task.get_cancel() || task_pool.cancelled()) - break; + if (task.get_cancel() || task_pool.cancelled()) { + if(task.need_finish_queue == false) + break; + } for(int y = tile.y; y < tile.y + tile.h; y++) { for(int x = tile.x; x < tile.x + tile.w; x++) { @@ -173,8 +185,10 @@ public: #endif { for(int sample = start_sample; sample < end_sample; sample++) { - if (task.get_cancel() || task_pool.cancelled()) - break; + if (task.get_cancel() || task_pool.cancelled()) { + if(task.need_finish_queue == false) + break; + } for(int y = tile.y; y < tile.y + tile.h; y++) { for(int x = tile.x; x < tile.x + tile.w; x++) { @@ -191,8 +205,10 @@ public: task.release_tile(tile); - if(task_pool.cancelled()) - break; + if(task_pool.cancelled()) { + if(task.need_finish_queue == false) + break; + } } #ifdef WITH_OSL @@ -258,7 +274,7 @@ public: /* split task into smaller ones, more than number of threads for uneven * workloads where some parts of the image render slower than others */ list<DeviceTask> tasks; - task.split(tasks, TaskScheduler::num_threads()+1); + task.split(tasks, TaskScheduler::num_threads()); foreach(DeviceTask& task, tasks) task_pool.push(new CPUDeviceTask(this, task)); @@ -275,9 +291,9 @@ public: } }; -Device *device_cpu_create(DeviceInfo& info, int threads) +Device *device_cpu_create(DeviceInfo& info, Stats &stats) { - return new CPUDevice(threads); + return new CPUDevice(stats); } void device_cpu_info(vector<DeviceInfo>& devices) diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index 18a29b2551c..440971e2663 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -157,7 +157,7 @@ public: cuda_assert(cuCtxSetCurrent(NULL)); } - CUDADevice(DeviceInfo& info, bool background_) + CUDADevice(DeviceInfo& info, Stats &stats, bool background_) : Device(stats) { background = background_; @@ -316,8 +316,10 @@ public: { cuda_push_context(); CUdeviceptr device_pointer; - cuda_assert(cuMemAlloc(&device_pointer, mem.memory_size())) + size_t size = mem.memory_size(); + cuda_assert(cuMemAlloc(&device_pointer, size)) mem.device_pointer = (device_ptr)device_pointer; + stats.mem_alloc(size); cuda_pop_context(); } @@ -356,6 +358,8 @@ public: cuda_pop_context(); mem.device_pointer = 0; + + stats.mem_free(mem.memory_size()); } } @@ -424,6 +428,8 @@ public: cuda_assert(cuTexRefSetFlags(texref, CU_TRSF_NORMALIZED_COORDINATES)) mem.device_pointer = (device_ptr)handle; + + stats.mem_alloc(size); } else { cuda_pop_context(); @@ -463,6 +469,8 @@ public: tex_interp_map.erase(tex_interp_map.find(mem.device_pointer)); mem.device_pointer = 0; + + stats.mem_free(mem.memory_size()); } else { tex_interp_map.erase(tex_interp_map.find(mem.device_pointer)); @@ -707,6 +715,8 @@ public: mem.device_pointer = pmem.cuTexId; pixel_mem_map[mem.device_pointer] = pmem; + stats.mem_alloc(mem.memory_size()); + return; } else { @@ -762,6 +772,8 @@ public: pixel_mem_map.erase(pixel_mem_map.find(mem.device_pointer)); mem.device_pointer = 0; + stats.mem_free(mem.memory_size()); + return; } @@ -839,8 +851,10 @@ public: int end_sample = tile.start_sample + tile.num_samples; for(int sample = start_sample; sample < end_sample; sample++) { - if (task->get_cancel()) - break; + if (task->get_cancel()) { + if(task->need_finish_queue == false) + break; + } path_trace(tile, sample); @@ -896,9 +910,9 @@ public: } }; -Device *device_cuda_create(DeviceInfo& info, bool background) +Device *device_cuda_create(DeviceInfo& info, Stats &stats, bool background) { - return new CUDADevice(info, background); + return new CUDADevice(info, stats, background); } void device_cuda_info(vector<DeviceInfo>& devices) diff --git a/intern/cycles/device/device_intern.h b/intern/cycles/device/device_intern.h index e3601aa8ad4..b49ebba3e8b 100644 --- a/intern/cycles/device/device_intern.h +++ b/intern/cycles/device/device_intern.h @@ -23,11 +23,11 @@ CCL_NAMESPACE_BEGIN class Device; -Device *device_cpu_create(DeviceInfo& info, int threads); -Device *device_opencl_create(DeviceInfo& info, bool background); -Device *device_cuda_create(DeviceInfo& info, bool background); -Device *device_network_create(DeviceInfo& info, const char *address); -Device *device_multi_create(DeviceInfo& info, bool background); +Device *device_cpu_create(DeviceInfo& info, Stats &stats); +Device *device_opencl_create(DeviceInfo& info, Stats &stats, bool background); +Device *device_cuda_create(DeviceInfo& info, Stats &stats, bool background); +Device *device_network_create(DeviceInfo& info, Stats &stats, const char *address); +Device *device_multi_create(DeviceInfo& info, Stats &stats, bool background); void device_cpu_info(vector<DeviceInfo>& devices); void device_opencl_info(vector<DeviceInfo>& devices); diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp index 546ffe5e4b9..807bfe578f3 100644 --- a/intern/cycles/device/device_multi.cpp +++ b/intern/cycles/device/device_multi.cpp @@ -46,14 +46,14 @@ public: list<SubDevice> devices; device_ptr unique_ptr; - MultiDevice(DeviceInfo& info, bool background_) - : unique_ptr(1) + MultiDevice(DeviceInfo& info, Stats &stats, bool background_) + : Device(stats), unique_ptr(1) { Device *device; background = background_; foreach(DeviceInfo& subinfo, info.multi_devices) { - device = Device::create(subinfo, background); + device = Device::create(subinfo, stats, background); devices.push_back(SubDevice(device)); } @@ -314,9 +314,9 @@ public: } }; -Device *device_multi_create(DeviceInfo& info, bool background) +Device *device_multi_create(DeviceInfo& info, Stats &stats, bool background) { - return new MultiDevice(info, background); + return new MultiDevice(info, stats, background); } static bool device_multi_add(vector<DeviceInfo>& devices, DeviceType type, bool with_display, bool with_advanced_shading, const char *id_fmt, int num) diff --git a/intern/cycles/device/device_network.cpp b/intern/cycles/device/device_network.cpp index 931890b5859..a5e0d39df73 100644 --- a/intern/cycles/device/device_network.cpp +++ b/intern/cycles/device/device_network.cpp @@ -32,8 +32,8 @@ public: boost::asio::io_service io_service; tcp::socket socket; - NetworkDevice(const char *address) - : socket(io_service) + NetworkDevice(Stats &stats, const char *address) + : Device(stats), socket(io_service) { stringstream portstr; portstr << SERVER_PORT; @@ -202,9 +202,9 @@ public: } }; -Device *device_network_create(DeviceInfo& info, const char *address) +Device *device_network_create(DeviceInfo& info, Stats &stats, const char *address) { - return new NetworkDevice(address); + return new NetworkDevice(stats, address); } void device_network_info(vector<DeviceInfo>& devices) diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index 673ffdf79fd..69287f1a8bd 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -144,7 +144,8 @@ public: } } - OpenCLDevice(DeviceInfo& info, bool background_) + OpenCLDevice(DeviceInfo& info, Stats &stats, bool background_) + : Device(stats) { background = background_; cpPlatform = NULL; @@ -473,6 +474,8 @@ public: mem.device_pointer = (device_ptr)clCreateBuffer(cxContext, CL_MEM_READ_WRITE, size, NULL, &ciErr); opencl_assert(ciErr); + + stats.mem_alloc(size); } void mem_copy_to(device_memory& mem) @@ -506,6 +509,8 @@ public: ciErr = clReleaseMemObject(CL_MEM_PTR(mem.device_pointer)); mem.device_pointer = 0; opencl_assert(ciErr); + + stats.mem_free(mem.memory_size()); } } @@ -686,8 +691,10 @@ public: int end_sample = tile.start_sample + tile.num_samples; for(int sample = start_sample; sample < end_sample; sample++) { - if (task->get_cancel()) - break; + if (task->get_cancel()) { + if(task->need_finish_queue == false) + break; + } path_trace(tile, sample); @@ -726,9 +733,9 @@ public: } }; -Device *device_opencl_create(DeviceInfo& info, bool background) +Device *device_opencl_create(DeviceInfo& info, Stats &stats, bool background) { - return new OpenCLDevice(info, background); + return new OpenCLDevice(info, stats, background); } void device_opencl_info(vector<DeviceInfo>& devices) diff --git a/intern/cycles/device/device_task.cpp b/intern/cycles/device/device_task.cpp index c85e182d629..b3f02deaf6f 100644 --- a/intern/cycles/device/device_task.cpp +++ b/intern/cycles/device/device_task.cpp @@ -101,7 +101,7 @@ void DeviceTask::update_progress(RenderTile &rtile) if(update_tile_sample) { double current_time = time_dt(); - if (current_time - last_update_time >= 1.0f) { + if (current_time - last_update_time >= 1.0) { update_tile_sample(rtile); last_update_time = current_time; diff --git a/intern/cycles/device/device_task.h b/intern/cycles/device/device_task.h index cfb3d8d988e..8ca8b88ea49 100644 --- a/intern/cycles/device/device_task.h +++ b/intern/cycles/device/device_task.h @@ -65,6 +65,7 @@ public: boost::function<void(RenderTile&)> release_tile; boost::function<bool(void)> get_cancel; + bool need_finish_queue; protected: double last_update_time; }; diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index df8a9b1d5b4..5a570328948 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -5,7 +5,9 @@ set(INC osl svm ) + set(INC_SYS + ) set(SRC @@ -31,13 +33,11 @@ set(SRC_HEADERS kernel_globals.h kernel_light.h kernel_math.h - kernel_mbvh.h kernel_montecarlo.h kernel_object.h kernel_passes.h kernel_path.h kernel_projection.h - kernel_qbvh.h kernel_random.h kernel_shader.h kernel_textures.h @@ -45,18 +45,22 @@ set(SRC_HEADERS kernel_types.h ) +set(SRC_CLOSURE_HEADERS + closure/bsdf.h + closure/bsdf_ashikhmin_velvet.h + closure/bsdf_diffuse.h + closure/bsdf_microfacet.h + closure/bsdf_oren_nayar.h + closure/bsdf_phong_ramp.h + closure/bsdf_reflection.h + closure/bsdf_refraction.h + closure/bsdf_transparent.h + closure/bsdf_ward.h + closure/bsdf_westin.h + closure/emissive.h + closure/volume.h +) set(SRC_SVM_HEADERS - svm/bsdf.h - svm/bsdf_ashikhmin_velvet.h - svm/bsdf_diffuse.h - svm/bsdf_oren_nayar.h - svm/bsdf_microfacet.h - svm/bsdf_reflection.h - svm/bsdf_refraction.h - svm/bsdf_transparent.h - svm/bsdf_ward.h - svm/bsdf_westin.h - svm/emissive.h svm/svm.h svm/svm_attribute.h svm/svm_bsdf.h @@ -92,7 +96,6 @@ set(SRC_SVM_HEADERS svm/svm_value.h svm/svm_voronoi.h svm/svm_wave.h - svm/volume.h ) set(SRC_UTIL_HEADERS @@ -110,7 +113,7 @@ if(WITH_CYCLES_CUDA_BINARIES) set(CUDA_BITS 32) endif() - set(cuda_sources kernel.cu ${SRC_HEADERS} ${SRC_SVM_HEADERS} ${SRC_UTIL_HEADERS}) + set(cuda_sources kernel.cu ${SRC_HEADERS} ${SRC_SVM_HEADERS} ${SRC_CLOSURE_HEADERS} ${SRC_UTIL_HEADERS}) set(cuda_cubins) foreach(arch ${CYCLES_CUDA_BINARIES_ARCH}) @@ -132,6 +135,7 @@ endif() if(WITH_CYCLES_OSL) add_subdirectory(osl) + add_subdirectory(shaders) endif() # CPU module @@ -139,7 +143,7 @@ endif() include_directories(${INC}) include_directories(SYSTEM ${INC_SYS}) -add_library(cycles_kernel ${SRC} ${SRC_HEADERS} ${SRC_SVM_HEADERS}) +add_library(cycles_kernel ${SRC} ${SRC_HEADERS} ${SRC_CLOSURE_HEADERS} ${SRC_SVM_HEADERS}) if(WITH_CYCLES_OPTIMIZED_KERNEL) set_source_files_properties(kernel_optimized.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_OPTIMIZED_KERNEL_FLAGS}") @@ -162,6 +166,7 @@ endif() delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernel.cl" ${CYCLES_INSTALL_PATH}/kernel) delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernel.cu" ${CYCLES_INSTALL_PATH}/kernel) delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel) +delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_CLOSURE_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel/closure) delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_SVM_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel/svm) delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_UTIL_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel) diff --git a/intern/cycles/kernel/svm/bsdf.h b/intern/cycles/kernel/closure/bsdf.h index cfb6321a918..cfb6321a918 100644 --- a/intern/cycles/kernel/svm/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h diff --git a/intern/cycles/kernel/svm/bsdf_ashikhmin_velvet.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h index 40249dbe9c6..016fd73204e 100644 --- a/intern/cycles/kernel/svm/bsdf_ashikhmin_velvet.h +++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h @@ -35,37 +35,34 @@ CCL_NAMESPACE_BEGIN -typedef struct BsdfAshikhminVelvetClosure { - //float3 m_N; - float m_invsigma2; -} BsdfAshikhminVelvetClosure; - -__device void bsdf_ashikhmin_velvet_setup(ShaderData *sd, ShaderClosure *sc, float sigma) +__device int bsdf_ashikhmin_velvet_setup(ShaderClosure *sc) { + float sigma = sc->data0; sigma = fmaxf(sigma, 0.01f); float m_invsigma2 = 1.0f/(sigma * sigma); sc->type = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID; - sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL; sc->data0 = m_invsigma2; + + return SD_BSDF|SD_BSDF_HAS_EVAL; } __device void bsdf_ashikhmin_velvet_blur(ShaderClosure *sc, float roughness) { } -__device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { float m_invsigma2 = sc->data0; - float3 m_N = sd->N; + float3 N = sc->N; - float cosNO = dot(m_N, I); - float cosNI = dot(m_N, omega_in); + float cosNO = dot(N, I); + float cosNI = dot(N, omega_in); if(cosNO > 0 && cosNI > 0) { float3 H = normalize(omega_in + I); - float cosNH = dot(m_N, H); + float cosNH = dot(N, H); float cosHO = fabsf(dot(I, H)); if(!(fabsf(cosNH) < 1.0f-1e-5f && cosHO > 1e-5f)) @@ -93,32 +90,27 @@ __device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderData *sd, const S return make_float3(0, 0, 0); } -__device float3 bsdf_ashikhmin_velvet_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_ashikhmin_velvet_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float bsdf_ashikhmin_velvet_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) -{ - return 1.0f; -} - -__device int bsdf_ashikhmin_velvet_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +__device int bsdf_ashikhmin_velvet_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { float m_invsigma2 = sc->data0; - float3 m_N = sd->N; + float3 N = sc->N; // we are viewing the surface from above - send a ray out with uniform // distribution over the hemisphere - sample_uniform_hemisphere(m_N, randu, randv, omega_in, pdf); + sample_uniform_hemisphere(N, randu, randv, omega_in, pdf); - if(dot(sd->Ng, *omega_in) > 0) { - float3 H = normalize(*omega_in + sd->I); + if(dot(Ng, *omega_in) > 0) { + float3 H = normalize(*omega_in + I); - float cosNI = dot(m_N, *omega_in); - float cosNO = dot(m_N, sd->I); - float cosNH = dot(m_N, H); - float cosHO = fabsf(dot(sd->I, H)); + float cosNI = dot(N, *omega_in); + float cosNO = dot(N, I); + float cosNH = dot(N, H); + float cosHO = fabsf(dot(I, H)); if(fabsf(cosNO) > 1e-5f && fabsf(cosNH) < 1.0f-1e-5f && cosHO > 1e-5f) { float cosNHdivHO = cosNH / cosHO; @@ -140,8 +132,8 @@ __device int bsdf_ashikhmin_velvet_sample(const ShaderData *sd, const ShaderClos #ifdef __RAY_DIFFERENTIALS__ // TODO: find a better approximation for the retroreflective bounce - *domega_in_dx = (2 * dot(m_N, sd->dI.dx)) * m_N - sd->dI.dx; - *domega_in_dy = (2 * dot(m_N, sd->dI.dy)) * m_N - sd->dI.dy; + *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx; + *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy; *domega_in_dx *= 125.0f; *domega_in_dy *= 125.0f; #endif diff --git a/intern/cycles/kernel/svm/bsdf_diffuse.h b/intern/cycles/kernel/closure/bsdf_diffuse.h index edf8dd93341..88b40e3d479 100644 --- a/intern/cycles/kernel/svm/bsdf_diffuse.h +++ b/intern/cycles/kernel/closure/bsdf_diffuse.h @@ -37,52 +37,43 @@ CCL_NAMESPACE_BEGIN /* DIFFUSE */ -typedef struct BsdfDiffuseClosure { - //float3 m_N; -} BsdfDiffuseClosure; - -__device void bsdf_diffuse_setup(ShaderData *sd, ShaderClosure *sc) +__device int bsdf_diffuse_setup(ShaderClosure *sc) { sc->type = CLOSURE_BSDF_DIFFUSE_ID; - sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL; + return SD_BSDF|SD_BSDF_HAS_EVAL; } __device void bsdf_diffuse_blur(ShaderClosure *sc, float roughness) { } -__device float3 bsdf_diffuse_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_diffuse_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { - float3 m_N = sd->N; + float3 N = sc->N; - float cos_pi = fmaxf(dot(m_N, omega_in), 0.0f) * M_1_PI_F; + float cos_pi = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F; *pdf = cos_pi; return make_float3(cos_pi, cos_pi, cos_pi); } -__device float3 bsdf_diffuse_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_diffuse_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float bsdf_diffuse_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) -{ - return 1.0f; -} - -__device int bsdf_diffuse_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +__device int bsdf_diffuse_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { - float3 m_N = sd->N; + float3 N = sc->N; // distribution over the hemisphere - sample_cos_hemisphere(m_N, randu, randv, omega_in, pdf); + sample_cos_hemisphere(N, randu, randv, omega_in, pdf); - if(dot(sd->Ng, *omega_in) > 0.0f) { + if(dot(Ng, *omega_in) > 0.0f) { *eval = make_float3(*pdf, *pdf, *pdf); #ifdef __RAY_DIFFERENTIALS__ // TODO: find a better approximation for the diffuse bounce - *domega_in_dx = (2 * dot(m_N, sd->dI.dx)) * m_N - sd->dI.dx; - *domega_in_dy = (2 * dot(m_N, sd->dI.dy)) * m_N - sd->dI.dy; + *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx; + *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy; *domega_in_dx *= 125.0f; *domega_in_dy *= 125.0f; #endif @@ -95,52 +86,48 @@ __device int bsdf_diffuse_sample(const ShaderData *sd, const ShaderClosure *sc, /* TRANSLUCENT */ -typedef struct BsdfTranslucentClosure { - //float3 m_N; -} BsdfTranslucentClosure; - -__device void bsdf_translucent_setup(ShaderData *sd, ShaderClosure *sc) +__device int bsdf_translucent_setup(ShaderClosure *sc) { sc->type = CLOSURE_BSDF_TRANSLUCENT_ID; - sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL; + return SD_BSDF|SD_BSDF_HAS_EVAL; } __device void bsdf_translucent_blur(ShaderClosure *sc, float roughness) { } -__device float3 bsdf_translucent_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_translucent_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float3 bsdf_translucent_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_translucent_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { - float3 m_N = sd->N; + float3 N = sc->N; - float cos_pi = fmaxf(-dot(m_N, omega_in), 0.0f) * M_1_PI_F; + float cos_pi = fmaxf(-dot(N, omega_in), 0.0f) * M_1_PI_F; *pdf = cos_pi; return make_float3 (cos_pi, cos_pi, cos_pi); } -__device float bsdf_translucent_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) +__device float bsdf_translucent_albedo(const ShaderClosure *sc, const float3 I) { return 1.0f; } -__device int bsdf_translucent_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +__device int bsdf_translucent_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { - float3 m_N = sd->N; + float3 N = sc->N; // we are viewing the surface from the right side - send a ray out with cosine // distribution over the hemisphere - sample_cos_hemisphere (-m_N, randu, randv, omega_in, pdf); - if(dot(sd->Ng, *omega_in) < 0) { + sample_cos_hemisphere (-N, randu, randv, omega_in, pdf); + if(dot(Ng, *omega_in) < 0) { *eval = make_float3(*pdf, *pdf, *pdf); #ifdef __RAY_DIFFERENTIALS__ // TODO: find a better approximation for the diffuse bounce - *domega_in_dx = (2 * dot(m_N, sd->dI.dx)) * m_N - sd->dI.dx; - *domega_in_dy = (2 * dot(m_N, sd->dI.dy)) * m_N - sd->dI.dy; + *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx; + *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy; *domega_in_dx *= -125.0f; *domega_in_dy *= -125.0f; #endif diff --git a/intern/cycles/kernel/svm/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index d8f0310bd02..a564b99e759 100644 --- a/intern/cycles/kernel/svm/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -37,31 +37,36 @@ CCL_NAMESPACE_BEGIN /* GGX */ -typedef struct BsdfMicrofacetGGXClosure { - //float3 m_N; - float m_ag; - float m_eta; -} BsdfMicrofacetGGXClosure; - __device_inline float safe_sqrtf(float f) { return sqrtf(max(f, 0.0f)); } -__device void bsdf_microfacet_ggx_setup(ShaderData *sd, ShaderClosure *sc, float ag, float eta, bool refractive) +__device int bsdf_microfacet_ggx_setup(ShaderClosure *sc) { + float ag = sc->data0; + + float m_ag = clamp(ag, 1e-4f, 1.0f); + + sc->data0 = m_ag; + sc->type = CLOSURE_BSDF_MICROFACET_GGX_ID; + + return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; +} + +__device int bsdf_microfacet_ggx_refraction_setup(ShaderClosure *sc) +{ + float ag = sc->data0; + float eta = sc->data1; + float m_ag = clamp(ag, 1e-4f, 1.0f); float m_eta = eta; sc->data0 = m_ag; sc->data1 = m_eta; + sc->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; - if(refractive) - sc->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; - else - sc->type = CLOSURE_BSDF_MICROFACET_GGX_ID; - - sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; + return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; } __device void bsdf_microfacet_ggx_blur(ShaderClosure *sc, float roughness) @@ -71,23 +76,22 @@ __device void bsdf_microfacet_ggx_blur(ShaderClosure *sc, float roughness) sc->data0 = m_ag; } -__device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { float m_ag = sc->data0; - //float m_eta = sc->data1; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; - float3 m_N = sd->N; + float3 N = sc->N; if(m_refractive) return make_float3 (0, 0, 0); - float cosNO = dot(m_N, I); - float cosNI = dot(m_N, omega_in); + float cosNO = dot(N, I); + float cosNI = dot(N, omega_in); if(cosNI > 0 && cosNO > 0) { // get half vector float3 Hr = normalize(omega_in + I); // eq. 20: (F*G*D)/(4*in*on) // eq. 33: first we calculate D(m) with m=Hr: float alpha2 = m_ag * m_ag; - float cosThetaM = dot(m_N, Hr); + float cosThetaM = dot(N, Hr); float cosThetaM2 = cosThetaM * cosThetaM; float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; float cosThetaM4 = cosThetaM2 * cosThetaM2; @@ -108,16 +112,16 @@ __device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderData *sd, const Sha return make_float3 (0, 0, 0); } -__device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { float m_ag = sc->data0; float m_eta = sc->data1; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; - float3 m_N = sd->N; + float3 N = sc->N; if(!m_refractive) return make_float3 (0, 0, 0); - float cosNO = dot(m_N, I); - float cosNI = dot(m_N, omega_in); + float cosNO = dot(N, I); + float cosNI = dot(N, omega_in); if(cosNO <= 0 || cosNI >= 0) return make_float3 (0, 0, 0); // vectors on same side -- not possible // compute half-vector of the refraction (eq. 16) @@ -128,7 +132,7 @@ __device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderData *sd, const Sh float cosHI = dot(Ht, omega_in); // eq. 33: first we calculate D(m) with m=Ht: float alpha2 = m_ag * m_ag; - float cosThetaM = dot(m_N, Ht); + float cosThetaM = dot(N, Ht); float cosThetaM2 = cosThetaM * cosThetaM; float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; float cosThetaM4 = cosThetaM2 * cosThetaM2; @@ -144,21 +148,15 @@ __device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderData *sd, const Sh return make_float3 (out, out, out); } -__device float bsdf_microfacet_ggx_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) -{ - return 1.0f; -} - -__device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +__device int bsdf_microfacet_ggx_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { float m_ag = sc->data0; - float m_eta = sc->data1; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; - float3 m_N = sd->N; + float3 N = sc->N; - float cosNO = dot(m_N, sd->I); + float cosNO = dot(N, I); if(cosNO > 0) { - float3 X, Y, Z = m_N; + float3 X, Y, Z = N; make_orthonormals(Z, &X, &Y); // generate a random microfacet normal m // eq. 35,36: @@ -173,11 +171,11 @@ __device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosur (sinf(phiM) * sinThetaM) * Y + cosThetaM * Z; if(!m_refractive) { - float cosMO = dot(m, sd->I); + float cosMO = dot(m, I); if(cosMO > 0) { // eq. 39 - compute actual reflected direction - *omega_in = 2 * cosMO * m - sd->I; - if(dot(sd->Ng, *omega_in) > 0) { + *omega_in = 2 * cosMO * m - I; + if(dot(Ng, *omega_in) > 0) { // microfacet normal is visible to this ray // eq. 33 float cosThetaM2 = cosThetaM * cosThetaM; @@ -190,7 +188,7 @@ __device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosur // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf *pdf = pm * 0.25f / cosMO; // eval BRDF*cosNI - float cosNI = dot(m_N, *omega_in); + float cosNI = dot(N, *omega_in); // eq. 34: now calculate G1(i,m) and G1(o,m) float G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); float G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); @@ -199,8 +197,8 @@ __device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosur float out = (G * D) * 0.25f / cosNO; *eval = make_float3(out, out, out); #ifdef __RAY_DIFFERENTIALS__ - *domega_in_dx = (2 * dot(m, sd->dI.dx)) * m - sd->dI.dx; - *domega_in_dy = (2 * dot(m, sd->dI.dy)) * m - sd->dI.dy; + *domega_in_dx = (2 * dot(m, dIdx)) * m - dIdx; + *domega_in_dy = (2 * dot(m, dIdy)) * m - dIdy; // Since there is some blur to this reflection, make the // derivatives a bit bigger. In theory this varies with the // roughness but the exact relationship is complex and @@ -218,10 +216,11 @@ __device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosur #ifdef __RAY_DIFFERENTIALS__ float3 dRdx, dRdy, dTdx, dTdy; #endif + float m_eta = sc->data1; bool inside; - fresnel_dielectric(m_eta, m, sd->I, &R, &T, + fresnel_dielectric(m_eta, m, I, &R, &T, #ifdef __RAY_DIFFERENTIALS__ - sd->dI.dx, sd->dI.dy, &dRdx, &dRdy, &dTdx, &dTdy, + dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy, #endif &inside); @@ -238,14 +237,14 @@ __device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosur // eq. 24 float pm = D * cosThetaM; // eval BRDF*cosNI - float cosNI = dot(m_N, *omega_in); + float cosNI = dot(N, *omega_in); // eq. 34: now calculate G1(i,m) and G1(o,m) float G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); float G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); float G = G1o * G1i; // eq. 21 float cosHI = dot(m, *omega_in); - float cosHO = dot(m, sd->I); + float cosHO = dot(m, I); float Ht2 = m_eta * cosHI + cosHO; Ht2 *= Ht2; float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2); @@ -268,26 +267,29 @@ __device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosur /* BECKMANN */ -typedef struct BsdfMicrofacetBeckmannClosure { - //float3 m_N; - float m_ab; - float m_eta; -} BsdfMicrofacetBeckmannClosure; +__device int bsdf_microfacet_beckmann_setup(ShaderClosure *sc) +{ + float ab = sc->data0; + float m_ab = clamp(ab, 1e-4f, 1.0f); -__device void bsdf_microfacet_beckmann_setup(ShaderData *sd, ShaderClosure *sc, float ab, float eta, bool refractive) + sc->data0 = m_ab; + + sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID; + return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; +} + +__device int bsdf_microfacet_beckmann_refraction_setup(ShaderClosure *sc) { + float ab = sc->data0; + float eta = sc->data1; float m_ab = clamp(ab, 1e-4f, 1.0f); float m_eta = eta; sc->data0 = m_ab; sc->data1 = m_eta; - if(refractive) - sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; - else - sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID; - - sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; + sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; + return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; } __device void bsdf_microfacet_beckmann_blur(ShaderClosure *sc, float roughness) @@ -297,23 +299,22 @@ __device void bsdf_microfacet_beckmann_blur(ShaderClosure *sc, float roughness) sc->data0 = m_ab; } -__device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { float m_ab = sc->data0; - //float m_eta = sc->data1; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; - float3 m_N = sd->N; + float3 N = sc->N; if(m_refractive) return make_float3 (0, 0, 0); - float cosNO = dot(m_N, I); - float cosNI = dot(m_N, omega_in); + float cosNO = dot(N, I); + float cosNI = dot(N, omega_in); if(cosNO > 0 && cosNI > 0) { // get half vector float3 Hr = normalize(omega_in + I); // eq. 20: (F*G*D)/(4*in*on) // eq. 25: first we calculate D(m) with m=Hr: float alpha2 = m_ab * m_ab; - float cosThetaM = dot(m_N, Hr); + float cosThetaM = dot(N, Hr); float cosThetaM2 = cosThetaM * cosThetaM; float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; float cosThetaM4 = cosThetaM2 * cosThetaM2; @@ -336,16 +337,16 @@ __device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderData *sd, cons return make_float3 (0, 0, 0); } -__device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { float m_ab = sc->data0; float m_eta = sc->data1; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; - float3 m_N = sd->N; + float3 N = sc->N; if(!m_refractive) return make_float3 (0, 0, 0); - float cosNO = dot(m_N, I); - float cosNI = dot(m_N, omega_in); + float cosNO = dot(N, I); + float cosNI = dot(N, omega_in); if(cosNO <= 0 || cosNI >= 0) return make_float3 (0, 0, 0); // compute half-vector of the refraction (eq. 16) @@ -356,7 +357,7 @@ __device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderData *sd, con float cosHI = dot(Ht, omega_in); // eq. 33: first we calculate D(m) with m=Ht: float alpha2 = m_ab * m_ab; - float cosThetaM = dot(m_N, Ht); + float cosThetaM = dot(N, Ht); float cosThetaM2 = cosThetaM * cosThetaM; float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; float cosThetaM4 = cosThetaM2 * cosThetaM2; @@ -374,21 +375,15 @@ __device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderData *sd, con return make_float3 (out, out, out); } -__device float bsdf_microfacet_beckmann_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) -{ - return 1.0f; -} - -__device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +__device int bsdf_microfacet_beckmann_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { float m_ab = sc->data0; - float m_eta = sc->data1; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; - float3 m_N = sd->N; + float3 N = sc->N; - float cosNO = dot(m_N, sd->I); + float cosNO = dot(N, I); if(cosNO > 0) { - float3 X, Y, Z = m_N; + float3 X, Y, Z = N; make_orthonormals(Z, &X, &Y); // generate a random microfacet normal m // eq. 35,36: @@ -404,11 +399,11 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderC cosThetaM * Z; if(!m_refractive) { - float cosMO = dot(m, sd->I); + float cosMO = dot(m, I); if(cosMO > 0) { // eq. 39 - compute actual reflected direction - *omega_in = 2 * cosMO * m - sd->I; - if(dot(sd->Ng, *omega_in) > 0) { + *omega_in = 2 * cosMO * m - I; + if(dot(Ng, *omega_in) > 0) { // microfacet normal is visible to this ray // eq. 25 float cosThetaM2 = cosThetaM * cosThetaM; @@ -422,7 +417,7 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderC // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf *pdf = pm * 0.25f / cosMO; // Eval BRDF*cosNI - float cosNI = dot(m_N, *omega_in); + float cosNI = dot(N, *omega_in); // eq. 26, 27: now calculate G1(i,m) and G1(o,m) float ao = 1 / (m_ab * safe_sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO))); float ai = 1 / (m_ab * safe_sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); @@ -433,8 +428,8 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderC float out = (G * D) * 0.25f / cosNO; *eval = make_float3(out, out, out); #ifdef __RAY_DIFFERENTIALS__ - *domega_in_dx = (2 * dot(m, sd->dI.dx)) * m - sd->dI.dx; - *domega_in_dy = (2 * dot(m, sd->dI.dy)) * m - sd->dI.dy; + *domega_in_dx = (2 * dot(m, dIdx)) * m - dIdx; + *domega_in_dy = (2 * dot(m, dIdy)) * m - dIdy; // Since there is some blur to this reflection, make the // derivatives a bit bigger. In theory this varies with the // roughness but the exact relationship is complex and @@ -452,10 +447,11 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderC #ifdef __RAY_DIFFERENTIALS__ float3 dRdx, dRdy, dTdx, dTdy; #endif + float m_eta = sc->data1; bool inside; - fresnel_dielectric(m_eta, m, sd->I, &R, &T, + fresnel_dielectric(m_eta, m, I, &R, &T, #ifdef __RAY_DIFFERENTIALS__ - sd->dI.dx, sd->dI.dy, &dRdx, &dRdy, &dTdx, &dTdy, + dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy, #endif &inside); @@ -474,7 +470,7 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderC // eq. 24 float pm = D * cosThetaM; // eval BRDF*cosNI - float cosNI = dot(m_N, *omega_in); + float cosNI = dot(N, *omega_in); // eq. 26, 27: now calculate G1(i,m) and G1(o,m) float ao = 1 / (m_ab * safe_sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO))); float ai = 1 / (m_ab * safe_sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); @@ -483,7 +479,7 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderC float G = G1o * G1i; // eq. 21 float cosHI = dot(m, *omega_in); - float cosHO = dot(m, sd->I); + float cosHO = dot(m, I); float Ht2 = m_eta * cosHI + cosHO; Ht2 *= Ht2; float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2); diff --git a/intern/cycles/kernel/svm/bsdf_oren_nayar.h b/intern/cycles/kernel/closure/bsdf_oren_nayar.h index a7edccdc423..066937da6eb 100644 --- a/intern/cycles/kernel/svm/bsdf_oren_nayar.h +++ b/intern/cycles/kernel/closure/bsdf_oren_nayar.h @@ -21,11 +21,6 @@ CCL_NAMESPACE_BEGIN -typedef struct BsdfOrenNayarClosure { - float m_a; - float m_b; -} BsdfOrenNayarClosure; - __device float3 bsdf_oren_nayar_get_intensity(const ShaderClosure *sc, float3 n, float3 v, float3 l) { float nl = max(dot(n, l), 0.0f); @@ -38,10 +33,11 @@ __device float3 bsdf_oren_nayar_get_intensity(const ShaderClosure *sc, float3 n, return make_float3(is, is, is); } -__device void bsdf_oren_nayar_setup(ShaderData *sd, ShaderClosure *sc, float sigma) +__device int bsdf_oren_nayar_setup(ShaderClosure *sc) { + float sigma = sc->data0; + sc->type = CLOSURE_BSDF_OREN_NAYAR_ID; - sd->flag |= SD_BSDF | SD_BSDF_HAS_EVAL; sigma = clamp(sigma, 0.0f, 1.0f); @@ -49,17 +45,19 @@ __device void bsdf_oren_nayar_setup(ShaderData *sd, ShaderClosure *sc, float sig sc->data0 = 1.0f * div; sc->data1 = sigma * div; + + return SD_BSDF | SD_BSDF_HAS_EVAL; } __device void bsdf_oren_nayar_blur(ShaderClosure *sc, float roughness) { } -__device float3 bsdf_oren_nayar_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_oren_nayar_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { - if (dot(sd->N, omega_in) > 0.0f) { + if (dot(sc->N, omega_in) > 0.0f) { *pdf = 0.5f * M_1_PI_F; - return bsdf_oren_nayar_get_intensity(sc, sd->N, I, omega_in); + return bsdf_oren_nayar_get_intensity(sc, sc->N, I, omega_in); } else { *pdf = 0.0f; @@ -67,27 +65,22 @@ __device float3 bsdf_oren_nayar_eval_reflect(const ShaderData *sd, const ShaderC } } -__device float3 bsdf_oren_nayar_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_oren_nayar_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float bsdf_oren_nayar_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) -{ - return 1.0f; -} - -__device int bsdf_oren_nayar_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +__device int bsdf_oren_nayar_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { - sample_uniform_hemisphere(sd->N, randu, randv, omega_in, pdf); + sample_uniform_hemisphere(sc->N, randu, randv, omega_in, pdf); - if (dot(sd->Ng, *omega_in) > 0.0f) { - *eval = bsdf_oren_nayar_get_intensity(sc, sd->N, sd->I, *omega_in); + if (dot(Ng, *omega_in) > 0.0f) { + *eval = bsdf_oren_nayar_get_intensity(sc, sc->N, I, *omega_in); #ifdef __RAY_DIFFERENTIALS__ // TODO: find a better approximation for the bounce - *domega_in_dx = (2.0f * dot(sd->N, sd->dI.dx)) * sd->N - sd->dI.dx; - *domega_in_dy = (2.0f * dot(sd->N, sd->dI.dy)) * sd->N - sd->dI.dy; + *domega_in_dx = (2.0f * dot(sc->N, dIdx)) * sc->N - dIdx; + *domega_in_dy = (2.0f * dot(sc->N, dIdy)) * sc->N - dIdy; *domega_in_dx *= 125.0f; *domega_in_dy *= 125.0f; #endif diff --git a/intern/cycles/kernel/closure/bsdf_phong_ramp.h b/intern/cycles/kernel/closure/bsdf_phong_ramp.h new file mode 100644 index 00000000000..a2df77c2d2b --- /dev/null +++ b/intern/cycles/kernel/closure/bsdf_phong_ramp.h @@ -0,0 +1,140 @@ +/* + * Adapted from Open Shading Language with this license: + * + * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. + * All Rights Reserved. + * + * Modifications Copyright 2012, Blender Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Sony Pictures Imageworks nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __BSDF_PHONG_RAMP_H__ +#define __BSDF_PHONG_RAMP_H__ + +CCL_NAMESPACE_BEGIN + +__device float3 bsdf_phong_ramp_get_color(const ShaderClosure *sc, const float3 colors[8], float pos) +{ + int MAXCOLORS = 8; + + float npos = pos * (float)(MAXCOLORS - 1); + int ipos = (int)npos; + if (ipos >= (MAXCOLORS - 1)) + return colors[MAXCOLORS - 1]; + float offset = npos - (float)ipos; + return colors[ipos] * (1.0f - offset) + colors[ipos+1] * offset; +} + +__device int bsdf_phong_ramp_setup(ShaderClosure *sc) +{ + sc->type = CLOSURE_BSDF_PHONG_RAMP_ID; + return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_GLOSSY; +} + +__device void bsdf_phong_ramp_blur(ShaderClosure *sc, float roughness) +{ +} + +__device float3 bsdf_phong_ramp_eval_reflect(const ShaderClosure *sc, const float3 colors[8], const float3 I, const float3 omega_in, float *pdf) +{ + float m_exponent = sc->data0; + float cosNI = dot(sc->N, omega_in); + float cosNO = dot(sc->N, I); + + if (cosNI > 0 && cosNO > 0) { + // reflect the view vector + float3 R = (2 * cosNO) * sc->N - I; + float cosRI = dot(R, omega_in); + if (cosRI > 0) { + float cosp = powf(cosRI, m_exponent); + float common = 0.5f * (float) M_1_PI_F * cosp; + float out = cosNI * (m_exponent + 2) * common; + *pdf = (m_exponent + 1) * common; + return bsdf_phong_ramp_get_color(sc, colors, cosp) * out; + } + } + + return make_float3(0.0f, 0.0f, 0.0f); +} + +__device float3 bsdf_phong_ramp_eval_transmit(const ShaderClosure *sc, const float3 colors[8], const float3 I, const float3 omega_in, float *pdf) +{ + return make_float3(0.0f, 0.0f, 0.0f); +} + +__device int bsdf_phong_ramp_sample(const ShaderClosure *sc, const float3 colors[8], float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +{ + float cosNO = dot(sc->N, I); + float m_exponent = sc->data0; + + if (cosNO > 0) { + // reflect the view vector + float3 R = (2 * cosNO) * sc->N - I; + +#ifdef __RAY_DIFFERENTIALS__ + *domega_in_dx = (2 * dot(sc->N, dIdx)) * sc->N - dIdx; + *domega_in_dy = (2 * dot(sc->N, dIdy)) * sc->N - dIdy; +#endif + + float3 T, B; + make_orthonormals (R, &T, &B); + float phi = 2 * M_PI_F * randu; + float cosTheta = powf(randv, 1 / (m_exponent + 1)); + float sinTheta2 = 1 - cosTheta * cosTheta; + float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0; + *omega_in = (cosf(phi) * sinTheta) * T + + (sinf(phi) * sinTheta) * B + + ( cosTheta) * R; + if (dot(Ng, *omega_in) > 0.0f) + { + // common terms for pdf and eval + float cosNI = dot(sc->N, *omega_in); + // make sure the direction we chose is still in the right hemisphere + if (cosNI > 0) + { + float cosp = powf(cosTheta, m_exponent); + float common = 0.5f * M_1_PI_F * cosp; + *pdf = (m_exponent + 1) * common; + float out = cosNI * (m_exponent + 2) * common; + *eval = bsdf_phong_ramp_get_color(sc, colors, cosp) * out; + +#ifdef __RAY_DIFFERENTIALS__ + // Since there is some blur to this reflection, make the + // derivatives a bit bigger. In theory this varies with the + // exponent but the exact relationship is complex and + // requires more ops than are practical. + *domega_in_dx *= 10; + *domega_in_dy *= 10; +#endif + } + } + } + return LABEL_REFLECT; +} + + +CCL_NAMESPACE_END + +#endif /* __BSDF_PHONG_RAMP_H__ */ diff --git a/intern/cycles/kernel/svm/bsdf_reflection.h b/intern/cycles/kernel/closure/bsdf_reflection.h index 09b4e0e48f0..9356f950d98 100644 --- a/intern/cycles/kernel/svm/bsdf_reflection.h +++ b/intern/cycles/kernel/closure/bsdf_reflection.h @@ -37,48 +37,39 @@ CCL_NAMESPACE_BEGIN /* REFLECTION */ -typedef struct BsdfReflectionClosure { - //float3 m_N; -} BsdfReflectionClosure; - -__device void bsdf_reflection_setup(ShaderData *sd, ShaderClosure *sc) +__device int bsdf_reflection_setup(ShaderClosure *sc) { sc->type = CLOSURE_BSDF_REFLECTION_ID; - sd->flag |= SD_BSDF; + return SD_BSDF; } __device void bsdf_reflection_blur(ShaderClosure *sc, float roughness) { } -__device float3 bsdf_reflection_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_reflection_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float3 bsdf_reflection_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_reflection_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float bsdf_reflection_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) -{ - return 1.0f; -} - -__device int bsdf_reflection_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +__device int bsdf_reflection_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { //const BsdfReflectionClosure *self = (const BsdfReflectionClosure*)sc->data; - float3 m_N = sd->N; + float3 N = sc->N; // only one direction is possible - float cosNO = dot(m_N, sd->I); + float cosNO = dot(N, I); if(cosNO > 0) { - *omega_in = (2 * cosNO) * m_N - sd->I; - if(dot(sd->Ng, *omega_in) > 0) { + *omega_in = (2 * cosNO) * N - I; + if(dot(Ng, *omega_in) > 0) { #ifdef __RAY_DIFFERENTIALS__ - *domega_in_dx = 2 * dot(m_N, sd->dI.dx) * m_N - sd->dI.dx; - *domega_in_dy = 2 * dot(m_N, sd->dI.dy) * m_N - sd->dI.dy; + *domega_in_dx = 2 * dot(N, dIdx) * N - dIdx; + *domega_in_dy = 2 * dot(N, dIdy) * N - dIdy; #endif *pdf = 1; *eval = make_float3(1, 1, 1); diff --git a/intern/cycles/kernel/svm/bsdf_refraction.h b/intern/cycles/kernel/closure/bsdf_refraction.h index c9c268999c0..ef79d6cc259 100644 --- a/intern/cycles/kernel/svm/bsdf_refraction.h +++ b/intern/cycles/kernel/closure/bsdf_refraction.h @@ -37,50 +37,39 @@ CCL_NAMESPACE_BEGIN /* REFRACTION */ -typedef struct BsdfRefractionClosure { - float m_eta; -} BsdfRefractionClosure; - -__device void bsdf_refraction_setup(ShaderData *sd, ShaderClosure *sc, float eta) +__device int bsdf_refraction_setup(ShaderClosure *sc) { - sc->data0 = eta; - sc->type = CLOSURE_BSDF_REFRACTION_ID; - sd->flag |= SD_BSDF; + return SD_BSDF; } __device void bsdf_refraction_blur(ShaderClosure *sc, float roughness) { } -__device float3 bsdf_refraction_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_refraction_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float3 bsdf_refraction_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_refraction_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float bsdf_refraction_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) -{ - return 1.0f; -} - -__device int bsdf_refraction_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +__device int bsdf_refraction_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { float m_eta = sc->data0; - float3 m_N = sd->N; + float3 N = sc->N; float3 R, T; #ifdef __RAY_DIFFERENTIALS__ float3 dRdx, dRdy, dTdx, dTdy; #endif bool inside; - fresnel_dielectric(m_eta, m_N, sd->I, &R, &T, + fresnel_dielectric(m_eta, N, I, &R, &T, #ifdef __RAY_DIFFERENTIALS__ - sd->dI.dx, sd->dI.dy, &dRdx, &dRdy, &dTdx, &dTdy, + dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy, #endif &inside); diff --git a/intern/cycles/kernel/svm/bsdf_transparent.h b/intern/cycles/kernel/closure/bsdf_transparent.h index 511836cdfa2..81bc7690b50 100644 --- a/intern/cycles/kernel/svm/bsdf_transparent.h +++ b/intern/cycles/kernel/closure/bsdf_transparent.h @@ -35,38 +35,33 @@ CCL_NAMESPACE_BEGIN -__device void bsdf_transparent_setup(ShaderData *sd, ShaderClosure *sc) +__device int bsdf_transparent_setup(ShaderClosure *sc) { sc->type = CLOSURE_BSDF_TRANSPARENT_ID; - sd->flag |= SD_BSDF; + return SD_BSDF; } __device void bsdf_transparent_blur(ShaderClosure *sc, float roughness) { } -__device float3 bsdf_transparent_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_transparent_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float3 bsdf_transparent_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_transparent_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float bsdf_transparent_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) -{ - return 1.0f; -} - -__device int bsdf_transparent_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +__device int bsdf_transparent_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { // only one direction is possible - *omega_in = -sd->I; + *omega_in = -I; #ifdef __RAY_DIFFERENTIALS__ - *domega_in_dx = -sd->dI.dx; - *domega_in_dy = -sd->dI.dy; + *domega_in_dx = -dIdx; + *domega_in_dy = -dIdy; #endif *pdf = 1; *eval = make_float3(1, 1, 1); diff --git a/intern/cycles/kernel/svm/bsdf_ward.h b/intern/cycles/kernel/closure/bsdf_ward.h index 6ae45948a73..dbddcf20dba 100644 --- a/intern/cycles/kernel/svm/bsdf_ward.h +++ b/intern/cycles/kernel/closure/bsdf_ward.h @@ -37,23 +37,19 @@ CCL_NAMESPACE_BEGIN /* WARD */ -typedef struct BsdfWardClosure { - //float3 m_N; - //float3 m_T; - float m_ax; - float m_ay; -} BsdfWardClosure; - -__device void bsdf_ward_setup(ShaderData *sd, ShaderClosure *sc, float3 T, float ax, float ay) +__device int bsdf_ward_setup(ShaderClosure *sc) { - float m_ax = clamp(ax, 1e-5f, 1.0f); - float m_ay = clamp(ay, 1e-5f, 1.0f); + float ax = sc->data0; + float ay = sc->data1; + + float m_ax = clamp(ax, 1e-4f, 1.0f); + float m_ay = clamp(ay, 1e-4f, 1.0f); sc->data0 = m_ax; sc->data1 = m_ay; sc->type = CLOSURE_BSDF_WARD_ID; - sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; + return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; } __device void bsdf_ward_blur(ShaderClosure *sc, float roughness) @@ -62,25 +58,28 @@ __device void bsdf_ward_blur(ShaderClosure *sc, float roughness) sc->data1 = fmaxf(roughness, sc->data1); } -__device float3 bsdf_ward_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_ward_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { float m_ax = sc->data0; float m_ay = sc->data1; - float3 m_N = sd->N; - float3 m_T = normalize(sd->dPdu); + float3 N = sc->N; + float3 T = sc->T; + + float cosNO = dot(N, I); + float cosNI = dot(N, omega_in); - float cosNO = dot(m_N, I); - float cosNI = dot(m_N, omega_in); + if(cosNI > 0.0f && cosNO > 0.0f) { + cosNO = max(cosNO, 1e-4f); + cosNI = max(cosNI, 1e-4f); - if(cosNI > 0 && cosNO > 0) { // get half vector and get x,y basis on the surface for anisotropy float3 H = normalize(omega_in + I); // normalize needed for pdf float3 X, Y; - make_orthonormals_tangent(m_N, m_T, &X, &Y); + make_orthonormals_tangent(N, T, &X, &Y); // eq. 4 float dotx = dot(H, X) / m_ax; float doty = dot(H, Y) / m_ay; - float dotn = dot(H, m_N); + float dotn = dot(H, N); float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn); float denom = (4 * M_PI_F * m_ax * m_ay * sqrtf(cosNO * cosNI)); float exp_val = expf(-exp_arg); @@ -90,31 +89,27 @@ __device float3 bsdf_ward_eval_reflect(const ShaderData *sd, const ShaderClosure *pdf = exp_val / denom; return make_float3 (out, out, out); } + return make_float3 (0, 0, 0); } -__device float3 bsdf_ward_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_ward_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float bsdf_ward_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) -{ - return 1.0f; -} - -__device int bsdf_ward_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +__device int bsdf_ward_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { float m_ax = sc->data0; float m_ay = sc->data1; - float3 m_N = sd->N; - float3 m_T = normalize(sd->dPdu); + float3 N = sc->N; + float3 T = sc->T; - float cosNO = dot(m_N, sd->I); - if(cosNO > 0) { + float cosNO = dot(N, I); + if(cosNO > 0.0f) { // get x,y basis on the surface for anisotropy float3 X, Y; - make_orthonormals_tangent(m_N, m_T, &X, &Y); + make_orthonormals_tangent(N, T, &X, &Y); // generate random angles for the half vector // eq. 7 (taking care around discontinuities to keep //ttoutput angle in the right quadrant) @@ -166,13 +161,16 @@ __device int bsdf_ward_sample(const ShaderData *sd, const ShaderClosure *sc, flo float doty = h.y / m_ay; float dotn = h.z; // transform to world space - h = h.x * X + h.y * Y + h.z * m_N; + h = h.x * X + h.y * Y + h.z * N; // generate the final sample - float oh = dot(h, sd->I); - *omega_in = 2.0f * oh * h - sd->I; - if(dot(sd->Ng, *omega_in) > 0) { - float cosNI = dot(m_N, *omega_in); + float oh = dot(h, I); + *omega_in = 2.0f * oh * h - I; + if(dot(Ng, *omega_in) > 0) { + float cosNI = dot(N, *omega_in); if(cosNI > 0) { + cosNO = max(cosNO, 1e-4f); + cosNI = max(cosNI, 1e-4f); + // eq. 9 float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn); float denom = 4 * M_PI_F * m_ax * m_ay * oh * dotn * dotn * dotn; @@ -182,8 +180,8 @@ __device int bsdf_ward_sample(const ShaderData *sd, const ShaderClosure *sc, flo float power = cosNI * expf(-exp_arg) / denom; *eval = make_float3(power, power, power); #ifdef __RAY_DIFFERENTIALS__ - *domega_in_dx = (2 * dot(m_N, sd->dI.dx)) * m_N - sd->dI.dx; - *domega_in_dy = (2 * dot(m_N, sd->dI.dy)) * m_N - sd->dI.dy; + *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx; + *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy; // Since there is some blur to this reflection, make the // derivatives a bit bigger. In theory this varies with the // roughness but the exact relationship is complex and diff --git a/intern/cycles/kernel/svm/bsdf_westin.h b/intern/cycles/kernel/closure/bsdf_westin.h index 3e7c27f44a4..968173208b4 100644 --- a/intern/cycles/kernel/svm/bsdf_westin.h +++ b/intern/cycles/kernel/closure/bsdf_westin.h @@ -37,19 +37,16 @@ CCL_NAMESPACE_BEGIN /* WESTIN BACKSCATTER */ -typedef struct BsdfWestinBackscatterClosure { - //float3 m_N; - float m_invroughness; -} BsdfWestinBackscatterClosure; - -__device void bsdf_westin_backscatter_setup(ShaderData *sd, ShaderClosure *sc, float roughness) +__device int bsdf_westin_backscatter_setup(ShaderClosure *sc) { + float roughness = sc->data0; roughness = clamp(roughness, 1e-5f, 1.0f); float m_invroughness = 1.0f/roughness; sc->type = CLOSURE_BSDF_WESTIN_BACKSCATTER_ID; - sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; sc->data0 = m_invroughness; + + return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; } __device void bsdf_westin_backscatter_blur(ShaderClosure *sc, float roughness) @@ -59,14 +56,14 @@ __device void bsdf_westin_backscatter_blur(ShaderClosure *sc, float roughness) sc->data0 = m_invroughness; } -__device float3 bsdf_westin_backscatter_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_westin_backscatter_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { float m_invroughness = sc->data0; - float3 m_N = sd->N; + float3 N = sc->N; // pdf is implicitly 0 (no indirect sampling) - float cosNO = dot(m_N, I); - float cosNI = dot(m_N, omega_in); + float cosNO = dot(N, I); + float cosNI = dot(N, omega_in); if(cosNO > 0 && cosNI > 0) { float cosine = dot(I, omega_in); *pdf = cosine > 0 ? (m_invroughness + 1) * powf(cosine, m_invroughness) : 0; @@ -76,40 +73,35 @@ __device float3 bsdf_westin_backscatter_eval_reflect(const ShaderData *sd, const return make_float3 (0, 0, 0); } -__device float3 bsdf_westin_backscatter_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_westin_backscatter_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float bsdf_westin_backscatter_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) -{ - return 1.0f; -} - -__device int bsdf_westin_backscatter_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +__device int bsdf_westin_backscatter_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { float m_invroughness = sc->data0; - float3 m_N = sd->N; + float3 N = sc->N; - float cosNO = dot(m_N, sd->I); + float cosNO = dot(N, I); if(cosNO > 0) { #ifdef __RAY_DIFFERENTIALS__ - *domega_in_dx = sd->dI.dx; - *domega_in_dy = sd->dI.dy; + *domega_in_dx = dIdx; + *domega_in_dy = dIdy; #endif float3 T, B; - make_orthonormals (sd->I, &T, &B); + make_orthonormals (I, &T, &B); float phi = 2 * M_PI_F * randu; float cosTheta = powf(randv, 1 / (m_invroughness + 1)); float sinTheta2 = 1 - cosTheta * cosTheta; float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0; *omega_in = (cosf(phi) * sinTheta) * T + (sinf(phi) * sinTheta) * B + - (cosTheta) * sd->I; - if(dot(sd->Ng, *omega_in) > 0) + (cosTheta) * I; + if(dot(Ng, *omega_in) > 0) { // common terms for pdf and eval - float cosNI = dot(m_N, *omega_in); + float cosNI = dot(N, *omega_in); // make sure the direction we chose is still in the right hemisphere if(cosNI > 0) { @@ -132,30 +124,26 @@ __device int bsdf_westin_backscatter_sample(const ShaderData *sd, const ShaderCl /* WESTIN SHEEN */ -typedef struct BsdfWestinSheenClosure { - //float3 m_N; - float m_edginess; -} BsdfWestinSheenClosure; - -__device void bsdf_westin_sheen_setup(ShaderData *sd, ShaderClosure *sc, float edginess) +__device int bsdf_westin_sheen_setup(ShaderClosure *sc) { + float edginess = sc->data0; sc->type = CLOSURE_BSDF_WESTIN_SHEEN_ID; - sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; sc->data0 = edginess; + return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; } __device void bsdf_westin_sheen_blur(ShaderClosure *sc, float roughness) { } -__device float3 bsdf_westin_sheen_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_westin_sheen_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { float m_edginess = sc->data0; - float3 m_N = sd->N; + float3 N = sc->N; // pdf is implicitly 0 (no indirect sampling) - float cosNO = dot(m_N, I); - float cosNI = dot(m_N, omega_in); + float cosNO = dot(N, I); + float cosNI = dot(N, omega_in); if(cosNO > 0 && cosNI > 0) { float sinNO2 = 1 - cosNO * cosNO; *pdf = cosNI * M_1_PI_F; @@ -165,34 +153,29 @@ __device float3 bsdf_westin_sheen_eval_reflect(const ShaderData *sd, const Shade return make_float3 (0, 0, 0); } -__device float3 bsdf_westin_sheen_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_westin_sheen_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float bsdf_westin_sheen_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) -{ - return 1.0f; -} - -__device int bsdf_westin_sheen_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +__device int bsdf_westin_sheen_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { float m_edginess = sc->data0; - float3 m_N = sd->N; + float3 N = sc->N; // we are viewing the surface from the right side - send a ray out with cosine // distribution over the hemisphere - sample_cos_hemisphere(m_N, randu, randv, omega_in, pdf); - if(dot(sd->Ng, *omega_in) > 0) { + sample_cos_hemisphere(N, randu, randv, omega_in, pdf); + if(dot(Ng, *omega_in) > 0) { // TODO: account for sheen when sampling - float cosNO = dot(m_N, sd->I); + float cosNO = dot(N, I); float sinNO2 = 1 - cosNO * cosNO; float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * (*pdf) : 0; *eval = make_float3(westin, westin, westin); #ifdef __RAY_DIFFERENTIALS__ // TODO: find a better approximation for the diffuse bounce - *domega_in_dx = (2 * dot(m_N, sd->dI.dx)) * m_N - sd->dI.dx; - *domega_in_dy = (2 * dot(m_N, sd->dI.dy)) * m_N - sd->dI.dy; + *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx; + *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy; *domega_in_dx *= 125.0f; *domega_in_dy *= 125.0f; #endif diff --git a/intern/cycles/kernel/svm/emissive.h b/intern/cycles/kernel/closure/emissive.h index 9a906f82963..cbf9d9a4efb 100644 --- a/intern/cycles/kernel/svm/emissive.h +++ b/intern/cycles/kernel/closure/emissive.h @@ -34,15 +34,21 @@ CCL_NAMESPACE_BEGIN /* EMISSION CLOSURE */ -/// Return the probability distribution function in the direction I, -/// given the parameters and the light's surface normal. This MUST match -/// the PDF computed by sample(). +/* return the probability distribution function in the direction I, + * given the parameters and the light's surface normal. This MUST match + * the PDF computed by sample(). */ __device float emissive_pdf(const float3 Ng, const float3 I) { float cosNO = fabsf(dot(Ng, I)); return (cosNO > 0.0f)? 1.0f: 0.0f; } +__device void emissive_sample(const float3 Ng, float randu, float randv, + float3 *omega_out, float *pdf) +{ + /* todo: not implemented and used yet */ +} + __device float3 emissive_eval(const float3 Ng, const float3 I) { float res = emissive_pdf(Ng, I); diff --git a/intern/cycles/kernel/svm/volume.h b/intern/cycles/kernel/closure/volume.h index 10e9c5de352..734f9111ab6 100644 --- a/intern/cycles/kernel/svm/volume.h +++ b/intern/cycles/kernel/closure/volume.h @@ -23,44 +23,46 @@ CCL_NAMESPACE_BEGIN /* ISOTROPIC VOLUME CLOSURE */ -__device void volume_isotropic_setup(ShaderData *sd, ShaderClosure *sc, float density) +__device int volume_isotropic_setup(ShaderClosure *sc, float density) { sc->type = CLOSURE_VOLUME_ISOTROPIC_ID; - sd->flag |= SD_VOLUME; sc->data0 = density; + + return SD_VOLUME; } -__device float3 volume_isotropic_eval_phase(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) +__device float3 volume_isotropic_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) { return make_float3(1.0f, 1.0f, 1.0f); } /* TRANSPARENT VOLUME CLOSURE */ -__device void volume_transparent_setup(ShaderData *sd, ShaderClosure *sc, float density) +__device int volume_transparent_setup(ShaderClosure *sc, float density) { sc->type = CLOSURE_VOLUME_TRANSPARENT_ID; - sd->flag |= SD_VOLUME; sc->data0 = density; + + return SD_VOLUME; } -__device float3 volume_transparent_eval_phase(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) +__device float3 volume_transparent_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) { return make_float3(1.0f, 1.0f, 1.0f); } /* VOLUME CLOSURE */ -__device float3 volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) +__device float3 volume_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) { float3 eval; switch(sc->type) { case CLOSURE_VOLUME_ISOTROPIC_ID: - eval = volume_isotropic_eval_phase(sd, sc, omega_in, omega_out); + eval = volume_isotropic_eval_phase(sc, omega_in, omega_out); break; case CLOSURE_VOLUME_TRANSPARENT_ID: - eval = volume_transparent_eval_phase(sd, sc, omega_in, omega_out); + eval = volume_transparent_eval_phase(sc, omega_in, omega_out); break; default: eval = make_float3(0.0f, 0.0f, 0.0f); diff --git a/intern/cycles/kernel/kernel_attribute.h b/intern/cycles/kernel/kernel_attribute.h index 115de2fdbdb..2774f5e924b 100644 --- a/intern/cycles/kernel/kernel_attribute.h +++ b/intern/cycles/kernel/kernel_attribute.h @@ -59,7 +59,7 @@ __device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id) attr_map = kernel_tex_fetch(__attributes_map, ++attr_offset); /* return result */ - return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : attr_map.z; + return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z; } } diff --git a/intern/cycles/kernel/kernel_bvh.h b/intern/cycles/kernel/kernel_bvh.h index 34a44af8b8d..d70485fd6cf 100644 --- a/intern/cycles/kernel/kernel_bvh.h +++ b/intern/cycles/kernel/kernel_bvh.h @@ -57,7 +57,7 @@ __device_inline float3 bvh_inverse_direction(float3 dir) __device_inline void bvh_instance_push(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *idir, float *t, const float tmax) { - Transform tfm = object_fetch_transform(kg, object, ray->time, OBJECT_INVERSE_TRANSFORM); + Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); *P = transform_point(&tfm, ray->P); @@ -75,7 +75,7 @@ __device_inline void bvh_instance_push(KernelGlobals *kg, int object, const Ray __device_inline void bvh_instance_pop(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *idir, float *t, const float tmax) { if(*t != FLT_MAX) { - Transform tfm = object_fetch_transform(kg, object, ray->time, OBJECT_TRANSFORM); + Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); *t *= len(transform_direction(&tfm, 1.0f/(*idir))); } @@ -83,6 +83,35 @@ __device_inline void bvh_instance_pop(KernelGlobals *kg, int object, const Ray * *idir = bvh_inverse_direction(ray->D); } +#ifdef __OBJECT_MOTION__ +__device_inline void bvh_instance_motion_push(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *idir, float *t, Transform *tfm, const float tmax) +{ + Transform itfm; + *tfm = object_fetch_transform_motion_test(kg, object, ray->time, &itfm); + + *P = transform_point(&itfm, ray->P); + + float3 dir = transform_direction(&itfm, ray->D); + + float len; + dir = normalize_len(dir, &len); + + *idir = bvh_inverse_direction(dir); + + if(*t != FLT_MAX) + *t *= len; +} + +__device_inline void bvh_instance_motion_pop(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *idir, float *t, Transform *tfm, const float tmax) +{ + if(*t != FLT_MAX) + *t *= len(transform_direction(tfm, 1.0f/(*idir))); + + *P = ray->P; + *idir = bvh_inverse_direction(ray->D); +} +#endif + /* intersect two bounding boxes */ __device_inline void bvh_node_intersect(KernelGlobals *kg, bool *traverseChild0, bool *traverseChild1, @@ -176,7 +205,7 @@ __device_inline void bvh_triangle_intersect(KernelGlobals *kg, Intersection *ise } } -__device_inline bool scene_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect) +__device_inline bool bvh_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect) { /* traversal stack in CUDA thread-local memory */ int traversalStack[BVH_STACK_SIZE]; @@ -268,7 +297,6 @@ __device_inline bool scene_intersect(KernelGlobals *kg, const Ray *ray, const ui else { /* instance push */ object = kernel_tex_fetch(__prim_object, -primAddr-1); - bvh_instance_push(kg, object, ray, &P, &idir, &isect->t, tmax); ++stackPtr; @@ -296,6 +324,135 @@ __device_inline bool scene_intersect(KernelGlobals *kg, const Ray *ray, const ui return (isect->prim != ~0); } +#ifdef __OBJECT_MOTION__ +__device_inline bool bvh_intersect_motion(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect) +{ + /* traversal stack in CUDA thread-local memory */ + int traversalStack[BVH_STACK_SIZE]; + traversalStack[0] = ENTRYPOINT_SENTINEL; + + /* traversal variables in registers */ + int stackPtr = 0; + int nodeAddr = kernel_data.bvh.root; + + /* ray parameters in registers */ + const float tmax = ray->t; + float3 P = ray->P; + float3 idir = bvh_inverse_direction(ray->D); + int object = ~0; + + Transform ob_tfm; + + isect->t = tmax; + isect->object = ~0; + isect->prim = ~0; + isect->u = 0.0f; + isect->v = 0.0f; + + /* traversal loop */ + do { + do + { + /* traverse internal nodes */ + while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) + { + bool traverseChild0, traverseChild1, closestChild1; + int nodeAddrChild1; + + bvh_node_intersect(kg, &traverseChild0, &traverseChild1, + &closestChild1, &nodeAddr, &nodeAddrChild1, + P, idir, isect->t, visibility, nodeAddr); + + if(traverseChild0 != traverseChild1) { + /* one child was intersected */ + if(traverseChild1) { + nodeAddr = nodeAddrChild1; + } + } + else { + if(!traverseChild0) { + /* neither child was intersected */ + nodeAddr = traversalStack[stackPtr]; + --stackPtr; + } + else { + /* both children were intersected, push the farther one */ + if(closestChild1) { + int tmp = nodeAddr; + nodeAddr = nodeAddrChild1; + nodeAddrChild1 = tmp; + } + + ++stackPtr; + traversalStack[stackPtr] = nodeAddrChild1; + } + } + } + + /* if node is leaf, fetch triangle list */ + if(nodeAddr < 0) { + float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_NODE_SIZE+(BVH_NODE_SIZE-1)); + int primAddr = __float_as_int(leaf.x); + + if(primAddr >= 0) { + int primAddr2 = __float_as_int(leaf.y); + + /* pop */ + nodeAddr = traversalStack[stackPtr]; + --stackPtr; + + /* triangle intersection */ + while(primAddr < primAddr2) { + /* intersect ray against triangle */ + bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr); + + /* shadow ray early termination */ + if(visibility == PATH_RAY_SHADOW_OPAQUE && isect->prim != ~0) + return true; + + primAddr++; + } + } + else { + /* instance push */ + object = kernel_tex_fetch(__prim_object, -primAddr-1); + bvh_instance_motion_push(kg, object, ray, &P, &idir, &isect->t, &ob_tfm, tmax); + + ++stackPtr; + traversalStack[stackPtr] = ENTRYPOINT_SENTINEL; + + nodeAddr = kernel_tex_fetch(__object_node, object); + } + } + } while(nodeAddr != ENTRYPOINT_SENTINEL); + + if(stackPtr >= 0) { + kernel_assert(object != ~0); + + /* instance pop */ + bvh_instance_motion_pop(kg, object, ray, &P, &idir, &isect->t, &ob_tfm, tmax); + object = ~0; + nodeAddr = traversalStack[stackPtr]; + --stackPtr; + } + } while(nodeAddr != ENTRYPOINT_SENTINEL); + + return (isect->prim != ~0); +} +#endif + +__device_inline bool scene_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect) +{ +#ifdef __OBJECT_MOTION__ + if(kernel_data.bvh.have_motion) + return bvh_intersect_motion(kg, ray, visibility, isect); + else + return bvh_intersect(kg, ray, visibility, isect); +#else + return bvh_intersect(kg, ray, visibility, isect); +#endif +} + __device_inline float3 ray_offset(float3 P, float3 Ng) { #ifdef __INTERSECTION_REFINE__ @@ -349,10 +506,10 @@ __device_inline float3 bvh_triangle_refine(KernelGlobals *kg, ShaderData *sd, co #ifdef __INTERSECTION_REFINE__ if(isect->object != ~0) { -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ Transform tfm = sd->ob_itfm; #else - Transform tfm = object_fetch_transform(kg, isect->object, ray->time, OBJECT_INVERSE_TRANSFORM); + Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM); #endif P = transform_point(&tfm, P); @@ -370,10 +527,10 @@ __device_inline float3 bvh_triangle_refine(KernelGlobals *kg, ShaderData *sd, co P = P + D*rt; if(isect->object != ~0) { -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ Transform tfm = sd->ob_tfm; #else - Transform tfm = object_fetch_transform(kg, isect->object, ray->time, OBJECT_TRANSFORM); + Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM); #endif P = transform_point(&tfm, P); diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h index 7fa987197c9..1b2fe8c56ee 100644 --- a/intern/cycles/kernel/kernel_camera.h +++ b/intern/cycles/kernel/kernel_camera.h @@ -63,7 +63,7 @@ __device void camera_sample_perspective(KernelGlobals *kg, float raster_x, float /* transform ray from camera to world */ Transform cameratoworld = kernel_data.cam.cameratoworld; -#ifdef __MOTION__ +#ifdef __CAMERA_MOTION__ if(kernel_data.cam.have_motion) transform_motion_interpolate(&cameratoworld, &kernel_data.cam.motion, ray->time); #endif @@ -106,7 +106,7 @@ __device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, floa /* transform ray from camera to world */ Transform cameratoworld = kernel_data.cam.cameratoworld; -#ifdef __MOTION__ +#ifdef __CAMERA_MOTION__ if(kernel_data.cam.have_motion) transform_motion_interpolate(&cameratoworld, &kernel_data.cam.motion, ray->time); #endif @@ -180,7 +180,7 @@ __device void camera_sample_panorama(KernelGlobals *kg, float raster_x, float ra /* transform ray from camera to world */ Transform cameratoworld = kernel_data.cam.cameratoworld; -#ifdef __MOTION__ +#ifdef __CAMERA_MOTION__ if(kernel_data.cam.have_motion) transform_motion_interpolate(&cameratoworld, &kernel_data.cam.motion, ray->time); #endif @@ -212,12 +212,12 @@ __device void camera_sample(KernelGlobals *kg, int x, int y, float filter_u, flo float raster_x = x + kernel_tex_interp(__filter_table, filter_u, FILTER_TABLE_SIZE); float raster_y = y + kernel_tex_interp(__filter_table, filter_v, FILTER_TABLE_SIZE); -#ifdef __MOTION__ +#ifdef __CAMERA_MOTION__ /* motion blur */ if(kernel_data.cam.shuttertime == 0.0f) ray->time = TIME_INVALID; else - ray->time = 0.5f + (time - 0.5f)*kernel_data.cam.shuttertime; + ray->time = 0.5f + 0.5f*(time - 0.5f)*kernel_data.cam.shuttertime; #endif /* sample */ diff --git a/intern/cycles/kernel/kernel_displace.h b/intern/cycles/kernel/kernel_displace.h index 6461a1eea38..a55f7a7fd75 100644 --- a/intern/cycles/kernel/kernel_displace.h +++ b/intern/cycles/kernel/kernel_displace.h @@ -47,6 +47,9 @@ __device void kernel_shader_evaluate(KernelGlobals *kg, uint4 *input, float4 *ou ray.P = make_float3(0.0f, 0.0f, 0.0f); ray.D = equirectangular_to_direction(u, v); ray.t = 0.0f; +#ifdef __CAMERA_MOTION__ + ray.time = 0.5f; +#endif #ifdef __RAY_DIFFERENTIALS__ ray.dD.dx = make_float3(0.0f, 0.0f, 0.0f); diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index 53d53b4bedd..6d650a0158d 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -32,8 +32,15 @@ __device float3 direct_emissive_eval(KernelGlobals *kg, float rando, Ray ray; ray.D = ls->D; ray.P = ls->P; + ray.t = 1.0f; +#ifdef __OBJECT_MOTION__ + ray.time = time; +#endif ray.dP.dx = make_float3(0.0f, 0.0f, 0.0f); ray.dP.dy = make_float3(0.0f, 0.0f, 0.0f); +#ifdef __CAMERA_MOTION__ + ray.time = time; +#endif shader_setup_from_background(kg, &sd, &ray); eval = shader_eval_background(kg, &sd, 0); } diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index 1084415d0cf..2791b3abbb6 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -301,8 +301,13 @@ __device void triangle_light_sample(KernelGlobals *kg, int prim, int object, #ifdef __INSTANCING__ /* instance transform */ if(ls->object >= 0) { - Transform tfm = object_fetch_transform(kg, ls->object, time, OBJECT_TRANSFORM); - Transform itfm = object_fetch_transform(kg, ls->object, time, OBJECT_INVERSE_TRANSFORM); +#ifdef __OBJECT_MOTION__ + Transform itfm; + Transform tfm = object_fetch_transform_motion_test(kg, object, time, &itfm); +#else + Transform tfm = object_fetch_transform(kg, ls->object, OBJECT_TRANSFORM); + Transform itfm = object_fetch_transform(kg, ls->object, OBJECT_INVERSE_TRANSFORM); +#endif ls->P = transform_point(&tfm, ls->P); ls->Ng = normalize(transform_direction_transposed(&itfm, ls->Ng)); diff --git a/intern/cycles/kernel/kernel_mbvh.h b/intern/cycles/kernel/kernel_mbvh.h deleted file mode 100644 index ccbd3d069b4..00000000000 --- a/intern/cycles/kernel/kernel_mbvh.h +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -CCL_NAMESPACE_BEGIN - -#define MBVH_OBJECT_SENTINEL 0x76543210 -#define MBVH_NODE_SIZE 8 -#define MBVH_STACK_SIZE 1024 -#define MBVH_RAY_STACK_SIZE 10000 - -typedef struct MBVHTask { - int node; - int index; - int num; - int object; -} MBVHTask; - -typedef struct MVBHRay { - float3 P; - float u; - float3 idir; - float v; - float t; - int index; - int object; - - float3 origP; - float3 origD; - float tmax; -} MBVHRay; - -__device float3 mbvh_inverse_direction(float3 dir) -{ - // Avoid divide by zero (ooeps = exp2f(-80.0f)) - float ooeps = 0.00000000000000000000000082718061255302767487140869206996285356581211090087890625f; - float3 idir; - - idir.x = 1.0f / (fabsf(dir.x) > ooeps ? dir.x : copysignf(ooeps, dir.x)); - idir.y = 1.0f / (fabsf(dir.y) > ooeps ? dir.y : copysignf(ooeps, dir.y)); - idir.z = 1.0f / (fabsf(dir.z) > ooeps ? dir.z : copysignf(ooeps, dir.z)); - - return idir; -} - -__device void mbvh_instance_push(KernelGlobals *kg, int object, MBVHRay *ray) -{ - Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); - - ray->P = transform_point(&tfm, ray->origP); - - float3 dir = ray->origD; - - if(ray->t != ray->tmax) dir *= ray->t; - - dir = transform_direction(&tfm, dir); - ray->idir = mbvh_inverse_direction(normalize(dir)); - - if(ray->t != ray->tmax) ray->t = len(dir); -} - -__device void mbvh_instance_pop(KernelGlobals *kg, int object, MBVHRay *ray) -{ - Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); - - if(ray->t != ray->tmax) - ray->t = len(transform_direction(&tfm, (1.0f/(ray->idir)) * (ray->t))); - - ray->P = ray->origP; - ray->idir = mbvh_inverse_direction(ray->origD); -} - -/* Sven Woop's algorithm */ -__device void mbvh_triangle_intersect(KernelGlobals *kg, MBVHRay *ray, int object, int triAddr) -{ - float3 P = ray->P; - float3 idir = ray->idir; - - /* compute and check intersection t-value */ - float4 v00 = kernel_tex_fetch(__tri_woop, triAddr*MBVH_NODE_SIZE+0); - float4 v11 = kernel_tex_fetch(__tri_woop, triAddr*MBVH_NODE_SIZE+1); - float3 dir = 1.0f/idir; - - float Oz = v00.w - P.x*v00.x - P.y*v00.y - P.z*v00.z; - float invDz = 1.0f/(dir.x*v00.x + dir.y*v00.y + dir.z*v00.z); - float t = Oz * invDz; - - if(t > 0.0f && t < ray->t) { - /* compute and check barycentric u */ - float Ox = v11.w + P.x*v11.x + P.y*v11.y + P.z*v11.z; - float Dx = dir.x*v11.x + dir.y*v11.y + dir.z*v11.z; - float u = Ox + t*Dx; - - if(u >= 0.0f) { - /* compute and check barycentric v */ - float4 v22 = kernel_tex_fetch(__tri_woop, triAddr*MBVH_NODE_SIZE+2); - float Oy = v22.w + P.x*v22.x + P.y*v22.y + P.z*v22.z; - float Dy = dir.x*v22.x + dir.y*v22.y + dir.z*v22.z; - float v = Oy + t*Dy; - - if(v >= 0.0f && u + v <= 1.0f) { - /* record intersection */ - ray->index = triAddr; - ray->object = object; - ray->u = u; - ray->v = v; - ray->t = t; - } - } - } -} - -__device void mbvh_node_intersect(KernelGlobals *kg, __m128 *traverseChild, - __m128 *tHit, float3 P, float3 idir, float t, int nodeAddr) -{ - /* X axis */ - const __m128 bminx = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*MBVH_NODE_SIZE+0); - const __m128 t0x = _mm_mul_ps(_mm_sub_ps(bminx, _mm_set_ps1(P.x)), _mm_set_ps1(idir.x)); - const __m128 bmaxx = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*MBVH_NODE_SIZE+1); - const __m128 t1x = _mm_mul_ps(_mm_sub_ps(bmaxx, _mm_set_ps1(P.x)), _mm_set_ps1(idir.x)); - - __m128 tmin = _mm_max_ps(_mm_min_ps(t0x, t1x), _mm_setzero_ps()); - __m128 tmax = _mm_min_ps(_mm_max_ps(t0x, t1x), _mm_set_ps1(t)); - - /* Y axis */ - const __m128 bminy = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*MBVH_NODE_SIZE+2); - const __m128 t0y = _mm_mul_ps(_mm_sub_ps(bminy, _mm_set_ps1(P.y)), _mm_set_ps1(idir.y)); - const __m128 bmaxy = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*MBVH_NODE_SIZE+3); - const __m128 t1y = _mm_mul_ps(_mm_sub_ps(bmaxy, _mm_set_ps1(P.y)), _mm_set_ps1(idir.y)); - - tmin = _mm_max_ps(_mm_min_ps(t0y, t1y), tmin); - tmax = _mm_min_ps(_mm_max_ps(t0y, t1y), tmax); - - /* Z axis */ - const __m128 bminz = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*MBVH_NODE_SIZE+4); - const __m128 t0z = _mm_mul_ps(_mm_sub_ps(bminz, _mm_set_ps1(P.z)), _mm_set_ps1(idir.z)); - const __m128 bmaxz = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*MBVH_NODE_SIZE+5); - const __m128 t1z = _mm_mul_ps(_mm_sub_ps(bmaxz, _mm_set_ps1(P.z)), _mm_set_ps1(idir.z)); - - tmin = _mm_max_ps(_mm_min_ps(t0z, t1z), tmin); - tmax = _mm_min_ps(_mm_max_ps(t0z, t1z), tmax); - - /* compare and get mask */ - *traverseChild = _mm_cmple_ps(tmin, tmax); - - /* get distance XXX probably wrong */ - *tHit = tmin; -} - -static void mbvh_sort_by_length(int id[4], float len[4]) -{ - for(int i = 1; i < 4; i++) { - int j = i - 1; - - while(j >= 0 && len[j] > len[j+1]) { - swap(len[j], len[j+1]); - swap(id[j], id[j+1]); - j--; - } - } -} - -__device void scene_intersect(KernelGlobals *kg, MBVHRay *rays, int numrays) -{ - /* traversal stacks */ - MBVHTask task_stack[MBVH_STACK_SIZE]; - int active_ray_stacks[4][MBVH_RAY_STACK_SIZE]; - int num_task, num_active[4] = {0, 0, 0, 0}; - __m128i one_mm = _mm_set1_epi32(1); - - /* push root node task on stack */ - task_stack[0].node = kernel_data.bvh.root; - task_stack[0].index = 0; - task_stack[0].num = numrays; - task_stack[0].object = ~0; - num_task = 1; - - /* push all rays in first SIMD lane */ - for(int i = 0; i < numrays; i++) - active_ray_stacks[0][i] = i; - num_active[0] = numrays; - - while(num_task >= 1) { - /* pop task */ - MBVHTask task = task_stack[--num_task]; - - if(task.node == MBVH_OBJECT_SENTINEL) { - /* instance pop */ - - /* pop rays from stack */ - num_active[task.index] -= task.num; - int ray_offset = num_active[task.index]; - - /* transform rays */ - for(int i = 0; i < task.num; i++) { - MBVHRay *ray = &rays[active_ray_stacks[task.index][ray_offset + i]]; - mbvh_instance_pop(kg, task.object, ray); - } - } - else if(task.node >= 0) { - /* inner node? */ - - /* pop rays from stack*/ - num_active[task.index] -= task.num; - int ray_offset = num_active[task.index]; - - /* initialze simd values */ - __m128i num_active_mm = _mm_load_si128((__m128i*)num_active); - __m128 len_mm = _mm_set_ps1(0.0f); - - for(int i = 0; i < task.num; i++) { - int rayid = active_ray_stacks[task.index][ray_offset + i]; - MVBHRay *ray = rays + rayid; - - /* intersect 4 QBVH node children */ - __m128 result; - __m128 thit; - - mbvh_node_intersect(kg, &result, &thit, ray->P, ray->idir, ray->t, task.node); - - /* update length for sorting */ - len_mm = _mm_add_ps(len_mm, _mm_and_ps(thit, result)); - - /* push rays on stack */ - for(int j = 0; j < 4; j++) - active_ray_stacks[j][num_active[j]] = rayid; - - /* update num active */ - __m128i resulti = _mm_and_si128(*((__m128i*)&result), one_mm); - num_active_mm = _mm_add_epi32(resulti, num_active_mm); - _mm_store_si128((__m128i*)num_active, num_active_mm); - } - - if(num_active[0] || num_active[1] || num_active[2] || num_active[3]) { - /* load child node addresses */ - float4 cnodes = kernel_tex_fetch(__bvh_nodes, task.node); - int child[4] = { - __float_as_int(cnodes.x), - __float_as_int(cnodes.y), - __float_as_int(cnodes.z), - __float_as_int(cnodes.w)}; - - /* sort nodes by average intersection distance */ - int ids[4] = {0, 1, 2, 3}; - float len[4]; - - _mm_store_ps(len, len_mm); - mbvh_sort_by_length(ids, len); - - /* push new tasks on stack */ - for(int j = 0; j < 4; j++) { - if(num_active[j]) { - int id = ids[j]; - - task_stack[num_task].node = child[id]; - task_stack[num_task].index = id; - task_stack[num_task].num = num_active[id]; - task_stack[num_task].object = task.object; - num_task++; - } - } - } - } - else { - /* fetch leaf node data */ - float4 leaf = kernel_tex_fetch(__bvh_nodes, (-task.node-1)*MBVH_NODE_SIZE+(MBVH_NODE_SIZE-2)); - int triAddr = __float_as_int(leaf.x); - int triAddr2 = __float_as_int(leaf.y); - - /* pop rays from stack*/ - num_active[task.index] -= task.num; - int ray_offset = num_active[task.index]; - - /* triangles */ - if(triAddr >= 0) { - int i, numq = (task.num >> 2) << 2; - - /* SIMD ray leaf intersection */ - for(i = 0; i < numq; i += 4) { - MBVHRay *ray4[4] = { - &rays[active_ray_stacks[task.index][ray_offset + i + 0]], - &rays[active_ray_stacks[task.index][ray_offset + i + 1]], - &rays[active_ray_stacks[task.index][ray_offset + i + 2]], - &rays[active_ray_stacks[task.index][ray_offset + i + 3]]}; - - /* load SoA */ - - while(triAddr < triAddr2) { - mbvh_triangle_intersect(ray4[0], task.object, task.node); - mbvh_triangle_intersect(ray4[1], task.object, task.node); - mbvh_triangle_intersect(ray4[2], task.object, task.node); - mbvh_triangle_intersect(ray4[3], task.object, task.node); - triAddr++; - - /* some shadow ray optim could be done by setting t=0 */ - } - - /* store AoS */ - } - - /* mono ray leaf intersection */ - for(; i < task.num; i++) { - MBVHRay *ray = &rays[active_ray_stacks[task.index][ray_offset + i]]; - - while(triAddr < triAddr2) { - mbvh_triangle_intersect(kg, ray, task.object, task.node); - triAddr++; - } - } - } - else { - /* instance push */ - int object = -triAddr-1; - int node = triAddr; - - /* push instance pop task */ - task_stack[num_task].node = MBVH_OBJECT_SENTINEL; - task_stack[num_task].index = task.index; - task_stack[num_task].num = task.num; - task_stack[num_task].object = object; - num_task++; - - num_active[task.index] += task.num; - - /* push node task */ - task_stack[num_task].node = node; - task_stack[num_task].index = task.index; - task_stack[num_task].num = task.num; - task_stack[num_task].object = object; - num_task++; - - for(int i = 0; i < task.num; i++) { - int rayid = active_ray_stacks[task.index][ray_offset + i]; - - /* push on stack for last task */ - active_ray_stacks[task.index][num_active[task.index]] = rayid; - num_active[task.index]++; - - /* transform ray */ - MBVHRay *ray = &rays[rayid]; - mbvh_instance_push(kg, object, ray); - } - } - } - } -} - -__device void mbvh_set_ray(MBVHRay *rays, int i, Ray *ray, float tmax) -{ - MBVHRay *mray = &rays[i]; - - /* ray parameters in registers */ - mray->P = ray->P; - mray->idir = mbvh_inverse_direction(ray->D); - mray->t = tmax; -} - -__device bool mbvh_get_intersection(MVBHRay *rays, int i, Intersection *isect, float tmax) -{ - MBVHRay *mray = &rays[i]; - - if(mray->t == tmax) - return false; - - isect->t = mray->t; - isect->u = mray->u; - isect->v = mray->v; - isect->index = mray->index; - isect->object = mray->object; - - return true; -} - -__device bool mbvh_get_shadow(MBVHRay *rays, int i, float tmax) -{ - return (rays[i].t == tmax); -} - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/kernel_montecarlo.h b/intern/cycles/kernel/kernel_montecarlo.h index d0b588a88d4..48d1aa64c9f 100644 --- a/intern/cycles/kernel/kernel_montecarlo.h +++ b/intern/cycles/kernel/kernel_montecarlo.h @@ -72,7 +72,7 @@ __device void to_unit_disk(float *x, float *y) __device void make_orthonormals_tangent(const float3 N, const float3 T, float3 *a, float3 *b) { - *b = cross(N, T); + *b = normalize(cross(N, T)); *a = cross(*b, N); } diff --git a/intern/cycles/kernel/kernel_object.h b/intern/cycles/kernel/kernel_object.h index 01da5050c8d..112bfbb86b5 100644 --- a/intern/cycles/kernel/kernel_object.h +++ b/intern/cycles/kernel/kernel_object.h @@ -23,107 +23,134 @@ enum ObjectTransform { OBJECT_INVERSE_TRANSFORM = 3, OBJECT_PROPERTIES = 6, OBJECT_TRANSFORM_MOTION_PRE = 8, - OBJECT_TRANSFORM_MOTION_POST = 12, - OBJECT_DUPLI = 16 + OBJECT_TRANSFORM_MOTION_MID = 12, + OBJECT_TRANSFORM_MOTION_POST = 16, + OBJECT_DUPLI = 20 }; -__device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, float time, enum ObjectTransform type) +__device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, enum ObjectTransform type) { - Transform tfm; + int offset = object*OBJECT_SIZE + (int)type; -#ifdef __MOTION__ - /* if we do motion blur */ - if(sd->flag & SD_OBJECT_MOTION) { - /* fetch motion transforms */ - MotionTransform motion; + Transform tfm; + tfm.x = kernel_tex_fetch(__objects, offset + 0); + tfm.y = kernel_tex_fetch(__objects, offset + 1); + tfm.z = kernel_tex_fetch(__objects, offset + 2); + tfm.w = make_float4(0.0f, 0.0f, 0.0f, 1.0f); - motion.pre.x = have_motion; - motion.pre.y = kernel_tex_fetch(__objects, offset + 1); - motion.pre.z = kernel_tex_fetch(__objects, offset + 2); - motion.pre.w = kernel_tex_fetch(__objects, offset + 3); + return tfm; +} - motion.post.x = kernel_tex_fetch(__objects, offset + 4); - motion.post.y = kernel_tex_fetch(__objects, offset + 5); - motion.post.z = kernel_tex_fetch(__objects, offset + 6); - motion.post.w = kernel_tex_fetch(__objects, offset + 7); +#ifdef __OBJECT_MOTION__ +__device_inline Transform object_fetch_transform_motion(KernelGlobals *kg, int object, float time) +{ + MotionTransform motion; - /* interpolate (todo: do only once per object) */ - transform_motion_interpolate(&tfm, &motion, time); + int offset = object*OBJECT_SIZE + (int)OBJECT_TRANSFORM_MOTION_PRE; - /* invert */ - if(type == OBJECT_INVERSE_TRANSFORM) - tfm = transform_quick_inverse(tfm); + motion.pre.x = kernel_tex_fetch(__objects, offset + 0); + motion.pre.y = kernel_tex_fetch(__objects, offset + 1); + motion.pre.z = kernel_tex_fetch(__objects, offset + 2); + motion.pre.w = kernel_tex_fetch(__objects, offset + 3); - return tfm; - } -#endif + motion.mid.x = kernel_tex_fetch(__objects, offset + 4); + motion.mid.y = kernel_tex_fetch(__objects, offset + 5); + motion.mid.z = kernel_tex_fetch(__objects, offset + 6); + motion.mid.w = kernel_tex_fetch(__objects, offset + 7); - int offset = object*OBJECT_SIZE + (int)type; + motion.post.x = kernel_tex_fetch(__objects, offset + 8); + motion.post.y = kernel_tex_fetch(__objects, offset + 9); + motion.post.z = kernel_tex_fetch(__objects, offset + 10); + motion.post.w = kernel_tex_fetch(__objects, offset + 11); - tfm.x = kernel_tex_fetch(__objects, offset + 0); - tfm.y = kernel_tex_fetch(__objects, offset + 1); - tfm.z = kernel_tex_fetch(__objects, offset + 2); - tfm.w = make_float4(0.0f, 0.0f, 0.0f, 1.0f); + Transform tfm; + transform_motion_interpolate(&tfm, &motion, time); return tfm; } +__device_inline Transform object_fetch_transform_motion_test(KernelGlobals *kg, int object, float time, Transform *itfm) +{ + int object_flag = kernel_tex_fetch(__object_flag, object); + + if(object_flag & SD_OBJECT_MOTION) { + /* if we do motion blur */ + Transform tfm = object_fetch_transform_motion(kg, object, time); + + if(itfm) + *itfm = transform_quick_inverse(tfm); + + return tfm; + } + else { + Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); + if(itfm) + *itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); + + return tfm; + } +} +#endif + __device_inline void object_position_transform(KernelGlobals *kg, ShaderData *sd, float3 *P) { -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ *P = transform_point(&sd->ob_tfm, *P); #else - Transform tfm = object_fetch_transform(kg, sd->object, TIME_INVALID, OBJECT_TRANSFORM); + Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM); *P = transform_point(&tfm, *P); #endif } __device_inline void object_inverse_position_transform(KernelGlobals *kg, ShaderData *sd, float3 *P) { -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ *P = transform_point(&sd->ob_itfm, *P); #else - Transform tfm = object_fetch_transform(kg, sd->object, TIME_INVALID, OBJECT_INVERSE_TRANSFORM); + Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM); *P = transform_point(&tfm, *P); #endif } __device_inline void object_inverse_normal_transform(KernelGlobals *kg, ShaderData *sd, float3 *N) { -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ *N = normalize(transform_direction_transposed(&sd->ob_tfm, *N)); #else - Transform tfm = object_fetch_transform(kg, sd->object, TIME_INVALID, OBJECT_TRANSFORM); + Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM); *N = normalize(transform_direction_transposed(&tfm, *N)); #endif } __device_inline void object_normal_transform(KernelGlobals *kg, ShaderData *sd, float3 *N) { -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ *N = normalize(transform_direction_transposed(&sd->ob_itfm, *N)); #else - Transform tfm = object_fetch_transform(kg, sd->object, TIME_INVALID, OBJECT_INVERSE_TRANSFORM); + Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM); *N = normalize(transform_direction_transposed(&tfm, *N)); #endif } __device_inline void object_dir_transform(KernelGlobals *kg, ShaderData *sd, float3 *D) { -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ *D = transform_direction(&sd->ob_tfm, *D); #else - Transform tfm = object_fetch_transform(kg, sd->object, 0.0f, OBJECT_TRANSFORM); + Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM); *D = transform_direction(&tfm, *D); #endif } __device_inline float3 object_location(KernelGlobals *kg, ShaderData *sd) { -#ifdef __MOTION__ + if(sd->object == ~0) + return make_float3(0.0f, 0.0f, 0.0f); + +#ifdef __OBJECT_MOTION__ return make_float3(sd->ob_tfm.x.w, sd->ob_tfm.y.w, sd->ob_tfm.z.w); #else - Transform tfm = object_fetch_transform(kg, sd->object, 0.0f, OBJECT_TRANSFORM); + Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM); return make_float3(tfm.x.w, tfm.y.w, tfm.z.w); #endif } @@ -249,6 +276,5 @@ __device float3 particle_angular_velocity(KernelGlobals *kg, int particle) return make_float3(f3.z, f3.w, f4.x); } - CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index d606c3d634a..585068ce8e2 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -326,7 +326,7 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, #ifdef __AO__ /* ambient occlusion */ - if(kernel_data.integrator.use_ambient_occlusion) { + if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) { /* todo: solve correlation */ float bsdf_u = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_U); float bsdf_v = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_V); @@ -343,12 +343,13 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, light_ray.P = ray_offset(sd.P, sd.Ng); light_ray.D = ao_D; light_ray.t = kernel_data.background.ao_distance; -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ light_ray.time = sd.time; #endif if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) { float3 ao_bsdf = shader_bsdf_diffuse(kg, &sd)*kernel_data.background.ao_factor; + ao_bsdf += shader_bsdf_ao(kg, &sd); path_radiance_accum_ao(&L, throughput, ao_bsdf, ao_shadow, state.bounce); } } @@ -368,7 +369,7 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, BsdfEval L_light; bool is_lamp; -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ light_ray.time = sd.time; #endif @@ -503,7 +504,7 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray #ifdef __AO__ /* ambient occlusion */ - if(kernel_data.integrator.use_ambient_occlusion) { + if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) { /* todo: solve correlation */ float bsdf_u = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_U); float bsdf_v = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_V); @@ -520,12 +521,13 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray light_ray.P = ray_offset(sd.P, sd.Ng); light_ray.D = ao_D; light_ray.t = kernel_data.background.ao_distance; -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ light_ray.time = sd.time; #endif if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) { float3 ao_bsdf = shader_bsdf_diffuse(kg, &sd)*kernel_data.background.ao_factor; + ao_bsdf += shader_bsdf_ao(kg, &sd); path_radiance_accum_ao(L, throughput, ao_bsdf, ao_shadow, state.bounce); } } @@ -545,7 +547,7 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray BsdfEval L_light; bool is_lamp; -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ light_ray.time = sd.time; #endif @@ -706,7 +708,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam #ifdef __AO__ /* ambient occlusion */ - if(kernel_data.integrator.use_ambient_occlusion) { + if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) { int num_samples = kernel_data.integrator.ao_samples; float num_samples_inv = 1.0f/num_samples; float ao_factor = kernel_data.background.ao_factor; @@ -728,12 +730,13 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam light_ray.P = ray_offset(sd.P, sd.Ng); light_ray.D = ao_D; light_ray.t = kernel_data.background.ao_distance; -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ light_ray.time = sd.time; #endif if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) { float3 ao_bsdf = shader_bsdf_diffuse(kg, &sd)*ao_factor; + ao_bsdf += shader_bsdf_ao(kg, &sd); path_radiance_accum_ao(&L, throughput*num_samples_inv, ao_bsdf, ao_shadow, state.bounce); } } @@ -748,7 +751,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam BsdfEval L_light; bool is_lamp; -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ light_ray.time = sd.time; #endif @@ -867,7 +870,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam bsdf_ray.dP = sd.dP; bsdf_ray.dD = bsdf_domega_in; #endif -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ bsdf_ray.time = sd.time; #endif @@ -925,7 +928,7 @@ __device void kernel_path_trace(KernelGlobals *kg, float lens_u = path_rng(kg, &rng, sample, PRNG_LENS_U); float lens_v = path_rng(kg, &rng, sample, PRNG_LENS_V); -#ifdef __MOTION__ +#ifdef __CAMERA_MOTION__ float time = path_rng(kg, &rng, sample, PRNG_TIME); #else float time = 0.0f; diff --git a/intern/cycles/kernel/kernel_projection.h b/intern/cycles/kernel/kernel_projection.h index 64747bcb42e..6516b9e4d82 100644 --- a/intern/cycles/kernel/kernel_projection.h +++ b/intern/cycles/kernel/kernel_projection.h @@ -98,7 +98,7 @@ __device float3 fisheye_to_direction(float u, float v, float fov) return make_float3(0.0f, 0.0f, 0.0f); float phi = acosf((r != 0.0f)? u/r: 0.0f); - float theta = asinf(r) * (fov / M_PI_F); + float theta = r * fov * 0.5f; if(v < 0.0f) phi = -phi; diff --git a/intern/cycles/kernel/kernel_qbvh.h b/intern/cycles/kernel/kernel_qbvh.h deleted file mode 100644 index 525b616921d..00000000000 --- a/intern/cycles/kernel/kernel_qbvh.h +++ /dev/null @@ -1,413 +0,0 @@ -/* - * Adapted from code Copyright 2009-2010 NVIDIA Corporation - * Modifications Copyright 2011, Blender Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -CCL_NAMESPACE_BEGIN - -/* - * "Persistent while-while kernel" used in: - * - * "Understanding the Efficiency of Ray Traversal on GPUs", - * Timo Aila and Samuli Laine, - * Proc. High-Performance Graphics 2009 - */ - -/* bottom-most stack entry, indicating the end of traversal */ - -#define ENTRYPOINT_SENTINEL 0x76543210 -/* 64 object BVH + 64 mesh BVH + 64 object node splitting */ -#define QBVH_STACK_SIZE 192 -#define QBVH_NODE_SIZE 8 -#define TRI_NODE_SIZE 3 - -__device_inline float3 qbvh_inverse_direction(float3 dir) -{ - // Avoid divide by zero (ooeps = exp2f(-80.0f)) - float ooeps = 0.00000000000000000000000082718061255302767487140869206996285356581211090087890625f; - float3 idir; - - idir.x = 1.0f/((fabsf(dir.x) > ooeps)? dir.x: copysignf(ooeps, dir.x)); - idir.y = 1.0f/((fabsf(dir.y) > ooeps)? dir.y: copysignf(ooeps, dir.y)); - idir.z = 1.0f/((fabsf(dir.z) > ooeps)? dir.z: copysignf(ooeps, dir.z)); - - return idir; -} - -__device_inline void qbvh_instance_push(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *idir, float *t, const float tmax) -{ - Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); - - *P = transform_point(&tfm, ray->P); - - float3 dir = transform_direction(&tfm, ray->D); - - float len; - dir = normalize_len(dir, &len); - - *idir = qbvh_inverse_direction(dir); - - if(*t != FLT_MAX) - *t *= len; -} - -__device_inline void qbvh_instance_pop(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *idir, float *t, const float tmax) -{ - Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); - - if(*t != FLT_MAX) - *t *= len(transform_direction(&tfm, 1.0f/(*idir))); - - *P = ray->P; - *idir = qbvh_inverse_direction(ray->D); -} - -#ifdef __KERNEL_CPU__ - -__device_inline void qbvh_node_intersect(KernelGlobals *kg, int *traverseChild, - int nodeAddrChild[4], float3 P, float3 idir, float t, int nodeAddr) -{ - /* X axis */ - const __m128 bminx = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+0); - const __m128 t0x = _mm_mul_ps(_mm_sub_ps(bminx, _mm_set_ps1(P.x)), _mm_set_ps1(idir.x)); - const __m128 bmaxx = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+1); - const __m128 t1x = _mm_mul_ps(_mm_sub_ps(bmaxx, _mm_set_ps1(P.x)), _mm_set_ps1(idir.x)); - - __m128 tmin = _mm_max_ps(_mm_min_ps(t0x, t1x), _mm_setzero_ps()); - __m128 tmax = _mm_min_ps(_mm_max_ps(t0x, t1x), _mm_set_ps1(t)); - - /* Y axis */ - const __m128 bminy = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+2); - const __m128 t0y = _mm_mul_ps(_mm_sub_ps(bminy, _mm_set_ps1(P.y)), _mm_set_ps1(idir.y)); - const __m128 bmaxy = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+3); - const __m128 t1y = _mm_mul_ps(_mm_sub_ps(bmaxy, _mm_set_ps1(P.y)), _mm_set_ps1(idir.y)); - - tmin = _mm_max_ps(_mm_min_ps(t0y, t1y), tmin); - tmax = _mm_min_ps(_mm_max_ps(t0y, t1y), tmax); - - /* Z axis */ - const __m128 bminz = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+4); - const __m128 t0z = _mm_mul_ps(_mm_sub_ps(bminz, _mm_set_ps1(P.z)), _mm_set_ps1(idir.z)); - const __m128 bmaxz = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+5); - const __m128 t1z = _mm_mul_ps(_mm_sub_ps(bmaxz, _mm_set_ps1(P.z)), _mm_set_ps1(idir.z)); - - tmin = _mm_max_ps(_mm_min_ps(t0z, t1z), tmin); - tmax = _mm_min_ps(_mm_max_ps(t0z, t1z), tmax); - - /* compare and get mask */ - *traverseChild = _mm_movemask_ps(_mm_cmple_ps(tmin, tmax)); - - /* get node addresses */ - float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+6); - - nodeAddrChild[0] = __float_as_int(cnodes.x); - nodeAddrChild[1] = __float_as_int(cnodes.y); - nodeAddrChild[2] = __float_as_int(cnodes.z); - nodeAddrChild[3] = __float_as_int(cnodes.w); -} - -#else - -__device_inline bool qbvh_bb_intersect(float3 bmin, float3 bmax, float3 P, float3 idir, float t) -{ - float t0x = (bmin.x - P.x)*idir.x; - float t1x = (bmax.x - P.x)*idir.x; - float t0y = (bmin.y - P.y)*idir.y; - float t1y = (bmax.y - P.y)*idir.y; - float t0z = (bmin.z - P.z)*idir.z; - float t1z = (bmax.z - P.z)*idir.z; - - float minx = min(t0x, t1x); - float maxx = max(t0x, t1x); - float miny = min(t0y, t1y); - float maxy = max(t0y, t1y); - float minz = min(t0z, t1z); - float maxz = max(t0z, t1z); - - float tmin = max4(0.0f, minx, miny, minz); - float tmax = min4(t, maxx, maxy, maxz); - - return (tmin <= tmax); -} - -/* intersect four bounding boxes */ -__device_inline void qbvh_node_intersect(KernelGlobals *kg, int *traverseChild, - int nodeAddrChild[4], float3 P, float3 idir, float t, int nodeAddr) -{ - /* fetch node data */ - float4 minx = kernel_tex_fetch(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+0); - float4 miny = kernel_tex_fetch(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+2); - float4 minz = kernel_tex_fetch(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+4); - float4 maxx = kernel_tex_fetch(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+1); - float4 maxy = kernel_tex_fetch(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+3); - float4 maxz = kernel_tex_fetch(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+5); - - /* intersect bounding boxes */ - bool traverseChild0 = qbvh_bb_intersect(make_float3(minx.x, miny.x, minz.x), make_float3(maxx.x, maxy.x, maxz.x), P, idir, t); - bool traverseChild1 = qbvh_bb_intersect(make_float3(minx.y, miny.y, minz.y), make_float3(maxx.y, maxy.y, maxz.y), P, idir, t); - bool traverseChild2 = qbvh_bb_intersect(make_float3(minx.z, miny.z, minz.z), make_float3(maxx.z, maxy.z, maxz.z), P, idir, t); - bool traverseChild3 = qbvh_bb_intersect(make_float3(minx.w, miny.w, minz.w), make_float3(maxx.w, maxy.w, maxz.w), P, idir, t); - - *traverseChild = 0; - if(traverseChild0) *traverseChild |= 1; - if(traverseChild1) *traverseChild |= 2; - if(traverseChild2) *traverseChild |= 4; - if(traverseChild3) *traverseChild |= 8; - - /* get node addresses */ - float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+6); - - nodeAddrChild[0] = __float_as_int(cnodes.x); - nodeAddrChild[1] = __float_as_int(cnodes.y); - nodeAddrChild[2] = __float_as_int(cnodes.z); - nodeAddrChild[3] = __float_as_int(cnodes.w); -} - -#endif - -/* Sven Woop's algorithm */ -__device_inline void qbvh_triangle_intersect(KernelGlobals *kg, Intersection *isect, float3 P, float3 idir, int object, int triAddr) -{ - /* compute and check intersection t-value */ - float4 v00 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0); - float4 v11 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1); - float3 dir = 1.0f/idir; - - float Oz = v00.w - P.x*v00.x - P.y*v00.y - P.z*v00.z; - float invDz = 1.0f/(dir.x*v00.x + dir.y*v00.y + dir.z*v00.z); - float t = Oz * invDz; - - if(t > 0.0f && t < isect->t) { - /* compute and check barycentric u */ - float Ox = v11.w + P.x*v11.x + P.y*v11.y + P.z*v11.z; - float Dx = dir.x*v11.x + dir.y*v11.y + dir.z*v11.z; - float u = Ox + t*Dx; - - if(u >= 0.0f) { - /* compute and check barycentric v */ - float4 v22 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2); - float Oy = v22.w + P.x*v22.x + P.y*v22.y + P.z*v22.z; - float Dy = dir.x*v22.x + dir.y*v22.y + dir.z*v22.z; - float v = Oy + t*Dy; - - if(v >= 0.0f && u + v <= 1.0f) { - /* record intersection */ - isect->prim = triAddr; - isect->object = object; - isect->u = u; - isect->v = v; - isect->t = t; - } - } - } -} - -__device_inline bool scene_intersect(KernelGlobals *kg, const Ray *ray, const bool isshadowray, Intersection *isect) -{ - /* traversal stack in CUDA thread-local memory */ - int traversalStack[QBVH_STACK_SIZE]; - traversalStack[0] = ENTRYPOINT_SENTINEL; - - /* traversal variables in registers */ - int stackPtr = 0; - int nodeAddr = kernel_data.bvh.root; - - /* ray parameters in registers */ - const float tmax = ray->t; - float3 P = ray->P; - float3 idir = qbvh_inverse_direction(ray->D); - int object = ~0; - - isect->t = tmax; - isect->object = ~0; - isect->prim = ~0; - isect->u = 0.0f; - isect->v = 0.0f; - - /* traversal loop */ - do { - do - { - /* traverse internal nodes */ - while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) - { - int traverseChild, nodeAddrChild[4]; - - qbvh_node_intersect(kg, &traverseChild, nodeAddrChild, - P, idir, isect->t, nodeAddr); - - if(traverseChild & 1) { - ++stackPtr; - traversalStack[stackPtr] = nodeAddrChild[0]; - } - - if(traverseChild & 2) { - ++stackPtr; - traversalStack[stackPtr] = nodeAddrChild[1]; - } - if(traverseChild & 4) { - ++stackPtr; - traversalStack[stackPtr] = nodeAddrChild[2]; - } - - if(traverseChild & 8) { - ++stackPtr; - traversalStack[stackPtr] = nodeAddrChild[3]; - } - - nodeAddr = traversalStack[stackPtr]; - --stackPtr; - } - - /* if node is leaf, fetch triangle list */ - if(nodeAddr < 0) { - float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*QBVH_NODE_SIZE+(QBVH_NODE_SIZE-2)); - int primAddr = __float_as_int(leaf.x); - -#ifdef __INSTANCING__ - if(primAddr >= 0) { -#endif - int primAddr2 = __float_as_int(leaf.y); - - /* pop */ - nodeAddr = traversalStack[stackPtr]; - --stackPtr; - - /* triangle intersection */ - while(primAddr < primAddr2) { - /* intersect ray against triangle */ - qbvh_triangle_intersect(kg, isect, P, idir, object, primAddr); - - /* shadow ray early termination */ - if(isshadowray && isect->prim != ~0) - return true; - - primAddr++; - } -#ifdef __INSTANCING__ - } - else { - /* instance push */ - object = kernel_tex_fetch(__prim_object, -primAddr-1); - - qbvh_instance_push(kg, object, ray, &P, &idir, &isect->t, tmax); - - ++stackPtr; - traversalStack[stackPtr] = ENTRYPOINT_SENTINEL; - - nodeAddr = kernel_tex_fetch(__object_node, object); - } -#endif - } - } while(nodeAddr != ENTRYPOINT_SENTINEL); - -#ifdef __INSTANCING__ - if(stackPtr >= 0) { - kernel_assert(object != ~0); - - /* instance pop */ - qbvh_instance_pop(kg, object, ray, &P, &idir, &isect->t, tmax); - object = ~0; - nodeAddr = traversalStack[stackPtr]; - --stackPtr; - } -#endif - } while(nodeAddr != ENTRYPOINT_SENTINEL); - - return (isect->prim != ~0); -} - -__device_inline float3 ray_offset(float3 P, float3 Ng) -{ -#ifdef __INTERSECTION_REFINE__ - const float epsilon_f = 1e-5f; - const int epsilon_i = 32; - - float3 res; - - /* x component */ - if(fabsf(P.x) < epsilon_f) { - res.x = P.x + Ng.x*epsilon_f; - } - else { - uint ix = __float_as_uint(P.x); - ix += ((ix ^ __float_as_uint(Ng.x)) >> 31)? -epsilon_i: epsilon_i; - res.x = __uint_as_float(ix); - } - - /* y component */ - if(fabsf(P.y) < epsilon_f) { - res.y = P.y + Ng.y*epsilon_f; - } - else { - uint iy = __float_as_uint(P.y); - iy += ((iy ^ __float_as_uint(Ng.y)) >> 31)? -epsilon_i: epsilon_i; - res.y = __uint_as_float(iy); - } - - /* z component */ - if(fabsf(P.z) < epsilon_f) { - res.z = P.z + Ng.z*epsilon_f; - } - else { - uint iz = __float_as_uint(P.z); - iz += ((iz ^ __float_as_uint(Ng.z)) >> 31)? -epsilon_i: epsilon_i; - res.z = __uint_as_float(iz); - } - - return res; -#else - const float epsilon_f = 1e-4f; - return P + epsilon_f*Ng; -#endif -} - -__device_inline float3 bvh_triangle_refine(KernelGlobals *kg, const Intersection *isect, const Ray *ray) -{ - float3 P = ray->P; - float3 D = ray->D; - float t = isect->t; - -#ifdef __INTERSECTION_REFINE__ - if(isect->object != ~0) { - Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM); - - P = transform_point(&tfm, P); - D = transform_direction(&tfm, D*t); - D = normalize_len(D, &t); - } - - P = P + D*t; - - float4 v00 = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0); - float Oz = v00.w - P.x*v00.x - P.y*v00.y - P.z*v00.z; - float invDz = 1.0f/(D.x*v00.x + D.y*v00.y + D.z*v00.z); - float rt = Oz * invDz; - - P = P + D*rt; - - if(isect->object != ~0) { - Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM); - P = transform_point(&tfm, P); - } - - return P; -#else - return P + D*t; -#endif -} - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index b57e27bc8ed..1af5e048ad9 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -27,22 +27,36 @@ */ #ifdef __OSL__ - #include "osl_shader.h" - #endif -#include "svm/bsdf.h" -#include "svm/emissive.h" -#include "svm/volume.h" +#include "closure/bsdf.h" +#include "closure/emissive.h" +#include "closure/volume.h" + #include "svm/svm_bsdf.h" #include "svm/svm.h" - CCL_NAMESPACE_BEGIN /* ShaderData setup from incoming ray */ +#ifdef __OBJECT_MOTION__ +__device_noinline void shader_setup_object_transforms(KernelGlobals *kg, ShaderData *sd, float time) +{ + /* note that this is a separate non-inlined function to work around crash + * on CUDA sm 2.0, otherwise kernel execution crashes (compiler bug?) */ + if(sd->flag & SD_OBJECT_MOTION) { + sd->ob_tfm = object_fetch_transform_motion(kg, sd->object, time); + sd->ob_itfm= transform_quick_inverse(sd->ob_tfm); + } + else { + sd->ob_tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM); + sd->ob_itfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM); + } +} +#endif + __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray) { @@ -67,11 +81,12 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, sd->v = isect->v; #endif - /* matrices and time */ -#ifdef __MOTION__ - sd->ob_tfm = object_fetch_transform(kg, sd->object, ray->time, OBJECT_TRANSFORM); - sd->ob_itfm = object_fetch_transform(kg, sd->object, ray->time, OBJECT_INVERSE_TRANSFORM); + sd->flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*2); + sd->flag |= kernel_tex_fetch(__object_flag, sd->object); + /* matrices and time */ +#ifdef __OBJECT_MOTION__ + shader_setup_object_transforms(kg, sd, ray->time); sd->time = ray->time; #endif @@ -87,9 +102,6 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, if(sd->shader & SHADER_SMOOTH_NORMAL) sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v); - sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2); - sd->flag |= kernel_tex_fetch(__object_flag, sd->object); - #ifdef __DPDU__ /* dPdu/dPdv */ triangle_dPdudv(kg, &sd->dPdu, &sd->dPdv, sd->prim); @@ -171,11 +183,17 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, } #endif -#ifdef __MOTION__ - sd->time = time; + sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2); + if(sd->object != -1) { + sd->flag |= kernel_tex_fetch(__object_flag, sd->object); - sd->ob_tfm = object_fetch_transform(kg, sd->object, time, OBJECT_TRANSFORM); - sd->ob_itfm = object_fetch_transform(kg, sd->object, time, OBJECT_INVERSE_TRANSFORM); +#ifdef __OBJECT_MOTION__ + shader_setup_object_transforms(kg, sd, time); + } + + sd->time = time; +#else + } #endif /* smooth normal */ @@ -188,10 +206,6 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, #endif } - sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2); - if(sd->object != -1) - sd->flag |= kernel_tex_fetch(__object_flag, sd->object); - #ifdef __DPDU__ /* dPdu/dPdv */ if(sd->prim == ~0) { @@ -275,7 +289,7 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData sd->I = -sd->P; sd->shader = kernel_data.background.shader; sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2); -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ sd->time = ray->time; #endif sd->ray_length = 0.0f; @@ -483,18 +497,22 @@ __device int shader_bsdf_sample_closure(KernelGlobals *kg, const ShaderData *sd, __device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughness) { -#ifndef __OSL__ #ifdef __MULTI_CLOSURE__ for(int i = 0; i< sd->num_closure; i++) { ShaderClosure *sc = &sd->closure[i]; - if(CLOSURE_IS_BSDF(sc->type)) - svm_bsdf_blur(sc, roughness); + if(CLOSURE_IS_BSDF(sc->type)) { +#ifdef __OSL__ + if (kernel_osl_use(kg)) + OSLShader::bsdf_blur(sc, roughness); + else +#endif + svm_bsdf_blur(sc, roughness); + } } #else svm_bsdf_blur(&sd->closure, roughness); #endif -#endif } __device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *sd) @@ -581,6 +599,27 @@ __device float3 shader_bsdf_transmission(KernelGlobals *kg, ShaderData *sd) #endif } +__device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd) +{ +#ifdef __MULTI_CLOSURE__ + float3 eval = make_float3(0.0f, 0.0f, 0.0f); + + for(int i = 0; i< sd->num_closure; i++) { + ShaderClosure *sc = &sd->closure[i]; + + if(CLOSURE_IS_AMBIENT_OCCLUSION(sc->type)) + eval += sc->weight; + } + + return eval; +#else + if(CLOSURE_IS_AMBIENT_OCCLUSION(sd->closure.type)) + return sd->closure.weight; + else + return make_float3(0.0f, 0.0f, 0.0f); +#endif +} + /* Emission */ __device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd) @@ -704,16 +743,16 @@ __device float3 shader_volume_eval_phase(KernelGlobals *kg, ShaderData *sd, if(CLOSURE_IS_VOLUME(sc->type)) { #ifdef __OSL__ if (kernel_osl_use(kg)) - eval += OSLShader::volume_eval_phase(sd, sc, omega_in, omega_out); + eval += OSLShader::volume_eval_phase(sc, omega_in, omega_out); else #endif - eval += volume_eval_phase(sd, sc, omega_in, omega_out); + eval += volume_eval_phase(sc, omega_in, omega_out); } } return eval; #else - return volume_eval_phase(sd, &sd->closure, omega_in, omega_out); + return volume_eval_phase(&sd->closure, omega_in, omega_out); #endif } diff --git a/intern/cycles/kernel/kernel_triangle.h b/intern/cycles/kernel/kernel_triangle.h index f57c59a45eb..e39ae1d4fbc 100644 --- a/intern/cycles/kernel/kernel_triangle.h +++ b/intern/cycles/kernel/kernel_triangle.h @@ -68,6 +68,17 @@ __device_inline float3 triangle_normal_MT(KernelGlobals *kg, int tri_index, int #endif } +/* Return 3 triangle vertex locations */ +__device_inline void triangle_vertices(KernelGlobals *kg, int tri_index, float3 P[3]) +{ + /* load triangle vertices */ + float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, tri_index)); + + P[0] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x))); + P[1] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y))); + P[2] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z))); +} + __device_inline float3 triangle_smooth_normal(KernelGlobals *kg, int tri_index, float u, float v) { /* load triangle vertices */ @@ -201,10 +212,10 @@ __device float4 triangle_motion_vector(KernelGlobals *kg, ShaderData *sd) * transformation was set match the world/object space of motion_pre/post */ Transform tfm; - tfm = object_fetch_transform(kg, sd->object, TIME_INVALID, OBJECT_TRANSFORM_MOTION_PRE); + tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM_MOTION_PRE); motion_pre = transform_point(&tfm, motion_pre); - tfm = object_fetch_transform(kg, sd->object, TIME_INVALID, OBJECT_TRANSFORM_MOTION_POST); + tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM_MOTION_POST); motion_post = transform_point(&tfm, motion_post); float3 P; diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 48e271a9f3f..d4d88466688 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -29,13 +29,15 @@ CCL_NAMESPACE_BEGIN /* constants */ -#define OBJECT_SIZE 18 +#define OBJECT_SIZE 22 #define LIGHT_SIZE 4 #define FILTER_TABLE_SIZE 256 #define RAMP_TABLE_SIZE 256 #define PARTICLE_SIZE 5 #define TIME_INVALID FLT_MAX +#define TEX_NUM_FLOAT_IMAGES 5 + /* device capabilities */ #ifdef __KERNEL_CPU__ #define __KERNEL_SHADING__ @@ -108,11 +110,15 @@ CCL_NAMESPACE_BEGIN #define __PASSES__ #define __BACKGROUND_MIS__ #define __AO__ -//#define __MOTION__ +#define __CAMERA_MOTION__ + +#ifndef __KERNEL_CUDA__ +#define __OBJECT_MOTION__ +#endif + #endif //#define __SOBOL_FULL_SCREEN__ -//#define __QBVH__ /* Shader Evaluation */ @@ -129,7 +135,7 @@ enum PathTraceDimension { PRNG_FILTER_V = 1, PRNG_LENS_U = 2, PRNG_LENS_V = 3, -#ifdef __MOTION__ +#ifdef __CAMERA_MOTION__ PRNG_TIME = 4, PRNG_UNUSED = 5, PRNG_BASE_NUM = 6, @@ -148,9 +154,7 @@ enum PathTraceDimension { PRNG_BOUNCE_NUM = 8 }; -/* these flag values correspond exactly to OSL defaults, so be careful not to - * change this, or if you do, set the "raytypes" shading system attribute with - * your own new ray types and bitflag values. +/* these flags values correspond to raytypes in osl.cpp, so keep them in sync! * * for ray visibility tests in BVH traversal, the upper 20 bits are used for * layer visibility tests. */ @@ -370,6 +374,9 @@ typedef struct ShaderClosure { float data0; float data1; + float3 N; + float3 T; + } ShaderClosure; /* Shader Data @@ -386,16 +393,17 @@ enum ShaderDataFlag { SD_BSDF_GLOSSY = 16, /* have glossy bsdf */ SD_HOLDOUT = 32, /* have holdout closure? */ SD_VOLUME = 64, /* have volume closure? */ + SD_AO = 128, /* have ao closure? */ /* shader flags */ - SD_SAMPLE_AS_LIGHT = 128, /* direct light sample */ - SD_HAS_SURFACE_TRANSPARENT = 256, /* has surface transparency */ - SD_HAS_VOLUME = 512, /* has volume shader */ - SD_HOMOGENEOUS_VOLUME = 1024, /* has homogeneous volume */ + SD_SAMPLE_AS_LIGHT = 256, /* direct light sample */ + SD_HAS_SURFACE_TRANSPARENT = 512, /* has surface transparency */ + SD_HAS_VOLUME = 1024, /* has volume shader */ + SD_HOMOGENEOUS_VOLUME = 2048, /* has homogeneous volume */ /* object flags */ - SD_HOLDOUT_MASK = 2048, /* holdout for camera rays */ - SD_OBJECT_MOTION = 4096 /* has object motion blur */ + SD_HOLDOUT_MASK = 4096, /* holdout for camera rays */ + SD_OBJECT_MOTION = 8192 /* has object motion blur */ }; typedef struct ShaderData { @@ -408,7 +416,7 @@ typedef struct ShaderData { /* view/incoming direction */ float3 I; /* shader id */ - int shader; + int shader; /* booleans describing shader, see ShaderDataFlag */ int flag; @@ -426,13 +434,6 @@ typedef struct ShaderData { /* length of the ray being shaded */ float ray_length; -#ifdef __MOTION__ - /* object <-> world space transformations, cached to avoid - * re-interpolating them constantly for shading */ - Transform ob_tfm; - Transform ob_itfm; -#endif - #ifdef __RAY_DIFFERENTIALS__ /* differential of P. these are orthogonal to Ng, not N */ differential3 dP; @@ -448,6 +449,13 @@ typedef struct ShaderData { float3 dPdu, dPdv; #endif +#ifdef __OBJECT_MOTION__ + /* object <-> world space transformations, cached to avoid + * re-interpolating them constantly for shading */ + Transform ob_tfm; + Transform ob_itfm; +#endif + #ifdef __MULTI_CLOSURE__ /* Closure data, we store a fixed array of closures */ ShaderClosure closure[MAX_CLOSURE]; @@ -511,7 +519,9 @@ typedef struct KernelCamera { /* more matrices */ Transform screentoworld; Transform rastertoworld; - Transform ndctoworld; + /* work around cuda sm 2.0 crash, this seems to + * cross some limit in combination with motion + * Transform ndctoworld; */ Transform worldtoscreen; Transform worldtoraster; Transform worldtondc; @@ -627,7 +637,8 @@ typedef struct KernelBVH { /* root node */ int root; int attributes_map_stride; - int pad1, pad2; + int have_motion; + int pad2; } KernelBVH; typedef struct KernelData { diff --git a/intern/cycles/kernel/osl/CMakeLists.txt b/intern/cycles/kernel/osl/CMakeLists.txt index 65d7a7ad53b..1b1bb558bc9 100644 --- a/intern/cycles/kernel/osl/CMakeLists.txt +++ b/intern/cycles/kernel/osl/CMakeLists.txt @@ -7,28 +7,18 @@ set(INC ../../util ../../device ) + set(INC_SYS + ) set(SRC background.cpp - bsdf_ashikhmin_velvet.cpp - bsdf_diffuse.cpp - bsdf_oren_nayar.cpp - bsdf_phong.cpp - bsdf_microfacet.cpp - bsdf_reflection.cpp - bsdf_refraction.cpp - bsdf_transparent.cpp - bsdf_ward.cpp - bsdf_westin.cpp - bssrdf.cpp - debug.cpp + bsdf_phong_ramp.cpp emissive.cpp osl_closures.cpp osl_services.cpp osl_shader.cpp - vol_subsurface.cpp ) set(HEADER_SRC @@ -45,4 +35,3 @@ include_directories(SYSTEM ${INC_SYS}) add_library(cycles_kernel_osl ${SRC} ${HEADER_SRC}) -add_subdirectory(nodes) diff --git a/intern/cycles/kernel/osl/background.cpp b/intern/cycles/kernel/osl/background.cpp index 6290eed0af8..eed4446cddc 100644 --- a/intern/cycles/kernel/osl/background.cpp +++ b/intern/cycles/kernel/osl/background.cpp @@ -46,23 +46,16 @@ using namespace OSL; /// to return a color in background shaders. No methods, /// only the weight is taking into account /// -class GenericBackgroundClosure : public BackgroundClosure { +class GenericBackgroundClosure : public OSL::BackgroundClosure { public: GenericBackgroundClosure() {} void setup() {}; - size_t memsize() const { return sizeof(*this); } - const char *name() const { return "background"; } - - void print_on(std::ostream &out) const { - out << name() << " ()"; - } - + void print_on(std::ostream &out) const { out << name() << " ()"; } }; - /// Holdout closure /// /// This will be used by the shader to mark the @@ -75,16 +68,26 @@ public: HoldoutClosure () : ClosurePrimitive(Holdout) {} void setup() {}; - size_t memsize() const { return sizeof(*this); } - const char *name() const { return "holdout"; } - - void print_on(std::ostream &out) const { - out << name() << " ()"; - } + void print_on(std::ostream &out) const { out << name() << " ()"; } }; +/// ambient occlusion closure +/// +/// We only have a ambient occlusion closure for the shaders +/// to return a color in ambient occlusion shaders. No methods, +/// only the weight is taking into account +/// +class AmbientOcclusionClosure : public ClosurePrimitive { +public: + AmbientOcclusionClosure () : ClosurePrimitive((ClosurePrimitive::Category)AmbientOcclusion) {} + + void setup() {}; + size_t memsize() const { return sizeof(*this); } + const char *name() const { return "ambient_occlusion"; } + void print_on(std::ostream &out) const { out << name() << " ()"; } +}; ClosureParam *closure_background_params() { @@ -107,5 +110,16 @@ ClosureParam *closure_holdout_params() CLOSURE_PREPARE(closure_holdout_prepare, HoldoutClosure) +ClosureParam *closure_ambient_occlusion_params() +{ + static ClosureParam params[] = { + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(AmbientOcclusionClosure) + }; + return params; +} + +CLOSURE_PREPARE(closure_ambient_occlusion_prepare, AmbientOcclusionClosure) + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp b/intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp deleted file mode 100644 index a1904d7f5d7..00000000000 --- a/intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Adapted from Open Shading Language with this license: - * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sony Pictures Imageworks nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <OpenImageIO/fmath.h> - -#include <OSL/genclosure.h> - -#include "osl_closures.h" - -#include "util_math.h" - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -class AshikhminVelvetClosure : public BSDFClosure { -public: - Vec3 m_N; - float m_sigma; - float m_invsigma2; - - AshikhminVelvetClosure() : BSDFClosure(Labels::DIFFUSE) {} - - void setup() - { - m_sigma = max(m_sigma, 0.01f); - m_invsigma2 = 1.0f / (m_sigma * m_sigma); - } - - bool mergeable(const ClosurePrimitive *other) const { - const AshikhminVelvetClosure *comp = (const AshikhminVelvetClosure *)other; - return m_N == comp->m_N && m_sigma == comp->m_sigma && - BSDFClosure::mergeable(other); - } - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { return "ashikhmin_velvet"; } - - void print_on(std::ostream &out) const - { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_sigma; - out << ")"; - } - - float albedo(const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNO > 0 && cosNI > 0) { - Vec3 H = omega_in + omega_out; - H.normalize(); - - float cosNH = m_N.dot(H); - float cosHO = fabsf(omega_out.dot(H)); - - if(!(fabsf(cosNH) < 1.0f-1e-5f && cosHO > 1e-5f)) - return Color3(0, 0, 0); - - float cosNHdivHO = cosNH / cosHO; - cosNHdivHO = max(cosNHdivHO, 1e-5f); - - float fac1 = 2 * fabsf(cosNHdivHO * cosNO); - float fac2 = 2 * fabsf(cosNHdivHO * cosNI); - - float sinNH2 = 1 - cosNH * cosNH; - float sinNH4 = sinNH2 * sinNH2; - float cotangent2 = (cosNH * cosNH) / sinNH2; - - float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4; - float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically - - float out = 0.25f * (D * G) / cosNO; - - pdf = 0.5f * (float) M_1_PI; - return Color3(out, out, out); - } - return Color3(0, 0, 0); - } - - Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3(0, 0, 0); - } - - ustring sample(const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - // we are viewing the surface from above - send a ray out with uniform - // distribution over the hemisphere - sample_uniform_hemisphere(m_N, omega_out, randu, randv, omega_in, pdf); - if (Ng.dot(omega_in) > 0) { - Vec3 H = omega_in + omega_out; - H.normalize(); - - float cosNI = m_N.dot(omega_in); - float cosNO = m_N.dot(omega_out); - float cosNH = m_N.dot(H); - float cosHO = fabsf(omega_out.dot(H)); - - if(fabsf(cosNO) > 1e-5f && fabsf(cosNH) < 1.0f-1e-5f && cosHO > 1e-5f) { - float cosNHdivHO = cosNH / cosHO; - cosNHdivHO = max(cosNHdivHO, 1e-5f); - - float fac1 = 2 * fabsf(cosNHdivHO * cosNO); - float fac2 = 2 * fabsf(cosNHdivHO * cosNI); - - float sinNH2 = 1 - cosNH * cosNH; - float sinNH4 = sinNH2 * sinNH2; - float cotangent2 = (cosNH * cosNH) / sinNH2; - - float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4; - float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically - - float power = 0.25f * (D * G) / cosNO; - - eval.setValue(power, power, power); - - // TODO: find a better approximation for the retroreflective bounce - domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; - domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; - domega_in_dx *= 125; - domega_in_dy *= 125; - } - else - pdf = 0; - } - else - pdf = 0; - return Labels::REFLECT; - } - -}; - - - -ClosureParam *bsdf_ashikhmin_velvet_params() -{ - static ClosureParam params[] = { - CLOSURE_VECTOR_PARAM(AshikhminVelvetClosure, m_N), - CLOSURE_FLOAT_PARAM(AshikhminVelvetClosure, m_sigma), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(AshikhminVelvetClosure) - }; - return params; -} - -CLOSURE_PREPARE(bsdf_ashikhmin_velvet_prepare, AshikhminVelvetClosure) - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/osl/bsdf_diffuse.cpp b/intern/cycles/kernel/osl/bsdf_diffuse.cpp deleted file mode 100644 index 1e06d3b583f..00000000000 --- a/intern/cycles/kernel/osl/bsdf_diffuse.cpp +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Adapted from Open Shading Language with this license: - * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sony Pictures Imageworks nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <OpenImageIO/fmath.h> - -#include <OSL/genclosure.h> - -#include "osl_closures.h" - -#include "util_math.h" - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -class DiffuseClosure : public BSDFClosure { -public: - Vec3 m_N; - - DiffuseClosure() : BSDFClosure(Labels::DIFFUSE) {} - - void setup() {}; - - bool mergeable(const ClosurePrimitive *other) const { - const DiffuseClosure *comp = (const DiffuseClosure *)other; - return m_N == comp->m_N && BSDFClosure::mergeable(other); - } - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { return "diffuse"; } - - void print_on(std::ostream &out) const - { - out << name() << " ((" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))"; - } - - float albedo(const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - float cos_pi = max(m_N.dot(omega_in), 0.0f) * (float) M_1_PI; - pdf = cos_pi; - return Color3(cos_pi, cos_pi, cos_pi); - } - - Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3(0, 0, 0); - } - - ustring sample(const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - // we are viewing the surface from the right side - send a ray out with cosine - // distribution over the hemisphere - sample_cos_hemisphere(m_N, omega_out, randu, randv, omega_in, pdf); - if (Ng.dot(omega_in) > 0) { - eval.setValue(pdf, pdf, pdf); - // TODO: find a better approximation for the diffuse bounce - domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; - domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; - domega_in_dx *= 125; - domega_in_dy *= 125; - } - else - pdf = 0; - return Labels::REFLECT; - } -}; - - - -class TranslucentClosure : public BSDFClosure { -public: - Vec3 m_N; - - TranslucentClosure() : BSDFClosure(Labels::DIFFUSE, Back) {} - - void setup() {}; - - bool mergeable(const ClosurePrimitive *other) const { - const TranslucentClosure *comp = (const TranslucentClosure *)other; - return m_N == comp->m_N && BSDFClosure::mergeable(other); - } - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { return "translucent"; } - - void print_on(std::ostream &out) const - { - out << name() << " ((" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))"; - } - - Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3(0, 0, 0); - } - - float albedo(const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - float cos_pi = max(-m_N.dot(omega_in), 0.0f) * (float) M_1_PI; - pdf = cos_pi; - return Color3(cos_pi, cos_pi, cos_pi); - } - - ustring sample(const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - // we are viewing the surface from the right side - send a ray out with cosine - // distribution over the hemisphere - sample_cos_hemisphere(-m_N, omega_out, randu, randv, omega_in, pdf); - if (Ng.dot(omega_in) < 0) { - eval.setValue(pdf, pdf, pdf); - // TODO: find a better approximation for the diffuse bounce - domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; - domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; - domega_in_dx *= -125; - domega_in_dy *= -125; - } - else - pdf = 0; - return Labels::TRANSMIT; - } -}; - -ClosureParam *bsdf_diffuse_params() -{ - static ClosureParam params[] = { - CLOSURE_VECTOR_PARAM(DiffuseClosure, m_N), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(DiffuseClosure) - }; - return params; -} - -ClosureParam *bsdf_translucent_params() -{ - static ClosureParam params[] = { - CLOSURE_VECTOR_PARAM(TranslucentClosure, m_N), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(TranslucentClosure) - }; - return params; -} - -CLOSURE_PREPARE(bsdf_diffuse_prepare, DiffuseClosure) -CLOSURE_PREPARE(bsdf_translucent_prepare, TranslucentClosure) - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/osl/bsdf_microfacet.cpp b/intern/cycles/kernel/osl/bsdf_microfacet.cpp deleted file mode 100644 index 8446dbbe982..00000000000 --- a/intern/cycles/kernel/osl/bsdf_microfacet.cpp +++ /dev/null @@ -1,558 +0,0 @@ -/* - * Adapted from Open Shading Language with this license: - * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sony Pictures Imageworks nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <OpenImageIO/fmath.h> - -#include <OSL/genclosure.h> - -#include "osl_closures.h" - -#include "util_math.h" - -using namespace OSL; - -CCL_NAMESPACE_BEGIN - -// TODO: fresnel_dielectric is only used for derivatives, could be optimized - -// TODO: refactor these two classes so they share everything by the microfacet -// distribution terms - -// microfacet model with GGX facet distribution -// see http://www.graphics.cornell.edu/~bjw/microfacetbsdf.pdf -template <int Refractive = 0> -class MicrofacetGGXClosure : public BSDFClosure { -public: - Vec3 m_N; - float m_ag; // width parameter (roughness) - float m_eta; // index of refraction (for fresnel term) - MicrofacetGGXClosure() : BSDFClosure(Labels::GLOSSY, Refractive ? Back : Front) { m_eta = 1.0f; } - - void setup() - { - m_ag = clamp(m_ag, 1e-5f, 1.0f); - } - - bool mergeable(const ClosurePrimitive *other) const { - const MicrofacetGGXClosure *comp = (const MicrofacetGGXClosure *)other; - return m_N == comp->m_N && m_ag == comp->m_ag && - m_eta == comp->m_eta && BSDFClosure::mergeable(other); - } - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { - return Refractive ? "microfacet_ggx_refraction" : "microfacet_ggx"; - } - - void print_on(std::ostream &out) const { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_ag << ", "; - out << m_eta; - out << ")"; - } - - float albedo(const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - if (Refractive == 1) return Color3(0, 0, 0); - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNI > 0 && cosNO > 0) { - // get half vector - Vec3 Hr = omega_in + omega_out; - Hr.normalize(); - // eq. 20: (F*G*D)/(4*in*on) - // eq. 33: first we calculate D(m) with m=Hr: - float alpha2 = m_ag * m_ag; - float cosThetaM = m_N.dot(Hr); - float cosThetaM2 = cosThetaM * cosThetaM; - float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = alpha2 / ((float) M_PI * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2)); - // eq. 34: now calculate G1(i,m) and G1(o,m) - float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); - float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); - float G = G1o * G1i; - float out = (G * D) * 0.25f / cosNO; - // eq. 24 - float pm = D * cosThetaM; - // convert into pdf of the sampled direction - // eq. 38 - but see also: - // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf - pdf = pm * 0.25f / Hr.dot(omega_out); - return Color3(out, out, out); - } - return Color3(0, 0, 0); - } - - Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - if (Refractive == 0) return Color3(0, 0, 0); - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNO <= 0 || cosNI >= 0) - return Color3(0, 0, 0); // vectors on same side -- not possible - // compute half-vector of the refraction (eq. 16) - Vec3 ht = -(m_eta * omega_in + omega_out); - Vec3 Ht = ht; Ht.normalize(); - float cosHO = Ht.dot(omega_out); - - float cosHI = Ht.dot(omega_in); - // eq. 33: first we calculate D(m) with m=Ht: - float alpha2 = m_ag * m_ag; - float cosThetaM = m_N.dot(Ht); - float cosThetaM2 = cosThetaM * cosThetaM; - float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = alpha2 / ((float) M_PI * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2)); - // eq. 34: now calculate G1(i,m) and G1(o,m) - float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); - float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); - float G = G1o * G1i; - // probability - float invHt2 = 1 / ht.dot(ht); - pdf = D * fabsf(cosThetaM) * (fabsf(cosHI) * (m_eta * m_eta)) * invHt2; - float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D) * invHt2) / cosNO; - return Color3(out, out, out); - } - - ustring sample(const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - float cosNO = m_N.dot(omega_out); - if (cosNO > 0) { - Vec3 X, Y, Z = m_N; - make_orthonormals(Z, X, Y); - // generate a random microfacet normal m - // eq. 35,36: - // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2) - // and sin(atan(x)) == x/sqrt(1+x^2) - float alpha2 = m_ag * m_ag; - float tanThetaM2 = alpha2 * randu / (1 - randu); - float cosThetaM = 1 / sqrtf(1 + tanThetaM2); - float sinThetaM = cosThetaM * sqrtf(tanThetaM2); - float phiM = 2 * float(M_PI) * randv; - Vec3 m = (cosf(phiM) * sinThetaM) * X + - (sinf(phiM) * sinThetaM) * Y + - cosThetaM * Z; - if (Refractive == 0) { - float cosMO = m.dot(omega_out); - if (cosMO > 0) { - // eq. 39 - compute actual reflected direction - omega_in = 2 * cosMO * m - omega_out; - if (Ng.dot(omega_in) > 0) { - // microfacet normal is visible to this ray - // eq. 33 - float cosThetaM2 = cosThetaM * cosThetaM; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = alpha2 / (float(M_PI) * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2)); - // eq. 24 - float pm = D * cosThetaM; - // convert into pdf of the sampled direction - // eq. 38 - but see also: - // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf - pdf = pm * 0.25f / cosMO; - // eval BRDF*cosNI - float cosNI = m_N.dot(omega_in); - // eq. 34: now calculate G1(i,m) and G1(o,m) - float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); - float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); - float G = G1o * G1i; - // eq. 20: (F*G*D)/(4*in*on) - float out = (G * D) * 0.25f / cosNO; - eval.setValue(out, out, out); - domega_in_dx = (2 * m.dot(domega_out_dx)) * m - domega_out_dx; - domega_in_dy = (2 * m.dot(domega_out_dy)) * m - domega_out_dy; - - /* disabled for now - gives texture filtering problems */ -#if 0 - // Since there is some blur to this reflection, make the - // derivatives a bit bigger. In theory this varies with the - // roughness but the exact relationship is complex and - // requires more ops than are practical. - domega_in_dx *= 10; - domega_in_dy *= 10; -#endif - } - } - } - else { - // CAUTION: the i and o variables are inverted relative to the paper - // eq. 39 - compute actual refractive direction - Vec3 R, dRdx, dRdy; - Vec3 T, dTdx, dTdy; - bool inside; - fresnel_dielectric(m_eta, m, omega_out, domega_out_dx, domega_out_dy, - R, dRdx, dRdy, - T, dTdx, dTdy, - inside); - - if (!inside) { - omega_in = T; - domega_in_dx = dTdx; - domega_in_dy = dTdy; - // eq. 33 - float cosThetaM2 = cosThetaM * cosThetaM; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = alpha2 / (float(M_PI) * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2)); - // eq. 24 - float pm = D * cosThetaM; - // eval BRDF*cosNI - float cosNI = m_N.dot(omega_in); - // eq. 34: now calculate G1(i,m) and G1(o,m) - float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); - float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); - float G = G1o * G1i; - // eq. 21 - float cosHI = m.dot(omega_in); - float cosHO = m.dot(omega_out); - float Ht2 = m_eta * cosHI + cosHO; - Ht2 *= Ht2; - float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2); - // eq. 38 and eq. 17 - pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2; - eval.setValue(out, out, out); - - /* disabled for now - gives texture filtering problems */ -#if 0 - // Since there is some blur to this refraction, make the - // derivatives a bit bigger. In theory this varies with the - // roughness but the exact relationship is complex and - // requires more ops than are practical. - domega_in_dx *= 10; - domega_in_dy *= 10; -#endif - } - } - } - return Refractive ? Labels::TRANSMIT : Labels::REFLECT; - } -}; - -// microfacet model with Beckmann facet distribution -// see http://www.graphics.cornell.edu/~bjw/microfacetbsdf.pdf -template <int Refractive = 0> -class MicrofacetBeckmannClosure : public BSDFClosure { -public: - Vec3 m_N; - float m_ab; // width parameter (roughness) - float m_eta; // index of refraction (for fresnel term) - MicrofacetBeckmannClosure() : BSDFClosure(Labels::GLOSSY, Refractive ? Back : Front) { - } - - void setup() - { - m_ab = clamp(m_ab, 1e-5f, 1.0f); - } - - bool mergeable(const ClosurePrimitive *other) const { - const MicrofacetBeckmannClosure *comp = (const MicrofacetBeckmannClosure *)other; - return m_N == comp->m_N && m_ab == comp->m_ab && - m_eta == comp->m_eta && BSDFClosure::mergeable(other); - } - - size_t memsize() const { - return sizeof(*this); - } - - const char *name() const { - return Refractive ? "microfacet_beckmann_refraction" - : "microfacet_beckmann"; - } - - void print_on(std::ostream &out) const - { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_ab << ", "; - out << m_eta; - out << ")"; - } - - float albedo(const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - if (Refractive == 1) return Color3(0, 0, 0); - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNO > 0 && cosNI > 0) { - // get half vector - Vec3 Hr = omega_in + omega_out; - Hr.normalize(); - // eq. 20: (F*G*D)/(4*in*on) - // eq. 25: first we calculate D(m) with m=Hr: - float alpha2 = m_ab * m_ab; - float cosThetaM = m_N.dot(Hr); - float cosThetaM2 = cosThetaM * cosThetaM; - float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4); - // eq. 26, 27: now calculate G1(i,m) and G1(o,m) - float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO))); - float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); - float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f; - float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; - float G = G1o * G1i; - float out = (G * D) * 0.25f / cosNO; - // eq. 24 - float pm = D * cosThetaM; - // convert into pdf of the sampled direction - // eq. 38 - but see also: - // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf - pdf = pm * 0.25f / Hr.dot(omega_out); - return Color3(out, out, out); - } - return Color3(0, 0, 0); - } - - Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - if (Refractive == 0) return Color3(0, 0, 0); - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNO <= 0 || cosNI >= 0) - return Color3(0, 0, 0); - // compute half-vector of the refraction (eq. 16) - Vec3 ht = -(m_eta * omega_in + omega_out); - Vec3 Ht = ht; Ht.normalize(); - float cosHO = Ht.dot(omega_out); - - float cosHI = Ht.dot(omega_in); - // eq. 33: first we calculate D(m) with m=Ht: - float alpha2 = m_ab * m_ab; - float cosThetaM = m_N.dot(Ht); - float cosThetaM2 = cosThetaM * cosThetaM; - float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4); - // eq. 26, 27: now calculate G1(i,m) and G1(o,m) - float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO))); - float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); - float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f; - float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; - float G = G1o * G1i; - // probability - float invHt2 = 1 / ht.dot(ht); - pdf = D * fabsf(cosThetaM) * (fabsf(cosHI) * (m_eta * m_eta)) * invHt2; - float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D) * invHt2) / cosNO; - return Color3(out, out, out); - } - - ustring sample(const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - float cosNO = m_N.dot(omega_out); - if (cosNO > 0) { - Vec3 X, Y, Z = m_N; - make_orthonormals(Z, X, Y); - // generate a random microfacet normal m - // eq. 35,36: - // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2) - // and sin(atan(x)) == x/sqrt(1+x^2) - float alpha2 = m_ab * m_ab; - float tanThetaM = sqrtf(-alpha2 * logf(1 - randu)); - float cosThetaM = 1 / sqrtf(1 + tanThetaM * tanThetaM); - float sinThetaM = cosThetaM * tanThetaM; - float phiM = 2 * float(M_PI) * randv; - Vec3 m = (cosf(phiM) * sinThetaM) * X + - (sinf(phiM) * sinThetaM) * Y + - cosThetaM * Z; - if (Refractive == 0) { - float cosMO = m.dot(omega_out); - if (cosMO > 0) { - // eq. 39 - compute actual reflected direction - omega_in = 2 * cosMO * m - omega_out; - if (Ng.dot(omega_in) > 0) { - // microfacet normal is visible to this ray - // eq. 25 - float cosThetaM2 = cosThetaM * cosThetaM; - float tanThetaM2 = tanThetaM * tanThetaM; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4); - // eq. 24 - float pm = D * cosThetaM; - // convert into pdf of the sampled direction - // eq. 38 - but see also: - // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf - pdf = pm * 0.25f / cosMO; - // Eval BRDF*cosNI - float cosNI = m_N.dot(omega_in); - // eq. 26, 27: now calculate G1(i,m) and G1(o,m) - float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO))); - float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); - float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f; - float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; - float G = G1o * G1i; - // eq. 20: (F*G*D)/(4*in*on) - float out = (G * D) * 0.25f / cosNO; - eval.setValue(out, out, out); - domega_in_dx = (2 * m.dot(domega_out_dx)) * m - domega_out_dx; - domega_in_dy = (2 * m.dot(domega_out_dy)) * m - domega_out_dy; - - /* disabled for now - gives texture filtering problems */ -#if 0 - // Since there is some blur to this reflection, make the - // derivatives a bit bigger. In theory this varies with the - // roughness but the exact relationship is complex and - // requires more ops than are practical. - domega_in_dx *= 10; - domega_in_dy *= 10; -#endif - } - } - } - else { - // CAUTION: the i and o variables are inverted relative to the paper - // eq. 39 - compute actual refractive direction - Vec3 R, dRdx, dRdy; - Vec3 T, dTdx, dTdy; - bool inside; - fresnel_dielectric(m_eta, m, omega_out, domega_out_dx, domega_out_dy, - R, dRdx, dRdy, - T, dTdx, dTdy, - inside); - if (!inside) { - omega_in = T; - domega_in_dx = dTdx; - domega_in_dy = dTdy; - // eq. 33 - float cosThetaM2 = cosThetaM * cosThetaM; - float tanThetaM2 = tanThetaM * tanThetaM; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4); - // eq. 24 - float pm = D * cosThetaM; - // eval BRDF*cosNI - float cosNI = m_N.dot(omega_in); - // eq. 26, 27: now calculate G1(i,m) and G1(o,m) - float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO))); - float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); - float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f; - float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; - float G = G1o * G1i; - // eq. 21 - float cosHI = m.dot(omega_in); - float cosHO = m.dot(omega_out); - float Ht2 = m_eta * cosHI + cosHO; - Ht2 *= Ht2; - float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2); - // eq. 38 and eq. 17 - pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2; - eval.setValue(out, out, out); - - /* disabled for now - gives texture filtering problems */ -#if 0 - // Since there is some blur to this refraction, make the - // derivatives a bit bigger. In theory this varies with the - // roughness but the exact relationship is complex and - // requires more ops than are practical. - domega_in_dx *= 10; - domega_in_dy *= 10; -#endif - } - } - } - return Refractive ? Labels::TRANSMIT : Labels::REFLECT; - } -}; - - - -ClosureParam *bsdf_microfacet_ggx_params() -{ - static ClosureParam params[] = { - CLOSURE_VECTOR_PARAM(MicrofacetGGXClosure<0>, m_N), - CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure<0>, m_ag), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(MicrofacetGGXClosure<0>) - }; - return params; -} - -ClosureParam *bsdf_microfacet_ggx_refraction_params() -{ - static ClosureParam params[] = { - CLOSURE_VECTOR_PARAM(MicrofacetGGXClosure<1>, m_N), - CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure<1>, m_ag), - CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure<1>, m_eta), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(MicrofacetGGXClosure<1>) - }; - return params; -} - -ClosureParam *bsdf_microfacet_beckmann_params() -{ - static ClosureParam params[] = { - CLOSURE_VECTOR_PARAM(MicrofacetBeckmannClosure<0>, m_N), - CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure<0>, m_ab), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(MicrofacetBeckmannClosure<0>) - }; - return params; -} - -ClosureParam *bsdf_microfacet_beckmann_refraction_params() -{ - static ClosureParam params[] = { - CLOSURE_VECTOR_PARAM(MicrofacetBeckmannClosure<1>, m_N), - CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure<1>, m_ab), - CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure<1>, m_eta), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(MicrofacetBeckmannClosure<1>) - }; - return params; -} - -CLOSURE_PREPARE(bsdf_microfacet_ggx_prepare, MicrofacetGGXClosure<0>) -CLOSURE_PREPARE(bsdf_microfacet_ggx_refraction_prepare, MicrofacetGGXClosure<1>) -CLOSURE_PREPARE(bsdf_microfacet_beckmann_prepare, MicrofacetBeckmannClosure<0>) -CLOSURE_PREPARE(bsdf_microfacet_beckmann_refraction_prepare, MicrofacetBeckmannClosure<1>) - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/osl/bsdf_oren_nayar.cpp b/intern/cycles/kernel/osl/bsdf_oren_nayar.cpp deleted file mode 100644 index 2a00100c256..00000000000 --- a/intern/cycles/kernel/osl/bsdf_oren_nayar.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include <OpenImageIO/fmath.h> -#include <OSL/genclosure.h> -#include "osl_closures.h" -#include "util_math.h" - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - - -class OrenNayarClosure : public BSDFClosure { -public: - Vec3 m_N; - float m_sigma; - float m_a, m_b; - - OrenNayarClosure() : BSDFClosure(Labels::DIFFUSE) {} - - void setup() { - m_sigma = clamp(m_sigma, 0.0f, 1.0f); - - float div = 1.0f / (M_PI + ((3.0f * M_PI - 4.0f) / 6.0f) * m_sigma); - - m_a = 1.0f * div; - m_b = m_sigma * div; - } - - bool mergeable(const ClosurePrimitive *other) const { - const OrenNayarClosure *comp = static_cast<const OrenNayarClosure *>(other); - return - m_N == comp->m_N && - m_sigma == comp->m_sigma && - BSDFClosure::mergeable(other); - } - - size_t memsize() const { - return sizeof(*this); - } - - const char *name() const { - return "oren_nayar"; - } - - void print_on(std::ostream& out) const { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_sigma; - out << ")"; - } - - float albedo(const Vec3& omega_out) const { - return 1.0f; - } - - Color3 eval_reflect(const Vec3& omega_out, const Vec3& omega_in, float& pdf) const { - if (m_N.dot(omega_in) > 0.0f) { - pdf = float(0.5 * M_1_PI); - float is = get_intensity(m_N, omega_out, omega_in); - return Color3(is, is, is); - } - else { - pdf = 0.0f; - return Color3(0.0f, 0.0f, 0.0f); - } - } - - Color3 eval_transmit(const Vec3& omega_out, const Vec3& omega_in, float& pdf) const { - return Color3(0.0f, 0.0f, 0.0f); - } - - ustring sample( - const Vec3& Ng, - const Vec3& omega_out, const Vec3& domega_out_dx, const Vec3& domega_out_dy, - float randu, float randv, - Vec3& omega_in, Vec3& domega_in_dx, Vec3& domega_in_dy, - float& pdf, Color3& eval - ) const { - sample_uniform_hemisphere(m_N, omega_out, randu, randv, omega_in, pdf); - - if (Ng.dot(omega_in) > 0.0f) { - float is = get_intensity(m_N, omega_out, omega_in); - eval.setValue(is, is, is); - - // TODO: find a better approximation for the bounce - domega_in_dx = (2.0f * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; - domega_in_dy = (2.0f * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; - domega_in_dx *= 125.0f; - domega_in_dy *= 125.0f; - } - else { - pdf = 0.0f; - } - - return Labels::REFLECT; - } - -private: - float get_intensity(Vec3 const& n, Vec3 const& v, Vec3 const& l) const { - float nl = max(n.dot(l), 0.0f); - float nv = max(n.dot(v), 0.0f); - float t = l.dot(v) - nl * nv; - - if (t > 0.0f) { - t /= max(nl, nv) + 1e-8f; - } - return nl * (m_a + m_b * t); - } -}; - -ClosureParam *bsdf_oren_nayar_params() -{ - static ClosureParam params[] = { - CLOSURE_VECTOR_PARAM(OrenNayarClosure, m_N), - CLOSURE_FLOAT_PARAM(OrenNayarClosure, m_sigma), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(OrenNayarClosure) - }; - return params; -} - -CLOSURE_PREPARE(bsdf_oren_nayar_prepare, OrenNayarClosure) - - -CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/bsdf_phong.cpp b/intern/cycles/kernel/osl/bsdf_phong.cpp deleted file mode 100644 index 1f430cc6f5d..00000000000 --- a/intern/cycles/kernel/osl/bsdf_phong.cpp +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Adapted from Open Shading Language with this license: - * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2012, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sony Pictures Imageworks nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <OpenImageIO/fmath.h> - -#include <OSL/genclosure.h> -#include "osl_closures.h" -#include "util_math.h" - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -// vanilla phong - leaks energy at grazing angles -// see Global Illumination Compendium entry (66) -class PhongClosure : public BSDFClosure { -public: - Vec3 m_N; - float m_exponent; - PhongClosure() : BSDFClosure(Labels::GLOSSY) { } - - void setup() {}; - - bool mergeable (const ClosurePrimitive *other) const { - const PhongClosure *comp = (const PhongClosure *)other; - return m_N == comp->m_N && m_exponent == comp->m_exponent && - BSDFClosure::mergeable(other); - } - - size_t memsize () const { return sizeof(*this); } - - const char *name () const { return "phong"; } - - void print_on (std::ostream &out) const { - out << name() << " (("; - out << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_exponent << ")"; - } - - float albedo (const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - float cosNI = m_N.dot(omega_in); - float cosNO = m_N.dot(omega_out); - if (cosNI > 0 && cosNO > 0) { - // reflect the view vector - Vec3 R = (2 * cosNO) * m_N - omega_out; - float cosRI = R.dot(omega_in); - if (cosRI > 0) { - float common = 0.5f * (float) M_1_PI * powf(cosRI, m_exponent); - float out = cosNI * (m_exponent + 2) * common; - pdf = (m_exponent + 1) * common; - return Color3 (out, out, out); - } - } - return Color3 (0, 0, 0); - } - - Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3 (0, 0, 0); - } - - ustring sample (const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - float cosNO = m_N.dot(omega_out); - if (cosNO > 0) { - // reflect the view vector - Vec3 R = (2 * cosNO) * m_N - omega_out; - domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; - domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; - Vec3 T, B; - make_orthonormals (R, T, B); - float phi = 2 * (float) M_PI * randu; - float cosTheta = powf(randv, 1 / (m_exponent + 1)); - float sinTheta2 = 1 - cosTheta * cosTheta; - float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0; - omega_in = (cosf(phi) * sinTheta) * T + - (sinf(phi) * sinTheta) * B + - ( cosTheta) * R; - if (Ng.dot(omega_in) > 0) - { - // common terms for pdf and eval - float cosNI = m_N.dot(omega_in); - // make sure the direction we chose is still in the right hemisphere - if (cosNI > 0) - { - float common = 0.5f * (float) M_1_PI * powf(cosTheta, m_exponent); - pdf = (m_exponent + 1) * common; - float out = cosNI * (m_exponent + 2) * common; - eval.setValue(out, out, out); - // Since there is some blur to this reflection, make the - // derivatives a bit bigger. In theory this varies with the - // exponent but the exact relationship is complex and - // requires more ops than are practical. - domega_in_dx *= 10; - domega_in_dy *= 10; - } - } - } - return Labels::REFLECT; - } -}; - - -class PhongRampClosure : public BSDFClosure { -public: - static const int MAXCOLORS = 8; - Vec3 m_N; - float m_exponent; - Color3 m_colors[MAXCOLORS]; - PhongRampClosure() : BSDFClosure(Labels::GLOSSY) { } - - void setup() {}; - - bool mergeable (const ClosurePrimitive *other) const { - const PhongRampClosure *comp = (const PhongRampClosure *)other; - if (! (m_N == comp->m_N && m_exponent == comp->m_exponent && - BSDFClosure::mergeable(other))) - return false; - for (int i = 0; i < MAXCOLORS; ++i) - if (m_colors[i] != comp->m_colors[i]) - return false; - return true; - } - - size_t memsize () const { return sizeof(*this); } - - const char *name () const { return "phong_ramp"; } - - void print_on (std::ostream &out) const { - out << name() << " (("; - out << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_exponent << ")"; - } - - Color3 get_color (float pos) const - { - float npos = pos * (float)(MAXCOLORS - 1); - int ipos = (int)npos; - if (ipos >= (MAXCOLORS - 1)) - return m_colors[MAXCOLORS - 1]; - float offset = npos - (float)ipos; - return m_colors[ipos] * (1.0f - offset) + m_colors[ipos+1] * offset; - } - - float albedo (const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - float cosNI = m_N.dot(omega_in); - float cosNO = m_N.dot(omega_out); - if (cosNI > 0 && cosNO > 0) { - // reflect the view vector - Vec3 R = (2 * cosNO) * m_N - omega_out; - float cosRI = R.dot(omega_in); - if (cosRI > 0) { - float cosp = powf(cosRI, m_exponent); - float common = 0.5f * (float) M_1_PI * cosp; - float out = cosNI * (m_exponent + 2) * common; - pdf = (m_exponent + 1) * common; - return get_color(cosp) * out; - } - } - return Color3 (0, 0, 0); - } - - Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3 (0, 0, 0); - } - - ustring sample (const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - float cosNO = m_N.dot(omega_out); - if (cosNO > 0) { - // reflect the view vector - Vec3 R = (2 * cosNO) * m_N - omega_out; - domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; - domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; - Vec3 T, B; - make_orthonormals (R, T, B); - float phi = 2 * (float) M_PI * randu; - float cosTheta = powf(randv, 1 / (m_exponent + 1)); - float sinTheta2 = 1 - cosTheta * cosTheta; - float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0; - omega_in = (cosf(phi) * sinTheta) * T + - (sinf(phi) * sinTheta) * B + - ( cosTheta) * R; - if (Ng.dot(omega_in) > 0) - { - // common terms for pdf and eval - float cosNI = m_N.dot(omega_in); - // make sure the direction we chose is still in the right hemisphere - if (cosNI > 0) - { - float cosp = powf(cosTheta, m_exponent); - float common = 0.5f * (float) M_1_PI * cosp; - pdf = (m_exponent + 1) * common; - float out = cosNI * (m_exponent + 2) * common; - eval = get_color(cosp) * out; - // Since there is some blur to this reflection, make the - // derivatives a bit bigger. In theory this varies with the - // exponent but the exact relationship is complex and - // requires more ops than are practical. - domega_in_dx *= 10; - domega_in_dy *= 10; - } - } - } - return Labels::REFLECT; - } -}; - - - -ClosureParam *bsdf_phong_params() -{ - static ClosureParam params[] = { - CLOSURE_VECTOR_PARAM(PhongClosure, m_N), - CLOSURE_FLOAT_PARAM (PhongClosure, m_exponent), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(PhongClosure) - }; - return params; -} - -ClosureParam *bsdf_phong_ramp_params() -{ - static ClosureParam params[] = { - CLOSURE_VECTOR_PARAM (PhongRampClosure, m_N), - CLOSURE_FLOAT_PARAM (PhongRampClosure, m_exponent), - CLOSURE_COLOR_ARRAY_PARAM(PhongRampClosure, m_colors, PhongRampClosure::MAXCOLORS), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM (PhongRampClosure) - }; - return params; -} - -CLOSURE_PREPARE(bsdf_phong_prepare, PhongClosure) -CLOSURE_PREPARE(bsdf_phong_ramp_prepare, PhongRampClosure) - -CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/bssrdf.cpp b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp index 889e8a54796..fb144be7e50 100644 --- a/intern/cycles/kernel/osl/bssrdf.cpp +++ b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp @@ -36,75 +36,80 @@ #include "osl_closures.h" +#include "kernel_types.h" +#include "closure/bsdf_phong_ramp.h" + CCL_NAMESPACE_BEGIN using namespace OSL; -class BSSRDFCubicClosure : public BSSRDFClosure { +class PhongRampClosure : public CBSDFClosure { public: - Color3 m_radius; - Color3 m_scale; - float m_max_radius; - - template <typename T> - static inline T pow3(const T &x) { return x * x * x; } + PhongRampClosure() : CBSDFClosure(LABEL_GLOSSY) {} + Color3 colors[8]; + float3 fcolors[8]; - template <typename T> - static inline T pow5(const T &x) { T x2 = x * x; return x2 * x2 * x; } - - BSSRDFCubicClosure() {} + size_t memsize() const { return sizeof(*this); } + const char *name() const { return "phong_ramp"; } void setup() { - // pre-compute some terms - m_max_radius = 0; - for (int i = 0; i < 3; i++) { - m_scale[i] = m_radius[i] > 0 ? 4 / pow5(m_radius[i]) : 0; - m_max_radius = std::max(m_max_radius, m_radius[i]); - } - } + sc.N = TO_FLOAT3(N); + m_shaderdata_flag = bsdf_phong_ramp_setup(&sc); - bool mergeable(const ClosurePrimitive *other) const { - const BSSRDFCubicClosure *comp = (const BSSRDFCubicClosure *)other; - return m_radius == comp->m_radius && BSSRDFClosure::mergeable(other); + for(int i = 0; i < 8; i++) + fcolors[i] = TO_FLOAT3(colors[i]); } - size_t memsize() const { return sizeof(*this); } + bool mergeable(const ClosurePrimitive *other) const + { + return false; + } - const char *name() const { return "bssrdf_cubic"; } + void blur(float roughness) + { + bsdf_phong_ramp_blur(&sc, roughness); + } void print_on(std::ostream &out) const { - out << name() << " ((" << m_radius[0] << ", " << m_radius[1] << ", " << m_radius[2] << "), (" - << m_scale[0] << ", " << m_scale[1] << ", " << m_scale[2] << "))"; + out << name() << " ((" << sc.N[0] << ", " << sc.N[1] << ", " << sc.N[2] << "))"; } - Color3 eval(float r) const + float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const { - return Color3((r < m_radius.x) ? pow3(m_radius.x - r) * m_scale.x : 0, - (r < m_radius.y) ? pow3(m_radius.y - r) * m_scale.y : 0, - (r < m_radius.z) ? pow3(m_radius.z - r) * m_scale.z : 0); + return bsdf_phong_ramp_eval_reflect(&sc, fcolors, omega_out, omega_in, &pdf); } - float max_radius() const + float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float& pdf) const { - return m_max_radius; + return bsdf_phong_ramp_eval_transmit(&sc, fcolors, omega_out, omega_in, &pdf); } -}; - + int sample(const float3 &Ng, + const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy, + float randu, float randv, + float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy, + float &pdf, float3 &eval) const + { + return bsdf_phong_ramp_sample(&sc, fcolors, Ng, omega_out, domega_out_dx, domega_out_dy, + randu, randv, &eval, &omega_in, &domega_in_dx, &domega_in_dy, &pdf); + } +}; -ClosureParam *closure_bssrdf_cubic_params() +ClosureParam *closure_bsdf_phong_ramp_params() { static ClosureParam params[] = { - CLOSURE_COLOR_PARAM(BSSRDFCubicClosure, m_radius), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(BSSRDFCubicClosure) + CLOSURE_VECTOR_PARAM(PhongRampClosure, N), + CLOSURE_FLOAT_PARAM(PhongRampClosure, sc.data0), + CLOSURE_COLOR_ARRAY_PARAM(PhongRampClosure, colors, 8), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(PhongRampClosure) }; return params; } -CLOSURE_PREPARE(closure_bssrdf_cubic_prepare, BSSRDFCubicClosure) +CLOSURE_PREPARE(closure_bsdf_phong_ramp_prepare, PhongRampClosure) CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/bsdf_reflection.cpp b/intern/cycles/kernel/osl/bsdf_reflection.cpp deleted file mode 100644 index 1b85ec146d3..00000000000 --- a/intern/cycles/kernel/osl/bsdf_reflection.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Adapted from Open Shading Language with this license: - * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sony Pictures Imageworks nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <OpenImageIO/fmath.h> - -#include <OSL/genclosure.h> - -#include "osl_closures.h" - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -class ReflectionClosure : public BSDFClosure { -public: - Vec3 m_N; // shading normal - ReflectionClosure() : BSDFClosure(Labels::SINGULAR) {} - - void setup() {}; - - bool mergeable(const ClosurePrimitive *other) const { - const ReflectionClosure *comp = (const ReflectionClosure *)other; - return m_N == comp->m_N && BSDFClosure::mergeable(other); - } - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { return "reflection"; } - - void print_on(std::ostream &out) const { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))"; - } - - float albedo(const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3(0, 0, 0); - } - - Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3(0, 0, 0); - } - - ustring sample(const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - // only one direction is possible - float cosNO = m_N.dot(omega_out); - if (cosNO > 0) { - omega_in = (2 * cosNO) * m_N - omega_out; - if (Ng.dot(omega_in) > 0) { - domega_in_dx = 2 * m_N.dot(domega_out_dx) * m_N - domega_out_dx; - domega_in_dy = 2 * m_N.dot(domega_out_dy) * m_N - domega_out_dy; - pdf = 1; - eval.setValue(1, 1, 1); - } - } - return Labels::REFLECT; - } -}; - -ClosureParam *bsdf_reflection_params() -{ - static ClosureParam params[] = { - CLOSURE_VECTOR_PARAM(ReflectionClosure, m_N), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(ReflectionClosure) - }; - return params; -} - -CLOSURE_PREPARE(bsdf_reflection_prepare, ReflectionClosure) - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/osl/bsdf_refraction.cpp b/intern/cycles/kernel/osl/bsdf_refraction.cpp deleted file mode 100644 index 76ee53f7929..00000000000 --- a/intern/cycles/kernel/osl/bsdf_refraction.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Adapted from Open Shading Language with this license: - * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sony Pictures Imageworks nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <OpenImageIO/fmath.h> - -#include <OSL/genclosure.h> - -#include "osl_closures.h" - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -class RefractionClosure : public BSDFClosure { -public: - Vec3 m_N; // shading normal - float m_eta; // ratio of indices of refraction (inside / outside) - RefractionClosure() : BSDFClosure(Labels::SINGULAR, Back) {} - - void setup() {} - - bool mergeable(const ClosurePrimitive *other) const { - const RefractionClosure *comp = (const RefractionClosure *)other; - return m_N == comp->m_N && m_eta == comp->m_eta && - BSDFClosure::mergeable(other); - } - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { return "refraction"; } - - void print_on(std::ostream &out) const { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_eta; - out << ")"; - } - - Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3(0, 0, 0); - } - - Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3(0, 0, 0); - } - - float albedo(const Vec3 &omega_out) const - { - return 1.0f; - } - - ustring sample(const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - Vec3 R, dRdx, dRdy; - Vec3 T, dTdx, dTdy; - bool inside; - - fresnel_dielectric(m_eta, m_N, - omega_out, domega_out_dx, domega_out_dy, - R, dRdx, dRdy, - T, dTdx, dTdy, - inside); - - if (!inside) { - pdf = 1; - eval.setValue(1.0f, 1.0f, 1.0f); - omega_in = T; - domega_in_dx = dTdx; - domega_in_dy = dTdy; - } - - return Labels::TRANSMIT; - } -}; - -ClosureParam *bsdf_refraction_params() -{ - static ClosureParam params[] = { - CLOSURE_VECTOR_PARAM(RefractionClosure, m_N), - CLOSURE_FLOAT_PARAM(RefractionClosure, m_eta), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(RefractionClosure) - }; - return params; -} - -CLOSURE_PREPARE(bsdf_refraction_prepare, RefractionClosure) - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/osl/bsdf_transparent.cpp b/intern/cycles/kernel/osl/bsdf_transparent.cpp deleted file mode 100644 index 29cef8e192f..00000000000 --- a/intern/cycles/kernel/osl/bsdf_transparent.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Adapted from Open Shading Language with this license: - * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sony Pictures Imageworks nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <OpenImageIO/fmath.h> - -#include <OSL/genclosure.h> - -#include "osl_closures.h" - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -class TransparentClosure : public BSDFClosure { -public: - TransparentClosure() : BSDFClosure(Labels::STRAIGHT, Back) {} - - void setup() {} - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { return "transparent"; } - - void print_on(std::ostream &out) const { - out << name() << " ()"; - } - - float albedo(const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3(0, 0, 0); - } - - Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3(0, 0, 0); - } - - ustring sample(const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - // only one direction is possible - omega_in = -omega_out; - domega_in_dx = -domega_out_dx; - domega_in_dy = -domega_out_dy; - pdf = 1; - eval.setValue(1, 1, 1); - return Labels::TRANSMIT; - } -}; - - - -ClosureParam *bsdf_transparent_params() -{ - static ClosureParam params[] = { - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(TransparentClosure) - }; - return params; -} - -CLOSURE_PREPARE(bsdf_transparent_prepare, TransparentClosure) - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/osl/bsdf_ward.cpp b/intern/cycles/kernel/osl/bsdf_ward.cpp deleted file mode 100644 index 9d8d2fc4b76..00000000000 --- a/intern/cycles/kernel/osl/bsdf_ward.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Adapted from Open Shading Language with this license: - * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sony Pictures Imageworks nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <OpenImageIO/fmath.h> - -#include <OSL/genclosure.h> - -#include "osl_closures.h" - -#include "util_math.h" - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -// anisotropic ward - leaks energy at grazing angles -// see http://www.graphics.cornell.edu/~bjw/wardnotes.pdf -class WardClosure : public BSDFClosure { -public: - Vec3 m_N; - Vec3 m_T; - float m_ax, m_ay; - WardClosure() : BSDFClosure(Labels::GLOSSY) {} - - void setup() - { - m_ax = clamp(m_ax, 1e-5f, 1.0f); - m_ay = clamp(m_ay, 1e-5f, 1.0f); - } - - bool mergeable(const ClosurePrimitive *other) const { - const WardClosure *comp = (const WardClosure *)other; - return m_N == comp->m_N && m_T == comp->m_T && - m_ax == comp->m_ax && m_ay == comp->m_ay && - BSDFClosure::mergeable(other); - } - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { return "ward"; } - - void print_on(std::ostream &out) const { - out << name() << " (("; - out << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ("; - out << m_T[0] << ", " << m_T[1] << ", " << m_T[2] << "), "; - out << m_ax << ", " << m_ay << ")"; - } - - float albedo(const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNI > 0 && cosNO > 0) { - // get half vector and get x,y basis on the surface for anisotropy - Vec3 H = omega_in + omega_out; - H.normalize(); // normalize needed for pdf - Vec3 X, Y; - make_orthonormals(m_N, m_T, X, Y); - // eq. 4 - float dotx = H.dot(X) / m_ax; - float doty = H.dot(Y) / m_ay; - float dotn = H.dot(m_N); - float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn); - float denom = (4 * (float) M_PI * m_ax * m_ay * sqrtf(cosNO * cosNI)); - float exp_val = expf(-exp_arg); - float out = cosNI * exp_val / denom; - float oh = H.dot(omega_out); - denom = 4 * (float) M_PI * m_ax * m_ay * oh * dotn * dotn * dotn; - pdf = exp_val / denom; - return Color3(out, out, out); - } - return Color3(0, 0, 0); - } - - Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3(0, 0, 0); - } - - ustring sample(const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - float cosNO = m_N.dot(omega_out); - if (cosNO > 0) { - // get x,y basis on the surface for anisotropy - Vec3 X, Y; - make_orthonormals(m_N, m_T, X, Y); - // generate random angles for the half vector - // eq. 7 (taking care around discontinuities to keep - // output angle in the right quadrant) - // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2) - // and sin(atan(x)) == x/sqrt(1+x^2) - float alphaRatio = m_ay / m_ax; - float cosPhi, sinPhi; - if (randu < 0.25f) { - float val = 4 * randu; - float tanPhi = alphaRatio * tanf((float) M_PI_2 * val); - cosPhi = 1 / sqrtf(1 + tanPhi * tanPhi); - sinPhi = tanPhi * cosPhi; - } - else if (randu < 0.5) { - float val = 1 - 4 * (0.5f - randu); - float tanPhi = alphaRatio * tanf((float) M_PI_2 * val); - // phi = (float) M_PI - phi; - cosPhi = -1 / sqrtf(1 + tanPhi * tanPhi); - sinPhi = -tanPhi * cosPhi; - } - else if (randu < 0.75f) { - float val = 4 * (randu - 0.5f); - float tanPhi = alphaRatio * tanf((float) M_PI_2 * val); - //phi = (float) M_PI + phi; - cosPhi = -1 / sqrtf(1 + tanPhi * tanPhi); - sinPhi = tanPhi * cosPhi; - } - else { - float val = 1 - 4 * (1 - randu); - float tanPhi = alphaRatio * tanf((float) M_PI_2 * val); - // phi = 2 * (float) M_PI - phi; - cosPhi = 1 / sqrtf(1 + tanPhi * tanPhi); - sinPhi = -tanPhi * cosPhi; - } - // eq. 6 - // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2) - // and sin(atan(x)) == x/sqrt(1+x^2) - float thetaDenom = (cosPhi * cosPhi) / (m_ax * m_ax) + (sinPhi * sinPhi) / (m_ay * m_ay); - float tanTheta2 = -logf(1 - randv) / thetaDenom; - float cosTheta = 1 / sqrtf(1 + tanTheta2); - float sinTheta = cosTheta * sqrtf(tanTheta2); - - Vec3 h; // already normalized becaused expressed from spherical coordinates - h.x = sinTheta * cosPhi; - h.y = sinTheta * sinPhi; - h.z = cosTheta; - // compute terms that are easier in local space - float dotx = h.x / m_ax; - float doty = h.y / m_ay; - float dotn = h.z; - // transform to world space - h = h.x * X + h.y * Y + h.z * m_N; - // generate the final sample - float oh = h.dot(omega_out); - omega_in.x = 2 * oh * h.x - omega_out.x; - omega_in.y = 2 * oh * h.y - omega_out.y; - omega_in.z = 2 * oh * h.z - omega_out.z; - if (Ng.dot(omega_in) > 0) { - float cosNI = m_N.dot(omega_in); - if (cosNI > 0) { - // eq. 9 - float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn); - float denom = 4 * (float) M_PI * m_ax * m_ay * oh * dotn * dotn * dotn; - pdf = expf(-exp_arg) / denom; - // compiler will reuse expressions already computed - denom = (4 * (float) M_PI * m_ax * m_ay * sqrtf(cosNO * cosNI)); - float power = cosNI * expf(-exp_arg) / denom; - eval.setValue(power, power, power); - domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; - domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; - - /* disabled for now - gives texture filtering problems */ -#if 0 - // Since there is some blur to this reflection, make the - // derivatives a bit bigger. In theory this varies with the - // roughness but the exact relationship is complex and - // requires more ops than are practical. - domega_in_dx *= 10; - domega_in_dy *= 10; -#endif - } - } - } - return Labels::REFLECT; - } -}; - - - -ClosureParam *bsdf_ward_params() -{ - static ClosureParam params[] = { - CLOSURE_VECTOR_PARAM(WardClosure, m_N), - CLOSURE_VECTOR_PARAM(WardClosure, m_T), - CLOSURE_FLOAT_PARAM(WardClosure, m_ax), - CLOSURE_FLOAT_PARAM(WardClosure, m_ay), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(WardClosure) - }; - return params; -} - -CLOSURE_PREPARE(bsdf_ward_prepare, WardClosure) - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/osl/bsdf_westin.cpp b/intern/cycles/kernel/osl/bsdf_westin.cpp deleted file mode 100644 index 6716376ad3e..00000000000 --- a/intern/cycles/kernel/osl/bsdf_westin.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Adapted from Open Shading Language with this license: - * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sony Pictures Imageworks nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <OpenImageIO/fmath.h> - -#include <OSL/genclosure.h> - -#include "osl_closures.h" - -#include "util_math.h" - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -class WestinBackscatterClosure : public BSDFClosure { -public: - Vec3 m_N; - float m_roughness; - float m_invroughness; - WestinBackscatterClosure() : BSDFClosure(Labels::GLOSSY) {} - - void setup() - { - m_roughness = clamp(m_roughness, 1e-5f, 1.0f); - m_invroughness = m_roughness > 0 ? 1 / m_roughness : 0; - } - - bool mergeable(const ClosurePrimitive *other) const { - const WestinBackscatterClosure *comp = (const WestinBackscatterClosure *)other; - return m_N == comp->m_N && m_roughness == comp->m_roughness && - BSDFClosure::mergeable(other); - } - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { return "westin_backscatter"; } - - void print_on(std::ostream &out) const - { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_roughness; - out << ")"; - } - - float albedo(const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const - { - // pdf is implicitly 0 (no indirect sampling) - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNO > 0 && cosNI > 0) { - float cosine = omega_out.dot(omega_in); - pdf = cosine > 0 ? (m_invroughness + 1) * powf(cosine, m_invroughness) : 0; - pdf *= 0.5f * float(M_1_PI); - return Color3(pdf, pdf, pdf); - } - return Color3(0, 0, 0); - } - - Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const - { - return Color3(0, 0, 0); - } - - ustring sample(const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - float cosNO = m_N.dot(omega_out); - if (cosNO > 0) { - domega_in_dx = domega_out_dx; - domega_in_dy = domega_out_dy; - Vec3 T, B; - make_orthonormals(omega_out, T, B); - float phi = 2 * (float) M_PI * randu; - float cosTheta = powf(randv, 1 / (m_invroughness + 1)); - float sinTheta2 = 1 - cosTheta * cosTheta; - float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0; - omega_in = (cosf(phi) * sinTheta) * T + - (sinf(phi) * sinTheta) * B + - (cosTheta) * omega_out; - if (Ng.dot(omega_in) > 0) - { - // common terms for pdf and eval - float cosNI = m_N.dot(omega_in); - // make sure the direction we chose is still in the right hemisphere - if (cosNI > 0) - { - pdf = 0.5f * (float) M_1_PI * powf(cosTheta, m_invroughness); - pdf = (m_invroughness + 1) * pdf; - eval.setValue(pdf, pdf, pdf); - // Since there is some blur to this reflection, make the - // derivatives a bit bigger. In theory this varies with the - // exponent but the exact relationship is complex and - // requires more ops than are practical. - domega_in_dx *= 10; - domega_in_dy *= 10; - } - } - } - return Labels::REFLECT; - } - -}; - - -class WestinSheenClosure : public BSDFClosure { -public: - Vec3 m_N; - float m_edginess; -// float m_normalization; - WestinSheenClosure() : BSDFClosure(Labels::DIFFUSE) {} - - void setup() {}; - - bool mergeable(const ClosurePrimitive *other) const { - const WestinSheenClosure *comp = (const WestinSheenClosure *)other; - return m_N == comp->m_N && m_edginess == comp->m_edginess && - BSDFClosure::mergeable(other); - } - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { return "westin_sheen"; } - - void print_on(std::ostream &out) const - { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_edginess; - out << ")"; - } - - float albedo(const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const - { - // pdf is implicitly 0 (no indirect sampling) - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNO > 0 && cosNI > 0) { - float sinNO2 = 1 - cosNO * cosNO; - pdf = cosNI * float(M_1_PI); - float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * pdf : 0; - return Color3(westin, westin, westin); - } - return Color3(0, 0, 0); - } - - Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const - { - return Color3(0, 0, 0); - } - - ustring sample(const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - // we are viewing the surface from the right side - send a ray out with cosine - // distribution over the hemisphere - sample_cos_hemisphere(m_N, omega_out, randu, randv, omega_in, pdf); - if (Ng.dot(omega_in) > 0) { - // TODO: account for sheen when sampling - float cosNO = m_N.dot(omega_out); - float sinNO2 = 1 - cosNO * cosNO; - float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * pdf : 0; - eval.setValue(westin, westin, westin); - // TODO: find a better approximation for the diffuse bounce - domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; - domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; - domega_in_dx *= 125; - domega_in_dy *= 125; - } - else { - pdf = 0; - } - return Labels::REFLECT; - } -}; - - - -ClosureParam *bsdf_westin_backscatter_params() -{ - static ClosureParam params[] = { - CLOSURE_VECTOR_PARAM(WestinBackscatterClosure, m_N), - CLOSURE_FLOAT_PARAM(WestinBackscatterClosure, m_roughness), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(WestinBackscatterClosure) - }; - return params; -} - -ClosureParam *bsdf_westin_sheen_params() -{ - static ClosureParam params[] = { - CLOSURE_VECTOR_PARAM(WestinSheenClosure, m_N), - CLOSURE_FLOAT_PARAM(WestinSheenClosure, m_edginess), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(WestinSheenClosure) - }; - return params; -} - -CLOSURE_PREPARE(bsdf_westin_backscatter_prepare, WestinBackscatterClosure) -CLOSURE_PREPARE(bsdf_westin_sheen_prepare, WestinSheenClosure) - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/osl/debug.cpp b/intern/cycles/kernel/osl/debug.cpp deleted file mode 100644 index ee5fb30371a..00000000000 --- a/intern/cycles/kernel/osl/debug.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Adapted from Open Shading Language with this license: - * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sony Pictures Imageworks nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <OpenImageIO/fmath.h> - -#include <OSL/genclosure.h> - -#include "osl_closures.h" - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -/// Debug closure -/// -/// This is going to be used for mask AOV's and similar -/// purposes. A tag (string) is always associated with -/// this closure, that "selects: the channel where the -/// weight should be sent. - -class DebugClosure : public ClosurePrimitive { -public: - ustring m_tag; - - DebugClosure () : ClosurePrimitive(Debug) {} - - bool mergeable(const ClosurePrimitive *other) const { - const DebugClosure *comp = (const DebugClosure *)other; - return m_tag == comp->m_tag && - ClosurePrimitive::mergeable(other); - } - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { return "debug"; } - - void print_on(std::ostream &out) const { - out << name() << " (\"" << m_tag.c_str() << "\")"; - } - -}; - -ClosureParam *closure_debug_params() -{ - static ClosureParam params[] = { - CLOSURE_STRING_PARAM(DebugClosure, m_tag), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(DebugClosure) - }; - return params; -} - -CLOSURE_PREPARE(closure_debug_prepare, DebugClosure) - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/osl/emissive.cpp b/intern/cycles/kernel/osl/emissive.cpp index 3ee57cbe6b6..37e3e37c00a 100644 --- a/intern/cycles/kernel/osl/emissive.cpp +++ b/intern/cycles/kernel/osl/emissive.cpp @@ -36,6 +36,9 @@ #include "osl_closures.h" +#include "kernel_types.h" +#include "closure/emissive.h" + CCL_NAMESPACE_BEGIN using namespace OSL; @@ -52,51 +55,34 @@ public: GenericEmissiveClosure() { } void setup() {} - size_t memsize() const { return sizeof(*this); } - const char *name() const { return "emission"; } - void print_on(std::ostream &out) const { + void print_on(std::ostream &out) const + { out << name() << "()"; } Color3 eval(const Vec3 &Ng, const Vec3 &omega_out) const { - float cosNO = fabsf(Ng.dot(omega_out)); - float res = cosNO > 0 ? 1.0f : 0.0f; - return Color3(res, res, res); + float3 result = emissive_eval(TO_FLOAT3(Ng), TO_FLOAT3(omega_out)); + return TO_COLOR3(result); } void sample(const Vec3 &Ng, float randu, float randv, Vec3 &omega_out, float &pdf) const { - // We don't do anything sophisticated here for the step - // We just sample the whole cone uniformly to the cosine - Vec3 T, B; - make_orthonormals(Ng, T, B); - float phi = 2 * (float) M_PI * randu; - float cosTheta = sqrtf(1.0f - 1.0f * randv); - float sinTheta = sqrtf(1.0f - cosTheta * cosTheta); - omega_out = (cosf(phi) * sinTheta) * T + - (sinf(phi) * sinTheta) * B + - cosTheta * Ng; - pdf = 1.0f / float(M_PI); + float3 omega_out_; + emissive_sample(TO_FLOAT3(Ng), randu, randv, &omega_out_, &pdf); + omega_out = TO_VEC3(omega_out_); } - /// Return the probability distribution function in the direction omega_out, - /// given the parameters and the light's surface normal. This MUST match - /// the PDF computed by sample(). - float pdf(const Vec3 &Ng, - const Vec3 &omega_out) const + float pdf(const Vec3 &Ng, const Vec3 &omega_out) const { - float cosNO = Ng.dot(omega_out); - return cosNO > 0 ? 1.0f : 0.0f; + return emissive_pdf(TO_FLOAT3(Ng), TO_FLOAT3(omega_out)); } }; - - ClosureParam *closure_emission_params() { static ClosureParam params[] = { diff --git a/intern/cycles/kernel/osl/nodes/node_object_info.osl b/intern/cycles/kernel/osl/nodes/node_object_info.osl deleted file mode 100644 index 21e50d8a43e..00000000000 --- a/intern/cycles/kernel/osl/nodes/node_object_info.osl +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "stdosl.h" - -shader node_object_info( - output point Location = point(0.0, 0.0, 0.0), - output float ObjectIndex = 0.0, - output float MaterialIndex = 0.0, - output float Random = 0.0 - ) -{ - getattribute("std::object_location", Location); - getattribute("std::object_index", ObjectIndex); - getattribute("std::material_index", MaterialIndex); - getattribute("std::object_random", Random); -} - diff --git a/intern/cycles/kernel/osl/nodes/node_rgb_ramp.osl b/intern/cycles/kernel/osl/nodes/node_rgb_ramp.osl deleted file mode 100644 index 2bc10f31cb3..00000000000 --- a/intern/cycles/kernel/osl/nodes/node_rgb_ramp.osl +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "stdosl.h" -#include "oslutil.h" - -shader node_rgb_ramp( - color ramp_color[RAMP_TABLE_SIZE] = {0.0}, - float ramp_alpha[RAMP_TABLE_SIZE] = {0.0}, - - float Fac = 0.0, - output color Color = color(0.0, 0.0, 0.0), - output float Alpha = 1.0 - ) -{ - float f = clamp(Fac, 0.0, 1.0)*(RAMP_TABLE_SIZE-1); - - int i = (int)f; - float t = f - (float)i; - - Color = ramp_color[i]; - Alpha = ramp_alpha[i]; - - if (t > 0.0) { - Color = (1.0 - t)*Color + t*ramp_color[i+1]; - Alpha = (1.0 - t)*Alpha + t*ramp_alpha[i+1]; - } -} - diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp index 9e99d4d2480..d42d65608c8 100644 --- a/intern/cycles/kernel/osl/osl_closures.cpp +++ b/intern/cycles/kernel/osl/osl_closures.cpp @@ -37,10 +37,101 @@ #include "osl_shader.h" #include "util_debug.h" +#include "util_math.h" #include "util_param.h" +#include "kernel_types.h" +#include "kernel_montecarlo.h" + +#include "closure/bsdf.h" +#include "closure/bsdf_ashikhmin_velvet.h" +#include "closure/bsdf_diffuse.h" +#include "closure/bsdf_microfacet.h" +#include "closure/bsdf_oren_nayar.h" +#include "closure/bsdf_phong_ramp.h" +#include "closure/bsdf_reflection.h" +#include "closure/bsdf_refraction.h" +#include "closure/bsdf_transparent.h" +#include "closure/bsdf_ward.h" +#include "closure/bsdf_westin.h" + CCL_NAMESPACE_BEGIN +using namespace OSL; + +/* BSDF class definitions */ + +BSDF_CLOSURE_CLASS_BEGIN(Diffuse, diffuse, diffuse, LABEL_DIFFUSE) + CLOSURE_VECTOR_PARAM(DiffuseClosure, N), +BSDF_CLOSURE_CLASS_END(Diffuse, diffuse) + +BSDF_CLOSURE_CLASS_BEGIN(Translucent, translucent, translucent, LABEL_DIFFUSE) + CLOSURE_VECTOR_PARAM(TranslucentClosure, N), +BSDF_CLOSURE_CLASS_END(Translucent, translucent) + +BSDF_CLOSURE_CLASS_BEGIN(OrenNayar, oren_nayar, oren_nayar, LABEL_DIFFUSE) + CLOSURE_VECTOR_PARAM(OrenNayarClosure, N), + CLOSURE_FLOAT_PARAM(OrenNayarClosure, sc.data0), +BSDF_CLOSURE_CLASS_END(OrenNayar, oren_nayar) + +BSDF_CLOSURE_CLASS_BEGIN(Reflection, reflection, reflection, LABEL_SINGULAR) + CLOSURE_VECTOR_PARAM(ReflectionClosure, N), +BSDF_CLOSURE_CLASS_END(Reflection, reflection) + +BSDF_CLOSURE_CLASS_BEGIN(Refraction, refraction, refraction, LABEL_SINGULAR) + CLOSURE_VECTOR_PARAM(RefractionClosure, N), + CLOSURE_FLOAT_PARAM(RefractionClosure, sc.data0), +BSDF_CLOSURE_CLASS_END(Refraction, refraction) + +BSDF_CLOSURE_CLASS_BEGIN(WestinBackscatter, westin_backscatter, westin_backscatter, LABEL_GLOSSY) + CLOSURE_VECTOR_PARAM(WestinBackscatterClosure, N), + CLOSURE_FLOAT_PARAM(WestinBackscatterClosure, sc.data0), +BSDF_CLOSURE_CLASS_END(WestinBackscatter, westin_backscatter) + +BSDF_CLOSURE_CLASS_BEGIN(WestinSheen, westin_sheen, westin_sheen, LABEL_DIFFUSE) + CLOSURE_VECTOR_PARAM(WestinSheenClosure, N), + CLOSURE_FLOAT_PARAM(WestinSheenClosure, sc.data0), +BSDF_CLOSURE_CLASS_END(WestinSheen, westin_sheen) + +BSDF_CLOSURE_CLASS_BEGIN(Transparent, transparent, transparent, LABEL_SINGULAR) +BSDF_CLOSURE_CLASS_END(Transparent, transparent) + +BSDF_CLOSURE_CLASS_BEGIN(AshikhminVelvet, ashikhmin_velvet, ashikhmin_velvet, LABEL_DIFFUSE) + CLOSURE_VECTOR_PARAM(AshikhminVelvetClosure, N), + CLOSURE_FLOAT_PARAM(AshikhminVelvetClosure, sc.data0), +BSDF_CLOSURE_CLASS_END(AshikhminVelvet, ashikhmin_velvet) + +BSDF_CLOSURE_CLASS_BEGIN(Ward, ward, ward, LABEL_GLOSSY) + CLOSURE_VECTOR_PARAM(WardClosure, N), + CLOSURE_VECTOR_PARAM(WardClosure, T), + CLOSURE_FLOAT_PARAM(WardClosure, sc.data0), + CLOSURE_FLOAT_PARAM(WardClosure, sc.data1), +BSDF_CLOSURE_CLASS_END(Ward, ward) + +BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGX, microfacet_ggx, microfacet_ggx, LABEL_GLOSSY) + CLOSURE_VECTOR_PARAM(MicrofacetGGXClosure, N), + CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure, sc.data0), +BSDF_CLOSURE_CLASS_END(MicrofacetGGX, microfacet_ggx) + +BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmann, microfacet_beckmann, microfacet_beckmann, LABEL_GLOSSY) + CLOSURE_VECTOR_PARAM(MicrofacetBeckmannClosure, N), + CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure, sc.data0), +BSDF_CLOSURE_CLASS_END(MicrofacetBeckmann, microfacet_beckmann) + +BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXRefraction, microfacet_ggx_refraction, microfacet_ggx, LABEL_GLOSSY) + CLOSURE_VECTOR_PARAM(MicrofacetGGXRefractionClosure, N), + CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, sc.data0), + CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, sc.data1), +BSDF_CLOSURE_CLASS_END(MicrofacetGGXRefraction, microfacet_ggx_refraction) + +BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction, microfacet_beckmann, LABEL_GLOSSY) + CLOSURE_VECTOR_PARAM(MicrofacetBeckmannRefractionClosure, N), + CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, sc.data0), + CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, sc.data1), +BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction) + +/* Registration */ + static void generic_closure_setup(OSL::RendererServices *, int id, void *data) { assert(data); @@ -64,28 +155,46 @@ static void register_closure(OSL::ShadingSystem *ss, const char *name, int id, O void OSLShader::register_closures(OSL::ShadingSystem *ss) { - register_closure(ss, "diffuse", OSL_CLOSURE_BSDF_DIFFUSE_ID, bsdf_diffuse_params(), bsdf_diffuse_prepare); - register_closure(ss, "oren_nayar", OSL_CLOSURE_BSDF_OREN_NAYAR_ID, bsdf_oren_nayar_params(), bsdf_oren_nayar_prepare); - register_closure(ss, "translucent", OSL_CLOSURE_BSDF_TRANSLUCENT_ID, bsdf_translucent_params(), bsdf_translucent_prepare); - register_closure(ss, "reflection", OSL_CLOSURE_BSDF_REFLECTION_ID, bsdf_reflection_params(), bsdf_reflection_prepare); - register_closure(ss, "refraction", OSL_CLOSURE_BSDF_REFRACTION_ID, bsdf_refraction_params(), bsdf_refraction_prepare); - register_closure(ss, "transparent", OSL_CLOSURE_BSDF_TRANSPARENT_ID, bsdf_transparent_params(), bsdf_transparent_prepare); - register_closure(ss, "microfacet_ggx", OSL_CLOSURE_BSDF_MICROFACET_GGX_ID, bsdf_microfacet_ggx_params(), bsdf_microfacet_ggx_prepare); - register_closure(ss, "microfacet_ggx_refraction", OSL_CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID, bsdf_microfacet_ggx_refraction_params(), bsdf_microfacet_ggx_refraction_prepare); - register_closure(ss, "microfacet_beckmann", OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_ID, bsdf_microfacet_beckmann_params(), bsdf_microfacet_beckmann_prepare); - register_closure(ss, "microfacet_beckmann_refraction", OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID, bsdf_microfacet_beckmann_refraction_params(), bsdf_microfacet_beckmann_refraction_prepare); - register_closure(ss, "ward", OSL_CLOSURE_BSDF_WARD_ID, bsdf_ward_params(), bsdf_ward_prepare); - register_closure(ss, "phong", OSL_CLOSURE_BSDF_PHONG_ID, bsdf_phong_params(), bsdf_phong_prepare); - register_closure(ss, "phong_ramp", OSL_CLOSURE_BSDF_PHONG_RAMP_ID, bsdf_phong_ramp_params(), bsdf_phong_ramp_prepare); - register_closure(ss, "ashikhmin_velvet", OSL_CLOSURE_BSDF_ASHIKHMIN_VELVET_ID, bsdf_ashikhmin_velvet_params(), bsdf_ashikhmin_velvet_prepare); - register_closure(ss, "westin_backscatter", OSL_CLOSURE_BSDF_WESTIN_BACKSCATTER_ID, bsdf_westin_backscatter_params(), bsdf_westin_backscatter_prepare); - register_closure(ss, "westin_sheen", OSL_CLOSURE_BSDF_WESTIN_SHEEN_ID, bsdf_westin_sheen_params(), bsdf_westin_sheen_prepare); - register_closure(ss, "bssrdf_cubic", OSL_CLOSURE_BSSRDF_CUBIC_ID, closure_bssrdf_cubic_params(), closure_bssrdf_cubic_prepare); - register_closure(ss, "emission", OSL_CLOSURE_EMISSION_ID, closure_emission_params(), closure_emission_prepare); - register_closure(ss, "debug", OSL_CLOSURE_DEBUG_ID, closure_debug_params(), closure_debug_prepare); - register_closure(ss, "background", OSL_CLOSURE_BACKGROUND_ID, closure_background_params(), closure_background_prepare); - register_closure(ss, "holdout", OSL_CLOSURE_HOLDOUT_ID, closure_holdout_params(), closure_holdout_prepare); - register_closure(ss, "subsurface", OSL_CLOSURE_SUBSURFACE_ID, closure_subsurface_params(), closure_subsurface_prepare); + int id = 0; + + register_closure(ss, "diffuse", id++, + bsdf_diffuse_params(), bsdf_diffuse_prepare); + register_closure(ss, "oren_nayar", id++, + bsdf_oren_nayar_params(), bsdf_oren_nayar_prepare); + register_closure(ss, "translucent", id++, + bsdf_translucent_params(), bsdf_translucent_prepare); + register_closure(ss, "reflection", id++, + bsdf_reflection_params(), bsdf_reflection_prepare); + register_closure(ss, "refraction", id++, + bsdf_refraction_params(), bsdf_refraction_prepare); + register_closure(ss, "transparent", id++, + bsdf_transparent_params(), bsdf_transparent_prepare); + register_closure(ss, "microfacet_ggx", id++, + bsdf_microfacet_ggx_params(), bsdf_microfacet_ggx_prepare); + register_closure(ss, "microfacet_ggx_refraction", id++, + bsdf_microfacet_ggx_refraction_params(), bsdf_microfacet_ggx_refraction_prepare); + register_closure(ss, "microfacet_beckmann", id++, + bsdf_microfacet_beckmann_params(), bsdf_microfacet_beckmann_prepare); + register_closure(ss, "microfacet_beckmann_refraction", id++, + bsdf_microfacet_beckmann_refraction_params(), bsdf_microfacet_beckmann_refraction_prepare); + register_closure(ss, "ward", id++, + bsdf_ward_params(), bsdf_ward_prepare); + register_closure(ss, "ashikhmin_velvet", id++, + bsdf_ashikhmin_velvet_params(), bsdf_ashikhmin_velvet_prepare); + register_closure(ss, "westin_backscatter", id++, + bsdf_westin_backscatter_params(), bsdf_westin_backscatter_prepare); + register_closure(ss, "westin_sheen", id++, + bsdf_westin_sheen_params(), bsdf_westin_sheen_prepare); + register_closure(ss, "emission", id++, + closure_emission_params(), closure_emission_prepare); + register_closure(ss, "background", id++, + closure_background_params(), closure_background_prepare); + register_closure(ss, "holdout", id++, + closure_holdout_params(), closure_holdout_prepare); + register_closure(ss, "ambient_occlusion", id++, + closure_ambient_occlusion_params(), closure_ambient_occlusion_prepare); + register_closure(ss, "phong_ramp", id++, + closure_bsdf_phong_ramp_params(), closure_bsdf_phong_ramp_prepare); } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h index a69af45672d..71e9e5ae4fd 100644 --- a/intern/cycles/kernel/osl/osl_closures.h +++ b/intern/cycles/kernel/osl/osl_closures.h @@ -37,78 +37,27 @@ #include <OSL/oslexec.h> #include <OSL/genclosure.h> -CCL_NAMESPACE_BEGIN +#include "kernel_types.h" -enum { - OSL_CLOSURE_BSDF_DIFFUSE_ID, - OSL_CLOSURE_BSDF_OREN_NAYAR_ID, - OSL_CLOSURE_BSDF_TRANSLUCENT_ID, - OSL_CLOSURE_BSDF_REFLECTION_ID, - OSL_CLOSURE_BSDF_REFRACTION_ID, - OSL_CLOSURE_BSDF_TRANSPARENT_ID, - OSL_CLOSURE_BSDF_MICROFACET_GGX_ID, - OSL_CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID, - OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_ID, - OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID, - OSL_CLOSURE_BSDF_WARD_ID, - OSL_CLOSURE_BSDF_PHONG_ID, - OSL_CLOSURE_BSDF_PHONG_RAMP_ID, - OSL_CLOSURE_BSDF_ASHIKHMIN_VELVET_ID, - OSL_CLOSURE_BSDF_WESTIN_BACKSCATTER_ID, - OSL_CLOSURE_BSDF_WESTIN_SHEEN_ID, - OSL_CLOSURE_BSSRDF_CUBIC_ID, - OSL_CLOSURE_EMISSION_ID, - OSL_CLOSURE_DEBUG_ID, - OSL_CLOSURE_BACKGROUND_ID, - OSL_CLOSURE_HOLDOUT_ID, - OSL_CLOSURE_SUBSURFACE_ID -}; +#include "util_types.h" + +CCL_NAMESPACE_BEGIN -OSL::ClosureParam *bsdf_diffuse_params(); -OSL::ClosureParam *bsdf_oren_nayar_params(); -OSL::ClosureParam *bsdf_translucent_params(); -OSL::ClosureParam *bsdf_reflection_params(); -OSL::ClosureParam *bsdf_refraction_params(); -OSL::ClosureParam *bsdf_transparent_params(); -OSL::ClosureParam *bsdf_microfacet_ggx_params(); -OSL::ClosureParam *bsdf_microfacet_ggx_refraction_params(); -OSL::ClosureParam *bsdf_microfacet_beckmann_params(); -OSL::ClosureParam *bsdf_microfacet_beckmann_refraction_params(); -OSL::ClosureParam *bsdf_ward_params(); -OSL::ClosureParam *bsdf_phong_params(); -OSL::ClosureParam *bsdf_phong_ramp_params(); -OSL::ClosureParam *bsdf_ashikhmin_velvet_params(); -OSL::ClosureParam *bsdf_westin_backscatter_params(); -OSL::ClosureParam *bsdf_westin_sheen_params(); -OSL::ClosureParam *closure_bssrdf_cubic_params(); OSL::ClosureParam *closure_emission_params(); -OSL::ClosureParam *closure_debug_params(); OSL::ClosureParam *closure_background_params(); OSL::ClosureParam *closure_holdout_params(); -OSL::ClosureParam *closure_subsurface_params(); - -void bsdf_diffuse_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_oren_nayar_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_translucent_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_reflection_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_refraction_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_transparent_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_microfacet_ggx_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_microfacet_ggx_refraction_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_microfacet_beckmann_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_microfacet_beckmann_refraction_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_ward_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_phong_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_phong_ramp_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_ashikhmin_velvet_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_westin_backscatter_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_westin_sheen_prepare(OSL::RendererServices *, int id, void *data); -void closure_bssrdf_cubic_prepare(OSL::RendererServices *, int id, void *data); +OSL::ClosureParam *closure_ambient_occlusion_params(); +OSL::ClosureParam *closure_bsdf_phong_ramp_params(); + void closure_emission_prepare(OSL::RendererServices *, int id, void *data); -void closure_debug_prepare(OSL::RendererServices *, int id, void *data); void closure_background_prepare(OSL::RendererServices *, int id, void *data); void closure_holdout_prepare(OSL::RendererServices *, int id, void *data); -void closure_subsurface_prepare(OSL::RendererServices *, int id, void *data); +void closure_ambient_occlusion_prepare(OSL::RendererServices *, int id, void *data); +void closure_bsdf_phong_ramp_prepare(OSL::RendererServices *, int id, void *data); + +enum { + AmbientOcclusion = 100 +}; #define CLOSURE_PREPARE(name, classname) \ void name(RendererServices *, int id, void *data) \ @@ -117,6 +66,106 @@ void name(RendererServices *, int id, void *data) \ new (data) classname(); \ } +#define TO_VEC3(v) (*(OSL::Vec3 *)&(v)) +#define TO_COLOR3(v) (*(OSL::Color3 *)&(v)) +#define TO_FLOAT3(v) make_float3(v[0], v[1], v[2]) + +/* BSDF */ + +class CBSDFClosure : public OSL::ClosurePrimitive { +public: + ShaderClosure sc; + OSL::Vec3 N, T; + + CBSDFClosure(int scattering) : OSL::ClosurePrimitive(BSDF), + m_scattering_label(scattering), m_shaderdata_flag(0) { } + ~CBSDFClosure() { } + + int scattering() const { return m_scattering_label; } + int shaderdata_flag() const { return m_shaderdata_flag; } + ClosureType shaderclosure_type() const { return sc.type; } + + virtual void blur(float roughness) = 0; + virtual float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0; + virtual float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0; + + virtual int sample(const float3 &Ng, + const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy, + float randu, float randv, + float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy, + float &pdf, float3 &eval) const = 0; + +protected: + int m_scattering_label; + int m_shaderdata_flag; +}; + +#define BSDF_CLOSURE_CLASS_BEGIN(Upper, lower, svmlower, TYPE) \ +\ +class Upper##Closure : public CBSDFClosure { \ +public: \ + Upper##Closure() : CBSDFClosure(TYPE) {} \ + size_t memsize() const { return sizeof(*this); } \ + const char *name() const { return #lower; } \ +\ + void setup() \ + { \ + sc.N = TO_FLOAT3(N); \ + sc.T = TO_FLOAT3(T); \ + m_shaderdata_flag = bsdf_##lower##_setup(&sc); \ + } \ +\ + bool mergeable(const ClosurePrimitive *other) const \ + { \ + return false; \ + } \ + \ + void blur(float roughness) \ + { \ + bsdf_##svmlower##_blur(&sc, roughness); \ + } \ +\ + void print_on(std::ostream &out) const \ + { \ + out << name() << " ((" << sc.N[0] << ", " << sc.N[1] << ", " << sc.N[2] << "))"; \ + } \ +\ + float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const \ + { \ + return bsdf_##svmlower##_eval_reflect(&sc, omega_out, omega_in, &pdf); \ + } \ +\ + float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float& pdf) const \ + { \ + return bsdf_##svmlower##_eval_transmit(&sc, omega_out, omega_in, &pdf); \ + } \ +\ + int sample(const float3 &Ng, \ + const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy, \ + float randu, float randv, \ + float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy, \ + float &pdf, float3 &eval) const \ + { \ + return bsdf_##svmlower##_sample(&sc, Ng, omega_out, domega_out_dx, domega_out_dy, \ + randu, randv, &eval, &omega_in, &domega_in_dx, &domega_in_dy, &pdf); \ + } \ +}; \ +\ +ClosureParam *bsdf_##lower##_params() \ +{ \ + static ClosureParam params[] = { + +/* parameters */ + +#define BSDF_CLOSURE_CLASS_END(Upper, lower) \ + CLOSURE_STRING_KEYPARAM("label"), \ + CLOSURE_FINISH_PARAM(Upper##Closure) \ + }; \ + return params; \ +} \ +\ +CLOSURE_PREPARE(bsdf_##lower##_prepare, Upper##Closure) + CCL_NAMESPACE_END #endif /* __OSL_CLOSURES_H__ */ diff --git a/intern/cycles/kernel/osl/osl_globals.h b/intern/cycles/kernel/osl/osl_globals.h index 8cbbfc8dbb1..80ced9dfd62 100644 --- a/intern/cycles/kernel/osl/osl_globals.h +++ b/intern/cycles/kernel/osl/osl_globals.h @@ -59,6 +59,7 @@ struct OSLGlobals { vector<AttributeMap> attribute_map; ObjectNameMap object_name_map; + vector<ustring> object_names; /* thread key for thread specific data lookup */ struct ThreadData { @@ -67,6 +68,11 @@ struct OSLGlobals { }; static tls_ptr(ThreadData, thread_data); + static thread_mutex thread_data_mutex; + static volatile int thread_data_users; + + void thread_data_init(); + void thread_data_free(); }; CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index f1deaa9db9d..54cbf49704f 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -22,6 +22,7 @@ #include "object.h" #include "scene.h" +#include "osl_closures.h" #include "osl_services.h" #include "osl_shader.h" @@ -30,8 +31,14 @@ #include "kernel_compat_cpu.h" #include "kernel_globals.h" +#include "kernel_montecarlo.h" +#include "kernel_projection.h" +#include "kernel_differential.h" #include "kernel_object.h" +#include "kernel_bvh.h" #include "kernel_triangle.h" +#include "kernel_accumulate.h" +#include "kernel_shader.h" CCL_NAMESPACE_BEGIN @@ -72,7 +79,11 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr int object = sd->object; if (object != ~0) { - Transform tfm = object_fetch_transform(kg, object, time, OBJECT_TRANSFORM); +#ifdef __OBJECT_MOTION__ + Transform tfm = object_fetch_transform_motion_test(kg, object, time, NULL); +#else + Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); +#endif tfm = transform_transpose(tfm); result = TO_MATRIX44(tfm); @@ -93,9 +104,14 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, OSL::Transform int object = sd->object; if (object != ~0) { - Transform tfm = object_fetch_transform(kg, object, time, OBJECT_INVERSE_TRANSFORM); - tfm = transform_transpose(tfm); - result = TO_MATRIX44(tfm); +#ifdef __OBJECT_MOTION__ + Transform itfm; + object_fetch_transform_motion_test(kg, object, time, &itfm); +#else + Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); +#endif + itfm = transform_transpose(itfm); + result = TO_MATRIX44(itfm); return true; } @@ -109,7 +125,7 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, ustring from, float ti KernelGlobals *kg = kernel_globals; if (from == u_ndc) { - Transform tfm = transform_transpose(kernel_data.cam.ndctoworld); + Transform tfm = transform_transpose(transform_quick_inverse(kernel_data.cam.worldtondc)); result = TO_MATRIX44(tfm); return true; } @@ -162,14 +178,108 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, ustring to, fl bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform) { - // XXX implementation - return true; + /* this is only used for shader and object space, we don't really have + * a concept of shader space, so we just use object space for both. */ + if (xform) { + const ShaderData *sd = (const ShaderData *)xform; + int object = sd->object; + + if (object != ~0) { +#ifdef __OBJECT_MOTION__ + Transform tfm = sd->ob_tfm; +#else + KernelGlobals *kg = kernel_globals; + Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); +#endif + tfm = transform_transpose(tfm); + result = TO_MATRIX44(tfm); + + return true; + } + } + + return false; +} + +bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform) +{ + /* this is only used for shader and object space, we don't really have + * a concept of shader space, so we just use object space for both. */ + if (xform) { + const ShaderData *sd = (const ShaderData *)xform; + int object = sd->object; + + if (object != ~0) { +#ifdef __OBJECT_MOTION__ + Transform tfm = sd->ob_itfm; +#else + KernelGlobals *kg = kernel_globals; + Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); +#endif + tfm = transform_transpose(tfm); + result = TO_MATRIX44(tfm); + + return true; + } + } + + return false; } bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, ustring from) { - // XXX implementation - return true; + KernelGlobals *kg = kernel_globals; + + if (from == u_ndc) { + Transform tfm = transform_transpose(transform_quick_inverse(kernel_data.cam.worldtondc)); + result = TO_MATRIX44(tfm); + return true; + } + else if (from == u_raster) { + Transform tfm = transform_transpose(kernel_data.cam.rastertoworld); + result = TO_MATRIX44(tfm); + return true; + } + else if (from == u_screen) { + Transform tfm = transform_transpose(kernel_data.cam.screentoworld); + result = TO_MATRIX44(tfm); + return true; + } + else if (from == u_camera) { + Transform tfm = transform_transpose(kernel_data.cam.cameratoworld); + result = TO_MATRIX44(tfm); + return true; + } + + return false; +} + +bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, ustring to) +{ + KernelGlobals *kg = kernel_globals; + + if (to == u_ndc) { + Transform tfm = transform_transpose(kernel_data.cam.worldtondc); + result = TO_MATRIX44(tfm); + return true; + } + else if (to == u_raster) { + Transform tfm = transform_transpose(kernel_data.cam.worldtoraster); + result = TO_MATRIX44(tfm); + return true; + } + else if (to == u_screen) { + Transform tfm = transform_transpose(kernel_data.cam.worldtoscreen); + result = TO_MATRIX44(tfm); + return true; + } + else if (to == u_camera) { + Transform tfm = transform_transpose(kernel_data.cam.worldtocamera); + result = TO_MATRIX44(tfm); + return true; + } + + return false; } bool OSLRenderServices::get_array_attribute(void *renderstate, bool derivatives, @@ -179,72 +289,185 @@ bool OSLRenderServices::get_array_attribute(void *renderstate, bool derivatives, return false; } -static void set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, void *val) +static bool set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, void *val) { if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) { - float3 *fval = (float3 *)val; - fval[0] = f[0]; + float *fval = (float *)val; + + fval[0] = f[0].x; + fval[1] = f[0].y; + fval[2] = f[0].z; + if (derivatives) { - fval[1] = f[1]; - fval[2] = f[2]; + fval[3] = f[1].x; + fval[4] = f[1].y; + fval[5] = f[1].z; + + fval[6] = f[2].x; + fval[7] = f[2].y; + fval[8] = f[2].z; } + + return true; } - else { + else if(type == TypeDesc::TypeFloat) { float *fval = (float *)val; fval[0] = average(f[0]); + if (derivatives) { fval[1] = average(f[1]); fval[2] = average(f[2]); } + + return true; } + + return false; } -static void set_attribute_float(float f[3], TypeDesc type, bool derivatives, void *val) +static bool set_attribute_float3(float3 f, TypeDesc type, bool derivatives, void *val) +{ + float3 fv[3]; + + fv[0] = f; + fv[1] = make_float3(0.0f, 0.0f, 0.0f); + fv[2] = make_float3(0.0f, 0.0f, 0.0f); + + return set_attribute_float3(fv, type, derivatives, val); +} + +static bool set_attribute_float(float f[3], TypeDesc type, bool derivatives, void *val) { if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) { - float3 *fval = (float3 *)val; - fval[0] = make_float3(f[0], f[0], f[0]); + float *fval = (float *)val; + fval[0] = f[0]; + fval[1] = f[1]; + fval[2] = f[2]; + if (derivatives) { - fval[1] = make_float3(f[1], f[2], f[1]); - fval[2] = make_float3(f[2], f[2], f[2]); + fval[3] = f[1]; + fval[4] = f[1]; + fval[5] = f[1]; + + fval[6] = f[2]; + fval[7] = f[2]; + fval[8] = f[2]; } + + return true; } - else { + else if(type == TypeDesc::TypeFloat) { float *fval = (float *)val; fval[0] = f[0]; + if (derivatives) { fval[1] = f[1]; fval[2] = f[2]; } + + return true; } + + return false; } -static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, const OSLGlobals::Attribute& attr, - const TypeDesc& type, bool derivatives, void *val) +static bool set_attribute_float(float f, TypeDesc type, bool derivatives, void *val) { - if (attr.type == TypeDesc::TypeFloat) { - float fval[3]; - fval[0] = triangle_attribute_float(kg, sd, attr.elem, attr.offset, - (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); - set_attribute_float(fval, type, derivatives, val); + float fv[3]; + + fv[0] = f; + fv[1] = 0.0f; + fv[2] = 0.0f; + + return set_attribute_float(fv, type, derivatives, val); +} + +static bool set_attribute_int(int i, TypeDesc type, bool derivatives, void *val) +{ + if(type.basetype == TypeDesc::INT && type.aggregate == TypeDesc::SCALAR && type.arraylen == 0) { + int *ival = (int *)val; + ival[0] = i; + + if (derivatives) { + ival[1] = 0; + ival[2] = 0; + } + return true; } - else if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector || - attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) + + return false; +} + +static bool set_attribute_string(ustring str, TypeDesc type, bool derivatives, void *val) +{ + if(type.basetype == TypeDesc::INT && type.aggregate == TypeDesc::SCALAR && type.arraylen == 0) { + ustring *sval = (ustring *)val; + sval[0] = str; + + if (derivatives) { + sval[1] = OSLRenderServices::u_empty; + sval[2] = OSLRenderServices::u_empty; + } + + return true; + } + + return false; +} + +static bool set_attribute_float3_3(float3 P[3], TypeDesc type, bool derivatives, void *val) +{ + if(type.vecsemantics == TypeDesc::POINT && type.arraylen >= 3) { + float *fval = (float *)val; + + fval[0] = P[0].x; + fval[1] = P[0].y; + fval[2] = P[0].z; + + fval[3] = P[1].x; + fval[4] = P[1].y; + fval[5] = P[1].z; + + fval[6] = P[2].x; + fval[7] = P[2].y; + fval[8] = P[2].z; + + if(type.arraylen > 3) + memset(fval + 3*3, 0, sizeof(float)*3*(type.arraylen - 3)); + if (derivatives) + memset(fval + type.arraylen*3, 0, sizeof(float)*2*3*type.arraylen); + + return true; + } + + return false; +} + +static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, const OSLGlobals::Attribute& attr, + const TypeDesc& type, bool derivatives, void *val) +{ + if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector || + attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) { - /* todo: this won't work when float3 has w component */ float3 fval[3]; fval[0] = triangle_attribute_float3(kg, sd, attr.elem, attr.offset, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); - set_attribute_float3(fval, type, derivatives, val); - return true; + return set_attribute_float3(fval, type, derivatives, val); } - else + else if (attr.type == TypeDesc::TypeFloat) { + float fval[3]; + fval[0] = triangle_attribute_float(kg, sd, attr.elem, attr.offset, + (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); + return set_attribute_float(fval, type, derivatives, val); + } + else { return false; + } } static void get_object_attribute(const OSLGlobals::Attribute& attr, bool derivatives, void *val) @@ -259,102 +482,103 @@ static void get_object_attribute(const OSLGlobals::Attribute& attr, bool derivat static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ustring name, TypeDesc type, bool derivatives, void *val) { + /* todo: turn this into hash table returning int, which can be used in switch */ + /* Object Attributes */ - if (name == "std::object_location") { - float3 fval[3]; - fval[0] = object_location(kg, sd); - fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */ - set_attribute_float3(fval, type, derivatives, val); - return true; + if (name == "object:location") { + float3 f = object_location(kg, sd); + return set_attribute_float3(f, type, derivatives, val); } - else if (name == "std::object_index") { - float fval[3]; - fval[0] = object_pass_id(kg, sd->object); - fval[1] = fval[2] = 0.0; /* derivates set to 0 */ - set_attribute_float(fval, type, derivatives, val); - return true; + else if (name == "object:index") { + float f = object_pass_id(kg, sd->object); + return set_attribute_float(f, type, derivatives, val); } - else if (name == "std::material_index") { - float fval[3]; - fval[0] = shader_pass_id(kg, sd); - fval[1] = fval[2] = 0.0; /* derivates set to 0 */ - set_attribute_float(fval, type, derivatives, val); - return true; + else if (name == "geom:dupli_generated") { + float3 f = object_dupli_generated(kg, sd->object); + return set_attribute_float3(f, type, derivatives, val); } - else if (name == "std::object_random") { - float fval[3]; - fval[0] = object_random_number(kg, sd->object); - fval[1] = fval[2] = 0.0; /* derivates set to 0 */ - set_attribute_float(fval, type, derivatives, val); - return true; + else if (name == "geom:dupli_uv") { + float3 f = object_dupli_uv(kg, sd->object); + return set_attribute_float3(f, type, derivatives, val); + } + else if (name == "material:index") { + float f = shader_pass_id(kg, sd); + return set_attribute_float(f, type, derivatives, val); + } + else if (name == "object:random") { + float f = object_random_number(kg, sd->object); + return set_attribute_float(f, type, derivatives, val); } /* Particle Attributes */ - else if (name == "std::particle_index") { - float fval[3]; + else if (name == "particle:index") { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_index(kg, particle_id); - fval[1] = fval[2] = 0.0; /* derivates set to 0 */ - set_attribute_float(fval, type, derivatives, val); - return true; + float f = particle_index(kg, particle_id); + return set_attribute_float(f, type, derivatives, val); } - else if (name == "std::particle_age") { - float fval[3]; + else if (name == "particle:age") { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_age(kg, particle_id); - fval[1] = fval[2] = 0.0; /* derivates set to 0 */ - set_attribute_float(fval, type, derivatives, val); - return true; + float f = particle_age(kg, particle_id); + return set_attribute_float(f, type, derivatives, val); } - else if (name == "std::particle_lifetime") { - float fval[3]; + else if (name == "particle:lifetime") { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_lifetime(kg, particle_id); - fval[1] = fval[2] = 0.0; /* derivates set to 0 */ - set_attribute_float(fval, type, derivatives, val); - return true; + float f= particle_lifetime(kg, particle_id); + return set_attribute_float(f, type, derivatives, val); } - else if (name == "std::particle_location") { - float3 fval[3]; + else if (name == "particle:location") { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_location(kg, particle_id); - fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */ - set_attribute_float3(fval, type, derivatives, val); - return true; + float3 f = particle_location(kg, particle_id); + return set_attribute_float3(f, type, derivatives, val); } #if 0 /* unsupported */ - else if (name == "std::particle_rotation") { - float4 fval[3]; + else if (name == "particle:rotation") { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_rotation(kg, particle_id); - fval[1] = fval[2] = make_float4(0.0, 0.0, 0.0, 0.0); /* derivates set to 0 */ - set_attribute_float4(fval, type, derivatives, val); - return true; + float4 f = particle_rotation(kg, particle_id); + return set_attribute_float4(f, type, derivatives, val); } #endif - else if (name == "std::particle_size") { - float fval[3]; + else if (name == "particle:size") { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_size(kg, particle_id); - fval[1] = fval[2] = 0.0; /* derivates set to 0 */ - set_attribute_float(fval, type, derivatives, val); - return true; + float f = particle_size(kg, particle_id); + return set_attribute_float(f, type, derivatives, val); } - else if (name == "std::particle_velocity") { - float3 fval[3]; + else if (name == "particle:velocity") { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_velocity(kg, particle_id); - fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */ - set_attribute_float3(fval, type, derivatives, val); - return true; + float3 f = particle_velocity(kg, particle_id); + return set_attribute_float3(f, type, derivatives, val); } - else if (name == "std::particle_angular_velocity") { - float3 fval[3]; + else if (name == "particle:angular_velocity") { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_angular_velocity(kg, particle_id); - fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */ - set_attribute_float3(fval, type, derivatives, val); - return true; + float3 f = particle_angular_velocity(kg, particle_id); + return set_attribute_float3(f, type, derivatives, val); + } + else if (name == "geom:numpolyvertices") { + return set_attribute_int(3, type, derivatives, val); + } + else if (name == "geom:trianglevertices" || name == "geom:polyvertices") { + float3 P[3]; + triangle_vertices(kg, sd->prim, P); + object_position_transform(kg, sd, &P[0]); + object_position_transform(kg, sd, &P[1]); + object_position_transform(kg, sd, &P[2]); + return set_attribute_float3_3(P, type, derivatives, val); + } + else if(name == "geom:name") { + ustring object_name = kg->osl.object_names[sd->object]; + return set_attribute_string(object_name, type, derivatives, val); + } + else + return false; +} + +static bool get_background_attribute(KernelGlobals *kg, ShaderData *sd, ustring name, + TypeDesc type, bool derivatives, void *val) +{ + /* Ray Length */ + if (name == "path:ray_length") { + float f = sd->ray_length; + return set_attribute_float(f, type, derivatives, val); } else @@ -380,8 +604,7 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri tri = ~0; } else if (object == ~0) { - /* no background attributes supported */ - return false; + return get_background_attribute(kg, sd, name, type, derivatives, val); } /* find attribute on object */ @@ -390,7 +613,7 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri if (it != attribute_map.end()) { const OSLGlobals::Attribute& attr = it->second; - + if (attr.elem != ATTR_ELEMENT_VALUE) { /* triangle and vertex attributes */ if (tri != ~0) @@ -404,7 +627,12 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri } else { /* not found in attribute, check standard object info */ - return get_object_standard_attribute(kg, sd, name, type, derivatives, val); + bool is_std_object_attribute = get_object_standard_attribute(kg, sd, name, type, derivatives, val); + + if (is_std_object_attribute) + return true; + + return get_background_attribute(kg, sd, name, type, derivatives, val); } return false; @@ -434,4 +662,107 @@ int OSLRenderServices::pointcloud_get(ustring filename, size_t *indices, int cou return 0; } +bool OSLRenderServices::trace(TraceOpt &options, OSL::ShaderGlobals *sg, + const OSL::Vec3 &P, const OSL::Vec3 &dPdx, + const OSL::Vec3 &dPdy, const OSL::Vec3 &R, + const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy) +{ + /* todo: options.shader support, maybe options.traceset */ + ShaderData *sd = (ShaderData *)(sg->renderstate); + + /* setup ray */ + Ray ray; + + ray.P = TO_FLOAT3(P); + ray.D = TO_FLOAT3(R); + ray.t = (options.maxdist == 1.0e30)? FLT_MAX: options.maxdist - options.mindist; + ray.time = sd->time; + + if(options.mindist == 0.0f) { + /* avoid self-intersections */ + if(ray.P == sd->P) { + bool transmit = (dot(sd->Ng, ray.D) < 0.0f); + ray.P = ray_offset(sd->P, (transmit)? -sd->Ng: sd->Ng); + } + } + else { + /* offset for minimum distance */ + ray.P += options.mindist*ray.D; + } + + /* ray differentials */ + ray.dP.dx = TO_FLOAT3(dPdx); + ray.dP.dy = TO_FLOAT3(dPdy); + ray.dD.dx = TO_FLOAT3(dRdx); + ray.dD.dy = TO_FLOAT3(dRdy); + + /* allocate trace data */ + TraceData *tracedata = new TraceData(); + tracedata->ray = ray; + tracedata->setup = false; + + if(sg->tracedata) + delete (TraceData*)sg->tracedata; + sg->tracedata = tracedata; + + /* raytrace */ + return scene_intersect(kernel_globals, &ray, ~0, &tracedata->isect); +} + + +bool OSLRenderServices::getmessage(OSL::ShaderGlobals *sg, ustring source, ustring name, + TypeDesc type, void *val, bool derivatives) +{ + TraceData *tracedata = (TraceData*)sg->tracedata; + + if(source == "trace" && tracedata) { + if(name == "hit") { + return set_attribute_int((tracedata->isect.prim != ~0), type, derivatives, val); + } + else if(tracedata->isect.prim != ~0) { + if(name == "hitdist") { + float f[3] = {tracedata->isect.t, 0.0f, 0.0f}; + return set_attribute_float(f, type, derivatives, val); + } + else { + KernelGlobals *kg = kernel_globals; + ShaderData *sd = &tracedata->sd; + + if(!tracedata->setup) { + /* lazy shader data setup */ + shader_setup_from_ray(kg, sd, &tracedata->isect, &tracedata->ray); + tracedata->setup = true; + } + + if(name == "N") { + return set_attribute_float3(sd->N, type, derivatives, val); + } + else if(name == "Ng") { + return set_attribute_float3(sd->Ng, type, derivatives, val); + } + else if(name == "P") { + float3 f[3] = {sd->P, sd->dP.dx, sd->dP.dy}; + return set_attribute_float3(f, type, derivatives, val); + } + else if(name == "I") { + float3 f[3] = {sd->I, sd->dI.dx, sd->dI.dy}; + return set_attribute_float3(f, type, derivatives, val); + } + else if(name == "u") { + float f[3] = {sd->u, sd->du.dx, sd->du.dy}; + return set_attribute_float(f, type, derivatives, val); + } + else if(name == "v") { + float f[3] = {sd->v, sd->dv.dx, sd->dv.dy}; + return set_attribute_float(f, type, derivatives, val); + } + + return get_attribute(sd, derivatives, u_empty, type, name, val); + } + } + } + + return false; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h index 790b02a8abc..ce62eaf8994 100644 --- a/intern/cycles/kernel/osl/osl_services.h +++ b/intern/cycles/kernel/osl/osl_services.h @@ -54,7 +54,10 @@ public: bool get_inverse_matrix(OSL::Matrix44 &result, ustring to, float time); bool get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform); + bool get_inverse_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform); + bool get_matrix(OSL::Matrix44 &result, ustring from); + bool get_inverse_matrix(OSL::Matrix44 &result, ustring from); bool get_array_attribute(void *renderstate, bool derivatives, ustring object, TypeDesc type, ustring name, @@ -73,8 +76,20 @@ public: int pointcloud_get(ustring filename, size_t *indices, int count, ustring attr_name, TypeDesc attr_type, void *out_data); -private: - KernelGlobals *kernel_globals; + bool trace(TraceOpt &options, OSL::ShaderGlobals *sg, + const OSL::Vec3 &P, const OSL::Vec3 &dPdx, + const OSL::Vec3 &dPdy, const OSL::Vec3 &R, + const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy); + + bool getmessage(OSL::ShaderGlobals *sg, ustring source, ustring name, + TypeDesc type, void *val, bool derivatives); + + struct TraceData { + Ray ray; + Intersection isect; + ShaderData sd; + bool setup; + }; static ustring u_distance; static ustring u_index; @@ -83,6 +98,9 @@ private: static ustring u_raster; static ustring u_ndc; static ustring u_empty; + +private: + KernelGlobals *kernel_globals; }; CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index ea508dcb660..abf7c041cb3 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -21,6 +21,7 @@ #include "kernel_globals.h" #include "kernel_object.h" +#include "osl_closures.h" #include "osl_services.h" #include "osl_shader.h" @@ -31,9 +32,32 @@ CCL_NAMESPACE_BEGIN tls_ptr(OSLGlobals::ThreadData, OSLGlobals::thread_data); +volatile int OSLGlobals::thread_data_users = 0; +thread_mutex OSLGlobals::thread_data_mutex; /* Threads */ +void OSLGlobals::thread_data_init() +{ + thread_scoped_lock thread_data_lock(thread_data_mutex); + + if(thread_data_users == 0) + tls_create(OSLGlobals::ThreadData, thread_data); + + thread_data_users++; +} + +void OSLGlobals::thread_data_free() +{ + /* thread local storage delete */ + thread_scoped_lock thread_data_lock(thread_data_mutex); + + thread_data_users--; + + if(thread_data_users == 0) + tls_delete(OSLGlobals::ThreadData, thread_data); +} + void OSLShader::thread_init(KernelGlobals *kg) { OSL::ShadingSystem *ss = kg->osl.ss; @@ -61,10 +85,6 @@ void OSLShader::thread_free(KernelGlobals *kg) /* Globals */ -#define TO_VEC3(v) (*(OSL::Vec3 *)&(v)) -#define TO_COLOR3(v) (*(OSL::Color3 *)&(v)) -#define TO_FLOAT3(v) make_float3(v[0], v[1], v[2]) - static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd, int path_flag, OSL::ShaderGlobals *globals) { @@ -96,6 +116,7 @@ static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd, /* shader data to be used in services callbacks */ globals->renderstate = sd; + globals->tracedata = NULL; /* hacky, we leave it to services to fetch actual object matrix */ globals->shader2common = sd; @@ -127,39 +148,20 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, if (sd->num_closure == MAX_CLOSURE) return; - OSL::BSDFClosure *bsdf = (OSL::BSDFClosure *)prim; - ustring scattering = bsdf->scattering(); + CBSDFClosure *bsdf = (CBSDFClosure *)prim; + int scattering = bsdf->scattering(); /* no caustics option */ - if (no_glossy && scattering == OSL::Labels::GLOSSY) + if (no_glossy && scattering == LABEL_GLOSSY) return; /* sample weight */ - float albedo = bsdf->albedo(TO_VEC3(sd->I)); - float sample_weight = fabsf(average(weight)) * albedo; + float sample_weight = fabsf(average(weight)); - sc.sample_weight = sample_weight; + sd->flag |= bsdf->shaderdata_flag(); - /* scattering flags */ - if (scattering == OSL::Labels::DIFFUSE) { - sd->flag |= SD_BSDF | SD_BSDF_HAS_EVAL; - sc.type = CLOSURE_BSDF_DIFFUSE_ID; - } - else if (scattering == OSL::Labels::GLOSSY) { - sd->flag |= SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_GLOSSY; - sc.type = CLOSURE_BSDF_GLOSSY_ID; - } - else if (scattering == OSL::Labels::STRAIGHT) { - sd->flag |= SD_BSDF; - sc.type = CLOSURE_BSDF_TRANSPARENT_ID; - } - else { - /* todo: we don't actually have a way to determine if - * this closure will reflect/transmit. could add our own - * own scattering flag that do give this info */ - sd->flag |= SD_BSDF; - sc.type = CLOSURE_BSDF_GLOSSY_ID; - } + sc.sample_weight = sample_weight; + sc.type = bsdf->shaderclosure_type(); /* add */ sd->closure[sd->num_closure++] = sc; @@ -181,6 +183,20 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, sd->closure[sd->num_closure++] = sc; break; } + case AmbientOcclusion: { + if (sd->num_closure == MAX_CLOSURE) + return; + + /* sample weight */ + float sample_weight = fabsf(average(weight)); + + sc.sample_weight = sample_weight; + sc.type = CLOSURE_AMBIENT_OCCLUSION_ID; + + sd->closure[sd->num_closure++] = sc; + sd->flag |= SD_AO; + break; + } case OSL::ClosurePrimitive::Holdout: if (sd->num_closure == MAX_CLOSURE) return; @@ -227,6 +243,10 @@ void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int if (kg->osl.surface_state[shader]) ss->execute(*ctx, *(kg->osl.surface_state[shader]), *globals); + /* free trace data */ + if(globals->tracedata) + delete (OSLRenderServices::TraceData*)globals->tracedata; + /* flatten closure tree */ sd->num_closure = 0; sd->randb_closure = randb; @@ -282,6 +302,10 @@ float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_fl if (kg->osl.background_state) ss->execute(*ctx, *(kg->osl.background_state), *globals); + /* free trace data */ + if(globals->tracedata) + delete (OSLRenderServices::TraceData*)globals->tracedata; + /* return background color immediately */ if (globals->Ci) return flatten_background_closure_tree(globals->Ci); @@ -360,6 +384,10 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int if (kg->osl.volume_state[shader]) ss->execute(*ctx, *(kg->osl.volume_state[shader]), *globals); + /* free trace data */ + if(globals->tracedata) + delete (OSLRenderServices::TraceData*)globals->tracedata; + if (globals->Ci) flatten_volume_closure_tree(sd, globals->Ci); } @@ -383,6 +411,10 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd) if (kg->osl.displacement_state[shader]) ss->execute(*ctx, *(kg->osl.displacement_state[shader]), *globals); + /* free trace data */ + if(globals->tracedata) + delete (OSLRenderServices::TraceData*)globals->tracedata; + /* get back position */ sd->P = TO_FLOAT3(globals->P); } @@ -406,54 +438,34 @@ void OSLShader::release(KernelGlobals *kg, ShaderData *sd) int OSLShader::bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3& eval, float3& omega_in, differential3& domega_in, float& pdf) { - OSL::BSDFClosure *sample_bsdf = (OSL::BSDFClosure *)sc->prim; - int label = LABEL_NONE; + CBSDFClosure *sample_bsdf = (CBSDFClosure *)sc->prim; pdf = 0.0f; - /* sample BSDF closure */ - ustring ulabel; - - ulabel = sample_bsdf->sample(TO_VEC3(sd->Ng), - TO_VEC3(sd->I), TO_VEC3(sd->dI.dx), TO_VEC3(sd->dI.dy), - randu, randv, - TO_VEC3(omega_in), TO_VEC3(domega_in.dx), TO_VEC3(domega_in.dy), - pdf, TO_COLOR3(eval)); - - /* convert OSL label */ - if (ulabel == OSL::Labels::REFLECT) - label = LABEL_REFLECT; - else if (ulabel == OSL::Labels::TRANSMIT) - label = LABEL_TRANSMIT; - else - return LABEL_NONE; /* sampling failed */ - - /* convert scattering to our bitflag label */ - ustring uscattering = sample_bsdf->scattering(); - - if (uscattering == OSL::Labels::DIFFUSE) - label |= LABEL_DIFFUSE; - else if (uscattering == OSL::Labels::GLOSSY) - label |= LABEL_GLOSSY; - else if (uscattering == OSL::Labels::SINGULAR) - label |= LABEL_SINGULAR; - else - label |= LABEL_TRANSPARENT; - - return label; + return sample_bsdf->sample(sd->Ng, + sd->I, sd->dI.dx, sd->dI.dy, + randu, randv, + omega_in, domega_in.dx, domega_in.dy, + pdf, eval); } float3 OSLShader::bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const float3& omega_in, float& pdf) { - OSL::BSDFClosure *bsdf = (OSL::BSDFClosure *)sc->prim; - OSL::Color3 bsdf_eval; + CBSDFClosure *bsdf = (CBSDFClosure *)sc->prim; + float3 bsdf_eval; if (dot(sd->Ng, omega_in) >= 0.0f) - bsdf_eval = bsdf->eval_reflect(TO_VEC3(sd->I), TO_VEC3(omega_in), pdf); + bsdf_eval = bsdf->eval_reflect(sd->I, omega_in, pdf); else - bsdf_eval = bsdf->eval_transmit(TO_VEC3(sd->I), TO_VEC3(omega_in), pdf); + bsdf_eval = bsdf->eval_transmit(sd->I, omega_in, pdf); - return TO_FLOAT3(bsdf_eval); + return bsdf_eval; +} + +void OSLShader::bsdf_blur(ShaderClosure *sc, float roughness) +{ + CBSDFClosure *bsdf = (CBSDFClosure *)sc->prim; + bsdf->blur(roughness); } /* Emissive Closure */ @@ -468,7 +480,7 @@ float3 OSLShader::emissive_eval(const ShaderData *sd, const ShaderClosure *sc) /* Volume Closure */ -float3 OSLShader::volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) +float3 OSLShader::volume_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) { OSL::VolumeClosure *volume = (OSL::VolumeClosure *)sc->prim; OSL::Color3 volume_eval = volume->eval_phase(TO_VEC3(omega_in), TO_VEC3(omega_out)); diff --git a/intern/cycles/kernel/osl/osl_shader.h b/intern/cycles/kernel/osl/osl_shader.h index e2f4d1e94b8..9ff31e9160b 100644 --- a/intern/cycles/kernel/osl/osl_shader.h +++ b/intern/cycles/kernel/osl/osl_shader.h @@ -72,10 +72,11 @@ public: float3& eval, float3& omega_in, differential3& domega_in, float& pdf); static float3 bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const float3& omega_in, float& pdf); + static void bsdf_blur(ShaderClosure *sc, float roughness); static float3 emissive_eval(const ShaderData *sd, const ShaderClosure *sc); - static float3 volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc, + static float3 volume_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out); /* release */ diff --git a/intern/cycles/kernel/osl/vol_subsurface.cpp b/intern/cycles/kernel/osl/vol_subsurface.cpp deleted file mode 100644 index 5845428ed43..00000000000 --- a/intern/cycles/kernel/osl/vol_subsurface.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Adapted from Open Shading Language with this license: - * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sony Pictures Imageworks nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <OpenImageIO/fmath.h> - -#include <OSL/genclosure.h> - -#include "osl_closures.h" - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -// Computes scattering properties based on Jensen's reparameterization -// described in: -// http://graphics.ucsd.edu/~henrik/papers/fast_bssrdf/ - -class SubsurfaceClosure : public VolumeClosure { -public: - float m_g; - float m_eta; - Color3 m_mfp, m_albedo; - static float root_find_Rd(const float Rd0, const float A) { - // quick exit for trivial cases - if (Rd0 <= 0) return 0; - const float A43 = A * 4.0f / 3.0f; - // Find alpha such that f(alpha) = Rd (see eq.15). A simple bisection - // method can be used because this function is monotonicaly increasing. - float lo = 0, hi = 1; - for (int i = 0; i < 20; i++) { // 2^20 divisions should be sufficient - // eval function at midpoint - float alpha = 0.5f * (lo + hi); - float a1 = sqrtf(3 * (1 - alpha)); - float e1 = expf(-a1); - float e2 = expf(-A43 * a1); - float Rd = 0.5f * alpha * (1 + e2) * e1 - Rd0; - if (fabsf(Rd) < 1e-6f) - return alpha; // close enough - else if (Rd > 0) - hi = alpha; // root is on left side - else - lo = alpha; // root is on right side - } - // didn't quite converge, pick result in the middle of remaining interval - return 0.5f * (lo + hi); - } - SubsurfaceClosure() { - } - - void setup() - { - ior(m_eta); - - if (m_g >= 0.99f) m_g = 0.99f; - if (m_g <= -0.99f) m_g = -0.99f; - - // eq.10 - float inv_eta = 1 / m_eta; - float Fdr = -1.440f * inv_eta * inv_eta + 0.710 * inv_eta + 0.668f + 0.0636 * m_eta; - float A = (1 + Fdr) / (1 - Fdr); - // compute sigma_s, sigma_a (eq.16) - Color3 alpha_prime = Color3(root_find_Rd(m_albedo[0], A), - root_find_Rd(m_albedo[1], A), - root_find_Rd(m_albedo[2], A)); - Color3 sigma_t_prime = Color3(m_mfp.x > 0 ? 1.0f / (m_mfp[0] * sqrtf(3 * (1 - alpha_prime[0]))) : 0.0f, - m_mfp.y > 0 ? 1.0f / (m_mfp[1] * sqrtf(3 * (1 - alpha_prime[1]))) : 0.0f, - m_mfp.z > 0 ? 1.0f / (m_mfp[2] * sqrtf(3 * (1 - alpha_prime[2]))) : 0.0f); - Color3 sigma_s_prime = alpha_prime * sigma_t_prime; - - sigma_s((1.0f / (1 - m_g)) * sigma_s_prime); - sigma_a(sigma_t_prime - sigma_s_prime); - } - - bool mergeable(const ClosurePrimitive *other) const { - const SubsurfaceClosure *comp = (const SubsurfaceClosure *)other; - return m_g == comp->m_g && VolumeClosure::mergeable(other); - } - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { return "subsurface"; } - - void print_on(std::ostream &out) const { - out << name() << " ()"; - } - - virtual Color3 eval_phase(const Vec3 &omega_in, const Vec3 &omega_out) const { - float costheta = omega_in.dot(omega_out); - float ph = 0.25f * float(M_1_PI) * ((1 - m_g * m_g) / powf(1 + m_g * m_g - 2.0f * m_g * costheta, 1.5f)); - return Color3(ph, ph, ph); - } -}; - - - -ClosureParam *closure_subsurface_params() -{ - static ClosureParam params[] = { - CLOSURE_FLOAT_PARAM(SubsurfaceClosure, m_eta), - CLOSURE_FLOAT_PARAM(SubsurfaceClosure, m_g), - CLOSURE_COLOR_PARAM(SubsurfaceClosure, m_mfp), - CLOSURE_COLOR_PARAM(SubsurfaceClosure, m_albedo), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(SubsurfaceClosure) - }; - return params; -} - -CLOSURE_PREPARE(closure_subsurface_prepare, SubsurfaceClosure) - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/osl/nodes/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt index 541076f84c9..4f5a97c1bb6 100644 --- a/intern/cycles/kernel/osl/nodes/CMakeLists.txt +++ b/intern/cycles/kernel/shaders/CMakeLists.txt @@ -3,15 +3,18 @@ set(SRC_OSL node_add_closure.osl + node_ambient_occlusion.osl node_attribute.osl node_background.osl node_brick_texture.osl + node_brightness.osl node_bump.osl node_camera.osl node_checker_texture.osl node_combine_rgb.osl node_convert_from_color.osl node_convert_from_float.osl + node_convert_from_int.osl node_convert_from_normal.osl node_convert_from_point.osl node_convert_from_vector.osl @@ -20,15 +23,16 @@ set(SRC_OSL node_environment_texture.osl node_fresnel.osl node_gamma.osl - node_gradient_texture.osl - node_brightness.osl node_geometry.osl node_glass_bsdf.osl node_glossy_bsdf.osl + node_gradient_texture.osl node_holdout.osl node_hsv.osl node_image_texture.osl node_invert.osl + node_layer_weight.osl + node_light_falloff.osl node_light_path.osl node_magic_texture.osl node_mapping.osl @@ -36,16 +40,20 @@ set(SRC_OSL node_mix.osl node_mix_closure.osl node_musgrave_texture.osl - node_normal.osl node_noise_texture.osl + node_normal.osl + node_normal_map.osl node_object_info.osl node_output_displacement.osl node_output_surface.osl node_output_volume.osl node_particle_info.osl + node_refraction_bsdf.osl node_rgb_ramp.osl node_separate_rgb.osl + node_set_normal.osl node_sky_texture.osl + node_tangent.osl node_texture_coordinate.osl node_translucent_bsdf.osl node_transparent_bsdf.osl @@ -72,11 +80,11 @@ set(SRC_OSO # TODO, add a module to compile OSL foreach(_file ${SRC_OSL}) set(_OSL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${_file}) - string(REPLACE ".osl" ".oso" _OSO_FILE ${_OSL_FILE}) # TODO, replace extension only + string(REPLACE ".osl" ".oso" _OSO_FILE ${_OSL_FILE}) string(REPLACE ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} _OSO_FILE ${_OSO_FILE}) add_custom_command( OUTPUT ${_OSO_FILE} - COMMAND ${OSL_COMPILER} -O2 ${_OSL_FILE} + COMMAND ${OSL_COMPILER} -O2 -I"${CMAKE_CURRENT_SOURCE_DIR}" ${_OSL_FILE} DEPENDS ${_OSL_FILE} ${SRC_OSL_HEADERS}) list(APPEND SRC_OSO ${_OSO_FILE} @@ -86,7 +94,9 @@ foreach(_file ${SRC_OSL}) unset(_OSO_FILE) endforeach() -add_custom_target(shader ALL DEPENDS ${SRC_OSO} ${SRC_OSL_HEADERS}) +add_custom_target(cycles_osl_shaders ALL DEPENDS ${SRC_OSO} ${SRC_OSL_HEADERS}) # CMAKE_CURRENT_SOURCE_DIR is already included in OSO paths delayed_install("" "${SRC_OSO}" ${CYCLES_INSTALL_PATH}/shader) +delayed_install("${CMAKE_CURRENT_SOURCE_DIR}" "${SRC_OSL_HEADERS}" ${CYCLES_INSTALL_PATH}/shader) + diff --git a/intern/cycles/kernel/osl/nodes/node_add_closure.osl b/intern/cycles/kernel/shaders/node_add_closure.osl index ecf6bf5912e..ecf6bf5912e 100644 --- a/intern/cycles/kernel/osl/nodes/node_add_closure.osl +++ b/intern/cycles/kernel/shaders/node_add_closure.osl diff --git a/intern/cycles/kernel/shaders/node_ambient_occlusion.osl b/intern/cycles/kernel/shaders/node_ambient_occlusion.osl new file mode 100644 index 00000000000..57a06f35461 --- /dev/null +++ b/intern/cycles/kernel/shaders/node_ambient_occlusion.osl @@ -0,0 +1,27 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "stdosl.h" + +shader node_ambient_occlusion( + color Color = color(0.8, 0.8, 0.8), + output closure color AO = ambient_occlusion()) +{ + AO = Color * ambient_occlusion(); +} + diff --git a/intern/cycles/kernel/osl/nodes/node_attribute.osl b/intern/cycles/kernel/shaders/node_attribute.osl index d273d0c68d7..8e7c846d1a3 100644 --- a/intern/cycles/kernel/osl/nodes/node_attribute.osl +++ b/intern/cycles/kernel/shaders/node_attribute.osl @@ -29,12 +29,12 @@ shader node_attribute( Vector = point(Color); getattribute(name, Fac); - if(bump_offset == "dx") { + if (bump_offset == "dx") { Color += Dx(Color); Vector += Dx(Vector); Fac += Dx(Fac); } - else if(bump_offset == "dy") { + else if (bump_offset == "dy") { Color += Dy(Color); Vector += Dy(Vector); Fac += Dy(Fac); diff --git a/intern/cycles/kernel/osl/nodes/node_background.osl b/intern/cycles/kernel/shaders/node_background.osl index 69f8d85a82e..b51a1685294 100644 --- a/intern/cycles/kernel/osl/nodes/node_background.osl +++ b/intern/cycles/kernel/shaders/node_background.osl @@ -23,6 +23,6 @@ shader node_background( float Strength = 1.0, output closure color Background = background()) { - Background = Color*Strength*background(); + Background = Color * Strength * background(); } diff --git a/intern/cycles/kernel/osl/nodes/node_brick_texture.osl b/intern/cycles/kernel/shaders/node_brick_texture.osl index 4daceb4018e..478d9457001 100644 --- a/intern/cycles/kernel/osl/nodes/node_brick_texture.osl +++ b/intern/cycles/kernel/shaders/node_brick_texture.osl @@ -40,21 +40,21 @@ float brick(point p, float mortar_size, float bias, rownum = (int)floor(p[1] / row_height); - if(offset_frequency && squash_frequency) { - brick_width *= ((int)(rownum) % squash_frequency ) ? 1.0 : squash_amount; /* squash */ - offset = ((int)(rownum) % offset_frequency ) ? 0 : (brick_width*offset_amount); /* offset */ + if (offset_frequency && squash_frequency) { + brick_width *= ((int)(rownum) % squash_frequency) ? 1.0 : squash_amount; /* squash */ + offset = ((int)(rownum) % offset_frequency) ? 0 : (brick_width * offset_amount); /* offset */ } - bricknum = (int)floor((p[0]+offset) / brick_width); + bricknum = (int)floor((p[0] + offset) / brick_width); - x = (p[0]+offset) - brick_width*bricknum; - y = p[1] - row_height*rownum; + x = (p[0] + offset) - brick_width * bricknum; + y = p[1] - row_height * rownum; tint = clamp((brick_noise((rownum << 16) + (bricknum & 65535)) + bias), 0.0, 1.0); return (x < mortar_size || y < mortar_size || - x > (brick_width - mortar_size) || - y > (row_height - mortar_size)) ? 1.0 : 0.0; + x > (brick_width - mortar_size) || + y > (row_height - mortar_size)) ? 1.0 : 0.0; } shader node_brick_texture( @@ -77,10 +77,10 @@ shader node_brick_texture( float tint = 0.0; color Col = Color1; - Fac = brick(Vector*Scale, MortarSize, Bias, BrickWidth, RowHeight, + Fac = brick(Vector * Scale, MortarSize, Bias, BrickWidth, RowHeight, Offset, OffsetFrequency, Squash, SquashFrequency, tint); - if(Fac != 1.0) { + if (Fac != 1.0) { float facm = 1.0 - tint; Col[0] = facm * (Color1[0]) + tint * Color2[0]; @@ -89,6 +89,5 @@ shader node_brick_texture( } Color = (Fac == 1.0) ? Mortar: Col; - } diff --git a/intern/cycles/kernel/osl/nodes/node_brightness.osl b/intern/cycles/kernel/shaders/node_brightness.osl index 4f19a20f736..8e9f5c9c796 100644 --- a/intern/cycles/kernel/osl/nodes/node_brightness.osl +++ b/intern/cycles/kernel/shaders/node_brightness.osl @@ -24,7 +24,7 @@ shader node_brightness( float Contrast = 0.0, output color ColorOut = color(0.8, 0.8, 0.8)) { - float delta = Contrast * (1.0/200.0); + float delta = Contrast * (1.0 / 200.0); float a = 1.0 - delta * 2.0; float b; @@ -32,13 +32,13 @@ shader node_brightness( float bright_factor = Brightness / 100.0; /* - * The algorithm is by Werner D. Streidt - * (http://visca.com/ffactory/archives/5-99/msg00021.html) - * Extracted of OpenCV demhist.c - */ + * The algorithm is by Werner D. Streidt + * (http://visca.com/ffactory/archives/5-99/msg00021.html) + * Extracted of OpenCV demhist.c + */ if (Contrast > 0.0) { - a = (a < 0.0 ? 1.0/a : 0.0); + a = (a < 0.0 ? 1.0 / a : 0.0); b = a * (bright_factor - delta); } else { diff --git a/intern/cycles/kernel/osl/nodes/node_bump.osl b/intern/cycles/kernel/shaders/node_bump.osl index a3849e70f98..24db1b24458 100644 --- a/intern/cycles/kernel/osl/nodes/node_bump.osl +++ b/intern/cycles/kernel/shaders/node_bump.osl @@ -18,29 +18,32 @@ #include "stdosl.h" -/* "Bump Mapping Unparametrized Surfaces on the GPU" +/* "Bump Mapping Unparameterized Surfaces on the GPU" * Morten S. Mikkelsen, 2010 */ surface node_bump( + normal NormalIn = N, + float Strength = 0.0, float SampleCenter = 0.0, float SampleX = 0.0, float SampleY = 0.0, output normal Normal = N) { - float dx = SampleX - SampleCenter; - float dy = SampleY - SampleCenter; - + /* get surface tangents from normal */ vector dPdx = Dx(P); vector dPdy = Dy(P); - vector Rx = cross(dPdy, N); - vector Ry = cross(N, dPdx); + vector Rx = cross(dPdy, NormalIn); + vector Ry = cross(NormalIn, dPdx); + /* compute surface gradient and determinant */ float det = dot(dPdx, Rx); - vector surfgrad = dx*Rx + dy*Ry; + vector surfgrad = (SampleX - SampleCenter) * Rx + (SampleY - SampleCenter) * Ry; - surfgrad *= 0.1; /* todo: remove this factor */ + surfgrad *= Strength; + float absdet = fabs(det); - Normal = normalize(abs(det)*N - sign(det)*surfgrad); + /* compute and output perturbed normal */ + Normal = normalize(absdet * NormalIn - sign(det) * surfgrad); } diff --git a/intern/cycles/kernel/osl/nodes/node_camera.osl b/intern/cycles/kernel/shaders/node_camera.osl index 898ebd2bbb2..898ebd2bbb2 100644 --- a/intern/cycles/kernel/osl/nodes/node_camera.osl +++ b/intern/cycles/kernel/shaders/node_camera.osl diff --git a/intern/cycles/kernel/osl/nodes/node_checker_texture.osl b/intern/cycles/kernel/shaders/node_checker_texture.osl index e92d7be34fc..577caf308ff 100644 --- a/intern/cycles/kernel/osl/nodes/node_checker_texture.osl +++ b/intern/cycles/kernel/shaders/node_checker_texture.osl @@ -23,15 +23,15 @@ float checker(point p) { - p[0] = (p[0] + 0.00001)*0.9999; - p[1] = (p[1] + 0.00001)*0.9999; - p[2] = (p[2] + 0.00001)*0.9999; + p[0] = (p[0] + 0.00001) * 0.9999; + p[1] = (p[1] + 0.00001) * 0.9999; + p[2] = (p[2] + 0.00001) * 0.9999; int xi = (int)fabs(floor(p[0])); int yi = (int)fabs(floor(p[1])); int zi = (int)fabs(floor(p[2])); - if((xi % 2 == yi % 2) == (zi % 2)) { + if ((xi % 2 == yi % 2) == (zi % 2)) { return 1.0; } else { @@ -47,8 +47,8 @@ shader node_checker_texture( output float Fac = 0.0, output color Color = color(0.0, 0.0, 0.0)) { - Fac = checker(Vector*Scale); - if(Fac == 1.0) { + Fac = checker(Vector * Scale); + if (Fac == 1.0) { Color = Color1; } else { diff --git a/intern/cycles/kernel/osl/nodes/node_color.h b/intern/cycles/kernel/shaders/node_color.h index 80786e4e369..80786e4e369 100644 --- a/intern/cycles/kernel/osl/nodes/node_color.h +++ b/intern/cycles/kernel/shaders/node_color.h diff --git a/intern/cycles/kernel/osl/nodes/node_combine_rgb.osl b/intern/cycles/kernel/shaders/node_combine_rgb.osl index 546369f660e..546369f660e 100644 --- a/intern/cycles/kernel/osl/nodes/node_combine_rgb.osl +++ b/intern/cycles/kernel/shaders/node_combine_rgb.osl diff --git a/intern/cycles/kernel/osl/nodes/node_convert_from_color.osl b/intern/cycles/kernel/shaders/node_convert_from_color.osl index 97356139c48..2884c772414 100644 --- a/intern/cycles/kernel/osl/nodes/node_convert_from_color.osl +++ b/intern/cycles/kernel/shaders/node_convert_from_color.osl @@ -21,11 +21,13 @@ shader node_convert_from_color( color Color = color(0.0, 0.0, 0.0), output float Val = 0.0, + output int ValInt = 0, output vector Vector = vector(0.0, 0.0, 0.0), output point Point = point(0.0, 0.0, 0.0), output normal Normal = normal(0.0, 0.0, 0.0)) { - Val = Color[0]*0.2126 + Color[1]*0.7152 + Color[2]*0.0722; + Val = Color[0] * 0.2126 + Color[1] * 0.7152 + Color[2] * 0.0722; + ValInt = (int)(Color[0]*0.2126 + Color[1]*0.7152 + Color[2]*0.0722); Vector = vector(Color[0], Color[1], Color[2]); Point = point(Color[0], Color[1], Color[2]); Normal = normal(Color[0], Color[1], Color[2]); diff --git a/intern/cycles/kernel/osl/nodes/node_convert_from_float.osl b/intern/cycles/kernel/shaders/node_convert_from_float.osl index 00e78f3bab4..4466fbae3a6 100644 --- a/intern/cycles/kernel/osl/nodes/node_convert_from_float.osl +++ b/intern/cycles/kernel/shaders/node_convert_from_float.osl @@ -20,11 +20,13 @@ shader node_convert_from_float( float Val = 0.0, + output int ValInt = 0, output color Color = color(0.0, 0.0, 0.0), output vector Vector = vector(0.0, 0.0, 0.0), output point Point = point(0.0, 0.0, 0.0), output normal Normal = normal(0.0, 0.0, 0.0)) { + ValInt = (int)Val; Color = color(Val, Val, Val); Vector = vector(Val, Val, Val); Point = point(Val, Val, Val); diff --git a/intern/cycles/kernel/shaders/node_convert_from_int.osl b/intern/cycles/kernel/shaders/node_convert_from_int.osl new file mode 100644 index 00000000000..060d4184fa6 --- /dev/null +++ b/intern/cycles/kernel/shaders/node_convert_from_int.osl @@ -0,0 +1,36 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "stdosl.h" + +shader node_convert_from_int( + int ValInt = 0, + output float Val = 0.0, + output color Color = color(0.0, 0.0, 0.0), + output vector Vector = vector(0.0, 0.0, 0.0), + output point Point = point(0.0, 0.0, 0.0), + output normal Normal = normal(0.0, 0.0, 0.0)) +{ + float f = (float)ValInt; + Val = f; + Color = color(f, f, f); + Vector = vector(f, f, f); + Point = point(f, f, f); + Normal = normal(f, f, f); +} + diff --git a/intern/cycles/kernel/osl/nodes/node_convert_from_normal.osl b/intern/cycles/kernel/shaders/node_convert_from_normal.osl index 0bb9092591d..32ef430d93b 100644 --- a/intern/cycles/kernel/osl/nodes/node_convert_from_normal.osl +++ b/intern/cycles/kernel/shaders/node_convert_from_normal.osl @@ -21,11 +21,13 @@ shader node_convert_from_normal( normal Normal = normal(0.0, 0.0, 0.0), output float Val = 0.0, + output int ValInt = 0, output vector Vector = vector(0.0, 0.0, 0.0), output color Color = color(0.0, 0.0, 0.0), output point Point = point(0.0, 0.0, 0.0)) { - Val = (Normal[0] + Normal[1] + Normal[2])*(1.0/3.0); + Val = (Normal[0] + Normal[1] + Normal[2]) * (1.0 / 3.0); + ValInt = (int)((Normal[0] + Normal[1] + Normal[2]) * (1.0 / 3.0)); Vector = vector(Normal[0], Normal[1], Normal[2]); Color = color(Normal[0], Normal[1], Normal[2]); Point = point(Normal[0], Normal[1], Normal[2]); diff --git a/intern/cycles/kernel/osl/nodes/node_convert_from_point.osl b/intern/cycles/kernel/shaders/node_convert_from_point.osl index e66d6a864d6..a9435c8abf4 100644 --- a/intern/cycles/kernel/osl/nodes/node_convert_from_point.osl +++ b/intern/cycles/kernel/shaders/node_convert_from_point.osl @@ -21,11 +21,13 @@ shader node_convert_from_point( point Point = point(0.0, 0.0, 0.0), output float Val = 0.0, + output int ValInt = 0, output vector Vector = vector(0.0, 0.0, 0.0), output color Color = color(0.0, 0.0, 0.0), output normal Normal = normal(0.0, 0.0, 0.0)) { - Val = (Point[0] + Point[1] + Point[2])*(1.0/3.0); + Val = (Point[0] + Point[1] + Point[2]) * (1.0 / 3.0); + ValInt = (int)((Normal[0] + Normal[1] + Normal[2]) * (1.0 / 3.0)); Vector = vector(Point[0], Point[1], Point[2]); Color = color(Point[0], Point[1], Point[2]); Normal = normal(Point[0], Point[1], Point[2]); diff --git a/intern/cycles/kernel/osl/nodes/node_convert_from_vector.osl b/intern/cycles/kernel/shaders/node_convert_from_vector.osl index 37ba9582cad..4516f92c753 100644 --- a/intern/cycles/kernel/osl/nodes/node_convert_from_vector.osl +++ b/intern/cycles/kernel/shaders/node_convert_from_vector.osl @@ -21,11 +21,13 @@ shader node_convert_from_vector( vector Vector = vector(0.0, 0.0, 0.0), output float Val = 0.0, + output int ValInt = 0, output color Color = color(0.0, 0.0, 0.0), output point Point = point(0.0, 0.0, 0.0), output normal Normal = normal(0.0, 0.0, 0.0)) { - Val = (Vector[0] + Vector[1] + Vector[2])*(1.0/3.0); + Val = (Vector[0] + Vector[1] + Vector[2]) * (1.0 / 3.0); + ValInt = (int)((Normal[0] + Normal[1] + Normal[2]) * (1.0 / 3.0)); Color = color(Vector[0], Vector[1], Vector[2]); Point = point(Vector[0], Vector[1], Vector[2]); Normal = normal(Vector[0], Vector[1], Vector[2]); diff --git a/intern/cycles/kernel/osl/nodes/node_diffuse_bsdf.osl b/intern/cycles/kernel/shaders/node_diffuse_bsdf.osl index 6075b7c93f3..d6dc17316e8 100644 --- a/intern/cycles/kernel/osl/nodes/node_diffuse_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_diffuse_bsdf.osl @@ -24,7 +24,7 @@ shader node_diffuse_bsdf( normal Normal = N, output closure color BSDF = diffuse(Normal)) { - if(Roughness == 0.0) + if (Roughness == 0.0) BSDF = Color * diffuse(Normal); else BSDF = Color * oren_nayar(Normal, Roughness); diff --git a/intern/cycles/kernel/osl/nodes/node_emission.osl b/intern/cycles/kernel/shaders/node_emission.osl index 8bfd1af173a..7ad0f9f7760 100644 --- a/intern/cycles/kernel/osl/nodes/node_emission.osl +++ b/intern/cycles/kernel/shaders/node_emission.osl @@ -24,9 +24,9 @@ shader node_emission( float Strength = 1.0, output closure color Emission = emission()) { - if(TotalPower) - Emission = ((Strength/surfacearea())*Color)*emission(); + if (TotalPower) + Emission = ((Strength / surfacearea()) * Color) * emission(); else - Emission = (Strength*Color)*emission(); + Emission = (Strength * Color) * emission(); } diff --git a/intern/cycles/kernel/osl/nodes/node_environment_texture.osl b/intern/cycles/kernel/shaders/node_environment_texture.osl index 3ad806781eb..bad62e56ab4 100644 --- a/intern/cycles/kernel/osl/nodes/node_environment_texture.osl +++ b/intern/cycles/kernel/shaders/node_environment_texture.osl @@ -28,7 +28,7 @@ shader node_environment_texture( { Color = (color)environment(filename, Vector, "alpha", Alpha); - if(color_space == "sRGB") + if (color_space == "sRGB") Color = color_srgb_to_scene_linear(Color); } diff --git a/intern/cycles/kernel/osl/nodes/node_fresnel.h b/intern/cycles/kernel/shaders/node_fresnel.h index dfd0a23fe1e..dfd0a23fe1e 100644 --- a/intern/cycles/kernel/osl/nodes/node_fresnel.h +++ b/intern/cycles/kernel/shaders/node_fresnel.h diff --git a/intern/cycles/kernel/osl/nodes/node_fresnel.osl b/intern/cycles/kernel/shaders/node_fresnel.osl index 3af4448b43f..e8d8e945f98 100644 --- a/intern/cycles/kernel/osl/nodes/node_fresnel.osl +++ b/intern/cycles/kernel/shaders/node_fresnel.osl @@ -25,7 +25,7 @@ shader node_fresnel( output float Fac = 0.0) { float f = max(IOR, 1.0 + 1e-5); - float eta = backfacing()? 1.0/f: f; + float eta = backfacing() ? 1.0 / f: f; Fac = fresnel_dielectric(I, Normal, eta); } diff --git a/intern/cycles/kernel/osl/nodes/node_gamma.osl b/intern/cycles/kernel/shaders/node_gamma.osl index d55e908b0b7..d55e908b0b7 100644 --- a/intern/cycles/kernel/osl/nodes/node_gamma.osl +++ b/intern/cycles/kernel/shaders/node_gamma.osl diff --git a/intern/cycles/kernel/osl/nodes/node_geometry.osl b/intern/cycles/kernel/shaders/node_geometry.osl index 9efc2a75c64..3940b98eec1 100644 --- a/intern/cycles/kernel/osl/nodes/node_geometry.osl +++ b/intern/cycles/kernel/shaders/node_geometry.osl @@ -32,19 +32,32 @@ shader node_geometry( { Position = P; Normal = NormalIn; - Tangent = normalize(dPdu); TrueNormal = Ng; Incoming = I; Parametric = point(u, v, 0.0); Backfacing = backfacing(); - if(bump_offset == "dx") { + if (bump_offset == "dx") { Position += Dx(Position); Parametric += Dx(Parametric); } - else if(bump_offset == "dy") { + else if (bump_offset == "dy") { Position += Dy(Position); Parametric += Dy(Parametric); } + + /* first try to get tangent attribute */ + point generated; + + /* try to create spherical tangent from generated coordinates */ + if (getattribute("geom:generated", generated)) { + vector T = vector(-(generated[1] - 0.5), (generated[0] - 0.5), 0.0); + T = transform("object", "world", T); + Tangent = cross(Normal, normalize(cross(T, Normal))); + } + else { + /* otherwise use surface derivatives */ + Tangent = normalize(dPdu); + } } diff --git a/intern/cycles/kernel/osl/nodes/node_glass_bsdf.osl b/intern/cycles/kernel/shaders/node_glass_bsdf.osl index 52743669c99..30b9d301f32 100644 --- a/intern/cycles/kernel/osl/nodes/node_glass_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_glass_bsdf.osl @@ -28,14 +28,16 @@ shader node_glass_bsdf( output closure color BSDF = diffuse(Normal)) { float f = max(IOR, 1.0 + 1e-5); - float eta = backfacing()? 1.0/f: f; + float eta = backfacing() ? 1.0 / f: f; float Fr = fresnel_dielectric(I, Normal, eta); - if(distribution == "Sharp") - BSDF = Color*(Fr*reflection(Normal) + (1.0-Fr)*refraction(Normal, eta)); - else if(distribution == "Beckmann") - BSDF = Color*(Fr*microfacet_beckmann(Normal, Roughness, eta) + (1.0-Fr)*microfacet_beckmann_refraction(Normal, Roughness, eta)); - else if(distribution == "GGX") - BSDF = Color*(Fr*microfacet_ggx(Normal, Roughness, eta) + (1.0-Fr)*microfacet_ggx_refraction(Normal, Roughness, eta)); + if (distribution == "Sharp") + BSDF = Color * (Fr * reflection(Normal) + (1.0 - Fr) * refraction(Normal, eta)); + else if (distribution == "Beckmann") + BSDF = Color * (Fr * microfacet_beckmann(Normal, Roughness) + + (1.0 - Fr) * microfacet_beckmann_refraction(Normal, Roughness, eta)); + else if (distribution == "GGX") + BSDF = Color * (Fr * microfacet_ggx(Normal, Roughness) + + (1.0 - Fr) * microfacet_ggx_refraction(Normal, Roughness, eta)); } diff --git a/intern/cycles/kernel/osl/nodes/node_glossy_bsdf.osl b/intern/cycles/kernel/shaders/node_glossy_bsdf.osl index 3890630e8a2..03340c74af5 100644 --- a/intern/cycles/kernel/osl/nodes/node_glossy_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_glossy_bsdf.osl @@ -26,12 +26,12 @@ shader node_glossy_bsdf( normal Normal = N, output closure color BSDF = diffuse(Normal)) { - if(distribution == "Sharp") - BSDF = Color*reflection(Normal); - else if(distribution == "Beckmann") - BSDF = Color*microfacet_beckmann(Normal, Roughness, 1.0); - else if(distribution == "GGX") - BSDF = Color*microfacet_ggx(Normal, Roughness, 1.0); + if (distribution == "Sharp") + BSDF = Color * reflection(Normal); + else if (distribution == "Beckmann") + BSDF = Color * microfacet_beckmann(Normal, Roughness); + else if (distribution == "GGX") + BSDF = Color * microfacet_ggx(Normal, Roughness); } diff --git a/intern/cycles/kernel/osl/nodes/node_gradient_texture.osl b/intern/cycles/kernel/shaders/node_gradient_texture.osl index e0cbc2cc569..ae7cfa51f59 100644 --- a/intern/cycles/kernel/osl/nodes/node_gradient_texture.osl +++ b/intern/cycles/kernel/shaders/node_gradient_texture.osl @@ -31,31 +31,31 @@ float gradient(point p, string type) float result = 0.0; - if(type == "Linear") { + if (type == "Linear") { result = x; } - else if(type == "Quadratic") { + else if (type == "Quadratic") { float r = max(x, 0.0); - result = r*r; + result = r * r; } - else if(type == "Easing") { + else if (type == "Easing") { float r = min(max(x, 0.0), 1.0); - float t = r*r; + float t = r * r; - result = (3.0*t - 2.0*t*r); + result = (3.0 * t - 2.0 * t * r); } - else if(type == "Diagonal") { - result = (x + y)/2.0; + else if (type == "Diagonal") { + result = (x + y) / 2.0; } - else if(type == "Radial") { - result = atan2(y, x)/(2.0*M_PI) + 0.5; + else if (type == "Radial") { + result = atan2(y, x) / (2.0 * M_PI) + 0.5; } else { - float r = max(1.0 - sqrt(x*x + y*y + z*z), 0.0); + float r = max(1.0 - sqrt(x * x + y * y + z * z), 0.0); - if(type == "Quadratic Sphere") - result = r*r; - else if(type == "Spherical") + if (type == "Quadratic Sphere") + result = r * r; + else if (type == "Spherical") result = r; } diff --git a/intern/cycles/kernel/osl/nodes/node_holdout.osl b/intern/cycles/kernel/shaders/node_holdout.osl index aede50c7ca0..aede50c7ca0 100644 --- a/intern/cycles/kernel/osl/nodes/node_holdout.osl +++ b/intern/cycles/kernel/shaders/node_holdout.osl diff --git a/intern/cycles/kernel/osl/nodes/node_hsv.osl b/intern/cycles/kernel/shaders/node_hsv.osl index 8fd7a1612e8..8fd7a1612e8 100644 --- a/intern/cycles/kernel/osl/nodes/node_hsv.osl +++ b/intern/cycles/kernel/shaders/node_hsv.osl diff --git a/intern/cycles/kernel/shaders/node_image_texture.osl b/intern/cycles/kernel/shaders/node_image_texture.osl new file mode 100644 index 00000000000..6393605e6b5 --- /dev/null +++ b/intern/cycles/kernel/shaders/node_image_texture.osl @@ -0,0 +1,120 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "stdosl.h" +#include "node_color.h" + +color image_texture_lookup(string filename, string color_space, float u, float v, output float Alpha) +{ + color rgb = (color)texture(filename, u, 1.0 - v, "wrap", "periodic", "alpha", Alpha); + + if (color_space == "sRGB") + rgb = color_srgb_to_scene_linear(rgb); + + return rgb; +} + +shader node_image_texture( + point Vector = P, + string filename = "", + string color_space = "sRGB", + string projection = "Flat", + float projection_blend = 0.0, + output color Color = color(0.0, 0.0, 0.0), + output float Alpha = 1.0) +{ + if (projection == "Flat") { + Color = image_texture_lookup(filename, color_space, Vector[0], Vector[1], Alpha); + } + else if (projection == "Box") { + /* object space normal */ + vector Nob = transform("world", "object", N); + + /* project from direction vector to barycentric coordinates in triangles */ + Nob = vector(fabs(Nob[0]), fabs(Nob[1]), fabs(Nob[2])); + Nob /= (Nob[0] + Nob[1] + Nob[2]); + + /* basic idea is to think of this as a triangle, each corner representing + * one of the 3 faces of the cube. in the corners we have single textures, + * in between we blend between two textures, and in the middle we a blend + * between three textures. + * + * the Nxyz values are the barycentric coordinates in an equilateral + * triangle, which in case of blending, in the middle has a smaller + * equilateral triangle where 3 textures blend. this divides things into + * 7 zones, with an if () test for each zone */ + + vector weight = vector(0.0, 0.0, 0.0); + float blend = projection_blend; + float limit = 0.5*(1.0 + blend); + + /* first test for corners with single texture */ + if (Nob[0] > limit*(Nob[0] + Nob[1]) && Nob[0] > limit*(Nob[0] + Nob[2])) { + weight[0] = 1.0; + } + else if (Nob[1] > limit*(Nob[0] + Nob[1]) && Nob[1] > limit*(Nob[1] + Nob[2])) { + weight[1] = 1.0; + } + else if (Nob[2] > limit*(Nob[0] + Nob[2]) && Nob[2] > limit*(Nob[1] + Nob[2])) { + weight[2] = 1.0; + } + else if (blend > 0.0) { + /* in case of blending, test for mixes between two textures */ + if (Nob[2] < (1.0 - limit)*(Nob[1] + Nob[0])) { + weight[0] = Nob[0] / (Nob[0] + Nob[1]); + weight[0] = clamp((weight[0] - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0); + weight[1] = 1.0 - weight[0]; + } + else if (Nob[0] < (1.0 - limit)*(Nob[1] + Nob[2])) { + weight[1] = Nob[1] / (Nob[1] + Nob[2]); + weight[1] = clamp((weight[1] - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0); + weight[2] = 1.0 - weight[1]; + } + else if (Nob[1] < (1.0 - limit) * (Nob[0] + Nob[2])) { + weight[0] = Nob[0] / (Nob[0] + Nob[2]); + weight[0] = clamp((weight[0] - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0); + weight[2] = 1.0 - weight[0]; + } + else { + /* last case, we have a mix between three */ + weight[0] = ((2.0 - limit) * Nob[0] + (limit - 1.0)) / (2.0 * limit - 1.0); + weight[1] = ((2.0 - limit) * Nob[1] + (limit - 1.0)) / (2.0 * limit - 1.0); + weight[2] = ((2.0 - limit) * Nob[2] + (limit - 1.0)) / (2.0 * limit - 1.0); + } + } + + Color = color(0.0, 0.0, 0.0); + Alpha = 0.0; + + float tmp_alpha; + + if (weight[0] > 0.0) { + Color += weight[0]*image_texture_lookup(filename, color_space, Vector[1], Vector[2], tmp_alpha); + Alpha += weight[0]*tmp_alpha; + } + if (weight[1] > 0.0) { + Color += weight[1]*image_texture_lookup(filename, color_space, Vector[0], Vector[2], tmp_alpha); + Alpha += weight[1]*tmp_alpha; + } + if (weight[2] > 0.0) { + Color += weight[2]*image_texture_lookup(filename, color_space, Vector[1], Vector[0], tmp_alpha); + Alpha += weight[2]*tmp_alpha; + } + } +} + diff --git a/intern/cycles/kernel/osl/nodes/node_invert.osl b/intern/cycles/kernel/shaders/node_invert.osl index 27021942558..27021942558 100644 --- a/intern/cycles/kernel/osl/nodes/node_invert.osl +++ b/intern/cycles/kernel/shaders/node_invert.osl diff --git a/intern/cycles/kernel/osl/nodes/node_blend_weight.osl b/intern/cycles/kernel/shaders/node_layer_weight.osl index d834819ef3a..3ea57f71786 100644 --- a/intern/cycles/kernel/osl/nodes/node_blend_weight.osl +++ b/intern/cycles/kernel/shaders/node_layer_weight.osl @@ -19,24 +19,28 @@ #include "stdosl.h" #include "node_fresnel.h" -shader node_blend_weight( - float Blend = 0.3, +shader node_layer_weight( + float Blend = 0.5, normal Normal = N, output float Fresnel = 0.0, output float Facing = 0.0) { - float f = max(1.0 - Blend, 1e-5); - Fresnel = fresnel_dielectric(I, Normal, backfacing()? f: 1.0/f); + float blend = Blend; + /* Fresnel */ + float eta = max(1.0 - Blend, 1e-5); + eta = backfacing() ? eta : 1.0 / eta; + Fresnel = fresnel_dielectric(I, Normal, eta); + + /* Facing */ Facing = abs(dot(I, Normal)); - if(Blend != 0.5) { - Blend = clamp(Blend, 0.0, 1.0); - Blend = (Blend < 0.5)? 2.0*Blend: 0.5/(1.0 - Blend); + if (blend != 0.5) { + blend = clamp(blend, 0.0, 1.0 - 1e-5); + blend = (blend < 0.5) ? 2.0 * blend : 0.5 / (1.0 - blend); - Facing = powf(Facing, Blend); + Facing = pow(Facing, blend); } Facing = 1.0 - Facing; } - diff --git a/intern/cycles/kernel/shaders/node_light_falloff.osl b/intern/cycles/kernel/shaders/node_light_falloff.osl new file mode 100644 index 00000000000..7ffa6fe0ffb --- /dev/null +++ b/intern/cycles/kernel/shaders/node_light_falloff.osl @@ -0,0 +1,46 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "stdosl.h" + +shader node_light_falloff( + float Strength = 0.0, + float Smooth = 0.0, + output float Quadratic = 0.0, + output float Linear = 0.0, + output float Constant = 0.0) +{ + float ray_length = 0.0; + float strength = Strength; + getattribute("path:ray_length", ray_length); + + if (Smooth > 0.0) { + float squared = ray_length*ray_length; + strength *= squared / (Smooth + squared); + } + + /* Quadratic */ + Quadratic = strength; + + /* Linear */ + Linear = (strength*ray_length); + + /* Constant */ + Constant = (strength*ray_length*ray_length); +} + diff --git a/intern/cycles/kernel/osl/nodes/node_light_path.osl b/intern/cycles/kernel/shaders/node_light_path.osl index 0ead20bf2bb..9e3f6c7b4a9 100644 --- a/intern/cycles/kernel/osl/nodes/node_light_path.osl +++ b/intern/cycles/kernel/shaders/node_light_path.osl @@ -25,7 +25,8 @@ shader node_light_path( output float IsGlossyRay = 0.0, output float IsSingularRay = 0.0, output float IsReflectionRay = 0.0, - output float IsTransmissionRay = 0.0) + output float IsTransmissionRay = 0.0, + output float RayLength = 0.0) { IsCameraRay = raytype("camera"); IsShadowRay = raytype("shadow"); @@ -34,5 +35,7 @@ shader node_light_path( IsSingularRay = raytype("singular"); IsReflectionRay = raytype("reflection"); IsTransmissionRay = raytype("refraction"); + + getattribute("path:ray_length", RayLength); } diff --git a/intern/cycles/kernel/osl/nodes/node_magic_texture.osl b/intern/cycles/kernel/shaders/node_magic_texture.osl index c013ebfe658..e464b83bc9e 100644 --- a/intern/cycles/kernel/osl/nodes/node_magic_texture.osl +++ b/intern/cycles/kernel/shaders/node_magic_texture.osl @@ -25,51 +25,51 @@ color magic(point p, int n, float distortion) { float dist = distortion; - float x = sin((p[0] + p[1] + p[2])*5.0); - float y = cos((-p[0] + p[1] - p[2])*5.0); - float z = -cos((-p[0] - p[1] + p[2])*5.0); + float x = sin(( p[0] + p[1] + p[2]) * 5.0); + float y = cos((-p[0] + p[1] - p[2]) * 5.0); + float z = -cos((-p[0] - p[1] + p[2]) * 5.0); - if(n > 0) { + if (n > 0) { x *= dist; y *= dist; z *= dist; - y = -cos(x-y+z); + y = -cos(x - y + z); y *= dist; - if(n > 1) { - x = cos(x-y-z); + if (n > 1) { + x = cos(x - y - z); x *= dist; - if(n > 2) { - z = sin(-x-y-z); + if (n > 2) { + z = sin(-x - y - z); z *= dist; - if(n > 3) { - x = -cos(-x+y-z); + if (n > 3) { + x = -cos(-x + y - z); x *= dist; - if(n > 4) { - y = -sin(-x+y+z); + if (n > 4) { + y = -sin(-x + y + z); y *= dist; - if(n > 5) { - y = -cos(-x+y+z); + if (n > 5) { + y = -cos(-x + y + z); y *= dist; - if(n > 6) { - x = cos(x+y+z); + if (n > 6) { + x = cos(x + y + z); x *= dist; - if(n > 7) { - z = sin(x+y-z); + if (n > 7) { + z = sin(x + y - z); z *= dist; - if(n > 8) { - x = -cos(-x-y+z); + if (n > 8) { + x = -cos(-x - y + z); x *= dist; - if(n > 9) { - y = -sin(x-y+z); + if (n > 9) { + y = -sin(x - y + z); y *= dist; } } @@ -82,7 +82,7 @@ color magic(point p, int n, float distortion) } } - if(dist != 0.0) { + if (dist != 0.0) { dist *= 2.0; x /= dist; y /= dist; @@ -99,6 +99,6 @@ shader node_magic_texture( point Vector = P, output color Color = color(0.0, 0.0, 0.0)) { - Color = magic(Vector*Scale, Depth, Distortion); + Color = magic(Vector * Scale, Depth, Distortion); } diff --git a/intern/cycles/kernel/osl/nodes/node_mapping.osl b/intern/cycles/kernel/shaders/node_mapping.osl index f342837d3c9..2e720edfc7e 100644 --- a/intern/cycles/kernel/osl/nodes/node_mapping.osl +++ b/intern/cycles/kernel/shaders/node_mapping.osl @@ -20,9 +20,9 @@ shader node_mapping( matrix Matrix = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - point Vector = point(0.0, 0.0, 0.0), - output point Vector_ = point(0.0, 0.0, 0.0)) + point VectorIn = point(0.0, 0.0, 0.0), + output point VectorOut = point(0.0, 0.0, 0.0)) { - Vector_ = transform(Matrix, Vector); + VectorOut = transform(Matrix, VectorIn); } diff --git a/intern/cycles/kernel/osl/nodes/node_math.osl b/intern/cycles/kernel/shaders/node_math.osl index 3327795286a..24dce898fd2 100644 --- a/intern/cycles/kernel/osl/nodes/node_math.osl +++ b/intern/cycles/kernel/shaders/node_math.osl @@ -22,20 +22,20 @@ float safe_divide(float a, float b) { float result; - if(b == 0.0) + if (b == 0.0) result = 0.0; else - result = a/b; + result = a / b; return result; } float safe_log(float a, float b) { - if(a < 0.0 || b < 0.0) + if (a < 0.0 || b < 0.0) return 0.0; - return log(a)/log(b); + return log(a) / log(b); } shader node_math( @@ -47,42 +47,42 @@ shader node_math( { /* OSL asin, acos, pow check for values that could give rise to nan */ - if(type == "Add") + if (type == "Add") Value = Value1 + Value2; - if(type == "Subtract") + if (type == "Subtract") Value = Value1 - Value2; - if(type == "Multiply") - Value = Value1*Value2; - if(type == "Divide") + if (type == "Multiply") + Value = Value1 * Value2; + if (type == "Divide") Value = safe_divide(Value1, Value2); - if(type == "Sine") + if (type == "Sine") Value = sin(Value1); - if(type == "Cosine") + if (type == "Cosine") Value = cos(Value1); - if(type == "Tangent") + if (type == "Tangent") Value = tan(Value1); - if(type == "Arcsine") + if (type == "Arcsine") Value = asin(Value1); - if(type == "Arccosine") + if (type == "Arccosine") Value = acos(Value1); - if(type == "Arctangent") + if (type == "Arctangent") Value = atan(Value1); - if(type == "Power") + if (type == "Power") Value = pow(Value1, Value2); - if(type == "Logarithm") + if (type == "Logarithm") Value = safe_log(Value1, Value2); - if(type == "Minimum") + if (type == "Minimum") Value = min(Value1, Value2); - if(type == "Maximum") + if (type == "Maximum") Value = max(Value1, Value2); - if(type == "Round") + if (type == "Round") Value = floor(Value1 + 0.5); - if(type == "Less Than") + if (type == "Less Than") Value = Value1 < Value2; - if(type == "Greater Than") + if (type == "Greater Than") Value = Value1 > Value2; - if(Clamp) + if (Clamp) Value = clamp(Value1, 0.0, 1.0); } diff --git a/intern/cycles/kernel/osl/nodes/node_mix.osl b/intern/cycles/kernel/shaders/node_mix.osl index 2ce342c49cd..69e68e5ed15 100644 --- a/intern/cycles/kernel/osl/nodes/node_mix.osl +++ b/intern/cycles/kernel/shaders/node_mix.osl @@ -38,7 +38,7 @@ color node_mix_screen(float t, color col1, color col2) { float tm = 1.0 - t; - return color(1.0) - (color(tm) + t*(color(1.0) - col2))*(color(1.0) - col1); + return color(1.0) - (color(tm) + t * (color(1.0) - col2)) * (color(1.0) - col1); } color node_mix_overlay(float t, color col1, color col2) @@ -47,20 +47,20 @@ color node_mix_overlay(float t, color col1, color col2) color outcol = col1; - if(outcol[0] < 0.5) - outcol[0] *= tm + 2.0*t*col2[0]; + if (outcol[0] < 0.5) + outcol[0] *= tm + 2.0 * t * col2[0]; else - outcol[0] = 1.0 - (tm + 2.0*t*(1.0 - col2[0]))*(1.0 - outcol[0]); + outcol[0] = 1.0 - (tm + 2.0 * t * (1.0 - col2[0])) * (1.0 - outcol[0]); - if(outcol[1] < 0.5) - outcol[1] *= tm + 2.0*t*col2[1]; + if (outcol[1] < 0.5) + outcol[1] *= tm + 2.0 * t * col2[1]; else - outcol[1] = 1.0 - (tm + 2.0*t*(1.0 - col2[1]))*(1.0 - outcol[1]); + outcol[1] = 1.0 - (tm + 2.0 * t * (1.0 - col2[1])) * (1.0 - outcol[1]); - if(outcol[2] < 0.5) - outcol[2] *= tm + 2.0*t*col2[2]; + if (outcol[2] < 0.5) + outcol[2] *= tm + 2.0 * t * col2[2]; else - outcol[2] = 1.0 - (tm + 2.0*t*(1.0 - col2[2]))*(1.0 - outcol[2]); + outcol[2] = 1.0 - (tm + 2.0 * t * (1.0 - col2[2])) * (1.0 - outcol[2]); return outcol; } @@ -76,9 +76,9 @@ color node_mix_div(float t, color col1, color col2) color outcol = col1; - if(col2[0] != 0.0) outcol[0] = tm*outcol[0] + t*outcol[0]/col2[0]; - if(col2[1] != 0.0) outcol[1] = tm*outcol[1] + t*outcol[1]/col2[1]; - if(col2[2] != 0.0) outcol[2] = tm*outcol[2] + t*outcol[2]/col2[2]; + if (col2[0] != 0.0) outcol[0] = tm * outcol[0] + t * outcol[0] / col2[0]; + if (col2[1] != 0.0) outcol[1] = tm * outcol[1] + t * outcol[1] / col2[1]; + if (col2[2] != 0.0) outcol[2] = tm * outcol[2] + t * outcol[2] / col2[2]; return outcol; } @@ -90,41 +90,41 @@ color node_mix_diff(float t, color col1, color col2) color node_mix_dark(float t, color col1, color col2) { - return min(col1, col2*t); + return min(col1, col2 * t); } color node_mix_light(float t, color col1, color col2) { - return max(col1, col2*t); + return max(col1, col2 * t); } color node_mix_dodge(float t, color col1, color col2) { color outcol = col1; - if(outcol[0] != 0.0) { - float tmp = 1.0 - t*col2[0]; - if(tmp <= 0.0) + if (outcol[0] != 0.0) { + float tmp = 1.0 - t * col2[0]; + if (tmp <= 0.0) outcol[0] = 1.0; - else if((tmp = outcol[0]/tmp) > 1.0) + else if ((tmp = outcol[0] / tmp) > 1.0) outcol[0] = 1.0; else outcol[0] = tmp; } - if(outcol[1] != 0.0) { - float tmp = 1.0 - t*col2[1]; - if(tmp <= 0.0) + if (outcol[1] != 0.0) { + float tmp = 1.0 - t * col2[1]; + if (tmp <= 0.0) outcol[1] = 1.0; - else if((tmp = outcol[1]/tmp) > 1.0) + else if ((tmp = outcol[1] / tmp) > 1.0) outcol[1] = 1.0; else outcol[1] = tmp; } - if(outcol[2] != 0.0) { - float tmp = 1.0 - t*col2[2]; - if(tmp <= 0.0) + if (outcol[2] != 0.0) { + float tmp = 1.0 - t * col2[2]; + if (tmp <= 0.0) outcol[2] = 1.0; - else if((tmp = outcol[2]/tmp) > 1.0) + else if ((tmp = outcol[2] / tmp) > 1.0) outcol[2] = 1.0; else outcol[2] = tmp; @@ -139,32 +139,32 @@ color node_mix_burn(float t, color col1, color col2) color outcol = col1; - tmp = tm + t*col2[0]; - if(tmp <= 0.0) + tmp = tm + t * col2[0]; + if (tmp <= 0.0) outcol[0] = 0.0; - else if((tmp = (1.0 - (1.0 - outcol[0])/tmp)) < 0.0) + else if ((tmp = (1.0 - (1.0 - outcol[0]) / tmp)) < 0.0) outcol[0] = 0.0; - else if(tmp > 1.0) + else if (tmp > 1.0) outcol[0] = 1.0; else outcol[0] = tmp; - tmp = tm + t*col2[1]; - if(tmp <= 0.0) + tmp = tm + t * col2[1]; + if (tmp <= 0.0) outcol[1] = 0.0; - else if((tmp = (1.0 - (1.0 - outcol[1])/tmp)) < 0.0) + else if ((tmp = (1.0 - (1.0 - outcol[1]) / tmp)) < 0.0) outcol[1] = 0.0; - else if(tmp > 1.0) + else if (tmp > 1.0) outcol[1] = 1.0; else outcol[1] = tmp; - tmp = tm + t*col2[2]; - if(tmp <= 0.0) + tmp = tm + t * col2[2]; + if (tmp <= 0.0) outcol[2] = 0.0; - else if((tmp = (1.0 - (1.0 - outcol[2])/tmp)) < 0.0) + else if ((tmp = (1.0 - (1.0 - outcol[2]) / tmp)) < 0.0) outcol[2] = 0.0; - else if(tmp > 1.0) + else if (tmp > 1.0) outcol[2] = 1.0; else outcol[2] = tmp; @@ -177,7 +177,7 @@ color node_mix_hue(float t, color col1, color col2) color outcol = col1; color hsv2 = rgb_to_hsv(col2); - if(hsv2[1] != 0.0) { + if (hsv2[1] != 0.0) { color hsv = rgb_to_hsv(outcol); hsv[0] = hsv2[0]; color tmp = hsv_to_rgb(hsv); @@ -196,10 +196,10 @@ color node_mix_sat(float t, color col1, color col2) color hsv = rgb_to_hsv(outcol); - if(hsv[1] != 0.0) { + if (hsv[1] != 0.0) { color hsv2 = rgb_to_hsv(col2); - hsv[1] = tm*hsv[1] + t*hsv2[1]; + hsv[1] = tm * hsv[1] + t * hsv2[1]; outcol = hsv_to_rgb(hsv); } @@ -213,7 +213,7 @@ color node_mix_val(float t, color col1, color col2) color hsv = rgb_to_hsv(col1); color hsv2 = rgb_to_hsv(col2); - hsv[2] = tm*hsv[2] + t*hsv2[2]; + hsv[2] = tm * hsv[2] + t * hsv2[2]; return hsv_to_rgb(hsv); } @@ -223,7 +223,7 @@ color node_mix_color(float t, color col1, color col2) color outcol = col1; color hsv2 = rgb_to_hsv(col2); - if(hsv2[1] != 0.0) { + if (hsv2[1] != 0.0) { color hsv = rgb_to_hsv(outcol); hsv[0] = hsv2[0]; hsv[1] = hsv2[1]; @@ -240,29 +240,29 @@ color node_mix_soft(float t, color col1, color col2) float tm = 1.0 - t; color one = color(1.0); - color scr = one - (one - col2)*(one - col1); + color scr = one - (one - col2) * (one - col1); - return tm*col1 + t*((one - col1)*col2*col1 + col1*scr); + return tm * col1 + t * ((one - col1) * col2 * col1 + col1 * scr); } color node_mix_linear(float t, color col1, color col2) { color outcol = col1; - if(col2[0] > 0.5) - outcol[0]= col1[0] + t*(2.0*(col2[0] - 0.5)); + if (col2[0] > 0.5) + outcol[0] = col1[0] + t * (2.0 * (col2[0] - 0.5)); else - outcol[0]= col1[0] + t*(2.0*(col2[0]) - 1.0); + outcol[0] = col1[0] + t * (2.0 * (col2[0]) - 1.0); - if(col2[1] > 0.5) - outcol[1]= col1[1] + t*(2.0*(col2[1] - 0.5)); + if (col2[1] > 0.5) + outcol[1] = col1[1] + t * (2.0 * (col2[1] - 0.5)); else - outcol[1]= col1[1] + t*(2.0*(col2[1]) - 1.0); + outcol[1] = col1[1] + t * (2.0 * (col2[1]) - 1.0); - if(col2[2] > 0.5) - outcol[2]= col1[2] + t*(2.0*(col2[2] - 0.5)); + if (col2[2] > 0.5) + outcol[2] = col1[2] + t * (2.0 * (col2[2] - 0.5)); else - outcol[2]= col1[2] + t*(2.0*(col2[2]) - 1.0); + outcol[2] = col1[2] + t * (2.0 * (col2[2]) - 1.0); return outcol; } @@ -288,44 +288,44 @@ shader node_mix( { float t = clamp(Fac, 0.0, 1.0); - if(type == "Mix") + if (type == "Mix") Color = node_mix_blend(t, Color1, Color2); - if(type == "Add") + if (type == "Add") Color = node_mix_add(t, Color1, Color2); - if(type == "Multiply") + if (type == "Multiply") Color = node_mix_mul(t, Color1, Color2); - if(type == "Screen") + if (type == "Screen") Color = node_mix_screen(t, Color1, Color2); - if(type == "Overlay") + if (type == "Overlay") Color = node_mix_overlay(t, Color1, Color2); - if(type == "Subtract") + if (type == "Subtract") Color = node_mix_sub(t, Color1, Color2); - if(type == "Divide") + if (type == "Divide") Color = node_mix_div(t, Color1, Color2); - if(type == "Difference") + if (type == "Difference") Color = node_mix_diff(t, Color1, Color2); - if(type == "Darken") + if (type == "Darken") Color = node_mix_dark(t, Color1, Color2); - if(type == "Lighten") + if (type == "Lighten") Color = node_mix_light(t, Color1, Color2); - if(type == "Dodge") + if (type == "Dodge") Color = node_mix_dodge(t, Color1, Color2); - if(type == "Burn") + if (type == "Burn") Color = node_mix_burn(t, Color1, Color2); - if(type == "Hue") + if (type == "Hue") Color = node_mix_hue(t, Color1, Color2); - if(type == "Saturation") + if (type == "Saturation") Color = node_mix_sat(t, Color1, Color2); - if(type == "Value") + if (type == "Value") Color = node_mix_val (t, Color1, Color2); - if(type == "Color") + if (type == "Color") Color = node_mix_color(t, Color1, Color2); - if(type == "Soft Light") + if (type == "Soft Light") Color = node_mix_soft(t, Color1, Color2); - if(type == "Linear Light") + if (type == "Linear Light") Color = node_mix_linear(t, Color1, Color2); - if(Clamp) + if (Clamp) Color = node_mix_clamp(Color); } diff --git a/intern/cycles/kernel/osl/nodes/node_mix_closure.osl b/intern/cycles/kernel/shaders/node_mix_closure.osl index 1a377abd381..e28dd1fc436 100644 --- a/intern/cycles/kernel/osl/nodes/node_mix_closure.osl +++ b/intern/cycles/kernel/shaders/node_mix_closure.osl @@ -25,6 +25,6 @@ shader node_mix_closure( output closure color Closure = background()) { float t = clamp(Fac, 0.0, 1.0); - Closure = (1.0 - t)*Closure1 + t*Closure2; + Closure = (1.0 - t) * Closure1 + t * Closure2; } diff --git a/intern/cycles/kernel/osl/nodes/node_musgrave_texture.osl b/intern/cycles/kernel/shaders/node_musgrave_texture.osl index 7d125d50fd6..71461b8fd79 100644 --- a/intern/cycles/kernel/osl/nodes/node_musgrave_texture.osl +++ b/intern/cycles/kernel/shaders/node_musgrave_texture.osl @@ -36,14 +36,14 @@ float noise_musgrave_fBm(point p, string basis, float H, float lacunarity, float float pwHL = pow(lacunarity, -H); int i; - for(i = 0; i < (int)octaves; i++) { + for (i = 0; i < (int)octaves; i++) { value += noise("perlin", p) * pwr; pwr *= pwHL; p *= lacunarity; } rmd = octaves - floor(octaves); - if(rmd != 0.0) + if (rmd != 0.0) value += rmd * noise("perlin", p) * pwr; return value; @@ -64,14 +64,14 @@ float noise_musgrave_multi_fractal(point p, string basis, float H, float lacunar float pwHL = pow(lacunarity, -H); int i; - for(i = 0; i < (int)octaves; i++) { + for (i = 0; i < (int)octaves; i++) { value *= (pwr * noise("perlin", p) + 1.0); pwr *= pwHL; p *= lacunarity; } rmd = octaves - floor(octaves); - if(rmd != 0.0) + if (rmd != 0.0) value *= (rmd * pwr * noise("perlin", p) + 1.0); /* correct? */ return value; @@ -96,7 +96,7 @@ float noise_musgrave_hetero_terrain(point p, string basis, float H, float lacuna value = offset + noise("perlin", p); p *= lacunarity; - for(i = 1; i < (int)octaves; i++) { + for (i = 1; i < (int)octaves; i++) { increment = (noise("perlin", p) + offset) * pwr * value; value += increment; pwr *= pwHL; @@ -104,7 +104,7 @@ float noise_musgrave_hetero_terrain(point p, string basis, float H, float lacuna } rmd = octaves - floor(octaves); - if(rmd != 0.0) { + if (rmd != 0.0) { increment = (noise("perlin", p) + offset) * pwr * value; value += rmd * increment; } @@ -120,7 +120,8 @@ float noise_musgrave_hetero_terrain(point p, string basis, float H, float lacuna * offset: raises the terrain from `sea level' */ -float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H, float lacunarity, float octaves, float offset, float gain) +float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H, + float lacunarity, float octaves, float offset, float gain) { float result, signal, weight, rmd; float pwHL = pow(lacunarity, -H); @@ -131,8 +132,8 @@ float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H, float weight = gain * result; p *= lacunarity; - for(i = 1; (weight > 0.001) && (i < (int)octaves); i++) { - if(weight > 1.0) + for (i = 1; (weight > 0.001) && (i < (int)octaves); i++) { + if (weight > 1.0) weight = 1.0; signal = (noise("perlin", p) + offset) * pwr; @@ -143,7 +144,7 @@ float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H, float } rmd = octaves - floor(octaves); - if(rmd != 0.0) + if (rmd != 0.0) result += rmd * ((noise("perlin", p) + offset) * pwr); return result; @@ -157,7 +158,8 @@ float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H, float * offset: raises the terrain from `sea level' */ -float noise_musgrave_ridged_multi_fractal(point p, string basis, float H, float lacunarity, float octaves, float offset, float gain) +float noise_musgrave_ridged_multi_fractal(point p, string basis, float H, + float lacunarity, float octaves, float offset, float gain) { float result, signal, weight; float pwHL = pow(lacunarity, -H); @@ -169,7 +171,7 @@ float noise_musgrave_ridged_multi_fractal(point p, string basis, float H, float result = signal; weight = 1.0; - for(i = 1; i < (int)octaves; i++) { + for (i = 1; i < (int)octaves; i++) { p *= lacunarity; weight = clamp(signal * gain, 0.0, 1.0); signal = offset - fabs(noise("perlin", p)); @@ -202,18 +204,18 @@ shader node_musgrave_texture( string Basis = "Perlin"; float intensity = 1.0; - point p = Vector*Scale; - - if(Type == "Multifractal") - Fac = intensity*noise_musgrave_multi_fractal(p, Basis, dimension, lacunarity, octaves); - else if(Type == "fBM") - Fac = intensity*noise_musgrave_fBm(p, Basis, dimension, lacunarity, octaves); - else if(Type == "Hybrid Multifractal") - Fac = intensity*noise_musgrave_hybrid_multi_fractal(p, Basis, dimension, lacunarity, octaves, Offset, Gain); - else if(Type == "Ridged Multifractal") - Fac = intensity*noise_musgrave_ridged_multi_fractal(p, Basis, dimension, lacunarity, octaves, Offset, Gain); - else if(Type == "Hetero Terrain") - Fac = intensity*noise_musgrave_hetero_terrain(p, Basis, dimension, lacunarity, octaves, Offset); + point p = Vector * Scale; + + if (Type == "Multifractal") + Fac = intensity * noise_musgrave_multi_fractal(p, Basis, dimension, lacunarity, octaves); + else if (Type == "fBM") + Fac = intensity * noise_musgrave_fBm(p, Basis, dimension, lacunarity, octaves); + else if (Type == "Hybrid Multifractal") + Fac = intensity * noise_musgrave_hybrid_multi_fractal(p, Basis, dimension, lacunarity, octaves, Offset, Gain); + else if (Type == "Ridged Multifractal") + Fac = intensity * noise_musgrave_ridged_multi_fractal(p, Basis, dimension, lacunarity, octaves, Offset, Gain); + else if (Type == "Hetero Terrain") + Fac = intensity * noise_musgrave_hetero_terrain(p, Basis, dimension, lacunarity, octaves, Offset); Color = color(Fac, Fac, Fac); } diff --git a/intern/cycles/kernel/osl/nodes/node_noise_texture.osl b/intern/cycles/kernel/shaders/node_noise_texture.osl index 1ddb4d8a08b..227b2bf8cea 100644 --- a/intern/cycles/kernel/osl/nodes/node_noise_texture.osl +++ b/intern/cycles/kernel/shaders/node_noise_texture.osl @@ -25,8 +25,8 @@ float noise(point p, string basis, float distortion, float detail, float fac, co { point r; int hard = 0; - - if(distortion != 0.0) { + + if (distortion != 0.0) { r[0] = noise_basis(p + point(13.5), basis) * distortion; r[1] = noise_basis(p, basis) * distortion; r[2] = noise_basis(p - point(13.5), basis) * distortion; @@ -51,6 +51,6 @@ shader node_noise_texture( output color Color = color(0.2, 0.2, 0.2)) { string Basis = "Perlin"; - Fac = noise(Vector*Scale, Basis, Distortion, Detail, Fac, Color); + Fac = noise(Vector * Scale, Basis, Distortion, Detail, Fac, Color); } diff --git a/intern/cycles/kernel/osl/nodes/node_normal.osl b/intern/cycles/kernel/shaders/node_normal.osl index d5f16acb88c..d5f16acb88c 100644 --- a/intern/cycles/kernel/osl/nodes/node_normal.osl +++ b/intern/cycles/kernel/shaders/node_normal.osl diff --git a/intern/cycles/kernel/shaders/node_normal_map.osl b/intern/cycles/kernel/shaders/node_normal_map.osl new file mode 100644 index 00000000000..d101ee870b7 --- /dev/null +++ b/intern/cycles/kernel/shaders/node_normal_map.osl @@ -0,0 +1,52 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "stdosl.h" + +shader node_normal_map( + normal NormalIn = N, + float Strength = 1.0, + color Color = color(0.5, 0.5, 1.0), + string space = "Tangent", + string attr_name = "geom:tangent", + string attr_sign_name = "geom:tangent_sign", + output normal Normal = NormalIn) +{ + color mcolor = 2.0*color(Color[0] - 0.5, Color[1] - 0.5, Color[2] - 0.5); + + if (space == "Tangent") { + vector tangent; + float tangent_sign; + + getattribute(attr_name, tangent); + getattribute(attr_sign_name, tangent_sign); + + tangent = transform("object", "world", tangent); + + vector B = tangent_sign * cross(NormalIn, tangent); + Normal = normalize(mcolor[0] * tangent + mcolor[1] * B + mcolor[2] * NormalIn); + } + else if (space == "Object") + Normal = normalize(transform("object", "world", vector(mcolor))); + else if (space == "World") + Normal = normalize(vector(mcolor)); + + if (Strength != 1.0) + Normal = normalize(NormalIn + (Normal - NormalIn)*max(Strength, 0.0)); +} + diff --git a/intern/cycles/kernel/shaders/node_object_info.osl b/intern/cycles/kernel/shaders/node_object_info.osl new file mode 100644 index 00000000000..c3b1ff29f09 --- /dev/null +++ b/intern/cycles/kernel/shaders/node_object_info.osl @@ -0,0 +1,32 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "stdosl.h" + +shader node_object_info( + output point Location = point(0.0, 0.0, 0.0), + output float ObjectIndex = 0.0, + output float MaterialIndex = 0.0, + output float Random = 0.0) +{ + getattribute("object:location", Location); + getattribute("object:index", ObjectIndex); + getattribute("material:index", MaterialIndex); + getattribute("object:random", Random); +} + diff --git a/intern/cycles/kernel/osl/nodes/node_output_displacement.osl b/intern/cycles/kernel/shaders/node_output_displacement.osl index a6b452c532a..5649b879c5b 100644 --- a/intern/cycles/kernel/osl/nodes/node_output_displacement.osl +++ b/intern/cycles/kernel/shaders/node_output_displacement.osl @@ -20,6 +20,6 @@ displacement node_output_displacement(float Displacement = 0.0) { - P += N*Displacement*0.1; /* todo: get rid of this factor */ + P += N * Displacement * 0.1; /* todo: get rid of this factor */ } diff --git a/intern/cycles/kernel/osl/nodes/node_output_surface.osl b/intern/cycles/kernel/shaders/node_output_surface.osl index 6efaf91121b..6efaf91121b 100644 --- a/intern/cycles/kernel/osl/nodes/node_output_surface.osl +++ b/intern/cycles/kernel/shaders/node_output_surface.osl diff --git a/intern/cycles/kernel/osl/nodes/node_output_volume.osl b/intern/cycles/kernel/shaders/node_output_volume.osl index 18094242dc7..18094242dc7 100644 --- a/intern/cycles/kernel/osl/nodes/node_output_volume.osl +++ b/intern/cycles/kernel/shaders/node_output_volume.osl diff --git a/intern/cycles/kernel/osl/nodes/node_particle_info.osl b/intern/cycles/kernel/shaders/node_particle_info.osl index aadc2812865..5e59ad1a990 100644 --- a/intern/cycles/kernel/osl/nodes/node_particle_info.osl +++ b/intern/cycles/kernel/shaders/node_particle_info.osl @@ -25,15 +25,14 @@ shader node_particle_info( output point Location = point(0.0, 0.0, 0.0), output float Size = 0.0, output vector Velocity = point(0.0, 0.0, 0.0), - output vector AngularVelocity = point(0.0, 0.0, 0.0) - ) + output vector AngularVelocity = point(0.0, 0.0, 0.0)) { - getattribute("std::particle_index", Index); - getattribute("std::particle_age", Age); - getattribute("std::particle_lifetime", Lifetime); - getattribute("std::particle_location", Location); - getattribute("std::particle_size", Size); - getattribute("std::particle_velocity", Velocity); - getattribute("std::particle_angular_velocity", AngularVelocity); + getattribute("particle:index", Index); + getattribute("particle:age", Age); + getattribute("particle:lifetime", Lifetime); + getattribute("particle:location", Location); + getattribute("particle:size", Size); + getattribute("particle:velocity", Velocity); + getattribute("particle:angular_velocity", AngularVelocity); } diff --git a/intern/cycles/kernel/shaders/node_refraction_bsdf.osl b/intern/cycles/kernel/shaders/node_refraction_bsdf.osl new file mode 100644 index 00000000000..0cf9d460c6e --- /dev/null +++ b/intern/cycles/kernel/shaders/node_refraction_bsdf.osl @@ -0,0 +1,39 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "stdosl.h" + +shader node_refraction_bsdf( + color Color = color(0.8, 0.8, 0.8), + string distribution = "Sharp", + float Roughness = 0.2, + float IOR = 1.45, + normal Normal = N, + output closure color BSDF = diffuse(Normal)) +{ + float f = max(IOR, 1.0 + 1e-5); + float eta = backfacing() ? 1.0 / f: f; + + if (distribution == "Sharp") + BSDF = Color * refraction(Normal, eta); + else if (distribution == "Beckmann") + BSDF = Color * microfacet_beckmann_refraction(Normal, Roughness, eta); + else if (distribution == "GGX") + BSDF = Color * microfacet_ggx_refraction(Normal, Roughness, eta); +} + diff --git a/intern/cycles/kernel/osl/nodes/node_image_texture.osl b/intern/cycles/kernel/shaders/node_rgb_ramp.osl index 38126401d76..a128ebbd1cf 100644 --- a/intern/cycles/kernel/osl/nodes/node_image_texture.osl +++ b/intern/cycles/kernel/shaders/node_rgb_ramp.osl @@ -17,18 +17,27 @@ */ #include "stdosl.h" -#include "node_color.h" +#include "oslutil.h" -shader node_image_texture( - point Vector = P, - string filename = "", - string color_space = "sRGB", +shader node_rgb_ramp( + color ramp_color[RAMP_TABLE_SIZE] = {0.0}, + float ramp_alpha[RAMP_TABLE_SIZE] = {0.0}, + + float Fac = 0.0, output color Color = color(0.0, 0.0, 0.0), output float Alpha = 1.0) { - Color = (color)texture(filename, Vector[0], 1.0-Vector[1], "wrap", "periodic", "alpha", Alpha); + float f = clamp(Fac, 0.0, 1.0) * (RAMP_TABLE_SIZE - 1); + + int i = (int)f; + float t = f - (float)i; + + Color = ramp_color[i]; + Alpha = ramp_alpha[i]; - if(color_space == "sRGB") - Color = color_srgb_to_scene_linear(Color); + if (t > 0.0) { + Color = (1.0 - t) * Color + t * ramp_color[i + 1]; + Alpha = (1.0 - t) * Alpha + t * ramp_alpha[i + 1]; + } } diff --git a/intern/cycles/kernel/osl/nodes/node_separate_rgb.osl b/intern/cycles/kernel/shaders/node_separate_rgb.osl index b48bd7e59d6..b48bd7e59d6 100644 --- a/intern/cycles/kernel/osl/nodes/node_separate_rgb.osl +++ b/intern/cycles/kernel/shaders/node_separate_rgb.osl diff --git a/intern/cycles/kernel/shaders/node_set_normal.osl b/intern/cycles/kernel/shaders/node_set_normal.osl new file mode 100644 index 00000000000..27a4b2f5b8b --- /dev/null +++ b/intern/cycles/kernel/shaders/node_set_normal.osl @@ -0,0 +1,28 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "stdosl.h" + +surface node_set_normal( + normal Direction = N, + output normal Normal = N) +{ + N = Direction; + Normal = Direction; +} + diff --git a/intern/cycles/kernel/osl/nodes/node_sky_texture.osl b/intern/cycles/kernel/shaders/node_sky_texture.osl index fdb9b1d9708..932fb1e2f17 100644 --- a/intern/cycles/kernel/osl/nodes/node_sky_texture.osl +++ b/intern/cycles/kernel/shaders/node_sky_texture.osl @@ -32,10 +32,10 @@ color xyY_to_xyz(float x, float y, float Y) { float X, Z; - if(y != 0.0) X = (x / y) * Y; + if (y != 0.0) X = (x / y) * Y; else X = 0.0; - if(y != 0.0 && Y != 0.0) Z = ((1.0 - x - y) / y) * Y; + if (y != 0.0 && Y != 0.0) Z = ((1.0 - x - y) / y) * Y; else Z = 0.0; return color(X, Y, Z); @@ -50,11 +50,11 @@ color xyz_to_rgb(float x, float y, float z) float sky_angle_between(float thetav, float phiv, float theta, float phi) { - float cospsi = sin(thetav)*sin(theta)*cos(phi - phiv) + cos(thetav)*cos(theta); + float cospsi = sin(thetav) * sin(theta) * cos(phi - phiv) + cos(thetav) * cos(theta); - if(cospsi > 1.0) + if (cospsi > 1.0) return 0.0; - if(cospsi < -1.0) + if (cospsi < -1.0) return M_PI; return acos(cospsi); @@ -70,7 +70,7 @@ float sky_perez_function(float lam[5], float theta, float gamma) float ctheta = cos(theta); float cgamma = cos(gamma); - return (1.0 + lam[0]*exp(lam[1] / ctheta)) * (1.0 + lam[2]*exp(lam[3]*gamma) + lam[4]*cgamma*cgamma); + return (1.0 + lam[0] * exp(lam[1] / ctheta)) * (1.0 + lam[2] * exp(lam[3] * gamma) + lam[4] * cgamma * cgamma); } color sky_xyz_radiance(KernelSunSky sunsky, vector dir) @@ -106,42 +106,42 @@ void precompute_sunsky(vector dir, float turbidity, output KernelSunSky sunsky) sunsky.phi = phi; sunsky.dir = dir; - float theta2 = theta*theta; - float theta3 = theta*theta*theta; + float theta2 = theta * theta; + float theta3 = theta * theta * theta; float T = turbidity; - float T2 = T*T; + float T2 = T * T; - float chi = (4.0/ 9.0- T / 120.0) * (M_PI - 2.0* theta); - sunsky.zenith_Y = (4.0453*T - 4.9710) * tan(chi) - 0.2155*T + 2.4192; + float chi = (4.0 / 9.0 - T / 120.0) * (M_PI - 2.0 * theta); + sunsky.zenith_Y = (4.0453 * T - 4.9710) * tan(chi) - 0.2155 * T + 2.4192; sunsky.zenith_Y *= 0.06; sunsky.zenith_x = - (0.00166* theta3 - 0.00375* theta2 + 0.00209* theta)*T2 + - (-0.02903* theta3 + 0.06377* theta2 - 0.03202* theta + 0.00394)*T + - (0.11693* theta3 - 0.21196* theta2 + 0.06052* theta + 0.25886); + ( 0.00166 * theta3 - 0.00375 * theta2 + 0.00209 * theta) * T2 + + (-0.02903 * theta3 + 0.06377 * theta2 - 0.03202 * theta + 0.00394) * T + + ( 0.11693 * theta3 - 0.21196 * theta2 + 0.06052 * theta + 0.25886); sunsky.zenith_y = - (0.00275* theta3 - 0.00610* theta2 + 0.00317* theta)*T2 + - (-0.04214* theta3 + 0.08970* theta2 - 0.04153* theta + 0.00516)*T + - (0.15346* theta3 - 0.26756* theta2 + 0.06670* theta + 0.26688); - - sunsky.perez_Y[0] = (0.1787*T - 1.4630); - sunsky.perez_Y[1] = (-0.3554*T + 0.4275); - sunsky.perez_Y[2] = (-0.0227*T + 5.3251); - sunsky.perez_Y[3] = (0.1206*T - 2.5771); - sunsky.perez_Y[4] = (-0.0670*T + 0.3703); - - sunsky.perez_x[0] = (-0.0193*T - 0.2592); - sunsky.perez_x[1] = (-0.0665*T + 0.0008); - sunsky.perez_x[2] = (-0.0004*T + 0.2125); - sunsky.perez_x[3] = (-0.0641*T - 0.8989); - sunsky.perez_x[4] = (-0.0033*T + 0.0452); - - sunsky.perez_y[0] = (-0.0167*T - 0.2608); - sunsky.perez_y[1] = (-0.0950*T + 0.0092); - sunsky.perez_y[2] = (-0.0079*T + 0.2102); - sunsky.perez_y[3] = (-0.0441*T - 1.6537); - sunsky.perez_y[4] = (-0.0109*T + 0.0529); + ( 0.00275 * theta3 - 0.00610 * theta2 + 0.00317 * theta) * T2 + + (-0.04214 * theta3 + 0.08970 * theta2 - 0.04153 * theta + 0.00516) * T + + ( 0.15346 * theta3 - 0.26756 * theta2 + 0.06670 * theta + 0.26688); + + sunsky.perez_Y[0] = ( 0.1787 * T - 1.4630); + sunsky.perez_Y[1] = (-0.3554 * T + 0.4275); + sunsky.perez_Y[2] = (-0.0227 * T + 5.3251); + sunsky.perez_Y[3] = ( 0.1206 * T - 2.5771); + sunsky.perez_Y[4] = (-0.0670 * T + 0.3703); + + sunsky.perez_x[0] = (-0.0193 * T - 0.2592); + sunsky.perez_x[1] = (-0.0665 * T + 0.0008); + sunsky.perez_x[2] = (-0.0004 * T + 0.2125); + sunsky.perez_x[3] = (-0.0641 * T - 0.8989); + sunsky.perez_x[4] = (-0.0033 * T + 0.0452); + + sunsky.perez_y[0] = (-0.0167 * T - 0.2608); + sunsky.perez_y[1] = (-0.0950 * T + 0.0092); + sunsky.perez_y[2] = (-0.0079 * T + 0.2102); + sunsky.perez_y[3] = (-0.0441 * T - 1.6537); + sunsky.perez_y[4] = (-0.0109 * T + 0.0529); sunsky.zenith_Y /= sky_perez_function(sunsky.perez_Y, 0, theta); sunsky.zenith_x /= sky_perez_function(sunsky.perez_x, 0, theta); diff --git a/intern/cycles/kernel/shaders/node_tangent.osl b/intern/cycles/kernel/shaders/node_tangent.osl new file mode 100644 index 00000000000..731af89231a --- /dev/null +++ b/intern/cycles/kernel/shaders/node_tangent.osl @@ -0,0 +1,50 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "stdosl.h" + +shader node_tangent( + normal NormalIn = N, + string attr_name = "geom:tangent", + string direction_type = "Radial", + string axis = "Z", + output normal Tangent = normalize(dPdu)) +{ + vector T; + + if (direction_type == "UV Map") { + getattribute(attr_name, T); + } + else if (direction_type == "Radial") { + point generated; + + if (!getattribute("geom:generated", generated)) + generated = P; + + if (axis == "X") + T = vector(0.0, -(generated[2] - 0.5), (generated[1] - 0.5)); + else if (axis == "Y") + T = vector(-(generated[2] - 0.5), 0.0, (generated[0] - 0.5)); + else + T = vector(-(generated[1] - 0.5), (generated[0] - 0.5), 0.0); + } + + T = transform("object", "world", T); + Tangent = cross(NormalIn, normalize(cross(T, NormalIn))); +} + diff --git a/intern/cycles/kernel/osl/nodes/node_texture.h b/intern/cycles/kernel/shaders/node_texture.h index 7cd0742ffe8..1b3ba8207ab 100644 --- a/intern/cycles/kernel/osl/nodes/node_texture.h +++ b/intern/cycles/kernel/shaders/node_texture.h @@ -235,21 +235,21 @@ float noise_turbulence(point p, string basis, float details, int hard) float rmd = octaves - floor(octaves); - if(rmd != 0.0) { - float t = noise_basis(fscale*p, basis); + if (rmd != 0.0) { + float t = noise_basis(fscale * p, basis); - if(hard) - t = fabs(2.0*t - 1.0); + if (hard) + t = fabs(2.0 * t - 1.0); float sum2 = sum + t*amp; - sum *= ((float)(1 << n)/(float)((1 << (n+1)) - 1)); - sum2 *= ((float)(1 << (n+1))/(float)((1 << (n+2)) - 1)); + sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1)); + sum2 *= ((float)(1 << (n + 1)) / (float)((1 << (n + 2)) - 1)); return (1.0 - rmd)*sum + rmd*sum2; } else { - sum *= ((float)(1 << n)/(float)((1 << (n+1)) - 1)); + sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1)); return sum; } } diff --git a/intern/cycles/kernel/osl/nodes/node_texture_coordinate.osl b/intern/cycles/kernel/shaders/node_texture_coordinate.osl index 2acf72aef54..791838dfffe 100644 --- a/intern/cycles/kernel/osl/nodes/node_texture_coordinate.osl +++ b/intern/cycles/kernel/shaders/node_texture_coordinate.osl @@ -19,8 +19,9 @@ #include "stdosl.h" shader node_texture_coordinate( - normal Normal = N, + normal NormalIn = N, int is_background = 0, + int from_dupli = 0, string bump_offset = "center", output point Generated = point(0.0, 0.0, 0.0), @@ -28,36 +29,50 @@ shader node_texture_coordinate( output point Object = point(0.0, 0.0, 0.0), output point Camera = point(0.0, 0.0, 0.0), output point Window = point(0.0, 0.0, 0.0), + output normal Normal = normal(0.0, 0.0, 0.0), output point Reflection = point(0.0, 0.0, 0.0)) { - if(is_background) { + if (is_background) { Generated = P; UV = point(0.0, 0.0, 0.0); Object = P; point Pcam = transform("camera", "world", point(0, 0, 0)); Camera = transform("camera", P + Pcam); Window = transform("NDC", P + Pcam); + Normal = NormalIn; Reflection = I; } else { - getattribute("std::generated", Generated); - getattribute("std::uv", UV); + if (from_dupli) { + getattribute("geom:dupli_generated", Generated); + getattribute("geom:dupli_uv", UV); + } + else { + getattribute("geom:generated", Generated); + getattribute("geom:uv", UV); + } + Object = transform("object", P); Camera = transform("camera", P); Window = transform("NDC", P); - Reflection = reflect(I, Normal); + Normal = transform("world", "object", NormalIn); + Reflection = reflect(I, NormalIn); } - if(bump_offset == "dx") { - Generated += Dx(Generated); - UV += Dx(UV); + if (bump_offset == "dx") { + if (!from_dupli) { + Generated += Dx(Generated); + UV += Dx(UV); + } Object += Dx(Object); Camera += Dx(Camera); Window += Dx(Window); } - else if(bump_offset == "dy") { - Generated += Dy(Generated); - UV += Dy(UV); + else if (bump_offset == "dy") { + if (!from_dupli) { + Generated += Dy(Generated); + UV += Dy(UV); + } Object += Dy(Object); Camera += Dy(Camera); Window += Dy(Window); diff --git a/intern/cycles/kernel/osl/nodes/node_translucent_bsdf.osl b/intern/cycles/kernel/shaders/node_translucent_bsdf.osl index 9acd46756d2..e7efe73700c 100644 --- a/intern/cycles/kernel/osl/nodes/node_translucent_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_translucent_bsdf.osl @@ -23,6 +23,6 @@ shader node_translucent_bsdf( normal Normal = N, output closure color BSDF = diffuse(Normal)) { - BSDF = Color*translucent(Normal); + BSDF = Color * translucent(Normal); } diff --git a/intern/cycles/kernel/osl/nodes/node_transparent_bsdf.osl b/intern/cycles/kernel/shaders/node_transparent_bsdf.osl index b347bfb116b..875bce3f16c 100644 --- a/intern/cycles/kernel/osl/nodes/node_transparent_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_transparent_bsdf.osl @@ -23,6 +23,6 @@ shader node_transparent_bsdf( normal Normal = N, output closure color BSDF = diffuse(Normal)) { - BSDF = Color*transparent(); + BSDF = Color * transparent(); } diff --git a/intern/cycles/kernel/osl/nodes/node_value.osl b/intern/cycles/kernel/shaders/node_value.osl index bee6f39f2bc..bee6f39f2bc 100644 --- a/intern/cycles/kernel/osl/nodes/node_value.osl +++ b/intern/cycles/kernel/shaders/node_value.osl diff --git a/intern/cycles/kernel/osl/nodes/node_vector_math.osl b/intern/cycles/kernel/shaders/node_vector_math.osl index 9e0f0b60522..f22a6e8441a 100644 --- a/intern/cycles/kernel/osl/nodes/node_vector_math.osl +++ b/intern/cycles/kernel/shaders/node_vector_math.osl @@ -25,27 +25,27 @@ shader node_vector_math( output float Value = 0.0, output vector Vector = vector(0.0, 0.0, 0.0)) { - if(type == "Add") { + if (type == "Add") { Vector = Vector1 + Vector2; - Value = (abs(Vector[0]) + abs(Vector[1]) + abs(Vector[2]))/3.0; + Value = (abs(Vector[0]) + abs(Vector[1]) + abs(Vector[2])) / 3.0; } - if(type == "Subtract") { + if (type == "Subtract") { Vector = Vector1 - Vector2; - Value = (abs(Vector[0]) + abs(Vector[1]) + abs(Vector[2]))/3.0; + Value = (abs(Vector[0]) + abs(Vector[1]) + abs(Vector[2])) / 3.0; } - if(type == "Average") { + if (type == "Average") { Value = length(Vector1 + Vector2); Vector = normalize(Vector1 + Vector2); } - if(type == "Dot Product") { + if (type == "Dot Product") { Value = dot(Vector1, Vector2); } - if(type == "Cross Product") { + if (type == "Cross Product") { vector c = cross(Vector1, Vector2); Value = length(c); Vector = normalize(c); } - if(type == "Normalize") { + if (type == "Normalize") { Value = length(Vector1); Vector = normalize(Vector1); } diff --git a/intern/cycles/kernel/osl/nodes/node_velvet_bsdf.osl b/intern/cycles/kernel/shaders/node_velvet_bsdf.osl index 5e0cae8cbd1..3aa662bdd08 100644 --- a/intern/cycles/kernel/osl/nodes/node_velvet_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_velvet_bsdf.osl @@ -27,6 +27,6 @@ shader node_velvet_bsdf( { float sigma = clamp(Sigma, 0.0, 1.0); - BSDF = Color*ashikhmin_velvet(Normal, sigma, 1.0); + BSDF = Color * ashikhmin_velvet(Normal, sigma); } diff --git a/intern/cycles/kernel/osl/nodes/node_voronoi_texture.osl b/intern/cycles/kernel/shaders/node_voronoi_texture.osl index db08b64de1c..a44df00a267 100644 --- a/intern/cycles/kernel/osl/nodes/node_voronoi_texture.osl +++ b/intern/cycles/kernel/shaders/node_voronoi_texture.osl @@ -32,16 +32,16 @@ shader node_voronoi_texture( float da[4]; point pa[4]; - voronoi(Vector*Scale, "Distance Squared", 1.0, da, pa); + voronoi(Vector * Scale, "Distance Squared", 1.0, da, pa); /* Colored output */ - if(Coloring == "Intensity") { + if (Coloring == "Intensity") { Fac = fabs(da[0]); Color = color(Fac); } else { Color = cellnoise_color(pa[0]); - Fac = (Color[0]+Color[1]+Color[2])*(1.0/3.0); + Fac = (Color[0] + Color[1] + Color[2]) * (1.0 / 3.0); } } diff --git a/intern/cycles/kernel/osl/nodes/node_ward_bsdf.osl b/intern/cycles/kernel/shaders/node_ward_bsdf.osl index 68db07109ed..e5c6f0ad705 100644 --- a/intern/cycles/kernel/osl/nodes/node_ward_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_ward_bsdf.osl @@ -20,11 +20,32 @@ shader node_ward_bsdf( color Color = color(0.8, 0.8, 0.8), - float RoughnessU = 0.0, - float RoughnessV = 0.0, + float Roughness = 0.0, + float Anisotropy = 0.0, + float Rotation = 0.0, normal Normal = N, + normal Tangent = normalize(dPdu), output closure color BSDF = diffuse(Normal)) { - BSDF = Color*ward(Normal, normalize(dPdu), RoughnessU, RoughnessV); + /* rotate tangent around normal */ + vector T = Tangent; + + if(Rotation != 0.0) + T = rotate(T, Rotation*2.0*M_PI, point(0.0, 0.0, 0.0), Normal); + + /* compute roughness */ + float RoughnessU, RoughnessV; + float aniso = clamp(Anisotropy, -0.99, 0.99); + + if(aniso < 0.0) { + RoughnessU = Roughness/(1.0 + aniso); + RoughnessV = Roughness*(1.0 + aniso); + } + else { + RoughnessU = Roughness*(1.0 - aniso); + RoughnessV = Roughness/(1.0 - aniso); + } + + BSDF = Color * ward(Normal, T, RoughnessU, RoughnessV); } diff --git a/intern/cycles/kernel/osl/nodes/node_wave_texture.osl b/intern/cycles/kernel/shaders/node_wave_texture.osl index db53faaf94b..79b8a8885d1 100644 --- a/intern/cycles/kernel/osl/nodes/node_wave_texture.osl +++ b/intern/cycles/kernel/shaders/node_wave_texture.osl @@ -30,15 +30,15 @@ float wave(point p, float scale, string type, float detail, float distortion, fl float result = 0.0; float n = 0.0; - if(type == "Bands") { - n = (x + y + z)*10.0; + if (type == "Bands") { + n = (x + y + z) * 10.0; } - else if(type == "Rings") { - n = (sqrt(x*x + y*y + z*z)*20.0); + else if (type == "Rings") { + n = (sqrt(x * x + y * y + z * z) * 20.0); } - - if(distortion != 0.0) { - n = n +(distortion * noise_turbulence(p*dscale, "Perlin", detail, 0)); + + if (distortion != 0.0) { + n = n + (distortion * noise_turbulence(p * dscale, "Perlin", detail, 0)); } result = noise_wave("Sine", n); diff --git a/intern/cycles/kernel/osl/nodes/oslutil.h b/intern/cycles/kernel/shaders/oslutil.h index 6c91684d9a6..6c91684d9a6 100644 --- a/intern/cycles/kernel/osl/nodes/oslutil.h +++ b/intern/cycles/kernel/shaders/oslutil.h diff --git a/intern/cycles/kernel/osl/nodes/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h index e5accf4eb54..24c3a50e6f6 100644 --- a/intern/cycles/kernel/osl/nodes/stdosl.h +++ b/intern/cycles/kernel/shaders/stdosl.h @@ -433,82 +433,21 @@ string concat (string a, string b, string c, string d, string e, string f) { closure color diffuse(normal N) BUILTIN; closure color oren_nayar(normal N, float sigma) BUILTIN; +closure color phong_ramp(normal N, float exponent, color colors[8]) BUILTIN; closure color translucent(normal N) BUILTIN; -closure color reflection(normal N, float eta) BUILTIN; -closure color reflection(normal N) { return reflection (N, 0.0); } +closure color reflection(normal N) BUILTIN; closure color refraction(normal N, float eta) BUILTIN; -closure color dielectric(normal N, float eta) BUILTIN; closure color transparent() BUILTIN; -closure color microfacet_ggx(normal N, float ag, float eta) BUILTIN; +closure color microfacet_ggx(normal N, float ag) BUILTIN; closure color microfacet_ggx_refraction(normal N, float ag, float eta) BUILTIN; -closure color microfacet_beckmann(normal N, float ab, float eta) BUILTIN; +closure color microfacet_beckmann(normal N, float ab) BUILTIN; closure color microfacet_beckmann_refraction(normal N, float ab, float eta) BUILTIN; closure color ward(normal N, vector T,float ax, float ay) BUILTIN; -closure color phong(normal N, float exponent) BUILTIN; -closure color phong_ramp(normal N, float exponent, color colors[8]) BUILTIN; -closure color hair_diffuse(vector T) BUILTIN; -closure color hair_specular(vector T, float offset, float exponent) BUILTIN; -closure color ashikhmin_velvet(normal N, float sigma, float eta) BUILTIN; -closure color westin_backscatter(normal N, float roughness) BUILTIN; -closure color westin_sheen(normal N, float edginess) BUILTIN; -closure color bssrdf_cubic(color radius) BUILTIN; -closure color emission(float inner_angle, float outer_angle) BUILTIN; -closure color emission(float outer_angle) BUILTIN; +closure color ashikhmin_velvet(normal N, float sigma) BUILTIN; closure color emission() BUILTIN; -closure color debug(string tag) BUILTIN; closure color background() BUILTIN; closure color holdout() BUILTIN; -closure color subsurface(float eta, float g, color mfp, color albedo) BUILTIN; - -closure color cloth(normal N, float s, float t, float dsdx, float dtdx, float dsdy, float dtdy, - float area_scaled, vector dPdu, color diff_warp_col, color diff_weft_col, - color spec_warp_col, color spec_weft_col, float fresnel_warp, float fresnel_weft, - float spread_x_mult, float spread_y_mult, int pattern, float pattern_angle, - float warp_width_scale, float weft_width_scale, float thread_count_mult_u, - float thread_count_mult_v) BUILTIN; -closure color cloth_specular(normal N, color spec_col[4], float eta[4], int thread_pattern[4], - float pattern_weight[4], int current_thread, float brdf_interp, - float btf_interp, float uux, float vvx, float area_scaled, vector dPdu, - float eccentricity[4], float angle[4], float Kx[4], float Ky[4], - float Sx[4], float Sy[4]) BUILTIN; -closure color fakefur_diffuse(normal N, vector T, float fur_reflectivity, float fur_transmission, - float shadow_start, float shadow_end, float fur_attenuation, float fur_density, - float fur_avg_radius, float fur_length, float fur_shadow_fraction) BUILTIN; -closure color fakefur_specular(normal N, vector T, float offset, float exp, float fur_reflectivity, - float fur_transmission, float shadow_start, float shadow_end, - float fur_attenuation, float fur_density, float fur_avg_radius, - float fur_length, float fur_shadow_fraction) BUILTIN; - -closure color fakefur_skin(vector N, vector T, float fur_reflectivity, float fur_transmission, - float shadow_start, float shadow_end, float fur_attenuation, float fur_density, - float fur_avg_radius, float fur_length) BUILTIN; - - -closure color cloth(normal N, float s, float t, color diff_warp, color diff_weft, - color spec_warp, color spec_weft, float fresnel_warp, float fresnel_weft, - float spread_x_mult, float spread_y_mult, int pattern, float pattern_angle, - float warp_width_scale, float weft_width_scale, float thread_count_mult_u, - float thread_count_mult_v) -{ - - return cloth(N, s, t, Dx(s), Dx(t), Dy(s), Dy(t), area(P), dPdu, diff_warp, diff_weft, spec_warp, spec_weft, - fresnel_warp, fresnel_weft, spread_x_mult, spread_y_mult, pattern, pattern_angle, - warp_width_scale, weft_width_scale, thread_count_mult_u, thread_count_mult_v); -} - -closure color cloth(normal N, float s, float t, color diff_warp, color diff_weft, - color spec_warp, color spec_weft, float fresnel_warp, float fresnel_weft, - float spread_x_mult, float spread_y_mult, int pattern, float pattern_angle, - float warp_width_scale, float weft_width_scale, float thread_count_mult_u, - float thread_count_mult_v, string tok, string val) -{ - - return cloth(N, s, t, Dx(s), Dx(t), Dy(s), Dy(t), area(P), dPdu, diff_warp, diff_weft, spec_warp, spec_weft, - fresnel_warp, fresnel_weft, spread_x_mult, spread_y_mult, pattern, pattern_angle, - warp_width_scale, weft_width_scale, thread_count_mult_u, thread_count_mult_v, tok, val); -} - - +closure color ambient_occlusion() BUILTIN; // Renderer state int raytype (string typename) BUILTIN; diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index 5b0f192ea47..886fce63fd4 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -82,6 +82,25 @@ __device_inline void stack_store_float(float *stack, uint a, float f) stack[a] = f; } +__device_inline int stack_load_int(float *stack, uint a) +{ + kernel_assert(a < SVM_STACK_SIZE); + + return __float_as_int(stack[a]); +} + +__device_inline float stack_load_int_default(float *stack, uint a, uint value) +{ + return (a == (uint)SVM_STACK_INVALID)? (int)value: stack_load_int(stack, a); +} + +__device_inline void stack_store_int(float *stack, uint a, int i) +{ + kernel_assert(a < SVM_STACK_SIZE); + + stack[a] = __int_as_float(i); +} + __device_inline bool stack_valid(uint a) { return a != (uint)SVM_STACK_INVALID; @@ -185,7 +204,7 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT break; } case NODE_CLOSURE_BSDF: - svm_node_closure_bsdf(kg, sd, stack, node, randb, path_flag); + svm_node_closure_bsdf(kg, sd, stack, node, randb, path_flag, &offset); break; case NODE_CLOSURE_EMISSION: svm_node_closure_emission(sd, stack, node); @@ -196,6 +215,9 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT case NODE_CLOSURE_HOLDOUT: svm_node_closure_holdout(sd, stack, node); break; + case NODE_CLOSURE_AMBIENT_OCCLUSION: + svm_node_closure_ambient_occlusion(sd, stack, node); + break; case NODE_CLOSURE_VOLUME: svm_node_closure_volume(kg, sd, stack, node, path_flag); break; @@ -261,14 +283,14 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT svm_node_camera(kg, sd, stack, node.y, node.z, node.w); break; case NODE_GEOMETRY: - svm_node_geometry(sd, stack, node.y, node.z); + svm_node_geometry(kg, sd, stack, node.y, node.z); break; #ifdef __EXTRA_NODES__ case NODE_GEOMETRY_BUMP_DX: - svm_node_geometry_bump_dx(sd, stack, node.y, node.z); + svm_node_geometry_bump_dx(kg, sd, stack, node.y, node.z); break; case NODE_GEOMETRY_BUMP_DY: - svm_node_geometry_bump_dy(sd, stack, node.y, node.z); + svm_node_geometry_bump_dy(kg, sd, stack, node.y, node.z); break; case NODE_LIGHT_PATH: svm_node_light_path(sd, stack, node.y, node.z, path_flag); @@ -334,7 +356,7 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT svm_node_set_displacement(sd, stack, node.y); break; case NODE_SET_BUMP: - svm_node_set_bump(sd, stack, node.y, node.z, node.w); + svm_node_set_bump(kg, sd, stack, node); break; case NODE_MATH: svm_node_math(kg, sd, stack, node.y, node.z, node.w, &offset); @@ -362,6 +384,9 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT case NODE_TEX_COORD_BUMP_DY: svm_node_tex_coord_bump_dy(kg, sd, stack, node.y, node.z); break; + case NODE_CLOSURE_SET_NORMAL: + svm_node_set_normal(kg, sd, stack, node.y, node.z ); + break; #endif case NODE_EMISSION_SET_WEIGHT_TOTAL: svm_node_emission_set_weight_total(kg, sd, node.y, node.z, node.w); @@ -376,7 +401,13 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT case NODE_LIGHT_FALLOFF: svm_node_light_falloff(sd, stack, node); break; -#endif + case NODE_TANGENT: + svm_node_tangent(kg, sd, stack, node); + break; + case NODE_NORMAL_MAP: + svm_node_normal_map(kg, sd, stack, node); + break; +#endif case NODE_END: default: #ifndef __MULTI_CLOSURE__ diff --git a/intern/cycles/kernel/svm/svm_bsdf.h b/intern/cycles/kernel/svm/svm_bsdf.h index 411916f8aa0..373710446e5 100644 --- a/intern/cycles/kernel/svm/svm_bsdf.h +++ b/intern/cycles/kernel/svm/svm_bsdf.h @@ -16,17 +16,18 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "bsdf_ashikhmin_velvet.h" -#include "bsdf_diffuse.h" -#include "bsdf_oren_nayar.h" -#include "bsdf_microfacet.h" -#include "bsdf_reflection.h" -#include "bsdf_refraction.h" -#include "bsdf_transparent.h" +#include "../closure/bsdf_ashikhmin_velvet.h" +#include "../closure/bsdf_diffuse.h" +#include "../closure/bsdf_oren_nayar.h" +#include "../closure/bsdf_phong_ramp.h" +#include "../closure/bsdf_microfacet.h" +#include "../closure/bsdf_reflection.h" +#include "../closure/bsdf_refraction.h" +#include "../closure/bsdf_transparent.h" #ifdef __DPDU__ -#include "bsdf_ward.h" +#include "../closure/bsdf_ward.h" #endif -#include "bsdf_westin.h" +#include "../closure/bsdf_westin.h" CCL_NAMESPACE_BEGIN @@ -36,45 +37,61 @@ __device int svm_bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, floa switch(sc->type) { case CLOSURE_BSDF_DIFFUSE_ID: - label = bsdf_diffuse_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_diffuse_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; #ifdef __SVM__ case CLOSURE_BSDF_OREN_NAYAR_ID: - label = bsdf_oren_nayar_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_oren_nayar_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; + /*case CLOSURE_BSDF_PHONG_RAMP_ID: + label = bsdf_phong_ramp_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + break;*/ case CLOSURE_BSDF_TRANSLUCENT_ID: - label = bsdf_translucent_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_translucent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_REFLECTION_ID: - label = bsdf_reflection_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_reflection_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_REFRACTION_ID: - label = bsdf_refraction_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_refraction_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_TRANSPARENT_ID: - label = bsdf_transparent_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_transparent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_MICROFACET_GGX_ID: case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: - label = bsdf_microfacet_ggx_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_microfacet_ggx_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: - label = bsdf_microfacet_beckmann_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_microfacet_beckmann_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; #ifdef __DPDU__ case CLOSURE_BSDF_WARD_ID: - label = bsdf_ward_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_ward_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; #endif case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: - label = bsdf_ashikhmin_velvet_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_ashikhmin_velvet_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID: - label = bsdf_westin_backscatter_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_westin_backscatter_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_WESTIN_SHEEN_ID: - label = bsdf_westin_sheen_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_westin_sheen_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; #endif default: @@ -92,45 +109,48 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con if(dot(sd->Ng, omega_in) >= 0.0f) { switch(sc->type) { case CLOSURE_BSDF_DIFFUSE_ID: - eval = bsdf_diffuse_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_diffuse_eval_reflect(sc, sd->I, omega_in, pdf); break; #ifdef __SVM__ case CLOSURE_BSDF_OREN_NAYAR_ID: - eval = bsdf_oren_nayar_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_oren_nayar_eval_reflect(sc, sd->I, omega_in, pdf); break; + /*case CLOSURE_BSDF_PHONG_RAMP_ID: + eval = bsdf_phong_ramp_eval_reflect(sc, sd->I, omega_in, pdf); + break;*/ case CLOSURE_BSDF_TRANSLUCENT_ID: - eval = bsdf_translucent_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_translucent_eval_reflect(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_REFLECTION_ID: - eval = bsdf_reflection_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_reflection_eval_reflect(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_REFRACTION_ID: - eval = bsdf_refraction_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_refraction_eval_reflect(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_TRANSPARENT_ID: - eval = bsdf_transparent_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_transparent_eval_reflect(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_MICROFACET_GGX_ID: case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: - eval = bsdf_microfacet_ggx_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_microfacet_ggx_eval_reflect(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: - eval = bsdf_microfacet_beckmann_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf); break; #ifdef __DPDU__ case CLOSURE_BSDF_WARD_ID: - eval = bsdf_ward_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_ward_eval_reflect(sc, sd->I, omega_in, pdf); break; #endif case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: - eval = bsdf_ashikhmin_velvet_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_ashikhmin_velvet_eval_reflect(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID: - eval = bsdf_westin_backscatter_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_westin_backscatter_eval_reflect(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_WESTIN_SHEEN_ID: - eval = bsdf_westin_sheen_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_westin_sheen_eval_reflect(sc, sd->I, omega_in, pdf); break; #endif default: @@ -141,45 +161,45 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con else { switch(sc->type) { case CLOSURE_BSDF_DIFFUSE_ID: - eval = bsdf_diffuse_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_diffuse_eval_transmit(sc, sd->I, omega_in, pdf); break; #ifdef __SVM__ case CLOSURE_BSDF_OREN_NAYAR_ID: - eval = bsdf_oren_nayar_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_oren_nayar_eval_transmit(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_TRANSLUCENT_ID: - eval = bsdf_translucent_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_translucent_eval_transmit(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_REFLECTION_ID: - eval = bsdf_reflection_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_reflection_eval_transmit(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_REFRACTION_ID: - eval = bsdf_refraction_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_refraction_eval_transmit(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_TRANSPARENT_ID: - eval = bsdf_transparent_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_transparent_eval_transmit(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_MICROFACET_GGX_ID: case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: - eval = bsdf_microfacet_ggx_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_microfacet_ggx_eval_transmit(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: - eval = bsdf_microfacet_beckmann_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf); break; #ifdef __DPDU__ case CLOSURE_BSDF_WARD_ID: - eval = bsdf_ward_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_ward_eval_transmit(sc, sd->I, omega_in, pdf); break; #endif case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: - eval = bsdf_ashikhmin_velvet_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_ashikhmin_velvet_eval_transmit(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID: - eval = bsdf_westin_backscatter_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_westin_backscatter_eval_transmit(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_WESTIN_SHEEN_ID: - eval = bsdf_westin_sheen_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_westin_sheen_eval_transmit(sc, sd->I, omega_in, pdf); break; #endif default: @@ -201,6 +221,9 @@ __device void svm_bsdf_blur(ShaderClosure *sc, float roughness) case CLOSURE_BSDF_OREN_NAYAR_ID: bsdf_oren_nayar_blur(sc, roughness); break; + /*case CLOSURE_BSDF_PHONG_RAMP_ID: + bsdf_phong_ramp_blur(sc, roughness); + break;*/ case CLOSURE_BSDF_TRANSLUCENT_ID: bsdf_translucent_blur(sc, roughness); break; diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h index 935504026ef..f378d24463d 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -20,19 +20,34 @@ CCL_NAMESPACE_BEGIN /* Closure Nodes */ -__device void svm_node_glossy_setup(ShaderData *sd, ShaderClosure *sc, int type, float eta, float roughness, bool refract) +__device void svm_node_glass_setup(ShaderData *sd, ShaderClosure *sc, int type, float eta, float roughness, bool refract) { - if(type == CLOSURE_BSDF_REFRACTION_ID) { + if(type == CLOSURE_BSDF_SHARP_GLASS_ID) { + if(refract) { + sc->data0 = eta; + sd->flag |= bsdf_refraction_setup(sc); + } + else + sd->flag |= bsdf_reflection_setup(sc); + } + else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID) { + sc->data0 = roughness; + sc->data1 = eta; + if(refract) - bsdf_refraction_setup(sd, sc, eta); + sd->flag |= bsdf_microfacet_beckmann_refraction_setup(sc); else - bsdf_reflection_setup(sd, sc); + sd->flag |= bsdf_microfacet_beckmann_setup(sc); } - else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) { - bsdf_microfacet_beckmann_setup(sd, sc, roughness, eta, refract); + else { + sc->data0 = roughness; + sc->data1 = eta; + + if(refract) + sd->flag |= bsdf_microfacet_ggx_refraction_setup(sc); + else + sd->flag |= bsdf_microfacet_ggx_setup(sc); } - else - bsdf_microfacet_ggx_setup(sd, sc, roughness, eta, refract); } __device_inline ShaderClosure *svm_node_closure_get(ShaderData *sd) @@ -57,7 +72,7 @@ __device_inline void svm_node_closure_set_mix_weight(ShaderClosure *sc, float mi #endif } -__device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, float randb, int path_flag) +__device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, float randb, int path_flag, int *offset) { uint type, param1_offset, param2_offset; @@ -66,11 +81,19 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st decode_node_uchar4(node.y, &type, ¶m1_offset, ¶m2_offset, &mix_weight_offset); float mix_weight = (stack_valid(mix_weight_offset)? stack_load_float(stack, mix_weight_offset): 1.0f); + /* note we read this extra node before weight check, so offset is added */ + uint4 data_node = read_node(kg, offset); + if(mix_weight == 0.0f) return; + + float3 N = stack_valid(data_node.y)? stack_load_float3(stack, data_node.y): sd->N; #else decode_node_uchar4(node.y, &type, ¶m1_offset, ¶m2_offset, NULL); float mix_weight = 1.0f; + + uint4 data_node = read_node(kg, offset); + float3 N = stack_valid(data_node.y)? stack_load_float3(stack, data_node.y): sd->N; #endif float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __int_as_float(node.z); @@ -79,25 +102,32 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st switch(type) { case CLOSURE_BSDF_DIFFUSE_ID: { ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; svm_node_closure_set_mix_weight(sc, mix_weight); float roughness = param1; - if(roughness == 0.0f) - bsdf_diffuse_setup(sd, sc); - else - bsdf_oren_nayar_setup(sd, sc, roughness); + + if(roughness == 0.0f) { + sd->flag |= bsdf_diffuse_setup(sc); + } + else { + sc->data0 = roughness; + sd->flag |= bsdf_oren_nayar_setup(sc); + } break; } case CLOSURE_BSDF_TRANSLUCENT_ID: { ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; svm_node_closure_set_mix_weight(sc, mix_weight); - bsdf_translucent_setup(sd, sc); + sd->flag |= bsdf_translucent_setup(sc); break; } case CLOSURE_BSDF_TRANSPARENT_ID: { ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; svm_node_closure_set_mix_weight(sc, mix_weight); - bsdf_transparent_setup(sd, sc); + sd->flag |= bsdf_transparent_setup(sc); break; } case CLOSURE_BSDF_REFLECTION_ID: @@ -108,17 +138,17 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st break; #endif ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; + sc->data0 = param1; svm_node_closure_set_mix_weight(sc, mix_weight); - float roughness = param1; - /* setup bsdf */ if(type == CLOSURE_BSDF_REFLECTION_ID) - bsdf_reflection_setup(sd, sc); + sd->flag |= bsdf_reflection_setup(sc); else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID) - bsdf_microfacet_beckmann_setup(sd, sc, roughness, 1.0f, false); + sd->flag |= bsdf_microfacet_beckmann_setup(sc); else - bsdf_microfacet_ggx_setup(sd, sc, roughness, 1.0f, false); + sd->flag |= bsdf_microfacet_ggx_setup(sc); break; } @@ -129,40 +159,68 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE)) break; #endif + ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; + sc->data0 = param1; + svm_node_closure_set_mix_weight(sc, mix_weight); + + float eta = fmaxf(param2, 1.0f + 1e-5f); + sc->data1 = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta; + + /* setup bsdf */ + if(type == CLOSURE_BSDF_REFRACTION_ID) + sd->flag |= bsdf_refraction_setup(sc); + else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) + sd->flag |= bsdf_microfacet_beckmann_refraction_setup(sc); + else + sd->flag |= bsdf_microfacet_ggx_refraction_setup(sc); + + break; + } + case CLOSURE_BSDF_SHARP_GLASS_ID: + case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID: + case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID: { +#ifdef __CAUSTICS_TRICKS__ + if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE)) + break; +#endif /* index of refraction */ float eta = fmaxf(param2, 1.0f + 1e-5f); eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta; /* fresnel */ - float cosNO = dot(sd->N, sd->I); + float cosNO = dot(N, sd->I); float fresnel = fresnel_dielectric_cos(cosNO, eta); float roughness = param1; #ifdef __MULTI_CLOSURE__ /* reflection */ ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; float3 weight = sc->weight; float sample_weight = sc->sample_weight; svm_node_closure_set_mix_weight(sc, mix_weight*fresnel); - svm_node_glossy_setup(sd, sc, type, eta, roughness, false); + svm_node_glass_setup(sd, sc, type, eta, roughness, false); /* refraction */ sc = svm_node_closure_get(sd); + sc->N = N; sc->weight = weight; sc->sample_weight = sample_weight; svm_node_closure_set_mix_weight(sc, mix_weight*(1.0f - fresnel)); - svm_node_glossy_setup(sd, sc, type, eta, roughness, true); + svm_node_glass_setup(sd, sc, type, eta, roughness, true); #else ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; bool refract = (randb > fresnel); svm_node_closure_set_mix_weight(sc, mix_weight); - svm_node_glossy_setup(sd, sc, type, eta, roughness, refract); + svm_node_glass_setup(sd, sc, type, eta, roughness, refract); #endif break; @@ -174,22 +232,41 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st break; #endif ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; + sc->T = stack_load_float3(stack, data_node.z); svm_node_closure_set_mix_weight(sc, mix_weight); - float roughness_u = param1; - float roughness_v = param2; + /* rotate tangent */ + float rotation = stack_load_float(stack, data_node.w); - bsdf_ward_setup(sd, sc, normalize(sd->dPdu), roughness_u, roughness_v); + if(rotation != 0.0f) + sc->T = rotate_around_axis(sc->T, sc->N, rotation * 2.0f * M_PI_F); + + /* compute roughness */ + float roughness = param1; + float anisotropy = clamp(param2, -0.99f, 0.99f); + + if(anisotropy < 0.0f) { + sc->data0 = roughness/(1.0f + anisotropy); + sc->data1 = roughness*(1.0f + anisotropy); + } + else { + sc->data0 = roughness*(1.0f - anisotropy); + sc->data1 = roughness/(1.0f - anisotropy); + } + + sd->flag |= bsdf_ward_setup(sc); break; } #endif case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: { ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; svm_node_closure_set_mix_weight(sc, mix_weight); /* sigma */ - float sigma = clamp(param1, 0.0f, 1.0f); - bsdf_ashikhmin_velvet_setup(sd, sc, sigma); + sc->data0 = clamp(param1, 0.0f, 1.0f); + sd->flag |= bsdf_ashikhmin_velvet_setup(sc); break; } default: @@ -222,7 +299,7 @@ __device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float * svm_node_closure_set_mix_weight(sc, mix_weight); float density = param1; - volume_transparent_setup(sd, sc, density); + sd->flag |= volume_transparent_setup(sc, density); break; } case CLOSURE_VOLUME_ISOTROPIC_ID: { @@ -230,7 +307,7 @@ __device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float * svm_node_closure_set_mix_weight(sc, mix_weight); float density = param1; - volume_isotropic_setup(sd, sc, density); + sd->flag |= volume_isotropic_setup(sc, density); break; } default: @@ -320,6 +397,34 @@ __device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 node) sd->flag |= SD_HOLDOUT; } +__device void svm_node_closure_ambient_occlusion(ShaderData *sd, float *stack, uint4 node) +{ +#ifdef __MULTI_CLOSURE__ + uint mix_weight_offset = node.y; + + if(stack_valid(mix_weight_offset)) { + float mix_weight = stack_load_float(stack, mix_weight_offset); + + if(mix_weight == 0.0f) + return; + + ShaderClosure *sc = svm_node_closure_get(sd); + sc->weight *= mix_weight; + sc->type = CLOSURE_AMBIENT_OCCLUSION_ID; + } + else { + ShaderClosure *sc = svm_node_closure_get(sd); + sc->type = CLOSURE_AMBIENT_OCCLUSION_ID; + } + +#else + ShaderClosure *sc = &sd->closure; + sc->type = CLOSURE_AMBIENT_OCCLUSION_ID; +#endif + + sd->flag |= SD_AO; +} + /* Closure Nodes */ __device_inline void svm_node_closure_store_weight(ShaderData *sd, float3 weight) @@ -425,5 +530,14 @@ __device void svm_node_add_closure(ShaderData *sd, float *stack, uint unused, #endif } +/* (Bump) normal */ + +__device void svm_node_set_normal(KernelGlobals *kg, ShaderData *sd, float *stack, uint in_direction, uint out_normal) +{ + float3 normal = stack_load_float3(stack, in_direction); + sd->N = normal; + stack_store_float3(stack, out_normal, normal); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm_convert.h b/intern/cycles/kernel/svm/svm_convert.h index 188b0489d9e..f74915a4bc9 100644 --- a/intern/cycles/kernel/svm/svm_convert.h +++ b/intern/cycles/kernel/svm/svm_convert.h @@ -23,6 +23,11 @@ CCL_NAMESPACE_BEGIN __device void svm_node_convert(ShaderData *sd, float *stack, uint type, uint from, uint to) { switch(type) { + case NODE_CONVERT_FI: { + float f = stack_load_float(stack, from); + stack_store_int(stack, to, (int)f); + break; + } case NODE_CONVERT_FV: { float f = stack_load_float(stack, from); stack_store_float3(stack, to, make_float3(f, f, f)); @@ -34,13 +39,34 @@ __device void svm_node_convert(ShaderData *sd, float *stack, uint type, uint fro stack_store_float(stack, to, g); break; } + case NODE_CONVERT_CI: { + float3 f = stack_load_float3(stack, from); + int i = (int)linear_rgb_to_gray(f); + stack_store_int(stack, to, i); + break; + } case NODE_CONVERT_VF: { float3 f = stack_load_float3(stack, from); float g = (f.x + f.y + f.z)*(1.0f/3.0f); stack_store_float(stack, to, g); break; } - + case NODE_CONVERT_VI: { + float3 f = stack_load_float3(stack, from); + int i = (f.x + f.y + f.z)*(1.0f/3.0f); + stack_store_int(stack, to, i); + break; + } + case NODE_CONVERT_IF: { + float f = (float)stack_load_int(stack, from); + stack_store_float(stack, to, f); + break; + } + case NODE_CONVERT_IV: { + float f = (float)stack_load_int(stack, from); + stack_store_float3(stack, to, make_float3(f, f, f)); + break; + } } } diff --git a/intern/cycles/kernel/svm/svm_displace.h b/intern/cycles/kernel/svm/svm_displace.h index b1677f67eca..92f23990ad1 100644 --- a/intern/cycles/kernel/svm/svm_displace.h +++ b/intern/cycles/kernel/svm/svm_displace.h @@ -20,23 +20,35 @@ CCL_NAMESPACE_BEGIN /* Bump Node */ -__device void svm_node_set_bump(ShaderData *sd, float *stack, uint c_offset, uint x_offset, uint y_offset) +__device void svm_node_set_bump(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) { #ifdef __RAY_DIFFERENTIALS__ + /* get normal input */ + float3 normal_in = stack_valid(node.y)? stack_load_float3(stack, node.y): sd->N; + + /* get surface tangents from normal */ + float3 Rx = cross(sd->dP.dy, normal_in); + float3 Ry = cross(normal_in, sd->dP.dx); + + /* get bump values */ + uint c_offset, x_offset, y_offset, intensity_offset; + decode_node_uchar4(node.z, &c_offset, &x_offset, &y_offset, &intensity_offset); + float h_c = stack_load_float(stack, c_offset); float h_x = stack_load_float(stack, x_offset); float h_y = stack_load_float(stack, y_offset); - float3 Rx = cross(sd->dP.dy, sd->N); - float3 Ry = cross(sd->N, sd->dP.dx); - + /* compute surface gradient and determinant */ float det = dot(sd->dP.dx, Rx); float3 surfgrad = (h_x - h_c)*Rx + (h_y - h_c)*Ry; + float intensity = stack_load_float(stack, intensity_offset); - surfgrad *= 0.1f; /* todo: remove this factor */ - + surfgrad *= intensity; float absdet = fabsf(det); - sd->N = normalize(absdet*sd->N - signf(det)*surfgrad); + + /* compute and output perturbed normal */ + float3 outN = normalize(absdet*normal_in - signf(det)*surfgrad); + stack_store_float3(stack, node.w, outN); #endif } diff --git a/intern/cycles/kernel/svm/svm_fresnel.h b/intern/cycles/kernel/svm/svm_fresnel.h index 7684eabeecb..d5b415a87ce 100644 --- a/intern/cycles/kernel/svm/svm_fresnel.h +++ b/intern/cycles/kernel/svm/svm_fresnel.h @@ -54,7 +54,7 @@ __device void svm_node_layer_weight(ShaderData *sd, float *stack, uint4 node) f = fabsf(dot(sd->I, sd->N)); if(blend != 0.5f) { - blend = clamp(blend, 0.0f, 1.0f); + blend = clamp(blend, 0.0f, 1.0f-1e-5f); blend = (blend < 0.5f)? 2.0f*blend: 0.5f/(1.0f - blend); f = powf(f, blend); diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h index 22741bdb067..c4d03c1f948 100644 --- a/intern/cycles/kernel/svm/svm_geometry.h +++ b/intern/cycles/kernel/svm/svm_geometry.h @@ -20,7 +20,7 @@ CCL_NAMESPACE_BEGIN /* Geometry Node */ -__device void svm_node_geometry(ShaderData *sd, float *stack, uint type, uint out_offset) +__device void svm_node_geometry(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset) { float3 data; @@ -28,7 +28,23 @@ __device void svm_node_geometry(ShaderData *sd, float *stack, uint type, uint ou case NODE_GEOM_P: data = sd->P; break; case NODE_GEOM_N: data = sd->N; break; #ifdef __DPDU__ - case NODE_GEOM_T: data = normalize(sd->dPdu); break; + case NODE_GEOM_T: { + /* try to create spherical tangent from generated coordinates */ + int attr_offset = (sd->object != ~0)? find_attribute(kg, sd, ATTR_STD_GENERATED): ATTR_STD_NOT_FOUND; + + if(attr_offset != ATTR_STD_NOT_FOUND) { + data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL); + data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f); + object_normal_transform(kg, sd, &data); + data = cross(sd->N, normalize(cross(data, sd->N)));; + } + else { + /* otherwise use surface derivatives */ + data = normalize(sd->dPdu); + } + + break; + } #endif case NODE_GEOM_I: data = sd->I; break; case NODE_GEOM_Ng: data = sd->Ng; break; @@ -40,7 +56,7 @@ __device void svm_node_geometry(ShaderData *sd, float *stack, uint type, uint ou stack_store_float3(stack, out_offset, data); } -__device void svm_node_geometry_bump_dx(ShaderData *sd, float *stack, uint type, uint out_offset) +__device void svm_node_geometry_bump_dx(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset) { #ifdef __RAY_DIFFERENTIALS__ float3 data; @@ -48,16 +64,16 @@ __device void svm_node_geometry_bump_dx(ShaderData *sd, float *stack, uint type, switch(type) { case NODE_GEOM_P: data = sd->P + sd->dP.dx; break; case NODE_GEOM_uv: data = make_float3(sd->u + sd->du.dx, sd->v + sd->dv.dx, 0.0f); break; - default: svm_node_geometry(sd, stack, type, out_offset); return; + default: svm_node_geometry(kg, sd, stack, type, out_offset); return; } stack_store_float3(stack, out_offset, data); #else - svm_node_geometry(sd, stack, type, out_offset); + svm_node_geometry(kg, sd, stack, type, out_offset); #endif } -__device void svm_node_geometry_bump_dy(ShaderData *sd, float *stack, uint type, uint out_offset) +__device void svm_node_geometry_bump_dy(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset) { #ifdef __RAY_DIFFERENTIALS__ float3 data; @@ -65,12 +81,12 @@ __device void svm_node_geometry_bump_dy(ShaderData *sd, float *stack, uint type, switch(type) { case NODE_GEOM_P: data = sd->P + sd->dP.dy; break; case NODE_GEOM_uv: data = make_float3(sd->u + sd->du.dy, sd->v + sd->dv.dy, 0.0f); break; - default: svm_node_geometry(sd, stack, type, out_offset); return; + default: svm_node_geometry(kg, sd, stack, type, out_offset); return; } stack_store_float3(stack, out_offset, data); #else - svm_node_geometry(sd, stack, type, out_offset); + svm_node_geometry(kg, sd, stack, type, out_offset); #endif } diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h index 662419418e3..0894c9c8290 100644 --- a/intern/cycles/kernel/svm/svm_image.h +++ b/intern/cycles/kernel/svm/svm_image.h @@ -52,6 +52,12 @@ __device_inline float svm_image_texture_frac(float x, int *ix) __device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, uint srgb) { + /* first slots are used by float textures, which are not supported here */ + if(id < TEX_NUM_FLOAT_IMAGES) + return make_float4(1.0f, 0.0f, 1.0f, 1.0f); + + id -= TEX_NUM_FLOAT_IMAGES; + uint4 info = kernel_tex_fetch(__tex_image_packed_info, id); uint width = info.x; uint height = info.y; @@ -265,7 +271,7 @@ __device void svm_node_tex_image_box(KernelGlobals *kg, ShaderData *sd, float *s * between three textures. * * the Nxyz values are the barycentric coordinates in an equilateral - * triangle, which in case of blending in the middle has a smaller + * triangle, which in case of blending, in the middle has a smaller * equilateral triangle where 3 textures blend. this divides things into * 7 zones, with an if() test for each zone */ diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h index 6bd8f2ac69c..8ca7dff3970 100644 --- a/intern/cycles/kernel/svm/svm_tex_coord.h +++ b/intern/cycles/kernel/svm/svm_tex_coord.h @@ -225,5 +225,100 @@ __device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, floa #endif } +__device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) +{ + uint color_offset, strength_offset, normal_offset, space; + decode_node_uchar4(node.y, &color_offset, &strength_offset, &normal_offset, &space); + + float3 color = stack_load_float3(stack, color_offset); + color = 2.0f*make_float3(color.x - 0.5f, color.y - 0.5f, color.z - 0.5f); + + float3 N; + + if(space == NODE_NORMAL_MAP_TANGENT) { + /* tangent space */ + if(sd->object == ~0) { + stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f)); + return; + } + + /* first try to get tangent attribute */ + int attr_offset = find_attribute(kg, sd, node.z); + int attr_sign_offset = find_attribute(kg, sd, node.w); + + if(attr_offset == ATTR_STD_NOT_FOUND || attr_sign_offset == ATTR_STD_NOT_FOUND) { + stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f)); + return; + } + + /* ensure orthogonal and normalized (interpolation breaks it) */ + float3 tangent = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL); + float sign = triangle_attribute_float(kg, sd, ATTR_ELEMENT_CORNER, attr_sign_offset, NULL, NULL); + + object_normal_transform(kg, sd, &tangent); + tangent = cross(sd->N, normalize(cross(tangent, sd->N)));; + + float3 B = sign * cross(sd->N, tangent); + N = normalize(color.x * tangent + color.y * B + color.z * sd->N); + } + else { + /* object, world space */ + N = color; + + if(space == NODE_NORMAL_MAP_OBJECT) + object_normal_transform(kg, sd, &N); + + N = normalize(N); + } + + float strength = stack_load_float(stack, strength_offset); + + if(strength != 1.0f) { + strength = max(strength, 0.0f); + N = normalize(sd->N + (N - sd->N)*strength); + } + + stack_store_float3(stack, normal_offset, normalize(N)); +} + +__device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) +{ + uint tangent_offset, direction_type, axis; + decode_node_uchar4(node.y, &tangent_offset, &direction_type, &axis, NULL); + + float3 tangent; + + if(direction_type == NODE_TANGENT_UVMAP) { + /* UV map */ + int attr_offset = find_attribute(kg, sd, node.z); + + if(attr_offset == ATTR_STD_NOT_FOUND) + tangent = make_float3(0.0f, 0.0f, 0.0f); + else + tangent = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL); + } + else { + /* radial */ + int attr_offset = find_attribute(kg, sd, node.z); + float3 generated; + + if(attr_offset == ATTR_STD_NOT_FOUND) + generated = sd->P; + else + generated = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL); + + if(axis == NODE_TANGENT_AXIS_X) + tangent = make_float3(0.0f, -(generated.z - 0.5f), (generated.y - 0.5f)); + else if(axis == NODE_TANGENT_AXIS_Y) + tangent = make_float3(-(generated.z - 0.5f), 0.0f, (generated.x - 0.5f)); + else + tangent = make_float3(-(generated.y - 0.5f), (generated.x - 0.5f), 0.0f); + } + + object_normal_transform(kg, sd, &tangent); + tangent = cross(sd->N, normalize(cross(tangent, sd->N))); + stack_store_float3(stack, tangent_offset, tangent); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index ee423573cdf..b41e34ab407 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -92,7 +92,11 @@ typedef enum NodeType { NODE_LIGHT_FALLOFF, NODE_OBJECT_INFO, NODE_PARTICLE_INFO, - NODE_TEX_BRICK + NODE_TEX_BRICK, + NODE_CLOSURE_SET_NORMAL, + NODE_CLOSURE_AMBIENT_OCCLUSION, + NODE_TANGENT, + NODE_NORMAL_MAP } NodeType; typedef enum NodeAttributeType { @@ -209,8 +213,13 @@ typedef enum NodeVectorMath { typedef enum NodeConvert { NODE_CONVERT_FV, + NODE_CONVERT_FI, NODE_CONVERT_CF, - NODE_CONVERT_VF + NODE_CONVERT_CI, + NODE_CONVERT_VF, + NODE_CONVERT_VI, + NODE_CONVERT_IF, + NODE_CONVERT_IV } NodeConvert; typedef enum NodeDistanceMetric { @@ -273,6 +282,23 @@ typedef enum NodeBlendWeightType { NODE_LAYER_WEIGHT_FACING } NodeBlendWeightType; +typedef enum NodeTangentDirectionType { + NODE_TANGENT_RADIAL, + NODE_TANGENT_UVMAP +} NodeTangentDirectionType; + +typedef enum NodeTangentAxis { + NODE_TANGENT_AXIS_X, + NODE_TANGENT_AXIS_Y, + NODE_TANGENT_AXIS_Z +} NodeTangentAxis; + +typedef enum NodeNormalMapSpace { + NODE_NORMAL_MAP_TANGENT, + NODE_NORMAL_MAP_OBJECT, + NODE_NORMAL_MAP_WORLD +} NodeNormalMapSpace; + typedef enum ShaderType { SHADER_TYPE_SURFACE, SHADER_TYPE_VOLUME, @@ -294,6 +320,7 @@ typedef enum ClosureType { CLOSURE_BSDF_WARD_ID, CLOSURE_BSDF_ASHIKHMIN_VELVET_ID, CLOSURE_BSDF_WESTIN_SHEEN_ID, + CLOSURE_BSDF_PHONG_RAMP_ID, CLOSURE_BSDF_TRANSMISSION_ID, CLOSURE_BSDF_TRANSLUCENT_ID, @@ -301,7 +328,9 @@ typedef enum ClosureType { CLOSURE_BSDF_WESTIN_BACKSCATTER_ID, CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID, CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID, - CLOSURE_BSDF_GLASS_ID, + CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID, + CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID, + CLOSURE_BSDF_SHARP_GLASS_ID, CLOSURE_BSDF_TRANSPARENT_ID, @@ -311,6 +340,7 @@ typedef enum ClosureType { CLOSURE_BACKGROUND_ID, CLOSURE_HOLDOUT_ID, CLOSURE_SUBSURFACE_ID, + CLOSURE_AMBIENT_OCCLUSION_ID, CLOSURE_VOLUME_ID, CLOSURE_VOLUME_TRANSPARENT_ID, @@ -322,12 +352,13 @@ typedef enum ClosureType { /* watch this, being lazy with memory usage */ #define CLOSURE_IS_BSDF(type) (type <= CLOSURE_BSDF_TRANSPARENT_ID) #define CLOSURE_IS_BSDF_DIFFUSE(type) (type >= CLOSURE_BSDF_DIFFUSE_ID && type <= CLOSURE_BSDF_OREN_NAYAR_ID) -#define CLOSURE_IS_BSDF_GLOSSY(type) (type >= CLOSURE_BSDF_GLOSSY_ID && type <= CLOSURE_BSDF_WESTIN_SHEEN_ID) -#define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSMISSION_ID && type <= CLOSURE_BSDF_GLASS_ID) +#define CLOSURE_IS_BSDF_GLOSSY(type) (type >= CLOSURE_BSDF_GLOSSY_ID && type <= CLOSURE_BSDF_PHONG_RAMP_ID) +#define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSMISSION_ID && type <= CLOSURE_BSDF_SHARP_GLASS_ID) #define CLOSURE_IS_VOLUME(type) (type >= CLOSURE_VOLUME_ID && type <= CLOSURE_VOLUME_ISOTROPIC_ID) #define CLOSURE_IS_EMISSION(type) (type == CLOSURE_EMISSION_ID) #define CLOSURE_IS_HOLDOUT(type) (type == CLOSURE_HOLDOUT_ID) #define CLOSURE_IS_BACKGROUND(type) (type == CLOSURE_BACKGROUND_ID) +#define CLOSURE_IS_AMBIENT_OCCLUSION(type) (type == CLOSURE_AMBIENT_OCCLUSION_ID) CCL_NAMESPACE_END diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt index e75a3b37f3b..7907061c19c 100644 --- a/intern/cycles/render/CMakeLists.txt +++ b/intern/cycles/render/CMakeLists.txt @@ -8,6 +8,7 @@ set(INC ../bvh ../util ) + set(INC_SYS ${GLEW_INCLUDE_PATH} ) diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index 5122c1af410..95941c14b6c 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -162,6 +162,10 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name) attr = add(name, TypeDesc::TypeNormal, Attribute::FACE); else if(std == ATTR_STD_UV) attr = add(name, TypeDesc::TypePoint, Attribute::CORNER); + else if(std == ATTR_STD_UV_TANGENT) + attr = add(name, TypeDesc::TypeVector, Attribute::CORNER); + else if(std == ATTR_STD_UV_TANGENT_SIGN) + attr = add(name, TypeDesc::TypeFloat, Attribute::CORNER); else if(std == ATTR_STD_GENERATED) attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX); else if(std == ATTR_STD_POSITION_UNDEFORMED) diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp index 6f8740b8a51..3b61ccd176d 100644 --- a/intern/cycles/render/buffers.cpp +++ b/intern/cycles/render/buffers.cpp @@ -101,7 +101,7 @@ RenderTile::RenderTile() RenderBuffers::RenderBuffers(Device *device_) { - device = device_; + device = device_; } RenderBuffers::~RenderBuffers() diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 3fd7a1b28e3..308ebd0794a 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -19,6 +19,8 @@ #include "camera.h" #include "scene.h" +#include "device.h" + #include "util_vector.h" CCL_NAMESPACE_BEGIN @@ -53,15 +55,10 @@ Camera::Camera() width = 1024; height = 512; - left = -((float)width/(float)height); - right = (float)width/(float)height; - bottom = -1.0f; - top = 1.0f; - - border_left = 0.0f; - border_right = 1.0f; - border_bottom = 0.0f; - border_top = 1.0f; + viewplane.left = -((float)width/(float)height); + viewplane.right = (float)width/(float)height; + viewplane.bottom = -1.0f; + viewplane.top = 1.0f; screentoworld = transform_identity(); rastertoworld = transform_identity(); @@ -93,10 +90,11 @@ void Camera::update() /* raster to screen */ Transform screentoraster = ndctoraster; - + screentoraster = ndctoraster * - transform_scale(1.0f/(right - left), 1.0f/(top - bottom), 1.0f) * - transform_translate(-left, -bottom, 0.0f); + transform_scale(1.0f/(viewplane.right - viewplane.left), + 1.0f/(viewplane.top - viewplane.bottom), 1.0f) * + transform_translate(-viewplane.left, -viewplane.bottom, 0.0f); Transform rastertoscreen = transform_inverse(screentoraster); @@ -141,7 +139,7 @@ void Camera::update() void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) { - Scene::MotionType need_motion = scene->need_motion(); + Scene::MotionType need_motion = scene->need_motion(device->info.advanced_shading); update(); @@ -160,7 +158,6 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) /* store matrices */ kcam->screentoworld = screentoworld; kcam->rastertoworld = rastertoworld; - kcam->ndctoworld = ndctoworld; kcam->rastertocamera = rastertocamera; kcam->cameratoworld = cameratoworld; kcam->worldtoscreen = transform_inverse(screentoworld); @@ -193,13 +190,14 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) } } } +#ifdef __CAMERA_MOTION__ else if(need_motion == Scene::MOTION_BLUR) { - /* todo: exact camera position will not be hit this way */ if(use_motion) { - transform_motion_decompose(&kcam->motion, &motion); + transform_motion_decompose(&kcam->motion, &motion, &matrix); kcam->have_motion = 1; } } +#endif /* depth of field */ kcam->aperturesize = aperturesize; @@ -208,7 +206,11 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) kcam->bladesrotation = bladesrotation; /* motion blur */ +#ifdef __CAMERA_MOTION__ kcam->shuttertime = (need_motion == Scene::MOTION_BLUR) ? shuttertime: 0.0f; +#else + kcam->shuttertime = 0.0f; +#endif /* type */ kcam->type = type; @@ -259,22 +261,20 @@ bool Camera::modified(const Camera& cam) // modified for progressive render // (width == cam.width) && // (height == cam.height) && - (left == cam.left) && - (right == cam.right) && - (bottom == cam.bottom) && - (top == cam.top) && - (border_left == cam.border_left) && - (border_right == cam.border_right) && - (border_bottom == cam.border_bottom) && - (border_top == cam.border_top) && + (viewplane == cam.viewplane) && + (border == cam.border) && (matrix == cam.matrix) && - (motion == cam.motion) && - (use_motion == cam.use_motion) && (panorama_type == cam.panorama_type) && (fisheye_fov == cam.fisheye_fov) && (fisheye_lens == cam.fisheye_lens)); } +bool Camera::motion_modified(const Camera& cam) +{ + return !((motion == cam.motion) && + (use_motion == cam.use_motion)); +} + void Camera::tag_update() { need_update = true; diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 82852bde5e0..4c2de7b50b8 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -21,6 +21,7 @@ #include "kernel_types.h" +#include "util_boundbox.h" #include "util_transform.h" #include "util_types.h" @@ -65,10 +66,10 @@ public: /* screen */ int width, height; - float left, right, bottom, top; + BoundBox2D viewplane; /* border */ - float border_left, border_right, border_bottom, border_top; + BoundBox2D border; /* transformation */ Transform matrix; @@ -103,6 +104,7 @@ public: void device_free(Device *device, DeviceScene *dscene); bool modified(const Camera& cam); + bool motion_modified(const Camera& cam); void tag_update(); }; diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index 62758128a73..f71675dbda3 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -229,6 +229,8 @@ void ShaderGraph::finalize(bool do_bump, bool do_osl) if(!finalized) { clean(); default_inputs(do_osl); + refine_bump_nodes(); + if(do_bump) bump_from_displacement(); @@ -324,6 +326,7 @@ void ShaderGraph::remove_proxy_nodes(vector<bool>& removed) /* transfer the default input value to the target socket */ to->set(input->value); + to->set(input->value_string); } } @@ -468,6 +471,12 @@ void ShaderGraph::default_inputs(bool do_osl) connect(geom->output("Position"), input); } + else if(input->default_value == ShaderInput::TANGENT) { + if(!geom) + geom = new GeometryNode(); + + connect(geom->output("Tangent"), input); + } } } } @@ -478,6 +487,61 @@ void ShaderGraph::default_inputs(bool do_osl) add(texco); } +void ShaderGraph::refine_bump_nodes() +{ + /* we transverse the node graph looking for bump nodes, when we find them, + * like in bump_from_displacement(), we copy the sub-graph defined from "bump" + * input to the inputs "center","dx" and "dy" What is in "bump" input is moved + * to "center" input. */ + + foreach(ShaderNode *node, nodes) { + if(node->name == ustring("bump") && node->input("Height")->link) { + ShaderInput *bump_input = node->input("Height"); + set<ShaderNode*> nodes_bump; + + /* make 2 extra copies of the subgraph defined in Bump input */ + map<ShaderNode*, ShaderNode*> nodes_dx; + map<ShaderNode*, ShaderNode*> nodes_dy; + + /* find dependencies for the given input */ + find_dependencies(nodes_bump, bump_input ); + + copy_nodes(nodes_bump, nodes_dx); + copy_nodes(nodes_bump, nodes_dy); + + /* mark nodes to indicate they are use for bump computation, so + that any texture coordinates are shifted by dx/dy when sampling */ + foreach(ShaderNode *node, nodes_bump) + node->bump = SHADER_BUMP_CENTER; + foreach(NodePair& pair, nodes_dx) + pair.second->bump = SHADER_BUMP_DX; + foreach(NodePair& pair, nodes_dy) + pair.second->bump = SHADER_BUMP_DY; + + ShaderOutput *out = bump_input->link; + ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name); + ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name); + + connect(out_dx, node->input("SampleX")); + connect(out_dy, node->input("SampleY")); + + /* add generated nodes */ + foreach(NodePair& pair, nodes_dx) + add(pair.second); + foreach(NodePair& pair, nodes_dy) + add(pair.second); + + /* connect what is conected is bump to samplecenter input*/ + connect(out , node->input("SampleCenter")); + + /* bump input is just for connectivity purpose for the graph input, + * we reconected this input to samplecenter, so lets disconnect it + * from bump input */ + disconnect(bump_input); + } + } +} + void ShaderGraph::bump_from_displacement() { /* generate bump mapping automatically from displacement. bump mapping is @@ -491,7 +555,7 @@ void ShaderGraph::bump_from_displacement() * different shifted coordinates. * * these 3 displacement values are then fed into the bump node, which will - * modify the normal. */ + * output the the perturbed normal. */ ShaderInput *displacement_in = output()->input("Displacement"); @@ -520,6 +584,12 @@ void ShaderGraph::bump_from_displacement() foreach(NodePair& pair, nodes_dy) pair.second->bump = SHADER_BUMP_DY; + /* add set normal node and connect the bump normal ouput to the set normal + * output, so it can finally set the shader normal, note we are only doing + * this for bump from displacement, this will be the only bump allowed to + * overwrite the shader normal */ + ShaderNode *set_normal = add(new SetNormalNode()); + /* add bump node and connect copied graphs to it */ ShaderNode *bump = add(new BumpNode()); @@ -531,6 +601,9 @@ void ShaderGraph::bump_from_displacement() connect(out_center, bump->input("SampleCenter")); connect(out_dx, bump->input("SampleX")); connect(out_dy, bump->input("SampleY")); + + /* connect the bump out to the set normal in: */ + connect(bump->output("Normal"), set_normal->input("Direction")); /* connect bump output to normal input nodes that aren't set yet. actually * this will only set the normal input to the geometry node that we created @@ -538,8 +611,14 @@ void ShaderGraph::bump_from_displacement() foreach(ShaderNode *node, nodes) foreach(ShaderInput *input, node->inputs) if(!input->link && input->default_value == ShaderInput::NORMAL) - connect(bump->output("Normal"), input); - + connect(set_normal->output("Normal"), input); + + /* for displacement bump, clear the normal input in case the above loop + * connected the setnormal out to the bump normalin */ + ShaderInput *bump_normal_in = bump->input("NormalIn"); + if(bump_normal_in) + bump_normal_in->link = NULL; + /* finally, add the copied nodes to the graph. we can't do this earlier * because we would create dependency cycles in the above loop */ foreach(NodePair& pair, nodes_center) diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index c3b674d0f23..373c7e0eaab 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -44,11 +44,13 @@ class OSLCompiler; enum ShaderSocketType { SHADER_SOCKET_FLOAT, + SHADER_SOCKET_INT, SHADER_SOCKET_COLOR, SHADER_SOCKET_VECTOR, SHADER_SOCKET_POINT, SHADER_SOCKET_NORMAL, - SHADER_SOCKET_CLOSURE + SHADER_SOCKET_CLOSURE, + SHADER_SOCKET_STRING }; /* Bump @@ -112,12 +114,14 @@ public: INCOMING, NORMAL, POSITION, + TANGENT, NONE }; ShaderInput(ShaderNode *parent, const char *name, ShaderSocketType type); void set(const float3& v) { value = v; } void set(float f) { value = make_float3(f, 0, 0); } + void set(const ustring v) { value_string = v; } const char *name; ShaderSocketType type; @@ -127,6 +131,7 @@ public: DefaultValue default_value; float3 value; + ustring value_string; int stack_offset; /* for SVM compiler */ bool osl_only; @@ -234,6 +239,7 @@ protected: void break_cycles(ShaderNode *node, vector<bool>& visited, vector<bool>& on_stack); void clean(); void bump_from_displacement(); + void refine_bump_nodes(); void default_inputs(bool do_osl); }; diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index 8fb229282dc..485bfc5cbf5 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -25,9 +25,10 @@ #include "util_thread.h" #include "util_vector.h" +#include "kernel_types.h" /* for TEX_NUM_FLOAT_IMAGES */ + CCL_NAMESPACE_BEGIN -#define TEX_NUM_FLOAT_IMAGES 5 #define TEX_NUM_IMAGES 95 #define TEX_IMAGE_BYTE_START TEX_NUM_FLOAT_IMAGES diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 5c1737bd60a..4173da453fd 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -68,20 +68,15 @@ static void dump_background_pixels(Device *device, DeviceScene *dscene, int res, main_task.shader_w = width*height; /* disabled splitting for now, there's an issue with multi-GPU mem_copy_from */ -#if 0 list<DeviceTask> split_tasks; main_task.split_max_size(split_tasks, 128*128); foreach(DeviceTask& task, split_tasks) { device->task_add(task); device->task_wait(); + device->mem_copy_from(d_output, task.shader_x, 1, task.shader_w, sizeof(float4)); } -#else - device->task_add(main_task); - device->task_wait(); -#endif - device->mem_copy_from(d_output, 0, 1, d_output.size(), sizeof(float4)); device->mem_free(d_input); device->mem_free(d_output); @@ -152,6 +147,10 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen Mesh *mesh = object->mesh; bool have_emission = false; + /* skip if we are not visible for BSDFs */ + if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT))) + continue; + /* skip if we have no emission shaders */ foreach(uint sindex, mesh->used_shaders) { Shader *shader = scene->shaders[sindex]; @@ -188,6 +187,10 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen Mesh *mesh = object->mesh; bool have_emission = false; + /* skip if we are not visible for BSDFs */ + if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT))) + continue; + /* skip if we have no emission shaders */ foreach(uint sindex, mesh->used_shaders) { Shader *shader = scene->shaders[sindex]; diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 7037e36f313..1958cfc10f7 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -19,6 +19,7 @@ #include "bvh.h" #include "bvh_build.h" +#include "camera.h" #include "device.h" #include "shader.h" #include "light.h" @@ -324,6 +325,7 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att og->object_name_map.clear(); og->attribute_map.clear(); + og->object_names.clear(); og->attribute_map.resize(scene->objects.size()); @@ -331,6 +333,7 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att /* set object name to object index map */ Object *object = scene->objects[i]; og->object_name_map[object->name] = i; + og->object_names.push_back(object->name); /* set object attributes */ foreach(ParamValue& attr, object->attributes) { @@ -354,6 +357,9 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att /* set object attributes */ foreach(AttributeRequest& req, attributes.requests) { + if(req.element == ATTR_ELEMENT_NONE) + continue; + OSLGlobals::Attribute osl_attr; osl_attr.elem = req.element; @@ -365,8 +371,8 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att osl_attr.type = TypeDesc::TypeColor; if(req.std != ATTR_STD_NONE) { - /* if standard attribute, add lookup by std:: name convention */ - ustring stdname(std::string("std::") + std::string(attribute_standard_name(req.std))); + /* if standard attribute, add lookup by geom: name convention */ + ustring stdname(string("geom:") + string(attribute_standard_name(req.std))); og->attribute_map[i][stdname] = osl_attr; } else if(req.name != ustring()) { @@ -722,10 +728,16 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen foreach(Shader *shader, scene->shaders) shader->need_update_attributes = false; - bool motion_blur = scene->need_motion() == Scene::MOTION_BLUR; + float shuttertime = scene->camera->shuttertime; +#ifdef __OBJECT_MOTION__ + Scene::MotionType need_motion = scene->need_motion(device->info.advanced_shading); + bool motion_blur = need_motion == Scene::MOTION_BLUR; +#else + bool motion_blur = false; +#endif foreach(Object *object, scene->objects) - object->compute_bounds(motion_blur); + object->compute_bounds(motion_blur, shuttertime); if(progress.get_cancel()) return; diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 4e16eea2774..82afab4dc1a 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -225,6 +225,8 @@ void ImageTextureNode::compile(OSLCompiler& compiler) compiler.parameter("color_space", "Linear"); else compiler.parameter("color_space", "sRGB"); + compiler.parameter("projection", projection); + compiler.parameter("projection_blend", projection_blend); compiler.add(this, "node_image_texture"); } @@ -1065,6 +1067,8 @@ ConvertNode::ConvertNode(ShaderSocketType from_, ShaderSocketType to_) if(from == SHADER_SOCKET_FLOAT) add_input("Val", SHADER_SOCKET_FLOAT); + else if(from == SHADER_SOCKET_INT) + add_input("ValInt", SHADER_SOCKET_INT); else if(from == SHADER_SOCKET_COLOR) add_input("Color", SHADER_SOCKET_COLOR); else if(from == SHADER_SOCKET_VECTOR) @@ -1078,6 +1082,8 @@ ConvertNode::ConvertNode(ShaderSocketType from_, ShaderSocketType to_) if(to == SHADER_SOCKET_FLOAT) add_output("Val", SHADER_SOCKET_FLOAT); + else if(to == SHADER_SOCKET_INT) + add_output("ValInt", SHADER_SOCKET_INT); else if(to == SHADER_SOCKET_COLOR) add_output("Color", SHADER_SOCKET_COLOR); else if(to == SHADER_SOCKET_VECTOR) @@ -1095,7 +1101,29 @@ void ConvertNode::compile(SVMCompiler& compiler) ShaderInput *in = inputs[0]; ShaderOutput *out = outputs[0]; - if(to == SHADER_SOCKET_FLOAT) { + if(from == SHADER_SOCKET_FLOAT) { + compiler.stack_assign(in); + compiler.stack_assign(out); + + if(to == SHADER_SOCKET_INT) + /* float to int */ + compiler.add_node(NODE_CONVERT, NODE_CONVERT_FI, in->stack_offset, out->stack_offset); + else + /* float to float3 */ + compiler.add_node(NODE_CONVERT, NODE_CONVERT_FV, in->stack_offset, out->stack_offset); + } + else if(from == SHADER_SOCKET_INT) { + compiler.stack_assign(in); + compiler.stack_assign(out); + + if(to == SHADER_SOCKET_FLOAT) + /* int to float */ + compiler.add_node(NODE_CONVERT, NODE_CONVERT_IF, in->stack_offset, out->stack_offset); + else + /* int to vector/point/normal */ + compiler.add_node(NODE_CONVERT, NODE_CONVERT_IV, in->stack_offset, out->stack_offset); + } + else if(to == SHADER_SOCKET_FLOAT) { compiler.stack_assign(in); compiler.stack_assign(out); @@ -1106,12 +1134,16 @@ void ConvertNode::compile(SVMCompiler& compiler) /* vector/point/normal to float */ compiler.add_node(NODE_CONVERT, NODE_CONVERT_VF, in->stack_offset, out->stack_offset); } - else if(from == SHADER_SOCKET_FLOAT) { + else if(to == SHADER_SOCKET_INT) { compiler.stack_assign(in); compiler.stack_assign(out); - /* float to float3 */ - compiler.add_node(NODE_CONVERT, NODE_CONVERT_FV, in->stack_offset, out->stack_offset); + if(from == SHADER_SOCKET_COLOR) + /* color to int */ + compiler.add_node(NODE_CONVERT, NODE_CONVERT_CI, in->stack_offset, out->stack_offset); + else + /* vector/point/normal to int */ + compiler.add_node(NODE_CONVERT, NODE_CONVERT_VI, in->stack_offset, out->stack_offset); } else { /* float3 to float3 */ @@ -1134,6 +1166,8 @@ void ConvertNode::compile(OSLCompiler& compiler) { if(from == SHADER_SOCKET_FLOAT) compiler.add(this, "node_convert_from_float"); + else if(from == SHADER_SOCKET_INT) + compiler.add(this, "node_convert_from_int"); else if(from == SHADER_SOCKET_COLOR) compiler.add(this, "node_convert_from_color"); else if(from == SHADER_SOCKET_VECTOR) @@ -1175,14 +1209,16 @@ BsdfNode::BsdfNode() closure = ccl::CLOSURE_BSDF_DIFFUSE_ID; add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f)); - add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); + add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL); add_output("BSDF", SHADER_SOCKET_CLOSURE); } -void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2) +void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3) { ShaderInput *color_in = input("Color"); + ShaderInput *normal_in = input("Normal"); + ShaderInput *tangent_in = input("Tangent"); if(color_in->link) { compiler.stack_assign(color_in); @@ -1195,6 +1231,14 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput * compiler.stack_assign(param1); if(param2) compiler.stack_assign(param2); + if(param3) + compiler.stack_assign(param3); + + if(normal_in->link) + compiler.stack_assign(normal_in); + + if(tangent_in && tangent_in->link) + compiler.stack_assign(tangent_in); compiler.add_node(NODE_CLOSURE_BSDF, compiler.encode_uchar4(closure, @@ -1203,6 +1247,14 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput * compiler.closure_mix_weight_offset()), __float_as_int((param1)? param1->value.x: 0.0f), __float_as_int((param2)? param2->value.x: 0.0f)); + + if(tangent_in) { + compiler.add_node(NODE_CLOSURE_BSDF, normal_in->stack_offset, tangent_in->stack_offset, + (param3)? param3->stack_offset: SVM_STACK_INVALID); + } + else { + compiler.add_node(NODE_CLOSURE_BSDF, normal_in->stack_offset); + } } void BsdfNode::compile(SVMCompiler& compiler) @@ -1221,13 +1273,26 @@ WardBsdfNode::WardBsdfNode() { closure = CLOSURE_BSDF_WARD_ID; - add_input("Roughness U", SHADER_SOCKET_FLOAT, 0.2f); - add_input("Roughness V", SHADER_SOCKET_FLOAT, 0.2f); + add_input("Tangent", SHADER_SOCKET_VECTOR, ShaderInput::TANGENT); + + add_input("Roughness", SHADER_SOCKET_FLOAT, 0.2f); + add_input("Anisotropy", SHADER_SOCKET_FLOAT, 0.5f); + add_input("Rotation", SHADER_SOCKET_FLOAT, 0.0f); +} + +void WardBsdfNode::attributes(AttributeRequestSet *attributes) +{ + ShaderInput *tangent_in = input("Tangent"); + + if(!tangent_in->link) + attributes->add(ATTR_STD_GENERATED); + + ShaderNode::attributes(attributes); } void WardBsdfNode::compile(SVMCompiler& compiler) { - BsdfNode::compile(compiler, input("Roughness U"), input("Roughness V")); + BsdfNode::compile(compiler, input("Roughness"), input("Anisotropy"), input("Rotation")); } void WardBsdfNode::compile(OSLCompiler& compiler) @@ -1279,9 +1344,9 @@ static ShaderEnum glass_distribution_init() { ShaderEnum enm; - enm.insert("Sharp", CLOSURE_BSDF_REFRACTION_ID); - enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID); - enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID); + enm.insert("Sharp", CLOSURE_BSDF_SHARP_GLASS_ID); + enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID); + enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID); return enm; } @@ -1300,7 +1365,7 @@ void GlassBsdfNode::compile(SVMCompiler& compiler) { closure = (ClosureType)distribution_enum[distribution]; - if(closure == CLOSURE_BSDF_REFRACTION_ID) + if(closure == CLOSURE_BSDF_SHARP_GLASS_ID) BsdfNode::compile(compiler, NULL, input("IOR")); else BsdfNode::compile(compiler, input("Roughness"), input("IOR")); @@ -1312,6 +1377,45 @@ void GlassBsdfNode::compile(OSLCompiler& compiler) compiler.add(this, "node_glass_bsdf"); } +/* Refraction BSDF Closure */ + +static ShaderEnum refraction_distribution_init() +{ + ShaderEnum enm; + + enm.insert("Sharp", CLOSURE_BSDF_REFRACTION_ID); + enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID); + enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID); + + return enm; +} + +ShaderEnum RefractionBsdfNode::distribution_enum = refraction_distribution_init(); + +RefractionBsdfNode::RefractionBsdfNode() +{ + distribution = ustring("Sharp"); + + add_input("Roughness", SHADER_SOCKET_FLOAT, 0.0f); + add_input("IOR", SHADER_SOCKET_FLOAT, 0.3f); +} + +void RefractionBsdfNode::compile(SVMCompiler& compiler) +{ + closure = (ClosureType)distribution_enum[distribution]; + + if(closure == CLOSURE_BSDF_REFRACTION_ID) + BsdfNode::compile(compiler, NULL, input("IOR")); + else + BsdfNode::compile(compiler, input("Roughness"), input("IOR")); +} + +void RefractionBsdfNode::compile(OSLCompiler& compiler) +{ + compiler.parameter("distribution", distribution); + compiler.add(this, "node_refraction_bsdf"); +} + /* Velvet BSDF Closure */ VelvetBsdfNode::VelvetBsdfNode() @@ -1469,6 +1573,34 @@ void HoldoutNode::compile(OSLCompiler& compiler) compiler.add(this, "node_holdout"); } +/* Ambient Occlusion */ + +AmbientOcclusionNode::AmbientOcclusionNode() +: ShaderNode("ambient_occlusion") +{ + add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f)); + add_output("AO", SHADER_SOCKET_CLOSURE); +} + +void AmbientOcclusionNode::compile(SVMCompiler& compiler) +{ + ShaderInput *color_in = input("Color"); + + if(color_in->link) { + compiler.stack_assign(color_in); + compiler.add_node(NODE_CLOSURE_WEIGHT, color_in->stack_offset); + } + else + compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value); + + compiler.add_node(NODE_CLOSURE_AMBIENT_OCCLUSION, compiler.closure_mix_weight_offset()); +} + +void AmbientOcclusionNode::compile(OSLCompiler& compiler) +{ + compiler.add(this, "node_ambient_occlusion"); +} + /* Volume Closure */ VolumeNode::VolumeNode() @@ -1566,6 +1698,14 @@ GeometryNode::GeometryNode() add_output("Backfacing", SHADER_SOCKET_FLOAT); } +void GeometryNode::attributes(AttributeRequestSet *attributes) +{ + if(!output("Tangent")->links.empty()) + attributes->add(ATTR_STD_GENERATED); + + ShaderNode::attributes(attributes); +} + void GeometryNode::compile(SVMCompiler& compiler) { ShaderOutput *out; @@ -1636,7 +1776,7 @@ void GeometryNode::compile(OSLCompiler& compiler) TextureCoordinateNode::TextureCoordinateNode() : ShaderNode("texture_coordinate") { - add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); + add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); add_output("Generated", SHADER_SOCKET_POINT); add_output("Normal", SHADER_SOCKET_NORMAL); add_output("UV", SHADER_SOCKET_POINT); @@ -1758,6 +1898,8 @@ void TextureCoordinateNode::compile(OSLCompiler& compiler) if(compiler.background) compiler.parameter("is_background", true); + + compiler.parameter("from_dupli", from_dupli); compiler.add(this, "node_texture_coordinate"); } @@ -1996,13 +2138,14 @@ void ParticleInfoNode::compile(SVMCompiler& compiler) compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LOCATION, out->stack_offset); } - #if 0 /* XXX Quaternion data is not yet supported by Cycles */ + /* quaternion data is not yet supported by Cycles */ +#if 0 out = output("Rotation"); if(!out->links.empty()) { compiler.stack_assign(out); compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_ROTATION, out->stack_offset); } - #endif +#endif out = output("Size"); if(!out->links.empty()) { @@ -2184,7 +2327,7 @@ static ShaderEnum mix_type_init() enm.insert("Burn", NODE_MIX_BURN); enm.insert("Hue", NODE_MIX_HUE); enm.insert("Saturation", NODE_MIX_SAT); - enm.insert("Value", NODE_MIX_VAL ); + enm.insert("Value", NODE_MIX_VAL); enm.insert("Color", NODE_MIX_COLOR); enm.insert("Soft Light", NODE_MIX_SOFT); enm.insert("Linear Light", NODE_MIX_LINEAR); @@ -2544,7 +2687,7 @@ void LayerWeightNode::compile(SVMCompiler& compiler) void LayerWeightNode::compile(OSLCompiler& compiler) { - compiler.add(this, "node_blend_weight"); + compiler.add(this, "node_layer_weight"); } /* Output */ @@ -2555,6 +2698,7 @@ OutputNode::OutputNode() add_input("Surface", SHADER_SOCKET_CLOSURE); add_input("Volume", SHADER_SOCKET_CLOSURE); add_input("Displacement", SHADER_SOCKET_FLOAT); + add_input("Normal", SHADER_SOCKET_NORMAL); } void OutputNode::compile(SVMCompiler& compiler) @@ -2702,9 +2846,15 @@ void VectorMathNode::compile(OSLCompiler& compiler) BumpNode::BumpNode() : ShaderNode("bump") { + /* this input is used by the user, but after graph transform it is no longer + * used and moved to sampler center/x/y instead */ + add_input("Height", SHADER_SOCKET_FLOAT); + add_input("SampleCenter", SHADER_SOCKET_FLOAT); add_input("SampleX", SHADER_SOCKET_FLOAT); add_input("SampleY", SHADER_SOCKET_FLOAT); + add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL); + add_input("Strength", SHADER_SOCKET_FLOAT, 0.1f); add_output("Normal", SHADER_SOCKET_NORMAL); } @@ -2714,12 +2864,25 @@ void BumpNode::compile(SVMCompiler& compiler) ShaderInput *center_in = input("SampleCenter"); ShaderInput *dx_in = input("SampleX"); ShaderInput *dy_in = input("SampleY"); + ShaderInput *normal_in = input("NormalIn"); + ShaderInput *intensity_in = input("Strength"); + ShaderOutput *normal_out = output("Normal"); compiler.stack_assign(center_in); compiler.stack_assign(dx_in); compiler.stack_assign(dy_in); + compiler.stack_assign(intensity_in); + compiler.stack_assign(normal_out); - compiler.add_node(NODE_SET_BUMP, center_in->stack_offset, dx_in->stack_offset, dy_in->stack_offset); + if(normal_in->link) + compiler.stack_assign(normal_in); + + /* pack all parameters in the node */ + compiler.add_node(NODE_SET_BUMP, + normal_in->stack_offset, + compiler.encode_uchar4(center_in->stack_offset, dx_in->stack_offset, + dy_in->stack_offset, intensity_in->stack_offset), + normal_out->stack_offset); } void BumpNode::compile(OSLCompiler& compiler) @@ -2788,17 +2951,245 @@ void RGBRampNode::compile(OSLCompiler& compiler) /* NB: cycles float3 type is actually 4 floats! need to use an explicit array */ float ramp_color[RAMP_TABLE_SIZE][3]; float ramp_alpha[RAMP_TABLE_SIZE]; + for (int i = 0; i < RAMP_TABLE_SIZE; ++i) { ramp_color[i][0] = ramp[i].x; ramp_color[i][1] = ramp[i].y; ramp_color[i][2] = ramp[i].z; ramp_alpha[i] = ramp[i].w; } + compiler.parameter_color_array("ramp_color", ramp_color, RAMP_TABLE_SIZE); compiler.parameter_array("ramp_alpha", ramp_alpha, RAMP_TABLE_SIZE); compiler.add(this, "node_rgb_ramp"); } +/* Set Normal Node */ + +SetNormalNode::SetNormalNode() +: ShaderNode("set_normal") +{ + add_input("Direction", SHADER_SOCKET_VECTOR); + add_output("Normal", SHADER_SOCKET_NORMAL); +} + +void SetNormalNode::compile(SVMCompiler& compiler) +{ + ShaderInput *direction_in = input("Direction"); + ShaderOutput *normal_out = output("Normal"); + + compiler.stack_assign(direction_in); + compiler.stack_assign(normal_out); + + compiler.add_node(NODE_CLOSURE_SET_NORMAL, direction_in->stack_offset, normal_out->stack_offset); +} + +void SetNormalNode::compile(OSLCompiler& compiler) +{ + compiler.add(this, "node_set_normal"); +} + +/* OSLScriptNode */ + +OSLScriptNode::OSLScriptNode() +: ShaderNode("osl_script") +{ +} + +void OSLScriptNode::compile(SVMCompiler& compiler) +{ + /* doesn't work for SVM, obviously ... */ +} + +void OSLScriptNode::compile(OSLCompiler& compiler) +{ + if(!filepath.empty()) + compiler.add(this, filepath.c_str(), true); + else + compiler.add(this, bytecode_hash.c_str(), false); +} + +/* Normal Map */ + +static ShaderEnum normal_map_space_init() +{ + ShaderEnum enm; + + enm.insert("Tangent", NODE_NORMAL_MAP_TANGENT); + enm.insert("Object", NODE_NORMAL_MAP_OBJECT); + enm.insert("World", NODE_NORMAL_MAP_WORLD); + + return enm; +} + +ShaderEnum NormalMapNode::space_enum = normal_map_space_init(); + +NormalMapNode::NormalMapNode() +: ShaderNode("normal_map") +{ + space = ustring("Tangent"); + attribute = ustring(""); + + add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); + add_input("Strength", SHADER_SOCKET_FLOAT, 1.0f); + add_input("Color", SHADER_SOCKET_COLOR); + + add_output("Normal", SHADER_SOCKET_NORMAL); +} + +void NormalMapNode::attributes(AttributeRequestSet *attributes) +{ + if(space == ustring("Tangent")) { + if(attribute == ustring("")) { + attributes->add(ATTR_STD_UV_TANGENT); + attributes->add(ATTR_STD_UV_TANGENT_SIGN); + } + else { + attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str())); + attributes->add(ustring((string(attribute.c_str()) + ".tangent_sign").c_str())); + } + } + + ShaderNode::attributes(attributes); +} + +void NormalMapNode::compile(SVMCompiler& compiler) +{ + ShaderInput *color_in = input("Color"); + ShaderInput *strength_in = input("Strength"); + ShaderOutput *normal_out = output("Normal"); + int attr = 0, attr_sign = 0; + + if(space == ustring("Tangent")) { + if(attribute == ustring("")) { + attr = compiler.attribute(ATTR_STD_UV_TANGENT); + attr_sign = compiler.attribute(ATTR_STD_UV_TANGENT_SIGN); + } + else { + attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str())); + attr_sign = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent_sign").c_str())); + } + } + + compiler.stack_assign(color_in); + compiler.stack_assign(strength_in); + compiler.stack_assign(normal_out); + + compiler.add_node(NODE_NORMAL_MAP, + compiler.encode_uchar4( + color_in->stack_offset, + strength_in->stack_offset, + normal_out->stack_offset, + space_enum[space]), + attr, attr_sign); +} + +void NormalMapNode::compile(OSLCompiler& compiler) +{ + if(space == ustring("Tangent")) { + if(attribute == ustring("")) { + compiler.parameter("attr_name", ustring("geom:tangent")); + compiler.parameter("attr_sign_name", ustring("geom:tangent_sign")); + } + else { + compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str())); + compiler.parameter("attr_sign_name", ustring((string(attribute.c_str()) + ".tangent_sign").c_str())); + } + } + + compiler.parameter("space", space); + + compiler.add(this, "node_normal_map"); +} + +/* Tangent */ + +static ShaderEnum tangent_direction_type_init() +{ + ShaderEnum enm; + + enm.insert("Radial", NODE_TANGENT_RADIAL); + enm.insert("UV Map", NODE_TANGENT_UVMAP); + + return enm; +} + +static ShaderEnum tangent_axis_init() +{ + ShaderEnum enm; + + enm.insert("X", NODE_TANGENT_AXIS_X); + enm.insert("Y", NODE_TANGENT_AXIS_Y); + enm.insert("Z", NODE_TANGENT_AXIS_Z); + + return enm; +} + +ShaderEnum TangentNode::direction_type_enum = tangent_direction_type_init(); +ShaderEnum TangentNode::axis_enum = tangent_axis_init(); + +TangentNode::TangentNode() +: ShaderNode("normal_map") +{ + direction_type = ustring("Radial"); + axis = ustring("X"); + attribute = ustring(""); + + add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); + add_output("Tangent", SHADER_SOCKET_NORMAL); +} + +void TangentNode::attributes(AttributeRequestSet *attributes) +{ + if(direction_type == ustring("UV Map")) { + if(attribute == ustring("")) + attributes->add(ATTR_STD_UV_TANGENT); + else + attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str())); + } + else + attributes->add(ATTR_STD_GENERATED); + + ShaderNode::attributes(attributes); +} + +void TangentNode::compile(SVMCompiler& compiler) +{ + ShaderOutput *tangent_out = output("Tangent"); + int attr; + + if(direction_type == ustring("UV Map")) { + if(attribute == ustring("")) + attr = compiler.attribute(ATTR_STD_UV_TANGENT); + else + attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str())); + } + else + attr = compiler.attribute(ATTR_STD_GENERATED); + + compiler.stack_assign(tangent_out); + + compiler.add_node(NODE_TANGENT, + compiler.encode_uchar4( + tangent_out->stack_offset, + direction_type_enum[direction_type], + axis_enum[axis]), attr); +} + +void TangentNode::compile(OSLCompiler& compiler) +{ + if(direction_type == ustring("UV Map")) { + if(attribute == ustring("")) + compiler.parameter("attr_name", ustring("geom:tangent")); + else + compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str())); + } + + compiler.parameter("direction_type", direction_type); + compiler.parameter("axis", axis); + compiler.add(this, "node_tangent"); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index e8e584dd8ef..27b07769e28 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -193,7 +193,7 @@ class BsdfNode : public ShaderNode { public: SHADER_NODE_CLASS(BsdfNode) - void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2); + void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3 = NULL); ClosureType closure; }; @@ -201,6 +201,7 @@ public: class WardBsdfNode : public BsdfNode { public: SHADER_NODE_CLASS(WardBsdfNode) + void attributes(AttributeRequestSet *attributes); }; class DiffuseBsdfNode : public BsdfNode { @@ -239,6 +240,14 @@ public: static ShaderEnum distribution_enum; }; +class RefractionBsdfNode : public BsdfNode { +public: + SHADER_NODE_CLASS(RefractionBsdfNode) + + ustring distribution; + static ShaderEnum distribution_enum; +}; + class EmissionNode : public ShaderNode { public: SHADER_NODE_CLASS(EmissionNode) @@ -256,6 +265,11 @@ public: SHADER_NODE_CLASS(HoldoutNode) }; +class AmbientOcclusionNode : public ShaderNode { +public: + SHADER_NODE_CLASS(AmbientOcclusionNode) +}; + class VolumeNode : public ShaderNode { public: SHADER_NODE_CLASS(VolumeNode) @@ -278,6 +292,7 @@ public: class GeometryNode : public ShaderNode { public: SHADER_NODE_CLASS(GeometryNode) + void attributes(AttributeRequestSet *attributes); }; class TextureCoordinateNode : public ShaderNode { @@ -438,6 +453,48 @@ public: float4 ramp[RAMP_TABLE_SIZE]; }; +class SetNormalNode : public ShaderNode { +public: + SHADER_NODE_CLASS(SetNormalNode) +}; + +class OSLScriptNode : public ShaderNode { +public: + SHADER_NODE_CLASS(OSLScriptNode) + string filepath; + string bytecode_hash; + + /* ShaderInput/ShaderOutput only stores a shallow string copy (const char *)! + * The actual socket names have to be stored externally to avoid memory errors. */ + vector<ustring> input_names; + vector<ustring> output_names; +}; + +class NormalMapNode : public ShaderNode { +public: + SHADER_NODE_CLASS(NormalMapNode) + void attributes(AttributeRequestSet *attributes); + + ustring space; + static ShaderEnum space_enum; + + ustring attribute; +}; + +class TangentNode : public ShaderNode { +public: + SHADER_NODE_CLASS(TangentNode) + void attributes(AttributeRequestSet *attributes); + + ustring direction_type; + static ShaderEnum direction_type_enum; + + ustring axis; + static ShaderEnum axis_enum; + + ustring attribute; +}; + CCL_NAMESPACE_END #endif /* __NODES_H__ */ diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index d78a82d589a..25b4d1f08cc 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -51,20 +51,23 @@ Object::~Object() { } -void Object::compute_bounds(bool motion_blur) +void Object::compute_bounds(bool motion_blur, float shuttertime) { BoundBox mbounds = mesh->bounds; if(motion_blur && use_motion) { MotionTransform decomp; - transform_motion_decompose(&decomp, &motion); + transform_motion_decompose(&decomp, &motion, &tfm); bounds = BoundBox::empty; /* todo: this is really terrible. according to pbrt there is a better * way to find this iteratively, but did not find implementation yet * or try to implement myself */ - for(float t = 0.0f; t < 1.0f; t += 1.0f/128.0f) { + float start_t = 0.5f - shuttertime*0.25f; + float end_t = 0.5f + shuttertime*0.25f; + + for(float t = start_t; t < end_t; t += (1.0f/128.0f)*shuttertime) { Transform ttfm; transform_motion_interpolate(&ttfm, &decomp, t); @@ -109,7 +112,7 @@ void Object::apply_transform() if(bounds.valid()) { mesh->compute_bounds(); - compute_bounds(false); + compute_bounds(false, 0.0f); } /* tfm is not reset to identity, all code that uses it needs to check the @@ -151,7 +154,8 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene uint *object_flag = dscene->object_flag.resize(scene->objects.size()); int i = 0; map<Mesh*, float> surface_area_map; - Scene::MotionType need_motion = scene->need_motion(); + Scene::MotionType need_motion = scene->need_motion(device->info.advanced_shading); + bool have_motion = false; foreach(Object *ob, scene->objects) { Mesh *mesh = ob->mesh; @@ -218,26 +222,29 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene mtfm_post = mtfm_post * itfm; memcpy(&objects[offset+8], &mtfm_pre, sizeof(float4)*4); - memcpy(&objects[offset+12], &mtfm_post, sizeof(float4)*4); + memcpy(&objects[offset+16], &mtfm_post, sizeof(float4)*4); } +#ifdef __OBJECT_MOTION__ else if(need_motion == Scene::MOTION_BLUR) { if(ob->use_motion) { /* decompose transformations for interpolation */ MotionTransform decomp; - transform_motion_decompose(&decomp, &ob->motion); - memcpy(&objects[offset+8], &decomp, sizeof(float4)*8); + transform_motion_decompose(&decomp, &ob->motion, &ob->tfm); + memcpy(&objects[offset+8], &decomp, sizeof(float4)*12); flag |= SD_OBJECT_MOTION; + have_motion = true; } else { float4 no_motion = make_float4(FLT_MAX); - memcpy(&objects[offset+8], &no_motion, sizeof(float4)); + memcpy(&objects[offset+8], &no_motion, sizeof(float4)*12); } } +#endif /* dupli object coords */ - objects[offset+16] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], 0.0f); - objects[offset+17] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], 0.0f, 0.0f); + objects[offset+20] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], 0.0f); + objects[offset+21] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], 0.0f, 0.0f); /* object flag */ if(ob->use_holdout) @@ -251,6 +258,8 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene device->tex_alloc("__objects", dscene->objects); device->tex_alloc("__object_flag", dscene->object_flag); + + dscene->data.bvh.have_motion = have_motion; } void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) @@ -297,7 +306,12 @@ void ObjectManager::apply_static_transforms(Scene *scene, Progress& progress) /* counter mesh users */ map<Mesh*, int> mesh_users; - bool motion_blur = scene->need_motion() == Scene::MOTION_BLUR; +#ifdef __OBJECT_MOTION__ + Scene::MotionType need_motion = scene->need_motion(); + bool motion_blur = need_motion == Scene::MOTION_BLUR; +#else + bool motion_blur = false; +#endif foreach(Object *object, scene->objects) { map<Mesh*, int>::iterator it = mesh_users.find(object->mesh); diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index e2c3ad4e071..922c886d961 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -59,7 +59,7 @@ public: void tag_update(Scene *scene); - void compute_bounds(bool motion_blur); + void compute_bounds(bool motion_blur, float shuttertime); void apply_transform(); }; diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index 6d23097d7a8..5fbc7932849 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -31,6 +31,7 @@ #include "osl_shader.h" #include "util_foreach.h" +#include "util_md5.h" #include "util_path.h" #include "util_progress.h" @@ -44,22 +45,12 @@ CCL_NAMESPACE_BEGIN OSLShaderManager::OSLShaderManager() { - services = new OSLRenderServices(); - - /* if we let OSL create it, it leaks */ - ts = TextureSystem::create(true); - ts->attribute("automip", 1); - ts->attribute("autotile", 64); + thread_data_initialized = false; - ss = OSL::ShadingSystem::create(services, ts, &errhandler); - ss->attribute("lockgeom", 1); - ss->attribute("commonspace", "world"); - ss->attribute("optimize", 2); - //ss->attribute("debug", 1); - //ss->attribute("statistics:level", 1); - ss->attribute("searchpath:shader", path_get("shader").c_str()); + services = new OSLRenderServices(); - OSLShader::register_closures(ss); + shading_system_init(); + texture_system_init(); } OSLShaderManager::~OSLShaderManager() @@ -71,18 +62,14 @@ OSLShaderManager::~OSLShaderManager() void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) { - /* test if we need to update */ - bool need_update = false; - - foreach(Shader *shader, scene->shaders) - if(shader->need_update) - need_update = true; - if(!need_update) return; device_free(device, dscene); + /* determine which shaders are in use */ + device_update_shaders_used(scene); + /* create shaders */ OSLGlobals *og = (OSLGlobals*)device->osl_memory(); @@ -94,7 +81,7 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene if(shader->sample_as_light && shader->has_surface_emission) scene->light_manager->need_update = true; - OSLCompiler compiler((void*)ss); + OSLCompiler compiler((void*)this, (void*)ss); compiler.background = (shader == scene->shaders[scene->default_background]); compiler.compile(og, shader); } @@ -106,15 +93,20 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene og->background_state = og->surface_state[background_id & SHADER_MASK]; og->use = true; - tls_create(OSLGlobals::ThreadData, og->thread_data); - foreach(Shader *shader, scene->shaders) shader->need_update = false; + + need_update = false; /* set texture system */ scene->image_manager->set_osl_texture_system((void*)ts); device_update_common(device, dscene, scene, progress); + + if(!thread_data_initialized) { + og->thread_data_init(); + thread_data_initialized = true; + } } void OSLShaderManager::device_free(Device *device, DeviceScene *dscene) @@ -127,18 +119,176 @@ void OSLShaderManager::device_free(Device *device, DeviceScene *dscene) og->use = false; og->ss = NULL; - tls_delete(OSLGlobals::ThreadData, og->thread_data); - og->surface_state.clear(); og->volume_state.clear(); og->displacement_state.clear(); og->background_state.reset(); + + if(thread_data_initialized) { + og->thread_data_free(); + thread_data_initialized = false; + } +} + +void OSLShaderManager::texture_system_init() +{ + /* if we let OSL create it, it leaks */ + ts = TextureSystem::create(true); + ts->attribute("automip", 1); + ts->attribute("autotile", 64); + + /* effectively unlimited for now, until we support proper mipmap lookups */ + ts->attribute("max_memory_MB", 16384); +} + +void OSLShaderManager::shading_system_init() +{ + ss = OSL::ShadingSystem::create(services, ts, &errhandler); + ss->attribute("lockgeom", 1); + ss->attribute("commonspace", "world"); + ss->attribute("optimize", 2); + //ss->attribute("debug", 1); + //ss->attribute("statistics:level", 1); + ss->attribute("searchpath:shader", path_get("shader")); + + /* our own ray types */ + static const char *raytypes[] = { + "camera", /* PATH_RAY_CAMERA */ + "reflection", /* PATH_RAY_REFLECT */ + "refraction", /* PATH_RAY_TRANSMIT */ + "diffuse", /* PATH_RAY_DIFFUSE */ + "glossy", /* PATH_RAY_GLOSSY */ + "singular", /* PATH_RAY_SINGULAR */ + "transparent", /* PATH_RAY_TRANSPARENT */ + "shadow", /* PATH_RAY_SHADOW_OPAQUE */ + "shadow", /* PATH_RAY_SHADOW_TRANSPARENT */ + }; + + const int nraytypes = sizeof(raytypes)/sizeof(raytypes[0]); + ss->attribute("raytypes", TypeDesc(TypeDesc::STRING, nraytypes), raytypes); + + OSLShader::register_closures(ss); + + loaded_shaders.clear(); +} + +bool OSLShaderManager::osl_compile(const string& inputfile, const string& outputfile) +{ + vector<string> options; + string stdosl_path; + + /* specify output file name */ + options.push_back("-o"); + options.push_back(outputfile); + + /* specify standard include path */ + options.push_back("-I" + path_get("shader")); + stdosl_path = path_get("shader/stdosl.h"); + + /* compile */ + OSL::OSLCompiler *compiler = OSL::OSLCompiler::create(); + bool ok = compiler->compile(inputfile, options, stdosl_path); + delete compiler; + + return ok; +} + +bool OSLShaderManager::osl_query(OSL::OSLQuery& query, const string& filepath) +{ + string searchpath = path_user_get("shaders"); + return query.open(filepath, searchpath); +} + +static string shader_filepath_hash(const string& filepath, uint64_t modified_time) +{ + /* compute a hash from filepath and modified time to detect changes */ + MD5Hash md5; + md5.append((const uint8_t*)filepath.c_str(), filepath.size()); + md5.append((const uint8_t*)&modified_time, sizeof(modified_time)); + + return md5.get_hex(); +} + +const char *OSLShaderManager::shader_test_loaded(const string& hash) +{ + set<string>::iterator it = loaded_shaders.find(hash); + return (it == loaded_shaders.end())? NULL: it->c_str(); +} + +const char *OSLShaderManager::shader_load_filepath(string filepath) +{ + size_t len = filepath.size(); + string extension = filepath.substr(len - 4); + uint64_t modified_time = path_modified_time(filepath); + + if(extension == ".osl") { + /* .OSL File */ + string osopath = filepath.substr(0, len - 4) + ".oso"; + uint64_t oso_modified_time = path_modified_time(osopath); + + /* test if we have loaded the corresponding .OSO already */ + if(oso_modified_time != 0) { + const char *hash = shader_test_loaded(shader_filepath_hash(osopath, oso_modified_time)); + + if(hash) + return hash; + } + + /* autocompile .OSL to .OSO if needed */ + if(oso_modified_time == 0 || (oso_modified_time < modified_time)) { + OSLShaderManager::osl_compile(filepath, osopath); + modified_time = path_modified_time(osopath); + } + else + modified_time = oso_modified_time; + + filepath = osopath; + } + else { + if(extension == ".oso") { + /* .OSO File, nothing to do */ + } + else if(path_dirname(filepath) == "") { + /* .OSO File in search path */ + filepath = path_join(path_user_get("shaders"), filepath + ".oso"); + } + else { + /* unknown file */ + return NULL; + } + + /* test if we have loaded this .OSO already */ + const char *hash = shader_test_loaded(shader_filepath_hash(filepath, modified_time)); + + if(hash) + return hash; + } + + /* read oso bytecode from file */ + string bytecode_hash = shader_filepath_hash(filepath, modified_time); + string bytecode; + + if(!path_read_text(filepath, bytecode)) { + fprintf(stderr, "Cycles shader graph: failed to read file %s\n", filepath.c_str()); + loaded_shaders.insert(bytecode_hash); /* to avoid repeat tries */ + return NULL; + } + + return shader_load_bytecode(bytecode_hash, bytecode); +} + +const char *OSLShaderManager::shader_load_bytecode(const string& hash, const string& bytecode) +{ + ss->LoadMemoryShader(hash.c_str(), bytecode.c_str()); + + return loaded_shaders.insert(hash).first->c_str(); } /* Graph Compiler */ -OSLCompiler::OSLCompiler(void *shadingsys_) +OSLCompiler::OSLCompiler(void *manager_, void *shadingsys_) { + manager = manager_; shadingsys = shadingsys_; current_type = SHADER_TYPE_SURFACE; current_shader = NULL; @@ -206,6 +356,12 @@ bool OSLCompiler::node_skip_input(ShaderNode *node, ShaderInput *input) return true; if(strcmp(input->name, "Displacement") == 0 && current_type != SHADER_TYPE_DISPLACEMENT) return true; + if(strcmp(input->name, "Normal") == 0) + return true; + } + else if(node->name == ustring("bump")) { + if(strcmp(input->name, "Height") == 0) + return true; } else if(current_type == SHADER_TYPE_DISPLACEMENT && input->link && input->link->parent->name == ustring("bump")) return true; @@ -213,10 +369,18 @@ bool OSLCompiler::node_skip_input(ShaderNode *node, ShaderInput *input) return false; } -void OSLCompiler::add(ShaderNode *node, const char *name) +void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath) { OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; + /* load filepath */ + if(isfilepath) { + name = ((OSLShaderManager*)manager)->shader_load_filepath(name); + + if(name == NULL) + return; + } + /* pass in fixed parameter values */ foreach(ShaderInput *input, node->inputs) { if(!input->link) { @@ -244,6 +408,12 @@ void OSLCompiler::add(ShaderNode *node, const char *name) case SHADER_SOCKET_FLOAT: parameter(param_name.c_str(), input->value.x); break; + case SHADER_SOCKET_INT: + parameter(param_name.c_str(), (int)input->value.x); + break; + case SHADER_SOCKET_STRING: + parameter(param_name.c_str(), input->value_string); + break; case SHADER_SOCKET_CLOSURE: break; } @@ -482,82 +652,85 @@ void OSLCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty void OSLCompiler::compile(OSLGlobals *og, Shader *shader) { - OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; - ShaderGraph *graph = shader->graph; - ShaderNode *output = (graph)? graph->output(): NULL; + if(shader->need_update) { + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; + ShaderGraph *graph = shader->graph; + ShaderNode *output = (graph)? graph->output(): NULL; - /* copy graph for shader with bump mapping */ - if(output->input("Surface")->link && output->input("Displacement")->link) - if(!shader->graph_bump) - shader->graph_bump = shader->graph->copy(); + /* copy graph for shader with bump mapping */ + if(output->input("Surface")->link && output->input("Displacement")->link) + if(!shader->graph_bump) + shader->graph_bump = shader->graph->copy(); - /* finalize */ - shader->graph->finalize(false, true); - if(shader->graph_bump) - shader->graph_bump->finalize(true, true); + /* finalize */ + shader->graph->finalize(false, true); + if(shader->graph_bump) + shader->graph_bump->finalize(true, true); - current_shader = shader; + current_shader = shader; - shader->has_surface = false; - shader->has_surface_emission = false; - shader->has_surface_transparent = false; - shader->has_volume = false; - shader->has_displacement = false; + shader->has_surface = false; + shader->has_surface_emission = false; + shader->has_surface_transparent = false; + shader->has_volume = false; + shader->has_displacement = false; - /* generate surface shader */ - if(graph && output->input("Surface")->link) { - compile_type(shader, shader->graph, SHADER_TYPE_SURFACE); - og->surface_state.push_back(ss->state()); + /* generate surface shader */ + if(shader->used && graph && output->input("Surface")->link) { + compile_type(shader, shader->graph, SHADER_TYPE_SURFACE); + shader->osl_surface_ref = ss->state(); - if(shader->graph_bump) { + if(shader->graph_bump) { + ss->clear_state(); + compile_type(shader, shader->graph_bump, SHADER_TYPE_SURFACE); + } + + shader->osl_surface_bump_ref = ss->state(); ss->clear_state(); - compile_type(shader, shader->graph_bump, SHADER_TYPE_SURFACE); - og->surface_state.push_back(ss->state()); - } - else - og->surface_state.push_back(ss->state()); - ss->clear_state(); + shader->has_surface = true; + } + else { + shader->osl_surface_ref = OSL::ShadingAttribStateRef(); + shader->osl_surface_bump_ref = OSL::ShadingAttribStateRef(); + } - shader->has_surface = true; - } - else { - og->surface_state.push_back(OSL::ShadingAttribStateRef()); - og->surface_state.push_back(OSL::ShadingAttribStateRef()); - } + /* generate volume shader */ + if(shader->used && graph && output->input("Volume")->link) { + compile_type(shader, shader->graph, SHADER_TYPE_VOLUME); + shader->has_volume = true; - /* generate volume shader */ - if(graph && output->input("Volume")->link) { - compile_type(shader, shader->graph, SHADER_TYPE_VOLUME); - shader->has_volume = true; + shader->osl_volume_ref = ss->state(); + ss->clear_state(); + } + else + shader->osl_volume_ref = OSL::ShadingAttribStateRef(); - og->volume_state.push_back(ss->state()); - og->volume_state.push_back(ss->state()); - ss->clear_state(); - } - else { - og->volume_state.push_back(OSL::ShadingAttribStateRef()); - og->volume_state.push_back(OSL::ShadingAttribStateRef()); + /* generate displacement shader */ + if(shader->used && graph && output->input("Displacement")->link) { + compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT); + shader->has_displacement = true; + shader->osl_displacement_ref = ss->state(); + ss->clear_state(); + } + else + shader->osl_displacement_ref = OSL::ShadingAttribStateRef(); } - /* generate displacement shader */ - if(graph && output->input("Displacement")->link) { - compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT); - shader->has_displacement = true; + /* push state to array for lookup */ + og->surface_state.push_back(shader->osl_surface_ref); + og->surface_state.push_back(shader->osl_surface_bump_ref); - og->displacement_state.push_back(ss->state()); - og->displacement_state.push_back(ss->state()); - ss->clear_state(); - } - else { - og->displacement_state.push_back(OSL::ShadingAttribStateRef()); - og->displacement_state.push_back(OSL::ShadingAttribStateRef()); - } + og->volume_state.push_back(shader->osl_volume_ref); + og->volume_state.push_back(shader->osl_volume_ref); + + og->displacement_state.push_back(shader->osl_displacement_ref); + og->displacement_state.push_back(shader->osl_displacement_ref); } #else -void OSLCompiler::add(ShaderNode *node, const char *name) +void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath) { } diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h index 90107a34a98..b4b3f59e02a 100644 --- a/intern/cycles/render/osl.h +++ b/intern/cycles/render/osl.h @@ -20,11 +20,14 @@ #define __OSL_H__ #include "util_set.h" +#include "util_string.h" #include "shader.h" #ifdef WITH_OSL +#include <OSL/oslcomp.h> #include <OSL/oslexec.h> +#include <OSL/oslquery.h> #endif CCL_NAMESPACE_BEGIN @@ -52,11 +55,26 @@ public: void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); void device_free(Device *device, DeviceScene *dscene); -private: + /* osl compile and query */ + static bool osl_compile(const string& inputfile, const string& outputfile); + static bool osl_query(OSL::OSLQuery& query, const string& filepath); + + /* shader file loading, all functions return pointer to hash string if found */ + const char *shader_test_loaded(const string& hash); + const char *shader_load_bytecode(const string& hash, const string& bytecode); + const char *shader_load_filepath(string filepath); + +protected: + void texture_system_init(); + void shading_system_init(); + OSL::ShadingSystem *ss; OSL::TextureSystem *ts; OSLRenderServices *services; OSL::ErrorHandler errhandler; + set<string> loaded_shaders; + + bool thread_data_initialized; }; #endif @@ -65,10 +83,10 @@ private: class OSLCompiler { public: - OSLCompiler(void *shadingsys); + OSLCompiler(void *manager, void *shadingsys); void compile(OSLGlobals *og, Shader *shader); - void add(ShaderNode *node, const char *name); + void add(ShaderNode *node, const char *name, bool isfilepath = false); void parameter(const char *name, float f); void parameter_color(const char *name, float3 f); @@ -104,6 +122,7 @@ private: void generate_nodes(const set<ShaderNode*>& nodes); void *shadingsys; + void *manager; ShaderType current_type; Shader *current_shader; }; diff --git a/intern/cycles/render/particles.cpp b/intern/cycles/render/particles.cpp index 9f951d9673f..2a1570f7a0d 100644 --- a/intern/cycles/render/particles.cpp +++ b/intern/cycles/render/particles.cpp @@ -57,8 +57,7 @@ void ParticleSystemManager::device_update_particles(Device *device, DeviceScene { /* count particles. * adds one dummy particle at the beginning to avoid invalid lookups, - * in case a shader uses particle info without actual particle data. - */ + * in case a shader uses particle info without actual particle data. */ int num_particles = 1; foreach(ParticleSystem *psys, scene->particle_systems) num_particles += psys->particles.size(); diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index 071338d49c2..7834aa701ea 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -44,6 +44,10 @@ Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_) device = NULL; memset(&dscene.data, 0, sizeof(dscene.data)); + /* OSL only works on the CPU */ + if(device_info_.type != DEVICE_CPU) + params.shadingsystem = SceneParams::SVM; + camera = new Camera(); filter = new Filter(); film = new Film(); @@ -62,33 +66,11 @@ Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_) Scene::~Scene() { - if(device) camera->device_free(device, &dscene); - delete camera; - - if(device) filter->device_free(device, &dscene); - delete filter; - - if(device) film->device_free(device, &dscene); - delete film; - - if(device) background->device_free(device, &dscene); - delete background; - - if(device) mesh_manager->device_free(device, &dscene); - delete mesh_manager; - - if(device) object_manager->device_free(device, &dscene); - delete object_manager; - - if(device) integrator->device_free(device, &dscene); - delete integrator; - - if(device) shader_manager->device_free(device, &dscene); - delete shader_manager; - - if(device) light_manager->device_free(device, &dscene); - delete light_manager; + free_memory(true); +} +void Scene::free_memory(bool final) +{ foreach(Shader *s, shaders) delete s; foreach(Mesh *m, meshes) @@ -100,11 +82,44 @@ Scene::~Scene() foreach(ParticleSystem *p, particle_systems) delete p; - if(device) image_manager->device_free(device, &dscene); - delete image_manager; - - if(device) particle_system_manager->device_free(device, &dscene); - delete particle_system_manager; + if(device) { + camera->device_free(device, &dscene); + filter->device_free(device, &dscene); + film->device_free(device, &dscene); + background->device_free(device, &dscene); + integrator->device_free(device, &dscene); + + object_manager->device_free(device, &dscene); + mesh_manager->device_free(device, &dscene); + shader_manager->device_free(device, &dscene); + light_manager->device_free(device, &dscene); + + particle_system_manager->device_free(device, &dscene); + + if(!params.persistent_images || final) + image_manager->device_free(device, &dscene); + } + + if(final) { + delete filter; + delete camera; + delete film; + delete background; + delete integrator; + delete object_manager; + delete mesh_manager; + delete shader_manager; + delete light_manager; + delete particle_system_manager; + delete image_manager; + } + else { + shaders.clear(); + meshes.clear(); + objects.clear(); + lights.clear(); + particle_systems.clear(); + } } void Scene::device_update(Device *device_, Progress& progress) @@ -183,10 +198,10 @@ void Scene::device_update(Device *device_, Progress& progress) device->const_copy_to("__data", &dscene.data, sizeof(dscene.data)); } -Scene::MotionType Scene::need_motion() +Scene::MotionType Scene::need_motion(bool advanced_shading) { if(integrator->motion_blur) - return MOTION_BLUR; + return (advanced_shading)? MOTION_BLUR: MOTION_NONE; else if(Pass::contains(film->passes, PASS_MOTION)) return MOTION_PASS; else @@ -229,5 +244,22 @@ bool Scene::need_reset() || particle_system_manager->need_update); } +void Scene::reset() +{ + shader_manager->add_default(this); + + /* ensure all objects are updated */ + camera->tag_update(); + filter->tag_update(this); + film->tag_update(this); + background->tag_update(this); + integrator->tag_update(this); +} + +void Scene::device_free() +{ + free_memory(false); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 09087fb2970..92ef692b4b9 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -120,6 +120,7 @@ public: bool use_bvh_cache; bool use_bvh_spatial_split; bool use_qbvh; + bool persistent_images; SceneParams() { @@ -139,7 +140,8 @@ public: && bvh_type == params.bvh_type && use_bvh_cache == params.use_bvh_cache && use_bvh_spatial_split == params.use_bvh_spatial_split - && use_qbvh == params.use_qbvh); } + && use_qbvh == params.use_qbvh + && persistent_images == params.persistent_images); } }; /* Scene */ @@ -194,10 +196,16 @@ public: void need_global_attributes(AttributeRequestSet& attributes); enum MotionType { MOTION_NONE = 0, MOTION_PASS, MOTION_BLUR }; - MotionType need_motion(); + MotionType need_motion(bool advanced_shading = true); bool need_update(); bool need_reset(); + + void reset(); + void device_free(); + +protected: + void free_memory(bool final); }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index cd410e4e011..41212c2db84 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -34,16 +34,22 @@ CCL_NAMESPACE_BEGIN +/* Note about preserve_tile_device option for tile manager: + * progressive refine and viewport rendering does requires tiles to + * always be allocated for the same device + */ Session::Session(const SessionParams& params_) : params(params_), tile_manager(params.progressive, params.samples, params.tile_size, params.start_resolution, - (params.background)? 1: max(params.device.multi_devices.size(), 1)) + params.background == false || params.progressive_refine, params.background, + max(params.device.multi_devices.size(), 1)), + stats() { device_use_gl = ((params.device.type != DEVICE_CPU) && !params.background); TaskScheduler::init(params.threads); - device = Device::create(params.device, params.background, params.threads); + device = Device::create(params.device, stats, params.background); if(params.background) { buffers = NULL; @@ -96,6 +102,9 @@ Session::~Session() display->write(device, params.output_path); } + foreach(RenderBuffers *buffers, tile_buffers) + delete buffers; + delete buffers; delete display; delete scene; @@ -173,9 +182,12 @@ bool Session::draw_gpu(BufferParams& buffer_params) void Session::run_gpu() { + bool tiles_written = false; + start_time = time_dt(); reset_time = time_dt(); paused_time = 0.0; + last_update_time = time_dt(); if(!params.background) progress.set_start_time(start_time + paused_time); @@ -267,10 +279,15 @@ void Session::run_gpu() if(device->error_message() != "") progress.set_cancel(device->error_message()); + tiles_written = update_progressive_refine(progress.get_cancel()); + if(progress.get_cancel()) break; } } + + if(!tiles_written) + update_progressive_refine(true); } /* CPU Session */ @@ -313,14 +330,18 @@ bool Session::draw_cpu(BufferParams& buffer_params) bool Session::acquire_tile(Device *tile_device, RenderTile& rtile) { - if(progress.get_cancel()) - return false; + if(progress.get_cancel()) { + if(params.progressive_refine == false) { + /* for progressive refine current sample should be finished for all tiles */ + return false; + } + } thread_scoped_lock tile_lock(tile_mutex); /* get next tile from manager */ Tile tile; - int device_num = (params.background)? 0: device->device_number(tile_device); + int device_num = device->device_number(tile_device); if(!tile_manager.next_tile(tile, device_num)) return false; @@ -338,7 +359,7 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile) /* in case of a permant buffer, return it, otherwise we will allocate * a new temporary buffer */ - if(!write_render_tile_cb) { + if(!params.background) { tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride); rtile.buffer = buffers->buffer.device_pointer; @@ -360,9 +381,30 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile) buffer_params.get_offset_stride(rtile.offset, rtile.stride); - /* allocate buffers */ RenderBuffers *tilebuffers = new RenderBuffers(tile_device); - tilebuffers->reset(tile_device, buffer_params); + + /* allocate buffers */ + if(params.progressive_refine) { + tile_lock.lock(); + + if(tile_buffers.size() == 0) + tile_buffers.resize(tile_manager.state.num_tiles, NULL); + + tilebuffers = tile_buffers[tile.index]; + if(tilebuffers == NULL) { + tilebuffers = new RenderBuffers(tile_device); + tile_buffers[tile.index] = tilebuffers; + + tilebuffers->reset(tile_device, buffer_params); + } + + tile_lock.unlock(); + } + else { + tilebuffers = new RenderBuffers(tile_device); + + tilebuffers->reset(tile_device, buffer_params); + } rtile.buffer = tilebuffers->buffer.device_pointer; rtile.rng_state = tilebuffers->rng_state.device_pointer; @@ -377,9 +419,11 @@ void Session::update_tile_sample(RenderTile& rtile) thread_scoped_lock tile_lock(tile_mutex); if(update_render_tile_cb) { - /* todo: optimize this by making it thread safe and removing lock */ + if(params.progressive_refine == false) { + /* todo: optimize this by making it thread safe and removing lock */ - update_render_tile_cb(rtile); + update_render_tile_cb(rtile); + } } update_status_time(); @@ -390,10 +434,12 @@ void Session::release_tile(RenderTile& rtile) thread_scoped_lock tile_lock(tile_mutex); if(write_render_tile_cb) { - /* todo: optimize this by making it thread safe and removing lock */ - write_render_tile_cb(rtile); + if(params.progressive_refine == false) { + /* todo: optimize this by making it thread safe and removing lock */ + write_render_tile_cb(rtile); - delete rtile.buffers; + delete rtile.buffers; + } } update_status_time(); @@ -401,6 +447,10 @@ void Session::release_tile(RenderTile& rtile) void Session::run_cpu() { + bool tiles_written = false; + + last_update_time = time_dt(); + { /* reset once to start */ thread_scoped_lock reset_lock(delayed_reset.mutex); @@ -502,10 +552,15 @@ void Session::run_cpu() if(device->error_message() != "") progress.set_cancel(device->error_message()); + + tiles_written = update_progressive_refine(progress.get_cancel()); } progress.set_update(); } + + if(!tiles_written) + update_progressive_refine(true); } void Session::run() @@ -657,10 +712,13 @@ void Session::update_status_time(bool show_pause, bool show_done) string status, substatus; if(!params.progressive) { + bool is_gpu = params.device.type == DEVICE_CUDA || params.device.type == DEVICE_OPENCL; + bool is_multidevice = params.device.multi_devices.size() > 1; + bool is_cpu = params.device.type == DEVICE_CPU; + substatus = string_printf("Path Tracing Tile %d/%d", tile, num_tiles); - if(params.device.type == DEVICE_CUDA || params.device.type == DEVICE_OPENCL || - (params.device.type == DEVICE_CPU && num_tiles == 1)) { + if((is_gpu && !is_multidevice) || (is_cpu && num_tiles == 1)) { /* when rendering on GPU multithreading happens within single tile, as in * tiles are handling sequentially and in this case we could display * currently rendering sample number @@ -722,6 +780,7 @@ void Session::path_trace() task.get_cancel = function_bind(&Progress::get_cancel, &this->progress); task.update_tile_sample = function_bind(&Session::update_tile_sample, this, _1); task.update_progress_sample = function_bind(&Session::update_progress_sample, this); + task.need_finish_queue = params.progressive_refine; device->task_add(task); } @@ -752,5 +811,49 @@ void Session::tonemap() display_outdated = false; } -CCL_NAMESPACE_END +bool Session::update_progressive_refine(bool cancel) +{ + int sample = tile_manager.state.sample + 1; + bool write = sample == params.samples || cancel; + double current_time = time_dt(); + + if (current_time - last_update_time < 1.0) { + /* if last sample was processed, we need to write buffers anyway */ + if (!write) + return false; + } + + if(params.progressive_refine) { + foreach(RenderBuffers *buffers, tile_buffers) { + RenderTile rtile; + rtile.buffers = buffers; + rtile.sample = sample; + + if(write) + write_render_tile_cb(rtile); + else + update_render_tile_cb(rtile); + } + } + + last_update_time = current_time; + + return write; +} + +void Session::device_free() +{ + scene->device_free(); + + foreach(RenderBuffers *buffers, tile_buffers) + delete buffers; + + tile_buffers.clear(); + + /* used from background render only, so no need to + * re-create render/display buffers here + */ +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index eda8b3da60e..cfc1502287d 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -24,7 +24,9 @@ #include "tile.h" #include "util_progress.h" +#include "util_stats.h" #include "util_thread.h" +#include "util_vector.h" CCL_NAMESPACE_BEGIN @@ -42,6 +44,7 @@ class SessionParams { public: DeviceInfo device; bool background; + bool progressive_refine; string output_path; bool progressive; @@ -55,9 +58,12 @@ public: double reset_timeout; double text_timeout; + enum { OSL, SVM } shadingsystem; + SessionParams() { background = false; + progressive_refine = false; output_path = ""; progressive = false; @@ -70,12 +76,15 @@ public: cancel_timeout = 0.1; reset_timeout = 0.1; text_timeout = 1.0; + + shadingsystem = SVM; } bool modified(const SessionParams& params) { return !(device.type == params.device.type && device.id == params.device.id && background == params.background + && progressive_refine == params.progressive_refine && output_path == params.output_path /* && samples == params.samples */ && progressive == params.progressive @@ -85,7 +94,8 @@ public: && threads == params.threads && cancel_timeout == params.cancel_timeout && reset_timeout == params.reset_timeout - && text_timeout == params.text_timeout); } + && text_timeout == params.text_timeout + && shadingsystem == params.shadingsystem); } }; @@ -103,6 +113,7 @@ public: Progress progress; SessionParams params; TileManager tile_manager; + Stats stats; boost::function<void(RenderTile&)> write_render_tile_cb; boost::function<void(RenderTile&)> update_render_tile_cb; @@ -119,6 +130,7 @@ public: void set_samples(int samples); void set_pause(bool pause); + void device_free(); protected: struct DelayedReset { thread_mutex mutex; @@ -173,6 +185,12 @@ protected: double reset_time; double preview_time; double paused_time; + + /* progressive refine */ + double last_update_time; + bool update_progressive_refine(bool cancel); + + vector<RenderBuffers *> tile_buffers; }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index fae1d6bd81c..17f7fbd43d6 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -49,6 +49,8 @@ Shader::Shader() has_volume = false; has_displacement = false; + used = false; + need_update = true; need_update_attributes = true; } @@ -98,6 +100,16 @@ void Shader::tag_update(Scene *scene) } } +void Shader::tag_used(Scene *scene) +{ + /* if an unused shader suddenly gets used somewhere, it needs to be + * recompiled because it was skipped for compilation before */ + if(!used) { + need_update = true; + scene->shader_manager->need_update = true; + } +} + /* Shader Manager */ ShaderManager::ShaderManager() @@ -161,6 +173,27 @@ int ShaderManager::get_shader_id(uint shader, Mesh *mesh, bool smooth) return id; } +void ShaderManager::device_update_shaders_used(Scene *scene) +{ + /* figure out which shaders are in use, so SVM/OSL can skip compiling them + * for speed and avoid loading image textures into memory */ + foreach(Shader *shader, scene->shaders) + shader->used = false; + + scene->shaders[scene->default_surface]->used = true; + scene->shaders[scene->default_light]->used = true; + scene->shaders[scene->default_background]->used = true; + scene->shaders[scene->default_holdout]->used = true; + scene->shaders[scene->default_empty]->used = true; + + foreach(Mesh *mesh, scene->meshes) + foreach(uint shader, mesh->used_shaders) + scene->shaders[shader]->used = true; + + foreach(Light *light, scene->lights) + scene->shaders[light->shader]->used = true; +} + void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) { device_free_common(device, dscene); diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index 02788008060..373b3356f51 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -27,6 +27,10 @@ #include "util_string.h" #include "util_types.h" +#ifdef WITH_OSL +#include <OSL/oslexec.h> +#endif + CCL_NAMESPACE_BEGIN class Device; @@ -75,11 +79,23 @@ public: /* requested mesh attributes */ AttributeRequestSet attributes; + /* determined before compiling */ + bool used; + +#ifdef WITH_OSL + /* osl shading state references */ + OSL::ShadingAttribStateRef osl_surface_ref; + OSL::ShadingAttribStateRef osl_surface_bump_ref; + OSL::ShadingAttribStateRef osl_volume_ref; + OSL::ShadingAttribStateRef osl_displacement_ref; +#endif + Shader(); ~Shader(); void set_graph(ShaderGraph *graph); void tag_update(Scene *scene); + void tag_used(Scene *scene); }; /* Shader Manager virtual base class @@ -98,6 +114,7 @@ public: virtual void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) = 0; virtual void device_free(Device *device, DeviceScene *dscene) = 0; + void device_update_shaders_used(Scene *scene); void device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); void device_free_common(Device *device, DeviceScene *dscene); diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index da287a10199..dc249984499 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -48,6 +48,9 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene /* test if we need to update */ device_free(device, dscene); + /* determine which shaders are in use */ + device_update_shaders_used(scene); + /* svm_nodes */ vector<int4> svm_nodes; size_t i; @@ -119,6 +122,8 @@ int SVMCompiler::stack_size(ShaderSocketType type) { if(type == SHADER_SOCKET_FLOAT) return 1; + else if(type == SHADER_SOCKET_INT) + return 1; else if(type == SHADER_SOCKET_COLOR) return 3; else if(type == SHADER_SOCKET_VECTOR) @@ -212,10 +217,13 @@ void SVMCompiler::stack_assign(ShaderInput *input) if(input->type == SHADER_SOCKET_FLOAT) { add_node(NODE_VALUE_F, __float_as_int(input->value.x), input->stack_offset); } + else if(input->type == SHADER_SOCKET_INT) { + add_node(NODE_VALUE_F, (int)input->value.x, input->stack_offset); + } else if(input->type == SHADER_SOCKET_VECTOR || - input->type == SHADER_SOCKET_NORMAL || - input->type == SHADER_SOCKET_POINT || - input->type == SHADER_SOCKET_COLOR) { + input->type == SHADER_SOCKET_NORMAL || + input->type == SHADER_SOCKET_POINT || + input->type == SHADER_SOCKET_COLOR) { add_node(NODE_VALUE_V, input->stack_offset); add_node(NODE_VALUE_V, input->value); @@ -274,17 +282,6 @@ void SVMCompiler::stack_clear_users(ShaderNode *node, set<ShaderNode*>& done) foreach(ShaderInput *in, output->links) in->stack_offset = SVM_STACK_INVALID; - - /* unmark any nodes that have no more valid outputs, see [#31806] */ - if(done.find(output->parent) != done.end()) { - all_done = true; - foreach(ShaderOutput *pout, output->parent->outputs) - if(pout->stack_offset != SVM_STACK_INVALID) - all_done = false; - - if(all_done) - done.erase(output->parent); - } } } } @@ -615,36 +612,38 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty output->stack_offset = SVM_STACK_INVALID; } - if(clin->link) { - bool generate = false; - if(type == SHADER_TYPE_SURFACE) { - /* generate surface shader */ - generate = true; - shader->has_surface = true; - } - else if(type == SHADER_TYPE_VOLUME) { - /* generate volume shader */ - generate = true; - shader->has_volume = true; - } - else if(type == SHADER_TYPE_DISPLACEMENT) { - /* generate displacement shader */ - generate = true; - shader->has_displacement = true; - } + if(shader->used) { + if(clin->link) { + bool generate = false; + if(type == SHADER_TYPE_SURFACE) { + /* generate surface shader */ + generate = true; + shader->has_surface = true; + } + else if(type == SHADER_TYPE_VOLUME) { + /* generate volume shader */ + generate = true; + shader->has_volume = true; + } + else if(type == SHADER_TYPE_DISPLACEMENT) { + /* generate displacement shader */ + generate = true; + shader->has_displacement = true; + } - if(generate) { - set<ShaderNode*> done; + if(generate) { + set<ShaderNode*> done; - if(use_multi_closure) - generate_multi_closure(clin->link->parent, done, SVM_STACK_INVALID); - else - generate_closure(clin->link->parent, done); + if(use_multi_closure) + generate_multi_closure(clin->link->parent, done, SVM_STACK_INVALID); + else + generate_closure(clin->link->parent, done); + } } - } - /* compile output node */ - node->compile(*this); + /* compile output node */ + node->compile(*this); + } add_node(NODE_END, 0, 0, 0); } diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp index 874f1a6b3aa..bbcdb47260e 100644 --- a/intern/cycles/render/tile.cpp +++ b/intern/cycles/render/tile.cpp @@ -23,12 +23,15 @@ CCL_NAMESPACE_BEGIN -TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int start_resolution_, int num_devices_) +TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int start_resolution_, + bool preserve_tile_device_, bool background_, int num_devices_) { progressive = progressive_; tile_size = tile_size_; start_resolution = start_resolution_; num_devices = num_devices_; + preserve_tile_device = preserve_tile_device_; + background = background_; BufferParams buffer_params; reset(buffer_params, 0); @@ -70,7 +73,45 @@ void TileManager::set_samples(int num_samples_) num_samples = num_samples_; } -void TileManager::set_tiles() +/* splits image into tiles and assigns equal amount of tiles to every render device */ +void TileManager::gen_tiles_global() +{ + int resolution = state.resolution_divider; + int image_w = max(1, params.width/resolution); + int image_h = max(1, params.height/resolution); + + state.tiles.clear(); + + int tile_w = (tile_size.x >= image_w)? 1: (image_w + tile_size.x - 1)/tile_size.x; + int tile_h = (tile_size.y >= image_h)? 1: (image_h + tile_size.y - 1)/tile_size.y; + + int num_logical_devices = preserve_tile_device? num_devices: 1; + int num = min(image_h, num_logical_devices); + int tile_index = 0; + + int tiles_per_device = (tile_w * tile_h + num - 1) / num; + int cur_device = 0, cur_tiles = 0; + + for(int tile_y = 0; tile_y < tile_h; tile_y++) { + for(int tile_x = 0; tile_x < tile_w; tile_x++, tile_index++) { + int x = tile_x * tile_size.x; + int y = tile_y * tile_size.y; + int w = (tile_x == tile_w-1)? image_w - x: tile_size.x; + int h = (tile_y == tile_h-1)? image_h - y: tile_size.y; + + state.tiles.push_back(Tile(tile_index, x, y, w, h, cur_device)); + cur_tiles++; + + if(cur_tiles == tiles_per_device) { + cur_tiles = 0; + cur_device++; + } + } + } +} + +/* slices image into as much pieces as how many devices are rendering this image */ +void TileManager::gen_tiles_sliced() { int resolution = state.resolution_divider; int image_w = max(1, params.width/resolution); @@ -78,7 +119,9 @@ void TileManager::set_tiles() state.tiles.clear(); - int num = min(image_h, num_devices); + int num_logical_devices = preserve_tile_device? num_devices: 1; + int num = min(image_h, num_logical_devices); + int tile_index = 0; for(int device = 0; device < num; device++) { int device_y = (image_h/num)*device; @@ -86,20 +129,30 @@ void TileManager::set_tiles() int tile_w = (tile_size.x >= image_w)? 1: (image_w + tile_size.x - 1)/tile_size.x; int tile_h = (tile_size.y >= device_h)? 1: (device_h + tile_size.y - 1)/tile_size.y; - int sub_w = (image_w + tile_w - 1)/tile_w; - int sub_h = (device_h + tile_h - 1)/tile_h; for(int tile_y = 0; tile_y < tile_h; tile_y++) { - for(int tile_x = 0; tile_x < tile_w; tile_x++) { - int x = tile_x * sub_w; - int y = tile_y * sub_h; - int w = (tile_x == tile_w-1)? image_w - x: sub_w; - int h = (tile_y == tile_h-1)? device_h - y: sub_h; + for(int tile_x = 0; tile_x < tile_w; tile_x++, tile_index++) { + int x = tile_x * tile_size.x; + int y = tile_y * tile_size.y; + int w = (tile_x == tile_w-1)? image_w - x: tile_size.x; + int h = (tile_y == tile_h-1)? device_h - y: tile_size.y; - state.tiles.push_back(Tile(x, y + device_y, w, h, device)); + state.tiles.push_back(Tile(tile_index, x, y + device_y, w, h, device)); } } } +} + +void TileManager::set_tiles() +{ + int resolution = state.resolution_divider; + int image_w = max(1, params.width/resolution); + int image_h = max(1, params.height/resolution); + + if(background) + gen_tiles_global(); + else + gen_tiles_sliced(); state.num_tiles = state.tiles.size(); @@ -120,13 +173,10 @@ list<Tile>::iterator TileManager::next_center_tile(int device) int image_w = max(1, params.width/resolution); int image_h = max(1, params.height/resolution); - int num = min(image_h, num_devices); - - int device_y = (image_h / num) * device; - int device_h = (device == num - 1) ? image_h - device * (image_h / num) : image_h / num; + int logical_device = preserve_tile_device? device: 0; - int64_t centx = image_w / 2, centy = device_y + device_h / 2, tot = 1; - int64_t mindist = (int64_t) image_w * (int64_t) device_h; + int64_t centx = image_w / 2, centy = image_h / 2, tot = 1; + int64_t mindist = (int64_t) image_w * (int64_t) image_h; /* find center of rendering tiles, image center counts for 1 too */ for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) { @@ -143,7 +193,7 @@ list<Tile>::iterator TileManager::next_center_tile(int device) /* closest of the non-rendering tiles */ for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) { - if(iter->device == device && iter->rendering == false) { + if(iter->device == logical_device && iter->rendering == false) { Tile &cur_tile = *iter; int64_t distx = centx - (cur_tile.x + cur_tile.w / 2); @@ -160,11 +210,28 @@ list<Tile>::iterator TileManager::next_center_tile(int device) return best; } +list<Tile>::iterator TileManager::next_simple_tile(int device) +{ + list<Tile>::iterator iter; + + int logical_device = preserve_tile_device? device: 0; + + for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) { + if(iter->device == logical_device && iter->rendering == false) + return iter; + } + + return state.tiles.end(); +} + bool TileManager::next_tile(Tile& tile, int device) { list<Tile>::iterator tile_it; - tile_it = next_center_tile(device); + if(background) + tile_it = next_center_tile(device); + else + tile_it = next_simple_tile(device); if(tile_it != state.tiles.end()) { tile_it->rendering = true; diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h index d820f74e3bd..6f7a8f20734 100644 --- a/intern/cycles/render/tile.h +++ b/intern/cycles/render/tile.h @@ -30,6 +30,7 @@ CCL_NAMESPACE_BEGIN class Tile { public: + int index; int x, y, w, h; int device; bool rendering; @@ -37,8 +38,8 @@ public: Tile() {} - Tile(int x_, int y_, int w_, int h_, int device_) - : x(x_), y(y_), w(w_), h(h_), device(device_), rendering(false) {} + Tile(int index_, int x_, int y_, int w_, int h_, int device_) + : index(index_), x(x_), y(y_), w(w_), h(h_), device(device_), rendering(false) {} }; /* Tile Manager */ @@ -57,7 +58,8 @@ public: list<Tile> tiles; } state; - TileManager(bool progressive, int num_samples, int2 tile_size, int start_resolution, int num_devices = 1); + TileManager(bool progressive, int num_samples, int2 tile_size, int start_resolution, + bool preserve_tile_device, bool background, int num_devices = 1); ~TileManager(); void reset(BufferParams& params, int num_samples); @@ -75,7 +77,38 @@ protected: int start_resolution; int num_devices; - list<Tile>::iterator next_center_tile(int device = 0); + /* in some cases it is important that the same tile will be returned for the same + * device it was originally generated for (i.e. viewport rendering when buffer is + * allocating once for tile and then always used by it) + * + * in other cases any tile could be handled by any device (i.e. final rendering + * without progressive refine) + */ + bool preserve_tile_device; + + /* for background render tiles should exactly match render parts generated from + * blender side, which means image first gets split into tiles and then tiles are + * assigning to render devices + * + * however viewport rendering expects tiles to be allocated in a special way, + * meaning image is being sliced horizontally first and every device handles + * it's own slice + */ + bool background; + + /* splits image into tiles and assigns equal amount of tiles to every render device */ + void gen_tiles_global(); + + /* slices image into as much pieces as how many devices are rendering this image */ + void gen_tiles_sliced(); + + /* returns closest tile to center of rendered tiles + * mimics behavior of blender internal's tile order + */ + list<Tile>::iterator next_center_tile(int device); + + /* returns first unhandled tile starting from left bottom corner of the image */ + list<Tile>::iterator next_simple_tile(int device); }; CCL_NAMESPACE_END diff --git a/intern/cycles/subd/CMakeLists.txt b/intern/cycles/subd/CMakeLists.txt index c0986e9c173..838776d60bf 100644 --- a/intern/cycles/subd/CMakeLists.txt +++ b/intern/cycles/subd/CMakeLists.txt @@ -6,7 +6,9 @@ set(INC ../kernel/svm ../render ) + set(INC_SYS + ) set(SRC diff --git a/intern/cycles/subd/subd_build.cpp b/intern/cycles/subd/subd_build.cpp index 312980f1fa2..8e84da7f019 100644 --- a/intern/cycles/subd/subd_build.cpp +++ b/intern/cycles/subd/subd_build.cpp @@ -333,7 +333,7 @@ void SubdAccBuilder::computeEdgeStencil(SubdFaceRing *ring, GregoryAccStencil *s /* @@ this probably does not provide watertight results!! (1/3 + 1/3 + 1/3 != 1) */ /* distribute weight to all verts */ - stencil->get(eid1, vert) += beta * costerm1_b / 3.0f; + stencil->get(eid1, vert) += beta * costerm1_b / 3.0f; stencil->get(eid1, edge->to()) += beta * costerm1_b / 3.0f; stencil->get(eid1, edge->next->to()) += beta * costerm1_b / 3.0f; diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt index 6349870f4a2..4e6ecdeb5d6 100644 --- a/intern/cycles/util/CMakeLists.txt +++ b/intern/cycles/util/CMakeLists.txt @@ -2,6 +2,7 @@ set(INC . ) + set(INC_SYS ${GLEW_INCLUDE_PATH} ${OPENGL_INCLUDE_DIR} diff --git a/intern/cycles/util/util_attribute.cpp b/intern/cycles/util/util_attribute.cpp index 3a1c2b6f332..057fb6213e9 100644 --- a/intern/cycles/util/util_attribute.cpp +++ b/intern/cycles/util/util_attribute.cpp @@ -30,6 +30,10 @@ const char *attribute_standard_name(AttributeStandard std) return "uv"; else if(std == ATTR_STD_GENERATED) return "generated"; + else if(std == ATTR_STD_UV_TANGENT) + return "tangent"; + else if(std == ATTR_STD_UV_TANGENT_SIGN) + return "tangent_sign"; else if(std == ATTR_STD_POSITION_UNDEFORMED) return "undeformed"; else if(std == ATTR_STD_POSITION_UNDISPLACED) diff --git a/intern/cycles/util/util_boundbox.h b/intern/cycles/util/util_boundbox.h index b35c4c12bb8..a0cdf1761ad 100644 --- a/intern/cycles/util/util_boundbox.h +++ b/intern/cycles/util/util_boundbox.h @@ -31,6 +31,8 @@ using namespace std; CCL_NAMESPACE_BEGIN +/* 3D BoundBox */ + class BoundBox { public: @@ -160,6 +162,75 @@ __forceinline BoundBox intersect(const BoundBox& a, const BoundBox& b, const Bou return intersect(a, intersect(b, c)); } +/* 2D BoundBox */ + +class BoundBox2D { +public: + float left; + float right; + float bottom; + float top; + + BoundBox2D() + : left(0.0f), right(1.0f), bottom(0.0f), top(1.0f) + { + } + + bool operator==(const BoundBox2D& other) const + { + return (left == other.left && right == other.right && + bottom == other.bottom && top == other.top); + } + + BoundBox2D operator*(float f) const + { + BoundBox2D result; + + result.left = left*f; + result.right = right*f; + result.bottom = bottom*f; + result.top = top*f; + + return result; + } + + BoundBox2D subset(const BoundBox2D& other) const + { + BoundBox2D subset; + + subset.left = left + other.left*(right - left); + subset.right = left + other.right*(right - left); + subset.bottom = bottom + other.bottom*(top - bottom); + subset.top = bottom + other.top*(top - bottom); + + return subset; + } + + BoundBox2D make_relative_to(const BoundBox2D& other) const + { + BoundBox2D result; + + result.left = ((left - other.left) / (other.right - other.left)); + result.right = ((right - other.left) / (other.right - other.left)); + result.bottom = ((bottom - other.bottom) / (other.top - other.bottom)); + result.top = ((top - other.bottom) / (other.top - other.bottom)); + + return result; + } + + BoundBox2D clamp(float mn = 0.0f, float mx = 1.0f) + { + BoundBox2D result; + + result.left = ccl::clamp(left, mn, mx); + result.right = ccl::clamp(right, mn, mx); + result.bottom = ccl::clamp(bottom, mn, mx); + result.top = ccl::clamp(top, mn, mx); + + return result; + } +}; + CCL_NAMESPACE_END #endif /* __UTIL_BOUNDBOX_H__ */ diff --git a/intern/cycles/util/util_cuda.cpp b/intern/cycles/util/util_cuda.cpp index 2960022fd8d..2716f00e173 100644 --- a/intern/cycles/util/util_cuda.cpp +++ b/intern/cycles/util/util_cuda.cpp @@ -17,6 +17,7 @@ */ #include <stdlib.h> +#include <stdio.h> #include "util_cuda.h" #include "util_debug.h" @@ -413,8 +414,18 @@ string cuCompilerPath() return nvcc; #ifndef _WIN32 - if(system("which nvcc") == 0) - return "nvcc"; + { + FILE *handle = popen("which nvcc", "r"); + if(handle) { + char buffer[4096] = {0}; + int len = fread(buffer, 1, sizeof(buffer) - 1, handle); + buffer[len] = '\0'; + pclose(handle); + + if(buffer[0]) + return "nvcc"; + } + } #endif return ""; diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index 0b6f020ade5..70adee4385b 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -1069,6 +1069,29 @@ __device_inline float3 safe_divide_color(float3 a, float3 b) return make_float3(x, y, z); } +/* Rotation of point around axis and angle */ + +__device_inline float3 rotate_around_axis(float3 p, float3 axis, float angle) +{ + float costheta = cosf(angle); + float sintheta = sinf(angle); + float3 r; + + r.x = ((costheta + (1 - costheta) * axis.x * axis.x) * p.x) + + (((1 - costheta) * axis.x * axis.y - axis.z * sintheta) * p.y) + + (((1 - costheta) * axis.x * axis.z + axis.y * sintheta) * p.z); + + r.y = (((1 - costheta) * axis.x * axis.y + axis.z * sintheta) * p.x) + + ((costheta + (1 - costheta) * axis.y * axis.y) * p.y) + + (((1 - costheta) * axis.y * axis.z - axis.x * sintheta) * p.z); + + r.z = (((1 - costheta) * axis.x * axis.z - axis.y * sintheta) * p.x) + + (((1 - costheta) * axis.y * axis.z + axis.x * sintheta) * p.y) + + ((costheta + (1 - costheta) * axis.z * axis.z) * p.z); + + return r; +} + CCL_NAMESPACE_END #endif /* __UTIL_MATH_H__ */ diff --git a/intern/cycles/util/util_md5.h b/intern/cycles/util/util_md5.h index 43e08e64f39..aab177d9fe6 100644 --- a/intern/cycles/util/util_md5.h +++ b/intern/cycles/util/util_md5.h @@ -44,7 +44,7 @@ public: bool append_file(const string& filepath); string get_hex(); - protected: +protected: void process(const uint8_t *data); void finish(uint8_t digest[16]); diff --git a/intern/cycles/util/util_opencl.cpp b/intern/cycles/util/util_opencl.cpp index 40b637f5cb7..c146c14b10c 100644 --- a/intern/cycles/util/util_opencl.cpp +++ b/intern/cycles/util/util_opencl.cpp @@ -140,6 +140,10 @@ int clLibraryInit() #endif int error = 0; + // OpenCL disabled for now, only works with this environment variable set + if(!getenv("CYCLES_OPENCL_TEST")) + return 0; + // Check if already initialized if (module != NULL) { diff --git a/intern/cycles/util/util_path.cpp b/intern/cycles/util/util_path.cpp index a571fe81118..8cf23bc6a76 100644 --- a/intern/cycles/util/util_path.cpp +++ b/intern/cycles/util/util_path.cpp @@ -170,7 +170,7 @@ bool path_read_binary(const string& path, vector<uint8_t>& binary) return true; } -static bool path_read_text(const string& path, string& text) +bool path_read_text(const string& path, string& text) { vector<uint8_t> binary; @@ -184,6 +184,14 @@ static bool path_read_text(const string& path, string& text) return true; } +uint64_t path_modified_time(const string& path) +{ + if(boost::filesystem::exists(path)) + return (uint64_t)boost::filesystem::last_write_time(path); + + return 0; +} + string path_source_replace_includes(const string& source_, const string& path) { /* our own little c preprocessor that replaces #includes with the file diff --git a/intern/cycles/util/util_path.h b/intern/cycles/util/util_path.h index 6cba6a3158f..89e4452ecd9 100644 --- a/intern/cycles/util/util_path.h +++ b/intern/cycles/util/util_path.h @@ -45,6 +45,9 @@ string path_files_md5_hash(const string& dir); void path_create_directories(const string& path); bool path_write_binary(const string& path, const vector<uint8_t>& binary); bool path_read_binary(const string& path, vector<uint8_t>& binary); +bool path_read_text(const string& path, string& text); + +uint64_t path_modified_time(const string& path); string path_source_replace_includes(const string& source, const string& path); diff --git a/intern/cycles/util/util_progress.h b/intern/cycles/util/util_progress.h index c97379d8776..03e25d4d132 100644 --- a/intern/cycles/util/util_progress.h +++ b/intern/cycles/util/util_progress.h @@ -68,6 +68,21 @@ public: return *this; } + void reset() + { + tile = 0; + sample = 0; + start_time = time_dt(); + total_time = 0.0f; + tile_time = 0.0f; + status = "Initializing"; + substatus = ""; + sync_status = ""; + sync_substatus = ""; + cancel = false; + cancel_message = ""; + } + /* cancel */ void set_cancel(const string& cancel_message_) { diff --git a/intern/cycles/util/util_stats.h b/intern/cycles/util/util_stats.h new file mode 100644 index 00000000000..27638015f40 --- /dev/null +++ b/intern/cycles/util/util_stats.h @@ -0,0 +1,44 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __UTIL_STATS_H__ +#define __UTIL_STATS_H__ + +CCL_NAMESPACE_BEGIN + +class Stats { +public: + Stats() : mem_used(0), mem_peak(0) {} + + void mem_alloc(size_t size) { + mem_used += size; + if(mem_used > mem_peak) + mem_peak = mem_used; + } + + void mem_free(size_t size) { + mem_used -= size; + } + + size_t mem_used; + size_t mem_peak; +}; + +CCL_NAMESPACE_END + +#endif /* __UTIL_STATS_H__ */ diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp index ea0abd6f54f..8c4ec312256 100644 --- a/intern/cycles/util/util_task.cpp +++ b/intern/cycles/util/util_task.cpp @@ -168,10 +168,16 @@ void TaskScheduler::init(int num_threads) if(users == 0) { do_exit = false; - /* launch threads that will be waiting for work */ - if(num_threads == 0) + if(num_threads == 0) { + /* automatic number of threads will be main thread + num cores */ num_threads = system_cpu_thread_count(); + } + else { + /* main thread will also work, for fixed threads we count it too */ + num_threads -= 1; + } + /* launch threads that will be waiting for work */ threads.resize(num_threads); thread_level.resize(num_threads); diff --git a/intern/cycles/util/util_task.h b/intern/cycles/util/util_task.h index 401a503f540..b795ca7524b 100644 --- a/intern/cycles/util/util_task.h +++ b/intern/cycles/util/util_task.h @@ -94,7 +94,11 @@ public: static void init(int num_threads = 0); static void exit(); - static int num_threads() { return threads.size(); } + /* number of threads that can work on tasks, main thread counts too */ + static int num_threads() { return threads.size() + 1; } + + /* test if any session is using the scheduler */ + static bool active() { return users != 0; } protected: friend class TaskPool; diff --git a/intern/cycles/util/util_thread.h b/intern/cycles/util/util_thread.h index 9bea4e7808a..843764ca9d6 100644 --- a/intern/cycles/util/util_thread.h +++ b/intern/cycles/util/util_thread.h @@ -60,6 +60,7 @@ public: bool join() { + joined = true; return pthread_join(pthread_id, NULL) == 0; } diff --git a/intern/cycles/util/util_transform.cpp b/intern/cycles/util/util_transform.cpp index b3c6506dfa0..70ee13d96d7 100644 --- a/intern/cycles/util/util_transform.cpp +++ b/intern/cycles/util/util_transform.cpp @@ -246,9 +246,10 @@ static void transform_decompose(Transform *decomp, const Transform *tfm) decomp->w = make_float4(scale.y.z, scale.z.x, scale.z.y, scale.z.z); } -void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion) +void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion, const Transform *mid) { transform_decompose(&decomp->pre, &motion->pre); + transform_decompose(&decomp->mid, mid); transform_decompose(&decomp->post, &motion->post); } diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h index d93bbff5415..df525542207 100644 --- a/intern/cycles/util/util_transform.h +++ b/intern/cycles/util/util_transform.h @@ -41,6 +41,7 @@ typedef struct Transform { typedef struct MotionTransform { Transform pre; + Transform mid; Transform post; } MotionTransform; @@ -304,10 +305,18 @@ __device_inline float4 quat_interpolate(float4 q1, float4 q2, float t) { float costheta = dot(q1, q2); + /* rotate around shortest angle */ + if(costheta < 0.0f) { + costheta = -costheta; + q1 = -q1; + } + if(costheta > 0.9995f) { + /* linear interpolation in degenerate case */ return normalize((1.0f - t)*q1 + t*q2); } else { + /* slerp */ float theta = acosf(clamp(costheta, -1.0f, 1.0f)); float thetap = theta * t; float4 qperp = normalize(q2 - q1 * costheta); @@ -375,11 +384,37 @@ __device void transform_motion_interpolate(Transform *tfm, const MotionTransform { Transform decomp; - decomp.x = quat_interpolate(motion->pre.x, motion->post.x, t); - decomp.y = (1.0f - t)*motion->pre.y + t*motion->post.y; - decomp.z = (1.0f - t)*motion->pre.z + t*motion->post.z; - decomp.w = (1.0f - t)*motion->pre.w + t*motion->post.w; + /* 3 point bezier curve interpolation for position */ + float3 Ppre = float4_to_float3(motion->pre.y); + float3 Pmid = float4_to_float3(motion->mid.y); + float3 Ppost = float4_to_float3(motion->post.y); + + float3 Pcontrol = 2.0f*Pmid - 0.5f*(Ppre + Ppost); + float3 P = Ppre*t*t + Pcontrol*2.0f*t*(1.0f - t) + Ppost*(1.0f - t)*(1.0f - t); + + decomp.y.x = P.x; + decomp.y.y = P.y; + decomp.y.z = P.z; + + /* linear interpolation for rotation and scale */ + if(t < 0.5f) { + t *= 2.0f; + + decomp.x = quat_interpolate(motion->pre.x, motion->mid.x, t); + decomp.y.w = (1.0f - t)*motion->pre.y.w + t*motion->mid.y.w; + decomp.z = (1.0f - t)*motion->pre.z + t*motion->mid.z; + decomp.w = (1.0f - t)*motion->pre.w + t*motion->mid.w; + } + else { + t = (t - 0.5f)*2.0f; + + decomp.x = quat_interpolate(motion->mid.x, motion->post.x, t); + decomp.y.w = (1.0f - t)*motion->mid.y.w + t*motion->post.y.w; + decomp.z = (1.0f - t)*motion->mid.z + t*motion->post.z; + decomp.w = (1.0f - t)*motion->mid.w + t*motion->post.w; + } + /* compose rotation, translation, scale into matrix */ transform_compose(tfm, &decomp); } @@ -390,7 +425,7 @@ __device_inline bool operator==(const MotionTransform& A, const MotionTransform& return (A.pre == B.pre && A.post == B.post); } -void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion); +void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion, const Transform *mid); #endif diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h index 5c6b9d5bb78..fe530d727ad 100644 --- a/intern/cycles/util/util_types.h +++ b/intern/cycles/util/util_types.h @@ -449,6 +449,8 @@ typedef enum AttributeStandard { ATTR_STD_VERTEX_NORMAL, ATTR_STD_FACE_NORMAL, ATTR_STD_UV, + ATTR_STD_UV_TANGENT, + ATTR_STD_UV_TANGENT_SIGN, ATTR_STD_GENERATED, ATTR_STD_POSITION_UNDEFORMED, ATTR_STD_POSITION_UNDISPLACED, diff --git a/intern/decimation/CMakeLists.txt b/intern/decimation/CMakeLists.txt deleted file mode 100644 index 73b67d7f3b1..00000000000 --- a/intern/decimation/CMakeLists.txt +++ /dev/null @@ -1,63 +0,0 @@ -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# The Original Code is Copyright (C) 2006, Blender Foundation -# All rights reserved. -# -# The Original Code is: all of this file. -# -# Contributor(s): Jacques Beaurain. -# -# ***** END GPL LICENSE BLOCK ***** - -set(INC - . - ../container - ../guardedalloc - ../memutil - ../moto/include -) - -set(INC_SYS - -) - -set(SRC - intern/LOD_EdgeCollapser.cpp - intern/LOD_ExternNormalEditor.cpp - intern/LOD_FaceNormalEditor.cpp - intern/LOD_ManMesh2.cpp - intern/LOD_MeshPrimitives.cpp - intern/LOD_QSDecimator.cpp - intern/LOD_QuadricEditor.cpp - intern/LOD_decimation.cpp - - extern/LOD_decimation.h - intern/LOD_DecimationClass.h - intern/LOD_EdgeCollapser.h - intern/LOD_ExternBufferEditor.h - intern/LOD_ExternNormalEditor.h - intern/LOD_FaceNormalEditor.h - intern/LOD_ManMesh2.h - intern/LOD_MeshBounds.h - intern/LOD_MeshException.h - intern/LOD_MeshPrimitives.h - intern/LOD_QSDecimator.h - intern/LOD_Quadric.h - intern/LOD_QuadricEditor.h -) - -blender_add_lib(bf_intern_decimate "${SRC}" "${INC}" "${INC_SYS}") diff --git a/intern/decimation/SConscript b/intern/decimation/SConscript deleted file mode 100644 index 6f4befb3ffa..00000000000 --- a/intern/decimation/SConscript +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/python -Import ('env') - -sources = env.Glob('intern/*.cpp') - -incs = '. ../moto/include ../container ../memutil ../guardedalloc' - -env.BlenderLib ('bf_intern_decimate', sources, Split(incs) , [], libtype=['core', 'player'], priority = [200, 100] ) diff --git a/intern/decimation/extern/LOD_decimation.h b/intern/decimation/extern/LOD_decimation.h deleted file mode 100644 index 4c52cb18577..00000000000 --- a/intern/decimation/extern/LOD_decimation.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/extern/LOD_decimation.h - * \ingroup decimation - */ - - -/** - - * @author Laurence Bourn - * @date 6/7/2001 - * - * This is the external interface for the decimation module. - */ - -#ifndef __LOD_DECIMATION_H__ -#define __LOD_DECIMATION_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * External decimation structure - */ - -typedef struct LOD_Decimation_Info { - float * vertex_buffer; - float * vertex_normal_buffer; - int * triangle_index_buffer; - int vertex_num; - int face_num; - void * intern; -} LOD_Decimation_Info; - -typedef LOD_Decimation_Info* LOD_Decimation_InfoPtr; - -/** - * Create internal mesh representation from - * LOD_Decimation_Info structure. - * @return 1 on successful loading - * @return 0 on failure - * @warning This should be changed to return an enumeration - * detailing the error encountered - */ - -extern int LOD_LoadMesh(LOD_Decimation_InfoPtr info); - -/** - * Allocate and Compute internal data strucures required for - * decimation. - * @return 1 on successful computation of data - * @return 0 on failure - * @warning This should be changed to return an enumeration - * detailing the error encountered - */ - -extern int LOD_PreprocessMesh(LOD_Decimation_InfoPtr info); - -/** - * Once both the stages above have been completed - * this function collapses a single edge in the mesh. - * The LOD_Decimation_Info structure is updated - * to represent the new mesh. - * @return 1 if an edge was collapsed. - * @return 0 if no suitable edge was found to be collapsable - * You should stop calling this method in this case - * @warning Do not expect that the order of polygons, vertices or - * vertex normals will be preserved by this operation. This function - * returns a packed array of polygons and vertices and so necessarily - * the order will be different. This means you should not expect to - * find the same polygon in the same place in the polygon array after - * this function has been called. - */ - -extern int LOD_CollapseEdge(LOD_Decimation_InfoPtr info); - -/** - * Free any memory the decimation process used - * during the decimation process - * @return 1 if internal data successfully freed - * @return 0 if no data was freed - */ - -extern int LOD_FreeDecimationData(LOD_Decimation_InfoPtr); - -#ifdef __cplusplus -} -#endif - -#endif // __LOD_DECIMATION_H__ - diff --git a/intern/decimation/intern/LOD_DecimationClass.h b/intern/decimation/intern/LOD_DecimationClass.h deleted file mode 100644 index ecf2e4e6790..00000000000 --- a/intern/decimation/intern/LOD_DecimationClass.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_DecimationClass.h - * \ingroup decimation - */ - - -#ifndef __LOD_DECIMATIONCLASS_H__ -#define __LOD_DECIMATIONCLASS_H__ - -#include "MEM_SmartPtr.h" -#include "MEM_NonCopyable.h" - -#include "LOD_ManMesh2.h" -#include "LOD_QSDecimator.h" -#include "LOD_ExternNormalEditor.h" -#include "../extern/LOD_decimation.h" -#include "LOD_ExternBufferEditor.h" - - -class LOD_DecimationClass : public MEM_NonCopyable -{ -public : - - enum { - e_not_loaded, - e_loaded, - e_preprocessed - } m_e_decimation_state; - - - static - LOD_DecimationClass * - New( - LOD_Decimation_InfoPtr extern_info - ) { - // create everything - - MEM_SmartPtr<LOD_DecimationClass> output(new LOD_DecimationClass()); - MEM_SmartPtr<LOD_ManMesh2> mesh(LOD_ManMesh2::New()); - MEM_SmartPtr<LOD_ExternBufferEditor> extern_editor(LOD_ExternBufferEditor::New(extern_info)); - - if (mesh == NULL || extern_editor == NULL) return NULL; - MEM_SmartPtr<LOD_ExternNormalEditor> normals(LOD_ExternNormalEditor::New(extern_info,mesh.Ref())); - - if (normals == NULL) return NULL; - MEM_SmartPtr<LOD_QSDecimator> decimator(LOD_QSDecimator::New( - mesh.Ref(), - normals.Ref(), - extern_editor.Ref() - )); - if (decimator == NULL || output == NULL) return NULL; - - output->m_mesh = mesh.Release(); - output->m_decimator = decimator.Release(); - output->m_normals = normals.Release(); - output->m_extern_editor = extern_editor.Release(); - - return output.Release(); - } - - LOD_ManMesh2 & - Mesh( - ){ - return m_mesh.Ref(); - } - - LOD_QSDecimator & - Decimator( - ) { - return m_decimator.Ref(); - } - - LOD_ExternNormalEditor & - FaceEditor( - ){ - return m_normals.Ref(); - } - -private : - - LOD_DecimationClass( - ) : m_e_decimation_state(e_not_loaded) { - }; - - MEM_SmartPtr<LOD_ManMesh2> m_mesh; - MEM_SmartPtr<LOD_QSDecimator> m_decimator; - MEM_SmartPtr<LOD_ExternNormalEditor> m_normals; - MEM_SmartPtr<LOD_ExternBufferEditor> m_extern_editor; -}; - -#endif - diff --git a/intern/decimation/intern/LOD_EdgeCollapser.cpp b/intern/decimation/intern/LOD_EdgeCollapser.cpp deleted file mode 100644 index 1405d6f53fa..00000000000 --- a/intern/decimation/intern/LOD_EdgeCollapser.cpp +++ /dev/null @@ -1,410 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_EdgeCollapser.cpp - * \ingroup decimation - */ - - -#include "LOD_EdgeCollapser.h" - -#include "LOD_ManMesh2.h" -#include "CTR_TaggedSetOps.h" -#include <algorithm> -#include <functional> - - -using namespace std; - - - LOD_EdgeCollapser * -LOD_EdgeCollapser:: -New( -){ - return new LOD_EdgeCollapser(); -} - - - bool -LOD_EdgeCollapser:: -TJunctionTest( - LOD_ManMesh2 &mesh, - vector<LOD_EdgeInd> &e_v0v1, - LOD_EdgeInd collapse_edge -){ - - // we need to copy the edges in e_v0v1 from the mesh - // into a new buffer -> we are going to modify them - - int original_size = e_v0v1.size(); - if (original_size == 0) return true; - - vector<LOD_Edge> &edge_set = mesh.EdgeSet(); - - LOD_VertexInd c_v0 = edge_set[collapse_edge].m_verts[0]; - LOD_VertexInd c_v1 = edge_set[collapse_edge].m_verts[1]; - - vector<LOD_Edge> temp_edges; - temp_edges.reserve(e_v0v1.size()); - - vector<LOD_EdgeInd>::iterator edge_it = e_v0v1.begin(); - vector<LOD_EdgeInd>::const_iterator edge_end = e_v0v1.end(); - - for (;edge_it != edge_end; ++edge_it) { - temp_edges.push_back(edge_set[*edge_it]); - } - - // in the copied edges replace all instances of c_v0 with c_v1 - - vector<LOD_Edge>::iterator e_it = temp_edges.begin(); - vector<LOD_Edge>::const_iterator e_it_end = temp_edges.end(); - - for (; e_it != e_it_end; ++e_it) { - - if (e_it->m_verts[0] == c_v0) { - e_it->m_verts[0] = c_v1; - } - if (e_it->m_verts[1] == c_v0) { - e_it->m_verts[1] = c_v1; - } - - // normalize the edge - if (int(e_it->m_verts[0]) > int(e_it->m_verts[1])) { - LOD_EdgeInd temp = e_it->m_verts[0]; - e_it->m_verts[0] = e_it->m_verts[1]; - e_it->m_verts[1] = temp; - } - } - - // sort the edges using the edge less functional - - sort(temp_edges.begin(),temp_edges.end(),LOD_EdgeCollapser::less()); - // count the unique edges. - - e_it = temp_edges.begin(); - e_it_end = temp_edges.end(); - - int coincedent_edges = 0; - - vector<LOD_Edge>::const_iterator last_edge = e_it; - ++e_it; - - for (; e_it != e_it_end; ++e_it) { - - if ((e_it->m_verts[0] == last_edge->m_verts[0]) && - (e_it->m_verts[1] == last_edge->m_verts[1]) - ) { - ++coincedent_edges; - } - last_edge = e_it; - } - - // now if the collapse edge is a boundary edges - // then we are alloved at most one coincedent edge - - // otherwise at most 2 coincedent edges - - if (edge_set[collapse_edge].BoundaryEdge()) { - return (coincedent_edges > 1); - } else { - return (coincedent_edges > 2); - } - - -} - - - - bool -LOD_EdgeCollapser:: -CollapseEdge( - LOD_EdgeInd ei, - LOD_ManMesh2 &mesh, - vector<LOD_EdgeInd> & degenerate_edges, - vector<LOD_FaceInd> & degenerate_faces, - vector<LOD_VertexInd> & degenerate_vertices, - vector<LOD_EdgeInd> & new_edges, - vector<LOD_FaceInd> & update_faces, - vector<LOD_VertexInd> & update_vertices -){ - - vector<LOD_Vertex> &verts = mesh.VertexSet(); - vector<LOD_Edge> &edges = mesh.EdgeSet(); - vector<LOD_TriFace> &faces = mesh.FaceSet(); - - // shouldn't do this (use mesh interface instead!) - LOD_VertexInd v0_ind = edges[ei].m_verts[0]; - LOD_VertexInd v1_ind = edges[ei].m_verts[1]; -#if 0 - LOD_Vertex &v0 = verts[v0_ind]; - LOD_Vertex &v1 = verts[v1_ind]; -#endif - vector<vector<LOD_EdgeInd> > e_v01(2); - e_v01[0].reserve(32); - e_v01[1].reserve(32); - - mesh.VertexEdges(v0_ind,e_v01[0]); - mesh.VertexEdges(v1_ind,e_v01[1]); - - - // compute the union of e_v0 and e_v1 -> this is the degenerate edges of the collapse - // we remove old edges and replace edges inside the collapse zone with new ones - - CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::Union(e_v01,edges,degenerate_edges); - - vector< vector<LOD_FaceInd> > p_v01(2); - p_v01[0].reserve(32); - p_v01[1].reserve(32); - - mesh.VertexFaces(v0_ind,p_v01[0]); - mesh.VertexFaces(v1_ind,p_v01[1]); - - // compute the union of p_v0 anf p_v1 - vector<LOD_FaceInd> p_v0v1; - p_v0v1.reserve(32); - - CTR_TaggedSetOps<LOD_FaceInd,LOD_TriFace>::Union(p_v01,faces,p_v0v1); - - // compute the union of all the edges in p_v0v1 this is the collapse zone - - vector<vector<LOD_EdgeInd> > e_input_vectors(p_v0v1.size()); - - vector<LOD_FaceInd>::iterator p_v0v1_end = p_v0v1.end(); - vector<LOD_FaceInd>::iterator p_v0v1_start = p_v0v1.begin(); - - vector<vector<LOD_FaceInd> >::iterator vector_insert_it = e_input_vectors.begin(); - - for (;p_v0v1_start != p_v0v1_end; ++p_v0v1_start , ++vector_insert_it) { - mesh.FaceEdges(*p_v0v1_start,*vector_insert_it); - } - - vector<LOD_EdgeInd> collapse_zone; - collapse_zone.reserve(32); - - CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::Union(e_input_vectors,edges,collapse_zone); - - // compute the ring edges = collpase_zone - e_v0v1 - - vector<LOD_EdgeInd> edge_ring; - edge_ring.reserve(32); - - CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::Difference(collapse_zone,degenerate_edges,edges,edge_ring); - - // T Junction test - ////////////////// - // At this point we check to see if any of the polygons - // in p_v0v1 are coninceddent - this leads - // to errors later on if we try and insert a polygon - // into the mesh to an edge which already has 2 polygons. - - // not that t junctions occur naturally from edge collapses - // and are not just the result of coincedent polygons - // for example consider collapsing an edge that forms part - // of a triangular bottle neck. - - // Really we need to make sure that we don't create t-junctions. - - // I think that a sufficient test is to check the number of - // coincedent edge pairs after a collapse. If it is more than 2 - // then collapsing the edge may result in an undeleted edge - // sharing more than 2 polygons. This test probably is too - // restictive though. - - // To perform this test we need to make a copy of the edges - // in e_v0v1. We then apply the contraction to these edge - // copies. Sort them using a function that places coincedent - // edges next to each other. And then count the number - // of coincedent pairs. - - // Of course we have to do this test before we change any of the - // mesh -> so we can back out safely. - - if (TJunctionTest(mesh,degenerate_edges,ei)) return false; - - // Compute the set of possibly degenerate vertices - // this is the union of all the vertices of polygons - // of v0 and v1 - - vector<LOD_FaceInd>::iterator face_it = p_v0v1.begin(); - vector<LOD_FaceInd>::const_iterator face_end = p_v0v1.end(); - - - vector<vector<LOD_VertexInd> > p_v0v1_vertices(p_v0v1.size()); - - for (int i = 0; face_it != face_end; ++face_it, ++i) { - mesh.FaceVertices(*face_it,p_v0v1_vertices[i]); - } - - vector<LOD_VertexInd> vertex_ring; - vertex_ring.reserve(32); - - CTR_TaggedSetOps<LOD_VertexInd,LOD_Vertex>::Union(p_v0v1_vertices,verts,vertex_ring); - - // remove all the internal edges e_v0v1 from the mesh. - // for each edge remove the egde from it's vertices edge lists. - - vector<LOD_EdgeInd>::iterator edge_it = degenerate_edges.begin(); - vector<LOD_EdgeInd>::const_iterator edge_end = degenerate_edges.end(); - - for (; !(edge_it == edge_end); ++edge_it) { - - LOD_EdgeInd ed = (*edge_it); - LOD_Edge & edge = edges[ed];//*edge_it]; - - verts[edge.m_verts[0]].RemoveEdge(ed); - verts[edge.m_verts[1]].RemoveEdge(ed); - } - - // we postpone deletion of the internal edges untill the end - // this is because deleting edges invalidates all of the - // EdgeInd vectors above. - - - // now untie all the polygons in p_v0v1 from the edge ring - - // select all polygons in p_v0v1 - - face_it = p_v0v1.begin(); - face_end = p_v0v1.end(); - - for (;face_it != face_end; ++face_it) { - faces[*face_it].SetSelectTag(true); - } - - edge_it = edge_ring.begin(); - edge_end = edge_ring.end(); - - for (;edge_it != edge_end; ++edge_it) { - LOD_Edge & edge = edges[*edge_it]; - - // presumably all edges in edge_ring point to at least - // one polygon from p_v0v1 - - if (!edge.m_faces[0].IsEmpty() && faces[edge.m_faces[0]].SelectTag()) { - edge.m_faces[0].Invalidate(); - } - - if (!edge.m_faces[1].IsEmpty() && faces[edge.m_faces[1]].SelectTag()) { - edge.m_faces[1].Invalidate(); - } - } - - // deselect the faces - - face_it = p_v0v1.begin(); - face_end = p_v0v1.end(); - - for (;face_it != face_end; ++face_it) { - faces[*face_it].SetSelectTag(false); - } - - // perform the edge collapse - //////////////////////////// - - // iterate through the polygons of p_v0 and replace the vertex - // index v0 with v1 - - face_it = p_v01[0].begin(); - face_end = p_v01[0].end(); - - for (;face_it != face_end; ++face_it) { - faces[*face_it].SwapVertex(v0_ind,v1_ind); - } - - face_it = p_v0v1.begin(); - face_end = p_v0v1.end(); - - for (;face_it != face_end; ++face_it) { - if (faces[*face_it].Degenerate()) { - degenerate_faces.push_back(*face_it); - } else { - update_faces.push_back(*face_it); - } - } - - // Add all the non-degenerate faces back into the - // mesh. Get a record of the new edges created in - // this process. - - face_it = update_faces.begin(); - face_end = update_faces.end(); - - for (;face_it != face_end; ++face_it) { - mesh.ConnectTriangle(*face_it,new_edges); - } - - // degenerate ring primitives - ///////////////////////////// - - // we now need to examine each of the edges on the ring - // and work out if they are degenerate - if so we attempt - // to delete them -> add them to the other edges to delete - // in e_v0v1 - - edge_it = edge_ring.begin(); - edge_end = edge_ring.end(); - - for (;edge_it != edge_end; ++edge_it) { - if (edges[*edge_it].Degenerate()) { - degenerate_edges.push_back(*edge_it); - } - } - - // do the same for the ring vertices. - - vector<LOD_VertexInd>::iterator vertex_it = vertex_ring.begin(); - vector<LOD_VertexInd>::const_iterator vertex_end = vertex_ring.end(); - - for (;vertex_it != vertex_end; ++vertex_it) { - if (verts[*vertex_it].Degenerate()) { - degenerate_vertices.push_back(*vertex_it); - } else { - update_vertices.push_back(*vertex_it); - } - } - - // we now know all the degenerate primitives - // and the new primitives we have inserted into the mesh - - // We now delete the mesh primitives, mesh.DeleteXXXXXX() methods - // assume that the index vectors are sorted into descending order. - // we do that now. - - sort(degenerate_edges.begin(),degenerate_edges.end(),LOD_EdgeInd::greater()); - sort(degenerate_faces.begin(),degenerate_faces.end(),LOD_FaceInd::greater()); - sort(degenerate_vertices.begin(),degenerate_vertices.end(),LOD_VertexInd::greater()); - - - return true; - -} - -LOD_EdgeCollapser:: -LOD_EdgeCollapser( -){ - // nothing to do -} diff --git a/intern/decimation/intern/LOD_EdgeCollapser.h b/intern/decimation/intern/LOD_EdgeCollapser.h deleted file mode 100644 index 75a8b70f672..00000000000 --- a/intern/decimation/intern/LOD_EdgeCollapser.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_EdgeCollapser.h - * \ingroup decimation - */ - - -#ifndef __LOD_EDGECOLLAPSER_H__ -#define __LOD_EDGECOLLAPSER_H__ - -// This is a helper class that collapses edges of a 2 - manifold mesh. - -#include "LOD_MeshPrimitives.h" -#include "MEM_NonCopyable.h" -#include <vector> -#include <functional> - -class LOD_ManMesh2; - -class LOD_EdgeCollapser -: public MEM_NonCopyable -{ - -public : - - static - LOD_EdgeCollapser * - New( - ); - - // returns via arguments the set of modified - // verts,edges and faces. - - bool - CollapseEdge( - LOD_EdgeInd ei, - LOD_ManMesh2 &mesh, - std::vector<LOD_EdgeInd> & degenerate_edges, - std::vector<LOD_FaceInd> & degenerate_faces, - std::vector<LOD_VertexInd> & degenerate_vertices, - std::vector<LOD_EdgeInd> & new_edges, - std::vector<LOD_FaceInd> & update_faces, - std::vector<LOD_VertexInd> & update_vertices - ); - -private : - - LOD_EdgeCollapser( - ); - - // Test to see if the result of collapsing the - // edge produces 2 junctions in the mesh i.e. where - // an edge is shared by more than 2 polygons - - // We count the number of coincedent edge pairs that - // result from the collapse of collapse_edge. - - // If collapse edge is a boundary edge then the number of - // coincedent pairs should be 1 - // else it should be 2. - - bool - TJunctionTest( - LOD_ManMesh2 &mesh, - std::vector<LOD_EdgeInd> &e_v0v1, - LOD_EdgeInd collapse_edge - ); - - // here's the definition of the sort function - // we use to determine coincedent edges - - // assumes the edges are normalized i.e. m_verts[0] <= m_verts[1] - - struct less : std::binary_function<LOD_Edge, LOD_Edge, bool> { - bool - operator()( - const LOD_Edge& a, - const LOD_Edge& b - ) const { - - if (int(a.m_verts[0]) == int(b.m_verts[0])) { - return (int(a.m_verts[1]) < int(b.m_verts[1])); - } else { - return (int(a.m_verts[0]) < int(b.m_verts[0])); - } - } - }; - -}; - -#endif - diff --git a/intern/decimation/intern/LOD_ExternBufferEditor.h b/intern/decimation/intern/LOD_ExternBufferEditor.h deleted file mode 100644 index c903b255812..00000000000 --- a/intern/decimation/intern/LOD_ExternBufferEditor.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_ExternBufferEditor.h - * \ingroup decimation - */ - - -/** - - * Copyright (C) 2001 NaN Technologies B.V. - */ - -#ifndef __LOD_EXTERNBUFFEREDITOR_H__ -#define __LOD_EXTERNBUFFEREDITOR_H__ - -#include "LOD_MeshPrimitives.h" -#include <vector> -#include "LOD_ManMesh2.h" -#include "../extern/LOD_decimation.h" - - -// This class syncs external vertex/face buffers -// with the internal mesh representation during -// decimation. - -class LOD_ExternBufferEditor -{ - -public : - - static - LOD_ExternBufferEditor * - New( - LOD_Decimation_InfoPtr extern_info - ){ - if (extern_info == NULL) return NULL; - return new LOD_ExternBufferEditor(extern_info); - } - - // update the external vertex buffer with vertices - // from the mesh - - void - CopyModifiedVerts( - LOD_ManMesh2 & mesh, - const std::vector<LOD_VertexInd> & mod_vertices - ){ - - std::vector<LOD_VertexInd>::const_iterator v_start = mod_vertices.begin(); - std::vector<LOD_VertexInd>::const_iterator v_end = mod_vertices.end(); - - std::vector<LOD_Vertex> & mesh_verts = mesh.VertexSet(); - - float * const extern_vertex_ptr = m_extern_info->vertex_buffer; - - for (; v_start != v_end; ++v_start) { - float * mod_vert = extern_vertex_ptr + int(*v_start)*3; - mesh_verts[*v_start].CopyPosition(mod_vert); - } - } - - // update the external face buffer with faces from the mesh - - void - CopyModifiedFaces( - LOD_ManMesh2 & mesh, - const std::vector<LOD_FaceInd> & mod_faces - ){ - - std::vector<LOD_FaceInd>::const_iterator f_start = mod_faces.begin(); - std::vector<LOD_FaceInd>::const_iterator f_end = mod_faces.end(); - - std::vector<LOD_TriFace> &mesh_faces = mesh.FaceSet(); - - int * const extern_face_ptr = m_extern_info->triangle_index_buffer; - - for (; f_start != f_end; ++f_start) { - int *mod_face = extern_face_ptr + 3*int(*f_start); - mesh_faces[*f_start].CopyVerts(mod_face); - } - } - - - // Copy the last vertex over the vertex specified by - // vi. Decrement the size of the vertex array - - void - CopyBackVertex( - LOD_VertexInd vi - ){ - - float * const extern_vertex_ptr = m_extern_info->vertex_buffer; - int * extern_vertex_num = &(m_extern_info->vertex_num); - - float * last_external_vert = extern_vertex_ptr + 3*((*extern_vertex_num) - 1); - float * external_vert = extern_vertex_ptr + 3*int(vi); - - external_vert[0] = last_external_vert[0]; - external_vert[1] = last_external_vert[1]; - external_vert[2] = last_external_vert[2]; - - *extern_vertex_num -=1; - } - - // Copy the last face over the face specified by fi - // Decrement the size of the face array - - void - CopyBackFace( - LOD_FaceInd fi - ) { - int * const extern_face_ptr = m_extern_info->triangle_index_buffer; - int * extern_face_num = &(m_extern_info->face_num); - - int * last_external_face = extern_face_ptr + 3*((*extern_face_num) -1); - int * external_face = extern_face_ptr + 3*int(fi); - external_face[0] = last_external_face[0]; - external_face[1] = last_external_face[1]; - external_face[2] = last_external_face[2]; - - *extern_face_num -=1; - } - - -private : - - LOD_ExternBufferEditor( - LOD_Decimation_InfoPtr extern_info - ) : - m_extern_info (extern_info) - { - } - - LOD_Decimation_InfoPtr const m_extern_info; - -}; - -#endif - diff --git a/intern/decimation/intern/LOD_ExternNormalEditor.cpp b/intern/decimation/intern/LOD_ExternNormalEditor.cpp deleted file mode 100644 index 90033fe672b..00000000000 --- a/intern/decimation/intern/LOD_ExternNormalEditor.cpp +++ /dev/null @@ -1,264 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_ExternNormalEditor.cpp - * \ingroup decimation - */ - - -#include "LOD_ExternNormalEditor.h" -#include <vector> - -using namespace std; - - -LOD_ExternNormalEditor:: -LOD_ExternNormalEditor( - LOD_Decimation_InfoPtr extern_info, - LOD_ManMesh2 &mesh -) : - m_mesh(mesh), - m_extern_info (extern_info) -{ -} - - LOD_ExternNormalEditor * -LOD_ExternNormalEditor:: -New( - LOD_Decimation_InfoPtr extern_info, - LOD_ManMesh2 &mesh -){ - if (extern_info == NULL) return NULL; - - MEM_SmartPtr<LOD_ExternNormalEditor> output(new LOD_ExternNormalEditor(extern_info,mesh)); - - int face_num = mesh.FaceSet().size(); - - MEM_SmartPtr<vector<MT_Vector3> > normals(new vector<MT_Vector3>); - - if (output == NULL || - normals == NULL - ) { - return NULL; - } - - normals->reserve(face_num); - output->m_normals = normals.Release(); - - return output.Release(); -}; - - - void -LOD_ExternNormalEditor:: -Remove( - std::vector<LOD_FaceInd> &sorted_faces -){ - // assumes a collection of faces sorted in descending order . - - vector<MT_Vector3> & normals = m_normals.Ref(); - - vector<LOD_FaceInd>::const_iterator it_start = sorted_faces.begin(); - vector<LOD_FaceInd>::const_iterator it_end = sorted_faces.end(); - - for (; it_start != it_end; ++it_start) { - - if (normals.size() > 0) { - MT_Vector3 temp = normals[*it_start]; - - normals[*it_start] = normals.back(); - normals.back() = temp; - - normals.pop_back(); - } - - // FIXME - throw exception - } -} - - - void -LOD_ExternNormalEditor:: -Add( -){ - MT_Vector3 zero(0.0f,0.0f,0.0f); - m_normals->push_back(zero); -}; - - void -LOD_ExternNormalEditor:: -Update( - std::vector<LOD_FaceInd> &sorted_faces -){ - vector<MT_Vector3> & normals = m_normals.Ref(); - - vector<LOD_FaceInd>::const_iterator it_start = sorted_faces.begin(); - vector<LOD_FaceInd>::const_iterator it_end = sorted_faces.end(); - - const vector<LOD_TriFace> &faces = m_mesh.FaceSet(); - - for (; it_start != it_end; ++it_start) { - normals[*it_start] = ComputeNormal(faces[*it_start]); - } -}; - - - - -// vertex normals -///////////////// - - void -LOD_ExternNormalEditor:: -RemoveVertexNormals( - std::vector<LOD_VertexInd> &sorted_verts -){ - - float * vertex_normals = m_extern_info->vertex_normal_buffer; - - // assumption here that the vertexs normal number corresponds with - // the number of vertices ! - - int vertex_normal_num = m_extern_info->vertex_num; - - vector<LOD_VertexInd>::const_iterator it_start = sorted_verts.begin(); - vector<LOD_VertexInd>::const_iterator it_end = sorted_verts.end(); - - for (; it_start != it_end; ++it_start) { - - if (vertex_normal_num > 0) { - float * vertex_normal = vertex_normals + int(*it_start)*3; - float * last_vertex = vertex_normals + ((vertex_normal_num-1)*3); - - MT_Vector3 last_v(last_vertex); - last_v.getValue(vertex_normal); - vertex_normal_num--; - } - - // FIXME - through exception - } -}; - - - - void -LOD_ExternNormalEditor:: -UpdateVertexNormals( - std::vector<LOD_VertexInd> &sorted_verts -){ - float * vertex_normals = m_extern_info->vertex_normal_buffer; - - vector<LOD_VertexInd>::const_iterator it_start = sorted_verts.begin(); - vector<LOD_VertexInd>::const_iterator it_end = sorted_verts.end(); - - for (; it_start != it_end; ++it_start) { - MT_Vector3 temp = ComputeVertexNormal(*it_start); - float * vertex_normal = vertex_normals + int(*it_start)*3; - temp.getValue(vertex_normal); - } -} - -// Editor specific methods -////////////////////////// - - void -LOD_ExternNormalEditor:: -BuildNormals( -) { - const vector<LOD_TriFace> &faces = m_mesh.FaceSet(); - vector<MT_Vector3> & normals = m_normals.Ref(); - - int face_num = faces.size(); - int cur_face = 0; - - for (; cur_face < face_num; ++cur_face) { - - MT_Vector3 new_normal = ComputeNormal(faces[cur_face]); - normals.push_back(new_normal); - } -} - -const - MT_Vector3 -LOD_ExternNormalEditor:: -ComputeNormal( - const LOD_TriFace &face -) const { - - const vector<LOD_Vertex> &verts = m_mesh.VertexSet(); - - MT_Vector3 vec1 = - verts[face.m_verts[1]].pos - - verts[face.m_verts[0]].pos; - - MT_Vector3 vec2 = - verts[face.m_verts[2]].pos - - verts[face.m_verts[1]].pos; - - vec1 = vec1.cross(vec2); - - if (!vec1.fuzzyZero()) { - vec1.normalize(); - return (vec1); - } else { - return (MT_Vector3(1.0,0,0)); - } -} - -const - MT_Vector3 -LOD_ExternNormalEditor:: -ComputeVertexNormal( - const LOD_VertexInd v -) const { - - // average the face normals surrounding this - // vertex and normalize - // vector<LOD_Vertex> &verts = m_mesh.VertexSet(); /*unused*/ - const vector<MT_Vector3> & face_normals = m_normals.Ref(); - - vector<LOD_FaceInd> vertex_faces; - vertex_faces.reserve(32); - - m_mesh.VertexFaces(v,vertex_faces); - - MT_Vector3 normal(0,0,0); - - vector<LOD_FaceInd>::const_iterator face_it = vertex_faces.begin(); - vector<LOD_FaceInd>::const_iterator face_end = vertex_faces.end(); - - for (; face_it != face_end; ++face_it) { - normal += face_normals[*face_it]; - } - - if (!normal.fuzzyZero()) { - normal.normalize(); - return (normal); - } else { - return (MT_Vector3(1.0,0,0)); - } -} diff --git a/intern/decimation/intern/LOD_ExternNormalEditor.h b/intern/decimation/intern/LOD_ExternNormalEditor.h deleted file mode 100644 index 52135196dc5..00000000000 --- a/intern/decimation/intern/LOD_ExternNormalEditor.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_ExternNormalEditor.h - * \ingroup decimation - */ - - -#ifndef __LOD_EXTERNNORMALEDITOR_H__ -#define __LOD_EXTERNNORMALEDITOR_H__ - -#include "MEM_NonCopyable.h" -#include "LOD_ManMesh2.h" -#include "MT_Vector3.h" -#include "../extern/LOD_decimation.h" - -class LOD_ExternNormalEditor : public MEM_NonCopyable -{ - -public : - - // Creation - /////////// - - static - LOD_ExternNormalEditor * - New( - LOD_Decimation_InfoPtr, - LOD_ManMesh2 &mesh - ); - - // Property editor interface - //////////////////////////// - - - // Faces - //////// - void - Remove( - std::vector<LOD_FaceInd> &sorted_faces - ); - - void - Add( - ); - - void - Update( - std::vector<LOD_FaceInd> &sorted_faces - ); - - const - std::vector<MT_Vector3> & - Normals( - ) const { - return m_normals.Ref(); - }; - - - // vertex normals - ///////////////// - - void - RemoveVertexNormals( - std::vector<LOD_VertexInd> &sorted_verts - ); - - - void - UpdateVertexNormals( - std::vector<LOD_VertexInd> &sorted_verts - ); - - // Editor specific methods - ////////////////////////// - - void - BuildNormals( - ); - - -private : - - MEM_SmartPtr<std::vector<MT_Vector3> > m_normals; - - LOD_ManMesh2 &m_mesh; - LOD_Decimation_InfoPtr m_extern_info; - -private : - - - LOD_ExternNormalEditor( - LOD_Decimation_InfoPtr extern_info, - LOD_ManMesh2 &mesh - ); - - const - MT_Vector3 - ComputeNormal( - const LOD_TriFace &face - ) const; - - const - MT_Vector3 - ComputeVertexNormal ( - const LOD_VertexInd vi - ) const; -}; - -#endif - diff --git a/intern/decimation/intern/LOD_FaceNormalEditor.cpp b/intern/decimation/intern/LOD_FaceNormalEditor.cpp deleted file mode 100644 index 430406a6d63..00000000000 --- a/intern/decimation/intern/LOD_FaceNormalEditor.cpp +++ /dev/null @@ -1,291 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_FaceNormalEditor.cpp - * \ingroup decimation - */ - - -// implementation of LOD_FaceNormalEditor.h - -/////////////////////////////////////// -#include "LOD_FaceNormalEditor.h" - -using namespace std; - -LOD_FaceNormalEditor:: -LOD_FaceNormalEditor( - LOD_ManMesh2 & mesh -) : m_mesh(mesh) { -}; - - LOD_FaceNormalEditor * -LOD_FaceNormalEditor:: -New( - LOD_ManMesh2 &mesh -){ - // build a set of normals of the same size - // as the number of polys in the mesh - - MEM_SmartPtr<LOD_FaceNormalEditor> output(new LOD_FaceNormalEditor(mesh)); - - int face_num = mesh.FaceSet().size(); - - MEM_SmartPtr<vector<MT_Vector3> > normals(new vector<MT_Vector3>); - MEM_SmartPtr<vector<MT_Vector3> > vertex_normals(new vector<MT_Vector3>); - - if (output == NULL || - normals == NULL - ) { - return NULL; - } - - normals->reserve(face_num); - vertex_normals->reserve(mesh.VertexSet().size()); - output->m_normals = normals.Release(); - output->m_vertex_normals = vertex_normals.Release(); - - return output.Release(); -}; - - -// Property editor interface -//////////////////////////// - - void -LOD_FaceNormalEditor:: -Remove( - std::vector<LOD_FaceInd> &sorted_faces -){ - - // assumes a collection of faces sorted in descending order . - - vector<MT_Vector3> & normals = m_normals.Ref(); - - vector<LOD_FaceInd>::const_iterator it_start = sorted_faces.begin(); - vector<LOD_FaceInd>::const_iterator it_end = sorted_faces.end(); - - for (; it_start != it_end; ++it_start) { - - if (normals.size() > 0) { - MT_Vector3 temp = normals[*it_start]; - - normals[*it_start] = normals.back(); - normals.back() = temp; - - normals.pop_back(); - } - - // FIXME - through exception - } -} - - - void -LOD_FaceNormalEditor:: -Add( -){ - MT_Vector3 zero(0.0f,0.0f,0.0f); - m_normals->push_back(zero); -} - - void -LOD_FaceNormalEditor:: -Update( - std::vector<LOD_FaceInd> &sorted_faces -){ - - vector<MT_Vector3> & normals = m_normals.Ref(); - - vector<LOD_FaceInd>::const_iterator it_start = sorted_faces.begin(); - vector<LOD_FaceInd>::const_iterator it_end = sorted_faces.end(); - - const vector<LOD_TriFace> &faces = m_mesh.FaceSet(); - - for (; it_start != it_end; ++it_start) { - normals[*it_start] = ComputeNormal(faces[*it_start]); - } -}; - -// vertex normals -///////////////// - - - void -LOD_FaceNormalEditor:: -RemoveVertexNormals( - vector<LOD_VertexInd> &sorted_verts -){ - vector<MT_Vector3> & vertex_normals = m_vertex_normals.Ref(); - - vector<LOD_VertexInd>::const_iterator it_start = sorted_verts.begin(); - vector<LOD_VertexInd>::const_iterator it_end = sorted_verts.end(); - - for (; it_start != it_end; ++it_start) { - - if (vertex_normals.size() > 0) { - MT_Vector3 temp = vertex_normals[*it_start]; - - vertex_normals[*it_start] = vertex_normals.back(); - vertex_normals.back() = temp; - - vertex_normals.pop_back(); - } - - // FIXME - through exception - } -}; - - void -LOD_FaceNormalEditor:: -UpdateVertexNormals( - vector<LOD_VertexInd> &sorted_verts -){ - vector<MT_Vector3> & vertex_normals = m_vertex_normals.Ref(); - - vector<LOD_VertexInd>::const_iterator it_start = sorted_verts.begin(); - vector<LOD_VertexInd>::const_iterator it_end = sorted_verts.end(); - - for (; it_start != it_end; ++it_start) { - vertex_normals[*it_start] = ComputeVertexNormal(*it_start); - } -} - - - -// Editor specific methods -////////////////////////// - - void -LOD_FaceNormalEditor:: -BuildNormals( -){ - - const vector<LOD_TriFace> &faces = m_mesh.FaceSet(); - vector<MT_Vector3> & normals = m_normals.Ref(); - - int face_num = faces.size(); - int cur_face = 0; - - for (; cur_face < face_num; ++cur_face) { - - MT_Vector3 new_normal = ComputeNormal(faces[cur_face]); - normals.push_back(new_normal); - } - // now build the vertex normals - - vector<MT_Vector3> & vertex_normals = m_vertex_normals.Ref(); - const vector<LOD_Vertex> &verts = m_mesh.VertexSet(); - - int vertex_num = verts.size(); - int cur_vertex = 0; - - for (; cur_vertex < vertex_num; ++cur_vertex) { - MT_Vector3 new_normal = ComputeVertexNormal(cur_vertex); - vertex_normals.push_back(new_normal); - } -} - -const - MT_Vector3 -LOD_FaceNormalEditor:: -ComputeNormal( - const LOD_TriFace &face -) const { - - const vector<LOD_Vertex> &verts = m_mesh.VertexSet(); - - MT_Vector3 vec1 = - verts[face.m_verts[1]].pos - - verts[face.m_verts[0]].pos; - - MT_Vector3 vec2 = - verts[face.m_verts[2]].pos - - verts[face.m_verts[1]].pos; - - vec1 = vec1.cross(vec2); - - if (!vec1.fuzzyZero()) { - vec1.normalize(); - return (vec1); - } else { - return (MT_Vector3(1.0,0,0)); - } -} - -const - MT_Vector3 -LOD_FaceNormalEditor:: -ComputeVertexNormal( - const LOD_VertexInd v -) const { - - // average the face normals surrounding this - // vertex and normalize - const vector<MT_Vector3> & face_normals = m_normals.Ref(); - - vector<LOD_FaceInd> vertex_faces; - vertex_faces.reserve(32); - - m_mesh.VertexFaces(v,vertex_faces); - - MT_Vector3 normal(0,0,0); - - vector<LOD_FaceInd>::const_iterator face_it = vertex_faces.begin(); - vector<LOD_FaceInd>::const_iterator face_end = vertex_faces.end(); - - for (; face_it != face_end; ++face_it) { - normal += face_normals[*face_it]; - } - - if (!normal.fuzzyZero()) { - normal.normalize(); - return (normal); - } else { - return (MT_Vector3(1.0,0,0)); - } -} - - - - - - - - - - - - - - - - - - - - diff --git a/intern/decimation/intern/LOD_FaceNormalEditor.h b/intern/decimation/intern/LOD_FaceNormalEditor.h deleted file mode 100644 index a221ab0bd7a..00000000000 --- a/intern/decimation/intern/LOD_FaceNormalEditor.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_FaceNormalEditor.h - * \ingroup decimation - */ - - -#ifndef __LOD_FACENORMALEDITOR_H__ -#define __LOD_FACENORMALEDITOR_H__ - -#include "MEM_NonCopyable.h" -#include "LOD_ManMesh2.h" -#include "MT_Vector3.h" - - -class LOD_FaceNormalEditor : public MEM_NonCopyable -{ - -public : - - // Creation - /////////// - - static - LOD_FaceNormalEditor * - New( - LOD_ManMesh2 &mesh - ); - - // Property editor interface - //////////////////////////// - - - // Faces - //////// - void - Remove( - std::vector<LOD_FaceInd> &sorted_faces - ); - - void - Add( - ); - - void - Update( - std::vector<LOD_FaceInd> &sorted_faces - ); - - - // vertex normals - ///////////////// - - void - RemoveVertexNormals( - std::vector<LOD_VertexInd> &sorted_verts - ); - - - void - UpdateVertexNormals( - std::vector<LOD_VertexInd> &sorted_verts - ); - - - - const - std::vector<MT_Vector3> & - Normals( - ) const { - return m_normals.Ref(); - }; - - - const - std::vector<MT_Vector3> & - VertexNormals( - ) const { - return m_vertex_normals.Ref(); - }; - - // Editor specific methods - ////////////////////////// - - void - BuildNormals( - ); - - -private : - - MEM_SmartPtr<std::vector<MT_Vector3> > m_normals; - MEM_SmartPtr<std::vector<MT_Vector3> > m_vertex_normals; - - LOD_ManMesh2 &m_mesh; - -private : - - - LOD_FaceNormalEditor(LOD_ManMesh2 &mesh); - - const - MT_Vector3 - ComputeNormal( - const LOD_TriFace &face - ) const; - - const - MT_Vector3 - ComputeVertexNormal ( - const LOD_VertexInd vi - ) const; - - - -}; - -#endif - diff --git a/intern/decimation/intern/LOD_ManMesh2.cpp b/intern/decimation/intern/LOD_ManMesh2.cpp deleted file mode 100644 index c618944162f..00000000000 --- a/intern/decimation/intern/LOD_ManMesh2.cpp +++ /dev/null @@ -1,618 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_ManMesh2.cpp - * \ingroup decimation - */ - - -#include "LOD_ManMesh2.h" - -#include "MT_assert.h" -#include <algorithm> -#include "LOD_MeshException.h" -#include "CTR_TaggedSetOps.h" -#include "CTR_UHeap.h" -#include "LOD_ExternBufferEditor.h" - - -using namespace std; - -LOD_ManMesh2:: -LOD_ManMesh2( -) : - m_bbox_min(0,0,0), - m_bbox_max(0,0,0) -{ -} - - - LOD_ManMesh2 * -LOD_ManMesh2:: -New( -){ - MEM_SmartPtr<LOD_ManMesh2> output(new LOD_ManMesh2()); - if (output == NULL) return NULL; - - // build the vertex, edge and face sets. - - MEM_SmartPtr<vector<LOD_Vertex> > verts(new vector<LOD_Vertex>); - MEM_SmartPtr<vector<LOD_TriFace> > faces(new vector<LOD_TriFace>); - MEM_SmartPtr<vector<LOD_Edge> > edges(new vector<LOD_Edge>); - - if ((faces == NULL) || (edges == NULL) || (verts == NULL)) { - return NULL; - } - - output->m_verts = verts.Release(); - output->m_faces = faces.Release(); - output->m_edges = edges.Release(); - - return output.Release(); -} - -// take ownership of the vertices. - - bool -LOD_ManMesh2:: -SetVertices( - MEM_SmartPtr<vector<LOD_Vertex> > verts -){ - - - // take ownership of vertices - m_verts = verts; - - // create a polygon and edge buffer of half the size - // and just use the automatic resizing feature of vector<> - // to worry about the dynamic array resizing - - m_faces->clear(); - m_edges->clear(); - - m_faces->reserve(m_verts->size()/2); - m_edges->reserve(m_verts->size()/2); - - return true; - -} - - -// add a triangle to the mesh - - void -LOD_ManMesh2:: -AddTriangle( - int verts[3] -) { - - MT_assert(verts[0] < int(m_verts->size())); - MT_assert(verts[1] < int(m_verts->size())); - MT_assert(verts[2] < int(m_verts->size())); - - LOD_TriFace face; - face.m_verts[0] = verts[0]; - face.m_verts[1] = verts[1]; - face.m_verts[2] = verts[2]; - - LOD_FaceInd face_index = m_faces->size(); - - m_faces->push_back(face); - - // now work out if any of the directed edges or their - // companion edges exist already. - // We go through the edges associated with each of the given vertices - - // the safest thing to do is iterate through each of the edge sets - // check against each of the 2 other triangle edges to see if they are there - - vector<LOD_EdgeInd> new_edges; - new_edges.reserve(3); - - InsertEdge(verts[0],verts[1],face_index,new_edges); - InsertEdge(verts[1],verts[2],face_index,new_edges); - InsertEdge(verts[2],verts[0],face_index,new_edges); - -} - -// Adds the index of any created edges to new_edges - - bool -LOD_ManMesh2:: -InsertEdge( - const LOD_VertexInd v1, - const LOD_VertexInd v2, - const LOD_FaceInd f, - vector<LOD_EdgeInd> &new_edges -){ - - MT_assert(!v1.IsEmpty()); - MT_assert(!v2.IsEmpty()); - MT_assert(!f.IsEmpty()); - - vector<LOD_Vertex> &verts = VertexSet(); - vector<LOD_Edge> &edges = EdgeSet(); - - LOD_EdgeInd e; - - e = FindEdge(v1,v2); - - if (e.IsEmpty()) { - // This edge does not exist -- make a new one - - LOD_Edge temp_e; - temp_e.m_verts[0] = v1; - temp_e.m_verts[1] = v2; - - e = m_edges->size(); - - // set the face ptr for this half-edge - temp_e.m_faces[0] = f; - - m_edges->push_back(temp_e); - - // add the edge index to it's vertices - - verts[v1].AddEdge(e); - verts[v2].AddEdge(e); - - new_edges.push_back(e); - - } else { - - // edge already exists - // insure that there is no polygon already - // attached to the other side of this edge - - // swap the empty face pointer in edge with f - - LOD_Edge &edge = edges[e]; - - edge.SwapFace(LOD_FaceInd::Empty(),f); - } - - - return true; - -} - - void -LOD_ManMesh2:: -ConnectTriangle( - LOD_FaceInd fi, - std::vector<LOD_EdgeInd> & new_edges -){ - - vector<LOD_TriFace> &faces = FaceSet(); - - MT_assert(!faces[fi].Degenerate()); - - LOD_TriFace & face = faces[fi]; - - InsertEdge(face.m_verts[0],face.m_verts[1],fi,new_edges); - InsertEdge(face.m_verts[1],face.m_verts[2],fi,new_edges); - InsertEdge(face.m_verts[2],face.m_verts[0],fi,new_edges); -}; - - - - -// geometry access -////////////////// - - vector<LOD_Vertex> & -LOD_ManMesh2:: -VertexSet( -) const { - return m_verts.Ref(); -} - - vector<LOD_TriFace> & -LOD_ManMesh2:: -FaceSet( -) const { - return m_faces.Ref(); -} - - vector<LOD_Edge> & -LOD_ManMesh2:: -EdgeSet( -) const { - return m_edges.Ref(); -}; - -LOD_ManMesh2:: -~LOD_ManMesh2( -){ - //auto ptr takes care of vertex arrays etc. -} - - LOD_EdgeInd -LOD_ManMesh2:: -FindEdge( - const LOD_VertexInd v1, - const LOD_VertexInd v2 -) { - - vector<LOD_Vertex> &verts = VertexSet(); - vector<LOD_Edge> &edges = EdgeSet(); - - LOD_Edge e; - e.m_verts[0] = v1; - e.m_verts[1] = v2; - - vector<LOD_EdgeInd> &v1_edges = verts[v1].m_edges; - vector<LOD_EdgeInd>::const_iterator v1_end = v1_edges.end(); - vector<LOD_EdgeInd>::iterator v1_begin = v1_edges.begin(); - - for (; v1_begin != v1_end; ++v1_begin) { - if (edges[*v1_begin] == e) return *v1_begin; - } - - return LOD_EdgeInd::Empty(); -} - -// face queries -/////////////// - - void -LOD_ManMesh2:: -FaceVertices( - LOD_FaceInd fi, - vector<LOD_VertexInd> &output -){ - const vector<LOD_TriFace> &faces = FaceSet(); - const LOD_TriFace & f = faces[fi]; - - output.push_back(f.m_verts[0]); - output.push_back(f.m_verts[1]); - output.push_back(f.m_verts[2]); -} - - void -LOD_ManMesh2:: -FaceEdges( - LOD_FaceInd fi, - vector<LOD_EdgeInd> &output -){ - const vector<LOD_TriFace> &faces = FaceSet(); - vector<LOD_Edge> &edges = EdgeSet(); - vector<LOD_Vertex> &verts = VertexSet(); - - const LOD_TriFace & f = faces[fi]; - // intersect vertex edges - - vector<LOD_EdgeInd> & v0_edges = verts[f.m_verts[0]].m_edges; - vector<LOD_EdgeInd> & v1_edges = verts[f.m_verts[1]].m_edges; - vector<LOD_EdgeInd> & v2_edges = verts[f.m_verts[2]].m_edges; - - CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::IntersectPair(v0_edges,v1_edges,edges,output); - CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::IntersectPair(v1_edges,v2_edges,edges,output); - CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::IntersectPair(v2_edges,v0_edges,edges,output); - - MT_assert(output.size() == 3); - if (output.size() != 3) { - LOD_MeshException e(LOD_MeshException::e_non_manifold); - throw(e); - } -} - - -// edge queries -/////////////// - - void -LOD_ManMesh2:: -EdgeVertices( - LOD_EdgeInd ei, - vector<LOD_VertexInd> &output -){ - const vector<LOD_Edge> &edges = EdgeSet(); - const LOD_Edge & e = edges[ei]; - - output.push_back(e.m_verts[0]); - output.push_back(e.m_verts[1]); -} - - void -LOD_ManMesh2:: -EdgeFaces( - LOD_EdgeInd ei, - vector<LOD_FaceInd> &output -){ - const vector<LOD_Edge> &edges = EdgeSet(); - const LOD_Edge & e = edges[ei]; - - if (!e.m_faces[0].IsEmpty()) { - output.push_back(e.m_faces[0]); - } - if (!e.m_faces[1].IsEmpty()) { - output.push_back(e.m_faces[1]); - } -} - -// vertex queries -///////////////// - - void -LOD_ManMesh2:: -VertexEdges( - LOD_VertexInd vi, - vector<LOD_EdgeInd> &output -){ - // iterate through the edges of v and push them onto the - // output - - vector<LOD_Vertex> &verts = VertexSet(); - - vector<LOD_EdgeInd> & v_edges = verts[vi].m_edges; - vector<LOD_EdgeInd>::iterator v_it = v_edges.begin(); - - for (; v_it != v_edges.end(); ++v_it) { - output.push_back(*v_it); - } -} - - void -LOD_ManMesh2:: -VertexFaces( - LOD_VertexInd vi, - vector<LOD_FaceInd> &output -){ - const vector<LOD_Vertex> &verts = VertexSet(); - vector<LOD_Edge> &edges = EdgeSet(); - vector<LOD_TriFace> &faces = FaceSet(); - - const vector<LOD_EdgeInd> &v_edges = verts[vi].m_edges; - vector<LOD_EdgeInd>::const_iterator e_it = v_edges.begin(); - - for (; e_it != v_edges.end(); ++e_it) { - - LOD_Edge &e = edges[*e_it]; - - if ((!e.m_faces[0].IsEmpty()) && (!faces[e.m_faces[0]].SelectTag())) { - output.push_back(e.m_faces[0]); - faces[e.m_faces[0]].SetSelectTag(true); - } - - if ((!e.m_faces[1].IsEmpty()) && (!faces[e.m_faces[1]].SelectTag())) { - output.push_back(e.m_faces[1]); - faces[e.m_faces[1]].SetSelectTag(true); - } - } - - vector<LOD_FaceInd>::iterator f_it = output.begin(); - - for (; f_it != output.end(); ++f_it) { - faces[*f_it].SetSelectTag(false); - } -}; - - void -LOD_ManMesh2:: -SetBBox( - MT_Vector3 bbox_min, - MT_Vector3 bbox_max -){ - m_bbox_min = bbox_min; - m_bbox_max = bbox_max; -}; - - void -LOD_ManMesh2:: -SC_TriFace( - LOD_FaceInd f -){ - LOD_TriFace face = (*m_faces)[f]; - - // check for unique vertices - - if ( - (face.m_verts[0] == face.m_verts[1]) || - (face.m_verts[1] == face.m_verts[2]) || - (face.m_verts[2] == face.m_verts[0]) - ) { - MT_assert(false); - } - -} - - - void -LOD_ManMesh2:: -SC_EdgeList( - LOD_VertexInd v -){ - vector<LOD_Edge> &edges = EdgeSet(); - vector<LOD_Vertex> &verts = VertexSet(); - - vector<LOD_EdgeInd>::iterator e_it = verts[v].m_edges.begin(); - - for (;e_it != verts[v].m_edges.end(); ++e_it) { - MT_assert( (edges[*e_it].m_verts[0] == v) || (edges[*e_it].m_verts[1] == v)); - } - -}; - - void -LOD_ManMesh2:: -DeleteVertex( - LOD_ExternBufferEditor & extern_editor, - LOD_VertexInd v -){ - - vector<LOD_Edge> &edges = EdgeSet(); - vector<LOD_Vertex> &verts = VertexSet(); - vector<LOD_TriFace> &faces = FaceSet(); - - // need to update all the edge and polygons pointing to - // the last vertex in m_verts - - if (verts.size() == 1) { - verts.clear(); - return; - } - - LOD_VertexInd last = LOD_VertexInd(size_t(verts.end() - verts.begin() - 1)); - - if (!(last == v)) { - - // we asume that v is already disconnected - - vector<LOD_FaceInd> v_faces; - vector<LOD_EdgeInd> v_edges; - - v_faces.reserve(64); - v_edges.reserve(64); - - VertexFaces(last,v_faces); - VertexEdges(last,v_edges); - - // map the faces and edges to look at v - - vector<LOD_FaceInd>::iterator face_it = v_faces.begin(); - - for(; face_it != v_faces.end(); ++face_it) { - faces[*face_it].SwapVertex(last,v); - } - vector<LOD_EdgeInd>::iterator edge_it = v_edges.begin(); - - for (; edge_it != v_edges.end(); ++edge_it) { - edges[*edge_it].SwapVertex(last,v); - } - - // copy the last vertex onto v and pop off the back. - - verts[v] = verts[last]; - - // tidy external buffer - extern_editor.CopyModifiedFaces(*this,v_faces); - } - - verts.pop_back(); - extern_editor.CopyBackVertex(v); - - -}; - - void -LOD_ManMesh2:: -DeleteEdge( - LOD_EdgeInd e, - CTR_UHeap<LOD_Edge> * heap -){ - vector<LOD_Edge> &edges = EdgeSet(); - vector<LOD_Vertex> &verts = VertexSet(); - - if (edges.size() == 1) { - edges.clear(); - return; - } - - LOD_EdgeInd last = LOD_EdgeInd(size_t(edges.end() - edges.begin() - 1)); - - if (!(last == e)) { - vector<LOD_EdgeInd> e_verts; - e_verts.reserve(2); - EdgeVertices(last,e_verts); - // something is wrong if there arent two! - - verts[e_verts[0]].SwapEdge(last,e); - verts[e_verts[1]].SwapEdge(last,e); - - // edges[e] should already have been removed from the heap - - MT_assert(edges[e].HeapPos() == -1); - - edges[e] = edges[last]; - // also have to swap there heap positions.!!!!! - - heap->HeapVector()[edges[e].HeapPos()] = e; - - - } - edges.pop_back(); -}; - - void -LOD_ManMesh2:: -DeleteFace( - LOD_ExternBufferEditor & extern_editor, - LOD_FaceInd f -){ - - vector<LOD_Edge> &edges = EdgeSet(); - vector<LOD_TriFace> &faces = FaceSet(); - - if (faces.size() == 1) { - faces.clear(); - return; - } - - LOD_FaceInd last = LOD_FaceInd(size_t (faces.end() - faces.begin() - 1)); - - if (!(last == f)) { - - // we have to update the edges which point to the last - // face - - vector<LOD_EdgeInd> f_edges; - f_edges.reserve(3); - - FaceEdges(last,f_edges); - - vector<LOD_EdgeInd>::iterator edge_it = f_edges.begin(); - vector<LOD_EdgeInd>::const_iterator edge_end = f_edges.end(); - - for (; edge_it != edge_end; ++edge_it) { - edges[*edge_it].SwapFace(last,f); - } - - faces[f] = faces[last]; - - } - faces.pop_back(); - - // tidy external buffers - extern_editor.CopyBackFace(f); -}; - - - - - - - - - - - - - - - - diff --git a/intern/decimation/intern/LOD_ManMesh2.h b/intern/decimation/intern/LOD_ManMesh2.h deleted file mode 100644 index 5d4e1aff4e6..00000000000 --- a/intern/decimation/intern/LOD_ManMesh2.h +++ /dev/null @@ -1,265 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_ManMesh2.h - * \ingroup decimation - */ - - -#ifndef __LOD_MANMESH2_H__ -#define __LOD_MANMESH2_H__ - -#include "LOD_MeshPrimitives.h" -#include "MEM_SmartPtr.h" -#include <vector> - -template <class HeapType> class CTR_UHeap; - -class LOD_ExternBufferEditor; - -class LOD_ManMesh2 // Manifold 2 dimensional mesh -{ - -public: - - static - LOD_ManMesh2 * - New( - ); - - // take ownership of the vertices. - - bool - SetVertices( - MEM_SmartPtr<std::vector<LOD_Vertex> > verts - ); - - // Add a triangle to the mesh - - void - AddTriangle( - int verts[3] - ); - - void - ConnectTriangle( - LOD_FaceInd fi, - std::vector<LOD_EdgeInd> & new_edges - ); - - // geometry access - ////////////////// - - std::vector<LOD_Vertex> & - VertexSet( - ) const; - - std::vector<LOD_TriFace> & - FaceSet( - ) const; - - std::vector<LOD_Edge> & - EdgeSet( - ) const; - - ~LOD_ManMesh2( - ); - - // local geometry queries - ///////////////////////// - - // face queries - /////////////// - - void - FaceVertices( - LOD_FaceInd f, - std::vector<LOD_VertexInd> &output - ); - - void - FaceEdges( - LOD_FaceInd f, - std::vector<LOD_EdgeInd> &output - ); - - // edge queries - /////////////// - - void - EdgeVertices( - LOD_EdgeInd e, - std::vector<LOD_VertexInd> &output - ); - - void - EdgeFaces( - LOD_EdgeInd e, - std::vector<LOD_FaceInd> &output - ); - - // vertex queries - ///////////////// - - void - VertexEdges( - LOD_VertexInd v, - std::vector<LOD_EdgeInd> &output - ); - - void - VertexFaces( - LOD_VertexInd v, - std::vector<LOD_FaceInd> &output - ); - - void - SetBBox( - MT_Vector3 bbox_min, - MT_Vector3 bbox_max - ); - - MT_Vector3 - BBoxMin( - ) const { - return m_bbox_min; - }; - - MT_Vector3 - BBoxMax( - ) const { - return m_bbox_max; - }; - - // Remove a primitive from the mesh - /////////////////////////////////// - - // These methods assume you have correctly - // tidied up the index pointers in other primitives, - // so that nothing refers to this object any more - - // These methods exchange the primitive with the - // last primitive in the vector. It modifies everything - // pointing to the last primitive correctly. - - // FIXME refactor extern editor out of primitive deletion - // insead return a vector of primitives that need to be - // modified and do this externally - - void - DeleteVertex( - LOD_ExternBufferEditor & extern_editor, - LOD_VertexInd v - ); - - void - DeleteEdge( - LOD_EdgeInd e, - CTR_UHeap<LOD_Edge> *heap - ); - - void - DeleteFace( - LOD_ExternBufferEditor & extern_editor, - LOD_FaceInd f - ); - - // Sanity Check routines - //////////////////////// - - // Make sure the edge sets and the vertex sets are - // consistent - - void - SC_TriFace( - LOD_FaceInd f - ); - - // basic sanity checking of an edge list bails out if there are more than 1024 - // edges - - void - SC_EdgeList( - LOD_EdgeInd e - ); - - - // Check to see that the edges of v1 and v2 are unique. - - bool - SC_UniqueEdge( - LOD_EdgeInd e - ); - - -private : - - - // Returns the edge index of the edge from v1 to v2. - // Does this by searching the edge sets of v1 - but not v2. - // If you are paranoid you should check both and make sure the - // indices are the same. If the edge doe not exist edgeInd is empty. - - LOD_EdgeInd - FindEdge( - const LOD_VertexInd v1, - const LOD_VertexInd v2 - ); - - // Insert an edge into the mesh - // Tie up the ptrs and create space for the edge - // returns manifold errors - need to sort out memory edges - - bool - InsertEdge( - const LOD_VertexInd v1, - const LOD_VertexInd v2, - const LOD_FaceInd f, - std::vector<LOD_EdgeInd> &new_edges - ); - - -private : - - LOD_ManMesh2( - ); - - MEM_SmartPtr< std::vector<LOD_Vertex> > m_verts; - MEM_SmartPtr< std::vector<LOD_TriFace> > m_faces; - MEM_SmartPtr< std::vector<LOD_Edge> > m_edges; - - // not sure of these descrtiptions of the mesh should - // reside in this class coz may lead to very bloated interface. - - MT_Vector3 m_bbox_min; - MT_Vector3 m_bbox_max; - - -}; - -#endif - diff --git a/intern/decimation/intern/LOD_MeshBounds.h b/intern/decimation/intern/LOD_MeshBounds.h deleted file mode 100644 index c95e6c7b61f..00000000000 --- a/intern/decimation/intern/LOD_MeshBounds.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_MeshBounds.h - * \ingroup decimation - */ - - -#ifndef __LOD_MESHBOUNDS_H__ -#define __LOD_MESHBOUNDS_H__ - -#include "MEM_SmartPtr.h" -#include "LOD_MeshPrimitives.h" -#include "LOD_ManMesh2.h" -#include "MT_assert.h" - -// simple class to compute the mesh bounds of a manifold mesh, - -class LOD_MeshBounds { - -public : - static - LOD_MeshBounds * - New( - ){ - - MEM_SmartPtr<LOD_MeshBounds> output(new LOD_MeshBounds()); - return output.Release(); - } - - void - ComputeBounds( - const LOD_ManMesh2 * mesh - ){ - MT_assert(mesh!=NULL); - MT_assert(mesh->VertexSet().size() > 0); - - const std::vector<LOD_Vertex> &verts = mesh->VertexSet(); - - m_min = verts[0].pos; - m_max = verts[0].pos; - - // iterate through the verts - - int t; - const int size = verts.size(); - - for (t=1; t< size ; ++t) { - - UpdateBounds(verts[t].pos,m_min,m_max); - } - } - - MT_Vector3 - Min( - ) const { - return m_min; - } - - MT_Vector3 - Max( - ) const { - return m_max; - } - -private : - - void - UpdateBounds( - MT_Vector3 vertex, - MT_Vector3& min, - MT_Vector3& max - ) { - if (vertex.x() < min.x()) { - min.x() = vertex.x(); - } else - if (vertex.x() > max.x()) { - max.x()= vertex.x(); - } - - if (vertex.y() < min.y()) { - min.y() = vertex.y(); - } else - if (vertex.y() > max.y()) { - max.y()= vertex.y(); - } - - if (vertex.z() < min.z()) { - min.z() = vertex.z(); - } else - if (vertex.z() > max.z()) { - max.z()= vertex.z(); - } - } - - LOD_MeshBounds( - ) : - m_min(0,0,0), - m_max(0,0,0) - { - }; - - MT_Vector3 m_min; - MT_Vector3 m_max; - -}; - -#endif - diff --git a/intern/decimation/intern/LOD_MeshException.h b/intern/decimation/intern/LOD_MeshException.h deleted file mode 100644 index 67bd8188c41..00000000000 --- a/intern/decimation/intern/LOD_MeshException.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_MeshException.h - * \ingroup decimation - */ - - -#ifndef __LOD_MESHEXCEPTION_H__ -#define __LOD_MESHEXCEPTION_H__ - -class LOD_MeshException { - -public : - - // stick in more error types as you think of them - - enum ExceptionType{ - e_non_manifold, - e_search_error - } m_e_type; - - LOD_MeshException ( - ExceptionType type - ) : m_e_type (type) - { - } -}; - -#endif - diff --git a/intern/decimation/intern/LOD_MeshPrimitives.cpp b/intern/decimation/intern/LOD_MeshPrimitives.cpp deleted file mode 100644 index ee4e4c120fc..00000000000 --- a/intern/decimation/intern/LOD_MeshPrimitives.cpp +++ /dev/null @@ -1,404 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_MeshPrimitives.cpp - * \ingroup decimation - */ - - -#include "LOD_MeshPrimitives.h" - -#include "MT_assert.h" -#include "LOD_MeshException.h" -#include <algorithm> - -using namespace std; - -// Vertex Methods -///////////////// - -LOD_Vertex:: -LOD_Vertex( -) : - pos (MT_Vector3()), - m_select_tag(false) -{ -}; - - bool -LOD_Vertex:: -RemoveEdge( - LOD_EdgeInd e -){ - - vector<LOD_EdgeInd>::iterator result = find(m_edges.begin(),m_edges.end(),e); - if (result == m_edges.end()) { - return false; - } - - std::swap(*result, m_edges.back()); - m_edges.pop_back(); - return true; -}; - - void -LOD_Vertex:: -AddEdge( - LOD_EdgeInd e -){ - m_edges.push_back(e); -}; - - void -LOD_Vertex:: -SwapEdge( - LOD_EdgeInd e_old, - LOD_EdgeInd e_new -){ - - vector<LOD_EdgeInd>::iterator result = - find(m_edges.begin(),m_edges.end(),e_old); - if (result == m_edges.end()) { - MT_assert(false); - LOD_MeshException e(LOD_MeshException::e_search_error); - throw(e); - } - - *result = e_new; -}; - - bool -LOD_Vertex:: -SelectTag( -) const { - return m_select_tag; -}; - - void -LOD_Vertex:: -SetSelectTag( - bool tag -){ - m_select_tag = tag; -}; - - bool -LOD_Vertex:: -Degenerate( -){ - return m_edges.empty(); -} - - void -LOD_Vertex:: -CopyPosition( - float *float_ptr -){ - pos.getValue(float_ptr); -} - - - -// Edge Methods -/////////////// - -LOD_Edge:: -LOD_Edge ( -) { - m_verts[0] = m_verts[1] = LOD_VertexInd::Empty(); - m_faces[0] = m_faces[1] = LOD_FaceInd::Empty(); -} - - bool -LOD_Edge:: -operator == ( - LOD_Edge & rhs -) { - // edges are the same if their vertex indices are the - // same!!! Other properties are not checked - - int matches = 0; - - if (this->m_verts[0] == rhs.m_verts[0]) { - ++matches; - } - if (this->m_verts[1] == rhs.m_verts[0]) { - ++matches; - } - if (this->m_verts[0] == rhs.m_verts[1]) { - ++matches; - } - if (this->m_verts[1] == rhs.m_verts[1]) { - ++matches; - } - - if (matches >= 2) { - return true; - } - return false; -} - -// Elementary helper methods -//////////////////////////// - - LOD_FaceInd -LOD_Edge:: -OpFace( - LOD_FaceInd f -) const { - if (f == m_faces[0]) { - return m_faces[1]; - } else - if (f == m_faces[1]) { - return m_faces[0]; - } else { - MT_assert(false); - LOD_MeshException e(LOD_MeshException::e_search_error); - throw(e); - - return LOD_FaceInd::Empty(); - } -} - - void -LOD_Edge:: -SwapFace( - LOD_FaceInd old_f, - LOD_FaceInd new_f -) { - if (old_f == m_faces[0]) { - m_faces[0] = new_f; - } else - if (old_f == m_faces[1]) { - m_faces[1] = new_f; - } else { - LOD_MeshException e(LOD_MeshException::e_search_error); - throw(e); - } -} - - -// return the half edge face - the half edge is defined -// by the {vertex,edge} tuple. - - LOD_FaceInd -LOD_Edge:: -HalfEdgeFace( - LOD_VertexInd vi -){ - if (vi == m_verts[0]) return m_faces[0]; - if (vi == m_verts[1]) return m_faces[1]; - MT_assert(false); - - LOD_MeshException e(LOD_MeshException::e_search_error); - throw(e); - - return LOD_FaceInd::Empty(); -} - - - LOD_VertexInd -LOD_Edge:: -OpVertex( - LOD_VertexInd vi -) { - if (vi == m_verts[0]) return m_verts[1]; - if (vi == m_verts[1]) return m_verts[0]; - MT_assert(false); - - LOD_MeshException e(LOD_MeshException::e_search_error); - throw(e); - - return LOD_VertexInd::Empty(); -} - -// replace the vertex v_old with vertex v_new -// error if v_old is not one of the original vertices - - void -LOD_Edge:: -SwapVertex( - LOD_VertexInd v_old, - LOD_VertexInd v_new -) { - if (v_old == m_verts[0]) { - m_verts[0] = v_new; - } else - if (v_old == m_verts[1]) { - m_verts[1] = v_new; - } else { - - MT_assert(false); - - LOD_MeshException e(LOD_MeshException::e_search_error); - throw(e); - } - if(m_verts[0] == m_verts[1]) { - MT_assert(false); - - LOD_MeshException e(LOD_MeshException::e_non_manifold); - throw(e); - } - -} - - bool -LOD_Edge:: -SelectTag( -) const { - return bool(m_verts[1].Tag() & 0x1); -}; - - void -LOD_Edge:: -SetSelectTag( - bool tag -) { - m_verts[1].SetTag(int(tag)); -}; - - int -LOD_Edge:: -OpenTag( -) const { - return m_faces[0].Tag(); -} - - void -LOD_Edge:: -SetOpenTag( - int tag -) { - m_faces[0].SetTag(tag); -} - - bool -LOD_Edge:: -Degenerate( -) const { - return ( - (m_faces[0].IsEmpty() && m_faces[1].IsEmpty()) || - (m_verts[0] == m_verts[1]) - ); -}; - -// TriFace Methods -////////////////// - -LOD_TriFace:: -LOD_TriFace( -) { - m_verts[0] = m_verts[1] = m_verts[2] = LOD_VertexInd::Empty(); -} - -// Elementary helper methods -//////////////////////////// - - void -LOD_TriFace:: -SwapVertex( - LOD_VertexInd old_v, - LOD_VertexInd new_v -) { - // could save branching here... - - if (m_verts[0] == old_v) { - m_verts[0] = new_v; - } else - if (m_verts[1] == old_v) { - m_verts[1] = new_v; - } else - if (m_verts[2] == old_v) { - m_verts[2] = new_v; - } else { - MT_assert(false); - - LOD_MeshException excep(LOD_MeshException::e_search_error); - throw(excep); - } -} - - bool -LOD_TriFace:: -SelectTag( -) const { - return bool(m_verts[1].Tag() & 0x1); -}; - - void -LOD_TriFace:: -SetSelectTag( - bool tag -) { - m_verts[1].SetTag(int(tag)); -}; - - int -LOD_TriFace:: -OpenTag( -) { - return m_verts[2].Tag(); -} - - void -LOD_TriFace:: -SetOpenTag( - int tag -) { - m_verts[2].SetTag(tag); -} - - bool -LOD_TriFace:: -Degenerate( -) { - - return ( - (m_verts[0] == m_verts[1]) || - (m_verts[1] == m_verts[2]) || - (m_verts[2] == m_verts[0]) - ); -} - - void -LOD_TriFace:: -CopyVerts( - int * index_ptr -){ - index_ptr[0] = m_verts[0]; - index_ptr[1] = m_verts[1]; - index_ptr[2] = m_verts[2]; -}; - - - - - - - - - diff --git a/intern/decimation/intern/LOD_MeshPrimitives.h b/intern/decimation/intern/LOD_MeshPrimitives.h deleted file mode 100644 index ea2d157308b..00000000000 --- a/intern/decimation/intern/LOD_MeshPrimitives.h +++ /dev/null @@ -1,221 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_MeshPrimitives.h - * \ingroup decimation - */ - - -#ifndef __LOD_MESHPRIMITIVES_H__ -#define __LOD_MESHPRIMITIVES_H__ - -#include "MT_Vector3.h" -#include "CTR_TaggedIndex.h" -#include "CTR_UHeap.h" -#include <vector> - -typedef CTR_TaggedIndex<24,0x00ffffff> LOD_VertexInd; -typedef CTR_TaggedIndex<24,0x00ffffff> LOD_EdgeInd; -typedef CTR_TaggedIndex<24,0x00ffffff> LOD_FaceInd; -typedef CTR_TaggedIndex<24,0x00ffffff> LOD_HeapInd; - -class LOD_Vertex { -public : - MT_Vector3 pos; - std::vector<LOD_EdgeInd> m_edges; - bool m_select_tag; - - LOD_Vertex( - ); - - bool - RemoveEdge( - LOD_EdgeInd e - ); - - void - AddEdge( - LOD_EdgeInd e - ); - - void - SwapEdge( - LOD_EdgeInd e_old, - LOD_EdgeInd e_new - ); - - bool - SelectTag( - ) const; - - void - SetSelectTag( - bool tag - ); - - bool - Degenerate( - ); - - void - CopyPosition( - float *float_ptr - ); - -private : - - -}; - -class LOD_Edge : public CTR_UHeapable { -public : - LOD_VertexInd m_verts[2]; - LOD_FaceInd m_faces[2]; - - LOD_Edge ( - ); - - bool operator == ( - LOD_Edge & rhs - ); - - // Elementary helper methods - //////////////////////////// - - LOD_FaceInd - OpFace( - LOD_FaceInd f - ) const; - - void - SwapFace( - LOD_FaceInd old_f, - LOD_FaceInd new_f - ); - - - // return the half edge face - the half edge is defined - // by the {vertex,edge} tuple. - - LOD_FaceInd - HalfEdgeFace( - LOD_VertexInd vi - ); - - - LOD_VertexInd - OpVertex( - LOD_VertexInd vi - ); - - // replace the vertex v_old with vertex v_new - // error if v_old is not one of the original vertices - - void - SwapVertex( - LOD_VertexInd v_old, - LOD_VertexInd v_new - ); - - bool - SelectTag( - ) const; - - void - SetSelectTag( - bool tag - ); - - int - OpenTag( - ) const; - - void - SetOpenTag( - int tag - ); - - bool - Degenerate( - ) const; - - bool - BoundaryEdge( - ) const { - return (m_faces[0].IsEmpty() || m_faces[1].IsEmpty()); - }; - - -}; - -class LOD_TriFace { -public: - - LOD_VertexInd m_verts[3]; - - LOD_TriFace( - ); - - // Elementary helper methods - //////////////////////////// - - void - SwapVertex( - LOD_VertexInd old_v, - LOD_VertexInd new_v - ); - - bool - SelectTag( - ) const; - - void - SetSelectTag( - bool tag - ); - - int - OpenTag( - ); - void - SetOpenTag( - int tag - ); - - bool - Degenerate( - ); - - void - CopyVerts( - int * index_ptr - ); - -}; - -#endif - diff --git a/intern/decimation/intern/LOD_QSDecimator.cpp b/intern/decimation/intern/LOD_QSDecimator.cpp deleted file mode 100644 index bdcf7950447..00000000000 --- a/intern/decimation/intern/LOD_QSDecimator.cpp +++ /dev/null @@ -1,327 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_QSDecimator.cpp - * \ingroup decimation - */ - - -#include "LOD_QSDecimator.h" - -#include "LOD_ExternBufferEditor.h" - -using namespace std; - - LOD_QSDecimator * -LOD_QSDecimator:: -New( - LOD_ManMesh2 &mesh, - LOD_ExternNormalEditor &face_editor, - LOD_ExternBufferEditor &extern_editor -){ - - MEM_SmartPtr<LOD_QSDecimator> output - = new LOD_QSDecimator(mesh,face_editor,extern_editor); - - MEM_SmartPtr<LOD_EdgeCollapser > collapser(LOD_EdgeCollapser::New()); - MEM_SmartPtr<LOD_QuadricEditor> q_editor(LOD_QuadricEditor::New(mesh)); - - if ( - output == NULL || - collapser == NULL || - q_editor == NULL - ) { - return NULL; - } - output->m_collapser = collapser.Release(); - output->m_quadric_editor = q_editor.Release(); - return output.Release(); -} - - - - bool -LOD_QSDecimator:: -Arm( -){ - MT_assert(!m_is_armed); - bool heap_result = BuildHeap(); - if (!heap_result) { - return false; - } - m_is_armed = true; - return true; -} - - bool -LOD_QSDecimator:: -Step( -){ - return CollapseEdge(); -} - - -LOD_QSDecimator:: -LOD_QSDecimator( - LOD_ManMesh2 &mesh, - LOD_ExternNormalEditor &face_editor, - LOD_ExternBufferEditor &extern_editor -) : - m_is_armed (false), - m_mesh(mesh), - m_face_editor(face_editor), - m_extern_editor(extern_editor) -{ - m_deg_edges.reserve(32); - m_deg_faces.reserve(32); - m_deg_vertices.reserve(32); - m_update_faces.reserve(32); - m_new_edges.reserve(32); - m_update_vertices.reserve(32); -}; - - bool -LOD_QSDecimator:: -CollapseEdge( -){ - - // find an edge to collapse - - // FIXME force an edge collapse - // or return false - - std::vector<LOD_Edge> & edges = m_mesh.EdgeSet(); - std::vector<LOD_Vertex> & verts = m_mesh.VertexSet(); - std::vector<LOD_Quadric> & quadrics = m_quadric_editor->Quadrics(); - int size = edges.size(); - - if (size == 0) return false; - - const int heap_top = m_heap->Top(); - - if (heap_top == -1 || edges[heap_top].HeapKey() <= -MT_INFINITY) { - return false; - } - - // compute the target position - MT_Vector3 new_vertex = m_quadric_editor->TargetVertex(edges[heap_top]); - LOD_Quadric & q0 = quadrics[edges[heap_top].m_verts[0]]; - LOD_Quadric & q1 = quadrics[edges[heap_top].m_verts[1]]; - - LOD_Vertex &v0 = verts[edges[heap_top].m_verts[0]]; - LOD_Vertex &v1 = verts[edges[heap_top].m_verts[1]]; - - LOD_Quadric sum = q0; - sum += q1; - - - if (m_collapser->CollapseEdge( - heap_top, - m_mesh, - m_deg_edges, - m_deg_faces, - m_deg_vertices, - m_new_edges, - m_update_faces, - m_update_vertices - )) { - - // assign new vertex position - - v0.pos = new_vertex; - v1.pos = new_vertex; - - // sum the quadrics of v0 and v1 - q0 = sum; - q1 = sum; - - // ok update the primitive properties - - m_face_editor.Update(m_update_faces); - m_face_editor.UpdateVertexNormals(m_update_vertices); - - // update the external vertex buffer - m_extern_editor.CopyModifiedVerts(m_mesh,m_update_vertices); - - // update the external face buffer - m_extern_editor.CopyModifiedFaces(m_mesh,m_update_faces); - - // update the edge heap - UpdateHeap(m_deg_edges,m_new_edges); - - m_quadric_editor->Remove(m_deg_vertices); - m_face_editor.Remove(m_deg_faces); - m_face_editor.RemoveVertexNormals(m_deg_vertices); - - // delete the primitives - - DeletePrimitives(m_deg_edges,m_deg_faces,m_deg_vertices); - - } else { - // the edge could not be collapsed at the moment - so - // we adjust it's priority and add it back to the heap. - m_heap->Remove(&edges[0],0); - edges[heap_top].HeapKey() = - MT_INFINITY; - m_heap->Insert(&edges[0],heap_top); - } - - //clear all the temporary buffers - - m_deg_faces.clear(); - m_deg_edges.clear(); - m_deg_vertices.clear(); - - m_update_faces.clear(); - m_update_vertices.clear(); - m_new_edges.clear(); - - return true; - -} - - void -LOD_QSDecimator:: -DeletePrimitives( - const vector<LOD_EdgeInd> & degenerate_edges, - const vector<LOD_FaceInd> & degenerate_faces, - const vector<LOD_VertexInd> & degenerate_vertices -) { - - // assumes that the 3 vectors are sorted in descending order. - - // Delete Degnerate primitives - ////////////////////////////// - - - // delete the old edges - we have to be very careful here - // mesh.delete() swaps edges to be deleted with the last edge in - // the edge buffer. However the next edge to be deleted may have - // been the last edge in the buffer! - - // One way to solve this is to sort degenerate_edges in descending order. - // And then delete them in that order. - - // it is also vital that degenerate_edges contains no duplicates - - vector<LOD_EdgeInd>::const_iterator edge_it = degenerate_edges.begin(); - vector<LOD_EdgeInd>::const_iterator edge_end = degenerate_edges.end(); - - for (; edge_it != edge_end; ++edge_it) { - m_mesh.DeleteEdge(*edge_it,m_heap); - } - - - - vector<LOD_FaceInd>::const_iterator face_it = degenerate_faces.begin(); - vector<LOD_FaceInd>::const_iterator face_end = degenerate_faces.end(); - - for (;face_it != face_end; ++face_it) { - m_mesh.DeleteFace(m_extern_editor,*face_it); - } - - vector<LOD_VertexInd>::const_iterator vertex_it = degenerate_vertices.begin(); - vector<LOD_VertexInd>::const_iterator vertex_end = degenerate_vertices.end(); - - for (;vertex_it != vertex_end; ++vertex_it) { - m_mesh.DeleteVertex(m_extern_editor,*vertex_it); - } -} - - - bool -LOD_QSDecimator:: -BuildHeap( -){ - // build the quadrics - - if (m_quadric_editor->BuildQuadrics(m_face_editor,true) == false) return false; - - - m_heap = CTR_UHeap<LOD_Edge>::New(); - // load in edge pointers to the heap - - std::vector<LOD_Edge> & edge_set= m_mesh.EdgeSet(); - - // UNUSED - // std::vector<LOD_Edge>::const_iterator edge_end = edge_set.end(); - // std::vector<LOD_Edge>::iterator edge_start = edge_set.begin(); - - std::vector<int> & heap_vector = m_heap->HeapVector(); - - for (unsigned int i = 0; i < edge_set.size(); ++i) { - edge_set[i].HeapPos() = i; - heap_vector.push_back(i); - } - - m_heap->MakeHeap(&edge_set[0]); - - return true; -} - - void -LOD_QSDecimator:: -UpdateHeap( - std::vector<LOD_EdgeInd> °_edges, - std::vector<LOD_EdgeInd> &new_edges -){ - // first of all compute values for the new edges - // and bung them on the heap. - - std::vector<LOD_Edge> & edge_set= m_mesh.EdgeSet(); - - std::vector<LOD_EdgeInd>::const_iterator edge_it = new_edges.begin(); - std::vector<LOD_EdgeInd>::const_iterator end_it = new_edges.end(); - - - // insert all the new edges - /////////////////////////// - - // compute edge costs ffor the new edges - - m_quadric_editor->ComputeEdgeCosts(new_edges); - - // inser the new elements into the heap - - for (; edge_it != end_it; ++edge_it) { - m_heap->Insert(&edge_set[0],*edge_it); - } - - - // remove all the old values from the heap - - edge_it = deg_edges.begin(); - end_it = deg_edges.end(); - - for (; edge_it != end_it; ++edge_it) { - LOD_Edge &e = edge_set[*edge_it]; - m_heap->Remove(&edge_set[0],e.HeapPos()); - - e.HeapPos() = -1; - - } -} - diff --git a/intern/decimation/intern/LOD_QSDecimator.h b/intern/decimation/intern/LOD_QSDecimator.h deleted file mode 100644 index 2ac223996f2..00000000000 --- a/intern/decimation/intern/LOD_QSDecimator.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_QSDecimator.h - * \ingroup decimation - */ - - -#ifndef __LOD_QSDECIMATOR_H__ -#define __LOD_QSDECIMATOR_H__ - -#include "MEM_NonCopyable.h" -#include "LOD_ManMesh2.h" -#include "LOD_ExternNormalEditor.h" -#include "LOD_EdgeCollapser.h" -#include "LOD_QuadricEditor.h" - -class LOD_ExternBufferEditor; - -class LOD_QSDecimator : public MEM_NonCopyable { - -public : - - static - LOD_QSDecimator * - New( - LOD_ManMesh2 &mesh, - LOD_ExternNormalEditor &face_editor, - LOD_ExternBufferEditor &extern_editor - ); - - - bool - Arm( - ); - - - bool - Step( - ); - -private : - - LOD_QSDecimator( - LOD_ManMesh2 &mesh, - LOD_ExternNormalEditor &face_editor, - LOD_ExternBufferEditor &extern_editor - ); - - bool - CollapseEdge( - ); - - bool - BuildHeap( - ); - - void - UpdateHeap( - std::vector<LOD_EdgeInd> °_edges, - std::vector<LOD_EdgeInd> &new_edges - ); - - void - DeletePrimitives( - const std::vector<LOD_EdgeInd> & degenerate_edges, - const std::vector<LOD_FaceInd> & degenerate_faces, - const std::vector<LOD_VertexInd> & degenerate_vertices - ); - - -private : - - // owned by this class - ////////////////////// - - MEM_SmartPtr<LOD_EdgeCollapser> m_collapser; - MEM_SmartPtr<CTR_UHeap<LOD_Edge> > m_heap; - MEM_SmartPtr<LOD_QuadricEditor> m_quadric_editor; - - bool m_is_armed; - - // arguments to New(...) - //////////////////////// - - LOD_ManMesh2 & m_mesh; - LOD_ExternNormalEditor &m_face_editor; - LOD_ExternBufferEditor & m_extern_editor; - - // temporary buffers - //////////////////// - - std::vector<LOD_FaceInd> m_deg_faces; - std::vector<LOD_EdgeInd> m_deg_edges; - std::vector<LOD_VertexInd> m_deg_vertices; - - std::vector<LOD_FaceInd> m_update_faces; - std::vector<LOD_EdgeInd> m_new_edges; - std::vector<LOD_VertexInd> m_update_vertices; - - -}; - -#endif - diff --git a/intern/decimation/intern/LOD_Quadric.h b/intern/decimation/intern/LOD_Quadric.h deleted file mode 100644 index 9dde0502aa3..00000000000 --- a/intern/decimation/intern/LOD_Quadric.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_Quadric.h - * \ingroup decimation - */ - - -#ifndef __LOD_QUADRIC_H__ -#define __LOD_QUADRIC_H__ - -#include "MT_Vector3.h" -#include "MT_Matrix3x3.h" - - -class LOD_Quadric { - -private: - MT_Scalar a2, ab, ac, ad; - MT_Scalar b2, bc, bd; - MT_Scalar c2, cd; - MT_Scalar d2; - - void init(MT_Scalar a, MT_Scalar b, MT_Scalar c, MT_Scalar d); - -public: - - LOD_Quadric( - ) { - Clear(); - }; - - LOD_Quadric( - const MT_Vector3 & vec, - const MT_Scalar & offset - ) { - a2 = vec[0] *vec[0]; - b2 = vec[1] *vec[1]; - c2 = vec[2] *vec[2]; - - ab = vec[0]*vec[1]; - ac = vec[0]*vec[2]; - bc = vec[1]*vec[2]; - - MT_Vector3 temp = vec*offset; - ad = temp[0]; - bd = temp[1]; - cd = temp[2]; - - d2 = offset*offset; - }; - - MT_Matrix3x3 - Tensor( - ) const { - // return a symmetric matrix - - return MT_Matrix3x3( - a2,ab,ac, - ab,b2,bc, - ac,bc,c2 - ); - }; - - - MT_Vector3 - Vector( - ) const { - return MT_Vector3(ad, bd, cd); - }; - - void - Clear( - MT_Scalar val=0.0 - ) { - a2=ab=ac=ad=b2=bc=bd=c2=cd=d2=val; - }; - - LOD_Quadric & - operator=( - const LOD_Quadric& Q - ) { - - a2 = Q.a2; ab = Q.ab; ac = Q.ac; ad = Q.ad; - b2 = Q.b2; bc = Q.bc; bd = Q.bd; - c2 = Q.c2; cd = Q.cd; - d2 = Q.d2; - return *this; - }; - - LOD_Quadric& - operator+=( - const LOD_Quadric& Q - ) { - a2 += Q.a2; ab += Q.ab; ac += Q.ac; ad += Q.ad; - b2 += Q.b2; bc += Q.bc; bd += Q.bd; - c2 += Q.c2; cd += Q.cd; - d2 += Q.d2; - return *this; - }; - - LOD_Quadric& - operator*=( - const MT_Scalar & s - ) { - a2 *= s; ab *= s; ac *= s; ad *= s; - b2 *= s; bc *= s; bd *= s; - c2 *= s; cd *= s; - d2 *= s; - return *this; - }; - - - MT_Scalar - Evaluate( - const MT_Vector3 &v - ) const { - // compute the LOD_Quadric error - - return v[0]*v[0]*a2 + 2*v[0]*v[1]*ab + 2*v[0]*v[2]*ac + 2*v[0]*ad - +v[1]*v[1]*b2 + 2*v[1]*v[2]*bc + 2*v[1]*bd - +v[2]*v[2]*c2 + 2*v[2]*cd - + d2; - }; - - bool - Optimize( - MT_Vector3& v - ) const { - - MT_Scalar det = Tensor().determinant(); - if (MT_fuzzyZero(det)) { - return false; - } - - v = -((Tensor().inverse()) * Vector()); - return true; - }; - -}; - -#endif - diff --git a/intern/decimation/intern/LOD_QuadricEditor.cpp b/intern/decimation/intern/LOD_QuadricEditor.cpp deleted file mode 100644 index fbaf0c1180f..00000000000 --- a/intern/decimation/intern/LOD_QuadricEditor.cpp +++ /dev/null @@ -1,279 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_QuadricEditor.cpp - * \ingroup decimation - */ - - -#include "LOD_QuadricEditor.h" -#include "LOD_ExternNormalEditor.h" - -// Creation -/////////// - -using namespace std; - - -LOD_QuadricEditor:: -LOD_QuadricEditor( - LOD_ManMesh2 &mesh -) : - m_quadrics(NULL), - m_mesh(mesh) -{ -}; - - LOD_QuadricEditor * -LOD_QuadricEditor:: -New( - LOD_ManMesh2 &mesh -){ - //same number of quadrics as vertices in the mesh - - MEM_SmartPtr<LOD_QuadricEditor> output(new LOD_QuadricEditor(mesh)); - - if (output == NULL) { - return NULL; - } - return output.Release(); -} - - -// Property editor interface -//////////////////////////// - - void -LOD_QuadricEditor:: -Remove( - std::vector<LOD_VertexInd> &sorted_vertices -){ - vector<LOD_Quadric> & quadrics = *m_quadrics; - - vector<LOD_VertexInd>::const_iterator it_start = sorted_vertices.begin(); - vector<LOD_VertexInd>::const_iterator it_end = sorted_vertices.end(); - - for (; it_start != it_end; ++it_start) { - - if (quadrics.size() > 0) { - LOD_Quadric temp = quadrics[*it_start]; - - quadrics[*it_start] = quadrics.back(); - quadrics.back() = temp; - - quadrics.pop_back(); - } - } -}; - - -// Editor specific methods -////////////////////////// - - bool -LOD_QuadricEditor:: -BuildQuadrics( - LOD_ExternNormalEditor& normal_editor, - bool preserve_boundaries -){ - if (m_quadrics != NULL) delete(m_quadrics); - - m_quadrics =new vector<LOD_Quadric> (m_mesh.VertexSet().size()); - if (m_quadrics == NULL) return false; - - // iterate through the face set of the mesh - // compute a quadric based upon that face and - // add it to each of it's vertices quadrics. - - const vector<LOD_TriFace> &faces = m_mesh.FaceSet(); - const vector<LOD_Vertex> &verts = m_mesh.VertexSet(); - vector<LOD_Edge> &edges = m_mesh.EdgeSet(); - - const vector<MT_Vector3> &normals = normal_editor.Normals(); - vector<MT_Vector3>::const_iterator normal_it = normals.begin(); - - vector<LOD_TriFace>::const_iterator face_it = faces.begin(); - vector<LOD_TriFace>::const_iterator face_end = faces.end(); - - vector<LOD_Quadric> & quadrics = *m_quadrics; - - - for (; face_it != face_end; ++face_it, ++normal_it) { - - MT_Vector3 normal = *normal_it; - MT_Scalar offset = -normal.dot(verts[face_it->m_verts[0]].pos); - - LOD_Quadric q(normal,offset); - - quadrics[face_it->m_verts[0]] += q; - quadrics[face_it->m_verts[1]] += q; - quadrics[face_it->m_verts[2]] += q; - } - - if (preserve_boundaries) { - - // iterate through the edge set and add a boundary quadric to - // each of the boundary edges vertices. - - vector<LOD_Edge>::const_iterator edge_it = edges.begin(); - vector<LOD_Edge>::const_iterator edge_end = edges.end(); - - for (; edge_it != edge_end; ++edge_it) { - if (edge_it->BoundaryEdge()) { - - // compute a plane perpendicular to the edge and the normal - // of the edges single polygon. - const MT_Vector3 & v0 = verts[edge_it->m_verts[0]].pos; - const MT_Vector3 & v1 = verts[edge_it->m_verts[1]].pos; - - MT_Vector3 edge_vector = v1 - v0; - - LOD_FaceInd edge_face = edge_it->OpFace(LOD_EdgeInd::Empty()); - edge_vector = edge_vector.cross(normals[edge_face]); - - if (!edge_vector.fuzzyZero()) { - edge_vector.normalize(); - - LOD_Quadric boundary_q(edge_vector, - edge_vector.dot(v0)); - boundary_q *= 100; - - quadrics[edge_it->m_verts[0]] += boundary_q; - quadrics[edge_it->m_verts[1]] += boundary_q; - } - } - } - } - - - // initiate the heap keys of the edges by computing the edge costs. - - vector<LOD_Edge>::iterator edge_it = edges.begin(); - vector<LOD_Edge>::const_iterator edge_end = edges.end(); - - for (; edge_it != edge_end; ++edge_it) { - - MT_Vector3 target = TargetVertex(*edge_it); - - LOD_Edge &e = *edge_it; - LOD_Quadric q0 = quadrics[e.m_verts[0]]; - const LOD_Quadric &q1 = quadrics[e.m_verts[1]]; - - e.HeapKey() = -float(q0.Evaluate(target) + q1.Evaluate(target)); - } - - return true; - -}; - - MT_Vector3 -LOD_QuadricEditor:: -TargetVertex( - LOD_Edge & e -){ - - // compute an edge contration target for edge ei - // this is computed by summing it's vertices quadrics and - // optimizing the result. - vector<LOD_Vertex> &verts = m_mesh.VertexSet(); - - vector<LOD_Quadric> &quadrics = *m_quadrics; - - LOD_VertexInd v0 = e.m_verts[0]; - LOD_VertexInd v1 = e.m_verts[1]; - - LOD_Quadric q0 = quadrics[v0]; - q0 += quadrics[v1]; - - MT_Vector3 result; - - if (q0.Optimize(result)) { - return result; - } else { - // the quadric was degenerate -> just take the average of - // v0 and v1 - - return ((verts[v0].pos + verts[v1].pos) * 0.5); - } -}; - - void -LOD_QuadricEditor:: -ComputeEdgeCosts( - vector<LOD_EdgeInd> &edges -){ - - // for each we compute the target vertex and then compute - // the quadric error e = Q1(v') + Q2(v') - vector<LOD_Edge> &edge_set = m_mesh.EdgeSet(); - - vector<LOD_Quadric> &quadrics = *m_quadrics; - - vector<LOD_EdgeInd>::const_iterator edge_it = edges.begin(); - vector<LOD_EdgeInd>::const_iterator edge_end = edges.end(); - - for (; edge_it != edge_end; ++edge_it) { - - MT_Vector3 target = TargetVertex(edge_set[*edge_it]); - - LOD_Edge &e = edge_set[*edge_it]; - LOD_Quadric q0 = quadrics[e.m_verts[0]]; - const LOD_Quadric &q1 = quadrics[e.m_verts[1]]; - - e.HeapKey() = -float(q0.Evaluate(target) + q1.Evaluate(target)); - } -}; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/intern/decimation/intern/LOD_QuadricEditor.h b/intern/decimation/intern/LOD_QuadricEditor.h deleted file mode 100644 index 0a66d299e15..00000000000 --- a/intern/decimation/intern/LOD_QuadricEditor.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_QuadricEditor.h - * \ingroup decimation - */ - - -#ifndef __LOD_QUADRICEDITOR_H__ -#define __LOD_QUADRICEDITOR_H__ - -#include "MEM_NonCopyable.h" -#include "LOD_ManMesh2.h" -#include "MT_Vector3.h" -#include "LOD_Quadric.h" - -class LOD_ExternNormalEditor; - - -class LOD_QuadricEditor : public MEM_NonCopyable -{ - -public : - - // Creation - /////////// - - static - LOD_QuadricEditor * - New( - LOD_ManMesh2 &mesh - ); - - // Property editor interface - //////////////////////////// - - void - Remove( - std::vector<LOD_VertexInd> &sorted_vertices - ); - - void - Update( - std::vector<LOD_FaceInd> &sorted_vertices - ); - - - std::vector<LOD_Quadric> & - Quadrics( - ) const { - return *m_quadrics; - }; - - - // Editor specific methods - ////////////////////////// - - bool - BuildQuadrics( - LOD_ExternNormalEditor& normal_editor, - bool preserve_boundaries - ); - - - void - ComputeEdgeCosts( - std::vector<LOD_EdgeInd> &edges - ); - - MT_Vector3 - TargetVertex( - LOD_Edge &e - ); - - ~LOD_QuadricEditor( - ){ - delete(m_quadrics); - }; - - -private : - - std::vector<LOD_Quadric> * m_quadrics; - - LOD_ManMesh2 &m_mesh; - -private : - - LOD_QuadricEditor(LOD_ManMesh2 &mesh); - - - -}; - -#endif - diff --git a/intern/decimation/intern/LOD_decimation.cpp b/intern/decimation/intern/LOD_decimation.cpp deleted file mode 100644 index 49033933cd6..00000000000 --- a/intern/decimation/intern/LOD_decimation.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_decimation.cpp - * \ingroup decimation - */ - - -// implementation of external c api -#include "../extern/LOD_decimation.h" -#include "LOD_DecimationClass.h" - -using namespace std; - - int -LOD_LoadMesh( - LOD_Decimation_InfoPtr info -) { - if (info == NULL) return 0; - if ( - info->vertex_buffer == NULL || - info->vertex_normal_buffer == NULL || - info->triangle_index_buffer == NULL - ) { - return 0; - } - - - // create the intern object to hold all - // the decimation classes - - MEM_SmartPtr<LOD_DecimationClass> intern(LOD_DecimationClass::New(info)); - - if (intern == NULL) return 0; - - MEM_SmartPtr<vector<LOD_Vertex> > intern_vertex_buffer(new vector<LOD_Vertex>(info->vertex_num)); - if (intern_vertex_buffer == NULL) return 0; - - vector<LOD_Vertex>::iterator intern_vertex_it(intern_vertex_buffer->begin()); - - // now load in the vertices to the mesh - - const int vertex_stride = 3; - - float * vertex_ptr = info->vertex_buffer; - const float * vertex_end = vertex_ptr + info->vertex_num*vertex_stride; - - LOD_ManMesh2 &mesh = intern->Mesh(); - - for (;vertex_ptr < vertex_end; vertex_ptr += vertex_stride,++intern_vertex_it) { - intern_vertex_it->pos = MT_Vector3(vertex_ptr); - } - - mesh.SetVertices(intern_vertex_buffer); - - // load in the triangles - - const int triangle_stride = 3; - - int * triangle_ptr = info->triangle_index_buffer; - const int * triangle_end = triangle_ptr + info->face_num*triangle_stride; - - try { - - for (;triangle_ptr < triangle_end; triangle_ptr += triangle_stride) { - mesh.AddTriangle(triangle_ptr); - } - } - - catch (...) { - return 0; - } - - // ok we have built the mesh - - intern->m_e_decimation_state = LOD_DecimationClass::e_loaded; - - info->intern = (void *) (intern.Release()); - - return 1; -} - - int -LOD_PreprocessMesh( - LOD_Decimation_InfoPtr info -) { - if (info == NULL) return 0; - if (info->intern == NULL) return 0; - - LOD_DecimationClass *intern = (LOD_DecimationClass *) info->intern; - if (intern->m_e_decimation_state != LOD_DecimationClass::e_loaded) return 0; - - // arm the various internal classes so that we are ready to step - // through decimation - - intern->FaceEditor().BuildNormals(); - if (intern->Decimator().Arm() == false) return 0; - - // ok preprocessing done - intern->m_e_decimation_state = LOD_DecimationClass::e_preprocessed; - - return 1; -} - - int -LOD_CollapseEdge( - LOD_Decimation_InfoPtr info -){ - if (info == NULL) return 0; - if (info->intern == NULL) return 0; - LOD_DecimationClass *intern = (LOD_DecimationClass *) info->intern; - if (intern->m_e_decimation_state != LOD_DecimationClass::e_preprocessed) return 0; - - bool step_result = intern->Decimator().Step(); - - return step_result == true ? 1 : 0; -} - - - int -LOD_FreeDecimationData( - LOD_Decimation_InfoPtr info -){ - if (info == NULL) return 0; - if (info->intern == NULL) return 0; - LOD_DecimationClass *intern = (LOD_DecimationClass *) info->intern; - delete(intern); - info->intern = NULL; - return 1; -} - diff --git a/intern/dualcon/CMakeLists.txt b/intern/dualcon/CMakeLists.txt index caa1ea09b04..da5e10fe6a7 100644 --- a/intern/dualcon/CMakeLists.txt +++ b/intern/dualcon/CMakeLists.txt @@ -19,6 +19,9 @@ set(INC . intern +) + +set(INC_SYS ../../extern/Eigen3 ) @@ -42,5 +45,5 @@ set(SRC dualcon.h ) -blender_add_lib(bf_intern_dualcon "${SRC}" "${INC}" "") +blender_add_lib(bf_intern_dualcon "${SRC}" "${INC}" "${INC_SYS}") diff --git a/intern/elbeem/intern/ntl_geometryshader.h b/intern/elbeem/intern/ntl_geometryshader.h index 61598556b7e..f43df6539e6 100644 --- a/intern/elbeem/intern/ntl_geometryshader.h +++ b/intern/elbeem/intern/ntl_geometryshader.h @@ -46,7 +46,7 @@ class ntlGeometryShader : /*! notify object that dump is in progress (e.g. for field dump) */ virtual void notifyShaderOfDump(int dumptype, int frameNr,char *frameNrStr,string outfilename) = 0; - /*! get ouput filename, returns global render outfile if empty */ + /*! get output filename, returns global render outfile if empty */ string getOutFilename( void ) { return mOutFilename; } protected: diff --git a/intern/elbeem/intern/utilities.cpp b/intern/elbeem/intern/utilities.cpp index c912e70b281..2b9b8d5b8a5 100644 --- a/intern/elbeem/intern/utilities.cpp +++ b/intern/elbeem/intern/utilities.cpp @@ -51,7 +51,7 @@ int getElbeemState(void) { return gElbeemState; } int isSimworldOk(void) { - return (getElbeemState>=0); + return (getElbeemState() >=0); } // last error as string, acces with get/setElbeemErrorString diff --git a/intern/ffmpeg/ffmpeg_compat.h b/intern/ffmpeg/ffmpeg_compat.h index 2fd61570011..37cde2c2837 100644 --- a/intern/ffmpeg/ffmpeg_compat.h +++ b/intern/ffmpeg/ffmpeg_compat.h @@ -110,7 +110,7 @@ void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp) #endif /* there are some version inbetween, which have avio_... functions but no - AVIO_FLAG_... */ + * AVIO_FLAG_... */ #ifndef AVIO_FLAG_WRITE #define AVIO_FLAG_WRITE URL_WRONLY #endif diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index be79aad2e90..8771929c14d 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -223,7 +223,6 @@ elseif(APPLE) if(WITH_INPUT_NDOF) list(APPEND SRC intern/GHOST_NDOFManagerCocoa.mm - intern/GHOST_NDOFManagerCocoa.h ) endif() diff --git a/intern/ghost/GHOST_IEventConsumer.h b/intern/ghost/GHOST_IEventConsumer.h index 5682d04d434..5b6fa7ba046 100644 --- a/intern/ghost/GHOST_IEventConsumer.h +++ b/intern/ghost/GHOST_IEventConsumer.h @@ -42,8 +42,8 @@ * they want to receive events. The system will call the processEvent() method * for every installed event consumer to pass events. * \see GHOST_ISystem#addEventConsumer - * \author Maarten Gribnau - * \date May 14, 2001 + * \author Maarten Gribnau + * \date May 14, 2001 */ class GHOST_IEventConsumer { @@ -58,15 +58,14 @@ public: /** * This method is called by the system when it has events to dispatch. * \see GHOST_ISystem#dispatchEvents - * \param event The event that can be handled or ignored. - * \return Indication as to whether the event was handled. + * \param event The event that can be handled or ignored. + * \return Indication as to whether the event was handled. */ virtual bool processEvent(GHOST_IEvent *event) = 0; - + #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IEventConsumer") #endif }; -#endif // _GHOST_EVENT_CONSUMER_H_ - +#endif /* __GHOST_IEVENTCONSUMER_H__ */ diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 7bf86925875..69f44ee6bcb 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -47,14 +47,14 @@ class GHOST_IEventConsumer; * \section intro Introduction * * GHOST is yet another acronym. It stands for "Generic Handy Operating System - * Toolkit". It has been created to replace the OpenGL utility tool kit + * Toolkit". It has been created to replace the OpenGL utility tool kit * <a href="http://www.opengl.org/developers/documentation/glut.html">GLUT</a>. * GLUT was used in <a href="http://www.blender3d.com">Blender</a> until the * point that Blender needed to be ported to Apple's Mac OSX. Blender needed a * number of modifications in GLUT to work but the GLUT sources for OSX were * unavailable at the time. The decision was made to build our own replacement - * for GLUT. In those days, NaN Technologies BV was the company that developed - * Blender. + * for GLUT. In those days, NaN Technologies BV was the company that developed + * Blender. * <br><br> * Enough history. What does GHOST have to offer?<br> * In short: everything that Blender needed from GLUT to run on all it's supported @@ -96,7 +96,7 @@ class GHOST_IEventConsumer; * <li>The C-API. For programs written in C.</li> * <li>The C++-API. For programs written in C++.</li> * </ul> - * GHOST itself is writtem in C++ and the C-API is a wrapper around the C++ + * GHOST itself is writtem in C++ and the C-API is a wrapper around the C++ * API. * * \subsection cplusplus_api The C++ API consists of the following files: @@ -113,7 +113,7 @@ class GHOST_IEventConsumer; * program in the ?/ghost/test/gears/ directory. * * \subsection c_api The C-API - * To use GHOST in programs written in C, include the file GHOST_C-API.h in + * To use GHOST in programs written in C, include the file GHOST_C-API.h in * your program. This file includes the GHOST_Types.h file for all GHOST types * and defines functions that give you access to the same functionality present * in the C++ API.<br> @@ -123,7 +123,7 @@ class GHOST_IEventConsumer; * \section work Work in progress * \todo write WIP section */ - + /** \interface GHOST_ISystem * Interface for classes that provide access to the operating system. * There should be only one system class in an application. @@ -136,8 +136,8 @@ class GHOST_IEventConsumer; * -# Access to the state of the mouse buttons and the keyboard. * -# Menus for windows with events generated when they are accessed (this is * work in progress). - * \author Maarten Gribnau - * \date May 30, 2001 + * \author Maarten Gribnau + * \date May 30, 2001 */ class GHOST_ISystem { @@ -190,12 +190,12 @@ public: /** * Installs a timer. - * Note that, on most operating systems, messages need to be processed in order + * Note that, on most operating systems, messages need to be processed in order * for the timer callbacks to be invoked. - * \param delay The time to wait for the first call to the timerProc (in milliseconds) - * \param interval The interval between calls to the timerProc (in milliseconds) - * \param timerProc The callback invoked when the interval expires, - * \param userData Placeholder for user data. + * \param delay The time to wait for the first call to the timerProc (in milliseconds) + * \param interval The interval between calls to the timerProc (in milliseconds) + * \param timerProc The callback invoked when the interval expires, + * \param userData Placeholder for user data. * \return A timer task (0 if timer task installation failed). */ virtual GHOST_ITimerTask *installTimer(GHOST_TUns64 delay, @@ -225,22 +225,22 @@ public: * \return The dimension of the main display. */ virtual void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const = 0; - + /** * Create a new window. - * The new window is added to the list of windows managed. + * The new window is added to the list of windows managed. * Never explicitly delete the window, use disposeWindow() instead. - * \param title The name of the window (displayed in the title bar of the window if the OS supports it). - * \param left The coordinate of the left edge of the window. - * \param top The coordinate of the top edge of the window. - * \param width The width the window. - * \param height The height the window. - * \param state The state of the window when opened. - * \param type The type of drawing context installed in this window. - * \param stereoVisual Create a stereo visual for quad buffered stereo. - * \param numOfAASamples Number of samples used for AA (zero if no AA) - * \param parentWindow Parent (embedder) window - * \return The new window (or 0 if creation failed). + * \param title The name of the window (displayed in the title bar of the window if the OS supports it). + * \param left The coordinate of the left edge of the window. + * \param top The coordinate of the top edge of the window. + * \param width The width the window. + * \param height The height the window. + * \param state The state of the window when opened. + * \param type The type of drawing context installed in this window. + * \param stereoVisual Create a stereo visual for quad buffered stereo. + * \param numOfAASamples Number of samples used for AA (zero if no AA) + * \param parentWindow Parent (embedder) window + * \return The new window (or 0 if creation failed). */ virtual GHOST_IWindow *createWindow( const STR_String& title, @@ -252,40 +252,40 @@ public: /** * Dispose a window. - * \param window Pointer to the window to be disposed. - * \return Indication of success. + * \param window Pointer to the window to be disposed. + * \return Indication of success. */ virtual GHOST_TSuccess disposeWindow(GHOST_IWindow *window) = 0; /** * Returns whether a window is valid. - * \param window Pointer to the window to be checked. - * \return Indication of validity. + * \param window Pointer to the window to be checked. + * \return Indication of validity. */ virtual bool validWindow(GHOST_IWindow *window) = 0; /** * Begins full screen mode. - * \param setting The new setting of the display. - * \param window Window displayed in full screen. - * This window is invalid after full screen has been ended. - * \return Indication of success. + * \param setting The new setting of the display. + * \param window Window displayed in full screen. + * This window is invalid after full screen has been ended. + * \return Indication of success. */ virtual GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window, const bool stereoVisual, const GHOST_TUns16 numOfAASamples = 0) = 0; - + /** * Updates the resolution while in fullscreen mode. - * \param setting The new setting of the display. - * \param window Window displayed in full screen. + * \param setting The new setting of the display. + * \param window Window displayed in full screen. * - * \return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess updateFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window) = 0; /** * Ends full screen mode. - * \return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess endFullScreen(void) = 0; @@ -305,7 +305,7 @@ public: * \return Indication of the presence of events. */ virtual bool processEvents(bool waitForEvent) = 0; - + /** * Retrieves events from the queue and send them to the event consumers. * \return Indication of the presence of events. @@ -332,18 +332,18 @@ public: /** * Returns the current location of the cursor (location in screen coordinates) - * \param x The x-coordinate of the cursor. - * \param y The y-coordinate of the cursor. - * \return Indication of success. + * \param x The x-coordinate of the cursor. + * \param y The y-coordinate of the cursor. + * \return Indication of success. */ virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const = 0; /** * Updates the location of the cursor (location in screen coordinates). * Not all operating systems allow the cursor to be moved (without the input device being moved). - * \param x The x-coordinate of the cursor. - * \param y The y-coordinate of the cursor. - * \return Indication of success. + * \param x The x-coordinate of the cursor. + * \param y The y-coordinate of the cursor. + * \return Indication of success. */ virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) = 0; @@ -353,17 +353,17 @@ public: /** * Returns the state of a modifier key (ouside the message queue). - * \param mask The modifier key state to retrieve. - * \param isDown The state of a modifier key (true == pressed). - * \return Indication of success. + * \param mask The modifier key state to retrieve. + * \param isDown The state of a modifier key (true == pressed). + * \return Indication of success. */ virtual GHOST_TSuccess getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const = 0; /** * Returns the state of a mouse button (ouside the message queue). - * \param mask The button state to retrieve. - * \param isDown Button state. - * \return Indication of success. + * \param mask The button state to retrieve. + * \param isDown Button state. + * \return Indication of success. */ virtual GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool& isDown) const = 0; @@ -398,11 +398,11 @@ public: * \return current status (1 -visible, 0 - hidden) */ virtual int toggleConsole(int action) = 0; - + /*************************************************************************************** * Access to clipboard. ***************************************************************************************/ - + /** * Returns the selection buffer * \return Returns "unsinged char" from X11 XA_CUT_BUFFER0 buffer diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h index 7ec6417ca4f..88f130aabe8 100644 --- a/intern/ghost/GHOST_IWindow.h +++ b/intern/ghost/GHOST_IWindow.h @@ -41,20 +41,20 @@ /** * Interface for GHOST windows. * - * You can create a window with the system's GHOST_ISystem::createWindow + * You can create a window with the system's GHOST_ISystem::createWindow * method. * \see GHOST_ISystem#createWindow * * There are two coordinate systems: * <ul> * <li>The screen coordinate system. The origin of the screen is located in the - * upper left corner of the screen.</li> + * upper left corner of the screen.</li> * <li>The client rectangle coordinate system. The client rectangle of a window * is the area that is drawable by the application (excluding title bars etc.). - * </li> + * </li> * </ul> - * \author Maarten Gribnau - * \date May 31, 2001 + * \author Maarten Gribnau + * \date May 31, 2001 */ class GHOST_IWindow { @@ -86,20 +86,20 @@ public: /** * Tries to install a rendering context in this window. - * \param type The type of rendering context installed. + * \param type The type of rendering context installed. * \return Indication as to whether installation has succeeded. */ virtual GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type) = 0; /** * Sets the title displayed in the title bar. - * \param title The title to display in the title bar. + * \param title The title to display in the title bar. */ virtual void setTitle(const STR_String& title) = 0; /** * Returns the title displayed in the title bar. - * \param title The title displayed in the title bar. + * \param title The title displayed in the title bar. */ virtual void getTitle(STR_String& title) const = 0; @@ -109,7 +109,7 @@ public: * \param bounds The bounding rectangle of the window. */ virtual void getWindowBounds(GHOST_Rect& bounds) const = 0; - + /** * Returns the client rectangle dimensions. * The left and top members of the rectangle are always zero. @@ -131,26 +131,26 @@ public: /** * Resizes client rectangle. - * \param width The new width of the client area of the window. - * \param height The new height of the client area of the window. + * \param width The new width of the client area of the window. + * \param height The new height of the client area of the window. */ virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) = 0; /** * Converts a point in screen coordinates to client rectangle coordinates - * \param inX The x-coordinate on the screen. - * \param inY The y-coordinate on the screen. - * \param outX The x-coordinate in the client rectangle. - * \param outY The y-coordinate in the client rectangle. + * \param inX The x-coordinate on the screen. + * \param inY The y-coordinate on the screen. + * \param outX The x-coordinate in the client rectangle. + * \param outY The y-coordinate in the client rectangle. */ virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0; /** * Converts a point in screen coordinates to client rectangle coordinates - * \param inX The x-coordinate in the client rectangle. - * \param inY The y-coordinate in the client rectangle. - * \param outX The x-coordinate on the screen. - * \param outY The y-coordinate on the screen. + * \param inX The x-coordinate in the client rectangle. + * \param inY The y-coordinate in the client rectangle. + * \param outX The x-coordinate on the screen. + * \param outY The y-coordinate on the screen. */ virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0; @@ -158,13 +158,13 @@ public: * Tells if the ongoing drag'n'drop object can be accepted upon mouse drop */ virtual void setAcceptDragOperation(bool canAccept) = 0; - + /** * Returns acceptance of the dropped object * Usually called by the "object dropped" event handling function */ virtual bool canAcceptDragOperation() const = 0; - + /** * Returns the state of the window (normal, minimized, maximized). * \return The state of the window. @@ -184,13 +184,13 @@ public: * \return Indication of success. */ virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges) = 0; - + /** * Gets the window "modified" status, indicating unsaved changes * \return True if there are unsaved changes */ virtual bool getModifiedState() = 0; - + /** * Sets the order of the window (bottom, top). * \param order The order of the window. @@ -200,13 +200,13 @@ public: /** * Swaps front and back buffers of a window. - * \return A boolean success indicator. + * \return A boolean success indicator. */ virtual GHOST_TSuccess swapBuffers() = 0; /** * Activates the drawing context of this window. - * \return A boolean success indicator. + * \return A boolean success indicator. */ virtual GHOST_TSuccess activateDrawingContext() = 0; @@ -215,71 +215,71 @@ public: * \return Indication of success. */ virtual GHOST_TSuccess invalidate() = 0; - + /** * Returns the window user data. * \return The window user data. */ virtual GHOST_TUserDataPtr getUserData() const = 0; - + /** * Changes the window user data. * \param data The window user data. */ virtual void setUserData(const GHOST_TUserDataPtr userData) = 0; - + /** * Returns the tablet data (pressure etc). * \return The tablet data (pressure etc). */ virtual const GHOST_TabletData *GetTabletData() = 0; - + /*************************************************************************************** * Progress bar functionality ***************************************************************************************/ - + /** * Sets the progress bar value displayed in the window/application icon * \param progress The progress % */ virtual GHOST_TSuccess setProgressBar(float progress) = 0; - + /** * Hides the progress bar in the icon */ virtual GHOST_TSuccess endProgressBar() = 0; - + /*************************************************************************************** * Cursor management functionality ***************************************************************************************/ /** * Returns the current cursor shape. - * \return The current cursor shape. + * \return The current cursor shape. */ virtual GHOST_TStandardCursor getCursorShape() const = 0; /** * Set the shape of the cursor. - * \param cursor The new cursor shape type id. - * \return Indication of success. + * \param cursor The new cursor shape type id. + * \return Indication of success. */ virtual GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape) = 0; /** * Set the shape of the cursor to a custom cursor. - * \param bitmap The bitmap data for the cursor. - * \param mask The mask data for the cursor. - * \param hotX The X coordinate of the cursor hotspot. - * \param hotY The Y coordinate of the cursor hotspot. - * \return Indication of success. + * \param bitmap The bitmap data for the cursor. + * \param mask The mask data for the cursor. + * \param hotX The X coordinate of the cursor hotspot. + * \param hotY The Y coordinate of the cursor hotspot. + * \return Indication of success. */ - virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 bitmap[16][2], + virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY) = 0; - virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap, + virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask, int sizex, int sizey, int hotX, int hotY, @@ -287,21 +287,21 @@ public: /** * Returns the visibility state of the cursor. - * \return The visibility state of the cursor. + * \return The visibility state of the cursor. */ virtual bool getCursorVisibility() const = 0; /** * Shows or hides the cursor. - * \param visible The new visibility state of the cursor. - * \return Indication of success. + * \param visible The new visibility state of the cursor. + * \return Indication of success. */ virtual GHOST_TSuccess setCursorVisibility(bool visible) = 0; /** * Grabs the cursor for a modal operation. - * \param grab The new grab state of the cursor. - * \return Indication of success. + * \param grab The new grab state of the cursor. + * \return Indication of success. */ virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds, GHOST_TInt32 mouse_ungrab_xy[2]) { return GHOST_kSuccess; } diff --git a/intern/ghost/GHOST_Rect.h b/intern/ghost/GHOST_Rect.h index aa7969d68ad..a055b6f7f0d 100644 --- a/intern/ghost/GHOST_Rect.h +++ b/intern/ghost/GHOST_Rect.h @@ -41,8 +41,8 @@ * The four extreme coordinates are stored as left, top, right and bottom. * To be valid, a rectangle should have a left coordinate smaller than or equal to right. * To be valid, a rectangle should have a top coordinate smaller than or equal to bottom. - * \author Maarten Gribnau - * \date May 10, 2001 + * \author Maarten Gribnau + * \date May 10, 2001 */ class GHOST_Rect { @@ -50,10 +50,10 @@ public: /** * Constructs a rectangle with the given values. - * \param l requested left coordinate of the rectangle - * \param t requested top coordinate of the rectangle - * \param r requested right coordinate of the rectangle - * \param b requested bottom coordinate of the rectangle + * \param l requested left coordinate of the rectangle + * \param t requested top coordinate of the rectangle + * \param r requested right coordinate of the rectangle + * \param b requested bottom coordinate of the rectangle */ GHOST_Rect(GHOST_TInt32 l = 0, GHOST_TInt32 t = 0, GHOST_TInt32 r = 0, GHOST_TInt32 b = 0) : m_l(l), m_t(t), m_r(r), m_b(b) @@ -61,12 +61,12 @@ public: /** * Copy constructor. - * \param r rectangle to copy + * \param r rectangle to copy */ GHOST_Rect(const GHOST_Rect& r) : m_l(r.m_l), m_t(r.m_t), m_r(r.m_r), m_b(r.m_b) {} - + /** * Destructor. */ @@ -74,71 +74,71 @@ public: /** * Access to rectangle width. - * \return width of the rectangle + * \return width of the rectangle */ virtual inline GHOST_TInt32 getWidth() const; /** * Access to rectangle height. - * \return height of the rectangle + * \return height of the rectangle */ virtual inline GHOST_TInt32 getHeight() const; /** * Sets all members of the rectangle. - * \param l requested left coordinate of the rectangle - * \param t requested top coordinate of the rectangle - * \param r requested right coordinate of the rectangle - * \param b requested bottom coordinate of the rectangle + * \param l requested left coordinate of the rectangle + * \param t requested top coordinate of the rectangle + * \param r requested right coordinate of the rectangle + * \param b requested bottom coordinate of the rectangle */ virtual inline void set(GHOST_TInt32 l, GHOST_TInt32 t, GHOST_TInt32 r, GHOST_TInt32 b); /** * Returns whether this rectangle is empty. * Empty rectangles are rectangles that have width==0 and/or height==0. - * \return boolean value (true==empty rectangle) + * \return boolean value (true==empty rectangle) */ virtual inline bool isEmpty() const; /** * Returns whether this rectangle is valid. * Valid rectangles are rectangles that have m_l <= m_r and m_t <= m_b. Thus, emapty rectangles are valid. - * \return boolean value (true==valid rectangle) + * \return boolean value (true==valid rectangle) */ virtual inline bool isValid() const; /** * Grows (or shrinks the rectangle). * The method avoids negative insets making the rectangle invalid - * \param i The amount of offset given to each extreme (negative values shrink the rectangle). + * \param i The amount of offset given to each extreme (negative values shrink the rectangle). */ virtual void inset(GHOST_TInt32 i); /** * Does a union of the rectangle given and this rectangle. * The result is stored in this rectangle. - * \param r The rectangle that is input for the union operation. + * \param r The rectangle that is input for the union operation. */ virtual inline void unionRect(const GHOST_Rect& r); /** * Grows the rectangle to included a point. - * \param x The x-coordinate of the point. - * \param y The y-coordinate of the point. + * \param x The x-coordinate of the point. + * \param y The y-coordinate of the point. */ virtual inline void unionPoint(GHOST_TInt32 x, GHOST_TInt32 y); /** * Grows the rectangle to included a point. - * \param x The x-coordinate of the point. - * \param y The y-coordinate of the point. + * \param x The x-coordinate of the point. + * \param y The y-coordinate of the point. */ virtual inline void wrapPoint(GHOST_TInt32 &x, GHOST_TInt32 &y, GHOST_TInt32 ofs); /** * Returns whether the point is inside this rectangle. * Point on the boundary is considered inside. - * \param x x-coordinate of point to test. + * \param x x-coordinate of point to test. * \param y y-coordinate of point to test. * \return boolean value (true if point is inside). */ @@ -146,16 +146,16 @@ public: /** * Returns whether the rectangle is inside this rectangle. - * \param r rectangle to test. - * \return visibility (not, partially or fully visible). + * \param r rectangle to test. + * \return visibility (not, partially or fully visible). */ virtual GHOST_TVisibility getVisibility(GHOST_Rect& r) const; /** * Sets rectangle members. * Sets rectangle members such that it is centered at the given location. - * \param cx requested center x-coordinate of the rectangle - * \param cy requested center y-coordinate of the rectangle + * \param cx requested center x-coordinate of the rectangle + * \param cy requested center y-coordinate of the rectangle */ virtual void setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy); @@ -163,10 +163,10 @@ public: * Sets rectangle members. * Sets rectangle members such that it is centered at the given location, * with the width requested. - * \param cx requested center x-coordinate of the rectangle - * \param cy requested center y-coordinate of the rectangle - * \param w requested width of the rectangle - * \param h requested height of the rectangle + * \param cx requested center x-coordinate of the rectangle + * \param cy requested center y-coordinate of the rectangle + * \param w requested width of the rectangle + * \param h requested height of the rectangle */ virtual void setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy, GHOST_TInt32 w, GHOST_TInt32 h); @@ -174,8 +174,8 @@ public: * Clips a rectangle. * Updates the rectangle given such that it will fit within this one. * This can result in an empty rectangle. - * \param r the rectangle to clip - * \return whether clipping has occurred + * \param r the rectangle to clip + * \return whether clipping has occurred */ virtual bool clip(GHOST_Rect& r) const; diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index d5cf6e0a8fc..4fe3f10d23e 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -50,7 +50,7 @@ typedef unsigned short GHOST_TUns16; typedef int GHOST_TInt32; typedef unsigned int GHOST_TUns32; -#if defined(WIN32) && !defined(FREE_WINDOWS) +#ifdef _MSC_VER typedef __int64 GHOST_TInt64; typedef unsigned __int64 GHOST_TUns64; #else @@ -392,7 +392,7 @@ typedef struct { typedef struct { /** Displacement of a mouse wheel. */ - GHOST_TInt32 z; + GHOST_TInt32 z; } GHOST_TEventWheelData; typedef enum { diff --git a/intern/ghost/intern/GHOST_Debug.h b/intern/ghost/intern/GHOST_Debug.h index c364f1d26a4..f0db1b3de8d 100644 --- a/intern/ghost/intern/GHOST_Debug.h +++ b/intern/ghost/intern/GHOST_Debug.h @@ -33,12 +33,12 @@ #ifndef __GHOST_DEBUG_H__ #define __GHOST_DEBUG_H__ -#if defined(WIN32) && !defined(FREE_WINDOWS) +#ifdef _MSC_VER # ifdef DEBUG # pragma warning (disable:4786) // suppress stl-MSVC debug info warning // #define GHOST_DEBUG # endif // DEBUG -#endif // WIN32 +#endif // _MSC_VER #ifdef WITH_GHOST_DEBUG # define GHOST_DEBUG // spit ghost events to stdout diff --git a/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm b/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm index c5a2fecd3b8..555f883cbf2 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm +++ b/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm @@ -102,7 +102,7 @@ GHOST_TSuccess GHOST_DisplayManagerCocoa::getCurrentDisplaySetting(GHOST_TUns8 d GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCocoa::getCurrentDisplaySetting(): only main display is supported"); - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; if (display == kMainDisplay) //Screen #0 may not be the main one askedDisplay = [NSScreen mainScreen]; diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.cpp b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp index 0bd90854a31..754218191a5 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerX11.cpp +++ b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp @@ -88,8 +88,8 @@ getNumDisplaySettings( #else /* We only have one X11 setting at the moment. */ - GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n"); - numSettings = GHOST_TInt32(1); + GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n"); + numSettings = 1; #endif return GHOST_kSuccess; @@ -130,8 +130,8 @@ getDisplaySetting( setting.bpp = DefaultDepth(dpy, DefaultScreen(dpy)); #else - GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n"); - GHOST_ASSERT(index < 1, "Requested setting outside of valid range.\n"); + GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n"); + GHOST_ASSERT(index < 1, "Requested setting outside of valid range.\n"); Display *x_display = m_system->getXDisplay(); @@ -160,7 +160,7 @@ getCurrentDisplaySetting( /* According to the xf86vidmodegetallmodelines man page, * "The first element of the array corresponds to the current video mode." */ - return getDisplaySetting(display, GHOST_TInt32(0), setting); + return getDisplaySetting(display, 0, setting); } diff --git a/intern/ghost/intern/GHOST_EventDragnDrop.h b/intern/ghost/intern/GHOST_EventDragnDrop.h index cef9bb0a34a..c51f9568087 100644 --- a/intern/ghost/intern/GHOST_EventDragnDrop.h +++ b/intern/ghost/intern/GHOST_EventDragnDrop.h @@ -72,13 +72,13 @@ class GHOST_EventDragnDrop : public GHOST_Event public: /** * Constructor. - * \param time The time this event was generated. - * \param type The type of this event. - * \param dataType The type of the drop candidate object - * \param window The window where the event occurred - * \param x The x-coordinate of the location the cursor was at at the time of the event. - * \param y The y-coordinate of the location the cursor was at at the time of the event. - * \param data The "content" dropped in the window + * \param time The time this event was generated. + * \param type The type of this event. + * \param dataType The type of the drop candidate object + * \param window The window where the event occurred + * \param x The x-coordinate of the location the cursor was at at the time of the event. + * \param y The y-coordinate of the location the cursor was at at the time of the event. + * \param data The "content" dropped in the window */ GHOST_EventDragnDrop(GHOST_TUns64 time, GHOST_TEventType type, diff --git a/intern/ghost/intern/GHOST_Rect.cpp b/intern/ghost/intern/GHOST_Rect.cpp index dc30b3eb220..9af4f30ebc1 100644 --- a/intern/ghost/intern/GHOST_Rect.cpp +++ b/intern/ghost/intern/GHOST_Rect.cpp @@ -75,7 +75,7 @@ GHOST_TVisibility GHOST_Rect::getVisibility(GHOST_Rect& r) const GHOST_TVisibility v; if (lt && rt && lb && rb) { // All points inside, rectangle is inside this - v = GHOST_kFullyVisible; + v = GHOST_kFullyVisible; } else if (!(lt || rt || lb || rb)) { // None of the points inside diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index 5f9928c47c7..f8c930a4824 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -207,7 +207,7 @@ public: ***************************************************************************************/ /** Inherited from GHOST_ISystem but left pure virtual - * GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const = 0; + * GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const = 0; * GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) */ diff --git a/intern/ghost/intern/GHOST_SystemCarbon.cpp b/intern/ghost/intern/GHOST_SystemCarbon.cpp index bb68ce8889c..f5784c7d451 100644 --- a/intern/ghost/intern/GHOST_SystemCarbon.cpp +++ b/intern/ghost/intern/GHOST_SystemCarbon.cpp @@ -126,7 +126,7 @@ static GHOST_TKey convertKey(int rawCode) */ static UInt32 dummy = 0; Handle transData = (Handle) GetScriptManagerVariable(smKCHRCache); - unsigned char vk = KeyTranslate(transData, rawCode, &dummy); + unsigned char vk = KeyTranslate(transData, rawCode, &dummy); /* Map numpad based on rawcodes first, otherwise they * look like non-numpad events. * Added too: mapping the number keys, for french keyboards etc (ton) diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index fed3bdbc8f0..475ad2bdcb3 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -423,7 +423,7 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction) #pragma mark defines for 10.6 api not documented in 10.5 -#ifndef MAC_OS_X_VERSION_10_6 +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 enum { /* The following event types are available on some hardware on 10.5.2 and later */ NSEventTypeGesture = 29, @@ -435,12 +435,10 @@ enum { }; @interface NSEvent(GestureEvents) -/* This message is valid for events of type NSEventTypeMagnify, on 10.5.2 or later */ -#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 - (float)magnification; // change in magnification. #else -- (CGFloat)magnification; // change in magnification. -#endif +@interface NSEvent(GestureEvents) +- (CGFloat)magnification; // change in magnification on 10.5.2 or later. @end #endif @@ -966,7 +964,7 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) //Resend event to NSApp to ensure Mac wide events are handled [NSApp sendEvent:event]; [pool drain]; - } while (event!= nil); + } while (event != nil); #if 0 } while (waitForEvent && !anyProcessed); // Needed only for timer implementation #endif @@ -1000,16 +998,16 @@ GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent() modifiers = [[[NSApplication sharedApplication] currentEvent] modifierFlags]; if ((modifiers & NSShiftKeyMask) != (m_modifierMask & NSShiftKeyMask)) { - pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSShiftKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) ); + pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSShiftKeyMask) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift)); } if ((modifiers & NSControlKeyMask) != (m_modifierMask & NSControlKeyMask)) { - pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSControlKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl) ); + pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSControlKeyMask) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl)); } if ((modifiers & NSAlternateKeyMask) != (m_modifierMask & NSAlternateKeyMask)) { - pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSAlternateKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt) ); + pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSAlternateKeyMask) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt)); } if ((modifiers & NSCommandKeyMask) != (m_modifierMask & NSCommandKeyMask)) { - pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSCommandKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyOS) ); + pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSCommandKeyMask) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp, window, GHOST_kKeyOS)); } m_modifierMask = modifiers; @@ -1052,7 +1050,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType, case GHOST_kEventWindowSize: if (!m_ignoreWindowSizedMessages) { - //Enforce only one resize message per event loop (coalescing all the live resize messages) + //Enforce only one resize message per event loop (coalescing all the live resize messages) window->updateDrawingContext(); pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) ); //Mouse up event is trapped by the resizing event loop, so send it anyway to the window manager @@ -1089,7 +1087,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType GHOST_TUns8 * temp_buff; GHOST_TStringArray *strArray; NSArray *droppedArray; - size_t pastedTextSize; + size_t pastedTextSize; NSString *droppedStr; GHOST_TEventDataPtr eventData; int i; @@ -1126,7 +1124,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType strArray->strings[i] = temp_buff; } - eventData = (GHOST_TEventDataPtr) strArray; + eventData = (GHOST_TEventDataPtr) strArray; break; case GHOST_kDragnDropTypeString: @@ -1159,7 +1157,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType NSEnumerator *enumerator; NSImageRep *representation; - ibuf = IMB_allocImBuf (imgSize.width , imgSize.height, 32, IB_rect); + ibuf = IMB_allocImBuf (imgSize.width, imgSize.height, 32, IB_rect); if (!ibuf) { [droppedImg release]; return GHOST_kFailure; @@ -1326,7 +1324,7 @@ bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr) int confirmOpen = NSAlertAlternateReturn; NSArray *windowsList; char * temp_buff; - size_t filenameTextSize; + size_t filenameTextSize; GHOST_Window* window= (GHOST_Window*)m_windowManager->getActiveWindow(); if (!window) { @@ -1460,7 +1458,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) case NSLeftMouseDown: case NSRightMouseDown: case NSOtherMouseDown: - pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonDown, window, convertButton([event buttonNumber]))); + pushEvent(new GHOST_EventButton([event timestamp] * 1000, GHOST_kEventButtonDown, window, convertButton([event buttonNumber]))); //Handle tablet events combined with mouse events handleTabletEvent(event); break; @@ -1468,14 +1466,14 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp: - pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonUp, window, convertButton([event buttonNumber]))); + pushEvent(new GHOST_EventButton([event timestamp] * 1000, GHOST_kEventButtonUp, window, convertButton([event buttonNumber]))); //Handle tablet events combined with mouse events handleTabletEvent(event); break; case NSLeftMouseDragged: case NSRightMouseDragged: - case NSOtherMouseDragged: + case NSOtherMouseDragged: //Handle tablet events combined with mouse events handleTabletEvent(event); @@ -1503,7 +1501,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) window->setCursorGrabAccum(x_accum, y_accum); window->clientToScreenIntern(x_warp+x_accum, y_warp+y_accum, x, y); - pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, x, y)); + pushEvent(new GHOST_EventCursor([event timestamp] * 1000, GHOST_kEventCursorMove, window, x, y)); } break; case GHOST_kGrabWrap: //Wrap cursor at area/window boundaries @@ -1548,7 +1546,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) //Post event window->getCursorGrabInitPos(x_cur, y_cur); window->clientToScreenIntern(x_cur + x_accum, y_cur + y_accum, x, y); - pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, x, y)); + pushEvent(new GHOST_EventCursor([event timestamp] * 1000, GHOST_kEventCursorMove, window, x, y)); } break; default: @@ -1558,7 +1556,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) GHOST_TInt32 x, y; window->clientToScreenIntern(mousePos.x, mousePos.y, x, y); - pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, x, y)); + pushEvent(new GHOST_EventCursor([event timestamp] * 1000, GHOST_kEventCursorMove, window, x, y)); m_cursorDelta_x=0; m_cursorDelta_y=0; //Mouse motion occurred between two cursor warps, so we can reset the delta counter @@ -1580,7 +1578,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) if (deltaF == 0.0) break; //discard trackpad delta=0 events delta = deltaF > 0.0 ? 1 : -1; - pushEvent(new GHOST_EventWheel([event timestamp]*1000, window, delta)); + pushEvent(new GHOST_EventWheel([event timestamp] * 1000, window, delta)); } else { NSPoint mousePos = [event locationInWindow]; @@ -1604,7 +1602,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) window->clientToScreenIntern(mousePos.x, mousePos.y, x, y); dy = -dy; - pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventScroll, x, y, dx, dy)); + pushEvent(new GHOST_EventTrackpad([event timestamp] * 1000, window, GHOST_kTrackpadEventScroll, x, y, dx, dy)); } } break; @@ -1614,8 +1612,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) NSPoint mousePos = [event locationInWindow]; GHOST_TInt32 x, y; window->clientToScreenIntern(mousePos.x, mousePos.y, x, y); - pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventMagnify, x, y, - [event magnification]*125.0 + 0.1, 0)); + pushEvent(new GHOST_EventTrackpad([event timestamp] * 1000, window, GHOST_kTrackpadEventMagnify, x, y, + [event magnification] * 125.0 + 0.1, 0)); } break; @@ -1624,8 +1622,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) NSPoint mousePos = [event locationInWindow]; GHOST_TInt32 x, y; window->clientToScreenIntern(mousePos.x, mousePos.y, x, y); - pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventRotate, x, y, - -[event rotation] * 5.0, 0)); + pushEvent(new GHOST_EventTrackpad([event timestamp] * 1000, window, GHOST_kTrackpadEventRotate, x, y, + -[event rotation] * 5.0, 0)); } case NSEventTypeBeginGesture: m_isGestureInProgress = true; @@ -1700,11 +1698,11 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) break; //Cmd-Q is directly handled by Cocoa if ([event type] == NSKeyDown) { - pushEvent( new GHOST_EventKey([event timestamp]*1000, GHOST_kEventKeyDown, window, keyCode, ascii, utf8_buf) ); + pushEvent( new GHOST_EventKey([event timestamp] * 1000, GHOST_kEventKeyDown, window, keyCode, ascii, utf8_buf) ); //printf("Key down rawCode=0x%x charsIgnoringModifiers=%c keyCode=%u ascii=%i %c utf8=%s\n",[event keyCode],[charsIgnoringModifiers length]>0?[charsIgnoringModifiers characterAtIndex:0]:' ',keyCode,ascii,ascii, utf8_buf); } else { - pushEvent( new GHOST_EventKey([event timestamp]*1000, GHOST_kEventKeyUp, window, keyCode, 0, '\0') ); + pushEvent( new GHOST_EventKey([event timestamp] * 1000, GHOST_kEventKeyUp, window, keyCode, 0, '\0') ); //printf("Key up rawCode=0x%x charsIgnoringModifiers=%c keyCode=%u ascii=%i %c utf8=%s\n",[event keyCode],[charsIgnoringModifiers length]>0?[charsIgnoringModifiers characterAtIndex:0]:' ',keyCode,ascii,ascii, utf8_buf); } break; @@ -1713,16 +1711,16 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) modifiers = [event modifierFlags]; if ((modifiers & NSShiftKeyMask) != (m_modifierMask & NSShiftKeyMask)) { - pushEvent( new GHOST_EventKey([event timestamp]*1000, (modifiers & NSShiftKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) ); + pushEvent(new GHOST_EventKey([event timestamp] * 1000, (modifiers & NSShiftKeyMask) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift)); } if ((modifiers & NSControlKeyMask) != (m_modifierMask & NSControlKeyMask)) { - pushEvent( new GHOST_EventKey([event timestamp]*1000, (modifiers & NSControlKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl) ); + pushEvent(new GHOST_EventKey([event timestamp] * 1000, (modifiers & NSControlKeyMask) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl)); } if ((modifiers & NSAlternateKeyMask) != (m_modifierMask & NSAlternateKeyMask)) { - pushEvent( new GHOST_EventKey([event timestamp]*1000, (modifiers & NSAlternateKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt) ); + pushEvent(new GHOST_EventKey([event timestamp] * 1000, (modifiers & NSAlternateKeyMask) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt)); } if ((modifiers & NSCommandKeyMask) != (m_modifierMask & NSCommandKeyMask)) { - pushEvent( new GHOST_EventKey([event timestamp]*1000, (modifiers & NSCommandKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyOS) ); + pushEvent(new GHOST_EventKey([event timestamp] * 1000, (modifiers & NSCommandKeyMask) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp, window, GHOST_kKeyOS)); } m_modifierMask = modifiers; @@ -1743,7 +1741,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const { GHOST_TUns8 * temp_buff; - size_t pastedTextSize; + size_t pastedTextSize; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 271935639fd..430569823ab 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -758,8 +758,6 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, RAWINP ascii = utf8_char[0] & 0x80 ? '?' : utf8_char[0]; } - if (0x80 & state[VK_MENU]) utf8_char[0] = '\0'; - event = new GHOST_EventKey(system->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown : GHOST_kEventKeyUp, window, key, ascii, utf8_char); #ifdef GHOST_DEBUG diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 232bea6749b..c9953c80a52 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -858,7 +858,7 @@ GHOST_SystemX11::processEvent(XEvent *xe) } case DestroyNotify: - ::exit(-1); + ::exit(-1); /* We're not interested in the following things.(yet...) */ case NoExpose: case GraphicsExpose: @@ -1171,7 +1171,7 @@ generateWindowExposeEvents() *w_start ); - (*w_start)->validate(); + (*w_start)->validate(); if (g_event) { pushEvent(g_event); @@ -1456,7 +1456,7 @@ void GHOST_SystemX11::getClipboard_xcout(XEvent evt, /* check size and format of the property */ XGetWindowProperty(m_display, win, m_xclip_out, 0, 0, False, AnyPropertyType, &pty_type, &pty_format, - &pty_items, &pty_size, (unsigned char **) &buffer); + &pty_items, &pty_size, &buffer); if (pty_format != 8) { /* property does not contain text, delete it @@ -1484,7 +1484,7 @@ void GHOST_SystemX11::getClipboard_xcout(XEvent evt, * text, we know the size. */ XGetWindowProperty(m_display, win, m_xclip_out, 0, (long) pty_size, False, AnyPropertyType, &pty_type, &pty_format, - &pty_items, &pty_size, (unsigned char **) &buffer); + &pty_items, &pty_size, &buffer); /* allocate memory to accommodate data in *txt */ if (*len == 0) { @@ -1538,12 +1538,12 @@ GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const if (sseln == m_clipboard) { sel_buf = (unsigned char *)malloc(strlen(txt_cut_buffer) + 1); strcpy((char *)sel_buf, txt_cut_buffer); - return((GHOST_TUns8 *)sel_buf); + return sel_buf; } else { sel_buf = (unsigned char *)malloc(strlen(txt_select_buffer) + 1); strcpy((char *)sel_buf, txt_select_buffer); - return((GHOST_TUns8 *)sel_buf); + return sel_buf; } } else if (owner == None) @@ -1594,7 +1594,7 @@ GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const else free(sel_buf); - return (GHOST_TUns8 *)tmp_data; + return tmp_data; } return(NULL); } @@ -1603,7 +1603,7 @@ void GHOST_SystemX11::putClipboard(GHOST_TInt8 *buffer, bool selection) const { Window m_window, owner; - vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows(); + vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows(); vector<GHOST_IWindow *>::iterator win_it = win_vec.begin(); GHOST_WindowX11 *window = static_cast<GHOST_WindowX11 *>(*win_it); m_window = window->getXWindow(); diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index bc556490d12..02c0109085a 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -230,7 +230,7 @@ public: /** * Puts buffer to system clipboard - * \param buffer The buffer to copy to the clipboard + * \param buffer The buffer to copy to the clipboard * \param selection Set the selection into the clipboard, X11 only feature */ void putClipboard(GHOST_TInt8 *buffer, bool selection) const; diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index dc05fe42a70..01705fe8f7b 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -28,7 +28,7 @@ #include <Cocoa/Cocoa.h> -#ifndef MAC_OS_X_VERSION_10_6 +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5 //Use of the SetSystemUIMode function (64bit compatible) #include <Carbon/Carbon.h> #endif @@ -58,7 +58,7 @@ extern "C" { extern void wm_draw_update(bContext *C); };*/ @interface CocoaWindowDelegate : NSObject -#ifdef MAC_OS_X_VERSION_10_6 +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 <NSWindowDelegate> #endif { @@ -115,12 +115,12 @@ extern "C" { - (void)windowDidResize:(NSNotification *)notification { -#ifdef MAC_OS_X_VERSION_10_6 +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 //if (![[notification object] inLiveResize]) { //Send event only once, at end of resize operation (when user has released mouse button) #endif systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, associatedWindow); -#ifdef MAC_OS_X_VERSION_10_6 +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 //} #endif /* Live resize ugly patch. Needed because live resize runs in a modal loop, not letting main loop run @@ -187,7 +187,7 @@ extern "C" { NSPoint mouseLocation = [sender draggingLocation]; systemCocoa->handleDraggingEvent(GHOST_kEventDraggingUpdated, m_draggedObjectType, associatedWindow, mouseLocation.x, mouseLocation.y, nil); - return associatedWindow->canAcceptDragOperation()?NSDragOperationCopy:NSDragOperationNone; + return associatedWindow->canAcceptDragOperation() ? NSDragOperationCopy : NSDragOperationNone; } - (void)draggingExited:(id < NSDraggingInfo >)sender @@ -368,7 +368,7 @@ extern "C" { - (BOOL)hasMarkedText { - return (composing)? YES: NO; + return (composing) ? YES : NO; } - (void)doCommandBySelector:(SEL)selector @@ -392,7 +392,7 @@ extern "C" { - (NSRange)markedRange { - unsigned int length = (composing_text)? [composing_text length]: 0; + unsigned int length = (composing_text) ? [composing_text length] : 0; if (composing) return NSMakeRange(0, length); @@ -402,7 +402,7 @@ extern "C" { - (NSRange)selectedRange { - unsigned int length = (composing_text)? [composing_text length]: 0; + unsigned int length = (composing_text) ? [composing_text length] : 0; return NSMakeRange(0, length); } @@ -637,7 +637,7 @@ void* GHOST_WindowCocoa::getOSWindow() const void GHOST_WindowCocoa::setTitle(const STR_String& title) { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString *windowTitle = [[NSString alloc] initWithCString:title encoding:NSUTF8StringEncoding]; @@ -684,7 +684,7 @@ void GHOST_WindowCocoa::setTitle(const STR_String& title) void GHOST_WindowCocoa::getTitle(STR_String& title) const { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -701,7 +701,7 @@ void GHOST_WindowCocoa::getTitle(STR_String& title) const void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect& bounds) const { NSRect rect; - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getWindowBounds(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getWindowBounds(): window invalid"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -721,7 +721,7 @@ void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect& bounds) const void GHOST_WindowCocoa::getClientBounds(GHOST_Rect& bounds) const { NSRect rect; - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getClientBounds(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getClientBounds(): window invalid"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -753,7 +753,7 @@ void GHOST_WindowCocoa::getClientBounds(GHOST_Rect& bounds) const GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width) { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientWidth(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientWidth(): window invalid"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; GHOST_Rect cBnds, wBnds; getClientBounds(cBnds); @@ -770,7 +770,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width) GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height) { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientHeight(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientHeight(): window invalid"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; GHOST_Rect cBnds, wBnds; getClientBounds(cBnds); @@ -787,7 +787,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height) GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientSize(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientSize(): window invalid"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; GHOST_Rect cBnds, wBnds; getClientBounds(cBnds); @@ -806,7 +806,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32 GHOST_TWindowState GHOST_WindowCocoa::getState() const { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getState(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getState(): window invalid"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; GHOST_TWindowState state; if (m_fullScreen) { @@ -828,7 +828,7 @@ GHOST_TWindowState GHOST_WindowCocoa::getState() const void GHOST_WindowCocoa::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::screenToClient(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::screenToClient(): window invalid"); screenToClientIntern(inX, inY, outX, outY); @@ -841,7 +841,7 @@ void GHOST_WindowCocoa::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST void GHOST_WindowCocoa::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::clientToScreen(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::clientToScreen(): window invalid"); /* switch y to match ghost convention */ GHOST_Rect cBnds; @@ -895,7 +895,7 @@ NSScreen* GHOST_WindowCocoa::getScreen() */ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setState(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setState(): window invalid"); switch (state) { case GHOST_kWindowStateMinimized: [m_window miniaturize:nil]; @@ -913,7 +913,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) * doesn't know view/window difference. */ m_fullScreen = true; -#ifdef MAC_OS_X_VERSION_10_6 +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 //10.6 provides Cocoa functions to autoshow menu bar, and to change a window style //Hide menu & dock if needed if ([[m_window screen] isEqual:[[NSScreen screens] objectAtIndex:0]]) { @@ -972,7 +972,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) m_fullScreen = false; //Exit fullscreen -#ifdef MAC_OS_X_VERSION_10_6 +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 //Show again menu & dock if needed if ([[m_window screen] isEqual:[NSScreen mainScreen]]) { [NSApp setPresentationOptions:NSApplicationPresentationDefault]; @@ -1049,7 +1049,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setOrder(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setOrder(): window invalid"); if (order == GHOST_kWindowOrderTop) { [m_window makeKeyAndOrderFront:nil]; } @@ -1199,7 +1199,7 @@ GHOST_TSuccess GHOST_WindowCocoa::removeDrawingContext() GHOST_TSuccess GHOST_WindowCocoa::invalidate() { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::invalidate(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::invalidate(): window invalid"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [m_openGLView setNeedsDisplay:YES]; [pool drain]; diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index 903e02e33d5..61bee046103 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -726,7 +726,7 @@ GHOST_TSuccess GHOST_WindowWin32::initMultisample(PIXELFORMATDESCRIPTOR pfd) }; // Get the function - PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); + PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); if (!wglChoosePixelFormatARB) { diff --git a/intern/ghost/test/multitest/EventToBuf.c b/intern/ghost/test/multitest/EventToBuf.c index aba80784a72..49255de5e64 100644 --- a/intern/ghost/test/multitest/EventToBuf.c +++ b/intern/ghost/test/multitest/EventToBuf.c @@ -197,15 +197,15 @@ static char *keytype_to_string(GHOST_TKey key) void event_to_buf(GHOST_EventHandle evt, char buf[128]) { - GHOST_TEventType type= GHOST_GetEventType(evt); - double time= (double) ((GHOST_TInt64) GHOST_GetEventTime(evt))/1000; - GHOST_WindowHandle win= GHOST_GetEventWindow(evt); - void *data= GHOST_GetEventData(evt); - char *pos= buf; + GHOST_TEventType type = GHOST_GetEventType(evt); + double time = (double) ((GHOST_TInt64) GHOST_GetEventTime(evt))/1000; + GHOST_WindowHandle win = GHOST_GetEventWindow(evt); + void *data = GHOST_GetEventData(evt); + char *pos = buf; pos += sprintf(pos, "event: %6.2f, %16s", time, eventtype_to_string(type)); if (win) { - char *s= GHOST_GetTitle(win); + char *s = GHOST_GetTitle(win); pos += sprintf(pos, " - win: %s", s); free(s); } @@ -215,14 +215,14 @@ void event_to_buf(GHOST_EventHandle evt, char buf[128]) switch (type) { case GHOST_kEventCursorMove: { - GHOST_TEventCursorData *cd= data; + GHOST_TEventCursorData *cd = data; pos += sprintf(pos, " - pos: (%d, %d)", cd->x, cd->y); break; } case GHOST_kEventButtonDown: case GHOST_kEventButtonUp: { - GHOST_TEventButtonData *bd= data; + GHOST_TEventButtonData *bd = data; pos += sprintf(pos, " - but: %d", bd->button); break; } @@ -230,7 +230,7 @@ void event_to_buf(GHOST_EventHandle evt, char buf[128]) case GHOST_kEventKeyDown: case GHOST_kEventKeyUp: { - GHOST_TEventKeyData *kd= data; + GHOST_TEventKeyData *kd = data; pos += sprintf(pos, " - key: %s (%d)", keytype_to_string(kd->key), kd->key); if (kd->ascii) pos+= sprintf(pos, " ascii: '%c' (%d)", kd->ascii, kd->ascii); break; diff --git a/intern/ghost/test/multitest/MultiTest.c b/intern/ghost/test/multitest/MultiTest.c index 5d207dafaaf..2d0afcf671c 100644 --- a/intern/ghost/test/multitest/MultiTest.c +++ b/intern/ghost/test/multitest/MultiTest.c @@ -26,9 +26,8 @@ */ #define FALSE 0 -#ifdef WIN32 - -#pragma warning(disable: 4244 4305) +#ifdef _MSC_VER +# pragma warning(disable: 4244 4305) #endif #include <stdlib.h> diff --git a/intern/guardedalloc/cpp/mallocn.cpp b/intern/guardedalloc/cpp/mallocn.cpp index da77f0e1c83..8b05d25018f 100644 --- a/intern/guardedalloc/cpp/mallocn.cpp +++ b/intern/guardedalloc/cpp/mallocn.cpp @@ -28,6 +28,9 @@ #include <new> #include "../MEM_guardedalloc.h" +void *operator new(size_t size, const char *str) throw(std::bad_alloc); +void *operator new[](size_t size, const char *str) throw(std::bad_alloc); + /* not default but can be used when needing to set a string */ void *operator new(size_t size, const char *str) throw(std::bad_alloc) { diff --git a/intern/itasc/CMakeLists.txt b/intern/itasc/CMakeLists.txt index f4bc0326ea1..bc3ea0cf24c 100644 --- a/intern/itasc/CMakeLists.txt +++ b/intern/itasc/CMakeLists.txt @@ -22,13 +22,13 @@ # Contributor(s): Jacques Beaurain. # # ***** END GPL LICENSE BLOCK ***** - +remove_strict_flags() set(INC - ../../extern/Eigen3 + ) set(INC_SYS - + ../../extern/Eigen3 ) set(SRC @@ -121,201 +121,235 @@ set(SRC kdl/framevel.inl # until we have another user... - ../../extern/Eigen3/Eigen/src/plugins/MatrixCwiseUnaryOps.h - ../../extern/Eigen3/Eigen/src/plugins/CommonCwiseUnaryOps.h - ../../extern/Eigen3/Eigen/src/plugins/MatrixCwiseBinaryOps.h - ../../extern/Eigen3/Eigen/src/plugins/BlockMethods.h - ../../extern/Eigen3/Eigen/src/plugins/ArrayCwiseUnaryOps.h - ../../extern/Eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.h - ../../extern/Eigen3/Eigen/src/plugins/CommonCwiseBinaryOps.h - ../../extern/Eigen3/Eigen/src/misc/Kernel.h - ../../extern/Eigen3/Eigen/src/misc/Image.h - ../../extern/Eigen3/Eigen/src/misc/Solve.h - ../../extern/Eigen3/Eigen/src/QR/HouseholderQR.h - ../../extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR.h - ../../extern/Eigen3/Eigen/src/QR/FullPivHouseholderQR.h - ../../extern/Eigen3/Eigen/src/StlSupport/details.h - ../../extern/Eigen3/Eigen/src/StlSupport/StdList.h - ../../extern/Eigen3/Eigen/src/StlSupport/StdDeque.h - ../../extern/Eigen3/Eigen/src/StlSupport/StdVector.h - ../../extern/Eigen3/Eigen/src/SVD/UpperBidiagonalization.h - ../../extern/Eigen3/Eigen/src/SVD/JacobiSVD.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexEigenSolver.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/HessenbergDecomposition.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/Tridiagonalization.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/RealSchur.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/EigenvaluesCommon.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h - ../../extern/Eigen3/Eigen/src/Jacobi/Jacobi.h - ../../extern/Eigen3/Eigen/src/Householder/Householder.h - ../../extern/Eigen3/Eigen/src/Householder/BlockHouseholder.h - ../../extern/Eigen3/Eigen/src/Householder/HouseholderSequence.h - ../../extern/Eigen3/Eigen/src/Geometry/RotationBase.h - ../../extern/Eigen3/Eigen/src/Geometry/Rotation2D.h - ../../extern/Eigen3/Eigen/src/Geometry/Homogeneous.h - ../../extern/Eigen3/Eigen/src/Geometry/Hyperplane.h - ../../extern/Eigen3/Eigen/src/Geometry/EulerAngles.h - ../../extern/Eigen3/Eigen/src/Geometry/arch/Geometry_SSE.h - ../../extern/Eigen3/Eigen/src/Geometry/ParametrizedLine.h - ../../extern/Eigen3/Eigen/src/Geometry/OrthoMethods.h - ../../extern/Eigen3/Eigen/src/Geometry/AngleAxis.h - ../../extern/Eigen3/Eigen/src/Geometry/Umeyama.h - ../../extern/Eigen3/Eigen/src/Geometry/Scaling.h - ../../extern/Eigen3/Eigen/src/Geometry/Translation.h - ../../extern/Eigen3/Eigen/src/Geometry/AlignedBox.h - ../../extern/Eigen3/Eigen/src/Geometry/Transform.h - ../../extern/Eigen3/Eigen/src/Geometry/Quaternion.h - ../../extern/Eigen3/Eigen/src/LU/PartialPivLU.h - ../../extern/Eigen3/Eigen/src/LU/Determinant.h - ../../extern/Eigen3/Eigen/src/LU/arch/Inverse_SSE.h - ../../extern/Eigen3/Eigen/src/LU/FullPivLU.h - ../../extern/Eigen3/Eigen/src/LU/Inverse.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseMatrixBase.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseSelfAdjointView.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseVector.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseDiagonalProduct.h - ../../extern/Eigen3/Eigen/src/Sparse/TriangularSolver.h - ../../extern/Eigen3/Eigen/src/Sparse/AmbiVector.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseDenseProduct.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseBlock.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseTriangularView.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseCwiseBinaryOp.h - ../../extern/Eigen3/Eigen/src/Sparse/CoreIterators.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseMatrix.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseAssign.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseSparseProduct.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseDot.h - ../../extern/Eigen3/Eigen/src/Sparse/DynamicSparseMatrix.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseRedux.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseFuzzy.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseCwiseUnaryOp.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseView.h - ../../extern/Eigen3/Eigen/src/Sparse/MappedSparseMatrix.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseUtil.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseTranspose.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseProduct.h - ../../extern/Eigen3/Eigen/src/Sparse/CompressedStorage.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Cwise.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/TriangularSolver.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/QR.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Lazy.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Memory.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/SVD.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/CwiseOperators.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/VectorBlock.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Meta.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Macros.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/LeastSquares.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/LU.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Block.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/RotationBase.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Rotation2D.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Hyperplane.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AngleAxis.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Scaling.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/All.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Translation.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AlignedBox.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Transform.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Quaternion.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Minor.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/MathFunctions.h - ../../extern/Eigen3/Eigen/src/Core/SelfAdjointView.h - ../../extern/Eigen3/Eigen/src/Core/MatrixBase.h - ../../extern/Eigen3/Eigen/src/Core/Swap.h - ../../extern/Eigen3/Eigen/src/Core/DenseCoeffsBase.h - ../../extern/Eigen3/Eigen/src/Core/DenseBase.h - ../../extern/Eigen3/Eigen/src/Core/GlobalFunctions.h - ../../extern/Eigen3/Eigen/src/Core/ProductBase.h - ../../extern/Eigen3/Eigen/src/Core/CwiseBinaryOp.h - ../../extern/Eigen3/Eigen/src/Core/Stride.h - ../../extern/Eigen3/Eigen/src/Core/Matrix.h - ../../extern/Eigen3/Eigen/src/Core/Visitor.h + ../../extern/Eigen3/Eigen/src/Cholesky/LDLT.h + ../../extern/Eigen3/Eigen/src/Cholesky/LLT.h + ../../extern/Eigen3/Eigen/src/Cholesky/LLT_MKL.h + ../../extern/Eigen3/Eigen/src/CholmodSupport/CholmodSupport.h ../../extern/Eigen3/Eigen/src/Core/Array.h - ../../extern/Eigen3/Eigen/src/Core/ReturnByValue.h - ../../extern/Eigen3/Eigen/src/Core/SelfCwiseBinaryOp.h - ../../extern/Eigen3/Eigen/src/Core/EigenBase.h - ../../extern/Eigen3/Eigen/src/Core/Random.h - ../../extern/Eigen3/Eigen/src/Core/Redux.h - ../../extern/Eigen3/Eigen/src/Core/arch/Default/Settings.h - ../../extern/Eigen3/Eigen/src/Core/arch/AltiVec/PacketMath.h - ../../extern/Eigen3/Eigen/src/Core/arch/AltiVec/Complex.h - ../../extern/Eigen3/Eigen/src/Core/arch/NEON/PacketMath.h - ../../extern/Eigen3/Eigen/src/Core/arch/NEON/Complex.h - ../../extern/Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h - ../../extern/Eigen3/Eigen/src/Core/arch/SSE/Complex.h - ../../extern/Eigen3/Eigen/src/Core/arch/SSE/MathFunctions.h - ../../extern/Eigen3/Eigen/src/Core/BooleanRedux.h - ../../extern/Eigen3/Eigen/src/Core/util/ReenableStupidWarnings.h - ../../extern/Eigen3/Eigen/src/Core/util/BlasUtil.h - ../../extern/Eigen3/Eigen/src/Core/util/Memory.h - ../../extern/Eigen3/Eigen/src/Core/util/Meta.h - ../../extern/Eigen3/Eigen/src/Core/util/Constants.h - ../../extern/Eigen3/Eigen/src/Core/util/Macros.h - ../../extern/Eigen3/Eigen/src/Core/util/ForwardDeclarations.h - ../../extern/Eigen3/Eigen/src/Core/util/StaticAssert.h - ../../extern/Eigen3/Eigen/src/Core/util/DisableStupidWarnings.h - ../../extern/Eigen3/Eigen/src/Core/util/XprHelper.h - ../../extern/Eigen3/Eigen/src/Core/VectorBlock.h - ../../extern/Eigen3/Eigen/src/Core/Transpositions.h - ../../extern/Eigen3/Eigen/src/Core/Select.h + ../../extern/Eigen3/Eigen/src/Core/ArrayBase.h + ../../extern/Eigen3/Eigen/src/Core/ArrayWrapper.h + ../../extern/Eigen3/Eigen/src/Core/Assign.h + ../../extern/Eigen3/Eigen/src/Core/Assign_MKL.h ../../extern/Eigen3/Eigen/src/Core/BandMatrix.h + ../../extern/Eigen3/Eigen/src/Core/Block.h + ../../extern/Eigen3/Eigen/src/Core/BooleanRedux.h + ../../extern/Eigen3/Eigen/src/Core/CommaInitializer.h + ../../extern/Eigen3/Eigen/src/Core/CwiseBinaryOp.h + ../../extern/Eigen3/Eigen/src/Core/CwiseNullaryOp.h + ../../extern/Eigen3/Eigen/src/Core/CwiseUnaryOp.h ../../extern/Eigen3/Eigen/src/Core/CwiseUnaryView.h + ../../extern/Eigen3/Eigen/src/Core/DenseBase.h + ../../extern/Eigen3/Eigen/src/Core/DenseCoeffsBase.h + ../../extern/Eigen3/Eigen/src/Core/DenseStorage.h + ../../extern/Eigen3/Eigen/src/Core/Diagonal.h + ../../extern/Eigen3/Eigen/src/Core/DiagonalMatrix.h + ../../extern/Eigen3/Eigen/src/Core/DiagonalProduct.h ../../extern/Eigen3/Eigen/src/Core/Dot.h + ../../extern/Eigen3/Eigen/src/Core/EigenBase.h + ../../extern/Eigen3/Eigen/src/Core/Flagged.h + ../../extern/Eigen3/Eigen/src/Core/ForceAlignedAccess.h + ../../extern/Eigen3/Eigen/src/Core/Functors.h + ../../extern/Eigen3/Eigen/src/Core/Fuzzy.h + ../../extern/Eigen3/Eigen/src/Core/GeneralProduct.h ../../extern/Eigen3/Eigen/src/Core/GenericPacketMath.h - ../../extern/Eigen3/Eigen/src/Core/Product.h - ../../extern/Eigen3/Eigen/src/Core/Transpose.h - ../../extern/Eigen3/Eigen/src/Core/Block.h - ../../extern/Eigen3/Eigen/src/Core/ArrayWrapper.h + ../../extern/Eigen3/Eigen/src/Core/GlobalFunctions.h + ../../extern/Eigen3/Eigen/src/Core/IO.h + ../../extern/Eigen3/Eigen/src/Core/Map.h ../../extern/Eigen3/Eigen/src/Core/MapBase.h + ../../extern/Eigen3/Eigen/src/Core/MathFunctions.h + ../../extern/Eigen3/Eigen/src/Core/Matrix.h + ../../extern/Eigen3/Eigen/src/Core/MatrixBase.h + ../../extern/Eigen3/Eigen/src/Core/NestByValue.h ../../extern/Eigen3/Eigen/src/Core/NoAlias.h - ../../extern/Eigen3/Eigen/src/Core/ForceAlignedAccess.h - ../../extern/Eigen3/Eigen/src/Core/PlainObjectBase.h - ../../extern/Eigen3/Eigen/src/Core/IO.h - ../../extern/Eigen3/Eigen/src/Core/DiagonalMatrix.h - ../../extern/Eigen3/Eigen/src/Core/CwiseUnaryOp.h - ../../extern/Eigen3/Eigen/src/Core/Reverse.h - ../../extern/Eigen3/Eigen/src/Core/Fuzzy.h - ../../extern/Eigen3/Eigen/src/Core/DenseStorage.h - ../../extern/Eigen3/Eigen/src/Core/StableNorm.h ../../extern/Eigen3/Eigen/src/Core/NumTraits.h - ../../extern/Eigen3/Eigen/src/Core/Map.h - ../../extern/Eigen3/Eigen/src/Core/Functors.h ../../extern/Eigen3/Eigen/src/Core/PermutationMatrix.h - ../../extern/Eigen3/Eigen/src/Core/ArrayBase.h - ../../extern/Eigen3/Eigen/src/Core/CwiseNullaryOp.h - ../../extern/Eigen3/Eigen/src/Core/SolveTriangular.h - ../../extern/Eigen3/Eigen/src/Core/NestByValue.h - ../../extern/Eigen3/Eigen/src/Core/DiagonalProduct.h - ../../extern/Eigen3/Eigen/src/Core/CommaInitializer.h - ../../extern/Eigen3/Eigen/src/Core/MathFunctions.h - ../../extern/Eigen3/Eigen/src/Core/Diagonal.h + ../../extern/Eigen3/Eigen/src/Core/PlainObjectBase.h + ../../extern/Eigen3/Eigen/src/Core/Product.h + ../../extern/Eigen3/Eigen/src/Core/ProductBase.h + ../../extern/Eigen3/Eigen/src/Core/Random.h + ../../extern/Eigen3/Eigen/src/Core/Redux.h ../../extern/Eigen3/Eigen/src/Core/Replicate.h - ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix.h - ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointProduct.h - ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector.h + ../../extern/Eigen3/Eigen/src/Core/ReturnByValue.h + ../../extern/Eigen3/Eigen/src/Core/Reverse.h + ../../extern/Eigen3/Eigen/src/Core/Select.h + ../../extern/Eigen3/Eigen/src/Core/SelfAdjointView.h + ../../extern/Eigen3/Eigen/src/Core/SelfCwiseBinaryOp.h + ../../extern/Eigen3/Eigen/src/Core/SolveTriangular.h + ../../extern/Eigen3/Eigen/src/Core/StableNorm.h + ../../extern/Eigen3/Eigen/src/Core/Stride.h + ../../extern/Eigen3/Eigen/src/Core/Swap.h + ../../extern/Eigen3/Eigen/src/Core/Transpose.h + ../../extern/Eigen3/Eigen/src/Core/Transpositions.h + ../../extern/Eigen3/Eigen/src/Core/TriangularMatrix.h + ../../extern/Eigen3/Eigen/src/Core/VectorBlock.h + ../../extern/Eigen3/Eigen/src/Core/VectorwiseOp.h + ../../extern/Eigen3/Eigen/src/Core/Visitor.h + ../../extern/Eigen3/Eigen/src/Core/arch/AltiVec/Complex.h + ../../extern/Eigen3/Eigen/src/Core/arch/AltiVec/PacketMath.h + ../../extern/Eigen3/Eigen/src/Core/arch/Default/Settings.h + ../../extern/Eigen3/Eigen/src/Core/arch/NEON/Complex.h + ../../extern/Eigen3/Eigen/src/Core/arch/NEON/PacketMath.h + ../../extern/Eigen3/Eigen/src/Core/arch/SSE/Complex.h + ../../extern/Eigen3/Eigen/src/Core/arch/SSE/MathFunctions.h + ../../extern/Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h ../../extern/Eigen3/Eigen/src/Core/products/CoeffBasedProduct.h - ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector.h - ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointRank2Update.h - ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h + ../../extern/Eigen3/Eigen/src/Core/products/GeneralBlockPanelKernel.h ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix.h - ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix.h + ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h + ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_MKL.h + ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix_MKL.h + ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector.h + ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector_MKL.h ../../extern/Eigen3/Eigen/src/Core/products/Parallelizer.h + ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix.h + ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix_MKL.h + ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector.h + ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector_MKL.h + ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointProduct.h + ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointRank2Update.h + ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix.h + ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h + ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector.h + ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector_MKL.h ../../extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix.h + ../../extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix_MKL.h ../../extern/Eigen3/Eigen/src/Core/products/TriangularSolverVector.h - ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector.h - ../../extern/Eigen3/Eigen/src/Core/products/GeneralBlockPanelKernel.h - ../../extern/Eigen3/Eigen/src/Core/TriangularMatrix.h - ../../extern/Eigen3/Eigen/src/Core/VectorwiseOp.h - ../../extern/Eigen3/Eigen/src/Core/Assign.h - ../../extern/Eigen3/Eigen/src/Core/Flagged.h - ../../extern/Eigen3/Eigen/src/Cholesky/LDLT.h - ../../extern/Eigen3/Eigen/src/Cholesky/LLT.h + ../../extern/Eigen3/Eigen/src/Core/util/BlasUtil.h + ../../extern/Eigen3/Eigen/src/Core/util/Constants.h + ../../extern/Eigen3/Eigen/src/Core/util/DisableStupidWarnings.h + ../../extern/Eigen3/Eigen/src/Core/util/ForwardDeclarations.h + ../../extern/Eigen3/Eigen/src/Core/util/Macros.h + ../../extern/Eigen3/Eigen/src/Core/util/Memory.h + ../../extern/Eigen3/Eigen/src/Core/util/Meta.h + ../../extern/Eigen3/Eigen/src/Core/util/MKL_support.h + ../../extern/Eigen3/Eigen/src/Core/util/NonMPL2.h + ../../extern/Eigen3/Eigen/src/Core/util/ReenableStupidWarnings.h + ../../extern/Eigen3/Eigen/src/Core/util/StaticAssert.h + ../../extern/Eigen3/Eigen/src/Core/util/XprHelper.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Block.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Cwise.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/CwiseOperators.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Lazy.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/LeastSquares.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/LU.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Macros.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/MathFunctions.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Memory.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Meta.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Minor.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/QR.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/SVD.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/TriangularSolver.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/VectorBlock.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AlignedBox.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/All.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AngleAxis.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Hyperplane.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Quaternion.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Rotation2D.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/RotationBase.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Scaling.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Transform.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Translation.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexEigenSolver.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur_MKL.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/HessenbergDecomposition.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/RealSchur.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/RealSchur_MKL.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_MKL.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/Tridiagonalization.h + ../../extern/Eigen3/Eigen/src/Geometry/AlignedBox.h + ../../extern/Eigen3/Eigen/src/Geometry/AngleAxis.h + ../../extern/Eigen3/Eigen/src/Geometry/EulerAngles.h + ../../extern/Eigen3/Eigen/src/Geometry/Homogeneous.h + ../../extern/Eigen3/Eigen/src/Geometry/Hyperplane.h + ../../extern/Eigen3/Eigen/src/Geometry/OrthoMethods.h + ../../extern/Eigen3/Eigen/src/Geometry/ParametrizedLine.h + ../../extern/Eigen3/Eigen/src/Geometry/Quaternion.h + ../../extern/Eigen3/Eigen/src/Geometry/Rotation2D.h + ../../extern/Eigen3/Eigen/src/Geometry/RotationBase.h + ../../extern/Eigen3/Eigen/src/Geometry/Scaling.h + ../../extern/Eigen3/Eigen/src/Geometry/Transform.h + ../../extern/Eigen3/Eigen/src/Geometry/Translation.h + ../../extern/Eigen3/Eigen/src/Geometry/Umeyama.h + ../../extern/Eigen3/Eigen/src/Geometry/arch/Geometry_SSE.h + ../../extern/Eigen3/Eigen/src/Householder/BlockHouseholder.h + ../../extern/Eigen3/Eigen/src/Householder/Householder.h + ../../extern/Eigen3/Eigen/src/Householder/HouseholderSequence.h + ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h + ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h + ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h + ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h + ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h + ../../extern/Eigen3/Eigen/src/Jacobi/Jacobi.h + ../../extern/Eigen3/Eigen/src/LU/Determinant.h + ../../extern/Eigen3/Eigen/src/LU/FullPivLU.h + ../../extern/Eigen3/Eigen/src/LU/Inverse.h + ../../extern/Eigen3/Eigen/src/LU/PartialPivLU.h + ../../extern/Eigen3/Eigen/src/LU/PartialPivLU_MKL.h + ../../extern/Eigen3/Eigen/src/LU/arch/Inverse_SSE.h + ../../extern/Eigen3/Eigen/src/misc/blas.h + ../../extern/Eigen3/Eigen/src/misc/Image.h + ../../extern/Eigen3/Eigen/src/misc/Kernel.h + ../../extern/Eigen3/Eigen/src/misc/Solve.h + ../../extern/Eigen3/Eigen/src/misc/SparseSolve.h + ../../extern/Eigen3/Eigen/src/OrderingMethods/Amd.h + ../../extern/Eigen3/Eigen/src/PardisoSupport/PardisoSupport.h + ../../extern/Eigen3/Eigen/src/PaStiXSupport/PaStiXSupport.h + ../../extern/Eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.h + ../../extern/Eigen3/Eigen/src/plugins/ArrayCwiseUnaryOps.h + ../../extern/Eigen3/Eigen/src/plugins/BlockMethods.h + ../../extern/Eigen3/Eigen/src/plugins/CommonCwiseBinaryOps.h + ../../extern/Eigen3/Eigen/src/plugins/CommonCwiseUnaryOps.h + ../../extern/Eigen3/Eigen/src/plugins/MatrixCwiseBinaryOps.h + ../../extern/Eigen3/Eigen/src/plugins/MatrixCwiseUnaryOps.h + ../../extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR.h + ../../extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR_MKL.h + ../../extern/Eigen3/Eigen/src/QR/FullPivHouseholderQR.h + ../../extern/Eigen3/Eigen/src/QR/HouseholderQR.h + ../../extern/Eigen3/Eigen/src/QR/HouseholderQR_MKL.h + ../../extern/Eigen3/Eigen/src/SparseCholesky/SimplicialCholesky.h + ../../extern/Eigen3/Eigen/src/SparseCore/AmbiVector.h + ../../extern/Eigen3/Eigen/src/SparseCore/CompressedStorage.h + ../../extern/Eigen3/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h + ../../extern/Eigen3/Eigen/src/SparseCore/CoreIterators.h + ../../extern/Eigen3/Eigen/src/SparseCore/MappedSparseMatrix.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseAssign.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseBlock.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseCwiseBinaryOp.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseCwiseUnaryOp.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseDenseProduct.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseDiagonalProduct.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseDot.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseFuzzy.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseMatrix.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseMatrixBase.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparsePermutation.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseProduct.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseRedux.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseSelfAdjointView.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseSparseProductWithPruning.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseTranspose.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseTriangularView.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseUtil.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseVector.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseView.h + ../../extern/Eigen3/Eigen/src/SparseCore/TriangularSolver.h + ../../extern/Eigen3/Eigen/src/StlSupport/details.h + ../../extern/Eigen3/Eigen/src/StlSupport/StdDeque.h + ../../extern/Eigen3/Eigen/src/StlSupport/StdList.h + ../../extern/Eigen3/Eigen/src/StlSupport/StdVector.h + ../../extern/Eigen3/Eigen/src/SuperLUSupport/SuperLUSupport.h + ../../extern/Eigen3/Eigen/src/SVD/JacobiSVD.h + ../../extern/Eigen3/Eigen/src/SVD/JacobiSVD_MKL.h + ../../extern/Eigen3/Eigen/src/SVD/UpperBidiagonalization.h + ../../extern/Eigen3/Eigen/src/UmfPackSupport/UmfPackSupport.h ) diff --git a/intern/itasc/Scene.cpp b/intern/itasc/Scene.cpp index 7a83f821bf0..7ed8fc4e63c 100644 --- a/intern/itasc/Scene.cpp +++ b/intern/itasc/Scene.cpp @@ -40,7 +40,7 @@ public: { q_nr += m_qrange.start; project(m_scene->m_Wq, Range(q_nr, ndof), m_qrange).setZero(); - // update the ouput vector so that the movement of this joint will be + // update the output vector so that the movement of this joint will be // taken into account and we can put the joint back in its initial position // which means that the jacobian doesn't need to be changed for (unsigned int i=0 ;i<ndof ; ++i, ++q_nr) { diff --git a/intern/itasc/kdl/chain.hpp b/intern/itasc/kdl/chain.hpp index 773f472cc5c..fde9d4ed23e 100644 --- a/intern/itasc/kdl/chain.hpp +++ b/intern/itasc/kdl/chain.hpp @@ -35,11 +35,16 @@ namespace KDL { */ class Chain { private: -#if !defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_5) +#if defined(__APPLE__) +# if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5 + std::vector<Segment> segments; +# else // Eigen allocator is needed for alignment of Eigen data types std::vector<Segment, Eigen::aligned_allocator<Segment> > segments; +# endif /* MAC_OS_X_VERSION_MIN_REQUIRED */ #else - std::vector<Segment> segments; + // Eigen allocator is needed for alignment of Eigen data types + std::vector<Segment, Eigen::aligned_allocator<Segment> > segments; #endif unsigned int nrOfJoints; unsigned int nrOfSegments; diff --git a/intern/itasc/kdl/tree.hpp b/intern/itasc/kdl/tree.hpp index 08c1aadc6de..a020c6cf2cf 100644 --- a/intern/itasc/kdl/tree.hpp +++ b/intern/itasc/kdl/tree.hpp @@ -27,19 +27,30 @@ #include <string> #include <map> -#if !defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_5) -#include <Eigen/Core> +#if defined(__APPLE__) +# if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5 + //no include +# else +# include <Eigen/Core> +# endif /* MAC_OS_X_VERSION_MIN_REQUIRED */ +#else +# include <Eigen/Core> #endif namespace KDL { //Forward declaration class TreeElement; -#if !defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_5) +#if defined(__APPLE__) +# if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5 + typedef std::map<std::string,TreeElement> SegmentMap; +# else // Eigen allocator is needed for alignment of Eigen data types typedef std::map<std::string,TreeElement, std::less<std::string>, Eigen::aligned_allocator<std::pair<std::string, TreeElement> > > SegmentMap; +# endif /* MAC_OS_X_VERSION_MIN_REQUIRED */ #else - typedef std::map<std::string,TreeElement> SegmentMap; + // Eigen allocator is needed for alignment of Eigen data types + typedef std::map<std::string,TreeElement, std::less<std::string>, Eigen::aligned_allocator<std::pair<std::string, TreeElement> > > SegmentMap; #endif class TreeElement { diff --git a/intern/memutil/MEM_CacheLimiterC-Api.h b/intern/memutil/MEM_CacheLimiterC-Api.h index 1ae5e9df1c6..c05c9d61ea2 100644 --- a/intern/memutil/MEM_CacheLimiterC-Api.h +++ b/intern/memutil/MEM_CacheLimiterC-Api.h @@ -80,7 +80,7 @@ void delete_MEM_CacheLimiter(MEM_CacheLimiterC *This); * @return CacheLimiterHandle to ref, unref, touch the managed object */ -MEM_CacheLimiterHandleC *MEM_CacheLimiter_insert(MEM_CacheLimiterC * This, void * data); +MEM_CacheLimiterHandleC *MEM_CacheLimiter_insert(MEM_CacheLimiterC *This, void *data); /** * Free objects until memory constraints are satisfied @@ -140,7 +140,7 @@ int MEM_CacheLimiter_get_refcount(MEM_CacheLimiterHandleC *handle); * @param handle of object */ -void * MEM_CacheLimiter_get(MEM_CacheLimiterHandleC *handle); +void *MEM_CacheLimiter_get(MEM_CacheLimiterHandleC *handle); void MEM_CacheLimiter_ItemPriority_Func_set(MEM_CacheLimiterC *This, MEM_CacheLimiter_ItemPriority_Func item_priority_func); diff --git a/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp b/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp index 81a1ce670ae..7a19543b2db 100644 --- a/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp +++ b/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp @@ -59,9 +59,9 @@ public: } ~MEM_CacheLimiterCClass(); - handle_t * insert(void * data); + handle_t * insert(void *data); - void destruct(void * data, list_t::iterator it); + void destruct(void *data, list_t::iterator it); cache_t * get_cache() { return &cache; @@ -76,7 +76,7 @@ private: class MEM_CacheLimiterHandleCClass { public: - MEM_CacheLimiterHandleCClass(void * data_, MEM_CacheLimiterCClass * parent_) : + MEM_CacheLimiterHandleCClass(void *data_, MEM_CacheLimiterCClass *parent_) : data(data_), parent(parent_) { } @@ -87,7 +87,7 @@ public: it = it_; } - void set_data(void * data_) { + void set_data(void *data_) { data = data_; } @@ -101,7 +101,7 @@ private: list_t::iterator it; }; -handle_t *MEM_CacheLimiterCClass::insert(void * data) +handle_t *MEM_CacheLimiterCClass::insert(void *data) { cclass_list.push_back(new MEM_CacheLimiterHandleCClass(data, this)); list_t::iterator it = cclass_list.end(); @@ -111,7 +111,7 @@ handle_t *MEM_CacheLimiterCClass::insert(void * data) return cache.insert(cclass_list.back()); } -void MEM_CacheLimiterCClass::destruct(void * data, list_t::iterator it) +void MEM_CacheLimiterCClass::destruct(void *data, list_t::iterator it) { data_destructor(data); cclass_list.erase(it); diff --git a/intern/opencolorio/CMakeLists.txt b/intern/opencolorio/CMakeLists.txt index d46b09cf76a..c281a6e7bbb 100644 --- a/intern/opencolorio/CMakeLists.txt +++ b/intern/opencolorio/CMakeLists.txt @@ -30,6 +30,7 @@ set(INC ) set(INC_SYS + ) set(SRC diff --git a/intern/opennl/CMakeLists.txt b/intern/opennl/CMakeLists.txt index 4f96587953f..2f15bbb907c 100644 --- a/intern/opennl/CMakeLists.txt +++ b/intern/opennl/CMakeLists.txt @@ -40,11 +40,10 @@ add_definitions( set(INC extern superlu - ../../extern/colamd/Include ) set(INC_SYS - + ../../extern/colamd/Include ) set(SRC diff --git a/intern/opennl/SConscript b/intern/opennl/SConscript index 711955cbfeb..a0f02735748 100644 --- a/intern/opennl/SConscript +++ b/intern/opennl/SConscript @@ -5,8 +5,5 @@ sources = env.Glob('intern/*.c') + env.Glob('superlu/*.c') incs = 'extern superlu ../../extern/colamd/Include' -if (env['OURPLATFORM'] in ('win32-mingw', 'win64-mingw')): - env.BlenderLib ('bf_intern_opennl', sources, Split(incs), [], libtype=['core','intern'], priority=[1,80] ) -else: - env.BlenderLib ('bf_intern_opennl', sources, Split(incs), [], libtype=['core'], priority=[55] ) +env.BlenderLib ('bf_intern_opennl', sources, Split(incs), [], libtype=['intern','player'], priority=[100,90] ) diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index c79bcc4a76d..21153082324 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -113,7 +113,7 @@ static void preprocess_all_edges(struct r_FillContext *ctx, ctx->rb.xmin = xbeg; } if (ybeg >= ctx->rb.ymax) { - ctx->rb.ymax= ybeg; + ctx->rb.ymax = ybeg; } else if (ybeg <= ctx->rb.ymin) { ctx->rb.ymin=ybeg; diff --git a/intern/smoke/CMakeLists.txt b/intern/smoke/CMakeLists.txt index 9524f7b2935..3b8a4c06e69 100644 --- a/intern/smoke/CMakeLists.txt +++ b/intern/smoke/CMakeLists.txt @@ -26,10 +26,10 @@ set(INC intern ../memutil - ../../extern/bullet2/src ) set(INC_SYS + ../../extern/bullet2/src ${PNG_INCLUDE_DIR} ${ZLIB_INCLUDE_DIRS} ) @@ -40,6 +40,7 @@ set(SRC intern/FLUID_3D_SOLVERS.cpp intern/FLUID_3D_STATIC.cpp intern/LU_HELPER.cpp + intern/spectrum.cpp intern/SPHERE.cpp intern/WTURBULENCE.cpp intern/smoke_API.cpp @@ -53,6 +54,7 @@ set(SRC intern/LU_HELPER.h intern/MERSENNETWISTER.h intern/OBSTACLE.h + intern/spectrum.h intern/SPHERE.h intern/VEC3.h intern/WAVELET_NOISE.h diff --git a/intern/smoke/extern/smoke_API.h b/intern/smoke/extern/smoke_API.h index a0eb1bf38e0..98c63f08fbd 100644 --- a/intern/smoke/extern/smoke_API.h +++ b/intern/smoke/extern/smoke_API.h @@ -37,17 +37,23 @@ extern "C" { struct FLUID_3D; -// export -void smoke_export(struct FLUID_3D *fluid, float *dt, float *dx, float **dens, float **densold, float **heat, float **heatold, float **vx, float **vy, float **vz, float **vxold, float **vyold, float **vzold, unsigned char **obstacles); - // low res -struct FLUID_3D *smoke_init(int *res, float *p0, float dtdef); +struct FLUID_3D *smoke_init(int *res, float dx, float dtdef, int use_heat, int use_fire, int use_colors); void smoke_free(struct FLUID_3D *fluid); -void smoke_initBlenderRNA(struct FLUID_3D *fluid, float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli); -void smoke_step(struct FLUID_3D *fluid, float dtSubdiv); +void smoke_initBlenderRNA(struct FLUID_3D *fluid, float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli, float *burning_rate, + float *flame_smoke, float *flame_smoke_color, float *flame_vorticity, float *flame_ignition_temp, float *flame_max_temp); +void smoke_step(struct FLUID_3D *fluid, float gravity[3], float dtSubdiv); float *smoke_get_density(struct FLUID_3D *fluid); +float *smoke_get_flame(struct FLUID_3D *fluid); +float *smoke_get_fuel(struct FLUID_3D *fluid); +float *smoke_get_react(struct FLUID_3D *fluid); +float *smoke_get_color_r(struct FLUID_3D *fluid); +float *smoke_get_color_g(struct FLUID_3D *fluid); +float *smoke_get_color_b(struct FLUID_3D *fluid); +void smoke_get_rgba(struct FLUID_3D *fluid, float *data, int sequential); +void smoke_get_rgba_from_density(struct FLUID_3D *fluid, float color[3], float *data, int sequential); float *smoke_get_heat(struct FLUID_3D *fluid); float *smoke_get_velocity_x(struct FLUID_3D *fluid); float *smoke_get_velocity_y(struct FLUID_3D *fluid); @@ -68,19 +74,44 @@ size_t smoke_get_index2d(int x, int max_x, int y); void smoke_dissolve(struct FLUID_3D *fluid, int speed, int log); // wavelet turbulence functions -struct WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype); +struct WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype, int use_fire, int use_colors); void smoke_turbulence_free(struct WTURBULENCE *wt); void smoke_turbulence_step(struct WTURBULENCE *wt, struct FLUID_3D *fluid); float *smoke_turbulence_get_density(struct WTURBULENCE *wt); +float *smoke_turbulence_get_color_r(struct WTURBULENCE *wt); +float *smoke_turbulence_get_color_g(struct WTURBULENCE *wt); +float *smoke_turbulence_get_color_b(struct WTURBULENCE *wt); +void smoke_turbulence_get_rgba(struct WTURBULENCE *wt, float *data, int sequential); +void smoke_turbulence_get_rgba_from_density(struct WTURBULENCE *wt, float color[3], float *data, int sequential); +float *smoke_turbulence_get_flame(struct WTURBULENCE *wt); +float *smoke_turbulence_get_fuel(struct WTURBULENCE *wt); +float *smoke_turbulence_get_react(struct WTURBULENCE *wt); void smoke_turbulence_get_res(struct WTURBULENCE *wt, int *res); +int smoke_turbulence_get_cells(struct WTURBULENCE *wt); void smoke_turbulence_set_noise(struct WTURBULENCE *wt, int type); void smoke_initWaveletBlenderRNA(struct WTURBULENCE *wt, float *strength); - void smoke_dissolve_wavelet(struct WTURBULENCE *wt, int speed, int log); -// export -void smoke_turbulence_export(struct WTURBULENCE *wt, float **dens, float **densold, float **tcu, float **tcv, float **tcw); +/* export */ +void smoke_export(struct FLUID_3D *fluid, float *dt, float *dx, float **dens, float **react, float **flame, float **fuel, float **heat, float **heatold, + float **vx, float **vy, float **vz, float **r, float **g, float **b, unsigned char **obstacles); +void smoke_turbulence_export(struct WTURBULENCE *wt, float **dens, float **react, float **flame, float **fuel, + float **r, float **g, float **b, float **tcu, float **tcv, float **tcw); + +/* flame spectrum */ +void flame_get_spectrum(unsigned char *spec, int width, float t1, float t2); + +/* data fields */ +int smoke_has_heat(struct FLUID_3D *fluid); +int smoke_has_fuel(struct FLUID_3D *fluid); +int smoke_has_colors(struct FLUID_3D *fluid); +int smoke_turbulence_has_fuel(struct WTURBULENCE *wt); +int smoke_turbulence_has_colors(struct WTURBULENCE *wt); + +void smoke_ensure_heat(struct FLUID_3D *fluid); +void smoke_ensure_fire(struct FLUID_3D *fluid, struct WTURBULENCE *wt); +void smoke_ensure_colors(struct FLUID_3D *fluid, struct WTURBULENCE *wt, float init_r, float init_g, float init_b); #ifdef __cplusplus } diff --git a/intern/smoke/intern/FLUID_3D.cpp b/intern/smoke/intern/FLUID_3D.cpp index e006132ea8f..4eb11a46f5b 100644 --- a/intern/smoke/intern/FLUID_3D.cpp +++ b/intern/smoke/intern/FLUID_3D.cpp @@ -44,16 +44,11 @@ // Construction/Destruction ////////////////////////////////////////////////////////////////////// -FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) : +FLUID_3D::FLUID_3D(int *res, float dx, float dtdef, int init_heat, int init_fire, int init_colors) : _xRes(res[0]), _yRes(res[1]), _zRes(res[2]), _res(0.0f) { // set simulation consts _dt = dtdef; // just in case. set in step from a RNA factor - - // start point of array - _p0[0] = p0[0]; - _p0[1] = p0[1]; - _p0[2] = p0[2]; _iterations = 100; _tempAmb = 0; @@ -72,7 +67,10 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) : */ // scale the constants according to the refinement of the grid - _dx = 1.0f / (float)_maxRes; + if (!dx) + _dx = 1.0f / (float)_maxRes; + else + _dx = dx; _constantScaling = 64.0f / _maxRes; _constantScaling = (_constantScaling < 1.0f) ? 1.0f : _constantScaling; _vorticityEps = 2.0f / _constantScaling; // Just in case set a default value @@ -94,8 +92,6 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) : _zForce = new float[_totalCells]; _density = new float[_totalCells]; _densityOld = new float[_totalCells]; - _heat = new float[_totalCells]; - _heatOld = new float[_totalCells]; _obstacles = new unsigned char[_totalCells]; // set 0 at end of step // For threaded version: @@ -103,7 +99,6 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) : _yVelocityTemp = new float[_totalCells]; _zVelocityTemp = new float[_totalCells]; _densityTemp = new float[_totalCells]; - _heatTemp = new float[_totalCells]; // DG TODO: check if alloc went fine @@ -111,8 +106,6 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) : { _density[x] = 0.0f; _densityOld[x] = 0.0f; - _heat[x] = 0.0f; - _heatOld[x] = 0.0f; _xVelocity[x] = 0.0f; _yVelocity[x] = 0.0f; _zVelocity[x] = 0.0f; @@ -128,6 +121,25 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) : _obstacles[x] = false; } + /* heat */ + _heat = _heatOld = _heatTemp = NULL; + if (init_heat) { + initHeat(); + } + // Fire simulation + _flame = _fuel = _fuelTemp = _fuelOld = NULL; + _react = _reactTemp = _reactOld = NULL; + if (init_fire) { + initFire(); + } + // Smoke color + _color_r = _color_rOld = _color_rTemp = NULL; + _color_g = _color_gOld = _color_gTemp = NULL; + _color_b = _color_bOld = _color_bTemp = NULL; + if (init_colors) { + initColors(0.0f, 0.0f, 0.0f); + } + // boundary conditions of the fluid domain // set default values -> vertically non-colliding _domainBcFront = true; @@ -138,9 +150,70 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) : _domainBcRight = _domainBcLeft; _colloPrev = 1; // default value +} - setBorderObstacles(); // walls +void FLUID_3D::initHeat() +{ + if (!_heat) { + _heat = new float[_totalCells]; + _heatOld = new float[_totalCells]; + _heatTemp = new float[_totalCells]; + for (int x = 0; x < _totalCells; x++) + { + _heat[x] = 0.0f; + _heatOld[x] = 0.0f; + } + } +} + +void FLUID_3D::initFire() +{ + if (!_flame) { + _flame = new float[_totalCells]; + _fuel = new float[_totalCells]; + _fuelTemp = new float[_totalCells]; + _fuelOld = new float[_totalCells]; + _react = new float[_totalCells]; + _reactTemp = new float[_totalCells]; + _reactOld = new float[_totalCells]; + + for (int x = 0; x < _totalCells; x++) + { + _flame[x] = 0.0f; + _fuel[x] = 0.0f; + _fuelTemp[x] = 0.0f; + _fuelOld[x] = 0.0f; + _react[x] = 0.0f; + _reactTemp[x] = 0.0f; + _reactOld[x] = 0.0f; + } + } +} + +void FLUID_3D::initColors(float init_r, float init_g, float init_b) +{ + if (!_color_r) { + _color_r = new float[_totalCells]; + _color_rOld = new float[_totalCells]; + _color_rTemp = new float[_totalCells]; + _color_g = new float[_totalCells]; + _color_gOld = new float[_totalCells]; + _color_gTemp = new float[_totalCells]; + _color_b = new float[_totalCells]; + _color_bOld = new float[_totalCells]; + _color_bTemp = new float[_totalCells]; + + for (int x = 0; x < _totalCells; x++) + { + _color_r[x] = _density[x] * init_r; + _color_rOld[x] = 0.0f; + _color_g[x] = _density[x] * init_g; + _color_gOld[x] = 0.0f; + _color_b[x] = _density[x] * init_b; + _color_bOld[x] = 0.0f; + } + } } void FLUID_3D::setBorderObstacles() @@ -204,7 +277,6 @@ FLUID_3D::~FLUID_3D() if (_heat) delete[] _heat; if (_heatOld) delete[] _heatOld; if (_obstacles) delete[] _obstacles; - // if (_wTurbulence) delete _wTurbulence; if (_xVelocityTemp) delete[] _xVelocityTemp; if (_yVelocityTemp) delete[] _yVelocityTemp; @@ -212,23 +284,48 @@ FLUID_3D::~FLUID_3D() if (_densityTemp) delete[] _densityTemp; if (_heatTemp) delete[] _heatTemp; + if (_flame) delete[] _flame; + if (_fuel) delete[] _fuel; + if (_fuelTemp) delete[] _fuelTemp; + if (_fuelOld) delete[] _fuelOld; + if (_react) delete[] _react; + if (_reactTemp) delete[] _reactTemp; + if (_reactOld) delete[] _reactOld; + + if (_color_r) delete[] _color_r; + if (_color_rOld) delete[] _color_rOld; + if (_color_rTemp) delete[] _color_rTemp; + if (_color_g) delete[] _color_g; + if (_color_gOld) delete[] _color_gOld; + if (_color_gTemp) delete[] _color_gTemp; + if (_color_b) delete[] _color_b; + if (_color_bOld) delete[] _color_bOld; + if (_color_bTemp) delete[] _color_bTemp; + // printf("deleted fluid\n"); } // init direct access functions from blender -void FLUID_3D::initBlenderRNA(float *alpha, float *beta, float *dt_factor, float *vorticity, int *borderCollision) +void FLUID_3D::initBlenderRNA(float *alpha, float *beta, float *dt_factor, float *vorticity, int *borderCollision, float *burning_rate, + float *flame_smoke, float *flame_smoke_color, float *flame_vorticity, float *flame_ignition_temp, float *flame_max_temp) { _alpha = alpha; _beta = beta; _dtFactor = dt_factor; _vorticityRNA = vorticity; _borderColli = borderCollision; + _burning_rate = burning_rate; + _flame_smoke = flame_smoke; + _flame_smoke_color = flame_smoke_color; + _flame_vorticity = flame_vorticity; + _ignition_temp = flame_ignition_temp; + _max_temp = flame_max_temp; } ////////////////////////////////////////////////////////////////////// // step simulation once ////////////////////////////////////////////////////////////////////// -void FLUID_3D::step(float dt) +void FLUID_3D::step(float dt, float gravity[3]) { #if 0 // If border rules have been changed @@ -281,7 +378,7 @@ void FLUID_3D::step(float dt) wipeBoundariesSL(zBegin, zEnd); addVorticity(zBegin, zEnd); - addBuoyancy(_heat, _density, zBegin, zEnd); + addBuoyancy(_heat, _density, gravity, zBegin, zEnd); addForce(zBegin, zEnd); #if PARALLEL==1 @@ -312,13 +409,15 @@ void FLUID_3D::step(float dt) if (i==0) { #endif - project(); + project(); #if PARALLEL==1 } - else + else if (i==1) { #endif - diffuseHeat(); + if (_heat) { + diffuseHeat(); + } #if PARALLEL==1 } } @@ -338,6 +437,13 @@ void FLUID_3D::step(float dt) SWAP_POINTERS(_density, _densityOld); SWAP_POINTERS(_heat, _heatOld); + SWAP_POINTERS(_fuel, _fuelOld); + SWAP_POINTERS(_react, _reactOld); + + SWAP_POINTERS(_color_r, _color_rOld); + SWAP_POINTERS(_color_g, _color_gOld); + SWAP_POINTERS(_color_b, _color_bOld); + advectMacCormackBegin(0, _zRes); #if PARALLEL==1 @@ -398,11 +504,8 @@ void FLUID_3D::step(float dt) SWAP_POINTERS(_yVelocity, _yForce); SWAP_POINTERS(_zVelocity, _zForce); - - - _totalTime += _dt; - _totalSteps++; + _totalSteps++; for (int i = 0; i < _totalCells; i++) { @@ -643,6 +746,15 @@ void FLUID_3D::wipeBoundaries(int zBegin, int zEnd) setZeroBorder(_yVelocity, _res, zBegin, zEnd); setZeroBorder(_zVelocity, _res, zBegin, zEnd); setZeroBorder(_density, _res, zBegin, zEnd); + if (_fuel) { + setZeroBorder(_fuel, _res, zBegin, zEnd); + setZeroBorder(_react, _res, zBegin, zEnd); + } + if (_color_r) { + setZeroBorder(_color_r, _res, zBegin, zEnd); + setZeroBorder(_color_g, _res, zBegin, zEnd); + setZeroBorder(_color_b, _res, zBegin, zEnd); + } } void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd) @@ -668,6 +780,15 @@ void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd) _yVelocity[index] = 0.0f; _zVelocity[index] = 0.0f; _density[index] = 0.0f; + if (_fuel) { + _fuel[index] = 0.0f; + _react[index] = 0.0f; + } + if (_color_r) { + _color_r[index] = 0.0f; + _color_g[index] = 0.0f; + _color_b[index] = 0.0f; + } // right slab index += _xRes - 1; @@ -675,6 +796,15 @@ void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd) _yVelocity[index] = 0.0f; _zVelocity[index] = 0.0f; _density[index] = 0.0f; + if (_fuel) { + _fuel[index] = 0.0f; + _react[index] = 0.0f; + } + if (_color_r) { + _color_r[index] = 0.0f; + _color_g[index] = 0.0f; + _color_b[index] = 0.0f; + } } ///////////////////////////////////// @@ -690,6 +820,15 @@ void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd) _yVelocity[index] = 0.0f; _zVelocity[index] = 0.0f; _density[index] = 0.0f; + if (_fuel) { + _fuel[index] = 0.0f; + _react[index] = 0.0f; + } + if (_color_r) { + _color_r[index] = 0.0f; + _color_g[index] = 0.0f; + _color_b[index] = 0.0f; + } // top slab index += slabSize - _xRes; @@ -697,6 +836,15 @@ void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd) _yVelocity[index] = 0.0f; _zVelocity[index] = 0.0f; _density[index] = 0.0f; + if (_fuel) { + _fuel[index] = 0.0f; + _react[index] = 0.0f; + } + if (_color_r) { + _color_r[index] = 0.0f; + _color_g[index] = 0.0f; + _color_b[index] = 0.0f; + } } @@ -717,6 +865,15 @@ void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd) _yVelocity[index] = 0.0f; _zVelocity[index] = 0.0f; _density[index] = 0.0f; + if (_fuel) { + _fuel[index] = 0.0f; + _react[index] = 0.0f; + } + if (_color_r) { + _color_r[index] = 0.0f; + _color_g[index] = 0.0f; + _color_b[index] = 0.0f; + } } if (zEnd == _zRes) @@ -735,6 +892,15 @@ void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd) _yVelocity[indexx] = 0.0f; _zVelocity[indexx] = 0.0f; _density[indexx] = 0.0f; + if (_fuel) { + _fuel[index] = 0.0f; + _react[index] = 0.0f; + } + if (_color_r) { + _color_r[index] = 0.0f; + _color_g[index] = 0.0f; + _color_b[index] = 0.0f; + } } } @@ -781,35 +947,6 @@ void FLUID_3D::project() if(!_domainBcTop) setNeumannZ(_zVelocity, _res, 0, _zRes); else setZeroZ(_zVelocity, _res, 0, _zRes); - /* - { - float maxx = 0, maxy = 0, maxz = 0; - for(unsigned int i = 0; i < _xRes * _yRes * _zRes; i++) - { - if(_xVelocity[i] > maxx) - maxx = _xVelocity[i]; - if(_yVelocity[i] > maxy) - maxy = _yVelocity[i]; - if(_zVelocity[i] > maxz) - maxz = _zVelocity[i]; - } - printf("Max velx: %f, vely: %f, velz: %f\n", maxx, maxy, maxz); - } - */ - - /* - { - float maxvalue = 0; - for(unsigned int i = 0; i < _xRes * _yRes * _zRes; i++) - { - if(_heat[i] > maxvalue) - maxvalue = _heat[i]; - - } - printf("Max heat: %f\n", maxvalue); - } - */ - // calculate divergence index = _slabSize + _xRes + 1; for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes) @@ -910,21 +1047,52 @@ void FLUID_3D::project() setObstaclePressure(_pressure, 0, _zRes); // project out solution + // New idea for code from NVIDIA graphic gems 3 - DG float invDx = 1.0f / _dx; index = _slabSize + _xRes + 1; for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes) for (y = 1; y < _yRes - 1; y++, index += 2) for (x = 1; x < _xRes - 1; x++, index++) { + float vMask[3] = {1.0f, 1.0f, 1.0f}, vObst[3] = {0, 0, 0}; + float vR = 0.0f, vL = 0.0f, vT = 0.0f, vB = 0.0f, vD = 0.0f, vU = 0.0f; + + float pC = _pressure[index]; // center + float pR = _pressure[index + 1]; // right + float pL = _pressure[index - 1]; // left + float pU = _pressure[index + _xRes]; // Up + float pD = _pressure[index - _xRes]; // Down + float pT = _pressure[index + _slabSize]; // top + float pB = _pressure[index - _slabSize]; // bottom + if(!_obstacles[index]) { - _xVelocity[index] -= 0.5f * (_pressure[index + 1] - _pressure[index - 1]) * invDx; - _yVelocity[index] -= 0.5f * (_pressure[index + _xRes] - _pressure[index - _xRes]) * invDx; - _zVelocity[index] -= 0.5f * (_pressure[index + _slabSize] - _pressure[index - _slabSize]) * invDx; + // DG TODO: What if obstacle is left + right and one of them is moving? + if(_obstacles[index+1]) { pR = pC; vObst[0] = _xVelocityOb[index + 1]; vMask[0] = 0; } + if(_obstacles[index-1]) { pL = pC; vObst[0] = _xVelocityOb[index - 1]; vMask[0] = 0; } + if(_obstacles[index+_xRes]) { pU = pC; vObst[1] = _yVelocityOb[index + _xRes]; vMask[1] = 0; } + if(_obstacles[index-_xRes]) { pD = pC; vObst[1] = _yVelocityOb[index - _xRes]; vMask[1] = 0; } + if(_obstacles[index+_slabSize]) { pT = pC; vObst[2] = _zVelocityOb[index + _slabSize]; vMask[2] = 0; } + if(_obstacles[index-_slabSize]) { pB = pC; vObst[2] = _zVelocityOb[index - _slabSize]; vMask[2] = 0; } + + _xVelocity[index] -= 0.5f * (pR - pL) * invDx; + _yVelocity[index] -= 0.5f * (pU - pD) * invDx; + _zVelocity[index] -= 0.5f * (pT - pB) * invDx; + + _xVelocity[index] = (vMask[0] * _xVelocity[index]) + vObst[0]; + _yVelocity[index] = (vMask[1] * _yVelocity[index]) + vObst[1]; + _zVelocity[index] = (vMask[2] * _zVelocity[index]) + vObst[2]; + } + else + { + _xVelocity[index] = _xVelocityOb[index]; + _yVelocity[index] = _yVelocityOb[index]; + _zVelocity[index] = _zVelocityOb[index]; } } - setObstacleVelocity(0, _zRes); + // DG: was enabled in original code but now we do this later + // setObstacleVelocity(0, _zRes); if (_pressure) delete[] _pressure; if (_divergence) delete[] _divergence; @@ -1007,7 +1175,6 @@ void FLUID_3D::diffuseHeat() for (int x = 0; x < _totalCells; x++) if (_obstacles[x]) _heat[x] = 0.0f; - } ////////////////////////////////////////////////////////////////////// @@ -1175,7 +1342,7 @@ void FLUID_3D::setObstacleBoundaries(float *_pressure, int zBegin, int zEnd) ////////////////////////////////////////////////////////////////////// // add buoyancy forces ////////////////////////////////////////////////////////////////////// -void FLUID_3D::addBuoyancy(float *heat, float *density, int zBegin, int zEnd) +void FLUID_3D::addBuoyancy(float *heat, float *density, float gravity[3], int zBegin, int zEnd) { int index = zBegin*_slabSize; @@ -1183,17 +1350,26 @@ void FLUID_3D::addBuoyancy(float *heat, float *density, int zBegin, int zEnd) for (int y = 0; y < _yRes; y++) for (int x = 0; x < _xRes; x++, index++) { - _zForce[index] += *_alpha * density[index] + (*_beta * (heat[index] - _tempAmb)); // DG: was _yForce, changed for Blender + float buoyancy = *_alpha * density[index] + (*_beta * (((heat) ? heat[index] : 0.0f) - _tempAmb)); + _xForce[index] -= gravity[0] * buoyancy; + _yForce[index] -= gravity[1] * buoyancy; + _zForce[index] -= gravity[2] * buoyancy; } } + ////////////////////////////////////////////////////////////////////// // add vorticity to the force field ////////////////////////////////////////////////////////////////////// +#define VORT_VEL(i, j) \ + ((_obstacles[obpos[(i)]] & 8) ? ((abs(objvelocity[(j)][obpos[(i)]]) > FLT_EPSILON) ? objvelocity[(j)][obpos[(i)]] : velocity[(j)][index]) : velocity[(j)][obpos[(i)]]) + void FLUID_3D::addVorticity(int zBegin, int zEnd) { + // set flame vorticity from RNA value + float flame_vorticity = (*_flame_vorticity)/_constantScaling; //int x,y,z,index; - if(_vorticityEps<=0.) return; + if(_vorticityEps+flame_vorticity<=0.) return; int _blockSize=zEnd-zBegin; int _blockTotalCells = _slabSize * (_blockSize+2); @@ -1225,9 +1401,18 @@ void FLUID_3D::addVorticity(int zBegin, int zEnd) float gridSize = 0.5f / _dx; //index = _slabSize + _xRes + 1; + float *velocity[3]; + float *objvelocity[3]; - size_t vIndex=_xRes + 1; + velocity[0] = _xVelocity; + velocity[1] = _yVelocity; + velocity[2] = _zVelocity; + + objvelocity[0] = _xVelocityOb; + objvelocity[1] = _yVelocityOb; + objvelocity[2] = _zVelocityOb; + size_t vIndex=_xRes + 1; for (int z = zBegin + bb1; z < (zEnd - bt1); z++) { size_t index = index_ +(z-1)*_slabSize; @@ -1237,25 +1422,47 @@ void FLUID_3D::addVorticity(int zBegin, int zEnd) { for (int x = 1; x < _xRes - 1; x++, index++) { + if (!_obstacles[index]) + { + int obpos[6]; + + obpos[0] = (_obstacles[index + _xRes] == 1) ? index : index + _xRes; // up + obpos[1] = (_obstacles[index - _xRes] == 1) ? index : index - _xRes; // down + float dy = (obpos[0] == index || obpos[1] == index) ? 1.0f / _dx : gridSize; + + obpos[2] = (_obstacles[index + _slabSize] == 1) ? index : index + _slabSize; // out + obpos[3] = (_obstacles[index - _slabSize] == 1) ? index : index - _slabSize; // in + float dz = (obpos[2] == index || obpos[3] == index) ? 1.0f / _dx : gridSize; + + obpos[4] = (_obstacles[index + 1] == 1) ? index : index + 1; // right + obpos[5] = (_obstacles[index - 1] == 1) ? index : index - 1; // left + float dx = (obpos[4] == index || obpos[5] == index) ? 1.0f / _dx : gridSize; + + float xV[2], yV[2], zV[2]; + + zV[1] = VORT_VEL(0, 2); + zV[0] = VORT_VEL(1, 2); + yV[1] = VORT_VEL(2, 1); + yV[0] = VORT_VEL(3, 1); + _xVorticity[vIndex] = (zV[1] - zV[0]) * dy + (-yV[1] + yV[0]) * dz; + + xV[1] = VORT_VEL(2, 0); + xV[0] = VORT_VEL(3, 0); + zV[1] = VORT_VEL(4, 2); + zV[0] = VORT_VEL(5, 2); + _yVorticity[vIndex] = (xV[1] - xV[0]) * dz + (-zV[1] + zV[0]) * dx; + + yV[1] = VORT_VEL(4, 1); + yV[0] = VORT_VEL(5, 1); + xV[1] = VORT_VEL(0, 0); + xV[0] = VORT_VEL(1, 0); + _zVorticity[vIndex] = (yV[1] - yV[0]) * dx + (-xV[1] + xV[0])* dy; - int up = _obstacles[index + _xRes] ? index : index + _xRes; - int down = _obstacles[index - _xRes] ? index : index - _xRes; - float dy = (up == index || down == index) ? 1.0f / _dx : gridSize; - int out = _obstacles[index + _slabSize] ? index : index + _slabSize; - int in = _obstacles[index - _slabSize] ? index : index - _slabSize; - float dz = (out == index || in == index) ? 1.0f / _dx : gridSize; - int right = _obstacles[index + 1] ? index : index + 1; - int left = _obstacles[index - 1] ? index : index - 1; - float dx = (right == index || left == index) ? 1.0f / _dx : gridSize; - - _xVorticity[vIndex] = (_zVelocity[up] - _zVelocity[down]) * dy + (-_yVelocity[out] + _yVelocity[in]) * dz; - _yVorticity[vIndex] = (_xVelocity[out] - _xVelocity[in]) * dz + (-_zVelocity[right] + _zVelocity[left]) * dx; - _zVorticity[vIndex] = (_yVelocity[right] - _yVelocity[left]) * dx + (-_xVelocity[up] + _xVelocity[down])* dy; - - _vorticity[vIndex] = sqrtf(_xVorticity[vIndex] * _xVorticity[vIndex] + + _vorticity[vIndex] = sqrtf(_xVorticity[vIndex] * _xVorticity[vIndex] + _yVorticity[vIndex] * _yVorticity[vIndex] + _zVorticity[vIndex] * _zVorticity[vIndex]); + } vIndex++; } vIndex+=2; @@ -1284,15 +1491,18 @@ void FLUID_3D::addVorticity(int zBegin, int zEnd) { float N[3]; - int up = _obstacles[index + _xRes] ? vIndex : vIndex + _xRes; - int down = _obstacles[index - _xRes] ? vIndex : vIndex - _xRes; + int up = (_obstacles[index + _xRes] == 1) ? vIndex : vIndex + _xRes; + int down = (_obstacles[index - _xRes] == 1) ? vIndex : vIndex - _xRes; float dy = (up == vIndex || down == vIndex) ? 1.0f / _dx : gridSize; - int out = _obstacles[index + _slabSize] ? vIndex : vIndex + _slabSize; - int in = _obstacles[index - _slabSize] ? vIndex : vIndex - _slabSize; + + int out = (_obstacles[index + _slabSize] == 1) ? vIndex : vIndex + _slabSize; + int in = (_obstacles[index - _slabSize] == 1) ? vIndex : vIndex - _slabSize; float dz = (out == vIndex || in == vIndex) ? 1.0f / _dx : gridSize; - int right = _obstacles[index + 1] ? vIndex : vIndex + 1; - int left = _obstacles[index - 1] ? vIndex : vIndex - 1; + + int right = (_obstacles[index + 1] == 1) ? vIndex : vIndex + 1; + int left = (_obstacles[index - 1] == 1) ? vIndex : vIndex - 1; float dx = (right == vIndex || left == vIndex) ? 1.0f / _dx : gridSize; + N[0] = (_vorticity[right] - _vorticity[left]) * dx; N[1] = (_vorticity[up] - _vorticity[down]) * dy; N[2] = (_vorticity[out] - _vorticity[in]) * dz; @@ -1300,14 +1510,15 @@ void FLUID_3D::addVorticity(int zBegin, int zEnd) float magnitude = sqrtf(N[0] * N[0] + N[1] * N[1] + N[2] * N[2]); if (magnitude > FLT_EPSILON) { + float flame_vort = (_fuel) ? _fuel[index]*flame_vorticity : 0.0f; magnitude = 1.0f / magnitude; N[0] *= magnitude; N[1] *= magnitude; N[2] *= magnitude; - _xForce[index] += (N[1] * _zVorticity[vIndex] - N[2] * _yVorticity[vIndex]) * _dx * eps; - _yForce[index] += (N[2] * _xVorticity[vIndex] - N[0] * _zVorticity[vIndex]) * _dx * eps; - _zForce[index] += (N[0] * _yVorticity[vIndex] - N[1] * _xVorticity[vIndex]) * _dx * eps; + _xForce[index] += (N[1] * _zVorticity[vIndex] - N[2] * _yVorticity[vIndex]) * _dx * (eps + flame_vort); + _yForce[index] += (N[2] * _xVorticity[vIndex] - N[0] * _zVorticity[vIndex]) * _dx * (eps + flame_vort); + _zForce[index] += (N[0] * _yVorticity[vIndex] - N[1] * _xVorticity[vIndex]) * _dx * (eps + flame_vort); } } // if vIndex++; @@ -1328,14 +1539,9 @@ void FLUID_3D::advectMacCormackBegin(int zBegin, int zEnd) { Vec3Int res = Vec3Int(_xRes,_yRes,_zRes); - if(!_domainBcLeft) copyBorderX(_xVelocityOld, res, zBegin, zEnd); - else setZeroX(_xVelocityOld, res, zBegin, zEnd); - - if(!_domainBcFront) copyBorderY(_yVelocityOld, res, zBegin, zEnd); - else setZeroY(_yVelocityOld, res, zBegin, zEnd); - - if(!_domainBcTop) copyBorderZ(_zVelocityOld, res, zBegin, zEnd); - else setZeroZ(_zVelocityOld, res, zBegin, zEnd); + setZeroX(_xVelocityOld, res, zBegin, zEnd); + setZeroY(_yVelocityOld, res, zBegin, zEnd); + setZeroZ(_zVelocityOld, res, zBegin, zEnd); } ////////////////////////////////////////////////////////////////////// @@ -1355,7 +1561,18 @@ void FLUID_3D::advectMacCormackEnd1(int zBegin, int zEnd) // advectFieldMacCormack1(dt, xVelocity, yVelocity, zVelocity, oldField, newField, res) advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _densityOld, _densityTemp, res, zBegin, zEnd); - advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heatTemp, res, zBegin, zEnd); + if (_heat) { + advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heatTemp, res, zBegin, zEnd); + } + if (_fuel) { + advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _fuelOld, _fuelTemp, res, zBegin, zEnd); + advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _reactOld, _reactTemp, res, zBegin, zEnd); + } + if (_color_r) { + advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_rOld, _color_rTemp, res, zBegin, zEnd); + advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_gOld, _color_gTemp, res, zBegin, zEnd); + advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_bOld, _color_bTemp, res, zBegin, zEnd); + } advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _xVelocityOld, _xVelocity, res, zBegin, zEnd); advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _yVelocityOld, _yVelocity, res, zBegin, zEnd); advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _zVelocityOld, _zVelocity, res, zBegin, zEnd); @@ -1371,17 +1588,30 @@ void FLUID_3D::advectMacCormackEnd2(int zBegin, int zEnd) const float dt0 = _dt / _dx; Vec3Int res = Vec3Int(_xRes,_yRes,_zRes); - // use force array as temp arrays + // use force array as temp array float* t1 = _xForce; // advectFieldMacCormack2(dt, xVelocity, yVelocity, zVelocity, oldField, newField, tempfield, temp, res, obstacles) + /* finish advection */ advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _densityOld, _density, _densityTemp, t1, res, _obstacles, zBegin, zEnd); - advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heat, _heatTemp, t1, res, _obstacles, zBegin, zEnd); + if (_heat) { + advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heat, _heatTemp, t1, res, _obstacles, zBegin, zEnd); + } + if (_fuel) { + advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _fuelOld, _fuel, _fuelTemp, t1, res, _obstacles, zBegin, zEnd); + advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _reactOld, _react, _reactTemp, t1, res, _obstacles, zBegin, zEnd); + } + if (_color_r) { + advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_rOld, _color_r, _color_rTemp, t1, res, _obstacles, zBegin, zEnd); + advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_gOld, _color_g, _color_gTemp, t1, res, _obstacles, zBegin, zEnd); + advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_bOld, _color_b, _color_bTemp, t1, res, _obstacles, zBegin, zEnd); + } advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _xVelocityOld, _xVelocityTemp, _xVelocity, t1, res, _obstacles, zBegin, zEnd); advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _yVelocityOld, _yVelocityTemp, _yVelocity, t1, res, _obstacles, zBegin, zEnd); advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _zVelocityOld, _zVelocityTemp, _zVelocity, t1, res, _obstacles, zBegin, zEnd); + /* set boundary conditions for velocity */ if(!_domainBcLeft) copyBorderX(_xVelocityTemp, res, zBegin, zEnd); else setZeroX(_xVelocityTemp, res, zBegin, zEnd); @@ -1391,40 +1621,71 @@ void FLUID_3D::advectMacCormackEnd2(int zBegin, int zEnd) if(!_domainBcTop) copyBorderZ(_zVelocityTemp, res, zBegin, zEnd); else setZeroZ(_zVelocityTemp, res, zBegin, zEnd); + /* clear data boundaries */ setZeroBorder(_density, res, zBegin, zEnd); - setZeroBorder(_heat, res, zBegin, zEnd); -#if 0 - { - const size_t index_ = _slabSize + _xRes + 1; - int bb=0; - int bt=0; + if (_fuel) { + setZeroBorder(_fuel, res, zBegin, zEnd); + setZeroBorder(_react, res, zBegin, zEnd); + } + if (_color_r) { + setZeroBorder(_color_r, res, zBegin, zEnd); + setZeroBorder(_color_g, res, zBegin, zEnd); + setZeroBorder(_color_b, res, zBegin, zEnd); + } +} - if (zBegin == 0) {bb = 1;} - if (zEnd == _zRes) {bt = 1;} - - for (int z = zBegin + bb; z < zEnd - bt; z++) + +void FLUID_3D::processBurn(float *fuel, float *smoke, float *react, float *flame, float *heat, + float *r, float *g, float *b, int total_cells, float dt) +{ + float burning_rate = *_burning_rate; + float flame_smoke = *_flame_smoke; + float ignition_point = *_ignition_temp; + float temp_max = *_max_temp; + + for (int index = 0; index < total_cells; index++) { - size_t index = index_ +(z-1)*_slabSize; + float orig_fuel = fuel[index]; + float orig_smoke = smoke[index]; + float smoke_emit = 0.0f; + float react_coord = 0.0f; + + /* process fuel */ + fuel[index] -= burning_rate * dt; + if (fuel[index] < 0.0f) fuel[index] = 0.0f; + /* process reaction coordinate */ + if (orig_fuel) { + react[index] *= fuel[index]/orig_fuel; + react_coord = react[index]; + } + else { + react[index] = 0.0f; + } - for (int y = 1; y < _yRes - 1; y++, index += 2) - { - for (int x = 1; x < _xRes - 1; x++, index++) - { - // clean custom velocities from moving obstacles again - if (_obstacles[index]) - { - _xVelocity[index] = - _yVelocity[index] = - _zVelocity[index] = 0.0f; - } - } + /* emit smoke based on fuel burn rate and "flame_smoke" factor */ + smoke_emit = (orig_fuel < 1.0f) ? (1.0f - orig_fuel)*0.5f : 0.0f; + smoke_emit = (smoke_emit + 0.5f) * (orig_fuel-fuel[index]) * 0.1f * flame_smoke; + smoke[index] += smoke_emit; + CLAMP(smoke[index], 0.0f, 1.0f); + + /* model flame temperature curve from the reaction coordinate (fuel) */ + if (react_coord>0.0f) { + /* do a smooth falloff for rest of the values */ + flame[index] = pow(react_coord, 0.5f); + } + else + flame[index] = 0.0f; + + /* set fluid temperature from the flame temperature profile */ + if (heat && flame[index]) + heat[index] = (1.0f-flame[index])*ignition_point + flame[index]*temp_max; + + /* mix new color */ + if (r && smoke_emit) { + float smoke_factor = smoke[index]/(orig_smoke+smoke_emit); + r[index] = (r[index] + _flame_smoke_color[0] * smoke_emit) * smoke_factor; + g[index] = (g[index] + _flame_smoke_color[1] * smoke_emit) * smoke_factor; + b[index] = (b[index] + _flame_smoke_color[2] * smoke_emit) * smoke_factor; } } - } -#endif - - /*int begin=zBegin * _slabSize; - int end=begin + (zEnd - zBegin) * _slabSize; - for (int x = begin; x < end; x++) - _xForce[x] = _yForce[x] = 0.0f;*/ } diff --git a/intern/smoke/intern/FLUID_3D.h b/intern/smoke/intern/FLUID_3D.h index ac77148ce84..8cadf3bc989 100644 --- a/intern/smoke/intern/FLUID_3D.h +++ b/intern/smoke/intern/FLUID_3D.h @@ -46,11 +46,16 @@ class WTURBULENCE; class FLUID_3D { public: - FLUID_3D(int *res, /* int amplify, */ float *p0, float dtdef); + FLUID_3D(int *res, float dx, float dtdef, int init_heat, int init_fire, int init_colors); FLUID_3D() {}; virtual ~FLUID_3D(); - void initBlenderRNA(float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli); + void initHeat(); + void initFire(); + void initColors(float init_r, float init_g, float init_b); + + void initBlenderRNA(float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli, float *burning_rate, + float *flame_smoke, float *flame_smoke_color, float *flame_vorticity, float *ignition_temp, float *max_temp); // create & allocate vector noise advection void initVectorNoise(int amplify); @@ -58,7 +63,7 @@ class FLUID_3D void addSmokeColumn(); static void addSmokeTestCase(float* field, Vec3Int res); - void step(float dt); + void step(float dt, float gravity[3]); void addObstacle(OBSTACLE* obstacle); const float* xVelocity() { return _xVelocity; }; @@ -115,6 +120,27 @@ class FLUID_3D float* _heatTemp; float* _densityTemp; + // fire simulation + float *_flame; + float *_fuel; + float *_fuelTemp; + float *_fuelOld; + float *_react; + float *_reactTemp; + float *_reactOld; + + // smoke color + float *_color_r; + float *_color_rOld; + float *_color_rTemp; + float *_color_g; + float *_color_gOld; + float *_color_gTemp; + float *_color_b; + float *_color_bOld; + float *_color_bTemp; + + // CG fields int _iterations; @@ -153,14 +179,16 @@ class FLUID_3D void wipeBoundariesSL(int zBegin, int zEnd); void addForce(int zBegin, int zEnd); void addVorticity(int zBegin, int zEnd); - void addBuoyancy(float *heat, float *density, int zBegin, int zEnd); + void addBuoyancy(float *heat, float *density, float gravity[3], int zBegin, int zEnd); // solver stuff void project(); void diffuseHeat(); + void diffuseColor(); void solvePressure(float* field, float* b, unsigned char* skip); void solvePressurePre(float* field, float* b, unsigned char* skip); void solveHeat(float* field, float* b, unsigned char* skip); + void solveDiffusion(float* field, float* b, float* factor); // handle obstacle boundaries @@ -174,6 +202,16 @@ class FLUID_3D void advectMacCormackEnd1(int zBegin, int zEnd); void advectMacCormackEnd2(int zBegin, int zEnd); + /* burning */ + float *_burning_rate; // RNA pointer + float *_flame_smoke; // RNA pointer + float *_flame_smoke_color; // RNA pointer + float *_flame_vorticity; // RNA pointer + float *_ignition_temp; // RNA pointer + float *_max_temp; // RNA pointer + void processBurn(float *fuel, float *smoke, float *react, float *flame, float *heat, + float *r, float *g, float *b, int total_cells, float dt); + // boundary setting functions static void copyBorderX(float* field, Vec3Int res, int zBegin, int zEnd); static void copyBorderY(float* field, Vec3Int res, int zBegin, int zEnd); diff --git a/intern/smoke/intern/FLUID_3D_SOLVERS.cpp b/intern/smoke/intern/FLUID_3D_SOLVERS.cpp index 3cf94eb00a9..42a8b2d6923 100644 --- a/intern/smoke/intern/FLUID_3D_SOLVERS.cpp +++ b/intern/smoke/intern/FLUID_3D_SOLVERS.cpp @@ -165,7 +165,6 @@ void FLUID_3D::solveHeat(float* field, float* b, unsigned char* skip) if (_Acenter) delete[] _Acenter; } - void FLUID_3D::solvePressurePre(float* field, float* b, unsigned char* skip) { int x, y, z; diff --git a/intern/smoke/intern/FLUID_3D_STATIC.cpp b/intern/smoke/intern/FLUID_3D_STATIC.cpp index c7a0ddcd04c..ac485ad983a 100644 --- a/intern/smoke/intern/FLUID_3D_STATIC.cpp +++ b/intern/smoke/intern/FLUID_3D_STATIC.cpp @@ -92,18 +92,10 @@ void FLUID_3D::setNeumannX(float* field, Vec3Int res, int zBegin, int zEnd) // left slab index = y * res[0] + z * slabSize; field[index] = field[index + 2]; - /* only allow outwards flux */ - if(field[index]>0.) field[index] = 0.; - index += 1; - if(field[index]>0.) field[index] = 0.; // right slab index = y * res[0] + z * slabSize + res[0] - 1; field[index] = field[index - 2]; - /* only allow outwards flux */ - if(field[index]<0.) field[index] = 0.; - index -= 1; - if(field[index]<0.) field[index] = 0.; } } @@ -120,18 +112,10 @@ void FLUID_3D::setNeumannY(float* field, Vec3Int res, int zBegin, int zEnd) // front slab index = x + z * slabSize; field[index] = field[index + 2 * res[0]]; - /* only allow outwards flux */ - if(field[index]>0.) field[index] = 0.; - index += res[0]; - if(field[index]>0.) field[index] = 0.; // back slab index = x + z * slabSize + slabSize - res[0]; field[index] = field[index - 2 * res[0]]; - /* only allow outwards flux */ - if(field[index]<0.) field[index] = 0.; - index -= res[0]; - if(field[index]<0.) field[index] = 0.; } } @@ -152,14 +136,6 @@ void FLUID_3D::setNeumannZ(float* field, Vec3Int res, int zBegin, int zEnd) // front slab index = x + y * res[0]; field[index] = field[index + 2 * slabSize]; - /* only allow outwards flux */ - - // DG: Disable this for z-axis. - // The problem is that smoke somehow gets sucked in again - // from the TOP slab when this is enabled - // if(field[index]>0.) field[index] = 0.; - // index += slabSize; - // if(field[index]>0.) field[index] = 0.; } } @@ -170,10 +146,6 @@ void FLUID_3D::setNeumannZ(float* field, Vec3Int res, int zBegin, int zEnd) // back slab index = x + y * res[0] + cellsslab; field[index] = field[index - 2 * slabSize]; - /* only allow outwards flux */ - if(field[index]<0.) field[index] = 0.; - index -= slabSize; - if(field[index]<0.) field[index] = 0.; } } diff --git a/intern/smoke/intern/WTURBULENCE.cpp b/intern/smoke/intern/WTURBULENCE.cpp index 671198065e8..1c89f5d681b 100644 --- a/intern/smoke/intern/WTURBULENCE.cpp +++ b/intern/smoke/intern/WTURBULENCE.cpp @@ -51,7 +51,7 @@ static const float persistence = 0.56123f; ////////////////////////////////////////////////////////////////////// // constructor ////////////////////////////////////////////////////////////////////// -WTURBULENCE::WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int noisetype) +WTURBULENCE::WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int noisetype, int init_fire, int init_colors) { // if noise magnitude is below this threshold, its contribution // is negilgible, so stop evaluating new octaves @@ -87,12 +87,26 @@ WTURBULENCE::WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int no // allocate high resolution density field _totalStepsBig = 0; _densityBig = new float[_totalCellsBig]; - _densityBigOld = new float[_totalCellsBig]; + _densityBigOld = new float[_totalCellsBig]; for(int i = 0; i < _totalCellsBig; i++) { _densityBig[i] = _densityBigOld[i] = 0.; } + + /* fire */ + _flameBig = _fuelBig = _fuelBigOld = NULL; + _reactBig = _reactBigOld = NULL; + if (init_fire) { + initFire(); + } + /* colors */ + _color_rBig = _color_rBigOld = NULL; + _color_gBig = _color_gBigOld = NULL; + _color_bBig = _color_bBigOld = NULL; + if (init_colors) { + initColors(0.0f, 0.0f, 0.0f); + } // allocate & init texture coordinates _tcU = new float[_totalCellsSm]; @@ -128,12 +142,64 @@ WTURBULENCE::WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int no */ } +void WTURBULENCE::initFire() +{ + if (!_fuelBig) { + _flameBig = new float[_totalCellsBig]; + _fuelBig = new float[_totalCellsBig]; + _fuelBigOld = new float[_totalCellsBig]; + _reactBig = new float[_totalCellsBig]; + _reactBigOld = new float[_totalCellsBig]; + + for(int i = 0; i < _totalCellsBig; i++) { + _flameBig[i] = + _fuelBig[i] = + _fuelBigOld[i] = 0.; + _reactBig[i] = + _reactBigOld[i] = 0.; + } + } +} + +void WTURBULENCE::initColors(float init_r, float init_g, float init_b) +{ + if (!_color_rBig) { + _color_rBig = new float[_totalCellsBig]; + _color_rBigOld = new float[_totalCellsBig]; + _color_gBig = new float[_totalCellsBig]; + _color_gBigOld = new float[_totalCellsBig]; + _color_bBig = new float[_totalCellsBig]; + _color_bBigOld = new float[_totalCellsBig]; + + for(int i = 0; i < _totalCellsBig; i++) { + _color_rBig[i] = _densityBig[i] * init_r; + _color_rBigOld[i] = 0.0f; + _color_gBig[i] = _densityBig[i] * init_g; + _color_gBigOld[i] = 0.0f; + _color_bBig[i] = _densityBig[i] * init_b; + _color_bBigOld[i] = 0.0f; + } + } +} + ////////////////////////////////////////////////////////////////////// // destructor ////////////////////////////////////////////////////////////////////// WTURBULENCE::~WTURBULENCE() { delete[] _densityBig; delete[] _densityBigOld; + if (_flameBig) delete[] _flameBig; + if (_fuelBig) delete[] _fuelBig; + if (_fuelBigOld) delete[] _fuelBigOld; + if (_reactBig) delete[] _reactBig; + if (_reactBigOld) delete[] _reactBigOld; + + if (_color_rBig) delete[] _color_rBig; + if (_color_rBigOld) delete[] _color_rBigOld; + if (_color_gBig) delete[] _color_gBig; + if (_color_gBigOld) delete[] _color_gBigOld; + if (_color_bBig) delete[] _color_bBig; + if (_color_bBigOld) delete[] _color_bBigOld; delete[] _tcU; delete[] _tcV; @@ -757,8 +823,10 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa // enlarge timestep to match grid const float dt = dtOrg * _amplify; const float invAmp = 1.0f / _amplify; - float *tempBig1 = (float *)calloc(_totalCellsBig, sizeof(float)); - float *tempBig2 = (float *)calloc(_totalCellsBig, sizeof(float)); + float *tempFuelBig = NULL, *tempReactBig = NULL; + float *tempColor_rBig = NULL, *tempColor_gBig = NULL, *tempColor_bBig = NULL; + float *tempDensityBig = (float *)calloc(_totalCellsBig, sizeof(float)); + float *tempBig = (float *)calloc(_totalCellsBig, sizeof(float)); float *bigUx = (float *)calloc(_totalCellsBig, sizeof(float)); float *bigUy = (float *)calloc(_totalCellsBig, sizeof(float)); float *bigUz = (float *)calloc(_totalCellsBig, sizeof(float)); @@ -767,11 +835,21 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa float *eigMin = (float *)calloc(_totalCellsSm, sizeof(float)); float *eigMax = (float *)calloc(_totalCellsSm, sizeof(float)); + if (_fuelBig) { + tempFuelBig = (float *)calloc(_totalCellsBig, sizeof(float)); + tempReactBig = (float *)calloc(_totalCellsBig, sizeof(float)); + } + if (_color_rBig) { + tempColor_rBig = (float *)calloc(_totalCellsBig, sizeof(float)); + tempColor_gBig = (float *)calloc(_totalCellsBig, sizeof(float)); + tempColor_bBig = (float *)calloc(_totalCellsBig, sizeof(float)); + } + memset(_tcTemp, 0, sizeof(float)*_totalCellsSm); // prepare textures - advectTextureCoordinates(dtOrg, xvel,yvel,zvel, tempBig1, tempBig2); + advectTextureCoordinates(dtOrg, xvel,yvel,zvel, tempDensityBig, tempBig); // do wavelet decomposition of energy computeEnergy(_energy, xvel, yvel, zvel, obstacles); @@ -972,6 +1050,11 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa // prepare density for an advection SWAP_POINTERS(_densityBig, _densityBigOld); + SWAP_POINTERS(_fuelBig, _fuelBigOld); + SWAP_POINTERS(_reactBig, _reactBigOld); + SWAP_POINTERS(_color_rBig, _color_rBigOld); + SWAP_POINTERS(_color_gBig, _color_gBigOld); + SWAP_POINTERS(_color_bBig, _color_bBigOld); // based on the maximum velocity present, see if we need to substep, // but cap the maximum number of substeps to 5 @@ -1017,7 +1100,21 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa int zEnd = (int)((float)(i+1)*partSize + 0.5f); #endif FLUID_3D::advectFieldMacCormack1(dtSubdiv, bigUx, bigUy, bigUz, - _densityBigOld, tempBig1, _resBig, zBegin, zEnd); + _densityBigOld, tempDensityBig, _resBig, zBegin, zEnd); + if (_fuelBig) { + FLUID_3D::advectFieldMacCormack1(dtSubdiv, bigUx, bigUy, bigUz, + _fuelBigOld, tempFuelBig, _resBig, zBegin, zEnd); + FLUID_3D::advectFieldMacCormack1(dtSubdiv, bigUx, bigUy, bigUz, + _reactBigOld, tempReactBig, _resBig, zBegin, zEnd); + } + if (_color_rBig) { + FLUID_3D::advectFieldMacCormack1(dtSubdiv, bigUx, bigUy, bigUz, + _color_rBigOld, tempColor_rBig, _resBig, zBegin, zEnd); + FLUID_3D::advectFieldMacCormack1(dtSubdiv, bigUx, bigUy, bigUz, + _color_gBigOld, tempColor_gBig, _resBig, zBegin, zEnd); + FLUID_3D::advectFieldMacCormack1(dtSubdiv, bigUx, bigUy, bigUz, + _color_bBigOld, tempColor_bBig, _resBig, zBegin, zEnd); + } #if PARALLEL==1 } @@ -1030,18 +1127,43 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa int zEnd = (int)((float)(i+1)*partSize + 0.5f); #endif FLUID_3D::advectFieldMacCormack2(dtSubdiv, bigUx, bigUy, bigUz, - _densityBigOld, _densityBig, tempBig1, tempBig2, _resBig, NULL, zBegin, zEnd); + _densityBigOld, _densityBig, tempDensityBig, tempBig, _resBig, NULL, zBegin, zEnd); + if (_fuelBig) { + FLUID_3D::advectFieldMacCormack2(dtSubdiv, bigUx, bigUy, bigUz, + _fuelBigOld, _fuelBig, tempFuelBig, tempBig, _resBig, NULL, zBegin, zEnd); + FLUID_3D::advectFieldMacCormack2(dtSubdiv, bigUx, bigUy, bigUz, + _reactBigOld, _reactBig, tempReactBig, tempBig, _resBig, NULL, zBegin, zEnd); + } + if (_color_rBig) { + FLUID_3D::advectFieldMacCormack2(dtSubdiv, bigUx, bigUy, bigUz, + _color_rBigOld, _color_rBig, tempColor_rBig, tempBig, _resBig, NULL, zBegin, zEnd); + FLUID_3D::advectFieldMacCormack2(dtSubdiv, bigUx, bigUy, bigUz, + _color_gBigOld, _color_gBig, tempColor_gBig, tempBig, _resBig, NULL, zBegin, zEnd); + FLUID_3D::advectFieldMacCormack2(dtSubdiv, bigUx, bigUy, bigUz, + _color_bBigOld, _color_bBig, tempColor_bBig, tempBig, _resBig, NULL, zBegin, zEnd); + } #if PARALLEL==1 } } #endif - if (substep < totalSubsteps - 1) + if (substep < totalSubsteps - 1) { SWAP_POINTERS(_densityBig, _densityBigOld); + SWAP_POINTERS(_fuelBig, _fuelBigOld); + SWAP_POINTERS(_reactBig, _reactBigOld); + SWAP_POINTERS(_color_rBig, _color_rBigOld); + SWAP_POINTERS(_color_gBig, _color_gBigOld); + SWAP_POINTERS(_color_bBig, _color_bBigOld); + } } // substep - free(tempBig1); - free(tempBig2); + free(tempDensityBig); + if (tempFuelBig) free(tempFuelBig); + if (tempReactBig) free(tempReactBig); + if (tempColor_rBig) free(tempColor_rBig); + if (tempColor_gBig) free(tempColor_gBig); + if (tempColor_bBig) free(tempColor_bBig); + free(tempBig); free(bigUx); free(bigUy); free(bigUz); @@ -1050,6 +1172,15 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa // wipe the density borders FLUID_3D::setZeroBorder(_densityBig, _resBig, 0 , _resBig[2]); + if (_fuelBig) { + FLUID_3D::setZeroBorder(_fuelBig, _resBig, 0 , _resBig[2]); + FLUID_3D::setZeroBorder(_reactBig, _resBig, 0 , _resBig[2]); + } + if (_color_rBig) { + FLUID_3D::setZeroBorder(_color_rBig, _resBig, 0 , _resBig[2]); + FLUID_3D::setZeroBorder(_color_gBig, _resBig, 0 , _resBig[2]); + FLUID_3D::setZeroBorder(_color_bBig, _resBig, 0 , _resBig[2]); + } // reset texture coordinates now in preparation for next timestep // Shouldn't do this before generating the noise because then the diff --git a/intern/smoke/intern/WTURBULENCE.h b/intern/smoke/intern/WTURBULENCE.h index f31ca100fdf..1655bd95d32 100644 --- a/intern/smoke/intern/WTURBULENCE.h +++ b/intern/smoke/intern/WTURBULENCE.h @@ -36,10 +36,13 @@ class WTURBULENCE { public: // both config files can be NULL, altCfg might override values from noiseCfg - WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int noisetype); + WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int noisetype, int init_fire, int init_colors); /// destructor virtual ~WTURBULENCE(); + + void initFire(); + void initColors(float init_r, float init_g, float init_b); void setNoise(int type); void initBlenderRNA(float *strength); @@ -63,6 +66,8 @@ class WTURBULENCE // access functions inline float* getDensityBig() { return _densityBig; } + inline float* getFlameBig() { return _flameBig; } + inline float* getFuelBig() { return _fuelBig; } inline float* getArrayTcU() { return _tcU; } inline float* getArrayTcV() { return _tcV; } inline float* getArrayTcW() { return _tcW; } @@ -111,6 +116,18 @@ class WTURBULENCE float* _densityBig; float* _densityBigOld; + float* _flameBig; + float* _fuelBig; + float* _fuelBigOld; + float* _reactBig; + float* _reactBigOld; + + float* _color_rBig; + float* _color_rBigOld; + float* _color_gBig; + float* _color_gBigOld; + float* _color_bBig; + float* _color_bBigOld; // texture coordinates for noise float* _tcU; diff --git a/intern/smoke/intern/smoke_API.cpp b/intern/smoke/intern/smoke_API.cpp index 4bbf8e0a82b..6011de0bddb 100644 --- a/intern/smoke/intern/smoke_API.cpp +++ b/intern/smoke/intern/smoke_API.cpp @@ -30,6 +30,7 @@ #include "FLUID_3D.h" #include "WTURBULENCE.h" +#include "spectrum.h" #include <stdio.h> #include <stdlib.h> @@ -37,22 +38,16 @@ #include "../extern/smoke_API.h" /* to ensure valid prototypes */ -// y in smoke is z in blender -extern "C" FLUID_3D *smoke_init(int *res, float *p0, float dtdef) +extern "C" FLUID_3D *smoke_init(int *res, float dx, float dtdef, int use_heat, int use_fire, int use_colors) { - // smoke lib uses y as top-bottom/vertical axis where blender uses z - FLUID_3D *fluid = new FLUID_3D(res, p0, dtdef); - - // printf("xres: %d, yres: %d, zres: %d\n", res[0], res[1], res[2]); - + FLUID_3D *fluid = new FLUID_3D(res, dx, dtdef, use_heat, use_fire, use_colors); return fluid; } -extern "C" WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype) +extern "C" WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype, int use_fire, int use_colors) { - // initialize wavelet turbulence - if(amplify) - return new WTURBULENCE(res[0],res[1],res[2], amplify, noisetype); + if (amplify) + return new WTURBULENCE(res[0],res[1],res[2], amplify, noisetype, use_fire, use_colors); else return NULL; } @@ -71,7 +66,6 @@ extern "C" void smoke_turbulence_free(WTURBULENCE *wt) extern "C" size_t smoke_get_index(int x, int max_x, int y, int max_y, int z /*, int max_z */) { - // // const int index = x + y * smd->res[0] + z * smd->res[0]*smd->res[1]; return x + y * max_x + z * max_x*max_y; } @@ -80,137 +74,133 @@ extern "C" size_t smoke_get_index2d(int x, int max_x, int y /*, int max_y, int z return x + y * max_x; } -extern "C" void smoke_step(FLUID_3D *fluid, float dtSubdiv) +extern "C" void smoke_step(FLUID_3D *fluid, float gravity[3], float dtSubdiv) { - fluid->step(dtSubdiv); + if (fluid->_fuel) { + fluid->processBurn(fluid->_fuel, fluid->_density, fluid->_react, fluid->_flame, fluid->_heat, + fluid->_color_r, fluid->_color_g, fluid->_color_b, fluid->_totalCells, (*fluid->_dtFactor)*dtSubdiv); + } + fluid->step(dtSubdiv, gravity); } extern "C" void smoke_turbulence_step(WTURBULENCE *wt, FLUID_3D *fluid) { + if (wt->_fuelBig) { + fluid->processBurn(wt->_fuelBig, wt->_densityBig, wt->_reactBig, wt->_flameBig, 0, + wt->_color_rBig, wt->_color_gBig, wt->_color_bBig, wt->_totalCellsBig, fluid->_dt); + } wt->stepTurbulenceFull(fluid->_dt/fluid->_dx, fluid->_xVelocity, fluid->_yVelocity, fluid->_zVelocity, fluid->_obstacles); } -extern "C" void smoke_initBlenderRNA(FLUID_3D *fluid, float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli) +extern "C" void smoke_initBlenderRNA(FLUID_3D *fluid, float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli, float *burning_rate, + float *flame_smoke, float *flame_smoke_color, float *flame_vorticity, float *flame_ignition_temp, float *flame_max_temp) { - fluid->initBlenderRNA(alpha, beta, dt_factor, vorticity, border_colli); + fluid->initBlenderRNA(alpha, beta, dt_factor, vorticity, border_colli, burning_rate, flame_smoke, flame_smoke_color, flame_vorticity, flame_ignition_temp, flame_max_temp); } -extern "C" void smoke_dissolve(FLUID_3D *fluid, int speed, int log) +extern "C" void smoke_initWaveletBlenderRNA(WTURBULENCE *wt, float *strength) { - float *density = fluid->_density; - //float *densityOld = fluid->_densityOld; - float *heat = fluid->_heat; - - if(log) - { - /* max density/speed = dydx */ - float dydx = 1.0 / (float)speed; - size_t size= fluid->_xRes * fluid->_yRes * fluid->_zRes; - - for(size_t i = 0; i < size; i++) - { - density[i] *= (1.0 - dydx); - - if(density[i] < 0.0f) - density[i] = 0.0f; - - heat[i] *= (1.0 - dydx); - - /*if(heat[i] < 0.0f) - heat[i] = 0.0f;*/ - } - } - else // linear falloff - { - /* max density/speed = dydx */ - float dydx = 1.0 / (float)speed; - size_t size= fluid->_xRes * fluid->_yRes * fluid->_zRes; - - for(size_t i = 0; i < size; i++) - { - density[i] -= dydx; - - if(density[i] < 0.0f) - density[i] = 0.0f; - - if(abs(heat[i]) < dydx) heat[i] = 0.0f; - else if (heat[i]>0.0f) heat[i] -= dydx; - else if (heat[i]<0.0f) heat[i] += dydx; - - } - } + wt->initBlenderRNA(strength); } -extern "C" void smoke_dissolve_wavelet(WTURBULENCE *wt, int speed, int log) +static void data_dissolve(float *density, float *heat, float *r, float *g, float *b, int total_cells, int speed, int log) { - float *density = wt->getDensityBig(); - Vec3Int r = wt->getResBig(); - - if(log) - { + if (log) { /* max density/speed = dydx */ - float dydx = 1.0 / (float)speed; - size_t size= r[0] * r[1] * r[2]; + float fac = 1.0f - (1.0f / (float)speed); - for(size_t i = 0; i < size; i++) + for(size_t i = 0; i < total_cells; i++) { - density[i] *= (1.0 - dydx); - - if(density[i] < 0.0f) - density[i] = 0.0f; + /* density */ + density[i] *= fac; + + /* heat */ + if (heat) { + heat[i] *= fac; + } + + /* color */ + if (r) { + r[i] *= fac; + g[i] *= fac; + b[i] *= fac; + } } } else // linear falloff { /* max density/speed = dydx */ - float dydx = 1.0 / (float)speed; - size_t size= r[0] * r[1] * r[2]; + float dydx = 1.0f / (float)speed; - for(size_t i = 0; i < size; i++) + for(size_t i = 0; i < total_cells; i++) { + float d = density[i]; + /* density */ density[i] -= dydx; + if (density[i] < 0.0f) + density[i] = 0.0f; - if(density[i] < 0.0f) - density[i] = 0.0f; + /* heat */ + if (heat) { + if (abs(heat[i]) < dydx) heat[i] = 0.0f; + else if (heat[i] > 0.0f) heat[i] -= dydx; + else if (heat[i] < 0.0f) heat[i] += dydx; + } + + /* color */ + if (r && d) { + r[i] *= (density[i]/d); + g[i] *= (density[i]/d); + b[i] *= (density[i]/d); + } + } } } -extern "C" void smoke_initWaveletBlenderRNA(WTURBULENCE *wt, float *strength) +extern "C" void smoke_dissolve(FLUID_3D *fluid, int speed, int log) { - wt->initBlenderRNA(strength); + data_dissolve(fluid->_density, fluid->_heat, fluid->_color_r, fluid->_color_g, fluid->_color_b, fluid->_totalCells, speed, log); } -template < class T > inline T ABS( T a ) +extern "C" void smoke_dissolve_wavelet(WTURBULENCE *wt, int speed, int log) { - return (0 < a) ? a : -a ; + data_dissolve(wt->_densityBig, 0, wt->_color_rBig, wt->_color_gBig, wt->_color_bBig, wt->_totalCellsBig, speed, log); } -extern "C" void smoke_export(FLUID_3D *fluid, float *dt, float *dx, float **dens, float **densold, float **heat, float **heatold, float **vx, float **vy, float **vz, float **vxold, float **vyold, float **vzold, unsigned char **obstacles) +extern "C" void smoke_export(FLUID_3D *fluid, float *dt, float *dx, float **dens, float **react, float **flame, float **fuel, float **heat, + float **heatold, float **vx, float **vy, float **vz, float **r, float **g, float **b, unsigned char **obstacles) { *dens = fluid->_density; - *densold = fluid->_densityOld; + *fuel = fluid->_fuel; + *react = fluid->_react; + *flame = fluid->_flame; *heat = fluid->_heat; *heatold = fluid->_heatOld; *vx = fluid->_xVelocity; *vy = fluid->_yVelocity; *vz = fluid->_zVelocity; - *vxold = fluid->_xVelocityOld; - *vyold = fluid->_yVelocityOld; - *vzold = fluid->_zVelocityOld; + *r = fluid->_color_r; + *g = fluid->_color_g; + *b = fluid->_color_b; *obstacles = fluid->_obstacles; *dt = fluid->_dt; *dx = fluid->_dx; - } -extern "C" void smoke_turbulence_export(WTURBULENCE *wt, float **dens, float **densold, float **tcu, float **tcv, float **tcw) +extern "C" void smoke_turbulence_export(WTURBULENCE *wt, float **dens, float **react, float **flame, float **fuel, + float **r, float **g, float **b , float **tcu, float **tcv, float **tcw) { - if(!wt) + if (!wt) return; *dens = wt->_densityBig; - *densold = wt->_densityBigOld; + *fuel = wt->_fuelBig; + *react = wt->_reactBig; + *flame = wt->_flameBig; + *r = wt->_color_rBig; + *g = wt->_color_gBig; + *b = wt->_color_bBig; *tcu = wt->_tcU; *tcv = wt->_tcV; *tcw = wt->_tcW; @@ -221,6 +211,16 @@ extern "C" float *smoke_get_density(FLUID_3D *fluid) return fluid->_density; } +extern "C" float *smoke_get_fuel(FLUID_3D *fluid) +{ + return fluid->_fuel; +} + +extern "C" float *smoke_get_react(FLUID_3D *fluid) +{ + return fluid->_react; +} + extern "C" float *smoke_get_heat(FLUID_3D *fluid) { return fluid->_heat; @@ -256,15 +256,137 @@ extern "C" float *smoke_get_force_z(FLUID_3D *fluid) return fluid->_zForce; } +extern "C" float *smoke_get_flame(FLUID_3D *fluid) +{ + return fluid->_flame; +} + +extern "C" float *smoke_get_color_r(FLUID_3D *fluid) +{ + return fluid->_color_r; +} + +extern "C" float *smoke_get_color_g(FLUID_3D *fluid) +{ + return fluid->_color_g; +} + +extern "C" float *smoke_get_color_b(FLUID_3D *fluid) +{ + return fluid->_color_b; +} + +static void get_rgba(float *r, float *g, float *b, float *a, int total_cells, float *data, int sequential) +{ + int i; + int m = 4, i_g = 1, i_b = 2, i_a = 3; + /* sequential data */ + if (sequential) { + m = 1; + i_g *= total_cells; + i_b *= total_cells; + i_a *= total_cells; + } + + for (i=0; i<total_cells; i++) { + float alpha = a[i]; + if (alpha) { + data[i*m ] = r[i]; + data[i*m+i_g] = g[i]; + data[i*m+i_b] = b[i]; + } + else { + data[i*m ] = data[i*m+i_g] = data[i*m+i_b] = 0.0f; + } + data[i*m+i_a] = alpha; + } +} + +extern "C" void smoke_get_rgba(FLUID_3D *fluid, float *data, int sequential) +{ + get_rgba(fluid->_color_r, fluid->_color_g, fluid->_color_b, fluid->_density, fluid->_totalCells, data, sequential); +} + +extern "C" void smoke_turbulence_get_rgba(WTURBULENCE *wt, float *data, int sequential) +{ + get_rgba(wt->_color_rBig, wt->_color_gBig, wt->_color_bBig, wt->_densityBig, wt->_totalCellsBig, data, sequential); +} + +/* get a single color premultiplied voxel grid */ +static void get_rgba_from_density(float color[3], float *a, int total_cells, float *data, int sequential) +{ + int i; + int m = 4, i_g = 1, i_b = 2, i_a = 3; + /* sequential data */ + if (sequential) { + m = 1; + i_g *= total_cells; + i_b *= total_cells; + i_a *= total_cells; + } + + for (i=0; i<total_cells; i++) { + float alpha = a[i]; + if (alpha) { + data[i*m ] = color[0] * alpha; + data[i*m+i_g] = color[1] * alpha; + data[i*m+i_b] = color[2] * alpha; + } + else { + data[i*m ] = data[i*m+i_g] = data[i*m+i_b] = 0.0f; + } + data[i*m+i_a] = alpha; + } +} + +extern "C" void smoke_get_rgba_from_density(FLUID_3D *fluid, float color[3], float *data, int sequential) +{ + get_rgba_from_density(color, fluid->_density, fluid->_totalCells, data, sequential); +} + +extern "C" void smoke_turbulence_get_rgba_from_density(WTURBULENCE *wt, float color[3], float *data, int sequential) +{ + get_rgba_from_density(color, wt->_densityBig, wt->_totalCellsBig, data, sequential); +} + extern "C" float *smoke_turbulence_get_density(WTURBULENCE *wt) { return wt ? wt->getDensityBig() : NULL; } +extern "C" float *smoke_turbulence_get_fuel(WTURBULENCE *wt) +{ + return wt ? wt->getFuelBig() : NULL; +} + +extern "C" float *smoke_turbulence_get_react(WTURBULENCE *wt) +{ + return wt ? wt->_reactBig : NULL; +} + +extern "C" float *smoke_turbulence_get_color_r(WTURBULENCE *wt) +{ + return wt ? wt->_color_rBig : NULL; +} + +extern "C" float *smoke_turbulence_get_color_g(WTURBULENCE *wt) +{ + return wt ? wt->_color_gBig : NULL; +} + +extern "C" float *smoke_turbulence_get_color_b(WTURBULENCE *wt) +{ + return wt ? wt->_color_bBig : NULL; +} + +extern "C" float *smoke_turbulence_get_flame(WTURBULENCE *wt) +{ + return wt ? wt->getFlameBig() : NULL; +} + extern "C" void smoke_turbulence_get_res(WTURBULENCE *wt, int *res) { - if(wt) - { + if (wt) { Vec3Int r = wt->getResBig(); res[0] = r[0]; res[1] = r[1]; @@ -272,6 +394,15 @@ extern "C" void smoke_turbulence_get_res(WTURBULENCE *wt, int *res) } } +extern "C" int smoke_turbulence_get_cells(WTURBULENCE *wt) +{ + if (wt) { + Vec3Int r = wt->getResBig(); + return r[0] * r[1] * r[2]; + } + return 0; +} + extern "C" unsigned char *smoke_get_obstacle(FLUID_3D *fluid) { return fluid->_obstacles; @@ -295,3 +426,61 @@ extern "C" void smoke_turbulence_set_noise(WTURBULENCE *wt, int type) { wt->setNoise(type); } + +extern "C" void flame_get_spectrum(unsigned char *spec, int width, float t1, float t2) +{ + spectrum(t1, t2, width, spec); +} + +extern "C" int smoke_has_heat(FLUID_3D *fluid) +{ + return (fluid->_heat) ? 1 : 0; +} + +extern "C" int smoke_has_fuel(FLUID_3D *fluid) +{ + return (fluid->_fuel) ? 1 : 0; +} + +extern "C" int smoke_has_colors(FLUID_3D *fluid) +{ + return (fluid->_color_r && fluid->_color_g && fluid->_color_b) ? 1 : 0; +} + +extern "C" int smoke_turbulence_has_fuel(WTURBULENCE *wt) +{ + return (wt->_fuelBig) ? 1 : 0; +} + +extern "C" int smoke_turbulence_has_colors(WTURBULENCE *wt) +{ + return (wt->_color_rBig && wt->_color_gBig && wt->_color_bBig) ? 1 : 0; +} + +/* additional field initialization */ +extern "C" void smoke_ensure_heat(FLUID_3D *fluid) +{ + if (fluid) { + fluid->initHeat(); + } +} + +extern "C" void smoke_ensure_fire(FLUID_3D *fluid, WTURBULENCE *wt) +{ + if (fluid) { + fluid->initFire(); + } + if (wt) { + wt->initFire(); + } +} + +extern "C" void smoke_ensure_colors(FLUID_3D *fluid, WTURBULENCE *wt, float init_r, float init_g, float init_b) +{ + if (fluid) { + fluid->initColors(init_r, init_g, init_b); + } + if (wt) { + wt->initColors(init_r, init_g, init_b); + } +} diff --git a/intern/smoke/intern/spectrum.cpp b/intern/smoke/intern/spectrum.cpp new file mode 100644 index 00000000000..30433451ac2 --- /dev/null +++ b/intern/smoke/intern/spectrum.cpp @@ -0,0 +1,426 @@ +/* + Colour Rendering of Spectra + + by John Walker + http://www.fourmilab.ch/ + + Last updated: March 9, 2003 + + This program is in the public domain. + + For complete information about the techniques employed in + this program, see the World-Wide Web document: + + http://www.fourmilab.ch/documents/specrend/ + + The xyz_to_rgb() function, which was wrong in the original + version of this program, was corrected by: + + Andrew J. S. Hamilton 21 May 1999 + Andrew.Hamilton@Colorado.EDU + http://casa.colorado.edu/~ajsh/ + + who also added the gamma correction facilities and + modified constrain_rgb() to work by desaturating the + colour by adding white. + + A program which uses these functions to plot CIE + "tongue" diagrams called "ppmcie" is included in + the Netpbm graphics toolkit: + http://netpbm.sourceforge.net/ + (The program was called cietoppm in earlier + versions of Netpbm.) + +*/ + +#include <stdio.h> +#include <math.h> +#include "spectrum.h" + +/* A colour system is defined by the CIE x and y coordinates of + its three primary illuminants and the x and y coordinates of + the white point. */ + +struct colourSystem { + const char *name; /* Colour system name */ + double xRed, yRed, /* Red x, y */ + xGreen, yGreen, /* Green x, y */ + xBlue, yBlue, /* Blue x, y */ + xWhite, yWhite, /* White point x, y */ + gamma; /* Gamma correction for system */ +}; + +/* White point chromaticities. */ + +#define IlluminantC 0.3101, 0.3162 /* For NTSC television */ +#define IlluminantD65 0.3127, 0.3291 /* For EBU and SMPTE */ +#define IlluminantE 0.33333333, 0.33333333 /* CIE equal-energy illuminant */ + +/* Gamma of nonlinear correction. + + See Charles Poynton's ColorFAQ Item 45 and GammaFAQ Item 6 at: + + http://www.poynton.com/ColorFAQ.html + http://www.poynton.com/GammaFAQ.html + +*/ + +#define GAMMA_REC709 0 /* Rec. 709 */ + +static struct colourSystem + /* Name xRed yRed xGreen yGreen xBlue yBlue White point Gamma */ +#if 0 /* UNUSED */ + NTSCsystem = { "NTSC", 0.67, 0.33, 0.21, 0.71, 0.14, 0.08, IlluminantC, GAMMA_REC709 }, + EBUsystem = { "EBU (PAL/SECAM)", 0.64, 0.33, 0.29, 0.60, 0.15, 0.06, IlluminantD65, GAMMA_REC709 }, + SMPTEsystem = { "SMPTE", 0.630, 0.340, 0.310, 0.595, 0.155, 0.070, IlluminantD65, GAMMA_REC709 }, + HDTVsystem = { "HDTV", 0.670, 0.330, 0.210, 0.710, 0.150, 0.060, IlluminantD65, GAMMA_REC709 }, +#endif + + CIEsystem = { "CIE", 0.7355, 0.2645, 0.2658, 0.7243, 0.1669, 0.0085, IlluminantE, GAMMA_REC709 }; + +#if 0 /* UNUSED */ + Rec709system = { "CIE REC 709", 0.64, 0.33, 0.30, 0.60, 0.15, 0.06, IlluminantD65, GAMMA_REC709 }; +#endif + +/* UPVP_TO_XY + + Given 1976 coordinates u', v', determine 1931 chromaticities x, y + +*/ + +#if 0 /* UNUSED */ +static void upvp_to_xy(double up, double vp, double *xc, double *yc) +{ + *xc = (9 * up) / ((6 * up) - (16 * vp) + 12); + *yc = (4 * vp) / ((6 * up) - (16 * vp) + 12); +} +#endif + +/* XY_TO_UPVP + + Given 1931 chromaticities x, y, determine 1976 coordinates u', v' + +*/ + +#if 0 /* UNUSED */ +static void xy_to_upvp(double xc, double yc, double *up, double *vp) +{ + *up = (4 * xc) / ((-2 * xc) + (12 * yc) + 3); + *vp = (9 * yc) / ((-2 * xc) + (12 * yc) + 3); +} +#endif + +/* XYZ_TO_RGB + + Given an additive tricolour system CS, defined by the CIE x + and y chromaticities of its three primaries (z is derived + trivially as 1-(x+y)), and a desired chromaticity (XC, YC, + ZC) in CIE space, determine the contribution of each + primary in a linear combination which sums to the desired + chromaticity. If the requested chromaticity falls outside + the Maxwell triangle (colour gamut) formed by the three + primaries, one of the r, g, or b weights will be negative. + + Caller can use constrain_rgb() to desaturate an + outside-gamut colour to the closest representation within + the available gamut and/or norm_rgb to normalise the RGB + components so the largest nonzero component has value 1. + +*/ + +static void xyz_to_rgb(struct colourSystem *cs, + double xc, double yc, double zc, + double *r, double *g, double *b) +{ + double xr, yr, zr, xg, yg, zg, xb, yb, zb; + double xw, yw, zw; + double rx, ry, rz, gx, gy, gz, bx, by, bz; + double rw, gw, bw; + + xr = cs->xRed; yr = cs->yRed; zr = 1 - (xr + yr); + xg = cs->xGreen; yg = cs->yGreen; zg = 1 - (xg + yg); + xb = cs->xBlue; yb = cs->yBlue; zb = 1 - (xb + yb); + + xw = cs->xWhite; yw = cs->yWhite; zw = 1 - (xw + yw); + + /* xyz -> rgb matrix, before scaling to white. */ + + rx = (yg * zb) - (yb * zg); ry = (xb * zg) - (xg * zb); rz = (xg * yb) - (xb * yg); + gx = (yb * zr) - (yr * zb); gy = (xr * zb) - (xb * zr); gz = (xb * yr) - (xr * yb); + bx = (yr * zg) - (yg * zr); by = (xg * zr) - (xr * zg); bz = (xr * yg) - (xg * yr); + + /* White scaling factors. + Dividing by yw scales the white luminance to unity, as conventional. */ + + rw = ((rx * xw) + (ry * yw) + (rz * zw)) / yw; + gw = ((gx * xw) + (gy * yw) + (gz * zw)) / yw; + bw = ((bx * xw) + (by * yw) + (bz * zw)) / yw; + + /* xyz -> rgb matrix, correctly scaled to white. */ + + rx = rx / rw; ry = ry / rw; rz = rz / rw; + gx = gx / gw; gy = gy / gw; gz = gz / gw; + bx = bx / bw; by = by / bw; bz = bz / bw; + + /* rgb of the desired point */ + + *r = (rx * xc) + (ry * yc) + (rz * zc); + *g = (gx * xc) + (gy * yc) + (gz * zc); + *b = (bx * xc) + (by * yc) + (bz * zc); +} + +/* INSIDE_GAMUT + + Test whether a requested colour is within the gamut + achievable with the primaries of the current colour + system. This amounts simply to testing whether all the + primary weights are non-negative. */ + +#if 0 /* UNUSED */ +static int inside_gamut(double r, double g, double b) +{ + return (r >= 0) && (g >= 0) && (b >= 0); +} +#endif + +/* CONSTRAIN_RGB + + If the requested RGB shade contains a negative weight for + one of the primaries, it lies outside the colour gamut + accessible from the given triple of primaries. Desaturate + it by adding white, equal quantities of R, G, and B, enough + to make RGB all positive. The function returns 1 if the + components were modified, zero otherwise. + +*/ + +static int constrain_rgb(double *r, double *g, double *b) +{ + double w; + + /* Amount of white needed is w = - min(0, *r, *g, *b) */ + + w = (0 < *r) ? 0 : *r; + w = (w < *g) ? w : *g; + w = (w < *b) ? w : *b; + w = -w; + + /* Add just enough white to make r, g, b all positive. */ + + if (w > 0) { + *r += w; *g += w; *b += w; + return 1; /* Colour modified to fit RGB gamut */ + } + + return 0; /* Colour within RGB gamut */ +} + +/* GAMMA_CORRECT_RGB + + Transform linear RGB values to nonlinear RGB values. Rec. + 709 is ITU-R Recommendation BT. 709 (1990) ``Basic + Parameter Values for the HDTV Standard for the Studio and + for International Programme Exchange'', formerly CCIR Rec. + 709. For details see + + http://www.poynton.com/ColorFAQ.html + http://www.poynton.com/GammaFAQ.html +*/ + +#if 0 /* UNUSED */ +static void gamma_correct(const struct colourSystem *cs, double *c) +{ + double gamma; + + gamma = cs->gamma; + + if (gamma == GAMMA_REC709) { + /* Rec. 709 gamma correction. */ + double cc = 0.018; + + if (*c < cc) { + *c *= ((1.099 * pow(cc, 0.45)) - 0.099) / cc; + } else { + *c = (1.099 * pow(*c, 0.45)) - 0.099; + } + } else { + /* Nonlinear colour = (Linear colour)^(1/gamma) */ + *c = pow(*c, 1.0 / gamma); + } +} + +static void gamma_correct_rgb(const struct colourSystem *cs, double *r, double *g, double *b) +{ + gamma_correct(cs, r); + gamma_correct(cs, g); + gamma_correct(cs, b); +} +#endif + +/* NORM_RGB + + Normalise RGB components so the most intense (unless all + are zero) has a value of 1. + +*/ + +static void norm_rgb(double *r, double *g, double *b) +{ +#define Max(a, b) (((a) > (b)) ? (a) : (b)) + double greatest = Max(*r, Max(*g, *b)); + + if (greatest > 0) { + *r /= greatest; + *g /= greatest; + *b /= greatest; + } +#undef Max +} + +/* SPECTRUM_TO_XYZ + + Calculate the CIE X, Y, and Z coordinates corresponding to + a light source with spectral distribution given by the + function SPEC_INTENS, which is called with a series of + wavelengths between 380 and 780 nm (the argument is + expressed in meters), which returns emittance at that + wavelength in arbitrary units. The chromaticity + coordinates of the spectrum are returned in the x, y, and z + arguments which respect the identity: + + x + y + z = 1. +*/ + +static void spectrum_to_xyz(double (*spec_intens)(double wavelength), + double *x, double *y, double *z) +{ + int i; + double lambda, X = 0, Y = 0, Z = 0, XYZ; + + /* CIE colour matching functions xBar, yBar, and zBar for + wavelengths from 380 through 780 nanometers, every 5 + nanometers. For a wavelength lambda in this range: + + cie_colour_match[(lambda - 380) / 5][0] = xBar + cie_colour_match[(lambda - 380) / 5][1] = yBar + cie_colour_match[(lambda - 380) / 5][2] = zBar + + To save memory, this table can be declared as floats + rather than doubles; (IEEE) float has enough + significant bits to represent the values. It's declared + as a double here to avoid warnings about "conversion + between floating-point types" from certain persnickety + compilers. */ + + static double cie_colour_match[81][3] = { + {0.0014,0.0000,0.0065}, {0.0022,0.0001,0.0105}, {0.0042,0.0001,0.0201}, + {0.0076,0.0002,0.0362}, {0.0143,0.0004,0.0679}, {0.0232,0.0006,0.1102}, + {0.0435,0.0012,0.2074}, {0.0776,0.0022,0.3713}, {0.1344,0.0040,0.6456}, + {0.2148,0.0073,1.0391}, {0.2839,0.0116,1.3856}, {0.3285,0.0168,1.6230}, + {0.3483,0.0230,1.7471}, {0.3481,0.0298,1.7826}, {0.3362,0.0380,1.7721}, + {0.3187,0.0480,1.7441}, {0.2908,0.0600,1.6692}, {0.2511,0.0739,1.5281}, + {0.1954,0.0910,1.2876}, {0.1421,0.1126,1.0419}, {0.0956,0.1390,0.8130}, + {0.0580,0.1693,0.6162}, {0.0320,0.2080,0.4652}, {0.0147,0.2586,0.3533}, + {0.0049,0.3230,0.2720}, {0.0024,0.4073,0.2123}, {0.0093,0.5030,0.1582}, + {0.0291,0.6082,0.1117}, {0.0633,0.7100,0.0782}, {0.1096,0.7932,0.0573}, + {0.1655,0.8620,0.0422}, {0.2257,0.9149,0.0298}, {0.2904,0.9540,0.0203}, + {0.3597,0.9803,0.0134}, {0.4334,0.9950,0.0087}, {0.5121,1.0000,0.0057}, + {0.5945,0.9950,0.0039}, {0.6784,0.9786,0.0027}, {0.7621,0.9520,0.0021}, + {0.8425,0.9154,0.0018}, {0.9163,0.8700,0.0017}, {0.9786,0.8163,0.0014}, + {1.0263,0.7570,0.0011}, {1.0567,0.6949,0.0010}, {1.0622,0.6310,0.0008}, + {1.0456,0.5668,0.0006}, {1.0026,0.5030,0.0003}, {0.9384,0.4412,0.0002}, + {0.8544,0.3810,0.0002}, {0.7514,0.3210,0.0001}, {0.6424,0.2650,0.0000}, + {0.5419,0.2170,0.0000}, {0.4479,0.1750,0.0000}, {0.3608,0.1382,0.0000}, + {0.2835,0.1070,0.0000}, {0.2187,0.0816,0.0000}, {0.1649,0.0610,0.0000}, + {0.1212,0.0446,0.0000}, {0.0874,0.0320,0.0000}, {0.0636,0.0232,0.0000}, + {0.0468,0.0170,0.0000}, {0.0329,0.0119,0.0000}, {0.0227,0.0082,0.0000}, + {0.0158,0.0057,0.0000}, {0.0114,0.0041,0.0000}, {0.0081,0.0029,0.0000}, + {0.0058,0.0021,0.0000}, {0.0041,0.0015,0.0000}, {0.0029,0.0010,0.0000}, + {0.0020,0.0007,0.0000}, {0.0014,0.0005,0.0000}, {0.0010,0.0004,0.0000}, + {0.0007,0.0002,0.0000}, {0.0005,0.0002,0.0000}, {0.0003,0.0001,0.0000}, + {0.0002,0.0001,0.0000}, {0.0002,0.0001,0.0000}, {0.0001,0.0000,0.0000}, + {0.0001,0.0000,0.0000}, {0.0001,0.0000,0.0000}, {0.0000,0.0000,0.0000} + }; + + for (i = 0, lambda = 380; lambda < 780.1; i++, lambda += 5) { + double Me; + + Me = (*spec_intens)(lambda); + X += Me * cie_colour_match[i][0]; + Y += Me * cie_colour_match[i][1]; + Z += Me * cie_colour_match[i][2]; + } + XYZ = (X + Y + Z); + *x = X / XYZ; + *y = Y / XYZ; + *z = Z / XYZ; +} + +/* BB_SPECTRUM + + Calculate, by Planck's radiation law, the emittance of a black body + of temperature bbTemp at the given wavelength (in metres). */ + +double bbTemp = 5000; /* Hidden temperature argument + to BB_SPECTRUM. */ +static double bb_spectrum(double wavelength) +{ + double wlm = wavelength * 1e-9; /* Wavelength in meters */ + + return (3.74183e-16 * pow(wlm, -5.0)) / + (exp(1.4388e-2 / (wlm * bbTemp)) - 1.0); +} + +static void xyz_to_lms(double x, double y, double z, double* l, double* m, double* s) +{ + *l = 0.3897*x + 0.6890*y - 0.0787*z; + *m = -0.2298*x + 1.1834*y + 0.0464*z; + *s = z; +} + +static void lms_to_xyz(double l, double m, double s, double* x, double *y, double* z) +{ + *x = 1.9102*l - 1.1121*m + 0.2019*s; + *y = 0.3709*l + 0.6290*m + 0.0000*s; + *z = s; +} + +void spectrum(double t1, double t2, int N, unsigned char *d) +{ + int i,j,dj; + double X,Y,Z,R,G,B,L,M,S, Lw, Mw, Sw; + struct colourSystem *cs = &CIEsystem; + + j = 0; dj = 1; + if (t1<t2) { + double t = t1; + t1 = t2; + t2 = t; + j = N-1; dj=-1; + } + + for (i=0; i<N; i++) { + bbTemp = t1 + (t2-t1)/N*i; + + // integrate blackbody radiation spectrum to XYZ + spectrum_to_xyz(bb_spectrum, &X, &Y, &Z); + + // normalize highest temperature to white (in LMS system) + xyz_to_lms(X,Y,Z,&L,&M,&S); + if (i==0) { + Lw=1/L; Mw=1/M; Sw=1/S; + } + L *= Lw; M *= Mw; S *= Sw; + lms_to_xyz(L,M,S,&X,&Y,&Z); + + // convert to RGB + xyz_to_rgb(cs, X, Y, Z, &R, &G, &B); + constrain_rgb(&R, &G, &B); + norm_rgb(&R, &G, &B); + d[(j<<2)] = (unsigned char) ((double)R*255); + d[(j<<2)+1] = (unsigned char) ((double)G*255); + d[(j<<2)+2] = (unsigned char) ((double)B*255); + d[(j<<2)+3] = (B>0.1)? B*255 : 0; + j += dj; + } +} diff --git a/intern/smoke/intern/spectrum.h b/intern/smoke/intern/spectrum.h new file mode 100644 index 00000000000..3ffd41f9517 --- /dev/null +++ b/intern/smoke/intern/spectrum.h @@ -0,0 +1,6 @@ +#ifndef __SPECTRUM_H +#define __SPECTRUM_H + +void spectrum(double t1, double t2, int n, unsigned char *d); + +#endif diff --git a/intern/utfconv/utfconv.h b/intern/utfconv/utfconv.h index 3bfd2772991..cf0e69170a2 100644 --- a/intern/utfconv/utfconv.h +++ b/intern/utfconv/utfconv.h @@ -95,7 +95,7 @@ wchar_t *alloc_utf16_from_8(const char *in8, size_t add); wchar_t *in8str ## _16 = alloc_utf16_from_8((char *)in8str, 0) #define UTF16_UN_ENCODE(in8str) \ - free(in8str ## _16); } (void)0 + free(in8str ## _16); } (void)0 #ifdef __cplusplus } |