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_CUDABARYCENTRICMAPPING_INL
00026 #define SOFA_GPU_CUDA_CUDABARYCENTRICMAPPING_INL
00027
00028 #include "CudaBarycentricMapping.h"
00029 #include <sofa/component/mapping/BarycentricMapping.inl>
00030
00031 namespace sofa
00032 {
00033
00034 namespace gpu
00035 {
00036
00037 namespace cuda
00038 {
00039
00040 extern "C"
00041 {
00042 void RegularGridMapperCuda3f_apply(unsigned int size, const unsigned int* gridsize, const void* map, void* out, const void* in);
00043 void RegularGridMapperCuda3f_applyJ(unsigned int size, const unsigned int* gridsize, const void* map, void* out, const void* in);
00044 void RegularGridMapperCuda3f_applyJT(unsigned int insize, unsigned int maxNOut, const unsigned int* gridsize, const void* mapT, void* out, const void* in);
00045
00046 void RegularGridMapperCuda3f1_apply(unsigned int size, const unsigned int* gridsize, const void* map, void* out, const void* in);
00047 void RegularGridMapperCuda3f1_applyJ(unsigned int size, const unsigned int* gridsize, const void* map, void* out, const void* in);
00048 void RegularGridMapperCuda3f1_applyJT(unsigned int insize, unsigned int maxNOut, const unsigned int* gridsize, const void* mapT, void* out, const void* in);
00049
00050 void RegularGridMapperCuda3f_3f1_apply(unsigned int size, const unsigned int* gridsize, const void* map, void* out, const void* in);
00051 void RegularGridMapperCuda3f_3f1_applyJ(unsigned int size, const unsigned int* gridsize, const void* map, void* out, const void* in);
00052 void RegularGridMapperCuda3f_3f1_applyJT(unsigned int insize, unsigned int maxNOut, const unsigned int* gridsize, const void* mapT, void* out, const void* in);
00053
00054 void RegularGridMapperCuda3f1_3f_apply(unsigned int size, const unsigned int* gridsize, const void* map, void* out, const void* in);
00055 void RegularGridMapperCuda3f1_3f_applyJ(unsigned int size, const unsigned int* gridsize, const void* map, void* out, const void* in);
00056 void RegularGridMapperCuda3f1_3f_applyJT(unsigned int insize, unsigned int maxNOut, const unsigned int* gridsize, const void* mapT, void* out, const void* in);
00057
00058 void MeshMapperCuda3f_apply(unsigned int size, unsigned int maxN, const void* map, void* out, const void* in);
00059 void MeshMapperCuda3f1_apply(unsigned int size, unsigned int maxN, const void* map, void* out, const void* in);
00060 void MeshMapperCuda3f_3f1_apply(unsigned int size, unsigned int maxN, const void* map, void* out, const void* in);
00061 void MeshMapperCuda3f1_3f_apply(unsigned int size, unsigned int maxN, const void* map, void* out, const void* in);
00062
00063 void MeshMapperCuda3f_applyPEq(unsigned int size, unsigned int maxN, const void* map, void* out, const void* in);
00064 void MeshMapperCuda3f1_applyPEq(unsigned int size, unsigned int maxN, const void* map, void* out, const void* in);
00065 void MeshMapperCuda3f_3f1_applyPEq(unsigned int size, unsigned int maxN, const void* map, void* out, const void* in);
00066 void MeshMapperCuda3f1_3f_applyPEq(unsigned int size, unsigned int maxN, const void* map, void* out, const void* in);
00067 }
00068
00069 }
00070
00071 }
00072
00073 namespace component
00074 {
00075
00076 namespace mapping
00077 {
00078
00079 using namespace gpu::cuda;
00080
00081
00085
00086
00087 template <typename VecIn, typename VecOut>
00088 void BarycentricMapperRegularGridTopology<gpu::cuda::CudaVectorTypes<VecIn,VecIn,float>, gpu::cuda::CudaVectorTypes<VecOut,VecOut,float> >::clear(int reserve)
00089 {
00090 map.clear();
00091 if (reserve>0) map.reserve(reserve);
00092 }
00093
00094 template <typename VecIn, typename VecOut>
00095 int BarycentricMapperRegularGridTopology<gpu::cuda::CudaVectorTypes<VecIn,VecIn,float>, gpu::cuda::CudaVectorTypes<VecOut,VecOut,float> >::addPointInCube(int cubeIndex, const Real* baryCoords)
00096 {
00097 map.resize(map.size()+1);
00098 CubeData& data = map[map.size()-1];
00099
00100 #ifdef SOFA_NEW_HEXA
00101 data.in_index = topology->getHexaCopy(cubeIndex)[0];
00102 #else
00103 data.in_index = topology->getCubeCopy(cubeIndex)[0];
00104 #endif
00105 data.baryCoords[0] = baryCoords[0];
00106 data.baryCoords[1] = baryCoords[1];
00107 data.baryCoords[2] = baryCoords[2];
00108 maxNOut = 0;
00109 return map.size()-1;
00110 }
00111
00112 template <typename VecIn, typename VecOut>
00113 void BarycentricMapperRegularGridTopology<gpu::cuda::CudaVectorTypes<VecIn,VecIn,float>, gpu::cuda::CudaVectorTypes<VecOut,VecOut,float> >::init(const typename Out::VecCoord& out, const typename In::VecCoord& )
00114 {
00115 int outside = 0;
00116
00117 clear(out.size());
00118 for (unsigned int i=0;i<out.size();i++)
00119 {
00120 Vector3 coefs;
00121 int cube = topology->findCube(Vector3(out[i]), coefs[0], coefs[1], coefs[2]);
00122 if (cube==-1)
00123 {
00124 ++outside;
00125 cube = topology->findNearestCube(Vector3(out[i]), coefs[0], coefs[1], coefs[2]);
00126 }
00127 Vec<3,Real> baryCoords = coefs;
00128 addPointInCube(cube, baryCoords.ptr());
00129 }
00130 }
00131
00132 template <typename VecIn, typename VecOut>
00133 void BarycentricMapperRegularGridTopology<gpu::cuda::CudaVectorTypes<VecIn,VecIn,float>, gpu::cuda::CudaVectorTypes<VecOut,VecOut,float> >::calcMapT()
00134 {
00135 if (!map.empty() && maxNOut == 0)
00136 {
00137 const unsigned int insize = topology->getNbPoints();
00138 const unsigned int gridsize[3] = { topology->getNx(), topology->getNy(), topology->getNz() };
00139
00140 const int nx = gridsize[0];
00141 const int nxny = gridsize[0]*gridsize[1];
00142 const int shift[8] = { 0, 1, nx, 1+nx, nxny, 1+nxny, nx+nxny, 1+nx+nxny };
00143 std::vector<int> nout(insize);
00144 for (unsigned int i=0;i<map.size();i++)
00145 {
00146 int index0 = map[i].in_index;
00147 for (int j=0;j<8;j++)
00148 nout[index0+shift[j]]++;
00149 }
00150 for (unsigned int i=0;i<insize;i++)
00151 if (nout[i] > maxNOut) maxNOut = nout[i];
00152 int nbloc = (insize+BSIZE-1)/BSIZE;
00153 std::cout << "CudaBarycentricMapping: mapT with "<<maxNOut<<" entries per DOF and "<<nbloc<<" blocs."<<std::endl;
00154 mapT.resize(nbloc*(BSIZE*maxNOut));
00155 for (unsigned int i=0;i<mapT.size();i++)
00156 mapT[i] = std::make_pair(-1,0.0f);
00157 nout.clear();
00158 nout.resize(insize);
00159 for (unsigned int i=0;i<map.size();i++)
00160 {
00161 int index0 = map[i].in_index;
00162 for (int j=0;j<8;j++)
00163 {
00164 int index = index0+shift[j];
00165 int num = nout[index]++;
00166 int b = (index / BSIZE); index -= b*BSIZE;
00167 float f;
00168 f = (j&1)?(map[i].baryCoords[0]):(1-map[i].baryCoords[0]);
00169 f *= (j&2)?(map[i].baryCoords[1]):(1-map[i].baryCoords[1]);
00170 f *= (j&4)?(map[i].baryCoords[2]):(1-map[i].baryCoords[2]);
00171
00172 mapT[(maxNOut*b+num)*BSIZE+index] = std::make_pair(i,f);
00173 }
00174 }
00175 }
00176 }
00177
00178 template<>
00179 void BarycentricMapperRegularGridTopology<CudaVec3fTypes,CudaVec3fTypes>::apply( Out::VecCoord& out, const In::VecCoord& in )
00180 {
00181 unsigned int gridsize[3] = { topology->getNx(), topology->getNy(), topology->getNz() };
00182 out.fastResize(map.size());
00183 RegularGridMapperCuda3f_apply(map.size(), gridsize, map.deviceRead(), out.deviceWrite(), in.deviceRead());
00184 }
00185
00186 template<>
00187 void BarycentricMapperRegularGridTopology<CudaVec3fTypes,CudaVec3fTypes>::applyJ( Out::VecDeriv& out, const In::VecDeriv& in )
00188 {
00189 unsigned int gridsize[3] = { topology->getNx(), topology->getNy(), topology->getNz() };
00190 out.fastResize(map.size());
00191 RegularGridMapperCuda3f_applyJ(map.size(), gridsize, map.deviceRead(), out.deviceWrite(), in.deviceRead());
00192 }
00193
00194 template<>
00195 void BarycentricMapperRegularGridTopology<CudaVec3fTypes,CudaVec3fTypes>::applyJT( In::VecDeriv& out, const Out::VecDeriv& in )
00196 {
00197 if (map.size() == 0) return;
00198 calcMapT();
00199 unsigned int gridsize[3] = { topology->getNx(), topology->getNy(), topology->getNz() };
00200 unsigned int insize = out.size();
00201
00202 RegularGridMapperCuda3f_applyJT(insize, maxNOut, gridsize, mapT.deviceRead(), out.deviceWrite(), in.deviceRead());
00203 }
00204
00205 template<>
00206 void BarycentricMapperRegularGridTopology<CudaVec3fTypes,CudaVec3fTypes>::applyJT( In::VecConst& , const Out::VecConst& )
00207 {
00208 }
00209
00210 template<>
00211 void BarycentricMapperRegularGridTopology<CudaVec3fTypes,CudaVec3fTypes>::draw( const Out::VecCoord& , const In::VecCoord& )
00212 {
00213 }
00214
00215
00216
00217
00218 template<>
00219 void BarycentricMapperRegularGridTopology<CudaVec3f1Types,CudaVec3f1Types>::apply( Out::VecCoord& out, const In::VecCoord& in )
00220 {
00221 unsigned int gridsize[3] = { topology->getNx(), topology->getNy(), topology->getNz() };
00222 out.fastResize(map.size());
00223 RegularGridMapperCuda3f1_apply(map.size(), gridsize, map.deviceRead(), out.deviceWrite(), in.deviceRead());
00224 }
00225
00226 template<>
00227 void BarycentricMapperRegularGridTopology<CudaVec3f1Types,CudaVec3f1Types>::applyJ( Out::VecDeriv& out, const In::VecDeriv& in )
00228 {
00229 unsigned int gridsize[3] = { topology->getNx(), topology->getNy(), topology->getNz() };
00230 out.fastResize(map.size());
00231 RegularGridMapperCuda3f1_applyJ(map.size(), gridsize, map.deviceRead(), out.deviceWrite(), in.deviceRead());
00232 }
00233
00234 template<>
00235 void BarycentricMapperRegularGridTopology<CudaVec3f1Types,CudaVec3f1Types>::applyJT( In::VecDeriv& out, const Out::VecDeriv& in )
00236 {
00237 calcMapT();
00238 if (map.size() == 0) return;
00239 unsigned int gridsize[3] = { topology->getNx(), topology->getNy(), topology->getNz() };
00240 unsigned int insize = out.size();
00241
00242 RegularGridMapperCuda3f1_applyJT(insize, maxNOut, gridsize, mapT.deviceRead(), out.deviceWrite(), in.deviceRead());
00243 }
00244
00245 template<>
00246 void BarycentricMapperRegularGridTopology<CudaVec3f1Types,CudaVec3f1Types>::applyJT( In::VecConst& , const Out::VecConst& )
00247 {
00248 }
00249
00250 template<>
00251 void BarycentricMapperRegularGridTopology<CudaVec3f1Types,CudaVec3f1Types>::draw( const Out::VecCoord& , const In::VecCoord& )
00252 {
00253 }
00254
00255
00256
00257
00258 template<>
00259 void BarycentricMapperRegularGridTopology<CudaVec3f1Types,CudaVec3fTypes>::apply( Out::VecCoord& out, const In::VecCoord& in )
00260 {
00261 unsigned int gridsize[3] = { topology->getNx(), topology->getNy(), topology->getNz() };
00262 out.fastResize(map.size());
00263 RegularGridMapperCuda3f1_3f_apply(map.size(), gridsize, map.deviceRead(), out.deviceWrite(), in.deviceRead());
00264 }
00265
00266 template<>
00267 void BarycentricMapperRegularGridTopology<CudaVec3f1Types,CudaVec3fTypes>::applyJ( Out::VecDeriv& out, const In::VecDeriv& in )
00268 {
00269 unsigned int gridsize[3] = { topology->getNx(), topology->getNy(), topology->getNz() };
00270 out.fastResize(map.size());
00271 RegularGridMapperCuda3f1_3f_applyJ(map.size(), gridsize, map.deviceRead(), out.deviceWrite(), in.deviceRead());
00272 }
00273
00274 template<>
00275 void BarycentricMapperRegularGridTopology<CudaVec3f1Types,CudaVec3fTypes>::applyJT( In::VecDeriv& out, const Out::VecDeriv& in )
00276 {
00277 calcMapT();
00278 if (map.size() == 0) return;
00279 unsigned int gridsize[3] = { topology->getNx(), topology->getNy(), topology->getNz() };
00280 unsigned int insize = out.size();
00281
00282 RegularGridMapperCuda3f1_3f_applyJT(insize, maxNOut, gridsize, mapT.deviceRead(), out.deviceWrite(), in.deviceRead());
00283 }
00284
00285 template<>
00286 void BarycentricMapperRegularGridTopology<CudaVec3f1Types,CudaVec3fTypes>::applyJT( In::VecConst& , const Out::VecConst& )
00287 {
00288 }
00289
00290 template<>
00291 void BarycentricMapperRegularGridTopology<CudaVec3f1Types,CudaVec3fTypes>::draw( const Out::VecCoord& , const In::VecCoord& )
00292 {
00293 }
00294
00295
00296
00297 template<>
00298 void BarycentricMapperRegularGridTopology<CudaVec3fTypes,CudaVec3f1Types>::apply( Out::VecCoord& out, const In::VecCoord& in )
00299 {
00300 unsigned int gridsize[3] = { topology->getNx(), topology->getNy(), topology->getNz() };
00301 out.fastResize(map.size());
00302 RegularGridMapperCuda3f_3f1_apply(map.size(), gridsize, map.deviceRead(), out.deviceWrite(), in.deviceRead());
00303 }
00304
00305 template<>
00306 void BarycentricMapperRegularGridTopology<CudaVec3fTypes,CudaVec3f1Types>::applyJ( Out::VecDeriv& out, const In::VecDeriv& in )
00307 {
00308 unsigned int gridsize[3] = { topology->getNx(), topology->getNy(), topology->getNz() };
00309 out.fastResize(map.size());
00310 RegularGridMapperCuda3f_3f1_applyJ(map.size(), gridsize, map.deviceRead(), out.deviceWrite(), in.deviceRead());
00311 }
00312
00313 template<>
00314 void BarycentricMapperRegularGridTopology<CudaVec3fTypes,CudaVec3f1Types>::applyJT( In::VecDeriv& out, const Out::VecDeriv& in )
00315 {
00316 calcMapT();
00317 if (map.size() == 0) return;
00318 unsigned int gridsize[3] = { topology->getNx(), topology->getNy(), topology->getNz() };
00319 unsigned int insize = out.size();
00320
00321 RegularGridMapperCuda3f_3f1_applyJT(insize, maxNOut, gridsize, mapT.deviceRead(), out.deviceWrite(), in.deviceRead());
00322 }
00323
00324 template<>
00325 void BarycentricMapperRegularGridTopology<CudaVec3fTypes,CudaVec3f1Types>::applyJT( In::VecConst& , const Out::VecConst& )
00326 {
00327 }
00328
00329 template<>
00330 void BarycentricMapperRegularGridTopology<CudaVec3fTypes,CudaVec3f1Types>::draw( const Out::VecCoord& , const In::VecCoord& )
00331 {
00332 }
00333
00334
00338
00339
00340 template <typename VecIn, typename VecOut>
00341 void BarycentricMapperMeshTopology<gpu::cuda::CudaVectorTypes<VecIn,VecIn,float>, gpu::cuda::CudaVectorTypes<VecOut,VecOut,float> >::resizeMap(int size2, int maxNIn2)
00342 {
00343 if (maxNIn2 < maxNIn) maxNIn2 = maxNIn;
00344 map.resize(((size2+BSIZE-1)/BSIZE)*maxNIn2);
00345 if (maxNIn2 > maxNIn)
00346 {
00347 int n = (size+BSIZE-1)/BSIZE;
00348 for (int b=n-1;b>0;--b)
00349 for (int j=maxNIn-1;j>=0;--j)
00350 {
00351
00352 map[b*maxNIn2+j]=map[b*maxNIn+j];
00353
00354 for (int i=0;i<BSIZE;++i)
00355 {
00356 map[b*maxNIn+j].d[i].i = 0;
00357 map[b*maxNIn+j].d[i].val = 0.0f;
00358 }
00359 }
00360 }
00361 size = size2;
00362 maxNIn = maxNIn2;
00363 }
00364
00365 template <typename VecIn, typename VecOut>
00366 void BarycentricMapperMeshTopology<gpu::cuda::CudaVectorTypes<VecIn,VecIn,float>, gpu::cuda::CudaVectorTypes<VecOut,VecOut,float> >::setMap(int outIndex, int j, int inIndex, Real val)
00367 {
00368 int b = outIndex / BSIZE;
00369 outIndex = outIndex % BSIZE;
00370 map[b*maxNIn+j].d[outIndex].i = inIndex+1;
00371 map[b*maxNIn+j].d[outIndex].val = val;
00372 }
00373
00374 template <typename VecIn, typename VecOut>
00375 void BarycentricMapperMeshTopology<gpu::cuda::CudaVectorTypes<VecIn,VecIn,float>, gpu::cuda::CudaVectorTypes<VecOut,VecOut,float> >::clear(int reserve)
00376 {
00377 map.clear(); if (reserve>0) map.reserve((reserve+BSIZE-1)/BSIZE*maxNIn);
00378 size = 0;
00379 }
00380
00381 template <typename VecIn, typename VecOut>
00382 int BarycentricMapperMeshTopology<gpu::cuda::CudaVectorTypes<VecIn,VecIn,float>, gpu::cuda::CudaVectorTypes<VecOut,VecOut,float> >::addPointInLine(int lineIndex, const SReal* baryCoords)
00383 {
00384 unsigned int i0 = size;
00385 resizeMap(i0+1,2);
00386 core::componentmodel::topology::BaseMeshTopology::Line e = topology->getLine(lineIndex);
00387 setMap(i0,0,e[0],(Real)(1-baryCoords[0]));
00388 setMap(i0,1,e[1],(Real)(baryCoords[0]));
00389 return i0;
00390 }
00391
00392 template <typename VecIn, typename VecOut>
00393 int BarycentricMapperMeshTopology<gpu::cuda::CudaVectorTypes<VecIn,VecIn,float>, gpu::cuda::CudaVectorTypes<VecOut,VecOut,float> >::addPointInTriangle(int triangleIndex, const SReal* baryCoords)
00394 {
00395 unsigned int i0 = size;
00396 resizeMap(i0+1,3);
00397 core::componentmodel::topology::BaseMeshTopology::Triangle e = topology->getTriangle(triangleIndex);
00398 setMap(i0,0,e[0],(Real)(1-baryCoords[0]-baryCoords[1]));
00399 setMap(i0,1,e[1],(Real)(baryCoords[0]));
00400 setMap(i0,2,e[2],(Real)(baryCoords[1]));
00401 return i0;
00402 }
00403
00404 template <typename VecIn, typename VecOut>
00405 int BarycentricMapperMeshTopology<gpu::cuda::CudaVectorTypes<VecIn,VecIn,float>, gpu::cuda::CudaVectorTypes<VecOut,VecOut,float> >::addPointInQuad(int quadIndex, const SReal* baryCoords)
00406 {
00407 unsigned int i0 = size;
00408 resizeMap(i0+1,4);
00409 core::componentmodel::topology::BaseMeshTopology::Quad e = topology->getQuad(quadIndex);
00410 setMap(i0,0,e[0],(Real)((1-baryCoords[0])*(1-baryCoords[1])));
00411 setMap(i0,1,e[1],(Real)(( baryCoords[0])*(1-baryCoords[1])));
00412 setMap(i0,2,e[3],(Real)((1-baryCoords[0])*( baryCoords[1])));
00413 setMap(i0,3,e[2],(Real)(( baryCoords[0])*( baryCoords[1])));
00414 return i0;
00415 }
00416
00417 template <typename VecIn, typename VecOut>
00418 int BarycentricMapperMeshTopology<gpu::cuda::CudaVectorTypes<VecIn,VecIn,float>, gpu::cuda::CudaVectorTypes<VecOut,VecOut,float> >::addPointInTetra(int tetraIndex, const SReal* baryCoords)
00419 {
00420 unsigned int i0 = size;
00421 resizeMap(i0+1,4);
00422 core::componentmodel::topology::BaseMeshTopology::Tetra e = topology->getTetra(tetraIndex);
00423 setMap(i0,0,e[0],(Real)(1-baryCoords[0]-baryCoords[1]-baryCoords[2]));
00424 setMap(i0,1,e[1],(Real)(baryCoords[0]));
00425 setMap(i0,2,e[2],(Real)(baryCoords[1]));
00426 setMap(i0,3,e[3],(Real)(baryCoords[2]));
00427 return i0;
00428 }
00429
00430 template <typename VecIn, typename VecOut>
00431 int BarycentricMapperMeshTopology<gpu::cuda::CudaVectorTypes<VecIn,VecIn,float>, gpu::cuda::CudaVectorTypes<VecOut,VecOut,float> >::addPointInCube(int cubeIndex, const SReal* baryCoords)
00432 {
00433 unsigned int i0 = size;
00434 resizeMap(i0+1,8);
00435 #ifdef SOFA_NEW_HEXA
00436 core::componentmodel::topology::BaseMeshTopology::Hexa e = topology->getHexa(cubeIndex);
00437 setMap(i0,0,e[0],(Real)((1-baryCoords[0])*(1-baryCoords[1])*(1-baryCoords[2])));
00438 setMap(i0,1,e[1],(Real)(( baryCoords[0])*(1-baryCoords[1])*(1-baryCoords[2])));
00439 setMap(i0,2,e[3],(Real)((1-baryCoords[0])*( baryCoords[1])*(1-baryCoords[2])));
00440 setMap(i0,3,e[2],(Real)(( baryCoords[0])*( baryCoords[1])*(1-baryCoords[2])));
00441 setMap(i0,4,e[4],(Real)((1-baryCoords[0])*(1-baryCoords[1])*( baryCoords[2])));
00442 setMap(i0,5,e[5],(Real)(( baryCoords[0])*(1-baryCoords[1])*( baryCoords[2])));
00443 setMap(i0,6,e[7],(Real)((1-baryCoords[0])*( baryCoords[1])*( baryCoords[2])));
00444 setMap(i0,7,e[6],(Real)(( baryCoords[0])*( baryCoords[1])*( baryCoords[2])));
00445 #else
00446 core::componentmodel::topology::BaseMeshTopology::Cube e = topology->getCube(cubeIndex);
00447 setMap(i0,0,e[0],(Real)((1-baryCoords[0])*(1-baryCoords[1])*(1-baryCoords[2])));
00448 setMap(i0,1,e[1],(Real)(( baryCoords[0])*(1-baryCoords[1])*(1-baryCoords[2])));
00449 setMap(i0,2,e[2],(Real)((1-baryCoords[0])*( baryCoords[1])*(1-baryCoords[2])));
00450 setMap(i0,3,e[3],(Real)(( baryCoords[0])*( baryCoords[1])*(1-baryCoords[2])));
00451 setMap(i0,4,e[4],(Real)((1-baryCoords[0])*(1-baryCoords[1])*( baryCoords[2])));
00452 setMap(i0,5,e[5],(Real)(( baryCoords[0])*(1-baryCoords[1])*( baryCoords[2])));
00453 setMap(i0,6,e[6],(Real)((1-baryCoords[0])*( baryCoords[1])*( baryCoords[2])));
00454 setMap(i0,7,e[7],(Real)(( baryCoords[0])*( baryCoords[1])*( baryCoords[2])));
00455 #endif
00456 return i0;
00457 }
00458
00459
00460 template <typename VecIn, typename VecOut>
00461 int BarycentricMapperMeshTopology<gpu::cuda::CudaVectorTypes<VecIn,VecIn,float>, gpu::cuda::CudaVectorTypes<VecOut,VecOut,float> >::createPointInLine(const typename Out::Coord& p, int lineIndex, const typename In::VecCoord* points)
00462 {
00463 SReal baryCoords[1];
00464 const topology::MeshTopology::Line& elem = topology->getLine(lineIndex);
00465 const typename In::Coord p0 = (*points)[elem[0]];
00466 const typename In::Coord pA = (*points)[elem[1]] - p0;
00467 typename In::Coord pos = p - p0;
00468 baryCoords[0] = ((pos*pA)/pA.norm2());
00469 return this->addPointInLine(lineIndex, baryCoords);
00470 }
00471
00472 template <typename VecIn, typename VecOut>
00473 int BarycentricMapperMeshTopology<gpu::cuda::CudaVectorTypes<VecIn,VecIn,float>, gpu::cuda::CudaVectorTypes<VecOut,VecOut,float> >::createPointInTriangle(const typename Out::Coord& p, int triangleIndex, const typename In::VecCoord* points)
00474 {
00475 SReal baryCoords[2];
00476 const topology::MeshTopology::Triangle& elem = topology->getTriangle(triangleIndex);
00477 const typename In::Coord p0 = (*points)[elem[0]];
00478 const typename In::Coord pA = (*points)[elem[1]] - p0;
00479 const typename In::Coord pB = (*points)[elem[2]] - p0;
00480 typename In::Coord pos = p - p0;
00481
00482 typename In::Coord normal = cross(pA, pB);
00483 Real norm2 = normal.norm2();
00484 pos -= normal*((pos*normal)/norm2);
00485 baryCoords[0] = (Real)sqrt(cross(pB, pos).norm2() / norm2);
00486 baryCoords[1] = (Real)sqrt(cross(pA, pos).norm2() / norm2);
00487 return this->addPointInTriangle(triangleIndex, baryCoords);
00488 }
00489
00490 template <typename VecIn, typename VecOut>
00491 int BarycentricMapperMeshTopology<gpu::cuda::CudaVectorTypes<VecIn,VecIn,float>, gpu::cuda::CudaVectorTypes<VecOut,VecOut,float> >::createPointInQuad(const typename Out::Coord& p, int quadIndex, const typename In::VecCoord* points)
00492 {
00493 SReal baryCoords[2];
00494 const topology::MeshTopology::Quad& elem = topology->getQuad(quadIndex);
00495 const typename In::Coord p0 = (*points)[elem[0]];
00496 const typename In::Coord pA = (*points)[elem[1]] - p0;
00497 const typename In::Coord pB = (*points)[elem[3]] - p0;
00498 typename In::Coord pos = p - p0;
00499 Mat<3,3,typename In::Real> m,mt,base;
00500 m[0] = pA;
00501 m[1] = pB;
00502 m[2] = cross(pA, pB);
00503 mt.transpose(m);
00504 base.invert(mt);
00505 const typename In::Coord base0 = base[0];
00506 const typename In::Coord base1 = base[1];
00507 baryCoords[0] = base0 * pos;
00508 baryCoords[1] = base1 * pos;
00509 return this->addPointInQuad(quadIndex, baryCoords);
00510 }
00511
00512
00513 template <typename VecIn, typename VecOut>
00514 void BarycentricMapperMeshTopology<gpu::cuda::CudaVectorTypes<VecIn,VecIn,float>, gpu::cuda::CudaVectorTypes<VecOut,VecOut,float> >::init(const typename Out::VecCoord& out, const typename In::VecCoord& in)
00515 {
00516 int outside = 0;
00517
00518 const topology::MeshTopology::SeqTetras& tetras = topology->getTetras();
00519 #ifdef SOFA_NEW_HEXA
00520 const topology::MeshTopology::SeqHexas& cubes = topology->getHexas();
00521 #else
00522 const topology::MeshTopology::SeqCubes& cubes = topology->getCubes();
00523 #endif
00524 const topology::MeshTopology::SeqTriangles& triangles = topology->getTriangles();
00525 const topology::MeshTopology::SeqQuads& quads = topology->getQuads();
00526 sofa::helper::vector<Matrix3> bases;
00527 sofa::helper::vector<Vector3> centers;
00528 clear(out.size());
00529 if (tetras.empty() && cubes.empty())
00530 {
00531 int c0 = triangles.size();
00532 bases.resize(triangles.size()+quads.size());
00533 centers.resize(triangles.size()+quads.size());
00534 for (unsigned int t = 0; t < triangles.size(); t++)
00535 {
00536 Mat3x3d m,mt;
00537 m[0] = in[triangles[t][1]]-in[triangles[t][0]];
00538 m[1] = in[triangles[t][2]]-in[triangles[t][0]];
00539 m[2] = cross(m[0],m[1]);
00540 mt.transpose(m);
00541 bases[t].invert(mt);
00542 centers[t] = (in[triangles[t][0]]+in[triangles[t][1]]+in[triangles[t][2]])/3;
00543 }
00544 for (unsigned int c = 0; c < quads.size(); c++)
00545 {
00546 Mat3x3d m,mt;
00547 m[0] = in[quads[c][1]]-in[quads[c][0]];
00548 m[1] = in[quads[c][3]]-in[quads[c][0]];
00549 m[2] = cross(m[0],m[1]);
00550 mt.transpose(m);
00551 bases[c0+c].invert(mt);
00552 centers[c0+c] = (in[quads[c][0]]+in[quads[c][1]]+in[quads[c][2]]+in[quads[c][3]])*0.25;
00553 }
00554 for (unsigned int i=0;i<out.size();i++)
00555 {
00556 Vector3 pos = out[i];
00557 Vector3 coefs;
00558 int index = -1;
00559 double distance = 1e10;
00560 for (unsigned int t = 0; t < triangles.size(); t++)
00561 {
00562 Vec3d v = bases[t] * (pos - in[triangles[t][0]]);
00563 double d = std::max(std::max(-v[0],-v[1]),std::max((v[2]<0?-v[2]:v[2])-0.01,v[0]+v[1]-1));
00564 if (d>0) d = (pos-centers[t]).norm2();
00565 if (d<distance) { coefs = v; distance = d; index = t; }
00566 }
00567 for (unsigned int c = 0; c < quads.size(); c++)
00568 {
00569 Vec3d v = bases[c0+c] * (pos - in[quads[c][0]]);
00570 double d = std::max(std::max(-v[0],-v[1]),std::max(std::max(v[1]-1,v[0]-1),std::max(v[2]-0.01,-v[2]-0.01)));
00571 if (d>0) d = (pos-centers[c0+c]).norm2();
00572 if (d<distance) { coefs = v; distance = d; index = c0+c; }
00573 }
00574 if (distance>0)
00575 {
00576 ++outside;
00577 }
00578 if (index < c0)
00579 addPointInTriangle(index, coefs.ptr());
00580 else
00581 addPointInQuad(index-c0, coefs.ptr());
00582 }
00583 }
00584 else
00585 {
00586 int c0 = tetras.size();
00587 bases.resize(tetras.size()+cubes.size());
00588 centers.resize(tetras.size()+cubes.size());
00589 for (unsigned int t = 0; t < tetras.size(); t++)
00590 {
00591 Mat3x3d m,mt;
00592 m[0] = in[tetras[t][1]]-in[tetras[t][0]];
00593 m[1] = in[tetras[t][2]]-in[tetras[t][0]];
00594 m[2] = in[tetras[t][3]]-in[tetras[t][0]];
00595 mt.transpose(m);
00596 bases[t].invert(mt);
00597 centers[t] = (in[tetras[t][0]]+in[tetras[t][1]]+in[tetras[t][2]]+in[tetras[t][3]])*0.25;
00598
00599 }
00600 for (unsigned int c = 0; c < cubes.size(); c++)
00601 {
00602 Mat3x3d m,mt;
00603 m[0] = in[cubes[c][1]]-in[cubes[c][0]];
00604 #ifdef SOFA_NEW_HEXA
00605 m[1] = in[cubes[c][3]]-in[cubes[c][0]];
00606 #else
00607 m[1] = in[cubes[c][2]]-in[cubes[c][0]];
00608 #endif
00609 m[2] = in[cubes[c][4]]-in[cubes[c][0]];
00610 mt.transpose(m);
00611 bases[c0+c].invert(mt);
00612 centers[c0+c] = (in[cubes[c][0]]+in[cubes[c][1]]+in[cubes[c][2]]+in[cubes[c][3]]+in[cubes[c][4]]+in[cubes[c][5]]+in[cubes[c][6]]+in[cubes[c][7]])*0.125;
00613 }
00614 for (unsigned int i=0;i<out.size();i++)
00615 {
00616 Vector3 pos = out[i];
00617 Vector3 coefs;
00618 int index = -1;
00619 double distance = 1e10;
00620 for (unsigned int t = 0; t < tetras.size(); t++)
00621 {
00622 Vector3 v = bases[t] * (pos - in[tetras[t][0]]);
00623 double d = std::max(std::max(-v[0],-v[1]),std::max(-v[2],v[0]+v[1]+v[2]-1));
00624 if (d>0) d = (pos-centers[t]).norm2();
00625 if (d<distance) { coefs = v; distance = d; index = t; }
00626 }
00627 for (unsigned int c = 0; c < cubes.size(); c++)
00628 {
00629 Vector3 v = bases[c0+c] * (pos - in[cubes[c][0]]);
00630 double d = std::max(std::max(-v[0],-v[1]),std::max(std::max(-v[2],v[0]-1),std::max(v[1]-1,v[2]-1)));
00631 if (d>0) d = (pos-centers[c0+c]).norm2();
00632 if (d<distance) { coefs = v; distance = d; index = c0+c; }
00633 }
00634 if (distance>0)
00635 {
00636 ++outside;
00637 }
00638 if (index < c0)
00639 addPointInTetra(index, coefs.ptr());
00640 else
00641 addPointInCube(index-c0, coefs.ptr());
00642 }
00643 }
00644 std::cout << "CUDA: BarycentricMapperMeshTopology: map initialized, "<<size<<" output points, max "<<maxNIn<<" inputs points per output, "<<map.size()*BSIZE<<" contributions total."<<std::endl;
00645 }
00646
00647
00648 template <typename VecIn, typename VecOut>
00649 void BarycentricMapperMeshTopology<gpu::cuda::CudaVectorTypes<VecIn,VecIn,float>, gpu::cuda::CudaVectorTypes<VecOut,VecOut,float> >::calcMapT()
00650 {
00651 if (size > 0 && maxNOut == 0)
00652 {
00653
00654 std::vector<int> nout;
00655 int nb = (size+BSIZE-1)/BSIZE;
00656 for (int b=0;b<nb;b++)
00657 {
00658 for (int j=0;j<maxNIn;j++)
00659 {
00660 int n = (b<nb-1) ? BSIZE : size-b*BSIZE;
00661 for (int i=0;i<n;i++)
00662 {
00663 int index = map[b*maxNIn+j].d[i].i-1;
00664 std::cout << "map["<<b<<"*"<<maxNIn<<"+"<<j<<"].index["<<i<<"]="<<index<<std::endl;
00665 if (index >= 0)
00666 {
00667 if ((unsigned)index >= nout.size()) nout.resize(index+1);
00668 nout[index]++;
00669 }
00670 }
00671 }
00672 }
00673 insize = nout.size();
00674 for (int i=0;i<insize;i++)
00675 if (nout[i] > maxNOut) maxNOut = nout[i];
00676 int nbloc = (insize+BSIZE-1)/BSIZE;
00677 std::cout << "CudaBarycentricMapping: mapT with "<<maxNOut<<" entries per DOF and "<<nbloc<<" blocs."<<std::endl;
00678 mapT.clear();
00679 mapT.resize(nbloc*maxNOut);
00680
00681
00682 nout.clear();
00683 nout.resize(insize);
00684 for (int b=0;b<nb;b++)
00685 {
00686 for (int j=0;j<maxNIn;j++)
00687 {
00688 int n = (b<nb-1) ? BSIZE : size-b*BSIZE;
00689 for (int i=0;i<n;i++)
00690 {
00691 int index = map[b*maxNIn+j].d[i].i-1;
00692 float val = (float) map[b*maxNIn+j].d[i].val;
00693 if (index >= 0)
00694 {
00695 int num = nout[index]++;
00696 int bo = (index / BSIZE); index -= b*BSIZE;
00697 mapT[bo*maxNOut+num].d[index].i = b*BSIZE+i;
00698 mapT[bo*maxNOut+num].d[index].val = val;
00699 }
00700 }
00701 }
00702 }
00703 }
00704 }
00705
00706
00707
00708
00709 template<>
00710 void BarycentricMapperMeshTopology<CudaVec3fTypes,CudaVec3fTypes>::apply( Out::VecCoord& out, const In::VecCoord& in )
00711 {
00712 out.fastResize(size);
00713 MeshMapperCuda3f_apply(size, maxNIn, map.deviceRead(), out.deviceWrite(), in.deviceRead());
00714 }
00715
00716 template<>
00717 void BarycentricMapperMeshTopology<CudaVec3fTypes,CudaVec3fTypes>::applyJ( Out::VecDeriv& out, const In::VecDeriv& in )
00718 {
00719 out.fastResize(size);
00720 MeshMapperCuda3f_apply(size, maxNIn, map.deviceRead(), out.deviceWrite(), in.deviceRead());
00721 }
00722
00723 template<>
00724 void BarycentricMapperMeshTopology<CudaVec3fTypes,CudaVec3fTypes>::applyJT( In::VecDeriv& out, const Out::VecDeriv& in )
00725 {
00726 if (size == 0) return;
00727 calcMapT();
00728 MeshMapperCuda3f_applyPEq(insize, maxNOut, mapT.deviceRead(), out.deviceWrite(), in.deviceRead());
00729 }
00730
00731 template<>
00732 void BarycentricMapperMeshTopology<CudaVec3fTypes,CudaVec3fTypes>::applyJT( In::VecConst& , const Out::VecConst& )
00733 {
00734 }
00735
00736 template<>
00737 void BarycentricMapperMeshTopology<CudaVec3fTypes,CudaVec3fTypes>::draw( const Out::VecCoord& , const In::VecCoord& )
00738 {
00739 }
00740
00741
00742
00743
00744
00745 template<>
00746 void BarycentricMapperMeshTopology<CudaVec3f1Types,CudaVec3f1Types>::apply( Out::VecCoord& out, const In::VecCoord& in )
00747 {
00748 out.fastResize(size);
00749 MeshMapperCuda3f1_apply(size, maxNIn, map.deviceRead(), out.deviceWrite(), in.deviceRead());
00750 }
00751
00752 template<>
00753 void BarycentricMapperMeshTopology<CudaVec3f1Types,CudaVec3f1Types>::applyJ( Out::VecDeriv& out, const In::VecDeriv& in )
00754 {
00755 out.fastResize(size);
00756 MeshMapperCuda3f1_apply(size, maxNIn, map.deviceRead(), out.deviceWrite(), in.deviceRead());
00757 }
00758
00759 template<>
00760 void BarycentricMapperMeshTopology<CudaVec3f1Types,CudaVec3f1Types>::applyJT( In::VecDeriv& out, const Out::VecDeriv& in )
00761 {
00762 if (size == 0) return;
00763 calcMapT();
00764 MeshMapperCuda3f1_applyPEq(insize, maxNOut, mapT.deviceRead(), out.deviceWrite(), in.deviceRead());
00765 }
00766
00767 template<>
00768 void BarycentricMapperMeshTopology<CudaVec3f1Types,CudaVec3f1Types>::applyJT( In::VecConst& , const Out::VecConst& )
00769 {
00770 }
00771
00772 template<>
00773 void BarycentricMapperMeshTopology<CudaVec3f1Types,CudaVec3f1Types>::draw( const Out::VecCoord& , const In::VecCoord& )
00774 {
00775 }
00776
00777
00778
00779
00780
00781
00782 template<>
00783 void BarycentricMapperMeshTopology<CudaVec3f1Types,CudaVec3fTypes>::apply( Out::VecCoord& out, const In::VecCoord& in )
00784 {
00785 out.fastResize(size);
00786 MeshMapperCuda3f1_3f_apply(size, maxNIn, map.deviceRead(), out.deviceWrite(), in.deviceRead());
00787 }
00788
00789 template<>
00790 void BarycentricMapperMeshTopology<CudaVec3f1Types,CudaVec3fTypes>::applyJ( Out::VecDeriv& out, const In::VecDeriv& in )
00791 {
00792 out.fastResize(size);
00793 MeshMapperCuda3f1_3f_apply(size, maxNIn, map.deviceRead(), out.deviceWrite(), in.deviceRead());
00794 }
00795
00796 template<>
00797 void BarycentricMapperMeshTopology<CudaVec3f1Types,CudaVec3fTypes>::applyJT( In::VecDeriv& out, const Out::VecDeriv& in )
00798 {
00799 if (size == 0) return;
00800 calcMapT();
00801 MeshMapperCuda3f_3f1_applyPEq(insize, maxNOut, mapT.deviceRead(), out.deviceWrite(), in.deviceRead());
00802 }
00803
00804 template<>
00805 void BarycentricMapperMeshTopology<CudaVec3f1Types,CudaVec3fTypes>::applyJT( In::VecConst& , const Out::VecConst& )
00806 {
00807 }
00808
00809 template<>
00810 void BarycentricMapperMeshTopology<CudaVec3f1Types,CudaVec3fTypes>::draw( const Out::VecCoord& , const In::VecCoord& )
00811 {
00812 }
00813
00814
00815
00816
00817
00818 template<>
00819 void BarycentricMapperMeshTopology<CudaVec3fTypes,CudaVec3f1Types>::apply( Out::VecCoord& out, const In::VecCoord& in )
00820 {
00821 out.fastResize(size);
00822 MeshMapperCuda3f_3f1_apply(size, maxNIn, map.deviceRead(), out.deviceWrite(), in.deviceRead());
00823 }
00824
00825 template<>
00826 void BarycentricMapperMeshTopology<CudaVec3fTypes,CudaVec3f1Types>::applyJ( Out::VecDeriv& out, const In::VecDeriv& in )
00827 {
00828 out.fastResize(size);
00829 MeshMapperCuda3f_3f1_apply(size, maxNIn, map.deviceRead(), out.deviceWrite(), in.deviceRead());
00830 }
00831
00832 template<>
00833 void BarycentricMapperMeshTopology<CudaVec3fTypes,CudaVec3f1Types>::applyJT( In::VecDeriv& out, const Out::VecDeriv& in )
00834 {
00835 if (size == 0) return;
00836 calcMapT();
00837 MeshMapperCuda3f1_3f_applyPEq(insize, maxNOut, mapT.deviceRead(), out.deviceWrite(), in.deviceRead());
00838 }
00839
00840 template<>
00841 void BarycentricMapperMeshTopology<CudaVec3fTypes,CudaVec3f1Types>::applyJT( In::VecConst& , const Out::VecConst& )
00842 {
00843 }
00844
00845 template<>
00846 void BarycentricMapperMeshTopology<CudaVec3fTypes,CudaVec3f1Types>::draw( const Out::VecCoord& , const In::VecCoord& )
00847 {
00848 }
00849
00850
00851 }
00852
00853 }
00854
00855 }
00856
00857 #endif