TetrahedronModel.cpp
Go to the documentation of this file.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 #include <sofa/component/collision/TetrahedronModel.h>
00026 #include <sofa/component/collision/CubeModel.h>
00027 #include <sofa/helper/gl/template.h>
00028 #include <sofa/simulation/tree/GNode.h>
00029 #include <sofa/component/topology/RegularGridTopology.h>
00030 #include <sofa/core/CollisionElement.h>
00031 #include <sofa/core/ObjectFactory.h>
00032 #include <vector>
00033 #include <sofa/helper/system/gl.h>
00034 #include <iostream>
00035 using std::cerr;
00036 using std::endl;
00037
00038 namespace sofa
00039 {
00040
00041 namespace component
00042 {
00043
00044 namespace collision
00045 {
00046
00047 SOFA_DECL_CLASS(TetrahedronModel)
00048
00049 int TetrahedronModelClass = core::RegisterObject("collision model using a tetrahedral mesh, as described in BaseMeshTopology")
00050 .add< TetrahedronModel >()
00051 .addAlias("Tetrahedron")
00052 ;
00053
00054 TetrahedronModel::TetrahedronModel()
00055 : tetra(NULL), mstate(NULL)
00056 {
00057 }
00058
00059 void TetrahedronModel::resize(int size)
00060 {
00061 this->core::CollisionModel::resize(size);
00062 elems.resize(size);
00063 if (getPrevious() != NULL) getPrevious()->resize(0);
00064 }
00065
00066 void TetrahedronModel::init()
00067 {
00068 _topology = this->getContext()->getMeshTopology();
00069
00070 this->CollisionModel::init();
00071 mstate = dynamic_cast< core::componentmodel::behavior::MechanicalState<Vec3Types>* > (getContext()->getMechanicalState());
00072
00073 if (mstate==NULL)
00074 {
00075 std::cerr << "ERROR: TetrahedronModel requires a Vec3 Mechanical Model.\n";
00076 return;
00077 }
00078
00079 if (!_topology) {
00080 std::cerr << "ERROR: TetrahedronModel requires a BaseMeshTopology.\n";
00081 return;
00082 }
00083
00084 tetra = &_topology->getTetras();
00085 resize(tetra->size());
00086
00087 }
00088
00089 void TetrahedronModel::handleTopologyChange()
00090 {
00091 resize(_topology->getNbTetras());
00092 }
00093
00094 void TetrahedronModel::draw(int index)
00095 {
00096 Tetrahedron t(this,index);
00097 glBegin(GL_TRIANGLES);
00098 Coord p1 = t.p1();
00099 Coord p2 = t.p2();
00100 Coord p3 = t.p3();
00101 Coord p4 = t.p4();
00102 Coord c = (p1+p2+p3+p4)*0.25f;
00103 p1 += (c-p1)*0.1f;
00104 p2 += (c-p2)*0.1f;
00105 p3 += (c-p3)*0.1f;
00106 p4 += (c-p4)*0.1f;
00107 Coord n1,n2,n3,n4;
00108 n1 = cross(p3-p1,p2-p1); n1.normalize();
00109 helper::gl::glNormalT(n1);
00110 helper::gl::glVertexT(p1);
00111 helper::gl::glVertexT(p3);
00112 helper::gl::glVertexT(p2);
00113
00114 n2 = cross(p4-p1,p3-p1); n2.normalize();
00115 helper::gl::glNormalT(n2);
00116 helper::gl::glVertexT(p1);
00117 helper::gl::glVertexT(p4);
00118 helper::gl::glVertexT(p3);
00119
00120 n3 = cross(p2-p1,p4-p1); n3.normalize();
00121 helper::gl::glNormalT(n3);
00122 helper::gl::glVertexT(p1);
00123 helper::gl::glVertexT(p2);
00124 helper::gl::glVertexT(p4);
00125
00126 n4 = cross(p3-p2,p4-p2); n4.normalize();
00127 helper::gl::glNormalT(n4);
00128 helper::gl::glVertexT(p2);
00129 helper::gl::glVertexT(p3);
00130 helper::gl::glVertexT(p4);
00131 glEnd();
00132 if (getContext()->getShowNormals())
00133 {
00134 Coord p;
00135 glBegin(GL_LINES);
00136 p = (p1+p2+p3)*(1.0/3.0);
00137 helper::gl::glVertexT(p);
00138 helper::gl::glVertexT(p+n1*0.1);
00139 p = (p1+p3+p4)*(1.0/3.0);
00140 helper::gl::glVertexT(p);
00141 helper::gl::glVertexT(p+n2*0.1);
00142 p = (p1+p4+p2)*(1.0/3.0);
00143 helper::gl::glVertexT(p);
00144 helper::gl::glVertexT(p+n3*0.1);
00145 p = (p2+p3+p4)*(1.0/3.0);
00146 helper::gl::glVertexT(p);
00147 helper::gl::glVertexT(p+n4*0.1);
00148 glEnd();
00149 }
00150 }
00151
00152 void TetrahedronModel::draw()
00153 {
00154 if (mstate && _topology && getContext()->getShowCollisionModels())
00155 {
00156 if (getContext()->getShowWireFrame())
00157 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00158
00159 glEnable(GL_LIGHTING);
00160
00161
00162
00163 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, getColor4f());
00164 static const float emissive[4] = { 0.0f, 0.0f, 0.0f, 0.0f};
00165 static const float specular[4] = { 1.0f, 1.0f, 1.0f, 1.0f};
00166 glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, emissive);
00167 glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular);
00168 glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 20);
00169
00170 for (int i=0;i<size;i++)
00171 {
00172 draw(i);
00173 }
00174
00175 glColor3f(1.0f, 1.0f, 1.0f);
00176 glDisable(GL_LIGHTING);
00177 if (getContext()->getShowWireFrame())
00178 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00179 }
00180 if (getPrevious()!=NULL && getContext()->getShowBoundingCollisionModels())
00181 getPrevious()->draw();
00182 }
00183
00184 void TetrahedronModel::computeBoundingTree(int maxDepth)
00185 {
00186 CubeModel* cubeModel = createPrevious<CubeModel>();
00187 if (!mstate || !_topology) return;
00188 if (!isMoving() && !cubeModel->empty()) return;
00189
00190 Vector3 minElem, maxElem;
00191 const VecCoord& x = *this->mstate->getX();
00192
00193 for (int i=0;i<size;i++)
00194 {
00195 Tetrahedron t(this,i);
00196 const Vector3& pt1 = x[t.p1Index()];
00197 const Vector3& pt2 = x[t.p2Index()];
00198 const Vector3& pt3 = x[t.p3Index()];
00199 const Vector3& pt4 = x[t.p4Index()];
00200 Matrix3 m, minv;
00201 m[0] = pt2-pt1;
00202 m[1] = pt3-pt1;
00203 m[2] = pt4-pt1;
00204 m.transpose();
00205 minv.invert(m);
00206 elems[i].coord0 = pt1;
00207 elems[i].bary2coord = m;
00208 elems[i].coord2bary = minv;
00209 }
00210
00211 if (maxDepth == 0)
00212 {
00213 if (empty())
00214 cubeModel->resize(0);
00215 else
00216 {
00217 cubeModel->resize(1);
00218 minElem = x[0];
00219 maxElem = x[0];
00220 for (unsigned i=1;i<x.size();i++)
00221 {
00222 const Vector3& pt1 = x[i];
00223 if (pt1[0] > maxElem[0]) maxElem[0] = pt1[0];
00224 else if (pt1[0] < minElem[0]) minElem[0] = pt1[0];
00225 if (pt1[1] > maxElem[1]) maxElem[1] = pt1[1];
00226 else if (pt1[1] < minElem[1]) minElem[1] = pt1[1];
00227 if (pt1[2] > maxElem[2]) maxElem[2] = pt1[2];
00228 else if (pt1[2] < minElem[2]) minElem[2] = pt1[2];
00229 }
00230 cubeModel->setLeafCube(0, std::make_pair(this->begin(),this->end()), minElem, maxElem);
00231 }
00232 }
00233 else
00234 {
00235 cubeModel->resize(size);
00236 if (!empty())
00237 {
00238 for (int i=0;i<size;i++)
00239 {
00240 Tetrahedron t(this,i);
00241 const Vector3& pt1 = x[t.p1Index()];
00242 const Vector3& pt2 = x[t.p2Index()];
00243 const Vector3& pt3 = x[t.p3Index()];
00244 const Vector3& pt4 = x[t.p4Index()];
00245 for (int c = 0; c < 3; c++)
00246 {
00247 minElem[c] = pt1[c];
00248 maxElem[c] = pt1[c];
00249 if (pt2[c] > maxElem[c]) maxElem[c] = pt2[c];
00250 else if (pt2[c] < minElem[c]) minElem[c] = pt2[c];
00251 if (pt3[c] > maxElem[c]) maxElem[c] = pt3[c];
00252 else if (pt3[c] < minElem[c]) minElem[c] = pt3[c];
00253 if (pt4[c] > maxElem[c]) maxElem[c] = pt4[c];
00254 else if (pt4[c] < minElem[c]) minElem[c] = pt4[c];
00255 }
00256 cubeModel->setParentOf(i, minElem, maxElem);
00257 }
00258 cubeModel->computeBoundingTree(maxDepth);
00259 }
00260 }
00261 }
00262
00263 }
00264
00265 }
00266
00267 }