CudaBarycentricMapping.inl

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
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 } // namespace cuda
00070 
00071 } // namespace gpu
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     //data.in_index = cubeIndex;
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; // mapT must be recomputed
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& /*in*/)
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         // compute mapT
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                 //std::cout << "mapT["<<b<<"*"<<maxNOut*BSIZE<<"+"<<num<<"*"<<BSIZE<<"+"<<index<<"] = < "<<i<<", "<<f<<">"<<std::endl;
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& /*out*/, const Out::VecConst& /*in*/ )
00207 {
00208 }
00209 
00210 template<>
00211 void BarycentricMapperRegularGridTopology<CudaVec3fTypes,CudaVec3fTypes>::draw( const Out::VecCoord& /*out*/, const In::VecCoord& /*in*/)
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& /*out*/, const Out::VecConst& /*in*/ )
00247 {
00248 }
00249 
00250 template<>
00251 void BarycentricMapperRegularGridTopology<CudaVec3f1Types,CudaVec3f1Types>::draw( const Out::VecCoord& /*out*/, const In::VecCoord& /*in*/)
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& /*out*/, const Out::VecConst& /*in*/ )
00287 {
00288 }
00289 
00290 template<>
00291 void BarycentricMapperRegularGridTopology<CudaVec3f1Types,CudaVec3fTypes>::draw( const Out::VecCoord& /*out*/, const In::VecCoord& /*in*/)
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& /*out*/, const Out::VecConst& /*in*/ )
00326 {
00327 }
00328 
00329 template<>
00330 void BarycentricMapperRegularGridTopology<CudaVec3fTypes,CudaVec3f1Types>::draw( const Out::VecCoord& /*out*/, const In::VecCoord& /*in*/)
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         // copy old data
00352         map[b*maxNIn2+j]=map[b*maxNIn+j];
00353         // clear other data
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     // First project to plane
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()); // reserve space for mapping
00529     if (tetras.empty() && cubes.empty())
00530     { // no 3D elements -> map on 2D elements
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             //std::cout << "Tetra "<<t<<" center="<<centers[t]<<" base="<<m<<std::endl;
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         // compute mapT
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         //for (unsigned int i=0;i<mapT.size();i++)
00681         //    mapT[i] = std::make_pair(-1,0.0f);
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& /*out*/, const Out::VecConst& /*in*/ )
00733 {
00734 }
00735 
00736 template<>
00737 void BarycentricMapperMeshTopology<CudaVec3fTypes,CudaVec3fTypes>::draw( const Out::VecCoord& /*out*/, const In::VecCoord& /*in*/)
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& /*out*/, const Out::VecConst& /*in*/ )
00769 {
00770 }
00771 
00772 template<>
00773 void BarycentricMapperMeshTopology<CudaVec3f1Types,CudaVec3f1Types>::draw( const Out::VecCoord& /*out*/, const In::VecCoord& /*in*/)
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& /*out*/, const Out::VecConst& /*in*/ )
00806 {
00807 }
00808 
00809 template<>
00810 void BarycentricMapperMeshTopology<CudaVec3f1Types,CudaVec3fTypes>::draw( const Out::VecCoord& /*out*/, const In::VecCoord& /*in*/)
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& /*out*/, const Out::VecConst& /*in*/ )
00842 {
00843 }
00844 
00845 template<>
00846 void BarycentricMapperMeshTopology<CudaVec3fTypes,CudaVec3f1Types>::draw( const Out::VecCoord& /*out*/, const In::VecCoord& /*in*/)
00847 {
00848 }
00849 
00850 
00851 } // namespace mapping
00852 
00853 } // namespace component
00854 
00855 } // namespace sofa
00856 
00857 #endif

Generated on Sun Nov 23 03:57:23 2008 for Sofa by  doxygen 1.5.7.1