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_CUDAPENALITYCONTACTFORCEFIELD_INL
00026 #define SOFA_GPU_CUDA_CUDAPENALITYCONTACTFORCEFIELD_INL
00027
00028 #include "CudaPenalityContactForceField.h"
00029 #include <sofa/component/forcefield/PenalityContactForceField.inl>
00030
00031
00032 namespace sofa
00033 {
00034
00035 namespace gpu
00036 {
00037
00038 namespace cuda
00039 {
00040
00041 extern "C"
00042 {
00043 void PenalityContactForceFieldCuda3f_setContacts(unsigned int size, unsigned int nbTests, unsigned int maxPoints, const void* tests, const void* outputs, void* contacts, float d0, float stiffness, defaulttype::Mat3x3f xform);
00044 void PenalityContactForceFieldCuda3f_addForce(unsigned int size, const void* contacts, void* penetration, void* f1, const void* x1, const void* v1, void* f2, const void* x2, const void* v2);
00045 void PenalityContactForceFieldCuda3f_addDForce(unsigned int size, const void* contacts, const void* penetration, void* f1, const void* dx1, void* f2, const void* dx2, double factor);
00046 }
00047
00048 }
00049
00050 }
00051
00052 namespace component
00053 {
00054
00055 namespace forcefield
00056 {
00057
00058 using namespace gpu::cuda;
00059
00060
00061 void PenalityContactForceField<CudaVec3fTypes>::clear(int reserve)
00062 {
00063
00064 contacts.clear();
00065 pen.clear();
00066 if (reserve)
00067 {
00068 contacts.reserve(reserve);
00069 pen.reserve(reserve);
00070 }
00071 }
00072
00073
00074 void PenalityContactForceField<CudaVec3fTypes>::addContact(int , int , const Deriv& norm, Real dist, Real ks, Real , Real , int )
00075 {
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 sofa::defaulttype::Vec4f c(norm, dist);
00098 Real fact = helper::rsqrt(ks);
00099 c *= fact;
00100 contacts.push_back(c);
00101 pen.push_back(0);
00102 }
00103
00104 void PenalityContactForceField<CudaVec3fTypes>::setContacts(Real d0, Real stiffness, sofa::core::componentmodel::collision::GPUDetectionOutputVector* outputs, bool useDistance, defaulttype::Mat3x3f* normXForm)
00105 {
00106 #if 1
00107 int n = outputs->size();
00108 contacts.fastResize(n);
00109 pen.fastResize(n);
00110 if (!n) return;
00111 for (int i=0;i<n;i++)
00112 {
00113 const sofa::core::componentmodel::collision::GPUDetectionOutput* o = outputs->get(i);
00114 Real distance = (useDistance) ? d0 + o->distance : d0;
00115 Real ks = (distance > 1.0e-10) ? stiffness / distance : stiffness;
00116 Coord n = (normXForm)?(*normXForm)*o->normal : o->normal;
00117 defaulttype::Vec4f c(n, distance);
00118 c *= helper::rsqrt(ks);
00119 contacts[i] = c;
00120 pen[i] = 0;
00121 }
00122 #else
00123 int n = outputs->size();
00124 int nt = outputs->nbTests();
00125 int maxp = 0;
00126 for (int i=0;i<nt;i++)
00127 if (outputs->rtest(i).curSize > maxp) maxp = outputs->rtest(i).curSize;
00128 contacts.fastResize(n);
00129 pen.fastResize(n);
00130 defaulttype::Mat3x3f xform;
00131 if (normXForm) xform = *normXForm; else xform.identity();
00132 PenalityContactForceFieldCuda3f_setContacts(n, nt, maxp, outputs->tests.deviceRead(), outputs->results.deviceRead(), contacts.deviceWrite(), d0, stiffness, xform);
00133 #endif
00134 }
00135
00136
00137 void PenalityContactForceField<CudaVec3fTypes>::addForce(VecDeriv& f1, VecDeriv& f2, const VecCoord& x1, const VecCoord& x2, const VecDeriv& v1, const VecDeriv& v2)
00138 {
00139 pen.resize(contacts.size());
00140 f1.resize(x1.size());
00141 f2.resize(x2.size());
00142 #if 0
00143 for (unsigned int i=0; i<contacts.size(); i++)
00144 {
00145 sofa::defaulttype::Vec4f c = contacts[i];
00146
00147 Coord u = x2[i]-x1[i];
00148 Coord norm(c[0],c[1],c[2]);
00149
00150 Real p = c[3] - u*norm;
00151 pen[i] = p;
00152 if (p > 0)
00153 {
00154
00155 Deriv force = -norm*p;
00156 f1[i]+=force;
00157 f2[i]-=force;
00158 }
00159 }
00160 #else
00161 PenalityContactForceFieldCuda3f_addForce(contacts.size(), contacts.deviceRead(), pen.deviceWrite(),
00162 f1.deviceWrite(), x1.deviceRead(), v1.deviceRead(),
00163 f2.deviceWrite(), x2.deviceRead(), v2.deviceRead());
00164 #endif
00165 }
00166
00167
00168 void PenalityContactForceField<CudaVec3fTypes>::addDForce(VecDeriv& df1, VecDeriv& df2, const VecDeriv& dx1, const VecDeriv& dx2, double kFactor, double )
00169 {
00170 df1.resize(dx1.size());
00171 df2.resize(dx2.size());
00172 #if 0
00173 for (unsigned int i=0; i<contacts.size(); i++)
00174 {
00175 if (pen[i] > 0)
00176 {
00177 sofa::defaulttype::Vec4f c = contacts[i];
00178
00179 Coord du = dx2[i]-dx1[i];
00180 Coord norm(c[0],c[1],c[2]);
00181 Real dpen = - du*norm;
00182
00183
00184 Deriv dforce = -norm*(dpen*kFactor);
00185 df1[i]+=dforce;
00186 df2[i]-=dforce;
00187 }
00188 }
00189 #else
00190 PenalityContactForceFieldCuda3f_addDForce(contacts.size(), contacts.deviceRead(), pen.deviceWrite(),
00191 df1.deviceWrite(), dx1.deviceRead(),
00192 df2.deviceWrite(), dx2.deviceRead(), kFactor);
00193 #endif
00194 }
00195
00196
00197 double PenalityContactForceField<CudaVec3fTypes>::getPotentialEnergy(const VecCoord&, const VecCoord&)
00198 {
00199 cerr<<"PenalityContactForceField::getPotentialEnergy-not-implemented !!!"<<endl;
00200 return 0;
00201 }
00202
00203
00204 void PenalityContactForceField<CudaVec3fTypes>::draw()
00205 {
00206 if (!((this->mstate1 == this->mstate2)?getContext()->getShowForceFields():getContext()->getShowInteractionForceFields())) return;
00207 const VecCoord& p1 = *this->mstate1->getX();
00208 const VecCoord& p2 = *this->mstate2->getX();
00209 glDisable(GL_LIGHTING);
00210
00211 glBegin(GL_LINES);
00212 for (unsigned int i=0; i<contacts.size(); i++)
00213 {
00214 sofa::defaulttype::Vec4f c = contacts[i];
00215 Coord u = p2[i]-p1[i];
00216 Coord norm(c[0],c[1],c[2]);
00217
00218 Real d = c[3] - u*norm;
00219
00220
00221
00222
00223
00224
00225 if (d > 0)
00226 glColor4f(1,0,0,1);
00227 else
00228 glColor4f(0,1,0,1);
00229 helper::gl::glVertexT(p1[i]);
00230 helper::gl::glVertexT(p2[i]);
00231 }
00232 glEnd();
00233
00234
00235 {
00236 glColor4f(1,1,0,1);
00237 glBegin(GL_LINES);
00238 for (unsigned int i=0; i<contacts.size(); i++)
00239 {
00240 sofa::defaulttype::Vec4f c = contacts[i];
00241 Coord norm(c[0],c[1],c[2]); norm.normalize();
00242 Coord p = p1[i] - norm*0.1;
00243 helper::gl::glVertexT(p1[i]);
00244 helper::gl::glVertexT(p);
00245 p = p2[i] + norm*0.1;
00246 helper::gl::glVertexT(p2[i]);
00247 helper::gl::glVertexT(p);
00248 }
00249 glEnd();
00250 }
00251 }
00252
00253 }
00254
00255 }
00256
00257 }
00258
00259 #endif