Visualization LibraryA lightweight C++ OpenGL middleware for 2D/3D graphics |
[Home] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://www.visualizationlibrary.com */ 00005 /* */ 00006 /* Copyright (c) 2005-2010, Michele Bosi */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without modification, */ 00010 /* are permitted provided that the following conditions are met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, this */ 00013 /* list of conditions and the following disclaimer. */ 00014 /* */ 00015 /* - Redistributions in binary form must reproduce the above copyright notice, this */ 00016 /* list of conditions and the following disclaimer in the documentation and/or */ 00017 /* other materials provided with the distribution. */ 00018 /* */ 00019 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ 00020 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ 00021 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ 00022 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ 00023 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ 00024 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ 00025 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ 00026 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ 00027 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ 00028 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 00029 /* */ 00030 /**************************************************************************************/ 00031 00032 #ifndef CatmullRomInterpolator_INCLUDE_ONCE 00033 #define CatmullRomInterpolator_INCLUDE_ONCE 00034 00035 #include <vlCore/Interpolator.hpp> 00036 00037 namespace vl 00038 { 00045 template<typename T> 00046 class CatmullRomInterpolator: public Object 00047 { 00048 public: 00049 virtual const char* className() { return "vl::CatmullRomInterpolator"; } 00050 00051 CatmullRomInterpolator() 00052 { 00053 VL_DEBUG_SET_OBJECT_NAME() 00054 } 00055 00056 CatmullRomInterpolator(const std::vector<T>& path): mPath(path) {} 00057 00059 void setupEndPoints(bool is_loop) 00060 { 00061 VL_CHECK(mPath.size()>=2) 00062 if (mPath.size()<2) 00063 return; 00064 00065 mCatmullRomSpline = mPath; 00066 00067 /* 00068 D-------C 00069 . | 00070 . | 00071 . | 00072 A-------B 00073 */ 00074 00075 if (is_loop) 00076 { 00077 T a = mCatmullRomSpline[0]; 00078 T b = mCatmullRomSpline[1]; 00079 T c = mCatmullRomSpline[mCatmullRomSpline.size()-2]; 00080 T d = mCatmullRomSpline[mCatmullRomSpline.size()-1]; 00081 00082 mCatmullRomSpline.insert(mCatmullRomSpline.begin(),d); 00083 mCatmullRomSpline.push_back(a); 00084 mCatmullRomSpline.push_back(b); 00085 } 00086 else 00087 { 00088 T a = mCatmullRomSpline[0] + (mCatmullRomSpline[0] - mCatmullRomSpline[1]); 00089 T b = mCatmullRomSpline[mCatmullRomSpline.size()-1] + (mCatmullRomSpline[mCatmullRomSpline.size()-1] - mCatmullRomSpline[mCatmullRomSpline.size()-2]); 00090 mCatmullRomSpline.insert(mCatmullRomSpline.begin(),a); 00091 mCatmullRomSpline.push_back(b); 00092 } 00093 00094 } 00095 00097 T computePoint(float t) const 00098 { 00099 VL_CHECK(mCatmullRomSpline.size() >= 4) 00100 size_t size = mCatmullRomSpline.size()-2; 00101 t = vl::clamp(t, 0.0f, 1.0f); 00102 if (t == 0.0f) 00103 return mCatmullRomSpline[1]; 00104 else 00105 if (t == 1.0f) 00106 return mCatmullRomSpline[ mCatmullRomSpline.size()-1-1 ]; 00107 else 00108 { 00109 int i = 1 + (int)((size-1)*t); 00110 int i0 = i-1; 00111 int i1 = i; 00112 int i2 = i+1; 00113 int i3 = i+2; 00114 VL_CHECK(i3<(int)mCatmullRomSpline.size()) 00115 float tt = (size-1)*t - int((size-1)*t); // vl::frac generates rounding errors 00116 T p0 = mCatmullRomSpline[i0]; 00117 T p1 = mCatmullRomSpline[i1]; 00118 T p2 = mCatmullRomSpline[i2]; 00119 T p3 = mCatmullRomSpline[i3]; 00120 T p = ( (p1 * 2.0f) + (-p0 + p2) * tt + 00121 ( p0*2.0f - p1*5.0f + p2*4.0f - p3) * tt*tt + 00122 ( p0*-1 + p1*3.0f - p2*3.0f + p3) * tt*tt*tt ) * 0.5f; 00123 return p; 00124 } 00125 } 00126 00131 void setPath(const std::vector<T>& path) { mPath = path; } 00132 00134 const std::vector<T>& path() const { return mPath; } 00135 00137 std::vector<T>& path() { return mPath; } 00138 00139 protected: 00140 std::vector<T> mPath; 00141 std::vector<T> mCatmullRomSpline; 00142 }; 00143 00144 typedef CatmullRomInterpolator<float> CatmullRomInterpolatorFloat_T; 00145 typedef CatmullRomInterpolator<vl::fvec2> CatmullRomInterpolatorFVec2_T; 00146 typedef CatmullRomInterpolator<vl::fvec3> CatmullRomInterpolatorFVec3_T; 00147 typedef CatmullRomInterpolator<vl::fvec4> CatmullRomInterpolatorFVec4_T; 00148 typedef CatmullRomInterpolator<double> CatmullRomInterpolatorDouble_T; 00149 typedef CatmullRomInterpolator<vl::dvec2> CatmullRomInterpolatorDVec2_T; 00150 typedef CatmullRomInterpolator<vl::dvec3> CatmullRomInterpolatorDVec3_T; 00151 typedef CatmullRomInterpolator<vl::dvec4> CatmullRomInterpolatorDVec4_T; 00152 00154 class CatmullRomInterpolatorFVec4: public vl::InterpolatorFVec4 00155 { 00156 public: 00157 CatmullRomInterpolatorFVec4(): mInterpolator( new CatmullRomInterpolatorFVec4_T ) {} 00158 CatmullRomInterpolatorFVec4(const std::vector<vl::fvec4>& path): mInterpolator( new CatmullRomInterpolatorFVec4_T(path) ) {} 00159 vl::fvec4 computePoint(float t) const { return interpolator()->computePoint(t); } 00160 CatmullRomInterpolatorFVec4_T* interpolator() { return mInterpolator.get(); } 00161 const CatmullRomInterpolatorFVec4_T* interpolator() const { return mInterpolator.get(); } 00162 void setInterpolator(CatmullRomInterpolatorFVec4_T* interpolator) { mInterpolator = interpolator; } 00163 protected: 00164 vl::ref<CatmullRomInterpolatorFVec4_T> mInterpolator; 00165 }; 00167 class CatmullRomInterpolatorFVec3: public vl::InterpolatorFVec3 00168 { 00169 public: 00170 CatmullRomInterpolatorFVec3(): mInterpolator( new CatmullRomInterpolatorFVec3_T ) {} 00171 CatmullRomInterpolatorFVec3(const std::vector<vl::fvec3>& path): mInterpolator( new CatmullRomInterpolatorFVec3_T(path) ) {} 00172 vl::fvec3 computePoint(float t) const { return interpolator()->computePoint(t); } 00173 CatmullRomInterpolatorFVec3_T* interpolator() { return mInterpolator.get(); } 00174 const CatmullRomInterpolatorFVec3_T* interpolator() const { return mInterpolator.get(); } 00175 void setInterpolator(CatmullRomInterpolatorFVec3_T* interpolator) { mInterpolator = interpolator; } 00176 protected: 00177 vl::ref<CatmullRomInterpolatorFVec3_T> mInterpolator; 00178 }; 00180 class CatmullRomInterpolatorFVec2: public vl::InterpolatorFVec2 00181 { 00182 public: 00183 CatmullRomInterpolatorFVec2(): mInterpolator( new CatmullRomInterpolatorFVec2_T ) {} 00184 CatmullRomInterpolatorFVec2(const std::vector<vl::fvec2>& path): mInterpolator( new CatmullRomInterpolatorFVec2_T(path) ) {} 00185 vl::fvec2 computePoint(float t) const { return interpolator()->computePoint(t); } 00186 CatmullRomInterpolatorFVec2_T* interpolator() { return mInterpolator.get(); } 00187 const CatmullRomInterpolatorFVec2_T* interpolator() const { return mInterpolator.get(); } 00188 void setInterpolator(CatmullRomInterpolatorFVec2_T* interpolator) { mInterpolator = interpolator; } 00189 protected: 00190 vl::ref<CatmullRomInterpolatorFVec2_T> mInterpolator; 00191 }; 00193 class CatmullRomInterpolatorFloat: public vl::InterpolatorFloat 00194 { 00195 public: 00196 CatmullRomInterpolatorFloat(): mInterpolator( new CatmullRomInterpolatorFloat_T ) {} 00197 CatmullRomInterpolatorFloat(const std::vector<float>& path): mInterpolator( new CatmullRomInterpolatorFloat_T(path) ) {} 00198 float computePoint(float t) const { return interpolator()->computePoint(t); } 00199 CatmullRomInterpolatorFloat_T* interpolator() { return mInterpolator.get(); } 00200 const CatmullRomInterpolatorFloat_T* interpolator() const { return mInterpolator.get(); } 00201 void setInterpolator(CatmullRomInterpolatorFloat_T* interpolator) { mInterpolator = interpolator; } 00202 protected: 00203 vl::ref<CatmullRomInterpolatorFloat_T> mInterpolator; 00204 }; 00206 class CatmullRomInterpolatorDVec4: public vl::InterpolatorDVec4 00207 { 00208 public: 00209 CatmullRomInterpolatorDVec4(): mInterpolator( new CatmullRomInterpolatorDVec4_T ) {} 00210 CatmullRomInterpolatorDVec4(const std::vector<vl::dvec4>& path): mInterpolator( new CatmullRomInterpolatorDVec4_T(path) ) {} 00211 vl::dvec4 computePoint(float t) const { return interpolator()->computePoint(t); } 00212 CatmullRomInterpolatorDVec4_T* interpolator() { return mInterpolator.get(); } 00213 const CatmullRomInterpolatorDVec4_T* interpolator() const { return mInterpolator.get(); } 00214 void setInterpolator(CatmullRomInterpolatorDVec4_T* interpolator) { mInterpolator = interpolator; } 00215 protected: 00216 vl::ref<CatmullRomInterpolatorDVec4_T> mInterpolator; 00217 }; 00219 class CatmullRomInterpolatorDVec3: public vl::InterpolatorDVec3 00220 { 00221 public: 00222 CatmullRomInterpolatorDVec3(): mInterpolator( new CatmullRomInterpolatorDVec3_T ) {} 00223 CatmullRomInterpolatorDVec3(const std::vector<vl::dvec3>& path): mInterpolator( new CatmullRomInterpolatorDVec3_T(path) ) {} 00224 vl::dvec3 computePoint(float t) const { return interpolator()->computePoint(t); } 00225 CatmullRomInterpolatorDVec3_T* interpolator() { return mInterpolator.get(); } 00226 const CatmullRomInterpolatorDVec3_T* interpolator() const { return mInterpolator.get(); } 00227 void setInterpolator(CatmullRomInterpolatorDVec3_T* interpolator) { mInterpolator = interpolator; } 00228 protected: 00229 vl::ref<CatmullRomInterpolatorDVec3_T> mInterpolator; 00230 }; 00232 class CatmullRomInterpolatorDVec2: public vl::InterpolatorDVec2 00233 { 00234 public: 00235 CatmullRomInterpolatorDVec2(): mInterpolator( new CatmullRomInterpolatorDVec2_T ) {} 00236 CatmullRomInterpolatorDVec2(const std::vector<vl::dvec2>& path): mInterpolator( new CatmullRomInterpolatorDVec2_T(path) ) {} 00237 vl::dvec2 computePoint(float t) const { return interpolator()->computePoint(t); } 00238 CatmullRomInterpolatorDVec2_T* interpolator() { return mInterpolator.get(); } 00239 const CatmullRomInterpolatorDVec2_T* interpolator() const { return mInterpolator.get(); } 00240 void setInterpolator(CatmullRomInterpolatorDVec2_T* interpolator) { mInterpolator = interpolator; } 00241 protected: 00242 vl::ref<CatmullRomInterpolatorDVec2_T> mInterpolator; 00243 }; 00245 class CatmullRomInterpolatorDouble: public vl::InterpolatorDouble 00246 { 00247 public: 00248 CatmullRomInterpolatorDouble(): mInterpolator( new CatmullRomInterpolatorDouble_T ) {} 00249 CatmullRomInterpolatorDouble(const std::vector<double>& path): mInterpolator( new CatmullRomInterpolatorDouble_T(path) ) {} 00250 double computePoint(float t) const { return interpolator()->computePoint(t); } 00251 CatmullRomInterpolatorDouble_T* interpolator() { return mInterpolator.get(); } 00252 const CatmullRomInterpolatorDouble_T* interpolator() const { return mInterpolator.get(); } 00253 void setInterpolator(CatmullRomInterpolatorDouble_T* interpolator) { mInterpolator = interpolator; } 00254 protected: 00255 vl::ref<CatmullRomInterpolatorDouble_T> mInterpolator; 00256 }; 00257 } 00258 00259 #endif