SphereTreeModel.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/SphereTreeModel.h>
00026 #include <sofa/helper/io/SphereLoader.h>
00027 #include <sofa/component/collision/CubeModel.h>
00028 #include <sofa/core/ObjectFactory.h>
00029 #include <iostream>
00030 #include <sofa/helper/system/gl.h>
00031 #include <sofa/helper/system/glut.h>
00032 #include <sofa/helper/system/FileRepository.h>
00033
00034 using std::cerr;
00035 using std::endl;
00036
00037
00038 namespace sofa
00039 {
00040
00041 namespace component
00042 {
00043
00044 namespace collision
00045 {
00046
00047
00048 SOFA_DECL_CLASS(SphereTreeModel)
00049
00050 using namespace sofa::defaulttype;
00051 using namespace std;
00052
00053 int SphereTreeModelClass = core::RegisterObject("CollisionModel based on a hierarchy of bounding spheres")
00054 .add< SphereTreeModel >()
00055 .addAlias("SphereTree")
00056 ;
00057
00058 SphereTreeModel::SphereTreeModel(double radius)
00059 : defaultRadius(initData(&defaultRadius, radius, "radius","TODO"))
00060 {
00061 }
00062
00063
00064 void SphereTreeModel::resize(int size)
00065 {
00066 this->component::MechanicalObject<Vec3Types>::resize(size);
00067 this->core::CollisionModel::resize(size);
00068
00069
00070 if ((int)radius.size() < size)
00071 {
00072 radius.reserve(size);
00073 while ((int)radius.size() < size)
00074 radius.push_back(defaultRadius.getValue());
00075 }
00076 else
00077 {
00078 radius.resize(size);
00079 }
00080 }
00081
00082 int SphereTreeModel::addSphere(const Vector3& pos, SReal radius)
00083 {
00084 int i = size;
00085 resize(i+1);
00086 setSphere(i, pos, radius);
00087 return i;
00088 }
00089
00090 void SphereTreeModel::setSphere(int i, const Vector3& pos, SReal r)
00091 {
00092 if ((unsigned)i >= (unsigned) size) return;
00093 (*this->getX())[i] = pos;
00094 radius[i] = r;
00095 }
00096
00097 bool SphereTreeModel::load(const char* filename)
00098 {
00099 this->resize(0);
00100 return loadSphereTree(filename);
00101 }
00102
00103 bool SphereTreeModel::loadSphereTree( const char *fileName )
00104 {
00105 std::ifstream inFile;
00106
00107 std::string fileInRepository(fileName);
00108 if ( !sofa::helper::system::DataRepository.findFile ( fileInRepository ) )
00109 return false;
00110
00111 fileInRepository = sofa::helper::system::DataRepository.getFile ( fileInRepository);
00112
00113 inFile.open(fileInRepository.c_str());
00114 if (inFile.fail())
00115 {
00116 std::cerr << "Fail to open file sph" << std::endl;
00117 return false;
00118 }
00119 levels = 0; degree = 0;
00120 inFile >> levels >> degree;
00121
00122 if (!levels || !degree)
00123 return false;
00124
00125 int numnodes = 1;
00126 int numSpheres=0;
00127
00128 double x, y, z, r, errDec;
00129 for (int level = 0; level < levels; level++ )
00130 {
00131
00132 for (int i = 0; i < numnodes; i++)
00133 {
00134 inFile >> x >> y >> z >> r >> errDec;
00135
00136 if (inFile.fail())
00137 {
00138 std::cerr << "Error: incorrect file format sph " << std::endl;
00139 return false;
00140 }
00141
00142 resize( numSpheres+1 );
00143
00144
00145 SingleSphere s(this, numSpheres);
00146 s.setCenter(x,y,z);
00147 radius[numSpheres] = r;
00148
00149 #if 0
00150 SphereData sphData;
00151
00152
00153 if (isLeaf)
00154 {
00155 sphData.leaf = core::CollisionElementIterator(this,numSpheres);
00156 }
00157 else
00158 {
00159 sphData.leaf = core::CollisionElementIterator();
00160 }
00161
00162 sphData.node = s;
00163
00164 this->elems.push_back( sphData );
00165 #endif
00166 numSpheres=numSpheres+1;
00167
00168 }
00169 numnodes *= degree;
00170 }
00171 #if 0
00172
00173 numnodes = 1;
00174 int node = 0;
00175 int nodeinit = 0;
00176 int firstchild;
00177 for (int level = 0; level < levels-1; level++ )
00178 {
00179 for (int i = 0; i < numnodes; i++)
00180 {
00181 while ( node < nodeinit )
00182 {
00183 firstchild = node * degree + 1;
00184 for ( int deg = 0; deg <= degree; deg++)
00185 {
00186
00187 SphereData s = this->elems[ firstchild + deg ];
00188 core::CollisionElementIterator begin(this, (firstchild+deg) );
00189 core::CollisionElementIterator end(this, (firstchild+degree) );
00190
00191 if ( deg == 0 ) this->elems[node].subcells.first = begin;
00192
00193
00194 if ( deg == degree ) this->elems[node].subcells.second = end;
00195
00196 }
00197 node++;
00198 }
00199 }
00200 numnodes *= degree;
00201 nodeinit = node+numnodes;
00202 }
00203 #endif
00204 inFile.close();
00205 return true;
00206 }
00207
00208 void SphereTreeModel::applyScale(const double s)
00209 {
00210 Inherit::applyScale(s);
00211 std::cout << "Applying scale " << s << " to " << size << " spheres" << std::endl;
00212 for (int i=0;i<size;i++)
00213 radius[i] *= s;
00214 }
00215
00216
00217 void SphereTreeModel::draw(int index)
00218 {
00219 Vector3 p = (*getX())[index];
00220 glPushMatrix();
00221 glTranslated(p[0], p[1], p[2]);
00222 glutWireSphere(radius[index], 16, 8);
00223 glPopMatrix();
00224 }
00225
00226 void SphereTreeModel::draw()
00227 {
00228 float color = 1.0f;
00229 if ( getContext()->getShowCollisionModels())
00230 {
00231 glDisable(GL_LIGHTING);
00232 if (!isSimulated())
00233 glColor4f(1.0f, 1.0f, 1.0f, color);
00234 else
00235 glColor4f(1.0f, 1.0f, 0.0f, color);
00236
00237
00238
00239
00240
00241
00242
00243 int numnodes = 1;
00244 int node = 0;
00245 for (int level = 0; level < levels; level++ )
00246 {
00247 if ( level < levels-1 ) {
00248 glColor4f(1.0f, color, color*color, (1.0 - color) );
00249 color *= 0.5f;
00250 }
00251 else glColor4f(0.0f, 0.0f, 1.0f, 1.0);
00252
00253 for (int i = 0; i < numnodes; i++)
00254 {
00255 draw( node );
00256 node++;
00257 }
00258 numnodes *= degree;
00259
00260
00261 }
00262
00263
00264
00265
00266
00267
00268
00269 }
00270 if (isActive() && getPrevious()!=NULL && getContext()->getShowBoundingCollisionModels())
00271 getPrevious()->draw();
00272 }
00273
00274 void SphereTreeModel::computeBoundingTree(int )
00275 {
00276
00277
00278
00279 }
00280
00281 void SphereTreeModel::computeContinuousBoundingTree(double , int )
00282 {
00283 cout << "SphereTreeModel::computeContinuousBoundingTree - not implemented" << endl;
00284 }
00285
00286 std::pair<core::CollisionElementIterator,core::CollisionElementIterator> SphereTreeModel::getInternalChildren(int index) const
00287 {
00288
00289 int firstchild = index*degree+1;
00290 if (firstchild >= size)
00291 return std::make_pair(core::CollisionElementIterator(),core::CollisionElementIterator());
00292 int lastchild = firstchild+degree-1;
00293 if (lastchild >= size) lastchild = size-1;
00294 return std::make_pair(core::CollisionElementIterator(const_cast<SphereTreeModel*>(this),firstchild),core::CollisionElementIterator(const_cast<SphereTreeModel*>(this),lastchild+1));
00295 }
00296
00297 bool SphereTreeModel::isLeaf( int index ) const
00298 {
00299 int firstchild = index*degree+1;
00300 return (firstchild >= size);
00301
00302
00303
00304
00305 }
00306
00307
00308 }
00309
00310 }
00311
00312 }
00313