Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://visualizationlibrary.org */ 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 Transform_INCLUDE_ONCE 00033 #define Transform_INCLUDE_ONCE 00034 00035 #include <vlCore/vlnamespace.hpp> 00036 #include <vlCore/Object.hpp> 00037 #include <vlCore/Matrix4.hpp> 00038 #include <vector> 00039 #include <set> 00040 #include <algorithm> 00041 00042 namespace vl 00043 { 00044 class Camera; 00045 00046 //------------------------------------------------------------------------------ 00047 // Transform 00048 //------------------------------------------------------------------------------ 00072 class VLCORE_EXPORT Transform: public Object 00073 { 00074 VL_INSTRUMENT_CLASS(vl::Transform, Object) 00075 00076 public: 00078 Transform(): mWorldMatrixUpdateTick(0), mAssumeIdentityWorldMatrix(false), mParent(NULL) 00079 { 00080 VL_DEBUG_SET_OBJECT_NAME() 00081 00082 #if VL_TRANSFORM_USER_DATA 00083 mTransformUserData = NULL; 00084 #endif 00085 } 00086 00088 Transform(const mat4& matrix): mWorldMatrixUpdateTick(0), mAssumeIdentityWorldMatrix(false), mParent(NULL) 00089 { 00090 VL_DEBUG_SET_OBJECT_NAME() 00091 00092 #if VL_TRANSFORM_USER_DATA 00093 mTransformUserData = NULL; 00094 #endif 00095 00096 setLocalMatrix(matrix); 00097 setWorldMatrix(matrix); 00098 } 00099 00101 ~Transform(); 00102 00104 const Transform* parent() const { return mParent; } 00105 00107 Transform* parent() { return mParent; } 00108 00111 void translate(real x, real y, real z); 00112 00115 void translate(const vec3& t); 00116 00119 void scale(real x, real y, real z); 00120 00123 void rotate(real degrees, real x, real y, real z); 00124 00127 void rotate(const vec3& from, const vec3& to); 00128 00131 void preMultiply(const mat4& m); 00132 00135 void postMultiply(const mat4& m); 00136 00139 void setLocalMatrix(const mat4& m) 00140 { 00141 mLocalMatrix = m; 00142 } 00143 00145 const mat4& localMatrix() const 00146 { 00147 return mLocalMatrix; 00148 } 00149 00153 void setWorldMatrix(const mat4& matrix) 00154 { 00155 mWorldMatrix = matrix; 00156 ++mWorldMatrixUpdateTick; 00157 } 00158 00160 const mat4& worldMatrix() const 00161 { 00162 return mWorldMatrix; 00163 } 00164 00168 void setLocalAndWorldMatrix(const mat4& matrix) 00169 { 00170 mLocalMatrix = matrix; 00171 setWorldMatrix(matrix); 00172 } 00173 00176 long long worldMatrixUpdateTick() const { return mWorldMatrixUpdateTick; } 00177 00180 void setAssumeIdentityWorldMatrix(bool assume_I) { mAssumeIdentityWorldMatrix = assume_I; } 00181 00184 bool assumeIdentityWorldMatrix() { return mAssumeIdentityWorldMatrix; } 00185 00187 virtual void computeWorldMatrix(Camera* /*camera*/ = NULL) 00188 { 00189 if( assumeIdentityWorldMatrix() ) 00190 { 00191 setWorldMatrix(mat4()); 00192 } 00193 else 00194 /* top Transforms are usually assumeIdentityWorldMatrix() == true for performance reasons */ 00195 if( parent() && !parent()->assumeIdentityWorldMatrix() ) 00196 { 00197 setWorldMatrix( parent()->worldMatrix() * localMatrix() ); 00198 } 00199 else 00200 setWorldMatrix( localMatrix() ); 00201 } 00202 00204 void computeWorldMatrixRecursive(Camera* camera = NULL) 00205 { 00206 computeWorldMatrix(camera); 00207 for(size_t i=0; i<mChildren.size(); ++i) 00208 mChildren[i]->computeWorldMatrixRecursive(camera); 00209 } 00210 00212 mat4 getComputedWorldMatrix() 00213 { 00214 mat4 world = localMatrix(); 00215 Transform* par = parent(); 00216 while(par) 00217 { 00218 world = par->localMatrix() * world; 00219 par = par->parent(); 00220 } 00221 return world; 00222 } 00223 00224 // --- --- children management --- --- 00225 00227 const ref<Transform>* children() const { if (mChildren.empty()) return NULL; else return &mChildren[0]; } 00228 00230 ref<Transform>* children() { if (mChildren.empty()) return NULL; else return &mChildren[0]; } 00231 00233 size_t childrenCount() const { return mChildren.size(); } 00234 00236 void addChild(Transform* child) 00237 { 00238 VL_CHECK(child != NULL) 00239 VL_CHECK(child->mParent == NULL) 00240 00241 mChildren.push_back(child); 00242 child->mParent = this; 00243 } 00244 00246 void addChildren(Transform*const* children, size_t count) 00247 { 00248 VL_CHECK(children != NULL) 00249 00250 if (count) 00251 { 00252 size_t insert_point = mChildren.size(); 00253 mChildren.resize(mChildren.size() + count); 00254 vl::ref<Transform>* ptr = &mChildren[insert_point]; 00255 for(size_t i=0; i<count; ++i, ++ptr) 00256 { 00257 VL_CHECK(children[i]->mParent == NULL); 00258 children[i]->mParent = this; 00259 (*ptr) = children[i]; 00260 } 00261 } 00262 } 00263 00264 void addChildren(const ref<Transform>* children, size_t count) 00265 { 00266 VL_CHECK(children != NULL) 00267 00268 if (count) 00269 { 00270 size_t insert_point = mChildren.size(); 00271 mChildren.resize(mChildren.size() + count); 00272 vl::ref<Transform>* ptr = &mChildren[insert_point]; 00273 for(size_t i=0; i<count; ++i) 00274 { 00275 VL_CHECK(children[i]->mParent == NULL); 00276 ptr[i] = children[i]; 00277 ptr[i]->mParent = this; 00278 } 00279 } 00280 } 00281 00282 void addChildren(const std::vector< ref<Transform> >& children) 00283 { 00284 if (children.size()) 00285 addChildren( &children[0], children.size() ); 00286 } 00287 00289 void addChildren(const std::vector< Transform* >& children) 00290 { 00291 if (children.size()) 00292 addChildren( &children[0], children.size() ); 00293 } 00294 00296 void setChild(int index, Transform* child) 00297 { 00298 VL_CHECK(child) 00299 VL_CHECK( index < (int)mChildren.size() ) 00300 mChildren[index]->mParent = NULL; 00301 mChildren[index] = child; 00302 mChildren[index]->mParent = this; 00303 } 00304 00306 const Transform* lastChild() const { return mChildren.back().get(); } 00307 00309 Transform* lastChild() { return mChildren.back().get(); } 00310 00312 void eraseChild(const Transform* child) 00313 { 00314 VL_CHECK(child != NULL) 00315 std::vector< ref<Transform> >::iterator it; 00316 it = std::find(mChildren.begin(), mChildren.end(), child); 00317 VL_CHECK(it != mChildren.end()) 00318 if (it != mChildren.end()) 00319 { 00320 (*it)->mParent = NULL; 00321 mChildren.erase(it); 00322 } 00323 } 00324 00326 void eraseChildren(int index, int count) 00327 { 00328 VL_CHECK( index + count <= (int)mChildren.size() ); 00329 00330 for(int j=index; j<index+count; ++j) 00331 mChildren[j]->mParent = NULL; 00332 00333 for(int i=index+count, j=index; i<(int)mChildren.size(); ++i, ++j) 00334 mChildren[j] = mChildren[i]; 00335 00336 mChildren.resize( mChildren.size() - count ); 00337 } 00338 00340 void eraseAllChildren() 00341 { 00342 for(int i=0; i<(int)mChildren.size(); ++i) 00343 mChildren[i]->mParent = NULL; 00344 mChildren.clear(); 00345 } 00346 00348 void eraseAllChildrenRecursive() 00349 { 00350 for(int i=0; i<(int)mChildren.size(); ++i) 00351 { 00352 mChildren[i]->eraseAllChildrenRecursive(); 00353 mChildren[i]->mParent = NULL; 00354 } 00355 mChildren.clear(); 00356 } 00357 00359 void flattenHierarchy() 00360 { 00361 for(int i=0; i<(int)mChildren.size(); ++i) 00362 { 00363 mChildren[i]->setLocalAndWorldMatrix( mChildren[i]->worldMatrix() ); 00364 mChildren[i]->eraseAllChildrenRecursive(); 00365 mChildren[i]->mParent = NULL; 00366 } 00367 mChildren.clear(); 00368 } 00369 00371 void removeFromParent() 00372 { 00373 if (parent()) 00374 { 00375 mParent->eraseChild(this); 00376 setLocalMatrix( worldMatrix() ); 00377 } 00378 } 00379 00381 void shrink() 00382 { 00383 std::vector< ref<Transform> > tmp (mChildren); 00384 mChildren.swap(tmp); 00385 } 00386 00388 void shrinkRecursive() 00389 { 00390 shrink(); 00391 for(size_t i=0; i<mChildren.size(); ++i) 00392 mChildren[i]->shrinkRecursive(); 00393 } 00394 00399 void reserveChildren(size_t count) { mChildren.reserve(count); } 00400 00402 bool hasDuplicatedChildren() const 00403 { 00404 std::set<const Transform*> tr_set; 00405 for(size_t i=0; i<mChildren.size(); ++i) 00406 tr_set.insert( mChildren[i].get() ); 00407 return tr_set.size() != mChildren.size(); 00408 } 00409 00410 #if VL_TRANSFORM_USER_DATA 00411 public: 00412 void setTransformUserData(void* data) { mTransformUserData = data; } 00413 const void* transformUserData() const { return mTransformUserData; } 00414 void* transformUserData() { return mTransformUserData; } 00415 00416 private: 00417 void* mTransformUserData; 00418 #endif 00419 00420 protected: 00421 mat4 mLocalMatrix; 00422 mat4 mWorldMatrix; 00423 long long mWorldMatrixUpdateTick; 00424 bool mAssumeIdentityWorldMatrix; 00425 std::vector< ref<Transform> > mChildren; 00426 Transform* mParent; 00427 }; 00428 00429 } 00430 00431 #endif