Field3D
|
00001 //----------------------------------------------------------------------------// 00002 00003 /* 00004 * Copyright (c) 2009 Sony Pictures Imageworks Inc 00005 * 00006 * All rights reserved. 00007 * 00008 * Redistribution and use in source and binary forms, with or without 00009 * modification, are permitted provided that the following conditions 00010 * are met: 00011 * 00012 * Redistributions of source code must retain the above copyright 00013 * notice, this list of conditions and the following disclaimer. 00014 * Redistributions in binary form must reproduce the above copyright 00015 * notice, this list of conditions and the following disclaimer in the 00016 * documentation and/or other materials provided with the 00017 * distribution. Neither the name of Sony Pictures Imageworks nor the 00018 * names of its contributors may be used to endorse or promote 00019 * products derived from this software without specific prior written 00020 * permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00023 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00024 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00025 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00026 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00027 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00028 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00029 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00030 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 00031 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00032 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 00033 * OF THE POSSIBILITY OF SUCH DAMAGE. 00034 */ 00035 00036 //----------------------------------------------------------------------------// 00037 00043 //----------------------------------------------------------------------------// 00044 00045 #ifndef _INCLUDED_Field3D_Curve_H_ 00046 #define _INCLUDED_Field3D_Curve_H_ 00047 00048 //----------------------------------------------------------------------------// 00049 00050 #include <algorithm> 00051 #include <utility> 00052 #include <vector> 00053 00054 #include <boost/lexical_cast.hpp> 00055 00056 #include <OpenEXR/ImathFun.h> 00057 #include <OpenEXR/ImathMatrix.h> 00058 00059 //----------------------------------------------------------------------------// 00060 00061 #include "ns.h" 00062 00063 FIELD3D_NAMESPACE_OPEN 00064 00065 //----------------------------------------------------------------------------// 00066 // Curve 00067 //----------------------------------------------------------------------------// 00068 00075 //----------------------------------------------------------------------------// 00076 00077 template <typename T> 00078 class Curve 00079 { 00080 public: 00081 00082 // Typedefs ------------------------------------------------------------------ 00083 00084 typedef std::pair<float, T> Sample; 00085 typedef std::vector<Sample> SampleVec; 00086 00087 // Main methods -------------------------------------------------------------- 00088 00092 void addSample(const float t, const T &value); 00093 00096 T linear(const float t) const; 00097 00099 size_t numSamples() const 00100 { return m_samples.size(); } 00101 00103 const SampleVec& samples() const 00104 { return m_samples; } 00105 00107 void clear() 00108 { SampleVec().swap(m_samples); } 00109 00110 private: 00111 00112 // Structs ------------------------------------------------------------------- 00113 00115 struct CheckTGreaterThan : 00116 public std::unary_function<std::pair<float, T>, bool> 00117 { 00118 CheckTGreaterThan(float match) 00119 : m_match(match) 00120 { } 00121 bool operator()(std::pair<float, T> test) 00122 { 00123 return test.first > m_match; 00124 } 00125 private: 00126 float m_match; 00127 }; 00128 00130 struct CheckTEqual : 00131 public std::unary_function<std::pair<float, T>, bool> 00132 { 00133 CheckTEqual(float match) 00134 : m_match(match) 00135 { } 00136 bool operator()(std::pair<float, T> test) 00137 { 00138 return test.first == m_match; 00139 } 00140 private: 00141 float m_match; 00142 }; 00143 00144 // Utility methods ----------------------------------------------------------- 00145 00150 T defaultReturnValue() const 00151 { return T(0); } 00152 00156 T lerp(const Sample &lower, const Sample &upper, const float t) const 00157 { return Imath::lerp(lower.second, upper.second, t); } 00158 00159 // Private data members ------------------------------------------------------ 00160 00163 SampleVec m_samples; 00164 00165 }; 00166 00167 //----------------------------------------------------------------------------// 00168 // Template implementations 00169 //----------------------------------------------------------------------------// 00170 00171 template <typename T> 00172 void Curve<T>::addSample(const float t, const T &value) 00173 { 00174 using namespace std; 00175 // Check that sample time is not already in curve 00176 typename SampleVec::iterator i = 00177 find_if(m_samples.begin(), m_samples.end(), CheckTEqual(t)); 00178 if (i != m_samples.end()) { 00179 // Sample position already exists, so we replace it 00180 i->second = value; 00181 return; 00182 } 00183 // Find the first sample location that is greater than the interpolation 00184 // position 00185 i = find_if(m_samples.begin(), m_samples.end(), CheckTGreaterThan(t)); 00186 // If we get something other than end() back then we insert the new 00187 // sample before that. If there wasn't a larger value we add this sample 00188 // to the end of the vector. 00189 if (i != m_samples.end()) { 00190 m_samples.insert(i, make_pair(t, value)); 00191 } else { 00192 m_samples.push_back(make_pair(t, value)); 00193 } 00194 } 00195 00196 //----------------------------------------------------------------------------// 00197 00198 template <typename T> 00199 T Curve<T>::linear(const float t) const 00200 { 00201 using namespace std; 00202 // If there are no samples, return zero 00203 if (m_samples.size() == 0) { 00204 return defaultReturnValue(); 00205 } 00206 // Find the first sample location that is greater than the interpolation 00207 // position 00208 typename SampleVec::const_iterator i = 00209 find_if(m_samples.begin(), m_samples.end(), CheckTGreaterThan(t)); 00210 // If we get end() back then there was no sample larger, so we return the 00211 // last value. If we got the first value then there is only one value and 00212 // we return that. 00213 if (i == m_samples.end()) { 00214 return m_samples.back().second; 00215 } else if (i == m_samples.begin()) { 00216 return m_samples.front().second; 00217 } 00218 // Interpolate between the nearest two samples. 00219 const Sample &upper = *i; 00220 const Sample &lower = *(--i); 00221 const float interpT = Imath::lerpfactor(t, lower.first, upper.first); 00222 return lerp(lower, upper, interpT); 00223 } 00224 00225 //----------------------------------------------------------------------------// 00226 // Template specializations 00227 //----------------------------------------------------------------------------// 00228 00229 template <> 00230 inline Imath::Matrix44<float> 00231 Curve<Imath::Matrix44<float> >::defaultReturnValue() const 00232 { 00233 Imath::Matrix44<float> identity; 00234 identity.makeIdentity(); 00235 return identity; 00236 } 00237 00238 //----------------------------------------------------------------------------// 00239 00240 template <> 00241 inline Imath::Matrix44<double> 00242 Curve<Imath::Matrix44<double> >::defaultReturnValue() const 00243 { 00244 Imath::Matrix44<double> identity; 00245 identity.makeIdentity(); 00246 return identity; 00247 } 00248 00249 //----------------------------------------------------------------------------// 00250 00251 FIELD3D_NAMESPACE_HEADER_CLOSE 00252 00253 //----------------------------------------------------------------------------// 00254 00255 #endif // Include guard