00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef SOFA_GPU_CUDA_CUDATYPES_H
00026 #define SOFA_GPU_CUDA_CUDATYPES_H
00027
00028
00029 #include "CudaCommon.h"
00030 #include "mycuda.h"
00031 #include <sofa/helper/system/gl.h>
00032 #include <sofa/defaulttype/Vec.h>
00033 #include <sofa/helper/vector.h>
00034
00035 #include <sofa/core/objectmodel/Base.h>
00036 #include <sofa/core/componentmodel/behavior/ForceField.h>
00037 #include <sofa/defaulttype/RigidTypes.h>
00038 #include <iostream>
00039
00040 namespace sofa
00041 {
00042
00043 namespace gpu
00044 {
00045
00046 namespace cuda
00047 {
00048
00049
00050 template<class T>
00051 class CudaVector
00052 {
00053 public:
00054 typedef T value_type;
00055 typedef size_t size_type;
00056
00057 protected:
00058 size_type vectorSize;
00059 size_type allocSize;
00060 mutable void* devicePointer;
00061 T* hostPointer;
00062 GLuint bufferObject;
00063 mutable bool deviceIsValid;
00064 mutable bool hostIsValid;
00065 mutable bool bufferIsRegistered;
00066
00067 public:
00068
00069 CudaVector()
00070 : vectorSize ( 0 ), allocSize ( 0 ), devicePointer ( NULL ), hostPointer ( NULL ), bufferObject ( 0 ), deviceIsValid ( true ), hostIsValid ( true ), bufferIsRegistered( false )
00071 {}
00072 CudaVector ( size_type n )
00073 : vectorSize ( 0 ), allocSize ( 0 ), devicePointer ( NULL ), hostPointer ( NULL ), bufferObject ( 0 ), deviceIsValid ( true ), hostIsValid ( true ), bufferIsRegistered( false )
00074 {
00075 resize ( n );
00076 }
00077 CudaVector ( const CudaVector<T>& v )
00078 : vectorSize ( 0 ), allocSize ( 0 ), devicePointer ( NULL ), hostPointer ( NULL ), bufferObject ( 0 ), deviceIsValid ( true ), hostIsValid ( true ), bufferIsRegistered( false )
00079 {
00080 *this = v;
00081 }
00082 void clear()
00083 {
00084 vectorSize = 0;
00085 deviceIsValid = true;
00086 hostIsValid = true;
00087 }
00088
00089 void operator= ( const CudaVector<T>& v )
00090 {
00091 if (&v == this)
00092 {
00093 std::cerr << "ERROR: self-assignment of CudaVector< " << core::objectmodel::Base::decodeTypeName(typeid(T)) << ">"<<std::endl;
00094 return;
00095 }
00096 size_type newSize = v.size();
00097 clear();
00098 fastResize ( newSize );
00099 deviceIsValid = v.deviceIsValid;
00100 hostIsValid = v.hostIsValid;
00101 if ( vectorSize > 0 && deviceIsValid )
00102 {
00103 if (bufferObject)
00104 mapBuffer();
00105 if (v.bufferObject)
00106 v.mapBuffer();
00107 mycudaMemcpyDeviceToDevice ( devicePointer, v.devicePointer, vectorSize*sizeof ( T ) );
00108 }
00109 if ( vectorSize!=0 && hostIsValid )
00110 std::copy ( v.hostPointer, v.hostPointer+vectorSize, hostPointer );
00111 }
00112 ~CudaVector()
00113 {
00114 if ( hostPointer!=NULL )
00115 mycudaFreeHost ( hostPointer );
00116 if ( bufferObject )
00117 {
00118 unregisterBuffer();
00119 glDeleteBuffers( 1, &bufferObject);
00120 }
00121 else
00122 {
00123 if ( devicePointer!=NULL )
00124 mycudaFree ( devicePointer );
00125 }
00126 }
00127 size_type size() const
00128 {
00129 return vectorSize;
00130 }
00131 bool empty() const
00132 {
00133 return vectorSize==0;
00134 }
00135 void reserve (size_type s,size_type WARP_SIZE=BSIZE)
00136 {
00137 if ( s <= allocSize ) return;
00138 allocSize = ( s>2*allocSize ) ?s:2*allocSize;
00139
00140 allocSize = ( allocSize+WARP_SIZE-1 ) &-WARP_SIZE;
00141
00142 if (bufferObject)
00143 {
00144 if (mycudaVerboseLevel>=LOG_INFO) std::cout << "CudaVector<"<<sofa::core::objectmodel::Base::className((T*)NULL)<<"> : GL reserve("<<s<<")"<<std::endl;
00145 hostRead();
00146 unregisterBuffer();
00147 glBindBuffer( GL_ARRAY_BUFFER, bufferObject);
00148 glBufferData( GL_ARRAY_BUFFER, allocSize*sizeof ( T ), 0, GL_DYNAMIC_DRAW);
00149 glBindBuffer( GL_ARRAY_BUFFER, 0);
00150 if ( vectorSize > 0 && deviceIsValid )
00151 deviceIsValid = false;
00152 }
00153 else
00154 {
00155 void* prevDevicePointer = devicePointer;
00156 if (mycudaVerboseLevel>=LOG_INFO) std::cout << "CudaVector<"<<sofa::core::objectmodel::Base::className((T*)NULL)<<"> : reserve("<<s<<")"<<std::endl;
00157 mycudaMalloc ( &devicePointer, allocSize*sizeof ( T ) );
00158 if ( vectorSize > 0 && deviceIsValid )
00159 mycudaMemcpyDeviceToDevice ( devicePointer, prevDevicePointer, vectorSize*sizeof ( T ) );
00160 if ( prevDevicePointer != NULL )
00161 mycudaFree ( prevDevicePointer );
00162 }
00163
00164 T* prevHostPointer = hostPointer;
00165 void* newHostPointer = NULL;
00166 mycudaMallocHost ( &newHostPointer, allocSize*sizeof ( T ) );
00167 hostPointer = (T*)newHostPointer;
00168 if ( vectorSize!=0 && hostIsValid )
00169 std::copy ( prevHostPointer, prevHostPointer+vectorSize, hostPointer );
00170 if ( prevHostPointer != NULL )
00171 mycudaFreeHost ( prevHostPointer );
00172 }
00174 void fastResize ( size_type s,size_type WARP_SIZE=BSIZE)
00175 {
00176 if ( s == vectorSize ) return;
00177 reserve ( s,WARP_SIZE);
00178 vectorSize = s;
00179 if ( !vectorSize )
00180 {
00181
00182 deviceIsValid = true;
00183 hostIsValid = true;
00184 }
00185 }
00186 void resize ( size_type s,size_type WARP_SIZE=BSIZE)
00187 {
00188 if ( s == vectorSize ) return;
00189 reserve ( s,WARP_SIZE);
00190 if ( s > vectorSize )
00191 {
00192 copyToHost();
00193 memset(hostPointer+vectorSize,0,(s-vectorSize)*sizeof(T));
00194
00195 for ( size_type i = vectorSize; i < s; i++ )
00196 {
00197 ::new ( hostPointer+i ) T;
00198 }
00199 if ( deviceIsValid )
00200 {
00201 if ( vectorSize == 0 )
00202 {
00203
00204 deviceIsValid = false;
00205 }
00206 else
00207 {
00208 if (bufferObject)
00209 mapBuffer();
00210 mycudaMemcpyHostToDevice ( ( ( T* ) devicePointer ) +vectorSize, hostPointer+vectorSize, ( s-vectorSize ) *sizeof ( T ) );
00211 }
00212 }
00213 }
00214 else if (s < vectorSize)
00215 {
00216 copyToHost();
00217
00218 for ( size_type i = s; i < vectorSize; i++ )
00219 {
00220 hostPointer[i].~T();
00221 }
00222 }
00223 vectorSize = s;
00224 if ( !vectorSize )
00225 {
00226
00227 deviceIsValid = true;
00228 hostIsValid = true;
00229 }
00230 }
00231 void swap ( CudaVector<T>& v )
00232 {
00233 #define VSWAP(type, var) { type t = var; var = v.var; v.var = t; }
00234 VSWAP ( size_type, vectorSize );
00235 VSWAP ( size_type, allocSize );
00236 VSWAP ( void* , devicePointer );
00237 VSWAP ( T* , hostPointer );
00238 VSWAP ( GLuint , bufferObject );
00239 VSWAP ( bool , deviceIsValid );
00240 VSWAP ( bool , hostIsValid );
00241 VSWAP ( bool , bufferIsRegistered );
00242 #undef VSWAP
00243 }
00244 const void* deviceRead ( int i=0 ) const
00245 {
00246 copyToDevice();
00247 return ( ( const T* ) devicePointer ) +i;
00248 }
00249 void* deviceWrite ( int i=0 )
00250 {
00251 copyToDevice();
00252 hostIsValid = false;
00253 return ( ( T* ) devicePointer ) +i;
00254 }
00255 const T* hostRead ( int i=0 ) const
00256 {
00257 copyToHost();
00258 return hostPointer+i;
00259 }
00260 T* hostWrite ( int i=0 )
00261 {
00262 copyToHost();
00263 deviceIsValid = false;
00264 return hostPointer+i;
00265 }
00266 bool isHostValid() const
00267 {
00268 return hostIsValid;
00269 }
00270 bool isDeviceValid() const
00271 {
00272 return deviceIsValid;
00273 }
00274
00276 GLuint bufferRead(bool create = false)
00277 {
00278 if (!bufferObject)
00279 {
00280 if (create)
00281 createBuffer();
00282 else
00283 return 0;
00284 }
00285 copyToDevice();
00286 return bufferObject;
00287 }
00288
00290 GLuint bufferWrite(bool create = false)
00291 {
00292 if (!bufferObject)
00293 {
00294 if (create)
00295 createBuffer();
00296 else
00297 return 0;
00298 }
00299 copyToDevice();
00300 unmapBuffer();
00301 hostIsValid = false;
00302 return bufferObject;
00303 }
00304
00305 void push_back ( const T& t )
00306 {
00307 size_type i = size();
00308 copyToHost();
00309 deviceIsValid = false;
00310 fastResize ( i+1 );
00311 ::new ( hostPointer+i ) T ( t );
00312 }
00313 void pop_back()
00314 {
00315 if ( !empty() )
00316 resize ( size()-1 );
00317 }
00318 const T& operator[] ( size_type i ) const
00319 {
00320 checkIndex ( i );
00321 return hostRead() [i];
00322 }
00323 T& operator[] ( size_type i )
00324 {
00325 checkIndex ( i );
00326 return hostWrite() [i];
00327 }
00328
00329 const T& getCached ( size_type i ) const
00330 {
00331 checkIndex ( i );
00332 return hostPointer[i];
00333 }
00334
00336 inline friend std::ostream& operator<< ( std::ostream& os, const CudaVector<T>& vec )
00337 {
00338 if ( vec.size() >0 )
00339 {
00340 for ( unsigned int i=0; i<vec.size()-1; ++i ) os<<vec[i]<<" ";
00341 os<<vec[vec.size()-1];
00342 }
00343 return os;
00344 }
00345
00347 inline friend std::istream& operator>> ( std::istream& in, CudaVector<T>& vec )
00348 {
00349 T t;
00350 vec.clear();
00351 while ( in>>t )
00352 {
00353 vec.push_back ( t );
00354 }
00355 if ( in.rdstate() & std::ios_base::eofbit ) { in.clear(); }
00356 return in;
00357 }
00358
00359 protected:
00360 void copyToHost() const
00361 {
00362 if ( hostIsValid ) return;
00363
00364 if (mycudaVerboseLevel>=LOG_TRACE)
00365 {
00366 std::cout << "CUDA: GPU->CPU copy of "<<sofa::core::objectmodel::Base::decodeTypeName ( typeid ( *this ) ) <<": "<<vectorSize*sizeof ( T ) <<" B"<<std::endl;
00367
00368 }
00369
00370 if (bufferObject)
00371 mapBuffer();
00372 mycudaMemcpyDeviceToHost ( hostPointer, devicePointer, vectorSize*sizeof ( T ) );
00373 hostIsValid = true;
00374 }
00375 void copyToDevice() const
00376 {
00377 if (bufferObject)
00378 mapBuffer();
00379 if ( deviceIsValid ) return;
00380
00381 if (mycudaVerboseLevel>=LOG_TRACE) std::cout << "CUDA: CPU->GPU copy of "<<sofa::core::objectmodel::Base::decodeTypeName ( typeid ( *this ) ) <<": "<<vectorSize*sizeof ( T ) <<" B"<<std::endl;
00382
00383 mycudaMemcpyHostToDevice ( devicePointer, hostPointer, vectorSize*sizeof ( T ) );
00384 deviceIsValid = true;
00385 }
00386 #ifdef NDEBUG
00387 void checkIndex ( size_type ) const
00388 {
00389 }
00390 #else
00391 void checkIndex ( size_type i ) const
00392 {
00393 assert ( i<this->size() );
00394 }
00395 #endif
00396 void registerBuffer() const
00397 {
00398 if (allocSize > 0 && !bufferIsRegistered)
00399 {
00400 mycudaGLRegisterBufferObject(bufferObject);
00401 bufferIsRegistered = true;
00402 }
00403 }
00404 void mapBuffer() const
00405 {
00406 registerBuffer();
00407 if (allocSize > 0 && devicePointer==NULL)
00408 {
00409 mycudaGLMapBufferObject(&devicePointer, bufferObject);
00410 }
00411 }
00412 void unmapBuffer() const
00413 {
00414 if (allocSize > 0 && devicePointer != NULL)
00415 {
00416 mycudaGLUnmapBufferObject(bufferObject);
00417 devicePointer = NULL;
00418 }
00419 }
00420 void unregisterBuffer() const
00421 {
00422 unmapBuffer();
00423 if (allocSize > 0 && bufferIsRegistered)
00424 {
00425 mycudaGLUnregisterBufferObject(bufferObject);
00426 bufferIsRegistered = false;
00427 }
00428 }
00429 void createBuffer()
00430 {
00431 if (bufferObject) return;
00432 glGenBuffers(1, &bufferObject);
00433 if (allocSize > 0)
00434 {
00435 glBindBuffer( GL_ARRAY_BUFFER, bufferObject);
00436 glBufferData( GL_ARRAY_BUFFER, allocSize*sizeof ( T ), 0, GL_DYNAMIC_DRAW);
00437 glBindBuffer( GL_ARRAY_BUFFER, 0);
00438 void* prevDevicePointer = devicePointer;
00439 devicePointer = NULL;
00440 if ( vectorSize > 0 && deviceIsValid )
00441 {
00442 mapBuffer();
00443 mycudaMemcpyDeviceToDevice ( devicePointer, prevDevicePointer, vectorSize*sizeof ( T ) );
00444 }
00445 if ( prevDevicePointer != NULL )
00446 mycudaFree ( prevDevicePointer );
00447 }
00448 }
00449 };
00450
00451 template<class T>
00452 class CudaMatrix
00453 {
00454 public:
00455 typedef T value_type;
00456 typedef size_t size_type;
00457
00458 protected:
00459 size_type sizeX;
00460 size_type sizeY;
00461 size_type pitch;
00462 size_type hostAllocSize;
00463 size_type deviceAllocSize;
00464 void* devicePointer;
00465 T* hostPointer;
00466 mutable bool deviceIsValid;
00467 mutable bool hostIsValid;
00468 public:
00469
00470 CudaMatrix()
00471 : sizeX ( 0 ), sizeY( 0 ), pitch(0), hostAllocSize ( 0 ), deviceAllocSize ( 0 ), devicePointer ( NULL ), hostPointer ( NULL ), deviceIsValid ( true ), hostIsValid ( true )
00472 {}
00473
00474 CudaMatrix(size_t x, size_t y )
00475 : sizeX ( 0 ), sizeY ( 0 ), pitch(0), hostAllocSize ( 0 ), deviceAllocSize ( 0 ), devicePointer ( NULL ), hostPointer ( NULL ), deviceIsValid ( true ), hostIsValid ( true ) {
00476 resize (x,y,0);
00477 }
00478
00479 CudaMatrix(const CudaMatrix<T>& v )
00480 : sizeX ( 0 ), sizeY ( 0 ), pitch(0), hostAllocSize ( 0 ), deviceAllocSize ( 0 ), devicePointer ( NULL ), hostPointer ( NULL ), deviceIsValid ( true ), hostIsValid ( true ) {
00481 *this = v;
00482 }
00483
00484 void clear() {
00485 sizeY = 0;
00486 sizeY = 0;
00487 pitch = 0;
00488 deviceIsValid = true;
00489 hostIsValid = true;
00490 }
00491
00492 ~CudaMatrix() {
00493 if (hostPointer!=NULL) mycudaFreeHost(hostPointer);
00494 if (devicePointer!=NULL) mycudaFree(devicePointer);
00495 }
00496
00497 size_type getSizeX() const {
00498 return sizeX;
00499 }
00500
00501 size_type getSizeY() const {
00502 return sizeY;
00503 }
00504
00505 size_type getPitch() const {
00506 return pitch;
00507 }
00508 bool empty() const {
00509 return sizeX==0 || sizeY==0;
00510 }
00511
00512 void fastResize(size_type x,size_type y,size_type WARP_SIZE=BSIZE) {
00513 size_type s = x*y;
00514
00515 if (s > hostAllocSize) {
00516 hostAllocSize = ( s>2*hostAllocSize ) ? s : 2*hostAllocSize;
00517
00518 hostAllocSize = ( hostAllocSize+WARP_SIZE-1 )/WARP_SIZE * WARP_SIZE;
00519 T* prevHostPointer = hostPointer;
00520
00521 if ( prevHostPointer != NULL ) mycudaFreeHost ( prevHostPointer );
00522 void* newHostPointer = NULL;
00523 mycudaMallocHost ( &newHostPointer, hostAllocSize*sizeof ( T ) );
00524 hostPointer = (T*)newHostPointer;
00525 }
00526
00527 if (WARP_SIZE==0) pitch = x*sizeof(T);
00528 else pitch = ((x+WARP_SIZE-1)/WARP_SIZE)*WARP_SIZE*sizeof(T);
00529 int ypitch;
00530 if (WARP_SIZE==0) ypitch = y;
00531 else ypitch = ((y+WARP_SIZE-1)/WARP_SIZE)*WARP_SIZE;
00532 if (ypitch*pitch > deviceAllocSize) {
00533 void* prevDevicePointer = devicePointer;
00534 if (prevDevicePointer != NULL ) mycudaFree ( prevDevicePointer );
00535
00536 mycudaMallocPitch(&devicePointer, &pitch, pitch, ypitch);
00537 deviceAllocSize = ypitch*pitch;
00538 }
00539
00540 sizeX = x;
00541 sizeY = y;
00542 deviceIsValid = true;
00543 hostIsValid = true;
00544 }
00545
00546 void resize (size_type x,size_type y,size_t WARP_SIZE=BSIZE) {
00547 fastResize(x,y,WARP_SIZE);
00548 }
00549
00550 void swap ( CudaMatrix<T>& v ) {
00551 #define VSWAP(type, var) { type t = var; var = v.var; v.var = t; }
00552 VSWAP ( size_type, sizeX );
00553 VSWAP ( size_type, sizeY );
00554 VSWAP ( size_type, pitch );
00555 VSWAP ( size_type, hostAllocSize );
00556 VSWAP ( size_type, deviceAllocSize );
00557 VSWAP ( void* , devicePointer );
00558 VSWAP ( T* , hostPointer );
00559 VSWAP ( bool , deviceIsValid );
00560 VSWAP ( bool , hostIsValid );
00561 #undef VSWAP
00562 }
00563
00564 const void* deviceRead ( int x=0, int y=0 ) const {
00565 copyToDevice();
00566 return (const T*)(( ( const char* ) devicePointer ) +(y*pitch+x*sizeof(T)));
00567 }
00568
00569 void* deviceWrite ( int x=0, int y=0 ) {
00570 copyToDevice();
00571 hostIsValid = false;
00572 return (T*)(( ( const char* ) devicePointer ) +(y*pitch+x*sizeof(T)));
00573 }
00574
00575 const T* hostRead ( int x=0, int y=0 ) const {
00576 copyToHost();
00577 return hostPointer+(y*sizeX+x);
00578 }
00579
00580 T* hostWrite ( int x=0, int y=0 ) {
00581 copyToHost();
00582 deviceIsValid = false;
00583 return hostPointer+(y*sizeX+x);
00584 }
00585
00586 bool isHostValid() const {
00587 return hostIsValid;
00588 }
00589
00590 bool isDeviceValid() const {
00591 return deviceIsValid;
00592 }
00593
00594 const T& operator() (size_type x,size_type y) const {
00595 checkIndex (x,y);
00596 return hostRead(x,y);
00597 }
00598
00599 T& operator() (size_type x,size_type y) {
00600 checkIndex (x,y);
00601 return hostWrite(x,y);
00602 }
00603
00604 const T* operator[] (size_type y) const {
00605 checkIndex (0,y);
00606 return hostRead(0,y);
00607 }
00608
00609 T* operator[] (size_type y) {
00610 checkIndex (0,y);
00611 return hostWrite(0,y);
00612 }
00613
00614 const T& getCached (size_type x,size_type y) const {
00615 checkIndex (x,y);
00616 return hostPointer[y*sizeX+x];
00617 }
00618
00619 protected:
00620 void copyToHost() const
00621 {
00622 if ( hostIsValid ) return;
00623
00624 if (mycudaVerboseLevel>=LOG_TRACE) std::cout << "CUDA: GPU->CPU copy of "<<sofa::core::objectmodel::Base::decodeTypeName ( typeid ( *this ) ) <<": "<<sizeX*sizeof(T) <<" B"<<std::endl;
00625
00626 mycudaMemcpyDeviceToHost2D ( hostPointer, sizeX*sizeof(T), devicePointer, pitch, sizeX*sizeof(T), sizeY);
00627 hostIsValid = true;
00628 }
00629 void copyToDevice() const
00630 {
00631 if ( deviceIsValid ) return;
00632
00633 if (mycudaVerboseLevel>=LOG_TRACE) std::cout << "CUDA: CPU->GPU copy of "<<sofa::core::objectmodel::Base::decodeTypeName ( typeid ( *this ) ) <<": "<<sizeX*sizeof(T) <<" B"<<std::endl;
00634
00635 mycudaMemcpyHostToDevice2D ( devicePointer, pitch, hostPointer, sizeX*sizeof(T), sizeX*sizeof(T), sizeY);
00636 deviceIsValid = true;
00637 }
00638
00639 #ifdef NDEBUG
00640 void checkIndex ( size_type,size_type ) const
00641 {
00642 }
00643 #else
00644 void checkIndex ( size_type x,size_type y) const
00645 {
00646 assert (x<this->sizeX);
00647 assert (y<this->sizeY);
00648 }
00649 #endif
00650
00651 };
00652
00653 template<class TCoord, class TDeriv, class TReal = typename TCoord::value_type>
00654 class CudaVectorTypes
00655 {
00656 public:
00657 typedef TCoord Coord;
00658 typedef TDeriv Deriv;
00659 typedef TReal Real;
00660 typedef CudaVector<Coord> VecCoord;
00661 typedef CudaVector<Deriv> VecDeriv;
00662 typedef CudaVector<Real> VecReal;
00663
00664 template <class T>
00665 class SparseData
00666 {
00667 public:
00668 SparseData ( unsigned int _index, const T& _data ) : index ( _index ), data ( _data ) {};
00669 unsigned int index;
00670 T data;
00671 };
00672
00673 typedef SparseData<Coord> SparseCoord;
00674 typedef SparseData<Deriv> SparseDeriv;
00675
00676 typedef CudaVector<SparseCoord> SparseVecCoord;
00677 typedef CudaVector<SparseDeriv> SparseVecDeriv;
00678
00680 typedef sofa::helper::vector<SparseVecDeriv> VecConst;
00681
00682 template<class C, typename T>
00683 static void set( C& c, T x, T y, T z )
00684 {
00685 if ( c.size() >0 )
00686 c[0] = (Real) x;
00687 if ( c.size() >1 )
00688 c[1] = (Real) y;
00689 if ( c.size() >2 )
00690 c[2] = (Real) z;
00691 }
00692
00693 template<class C, typename T>
00694 static void get( T& x, T& y, T& z, const C& c )
00695 {
00696 x = ( c.size() >0 ) ? (T) c[0] : (T) 0.0;
00697 y = ( c.size() >1 ) ? (T) c[1] : (T) 0.0;
00698 z = ( c.size() >2 ) ? (T) c[2] : (T) 0.0;
00699 }
00700
00701 template<class C, typename T>
00702 static void add( C& c, T x, T y, T z )
00703 {
00704 if ( c.size() >0 )
00705 c[0] += (Real) x;
00706 if ( c.size() >1 )
00707 c[1] += (Real) y;
00708 if ( c.size() >2 )
00709 c[2] += (Real) z;
00710 }
00711
00712 template<class C>
00713 static C interpolate(const helper::vector< C > & ancestors, const helper::vector< Real > & coefs)
00714 {
00715 assert(ancestors.size() == coefs.size());
00716
00717 C coord;
00718
00719 for (unsigned int i = 0; i < ancestors.size(); i++)
00720 {
00721 coord += ancestors[i] * coefs[i];
00722 }
00723
00724 return coord;
00725 }
00726
00727 static const char* Name();
00728 };
00729
00730 typedef sofa::defaulttype::Vec3f Vec3f;
00731 typedef sofa::defaulttype::Vec2f Vec2f;
00732
00733 using defaulttype::Vec;
00734 using defaulttype::NoInit;
00735 using defaulttype::NOINIT;
00736
00737 template<class Real>
00738 class Vec3r1 : public sofa::defaulttype::Vec<3,Real>
00739 {
00740 public:
00741 typedef sofa::defaulttype::Vec<3,Real> Inherit;
00742 typedef Real real;
00743 enum { N=3 };
00744 Vec3r1() : dummy(0.0f) {}
00745 template<class real2>
00746 Vec3r1(const Vec<N,real2>& v): Inherit(v), dummy(0.0f) {}
00747 Vec3r1(float x, float y, float z) : Inherit(x,y,z), dummy(0.0f) {}
00748
00750 explicit Vec3r1(NoInit n) : Inherit(n), dummy(0.0f)
00751 {
00752 }
00753
00754
00755
00757 template<class real2>
00758 Vec3r1 operator*(real2 f) const
00759 {
00760 Vec3r1 r(NOINIT);
00761 for (int i=0;i<N;i++)
00762 r[i] = this->elems[i]*(real)f;
00763 return r;
00764 }
00765
00767 template<class real2>
00768 void operator*=(real2 f)
00769 {
00770 for (int i=0;i<N;i++)
00771 this->elems[i]*=(real)f;
00772 }
00773
00774 template<class real2>
00775 Vec3r1 operator/(real2 f) const
00776 {
00777 Vec3r1 r(NOINIT);
00778 for (int i=0;i<N;i++)
00779 r[i] = this->elems[i]/(real)f;
00780 return r;
00781 }
00782
00784 template<class real2>
00785 void operator/=(real2 f)
00786 {
00787 for (int i=0;i<N;i++)
00788 this->elems[i]/=(real)f;
00789 }
00790
00792 template<class real2>
00793 real operator*(const Vec<N,real2>& v) const
00794 {
00795 real r = (real)(this->elems[0]*v[0]);
00796 for (int i=1;i<N;i++)
00797 r += (real)(this->elems[i]*v[i]);
00798 return r;
00799 }
00800
00802 real operator*(const Vec3r1& v) const
00803 {
00804 real r = (real)(this->elems[0]*v[0]);
00805 for (int i=1;i<N;i++)
00806 r += (real)(this->elems[i]*v[i]);
00807 return r;
00808 }
00809
00811 template<class real2>
00812 Vec3r1 linearProduct(const Vec<N,real2>& v) const
00813 {
00814 Vec3r1 r(NOINIT);
00815 for (int i=0;i<N;i++)
00816 r[i]=this->elems[i]*(real)v[i];
00817 return r;
00818 }
00819
00821 Vec3r1 linearProduct(const Vec3r1& v) const
00822 {
00823 Vec3r1 r(NOINIT);
00824 for (int i=0;i<N;i++)
00825 r[i]=this->elems[i]*(real)v[i];
00826 return r;
00827 }
00828
00830 template<class real2>
00831 Vec3r1 operator+(const Vec<N,real2>& v) const
00832 {
00833 Vec3r1 r(NOINIT);
00834 for (int i=0;i<N;i++)
00835 r[i]=this->elems[i]+(real)v[i];
00836 return r;
00837 }
00838
00840 Vec3r1 operator+(const Vec3r1& v) const
00841 {
00842 Vec3r1 r(NOINIT);
00843 for (int i=0;i<N;i++)
00844 r[i]=this->elems[i]+(real)v[i];
00845 return r;
00846 }
00847
00849 template<class real2>
00850 void operator+=(const Vec<N,real2>& v)
00851 {
00852 for (int i=0;i<N;i++)
00853 this->elems[i]+=(real)v[i];
00854 }
00855
00857 void operator+=(const Vec3r1& v)
00858 {
00859 for (int i=0;i<N;i++)
00860 this->elems[i]+=(real)v[i];
00861 }
00862
00864 template<class real2>
00865 Vec3r1 operator-(const Vec<N,real2>& v) const
00866 {
00867 Vec3r1 r(NOINIT);
00868 for (int i=0;i<N;i++)
00869 r[i]=this->elems[i]-(real)v[i];
00870 return r;
00871 }
00872
00874 Vec3r1 operator-(const Vec3r1& v) const
00875 {
00876 Vec3r1 r(NOINIT);
00877 for (int i=0;i<N;i++)
00878 r[i]=this->elems[i]-(real)v[i];
00879 return r;
00880 }
00881
00883 template<class real2>
00884 void operator-=(const Vec<N,real2>& v)
00885 {
00886 for (int i=0;i<N;i++)
00887 this->elems[i]-=(real)v[i];
00888 }
00889
00891 void operator-=(const Vec3r1& v)
00892 {
00893 for (int i=0;i<N;i++)
00894 this->elems[i]-=(real)v[i];
00895 }
00896
00898 Vec3r1 operator-() const
00899 {
00900 Vec3r1 r(NOINIT);
00901 for (int i=0;i<N;i++)
00902 r[i]=-this->elems[i];
00903 return r;
00904 }
00905
00906 Vec3r1 cross( const Vec3r1& b ) const
00907 {
00908 BOOST_STATIC_ASSERT(N == 3);
00909 return Vec3r1(
00910 (*this)[1]*b[2] - (*this)[2]*b[1],
00911 (*this)[2]*b[0] - (*this)[0]*b[2],
00912 (*this)[0]*b[1] - (*this)[1]*b[0]
00913 );
00914 }
00915
00916 protected:
00917 float dummy;
00918 };
00919
00920 typedef Vec3r1<float> Vec3f1;
00921
00922 typedef CudaVectorTypes<Vec3f,Vec3f,float> CudaVec3fTypes;
00923 typedef CudaVec3fTypes CudaVec3Types;
00924
00925 template<>
00926 inline const char* CudaVec3fTypes::Name()
00927 {
00928 return "CudaVec3f";
00929 }
00930
00931 typedef CudaVectorTypes<Vec2f,Vec2f,float> CudaVec2fTypes;
00932 typedef CudaVec2fTypes CudaVec2Types;
00933
00934 template<>
00935 inline const char* CudaVec2fTypes::Name()
00936 {
00937 return "CudaVec2f";
00938 }
00939
00940 typedef CudaVectorTypes<Vec3f1,Vec3f1,float> CudaVec3f1Types;
00941
00942 template<>
00943 inline const char* CudaVec3f1Types::Name()
00944 {
00945 return "CudaVec3f1";
00946 }
00947
00948 template<int N, typename real>
00949 class CudaRigidTypes;
00950
00951 template<typename real>
00952 class CudaRigidTypes<3, real>
00953 {
00954 public:
00955 typedef real Real;
00956 typedef sofa::defaulttype::RigidCoord<3,real> Coord;
00957 typedef sofa::defaulttype::RigidDeriv<3,real> Deriv;
00958 typedef typename Coord::Vec3 Vec3;
00959 typedef typename Coord::Quat Quat;
00960 typedef CudaVector<Coord> VecCoord;
00961 typedef CudaVector<Deriv> VecDeriv;
00962 typedef CudaVector<Real> VecReal;
00963
00964 template <class T>
00965 class SparseData
00966 {
00967 public:
00968 SparseData ( unsigned int _index, const T& _data ) : index ( _index ), data ( _data ) {};
00969 unsigned int index;
00970 T data;
00971 };
00972
00973 typedef SparseData<Coord> SparseCoord;
00974 typedef SparseData<Deriv> SparseDeriv;
00975
00976 typedef CudaVector<SparseCoord> SparseVecCoord;
00977 typedef CudaVector<SparseDeriv> SparseVecDeriv;
00978
00980 typedef sofa::helper::vector<SparseVecDeriv> VecConst;
00981
00982 template<typename T>
00983 static void set(Coord& r, T x, T y, T z)
00984 {
00985 Vec3& c = r.getCenter();
00986 if ( c.size() >0 )
00987 c[0] = (Real) x;
00988 if ( c.size() >1 )
00989 c[1] = (Real) y;
00990 if ( c.size() >2 )
00991 c[2] = (Real) z;
00992 }
00993
00994 template<typename T>
00995 static void get(T& x, T& y, T& z, const Coord& r)
00996 {
00997 const Vec3& c = r.getCenter();
00998 x = ( c.size() >0 ) ? (T) c[0] : (T) 0.0;
00999 y = ( c.size() >1 ) ? (T) c[1] : (T) 0.0;
01000 z = ( c.size() >2 ) ? (T) c[2] : (T) 0.0;
01001 }
01002
01003 template<typename T>
01004 static void add(Coord& r, T x, T y, T z)
01005 {
01006 Vec3& c = r.getCenter();
01007 if ( c.size() >0 )
01008 c[0] += (Real) x;
01009 if ( c.size() >1 )
01010 c[1] += (Real) y;
01011 if ( c.size() >2 )
01012 c[2] += (Real) z;
01013 }
01014
01015 template<typename T>
01016 static void set(Deriv& r, T x, T y, T z)
01017 {
01018 Vec3& c = r.getVCenter();
01019 if ( c.size() >0 )
01020 c[0] = (Real) x;
01021 if ( c.size() >1 )
01022 c[1] = (Real) y;
01023 if ( c.size() >2 )
01024 c[2] = (Real) z;
01025 }
01026
01027 template<typename T>
01028 static void get(T& x, T& y, T& z, const Deriv& r)
01029 {
01030 const Vec3& c = r.getVCenter();
01031 x = ( c.size() >0 ) ? (T) c[0] : (T) 0.0;
01032 y = ( c.size() >1 ) ? (T) c[1] : (T) 0.0;
01033 z = ( c.size() >2 ) ? (T) c[2] : (T) 0.0;
01034 }
01035
01036 template<typename T>
01037 static void add(Deriv& r, T x, T y, T z)
01038 {
01039 Vec3& c = r.getVCenter();
01040 if ( c.size() >0 )
01041 c[0] += (Real) x;
01042 if ( c.size() >1 )
01043 c[1] += (Real) y;
01044 if ( c.size() >2 )
01045 c[2] += (Real) z;
01046 }
01047
01048 static Coord interpolate(const helper::vector< Coord > & ancestors, const helper::vector< Real > & coefs)
01049 {
01050 assert(ancestors.size() == coefs.size());
01051
01052 Coord c;
01053
01054 for (unsigned int i = 0; i < ancestors.size(); i++)
01055 {
01056
01057 c.getCenter() += ancestors[i].getCenter() * coefs[i];
01058
01059
01060 helper::Quater<Real> q = ancestors[i].getOrientation();
01061 Real angle = acos(q[3]) * 2;
01062
01063
01064 defaulttype::Vec<3,Real> v(q[0], q[1], q[2]);
01065 Real norm = v.norm();
01066 if (norm > 0.0005)
01067 {
01068 v.normalize();
01069
01070
01071 angle *= coefs[i];
01072
01073
01074 q.axisToQuat(v, angle);
01075 q.normalize();
01076
01077 c.getOrientation() += q;
01078 }
01079 }
01080
01081 c.getOrientation().normalize();
01082
01083 return c;
01084 }
01085
01086 static Deriv interpolate(const helper::vector< Deriv > & ancestors, const helper::vector< Real > & coefs)
01087 {
01088 assert(ancestors.size() == coefs.size());
01089
01090 Deriv d;
01091
01092 for (unsigned int i = 0; i < ancestors.size(); i++)
01093 {
01094 d += ancestors[i] * coefs[i];
01095 }
01096
01097 return d;
01098 }
01099
01100 static const char* Name();
01101 };
01102
01103 typedef CudaRigidTypes<3,float> CudaRigid3fTypes;
01104 typedef CudaRigid3fTypes CudaRigid3Types;
01105
01106 template<>
01107 inline const char* CudaRigid3fTypes::Name()
01108 {
01109 return "CudaRigid3f";
01110 }
01111
01112
01113 }
01114
01115 }
01116
01117 }
01118
01119 #endif